Conflicts fixed

This commit is contained in:
Oil 2014-11-30 12:35:03 +04:00
commit 58787f80a1
237 changed files with 40998 additions and 19637 deletions

1
.gitignore vendored
View File

@ -36,6 +36,7 @@
/ipch /ipch
/rpcs3/Debug /rpcs3/Debug
/rpcs3/Release /rpcs3/Release
/llvm_build
/wxWidgets/lib /wxWidgets/lib
/bin/rpcs3.ini /bin/rpcs3.ini

4
.gitmodules vendored
View File

@ -8,3 +8,7 @@
[submodule "asmjit"] [submodule "asmjit"]
path = asmjit path = asmjit
url = https://github.com/kobalicekp/asmjit url = https://github.com/kobalicekp/asmjit
[submodule "llvm"]
path = llvm
url = https://github.com/llvm-mirror/llvm.git
branch = release_35

View File

@ -27,7 +27,12 @@ before_install:
sudo ./cmake-3.0.0-Linux-i386.sh --skip-license --prefix=/usr; sudo ./cmake-3.0.0-Linux-i386.sh --skip-license --prefix=/usr;
before_script: 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 - mkdir build
- cd build - cd build
- cmake .. - cmake ..

21123
GL/glext.h

File diff suppressed because it is too large Load Diff

View File

@ -29,7 +29,7 @@ __Mac OSX__
### Building ### Building
To initialize the repository don't forget to execute `git submodule update --init` to pull the wxWidgets source. 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__: * __Linux & Mac OSX__:
`cd rpcs3 && cmake CMakeLists.txt && make && cd ../` Then run with `cd bin && ./rpcs3` `cd rpcs3 && cmake CMakeLists.txt && make && cd ../` Then run with `cd bin && ./rpcs3`

View File

@ -69,12 +69,12 @@ void AutoPause::Reload(void)
//Less than 1024 - be regarded as a system call. //Less than 1024 - be regarded as a system call.
//emplace_back may not cause reductant move/copy operation. //emplace_back may not cause reductant move/copy operation.
m_pause_syscall.emplace_back(num); 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 else
{ {
m_pause_function.emplace_back(num); 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(); list.Close();
@ -103,7 +103,7 @@ void AutoPause::TryPause(u32 code) {
if (code == m_pause_syscall[i]) if (code == m_pause_syscall[i])
{ {
Emu.Pause(); 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]) if (code == m_pause_function[i])
{ {
Emu.Pause(); 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
} }
} }
} }

View File

@ -1,20 +1,91 @@
#pragma once #pragma once
#include <emmintrin.h> union _CRT_ALIGN(16) u128
union u128
{ {
u64 _u64[2]; u64 _u64[2];
s64 _s64[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]; u32 _u32[4];
s32 _s32[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]; u16 _u16[8];
s16 _s16[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]; u8 _u8[16];
s8 _s8[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]; float _f[4];
double _d[2]; double _d[2];
__m128 xmm; __m128 vf;
__m128i vi;
class bit_array_128 class bit_array_128
{ {
@ -94,6 +165,11 @@ union u128
return ret; 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) static u128 from32(u32 _0, u32 _1 = 0, u32 _2 = 0, u32 _3 = 0)
{ {
u128 ret; u128 ret;
@ -104,6 +180,25 @@ union u128
return ret; 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) static u128 fromBit(u32 bit)
{ {
u128 ret = {}; u128 ret = {};
@ -111,9 +206,41 @@ union u128
return ret; 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 bool operator == (const u128& right) const
@ -126,19 +253,19 @@ union u128
return (_u64[0] != right._u64[0]) || (_u64[1] != right._u64[1]); 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 u128 operator ~ () const
@ -146,6 +273,12 @@ union u128
return from64(~_u64[0], ~_u64[1]); 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() void clear()
{ {
_u64[1] = _u64[0] = 0; _u64[1] = _u64[0] = 0;
@ -153,7 +286,7 @@ union u128
std::string to_hex() const 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 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 re16(val) _byteswap_ushort(val)
#define re32(val) _byteswap_ulong(val) #define re32(val) _byteswap_ulong(val)
#define re64(val) _byteswap_uint64(val) #define re64(val) _byteswap_uint64(val)
@ -252,7 +451,13 @@ template<typename T, typename T2 = T>
class be_t class be_t
{ {
static_assert(sizeof(T2) == 1 || sizeof(T2) == 2 || sizeof(T2) == 4 || sizeof(T2) == 8, "Bad be_t type"); 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> template<typename Tto, typename Tfrom, int mode>
struct _convert struct _convert
@ -283,59 +488,78 @@ class be_t
return (be_t<Tto>&)res; return (be_t<Tto>&)res;
} }
}; };
public:
typedef T type;
const T& ToBE() const public:
const type& ToBE() const
{ {
return m_data; 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; 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; return (be_t&)data;
} }
static be_t MakeFromBE(const T value) static be_t MakeFromBE(const type value)
{ {
return (be_t&)value; return (be_t&)value;
} }
//template<typename T1> //make be_t from current machine byte ordering
operator const T() const 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 = (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; return *this;
} }
operator type() const
{
return value();
}
template<typename T1> template<typename T1>
operator const be_t<T1>() const 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; } 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; } 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> template<typename T, typename T2 = T>
struct is_be_t : public std::integral_constant<bool, false> {}; 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 //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, value >::type type;
typedef typename _be_type_selector< T, T2, !is_be_t<T, T2>::value >::type forced_type;
}; };
template<typename T> template<typename T>
@ -623,3 +774,51 @@ template<typename T> __forceinline static void Write64(T& f, const u64 data)
{ {
Write64LE(f, re64(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);
}

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <emmintrin.h>
#ifdef _WIN32 #ifdef _WIN32
#define thread_local __declspec(thread) #define thread_local __declspec(thread)
#elif __APPLE__ #elif __APPLE__
@ -13,13 +15,21 @@
#endif #endif
template<size_t size> 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(); const size_t count = (src.size() >= size) ? size - 1 /* truncation */ : src.size();
memcpy(dst, src.c_str(), count); memcpy(dst, src.c_str(), count);
dst[count] = 0; 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__) #if defined(__GNUG__)
#include <cmath> #include <cmath>
#include <stdlib.h> #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 _byteswap_uint64(x) __builtin_bswap64(x)
#define INFINITE 0xFFFFFFFF #define INFINITE 0xFFFFFFFF
#define _CRT_ALIGN(x) __attribute__((aligned(x))) #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) inline uint64_t __umulh(uint64_t a, uint64_t b)
{ {
@ -84,12 +80,257 @@ int clock_gettime(int foo, struct timespec *ts);
#endif #endif
#ifndef InterlockedCompareExchange #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) 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); return _InterlockedCompareExchange((volatile long*)dest, exch, comp);
#endif
} }
static __forceinline uint64_t InterlockedCompareExchange(volatile uint64_t* dest, uint64_t exch, uint64_t comp) 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); return _InterlockedCompareExchange64((volatile long long*)dest, exch, comp);
#endif
} }
#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));
}

View File

@ -24,6 +24,7 @@ namespace Log
HLE, HLE,
PPU, PPU,
SPU, SPU,
ARMv7,
TTY, TTY,
}; };
@ -35,7 +36,7 @@ namespace Log
}; };
//well I'd love make_array() but alas manually counting is not the end of the world //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: " }, { GENERAL, "G: " },
{ LOADER, "LDR: " }, { LOADER, "LDR: " },
{ MEMORY, "MEM: " }, { MEMORY, "MEM: " },
@ -43,6 +44,7 @@ namespace Log
{ HLE, "HLE: " }, { HLE, "HLE: " },
{ PPU, "PPU: " }, { PPU, "PPU: " },
{ SPU, "SPU: " }, { SPU, "SPU: " },
{ ARMv7, "ARM: " },
{ TTY, "TTY: " } { 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::HLE; } } HLE;
static struct { inline operator Log::LogType() { return Log::LogType::PPU; } } PPU; 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::SPU; } } SPU;
static struct { inline operator Log::LogType() { return Log::LogType::ARMv7; } } ARMv7;
static struct { inline operator Log::LogType() { return Log::LogType::TTY; } } TTY; static struct { inline operator Log::LogType() { return Log::LogType::TTY; } } TTY;
inline void log_message(Log::LogType type, Log::LogSeverity sev, const char* text) inline void log_message(Log::LogType type, Log::LogSeverity sev, const char* text)

View File

@ -8,15 +8,3 @@ bool SM_IsAborted()
{ {
return Emu.IsStopped(); return Emu.IsStopped();
} }
void SM_Sleep()
{
if (NamedThreadBase* t = GetCurrentNamedThread())
{
t->WaitForAnySignal();
}
else
{
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "Emu/Memory/atomic_type.h"
bool SM_IsAborted(); bool SM_IsAborted();
void SM_Sleep();
enum SMutexResult enum SMutexResult
{ {
@ -19,25 +19,25 @@ template
< <
typename T, typename T,
const u64 free_value = 0, const u64 free_value = 0,
const u64 dead_value = 0xffffffffffffffffull, const u64 dead_value = 0xffffffffffffffffull
void (*wait)() = SM_Sleep
> >
class SMutexBase class SMutexBase
{ {
static_assert(sizeof(T) == sizeof(std::atomic<T>), "Invalid SMutexBase type"); static_assert(sizeof(T) == sizeof(atomic_le_t<T>), "Invalid SMutexBase type");
std::atomic<T> owner; T owner;
typedef atomic_le_t<T> AT;
public: public:
static const T GetFreeValue() static const T GetFreeValue()
{ {
static const u64 value = free_value; static const u64 value = free_value;
return (const T&)value; return (T&)value;
} }
static const T GetDeadValue() static const T GetDeadValue()
{ {
static const u64 value = dead_value; static const u64 value = dead_value;
return (const T&)value; return (T&)value;
} }
void initialize() void initialize()
@ -45,11 +45,6 @@ public:
owner = GetFreeValue(); owner = GetFreeValue();
} }
SMutexBase()
{
initialize();
}
void finalize() void finalize()
{ {
owner = GetDeadValue(); owner = GetDeadValue();
@ -66,9 +61,9 @@ public:
{ {
return SMR_ABORT; 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) if (old == tid)
{ {
@ -90,9 +85,9 @@ public:
{ {
return SMR_ABORT; 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()) if (old == GetFreeValue())
{ {
@ -121,7 +116,7 @@ public:
default: return res; default: return res;
} }
if (wait != nullptr) wait(); std::this_thread::sleep_for(std::chrono::milliseconds(1));
if (timeout && counter++ > timeout) if (timeout && counter++ > timeout)
{ {
@ -131,5 +126,4 @@ public:
} }
}; };
typedef SMutexBase<u32> typedef SMutexBase<u32> SMutex;
SMutex;

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "Utilities/SMutex.h" static const volatile bool sq_no_wait = true;
template<typename T, u32 SQSize = 666> template<typename T, u32 SQSize = 666>
class SQueue class SQueue
@ -22,18 +22,18 @@ public:
return SQSize; return SQSize;
} }
bool Push(const T& data) bool Push(const T& data, const volatile bool* do_exit)
{ {
while (true) while (true)
{ {
if (m_count >= SQSize) if (m_count >= SQSize)
{ {
if (Emu.IsStopped()) if (Emu.IsStopped() || (do_exit && *do_exit))
{ {
return false; return false;
} }
SM_Sleep(); std::this_thread::sleep_for(std::chrono::milliseconds(1));
continue; continue;
} }
@ -49,18 +49,18 @@ public:
} }
} }
bool Pop(T& data) bool Pop(T& data, const volatile bool* do_exit)
{ {
while (true) while (true)
{ {
if (!m_count) if (!m_count)
{ {
if (Emu.IsStopped()) if (Emu.IsStopped() || (do_exit && *do_exit))
{ {
return false; return false;
} }
SM_Sleep(); std::this_thread::sleep_for(std::chrono::milliseconds(1));
continue; 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() void Clear()
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::mutex> lock(m_mutex);
m_count = 0; m_count = 0;
} }
T& Peek(u32 pos = 0) bool Peek(T& data, const volatile bool* do_exit, u32 pos = 0)
{ {
while (true) while (true)
{ {
if (m_count <= pos) 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; continue;
} }
@ -124,21 +107,7 @@ public:
} }
} }
} }
return m_data[(m_pos + pos) % SQSize]; data = m_data[(m_pos + pos) % SQSize];
} return true;
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];
}
} }
}; };

View File

@ -103,3 +103,34 @@ std::vector<std::string> fmt::rSplit(const std::string& source, const std::strin
} while (true); } while (true);
return ret; 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);
}

View File

@ -192,4 +192,6 @@ namespace fmt{
void Replace(std::string &str, const std::string &searchterm, const std::string& replaceterm); 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> 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);
} }

View File

@ -1,4 +1,5 @@
#include "stdafx.h" #include "stdafx.h"
#include "Emu/System.h"
#include "Log.h" #include "Log.h"
#include "Thread.h" #include "Thread.h"
@ -207,3 +208,61 @@ bool thread::joinable() const
{ {
return m_thr.joinable(); 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();
}
}
}

View File

@ -70,3 +70,106 @@ public:
void join(); void join();
bool joinable() const; 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);
};

View File

@ -21,6 +21,12 @@ std::wstring ConvertUTF8ToWString(const std::string &source) {
} }
#endif #endif
#ifdef _WIN32
#define GET_API_ERROR GetLastError()
#else
#define GET_API_ERROR err
#endif
bool getFileInfo(const char *path, FileInfo *fileInfo) { bool getFileInfo(const char *path, FileInfo *fileInfo) {
// TODO: Expand relative paths? // TODO: Expand relative paths?
fileInfo->fullName = path; fileInfo->fullName = path;
@ -103,14 +109,15 @@ bool rMkpath(const std::string &path)
bool rRmdir(const std::string &dir) bool rRmdir(const std::string &dir)
{ {
#ifdef _WIN32 #ifdef _WIN32
if (!RemoveDirectory(ConvertUTF8ToWString(dir).c_str())) { if (!RemoveDirectory(ConvertUTF8ToWString(dir).c_str()))
LOG_ERROR(GENERAL, "Error deleting directory %s: %i", dir.c_str(), GetLastError()); #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 false;
} }
return true; return true;
#else
rmdir(dir.c_str());
#endif
} }
bool rRename(const std::string &from, const std::string &to) 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) bool rRemoveFile(const std::string &file)
{ {
#ifdef _WIN32 #ifdef _WIN32
if (!DeleteFile(ConvertUTF8ToWString(file).c_str())) { if (!DeleteFile(ConvertUTF8ToWString(file).c_str()))
LOG_ERROR(GENERAL, "Error deleting %s: %i", file.c_str(), GetLastError());
return false;
}
#else #else
int err = unlink(file.c_str()); if (int err = unlink(file.c_str()))
if (err) { #endif
LOG_ERROR(GENERAL, "Error unlinking %s: %i", file.c_str(), err); {
LOG_ERROR(GENERAL, "Error deleting %s: %i", file.c_str(), GET_API_ERROR);
return false; return false;
} }
#endif
return true; return true;
} }

2
asmjit

@ -1 +1 @@
Subproject commit 9ead0cfb4cb5eb1bcf8c12b4a1ea115e438c44fa Subproject commit 1318c9aff7137b30aec7dee2ababb2b313ae0f06

View File

@ -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

1
llvm Submodule

@ -0,0 +1 @@
Subproject commit f55c17bc3395fa7fdbd997d751a55de5228ebd77

View File

@ -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

View File

@ -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>

View File

@ -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>

View File

@ -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
View File

@ -1,6 +1,6 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013 # Visual Studio 2013
VisualStudioVersion = 12.0.21005.1 VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rpcs3", "rpcs3\rpcs3.vcxproj", "{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rpcs3", "rpcs3\rpcs3.vcxproj", "{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}"
ProjectSection(ProjectDependencies) = postProject 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} {7047EE97-7F80-A70D-6147-BC11102DB6F4} = {7047EE97-7F80-A70D-6147-BC11102DB6F4}
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D} = {87B42A9C-3F5C-53D7-9017-2B1CAE39457D} {87B42A9C-3F5C-53D7-9017-2B1CAE39457D} = {87B42A9C-3F5C-53D7-9017-2B1CAE39457D}
{6FCB55A5-563F-4039-1D79-1EB6ED8AAB82} = {6FCB55A5-563F-4039-1D79-1EB6ED8AAB82} {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} {949C6DB8-E638-6EC6-AB31-BCCFD1379E01} = {949C6DB8-E638-6EC6-AB31-BCCFD1379E01}
{74827EBD-93DC-5110-BA95-3F2AB029B6B0} = {74827EBD-93DC-5110-BA95-3F2AB029B6B0} {74827EBD-93DC-5110-BA95-3F2AB029B6B0} = {74827EBD-93DC-5110-BA95-3F2AB029B6B0}
{46333DC3-B4A5-3DCC-E8BF-A3F20ADC56D2} = {46333DC3-B4A5-3DCC-E8BF-A3F20ADC56D2} {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}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "asmjit", "asmjit", "{E2A982F2-4B1A-48B1-8D77-A17A589C58D7}"
EndProject EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "emucore", "rpcs3\emucore.vcxproj", "{C4A10229-4712-4BD2-B63E-50D93C67A038}" 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 EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug - LLVM|x64 = Debug - LLVM|x64
Debug - MemLeak|x64 = Debug - MemLeak|x64 Debug - MemLeak|x64 = Debug - MemLeak|x64
Debug|x64 = Debug|x64 Debug|x64 = Debug|x64
Release - LLVM|x64 = Release - LLVM|x64
Release|x64 = Release|x64 Release|x64 = Release|x64
EndGlobalSection EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution 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.ActiveCfg = Debug - MemLeak|x64
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{70CD65B0-91D6-4FAE-9A7B-4AF55D0D1B12}.Release|x64.Build.0 = 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.ActiveCfg = Debug|x64
{6FCB55A5-563F-4039-1D79-1EB6ED8AAB82}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{6FCB55A5-563F-4039-1D79-1EB6ED8AAB82}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{6FCB55A5-563F-4039-1D79-1EB6ED8AAB82}.Release|x64.Build.0 = 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.ActiveCfg = Debug|x64
{7047EE97-7F80-A70D-6147-BC11102DB6F4}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{7047EE97-7F80-A70D-6147-BC11102DB6F4}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{7047EE97-7F80-A70D-6147-BC11102DB6F4}.Release|x64.Build.0 = 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.ActiveCfg = Debug|x64
{3111D679-7796-23C4-BA0C-271F1145DA24}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{3111D679-7796-23C4-BA0C-271F1145DA24}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{3111D679-7796-23C4-BA0C-271F1145DA24}.Release|x64.Build.0 = 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.ActiveCfg = Debug|x64
{067D9406-2A93-DACA-9449-93A2D356357D}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{067D9406-2A93-DACA-9449-93A2D356357D}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{067D9406-2A93-DACA-9449-93A2D356357D}.Release|x64.Build.0 = 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.ActiveCfg = Debug|x64
{9ED1866B-D4AE-3440-24E4-7A9475B163B2}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{9ED1866B-D4AE-3440-24E4-7A9475B163B2}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{9ED1866B-D4AE-3440-24E4-7A9475B163B2}.Release|x64.Build.0 = 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.ActiveCfg = Debug|x64
{99C9EB95-DB4C-1996-490E-5212EFBF07C3}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{99C9EB95-DB4C-1996-490E-5212EFBF07C3}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{99C9EB95-DB4C-1996-490E-5212EFBF07C3}.Release|x64.Build.0 = 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.ActiveCfg = Debug|x64
{6EDC3B79-D217-F11A-406F-F11D856493F9}.Debug - MemLeak|x64.Build.0 = 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 - MemLeak|x64.Deploy.0 = Debug|x64
{6EDC3B79-D217-F11A-406F-F11D856493F9}.Debug|x64.ActiveCfg = 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}.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.ActiveCfg = Release|x64
{6EDC3B79-D217-F11A-406F-F11D856493F9}.Release|x64.Build.0 = 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.ActiveCfg = Debug|x64
{A9AC9CF5-8E6C-0BA2-0769-6E42EDB88E25}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{A9AC9CF5-8E6C-0BA2-0769-6E42EDB88E25}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{A9AC9CF5-8E6C-0BA2-0769-6E42EDB88E25}.Release|x64.Build.0 = 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.ActiveCfg = Debug|x64
{CD478F02-7550-58A5-E085-CE4BC0C0AD23}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{CD478F02-7550-58A5-E085-CE4BC0C0AD23}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{CD478F02-7550-58A5-E085-CE4BC0C0AD23}.Release|x64.Build.0 = 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.ActiveCfg = Debug|x64
{22B14659-C5B6-B775-868D-A49198FEAD4A}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{22B14659-C5B6-B775-868D-A49198FEAD4A}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{22B14659-C5B6-B775-868D-A49198FEAD4A}.Release|x64.Build.0 = 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.ActiveCfg = Debug|x64
{FAF0CB93-F7CE-A6B8-8342-19CE99BAF774}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{FAF0CB93-F7CE-A6B8-8342-19CE99BAF774}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{FAF0CB93-F7CE-A6B8-8342-19CE99BAF774}.Release|x64.Build.0 = 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.ActiveCfg = Debug|x64
{46333DC3-B4A5-3DCC-E8BF-A3F20ADC56D2}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{46333DC3-B4A5-3DCC-E8BF-A3F20ADC56D2}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{46333DC3-B4A5-3DCC-E8BF-A3F20ADC56D2}.Release|x64.Build.0 = 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.ActiveCfg = Debug|x64
{5C363C34-4741-7036-861C-2E2279CF552E}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{5C363C34-4741-7036-861C-2E2279CF552E}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{5C363C34-4741-7036-861C-2E2279CF552E}.Release|x64.Build.0 = 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.ActiveCfg = Debug|x64
{76169FE8-0814-4F36-6409-699EF1A23001}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{76169FE8-0814-4F36-6409-699EF1A23001}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{76169FE8-0814-4F36-6409-699EF1A23001}.Release|x64.Build.0 = 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.ActiveCfg = Debug|x64
{949C6DB8-E638-6EC6-AB31-BCCFD1379E01}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{949C6DB8-E638-6EC6-AB31-BCCFD1379E01}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{949C6DB8-E638-6EC6-AB31-BCCFD1379E01}.Release|x64.Build.0 = 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.ActiveCfg = Debug|x64
{B87216CD-6C64-1DB0-D900-BC6E745C1DF9}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{B87216CD-6C64-1DB0-D900-BC6E745C1DF9}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{B87216CD-6C64-1DB0-D900-BC6E745C1DF9}.Release|x64.Build.0 = 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.ActiveCfg = Debug|x64
{AFF2C68B-B867-DD50-6AC5-74B09D41F8EA}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{AFF2C68B-B867-DD50-6AC5-74B09D41F8EA}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{AFF2C68B-B867-DD50-6AC5-74B09D41F8EA}.Release|x64.Build.0 = 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.ActiveCfg = Debug|x64
{6FDC76D5-CB44-B9F8-5EF6-C59B020719DF}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{6FDC76D5-CB44-B9F8-5EF6-C59B020719DF}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{6FDC76D5-CB44-B9F8-5EF6-C59B020719DF}.Release|x64.Build.0 = 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.ActiveCfg = Debug|x64
{8BECCA95-C7D7-CFF8-FDB1-4950E9F8E8E6}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{8BECCA95-C7D7-CFF8-FDB1-4950E9F8E8E6}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{8BECCA95-C7D7-CFF8-FDB1-4950E9F8E8E6}.Release|x64.Build.0 = 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.ActiveCfg = Debug|x64
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}.Release|x64.Build.0 = 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.ActiveCfg = Debug|x64
{23E1C437-A951-5943-8639-A17F3CF2E606}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{23E1C437-A951-5943-8639-A17F3CF2E606}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{23E1C437-A951-5943-8639-A17F3CF2E606}.Release|x64.Build.0 = 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.ActiveCfg = Debug|x64
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Release|x64.Build.0 = 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.ActiveCfg = Debug|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Release|x64.Build.0 = 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.ActiveCfg = Debug - MemLeak|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Debug - MemLeak|x64.Build.0 = 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.ActiveCfg = Debug|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Debug|x64.Build.0 = 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.ActiveCfg = Release|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Release|x64.Build.0 = 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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -325,5 +442,6 @@ Global
{23E1C437-A951-5943-8639-A17F3CF2E606} = {5812E712-6213-4372-B095-9EB9BAA1F2DF} {23E1C437-A951-5943-8639-A17F3CF2E606} = {5812E712-6213-4372-B095-9EB9BAA1F2DF}
{74827EBD-93DC-5110-BA95-3F2AB029B6B0} = {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} {AC40FF01-426E-4838-A317-66354CEFAE88} = {E2A982F2-4B1A-48B1-8D77-A17A589C58D7}
{8BC303AB-25BE-4276-8E57-73F171B2D672} = {C8068CE9-D626-4FEA-BEE7-893F06A25BF3}
EndGlobalSection EndGlobalSection
EndGlobal EndGlobal

View File

@ -55,6 +55,7 @@ find_package(GLEW REQUIRED)
find_package(OpenGL REQUIRED) find_package(OpenGL REQUIRED)
find_package(ZLIB REQUIRED) find_package(ZLIB REQUIRED)
find_package(OpenAL REQUIRED) find_package(OpenAL REQUIRED)
find_package(LLVM REQUIRED CONFIG)
include("${wxWidgets_USE_FILE}") include("${wxWidgets_USE_FILE}")
@ -69,6 +70,7 @@ endif()
include_directories( include_directories(
${wxWidgets_INCLUDE_DIRS} ${wxWidgets_INCLUDE_DIRS}
${OPENAL_INCLUDE_DIR} ${OPENAL_INCLUDE_DIR}
${LLVM_INCLUDE_DIRS}
"${RPCS3_SRC_DIR}/../ffmpeg/${PLATFORM_ARCH}/include" "${RPCS3_SRC_DIR}/../ffmpeg/${PLATFORM_ARCH}/include"
"${RPCS3_SRC_DIR}" "${RPCS3_SRC_DIR}"
"${RPCS3_SRC_DIR}/Loader" "${RPCS3_SRC_DIR}/Loader"
@ -77,6 +79,14 @@ ${OPENAL_INCLUDE_DIR}
"${RPCS3_SRC_DIR}/../asmjit/src/asmjit" "${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") link_directories("${RPCS3_SRC_DIR}/../ffmpeg/${PLATFORM_ARCH}/lib")
get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES) get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
@ -97,10 +107,13 @@ RPCS3_SRC
"${RPCS3_SRC_DIR}/../Utilities/*" "${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}) 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 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") set_target_properties(rpcs3 PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${RPCS3_SRC_DIR}/stdafx.h")
cotire(rpcs3) cotire(rpcs3)

548
rpcs3/Crypto/ec.cpp Normal file
View File

@ -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);
}

14
rpcs3/Crypto/ec.h Normal file
View File

@ -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);

View File

@ -8,10 +8,10 @@ SELF_KEY::SELF_KEY(u64 ver, u16 rev, u32 type, const std::string& e, const std::
version = ver; version = ver;
revision = rev; revision = rev;
self_type = type; self_type = type;
hex_to_bytes(erk, e.c_str()); hex_to_bytes(erk, e.c_str(), 0);
hex_to_bytes(riv, r.c_str()); hex_to_bytes(riv, r.c_str(), 0);
hex_to_bytes(pub, pb.c_str()); hex_to_bytes(pub, pb.c_str(), 0);
hex_to_bytes(priv, pr.c_str()); hex_to_bytes(priv, pr.c_str(), 0);
curve_type = ct; curve_type = ct;
} }

View File

@ -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 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 class KeyVault
{ {
std::vector<SELF_KEY> sk_LV0_arr; std::vector<SELF_KEY> sk_LV0_arr;

View File

@ -4,26 +4,20 @@
#include "lz.h" #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)) if (!((*range) >> 24))
{ {
(*range) <<= 8; (*range) <<= 8;
*code = ((*code) << 8) + (*src)++[5]; *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) 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)) unsigned int val = ((*range) >> 8) * (*c);
val *= (*c);
else
val = (val >> 8) * (*c);
*c -= ((*c) >> 3); *c -= ((*c) >> 3);
if (index) (*index) <<= 1; 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) if (index >= 3)
{ {
decode_bit(range, code, &i, src, ptr + 0x18); // Offset 0x978 decode_bit(range, code, &i, src, ptr + 0x18);
if (index >= 4) if (index >= 4)
{ {
decode_bit(range, code, &i, src, ptr + 0x18); // Offset 0x978 decode_bit(range, code, &i, src, ptr + 0x18);
if (index >= 5) if (index >= 5)
{ {
decode_range(range, code, src); 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) if (index >= 1)
{ {
decode_bit(range, code, &i, src, ptr + 0x8); // Offset 0x968 decode_bit(range, code, &i, src, ptr + 0x8);
if (index >= 2) 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) if (index >= 3)
{ {
decode_bit(range, code, &i, src, ptr); // Offset 0x8A8 decode_bit(range, code, &i, src, ptr + 4);
if (index >= 4) if (index >= 4)
{ {
decode_bit(range, code, &i, src, ptr); // Offset 0x8A8 decode_bit(range, code, &i, src, ptr + 4);
if (index >= 5) if (index >= 5)
{ {
decode_range(range, code, src); 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) 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) 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; int result;
unsigned char *tmp = new unsigned char[0xA70]; unsigned char *tmp = new unsigned char[0xCC8];
int offset = 0; int offset = 0;
int bit_flag = 0; int bit_flag = 0;
@ -159,11 +153,11 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
else else
{ {
// Set up a temporary buffer (sliding window). // Set up a temporary buffer (sliding window).
memset(tmp, 0x80, 0xA60); memset(tmp, 0x80, 0xCA8);
while (1) while (1)
{ {
// Start reading at 0x920. // Start reading at 0xB68.
tmp_sect1 = tmp + offset + 0x920; tmp_sect1 = tmp + offset + 0xB68;
if (!decode_bit(&range, &code, 0, &in, tmp_sect1)) // Raw char. if (!decode_bit(&range, &code, 0, &in, tmp_sect1)) // Raw char.
{ {
// Adjust offset and check for stream end. // 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; int index = -1;
// Identify the data length bit field. // Identify the data length bit field.
do { do
{
tmp_sect1 += 8; tmp_sect1 += 8;
bit_flag = decode_bit(&range, &code, 0, &in, tmp_sect1); bit_flag = decode_bit(&range, &code, 0, &in, tmp_sect1);
index += bit_flag; index += bit_flag;
} while ((bit_flag != 0) && (index < 6)); } while ((bit_flag != 0) && (index < 6));
// Default block size is 0x40. // Default block size is 0x160.
int b_size = 0x40; int b_size = 0x160;
tmp_sect2 = tmp + index + 0x7F1; tmp_sect2 = tmp + index + 0x7F1;
// If the data length was found, parse it as a number. // If the data length was found, parse it as a number.
if ((index >= 0) || (bit_flag != 0)) if ((index >= 0) || (bit_flag != 0))
{ {
// Locate next section. // Locate next section.
int sect = (index << 5) | (((((start - out)) << index) & 3) << 3) | (offset & 7); int sect = (index << 5) | (((((int)(start - out)) << index) & 3) << 3) | (offset & 7);
tmp_sect1 = tmp + 0x960 + sect; tmp_sect1 = tmp + 0xBA8 + sect;
// Decode the data length (8 bit fields). // Decode the data length (8 bit fields).
data_length = decode_number(tmp_sect1, index, &bit_flag, &range, &code, &in); data_length = decode_number(tmp_sect1, index, &bit_flag, &range, &code, &in);
if (data_length == 0xFF) return (start - out); // End of stream.
// 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.
} }
} else { else
{
// Assume one byte of advance. // Assume one byte of advance.
data_length = 1; 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 diff = 0;
int shift = 1; int shift = 1;
// Identify the data offset bit field. // Identify the data offset bit field.
do { do
{
diff = (shift << 4) - b_size; diff = (shift << 4) - b_size;
bit_flag = decode_bit(&range, &code, &shift, &in, tmp_sect2 + (shift << 3)); bit_flag = decode_bit(&range, &code, &shift, &in, tmp_sect2 + (shift << 3));
} while (diff < 0); } while (diff < 0);
@ -235,11 +235,13 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
if (bit_flag == 0) diff -= 8; if (bit_flag == 0) diff -= 8;
// Locate section. // Locate section.
tmp_sect3 = tmp + 0x8A8 + diff; tmp_sect3 = tmp + 0x928 + diff;
// Decode the data offset (1 bit fields). // Decode the data offset (1 bit fields).
data_offset = decode_word(tmp_sect3, diff, &bit_flag, &range, &code, &in); data_offset = decode_word(tmp_sect3, diff, &bit_flag, &range, &code, &in);
} else { }
else
{
// Assume one byte of advance. // Assume one byte of advance.
data_offset = 1; 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; offset = ((((int)(buf_end - out)) + 1) & 1) + 6;
// Copy data. // Copy data.
do { do
{
*start++ = *buf_start++; *start++ = *buf_start++;
} while (start < buf_end); } while (start < buf_end);

View File

@ -1,7 +1,14 @@
#pragma once #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 LempelZivMarkov based compression.
#include <string.h> #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_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_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); int decode_word(unsigned char *ptr, int index, int *bit_flag, unsigned int *range, unsigned int *code, unsigned char **src);

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
/** /**
* \file sha1.h * \file sha1.h
* *

View File

@ -1,5 +1,4 @@
#include "stdafx.h" #include "stdafx.h"
#include "utils.h"
#include "key_vault.h" #include "key_vault.h"
#include "unedat.h" #include "unedat.h"
#include "Utilities/Log.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) 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) { switch (mode) {
case 0x10000000: case 0x10000000:
// Encrypted ERK. // 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) 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) { switch (mode) {
case 0x10000000: case 0x10000000:
// Encrypted HASH. // 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. // Setup buffers for key, iv and hash.
unsigned char key_final[0x10] = {}; unsigned char key_final[0x10] = {};
@ -77,29 +76,30 @@ bool crypto(int hash_mode, int crypto_mode, int version, unsigned char *in, unsi
} }
else else
{ {
LOG_ERROR(LOADER, "EDAT: Unknown crypto algorithm!\n"); LOG_ERROR(LOADER, "EDAT: Unknown crypto algorithm!");
return false; return false;
} }
if ((hash_mode & 0xFF) == 0x01) // 0x14 SHA1-HMAC 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 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 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 else
{ {
LOG_ERROR(LOADER, "EDAT: Unknown hashing algorithm!\n"); LOG_ERROR(LOADER, "EDAT: Unknown hashing algorithm!");
return false; return false;
} }
} }
// EDAT/SDAT functions.
unsigned char* dec_section(unsigned char* metadata) unsigned char* dec_section(unsigned char* metadata)
{ {
unsigned char *dec = new unsigned char[0x10]; unsigned char *dec = new unsigned char[0x10];
@ -135,11 +135,11 @@ unsigned char* get_block_key(int block, NPD_HEADER *npd)
return dest_key; return dest_key;
} }
// EDAT/SDAT functions. // EDAT/SDAT decryption.
int decrypt_data(rFile *in, rFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd, unsigned char* crypt_key, bool verbose) 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. // 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_section_size = ((edat->flags & EDAT_COMPRESSED_FLAG) != 0 || (edat->flags & EDAT_FLAG_0x20) != 0) ? 0x20 : 0x10;
int metadata_offset = 0x100; 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 *b_key;
unsigned char *iv; 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] = {}; unsigned char empty_iv[0x10] = {};
// Decrypt the metadata. // 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); memset(hash_result, 0, 0x14);
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;
}
if ((edat->flags & EDAT_COMPRESSED_FLAG) != 0) 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]; unsigned char metadata[0x20];
memset(metadata, 0, 0x20);
in->Read(metadata, 0x20); in->Read(metadata, 0x20);
// If the data is compressed, decrypt the metadata. // 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); 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]); length = swap32(*(int*)&result[8]);
compression_end = swap32(*(int*)&result[12]); compression_end = swap32(*(int*)&result[12]);
delete[] result; delete[] result;
}
memcpy(hash_result, metadata, 0x10); memcpy(hash_result, metadata, 0x10);
} }
else if ((edat->flags & EDAT_FLAG_0x20) != 0) else if ((edat->flags & EDAT_FLAG_0x20) != 0)
{ {
// If FLAG 0x20, the metadata precedes each data block. // 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]; unsigned char metadata[0x20];
memset(metadata, 0, 0x20);
in->Read(metadata, 0x20); in->Read(metadata, 0x20);
memcpy(hash_result, metadata, 0x14);
// If FLAG 0x20 is set, apply custom xor. // If FLAG 0x20 is set, apply custom xor.
for (int j = 0; j < 0x10; j++) { int j;
hash_result[j] = (unsigned char)(metadata[j] ^ metadata[j+0x10]); 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; length = edat->block_size;
if ((i == (block_num - 1)) && (edat->file_size % 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 else
{ {
metadata_sec_offset = metadata_offset + (unsigned long long) i * metadata_section_size;
in->Seek(metadata_sec_offset);
in->Read(hash_result, 0x10); 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; length = edat->block_size;
if ((i == (block_num - 1)) && (edat->file_size % 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. // Locate the real data.
int pad_length = length; int pad_length = length;
length = (int) ((pad_length + 0xF) & 0xFFFFFFF0); length = (int)((pad_length + 0xF) & 0xFFFFFFF0);
in->Seek(offset);
// Setup buffers for decryption and read the data. // Setup buffers for decryption and read the data.
enc_data = new unsigned char[length]; enc_data = new unsigned char[length];
dec_data = new unsigned char[length]; dec_data = new unsigned char[length];
unsigned char key_result[0x10]; memset(enc_data, 0, length);
unsigned char hash[0x10]; memset(dec_data, 0, length);
memset(hash, 0, 0x10);
memset(key_result, 0, 0x10);
in->Seek(offset);
in->Read(enc_data, length); in->Read(enc_data, length);
// Generate a key for the current block. // 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 is null if NPD version is 1 or 0.
iv = (npd->version <= 1) ? empty_iv : npd->digest; iv = (npd->version <= 1) ? empty_iv : npd->digest;
// Call main crypto routine on this data block. // 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. // 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); memset(decomp_data, 0, decomp_size);
if (verbose) 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); out->Write(decomp_data, res);
if (verbose) if (verbose)
{ {
LOG_NOTICE(LOADER, "EDAT: Compressed block size: %d\n", pad_length); LOG_NOTICE(LOADER, "EDAT: Compressed block size: %d", pad_length);
LOG_NOTICE(LOADER, "EDAT: Decompressed block size: %d\n", res); LOG_NOTICE(LOADER, "EDAT: Decompressed block size: %d", res);
} }
edat->file_size -= 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) if (res < 0)
{ {
LOG_ERROR(LOADER, "EDAT: Decompression failed!\n"); LOG_ERROR(LOADER, "EDAT: Decompression failed!");
return 1; return 1;
} }
else else
LOG_SUCCESS(LOADER, "EDAT: Data successfully decompressed!\n"); LOG_NOTICE(LOADER, "EDAT: Successfully decompressed!");
} }
delete[] decomp_data; delete[] decomp_data;
@ -309,158 +340,262 @@ int decrypt_data(rFile *in, rFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd,
return 0; 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) f->Seek(0);
return false; 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) if (edat->flags & 0x7EFFFFFE)
{ {
LOG_ERROR(LOADER, "EDAT: Bad header flags!\n"); LOG_ERROR(LOADER, "EDAT: Bad header flags!");
return false; return 1;
} }
} }
else if (npd->version == 2) else if (npd->version == 2)
{ {
if (edat->flags & 0x7EFFFFE0) if (edat->flags & 0x7EFFFFE0)
{ {
LOG_ERROR(LOADER, "EDAT: Bad header flags!\n"); LOG_ERROR(LOADER, "EDAT: Bad header flags!");
return false; return 1;
} }
} }
else if (npd->version == 3 || npd->version == 4) else if ((npd->version == 3) || (npd->version == 4))
{ {
if (edat->flags & 0x7EFFFFC0) if (edat->flags & 0x7EFFFFC0)
{ {
LOG_ERROR(LOADER, "EDAT: Bad header flags!\n"); LOG_ERROR(LOADER, "EDAT: Bad header flags!");
return false; return 1;
} }
} }
else if (npd->version > 4) else
{ {
LOG_ERROR(LOADER, "EDAT: Unknown version - %d\n", npd->version); LOG_ERROR(LOADER, "EDAT: Unknown 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;
return 1; return 1;
} }
// Read in the file header. // Read in the file header.
f->Read(header, 0xA0); 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. // Setup the hashing mode and the crypto mode used in the file.
int crypto_mode = 0x1; int crypto_mode = 0x1;
int hash_mode = ((edat->flags & EDAT_ENCRYPTED_KEY_FLAG) == 0) ? 0x00000002 : 0x10000002; int hash_mode = ((edat->flags & EDAT_ENCRYPTED_KEY_FLAG) == 0) ? 0x00000002 : 0x10000002;
if ((edat->flags & EDAT_DEBUG_DATA_FLAG) != 0) if ((edat->flags & EDAT_DEBUG_DATA_FLAG) != 0)
{ {
LOG_ERROR(LOADER, "EDAT: DEBUG data detected!\n");
hash_mode |= 0x01000000; hash_mode |= 0x01000000;
if (verbose)
LOG_WARNING(LOADER, "EDAT: DEBUG data detected!");
} }
// Setup header key and iv buffers. // Setup header key and iv buffers.
unsigned char header_key[0x10] = {}; unsigned char header_key[0x10];
unsigned char header_iv[0x10] = {}; unsigned char header_iv[0x10];
memset(header_key, 0, 0x10);
memset(header_iv, 0, 0x10);
// Test the header hash (located at offset 0xA0). // 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) 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. // 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)) if (((edat->flags & EDAT_COMPRESSED_FLAG) != 0))
{ {
LOG_WARNING(LOADER, "EDAT: COMPRESSED data detected!\n"); if (verbose)
metadata_section_size = 0x20; LOG_WARNING(LOADER, "EDAT: COMPRESSED data detected!");
} }
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 bytes_read = 0;
int metadata_offset = 0x100; 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) while (bytes_to_read > 0)
{ {
// Locate the metadata blocks. // 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_section_offset);
f->Seek(metadata_offset + bytes_read);
unsigned char *data = new unsigned char[block_size];
// Read in the metadata. // Read in the metadata.
tmp = new unsigned char[block_size]; f->Read(metadata + bytes_read, metadata_section_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);
}
// Adjust sizes. // Adjust sizes.
bytes_read += block_size; bytes_read += metadata_section_size;
bytes_to_read -= block_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. // Cleanup.
delete[] header; delete[] metadata;
delete[] tmp; delete[] empty_metadata;
delete[] hash_result;
return 0; 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 title_hash_result = 0;
int dev_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 *buf = new unsigned char[0x30 + file_name_length];
unsigned char dev[0x60];
unsigned char key[0x10]; 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, npd->content_id, 0x30);
memcpy(buf + 0x30, file_name, file_name_length); memcpy(buf + 0x30, file_name, file_name_length);
// Hash with NP_OMAC_KEY_3 and compare with title_hash. // Build the dev buffer (first 0x60 bytes of NPD header in big-endian).
title_hash_result = cmac_hash_compare(NP_OMAC_KEY_3, 0x10, buf, 0x30 + file_name_length, npd->title_hash); 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 (verbose)
{ {
if (title_hash_result) if (title_hash_result)
LOG_SUCCESS(LOADER, "EDAT: NPD title hash is valid!\n"); LOG_NOTICE(LOADER, "EDAT: NPD title hash is valid!");
else 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); // 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 (isDevklicEmpty)
{ {
if (verbose) 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 else
{ {
// Generate klicensee xor key. // 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. // 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 (verbose)
{ {
if (dev_hash_result) if (dev_hash_result)
LOG_SUCCESS(LOADER, "EDAT: NPD dev hash is valid!\n"); LOG_NOTICE(LOADER, "EDAT: NPD dev hash is valid!");
else else
LOG_WARNING(LOADER, "EDAT: NPD dev hash is invalid!\n"); LOG_WARNING(LOADER, "EDAT: NPD dev hash is invalid!");
} }
} }
delete[] buf; 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) 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. // Setup NPD and EDAT/SDAT structs.
NPD_HEADER *NPD = new NPD_HEADER(); 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. // Read in the NPD and EDAT/SDAT headers.
char npd_header[0x80]; char npd_header[0x80];
char edat_header[0x10]; char edat_header[0x10];
input->Read(npd_header, 0x80); input->Read(npd_header, sizeof(npd_header));
input->Read(edat_header, 0x10); input->Read(edat_header, sizeof(edat_header));
memcpy(NPD->magic, npd_header, 4); memcpy(NPD->magic, npd_header, 4);
NPD->version = swap32(*(int*)&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]); NPD->unk2 = swap64(*(u64*)&npd_header[120]);
unsigned char npd_magic[4] = {0x4E, 0x50, 0x44, 0x00}; //NPD0 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); LOG_ERROR(LOADER, "EDAT: %s has invalid NPD header or already decrypted.", input_file_name);
delete NPD; delete NPD;
@ -537,32 +677,56 @@ bool extract_data(rFile *input, rFile *output, const char* input_file_name, unsi
if (verbose) if (verbose)
{ {
LOG_NOTICE(LOADER, "NPD HEADER\n"); LOG_NOTICE(LOADER, "NPD HEADER");
LOG_NOTICE(LOADER, "NPD version: %d\n", NPD->version); LOG_NOTICE(LOADER, "NPD version: %d", NPD->version);
LOG_NOTICE(LOADER, "NPD license: %d\n", NPD->license); LOG_NOTICE(LOADER, "NPD license: %d", NPD->license);
LOG_NOTICE(LOADER, "NPD type: %d\n", NPD->type); LOG_NOTICE(LOADER, "NPD type: %d", 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");
} }
// Set decryption key. // Set decryption key.
unsigned char key[0x10]; unsigned char key[0x10];
memset(key, 0, 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"); if (verbose)
xor_(key, NPD->dev_hash, SDAT_KEY, 0x10); {
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 else
{ {
// Perform header validation (optional step). if (verbose)
validate_data(input_file_name, devklic, NPD, 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. if ((NPD->license & 0x3) == 0x3) // Type 3: Use supplied devklic.
memcpy(key, devklic, 0x10); memcpy(key, devklic, 0x10);
else if ((NPD->license & 0x2) == 0x2) // Type 2: Use key from RAP file (RIF key). 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. // Make sure we don't have an empty RIF key.
int i, test = 0; int i, test = 0;
for(i = 0; i < 0x10; i++) for (i = 0; i < 0x10; i++)
{ {
if (key[i] != 0) if (key[i] != 0)
{ {
@ -582,27 +746,62 @@ bool extract_data(rFile *input, rFile *output, const char* input_file_name, unsi
if (!test) 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 NPD;
delete EDAT; delete EDAT;
return 1; 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)) 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 else
LOG_SUCCESS(LOADER, "EDAT: Data successfully parsed!\n"); LOG_NOTICE(LOADER, "EDAT: Data successfully parsed!");
printf("\n"); LOG_NOTICE(LOADER, "EDAT: Decrypting data...");
LOG_NOTICE(LOADER, "EDAT: Decrypting data...\n");
if (decrypt_data(input, output, EDAT, NPD, key, verbose)) if (decrypt_data(input, output, EDAT, NPD, key, verbose))
{
LOG_ERROR(LOADER, "EDAT: Data decryption failed!"); LOG_ERROR(LOADER, "EDAT: Data decryption failed!");
delete NPD;
delete EDAT;
return 1;
}
else else
LOG_SUCCESS(LOADER, "EDAT: Data successfully decrypted!"); LOG_NOTICE(LOADER, "EDAT: Data successfully decrypted!");
delete NPD; delete NPD;
delete EDAT; delete EDAT;
@ -655,21 +854,21 @@ int DecryptEDAT(const std::string& input_file_name, const std::string& output_fi
memcpy(devklic, custom_klic, 0x10); memcpy(devklic, custom_klic, 0x10);
else else
{ {
LOG_ERROR(LOADER, "EDAT: Invalid custom klic!\n"); LOG_ERROR(LOADER, "EDAT: Invalid custom klic!");
return -1; return -1;
} }
break; break;
} }
default: default:
LOG_ERROR(LOADER, "EDAT: Invalid mode!\n"); LOG_ERROR(LOADER, "EDAT: Invalid mode!");
return -1; return -1;
} }
// Check the input/output files. // Check the input/output files.
if (!input.IsOpened() || !output.IsOpened()) if (!input.IsOpened() || !output.IsOpened())
{ {
LOG_ERROR(LOADER, "EDAT: Failed to open files!\n"); LOG_ERROR(LOADER, "EDAT: Failed to open files!");
return -1; return -1;
} }
@ -692,7 +891,7 @@ int DecryptEDAT(const std::string& input_file_name, const std::string& output_fi
input.Close(); input.Close();
output.Close(); output.Close();
rRemoveFile(output_file_name); rRemoveFile(output_file_name);
return 0; return -1;
} }
// Cleanup. // Cleanup.

View File

@ -1,9 +1,12 @@
#pragma once #pragma once
#include <stdio.h>
#include <string.h>
#include "utils.h"
#define SDAT_FLAG 0x01000000 #define SDAT_FLAG 0x01000000
#define EDAT_COMPRESSED_FLAG 0x00000001 #define EDAT_COMPRESSED_FLAG 0x00000001
#define EDAT_FLAG_0x02 0x00000002 #define EDAT_FLAG_0x02 0x00000002
#define EDAT_FLAG_0x04 0x00000004
#define EDAT_ENCRYPTED_KEY_FLAG 0x00000008 #define EDAT_ENCRYPTED_KEY_FLAG 0x00000008
#define EDAT_FLAG_0x10 0x00000010 #define EDAT_FLAG_0x10 0x00000010
#define EDAT_FLAG_0x20 0x00000020 #define EDAT_FLAG_0x20 0x00000020
@ -28,6 +31,6 @@ typedef struct
int flags; int flags;
int block_size; int block_size;
unsigned long long file_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); 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);

View File

@ -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); 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> hi = *(be_t<u64>*)&iv[0];
be_t<u64> lo = be_t<u64>::MakeFromBE(*(u64*)&iv[8]); be_t<u64> lo = *(be_t<u64>*)&iv[8];
lo++; lo++;
if (lo == 0) if (lo == 0)

View File

@ -10,6 +10,101 @@
#include <wx/mstream.h> #include <wx/mstream.h>
#include <wx/zstream.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) void AppInfo::Load(vfsStream& f)
{ {
authid = Read64(f); authid = Read64(f);
@ -813,10 +908,10 @@ bool SELFDecrypter::GetKeyFromRap(u8 *content_id, u8 *npdrm_key)
u8 rap_key[0x10]; u8 rap_key[0x10];
memset(rap_key, 0, 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); std::string ci_str((const char *)content_id);
// TODO: This shouldn't use current dir std::string pf_str("00000001"); // TODO: Allow multiple profiles. Use default for now.
std::string rap_path("./dev_usb000/" + ci_str + ".rap"); std::string rap_path("dev_hdd0/home/" + pf_str + "/exdata/" + ci_str + ".rap");
// Check if we have a valid RAP file. // Check if we have a valid RAP file.
if (!rExists(rap_path)) if (!rExists(rap_path))

View File

@ -1,6 +1,5 @@
#pragma once #pragma once
#include "Loader/SELF.h"
#include "Loader/ELF64.h" #include "Loader/ELF64.h"
#include "Loader/ELF32.h" #include "Loader/ELF32.h"
#include "key_vault.h" #include "key_vault.h"
@ -142,7 +141,8 @@ struct MetadataSectionHeader
void Show(); void Show();
}; };
struct SectionHash { struct SectionHash
{
u8 sha1[20]; u8 sha1[20];
u8 padding[12]; u8 padding[12];
u8 hmac_key[64]; u8 hmac_key[64];
@ -183,6 +183,291 @@ struct SelfSection
void Load(vfsStream& f); 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 class SELFDecrypter
{ {
// Main SELF file stream. // Main SELF file stream.

View File

@ -1,9 +1,13 @@
#include "stdafx.h" // Copyright (C) 2014 Hykem <hykem@hotmail.com>
#include "aes.h" // Licensed under the terms of the GNU GPL, version 3
#include "sha1.h" // http://www.gnu.org/licenses/gpl-3.0.txt
#include "utils.h"
// 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) u16 swap16(u16 i)
{ {
return ((i & 0xFF00) >> 8) | ((i & 0xFF) << 8); return ((i & 0xFF00) >> 8) | ((i & 0xFF) << 8);
@ -22,7 +26,7 @@ u64 swap64(u64 i)
((i & 0x00ff000000000000) >> 40) | ((i & 0xff00000000000000) >> 56); ((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; int i;
for(i = 0; i < size; 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. // Hex string conversion auxiliary functions.
u64 hex_to_u64(const char* hex_str) u64 hex_to_u64(const char* hex_str)
{ {
u32 length = (u32)strlen(hex_str); u32 length = (u32) strlen(hex_str);
u64 tmp = 0; u64 tmp = 0;
u64 result = 0; u64 result = 0;
char c; char c;
@ -56,19 +74,19 @@ u64 hex_to_u64(const char* hex_str)
return result; 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 strn_length = (str_length > 0) ? str_length : (u32) strlen(hex_str);
u32 data_length = str_length / 2; u32 data_length = strn_length / 2;
char tmp_buf[3] = {0, 0, 0}; char tmp_buf[3] = {0, 0, 0};
// Don't convert if the string length is odd. // 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; u8 *pos = out;
while (str_length--) while (strn_length--)
{ {
tmp_buf[0] = *hex_str++; tmp_buf[0] = *hex_str++;
tmp_buf[1] = *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). // 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_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); 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) void aesecb128_encrypt(unsigned char *key, unsigned char *in, unsigned char *out)
{ {
aes_context ctx; 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); 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]; unsigned char *out = new unsigned char[key_len];
sha1_hmac(key, key_len, in, in_len, out); 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]) 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; 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]; 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_setkey_enc(&ctx, key, 128);
aes_cmac(&ctx, in_len, in, out); 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]) 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; return true;
} }
#include "lz.h" void cmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash)
// Reverse-engineered custom LempelZivMarkov based compression (unknown variant of LZRC).
int lz_decompress(unsigned char *out, unsigned char *in, unsigned int size)
{ {
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;
} }

View File

@ -1,20 +1,35 @@
#pragma once #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); u16 swap16(u16 i);
u32 swap32(u32 i); u32 swap32(u32 i);
u64 swap64(u64 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. // Hex string conversion auxiliary functions.
u64 hex_to_u64(const char* hex_str); 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). // 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_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); 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 hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash, int hash_len);
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);
bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash, int hash_len);
// Reverse-engineered custom LempelZivMarkov based compression (unknown variant of LZRC). void cmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash);
int lz_decompress(unsigned char *out, unsigned char *in, unsigned int size);

View File

@ -13,125 +13,23 @@ public:
{ {
} }
u32 branchTarget(u32 imm)
{
return imm << 1;
}
virtual u8 DecodeMemory(const u32 address) virtual u8 DecodeMemory(const u32 address)
{ {
using namespace ARMv7_opcodes; const u32 code0 = vm::psv::read16(address & ~1);
const u16 code0 = vm::psv::read16(address); const u32 code1 = vm::psv::read16(address + 2 & ~1);
const u16 code1 = vm::psv::read16(address + 2); 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: if ((opcode.type < A1) == ((address & 1) == 0) && (arg & opcode.mask) == opcode.code)
switch((code0 >> 10) & 0x1)
{ {
case 0: (m_op.*opcode.func)(opcode.length == 2 ? code0 : arg, opcode.type);
switch((code0 >> 8) & 0x1) return opcode.length;
{
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;
} }
} }
break;
}
switch(code0 >> 9) m_op.UNK(data);
{ return address & 1 ? 4 : 2;
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;
} }
}; };

File diff suppressed because it is too large Load Diff

View File

@ -45,50 +45,276 @@ protected:
return regs_str; return regs_str;
} }
void NULL_OP() virtual void UNK(const u32 data);
{
Write("null");
}
void PUSH(u16 regs_list) virtual void NULL_OP(const u32 data, const ARMv7_encoding type);
{
Write(fmt::Format("push {%s}", GetRegsListString(regs_list).c_str()));
}
void POP(u16 regs_list) virtual void HACK(const u32 data, const ARMv7_encoding type);
{
Write(fmt::Format("pop {%s}", GetRegsListString(regs_list).c_str()));
}
void NOP() virtual void ADC_IMM(const u32 data, const ARMv7_encoding type);
{ virtual void ADC_REG(const u32 data, const ARMv7_encoding type);
Write("nop"); virtual void ADC_RSR(const u32 data, const ARMv7_encoding type);
}
void B(u8 cond, u32 imm, u8 intstr_size) virtual void ADD_IMM(const u32 data, const ARMv7_encoding type);
{ virtual void ADD_REG(const u32 data, const ARMv7_encoding type);
if((cond & 0xe) == 0xe) virtual void ADD_RSR(const u32 data, const ARMv7_encoding type);
{ virtual void ADD_SPI(const u32 data, const ARMv7_encoding type);
Write(fmt::Format("b 0x%x", DisAsmBranchTarget(imm) + intstr_size)); virtual void ADD_SPR(const u32 data, const ARMv7_encoding type);
}
else
{
Write(fmt::Format("b[%s] 0x%x", g_arm_cond_name[cond], DisAsmBranchTarget(imm) + intstr_size));
}
}
virtual void CBZ(u8 op, u32 imm, u8 rn, u8 intstr_size) virtual void ADR(const u32 data, const ARMv7_encoding type);
{
Write(fmt::Format("cb%sz 0x%x,%s", (op ? "n" : ""), DisAsmBranchTarget(imm) + intstr_size, g_arm_reg_name[rn]));
}
void BL(u32 imm, u8 intstr_size) virtual void AND_IMM(const u32 data, const ARMv7_encoding type);
{ virtual void AND_REG(const u32 data, const ARMv7_encoding type);
Write(fmt::Format("bl 0x%x", DisAsmBranchTarget(imm) + intstr_size)); virtual void AND_RSR(const u32 data, const ARMv7_encoding type);
}
void UNK(const u16 code0, const u16 code1) virtual void ASR_IMM(const u32 data, const ARMv7_encoding type);
{ virtual void ASR_REG(const u32 data, const ARMv7_encoding type);
Write(fmt::Format("Unknown/Illegal opcode! (0x%04x : 0x%04x)", code0, code1));
} 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

View File

@ -10,7 +10,7 @@ public:
{ {
} }
enum SRType enum SRType : u32
{ {
SRType_None, SRType_None,
SRType_LSL, SRType_LSL,
@ -93,7 +93,7 @@ public:
return len - 1 - HighestSetBit(x, len); 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; SRType shift_t = SRType_None;
@ -217,7 +217,7 @@ public:
return value; 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; bool carry_out;
return Shift_C(value, type, amount, carry_in, 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) 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; const T sign_mask = (T)1 << (sizeof(T) - 1);
int signed_sum = (int)x + (int)y + (int)carry_in;
T result = unsigned_sum & ~(T(1) << (sizeof(T) - 1)); T result = x + y;
carry_out = (uint)result != unsigned_sum; carry_out = ((x & y) | ((x ^ y) & ~result)) & sign_mask;
overflow = (int)result != signed_sum; overflow = (x ^ result) & (y ^ result) & sign_mask;
if (carry_in)
{
result += 1;
carry_out ^= (result == 0);
overflow ^= (result == sign_mask);
}
return result; 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; bool result = false;
@ -258,65 +293,276 @@ public:
} }
protected: protected:
void NULL_OP() virtual void UNK(const u32 data);
{
LOG_ERROR(HLE, "null");
Emu.Pause();
}
void NOP() virtual void NULL_OP(const u32 data, const ARMv7_encoding type);
{
}
void PUSH(u16 regs_list) virtual void HACK(const u32 data, const ARMv7_encoding type);
{
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));
}
}
}
void POP(u16 regs_list) virtual void ADC_IMM(const u32 data, const ARMv7_encoding type);
{ virtual void ADC_REG(const u32 data, const ARMv7_encoding type);
for(u16 mask=(0x1 << 15), i=15; mask; mask >>= 1, i--) virtual void ADC_RSR(const u32 data, const ARMv7_encoding type);
{
if(regs_list & mask)
{
CPU.write_gpr(i, vm::psv::read32(CPU.SP));
CPU.SP += 4;
}
}
}
void B(u8 cond, u32 imm, u8 intstr_size) virtual void ADD_IMM(const u32 data, const ARMv7_encoding type);
{ virtual void ADD_REG(const u32 data, const ARMv7_encoding type);
if(ConditionPassed(cond)) virtual void ADD_RSR(const u32 data, const ARMv7_encoding type);
{ virtual void ADD_SPI(const u32 data, const ARMv7_encoding type);
CPU.SetBranch(CPU.PC + intstr_size + imm); virtual void ADD_SPR(const u32 data, const ARMv7_encoding type);
}
}
void CBZ(u8 op, u32 imm, u8 rn, u8 intstr_size) virtual void ADR(const u32 data, const ARMv7_encoding type);
{
if((CPU.GPR[rn] == 0) ^ op)
{
CPU.SetBranch(CPU.PC + intstr_size + imm);
}
}
void BL(u32 imm, u8 intstr_size) virtual void AND_IMM(const u32 data, const ARMv7_encoding type);
{ virtual void AND_REG(const u32 data, const ARMv7_encoding type);
CPU.LR = (CPU.PC + intstr_size) | 1; virtual void AND_RSR(const u32 data, const ARMv7_encoding type);
CPU.SetBranch(CPU.PC + intstr_size + imm);
}
void UNK(const u16 code0, const u16 code1) virtual void ASR_IMM(const u32 data, const ARMv7_encoding type);
{ virtual void ASR_REG(const u32 data, const ARMv7_encoding type);
LOG_ERROR(HLE, "Unknown/Illegal opcode! (0x%04x : 0x%04x)", code0, code1);
Emu.Pause(); 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);
}; };

View File

@ -32,18 +32,686 @@ namespace ARMv7_opcodes
}; };
} }
enum ARMv7_encoding
{
T1,
T2,
T3,
T4,
A1,
A2,
};
class ARMv7Opcodes class ARMv7Opcodes
{ {
public: public:
virtual void NULL_OP() = 0; virtual void UNK(const u32 data) = 0;
virtual void NOP() = 0;
virtual void PUSH(u16 regs_list) = 0; virtual void NULL_OP(const u32 data, const ARMv7_encoding type) = 0;
virtual void POP(u16 regs_list) = 0;
virtual void B(u8 cond, u32 imm, u8 intstr_size) = 0; virtual void HACK(const u32 data, const ARMv7_encoding type) = 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 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

View File

@ -3,6 +3,7 @@
#include "Utilities/Log.h" #include "Utilities/Log.h"
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/CPU/CPUThreadManager.h"
#include "ARMv7Thread.h" #include "ARMv7Thread.h"
#include "ARMv7Decoder.h" #include "ARMv7Decoder.h"
@ -18,6 +19,8 @@ void ARMv7Thread::InitRegs()
memset(GPR, 0, sizeof(GPR[0]) * 15); memset(GPR, 0, sizeof(GPR[0]) * 15);
APSR.APSR = 0; APSR.APSR = 0;
IPSR.IPSR = 0; IPSR.IPSR = 0;
ISET = Thumb;
ITSTATE.IT = 0;
SP = m_stack_addr + m_stack_size; 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() std::string ARMv7Thread::RegsToString()
@ -98,3 +101,15 @@ void ARMv7Thread::DoStop()
void ARMv7Thread::DoCode() 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;
}

View File

@ -1,6 +1,14 @@
#pragma once #pragma once
#include "Emu/CPU/CPUThread.h" #include "Emu/CPU/CPUThread.h"
enum ARMv7InstructionSet
{
ARM,
Thumb,
Jazelle,
ThumbEE,
};
class ARMv7Thread : public CPUThread class ARMv7Thread : public CPUThread
{ {
public: public:
@ -38,6 +46,7 @@ public:
}; };
u32 APSR; u32 APSR;
} APSR; } APSR;
union union
@ -49,8 +58,41 @@ public:
}; };
u32 IPSR; u32 IPSR;
} 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) void write_gpr(u32 n, u32 value)
{ {
assert(n < 16); assert(n < 16);
@ -61,7 +103,7 @@ public:
} }
else else
{ {
SetBranch(value); SetBranch(value & ~1);
} }
} }
@ -80,7 +122,7 @@ public:
public: public:
virtual void InitRegs(); virtual void InitRegs();
virtual void InitStack(); virtual void InitStack();
virtual void SetArg(const uint pos, const u64 arg); u32 GetStackArg(u32 pos);
public: public:
virtual std::string RegsToString(); virtual std::string RegsToString();
@ -96,3 +138,48 @@ protected:
virtual void DoCode(); 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;
}
};

View File

@ -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");
}();

View File

@ -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");
}();

View File

@ -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

View File

@ -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("");
}

View File

@ -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();

View File

@ -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() virtual ~InstrBase()
{ {
if (m_args) { if (m_args) {

View File

@ -28,6 +28,8 @@ CPUThread::CPUThread(CPUThreadType type)
, m_is_branch(false) , m_is_branch(false)
, m_status(Stopped) , m_status(Stopped)
, m_last_syscall(0) , 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; m_is_branch = true;
nPC = pc; nPC = pc;
if(record_branch) if(m_trace_call_stack && record_branch)
CallStackBranch(pc); CallStackBranch(pc);
} }
@ -298,7 +300,7 @@ void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp)
void CPUThread::Task() 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(); const std::vector<u64>& bp = Emu.GetBreakPoints();
@ -337,7 +339,7 @@ void CPUThread::Task()
} }
Step(); Step();
//if (PC - 0x13ED4 < 0x288) trace.push_back(PC); //if (m_trace_enabled) trace.push_back(PC);
NextPc(m_dec->DecodeMemory(PC + m_offset)); NextPc(m_dec->DecodeMemory(PC + m_offset));
if (status == CPUThread_Step) if (status == CPUThread_Step)
@ -373,7 +375,25 @@ void CPUThread::Task()
// TODO: linux version // TODO: linux version
#endif #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());
} }

View File

@ -43,6 +43,8 @@ protected:
CPUDecoder* m_dec; CPUDecoder* m_dec;
bool m_trace_call_stack;
public: public:
virtual void InitRegs()=0; virtual void InitRegs()=0;
@ -109,16 +111,19 @@ public:
virtual std::string GetThreadName() const 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; return temp;
} }
CPUDecoder * GetDecoder() { return m_dec; };
public: public:
u32 entry; u32 entry;
u32 PC; u32 PC;
u32 nPC; u32 nPC;
u64 cycle; u64 cycle;
bool m_is_branch; bool m_is_branch;
bool m_trace_enabled;
bool m_is_interrupt; bool m_is_interrupt;
bool m_has_interrupt; bool m_has_interrupt;
@ -174,6 +179,8 @@ public:
u32 GetId() const { return m_id; } u32 GetId() const { return m_id; }
CPUThreadType GetType() const { return m_type; } CPUThreadType GetType() const { return m_type; }
void SetCallStackTracing(bool trace_call_stack) { m_trace_call_stack = trace_call_stack; }
void Reset(); void Reset();
void Close(); void Close();
void Run(); void Run();
@ -249,3 +256,42 @@ protected:
}; };
CPUThread* GetCurrentCPUThread(); 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();
}
};

View File

@ -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() void CPUThreadManager::Exec()
{ {
std::lock_guard<std::mutex> lock(m_mtx_thread); std::lock_guard<std::mutex> lock(m_mtx_thread);

View File

@ -17,7 +17,6 @@ public:
CPUThread& AddThread(CPUThreadType type); CPUThread& AddThread(CPUThreadType type);
void RemoveThread(const u32 id); void RemoveThread(const u32 id);
void NotifyThread(const u32 id);
std::vector<CPUThread*>& GetThreads() { return m_threads; } std::vector<CPUThread*>& GetThreads() { return m_threads; }
s32 GetThreadNumById(CPUThreadType type, u32 id); s32 GetThreadNumById(CPUThreadType type, u32 id);

View File

@ -61,5 +61,4 @@ enum
struct DMAC struct DMAC
{ {
u32 ls_offset;
}; };

View File

@ -9,7 +9,7 @@ public:
virtual std::string GetThreadName() const virtual std::string GetThreadName() const
{ {
return (GetFName() + fmt::Format("[0x%08llx]", PC)); return (GetFName() + fmt::Format("[0x%08x]", PC));
} }
protected: protected:

View File

@ -1037,7 +1037,7 @@ private:
case 0x1: Write("HyperCall"); break; case 0x1: Write("HyperCall"); break;
case 0x2: Write("sc"); break; case 0x2: Write("sc"); break;
case 0x22: Write("HyperCall LV1"); 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) void B(s32 ll, u32 aa, u32 lk)
@ -1600,7 +1600,10 @@ private:
default: DisAsm_IMM_R1("mtspr", spr, rs); break; 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) void NAND(u32 ra, u32 rs, u32 rb, bool rc)
{ {
DisAsm_R3_RC("nand", ra, rs, rb, rc); DisAsm_R3_RC("nand", ra, rs, rb, rc);

View File

@ -5,6 +5,8 @@
namespace PPU_instr namespace PPU_instr
{ {
namespace fields
{
//This field is used in rotate instructions to specify the first 1 bit of a 64-bit mask //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; 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<21, 30> GD_3f_0; //0x3ff
static CodeField<9, 10> STRM; 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 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)); 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_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)); 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__) static const auto& name = make_instr<PPU_opcodes::name>(list, #name, &PPUOpcodes::name, ##__VA_ARGS__)
bind_instr(main_list, TDI, TO, RA, simm16); 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, MFFS, FRD, RC);
bind_instr(g3f_0_list, MTFSF, FM, FRB, 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 #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

View File

@ -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
}

View File

@ -276,7 +276,7 @@ namespace PPU_opcodes
LVEHX = 0x027, //Load Vector Element Halfword Indexed LVEHX = 0x027, //Load Vector Element Halfword Indexed
SUBF = 0x028, SUBF = 0x028,
LDUX = 0x035, //Load Doubleword with Update Indexed LDUX = 0x035, //Load Doubleword with Update Indexed
DCBST = 0x036, DCBST = 0x036, //Data Cache Block Store
LWZUX = 0x037, LWZUX = 0x037,
CNTLZD = 0x03a, CNTLZD = 0x03a,
ANDC = 0x03c, ANDC = 0x03c,
@ -285,7 +285,7 @@ namespace PPU_opcodes
MULHD = 0x049, MULHD = 0x049,
MULHW = 0x04b, MULHW = 0x04b,
LDARX = 0x054, LDARX = 0x054,
DCBF = 0x056, DCBF = 0x056, //Data Cache Block Flush
LBZX = 0x057, LBZX = 0x057,
LVX = 0x067, //Load Vector Indexed LVX = 0x067, //Load Vector Indexed
NEG = 0x068, NEG = 0x068,
@ -311,11 +311,11 @@ namespace PPU_opcodes
MULLD = 0x0e9, MULLD = 0x0e9,
ADDME = 0x0ea, ADDME = 0x0ea,
MULLW = 0x0eb, MULLW = 0x0eb,
DCBTST = 0x0f6, DCBTST = 0x0f6, //Data Cache Block Touch for Store
STBUX = 0x0f7, STBUX = 0x0f7,
DOZ = 0x108, DOZ = 0x108,
ADD = 0x10a, ADD = 0x10a,
DCBT = 0x116, DCBT = 0x116, //Data Cache Block Touch
LHZX = 0x117, LHZX = 0x117,
EQV = 0x11c, EQV = 0x11c,
ECIWX = 0x136, ECIWX = 0x136,
@ -338,7 +338,7 @@ namespace PPU_opcodes
DIVDU = 0x1c9, DIVDU = 0x1c9,
DIVWU = 0x1cb, DIVWU = 0x1cb,
MTSPR = 0x1d3, MTSPR = 0x1d3,
DCBI = 0x1d6, DCBI = 0x1d6, //Data Cache Block Invalidate
NAND = 0x1dc, NAND = 0x1dc,
STVXL = 0x1e7, //Store Vector Indexed Last STVXL = 0x1e7, //Store Vector Indexed Last
DIVD = 0x1e9, DIVD = 0x1e9,
@ -382,8 +382,8 @@ namespace PPU_opcodes
EXTSB = 0x3ba, EXTSB = 0x3ba,
STFIWX = 0x3d7, STFIWX = 0x3d7,
EXTSW = 0x3da, EXTSW = 0x3da,
ICBI = 0x3d6, ICBI = 0x3d6, //Instruction Cache Block Invalidate
DCBZ = 0x3f6, DCBZ = 0x3f6, //Data Cache Block Set to Zero
}; };
enum G_3aOpcodes //Field 30 - 31 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 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 DIVWU(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) = 0;
virtual void MTSPR(u32 spr, u32 rs) = 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 NAND(u32 ra, u32 rs, u32 rb, bool rc) = 0;
virtual void STVXL(u32 vs, u32 ra, u32 rb) = 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; virtual void DIVD(u32 rd, u32 ra, u32 rb, u32 oe, bool rc) = 0;

View File

@ -1,7 +1,7 @@
#include "stdafx_gui.h" #include "stdafx_gui.h"
#include "PPUProgramCompiler.h" #include "PPUProgramCompiler.h"
#include "Utilities/rFile.h" #include "Utilities/rFile.h"
/*
using namespace PPU_instr; using namespace PPU_instr;
template<typename TO, typename T> template<typename TO, typename T>
@ -78,10 +78,10 @@ SectionInfo::SectionInfo(const std::string& _name)
section_name_offs += name.length() + 1; 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 (addralign) shdr.sh_addralign = addralign;
if(shdr.sh_addralign) size = AlignAddr(size, shdr.sh_addralign); if (shdr.sh_addralign) size = align(size, shdr.sh_addralign);
if(!code.empty()) if(!code.empty())
{ {
@ -985,7 +985,7 @@ void CompilePPUProgram::Compile()
elf_info.e_shnum = 15; elf_info.e_shnum = 15;
elf_info.e_shstrndx = elf_info.e_shnum - 1; elf_info.e_shstrndx = elf_info.e_shnum - 1;
elf_info.e_phoff = elf_info.e_ehsize; 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; static const u32 sceStub_text_block = 8 * 4;
@ -1143,7 +1143,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_sceStub_text; Elf64_Shdr s_sceStub_text;
memset(&s_sceStub_text, 0, sizeof(Elf64_Shdr)); memset(&s_sceStub_text, 0, sizeof(Elf64_Shdr));
s_sceStub_text.sh_addralign = 4; 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_type = 1;
s_sceStub_text.sh_offset = section_offset; s_sceStub_text.sh_offset = section_offset;
s_sceStub_text.sh_addr = section_offset + 0x10000; s_sceStub_text.sh_addr = section_offset + 0x10000;
@ -1167,7 +1167,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_lib_stub_top; Elf64_Shdr s_lib_stub_top;
memset(&s_lib_stub_top, 0, sizeof(Elf64_Shdr)); memset(&s_lib_stub_top, 0, sizeof(Elf64_Shdr));
s_lib_stub_top.sh_addralign = 4; 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_type = 1;
s_lib_stub_top.sh_name = section_name_offset; s_lib_stub_top.sh_name = section_name_offset;
s_lib_stub_top.sh_offset = section_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_offset = section_offset;
s_lib_stub.sh_addr = section_offset + 0x10000; s_lib_stub.sh_addr = section_offset + 0x10000;
s_lib_stub.sh_flags = 2; 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"); sections_names.push_back(".lib.stub");
section_name_offset += std::string(".lib.stub").length() + 1; section_name_offset += std::string(".lib.stub").length() + 1;
section_offset += s_lib_stub.sh_size; section_offset += s_lib_stub.sh_size;
@ -1207,7 +1207,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_rodata_sceFNID; Elf64_Shdr s_rodata_sceFNID;
memset(&s_rodata_sceFNID, 0, sizeof(Elf64_Shdr)); memset(&s_rodata_sceFNID, 0, sizeof(Elf64_Shdr));
s_rodata_sceFNID.sh_addralign = 4; 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_type = 1;
s_rodata_sceFNID.sh_name = section_name_offset; s_rodata_sceFNID.sh_name = section_name_offset;
s_rodata_sceFNID.sh_offset = section_offset; s_rodata_sceFNID.sh_offset = section_offset;
@ -1221,7 +1221,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_rodata_sceResident; Elf64_Shdr s_rodata_sceResident;
memset(&s_rodata_sceResident, 0, sizeof(Elf64_Shdr)); memset(&s_rodata_sceResident, 0, sizeof(Elf64_Shdr));
s_rodata_sceResident.sh_addralign = 4; 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_type = 1;
s_rodata_sceResident.sh_name = section_name_offset; s_rodata_sceResident.sh_name = section_name_offset;
s_rodata_sceResident.sh_offset = section_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 += 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"); sections_names.push_back(".rodata.sceResident");
section_name_offset += std::string(".rodata.sceResident").length() + 1; section_name_offset += std::string(".rodata.sceResident").length() + 1;
section_offset += s_rodata_sceResident.sh_size; section_offset += s_rodata_sceResident.sh_size;
@ -1240,7 +1240,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_lib_ent_top; Elf64_Shdr s_lib_ent_top;
memset(&s_lib_ent_top, 0, sizeof(Elf64_Shdr)); memset(&s_lib_ent_top, 0, sizeof(Elf64_Shdr));
s_lib_ent_top.sh_addralign = 4; 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_size = 4;
s_lib_ent_top.sh_flags = 2; s_lib_ent_top.sh_flags = 2;
s_lib_ent_top.sh_type = 1; s_lib_ent_top.sh_type = 1;
@ -1267,7 +1267,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_sys_proc_prx_param; Elf64_Shdr s_sys_proc_prx_param;
memset(&s_sys_proc_prx_param, 0, sizeof(Elf64_Shdr)); memset(&s_sys_proc_prx_param, 0, sizeof(Elf64_Shdr));
s_sys_proc_prx_param.sh_addralign = 4; 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_type = 1;
s_sys_proc_prx_param.sh_size = sizeof(sys_proc_prx_param); s_sys_proc_prx_param.sh_size = sizeof(sys_proc_prx_param);
s_sys_proc_prx_param.sh_name = section_name_offset; 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; 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; const u32 prog_load_1_start = section_offset;
Elf64_Shdr s_data_sceFStub; Elf64_Shdr s_data_sceFStub;
memset(&s_data_sceFStub, 0, sizeof(Elf64_Shdr)); memset(&s_data_sceFStub, 0, sizeof(Elf64_Shdr));
s_data_sceFStub.sh_name = section_name_offset; s_data_sceFStub.sh_name = section_name_offset;
s_data_sceFStub.sh_addralign = 4; 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_flags = 3;
s_data_sceFStub.sh_type = 1; s_data_sceFStub.sh_type = 1;
s_data_sceFStub.sh_offset = section_offset; s_data_sceFStub.sh_offset = section_offset;
@ -1300,7 +1300,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_tbss; Elf64_Shdr s_tbss;
memset(&s_tbss, 0, sizeof(Elf64_Shdr)); memset(&s_tbss, 0, sizeof(Elf64_Shdr));
s_tbss.sh_addralign = 4; 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_size = 4;
s_tbss.sh_flags = 0x403; s_tbss.sh_flags = 0x403;
s_tbss.sh_type = 8; s_tbss.sh_type = 8;
@ -1314,7 +1314,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_opd; Elf64_Shdr s_opd;
memset(&s_opd, 0, sizeof(Elf64_Shdr)); memset(&s_opd, 0, sizeof(Elf64_Shdr));
s_opd.sh_addralign = 8; 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_size = 2*4;
s_opd.sh_type = 1; s_opd.sh_type = 1;
s_opd.sh_offset = section_offset; s_opd.sh_offset = section_offset;
@ -1475,7 +1475,7 @@ void CompilePPUProgram::Compile()
if(!m_file_path.empty() && !m_analyze && !m_error) 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; section_offset += s_opd.sh_size;
const u32 prog_load_1_end = section_offset; const u32 prog_load_1_end = section_offset;
@ -1483,7 +1483,7 @@ void CompilePPUProgram::Compile()
Elf64_Shdr s_shstrtab; Elf64_Shdr s_shstrtab;
memset(&s_shstrtab, 0, sizeof(Elf64_Shdr)); memset(&s_shstrtab, 0, sizeof(Elf64_Shdr));
s_shstrtab.sh_addralign = 1; 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_name = section_name_offset;
s_shstrtab.sh_type = 3; s_shstrtab.sh_type = 3;
s_shstrtab.sh_offset = section_offset; s_shstrtab.sh_offset = section_offset;
@ -1505,7 +1505,7 @@ void CompilePPUProgram::Compile()
elf_info.e_machine = MACHINE_PPC64; //PowerPC64 elf_info.e_machine = MACHINE_PPC64; //PowerPC64
elf_info.e_version = 1; //ver 1 elf_info.e_version = 1; //ver 1
elf_info.e_flags = 0x0; 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]; u8* opd_data = new u8[s_opd.sh_size];
u32 entry_point = s_text.sh_addr; u32 entry_point = s_text.sh_addr;
@ -1523,14 +1523,14 @@ void CompilePPUProgram::Compile()
sys_proc_prx_param prx_param; sys_proc_prx_param prx_param;
memset(&prx_param, 0, sizeof(sys_proc_prx_param)); memset(&prx_param, 0, sizeof(sys_proc_prx_param));
prx_param.size = re32(0x40); prx_param.size = 0x40;
prx_param.magic = re32(0x1b434cec); prx_param.magic = 0x1b434cec;
prx_param.version = re32(0x4); prx_param.version = 0x4;
prx_param.libentstart = re32(s_lib_ent_top.sh_addr + s_lib_ent_top.sh_size); prx_param.libentstart = s_lib_ent_top.sh_addr + s_lib_ent_top.sh_size;
prx_param.libentend = re32(s_lib_ent_btm.sh_addr); prx_param.libentend = s_lib_ent_btm.sh_addr;
prx_param.libstubstart = re32(s_lib_stub_top.sh_addr + s_lib_stub_top.sh_size); prx_param.libstubstart = vm::bptr<sys_stub>::make(s_lib_stub_top.sh_addr + s_lib_stub_top.sh_size);
prx_param.libstubend = re32(s_lib_stub_btm.sh_addr); prx_param.libstubend = vm::bptr<sys_stub>::make(s_lib_stub_btm.sh_addr);
prx_param.ver = re16(0x101); prx_param.ver = 0x101;
elf_info.e_entry = s_opd.sh_addr; elf_info.e_entry = s_opd.sh_addr;
@ -1588,20 +1588,20 @@ void CompilePPUProgram::Compile()
f.Seek(s_lib_stub.sh_offset); f.Seek(s_lib_stub.sh_offset);
for(u32 i=0, nameoffs=4, dataoffs=0; i<modules.size(); ++i) for(u32 i=0, nameoffs=4, dataoffs=0; i<modules.size(); ++i)
{ {
Elf64_StubHeader stub; sys_stub stub;
memset(&stub, 0, sizeof(Elf64_StubHeader)); memset(&stub, 0, sizeof(sys_stub));
stub.s_size = 0x2c; stub.s_size = 0x2c;
stub.s_version = re16(0x1); stub.s_version = re16(0x1);
stub.s_unk1 = re16(0x9); stub.s_unk1 = re16(0x9);
stub.s_modulename = re32(s_rodata_sceResident.sh_addr + nameoffs); stub.s_modulename = vm::bptr<const char>::make(s_rodata_sceResident.sh_addr + nameoffs);
stub.s_nid = re32(s_rodata_sceFNID.sh_addr + dataoffs); stub.s_nid = vm::bptr<u32>::make(s_rodata_sceFNID.sh_addr + dataoffs);
stub.s_text = re32(s_data_sceFStub.sh_addr + dataoffs); stub.s_text = vm::bptr<u32>::make(s_data_sceFStub.sh_addr + dataoffs);
stub.s_imports = re16(modules[i].m_imports.size()); stub.s_imports = modules[i].m_imports.size();
dataoffs += modules[i].m_imports.size() * 4; 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; nameoffs += modules[i].m_name.length() + 1;
} }
@ -1732,3 +1732,4 @@ void CompilePPUProgram::Compile()
system("make_fself.cmd"); system("make_fself.cmd");
} }
} }
*/

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include "PPUInstrTable.h" #include "PPUInstrTable.h"
#include "Loader/ELF64.h" #include "Loader/ELF64.h"
/*
enum ArgType enum ArgType
{ {
ARG_ERR = 0, ARG_ERR = 0,
@ -189,3 +189,4 @@ protected:
public: public:
void Compile(); void Compile();
}; };
*/

View File

@ -9,6 +9,9 @@
#include "Emu/SysCalls/Static.h" #include "Emu/SysCalls/Static.h"
#include "Emu/Cell/PPUDecoder.h" #include "Emu/Cell/PPUDecoder.h"
#include "Emu/Cell/PPUInterpreter.h" #include "Emu/Cell/PPUInterpreter.h"
#include "Emu/Cell/PPULLVMRecompiler.h"
//#include "Emu/Cell/PPURecompiler.h"
#include "Emu/CPU/CPUThreadManager.h"
PPUThread& GetCurrentPPUThread() PPUThread& GetCurrentPPUThread()
{ {
@ -38,11 +41,11 @@ void PPUThread::DoReset()
memset(FPR, 0, sizeof(FPR)); memset(FPR, 0, sizeof(FPR));
memset(GPR, 0, sizeof(GPR)); memset(GPR, 0, sizeof(GPR));
memset(SPRG, 0, sizeof(SPRG)); memset(SPRG, 0, sizeof(SPRG));
memset(USPRG, 0, sizeof(USPRG));
CR.CR = 0; CR.CR = 0;
LR = 0; LR = 0;
CTR = 0; CTR = 0;
USPRG0 = 0;
TB = 0; TB = 0;
XER.XER = 0; XER.XER = 0;
FPSCR.FPSCR = 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[2] = rtoc;
//GPR[11] = entry;
//GPR[12] = Emu.GetMallocPageSize();
GPR[13] = Memory.PRXMem.GetStartAddr() + 0x7060; GPR[13] = Memory.PRXMem.GetStartAddr() + 0x7060;
LR = Emu.GetPPUThreadExit(); LR = Emu.GetPPUThreadExit();
@ -103,13 +108,26 @@ void PPUThread::DoRun()
break; break;
case 1: case 1:
case 2:
{ {
auto ppui = new PPUInterpreter(*this); auto ppui = new PPUInterpreter(*this);
m_dec = new PPUDecoder(ppui); m_dec = new PPUDecoder(ppui);
} }
break; 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: default:
LOG_ERROR(PPU, "Invalid CPU decoder mode: %d", Ini.CPUDecoderMode.GetValue()); LOG_ERROR(PPU, "Invalid CPU decoder mode: %d", Ini.CPUDecoderMode.GetValue());
Emu.Pause(); Emu.Pause();
@ -187,7 +205,7 @@ u64 PPUThread::FastCall2(u32 addr, u32 rtoc)
LR = Emu.m_ppu_thr_stop; LR = Emu.m_ppu_thr_stop;
SetCurrentNamedThread(this); SetCurrentNamedThread(this);
Task(); CPUThread::Task();
m_status = old_status; m_status = old_status;
PC = old_PC; PC = old_PC;
@ -203,3 +221,71 @@ void PPUThread::FastStop()
{ {
m_status = Stopped; 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;
}

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include "Emu/Cell/PPCThread.h" #include "Emu/Cell/PPCThread.h"
#include "Emu/Memory/vm.h"
enum enum
{ {
@ -470,9 +471,6 @@ struct FPRdouble
class PPUThread : public PPCThread class PPUThread : public PPCThread
{ {
public:
u32 owned_mutexes;
public: public:
PPCdouble FPR[32]; //Floating Point Register PPCdouble FPR[32]; //Floating Point Register
FPSCRhdr FPSCR; //Floating Point Status and Control Register FPSCRhdr FPSCR; //Floating Point Status and Control Register
@ -533,11 +531,8 @@ public:
u64 LR; //SPR 0x008 : Link Register u64 LR; //SPR 0x008 : Link Register
u64 CTR; //SPR 0x009 : Count Register u64 CTR; //SPR 0x009 : Count Register
union u64 USPRG[8]; //SPR 0x100 - 0x107: User-SPR General-Purpose Registers
{ u64 SPRG[8]; //SPR 0x110 - 0x117 : SPR General-Purpose Registers
u64 USPRG0; //SPR 0x100 : User-SPR General-Purpose Register 0
u64 SPRG[8]; //SPR 0x100 - 0x107 : SPR General-Purpose Registers
};
//TBR : Time-Base Registers //TBR : Time-Base Registers
union union
@ -556,6 +551,9 @@ public:
u64 R_ADDR; // reservation address u64 R_ADDR; // reservation address
u64 R_VALUE; // reservation value (BE) u64 R_VALUE; // reservation value (BE)
u32 owned_mutexes;
std::function<void(PPUThread& CPU)> custom_task;
public: public:
PPUThread(); PPUThread();
virtual ~PPUThread(); virtual ~PPUThread();
@ -785,25 +783,32 @@ public:
public: public:
virtual void InitRegs(); virtual void InitRegs();
virtual void Task();
u64 GetStackArg(s32 i); u64 GetStackArg(s32 i);
u64 FastCall2(u32 addr, u32 rtoc); u64 FastCall2(u32 addr, u32 rtoc);
void FastStop(); void FastStop();
virtual void DoReset() override;
virtual void DoRun() override; virtual void DoRun() override;
protected:
virtual void DoReset() override;
virtual void DoPause() override; virtual void DoPause() override;
virtual void DoResume() override; virtual void DoResume() override;
virtual void DoStop() override; virtual void DoStop() override;
protected:
virtual void Step() override
{
//if(++cycle > 20)
{
TB++;
//cycle = 0;
}
}
}; };
PPUThread& GetCurrentPPUThread(); 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);
};

View File

@ -190,7 +190,7 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value)
void RawSPUThread::InitRegs() 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(); SPUThread::InitRegs();
} }

View File

@ -3,7 +3,7 @@
#define UNIMPLEMENTED() UNK(__FUNCTION__) #define UNIMPLEMENTED() UNK(__FUNCTION__)
#define MEM_AND_REG_HASH() \ #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); \ 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); 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) void BIZ(u32 intr, u32 rt, u32 ra)
{ {
if (intr) switch (intr)
{ {
UNIMPLEMENTED(); case 0: break;
return; case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
} }
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0); u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
@ -270,10 +272,12 @@ private:
} }
void BINZ(u32 intr, u32 rt, u32 ra) void BINZ(u32 intr, u32 rt, u32 ra)
{ {
if (intr) switch (intr)
{ {
UNIMPLEMENTED(); case 0: break;
return; case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
} }
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0); u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
@ -289,10 +293,12 @@ private:
} }
void BIHZ(u32 intr, u32 rt, u32 ra) void BIHZ(u32 intr, u32 rt, u32 ra)
{ {
if (intr) switch (intr)
{ {
UNIMPLEMENTED(); case 0: break;
return; case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
} }
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0); u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
@ -308,10 +314,12 @@ private:
} }
void BIHNZ(u32 intr, u32 rt, u32 ra) void BIHNZ(u32 intr, u32 rt, u32 ra)
{ {
if (intr) switch (intr)
{ {
UNIMPLEMENTED(); case 0: break;
return; case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
} }
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0); u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
@ -337,10 +345,12 @@ private:
} }
void BI(u32 intr, u32 ra) void BI(u32 intr, u32 ra)
{ {
if (intr) switch (intr)
{ {
UNIMPLEMENTED(); case 0: break;
return; case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
} }
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0); u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
@ -349,10 +359,12 @@ private:
} }
void BISL(u32 intr, u32 rt, u32 ra) void BISL(u32 intr, u32 rt, u32 ra)
{ {
if (intr) switch (intr)
{ {
UNIMPLEMENTED(); case 0: break;
return; case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
} }
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0); u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
@ -432,9 +444,7 @@ private:
} }
void LQX(u32 rt, u32 ra, u32 rb) void LQX(u32 rt, u32 ra, u32 rb)
{ {
u32 a = CPU.GPR[ra]._u32[3], b = CPU.GPR[rb]._u32[3]; u32 lsa = (CPU.GPR[ra]._u32[3] + CPU.GPR[rb]._u32[3]) & 0x3fff0;
u32 lsa = (a + b) & 0x3fff0;
CPU.GPR[rt] = CPU.ReadLS128(lsa); 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; 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[0] = (u64)0x18191A1B1C1D1E1F;
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617; CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
CPU.GPR[rt]._u8[15 - t] = 0x03; 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; 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[0] = (u64)0x18191A1B1C1D1E1F;
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617; CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
CPU.GPR[rt]._u16[7 - (t >> 1)] = 0x0203; 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; 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[0] = (u64)0x18191A1B1C1D1E1F;
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617; CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
CPU.GPR[rt]._u32[3 - (t >> 2)] = 0x00010203; 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; 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[0] = (u64)0x18191A1B1C1D1E1F;
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617; CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
CPU.GPR[rt]._u64[1 - (t >> 3)] = (u64)0x0001020304050607; CPU.GPR[rt]._u64[1 - (t >> 3)] = (u64)0x0001020304050607;
@ -574,6 +608,12 @@ private:
{ {
const int t = (CPU.GPR[ra]._u32[3] + i7) & 0xF; 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[0] = (u64)0x18191A1B1C1D1E1F;
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617; CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
CPU.GPR[rt]._u8[15 - t] = 0x03; CPU.GPR[rt]._u8[15 - t] = 0x03;
@ -582,6 +622,12 @@ private:
{ {
const int t = (CPU.GPR[ra]._u32[3] + i7) & 0xE; 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[0] = (u64)0x18191A1B1C1D1E1F;
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617; CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
CPU.GPR[rt]._u16[7 - (t >> 1)] = 0x0203; CPU.GPR[rt]._u16[7 - (t >> 1)] = 0x0203;
@ -590,6 +636,12 @@ private:
{ {
const int t = (CPU.GPR[ra]._u32[3] + i7) & 0xC; 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[0] = (u64)0x18191A1B1C1D1E1F;
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617; CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
CPU.GPR[rt]._u32[3 - (t >> 2)] = 0x00010203; CPU.GPR[rt]._u32[3 - (t >> 2)] = 0x00010203;
@ -598,6 +650,12 @@ private:
{ {
const int t = (CPU.GPR[ra]._u32[3] + i7) & 0x8; 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[0] = (u64)0x18191A1B1C1D1E1F;
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617; CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
CPU.GPR[rt]._u64[1 - (t >> 3)] = (u64)0x0001020304050607; CPU.GPR[rt]._u64[1 - (t >> 3)] = (u64)0x0001020304050607;
@ -1088,6 +1146,7 @@ private:
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
CPU.GPR[rt]._f[i] = (float)CPU.GPR[ra]._u32[i]; CPU.GPR[rt]._f[i] = (float)CPU.GPR[ra]._u32[i];
u32 exp = ((CPU.GPR[rt]._u32[i] >> 23) & 0xff) - scale; u32 exp = ((CPU.GPR[rt]._u32[i] >> 23) & 0xff) - scale;
if (exp > 255) //< 0 if (exp > 255) //< 0

View File

@ -9,64 +9,6 @@ using namespace asmjit::host;
#define UNIMPLEMENTED() UNK(__FUNCTION__) #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 SPURecompiler;
class SPURecompilerCore : public CPUDecoder class SPURecompilerCore : public CPUDecoder
@ -78,6 +20,7 @@ public:
SPUInterpreter* inter; SPUInterpreter* inter;
JitRuntime runtime; JitRuntime runtime;
bool first; bool first;
bool need_check;
struct SPURecEntry struct SPURecEntry
{ {
@ -457,7 +400,7 @@ private:
c.mov(cpu_dword(PC), CPU.PC); c.mov(cpu_dword(PC), CPU.PC);
// This instruction must be used following a store instruction that modifies the instruction stream. // This instruction must be used following a store instruction that modifies the instruction stream.
c.mfence(); c.mfence();
c.mov(*pos_var, (CPU.PC >> 2) + 1); c.mov(*pos_var, (CPU.PC >> 2) + 1 + 0x2000000);
do_finalize = true; do_finalize = true;
LOG_OPCODE(); LOG_OPCODE();
} }
@ -688,7 +631,7 @@ private:
} }
LOG_OPCODE(); LOG_OPCODE();
} }
void ROTH(u32 rt, u32 ra, u32 rb) void ROTH(u32 rt, u32 ra, u32 rb) //nf
{ {
XmmInvalidate(rt); XmmInvalidate(rt);
for (u32 i = 0; i < 8; i++) for (u32 i = 0; i < 8; i++)
@ -1131,10 +1074,12 @@ private:
} }
void BIZ(u32 intr, u32 rt, u32 ra) void BIZ(u32 intr, u32 rt, u32 ra)
{ {
if (intr) switch (intr)
{ {
UNIMPLEMENTED(); case 0: break;
return; case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
} }
c.mov(cpu_dword(PC), CPU.PC); c.mov(cpu_dword(PC), CPU.PC);
@ -1142,6 +1087,7 @@ private:
c.mov(*addr, CPU.PC + 4); c.mov(*addr, CPU.PC + 4);
c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); 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.cmp(cpu_dword(GPR[rt]._u32[3]), 0);
c.cmovne(*pos_var, *addr); c.cmovne(*pos_var, *addr);
c.shr(*pos_var, 2); c.shr(*pos_var, 2);
@ -1149,10 +1095,12 @@ private:
} }
void BINZ(u32 intr, u32 rt, u32 ra) void BINZ(u32 intr, u32 rt, u32 ra)
{ {
if (intr) switch (intr)
{ {
UNIMPLEMENTED(); case 0: break;
return; case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
} }
c.mov(cpu_dword(PC), CPU.PC); c.mov(cpu_dword(PC), CPU.PC);
@ -1160,6 +1108,7 @@ private:
c.mov(*addr, CPU.PC + 4); c.mov(*addr, CPU.PC + 4);
c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); 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.cmp(cpu_dword(GPR[rt]._u32[3]), 0);
c.cmove(*pos_var, *addr); c.cmove(*pos_var, *addr);
c.shr(*pos_var, 2); c.shr(*pos_var, 2);
@ -1167,10 +1116,12 @@ private:
} }
void BIHZ(u32 intr, u32 rt, u32 ra) void BIHZ(u32 intr, u32 rt, u32 ra)
{ {
if (intr) switch (intr)
{ {
UNIMPLEMENTED(); case 0: break;
return; case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
} }
c.mov(cpu_dword(PC), CPU.PC); c.mov(cpu_dword(PC), CPU.PC);
@ -1178,6 +1129,7 @@ private:
c.mov(*addr, CPU.PC + 4); c.mov(*addr, CPU.PC + 4);
c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); 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.cmp(cpu_word(GPR[rt]._u16[6]), 0);
c.cmovne(*pos_var, *addr); c.cmovne(*pos_var, *addr);
c.shr(*pos_var, 2); c.shr(*pos_var, 2);
@ -1185,10 +1137,12 @@ private:
} }
void BIHNZ(u32 intr, u32 rt, u32 ra) void BIHNZ(u32 intr, u32 rt, u32 ra)
{ {
if (intr) switch (intr)
{ {
UNIMPLEMENTED(); case 0: break;
return; case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
} }
c.mov(cpu_dword(PC), CPU.PC); c.mov(cpu_dword(PC), CPU.PC);
@ -1196,6 +1150,7 @@ private:
c.mov(*addr, CPU.PC + 4); c.mov(*addr, CPU.PC + 4);
c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); 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.cmp(cpu_word(GPR[rt]._u16[6]), 0);
c.cmove(*pos_var, *addr); c.cmove(*pos_var, *addr);
c.shr(*pos_var, 2); c.shr(*pos_var, 2);
@ -1234,25 +1189,30 @@ private:
} }
void BI(u32 intr, u32 ra) void BI(u32 intr, u32 ra)
{ {
if (intr) switch (intr)
{ {
UNIMPLEMENTED(); case 0: break;
return; case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
} }
c.mov(cpu_dword(PC), CPU.PC); c.mov(cpu_dword(PC), CPU.PC);
do_finalize = true; do_finalize = true;
c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); 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); c.shr(*pos_var, 2);
LOG_OPCODE(); LOG_OPCODE();
} }
void BISL(u32 intr, u32 rt, u32 ra) void BISL(u32 intr, u32 rt, u32 ra)
{ {
if (intr) switch (intr)
{ {
UNIMPLEMENTED(); case 0: break;
return; case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
} }
XmmInvalidate(rt); XmmInvalidate(rt);
@ -1267,6 +1227,7 @@ private:
c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3])); c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3]));
c.mov(cpu_dword(GPR[rt]._u32[3]), CPU.PC + 4); c.mov(cpu_dword(GPR[rt]._u32[3]), CPU.PC + 4);
c.shr(*pos_var, 2); c.shr(*pos_var, 2);
c.or_(*pos_var, 0x2000000);
LOG_OPCODE(); LOG_OPCODE();
} }
void IRET(u32 ra) void IRET(u32 ra)
@ -1423,18 +1384,21 @@ private:
} }
void CBX(u32 rt, u32 ra, u32 rb) void CBX(u32 rt, u32 ra, u32 rb)
{ {
c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); c.mov(*addr, cpu_dword(GPR[rb]._u32[3]));
if (ra == rb) if (ra == 1)
{
// assuming that SP % 16 is always zero
}
else if (ra == rb)
{ {
c.add(*addr, *addr); c.add(*addr, *addr);
} }
else 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.and_(*addr, 0xf);
c.neg(*addr);
c.add(*addr, 0xf);
const XmmLink& vr = XmmAlloc(rt); const XmmLink& vr = XmmAlloc(rt);
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f))); c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt); XmmFinalize(vr, rt);
@ -1444,18 +1408,21 @@ private:
} }
void CHX(u32 rt, u32 ra, u32 rb) void CHX(u32 rt, u32 ra, u32 rb)
{ {
c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); c.mov(*addr, cpu_dword(GPR[rb]._u32[3]));
if (ra == rb) if (ra == 1)
{
// assuming that SP % 16 is always zero
}
else if (ra == rb)
{ {
c.add(*addr, *addr); c.add(*addr, *addr);
} }
else 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.and_(*addr, 0xe);
c.neg(*addr);
c.add(*addr, 0xe);
const XmmLink& vr = XmmAlloc(rt); const XmmLink& vr = XmmAlloc(rt);
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f))); c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt); XmmFinalize(vr, rt);
@ -1465,18 +1432,21 @@ private:
} }
void CWX(u32 rt, u32 ra, u32 rb) void CWX(u32 rt, u32 ra, u32 rb)
{ {
c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); c.mov(*addr, cpu_dword(GPR[rb]._u32[3]));
if (ra == rb) if (ra == 1)
{
// assuming that SP % 16 is always zero
}
else if (ra == rb)
{ {
c.add(*addr, *addr); c.add(*addr, *addr);
} }
else 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.and_(*addr, 0xc);
c.neg(*addr);
c.add(*addr, 0xc);
const XmmLink& vr = XmmAlloc(rt); const XmmLink& vr = XmmAlloc(rt);
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f))); c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt); XmmFinalize(vr, rt);
@ -1486,18 +1456,21 @@ private:
} }
void CDX(u32 rt, u32 ra, u32 rb) void CDX(u32 rt, u32 ra, u32 rb)
{ {
c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); c.mov(*addr, cpu_dword(GPR[rb]._u32[3]));
if (ra == rb) if (ra == 1)
{
// assuming that SP % 16 is always zero
}
else if (ra == rb)
{ {
c.add(*addr, *addr); c.add(*addr, *addr);
} }
else 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.and_(*addr, 0x8);
c.neg(*addr);
c.add(*addr, 0x8);
const XmmLink& vr = XmmAlloc(rt); const XmmLink& vr = XmmAlloc(rt);
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f))); c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt); XmmFinalize(vr, rt);
@ -1593,60 +1566,104 @@ private:
LOG_OPCODE(); LOG_OPCODE();
} }
void CBD(u32 rt, u32 ra, s32 i7) 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.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
c.add(*addr, i7); c.add(*addr, i7);
c.not_(*addr);
c.and_(*addr, 0xf); c.and_(*addr, 0xf);
c.neg(*addr);
c.add(*addr, 0xf);
const XmmLink& vr = XmmAlloc(rt); const XmmLink& vr = XmmAlloc(rt);
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f))); c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt); XmmFinalize(vr, rt);
XmmInvalidate(rt); XmmInvalidate(rt);
c.mov(byte_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u8[0])), 0x03); c.mov(byte_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u8[0])), 0x03);
}
LOG_OPCODE(); LOG_OPCODE();
} }
void CHD(u32 rt, u32 ra, s32 i7) 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.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
c.add(*addr, i7); c.add(*addr, i7);
c.not_(*addr);
c.and_(*addr, 0xe); c.and_(*addr, 0xe);
c.neg(*addr);
c.add(*addr, 0xe);
const XmmLink& vr = XmmAlloc(rt); const XmmLink& vr = XmmAlloc(rt);
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f))); c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt); XmmFinalize(vr, rt);
XmmInvalidate(rt); XmmInvalidate(rt);
c.mov(word_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u16[0])), 0x0203); c.mov(word_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u16[0])), 0x0203);
}
LOG_OPCODE(); LOG_OPCODE();
} }
void CWD(u32 rt, u32 ra, s32 i7) 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.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
c.add(*addr, i7); c.add(*addr, i7);
c.not_(*addr);
c.and_(*addr, 0xc); c.and_(*addr, 0xc);
c.neg(*addr);
c.add(*addr, 0xc);
const XmmLink& vr = XmmAlloc(rt); const XmmLink& vr = XmmAlloc(rt);
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f))); c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt); XmmFinalize(vr, rt);
XmmInvalidate(rt); XmmInvalidate(rt);
c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[0])), 0x00010203); c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[0])), 0x00010203);
}
LOG_OPCODE(); LOG_OPCODE();
} }
void CDD(u32 rt, u32 ra, s32 i7) 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.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
c.add(*addr, i7); c.add(*addr, i7);
c.not_(*addr);
c.and_(*addr, 0x8); c.and_(*addr, 0x8);
c.neg(*addr);
c.add(*addr, 0x8);
const XmmLink& vr = XmmAlloc(rt); const XmmLink& vr = XmmAlloc(rt);
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f))); c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt); XmmFinalize(vr, rt);
XmmInvalidate(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[0])), 0x04050607);
c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[1])), 0x00010203); c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[1])), 0x00010203);
}
LOG_OPCODE(); LOG_OPCODE();
} }
void ROTQBII(u32 rt, u32 ra, s32 i7) void ROTQBII(u32 rt, u32 ra, s32 i7)
@ -1947,23 +1964,22 @@ private:
{ {
c.mov(*addr, cpu_dword(GPR[ra]._s32[3])); c.mov(*addr, cpu_dword(GPR[ra]._s32[3]));
c.cmp(*addr, cpu_dword(GPR[rb]._s32[3])); c.cmp(*addr, cpu_dword(GPR[rb]._s32[3]));
c.mov(*addr, 0);
c.setg(addr->r8()); c.setg(addr->r8());
c.neg(*addr); c.shl(*addr, 24);
c.mov(*pos_var, (CPU.PC >> 2) + 1); c.mov(*pos_var, (CPU.PC >> 2) + 1);
c.xor_(*pos_var, *addr); c.or_(*pos_var, *addr);
do_finalize = true; do_finalize = true;
LOG_OPCODE(); LOG_OPCODE();
} }
void CLZ(u32 rt, u32 ra) void CLZ(u32 rt, u32 ra)
{ {
XmmInvalidate(rt); XmmInvalidate(rt);
c.mov(*qw0, 32 + 31);
for (u32 i = 0; i < 4; i++) for (u32 i = 0; i < 4; i++)
{ {
c.bsr(*addr, cpu_dword(GPR[ra]._u32[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.cmovz(*addr, qw0->r32());
c.neg(*addr); c.xor_(*addr, 31);
c.add(*addr, 31);
c.mov(cpu_dword(GPR[rt]._u32[i]), *addr); c.mov(cpu_dword(GPR[rt]._u32[i]), *addr);
} }
LOG_OPCODE(); LOG_OPCODE();
@ -2308,11 +2324,10 @@ private:
{ {
c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
c.cmp(*addr, cpu_dword(GPR[rb]._u32[3])); c.cmp(*addr, cpu_dword(GPR[rb]._u32[3]));
c.mov(*addr, 0);
c.seta(addr->r8()); c.seta(addr->r8());
c.neg(*addr); c.shl(*addr, 24);
c.mov(*pos_var, (CPU.PC >> 2) + 1); c.mov(*pos_var, (CPU.PC >> 2) + 1);
c.xor_(*pos_var, *addr); c.or_(*pos_var, *addr);
do_finalize = true; do_finalize = true;
LOG_OPCODE(); LOG_OPCODE();
} }
@ -2662,11 +2677,10 @@ private:
{ {
c.mov(*addr, cpu_dword(GPR[ra]._s32[3])); c.mov(*addr, cpu_dword(GPR[ra]._s32[3]));
c.cmp(*addr, cpu_dword(GPR[rb]._s32[3])); c.cmp(*addr, cpu_dword(GPR[rb]._s32[3]));
c.mov(*addr, 0);
c.sete(addr->r8()); c.sete(addr->r8());
c.neg(*addr); c.shl(*addr, 24);
c.mov(*pos_var, (CPU.PC >> 2) + 1); c.mov(*pos_var, (CPU.PC >> 2) + 1);
c.xor_(*pos_var, *addr); c.or_(*pos_var, *addr);
do_finalize = true; do_finalize = true;
LOG_OPCODE(); LOG_OPCODE();
} }
@ -3324,11 +3338,10 @@ private:
{ {
c.mov(*addr, cpu_dword(GPR[ra]._s32[3])); c.mov(*addr, cpu_dword(GPR[ra]._s32[3]));
c.cmp(*addr, i10); c.cmp(*addr, i10);
c.mov(*addr, 0);
c.setg(addr->r8()); c.setg(addr->r8());
c.neg(*addr); c.shl(*addr, 24);
c.mov(*pos_var, (CPU.PC >> 2) + 1); c.mov(*pos_var, (CPU.PC >> 2) + 1);
c.xor_(*pos_var, *addr); c.or_(*pos_var, *addr);
do_finalize = true; do_finalize = true;
LOG_OPCODE(); LOG_OPCODE();
} }
@ -3390,11 +3403,10 @@ private:
{ {
c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
c.cmp(*addr, i10); c.cmp(*addr, i10);
c.mov(*addr, 0);
c.seta(addr->r8()); c.seta(addr->r8());
c.neg(*addr); c.shl(*addr, 24);
c.mov(*pos_var, (CPU.PC >> 2) + 1); c.mov(*pos_var, (CPU.PC >> 2) + 1);
c.xor_(*pos_var, *addr); c.or_(*pos_var, *addr);
do_finalize = true; do_finalize = true;
LOG_OPCODE(); LOG_OPCODE();
} }
@ -3441,11 +3453,10 @@ private:
{ {
c.mov(*addr, cpu_dword(GPR[ra]._u32[3])); c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
c.cmp(*addr, i10); c.cmp(*addr, i10);
c.mov(*addr, 0);
c.sete(addr->r8()); c.sete(addr->r8());
c.neg(*addr); c.shl(*addr, 24);
c.mov(*pos_var, (CPU.PC >> 2) + 1); c.mov(*pos_var, (CPU.PC >> 2) + 1);
c.xor_(*pos_var, *addr); c.or_(*pos_var, *addr);
do_finalize = true; do_finalize = true;
LOG_OPCODE(); LOG_OPCODE();
} }
@ -3517,6 +3528,16 @@ private:
} }
WRAPPER_END(rc, rt, ra, rb);*/ 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& v0 = XmmGet(rc); // v0 = mask
const XmmLink& v1 = XmmAlloc(); const XmmLink& v1 = XmmAlloc();
const XmmLink& v2 = XmmCopy(v0); // v2 = mask const XmmLink& v2 = XmmCopy(v0); // v2 = mask

View File

@ -13,13 +13,14 @@
#include "SPUInterpreter.h" #include "SPUInterpreter.h"
#include "SPURecompiler.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) SPURecompilerCore::SPURecompilerCore(SPUThread& cpu)
: m_enc(new SPURecompiler(cpu, *this)) : m_enc(new SPURecompiler(cpu, *this))
, inter(new SPUInterpreter(cpu)) , inter(new SPUInterpreter(cpu))
, CPU(cpu) , CPU(cpu)
, first(true) , first(true)
, need_check(false)
{ {
memset(entry, 0, sizeof(entry)); memset(entry, 0, sizeof(entry));
X86CpuInfo inf; X86CpuInfo inf;
@ -48,7 +49,7 @@ void SPURecompilerCore::Compile(u16 pos)
u64 time0 = 0; u64 time0 = 0;
SPUDisAsm dis_asm(CPUDisAsm_InterpreterMode); 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 stringLogger;
stringLogger.setOption(kLoggerOptionBinaryForm, true); stringLogger.setOption(kLoggerOptionBinaryForm, true);
@ -102,7 +103,7 @@ void SPURecompilerCore::Compile(u16 pos)
while (true) 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; m_enc->do_finalize = false;
if (opcode) if (opcode)
{ {
@ -181,8 +182,8 @@ void SPURecompilerCore::Compile(u16 pos)
u8 SPURecompilerCore::DecodeMemory(const u32 address) u8 SPURecompilerCore::DecodeMemory(const u32 address)
{ {
assert(CPU.dmac.ls_offset == address - CPU.PC); assert(CPU.ls_offset == address - CPU.PC);
const u32 m_offset = CPU.dmac.ls_offset; const u32 m_offset = CPU.ls_offset;
const u16 pos = (u16)(CPU.PC >> 2); const u16 pos = (u16)(CPU.PC >> 2);
//ConLog.Write("DecodeMemory: pos=%d", pos); //ConLog.Write("DecodeMemory: pos=%d", pos);
@ -192,20 +193,26 @@ u8 SPURecompilerCore::DecodeMemory(const u32 address)
{ {
// check data (hard way) // check data (hard way)
bool is_valid = true; bool is_valid = true;
//for (u32 i = pos; i < (u32)(entry[pos].count + pos); i++) if (need_check)
//{ {
// if (entry[i].valid != ls[i]) for (u32 i = 0; i < 0x10000; i++)
// { {
// is_valid = false; if (entry[i].valid && entry[i].valid != ls[i])
// break; {
// } is_valid = false;
//} break;
}
}
need_check = false;
}
// invalidate if necessary // invalidate if necessary
if (!is_valid) if (!is_valid)
{ {
for (u32 i = 0; i < 0x10000; i++) 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)entry[i].count > (u32)pos &&
i < (u32)pos + (u32)entry[pos].count) i < (u32)pos + (u32)entry[pos].count)
{ {
@ -214,6 +221,11 @@ u8 SPURecompilerCore::DecodeMemory(const u32 address)
//RtlDeleteFunctionTable(&entry[i].info); //RtlDeleteFunctionTable(&entry[i].info);
#endif #endif
entry[i].pointer = nullptr; 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)); //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; u32 res = pos;
res = func(cpu, vm::get_ptr<void>(m_offset), imm_table.data(), &g_imm_table); 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.SPU.Status.SetValue(SPU_STATUS_STOPPED_BY_HALT);
CPU.Stop(); CPU.Stop();
res = ~res; res &= ~0x1000000;
}
if (res & 0x2000000)
{
need_check = true;
res &= ~0x2000000;
} }
if (did_compile) if (did_compile)

View File

@ -50,7 +50,15 @@ void SPUThread::Task()
const int round = std::fegetround(); const int round = std::fegetround();
std::fesetround(FE_TOWARDZERO); std::fesetround(FE_TOWARDZERO);
if (m_custom_task)
{
m_custom_task(*this);
}
else
{
CPUThread::Task(); CPUThread::Task();
}
if (std::fegetround() != FE_TOWARDZERO) if (std::fegetround() != FE_TOWARDZERO)
{ {
LOG_ERROR(Log::SPU, "Rounding mode has changed(%d)", std::fegetround()); LOG_ERROR(Log::SPU, "Rounding mode has changed(%d)", std::fegetround());
@ -68,11 +76,11 @@ void SPUThread::DoReset()
void SPUThread::InitRegs() void SPUThread::InitRegs()
{ {
GPR[1]._u32[3] = 0x40000 - 120; GPR[1]._u32[3] = 0x3FFF0; // initial stack frame pointer
cfg.Reset(); cfg.Reset();
dmac.ls_offset = m_offset; ls_offset = m_offset;
SPU.Status.SetValue(SPU_STATUS_STOPPED); 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) void SPUThread::WriteSNR(bool number, u32 value)
{ {
if (cfg.value & ((u64)1 << (u64)number)) 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)) if ((addr <= 0x3ffff) && (addr + size <= 0x40000))
{ {
// LS access // 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)) 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; return;
} }
else else
@ -208,13 +241,13 @@ void SPUThread::ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
{ {
case MFC_PUT_CMD: case MFC_PUT_CMD:
{ {
vm::write32(ea, ReadLS32(lsa)); vm::write32((u32)ea, ReadLS32(lsa));
return; return;
} }
case MFC_GET_CMD: case MFC_GET_CMD:
{ {
WriteLS32(lsa, vm::read32(ea)); WriteLS32(lsa, vm::read32((u32)ea));
return; return;
} }
@ -231,13 +264,13 @@ void SPUThread::ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
{ {
case MFC_PUT_CMD: 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; return;
} }
case MFC_GET_CMD: 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; 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++) 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; 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); LOG_ERROR(Log::SPU, "DMA List: invalid transfer size(%d)", size);
result = MFC_PPU_DMA_CMD_SEQUENCE_ERROR; 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; u32 addr = rec->ea;
if (size)
ProcessCmd(cmd, tag, lsa | (addr & 0xf), addr, 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)", 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)); i, list_size, (u16)rec->s, (u16)rec->ts, (u32)rec->ea, lsa | (addr & 0xf));
if (size)
lsa += std::max(size, (u32)16); lsa += std::max(size, (u32)16);
if (rec->s.ToBE() & se16(0x8000)) if (rec->s.ToBE() & se16(0x8000))
@ -366,6 +402,17 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
op == MFC_PUTLLUC_CMD ? "PUTLLUC" : "PUTQLLUC"), op == MFC_PUTLLUC_CMD ? "PUTLLUC" : "PUTQLLUC"),
lsa, ea, tag, size, cmd); 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 (op == MFC_GETLLAR_CMD) // get reservation
{ {
if (R_ADDR) if (R_ADDR)
@ -376,8 +423,8 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
R_ADDR = ea; R_ADDR = ea;
for (u32 i = 0; i < 16; i++) for (u32 i = 0; i < 16; i++)
{ {
R_DATA[i] = vm::get_ptr<u64>(R_ADDR)[i]; R_DATA[i] = vm::get_ptr<u64>((u32)R_ADDR)[i];
vm::get_ptr<u64>(dmac.ls_offset + lsa)[i] = R_DATA[i]; vm::get_ptr<u64>(ls_offset + lsa)[i] = R_DATA[i];
} }
MFCArgs.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS); MFCArgs.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS);
} }
@ -391,12 +438,12 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
u64 buf[16]; u64 buf[16];
for (u32 i = 0; i < 16; i++) 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]) if (buf[i] != R_DATA[i])
{ {
changed++; changed++;
mask |= (0x3 << (i * 2)); 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; m_events |= SPU_EVENT_LR;
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE); MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE);
@ -410,7 +457,7 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
{ {
if (buf[i] != R_DATA[i]) 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; m_events |= SPU_EVENT_LR;
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE); 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) for (s32 i = (s32)PC; i < (s32)PC + 4 * 7; i += 4)
{ {
dis_asm.dump_pc = i; dis_asm.dump_pc = i;
dis_asm.offset = vm::get_ptr<u8>(dmac.ls_offset); dis_asm.offset = vm::get_ptr<u8>(ls_offset);
const u32 opcode = vm::read32(i + dmac.ls_offset); const u32 opcode = vm::read32(i + ls_offset);
(*SPU_instr::rrr_list)(&dis_asm, opcode); (*SPU_instr::rrr_list)(&dis_asm, opcode);
if (i >= 0 && i < 0x40000) if (i >= 0 && i < 0x40000)
{ {
@ -454,7 +501,7 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
} }
else // store unconditional else // store unconditional
{ {
if (R_ADDR) if (R_ADDR) // may be wrong
{ {
m_events |= SPU_EVENT_LR; m_events |= SPU_EVENT_LR;
} }
@ -484,7 +531,7 @@ bool SPUThread::CheckEvents()
{ {
for (u32 i = 0; i < 16; i++) 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; m_events |= SPU_EVENT_LR;
R_ADDR = 0; R_ADDR = 0;
@ -498,18 +545,20 @@ bool SPUThread::CheckEvents()
u32 SPUThread::GetChannelCount(u32 ch) u32 SPUThread::GetChannelCount(u32 ch)
{ {
u32 res = 0xdeafbeef;
switch (ch) switch (ch)
{ {
case SPU_WrOutMbox: return SPU.Out_MBox.GetFreeCount(); case SPU_WrOutMbox: res = SPU.Out_MBox.GetFreeCount(); break;
case SPU_WrOutIntrMbox: return SPU.Out_IntrMBox.GetFreeCount(); case SPU_WrOutIntrMbox: res = SPU.Out_IntrMBox.GetFreeCount(); break;
case SPU_RdInMbox: return SPU.In_MBox.GetCount(); case SPU_RdInMbox: res = SPU.In_MBox.GetCount(); break;
case MFC_RdTagStat: return MFC1.TagStatus.GetCount(); case MFC_RdTagStat: res = MFC1.TagStatus.GetCount(); break;
case MFC_RdListStallStat: return StallStat.GetCount(); case MFC_RdListStallStat: res = StallStat.GetCount(); break;
case MFC_WrTagUpdate: return MFC1.TagStatus.GetCount(); // hack case MFC_WrTagUpdate: res = MFC1.TagStatus.GetCount(); break;// hack
case SPU_RdSigNotify1: return SPU.SNR[0].GetCount(); case SPU_RdSigNotify1: res = SPU.SNR[0].GetCount(); break;
case SPU_RdSigNotify2: return SPU.SNR[1].GetCount(); case SPU_RdSigNotify2: res = SPU.SNR[1].GetCount(); break;
case MFC_RdAtomicStat: return MFC1.AtomicStat.GetCount(); case MFC_RdAtomicStat: res = MFC1.AtomicStat.GetCount(); break;
case SPU_RdEventStat: return CheckEvents() ? 1 : 0; case SPU_RdEventStat: res = CheckEvents() ? 1 : 0; break;
default: default:
{ {
@ -518,12 +567,17 @@ u32 SPUThread::GetChannelCount(u32 ch)
return 0; 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) void SPUThread::WriteChannel(u32 ch, const u128& r)
{ {
const u32 v = r._u32[3]; const u32 v = r._u32[3];
//LOG_NOTICE(Log::SPU, "%s(%s): v=0x%x", __FUNCTION__, spu_ch_name[ch], v);
switch (ch) switch (ch)
{ {
case SPU_WrOutIntrMbox: case SPU_WrOutIntrMbox:
@ -879,14 +933,28 @@ void SPUThread::ReadChannel(u128& r, u32 ch)
} }
case SPU_RdSigNotify1: 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)); while (!SPU.SNR[0].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
break; break;
} }
case SPU_RdSigNotify2: 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)); while (!SPU.SNR[1].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
break; 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]); 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) void SPUThread::StopAndSignal(u32 code)
@ -945,6 +1015,24 @@ void SPUThread::StopAndSignal(u32 code)
switch (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: case 0x110:
{ {
/* ===== sys_spu_thread_receive_event ===== */ /* ===== sys_spu_thread_receive_event ===== */
@ -1075,7 +1163,6 @@ void SPUThread::StopAndSignal(u32 code)
} }
default: default:
{
if (!SPU.Out_MBox.GetCount()) if (!SPU.Out_MBox.GetCount())
{ {
LOG_ERROR(Log::SPU, "Unknown STOP code: 0x%x (no message)", code); 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()); LOG_ERROR(Log::SPU, "Unknown STOP code: 0x%x (message=0x%x)", code, SPU.Out_MBox.GetValue());
} }
Stop(); Emu.Pause();
break; 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;
} }

View File

@ -1,4 +1,5 @@
#pragma once #pragma once
#include "Emu/Memory/atomic_type.h"
#include "PPCThread.h" #include "PPCThread.h"
#include "Emu/Event.h" #include "Emu/Event.h"
#include "MFC.h" #include "MFC.h"
@ -104,6 +105,66 @@ enum
SPU_RdSigNotify2_offs = 0x1C00C, 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 //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 //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 class FPSCR
@ -246,181 +307,127 @@ public:
} }
} m_intrtag[3]; } m_intrtag[3];
template<size_t _max_count> // limited lock-free queue, most functions are barrier-free
template<size_t max_count>
class Channel class Channel
{ {
public: static_assert(max_count >= 1, "Invalid channel count");
static const size_t max_count = _max_count;
private: struct ChannelData
union _CRT_ALIGN(8) { {
struct { u32 value;
volatile u32 m_index; u32 is_set;
u32 m_value[max_count];
}; };
volatile u64 m_indval;
}; atomic_t<ChannelData> m_data[max_count];
std::mutex m_lock; size_t m_push;
size_t m_pop;
public: public:
Channel() __noinline Channel()
{ {
Init(); for (size_t i = 0; i < max_count; i++)
}
void Init()
{ {
m_indval = 0; m_data[i].write_relaxed({});
}
__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_push = 0;
m_pop = 0;
} }
__forceinline void PopUncond(u32& res) __forceinline void PopUncond(u32& res)
{ {
if (max_count > 1) res = m_data[m_pop].read_relaxed().value;
{ m_data[m_pop].write_relaxed({});
std::lock_guard<std::mutex> lock(m_lock); m_pop = (m_pop + 1) % max_count;
if(!m_index)
res = 0; //result is undefined
else
{
res = m_value[--m_index];
m_value[m_index] = 0;
} }
__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 else
{ //lock-free
if(!m_index)
res = 0;
else
{ {
res = (m_indval >> 32); return false;
m_indval = 0;
}
} }
} }
__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); res = data.value;
return m_index; m_pop = (m_pop + 1) % max_count;
return true;
} }
else 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); m_data[m_push].write_relaxed({ value, 1 });
return max_count - m_index; 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 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; }; struct { u32 EAH, EAL; };
}; };
DMAC dmac; u32 ls_offset;
void ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size); 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 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); } 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: public:
SPUThread(CPUThreadType type = CPU_THREAD_SPU); SPUThread(CPUThreadType type = CPU_THREAD_SPU);
virtual ~SPUThread(); virtual ~SPUThread();
@ -560,6 +570,8 @@ public:
public: public:
virtual void InitRegs(); virtual void InitRegs();
virtual void Task(); virtual void Task();
void FastCall(u32 ls_addr);
void FastStop();
protected: protected:
virtual void DoReset(); virtual void DoReset();
@ -571,3 +583,49 @@ protected:
}; };
SPUThread& GetCurrentSPUThread(); 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;
}
};

View File

@ -4,33 +4,94 @@
#include "Emu/HDD/HDD.h" #include "Emu/HDD/HDD.h"
#include "vfsDeviceLocalFile.h" #include "vfsDeviceLocalFile.h"
#include "Ini.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) int sort_devices(const void* _a, const void* _b)
{ {
const vfsDevice& a = **(const vfsDevice**)_a; const vfsDevice& a = **(const vfsDevice**)_a;
const vfsDevice& b = **(const vfsDevice**)_b; 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; 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() VFS::~VFS()
{ {
UnMountAll(); 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) 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); 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); //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) 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]; delete m_devices[i];
m_devices.erase(m_devices.begin() +i); m_devices.erase(m_devices.begin() +i);
return; return;
@ -63,9 +127,9 @@ void VFS::UnMountAll()
vfsFileBase* VFS::OpenFile(const std::string& ps3_path, vfsOpenMode mode) const vfsFileBase* VFS::OpenFile(const std::string& ps3_path, vfsOpenMode mode) const
{ {
std::string path; 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); res->Open(path, mode);
return res; return res;
@ -79,9 +143,9 @@ vfsDirBase* VFS::OpenDir(const std::string& ps3_path) const
{ {
std::string path; 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); res->Open(path);
return res; return res;
@ -94,11 +158,11 @@ vfsDirBase* VFS::OpenDir(const std::string& ps3_path) const
bool VFS::CreateFile(const std::string& ps3_path) const bool VFS::CreateFile(const std::string& ps3_path) const
{ {
std::string path; std::string path;
if(vfsDevice* dev = GetDevice(ps3_path, path)) if (vfsDevice* dev = GetDevice(ps3_path, path))
{ {
std::shared_ptr<vfsFileBase> res(dev->GetNewFileStream()); std::shared_ptr<vfsFileBase> res(dev->GetNewFileStream());
if(res) if (res)
{ {
return res->Create(path); 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 bool VFS::CreateDir(const std::string& ps3_path) const
{ {
std::string path; std::string path;
if(vfsDevice* dev = GetDevice(ps3_path, path)) if (vfsDevice* dev = GetDevice(ps3_path, path))
{ {
std::shared_ptr<vfsDirBase> res(dev->GetNewDirStream()); std::shared_ptr<vfsDirBase> res(dev->GetNewDirStream());
if(res) if (res)
{ {
return res->Create(path); 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 bool VFS::RemoveFile(const std::string& ps3_path) const
{ {
std::string path; std::string path;
if(vfsDevice* dev = GetDevice(ps3_path, path)) if (vfsDevice* dev = GetDevice(ps3_path, path))
{ {
std::shared_ptr<vfsFileBase> res(dev->GetNewFileStream()); std::shared_ptr<vfsFileBase> res(dev->GetNewFileStream());
if(res) if (res)
{ {
return res->Remove(path); 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 bool VFS::RemoveDir(const std::string& ps3_path) const
{ {
std::string path; std::string path;
if(vfsDevice* dev = GetDevice(ps3_path, path)) if (vfsDevice* dev = GetDevice(ps3_path, path))
{ {
std::shared_ptr<vfsDirBase> res(dev->GetNewDirStream()); std::shared_ptr<vfsDirBase> res(dev->GetNewDirStream());
if(res) if (res)
{ {
return res->Remove(path); 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 bool VFS::ExistsFile(const std::string& ps3_path) const
{ {
std::string path; std::string path;
if(vfsDevice* dev = GetDevice(ps3_path, path)) if (vfsDevice* dev = GetDevice(ps3_path, path))
{ {
std::shared_ptr<vfsFileBase> res(dev->GetNewFileStream()); std::shared_ptr<vfsFileBase> res(dev->GetNewFileStream());
if(res) if (res)
{ {
return res->Exists(path); 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 bool VFS::ExistsDir(const std::string& ps3_path) const
{ {
std::string path; std::string path;
if(vfsDevice* dev = GetDevice(ps3_path, path)) if (vfsDevice* dev = GetDevice(ps3_path, path))
{ {
std::shared_ptr<vfsDirBase> res(dev->GetNewDirStream()); std::shared_ptr<vfsDirBase> res(dev->GetNewDirStream());
if(res) if (res)
{ {
return res->IsExists(path); 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 bool VFS::RenameFile(const std::string& ps3_path_from, const std::string& ps3_path_to) const
{ {
std::string path; 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()); std::shared_ptr<vfsFileBase> res(dev->GetNewFileStream());
if(res) if (res)
{ {
return res->Rename(path, ps3_path_to); 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 bool VFS::RenameDir(const std::string& ps3_path_from, const std::string& ps3_path_to) const
{ {
std::string path; 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()); std::shared_ptr<vfsDirBase> res(dev->GetNewDirStream());
if(res) if (res)
{ {
return res->Rename(path, ps3_path_to); 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 vfsDevice* VFS::GetDevice(const std::string& ps3_path, std::string& path) const
{ {
u32 max_eq; auto try_get_device = [this, &path](const std::vector<std::string>& ps3_path_blocks) -> vfsDevice*
s32 max_i=-1;
for(u32 i=0; i<m_devices.size(); ++i)
{ {
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_eq = eq;
max_i = i; max_i = i;
} }
} }
if(max_i < 0) return nullptr; if (max_i < 0)
path = vfsDevice::GetWinPath(m_devices[max_i]->GetLocalPath(), ps3_path.substr(max_eq, ps3_path.length() - max_eq)); 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]; 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 vfsDevice* VFS::GetDeviceLocal(const std::string& local_path, std::string& path) const
{ {
u32 max_eq; size_t max_eq = 0;
s32 max_i=-1; int max_i = -1;
rFileName file_path(local_path); std::vector<std::string> local_path_blocks = simplify_path_blocks(local_path);
file_path.Normalize();
std::string mormalized_path = file_path.GetFullPath();
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_eq = eq;
max_i = i; 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]; return m_devices[max_i];
} }
void VFS::Init(const std::string& path) void VFS::Init(const std::string& path)
{ {
cwd = simplify_path(path, true);
UnMountAll(); UnMountAll();
std::vector<VFSManagerEntry> entries; std::vector<VFSManagerEntry> entries;
@ -293,8 +411,8 @@ void VFS::Init(const std::string& path)
std::string mpath = entry.path; std::string mpath = entry.path;
// TODO: This shouldn't use current dir // TODO: This shouldn't use current dir
fmt::Replace(mpath,"$(EmulatorDir)", "."); fmt::Replace(mpath, "$(EmulatorDir)", Emu.GetEmulatorPath());
fmt::Replace(mpath,"$(GameDir)", vfsDevice::GetRoot(path)); fmt::Replace(mpath, "$(GameDir)", cwd);
Mount(entry.mount, mpath, dev); Mount(entry.mount, mpath, dev);
} }
} }
@ -305,11 +423,11 @@ void VFS::SaveLoadDevices(std::vector<VFSManagerEntry>& res, bool is_load)
entries_count.Init("count", "VFSManager"); entries_count.Init("count", "VFSManager");
int count = 0; int count = 0;
if(is_load) if (is_load)
{ {
count = entries_count.LoadValue(count); 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_hdd0/", "/dev_hdd0/");
res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_hdd1/", "/dev_hdd1/"); 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)", "/app_home/");
res.emplace_back(vfsDevice_LocalFile, "$(GameDir)/../", "/dev_bdvd/"); res.emplace_back(vfsDevice_LocalFile, "$(GameDir)/../", "/dev_bdvd/");
res.emplace_back(vfsDevice_LocalFile, "", "/host_root/"); res.emplace_back(vfsDevice_LocalFile, "", "/host_root/");
res.emplace_back(vfsDevice_LocalFile, "$(GameDir)", "/");
return; 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_mount.Init(fmt::Format("mount[%d]", i), "VFSManager");
entry_device.Init(fmt::Format("device[%d]", i), "VFSManager"); entry_device.Init(fmt::Format("device[%d]", i), "VFSManager");
if(is_load) if (is_load)
{ {
res[i] = VFSManagerEntry(); res[i] = VFSManagerEntry();
res[i].path = entry_path.LoadValue(""); res[i].path = entry_path.LoadValue("");

View File

@ -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 struct VFS
{ {
~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 //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. //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. // A vfsDevice will be deleted when they're unmounted or the VFS struct is destroyed.

View File

@ -1,6 +1,7 @@
#include "stdafx.h" #include "stdafx.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "vfsDevice.h"
#include "VFS.h" #include "VFS.h"
#include "vfsDir.h" #include "vfsDir.h"
@ -10,7 +11,7 @@ vfsDir::vfsDir()
{ {
// TODO: proper implementation // TODO: proper implementation
// m_stream is nullptr here. So open root until a proper dir is given // m_stream is nullptr here. So open root until a proper dir is given
Open("/"); //Open("/");
} }
vfsDir::vfsDir(const std::string& path) vfsDir::vfsDir(const std::string& path)
@ -26,37 +27,78 @@ bool vfsDir::Open(const std::string& path)
m_stream.reset(Emu.GetVFS().OpenDir(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) 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 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 if (path_blocks.empty())
{ return false;
return m_stream->GetEntries();
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) 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) bool vfsDir::Remove(const std::string& path)
{ {
return m_stream->Remove(path); return Emu.GetVFS().RemoveDir(path);
}
const DirEntryInfo* vfsDir::Read()
{
return m_stream->Read();
} }
void vfsDir::Close() void vfsDir::Close()
@ -64,12 +106,7 @@ void vfsDir::Close()
m_stream.reset(); m_stream.reset();
} }
std::string vfsDir::GetPath() const
{
return m_stream->GetPath();
}
bool vfsDir::IsOpened() const bool vfsDir::IsOpened() const
{ {
return m_stream && m_stream->IsOpened(); return !m_entries.empty();
} }

View File

@ -13,13 +13,11 @@ public:
virtual bool Open(const std::string& path) override; virtual bool Open(const std::string& path) override;
virtual bool IsOpened() const override; virtual bool IsOpened() const override;
virtual bool IsExists(const std::string& path) const override; virtual bool IsExists(const std::string& path) const override;
virtual const std::vector<DirEntryInfo>& GetEntries() const override;
virtual void Close() 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 std::string& path) override;
//virtual bool Create(const DirEntryInfo& info) override; //virtual bool Create(const DirEntryInfo& info) override;
virtual bool Rename(const std::string& from, const std::string& to) override; virtual bool Rename(const std::string& from, const std::string& to) override;
virtual bool Remove(const std::string& path) override; virtual bool Remove(const std::string& path) override;
virtual const DirEntryInfo* Read() override;
}; };

View File

@ -32,7 +32,7 @@ bool vfsDirBase::IsOpened() const
bool vfsDirBase::IsExists(const std::string& path) const bool vfsDirBase::IsExists(const std::string& path) const
{ {
return rExists(path); return false;
} }
const std::vector<DirEntryInfo>& vfsDirBase::GetEntries() const const std::vector<DirEntryInfo>& vfsDirBase::GetEntries() const
@ -58,3 +58,9 @@ const DirEntryInfo* vfsDirBase::Read()
return &m_entries[m_pos++]; return &m_entries[m_pos++];
} }
const DirEntryInfo* vfsDirBase::First()
{
m_pos = 0;
return Read();
}

View File

@ -53,4 +53,57 @@ public:
virtual bool Rename(const std::string& from, const std::string& to) = 0; virtual bool Rename(const std::string& from, const std::string& to) = 0;
virtual bool Remove(const std::string& path) = 0; virtual bool Remove(const std::string& path) = 0;
virtual const DirEntryInfo* Read(); 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);
}
}; };

View File

@ -21,7 +21,7 @@ bool vfsLocalDir::Open(const std::string& path)
std::string name; std::string name;
for(bool is_ok = dir.GetFirst(&name); is_ok; is_ok = dir.GetNext(&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(); m_entries.emplace_back();
// TODO: Use same info structure as fileinfo? // TODO: Use same info structure as fileinfo?
@ -46,6 +46,11 @@ bool vfsLocalDir::Create(const std::string& path)
return rMkpath(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) bool vfsLocalDir::Rename(const std::string& from, const std::string& to)
{ {
return false; return false;

View File

@ -18,4 +18,5 @@ public:
virtual bool Rename(const std::string& from, const std::string& to) override; virtual bool Rename(const std::string& from, const std::string& to) override;
virtual bool Remove(const std::string& path) override; virtual bool Remove(const std::string& path) override;
virtual bool IsOpened() const override; virtual bool IsOpened() const override;
virtual bool IsExists(const std::string& path) const;
}; };

View File

@ -59,12 +59,13 @@ public:
} }
}; };
struct ID class ID
{ {
std::string m_name; std::string m_name;
IDData* m_data; IDData* m_data;
IDType m_type; IDType m_type;
public:
template<typename T> template<typename T>
ID(const std::string& name, T* data, const IDType type) ID(const std::string& name, T* data, const IDType type)
: m_name(name) : m_name(name)
@ -96,6 +97,21 @@ struct ID
{ {
delete m_data; 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 class IdManager
@ -172,7 +188,7 @@ public:
return false; return false;
} }
result = f->second.m_data->get<T>(); result = f->second.GetData()->get<T>();
return true; return true;
} }
@ -198,8 +214,8 @@ public:
if (item == m_id_map.end()) { if (item == m_id_map.end()) {
return false; return false;
} }
if (item->second.m_type < TYPE_OTHER) { if (item->second.GetType() < TYPE_OTHER) {
m_types[item->second.m_type].erase(id); m_types[item->second.GetType()].erase(id);
} }
item->second.Kill(); item->second.Kill();

View File

@ -108,9 +108,9 @@ void MemoryBase::Init(MemoryType type)
memset(RawSPUMem, 0, sizeof(RawSPUMem)); memset(RawSPUMem, 0, sizeof(RawSPUMem));
#ifdef _WIN32 #ifdef _WIN32
if (!m_base_addr) if (!vm::g_base_addr)
#else #else
if ((s64)m_base_addr == (s64)-1) if ((s64)vm::g_base_addr == (s64)-1)
#endif #endif
{ {
LOG_ERROR(MEMORY, "Initializing memory failed"); LOG_ERROR(MEMORY, "Initializing memory failed");
@ -119,7 +119,7 @@ void MemoryBase::Init(MemoryType type)
} }
else 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) switch (type)
@ -128,6 +128,7 @@ void MemoryBase::Init(MemoryType type)
MemoryBlocks.push_back(MainMem.SetRange(0x00010000, 0x2FFF0000)); MemoryBlocks.push_back(MainMem.SetRange(0x00010000, 0x2FFF0000));
MemoryBlocks.push_back(UserMemory = PRXMem.SetRange(0x30000000, 0x10000000)); MemoryBlocks.push_back(UserMemory = PRXMem.SetRange(0x30000000, 0x10000000));
MemoryBlocks.push_back(RSXCMDMem.SetRange(0x40000000, 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(MmaperMem.SetRange(0xB0000000, 0x10000000));
MemoryBlocks.push_back(RSXFBMem.SetRange(0xC0000000, 0x10000000)); MemoryBlocks.push_back(RSXFBMem.SetRange(0xC0000000, 0x10000000));
MemoryBlocks.push_back(StackMem.SetRange(0xD0000000, 0x10000000)); MemoryBlocks.push_back(StackMem.SetRange(0xD0000000, 0x10000000));
@ -205,7 +206,7 @@ bool MemoryBase::Map(const u64 addr, const u32 size)
{ {
LV2_LOCK(0); LV2_LOCK(0);
if ((u32)addr != addr || (u64)addr + (u64)size > 0x100000000ull) if ((addr | (addr + size)) & ~0xFFFFFFFFull)
{ {
return false; return false;
} }
@ -218,7 +219,8 @@ bool MemoryBase::Map(const u64 addr, const u32 size)
} }
MemoryBlocks.push_back((new MemoryBlock())->SetRange(addr, 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; return true;
} }
@ -442,6 +444,12 @@ void DynamicMemoryBlockBase::AppendMem(u64 addr, u32 size) /* private */
u64 DynamicMemoryBlockBase::AllocAlign(u32 size, u32 align) 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); size = PAGE_4K(size);
u32 exsize; u32 exsize;
@ -568,9 +576,9 @@ bool VirtualMemoryBlock::IsInMyRange(const u64 addr, const u32 size)
bool VirtualMemoryBlock::IsMyAddress(const u64 addr) 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; return true;
} }
@ -579,26 +587,16 @@ bool VirtualMemoryBlock::IsMyAddress(const u64 addr)
return false; return false;
} }
u64 VirtualMemoryBlock::Map(u64 realaddr, u32 size, u64 addr) u64 VirtualMemoryBlock::Map(u64 realaddr, u32 size)
{ {
if(addr) for (u64 addr = GetStartAddr(); addr <= GetEndAddr() - GetReservedAmount() - size;)
{
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;)
{ {
bool is_good_addr = true; bool is_good_addr = true;
// check if address is already mapped // 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)) (m_mapped_memory[i].addr >= addr && m_mapped_memory[i].addr < addr + size))
{ {
is_good_addr = false; 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); m_mapped_memory.emplace_back(addr, realaddr, size);
@ -615,37 +613,45 @@ u64 VirtualMemoryBlock::Map(u64 realaddr, u32 size, u64 addr)
} }
return 0; 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 (!IsInMyRange(addr, size) && (IsMyAddress(addr) || IsMyAddress(addr + size - 1)))
{ return false;
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;
}
}
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); 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) 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) bool VirtualMemoryBlock::Write32(const u64 addr, const u32 value)
{ {
u64 realAddr; u64 realAddr;
if(!getRealAddr(addr, realAddr)) if (!getRealAddr(addr, realAddr))
return false; return false;
vm::write32(realAddr, value); vm::write32(realAddr, value);
return true; return true;
@ -668,9 +674,9 @@ bool VirtualMemoryBlock::Write32(const u64 addr, const u32 value)
bool VirtualMemoryBlock::getRealAddr(u64 addr, u64& result) 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); result = m_mapped_memory[i].realAddress + (addr - m_mapped_memory[i].addr);
return true; return true;
@ -682,9 +688,9 @@ bool VirtualMemoryBlock::getRealAddr(u64 addr, u64& result)
u64 VirtualMemoryBlock::getMappedAddress(u64 realAddress) 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); return m_mapped_memory[i].addr + (realAddress - m_mapped_memory[i].realAddress);
} }
@ -702,7 +708,7 @@ void VirtualMemoryBlock::Delete()
bool VirtualMemoryBlock::Reserve(u32 size) bool VirtualMemoryBlock::Reserve(u32 size)
{ {
if(size + GetReservedAmount() > GetEndAddr() - GetStartAddr()) if (size + GetReservedAmount() > GetEndAddr() - GetStartAddr())
return false; return false;
m_reserve_size += size; m_reserve_size += size;
@ -711,7 +717,7 @@ bool VirtualMemoryBlock::Reserve(u32 size)
bool VirtualMemoryBlock::Unreserve(u32 size) bool VirtualMemoryBlock::Unreserve(u32 size)
{ {
if(size > GetReservedAmount()) if (size > GetReservedAmount())
return false; return false;
m_reserve_size -= size; m_reserve_size -= size;

View File

@ -7,8 +7,6 @@ using std::nullptr_t;
#define safe_delete(x) do {delete (x);(x)=nullptr;} while(0) #define safe_delete(x) do {delete (x);(x)=nullptr;} while(0)
#define safe_free(x) do {free(x);(x)=nullptr;} while(0) #define safe_free(x) do {free(x);(x)=nullptr;} while(0)
extern void* const m_base_addr;
enum MemoryType enum MemoryType
{ {
Memory_PS3, Memory_PS3,
@ -24,6 +22,11 @@ enum : u32
RAW_SPU_PROB_OFFSET = 0x00040000, RAW_SPU_PROB_OFFSET = 0x00040000,
}; };
namespace vm
{
extern void* const g_base_addr;
}
class MemoryBase class MemoryBase
{ {
std::vector<MemoryBlock*> MemoryBlocks; std::vector<MemoryBlock*> MemoryBlocks;
@ -33,6 +36,7 @@ public:
MemoryBlock* UserMemory; MemoryBlock* UserMemory;
DynamicMemoryBlock MainMem; DynamicMemoryBlock MainMem;
DynamicMemoryBlock SPRXMem;
DynamicMemoryBlock PRXMem; DynamicMemoryBlock PRXMem;
DynamicMemoryBlock RSXCMDMem; DynamicMemoryBlock RSXCMDMem;
DynamicMemoryBlock MmaperMem; DynamicMemoryBlock MmaperMem;
@ -70,7 +74,7 @@ public:
static void* const GetBaseAddr() static void* const GetBaseAddr()
{ {
return m_base_addr; return vm::g_base_addr;
} }
__noinline void InvalidAddress(const char* func, const u64 addr); __noinline void InvalidAddress(const char* func, const u64 addr);

View File

@ -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 // 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) // 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 // 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 // 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 // Reserve a certain amount so no one can use it, returns true on succces, false on failure
virtual bool Reserve(u32 size); virtual bool Reserve(u32 size);

View File

@ -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;

View File

@ -1,23 +1,22 @@
#include "stdafx.h" #include "stdafx.h"
#include "Memory.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 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) bool check_addr(u32 addr)
{ {
// Checking address before using it is unsafe. // Checking address before using it is unsafe.
@ -28,20 +27,120 @@ namespace vm
//TODO //TODO
bool map(u32 addr, u32 size, u32 flags) bool map(u32 addr, u32 size, u32 flags)
{ {
return false; return Memory.Map(addr, size);
} }
bool unmap(u32 addr, u32 size, u32 flags) 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();
} }
} }

View File

@ -1,22 +1,35 @@
#pragma once #pragma once
#include "Memory.h"
namespace vm 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 map(u32 addr, u32 size, u32 flags);
bool unmap(u32 addr, u32 size = 0, u32 flags = 0); bool unmap(u32 addr, u32 size = 0, u32 flags = 0);
u32 alloc(u32 size); u32 alloc(u32 size, memory_location location = user_space);
void unalloc(u32 addr); 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) T* const get_ptr(u32 addr)
{ {
return (T*)((u8*)m_base_addr + addr); return (T*)((u8*)g_base_addr + addr);
}
template<typename T>
T* const get_ptr(u64 addr)
{
return get_ptr<T>((u32)addr);
} }
template<typename T> template<typename T>
@ -25,59 +38,35 @@ namespace vm
return *get_ptr<T>(addr); return *get_ptr<T>(addr);
} }
template<typename T>
T& get_ref(u64 addr)
{
return get_ref<T>((u32)addr);
}
namespace ps3 namespace ps3
{ {
void init();
static u8 read8(u32 addr) static u8 read8(u32 addr)
{ {
return *((u8*)m_base_addr + addr); return *((u8*)g_base_addr + addr);
}
static u8 read8(u64 addr)
{
return read8((u32)addr);
} }
static void write8(u32 addr, u8 value) static void write8(u32 addr, u8 value)
{ {
*((u8*)m_base_addr + addr) = value; *((u8*)g_base_addr + addr) = value;
}
static void write8(u64 addr, u8 value)
{
write8((u32)addr, value);
} }
static u16 read16(u32 addr) 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); *(be_t<u16>*)((u8*)g_base_addr + addr) = value;
}
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);
} }
static u32 read32(u32 addr) static u32 read32(u32 addr)
{ {
if (addr < RAW_SPU_BASE_ADDR || (addr % RAW_SPU_OFFSET) < RAW_SPU_PROB_OFFSET) 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 else
{ {
@ -85,16 +74,11 @@ namespace vm
} }
} }
static u32 read32(u64 addr) static void write32(u32 addr, be_t<u32> value)
{
return read32((u32)addr);
}
static void write32(u32 addr, u32 value)
{ {
if (addr < RAW_SPU_BASE_ADDR || (addr % RAW_SPU_OFFSET) < RAW_SPU_PROB_OFFSET) 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 else
{ {
@ -102,106 +86,170 @@ namespace vm
} }
} }
static void write32(u64 addr, u32 value)
{
write32((u32)addr, value);
}
static u64 read64(u32 addr) 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) static void write64(u32 addr, u64 value)
{ {
*(u64*)((u8*)m_base_addr + addr) = re64(value); write64(addr, be_t<u64>::make(value));
}
static void write64(u64 addr, u64 value)
{
write64((u32)addr, value);
} }
static u128 read128(u32 addr) static u128 read128(u32 addr)
{ {
return re128(*(u128*)((u8*)m_base_addr + addr)); return re128(*(u128*)((u8*)g_base_addr + addr));
}
static u128 read128(u64 addr)
{
return read128((u32)addr);
} }
static void write128(u32 addr, u128 value) static void write128(u32 addr, u128 value)
{ {
*(u128*)((u8*)m_base_addr + addr) = re128(value); *(u128*)((u8*)g_base_addr + addr) = re128(value);
}
static void write128(u64 addr, u128 value)
{
write128((u32)addr, value);
} }
} }
namespace psv namespace psv
{ {
void init();
static u8 read8(u32 addr) static u8 read8(u32 addr)
{ {
return *((u8*)m_base_addr + addr); return *((u8*)g_base_addr + addr);
} }
static void write8(u32 addr, u8 value) static void write8(u32 addr, u8 value)
{ {
*((u8*)m_base_addr + addr) = value; *((u8*)g_base_addr + addr) = value;
} }
static u16 read16(u32 addr) 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) 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) 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) 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) 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) 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) 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) 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_ref.h"
#include "vm_ptr.h" #include "vm_ptr.h"
#include "vm_var.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;
}
};
}

View File

@ -10,7 +10,7 @@ namespace vm
AT m_addr; AT m_addr;
public: public:
typedef T type; typedef typename std::remove_cv<T>::type type;
_ptr_base operator++ (int) _ptr_base operator++ (int)
{ {
@ -38,41 +38,41 @@ namespace vm
return *this; return *this;
} }
_ptr_base& operator += (int count) _ptr_base& operator += (AT count)
{ {
m_addr += count * sizeof(AT); m_addr += count * sizeof(AT);
return *this; return *this;
} }
_ptr_base& operator -= (int count) _ptr_base& operator -= (AT count)
{ {
m_addr -= count * sizeof(AT); m_addr -= count * sizeof(AT);
return *this; 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)); 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);
}
__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;
} }
//typedef typename invert_be_t<AT>::type AT2; //typedef typename invert_be_t<AT>::type AT2;
@ -80,7 +80,7 @@ namespace vm
template<typename AT2> template<typename AT2>
operator const _ptr_base<T, lvl, AT2>() const 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; return (_ptr_base<T, lvl, AT2>&)addr;
} }
@ -108,6 +108,8 @@ namespace vm
AT m_addr; AT m_addr;
public: public:
typedef typename std::remove_cv<T>::type type;
__forceinline T* const operator -> () const __forceinline T* const operator -> () const
{ {
return vm::get_ptr<T>(m_addr); return vm::get_ptr<T>(m_addr);
@ -139,38 +141,49 @@ namespace vm
return *this; return *this;
} }
_ptr_base& operator += (int count) _ptr_base& operator += (AT count)
{ {
m_addr += count * sizeof(T); m_addr += count * sizeof(T);
return *this; return *this;
} }
_ptr_base& operator -= (int count) _ptr_base& operator -= (AT count)
{ {
m_addr -= count * sizeof(T); m_addr -= count * sizeof(T);
return *this; 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(T)); }
{ _ptr_base operator + (typename to_be_t<AT>::type count) const { return make(m_addr + count * sizeof(T)); }
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 - (int count) const
{
return make(m_addr - count * sizeof(T));
}
__forceinline T& operator *() const __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>() operator _ref_base<T, AT>()
{ {
@ -188,26 +201,28 @@ namespace vm
return m_addr; 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; //typedef typename invert_be_t<AT>::type AT2;
template<typename AT2> template<typename AT2>
operator const _ptr_base<T, 1, AT2>() const 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; return (_ptr_base<T, 1, AT2>&)addr;
} }
T* const get_ptr() const T* get_ptr() const
{ {
return vm::get_ptr<T>(m_addr); return vm::get_ptr<T>(m_addr);
} }
@ -236,29 +251,39 @@ namespace vm
m_addr = value; m_addr = value;
} }
void* const get_ptr() const void* get_ptr() const
{ {
return vm::get_ptr<void>(m_addr); 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; //typedef typename invert_be_t<AT>::type AT2;
template<typename AT2> template<typename AT2>
operator const _ptr_base<void, 1, AT2>() const 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; return (_ptr_base<void, 1, AT2>&)addr;
} }
template<typename AT2> template<typename AT2>
operator const _ptr_base<const void, 1, AT2>() const 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; return (_ptr_base<const void, 1, AT2>&)addr;
} }
@ -286,22 +311,32 @@ namespace vm
m_addr = value; m_addr = value;
} }
const void* const get_ptr() const const void* get_ptr() const
{ {
return vm::get_ptr<const void>(m_addr); 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; //typedef typename invert_be_t<AT>::type AT2;
template<typename AT2> template<typename AT2>
operator const _ptr_base<const void, 1, AT2>() const 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; return (_ptr_base<const void, 1, AT2>&)addr;
} }
@ -335,17 +370,22 @@ namespace vm
m_addr = value; m_addr = value;
} }
operator bool() const __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; }
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 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; //typedef typename invert_be_t<AT>::type AT2;
template<typename AT2> template<typename AT2>
operator const _ptr_base<RT(*)(T...), 1, AT2>() const 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; return (_ptr_base<RT(*)(T...), 1, AT2>&)addr;
} }
@ -356,7 +396,7 @@ namespace vm
operator const std::function<RT(T...)>() const 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...); }; return [addr](T... args) -> RT { return make(addr)(args...); };
} }
@ -413,7 +453,7 @@ namespace vm
namespace ps3 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> template<typename T, int lvl = 1, typename AT = u32> struct ptr : public lptrb<T, lvl, AT>
{ {
static ptr make(AT addr) 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>; //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> template<typename T, int lvl = 1, typename AT = u32> struct bptr : public bptrb<T, lvl, AT>
{ {
static bptr make(AT addr) static bptr make(AT addr)
@ -440,7 +480,7 @@ namespace vm
namespace psv 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> template<typename T, int lvl = 1, typename AT = u32> struct ptr : public lptrl<T, lvl, AT>
{ {
static ptr make(AT addr) static ptr make(AT addr)

View File

@ -90,7 +90,7 @@ std::string GLFragmentDecompilerThread::AddConst()
return name; 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; m_offset += 4 * 4;
u32 x = GetData(data[0]); u32 x = GetData(data[0]);
@ -279,7 +279,7 @@ std::string GLFragmentDecompilerThread::BuildCode()
void GLFragmentDecompilerThread::Task() 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_size = 0;
m_location = 0; m_location = 0;
m_loop_count = 0; m_loop_count = 0;

View File

@ -1380,6 +1380,7 @@ void GLGSRender::WriteColorBuffers()
glBindBuffer(GL_PIXEL_PACK_BUFFER, g_pbo[i]); glBindBuffer(GL_PIXEL_PACK_BUFFER, g_pbo[i]);
glBufferData(GL_PIXEL_PACK_BUFFER, RSXThread::m_width * RSXThread::m_height * 4, 0, GL_STREAM_READ); glBufferData(GL_PIXEL_PACK_BUFFER, RSXThread::m_width * RSXThread::m_height * 4, 0, GL_STREAM_READ);
} }
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
WriteColorBufferA(); WriteColorBufferA();
WriteColorBufferB(); WriteColorBufferB();
break; break;
@ -1804,11 +1805,9 @@ void GLGSRender::ExecCMD()
} }
} }
if (m_set_two_side_light_enable) // TODO: Use other glLightModel functions?
{ glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, m_set_two_side_light_enable ? GL_TRUE : GL_FALSE);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE);
checkForGlError("glLightModeli"); checkForGlError("glLightModeli");
}
if(m_set_shade_mode) 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); 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)"); checkForGlError("Flip(): glReadPixels(GL_BGRA, GL_UNSIGNED_INT_8_8_8_8)");
GLubyte *packed = (GLubyte *)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY); GLubyte *packed = (GLubyte *)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
if (packed)
{
memcpy(pixels.data(), packed, RSXThread::m_width * RSXThread::m_height * 4); memcpy(pixels.data(), packed, RSXThread::m_width * RSXThread::m_height * 4);
glUnmapBuffer(GL_PIXEL_PACK_BUFFER); glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
checkForGlError("Flip(): glUnmapBuffer");
}
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
src_buffer = pixels.data(); src_buffer = pixels.data();

View File

@ -90,9 +90,8 @@ struct GLParamArray
case PARAM_IN: return "in "; case PARAM_IN: return "in ";
case PARAM_UNIFORM: return "uniform "; case PARAM_UNIFORM: return "uniform ";
case PARAM_CONST: return "const "; case PARAM_CONST: return "const ";
default: return "";
} }
return "";
} }
bool HasParam(const GLParamFlag flag, std::string type, const std::string& name) bool HasParam(const GLParamFlag flag, std::string type, const std::string& name)

View File

@ -3,6 +3,7 @@
#include "Utilities/Log.h" #include "Utilities/Log.h"
#include "Emu/Memory/Memory.h" #include "Emu/Memory/Memory.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/RSX/GSManager.h"
#include "RSXThread.h" #include "RSXThread.h"
#include "Emu/SysCalls/Callback.h" #include "Emu/SysCalls/Callback.h"
@ -45,15 +46,40 @@ void RSXThread::nativeRescale(float width, float height)
u32 GetAddress(u32 offset, u32 location) u32 GetAddress(u32 offset, u32 location)
{ {
u32 res = 0;
switch(location) switch(location)
{ {
case CELL_GCM_LOCATION_LOCAL: return (u32)Memory.RSXFBMem.GetStartAddr() + offset; case CELL_GCM_LOCATION_LOCAL:
case CELL_GCM_LOCATION_MAIN: return (u32)Memory.RSXIOMem.RealAddr(Memory.RSXIOMem.GetStartAddr() + offset); // TODO: Error Check? {
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); if (Emu.GetGSManager().GetRender().m_strict_ordering[offset >> 20])
assert(0); {
return 0; _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() 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) 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); std::string debug = GetMethodName(cmd);
debug += "("; debug += "(";
for(u32 i=0; i<count; ++i) debug += (i ? ", " : "") + fmt::Format("0x%x", ARGS(i)); 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) 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 #if CMD_DEBUG
std::string debug = GetMethodName(cmd); 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: case NV406E_SET_CONTEXT_DMA_SEMAPHORE:
{ {
if (ARGS(0)) 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; break;
@ -254,7 +280,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV406E_SEMAPHORE_ACQUIRE: case NV406E_SEMAPHORE_ACQUIRE:
{ {
if (ARGS(0)) if (ARGS(0))
LOG_WARNING(RSX, "NV406E_SEMAPHORE_ACQUIRE: %x", ARGS(0)); LOG_WARNING(RSX, "NV406E_SEMAPHORE_ACQUIRE: 0x%x", ARGS(0));
} }
break; break;
@ -315,21 +341,21 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_NOTIFY: case NV4097_NOTIFY:
{ {
if (ARGS(0)) if (ARGS(0))
LOG_WARNING(RSX, "NV4097_NOTIFY: %x", ARGS(0)); LOG_WARNING(RSX, "NV4097_NOTIFY: 0x%x", ARGS(0));
} }
break; break;
case NV4097_WAIT_FOR_IDLE: case NV4097_WAIT_FOR_IDLE:
{ {
if (ARGS(0)) 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; break;
case NV4097_PM_TRIGGER: case NV4097_PM_TRIGGER:
{ {
if (ARGS(0)) if (ARGS(0))
LOG_WARNING(RSX, "NV4097_PM_TRIGGER: %x", ARGS(0)); LOG_WARNING(RSX, "NV4097_PM_TRIGGER: 0x%x", ARGS(0));
} }
break; 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: case NV4097_SET_VERTEX_ATTRIB_INPUT_MASK:
{ {
if (ARGS(0)) 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); //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: case NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK:
{ {
if (ARGS(0)) 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); //VertexData[0].prog.attributeOutputMask = ARGS(0);
//FragmentData.prog.attributeInputMask = ARGS(0)/* & ~0x20*/; //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: case NV4097_SET_COLOR_MASK_MRT:
{ {
if (ARGS(0)) 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; 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: case NV4097_SET_CLEAR_RECT_HORIZONTAL:
{ {
if (ARGS(0)) 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; break;
case NV4097_SET_CLEAR_RECT_VERTICAL: case NV4097_SET_CLEAR_RECT_VERTICAL:
{ {
if (ARGS(0)) 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; break;
@ -933,7 +959,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
{ {
const u32 a0 = ARGS(0); 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; 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: case NV4097_INVALIDATE_L2:
{ {
if (ARGS(0)) if (ARGS(0))
LOG_WARNING(RSX, "NV4097_INVALIDATE_L2: %x", ARGS(0)); LOG_WARNING(RSX, "NV4097_INVALIDATE_L2: 0x%x", ARGS(0));
} }
break; break;
@ -1085,7 +1111,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_INVALIDATE_ZCULL: case NV4097_INVALIDATE_ZCULL:
{ {
if (ARGS(0)) if (ARGS(0))
LOG_WARNING(RSX, "NV4097_INVALIDATE_ZCULL: %x", ARGS(0)); LOG_WARNING(RSX, "NV4097_INVALIDATE_ZCULL: 0x%x", ARGS(0));
} }
break; break;
@ -1249,7 +1275,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_SET_SCULL_CONTROL: case NV4097_SET_SCULL_CONTROL:
{ {
if (ARGS(0)) 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 //This is stencil culling , nothing to do with stencil masking on regular color or depth buffer
//const u32 a0 = ARGS(0); //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: case NV4097_SET_POINT_PARAMS_ENABLE:
{ {
if (ARGS(0)) 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; 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: case NV4097_SET_SURFACE_PITCH_D:
{ {
if (ARGS(0)) 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; 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: case NV4097_SET_CONTEXT_DMA_COLOR_D:
{ {
if (ARGS(0)) 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; 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: case NV4097_SET_CONTEXT_DMA_SEMAPHORE:
{ {
if (ARGS(0)) 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; break;
case NV4097_SET_CONTEXT_DMA_NOTIFIES: case NV4097_SET_CONTEXT_DMA_NOTIFIES:
{ {
if (ARGS(0)) 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; 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 u8 alphaToOne = (a0 >> 8) & 0xf;
const u16 sampleMask = a0 >> 16; 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; break;
@ -1599,7 +1625,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_SET_ZCULL_CONTROL0: case NV4097_SET_ZCULL_CONTROL0:
{ {
if (ARGS(0)) 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_set_depth_func = true;
//m_depth_func = ARGS(0) >> 4; //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: case NV4097_SET_ZCULL_CONTROL1:
{ {
if (ARGS(0)) 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_set_depth_func = true;
//m_depth_func = ARGS(0) >> 4; //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: case NV4097_SET_ZCULL_STATS_ENABLE:
{ {
if (ARGS(0)) 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; break;
case NV4097_ZCULL_SYNC: case NV4097_ZCULL_SYNC:
{ {
if (ARGS(0)) if (ARGS(0))
LOG_WARNING(RSX, "NV4097_ZCULL_SYNC: %x", ARGS(0)); LOG_WARNING(RSX, "NV4097_ZCULL_SYNC: 0x%x", ARGS(0));
} }
break; 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 u32 offset = ARGS(0) & 0xffffff;
const u8 mode = ARGS(0) >> 24; 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; break;
@ -1812,14 +1838,14 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV0039_PITCH_IN: case NV0039_PITCH_IN:
{ {
if (ARGS(0)) if (ARGS(0))
LOG_WARNING(RSX, "NV0039_PITCH_IN: %x", ARGS(0)); LOG_WARNING(RSX, "NV0039_PITCH_IN: 0x%x", ARGS(0));
} }
break; break;
case NV0039_BUFFER_NOTIFY: case NV0039_BUFFER_NOTIFY:
{ {
if (ARGS(0)) if (ARGS(0))
LOG_WARNING(RSX, "NV0039_BUFFER_NOTIFY: %x", ARGS(0)); LOG_WARNING(RSX, "NV0039_BUFFER_NOTIFY: 0x%x", ARGS(0));
} }
break; 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: case NV309E_SET_CONTEXT_DMA_IMAGE:
{ {
if (ARGS(0)) 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; 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_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)); 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 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) 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 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; 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; const u32 count = (cmd >> 18) & 0x7ff;
//if(cmd == 0) continue; //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) if(cmd & CELL_GCM_METHOD_FLAG_JUMP)
{ {
u32 addr = cmd & ~(CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_NON_INCREMENT); 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); m_call_stack.push(get + 4);
u32 offs = cmd & ~CELL_GCM_METHOD_FLAG_CALL; 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); //LOG_WARNING(RSX, "rsx call(0x%x) #0x%x - 0x%x - 0x%x", offs, addr, cmd, get);
m_ctrl->get = offs; m_ctrl->get = offs;
continue; continue;
@ -2229,19 +2264,19 @@ void RSXThread::Task()
if(cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT) if(cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT)
{ {
//LOG_WARNING(RSX, "non increment cmd! 0x%x", cmd); //LOG_WARNING(RSX, "non increment cmd! 0x%x", cmd);
inc=0; inc = 0;
} }
if(cmd == 0) if(cmd == 0)
{ {
//HACK! We couldn't be here 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));
//ConLog.Error("null cmd: addr=0x%x, put=0x%x, get=0x%x", Memory.RSXIOMem.GetStartAddr() + get, m_ctrl->put, get);
//Emu.Pause(); //Emu.Pause();
//HACK! We shouldn't be here
m_ctrl->get = get + (count + 1) * 4; m_ctrl->get = get + (count + 1) * 4;
continue; 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++) 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 RSXThread::ReadIO32(u32 addr)
{ {
u32 value; 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); 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) 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); throw fmt::Format("%s(rsxio_addr=0x%x): RSXIO memory not mapped", __FUNCTION__, addr);
} }

View File

@ -134,6 +134,7 @@ public:
u32 m_report_main_addr; u32 m_report_main_addr;
u32 m_local_mem_addr, m_main_mem_addr; u32 m_local_mem_addr, m_main_mem_addr;
bool m_strict_ordering[0x1000];
public: public:
uint m_draw_mode; uint m_draw_mode;

View File

@ -228,15 +228,15 @@ enum CellVideoOutRGBOutputRange
static const CellVideoOutResolution ResolutionTable[] = static const CellVideoOutResolution ResolutionTable[] =
{ {
{ be_t<u16>::MakeFromBE(se16(0xffff)), be_t<u16>::MakeFromBE(se16(0xffff)) }, //0 - 0 { be_t<u16>::make(0xffff), be_t<u16>::make(0xffff) }, //0 - 0
{ be_t<u16>::MakeFromBE(se16(1920)), be_t<u16>::MakeFromBE(se16(1080)) }, //1 - 1 { be_t<u16>::make(1920), be_t<u16>::make(1080) }, //1 - 1
{ be_t<u16>::MakeFromBE(se16(1280)), be_t<u16>::MakeFromBE(se16(720)) }, //2 - 2 { be_t<u16>::make(1280), be_t<u16>::make(720) }, //2 - 2
{ be_t<u16>::MakeFromBE(se16(720)), be_t<u16>::MakeFromBE(se16(480)) }, //4 - 3 { be_t<u16>::make(720), be_t<u16>::make(480) }, //4 - 3
{ be_t<u16>::MakeFromBE(se16(720)), be_t<u16>::MakeFromBE(se16(576)) }, //5 - 4 { be_t<u16>::make(720), be_t<u16>::make(576) }, //5 - 4
{ be_t<u16>::MakeFromBE(se16(1600)), be_t<u16>::MakeFromBE(se16(1080)) }, //10 - 5 { be_t<u16>::make(1600), be_t<u16>::make(1080) }, //10 - 5
{ be_t<u16>::MakeFromBE(se16(1440)), be_t<u16>::MakeFromBE(se16(1080)) }, //11 - 6 { be_t<u16>::make(1440), be_t<u16>::make(1080) }, //11 - 6
{ be_t<u16>::MakeFromBE(se16(1280)), be_t<u16>::MakeFromBE(se16(1080)) }, //12 - 7 { be_t<u16>::make(1280), be_t<u16>::make(1080) }, //12 - 7
{ be_t<u16>::MakeFromBE(se16(960)), be_t<u16>::MakeFromBE(se16(1080)) }, //13 - 8 { be_t<u16>::make(960), be_t<u16>::make(1080) }, //13 - 8
}; };
inline static u32 ResolutionIdToNum(u32 id) inline static u32 ResolutionIdToNum(u32 id)

Some files were not shown because too many files have changed in this diff Show More