diff options
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | src/common/assert.h | 5 | ||||
| -rw-r--r-- | src/common/bit_field.h | 19 | ||||
| -rw-r--r-- | src/common/bit_set.h | 244 | ||||
| -rw-r--r-- | src/common/logging/backend.cpp | 11 | ||||
| -rw-r--r-- | src/common/logging/backend.h | 14 | ||||
| -rw-r--r-- | src/common/math_util.h | 16 | ||||
| -rw-r--r-- | src/common/string_util.cpp | 66 | ||||
| -rw-r--r-- | src/common/string_util.h | 41 | ||||
| -rw-r--r-- | src/common/thread.cpp | 35 | ||||
| -rw-r--r-- | src/common/thread.h | 20 | ||||
| -rw-r--r-- | src/common/x64/xbyak_abi.h | 222 | ||||
| -rw-r--r-- | src/common/x64/xbyak_util.h | 47 | 
13 files changed, 75 insertions, 671 deletions
| diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index eccd8f64a..a5e71d879 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -44,7 +44,6 @@ add_library(common STATIC      detached_tasks.cpp      detached_tasks.h      bit_field.h -    bit_set.h      cityhash.cpp      cityhash.h      color.h @@ -95,14 +94,9 @@ if(ARCHITECTURE_x86_64)          PRIVATE              x64/cpu_detect.cpp              x64/cpu_detect.h -            x64/xbyak_abi.h -            x64/xbyak_util.h      )  endif()  create_target_directory_groups(common)  target_link_libraries(common PUBLIC Boost::boost fmt microprofile) -if (ARCHITECTURE_x86_64) -    target_link_libraries(common PRIVATE xbyak) -endif() diff --git a/src/common/assert.h b/src/common/assert.h index 0d4eddc19..6002f7ab1 100644 --- a/src/common/assert.h +++ b/src/common/assert.h @@ -52,5 +52,8 @@ __declspec(noinline, noreturn)  #define DEBUG_ASSERT_MSG(_a_, _desc_, ...)  #endif -#define UNIMPLEMENTED() LOG_CRITICAL(Debug, "Unimplemented code!") +#define UNIMPLEMENTED() ASSERT_MSG(false, "Unimplemented code!")  #define UNIMPLEMENTED_MSG(...) ASSERT_MSG(false, __VA_ARGS__) + +#define UNIMPLEMENTED_IF(cond) ASSERT_MSG(!(cond), "Unimplemented code!") +#define UNIMPLEMENTED_IF_MSG(cond, ...) ASSERT_MSG(!(cond), __VA_ARGS__) diff --git a/src/common/bit_field.h b/src/common/bit_field.h index bf803da8d..21e07925d 100644 --- a/src/common/bit_field.h +++ b/src/common/bit_field.h @@ -117,21 +117,21 @@ private:      // We don't delete it because we want BitField to be trivially copyable.      constexpr BitField& operator=(const BitField&) = default; -    // StorageType is T for non-enum types and the underlying type of T if +    // UnderlyingType is T for non-enum types and the underlying type of T if      // T is an enumeration. Note that T is wrapped within an enable_if in the      // former case to workaround compile errors which arise when using      // std::underlying_type<T>::type directly. -    using StorageType = typename std::conditional_t<std::is_enum<T>::value, std::underlying_type<T>, -                                                    std::enable_if<true, T>>::type; +    using UnderlyingType = typename std::conditional_t<std::is_enum_v<T>, std::underlying_type<T>, +                                                       std::enable_if<true, T>>::type; -    // Unsigned version of StorageType -    using StorageTypeU = std::make_unsigned_t<StorageType>; +    // We store the value as the unsigned type to avoid undefined behaviour on value shifting +    using StorageType = std::make_unsigned_t<UnderlyingType>;  public:      /// Constants to allow limited introspection of fields if needed      static constexpr std::size_t position = Position;      static constexpr std::size_t bits = Bits; -    static constexpr StorageType mask = (((StorageTypeU)~0) >> (8 * sizeof(T) - bits)) << position; +    static constexpr StorageType mask = (((StorageType)~0) >> (8 * sizeof(T) - bits)) << position;      /**       * Formats a value by masking and shifting it according to the field parameters. A value @@ -148,11 +148,12 @@ public:       * union in a constexpr context.       */      static constexpr FORCE_INLINE T ExtractValue(const StorageType& storage) { -        if (std::numeric_limits<T>::is_signed) { +        if constexpr (std::numeric_limits<UnderlyingType>::is_signed) {              std::size_t shift = 8 * sizeof(T) - bits; -            return (T)((storage << (shift - position)) >> shift); +            return static_cast<T>(static_cast<UnderlyingType>(storage << (shift - position)) >> +                                  shift);          } else { -            return (T)((storage & mask) >> position); +            return static_cast<T>((storage & mask) >> position);          }      } diff --git a/src/common/bit_set.h b/src/common/bit_set.h deleted file mode 100644 index 5cd1352b2..000000000 --- a/src/common/bit_set.h +++ /dev/null @@ -1,244 +0,0 @@ -// This file is under the public domain. - -#pragma once - -#include <cstddef> -#ifdef _WIN32 -#include <intrin.h> -#endif -#include <initializer_list> -#include <new> -#include <type_traits> -#include "common/common_types.h" - -// namespace avoids conflict with OS X Carbon; don't use BitSet<T> directly -namespace Common { - -// Helper functions: - -#ifdef _MSC_VER -template <typename T> -static inline int CountSetBits(T v) { -    // from https://graphics.stanford.edu/~seander/bithacks.html -    // GCC has this built in, but MSVC's intrinsic will only emit the actual -    // POPCNT instruction, which we're not depending on -    v = v - ((v >> 1) & (T) ~(T)0 / 3); -    v = (v & (T) ~(T)0 / 15 * 3) + ((v >> 2) & (T) ~(T)0 / 15 * 3); -    v = (v + (v >> 4)) & (T) ~(T)0 / 255 * 15; -    return (T)(v * ((T) ~(T)0 / 255)) >> (sizeof(T) - 1) * 8; -} -static inline int LeastSignificantSetBit(u8 val) { -    unsigned long index; -    _BitScanForward(&index, val); -    return (int)index; -} -static inline int LeastSignificantSetBit(u16 val) { -    unsigned long index; -    _BitScanForward(&index, val); -    return (int)index; -} -static inline int LeastSignificantSetBit(u32 val) { -    unsigned long index; -    _BitScanForward(&index, val); -    return (int)index; -} -static inline int LeastSignificantSetBit(u64 val) { -    unsigned long index; -    _BitScanForward64(&index, val); -    return (int)index; -} -#else -static inline int CountSetBits(u8 val) { -    return __builtin_popcount(val); -} -static inline int CountSetBits(u16 val) { -    return __builtin_popcount(val); -} -static inline int CountSetBits(u32 val) { -    return __builtin_popcount(val); -} -static inline int CountSetBits(u64 val) { -    return __builtin_popcountll(val); -} -static inline int LeastSignificantSetBit(u8 val) { -    return __builtin_ctz(val); -} -static inline int LeastSignificantSetBit(u16 val) { -    return __builtin_ctz(val); -} -static inline int LeastSignificantSetBit(u32 val) { -    return __builtin_ctz(val); -} -static inline int LeastSignificantSetBit(u64 val) { -    return __builtin_ctzll(val); -} -#endif - -// Similar to std::bitset, this is a class which encapsulates a bitset, i.e. -// using the set bits of an integer to represent a set of integers.  Like that -// class, it acts like an array of bools: -//     BitSet32 bs; -//     bs[1] = true; -// but also like the underlying integer ([0] = least significant bit): -//     BitSet32 bs2 = ...; -//     bs = (bs ^ bs2) & BitSet32(0xffff); -// The following additional functionality is provided: -// - Construction using an initializer list. -//     BitSet bs { 1, 2, 4, 8 }; -// - Efficiently iterating through the set bits: -//     for (int i : bs) -//         [i is the *index* of a set bit] -//   (This uses the appropriate CPU instruction to find the next set bit in one -//   operation.) -// - Counting set bits using .Count() - see comment on that method. - -// TODO: use constexpr when MSVC gets out of the Dark Ages - -template <typename IntTy> -class BitSet { -    static_assert(!std::is_signed_v<IntTy>, "BitSet should not be used with signed types"); - -public: -    // A reference to a particular bit, returned from operator[]. -    class Ref { -    public: -        Ref(Ref&& other) : m_bs(other.m_bs), m_mask(other.m_mask) {} -        Ref(BitSet* bs, IntTy mask) : m_bs(bs), m_mask(mask) {} -        operator bool() const { -            return (m_bs->m_val & m_mask) != 0; -        } -        bool operator=(bool set) { -            m_bs->m_val = (m_bs->m_val & ~m_mask) | (set ? m_mask : 0); -            return set; -        } - -    private: -        BitSet* m_bs; -        IntTy m_mask; -    }; - -    // A STL-like iterator is required to be able to use range-based for loops. -    class Iterator { -    public: -        Iterator(const Iterator& other) : m_val(other.m_val), m_bit(other.m_bit) {} -        Iterator(IntTy val) : m_val(val), m_bit(0) {} -        Iterator& operator=(Iterator other) { -            new (this) Iterator(other); -            return *this; -        } -        int operator*() { -            return m_bit + ComputeLsb(); -        } -        Iterator& operator++() { -            int lsb = ComputeLsb(); -            m_val >>= lsb + 1; -            m_bit += lsb + 1; -            m_has_lsb = false; -            return *this; -        } -        Iterator operator++(int _) { -            Iterator other(*this); -            ++*this; -            return other; -        } -        bool operator==(Iterator other) const { -            return m_val == other.m_val; -        } -        bool operator!=(Iterator other) const { -            return m_val != other.m_val; -        } - -    private: -        int ComputeLsb() { -            if (!m_has_lsb) { -                m_lsb = LeastSignificantSetBit(m_val); -                m_has_lsb = true; -            } -            return m_lsb; -        } -        IntTy m_val; -        int m_bit; -        int m_lsb = -1; -        bool m_has_lsb = false; -    }; - -    BitSet() : m_val(0) {} -    explicit BitSet(IntTy val) : m_val(val) {} -    BitSet(std::initializer_list<int> init) { -        m_val = 0; -        for (int bit : init) -            m_val |= (IntTy)1 << bit; -    } - -    static BitSet AllTrue(std::size_t count) { -        return BitSet(count == sizeof(IntTy) * 8 ? ~(IntTy)0 : (((IntTy)1 << count) - 1)); -    } - -    Ref operator[](std::size_t bit) { -        return Ref(this, (IntTy)1 << bit); -    } -    const Ref operator[](std::size_t bit) const { -        return (*const_cast<BitSet*>(this))[bit]; -    } -    bool operator==(BitSet other) const { -        return m_val == other.m_val; -    } -    bool operator!=(BitSet other) const { -        return m_val != other.m_val; -    } -    bool operator<(BitSet other) const { -        return m_val < other.m_val; -    } -    bool operator>(BitSet other) const { -        return m_val > other.m_val; -    } -    BitSet operator|(BitSet other) const { -        return BitSet(m_val | other.m_val); -    } -    BitSet operator&(BitSet other) const { -        return BitSet(m_val & other.m_val); -    } -    BitSet operator^(BitSet other) const { -        return BitSet(m_val ^ other.m_val); -    } -    BitSet operator~() const { -        return BitSet(~m_val); -    } -    BitSet& operator|=(BitSet other) { -        return *this = *this | other; -    } -    BitSet& operator&=(BitSet other) { -        return *this = *this & other; -    } -    BitSet& operator^=(BitSet other) { -        return *this = *this ^ other; -    } -    operator u32() = delete; -    operator bool() { -        return m_val != 0; -    } - -    // Warning: Even though on modern CPUs this is a single fast instruction, -    // Dolphin's official builds do not currently assume POPCNT support on x86, -    // so slower explicit bit twiddling is generated.  Still should generally -    // be faster than a loop. -    unsigned int Count() const { -        return CountSetBits(m_val); -    } - -    Iterator begin() const { -        return Iterator(m_val); -    } -    Iterator end() const { -        return Iterator(0); -    } - -    IntTy m_val; -}; - -} // namespace Common - -typedef Common::BitSet<u8> BitSet8; -typedef Common::BitSet<u16> BitSet16; -typedef Common::BitSet<u32> BitSet32; -typedef Common::BitSet<u64> BitSet64; diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 6d5218465..5753b871a 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -12,7 +12,8 @@  #include <thread>  #include <vector>  #ifdef _WIN32 -#include <share.h> // For _SH_DENYWR +#include <share.h>   // For _SH_DENYWR +#include <windows.h> // For OutputDebugStringA  #else  #define _SH_DENYWR 0  #endif @@ -139,12 +140,18 @@ void FileBackend::Write(const Entry& entry) {      if (!file.IsOpen() || bytes_written > MAX_BYTES_WRITTEN) {          return;      } -    bytes_written += file.WriteString(FormatLogMessage(entry) + '\n'); +    bytes_written += file.WriteString(FormatLogMessage(entry).append(1, '\n'));      if (entry.log_level >= Level::Error) {          file.Flush();      }  } +void DebuggerBackend::Write(const Entry& entry) { +#ifdef _WIN32 +    ::OutputDebugStringA(FormatLogMessage(entry).append(1, '\n').c_str()); +#endif +} +  /// Macro listing all log classes. Code should define CLS and SUB as desired before invoking this.  #define ALL_LOG_CLASSES()                                                                          \      CLS(Log)                                                                                       \ diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h index 11edbf1b6..91bb0c309 100644 --- a/src/common/logging/backend.h +++ b/src/common/logging/backend.h @@ -103,6 +103,20 @@ private:      std::size_t bytes_written;  }; +/** + * Backend that writes to Visual Studio's output window + */ +class DebuggerBackend : public Backend { +public: +    static const char* Name() { +        return "debugger"; +    } +    const char* GetName() const override { +        return Name(); +    } +    void Write(const Entry& entry) override; +}; +  void AddBackend(std::unique_ptr<Backend> backend);  void RemoveBackend(std::string_view backend_name); diff --git a/src/common/math_util.h b/src/common/math_util.h index 343cdd902..94b4394c5 100644 --- a/src/common/math_util.h +++ b/src/common/math_util.h @@ -4,18 +4,12 @@  #pragma once -#include <algorithm>  #include <cstdlib>  #include <type_traits>  namespace MathUtil { -static constexpr float PI = 3.14159265f; - -inline bool IntervalsIntersect(unsigned start0, unsigned length0, unsigned start1, -                               unsigned length1) { -    return (std::max(start0, start1) < std::min(start0 + length0, start1 + length1)); -} +constexpr float PI = 3.14159265f;  template <class T>  struct Rectangle { @@ -24,16 +18,16 @@ struct Rectangle {      T right{};      T bottom{}; -    Rectangle() = default; +    constexpr Rectangle() = default; -    Rectangle(T left, T top, T right, T bottom) +    constexpr Rectangle(T left, T top, T right, T bottom)          : left(left), top(top), right(right), bottom(bottom) {}      T GetWidth() const { -        return std::abs(static_cast<typename std::make_signed<T>::type>(right - left)); +        return std::abs(static_cast<std::make_signed_t<T>>(right - left));      }      T GetHeight() const { -        return std::abs(static_cast<typename std::make_signed<T>::type>(bottom - top)); +        return std::abs(static_cast<std::make_signed_t<T>>(bottom - top));      }      Rectangle<T> TranslateX(const T x) const {          return Rectangle{left + x, top, right + x, bottom}; diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index 731d1db34..959f278aa 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp @@ -4,11 +4,10 @@  #include <algorithm>  #include <cctype> -#include <cerrno>  #include <codecvt> -#include <cstdio>  #include <cstdlib> -#include <cstring> +#include <locale> +#include <sstream>  #include "common/common_paths.h"  #include "common/logging/log.h"  #include "common/string_util.h" @@ -33,24 +32,6 @@ std::string ToUpper(std::string str) {      return str;  } -// For Debugging. Read out an u8 array. -std::string ArrayToString(const u8* data, std::size_t size, int line_len, bool spaces) { -    std::ostringstream oss; -    oss << std::setfill('0') << std::hex; - -    for (int line = 0; size; ++data, --size) { -        oss << std::setw(2) << (int)*data; - -        if (line_len == ++line) { -            oss << '\n'; -            line = 0; -        } else if (spaces) -            oss << ' '; -    } - -    return oss.str(); -} -  std::string StringFromBuffer(const std::vector<u8>& data) {      return std::string(data.begin(), std::find(data.begin(), data.end(), '\0'));  } @@ -75,40 +56,6 @@ std::string StripQuotes(const std::string& s) {          return s;  } -bool TryParse(const std::string& str, u32* const output) { -    char* endptr = nullptr; - -    // Reset errno to a value other than ERANGE -    errno = 0; - -    unsigned long value = strtoul(str.c_str(), &endptr, 0); - -    if (!endptr || *endptr) -        return false; - -    if (errno == ERANGE) -        return false; - -#if ULONG_MAX > UINT_MAX -    if (value >= 0x100000000ull && value <= 0xFFFFFFFF00000000ull) -        return false; -#endif - -    *output = static_cast<u32>(value); -    return true; -} - -bool TryParse(const std::string& str, bool* const output) { -    if ("1" == str || "true" == ToLower(str)) -        *output = true; -    else if ("0" == str || "false" == ToLower(str)) -        *output = false; -    else -        return false; - -    return true; -} -  std::string StringFromBool(bool value) {      return value ? "True" : "False";  } @@ -267,6 +214,15 @@ std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, std::size_t      return std::string(buffer, len);  } +std::u16string UTF16StringFromFixedZeroTerminatedBuffer(std::u16string_view buffer, +                                                        std::size_t max_len) { +    std::size_t len = 0; +    while (len < max_len && buffer[len] != '\0') +        ++len; + +    return std::u16string(buffer.begin(), buffer.begin() + len); +} +  const char* TrimSourcePath(const char* path, const char* root) {      const char* p = path; diff --git a/src/common/string_util.h b/src/common/string_util.h index 32bf6a19c..583fd05e6 100644 --- a/src/common/string_util.h +++ b/src/common/string_util.h @@ -5,8 +5,6 @@  #pragma once  #include <cstddef> -#include <iomanip> -#include <sstream>  #include <string>  #include <vector>  #include "common/common_types.h" @@ -19,44 +17,13 @@ std::string ToLower(std::string str);  /// Make a string uppercase  std::string ToUpper(std::string str); -std::string ArrayToString(const u8* data, std::size_t size, int line_len = 20, bool spaces = true); -  std::string StringFromBuffer(const std::vector<u8>& data);  std::string StripSpaces(const std::string& s);  std::string StripQuotes(const std::string& s); -// Thousand separator. Turns 12345678 into 12,345,678 -template <typename I> -std::string ThousandSeparate(I value, int spaces = 0) { -    std::ostringstream oss; - -// std::locale("") seems to be broken on many platforms -#if defined _WIN32 || (defined __linux__ && !defined __clang__) -    oss.imbue(std::locale("")); -#endif -    oss << std::setw(spaces) << value; - -    return oss.str(); -} -  std::string StringFromBool(bool value); -bool TryParse(const std::string& str, bool* output); -bool TryParse(const std::string& str, u32* output); - -template <typename N> -static bool TryParse(const std::string& str, N* const output) { -    std::istringstream iss(str); - -    N tmp = 0; -    if (iss >> tmp) { -        *output = tmp; -        return true; -    } else -        return false; -} -  std::string TabsToSpaces(int tab_size, std::string in);  void SplitString(const std::string& str, char delim, std::vector<std::string>& output); @@ -100,6 +67,14 @@ bool ComparePartialString(InIt begin, InIt end, const char* other) {  std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, std::size_t max_len);  /** + * Creates a UTF-16 std::u16string from a fixed-size NUL-terminated char buffer. If the buffer isn't + * null-terminated, then the string ends at the greatest multiple of two less then or equal to + * max_len_bytes. + */ +std::u16string UTF16StringFromFixedZeroTerminatedBuffer(std::u16string_view buffer, +                                                        std::size_t max_len); + +/**   * Attempts to trim an arbitrary prefix from `path`, leaving only the part starting at `root`. It's   * intended to be used to strip a system-specific build directory from the `__FILE__` macro,   * leaving only the path relative to the sources root. diff --git a/src/common/thread.cpp b/src/common/thread.cpp index 9e207118f..5144c0d9f 100644 --- a/src/common/thread.cpp +++ b/src/common/thread.cpp @@ -25,23 +25,6 @@  namespace Common { -int CurrentThreadId() { -#ifdef _MSC_VER -    return GetCurrentThreadId(); -#elif defined __APPLE__ -    return mach_thread_self(); -#else -    return 0; -#endif -} - -#ifdef _WIN32 -// Supporting functions -void SleepCurrentThread(int ms) { -    Sleep(ms); -} -#endif -  #ifdef _MSC_VER  void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask) { @@ -62,7 +45,7 @@ void SwitchCurrentThread() {  // This is implemented much nicer in upcoming msvc++, see:  // http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.100).aspx -void SetCurrentThreadName(const char* szThreadName) { +void SetCurrentThreadName(const char* name) {      static const DWORD MS_VC_EXCEPTION = 0x406D1388;  #pragma pack(push, 8) @@ -75,7 +58,7 @@ void SetCurrentThreadName(const char* szThreadName) {  #pragma pack(pop)      info.dwType = 0x1000; -    info.szName = szThreadName; +    info.szName = name;      info.dwThreadID = -1; // dwThreadID;      info.dwFlags = 0; @@ -107,10 +90,6 @@ void SetCurrentThreadAffinity(u32 mask) {  }  #ifndef _WIN32 -void SleepCurrentThread(int ms) { -    usleep(1000 * ms); -} -  void SwitchCurrentThread() {      usleep(1000 * 1);  } @@ -118,15 +97,15 @@ void SwitchCurrentThread() {  // MinGW with the POSIX threading model does not support pthread_setname_np  #if !defined(_WIN32) || defined(_MSC_VER) -void SetCurrentThreadName(const char* szThreadName) { +void SetCurrentThreadName(const char* name) {  #ifdef __APPLE__ -    pthread_setname_np(szThreadName); +    pthread_setname_np(name);  #elif defined(__Bitrig__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__) -    pthread_set_name_np(pthread_self(), szThreadName); +    pthread_set_name_np(pthread_self(), name);  #elif defined(__NetBSD__) -    pthread_setname_np(pthread_self(), "%s", (void*)szThreadName); +    pthread_setname_np(pthread_self(), "%s", (void*)name);  #else -    pthread_setname_np(pthread_self(), szThreadName); +    pthread_setname_np(pthread_self(), name);  #endif  }  #endif diff --git a/src/common/thread.h b/src/common/thread.h index 6cbdb96a3..2cf74452d 100644 --- a/src/common/thread.h +++ b/src/common/thread.h @@ -13,15 +13,8 @@  namespace Common { -int CurrentThreadId(); - -void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask); -void SetCurrentThreadAffinity(u32 mask); -  class Event {  public: -    Event() : is_set(false) {} -      void Set() {          std::lock_guard<std::mutex> lk(mutex);          if (!is_set) { @@ -53,14 +46,14 @@ public:      }  private: -    bool is_set; +    bool is_set = false;      std::condition_variable condvar;      std::mutex mutex;  };  class Barrier {  public: -    explicit Barrier(std::size_t count_) : count(count_), waiting(0), generation(0) {} +    explicit Barrier(std::size_t count_) : count(count_) {}      /// Blocks until all "count" threads have called Sync()      void Sync() { @@ -80,12 +73,13 @@ public:  private:      std::condition_variable condvar;      std::mutex mutex; -    const std::size_t count; -    std::size_t waiting; -    std::size_t generation; // Incremented once each time the barrier is used +    std::size_t count; +    std::size_t waiting = 0; +    std::size_t generation = 0; // Incremented once each time the barrier is used  }; -void SleepCurrentThread(int ms); +void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask); +void SetCurrentThreadAffinity(u32 mask);  void SwitchCurrentThread(); // On Linux, this is equal to sleep 1ms  void SetCurrentThreadName(const char* name); diff --git a/src/common/x64/xbyak_abi.h b/src/common/x64/xbyak_abi.h deleted file mode 100644 index 636a5c0f9..000000000 --- a/src/common/x64/xbyak_abi.h +++ /dev/null @@ -1,222 +0,0 @@ -// Copyright 2016 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include <initializer_list> -#include <xbyak.h> -#include "common/assert.h" -#include "common/bit_set.h" - -namespace Common::X64 { - -inline int RegToIndex(const Xbyak::Reg& reg) { -    using Kind = Xbyak::Reg::Kind; -    ASSERT_MSG((reg.getKind() & (Kind::REG | Kind::XMM)) != 0, -               "RegSet only support GPRs and XMM registers."); -    ASSERT_MSG(reg.getIdx() < 16, "RegSet only supports XXM0-15."); -    return reg.getIdx() + (reg.getKind() == Kind::REG ? 0 : 16); -} - -inline Xbyak::Reg64 IndexToReg64(int reg_index) { -    ASSERT(reg_index < 16); -    return Xbyak::Reg64(reg_index); -} - -inline Xbyak::Xmm IndexToXmm(int reg_index) { -    ASSERT(reg_index >= 16 && reg_index < 32); -    return Xbyak::Xmm(reg_index - 16); -} - -inline Xbyak::Reg IndexToReg(int reg_index) { -    if (reg_index < 16) { -        return IndexToReg64(reg_index); -    } else { -        return IndexToXmm(reg_index); -    } -} - -inline BitSet32 BuildRegSet(std::initializer_list<Xbyak::Reg> regs) { -    BitSet32 bits; -    for (const Xbyak::Reg& reg : regs) { -        bits[RegToIndex(reg)] = true; -    } -    return bits; -} - -const BitSet32 ABI_ALL_GPRS(0x0000FFFF); -const BitSet32 ABI_ALL_XMMS(0xFFFF0000); - -#ifdef _WIN32 - -// Microsoft x64 ABI -const Xbyak::Reg ABI_RETURN = Xbyak::util::rax; -const Xbyak::Reg ABI_PARAM1 = Xbyak::util::rcx; -const Xbyak::Reg ABI_PARAM2 = Xbyak::util::rdx; -const Xbyak::Reg ABI_PARAM3 = Xbyak::util::r8; -const Xbyak::Reg ABI_PARAM4 = Xbyak::util::r9; - -const BitSet32 ABI_ALL_CALLER_SAVED = BuildRegSet({ -    // GPRs -    Xbyak::util::rcx, -    Xbyak::util::rdx, -    Xbyak::util::r8, -    Xbyak::util::r9, -    Xbyak::util::r10, -    Xbyak::util::r11, -    // XMMs -    Xbyak::util::xmm0, -    Xbyak::util::xmm1, -    Xbyak::util::xmm2, -    Xbyak::util::xmm3, -    Xbyak::util::xmm4, -    Xbyak::util::xmm5, -}); - -const BitSet32 ABI_ALL_CALLEE_SAVED = BuildRegSet({ -    // GPRs -    Xbyak::util::rbx, -    Xbyak::util::rsi, -    Xbyak::util::rdi, -    Xbyak::util::rbp, -    Xbyak::util::r12, -    Xbyak::util::r13, -    Xbyak::util::r14, -    Xbyak::util::r15, -    // XMMs -    Xbyak::util::xmm6, -    Xbyak::util::xmm7, -    Xbyak::util::xmm8, -    Xbyak::util::xmm9, -    Xbyak::util::xmm10, -    Xbyak::util::xmm11, -    Xbyak::util::xmm12, -    Xbyak::util::xmm13, -    Xbyak::util::xmm14, -    Xbyak::util::xmm15, -}); - -constexpr std::size_t ABI_SHADOW_SPACE = 0x20; - -#else - -// System V x86-64 ABI -const Xbyak::Reg ABI_RETURN = Xbyak::util::rax; -const Xbyak::Reg ABI_PARAM1 = Xbyak::util::rdi; -const Xbyak::Reg ABI_PARAM2 = Xbyak::util::rsi; -const Xbyak::Reg ABI_PARAM3 = Xbyak::util::rdx; -const Xbyak::Reg ABI_PARAM4 = Xbyak::util::rcx; - -const BitSet32 ABI_ALL_CALLER_SAVED = BuildRegSet({ -    // GPRs -    Xbyak::util::rcx, -    Xbyak::util::rdx, -    Xbyak::util::rdi, -    Xbyak::util::rsi, -    Xbyak::util::r8, -    Xbyak::util::r9, -    Xbyak::util::r10, -    Xbyak::util::r11, -    // XMMs -    Xbyak::util::xmm0, -    Xbyak::util::xmm1, -    Xbyak::util::xmm2, -    Xbyak::util::xmm3, -    Xbyak::util::xmm4, -    Xbyak::util::xmm5, -    Xbyak::util::xmm6, -    Xbyak::util::xmm7, -    Xbyak::util::xmm8, -    Xbyak::util::xmm9, -    Xbyak::util::xmm10, -    Xbyak::util::xmm11, -    Xbyak::util::xmm12, -    Xbyak::util::xmm13, -    Xbyak::util::xmm14, -    Xbyak::util::xmm15, -}); - -const BitSet32 ABI_ALL_CALLEE_SAVED = BuildRegSet({ -    // GPRs -    Xbyak::util::rbx, -    Xbyak::util::rbp, -    Xbyak::util::r12, -    Xbyak::util::r13, -    Xbyak::util::r14, -    Xbyak::util::r15, -}); - -constexpr std::size_t ABI_SHADOW_SPACE = 0; - -#endif - -inline void ABI_CalculateFrameSize(BitSet32 regs, std::size_t rsp_alignment, -                                   std::size_t needed_frame_size, s32* out_subtraction, -                                   s32* out_xmm_offset) { -    int count = (regs & ABI_ALL_GPRS).Count(); -    rsp_alignment -= count * 8; -    std::size_t subtraction = 0; -    int xmm_count = (regs & ABI_ALL_XMMS).Count(); -    if (xmm_count) { -        // If we have any XMMs to save, we must align the stack here. -        subtraction = rsp_alignment & 0xF; -    } -    subtraction += 0x10 * xmm_count; -    std::size_t xmm_base_subtraction = subtraction; -    subtraction += needed_frame_size; -    subtraction += ABI_SHADOW_SPACE; -    // Final alignment. -    rsp_alignment -= subtraction; -    subtraction += rsp_alignment & 0xF; - -    *out_subtraction = (s32)subtraction; -    *out_xmm_offset = (s32)(subtraction - xmm_base_subtraction); -} - -inline std::size_t ABI_PushRegistersAndAdjustStack(Xbyak::CodeGenerator& code, BitSet32 regs, -                                                   std::size_t rsp_alignment, -                                                   std::size_t needed_frame_size = 0) { -    s32 subtraction, xmm_offset; -    ABI_CalculateFrameSize(regs, rsp_alignment, needed_frame_size, &subtraction, &xmm_offset); - -    for (int reg_index : (regs & ABI_ALL_GPRS)) { -        code.push(IndexToReg64(reg_index)); -    } - -    if (subtraction != 0) { -        code.sub(code.rsp, subtraction); -    } - -    for (int reg_index : (regs & ABI_ALL_XMMS)) { -        code.movaps(code.xword[code.rsp + xmm_offset], IndexToXmm(reg_index)); -        xmm_offset += 0x10; -    } - -    return ABI_SHADOW_SPACE; -} - -inline void ABI_PopRegistersAndAdjustStack(Xbyak::CodeGenerator& code, BitSet32 regs, -                                           std::size_t rsp_alignment, -                                           std::size_t needed_frame_size = 0) { -    s32 subtraction, xmm_offset; -    ABI_CalculateFrameSize(regs, rsp_alignment, needed_frame_size, &subtraction, &xmm_offset); - -    for (int reg_index : (regs & ABI_ALL_XMMS)) { -        code.movaps(IndexToXmm(reg_index), code.xword[code.rsp + xmm_offset]); -        xmm_offset += 0x10; -    } - -    if (subtraction != 0) { -        code.add(code.rsp, subtraction); -    } - -    // GPRs need to be popped in reverse order -    for (int reg_index = 15; reg_index >= 0; reg_index--) { -        if (regs[reg_index]) { -            code.pop(IndexToReg64(reg_index)); -        } -    } -} - -} // namespace Common::X64 diff --git a/src/common/x64/xbyak_util.h b/src/common/x64/xbyak_util.h deleted file mode 100644 index 5cc8a8c76..000000000 --- a/src/common/x64/xbyak_util.h +++ /dev/null @@ -1,47 +0,0 @@ -// 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, -}; - -inline bool IsWithin2G(uintptr_t ref, uintptr_t target) { -    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."); -    std::size_t addr = reinterpret_cast<std::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 | 
