mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-25 23:29:55 -06:00
move ARM64 JIT backend here
This commit is contained in:
24
src/dolphin/Align.h
Normal file
24
src/dolphin/Align.h
Normal file
@ -0,0 +1,24 @@
|
||||
// This file is under the public domain.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
||||
namespace Common
|
||||
{
|
||||
template <typename T>
|
||||
constexpr T AlignUp(T value, size_t size)
|
||||
{
|
||||
static_assert(std::is_unsigned<T>(), "T must be an unsigned value.");
|
||||
return static_cast<T>(value + (size - value % size) % size);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr T AlignDown(T value, size_t size)
|
||||
{
|
||||
static_assert(std::is_unsigned<T>(), "T must be an unsigned value.");
|
||||
return static_cast<T>(value - value % size);
|
||||
}
|
||||
|
||||
} // namespace Common
|
4466
src/dolphin/Arm64Emitter.cpp
Normal file
4466
src/dolphin/Arm64Emitter.cpp
Normal file
File diff suppressed because it is too large
Load Diff
1152
src/dolphin/Arm64Emitter.h
Normal file
1152
src/dolphin/Arm64Emitter.h
Normal file
File diff suppressed because it is too large
Load Diff
27
src/dolphin/ArmCommon.h
Normal file
27
src/dolphin/ArmCommon.h
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2014 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
enum CCFlags
|
||||
{
|
||||
CC_EQ = 0, // Equal
|
||||
CC_NEQ, // Not equal
|
||||
CC_CS, // Carry Set
|
||||
CC_CC, // Carry Clear
|
||||
CC_MI, // Minus (Negative)
|
||||
CC_PL, // Plus
|
||||
CC_VS, // Overflow
|
||||
CC_VC, // No Overflow
|
||||
CC_HI, // Unsigned higher
|
||||
CC_LS, // Unsigned lower or same
|
||||
CC_GE, // Signed greater than or equal
|
||||
CC_LT, // Signed less than
|
||||
CC_GT, // Signed greater than
|
||||
CC_LE, // Signed less than or equal
|
||||
CC_AL, // Always (unconditional) 14
|
||||
CC_HS = CC_CS, // Alias of CC_CS Unsigned higher or same
|
||||
CC_LO = CC_CC, // Alias of CC_CC Unsigned lower
|
||||
};
|
||||
const u32 NO_COND = 0xE0000000;
|
254
src/dolphin/BitUtils.h
Normal file
254
src/dolphin/BitUtils.h
Normal file
@ -0,0 +1,254 @@
|
||||
// Copyright 2017 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <climits>
|
||||
#include <cstddef>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
|
||||
namespace Common
|
||||
{
|
||||
///
|
||||
/// Retrieves the size of a type in bits.
|
||||
///
|
||||
/// @tparam T Type to get the size of.
|
||||
///
|
||||
/// @return the size of the type in bits.
|
||||
///
|
||||
template <typename T>
|
||||
constexpr size_t BitSize() noexcept
|
||||
{
|
||||
return sizeof(T) * CHAR_BIT;
|
||||
}
|
||||
|
||||
///
|
||||
/// Extracts a bit from a value.
|
||||
///
|
||||
/// @param src The value to extract a bit from.
|
||||
/// @param bit The bit to extract.
|
||||
///
|
||||
/// @tparam T The type of the value.
|
||||
///
|
||||
/// @return The extracted bit.
|
||||
///
|
||||
template <typename T>
|
||||
constexpr T ExtractBit(const T src, const size_t bit) noexcept
|
||||
{
|
||||
return (src >> bit) & static_cast<T>(1);
|
||||
}
|
||||
|
||||
///
|
||||
/// Extracts a bit from a value.
|
||||
///
|
||||
/// @param src The value to extract a bit from.
|
||||
///
|
||||
/// @tparam bit The bit to extract.
|
||||
/// @tparam T The type of the value.
|
||||
///
|
||||
/// @return The extracted bit.
|
||||
///
|
||||
template <size_t bit, typename T>
|
||||
constexpr T ExtractBit(const T src) noexcept
|
||||
{
|
||||
static_assert(bit < BitSize<T>(), "Specified bit must be within T's bit width.");
|
||||
|
||||
return ExtractBit(src, bit);
|
||||
}
|
||||
|
||||
///
|
||||
/// Extracts a range of bits from a value.
|
||||
///
|
||||
/// @param src The value to extract the bits from.
|
||||
/// @param begin The beginning of the bit range. This is inclusive.
|
||||
/// @param end The ending of the bit range. This is inclusive.
|
||||
///
|
||||
/// @tparam T The type of the value.
|
||||
/// @tparam Result The returned result type. This is the unsigned analog
|
||||
/// of a signed type if a signed type is passed as T.
|
||||
///
|
||||
/// @return The extracted bits.
|
||||
///
|
||||
template <typename T, typename Result = std::make_unsigned_t<T>>
|
||||
constexpr Result ExtractBits(const T src, const size_t begin, const size_t end) noexcept
|
||||
{
|
||||
return static_cast<Result>(((static_cast<Result>(src) << ((BitSize<T>() - 1) - end)) >>
|
||||
(BitSize<T>() - end + begin - 1)));
|
||||
}
|
||||
|
||||
///
|
||||
/// Extracts a range of bits from a value.
|
||||
///
|
||||
/// @param src The value to extract the bits from.
|
||||
///
|
||||
/// @tparam begin The beginning of the bit range. This is inclusive.
|
||||
/// @tparam end The ending of the bit range. This is inclusive.
|
||||
/// @tparam T The type of the value.
|
||||
/// @tparam Result The returned result type. This is the unsigned analog
|
||||
/// of a signed type if a signed type is passed as T.
|
||||
///
|
||||
/// @return The extracted bits.
|
||||
///
|
||||
template <size_t begin, size_t end, typename T, typename Result = std::make_unsigned_t<T>>
|
||||
constexpr Result ExtractBits(const T src) noexcept
|
||||
{
|
||||
static_assert(begin < end, "Beginning bit must be less than the ending bit.");
|
||||
static_assert(begin < BitSize<T>(), "Beginning bit is larger than T's bit width.");
|
||||
static_assert(end < BitSize<T>(), "Ending bit is larger than T's bit width.");
|
||||
|
||||
return ExtractBits<T, Result>(src, begin, end);
|
||||
}
|
||||
|
||||
///
|
||||
/// Rotates a value left (ROL).
|
||||
///
|
||||
/// @param value The value to rotate.
|
||||
/// @param amount The number of bits to rotate the value.
|
||||
/// @tparam T An unsigned type.
|
||||
///
|
||||
/// @return The rotated value.
|
||||
///
|
||||
template <typename T>
|
||||
constexpr T RotateLeft(const T value, size_t amount) noexcept
|
||||
{
|
||||
static_assert(std::is_unsigned<T>(), "Can only rotate unsigned types left.");
|
||||
|
||||
amount %= BitSize<T>();
|
||||
|
||||
if (amount == 0)
|
||||
return value;
|
||||
|
||||
return static_cast<T>((value << amount) | (value >> (BitSize<T>() - amount)));
|
||||
}
|
||||
|
||||
///
|
||||
/// Rotates a value right (ROR).
|
||||
///
|
||||
/// @param value The value to rotate.
|
||||
/// @param amount The number of bits to rotate the value.
|
||||
/// @tparam T An unsigned type.
|
||||
///
|
||||
/// @return The rotated value.
|
||||
///
|
||||
template <typename T>
|
||||
constexpr T RotateRight(const T value, size_t amount) noexcept
|
||||
{
|
||||
static_assert(std::is_unsigned<T>(), "Can only rotate unsigned types right.");
|
||||
|
||||
amount %= BitSize<T>();
|
||||
|
||||
if (amount == 0)
|
||||
return value;
|
||||
|
||||
return static_cast<T>((value >> amount) | (value << (BitSize<T>() - amount)));
|
||||
}
|
||||
|
||||
///
|
||||
/// Verifies whether the supplied value is a valid bit mask of the form 0b00...0011...11.
|
||||
/// Both edge cases of all zeros and all ones are considered valid masks, too.
|
||||
///
|
||||
/// @param mask The mask value to test for validity.
|
||||
///
|
||||
/// @tparam T The type of the value.
|
||||
///
|
||||
/// @return A bool indicating whether the mask is valid.
|
||||
///
|
||||
template <typename T>
|
||||
constexpr bool IsValidLowMask(const T mask) noexcept
|
||||
{
|
||||
static_assert(std::is_integral<T>::value, "Mask must be an integral type.");
|
||||
static_assert(std::is_unsigned<T>::value, "Signed masks can introduce hard to find bugs.");
|
||||
|
||||
// Can be efficiently determined without looping or bit counting. It's the counterpart
|
||||
// to https://graphics.stanford.edu/~seander/bithacks.html#DetermineIfPowerOf2
|
||||
// and doesn't require special casing either edge case.
|
||||
return (mask & (mask + 1)) == 0;
|
||||
}
|
||||
|
||||
///
|
||||
/// Reinterpret objects of one type as another by bit-casting between object representations.
|
||||
///
|
||||
/// @remark This is the example implementation of std::bit_cast which is to be included
|
||||
/// in C++2a. See http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0476r2.html
|
||||
/// for more details. The only difference is this variant is not constexpr,
|
||||
/// as the mechanism for bit_cast requires a compiler built-in to have that quality.
|
||||
///
|
||||
/// @param source The source object to convert to another representation.
|
||||
///
|
||||
/// @tparam To The type to reinterpret source as.
|
||||
/// @tparam From The initial type representation of source.
|
||||
///
|
||||
/// @return The representation of type From as type To.
|
||||
///
|
||||
/// @pre Both To and From types must be the same size
|
||||
/// @pre Both To and From types must satisfy the TriviallyCopyable concept.
|
||||
///
|
||||
template <typename To, typename From>
|
||||
inline To BitCast(const From& source) noexcept
|
||||
{
|
||||
static_assert(sizeof(From) == sizeof(To),
|
||||
"BitCast source and destination types must be equal in size.");
|
||||
static_assert(std::is_trivially_copyable<From>(),
|
||||
"BitCast source type must be trivially copyable.");
|
||||
static_assert(std::is_trivially_copyable<To>(),
|
||||
"BitCast destination type must be trivially copyable.");
|
||||
|
||||
std::aligned_storage_t<sizeof(To), alignof(To)> storage;
|
||||
std::memcpy(&storage, &source, sizeof(storage));
|
||||
return reinterpret_cast<To&>(storage);
|
||||
}
|
||||
|
||||
template <typename T, typename PtrType>
|
||||
class BitCastPtrType
|
||||
{
|
||||
public:
|
||||
static_assert(std::is_trivially_copyable<PtrType>(),
|
||||
"BitCastPtr source type must be trivially copyable.");
|
||||
static_assert(std::is_trivially_copyable<T>(),
|
||||
"BitCastPtr destination type must be trivially copyable.");
|
||||
|
||||
explicit BitCastPtrType(PtrType* ptr) : m_ptr(ptr) {}
|
||||
|
||||
// Enable operator= only for pointers to non-const data
|
||||
template <typename S>
|
||||
inline typename std::enable_if<std::is_same<S, T>() && !std::is_const<PtrType>()>::type
|
||||
operator=(const S& source)
|
||||
{
|
||||
std::memcpy(m_ptr, &source, sizeof(source));
|
||||
}
|
||||
|
||||
inline operator T() const
|
||||
{
|
||||
T result;
|
||||
std::memcpy(&result, m_ptr, sizeof(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
PtrType* m_ptr;
|
||||
};
|
||||
|
||||
// Provides an aliasing-safe alternative to reinterpret_cast'ing pointers to structs
|
||||
// Conversion constructor and operator= provided for a convenient syntax.
|
||||
// Usage: MyStruct s = BitCastPtr<MyStruct>(some_ptr);
|
||||
// BitCastPtr<MyStruct>(some_ptr) = s;
|
||||
template <typename T, typename PtrType>
|
||||
inline auto BitCastPtr(PtrType* ptr) noexcept -> BitCastPtrType<T, PtrType>
|
||||
{
|
||||
return BitCastPtrType<T, PtrType>{ptr};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void SetBit(T& value, size_t bit_number, bool bit_value)
|
||||
{
|
||||
static_assert(std::is_unsigned<T>(), "SetBit is only sane on unsigned types.");
|
||||
|
||||
if (bit_value)
|
||||
value |= (T{1} << bit_number);
|
||||
else
|
||||
value &= ~(T{1} << bit_number);
|
||||
}
|
||||
|
||||
} // namespace Common
|
@ -61,3 +61,15 @@
|
||||
{ \
|
||||
printf(fmt "\n", ## __VA_ARGS__); \
|
||||
} while (false)
|
||||
|
||||
#if __cplusplus < 201703L
|
||||
// cheat
|
||||
namespace std
|
||||
{
|
||||
template <typename T>
|
||||
T clamp(const T& v, const T& lo, const T& hi)
|
||||
{
|
||||
return v < lo ? lo : (v > hi ? hi : v);
|
||||
}
|
||||
}
|
||||
#endif
|
13
src/dolphin/MathUtil.cpp
Normal file
13
src/dolphin/MathUtil.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2008 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "MathUtil.h"
|
||||
|
||||
#include <numeric>
|
||||
|
||||
// Calculate sum of a float list
|
||||
float MathFloatVectorSum(const std::vector<float>& Vec)
|
||||
{
|
||||
return std::accumulate(Vec.begin(), Vec.end(), 0.0f);
|
||||
}
|
121
src/dolphin/MathUtil.h
Normal file
121
src/dolphin/MathUtil.h
Normal file
@ -0,0 +1,121 @@
|
||||
// Copyright 2008 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "Compat.h"
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
namespace MathUtil
|
||||
{
|
||||
constexpr double TAU = 6.2831853071795865;
|
||||
constexpr double PI = TAU / 2;
|
||||
|
||||
template <typename T>
|
||||
constexpr auto Sign(const T& val) -> decltype((T{} < val) - (val < T{}))
|
||||
{
|
||||
return (T{} < val) - (val < T{});
|
||||
}
|
||||
|
||||
template <typename T, typename F>
|
||||
constexpr auto Lerp(const T& x, const T& y, const F& a) -> decltype(x + (y - x) * a)
|
||||
{
|
||||
return x + (y - x) * a;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr bool IsPow2(T imm)
|
||||
{
|
||||
return imm > 0 && (imm & (imm - 1)) == 0;
|
||||
}
|
||||
|
||||
constexpr u32 NextPowerOf2(u32 value)
|
||||
{
|
||||
--value;
|
||||
value |= value >> 1;
|
||||
value |= value >> 2;
|
||||
value |= value >> 4;
|
||||
value |= value >> 8;
|
||||
value |= value >> 16;
|
||||
++value;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
struct Rectangle
|
||||
{
|
||||
T left{};
|
||||
T top{};
|
||||
T right{};
|
||||
T bottom{};
|
||||
|
||||
constexpr Rectangle() = default;
|
||||
|
||||
constexpr Rectangle(T theLeft, T theTop, T theRight, T theBottom)
|
||||
: left(theLeft), top(theTop), right(theRight), bottom(theBottom)
|
||||
{
|
||||
}
|
||||
|
||||
constexpr bool operator==(const Rectangle& r) const
|
||||
{
|
||||
return left == r.left && top == r.top && right == r.right && bottom == r.bottom;
|
||||
}
|
||||
|
||||
T GetWidth() const { return abs(right - left); }
|
||||
T GetHeight() const { return abs(bottom - top); }
|
||||
// If the rectangle is in a coordinate system with a lower-left origin, use
|
||||
// this Clamp.
|
||||
void ClampLL(T x1, T y1, T x2, T y2)
|
||||
{
|
||||
left = std::clamp(left, x1, x2);
|
||||
right = std::clamp(right, x1, x2);
|
||||
top = std::clamp(top, y2, y1);
|
||||
bottom = std::clamp(bottom, y2, y1);
|
||||
}
|
||||
|
||||
// If the rectangle is in a coordinate system with an upper-left origin,
|
||||
// use this Clamp.
|
||||
void ClampUL(T x1, T y1, T x2, T y2)
|
||||
{
|
||||
left = std::clamp(left, x1, x2);
|
||||
right = std::clamp(right, x1, x2);
|
||||
top = std::clamp(top, y1, y2);
|
||||
bottom = std::clamp(bottom, y1, y2);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace MathUtil
|
||||
|
||||
float MathFloatVectorSum(const std::vector<float>&);
|
||||
|
||||
// Rounds down. 0 -> undefined
|
||||
inline int IntLog2(u64 val)
|
||||
{
|
||||
#if defined(__GNUC__)
|
||||
return 63 - __builtin_clzll(val);
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
unsigned long result = ULONG_MAX;
|
||||
_BitScanReverse64(&result, val);
|
||||
return result;
|
||||
|
||||
#else
|
||||
int result = -1;
|
||||
while (val != 0)
|
||||
{
|
||||
val >>= 1;
|
||||
++result;
|
||||
}
|
||||
return result;
|
||||
#endif
|
||||
}
|
Reference in New Issue
Block a user