mirror of https://github.com/RPCS3/rpcs3.git
Conflicts fixed
This commit is contained in:
commit
58787f80a1
|
@ -36,6 +36,7 @@
|
|||
/ipch
|
||||
/rpcs3/Debug
|
||||
/rpcs3/Release
|
||||
/llvm_build
|
||||
|
||||
/wxWidgets/lib
|
||||
/bin/rpcs3.ini
|
||||
|
|
|
@ -8,3 +8,7 @@
|
|||
[submodule "asmjit"]
|
||||
path = asmjit
|
||||
url = https://github.com/kobalicekp/asmjit
|
||||
[submodule "llvm"]
|
||||
path = llvm
|
||||
url = https://github.com/llvm-mirror/llvm.git
|
||||
branch = release_35
|
||||
|
|
|
@ -27,7 +27,12 @@ before_install:
|
|||
sudo ./cmake-3.0.0-Linux-i386.sh --skip-license --prefix=/usr;
|
||||
|
||||
before_script:
|
||||
- git submodule update --init asmjit ffmpeg
|
||||
- git submodule update --init asmjit ffmpeg llvm
|
||||
- cd llvm_build
|
||||
- cmake -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF ../llvm
|
||||
- make -j 4
|
||||
- sudo make install
|
||||
- cd ..
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake ..
|
||||
|
|
21123
GL/glext.h
21123
GL/glext.h
File diff suppressed because it is too large
Load Diff
|
@ -29,7 +29,7 @@ __Mac OSX__
|
|||
### Building
|
||||
|
||||
To initialize the repository don't forget to execute `git submodule update --init` to pull the wxWidgets source.
|
||||
* __Windows__: Install *Visual Studio 2013*. Then open the *.SLN* file, and press *Build* > *Rebuild Solution*.
|
||||
* __Windows__: Install *Visual Studio 2013*, *Cmake*, *Python* and select *Add in the PATH variable* for both. Then open the *.SLN* file, and press *Build* > *Rebuild Solution*.
|
||||
* __Linux & Mac OSX__:
|
||||
`cd rpcs3 && cmake CMakeLists.txt && make && cd ../` Then run with `cd bin && ./rpcs3`
|
||||
|
||||
|
|
|
@ -69,12 +69,12 @@ void AutoPause::Reload(void)
|
|||
//Less than 1024 - be regarded as a system call.
|
||||
//emplace_back may not cause reductant move/copy operation.
|
||||
m_pause_syscall.emplace_back(num);
|
||||
LOG_WARNING(HLE, "Auto Pause: Find System Call ID %x", num);
|
||||
LOG_WARNING(HLE, "Auto Pause: Find System Call ID 0x%x", num);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pause_function.emplace_back(num);
|
||||
LOG_WARNING(HLE, "Auto Pause: Find Function Call ID %x", num);
|
||||
LOG_WARNING(HLE, "Auto Pause: Find Function Call ID 0x%x", num);
|
||||
}
|
||||
}
|
||||
list.Close();
|
||||
|
@ -103,7 +103,7 @@ void AutoPause::TryPause(u32 code) {
|
|||
if (code == m_pause_syscall[i])
|
||||
{
|
||||
Emu.Pause();
|
||||
LOG_ERROR(HLE, "Auto Pause Triggered: System call %x", code); //Used Error
|
||||
LOG_ERROR(HLE, "Auto Pause Triggered: System call 0x%x", code); // Used Error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -121,7 +121,7 @@ void AutoPause::TryPause(u32 code) {
|
|||
if (code == m_pause_function[i])
|
||||
{
|
||||
Emu.Pause();
|
||||
LOG_ERROR(HLE, "Auto Pause Triggered: Function call %x", code); //Used Error
|
||||
LOG_ERROR(HLE, "Auto Pause Triggered: Function call 0x%x", code); // Used Error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,91 @@
|
|||
#pragma once
|
||||
|
||||
#include <emmintrin.h>
|
||||
|
||||
union u128
|
||||
union _CRT_ALIGN(16) u128
|
||||
{
|
||||
u64 _u64[2];
|
||||
s64 _s64[2];
|
||||
|
||||
class u64_reversed_array_2
|
||||
{
|
||||
u64 data[2];
|
||||
|
||||
public:
|
||||
u64& operator [] (s32 index)
|
||||
{
|
||||
return data[1 - index];
|
||||
}
|
||||
|
||||
const u64& operator [] (s32 index) const
|
||||
{
|
||||
return data[1 - index];
|
||||
}
|
||||
|
||||
} u64r;
|
||||
|
||||
u32 _u32[4];
|
||||
s32 _s32[4];
|
||||
|
||||
class u32_reversed_array_4
|
||||
{
|
||||
u32 data[4];
|
||||
|
||||
public:
|
||||
u32& operator [] (s32 index)
|
||||
{
|
||||
return data[3 - index];
|
||||
}
|
||||
|
||||
const u32& operator [] (s32 index) const
|
||||
{
|
||||
return data[3 - index];
|
||||
}
|
||||
|
||||
} u32r;
|
||||
|
||||
u16 _u16[8];
|
||||
s16 _s16[8];
|
||||
|
||||
class u16_reversed_array_8
|
||||
{
|
||||
u16 data[8];
|
||||
|
||||
public:
|
||||
u16& operator [] (s32 index)
|
||||
{
|
||||
return data[7 - index];
|
||||
}
|
||||
|
||||
const u16& operator [] (s32 index) const
|
||||
{
|
||||
return data[7 - index];
|
||||
}
|
||||
|
||||
} u16r;
|
||||
|
||||
u8 _u8[16];
|
||||
s8 _s8[16];
|
||||
|
||||
class u8_reversed_array_16
|
||||
{
|
||||
u8 data[16];
|
||||
|
||||
public:
|
||||
u8& operator [] (s32 index)
|
||||
{
|
||||
return data[15 - index];
|
||||
}
|
||||
|
||||
const u8& operator [] (s32 index) const
|
||||
{
|
||||
return data[15 - index];
|
||||
}
|
||||
|
||||
} u8r;
|
||||
|
||||
float _f[4];
|
||||
double _d[2];
|
||||
__m128 xmm;
|
||||
__m128 vf;
|
||||
__m128i vi;
|
||||
|
||||
class bit_array_128
|
||||
{
|
||||
|
@ -94,6 +165,11 @@ union u128
|
|||
return ret;
|
||||
}
|
||||
|
||||
static u128 from64r(u64 _1, u64 _0 = 0)
|
||||
{
|
||||
return from64(_0, _1);
|
||||
}
|
||||
|
||||
static u128 from32(u32 _0, u32 _1 = 0, u32 _2 = 0, u32 _3 = 0)
|
||||
{
|
||||
u128 ret;
|
||||
|
@ -104,6 +180,25 @@ union u128
|
|||
return ret;
|
||||
}
|
||||
|
||||
static u128 from32r(u32 _3, u32 _2 = 0, u32 _1 = 0, u32 _0 = 0)
|
||||
{
|
||||
return from32(_0, _1, _2, _3);
|
||||
}
|
||||
|
||||
static u128 from32p(u32 value)
|
||||
{
|
||||
u128 ret;
|
||||
ret.vi = _mm_set1_epi32((int)value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u128 from8p(u8 value)
|
||||
{
|
||||
u128 ret;
|
||||
ret.vi = _mm_set1_epi8((char)value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static u128 fromBit(u32 bit)
|
||||
{
|
||||
u128 ret = {};
|
||||
|
@ -111,9 +206,41 @@ union u128
|
|||
return ret;
|
||||
}
|
||||
|
||||
void setBit(u32 bit)
|
||||
static u128 fromV(__m128i value)
|
||||
{
|
||||
_bit[bit] = true;
|
||||
u128 ret;
|
||||
ret.vi = value;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static __forceinline u128 add8(const u128& left, const u128& right)
|
||||
{
|
||||
return fromV(_mm_add_epi8(left.vi, right.vi));
|
||||
}
|
||||
|
||||
static __forceinline u128 sub8(const u128& left, const u128& right)
|
||||
{
|
||||
return fromV(_mm_sub_epi8(left.vi, right.vi));
|
||||
}
|
||||
|
||||
static __forceinline u128 minu8(const u128& left, const u128& right)
|
||||
{
|
||||
return fromV(_mm_min_epu8(left.vi, right.vi));
|
||||
}
|
||||
|
||||
static __forceinline u128 eq8(const u128& left, const u128& right)
|
||||
{
|
||||
return fromV(_mm_cmpeq_epi8(left.vi, right.vi));
|
||||
}
|
||||
|
||||
static __forceinline u128 gtu8(const u128& left, const u128& right)
|
||||
{
|
||||
return fromV(_mm_cmpgt_epu8(left.vi, right.vi));
|
||||
}
|
||||
|
||||
static __forceinline u128 leu8(const u128& left, const u128& right)
|
||||
{
|
||||
return fromV(_mm_cmple_epu8(left.vi, right.vi));
|
||||
}
|
||||
|
||||
bool operator == (const u128& right) const
|
||||
|
@ -126,19 +253,19 @@ union u128
|
|||
return (_u64[0] != right._u64[0]) || (_u64[1] != right._u64[1]);
|
||||
}
|
||||
|
||||
u128 operator | (const u128& right) const
|
||||
__forceinline u128 operator | (const u128& right) const
|
||||
{
|
||||
return from64(_u64[0] | right._u64[0], _u64[1] | right._u64[1]);
|
||||
return fromV(_mm_or_si128(vi, right.vi));
|
||||
}
|
||||
|
||||
u128 operator & (const u128& right) const
|
||||
__forceinline u128 operator & (const u128& right) const
|
||||
{
|
||||
return from64(_u64[0] & right._u64[0], _u64[1] & right._u64[1]);
|
||||
return fromV(_mm_and_si128(vi, right.vi));
|
||||
}
|
||||
|
||||
u128 operator ^ (const u128& right) const
|
||||
__forceinline u128 operator ^ (const u128& right) const
|
||||
{
|
||||
return from64(_u64[0] ^ right._u64[0], _u64[1] ^ right._u64[1]);
|
||||
return fromV(_mm_xor_si128(vi, right.vi));
|
||||
}
|
||||
|
||||
u128 operator ~ () const
|
||||
|
@ -146,6 +273,12 @@ union u128
|
|||
return from64(~_u64[0], ~_u64[1]);
|
||||
}
|
||||
|
||||
// result = (~left) & (right)
|
||||
static __forceinline u128 andnot(const u128& left, const u128& right)
|
||||
{
|
||||
return fromV(_mm_andnot_si128(left.vi, right.vi));
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
_u64[1] = _u64[0] = 0;
|
||||
|
@ -153,7 +286,7 @@ union u128
|
|||
|
||||
std::string to_hex() const
|
||||
{
|
||||
return fmt::Format("%16llx%16llx", _u64[1], _u64[0]);
|
||||
return fmt::Format("%016llx%016llx", _u64[1], _u64[0]);
|
||||
}
|
||||
|
||||
std::string to_xyzw() const
|
||||
|
@ -170,6 +303,72 @@ union u128
|
|||
}
|
||||
};
|
||||
|
||||
#ifndef InterlockedCompareExchange
|
||||
static __forceinline u128 InterlockedCompareExchange(volatile u128* dest, u128 exch, u128 comp)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
auto res = __sync_val_compare_and_swap((volatile __int128_t*)dest, (__int128_t&)comp, (__int128_t&)exch);
|
||||
return (u128&)res;
|
||||
#else
|
||||
_InterlockedCompareExchange128((volatile long long*)dest, exch._u64[1], exch._u64[0], (long long*)&comp);
|
||||
return comp;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static __forceinline bool InterlockedCompareExchangeTest(volatile u128* dest, u128 exch, u128 comp)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_bool_compare_and_swap((volatile __int128_t*)dest, (__int128_t&)comp, (__int128_t&)exch);
|
||||
#else
|
||||
return _InterlockedCompareExchange128((volatile long long*)dest, exch._u64[1], exch._u64[0], (long long*)&comp) != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef InterlockedExchange
|
||||
static __forceinline u128 InterlockedExchange(volatile u128* dest, u128 value)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
const u128 old = *(u128*)dest;
|
||||
if (InterlockedCompareExchangeTest(dest, value, old)) return old;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef InterlockedOr
|
||||
static __forceinline u128 InterlockedOr(volatile u128* dest, u128 value)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
const u128 old = *(u128*)dest;
|
||||
if (InterlockedCompareExchangeTest(dest, old | value, old)) return old;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef InterlockedAnd
|
||||
static __forceinline u128 InterlockedAnd(volatile u128* dest, u128 value)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
const u128 old = *(u128*)dest;
|
||||
if (InterlockedCompareExchangeTest(dest, old & value, old)) return old;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef InterlockedXor
|
||||
static __forceinline u128 InterlockedXor(volatile u128* dest, u128 value)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
const u128 old = *(u128*)dest;
|
||||
if (InterlockedCompareExchangeTest(dest, old ^ value, old)) return old;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#define re16(val) _byteswap_ushort(val)
|
||||
#define re32(val) _byteswap_ulong(val)
|
||||
#define re64(val) _byteswap_uint64(val)
|
||||
|
@ -252,7 +451,13 @@ template<typename T, typename T2 = T>
|
|||
class be_t
|
||||
{
|
||||
static_assert(sizeof(T2) == 1 || sizeof(T2) == 2 || sizeof(T2) == 4 || sizeof(T2) == 8, "Bad be_t type");
|
||||
T m_data;
|
||||
|
||||
public:
|
||||
typedef typename std::remove_cv<T>::type type;
|
||||
static const bool is_le_machine = true;
|
||||
|
||||
private:
|
||||
type m_data;
|
||||
|
||||
template<typename Tto, typename Tfrom, int mode>
|
||||
struct _convert
|
||||
|
@ -283,59 +488,78 @@ class be_t
|
|||
return (be_t<Tto>&)res;
|
||||
}
|
||||
};
|
||||
public:
|
||||
typedef T type;
|
||||
|
||||
const T& ToBE() const
|
||||
public:
|
||||
const type& ToBE() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
T ToLE() const
|
||||
type ToLE() const
|
||||
{
|
||||
return se_t<T, sizeof(T2)>::func(m_data);
|
||||
return se_t<type, sizeof(T2)>::func(m_data);
|
||||
}
|
||||
|
||||
void FromBE(const T& value)
|
||||
void FromBE(const type& value)
|
||||
{
|
||||
m_data = value;
|
||||
}
|
||||
|
||||
void FromLE(const T& value)
|
||||
void FromLE(const type& value)
|
||||
{
|
||||
m_data = se_t<T, sizeof(T2)>::func(value);
|
||||
m_data = se_t<type, sizeof(T2)>::func(value);
|
||||
}
|
||||
|
||||
static be_t MakeFromLE(const T value)
|
||||
static be_t MakeFromLE(const type value)
|
||||
{
|
||||
T data = se_t<T, sizeof(T2)>::func(value);
|
||||
type data = se_t<type, sizeof(T2)>::func(value);
|
||||
return (be_t&)data;
|
||||
}
|
||||
|
||||
static be_t MakeFromBE(const T value)
|
||||
static be_t MakeFromBE(const type value)
|
||||
{
|
||||
return (be_t&)value;
|
||||
}
|
||||
|
||||
//template<typename T1>
|
||||
operator const T() const
|
||||
//make be_t from current machine byte ordering
|
||||
static be_t make(const type value)
|
||||
{
|
||||
return ToLE();
|
||||
return is_le_machine ? MakeFromLE(value) : MakeFromBE(value);
|
||||
}
|
||||
|
||||
//get value in current machine byte ordering
|
||||
__forceinline type value() const
|
||||
{
|
||||
return is_le_machine ? ToLE() : ToBE();
|
||||
}
|
||||
|
||||
//be_t() = default;
|
||||
//be_t(const be_t& value) = default;
|
||||
|
||||
//be_t(type value)
|
||||
//{
|
||||
// m_data = se_t<type, sizeof(T2)>::func(value);
|
||||
//}
|
||||
|
||||
be_t& operator = (const be_t& value) = default;
|
||||
|
||||
be_t& operator = (T value)
|
||||
be_t& operator = (type value)
|
||||
{
|
||||
m_data = se_t<T, sizeof(T2)>::func(value);
|
||||
m_data = se_t<type, sizeof(T2)>::func(value);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator type() const
|
||||
{
|
||||
return value();
|
||||
}
|
||||
|
||||
template<typename T1>
|
||||
operator const be_t<T1>() const
|
||||
{
|
||||
return _convert<T1, T, ((sizeof(T1) > sizeof(T)) ? 1 : (sizeof(T1) < sizeof(T) ? 2 : 0))>::func(m_data);
|
||||
return be_t<T1>::make(value());
|
||||
//return _convert<T1, T, ((sizeof(T1) > sizeof(T)) ? 1 : (sizeof(T1) < sizeof(T) ? 2 : 0))>::func(m_data);
|
||||
}
|
||||
|
||||
template<typename T1> be_t& operator += (T1 right) { return *this = T(*this) + right; }
|
||||
|
@ -382,81 +606,6 @@ public:
|
|||
be_t& operator-- () { *this -= 1; return *this; }
|
||||
};
|
||||
|
||||
template<typename T, typename T2>
|
||||
class be_t<const T, T2>
|
||||
{
|
||||
static_assert(sizeof(T2) == 1 || sizeof(T2) == 2 || sizeof(T2) == 4 || sizeof(T2) == 8, "Bad be_t type");
|
||||
const T m_data;
|
||||
|
||||
public:
|
||||
typedef const T type;
|
||||
|
||||
const T& ToBE() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
const T ToLE() const
|
||||
{
|
||||
return se_t<const T, sizeof(T2)>::func(m_data);
|
||||
}
|
||||
|
||||
static be_t MakeFromLE(const T value)
|
||||
{
|
||||
const T data = se_t<const T, sizeof(T2)>::func(value);
|
||||
return (be_t&)data;
|
||||
}
|
||||
|
||||
static be_t MakeFromBE(const T value)
|
||||
{
|
||||
return (be_t&)value;
|
||||
}
|
||||
|
||||
//template<typename T1>
|
||||
operator const T() const
|
||||
{
|
||||
return ToLE();
|
||||
}
|
||||
|
||||
template<typename T1>
|
||||
operator const be_t<T1>() const
|
||||
{
|
||||
if (sizeof(T1) > sizeof(T) || std::is_floating_point<T>::value || std::is_floating_point<T1>::value)
|
||||
{
|
||||
T1 res = se_t<T1, sizeof(T1)>::func(ToLE());
|
||||
return (be_t<T1>&)res;
|
||||
}
|
||||
else if (sizeof(T1) < sizeof(T))
|
||||
{
|
||||
T1 res = ToBE() >> ((sizeof(T) - sizeof(T1)) * 8);
|
||||
return (be_t<T1>&)res;
|
||||
}
|
||||
else
|
||||
{
|
||||
T1 res = ToBE();
|
||||
return (be_t<T1>&)res;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T1> be_t operator & (const be_t<T1>& right) const { const T res = ToBE() & right.ToBE(); return (be_t&)res; }
|
||||
template<typename T1> be_t operator | (const be_t<T1>& right) const { const T res = ToBE() | right.ToBE(); return (be_t&)res; }
|
||||
template<typename T1> be_t operator ^ (const be_t<T1>& right) const { const T res = ToBE() ^ right.ToBE(); return (be_t&)res; }
|
||||
|
||||
template<typename T1> bool operator == (T1 right) const { return (T1)ToLE() == right; }
|
||||
template<typename T1> bool operator != (T1 right) const { return !(*this == right); }
|
||||
template<typename T1> bool operator > (T1 right) const { return (T1)ToLE() > right; }
|
||||
template<typename T1> bool operator < (T1 right) const { return (T1)ToLE() < right; }
|
||||
template<typename T1> bool operator >= (T1 right) const { return (T1)ToLE() >= right; }
|
||||
template<typename T1> bool operator <= (T1 right) const { return (T1)ToLE() <= right; }
|
||||
|
||||
template<typename T1> bool operator == (const be_t<T1>& right) const { return ToBE() == right.ToBE(); }
|
||||
template<typename T1> bool operator != (const be_t<T1>& right) const { return !(*this == right); }
|
||||
template<typename T1> bool operator > (const be_t<T1>& right) const { return (T1)ToLE() > right.ToLE(); }
|
||||
template<typename T1> bool operator < (const be_t<T1>& right) const { return (T1)ToLE() < right.ToLE(); }
|
||||
template<typename T1> bool operator >= (const be_t<T1>& right) const { return (T1)ToLE() >= right.ToLE(); }
|
||||
template<typename T1> bool operator <= (const be_t<T1>& right) const { return (T1)ToLE() <= right.ToLE(); }
|
||||
};
|
||||
|
||||
template<typename T, typename T2 = T>
|
||||
struct is_be_t : public std::integral_constant<bool, false> {};
|
||||
|
||||
|
@ -496,6 +645,8 @@ public:
|
|||
|
||||
//be_t<T, size> if need swap endianes, T otherwise
|
||||
typedef typename _be_type_selector< T, T2, value >::type type;
|
||||
|
||||
typedef typename _be_type_selector< T, T2, !is_be_t<T, T2>::value >::type forced_type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
@ -623,3 +774,51 @@ template<typename T> __forceinline static void Write64(T& f, const u64 data)
|
|||
{
|
||||
Write64LE(f, re64(data));
|
||||
}
|
||||
|
||||
template<typename Tto, typename Tfrom>
|
||||
struct convert_le_be_t
|
||||
{
|
||||
static Tto func(Tfrom&& value)
|
||||
{
|
||||
return (Tto)value;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Tt, typename Tt1, typename Tfrom>
|
||||
struct convert_le_be_t<be_t<Tt, Tt1>, Tfrom>
|
||||
{
|
||||
static be_t<Tt, Tt1> func(Tfrom&& value)
|
||||
{
|
||||
return be_t<Tt, Tt1>::make(value);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Tt, typename Tt1, typename Tf, typename Tf1>
|
||||
struct convert_le_be_t<be_t<Tt, Tt1>, be_t<Tf, Tf1>>
|
||||
{
|
||||
static be_t<Tt, Tt1> func(be_t<Tf, Tf1>&& value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Tto, typename Tf, typename Tf1>
|
||||
struct convert_le_be_t<Tto, be_t<Tf, Tf1>>
|
||||
{
|
||||
static Tto func(be_t<Tf, Tf1>&& value)
|
||||
{
|
||||
return value.value();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Tto, typename Tfrom>
|
||||
__forceinline Tto convert_le_be(Tfrom&& value)
|
||||
{
|
||||
return convert_le_be_t<Tto, Tfrom>::func(value);
|
||||
}
|
||||
|
||||
template<typename Tto, typename Tfrom>
|
||||
__forceinline void convert_le_be(Tto& dst, Tfrom&& src)
|
||||
{
|
||||
dst = convert_le_be_t<Tto, Tfrom>::func(src);
|
||||
}
|
271
Utilities/GNU.h
271
Utilities/GNU.h
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <emmintrin.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define thread_local __declspec(thread)
|
||||
#elif __APPLE__
|
||||
|
@ -13,13 +15,21 @@
|
|||
#endif
|
||||
|
||||
template<size_t size>
|
||||
void strcpy_trunc(char (&dst)[size], const std::string& src)
|
||||
void strcpy_trunc(char(&dst)[size], const std::string& src)
|
||||
{
|
||||
const size_t count = (src.size() >= size) ? size - 1 /* truncation */ : src.size();
|
||||
memcpy(dst, src.c_str(), count);
|
||||
dst[count] = 0;
|
||||
}
|
||||
|
||||
template<size_t size, size_t rsize>
|
||||
void strcpy_trunc(char(&dst)[size], const char(&src)[rsize])
|
||||
{
|
||||
const size_t count = (rsize >= size) ? size - 1 /* truncation */ : rsize;
|
||||
memcpy(dst, src, count);
|
||||
dst[count] = 0;
|
||||
}
|
||||
|
||||
#if defined(__GNUG__)
|
||||
#include <cmath>
|
||||
#include <stdlib.h>
|
||||
|
@ -36,20 +46,6 @@ void strcpy_trunc(char (&dst)[size], const std::string& src)
|
|||
#define _byteswap_uint64(x) __builtin_bswap64(x)
|
||||
#define INFINITE 0xFFFFFFFF
|
||||
#define _CRT_ALIGN(x) __attribute__((aligned(x)))
|
||||
#define InterlockedCompareExchange(ptr,new_val,old_val) __sync_val_compare_and_swap(ptr,old_val,new_val)
|
||||
#define InterlockedCompareExchange64(ptr,new_val,old_val) __sync_val_compare_and_swap(ptr,old_val,new_val)
|
||||
|
||||
inline int64_t InterlockedOr64(volatile int64_t *dest, int64_t val)
|
||||
{
|
||||
int64_t olderval;
|
||||
int64_t oldval = *dest;
|
||||
do
|
||||
{
|
||||
olderval = oldval;
|
||||
oldval = InterlockedCompareExchange64(dest, olderval | val, olderval);
|
||||
} while (olderval != oldval);
|
||||
return oldval;
|
||||
}
|
||||
|
||||
inline uint64_t __umulh(uint64_t a, uint64_t b)
|
||||
{
|
||||
|
@ -84,12 +80,257 @@ int clock_gettime(int foo, struct timespec *ts);
|
|||
#endif
|
||||
|
||||
#ifndef InterlockedCompareExchange
|
||||
static __forceinline uint8_t InterlockedCompareExchange(volatile uint8_t* dest, uint8_t exch, uint8_t comp)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_val_compare_and_swap(dest, comp, exch);
|
||||
#else
|
||||
return _InterlockedCompareExchange8((volatile char*)dest, exch, comp);
|
||||
#endif
|
||||
}
|
||||
static __forceinline uint16_t InterlockedCompareExchange(volatile uint16_t* dest, uint16_t exch, uint16_t comp)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_val_compare_and_swap(dest, comp, exch);
|
||||
#else
|
||||
return _InterlockedCompareExchange16((volatile short*)dest, exch, comp);
|
||||
#endif
|
||||
}
|
||||
static __forceinline uint32_t InterlockedCompareExchange(volatile uint32_t* dest, uint32_t exch, uint32_t comp)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_val_compare_and_swap(dest, comp, exch);
|
||||
#else
|
||||
return _InterlockedCompareExchange((volatile long*)dest, exch, comp);
|
||||
#endif
|
||||
}
|
||||
static __forceinline uint64_t InterlockedCompareExchange(volatile uint64_t* dest, uint64_t exch, uint64_t comp)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_val_compare_and_swap(dest, comp, exch);
|
||||
#else
|
||||
return _InterlockedCompareExchange64((volatile long long*)dest, exch, comp);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static __forceinline bool InterlockedCompareExchangeTest(volatile uint8_t* dest, uint8_t exch, uint8_t comp)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_bool_compare_and_swap(dest, comp, exch);
|
||||
#else
|
||||
return (uint8_t)_InterlockedCompareExchange8((volatile char*)dest, exch, comp) == comp;
|
||||
#endif
|
||||
}
|
||||
static __forceinline bool InterlockedCompareExchangeTest(volatile uint16_t* dest, uint16_t exch, uint16_t comp)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_bool_compare_and_swap(dest, comp, exch);
|
||||
#else
|
||||
return (uint16_t)_InterlockedCompareExchange16((volatile short*)dest, exch, comp) == comp;
|
||||
#endif
|
||||
}
|
||||
static __forceinline bool InterlockedCompareExchangeTest(volatile uint32_t* dest, uint32_t exch, uint32_t comp)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_bool_compare_and_swap(dest, comp, exch);
|
||||
#else
|
||||
return (uint32_t)_InterlockedCompareExchange((volatile long*)dest, exch, comp) == comp;
|
||||
#endif
|
||||
}
|
||||
static __forceinline bool InterlockedCompareExchangeTest(volatile uint64_t* dest, uint64_t exch, uint64_t comp)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_bool_compare_and_swap(dest, comp, exch);
|
||||
#else
|
||||
return (uint64_t)_InterlockedCompareExchange64((volatile long long*)dest, exch, comp) == comp;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef InterlockedExchange
|
||||
static __forceinline uint8_t InterlockedExchange(volatile uint8_t* dest, uint8_t value)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_lock_test_and_set(dest, value);
|
||||
#else
|
||||
return _InterlockedExchange8((volatile char*)dest, value);
|
||||
#endif
|
||||
}
|
||||
static __forceinline uint16_t InterlockedExchange(volatile uint16_t* dest, uint16_t value)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_lock_test_and_set(dest, value);
|
||||
#else
|
||||
return _InterlockedExchange16((volatile short*)dest, value);
|
||||
#endif
|
||||
}
|
||||
static __forceinline uint32_t InterlockedExchange(volatile uint32_t* dest, uint32_t value)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_lock_test_and_set(dest, value);
|
||||
#else
|
||||
return _InterlockedExchange((volatile long*)dest, value);
|
||||
#endif
|
||||
}
|
||||
static __forceinline uint64_t InterlockedExchange(volatile uint64_t* dest, uint64_t value)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_lock_test_and_set(dest, value);
|
||||
#else
|
||||
return _InterlockedExchange64((volatile long long*)dest, value);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef InterlockedOr
|
||||
static __forceinline uint8_t InterlockedOr(volatile uint8_t* dest, uint8_t value)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_fetch_and_or(dest, value);
|
||||
#else
|
||||
return _InterlockedOr8((volatile char*)dest, value);
|
||||
#endif
|
||||
}
|
||||
static __forceinline uint16_t InterlockedOr(volatile uint16_t* dest, uint16_t value)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_fetch_and_or(dest, value);
|
||||
#else
|
||||
return _InterlockedOr16((volatile short*)dest, value);
|
||||
#endif
|
||||
}
|
||||
static __forceinline uint32_t InterlockedOr(volatile uint32_t* dest, uint32_t value)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_fetch_and_or(dest, value);
|
||||
#else
|
||||
return _InterlockedOr((volatile long*)dest, value);
|
||||
#endif
|
||||
}
|
||||
static __forceinline uint64_t InterlockedOr(volatile uint64_t* dest, uint64_t value)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_fetch_and_or(dest, value);
|
||||
#else
|
||||
return _InterlockedOr64((volatile long long*)dest, value);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef InterlockedAnd
|
||||
static __forceinline uint8_t InterlockedAnd(volatile uint8_t* dest, uint8_t value)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_fetch_and_and(dest, value);
|
||||
#else
|
||||
return _InterlockedAnd8((volatile char*)dest, value);
|
||||
#endif
|
||||
}
|
||||
static __forceinline uint16_t InterlockedAnd(volatile uint16_t* dest, uint16_t value)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_fetch_and_and(dest, value);
|
||||
#else
|
||||
return _InterlockedAnd16((volatile short*)dest, value);
|
||||
#endif
|
||||
}
|
||||
static __forceinline uint32_t InterlockedAnd(volatile uint32_t* dest, uint32_t value)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_fetch_and_and(dest, value);
|
||||
#else
|
||||
return _InterlockedAnd((volatile long*)dest, value);
|
||||
#endif
|
||||
}
|
||||
static __forceinline uint64_t InterlockedAnd(volatile uint64_t* dest, uint64_t value)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_fetch_and_and(dest, value);
|
||||
#else
|
||||
return _InterlockedAnd64((volatile long long*)dest, value);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef InterlockedXor
|
||||
static __forceinline uint8_t InterlockedXor(volatile uint8_t* dest, uint8_t value)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_fetch_and_xor(dest, value);
|
||||
#else
|
||||
return _InterlockedXor8((volatile char*)dest, value);
|
||||
#endif
|
||||
}
|
||||
static __forceinline uint16_t InterlockedXor(volatile uint16_t* dest, uint16_t value)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_fetch_and_xor(dest, value);
|
||||
#else
|
||||
return _InterlockedXor16((volatile short*)dest, value);
|
||||
#endif
|
||||
}
|
||||
static __forceinline uint32_t InterlockedXor(volatile uint32_t* dest, uint32_t value)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_fetch_and_xor(dest, value);
|
||||
#else
|
||||
return _InterlockedXor((volatile long*)dest, value);
|
||||
#endif
|
||||
}
|
||||
static __forceinline uint64_t InterlockedXor(volatile uint64_t* dest, uint64_t value)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __sync_fetch_and_xor(dest, value);
|
||||
#else
|
||||
return _InterlockedXor64((volatile long long*)dest, value);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static __forceinline uint32_t cntlz32(uint32_t arg)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __builtin_clzl(arg);
|
||||
#else
|
||||
unsigned long res;
|
||||
if (!_BitScanReverse(&res, arg))
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
return res ^ 31;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static __forceinline uint64_t cntlz64(uint64_t arg)
|
||||
{
|
||||
#if defined(__GNUG__)
|
||||
return __builtin_clzll(arg);
|
||||
#else
|
||||
unsigned long res;
|
||||
if (!_BitScanReverse64(&res, arg))
|
||||
{
|
||||
return 64;
|
||||
}
|
||||
else
|
||||
{
|
||||
return res ^ 63;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// compare 16 packed unsigned bytes (greater than)
|
||||
static __forceinline __m128i _mm_cmpgt_epu8(__m128i A, __m128i B)
|
||||
{
|
||||
// (A xor 0x80) > (B xor 0x80)
|
||||
return _mm_cmpgt_epi8(_mm_xor_si128(A, _mm_set1_epi8(-128)), _mm_xor_si128(B, _mm_set1_epi8(-128)));
|
||||
}
|
||||
|
||||
// compare 16 packed unsigned bytes (less or equal)
|
||||
static __forceinline __m128i _mm_cmple_epu8(__m128i A, __m128i B)
|
||||
{
|
||||
// ((B xor 0x80) > (A xor 0x80)) || A == B
|
||||
return _mm_or_si128(_mm_cmpgt_epu8(B, A), _mm_cmpeq_epi8(A, B));
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace Log
|
|||
HLE,
|
||||
PPU,
|
||||
SPU,
|
||||
ARMv7,
|
||||
TTY,
|
||||
};
|
||||
|
||||
|
@ -35,7 +36,7 @@ namespace Log
|
|||
};
|
||||
|
||||
//well I'd love make_array() but alas manually counting is not the end of the world
|
||||
static const std::array<LogTypeName, 8> gTypeNameTable = { {
|
||||
static const std::array<LogTypeName, 9> gTypeNameTable = { {
|
||||
{ GENERAL, "G: " },
|
||||
{ LOADER, "LDR: " },
|
||||
{ MEMORY, "MEM: " },
|
||||
|
@ -43,6 +44,7 @@ namespace Log
|
|||
{ HLE, "HLE: " },
|
||||
{ PPU, "PPU: " },
|
||||
{ SPU, "SPU: " },
|
||||
{ ARMv7, "ARM: " },
|
||||
{ TTY, "TTY: " }
|
||||
} };
|
||||
|
||||
|
@ -121,6 +123,7 @@ static struct { inline operator Log::LogType() { return Log::LogType::RSX; } } R
|
|||
static struct { inline operator Log::LogType() { return Log::LogType::HLE; } } HLE;
|
||||
static struct { inline operator Log::LogType() { return Log::LogType::PPU; } } PPU;
|
||||
static struct { inline operator Log::LogType() { return Log::LogType::SPU; } } SPU;
|
||||
static struct { inline operator Log::LogType() { return Log::LogType::ARMv7; } } ARMv7;
|
||||
static struct { inline operator Log::LogType() { return Log::LogType::TTY; } } TTY;
|
||||
|
||||
inline void log_message(Log::LogType type, Log::LogSeverity sev, const char* text)
|
||||
|
|
|
@ -8,15 +8,3 @@ bool SM_IsAborted()
|
|||
{
|
||||
return Emu.IsStopped();
|
||||
}
|
||||
|
||||
void SM_Sleep()
|
||||
{
|
||||
if (NamedThreadBase* t = GetCurrentNamedThread())
|
||||
{
|
||||
t->WaitForAnySignal();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
|
||||
bool SM_IsAborted();
|
||||
void SM_Sleep();
|
||||
|
||||
enum SMutexResult
|
||||
{
|
||||
|
@ -19,25 +19,25 @@ template
|
|||
<
|
||||
typename T,
|
||||
const u64 free_value = 0,
|
||||
const u64 dead_value = 0xffffffffffffffffull,
|
||||
void (*wait)() = SM_Sleep
|
||||
const u64 dead_value = 0xffffffffffffffffull
|
||||
>
|
||||
class SMutexBase
|
||||
{
|
||||
static_assert(sizeof(T) == sizeof(std::atomic<T>), "Invalid SMutexBase type");
|
||||
std::atomic<T> owner;
|
||||
static_assert(sizeof(T) == sizeof(atomic_le_t<T>), "Invalid SMutexBase type");
|
||||
T owner;
|
||||
typedef atomic_le_t<T> AT;
|
||||
|
||||
public:
|
||||
static const T GetFreeValue()
|
||||
{
|
||||
static const u64 value = free_value;
|
||||
return (const T&)value;
|
||||
return (T&)value;
|
||||
}
|
||||
|
||||
static const T GetDeadValue()
|
||||
{
|
||||
static const u64 value = dead_value;
|
||||
return (const T&)value;
|
||||
return (T&)value;
|
||||
}
|
||||
|
||||
void initialize()
|
||||
|
@ -45,11 +45,6 @@ public:
|
|||
owner = GetFreeValue();
|
||||
}
|
||||
|
||||
SMutexBase()
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
||||
void finalize()
|
||||
{
|
||||
owner = GetDeadValue();
|
||||
|
@ -66,9 +61,9 @@ public:
|
|||
{
|
||||
return SMR_ABORT;
|
||||
}
|
||||
T old = GetFreeValue();
|
||||
T old = reinterpret_cast<AT&>(owner).compare_and_swap(GetFreeValue(), tid);
|
||||
|
||||
if (!owner.compare_exchange_strong(old, tid))
|
||||
if (old != GetFreeValue())
|
||||
{
|
||||
if (old == tid)
|
||||
{
|
||||
|
@ -90,9 +85,9 @@ public:
|
|||
{
|
||||
return SMR_ABORT;
|
||||
}
|
||||
T old = tid;
|
||||
T old = reinterpret_cast<AT&>(owner).compare_and_swap(tid, to);
|
||||
|
||||
if (!owner.compare_exchange_strong(old, to))
|
||||
if (old != tid)
|
||||
{
|
||||
if (old == GetFreeValue())
|
||||
{
|
||||
|
@ -121,7 +116,7 @@ public:
|
|||
default: return res;
|
||||
}
|
||||
|
||||
if (wait != nullptr) wait();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
|
||||
if (timeout && counter++ > timeout)
|
||||
{
|
||||
|
@ -131,5 +126,4 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
typedef SMutexBase<u32>
|
||||
SMutex;
|
||||
typedef SMutexBase<u32> SMutex;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "Utilities/SMutex.h"
|
||||
static const volatile bool sq_no_wait = true;
|
||||
|
||||
template<typename T, u32 SQSize = 666>
|
||||
class SQueue
|
||||
|
@ -22,18 +22,18 @@ public:
|
|||
return SQSize;
|
||||
}
|
||||
|
||||
bool Push(const T& data)
|
||||
bool Push(const T& data, const volatile bool* do_exit)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (m_count >= SQSize)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
if (Emu.IsStopped() || (do_exit && *do_exit))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
SM_Sleep();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -49,18 +49,18 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
bool Pop(T& data)
|
||||
bool Pop(T& data, const volatile bool* do_exit)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (!m_count)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
if (Emu.IsStopped() || (do_exit && *do_exit))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
SM_Sleep();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -78,41 +78,24 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
u32 GetCount()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
return m_count;
|
||||
}
|
||||
|
||||
u32 GetCountUnsafe()
|
||||
{
|
||||
return m_count;
|
||||
}
|
||||
|
||||
bool IsEmpty()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
return !m_count;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
T& Peek(u32 pos = 0)
|
||||
bool Peek(T& data, const volatile bool* do_exit, u32 pos = 0)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
if (m_count <= pos)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
if (Emu.IsStopped() || (do_exit && *do_exit))
|
||||
{
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
|
||||
SM_Sleep();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -124,21 +107,7 @@ public:
|
|||
}
|
||||
}
|
||||
}
|
||||
return m_data[(m_pos + pos) % SQSize];
|
||||
}
|
||||
|
||||
T& PeekIfExist(u32 pos = 0)
|
||||
{
|
||||
static T def_value;
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
if (m_count <= pos)
|
||||
{
|
||||
return def_value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_data[(m_pos + pos) % SQSize];
|
||||
}
|
||||
data = m_data[(m_pos + pos) % SQSize];
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
|
|
@ -103,3 +103,34 @@ std::vector<std::string> fmt::rSplit(const std::string& source, const std::strin
|
|||
} while (true);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<std::string> fmt::split(const std::string& source, std::initializer_list<std::string> separators, bool is_skip_empty)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
|
||||
size_t cursor_begin = 0;
|
||||
|
||||
for (size_t cursor_end = 0; cursor_end < source.length(); ++cursor_end)
|
||||
{
|
||||
for (auto &separator : separators)
|
||||
{
|
||||
if (strncmp(source.c_str() + cursor_end, separator.c_str(), separator.length()) == 0)
|
||||
{
|
||||
std::string candidate = source.substr(cursor_begin, cursor_end - cursor_begin);
|
||||
if (!is_skip_empty || !candidate.empty())
|
||||
result.push_back(candidate);
|
||||
|
||||
cursor_begin = cursor_end + separator.length();
|
||||
cursor_end = cursor_begin - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cursor_begin != source.length())
|
||||
{
|
||||
result.push_back(source.substr(cursor_begin));
|
||||
}
|
||||
|
||||
return std::move(result);
|
||||
}
|
|
@ -192,4 +192,6 @@ namespace fmt{
|
|||
void Replace(std::string &str, const std::string &searchterm, const std::string& replaceterm);
|
||||
|
||||
std::vector<std::string> rSplit(const std::string& source, const std::string& delim);
|
||||
|
||||
std::vector<std::string> split(const std::string& source, std::initializer_list<std::string> separators, bool is_skip_empty = true);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "stdafx.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Log.h"
|
||||
#include "Thread.h"
|
||||
|
||||
|
@ -207,3 +208,61 @@ bool thread::joinable() const
|
|||
{
|
||||
return m_thr.joinable();
|
||||
}
|
||||
|
||||
bool waiter_map_t::is_stopped(u64 signal_id)
|
||||
{
|
||||
if (Emu.IsStopped())
|
||||
{
|
||||
LOG_WARNING(Log::HLE, "%s.waiter_op() aborted (signal_id=0x%llx)", m_name.c_str(), signal_id);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void waiter_map_t::waiter_reg_t::init()
|
||||
{
|
||||
if (thread) return;
|
||||
|
||||
thread = GetCurrentNamedThread();
|
||||
|
||||
std::lock_guard<std::mutex> lock(map.m_mutex);
|
||||
|
||||
// add waiter
|
||||
map.m_waiters.push_back({ signal_id, thread });
|
||||
}
|
||||
|
||||
waiter_map_t::waiter_reg_t::~waiter_reg_t()
|
||||
{
|
||||
if (!thread) return;
|
||||
|
||||
std::lock_guard<std::mutex> lock(map.m_mutex);
|
||||
|
||||
// remove waiter
|
||||
for (s64 i = map.m_waiters.size() - 1; i >= 0; i--)
|
||||
{
|
||||
if (map.m_waiters[i].signal_id == signal_id && map.m_waiters[i].thread == thread)
|
||||
{
|
||||
map.m_waiters.erase(map.m_waiters.begin() + i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LOG_ERROR(HLE, "%s(): waiter not found (signal_id=0x%llx, map='%s')", __FUNCTION__, signal_id, map.m_name.c_str());
|
||||
Emu.Pause();
|
||||
}
|
||||
|
||||
void waiter_map_t::notify(u64 signal_id)
|
||||
{
|
||||
if (!m_waiters.size()) return;
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
// find waiter and signal
|
||||
for (auto& v : m_waiters)
|
||||
{
|
||||
if (v.signal_id == signal_id)
|
||||
{
|
||||
v.thread->Notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,3 +70,106 @@ public:
|
|||
void join();
|
||||
bool joinable() const;
|
||||
};
|
||||
|
||||
class s_mutex_t
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
class s_shared_mutex_t
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
class s_cond_var_t
|
||||
{
|
||||
|
||||
//public:
|
||||
// s_cond_var_t();
|
||||
// ~s_cond_var_t();
|
||||
//
|
||||
// s_cond_var_t(s_cond_var_t& right) = delete;
|
||||
// s_cond_var_t& operator = (s_cond_var_t& right) = delete;
|
||||
//
|
||||
// void wait();
|
||||
// void wait_for();
|
||||
//
|
||||
// void notify();
|
||||
// void notify_all();
|
||||
};
|
||||
|
||||
class slw_mutex_t
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
class slw_recursive_mutex_t
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
class slw_shared_mutex_t
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
class waiter_map_t
|
||||
{
|
||||
// TODO: optimize (use custom lightweight readers-writer lock)
|
||||
std::mutex m_mutex;
|
||||
|
||||
struct waiter_t
|
||||
{
|
||||
u64 signal_id;
|
||||
NamedThreadBase* thread;
|
||||
};
|
||||
|
||||
std::vector<waiter_t> m_waiters;
|
||||
|
||||
std::string m_name;
|
||||
|
||||
struct waiter_reg_t
|
||||
{
|
||||
NamedThreadBase* thread;
|
||||
const u64 signal_id;
|
||||
waiter_map_t& map;
|
||||
|
||||
waiter_reg_t(waiter_map_t& map, u64 signal_id)
|
||||
: thread(nullptr)
|
||||
, signal_id(signal_id)
|
||||
, map(map)
|
||||
{
|
||||
}
|
||||
|
||||
~waiter_reg_t();
|
||||
|
||||
void init();
|
||||
};
|
||||
|
||||
bool is_stopped(u64 signal_id);
|
||||
|
||||
public:
|
||||
waiter_map_t(const char* name)
|
||||
: m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
// wait until waiter_func() returns true, signal_id is an arbitrary number
|
||||
template<typename WT> __forceinline void wait_op(u64 signal_id, const WT waiter_func)
|
||||
{
|
||||
// register waiter
|
||||
waiter_reg_t waiter(*this, signal_id);
|
||||
|
||||
// check condition or if emulator is stopped
|
||||
while (!waiter_func() && !is_stopped(signal_id))
|
||||
{
|
||||
// initialize waiter (only first time)
|
||||
waiter.init();
|
||||
// wait for 1 ms or until signal arrived
|
||||
waiter.thread->WaitForAnySignal(1);
|
||||
}
|
||||
}
|
||||
|
||||
// signal all threads waiting on waiter_op() with the same signal_id (signaling only hints those threads that corresponding conditions are *probably* met)
|
||||
void notify(u64 signal_id);
|
||||
};
|
||||
|
|
|
@ -21,6 +21,12 @@ std::wstring ConvertUTF8ToWString(const std::string &source) {
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define GET_API_ERROR GetLastError()
|
||||
#else
|
||||
#define GET_API_ERROR err
|
||||
#endif
|
||||
|
||||
bool getFileInfo(const char *path, FileInfo *fileInfo) {
|
||||
// TODO: Expand relative paths?
|
||||
fileInfo->fullName = path;
|
||||
|
@ -103,14 +109,15 @@ bool rMkpath(const std::string &path)
|
|||
bool rRmdir(const std::string &dir)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (!RemoveDirectory(ConvertUTF8ToWString(dir).c_str())) {
|
||||
LOG_ERROR(GENERAL, "Error deleting directory %s: %i", dir.c_str(), GetLastError());
|
||||
if (!RemoveDirectory(ConvertUTF8ToWString(dir).c_str()))
|
||||
#else
|
||||
if (int err = rmdir(dir.c_str()))
|
||||
#endif
|
||||
{
|
||||
LOG_ERROR(GENERAL, "Error deleting directory %s: %i", dir.c_str(), GET_API_ERROR);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
rmdir(dir.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
bool rRename(const std::string &from, const std::string &to)
|
||||
|
@ -137,17 +144,14 @@ bool rExists(const std::string &file)
|
|||
bool rRemoveFile(const std::string &file)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (!DeleteFile(ConvertUTF8ToWString(file).c_str())) {
|
||||
LOG_ERROR(GENERAL, "Error deleting %s: %i", file.c_str(), GetLastError());
|
||||
return false;
|
||||
}
|
||||
if (!DeleteFile(ConvertUTF8ToWString(file).c_str()))
|
||||
#else
|
||||
int err = unlink(file.c_str());
|
||||
if (err) {
|
||||
LOG_ERROR(GENERAL, "Error unlinking %s: %i", file.c_str(), err);
|
||||
if (int err = unlink(file.c_str()))
|
||||
#endif
|
||||
{
|
||||
LOG_ERROR(GENERAL, "Error deleting %s: %i", file.c_str(), GET_API_ERROR);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
2
asmjit
2
asmjit
|
@ -1 +1 @@
|
|||
Subproject commit 9ead0cfb4cb5eb1bcf8c12b4a1ea115e438c44fa
|
||||
Subproject commit 1318c9aff7137b30aec7dee2ababb2b313ae0f06
|
|
@ -0,0 +1,6 @@
|
|||
# Note: This folder has to exist. Once the User Account manager is implemented, make sure it creates this folder in case it's missing and delete this .gitignore file.
|
||||
|
||||
# Ignore everything in this directory
|
||||
*
|
||||
# Except this file
|
||||
!.gitignore
|
|
@ -0,0 +1 @@
|
|||
Subproject commit f55c17bc3395fa7fdbd997d751a55de5228ebd77
|
|
@ -0,0 +1,30 @@
|
|||
REM You need cmake and python to update the project files
|
||||
REM this script relies on CWD being the path that this script is in
|
||||
|
||||
cmake -G "Visual Studio 12 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF ../llvm
|
||||
|
||||
RD /S /Q cmake
|
||||
RD /S /Q CMakeFiles
|
||||
RD /S /Q projects
|
||||
RD /S /Q share
|
||||
RD /S /Q tools
|
||||
DEL ALL_BUILD.vcxproj
|
||||
DEL ALL_BUILD.vcxproj.filters
|
||||
DEL CMakeCache.txt
|
||||
DEL cmake_install.cmake
|
||||
DEL CPackConfig.cmake
|
||||
DEL CPackSourceConfig.cmake
|
||||
DEL DummyConfigureOutput
|
||||
DEL INSTALL.vcxproj
|
||||
DEL INSTALL.vcxproj.filters
|
||||
DEL LLVM.sdf
|
||||
DEL LLVM.sln
|
||||
DEL LLVMBuild.cmake
|
||||
DEL PACKAGE.vcxproj
|
||||
DEL PACKAGE.vcxproj.filters
|
||||
DEL ZERO_CHECK.vcxproj
|
||||
DEL ZERO_CHECK.vcxproj.filters
|
||||
DEL include\llvm\llvm_headers_do_not_build.vcxproj
|
||||
DEL include\llvm\llvm_headers_do_not_build.vcxproj.filters
|
||||
python make_paths_relative.py
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{8BC303AB-25BE-4276-8E57-73F171B2D672}</ProjectGuid>
|
||||
<Keyword>MakeFileProj</Keyword>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Makefile</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Makefile</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v120</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<NMakePreprocessorDefinitions>
|
||||
</NMakePreprocessorDefinitions>
|
||||
<NMakeBuildCommandLine>cmake -G "Visual Studio 12 2013 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF ../llvm
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Debug
|
||||
</NMakeBuildCommandLine>
|
||||
<NMakeReBuildCommandLine>cmake -G "Visual Studio 12 2013 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF ../llvm
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Debug
|
||||
</NMakeReBuildCommandLine>
|
||||
<NMakeCleanCommandLine>cmake -G "Visual Studio 12 2013 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF ../llvm
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Debug
|
||||
</NMakeCleanCommandLine>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<NMakePreprocessorDefinitions />
|
||||
<NMakeBuildCommandLine>cmake -G "Visual Studio 12 2013 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF ../llvm
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:build /p:Configuration=Release
|
||||
</NMakeBuildCommandLine>
|
||||
<NMakeReBuildCommandLine>cmake -G "Visual Studio 12 2013 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF ../llvm
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:rebuild /p:Configuration=Release
|
||||
</NMakeReBuildCommandLine>
|
||||
<NMakeCleanCommandLine>cmake -G "Visual Studio 12 2013 Win64" -DCMAKE_CONFIGURATION_TYPES="Debug;Release" -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF ../llvm
|
||||
msbuild.exe ALL_BUILD.vcxproj /t:clean /p:Configuration=Release
|
||||
</NMakeCleanCommandLine>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,164 @@
|
|||
import os
|
||||
import shutil
|
||||
import xml.etree.ElementTree as ET
|
||||
import re
|
||||
|
||||
RPCS3DIR = ""
|
||||
|
||||
cmake_dirs = ["CMakeFiles",]
|
||||
|
||||
cmake_files = ["INSTALL.vcxproj",
|
||||
"INSTALL.vcxproj.filters",
|
||||
"PACKAGE.vcxproj",
|
||||
"PACKAGE.vcxproj.filters",
|
||||
"cmake_install.cmake",
|
||||
]
|
||||
|
||||
vcxproj_files_blacklist = ["llvm_build.vcxproj","llvm_build.vcxproj.filters"]
|
||||
|
||||
vcxproj_files = ["lib\Analysis\LLVMAnalysis.vcxproj",
|
||||
"lib\Analysis\IPA\LLVMipa.vcxproj",
|
||||
"lib\AsmParser\LLVMAsmParser.vcxproj",
|
||||
"lib\Bitcode\Reader\LLVMBitReader.vcxproj",
|
||||
"lib\Bitcode\Writer\LLVMBitWriter.vcxproj",
|
||||
"lib\CodeGen\LLVMCodeGen.vcxproj",
|
||||
"lib\CodeGen\AsmPrinter\LLVMAsmPrinter.vcxproj",
|
||||
"lib\CodeGen\SelectionDAG\LLVMSelectionDAG.vcxproj",
|
||||
"lib\DebugInfo\LLVMDebugInfo.vcxproj",
|
||||
"lib\ExecutionEngine\LLVMExecutionEngine.vcxproj",
|
||||
"lib\ExecutionEngine\Interpreter\LLVMInterpreter.vcxproj",
|
||||
"lib\ExecutionEngine\JIT\LLVMJIT.vcxproj",
|
||||
"lib\ExecutionEngine\MCJIT\LLVMMCJIT.vcxproj",
|
||||
"lib\ExecutionEngine\RuntimeDyld\LLVMRuntimeDyld.vcxproj",
|
||||
"lib\IR\LLVMCore.vcxproj",
|
||||
"lib\IRReader\LLVMIRReader.vcxproj",
|
||||
"lib\LineEditor\LLVMLineEditor.vcxproj",
|
||||
"lib\Linker\LLVMLinker.vcxproj",
|
||||
"lib\LTO\LLVMLTO.vcxproj",
|
||||
"lib\MC\LLVMMC.vcxproj",
|
||||
"lib\MC\MCAnalysis\LLVMMCAnalysis.vcxproj",
|
||||
"lib\MC\MCDisassembler\LLVMMCDisassembler.vcxproj",
|
||||
"lib\MC\MCParser\LLVMMCParser.vcxproj",
|
||||
"lib\Object\LLVMObject.vcxproj",
|
||||
"lib\Option\LLVMOption.vcxproj",
|
||||
"lib\ProfileData\LLVMProfileData.vcxproj",
|
||||
"lib\Support\LLVMSupport.vcxproj",
|
||||
"lib\TableGen\LLVMTableGen.vcxproj",
|
||||
"lib\Target\LLVMTarget.vcxproj",
|
||||
"lib\Target\X86\LLVMX86CodeGen.vcxproj",
|
||||
"lib\Target\X86\X86CommonTableGen.vcxproj",
|
||||
"lib\Target\X86\AsmParser\LLVMX86AsmParser.vcxproj",
|
||||
"lib\Target\X86\Disassembler\LLVMX86Disassembler.vcxproj",
|
||||
"lib\Target\X86\InstPrinter\LLVMX86AsmPrinter.vcxproj",
|
||||
"lib\Target\X86\MCTargetDesc\LLVMX86Desc.vcxproj",
|
||||
"lib\Target\X86\TargetInfo\LLVMX86Info.vcxproj",
|
||||
"lib\Target\X86\Utils\LLVMX86Utils.vcxproj",
|
||||
"lib\Transforms\Hello\LLVMHello.vcxproj",
|
||||
"lib\Transforms\InstCombine\LLVMInstCombine.vcxproj",
|
||||
"lib\Transforms\Instrumentation\LLVMInstrumentation.vcxproj",
|
||||
"lib\Transforms\IPO\LLVMipo.vcxproj",
|
||||
"lib\Transforms\ObjCARC\LLVMObjCARCOpts.vcxproj",
|
||||
"lib\Transforms\Scalar\LLVMScalarOpts.vcxproj",
|
||||
"lib\Transforms\Utils\LLVMTransformUtils.vcxproj",
|
||||
"lib\Transforms\Vectorize\LLVMVectorize.vcxproj",
|
||||
"include\llvm\IR\intrinsics_gen.vcxproj",
|
||||
"utils\TableGen\llvm-tblgen.vcxproj",
|
||||
]
|
||||
|
||||
def get_parent_dir():
|
||||
path = os.getcwd()
|
||||
os.chdir("..")
|
||||
rpcs3_dir = os.getcwd()
|
||||
os.chdir(path)
|
||||
return rpcs3_dir
|
||||
|
||||
def rem_cmake_files(root_path):
|
||||
for root, dirs, files in os.walk(root_path):
|
||||
for directory in dirs:
|
||||
if directory in cmake_dirs:
|
||||
print("deleting: " + os.path.join(root,directory))
|
||||
shutil.rmtree(os.path.join(root,directory))
|
||||
dirs = [item for item in dirs if item not in cmake_dirs]
|
||||
for file in files:
|
||||
if file in cmake_files:
|
||||
print("deleting: " + os.path.join(root,file))
|
||||
os.remove(os.path.join(root,file))
|
||||
|
||||
def repl_cmake_copy(match):
|
||||
newtext = "copy /y "
|
||||
files = match.group(1)
|
||||
files = files.replace('/','\\')
|
||||
return newtext+files
|
||||
|
||||
def make_paths_relative(file):
|
||||
global vcxproj_files
|
||||
global vcxproj_files_blacklist
|
||||
this_vcxproj = os.path.relpath(file,os.getcwd())
|
||||
if this_vcxproj in vcxproj_files_blacklist:
|
||||
return
|
||||
if (file.find('.vcxproj')!=len(file)-8) and (file.find('.vcxproj.filters')!=len(file)-16):
|
||||
print('ERROR: File "'+file+'" is not vcxproj file')
|
||||
return
|
||||
proj_path = os.path.dirname(file)
|
||||
if proj_path[1] != ':':
|
||||
print('ERROR: Path "'+proj_path+'" is not in the Windows format')
|
||||
return
|
||||
#check if we expected this project file
|
||||
if file[-8:] == '.vcxproj':
|
||||
if this_vcxproj in vcxproj_files:
|
||||
vcxproj_files.remove(this_vcxproj)
|
||||
else:
|
||||
print('ERROR: unexpected vcxproj file: "' + this_vcxproj +'" please update the script')
|
||||
return
|
||||
|
||||
#open the file and text-replace the absolute paths
|
||||
with open(file,'r') as f:
|
||||
file_cont = f.read()
|
||||
rel_path = '$(ProjDir)'+os.path.relpath(RPCS3DIR,proj_path)
|
||||
file_cont = file_cont.replace(RPCS3DIR,rel_path)
|
||||
rpcs3_path_alt = RPCS3DIR.replace('\\','/')
|
||||
rel_path_alt = rel_path.replace('\\','/')
|
||||
file_cont = file_cont.replace(rpcs3_path_alt,rel_path_alt)
|
||||
|
||||
#interpret the XML to remove the cmake commands from the "Command" tags
|
||||
ET.register_namespace('','http://schemas.microsoft.com/developer/msbuild/2003')
|
||||
tree = ET.fromstring(file_cont)
|
||||
|
||||
for parent in tree.findall('.//{http://schemas.microsoft.com/developer/msbuild/2003}Command/..'):
|
||||
for element in parent.findall('{http://schemas.microsoft.com/developer/msbuild/2003}Command'):
|
||||
text = str(element.text)
|
||||
rgx = re.compile(r'[^\r\n<>]+cmake.exe["]?\s+-E copy_if_different([^\r\n]+)')
|
||||
text, num_rep = rgx.subn(repl_cmake_copy,text)
|
||||
rgx = re.compile(r'[^\r\n<>]+cmake.exe([^\r\n]*)')
|
||||
text, num_rep2 = rgx.subn(r'REM OMMITTED CMAKE COMMAND',text)
|
||||
num_rep += num_rep2
|
||||
rgx = re.compile(r'[^\r\n<>]+ml64.exe"?([^\r\n]*)')
|
||||
text, num_rep2 = rgx.subn(r'"$(VCInstallDir)bin\x86_amd64\ml64.exe" \1',text)
|
||||
num_rep += num_rep2
|
||||
#if (text.find('cmake') != -1) or (text.find('python') != -1):
|
||||
# parent.remove(element)
|
||||
if num_rep > 0:
|
||||
element.text = text
|
||||
|
||||
#re-create the XML and save the file
|
||||
file_cont = ET.tostring(tree,'utf-8')
|
||||
with open(file,'w') as f:
|
||||
f.write(file_cont)
|
||||
|
||||
|
||||
def iterate_proj_file(root_path):
|
||||
for root, dirs, files in os.walk(root_path):
|
||||
for file in files:
|
||||
if file.find('.vcxproj') != -1 :
|
||||
make_paths_relative(os.path.join(root,file))
|
||||
|
||||
def main_func():
|
||||
global RPCS3DIR
|
||||
RPCS3DIR = get_parent_dir()
|
||||
rem_cmake_files(os.getcwd())
|
||||
iterate_proj_file(os.getcwd())
|
||||
for a in vcxproj_files:
|
||||
print('ERROR: project file was not found "'+ a + '"')
|
||||
|
||||
if __name__ == "__main__":
|
||||
main_func()
|
120
rpcs3.sln
120
rpcs3.sln
|
@ -1,6 +1,6 @@
|
|||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.21005.1
|
||||
VisualStudioVersion = 12.0.31101.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rpcs3", "rpcs3\rpcs3.vcxproj", "{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
|
@ -21,6 +21,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rpcs3", "rpcs3\rpcs3.vcxpro
|
|||
{7047EE97-7F80-A70D-6147-BC11102DB6F4} = {7047EE97-7F80-A70D-6147-BC11102DB6F4}
|
||||
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D} = {87B42A9C-3F5C-53D7-9017-2B1CAE39457D}
|
||||
{6FCB55A5-563F-4039-1D79-1EB6ED8AAB82} = {6FCB55A5-563F-4039-1D79-1EB6ED8AAB82}
|
||||
{8BC303AB-25BE-4276-8E57-73F171B2D672} = {8BC303AB-25BE-4276-8E57-73F171B2D672}
|
||||
{949C6DB8-E638-6EC6-AB31-BCCFD1379E01} = {949C6DB8-E638-6EC6-AB31-BCCFD1379E01}
|
||||
{74827EBD-93DC-5110-BA95-3F2AB029B6B0} = {74827EBD-93DC-5110-BA95-3F2AB029B6B0}
|
||||
{46333DC3-B4A5-3DCC-E8BF-A3F20ADC56D2} = {46333DC3-B4A5-3DCC-E8BF-A3F20ADC56D2}
|
||||
|
@ -138,165 +139,281 @@ EndProject
|
|||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "asmjit", "asmjit", "{E2A982F2-4B1A-48B1-8D77-A17A589C58D7}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "emucore", "rpcs3\emucore.vcxproj", "{C4A10229-4712-4BD2-B63E-50D93C67A038}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{8BC303AB-25BE-4276-8E57-73F171B2D672} = {8BC303AB-25BE-4276-8E57-73F171B2D672}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "llvm", "llvm", "{C8068CE9-D626-4FEA-BEE7-893F06A25BF3}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "llvm_build", "llvm_build\llvm_build.vcxproj", "{8BC303AB-25BE-4276-8E57-73F171B2D672}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug - LLVM|x64 = Debug - LLVM|x64
|
||||
Debug - MemLeak|x64 = Debug - MemLeak|x64
|
||||
Debug|x64 = Debug|x64
|
||||
Release - LLVM|x64 = Release - LLVM|x64
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Debug - MemLeak|x64.ActiveCfg = Debug - MemLeak|x64
|
||||
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Debug - MemLeak|x64.Build.0 = Debug - MemLeak|x64
|
||||
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Debug|x64.Build.0 = Debug|x64
|
||||
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Release|x64.ActiveCfg = Release|x64
|
||||
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Release|x64.Build.0 = Release|x64
|
||||
{6FCB55A5-563F-4039-1D79-1EB6ED8AAB82}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{6FCB55A5-563F-4039-1D79-1EB6ED8AAB82}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{6FCB55A5-563F-4039-1D79-1EB6ED8AAB82}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{6FCB55A5-563F-4039-1D79-1EB6ED8AAB82}.Debug - MemLeak|x64.Build.0 = Debug|x64
|
||||
{6FCB55A5-563F-4039-1D79-1EB6ED8AAB82}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6FCB55A5-563F-4039-1D79-1EB6ED8AAB82}.Debug|x64.Build.0 = Debug|x64
|
||||
{6FCB55A5-563F-4039-1D79-1EB6ED8AAB82}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{6FCB55A5-563F-4039-1D79-1EB6ED8AAB82}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{6FCB55A5-563F-4039-1D79-1EB6ED8AAB82}.Release|x64.ActiveCfg = Release|x64
|
||||
{6FCB55A5-563F-4039-1D79-1EB6ED8AAB82}.Release|x64.Build.0 = Release|x64
|
||||
{7047EE97-7F80-A70D-6147-BC11102DB6F4}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{7047EE97-7F80-A70D-6147-BC11102DB6F4}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{7047EE97-7F80-A70D-6147-BC11102DB6F4}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{7047EE97-7F80-A70D-6147-BC11102DB6F4}.Debug - MemLeak|x64.Build.0 = Debug|x64
|
||||
{7047EE97-7F80-A70D-6147-BC11102DB6F4}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{7047EE97-7F80-A70D-6147-BC11102DB6F4}.Debug|x64.Build.0 = Debug|x64
|
||||
{7047EE97-7F80-A70D-6147-BC11102DB6F4}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{7047EE97-7F80-A70D-6147-BC11102DB6F4}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{7047EE97-7F80-A70D-6147-BC11102DB6F4}.Release|x64.ActiveCfg = Release|x64
|
||||
{7047EE97-7F80-A70D-6147-BC11102DB6F4}.Release|x64.Build.0 = Release|x64
|
||||
{3111D679-7796-23C4-BA0C-271F1145DA24}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{3111D679-7796-23C4-BA0C-271F1145DA24}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{3111D679-7796-23C4-BA0C-271F1145DA24}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{3111D679-7796-23C4-BA0C-271F1145DA24}.Debug - MemLeak|x64.Build.0 = Debug|x64
|
||||
{3111D679-7796-23C4-BA0C-271F1145DA24}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{3111D679-7796-23C4-BA0C-271F1145DA24}.Debug|x64.Build.0 = Debug|x64
|
||||
{3111D679-7796-23C4-BA0C-271F1145DA24}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{3111D679-7796-23C4-BA0C-271F1145DA24}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{3111D679-7796-23C4-BA0C-271F1145DA24}.Release|x64.ActiveCfg = Release|x64
|
||||
{3111D679-7796-23C4-BA0C-271F1145DA24}.Release|x64.Build.0 = Release|x64
|
||||
{067D9406-2A93-DACA-9449-93A2D356357D}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{067D9406-2A93-DACA-9449-93A2D356357D}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{067D9406-2A93-DACA-9449-93A2D356357D}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{067D9406-2A93-DACA-9449-93A2D356357D}.Debug - MemLeak|x64.Build.0 = Debug|x64
|
||||
{067D9406-2A93-DACA-9449-93A2D356357D}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{067D9406-2A93-DACA-9449-93A2D356357D}.Debug|x64.Build.0 = Debug|x64
|
||||
{067D9406-2A93-DACA-9449-93A2D356357D}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{067D9406-2A93-DACA-9449-93A2D356357D}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{067D9406-2A93-DACA-9449-93A2D356357D}.Release|x64.ActiveCfg = Release|x64
|
||||
{067D9406-2A93-DACA-9449-93A2D356357D}.Release|x64.Build.0 = Release|x64
|
||||
{9ED1866B-D4AE-3440-24E4-7A9475B163B2}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{9ED1866B-D4AE-3440-24E4-7A9475B163B2}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{9ED1866B-D4AE-3440-24E4-7A9475B163B2}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{9ED1866B-D4AE-3440-24E4-7A9475B163B2}.Debug - MemLeak|x64.Build.0 = Debug|x64
|
||||
{9ED1866B-D4AE-3440-24E4-7A9475B163B2}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{9ED1866B-D4AE-3440-24E4-7A9475B163B2}.Debug|x64.Build.0 = Debug|x64
|
||||
{9ED1866B-D4AE-3440-24E4-7A9475B163B2}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{9ED1866B-D4AE-3440-24E4-7A9475B163B2}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{9ED1866B-D4AE-3440-24E4-7A9475B163B2}.Release|x64.ActiveCfg = Release|x64
|
||||
{9ED1866B-D4AE-3440-24E4-7A9475B163B2}.Release|x64.Build.0 = Release|x64
|
||||
{99C9EB95-DB4C-1996-490E-5212EFBF07C3}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{99C9EB95-DB4C-1996-490E-5212EFBF07C3}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{99C9EB95-DB4C-1996-490E-5212EFBF07C3}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{99C9EB95-DB4C-1996-490E-5212EFBF07C3}.Debug - MemLeak|x64.Build.0 = Debug|x64
|
||||
{99C9EB95-DB4C-1996-490E-5212EFBF07C3}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{99C9EB95-DB4C-1996-490E-5212EFBF07C3}.Debug|x64.Build.0 = Debug|x64
|
||||
{99C9EB95-DB4C-1996-490E-5212EFBF07C3}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{99C9EB95-DB4C-1996-490E-5212EFBF07C3}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{99C9EB95-DB4C-1996-490E-5212EFBF07C3}.Release|x64.ActiveCfg = Release|x64
|
||||
{99C9EB95-DB4C-1996-490E-5212EFBF07C3}.Release|x64.Build.0 = Release|x64
|
||||
{6EDC3B79-D217-F11A-406F-F11D856493F9}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{6EDC3B79-D217-F11A-406F-F11D856493F9}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{6EDC3B79-D217-F11A-406F-F11D856493F9}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{6EDC3B79-D217-F11A-406F-F11D856493F9}.Debug - MemLeak|x64.Build.0 = Debug|x64
|
||||
{6EDC3B79-D217-F11A-406F-F11D856493F9}.Debug - MemLeak|x64.Deploy.0 = Debug|x64
|
||||
{6EDC3B79-D217-F11A-406F-F11D856493F9}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6EDC3B79-D217-F11A-406F-F11D856493F9}.Debug|x64.Build.0 = Debug|x64
|
||||
{6EDC3B79-D217-F11A-406F-F11D856493F9}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{6EDC3B79-D217-F11A-406F-F11D856493F9}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{6EDC3B79-D217-F11A-406F-F11D856493F9}.Release|x64.ActiveCfg = Release|x64
|
||||
{6EDC3B79-D217-F11A-406F-F11D856493F9}.Release|x64.Build.0 = Release|x64
|
||||
{A9AC9CF5-8E6C-0BA2-0769-6E42EDB88E25}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{A9AC9CF5-8E6C-0BA2-0769-6E42EDB88E25}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{A9AC9CF5-8E6C-0BA2-0769-6E42EDB88E25}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{A9AC9CF5-8E6C-0BA2-0769-6E42EDB88E25}.Debug - MemLeak|x64.Build.0 = Debug|x64
|
||||
{A9AC9CF5-8E6C-0BA2-0769-6E42EDB88E25}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{A9AC9CF5-8E6C-0BA2-0769-6E42EDB88E25}.Debug|x64.Build.0 = Debug|x64
|
||||
{A9AC9CF5-8E6C-0BA2-0769-6E42EDB88E25}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{A9AC9CF5-8E6C-0BA2-0769-6E42EDB88E25}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{A9AC9CF5-8E6C-0BA2-0769-6E42EDB88E25}.Release|x64.ActiveCfg = Release|x64
|
||||
{A9AC9CF5-8E6C-0BA2-0769-6E42EDB88E25}.Release|x64.Build.0 = Release|x64
|
||||
{CD478F02-7550-58A5-E085-CE4BC0C0AD23}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{CD478F02-7550-58A5-E085-CE4BC0C0AD23}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{CD478F02-7550-58A5-E085-CE4BC0C0AD23}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{CD478F02-7550-58A5-E085-CE4BC0C0AD23}.Debug - MemLeak|x64.Build.0 = Debug|x64
|
||||
{CD478F02-7550-58A5-E085-CE4BC0C0AD23}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{CD478F02-7550-58A5-E085-CE4BC0C0AD23}.Debug|x64.Build.0 = Debug|x64
|
||||
{CD478F02-7550-58A5-E085-CE4BC0C0AD23}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{CD478F02-7550-58A5-E085-CE4BC0C0AD23}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{CD478F02-7550-58A5-E085-CE4BC0C0AD23}.Release|x64.ActiveCfg = Release|x64
|
||||
{CD478F02-7550-58A5-E085-CE4BC0C0AD23}.Release|x64.Build.0 = Release|x64
|
||||
{22B14659-C5B6-B775-868D-A49198FEAD4A}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{22B14659-C5B6-B775-868D-A49198FEAD4A}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{22B14659-C5B6-B775-868D-A49198FEAD4A}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{22B14659-C5B6-B775-868D-A49198FEAD4A}.Debug - MemLeak|x64.Build.0 = Debug|x64
|
||||
{22B14659-C5B6-B775-868D-A49198FEAD4A}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{22B14659-C5B6-B775-868D-A49198FEAD4A}.Debug|x64.Build.0 = Debug|x64
|
||||
{22B14659-C5B6-B775-868D-A49198FEAD4A}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{22B14659-C5B6-B775-868D-A49198FEAD4A}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{22B14659-C5B6-B775-868D-A49198FEAD4A}.Release|x64.ActiveCfg = Release|x64
|
||||
{22B14659-C5B6-B775-868D-A49198FEAD4A}.Release|x64.Build.0 = Release|x64
|
||||
{FAF0CB93-F7CE-A6B8-8342-19CE99BAF774}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{FAF0CB93-F7CE-A6B8-8342-19CE99BAF774}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{FAF0CB93-F7CE-A6B8-8342-19CE99BAF774}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{FAF0CB93-F7CE-A6B8-8342-19CE99BAF774}.Debug - MemLeak|x64.Build.0 = Debug|x64
|
||||
{FAF0CB93-F7CE-A6B8-8342-19CE99BAF774}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{FAF0CB93-F7CE-A6B8-8342-19CE99BAF774}.Debug|x64.Build.0 = Debug|x64
|
||||
{FAF0CB93-F7CE-A6B8-8342-19CE99BAF774}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{FAF0CB93-F7CE-A6B8-8342-19CE99BAF774}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{FAF0CB93-F7CE-A6B8-8342-19CE99BAF774}.Release|x64.ActiveCfg = Release|x64
|
||||
{FAF0CB93-F7CE-A6B8-8342-19CE99BAF774}.Release|x64.Build.0 = Release|x64
|
||||
{46333DC3-B4A5-3DCC-E8BF-A3F20ADC56D2}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{46333DC3-B4A5-3DCC-E8BF-A3F20ADC56D2}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{46333DC3-B4A5-3DCC-E8BF-A3F20ADC56D2}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{46333DC3-B4A5-3DCC-E8BF-A3F20ADC56D2}.Debug - MemLeak|x64.Build.0 = Debug|x64
|
||||
{46333DC3-B4A5-3DCC-E8BF-A3F20ADC56D2}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{46333DC3-B4A5-3DCC-E8BF-A3F20ADC56D2}.Debug|x64.Build.0 = Debug|x64
|
||||
{46333DC3-B4A5-3DCC-E8BF-A3F20ADC56D2}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{46333DC3-B4A5-3DCC-E8BF-A3F20ADC56D2}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{46333DC3-B4A5-3DCC-E8BF-A3F20ADC56D2}.Release|x64.ActiveCfg = Release|x64
|
||||
{46333DC3-B4A5-3DCC-E8BF-A3F20ADC56D2}.Release|x64.Build.0 = Release|x64
|
||||
{5C363C34-4741-7036-861C-2E2279CF552E}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{5C363C34-4741-7036-861C-2E2279CF552E}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{5C363C34-4741-7036-861C-2E2279CF552E}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{5C363C34-4741-7036-861C-2E2279CF552E}.Debug - MemLeak|x64.Build.0 = Debug|x64
|
||||
{5C363C34-4741-7036-861C-2E2279CF552E}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{5C363C34-4741-7036-861C-2E2279CF552E}.Debug|x64.Build.0 = Debug|x64
|
||||
{5C363C34-4741-7036-861C-2E2279CF552E}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{5C363C34-4741-7036-861C-2E2279CF552E}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{5C363C34-4741-7036-861C-2E2279CF552E}.Release|x64.ActiveCfg = Release|x64
|
||||
{5C363C34-4741-7036-861C-2E2279CF552E}.Release|x64.Build.0 = Release|x64
|
||||
{76169FE8-0814-4F36-6409-699EF1A23001}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{76169FE8-0814-4F36-6409-699EF1A23001}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{76169FE8-0814-4F36-6409-699EF1A23001}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{76169FE8-0814-4F36-6409-699EF1A23001}.Debug - MemLeak|x64.Build.0 = Debug|x64
|
||||
{76169FE8-0814-4F36-6409-699EF1A23001}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{76169FE8-0814-4F36-6409-699EF1A23001}.Debug|x64.Build.0 = Debug|x64
|
||||
{76169FE8-0814-4F36-6409-699EF1A23001}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{76169FE8-0814-4F36-6409-699EF1A23001}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{76169FE8-0814-4F36-6409-699EF1A23001}.Release|x64.ActiveCfg = Release|x64
|
||||
{76169FE8-0814-4F36-6409-699EF1A23001}.Release|x64.Build.0 = Release|x64
|
||||
{949C6DB8-E638-6EC6-AB31-BCCFD1379E01}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{949C6DB8-E638-6EC6-AB31-BCCFD1379E01}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{949C6DB8-E638-6EC6-AB31-BCCFD1379E01}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{949C6DB8-E638-6EC6-AB31-BCCFD1379E01}.Debug - MemLeak|x64.Build.0 = Debug|x64
|
||||
{949C6DB8-E638-6EC6-AB31-BCCFD1379E01}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{949C6DB8-E638-6EC6-AB31-BCCFD1379E01}.Debug|x64.Build.0 = Debug|x64
|
||||
{949C6DB8-E638-6EC6-AB31-BCCFD1379E01}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{949C6DB8-E638-6EC6-AB31-BCCFD1379E01}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{949C6DB8-E638-6EC6-AB31-BCCFD1379E01}.Release|x64.ActiveCfg = Release|x64
|
||||
{949C6DB8-E638-6EC6-AB31-BCCFD1379E01}.Release|x64.Build.0 = Release|x64
|
||||
{B87216CD-6C64-1DB0-D900-BC6E745C1DF9}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{B87216CD-6C64-1DB0-D900-BC6E745C1DF9}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{B87216CD-6C64-1DB0-D900-BC6E745C1DF9}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{B87216CD-6C64-1DB0-D900-BC6E745C1DF9}.Debug - MemLeak|x64.Build.0 = Debug|x64
|
||||
{B87216CD-6C64-1DB0-D900-BC6E745C1DF9}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{B87216CD-6C64-1DB0-D900-BC6E745C1DF9}.Debug|x64.Build.0 = Debug|x64
|
||||
{B87216CD-6C64-1DB0-D900-BC6E745C1DF9}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{B87216CD-6C64-1DB0-D900-BC6E745C1DF9}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{B87216CD-6C64-1DB0-D900-BC6E745C1DF9}.Release|x64.ActiveCfg = Release|x64
|
||||
{B87216CD-6C64-1DB0-D900-BC6E745C1DF9}.Release|x64.Build.0 = Release|x64
|
||||
{AFF2C68B-B867-DD50-6AC5-74B09D41F8EA}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{AFF2C68B-B867-DD50-6AC5-74B09D41F8EA}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{AFF2C68B-B867-DD50-6AC5-74B09D41F8EA}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{AFF2C68B-B867-DD50-6AC5-74B09D41F8EA}.Debug - MemLeak|x64.Build.0 = Debug|x64
|
||||
{AFF2C68B-B867-DD50-6AC5-74B09D41F8EA}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{AFF2C68B-B867-DD50-6AC5-74B09D41F8EA}.Debug|x64.Build.0 = Debug|x64
|
||||
{AFF2C68B-B867-DD50-6AC5-74B09D41F8EA}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{AFF2C68B-B867-DD50-6AC5-74B09D41F8EA}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{AFF2C68B-B867-DD50-6AC5-74B09D41F8EA}.Release|x64.ActiveCfg = Release|x64
|
||||
{AFF2C68B-B867-DD50-6AC5-74B09D41F8EA}.Release|x64.Build.0 = Release|x64
|
||||
{6FDC76D5-CB44-B9F8-5EF6-C59B020719DF}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{6FDC76D5-CB44-B9F8-5EF6-C59B020719DF}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{6FDC76D5-CB44-B9F8-5EF6-C59B020719DF}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{6FDC76D5-CB44-B9F8-5EF6-C59B020719DF}.Debug - MemLeak|x64.Build.0 = Debug|x64
|
||||
{6FDC76D5-CB44-B9F8-5EF6-C59B020719DF}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{6FDC76D5-CB44-B9F8-5EF6-C59B020719DF}.Debug|x64.Build.0 = Debug|x64
|
||||
{6FDC76D5-CB44-B9F8-5EF6-C59B020719DF}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{6FDC76D5-CB44-B9F8-5EF6-C59B020719DF}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{6FDC76D5-CB44-B9F8-5EF6-C59B020719DF}.Release|x64.ActiveCfg = Release|x64
|
||||
{6FDC76D5-CB44-B9F8-5EF6-C59B020719DF}.Release|x64.Build.0 = Release|x64
|
||||
{8BECCA95-C7D7-CFF8-FDB1-4950E9F8E8E6}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{8BECCA95-C7D7-CFF8-FDB1-4950E9F8E8E6}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{8BECCA95-C7D7-CFF8-FDB1-4950E9F8E8E6}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{8BECCA95-C7D7-CFF8-FDB1-4950E9F8E8E6}.Debug - MemLeak|x64.Build.0 = Debug|x64
|
||||
{8BECCA95-C7D7-CFF8-FDB1-4950E9F8E8E6}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{8BECCA95-C7D7-CFF8-FDB1-4950E9F8E8E6}.Debug|x64.Build.0 = Debug|x64
|
||||
{8BECCA95-C7D7-CFF8-FDB1-4950E9F8E8E6}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{8BECCA95-C7D7-CFF8-FDB1-4950E9F8E8E6}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{8BECCA95-C7D7-CFF8-FDB1-4950E9F8E8E6}.Release|x64.ActiveCfg = Release|x64
|
||||
{8BECCA95-C7D7-CFF8-FDB1-4950E9F8E8E6}.Release|x64.Build.0 = Release|x64
|
||||
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}.Debug - MemLeak|x64.Build.0 = Debug|x64
|
||||
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}.Debug|x64.Build.0 = Debug|x64
|
||||
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}.Release|x64.ActiveCfg = Release|x64
|
||||
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}.Release|x64.Build.0 = Release|x64
|
||||
{23E1C437-A951-5943-8639-A17F3CF2E606}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{23E1C437-A951-5943-8639-A17F3CF2E606}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{23E1C437-A951-5943-8639-A17F3CF2E606}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{23E1C437-A951-5943-8639-A17F3CF2E606}.Debug - MemLeak|x64.Build.0 = Debug|x64
|
||||
{23E1C437-A951-5943-8639-A17F3CF2E606}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{23E1C437-A951-5943-8639-A17F3CF2E606}.Debug|x64.Build.0 = Debug|x64
|
||||
{23E1C437-A951-5943-8639-A17F3CF2E606}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{23E1C437-A951-5943-8639-A17F3CF2E606}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{23E1C437-A951-5943-8639-A17F3CF2E606}.Release|x64.ActiveCfg = Release|x64
|
||||
{23E1C437-A951-5943-8639-A17F3CF2E606}.Release|x64.Build.0 = Release|x64
|
||||
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Debug - MemLeak|x64.Build.0 = Debug|x64
|
||||
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Debug|x64.Build.0 = Debug|x64
|
||||
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Release|x64.ActiveCfg = Release|x64
|
||||
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Release|x64.Build.0 = Release|x64
|
||||
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug - MemLeak|x64.Build.0 = Debug|x64
|
||||
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug|x64.Build.0 = Debug|x64
|
||||
{AC40FF01-426E-4838-A317-66354CEFAE88}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{AC40FF01-426E-4838-A317-66354CEFAE88}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{AC40FF01-426E-4838-A317-66354CEFAE88}.Release|x64.ActiveCfg = Release|x64
|
||||
{AC40FF01-426E-4838-A317-66354CEFAE88}.Release|x64.Build.0 = Release|x64
|
||||
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Debug - LLVM|x64.ActiveCfg = Debug - LLVM|x64
|
||||
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Debug - LLVM|x64.Build.0 = Debug - LLVM|x64
|
||||
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Debug - MemLeak|x64.ActiveCfg = Debug - MemLeak|x64
|
||||
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Debug - MemLeak|x64.Build.0 = Debug - MemLeak|x64
|
||||
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Debug|x64.Build.0 = Debug|x64
|
||||
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Release - LLVM|x64.ActiveCfg = Release - LLVM|x64
|
||||
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Release - LLVM|x64.Build.0 = Release - LLVM|x64
|
||||
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Release|x64.ActiveCfg = Release|x64
|
||||
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Release|x64.Build.0 = Release|x64
|
||||
{8BC303AB-25BE-4276-8E57-73F171B2D672}.Debug - LLVM|x64.ActiveCfg = Debug|x64
|
||||
{8BC303AB-25BE-4276-8E57-73F171B2D672}.Debug - LLVM|x64.Build.0 = Debug|x64
|
||||
{8BC303AB-25BE-4276-8E57-73F171B2D672}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
|
||||
{8BC303AB-25BE-4276-8E57-73F171B2D672}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{8BC303AB-25BE-4276-8E57-73F171B2D672}.Release - LLVM|x64.ActiveCfg = Release|x64
|
||||
{8BC303AB-25BE-4276-8E57-73F171B2D672}.Release - LLVM|x64.Build.0 = Release|x64
|
||||
{8BC303AB-25BE-4276-8E57-73F171B2D672}.Release|x64.ActiveCfg = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -325,5 +442,6 @@ Global
|
|||
{23E1C437-A951-5943-8639-A17F3CF2E606} = {5812E712-6213-4372-B095-9EB9BAA1F2DF}
|
||||
{74827EBD-93DC-5110-BA95-3F2AB029B6B0} = {5812E712-6213-4372-B095-9EB9BAA1F2DF}
|
||||
{AC40FF01-426E-4838-A317-66354CEFAE88} = {E2A982F2-4B1A-48B1-8D77-A17A589C58D7}
|
||||
{8BC303AB-25BE-4276-8E57-73F171B2D672} = {C8068CE9-D626-4FEA-BEE7-893F06A25BF3}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
|
@ -55,6 +55,7 @@ find_package(GLEW REQUIRED)
|
|||
find_package(OpenGL REQUIRED)
|
||||
find_package(ZLIB REQUIRED)
|
||||
find_package(OpenAL REQUIRED)
|
||||
find_package(LLVM REQUIRED CONFIG)
|
||||
|
||||
include("${wxWidgets_USE_FILE}")
|
||||
|
||||
|
@ -69,6 +70,7 @@ endif()
|
|||
include_directories(
|
||||
${wxWidgets_INCLUDE_DIRS}
|
||||
${OPENAL_INCLUDE_DIR}
|
||||
${LLVM_INCLUDE_DIRS}
|
||||
"${RPCS3_SRC_DIR}/../ffmpeg/${PLATFORM_ARCH}/include"
|
||||
"${RPCS3_SRC_DIR}"
|
||||
"${RPCS3_SRC_DIR}/Loader"
|
||||
|
@ -77,6 +79,14 @@ ${OPENAL_INCLUDE_DIR}
|
|||
"${RPCS3_SRC_DIR}/../asmjit/src/asmjit"
|
||||
)
|
||||
|
||||
add_definitions(${LLVM_DEFINITIONS})
|
||||
add_definitions(-DLLVM_AVAILABLE)
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
llvm_map_components_to_libnames(LLVM_LIBS jit vectorize x86codegen x86disassembler)
|
||||
else()
|
||||
llvm_map_components_to_libnames(LLVM_LIBS jit vectorize x86codegen x86disassembler mcdisassembler)
|
||||
endif()
|
||||
|
||||
link_directories("${RPCS3_SRC_DIR}/../ffmpeg/${PLATFORM_ARCH}/lib")
|
||||
|
||||
get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
|
||||
|
@ -97,10 +107,13 @@ RPCS3_SRC
|
|||
"${RPCS3_SRC_DIR}/../Utilities/*"
|
||||
)
|
||||
|
||||
list(REMOVE_ITEM RPCS3_SRC ${RPCS3_SRC_DIR}/../Utilities/simpleini/ConvertUTF.c)
|
||||
set_source_files_properties(${RPCS3_SRC_DIR}/Emu/Cell/PPULLVMRecompiler.cpp PROPERTIES COMPILE_FLAGS -fno-rtti)
|
||||
|
||||
add_executable(rpcs3 ${RPCS3_SRC})
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_CURRENT_BINARY_DIR}/../asmjit/") #hack because the asmjit cmake file force fno exceptions
|
||||
target_link_libraries(rpcs3 asmjit.a ${wxWidgets_LIBRARIES} ${OPENAL_LIBRARY} ${GLEW_LIBRARY} ${OPENGL_LIBRARIES} libavformat.a libavcodec.a libavutil.a libswresample.a libswscale.a ${ZLIB_LIBRARIES})
|
||||
target_link_libraries(rpcs3 asmjit.a ${wxWidgets_LIBRARIES} ${OPENAL_LIBRARY} ${GLEW_LIBRARY} ${OPENGL_LIBRARIES} libavformat.a libavcodec.a libavutil.a libswresample.a libswscale.a ${ZLIB_LIBRARIES} ${LLVM_LIBS})
|
||||
|
||||
set_target_properties(rpcs3 PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${RPCS3_SRC_DIR}/stdafx.h")
|
||||
cotire(rpcs3)
|
||||
|
|
|
@ -0,0 +1,548 @@
|
|||
// Copyright 2007,2008,2010 Segher Boessenkool <segher@kernel.crashing.org>
|
||||
// Licensed under the terms of the GNU GPL, version 2
|
||||
// http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "utils.h"
|
||||
|
||||
void bn_print(char *name, u8 *a, u32 n)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
printf("%s = ", name);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
printf("%02x", a[i]);
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void bn_zero(u8 *d, u32 n)
|
||||
{
|
||||
memset(d, 0, n);
|
||||
}
|
||||
void bn_copy(u8 *d, u8 *a, u32 n)
|
||||
{
|
||||
memcpy(d, a, n);
|
||||
}
|
||||
|
||||
int bn_compare(u8 *a, u8 *b, u32 n)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
if (a[i] < b[i])
|
||||
return -1;
|
||||
if (a[i] > b[i])
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u8 bn_add_1(u8 *d, u8 *a, u8 *b, u32 n)
|
||||
{
|
||||
u32 i;
|
||||
u32 dig;
|
||||
u8 c;
|
||||
|
||||
c = 0;
|
||||
for (i = n - 1; i < n; i--) {
|
||||
dig = a[i] + b[i] + c;
|
||||
c = dig >> 8;
|
||||
d[i] = dig;
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static u8 bn_sub_1(u8 *d, u8 *a, u8 *b, u32 n)
|
||||
{
|
||||
u32 i;
|
||||
u32 dig;
|
||||
u8 c;
|
||||
|
||||
c = 1;
|
||||
for (i = n - 1; i < n; i--) {
|
||||
dig = a[i] + 255 - b[i] + c;
|
||||
c = dig >> 8;
|
||||
d[i] = dig;
|
||||
}
|
||||
|
||||
return 1 - c;
|
||||
}
|
||||
|
||||
void bn_reduce(u8 *d, u8 *N, u32 n)
|
||||
{
|
||||
if (bn_compare(d, N, n) >= 0)
|
||||
bn_sub_1(d, d, N, n);
|
||||
}
|
||||
|
||||
void bn_add(u8 *d, u8 *a, u8 *b, u8 *N, u32 n)
|
||||
{
|
||||
if (bn_add_1(d, a, b, n))
|
||||
bn_sub_1(d, d, N, n);
|
||||
|
||||
bn_reduce(d, N, n);
|
||||
}
|
||||
|
||||
void bn_sub(u8 *d, u8 *a, u8 *b, u8 *N, u32 n)
|
||||
{
|
||||
if (bn_sub_1(d, a, b, n))
|
||||
bn_add_1(d, d, N, n);
|
||||
}
|
||||
|
||||
static const u8 inv256[0x80] = {
|
||||
0x01, 0xab, 0xcd, 0xb7, 0x39, 0xa3, 0xc5, 0xef,
|
||||
0xf1, 0x1b, 0x3d, 0xa7, 0x29, 0x13, 0x35, 0xdf,
|
||||
0xe1, 0x8b, 0xad, 0x97, 0x19, 0x83, 0xa5, 0xcf,
|
||||
0xd1, 0xfb, 0x1d, 0x87, 0x09, 0xf3, 0x15, 0xbf,
|
||||
0xc1, 0x6b, 0x8d, 0x77, 0xf9, 0x63, 0x85, 0xaf,
|
||||
0xb1, 0xdb, 0xfd, 0x67, 0xe9, 0xd3, 0xf5, 0x9f,
|
||||
0xa1, 0x4b, 0x6d, 0x57, 0xd9, 0x43, 0x65, 0x8f,
|
||||
0x91, 0xbb, 0xdd, 0x47, 0xc9, 0xb3, 0xd5, 0x7f,
|
||||
0x81, 0x2b, 0x4d, 0x37, 0xb9, 0x23, 0x45, 0x6f,
|
||||
0x71, 0x9b, 0xbd, 0x27, 0xa9, 0x93, 0xb5, 0x5f,
|
||||
0x61, 0x0b, 0x2d, 0x17, 0x99, 0x03, 0x25, 0x4f,
|
||||
0x51, 0x7b, 0x9d, 0x07, 0x89, 0x73, 0x95, 0x3f,
|
||||
0x41, 0xeb, 0x0d, 0xf7, 0x79, 0xe3, 0x05, 0x2f,
|
||||
0x31, 0x5b, 0x7d, 0xe7, 0x69, 0x53, 0x75, 0x1f,
|
||||
0x21, 0xcb, 0xed, 0xd7, 0x59, 0xc3, 0xe5, 0x0f,
|
||||
0x11, 0x3b, 0x5d, 0xc7, 0x49, 0x33, 0x55, 0xff,
|
||||
};
|
||||
|
||||
static void bn_mon_muladd_dig(u8 *d, u8 *a, u8 b, u8 *N, u32 n)
|
||||
{
|
||||
u32 dig;
|
||||
u32 i;
|
||||
|
||||
u8 z = -(d[n-1] + a[n-1]*b) * inv256[N[n-1]/2];
|
||||
|
||||
dig = d[n-1] + a[n-1]*b + N[n-1]*z;
|
||||
dig >>= 8;
|
||||
|
||||
for (i = n - 2; i < n; i--) {
|
||||
dig += d[i] + a[i]*b + N[i]*z;
|
||||
d[i+1] = dig;
|
||||
dig >>= 8;
|
||||
}
|
||||
|
||||
d[0] = dig;
|
||||
dig >>= 8;
|
||||
|
||||
if (dig)
|
||||
bn_sub_1(d, d, N, n);
|
||||
|
||||
bn_reduce(d, N, n);
|
||||
}
|
||||
|
||||
void bn_mon_mul(u8 *d, u8 *a, u8 *b, u8 *N, u32 n)
|
||||
{
|
||||
u8 t[512];
|
||||
u32 i;
|
||||
|
||||
bn_zero(t, n);
|
||||
|
||||
for (i = n - 1; i < n; i--)
|
||||
bn_mon_muladd_dig(t, a, b[i], N, n);
|
||||
|
||||
bn_copy(d, t, n);
|
||||
}
|
||||
|
||||
void bn_to_mon(u8 *d, u8 *N, u32 n)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < 8*n; i++)
|
||||
bn_add(d, d, d, N, n);
|
||||
}
|
||||
|
||||
void bn_from_mon(u8 *d, u8 *N, u32 n)
|
||||
{
|
||||
u8 t[512];
|
||||
|
||||
bn_zero(t, n);
|
||||
t[n-1] = 1;
|
||||
bn_mon_mul(d, d, t, N, n);
|
||||
}
|
||||
|
||||
static void bn_mon_exp(u8 *d, u8 *a, u8 *N, u32 n, u8 *e, u32 en)
|
||||
{
|
||||
u8 t[512];
|
||||
u32 i;
|
||||
u8 mask;
|
||||
|
||||
bn_zero(d, n);
|
||||
d[n-1] = 1;
|
||||
bn_to_mon(d, N, n);
|
||||
|
||||
for (i = 0; i < en; i++)
|
||||
for (mask = 0x80; mask != 0; mask >>= 1) {
|
||||
bn_mon_mul(t, d, d, N, n);
|
||||
if ((e[i] & mask) != 0)
|
||||
bn_mon_mul(d, t, a, N, n);
|
||||
else
|
||||
bn_copy(d, t, n);
|
||||
}
|
||||
}
|
||||
|
||||
void bn_mon_inv(u8 *d, u8 *a, u8 *N, u32 n)
|
||||
{
|
||||
u8 t[512], s[512];
|
||||
|
||||
bn_zero(s, n);
|
||||
s[n-1] = 2;
|
||||
bn_sub_1(t, N, s, n);
|
||||
bn_mon_exp(d, a, N, n, t, n);
|
||||
}
|
||||
|
||||
void bn_copy(u8 *d, u8 *a, u32 n);
|
||||
int bn_compare(u8 *a, u8 *b, u32 n);
|
||||
void bn_reduce(u8 *d, u8 *N, u32 n);
|
||||
void bn_add(u8 *d, u8 *a, u8 *b, u8 *N, u32 n);
|
||||
void bn_sub(u8 *d, u8 *a, u8 *b, u8 *N, u32 n);
|
||||
void bn_to_mon(u8 *d, u8 *N, u32 n);
|
||||
void bn_from_mon(u8 *d, u8 *N, u32 n);
|
||||
void bn_mon_mul(u8 *d, u8 *a, u8 *b, u8 *N, u32 n);
|
||||
void bn_mon_inv(u8 *d, u8 *a, u8 *N, u32 n);
|
||||
|
||||
struct point {
|
||||
u8 x[20];
|
||||
u8 y[20];
|
||||
};
|
||||
|
||||
static u8 ec_p[20];
|
||||
static u8 ec_a[20]; // mon
|
||||
static u8 ec_b[20]; // mon
|
||||
static u8 ec_N[21];
|
||||
static struct point ec_G; // mon
|
||||
static struct point ec_Q; // mon
|
||||
static u8 ec_k[21];
|
||||
|
||||
static void elt_copy(u8 *d, u8 *a)
|
||||
{
|
||||
memcpy(d, a, 20);
|
||||
}
|
||||
|
||||
static void elt_zero(u8 *d)
|
||||
{
|
||||
memset(d, 0, 20);
|
||||
}
|
||||
|
||||
static int elt_is_zero(u8 *d)
|
||||
{
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < 20; i++)
|
||||
if (d[i] != 0)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void elt_add(u8 *d, u8 *a, u8 *b)
|
||||
{
|
||||
bn_add(d, a, b, ec_p, 20);
|
||||
}
|
||||
|
||||
static void elt_sub(u8 *d, u8 *a, u8 *b)
|
||||
{
|
||||
bn_sub(d, a, b, ec_p, 20);
|
||||
}
|
||||
|
||||
static void elt_mul(u8 *d, u8 *a, u8 *b)
|
||||
{
|
||||
bn_mon_mul(d, a, b, ec_p, 20);
|
||||
}
|
||||
|
||||
static void elt_square(u8 *d, u8 *a)
|
||||
{
|
||||
elt_mul(d, a, a);
|
||||
}
|
||||
|
||||
static void elt_inv(u8 *d, u8 *a)
|
||||
{
|
||||
u8 s[20];
|
||||
elt_copy(s, a);
|
||||
bn_mon_inv(d, s, ec_p, 20);
|
||||
}
|
||||
|
||||
static void point_to_mon(struct point *p)
|
||||
{
|
||||
bn_to_mon(p->x, ec_p, 20);
|
||||
bn_to_mon(p->y, ec_p, 20);
|
||||
}
|
||||
|
||||
static void point_from_mon(struct point *p)
|
||||
{
|
||||
bn_from_mon(p->x, ec_p, 20);
|
||||
bn_from_mon(p->y, ec_p, 20);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int point_is_on_curve(u8 *p)
|
||||
{
|
||||
u8 s[20], t[20];
|
||||
u8 *x, *y;
|
||||
|
||||
x = p;
|
||||
y = p + 20;
|
||||
|
||||
elt_square(t, x);
|
||||
elt_mul(s, t, x);
|
||||
|
||||
elt_mul(t, x, ec_a);
|
||||
elt_add(s, s, t);
|
||||
|
||||
elt_add(s, s, ec_b);
|
||||
|
||||
elt_square(t, y);
|
||||
elt_sub(s, s, t);
|
||||
|
||||
return elt_is_zero(s);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void point_zero(struct point *p)
|
||||
{
|
||||
elt_zero(p->x);
|
||||
elt_zero(p->y);
|
||||
}
|
||||
|
||||
static int point_is_zero(struct point *p)
|
||||
{
|
||||
return elt_is_zero(p->x) && elt_is_zero(p->y);
|
||||
}
|
||||
|
||||
static void point_double(struct point *r, struct point *p)
|
||||
{
|
||||
u8 s[20], t[20];
|
||||
struct point pp;
|
||||
u8 *px, *py, *rx, *ry;
|
||||
|
||||
pp = *p;
|
||||
|
||||
px = pp.x;
|
||||
py = pp.y;
|
||||
rx = r->x;
|
||||
ry = r->y;
|
||||
|
||||
if (elt_is_zero(py)) {
|
||||
point_zero(r);
|
||||
return;
|
||||
}
|
||||
|
||||
elt_square(t, px); // t = px*px
|
||||
elt_add(s, t, t); // s = 2*px*px
|
||||
elt_add(s, s, t); // s = 3*px*px
|
||||
elt_add(s, s, ec_a); // s = 3*px*px + a
|
||||
elt_add(t, py, py); // t = 2*py
|
||||
elt_inv(t, t); // t = 1/(2*py)
|
||||
elt_mul(s, s, t); // s = (3*px*px+a)/(2*py)
|
||||
|
||||
elt_square(rx, s); // rx = s*s
|
||||
elt_add(t, px, px); // t = 2*px
|
||||
elt_sub(rx, rx, t); // rx = s*s - 2*px
|
||||
|
||||
elt_sub(t, px, rx); // t = -(rx-px)
|
||||
elt_mul(ry, s, t); // ry = -s*(rx-px)
|
||||
elt_sub(ry, ry, py); // ry = -s*(rx-px) - py
|
||||
}
|
||||
|
||||
static void point_add(struct point *r, struct point *p, struct point *q)
|
||||
{
|
||||
u8 s[20], t[20], u[20];
|
||||
u8 *px, *py, *qx, *qy, *rx, *ry;
|
||||
struct point pp, qq;
|
||||
|
||||
pp = *p;
|
||||
qq = *q;
|
||||
|
||||
px = pp.x;
|
||||
py = pp.y;
|
||||
qx = qq.x;
|
||||
qy = qq.y;
|
||||
rx = r->x;
|
||||
ry = r->y;
|
||||
|
||||
if (point_is_zero(&pp)) {
|
||||
elt_copy(rx, qx);
|
||||
elt_copy(ry, qy);
|
||||
return;
|
||||
}
|
||||
|
||||
if (point_is_zero(&qq)) {
|
||||
elt_copy(rx, px);
|
||||
elt_copy(ry, py);
|
||||
return;
|
||||
}
|
||||
|
||||
elt_sub(u, qx, px);
|
||||
|
||||
if (elt_is_zero(u)) {
|
||||
elt_sub(u, qy, py);
|
||||
if (elt_is_zero(u))
|
||||
point_double(r, &pp);
|
||||
else
|
||||
point_zero(r);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
elt_inv(t, u); // t = 1/(qx-px)
|
||||
elt_sub(u, qy, py); // u = qy-py
|
||||
elt_mul(s, t, u); // s = (qy-py)/(qx-px)
|
||||
|
||||
elt_square(rx, s); // rx = s*s
|
||||
elt_add(t, px, qx); // t = px+qx
|
||||
elt_sub(rx, rx, t); // rx = s*s - (px+qx)
|
||||
|
||||
elt_sub(t, px, rx); // t = -(rx-px)
|
||||
elt_mul(ry, s, t); // ry = -s*(rx-px)
|
||||
elt_sub(ry, ry, py); // ry = -s*(rx-px) - py
|
||||
}
|
||||
|
||||
static void point_mul(struct point *d, u8 *a, struct point *b) // a is bignum
|
||||
{
|
||||
u32 i;
|
||||
u8 mask;
|
||||
|
||||
point_zero(d);
|
||||
|
||||
for (i = 0; i < 21; i++)
|
||||
for (mask = 0x80; mask != 0; mask >>= 1) {
|
||||
point_double(d, d);
|
||||
if ((a[i] & mask) != 0)
|
||||
point_add(d, d, b);
|
||||
}
|
||||
}
|
||||
|
||||
static void generate_ecdsa(u8 *R, u8 *S, u8 *k, u8 *hash)
|
||||
{
|
||||
u8 e[21];
|
||||
u8 kk[21];
|
||||
u8 m[21];
|
||||
u8 minv[21];
|
||||
struct point mG;
|
||||
|
||||
e[0] = 0;
|
||||
memcpy(e + 1, hash, 20);
|
||||
bn_reduce(e, ec_N, 21);
|
||||
|
||||
try_again:
|
||||
prng(m, 21);
|
||||
m[0] = 0;
|
||||
if (bn_compare(m, ec_N, 21) >= 0)
|
||||
goto try_again;
|
||||
|
||||
// R = (mG).x
|
||||
|
||||
point_mul(&mG, m, &ec_G);
|
||||
point_from_mon(&mG);
|
||||
R[0] = 0;
|
||||
elt_copy(R+1, mG.x);
|
||||
|
||||
// S = m**-1*(e + Rk) (mod N)
|
||||
|
||||
bn_copy(kk, k, 21);
|
||||
bn_reduce(kk, ec_N, 21);
|
||||
bn_to_mon(m, ec_N, 21);
|
||||
bn_to_mon(e, ec_N, 21);
|
||||
bn_to_mon(R, ec_N, 21);
|
||||
bn_to_mon(kk, ec_N, 21);
|
||||
|
||||
bn_mon_mul(S, R, kk, ec_N, 21);
|
||||
bn_add(kk, S, e, ec_N, 21);
|
||||
bn_mon_inv(minv, m, ec_N, 21);
|
||||
bn_mon_mul(S, minv, kk, ec_N, 21);
|
||||
|
||||
bn_from_mon(R, ec_N, 21);
|
||||
bn_from_mon(S, ec_N, 21);
|
||||
}
|
||||
|
||||
static int check_ecdsa(struct point *Q, u8 *R, u8 *S, u8 *hash)
|
||||
{
|
||||
u8 Sinv[21];
|
||||
u8 e[21];
|
||||
u8 w1[21], w2[21];
|
||||
struct point r1, r2;
|
||||
u8 rr[21];
|
||||
|
||||
e[0] = 0;
|
||||
memcpy(e + 1, hash, 20);
|
||||
bn_reduce(e, ec_N, 21);
|
||||
|
||||
bn_to_mon(R, ec_N, 21);
|
||||
bn_to_mon(S, ec_N, 21);
|
||||
bn_to_mon(e, ec_N, 21);
|
||||
|
||||
bn_mon_inv(Sinv, S, ec_N, 21);
|
||||
|
||||
bn_mon_mul(w1, e, Sinv, ec_N, 21);
|
||||
bn_mon_mul(w2, R, Sinv, ec_N, 21);
|
||||
|
||||
bn_from_mon(w1, ec_N, 21);
|
||||
bn_from_mon(w2, ec_N, 21);
|
||||
|
||||
point_mul(&r1, w1, &ec_G);
|
||||
point_mul(&r2, w2, Q);
|
||||
|
||||
point_add(&r1, &r1, &r2);
|
||||
|
||||
point_from_mon(&r1);
|
||||
|
||||
rr[0] = 0;
|
||||
memcpy(rr + 1, r1.x, 20);
|
||||
bn_reduce(rr, ec_N, 21);
|
||||
|
||||
bn_from_mon(R, ec_N, 21);
|
||||
bn_from_mon(S, ec_N, 21);
|
||||
|
||||
return (bn_compare(rr, R, 21) == 0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void ec_priv_to_pub(u8 *k, u8 *Q)
|
||||
{
|
||||
point_mul(Q, k, ec_G);
|
||||
}
|
||||
#endif
|
||||
|
||||
int ecdsa_set_curve(u8* p, u8* a, u8* b, u8* N, u8* Gx, u8* Gy)
|
||||
{
|
||||
memcpy(ec_p, p, 20);
|
||||
memcpy(ec_a, a, 20);
|
||||
memcpy(ec_b, b, 20);
|
||||
memcpy(ec_N, N, 21);
|
||||
memcpy(ec_G.x, Gx, 20);
|
||||
memcpy(ec_G.y, Gy, 20);
|
||||
|
||||
bn_to_mon(ec_a, ec_p, 20);
|
||||
bn_to_mon(ec_b, ec_p, 20);
|
||||
|
||||
point_to_mon(&ec_G);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ecdsa_set_pub(u8 *Q)
|
||||
{
|
||||
memcpy(ec_Q.x, Q, 20);
|
||||
memcpy(ec_Q.y, Q+20, 20);
|
||||
point_to_mon(&ec_Q);
|
||||
}
|
||||
|
||||
void ecdsa_set_priv(u8 *k)
|
||||
{
|
||||
memcpy(ec_k, k, sizeof ec_k);
|
||||
}
|
||||
|
||||
int ecdsa_verify(u8 *hash, u8 *R, u8 *S)
|
||||
{
|
||||
return check_ecdsa(&ec_Q, R, S, hash);
|
||||
}
|
||||
|
||||
void ecdsa_sign(u8 *hash, u8 *R, u8 *S)
|
||||
{
|
||||
generate_ecdsa(R, S, ec_k, hash);
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
// Copyright (C) 2014 Hykem <hykem@hotmail.com>
|
||||
// Licensed under the terms of the GNU GPL, version 3
|
||||
// http://www.gnu.org/licenses/gpl-3.0.txt
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int ecdsa_set_curve(unsigned char *p, unsigned char *a, unsigned char *b, unsigned char *N, unsigned char *Gx, unsigned char *Gy);
|
||||
void ecdsa_set_pub(unsigned char *Q);
|
||||
void ecdsa_set_priv(unsigned char *k);
|
||||
int ecdsa_verify(unsigned char *hash, unsigned char *R, unsigned char *S);
|
||||
void ecdsa_sign(unsigned char *hash, unsigned char *R, unsigned char *S);
|
|
@ -8,10 +8,10 @@ SELF_KEY::SELF_KEY(u64 ver, u16 rev, u32 type, const std::string& e, const std::
|
|||
version = ver;
|
||||
revision = rev;
|
||||
self_type = type;
|
||||
hex_to_bytes(erk, e.c_str());
|
||||
hex_to_bytes(riv, r.c_str());
|
||||
hex_to_bytes(pub, pb.c_str());
|
||||
hex_to_bytes(priv, pr.c_str());
|
||||
hex_to_bytes(erk, e.c_str(), 0);
|
||||
hex_to_bytes(riv, r.c_str(), 0);
|
||||
hex_to_bytes(pub, pb.c_str(), 0);
|
||||
hex_to_bytes(priv, pr.c_str(), 0);
|
||||
curve_type = ct;
|
||||
}
|
||||
|
||||
|
|
|
@ -104,6 +104,35 @@ static u8 EDAT_IV[0x10] = {
|
|||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
static u8 VSH_CURVE_P[0x14] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
|
||||
};
|
||||
|
||||
static u8 VSH_CURVE_A[0x14] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC
|
||||
};
|
||||
|
||||
static u8 VSH_CURVE_B[0x14] = {
|
||||
0xA6, 0x8B, 0xED, 0xC3, 0x34, 0x18, 0x02, 0x9C, 0x1D, 0x3C, 0xE3, 0x3B, 0x9A, 0x32, 0x1F, 0xCC, 0xBB, 0x9E, 0x0F, 0x0B
|
||||
};
|
||||
|
||||
static u8 VSH_CURVE_N[0x15] = {
|
||||
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xB5, 0xAE, 0x3C, 0x52, 0x3E, 0x63, 0x94, 0x4F, 0x21, 0x27
|
||||
};
|
||||
|
||||
static u8 VSH_CURVE_GX[0x14] = {
|
||||
0x12, 0x8E, 0xC4, 0x25, 0x64, 0x87, 0xFD, 0x8F, 0xDF, 0x64, 0xE2, 0x43, 0x7B, 0xC0, 0xA1, 0xF6, 0xD5, 0xAF, 0xDE, 0x2C
|
||||
};
|
||||
|
||||
static u8 VSH_CURVE_GY[0x14] = {
|
||||
0x59, 0x58, 0x55, 0x7E, 0xB1, 0xDB, 0x00, 0x12, 0x60, 0x42, 0x55, 0x24, 0xDB, 0xC3, 0x79, 0xD5, 0xAC, 0x5F, 0x4A, 0xDF
|
||||
};
|
||||
|
||||
static u8 VSH_PUB[0x28] = {
|
||||
0x62, 0x27, 0xB0, 0x0A, 0x02, 0x85, 0x6F, 0xB0, 0x41, 0x08, 0x87, 0x67, 0x19, 0xE0, 0xA0, 0x18, 0x32, 0x91, 0xEE, 0xB9,
|
||||
0x6E, 0x73, 0x6A, 0xBF, 0x81, 0xF7, 0x0E, 0xE9, 0x16, 0x1B, 0x0D, 0xDE, 0xB0, 0x26, 0x76, 0x1A, 0xFF, 0x7B, 0xC8, 0x5B
|
||||
};
|
||||
|
||||
class KeyVault
|
||||
{
|
||||
std::vector<SELF_KEY> sk_LV0_arr;
|
||||
|
|
|
@ -4,26 +4,20 @@
|
|||
|
||||
#include "lz.h"
|
||||
|
||||
int decode_range(unsigned int *range, unsigned int *code, unsigned char **src)
|
||||
void decode_range(unsigned int *range, unsigned int *code, unsigned char **src)
|
||||
{
|
||||
if (!((*range) >> 24))
|
||||
{
|
||||
(*range) <<= 8;
|
||||
*code = ((*code) << 8) + (*src)++[5];
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int decode_bit(unsigned int *range, unsigned int *code, int *index, unsigned char **src, unsigned char *c)
|
||||
{
|
||||
unsigned int val = *range;
|
||||
decode_range(range, code, src);
|
||||
|
||||
if (decode_range(range, code, src))
|
||||
val *= (*c);
|
||||
else
|
||||
val = (val >> 8) * (*c);
|
||||
unsigned int val = ((*range) >> 8) * (*c);
|
||||
|
||||
*c -= ((*c) >> 3);
|
||||
if (index) (*index) <<= 1;
|
||||
|
@ -49,10 +43,10 @@ int decode_number(unsigned char *ptr, int index, int *bit_flag, unsigned int *ra
|
|||
|
||||
if (index >= 3)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr + 0x18); // Offset 0x978
|
||||
decode_bit(range, code, &i, src, ptr + 0x18);
|
||||
if (index >= 4)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr + 0x18); // Offset 0x978
|
||||
decode_bit(range, code, &i, src, ptr + 0x18);
|
||||
if (index >= 5)
|
||||
{
|
||||
decode_range(range, code, src);
|
||||
|
@ -69,14 +63,14 @@ int decode_number(unsigned char *ptr, int index, int *bit_flag, unsigned int *ra
|
|||
}
|
||||
}
|
||||
|
||||
*bit_flag = decode_bit(range, code, &i, src, ptr); // Offset 0x960
|
||||
*bit_flag = decode_bit(range, code, &i, src, ptr);
|
||||
|
||||
if (index >= 1)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr + 0x8); // Offset 0x968
|
||||
decode_bit(range, code, &i, src, ptr + 0x8);
|
||||
if (index >= 2)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr + 0x10); // Offset 0x970
|
||||
decode_bit(range, code, &i, src, ptr + 0x10);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,10 +84,10 @@ int decode_word(unsigned char *ptr, int index, int *bit_flag, unsigned int *rang
|
|||
|
||||
if (index >= 3)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr); // Offset 0x8A8
|
||||
decode_bit(range, code, &i, src, ptr + 4);
|
||||
if (index >= 4)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr); // Offset 0x8A8
|
||||
decode_bit(range, code, &i, src, ptr + 4);
|
||||
if (index >= 5)
|
||||
{
|
||||
decode_range(range, code, src);
|
||||
|
@ -110,14 +104,14 @@ int decode_word(unsigned char *ptr, int index, int *bit_flag, unsigned int *rang
|
|||
}
|
||||
}
|
||||
|
||||
*bit_flag = decode_bit(range, code, &i, src, ptr + 3); // Offset 0x8A8 + 3
|
||||
*bit_flag = decode_bit(range, code, &i, src, ptr);
|
||||
|
||||
if (index >= 1)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr + 2); // Offset 0x8A8 + 2
|
||||
decode_bit(range, code, &i, src, ptr + 1);
|
||||
if (index >= 2)
|
||||
{
|
||||
decode_bit(range, code, &i, src, ptr + 1); // Offset 0x8A8 + 1
|
||||
decode_bit(range, code, &i, src, ptr + 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -128,7 +122,7 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
|
|||
{
|
||||
int result;
|
||||
|
||||
unsigned char *tmp = new unsigned char[0xA70];
|
||||
unsigned char *tmp = new unsigned char[0xCC8];
|
||||
|
||||
int offset = 0;
|
||||
int bit_flag = 0;
|
||||
|
@ -159,11 +153,11 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
|
|||
else
|
||||
{
|
||||
// Set up a temporary buffer (sliding window).
|
||||
memset(tmp, 0x80, 0xA60);
|
||||
memset(tmp, 0x80, 0xCA8);
|
||||
while (1)
|
||||
{
|
||||
// Start reading at 0x920.
|
||||
tmp_sect1 = tmp + offset + 0x920;
|
||||
// Start reading at 0xB68.
|
||||
tmp_sect1 = tmp + offset + 0xB68;
|
||||
if (!decode_bit(&range, &code, 0, &in, tmp_sect1)) // Raw char.
|
||||
{
|
||||
// Adjust offset and check for stream end.
|
||||
|
@ -189,41 +183,47 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
|
|||
int index = -1;
|
||||
|
||||
// Identify the data length bit field.
|
||||
do {
|
||||
do
|
||||
{
|
||||
tmp_sect1 += 8;
|
||||
bit_flag = decode_bit(&range, &code, 0, &in, tmp_sect1);
|
||||
index += bit_flag;
|
||||
} while ((bit_flag != 0) && (index < 6));
|
||||
|
||||
// Default block size is 0x40.
|
||||
int b_size = 0x40;
|
||||
// Default block size is 0x160.
|
||||
int b_size = 0x160;
|
||||
tmp_sect2 = tmp + index + 0x7F1;
|
||||
|
||||
// If the data length was found, parse it as a number.
|
||||
if ((index >= 0) || (bit_flag != 0))
|
||||
{
|
||||
// Locate next section.
|
||||
int sect = (index << 5) | (((((start - out)) << index) & 3) << 3) | (offset & 7);
|
||||
tmp_sect1 = tmp + 0x960 + sect;
|
||||
int sect = (index << 5) | (((((int)(start - out)) << index) & 3) << 3) | (offset & 7);
|
||||
tmp_sect1 = tmp + 0xBA8 + sect;
|
||||
|
||||
// Decode the data length (8 bit fields).
|
||||
data_length = decode_number(tmp_sect1, index, &bit_flag, &range, &code, &in);
|
||||
|
||||
// If we got valid parameters, seek to find data offset.
|
||||
if ((data_length != 3) && ((index > 0) || (bit_flag != 0))) {
|
||||
tmp_sect2 += 0x38;
|
||||
b_size = 0x80; // Block size is now 0x80.
|
||||
if (data_length == 0xFF) return (start - out); // End of stream.
|
||||
}
|
||||
} else {
|
||||
else
|
||||
{
|
||||
// Assume one byte of advance.
|
||||
data_length = 1;
|
||||
}
|
||||
|
||||
// If we got valid parameters, seek to find data offset.
|
||||
if ((data_length <= 2))
|
||||
{
|
||||
tmp_sect2 += 0xF8;
|
||||
b_size = 0x40; // Block size is now 0x40.
|
||||
}
|
||||
|
||||
int diff = 0;
|
||||
int shift = 1;
|
||||
|
||||
// Identify the data offset bit field.
|
||||
do {
|
||||
do
|
||||
{
|
||||
diff = (shift << 4) - b_size;
|
||||
bit_flag = decode_bit(&range, &code, &shift, &in, tmp_sect2 + (shift << 3));
|
||||
} while (diff < 0);
|
||||
|
@ -235,11 +235,13 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
|
|||
if (bit_flag == 0) diff -= 8;
|
||||
|
||||
// Locate section.
|
||||
tmp_sect3 = tmp + 0x8A8 + diff;
|
||||
tmp_sect3 = tmp + 0x928 + diff;
|
||||
|
||||
// Decode the data offset (1 bit fields).
|
||||
data_offset = decode_word(tmp_sect3, diff, &bit_flag, &range, &code, &in);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
// Assume one byte of advance.
|
||||
data_offset = 1;
|
||||
}
|
||||
|
@ -260,7 +262,8 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
|
|||
offset = ((((int)(buf_end - out)) + 1) & 1) + 6;
|
||||
|
||||
// Copy data.
|
||||
do {
|
||||
do
|
||||
{
|
||||
*start++ = *buf_start++;
|
||||
} while (start < buf_end);
|
||||
|
||||
|
|
|
@ -1,7 +1,14 @@
|
|||
#pragma once
|
||||
|
||||
// Copyright (C) 2014 Hykem <hykem@hotmail.com>
|
||||
// Licensed under the terms of the GNU GPL, version 3
|
||||
// http://www.gnu.org/licenses/gpl-3.0.txt
|
||||
|
||||
// Reverse-engineered custom Lempel–Ziv–Markov based compression.
|
||||
|
||||
#include <string.h>
|
||||
|
||||
int decode_range(unsigned int *range, unsigned int *code, unsigned char **src);
|
||||
void decode_range(unsigned int *range, unsigned int *code, unsigned char **src);
|
||||
int decode_bit(unsigned int *range, unsigned int *code, int *index, unsigned char **src, unsigned char *c);
|
||||
int decode_number(unsigned char *ptr, int index, int *bit_flag, unsigned int *range, unsigned int *code, unsigned char **src);
|
||||
int decode_word(unsigned char *ptr, int index, int *bit_flag, unsigned int *range, unsigned int *code, unsigned char **src);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
/**
|
||||
* \file sha1.h
|
||||
*
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include "stdafx.h"
|
||||
#include "utils.h"
|
||||
#include "key_vault.h"
|
||||
#include "unedat.h"
|
||||
#include "Utilities/Log.h"
|
||||
|
@ -7,7 +6,7 @@
|
|||
|
||||
void generate_key(int crypto_mode, int version, unsigned char *key_final, unsigned char *iv_final, unsigned char *key, unsigned char *iv)
|
||||
{
|
||||
int mode = (int) (crypto_mode & 0xF0000000);
|
||||
int mode = (int)(crypto_mode & 0xF0000000);
|
||||
switch (mode) {
|
||||
case 0x10000000:
|
||||
// Encrypted ERK.
|
||||
|
@ -32,7 +31,7 @@ void generate_key(int crypto_mode, int version, unsigned char *key_final, unsign
|
|||
|
||||
void generate_hash(int hash_mode, int version, unsigned char *hash_final, unsigned char *hash)
|
||||
{
|
||||
int mode = (int) (hash_mode & 0xF0000000);
|
||||
int mode = (int)(hash_mode & 0xF0000000);
|
||||
switch (mode) {
|
||||
case 0x10000000:
|
||||
// Encrypted HASH.
|
||||
|
@ -52,7 +51,7 @@ void generate_hash(int hash_mode, int version, unsigned char *hash_final, unsign
|
|||
};
|
||||
}
|
||||
|
||||
bool crypto(int hash_mode, int crypto_mode, int version, unsigned char *in, unsigned char *out, int length, unsigned char *key, unsigned char *iv, unsigned char *hash, unsigned char *test_hash)
|
||||
bool decrypt(int hash_mode, int crypto_mode, int version, unsigned char *in, unsigned char *out, int length, unsigned char *key, unsigned char *iv, unsigned char *hash, unsigned char *test_hash)
|
||||
{
|
||||
// Setup buffers for key, iv and hash.
|
||||
unsigned char key_final[0x10] = {};
|
||||
|
@ -77,29 +76,30 @@ bool crypto(int hash_mode, int crypto_mode, int version, unsigned char *in, unsi
|
|||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Unknown crypto algorithm!\n");
|
||||
LOG_ERROR(LOADER, "EDAT: Unknown crypto algorithm!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((hash_mode & 0xFF) == 0x01) // 0x14 SHA1-HMAC
|
||||
{
|
||||
return hmac_hash_compare(hash_final_14, 0x14, in, length, test_hash);
|
||||
return hmac_hash_compare(hash_final_14, 0x14, in, length, test_hash, 0x14);
|
||||
}
|
||||
else if ((hash_mode & 0xFF) == 0x02) // 0x10 AES-CMAC
|
||||
{
|
||||
return cmac_hash_compare(hash_final_10, 0x10, in, length, test_hash);
|
||||
return cmac_hash_compare(hash_final_10, 0x10, in, length, test_hash, 0x10);
|
||||
}
|
||||
else if ((hash_mode & 0xFF) == 0x04) //0x10 SHA1-HMAC
|
||||
{
|
||||
return hmac_hash_compare(hash_final_10, 0x10, in, length, test_hash);
|
||||
return hmac_hash_compare(hash_final_10, 0x10, in, length, test_hash, 0x10);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Unknown hashing algorithm!\n");
|
||||
LOG_ERROR(LOADER, "EDAT: Unknown hashing algorithm!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// EDAT/SDAT functions.
|
||||
unsigned char* dec_section(unsigned char* metadata)
|
||||
{
|
||||
unsigned char *dec = new unsigned char[0x10];
|
||||
|
@ -135,11 +135,11 @@ unsigned char* get_block_key(int block, NPD_HEADER *npd)
|
|||
return dest_key;
|
||||
}
|
||||
|
||||
// EDAT/SDAT functions.
|
||||
int decrypt_data(rFile *in, rFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd, unsigned char* crypt_key, bool verbose)
|
||||
// EDAT/SDAT decryption.
|
||||
int decrypt_data(rFile *in, rFile *out, EDAT_HEADER *edat, NPD_HEADER *npd, unsigned char* crypt_key, bool verbose)
|
||||
{
|
||||
// Get metadata info and setup buffers.
|
||||
int block_num = (int) ((edat->file_size + edat->block_size - 1) / edat->block_size);
|
||||
int block_num = (int)((edat->file_size + edat->block_size - 1) / edat->block_size);
|
||||
int metadata_section_size = ((edat->flags & EDAT_COMPRESSED_FLAG) != 0 || (edat->flags & EDAT_FLAG_0x20) != 0) ? 0x20 : 0x10;
|
||||
int metadata_offset = 0x100;
|
||||
|
||||
|
@ -148,76 +148,101 @@ int decrypt_data(rFile *in, rFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd,
|
|||
unsigned char *b_key;
|
||||
unsigned char *iv;
|
||||
|
||||
unsigned char hash[0x10];
|
||||
unsigned char key_result[0x10];
|
||||
unsigned char hash_result[0x14];
|
||||
memset(hash, 0, 0x10);
|
||||
memset(key_result, 0, 0x10);
|
||||
memset(hash_result, 0, 0x14);
|
||||
|
||||
unsigned long long offset = 0;
|
||||
unsigned long long metadata_sec_offset = 0;
|
||||
int length = 0;
|
||||
int compression_end = 0;
|
||||
unsigned char empty_iv[0x10] = {};
|
||||
|
||||
// Decrypt the metadata.
|
||||
for (int i = 0; i < block_num; i++)
|
||||
int i;
|
||||
for (i = 0; i < block_num; i++)
|
||||
{
|
||||
in->Seek(metadata_offset + i * metadata_section_size);
|
||||
unsigned char hash_result[0x10];
|
||||
long offset;
|
||||
int length = 0;
|
||||
int compression_end = 0;
|
||||
|
||||
if ((edat->flags & EDAT_FLAG_0x04) != 0)
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Flag 0x04 is not yet supported");
|
||||
return -1;
|
||||
}
|
||||
memset(hash_result, 0, 0x14);
|
||||
|
||||
if ((edat->flags & EDAT_COMPRESSED_FLAG) != 0)
|
||||
{
|
||||
metadata_sec_offset = metadata_offset + (unsigned long long) i * metadata_section_size;
|
||||
in->Seek(metadata_sec_offset);
|
||||
|
||||
unsigned char metadata[0x20];
|
||||
memset(metadata, 0, 0x20);
|
||||
in->Read(metadata, 0x20);
|
||||
|
||||
// If the data is compressed, decrypt the metadata.
|
||||
// NOTE: For NPD version 1 the metadata is not encrypted.
|
||||
if (npd->version <= 1)
|
||||
{
|
||||
offset = swap64(*(unsigned long long*)&metadata[0x10]);
|
||||
length = swap32(*(int*)&metadata[0x18]);
|
||||
compression_end = swap32(*(int*)&metadata[0x1C]);
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned char *result = dec_section(metadata);
|
||||
offset = ((swap32(*(int*)&result[0]) << 4) | (swap32(*(int*)&result[4])));
|
||||
offset = swap64(*(unsigned long long*)&result[0]);
|
||||
length = swap32(*(int*)&result[8]);
|
||||
compression_end = swap32(*(int*)&result[12]);
|
||||
delete[] result;
|
||||
}
|
||||
|
||||
memcpy(hash_result, metadata, 0x10);
|
||||
}
|
||||
else if ((edat->flags & EDAT_FLAG_0x20) != 0)
|
||||
{
|
||||
// If FLAG 0x20, the metadata precedes each data block.
|
||||
in->Seek(metadata_offset + i * metadata_section_size + length);
|
||||
metadata_sec_offset = metadata_offset + (unsigned long long) i * (metadata_section_size + length);
|
||||
in->Seek(metadata_sec_offset);
|
||||
|
||||
unsigned char metadata[0x20];
|
||||
memset(metadata, 0, 0x20);
|
||||
in->Read(metadata, 0x20);
|
||||
memcpy(hash_result, metadata, 0x14);
|
||||
|
||||
// If FLAG 0x20 is set, apply custom xor.
|
||||
for (int j = 0; j < 0x10; j++) {
|
||||
hash_result[j] = (unsigned char)(metadata[j] ^ metadata[j+0x10]);
|
||||
}
|
||||
int j;
|
||||
for (j = 0; j < 0x10; j++)
|
||||
hash_result[j] = (unsigned char)(metadata[j] ^ metadata[j + 0x10]);
|
||||
|
||||
offset = metadata_offset + i * edat->block_size + (i + 1) * metadata_section_size;
|
||||
offset = metadata_sec_offset + 0x20;
|
||||
length = edat->block_size;
|
||||
|
||||
if ((i == (block_num - 1)) && (edat->file_size % edat->block_size))
|
||||
length = (int) (edat->file_size % edat->block_size);
|
||||
length = (int)(edat->file_size % edat->block_size);
|
||||
}
|
||||
else
|
||||
{
|
||||
metadata_sec_offset = metadata_offset + (unsigned long long) i * metadata_section_size;
|
||||
in->Seek(metadata_sec_offset);
|
||||
|
||||
in->Read(hash_result, 0x10);
|
||||
offset = metadata_offset + i * edat->block_size + block_num * metadata_section_size;
|
||||
offset = metadata_offset + (unsigned long long) i * edat->block_size + (unsigned long long) block_num * metadata_section_size;
|
||||
length = edat->block_size;
|
||||
|
||||
if ((i == (block_num - 1)) && (edat->file_size % edat->block_size))
|
||||
length = (int) (edat->file_size % edat->block_size);
|
||||
length = (int)(edat->file_size % edat->block_size);
|
||||
}
|
||||
|
||||
// Locate the real data.
|
||||
int pad_length = length;
|
||||
length = (int) ((pad_length + 0xF) & 0xFFFFFFF0);
|
||||
in->Seek(offset);
|
||||
length = (int)((pad_length + 0xF) & 0xFFFFFFF0);
|
||||
|
||||
// Setup buffers for decryption and read the data.
|
||||
enc_data = new unsigned char[length];
|
||||
dec_data = new unsigned char[length];
|
||||
unsigned char key_result[0x10];
|
||||
unsigned char hash[0x10];
|
||||
memset(enc_data, 0, length);
|
||||
memset(dec_data, 0, length);
|
||||
memset(hash, 0, 0x10);
|
||||
memset(key_result, 0, 0x10);
|
||||
|
||||
in->Seek(offset);
|
||||
in->Read(enc_data, length);
|
||||
|
||||
// Generate a key for the current block.
|
||||
|
@ -260,7 +285,13 @@ int decrypt_data(rFile *in, rFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd,
|
|||
// IV is null if NPD version is 1 or 0.
|
||||
iv = (npd->version <= 1) ? empty_iv : npd->digest;
|
||||
// Call main crypto routine on this data block.
|
||||
crypto(hash_mode, crypto_mode, (npd->version == 4), enc_data, dec_data, length, key_result, iv, hash, hash_result);
|
||||
if (!decrypt(hash_mode, crypto_mode, (npd->version == 4), enc_data, dec_data, length, key_result, iv, hash, hash_result))
|
||||
{
|
||||
if (verbose)
|
||||
LOG_WARNING(LOADER, "EDAT: Block at offset 0x%llx has invalid hash!", offset);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply additional compression if needed and write the decrypted data.
|
||||
|
@ -271,15 +302,15 @@ int decrypt_data(rFile *in, rFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd,
|
|||
memset(decomp_data, 0, decomp_size);
|
||||
|
||||
if (verbose)
|
||||
LOG_NOTICE(LOADER, "EDAT: Decompressing...\n");
|
||||
LOG_NOTICE(LOADER, "EDAT: Decompressing data...");
|
||||
|
||||
int res = lz_decompress(decomp_data, dec_data, decomp_size);
|
||||
int res = decompress(decomp_data, dec_data, decomp_size);
|
||||
out->Write(decomp_data, res);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
LOG_NOTICE(LOADER, "EDAT: Compressed block size: %d\n", pad_length);
|
||||
LOG_NOTICE(LOADER, "EDAT: Decompressed block size: %d\n", res);
|
||||
LOG_NOTICE(LOADER, "EDAT: Compressed block size: %d", pad_length);
|
||||
LOG_NOTICE(LOADER, "EDAT: Decompressed block size: %d", res);
|
||||
}
|
||||
|
||||
edat->file_size -= res;
|
||||
|
@ -288,11 +319,11 @@ int decrypt_data(rFile *in, rFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd,
|
|||
{
|
||||
if (res < 0)
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Decompression failed!\n");
|
||||
LOG_ERROR(LOADER, "EDAT: Decompression failed!");
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
LOG_SUCCESS(LOADER, "EDAT: Data successfully decompressed!\n");
|
||||
LOG_NOTICE(LOADER, "EDAT: Successfully decompressed!");
|
||||
}
|
||||
|
||||
delete[] decomp_data;
|
||||
|
@ -309,158 +340,262 @@ int decrypt_data(rFile *in, rFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool check_flags(EDAT_SDAT_HEADER *edat, NPD_HEADER *npd)
|
||||
int check_data(unsigned char *key, EDAT_HEADER *edat, NPD_HEADER *npd, rFile *f, bool verbose)
|
||||
{
|
||||
if (edat == nullptr || npd == nullptr)
|
||||
return false;
|
||||
f->Seek(0);
|
||||
unsigned char header[0xA0];
|
||||
unsigned char empty_header[0xA0];
|
||||
unsigned char header_hash[0x10];
|
||||
unsigned char metadata_hash[0x10];
|
||||
memset(header, 0, 0xA0);
|
||||
memset(empty_header, 0, 0xA0);
|
||||
memset(header_hash, 0, 0x10);
|
||||
memset(metadata_hash, 0, 0x10);
|
||||
|
||||
if (npd->version == 0 || npd->version == 1)
|
||||
// Check NPD version and flags.
|
||||
if ((npd->version == 0) || (npd->version == 1))
|
||||
{
|
||||
if (edat->flags & 0x7EFFFFFE)
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Bad header flags!\n");
|
||||
return false;
|
||||
LOG_ERROR(LOADER, "EDAT: Bad header flags!");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (npd->version == 2)
|
||||
{
|
||||
if (edat->flags & 0x7EFFFFE0)
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Bad header flags!\n");
|
||||
return false;
|
||||
LOG_ERROR(LOADER, "EDAT: Bad header flags!");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (npd->version == 3 || npd->version == 4)
|
||||
else if ((npd->version == 3) || (npd->version == 4))
|
||||
{
|
||||
if (edat->flags & 0x7EFFFFC0)
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Bad header flags!\n");
|
||||
return false;
|
||||
LOG_ERROR(LOADER, "EDAT: Bad header flags!");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (npd->version > 4)
|
||||
else
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Unknown version - %d\n", npd->version);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int check_data(unsigned char *key, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd, rFile *f, bool verbose)
|
||||
{
|
||||
f->Seek(0);
|
||||
unsigned char *header = new unsigned char[0xA0];
|
||||
unsigned char *tmp = new unsigned char[0xA0];
|
||||
unsigned char *hash_result = new unsigned char[0x10];
|
||||
|
||||
// Check NPD version and EDAT flags.
|
||||
if (!check_flags(edat, npd))
|
||||
{
|
||||
delete[] header;
|
||||
delete[] tmp;
|
||||
delete[] hash_result;
|
||||
|
||||
LOG_ERROR(LOADER, "EDAT: Unknown version!");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Read in the file header.
|
||||
f->Read(header, 0xA0);
|
||||
f->Read(hash_result, 0x10);
|
||||
|
||||
// Read in the header and metadata section hashes.
|
||||
f->Seek(0x90);
|
||||
f->Read(metadata_hash, 0x10);
|
||||
f->Read(header_hash, 0x10);
|
||||
|
||||
// Setup the hashing mode and the crypto mode used in the file.
|
||||
int crypto_mode = 0x1;
|
||||
int hash_mode = ((edat->flags & EDAT_ENCRYPTED_KEY_FLAG) == 0) ? 0x00000002 : 0x10000002;
|
||||
if ((edat->flags & EDAT_DEBUG_DATA_FLAG) != 0)
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: DEBUG data detected!\n");
|
||||
hash_mode |= 0x01000000;
|
||||
|
||||
if (verbose)
|
||||
LOG_WARNING(LOADER, "EDAT: DEBUG data detected!");
|
||||
}
|
||||
|
||||
// Setup header key and iv buffers.
|
||||
unsigned char header_key[0x10] = {};
|
||||
unsigned char header_iv[0x10] = {};
|
||||
unsigned char header_key[0x10];
|
||||
unsigned char header_iv[0x10];
|
||||
memset(header_key, 0, 0x10);
|
||||
memset(header_iv, 0, 0x10);
|
||||
|
||||
// Test the header hash (located at offset 0xA0).
|
||||
if (!crypto(hash_mode, crypto_mode, (npd->version == 4), header, tmp, 0xA0, header_key, header_iv, key, hash_result))
|
||||
if (!decrypt(hash_mode, crypto_mode, (npd->version == 4), header, empty_header, 0xA0, header_key, header_iv, key, header_hash))
|
||||
{
|
||||
if (verbose)
|
||||
LOG_WARNING(LOADER, "EDAT: Header hash is invalid!\n");
|
||||
LOG_WARNING(LOADER, "EDAT: Header hash is invalid!");
|
||||
|
||||
// If the header hash test fails and the data is not DEBUG, then RAP/RIF/KLIC key is invalid.
|
||||
if ((edat->flags & EDAT_DEBUG_DATA_FLAG) != EDAT_DEBUG_DATA_FLAG)
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: RAP/RIF/KLIC key is invalid!");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the metadata info.
|
||||
int metadata_section_size = 0x10;
|
||||
int metadata_section_size = ((edat->flags & EDAT_COMPRESSED_FLAG) != 0 || (edat->flags & EDAT_FLAG_0x20) != 0) ? 0x20 : 0x10;
|
||||
if (((edat->flags & EDAT_COMPRESSED_FLAG) != 0))
|
||||
{
|
||||
LOG_WARNING(LOADER, "EDAT: COMPRESSED data detected!\n");
|
||||
metadata_section_size = 0x20;
|
||||
if (verbose)
|
||||
LOG_WARNING(LOADER, "EDAT: COMPRESSED data detected!");
|
||||
}
|
||||
|
||||
int block_num = (int) ((edat->file_size + edat->block_size - 1) / edat->block_size);
|
||||
int bytes_read = 0;
|
||||
int block_num = (int)((edat->file_size + edat->block_size - 1) / edat->block_size);
|
||||
int metadata_offset = 0x100;
|
||||
int metadata_size = metadata_section_size * block_num;
|
||||
long long metadata_section_offset = metadata_offset;
|
||||
|
||||
long bytes_read = 0;
|
||||
long bytes_to_read = metadata_size;
|
||||
unsigned char *metadata = new unsigned char[metadata_size];
|
||||
unsigned char *empty_metadata = new unsigned char[metadata_size];
|
||||
|
||||
long bytes_to_read = metadata_section_size * block_num;
|
||||
while (bytes_to_read > 0)
|
||||
{
|
||||
// Locate the metadata blocks.
|
||||
int block_size = (0x3C00 > bytes_to_read) ? (int) bytes_to_read : 0x3C00; // 0x3C00 is the maximum block size.
|
||||
f->Seek(metadata_offset + bytes_read);
|
||||
unsigned char *data = new unsigned char[block_size];
|
||||
f->Seek(metadata_section_offset);
|
||||
|
||||
// Read in the metadata.
|
||||
tmp = new unsigned char[block_size];
|
||||
f->Read(data, block_size);
|
||||
|
||||
// Check the generated hash against the metadata hash located at offset 0x90 in the header.
|
||||
memset(hash_result, 0, 0x10);
|
||||
f->Seek(0x90);
|
||||
f->Read(hash_result, 0x10);
|
||||
|
||||
// Generate the hash for this block.
|
||||
if (!crypto(hash_mode, crypto_mode, (npd->version == 4), data, tmp, block_size, header_key, header_iv, key, hash_result))
|
||||
{
|
||||
if (verbose)
|
||||
LOG_WARNING(LOADER, "EDAT: Metadata hash from block 0x%08x is invalid!\n", metadata_offset + bytes_read);
|
||||
}
|
||||
f->Read(metadata + bytes_read, metadata_section_size);
|
||||
|
||||
// Adjust sizes.
|
||||
bytes_read += block_size;
|
||||
bytes_to_read -= block_size;
|
||||
bytes_read += metadata_section_size;
|
||||
bytes_to_read -= metadata_section_size;
|
||||
|
||||
delete[] data;
|
||||
if (((edat->flags & EDAT_FLAG_0x20) != 0)) // Metadata block before each data block.
|
||||
metadata_section_offset += (metadata_section_size + edat->block_size);
|
||||
else
|
||||
metadata_section_offset += metadata_section_size;
|
||||
}
|
||||
|
||||
// Test the metadata section hash (located at offset 0x90).
|
||||
if (!decrypt(hash_mode, crypto_mode, (npd->version == 4), metadata, empty_metadata, metadata_size, header_key, header_iv, key, metadata_hash))
|
||||
{
|
||||
if (verbose)
|
||||
LOG_WARNING(LOADER, "EDAT: Metadata section hash is invalid!");
|
||||
}
|
||||
|
||||
// Checking ECDSA signatures.
|
||||
if ((edat->flags & EDAT_DEBUG_DATA_FLAG) == 0)
|
||||
{
|
||||
LOG_NOTICE(LOADER, "EDAT: Checking signatures...");
|
||||
|
||||
// Setup buffers.
|
||||
unsigned char metadata_signature[0x28];
|
||||
unsigned char header_signature[0x28];
|
||||
unsigned char signature_hash[20];
|
||||
unsigned char signature_r[0x15];
|
||||
unsigned char signature_s[0x15];
|
||||
unsigned char zero_buf[0x15];
|
||||
memset(metadata_signature, 0, 0x28);
|
||||
memset(header_signature, 0, 0x28);
|
||||
memset(signature_hash, 0, 20);
|
||||
memset(signature_r, 0, 0x15);
|
||||
memset(signature_s, 0, 0x15);
|
||||
memset(zero_buf, 0, 0x15);
|
||||
|
||||
// Setup ECDSA curve and public key.
|
||||
ecdsa_set_curve(VSH_CURVE_P, VSH_CURVE_A, VSH_CURVE_B, VSH_CURVE_N, VSH_CURVE_GX, VSH_CURVE_GY);
|
||||
ecdsa_set_pub(VSH_PUB);
|
||||
|
||||
|
||||
// Read in the metadata and header signatures.
|
||||
f->Seek(0xB0);
|
||||
f->Read(metadata_signature, 0x28);
|
||||
f->Seek(0xD8);
|
||||
f->Read(header_signature, 0x28);
|
||||
|
||||
// Checking metadata signature.
|
||||
// Setup signature r and s.
|
||||
memcpy(signature_r + 01, metadata_signature, 0x14);
|
||||
memcpy(signature_s + 01, metadata_signature + 0x14, 0x14);
|
||||
if ((!memcmp(signature_r, zero_buf, 0x15)) || (!memcmp(signature_s, zero_buf, 0x15)))
|
||||
LOG_WARNING(LOADER, "EDAT: Metadata signature is invalid!");
|
||||
else
|
||||
{
|
||||
// Setup signature hash.
|
||||
if ((edat->flags & EDAT_FLAG_0x20) != 0) //Sony failed again, they used buffer from 0x100 with half size of real metadata.
|
||||
{
|
||||
int metadata_buf_size = block_num * 0x10;
|
||||
unsigned char *metadata_buf = new unsigned char[metadata_buf_size];
|
||||
f->Seek(metadata_offset);
|
||||
f->Read(metadata_buf, metadata_buf_size);
|
||||
sha1(metadata_buf, metadata_buf_size, signature_hash);
|
||||
delete[] metadata_buf;
|
||||
}
|
||||
else
|
||||
sha1(metadata, metadata_size, signature_hash);
|
||||
|
||||
if (!ecdsa_verify(signature_hash, signature_r, signature_s))
|
||||
{
|
||||
LOG_WARNING(LOADER, "EDAT: Metadata signature is invalid!");
|
||||
if (((unsigned long long)edat->block_size * block_num) > 0x100000000)
|
||||
LOG_WARNING(LOADER, "EDAT: *Due to large file size, metadata signature status may be incorrect!");
|
||||
}
|
||||
else
|
||||
LOG_NOTICE(LOADER, "EDAT: Metadata signature is valid!");
|
||||
}
|
||||
|
||||
|
||||
// Checking header signature.
|
||||
// Setup header signature r and s.
|
||||
memset(signature_r, 0, 0x15);
|
||||
memset(signature_s, 0, 0x15);
|
||||
memcpy(signature_r + 01, header_signature, 0x14);
|
||||
memcpy(signature_s + 01, header_signature + 0x14, 0x14);
|
||||
|
||||
if ((!memcmp(signature_r, zero_buf, 0x15)) || (!memcmp(signature_s, zero_buf, 0x15)))
|
||||
LOG_WARNING(LOADER, "EDAT: Header signature is invalid!");
|
||||
else
|
||||
{
|
||||
// Setup header signature hash.
|
||||
memset(signature_hash, 0, 20);
|
||||
unsigned char *header_buf = new unsigned char[0xD8];
|
||||
f->Seek(0x00);
|
||||
f->Read(header_buf, 0xD8);
|
||||
sha1(header_buf, 0xD8, signature_hash );
|
||||
delete[] header_buf;
|
||||
|
||||
if (ecdsa_verify(signature_hash, signature_r, signature_s))
|
||||
LOG_NOTICE(LOADER, "EDAT: Header signature is valid!");
|
||||
else
|
||||
LOG_WARNING(LOADER, "EDAT: Header signature is invalid!");
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup.
|
||||
delete[] header;
|
||||
delete[] tmp;
|
||||
delete[] hash_result;
|
||||
delete[] metadata;
|
||||
delete[] empty_metadata;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void validate_data(const char* file_name, unsigned char *klicensee, NPD_HEADER *npd, bool verbose)
|
||||
int validate_npd_hashes(const char* file_name, unsigned char *klicensee, NPD_HEADER *npd, bool verbose)
|
||||
{
|
||||
int title_hash_result = 0;
|
||||
int dev_hash_result = 0;
|
||||
|
||||
int file_name_length = (int)strlen(file_name);
|
||||
int file_name_length = (int) strlen(file_name);
|
||||
unsigned char *buf = new unsigned char[0x30 + file_name_length];
|
||||
unsigned char dev[0x60];
|
||||
unsigned char key[0x10];
|
||||
memset(dev, 0, 0x60);
|
||||
memset(key, 0, 0x10);
|
||||
|
||||
// Build the buffer (content_id + file_name).
|
||||
// Build the title buffer (content_id + file_name).
|
||||
memcpy(buf, npd->content_id, 0x30);
|
||||
memcpy(buf + 0x30, file_name, file_name_length);
|
||||
|
||||
// Hash with NP_OMAC_KEY_3 and compare with title_hash.
|
||||
title_hash_result = cmac_hash_compare(NP_OMAC_KEY_3, 0x10, buf, 0x30 + file_name_length, npd->title_hash);
|
||||
// Build the dev buffer (first 0x60 bytes of NPD header in big-endian).
|
||||
memcpy(dev, npd, 0x60);
|
||||
|
||||
// Fix endianness.
|
||||
int version = swap32(npd->version);
|
||||
int license = swap32(npd->license);
|
||||
int type = swap32(npd->type);
|
||||
memcpy(dev + 0x4, &version, 4);
|
||||
memcpy(dev + 0x8, &license, 4);
|
||||
memcpy(dev + 0xC, &type, 4);
|
||||
|
||||
// Hash with NPDRM_OMAC_KEY_3 and compare with title_hash.
|
||||
title_hash_result = cmac_hash_compare(NP_OMAC_KEY_3, 0x10, buf, 0x30 + file_name_length, npd->title_hash, 0x10);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
if (title_hash_result)
|
||||
LOG_SUCCESS(LOADER, "EDAT: NPD title hash is valid!\n");
|
||||
LOG_NOTICE(LOADER, "EDAT: NPD title hash is valid!");
|
||||
else
|
||||
LOG_WARNING(LOADER, "EDAT: NPD title hash is invalid!\n");
|
||||
LOG_WARNING(LOADER, "EDAT: NPD title hash is invalid!");
|
||||
}
|
||||
|
||||
// Check for an empty dev_hash (can't validate if devklic is NULL);
|
||||
|
@ -477,39 +612,44 @@ void validate_data(const char* file_name, unsigned char *klicensee, NPD_HEADER *
|
|||
if (isDevklicEmpty)
|
||||
{
|
||||
if (verbose)
|
||||
LOG_WARNING(LOADER, "EDAT: NPD dev hash is empty!\n");
|
||||
LOG_WARNING(LOADER, "EDAT: NPD dev hash is empty!");
|
||||
|
||||
// Allow empty dev hash.
|
||||
dev_hash_result = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Generate klicensee xor key.
|
||||
xor_(key, klicensee, NP_OMAC_KEY_2, 0x10);
|
||||
xor_key(key, klicensee, NP_OMAC_KEY_2, 0x10);
|
||||
|
||||
// Hash with generated key and compare with dev_hash.
|
||||
dev_hash_result = cmac_hash_compare(key, 0x10, (unsigned char *)npd, 0x60, npd->dev_hash);
|
||||
dev_hash_result = cmac_hash_compare(key, 0x10, dev, 0x60, npd->dev_hash, 0x10);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
if (dev_hash_result)
|
||||
LOG_SUCCESS(LOADER, "EDAT: NPD dev hash is valid!\n");
|
||||
LOG_NOTICE(LOADER, "EDAT: NPD dev hash is valid!");
|
||||
else
|
||||
LOG_WARNING(LOADER, "EDAT: NPD dev hash is invalid!\n");
|
||||
LOG_WARNING(LOADER, "EDAT: NPD dev hash is invalid!");
|
||||
}
|
||||
}
|
||||
|
||||
delete[] buf;
|
||||
|
||||
return (title_hash_result && dev_hash_result);
|
||||
}
|
||||
|
||||
bool extract_data(rFile *input, rFile *output, const char* input_file_name, unsigned char* devklic, unsigned char* rifkey, bool verbose)
|
||||
{
|
||||
// Setup NPD and EDAT/SDAT structs.
|
||||
NPD_HEADER *NPD = new NPD_HEADER();
|
||||
EDAT_SDAT_HEADER *EDAT = new EDAT_SDAT_HEADER();
|
||||
EDAT_HEADER *EDAT = new EDAT_HEADER();
|
||||
|
||||
// Read in the NPD and EDAT/SDAT headers.
|
||||
char npd_header[0x80];
|
||||
char edat_header[0x10];
|
||||
input->Read(npd_header, 0x80);
|
||||
input->Read(edat_header, 0x10);
|
||||
input->Read(npd_header, sizeof(npd_header));
|
||||
input->Read(edat_header, sizeof(edat_header));
|
||||
|
||||
memcpy(NPD->magic, npd_header, 4);
|
||||
NPD->version = swap32(*(int*)&npd_header[4]);
|
||||
|
@ -523,7 +663,7 @@ bool extract_data(rFile *input, rFile *output, const char* input_file_name, unsi
|
|||
NPD->unk2 = swap64(*(u64*)&npd_header[120]);
|
||||
|
||||
unsigned char npd_magic[4] = {0x4E, 0x50, 0x44, 0x00}; //NPD0
|
||||
if(memcmp(NPD->magic, npd_magic, 4))
|
||||
if (memcmp(NPD->magic, npd_magic, 4))
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: %s has invalid NPD header or already decrypted.", input_file_name);
|
||||
delete NPD;
|
||||
|
@ -537,32 +677,56 @@ bool extract_data(rFile *input, rFile *output, const char* input_file_name, unsi
|
|||
|
||||
if (verbose)
|
||||
{
|
||||
LOG_NOTICE(LOADER, "NPD HEADER\n");
|
||||
LOG_NOTICE(LOADER, "NPD version: %d\n", NPD->version);
|
||||
LOG_NOTICE(LOADER, "NPD license: %d\n", NPD->license);
|
||||
LOG_NOTICE(LOADER, "NPD type: %d\n", NPD->type);
|
||||
LOG_NOTICE(LOADER, "\n");
|
||||
LOG_NOTICE(LOADER, "EDAT HEADER\n");
|
||||
LOG_NOTICE(LOADER, "EDAT flags: 0x%08X\n", EDAT->flags);
|
||||
LOG_NOTICE(LOADER, "EDAT block size: 0x%08X\n", EDAT->block_size);
|
||||
LOG_NOTICE(LOADER, "EDAT file size: 0x%08X\n", EDAT->file_size);
|
||||
LOG_NOTICE(LOADER, "\n");
|
||||
LOG_NOTICE(LOADER, "NPD HEADER");
|
||||
LOG_NOTICE(LOADER, "NPD version: %d", NPD->version);
|
||||
LOG_NOTICE(LOADER, "NPD license: %d", NPD->license);
|
||||
LOG_NOTICE(LOADER, "NPD type: %d", NPD->type);
|
||||
}
|
||||
|
||||
// Set decryption key.
|
||||
unsigned char key[0x10];
|
||||
memset(key, 0, 0x10);
|
||||
|
||||
if((EDAT->flags & SDAT_FLAG) == SDAT_FLAG)
|
||||
// Check EDAT/SDAT flag.
|
||||
if ((EDAT->flags & SDAT_FLAG) == SDAT_FLAG)
|
||||
{
|
||||
LOG_WARNING(LOADER, "EDAT: SDAT detected!\n");
|
||||
xor_(key, NPD->dev_hash, SDAT_KEY, 0x10);
|
||||
if (verbose)
|
||||
{
|
||||
LOG_NOTICE(LOADER, "SDAT HEADER");
|
||||
LOG_NOTICE(LOADER, "SDAT flags: 0x%08X", EDAT->flags);
|
||||
LOG_NOTICE(LOADER, "SDAT block size: 0x%08X", EDAT->block_size);
|
||||
LOG_NOTICE(LOADER, "SDAT file size: 0x%08X", EDAT->file_size);
|
||||
}
|
||||
|
||||
// Generate SDAT key.
|
||||
xor_key(key, NPD->dev_hash, SDAT_KEY, 0x10);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Perform header validation (optional step).
|
||||
validate_data(input_file_name, devklic, NPD, verbose);
|
||||
if (verbose)
|
||||
{
|
||||
LOG_NOTICE(LOADER, "EDAT HEADER");
|
||||
LOG_NOTICE(LOADER, "EDAT flags: 0x%08X", EDAT->flags);
|
||||
LOG_NOTICE(LOADER, "EDAT block size: 0x%08X", EDAT->block_size);
|
||||
LOG_NOTICE(LOADER, "EDAT file size: 0x%08X", EDAT->file_size);
|
||||
}
|
||||
|
||||
// Perform header validation (EDAT only).
|
||||
char real_file_name[MAX_PATH];
|
||||
extract_file_name(input_file_name, real_file_name);
|
||||
if (!validate_npd_hashes(real_file_name, devklic, NPD, verbose))
|
||||
{
|
||||
// Ignore header validation in DEBUG data.
|
||||
if ((EDAT->flags & EDAT_DEBUG_DATA_FLAG) != EDAT_DEBUG_DATA_FLAG)
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: NPD hash validation failed!");
|
||||
delete NPD;
|
||||
delete EDAT;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Select EDAT key.
|
||||
if ((NPD->license & 0x3) == 0x3) // Type 3: Use supplied devklic.
|
||||
memcpy(key, devklic, 0x10);
|
||||
else if ((NPD->license & 0x2) == 0x2) // Type 2: Use key from RAP file (RIF key).
|
||||
|
@ -571,7 +735,7 @@ bool extract_data(rFile *input, rFile *output, const char* input_file_name, unsi
|
|||
|
||||
// Make sure we don't have an empty RIF key.
|
||||
int i, test = 0;
|
||||
for(i = 0; i < 0x10; i++)
|
||||
for (i = 0; i < 0x10; i++)
|
||||
{
|
||||
if (key[i] != 0)
|
||||
{
|
||||
|
@ -582,27 +746,62 @@ bool extract_data(rFile *input, rFile *output, const char* input_file_name, unsi
|
|||
|
||||
if (!test)
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: A valid RAP file is needed!");
|
||||
LOG_ERROR(LOADER, "EDAT: A valid RAP file is needed for this EDAT file!");
|
||||
delete NPD;
|
||||
delete EDAT;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if ((NPD->license & 0x1) == 0x1) // Type 1: Use network activation.
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Network license not supported!");
|
||||
delete NPD;
|
||||
delete EDAT;
|
||||
return 1;
|
||||
}
|
||||
|
||||
LOG_NOTICE(LOADER, "EDAT: Parsing data...\n");
|
||||
if (verbose)
|
||||
{
|
||||
int i;
|
||||
LOG_NOTICE(LOADER, "DEVKLIC: ");
|
||||
for (i = 0; i < 0x10; i++)
|
||||
LOG_NOTICE(LOADER, "%02X", devklic[i]);
|
||||
|
||||
LOG_NOTICE(LOADER, "RIF KEY: ");
|
||||
for (i = 0; i < 0x10; i++)
|
||||
LOG_NOTICE(LOADER, "%02X", rifkey[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
int i;
|
||||
LOG_NOTICE(LOADER, "DECRYPTION KEY: ");
|
||||
for (i = 0; i < 0x10; i++)
|
||||
LOG_NOTICE(LOADER, "%02X", key[i]);
|
||||
}
|
||||
|
||||
LOG_NOTICE(LOADER, "EDAT: Parsing data...");
|
||||
if (check_data(key, EDAT, NPD, input, verbose))
|
||||
LOG_ERROR(LOADER, "EDAT: Data parsing failed!\n");
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Data parsing failed!");
|
||||
delete NPD;
|
||||
delete EDAT;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
LOG_SUCCESS(LOADER, "EDAT: Data successfully parsed!\n");
|
||||
LOG_NOTICE(LOADER, "EDAT: Data successfully parsed!");
|
||||
|
||||
printf("\n");
|
||||
|
||||
LOG_NOTICE(LOADER, "EDAT: Decrypting data...\n");
|
||||
LOG_NOTICE(LOADER, "EDAT: Decrypting data...");
|
||||
if (decrypt_data(input, output, EDAT, NPD, key, verbose))
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Data decryption failed!");
|
||||
delete NPD;
|
||||
delete EDAT;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
LOG_SUCCESS(LOADER, "EDAT: Data successfully decrypted!");
|
||||
LOG_NOTICE(LOADER, "EDAT: Data successfully decrypted!");
|
||||
|
||||
delete NPD;
|
||||
delete EDAT;
|
||||
|
@ -655,21 +854,21 @@ int DecryptEDAT(const std::string& input_file_name, const std::string& output_fi
|
|||
memcpy(devklic, custom_klic, 0x10);
|
||||
else
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Invalid custom klic!\n");
|
||||
LOG_ERROR(LOADER, "EDAT: Invalid custom klic!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG_ERROR(LOADER, "EDAT: Invalid mode!\n");
|
||||
LOG_ERROR(LOADER, "EDAT: Invalid mode!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check the input/output files.
|
||||
if (!input.IsOpened() || !output.IsOpened())
|
||||
{
|
||||
LOG_ERROR(LOADER, "EDAT: Failed to open files!\n");
|
||||
LOG_ERROR(LOADER, "EDAT: Failed to open files!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -692,7 +891,7 @@ int DecryptEDAT(const std::string& input_file_name, const std::string& output_fi
|
|||
input.Close();
|
||||
output.Close();
|
||||
rRemoveFile(output_file_name);
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Cleanup.
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "utils.h"
|
||||
|
||||
#define SDAT_FLAG 0x01000000
|
||||
#define EDAT_COMPRESSED_FLAG 0x00000001
|
||||
#define EDAT_FLAG_0x02 0x00000002
|
||||
#define EDAT_FLAG_0x04 0x00000004
|
||||
#define EDAT_ENCRYPTED_KEY_FLAG 0x00000008
|
||||
#define EDAT_FLAG_0x10 0x00000010
|
||||
#define EDAT_FLAG_0x20 0x00000020
|
||||
|
@ -28,6 +31,6 @@ typedef struct
|
|||
int flags;
|
||||
int block_size;
|
||||
unsigned long long file_size;
|
||||
} EDAT_SDAT_HEADER;
|
||||
} EDAT_HEADER;
|
||||
|
||||
int DecryptEDAT(const std::string& input_file_name, const std::string& output_file_name, int mode, const std::string& rap_file_name, unsigned char *custom_klic, bool verbose);
|
|
@ -120,8 +120,8 @@ int Decrypt(rFile& pkg_f, rFile& dec_pkg_f, PKGHeader* m_header)
|
|||
{
|
||||
aes_crypt_ecb(&c, AES_ENCRYPT, iv, ctr+j*HASH_LEN);
|
||||
|
||||
be_t<u64> hi = be_t<u64>::MakeFromBE(*(u64*)&iv[0]);
|
||||
be_t<u64> lo = be_t<u64>::MakeFromBE(*(u64*)&iv[8]);
|
||||
be_t<u64> hi = *(be_t<u64>*)&iv[0];
|
||||
be_t<u64> lo = *(be_t<u64>*)&iv[8];
|
||||
lo++;
|
||||
|
||||
if (lo == 0)
|
||||
|
|
|
@ -10,6 +10,101 @@
|
|||
#include <wx/mstream.h>
|
||||
#include <wx/zstream.h>
|
||||
|
||||
|
||||
void WriteEhdr(rFile& f, Elf64_Ehdr& ehdr)
|
||||
{
|
||||
Write32(f, ehdr.e_magic);
|
||||
Write8(f, ehdr.e_class);
|
||||
Write8(f, ehdr.e_data);
|
||||
Write8(f, ehdr.e_curver);
|
||||
Write8(f, ehdr.e_os_abi);
|
||||
Write64(f, ehdr.e_abi_ver);
|
||||
Write16(f, ehdr.e_type);
|
||||
Write16(f, ehdr.e_machine);
|
||||
Write32(f, ehdr.e_version);
|
||||
Write64(f, ehdr.e_entry);
|
||||
Write64(f, ehdr.e_phoff);
|
||||
Write64(f, ehdr.e_shoff);
|
||||
Write32(f, ehdr.e_flags);
|
||||
Write16(f, ehdr.e_ehsize);
|
||||
Write16(f, ehdr.e_phentsize);
|
||||
Write16(f, ehdr.e_phnum);
|
||||
Write16(f, ehdr.e_shentsize);
|
||||
Write16(f, ehdr.e_shnum);
|
||||
Write16(f, ehdr.e_shstrndx);
|
||||
}
|
||||
void WritePhdr(rFile& f, Elf64_Phdr& phdr)
|
||||
{
|
||||
Write32(f, phdr.p_type);
|
||||
Write32(f, phdr.p_flags);
|
||||
Write64(f, phdr.p_offset);
|
||||
Write64(f, phdr.p_vaddr);
|
||||
Write64(f, phdr.p_paddr);
|
||||
Write64(f, phdr.p_filesz);
|
||||
Write64(f, phdr.p_memsz);
|
||||
Write64(f, phdr.p_align);
|
||||
}
|
||||
void WriteShdr(rFile& f, Elf64_Shdr& shdr)
|
||||
{
|
||||
Write32(f, shdr.sh_name);
|
||||
Write32(f, shdr.sh_type);
|
||||
Write64(f, shdr.sh_flags);
|
||||
Write64(f, shdr.sh_addr);
|
||||
Write64(f, shdr.sh_offset);
|
||||
Write64(f, shdr.sh_size);
|
||||
Write32(f, shdr.sh_link);
|
||||
Write32(f, shdr.sh_info);
|
||||
Write64(f, shdr.sh_addralign);
|
||||
Write64(f, shdr.sh_entsize);
|
||||
}
|
||||
void WriteEhdr(rFile& f, Elf32_Ehdr& ehdr)
|
||||
{
|
||||
Write32(f, ehdr.e_magic);
|
||||
Write8(f, ehdr.e_class);
|
||||
Write8(f, ehdr.e_data);
|
||||
Write8(f, ehdr.e_curver);
|
||||
Write8(f, ehdr.e_os_abi);
|
||||
Write64(f, ehdr.e_abi_ver);
|
||||
Write16(f, ehdr.e_type);
|
||||
Write16(f, ehdr.e_machine);
|
||||
Write32(f, ehdr.e_version);
|
||||
Write32(f, ehdr.e_entry);
|
||||
Write32(f, ehdr.e_phoff);
|
||||
Write32(f, ehdr.e_shoff);
|
||||
Write32(f, ehdr.e_flags);
|
||||
Write16(f, ehdr.e_ehsize);
|
||||
Write16(f, ehdr.e_phentsize);
|
||||
Write16(f, ehdr.e_phnum);
|
||||
Write16(f, ehdr.e_shentsize);
|
||||
Write16(f, ehdr.e_shnum);
|
||||
Write16(f, ehdr.e_shstrndx);
|
||||
}
|
||||
void WritePhdr(rFile& f, Elf32_Phdr& phdr)
|
||||
{
|
||||
Write32(f, phdr.p_type);
|
||||
Write32(f, phdr.p_offset);
|
||||
Write32(f, phdr.p_vaddr);
|
||||
Write32(f, phdr.p_paddr);
|
||||
Write32(f, phdr.p_filesz);
|
||||
Write32(f, phdr.p_memsz);
|
||||
Write32(f, phdr.p_flags);
|
||||
Write32(f, phdr.p_align);
|
||||
}
|
||||
void WriteShdr(rFile& f, Elf32_Shdr& shdr)
|
||||
{
|
||||
Write32(f, shdr.sh_name);
|
||||
Write32(f, shdr.sh_type);
|
||||
Write32(f, shdr.sh_flags);
|
||||
Write32(f, shdr.sh_addr);
|
||||
Write32(f, shdr.sh_offset);
|
||||
Write32(f, shdr.sh_size);
|
||||
Write32(f, shdr.sh_link);
|
||||
Write32(f, shdr.sh_info);
|
||||
Write32(f, shdr.sh_addralign);
|
||||
Write32(f, shdr.sh_entsize);
|
||||
}
|
||||
|
||||
|
||||
void AppInfo::Load(vfsStream& f)
|
||||
{
|
||||
authid = Read64(f);
|
||||
|
@ -813,10 +908,10 @@ bool SELFDecrypter::GetKeyFromRap(u8 *content_id, u8 *npdrm_key)
|
|||
u8 rap_key[0x10];
|
||||
memset(rap_key, 0, 0x10);
|
||||
|
||||
// Try to find a matching RAP file under dev_usb000.
|
||||
// Try to find a matching RAP file under exdata folder.
|
||||
std::string ci_str((const char *)content_id);
|
||||
// TODO: This shouldn't use current dir
|
||||
std::string rap_path("./dev_usb000/" + ci_str + ".rap");
|
||||
std::string pf_str("00000001"); // TODO: Allow multiple profiles. Use default for now.
|
||||
std::string rap_path("dev_hdd0/home/" + pf_str + "/exdata/" + ci_str + ".rap");
|
||||
|
||||
// Check if we have a valid RAP file.
|
||||
if (!rExists(rap_path))
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "Loader/SELF.h"
|
||||
#include "Loader/ELF64.h"
|
||||
#include "Loader/ELF32.h"
|
||||
#include "key_vault.h"
|
||||
|
@ -142,7 +141,8 @@ struct MetadataSectionHeader
|
|||
void Show();
|
||||
};
|
||||
|
||||
struct SectionHash {
|
||||
struct SectionHash
|
||||
{
|
||||
u8 sha1[20];
|
||||
u8 padding[12];
|
||||
u8 hmac_key[64];
|
||||
|
@ -183,6 +183,291 @@ struct SelfSection
|
|||
void Load(vfsStream& f);
|
||||
};
|
||||
|
||||
struct Elf32_Ehdr
|
||||
{
|
||||
u32 e_magic;
|
||||
u8 e_class;
|
||||
u8 e_data;
|
||||
u8 e_curver;
|
||||
u8 e_os_abi;
|
||||
u64 e_abi_ver;
|
||||
u16 e_type;
|
||||
u16 e_machine;
|
||||
u32 e_version;
|
||||
u32 e_entry;
|
||||
u32 e_phoff;
|
||||
u32 e_shoff;
|
||||
u32 e_flags;
|
||||
u16 e_ehsize;
|
||||
u16 e_phentsize;
|
||||
u16 e_phnum;
|
||||
u16 e_shentsize;
|
||||
u16 e_shnum;
|
||||
u16 e_shstrndx;
|
||||
void Show() {}
|
||||
bool IsLittleEndian() const
|
||||
{
|
||||
return e_data == 1;
|
||||
}
|
||||
|
||||
void Load(vfsStream& f)
|
||||
{
|
||||
e_magic = Read32(f);
|
||||
e_class = Read8(f);
|
||||
e_data = Read8(f);
|
||||
e_curver = Read8(f);
|
||||
e_os_abi = Read8(f);
|
||||
|
||||
if (IsLittleEndian())
|
||||
{
|
||||
e_abi_ver = Read64LE(f);
|
||||
e_type = Read16LE(f);
|
||||
e_machine = Read16LE(f);
|
||||
e_version = Read32LE(f);
|
||||
e_entry = Read32LE(f);
|
||||
e_phoff = Read32LE(f);
|
||||
e_shoff = Read32LE(f);
|
||||
e_flags = Read32LE(f);
|
||||
e_ehsize = Read16LE(f);
|
||||
e_phentsize = Read16LE(f);
|
||||
e_phnum = Read16LE(f);
|
||||
e_shentsize = Read16LE(f);
|
||||
e_shnum = Read16LE(f);
|
||||
e_shstrndx = Read16LE(f);
|
||||
}
|
||||
else
|
||||
{
|
||||
e_abi_ver = Read64(f);
|
||||
e_type = Read16(f);
|
||||
e_machine = Read16(f);
|
||||
e_version = Read32(f);
|
||||
e_entry = Read32(f);
|
||||
e_phoff = Read32(f);
|
||||
e_shoff = Read32(f);
|
||||
e_flags = Read32(f);
|
||||
e_ehsize = Read16(f);
|
||||
e_phentsize = Read16(f);
|
||||
e_phnum = Read16(f);
|
||||
e_shentsize = Read16(f);
|
||||
e_shnum = Read16(f);
|
||||
e_shstrndx = Read16(f);
|
||||
}
|
||||
}
|
||||
bool CheckMagic() const { return e_magic == 0x7F454C46; }
|
||||
u32 GetEntry() const { return e_entry; }
|
||||
};
|
||||
|
||||
struct Elf32_Shdr
|
||||
{
|
||||
u32 sh_name;
|
||||
u32 sh_type;
|
||||
u32 sh_flags;
|
||||
u32 sh_addr;
|
||||
u32 sh_offset;
|
||||
u32 sh_size;
|
||||
u32 sh_link;
|
||||
u32 sh_info;
|
||||
u32 sh_addralign;
|
||||
u32 sh_entsize;
|
||||
void Load(vfsStream& f)
|
||||
{
|
||||
sh_name = Read32(f);
|
||||
sh_type = Read32(f);
|
||||
sh_flags = Read32(f);
|
||||
sh_addr = Read32(f);
|
||||
sh_offset = Read32(f);
|
||||
sh_size = Read32(f);
|
||||
sh_link = Read32(f);
|
||||
sh_info = Read32(f);
|
||||
sh_addralign = Read32(f);
|
||||
sh_entsize = Read32(f);
|
||||
}
|
||||
void LoadLE(vfsStream& f)
|
||||
{
|
||||
f.Read(this, sizeof(*this));
|
||||
}
|
||||
void Show() {}
|
||||
};
|
||||
struct Elf32_Phdr
|
||||
{
|
||||
u32 p_type;
|
||||
u32 p_offset;
|
||||
u32 p_vaddr;
|
||||
u32 p_paddr;
|
||||
u32 p_filesz;
|
||||
u32 p_memsz;
|
||||
u32 p_flags;
|
||||
u32 p_align;
|
||||
void Load(vfsStream& f)
|
||||
{
|
||||
p_type = Read32(f);
|
||||
p_offset = Read32(f);
|
||||
p_vaddr = Read32(f);
|
||||
p_paddr = Read32(f);
|
||||
p_filesz = Read32(f);
|
||||
p_memsz = Read32(f);
|
||||
p_flags = Read32(f);
|
||||
p_align = Read32(f);
|
||||
}
|
||||
void LoadLE(vfsStream& f)
|
||||
{
|
||||
f.Read(this, sizeof(*this));
|
||||
}
|
||||
void Show() {}
|
||||
};
|
||||
|
||||
struct Elf64_Ehdr
|
||||
{
|
||||
u32 e_magic;
|
||||
u8 e_class;
|
||||
u8 e_data;
|
||||
u8 e_curver;
|
||||
u8 e_os_abi;
|
||||
u64 e_abi_ver;
|
||||
u16 e_type;
|
||||
u16 e_machine;
|
||||
u32 e_version;
|
||||
u64 e_entry;
|
||||
u64 e_phoff;
|
||||
u64 e_shoff;
|
||||
u32 e_flags;
|
||||
u16 e_ehsize;
|
||||
u16 e_phentsize;
|
||||
u16 e_phnum;
|
||||
u16 e_shentsize;
|
||||
u16 e_shnum;
|
||||
u16 e_shstrndx;
|
||||
void Load(vfsStream& f)
|
||||
{
|
||||
e_magic = Read32(f);
|
||||
e_class = Read8(f);
|
||||
e_data = Read8(f);
|
||||
e_curver = Read8(f);
|
||||
e_os_abi = Read8(f);
|
||||
e_abi_ver = Read64(f);
|
||||
e_type = Read16(f);
|
||||
e_machine = Read16(f);
|
||||
e_version = Read32(f);
|
||||
e_entry = Read64(f);
|
||||
e_phoff = Read64(f);
|
||||
e_shoff = Read64(f);
|
||||
e_flags = Read32(f);
|
||||
e_ehsize = Read16(f);
|
||||
e_phentsize = Read16(f);
|
||||
e_phnum = Read16(f);
|
||||
e_shentsize = Read16(f);
|
||||
e_shnum = Read16(f);
|
||||
e_shstrndx = Read16(f);
|
||||
}
|
||||
void Show() {}
|
||||
bool CheckMagic() const { return e_magic == 0x7F454C46; }
|
||||
u64 GetEntry() const { return e_entry; }
|
||||
};
|
||||
|
||||
struct Elf64_Shdr
|
||||
{
|
||||
u32 sh_name;
|
||||
u32 sh_type;
|
||||
u64 sh_flags;
|
||||
u64 sh_addr;
|
||||
u64 sh_offset;
|
||||
u64 sh_size;
|
||||
u32 sh_link;
|
||||
u32 sh_info;
|
||||
u64 sh_addralign;
|
||||
u64 sh_entsize;
|
||||
void Load(vfsStream& f)
|
||||
{
|
||||
sh_name = Read32(f);
|
||||
sh_type = Read32(f);
|
||||
sh_flags = Read64(f);
|
||||
sh_addr = Read64(f);
|
||||
sh_offset = Read64(f);
|
||||
sh_size = Read64(f);
|
||||
sh_link = Read32(f);
|
||||
sh_info = Read32(f);
|
||||
sh_addralign = Read64(f);
|
||||
sh_entsize = Read64(f);
|
||||
}
|
||||
void Show(){}
|
||||
};
|
||||
|
||||
struct Elf64_Phdr
|
||||
{
|
||||
u32 p_type;
|
||||
u32 p_flags;
|
||||
u64 p_offset;
|
||||
u64 p_vaddr;
|
||||
u64 p_paddr;
|
||||
u64 p_filesz;
|
||||
u64 p_memsz;
|
||||
u64 p_align;
|
||||
void Load(vfsStream& f)
|
||||
{
|
||||
p_type = Read32(f);
|
||||
p_flags = Read32(f);
|
||||
p_offset = Read64(f);
|
||||
p_vaddr = Read64(f);
|
||||
p_paddr = Read64(f);
|
||||
p_filesz = Read64(f);
|
||||
p_memsz = Read64(f);
|
||||
p_align = Read64(f);
|
||||
}
|
||||
void Show(){}
|
||||
};
|
||||
|
||||
struct SceHeader
|
||||
{
|
||||
u32 se_magic;
|
||||
u32 se_hver;
|
||||
u16 se_flags;
|
||||
u16 se_type;
|
||||
u32 se_meta;
|
||||
u64 se_hsize;
|
||||
u64 se_esize;
|
||||
void Load(vfsStream& f)
|
||||
{
|
||||
se_magic = Read32(f);
|
||||
se_hver = Read32(f);
|
||||
se_flags = Read16(f);
|
||||
se_type = Read16(f);
|
||||
se_meta = Read32(f);
|
||||
se_hsize = Read64(f);
|
||||
se_esize = Read64(f);
|
||||
}
|
||||
void Show(){}
|
||||
bool CheckMagic() const { return se_magic == 0x53434500; }
|
||||
};
|
||||
|
||||
struct SelfHeader
|
||||
{
|
||||
u64 se_htype;
|
||||
u64 se_appinfooff;
|
||||
u64 se_elfoff;
|
||||
u64 se_phdroff;
|
||||
u64 se_shdroff;
|
||||
u64 se_secinfoff;
|
||||
u64 se_sceveroff;
|
||||
u64 se_controloff;
|
||||
u64 se_controlsize;
|
||||
u64 pad;
|
||||
void Load(vfsStream& f)
|
||||
{
|
||||
se_htype = Read64(f);
|
||||
se_appinfooff = Read64(f);
|
||||
se_elfoff = Read64(f);
|
||||
se_phdroff = Read64(f);
|
||||
se_shdroff = Read64(f);
|
||||
se_secinfoff = Read64(f);
|
||||
se_sceveroff = Read64(f);
|
||||
se_controloff = Read64(f);
|
||||
se_controlsize = Read64(f);
|
||||
pad = Read64(f);
|
||||
}
|
||||
void Show(){}
|
||||
};
|
||||
|
||||
|
||||
class SELFDecrypter
|
||||
{
|
||||
// Main SELF file stream.
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
#include "stdafx.h"
|
||||
#include "aes.h"
|
||||
#include "sha1.h"
|
||||
#include "utils.h"
|
||||
// Copyright (C) 2014 Hykem <hykem@hotmail.com>
|
||||
// Licensed under the terms of the GNU GPL, version 3
|
||||
// http://www.gnu.org/licenses/gpl-3.0.txt
|
||||
|
||||
// Endian swap auxiliary functions.
|
||||
#include "stdafx.h"
|
||||
#include "utils.h"
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
// Auxiliary functions (endian swap, xor and prng).
|
||||
u16 swap16(u16 i)
|
||||
{
|
||||
return ((i & 0xFF00) >> 8) | ((i & 0xFF) << 8);
|
||||
|
@ -22,7 +26,7 @@ u64 swap64(u64 i)
|
|||
((i & 0x00ff000000000000) >> 40) | ((i & 0xff00000000000000) >> 56);
|
||||
}
|
||||
|
||||
void xor_(unsigned char *dest, unsigned char *src1, unsigned char *src2, int size)
|
||||
void xor_key(unsigned char *dest, unsigned char *src1, unsigned char *src2, int size)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < size; i++)
|
||||
|
@ -31,10 +35,24 @@ void xor_(unsigned char *dest, unsigned char *src1, unsigned char *src2, int siz
|
|||
}
|
||||
}
|
||||
|
||||
void prng(unsigned char *dest, int size)
|
||||
{
|
||||
unsigned char *buffer = new unsigned char[size];
|
||||
srand((u32)time(0));
|
||||
|
||||
int i;
|
||||
for(i = 0; i < size; i++)
|
||||
buffer[i] = (unsigned char)(rand() & 0xFF);
|
||||
|
||||
memcpy(dest, buffer, size);
|
||||
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
// Hex string conversion auxiliary functions.
|
||||
u64 hex_to_u64(const char* hex_str)
|
||||
{
|
||||
u32 length = (u32)strlen(hex_str);
|
||||
u32 length = (u32) strlen(hex_str);
|
||||
u64 tmp = 0;
|
||||
u64 result = 0;
|
||||
char c;
|
||||
|
@ -56,19 +74,19 @@ u64 hex_to_u64(const char* hex_str)
|
|||
return result;
|
||||
}
|
||||
|
||||
void hex_to_bytes(unsigned char *data, const char *hex_str)
|
||||
void hex_to_bytes(unsigned char *data, const char *hex_str, unsigned int str_length)
|
||||
{
|
||||
u32 str_length = (u32)strlen(hex_str);
|
||||
u32 data_length = str_length / 2;
|
||||
u32 strn_length = (str_length > 0) ? str_length : (u32) strlen(hex_str);
|
||||
u32 data_length = strn_length / 2;
|
||||
char tmp_buf[3] = {0, 0, 0};
|
||||
|
||||
// Don't convert if the string length is odd.
|
||||
if (!(str_length % 2))
|
||||
if (!(strn_length % 2))
|
||||
{
|
||||
u8 *out = (u8 *) malloc (str_length * sizeof(u8));
|
||||
u8 *out = (u8 *)malloc(strn_length * sizeof(u8));
|
||||
u8 *pos = out;
|
||||
|
||||
while (str_length--)
|
||||
while (strn_length--)
|
||||
{
|
||||
tmp_buf[0] = *hex_str++;
|
||||
tmp_buf[1] = *hex_str++;
|
||||
|
@ -81,6 +99,23 @@ void hex_to_bytes(unsigned char *data, const char *hex_str)
|
|||
}
|
||||
}
|
||||
|
||||
bool is_hex(const char* hex_str, unsigned int str_length)
|
||||
{
|
||||
static const char hex_chars[] = "0123456789abcdefABCDEF";
|
||||
|
||||
if (hex_str == NULL)
|
||||
return false;
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0; i < str_length; i++)
|
||||
{
|
||||
if (strchr(hex_chars, hex_str[i]) == 0)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Crypto functions (AES128-CBC, AES128-ECB, SHA1-HMAC and AES-CMAC).
|
||||
void aescbc128_decrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, int len)
|
||||
{
|
||||
|
@ -92,6 +127,16 @@ void aescbc128_decrypt(unsigned char *key, unsigned char *iv, unsigned char *in,
|
|||
memset(iv, 0, 0x10);
|
||||
}
|
||||
|
||||
void aescbc128_encrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, int len)
|
||||
{
|
||||
aes_context ctx;
|
||||
aes_setkey_enc(&ctx, key, 128);
|
||||
aes_crypt_cbc(&ctx, AES_ENCRYPT, len, iv, in, out);
|
||||
|
||||
// Reset the IV.
|
||||
memset(iv, 0, 0x10);
|
||||
}
|
||||
|
||||
void aesecb128_encrypt(unsigned char *key, unsigned char *in, unsigned char *out)
|
||||
{
|
||||
aes_context ctx;
|
||||
|
@ -99,13 +144,13 @@ void aesecb128_encrypt(unsigned char *key, unsigned char *in, unsigned char *out
|
|||
aes_crypt_ecb(&ctx, AES_ENCRYPT, in, out);
|
||||
}
|
||||
|
||||
bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash)
|
||||
bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash, int hash_len)
|
||||
{
|
||||
unsigned char *out = new unsigned char[key_len];
|
||||
|
||||
sha1_hmac(key, key_len, in, in_len, out);
|
||||
|
||||
for (int i = 0; i < 0x10; i++)
|
||||
for (int i = 0; i < hash_len; i++)
|
||||
{
|
||||
if (out[i] != hash[i])
|
||||
{
|
||||
|
@ -119,7 +164,12 @@ bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int i
|
|||
return true;
|
||||
}
|
||||
|
||||
bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash)
|
||||
void hmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash)
|
||||
{
|
||||
sha1_hmac(key, key_len, in, in_len, hash);
|
||||
}
|
||||
|
||||
bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash, int hash_len)
|
||||
{
|
||||
unsigned char *out = new unsigned char[key_len];
|
||||
|
||||
|
@ -127,7 +177,7 @@ bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int i
|
|||
aes_setkey_enc(&ctx, key, 128);
|
||||
aes_cmac(&ctx, in_len, in, out);
|
||||
|
||||
for (int i = 0; i < key_len; i++)
|
||||
for (int i = 0; i < hash_len; i++)
|
||||
{
|
||||
if (out[i] != hash[i])
|
||||
{
|
||||
|
@ -141,9 +191,20 @@ bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int i
|
|||
return true;
|
||||
}
|
||||
|
||||
#include "lz.h"
|
||||
// Reverse-engineered custom Lempel–Ziv–Markov based compression (unknown variant of LZRC).
|
||||
int lz_decompress(unsigned char *out, unsigned char *in, unsigned int size)
|
||||
void cmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash)
|
||||
{
|
||||
return decompress(out,in,size);
|
||||
aes_context ctx;
|
||||
aes_setkey_enc(&ctx, key, 128);
|
||||
aes_cmac(&ctx, in_len, in, hash);
|
||||
}
|
||||
|
||||
char* extract_file_name(const char* file_path, char real_file_name[MAX_PATH])
|
||||
{
|
||||
size_t file_path_len = strlen(file_path);
|
||||
const char* p = strrchr(file_path, '/');
|
||||
if (!p) p = strrchr(file_path, '\\');
|
||||
if (p) file_path_len = file_path + file_path_len - p - 1;
|
||||
strncpy(real_file_name, p ? (p + 1) : file_path, file_path_len + 1);
|
||||
|
||||
return real_file_name;
|
||||
}
|
|
@ -1,20 +1,35 @@
|
|||
#pragma once
|
||||
|
||||
// Auxiliary functions (endian swap and xor).
|
||||
// Copyright (C) 2014 Hykem <hykem@hotmail.com>
|
||||
// Licensed under the terms of the GNU GPL, version 3
|
||||
// http://www.gnu.org/licenses/gpl-3.0.txt
|
||||
|
||||
#define MAX_PATH 4096
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "aes.h"
|
||||
#include "sha1.h"
|
||||
#include "lz.h"
|
||||
#include "ec.h"
|
||||
|
||||
// Auxiliary functions (endian swap, xor, prng and file name).
|
||||
u16 swap16(u16 i);
|
||||
u32 swap32(u32 i);
|
||||
u64 swap64(u64 i);
|
||||
void xor_(unsigned char *dest, unsigned char *src1, unsigned char *src2, int size);
|
||||
void xor_key(unsigned char *dest, unsigned char *src1, unsigned char *src2, int size);
|
||||
void prng(unsigned char *dest, int size);
|
||||
char* extract_file_name(const char* file_path, char real_file_name[MAX_PATH]);
|
||||
|
||||
// Hex string conversion auxiliary functions.
|
||||
u64 hex_to_u64(const char* hex_str);
|
||||
void hex_to_bytes(unsigned char *data, const char *hex_str);
|
||||
void hex_to_bytes(unsigned char *data, const char *hex_str, unsigned int str_length);
|
||||
bool is_hex(const char* hex_str, unsigned int str_length);
|
||||
|
||||
// Crypto functions (AES128-CBC, AES128-ECB, SHA1-HMAC and AES-CMAC).
|
||||
void aescbc128_decrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, int len);
|
||||
void aescbc128_encrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, int len);
|
||||
void aesecb128_encrypt(unsigned char *key, unsigned char *in, unsigned char *out);
|
||||
bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash);
|
||||
bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash);
|
||||
|
||||
// Reverse-engineered custom Lempel–Ziv–Markov based compression (unknown variant of LZRC).
|
||||
int lz_decompress(unsigned char *out, unsigned char *in, unsigned int size);
|
||||
bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash, int hash_len);
|
||||
void hmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash);
|
||||
bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash, int hash_len);
|
||||
void cmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash);
|
|
@ -13,125 +13,23 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
u32 branchTarget(u32 imm)
|
||||
{
|
||||
return imm << 1;
|
||||
}
|
||||
|
||||
virtual u8 DecodeMemory(const u32 address)
|
||||
{
|
||||
using namespace ARMv7_opcodes;
|
||||
const u16 code0 = vm::psv::read16(address);
|
||||
const u16 code1 = vm::psv::read16(address + 2);
|
||||
const u32 code0 = vm::psv::read16(address & ~1);
|
||||
const u32 code1 = vm::psv::read16(address + 2 & ~1);
|
||||
const u32 data = code0 << 16 | code1;
|
||||
const u32 arg = address & 1 ? code1 << 16 | code0 : data;
|
||||
|
||||
switch(code0 >> 12) //15 - 12
|
||||
for (auto& opcode : ARMv7_opcode_table)
|
||||
{
|
||||
case T1_CBZ:
|
||||
switch((code0 >> 10) & 0x1)
|
||||
if ((opcode.type < A1) == ((address & 1) == 0) && (arg & opcode.mask) == opcode.code)
|
||||
{
|
||||
case 0:
|
||||
switch((code0 >> 8) & 0x1)
|
||||
{
|
||||
case 1:
|
||||
m_op.CBZ((code0 >> 11) & 0x1, branchTarget((((code0 >> 9) & 0x1) << 5) | ((code0 >> 3) & 0x1f)), code0 & 0x7, 2);
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case T1_B:
|
||||
m_op.B((code0 >> 8) & 0xf, branchTarget(code0 & 0xff), 2);
|
||||
return 2;
|
||||
}
|
||||
|
||||
switch(code0 >> 11) //15 - 11
|
||||
{
|
||||
case T2_B:
|
||||
m_op.B(0xf, branchTarget(code0 & 0xfff), 2);
|
||||
return 2;
|
||||
|
||||
case T3_B:
|
||||
{
|
||||
u8 S = (code0 >> 10) & 0x1;
|
||||
u8 J1 = (code1 >> 13) & 0x1;
|
||||
u8 J2 = (code1 >> 11) & 0x1;
|
||||
u8 I1 = 1 - (J1 ^ S);
|
||||
u8 I2 = 1 - (J2 ^ S);
|
||||
u16 imm11 = code1 & 0x7ff;
|
||||
u32 imm32 = 0;
|
||||
|
||||
switch(code1 >> 14)
|
||||
{
|
||||
case 2: //B
|
||||
{
|
||||
u8 cond;
|
||||
switch((code1 >> 12) & 0x1)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
cond = (code0 >> 6) & 0xf;
|
||||
u32 imm6 = code0 & 0x3f;
|
||||
imm32 = sign<19, u32>((S << 19) | (I1 << 18) | (I2 << 17) | (imm6 << 11) | imm11);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
cond = 0xf;
|
||||
u32 imm10 = code0 & 0x7ff;
|
||||
imm32 = sign<23, u32>((S << 23) | (I1 << 22) | (I2 << 21) | (imm10 << 11) | imm11);
|
||||
break;
|
||||
}
|
||||
|
||||
m_op.B(cond, branchTarget(imm32), 4);
|
||||
}
|
||||
return 4;
|
||||
|
||||
case 3: //BL
|
||||
switch((code1 >> 12) & 0x1)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case 1:
|
||||
u32 imm10 = code0 & 0x7ff;
|
||||
imm32 = sign<23, u32>((S << 23) | (I1 << 22) | (I2 << 21) | (imm10 << 11) | imm11);
|
||||
m_op.BL(branchTarget(imm32), 4);
|
||||
return 4;
|
||||
}
|
||||
break;
|
||||
(m_op.*opcode.func)(opcode.length == 2 ? code0 : arg, opcode.type);
|
||||
return opcode.length;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch(code0 >> 9)
|
||||
{
|
||||
case T1_PUSH:
|
||||
m_op.PUSH((((code0 >> 8) & 0x1) << 14) | (code0 & 0xff));
|
||||
return 2;
|
||||
|
||||
case T1_POP:
|
||||
m_op.POP((((code0 >> 8) & 0x1) << 15) | (code0 & 0xff));
|
||||
return 2;
|
||||
}
|
||||
|
||||
switch(code0)
|
||||
{
|
||||
case T2_PUSH:
|
||||
m_op.PUSH(code1);
|
||||
return 4;
|
||||
|
||||
case T2_POP:
|
||||
m_op.POP(code1);
|
||||
return 4;
|
||||
|
||||
case T1_NOP:
|
||||
m_op.NOP();
|
||||
return 2;
|
||||
}
|
||||
|
||||
m_op.UNK(code0, code1);
|
||||
return 2;
|
||||
m_op.UNK(data);
|
||||
return address & 1 ? 4 : 2;
|
||||
}
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -45,50 +45,276 @@ protected:
|
|||
return regs_str;
|
||||
}
|
||||
|
||||
void NULL_OP()
|
||||
{
|
||||
Write("null");
|
||||
}
|
||||
virtual void UNK(const u32 data);
|
||||
|
||||
void PUSH(u16 regs_list)
|
||||
{
|
||||
Write(fmt::Format("push {%s}", GetRegsListString(regs_list).c_str()));
|
||||
}
|
||||
virtual void NULL_OP(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
void POP(u16 regs_list)
|
||||
{
|
||||
Write(fmt::Format("pop {%s}", GetRegsListString(regs_list).c_str()));
|
||||
}
|
||||
virtual void HACK(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
void NOP()
|
||||
{
|
||||
Write("nop");
|
||||
}
|
||||
virtual void ADC_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void ADC_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void ADC_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
void B(u8 cond, u32 imm, u8 intstr_size)
|
||||
{
|
||||
if((cond & 0xe) == 0xe)
|
||||
{
|
||||
Write(fmt::Format("b 0x%x", DisAsmBranchTarget(imm) + intstr_size));
|
||||
}
|
||||
else
|
||||
{
|
||||
Write(fmt::Format("b[%s] 0x%x", g_arm_cond_name[cond], DisAsmBranchTarget(imm) + intstr_size));
|
||||
}
|
||||
}
|
||||
virtual void ADD_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void ADD_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void ADD_RSR(const u32 data, const ARMv7_encoding type);
|
||||
virtual void ADD_SPI(const u32 data, const ARMv7_encoding type);
|
||||
virtual void ADD_SPR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void CBZ(u8 op, u32 imm, u8 rn, u8 intstr_size)
|
||||
{
|
||||
Write(fmt::Format("cb%sz 0x%x,%s", (op ? "n" : ""), DisAsmBranchTarget(imm) + intstr_size, g_arm_reg_name[rn]));
|
||||
}
|
||||
virtual void ADR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
void BL(u32 imm, u8 intstr_size)
|
||||
{
|
||||
Write(fmt::Format("bl 0x%x", DisAsmBranchTarget(imm) + intstr_size));
|
||||
}
|
||||
virtual void AND_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void AND_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void AND_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
void UNK(const u16 code0, const u16 code1)
|
||||
{
|
||||
Write(fmt::Format("Unknown/Illegal opcode! (0x%04x : 0x%04x)", code0, code1));
|
||||
}
|
||||
virtual void ASR_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void ASR_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void B(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void BFC(const u32 data, const ARMv7_encoding type);
|
||||
virtual void BFI(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void BIC_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void BIC_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void BIC_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void BKPT(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void BL(const u32 data, const ARMv7_encoding type);
|
||||
virtual void BLX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void BX(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void CB_Z(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void CLZ(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void CMN_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void CMN_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void CMN_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void CMP_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void CMP_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void CMP_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void EOR_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void EOR_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void EOR_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void IT(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void LDM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDMDA(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDMDB(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDMIB(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void LDR_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDR_LIT(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDR_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void LDRB_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDRB_LIT(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDRB_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void LDRD_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDRD_LIT(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDRD_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void LDRH_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDRH_LIT(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDRH_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void LDRSB_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDRSB_LIT(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDRSB_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void LDRSH_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDRSH_LIT(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDRSH_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void LSL_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LSL_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void LSR_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LSR_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void MLA(const u32 data, const ARMv7_encoding type);
|
||||
virtual void MLS(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void MOV_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void MOV_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void MOVT(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void MRS(const u32 data, const ARMv7_encoding type);
|
||||
virtual void MSR_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void MSR_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void MUL(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void MVN_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void MVN_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void MVN_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void NOP(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void ORN_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void ORN_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void ORR_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void ORR_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void ORR_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void PKH(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void POP(const u32 data, const ARMv7_encoding type);
|
||||
virtual void PUSH(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void QADD(const u32 data, const ARMv7_encoding type);
|
||||
virtual void QADD16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void QADD8(const u32 data, const ARMv7_encoding type);
|
||||
virtual void QASX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void QDADD(const u32 data, const ARMv7_encoding type);
|
||||
virtual void QDSUB(const u32 data, const ARMv7_encoding type);
|
||||
virtual void QSAX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void QSUB(const u32 data, const ARMv7_encoding type);
|
||||
virtual void QSUB16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void QSUB8(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void RBIT(const u32 data, const ARMv7_encoding type);
|
||||
virtual void REV(const u32 data, const ARMv7_encoding type);
|
||||
virtual void REV16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void REVSH(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void ROR_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void ROR_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void RRX(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void RSB_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void RSB_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void RSB_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void RSC_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void RSC_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void RSC_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void SADD16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SADD8(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SASX(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void SBC_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SBC_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SBC_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void SBFX(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void SDIV(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void SEL(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void SHADD16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SHADD8(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SHASX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SHSAX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SHSUB16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SHSUB8(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void SMLA__(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMLAD(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMLAL(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMLAL__(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMLALD(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMLAW_(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMLSD(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMLSLD(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMMLA(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMMLS(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMMUL(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMUAD(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMUL__(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMULL(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMULW_(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMUSD(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void SSAT(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SSAT16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SSAX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SSUB16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SSUB8(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void STM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void STMDA(const u32 data, const ARMv7_encoding type);
|
||||
virtual void STMDB(const u32 data, const ARMv7_encoding type);
|
||||
virtual void STMIB(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void STR_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void STR_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void STRB_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void STRB_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void STRD_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void STRD_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void STRH_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void STRH_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void SUB_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SUB_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SUB_RSR(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SUB_SPI(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SUB_SPR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void SVC(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void SXTAB(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SXTAB16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SXTAH(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SXTB(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SXTB16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SXTH(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void TB_(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void TEQ_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void TEQ_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void TEQ_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void TST_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void TST_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void TST_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void UADD16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UADD8(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UASX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UBFX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UDIV(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UHADD16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UHADD8(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UHASX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UHSAX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UHSUB16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UHSUB8(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UMAAL(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UMLAL(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UMULL(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UQADD16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UQADD8(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UQASX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UQSAX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UQSUB16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UQSUB8(const u32 data, const ARMv7_encoding type);
|
||||
virtual void USAD8(const u32 data, const ARMv7_encoding type);
|
||||
virtual void USADA8(const u32 data, const ARMv7_encoding type);
|
||||
virtual void USAT(const u32 data, const ARMv7_encoding type);
|
||||
virtual void USAT16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void USAX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void USUB16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void USUB8(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UXTAB(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UXTAB16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UXTAH(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UXTB(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UXTB16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UXTH(const u32 data, const ARMv7_encoding type);
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,7 +10,7 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
enum SRType
|
||||
enum SRType : u32
|
||||
{
|
||||
SRType_None,
|
||||
SRType_LSL,
|
||||
|
@ -93,7 +93,7 @@ public:
|
|||
return len - 1 - HighestSetBit(x, len);
|
||||
}
|
||||
|
||||
SRType DecodeImmShift(u8 type, u8 imm5, uint* shift_n)
|
||||
SRType DecodeImmShift(u32 type, u32 imm5, u32* shift_n)
|
||||
{
|
||||
SRType shift_t = SRType_None;
|
||||
|
||||
|
@ -217,7 +217,7 @@ public:
|
|||
return value;
|
||||
}
|
||||
|
||||
template<typename T> T Shift(T value, SRType type, uint amount, bool carry_in)
|
||||
template<typename T> T Shift(T value, SRType type, u32 amount, bool carry_in)
|
||||
{
|
||||
bool carry_out;
|
||||
return Shift_C(value, type, amount, carry_in, carry_out);
|
||||
|
@ -225,15 +225,50 @@ public:
|
|||
|
||||
template<typename T> T AddWithCarry(T x, T y, bool carry_in, bool& carry_out, bool& overflow)
|
||||
{
|
||||
uint unsigned_sum = (uint)x + (uint)y + (uint)carry_in;
|
||||
int signed_sum = (int)x + (int)y + (int)carry_in;
|
||||
T result = unsigned_sum & ~(T(1) << (sizeof(T) - 1));
|
||||
carry_out = (uint)result != unsigned_sum;
|
||||
overflow = (int)result != signed_sum;
|
||||
const T sign_mask = (T)1 << (sizeof(T) - 1);
|
||||
|
||||
T result = x + y;
|
||||
carry_out = ((x & y) | ((x ^ y) & ~result)) & sign_mask;
|
||||
overflow = (x ^ result) & (y ^ result) & sign_mask;
|
||||
if (carry_in)
|
||||
{
|
||||
result += 1;
|
||||
carry_out ^= (result == 0);
|
||||
overflow ^= (result == sign_mask);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ConditionPassed(u8 cond) const
|
||||
u32 ThumbExpandImm_C(u32 imm12, bool carry_in, bool& carry_out)
|
||||
{
|
||||
if ((imm12 & 0xc00) >> 10)
|
||||
{
|
||||
u32 unrotated_value = (imm12 & 0x7f) | 0x80;
|
||||
|
||||
return ROR_C(unrotated_value, (imm12 & 0xf80) >> 7, carry_out);
|
||||
}
|
||||
else
|
||||
{
|
||||
carry_out = carry_in;
|
||||
|
||||
u32 imm8 = imm12 & 0xff;
|
||||
switch ((imm12 & 0x300) >> 8)
|
||||
{
|
||||
case 0: return imm8;
|
||||
case 1: return imm8 << 16 | imm8;
|
||||
case 2: return imm8 << 24 | imm8 << 8;
|
||||
default: return imm8 << 24 | imm8 << 16 | imm8 << 8 | imm8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
u32 ThumbExpandImm(u32 imm12)
|
||||
{
|
||||
bool carry = CPU.APSR.C;
|
||||
return ThumbExpandImm_C(imm12, carry, carry);
|
||||
}
|
||||
|
||||
bool ConditionPassed(u32 cond) const
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
|
@ -258,65 +293,276 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
void NULL_OP()
|
||||
{
|
||||
LOG_ERROR(HLE, "null");
|
||||
Emu.Pause();
|
||||
}
|
||||
virtual void UNK(const u32 data);
|
||||
|
||||
void NOP()
|
||||
{
|
||||
}
|
||||
virtual void NULL_OP(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
void PUSH(u16 regs_list)
|
||||
{
|
||||
for(u16 mask=0x1, i=0; mask; mask <<= 1, i++)
|
||||
{
|
||||
if(regs_list & mask)
|
||||
{
|
||||
CPU.SP -= 4;
|
||||
vm::psv::write32(CPU.SP, CPU.read_gpr(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void HACK(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
void POP(u16 regs_list)
|
||||
{
|
||||
for(u16 mask=(0x1 << 15), i=15; mask; mask >>= 1, i--)
|
||||
{
|
||||
if(regs_list & mask)
|
||||
{
|
||||
CPU.write_gpr(i, vm::psv::read32(CPU.SP));
|
||||
CPU.SP += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void ADC_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void ADC_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void ADC_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
void B(u8 cond, u32 imm, u8 intstr_size)
|
||||
{
|
||||
if(ConditionPassed(cond))
|
||||
{
|
||||
CPU.SetBranch(CPU.PC + intstr_size + imm);
|
||||
}
|
||||
}
|
||||
virtual void ADD_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void ADD_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void ADD_RSR(const u32 data, const ARMv7_encoding type);
|
||||
virtual void ADD_SPI(const u32 data, const ARMv7_encoding type);
|
||||
virtual void ADD_SPR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
void CBZ(u8 op, u32 imm, u8 rn, u8 intstr_size)
|
||||
{
|
||||
if((CPU.GPR[rn] == 0) ^ op)
|
||||
{
|
||||
CPU.SetBranch(CPU.PC + intstr_size + imm);
|
||||
}
|
||||
}
|
||||
virtual void ADR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
void BL(u32 imm, u8 intstr_size)
|
||||
{
|
||||
CPU.LR = (CPU.PC + intstr_size) | 1;
|
||||
CPU.SetBranch(CPU.PC + intstr_size + imm);
|
||||
}
|
||||
virtual void AND_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void AND_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void AND_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
void UNK(const u16 code0, const u16 code1)
|
||||
{
|
||||
LOG_ERROR(HLE, "Unknown/Illegal opcode! (0x%04x : 0x%04x)", code0, code1);
|
||||
Emu.Pause();
|
||||
}
|
||||
virtual void ASR_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void ASR_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void B(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void BFC(const u32 data, const ARMv7_encoding type);
|
||||
virtual void BFI(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void BIC_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void BIC_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void BIC_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void BKPT(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void BL(const u32 data, const ARMv7_encoding type);
|
||||
virtual void BLX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void BX(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void CB_Z(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void CLZ(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void CMN_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void CMN_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void CMN_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void CMP_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void CMP_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void CMP_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void EOR_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void EOR_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void EOR_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void IT(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void LDM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDMDA(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDMDB(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDMIB(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void LDR_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDR_LIT(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDR_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void LDRB_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDRB_LIT(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDRB_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void LDRD_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDRD_LIT(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDRD_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void LDRH_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDRH_LIT(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDRH_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void LDRSB_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDRSB_LIT(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDRSB_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void LDRSH_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDRSH_LIT(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LDRSH_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void LSL_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LSL_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void LSR_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void LSR_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void MLA(const u32 data, const ARMv7_encoding type);
|
||||
virtual void MLS(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void MOV_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void MOV_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void MOVT(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void MRS(const u32 data, const ARMv7_encoding type);
|
||||
virtual void MSR_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void MSR_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void MUL(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void MVN_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void MVN_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void MVN_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void NOP(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void ORN_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void ORN_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void ORR_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void ORR_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void ORR_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void PKH(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void POP(const u32 data, const ARMv7_encoding type);
|
||||
virtual void PUSH(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void QADD(const u32 data, const ARMv7_encoding type);
|
||||
virtual void QADD16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void QADD8(const u32 data, const ARMv7_encoding type);
|
||||
virtual void QASX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void QDADD(const u32 data, const ARMv7_encoding type);
|
||||
virtual void QDSUB(const u32 data, const ARMv7_encoding type);
|
||||
virtual void QSAX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void QSUB(const u32 data, const ARMv7_encoding type);
|
||||
virtual void QSUB16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void QSUB8(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void RBIT(const u32 data, const ARMv7_encoding type);
|
||||
virtual void REV(const u32 data, const ARMv7_encoding type);
|
||||
virtual void REV16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void REVSH(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void ROR_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void ROR_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void RRX(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void RSB_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void RSB_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void RSB_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void RSC_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void RSC_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void RSC_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void SADD16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SADD8(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SASX(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void SBC_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SBC_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SBC_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void SBFX(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void SDIV(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void SEL(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void SHADD16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SHADD8(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SHASX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SHSAX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SHSUB16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SHSUB8(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void SMLA__(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMLAD(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMLAL(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMLAL__(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMLALD(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMLAW_(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMLSD(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMLSLD(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMMLA(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMMLS(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMMUL(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMUAD(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMUL__(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMULL(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMULW_(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SMUSD(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void SSAT(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SSAT16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SSAX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SSUB16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SSUB8(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void STM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void STMDA(const u32 data, const ARMv7_encoding type);
|
||||
virtual void STMDB(const u32 data, const ARMv7_encoding type);
|
||||
virtual void STMIB(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void STR_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void STR_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void STRB_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void STRB_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void STRD_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void STRD_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void STRH_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void STRH_REG(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void SUB_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SUB_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SUB_RSR(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SUB_SPI(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SUB_SPR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void SVC(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void SXTAB(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SXTAB16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SXTAH(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SXTB(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SXTB16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void SXTH(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void TB_(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void TEQ_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void TEQ_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void TEQ_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void TST_IMM(const u32 data, const ARMv7_encoding type);
|
||||
virtual void TST_REG(const u32 data, const ARMv7_encoding type);
|
||||
virtual void TST_RSR(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
virtual void UADD16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UADD8(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UASX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UBFX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UDIV(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UHADD16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UHADD8(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UHASX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UHSAX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UHSUB16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UHSUB8(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UMAAL(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UMLAL(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UMULL(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UQADD16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UQADD8(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UQASX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UQSAX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UQSUB16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UQSUB8(const u32 data, const ARMv7_encoding type);
|
||||
virtual void USAD8(const u32 data, const ARMv7_encoding type);
|
||||
virtual void USADA8(const u32 data, const ARMv7_encoding type);
|
||||
virtual void USAT(const u32 data, const ARMv7_encoding type);
|
||||
virtual void USAT16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void USAX(const u32 data, const ARMv7_encoding type);
|
||||
virtual void USUB16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void USUB8(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UXTAB(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UXTAB16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UXTAH(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UXTB(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UXTB16(const u32 data, const ARMv7_encoding type);
|
||||
virtual void UXTH(const u32 data, const ARMv7_encoding type);
|
||||
};
|
||||
|
|
|
@ -32,18 +32,686 @@ namespace ARMv7_opcodes
|
|||
};
|
||||
}
|
||||
|
||||
enum ARMv7_encoding
|
||||
{
|
||||
T1,
|
||||
T2,
|
||||
T3,
|
||||
T4,
|
||||
A1,
|
||||
A2,
|
||||
};
|
||||
|
||||
class ARMv7Opcodes
|
||||
{
|
||||
public:
|
||||
virtual void NULL_OP() = 0;
|
||||
virtual void NOP() = 0;
|
||||
virtual void UNK(const u32 data) = 0;
|
||||
|
||||
virtual void PUSH(u16 regs_list) = 0;
|
||||
virtual void POP(u16 regs_list) = 0;
|
||||
virtual void NULL_OP(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void B(u8 cond, u32 imm, u8 intstr_size) = 0;
|
||||
virtual void CBZ(u8 op, u32 imm, u8 rn, u8 intstr_size) = 0;
|
||||
virtual void BL(u32 imm, u8 intstr_size)=0;
|
||||
virtual void HACK(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void UNK(const u16 code0, const u16 code1) = 0;
|
||||
virtual void ADC_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void ADC_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void ADC_RSR(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void ADD_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void ADD_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void ADD_RSR(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void ADD_SPI(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void ADD_SPR(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void ADR(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void AND_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void AND_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void AND_RSR(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void ASR_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void ASR_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void B(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void BFC(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void BFI(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void BIC_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void BIC_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void BIC_RSR(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void BKPT(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void BL(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void BLX(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void BX(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void CB_Z(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void CLZ(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void CMN_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void CMN_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void CMN_RSR(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void CMP_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void CMP_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void CMP_RSR(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void EOR_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void EOR_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void EOR_RSR(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void IT(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void LDM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void LDMDA(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void LDMDB(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void LDMIB(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void LDR_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void LDR_LIT(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void LDR_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void LDRB_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void LDRB_LIT(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void LDRB_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void LDRD_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void LDRD_LIT(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void LDRD_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void LDRH_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void LDRH_LIT(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void LDRH_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void LDRSB_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void LDRSB_LIT(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void LDRSB_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void LDRSH_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void LDRSH_LIT(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void LDRSH_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void LSL_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void LSL_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void LSR_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void LSR_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void MLA(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void MLS(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void MOV_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void MOV_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void MOVT(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void MRS(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void MSR_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void MSR_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void MUL(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void MVN_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void MVN_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void MVN_RSR(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void NOP(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void ORN_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void ORN_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void ORR_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void ORR_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void ORR_RSR(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void PKH(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void POP(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void PUSH(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void QADD(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void QADD16(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void QADD8(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void QASX(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void QDADD(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void QDSUB(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void QSAX(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void QSUB(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void QSUB16(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void QSUB8(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void RBIT(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void REV(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void REV16(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void REVSH(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void ROR_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void ROR_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void RRX(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void RSB_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void RSB_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void RSB_RSR(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void RSC_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void RSC_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void RSC_RSR(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void SADD16(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SADD8(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SASX(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void SBC_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SBC_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SBC_RSR(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void SBFX(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void SDIV(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void SEL(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void SHADD16(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SHADD8(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SHASX(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SHSAX(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SHSUB16(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SHSUB8(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void SMLA__(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SMLAD(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SMLAL(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SMLAL__(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SMLALD(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SMLAW_(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SMLSD(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SMLSLD(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SMMLA(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SMMLS(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SMMUL(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SMUAD(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SMUL__(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SMULL(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SMULW_(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SMUSD(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void SSAT(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SSAT16(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SSAX(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SSUB16(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SSUB8(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void STM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void STMDA(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void STMDB(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void STMIB(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void STR_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void STR_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void STRB_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void STRB_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void STRD_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void STRD_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void STRH_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void STRH_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void SUB_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SUB_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SUB_RSR(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SUB_SPI(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SUB_SPR(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void SVC(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void SXTAB(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SXTAB16(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SXTAH(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SXTB(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SXTB16(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SXTH(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void TB_(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void TEQ_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void TEQ_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void TEQ_RSR(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void TST_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void TST_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void TST_RSR(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void UADD16(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UADD8(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UASX(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UBFX(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UDIV(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UHADD16(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UHADD8(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UHASX(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UHSAX(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UHSUB16(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UHSUB8(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UMAAL(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UMLAL(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UMULL(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UQADD16(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UQADD8(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UQASX(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UQSAX(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UQSUB16(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UQSUB8(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void USAD8(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void USADA8(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void USAT(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void USAT16(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void USAX(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void USUB16(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void USUB8(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UXTAB(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UXTAB16(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UXTAH(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UXTB(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UXTB16(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void UXTH(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
// TODO: vector ops + something
|
||||
};
|
||||
|
||||
struct ARMv7_opcode_t
|
||||
{
|
||||
u32 mask;
|
||||
u32 code;
|
||||
u32 length; // 2 or 4
|
||||
const char* name;
|
||||
ARMv7_encoding type;
|
||||
void (ARMv7Opcodes::*func)(const u32 data, const ARMv7_encoding type);
|
||||
};
|
||||
|
||||
// single 16-bit value
|
||||
#define ARMv7_OP2(mask, code, type, name) { (u32)((mask) << 16), (u32)((code) << 16), 2, #name "_" #type, type, &ARMv7Opcodes::name }
|
||||
// two 16-bit values
|
||||
#define ARMv7_OP4(mask0, mask1, code0, code1, type, name) { (u32)((mask0) << 16) | (mask1), (u32)((code0) << 16) | (code1), 4, #name "_" #type, type, &ARMv7Opcodes::name }
|
||||
|
||||
static const ARMv7_opcode_t ARMv7_opcode_table[] =
|
||||
{
|
||||
ARMv7_OP2(0xffff, 0x0000, T1, NULL_OP), // ???
|
||||
|
||||
ARMv7_OP4(0xffff, 0x0000, 0xf870, 0x0000, T1, HACK), // "Undefined" Thumb opcode
|
||||
ARMv7_OP4(0x0ff0, 0x00f0, 0x0070, 0x0090, A1, HACK), // "Undefined" ARM opcode
|
||||
|
||||
ARMv7_OP4(0xfbe0, 0x8000, 0xf140, 0x0000, T1, ADC_IMM),
|
||||
ARMv7_OP4(0x0fe0, 0x0000, 0x02a0, 0x0000, A1, ADC_IMM),
|
||||
ARMv7_OP2(0xffc0, 0x4040, T1, ADC_REG),
|
||||
ARMv7_OP4(0xffe0, 0x8000, 0xeb40, 0x0000, T2, ADC_REG),
|
||||
ARMv7_OP4(0x0fe0, 0x0010, 0x00a0, 0x0000, A1, ADC_REG),
|
||||
ARMv7_OP4(0x0fe0, 0x0090, 0x00a0, 0x0010, A1, ADC_RSR),
|
||||
|
||||
ARMv7_OP2(0xfe00, 0x1c00, T1, ADD_IMM),
|
||||
ARMv7_OP2(0xf800, 0x3000, T2, ADD_IMM),
|
||||
ARMv7_OP4(0xfbe0, 0x8000, 0xf100, 0x0000, T3, ADD_IMM),
|
||||
ARMv7_OP4(0xfbf0, 0x8000, 0xf200, 0x0000, T4, ADD_IMM),
|
||||
ARMv7_OP4(0x0fe0, 0x0000, 0x0280, 0x0000, A1, ADD_IMM),
|
||||
ARMv7_OP2(0xfe00, 0x1800, T1, ADD_REG),
|
||||
ARMv7_OP2(0xff00, 0x4400, T2, ADD_REG),
|
||||
ARMv7_OP4(0xffe0, 0x8000, 0xeb00, 0x0000, T3, ADD_REG),
|
||||
ARMv7_OP4(0x0fe0, 0x0010, 0x0080, 0x0000, A1, ADD_REG),
|
||||
ARMv7_OP4(0x0fe0, 0x0090, 0x0080, 0x0010, A1, ADD_RSR),
|
||||
ARMv7_OP2(0xf800, 0xa800, T1, ADD_SPI),
|
||||
ARMv7_OP2(0xff80, 0xb000, T2, ADD_SPI),
|
||||
ARMv7_OP4(0xfbef, 0x8000, 0xf10d, 0x0000, T3, ADD_SPI),
|
||||
ARMv7_OP4(0xfbff, 0x8000, 0xf20d, 0x0000, T4, ADD_SPI),
|
||||
ARMv7_OP4(0x0fef, 0x0000, 0x028d, 0x0000, A1, ADD_SPI),
|
||||
ARMv7_OP2(0xff78, 0x4468, T1, ADD_SPR),
|
||||
ARMv7_OP2(0xff87, 0x4485, T2, ADD_SPR),
|
||||
ARMv7_OP4(0xffef, 0x8000, 0xeb0d, 0x0000, T3, ADD_SPR),
|
||||
ARMv7_OP4(0x0fef, 0x0010, 0x008d, 0x0000, A1, ADD_SPR),
|
||||
|
||||
ARMv7_OP2(0xf800, 0xa000, T1, ADR),
|
||||
ARMv7_OP4(0xfbff, 0x8000, 0xf2af, 0x0000, T2, ADR),
|
||||
ARMv7_OP4(0xfbff, 0x8000, 0xf20f, 0x0000, T3, ADR),
|
||||
ARMv7_OP4(0x0fff, 0x0000, 0x028f, 0x0000, A1, ADR),
|
||||
ARMv7_OP4(0x0fff, 0x0000, 0x024f, 0x0000, A2, ADR),
|
||||
|
||||
ARMv7_OP4(0xfbe0, 0x8000, 0xf000, 0x0000, T1, AND_IMM),
|
||||
ARMv7_OP4(0x0fe0, 0x0000, 0x0200, 0x0000, A1, AND_IMM),
|
||||
ARMv7_OP2(0xffc0, 0x4000, T1, AND_REG),
|
||||
ARMv7_OP4(0xffe0, 0x8000, 0xea00, 0x0000, T2, AND_REG),
|
||||
ARMv7_OP4(0x0fe0, 0x0010, 0x0000, 0x0000, A1, AND_REG),
|
||||
ARMv7_OP4(0x0fe0, 0x0090, 0x0000, 0x0010, A1, AND_RSR),
|
||||
|
||||
ARMv7_OP2(0xf800, 0x1000, T1, ASR_IMM),
|
||||
ARMv7_OP4(0xffef, 0x8030, 0xea4f, 0x0020, T2, ASR_IMM),
|
||||
ARMv7_OP4(0x0fef, 0x0070, 0x01a0, 0x0040, A1, ASR_IMM),
|
||||
ARMv7_OP2(0xffc0, 0x4100, T1, ASR_REG),
|
||||
ARMv7_OP4(0xffe0, 0xf0f0, 0xfa40, 0xf000, T2, ASR_REG),
|
||||
ARMv7_OP4(0x0fef, 0x00f0, 0x01a0, 0x0050, A1, ASR_REG),
|
||||
|
||||
ARMv7_OP2(0xf000, 0xd000, T1, B),
|
||||
ARMv7_OP2(0xf800, 0xe000, T2, B),
|
||||
ARMv7_OP4(0xf800, 0xd000, 0xf000, 0x8000, T3, B),
|
||||
ARMv7_OP4(0xf800, 0xd000, 0xf000, 0x9000, T4, B),
|
||||
ARMv7_OP4(0x0f00, 0x0000, 0x0a00, 0x0000, A1, B),
|
||||
|
||||
ARMv7_OP4(0xffff, 0x8020, 0xf36f, 0x0000, T1, BFC),
|
||||
ARMv7_OP4(0x0fe0, 0x007f, 0x07c0, 0x001f, A1, BFC),
|
||||
ARMv7_OP4(0xfff0, 0x8020, 0xf360, 0x0000, T1, BFI),
|
||||
ARMv7_OP4(0x0fe0, 0x0070, 0x07c0, 0x0010, A1, BFI),
|
||||
|
||||
ARMv7_OP4(0xfbe0, 0x8000, 0xf020, 0x0000, T1, BIC_IMM),
|
||||
ARMv7_OP4(0x0fe0, 0x0000, 0x03c0, 0x0000, A1, BIC_IMM),
|
||||
ARMv7_OP2(0xffc0, 0x4380, T1, BIC_REG),
|
||||
ARMv7_OP4(0xffe0, 0x8000, 0xea20, 0x0000, T2, BIC_REG),
|
||||
ARMv7_OP4(0x0fe0, 0x0010, 0x01c0, 0x0000, A1, BIC_REG),
|
||||
ARMv7_OP4(0x0fe0, 0x0090, 0x01c0, 0x0010, A1, BIC_RSR),
|
||||
|
||||
ARMv7_OP2(0xff00, 0xbe00, T1, BKPT),
|
||||
ARMv7_OP4(0x0ff0, 0x00f0, 0x0120, 0x0070, A1, BKPT),
|
||||
|
||||
ARMv7_OP4(0xf800, 0xd000, 0xf000, 0xd000, T1, BL),
|
||||
ARMv7_OP4(0x0f00, 0x0000, 0x0b00, 0x0000, A1, BL),
|
||||
ARMv7_OP2(0xff80, 0x4780, T1, BLX),
|
||||
ARMv7_OP4(0xf800, 0xc001, 0xf000, 0xc000, T2, BLX),
|
||||
ARMv7_OP4(0x0fff, 0xfff0, 0x012f, 0xff30, A1, BLX),
|
||||
ARMv7_OP4(0xfe00, 0x0000, 0xfa00, 0x0000, A2, BLX),
|
||||
|
||||
ARMv7_OP2(0xff87, 0x4700, T1, BX),
|
||||
ARMv7_OP4(0x0fff, 0xfff0, 0x012f, 0xff10, A1, BX),
|
||||
|
||||
ARMv7_OP2(0xf500, 0xb100, T1, CB_Z),
|
||||
|
||||
ARMv7_OP4(0xfff0, 0xf0f0, 0xfab0, 0xf080, T1, CLZ),
|
||||
ARMv7_OP4(0x0fff, 0x0ff0, 0x016f, 0x0f10, A1, CLZ),
|
||||
|
||||
ARMv7_OP4(0xfbf0, 0x8f00, 0xf110, 0x0f00, T1, CMN_IMM),
|
||||
ARMv7_OP4(0x0ff0, 0xf000, 0x0370, 0x0000, A1, CMN_IMM),
|
||||
ARMv7_OP2(0xffc0, 0x42c0, T1, CMN_REG),
|
||||
ARMv7_OP4(0xfff0, 0x8f00, 0xeb10, 0x0f00, T2, CMN_REG),
|
||||
ARMv7_OP4(0x0ff0, 0xf010, 0x0170, 0x0000, A1, CMN_REG),
|
||||
ARMv7_OP4(0x0ff0, 0xf090, 0x0170, 0x0010, A1, CMN_RSR),
|
||||
|
||||
ARMv7_OP2(0xf800, 0x2800, T1, CMP_IMM),
|
||||
ARMv7_OP4(0xfbf0, 0x8f00, 0xf1b0, 0x0f00, T2, CMP_IMM),
|
||||
ARMv7_OP4(0x0ff0, 0xf000, 0x0350, 0x0000, A1, CMP_IMM),
|
||||
ARMv7_OP2(0xffc0, 0x4280, T1, CMP_REG),
|
||||
ARMv7_OP2(0xff00, 0x4500, T2, CMP_REG),
|
||||
ARMv7_OP4(0xfff0, 0x8f00, 0xebb0, 0x0f00, T3, CMP_REG),
|
||||
ARMv7_OP4(0x0ff0, 0xf010, 0x0150, 0x0000, A1, CMP_REG),
|
||||
ARMv7_OP4(0x0ff0, 0xf090, 0x0150, 0x0010, A1, CMP_RSR),
|
||||
|
||||
ARMv7_OP4(0xfbe0, 0x8000, 0xf080, 0x0000, T1, EOR_IMM),
|
||||
ARMv7_OP4(0x0fe0, 0x0000, 0x0220, 0x0000, A1, EOR_IMM),
|
||||
ARMv7_OP2(0xffc0, 0x4040, T1, EOR_REG),
|
||||
ARMv7_OP4(0xffe0, 0x8000, 0xea80, 0x0000, T2, EOR_REG),
|
||||
ARMv7_OP4(0x0fe0, 0x0010, 0x0020, 0x0000, A1, EOR_REG),
|
||||
ARMv7_OP4(0x0fe0, 0x0090, 0x0020, 0x0010, A1, EOR_RSR),
|
||||
|
||||
ARMv7_OP2(0xff00, 0xbf00, T1, IT),
|
||||
|
||||
ARMv7_OP2(0xf800, 0xc800, T1, LDM),
|
||||
ARMv7_OP4(0xffd0, 0x2000, 0xe890, 0x0000, T2, LDM),
|
||||
ARMv7_OP4(0x0fd0, 0x0000, 0x0890, 0x0000, A1, LDM),
|
||||
ARMv7_OP4(0x0fd0, 0x0000, 0x0810, 0x0000, A1, LDMDA),
|
||||
ARMv7_OP4(0xffd0, 0x2000, 0xe910, 0x0000, T1, LDMDB),
|
||||
ARMv7_OP4(0x0fd0, 0x0000, 0x0910, 0x0000, A1, LDMDB),
|
||||
ARMv7_OP4(0x0fd0, 0x0000, 0x0990, 0x0000, A1, LDMIB),
|
||||
|
||||
ARMv7_OP2(0xf800, 0x6800, T1, LDR_IMM),
|
||||
ARMv7_OP2(0xf800, 0x9800, T2, LDR_IMM),
|
||||
ARMv7_OP4(0xfff0, 0x0000, 0xf8d0, 0x0000, T3, LDR_IMM),
|
||||
ARMv7_OP4(0xfff0, 0x0800, 0xf850, 0x0800, T4, LDR_IMM),
|
||||
ARMv7_OP4(0x0e50, 0x0000, 0x0410, 0x0000, A1, LDR_IMM),
|
||||
ARMv7_OP2(0xf800, 0x4800, T1, LDR_LIT),
|
||||
ARMv7_OP4(0xff7f, 0x0000, 0xf85f, 0x0000, T2, LDR_LIT),
|
||||
ARMv7_OP4(0x0f7f, 0x0000, 0x051f, 0x0000, A1, LDR_LIT),
|
||||
ARMv7_OP2(0xfe00, 0x5800, T1, LDR_REG),
|
||||
ARMv7_OP4(0xfff0, 0x0fc0, 0xf850, 0x0000, T2, LDR_REG),
|
||||
ARMv7_OP4(0x0e50, 0x0010, 0x0610, 0x0000, A1, LDR_REG),
|
||||
|
||||
ARMv7_OP2(0xf800, 0x7800, T1, LDRB_IMM),
|
||||
ARMv7_OP4(0xfff0, 0x0000, 0xf890, 0x0000, T2, LDRB_IMM),
|
||||
ARMv7_OP4(0xfff0, 0x0800, 0xf810, 0x0800, T3, LDRB_IMM),
|
||||
ARMv7_OP4(0x0e50, 0x0000, 0x0450, 0x0000, A1, LDRB_IMM),
|
||||
ARMv7_OP4(0xff7f, 0x0000, 0xf81f, 0x0000, T1, LDRB_LIT),
|
||||
ARMv7_OP4(0x0f7f, 0x0000, 0x055f, 0x0000, A1, LDRB_LIT),
|
||||
ARMv7_OP2(0xfe00, 0x5c00, T1, LDRB_REG),
|
||||
ARMv7_OP4(0xfff0, 0x0fc0, 0xf810, 0x0000, T2, LDRB_REG),
|
||||
ARMv7_OP4(0x0e50, 0x0010, 0x0650, 0x0000, A1, LDRB_REG),
|
||||
|
||||
ARMv7_OP4(0xfe50, 0x0000, 0xe850, 0x0000, T1, LDRD_IMM),
|
||||
ARMv7_OP4(0x0e50, 0x00f0, 0x0040, 0x00d0, A1, LDRD_IMM),
|
||||
ARMv7_OP4(0xfe7f, 0x0000, 0xe85f, 0x0000, T1, LDRD_LIT),
|
||||
ARMv7_OP4(0x0f7f, 0x00f0, 0x014f, 0x00d0, A1, LDRD_LIT),
|
||||
ARMv7_OP4(0x0e50, 0x0ff0, 0x0000, 0x00d0, A1, LDRD_REG),
|
||||
|
||||
ARMv7_OP4(0xfff0, 0x0000, 0xf990, 0x0000, T1, LDRSB_IMM),
|
||||
ARMv7_OP4(0xfff0, 0x0800, 0xf910, 0x0800, T2, LDRSB_IMM),
|
||||
ARMv7_OP4(0x0e50, 0x00f0, 0x0050, 0x00d0, A1, LDRSB_IMM),
|
||||
ARMv7_OP4(0xff7f, 0x0000, 0xf91f, 0x0000, T1, LDRSB_LIT),
|
||||
ARMv7_OP4(0x0f7f, 0x00f0, 0x015f, 0x00d0, A1, LDRSB_LIT),
|
||||
ARMv7_OP2(0xfe00, 0x5600, T1, LDRSB_REG),
|
||||
ARMv7_OP4(0xfff0, 0x0fc0, 0xf910, 0x0000, T2, LDRSB_REG),
|
||||
ARMv7_OP4(0x0e50, 0x0ff0, 0x0010, 0x00d0, A1, LDRSB_REG),
|
||||
|
||||
ARMv7_OP4(0xfff0, 0x0000, 0xf9b0, 0x0000, T1, LDRSH_IMM),
|
||||
ARMv7_OP4(0xfff0, 0x0800, 0xf930, 0x0800, T2, LDRSH_IMM),
|
||||
ARMv7_OP4(0x0e50, 0x00f0, 0x0050, 0x00f0, A1, LDRSH_IMM),
|
||||
ARMv7_OP4(0xff7f, 0x0000, 0xf93f, 0x0000, T1, LDRSH_LIT),
|
||||
ARMv7_OP4(0x0f7f, 0x00f0, 0x015f, 0x00f0, A1, LDRSH_LIT),
|
||||
ARMv7_OP2(0xfe00, 0x5e00, T1, LDRSH_REG),
|
||||
ARMv7_OP4(0xfff0, 0x0fc0, 0xf930, 0x0000, T2, LDRSH_REG),
|
||||
ARMv7_OP4(0x0e50, 0x0ff0, 0x0010, 0x00f0, A1, LDRSH_REG),
|
||||
|
||||
ARMv7_OP2(0xf800, 0x0000, T1, LSL_IMM),
|
||||
ARMv7_OP4(0xffef, 0x8030, 0xea4f, 0x0000, T2, LSL_IMM),
|
||||
ARMv7_OP4(0x0fef, 0x0070, 0x01a0, 0x0000, A1, LSL_IMM),
|
||||
ARMv7_OP2(0xffc0, 0x4080, T1, LSL_REG),
|
||||
ARMv7_OP4(0xffe0, 0xf0f0, 0xfa00, 0xf000, T2, LSL_REG),
|
||||
ARMv7_OP4(0x0fef, 0x00f0, 0x01a0, 0x0010, A1, LSL_REG),
|
||||
|
||||
ARMv7_OP2(0xf800, 0x0800, T1, LSR_IMM),
|
||||
ARMv7_OP4(0xffef, 0x8030, 0xea4f, 0x0010, T2, LSR_IMM),
|
||||
ARMv7_OP4(0x0fef, 0x0030, 0x01a0, 0x0020, A1, LSR_IMM),
|
||||
ARMv7_OP2(0xffc0, 0x40c0, T1, LSR_REG),
|
||||
ARMv7_OP4(0xffe0, 0xf0f0, 0xfa20, 0xf000, T2, LSR_REG),
|
||||
ARMv7_OP4(0x0fef, 0x00f0, 0x01a0, 0x0030, A1, LSR_REG),
|
||||
|
||||
ARMv7_OP4(0xfff0, 0x00f0, 0xfb00, 0x0000, T1, MLA),
|
||||
ARMv7_OP4(0x0fe0, 0x00f0, 0x0020, 0x0090, A1, MLA),
|
||||
|
||||
ARMv7_OP4(0xfff0, 0x00f0, 0xfb00, 0x0010, T1, MLS),
|
||||
ARMv7_OP4(0x0ff0, 0x00f0, 0x0060, 0x0090, A1, MLS),
|
||||
|
||||
ARMv7_OP2(0xf800, 0x2000, T1, MOV_IMM),
|
||||
ARMv7_OP4(0xfbef, 0x8000, 0xf04f, 0x0000, T2, MOV_IMM),
|
||||
ARMv7_OP4(0xfbf0, 0x8000, 0xf240, 0x0000, T3, MOV_IMM),
|
||||
ARMv7_OP4(0x0fef, 0x0000, 0x03a0, 0x0000, A1, MOV_IMM),
|
||||
ARMv7_OP4(0x0ff0, 0x0000, 0x0300, 0x0000, A2, MOV_IMM),
|
||||
ARMv7_OP2(0xff00, 0x4600, T1, MOV_REG),
|
||||
ARMv7_OP2(0xffc0, 0x0000, T2, MOV_REG),
|
||||
ARMv7_OP4(0xffef, 0xf0f0, 0xea4f, 0x0000, T3, MOV_REG),
|
||||
ARMv7_OP4(0x0fef, 0x0ff0, 0x01a0, 0x0000, A1, MOV_REG),
|
||||
ARMv7_OP4(0xfbf0, 0x8000, 0xf2c0, 0x0000, T1, MOVT),
|
||||
ARMv7_OP4(0x0ff0, 0x0000, 0x0340, 0x0000, A1, MOVT),
|
||||
|
||||
ARMv7_OP4(0xffff, 0xf0ff, 0xf3ef, 0x8000, T1, MRS),
|
||||
ARMv7_OP4(0x0fff, 0x0fff, 0x010f, 0x0000, A1, MRS),
|
||||
ARMv7_OP4(0x0ff3, 0xf000, 0x0320, 0xf000, A1, MSR_IMM),
|
||||
ARMv7_OP4(0xfff0, 0xf3ff, 0xf380, 0x8000, T1, MSR_REG),
|
||||
ARMv7_OP4(0x0ff3, 0xfff0, 0x0120, 0xf000, A1, MSR_REG),
|
||||
|
||||
ARMv7_OP2(0xffc0, 0x4340, T1, MUL),
|
||||
ARMv7_OP4(0xfff0, 0xf0f0, 0xfb00, 0xf000, T2, MUL),
|
||||
ARMv7_OP4(0x0fe0, 0xf0f0, 0x0000, 0x0090, A1, MUL),
|
||||
|
||||
ARMv7_OP4(0xfbef, 0x8000, 0xf06f, 0x0000, T1, MVN_IMM),
|
||||
ARMv7_OP4(0x0fef, 0x0000, 0x03e0, 0x0000, A1, MVN_IMM),
|
||||
ARMv7_OP2(0xffc0, 0x43c0, T1, MVN_REG),
|
||||
ARMv7_OP4(0xffef, 0x8000, 0xea6f, 0x0000, T2, MVN_REG),
|
||||
ARMv7_OP4(0xffef, 0x0010, 0x01e0, 0x0000, A1, MVN_REG),
|
||||
ARMv7_OP4(0x0fef, 0x0090, 0x01e0, 0x0010, A1, MVN_RSR),
|
||||
|
||||
ARMv7_OP2(0xffff, 0xbf00, T1, NOP),
|
||||
ARMv7_OP4(0xffff, 0xffff, 0xf3af, 0x8000, T2, NOP),
|
||||
ARMv7_OP4(0x0fff, 0xffff, 0x0320, 0xf000, A1, NOP),
|
||||
|
||||
ARMv7_OP4(0xfbe0, 0x8000, 0xf060, 0x0000, T1, ORN_IMM),
|
||||
ARMv7_OP4(0xffe0, 0x8000, 0xea60, 0x0000, T1, ORN_REG),
|
||||
|
||||
ARMv7_OP4(0xfbe0, 0x8000, 0xf040, 0x0000, T1, ORR_IMM),
|
||||
ARMv7_OP4(0x0fe0, 0x0000, 0x0380, 0x0000, A1, ORR_IMM),
|
||||
ARMv7_OP2(0xffc0, 0x4300, T1, ORR_REG),
|
||||
ARMv7_OP4(0xffe0, 0x8000, 0xea40, 0x0000, T2, ORR_REG),
|
||||
ARMv7_OP4(0x0fe0, 0x0010, 0x0180, 0x0000, A1, ORR_REG),
|
||||
ARMv7_OP4(0x0fe0, 0x0090, 0x0180, 0x0010, A1, ORR_RSR),
|
||||
|
||||
ARMv7_OP4(0xfff0, 0x8010, 0xeac0, 0x0000, T1, PKH),
|
||||
ARMv7_OP4(0x0ff0, 0x0030, 0x0680, 0x0010, A1, PKH),
|
||||
|
||||
ARMv7_OP2(0xfe00, 0xbc00, T1, POP),
|
||||
ARMv7_OP4(0xffff, 0x0000, 0xe8bd, 0x0000, T2, POP),
|
||||
ARMv7_OP4(0xffff, 0x0fff, 0xf85d, 0x0b04, T3, POP),
|
||||
ARMv7_OP4(0x0fff, 0x0000, 0x08bd, 0x0000, A1, POP),
|
||||
ARMv7_OP4(0x0fff, 0x0fff, 0x049d, 0x0004, A2, POP),
|
||||
|
||||
ARMv7_OP2(0xfe00, 0xb400, T1, PUSH),
|
||||
ARMv7_OP4(0xffff, 0x0000, 0xe92d, 0x0000, T2, PUSH), // had an error in arch ref
|
||||
ARMv7_OP4(0xffff, 0x0fff, 0xf84d, 0x0d04, T3, PUSH),
|
||||
ARMv7_OP4(0x0fff, 0x0000, 0x092d, 0x0000, A1, PUSH),
|
||||
ARMv7_OP4(0x0fff, 0x0fff, 0x052d, 0x0004, A2, PUSH),
|
||||
|
||||
// TODO (Q*...)
|
||||
|
||||
ARMv7_OP4(0xfff0, 0xf0f0, 0xfa90, 0xf0a0, T1, RBIT),
|
||||
ARMv7_OP4(0x0fff, 0x0ff0, 0x06ff, 0x0f30, A1, RBIT),
|
||||
|
||||
ARMv7_OP2(0xffc0, 0xba00, T1, REV),
|
||||
ARMv7_OP4(0xfff0, 0xf0f0, 0xfa90, 0xf080, T2, REV),
|
||||
ARMv7_OP4(0x0fff, 0x0ff0, 0x06bf, 0x0f30, A1, REV),
|
||||
ARMv7_OP2(0xffc0, 0xba40, T1, REV16),
|
||||
ARMv7_OP4(0xfff0, 0xf0f0, 0xfa90, 0xf090, T2, REV16),
|
||||
ARMv7_OP4(0x0fff, 0x0ff0, 0x06bf, 0x0fb0, A1, REV16),
|
||||
ARMv7_OP2(0xffc0, 0xbac0, T1, REVSH),
|
||||
ARMv7_OP4(0xfff0, 0xf0f0, 0xfa90, 0xf0b0, T2, REVSH),
|
||||
ARMv7_OP4(0x0fff, 0x0ff0, 0x06ff, 0x0fb0, A1, REVSH),
|
||||
|
||||
ARMv7_OP4(0xffef, 0x8030, 0xea4f, 0x0030, T1, ROR_IMM),
|
||||
ARMv7_OP4(0x0fef, 0x0070, 0x01a0, 0x0060, A1, ROR_IMM),
|
||||
ARMv7_OP2(0xffc0, 0x41c0, T1, ROR_REG),
|
||||
ARMv7_OP4(0xffe0, 0xf0f0, 0xfa60, 0xf000, T2, ROR_REG),
|
||||
ARMv7_OP4(0x0fef, 0x00f0, 0x01a0, 0x0070, A1, ROR_REG),
|
||||
ARMv7_OP4(0xffef, 0xf0f0, 0xea4f, 0x0030, T1, RRX),
|
||||
ARMv7_OP4(0x0fef, 0x0ff0, 0x01a0, 0x0060, A1, RRX),
|
||||
|
||||
ARMv7_OP2(0xffc0, 0x4240, T1, RSB_IMM),
|
||||
ARMv7_OP4(0xfbe0, 0x8000, 0xf1c0, 0x0000, T2, RSB_IMM),
|
||||
ARMv7_OP4(0x0fe0, 0x0000, 0x0260, 0x0000, A1, RSB_IMM),
|
||||
ARMv7_OP4(0xffe0, 0x8000, 0xebc0, 0x0000, T1, RSB_REG),
|
||||
ARMv7_OP4(0x0fe0, 0x0010, 0x0060, 0x0000, A1, RSB_REG),
|
||||
ARMv7_OP4(0x0fe0, 0x0090, 0x0060, 0x0010, A1, RSB_RSR),
|
||||
|
||||
ARMv7_OP4(0x0fe0, 0x0000, 0x02e0, 0x0000, A1, RSC_IMM),
|
||||
ARMv7_OP4(0x0fe0, 0x0010, 0x00e0, 0x0000, A1, RSC_REG),
|
||||
ARMv7_OP4(0x0fe0, 0x0090, 0x00e0, 0x0010, A1, RSC_RSR),
|
||||
|
||||
// TODO (SADD16, SADD8, SASX)
|
||||
|
||||
ARMv7_OP4(0xfbe0, 0x8000, 0xf160, 0x0000, T1, SBC_IMM),
|
||||
ARMv7_OP4(0x0fe0, 0x0000, 0x02c0, 0x0000, A1, SBC_IMM),
|
||||
ARMv7_OP2(0xffc0, 0x4180, T1, SBC_REG),
|
||||
ARMv7_OP4(0xffe0, 0x8000, 0xeb60, 0x0000, T2, SBC_REG),
|
||||
ARMv7_OP4(0x0fe0, 0x0010, 0x00c0, 0x0000, A1, SBC_REG),
|
||||
ARMv7_OP4(0x0fe0, 0x0090, 0x00c0, 0x0010, A1, SBC_RSR),
|
||||
|
||||
ARMv7_OP4(0xfff0, 0x8020, 0xf340, 0x0000, T1, SBFX),
|
||||
ARMv7_OP4(0x0fe0, 0x0070, 0x07a0, 0x0050, A1, SBFX),
|
||||
|
||||
ARMv7_OP4(0xfff0, 0xf0f0, 0xfb90, 0xf0f0, T1, SDIV), // ???
|
||||
|
||||
ARMv7_OP4(0xfff0, 0xf0f0, 0xfaa0, 0xf080, T1, SEL),
|
||||
ARMv7_OP4(0x0ff0, 0x0ff0, 0x0680, 0x0fb0, A1, SEL),
|
||||
|
||||
// TODO (SH*, SM*, SS*)
|
||||
|
||||
ARMv7_OP2(0xf800, 0xc000, T1, STM),
|
||||
ARMv7_OP4(0xffd0, 0xa000, 0xe880, 0x0000, T2, STM),
|
||||
ARMv7_OP4(0x0fd0, 0x0000, 0x0880, 0x0000, A1, STM),
|
||||
ARMv7_OP4(0x0fd0, 0x0000, 0x0800, 0x0000, A1, STMDA),
|
||||
ARMv7_OP4(0xffd0, 0xa000, 0xe900, 0x0000, T1, STMDB),
|
||||
ARMv7_OP4(0x0fd0, 0x0000, 0x0900, 0x0000, A1, STMDB),
|
||||
ARMv7_OP4(0x0fd0, 0x0000, 0x0980, 0x0000, A1, STMIB),
|
||||
|
||||
ARMv7_OP2(0xf800, 0x6000, T1, STR_IMM),
|
||||
ARMv7_OP2(0xf800, 0x9000, T2, STR_IMM),
|
||||
ARMv7_OP4(0xfff0, 0x0000, 0xf8c0, 0x0000, T3, STR_IMM),
|
||||
ARMv7_OP4(0xfff0, 0x0800, 0xf840, 0x0800, T4, STR_IMM),
|
||||
ARMv7_OP4(0x0e50, 0x0000, 0x0400, 0x0000, A1, STR_IMM),
|
||||
ARMv7_OP2(0xfe00, 0x5000, T1, STR_REG),
|
||||
ARMv7_OP4(0xfff0, 0x0fc0, 0xf840, 0x0000, T2, STR_REG),
|
||||
ARMv7_OP4(0x0e50, 0x0010, 0x0600, 0x0000, A1, STR_REG),
|
||||
|
||||
ARMv7_OP2(0xf800, 0x7000, T1, STRB_IMM),
|
||||
ARMv7_OP4(0xfff0, 0x0000, 0xf880, 0x0000, T2, STRB_IMM),
|
||||
ARMv7_OP4(0xfff0, 0x0800, 0xf800, 0x0800, T3, STRB_IMM),
|
||||
ARMv7_OP4(0x0e50, 0x0000, 0x0440, 0x0000, A1, STRB_IMM),
|
||||
ARMv7_OP2(0xfe00, 0x5400, T1, STRB_REG),
|
||||
ARMv7_OP4(0xfff0, 0x0fc0, 0xf800, 0x0000, T2, STRB_REG),
|
||||
ARMv7_OP4(0x0e50, 0x0010, 0x0640, 0x0000, A1, STRB_REG),
|
||||
|
||||
ARMv7_OP4(0xfe50, 0x0000, 0xe840, 0x0000, T1, STRD_IMM),
|
||||
ARMv7_OP4(0x0e50, 0x00f0, 0x0040, 0x00f0, A1, STRD_IMM),
|
||||
ARMv7_OP4(0x0e50, 0x0ff0, 0x0000, 0x00f0, A1, STRD_REG),
|
||||
|
||||
ARMv7_OP2(0xf800, 0x8000, T1, STRH_IMM),
|
||||
ARMv7_OP4(0xfff0, 0x0000, 0xf8a0, 0x0000, T2, STRH_IMM),
|
||||
ARMv7_OP4(0xfff0, 0x0800, 0xf820, 0x0800, T3, STRH_IMM),
|
||||
ARMv7_OP4(0x0e50, 0x00f0, 0x0040, 0x00b0, A1, STRH_IMM),
|
||||
ARMv7_OP2(0xfe00, 0x5200, T1, STRH_REG),
|
||||
ARMv7_OP4(0xfff0, 0x0fc0, 0xf820, 0x0000, T2, STRH_REG),
|
||||
ARMv7_OP4(0x0e50, 0x0ff0, 0x0000, 0x00b0, A1, STRH_REG),
|
||||
|
||||
ARMv7_OP2(0xff80, 0xb080, T1, SUB_SPI),
|
||||
ARMv7_OP4(0xfbef, 0x8000, 0xf1ad, 0x0000, T2, SUB_SPI),
|
||||
ARMv7_OP4(0xfbff, 0x8000, 0xf2ad, 0x0000, T3, SUB_SPI),
|
||||
ARMv7_OP4(0x0fef, 0x0000, 0x024d, 0x0000, A1, SUB_SPI),
|
||||
ARMv7_OP4(0xffef, 0x8000, 0xebad, 0x0000, T1, SUB_SPR),
|
||||
ARMv7_OP4(0x0fef, 0x0010, 0x004d, 0x0000, A1, SUB_SPR),
|
||||
ARMv7_OP2(0xfe00, 0x1e00, T1, SUB_IMM),
|
||||
ARMv7_OP2(0xf800, 0x3800, T2, SUB_IMM),
|
||||
ARMv7_OP4(0xfbe0, 0x8000, 0xf1a0, 0x0000, T3, SUB_IMM),
|
||||
ARMv7_OP4(0xfbf0, 0x8000, 0xf2a0, 0x0000, T4, SUB_IMM),
|
||||
ARMv7_OP4(0x0fe0, 0x0000, 0x0240, 0x0000, A1, SUB_IMM),
|
||||
ARMv7_OP2(0xfe00, 0x1a00, T1, SUB_REG),
|
||||
ARMv7_OP4(0xffe0, 0x8000, 0xeba0, 0x0000, T2, SUB_REG),
|
||||
ARMv7_OP4(0x0fe0, 0x0010, 0x0040, 0x0000, A1, SUB_REG),
|
||||
ARMv7_OP4(0x0fe0, 0x0090, 0x0040, 0x0010, A1, SUB_RSR),
|
||||
|
||||
ARMv7_OP2(0xff00, 0xdf00, T1, SVC),
|
||||
ARMv7_OP4(0x0f00, 0x0000, 0x0f00, 0x0000, A1, SVC),
|
||||
|
||||
// TODO (SX*)
|
||||
|
||||
ARMv7_OP4(0xfff0, 0xffe0, 0xe8d0, 0xf000, T1, TB_),
|
||||
|
||||
ARMv7_OP4(0xfbf0, 0x8f00, 0xf090, 0x0f00, T1, TEQ_IMM),
|
||||
ARMv7_OP4(0x0ff0, 0xf000, 0x0330, 0x0000, A1, TEQ_IMM),
|
||||
ARMv7_OP4(0xfff0, 0x8f00, 0xea90, 0x0f00, T1, TEQ_REG),
|
||||
ARMv7_OP4(0x0ff0, 0xf010, 0x0130, 0x0000, A1, TEQ_REG),
|
||||
ARMv7_OP4(0x0ff0, 0xf090, 0x0130, 0x0010, A1, TEQ_RSR),
|
||||
|
||||
ARMv7_OP4(0xfbf0, 0x8f00, 0xf010, 0x0f00, T1, TST_IMM),
|
||||
ARMv7_OP4(0x0ff0, 0xf000, 0x0310, 0x0000, A1, TST_IMM),
|
||||
ARMv7_OP2(0xffc0, 0x4200, T1, TST_REG),
|
||||
ARMv7_OP4(0xfff0, 0x8f00, 0xea10, 0x0f00, T2, TST_REG),
|
||||
ARMv7_OP4(0x0ff0, 0xf010, 0x0110, 0x0000, A1, TST_REG),
|
||||
ARMv7_OP4(0x0ff0, 0xf090, 0x0110, 0x0010, A1, TST_RSR),
|
||||
|
||||
// TODO (U*, V*)
|
||||
};
|
||||
|
||||
#undef ARMv7_OP
|
||||
#undef ARMv7_OPP
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/CPU/CPUThreadManager.h"
|
||||
|
||||
#include "ARMv7Thread.h"
|
||||
#include "ARMv7Decoder.h"
|
||||
|
@ -18,6 +19,8 @@ void ARMv7Thread::InitRegs()
|
|||
memset(GPR, 0, sizeof(GPR[0]) * 15);
|
||||
APSR.APSR = 0;
|
||||
IPSR.IPSR = 0;
|
||||
ISET = Thumb;
|
||||
ITSTATE.IT = 0;
|
||||
SP = m_stack_addr + m_stack_size;
|
||||
}
|
||||
|
||||
|
@ -30,9 +33,9 @@ void ARMv7Thread::InitStack()
|
|||
}
|
||||
}
|
||||
|
||||
void ARMv7Thread::SetArg(const uint pos, const u64 arg)
|
||||
u32 ARMv7Thread::GetStackArg(u32 pos)
|
||||
{
|
||||
assert(0);
|
||||
return vm::psv::read32(SP + sizeof(u32) * (pos - 5));
|
||||
}
|
||||
|
||||
std::string ARMv7Thread::RegsToString()
|
||||
|
@ -98,3 +101,15 @@ void ARMv7Thread::DoStop()
|
|||
void ARMv7Thread::DoCode()
|
||||
{
|
||||
}
|
||||
|
||||
arm7_thread::arm7_thread(u32 entry, const std::string& name, u32 stack_size, u32 prio)
|
||||
{
|
||||
thread = &Emu.GetCPU().AddThread(CPU_THREAD_ARMv7);
|
||||
|
||||
thread->SetName(name);
|
||||
thread->SetEntry(entry);
|
||||
thread->SetStackSize(stack_size ? stack_size : Emu.GetInfo().GetProcParam().primary_stacksize);
|
||||
thread->SetPrio(prio ? prio : Emu.GetInfo().GetProcParam().primary_prio);
|
||||
|
||||
argc = 0;
|
||||
}
|
|
@ -1,6 +1,14 @@
|
|||
#pragma once
|
||||
#include "Emu/CPU/CPUThread.h"
|
||||
|
||||
enum ARMv7InstructionSet
|
||||
{
|
||||
ARM,
|
||||
Thumb,
|
||||
Jazelle,
|
||||
ThumbEE,
|
||||
};
|
||||
|
||||
class ARMv7Thread : public CPUThread
|
||||
{
|
||||
public:
|
||||
|
@ -38,6 +46,7 @@ public:
|
|||
};
|
||||
|
||||
u32 APSR;
|
||||
|
||||
} APSR;
|
||||
|
||||
union
|
||||
|
@ -49,8 +58,41 @@ public:
|
|||
};
|
||||
|
||||
u32 IPSR;
|
||||
|
||||
} IPSR;
|
||||
|
||||
ARMv7InstructionSet ISET;
|
||||
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
u8 cond : 3;
|
||||
u8 state : 5;
|
||||
};
|
||||
|
||||
u8 IT;
|
||||
|
||||
u32 advance()
|
||||
{
|
||||
const u32 res = (state & 0xf) ? (cond << 1 | state >> 4) : 0xe /* true */;
|
||||
|
||||
state <<= 1;
|
||||
if ((state & 0xf) == 0) // if no d
|
||||
{
|
||||
IT = 0; // clear ITSTATE
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return (state & 0xf) != 0;
|
||||
}
|
||||
|
||||
} ITSTATE;
|
||||
|
||||
void write_gpr(u32 n, u32 value)
|
||||
{
|
||||
assert(n < 16);
|
||||
|
@ -61,7 +103,7 @@ public:
|
|||
}
|
||||
else
|
||||
{
|
||||
SetBranch(value);
|
||||
SetBranch(value & ~1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -80,7 +122,7 @@ public:
|
|||
public:
|
||||
virtual void InitRegs();
|
||||
virtual void InitStack();
|
||||
virtual void SetArg(const uint pos, const u64 arg);
|
||||
u32 GetStackArg(u32 pos);
|
||||
|
||||
public:
|
||||
virtual std::string RegsToString();
|
||||
|
@ -96,3 +138,48 @@ protected:
|
|||
|
||||
virtual void DoCode();
|
||||
};
|
||||
class arm7_thread : cpu_thread
|
||||
{
|
||||
static const u32 stack_align = 0x10;
|
||||
vm::ptr<u64> argv;
|
||||
u32 argc;
|
||||
vm::ptr<u64> envp;
|
||||
|
||||
public:
|
||||
arm7_thread(u32 entry, const std::string& name = "", u32 stack_size = 0, u32 prio = 0);
|
||||
|
||||
cpu_thread& args(std::initializer_list<std::string> values) override
|
||||
{
|
||||
if (!values.size())
|
||||
return *this;
|
||||
|
||||
assert(argc == 0);
|
||||
|
||||
envp.set(vm::alloc((u32)sizeof(envp), stack_align, vm::main));
|
||||
*envp = 0;
|
||||
argv.set(vm::alloc(u32(sizeof(argv)* values.size()), stack_align, vm::main));
|
||||
|
||||
for (auto &arg : values)
|
||||
{
|
||||
u32 arg_size = align(u32(arg.size() + 1), stack_align);
|
||||
u32 arg_addr = vm::alloc(arg_size, stack_align, vm::main);
|
||||
|
||||
std::strcpy(vm::get_ptr<char>(arg_addr), arg.c_str());
|
||||
|
||||
argv[argc++] = arg_addr;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
cpu_thread& run() override
|
||||
{
|
||||
thread->Run();
|
||||
|
||||
static_cast<ARMv7Thread*>(thread)->GPR[3] = argc;
|
||||
static_cast<ARMv7Thread*>(thread)->GPR[4] = argv.addr();
|
||||
static_cast<ARMv7Thread*>(thread)->GPR[5] = envp.addr();
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
|
@ -0,0 +1,401 @@
|
|||
#include "stdafx.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/ARMv7/PSVFuncList.h"
|
||||
|
||||
extern psv_log_base sceLibKernel;
|
||||
|
||||
typedef s32(*SceKernelThreadEntry)(u32 argSize, vm::psv::ptr<void> pArgBlock);
|
||||
|
||||
struct SceKernelThreadOptParam
|
||||
{
|
||||
u32 size;
|
||||
u32 attr;
|
||||
};
|
||||
|
||||
s32 sceKernelCreateThread(
|
||||
vm::psv::ptr<const char> pName,
|
||||
vm::psv::ptr<SceKernelThreadEntry> entry,
|
||||
s32 initPriority,
|
||||
u32 stackSize,
|
||||
u32 attr,
|
||||
s32 cpuAffinityMask,
|
||||
vm::psv::ptr<const SceKernelThreadOptParam> pOptParam)
|
||||
{
|
||||
sceLibKernel.Todo("sceKernelCreateThread(pName_addr=0x%x ('%s'), entry_addr=0x%x, initPriority=%d, stackSize=0x%x, attr=0x%x, cpuAffinityMask=0x%x, pOptParam_addr=0x%x)",
|
||||
pName.addr(), pName.get_ptr(), entry.addr(), initPriority, stackSize, attr, cpuAffinityMask, pOptParam.addr());
|
||||
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
#define REG_FUNC(nid, name) reg_psv_func(nid, &sceLibKernel, #name, &name)
|
||||
|
||||
psv_log_base sceLibKernel = []() -> psv_log_base
|
||||
{
|
||||
//REG_FUNC(0x23EAA62, sceKernelPuts);
|
||||
//REG_FUNC(0xB0335388, sceClibToupper);
|
||||
//REG_FUNC(0x4C5471BC, sceClibTolower);
|
||||
//REG_FUNC(0xD8EBBB7E, sceClibLookCtypeTable);
|
||||
//REG_FUNC(0x20EC3210, sceClibGetCtypeTable);
|
||||
//REG_FUNC(0x407D6153, sceClibMemchr);
|
||||
//REG_FUNC(0x9CC2BFDF, sceClibMemcmp);
|
||||
//REG_FUNC(0x14E9DBD7, sceClibMemcpy);
|
||||
//REG_FUNC(0x736753C8, sceClibMemmove);
|
||||
//REG_FUNC(0x632980D7, sceClibMemset);
|
||||
//REG_FUNC(0xFA26BC62, sceClibPrintf);
|
||||
//REG_FUNC(0x5EA3B6CE, sceClibVprintf);
|
||||
//REG_FUNC(0x8CBA03D5, sceClibSnprintf);
|
||||
//REG_FUNC(0xFA6BE467, sceClibVsnprintf);
|
||||
//REG_FUNC(0xA2FB4D9D, sceClibStrcmp);
|
||||
//REG_FUNC(0x70CBC2D5, sceClibStrlcat);
|
||||
//REG_FUNC(0x2CDFCD1C, sceClibStrlcpy);
|
||||
//REG_FUNC(0xA37E6383, sceClibStrncat);
|
||||
//REG_FUNC(0x660D1F6D, sceClibStrncmp);
|
||||
//REG_FUNC(0xC458D60A, sceClibStrncpy);
|
||||
//REG_FUNC(0xAC595E68, sceClibStrnlen);
|
||||
//REG_FUNC(0x614076B7, sceClibStrchr);
|
||||
//REG_FUNC(0x6E728AAE, sceClibStrrchr);
|
||||
//REG_FUNC(0xE265498B, sceClibStrstr);
|
||||
//REG_FUNC(0xB54C0BE4, sceClibStrncasecmp);
|
||||
//REG_FUNC(0x2F2C6046, sceClibAbort);
|
||||
//REG_FUNC(0x2E581B88, sceClibStrtoll);
|
||||
//REG_FUNC(0x3B9E301A, sceClibMspaceCreate);
|
||||
//REG_FUNC(0xAE1A21EC, sceClibMspaceDestroy);
|
||||
//REG_FUNC(0x86EF7680, sceClibMspaceMalloc);
|
||||
//REG_FUNC(0x9C56B4D1, sceClibMspaceFree);
|
||||
//REG_FUNC(0x678374AD, sceClibMspaceCalloc);
|
||||
//REG_FUNC(0x3C847D57, sceClibMspaceMemalign);
|
||||
//REG_FUNC(0x774891D6, sceClibMspaceRealloc);
|
||||
//REG_FUNC(0x586AC68D, sceClibMspaceReallocalign);
|
||||
//REG_FUNC(0x46A02279, sceClibMspaceMallocUsableSize);
|
||||
//REG_FUNC(0x8CC1D38E, sceClibMspaceMallocStats);
|
||||
//REG_FUNC(0x738E0322, sceClibMspaceMallocStatsFast);
|
||||
//REG_FUNC(0xD1D59701, sceClibMspaceIsHeapEmpty);
|
||||
//REG_FUNC(0xE960FDA2, sceKernelAtomicSet8);
|
||||
//REG_FUNC(0x450BFECF, sceKernelAtomicSet16);
|
||||
//REG_FUNC(0xB69DA09B, sceKernelAtomicSet32);
|
||||
//REG_FUNC(0xC8A4339C, sceKernelAtomicSet64);
|
||||
//REG_FUNC(0x27A2AAFA, sceKernelAtomicGetAndAdd8);
|
||||
//REG_FUNC(0x5674DB0C, sceKernelAtomicGetAndAdd16);
|
||||
//REG_FUNC(0x2611CB0B, sceKernelAtomicGetAndAdd32);
|
||||
//REG_FUNC(0x63DAF37D, sceKernelAtomicGetAndAdd64);
|
||||
//REG_FUNC(0x8F7BD940, sceKernelAtomicAddAndGet8);
|
||||
//REG_FUNC(0x495C52EC, sceKernelAtomicAddAndGet16);
|
||||
//REG_FUNC(0x2E84A93B, sceKernelAtomicAddAndGet32);
|
||||
//REG_FUNC(0xB6CE9B9A, sceKernelAtomicAddAndGet64);
|
||||
//REG_FUNC(0xCDF5DF67, sceKernelAtomicGetAndSub8);
|
||||
//REG_FUNC(0xAC51979C, sceKernelAtomicGetAndSub16);
|
||||
//REG_FUNC(0x115C516F, sceKernelAtomicGetAndSub32);
|
||||
//REG_FUNC(0x4AE9C8E6, sceKernelAtomicGetAndSub64);
|
||||
//REG_FUNC(0x99E1796E, sceKernelAtomicSubAndGet8);
|
||||
//REG_FUNC(0xC26BBBB1, sceKernelAtomicSubAndGet16);
|
||||
//REG_FUNC(0x1C9CD92, sceKernelAtomicSubAndGet32);
|
||||
//REG_FUNC(0x9BB4A94B, sceKernelAtomicSubAndGet64);
|
||||
//REG_FUNC(0x53DCA02B, sceKernelAtomicGetAndAnd8);
|
||||
//REG_FUNC(0x7A0CB056, sceKernelAtomicGetAndAnd16);
|
||||
//REG_FUNC(0x8266595, sceKernelAtomicGetAndAnd32);
|
||||
//REG_FUNC(0x4828BC43, sceKernelAtomicGetAndAnd64);
|
||||
//REG_FUNC(0x86B9170F, sceKernelAtomicAndAndGet8);
|
||||
//REG_FUNC(0xF9890F7E, sceKernelAtomicAndAndGet16);
|
||||
//REG_FUNC(0x6709D30C, sceKernelAtomicAndAndGet32);
|
||||
//REG_FUNC(0xAED2B370, sceKernelAtomicAndAndGet64);
|
||||
//REG_FUNC(0x107A68DF, sceKernelAtomicGetAndOr8);
|
||||
//REG_FUNC(0x31E49E73, sceKernelAtomicGetAndOr16);
|
||||
//REG_FUNC(0x984AD276, sceKernelAtomicGetAndOr32);
|
||||
//REG_FUNC(0xC39186CD, sceKernelAtomicGetAndOr64);
|
||||
//REG_FUNC(0x51693931, sceKernelAtomicOrAndGet8);
|
||||
//REG_FUNC(0x8E248EBD, sceKernelAtomicOrAndGet16);
|
||||
//REG_FUNC(0xC3B2F7F8, sceKernelAtomicOrAndGet32);
|
||||
//REG_FUNC(0x809BBC7D, sceKernelAtomicOrAndGet64);
|
||||
//REG_FUNC(0x7350B2DF, sceKernelAtomicGetAndXor8);
|
||||
//REG_FUNC(0x6E2D0B9E, sceKernelAtomicGetAndXor16);
|
||||
//REG_FUNC(0x38739E2F, sceKernelAtomicGetAndXor32);
|
||||
//REG_FUNC(0x6A19BBE9, sceKernelAtomicGetAndXor64);
|
||||
//REG_FUNC(0x634AF062, sceKernelAtomicXorAndGet8);
|
||||
//REG_FUNC(0x6F524195, sceKernelAtomicXorAndGet16);
|
||||
//REG_FUNC(0x46940704, sceKernelAtomicXorAndGet32);
|
||||
//REG_FUNC(0xDDC6866E, sceKernelAtomicXorAndGet64);
|
||||
//REG_FUNC(0x327DB4C0, sceKernelAtomicCompareAndSet8);
|
||||
//REG_FUNC(0xE8C01236, sceKernelAtomicCompareAndSet16);
|
||||
//REG_FUNC(0x1124A1D4, sceKernelAtomicCompareAndSet32);
|
||||
//REG_FUNC(0x1EBDFCCD, sceKernelAtomicCompareAndSet64);
|
||||
//REG_FUNC(0xD7D49E36, sceKernelAtomicClearMask8);
|
||||
//REG_FUNC(0x5FE7DFF8, sceKernelAtomicClearMask16);
|
||||
//REG_FUNC(0xE3DF0CB3, sceKernelAtomicClearMask32);
|
||||
//REG_FUNC(0x953D118A, sceKernelAtomicClearMask64);
|
||||
//REG_FUNC(0x7FD94393, sceKernelAtomicAddUnless8);
|
||||
//REG_FUNC(0x1CF4AA4B, sceKernelAtomicAddUnless16);
|
||||
//REG_FUNC(0x4B33FD3C, sceKernelAtomicAddUnless32);
|
||||
//REG_FUNC(0xFFCE7438, sceKernelAtomicAddUnless64);
|
||||
//REG_FUNC(0x9DABE6C3, sceKernelAtomicDecIfPositive8);
|
||||
//REG_FUNC(0x323718FB, sceKernelAtomicDecIfPositive16);
|
||||
//REG_FUNC(0xCA3294F1, sceKernelAtomicDecIfPositive32);
|
||||
//REG_FUNC(0x8BE2A007, sceKernelAtomicDecIfPositive64);
|
||||
//REG_FUNC(0xBBE82155, sceKernelLoadModule);
|
||||
//REG_FUNC(0x2DCC4AFA, sceKernelLoadStartModule);
|
||||
//REG_FUNC(0x702425D5, sceKernelStartModule);
|
||||
//REG_FUNC(0x3B2CBA09, sceKernelStopModule);
|
||||
//REG_FUNC(0x1987920E, sceKernelUnloadModule);
|
||||
//REG_FUNC(0x2415F8A4, sceKernelStopUnloadModule);
|
||||
//REG_FUNC(0x15E2A45D, sceKernelCallModuleExit);
|
||||
//REG_FUNC(0xD11A5103, sceKernelGetModuleInfoByAddr);
|
||||
//REG_FUNC(0x4F2D8B15, sceKernelOpenModule);
|
||||
//REG_FUNC(0x657FA50E, sceKernelCloseModule);
|
||||
//REG_FUNC(0x7595D9AA, sceKernelExitProcess);
|
||||
//REG_FUNC(0x4C7AD128, sceKernelPowerLock);
|
||||
//REG_FUNC(0xAF8E9C11, sceKernelPowerUnlock);
|
||||
//REG_FUNC(0xB295EB61, sceKernelGetTLSAddr);
|
||||
//REG_FUNC(0xFB972F9, sceKernelGetThreadId);
|
||||
//REG_FUNC(0xA37A6057, sceKernelGetCurrentThreadVfpException);
|
||||
//REG_FUNC(0xCA71EA2, sceKernelSendMsgPipe);
|
||||
//REG_FUNC(0xA5CA74AC, sceKernelSendMsgPipeCB);
|
||||
//REG_FUNC(0xDFC670E0, sceKernelTrySendMsgPipe);
|
||||
//REG_FUNC(0x4E81DD5C, sceKernelReceiveMsgPipe);
|
||||
//REG_FUNC(0x33AF829B, sceKernelReceiveMsgPipeCB);
|
||||
//REG_FUNC(0x5615B006, sceKernelTryReceiveMsgPipe);
|
||||
//REG_FUNC(0xA7819967, sceKernelLockLwMutex);
|
||||
//REG_FUNC(0x6F9C4CC1, sceKernelLockLwMutexCB);
|
||||
//REG_FUNC(0x9EF798C1, sceKernelTryLockLwMutex);
|
||||
//REG_FUNC(0x499EA781, sceKernelUnlockLwMutex);
|
||||
//REG_FUNC(0xF7D8F1FC, sceKernelGetLwMutexInfo);
|
||||
//REG_FUNC(0xDDB395A9, sceKernelWaitThreadEnd);
|
||||
//REG_FUNC(0xC54941ED, sceKernelWaitThreadEndCB);
|
||||
//REG_FUNC(0xD5DC26C4, sceKernelGetThreadExitStatus);
|
||||
//REG_FUNC(0x4373B548, __sce_aeabi_idiv0);
|
||||
//REG_FUNC(0xFB235848, __sce_aeabi_ldiv0);
|
||||
//REG_FUNC(0xF08DE149, sceKernelStartThread);
|
||||
//REG_FUNC(0x58DDAC4F, sceKernelDeleteThread);
|
||||
//REG_FUNC(0x5150577B, sceKernelChangeThreadCpuAffinityMask);
|
||||
//REG_FUNC(0x8C57AC2A, sceKernelGetThreadCpuAffinityMask);
|
||||
//REG_FUNC(0xDF7E6EDA, sceKernelChangeThreadPriority);
|
||||
//REG_FUNC(0xBCB63B66, sceKernelGetThreadStackFreeSize);
|
||||
//REG_FUNC(0x8D9C5461, sceKernelGetThreadInfo);
|
||||
//REG_FUNC(0xD6B01013, sceKernelGetThreadRunStatus);
|
||||
//REG_FUNC(0xE0241FAA, sceKernelGetSystemInfo);
|
||||
//REG_FUNC(0xF994FE65, sceKernelGetThreadmgrUIDClass);
|
||||
//REG_FUNC(0xB4DE10C7, sceKernelGetActiveCpuMask);
|
||||
//REG_FUNC(0x2C1321A3, sceKernelChangeThreadVfpException);
|
||||
//REG_FUNC(0x3849359A, sceKernelCreateCallback);
|
||||
//REG_FUNC(0x88DD1BC8, sceKernelGetCallbackInfo);
|
||||
//REG_FUNC(0x464559D3, sceKernelDeleteCallback);
|
||||
//REG_FUNC(0xBD9C8F2B, sceKernelNotifyCallback);
|
||||
//REG_FUNC(0x3137A687, sceKernelCancelCallback);
|
||||
//REG_FUNC(0x76A2EF81, sceKernelGetCallbackCount);
|
||||
//REG_FUNC(0xD4F75281, sceKernelRegisterCallbackToEvent);
|
||||
//REG_FUNC(0x8D3940DF, sceKernelUnregisterCallbackFromEvent);
|
||||
//REG_FUNC(0x2BD1E682, sceKernelUnregisterCallbackFromEventAll);
|
||||
//REG_FUNC(0x120F03AF, sceKernelWaitEvent);
|
||||
//REG_FUNC(0xA0490795, sceKernelWaitEventCB);
|
||||
//REG_FUNC(0x241F3634, sceKernelPollEvent);
|
||||
//REG_FUNC(0x603AB770, sceKernelCancelEvent);
|
||||
//REG_FUNC(0x10586418, sceKernelWaitMultipleEvents);
|
||||
//REG_FUNC(0x4263DBC9, sceKernelWaitMultipleEventsCB);
|
||||
//REG_FUNC(0x8516D040, sceKernelCreateEventFlag);
|
||||
//REG_FUNC(0x11FE9B8B, sceKernelDeleteEventFlag);
|
||||
//REG_FUNC(0xE04EC73A, sceKernelOpenEventFlag);
|
||||
//REG_FUNC(0x9C0B8285, sceKernelCloseEventFlag);
|
||||
//REG_FUNC(0x83C0E2AF, sceKernelWaitEventFlag);
|
||||
//REG_FUNC(0xE737B1DF, sceKernelWaitEventFlagCB);
|
||||
//REG_FUNC(0x1FBB0FE1, sceKernelPollEventFlag);
|
||||
//REG_FUNC(0x2A12D9B7, sceKernelCancelEventFlag);
|
||||
//REG_FUNC(0x8BA4C0C1, sceKernelGetEventFlagInfo);
|
||||
//REG_FUNC(0x9EF9C0C5, sceKernelSetEventFlag);
|
||||
//REG_FUNC(0xD018793F, sceKernelClearEventFlag);
|
||||
//REG_FUNC(0x297AA2AE, sceKernelCreateSema);
|
||||
//REG_FUNC(0xC08F5BC5, sceKernelDeleteSema);
|
||||
//REG_FUNC(0xB028AB78, sceKernelOpenSema);
|
||||
//REG_FUNC(0x817707AB, sceKernelCloseSema);
|
||||
//REG_FUNC(0xC7B834B, sceKernelWaitSema);
|
||||
//REG_FUNC(0x174692B4, sceKernelWaitSemaCB);
|
||||
//REG_FUNC(0x66D6BF05, sceKernelCancelSema);
|
||||
//REG_FUNC(0x595D3FA6, sceKernelGetSemaInfo);
|
||||
//REG_FUNC(0x3012A9C6, sceKernelPollSema);
|
||||
//REG_FUNC(0x2053A496, sceKernelSignalSema);
|
||||
//REG_FUNC(0xED53334A, sceKernelCreateMutex);
|
||||
//REG_FUNC(0x12D11F65, sceKernelDeleteMutex);
|
||||
//REG_FUNC(0x16B85235, sceKernelOpenMutex);
|
||||
//REG_FUNC(0x43DDC9CC, sceKernelCloseMutex);
|
||||
//REG_FUNC(0x1D8D7945, sceKernelLockMutex);
|
||||
//REG_FUNC(0x2BDAA524, sceKernelLockMutexCB);
|
||||
//REG_FUNC(0x2144890D, sceKernelCancelMutex);
|
||||
//REG_FUNC(0x9A6C43CA, sceKernelGetMutexInfo);
|
||||
//REG_FUNC(0xE5901FF9, sceKernelTryLockMutex);
|
||||
//REG_FUNC(0x34746309, sceKernelUnlockMutex);
|
||||
//REG_FUNC(0x50572FDA, sceKernelCreateCond);
|
||||
//REG_FUNC(0xFD295414, sceKernelDeleteCond);
|
||||
//REG_FUNC(0xCB2A73A9, sceKernelOpenCond);
|
||||
//REG_FUNC(0x4FB91A89, sceKernelCloseCond);
|
||||
//REG_FUNC(0xC88D44AD, sceKernelWaitCond);
|
||||
//REG_FUNC(0x4CE42CE2, sceKernelWaitCondCB);
|
||||
//REG_FUNC(0x6864DCE2, sceKernelGetCondInfo);
|
||||
//REG_FUNC(0x10A4976F, sceKernelSignalCond);
|
||||
//REG_FUNC(0x2EB86929, sceKernelSignalCondAll);
|
||||
//REG_FUNC(0x87629E6, sceKernelSignalCondTo);
|
||||
//REG_FUNC(0xA10C1C8, sceKernelCreateMsgPipe);
|
||||
//REG_FUNC(0x69F6575D, sceKernelDeleteMsgPipe);
|
||||
//REG_FUNC(0x230691DA, sceKernelOpenMsgPipe);
|
||||
//REG_FUNC(0x7E5C0C16, sceKernelCloseMsgPipe);
|
||||
//REG_FUNC(0x94D506F7, sceKernelSendMsgPipeVector);
|
||||
//REG_FUNC(0x9C6F7F79, sceKernelSendMsgPipeVectorCB);
|
||||
//REG_FUNC(0x60DB346F, sceKernelTrySendMsgPipeVector);
|
||||
//REG_FUNC(0x9F899087, sceKernelReceiveMsgPipeVector);
|
||||
//REG_FUNC(0xBE5B3E27, sceKernelReceiveMsgPipeVectorCB);
|
||||
//REG_FUNC(0x86ECC0FF, sceKernelTryReceiveMsgPipeVector);
|
||||
//REG_FUNC(0xEF14BA37, sceKernelCancelMsgPipe);
|
||||
//REG_FUNC(0x4046D16B, sceKernelGetMsgPipeInfo);
|
||||
//REG_FUNC(0xDA6EC8EF, sceKernelCreateLwMutex);
|
||||
//REG_FUNC(0x244E76D2, sceKernelDeleteLwMutex);
|
||||
//REG_FUNC(0x4846613D, sceKernelGetLwMutexInfoById);
|
||||
//REG_FUNC(0x48C7EAE6, sceKernelCreateLwCond);
|
||||
//REG_FUNC(0x721F6CB3, sceKernelDeleteLwCond);
|
||||
//REG_FUNC(0xE1878282, sceKernelWaitLwCond);
|
||||
//REG_FUNC(0x8FA54B07, sceKernelWaitLwCondCB);
|
||||
//REG_FUNC(0x3AC63B9A, sceKernelSignalLwCond);
|
||||
//REG_FUNC(0xE5241A0C, sceKernelSignalLwCondAll);
|
||||
//REG_FUNC(0xFC1A48EB, sceKernelSignalLwCondTo);
|
||||
//REG_FUNC(0xE4DF36A0, sceKernelGetLwCondInfo);
|
||||
//REG_FUNC(0x971F1DE8, sceKernelGetLwCondInfoById);
|
||||
//REG_FUNC(0x2255B2A5, sceKernelCreateTimer);
|
||||
//REG_FUNC(0x746F3290, sceKernelDeleteTimer);
|
||||
//REG_FUNC(0x2F3D35A3, sceKernelOpenTimer);
|
||||
//REG_FUNC(0x17283DE6, sceKernelCloseTimer);
|
||||
//REG_FUNC(0x1478249B, sceKernelStartTimer);
|
||||
//REG_FUNC(0x75B1329, sceKernelStopTimer);
|
||||
//REG_FUNC(0x1F59E04D, sceKernelGetTimerBase);
|
||||
//REG_FUNC(0x3223CCD1, sceKernelGetTimerBaseWide);
|
||||
//REG_FUNC(0x381DC300, sceKernelGetTimerTime);
|
||||
//REG_FUNC(0x53C5D833, sceKernelGetTimerTimeWide);
|
||||
//REG_FUNC(0xFFAD717F, sceKernelSetTimerTime);
|
||||
//REG_FUNC(0xAF67678B, sceKernelSetTimerTimeWide);
|
||||
//REG_FUNC(0x621D293B, sceKernelSetTimerEvent);
|
||||
//REG_FUNC(0x9CCF768C, sceKernelCancelTimer);
|
||||
//REG_FUNC(0x7E35E10A, sceKernelGetTimerInfo);
|
||||
//REG_FUNC(0x8667951D, sceKernelCreateRWLock);
|
||||
//REG_FUNC(0x3D750204, sceKernelDeleteRWLock);
|
||||
//REG_FUNC(0xBA4DAC9A, sceKernelOpenRWLock);
|
||||
//REG_FUNC(0xA7F94E64, sceKernelCloseRWLock);
|
||||
//REG_FUNC(0xFA670F0F, sceKernelLockReadRWLock);
|
||||
//REG_FUNC(0x2D4A62B7, sceKernelLockReadRWLockCB);
|
||||
//REG_FUNC(0x1B8586C0, sceKernelTryLockReadRWLock);
|
||||
//REG_FUNC(0x675D10A8, sceKernelUnlockReadRWLock);
|
||||
//REG_FUNC(0x67A187BB, sceKernelLockWriteRWLock);
|
||||
//REG_FUNC(0xA4777082, sceKernelLockWriteRWLockCB);
|
||||
//REG_FUNC(0x597D4607, sceKernelTryLockWriteRWLock);
|
||||
//REG_FUNC(0xD9369DF2, sceKernelUnlockWriteRWLock);
|
||||
//REG_FUNC(0x190CA94B, sceKernelCancelRWLock);
|
||||
//REG_FUNC(0x79A573B, sceKernelGetRWLockInfo);
|
||||
//REG_FUNC(0x8AF15B5F, sceKernelGetSystemTime);
|
||||
//REG_FUNC(0x99B2BF15, sceKernelPMonThreadGetCounter);
|
||||
//REG_FUNC(0x7C21C961, sceKernelPMonCpuGetCounter);
|
||||
//REG_FUNC(0xADCA94E5, sceKernelWaitSignal);
|
||||
//REG_FUNC(0x24460BB3, sceKernelWaitSignalCB);
|
||||
//REG_FUNC(0x7BE9C4C8, sceKernelSendSignal);
|
||||
REG_FUNC(0xC5C11EE7, sceKernelCreateThread);
|
||||
//REG_FUNC(0x6C60AC61, sceIoOpen);
|
||||
//REG_FUNC(0xF5C6F098, sceIoClose);
|
||||
//REG_FUNC(0x713523E1, sceIoRead);
|
||||
//REG_FUNC(0x11FED231, sceIoWrite);
|
||||
//REG_FUNC(0x99BA173E, sceIoLseek);
|
||||
//REG_FUNC(0x5CC983AC, sceIoLseek32);
|
||||
//REG_FUNC(0xE20ED0F3, sceIoRemove);
|
||||
//REG_FUNC(0xF737E369, sceIoRename);
|
||||
//REG_FUNC(0x9670D39F, sceIoMkdir);
|
||||
//REG_FUNC(0xE9F91EC8, sceIoRmdir);
|
||||
//REG_FUNC(0xA9283DD0, sceIoDopen);
|
||||
//REG_FUNC(0x9DFF9C59, sceIoDclose);
|
||||
//REG_FUNC(0x9C8B6624, sceIoDread);
|
||||
//REG_FUNC(0xBCA5B623, sceIoGetstat);
|
||||
//REG_FUNC(0x29482F7F, sceIoChstat);
|
||||
//REG_FUNC(0x98ACED6D, sceIoSync);
|
||||
//REG_FUNC(0x4B30CB2, sceIoDevctl);
|
||||
//REG_FUNC(0x54ABACFA, sceIoIoctl);
|
||||
//REG_FUNC(0x6A7EA9FD, sceIoOpenAsync);
|
||||
//REG_FUNC(0x84201C9B, sceIoCloseAsync);
|
||||
//REG_FUNC(0x7B3BE857, sceIoReadAsync);
|
||||
//REG_FUNC(0x21329B20, sceIoWriteAsync);
|
||||
//REG_FUNC(0xCAC5D672, sceIoLseekAsync);
|
||||
//REG_FUNC(0x99C54B9, sceIoIoctlAsync);
|
||||
//REG_FUNC(0x446A60AC, sceIoRemoveAsync);
|
||||
//REG_FUNC(0x73FC184B, sceIoDopenAsync);
|
||||
//REG_FUNC(0x4D0597D7, sceIoDcloseAsync);
|
||||
//REG_FUNC(0xCE32490D, sceIoDreadAsync);
|
||||
//REG_FUNC(0x8E5FCBB1, sceIoMkdirAsync);
|
||||
//REG_FUNC(0x9694D00F, sceIoRmdirAsync);
|
||||
//REG_FUNC(0xEE9857CD, sceIoRenameAsync);
|
||||
//REG_FUNC(0x9739A5E2, sceIoChstatAsync);
|
||||
//REG_FUNC(0x82B20B41, sceIoGetstatAsync);
|
||||
//REG_FUNC(0x950F78EB, sceIoDevctlAsync);
|
||||
//REG_FUNC(0xF7C7FBFE, sceIoSyncAsync);
|
||||
//REG_FUNC(0xEC96EA71, sceIoCancel);
|
||||
//REG_FUNC(0x857E0C71, sceIoComplete);
|
||||
//REG_FUNC(0x52315AD7, sceIoPread);
|
||||
//REG_FUNC(0x8FFFF5A8, sceIoPwrite);
|
||||
//REG_FUNC(0xA010141E, sceIoPreadAsync);
|
||||
//REG_FUNC(0xED25BEEF, sceIoPwriteAsync);
|
||||
//REG_FUNC(0xA792C404, sceIoCompleteMultiple);
|
||||
//REG_FUNC(0x894037E8, sceKernelBacktrace);
|
||||
//REG_FUNC(0x20E2D4B7, sceKernelPrintBacktrace);
|
||||
//REG_FUNC(0x963F4A99, sceSblACMgrIsGameProgram);
|
||||
//REG_FUNC(0x261E2C34, sceKernelGetOpenPsId);
|
||||
|
||||
/* SceModulemgr */
|
||||
//REG_FUNC(0x36585DAF, sceKernelGetModuleInfo);
|
||||
//REG_FUNC(0x2EF2581F, sceKernelGetModuleList);
|
||||
//REG_FUNC(0xF5798C7C, sceKernelGetModuleIdByAddr);
|
||||
|
||||
/* SceProcessmgr */
|
||||
//REG_FUNC(0xCD248267, sceKernelGetCurrentProcess);
|
||||
//REG_FUNC(0x2252890C, sceKernelPowerTick);
|
||||
//REG_FUNC(0x9E45DA09, sceKernelLibcClock);
|
||||
//REG_FUNC(0x39BE45, sceKernelLibcTime);
|
||||
//REG_FUNC(0x4B879059, sceKernelLibcGettimeofday);
|
||||
//REG_FUNC(0xC1727F59, sceKernelGetStdin);
|
||||
//REG_FUNC(0xE5AA625C, sceKernelGetStdout);
|
||||
//REG_FUNC(0xFA5E3ADA, sceKernelGetStderr);
|
||||
//REG_FUNC(0xE6E9FCA3, sceKernelGetRemoteProcessTime);
|
||||
//REG_FUNC(0xD37A8437, sceKernelGetProcessTime);
|
||||
//REG_FUNC(0xF5D0D4C6, sceKernelGetProcessTimeLow);
|
||||
//REG_FUNC(0x89DA0967, sceKernelGetProcessTimeWide);
|
||||
//REG_FUNC(0x2BE3E066, sceKernelGetProcessParam);
|
||||
|
||||
/* SceStdio */
|
||||
//REG_FUNC(0x54237407, sceKernelStdin);
|
||||
//REG_FUNC(0x9033E9BD, sceKernelStdout);
|
||||
//REG_FUNC(0x35EE7CF5, sceKernelStderr);
|
||||
|
||||
/* SceSysmem */
|
||||
//REG_FUNC(0xB9D5EBDE, sceKernelAllocMemBlock);
|
||||
//REG_FUNC(0xA91E15EE, sceKernelFreeMemBlock);
|
||||
//REG_FUNC(0xB8EF5818, sceKernelGetMemBlockBase);
|
||||
//REG_FUNC(0x3B29E0F5, sceKernelRemapMemBlock);
|
||||
//REG_FUNC(0xA33B99D1, sceKernelFindMemBlockByAddr);
|
||||
//REG_FUNC(0x4010AD65, sceKernelGetMemBlockInfoByAddr);
|
||||
|
||||
/* SceCpu */
|
||||
//REG_FUNC(0x2704CFEE, sceKernelCpuId);
|
||||
|
||||
/* SceDipsw */
|
||||
//REG_FUNC(0x1C783FB2, sceKernelCheckDipsw);
|
||||
//REG_FUNC(0x817053D4, sceKernelSetDipsw);
|
||||
//REG_FUNC(0x800EDCC1, sceKernelClearDipsw);
|
||||
|
||||
/* SceThreadmgr */
|
||||
//REG_FUNC(0xC8A38E1, sceKernelExitThread);
|
||||
//REG_FUNC(0x1D17DECF, sceKernelExitDeleteThread);
|
||||
//REG_FUNC(0x4B675D05, sceKernelDelayThread);
|
||||
//REG_FUNC(0x9C0180E1, sceKernelDelayThreadCB);
|
||||
//REG_FUNC(0x1173F8, sceKernelChangeActiveCpuMask);
|
||||
//REG_FUNC(0x1414F0B, sceKernelGetThreadCurrentPriority);
|
||||
//REG_FUNC(0x751C9B7A, sceKernelChangeCurrentThreadAttr);
|
||||
//REG_FUNC(0xD9BD74EB, sceKernelCheckWaitableStatus);
|
||||
//REG_FUNC(0x9DCB4B7A, sceKernelGetProcessId);
|
||||
//REG_FUNC(0xE53E41F6, sceKernelCheckCallback);
|
||||
//REG_FUNC(0xF4EE4FA9, sceKernelGetSystemTimeWide);
|
||||
//REG_FUNC(0x47F6DE49, sceKernelGetSystemTimeLow);
|
||||
//REG_FUNC(0xC0FAF6A3, sceKernelCreateThreadForUser);
|
||||
|
||||
/* SceDebugLed */
|
||||
//REG_FUNC(0x78E702D3, sceKernelSetGPO);
|
||||
|
||||
return psv_log_base("sceLibKernel");
|
||||
}();
|
|
@ -0,0 +1,352 @@
|
|||
#include "stdafx.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/ARMv7/PSVFuncList.h"
|
||||
|
||||
extern psv_log_base sceLibc;
|
||||
|
||||
namespace sce_libc_func
|
||||
{
|
||||
void __cxa_atexit()
|
||||
{
|
||||
sceLibc.Todo(__FUNCTION__);
|
||||
Emu.Pause();
|
||||
}
|
||||
|
||||
void exit()
|
||||
{
|
||||
sceLibc.Error("exit()");
|
||||
Emu.Pause();
|
||||
|
||||
sceLibc.Success("Process finished");
|
||||
CallAfter([]()
|
||||
{
|
||||
Emu.Stop();
|
||||
});
|
||||
}
|
||||
|
||||
void printf(vm::psv::ptr<const char> fmt)
|
||||
{
|
||||
sceLibc.Error("printf(fmt_addr=0x%x)", fmt.addr());
|
||||
|
||||
LOG_NOTICE(TTY, "%s", fmt.get_ptr());
|
||||
}
|
||||
|
||||
void __cxa_set_dso_handle_main()
|
||||
{
|
||||
sceLibc.Error("__cxa_set_dso_handle_main()");
|
||||
}
|
||||
|
||||
void memcpy(vm::psv::ptr<void> dst, vm::psv::ptr<const void> src, u32 size)
|
||||
{
|
||||
sceLibc.Error("memcpy(dst_addr=0x%x, src_addr=0x%x, size=0x%x)", dst.addr(), src.addr(), size);
|
||||
|
||||
::memcpy(dst.get_ptr(), src.get_ptr(), size);
|
||||
}
|
||||
|
||||
void _Assert()
|
||||
{
|
||||
sceLibc.Todo(__FUNCTION__);
|
||||
Emu.Pause();
|
||||
}
|
||||
}
|
||||
|
||||
#define REG_FUNC(nid, name) reg_psv_func(nid, &sceLibc, #name, &sce_libc_func::name)
|
||||
|
||||
psv_log_base sceLibc = []() -> psv_log_base
|
||||
{
|
||||
REG_FUNC(0xE4531F85, _Assert);
|
||||
//REG_FUNC(0xE71C5CDE, _Stoul);
|
||||
//REG_FUNC(0x7A5CA6A3, _Stoulx);
|
||||
//REG_FUNC(0x6794B3C6, _Stoull);
|
||||
//REG_FUNC(0xD00F68FD, _Stoullx);
|
||||
//REG_FUNC(0xBF94193B, _Stod);
|
||||
//REG_FUNC(0x6798AA28, _Stodx);
|
||||
//REG_FUNC(0x784D8D95, _Stof);
|
||||
//REG_FUNC(0x99A49A62, _Stofx);
|
||||
//REG_FUNC(0x5AE9FFD8, _Stold);
|
||||
//REG_FUNC(0x448A3CBE, _Stoldx);
|
||||
//REG_FUNC(0x6B9E23FE, _Stoll);
|
||||
//REG_FUNC(0x0D9E3B1C, _Stollx);
|
||||
//REG_FUNC(0x52DDCDAF, _Stolx);
|
||||
//REG_FUNC(0x76904D60, _Wctomb);
|
||||
//REG_FUNC(0x5E56EA4E, _Mbtowc);
|
||||
//REG_FUNC(0xDEC462AB, _FCbuild);
|
||||
//REG_FUNC(0x9E248B76, _sceLibcErrnoLoc);
|
||||
//REG_FUNC(0xA2F50E9E, _Fltrounds);
|
||||
//REG_FUNC(0x7CC1B964, isalnum);
|
||||
//REG_FUNC(0x94A89A00, isalpha);
|
||||
//REG_FUNC(0xF894ECCB, isblank);
|
||||
//REG_FUNC(0x13F4A8C8, iscntrl);
|
||||
//REG_FUNC(0xEB93BC93, isdigit);
|
||||
//REG_FUNC(0xDFEEFB1A, isgraph);
|
||||
//REG_FUNC(0x465B93F1, islower);
|
||||
//REG_FUNC(0xB7F87C4D, isprint);
|
||||
//REG_FUNC(0x82C1E3FD, ispunct);
|
||||
//REG_FUNC(0x18F2A715, isspace);
|
||||
//REG_FUNC(0xF2012814, isupper);
|
||||
//REG_FUNC(0x3B561695, isxdigit);
|
||||
//REG_FUNC(0x83F73C88, tolower);
|
||||
//REG_FUNC(0x1218642B, toupper);
|
||||
//REG_FUNC(0x1118B49F, imaxabs);
|
||||
//REG_FUNC(0x5766B4A8, imaxdiv);
|
||||
//REG_FUNC(0xB45FD61E, strtoimax);
|
||||
//REG_FUNC(0xB318952F, strtoumax);
|
||||
//REG_FUNC(0x3F2D104F, wcstoimax);
|
||||
//REG_FUNC(0xB9E511B4, wcstoumax);
|
||||
//REG_FUNC(0xCEF7C575, mspace_create);
|
||||
//REG_FUNC(0x30CBBC66, mspace_destroy);
|
||||
//REG_FUNC(0xE080B96E, mspace_malloc);
|
||||
//REG_FUNC(0x3CDFD2A3, mspace_free);
|
||||
//REG_FUNC(0x30470BBA, mspace_calloc);
|
||||
//REG_FUNC(0x52F780DD, mspace_memalign);
|
||||
//REG_FUNC(0x4633134A, mspace_realloc);
|
||||
//REG_FUNC(0x915DA59E, mspace_reallocalign);
|
||||
//REG_FUNC(0x7AD7A737, mspace_malloc_usable_size);
|
||||
//REG_FUNC(0x8D2A14C4, mspace_malloc_stats);
|
||||
//REG_FUNC(0x2FF5D5BB, mspace_malloc_stats_fast);
|
||||
//REG_FUNC(0xF355F381, mspace_is_heap_empty);
|
||||
//REG_FUNC(0x50B326CE, setjmp);
|
||||
//REG_FUNC(0x2D81C8C8, longjmp);
|
||||
//REG_FUNC(0x72BA4468, clearerr);
|
||||
//REG_FUNC(0xEC97321C, fclose);
|
||||
//REG_FUNC(0xB2F318FE, fdopen);
|
||||
//REG_FUNC(0xBF96AD71, feof);
|
||||
//REG_FUNC(0xB724BFC1, ferror);
|
||||
//REG_FUNC(0x5AAD2996, fflush);
|
||||
//REG_FUNC(0x672C58E0, fgetc);
|
||||
//REG_FUNC(0x3CDA3118, fgetpos);
|
||||
//REG_FUNC(0xBA14322F, fgets);
|
||||
//REG_FUNC(0xFEC1502E, fileno);
|
||||
//REG_FUNC(0xFFFBE239, fopen);
|
||||
//REG_FUNC(0xE0C79764, fprintf);
|
||||
//REG_FUNC(0x7E6A6108, fputc);
|
||||
//REG_FUNC(0xC8FF13E5, fputs);
|
||||
//REG_FUNC(0xB31C73A9, fread);
|
||||
//REG_FUNC(0x715C4395, freopen);
|
||||
//REG_FUNC(0x505601C6, fscanf);
|
||||
//REG_FUNC(0xC3A7CDE1, fseek);
|
||||
//REG_FUNC(0xDC1BDBD7, fsetpos);
|
||||
//REG_FUNC(0x41C2AF95, ftell);
|
||||
//REG_FUNC(0x8BCDCC4E, fwrite);
|
||||
//REG_FUNC(0x4BD5212E, getc);
|
||||
//REG_FUNC(0x4790BF1E, getchar);
|
||||
//REG_FUNC(0xF97B8CA3, gets);
|
||||
//REG_FUNC(0x4696E7BE, perror);
|
||||
REG_FUNC(0x9a004680, printf);
|
||||
//REG_FUNC(0x995708A6, putc);
|
||||
//REG_FUNC(0x7CDAC89C, putchar);
|
||||
//REG_FUNC(0x59C3E171, puts);
|
||||
//REG_FUNC(0x40293B75, remove);
|
||||
//REG_FUNC(0x6FE983A3, rename);
|
||||
//REG_FUNC(0x6CA5BAB9, rewind);
|
||||
//REG_FUNC(0x9CB9D899, scanf);
|
||||
//REG_FUNC(0x395490DA, setbuf);
|
||||
//REG_FUNC(0x2CA980A0, setvbuf);
|
||||
//REG_FUNC(0xA1BFF606, snprintf);
|
||||
//REG_FUNC(0x7449B359, sprintf);
|
||||
//REG_FUNC(0xEC585241, sscanf);
|
||||
//REG_FUNC(0x2BCB3F01, ungetc);
|
||||
//REG_FUNC(0xF7915685, vfprintf);
|
||||
//REG_FUNC(0xF137771A, vfscanf);
|
||||
//REG_FUNC(0xE7B5E23E, vprintf);
|
||||
//REG_FUNC(0x0E9BD318, vscanf);
|
||||
//REG_FUNC(0xFE83F2E4, vsnprintf);
|
||||
//REG_FUNC(0x802FDDF9, vsprintf);
|
||||
//REG_FUNC(0xA9889307, vsscanf);
|
||||
//REG_FUNC(0x20FE0FFF, abort);
|
||||
//REG_FUNC(0x8E5A06C5, abs);
|
||||
//REG_FUNC(0xD500DE27, atof);
|
||||
//REG_FUNC(0x21493BE7, atoi);
|
||||
//REG_FUNC(0xA1DBEE9F, atol);
|
||||
//REG_FUNC(0x875994F3, atoll);
|
||||
//REG_FUNC(0xD1BC28E7, bsearch);
|
||||
//REG_FUNC(0xE9F823C0, div);
|
||||
REG_FUNC(0x826bbbaf, exit);
|
||||
//REG_FUNC(0xB53B345B, _Exit);
|
||||
//REG_FUNC(0xBCEA304B, labs);
|
||||
//REG_FUNC(0x9D2D17CD, llabs);
|
||||
//REG_FUNC(0xD63330DA, ldiv);
|
||||
//REG_FUNC(0x3F887699, lldiv);
|
||||
//REG_FUNC(0x3E347849, mblen);
|
||||
//REG_FUNC(0x2F75CF9B, mbstowcs);
|
||||
//REG_FUNC(0xD791A952, mbtowc);
|
||||
//REG_FUNC(0xA7CBE4A6, qsort);
|
||||
//REG_FUNC(0x6CA88B08, strtod);
|
||||
//REG_FUNC(0x6CB8540E, strtof);
|
||||
//REG_FUNC(0x181827ED, strtol);
|
||||
//REG_FUNC(0x48C684B2, strtold);
|
||||
//REG_FUNC(0x39B7E681, strtoll);
|
||||
//REG_FUNC(0xF34AE312, strtoul);
|
||||
//REG_FUNC(0xE0E12333, strtoull);
|
||||
//REG_FUNC(0x9A8F7FC0, wcstombs);
|
||||
//REG_FUNC(0x6489B5E4, wctomb);
|
||||
//REG_FUNC(0xC0883865, rand);
|
||||
//REG_FUNC(0x3AAD41B0, srand);
|
||||
//REG_FUNC(0x962097AA, rand_r);
|
||||
//REG_FUNC(0x775A0CB2, malloc);
|
||||
//REG_FUNC(0xE7EC3D0B, calloc);
|
||||
//REG_FUNC(0x006B54BA, realloc);
|
||||
//REG_FUNC(0x5B9BB802, free);
|
||||
//REG_FUNC(0xA9363E6B, memalign);
|
||||
//REG_FUNC(0x608AC135, reallocalign);
|
||||
//REG_FUNC(0x57A729DB, malloc_stats);
|
||||
//REG_FUNC(0xB3D29DE1, malloc_stats_fast);
|
||||
//REG_FUNC(0x54A54EB1, malloc_usable_size);
|
||||
//REG_FUNC(0x2F3E5B16, memchr);
|
||||
//REG_FUNC(0x7747F6D7, memcmp);
|
||||
REG_FUNC(0x7205BFDB, memcpy);
|
||||
//REG_FUNC(0xAF5C218D, memmove);
|
||||
//REG_FUNC(0x6DC1F0D8, memset);
|
||||
//REG_FUNC(0x1434FA46, strcat);
|
||||
//REG_FUNC(0xB9336E16, strchr);
|
||||
//REG_FUNC(0x1B58FA3B, strcmp);
|
||||
//REG_FUNC(0x46AE2311, strcoll);
|
||||
//REG_FUNC(0x85B924B7, strcpy);
|
||||
//REG_FUNC(0x0E29D27A, strcspn);
|
||||
//REG_FUNC(0x1E9D6335, strerror);
|
||||
//REG_FUNC(0x8AECC873, strlen);
|
||||
//REG_FUNC(0xFBA69BC2, strncat);
|
||||
//REG_FUNC(0xE4299DCB, strncmp);
|
||||
//REG_FUNC(0x9F87712D, strncpy);
|
||||
//REG_FUNC(0x68C307B6, strpbrk);
|
||||
//REG_FUNC(0xCEFDD143, strrchr);
|
||||
//REG_FUNC(0x4203B663, strspn);
|
||||
//REG_FUNC(0x0D5200CB, strstr);
|
||||
//REG_FUNC(0x0289B8B3, strtok);
|
||||
//REG_FUNC(0x4D023DE9, strxfrm);
|
||||
//REG_FUNC(0xEB31926D, strtok_r);
|
||||
//REG_FUNC(0xFF6F77C7, strdup);
|
||||
//REG_FUNC(0x184C4B07, strcasecmp);
|
||||
//REG_FUNC(0xAF1CA2F1, strncasecmp);
|
||||
//REG_FUNC(0xC94AE948, asctime);
|
||||
//REG_FUNC(0xC082CA03, clock);
|
||||
//REG_FUNC(0x1EA1CA8D, ctime);
|
||||
//REG_FUNC(0x33AD70A0, difftime);
|
||||
//REG_FUNC(0xF283CFE3, gmtime);
|
||||
//REG_FUNC(0xF4A2E0BF, localtime);
|
||||
//REG_FUNC(0xD1A2DFC3, mktime);
|
||||
//REG_FUNC(0xEEB76FED, strftime);
|
||||
//REG_FUNC(0xDAE8D60F, time);
|
||||
//REG_FUNC(0xEFB3BC61, btowc);
|
||||
//REG_FUNC(0x1D1DA5AD, _Btowc);
|
||||
//REG_FUNC(0x89541CA5, fgetwc);
|
||||
//REG_FUNC(0x982AFA4D, fgetws);
|
||||
//REG_FUNC(0xA597CDC8, fputwc);
|
||||
//REG_FUNC(0xB755927C, fputws);
|
||||
//REG_FUNC(0xA77327D2, fwide);
|
||||
//REG_FUNC(0xE52278E8, fwprintf);
|
||||
//REG_FUNC(0x7BFC75C6, fwscanf);
|
||||
//REG_FUNC(0x23E0F442, getwc);
|
||||
//REG_FUNC(0x55DB4E32, getwchar);
|
||||
//REG_FUNC(0x1927CAE8, mbrlen);
|
||||
//REG_FUNC(0x910664C3, mbrtowc);
|
||||
//REG_FUNC(0x961D12F8, mbsinit);
|
||||
//REG_FUNC(0x9C14D58E, mbsrtowcs);
|
||||
//REG_FUNC(0x247C71A6, putwc);
|
||||
//REG_FUNC(0x3E04AB1C, putwchar);
|
||||
//REG_FUNC(0x1B581BEB, swprintf);
|
||||
//REG_FUNC(0xE1D2AE42, swscanf);
|
||||
//REG_FUNC(0x39334D9C, ungetwc);
|
||||
//REG_FUNC(0x36BF1E06, vfwprintf);
|
||||
//REG_FUNC(0x37A563BE, vfwscanf);
|
||||
//REG_FUNC(0x572DAB57, vswprintf);
|
||||
//REG_FUNC(0x9451EE20, vswscanf);
|
||||
//REG_FUNC(0x0A451B11, vwprintf);
|
||||
//REG_FUNC(0xAD0C43DC, vwscanf);
|
||||
//REG_FUNC(0xD9FF289D, wcrtomb);
|
||||
//REG_FUNC(0x2F990FF9, wcscat);
|
||||
//REG_FUNC(0xC1587971, wcschr);
|
||||
//REG_FUNC(0xF42128B9, wcscmp);
|
||||
//REG_FUNC(0x8EC70609, wcscoll);
|
||||
//REG_FUNC(0x8AAADD56, wcscpy);
|
||||
//REG_FUNC(0x25F7E46A, wcscspn);
|
||||
//REG_FUNC(0x74136BC1, wcsftime);
|
||||
//REG_FUNC(0xA778A14B, wcslen);
|
||||
//REG_FUNC(0x196AB9F2, wcsncat);
|
||||
//REG_FUNC(0xAAA6AAA2, wcsncmp);
|
||||
//REG_FUNC(0x62E9B2D5, wcsncpy);
|
||||
//REG_FUNC(0x07F229DB, wcspbrk);
|
||||
//REG_FUNC(0xDF806521, wcsrchr);
|
||||
//REG_FUNC(0xD8889FC8, wcsrtombs);
|
||||
//REG_FUNC(0x5F5AA692, wcsspn);
|
||||
//REG_FUNC(0x5BE328EE, wcsstr);
|
||||
//REG_FUNC(0x35D7F1B1, wcstod);
|
||||
//REG_FUNC(0x322243A8, _WStod);
|
||||
//REG_FUNC(0x64123137, wcstof);
|
||||
//REG_FUNC(0x340AF0F7, _WStof);
|
||||
//REG_FUNC(0xA17C24A3, wcstok);
|
||||
//REG_FUNC(0xFBEB657E, wcstol);
|
||||
//REG_FUNC(0x2D7C3A7A, wcstold);
|
||||
//REG_FUNC(0x1EDA8F09, _WStold);
|
||||
//REG_FUNC(0x6EEFB7D7, wcstoll);
|
||||
//REG_FUNC(0xACF13D54, wcstoul);
|
||||
//REG_FUNC(0x87C94271, _WStoul);
|
||||
//REG_FUNC(0xCBFF8200, wcstoull);
|
||||
//REG_FUNC(0xF6069AFD, wcsxfrm);
|
||||
//REG_FUNC(0x704321CC, wctob);
|
||||
//REG_FUNC(0x2F0C81A6, _Wctob);
|
||||
//REG_FUNC(0x7A08BE70, wmemchr);
|
||||
//REG_FUNC(0x9864C99F, wmemcmp);
|
||||
//REG_FUNC(0xD9F9DDCD, wmemcpy);
|
||||
//REG_FUNC(0x53F7EB4B, wmemmove);
|
||||
//REG_FUNC(0x4D04A480, wmemset);
|
||||
//REG_FUNC(0xBF2F5FCE, wprintf);
|
||||
//REG_FUNC(0xADC32204, wscanf);
|
||||
//REG_FUNC(0x7E811AF2, iswalnum);
|
||||
//REG_FUNC(0xC5ECB7B6, iswalpha);
|
||||
//REG_FUNC(0xC8FC4BBE, iswblank);
|
||||
//REG_FUNC(0xC30AE3C7, iswcntrl);
|
||||
//REG_FUNC(0x9E348712, iswctype);
|
||||
//REG_FUNC(0xC37DB2C2, iswdigit);
|
||||
//REG_FUNC(0x70632234, iswgraph);
|
||||
//REG_FUNC(0x40F84B7D, iswlower);
|
||||
//REG_FUNC(0xF52F9241, iswprint);
|
||||
//REG_FUNC(0x3922B91A, iswpunct);
|
||||
//REG_FUNC(0x2BDA4905, iswspace);
|
||||
//REG_FUNC(0x9939E1AD, iswupper);
|
||||
//REG_FUNC(0x82FCEFA4, iswxdigit);
|
||||
//REG_FUNC(0x09C38DE4, towlower);
|
||||
//REG_FUNC(0xCF77D465, towctrans);
|
||||
//REG_FUNC(0xCACE34B9, towupper);
|
||||
//REG_FUNC(0xE8270951, wctrans);
|
||||
//REG_FUNC(0xA967B88D, wctype);
|
||||
//REG_FUNC(0x9D885076, _Towctrans);
|
||||
//REG_FUNC(0xE980110A, _Iswctype);
|
||||
REG_FUNC(0x33b83b70, __cxa_atexit);
|
||||
//REG_FUNC(0xEDC939E1, __aeabi_atexit);
|
||||
//REG_FUNC(0xB538BF48, __cxa_finalize);
|
||||
//REG_FUNC(0xD0310E31, __cxa_guard_acquire);
|
||||
//REG_FUNC(0x4ED1056F, __cxa_guard_release);
|
||||
//REG_FUNC(0xD18E461D, __cxa_guard_abort);
|
||||
REG_FUNC(0xbfe02b3a, __cxa_set_dso_handle_main);
|
||||
//REG_FUNC(0x64DA2C47, _Unlocksyslock);
|
||||
//REG_FUNC(0x7DBC0575, _Locksyslock);
|
||||
//REG_FUNC(0x5044FC32, _Lockfilelock);
|
||||
//REG_FUNC(0xFD5DD98C, _Unlockfilelock);
|
||||
//REG_FUNC(0x1EFFBAC2, __set_exidx_main);
|
||||
//REG_FUNC(0x855FC605, _Files);
|
||||
//REG_FUNC(0x66B7406C, _Stdin);
|
||||
//REG_FUNC(0x5D8C1282, _Stdout);
|
||||
//REG_FUNC(0xDDF9BB09, _Stderr);
|
||||
//REG_FUNC(0x3CE6109D, _Ctype);
|
||||
//REG_FUNC(0x36878958, _Touptab);
|
||||
//REG_FUNC(0xD662E07C, _Tolotab);
|
||||
//REG_FUNC(0xE5620A03, _Flt);
|
||||
//REG_FUNC(0x338FE545, _Dbl);
|
||||
//REG_FUNC(0x94CE931C, _Ldbl);
|
||||
//REG_FUNC(0xF708906E, _Denorm);
|
||||
//REG_FUNC(0x01B05132, _FDenorm);
|
||||
//REG_FUNC(0x2C8DBEB7, _LDenorm);
|
||||
//REG_FUNC(0x710B5F33, _Inf);
|
||||
//REG_FUNC(0x8A0F308C, _FInf);
|
||||
//REG_FUNC(0x5289BBC0, _LInf);
|
||||
//REG_FUNC(0x116F3DA9, _Nan);
|
||||
//REG_FUNC(0x415162DD, _FNan);
|
||||
//REG_FUNC(0x036D0F07, _LNan);
|
||||
//REG_FUNC(0x677CDE35, _Snan);
|
||||
//REG_FUNC(0x7D35108B, _FSnan);
|
||||
//REG_FUNC(0x48AEEF2A, _LSnan);
|
||||
|
||||
return psv_log_base("SceLibc");
|
||||
}();
|
|
@ -0,0 +1,217 @@
|
|||
#include "stdafx.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/ARMv7/PSVFuncList.h"
|
||||
|
||||
extern psv_log_base sceLibm;
|
||||
|
||||
namespace sce_libm_func
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#define REG_FUNC(nid, name) reg_psv_func(nid, &sceLibm, #name, &sce_libm_func::name)
|
||||
|
||||
psv_log_base sceLibm = []() -> psv_log_base
|
||||
{
|
||||
//REG_FUNC(0xC73FE76D, _Exp);
|
||||
//REG_FUNC(0xFF4EAE04, _FExp);
|
||||
//REG_FUNC(0xB363D7D4, _LExp);
|
||||
//REG_FUNC(0xD72B5ACB, acos);
|
||||
//REG_FUNC(0x27EAB8C1, acosf);
|
||||
//REG_FUNC(0x1C053D0F, acosh);
|
||||
//REG_FUNC(0x568ECFB0, acoshf);
|
||||
//REG_FUNC(0xD3D6D36E, acoshl);
|
||||
//REG_FUNC(0x3210F395, acosl);
|
||||
//REG_FUNC(0x4016B2E6, asin);
|
||||
//REG_FUNC(0x3A3E5424, asinf);
|
||||
//REG_FUNC(0x7C93F1DD, asinh);
|
||||
//REG_FUNC(0x285AEDEA, asinhf);
|
||||
//REG_FUNC(0x9496E15E, asinhl);
|
||||
//REG_FUNC(0x1724A81D, asinl);
|
||||
//REG_FUNC(0x516D9970, atan);
|
||||
//REG_FUNC(0xC9BE3F05, atan2);
|
||||
//REG_FUNC(0x4E09DD53, atan2f);
|
||||
//REG_FUNC(0xCE325597, atan2l);
|
||||
//REG_FUNC(0xD78FC94E, atanf);
|
||||
//REG_FUNC(0x434BCE01, atanh);
|
||||
//REG_FUNC(0xC7B0AFBA, atanhf);
|
||||
//REG_FUNC(0x6A6881A6, atanhl);
|
||||
//REG_FUNC(0xD423A4AB, atanl);
|
||||
//REG_FUNC(0xACC0DC5A, cbrt);
|
||||
//REG_FUNC(0xD1699F4D, cbrtf);
|
||||
//REG_FUNC(0x342F9501, cbrtl);
|
||||
//REG_FUNC(0x63F05BD6, ceil);
|
||||
//REG_FUNC(0x6BBFEC89, ceilf);
|
||||
//REG_FUNC(0x48082D81, ceill);
|
||||
//REG_FUNC(0xB918D13, copysign);
|
||||
//REG_FUNC(0x16EB9E63, copysignf);
|
||||
//REG_FUNC(0x19DFC0AA, copysignl);
|
||||
//REG_FUNC(0x61D0244, cos);
|
||||
//REG_FUNC(0x127F8302, cosf);
|
||||
//REG_FUNC(0x89B9BE1F, cosl);
|
||||
//REG_FUNC(0x110195E7, cosh);
|
||||
//REG_FUNC(0x61DE0770, coshf);
|
||||
//REG_FUNC(0x7EADDC5E, coshl);
|
||||
//REG_FUNC(0x4B84C012, _Cosh);
|
||||
//REG_FUNC(0x15993458, erf);
|
||||
//REG_FUNC(0x524AEBFE, erfc);
|
||||
//REG_FUNC(0x301F113, erfcf);
|
||||
//REG_FUNC(0xD4C92471, erfcl);
|
||||
//REG_FUNC(0x41DD1AB8, erff);
|
||||
//REG_FUNC(0xFD431619, erfl);
|
||||
//REG_FUNC(0xEB027358, exp);
|
||||
//REG_FUNC(0x9B18F38F, exp2);
|
||||
//REG_FUNC(0x79415BD3, exp2f);
|
||||
//REG_FUNC(0x40053307, exp2l);
|
||||
//REG_FUNC(0x56473BC7, expf);
|
||||
//REG_FUNC(0xA71A81AA, expl);
|
||||
//REG_FUNC(0x2A97A75F, expm1);
|
||||
//REG_FUNC(0x64131D7B, expm1f);
|
||||
//REG_FUNC(0x8BF1866C, expm1l);
|
||||
//REG_FUNC(0x3E672BE3, fabs);
|
||||
//REG_FUNC(0x75348906, fabsf);
|
||||
//REG_FUNC(0x3ECA514, fabsl);
|
||||
//REG_FUNC(0xA278B20D, _FCosh);
|
||||
//REG_FUNC(0xD6FD5A2E, fdim);
|
||||
//REG_FUNC(0x8B6CC137, fdimf);
|
||||
//REG_FUNC(0xE6988B7B, fdiml);
|
||||
//REG_FUNC(0xD5BD8D5C, _FLog);
|
||||
//REG_FUNC(0x22BB8237, floor);
|
||||
//REG_FUNC(0xCD7C05BD, floorf);
|
||||
//REG_FUNC(0xFDFA4558, floorl);
|
||||
//REG_FUNC(0x1EACA585, fma);
|
||||
//REG_FUNC(0xB61672A7, fmaf);
|
||||
//REG_FUNC(0xBCF6EA7C, fmal);
|
||||
//REG_FUNC(0xBE30CC1E, fmax);
|
||||
//REG_FUNC(0x7004FA75, fmaxf);
|
||||
//REG_FUNC(0xBF5AF69E, fmaxl);
|
||||
//REG_FUNC(0x2ABBDFF7, fmin);
|
||||
//REG_FUNC(0x7673CC1E, fminf);
|
||||
//REG_FUNC(0xE2F5A0F0, fminl);
|
||||
//REG_FUNC(0x798587E4, fmod);
|
||||
//REG_FUNC(0x1CD8F88E, fmodf);
|
||||
//REG_FUNC(0x986011B4, fmodl);
|
||||
//REG_FUNC(0x59197427, frexp);
|
||||
//REG_FUNC(0xA6879AC, frexpf);
|
||||
//REG_FUNC(0x6DC8D877, frexpl);
|
||||
//REG_FUNC(0x4A496BC0, _FSin);
|
||||
//REG_FUNC(0x7FBB4C55, _FSinh);
|
||||
//REG_FUNC(0x2D2CD795, hypot);
|
||||
//REG_FUNC(0xA397B929, hypotf);
|
||||
//REG_FUNC(0x5BFBEE8, hypotl);
|
||||
//REG_FUNC(0x667EE864, ilogb);
|
||||
//REG_FUNC(0x80050A43, ilogbf);
|
||||
//REG_FUNC(0x91298DCA, ilogbl);
|
||||
//REG_FUNC(0x197C9D5, _LCosh);
|
||||
//REG_FUNC(0x56061B, ldexp);
|
||||
//REG_FUNC(0xE61E016, ldexpf);
|
||||
//REG_FUNC(0x8280A7B1, ldexpl);
|
||||
//REG_FUNC(0x2480AA54, lgamma);
|
||||
//REG_FUNC(0x2D9556D5, lgammaf);
|
||||
//REG_FUNC(0xADEBD201, lgammal);
|
||||
//REG_FUNC(0x5B05329D, _LLog);
|
||||
//REG_FUNC(0x7B41AC38, llrint);
|
||||
//REG_FUNC(0xC1F6135B, llrintf);
|
||||
//REG_FUNC(0x80558247, llrintl);
|
||||
//REG_FUNC(0xD1251A18, llround);
|
||||
//REG_FUNC(0x4595A04, llroundf);
|
||||
//REG_FUNC(0x9AB5C7AF, llroundl);
|
||||
//REG_FUNC(0x6037C48F, log);
|
||||
//REG_FUNC(0x811ED68B, logf);
|
||||
//REG_FUNC(0xC6FFBCD6, logl);
|
||||
//REG_FUNC(0x67E99979, _Log);
|
||||
//REG_FUNC(0x2CBE04D7, log1p);
|
||||
//REG_FUNC(0xF1D7C851, log1pf);
|
||||
//REG_FUNC(0x3359152C, log1pl);
|
||||
//REG_FUNC(0xCF65F098, log10);
|
||||
//REG_FUNC(0xFD2A3464, log10f);
|
||||
//REG_FUNC(0x3D7E7201, log10l);
|
||||
//REG_FUNC(0x73AFEE5F, log2);
|
||||
//REG_FUNC(0x4095DBDB, log2f);
|
||||
//REG_FUNC(0x720021A9, log2l);
|
||||
//REG_FUNC(0x5EAE8AD4, logb);
|
||||
//REG_FUNC(0x25F51CE, logbf);
|
||||
//REG_FUNC(0x86C4B75F, logbl);
|
||||
//REG_FUNC(0x207307D0, lrint);
|
||||
//REG_FUNC(0xDA903135, lrintf);
|
||||
//REG_FUNC(0xE8C1F6F8, lrintl);
|
||||
//REG_FUNC(0xD35AFD56, lround);
|
||||
//REG_FUNC(0xA24C6453, lroundf);
|
||||
//REG_FUNC(0x8B3ACA4E, lroundl);
|
||||
//REG_FUNC(0xB397FE83, _LSin);
|
||||
//REG_FUNC(0xF247EE99, _LSinh);
|
||||
//REG_FUNC(0x1167B5D2, modf);
|
||||
//REG_FUNC(0x5D7A7EB2, modff);
|
||||
//REG_FUNC(0xD41D68F2, modfl);
|
||||
//REG_FUNC(0xC3FCA1FA, nan);
|
||||
//REG_FUNC(0xB4761D24, nanf);
|
||||
//REG_FUNC(0xBFA96D93, nanl);
|
||||
//REG_FUNC(0x877187C4, nearbyint);
|
||||
//REG_FUNC(0xD56E78F6, nearbyintf);
|
||||
//REG_FUNC(0x8DD794DC, nearbyintl);
|
||||
//REG_FUNC(0xE1A3D449, nextafter);
|
||||
//REG_FUNC(0xC8A94A33, nextafterf);
|
||||
//REG_FUNC(0xEAAB2055, nextafterl);
|
||||
//REG_FUNC(0x39E605E6, nexttoward);
|
||||
//REG_FUNC(0xDD652D4E, nexttowardf);
|
||||
//REG_FUNC(0x41E6AEA4, nexttowardl);
|
||||
//REG_FUNC(0x640DB443, pow);
|
||||
//REG_FUNC(0x6DEA815A, powf);
|
||||
//REG_FUNC(0x96328F3D, powl);
|
||||
//REG_FUNC(0xE4D6117F, remainder);
|
||||
//REG_FUNC(0xE6BB3DCF, remainderf);
|
||||
//REG_FUNC(0x354E568E, remainderl);
|
||||
//REG_FUNC(0x52337926, remquo);
|
||||
//REG_FUNC(0xD8F6B5D3, remquof);
|
||||
//REG_FUNC(0xBB353F24, remquol);
|
||||
//REG_FUNC(0x943F218F, rint);
|
||||
//REG_FUNC(0xCACE5A19, rintf);
|
||||
//REG_FUNC(0xE3C097E0, rintl);
|
||||
//REG_FUNC(0x64D37996, round);
|
||||
//REG_FUNC(0xAAF31896, roundf);
|
||||
//REG_FUNC(0x9AB1B1B1, roundl);
|
||||
//REG_FUNC(0x8F8CF628, scalbln);
|
||||
//REG_FUNC(0xDEB0A2D0, scalblnf);
|
||||
//REG_FUNC(0x2113921E, scalblnl);
|
||||
//REG_FUNC(0x569758D0, scalbn);
|
||||
//REG_FUNC(0x78F70588, scalbnf);
|
||||
//REG_FUNC(0x777C7463, scalbnl);
|
||||
//REG_FUNC(0xB5519FF0, sin);
|
||||
//REG_FUNC(0x7F00B590, sinf);
|
||||
//REG_FUNC(0x3294447C, sinl);
|
||||
//REG_FUNC(0xD92A7F85, _Sin);
|
||||
//REG_FUNC(0xF2C0AF49, sinh);
|
||||
//REG_FUNC(0xB5838E7D, sinhf);
|
||||
//REG_FUNC(0x4B91F2E6, sinhl);
|
||||
//REG_FUNC(0x40E42E8E, _Sinh);
|
||||
//REG_FUNC(0xDA227FCC, sqrt);
|
||||
//REG_FUNC(0xBA3F6937, sqrtf);
|
||||
//REG_FUNC(0xC1343477, sqrtl);
|
||||
//REG_FUNC(0x5BAE40B0, tan);
|
||||
//REG_FUNC(0xA98E941B, tanf);
|
||||
//REG_FUNC(0x26CD78CA, tanh);
|
||||
//REG_FUNC(0xC4847578, tanhf);
|
||||
//REG_FUNC(0x14F2BEA1, tanhl);
|
||||
//REG_FUNC(0xDC742A5E, tanl);
|
||||
//REG_FUNC(0x3A7FE686, tgamma);
|
||||
//REG_FUNC(0xE6067AC0, tgammaf);
|
||||
//REG_FUNC(0x2949109F, tgammal);
|
||||
//REG_FUNC(0x212323E, trunc);
|
||||
//REG_FUNC(0x90B899F, truncf);
|
||||
//REG_FUNC(0xBC0F1B1A, truncl);
|
||||
//REG_FUNC(0x98BBDAE0, _Dclass);
|
||||
//REG_FUNC(0xBD8EF217, _FDclass);
|
||||
//REG_FUNC(0x314CCE54, _LDclass);
|
||||
//REG_FUNC(0xC5B9C8D8, _FDtest);
|
||||
//REG_FUNC(0x27A55170, _Dtest);
|
||||
//REG_FUNC(0x8DAE8767, _LDtest);
|
||||
//REG_FUNC(0x622CBFEE, _Fpcomp);
|
||||
//REG_FUNC(0x9CD4CEFE, _FFpcomp);
|
||||
//REG_FUNC(0x18F43CD0, _LFpcomp);
|
||||
//REG_FUNC(0x5BD0F71C, _Dsign);
|
||||
//REG_FUNC(0xC4F7E42C, _FDsign);
|
||||
//REG_FUNC(0x1DF73D2B, _LDsign);
|
||||
|
||||
return psv_log_base("SceLibm");
|
||||
}();
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,72 @@
|
|||
#include "stdafx.h"
|
||||
#include "Emu/System.h"
|
||||
#include "PSVFuncList.h"
|
||||
|
||||
std::vector<psv_func> g_psv_func_list = []() -> std::vector<psv_func>
|
||||
{
|
||||
std::vector<psv_func> v;
|
||||
|
||||
psv_func f =
|
||||
{
|
||||
0xdeadbeef,
|
||||
"INVALID FUNCTION",
|
||||
new psv_func_detail::func_binder<u32>([]() -> u32
|
||||
{
|
||||
LOG_ERROR(HLE, "Unimplemented function found");
|
||||
Emu.Pause();
|
||||
|
||||
return 0xffffffffu;
|
||||
}),
|
||||
nullptr,
|
||||
};
|
||||
v.push_back(f);
|
||||
|
||||
return v;
|
||||
}();
|
||||
|
||||
void add_psv_func(psv_func& data)
|
||||
{
|
||||
g_psv_func_list.push_back(data);
|
||||
}
|
||||
|
||||
psv_func* get_psv_func_by_nid(u32 nid)
|
||||
{
|
||||
for (auto& f : g_psv_func_list)
|
||||
{
|
||||
if (f.nid == nid)
|
||||
{
|
||||
return &f;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
u32 get_psv_func_index(psv_func* func)
|
||||
{
|
||||
auto res = func - g_psv_func_list.data();
|
||||
|
||||
assert((size_t)res < g_psv_func_list.size());
|
||||
|
||||
return (u32)res;
|
||||
}
|
||||
|
||||
void execute_psv_func_by_index(ARMv7Thread& CPU, u32 index)
|
||||
{
|
||||
assert(index < g_psv_func_list.size());
|
||||
|
||||
(*g_psv_func_list[index].func)(CPU);
|
||||
}
|
||||
|
||||
extern psv_log_base sceLibc;
|
||||
extern psv_log_base sceLibm;
|
||||
extern psv_log_base sceLibstdcxx;
|
||||
extern psv_log_base sceLibKernel;
|
||||
|
||||
void list_known_psv_modules()
|
||||
{
|
||||
sceLibc.Log("");
|
||||
sceLibm.Log("");
|
||||
sceLibstdcxx.Log("");
|
||||
sceLibKernel.Log("");
|
||||
}
|
|
@ -0,0 +1,672 @@
|
|||
#pragma once
|
||||
#include "ARMv7Thread.h"
|
||||
#include "Emu/SysCalls/LogBase.h"
|
||||
|
||||
class psv_log_base : public LogBase
|
||||
{
|
||||
std::string m_name;
|
||||
|
||||
public:
|
||||
psv_log_base(const std::string& name)
|
||||
: m_name(name)
|
||||
{
|
||||
}
|
||||
|
||||
virtual const std::string& GetName() const override
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
enum psv_error_codes
|
||||
{
|
||||
SCE_OK = 0,
|
||||
|
||||
SCE_ERROR_ERRNO_EPERM = 0x80010001,
|
||||
SCE_ERROR_ERRNO_ENOENT = 0x80010002,
|
||||
SCE_ERROR_ERRNO_ESRCH = 0x80010003,
|
||||
SCE_ERROR_ERRNO_EINTR = 0x80010004,
|
||||
SCE_ERROR_ERRNO_EIO = 0x80010005,
|
||||
SCE_ERROR_ERRNO_ENXIO = 0x80010006,
|
||||
SCE_ERROR_ERRNO_E2BIG = 0x80010007,
|
||||
SCE_ERROR_ERRNO_ENOEXEC = 0x80010008,
|
||||
SCE_ERROR_ERRNO_EBADF = 0x80010009,
|
||||
SCE_ERROR_ERRNO_ECHILD = 0x8001000A,
|
||||
SCE_ERROR_ERRNO_EAGAIN = 0x8001000B,
|
||||
SCE_ERROR_ERRNO_ENOMEM = 0x8001000C,
|
||||
SCE_ERROR_ERRNO_EACCES = 0x8001000D,
|
||||
SCE_ERROR_ERRNO_EFAULT = 0x8001000E,
|
||||
SCE_ERROR_ERRNO_ENOTBLK = 0x8001000F,
|
||||
SCE_ERROR_ERRNO_EBUSY = 0x80010010,
|
||||
SCE_ERROR_ERRNO_EEXIST = 0x80010011,
|
||||
SCE_ERROR_ERRNO_EXDEV = 0x80010012,
|
||||
SCE_ERROR_ERRNO_ENODEV = 0x80010013,
|
||||
SCE_ERROR_ERRNO_ENOTDIR = 0x80010014,
|
||||
SCE_ERROR_ERRNO_EISDIR = 0x80010015,
|
||||
SCE_ERROR_ERRNO_EINVAL = 0x80010016,
|
||||
SCE_ERROR_ERRNO_ENFILE = 0x80010017,
|
||||
SCE_ERROR_ERRNO_EMFILE = 0x80010018,
|
||||
SCE_ERROR_ERRNO_ENOTTY = 0x80010019,
|
||||
SCE_ERROR_ERRNO_ETXTBSY = 0x8001001A,
|
||||
SCE_ERROR_ERRNO_EFBIG = 0x8001001B,
|
||||
SCE_ERROR_ERRNO_ENOSPC = 0x8001001C,
|
||||
SCE_ERROR_ERRNO_ESPIPE = 0x8001001D,
|
||||
SCE_ERROR_ERRNO_EROFS = 0x8001001E,
|
||||
SCE_ERROR_ERRNO_EMLINK = 0x8001001F,
|
||||
SCE_ERROR_ERRNO_EPIPE = 0x80010020,
|
||||
SCE_ERROR_ERRNO_EDOM = 0x80010021,
|
||||
SCE_ERROR_ERRNO_ERANGE = 0x80010022,
|
||||
SCE_ERROR_ERRNO_ENOMSG = 0x80010023,
|
||||
SCE_ERROR_ERRNO_EIDRM = 0x80010024,
|
||||
SCE_ERROR_ERRNO_ECHRNG = 0x80010025,
|
||||
SCE_ERROR_ERRNO_EL2NSYNC = 0x80010026,
|
||||
SCE_ERROR_ERRNO_EL3HLT = 0x80010027,
|
||||
SCE_ERROR_ERRNO_EL3RST = 0x80010028,
|
||||
SCE_ERROR_ERRNO_ELNRNG = 0x80010029,
|
||||
SCE_ERROR_ERRNO_EUNATCH = 0x8001002A,
|
||||
SCE_ERROR_ERRNO_ENOCSI = 0x8001002B,
|
||||
SCE_ERROR_ERRNO_EL2HLT = 0x8001002C,
|
||||
SCE_ERROR_ERRNO_EDEADLK = 0x8001002D,
|
||||
SCE_ERROR_ERRNO_ENOLCK = 0x8001002E,
|
||||
SCE_ERROR_ERRNO_EFORMAT = 0x8001002F,
|
||||
SCE_ERROR_ERRNO_EUNSUP = 0x80010030,
|
||||
SCE_ERROR_ERRNO_EBADE = 0x80010032,
|
||||
SCE_ERROR_ERRNO_EBADR = 0x80010033,
|
||||
SCE_ERROR_ERRNO_EXFULL = 0x80010034,
|
||||
SCE_ERROR_ERRNO_ENOANO = 0x80010035,
|
||||
SCE_ERROR_ERRNO_EBADRQC = 0x80010036,
|
||||
SCE_ERROR_ERRNO_EBADSLT = 0x80010037,
|
||||
SCE_ERROR_ERRNO_EDEADLOCK = 0x80010038,
|
||||
SCE_ERROR_ERRNO_EBFONT = 0x80010039,
|
||||
SCE_ERROR_ERRNO_ENOSTR = 0x8001003C,
|
||||
SCE_ERROR_ERRNO_ENODATA = 0x8001003D,
|
||||
SCE_ERROR_ERRNO_ETIME = 0x8001003E,
|
||||
SCE_ERROR_ERRNO_ENOSR = 0x8001003F,
|
||||
SCE_ERROR_ERRNO_ENONET = 0x80010040,
|
||||
SCE_ERROR_ERRNO_ENOPKG = 0x80010041,
|
||||
SCE_ERROR_ERRNO_EREMOTE = 0x80010042,
|
||||
SCE_ERROR_ERRNO_ENOLINK = 0x80010043,
|
||||
SCE_ERROR_ERRNO_EADV = 0x80010044,
|
||||
SCE_ERROR_ERRNO_ESRMNT = 0x80010045,
|
||||
SCE_ERROR_ERRNO_ECOMM = 0x80010046,
|
||||
SCE_ERROR_ERRNO_EPROTO = 0x80010047,
|
||||
SCE_ERROR_ERRNO_EMULTIHOP = 0x8001004A,
|
||||
SCE_ERROR_ERRNO_ELBIN = 0x8001004B,
|
||||
SCE_ERROR_ERRNO_EDOTDOT = 0x8001004C,
|
||||
SCE_ERROR_ERRNO_EBADMSG = 0x8001004D,
|
||||
SCE_ERROR_ERRNO_EFTYPE = 0x8001004F,
|
||||
SCE_ERROR_ERRNO_ENOTUNIQ = 0x80010050,
|
||||
SCE_ERROR_ERRNO_EBADFD = 0x80010051,
|
||||
SCE_ERROR_ERRNO_EREMCHG = 0x80010052,
|
||||
SCE_ERROR_ERRNO_ELIBACC = 0x80010053,
|
||||
SCE_ERROR_ERRNO_ELIBBAD = 0x80010054,
|
||||
SCE_ERROR_ERRNO_ELIBSCN = 0x80010055,
|
||||
SCE_ERROR_ERRNO_ELIBMAX = 0x80010056,
|
||||
SCE_ERROR_ERRNO_ELIBEXEC = 0x80010057,
|
||||
SCE_ERROR_ERRNO_ENOSYS = 0x80010058,
|
||||
SCE_ERROR_ERRNO_ENMFILE = 0x80010059,
|
||||
SCE_ERROR_ERRNO_ENOTEMPTY = 0x8001005A,
|
||||
SCE_ERROR_ERRNO_ENAMETOOLONG = 0x8001005B,
|
||||
SCE_ERROR_ERRNO_ELOOP = 0x8001005C,
|
||||
SCE_ERROR_ERRNO_EOPNOTSUPP = 0x8001005F,
|
||||
SCE_ERROR_ERRNO_EPFNOSUPPORT = 0x80010060,
|
||||
SCE_ERROR_ERRNO_ECONNRESET = 0x80010068,
|
||||
SCE_ERROR_ERRNO_ENOBUFS = 0x80010069,
|
||||
SCE_ERROR_ERRNO_EAFNOSUPPORT = 0x8001006A,
|
||||
SCE_ERROR_ERRNO_EPROTOTYPE = 0x8001006B,
|
||||
SCE_ERROR_ERRNO_ENOTSOCK = 0x8001006C,
|
||||
SCE_ERROR_ERRNO_ENOPROTOOPT = 0x8001006D,
|
||||
SCE_ERROR_ERRNO_ESHUTDOWN = 0x8001006E,
|
||||
SCE_ERROR_ERRNO_ECONNREFUSED = 0x8001006F,
|
||||
SCE_ERROR_ERRNO_EADDRINUSE = 0x80010070,
|
||||
SCE_ERROR_ERRNO_ECONNABORTED = 0x80010071,
|
||||
SCE_ERROR_ERRNO_ENETUNREACH = 0x80010072,
|
||||
SCE_ERROR_ERRNO_ENETDOWN = 0x80010073,
|
||||
SCE_ERROR_ERRNO_ETIMEDOUT = 0x80010074,
|
||||
SCE_ERROR_ERRNO_EHOSTDOWN = 0x80010075,
|
||||
SCE_ERROR_ERRNO_EHOSTUNREACH = 0x80010076,
|
||||
SCE_ERROR_ERRNO_EINPROGRESS = 0x80010077,
|
||||
SCE_ERROR_ERRNO_EALREADY = 0x80010078,
|
||||
SCE_ERROR_ERRNO_EDESTADDRREQ = 0x80010079,
|
||||
SCE_ERROR_ERRNO_EMSGSIZE = 0x8001007A,
|
||||
SCE_ERROR_ERRNO_EPROTONOSUPPORT = 0x8001007B,
|
||||
SCE_ERROR_ERRNO_ESOCKTNOSUPPORT = 0x8001007C,
|
||||
SCE_ERROR_ERRNO_EADDRNOTAVAIL = 0x8001007D,
|
||||
SCE_ERROR_ERRNO_ENETRESET = 0x8001007E,
|
||||
SCE_ERROR_ERRNO_EISCONN = 0x8001007F,
|
||||
SCE_ERROR_ERRNO_ENOTCONN = 0x80010080,
|
||||
SCE_ERROR_ERRNO_ETOOMANYREFS = 0x80010081,
|
||||
SCE_ERROR_ERRNO_EPROCLIM = 0x80010082,
|
||||
SCE_ERROR_ERRNO_EUSERS = 0x80010083,
|
||||
SCE_ERROR_ERRNO_EDQUOT = 0x80010084,
|
||||
SCE_ERROR_ERRNO_ESTALE = 0x80010085,
|
||||
SCE_ERROR_ERRNO_ENOTSUP = 0x80010086,
|
||||
SCE_ERROR_ERRNO_ENOMEDIUM = 0x80010087,
|
||||
SCE_ERROR_ERRNO_ENOSHARE = 0x80010088,
|
||||
SCE_ERROR_ERRNO_ECASECLASH = 0x80010089,
|
||||
SCE_ERROR_ERRNO_EILSEQ = 0x8001008A,
|
||||
SCE_ERROR_ERRNO_EOVERFLOW = 0x8001008B,
|
||||
SCE_ERROR_ERRNO_ECANCELED = 0x8001008C,
|
||||
SCE_ERROR_ERRNO_ENOTRECOVERABLE = 0x8001008D,
|
||||
SCE_ERROR_ERRNO_EOWNERDEAD = 0x8001008E,
|
||||
|
||||
SCE_KERNEL_ERROR_ERROR = 0x80020001,
|
||||
SCE_KERNEL_ERROR_NOT_IMPLEMENTED = 0x80020002,
|
||||
SCE_KERNEL_ERROR_INVALID_ARGUMENT = 0x80020003,
|
||||
SCE_KERNEL_ERROR_INVALID_ARGUMENT_SIZE = 0x80020004,
|
||||
SCE_KERNEL_ERROR_INVALID_FLAGS = 0x80020005,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_SIZE = 0x80020006,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_ADDR = 0x80020007,
|
||||
SCE_KERNEL_ERROR_UNSUP = 0x80020008,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_MODE = 0x80020009,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_ALIGNMENT = 0x8002000A,
|
||||
SCE_KERNEL_ERROR_NOSYS = 0x8002000B,
|
||||
SCE_KERNEL_ERROR_DEBUG_ERROR = 0x80021000,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_DIPSW_NUMBER = 0x80021001,
|
||||
SCE_KERNEL_ERROR_CPU_ERROR = 0x80022000,
|
||||
SCE_KERNEL_ERROR_MMU_ILLEGAL_L1_TYPE = 0x80022001,
|
||||
SCE_KERNEL_ERROR_MMU_L2_INDEX_OVERFLOW = 0x80022002,
|
||||
SCE_KERNEL_ERROR_MMU_L2_SIZE_OVERFLOW = 0x80022003,
|
||||
SCE_KERNEL_ERROR_INVALID_CPU_AFFINITY = 0x80022004,
|
||||
SCE_KERNEL_ERROR_INVALID_MEMORY_ACCESS = 0x80022005,
|
||||
SCE_KERNEL_ERROR_INVALID_MEMORY_ACCESS_PERMISSION = 0x80022006,
|
||||
SCE_KERNEL_ERROR_VA2PA_FAULT = 0x80022007,
|
||||
SCE_KERNEL_ERROR_VA2PA_MAPPED = 0x80022008,
|
||||
SCE_KERNEL_ERROR_VALIDATION_CHECK_FAILED = 0x80022009,
|
||||
SCE_KERNEL_ERROR_SYSMEM_ERROR = 0x80024000,
|
||||
SCE_KERNEL_ERROR_INVALID_PROCESS_CONTEXT = 0x80024001,
|
||||
SCE_KERNEL_ERROR_UID_NAME_TOO_LONG = 0x80024002,
|
||||
SCE_KERNEL_ERROR_VARANGE_IS_NOT_PHYSICAL_CONTINUOUS = 0x80024003,
|
||||
SCE_KERNEL_ERROR_PHYADDR_ERROR = 0x80024100,
|
||||
SCE_KERNEL_ERROR_NO_PHYADDR = 0x80024101,
|
||||
SCE_KERNEL_ERROR_PHYADDR_USED = 0x80024102,
|
||||
SCE_KERNEL_ERROR_PHYADDR_NOT_USED = 0x80024103,
|
||||
SCE_KERNEL_ERROR_NO_IOADDR = 0x80024104,
|
||||
SCE_KERNEL_ERROR_PHYMEM_ERROR = 0x80024300,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_PHYPAGE_STATUS = 0x80024301,
|
||||
SCE_KERNEL_ERROR_NO_FREE_PHYSICAL_PAGE = 0x80024302,
|
||||
SCE_KERNEL_ERROR_NO_FREE_PHYSICAL_PAGE_UNIT = 0x80024303,
|
||||
SCE_KERNEL_ERROR_PHYMEMPART_NOT_EMPTY = 0x80024304,
|
||||
SCE_KERNEL_ERROR_NO_PHYMEMPART_LPDDR2 = 0x80024305,
|
||||
SCE_KERNEL_ERROR_NO_PHYMEMPART_CDRAM = 0x80024306,
|
||||
SCE_KERNEL_ERROR_FIXEDHEAP_ERROR = 0x80024400,
|
||||
SCE_KERNEL_ERROR_FIXEDHEAP_ILLEGAL_SIZE = 0x80024401,
|
||||
SCE_KERNEL_ERROR_FIXEDHEAP_ILLEGAL_INDEX = 0x80024402,
|
||||
SCE_KERNEL_ERROR_FIXEDHEAP_INDEX_OVERFLOW = 0x80024403,
|
||||
SCE_KERNEL_ERROR_FIXEDHEAP_NO_CHUNK = 0x80024404,
|
||||
SCE_KERNEL_ERROR_UID_ERROR = 0x80024500,
|
||||
SCE_KERNEL_ERROR_INVALID_UID = 0x80024501,
|
||||
SCE_KERNEL_ERROR_SYSMEM_UID_INVALID_ARGUMENT = 0x80024502,
|
||||
SCE_KERNEL_ERROR_SYSMEM_INVALID_UID_RANGE = 0x80024503,
|
||||
SCE_KERNEL_ERROR_SYSMEM_NO_VALID_UID = 0x80024504,
|
||||
SCE_KERNEL_ERROR_SYSMEM_CANNOT_ALLOCATE_UIDENTRY = 0x80024505,
|
||||
SCE_KERNEL_ERROR_NOT_PROCESS_UID = 0x80024506,
|
||||
SCE_KERNEL_ERROR_NOT_KERNEL_UID = 0x80024507,
|
||||
SCE_KERNEL_ERROR_INVALID_UID_CLASS = 0x80024508,
|
||||
SCE_KERNEL_ERROR_INVALID_UID_SUBCLASS = 0x80024509,
|
||||
SCE_KERNEL_ERROR_UID_CANNOT_FIND_BY_NAME = 0x8002450A,
|
||||
SCE_KERNEL_ERROR_VIRPAGE_ERROR = 0x80024600,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_VIRPAGE_TYPE = 0x80024601,
|
||||
SCE_KERNEL_ERROR_BLOCK_ERROR = 0x80024700,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_BLOCK_ID = 0x80024701,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_BLOCK_TYPE = 0x80024702,
|
||||
SCE_KERNEL_ERROR_BLOCK_IN_USE = 0x80024703,
|
||||
SCE_KERNEL_ERROR_PARTITION_ERROR = 0x80024800,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_PARTITION_ID = 0x80024801,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_PARTITION_INDEX = 0x80024802,
|
||||
SCE_KERNEL_ERROR_NO_L2PAGETABLE = 0x80024803,
|
||||
SCE_KERNEL_ERROR_HEAPLIB_ERROR = 0x80024900,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_HEAP_ID = 0x80024901,
|
||||
SCE_KERNEL_ERROR_OUT_OF_RANG = 0x80024902,
|
||||
SCE_KERNEL_ERROR_HEAPLIB_NOMEM = 0x80024903,
|
||||
SCE_KERNEL_ERROR_SYSMEM_ADDRESS_SPACE_ERROR = 0x80024A00,
|
||||
SCE_KERNEL_ERROR_INVALID_ADDRESS_SPACE_ID = 0x80024A01,
|
||||
SCE_KERNEL_ERROR_INVALID_PARTITION_INDEX = 0x80024A02,
|
||||
SCE_KERNEL_ERROR_ADDRESS_SPACE_CANNOT_FIND_PARTITION_BY_ADDR = 0x80024A03,
|
||||
SCE_KERNEL_ERROR_SYSMEM_MEMBLOCK_ERROR = 0x80024B00,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_MEMBLOCK_TYPE = 0x80024B01,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_MEMBLOCK_REMAP_TYPE = 0x80024B02,
|
||||
SCE_KERNEL_ERROR_NOT_PHY_CONT_MEMBLOCK = 0x80024B03,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_MEMBLOCK_CODE = 0x80024B04,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_MEMBLOCK_SIZE = 0x80024B05,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_USERMAP_SIZE = 0x80024B06,
|
||||
SCE_KERNEL_ERROR_MEMBLOCK_TYPE_FOR_KERNEL_PROCESS = 0x80024B07,
|
||||
SCE_KERNEL_ERROR_PROCESS_CANNOT_REMAP_MEMBLOCK = 0x80024B08,
|
||||
SCE_KERNEL_ERROR_SYSMEM_PHYMEMLOW_ERROR = 0x80024C00,
|
||||
SCE_KERNEL_ERROR_CANNOT_ALLOC_PHYMEMLOW = 0x80024C01,
|
||||
SCE_KERNEL_ERROR_UNKNOWN_PHYMEMLOW_TYPE = 0x80024C02,
|
||||
SCE_KERNEL_ERROR_SYSMEM_BITHEAP_ERROR = 0x80024D00,
|
||||
SCE_KERNEL_ERROR_CANNOT_ALLOC_BITHEAP = 0x80024D01,
|
||||
SCE_KERNEL_ERROR_LOADCORE_ERROR = 0x80025000,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_ELF_HEADER = 0x80025001,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_SELF_HEADER = 0x80025002,
|
||||
SCE_KERNEL_ERROR_EXCPMGR_ERROR = 0x80027000,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_EXCPCODE = 0x80027001,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_EXCPHANDLER = 0x80027002,
|
||||
SCE_KERNEL_ERROR_NOTFOUND_EXCPHANDLER = 0x80027003,
|
||||
SCE_KERNEL_ERROR_CANNOT_RELEASE_EXCPHANDLER = 0x80027004,
|
||||
SCE_KERNEL_ERROR_INTRMGR_ERROR = 0x80027100,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_CONTEXT = 0x80027101,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_INTRCODE = 0x80027102,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_INTRPARAM = 0x80027103,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_INTRPRIORITY = 0x80027104,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_TARGET_CPU = 0x80027105,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_INTRFILTER = 0x80027106,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_INTRTYPE = 0x80027107,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_HANDLER = 0x80027108,
|
||||
SCE_KERNEL_ERROR_FOUND_HANDLER = 0x80027109,
|
||||
SCE_KERNEL_ERROR_NOTFOUND_HANDLER = 0x8002710A,
|
||||
SCE_KERNEL_ERROR_NO_MEMORY = 0x8002710B,
|
||||
SCE_KERNEL_ERROR_DMACMGR_ERROR = 0x80027200,
|
||||
SCE_KERNEL_ERROR_ALREADY_QUEUED = 0x80027201,
|
||||
SCE_KERNEL_ERROR_NOT_QUEUED = 0x80027202,
|
||||
SCE_KERNEL_ERROR_NOT_SETUP = 0x80027203,
|
||||
SCE_KERNEL_ERROR_ON_TRANSFERRING = 0x80027204,
|
||||
SCE_KERNEL_ERROR_NOT_INITIALIZED = 0x80027205,
|
||||
SCE_KERNEL_ERROR_TRANSFERRED = 0x80027206,
|
||||
SCE_KERNEL_ERROR_NOT_UNDER_CONTROL = 0x80027207,
|
||||
SCE_KERNEL_ERROR_SYSTIMER_ERROR = 0x80027300,
|
||||
SCE_KERNEL_ERROR_NO_FREE_TIMER = 0x80027301,
|
||||
SCE_KERNEL_ERROR_TIMER_NOT_ALLOCATED = 0x80027302,
|
||||
SCE_KERNEL_ERROR_TIMER_COUNTING = 0x80027303,
|
||||
SCE_KERNEL_ERROR_TIMER_STOPPED = 0x80027304,
|
||||
SCE_KERNEL_ERROR_THREADMGR_ERROR = 0x80028000,
|
||||
SCE_KERNEL_ERROR_DORMANT = 0x80028001,
|
||||
SCE_KERNEL_ERROR_NOT_DORMANT = 0x80028002,
|
||||
SCE_KERNEL_ERROR_UNKNOWN_THID = 0x80028003,
|
||||
SCE_KERNEL_ERROR_CAN_NOT_WAIT = 0x80028004,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_THID = 0x80028005,
|
||||
SCE_KERNEL_ERROR_THREAD_TERMINATED = 0x80028006,
|
||||
SCE_KERNEL_ERROR_DELETED = 0x80028007,
|
||||
SCE_KERNEL_ERROR_WAIT_TIMEOUT = 0x80028008,
|
||||
SCE_KERNEL_ERROR_NOTIFY_CALLBACK = 0x80028009,
|
||||
SCE_KERNEL_ERROR_WAIT_DELETE = 0x8002800A,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_ATTR = 0x8002800B,
|
||||
SCE_KERNEL_ERROR_EVF_MULTI = 0x8002800C,
|
||||
SCE_KERNEL_ERROR_WAIT_CANCEL = 0x8002800D,
|
||||
SCE_KERNEL_ERROR_EVF_COND = 0x8002800E,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_COUNT = 0x8002800F,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_PRIORITY = 0x80028010,
|
||||
SCE_KERNEL_ERROR_MUTEX_RECURSIVE = 0x80028011,
|
||||
SCE_KERNEL_ERROR_MUTEX_LOCK_OVF = 0x80028012,
|
||||
SCE_KERNEL_ERROR_MUTEX_NOT_OWNED = 0x80028013,
|
||||
SCE_KERNEL_ERROR_MUTEX_UNLOCK_UDF = 0x80028014,
|
||||
SCE_KERNEL_ERROR_MUTEX_FAILED_TO_OWN = 0x80028015,
|
||||
SCE_KERNEL_ERROR_FAST_MUTEX_RECURSIVE = 0x80028016,
|
||||
SCE_KERNEL_ERROR_FAST_MUTEX_LOCK_OVF = 0x80028017,
|
||||
SCE_KERNEL_ERROR_FAST_MUTEX_FAILED_TO_OWN = 0x80028018,
|
||||
SCE_KERNEL_ERROR_FAST_MUTEX_NOT_OWNED = 0x80028019,
|
||||
SCE_KERNEL_ERROR_FAST_MUTEX_OWNED = 0x8002801A,
|
||||
SCE_KERNEL_ERROR_ALARM_CAN_NOT_CANCEL = 0x8002801B,
|
||||
SCE_KERNEL_ERROR_INVALID_OBJECT_TYPE = 0x8002801C,
|
||||
SCE_KERNEL_ERROR_KERNEL_TLS_FULL = 0x8002801D,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_KERNEL_TLS_INDEX = 0x8002801E,
|
||||
SCE_KERNEL_ERROR_KERNEL_TLS_BUSY = 0x8002801F,
|
||||
SCE_KERNEL_ERROR_DIFFERENT_UID_CLASS = 0x80028020,
|
||||
SCE_KERNEL_ERROR_UNKNOWN_UID = 0x80028021,
|
||||
SCE_KERNEL_ERROR_SEMA_ZERO = 0x80028022,
|
||||
SCE_KERNEL_ERROR_SEMA_OVF = 0x80028023,
|
||||
SCE_KERNEL_ERROR_PMON_NOT_THREAD_MODE = 0x80028024,
|
||||
SCE_KERNEL_ERROR_PMON_NOT_CPU_MODE = 0x80028025,
|
||||
SCE_KERNEL_ERROR_ALREADY_REGISTERED = 0x80028026,
|
||||
SCE_KERNEL_ERROR_INVALID_THREAD_ID = 0x80028027,
|
||||
SCE_KERNEL_ERROR_ALREADY_DEBUG_SUSPENDED = 0x80028028,
|
||||
SCE_KERNEL_ERROR_NOT_DEBUG_SUSPENDED = 0x80028029,
|
||||
SCE_KERNEL_ERROR_CAN_NOT_USE_VFP = 0x8002802A,
|
||||
SCE_KERNEL_ERROR_RUNNING = 0x8002802B,
|
||||
SCE_KERNEL_ERROR_EVENT_COND = 0x8002802C,
|
||||
SCE_KERNEL_ERROR_MSG_PIPE_FULL = 0x8002802D,
|
||||
SCE_KERNEL_ERROR_MSG_PIPE_EMPTY = 0x8002802E,
|
||||
SCE_KERNEL_ERROR_ALREADY_SENT = 0x8002802F,
|
||||
SCE_KERNEL_ERROR_CAN_NOT_SUSPEND = 0x80028030,
|
||||
SCE_KERNEL_ERROR_FAST_MUTEX_ALREADY_INITIALIZED = 0x80028031,
|
||||
SCE_KERNEL_ERROR_FAST_MUTEX_NOT_INITIALIZED = 0x80028032,
|
||||
SCE_KERNEL_ERROR_THREAD_STOPPED = 0x80028033,
|
||||
SCE_KERNEL_ERROR_THREAD_SUSPENDED = 0x80028034,
|
||||
SCE_KERNEL_ERROR_NOT_SUSPENDED = 0x80028035,
|
||||
SCE_KERNEL_ERROR_WAIT_DELETE_MUTEX = 0x80028036,
|
||||
SCE_KERNEL_ERROR_WAIT_CANCEL_MUTEX = 0x80028037,
|
||||
SCE_KERNEL_ERROR_WAIT_DELETE_COND = 0x80028038,
|
||||
SCE_KERNEL_ERROR_WAIT_CANCEL_COND = 0x80028039,
|
||||
SCE_KERNEL_ERROR_LW_MUTEX_NOT_OWNED = 0x8002803A,
|
||||
SCE_KERNEL_ERROR_LW_MUTEX_LOCK_OVF = 0x8002803B,
|
||||
SCE_KERNEL_ERROR_LW_MUTEX_UNLOCK_UDF = 0x8002803C,
|
||||
SCE_KERNEL_ERROR_LW_MUTEX_RECURSIVE = 0x8002803D,
|
||||
SCE_KERNEL_ERROR_LW_MUTEX_FAILED_TO_OWN = 0x8002803E,
|
||||
SCE_KERNEL_ERROR_WAIT_DELETE_LW_MUTEX = 0x8002803F,
|
||||
SCE_KERNEL_ERROR_ILLEGAL_STACK_SIZE = 0x80028040,
|
||||
SCE_KERNEL_ERROR_RW_LOCK_RECURSIVE = 0x80028041,
|
||||
SCE_KERNEL_ERROR_RW_LOCK_LOCK_OVF = 0x80028042,
|
||||
SCE_KERNEL_ERROR_RW_LOCK_NOT_OWNED = 0x80028043,
|
||||
SCE_KERNEL_ERROR_RW_LOCK_UNLOCK_UDF = 0x80028044,
|
||||
SCE_KERNEL_ERROR_RW_LOCK_FAILED_TO_LOCK = 0x80028045,
|
||||
SCE_KERNEL_ERROR_RW_LOCK_FAILED_TO_UNLOCK = 0x80028046,
|
||||
|
||||
SCE_KERNEL_ERROR_PROCESSMGR_ERROR = 0x80029000,
|
||||
SCE_KERNEL_ERROR_INVALID_PID = 0x80029001,
|
||||
SCE_KERNEL_ERROR_INVALID_PROCESS_TYPE = 0x80029002,
|
||||
SCE_KERNEL_ERROR_PLS_FULL = 0x80029003,
|
||||
SCE_KERNEL_ERROR_INVALID_PROCESS_STATUS = 0x80029004,
|
||||
SCE_KERNEL_ERROR_INVALID_BUDGET_ID = 0x80029005,
|
||||
SCE_KERNEL_ERROR_INVALID_BUDGET_SIZE = 0x80029006,
|
||||
SCE_KERNEL_ERROR_CP14_DISABLED = 0x80029007,
|
||||
SCE_KERNEL_ERROR_EXCEEDED_MAX_PROCESSES = 0x80029008,
|
||||
SCE_KERNEL_ERROR_PROCESS_REMAINING = 0x80029009,
|
||||
SCE_KERNEL_ERROR_IOFILEMGR_ERROR = 0x8002A000,
|
||||
SCE_KERNEL_ERROR_IO_NAME_TOO_LONG = 0x8002A001,
|
||||
SCE_KERNEL_ERROR_IO_REG_DEV = 0x8002A002,
|
||||
SCE_KERNEL_ERROR_IO_ALIAS_USED = 0x8002A003,
|
||||
SCE_KERNEL_ERROR_IO_DEL_DEV = 0x8002A004,
|
||||
SCE_KERNEL_ERROR_IO_WOULD_BLOCK = 0x8002A005,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_START_FAILED = 0x8002D000,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_STOP_FAIL = 0x8002D001,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_IN_USE = 0x8002D002,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_NO_LIB = 0x8002D003,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_SYSCALL_REG = 0x8002D004,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_NOMEM_LIB = 0x8002D005,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_NOMEM_STUB = 0x8002D006,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_NOMEM_SELF = 0x8002D007,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_NOMEM = 0x8002D008,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_INVALID_LIB = 0x8002D009,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_INVALID_STUB = 0x8002D00A,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_NO_FUNC_NID = 0x8002D00B,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_NO_VAR_NID = 0x8002D00C,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_INVALID_TYPE = 0x8002D00D,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_NO_MOD_ENTRY = 0x8002D00E,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_INVALID_PROC_PARAM = 0x8002D00F,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_NO_MODOBJ = 0x8002D010,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_NO_MOD = 0x8002D011,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_NO_PROCESS = 0x8002D012,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_OLD_LIB = 0x8002D013,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_STARTED = 0x8002D014,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_NOT_STARTED = 0x8002D015,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_NOT_STOPPED = 0x8002D016,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_INVALID_PROCESS_UID = 0x8002D017,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_CANNOT_EXPORT_LIB_TO_SHARED = 0x8002D018,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_INVALID_REL_INFO = 0x8002D019,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_INVALID_REF_INFO = 0x8002D01A,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_ELINK = 0x8002D01B,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_NOENT = 0x8002D01C,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_BUSY = 0x8002D01D,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_NOEXEC = 0x8002D01E,
|
||||
SCE_KERNEL_ERROR_MODULEMGR_NAMETOOLONG = 0x8002D01F,
|
||||
SCE_KERNEL_ERROR_LIBRARYDB_NOENT = 0x8002D080,
|
||||
SCE_KERNEL_ERROR_LIBRARYDB_NO_LIB = 0x8002D081,
|
||||
SCE_KERNEL_ERROR_LIBRARYDB_NO_MOD = 0x8002D082,
|
||||
SCE_KERNEL_ERROR_AUTHFAIL = 0x8002F000,
|
||||
SCE_KERNEL_ERROR_NO_AUTH = 0x8002F001,
|
||||
};
|
||||
|
||||
class psv_func_caller
|
||||
{
|
||||
public:
|
||||
virtual void operator()(ARMv7Thread& CPU) = 0;
|
||||
virtual ~psv_func_caller(){};
|
||||
};
|
||||
|
||||
namespace psv_func_detail
|
||||
{
|
||||
enum bind_arg_type
|
||||
{
|
||||
ARG_GENERAL,
|
||||
ARG_FLOAT,
|
||||
ARG_VECTOR,
|
||||
ARG_STACK,
|
||||
};
|
||||
|
||||
template<typename T, bind_arg_type type, int g_count, int f_count, int v_count>
|
||||
struct bind_arg;
|
||||
|
||||
template<typename T, int g_count, int f_count, int v_count>
|
||||
struct bind_arg<T, ARG_GENERAL, g_count, f_count, v_count>
|
||||
{
|
||||
static_assert(sizeof(T) <= 4, "Invalid function argument type for ARG_GENERAL");
|
||||
|
||||
static __forceinline T func(ARMv7Thread& CPU)
|
||||
{
|
||||
return (T&)CPU.GPR[g_count - 1];
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, int g_count, int f_count, int v_count>
|
||||
struct bind_arg<T, ARG_FLOAT, g_count, f_count, v_count>
|
||||
{
|
||||
static_assert(f_count <= 0, "TODO: Unsupported argument type (float)");
|
||||
static_assert(sizeof(T) <= 8, "Invalid function argument type for ARG_FLOAT");
|
||||
|
||||
static __forceinline T func(ARMv7Thread& CPU)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, int g_count, int f_count, int v_count>
|
||||
struct bind_arg<T, ARG_VECTOR, g_count, f_count, v_count>
|
||||
{
|
||||
static_assert(v_count <= 0, "TODO: Unsupported argument type (vector)");
|
||||
static_assert(sizeof(T) == 16, "Invalid function argument type for ARG_VECTOR");
|
||||
|
||||
static __forceinline T func(ARMv7Thread& CPU)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, int g_count, int f_count, int v_count>
|
||||
struct bind_arg<T, ARG_STACK, g_count, f_count, v_count>
|
||||
{
|
||||
static_assert(f_count <= 0, "TODO: Unsupported stack argument type (float)");
|
||||
static_assert(v_count <= 0, "TODO: Unsupported stack argument type (vector)");
|
||||
static_assert(sizeof(T) <= 4, "Invalid function argument type for ARG_STACK");
|
||||
|
||||
static __forceinline T func(ARMv7Thread& CPU)
|
||||
{
|
||||
const u32 res = CPU.GetStackArg(g_count);
|
||||
return (T&)res;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, bind_arg_type type>
|
||||
struct bind_result
|
||||
{
|
||||
static_assert(type != ARG_FLOAT, "TODO: Unsupported funcion result type (float)");
|
||||
static_assert(type != ARG_VECTOR, "TODO: Unsupported funcion result type (vector)");
|
||||
static_assert(type == ARG_GENERAL, "Wrong use of bind_result template");
|
||||
static_assert(sizeof(T) <= 4, "Invalid function result type for ARG_GENERAL");
|
||||
|
||||
static __forceinline void func(ARMv7Thread& CPU, T result)
|
||||
{
|
||||
(T&)CPU.GPR[0] = result;
|
||||
}
|
||||
};
|
||||
|
||||
//template<typename T>
|
||||
//struct bind_result<T, ARG_FLOAT>
|
||||
//{
|
||||
// static_assert(sizeof(T) <= 8, "Invalid function result type for ARG_FLOAT");
|
||||
|
||||
// static __forceinline void func(ARMv7Thread& CPU, T result)
|
||||
// {
|
||||
// }
|
||||
//};
|
||||
|
||||
//template<typename T>
|
||||
//struct bind_result<T, ARG_VECTOR>
|
||||
//{
|
||||
// static_assert(sizeof(T) == 16, "Invalid function result type for ARG_VECTOR");
|
||||
|
||||
// static __forceinline void func(ARMv7Thread& CPU, const T result)
|
||||
// {
|
||||
// }
|
||||
//};
|
||||
|
||||
template <typename RT, typename F, typename Tuple, bool Done, int Total, int... N>
|
||||
struct call_impl
|
||||
{
|
||||
static __forceinline RT call(F f, Tuple && t)
|
||||
{
|
||||
return call_impl<RT, F, Tuple, Total == 1 + sizeof...(N), Total, N..., sizeof...(N)>::call(f, std::forward<Tuple>(t));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename RT, typename F, typename Tuple, int Total, int... N>
|
||||
struct call_impl<RT, F, Tuple, true, Total, N...>
|
||||
{
|
||||
static __forceinline RT call(F f, Tuple && t)
|
||||
{
|
||||
return f(std::get<N>(std::forward<Tuple>(t))...);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename RT, typename F, typename Tuple>
|
||||
static __forceinline RT call(F f, Tuple && t)
|
||||
{
|
||||
typedef typename std::decay<Tuple>::type ttype;
|
||||
return psv_func_detail::call_impl<RT, F, Tuple, 0 == std::tuple_size<ttype>::value, std::tuple_size<ttype>::value>::call(f, std::forward<Tuple>(t));
|
||||
}
|
||||
|
||||
template<int g_count, int f_count, int v_count>
|
||||
static __forceinline std::tuple<> iterate(ARMv7Thread& CPU)
|
||||
{
|
||||
// terminator
|
||||
return std::tuple<>();
|
||||
}
|
||||
|
||||
template<int g_count, int f_count, int v_count, typename T, typename... A>
|
||||
static __forceinline std::tuple<T, A...> iterate(ARMv7Thread& CPU)
|
||||
{
|
||||
static_assert(!std::is_pointer<T>::value, "Invalid function argument type (pointer)");
|
||||
static_assert(!std::is_reference<T>::value, "Invalid function argument type (reference)");
|
||||
// TODO: check calculations
|
||||
const bool is_float = std::is_floating_point<T>::value;
|
||||
const bool is_vector = std::is_same<T, u128>::value;
|
||||
const bind_arg_type t = is_float
|
||||
? ((f_count >= 4) ? ARG_STACK : ARG_FLOAT)
|
||||
: (is_vector ? ((v_count >= 4) ? ARG_STACK : ARG_VECTOR) : ((g_count >= 4) ? ARG_STACK : ARG_GENERAL));
|
||||
const int g = g_count + (is_float || is_vector ? 0 : 1);
|
||||
const int f = f_count + (is_float ? 1 : 0);
|
||||
const int v = v_count + (is_vector ? 1 : 0);
|
||||
|
||||
return std::tuple_cat(std::tuple<T>(bind_arg<T, t, g, f, v>::func(CPU)), iterate<g, f, v, A...>(CPU));
|
||||
}
|
||||
|
||||
template<typename RT, typename... T>
|
||||
class func_binder;
|
||||
|
||||
template<typename... T>
|
||||
class func_binder<void, T...> : public psv_func_caller
|
||||
{
|
||||
typedef void(*func_t)(T...);
|
||||
const func_t m_call;
|
||||
|
||||
public:
|
||||
func_binder(func_t call)
|
||||
: psv_func_caller()
|
||||
, m_call(call)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void operator()(ARMv7Thread& CPU)
|
||||
{
|
||||
call<void>(m_call, iterate<0, 0, 0, T...>(CPU));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... T>
|
||||
class func_binder<void, ARMv7Thread&, T...> : public psv_func_caller
|
||||
{
|
||||
typedef void(*func_t)(ARMv7Thread&, T...);
|
||||
const func_t m_call;
|
||||
|
||||
public:
|
||||
func_binder(func_t call)
|
||||
: psv_func_caller()
|
||||
, m_call(call)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void operator()(ARMv7Thread& CPU)
|
||||
{
|
||||
call<void>(m_call, std::tuple_cat(std::tuple<ARMv7Thread&>(CPU), iterate<0, 0, 0, T...>(CPU)));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename RT, typename... T>
|
||||
class func_binder : public psv_func_caller
|
||||
{
|
||||
typedef RT(*func_t)(T...);
|
||||
const func_t m_call;
|
||||
|
||||
public:
|
||||
func_binder(func_t call)
|
||||
: psv_func_caller()
|
||||
, m_call(call)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void operator()(ARMv7Thread& CPU)
|
||||
{
|
||||
static_assert(!std::is_pointer<RT>::value, "Invalid function result type (pointer)");
|
||||
static_assert(!std::is_reference<RT>::value, "Invalid function result type (reference)");
|
||||
const bool is_float = std::is_floating_point<RT>::value;
|
||||
const bool is_vector = std::is_same<RT, u128>::value;
|
||||
const bind_arg_type t = is_float ? ARG_FLOAT : (is_vector ? ARG_VECTOR : ARG_GENERAL);
|
||||
|
||||
bind_result<RT, t>::func(CPU, call<RT>(m_call, iterate<0, 0, 0, T...>(CPU)));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename RT, typename... T>
|
||||
class func_binder<RT, ARMv7Thread&, T...> : public psv_func_caller
|
||||
{
|
||||
typedef RT(*func_t)(ARMv7Thread&, T...);
|
||||
const func_t m_call;
|
||||
|
||||
public:
|
||||
func_binder(func_t call)
|
||||
: psv_func_caller()
|
||||
, m_call(call)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void operator()(ARMv7Thread& CPU)
|
||||
{
|
||||
static_assert(!std::is_pointer<RT>::value, "Invalid function result type (pointer)");
|
||||
static_assert(!std::is_reference<RT>::value, "Invalid function result type (reference)");
|
||||
const bool is_float = std::is_floating_point<RT>::value;
|
||||
const bool is_vector = std::is_same<RT, u128>::value;
|
||||
const bind_arg_type t = is_float ? ARG_FLOAT : (is_vector ? ARG_VECTOR : ARG_GENERAL);
|
||||
|
||||
bind_result<RT, t>::func(CPU, call<RT>(m_call, std::tuple_cat(std::tuple<ARMv7Thread&>(CPU), iterate<0, 0, 0, T...>(CPU))));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
struct psv_func
|
||||
{
|
||||
const u32 nid;
|
||||
const char* const name;
|
||||
psv_func_caller* const func;
|
||||
psv_log_base* const module;
|
||||
};
|
||||
|
||||
void add_psv_func(psv_func& data);
|
||||
|
||||
template<typename RT, typename... T>
|
||||
void reg_psv_func(u32 nid, psv_log_base* module, const char* name, RT(*func)(T...))
|
||||
{
|
||||
psv_func f =
|
||||
{
|
||||
nid,
|
||||
name,
|
||||
new psv_func_detail::func_binder<RT, T...>(func),
|
||||
module
|
||||
};
|
||||
|
||||
add_psv_func(f);
|
||||
}
|
||||
|
||||
psv_func* get_psv_func_by_nid(u32 nid);
|
||||
u32 get_psv_func_index(psv_func* func);
|
||||
|
||||
void execute_psv_func_by_index(ARMv7Thread& CPU, u32 index);
|
||||
void list_known_psv_modules();
|
|
@ -333,6 +333,17 @@ public:
|
|||
});
|
||||
}
|
||||
|
||||
InstrBase(const InstrBase &source)
|
||||
: InstrCaller<TO>(source)
|
||||
, m_name(source.m_name)
|
||||
, m_opcode(source.m_opcode)
|
||||
, m_args_count(source.m_args_count)
|
||||
, m_args(source.m_args_count ? new CodeFieldBase*[source.m_args_count] : nullptr)
|
||||
{
|
||||
for(uint i = 0; i < source.m_args_count; ++i)
|
||||
m_args[i] = source.m_args[i];
|
||||
}
|
||||
|
||||
virtual ~InstrBase()
|
||||
{
|
||||
if (m_args) {
|
||||
|
|
|
@ -28,6 +28,8 @@ CPUThread::CPUThread(CPUThreadType type)
|
|||
, m_is_branch(false)
|
||||
, m_status(Stopped)
|
||||
, m_last_syscall(0)
|
||||
, m_trace_enabled(false)
|
||||
, m_trace_call_stack(true)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -154,7 +156,7 @@ void CPUThread::SetBranch(const u32 pc, bool record_branch)
|
|||
m_is_branch = true;
|
||||
nPC = pc;
|
||||
|
||||
if(record_branch)
|
||||
if(m_trace_call_stack && record_branch)
|
||||
CallStackBranch(pc);
|
||||
}
|
||||
|
||||
|
@ -298,7 +300,7 @@ void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp)
|
|||
|
||||
void CPUThread::Task()
|
||||
{
|
||||
if (Ini.HLELogging.GetValue()) LOG_NOTICE(PPU, "%s enter", CPUThread::GetFName().c_str());
|
||||
if (Ini.HLELogging.GetValue()) LOG_NOTICE(GENERAL, "%s enter", CPUThread::GetFName().c_str());
|
||||
|
||||
const std::vector<u64>& bp = Emu.GetBreakPoints();
|
||||
|
||||
|
@ -337,7 +339,7 @@ void CPUThread::Task()
|
|||
}
|
||||
|
||||
Step();
|
||||
//if (PC - 0x13ED4 < 0x288) trace.push_back(PC);
|
||||
//if (m_trace_enabled) trace.push_back(PC);
|
||||
NextPc(m_dec->DecodeMemory(PC + m_offset));
|
||||
|
||||
if (status == CPUThread_Step)
|
||||
|
@ -373,7 +375,25 @@ void CPUThread::Task()
|
|||
// TODO: linux version
|
||||
#endif
|
||||
|
||||
for (auto& v : trace) LOG_NOTICE(PPU, "PC = 0x%x", v);
|
||||
if (trace.size())
|
||||
{
|
||||
LOG_NOTICE(GENERAL, "Trace begin (%d elements)", trace.size());
|
||||
|
||||
if (Ini.HLELogging.GetValue()) LOG_NOTICE(PPU, "%s leave", CPUThread::GetFName().c_str());
|
||||
u32 start = trace[0], prev = trace[0] - 4;
|
||||
|
||||
for (auto& v : trace) //LOG_NOTICE(GENERAL, "PC = 0x%x", v);
|
||||
{
|
||||
if (v - prev != 4)
|
||||
{
|
||||
LOG_NOTICE(GENERAL, "Trace: 0x%08x .. 0x%08x", start, prev);
|
||||
start = v;
|
||||
}
|
||||
prev = v;
|
||||
}
|
||||
|
||||
LOG_NOTICE(GENERAL, "Trace end: 0x%08x .. 0x%08x", start, prev);
|
||||
}
|
||||
|
||||
|
||||
if (Ini.HLELogging.GetValue()) LOG_NOTICE(GENERAL, "%s leave", CPUThread::GetFName().c_str());
|
||||
}
|
||||
|
|
|
@ -43,6 +43,8 @@ protected:
|
|||
|
||||
CPUDecoder* m_dec;
|
||||
|
||||
bool m_trace_call_stack;
|
||||
|
||||
public:
|
||||
virtual void InitRegs()=0;
|
||||
|
||||
|
@ -109,16 +111,19 @@ public:
|
|||
|
||||
virtual std::string GetThreadName() const
|
||||
{
|
||||
std::string temp = (GetFName() + fmt::Format("[0x%08llx]", PC));
|
||||
std::string temp = (GetFName() + fmt::Format("[0x%08x]", PC));
|
||||
return temp;
|
||||
}
|
||||
|
||||
CPUDecoder * GetDecoder() { return m_dec; };
|
||||
|
||||
public:
|
||||
u32 entry;
|
||||
u32 PC;
|
||||
u32 nPC;
|
||||
u64 cycle;
|
||||
bool m_is_branch;
|
||||
bool m_trace_enabled;
|
||||
|
||||
bool m_is_interrupt;
|
||||
bool m_has_interrupt;
|
||||
|
@ -174,6 +179,8 @@ public:
|
|||
u32 GetId() const { return m_id; }
|
||||
CPUThreadType GetType() const { return m_type; }
|
||||
|
||||
void SetCallStackTracing(bool trace_call_stack) { m_trace_call_stack = trace_call_stack; }
|
||||
|
||||
void Reset();
|
||||
void Close();
|
||||
void Run();
|
||||
|
@ -249,3 +256,42 @@ protected:
|
|||
};
|
||||
|
||||
CPUThread* GetCurrentCPUThread();
|
||||
|
||||
class cpu_thread
|
||||
{
|
||||
protected:
|
||||
CPUThread* thread;
|
||||
|
||||
public:
|
||||
u32 get_entry() const
|
||||
{
|
||||
return thread->entry;
|
||||
}
|
||||
|
||||
virtual cpu_thread& args(std::initializer_list<std::string> values) = 0;
|
||||
|
||||
virtual cpu_thread& run() = 0;
|
||||
|
||||
u64 join()
|
||||
{
|
||||
if (!joinable())
|
||||
throw "thread must be joinable for join";
|
||||
|
||||
thread->SetJoinable(false);
|
||||
|
||||
while (thread->IsRunning())
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
|
||||
return thread->GetExitStatus();
|
||||
}
|
||||
|
||||
bool joinable() const
|
||||
{
|
||||
return thread->IsJoinable();
|
||||
}
|
||||
|
||||
u32 get_id() const
|
||||
{
|
||||
return thread->GetId();
|
||||
}
|
||||
};
|
|
@ -135,22 +135,6 @@ RawSPUThread* CPUThreadManager::GetRawSPUThread(u32 num)
|
|||
}
|
||||
}
|
||||
|
||||
void CPUThreadManager::NotifyThread(const u32 id)
|
||||
{
|
||||
if (!id) return;
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mtx_thread);
|
||||
|
||||
for (u32 i = 0; i < m_threads.size(); i++)
|
||||
{
|
||||
if (m_threads[i]->GetId() == id)
|
||||
{
|
||||
m_threads[i]->Notify();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CPUThreadManager::Exec()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mtx_thread);
|
||||
|
|
|
@ -17,7 +17,6 @@ public:
|
|||
|
||||
CPUThread& AddThread(CPUThreadType type);
|
||||
void RemoveThread(const u32 id);
|
||||
void NotifyThread(const u32 id);
|
||||
|
||||
std::vector<CPUThread*>& GetThreads() { return m_threads; }
|
||||
s32 GetThreadNumById(CPUThreadType type, u32 id);
|
||||
|
|
|
@ -61,5 +61,4 @@ enum
|
|||
|
||||
struct DMAC
|
||||
{
|
||||
u32 ls_offset;
|
||||
};
|
||||
|
|
|
@ -9,7 +9,7 @@ public:
|
|||
|
||||
virtual std::string GetThreadName() const
|
||||
{
|
||||
return (GetFName() + fmt::Format("[0x%08llx]", PC));
|
||||
return (GetFName() + fmt::Format("[0x%08x]", PC));
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
|
@ -1037,7 +1037,7 @@ private:
|
|||
case 0x1: Write("HyperCall"); break;
|
||||
case 0x2: Write("sc"); break;
|
||||
case 0x22: Write("HyperCall LV1"); break;
|
||||
default: Write(fmt::Format("Unknown sc: %x", sc_code));
|
||||
default: Write(fmt::Format("Unknown sc: 0x%x", sc_code));
|
||||
}
|
||||
}
|
||||
void B(s32 ll, u32 aa, u32 lk)
|
||||
|
@ -1600,7 +1600,10 @@ private:
|
|||
default: DisAsm_IMM_R1("mtspr", spr, rs); break;
|
||||
}
|
||||
}
|
||||
/*0x1d6*///DCBI
|
||||
void DCBI(u32 ra, u32 rb)
|
||||
{
|
||||
DisAsm_R2("dcbi", ra, rb);
|
||||
}
|
||||
void NAND(u32 ra, u32 rs, u32 rb, bool rc)
|
||||
{
|
||||
DisAsm_R3_RC("nand", ra, rs, rb, rc);
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
namespace PPU_instr
|
||||
{
|
||||
namespace fields
|
||||
{
|
||||
//This field is used in rotate instructions to specify the first 1 bit of a 64-bit mask
|
||||
static DoubleCodeField<21, 25, 26, 26, 5> mb;
|
||||
|
||||
|
@ -202,6 +204,11 @@ namespace PPU_instr
|
|||
static CodeField<21, 30> GD_3f_0; //0x3ff
|
||||
|
||||
static CodeField<9, 10> STRM;
|
||||
}
|
||||
|
||||
namespace lists
|
||||
{
|
||||
using namespace fields;
|
||||
|
||||
//static auto main_list = new_list(OPCD, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, OPCD));
|
||||
static InstrList<1 << CodeField<0, 5>::size, ::PPUOpcodes> main_list_obj(OPCD, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, OPCD));
|
||||
|
@ -217,7 +224,7 @@ namespace PPU_instr
|
|||
static auto g3f_list = new_list(main_list, PPU_opcodes::G_3f, GD_3f);
|
||||
static auto g3f_0_list = new_list(g3f_list, GD_3f_0, instr_bind(&PPUOpcodes::UNK, GetCode, OPCD, GD_3f_0));
|
||||
|
||||
#define bind_instr(list, name, ...) \
|
||||
#define bind_instr(list, name, ...) \
|
||||
static const auto& name = make_instr<PPU_opcodes::name>(list, #name, &PPUOpcodes::name, ##__VA_ARGS__)
|
||||
|
||||
bind_instr(main_list, TDI, TO, RA, simm16);
|
||||
|
@ -624,5 +631,30 @@ namespace PPU_instr
|
|||
bind_instr(g3f_0_list, MFFS, FRD, RC);
|
||||
bind_instr(g3f_0_list, MTFSF, FM, FRB, RC);
|
||||
|
||||
enum
|
||||
{
|
||||
r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11,
|
||||
r12, r13, r14, r15, r16, r17, r18, r19, r20, r21,
|
||||
r22, r23, r24, r25, r26, r27, r28, r29, r30, r31
|
||||
};
|
||||
}
|
||||
|
||||
namespace implicts
|
||||
{
|
||||
using namespace lists;
|
||||
|
||||
//static auto LIS = std::bind(ADDIS, std::placeholders::_1, r0, std::placeholders::_2);
|
||||
//static auto LI = std::bind(ADDI, std::placeholders::_1, r0, std::placeholders::_2);
|
||||
static auto NOP = std::bind(ORI, r0, r0, 0);
|
||||
static auto MR = std::bind(OR, std::placeholders::_1, std::placeholders::_2, std::placeholders::_2, false);
|
||||
static auto BLR = std::bind(BCLR, 0x10 | 0x04, 0, 0, 0);
|
||||
static auto BCTR = std::bind(BCCTR, 0x10 | 0x04, 0, 0, 0);
|
||||
static auto BCTRL = std::bind(BCCTR, 0x10 | 0x04, 0, 0, 1);
|
||||
static auto MTCTR = std::bind(MTSPR, (0x1 << 5) | 0x8, std::placeholders::_1);
|
||||
}
|
||||
|
||||
|
||||
using namespace lists;
|
||||
using namespace implicts;
|
||||
#undef bind_instr
|
||||
};
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,772 @@
|
|||
#include "stdafx.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/Cell/PPULLVMRecompiler.h"
|
||||
#include "llvm/Support/Host.h"
|
||||
#include "llvm/IR/Verifier.h"
|
||||
#include "llvm/CodeGen/MachineCodeInfo.h"
|
||||
#include "llvm/ExecutionEngine/GenericValue.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/MC/MCDisassembler.h"
|
||||
|
||||
//#define PPU_LLVM_RECOMPILER_UNIT_TESTS 1
|
||||
|
||||
using namespace llvm;
|
||||
using namespace ppu_recompiler_llvm;
|
||||
|
||||
#define VERIFY_INSTRUCTION_AGAINST_INTERPRETER(fn, tc, input, ...) \
|
||||
VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Compiler::fn, &PPUInterpreter::fn, input, __VA_ARGS__)
|
||||
|
||||
#define VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(fn, s, n, ...) { \
|
||||
PPUState input; \
|
||||
for (int i = s; i < (n + s); i++) { \
|
||||
input.SetRandom(0x10000); \
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(fn, i, input, __VA_ARGS__); \
|
||||
} \
|
||||
}
|
||||
|
||||
/// Register state of a PPU
|
||||
struct ppu_recompiler_llvm::PPUState {
|
||||
/// Floating point registers
|
||||
PPCdouble FPR[32];
|
||||
|
||||
///Floating point status and control register
|
||||
FPSCRhdr FPSCR;
|
||||
|
||||
/// General purpose reggisters
|
||||
u64 GPR[32];
|
||||
|
||||
/// Vector purpose registers
|
||||
u128 VPR[32];
|
||||
|
||||
/// Condition register
|
||||
CRhdr CR;
|
||||
|
||||
/// Fixed point exception register
|
||||
XERhdr XER;
|
||||
|
||||
/// Vector status and control register
|
||||
VSCRhdr VSCR;
|
||||
|
||||
/// Link register
|
||||
u64 LR;
|
||||
|
||||
/// Count register
|
||||
u64 CTR;
|
||||
|
||||
/// SPR general purpose registers
|
||||
u64 SPRG[8];
|
||||
|
||||
/// Time base register
|
||||
u64 TB;
|
||||
|
||||
/// Reservations
|
||||
u64 R_ADDR;
|
||||
u64 R_VALUE;
|
||||
|
||||
/// Mmeory block
|
||||
u32 address;
|
||||
u64 mem_block[64];
|
||||
|
||||
void Load(PPUThread & ppu, u32 addr) {
|
||||
for (int i = 0; i < 32; i++) {
|
||||
FPR[i] = ppu.FPR[i];
|
||||
GPR[i] = ppu.GPR[i];
|
||||
VPR[i] = ppu.VPR[i];
|
||||
|
||||
if (i < 8) {
|
||||
SPRG[i] = ppu.SPRG[i];
|
||||
}
|
||||
}
|
||||
|
||||
FPSCR = ppu.FPSCR;
|
||||
CR = ppu.CR;
|
||||
XER = ppu.XER;
|
||||
VSCR = ppu.VSCR;
|
||||
LR = ppu.LR;
|
||||
CTR = ppu.CTR;
|
||||
TB = ppu.TB;
|
||||
|
||||
R_ADDR = ppu.R_ADDR;
|
||||
R_VALUE = ppu.R_VALUE;
|
||||
|
||||
address = addr;
|
||||
for (int i = 0; i < (sizeof(mem_block) / 8); i++) {
|
||||
mem_block[i] = vm::read64(address + (i * 8));
|
||||
}
|
||||
}
|
||||
|
||||
void Store(PPUThread & ppu) {
|
||||
for (int i = 0; i < 32; i++) {
|
||||
ppu.FPR[i] = FPR[i];
|
||||
ppu.GPR[i] = GPR[i];
|
||||
ppu.VPR[i] = VPR[i];
|
||||
|
||||
if (i < 8) {
|
||||
ppu.SPRG[i] = SPRG[i];
|
||||
}
|
||||
}
|
||||
|
||||
ppu.FPSCR = FPSCR;
|
||||
ppu.CR = CR;
|
||||
ppu.XER = XER;
|
||||
ppu.VSCR = VSCR;
|
||||
ppu.LR = LR;
|
||||
ppu.CTR = CTR;
|
||||
ppu.TB = TB;
|
||||
|
||||
ppu.R_ADDR = R_ADDR;
|
||||
ppu.R_VALUE = R_VALUE;
|
||||
|
||||
for (int i = 0; i < (sizeof(mem_block) / 8); i++) {
|
||||
vm::write64(address + (i * 8), mem_block[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void SetRandom(u32 addr) {
|
||||
std::mt19937_64 rng;
|
||||
|
||||
rng.seed((u32)std::chrono::high_resolution_clock::now().time_since_epoch().count());
|
||||
for (int i = 0; i < 32; i++) {
|
||||
FPR[i] = (double)rng();
|
||||
GPR[i] = rng();
|
||||
VPR[i]._f[0] = (float)rng();
|
||||
VPR[i]._f[1] = (float)rng();
|
||||
VPR[i]._f[2] = (float)rng();
|
||||
VPR[i]._f[3] = (float)rng();
|
||||
|
||||
if (i < 8) {
|
||||
SPRG[i] = rng();
|
||||
}
|
||||
}
|
||||
|
||||
FPSCR.FPSCR = (u32)rng();
|
||||
CR.CR = (u32)rng();
|
||||
XER.XER = 0;
|
||||
XER.CA = (u32)rng();
|
||||
XER.SO = (u32)rng();
|
||||
XER.OV = (u32)rng();
|
||||
VSCR.VSCR = (u32)rng();
|
||||
VSCR.X = 0;
|
||||
VSCR.Y = 0;
|
||||
LR = rng();
|
||||
CTR = rng();
|
||||
TB = rng();
|
||||
R_ADDR = rng();
|
||||
R_VALUE = rng();
|
||||
|
||||
address = addr;
|
||||
for (int i = 0; i < (sizeof(mem_block) / 8); i++) {
|
||||
mem_block[i] = rng();
|
||||
}
|
||||
}
|
||||
|
||||
std::string ToString() const {
|
||||
std::string ret;
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
ret += fmt::Format("GPR[%02d] = 0x%016llx FPR[%02d] = %16g VPR[%02d] = 0x%s [%s]\n", i, GPR[i], i, FPR[i]._double, i, VPR[i].to_hex().c_str(), VPR[i].to_xyzw().c_str());
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
ret += fmt::Format("SPRG[%d] = 0x%016llx\n", i, SPRG[i]);
|
||||
}
|
||||
|
||||
ret += fmt::Format("CR = 0x%08x LR = 0x%016llx CTR = 0x%016llx TB=0x%016llx\n", CR.CR, LR, CTR, TB);
|
||||
ret += fmt::Format("XER = 0x%016llx [CA=%d | OV=%d | SO=%d]\n", XER.XER, fmt::by_value(XER.CA), fmt::by_value(XER.OV), fmt::by_value(XER.SO));
|
||||
//ret += fmt::Format("FPSCR = 0x%08x " // TODO: Uncomment after implementing FPSCR
|
||||
// "[RN=%d | NI=%d | XE=%d | ZE=%d | UE=%d | OE=%d | VE=%d | "
|
||||
// "VXCVI=%d | VXSQRT=%d | VXSOFT=%d | FPRF=%d | "
|
||||
// "FI=%d | FR=%d | VXVC=%d | VXIMZ=%d | "
|
||||
// "VXZDZ=%d | VXIDI=%d | VXISI=%d | VXSNAN=%d | "
|
||||
// "XX=%d | ZX=%d | UX=%d | OX=%d | VX=%d | FEX=%d | FX=%d]\n",
|
||||
// FPSCR.FPSCR,
|
||||
// fmt::by_value(FPSCR.RN),
|
||||
// fmt::by_value(FPSCR.NI), fmt::by_value(FPSCR.XE), fmt::by_value(FPSCR.ZE), fmt::by_value(FPSCR.UE), fmt::by_value(FPSCR.OE), fmt::by_value(FPSCR.VE),
|
||||
// fmt::by_value(FPSCR.VXCVI), fmt::by_value(FPSCR.VXSQRT), fmt::by_value(FPSCR.VXSOFT), fmt::by_value(FPSCR.FPRF),
|
||||
// fmt::by_value(FPSCR.FI), fmt::by_value(FPSCR.FR), fmt::by_value(FPSCR.VXVC), fmt::by_value(FPSCR.VXIMZ),
|
||||
// fmt::by_value(FPSCR.VXZDZ), fmt::by_value(FPSCR.VXIDI), fmt::by_value(FPSCR.VXISI), fmt::by_value(FPSCR.VXSNAN),
|
||||
// fmt::by_value(FPSCR.XX), fmt::by_value(FPSCR.ZX), fmt::by_value(FPSCR.UX), fmt::by_value(FPSCR.OX), fmt::by_value(FPSCR.VX), fmt::by_value(FPSCR.FEX), fmt::by_value(FPSCR.FX));
|
||||
//ret += fmt::Format("VSCR = 0x%08x [NJ=%d | SAT=%d]\n", VSCR.VSCR, fmt::by_value(VSCR.NJ), fmt::by_value(VSCR.SAT)); // TODO: Uncomment after implementing VSCR.SAT
|
||||
ret += fmt::Format("R_ADDR = 0x%016llx R_VALUE = 0x%016llx\n", R_ADDR, R_VALUE);
|
||||
|
||||
for (int i = 0; i < (sizeof(mem_block) / 8); i += 2) {
|
||||
ret += fmt::Format("mem_block[%d] = 0x%016llx mem_block[%d] = 0x%016llx\n", i, mem_block[i], i + 1, mem_block[i + 1]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
#ifdef PPU_LLVM_RECOMPILER_UNIT_TESTS
|
||||
static PPUThread * s_ppu_state = nullptr;
|
||||
static PPUInterpreter * s_interpreter = nullptr;
|
||||
#endif // PPU_LLVM_RECOMPILER_UNIT_TESTS
|
||||
|
||||
template <class CompilerFn, class PPUInterpreterFn, class... Args>
|
||||
void Compiler::VerifyInstructionAgainstInterpreter(const char * name, CompilerFn recomp_fn, PPUInterpreterFn interp_fn, PPUState & input_state, Args... args) {
|
||||
#ifdef PPU_LLVM_RECOMPILER_UNIT_TESTS
|
||||
auto test_case = [&]() {
|
||||
(this->*recomp_fn)(args...);
|
||||
};
|
||||
auto input = [&]() {
|
||||
input_state.Store(*s_ppu_state);
|
||||
};
|
||||
auto check_result = [&](std::string & msg) {
|
||||
PPUState recomp_output_state;
|
||||
PPUState interp_output_state;
|
||||
|
||||
recomp_output_state.Load(*s_ppu_state, input_state.address);
|
||||
input_state.Store(*s_ppu_state);
|
||||
(s_interpreter->*interp_fn)(args...);
|
||||
interp_output_state.Load(*s_ppu_state, input_state.address);
|
||||
|
||||
if (interp_output_state.ToString() != recomp_output_state.ToString()) {
|
||||
msg = std::string("Input state:\n") + input_state.ToString() +
|
||||
std::string("\nOutput state:\n") + recomp_output_state.ToString() +
|
||||
std::string("\nInterpreter output state:\n") + interp_output_state.ToString();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
RunTest(name, test_case, input, check_result);
|
||||
#endif // PPU_LLVM_RECOMPILER_UNIT_TESTS
|
||||
}
|
||||
|
||||
void Compiler::RunTest(const char * name, std::function<void()> test_case, std::function<void()> input, std::function<bool(std::string & msg)> check_result) {
|
||||
#ifdef PPU_LLVM_RECOMPILER_UNIT_TESTS
|
||||
// Create the unit test function
|
||||
m_current_function = (Function *)m_module->getOrInsertFunction(name, m_ir_builder->getVoidTy(),
|
||||
m_ir_builder->getInt8PtrTy() /*ppu_state*/,
|
||||
m_ir_builder->getInt64Ty() /*base_addres*/,
|
||||
m_ir_builder->getInt8PtrTy() /*interpreter*/, nullptr);
|
||||
m_current_function->setCallingConv(CallingConv::X86_64_Win64);
|
||||
auto arg_i = m_current_function->arg_begin();
|
||||
arg_i->setName("ppu_state");
|
||||
(++arg_i)->setName("base_address");
|
||||
(++arg_i)->setName("interpreter");
|
||||
|
||||
auto block = BasicBlock::Create(*m_llvm_context, "start", m_current_function);
|
||||
m_ir_builder->SetInsertPoint(block);
|
||||
|
||||
test_case();
|
||||
|
||||
m_ir_builder->CreateRetVoid();
|
||||
|
||||
// Print the IR
|
||||
std::string ir;
|
||||
raw_string_ostream ir_ostream(ir);
|
||||
m_current_function->print(ir_ostream);
|
||||
LOG_NOTICE(PPU, "[UT %s] LLVM IR:%s", name, ir.c_str());
|
||||
|
||||
std::string verify;
|
||||
raw_string_ostream verify_ostream(verify);
|
||||
if (verifyFunction(*m_current_function, &verify_ostream)) {
|
||||
LOG_ERROR(PPU, "[UT %s] Verification Failed:%s", name, verify.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Optimize
|
||||
m_fpm->run(*m_current_function);
|
||||
|
||||
// Print the optimized IR
|
||||
ir = "";
|
||||
m_current_function->print(ir_ostream);
|
||||
LOG_NOTICE(PPU, "[UT %s] Optimized LLVM IR:%s", name, ir.c_str());
|
||||
|
||||
// Generate the function
|
||||
MachineCodeInfo mci;
|
||||
m_execution_engine->runJITOnFunction(m_current_function, &mci);
|
||||
|
||||
// Disassemble the generated function
|
||||
auto disassembler = LLVMCreateDisasm(sys::getProcessTriple().c_str(), nullptr, 0, nullptr, nullptr);
|
||||
|
||||
LOG_NOTICE(PPU, "[UT %s] Disassembly:", name);
|
||||
for (uint64_t pc = 0; pc < mci.size();) {
|
||||
char str[1024];
|
||||
|
||||
auto size = LLVMDisasmInstruction(disassembler, (uint8_t *)mci.address() + pc, mci.size() - pc, (uint64_t)((uint8_t *)mci.address() + pc), str, sizeof(str));
|
||||
LOG_NOTICE(PPU, "[UT %s] %p: %s.", name, (uint8_t *)mci.address() + pc, str);
|
||||
pc += size;
|
||||
}
|
||||
|
||||
LLVMDisasmDispose(disassembler);
|
||||
|
||||
// Run the test
|
||||
input();
|
||||
std::vector<GenericValue> args;
|
||||
args.push_back(GenericValue(s_ppu_state));
|
||||
args.push_back(GenericValue(s_interpreter));
|
||||
m_execution_engine->runFunction(m_current_function, args);
|
||||
|
||||
// Verify results
|
||||
std::string msg;
|
||||
bool pass = check_result(msg);
|
||||
if (pass) {
|
||||
LOG_NOTICE(PPU, "[UT %s] Test passed. %s", name, msg.c_str());
|
||||
} else {
|
||||
LOG_ERROR(PPU, "[UT %s] Test failed. %s", name, msg.c_str());
|
||||
}
|
||||
|
||||
m_execution_engine->freeMachineCodeForFunction(m_current_function);
|
||||
#endif // PPU_LLVM_RECOMPILER_UNIT_TESTS
|
||||
}
|
||||
|
||||
void Compiler::RunAllTests(PPUThread * ppu_state, PPUInterpreter * interpreter) {
|
||||
#ifdef PPU_LLVM_RECOMPILER_UNIT_TESTS
|
||||
s_ppu_state = ppu_state;
|
||||
s_interpreter = interpreter;
|
||||
|
||||
PPUState initial_state;
|
||||
initial_state.Load(*ppu_state, 0x10000);
|
||||
|
||||
LOG_NOTICE(PPU, "Running Unit Tests");
|
||||
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MFVSCR, 0, 5, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTVSCR, 0, 5, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VADDCUW, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VADDFP, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VADDSBS, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VADDSHS, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VADDSWS, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VADDUBM, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VADDUBS, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VADDUHM, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VADDUHS, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VADDUWM, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VADDUWS, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VAND, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VANDC, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VAVGSB, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VAVGSH, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VAVGSW, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VAVGUB, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VAVGUH, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VAVGUW, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCFSX, 0, 5, 0, 0, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCFSX, 5, 5, 0, 3, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCFUX, 0, 5, 0, 0, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCFUX, 5, 5, 0, 2, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPBFP, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPBFP, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPBFP_, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPBFP_, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPEQFP, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPEQFP, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPEQFP_, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPEQFP_, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPEQUB, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPEQUB, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPEQUB_, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPEQUB_, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPEQUH, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPEQUH, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPEQUH_, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPEQUH_, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPEQUW, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPEQUW, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPEQUW_, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPEQUW_, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGEFP, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGEFP, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGEFP_, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGEFP_, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTFP, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTFP, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTFP_, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTFP_, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTSB, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTSB, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTSB_, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTSB_, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTSH, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTSH, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTSH_, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTSH_, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTSW, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTSW, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTSW_, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTSW_, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTUB, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTUB, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTUB_, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTUB_, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTUH, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTUH, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTUH_, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTUH_, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTUW, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTUW, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTUW_, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VCMPGTUW_, 5, 5, 0, 1, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMADDFP, 0, 5, 0, 1, 2, 3);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMAXFP, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMAXSB, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMAXSH, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMAXSW, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMAXUB, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMAXUH, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMAXUW, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMINFP, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMINSB, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMINSH, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMINSW, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMINUB, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMINUH, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMINUW, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMRGHB, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMRGHH, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMRGHW, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMRGLB, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMRGLH, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMRGLW, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMSUMMBM, 0, 5, 0, 1, 2, 3);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMSUMSHM, 0, 5, 0, 1, 2, 3);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMSUMUBM, 0, 5, 0, 1, 2, 3);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VMSUMUHM, 0, 5, 0, 1, 2, 3);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VNMSUBFP, 0, 5, 0, 1, 2, 3);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VNOR, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VOR, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VPERM, 0, 5, 0, 1, 2, 3);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VREFP, 0, 5, 0, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSEL, 0, 5, 0, 1, 2, 3);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSL, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSLB, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSLDOI, 0, 5, 0, 1, 2, 6);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSLH, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSLO, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSLW, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSPLTB, 0, 5, 0, 3, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSPLTH, 0, 5, 0, 3, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSPLTISB, 0, 5, 0, 12345);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSPLTISH, 0, 5, 0, 12345);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSPLTISW, 0, 5, 0, -12345);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSPLTW, 0, 5, 0, 3, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSR, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSRAB, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSRAH, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSRAW, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSRB, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSRH, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSRO, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSRW, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSUBFP, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSUBSBS, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSUBSHS, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSUBSWS, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSUBUBM, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSUBUBS, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSUBUHM, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSUBUHS, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSUBUWM, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VSUBUWS, 0, 5, 0, 1, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(VXOR, 0, 5, 0, 1, 2);
|
||||
// TODO: Rest of the vector instructions
|
||||
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULLI, 0, 5, 1, 2, 12345);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SUBFIC, 0, 5, 1, 2, 12345);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMPLI, 0, 5, 1, 0, 7, 12345);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMPLI, 5, 5, 1, 1, 7, 12345);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMPI, 0, 5, 5, 0, 7, -12345);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMPI, 5, 5, 5, 1, 7, -12345);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDIC, 0, 5, 1, 2, 12345);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDIC_, 0, 5, 1, 2, 12345);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDI, 0, 5, 1, 2, 12345);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDI, 5, 5, 0, 2, 12345);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDIS, 0, 5, 1, 2, -12345);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDIS, 5, 5, 0, 2, -12345);
|
||||
// TODO: BC
|
||||
// TODO: SC
|
||||
// TODO: B
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MCRF, 0, 5, 0, 7);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MCRF, 5, 5, 6, 2);
|
||||
// TODO: BCLR
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CRNOR, 0, 5, 0, 7, 3);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CRANDC, 0, 5, 5, 6, 7);
|
||||
// TODO: ISYNC
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CRXOR, 0, 5, 7, 7, 7);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CRNAND, 0, 5, 3, 4, 5);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CRAND, 0, 5, 1, 2, 3);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CREQV, 0, 5, 2, 1, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CRORC, 0, 5, 3, 4, 5);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CROR, 0, 5, 6, 7, 0);
|
||||
// TODO: BCCTR
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(RLWIMI, 0, 5, 7, 8, 9, 12, 25, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(RLWIMI, 5, 5, 21, 22, 21, 18, 24, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(RLWINM, 0, 5, 7, 8, 9, 12, 25, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(RLWINM, 5, 5, 21, 22, 21, 18, 24, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(RLWNM, 0, 5, 7, 8, 9, 12, 25, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(RLWNM, 5, 5, 21, 22, 21, 18, 24, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ORI, 0, 5, 25, 29, 12345);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ORIS, 0, 5, 7, 31, -12345);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(XORI, 0, 5, 0, 19, 12345);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(XORIS, 0, 5, 3, 14, -12345);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ANDI_, 0, 5, 16, 7, 12345);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ANDIS_, 0, 5, 23, 21, -12345);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(RLDICL, 0, 5, 7, 8, 9, 12, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(RLDICL, 5, 5, 21, 22, 43, 43, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(RLDICR, 0, 5, 7, 8, 0, 12, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(RLDICR, 5, 5, 21, 22, 63, 43, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(RLDIC, 0, 5, 7, 8, 9, 12, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(RLDIC, 5, 5, 21, 22, 23, 43, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(RLDIMI, 0, 5, 7, 8, 9, 12, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(RLDIMI, 5, 5, 21, 22, 23, 43, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(RLDC_LR, 0, 5, 7, 8, 9, 12, 0, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(RLDC_LR, 5, 5, 21, 22, 23, 43, 1, 1);
|
||||
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADD, 0, 5, 7, 8, 9, 0, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADD, 5, 5, 21, 22, 23, 0, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SUBF, 0, 5, 7, 8, 9, 0, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SUBF, 5, 5, 21, 22, 23, 0, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(NEG, 0, 5, 7, 8, 0, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(NEG, 5, 5, 21, 22, 0, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULHDU, 0, 5, 7, 8, 9, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULHDU, 5, 5, 21, 22, 23, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULHWU, 0, 5, 7, 8, 9, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULHWU, 5, 5, 21, 22, 23, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULHD, 0, 5, 7, 8, 9, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULHD, 5, 5, 21, 22, 23, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULHW, 0, 5, 7, 8, 9, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULHW, 5, 5, 21, 22, 23, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULLD, 0, 5, 7, 8, 9, 0, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULLD, 5, 5, 21, 22, 23, 0, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULLW, 0, 5, 7, 8, 9, 0, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MULLW, 5, 5, 21, 22, 23, 0, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVD, 0, 5, 7, 8, 9, 0, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVD, 5, 5, 21, 22, 23, 0, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVDU, 0, 5, 7, 8, 9, 0, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVDU, 5, 5, 21, 22, 23, 0, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVW, 0, 5, 7, 8, 9, 0, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVW, 5, 5, 21, 22, 23, 0, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVWU, 0, 5, 7, 8, 9, 0, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(DIVWU, 5, 5, 21, 22, 23, 0, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(AND, 0, 5, 7, 8, 9, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(AND, 5, 5, 21, 22, 23, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(OR, 0, 5, 7, 8, 9, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(OR, 5, 5, 21, 22, 23, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(XOR, 0, 5, 7, 8, 9, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(XOR, 5, 5, 21, 22, 23, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(NOR, 0, 5, 7, 8, 9, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(NOR, 5, 5, 21, 22, 23, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMP, 0, 5, 3, 0, 9, 31);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMP, 5, 5, 6, 1, 23, 14);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMPL, 0, 5, 3, 0, 9, 31);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CMPL, 5, 5, 6, 1, 23, 14);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDC, 0, 5, 0, 1, 2, 0, false);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ADDC, 5, 5, 0, 1, 2, 0, true);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SUBFC, 0, 5, 0, 1, 2, 0, false);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SUBFC, 5, 5, 0, 1, 2, 0, true);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSB, 0, 5, 3, 5, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSB, 5, 5, 3, 5, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSH, 0, 5, 6, 9, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSH, 5, 5, 6, 9, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSW, 0, 5, 25, 29, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EXTSW, 5, 5, 25, 29, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTSPR, 0, 5, 0x20, 5);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTSPR, 5, 5, 0x100, 5);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTSPR, 10, 5, 0x120, 5);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MTSPR, 15, 5, 0x8, 5);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MFSPR, 0, 5, 5, 0x20);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MFSPR, 5, 5, 5, 0x100);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MFSPR, 10, 5, 5, 0x120);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(MFSPR, 15, 5, 5, 0x8);
|
||||
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRAWI, 0, 5, 5, 6, 0, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRAWI, 5, 5, 5, 6, 12, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRAWI, 10, 5, 5, 6, 22, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRAWI, 15, 5, 5, 6, 31, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRAW, 0, 5, 5, 6, 7, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRAW, 5, 5, 5, 6, 7, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRADI1, 0, 5, 5, 6, 0, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRADI1, 5, 5, 5, 6, 12, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRADI1, 10, 5, 5, 6, 48, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRADI1, 15, 5, 5, 6, 63, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRAD, 0, 5, 5, 6, 7, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRAD, 5, 5, 5, 6, 7, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SLW, 0, 5, 5, 6, 7, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SLW, 5, 5, 5, 6, 7, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRW, 0, 5, 5, 6, 7, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRW, 5, 5, 5, 6, 7, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SLD, 0, 5, 5, 6, 7, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SLD, 5, 5, 5, 6, 7, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRD, 0, 5, 5, 6, 7, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(SRD, 5, 5, 5, 6, 7, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CNTLZW, 0, 5, 5, 6, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CNTLZW, 5, 5, 5, 6, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CNTLZD, 0, 5, 5, 6, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(CNTLZD, 5, 5, 5, 6, 1);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(ISYNC, 0, 5);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(EIEIO, 0, 5);
|
||||
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FSQRT, 0, 5, 0, 1, false);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FSQRTS, 0, 5, 0, 1, false);
|
||||
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FDIV, 0, 5, 0, 1, 2, false);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FSUB, 0, 5, 0, 1, 2, false);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FADD, 0, 5, 0, 1, 2, false);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FMUL, 0, 5, 0, 1, 2, false);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FMSUB, 0, 5, 0, 1, 2, 3, false);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FMADD, 0, 5, 0, 1, 2, 3, false);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FNMSUB, 0, 5, 0, 1, 2, 3, false);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FNMADD, 0, 5, 0, 1, 2, 3, false);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FNEG, 0, 5, 0, 1, false);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FMR, 0, 5, 0, 1, false);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FNABS, 0, 5, 0, 1, false);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FABS, 0, 5, 0, 1, false);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FCFID, 0, 5, 0, 1, false);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FCTID, 0, 5, 0, 1, false);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER_USING_RANDOM_INPUT(FCTIW, 0, 5, 0, 1, false);
|
||||
|
||||
PPUState input;
|
||||
input.SetRandom(0x10000);
|
||||
input.GPR[14] = 10;
|
||||
input.GPR[21] = 15;
|
||||
input.GPR[23] = 0x10000;
|
||||
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LBZ, 0, input, 5, 0, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LBZ, 1, input, 5, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LBZU, 0, input, 5, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LBZX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LBZX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LBZUX, 0, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZ, 0, input, 5, 0, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZ, 1, input, 5, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZU, 0, input, 5, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZUX, 0, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHA, 0, input, 5, 0, 0x100F0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHA, 1, input, 5, 14, 0x100F0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHAU, 0, input, 5, 14, 0x100F0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHAX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHAX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHAUX, 0, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHBRX, 0, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWZ, 0, input, 5, 0, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWZ, 1, input, 5, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWZU, 0, input, 5, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWZX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWZX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWZUX, 0, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWA, 0, input, 5, 0, 0x100F0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWA, 1, input, 5, 14, 0x100F0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWAX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWAX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWAUX, 0, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWBRX, 0, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LD, 0, input, 5, 0, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LD, 1, input, 5, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDU, 0, input, 5, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDUX, 0, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDBRX, 0, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LFS, 0, input, 5, 0, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LFS, 1, input, 5, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LFSU, 0, input, 5, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LFSX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LFSX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LFSUX, 0, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LFD, 0, input, 5, 0, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LFD, 1, input, 5, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LFDU, 0, input, 5, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LFDX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LFDX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LFDUX, 0, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWARX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWARX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDARX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDARX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LSWI, 0, input, 5, 23, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LSWI, 1, input, 5, 23, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LSWI, 2, input, 5, 23, 7);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LSWI, 3, input, 5, 23, 25);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LMW, 0, input, 5, 0, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LMW, 1, input, 16, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVXL, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVXL, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVSL, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVSL, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVSL, 2, input, 5, 21, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVSR, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVSR, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVSR, 2, input, 5, 21, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVEBX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVEBX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVEBX, 2, input, 5, 21, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVEHX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVEHX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVEHX, 2, input, 5, 21, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVEWX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVEWX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVEWX, 2, input, 5, 21, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVLX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVLX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVLX, 2, input, 5, 21, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVRX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVRX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LVRX, 2, input, 5, 21, 23);
|
||||
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STB, 0, input, 3, 0, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STB, 1, input, 3, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBU, 0, input, 3, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBX, 0, input, 3, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBX, 1, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBUX, 0, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STH, 0, input, 3, 0, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STH, 1, input, 3, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHU, 0, input, 3, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHX, 0, input, 3, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHX, 1, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHUX, 0, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHBRX, 0, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STW, 0, input, 3, 0, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STW, 1, input, 3, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWU, 0, input, 3, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWX, 0, input, 3, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWX, 1, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWUX, 0, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWBRX, 0, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STD, 0, input, 3, 0, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STD, 1, input, 3, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDU, 0, input, 3, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDX, 0, input, 3, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDX, 1, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDUX, 0, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFS, 0, input, 3, 0, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFS, 1, input, 3, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFSU, 0, input, 3, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFSX, 0, input, 3, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFSX, 1, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFSUX, 0, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFD, 0, input, 3, 0, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFD, 1, input, 3, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFDU, 0, input, 3, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFDX, 0, input, 3, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFDX, 1, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFDUX, 0, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFIWX, 0, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STVX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STVX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STVXL, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STVXL, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STVEBX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STVEBX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STVEHX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STVEHX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STVEWX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STVEWX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STMW, 0, input, 5, 0, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STMW, 1, input, 16, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STSWI, 0, input, 5, 23, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STSWI, 1, input, 5, 23, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STSWI, 2, input, 5, 23, 7);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STSWI, 3, input, 5, 23, 25);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(DCBZ, 0, input, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(DCBZ, 1, input, 14, 23);
|
||||
|
||||
initial_state.Store(*ppu_state);
|
||||
#endif // PPU_LLVM_RECOMPILER_UNIT_TESTS
|
||||
}
|
|
@ -276,7 +276,7 @@ namespace PPU_opcodes
|
|||
LVEHX = 0x027, //Load Vector Element Halfword Indexed
|
||||
SUBF = 0x028,
|
||||
LDUX = 0x035, //Load Doubleword with Update Indexed
|
||||
DCBST = 0x036,
|
||||
DCBST = 0x036, //Data Cache Block Store
|
||||
LWZUX = 0x037,
|
||||
CNTLZD = 0x03a,
|
||||
ANDC = 0x03c,
|
||||
|
@ -285,7 +285,7 @@ namespace PPU_opcodes
|
|||
MULHD = 0x049,
|
||||
MULHW = 0x04b,
|
||||
LDARX = 0x054,
|
||||
DCBF = 0x056,
|
||||
DCBF = 0x056, //Data Cache Block Flush
|
||||
LBZX = 0x057,
|
||||
LVX = 0x067, //Load Vector Indexed
|
||||
NEG = 0x068,
|
||||
|
@ -311,11 +311,11 @@ namespace PPU_opcodes
|
|||
MULLD = 0x0e9,
|
||||
ADDME = 0x0ea,
|
||||
MULLW = 0x0eb,
|
||||
DCBTST = 0x0f6,
|
||||
DCBTST = 0x0f6, //Data Cache Block Touch for Store
|
||||
STBUX = 0x0f7,
|
||||
DOZ = 0x108,
|
||||
ADD = 0x10a,
|
||||
DCBT = 0x116,
|
||||
DCBT = 0x116, //Data Cache Block Touch
|
||||
LHZX = 0x117,
|
||||
EQV = 0x11c,
|
||||
ECIWX = 0x136,
|
||||
|
@ -338,7 +338,7 @@ namespace PPU_opcodes
|
|||
DIVDU = 0x1c9,
|
||||
DIVWU = 0x1cb,
|
||||
MTSPR = 0x1d3,
|
||||
DCBI = 0x1d6,
|
||||
DCBI = 0x1d6, //Data Cache Block Invalidate
|
||||
NAND = 0x1dc,
|
||||
STVXL = 0x1e7, //Store Vector Indexed Last
|
||||
DIVD = 0x1e9,
|
||||
|
@ -382,8 +382,8 @@ namespace PPU_opcodes
|
|||
EXTSB = 0x3ba,
|
||||
STFIWX = 0x3d7,
|
||||
EXTSW = 0x3da,
|
||||
ICBI = 0x3d6,
|
||||
DCBZ = 0x3f6,
|
||||
ICBI = 0x3d6, //Instruction Cache Block Invalidate
|
||||
DCBZ = 0x3f6, //Data Cache Block Set to Zero
|
||||
};
|
||||
|
||||
enum G_3aOpcodes //Field 30 - 31
|
||||
|
@ -738,7 +738,7 @@ public:
|
|||
virtual void DIVDU(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) = 0;
|
||||
virtual void DIVWU(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) = 0;
|
||||
virtual void MTSPR(u32 spr, u32 rs) = 0;
|
||||
//DCBI
|
||||
virtual void DCBI(u32 ra, u32 rb) = 0;
|
||||
virtual void NAND(u32 ra, u32 rs, u32 rb, bool rc) = 0;
|
||||
virtual void STVXL(u32 vs, u32 ra, u32 rb) = 0;
|
||||
virtual void DIVD(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) = 0;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#include "stdafx_gui.h"
|
||||
#include "PPUProgramCompiler.h"
|
||||
#include "Utilities/rFile.h"
|
||||
|
||||
/*
|
||||
using namespace PPU_instr;
|
||||
|
||||
template<typename TO, typename T>
|
||||
|
@ -78,10 +78,10 @@ SectionInfo::SectionInfo(const std::string& _name)
|
|||
section_name_offs += name.length() + 1;
|
||||
}
|
||||
|
||||
void SectionInfo::SetDataSize(u32 size, u32 align)
|
||||
void SectionInfo::SetDataSize(u32 size, u32 addralign)
|
||||
{
|
||||
if(align) shdr.sh_addralign = align;
|
||||
if(shdr.sh_addralign) size = AlignAddr(size, shdr.sh_addralign);
|
||||
if (addralign) shdr.sh_addralign = addralign;
|
||||
if (shdr.sh_addralign) size = align(size, shdr.sh_addralign);
|
||||
|
||||
if(!code.empty())
|
||||
{
|
||||
|
@ -985,7 +985,7 @@ void CompilePPUProgram::Compile()
|
|||
elf_info.e_shnum = 15;
|
||||
elf_info.e_shstrndx = elf_info.e_shnum - 1;
|
||||
elf_info.e_phoff = elf_info.e_ehsize;
|
||||
u32 section_offset = AlignAddr(elf_info.e_phoff + elf_info.e_phnum * elf_info.e_phentsize, 0x100);
|
||||
u32 section_offset = align(elf_info.e_phoff + elf_info.e_phnum * elf_info.e_phentsize, 0x100);
|
||||
|
||||
static const u32 sceStub_text_block = 8 * 4;
|
||||
|
||||
|
@ -1143,7 +1143,7 @@ void CompilePPUProgram::Compile()
|
|||
Elf64_Shdr s_sceStub_text;
|
||||
memset(&s_sceStub_text, 0, sizeof(Elf64_Shdr));
|
||||
s_sceStub_text.sh_addralign = 4;
|
||||
section_offset = AlignAddr(section_offset, s_sceStub_text.sh_addralign);
|
||||
section_offset = align(section_offset, s_sceStub_text.sh_addralign);
|
||||
s_sceStub_text.sh_type = 1;
|
||||
s_sceStub_text.sh_offset = section_offset;
|
||||
s_sceStub_text.sh_addr = section_offset + 0x10000;
|
||||
|
@ -1167,7 +1167,7 @@ void CompilePPUProgram::Compile()
|
|||
Elf64_Shdr s_lib_stub_top;
|
||||
memset(&s_lib_stub_top, 0, sizeof(Elf64_Shdr));
|
||||
s_lib_stub_top.sh_addralign = 4;
|
||||
section_offset = AlignAddr(section_offset, s_lib_stub_top.sh_addralign);
|
||||
section_offset = align(section_offset, s_lib_stub_top.sh_addralign);
|
||||
s_lib_stub_top.sh_type = 1;
|
||||
s_lib_stub_top.sh_name = section_name_offset;
|
||||
s_lib_stub_top.sh_offset = section_offset;
|
||||
|
@ -1186,7 +1186,7 @@ void CompilePPUProgram::Compile()
|
|||
s_lib_stub.sh_offset = section_offset;
|
||||
s_lib_stub.sh_addr = section_offset + 0x10000;
|
||||
s_lib_stub.sh_flags = 2;
|
||||
s_lib_stub.sh_size = sizeof(Elf64_StubHeader) * modules.size();
|
||||
s_lib_stub.sh_size = sizeof(sys_stub) * modules.size();
|
||||
sections_names.push_back(".lib.stub");
|
||||
section_name_offset += std::string(".lib.stub").length() + 1;
|
||||
section_offset += s_lib_stub.sh_size;
|
||||
|
@ -1207,7 +1207,7 @@ void CompilePPUProgram::Compile()
|
|||
Elf64_Shdr s_rodata_sceFNID;
|
||||
memset(&s_rodata_sceFNID, 0, sizeof(Elf64_Shdr));
|
||||
s_rodata_sceFNID.sh_addralign = 4;
|
||||
section_offset = AlignAddr(section_offset, s_rodata_sceFNID.sh_addralign);
|
||||
section_offset = align(section_offset, s_rodata_sceFNID.sh_addralign);
|
||||
s_rodata_sceFNID.sh_type = 1;
|
||||
s_rodata_sceFNID.sh_name = section_name_offset;
|
||||
s_rodata_sceFNID.sh_offset = section_offset;
|
||||
|
@ -1221,7 +1221,7 @@ void CompilePPUProgram::Compile()
|
|||
Elf64_Shdr s_rodata_sceResident;
|
||||
memset(&s_rodata_sceResident, 0, sizeof(Elf64_Shdr));
|
||||
s_rodata_sceResident.sh_addralign = 4;
|
||||
section_offset = AlignAddr(section_offset, s_rodata_sceResident.sh_addralign);
|
||||
section_offset = align(section_offset, s_rodata_sceResident.sh_addralign);
|
||||
s_rodata_sceResident.sh_type = 1;
|
||||
s_rodata_sceResident.sh_name = section_name_offset;
|
||||
s_rodata_sceResident.sh_offset = section_offset;
|
||||
|
@ -1232,7 +1232,7 @@ void CompilePPUProgram::Compile()
|
|||
{
|
||||
s_rodata_sceResident.sh_size += module.m_name.length() + 1;
|
||||
}
|
||||
s_rodata_sceResident.sh_size = AlignAddr(s_rodata_sceResident.sh_size, s_rodata_sceResident.sh_addralign);
|
||||
s_rodata_sceResident.sh_size = align(s_rodata_sceResident.sh_size, s_rodata_sceResident.sh_addralign);
|
||||
sections_names.push_back(".rodata.sceResident");
|
||||
section_name_offset += std::string(".rodata.sceResident").length() + 1;
|
||||
section_offset += s_rodata_sceResident.sh_size;
|
||||
|
@ -1240,7 +1240,7 @@ void CompilePPUProgram::Compile()
|
|||
Elf64_Shdr s_lib_ent_top;
|
||||
memset(&s_lib_ent_top, 0, sizeof(Elf64_Shdr));
|
||||
s_lib_ent_top.sh_addralign = 4;
|
||||
section_offset = AlignAddr(section_offset, s_lib_ent_top.sh_addralign);
|
||||
section_offset = align(section_offset, s_lib_ent_top.sh_addralign);
|
||||
s_lib_ent_top.sh_size = 4;
|
||||
s_lib_ent_top.sh_flags = 2;
|
||||
s_lib_ent_top.sh_type = 1;
|
||||
|
@ -1267,7 +1267,7 @@ void CompilePPUProgram::Compile()
|
|||
Elf64_Shdr s_sys_proc_prx_param;
|
||||
memset(&s_sys_proc_prx_param, 0, sizeof(Elf64_Shdr));
|
||||
s_sys_proc_prx_param.sh_addralign = 4;
|
||||
section_offset = AlignAddr(section_offset, s_sys_proc_prx_param.sh_addralign);
|
||||
section_offset = align(section_offset, s_sys_proc_prx_param.sh_addralign);
|
||||
s_sys_proc_prx_param.sh_type = 1;
|
||||
s_sys_proc_prx_param.sh_size = sizeof(sys_proc_prx_param);
|
||||
s_sys_proc_prx_param.sh_name = section_name_offset;
|
||||
|
@ -1280,14 +1280,14 @@ void CompilePPUProgram::Compile()
|
|||
|
||||
const u32 prog_load_0_end = section_offset;
|
||||
|
||||
section_offset = AlignAddr(section_offset + 0x10000, 0x10000);
|
||||
section_offset = align(section_offset + 0x10000, 0x10000);
|
||||
const u32 prog_load_1_start = section_offset;
|
||||
|
||||
Elf64_Shdr s_data_sceFStub;
|
||||
memset(&s_data_sceFStub, 0, sizeof(Elf64_Shdr));
|
||||
s_data_sceFStub.sh_name = section_name_offset;
|
||||
s_data_sceFStub.sh_addralign = 4;
|
||||
section_offset = AlignAddr(section_offset, s_data_sceFStub.sh_addralign);
|
||||
section_offset = align(section_offset, s_data_sceFStub.sh_addralign);
|
||||
s_data_sceFStub.sh_flags = 3;
|
||||
s_data_sceFStub.sh_type = 1;
|
||||
s_data_sceFStub.sh_offset = section_offset;
|
||||
|
@ -1300,7 +1300,7 @@ void CompilePPUProgram::Compile()
|
|||
Elf64_Shdr s_tbss;
|
||||
memset(&s_tbss, 0, sizeof(Elf64_Shdr));
|
||||
s_tbss.sh_addralign = 4;
|
||||
section_offset = AlignAddr(section_offset, s_tbss.sh_addralign);
|
||||
section_offset = align(section_offset, s_tbss.sh_addralign);
|
||||
s_tbss.sh_size = 4;
|
||||
s_tbss.sh_flags = 0x403;
|
||||
s_tbss.sh_type = 8;
|
||||
|
@ -1314,7 +1314,7 @@ void CompilePPUProgram::Compile()
|
|||
Elf64_Shdr s_opd;
|
||||
memset(&s_opd, 0, sizeof(Elf64_Shdr));
|
||||
s_opd.sh_addralign = 8;
|
||||
section_offset = AlignAddr(section_offset, s_opd.sh_addralign);
|
||||
section_offset = align(section_offset, s_opd.sh_addralign);
|
||||
s_opd.sh_size = 2*4;
|
||||
s_opd.sh_type = 1;
|
||||
s_opd.sh_offset = section_offset;
|
||||
|
@ -1475,7 +1475,7 @@ void CompilePPUProgram::Compile()
|
|||
|
||||
if(!m_file_path.empty() && !m_analyze && !m_error)
|
||||
{
|
||||
s_opd.sh_size = AlignAddr(s_opd.sh_size, s_opd.sh_addralign);
|
||||
s_opd.sh_size = align(s_opd.sh_size, s_opd.sh_addralign);
|
||||
section_offset += s_opd.sh_size;
|
||||
|
||||
const u32 prog_load_1_end = section_offset;
|
||||
|
@ -1483,7 +1483,7 @@ void CompilePPUProgram::Compile()
|
|||
Elf64_Shdr s_shstrtab;
|
||||
memset(&s_shstrtab, 0, sizeof(Elf64_Shdr));
|
||||
s_shstrtab.sh_addralign = 1;
|
||||
section_offset = AlignAddr(section_offset, s_shstrtab.sh_addralign);
|
||||
section_offset = align(section_offset, s_shstrtab.sh_addralign);
|
||||
s_shstrtab.sh_name = section_name_offset;
|
||||
s_shstrtab.sh_type = 3;
|
||||
s_shstrtab.sh_offset = section_offset;
|
||||
|
@ -1505,7 +1505,7 @@ void CompilePPUProgram::Compile()
|
|||
elf_info.e_machine = MACHINE_PPC64; //PowerPC64
|
||||
elf_info.e_version = 1; //ver 1
|
||||
elf_info.e_flags = 0x0;
|
||||
elf_info.e_shoff = AlignAddr(section_offset, 4);
|
||||
elf_info.e_shoff = align(section_offset, 4);
|
||||
|
||||
u8* opd_data = new u8[s_opd.sh_size];
|
||||
u32 entry_point = s_text.sh_addr;
|
||||
|
@ -1523,14 +1523,14 @@ void CompilePPUProgram::Compile()
|
|||
sys_proc_prx_param prx_param;
|
||||
memset(&prx_param, 0, sizeof(sys_proc_prx_param));
|
||||
|
||||
prx_param.size = re32(0x40);
|
||||
prx_param.magic = re32(0x1b434cec);
|
||||
prx_param.version = re32(0x4);
|
||||
prx_param.libentstart = re32(s_lib_ent_top.sh_addr + s_lib_ent_top.sh_size);
|
||||
prx_param.libentend = re32(s_lib_ent_btm.sh_addr);
|
||||
prx_param.libstubstart = re32(s_lib_stub_top.sh_addr + s_lib_stub_top.sh_size);
|
||||
prx_param.libstubend = re32(s_lib_stub_btm.sh_addr);
|
||||
prx_param.ver = re16(0x101);
|
||||
prx_param.size = 0x40;
|
||||
prx_param.magic = 0x1b434cec;
|
||||
prx_param.version = 0x4;
|
||||
prx_param.libentstart = s_lib_ent_top.sh_addr + s_lib_ent_top.sh_size;
|
||||
prx_param.libentend = s_lib_ent_btm.sh_addr;
|
||||
prx_param.libstubstart = vm::bptr<sys_stub>::make(s_lib_stub_top.sh_addr + s_lib_stub_top.sh_size);
|
||||
prx_param.libstubend = vm::bptr<sys_stub>::make(s_lib_stub_btm.sh_addr);
|
||||
prx_param.ver = 0x101;
|
||||
|
||||
elf_info.e_entry = s_opd.sh_addr;
|
||||
|
||||
|
@ -1588,20 +1588,20 @@ void CompilePPUProgram::Compile()
|
|||
f.Seek(s_lib_stub.sh_offset);
|
||||
for(u32 i=0, nameoffs=4, dataoffs=0; i<modules.size(); ++i)
|
||||
{
|
||||
Elf64_StubHeader stub;
|
||||
memset(&stub, 0, sizeof(Elf64_StubHeader));
|
||||
sys_stub stub;
|
||||
memset(&stub, 0, sizeof(sys_stub));
|
||||
|
||||
stub.s_size = 0x2c;
|
||||
stub.s_version = re16(0x1);
|
||||
stub.s_unk1 = re16(0x9);
|
||||
stub.s_modulename = re32(s_rodata_sceResident.sh_addr + nameoffs);
|
||||
stub.s_nid = re32(s_rodata_sceFNID.sh_addr + dataoffs);
|
||||
stub.s_text = re32(s_data_sceFStub.sh_addr + dataoffs);
|
||||
stub.s_imports = re16(modules[i].m_imports.size());
|
||||
stub.s_modulename = vm::bptr<const char>::make(s_rodata_sceResident.sh_addr + nameoffs);
|
||||
stub.s_nid = vm::bptr<u32>::make(s_rodata_sceFNID.sh_addr + dataoffs);
|
||||
stub.s_text = vm::bptr<u32>::make(s_data_sceFStub.sh_addr + dataoffs);
|
||||
stub.s_imports = modules[i].m_imports.size();
|
||||
|
||||
dataoffs += modules[i].m_imports.size() * 4;
|
||||
|
||||
f.Write(&stub, sizeof(Elf64_StubHeader));
|
||||
f.Write(&stub, sizeof(sys_stub));
|
||||
nameoffs += modules[i].m_name.length() + 1;
|
||||
}
|
||||
|
||||
|
@ -1732,3 +1732,4 @@ void CompilePPUProgram::Compile()
|
|||
system("make_fself.cmd");
|
||||
}
|
||||
}
|
||||
*/
|
|
@ -1,7 +1,7 @@
|
|||
#pragma once
|
||||
#include "PPUInstrTable.h"
|
||||
#include "Loader/ELF64.h"
|
||||
|
||||
/*
|
||||
enum ArgType
|
||||
{
|
||||
ARG_ERR = 0,
|
||||
|
@ -189,3 +189,4 @@ protected:
|
|||
public:
|
||||
void Compile();
|
||||
};
|
||||
*/
|
|
@ -9,6 +9,9 @@
|
|||
#include "Emu/SysCalls/Static.h"
|
||||
#include "Emu/Cell/PPUDecoder.h"
|
||||
#include "Emu/Cell/PPUInterpreter.h"
|
||||
#include "Emu/Cell/PPULLVMRecompiler.h"
|
||||
//#include "Emu/Cell/PPURecompiler.h"
|
||||
#include "Emu/CPU/CPUThreadManager.h"
|
||||
|
||||
PPUThread& GetCurrentPPUThread()
|
||||
{
|
||||
|
@ -38,11 +41,11 @@ void PPUThread::DoReset()
|
|||
memset(FPR, 0, sizeof(FPR));
|
||||
memset(GPR, 0, sizeof(GPR));
|
||||
memset(SPRG, 0, sizeof(SPRG));
|
||||
memset(USPRG, 0, sizeof(USPRG));
|
||||
|
||||
CR.CR = 0;
|
||||
LR = 0;
|
||||
CTR = 0;
|
||||
USPRG0 = 0;
|
||||
TB = 0;
|
||||
XER.XER = 0;
|
||||
FPSCR.FPSCR = 0;
|
||||
|
@ -83,8 +86,10 @@ void PPUThread::InitRegs()
|
|||
}
|
||||
*/
|
||||
|
||||
GPR[1] = AlignAddr(m_stack_addr + m_stack_size, 0x200) - 0x200;
|
||||
GPR[1] = align(m_stack_addr + m_stack_size, 0x200) - 0x200;
|
||||
GPR[2] = rtoc;
|
||||
//GPR[11] = entry;
|
||||
//GPR[12] = Emu.GetMallocPageSize();
|
||||
GPR[13] = Memory.PRXMem.GetStartAddr() + 0x7060;
|
||||
|
||||
LR = Emu.GetPPUThreadExit();
|
||||
|
@ -103,13 +108,26 @@ void PPUThread::DoRun()
|
|||
break;
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
{
|
||||
auto ppui = new PPUInterpreter(*this);
|
||||
m_dec = new PPUDecoder(ppui);
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
#ifdef PPU_LLVM_RECOMPILER
|
||||
SetCallStackTracing(false);
|
||||
if (!m_dec) {
|
||||
m_dec = new ppu_recompiler_llvm::ExecutionEngine(*this);
|
||||
}
|
||||
#else
|
||||
LOG_ERROR(PPU, "This image does not include PPU JIT (LLVM)");
|
||||
Emu.Pause();
|
||||
#endif
|
||||
break;
|
||||
|
||||
//case 3: m_dec = new PPURecompiler(*this); break;
|
||||
|
||||
default:
|
||||
LOG_ERROR(PPU, "Invalid CPU decoder mode: %d", Ini.CPUDecoderMode.GetValue());
|
||||
Emu.Pause();
|
||||
|
@ -187,7 +205,7 @@ u64 PPUThread::FastCall2(u32 addr, u32 rtoc)
|
|||
LR = Emu.m_ppu_thr_stop;
|
||||
SetCurrentNamedThread(this);
|
||||
|
||||
Task();
|
||||
CPUThread::Task();
|
||||
|
||||
m_status = old_status;
|
||||
PC = old_PC;
|
||||
|
@ -203,3 +221,71 @@ void PPUThread::FastStop()
|
|||
{
|
||||
m_status = Stopped;
|
||||
}
|
||||
|
||||
void PPUThread::Task()
|
||||
{
|
||||
if (custom_task)
|
||||
{
|
||||
custom_task(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
CPUThread::Task();
|
||||
}
|
||||
}
|
||||
|
||||
ppu_thread::ppu_thread(u32 entry, const std::string& name, u32 stack_size, u32 prio)
|
||||
{
|
||||
thread = &Emu.GetCPU().AddThread(CPU_THREAD_PPU);
|
||||
|
||||
thread->SetName(name);
|
||||
thread->SetEntry(entry);
|
||||
thread->SetStackSize(stack_size ? stack_size : Emu.GetInfo().GetProcParam().primary_stacksize);
|
||||
thread->SetPrio(prio ? prio : Emu.GetInfo().GetProcParam().primary_prio);
|
||||
|
||||
argc = 0;
|
||||
}
|
||||
|
||||
cpu_thread& ppu_thread::args(std::initializer_list<std::string> values)
|
||||
{
|
||||
if (!values.size())
|
||||
return *this;
|
||||
|
||||
assert(argc == 0);
|
||||
|
||||
envp.set(vm::alloc(align((u32)sizeof(*envp), stack_align), vm::main));
|
||||
*envp = 0;
|
||||
argv.set(vm::alloc(sizeof(*argv) * values.size(), vm::main));
|
||||
|
||||
for (auto &arg : values)
|
||||
{
|
||||
u32 arg_size = align(u32(arg.size() + 1), stack_align);
|
||||
u32 arg_addr = vm::alloc(arg_size, vm::main);
|
||||
|
||||
std::strcpy(vm::get_ptr<char>(arg_addr), arg.c_str());
|
||||
|
||||
argv[argc++] = arg_addr;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
cpu_thread& ppu_thread::run()
|
||||
{
|
||||
thread->Run();
|
||||
|
||||
gpr(3, argc);
|
||||
gpr(4, argv.addr());
|
||||
gpr(5, envp.addr());
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ppu_thread& ppu_thread::gpr(uint index, u64 value)
|
||||
{
|
||||
assert(index < 32);
|
||||
|
||||
static_cast<PPUThread*>(thread)->GPR[index] = value;
|
||||
|
||||
return *this;
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
#include "Emu/Cell/PPCThread.h"
|
||||
#include "Emu/Memory/vm.h"
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -470,9 +471,6 @@ struct FPRdouble
|
|||
|
||||
class PPUThread : public PPCThread
|
||||
{
|
||||
public:
|
||||
u32 owned_mutexes;
|
||||
|
||||
public:
|
||||
PPCdouble FPR[32]; //Floating Point Register
|
||||
FPSCRhdr FPSCR; //Floating Point Status and Control Register
|
||||
|
@ -533,11 +531,8 @@ public:
|
|||
u64 LR; //SPR 0x008 : Link Register
|
||||
u64 CTR; //SPR 0x009 : Count Register
|
||||
|
||||
union
|
||||
{
|
||||
u64 USPRG0; //SPR 0x100 : User-SPR General-Purpose Register 0
|
||||
u64 SPRG[8]; //SPR 0x100 - 0x107 : SPR General-Purpose Registers
|
||||
};
|
||||
u64 USPRG[8]; //SPR 0x100 - 0x107: User-SPR General-Purpose Registers
|
||||
u64 SPRG[8]; //SPR 0x110 - 0x117 : SPR General-Purpose Registers
|
||||
|
||||
//TBR : Time-Base Registers
|
||||
union
|
||||
|
@ -556,6 +551,9 @@ public:
|
|||
u64 R_ADDR; // reservation address
|
||||
u64 R_VALUE; // reservation value (BE)
|
||||
|
||||
u32 owned_mutexes;
|
||||
std::function<void(PPUThread& CPU)> custom_task;
|
||||
|
||||
public:
|
||||
PPUThread();
|
||||
virtual ~PPUThread();
|
||||
|
@ -785,25 +783,32 @@ public:
|
|||
|
||||
public:
|
||||
virtual void InitRegs();
|
||||
virtual void Task();
|
||||
u64 GetStackArg(s32 i);
|
||||
u64 FastCall2(u32 addr, u32 rtoc);
|
||||
void FastStop();
|
||||
|
||||
virtual void DoReset() override;
|
||||
virtual void DoRun() override;
|
||||
|
||||
protected:
|
||||
virtual void DoReset() override;
|
||||
virtual void DoPause() override;
|
||||
virtual void DoResume() override;
|
||||
virtual void DoStop() override;
|
||||
|
||||
protected:
|
||||
virtual void Step() override
|
||||
{
|
||||
//if(++cycle > 20)
|
||||
{
|
||||
TB++;
|
||||
//cycle = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
PPUThread& GetCurrentPPUThread();
|
||||
|
||||
class ppu_thread : cpu_thread
|
||||
{
|
||||
static const u32 stack_align = 0x10;
|
||||
vm::ptr<u64> argv;
|
||||
u32 argc;
|
||||
vm::ptr<u64> envp;
|
||||
|
||||
public:
|
||||
ppu_thread(u32 entry, const std::string& name = "", u32 stack_size = 0, u32 prio = 0);
|
||||
|
||||
cpu_thread& args(std::initializer_list<std::string> values) override;
|
||||
cpu_thread& run() override;
|
||||
ppu_thread& gpr(uint index, u64 value);
|
||||
};
|
|
@ -190,7 +190,7 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value)
|
|||
|
||||
void RawSPUThread::InitRegs()
|
||||
{
|
||||
dmac.ls_offset = m_offset = (u32)GetStartAddr() + RAW_SPU_LS_OFFSET;
|
||||
ls_offset = m_offset = (u32)GetStartAddr() + RAW_SPU_LS_OFFSET;
|
||||
SPUThread::InitRegs();
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#define UNIMPLEMENTED() UNK(__FUNCTION__)
|
||||
|
||||
#define MEM_AND_REG_HASH() \
|
||||
unsigned char mem_h[20]; sha1(vm::get_ptr<u8>(CPU.dmac.ls_offset), 256*1024, mem_h); \
|
||||
unsigned char mem_h[20]; sha1(vm::get_ptr<u8>(CPU.ls_offset), 256*1024, mem_h); \
|
||||
unsigned char reg_h[20]; sha1((const unsigned char*)CPU.GPR, sizeof(CPU.GPR), reg_h); \
|
||||
LOG_NOTICE(Log::SPU, "Mem hash: 0x%llx, reg hash: 0x%llx", *(u64*)mem_h, *(u64*)reg_h);
|
||||
|
||||
|
@ -251,10 +251,12 @@ private:
|
|||
}
|
||||
void BIZ(u32 intr, u32 rt, u32 ra)
|
||||
{
|
||||
if (intr)
|
||||
switch (intr)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return;
|
||||
case 0: break;
|
||||
case 0x10: break; // enable interrupts
|
||||
case 0x20: break; // disable interrupts
|
||||
default: UNIMPLEMENTED(); return;
|
||||
}
|
||||
|
||||
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
|
||||
|
@ -270,10 +272,12 @@ private:
|
|||
}
|
||||
void BINZ(u32 intr, u32 rt, u32 ra)
|
||||
{
|
||||
if (intr)
|
||||
switch (intr)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return;
|
||||
case 0: break;
|
||||
case 0x10: break; // enable interrupts
|
||||
case 0x20: break; // disable interrupts
|
||||
default: UNIMPLEMENTED(); return;
|
||||
}
|
||||
|
||||
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
|
||||
|
@ -289,10 +293,12 @@ private:
|
|||
}
|
||||
void BIHZ(u32 intr, u32 rt, u32 ra)
|
||||
{
|
||||
if (intr)
|
||||
switch (intr)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return;
|
||||
case 0: break;
|
||||
case 0x10: break; // enable interrupts
|
||||
case 0x20: break; // disable interrupts
|
||||
default: UNIMPLEMENTED(); return;
|
||||
}
|
||||
|
||||
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
|
||||
|
@ -308,10 +314,12 @@ private:
|
|||
}
|
||||
void BIHNZ(u32 intr, u32 rt, u32 ra)
|
||||
{
|
||||
if (intr)
|
||||
switch (intr)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return;
|
||||
case 0: break;
|
||||
case 0x10: break; // enable interrupts
|
||||
case 0x20: break; // disable interrupts
|
||||
default: UNIMPLEMENTED(); return;
|
||||
}
|
||||
|
||||
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
|
||||
|
@ -337,10 +345,12 @@ private:
|
|||
}
|
||||
void BI(u32 intr, u32 ra)
|
||||
{
|
||||
if (intr)
|
||||
switch (intr)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return;
|
||||
case 0: break;
|
||||
case 0x10: break; // enable interrupts
|
||||
case 0x20: break; // disable interrupts
|
||||
default: UNIMPLEMENTED(); return;
|
||||
}
|
||||
|
||||
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
|
||||
|
@ -349,10 +359,12 @@ private:
|
|||
}
|
||||
void BISL(u32 intr, u32 rt, u32 ra)
|
||||
{
|
||||
if (intr)
|
||||
switch (intr)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return;
|
||||
case 0: break;
|
||||
case 0x10: break; // enable interrupts
|
||||
case 0x20: break; // disable interrupts
|
||||
default: UNIMPLEMENTED(); return;
|
||||
}
|
||||
|
||||
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
|
||||
|
@ -432,9 +444,7 @@ private:
|
|||
}
|
||||
void LQX(u32 rt, u32 ra, u32 rb)
|
||||
{
|
||||
u32 a = CPU.GPR[ra]._u32[3], b = CPU.GPR[rb]._u32[3];
|
||||
|
||||
u32 lsa = (a + b) & 0x3fff0;
|
||||
u32 lsa = (CPU.GPR[ra]._u32[3] + CPU.GPR[rb]._u32[3]) & 0x3fff0;
|
||||
|
||||
CPU.GPR[rt] = CPU.ReadLS128(lsa);
|
||||
}
|
||||
|
@ -465,6 +475,12 @@ private:
|
|||
{
|
||||
const u32 t = (CPU.GPR[rb]._u32[3] + CPU.GPR[ra]._u32[3]) & 0xF;
|
||||
|
||||
if (ra == 1 && (CPU.GPR[ra]._u32[3] & 0xF))
|
||||
{
|
||||
LOG_ERROR(SPU, "%s(): SP = 0x%x", __FUNCTION__, CPU.GPR[ra]._u32[3]);
|
||||
Emu.Pause();
|
||||
}
|
||||
|
||||
CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F;
|
||||
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
|
||||
CPU.GPR[rt]._u8[15 - t] = 0x03;
|
||||
|
@ -473,6 +489,12 @@ private:
|
|||
{
|
||||
const u32 t = (CPU.GPR[rb]._u32[3] + CPU.GPR[ra]._u32[3]) & 0xE;
|
||||
|
||||
if (ra == 1 && (CPU.GPR[ra]._u32[3] & 0xF))
|
||||
{
|
||||
LOG_ERROR(SPU, "%s(): SP = 0x%x", __FUNCTION__, CPU.GPR[ra]._u32[3]);
|
||||
Emu.Pause();
|
||||
}
|
||||
|
||||
CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F;
|
||||
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
|
||||
CPU.GPR[rt]._u16[7 - (t >> 1)] = 0x0203;
|
||||
|
@ -481,6 +503,12 @@ private:
|
|||
{
|
||||
const u32 t = (CPU.GPR[ra]._u32[3] + CPU.GPR[rb]._u32[3]) & 0xC;
|
||||
|
||||
if (ra == 1 && (CPU.GPR[ra]._u32[3] & 0xF))
|
||||
{
|
||||
LOG_ERROR(SPU, "%s(): SP = 0x%x", __FUNCTION__, CPU.GPR[ra]._u32[3]);
|
||||
Emu.Pause();
|
||||
}
|
||||
|
||||
CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F;
|
||||
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
|
||||
CPU.GPR[rt]._u32[3 - (t >> 2)] = 0x00010203;
|
||||
|
@ -489,6 +517,12 @@ private:
|
|||
{
|
||||
const u32 t = (CPU.GPR[rb]._u32[3] + CPU.GPR[ra]._u32[3]) & 0x8;
|
||||
|
||||
if (ra == 1 && (CPU.GPR[ra]._u32[3] & 0xF))
|
||||
{
|
||||
LOG_ERROR(SPU, "%s(): SP = 0x%x", __FUNCTION__, CPU.GPR[ra]._u32[3]);
|
||||
Emu.Pause();
|
||||
}
|
||||
|
||||
CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F;
|
||||
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
|
||||
CPU.GPR[rt]._u64[1 - (t >> 3)] = (u64)0x0001020304050607;
|
||||
|
@ -574,6 +608,12 @@ private:
|
|||
{
|
||||
const int t = (CPU.GPR[ra]._u32[3] + i7) & 0xF;
|
||||
|
||||
if (ra == 1 && (CPU.GPR[ra]._u32[3] & 0xF))
|
||||
{
|
||||
LOG_ERROR(SPU, "%s(): SP = 0x%x", __FUNCTION__, CPU.GPR[ra]._u32[3]);
|
||||
Emu.Pause();
|
||||
}
|
||||
|
||||
CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F;
|
||||
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
|
||||
CPU.GPR[rt]._u8[15 - t] = 0x03;
|
||||
|
@ -582,6 +622,12 @@ private:
|
|||
{
|
||||
const int t = (CPU.GPR[ra]._u32[3] + i7) & 0xE;
|
||||
|
||||
if (ra == 1 && (CPU.GPR[ra]._u32[3] & 0xF))
|
||||
{
|
||||
LOG_ERROR(SPU, "%s(): SP = 0x%x", __FUNCTION__, CPU.GPR[ra]._u32[3]);
|
||||
Emu.Pause();
|
||||
}
|
||||
|
||||
CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F;
|
||||
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
|
||||
CPU.GPR[rt]._u16[7 - (t >> 1)] = 0x0203;
|
||||
|
@ -590,6 +636,12 @@ private:
|
|||
{
|
||||
const int t = (CPU.GPR[ra]._u32[3] + i7) & 0xC;
|
||||
|
||||
if (ra == 1 && (CPU.GPR[ra]._u32[3] & 0xF))
|
||||
{
|
||||
LOG_ERROR(SPU, "%s(): SP = 0x%x", __FUNCTION__, CPU.GPR[ra]._u32[3]);
|
||||
Emu.Pause();
|
||||
}
|
||||
|
||||
CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F;
|
||||
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
|
||||
CPU.GPR[rt]._u32[3 - (t >> 2)] = 0x00010203;
|
||||
|
@ -598,6 +650,12 @@ private:
|
|||
{
|
||||
const int t = (CPU.GPR[ra]._u32[3] + i7) & 0x8;
|
||||
|
||||
if (ra == 1 && (CPU.GPR[ra]._u32[3] & 0xF))
|
||||
{
|
||||
LOG_ERROR(SPU, "%s(): SP = 0x%x", __FUNCTION__, CPU.GPR[ra]._u32[3]);
|
||||
Emu.Pause();
|
||||
}
|
||||
|
||||
CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F;
|
||||
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
|
||||
CPU.GPR[rt]._u64[1 - (t >> 3)] = (u64)0x0001020304050607;
|
||||
|
@ -1088,6 +1146,7 @@ private:
|
|||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
CPU.GPR[rt]._f[i] = (float)CPU.GPR[ra]._u32[i];
|
||||
|
||||
u32 exp = ((CPU.GPR[rt]._u32[i] >> 23) & 0xff) - scale;
|
||||
|
||||
if (exp > 255) //< 0
|
||||
|
|
|
@ -9,64 +9,6 @@ using namespace asmjit::host;
|
|||
|
||||
#define UNIMPLEMENTED() UNK(__FUNCTION__)
|
||||
|
||||
#define mmToU64Ptr(x) ((u64*)(&x))
|
||||
#define mmToU32Ptr(x) ((u32*)(&x))
|
||||
#define mmToU16Ptr(x) ((u16*)(&x))
|
||||
#define mmToU8Ptr(x) ((u8*)(&x))
|
||||
|
||||
struct g_imm_table_struct
|
||||
{
|
||||
//u16 cntb_table[65536];
|
||||
|
||||
__m128i fsmb_table[65536];
|
||||
__m128i fsmh_table[256];
|
||||
__m128i fsm_table[16];
|
||||
|
||||
__m128i sldq_pshufb[32];
|
||||
__m128i srdq_pshufb[32];
|
||||
__m128i rldq_pshufb[16];
|
||||
|
||||
g_imm_table_struct()
|
||||
{
|
||||
/*static_assert(offsetof(g_imm_table_struct, cntb_table) == 0, "offsetof(cntb_table) != 0");
|
||||
for (u32 i = 0; i < sizeof(cntb_table) / sizeof(cntb_table[0]); i++)
|
||||
{
|
||||
u32 cnt_low = 0, cnt_high = 0;
|
||||
for (u32 j = 0; j < 8; j++)
|
||||
{
|
||||
cnt_low += (i >> j) & 1;
|
||||
cnt_high += (i >> (j + 8)) & 1;
|
||||
}
|
||||
cntb_table[i] = (cnt_high << 8) | cnt_low;
|
||||
}*/
|
||||
for (u32 i = 0; i < sizeof(fsm_table) / sizeof(fsm_table[0]); i++)
|
||||
{
|
||||
|
||||
for (u32 j = 0; j < 4; j++) mmToU32Ptr(fsm_table[i])[j] = (i & (1 << j)) ? ~0 : 0;
|
||||
}
|
||||
for (u32 i = 0; i < sizeof(fsmh_table) / sizeof(fsmh_table[0]); i++)
|
||||
{
|
||||
for (u32 j = 0; j < 8; j++) mmToU16Ptr(fsmh_table[i])[j] = (i & (1 << j)) ? ~0 : 0;
|
||||
}
|
||||
for (u32 i = 0; i < sizeof(fsmb_table) / sizeof(fsmb_table[0]); i++)
|
||||
{
|
||||
for (u32 j = 0; j < 16; j++) mmToU8Ptr(fsmb_table[i])[j] = (i & (1 << j)) ? ~0 : 0;
|
||||
}
|
||||
for (u32 i = 0; i < sizeof(sldq_pshufb) / sizeof(sldq_pshufb[0]); i++)
|
||||
{
|
||||
for (u32 j = 0; j < 16; j++) mmToU8Ptr(sldq_pshufb[i])[j] = (u8)(j - i);
|
||||
}
|
||||
for (u32 i = 0; i < sizeof(srdq_pshufb) / sizeof(srdq_pshufb[0]); i++)
|
||||
{
|
||||
for (u32 j = 0; j < 16; j++) mmToU8Ptr(srdq_pshufb[i])[j] = (j + i > 15) ? 0xff : (u8)(j + i);
|
||||
}
|
||||
for (u32 i = 0; i < sizeof(rldq_pshufb) / sizeof(rldq_pshufb[0]); i++)
|
||||
{
|
||||
for (u32 j = 0; j < 16; j++) mmToU8Ptr(rldq_pshufb[i])[j] = (u8)(j - i) & 0xf;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class SPURecompiler;
|
||||
|
||||
class SPURecompilerCore : public CPUDecoder
|
||||
|
@ -78,6 +20,7 @@ public:
|
|||
SPUInterpreter* inter;
|
||||
JitRuntime runtime;
|
||||
bool first;
|
||||
bool need_check;
|
||||
|
||||
struct SPURecEntry
|
||||
{
|
||||
|
@ -457,7 +400,7 @@ private:
|
|||
c.mov(cpu_dword(PC), CPU.PC);
|
||||
// This instruction must be used following a store instruction that modifies the instruction stream.
|
||||
c.mfence();
|
||||
c.mov(*pos_var, (CPU.PC >> 2) + 1);
|
||||
c.mov(*pos_var, (CPU.PC >> 2) + 1 + 0x2000000);
|
||||
do_finalize = true;
|
||||
LOG_OPCODE();
|
||||
}
|
||||
|
@ -688,7 +631,7 @@ private:
|
|||
}
|
||||
LOG_OPCODE();
|
||||
}
|
||||
void ROTH(u32 rt, u32 ra, u32 rb)
|
||||
void ROTH(u32 rt, u32 ra, u32 rb) //nf
|
||||
{
|
||||
XmmInvalidate(rt);
|
||||
for (u32 i = 0; i < 8; i++)
|
||||
|
@ -1131,10 +1074,12 @@ private:
|
|||
}
|
||||
void BIZ(u32 intr, u32 rt, u32 ra)
|
||||
{
|
||||
if (intr)
|
||||
switch (intr)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return;
|
||||
case 0: break;
|
||||
case 0x10: break; // enable interrupts
|
||||
case 0x20: break; // disable interrupts
|
||||
default: UNIMPLEMENTED(); return;
|
||||
}
|
||||
|
||||
c.mov(cpu_dword(PC), CPU.PC);
|
||||
|
@ -1142,6 +1087,7 @@ private:
|
|||
|
||||
c.mov(*addr, CPU.PC + 4);
|
||||
c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3]));
|
||||
if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR)
|
||||
c.cmp(cpu_dword(GPR[rt]._u32[3]), 0);
|
||||
c.cmovne(*pos_var, *addr);
|
||||
c.shr(*pos_var, 2);
|
||||
|
@ -1149,10 +1095,12 @@ private:
|
|||
}
|
||||
void BINZ(u32 intr, u32 rt, u32 ra)
|
||||
{
|
||||
if (intr)
|
||||
switch (intr)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return;
|
||||
case 0: break;
|
||||
case 0x10: break; // enable interrupts
|
||||
case 0x20: break; // disable interrupts
|
||||
default: UNIMPLEMENTED(); return;
|
||||
}
|
||||
|
||||
c.mov(cpu_dword(PC), CPU.PC);
|
||||
|
@ -1160,6 +1108,7 @@ private:
|
|||
|
||||
c.mov(*addr, CPU.PC + 4);
|
||||
c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3]));
|
||||
if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR)
|
||||
c.cmp(cpu_dword(GPR[rt]._u32[3]), 0);
|
||||
c.cmove(*pos_var, *addr);
|
||||
c.shr(*pos_var, 2);
|
||||
|
@ -1167,10 +1116,12 @@ private:
|
|||
}
|
||||
void BIHZ(u32 intr, u32 rt, u32 ra)
|
||||
{
|
||||
if (intr)
|
||||
switch (intr)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return;
|
||||
case 0: break;
|
||||
case 0x10: break; // enable interrupts
|
||||
case 0x20: break; // disable interrupts
|
||||
default: UNIMPLEMENTED(); return;
|
||||
}
|
||||
|
||||
c.mov(cpu_dword(PC), CPU.PC);
|
||||
|
@ -1178,6 +1129,7 @@ private:
|
|||
|
||||
c.mov(*addr, CPU.PC + 4);
|
||||
c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3]));
|
||||
if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR)
|
||||
c.cmp(cpu_word(GPR[rt]._u16[6]), 0);
|
||||
c.cmovne(*pos_var, *addr);
|
||||
c.shr(*pos_var, 2);
|
||||
|
@ -1185,10 +1137,12 @@ private:
|
|||
}
|
||||
void BIHNZ(u32 intr, u32 rt, u32 ra)
|
||||
{
|
||||
if (intr)
|
||||
switch (intr)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return;
|
||||
case 0: break;
|
||||
case 0x10: break; // enable interrupts
|
||||
case 0x20: break; // disable interrupts
|
||||
default: UNIMPLEMENTED(); return;
|
||||
}
|
||||
|
||||
c.mov(cpu_dword(PC), CPU.PC);
|
||||
|
@ -1196,6 +1150,7 @@ private:
|
|||
|
||||
c.mov(*addr, CPU.PC + 4);
|
||||
c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3]));
|
||||
if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR)
|
||||
c.cmp(cpu_word(GPR[rt]._u16[6]), 0);
|
||||
c.cmove(*pos_var, *addr);
|
||||
c.shr(*pos_var, 2);
|
||||
|
@ -1234,25 +1189,30 @@ private:
|
|||
}
|
||||
void BI(u32 intr, u32 ra)
|
||||
{
|
||||
if (intr)
|
||||
switch (intr)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return;
|
||||
case 0: break;
|
||||
case 0x10: break; // enable interrupts
|
||||
case 0x20: break; // disable interrupts
|
||||
default: UNIMPLEMENTED(); return;
|
||||
}
|
||||
|
||||
c.mov(cpu_dword(PC), CPU.PC);
|
||||
do_finalize = true;
|
||||
|
||||
c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3]));
|
||||
if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR)
|
||||
c.shr(*pos_var, 2);
|
||||
LOG_OPCODE();
|
||||
}
|
||||
void BISL(u32 intr, u32 rt, u32 ra)
|
||||
{
|
||||
if (intr)
|
||||
switch (intr)
|
||||
{
|
||||
UNIMPLEMENTED();
|
||||
return;
|
||||
case 0: break;
|
||||
case 0x10: break; // enable interrupts
|
||||
case 0x20: break; // disable interrupts
|
||||
default: UNIMPLEMENTED(); return;
|
||||
}
|
||||
|
||||
XmmInvalidate(rt);
|
||||
|
@ -1267,6 +1227,7 @@ private:
|
|||
c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3]));
|
||||
c.mov(cpu_dword(GPR[rt]._u32[3]), CPU.PC + 4);
|
||||
c.shr(*pos_var, 2);
|
||||
c.or_(*pos_var, 0x2000000);
|
||||
LOG_OPCODE();
|
||||
}
|
||||
void IRET(u32 ra)
|
||||
|
@ -1423,18 +1384,21 @@ private:
|
|||
}
|
||||
void CBX(u32 rt, u32 ra, u32 rb)
|
||||
{
|
||||
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
|
||||
if (ra == rb)
|
||||
c.mov(*addr, cpu_dword(GPR[rb]._u32[3]));
|
||||
if (ra == 1)
|
||||
{
|
||||
// assuming that SP % 16 is always zero
|
||||
}
|
||||
else if (ra == rb)
|
||||
{
|
||||
c.add(*addr, *addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
c.add(*addr, cpu_dword(GPR[rb]._u32[3]));
|
||||
c.add(*addr, cpu_dword(GPR[ra]._u32[3]));
|
||||
}
|
||||
c.not_(*addr);
|
||||
c.and_(*addr, 0xf);
|
||||
c.neg(*addr);
|
||||
c.add(*addr, 0xf);
|
||||
const XmmLink& vr = XmmAlloc(rt);
|
||||
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
|
||||
XmmFinalize(vr, rt);
|
||||
|
@ -1444,18 +1408,21 @@ private:
|
|||
}
|
||||
void CHX(u32 rt, u32 ra, u32 rb)
|
||||
{
|
||||
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
|
||||
if (ra == rb)
|
||||
c.mov(*addr, cpu_dword(GPR[rb]._u32[3]));
|
||||
if (ra == 1)
|
||||
{
|
||||
// assuming that SP % 16 is always zero
|
||||
}
|
||||
else if (ra == rb)
|
||||
{
|
||||
c.add(*addr, *addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
c.add(*addr, cpu_dword(GPR[rb]._u32[3]));
|
||||
c.add(*addr, cpu_dword(GPR[ra]._u32[3]));
|
||||
}
|
||||
c.not_(*addr);
|
||||
c.and_(*addr, 0xe);
|
||||
c.neg(*addr);
|
||||
c.add(*addr, 0xe);
|
||||
const XmmLink& vr = XmmAlloc(rt);
|
||||
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
|
||||
XmmFinalize(vr, rt);
|
||||
|
@ -1465,18 +1432,21 @@ private:
|
|||
}
|
||||
void CWX(u32 rt, u32 ra, u32 rb)
|
||||
{
|
||||
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
|
||||
if (ra == rb)
|
||||
c.mov(*addr, cpu_dword(GPR[rb]._u32[3]));
|
||||
if (ra == 1)
|
||||
{
|
||||
// assuming that SP % 16 is always zero
|
||||
}
|
||||
else if (ra == rb)
|
||||
{
|
||||
c.add(*addr, *addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
c.add(*addr, cpu_dword(GPR[rb]._u32[3]));
|
||||
c.add(*addr, cpu_dword(GPR[ra]._u32[3]));
|
||||
}
|
||||
c.not_(*addr);
|
||||
c.and_(*addr, 0xc);
|
||||
c.neg(*addr);
|
||||
c.add(*addr, 0xc);
|
||||
const XmmLink& vr = XmmAlloc(rt);
|
||||
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
|
||||
XmmFinalize(vr, rt);
|
||||
|
@ -1486,18 +1456,21 @@ private:
|
|||
}
|
||||
void CDX(u32 rt, u32 ra, u32 rb)
|
||||
{
|
||||
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
|
||||
if (ra == rb)
|
||||
c.mov(*addr, cpu_dword(GPR[rb]._u32[3]));
|
||||
if (ra == 1)
|
||||
{
|
||||
// assuming that SP % 16 is always zero
|
||||
}
|
||||
else if (ra == rb)
|
||||
{
|
||||
c.add(*addr, *addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
c.add(*addr, cpu_dword(GPR[rb]._u32[3]));
|
||||
c.add(*addr, cpu_dword(GPR[ra]._u32[3]));
|
||||
}
|
||||
c.not_(*addr);
|
||||
c.and_(*addr, 0x8);
|
||||
c.neg(*addr);
|
||||
c.add(*addr, 0x8);
|
||||
const XmmLink& vr = XmmAlloc(rt);
|
||||
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
|
||||
XmmFinalize(vr, rt);
|
||||
|
@ -1593,60 +1566,104 @@ private:
|
|||
LOG_OPCODE();
|
||||
}
|
||||
void CBD(u32 rt, u32 ra, s32 i7)
|
||||
{
|
||||
if (ra == 1)
|
||||
{
|
||||
// assuming that SP % 16 is always zero
|
||||
const XmmLink& vr = XmmAlloc(rt);
|
||||
u128 value = u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f));
|
||||
value.u8r[i7 & 0xf] = 0x03;
|
||||
c.movdqa(vr.get(), XmmConst(value.vi));
|
||||
XmmFinalize(vr, rt);
|
||||
}
|
||||
else
|
||||
{
|
||||
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
|
||||
c.add(*addr, i7);
|
||||
c.not_(*addr);
|
||||
c.and_(*addr, 0xf);
|
||||
c.neg(*addr);
|
||||
c.add(*addr, 0xf);
|
||||
const XmmLink& vr = XmmAlloc(rt);
|
||||
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
|
||||
XmmFinalize(vr, rt);
|
||||
XmmInvalidate(rt);
|
||||
c.mov(byte_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u8[0])), 0x03);
|
||||
}
|
||||
LOG_OPCODE();
|
||||
}
|
||||
void CHD(u32 rt, u32 ra, s32 i7)
|
||||
{
|
||||
if (ra == 1)
|
||||
{
|
||||
// assuming that SP % 16 is always zero
|
||||
const XmmLink& vr = XmmAlloc(rt);
|
||||
u128 value = u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f));
|
||||
value.u16r[(i7 >> 1) & 0x7] = 0x0203;
|
||||
c.movdqa(vr.get(), XmmConst(value.vi));
|
||||
XmmFinalize(vr, rt);
|
||||
}
|
||||
else
|
||||
{
|
||||
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
|
||||
c.add(*addr, i7);
|
||||
c.not_(*addr);
|
||||
c.and_(*addr, 0xe);
|
||||
c.neg(*addr);
|
||||
c.add(*addr, 0xe);
|
||||
const XmmLink& vr = XmmAlloc(rt);
|
||||
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
|
||||
XmmFinalize(vr, rt);
|
||||
XmmInvalidate(rt);
|
||||
c.mov(word_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u16[0])), 0x0203);
|
||||
}
|
||||
LOG_OPCODE();
|
||||
}
|
||||
void CWD(u32 rt, u32 ra, s32 i7)
|
||||
{
|
||||
if (ra == 1)
|
||||
{
|
||||
// assuming that SP % 16 is always zero
|
||||
const XmmLink& vr = XmmAlloc(rt);
|
||||
u128 value = u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f));
|
||||
value.u32r[(i7 >> 2) & 0x3] = 0x00010203;
|
||||
c.movdqa(vr.get(), XmmConst(value.vi));
|
||||
XmmFinalize(vr, rt);
|
||||
}
|
||||
else
|
||||
{
|
||||
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
|
||||
c.add(*addr, i7);
|
||||
c.not_(*addr);
|
||||
c.and_(*addr, 0xc);
|
||||
c.neg(*addr);
|
||||
c.add(*addr, 0xc);
|
||||
const XmmLink& vr = XmmAlloc(rt);
|
||||
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
|
||||
XmmFinalize(vr, rt);
|
||||
XmmInvalidate(rt);
|
||||
c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[0])), 0x00010203);
|
||||
}
|
||||
LOG_OPCODE();
|
||||
}
|
||||
void CDD(u32 rt, u32 ra, s32 i7)
|
||||
{
|
||||
if (ra == 1)
|
||||
{
|
||||
// assuming that SP % 16 is always zero
|
||||
const XmmLink& vr = XmmAlloc(rt);
|
||||
u128 value = u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f));
|
||||
value.u64r[(i7 >> 3) & 0x1] = 0x0001020304050607ull;
|
||||
c.movdqa(vr.get(), XmmConst(value.vi));
|
||||
XmmFinalize(vr, rt);
|
||||
}
|
||||
else
|
||||
{
|
||||
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
|
||||
c.add(*addr, i7);
|
||||
c.not_(*addr);
|
||||
c.and_(*addr, 0x8);
|
||||
c.neg(*addr);
|
||||
c.add(*addr, 0x8);
|
||||
const XmmLink& vr = XmmAlloc(rt);
|
||||
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
|
||||
XmmFinalize(vr, rt);
|
||||
XmmInvalidate(rt);
|
||||
c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[0])), 0x04050607);
|
||||
c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[1])), 0x00010203);
|
||||
}
|
||||
LOG_OPCODE();
|
||||
}
|
||||
void ROTQBII(u32 rt, u32 ra, s32 i7)
|
||||
|
@ -1947,23 +1964,22 @@ private:
|
|||
{
|
||||
c.mov(*addr, cpu_dword(GPR[ra]._s32[3]));
|
||||
c.cmp(*addr, cpu_dword(GPR[rb]._s32[3]));
|
||||
c.mov(*addr, 0);
|
||||
c.setg(addr->r8());
|
||||
c.neg(*addr);
|
||||
c.shl(*addr, 24);
|
||||
c.mov(*pos_var, (CPU.PC >> 2) + 1);
|
||||
c.xor_(*pos_var, *addr);
|
||||
c.or_(*pos_var, *addr);
|
||||
do_finalize = true;
|
||||
LOG_OPCODE();
|
||||
}
|
||||
void CLZ(u32 rt, u32 ra)
|
||||
{
|
||||
XmmInvalidate(rt);
|
||||
c.mov(*qw0, 32 + 31);
|
||||
for (u32 i = 0; i < 4; i++)
|
||||
{
|
||||
c.bsr(*addr, cpu_dword(GPR[ra]._u32[i]));
|
||||
c.cmovz(*addr, dword_ptr(*g_imm_var, (s32)offsetof(g_imm_table_struct, fsmb_table[0xffff]))); // load 0xffffffff
|
||||
c.neg(*addr);
|
||||
c.add(*addr, 31);
|
||||
c.cmovz(*addr, qw0->r32());
|
||||
c.xor_(*addr, 31);
|
||||
c.mov(cpu_dword(GPR[rt]._u32[i]), *addr);
|
||||
}
|
||||
LOG_OPCODE();
|
||||
|
@ -2308,11 +2324,10 @@ private:
|
|||
{
|
||||
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
|
||||
c.cmp(*addr, cpu_dword(GPR[rb]._u32[3]));
|
||||
c.mov(*addr, 0);
|
||||
c.seta(addr->r8());
|
||||
c.neg(*addr);
|
||||
c.shl(*addr, 24);
|
||||
c.mov(*pos_var, (CPU.PC >> 2) + 1);
|
||||
c.xor_(*pos_var, *addr);
|
||||
c.or_(*pos_var, *addr);
|
||||
do_finalize = true;
|
||||
LOG_OPCODE();
|
||||
}
|
||||
|
@ -2662,11 +2677,10 @@ private:
|
|||
{
|
||||
c.mov(*addr, cpu_dword(GPR[ra]._s32[3]));
|
||||
c.cmp(*addr, cpu_dword(GPR[rb]._s32[3]));
|
||||
c.mov(*addr, 0);
|
||||
c.sete(addr->r8());
|
||||
c.neg(*addr);
|
||||
c.shl(*addr, 24);
|
||||
c.mov(*pos_var, (CPU.PC >> 2) + 1);
|
||||
c.xor_(*pos_var, *addr);
|
||||
c.or_(*pos_var, *addr);
|
||||
do_finalize = true;
|
||||
LOG_OPCODE();
|
||||
}
|
||||
|
@ -3324,11 +3338,10 @@ private:
|
|||
{
|
||||
c.mov(*addr, cpu_dword(GPR[ra]._s32[3]));
|
||||
c.cmp(*addr, i10);
|
||||
c.mov(*addr, 0);
|
||||
c.setg(addr->r8());
|
||||
c.neg(*addr);
|
||||
c.shl(*addr, 24);
|
||||
c.mov(*pos_var, (CPU.PC >> 2) + 1);
|
||||
c.xor_(*pos_var, *addr);
|
||||
c.or_(*pos_var, *addr);
|
||||
do_finalize = true;
|
||||
LOG_OPCODE();
|
||||
}
|
||||
|
@ -3390,11 +3403,10 @@ private:
|
|||
{
|
||||
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
|
||||
c.cmp(*addr, i10);
|
||||
c.mov(*addr, 0);
|
||||
c.seta(addr->r8());
|
||||
c.neg(*addr);
|
||||
c.shl(*addr, 24);
|
||||
c.mov(*pos_var, (CPU.PC >> 2) + 1);
|
||||
c.xor_(*pos_var, *addr);
|
||||
c.or_(*pos_var, *addr);
|
||||
do_finalize = true;
|
||||
LOG_OPCODE();
|
||||
}
|
||||
|
@ -3441,11 +3453,10 @@ private:
|
|||
{
|
||||
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
|
||||
c.cmp(*addr, i10);
|
||||
c.mov(*addr, 0);
|
||||
c.sete(addr->r8());
|
||||
c.neg(*addr);
|
||||
c.shl(*addr, 24);
|
||||
c.mov(*pos_var, (CPU.PC >> 2) + 1);
|
||||
c.xor_(*pos_var, *addr);
|
||||
c.or_(*pos_var, *addr);
|
||||
do_finalize = true;
|
||||
LOG_OPCODE();
|
||||
}
|
||||
|
@ -3517,6 +3528,16 @@ private:
|
|||
}
|
||||
WRAPPER_END(rc, rt, ra, rb);*/
|
||||
|
||||
// hypothetical AVX-512 implementation:
|
||||
// VPXORD mask, rc, [byte:0x0f] // 15 - rc (only for index bits)
|
||||
// VPSHUFB res {k0}, ra, mask
|
||||
// VPTESTMB k1 {k0}, rc, [byte:0x10]
|
||||
// VPSHUFB res {k1}, rb, mask
|
||||
// VPCMPNLTUB k1 {k0}, mask, [byte:0xc0]
|
||||
// VPADDB res {k1}, res, [byte:0xff]
|
||||
// VPCMPNLTUB k1 {k1}, mask, [byte:0xe0]
|
||||
// VPSUBB res {k1}, res, [byte:0x7f]
|
||||
|
||||
const XmmLink& v0 = XmmGet(rc); // v0 = mask
|
||||
const XmmLink& v1 = XmmAlloc();
|
||||
const XmmLink& v2 = XmmCopy(v0); // v2 = mask
|
||||
|
|
|
@ -13,13 +13,14 @@
|
|||
#include "SPUInterpreter.h"
|
||||
#include "SPURecompiler.h"
|
||||
|
||||
static const g_imm_table_struct g_imm_table;
|
||||
const g_imm_table_struct g_imm_table;
|
||||
|
||||
SPURecompilerCore::SPURecompilerCore(SPUThread& cpu)
|
||||
: m_enc(new SPURecompiler(cpu, *this))
|
||||
, inter(new SPUInterpreter(cpu))
|
||||
, CPU(cpu)
|
||||
, first(true)
|
||||
, need_check(false)
|
||||
{
|
||||
memset(entry, 0, sizeof(entry));
|
||||
X86CpuInfo inf;
|
||||
|
@ -48,7 +49,7 @@ void SPURecompilerCore::Compile(u16 pos)
|
|||
u64 time0 = 0;
|
||||
|
||||
SPUDisAsm dis_asm(CPUDisAsm_InterpreterMode);
|
||||
dis_asm.offset = vm::get_ptr<u8>(CPU.dmac.ls_offset);
|
||||
dis_asm.offset = vm::get_ptr<u8>(CPU.ls_offset);
|
||||
|
||||
StringLogger stringLogger;
|
||||
stringLogger.setOption(kLoggerOptionBinaryForm, true);
|
||||
|
@ -102,7 +103,7 @@ void SPURecompilerCore::Compile(u16 pos)
|
|||
|
||||
while (true)
|
||||
{
|
||||
const u32 opcode = vm::read32(CPU.dmac.ls_offset + pos * 4);
|
||||
const u32 opcode = vm::read32(CPU.ls_offset + pos * 4);
|
||||
m_enc->do_finalize = false;
|
||||
if (opcode)
|
||||
{
|
||||
|
@ -181,8 +182,8 @@ void SPURecompilerCore::Compile(u16 pos)
|
|||
|
||||
u8 SPURecompilerCore::DecodeMemory(const u32 address)
|
||||
{
|
||||
assert(CPU.dmac.ls_offset == address - CPU.PC);
|
||||
const u32 m_offset = CPU.dmac.ls_offset;
|
||||
assert(CPU.ls_offset == address - CPU.PC);
|
||||
const u32 m_offset = CPU.ls_offset;
|
||||
const u16 pos = (u16)(CPU.PC >> 2);
|
||||
|
||||
//ConLog.Write("DecodeMemory: pos=%d", pos);
|
||||
|
@ -192,20 +193,26 @@ u8 SPURecompilerCore::DecodeMemory(const u32 address)
|
|||
{
|
||||
// check data (hard way)
|
||||
bool is_valid = true;
|
||||
//for (u32 i = pos; i < (u32)(entry[pos].count + pos); i++)
|
||||
//{
|
||||
// if (entry[i].valid != ls[i])
|
||||
// {
|
||||
// is_valid = false;
|
||||
// break;
|
||||
// }
|
||||
//}
|
||||
if (need_check)
|
||||
{
|
||||
for (u32 i = 0; i < 0x10000; i++)
|
||||
{
|
||||
if (entry[i].valid && entry[i].valid != ls[i])
|
||||
{
|
||||
is_valid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
need_check = false;
|
||||
}
|
||||
// invalidate if necessary
|
||||
if (!is_valid)
|
||||
{
|
||||
for (u32 i = 0; i < 0x10000; i++)
|
||||
{
|
||||
if (entry[i].pointer &&
|
||||
if (!entry[i].pointer) continue;
|
||||
|
||||
if (!entry[i].valid || entry[i].valid != ls[i] ||
|
||||
i + (u32)entry[i].count > (u32)pos &&
|
||||
i < (u32)pos + (u32)entry[pos].count)
|
||||
{
|
||||
|
@ -214,6 +221,11 @@ u8 SPURecompilerCore::DecodeMemory(const u32 address)
|
|||
//RtlDeleteFunctionTable(&entry[i].info);
|
||||
#endif
|
||||
entry[i].pointer = nullptr;
|
||||
for (u32 j = i; j < i + (u32)entry[i].count; j++)
|
||||
{
|
||||
entry[j].valid = 0;
|
||||
}
|
||||
//need_check = true;
|
||||
}
|
||||
}
|
||||
//LOG_ERROR(Log::SPU, "SPURecompilerCore::DecodeMemory(ls_addr=0x%x): code has changed", pos * sizeof(u32));
|
||||
|
@ -254,11 +266,17 @@ u8 SPURecompilerCore::DecodeMemory(const u32 address)
|
|||
u32 res = pos;
|
||||
res = func(cpu, vm::get_ptr<void>(m_offset), imm_table.data(), &g_imm_table);
|
||||
|
||||
if (res > 0xffff)
|
||||
if (res & 0x1000000)
|
||||
{
|
||||
CPU.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT);
|
||||
CPU.Stop();
|
||||
res = ~res;
|
||||
res &= ~0x1000000;
|
||||
}
|
||||
|
||||
if (res & 0x2000000)
|
||||
{
|
||||
need_check = true;
|
||||
res &= ~0x2000000;
|
||||
}
|
||||
|
||||
if (did_compile)
|
||||
|
|
|
@ -50,7 +50,15 @@ void SPUThread::Task()
|
|||
const int round = std::fegetround();
|
||||
std::fesetround(FE_TOWARDZERO);
|
||||
|
||||
if (m_custom_task)
|
||||
{
|
||||
m_custom_task(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
CPUThread::Task();
|
||||
}
|
||||
|
||||
if (std::fegetround() != FE_TOWARDZERO)
|
||||
{
|
||||
LOG_ERROR(Log::SPU, "Rounding mode has changed(%d)", std::fegetround());
|
||||
|
@ -68,11 +76,11 @@ void SPUThread::DoReset()
|
|||
|
||||
void SPUThread::InitRegs()
|
||||
{
|
||||
GPR[1]._u32[3] = 0x40000 - 120;
|
||||
GPR[1]._u32[3] = 0x3FFF0; // initial stack frame pointer
|
||||
|
||||
cfg.Reset();
|
||||
|
||||
dmac.ls_offset = m_offset;
|
||||
ls_offset = m_offset;
|
||||
|
||||
SPU.Status.SetValue(SPU_STATUS_STOPPED);
|
||||
|
||||
|
@ -138,6 +146,31 @@ void SPUThread::DoClose()
|
|||
}
|
||||
}
|
||||
|
||||
void SPUThread::FastCall(u32 ls_addr)
|
||||
{
|
||||
// can't be called from another thread (because it doesn't make sense)
|
||||
WriteLS32(0x0, 2);
|
||||
|
||||
auto old_PC = PC;
|
||||
auto old_LR = GPR[0]._u32[3];
|
||||
auto old_stack = GPR[1]._u32[3]; // only saved and restored (may be wrong)
|
||||
|
||||
m_status = Running;
|
||||
PC = ls_addr;
|
||||
GPR[0]._u32[3] = 0x0;
|
||||
|
||||
CPUThread::Task();
|
||||
|
||||
PC = old_PC;
|
||||
GPR[0]._u32[3] = old_LR;
|
||||
GPR[1]._u32[3] = old_stack;
|
||||
}
|
||||
|
||||
void SPUThread::FastStop()
|
||||
{
|
||||
m_status = Stopped;
|
||||
}
|
||||
|
||||
void SPUThread::WriteSNR(bool number, u32 value)
|
||||
{
|
||||
if (cfg.value & ((u64)1 << (u64)number))
|
||||
|
@ -181,11 +214,11 @@ void SPUThread::ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
|
|||
if ((addr <= 0x3ffff) && (addr + size <= 0x40000))
|
||||
{
|
||||
// LS access
|
||||
ea = spu->dmac.ls_offset + addr;
|
||||
ea = spu->ls_offset + addr;
|
||||
}
|
||||
else if ((cmd & MFC_PUT_CMD) && size == 4 && (addr == SYS_SPU_THREAD_SNR1 || addr == SYS_SPU_THREAD_SNR2))
|
||||
{
|
||||
spu->WriteSNR(SYS_SPU_THREAD_SNR2 == addr, vm::read32(dmac.ls_offset + lsa));
|
||||
spu->WriteSNR(SYS_SPU_THREAD_SNR2 == addr, vm::read32(ls_offset + lsa));
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
@ -208,13 +241,13 @@ void SPUThread::ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
|
|||
{
|
||||
case MFC_PUT_CMD:
|
||||
{
|
||||
vm::write32(ea, ReadLS32(lsa));
|
||||
vm::write32((u32)ea, ReadLS32(lsa));
|
||||
return;
|
||||
}
|
||||
|
||||
case MFC_GET_CMD:
|
||||
{
|
||||
WriteLS32(lsa, vm::read32(ea));
|
||||
WriteLS32(lsa, vm::read32((u32)ea));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -231,13 +264,13 @@ void SPUThread::ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
|
|||
{
|
||||
case MFC_PUT_CMD:
|
||||
{
|
||||
memcpy(vm::get_ptr<void>(ea), vm::get_ptr<void>(dmac.ls_offset + lsa), size);
|
||||
memcpy(vm::get_ptr<void>((u32)ea), vm::get_ptr<void>(ls_offset + lsa), size);
|
||||
return;
|
||||
}
|
||||
|
||||
case MFC_GET_CMD:
|
||||
{
|
||||
memcpy(vm::get_ptr<void>(dmac.ls_offset + lsa), vm::get_ptr<void>(ea), size);
|
||||
memcpy(vm::get_ptr<void>(ls_offset + lsa), vm::get_ptr<void>((u32)ea), size);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -269,10 +302,10 @@ void SPUThread::ListCmd(u32 lsa, u64 ea, u16 tag, u16 size, u32 cmd, MFCReg& MFC
|
|||
|
||||
for (u32 i = 0; i < list_size; i++)
|
||||
{
|
||||
auto rec = vm::ptr<list_element>::make(dmac.ls_offset + list_addr + i * 8);
|
||||
auto rec = vm::ptr<list_element>::make(ls_offset + list_addr + i * 8);
|
||||
|
||||
u32 size = rec->ts;
|
||||
if (size < 16 && size != 1 && size != 2 && size != 4 && size != 8)
|
||||
if (!(rec->s.ToBE() & se16(0x8000)) && size < 16 && size != 1 && size != 2 && size != 4 && size != 8)
|
||||
{
|
||||
LOG_ERROR(Log::SPU, "DMA List: invalid transfer size(%d)", size);
|
||||
result = MFC_PPU_DMA_CMD_SEQUENCE_ERROR;
|
||||
|
@ -280,12 +313,15 @@ void SPUThread::ListCmd(u32 lsa, u64 ea, u16 tag, u16 size, u32 cmd, MFCReg& MFC
|
|||
}
|
||||
|
||||
u32 addr = rec->ea;
|
||||
|
||||
if (size)
|
||||
ProcessCmd(cmd, tag, lsa | (addr & 0xf), addr, size);
|
||||
|
||||
if (Ini.HLELogging.GetValue() || rec->s)
|
||||
if (Ini.HLELogging.GetValue() || rec->s.ToBE())
|
||||
LOG_NOTICE(Log::SPU, "*** list element(%d/%d): s = 0x%x, ts = 0x%x, low ea = 0x%x (lsa = 0x%x)",
|
||||
i, list_size, (u16)rec->s, (u16)rec->ts, (u32)rec->ea, lsa | (addr & 0xf));
|
||||
|
||||
if (size)
|
||||
lsa += std::max(size, (u32)16);
|
||||
|
||||
if (rec->s.ToBE() & se16(0x8000))
|
||||
|
@ -366,6 +402,17 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
|
|||
op == MFC_PUTLLUC_CMD ? "PUTLLUC" : "PUTQLLUC"),
|
||||
lsa, ea, tag, size, cmd);
|
||||
|
||||
if ((u32)ea != ea)
|
||||
{
|
||||
LOG_ERROR(Log::SPU, "DMA %s: Invalid external address (0x%llx)",
|
||||
(op == MFC_GETLLAR_CMD ? "GETLLAR" :
|
||||
op == MFC_PUTLLC_CMD ? "PUTLLC" :
|
||||
op == MFC_PUTLLUC_CMD ? "PUTLLUC" : "PUTQLLUC"),
|
||||
ea);
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
|
||||
if (op == MFC_GETLLAR_CMD) // get reservation
|
||||
{
|
||||
if (R_ADDR)
|
||||
|
@ -376,8 +423,8 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
|
|||
R_ADDR = ea;
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
{
|
||||
R_DATA[i] = vm::get_ptr<u64>(R_ADDR)[i];
|
||||
vm::get_ptr<u64>(dmac.ls_offset + lsa)[i] = R_DATA[i];
|
||||
R_DATA[i] = vm::get_ptr<u64>((u32)R_ADDR)[i];
|
||||
vm::get_ptr<u64>(ls_offset + lsa)[i] = R_DATA[i];
|
||||
}
|
||||
MFCArgs.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS);
|
||||
}
|
||||
|
@ -391,12 +438,12 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
|
|||
u64 buf[16];
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
{
|
||||
buf[i] = vm::get_ptr<u64>(dmac.ls_offset + lsa)[i];
|
||||
buf[i] = vm::get_ptr<u64>(ls_offset + lsa)[i];
|
||||
if (buf[i] != R_DATA[i])
|
||||
{
|
||||
changed++;
|
||||
mask |= (0x3 << (i * 2));
|
||||
if (vm::get_ptr<u64>(R_ADDR)[i] != R_DATA[i])
|
||||
if (vm::get_ptr<u64>((u32)R_ADDR)[i] != R_DATA[i])
|
||||
{
|
||||
m_events |= SPU_EVENT_LR;
|
||||
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE);
|
||||
|
@ -410,7 +457,7 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
|
|||
{
|
||||
if (buf[i] != R_DATA[i])
|
||||
{
|
||||
if (InterlockedCompareExchange(&vm::get_ptr<volatile u64>(ea)[i], buf[i], R_DATA[i]) != R_DATA[i])
|
||||
if (InterlockedCompareExchange(&vm::get_ptr<volatile u64>((u32)R_ADDR)[i], buf[i], R_DATA[i]) != R_DATA[i])
|
||||
{
|
||||
m_events |= SPU_EVENT_LR;
|
||||
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE);
|
||||
|
@ -436,8 +483,8 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
|
|||
for (s32 i = (s32)PC; i < (s32)PC + 4 * 7; i += 4)
|
||||
{
|
||||
dis_asm.dump_pc = i;
|
||||
dis_asm.offset = vm::get_ptr<u8>(dmac.ls_offset);
|
||||
const u32 opcode = vm::read32(i + dmac.ls_offset);
|
||||
dis_asm.offset = vm::get_ptr<u8>(ls_offset);
|
||||
const u32 opcode = vm::read32(i + ls_offset);
|
||||
(*SPU_instr::rrr_list)(&dis_asm, opcode);
|
||||
if (i >= 0 && i < 0x40000)
|
||||
{
|
||||
|
@ -454,7 +501,7 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
|
|||
}
|
||||
else // store unconditional
|
||||
{
|
||||
if (R_ADDR)
|
||||
if (R_ADDR) // may be wrong
|
||||
{
|
||||
m_events |= SPU_EVENT_LR;
|
||||
}
|
||||
|
@ -484,7 +531,7 @@ bool SPUThread::CheckEvents()
|
|||
{
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
{
|
||||
if (vm::get_ptr<u64>(R_ADDR)[i] != R_DATA[i])
|
||||
if (vm::get_ptr<u64>((u32)R_ADDR)[i] != R_DATA[i])
|
||||
{
|
||||
m_events |= SPU_EVENT_LR;
|
||||
R_ADDR = 0;
|
||||
|
@ -498,18 +545,20 @@ bool SPUThread::CheckEvents()
|
|||
|
||||
u32 SPUThread::GetChannelCount(u32 ch)
|
||||
{
|
||||
u32 res = 0xdeafbeef;
|
||||
|
||||
switch (ch)
|
||||
{
|
||||
case SPU_WrOutMbox: return SPU.Out_MBox.GetFreeCount();
|
||||
case SPU_WrOutIntrMbox: return SPU.Out_IntrMBox.GetFreeCount();
|
||||
case SPU_RdInMbox: return SPU.In_MBox.GetCount();
|
||||
case MFC_RdTagStat: return MFC1.TagStatus.GetCount();
|
||||
case MFC_RdListStallStat: return StallStat.GetCount();
|
||||
case MFC_WrTagUpdate: return MFC1.TagStatus.GetCount(); // hack
|
||||
case SPU_RdSigNotify1: return SPU.SNR[0].GetCount();
|
||||
case SPU_RdSigNotify2: return SPU.SNR[1].GetCount();
|
||||
case MFC_RdAtomicStat: return MFC1.AtomicStat.GetCount();
|
||||
case SPU_RdEventStat: return CheckEvents() ? 1 : 0;
|
||||
case SPU_WrOutMbox: res = SPU.Out_MBox.GetFreeCount(); break;
|
||||
case SPU_WrOutIntrMbox: res = SPU.Out_IntrMBox.GetFreeCount(); break;
|
||||
case SPU_RdInMbox: res = SPU.In_MBox.GetCount(); break;
|
||||
case MFC_RdTagStat: res = MFC1.TagStatus.GetCount(); break;
|
||||
case MFC_RdListStallStat: res = StallStat.GetCount(); break;
|
||||
case MFC_WrTagUpdate: res = MFC1.TagStatus.GetCount(); break;// hack
|
||||
case SPU_RdSigNotify1: res = SPU.SNR[0].GetCount(); break;
|
||||
case SPU_RdSigNotify2: res = SPU.SNR[1].GetCount(); break;
|
||||
case MFC_RdAtomicStat: res = MFC1.AtomicStat.GetCount(); break;
|
||||
case SPU_RdEventStat: res = CheckEvents() ? 1 : 0; break;
|
||||
|
||||
default:
|
||||
{
|
||||
|
@ -518,12 +567,17 @@ u32 SPUThread::GetChannelCount(u32 ch)
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
//LOG_NOTICE(Log::SPU, "%s(%s) -> 0x%x", __FUNCTION__, spu_ch_name[ch], res);
|
||||
return res;
|
||||
}
|
||||
|
||||
void SPUThread::WriteChannel(u32 ch, const u128& r)
|
||||
{
|
||||
const u32 v = r._u32[3];
|
||||
|
||||
//LOG_NOTICE(Log::SPU, "%s(%s): v=0x%x", __FUNCTION__, spu_ch_name[ch], v);
|
||||
|
||||
switch (ch)
|
||||
{
|
||||
case SPU_WrOutIntrMbox:
|
||||
|
@ -879,14 +933,28 @@ void SPUThread::ReadChannel(u128& r, u32 ch)
|
|||
}
|
||||
|
||||
case SPU_RdSigNotify1:
|
||||
{
|
||||
if (cfg.value & 1)
|
||||
{
|
||||
while (!SPU.SNR[0].Pop_XCHG(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
while (!SPU.SNR[0].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SPU_RdSigNotify2:
|
||||
{
|
||||
if (cfg.value & 2)
|
||||
{
|
||||
while (!SPU.SNR[1].Pop_XCHG(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
while (!SPU.SNR[1].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -936,6 +1004,8 @@ void SPUThread::ReadChannel(u128& r, u32 ch)
|
|||
}
|
||||
|
||||
if (Emu.IsStopped()) LOG_WARNING(Log::SPU, "%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]);
|
||||
|
||||
//LOG_NOTICE(Log::SPU, "%s(%s) -> 0x%x", __FUNCTION__, spu_ch_name[ch], v);
|
||||
}
|
||||
|
||||
void SPUThread::StopAndSignal(u32 code)
|
||||
|
@ -945,6 +1015,24 @@ void SPUThread::StopAndSignal(u32 code)
|
|||
|
||||
switch (code)
|
||||
{
|
||||
case 0x001:
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x002:
|
||||
{
|
||||
FastStop();
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x003:
|
||||
{
|
||||
GPR[3]._u64[1] = m_code3_func(*this);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x110:
|
||||
{
|
||||
/* ===== sys_spu_thread_receive_event ===== */
|
||||
|
@ -1075,7 +1163,6 @@ void SPUThread::StopAndSignal(u32 code)
|
|||
}
|
||||
|
||||
default:
|
||||
{
|
||||
if (!SPU.Out_MBox.GetCount())
|
||||
{
|
||||
LOG_ERROR(Log::SPU, "Unknown STOP code: 0x%x (no message)", code);
|
||||
|
@ -1084,8 +1171,19 @@ void SPUThread::StopAndSignal(u32 code)
|
|||
{
|
||||
LOG_ERROR(Log::SPU, "Unknown STOP code: 0x%x (message=0x%x)", code, SPU.Out_MBox.GetValue());
|
||||
}
|
||||
Stop();
|
||||
Emu.Pause();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spu_thread::spu_thread(u32 entry, const std::string& name, u32 stack_size, u32 prio)
|
||||
{
|
||||
thread = &Emu.GetCPU().AddThread(CPU_THREAD_SPU);
|
||||
|
||||
thread->SetName(name);
|
||||
thread->SetEntry(entry);
|
||||
thread->SetStackSize(stack_size ? stack_size : Emu.GetInfo().GetProcParam().primary_stacksize);
|
||||
thread->SetPrio(prio ? prio : Emu.GetInfo().GetProcParam().primary_prio);
|
||||
|
||||
argc = 0;
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
#pragma once
|
||||
#include "Emu/Memory/atomic_type.h"
|
||||
#include "PPCThread.h"
|
||||
#include "Emu/Event.h"
|
||||
#include "MFC.h"
|
||||
|
@ -104,6 +105,66 @@ enum
|
|||
SPU_RdSigNotify2_offs = 0x1C00C,
|
||||
};
|
||||
|
||||
#define mmToU64Ptr(x) ((u64*)(&x))
|
||||
#define mmToU32Ptr(x) ((u32*)(&x))
|
||||
#define mmToU16Ptr(x) ((u16*)(&x))
|
||||
#define mmToU8Ptr(x) ((u8*)(&x))
|
||||
|
||||
struct g_imm_table_struct
|
||||
{
|
||||
//u16 cntb_table[65536];
|
||||
|
||||
__m128i fsmb_table[65536];
|
||||
__m128i fsmh_table[256];
|
||||
__m128i fsm_table[16];
|
||||
|
||||
__m128i sldq_pshufb[32];
|
||||
__m128i srdq_pshufb[32];
|
||||
__m128i rldq_pshufb[16];
|
||||
|
||||
g_imm_table_struct()
|
||||
{
|
||||
/*static_assert(offsetof(g_imm_table_struct, cntb_table) == 0, "offsetof(cntb_table) != 0");
|
||||
for (u32 i = 0; i < sizeof(cntb_table) / sizeof(cntb_table[0]); i++)
|
||||
{
|
||||
u32 cnt_low = 0, cnt_high = 0;
|
||||
for (u32 j = 0; j < 8; j++)
|
||||
{
|
||||
cnt_low += (i >> j) & 1;
|
||||
cnt_high += (i >> (j + 8)) & 1;
|
||||
}
|
||||
cntb_table[i] = (cnt_high << 8) | cnt_low;
|
||||
}*/
|
||||
for (u32 i = 0; i < sizeof(fsm_table) / sizeof(fsm_table[0]); i++)
|
||||
{
|
||||
|
||||
for (u32 j = 0; j < 4; j++) mmToU32Ptr(fsm_table[i])[j] = (i & (1 << j)) ? ~0 : 0;
|
||||
}
|
||||
for (u32 i = 0; i < sizeof(fsmh_table) / sizeof(fsmh_table[0]); i++)
|
||||
{
|
||||
for (u32 j = 0; j < 8; j++) mmToU16Ptr(fsmh_table[i])[j] = (i & (1 << j)) ? ~0 : 0;
|
||||
}
|
||||
for (u32 i = 0; i < sizeof(fsmb_table) / sizeof(fsmb_table[0]); i++)
|
||||
{
|
||||
for (u32 j = 0; j < 16; j++) mmToU8Ptr(fsmb_table[i])[j] = (i & (1 << j)) ? ~0 : 0;
|
||||
}
|
||||
for (u32 i = 0; i < sizeof(sldq_pshufb) / sizeof(sldq_pshufb[0]); i++)
|
||||
{
|
||||
for (u32 j = 0; j < 16; j++) mmToU8Ptr(sldq_pshufb[i])[j] = (u8)(j - i);
|
||||
}
|
||||
for (u32 i = 0; i < sizeof(srdq_pshufb) / sizeof(srdq_pshufb[0]); i++)
|
||||
{
|
||||
for (u32 j = 0; j < 16; j++) mmToU8Ptr(srdq_pshufb[i])[j] = (j + i > 15) ? 0xff : (u8)(j + i);
|
||||
}
|
||||
for (u32 i = 0; i < sizeof(rldq_pshufb) / sizeof(rldq_pshufb[0]); i++)
|
||||
{
|
||||
for (u32 j = 0; j < 16; j++) mmToU8Ptr(rldq_pshufb[i])[j] = (u8)(j - i) & 0xf;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
extern const g_imm_table_struct g_imm_table;
|
||||
|
||||
//Floating point status and control register. Unsure if this is one of the GPRs or SPRs
|
||||
//Is 128 bits, but bits 0-19, 24-28, 32-49, 56-60, 64-81, 88-92, 96-115, 120-124 are unused
|
||||
class FPSCR
|
||||
|
@ -246,181 +307,127 @@ public:
|
|||
}
|
||||
} m_intrtag[3];
|
||||
|
||||
template<size_t _max_count>
|
||||
// limited lock-free queue, most functions are barrier-free
|
||||
template<size_t max_count>
|
||||
class Channel
|
||||
{
|
||||
public:
|
||||
static const size_t max_count = _max_count;
|
||||
static_assert(max_count >= 1, "Invalid channel count");
|
||||
|
||||
private:
|
||||
union _CRT_ALIGN(8) {
|
||||
struct {
|
||||
volatile u32 m_index;
|
||||
u32 m_value[max_count];
|
||||
struct ChannelData
|
||||
{
|
||||
u32 value;
|
||||
u32 is_set;
|
||||
};
|
||||
volatile u64 m_indval;
|
||||
};
|
||||
std::mutex m_lock;
|
||||
|
||||
atomic_t<ChannelData> m_data[max_count];
|
||||
size_t m_push;
|
||||
size_t m_pop;
|
||||
|
||||
public:
|
||||
Channel()
|
||||
__noinline Channel()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
void Init()
|
||||
for (size_t i = 0; i < max_count; i++)
|
||||
{
|
||||
m_indval = 0;
|
||||
}
|
||||
|
||||
__forceinline bool Pop(u32& res)
|
||||
{
|
||||
if (max_count > 1)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
if(!m_index)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
res = m_value[0];
|
||||
if (max_count > 1) for (u32 i = 1; i < max_count; i++) // FIFO
|
||||
{
|
||||
m_value[i-1] = m_value[i];
|
||||
}
|
||||
m_value[max_count-1] = 0;
|
||||
m_index--;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{ //lock-free
|
||||
if ((m_indval & 0xffffffff) == 0)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
res = (m_indval >> 32);
|
||||
m_indval = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline bool Push(u32 value)
|
||||
{
|
||||
if (max_count > 1)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
if(m_index >= max_count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
m_value[m_index++] = value;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{ //lock-free
|
||||
if (m_indval & 0xffffffff)
|
||||
return false;
|
||||
else
|
||||
{
|
||||
const u64 new_value = ((u64)value << 32) | 1;
|
||||
m_indval = new_value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline void PushUncond(u32 value)
|
||||
{
|
||||
if (max_count > 1)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
if(m_index >= max_count)
|
||||
m_value[max_count-1] = value; //last message is overwritten
|
||||
else
|
||||
m_value[m_index++] = value;
|
||||
}
|
||||
else
|
||||
{ //lock-free
|
||||
const u64 new_value = ((u64)value << 32) | 1;
|
||||
m_indval = new_value;
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline void PushUncond_OR(u32 value)
|
||||
{
|
||||
if (max_count > 1)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
if(m_index >= max_count)
|
||||
m_value[max_count-1] |= value; //last message is logically ORed
|
||||
else
|
||||
m_value[m_index++] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
InterlockedOr64((volatile s64*)m_indval, ((u64)value << 32) | 1);
|
||||
m_data[i].write_relaxed({});
|
||||
}
|
||||
m_push = 0;
|
||||
m_pop = 0;
|
||||
}
|
||||
|
||||
__forceinline void PopUncond(u32& res)
|
||||
{
|
||||
if (max_count > 1)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
if(!m_index)
|
||||
res = 0; //result is undefined
|
||||
else
|
||||
{
|
||||
res = m_value[--m_index];
|
||||
m_value[m_index] = 0;
|
||||
res = m_data[m_pop].read_relaxed().value;
|
||||
m_data[m_pop].write_relaxed({});
|
||||
m_pop = (m_pop + 1) % max_count;
|
||||
}
|
||||
|
||||
__forceinline bool Pop(u32& res)
|
||||
{
|
||||
const auto data = m_data[m_pop].read_relaxed();
|
||||
if (data.is_set)
|
||||
{
|
||||
res = data.value;
|
||||
m_data[m_pop].write_relaxed({});
|
||||
m_pop = (m_pop + 1) % max_count;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{ //lock-free
|
||||
if(!m_index)
|
||||
res = 0;
|
||||
else
|
||||
{
|
||||
res = (m_indval >> 32);
|
||||
m_indval = 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline u32 GetCount()
|
||||
__forceinline bool Pop_XCHG(u32& res) // not barrier-free, not tested
|
||||
{
|
||||
if (max_count > 1)
|
||||
const auto data = m_data[m_pop].exchange({});
|
||||
if (data.is_set)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
return m_index;
|
||||
res = data.value;
|
||||
m_pop = (m_pop + 1) % max_count;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return m_index;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
__forceinline u32 GetFreeCount()
|
||||
__forceinline void PushUncond_OR(const u32 value) // not barrier-free, not tested
|
||||
{
|
||||
if (max_count > 1)
|
||||
m_data[m_push]._or({ value, 1 });
|
||||
m_push = (m_push + 1) % max_count;
|
||||
}
|
||||
|
||||
__forceinline void PushUncond(const u32 value)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_lock);
|
||||
return max_count - m_index;
|
||||
m_data[m_push].write_relaxed({ value, 1 });
|
||||
m_push = (m_push + 1) % max_count;
|
||||
}
|
||||
|
||||
__forceinline bool Push(const u32 value)
|
||||
{
|
||||
if (m_data[m_push].read_relaxed().is_set)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return max_count - m_index;
|
||||
PushUncond(value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void SetValue(u32 value)
|
||||
__forceinline u32 GetCount() const
|
||||
{
|
||||
m_value[0] = value;
|
||||
u32 res = 0;
|
||||
for (size_t i = 0; i < max_count; i++)
|
||||
{
|
||||
res += m_data[i].read_relaxed().is_set ? 1 : 0;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
u32 GetValue() const
|
||||
__forceinline u32 GetFreeCount() const
|
||||
{
|
||||
return m_value[0];
|
||||
u32 res = 0;
|
||||
for (size_t i = 0; i < max_count; i++)
|
||||
{
|
||||
res += m_data[i].read_relaxed().is_set ? 0 : 1;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
__forceinline void SetValue(const u32 value)
|
||||
{
|
||||
m_data[m_push].direct_op([value](ChannelData& v)
|
||||
{
|
||||
v.value = value;
|
||||
});
|
||||
}
|
||||
|
||||
__forceinline u32 GetValue() const
|
||||
{
|
||||
return m_data[m_pop].read_relaxed().value;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -473,7 +480,7 @@ public:
|
|||
struct { u32 EAH, EAL; };
|
||||
};
|
||||
|
||||
DMAC dmac;
|
||||
u32 ls_offset;
|
||||
|
||||
void ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size);
|
||||
|
||||
|
@ -503,6 +510,9 @@ public:
|
|||
void WriteLS64 (const u32 lsa, const u64& data) const { vm::write64 (lsa + m_offset, data); }
|
||||
void WriteLS128(const u32 lsa, const u128& data) const { vm::write128(lsa + m_offset, data); }
|
||||
|
||||
std::function<void(SPUThread& SPU)> m_custom_task;
|
||||
std::function<u64(SPUThread& SPU)> m_code3_func;
|
||||
|
||||
public:
|
||||
SPUThread(CPUThreadType type = CPU_THREAD_SPU);
|
||||
virtual ~SPUThread();
|
||||
|
@ -560,6 +570,8 @@ public:
|
|||
public:
|
||||
virtual void InitRegs();
|
||||
virtual void Task();
|
||||
void FastCall(u32 ls_addr);
|
||||
void FastStop();
|
||||
|
||||
protected:
|
||||
virtual void DoReset();
|
||||
|
@ -571,3 +583,49 @@ protected:
|
|||
};
|
||||
|
||||
SPUThread& GetCurrentSPUThread();
|
||||
|
||||
class spu_thread : cpu_thread
|
||||
{
|
||||
static const u32 stack_align = 0x10;
|
||||
vm::ptr<u64> argv;
|
||||
u32 argc;
|
||||
vm::ptr<u64> envp;
|
||||
|
||||
public:
|
||||
spu_thread(u32 entry, const std::string& name = "", u32 stack_size = 0, u32 prio = 0);
|
||||
|
||||
cpu_thread& args(std::initializer_list<std::string> values) override
|
||||
{
|
||||
if (!values.size())
|
||||
return *this;
|
||||
|
||||
assert(argc == 0);
|
||||
|
||||
envp.set(Memory.MainMem.AllocAlign((u32)sizeof(envp), stack_align));
|
||||
*envp = 0;
|
||||
argv.set(Memory.MainMem.AllocAlign(u32(sizeof(argv)* values.size()), stack_align));
|
||||
|
||||
for (auto &arg : values)
|
||||
{
|
||||
u32 arg_size = align(u32(arg.size() + 1), stack_align);
|
||||
u32 arg_addr = Memory.MainMem.AllocAlign(arg_size, stack_align);
|
||||
|
||||
std::strcpy(vm::get_ptr<char>(arg_addr), arg.c_str());
|
||||
|
||||
argv[argc++] = arg_addr;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
cpu_thread& run() override
|
||||
{
|
||||
thread->Run();
|
||||
|
||||
static_cast<SPUThread*>(thread)->GPR[3].from64(argc);
|
||||
static_cast<SPUThread*>(thread)->GPR[4].from64(argv.addr());
|
||||
static_cast<SPUThread*>(thread)->GPR[5].from64(envp.addr());
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
|
@ -4,33 +4,94 @@
|
|||
#include "Emu/HDD/HDD.h"
|
||||
#include "vfsDeviceLocalFile.h"
|
||||
#include "Ini.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
#undef CreateFile // TODO: what's wrong with it?
|
||||
#undef CreateFile
|
||||
|
||||
int sort_devices(const void* _a, const void* _b)
|
||||
{
|
||||
const vfsDevice& a = **(const vfsDevice**)_a;
|
||||
const vfsDevice& b = **(const vfsDevice**)_b;
|
||||
|
||||
if(a.GetPs3Path().length() > b.GetPs3Path().length()) return 1;
|
||||
if(a.GetPs3Path().length() < b.GetPs3Path().length()) return -1;
|
||||
if (a.GetPs3Path().length() > b.GetPs3Path().length()) return 1;
|
||||
if (a.GetPs3Path().length() < b.GetPs3Path().length()) return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::vector<std::string> simplify_path_blocks(const std::string& path)
|
||||
{
|
||||
std::string lower_path = path;
|
||||
std::transform(lower_path.begin(), lower_path.end(), lower_path.begin(), ::tolower);
|
||||
|
||||
std::vector<std::string> path_blocks = std::move(fmt::split(lower_path, { "/", "\\" }));
|
||||
|
||||
for (size_t i = 0; i < path_blocks.size(); ++i)
|
||||
{
|
||||
if (path_blocks[i] == ".")
|
||||
{
|
||||
path_blocks.erase(path_blocks.begin() + i--);
|
||||
}
|
||||
else if (i && path_blocks[i] == "..")
|
||||
{
|
||||
path_blocks.erase(path_blocks.begin() + (i - 1), path_blocks.begin() + (i + 1));
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
return path_blocks;
|
||||
}
|
||||
|
||||
std::string simplify_path(const std::string& path, bool is_dir)
|
||||
{
|
||||
std::vector<std::string> path_blocks = simplify_path_blocks(path);
|
||||
|
||||
std::string result;
|
||||
|
||||
if (path_blocks.empty())
|
||||
return result;
|
||||
|
||||
if (is_dir)
|
||||
{
|
||||
for (auto &dir : path_blocks)
|
||||
{
|
||||
result += dir + "/";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < path_blocks.size() - 1; ++i)
|
||||
{
|
||||
result += path_blocks[i] + "/";
|
||||
}
|
||||
|
||||
result += path_blocks[path_blocks.size() - 1];
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
VFS::~VFS()
|
||||
{
|
||||
UnMountAll();
|
||||
}
|
||||
|
||||
std::string VFS::FindEntry(const std::string &path)
|
||||
{
|
||||
return path;
|
||||
return cwd + "/" + path;
|
||||
}
|
||||
|
||||
void VFS::Mount(const std::string& ps3_path, const std::string& local_path, vfsDevice* device)
|
||||
{
|
||||
UnMount(ps3_path);
|
||||
std::string simpl_ps3_path = simplify_path(ps3_path, true);
|
||||
|
||||
device->SetPath(ps3_path, local_path);
|
||||
UnMount(simpl_ps3_path);
|
||||
|
||||
device->SetPath(simpl_ps3_path, simplify_path(local_path, true));
|
||||
m_devices.push_back(device);
|
||||
|
||||
if(m_devices.size() > 1)
|
||||
if (m_devices.size() > 1)
|
||||
{
|
||||
//std::qsort(m_devices.GetPtr(), m_devices.GetCount(), sizeof(vfsDevice*), sort_devices);
|
||||
}
|
||||
|
@ -38,11 +99,14 @@ void VFS::Mount(const std::string& ps3_path, const std::string& local_path, vfsD
|
|||
|
||||
void VFS::UnMount(const std::string& ps3_path)
|
||||
{
|
||||
for(u32 i=0; i<m_devices.size(); ++i)
|
||||
std::string simpl_ps3_path = simplify_path(ps3_path, true);
|
||||
|
||||
for (u32 i = 0; i < m_devices.size(); ++i)
|
||||
{
|
||||
if(!m_devices[i]->GetPs3Path().compare(ps3_path))
|
||||
if (!strcmp(m_devices[i]->GetPs3Path().c_str(), simpl_ps3_path.c_str()))
|
||||
{
|
||||
delete m_devices[i];
|
||||
|
||||
m_devices.erase(m_devices.begin() +i);
|
||||
|
||||
return;
|
||||
|
@ -63,9 +127,9 @@ void VFS::UnMountAll()
|
|||
vfsFileBase* VFS::OpenFile(const std::string& ps3_path, vfsOpenMode mode) const
|
||||
{
|
||||
std::string path;
|
||||
if(vfsDevice* dev = GetDevice(ps3_path, path))
|
||||
if (vfsDevice* dev = GetDevice(ps3_path, path))
|
||||
{
|
||||
if(vfsFileBase* res = dev->GetNewFileStream())
|
||||
if (vfsFileBase* res = dev->GetNewFileStream())
|
||||
{
|
||||
res->Open(path, mode);
|
||||
return res;
|
||||
|
@ -79,9 +143,9 @@ vfsDirBase* VFS::OpenDir(const std::string& ps3_path) const
|
|||
{
|
||||
std::string path;
|
||||
|
||||
if(vfsDevice* dev = GetDevice(ps3_path, path))
|
||||
if (vfsDevice* dev = GetDevice(ps3_path, path))
|
||||
{
|
||||
if(vfsDirBase* res = dev->GetNewDirStream())
|
||||
if (vfsDirBase* res = dev->GetNewDirStream())
|
||||
{
|
||||
res->Open(path);
|
||||
return res;
|
||||
|
@ -94,11 +158,11 @@ vfsDirBase* VFS::OpenDir(const std::string& ps3_path) const
|
|||
bool VFS::CreateFile(const std::string& ps3_path) const
|
||||
{
|
||||
std::string path;
|
||||
if(vfsDevice* dev = GetDevice(ps3_path, path))
|
||||
if (vfsDevice* dev = GetDevice(ps3_path, path))
|
||||
{
|
||||
std::shared_ptr<vfsFileBase> res(dev->GetNewFileStream());
|
||||
|
||||
if(res)
|
||||
if (res)
|
||||
{
|
||||
return res->Create(path);
|
||||
}
|
||||
|
@ -110,11 +174,11 @@ bool VFS::CreateFile(const std::string& ps3_path) const
|
|||
bool VFS::CreateDir(const std::string& ps3_path) const
|
||||
{
|
||||
std::string path;
|
||||
if(vfsDevice* dev = GetDevice(ps3_path, path))
|
||||
if (vfsDevice* dev = GetDevice(ps3_path, path))
|
||||
{
|
||||
std::shared_ptr<vfsDirBase> res(dev->GetNewDirStream());
|
||||
|
||||
if(res)
|
||||
if (res)
|
||||
{
|
||||
return res->Create(path);
|
||||
}
|
||||
|
@ -126,11 +190,11 @@ bool VFS::CreateDir(const std::string& ps3_path) const
|
|||
bool VFS::RemoveFile(const std::string& ps3_path) const
|
||||
{
|
||||
std::string path;
|
||||
if(vfsDevice* dev = GetDevice(ps3_path, path))
|
||||
if (vfsDevice* dev = GetDevice(ps3_path, path))
|
||||
{
|
||||
std::shared_ptr<vfsFileBase> res(dev->GetNewFileStream());
|
||||
|
||||
if(res)
|
||||
if (res)
|
||||
{
|
||||
return res->Remove(path);
|
||||
}
|
||||
|
@ -142,11 +206,11 @@ bool VFS::RemoveFile(const std::string& ps3_path) const
|
|||
bool VFS::RemoveDir(const std::string& ps3_path) const
|
||||
{
|
||||
std::string path;
|
||||
if(vfsDevice* dev = GetDevice(ps3_path, path))
|
||||
if (vfsDevice* dev = GetDevice(ps3_path, path))
|
||||
{
|
||||
std::shared_ptr<vfsDirBase> res(dev->GetNewDirStream());
|
||||
|
||||
if(res)
|
||||
if (res)
|
||||
{
|
||||
return res->Remove(path);
|
||||
}
|
||||
|
@ -158,11 +222,11 @@ bool VFS::RemoveDir(const std::string& ps3_path) const
|
|||
bool VFS::ExistsFile(const std::string& ps3_path) const
|
||||
{
|
||||
std::string path;
|
||||
if(vfsDevice* dev = GetDevice(ps3_path, path))
|
||||
if (vfsDevice* dev = GetDevice(ps3_path, path))
|
||||
{
|
||||
std::shared_ptr<vfsFileBase> res(dev->GetNewFileStream());
|
||||
|
||||
if(res)
|
||||
if (res)
|
||||
{
|
||||
return res->Exists(path);
|
||||
}
|
||||
|
@ -174,11 +238,11 @@ bool VFS::ExistsFile(const std::string& ps3_path) const
|
|||
bool VFS::ExistsDir(const std::string& ps3_path) const
|
||||
{
|
||||
std::string path;
|
||||
if(vfsDevice* dev = GetDevice(ps3_path, path))
|
||||
if (vfsDevice* dev = GetDevice(ps3_path, path))
|
||||
{
|
||||
std::shared_ptr<vfsDirBase> res(dev->GetNewDirStream());
|
||||
|
||||
if(res)
|
||||
if (res)
|
||||
{
|
||||
return res->IsExists(path);
|
||||
}
|
||||
|
@ -190,11 +254,11 @@ bool VFS::ExistsDir(const std::string& ps3_path) const
|
|||
bool VFS::RenameFile(const std::string& ps3_path_from, const std::string& ps3_path_to) const
|
||||
{
|
||||
std::string path;
|
||||
if(vfsDevice* dev = GetDevice(ps3_path_from, path))
|
||||
if (vfsDevice* dev = GetDevice(ps3_path_from, path))
|
||||
{
|
||||
std::shared_ptr<vfsFileBase> res(dev->GetNewFileStream());
|
||||
|
||||
if(res)
|
||||
if (res)
|
||||
{
|
||||
return res->Rename(path, ps3_path_to);
|
||||
}
|
||||
|
@ -206,11 +270,11 @@ bool VFS::RenameFile(const std::string& ps3_path_from, const std::string& ps3_pa
|
|||
bool VFS::RenameDir(const std::string& ps3_path_from, const std::string& ps3_path_to) const
|
||||
{
|
||||
std::string path;
|
||||
if(vfsDevice* dev = GetDevice(ps3_path_from, path))
|
||||
if (vfsDevice* dev = GetDevice(ps3_path_from, path))
|
||||
{
|
||||
std::shared_ptr<vfsDirBase> res(dev->GetNewDirStream());
|
||||
|
||||
if(res)
|
||||
if (res)
|
||||
{
|
||||
return res->Rename(path, ps3_path_to);
|
||||
}
|
||||
|
@ -221,53 +285,107 @@ bool VFS::RenameDir(const std::string& ps3_path_from, const std::string& ps3_pat
|
|||
|
||||
vfsDevice* VFS::GetDevice(const std::string& ps3_path, std::string& path) const
|
||||
{
|
||||
u32 max_eq;
|
||||
s32 max_i=-1;
|
||||
|
||||
for(u32 i=0; i<m_devices.size(); ++i)
|
||||
auto try_get_device = [this, &path](const std::vector<std::string>& ps3_path_blocks) -> vfsDevice*
|
||||
{
|
||||
const u32 eq = m_devices[i]->CmpPs3Path(ps3_path);
|
||||
size_t max_eq = 0;
|
||||
int max_i = -1;
|
||||
|
||||
if(max_i < 0 || eq > max_eq)
|
||||
for (u32 i = 0; i < m_devices.size(); ++i)
|
||||
{
|
||||
std::vector<std::string> dev_ps3_path_blocks = simplify_path_blocks(m_devices[i]->GetPs3Path());
|
||||
|
||||
if (ps3_path_blocks.size() < dev_ps3_path_blocks.size())
|
||||
continue;
|
||||
|
||||
size_t eq = 0;
|
||||
for (; eq < dev_ps3_path_blocks.size(); ++eq)
|
||||
{
|
||||
if (strcmp(ps3_path_blocks[eq].c_str(), dev_ps3_path_blocks[eq].c_str()))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (eq > max_eq)
|
||||
{
|
||||
max_eq = eq;
|
||||
max_i = i;
|
||||
}
|
||||
}
|
||||
|
||||
if(max_i < 0) return nullptr;
|
||||
path = vfsDevice::GetWinPath(m_devices[max_i]->GetLocalPath(), ps3_path.substr(max_eq, ps3_path.length() - max_eq));
|
||||
if (max_i < 0)
|
||||
return nullptr;
|
||||
|
||||
path = m_devices[max_i]->GetLocalPath();
|
||||
|
||||
for (u32 i = max_eq; i < ps3_path_blocks.size(); i++)
|
||||
{
|
||||
path += "/" + ps3_path_blocks[i];
|
||||
}
|
||||
|
||||
path = simplify_path(path, false);
|
||||
|
||||
return m_devices[max_i];
|
||||
};
|
||||
|
||||
if (auto res = try_get_device(simplify_path_blocks(ps3_path)))
|
||||
return res;
|
||||
|
||||
if (auto res = try_get_device(simplify_path_blocks(cwd + ps3_path)))
|
||||
return res;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
vfsDevice* VFS::GetDeviceLocal(const std::string& local_path, std::string& path) const
|
||||
{
|
||||
u32 max_eq;
|
||||
s32 max_i=-1;
|
||||
size_t max_eq = 0;
|
||||
int max_i = -1;
|
||||
|
||||
rFileName file_path(local_path);
|
||||
file_path.Normalize();
|
||||
std::string mormalized_path = file_path.GetFullPath();
|
||||
std::vector<std::string> local_path_blocks = simplify_path_blocks(local_path);
|
||||
|
||||
for(u32 i=0; i<m_devices.size(); ++i)
|
||||
for (u32 i = 0; i < m_devices.size(); ++i)
|
||||
{
|
||||
const u32 eq = m_devices[i]->CmpLocalPath(mormalized_path);
|
||||
std::vector<std::string> dev_local_path_blocks_blocks = simplify_path_blocks(m_devices[i]->GetLocalPath());
|
||||
|
||||
if(max_i < 0 || eq > max_eq)
|
||||
if (local_path_blocks.size() < dev_local_path_blocks_blocks.size())
|
||||
continue;
|
||||
|
||||
size_t eq = 0;
|
||||
for (; eq < dev_local_path_blocks_blocks.size(); ++eq)
|
||||
{
|
||||
if (strcmp(local_path_blocks[eq].c_str(), dev_local_path_blocks_blocks[eq].c_str()))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (eq > max_eq)
|
||||
{
|
||||
max_eq = eq;
|
||||
max_i = i;
|
||||
}
|
||||
}
|
||||
|
||||
if(max_i < 0) return nullptr;
|
||||
if (max_i < 0)
|
||||
return nullptr;
|
||||
|
||||
path = m_devices[max_i]->GetPs3Path();
|
||||
|
||||
for (u32 i = max_eq; i < local_path_blocks.size(); i++)
|
||||
{
|
||||
path += "/" + local_path_blocks[i];
|
||||
}
|
||||
|
||||
path = simplify_path(path, false);
|
||||
|
||||
path = vfsDevice::GetPs3Path(m_devices[max_i]->GetPs3Path(), local_path.substr(max_eq, local_path.length() - max_eq));
|
||||
return m_devices[max_i];
|
||||
}
|
||||
|
||||
void VFS::Init(const std::string& path)
|
||||
{
|
||||
cwd = simplify_path(path, true);
|
||||
|
||||
UnMountAll();
|
||||
|
||||
std::vector<VFSManagerEntry> entries;
|
||||
|
@ -293,8 +411,8 @@ void VFS::Init(const std::string& path)
|
|||
|
||||
std::string mpath = entry.path;
|
||||
// TODO: This shouldn't use current dir
|
||||
fmt::Replace(mpath,"$(EmulatorDir)", ".");
|
||||
fmt::Replace(mpath,"$(GameDir)", vfsDevice::GetRoot(path));
|
||||
fmt::Replace(mpath, "$(EmulatorDir)", Emu.GetEmulatorPath());
|
||||
fmt::Replace(mpath, "$(GameDir)", cwd);
|
||||
Mount(entry.mount, mpath, dev);
|
||||
}
|
||||
}
|
||||
|
@ -305,11 +423,11 @@ void VFS::SaveLoadDevices(std::vector<VFSManagerEntry>& res, bool is_load)
|
|||
entries_count.Init("count", "VFSManager");
|
||||
|
||||
int count = 0;
|
||||
if(is_load)
|
||||
if (is_load)
|
||||
{
|
||||
count = entries_count.LoadValue(count);
|
||||
|
||||
if(!count)
|
||||
if (!count)
|
||||
{
|
||||
res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_hdd0/", "/dev_hdd0/");
|
||||
res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_hdd1/", "/dev_hdd1/");
|
||||
|
@ -319,7 +437,6 @@ void VFS::SaveLoadDevices(std::vector<VFSManagerEntry>& res, bool is_load)
|
|||
res.emplace_back(vfsDevice_LocalFile, "$(GameDir)", "/app_home/");
|
||||
res.emplace_back(vfsDevice_LocalFile, "$(GameDir)/../", "/dev_bdvd/");
|
||||
res.emplace_back(vfsDevice_LocalFile, "", "/host_root/");
|
||||
res.emplace_back(vfsDevice_LocalFile, "$(GameDir)", "/");
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -344,7 +461,7 @@ void VFS::SaveLoadDevices(std::vector<VFSManagerEntry>& res, bool is_load)
|
|||
entry_mount.Init(fmt::Format("mount[%d]", i), "VFSManager");
|
||||
entry_device.Init(fmt::Format("device[%d]", i), "VFSManager");
|
||||
|
||||
if(is_load)
|
||||
if (is_load)
|
||||
{
|
||||
res[i] = VFSManagerEntry();
|
||||
res[i].path = entry_path.LoadValue("");
|
||||
|
|
|
@ -42,10 +42,17 @@ struct VFSManagerEntry
|
|||
}
|
||||
};
|
||||
|
||||
std::vector<std::string> simplify_path_blocks(const std::string& path);
|
||||
std::string simplify_path(const std::string& path, bool is_dir);
|
||||
|
||||
struct VFS
|
||||
{
|
||||
~VFS();
|
||||
|
||||
std::string cwd;
|
||||
|
||||
std::string FindEntry(const std::string &path);
|
||||
|
||||
//TODO: find out where these are supposed to be deleted or just make it shared_ptr
|
||||
//and also make GetDevice and GetDeviceLocal return shared_ptr then.
|
||||
// A vfsDevice will be deleted when they're unmounted or the VFS struct is destroyed.
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "stdafx.h"
|
||||
#include "Emu/System.h"
|
||||
|
||||
#include "vfsDevice.h"
|
||||
#include "VFS.h"
|
||||
#include "vfsDir.h"
|
||||
|
||||
|
@ -10,7 +11,7 @@ vfsDir::vfsDir()
|
|||
{
|
||||
// TODO: proper implementation
|
||||
// m_stream is nullptr here. So open root until a proper dir is given
|
||||
Open("/");
|
||||
//Open("/");
|
||||
}
|
||||
|
||||
vfsDir::vfsDir(const std::string& path)
|
||||
|
@ -26,37 +27,78 @@ bool vfsDir::Open(const std::string& path)
|
|||
|
||||
m_stream.reset(Emu.GetVFS().OpenDir(path));
|
||||
|
||||
return m_stream && m_stream->IsOpened();
|
||||
DirEntryInfo info;
|
||||
|
||||
m_cwd = simplify_path(0 && m_stream && m_stream->IsOpened() ? m_stream->GetPath() : path, true);
|
||||
|
||||
auto blocks = simplify_path_blocks(GetPath());
|
||||
|
||||
for (auto dev : Emu.GetVFS().m_devices)
|
||||
{
|
||||
auto dev_blocks = simplify_path_blocks(dev->GetPs3Path());
|
||||
|
||||
if (dev_blocks.size() < (blocks.size() + 1))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bool is_ok = true;
|
||||
|
||||
for (size_t i = 0; i < blocks.size(); ++i)
|
||||
{
|
||||
if (strcmp(dev_blocks[i].c_str(), blocks[i].c_str()))
|
||||
{
|
||||
is_ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_ok)
|
||||
{
|
||||
info.name = dev_blocks[blocks.size()];
|
||||
m_entries.push_back(info);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_stream && m_stream->IsOpened())
|
||||
{
|
||||
m_entries.insert(m_entries.begin(), m_stream->GetEntries().begin(), m_stream->GetEntries().end());
|
||||
}
|
||||
|
||||
return !m_entries.empty();
|
||||
}
|
||||
|
||||
bool vfsDir::Create(const std::string& path)
|
||||
{
|
||||
return m_stream->Create(path);
|
||||
return Emu.GetVFS().CreateDir(path);
|
||||
}
|
||||
|
||||
bool vfsDir::IsExists(const std::string& path) const
|
||||
{
|
||||
return m_stream->IsExists(path);
|
||||
}
|
||||
auto path_blocks = simplify_path_blocks(path);
|
||||
|
||||
const std::vector<DirEntryInfo>& vfsDir::GetEntries() const
|
||||
{
|
||||
return m_stream->GetEntries();
|
||||
if (path_blocks.empty())
|
||||
return false;
|
||||
|
||||
std::string dir_name = path_blocks[path_blocks.size() - 1];
|
||||
|
||||
for (const auto entry : vfsDir(path + "/.."))
|
||||
{
|
||||
if (!strcmp(entry->name.c_str(), dir_name.c_str()))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool vfsDir::Rename(const std::string& from, const std::string& to)
|
||||
{
|
||||
return m_stream->Rename(from, to);
|
||||
return Emu.GetVFS().RenameDir(from, to);
|
||||
}
|
||||
|
||||
bool vfsDir::Remove(const std::string& path)
|
||||
{
|
||||
return m_stream->Remove(path);
|
||||
}
|
||||
|
||||
const DirEntryInfo* vfsDir::Read()
|
||||
{
|
||||
return m_stream->Read();
|
||||
return Emu.GetVFS().RemoveDir(path);
|
||||
}
|
||||
|
||||
void vfsDir::Close()
|
||||
|
@ -64,12 +106,7 @@ void vfsDir::Close()
|
|||
m_stream.reset();
|
||||
}
|
||||
|
||||
std::string vfsDir::GetPath() const
|
||||
{
|
||||
return m_stream->GetPath();
|
||||
}
|
||||
|
||||
bool vfsDir::IsOpened() const
|
||||
{
|
||||
return m_stream && m_stream->IsOpened();
|
||||
return !m_entries.empty();
|
||||
}
|
||||
|
|
|
@ -13,13 +13,11 @@ public:
|
|||
virtual bool Open(const std::string& path) override;
|
||||
virtual bool IsOpened() const override;
|
||||
virtual bool IsExists(const std::string& path) const override;
|
||||
virtual const std::vector<DirEntryInfo>& GetEntries() const override;
|
||||
virtual void Close() override;
|
||||
virtual std::string GetPath() const override;
|
||||
//virtual std::string GetPath() const override;
|
||||
|
||||
virtual bool Create(const std::string& path) override;
|
||||
//virtual bool Create(const DirEntryInfo& info) override;
|
||||
virtual bool Rename(const std::string& from, const std::string& to) override;
|
||||
virtual bool Remove(const std::string& path) override;
|
||||
virtual const DirEntryInfo* Read() override;
|
||||
};
|
||||
|
|
|
@ -32,7 +32,7 @@ bool vfsDirBase::IsOpened() const
|
|||
|
||||
bool vfsDirBase::IsExists(const std::string& path) const
|
||||
{
|
||||
return rExists(path);
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::vector<DirEntryInfo>& vfsDirBase::GetEntries() const
|
||||
|
@ -58,3 +58,9 @@ const DirEntryInfo* vfsDirBase::Read()
|
|||
|
||||
return &m_entries[m_pos++];
|
||||
}
|
||||
|
||||
const DirEntryInfo* vfsDirBase::First()
|
||||
{
|
||||
m_pos = 0;
|
||||
return Read();
|
||||
}
|
|
@ -53,4 +53,57 @@ public:
|
|||
virtual bool Rename(const std::string& from, const std::string& to) = 0;
|
||||
virtual bool Remove(const std::string& path) = 0;
|
||||
virtual const DirEntryInfo* Read();
|
||||
virtual const DirEntryInfo* First();
|
||||
|
||||
class iterator
|
||||
{
|
||||
vfsDirBase *parent;
|
||||
const DirEntryInfo* data;
|
||||
|
||||
public:
|
||||
iterator(vfsDirBase* parent)
|
||||
: parent(parent)
|
||||
, data(parent->First())
|
||||
{
|
||||
}
|
||||
|
||||
iterator(const DirEntryInfo* data)
|
||||
: parent(parent)
|
||||
, data(data)
|
||||
{
|
||||
}
|
||||
|
||||
iterator& operator++()
|
||||
{
|
||||
data = parent->Read();
|
||||
return *this;
|
||||
}
|
||||
|
||||
iterator operator++(int)
|
||||
{
|
||||
const DirEntryInfo* olddata = data;
|
||||
data = parent->Read();
|
||||
return iterator(olddata);
|
||||
}
|
||||
|
||||
const DirEntryInfo* operator *()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
bool operator!=(iterator other) const
|
||||
{
|
||||
return data != other.data;
|
||||
}
|
||||
};
|
||||
|
||||
iterator begin()
|
||||
{
|
||||
return iterator(this);
|
||||
}
|
||||
|
||||
iterator end()
|
||||
{
|
||||
return iterator((const DirEntryInfo*)nullptr);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -21,7 +21,7 @@ bool vfsLocalDir::Open(const std::string& path)
|
|||
std::string name;
|
||||
for(bool is_ok = dir.GetFirst(&name); is_ok; is_ok = dir.GetNext(&name))
|
||||
{
|
||||
std::string dir_path = path + name;
|
||||
std::string dir_path = path + "/" + name;
|
||||
|
||||
m_entries.emplace_back();
|
||||
// TODO: Use same info structure as fileinfo?
|
||||
|
@ -46,6 +46,11 @@ bool vfsLocalDir::Create(const std::string& path)
|
|||
return rMkpath(path);
|
||||
}
|
||||
|
||||
bool vfsLocalDir::IsExists(const std::string& path) const
|
||||
{
|
||||
return rIsDir(path);
|
||||
}
|
||||
|
||||
bool vfsLocalDir::Rename(const std::string& from, const std::string& to)
|
||||
{
|
||||
return false;
|
||||
|
|
|
@ -18,4 +18,5 @@ public:
|
|||
virtual bool Rename(const std::string& from, const std::string& to) override;
|
||||
virtual bool Remove(const std::string& path) override;
|
||||
virtual bool IsOpened() const override;
|
||||
virtual bool IsExists(const std::string& path) const;
|
||||
};
|
|
@ -59,12 +59,13 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
struct ID
|
||||
class ID
|
||||
{
|
||||
std::string m_name;
|
||||
IDData* m_data;
|
||||
IDType m_type;
|
||||
|
||||
public:
|
||||
template<typename T>
|
||||
ID(const std::string& name, T* data, const IDType type)
|
||||
: m_name(name)
|
||||
|
@ -96,6 +97,21 @@ struct ID
|
|||
{
|
||||
delete m_data;
|
||||
}
|
||||
|
||||
const std::string& GetName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
IDData* GetData() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
IDType GetType() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
};
|
||||
|
||||
class IdManager
|
||||
|
@ -172,7 +188,7 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
result = f->second.m_data->get<T>();
|
||||
result = f->second.GetData()->get<T>();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -198,8 +214,8 @@ public:
|
|||
if (item == m_id_map.end()) {
|
||||
return false;
|
||||
}
|
||||
if (item->second.m_type < TYPE_OTHER) {
|
||||
m_types[item->second.m_type].erase(id);
|
||||
if (item->second.GetType() < TYPE_OTHER) {
|
||||
m_types[item->second.GetType()].erase(id);
|
||||
}
|
||||
|
||||
item->second.Kill();
|
||||
|
|
|
@ -108,9 +108,9 @@ void MemoryBase::Init(MemoryType type)
|
|||
memset(RawSPUMem, 0, sizeof(RawSPUMem));
|
||||
|
||||
#ifdef _WIN32
|
||||
if (!m_base_addr)
|
||||
if (!vm::g_base_addr)
|
||||
#else
|
||||
if ((s64)m_base_addr == (s64)-1)
|
||||
if ((s64)vm::g_base_addr == (s64)-1)
|
||||
#endif
|
||||
{
|
||||
LOG_ERROR(MEMORY, "Initializing memory failed");
|
||||
|
@ -119,7 +119,7 @@ void MemoryBase::Init(MemoryType type)
|
|||
}
|
||||
else
|
||||
{
|
||||
LOG_NOTICE(MEMORY, "Initializing memory: m_base_addr = 0x%llx", (u64)m_base_addr);
|
||||
LOG_NOTICE(MEMORY, "Initializing memory: base_addr = 0x%llx", (u64)vm::g_base_addr);
|
||||
}
|
||||
|
||||
switch (type)
|
||||
|
@ -128,6 +128,7 @@ void MemoryBase::Init(MemoryType type)
|
|||
MemoryBlocks.push_back(MainMem.SetRange(0x00010000, 0x2FFF0000));
|
||||
MemoryBlocks.push_back(UserMemory = PRXMem.SetRange(0x30000000, 0x10000000));
|
||||
MemoryBlocks.push_back(RSXCMDMem.SetRange(0x40000000, 0x10000000));
|
||||
MemoryBlocks.push_back(SPRXMem.SetRange(0x50000000, 0x10000000));
|
||||
MemoryBlocks.push_back(MmaperMem.SetRange(0xB0000000, 0x10000000));
|
||||
MemoryBlocks.push_back(RSXFBMem.SetRange(0xC0000000, 0x10000000));
|
||||
MemoryBlocks.push_back(StackMem.SetRange(0xD0000000, 0x10000000));
|
||||
|
@ -205,7 +206,7 @@ bool MemoryBase::Map(const u64 addr, const u32 size)
|
|||
{
|
||||
LV2_LOCK(0);
|
||||
|
||||
if ((u32)addr != addr || (u64)addr + (u64)size > 0x100000000ull)
|
||||
if ((addr | (addr + size)) & ~0xFFFFFFFFull)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -218,7 +219,8 @@ bool MemoryBase::Map(const u64 addr, const u32 size)
|
|||
}
|
||||
|
||||
MemoryBlocks.push_back((new MemoryBlock())->SetRange(addr, size));
|
||||
LOG_WARNING(MEMORY, "MemoryBase::Map(0x%llx, 0x%x)", addr, size);
|
||||
|
||||
LOG_WARNING(MEMORY, "Memory mapped at 0x%llx: size=0x%x", addr, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -442,6 +444,12 @@ void DynamicMemoryBlockBase::AppendMem(u64 addr, u32 size) /* private */
|
|||
|
||||
u64 DynamicMemoryBlockBase::AllocAlign(u32 size, u32 align)
|
||||
{
|
||||
if (!MemoryBlock::GetStartAddr())
|
||||
{
|
||||
LOG_ERROR(MEMORY, "DynamicMemoryBlockBase::AllocAlign(size=0x%x, align=0x%x): memory block not initialized", size, align);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size = PAGE_4K(size);
|
||||
u32 exsize;
|
||||
|
||||
|
@ -568,9 +576,9 @@ bool VirtualMemoryBlock::IsInMyRange(const u64 addr, const u32 size)
|
|||
|
||||
bool VirtualMemoryBlock::IsMyAddress(const u64 addr)
|
||||
{
|
||||
for(u32 i=0; i<m_mapped_memory.size(); ++i)
|
||||
for (u32 i = 0; i<m_mapped_memory.size(); ++i)
|
||||
{
|
||||
if(addr >= m_mapped_memory[i].addr && addr < m_mapped_memory[i].addr + m_mapped_memory[i].size)
|
||||
if (addr >= m_mapped_memory[i].addr && addr < m_mapped_memory[i].addr + m_mapped_memory[i].size)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -579,26 +587,16 @@ bool VirtualMemoryBlock::IsMyAddress(const u64 addr)
|
|||
return false;
|
||||
}
|
||||
|
||||
u64 VirtualMemoryBlock::Map(u64 realaddr, u32 size, u64 addr)
|
||||
u64 VirtualMemoryBlock::Map(u64 realaddr, u32 size)
|
||||
{
|
||||
if(addr)
|
||||
{
|
||||
if(!IsInMyRange(addr, size) && (IsMyAddress(addr) || IsMyAddress(addr + size - 1)))
|
||||
return 0;
|
||||
|
||||
m_mapped_memory.emplace_back(addr, realaddr, size);
|
||||
return addr;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(u64 addr = GetStartAddr(); addr <= GetEndAddr() - GetReservedAmount() - size;)
|
||||
for (u64 addr = GetStartAddr(); addr <= GetEndAddr() - GetReservedAmount() - size;)
|
||||
{
|
||||
bool is_good_addr = true;
|
||||
|
||||
// check if address is already mapped
|
||||
for(u32 i=0; i<m_mapped_memory.size(); ++i)
|
||||
for (u32 i = 0; i<m_mapped_memory.size(); ++i)
|
||||
{
|
||||
if((addr >= m_mapped_memory[i].addr && addr < m_mapped_memory[i].addr + m_mapped_memory[i].size) ||
|
||||
if ((addr >= m_mapped_memory[i].addr && addr < m_mapped_memory[i].addr + m_mapped_memory[i].size) ||
|
||||
(m_mapped_memory[i].addr >= addr && m_mapped_memory[i].addr < addr + size))
|
||||
{
|
||||
is_good_addr = false;
|
||||
|
@ -607,7 +605,7 @@ u64 VirtualMemoryBlock::Map(u64 realaddr, u32 size, u64 addr)
|
|||
}
|
||||
}
|
||||
|
||||
if(!is_good_addr) continue;
|
||||
if (!is_good_addr) continue;
|
||||
|
||||
m_mapped_memory.emplace_back(addr, realaddr, size);
|
||||
|
||||
|
@ -615,37 +613,45 @@ u64 VirtualMemoryBlock::Map(u64 realaddr, u32 size, u64 addr)
|
|||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
u32 VirtualMemoryBlock::UnmapRealAddress(u64 realaddr)
|
||||
bool VirtualMemoryBlock::Map(u64 realaddr, u32 size, u64 addr)
|
||||
{
|
||||
for(u32 i=0; i<m_mapped_memory.size(); ++i)
|
||||
{
|
||||
if(m_mapped_memory[i].realAddress == realaddr && IsInMyRange(m_mapped_memory[i].addr, m_mapped_memory[i].size))
|
||||
{
|
||||
u32 size = m_mapped_memory[i].size;
|
||||
m_mapped_memory.erase(m_mapped_memory.begin() + i);
|
||||
return size;
|
||||
}
|
||||
}
|
||||
if (!IsInMyRange(addr, size) && (IsMyAddress(addr) || IsMyAddress(addr + size - 1)))
|
||||
return false;
|
||||
|
||||
return 0;
|
||||
m_mapped_memory.emplace_back(addr, realaddr, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
u32 VirtualMemoryBlock::UnmapAddress(u64 addr)
|
||||
bool VirtualMemoryBlock::UnmapRealAddress(u64 realaddr, u32& size)
|
||||
{
|
||||
for(u32 i=0; i<m_mapped_memory.size(); ++i)
|
||||
for (u32 i = 0; i<m_mapped_memory.size(); ++i)
|
||||
{
|
||||
if(m_mapped_memory[i].addr == addr && IsInMyRange(m_mapped_memory[i].addr, m_mapped_memory[i].size))
|
||||
if (m_mapped_memory[i].realAddress == realaddr && IsInMyRange(m_mapped_memory[i].addr, m_mapped_memory[i].size))
|
||||
{
|
||||
u32 size = m_mapped_memory[i].size;
|
||||
size = m_mapped_memory[i].size;
|
||||
m_mapped_memory.erase(m_mapped_memory.begin() + i);
|
||||
return size;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VirtualMemoryBlock::UnmapAddress(u64 addr, u32& size)
|
||||
{
|
||||
for (u32 i = 0; i<m_mapped_memory.size(); ++i)
|
||||
{
|
||||
if (m_mapped_memory[i].addr == addr && IsInMyRange(m_mapped_memory[i].addr, m_mapped_memory[i].size))
|
||||
{
|
||||
size = m_mapped_memory[i].size;
|
||||
m_mapped_memory.erase(m_mapped_memory.begin() + i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VirtualMemoryBlock::Read32(const u64 addr, u32* value)
|
||||
|
@ -660,7 +666,7 @@ bool VirtualMemoryBlock::Read32(const u64 addr, u32* value)
|
|||
bool VirtualMemoryBlock::Write32(const u64 addr, const u32 value)
|
||||
{
|
||||
u64 realAddr;
|
||||
if(!getRealAddr(addr, realAddr))
|
||||
if (!getRealAddr(addr, realAddr))
|
||||
return false;
|
||||
vm::write32(realAddr, value);
|
||||
return true;
|
||||
|
@ -668,9 +674,9 @@ bool VirtualMemoryBlock::Write32(const u64 addr, const u32 value)
|
|||
|
||||
bool VirtualMemoryBlock::getRealAddr(u64 addr, u64& result)
|
||||
{
|
||||
for(u32 i=0; i<m_mapped_memory.size(); ++i)
|
||||
for (u32 i = 0; i<m_mapped_memory.size(); ++i)
|
||||
{
|
||||
if(addr >= m_mapped_memory[i].addr && addr < m_mapped_memory[i].addr + m_mapped_memory[i].size)
|
||||
if (addr >= m_mapped_memory[i].addr && addr < m_mapped_memory[i].addr + m_mapped_memory[i].size)
|
||||
{
|
||||
result = m_mapped_memory[i].realAddress + (addr - m_mapped_memory[i].addr);
|
||||
return true;
|
||||
|
@ -682,9 +688,9 @@ bool VirtualMemoryBlock::getRealAddr(u64 addr, u64& result)
|
|||
|
||||
u64 VirtualMemoryBlock::getMappedAddress(u64 realAddress)
|
||||
{
|
||||
for(u32 i=0; i<m_mapped_memory.size(); ++i)
|
||||
for (u32 i = 0; i<m_mapped_memory.size(); ++i)
|
||||
{
|
||||
if(realAddress >= m_mapped_memory[i].realAddress && realAddress < m_mapped_memory[i].realAddress + m_mapped_memory[i].size)
|
||||
if (realAddress >= m_mapped_memory[i].realAddress && realAddress < m_mapped_memory[i].realAddress + m_mapped_memory[i].size)
|
||||
{
|
||||
return m_mapped_memory[i].addr + (realAddress - m_mapped_memory[i].realAddress);
|
||||
}
|
||||
|
@ -702,7 +708,7 @@ void VirtualMemoryBlock::Delete()
|
|||
|
||||
bool VirtualMemoryBlock::Reserve(u32 size)
|
||||
{
|
||||
if(size + GetReservedAmount() > GetEndAddr() - GetStartAddr())
|
||||
if (size + GetReservedAmount() > GetEndAddr() - GetStartAddr())
|
||||
return false;
|
||||
|
||||
m_reserve_size += size;
|
||||
|
@ -711,7 +717,7 @@ bool VirtualMemoryBlock::Reserve(u32 size)
|
|||
|
||||
bool VirtualMemoryBlock::Unreserve(u32 size)
|
||||
{
|
||||
if(size > GetReservedAmount())
|
||||
if (size > GetReservedAmount())
|
||||
return false;
|
||||
|
||||
m_reserve_size -= size;
|
||||
|
|
|
@ -7,8 +7,6 @@ using std::nullptr_t;
|
|||
#define safe_delete(x) do {delete (x);(x)=nullptr;} while(0)
|
||||
#define safe_free(x) do {free(x);(x)=nullptr;} while(0)
|
||||
|
||||
extern void* const m_base_addr;
|
||||
|
||||
enum MemoryType
|
||||
{
|
||||
Memory_PS3,
|
||||
|
@ -24,6 +22,11 @@ enum : u32
|
|||
RAW_SPU_PROB_OFFSET = 0x00040000,
|
||||
};
|
||||
|
||||
namespace vm
|
||||
{
|
||||
extern void* const g_base_addr;
|
||||
}
|
||||
|
||||
class MemoryBase
|
||||
{
|
||||
std::vector<MemoryBlock*> MemoryBlocks;
|
||||
|
@ -33,6 +36,7 @@ public:
|
|||
MemoryBlock* UserMemory;
|
||||
|
||||
DynamicMemoryBlock MainMem;
|
||||
DynamicMemoryBlock SPRXMem;
|
||||
DynamicMemoryBlock PRXMem;
|
||||
DynamicMemoryBlock RSXCMDMem;
|
||||
DynamicMemoryBlock MmaperMem;
|
||||
|
@ -70,7 +74,7 @@ public:
|
|||
|
||||
static void* const GetBaseAddr()
|
||||
{
|
||||
return m_base_addr;
|
||||
return vm::g_base_addr;
|
||||
}
|
||||
|
||||
__noinline void InvalidAddress(const char* func, const u64 addr);
|
||||
|
|
|
@ -163,13 +163,14 @@ public:
|
|||
|
||||
// maps real address to virtual address space, returns the mapped address or 0 on failure (if no address is specified the
|
||||
// first mappable space is used)
|
||||
virtual u64 Map(u64 realaddr, u32 size, u64 addr = 0);
|
||||
virtual bool Map(u64 realaddr, u32 size, u64 addr);
|
||||
virtual u64 Map(u64 realaddr, u32 size);
|
||||
|
||||
// Unmap real address (please specify only starting point, no midway memory will be unmapped), returns the size of the unmapped area
|
||||
virtual u32 UnmapRealAddress(u64 realaddr);
|
||||
virtual bool UnmapRealAddress(u64 realaddr, u32& size);
|
||||
|
||||
// Unmap address (please specify only starting point, no midway memory will be unmapped), returns the size of the unmapped area
|
||||
virtual u32 UnmapAddress(u64 addr);
|
||||
virtual bool UnmapAddress(u64 addr, u32& size);
|
||||
|
||||
// Reserve a certain amount so no one can use it, returns true on succces, false on failure
|
||||
virtual bool Reserve(u32 size);
|
||||
|
|
|
@ -0,0 +1,211 @@
|
|||
#pragma once
|
||||
|
||||
template<typename T, size_t size = sizeof(T)>
|
||||
struct _to_atomic
|
||||
{
|
||||
static_assert(size == 1 || size == 2 || size == 4 || size == 8, "Invalid atomic type");
|
||||
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _to_atomic<T, 1>
|
||||
{
|
||||
typedef uint8_t type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _to_atomic<T, 2>
|
||||
{
|
||||
typedef uint16_t type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _to_atomic<T, 4>
|
||||
{
|
||||
typedef uint32_t type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct _to_atomic<T, 8>
|
||||
{
|
||||
typedef uint64_t type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class _atomic_base
|
||||
{
|
||||
typedef typename _to_atomic<T, sizeof(T)>::type atomic_type;
|
||||
atomic_type data;
|
||||
|
||||
public:
|
||||
// atomically compare data with cmp, replace with exch if equal, return previous data value anyway
|
||||
__forceinline const T compare_and_swap(const T& cmp, const T& exch) volatile
|
||||
{
|
||||
const atomic_type res = InterlockedCompareExchange(&data, (atomic_type&)(exch), (atomic_type&)(cmp));
|
||||
return (T&)res;
|
||||
}
|
||||
|
||||
// atomically compare data with cmp, replace with exch if equal, return true if data was replaced
|
||||
__forceinline bool compare_and_swap_test(const T& cmp, const T& exch) volatile
|
||||
{
|
||||
return InterlockedCompareExchangeTest(&data, (atomic_type&)(exch), (atomic_type&)(cmp));
|
||||
}
|
||||
|
||||
// read data with memory barrier
|
||||
__forceinline const T read_sync() const volatile
|
||||
{
|
||||
const atomic_type res = InterlockedCompareExchange(const_cast<volatile atomic_type*>(&data), 0, 0);
|
||||
return (T&)res;
|
||||
}
|
||||
|
||||
// atomically replace data with exch, return previous data value
|
||||
__forceinline const T exchange(const T& exch) volatile
|
||||
{
|
||||
const atomic_type res = InterlockedExchange(&data, (atomic_type&)(exch));
|
||||
return (T&)res;
|
||||
}
|
||||
|
||||
// read data without memory barrier
|
||||
__forceinline const T read_relaxed() const volatile
|
||||
{
|
||||
return (T&)data;
|
||||
}
|
||||
|
||||
// write data without memory barrier
|
||||
__forceinline void write_relaxed(const T& value) volatile
|
||||
{
|
||||
data = (atomic_type&)(value);
|
||||
}
|
||||
|
||||
// perform atomic operation on data
|
||||
template<typename FT> __forceinline void atomic_op(const FT atomic_proc) volatile
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
const T old = read_relaxed();
|
||||
T _new = old;
|
||||
atomic_proc(_new); // function should accept reference to T type
|
||||
if (compare_and_swap_test(old, _new)) return;
|
||||
}
|
||||
}
|
||||
|
||||
// perform atomic operation on data with special exit condition (if intermediate result != proceed_value)
|
||||
template<typename RT, typename FT> __forceinline RT atomic_op(const RT proceed_value, const FT atomic_proc) volatile
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
const T old = read_relaxed();
|
||||
T _new = old;
|
||||
RT res = (RT)atomic_proc(_new); // function should accept reference to T type and return some value
|
||||
if (res != proceed_value) return res;
|
||||
if (compare_and_swap_test(old, _new)) return proceed_value;
|
||||
}
|
||||
}
|
||||
|
||||
// perform atomic operation on data with additional memory barrier
|
||||
template<typename FT> __forceinline void atomic_op_sync(const FT atomic_proc) volatile
|
||||
{
|
||||
T old = read_sync();
|
||||
while (true)
|
||||
{
|
||||
T _new = old;
|
||||
atomic_proc(_new); // function should accept reference to T type
|
||||
const T val = compare_and_swap(old, _new);
|
||||
if ((atomic_type&)val == (atomic_type&)old) return;
|
||||
old = val;
|
||||
}
|
||||
}
|
||||
|
||||
// perform atomic operation on data with additional memory barrier and special exit condition (if intermediate result != proceed_value)
|
||||
template<typename RT, typename FT> __forceinline RT atomic_op_sync(const RT proceed_value, const FT atomic_proc) volatile
|
||||
{
|
||||
T old = read_sync();
|
||||
while (true)
|
||||
{
|
||||
T _new = old;
|
||||
RT res = (RT)atomic_proc(_new); // function should accept reference to T type and return some value
|
||||
if (res != proceed_value) return res;
|
||||
const T val = compare_and_swap(old, _new);
|
||||
if ((atomic_type&)val == (atomic_type&)old) return proceed_value;
|
||||
old = val;
|
||||
}
|
||||
}
|
||||
|
||||
// perform non-atomic operation on data directly without memory barriers
|
||||
template<typename FT> __forceinline void direct_op(const FT direct_proc) volatile
|
||||
{
|
||||
direct_proc((T&)data);
|
||||
}
|
||||
|
||||
// atomic bitwise OR, returns previous data
|
||||
__forceinline const T _or(const T& right) volatile
|
||||
{
|
||||
const atomic_type res = InterlockedOr(&data, (atomic_type&)(right));
|
||||
return (T&)res;
|
||||
}
|
||||
|
||||
// atomic bitwise AND, returns previous data
|
||||
__forceinline const T _and(const T& right) volatile
|
||||
{
|
||||
const atomic_type res = InterlockedAnd(&data, (atomic_type&)(right));
|
||||
return (T&)res;
|
||||
}
|
||||
|
||||
// atomic bitwise AND NOT (inverts right argument), returns previous data
|
||||
__forceinline const T _and_not(const T& right) volatile
|
||||
{
|
||||
const atomic_type res = InterlockedAnd(&data, ~(atomic_type&)(right));
|
||||
return (T&)res;
|
||||
}
|
||||
|
||||
// atomic bitwise XOR, returns previous data
|
||||
__forceinline const T _xor(const T& right) volatile
|
||||
{
|
||||
const atomic_type res = InterlockedXor(&data, (atomic_type&)(right));
|
||||
return (T&)res;
|
||||
}
|
||||
|
||||
__forceinline const T operator |= (const T& right) volatile
|
||||
{
|
||||
const atomic_type res = InterlockedOr(&data, (atomic_type&)(right)) | (atomic_type&)(right);
|
||||
return (T&)res;
|
||||
}
|
||||
|
||||
__forceinline const T operator &= (const T& right) volatile
|
||||
{
|
||||
const atomic_type res = InterlockedAnd(&data, (atomic_type&)(right)) & (atomic_type&)(right);
|
||||
return (T&)res;
|
||||
}
|
||||
|
||||
__forceinline const T operator ^= (const T& right) volatile
|
||||
{
|
||||
const atomic_type res = InterlockedXor(&data, (atomic_type&)(right)) ^ (atomic_type&)(right);
|
||||
return (T&)res;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename T> struct atomic_le_t : public _atomic_base<T>
|
||||
{
|
||||
};
|
||||
|
||||
template<typename T> struct atomic_be_t : public _atomic_base<typename to_be_t<T>::type>
|
||||
{
|
||||
};
|
||||
|
||||
namespace ps3
|
||||
{
|
||||
template<typename T> struct atomic_t : public atomic_be_t<T>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
namespace psv
|
||||
{
|
||||
template<typename T> struct atomic_t : public atomic_le_t<T>
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
using namespace ps3;
|
|
@ -1,23 +1,22 @@
|
|||
#include "stdafx.h"
|
||||
#include "Memory.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
|
||||
void* const m_base_addr = VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS);
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
|
||||
/* OS X uses MAP_ANON instead of MAP_ANONYMOUS */
|
||||
#ifndef MAP_ANONYMOUS
|
||||
#define MAP_ANONYMOUS MAP_ANON
|
||||
#endif
|
||||
|
||||
void* const m_base_addr = ::mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
|
||||
#endif
|
||||
|
||||
namespace vm
|
||||
{
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
void* const g_base_addr = VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS);
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
|
||||
/* OS X uses MAP_ANON instead of MAP_ANONYMOUS */
|
||||
#ifndef MAP_ANONYMOUS
|
||||
#define MAP_ANONYMOUS MAP_ANON
|
||||
#endif
|
||||
|
||||
void* const g_base_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
|
||||
#endif
|
||||
|
||||
bool check_addr(u32 addr)
|
||||
{
|
||||
// Checking address before using it is unsafe.
|
||||
|
@ -28,20 +27,120 @@ namespace vm
|
|||
//TODO
|
||||
bool map(u32 addr, u32 size, u32 flags)
|
||||
{
|
||||
return false;
|
||||
return Memory.Map(addr, size);
|
||||
}
|
||||
|
||||
bool unmap(u32 addr, u32 size, u32 flags)
|
||||
{
|
||||
return false;
|
||||
return Memory.Unmap(addr);
|
||||
}
|
||||
|
||||
u32 alloc(u32 size)
|
||||
u32 alloc(u32 addr, u32 size, memory_location location)
|
||||
{
|
||||
return 0;
|
||||
return g_locations[location].fixed_allocator(addr, size);
|
||||
}
|
||||
|
||||
void unalloc(u32 addr)
|
||||
u32 alloc(u32 size, memory_location location)
|
||||
{
|
||||
return g_locations[location].allocator(size);
|
||||
}
|
||||
|
||||
void dealloc(u32 addr, memory_location location)
|
||||
{
|
||||
return g_locations[location].deallocator(addr);
|
||||
}
|
||||
|
||||
namespace ps3
|
||||
{
|
||||
u32 main_alloc(u32 size)
|
||||
{
|
||||
return Memory.MainMem.AllocAlign(size, 1);
|
||||
}
|
||||
u32 main_fixed_alloc(u32 addr, u32 size)
|
||||
{
|
||||
return Memory.MainMem.AllocFixed(addr, size) ? addr : 0;
|
||||
}
|
||||
void main_dealloc(u32 addr)
|
||||
{
|
||||
Memory.MainMem.Free(addr);
|
||||
}
|
||||
|
||||
u32 g_stack_offset = 0;
|
||||
|
||||
u32 stack_alloc(u32 size)
|
||||
{
|
||||
return Memory.StackMem.AllocAlign(size, 0x10);
|
||||
}
|
||||
u32 stack_fixed_alloc(u32 addr, u32 size)
|
||||
{
|
||||
return Memory.StackMem.AllocFixed(addr, size) ? addr : 0;
|
||||
}
|
||||
void stack_dealloc(u32 addr)
|
||||
{
|
||||
Memory.StackMem.Free(addr);
|
||||
}
|
||||
|
||||
u32 sprx_alloc(u32 size)
|
||||
{
|
||||
return Memory.SPRXMem.AllocAlign(size, 1);
|
||||
}
|
||||
u32 sprx_fixed_alloc(u32 addr, u32 size)
|
||||
{
|
||||
return Memory.SPRXMem.AllocFixed(Memory.SPRXMem.GetStartAddr() + addr, size) ? Memory.SPRXMem.GetStartAddr() + addr : 0;
|
||||
}
|
||||
void sprx_dealloc(u32 addr)
|
||||
{
|
||||
Memory.SPRXMem.Free(addr);
|
||||
}
|
||||
|
||||
u32 user_space_alloc(u32 size)
|
||||
{
|
||||
return Memory.PRXMem.AllocAlign(size, 1);
|
||||
}
|
||||
u32 user_space_fixed_alloc(u32 addr, u32 size)
|
||||
{
|
||||
return Memory.PRXMem.AllocFixed(addr, size) ? addr : 0;
|
||||
}
|
||||
void user_space_dealloc(u32 addr)
|
||||
{
|
||||
Memory.PRXMem.Free(addr);
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
Memory.Init(Memory_PS3);
|
||||
}
|
||||
}
|
||||
|
||||
namespace psv
|
||||
{
|
||||
void init()
|
||||
{
|
||||
Memory.Init(Memory_PSV);
|
||||
}
|
||||
}
|
||||
|
||||
namespace psp
|
||||
{
|
||||
void init()
|
||||
{
|
||||
Memory.Init(Memory_PSP);
|
||||
}
|
||||
}
|
||||
|
||||
location_info g_locations[memory_location_count] =
|
||||
{
|
||||
{ 0x00010000, 0x2FFF0000, ps3::main_alloc, ps3::main_fixed_alloc, ps3::main_dealloc },
|
||||
{ 0xD0000000, 0x10000000, ps3::stack_alloc, ps3::stack_fixed_alloc, ps3::stack_dealloc },
|
||||
|
||||
//remove me
|
||||
{ 0x00010000, 0x2FFF0000, ps3::sprx_alloc, ps3::sprx_fixed_alloc, ps3::sprx_dealloc },
|
||||
|
||||
{ 0x30000000, 0x10000000, ps3::user_space_alloc, ps3::user_space_fixed_alloc, ps3::user_space_dealloc },
|
||||
};
|
||||
|
||||
void close()
|
||||
{
|
||||
Memory.Close();
|
||||
}
|
||||
}
|
|
@ -1,22 +1,35 @@
|
|||
#pragma once
|
||||
#include "Memory.h"
|
||||
|
||||
namespace vm
|
||||
{
|
||||
enum memory_location : uint
|
||||
{
|
||||
main,
|
||||
stack,
|
||||
|
||||
//remove me
|
||||
sprx,
|
||||
|
||||
user_space,
|
||||
|
||||
memory_location_count
|
||||
};
|
||||
|
||||
static void set_stack_size(u32 size) {}
|
||||
static void initialize_stack() {}
|
||||
|
||||
extern void* const g_base_addr;
|
||||
bool map(u32 addr, u32 size, u32 flags);
|
||||
bool unmap(u32 addr, u32 size = 0, u32 flags = 0);
|
||||
u32 alloc(u32 size);
|
||||
void unalloc(u32 addr);
|
||||
u32 alloc(u32 size, memory_location location = user_space);
|
||||
u32 alloc(u32 addr, u32 size, memory_location location = user_space);
|
||||
void dealloc(u32 addr, memory_location location = user_space);
|
||||
|
||||
template<typename T>
|
||||
template<typename T = void>
|
||||
T* const get_ptr(u32 addr)
|
||||
{
|
||||
return (T*)((u8*)m_base_addr + addr);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* const get_ptr(u64 addr)
|
||||
{
|
||||
return get_ptr<T>((u32)addr);
|
||||
return (T*)((u8*)g_base_addr + addr);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
|
@ -25,59 +38,35 @@ namespace vm
|
|||
return *get_ptr<T>(addr);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T& get_ref(u64 addr)
|
||||
{
|
||||
return get_ref<T>((u32)addr);
|
||||
}
|
||||
|
||||
namespace ps3
|
||||
{
|
||||
void init();
|
||||
|
||||
static u8 read8(u32 addr)
|
||||
{
|
||||
return *((u8*)m_base_addr + addr);
|
||||
}
|
||||
|
||||
static u8 read8(u64 addr)
|
||||
{
|
||||
return read8((u32)addr);
|
||||
return *((u8*)g_base_addr + addr);
|
||||
}
|
||||
|
||||
static void write8(u32 addr, u8 value)
|
||||
{
|
||||
*((u8*)m_base_addr + addr) = value;
|
||||
}
|
||||
|
||||
static void write8(u64 addr, u8 value)
|
||||
{
|
||||
write8((u32)addr, value);
|
||||
*((u8*)g_base_addr + addr) = value;
|
||||
}
|
||||
|
||||
static u16 read16(u32 addr)
|
||||
{
|
||||
return re16(*(u16*)((u8*)m_base_addr + addr));
|
||||
return re16(*(u16*)((u8*)g_base_addr + addr));
|
||||
}
|
||||
|
||||
static u16 read16(u64 addr)
|
||||
static void write16(u32 addr, be_t<u16> value)
|
||||
{
|
||||
return read16((u32)addr);
|
||||
}
|
||||
|
||||
static void write16(u32 addr, u16 value)
|
||||
{
|
||||
*(u16*)((u8*)m_base_addr + addr) = re16(value);
|
||||
}
|
||||
|
||||
static void write16(u64 addr, u16 value)
|
||||
{
|
||||
write16((u32)addr, value);
|
||||
*(be_t<u16>*)((u8*)g_base_addr + addr) = value;
|
||||
}
|
||||
|
||||
static u32 read32(u32 addr)
|
||||
{
|
||||
if (addr < RAW_SPU_BASE_ADDR || (addr % RAW_SPU_OFFSET) < RAW_SPU_PROB_OFFSET)
|
||||
{
|
||||
return re32(*(u32*)((u8*)m_base_addr + addr));
|
||||
return re32(*(u32*)((u8*)g_base_addr + addr));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -85,16 +74,11 @@ namespace vm
|
|||
}
|
||||
}
|
||||
|
||||
static u32 read32(u64 addr)
|
||||
{
|
||||
return read32((u32)addr);
|
||||
}
|
||||
|
||||
static void write32(u32 addr, u32 value)
|
||||
static void write32(u32 addr, be_t<u32> value)
|
||||
{
|
||||
if (addr < RAW_SPU_BASE_ADDR || (addr % RAW_SPU_OFFSET) < RAW_SPU_PROB_OFFSET)
|
||||
{
|
||||
*(u32*)((u8*)m_base_addr + addr) = re32(value);
|
||||
*(be_t<u32>*)((u8*)g_base_addr + addr) = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -102,106 +86,170 @@ namespace vm
|
|||
}
|
||||
}
|
||||
|
||||
static void write32(u64 addr, u32 value)
|
||||
{
|
||||
write32((u32)addr, value);
|
||||
}
|
||||
|
||||
static u64 read64(u32 addr)
|
||||
{
|
||||
return re64(*(u64*)((u8*)m_base_addr + addr));
|
||||
return re64(*(u64*)((u8*)g_base_addr + addr));
|
||||
}
|
||||
|
||||
static u64 read64(u64 addr)
|
||||
static void write64(u32 addr, be_t<u64> value)
|
||||
{
|
||||
return read64((u32)addr);
|
||||
*(be_t<u64>*)((u8*)g_base_addr + addr) = value;
|
||||
}
|
||||
|
||||
static void write16(u32 addr, u16 value)
|
||||
{
|
||||
write16(addr, be_t<u16>::make(value));
|
||||
}
|
||||
|
||||
static void write32(u32 addr, u32 value)
|
||||
{
|
||||
write32(addr, be_t<u32>::make(value));
|
||||
}
|
||||
|
||||
static void write64(u32 addr, u64 value)
|
||||
{
|
||||
*(u64*)((u8*)m_base_addr + addr) = re64(value);
|
||||
}
|
||||
|
||||
static void write64(u64 addr, u64 value)
|
||||
{
|
||||
write64((u32)addr, value);
|
||||
write64(addr, be_t<u64>::make(value));
|
||||
}
|
||||
|
||||
static u128 read128(u32 addr)
|
||||
{
|
||||
return re128(*(u128*)((u8*)m_base_addr + addr));
|
||||
}
|
||||
|
||||
static u128 read128(u64 addr)
|
||||
{
|
||||
return read128((u32)addr);
|
||||
return re128(*(u128*)((u8*)g_base_addr + addr));
|
||||
}
|
||||
|
||||
static void write128(u32 addr, u128 value)
|
||||
{
|
||||
*(u128*)((u8*)m_base_addr + addr) = re128(value);
|
||||
}
|
||||
|
||||
static void write128(u64 addr, u128 value)
|
||||
{
|
||||
write128((u32)addr, value);
|
||||
*(u128*)((u8*)g_base_addr + addr) = re128(value);
|
||||
}
|
||||
}
|
||||
|
||||
namespace psv
|
||||
{
|
||||
void init();
|
||||
|
||||
static u8 read8(u32 addr)
|
||||
{
|
||||
return *((u8*)m_base_addr + addr);
|
||||
return *((u8*)g_base_addr + addr);
|
||||
}
|
||||
|
||||
static void write8(u32 addr, u8 value)
|
||||
{
|
||||
*((u8*)m_base_addr + addr) = value;
|
||||
*((u8*)g_base_addr + addr) = value;
|
||||
}
|
||||
|
||||
static u16 read16(u32 addr)
|
||||
{
|
||||
return *(u16*)((u8*)m_base_addr + addr);
|
||||
return *(u16*)((u8*)g_base_addr + addr);
|
||||
}
|
||||
|
||||
static void write16(u32 addr, u16 value)
|
||||
{
|
||||
*(u16*)((u8*)m_base_addr + addr) = value;
|
||||
*(u16*)((u8*)g_base_addr + addr) = value;
|
||||
}
|
||||
|
||||
static u32 read32(u32 addr)
|
||||
{
|
||||
return *(u32*)((u8*)m_base_addr + addr);
|
||||
return *(u32*)((u8*)g_base_addr + addr);
|
||||
}
|
||||
|
||||
static void write32(u32 addr, u32 value)
|
||||
{
|
||||
*(u32*)((u8*)m_base_addr + addr) = value;
|
||||
*(u32*)((u8*)g_base_addr + addr) = value;
|
||||
}
|
||||
|
||||
static u64 read64(u32 addr)
|
||||
{
|
||||
return *(u64*)((u8*)m_base_addr + addr);
|
||||
return *(u64*)((u8*)g_base_addr + addr);
|
||||
}
|
||||
|
||||
static void write64(u32 addr, u64 value)
|
||||
{
|
||||
*(u64*)((u8*)m_base_addr + addr) = value;
|
||||
*(u64*)((u8*)g_base_addr + addr) = value;
|
||||
}
|
||||
|
||||
static u128 read128(u32 addr)
|
||||
{
|
||||
return *(u128*)((u8*)m_base_addr + addr);
|
||||
return *(u128*)((u8*)g_base_addr + addr);
|
||||
}
|
||||
|
||||
static void write128(u32 addr, u128 value)
|
||||
{
|
||||
*(u128*)((u8*)m_base_addr + addr) = value;
|
||||
*(u128*)((u8*)g_base_addr + addr) = value;
|
||||
}
|
||||
}
|
||||
|
||||
namespace psp
|
||||
{
|
||||
using namespace psv;
|
||||
|
||||
void init();
|
||||
}
|
||||
|
||||
void close();
|
||||
}
|
||||
|
||||
#include "vm_ref.h"
|
||||
#include "vm_ptr.h"
|
||||
#include "vm_var.h"
|
||||
|
||||
namespace vm
|
||||
{
|
||||
struct location_info
|
||||
{
|
||||
u32 addr_offset;
|
||||
u32 size;
|
||||
|
||||
u32(*allocator)(u32 size);
|
||||
u32(*fixed_allocator)(u32 addr, u32 size);
|
||||
void(*deallocator)(u32 addr);
|
||||
|
||||
u32 alloc_offset;
|
||||
|
||||
template<typename T = char>
|
||||
ptr<T> alloc(u32 count) const
|
||||
{
|
||||
return ptr<T>::make(allocator(count * sizeof(T)));
|
||||
}
|
||||
};
|
||||
|
||||
extern location_info g_locations[memory_location_count];
|
||||
|
||||
template<memory_location location = main>
|
||||
location_info& get()
|
||||
{
|
||||
assert(location < memory_location_count);
|
||||
return g_locations[location];
|
||||
}
|
||||
|
||||
class stack
|
||||
{
|
||||
u32 m_begin;
|
||||
u32 m_size;
|
||||
int m_page_size;
|
||||
int m_position;
|
||||
u8 m_align;
|
||||
|
||||
public:
|
||||
void init(u32 begin, u32 size, u32 page_size = 180, u8 align = 0x10)
|
||||
{
|
||||
m_begin = begin;
|
||||
m_size = size;
|
||||
m_page_size = page_size;
|
||||
m_position = 0;
|
||||
m_align = align;
|
||||
}
|
||||
|
||||
u32 alloc_new_page()
|
||||
{
|
||||
assert(m_position + m_page_size < (int)m_size);
|
||||
m_position += (int)m_page_size;
|
||||
return m_begin + m_position;
|
||||
}
|
||||
|
||||
u32 dealloc_new_page()
|
||||
{
|
||||
assert(m_position - m_page_size > 0);
|
||||
m_position -= (int)m_page_size;
|
||||
return m_begin + m_position;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace vm
|
|||
AT m_addr;
|
||||
|
||||
public:
|
||||
typedef T type;
|
||||
typedef typename std::remove_cv<T>::type type;
|
||||
|
||||
_ptr_base operator++ (int)
|
||||
{
|
||||
|
@ -38,41 +38,41 @@ namespace vm
|
|||
return *this;
|
||||
}
|
||||
|
||||
_ptr_base& operator += (int count)
|
||||
_ptr_base& operator += (AT count)
|
||||
{
|
||||
m_addr += count * sizeof(AT);
|
||||
return *this;
|
||||
}
|
||||
|
||||
_ptr_base& operator -= (int count)
|
||||
_ptr_base& operator -= (AT count)
|
||||
{
|
||||
m_addr -= count * sizeof(AT);
|
||||
return *this;
|
||||
}
|
||||
|
||||
_ptr_base operator + (int count) const
|
||||
_ptr_base operator + (typename remove_be_t<AT>::type count) const { return make(m_addr + count * sizeof(AT)); }
|
||||
_ptr_base operator + (typename to_be_t<AT>::type count) const { return make(m_addr + count * sizeof(AT)); }
|
||||
_ptr_base operator - (typename remove_be_t<AT>::type count) const { return make(m_addr - count * sizeof(AT)); }
|
||||
_ptr_base operator - (typename to_be_t<AT>::type count) const { return make(m_addr - count * sizeof(AT)); }
|
||||
|
||||
__forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; }
|
||||
__forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; }
|
||||
__forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; }
|
||||
__forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; }
|
||||
__forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; }
|
||||
__forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; }
|
||||
__forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; }
|
||||
__forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; }
|
||||
explicit operator bool() const { return m_addr != 0; }
|
||||
|
||||
__forceinline _ptr_base<T, lvl - 1, std::conditional<is_be_t<T>::value, typename to_be_t<AT>::type, AT>>& operator *() const
|
||||
{
|
||||
return make(m_addr + count * sizeof(AT));
|
||||
return vm::get_ref<_ptr_base<T, lvl - 1, std::conditional<is_be_t<T>::value, typename to_be_t<AT>::type, AT>>>(m_addr);
|
||||
}
|
||||
|
||||
_ptr_base operator - (int count) const
|
||||
__forceinline _ptr_base<T, lvl - 1, std::conditional<is_be_t<T>::value, typename to_be_t<AT>::type, AT>>& operator [](AT index) const
|
||||
{
|
||||
return make(m_addr - count * sizeof(AT));
|
||||
}
|
||||
|
||||
__forceinline _ptr_base<T, lvl - 1, AT>& operator *() const
|
||||
{
|
||||
return vm::get_ref<_ptr_base<T, lvl - 1, AT>>(m_addr);
|
||||
}
|
||||
|
||||
__forceinline _ptr_base<T, lvl - 1, AT>& operator [](int index) const
|
||||
{
|
||||
return vm::get_ref<_ptr_base<T, lvl - 1, AT>>(m_addr + sizeof(AT) * index);
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return m_addr != 0;
|
||||
return vm::get_ref<_ptr_base<T, lvl - 1, std::conditional<is_be_t<T>::value, typename to_be_t<AT>::type, AT>>>(m_addr + sizeof(AT)* index);
|
||||
}
|
||||
|
||||
//typedef typename invert_be_t<AT>::type AT2;
|
||||
|
@ -80,7 +80,7 @@ namespace vm
|
|||
template<typename AT2>
|
||||
operator const _ptr_base<T, lvl, AT2>() const
|
||||
{
|
||||
typename std::remove_const<AT2>::type addr; addr = m_addr;
|
||||
typename std::remove_const<AT2>::type addr = convert_le_be<AT2>(m_addr);
|
||||
return (_ptr_base<T, lvl, AT2>&)addr;
|
||||
}
|
||||
|
||||
|
@ -108,6 +108,8 @@ namespace vm
|
|||
AT m_addr;
|
||||
|
||||
public:
|
||||
typedef typename std::remove_cv<T>::type type;
|
||||
|
||||
__forceinline T* const operator -> () const
|
||||
{
|
||||
return vm::get_ptr<T>(m_addr);
|
||||
|
@ -139,38 +141,49 @@ namespace vm
|
|||
return *this;
|
||||
}
|
||||
|
||||
_ptr_base& operator += (int count)
|
||||
_ptr_base& operator += (AT count)
|
||||
{
|
||||
m_addr += count * sizeof(T);
|
||||
return *this;
|
||||
}
|
||||
|
||||
_ptr_base& operator -= (int count)
|
||||
_ptr_base& operator -= (AT count)
|
||||
{
|
||||
m_addr -= count * sizeof(T);
|
||||
return *this;
|
||||
}
|
||||
|
||||
_ptr_base operator + (int count) const
|
||||
{
|
||||
return make(m_addr + count * sizeof(T));
|
||||
}
|
||||
|
||||
_ptr_base operator - (int count) const
|
||||
{
|
||||
return make(m_addr - count * sizeof(T));
|
||||
}
|
||||
_ptr_base operator + (typename remove_be_t<AT>::type count) const { return make(m_addr + count * sizeof(T)); }
|
||||
_ptr_base operator + (typename to_be_t<AT>::type count) const { return make(m_addr + count * sizeof(T)); }
|
||||
_ptr_base operator - (typename remove_be_t<AT>::type count) const { return make(m_addr - count * sizeof(T)); }
|
||||
_ptr_base operator - (typename to_be_t<AT>::type count) const { return make(m_addr - count * sizeof(T)); }
|
||||
|
||||
__forceinline T& operator *() const
|
||||
{
|
||||
return get_ref<T>(m_addr);
|
||||
return vm::get_ref<T>(m_addr);
|
||||
}
|
||||
|
||||
__forceinline T& operator [](int index) const
|
||||
__forceinline T& operator [](typename remove_be_t<AT>::type index) const
|
||||
{
|
||||
return get_ref<T>(m_addr + sizeof(T) * index);
|
||||
return vm::get_ref<T>(m_addr + sizeof(T)* index);
|
||||
}
|
||||
|
||||
__forceinline T& operator [](typename to_be_t<AT>::forced_type index) const
|
||||
{
|
||||
return vm::get_ref<T>(m_addr + sizeof(T)* index);
|
||||
}
|
||||
|
||||
__forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; }
|
||||
__forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; }
|
||||
__forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; }
|
||||
__forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; }
|
||||
__forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; }
|
||||
__forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; }
|
||||
__forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; }
|
||||
__forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; }
|
||||
explicit operator bool() const { return m_addr != 0; }
|
||||
explicit operator T*() const { return get_ptr(); }
|
||||
|
||||
/*
|
||||
operator _ref_base<T, AT>()
|
||||
{
|
||||
|
@ -188,26 +201,28 @@ namespace vm
|
|||
return m_addr;
|
||||
}
|
||||
|
||||
void set(const AT value)
|
||||
template<typename U>
|
||||
void set(U&& value)
|
||||
{
|
||||
m_addr = value;
|
||||
m_addr = convert_le_be<AT>(value);
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
/*
|
||||
operator T*() const
|
||||
{
|
||||
return m_addr != 0;
|
||||
return get_ptr();
|
||||
}
|
||||
|
||||
*/
|
||||
//typedef typename invert_be_t<AT>::type AT2;
|
||||
|
||||
template<typename AT2>
|
||||
operator const _ptr_base<T, 1, AT2>() const
|
||||
{
|
||||
typename std::remove_const<AT2>::type addr; addr = m_addr;
|
||||
typename std::remove_const<AT2>::type addr = convert_le_be<AT2>(m_addr);
|
||||
return (_ptr_base<T, 1, AT2>&)addr;
|
||||
}
|
||||
|
||||
T* const get_ptr() const
|
||||
T* get_ptr() const
|
||||
{
|
||||
return vm::get_ptr<T>(m_addr);
|
||||
}
|
||||
|
@ -236,29 +251,39 @@ namespace vm
|
|||
m_addr = value;
|
||||
}
|
||||
|
||||
void* const get_ptr() const
|
||||
void* get_ptr() const
|
||||
{
|
||||
return vm::get_ptr<void>(m_addr);
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
explicit operator void*() const
|
||||
{
|
||||
return m_addr != 0;
|
||||
return get_ptr();
|
||||
}
|
||||
|
||||
__forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; }
|
||||
__forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; }
|
||||
__forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; }
|
||||
__forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; }
|
||||
__forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; }
|
||||
__forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; }
|
||||
__forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; }
|
||||
__forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; }
|
||||
explicit operator bool() const { return m_addr != 0; }
|
||||
|
||||
//typedef typename invert_be_t<AT>::type AT2;
|
||||
|
||||
template<typename AT2>
|
||||
operator const _ptr_base<void, 1, AT2>() const
|
||||
{
|
||||
typename std::remove_const<AT2>::type addr; addr = m_addr;
|
||||
typename std::remove_const<AT2>::type addr = convert_le_be<AT2>(m_addr);
|
||||
return (_ptr_base<void, 1, AT2>&)addr;
|
||||
}
|
||||
|
||||
template<typename AT2>
|
||||
operator const _ptr_base<const void, 1, AT2>() const
|
||||
{
|
||||
typename std::remove_const<AT2>::type addr; addr = m_addr;
|
||||
typename std::remove_const<AT2>::type addr = convert_le_be<AT2>(m_addr);
|
||||
return (_ptr_base<const void, 1, AT2>&)addr;
|
||||
}
|
||||
|
||||
|
@ -286,22 +311,32 @@ namespace vm
|
|||
m_addr = value;
|
||||
}
|
||||
|
||||
const void* const get_ptr() const
|
||||
const void* get_ptr() const
|
||||
{
|
||||
return vm::get_ptr<const void>(m_addr);
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
explicit operator const void*() const
|
||||
{
|
||||
return m_addr != 0;
|
||||
return get_ptr();
|
||||
}
|
||||
|
||||
__forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; }
|
||||
__forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; }
|
||||
__forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; }
|
||||
__forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; }
|
||||
__forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; }
|
||||
__forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; }
|
||||
__forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; }
|
||||
__forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; }
|
||||
explicit operator bool() const { return m_addr != 0; }
|
||||
|
||||
//typedef typename invert_be_t<AT>::type AT2;
|
||||
|
||||
template<typename AT2>
|
||||
operator const _ptr_base<const void, 1, AT2>() const
|
||||
{
|
||||
typename std::remove_const<AT2>::type addr; addr = m_addr;
|
||||
typename std::remove_const<AT2>::type addr = convert_le_be<AT2>(m_addr);
|
||||
return (_ptr_base<const void, 1, AT2>&)addr;
|
||||
}
|
||||
|
||||
|
@ -335,17 +370,22 @@ namespace vm
|
|||
m_addr = value;
|
||||
}
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return m_addr != 0;
|
||||
}
|
||||
__forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; }
|
||||
__forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; }
|
||||
__forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; }
|
||||
__forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; }
|
||||
__forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; }
|
||||
__forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; }
|
||||
__forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; }
|
||||
__forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; }
|
||||
explicit operator bool() const { return m_addr != 0; }
|
||||
|
||||
//typedef typename invert_be_t<AT>::type AT2;
|
||||
|
||||
template<typename AT2>
|
||||
operator const _ptr_base<RT(*)(T...), 1, AT2>() const
|
||||
{
|
||||
typename std::remove_const<AT2>::type addr; addr = m_addr;
|
||||
typename std::remove_const<AT2>::type addr = convert_le_be<AT2>(m_addr);
|
||||
return (_ptr_base<RT(*)(T...), 1, AT2>&)addr;
|
||||
}
|
||||
|
||||
|
@ -356,7 +396,7 @@ namespace vm
|
|||
|
||||
operator const std::function<RT(T...)>() const
|
||||
{
|
||||
typename std::remove_const<AT>::type addr; addr = m_addr;
|
||||
typename std::remove_const<AT>::type addr = convert_le_be<AT>(m_addr);
|
||||
return [addr](T... args) -> RT { return make(addr)(args...); };
|
||||
}
|
||||
|
||||
|
@ -413,7 +453,7 @@ namespace vm
|
|||
|
||||
namespace ps3
|
||||
{
|
||||
//default pointer for HLE functions (LE ptrerence to BE data)
|
||||
//default pointer for HLE functions (LE pointer to BE data)
|
||||
template<typename T, int lvl = 1, typename AT = u32> struct ptr : public lptrb<T, lvl, AT>
|
||||
{
|
||||
static ptr make(AT addr)
|
||||
|
@ -425,7 +465,7 @@ namespace vm
|
|||
//using lptrb<T, lvl, AT>::operator const _ptr_base<typename to_be_t<T>::type, lvl, AT>;
|
||||
};
|
||||
|
||||
//default pointer for HLE structures (BE ptrerence to BE data)
|
||||
//default pointer for HLE structures (BE pointer to BE data)
|
||||
template<typename T, int lvl = 1, typename AT = u32> struct bptr : public bptrb<T, lvl, AT>
|
||||
{
|
||||
static bptr make(AT addr)
|
||||
|
@ -440,7 +480,7 @@ namespace vm
|
|||
|
||||
namespace psv
|
||||
{
|
||||
//default pointer for HLE functions & structures (LE ptrerence to LE data)
|
||||
//default pointer for HLE functions & structures (LE pointer to LE data)
|
||||
template<typename T, int lvl = 1, typename AT = u32> struct ptr : public lptrl<T, lvl, AT>
|
||||
{
|
||||
static ptr make(AT addr)
|
||||
|
|
|
@ -90,7 +90,7 @@ std::string GLFragmentDecompilerThread::AddConst()
|
|||
return name;
|
||||
}
|
||||
|
||||
auto data = vm::ptr<be_t<u32>>::make(m_addr + m_size + m_offset);
|
||||
auto data = vm::ptr<u32>::make(m_addr + m_size + m_offset);
|
||||
|
||||
m_offset += 4 * 4;
|
||||
u32 x = GetData(data[0]);
|
||||
|
@ -279,7 +279,7 @@ std::string GLFragmentDecompilerThread::BuildCode()
|
|||
|
||||
void GLFragmentDecompilerThread::Task()
|
||||
{
|
||||
auto data = vm::ptr<be_t<u32>>::make(m_addr);
|
||||
auto data = vm::ptr<u32>::make(m_addr);
|
||||
m_size = 0;
|
||||
m_location = 0;
|
||||
m_loop_count = 0;
|
||||
|
|
|
@ -1380,6 +1380,7 @@ void GLGSRender::WriteColorBuffers()
|
|||
glBindBuffer(GL_PIXEL_PACK_BUFFER, g_pbo[i]);
|
||||
glBufferData(GL_PIXEL_PACK_BUFFER, RSXThread::m_width * RSXThread::m_height * 4, 0, GL_STREAM_READ);
|
||||
}
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
WriteColorBufferA();
|
||||
WriteColorBufferB();
|
||||
break;
|
||||
|
@ -1804,11 +1805,9 @@ void GLGSRender::ExecCMD()
|
|||
}
|
||||
}
|
||||
|
||||
if (m_set_two_side_light_enable)
|
||||
{
|
||||
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
|
||||
// TODO: Use other glLightModel functions?
|
||||
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, m_set_two_side_light_enable ? GL_TRUE : GL_FALSE);
|
||||
checkForGlError("glLightModeli");
|
||||
}
|
||||
|
||||
if(m_set_shade_mode)
|
||||
{
|
||||
|
@ -2038,8 +2037,12 @@ void GLGSRender::Flip()
|
|||
glReadPixels(0, 0, RSXThread::m_width, RSXThread::m_height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, 0);
|
||||
checkForGlError("Flip(): glReadPixels(GL_BGRA, GL_UNSIGNED_INT_8_8_8_8)");
|
||||
GLubyte *packed = (GLubyte *)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
|
||||
if (packed)
|
||||
{
|
||||
memcpy(pixels.data(), packed, RSXThread::m_width * RSXThread::m_height * 4);
|
||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||
checkForGlError("Flip(): glUnmapBuffer");
|
||||
}
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
|
||||
src_buffer = pixels.data();
|
||||
|
|
|
@ -90,9 +90,8 @@ struct GLParamArray
|
|||
case PARAM_IN: return "in ";
|
||||
case PARAM_UNIFORM: return "uniform ";
|
||||
case PARAM_CONST: return "const ";
|
||||
default: return "";
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
bool HasParam(const GLParamFlag flag, std::string type, const std::string& name)
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "Utilities/Log.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/RSX/GSManager.h"
|
||||
#include "RSXThread.h"
|
||||
|
||||
#include "Emu/SysCalls/Callback.h"
|
||||
|
@ -45,15 +46,40 @@ void RSXThread::nativeRescale(float width, float height)
|
|||
|
||||
u32 GetAddress(u32 offset, u32 location)
|
||||
{
|
||||
u32 res = 0;
|
||||
|
||||
switch(location)
|
||||
{
|
||||
case CELL_GCM_LOCATION_LOCAL: return (u32)Memory.RSXFBMem.GetStartAddr() + offset;
|
||||
case CELL_GCM_LOCATION_MAIN: return (u32)Memory.RSXIOMem.RealAddr(Memory.RSXIOMem.GetStartAddr() + offset); // TODO: Error Check?
|
||||
case CELL_GCM_LOCATION_LOCAL:
|
||||
{
|
||||
res = (u32)Memory.RSXFBMem.GetStartAddr() + offset;
|
||||
break;
|
||||
}
|
||||
case CELL_GCM_LOCATION_MAIN:
|
||||
{
|
||||
res = (u32)Memory.RSXIOMem.RealAddr(offset); // TODO: Error Check?
|
||||
if (res == 0)
|
||||
{
|
||||
LOG_ERROR(RSX, "GetAddress(offset=0x%x): RSXIO memory not mapped", offset);
|
||||
Emu.Pause();
|
||||
break;
|
||||
}
|
||||
|
||||
LOG_ERROR(RSX, "GetAddress(offset=0x%x, location=0x%x)", location);
|
||||
assert(0);
|
||||
return 0;
|
||||
if (Emu.GetGSManager().GetRender().m_strict_ordering[offset >> 20])
|
||||
{
|
||||
_mm_mfence(); // probably doesn't have any effect on current implementation
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
LOG_ERROR(RSX, "GetAddress(offset=0x%x, location=0x%x): invalid location", offset, location);
|
||||
Emu.Pause();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
RSXVertexData::RSXVertexData()
|
||||
|
@ -144,7 +170,7 @@ u32 RSXVertexData::GetTypeSize()
|
|||
|
||||
u32 RSXThread::OutOfArgsCount(const uint x, const u32 cmd, const u32 count, const u32 args_addr)
|
||||
{
|
||||
auto args = vm::ptr<be_t<u32>>::make(args_addr);
|
||||
auto args = vm::ptr<u32>::make(args_addr);
|
||||
std::string debug = GetMethodName(cmd);
|
||||
debug += "(";
|
||||
for(u32 i=0; i<count; ++i) debug += (i ? ", " : "") + fmt::Format("0x%x", ARGS(i));
|
||||
|
@ -211,7 +237,7 @@ u32 RSXThread::OutOfArgsCount(const uint x, const u32 cmd, const u32 count, cons
|
|||
|
||||
void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const u32 count)
|
||||
{
|
||||
auto args = vm::ptr<be_t<u32>>::make(args_addr);
|
||||
auto args = vm::ptr<u32>::make(args_addr);
|
||||
|
||||
#if CMD_DEBUG
|
||||
std::string debug = GetMethodName(cmd);
|
||||
|
@ -239,7 +265,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
case NV406E_SET_CONTEXT_DMA_SEMAPHORE:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV406E_SET_CONTEXT_DMA_SEMAPHORE: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV406E_SET_CONTEXT_DMA_SEMAPHORE: 0x%x", ARGS(0));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -254,7 +280,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
case NV406E_SEMAPHORE_ACQUIRE:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV406E_SEMAPHORE_ACQUIRE: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV406E_SEMAPHORE_ACQUIRE: 0x%x", ARGS(0));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -315,21 +341,21 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
case NV4097_NOTIFY:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV4097_NOTIFY: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV4097_NOTIFY: 0x%x", ARGS(0));
|
||||
}
|
||||
break;
|
||||
|
||||
case NV4097_WAIT_FOR_IDLE:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV4097_WAIT_FOR_IDLE: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV4097_WAIT_FOR_IDLE: 0x%x", ARGS(0));
|
||||
}
|
||||
break;
|
||||
|
||||
case NV4097_PM_TRIGGER:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV4097_PM_TRIGGER: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV4097_PM_TRIGGER: 0x%x", ARGS(0));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -458,7 +484,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
case NV4097_SET_VERTEX_ATTRIB_INPUT_MASK:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV4097_SET_VERTEX_ATTRIB_INPUT_MASK: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV4097_SET_VERTEX_ATTRIB_INPUT_MASK: 0x%x", ARGS(0));
|
||||
|
||||
//VertexData[0].prog.attributeInputMask = ARGS(0);
|
||||
}
|
||||
|
@ -467,7 +493,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
case NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK: 0x%x", ARGS(0));
|
||||
|
||||
//VertexData[0].prog.attributeOutputMask = ARGS(0);
|
||||
//FragmentData.prog.attributeInputMask = ARGS(0)/* & ~0x20*/;
|
||||
|
@ -490,7 +516,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
case NV4097_SET_COLOR_MASK_MRT:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV4097_SET_COLOR_MASK_MRT: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV4097_SET_COLOR_MASK_MRT: 0x%x", ARGS(0));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -829,14 +855,14 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
case NV4097_SET_CLEAR_RECT_HORIZONTAL:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV4097_SET_CLEAR_RECT_HORIZONTAL: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV4097_SET_CLEAR_RECT_HORIZONTAL: 0x%x", ARGS(0));
|
||||
}
|
||||
break;
|
||||
|
||||
case NV4097_SET_CLEAR_RECT_VERTICAL:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV4097_SET_CLEAR_RECT_VERTICAL: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV4097_SET_CLEAR_RECT_VERTICAL: 0x%x", ARGS(0));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -933,7 +959,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
{
|
||||
const u32 a0 = ARGS(0);
|
||||
|
||||
//LOG_WARNING(RSX, "NV4097_SET_BEGIN_END: %x", a0);
|
||||
//LOG_WARNING(RSX, "NV4097_SET_BEGIN_END: 0x%x", a0);
|
||||
|
||||
m_read_buffer = false;
|
||||
|
||||
|
@ -1066,7 +1092,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
case NV4097_INVALIDATE_L2:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV4097_INVALIDATE_L2: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV4097_INVALIDATE_L2: 0x%x", ARGS(0));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1085,7 +1111,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
case NV4097_INVALIDATE_ZCULL:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV4097_INVALIDATE_ZCULL: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV4097_INVALIDATE_ZCULL: 0x%x", ARGS(0));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1249,7 +1275,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
case NV4097_SET_SCULL_CONTROL:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV4097_SET_SCULL_CONTROL: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV4097_SET_SCULL_CONTROL: 0x%x", ARGS(0));
|
||||
|
||||
//This is stencil culling , nothing to do with stencil masking on regular color or depth buffer
|
||||
//const u32 a0 = ARGS(0);
|
||||
|
@ -1287,7 +1313,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
case NV4097_SET_POINT_PARAMS_ENABLE:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_ERROR(RSX, "NV4097_SET_POINT_PARAMS_ENABLE: %x", ARGS(0));
|
||||
LOG_ERROR(RSX, "NV4097_SET_POINT_PARAMS_ENABLE: 0x%x", ARGS(0));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1427,7 +1453,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
case NV4097_SET_SURFACE_PITCH_D:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV4097_SET_SURFACE_PITCH_D: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV4097_SET_SURFACE_PITCH_D: 0x%x", ARGS(0));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1467,7 +1493,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
case NV4097_SET_CONTEXT_DMA_COLOR_D:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV4097_SET_CONTEXT_DMA_COLOR_D: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV4097_SET_CONTEXT_DMA_COLOR_D: 0x%x", ARGS(0));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1481,14 +1507,14 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
case NV4097_SET_CONTEXT_DMA_SEMAPHORE:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV4097_SET_CONTEXT_DMA_SEMAPHORE: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV4097_SET_CONTEXT_DMA_SEMAPHORE: 0x%x", ARGS(0));
|
||||
}
|
||||
break;
|
||||
|
||||
case NV4097_SET_CONTEXT_DMA_NOTIFIES:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV4097_SET_CONTEXT_DMA_NOTIFIES: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV4097_SET_CONTEXT_DMA_NOTIFIES: 0x%x", ARGS(0));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1529,7 +1555,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
const u8 alphaToOne = (a0 >> 8) & 0xf;
|
||||
const u16 sampleMask = a0 >> 16;
|
||||
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_ANTI_ALIASING_CONTROL: %x", a0);
|
||||
LOG_WARNING(RSX, "TODO: NV4097_SET_ANTI_ALIASING_CONTROL: 0x%x", a0);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1599,7 +1625,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
case NV4097_SET_ZCULL_CONTROL0:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV4097_SET_ZCULL_CONTROL0: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV4097_SET_ZCULL_CONTROL0: 0x%x", ARGS(0));
|
||||
|
||||
//m_set_depth_func = true;
|
||||
//m_depth_func = ARGS(0) >> 4;
|
||||
|
@ -1609,7 +1635,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
case NV4097_SET_ZCULL_CONTROL1:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV4097_SET_ZCULL_CONTROL1: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV4097_SET_ZCULL_CONTROL1: 0x%x", ARGS(0));
|
||||
|
||||
//m_set_depth_func = true;
|
||||
//m_depth_func = ARGS(0) >> 4;
|
||||
|
@ -1619,14 +1645,14 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
case NV4097_SET_ZCULL_STATS_ENABLE:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV4097_SET_ZCULL_STATS_ENABLE: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV4097_SET_ZCULL_STATS_ENABLE: 0x%x", ARGS(0));
|
||||
}
|
||||
break;
|
||||
|
||||
case NV4097_ZCULL_SYNC:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV4097_ZCULL_SYNC: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV4097_ZCULL_SYNC: 0x%x", ARGS(0));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1745,7 +1771,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
{
|
||||
const u32 offset = ARGS(0) & 0xffffff;
|
||||
const u8 mode = ARGS(0) >> 24;
|
||||
LOG_WARNING(RSX, "NV4097_SET_RENDER_ENABLE: Offset=%06x, Mode=%x", offset, mode);
|
||||
LOG_WARNING(RSX, "NV4097_SET_RENDER_ENABLE: Offset=0x%06x, Mode=0x%x", offset, mode);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1812,14 +1838,14 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
case NV0039_PITCH_IN:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV0039_PITCH_IN: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV0039_PITCH_IN: 0x%x", ARGS(0));
|
||||
}
|
||||
break;
|
||||
|
||||
case NV0039_BUFFER_NOTIFY:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV0039_BUFFER_NOTIFY: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV0039_BUFFER_NOTIFY: 0x%x", ARGS(0));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1848,7 +1874,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
case NV309E_SET_CONTEXT_DMA_IMAGE:
|
||||
{
|
||||
if (ARGS(0))
|
||||
LOG_WARNING(RSX, "NV309E_SET_CONTEXT_DMA_IMAGE: %x", ARGS(0));
|
||||
LOG_WARNING(RSX, "NV309E_SET_CONTEXT_DMA_IMAGE: 0x%x", ARGS(0));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1947,13 +1973,17 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
|
|||
u8* pixels_src = vm::get_ptr<u8>(GetAddress(offset, m_context_dma_img_src - 0xfeed0000));
|
||||
u8* pixels_dst = vm::get_ptr<u8>(GetAddress(m_dst_offset, m_context_dma_img_dst - 0xfeed0000));
|
||||
|
||||
LOG_WARNING(RSX, "NV3089_IMAGE_IN_SIZE: width=%d, height=%d, pitch=%d, origin=%d, inter=%d, offset=0x%x, u=%d, v=%d", width, height, pitch, origin, inter, offset, u, v);
|
||||
LOG_WARNING(RSX, "*** m_dst_offset=0x%x, m_color: conv_in_h=0x%x, format_src_pitch=0x%x, conv_in_x=0x%x, conv_in_y=0x%x, conv_out_x=0x%x, conv_out_y=0x%x",
|
||||
m_dst_offset, m_color_conv_in_h, m_color_format_src_pitch, m_color_conv_in_x, m_color_conv_in_y, m_color_conv_out_x, m_color_conv_out_y);
|
||||
|
||||
for(u16 y=0; y<m_color_conv_in_h; ++y)
|
||||
{
|
||||
for(u16 x=0; x<m_color_format_src_pitch/4/*m_color_conv_in_w*/; ++x)
|
||||
{
|
||||
const u32 src_offset = (m_color_conv_in_y + y) * m_color_format_src_pitch + (m_color_conv_in_x + x) * 4;
|
||||
const u32 dst_offset = (m_color_conv_out_y + y) * m_color_format_dst_pitch + (m_color_conv_out_x + x) * 4;
|
||||
(u32&)pixels_dst[dst_offset] = (u32&)pixels_src[src_offset];
|
||||
//(u32&)pixels_dst[dst_offset] = (u32&)pixels_src[src_offset];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2201,6 +2231,11 @@ void RSXThread::Task()
|
|||
const u32 count = (cmd >> 18) & 0x7ff;
|
||||
//if(cmd == 0) continue;
|
||||
|
||||
if (Ini.RSXLogging.GetValue())
|
||||
LOG_NOTICE(Log::RSX, "%s (cmd=0x%x)", GetMethodName(cmd & 0xffff).c_str(), cmd);
|
||||
|
||||
//LOG_NOTICE(Log::RSX, "put=0x%x, get=0x%x, cmd=0x%x (%s)", put, get, cmd, GetMethodName(cmd & 0xffff).c_str());
|
||||
|
||||
if(cmd & CELL_GCM_METHOD_FLAG_JUMP)
|
||||
{
|
||||
u32 addr = cmd & ~(CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_NON_INCREMENT);
|
||||
|
@ -2212,7 +2247,7 @@ void RSXThread::Task()
|
|||
{
|
||||
m_call_stack.push(get + 4);
|
||||
u32 offs = cmd & ~CELL_GCM_METHOD_FLAG_CALL;
|
||||
//u32 addr = Memory.RSXIOMem.GetStartAddr() + offs;
|
||||
//u32 addr = offs;
|
||||
//LOG_WARNING(RSX, "rsx call(0x%x) #0x%x - 0x%x - 0x%x", offs, addr, cmd, get);
|
||||
m_ctrl->get = offs;
|
||||
continue;
|
||||
|
@ -2229,19 +2264,19 @@ void RSXThread::Task()
|
|||
if(cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT)
|
||||
{
|
||||
//LOG_WARNING(RSX, "non increment cmd! 0x%x", cmd);
|
||||
inc=0;
|
||||
inc = 0;
|
||||
}
|
||||
|
||||
if(cmd == 0)
|
||||
{
|
||||
//HACK! We couldn't be here
|
||||
//ConLog.Error("null cmd: addr=0x%x, put=0x%x, get=0x%x", Memory.RSXIOMem.GetStartAddr() + get, m_ctrl->put, get);
|
||||
LOG_ERROR(Log::RSX, "null cmd: cmd=0x%x, put=0x%x, get=0x%x (addr=0x%x)", cmd, put, get, (u32)Memory.RSXIOMem.RealAddr(get));
|
||||
//Emu.Pause();
|
||||
//HACK! We shouldn't be here
|
||||
m_ctrl->get = get + (count + 1) * 4;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto args = vm::ptr<be_t<u32>>::make((u32)Memory.RSXIOMem.RealAddr(Memory.RSXIOMem.GetStartAddr() + get + 4));
|
||||
auto args = vm::ptr<u32>::make((u32)Memory.RSXIOMem.RealAddr(get + 4));
|
||||
|
||||
for(u32 i=0; i<count; i++)
|
||||
{
|
||||
|
@ -2295,7 +2330,7 @@ void RSXThread::Init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddres
|
|||
u32 RSXThread::ReadIO32(u32 addr)
|
||||
{
|
||||
u32 value;
|
||||
if (!Memory.RSXIOMem.Read32(Memory.RSXIOMem.GetStartAddr() + addr, &value))
|
||||
if (!Memory.RSXIOMem.Read32(addr, &value))
|
||||
{
|
||||
throw fmt::Format("%s(rsxio_addr=0x%x): RSXIO memory not mapped", __FUNCTION__, addr);
|
||||
}
|
||||
|
@ -2304,7 +2339,7 @@ u32 RSXThread::ReadIO32(u32 addr)
|
|||
|
||||
void RSXThread::WriteIO32(u32 addr, u32 value)
|
||||
{
|
||||
if (!Memory.RSXIOMem.Write32(Memory.RSXIOMem.GetStartAddr() + addr, value))
|
||||
if (!Memory.RSXIOMem.Write32(addr, value))
|
||||
{
|
||||
throw fmt::Format("%s(rsxio_addr=0x%x): RSXIO memory not mapped", __FUNCTION__, addr);
|
||||
}
|
||||
|
|
|
@ -134,6 +134,7 @@ public:
|
|||
u32 m_report_main_addr;
|
||||
|
||||
u32 m_local_mem_addr, m_main_mem_addr;
|
||||
bool m_strict_ordering[0x1000];
|
||||
|
||||
public:
|
||||
uint m_draw_mode;
|
||||
|
|
|
@ -228,15 +228,15 @@ enum CellVideoOutRGBOutputRange
|
|||
|
||||
static const CellVideoOutResolution ResolutionTable[] =
|
||||
{
|
||||
{ be_t<u16>::MakeFromBE(se16(0xffff)), be_t<u16>::MakeFromBE(se16(0xffff)) }, //0 - 0
|
||||
{ be_t<u16>::MakeFromBE(se16(1920)), be_t<u16>::MakeFromBE(se16(1080)) }, //1 - 1
|
||||
{ be_t<u16>::MakeFromBE(se16(1280)), be_t<u16>::MakeFromBE(se16(720)) }, //2 - 2
|
||||
{ be_t<u16>::MakeFromBE(se16(720)), be_t<u16>::MakeFromBE(se16(480)) }, //4 - 3
|
||||
{ be_t<u16>::MakeFromBE(se16(720)), be_t<u16>::MakeFromBE(se16(576)) }, //5 - 4
|
||||
{ be_t<u16>::MakeFromBE(se16(1600)), be_t<u16>::MakeFromBE(se16(1080)) }, //10 - 5
|
||||
{ be_t<u16>::MakeFromBE(se16(1440)), be_t<u16>::MakeFromBE(se16(1080)) }, //11 - 6
|
||||
{ be_t<u16>::MakeFromBE(se16(1280)), be_t<u16>::MakeFromBE(se16(1080)) }, //12 - 7
|
||||
{ be_t<u16>::MakeFromBE(se16(960)), be_t<u16>::MakeFromBE(se16(1080)) }, //13 - 8
|
||||
{ be_t<u16>::make(0xffff), be_t<u16>::make(0xffff) }, //0 - 0
|
||||
{ be_t<u16>::make(1920), be_t<u16>::make(1080) }, //1 - 1
|
||||
{ be_t<u16>::make(1280), be_t<u16>::make(720) }, //2 - 2
|
||||
{ be_t<u16>::make(720), be_t<u16>::make(480) }, //4 - 3
|
||||
{ be_t<u16>::make(720), be_t<u16>::make(576) }, //5 - 4
|
||||
{ be_t<u16>::make(1600), be_t<u16>::make(1080) }, //10 - 5
|
||||
{ be_t<u16>::make(1440), be_t<u16>::make(1080) }, //11 - 6
|
||||
{ be_t<u16>::make(1280), be_t<u16>::make(1080) }, //12 - 7
|
||||
{ be_t<u16>::make(960), be_t<u16>::make(1080) }, //13 - 8
|
||||
};
|
||||
|
||||
inline static u32 ResolutionIdToNum(u32 id)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue