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
/rpcs3/Debug
/rpcs3/Release
/llvm_build
/wxWidgets/lib
/bin/rpcs3.ini

4
.gitmodules vendored
View File

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

View File

@ -27,7 +27,12 @@ before_install:
sudo ./cmake-3.0.0-Linux-i386.sh --skip-license --prefix=/usr;
before_script:
- git submodule update --init asmjit ffmpeg
- git submodule update --init asmjit ffmpeg llvm
- cd llvm_build
- cmake -DLLVM_TARGETS_TO_BUILD=X86 -DLLVM_BUILD_RUNTIME=OFF -DLLVM_BUILD_TOOLS=OFF -DLLVM_INCLUDE_DOCS=OFF -DLLVM_INCLUDE_EXAMPLES=OFF -DLLVM_INCLUDE_TESTS=OFF -DLLVM_INCLUDE_TOOLS=OFF -DLLVM_INCLUDE_UTILS=OFF -DWITH_POLLY=OFF ../llvm
- make -j 4
- sudo make install
- cd ..
- mkdir build
- cd build
- cmake ..

21129
GL/glext.h

File diff suppressed because it is too large Load Diff

View File

@ -29,7 +29,7 @@ __Mac OSX__
### Building
To initialize the repository don't forget to execute `git submodule update --init` to pull the wxWidgets source.
* __Windows__: Install *Visual Studio 2013*. Then open the *.SLN* file, and press *Build* > *Rebuild Solution*.
* __Windows__: Install *Visual Studio 2013*, *Cmake*, *Python* and select *Add in the PATH variable* for both. Then open the *.SLN* file, and press *Build* > *Rebuild Solution*.
* __Linux & Mac OSX__:
`cd rpcs3 && cmake CMakeLists.txt && make && cd ../` Then run with `cd bin && ./rpcs3`

View File

@ -69,12 +69,12 @@ void AutoPause::Reload(void)
//Less than 1024 - be regarded as a system call.
//emplace_back may not cause reductant move/copy operation.
m_pause_syscall.emplace_back(num);
LOG_WARNING(HLE, "Auto Pause: Find System Call ID %x", num);
LOG_WARNING(HLE, "Auto Pause: Find System Call ID 0x%x", num);
}
else
{
m_pause_function.emplace_back(num);
LOG_WARNING(HLE, "Auto Pause: Find Function Call ID %x", num);
LOG_WARNING(HLE, "Auto Pause: Find Function Call ID 0x%x", num);
}
}
list.Close();
@ -103,7 +103,7 @@ void AutoPause::TryPause(u32 code) {
if (code == m_pause_syscall[i])
{
Emu.Pause();
LOG_ERROR(HLE, "Auto Pause Triggered: System call %x", code); //Used Error
LOG_ERROR(HLE, "Auto Pause Triggered: System call 0x%x", code); // Used Error
}
}
}
@ -121,7 +121,7 @@ void AutoPause::TryPause(u32 code) {
if (code == m_pause_function[i])
{
Emu.Pause();
LOG_ERROR(HLE, "Auto Pause Triggered: Function call %x", code); //Used Error
LOG_ERROR(HLE, "Auto Pause Triggered: Function call 0x%x", code); // Used Error
}
}
}

View File

@ -1,20 +1,91 @@
#pragma once
#include <emmintrin.h>
union u128
union _CRT_ALIGN(16) u128
{
u64 _u64[2];
s64 _s64[2];
class u64_reversed_array_2
{
u64 data[2];
public:
u64& operator [] (s32 index)
{
return data[1 - index];
}
const u64& operator [] (s32 index) const
{
return data[1 - index];
}
} u64r;
u32 _u32[4];
s32 _s32[4];
class u32_reversed_array_4
{
u32 data[4];
public:
u32& operator [] (s32 index)
{
return data[3 - index];
}
const u32& operator [] (s32 index) const
{
return data[3 - index];
}
} u32r;
u16 _u16[8];
s16 _s16[8];
class u16_reversed_array_8
{
u16 data[8];
public:
u16& operator [] (s32 index)
{
return data[7 - index];
}
const u16& operator [] (s32 index) const
{
return data[7 - index];
}
} u16r;
u8 _u8[16];
s8 _s8[16];
class u8_reversed_array_16
{
u8 data[16];
public:
u8& operator [] (s32 index)
{
return data[15 - index];
}
const u8& operator [] (s32 index) const
{
return data[15 - index];
}
} u8r;
float _f[4];
double _d[2];
__m128 xmm;
__m128 vf;
__m128i vi;
class bit_array_128
{
@ -94,6 +165,11 @@ union u128
return ret;
}
static u128 from64r(u64 _1, u64 _0 = 0)
{
return from64(_0, _1);
}
static u128 from32(u32 _0, u32 _1 = 0, u32 _2 = 0, u32 _3 = 0)
{
u128 ret;
@ -104,6 +180,25 @@ union u128
return ret;
}
static u128 from32r(u32 _3, u32 _2 = 0, u32 _1 = 0, u32 _0 = 0)
{
return from32(_0, _1, _2, _3);
}
static u128 from32p(u32 value)
{
u128 ret;
ret.vi = _mm_set1_epi32((int)value);
return ret;
}
static u128 from8p(u8 value)
{
u128 ret;
ret.vi = _mm_set1_epi8((char)value);
return ret;
}
static u128 fromBit(u32 bit)
{
u128 ret = {};
@ -111,9 +206,41 @@ union u128
return ret;
}
void setBit(u32 bit)
static u128 fromV(__m128i value)
{
_bit[bit] = true;
u128 ret;
ret.vi = value;
return ret;
}
static __forceinline u128 add8(const u128& left, const u128& right)
{
return fromV(_mm_add_epi8(left.vi, right.vi));
}
static __forceinline u128 sub8(const u128& left, const u128& right)
{
return fromV(_mm_sub_epi8(left.vi, right.vi));
}
static __forceinline u128 minu8(const u128& left, const u128& right)
{
return fromV(_mm_min_epu8(left.vi, right.vi));
}
static __forceinline u128 eq8(const u128& left, const u128& right)
{
return fromV(_mm_cmpeq_epi8(left.vi, right.vi));
}
static __forceinline u128 gtu8(const u128& left, const u128& right)
{
return fromV(_mm_cmpgt_epu8(left.vi, right.vi));
}
static __forceinline u128 leu8(const u128& left, const u128& right)
{
return fromV(_mm_cmple_epu8(left.vi, right.vi));
}
bool operator == (const u128& right) const
@ -126,19 +253,19 @@ union u128
return (_u64[0] != right._u64[0]) || (_u64[1] != right._u64[1]);
}
u128 operator | (const u128& right) const
__forceinline u128 operator | (const u128& right) const
{
return from64(_u64[0] | right._u64[0], _u64[1] | right._u64[1]);
return fromV(_mm_or_si128(vi, right.vi));
}
u128 operator & (const u128& right) const
__forceinline u128 operator & (const u128& right) const
{
return from64(_u64[0] & right._u64[0], _u64[1] & right._u64[1]);
return fromV(_mm_and_si128(vi, right.vi));
}
u128 operator ^ (const u128& right) const
__forceinline u128 operator ^ (const u128& right) const
{
return from64(_u64[0] ^ right._u64[0], _u64[1] ^ right._u64[1]);
return fromV(_mm_xor_si128(vi, right.vi));
}
u128 operator ~ () const
@ -146,6 +273,12 @@ union u128
return from64(~_u64[0], ~_u64[1]);
}
// result = (~left) & (right)
static __forceinline u128 andnot(const u128& left, const u128& right)
{
return fromV(_mm_andnot_si128(left.vi, right.vi));
}
void clear()
{
_u64[1] = _u64[0] = 0;
@ -153,7 +286,7 @@ union u128
std::string to_hex() const
{
return fmt::Format("%16llx%16llx", _u64[1], _u64[0]);
return fmt::Format("%016llx%016llx", _u64[1], _u64[0]);
}
std::string to_xyzw() const
@ -170,6 +303,72 @@ union u128
}
};
#ifndef InterlockedCompareExchange
static __forceinline u128 InterlockedCompareExchange(volatile u128* dest, u128 exch, u128 comp)
{
#if defined(__GNUG__)
auto res = __sync_val_compare_and_swap((volatile __int128_t*)dest, (__int128_t&)comp, (__int128_t&)exch);
return (u128&)res;
#else
_InterlockedCompareExchange128((volatile long long*)dest, exch._u64[1], exch._u64[0], (long long*)&comp);
return comp;
#endif
}
#endif
static __forceinline bool InterlockedCompareExchangeTest(volatile u128* dest, u128 exch, u128 comp)
{
#if defined(__GNUG__)
return __sync_bool_compare_and_swap((volatile __int128_t*)dest, (__int128_t&)comp, (__int128_t&)exch);
#else
return _InterlockedCompareExchange128((volatile long long*)dest, exch._u64[1], exch._u64[0], (long long*)&comp) != 0;
#endif
}
#ifndef InterlockedExchange
static __forceinline u128 InterlockedExchange(volatile u128* dest, u128 value)
{
while (true)
{
const u128 old = *(u128*)dest;
if (InterlockedCompareExchangeTest(dest, value, old)) return old;
}
}
#endif
#ifndef InterlockedOr
static __forceinline u128 InterlockedOr(volatile u128* dest, u128 value)
{
while (true)
{
const u128 old = *(u128*)dest;
if (InterlockedCompareExchangeTest(dest, old | value, old)) return old;
}
}
#endif
#ifndef InterlockedAnd
static __forceinline u128 InterlockedAnd(volatile u128* dest, u128 value)
{
while (true)
{
const u128 old = *(u128*)dest;
if (InterlockedCompareExchangeTest(dest, old & value, old)) return old;
}
}
#endif
#ifndef InterlockedXor
static __forceinline u128 InterlockedXor(volatile u128* dest, u128 value)
{
while (true)
{
const u128 old = *(u128*)dest;
if (InterlockedCompareExchangeTest(dest, old ^ value, old)) return old;
}
}
#endif
#define re16(val) _byteswap_ushort(val)
#define re32(val) _byteswap_ulong(val)
#define re64(val) _byteswap_uint64(val)
@ -252,7 +451,13 @@ template<typename T, typename T2 = T>
class be_t
{
static_assert(sizeof(T2) == 1 || sizeof(T2) == 2 || sizeof(T2) == 4 || sizeof(T2) == 8, "Bad be_t type");
T m_data;
public:
typedef typename std::remove_cv<T>::type type;
static const bool is_le_machine = true;
private:
type m_data;
template<typename Tto, typename Tfrom, int mode>
struct _convert
@ -283,59 +488,78 @@ class be_t
return (be_t<Tto>&)res;
}
};
public:
typedef T type;
const T& ToBE() const
const type& ToBE() const
{
return m_data;
}
T ToLE() const
type ToLE() const
{
return se_t<T, sizeof(T2)>::func(m_data);
return se_t<type, sizeof(T2)>::func(m_data);
}
void FromBE(const T& value)
void FromBE(const type& value)
{
m_data = value;
}
void FromLE(const T& value)
void FromLE(const type& value)
{
m_data = se_t<T, sizeof(T2)>::func(value);
m_data = se_t<type, sizeof(T2)>::func(value);
}
static be_t MakeFromLE(const T value)
static be_t MakeFromLE(const type value)
{
T data = se_t<T, sizeof(T2)>::func(value);
type data = se_t<type, sizeof(T2)>::func(value);
return (be_t&)data;
}
static be_t MakeFromBE(const T value)
static be_t MakeFromBE(const type value)
{
return (be_t&)value;
}
//template<typename T1>
operator const T() const
//make be_t from current machine byte ordering
static be_t make(const type value)
{
return ToLE();
return is_le_machine ? MakeFromLE(value) : MakeFromBE(value);
}
//get value in current machine byte ordering
__forceinline type value() const
{
return is_le_machine ? ToLE() : ToBE();
}
//be_t() = default;
//be_t(const be_t& value) = default;
//be_t(type value)
//{
// m_data = se_t<type, sizeof(T2)>::func(value);
//}
be_t& operator = (const be_t& value) = default;
be_t& operator = (T value)
be_t& operator = (type value)
{
m_data = se_t<T, sizeof(T2)>::func(value);
m_data = se_t<type, sizeof(T2)>::func(value);
return *this;
}
operator type() const
{
return value();
}
template<typename T1>
operator const be_t<T1>() const
{
return _convert<T1, T, ((sizeof(T1) > sizeof(T)) ? 1 : (sizeof(T1) < sizeof(T) ? 2 : 0))>::func(m_data);
return be_t<T1>::make(value());
//return _convert<T1, T, ((sizeof(T1) > sizeof(T)) ? 1 : (sizeof(T1) < sizeof(T) ? 2 : 0))>::func(m_data);
}
template<typename T1> be_t& operator += (T1 right) { return *this = T(*this) + right; }
@ -382,81 +606,6 @@ public:
be_t& operator-- () { *this -= 1; return *this; }
};
template<typename T, typename T2>
class be_t<const T, T2>
{
static_assert(sizeof(T2) == 1 || sizeof(T2) == 2 || sizeof(T2) == 4 || sizeof(T2) == 8, "Bad be_t type");
const T m_data;
public:
typedef const T type;
const T& ToBE() const
{
return m_data;
}
const T ToLE() const
{
return se_t<const T, sizeof(T2)>::func(m_data);
}
static be_t MakeFromLE(const T value)
{
const T data = se_t<const T, sizeof(T2)>::func(value);
return (be_t&)data;
}
static be_t MakeFromBE(const T value)
{
return (be_t&)value;
}
//template<typename T1>
operator const T() const
{
return ToLE();
}
template<typename T1>
operator const be_t<T1>() const
{
if (sizeof(T1) > sizeof(T) || std::is_floating_point<T>::value || std::is_floating_point<T1>::value)
{
T1 res = se_t<T1, sizeof(T1)>::func(ToLE());
return (be_t<T1>&)res;
}
else if (sizeof(T1) < sizeof(T))
{
T1 res = ToBE() >> ((sizeof(T) - sizeof(T1)) * 8);
return (be_t<T1>&)res;
}
else
{
T1 res = ToBE();
return (be_t<T1>&)res;
}
}
template<typename T1> be_t operator & (const be_t<T1>& right) const { const T res = ToBE() & right.ToBE(); return (be_t&)res; }
template<typename T1> be_t operator | (const be_t<T1>& right) const { const T res = ToBE() | right.ToBE(); return (be_t&)res; }
template<typename T1> be_t operator ^ (const be_t<T1>& right) const { const T res = ToBE() ^ right.ToBE(); return (be_t&)res; }
template<typename T1> bool operator == (T1 right) const { return (T1)ToLE() == right; }
template<typename T1> bool operator != (T1 right) const { return !(*this == right); }
template<typename T1> bool operator > (T1 right) const { return (T1)ToLE() > right; }
template<typename T1> bool operator < (T1 right) const { return (T1)ToLE() < right; }
template<typename T1> bool operator >= (T1 right) const { return (T1)ToLE() >= right; }
template<typename T1> bool operator <= (T1 right) const { return (T1)ToLE() <= right; }
template<typename T1> bool operator == (const be_t<T1>& right) const { return ToBE() == right.ToBE(); }
template<typename T1> bool operator != (const be_t<T1>& right) const { return !(*this == right); }
template<typename T1> bool operator > (const be_t<T1>& right) const { return (T1)ToLE() > right.ToLE(); }
template<typename T1> bool operator < (const be_t<T1>& right) const { return (T1)ToLE() < right.ToLE(); }
template<typename T1> bool operator >= (const be_t<T1>& right) const { return (T1)ToLE() >= right.ToLE(); }
template<typename T1> bool operator <= (const be_t<T1>& right) const { return (T1)ToLE() <= right.ToLE(); }
};
template<typename T, typename T2 = T>
struct is_be_t : public std::integral_constant<bool, false> {};
@ -496,6 +645,8 @@ public:
//be_t<T, size> if need swap endianes, T otherwise
typedef typename _be_type_selector< T, T2, value >::type type;
typedef typename _be_type_selector< T, T2, !is_be_t<T, T2>::value >::type forced_type;
};
template<typename T>
@ -623,3 +774,51 @@ template<typename T> __forceinline static void Write64(T& f, const u64 data)
{
Write64LE(f, re64(data));
}
template<typename Tto, typename Tfrom>
struct convert_le_be_t
{
static Tto func(Tfrom&& value)
{
return (Tto)value;
}
};
template<typename Tt, typename Tt1, typename Tfrom>
struct convert_le_be_t<be_t<Tt, Tt1>, Tfrom>
{
static be_t<Tt, Tt1> func(Tfrom&& value)
{
return be_t<Tt, Tt1>::make(value);
}
};
template<typename Tt, typename Tt1, typename Tf, typename Tf1>
struct convert_le_be_t<be_t<Tt, Tt1>, be_t<Tf, Tf1>>
{
static be_t<Tt, Tt1> func(be_t<Tf, Tf1>&& value)
{
return value;
}
};
template<typename Tto, typename Tf, typename Tf1>
struct convert_le_be_t<Tto, be_t<Tf, Tf1>>
{
static Tto func(be_t<Tf, Tf1>&& value)
{
return value.value();
}
};
template<typename Tto, typename Tfrom>
__forceinline Tto convert_le_be(Tfrom&& value)
{
return convert_le_be_t<Tto, Tfrom>::func(value);
}
template<typename Tto, typename Tfrom>
__forceinline void convert_le_be(Tto& dst, Tfrom&& src)
{
dst = convert_le_be_t<Tto, Tfrom>::func(src);
}

View File

@ -1,5 +1,7 @@
#pragma once
#include <emmintrin.h>
#ifdef _WIN32
#define thread_local __declspec(thread)
#elif __APPLE__
@ -13,13 +15,21 @@
#endif
template<size_t size>
void strcpy_trunc(char (&dst)[size], const std::string& src)
void strcpy_trunc(char(&dst)[size], const std::string& src)
{
const size_t count = (src.size() >= size) ? size - 1 /* truncation */ : src.size();
memcpy(dst, src.c_str(), count);
dst[count] = 0;
}
template<size_t size, size_t rsize>
void strcpy_trunc(char(&dst)[size], const char(&src)[rsize])
{
const size_t count = (rsize >= size) ? size - 1 /* truncation */ : rsize;
memcpy(dst, src, count);
dst[count] = 0;
}
#if defined(__GNUG__)
#include <cmath>
#include <stdlib.h>
@ -36,20 +46,6 @@ void strcpy_trunc(char (&dst)[size], const std::string& src)
#define _byteswap_uint64(x) __builtin_bswap64(x)
#define INFINITE 0xFFFFFFFF
#define _CRT_ALIGN(x) __attribute__((aligned(x)))
#define InterlockedCompareExchange(ptr,new_val,old_val) __sync_val_compare_and_swap(ptr,old_val,new_val)
#define InterlockedCompareExchange64(ptr,new_val,old_val) __sync_val_compare_and_swap(ptr,old_val,new_val)
inline int64_t InterlockedOr64(volatile int64_t *dest, int64_t val)
{
int64_t olderval;
int64_t oldval = *dest;
do
{
olderval = oldval;
oldval = InterlockedCompareExchange64(dest, olderval | val, olderval);
} while (olderval != oldval);
return oldval;
}
inline uint64_t __umulh(uint64_t a, uint64_t b)
{
@ -84,12 +80,257 @@ int clock_gettime(int foo, struct timespec *ts);
#endif
#ifndef InterlockedCompareExchange
static __forceinline uint8_t InterlockedCompareExchange(volatile uint8_t* dest, uint8_t exch, uint8_t comp)
{
#if defined(__GNUG__)
return __sync_val_compare_and_swap(dest, comp, exch);
#else
return _InterlockedCompareExchange8((volatile char*)dest, exch, comp);
#endif
}
static __forceinline uint16_t InterlockedCompareExchange(volatile uint16_t* dest, uint16_t exch, uint16_t comp)
{
#if defined(__GNUG__)
return __sync_val_compare_and_swap(dest, comp, exch);
#else
return _InterlockedCompareExchange16((volatile short*)dest, exch, comp);
#endif
}
static __forceinline uint32_t InterlockedCompareExchange(volatile uint32_t* dest, uint32_t exch, uint32_t comp)
{
#if defined(__GNUG__)
return __sync_val_compare_and_swap(dest, comp, exch);
#else
return _InterlockedCompareExchange((volatile long*)dest, exch, comp);
#endif
}
static __forceinline uint64_t InterlockedCompareExchange(volatile uint64_t* dest, uint64_t exch, uint64_t comp)
{
#if defined(__GNUG__)
return __sync_val_compare_and_swap(dest, comp, exch);
#else
return _InterlockedCompareExchange64((volatile long long*)dest, exch, comp);
#endif
}
#endif
static __forceinline bool InterlockedCompareExchangeTest(volatile uint8_t* dest, uint8_t exch, uint8_t comp)
{
#if defined(__GNUG__)
return __sync_bool_compare_and_swap(dest, comp, exch);
#else
return (uint8_t)_InterlockedCompareExchange8((volatile char*)dest, exch, comp) == comp;
#endif
}
static __forceinline bool InterlockedCompareExchangeTest(volatile uint16_t* dest, uint16_t exch, uint16_t comp)
{
#if defined(__GNUG__)
return __sync_bool_compare_and_swap(dest, comp, exch);
#else
return (uint16_t)_InterlockedCompareExchange16((volatile short*)dest, exch, comp) == comp;
#endif
}
static __forceinline bool InterlockedCompareExchangeTest(volatile uint32_t* dest, uint32_t exch, uint32_t comp)
{
#if defined(__GNUG__)
return __sync_bool_compare_and_swap(dest, comp, exch);
#else
return (uint32_t)_InterlockedCompareExchange((volatile long*)dest, exch, comp) == comp;
#endif
}
static __forceinline bool InterlockedCompareExchangeTest(volatile uint64_t* dest, uint64_t exch, uint64_t comp)
{
#if defined(__GNUG__)
return __sync_bool_compare_and_swap(dest, comp, exch);
#else
return (uint64_t)_InterlockedCompareExchange64((volatile long long*)dest, exch, comp) == comp;
#endif
}
#ifndef InterlockedExchange
static __forceinline uint8_t InterlockedExchange(volatile uint8_t* dest, uint8_t value)
{
#if defined(__GNUG__)
return __sync_lock_test_and_set(dest, value);
#else
return _InterlockedExchange8((volatile char*)dest, value);
#endif
}
static __forceinline uint16_t InterlockedExchange(volatile uint16_t* dest, uint16_t value)
{
#if defined(__GNUG__)
return __sync_lock_test_and_set(dest, value);
#else
return _InterlockedExchange16((volatile short*)dest, value);
#endif
}
static __forceinline uint32_t InterlockedExchange(volatile uint32_t* dest, uint32_t value)
{
#if defined(__GNUG__)
return __sync_lock_test_and_set(dest, value);
#else
return _InterlockedExchange((volatile long*)dest, value);
#endif
}
static __forceinline uint64_t InterlockedExchange(volatile uint64_t* dest, uint64_t value)
{
#if defined(__GNUG__)
return __sync_lock_test_and_set(dest, value);
#else
return _InterlockedExchange64((volatile long long*)dest, value);
#endif
}
#endif
#ifndef InterlockedOr
static __forceinline uint8_t InterlockedOr(volatile uint8_t* dest, uint8_t value)
{
#if defined(__GNUG__)
return __sync_fetch_and_or(dest, value);
#else
return _InterlockedOr8((volatile char*)dest, value);
#endif
}
static __forceinline uint16_t InterlockedOr(volatile uint16_t* dest, uint16_t value)
{
#if defined(__GNUG__)
return __sync_fetch_and_or(dest, value);
#else
return _InterlockedOr16((volatile short*)dest, value);
#endif
}
static __forceinline uint32_t InterlockedOr(volatile uint32_t* dest, uint32_t value)
{
#if defined(__GNUG__)
return __sync_fetch_and_or(dest, value);
#else
return _InterlockedOr((volatile long*)dest, value);
#endif
}
static __forceinline uint64_t InterlockedOr(volatile uint64_t* dest, uint64_t value)
{
#if defined(__GNUG__)
return __sync_fetch_and_or(dest, value);
#else
return _InterlockedOr64((volatile long long*)dest, value);
#endif
}
#endif
#ifndef InterlockedAnd
static __forceinline uint8_t InterlockedAnd(volatile uint8_t* dest, uint8_t value)
{
#if defined(__GNUG__)
return __sync_fetch_and_and(dest, value);
#else
return _InterlockedAnd8((volatile char*)dest, value);
#endif
}
static __forceinline uint16_t InterlockedAnd(volatile uint16_t* dest, uint16_t value)
{
#if defined(__GNUG__)
return __sync_fetch_and_and(dest, value);
#else
return _InterlockedAnd16((volatile short*)dest, value);
#endif
}
static __forceinline uint32_t InterlockedAnd(volatile uint32_t* dest, uint32_t value)
{
#if defined(__GNUG__)
return __sync_fetch_and_and(dest, value);
#else
return _InterlockedAnd((volatile long*)dest, value);
#endif
}
static __forceinline uint64_t InterlockedAnd(volatile uint64_t* dest, uint64_t value)
{
#if defined(__GNUG__)
return __sync_fetch_and_and(dest, value);
#else
return _InterlockedAnd64((volatile long long*)dest, value);
#endif
}
#endif
#ifndef InterlockedXor
static __forceinline uint8_t InterlockedXor(volatile uint8_t* dest, uint8_t value)
{
#if defined(__GNUG__)
return __sync_fetch_and_xor(dest, value);
#else
return _InterlockedXor8((volatile char*)dest, value);
#endif
}
static __forceinline uint16_t InterlockedXor(volatile uint16_t* dest, uint16_t value)
{
#if defined(__GNUG__)
return __sync_fetch_and_xor(dest, value);
#else
return _InterlockedXor16((volatile short*)dest, value);
#endif
}
static __forceinline uint32_t InterlockedXor(volatile uint32_t* dest, uint32_t value)
{
#if defined(__GNUG__)
return __sync_fetch_and_xor(dest, value);
#else
return _InterlockedXor((volatile long*)dest, value);
#endif
}
static __forceinline uint64_t InterlockedXor(volatile uint64_t* dest, uint64_t value)
{
#if defined(__GNUG__)
return __sync_fetch_and_xor(dest, value);
#else
return _InterlockedXor64((volatile long long*)dest, value);
#endif
}
#endif
static __forceinline uint32_t cntlz32(uint32_t arg)
{
#if defined(__GNUG__)
return __builtin_clzl(arg);
#else
unsigned long res;
if (!_BitScanReverse(&res, arg))
{
return 32;
}
else
{
return res ^ 31;
}
#endif
}
static __forceinline uint64_t cntlz64(uint64_t arg)
{
#if defined(__GNUG__)
return __builtin_clzll(arg);
#else
unsigned long res;
if (!_BitScanReverse64(&res, arg))
{
return 64;
}
else
{
return res ^ 63;
}
#endif
}
// compare 16 packed unsigned bytes (greater than)
static __forceinline __m128i _mm_cmpgt_epu8(__m128i A, __m128i B)
{
// (A xor 0x80) > (B xor 0x80)
return _mm_cmpgt_epi8(_mm_xor_si128(A, _mm_set1_epi8(-128)), _mm_xor_si128(B, _mm_set1_epi8(-128)));
}
// compare 16 packed unsigned bytes (less or equal)
static __forceinline __m128i _mm_cmple_epu8(__m128i A, __m128i B)
{
// ((B xor 0x80) > (A xor 0x80)) || A == B
return _mm_or_si128(_mm_cmpgt_epu8(B, A), _mm_cmpeq_epi8(A, B));
}
#endif

View File

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

View File

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

View File

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

View File

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

View File

@ -102,4 +102,35 @@ std::vector<std::string> fmt::rSplit(const std::string& source, const std::strin
}
} while (true);
return ret;
}
std::vector<std::string> fmt::split(const std::string& source, std::initializer_list<std::string> separators, bool is_skip_empty)
{
std::vector<std::string> result;
size_t cursor_begin = 0;
for (size_t cursor_end = 0; cursor_end < source.length(); ++cursor_end)
{
for (auto &separator : separators)
{
if (strncmp(source.c_str() + cursor_end, separator.c_str(), separator.length()) == 0)
{
std::string candidate = source.substr(cursor_begin, cursor_end - cursor_begin);
if (!is_skip_empty || !candidate.empty())
result.push_back(candidate);
cursor_begin = cursor_end + separator.length();
cursor_end = cursor_begin - 1;
break;
}
}
}
if (cursor_begin != source.length())
{
result.push_back(source.substr(cursor_begin));
}
return std::move(result);
}

View File

@ -192,4 +192,6 @@ namespace fmt{
void Replace(std::string &str, const std::string &searchterm, const std::string& replaceterm);
std::vector<std::string> rSplit(const std::string& source, const std::string& delim);
std::vector<std::string> split(const std::string& source, std::initializer_list<std::string> separators, bool is_skip_empty = true);
}

View File

@ -1,4 +1,5 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "Log.h"
#include "Thread.h"
@ -207,3 +208,61 @@ bool thread::joinable() const
{
return m_thr.joinable();
}
bool waiter_map_t::is_stopped(u64 signal_id)
{
if (Emu.IsStopped())
{
LOG_WARNING(Log::HLE, "%s.waiter_op() aborted (signal_id=0x%llx)", m_name.c_str(), signal_id);
return true;
}
return false;
}
void waiter_map_t::waiter_reg_t::init()
{
if (thread) return;
thread = GetCurrentNamedThread();
std::lock_guard<std::mutex> lock(map.m_mutex);
// add waiter
map.m_waiters.push_back({ signal_id, thread });
}
waiter_map_t::waiter_reg_t::~waiter_reg_t()
{
if (!thread) return;
std::lock_guard<std::mutex> lock(map.m_mutex);
// remove waiter
for (s64 i = map.m_waiters.size() - 1; i >= 0; i--)
{
if (map.m_waiters[i].signal_id == signal_id && map.m_waiters[i].thread == thread)
{
map.m_waiters.erase(map.m_waiters.begin() + i);
return;
}
}
LOG_ERROR(HLE, "%s(): waiter not found (signal_id=0x%llx, map='%s')", __FUNCTION__, signal_id, map.m_name.c_str());
Emu.Pause();
}
void waiter_map_t::notify(u64 signal_id)
{
if (!m_waiters.size()) return;
std::lock_guard<std::mutex> lock(m_mutex);
// find waiter and signal
for (auto& v : m_waiters)
{
if (v.signal_id == signal_id)
{
v.thread->Notify();
}
}
}

View File

@ -69,4 +69,107 @@ public:
void detach();
void join();
bool joinable() const;
};
};
class s_mutex_t
{
};
class s_shared_mutex_t
{
};
class s_cond_var_t
{
//public:
// s_cond_var_t();
// ~s_cond_var_t();
//
// s_cond_var_t(s_cond_var_t& right) = delete;
// s_cond_var_t& operator = (s_cond_var_t& right) = delete;
//
// void wait();
// void wait_for();
//
// void notify();
// void notify_all();
};
class slw_mutex_t
{
};
class slw_recursive_mutex_t
{
};
class slw_shared_mutex_t
{
};
class waiter_map_t
{
// TODO: optimize (use custom lightweight readers-writer lock)
std::mutex m_mutex;
struct waiter_t
{
u64 signal_id;
NamedThreadBase* thread;
};
std::vector<waiter_t> m_waiters;
std::string m_name;
struct waiter_reg_t
{
NamedThreadBase* thread;
const u64 signal_id;
waiter_map_t& map;
waiter_reg_t(waiter_map_t& map, u64 signal_id)
: thread(nullptr)
, signal_id(signal_id)
, map(map)
{
}
~waiter_reg_t();
void init();
};
bool is_stopped(u64 signal_id);
public:
waiter_map_t(const char* name)
: m_name(name)
{
}
// wait until waiter_func() returns true, signal_id is an arbitrary number
template<typename WT> __forceinline void wait_op(u64 signal_id, const WT waiter_func)
{
// register waiter
waiter_reg_t waiter(*this, signal_id);
// check condition or if emulator is stopped
while (!waiter_func() && !is_stopped(signal_id))
{
// initialize waiter (only first time)
waiter.init();
// wait for 1 ms or until signal arrived
waiter.thread->WaitForAnySignal(1);
}
}
// signal all threads waiting on waiter_op() with the same signal_id (signaling only hints those threads that corresponding conditions are *probably* met)
void notify(u64 signal_id);
};

View File

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

2
asmjit

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

View File

@ -55,6 +55,7 @@ find_package(GLEW REQUIRED)
find_package(OpenGL REQUIRED)
find_package(ZLIB REQUIRED)
find_package(OpenAL REQUIRED)
find_package(LLVM REQUIRED CONFIG)
include("${wxWidgets_USE_FILE}")
@ -69,6 +70,7 @@ endif()
include_directories(
${wxWidgets_INCLUDE_DIRS}
${OPENAL_INCLUDE_DIR}
${LLVM_INCLUDE_DIRS}
"${RPCS3_SRC_DIR}/../ffmpeg/${PLATFORM_ARCH}/include"
"${RPCS3_SRC_DIR}"
"${RPCS3_SRC_DIR}/Loader"
@ -77,6 +79,14 @@ ${OPENAL_INCLUDE_DIR}
"${RPCS3_SRC_DIR}/../asmjit/src/asmjit"
)
add_definitions(${LLVM_DEFINITIONS})
add_definitions(-DLLVM_AVAILABLE)
if (CMAKE_BUILD_TYPE STREQUAL "Release")
llvm_map_components_to_libnames(LLVM_LIBS jit vectorize x86codegen x86disassembler)
else()
llvm_map_components_to_libnames(LLVM_LIBS jit vectorize x86codegen x86disassembler mcdisassembler)
endif()
link_directories("${RPCS3_SRC_DIR}/../ffmpeg/${PLATFORM_ARCH}/lib")
get_property(dirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
@ -97,10 +107,13 @@ RPCS3_SRC
"${RPCS3_SRC_DIR}/../Utilities/*"
)
list(REMOVE_ITEM RPCS3_SRC ${RPCS3_SRC_DIR}/../Utilities/simpleini/ConvertUTF.c)
set_source_files_properties(${RPCS3_SRC_DIR}/Emu/Cell/PPULLVMRecompiler.cpp PROPERTIES COMPILE_FLAGS -fno-rtti)
add_executable(rpcs3 ${RPCS3_SRC})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_CURRENT_BINARY_DIR}/../asmjit/") #hack because the asmjit cmake file force fno exceptions
target_link_libraries(rpcs3 asmjit.a ${wxWidgets_LIBRARIES} ${OPENAL_LIBRARY} ${GLEW_LIBRARY} ${OPENGL_LIBRARIES} libavformat.a libavcodec.a libavutil.a libswresample.a libswscale.a ${ZLIB_LIBRARIES})
target_link_libraries(rpcs3 asmjit.a ${wxWidgets_LIBRARIES} ${OPENAL_LIBRARY} ${GLEW_LIBRARY} ${OPENGL_LIBRARIES} libavformat.a libavcodec.a libavutil.a libswresample.a libswscale.a ${ZLIB_LIBRARIES} ${LLVM_LIBS})
set_target_properties(rpcs3 PROPERTIES COTIRE_CXX_PREFIX_HEADER_INIT "${RPCS3_SRC_DIR}/stdafx.h")
cotire(rpcs3)

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;
revision = rev;
self_type = type;
hex_to_bytes(erk, e.c_str());
hex_to_bytes(riv, r.c_str());
hex_to_bytes(pub, pb.c_str());
hex_to_bytes(priv, pr.c_str());
hex_to_bytes(erk, e.c_str(), 0);
hex_to_bytes(riv, r.c_str(), 0);
hex_to_bytes(pub, pb.c_str(), 0);
hex_to_bytes(priv, pr.c_str(), 0);
curve_type = ct;
}

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
};
static u8 VSH_CURVE_P[0x14] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
static u8 VSH_CURVE_A[0x14] = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC
};
static u8 VSH_CURVE_B[0x14] = {
0xA6, 0x8B, 0xED, 0xC3, 0x34, 0x18, 0x02, 0x9C, 0x1D, 0x3C, 0xE3, 0x3B, 0x9A, 0x32, 0x1F, 0xCC, 0xBB, 0x9E, 0x0F, 0x0B
};
static u8 VSH_CURVE_N[0x15] = {
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xB5, 0xAE, 0x3C, 0x52, 0x3E, 0x63, 0x94, 0x4F, 0x21, 0x27
};
static u8 VSH_CURVE_GX[0x14] = {
0x12, 0x8E, 0xC4, 0x25, 0x64, 0x87, 0xFD, 0x8F, 0xDF, 0x64, 0xE2, 0x43, 0x7B, 0xC0, 0xA1, 0xF6, 0xD5, 0xAF, 0xDE, 0x2C
};
static u8 VSH_CURVE_GY[0x14] = {
0x59, 0x58, 0x55, 0x7E, 0xB1, 0xDB, 0x00, 0x12, 0x60, 0x42, 0x55, 0x24, 0xDB, 0xC3, 0x79, 0xD5, 0xAC, 0x5F, 0x4A, 0xDF
};
static u8 VSH_PUB[0x28] = {
0x62, 0x27, 0xB0, 0x0A, 0x02, 0x85, 0x6F, 0xB0, 0x41, 0x08, 0x87, 0x67, 0x19, 0xE0, 0xA0, 0x18, 0x32, 0x91, 0xEE, 0xB9,
0x6E, 0x73, 0x6A, 0xBF, 0x81, 0xF7, 0x0E, 0xE9, 0x16, 0x1B, 0x0D, 0xDE, 0xB0, 0x26, 0x76, 0x1A, 0xFF, 0x7B, 0xC8, 0x5B
};
class KeyVault
{
std::vector<SELF_KEY> sk_LV0_arr;

View File

@ -4,26 +4,20 @@
#include "lz.h"
int decode_range(unsigned int *range, unsigned int *code, unsigned char **src)
void decode_range(unsigned int *range, unsigned int *code, unsigned char **src)
{
if (!((*range) >> 24))
if (!((*range) >> 24))
{
(*range) <<= 8;
*code = ((*code) << 8) + (*src)++[5];
return 1;
}
else
return 0;
}
int decode_bit(unsigned int *range, unsigned int *code, int *index, unsigned char **src, unsigned char *c)
{
unsigned int val = *range;
if (decode_range(range, code, src))
val *= (*c);
else
val = (val >> 8) * (*c);
decode_range(range, code, src);
unsigned int val = ((*range) >> 8) * (*c);
*c -= ((*c) >> 3);
if (index) (*index) <<= 1;
@ -47,12 +41,12 @@ int decode_number(unsigned char *ptr, int index, int *bit_flag, unsigned int *ra
{
int i = 1;
if (index >= 3)
if (index >= 3)
{
decode_bit(range, code, &i, src, ptr + 0x18); // Offset 0x978
if (index >= 4)
decode_bit(range, code, &i, src, ptr + 0x18);
if (index >= 4)
{
decode_bit(range, code, &i, src, ptr + 0x18); // Offset 0x978
decode_bit(range, code, &i, src, ptr + 0x18);
if (index >= 5)
{
decode_range(range, code, src);
@ -60,8 +54,8 @@ int decode_number(unsigned char *ptr, int index, int *bit_flag, unsigned int *ra
{
i <<= 1;
(*range) >>= 1;
if (*code < *range)
i++;
if (*code < *range)
i++;
else
(*code) -= *range;
}
@ -69,16 +63,16 @@ 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
if (index >= 2)
decode_bit(range, code, &i, src, ptr + 0x8);
if (index >= 2)
{
decode_bit(range, code, &i, src, ptr + 0x10); // Offset 0x970
decode_bit(range, code, &i, src, ptr + 0x10);
}
}
}
return i;
}
@ -88,12 +82,12 @@ int decode_word(unsigned char *ptr, int index, int *bit_flag, unsigned int *rang
int i = 1;
index /= 8;
if (index >= 3)
if (index >= 3)
{
decode_bit(range, code, &i, src, ptr); // Offset 0x8A8
if (index >= 4)
decode_bit(range, code, &i, src, ptr + 4);
if (index >= 4)
{
decode_bit(range, code, &i, src, ptr); // Offset 0x8A8
decode_bit(range, code, &i, src, ptr + 4);
if (index >= 5)
{
decode_range(range, code, src);
@ -101,8 +95,8 @@ int decode_word(unsigned char *ptr, int index, int *bit_flag, unsigned int *rang
{
i <<= 1;
(*range) >>= 1;
if (*code < *range)
i++;
if (*code < *range)
i++;
else
(*code) -= *range;
}
@ -110,16 +104,16 @@ 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
if (index >= 2)
decode_bit(range, code, &i, src, ptr + 1);
if (index >= 2)
{
decode_bit(range, code, &i, src, ptr + 1); // Offset 0x8A8 + 1
decode_bit(range, code, &i, src, ptr + 2);
}
}
}
return i;
}
@ -128,7 +122,7 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
{
int result;
unsigned char *tmp = new unsigned char[0xA70];
unsigned char *tmp = new unsigned char[0xCC8];
int offset = 0;
int bit_flag = 0;
@ -159,11 +153,11 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
else
{
// Set up a temporary buffer (sliding window).
memset(tmp, 0x80, 0xA60);
memset(tmp, 0x80, 0xCA8);
while (1)
{
// Start reading at 0x920.
tmp_sect1 = tmp + offset + 0x920;
// Start reading at 0xB68.
tmp_sect1 = tmp + offset + 0xB68;
if (!decode_bit(&range, &code, 0, &in, tmp_sect1)) // Raw char.
{
// Adjust offset and check for stream end.
@ -189,57 +183,65 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
int index = -1;
// Identify the data length bit field.
do {
tmp_sect1 += 8;
do
{
tmp_sect1 += 8;
bit_flag = decode_bit(&range, &code, 0, &in, tmp_sect1);
index += bit_flag;
} while ((bit_flag != 0) && (index < 6));
// Default block size is 0x40.
int b_size = 0x40;
// Default block size is 0x160.
int b_size = 0x160;
tmp_sect2 = tmp + index + 0x7F1;
// If the data length was found, parse it as a number.
if ((index >= 0) || (bit_flag != 0))
if ((index >= 0) || (bit_flag != 0))
{
// Locate next section.
int sect = (index << 5) | (((((start - out)) << index) & 3) << 3) | (offset & 7);
tmp_sect1 = tmp + 0x960 + sect;
int sect = (index << 5) | (((((int)(start - out)) << index) & 3) << 3) | (offset & 7);
tmp_sect1 = tmp + 0xBA8 + sect;
// Decode the data length (8 bit fields).
data_length = decode_number(tmp_sect1, index, &bit_flag, &range, &code, &in);
// If we got valid parameters, seek to find data offset.
if ((data_length != 3) && ((index > 0) || (bit_flag != 0))) {
tmp_sect2 += 0x38;
b_size = 0x80; // Block size is now 0x80.
}
} else {
if (data_length == 0xFF) return (start - out); // End of stream.
}
else
{
// Assume one byte of advance.
data_length = 1;
}
// If we got valid parameters, seek to find data offset.
if ((data_length <= 2))
{
tmp_sect2 += 0xF8;
b_size = 0x40; // Block size is now 0x40.
}
int diff = 0;
int shift = 1;
// Identify the data offset bit field.
do {
do
{
diff = (shift << 4) - b_size;
bit_flag = decode_bit(&range, &code, &shift, &in, tmp_sect2 + (shift << 3));
} while (diff < 0);
// If the data offset was found, parse it as a number.
if ((diff > 0) || (bit_flag != 0))
if ((diff > 0) || (bit_flag != 0))
{
// Adjust diff if needed.
if (bit_flag == 0) diff -= 8;
// Locate section.
tmp_sect3 = tmp + 0x8A8 + diff;
tmp_sect3 = tmp + 0x928 + diff;
// Decode the data offset (1 bit fields).
data_offset = decode_word(tmp_sect3, diff, &bit_flag, &range, &code, &in);
} else {
}
else
{
// Assume one byte of advance.
data_offset = 1;
}
@ -260,7 +262,8 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
offset = ((((int)(buf_end - out)) + 1) & 1) + 6;
// Copy data.
do {
do
{
*start++ = *buf_start++;
} while (start < buf_end);
@ -271,4 +274,4 @@ int decompress(unsigned char *out, unsigned char *in, unsigned int size)
}
delete[] tmp;
return result;
}
}

View File

@ -1,8 +1,15 @@
#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>
int decode_range(unsigned int *range, unsigned int *code, unsigned char **src);
void decode_range(unsigned int *range, unsigned int *code, unsigned char **src);
int decode_bit(unsigned int *range, unsigned int *code, int *index, unsigned char **src, unsigned char *c);
int decode_number(unsigned char *ptr, int index, int *bit_flag, unsigned int *range, unsigned int *code, unsigned char **src);
int decode_word(unsigned char *ptr, int index, int *bit_flag, unsigned int *range, unsigned int *code, unsigned char **src);
int decompress(unsigned char *out, unsigned char *in, unsigned int size);
int decompress(unsigned char *out, unsigned char *in, unsigned int size);

View File

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

View File

@ -1,5 +1,4 @@
#include "stdafx.h"
#include "utils.h"
#include "key_vault.h"
#include "unedat.h"
#include "Utilities/Log.h"
@ -7,7 +6,7 @@
void generate_key(int crypto_mode, int version, unsigned char *key_final, unsigned char *iv_final, unsigned char *key, unsigned char *iv)
{
int mode = (int) (crypto_mode & 0xF0000000);
int mode = (int)(crypto_mode & 0xF0000000);
switch (mode) {
case 0x10000000:
// Encrypted ERK.
@ -32,7 +31,7 @@ void generate_key(int crypto_mode, int version, unsigned char *key_final, unsign
void generate_hash(int hash_mode, int version, unsigned char *hash_final, unsigned char *hash)
{
int mode = (int) (hash_mode & 0xF0000000);
int mode = (int)(hash_mode & 0xF0000000);
switch (mode) {
case 0x10000000:
// Encrypted HASH.
@ -52,7 +51,7 @@ void generate_hash(int hash_mode, int version, unsigned char *hash_final, unsign
};
}
bool crypto(int hash_mode, int crypto_mode, int version, unsigned char *in, unsigned char *out, int length, unsigned char *key, unsigned char *iv, unsigned char *hash, unsigned char *test_hash)
bool decrypt(int hash_mode, int crypto_mode, int version, unsigned char *in, unsigned char *out, int length, unsigned char *key, unsigned char *iv, unsigned char *hash, unsigned char *test_hash)
{
// Setup buffers for key, iv and hash.
unsigned char key_final[0x10] = {};
@ -77,29 +76,30 @@ bool crypto(int hash_mode, int crypto_mode, int version, unsigned char *in, unsi
}
else
{
LOG_ERROR(LOADER, "EDAT: Unknown crypto algorithm!\n");
LOG_ERROR(LOADER, "EDAT: Unknown crypto algorithm!");
return false;
}
if ((hash_mode & 0xFF) == 0x01) // 0x14 SHA1-HMAC
{
return hmac_hash_compare(hash_final_14, 0x14, in, length, test_hash);
return hmac_hash_compare(hash_final_14, 0x14, in, length, test_hash, 0x14);
}
else if ((hash_mode & 0xFF) == 0x02) // 0x10 AES-CMAC
{
return cmac_hash_compare(hash_final_10, 0x10, in, length, test_hash);
return cmac_hash_compare(hash_final_10, 0x10, in, length, test_hash, 0x10);
}
else if ((hash_mode & 0xFF) == 0x04) //0x10 SHA1-HMAC
{
return hmac_hash_compare(hash_final_10, 0x10, in, length, test_hash);
return hmac_hash_compare(hash_final_10, 0x10, in, length, test_hash, 0x10);
}
else
{
LOG_ERROR(LOADER, "EDAT: Unknown hashing algorithm!\n");
LOG_ERROR(LOADER, "EDAT: Unknown hashing algorithm!");
return false;
}
}
// EDAT/SDAT functions.
unsigned char* dec_section(unsigned char* metadata)
{
unsigned char *dec = new unsigned char[0x10];
@ -135,11 +135,11 @@ unsigned char* get_block_key(int block, NPD_HEADER *npd)
return dest_key;
}
// EDAT/SDAT functions.
int decrypt_data(rFile *in, rFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd, unsigned char* crypt_key, bool verbose)
// EDAT/SDAT decryption.
int decrypt_data(rFile *in, rFile *out, EDAT_HEADER *edat, NPD_HEADER *npd, unsigned char* crypt_key, bool verbose)
{
// Get metadata info and setup buffers.
int block_num = (int) ((edat->file_size + edat->block_size - 1) / edat->block_size);
int block_num = (int)((edat->file_size + edat->block_size - 1) / edat->block_size);
int metadata_section_size = ((edat->flags & EDAT_COMPRESSED_FLAG) != 0 || (edat->flags & EDAT_FLAG_0x20) != 0) ? 0x20 : 0x10;
int metadata_offset = 0x100;
@ -148,78 +148,103 @@ int decrypt_data(rFile *in, rFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd,
unsigned char *b_key;
unsigned char *iv;
unsigned char hash[0x10];
unsigned char key_result[0x10];
unsigned char hash_result[0x14];
memset(hash, 0, 0x10);
memset(key_result, 0, 0x10);
memset(hash_result, 0, 0x14);
unsigned long long offset = 0;
unsigned long long metadata_sec_offset = 0;
int length = 0;
int compression_end = 0;
unsigned char empty_iv[0x10] = {};
// Decrypt the metadata.
for (int i = 0; i < block_num; i++)
int i;
for (i = 0; i < block_num; i++)
{
in->Seek(metadata_offset + i * metadata_section_size);
unsigned char hash_result[0x10];
long offset;
int length = 0;
int compression_end = 0;
memset(hash_result, 0, 0x14);
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)
{
unsigned char metadata[0x20];
in->Read(metadata, 0x20);
// If the data is compressed, decrypt the metadata.
unsigned char *result = dec_section(metadata);
offset = ((swap32(*(int*)&result[0]) << 4) | (swap32(*(int*)&result[4])));
length = swap32(*(int*)&result[8]);
compression_end = swap32(*(int*)&result[12]);
delete[] result;
metadata_sec_offset = metadata_offset + (unsigned long long) i * metadata_section_size;
in->Seek(metadata_sec_offset);
unsigned char metadata[0x20];
memset(metadata, 0, 0x20);
in->Read(metadata, 0x20);
// If the data is compressed, decrypt the metadata.
// NOTE: For NPD version 1 the metadata is not encrypted.
if (npd->version <= 1)
{
offset = swap64(*(unsigned long long*)&metadata[0x10]);
length = swap32(*(int*)&metadata[0x18]);
compression_end = swap32(*(int*)&metadata[0x1C]);
}
else
{
unsigned char *result = dec_section(metadata);
offset = swap64(*(unsigned long long*)&result[0]);
length = swap32(*(int*)&result[8]);
compression_end = swap32(*(int*)&result[12]);
delete[] result;
}
memcpy(hash_result, metadata, 0x10);
}
else if ((edat->flags & EDAT_FLAG_0x20) != 0)
{
// If FLAG 0x20, the metadata precedes each data block.
in->Seek(metadata_offset + i * metadata_section_size + length);
metadata_sec_offset = metadata_offset + (unsigned long long) i * (metadata_section_size + length);
in->Seek(metadata_sec_offset);
unsigned char metadata[0x20];
memset(metadata, 0, 0x20);
in->Read(metadata, 0x20);
memcpy(hash_result, metadata, 0x14);
// If FLAG 0x20 is set, apply custom xor.
for (int j = 0; j < 0x10; j++) {
hash_result[j] = (unsigned char)(metadata[j] ^ metadata[j+0x10]);
}
int j;
for (j = 0; j < 0x10; j++)
hash_result[j] = (unsigned char)(metadata[j] ^ metadata[j + 0x10]);
offset = metadata_offset + i * edat->block_size + (i + 1) * metadata_section_size;
offset = metadata_sec_offset + 0x20;
length = edat->block_size;
if ((i == (block_num - 1)) && (edat->file_size % edat->block_size))
length = (int) (edat->file_size % edat->block_size);
length = (int)(edat->file_size % edat->block_size);
}
else
{
metadata_sec_offset = metadata_offset + (unsigned long long) i * metadata_section_size;
in->Seek(metadata_sec_offset);
in->Read(hash_result, 0x10);
offset = metadata_offset + i * edat->block_size + block_num * metadata_section_size;
offset = metadata_offset + (unsigned long long) i * edat->block_size + (unsigned long long) block_num * metadata_section_size;
length = edat->block_size;
if ((i == (block_num - 1)) && (edat->file_size % edat->block_size))
length = (int) (edat->file_size % edat->block_size);
length = (int)(edat->file_size % edat->block_size);
}
// Locate the real data.
int pad_length = length;
length = (int) ((pad_length + 0xF) & 0xFFFFFFF0);
in->Seek(offset);
length = (int)((pad_length + 0xF) & 0xFFFFFFF0);
// Setup buffers for decryption and read the data.
enc_data = new unsigned char[length];
dec_data = new unsigned char[length];
unsigned char key_result[0x10];
unsigned char hash[0x10];
memset(enc_data, 0, length);
memset(dec_data, 0, length);
memset(hash, 0, 0x10);
memset(key_result, 0, 0x10);
in->Seek(offset);
in->Read(enc_data, length);
// Generate a key for the current block.
b_key = get_block_key(i, npd);
@ -247,7 +272,7 @@ int decrypt_data(rFile *in, rFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd,
hash_mode |= 0x10000000;
}
if ((edat->flags & EDAT_DEBUG_DATA_FLAG) != 0)
if ((edat->flags & EDAT_DEBUG_DATA_FLAG) != 0)
{
// Reset the flags.
crypto_mode |= 0x01000000;
@ -260,7 +285,13 @@ int decrypt_data(rFile *in, rFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd,
// IV is null if NPD version is 1 or 0.
iv = (npd->version <= 1) ? empty_iv : npd->digest;
// Call main crypto routine on this data block.
crypto(hash_mode, crypto_mode, (npd->version == 4), enc_data, dec_data, length, key_result, iv, hash, hash_result);
if (!decrypt(hash_mode, crypto_mode, (npd->version == 4), enc_data, dec_data, length, key_result, iv, hash, hash_result))
{
if (verbose)
LOG_WARNING(LOADER, "EDAT: Block at offset 0x%llx has invalid hash!", offset);
return 1;
}
}
// Apply additional compression if needed and write the decrypted data.
@ -271,28 +302,28 @@ int decrypt_data(rFile *in, rFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd,
memset(decomp_data, 0, decomp_size);
if (verbose)
LOG_NOTICE(LOADER, "EDAT: Decompressing...\n");
int res = lz_decompress(decomp_data, dec_data, decomp_size);
LOG_NOTICE(LOADER, "EDAT: Decompressing data...");
int res = decompress(decomp_data, dec_data, decomp_size);
out->Write(decomp_data, res);
if (verbose)
{
LOG_NOTICE(LOADER, "EDAT: Compressed block size: %d\n", pad_length);
LOG_NOTICE(LOADER, "EDAT: Decompressed block size: %d\n", res);
LOG_NOTICE(LOADER, "EDAT: Compressed block size: %d", pad_length);
LOG_NOTICE(LOADER, "EDAT: Decompressed block size: %d", res);
}
edat->file_size -= res;
if (edat->file_size == 0)
if (edat->file_size == 0)
{
if (res < 0)
{
LOG_ERROR(LOADER, "EDAT: Decompression failed!\n");
LOG_ERROR(LOADER, "EDAT: Decompression failed!");
return 1;
}
else
LOG_SUCCESS(LOADER, "EDAT: Data successfully decompressed!\n");
LOG_NOTICE(LOADER, "EDAT: Successfully decompressed!");
}
delete[] decomp_data;
@ -309,158 +340,262 @@ int decrypt_data(rFile *in, rFile *out, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd,
return 0;
}
static bool check_flags(EDAT_SDAT_HEADER *edat, NPD_HEADER *npd)
int check_data(unsigned char *key, EDAT_HEADER *edat, NPD_HEADER *npd, rFile *f, bool verbose)
{
if (edat == nullptr || npd == nullptr)
return false;
f->Seek(0);
unsigned char header[0xA0];
unsigned char empty_header[0xA0];
unsigned char header_hash[0x10];
unsigned char metadata_hash[0x10];
memset(header, 0, 0xA0);
memset(empty_header, 0, 0xA0);
memset(header_hash, 0, 0x10);
memset(metadata_hash, 0, 0x10);
if (npd->version == 0 || npd->version == 1)
// Check NPD version and flags.
if ((npd->version == 0) || (npd->version == 1))
{
if (edat->flags & 0x7EFFFFFE)
if (edat->flags & 0x7EFFFFFE)
{
LOG_ERROR(LOADER, "EDAT: Bad header flags!\n");
return false;
LOG_ERROR(LOADER, "EDAT: Bad header flags!");
return 1;
}
}
else if (npd->version == 2)
else if (npd->version == 2)
{
if (edat->flags & 0x7EFFFFE0)
if (edat->flags & 0x7EFFFFE0)
{
LOG_ERROR(LOADER, "EDAT: Bad header flags!\n");
return false;
LOG_ERROR(LOADER, "EDAT: Bad header flags!");
return 1;
}
}
else if (npd->version == 3 || npd->version == 4)
else if ((npd->version == 3) || (npd->version == 4))
{
if (edat->flags & 0x7EFFFFC0)
{
LOG_ERROR(LOADER, "EDAT: Bad header flags!\n");
return false;
LOG_ERROR(LOADER, "EDAT: Bad header flags!");
return 1;
}
}
else if (npd->version > 4)
else
{
LOG_ERROR(LOADER, "EDAT: Unknown version - %d\n", npd->version);
return false;
}
return true;
}
int check_data(unsigned char *key, EDAT_SDAT_HEADER *edat, NPD_HEADER *npd, rFile *f, bool verbose)
{
f->Seek(0);
unsigned char *header = new unsigned char[0xA0];
unsigned char *tmp = new unsigned char[0xA0];
unsigned char *hash_result = new unsigned char[0x10];
// Check NPD version and EDAT flags.
if (!check_flags(edat, npd))
{
delete[] header;
delete[] tmp;
delete[] hash_result;
LOG_ERROR(LOADER, "EDAT: Unknown version!");
return 1;
}
// Read in the file header.
f->Read(header, 0xA0);
f->Read(hash_result, 0x10);
// Read in the header and metadata section hashes.
f->Seek(0x90);
f->Read(metadata_hash, 0x10);
f->Read(header_hash, 0x10);
// Setup the hashing mode and the crypto mode used in the file.
int crypto_mode = 0x1;
int hash_mode = ((edat->flags & EDAT_ENCRYPTED_KEY_FLAG) == 0) ? 0x00000002 : 0x10000002;
if ((edat->flags & EDAT_DEBUG_DATA_FLAG) != 0)
{
LOG_ERROR(LOADER, "EDAT: DEBUG data detected!\n");
hash_mode |= 0x01000000;
if (verbose)
LOG_WARNING(LOADER, "EDAT: DEBUG data detected!");
}
// Setup header key and iv buffers.
unsigned char header_key[0x10] = {};
unsigned char header_iv[0x10] = {};
unsigned char header_key[0x10];
unsigned char header_iv[0x10];
memset(header_key, 0, 0x10);
memset(header_iv, 0, 0x10);
// Test the header hash (located at offset 0xA0).
if (!crypto(hash_mode, crypto_mode, (npd->version == 4), header, tmp, 0xA0, header_key, header_iv, key, hash_result))
if (!decrypt(hash_mode, crypto_mode, (npd->version == 4), header, empty_header, 0xA0, header_key, header_iv, key, header_hash))
{
if (verbose)
LOG_WARNING(LOADER, "EDAT: Header hash is invalid!\n");
LOG_WARNING(LOADER, "EDAT: Header hash is invalid!");
// If the header hash test fails and the data is not DEBUG, then RAP/RIF/KLIC key is invalid.
if ((edat->flags & EDAT_DEBUG_DATA_FLAG) != EDAT_DEBUG_DATA_FLAG)
{
LOG_ERROR(LOADER, "EDAT: RAP/RIF/KLIC key is invalid!");
return 1;
}
}
// Parse the metadata info.
int metadata_section_size = 0x10;
int metadata_section_size = ((edat->flags & EDAT_COMPRESSED_FLAG) != 0 || (edat->flags & EDAT_FLAG_0x20) != 0) ? 0x20 : 0x10;
if (((edat->flags & EDAT_COMPRESSED_FLAG) != 0))
{
LOG_WARNING(LOADER, "EDAT: COMPRESSED data detected!\n");
metadata_section_size = 0x20;
if (verbose)
LOG_WARNING(LOADER, "EDAT: COMPRESSED data detected!");
}
int block_num = (int) ((edat->file_size + edat->block_size - 1) / edat->block_size);
int bytes_read = 0;
int block_num = (int)((edat->file_size + edat->block_size - 1) / edat->block_size);
int metadata_offset = 0x100;
int metadata_size = metadata_section_size * block_num;
long long metadata_section_offset = metadata_offset;
long bytes_read = 0;
long bytes_to_read = metadata_size;
unsigned char *metadata = new unsigned char[metadata_size];
unsigned char *empty_metadata = new unsigned char[metadata_size];
long bytes_to_read = metadata_section_size * block_num;
while (bytes_to_read > 0)
{
// Locate the metadata blocks.
int block_size = (0x3C00 > bytes_to_read) ? (int) bytes_to_read : 0x3C00; // 0x3C00 is the maximum block size.
f->Seek(metadata_offset + bytes_read);
unsigned char *data = new unsigned char[block_size];
f->Seek(metadata_section_offset);
// Read in the metadata.
tmp = new unsigned char[block_size];
f->Read(data, block_size);
// Check the generated hash against the metadata hash located at offset 0x90 in the header.
memset(hash_result, 0, 0x10);
f->Seek(0x90);
f->Read(hash_result, 0x10);
// Generate the hash for this block.
if (!crypto(hash_mode, crypto_mode, (npd->version == 4), data, tmp, block_size, header_key, header_iv, key, hash_result))
{
if (verbose)
LOG_WARNING(LOADER, "EDAT: Metadata hash from block 0x%08x is invalid!\n", metadata_offset + bytes_read);
}
f->Read(metadata + bytes_read, metadata_section_size);
// Adjust sizes.
bytes_read += block_size;
bytes_to_read -= block_size;
bytes_read += metadata_section_size;
bytes_to_read -= metadata_section_size;
delete[] data;
if (((edat->flags & EDAT_FLAG_0x20) != 0)) // Metadata block before each data block.
metadata_section_offset += (metadata_section_size + edat->block_size);
else
metadata_section_offset += metadata_section_size;
}
// Test the metadata section hash (located at offset 0x90).
if (!decrypt(hash_mode, crypto_mode, (npd->version == 4), metadata, empty_metadata, metadata_size, header_key, header_iv, key, metadata_hash))
{
if (verbose)
LOG_WARNING(LOADER, "EDAT: Metadata section hash is invalid!");
}
// Checking ECDSA signatures.
if ((edat->flags & EDAT_DEBUG_DATA_FLAG) == 0)
{
LOG_NOTICE(LOADER, "EDAT: Checking signatures...");
// Setup buffers.
unsigned char metadata_signature[0x28];
unsigned char header_signature[0x28];
unsigned char signature_hash[20];
unsigned char signature_r[0x15];
unsigned char signature_s[0x15];
unsigned char zero_buf[0x15];
memset(metadata_signature, 0, 0x28);
memset(header_signature, 0, 0x28);
memset(signature_hash, 0, 20);
memset(signature_r, 0, 0x15);
memset(signature_s, 0, 0x15);
memset(zero_buf, 0, 0x15);
// Setup ECDSA curve and public key.
ecdsa_set_curve(VSH_CURVE_P, VSH_CURVE_A, VSH_CURVE_B, VSH_CURVE_N, VSH_CURVE_GX, VSH_CURVE_GY);
ecdsa_set_pub(VSH_PUB);
// Read in the metadata and header signatures.
f->Seek(0xB0);
f->Read(metadata_signature, 0x28);
f->Seek(0xD8);
f->Read(header_signature, 0x28);
// Checking metadata signature.
// Setup signature r and s.
memcpy(signature_r + 01, metadata_signature, 0x14);
memcpy(signature_s + 01, metadata_signature + 0x14, 0x14);
if ((!memcmp(signature_r, zero_buf, 0x15)) || (!memcmp(signature_s, zero_buf, 0x15)))
LOG_WARNING(LOADER, "EDAT: Metadata signature is invalid!");
else
{
// Setup signature hash.
if ((edat->flags & EDAT_FLAG_0x20) != 0) //Sony failed again, they used buffer from 0x100 with half size of real metadata.
{
int metadata_buf_size = block_num * 0x10;
unsigned char *metadata_buf = new unsigned char[metadata_buf_size];
f->Seek(metadata_offset);
f->Read(metadata_buf, metadata_buf_size);
sha1(metadata_buf, metadata_buf_size, signature_hash);
delete[] metadata_buf;
}
else
sha1(metadata, metadata_size, signature_hash);
if (!ecdsa_verify(signature_hash, signature_r, signature_s))
{
LOG_WARNING(LOADER, "EDAT: Metadata signature is invalid!");
if (((unsigned long long)edat->block_size * block_num) > 0x100000000)
LOG_WARNING(LOADER, "EDAT: *Due to large file size, metadata signature status may be incorrect!");
}
else
LOG_NOTICE(LOADER, "EDAT: Metadata signature is valid!");
}
// Checking header signature.
// Setup header signature r and s.
memset(signature_r, 0, 0x15);
memset(signature_s, 0, 0x15);
memcpy(signature_r + 01, header_signature, 0x14);
memcpy(signature_s + 01, header_signature + 0x14, 0x14);
if ((!memcmp(signature_r, zero_buf, 0x15)) || (!memcmp(signature_s, zero_buf, 0x15)))
LOG_WARNING(LOADER, "EDAT: Header signature is invalid!");
else
{
// Setup header signature hash.
memset(signature_hash, 0, 20);
unsigned char *header_buf = new unsigned char[0xD8];
f->Seek(0x00);
f->Read(header_buf, 0xD8);
sha1(header_buf, 0xD8, signature_hash );
delete[] header_buf;
if (ecdsa_verify(signature_hash, signature_r, signature_s))
LOG_NOTICE(LOADER, "EDAT: Header signature is valid!");
else
LOG_WARNING(LOADER, "EDAT: Header signature is invalid!");
}
}
// Cleanup.
delete[] header;
delete[] tmp;
delete[] hash_result;
delete[] metadata;
delete[] empty_metadata;
return 0;
}
void validate_data(const char* file_name, unsigned char *klicensee, NPD_HEADER *npd, bool verbose)
int validate_npd_hashes(const char* file_name, unsigned char *klicensee, NPD_HEADER *npd, bool verbose)
{
int title_hash_result = 0;
int dev_hash_result = 0;
int file_name_length = (int)strlen(file_name);
int file_name_length = (int) strlen(file_name);
unsigned char *buf = new unsigned char[0x30 + file_name_length];
unsigned char dev[0x60];
unsigned char key[0x10];
memset(dev, 0, 0x60);
memset(key, 0, 0x10);
// Build the buffer (content_id + file_name).
// Build the title buffer (content_id + file_name).
memcpy(buf, npd->content_id, 0x30);
memcpy(buf + 0x30, file_name, file_name_length);
// Hash with NP_OMAC_KEY_3 and compare with title_hash.
title_hash_result = cmac_hash_compare(NP_OMAC_KEY_3, 0x10, buf, 0x30 + file_name_length, npd->title_hash);
// Build the dev buffer (first 0x60 bytes of NPD header in big-endian).
memcpy(dev, npd, 0x60);
// Fix endianness.
int version = swap32(npd->version);
int license = swap32(npd->license);
int type = swap32(npd->type);
memcpy(dev + 0x4, &version, 4);
memcpy(dev + 0x8, &license, 4);
memcpy(dev + 0xC, &type, 4);
// Hash with NPDRM_OMAC_KEY_3 and compare with title_hash.
title_hash_result = cmac_hash_compare(NP_OMAC_KEY_3, 0x10, buf, 0x30 + file_name_length, npd->title_hash, 0x10);
if (verbose)
{
if (title_hash_result)
LOG_SUCCESS(LOADER, "EDAT: NPD title hash is valid!\n");
else
LOG_WARNING(LOADER, "EDAT: NPD title hash is invalid!\n");
LOG_NOTICE(LOADER, "EDAT: NPD title hash is valid!");
else
LOG_WARNING(LOADER, "EDAT: NPD title hash is invalid!");
}
// Check for an empty dev_hash (can't validate if devklic is NULL);
@ -477,40 +612,45 @@ void validate_data(const char* file_name, unsigned char *klicensee, NPD_HEADER *
if (isDevklicEmpty)
{
if (verbose)
LOG_WARNING(LOADER, "EDAT: NPD dev hash is empty!\n");
LOG_WARNING(LOADER, "EDAT: NPD dev hash is empty!");
// Allow empty dev hash.
dev_hash_result = 1;
}
else
{
// Generate klicensee xor key.
xor_(key, klicensee, NP_OMAC_KEY_2, 0x10);
xor_key(key, klicensee, NP_OMAC_KEY_2, 0x10);
// Hash with generated key and compare with dev_hash.
dev_hash_result = cmac_hash_compare(key, 0x10, (unsigned char *)npd, 0x60, npd->dev_hash);
dev_hash_result = cmac_hash_compare(key, 0x10, dev, 0x60, npd->dev_hash, 0x10);
if (verbose)
{
if (dev_hash_result)
LOG_SUCCESS(LOADER, "EDAT: NPD dev hash is valid!\n");
else
LOG_WARNING(LOADER, "EDAT: NPD dev hash is invalid!\n");
LOG_NOTICE(LOADER, "EDAT: NPD dev hash is valid!");
else
LOG_WARNING(LOADER, "EDAT: NPD dev hash is invalid!");
}
}
delete[] buf;
return (title_hash_result && dev_hash_result);
}
bool extract_data(rFile *input, rFile *output, const char* input_file_name, unsigned char* devklic, unsigned char* rifkey, bool verbose)
{
// Setup NPD and EDAT/SDAT structs.
NPD_HEADER *NPD = new NPD_HEADER();
EDAT_SDAT_HEADER *EDAT = new EDAT_SDAT_HEADER();
EDAT_HEADER *EDAT = new EDAT_HEADER();
// Read in the NPD and EDAT/SDAT headers.
char npd_header[0x80];
char edat_header[0x10];
input->Read(npd_header, 0x80);
input->Read(edat_header, 0x10);
input->Read(npd_header, sizeof(npd_header));
input->Read(edat_header, sizeof(edat_header));
memcpy(NPD->magic, npd_header, 4);
NPD->version = swap32(*(int*)&npd_header[4]);
NPD->license = swap32(*(int*)&npd_header[8]);
@ -523,7 +663,7 @@ bool extract_data(rFile *input, rFile *output, const char* input_file_name, unsi
NPD->unk2 = swap64(*(u64*)&npd_header[120]);
unsigned char npd_magic[4] = {0x4E, 0x50, 0x44, 0x00}; //NPD0
if(memcmp(NPD->magic, npd_magic, 4))
if (memcmp(NPD->magic, npd_magic, 4))
{
LOG_ERROR(LOADER, "EDAT: %s has invalid NPD header or already decrypted.", input_file_name);
delete NPD;
@ -537,41 +677,65 @@ bool extract_data(rFile *input, rFile *output, const char* input_file_name, unsi
if (verbose)
{
LOG_NOTICE(LOADER, "NPD HEADER\n");
LOG_NOTICE(LOADER, "NPD version: %d\n", NPD->version);
LOG_NOTICE(LOADER, "NPD license: %d\n", NPD->license);
LOG_NOTICE(LOADER, "NPD type: %d\n", NPD->type);
LOG_NOTICE(LOADER, "\n");
LOG_NOTICE(LOADER, "EDAT HEADER\n");
LOG_NOTICE(LOADER, "EDAT flags: 0x%08X\n", EDAT->flags);
LOG_NOTICE(LOADER, "EDAT block size: 0x%08X\n", EDAT->block_size);
LOG_NOTICE(LOADER, "EDAT file size: 0x%08X\n", EDAT->file_size);
LOG_NOTICE(LOADER, "\n");
LOG_NOTICE(LOADER, "NPD HEADER");
LOG_NOTICE(LOADER, "NPD version: %d", NPD->version);
LOG_NOTICE(LOADER, "NPD license: %d", NPD->license);
LOG_NOTICE(LOADER, "NPD type: %d", NPD->type);
}
// Set decryption key.
unsigned char key[0x10];
memset(key, 0, 0x10);
if((EDAT->flags & SDAT_FLAG) == SDAT_FLAG)
// Check EDAT/SDAT flag.
if ((EDAT->flags & SDAT_FLAG) == SDAT_FLAG)
{
LOG_WARNING(LOADER, "EDAT: SDAT detected!\n");
xor_(key, NPD->dev_hash, SDAT_KEY, 0x10);
if (verbose)
{
LOG_NOTICE(LOADER, "SDAT HEADER");
LOG_NOTICE(LOADER, "SDAT flags: 0x%08X", EDAT->flags);
LOG_NOTICE(LOADER, "SDAT block size: 0x%08X", EDAT->block_size);
LOG_NOTICE(LOADER, "SDAT file size: 0x%08X", EDAT->file_size);
}
// Generate SDAT key.
xor_key(key, NPD->dev_hash, SDAT_KEY, 0x10);
}
else
{
// Perform header validation (optional step).
validate_data(input_file_name, devklic, NPD, verbose);
if (verbose)
{
LOG_NOTICE(LOADER, "EDAT HEADER");
LOG_NOTICE(LOADER, "EDAT flags: 0x%08X", EDAT->flags);
LOG_NOTICE(LOADER, "EDAT block size: 0x%08X", EDAT->block_size);
LOG_NOTICE(LOADER, "EDAT file size: 0x%08X", EDAT->file_size);
}
if ((NPD->license & 0x3) == 0x3) // Type 3: Use supplied devklic.
// Perform header validation (EDAT only).
char real_file_name[MAX_PATH];
extract_file_name(input_file_name, real_file_name);
if (!validate_npd_hashes(real_file_name, devklic, NPD, verbose))
{
// Ignore header validation in DEBUG data.
if ((EDAT->flags & EDAT_DEBUG_DATA_FLAG) != EDAT_DEBUG_DATA_FLAG)
{
LOG_ERROR(LOADER, "EDAT: NPD hash validation failed!");
delete NPD;
delete EDAT;
return 1;
}
}
// Select EDAT key.
if ((NPD->license & 0x3) == 0x3) // Type 3: Use supplied devklic.
memcpy(key, devklic, 0x10);
else if ((NPD->license & 0x2) == 0x2) // Type 2: Use key from RAP file (RIF key).
{
else if ((NPD->license & 0x2) == 0x2) // Type 2: Use key from RAP file (RIF key).
{
memcpy(key, rifkey, 0x10);
// Make sure we don't have an empty RIF key.
int i, test = 0;
for(i = 0; i < 0x10; i++)
for (i = 0; i < 0x10; i++)
{
if (key[i] != 0)
{
@ -579,30 +743,65 @@ bool extract_data(rFile *input, rFile *output, const char* input_file_name, unsi
break;
}
}
if (!test)
{
LOG_ERROR(LOADER, "EDAT: A valid RAP file is needed!");
LOG_ERROR(LOADER, "EDAT: A valid RAP file is needed for this EDAT file!");
delete NPD;
delete EDAT;
return 1;
}
}
else if ((NPD->license & 0x1) == 0x1) // Type 1: Use network activation.
{
LOG_ERROR(LOADER, "EDAT: Network license not supported!");
delete NPD;
delete EDAT;
return 1;
}
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]);
}
}
LOG_NOTICE(LOADER, "EDAT: Parsing data...\n");
if (verbose)
{
int i;
LOG_NOTICE(LOADER, "DECRYPTION KEY: ");
for (i = 0; i < 0x10; i++)
LOG_NOTICE(LOADER, "%02X", key[i]);
}
LOG_NOTICE(LOADER, "EDAT: Parsing data...");
if (check_data(key, EDAT, NPD, input, verbose))
LOG_ERROR(LOADER, "EDAT: Data parsing failed!\n");
{
LOG_ERROR(LOADER, "EDAT: Data parsing failed!");
delete NPD;
delete EDAT;
return 1;
}
else
LOG_SUCCESS(LOADER, "EDAT: Data successfully parsed!\n");
LOG_NOTICE(LOADER, "EDAT: Data successfully parsed!");
printf("\n");
LOG_NOTICE(LOADER, "EDAT: Decrypting data...\n");
LOG_NOTICE(LOADER, "EDAT: Decrypting data...");
if (decrypt_data(input, output, EDAT, NPD, key, verbose))
{
LOG_ERROR(LOADER, "EDAT: Data decryption failed!");
delete NPD;
delete EDAT;
return 1;
}
else
LOG_SUCCESS(LOADER, "EDAT: Data successfully decrypted!");
LOG_NOTICE(LOADER, "EDAT: Data successfully decrypted!");
delete NPD;
delete EDAT;
@ -655,21 +854,21 @@ int DecryptEDAT(const std::string& input_file_name, const std::string& output_fi
memcpy(devklic, custom_klic, 0x10);
else
{
LOG_ERROR(LOADER, "EDAT: Invalid custom klic!\n");
LOG_ERROR(LOADER, "EDAT: Invalid custom klic!");
return -1;
}
break;
}
default:
LOG_ERROR(LOADER, "EDAT: Invalid mode!\n");
LOG_ERROR(LOADER, "EDAT: Invalid mode!");
return -1;
}
// Check the input/output files.
if (!input.IsOpened() || !output.IsOpened())
{
LOG_ERROR(LOADER, "EDAT: Failed to open files!\n");
LOG_ERROR(LOADER, "EDAT: Failed to open files!");
return -1;
}
@ -692,11 +891,11 @@ int DecryptEDAT(const std::string& input_file_name, const std::string& output_fi
input.Close();
output.Close();
rRemoveFile(output_file_name);
return 0;
return -1;
}
// Cleanup.
input.Close();
output.Close();
return 0;
}
}

View File

@ -1,9 +1,12 @@
#pragma once
#include <stdio.h>
#include <string.h>
#include "utils.h"
#define SDAT_FLAG 0x01000000
#define EDAT_COMPRESSED_FLAG 0x00000001
#define EDAT_FLAG_0x02 0x00000002
#define EDAT_FLAG_0x04 0x00000004
#define EDAT_ENCRYPTED_KEY_FLAG 0x00000008
#define EDAT_FLAG_0x10 0x00000010
#define EDAT_FLAG_0x20 0x00000020
@ -28,6 +31,6 @@ typedef struct
int flags;
int block_size;
unsigned long long file_size;
} EDAT_SDAT_HEADER;
} EDAT_HEADER;
int DecryptEDAT(const std::string& input_file_name, const std::string& output_file_name, int mode, const std::string& rap_file_name, unsigned char *custom_klic, bool verbose);
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);
be_t<u64> hi = be_t<u64>::MakeFromBE(*(u64*)&iv[0]);
be_t<u64> lo = be_t<u64>::MakeFromBE(*(u64*)&iv[8]);
be_t<u64> hi = *(be_t<u64>*)&iv[0];
be_t<u64> lo = *(be_t<u64>*)&iv[8];
lo++;
if (lo == 0)

View File

@ -10,6 +10,101 @@
#include <wx/mstream.h>
#include <wx/zstream.h>
void WriteEhdr(rFile& f, Elf64_Ehdr& ehdr)
{
Write32(f, ehdr.e_magic);
Write8(f, ehdr.e_class);
Write8(f, ehdr.e_data);
Write8(f, ehdr.e_curver);
Write8(f, ehdr.e_os_abi);
Write64(f, ehdr.e_abi_ver);
Write16(f, ehdr.e_type);
Write16(f, ehdr.e_machine);
Write32(f, ehdr.e_version);
Write64(f, ehdr.e_entry);
Write64(f, ehdr.e_phoff);
Write64(f, ehdr.e_shoff);
Write32(f, ehdr.e_flags);
Write16(f, ehdr.e_ehsize);
Write16(f, ehdr.e_phentsize);
Write16(f, ehdr.e_phnum);
Write16(f, ehdr.e_shentsize);
Write16(f, ehdr.e_shnum);
Write16(f, ehdr.e_shstrndx);
}
void WritePhdr(rFile& f, Elf64_Phdr& phdr)
{
Write32(f, phdr.p_type);
Write32(f, phdr.p_flags);
Write64(f, phdr.p_offset);
Write64(f, phdr.p_vaddr);
Write64(f, phdr.p_paddr);
Write64(f, phdr.p_filesz);
Write64(f, phdr.p_memsz);
Write64(f, phdr.p_align);
}
void WriteShdr(rFile& f, Elf64_Shdr& shdr)
{
Write32(f, shdr.sh_name);
Write32(f, shdr.sh_type);
Write64(f, shdr.sh_flags);
Write64(f, shdr.sh_addr);
Write64(f, shdr.sh_offset);
Write64(f, shdr.sh_size);
Write32(f, shdr.sh_link);
Write32(f, shdr.sh_info);
Write64(f, shdr.sh_addralign);
Write64(f, shdr.sh_entsize);
}
void WriteEhdr(rFile& f, Elf32_Ehdr& ehdr)
{
Write32(f, ehdr.e_magic);
Write8(f, ehdr.e_class);
Write8(f, ehdr.e_data);
Write8(f, ehdr.e_curver);
Write8(f, ehdr.e_os_abi);
Write64(f, ehdr.e_abi_ver);
Write16(f, ehdr.e_type);
Write16(f, ehdr.e_machine);
Write32(f, ehdr.e_version);
Write32(f, ehdr.e_entry);
Write32(f, ehdr.e_phoff);
Write32(f, ehdr.e_shoff);
Write32(f, ehdr.e_flags);
Write16(f, ehdr.e_ehsize);
Write16(f, ehdr.e_phentsize);
Write16(f, ehdr.e_phnum);
Write16(f, ehdr.e_shentsize);
Write16(f, ehdr.e_shnum);
Write16(f, ehdr.e_shstrndx);
}
void WritePhdr(rFile& f, Elf32_Phdr& phdr)
{
Write32(f, phdr.p_type);
Write32(f, phdr.p_offset);
Write32(f, phdr.p_vaddr);
Write32(f, phdr.p_paddr);
Write32(f, phdr.p_filesz);
Write32(f, phdr.p_memsz);
Write32(f, phdr.p_flags);
Write32(f, phdr.p_align);
}
void WriteShdr(rFile& f, Elf32_Shdr& shdr)
{
Write32(f, shdr.sh_name);
Write32(f, shdr.sh_type);
Write32(f, shdr.sh_flags);
Write32(f, shdr.sh_addr);
Write32(f, shdr.sh_offset);
Write32(f, shdr.sh_size);
Write32(f, shdr.sh_link);
Write32(f, shdr.sh_info);
Write32(f, shdr.sh_addralign);
Write32(f, shdr.sh_entsize);
}
void AppInfo::Load(vfsStream& f)
{
authid = Read64(f);
@ -813,10 +908,10 @@ bool SELFDecrypter::GetKeyFromRap(u8 *content_id, u8 *npdrm_key)
u8 rap_key[0x10];
memset(rap_key, 0, 0x10);
// Try to find a matching RAP file under dev_usb000.
// Try to find a matching RAP file under exdata folder.
std::string ci_str((const char *)content_id);
// TODO: This shouldn't use current dir
std::string rap_path("./dev_usb000/" + ci_str + ".rap");
std::string pf_str("00000001"); // TODO: Allow multiple profiles. Use default for now.
std::string rap_path("dev_hdd0/home/" + pf_str + "/exdata/" + ci_str + ".rap");
// Check if we have a valid RAP file.
if (!rExists(rap_path))

View File

@ -1,6 +1,5 @@
#pragma once
#include "Loader/SELF.h"
#include "Loader/ELF64.h"
#include "Loader/ELF32.h"
#include "key_vault.h"
@ -142,7 +141,8 @@ struct MetadataSectionHeader
void Show();
};
struct SectionHash {
struct SectionHash
{
u8 sha1[20];
u8 padding[12];
u8 hmac_key[64];
@ -183,6 +183,291 @@ struct SelfSection
void Load(vfsStream& f);
};
struct Elf32_Ehdr
{
u32 e_magic;
u8 e_class;
u8 e_data;
u8 e_curver;
u8 e_os_abi;
u64 e_abi_ver;
u16 e_type;
u16 e_machine;
u32 e_version;
u32 e_entry;
u32 e_phoff;
u32 e_shoff;
u32 e_flags;
u16 e_ehsize;
u16 e_phentsize;
u16 e_phnum;
u16 e_shentsize;
u16 e_shnum;
u16 e_shstrndx;
void Show() {}
bool IsLittleEndian() const
{
return e_data == 1;
}
void Load(vfsStream& f)
{
e_magic = Read32(f);
e_class = Read8(f);
e_data = Read8(f);
e_curver = Read8(f);
e_os_abi = Read8(f);
if (IsLittleEndian())
{
e_abi_ver = Read64LE(f);
e_type = Read16LE(f);
e_machine = Read16LE(f);
e_version = Read32LE(f);
e_entry = Read32LE(f);
e_phoff = Read32LE(f);
e_shoff = Read32LE(f);
e_flags = Read32LE(f);
e_ehsize = Read16LE(f);
e_phentsize = Read16LE(f);
e_phnum = Read16LE(f);
e_shentsize = Read16LE(f);
e_shnum = Read16LE(f);
e_shstrndx = Read16LE(f);
}
else
{
e_abi_ver = Read64(f);
e_type = Read16(f);
e_machine = Read16(f);
e_version = Read32(f);
e_entry = Read32(f);
e_phoff = Read32(f);
e_shoff = Read32(f);
e_flags = Read32(f);
e_ehsize = Read16(f);
e_phentsize = Read16(f);
e_phnum = Read16(f);
e_shentsize = Read16(f);
e_shnum = Read16(f);
e_shstrndx = Read16(f);
}
}
bool CheckMagic() const { return e_magic == 0x7F454C46; }
u32 GetEntry() const { return e_entry; }
};
struct Elf32_Shdr
{
u32 sh_name;
u32 sh_type;
u32 sh_flags;
u32 sh_addr;
u32 sh_offset;
u32 sh_size;
u32 sh_link;
u32 sh_info;
u32 sh_addralign;
u32 sh_entsize;
void Load(vfsStream& f)
{
sh_name = Read32(f);
sh_type = Read32(f);
sh_flags = Read32(f);
sh_addr = Read32(f);
sh_offset = Read32(f);
sh_size = Read32(f);
sh_link = Read32(f);
sh_info = Read32(f);
sh_addralign = Read32(f);
sh_entsize = Read32(f);
}
void LoadLE(vfsStream& f)
{
f.Read(this, sizeof(*this));
}
void Show() {}
};
struct Elf32_Phdr
{
u32 p_type;
u32 p_offset;
u32 p_vaddr;
u32 p_paddr;
u32 p_filesz;
u32 p_memsz;
u32 p_flags;
u32 p_align;
void Load(vfsStream& f)
{
p_type = Read32(f);
p_offset = Read32(f);
p_vaddr = Read32(f);
p_paddr = Read32(f);
p_filesz = Read32(f);
p_memsz = Read32(f);
p_flags = Read32(f);
p_align = Read32(f);
}
void LoadLE(vfsStream& f)
{
f.Read(this, sizeof(*this));
}
void Show() {}
};
struct Elf64_Ehdr
{
u32 e_magic;
u8 e_class;
u8 e_data;
u8 e_curver;
u8 e_os_abi;
u64 e_abi_ver;
u16 e_type;
u16 e_machine;
u32 e_version;
u64 e_entry;
u64 e_phoff;
u64 e_shoff;
u32 e_flags;
u16 e_ehsize;
u16 e_phentsize;
u16 e_phnum;
u16 e_shentsize;
u16 e_shnum;
u16 e_shstrndx;
void Load(vfsStream& f)
{
e_magic = Read32(f);
e_class = Read8(f);
e_data = Read8(f);
e_curver = Read8(f);
e_os_abi = Read8(f);
e_abi_ver = Read64(f);
e_type = Read16(f);
e_machine = Read16(f);
e_version = Read32(f);
e_entry = Read64(f);
e_phoff = Read64(f);
e_shoff = Read64(f);
e_flags = Read32(f);
e_ehsize = Read16(f);
e_phentsize = Read16(f);
e_phnum = Read16(f);
e_shentsize = Read16(f);
e_shnum = Read16(f);
e_shstrndx = Read16(f);
}
void Show() {}
bool CheckMagic() const { return e_magic == 0x7F454C46; }
u64 GetEntry() const { return e_entry; }
};
struct Elf64_Shdr
{
u32 sh_name;
u32 sh_type;
u64 sh_flags;
u64 sh_addr;
u64 sh_offset;
u64 sh_size;
u32 sh_link;
u32 sh_info;
u64 sh_addralign;
u64 sh_entsize;
void Load(vfsStream& f)
{
sh_name = Read32(f);
sh_type = Read32(f);
sh_flags = Read64(f);
sh_addr = Read64(f);
sh_offset = Read64(f);
sh_size = Read64(f);
sh_link = Read32(f);
sh_info = Read32(f);
sh_addralign = Read64(f);
sh_entsize = Read64(f);
}
void Show(){}
};
struct Elf64_Phdr
{
u32 p_type;
u32 p_flags;
u64 p_offset;
u64 p_vaddr;
u64 p_paddr;
u64 p_filesz;
u64 p_memsz;
u64 p_align;
void Load(vfsStream& f)
{
p_type = Read32(f);
p_flags = Read32(f);
p_offset = Read64(f);
p_vaddr = Read64(f);
p_paddr = Read64(f);
p_filesz = Read64(f);
p_memsz = Read64(f);
p_align = Read64(f);
}
void Show(){}
};
struct SceHeader
{
u32 se_magic;
u32 se_hver;
u16 se_flags;
u16 se_type;
u32 se_meta;
u64 se_hsize;
u64 se_esize;
void Load(vfsStream& f)
{
se_magic = Read32(f);
se_hver = Read32(f);
se_flags = Read16(f);
se_type = Read16(f);
se_meta = Read32(f);
se_hsize = Read64(f);
se_esize = Read64(f);
}
void Show(){}
bool CheckMagic() const { return se_magic == 0x53434500; }
};
struct SelfHeader
{
u64 se_htype;
u64 se_appinfooff;
u64 se_elfoff;
u64 se_phdroff;
u64 se_shdroff;
u64 se_secinfoff;
u64 se_sceveroff;
u64 se_controloff;
u64 se_controlsize;
u64 pad;
void Load(vfsStream& f)
{
se_htype = Read64(f);
se_appinfooff = Read64(f);
se_elfoff = Read64(f);
se_phdroff = Read64(f);
se_shdroff = Read64(f);
se_secinfoff = Read64(f);
se_sceveroff = Read64(f);
se_controloff = Read64(f);
se_controlsize = Read64(f);
pad = Read64(f);
}
void Show(){}
};
class SELFDecrypter
{
// Main SELF file stream.

View File

@ -1,9 +1,13 @@
#include "stdafx.h"
#include "aes.h"
#include "sha1.h"
#include "utils.h"
// Copyright (C) 2014 Hykem <hykem@hotmail.com>
// Licensed under the terms of the GNU GPL, version 3
// http://www.gnu.org/licenses/gpl-3.0.txt
// Endian swap auxiliary functions.
#include "stdafx.h"
#include "utils.h"
#include <stdio.h>
#include <time.h>
// Auxiliary functions (endian swap, xor and prng).
u16 swap16(u16 i)
{
return ((i & 0xFF00) >> 8) | ((i & 0xFF) << 8);
@ -22,7 +26,7 @@ u64 swap64(u64 i)
((i & 0x00ff000000000000) >> 40) | ((i & 0xff00000000000000) >> 56);
}
void xor_(unsigned char *dest, unsigned char *src1, unsigned char *src2, int size)
void xor_key(unsigned char *dest, unsigned char *src1, unsigned char *src2, int size)
{
int i;
for(i = 0; i < size; i++)
@ -31,10 +35,24 @@ void xor_(unsigned char *dest, unsigned char *src1, unsigned char *src2, int siz
}
}
void prng(unsigned char *dest, int size)
{
unsigned char *buffer = new unsigned char[size];
srand((u32)time(0));
int i;
for(i = 0; i < size; i++)
buffer[i] = (unsigned char)(rand() & 0xFF);
memcpy(dest, buffer, size);
delete[] buffer;
}
// Hex string conversion auxiliary functions.
u64 hex_to_u64(const char* hex_str)
{
u32 length = (u32)strlen(hex_str);
u32 length = (u32) strlen(hex_str);
u64 tmp = 0;
u64 result = 0;
char c;
@ -56,19 +74,19 @@ u64 hex_to_u64(const char* hex_str)
return result;
}
void hex_to_bytes(unsigned char *data, const char *hex_str)
void hex_to_bytes(unsigned char *data, const char *hex_str, unsigned int str_length)
{
u32 str_length = (u32)strlen(hex_str);
u32 data_length = str_length / 2;
u32 strn_length = (str_length > 0) ? str_length : (u32) strlen(hex_str);
u32 data_length = strn_length / 2;
char tmp_buf[3] = {0, 0, 0};
// Don't convert if the string length is odd.
if (!(str_length % 2))
if (!(strn_length % 2))
{
u8 *out = (u8 *) malloc (str_length * sizeof(u8));
u8 *out = (u8 *)malloc(strn_length * sizeof(u8));
u8 *pos = out;
while (str_length--)
while (strn_length--)
{
tmp_buf[0] = *hex_str++;
tmp_buf[1] = *hex_str++;
@ -81,6 +99,23 @@ void hex_to_bytes(unsigned char *data, const char *hex_str)
}
}
bool is_hex(const char* hex_str, unsigned int str_length)
{
static const char hex_chars[] = "0123456789abcdefABCDEF";
if (hex_str == NULL)
return false;
unsigned int i;
for (i = 0; i < str_length; i++)
{
if (strchr(hex_chars, hex_str[i]) == 0)
return false;
}
return true;
}
// Crypto functions (AES128-CBC, AES128-ECB, SHA1-HMAC and AES-CMAC).
void aescbc128_decrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, int len)
{
@ -92,6 +127,16 @@ void aescbc128_decrypt(unsigned char *key, unsigned char *iv, unsigned char *in,
memset(iv, 0, 0x10);
}
void aescbc128_encrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, int len)
{
aes_context ctx;
aes_setkey_enc(&ctx, key, 128);
aes_crypt_cbc(&ctx, AES_ENCRYPT, len, iv, in, out);
// Reset the IV.
memset(iv, 0, 0x10);
}
void aesecb128_encrypt(unsigned char *key, unsigned char *in, unsigned char *out)
{
aes_context ctx;
@ -99,13 +144,13 @@ void aesecb128_encrypt(unsigned char *key, unsigned char *in, unsigned char *out
aes_crypt_ecb(&ctx, AES_ENCRYPT, in, out);
}
bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash)
bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash, int hash_len)
{
unsigned char *out = new unsigned char[key_len];
sha1_hmac(key, key_len, in, in_len, out);
for (int i = 0; i < 0x10; i++)
for (int i = 0; i < hash_len; i++)
{
if (out[i] != hash[i])
{
@ -119,7 +164,12 @@ bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int i
return true;
}
bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash)
void hmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash)
{
sha1_hmac(key, key_len, in, in_len, hash);
}
bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash, int hash_len)
{
unsigned char *out = new unsigned char[key_len];
@ -127,7 +177,7 @@ bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int i
aes_setkey_enc(&ctx, key, 128);
aes_cmac(&ctx, in_len, in, out);
for (int i = 0; i < key_len; i++)
for (int i = 0; i < hash_len; i++)
{
if (out[i] != hash[i])
{
@ -141,9 +191,20 @@ bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int i
return true;
}
#include "lz.h"
// Reverse-engineered custom LempelZivMarkov based compression (unknown variant of LZRC).
int lz_decompress(unsigned char *out, unsigned char *in, unsigned int size)
void cmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash)
{
return decompress(out,in,size);
aes_context ctx;
aes_setkey_enc(&ctx, key, 128);
aes_cmac(&ctx, in_len, in, hash);
}
char* extract_file_name(const char* file_path, char real_file_name[MAX_PATH])
{
size_t file_path_len = strlen(file_path);
const char* p = strrchr(file_path, '/');
if (!p) p = strrchr(file_path, '\\');
if (p) file_path_len = file_path + file_path_len - p - 1;
strncpy(real_file_name, p ? (p + 1) : file_path, file_path_len + 1);
return real_file_name;
}

View File

@ -1,20 +1,35 @@
#pragma once
// Auxiliary functions (endian swap and xor).
// Copyright (C) 2014 Hykem <hykem@hotmail.com>
// Licensed under the terms of the GNU GPL, version 3
// http://www.gnu.org/licenses/gpl-3.0.txt
#define MAX_PATH 4096
#include <stdlib.h>
#include "aes.h"
#include "sha1.h"
#include "lz.h"
#include "ec.h"
// Auxiliary functions (endian swap, xor, prng and file name).
u16 swap16(u16 i);
u32 swap32(u32 i);
u64 swap64(u64 i);
void xor_(unsigned char *dest, unsigned char *src1, unsigned char *src2, int size);
void xor_key(unsigned char *dest, unsigned char *src1, unsigned char *src2, int size);
void prng(unsigned char *dest, int size);
char* extract_file_name(const char* file_path, char real_file_name[MAX_PATH]);
// Hex string conversion auxiliary functions.
u64 hex_to_u64(const char* hex_str);
void hex_to_bytes(unsigned char *data, const char *hex_str);
void hex_to_bytes(unsigned char *data, const char *hex_str, unsigned int str_length);
bool is_hex(const char* hex_str, unsigned int str_length);
// Crypto functions (AES128-CBC, AES128-ECB, SHA1-HMAC and AES-CMAC).
void aescbc128_decrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, int len);
void aescbc128_encrypt(unsigned char *key, unsigned char *iv, unsigned char *in, unsigned char *out, int len);
void aesecb128_encrypt(unsigned char *key, unsigned char *in, unsigned char *out);
bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash);
bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash);
// Reverse-engineered custom LempelZivMarkov based compression (unknown variant of LZRC).
int lz_decompress(unsigned char *out, unsigned char *in, unsigned int size);
bool hmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash, int hash_len);
void hmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash);
bool cmac_hash_compare(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash, int hash_len);
void cmac_hash_forge(unsigned char *key, int key_len, unsigned char *in, int in_len, unsigned char *hash);

View File

@ -13,125 +13,23 @@ public:
{
}
u32 branchTarget(u32 imm)
{
return imm << 1;
}
virtual u8 DecodeMemory(const u32 address)
{
using namespace ARMv7_opcodes;
const u16 code0 = vm::psv::read16(address);
const u16 code1 = vm::psv::read16(address + 2);
const u32 code0 = vm::psv::read16(address & ~1);
const u32 code1 = vm::psv::read16(address + 2 & ~1);
const u32 data = code0 << 16 | code1;
const u32 arg = address & 1 ? code1 << 16 | code0 : data;
switch(code0 >> 12) //15 - 12
for (auto& opcode : ARMv7_opcode_table)
{
case T1_CBZ:
switch((code0 >> 10) & 0x1)
if ((opcode.type < A1) == ((address & 1) == 0) && (arg & opcode.mask) == opcode.code)
{
case 0:
switch((code0 >> 8) & 0x1)
{
case 1:
m_op.CBZ((code0 >> 11) & 0x1, branchTarget((((code0 >> 9) & 0x1) << 5) | ((code0 >> 3) & 0x1f)), code0 & 0x7, 2);
return 2;
}
break;
}
break;
case T1_B:
m_op.B((code0 >> 8) & 0xf, branchTarget(code0 & 0xff), 2);
return 2;
}
switch(code0 >> 11) //15 - 11
{
case T2_B:
m_op.B(0xf, branchTarget(code0 & 0xfff), 2);
return 2;
case T3_B:
{
u8 S = (code0 >> 10) & 0x1;
u8 J1 = (code1 >> 13) & 0x1;
u8 J2 = (code1 >> 11) & 0x1;
u8 I1 = 1 - (J1 ^ S);
u8 I2 = 1 - (J2 ^ S);
u16 imm11 = code1 & 0x7ff;
u32 imm32 = 0;
switch(code1 >> 14)
{
case 2: //B
{
u8 cond;
switch((code1 >> 12) & 0x1)
{
case 0:
{
cond = (code0 >> 6) & 0xf;
u32 imm6 = code0 & 0x3f;
imm32 = sign<19, u32>((S << 19) | (I1 << 18) | (I2 << 17) | (imm6 << 11) | imm11);
}
break;
case 1:
cond = 0xf;
u32 imm10 = code0 & 0x7ff;
imm32 = sign<23, u32>((S << 23) | (I1 << 22) | (I2 << 21) | (imm10 << 11) | imm11);
break;
}
m_op.B(cond, branchTarget(imm32), 4);
}
return 4;
case 3: //BL
switch((code1 >> 12) & 0x1)
{
case 0:
break;
case 1:
u32 imm10 = code0 & 0x7ff;
imm32 = sign<23, u32>((S << 23) | (I1 << 22) | (I2 << 21) | (imm10 << 11) | imm11);
m_op.BL(branchTarget(imm32), 4);
return 4;
}
break;
(m_op.*opcode.func)(opcode.length == 2 ? code0 : arg, opcode.type);
return opcode.length;
}
}
break;
}
switch(code0 >> 9)
{
case T1_PUSH:
m_op.PUSH((((code0 >> 8) & 0x1) << 14) | (code0 & 0xff));
return 2;
case T1_POP:
m_op.POP((((code0 >> 8) & 0x1) << 15) | (code0 & 0xff));
return 2;
}
switch(code0)
{
case T2_PUSH:
m_op.PUSH(code1);
return 4;
case T2_POP:
m_op.POP(code1);
return 4;
case T1_NOP:
m_op.NOP();
return 2;
}
m_op.UNK(code0, code1);
return 2;
m_op.UNK(data);
return address & 1 ? 4 : 2;
}
};

File diff suppressed because it is too large Load Diff

View File

@ -45,50 +45,276 @@ protected:
return regs_str;
}
void NULL_OP()
{
Write("null");
}
virtual void UNK(const u32 data);
void PUSH(u16 regs_list)
{
Write(fmt::Format("push {%s}", GetRegsListString(regs_list).c_str()));
}
virtual void NULL_OP(const u32 data, const ARMv7_encoding type);
void POP(u16 regs_list)
{
Write(fmt::Format("pop {%s}", GetRegsListString(regs_list).c_str()));
}
virtual void HACK(const u32 data, const ARMv7_encoding type);
void NOP()
{
Write("nop");
}
virtual void ADC_IMM(const u32 data, const ARMv7_encoding type);
virtual void ADC_REG(const u32 data, const ARMv7_encoding type);
virtual void ADC_RSR(const u32 data, const ARMv7_encoding type);
void B(u8 cond, u32 imm, u8 intstr_size)
{
if((cond & 0xe) == 0xe)
{
Write(fmt::Format("b 0x%x", DisAsmBranchTarget(imm) + intstr_size));
}
else
{
Write(fmt::Format("b[%s] 0x%x", g_arm_cond_name[cond], DisAsmBranchTarget(imm) + intstr_size));
}
}
virtual void ADD_IMM(const u32 data, const ARMv7_encoding type);
virtual void ADD_REG(const u32 data, const ARMv7_encoding type);
virtual void ADD_RSR(const u32 data, const ARMv7_encoding type);
virtual void ADD_SPI(const u32 data, const ARMv7_encoding type);
virtual void ADD_SPR(const u32 data, const ARMv7_encoding type);
virtual void CBZ(u8 op, u32 imm, u8 rn, u8 intstr_size)
{
Write(fmt::Format("cb%sz 0x%x,%s", (op ? "n" : ""), DisAsmBranchTarget(imm) + intstr_size, g_arm_reg_name[rn]));
}
virtual void ADR(const u32 data, const ARMv7_encoding type);
void BL(u32 imm, u8 intstr_size)
{
Write(fmt::Format("bl 0x%x", DisAsmBranchTarget(imm) + intstr_size));
}
virtual void AND_IMM(const u32 data, const ARMv7_encoding type);
virtual void AND_REG(const u32 data, const ARMv7_encoding type);
virtual void AND_RSR(const u32 data, const ARMv7_encoding type);
void UNK(const u16 code0, const u16 code1)
{
Write(fmt::Format("Unknown/Illegal opcode! (0x%04x : 0x%04x)", code0, code1));
}
virtual void ASR_IMM(const u32 data, const ARMv7_encoding type);
virtual void ASR_REG(const u32 data, const ARMv7_encoding type);
virtual void B(const u32 data, const ARMv7_encoding type);
virtual void BFC(const u32 data, const ARMv7_encoding type);
virtual void BFI(const u32 data, const ARMv7_encoding type);
virtual void BIC_IMM(const u32 data, const ARMv7_encoding type);
virtual void BIC_REG(const u32 data, const ARMv7_encoding type);
virtual void BIC_RSR(const u32 data, const ARMv7_encoding type);
virtual void BKPT(const u32 data, const ARMv7_encoding type);
virtual void BL(const u32 data, const ARMv7_encoding type);
virtual void BLX(const u32 data, const ARMv7_encoding type);
virtual void BX(const u32 data, const ARMv7_encoding type);
virtual void CB_Z(const u32 data, const ARMv7_encoding type);
virtual void CLZ(const u32 data, const ARMv7_encoding type);
virtual void CMN_IMM(const u32 data, const ARMv7_encoding type);
virtual void CMN_REG(const u32 data, const ARMv7_encoding type);
virtual void CMN_RSR(const u32 data, const ARMv7_encoding type);
virtual void CMP_IMM(const u32 data, const ARMv7_encoding type);
virtual void CMP_REG(const u32 data, const ARMv7_encoding type);
virtual void CMP_RSR(const u32 data, const ARMv7_encoding type);
virtual void EOR_IMM(const u32 data, const ARMv7_encoding type);
virtual void EOR_REG(const u32 data, const ARMv7_encoding type);
virtual void EOR_RSR(const u32 data, const ARMv7_encoding type);
virtual void IT(const u32 data, const ARMv7_encoding type);
virtual void LDM(const u32 data, const ARMv7_encoding type);
virtual void LDMDA(const u32 data, const ARMv7_encoding type);
virtual void LDMDB(const u32 data, const ARMv7_encoding type);
virtual void LDMIB(const u32 data, const ARMv7_encoding type);
virtual void LDR_IMM(const u32 data, const ARMv7_encoding type);
virtual void LDR_LIT(const u32 data, const ARMv7_encoding type);
virtual void LDR_REG(const u32 data, const ARMv7_encoding type);
virtual void LDRB_IMM(const u32 data, const ARMv7_encoding type);
virtual void LDRB_LIT(const u32 data, const ARMv7_encoding type);
virtual void LDRB_REG(const u32 data, const ARMv7_encoding type);
virtual void LDRD_IMM(const u32 data, const ARMv7_encoding type);
virtual void LDRD_LIT(const u32 data, const ARMv7_encoding type);
virtual void LDRD_REG(const u32 data, const ARMv7_encoding type);
virtual void LDRH_IMM(const u32 data, const ARMv7_encoding type);
virtual void LDRH_LIT(const u32 data, const ARMv7_encoding type);
virtual void LDRH_REG(const u32 data, const ARMv7_encoding type);
virtual void LDRSB_IMM(const u32 data, const ARMv7_encoding type);
virtual void LDRSB_LIT(const u32 data, const ARMv7_encoding type);
virtual void LDRSB_REG(const u32 data, const ARMv7_encoding type);
virtual void LDRSH_IMM(const u32 data, const ARMv7_encoding type);
virtual void LDRSH_LIT(const u32 data, const ARMv7_encoding type);
virtual void LDRSH_REG(const u32 data, const ARMv7_encoding type);
virtual void LSL_IMM(const u32 data, const ARMv7_encoding type);
virtual void LSL_REG(const u32 data, const ARMv7_encoding type);
virtual void LSR_IMM(const u32 data, const ARMv7_encoding type);
virtual void LSR_REG(const u32 data, const ARMv7_encoding type);
virtual void MLA(const u32 data, const ARMv7_encoding type);
virtual void MLS(const u32 data, const ARMv7_encoding type);
virtual void MOV_IMM(const u32 data, const ARMv7_encoding type);
virtual void MOV_REG(const u32 data, const ARMv7_encoding type);
virtual void MOVT(const u32 data, const ARMv7_encoding type);
virtual void MRS(const u32 data, const ARMv7_encoding type);
virtual void MSR_IMM(const u32 data, const ARMv7_encoding type);
virtual void MSR_REG(const u32 data, const ARMv7_encoding type);
virtual void MUL(const u32 data, const ARMv7_encoding type);
virtual void MVN_IMM(const u32 data, const ARMv7_encoding type);
virtual void MVN_REG(const u32 data, const ARMv7_encoding type);
virtual void MVN_RSR(const u32 data, const ARMv7_encoding type);
virtual void NOP(const u32 data, const ARMv7_encoding type);
virtual void ORN_IMM(const u32 data, const ARMv7_encoding type);
virtual void ORN_REG(const u32 data, const ARMv7_encoding type);
virtual void ORR_IMM(const u32 data, const ARMv7_encoding type);
virtual void ORR_REG(const u32 data, const ARMv7_encoding type);
virtual void ORR_RSR(const u32 data, const ARMv7_encoding type);
virtual void PKH(const u32 data, const ARMv7_encoding type);
virtual void POP(const u32 data, const ARMv7_encoding type);
virtual void PUSH(const u32 data, const ARMv7_encoding type);
virtual void QADD(const u32 data, const ARMv7_encoding type);
virtual void QADD16(const u32 data, const ARMv7_encoding type);
virtual void QADD8(const u32 data, const ARMv7_encoding type);
virtual void QASX(const u32 data, const ARMv7_encoding type);
virtual void QDADD(const u32 data, const ARMv7_encoding type);
virtual void QDSUB(const u32 data, const ARMv7_encoding type);
virtual void QSAX(const u32 data, const ARMv7_encoding type);
virtual void QSUB(const u32 data, const ARMv7_encoding type);
virtual void QSUB16(const u32 data, const ARMv7_encoding type);
virtual void QSUB8(const u32 data, const ARMv7_encoding type);
virtual void RBIT(const u32 data, const ARMv7_encoding type);
virtual void REV(const u32 data, const ARMv7_encoding type);
virtual void REV16(const u32 data, const ARMv7_encoding type);
virtual void REVSH(const u32 data, const ARMv7_encoding type);
virtual void ROR_IMM(const u32 data, const ARMv7_encoding type);
virtual void ROR_REG(const u32 data, const ARMv7_encoding type);
virtual void RRX(const u32 data, const ARMv7_encoding type);
virtual void RSB_IMM(const u32 data, const ARMv7_encoding type);
virtual void RSB_REG(const u32 data, const ARMv7_encoding type);
virtual void RSB_RSR(const u32 data, const ARMv7_encoding type);
virtual void RSC_IMM(const u32 data, const ARMv7_encoding type);
virtual void RSC_REG(const u32 data, const ARMv7_encoding type);
virtual void RSC_RSR(const u32 data, const ARMv7_encoding type);
virtual void SADD16(const u32 data, const ARMv7_encoding type);
virtual void SADD8(const u32 data, const ARMv7_encoding type);
virtual void SASX(const u32 data, const ARMv7_encoding type);
virtual void SBC_IMM(const u32 data, const ARMv7_encoding type);
virtual void SBC_REG(const u32 data, const ARMv7_encoding type);
virtual void SBC_RSR(const u32 data, const ARMv7_encoding type);
virtual void SBFX(const u32 data, const ARMv7_encoding type);
virtual void SDIV(const u32 data, const ARMv7_encoding type);
virtual void SEL(const u32 data, const ARMv7_encoding type);
virtual void SHADD16(const u32 data, const ARMv7_encoding type);
virtual void SHADD8(const u32 data, const ARMv7_encoding type);
virtual void SHASX(const u32 data, const ARMv7_encoding type);
virtual void SHSAX(const u32 data, const ARMv7_encoding type);
virtual void SHSUB16(const u32 data, const ARMv7_encoding type);
virtual void SHSUB8(const u32 data, const ARMv7_encoding type);
virtual void SMLA__(const u32 data, const ARMv7_encoding type);
virtual void SMLAD(const u32 data, const ARMv7_encoding type);
virtual void SMLAL(const u32 data, const ARMv7_encoding type);
virtual void SMLAL__(const u32 data, const ARMv7_encoding type);
virtual void SMLALD(const u32 data, const ARMv7_encoding type);
virtual void SMLAW_(const u32 data, const ARMv7_encoding type);
virtual void SMLSD(const u32 data, const ARMv7_encoding type);
virtual void SMLSLD(const u32 data, const ARMv7_encoding type);
virtual void SMMLA(const u32 data, const ARMv7_encoding type);
virtual void SMMLS(const u32 data, const ARMv7_encoding type);
virtual void SMMUL(const u32 data, const ARMv7_encoding type);
virtual void SMUAD(const u32 data, const ARMv7_encoding type);
virtual void SMUL__(const u32 data, const ARMv7_encoding type);
virtual void SMULL(const u32 data, const ARMv7_encoding type);
virtual void SMULW_(const u32 data, const ARMv7_encoding type);
virtual void SMUSD(const u32 data, const ARMv7_encoding type);
virtual void SSAT(const u32 data, const ARMv7_encoding type);
virtual void SSAT16(const u32 data, const ARMv7_encoding type);
virtual void SSAX(const u32 data, const ARMv7_encoding type);
virtual void SSUB16(const u32 data, const ARMv7_encoding type);
virtual void SSUB8(const u32 data, const ARMv7_encoding type);
virtual void STM(const u32 data, const ARMv7_encoding type);
virtual void STMDA(const u32 data, const ARMv7_encoding type);
virtual void STMDB(const u32 data, const ARMv7_encoding type);
virtual void STMIB(const u32 data, const ARMv7_encoding type);
virtual void STR_IMM(const u32 data, const ARMv7_encoding type);
virtual void STR_REG(const u32 data, const ARMv7_encoding type);
virtual void STRB_IMM(const u32 data, const ARMv7_encoding type);
virtual void STRB_REG(const u32 data, const ARMv7_encoding type);
virtual void STRD_IMM(const u32 data, const ARMv7_encoding type);
virtual void STRD_REG(const u32 data, const ARMv7_encoding type);
virtual void STRH_IMM(const u32 data, const ARMv7_encoding type);
virtual void STRH_REG(const u32 data, const ARMv7_encoding type);
virtual void SUB_IMM(const u32 data, const ARMv7_encoding type);
virtual void SUB_REG(const u32 data, const ARMv7_encoding type);
virtual void SUB_RSR(const u32 data, const ARMv7_encoding type);
virtual void SUB_SPI(const u32 data, const ARMv7_encoding type);
virtual void SUB_SPR(const u32 data, const ARMv7_encoding type);
virtual void SVC(const u32 data, const ARMv7_encoding type);
virtual void SXTAB(const u32 data, const ARMv7_encoding type);
virtual void SXTAB16(const u32 data, const ARMv7_encoding type);
virtual void SXTAH(const u32 data, const ARMv7_encoding type);
virtual void SXTB(const u32 data, const ARMv7_encoding type);
virtual void SXTB16(const u32 data, const ARMv7_encoding type);
virtual void SXTH(const u32 data, const ARMv7_encoding type);
virtual void TB_(const u32 data, const ARMv7_encoding type);
virtual void TEQ_IMM(const u32 data, const ARMv7_encoding type);
virtual void TEQ_REG(const u32 data, const ARMv7_encoding type);
virtual void TEQ_RSR(const u32 data, const ARMv7_encoding type);
virtual void TST_IMM(const u32 data, const ARMv7_encoding type);
virtual void TST_REG(const u32 data, const ARMv7_encoding type);
virtual void TST_RSR(const u32 data, const ARMv7_encoding type);
virtual void UADD16(const u32 data, const ARMv7_encoding type);
virtual void UADD8(const u32 data, const ARMv7_encoding type);
virtual void UASX(const u32 data, const ARMv7_encoding type);
virtual void UBFX(const u32 data, const ARMv7_encoding type);
virtual void UDIV(const u32 data, const ARMv7_encoding type);
virtual void UHADD16(const u32 data, const ARMv7_encoding type);
virtual void UHADD8(const u32 data, const ARMv7_encoding type);
virtual void UHASX(const u32 data, const ARMv7_encoding type);
virtual void UHSAX(const u32 data, const ARMv7_encoding type);
virtual void UHSUB16(const u32 data, const ARMv7_encoding type);
virtual void UHSUB8(const u32 data, const ARMv7_encoding type);
virtual void UMAAL(const u32 data, const ARMv7_encoding type);
virtual void UMLAL(const u32 data, const ARMv7_encoding type);
virtual void UMULL(const u32 data, const ARMv7_encoding type);
virtual void UQADD16(const u32 data, const ARMv7_encoding type);
virtual void UQADD8(const u32 data, const ARMv7_encoding type);
virtual void UQASX(const u32 data, const ARMv7_encoding type);
virtual void UQSAX(const u32 data, const ARMv7_encoding type);
virtual void UQSUB16(const u32 data, const ARMv7_encoding type);
virtual void UQSUB8(const u32 data, const ARMv7_encoding type);
virtual void USAD8(const u32 data, const ARMv7_encoding type);
virtual void USADA8(const u32 data, const ARMv7_encoding type);
virtual void USAT(const u32 data, const ARMv7_encoding type);
virtual void USAT16(const u32 data, const ARMv7_encoding type);
virtual void USAX(const u32 data, const ARMv7_encoding type);
virtual void USUB16(const u32 data, const ARMv7_encoding type);
virtual void USUB8(const u32 data, const ARMv7_encoding type);
virtual void UXTAB(const u32 data, const ARMv7_encoding type);
virtual void UXTAB16(const u32 data, const ARMv7_encoding type);
virtual void UXTAH(const u32 data, const ARMv7_encoding type);
virtual void UXTB(const u32 data, const ARMv7_encoding type);
virtual void UXTB16(const u32 data, const ARMv7_encoding type);
virtual void UXTH(const u32 data, const ARMv7_encoding type);
};

File diff suppressed because it is too large Load Diff

View File

@ -10,7 +10,7 @@ public:
{
}
enum SRType
enum SRType : u32
{
SRType_None,
SRType_LSL,
@ -93,7 +93,7 @@ public:
return len - 1 - HighestSetBit(x, len);
}
SRType DecodeImmShift(u8 type, u8 imm5, uint* shift_n)
SRType DecodeImmShift(u32 type, u32 imm5, u32* shift_n)
{
SRType shift_t = SRType_None;
@ -217,7 +217,7 @@ public:
return value;
}
template<typename T> T Shift(T value, SRType type, uint amount, bool carry_in)
template<typename T> T Shift(T value, SRType type, u32 amount, bool carry_in)
{
bool carry_out;
return Shift_C(value, type, amount, carry_in, carry_out);
@ -225,15 +225,50 @@ public:
template<typename T> T AddWithCarry(T x, T y, bool carry_in, bool& carry_out, bool& overflow)
{
uint unsigned_sum = (uint)x + (uint)y + (uint)carry_in;
int signed_sum = (int)x + (int)y + (int)carry_in;
T result = unsigned_sum & ~(T(1) << (sizeof(T) - 1));
carry_out = (uint)result != unsigned_sum;
overflow = (int)result != signed_sum;
const T sign_mask = (T)1 << (sizeof(T) - 1);
T result = x + y;
carry_out = ((x & y) | ((x ^ y) & ~result)) & sign_mask;
overflow = (x ^ result) & (y ^ result) & sign_mask;
if (carry_in)
{
result += 1;
carry_out ^= (result == 0);
overflow ^= (result == sign_mask);
}
return result;
}
bool ConditionPassed(u8 cond) const
u32 ThumbExpandImm_C(u32 imm12, bool carry_in, bool& carry_out)
{
if ((imm12 & 0xc00) >> 10)
{
u32 unrotated_value = (imm12 & 0x7f) | 0x80;
return ROR_C(unrotated_value, (imm12 & 0xf80) >> 7, carry_out);
}
else
{
carry_out = carry_in;
u32 imm8 = imm12 & 0xff;
switch ((imm12 & 0x300) >> 8)
{
case 0: return imm8;
case 1: return imm8 << 16 | imm8;
case 2: return imm8 << 24 | imm8 << 8;
default: return imm8 << 24 | imm8 << 16 | imm8 << 8 | imm8;
}
}
}
u32 ThumbExpandImm(u32 imm12)
{
bool carry = CPU.APSR.C;
return ThumbExpandImm_C(imm12, carry, carry);
}
bool ConditionPassed(u32 cond) const
{
bool result = false;
@ -258,65 +293,276 @@ public:
}
protected:
void NULL_OP()
{
LOG_ERROR(HLE, "null");
Emu.Pause();
}
virtual void UNK(const u32 data);
void NOP()
{
}
virtual void NULL_OP(const u32 data, const ARMv7_encoding type);
void PUSH(u16 regs_list)
{
for(u16 mask=0x1, i=0; mask; mask <<= 1, i++)
{
if(regs_list & mask)
{
CPU.SP -= 4;
vm::psv::write32(CPU.SP, CPU.read_gpr(i));
}
}
}
virtual void HACK(const u32 data, const ARMv7_encoding type);
void POP(u16 regs_list)
{
for(u16 mask=(0x1 << 15), i=15; mask; mask >>= 1, i--)
{
if(regs_list & mask)
{
CPU.write_gpr(i, vm::psv::read32(CPU.SP));
CPU.SP += 4;
}
}
}
virtual void ADC_IMM(const u32 data, const ARMv7_encoding type);
virtual void ADC_REG(const u32 data, const ARMv7_encoding type);
virtual void ADC_RSR(const u32 data, const ARMv7_encoding type);
void B(u8 cond, u32 imm, u8 intstr_size)
{
if(ConditionPassed(cond))
{
CPU.SetBranch(CPU.PC + intstr_size + imm);
}
}
virtual void ADD_IMM(const u32 data, const ARMv7_encoding type);
virtual void ADD_REG(const u32 data, const ARMv7_encoding type);
virtual void ADD_RSR(const u32 data, const ARMv7_encoding type);
virtual void ADD_SPI(const u32 data, const ARMv7_encoding type);
virtual void ADD_SPR(const u32 data, const ARMv7_encoding type);
void CBZ(u8 op, u32 imm, u8 rn, u8 intstr_size)
{
if((CPU.GPR[rn] == 0) ^ op)
{
CPU.SetBranch(CPU.PC + intstr_size + imm);
}
}
virtual void ADR(const u32 data, const ARMv7_encoding type);
void BL(u32 imm, u8 intstr_size)
{
CPU.LR = (CPU.PC + intstr_size) | 1;
CPU.SetBranch(CPU.PC + intstr_size + imm);
}
virtual void AND_IMM(const u32 data, const ARMv7_encoding type);
virtual void AND_REG(const u32 data, const ARMv7_encoding type);
virtual void AND_RSR(const u32 data, const ARMv7_encoding type);
void UNK(const u16 code0, const u16 code1)
{
LOG_ERROR(HLE, "Unknown/Illegal opcode! (0x%04x : 0x%04x)", code0, code1);
Emu.Pause();
}
virtual void ASR_IMM(const u32 data, const ARMv7_encoding type);
virtual void ASR_REG(const u32 data, const ARMv7_encoding type);
virtual void B(const u32 data, const ARMv7_encoding type);
virtual void BFC(const u32 data, const ARMv7_encoding type);
virtual void BFI(const u32 data, const ARMv7_encoding type);
virtual void BIC_IMM(const u32 data, const ARMv7_encoding type);
virtual void BIC_REG(const u32 data, const ARMv7_encoding type);
virtual void BIC_RSR(const u32 data, const ARMv7_encoding type);
virtual void BKPT(const u32 data, const ARMv7_encoding type);
virtual void BL(const u32 data, const ARMv7_encoding type);
virtual void BLX(const u32 data, const ARMv7_encoding type);
virtual void BX(const u32 data, const ARMv7_encoding type);
virtual void CB_Z(const u32 data, const ARMv7_encoding type);
virtual void CLZ(const u32 data, const ARMv7_encoding type);
virtual void CMN_IMM(const u32 data, const ARMv7_encoding type);
virtual void CMN_REG(const u32 data, const ARMv7_encoding type);
virtual void CMN_RSR(const u32 data, const ARMv7_encoding type);
virtual void CMP_IMM(const u32 data, const ARMv7_encoding type);
virtual void CMP_REG(const u32 data, const ARMv7_encoding type);
virtual void CMP_RSR(const u32 data, const ARMv7_encoding type);
virtual void EOR_IMM(const u32 data, const ARMv7_encoding type);
virtual void EOR_REG(const u32 data, const ARMv7_encoding type);
virtual void EOR_RSR(const u32 data, const ARMv7_encoding type);
virtual void IT(const u32 data, const ARMv7_encoding type);
virtual void LDM(const u32 data, const ARMv7_encoding type);
virtual void LDMDA(const u32 data, const ARMv7_encoding type);
virtual void LDMDB(const u32 data, const ARMv7_encoding type);
virtual void LDMIB(const u32 data, const ARMv7_encoding type);
virtual void LDR_IMM(const u32 data, const ARMv7_encoding type);
virtual void LDR_LIT(const u32 data, const ARMv7_encoding type);
virtual void LDR_REG(const u32 data, const ARMv7_encoding type);
virtual void LDRB_IMM(const u32 data, const ARMv7_encoding type);
virtual void LDRB_LIT(const u32 data, const ARMv7_encoding type);
virtual void LDRB_REG(const u32 data, const ARMv7_encoding type);
virtual void LDRD_IMM(const u32 data, const ARMv7_encoding type);
virtual void LDRD_LIT(const u32 data, const ARMv7_encoding type);
virtual void LDRD_REG(const u32 data, const ARMv7_encoding type);
virtual void LDRH_IMM(const u32 data, const ARMv7_encoding type);
virtual void LDRH_LIT(const u32 data, const ARMv7_encoding type);
virtual void LDRH_REG(const u32 data, const ARMv7_encoding type);
virtual void LDRSB_IMM(const u32 data, const ARMv7_encoding type);
virtual void LDRSB_LIT(const u32 data, const ARMv7_encoding type);
virtual void LDRSB_REG(const u32 data, const ARMv7_encoding type);
virtual void LDRSH_IMM(const u32 data, const ARMv7_encoding type);
virtual void LDRSH_LIT(const u32 data, const ARMv7_encoding type);
virtual void LDRSH_REG(const u32 data, const ARMv7_encoding type);
virtual void LSL_IMM(const u32 data, const ARMv7_encoding type);
virtual void LSL_REG(const u32 data, const ARMv7_encoding type);
virtual void LSR_IMM(const u32 data, const ARMv7_encoding type);
virtual void LSR_REG(const u32 data, const ARMv7_encoding type);
virtual void MLA(const u32 data, const ARMv7_encoding type);
virtual void MLS(const u32 data, const ARMv7_encoding type);
virtual void MOV_IMM(const u32 data, const ARMv7_encoding type);
virtual void MOV_REG(const u32 data, const ARMv7_encoding type);
virtual void MOVT(const u32 data, const ARMv7_encoding type);
virtual void MRS(const u32 data, const ARMv7_encoding type);
virtual void MSR_IMM(const u32 data, const ARMv7_encoding type);
virtual void MSR_REG(const u32 data, const ARMv7_encoding type);
virtual void MUL(const u32 data, const ARMv7_encoding type);
virtual void MVN_IMM(const u32 data, const ARMv7_encoding type);
virtual void MVN_REG(const u32 data, const ARMv7_encoding type);
virtual void MVN_RSR(const u32 data, const ARMv7_encoding type);
virtual void NOP(const u32 data, const ARMv7_encoding type);
virtual void ORN_IMM(const u32 data, const ARMv7_encoding type);
virtual void ORN_REG(const u32 data, const ARMv7_encoding type);
virtual void ORR_IMM(const u32 data, const ARMv7_encoding type);
virtual void ORR_REG(const u32 data, const ARMv7_encoding type);
virtual void ORR_RSR(const u32 data, const ARMv7_encoding type);
virtual void PKH(const u32 data, const ARMv7_encoding type);
virtual void POP(const u32 data, const ARMv7_encoding type);
virtual void PUSH(const u32 data, const ARMv7_encoding type);
virtual void QADD(const u32 data, const ARMv7_encoding type);
virtual void QADD16(const u32 data, const ARMv7_encoding type);
virtual void QADD8(const u32 data, const ARMv7_encoding type);
virtual void QASX(const u32 data, const ARMv7_encoding type);
virtual void QDADD(const u32 data, const ARMv7_encoding type);
virtual void QDSUB(const u32 data, const ARMv7_encoding type);
virtual void QSAX(const u32 data, const ARMv7_encoding type);
virtual void QSUB(const u32 data, const ARMv7_encoding type);
virtual void QSUB16(const u32 data, const ARMv7_encoding type);
virtual void QSUB8(const u32 data, const ARMv7_encoding type);
virtual void RBIT(const u32 data, const ARMv7_encoding type);
virtual void REV(const u32 data, const ARMv7_encoding type);
virtual void REV16(const u32 data, const ARMv7_encoding type);
virtual void REVSH(const u32 data, const ARMv7_encoding type);
virtual void ROR_IMM(const u32 data, const ARMv7_encoding type);
virtual void ROR_REG(const u32 data, const ARMv7_encoding type);
virtual void RRX(const u32 data, const ARMv7_encoding type);
virtual void RSB_IMM(const u32 data, const ARMv7_encoding type);
virtual void RSB_REG(const u32 data, const ARMv7_encoding type);
virtual void RSB_RSR(const u32 data, const ARMv7_encoding type);
virtual void RSC_IMM(const u32 data, const ARMv7_encoding type);
virtual void RSC_REG(const u32 data, const ARMv7_encoding type);
virtual void RSC_RSR(const u32 data, const ARMv7_encoding type);
virtual void SADD16(const u32 data, const ARMv7_encoding type);
virtual void SADD8(const u32 data, const ARMv7_encoding type);
virtual void SASX(const u32 data, const ARMv7_encoding type);
virtual void SBC_IMM(const u32 data, const ARMv7_encoding type);
virtual void SBC_REG(const u32 data, const ARMv7_encoding type);
virtual void SBC_RSR(const u32 data, const ARMv7_encoding type);
virtual void SBFX(const u32 data, const ARMv7_encoding type);
virtual void SDIV(const u32 data, const ARMv7_encoding type);
virtual void SEL(const u32 data, const ARMv7_encoding type);
virtual void SHADD16(const u32 data, const ARMv7_encoding type);
virtual void SHADD8(const u32 data, const ARMv7_encoding type);
virtual void SHASX(const u32 data, const ARMv7_encoding type);
virtual void SHSAX(const u32 data, const ARMv7_encoding type);
virtual void SHSUB16(const u32 data, const ARMv7_encoding type);
virtual void SHSUB8(const u32 data, const ARMv7_encoding type);
virtual void SMLA__(const u32 data, const ARMv7_encoding type);
virtual void SMLAD(const u32 data, const ARMv7_encoding type);
virtual void SMLAL(const u32 data, const ARMv7_encoding type);
virtual void SMLAL__(const u32 data, const ARMv7_encoding type);
virtual void SMLALD(const u32 data, const ARMv7_encoding type);
virtual void SMLAW_(const u32 data, const ARMv7_encoding type);
virtual void SMLSD(const u32 data, const ARMv7_encoding type);
virtual void SMLSLD(const u32 data, const ARMv7_encoding type);
virtual void SMMLA(const u32 data, const ARMv7_encoding type);
virtual void SMMLS(const u32 data, const ARMv7_encoding type);
virtual void SMMUL(const u32 data, const ARMv7_encoding type);
virtual void SMUAD(const u32 data, const ARMv7_encoding type);
virtual void SMUL__(const u32 data, const ARMv7_encoding type);
virtual void SMULL(const u32 data, const ARMv7_encoding type);
virtual void SMULW_(const u32 data, const ARMv7_encoding type);
virtual void SMUSD(const u32 data, const ARMv7_encoding type);
virtual void SSAT(const u32 data, const ARMv7_encoding type);
virtual void SSAT16(const u32 data, const ARMv7_encoding type);
virtual void SSAX(const u32 data, const ARMv7_encoding type);
virtual void SSUB16(const u32 data, const ARMv7_encoding type);
virtual void SSUB8(const u32 data, const ARMv7_encoding type);
virtual void STM(const u32 data, const ARMv7_encoding type);
virtual void STMDA(const u32 data, const ARMv7_encoding type);
virtual void STMDB(const u32 data, const ARMv7_encoding type);
virtual void STMIB(const u32 data, const ARMv7_encoding type);
virtual void STR_IMM(const u32 data, const ARMv7_encoding type);
virtual void STR_REG(const u32 data, const ARMv7_encoding type);
virtual void STRB_IMM(const u32 data, const ARMv7_encoding type);
virtual void STRB_REG(const u32 data, const ARMv7_encoding type);
virtual void STRD_IMM(const u32 data, const ARMv7_encoding type);
virtual void STRD_REG(const u32 data, const ARMv7_encoding type);
virtual void STRH_IMM(const u32 data, const ARMv7_encoding type);
virtual void STRH_REG(const u32 data, const ARMv7_encoding type);
virtual void SUB_IMM(const u32 data, const ARMv7_encoding type);
virtual void SUB_REG(const u32 data, const ARMv7_encoding type);
virtual void SUB_RSR(const u32 data, const ARMv7_encoding type);
virtual void SUB_SPI(const u32 data, const ARMv7_encoding type);
virtual void SUB_SPR(const u32 data, const ARMv7_encoding type);
virtual void SVC(const u32 data, const ARMv7_encoding type);
virtual void SXTAB(const u32 data, const ARMv7_encoding type);
virtual void SXTAB16(const u32 data, const ARMv7_encoding type);
virtual void SXTAH(const u32 data, const ARMv7_encoding type);
virtual void SXTB(const u32 data, const ARMv7_encoding type);
virtual void SXTB16(const u32 data, const ARMv7_encoding type);
virtual void SXTH(const u32 data, const ARMv7_encoding type);
virtual void TB_(const u32 data, const ARMv7_encoding type);
virtual void TEQ_IMM(const u32 data, const ARMv7_encoding type);
virtual void TEQ_REG(const u32 data, const ARMv7_encoding type);
virtual void TEQ_RSR(const u32 data, const ARMv7_encoding type);
virtual void TST_IMM(const u32 data, const ARMv7_encoding type);
virtual void TST_REG(const u32 data, const ARMv7_encoding type);
virtual void TST_RSR(const u32 data, const ARMv7_encoding type);
virtual void UADD16(const u32 data, const ARMv7_encoding type);
virtual void UADD8(const u32 data, const ARMv7_encoding type);
virtual void UASX(const u32 data, const ARMv7_encoding type);
virtual void UBFX(const u32 data, const ARMv7_encoding type);
virtual void UDIV(const u32 data, const ARMv7_encoding type);
virtual void UHADD16(const u32 data, const ARMv7_encoding type);
virtual void UHADD8(const u32 data, const ARMv7_encoding type);
virtual void UHASX(const u32 data, const ARMv7_encoding type);
virtual void UHSAX(const u32 data, const ARMv7_encoding type);
virtual void UHSUB16(const u32 data, const ARMv7_encoding type);
virtual void UHSUB8(const u32 data, const ARMv7_encoding type);
virtual void UMAAL(const u32 data, const ARMv7_encoding type);
virtual void UMLAL(const u32 data, const ARMv7_encoding type);
virtual void UMULL(const u32 data, const ARMv7_encoding type);
virtual void UQADD16(const u32 data, const ARMv7_encoding type);
virtual void UQADD8(const u32 data, const ARMv7_encoding type);
virtual void UQASX(const u32 data, const ARMv7_encoding type);
virtual void UQSAX(const u32 data, const ARMv7_encoding type);
virtual void UQSUB16(const u32 data, const ARMv7_encoding type);
virtual void UQSUB8(const u32 data, const ARMv7_encoding type);
virtual void USAD8(const u32 data, const ARMv7_encoding type);
virtual void USADA8(const u32 data, const ARMv7_encoding type);
virtual void USAT(const u32 data, const ARMv7_encoding type);
virtual void USAT16(const u32 data, const ARMv7_encoding type);
virtual void USAX(const u32 data, const ARMv7_encoding type);
virtual void USUB16(const u32 data, const ARMv7_encoding type);
virtual void USUB8(const u32 data, const ARMv7_encoding type);
virtual void UXTAB(const u32 data, const ARMv7_encoding type);
virtual void UXTAB16(const u32 data, const ARMv7_encoding type);
virtual void UXTAH(const u32 data, const ARMv7_encoding type);
virtual void UXTB(const u32 data, const ARMv7_encoding type);
virtual void UXTB16(const u32 data, const ARMv7_encoding type);
virtual void UXTH(const u32 data, const ARMv7_encoding type);
};

View File

@ -32,18 +32,686 @@ namespace ARMv7_opcodes
};
}
enum ARMv7_encoding
{
T1,
T2,
T3,
T4,
A1,
A2,
};
class ARMv7Opcodes
{
public:
virtual void NULL_OP() = 0;
virtual void NOP() = 0;
virtual void UNK(const u32 data) = 0;
virtual void PUSH(u16 regs_list) = 0;
virtual void POP(u16 regs_list) = 0;
virtual void NULL_OP(const u32 data, const ARMv7_encoding type) = 0;
virtual void B(u8 cond, u32 imm, u8 intstr_size) = 0;
virtual void CBZ(u8 op, u32 imm, u8 rn, u8 intstr_size) = 0;
virtual void BL(u32 imm, u8 intstr_size)=0;
virtual void HACK(const u32 data, const ARMv7_encoding type) = 0;
virtual void 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 UNK(const u16 code0, const u16 code1) = 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 "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/CPU/CPUThreadManager.h"
#include "ARMv7Thread.h"
#include "ARMv7Decoder.h"
@ -18,6 +19,8 @@ void ARMv7Thread::InitRegs()
memset(GPR, 0, sizeof(GPR[0]) * 15);
APSR.APSR = 0;
IPSR.IPSR = 0;
ISET = Thumb;
ITSTATE.IT = 0;
SP = m_stack_addr + m_stack_size;
}
@ -30,9 +33,9 @@ void ARMv7Thread::InitStack()
}
}
void ARMv7Thread::SetArg(const uint pos, const u64 arg)
u32 ARMv7Thread::GetStackArg(u32 pos)
{
assert(0);
return vm::psv::read32(SP + sizeof(u32) * (pos - 5));
}
std::string ARMv7Thread::RegsToString()
@ -98,3 +101,15 @@ void ARMv7Thread::DoStop()
void ARMv7Thread::DoCode()
{
}
arm7_thread::arm7_thread(u32 entry, const std::string& name, u32 stack_size, u32 prio)
{
thread = &Emu.GetCPU().AddThread(CPU_THREAD_ARMv7);
thread->SetName(name);
thread->SetEntry(entry);
thread->SetStackSize(stack_size ? stack_size : Emu.GetInfo().GetProcParam().primary_stacksize);
thread->SetPrio(prio ? prio : Emu.GetInfo().GetProcParam().primary_prio);
argc = 0;
}

View File

@ -1,6 +1,14 @@
#pragma once
#include "Emu/CPU/CPUThread.h"
enum ARMv7InstructionSet
{
ARM,
Thumb,
Jazelle,
ThumbEE,
};
class ARMv7Thread : public CPUThread
{
public:
@ -38,6 +46,7 @@ public:
};
u32 APSR;
} APSR;
union
@ -49,8 +58,41 @@ public:
};
u32 IPSR;
} IPSR;
ARMv7InstructionSet ISET;
union
{
struct
{
u8 cond : 3;
u8 state : 5;
};
u8 IT;
u32 advance()
{
const u32 res = (state & 0xf) ? (cond << 1 | state >> 4) : 0xe /* true */;
state <<= 1;
if ((state & 0xf) == 0) // if no d
{
IT = 0; // clear ITSTATE
}
return res;
}
operator bool() const
{
return (state & 0xf) != 0;
}
} ITSTATE;
void write_gpr(u32 n, u32 value)
{
assert(n < 16);
@ -61,7 +103,7 @@ public:
}
else
{
SetBranch(value);
SetBranch(value & ~1);
}
}
@ -80,7 +122,7 @@ public:
public:
virtual void InitRegs();
virtual void InitStack();
virtual void SetArg(const uint pos, const u64 arg);
u32 GetStackArg(u32 pos);
public:
virtual std::string RegsToString();
@ -95,4 +137,49 @@ protected:
virtual void DoStop();
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()
{
if (m_args) {

View File

@ -28,6 +28,8 @@ CPUThread::CPUThread(CPUThreadType type)
, m_is_branch(false)
, m_status(Stopped)
, m_last_syscall(0)
, m_trace_enabled(false)
, m_trace_call_stack(true)
{
}
@ -154,7 +156,7 @@ void CPUThread::SetBranch(const u32 pc, bool record_branch)
m_is_branch = true;
nPC = pc;
if(record_branch)
if(m_trace_call_stack && record_branch)
CallStackBranch(pc);
}
@ -298,7 +300,7 @@ void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp)
void CPUThread::Task()
{
if (Ini.HLELogging.GetValue()) LOG_NOTICE(PPU, "%s enter", CPUThread::GetFName().c_str());
if (Ini.HLELogging.GetValue()) LOG_NOTICE(GENERAL, "%s enter", CPUThread::GetFName().c_str());
const std::vector<u64>& bp = Emu.GetBreakPoints();
@ -337,7 +339,7 @@ void CPUThread::Task()
}
Step();
//if (PC - 0x13ED4 < 0x288) trace.push_back(PC);
//if (m_trace_enabled) trace.push_back(PC);
NextPc(m_dec->DecodeMemory(PC + m_offset));
if (status == CPUThread_Step)
@ -373,7 +375,25 @@ void CPUThread::Task()
// TODO: linux version
#endif
for (auto& v : trace) LOG_NOTICE(PPU, "PC = 0x%x", v);
if (trace.size())
{
LOG_NOTICE(GENERAL, "Trace begin (%d elements)", trace.size());
if (Ini.HLELogging.GetValue()) LOG_NOTICE(PPU, "%s leave", CPUThread::GetFName().c_str());
u32 start = trace[0], prev = trace[0] - 4;
for (auto& v : trace) //LOG_NOTICE(GENERAL, "PC = 0x%x", v);
{
if (v - prev != 4)
{
LOG_NOTICE(GENERAL, "Trace: 0x%08x .. 0x%08x", start, prev);
start = v;
}
prev = v;
}
LOG_NOTICE(GENERAL, "Trace end: 0x%08x .. 0x%08x", start, prev);
}
if (Ini.HLELogging.GetValue()) LOG_NOTICE(GENERAL, "%s leave", CPUThread::GetFName().c_str());
}

View File

@ -43,6 +43,8 @@ protected:
CPUDecoder* m_dec;
bool m_trace_call_stack;
public:
virtual void InitRegs()=0;
@ -109,16 +111,19 @@ public:
virtual std::string GetThreadName() const
{
std::string temp = (GetFName() + fmt::Format("[0x%08llx]", PC));
std::string temp = (GetFName() + fmt::Format("[0x%08x]", PC));
return temp;
}
CPUDecoder * GetDecoder() { return m_dec; };
public:
u32 entry;
u32 PC;
u32 nPC;
u64 cycle;
bool m_is_branch;
bool m_trace_enabled;
bool m_is_interrupt;
bool m_has_interrupt;
@ -174,6 +179,8 @@ public:
u32 GetId() const { return m_id; }
CPUThreadType GetType() const { return m_type; }
void SetCallStackTracing(bool trace_call_stack) { m_trace_call_stack = trace_call_stack; }
void Reset();
void Close();
void Run();
@ -221,13 +228,13 @@ public:
m_call_stack.erase((res + 1).base(), m_call_stack.end());
return;
}
//add a new entry otherwise
CallStackItem new_item;
new_item.branch_pc = pc;
new_item.pc = PC;
m_call_stack.push_back(new_item);
}
@ -249,3 +256,42 @@ protected:
};
CPUThread* GetCurrentCPUThread();
class cpu_thread
{
protected:
CPUThread* thread;
public:
u32 get_entry() const
{
return thread->entry;
}
virtual cpu_thread& args(std::initializer_list<std::string> values) = 0;
virtual cpu_thread& run() = 0;
u64 join()
{
if (!joinable())
throw "thread must be joinable for join";
thread->SetJoinable(false);
while (thread->IsRunning())
std::this_thread::sleep_for(std::chrono::milliseconds(1));
return thread->GetExitStatus();
}
bool joinable() const
{
return thread->IsJoinable();
}
u32 get_id() const
{
return thread->GetId();
}
};

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

View File

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

View File

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

View File

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

View File

@ -1037,7 +1037,7 @@ private:
case 0x1: Write("HyperCall"); break;
case 0x2: Write("sc"); break;
case 0x22: Write("HyperCall LV1"); break;
default: Write(fmt::Format("Unknown sc: %x", sc_code));
default: Write(fmt::Format("Unknown sc: 0x%x", sc_code));
}
}
void B(s32 ll, u32 aa, u32 lk)
@ -1600,7 +1600,10 @@ private:
default: DisAsm_IMM_R1("mtspr", spr, rs); break;
}
}
/*0x1d6*///DCBI
void DCBI(u32 ra, u32 rb)
{
DisAsm_R2("dcbi", ra, rb);
}
void NAND(u32 ra, u32 rs, u32 rb, bool rc)
{
DisAsm_R3_RC("nand", ra, rs, rb, rc);

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

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

View File

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

View File

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

View File

@ -9,6 +9,9 @@
#include "Emu/SysCalls/Static.h"
#include "Emu/Cell/PPUDecoder.h"
#include "Emu/Cell/PPUInterpreter.h"
#include "Emu/Cell/PPULLVMRecompiler.h"
//#include "Emu/Cell/PPURecompiler.h"
#include "Emu/CPU/CPUThreadManager.h"
PPUThread& GetCurrentPPUThread()
{
@ -38,11 +41,11 @@ void PPUThread::DoReset()
memset(FPR, 0, sizeof(FPR));
memset(GPR, 0, sizeof(GPR));
memset(SPRG, 0, sizeof(SPRG));
memset(USPRG, 0, sizeof(USPRG));
CR.CR = 0;
LR = 0;
CTR = 0;
USPRG0 = 0;
TB = 0;
XER.XER = 0;
FPSCR.FPSCR = 0;
@ -83,8 +86,10 @@ void PPUThread::InitRegs()
}
*/
GPR[1] = AlignAddr(m_stack_addr + m_stack_size, 0x200) - 0x200;
GPR[1] = align(m_stack_addr + m_stack_size, 0x200) - 0x200;
GPR[2] = rtoc;
//GPR[11] = entry;
//GPR[12] = Emu.GetMallocPageSize();
GPR[13] = Memory.PRXMem.GetStartAddr() + 0x7060;
LR = Emu.GetPPUThreadExit();
@ -103,13 +108,26 @@ void PPUThread::DoRun()
break;
case 1:
case 2:
{
auto ppui = new PPUInterpreter(*this);
m_dec = new PPUDecoder(ppui);
}
break;
case 2:
#ifdef PPU_LLVM_RECOMPILER
SetCallStackTracing(false);
if (!m_dec) {
m_dec = new ppu_recompiler_llvm::ExecutionEngine(*this);
}
#else
LOG_ERROR(PPU, "This image does not include PPU JIT (LLVM)");
Emu.Pause();
#endif
break;
//case 3: m_dec = new PPURecompiler(*this); break;
default:
LOG_ERROR(PPU, "Invalid CPU decoder mode: %d", Ini.CPUDecoderMode.GetValue());
Emu.Pause();
@ -187,7 +205,7 @@ u64 PPUThread::FastCall2(u32 addr, u32 rtoc)
LR = Emu.m_ppu_thr_stop;
SetCurrentNamedThread(this);
Task();
CPUThread::Task();
m_status = old_status;
PC = old_PC;
@ -202,4 +220,72 @@ u64 PPUThread::FastCall2(u32 addr, u32 rtoc)
void PPUThread::FastStop()
{
m_status = Stopped;
}
void PPUThread::Task()
{
if (custom_task)
{
custom_task(*this);
}
else
{
CPUThread::Task();
}
}
ppu_thread::ppu_thread(u32 entry, const std::string& name, u32 stack_size, u32 prio)
{
thread = &Emu.GetCPU().AddThread(CPU_THREAD_PPU);
thread->SetName(name);
thread->SetEntry(entry);
thread->SetStackSize(stack_size ? stack_size : Emu.GetInfo().GetProcParam().primary_stacksize);
thread->SetPrio(prio ? prio : Emu.GetInfo().GetProcParam().primary_prio);
argc = 0;
}
cpu_thread& ppu_thread::args(std::initializer_list<std::string> values)
{
if (!values.size())
return *this;
assert(argc == 0);
envp.set(vm::alloc(align((u32)sizeof(*envp), stack_align), vm::main));
*envp = 0;
argv.set(vm::alloc(sizeof(*argv) * values.size(), vm::main));
for (auto &arg : values)
{
u32 arg_size = align(u32(arg.size() + 1), stack_align);
u32 arg_addr = vm::alloc(arg_size, vm::main);
std::strcpy(vm::get_ptr<char>(arg_addr), arg.c_str());
argv[argc++] = arg_addr;
}
return *this;
}
cpu_thread& ppu_thread::run()
{
thread->Run();
gpr(3, argc);
gpr(4, argv.addr());
gpr(5, envp.addr());
return *this;
}
ppu_thread& ppu_thread::gpr(uint index, u64 value)
{
assert(index < 32);
static_cast<PPUThread*>(thread)->GPR[index] = value;
return *this;
}

View File

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

View File

@ -190,7 +190,7 @@ bool RawSPUThread::Write32(const u64 addr, const u32 value)
void RawSPUThread::InitRegs()
{
dmac.ls_offset = m_offset = (u32)GetStartAddr() + RAW_SPU_LS_OFFSET;
ls_offset = m_offset = (u32)GetStartAddr() + RAW_SPU_LS_OFFSET;
SPUThread::InitRegs();
}

View File

@ -3,7 +3,7 @@
#define UNIMPLEMENTED() UNK(__FUNCTION__)
#define MEM_AND_REG_HASH() \
unsigned char mem_h[20]; sha1(vm::get_ptr<u8>(CPU.dmac.ls_offset), 256*1024, mem_h); \
unsigned char mem_h[20]; sha1(vm::get_ptr<u8>(CPU.ls_offset), 256*1024, mem_h); \
unsigned char reg_h[20]; sha1((const unsigned char*)CPU.GPR, sizeof(CPU.GPR), reg_h); \
LOG_NOTICE(Log::SPU, "Mem hash: 0x%llx, reg hash: 0x%llx", *(u64*)mem_h, *(u64*)reg_h);
@ -251,10 +251,12 @@ private:
}
void BIZ(u32 intr, u32 rt, u32 ra)
{
if (intr)
switch (intr)
{
UNIMPLEMENTED();
return;
case 0: break;
case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
}
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
@ -270,10 +272,12 @@ private:
}
void BINZ(u32 intr, u32 rt, u32 ra)
{
if (intr)
switch (intr)
{
UNIMPLEMENTED();
return;
case 0: break;
case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
}
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
@ -289,10 +293,12 @@ private:
}
void BIHZ(u32 intr, u32 rt, u32 ra)
{
if (intr)
switch (intr)
{
UNIMPLEMENTED();
return;
case 0: break;
case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
}
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
@ -308,10 +314,12 @@ private:
}
void BIHNZ(u32 intr, u32 rt, u32 ra)
{
if (intr)
switch (intr)
{
UNIMPLEMENTED();
return;
case 0: break;
case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
}
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
@ -337,10 +345,12 @@ private:
}
void BI(u32 intr, u32 ra)
{
if (intr)
switch (intr)
{
UNIMPLEMENTED();
return;
case 0: break;
case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
}
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
@ -349,10 +359,12 @@ private:
}
void BISL(u32 intr, u32 rt, u32 ra)
{
if (intr)
switch (intr)
{
UNIMPLEMENTED();
return;
case 0: break;
case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
}
u32 target = branchTarget(CPU.GPR[ra]._u32[3], 0);
@ -432,9 +444,7 @@ private:
}
void LQX(u32 rt, u32 ra, u32 rb)
{
u32 a = CPU.GPR[ra]._u32[3], b = CPU.GPR[rb]._u32[3];
u32 lsa = (a + b) & 0x3fff0;
u32 lsa = (CPU.GPR[ra]._u32[3] + CPU.GPR[rb]._u32[3]) & 0x3fff0;
CPU.GPR[rt] = CPU.ReadLS128(lsa);
}
@ -465,6 +475,12 @@ private:
{
const u32 t = (CPU.GPR[rb]._u32[3] + CPU.GPR[ra]._u32[3]) & 0xF;
if (ra == 1 && (CPU.GPR[ra]._u32[3] & 0xF))
{
LOG_ERROR(SPU, "%s(): SP = 0x%x", __FUNCTION__, CPU.GPR[ra]._u32[3]);
Emu.Pause();
}
CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F;
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
CPU.GPR[rt]._u8[15 - t] = 0x03;
@ -473,6 +489,12 @@ private:
{
const u32 t = (CPU.GPR[rb]._u32[3] + CPU.GPR[ra]._u32[3]) & 0xE;
if (ra == 1 && (CPU.GPR[ra]._u32[3] & 0xF))
{
LOG_ERROR(SPU, "%s(): SP = 0x%x", __FUNCTION__, CPU.GPR[ra]._u32[3]);
Emu.Pause();
}
CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F;
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
CPU.GPR[rt]._u16[7 - (t >> 1)] = 0x0203;
@ -480,6 +502,12 @@ private:
void CWX(u32 rt, u32 ra, u32 rb)
{
const u32 t = (CPU.GPR[ra]._u32[3] + CPU.GPR[rb]._u32[3]) & 0xC;
if (ra == 1 && (CPU.GPR[ra]._u32[3] & 0xF))
{
LOG_ERROR(SPU, "%s(): SP = 0x%x", __FUNCTION__, CPU.GPR[ra]._u32[3]);
Emu.Pause();
}
CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F;
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
@ -489,6 +517,12 @@ private:
{
const u32 t = (CPU.GPR[rb]._u32[3] + CPU.GPR[ra]._u32[3]) & 0x8;
if (ra == 1 && (CPU.GPR[ra]._u32[3] & 0xF))
{
LOG_ERROR(SPU, "%s(): SP = 0x%x", __FUNCTION__, CPU.GPR[ra]._u32[3]);
Emu.Pause();
}
CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F;
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
CPU.GPR[rt]._u64[1 - (t >> 3)] = (u64)0x0001020304050607;
@ -574,6 +608,12 @@ private:
{
const int t = (CPU.GPR[ra]._u32[3] + i7) & 0xF;
if (ra == 1 && (CPU.GPR[ra]._u32[3] & 0xF))
{
LOG_ERROR(SPU, "%s(): SP = 0x%x", __FUNCTION__, CPU.GPR[ra]._u32[3]);
Emu.Pause();
}
CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F;
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
CPU.GPR[rt]._u8[15 - t] = 0x03;
@ -582,6 +622,12 @@ private:
{
const int t = (CPU.GPR[ra]._u32[3] + i7) & 0xE;
if (ra == 1 && (CPU.GPR[ra]._u32[3] & 0xF))
{
LOG_ERROR(SPU, "%s(): SP = 0x%x", __FUNCTION__, CPU.GPR[ra]._u32[3]);
Emu.Pause();
}
CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F;
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
CPU.GPR[rt]._u16[7 - (t >> 1)] = 0x0203;
@ -590,6 +636,12 @@ private:
{
const int t = (CPU.GPR[ra]._u32[3] + i7) & 0xC;
if (ra == 1 && (CPU.GPR[ra]._u32[3] & 0xF))
{
LOG_ERROR(SPU, "%s(): SP = 0x%x", __FUNCTION__, CPU.GPR[ra]._u32[3]);
Emu.Pause();
}
CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F;
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
CPU.GPR[rt]._u32[3 - (t >> 2)] = 0x00010203;
@ -598,6 +650,12 @@ private:
{
const int t = (CPU.GPR[ra]._u32[3] + i7) & 0x8;
if (ra == 1 && (CPU.GPR[ra]._u32[3] & 0xF))
{
LOG_ERROR(SPU, "%s(): SP = 0x%x", __FUNCTION__, CPU.GPR[ra]._u32[3]);
Emu.Pause();
}
CPU.GPR[rt]._u64[0] = (u64)0x18191A1B1C1D1E1F;
CPU.GPR[rt]._u64[1] = (u64)0x1011121314151617;
CPU.GPR[rt]._u64[1 - (t >> 3)] = (u64)0x0001020304050607;
@ -1088,6 +1146,7 @@ private:
for (int i = 0; i < 4; i++)
{
CPU.GPR[rt]._f[i] = (float)CPU.GPR[ra]._u32[i];
u32 exp = ((CPU.GPR[rt]._u32[i] >> 23) & 0xff) - scale;
if (exp > 255) //< 0

View File

@ -9,64 +9,6 @@ using namespace asmjit::host;
#define UNIMPLEMENTED() UNK(__FUNCTION__)
#define mmToU64Ptr(x) ((u64*)(&x))
#define mmToU32Ptr(x) ((u32*)(&x))
#define mmToU16Ptr(x) ((u16*)(&x))
#define mmToU8Ptr(x) ((u8*)(&x))
struct g_imm_table_struct
{
//u16 cntb_table[65536];
__m128i fsmb_table[65536];
__m128i fsmh_table[256];
__m128i fsm_table[16];
__m128i sldq_pshufb[32];
__m128i srdq_pshufb[32];
__m128i rldq_pshufb[16];
g_imm_table_struct()
{
/*static_assert(offsetof(g_imm_table_struct, cntb_table) == 0, "offsetof(cntb_table) != 0");
for (u32 i = 0; i < sizeof(cntb_table) / sizeof(cntb_table[0]); i++)
{
u32 cnt_low = 0, cnt_high = 0;
for (u32 j = 0; j < 8; j++)
{
cnt_low += (i >> j) & 1;
cnt_high += (i >> (j + 8)) & 1;
}
cntb_table[i] = (cnt_high << 8) | cnt_low;
}*/
for (u32 i = 0; i < sizeof(fsm_table) / sizeof(fsm_table[0]); i++)
{
for (u32 j = 0; j < 4; j++) mmToU32Ptr(fsm_table[i])[j] = (i & (1 << j)) ? ~0 : 0;
}
for (u32 i = 0; i < sizeof(fsmh_table) / sizeof(fsmh_table[0]); i++)
{
for (u32 j = 0; j < 8; j++) mmToU16Ptr(fsmh_table[i])[j] = (i & (1 << j)) ? ~0 : 0;
}
for (u32 i = 0; i < sizeof(fsmb_table) / sizeof(fsmb_table[0]); i++)
{
for (u32 j = 0; j < 16; j++) mmToU8Ptr(fsmb_table[i])[j] = (i & (1 << j)) ? ~0 : 0;
}
for (u32 i = 0; i < sizeof(sldq_pshufb) / sizeof(sldq_pshufb[0]); i++)
{
for (u32 j = 0; j < 16; j++) mmToU8Ptr(sldq_pshufb[i])[j] = (u8)(j - i);
}
for (u32 i = 0; i < sizeof(srdq_pshufb) / sizeof(srdq_pshufb[0]); i++)
{
for (u32 j = 0; j < 16; j++) mmToU8Ptr(srdq_pshufb[i])[j] = (j + i > 15) ? 0xff : (u8)(j + i);
}
for (u32 i = 0; i < sizeof(rldq_pshufb) / sizeof(rldq_pshufb[0]); i++)
{
for (u32 j = 0; j < 16; j++) mmToU8Ptr(rldq_pshufb[i])[j] = (u8)(j - i) & 0xf;
}
}
};
class SPURecompiler;
class SPURecompilerCore : public CPUDecoder
@ -78,6 +20,7 @@ public:
SPUInterpreter* inter;
JitRuntime runtime;
bool first;
bool need_check;
struct SPURecEntry
{
@ -457,7 +400,7 @@ private:
c.mov(cpu_dword(PC), CPU.PC);
// This instruction must be used following a store instruction that modifies the instruction stream.
c.mfence();
c.mov(*pos_var, (CPU.PC >> 2) + 1);
c.mov(*pos_var, (CPU.PC >> 2) + 1 + 0x2000000);
do_finalize = true;
LOG_OPCODE();
}
@ -688,7 +631,7 @@ private:
}
LOG_OPCODE();
}
void ROTH(u32 rt, u32 ra, u32 rb)
void ROTH(u32 rt, u32 ra, u32 rb) //nf
{
XmmInvalidate(rt);
for (u32 i = 0; i < 8; i++)
@ -1131,10 +1074,12 @@ private:
}
void BIZ(u32 intr, u32 rt, u32 ra)
{
if (intr)
switch (intr)
{
UNIMPLEMENTED();
return;
case 0: break;
case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
}
c.mov(cpu_dword(PC), CPU.PC);
@ -1142,6 +1087,7 @@ private:
c.mov(*addr, CPU.PC + 4);
c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3]));
if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR)
c.cmp(cpu_dword(GPR[rt]._u32[3]), 0);
c.cmovne(*pos_var, *addr);
c.shr(*pos_var, 2);
@ -1149,10 +1095,12 @@ private:
}
void BINZ(u32 intr, u32 rt, u32 ra)
{
if (intr)
switch (intr)
{
UNIMPLEMENTED();
return;
case 0: break;
case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
}
c.mov(cpu_dword(PC), CPU.PC);
@ -1160,6 +1108,7 @@ private:
c.mov(*addr, CPU.PC + 4);
c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3]));
if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR)
c.cmp(cpu_dword(GPR[rt]._u32[3]), 0);
c.cmove(*pos_var, *addr);
c.shr(*pos_var, 2);
@ -1167,10 +1116,12 @@ private:
}
void BIHZ(u32 intr, u32 rt, u32 ra)
{
if (intr)
switch (intr)
{
UNIMPLEMENTED();
return;
case 0: break;
case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
}
c.mov(cpu_dword(PC), CPU.PC);
@ -1178,6 +1129,7 @@ private:
c.mov(*addr, CPU.PC + 4);
c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3]));
if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR)
c.cmp(cpu_word(GPR[rt]._u16[6]), 0);
c.cmovne(*pos_var, *addr);
c.shr(*pos_var, 2);
@ -1185,10 +1137,12 @@ private:
}
void BIHNZ(u32 intr, u32 rt, u32 ra)
{
if (intr)
switch (intr)
{
UNIMPLEMENTED();
return;
case 0: break;
case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
}
c.mov(cpu_dword(PC), CPU.PC);
@ -1196,6 +1150,7 @@ private:
c.mov(*addr, CPU.PC + 4);
c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3]));
if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR)
c.cmp(cpu_word(GPR[rt]._u16[6]), 0);
c.cmove(*pos_var, *addr);
c.shr(*pos_var, 2);
@ -1234,25 +1189,30 @@ private:
}
void BI(u32 intr, u32 ra)
{
if (intr)
switch (intr)
{
UNIMPLEMENTED();
return;
case 0: break;
case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
}
c.mov(cpu_dword(PC), CPU.PC);
do_finalize = true;
c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3]));
if (ra) c.or_(*pos_var, 0x2000000 << 2); // rude (check if not LR)
c.shr(*pos_var, 2);
LOG_OPCODE();
}
void BISL(u32 intr, u32 rt, u32 ra)
{
if (intr)
switch (intr)
{
UNIMPLEMENTED();
return;
case 0: break;
case 0x10: break; // enable interrupts
case 0x20: break; // disable interrupts
default: UNIMPLEMENTED(); return;
}
XmmInvalidate(rt);
@ -1267,6 +1227,7 @@ private:
c.mov(*pos_var, cpu_dword(GPR[ra]._u32[3]));
c.mov(cpu_dword(GPR[rt]._u32[3]), CPU.PC + 4);
c.shr(*pos_var, 2);
c.or_(*pos_var, 0x2000000);
LOG_OPCODE();
}
void IRET(u32 ra)
@ -1423,18 +1384,21 @@ private:
}
void CBX(u32 rt, u32 ra, u32 rb)
{
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
if (ra == rb)
c.mov(*addr, cpu_dword(GPR[rb]._u32[3]));
if (ra == 1)
{
// assuming that SP % 16 is always zero
}
else if (ra == rb)
{
c.add(*addr, *addr);
}
else
{
c.add(*addr, cpu_dword(GPR[rb]._u32[3]));
c.add(*addr, cpu_dword(GPR[ra]._u32[3]));
}
c.not_(*addr);
c.and_(*addr, 0xf);
c.neg(*addr);
c.add(*addr, 0xf);
const XmmLink& vr = XmmAlloc(rt);
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt);
@ -1444,18 +1408,21 @@ private:
}
void CHX(u32 rt, u32 ra, u32 rb)
{
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
if (ra == rb)
c.mov(*addr, cpu_dword(GPR[rb]._u32[3]));
if (ra == 1)
{
// assuming that SP % 16 is always zero
}
else if (ra == rb)
{
c.add(*addr, *addr);
}
else
{
c.add(*addr, cpu_dword(GPR[rb]._u32[3]));
c.add(*addr, cpu_dword(GPR[ra]._u32[3]));
}
c.not_(*addr);
c.and_(*addr, 0xe);
c.neg(*addr);
c.add(*addr, 0xe);
const XmmLink& vr = XmmAlloc(rt);
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt);
@ -1465,18 +1432,21 @@ private:
}
void CWX(u32 rt, u32 ra, u32 rb)
{
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
if (ra == rb)
c.mov(*addr, cpu_dword(GPR[rb]._u32[3]));
if (ra == 1)
{
// assuming that SP % 16 is always zero
}
else if (ra == rb)
{
c.add(*addr, *addr);
}
else
{
c.add(*addr, cpu_dword(GPR[rb]._u32[3]));
c.add(*addr, cpu_dword(GPR[ra]._u32[3]));
}
c.not_(*addr);
c.and_(*addr, 0xc);
c.neg(*addr);
c.add(*addr, 0xc);
const XmmLink& vr = XmmAlloc(rt);
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt);
@ -1486,18 +1456,21 @@ private:
}
void CDX(u32 rt, u32 ra, u32 rb)
{
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
if (ra == rb)
c.mov(*addr, cpu_dword(GPR[rb]._u32[3]));
if (ra == 1)
{
// assuming that SP % 16 is always zero
}
else if (ra == rb)
{
c.add(*addr, *addr);
}
else
{
c.add(*addr, cpu_dword(GPR[rb]._u32[3]));
c.add(*addr, cpu_dword(GPR[ra]._u32[3]));
}
c.not_(*addr);
c.and_(*addr, 0x8);
c.neg(*addr);
c.add(*addr, 0x8);
const XmmLink& vr = XmmAlloc(rt);
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt);
@ -1594,59 +1567,103 @@ private:
}
void CBD(u32 rt, u32 ra, s32 i7)
{
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
c.add(*addr, i7);
c.and_(*addr, 0xf);
c.neg(*addr);
c.add(*addr, 0xf);
const XmmLink& vr = XmmAlloc(rt);
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt);
XmmInvalidate(rt);
c.mov(byte_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u8[0])), 0x03);
if (ra == 1)
{
// assuming that SP % 16 is always zero
const XmmLink& vr = XmmAlloc(rt);
u128 value = u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f));
value.u8r[i7 & 0xf] = 0x03;
c.movdqa(vr.get(), XmmConst(value.vi));
XmmFinalize(vr, rt);
}
else
{
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
c.add(*addr, i7);
c.not_(*addr);
c.and_(*addr, 0xf);
const XmmLink& vr = XmmAlloc(rt);
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt);
XmmInvalidate(rt);
c.mov(byte_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u8[0])), 0x03);
}
LOG_OPCODE();
}
void CHD(u32 rt, u32 ra, s32 i7)
{
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
c.add(*addr, i7);
c.and_(*addr, 0xe);
c.neg(*addr);
c.add(*addr, 0xe);
const XmmLink& vr = XmmAlloc(rt);
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt);
XmmInvalidate(rt);
c.mov(word_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u16[0])), 0x0203);
if (ra == 1)
{
// assuming that SP % 16 is always zero
const XmmLink& vr = XmmAlloc(rt);
u128 value = u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f));
value.u16r[(i7 >> 1) & 0x7] = 0x0203;
c.movdqa(vr.get(), XmmConst(value.vi));
XmmFinalize(vr, rt);
}
else
{
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
c.add(*addr, i7);
c.not_(*addr);
c.and_(*addr, 0xe);
const XmmLink& vr = XmmAlloc(rt);
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt);
XmmInvalidate(rt);
c.mov(word_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u16[0])), 0x0203);
}
LOG_OPCODE();
}
void CWD(u32 rt, u32 ra, s32 i7)
{
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
c.add(*addr, i7);
c.and_(*addr, 0xc);
c.neg(*addr);
c.add(*addr, 0xc);
const XmmLink& vr = XmmAlloc(rt);
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt);
XmmInvalidate(rt);
c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[0])), 0x00010203);
if (ra == 1)
{
// assuming that SP % 16 is always zero
const XmmLink& vr = XmmAlloc(rt);
u128 value = u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f));
value.u32r[(i7 >> 2) & 0x3] = 0x00010203;
c.movdqa(vr.get(), XmmConst(value.vi));
XmmFinalize(vr, rt);
}
else
{
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
c.add(*addr, i7);
c.not_(*addr);
c.and_(*addr, 0xc);
const XmmLink& vr = XmmAlloc(rt);
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt);
XmmInvalidate(rt);
c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[0])), 0x00010203);
}
LOG_OPCODE();
}
void CDD(u32 rt, u32 ra, s32 i7)
{
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
c.add(*addr, i7);
c.and_(*addr, 0x8);
c.neg(*addr);
c.add(*addr, 0x8);
const XmmLink& vr = XmmAlloc(rt);
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt);
XmmInvalidate(rt);
c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[0])), 0x04050607);
c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[1])), 0x00010203);
if (ra == 1)
{
// assuming that SP % 16 is always zero
const XmmLink& vr = XmmAlloc(rt);
u128 value = u128::fromV(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f));
value.u64r[(i7 >> 3) & 0x1] = 0x0001020304050607ull;
c.movdqa(vr.get(), XmmConst(value.vi));
XmmFinalize(vr, rt);
}
else
{
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
c.add(*addr, i7);
c.not_(*addr);
c.and_(*addr, 0x8);
const XmmLink& vr = XmmAlloc(rt);
c.movdqa(vr.get(), XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
XmmFinalize(vr, rt);
XmmInvalidate(rt);
c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[0])), 0x04050607);
c.mov(dword_ptr(*cpu_var, *addr, 0, (s32)offsetof(SPUThread, GPR[rt]._u32[1])), 0x00010203);
}
LOG_OPCODE();
}
void ROTQBII(u32 rt, u32 ra, s32 i7)
@ -1947,23 +1964,22 @@ private:
{
c.mov(*addr, cpu_dword(GPR[ra]._s32[3]));
c.cmp(*addr, cpu_dword(GPR[rb]._s32[3]));
c.mov(*addr, 0);
c.setg(addr->r8());
c.neg(*addr);
c.shl(*addr, 24);
c.mov(*pos_var, (CPU.PC >> 2) + 1);
c.xor_(*pos_var, *addr);
c.or_(*pos_var, *addr);
do_finalize = true;
LOG_OPCODE();
}
void CLZ(u32 rt, u32 ra)
{
XmmInvalidate(rt);
c.mov(*qw0, 32 + 31);
for (u32 i = 0; i < 4; i++)
{
c.bsr(*addr, cpu_dword(GPR[ra]._u32[i]));
c.cmovz(*addr, dword_ptr(*g_imm_var, (s32)offsetof(g_imm_table_struct, fsmb_table[0xffff]))); // load 0xffffffff
c.neg(*addr);
c.add(*addr, 31);
c.cmovz(*addr, qw0->r32());
c.xor_(*addr, 31);
c.mov(cpu_dword(GPR[rt]._u32[i]), *addr);
}
LOG_OPCODE();
@ -2308,11 +2324,10 @@ private:
{
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
c.cmp(*addr, cpu_dword(GPR[rb]._u32[3]));
c.mov(*addr, 0);
c.seta(addr->r8());
c.neg(*addr);
c.shl(*addr, 24);
c.mov(*pos_var, (CPU.PC >> 2) + 1);
c.xor_(*pos_var, *addr);
c.or_(*pos_var, *addr);
do_finalize = true;
LOG_OPCODE();
}
@ -2662,11 +2677,10 @@ private:
{
c.mov(*addr, cpu_dword(GPR[ra]._s32[3]));
c.cmp(*addr, cpu_dword(GPR[rb]._s32[3]));
c.mov(*addr, 0);
c.sete(addr->r8());
c.neg(*addr);
c.shl(*addr, 24);
c.mov(*pos_var, (CPU.PC >> 2) + 1);
c.xor_(*pos_var, *addr);
c.or_(*pos_var, *addr);
do_finalize = true;
LOG_OPCODE();
}
@ -3324,11 +3338,10 @@ private:
{
c.mov(*addr, cpu_dword(GPR[ra]._s32[3]));
c.cmp(*addr, i10);
c.mov(*addr, 0);
c.setg(addr->r8());
c.neg(*addr);
c.shl(*addr, 24);
c.mov(*pos_var, (CPU.PC >> 2) + 1);
c.xor_(*pos_var, *addr);
c.or_(*pos_var, *addr);
do_finalize = true;
LOG_OPCODE();
}
@ -3390,11 +3403,10 @@ private:
{
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
c.cmp(*addr, i10);
c.mov(*addr, 0);
c.seta(addr->r8());
c.neg(*addr);
c.shl(*addr, 24);
c.mov(*pos_var, (CPU.PC >> 2) + 1);
c.xor_(*pos_var, *addr);
c.or_(*pos_var, *addr);
do_finalize = true;
LOG_OPCODE();
}
@ -3441,11 +3453,10 @@ private:
{
c.mov(*addr, cpu_dword(GPR[ra]._u32[3]));
c.cmp(*addr, i10);
c.mov(*addr, 0);
c.sete(addr->r8());
c.neg(*addr);
c.shl(*addr, 24);
c.mov(*pos_var, (CPU.PC >> 2) + 1);
c.xor_(*pos_var, *addr);
c.or_(*pos_var, *addr);
do_finalize = true;
LOG_OPCODE();
}
@ -3517,6 +3528,16 @@ private:
}
WRAPPER_END(rc, rt, ra, rb);*/
// hypothetical AVX-512 implementation:
// VPXORD mask, rc, [byte:0x0f] // 15 - rc (only for index bits)
// VPSHUFB res {k0}, ra, mask
// VPTESTMB k1 {k0}, rc, [byte:0x10]
// VPSHUFB res {k1}, rb, mask
// VPCMPNLTUB k1 {k0}, mask, [byte:0xc0]
// VPADDB res {k1}, res, [byte:0xff]
// VPCMPNLTUB k1 {k1}, mask, [byte:0xe0]
// VPSUBB res {k1}, res, [byte:0x7f]
const XmmLink& v0 = XmmGet(rc); // v0 = mask
const XmmLink& v1 = XmmAlloc();
const XmmLink& v2 = XmmCopy(v0); // v2 = mask

View File

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

View File

@ -50,7 +50,15 @@ void SPUThread::Task()
const int round = std::fegetround();
std::fesetround(FE_TOWARDZERO);
CPUThread::Task();
if (m_custom_task)
{
m_custom_task(*this);
}
else
{
CPUThread::Task();
}
if (std::fegetround() != FE_TOWARDZERO)
{
LOG_ERROR(Log::SPU, "Rounding mode has changed(%d)", std::fegetround());
@ -68,11 +76,11 @@ void SPUThread::DoReset()
void SPUThread::InitRegs()
{
GPR[1]._u32[3] = 0x40000 - 120;
GPR[1]._u32[3] = 0x3FFF0; // initial stack frame pointer
cfg.Reset();
dmac.ls_offset = m_offset;
ls_offset = m_offset;
SPU.Status.SetValue(SPU_STATUS_STOPPED);
@ -138,6 +146,31 @@ void SPUThread::DoClose()
}
}
void SPUThread::FastCall(u32 ls_addr)
{
// can't be called from another thread (because it doesn't make sense)
WriteLS32(0x0, 2);
auto old_PC = PC;
auto old_LR = GPR[0]._u32[3];
auto old_stack = GPR[1]._u32[3]; // only saved and restored (may be wrong)
m_status = Running;
PC = ls_addr;
GPR[0]._u32[3] = 0x0;
CPUThread::Task();
PC = old_PC;
GPR[0]._u32[3] = old_LR;
GPR[1]._u32[3] = old_stack;
}
void SPUThread::FastStop()
{
m_status = Stopped;
}
void SPUThread::WriteSNR(bool number, u32 value)
{
if (cfg.value & ((u64)1 << (u64)number))
@ -181,11 +214,11 @@ void SPUThread::ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
if ((addr <= 0x3ffff) && (addr + size <= 0x40000))
{
// LS access
ea = spu->dmac.ls_offset + addr;
ea = spu->ls_offset + addr;
}
else if ((cmd & MFC_PUT_CMD) && size == 4 && (addr == SYS_SPU_THREAD_SNR1 || addr == SYS_SPU_THREAD_SNR2))
{
spu->WriteSNR(SYS_SPU_THREAD_SNR2 == addr, vm::read32(dmac.ls_offset + lsa));
spu->WriteSNR(SYS_SPU_THREAD_SNR2 == addr, vm::read32(ls_offset + lsa));
return;
}
else
@ -208,13 +241,13 @@ void SPUThread::ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
{
case MFC_PUT_CMD:
{
vm::write32(ea, ReadLS32(lsa));
vm::write32((u32)ea, ReadLS32(lsa));
return;
}
case MFC_GET_CMD:
{
WriteLS32(lsa, vm::read32(ea));
WriteLS32(lsa, vm::read32((u32)ea));
return;
}
@ -231,13 +264,13 @@ void SPUThread::ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size)
{
case MFC_PUT_CMD:
{
memcpy(vm::get_ptr<void>(ea), vm::get_ptr<void>(dmac.ls_offset + lsa), size);
memcpy(vm::get_ptr<void>((u32)ea), vm::get_ptr<void>(ls_offset + lsa), size);
return;
}
case MFC_GET_CMD:
{
memcpy(vm::get_ptr<void>(dmac.ls_offset + lsa), vm::get_ptr<void>(ea), size);
memcpy(vm::get_ptr<void>(ls_offset + lsa), vm::get_ptr<void>((u32)ea), size);
return;
}
@ -269,10 +302,10 @@ void SPUThread::ListCmd(u32 lsa, u64 ea, u16 tag, u16 size, u32 cmd, MFCReg& MFC
for (u32 i = 0; i < list_size; i++)
{
auto rec = vm::ptr<list_element>::make(dmac.ls_offset + list_addr + i * 8);
auto rec = vm::ptr<list_element>::make(ls_offset + list_addr + i * 8);
u32 size = rec->ts;
if (size < 16 && size != 1 && size != 2 && size != 4 && size != 8)
if (!(rec->s.ToBE() & se16(0x8000)) && size < 16 && size != 1 && size != 2 && size != 4 && size != 8)
{
LOG_ERROR(Log::SPU, "DMA List: invalid transfer size(%d)", size);
result = MFC_PPU_DMA_CMD_SEQUENCE_ERROR;
@ -280,13 +313,16 @@ void SPUThread::ListCmd(u32 lsa, u64 ea, u16 tag, u16 size, u32 cmd, MFCReg& MFC
}
u32 addr = rec->ea;
ProcessCmd(cmd, tag, lsa | (addr & 0xf), addr, size);
if (Ini.HLELogging.GetValue() || rec->s)
if (size)
ProcessCmd(cmd, tag, lsa | (addr & 0xf), addr, size);
if (Ini.HLELogging.GetValue() || rec->s.ToBE())
LOG_NOTICE(Log::SPU, "*** list element(%d/%d): s = 0x%x, ts = 0x%x, low ea = 0x%x (lsa = 0x%x)",
i, list_size, (u16)rec->s, (u16)rec->ts, (u32)rec->ea, lsa | (addr & 0xf));
lsa += std::max(size, (u32)16);
if (size)
lsa += std::max(size, (u32)16);
if (rec->s.ToBE() & se16(0x8000))
{
@ -366,6 +402,17 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
op == MFC_PUTLLUC_CMD ? "PUTLLUC" : "PUTQLLUC"),
lsa, ea, tag, size, cmd);
if ((u32)ea != ea)
{
LOG_ERROR(Log::SPU, "DMA %s: Invalid external address (0x%llx)",
(op == MFC_GETLLAR_CMD ? "GETLLAR" :
op == MFC_PUTLLC_CMD ? "PUTLLC" :
op == MFC_PUTLLUC_CMD ? "PUTLLUC" : "PUTQLLUC"),
ea);
Emu.Pause();
return;
}
if (op == MFC_GETLLAR_CMD) // get reservation
{
if (R_ADDR)
@ -376,8 +423,8 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
R_ADDR = ea;
for (u32 i = 0; i < 16; i++)
{
R_DATA[i] = vm::get_ptr<u64>(R_ADDR)[i];
vm::get_ptr<u64>(dmac.ls_offset + lsa)[i] = R_DATA[i];
R_DATA[i] = vm::get_ptr<u64>((u32)R_ADDR)[i];
vm::get_ptr<u64>(ls_offset + lsa)[i] = R_DATA[i];
}
MFCArgs.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS);
}
@ -391,12 +438,12 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
u64 buf[16];
for (u32 i = 0; i < 16; i++)
{
buf[i] = vm::get_ptr<u64>(dmac.ls_offset + lsa)[i];
buf[i] = vm::get_ptr<u64>(ls_offset + lsa)[i];
if (buf[i] != R_DATA[i])
{
changed++;
mask |= (0x3 << (i * 2));
if (vm::get_ptr<u64>(R_ADDR)[i] != R_DATA[i])
if (vm::get_ptr<u64>((u32)R_ADDR)[i] != R_DATA[i])
{
m_events |= SPU_EVENT_LR;
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE);
@ -410,7 +457,7 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
{
if (buf[i] != R_DATA[i])
{
if (InterlockedCompareExchange(&vm::get_ptr<volatile u64>(ea)[i], buf[i], R_DATA[i]) != R_DATA[i])
if (InterlockedCompareExchange(&vm::get_ptr<volatile u64>((u32)R_ADDR)[i], buf[i], R_DATA[i]) != R_DATA[i])
{
m_events |= SPU_EVENT_LR;
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE);
@ -436,8 +483,8 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
for (s32 i = (s32)PC; i < (s32)PC + 4 * 7; i += 4)
{
dis_asm.dump_pc = i;
dis_asm.offset = vm::get_ptr<u8>(dmac.ls_offset);
const u32 opcode = vm::read32(i + dmac.ls_offset);
dis_asm.offset = vm::get_ptr<u8>(ls_offset);
const u32 opcode = vm::read32(i + ls_offset);
(*SPU_instr::rrr_list)(&dis_asm, opcode);
if (i >= 0 && i < 0x40000)
{
@ -454,7 +501,7 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
}
else // store unconditional
{
if (R_ADDR)
if (R_ADDR) // may be wrong
{
m_events |= SPU_EVENT_LR;
}
@ -484,7 +531,7 @@ bool SPUThread::CheckEvents()
{
for (u32 i = 0; i < 16; i++)
{
if (vm::get_ptr<u64>(R_ADDR)[i] != R_DATA[i])
if (vm::get_ptr<u64>((u32)R_ADDR)[i] != R_DATA[i])
{
m_events |= SPU_EVENT_LR;
R_ADDR = 0;
@ -498,18 +545,20 @@ bool SPUThread::CheckEvents()
u32 SPUThread::GetChannelCount(u32 ch)
{
u32 res = 0xdeafbeef;
switch (ch)
{
case SPU_WrOutMbox: return SPU.Out_MBox.GetFreeCount();
case SPU_WrOutIntrMbox: return SPU.Out_IntrMBox.GetFreeCount();
case SPU_RdInMbox: return SPU.In_MBox.GetCount();
case MFC_RdTagStat: return MFC1.TagStatus.GetCount();
case MFC_RdListStallStat: return StallStat.GetCount();
case MFC_WrTagUpdate: return MFC1.TagStatus.GetCount(); // hack
case SPU_RdSigNotify1: return SPU.SNR[0].GetCount();
case SPU_RdSigNotify2: return SPU.SNR[1].GetCount();
case MFC_RdAtomicStat: return MFC1.AtomicStat.GetCount();
case SPU_RdEventStat: return CheckEvents() ? 1 : 0;
case SPU_WrOutMbox: res = SPU.Out_MBox.GetFreeCount(); break;
case SPU_WrOutIntrMbox: res = SPU.Out_IntrMBox.GetFreeCount(); break;
case SPU_RdInMbox: res = SPU.In_MBox.GetCount(); break;
case MFC_RdTagStat: res = MFC1.TagStatus.GetCount(); break;
case MFC_RdListStallStat: res = StallStat.GetCount(); break;
case MFC_WrTagUpdate: res = MFC1.TagStatus.GetCount(); break;// hack
case SPU_RdSigNotify1: res = SPU.SNR[0].GetCount(); break;
case SPU_RdSigNotify2: res = SPU.SNR[1].GetCount(); break;
case MFC_RdAtomicStat: res = MFC1.AtomicStat.GetCount(); break;
case SPU_RdEventStat: res = CheckEvents() ? 1 : 0; break;
default:
{
@ -518,12 +567,17 @@ u32 SPUThread::GetChannelCount(u32 ch)
return 0;
}
}
//LOG_NOTICE(Log::SPU, "%s(%s) -> 0x%x", __FUNCTION__, spu_ch_name[ch], res);
return res;
}
void SPUThread::WriteChannel(u32 ch, const u128& r)
{
const u32 v = r._u32[3];
//LOG_NOTICE(Log::SPU, "%s(%s): v=0x%x", __FUNCTION__, spu_ch_name[ch], v);
switch (ch)
{
case SPU_WrOutIntrMbox:
@ -880,13 +934,27 @@ void SPUThread::ReadChannel(u128& r, u32 ch)
case SPU_RdSigNotify1:
{
while (!SPU.SNR[0].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
if (cfg.value & 1)
{
while (!SPU.SNR[0].Pop_XCHG(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
else
{
while (!SPU.SNR[0].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
break;
}
case SPU_RdSigNotify2:
{
while (!SPU.SNR[1].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
if (cfg.value & 2)
{
while (!SPU.SNR[1].Pop_XCHG(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
else
{
while (!SPU.SNR[1].Pop(v) && !Emu.IsStopped()) std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
break;
}
@ -936,6 +1004,8 @@ void SPUThread::ReadChannel(u128& r, u32 ch)
}
if (Emu.IsStopped()) LOG_WARNING(Log::SPU, "%s(%s) aborted", __FUNCTION__, spu_ch_name[ch]);
//LOG_NOTICE(Log::SPU, "%s(%s) -> 0x%x", __FUNCTION__, spu_ch_name[ch], v);
}
void SPUThread::StopAndSignal(u32 code)
@ -945,6 +1015,24 @@ void SPUThread::StopAndSignal(u32 code)
switch (code)
{
case 0x001:
{
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
break;
}
case 0x002:
{
FastStop();
break;
}
case 0x003:
{
GPR[3]._u64[1] = m_code3_func(*this);
break;
}
case 0x110:
{
/* ===== sys_spu_thread_receive_event ===== */
@ -1075,7 +1163,6 @@ void SPUThread::StopAndSignal(u32 code)
}
default:
{
if (!SPU.Out_MBox.GetCount())
{
LOG_ERROR(Log::SPU, "Unknown STOP code: 0x%x (no message)", code);
@ -1084,8 +1171,19 @@ void SPUThread::StopAndSignal(u32 code)
{
LOG_ERROR(Log::SPU, "Unknown STOP code: 0x%x (message=0x%x)", code, SPU.Out_MBox.GetValue());
}
Stop();
Emu.Pause();
break;
}
}
}
spu_thread::spu_thread(u32 entry, const std::string& name, u32 stack_size, u32 prio)
{
thread = &Emu.GetCPU().AddThread(CPU_THREAD_SPU);
thread->SetName(name);
thread->SetEntry(entry);
thread->SetStackSize(stack_size ? stack_size : Emu.GetInfo().GetProcParam().primary_stacksize);
thread->SetPrio(prio ? prio : Emu.GetInfo().GetProcParam().primary_prio);
argc = 0;
}

View File

@ -1,4 +1,5 @@
#pragma once
#include "Emu/Memory/atomic_type.h"
#include "PPCThread.h"
#include "Emu/Event.h"
#include "MFC.h"
@ -104,6 +105,66 @@ enum
SPU_RdSigNotify2_offs = 0x1C00C,
};
#define mmToU64Ptr(x) ((u64*)(&x))
#define mmToU32Ptr(x) ((u32*)(&x))
#define mmToU16Ptr(x) ((u16*)(&x))
#define mmToU8Ptr(x) ((u8*)(&x))
struct g_imm_table_struct
{
//u16 cntb_table[65536];
__m128i fsmb_table[65536];
__m128i fsmh_table[256];
__m128i fsm_table[16];
__m128i sldq_pshufb[32];
__m128i srdq_pshufb[32];
__m128i rldq_pshufb[16];
g_imm_table_struct()
{
/*static_assert(offsetof(g_imm_table_struct, cntb_table) == 0, "offsetof(cntb_table) != 0");
for (u32 i = 0; i < sizeof(cntb_table) / sizeof(cntb_table[0]); i++)
{
u32 cnt_low = 0, cnt_high = 0;
for (u32 j = 0; j < 8; j++)
{
cnt_low += (i >> j) & 1;
cnt_high += (i >> (j + 8)) & 1;
}
cntb_table[i] = (cnt_high << 8) | cnt_low;
}*/
for (u32 i = 0; i < sizeof(fsm_table) / sizeof(fsm_table[0]); i++)
{
for (u32 j = 0; j < 4; j++) mmToU32Ptr(fsm_table[i])[j] = (i & (1 << j)) ? ~0 : 0;
}
for (u32 i = 0; i < sizeof(fsmh_table) / sizeof(fsmh_table[0]); i++)
{
for (u32 j = 0; j < 8; j++) mmToU16Ptr(fsmh_table[i])[j] = (i & (1 << j)) ? ~0 : 0;
}
for (u32 i = 0; i < sizeof(fsmb_table) / sizeof(fsmb_table[0]); i++)
{
for (u32 j = 0; j < 16; j++) mmToU8Ptr(fsmb_table[i])[j] = (i & (1 << j)) ? ~0 : 0;
}
for (u32 i = 0; i < sizeof(sldq_pshufb) / sizeof(sldq_pshufb[0]); i++)
{
for (u32 j = 0; j < 16; j++) mmToU8Ptr(sldq_pshufb[i])[j] = (u8)(j - i);
}
for (u32 i = 0; i < sizeof(srdq_pshufb) / sizeof(srdq_pshufb[0]); i++)
{
for (u32 j = 0; j < 16; j++) mmToU8Ptr(srdq_pshufb[i])[j] = (j + i > 15) ? 0xff : (u8)(j + i);
}
for (u32 i = 0; i < sizeof(rldq_pshufb) / sizeof(rldq_pshufb[0]); i++)
{
for (u32 j = 0; j < 16; j++) mmToU8Ptr(rldq_pshufb[i])[j] = (u8)(j - i) & 0xf;
}
}
};
extern const g_imm_table_struct g_imm_table;
//Floating point status and control register. Unsure if this is one of the GPRs or SPRs
//Is 128 bits, but bits 0-19, 24-28, 32-49, 56-60, 64-81, 88-92, 96-115, 120-124 are unused
class FPSCR
@ -246,181 +307,127 @@ public:
}
} m_intrtag[3];
template<size_t _max_count>
// limited lock-free queue, most functions are barrier-free
template<size_t max_count>
class Channel
{
public:
static const size_t max_count = _max_count;
static_assert(max_count >= 1, "Invalid channel count");
private:
union _CRT_ALIGN(8) {
struct {
volatile u32 m_index;
u32 m_value[max_count];
};
volatile u64 m_indval;
struct ChannelData
{
u32 value;
u32 is_set;
};
std::mutex m_lock;
atomic_t<ChannelData> m_data[max_count];
size_t m_push;
size_t m_pop;
public:
Channel()
__noinline Channel()
{
Init();
}
void Init()
{
m_indval = 0;
}
__forceinline bool Pop(u32& res)
{
if (max_count > 1)
for (size_t i = 0; i < max_count; i++)
{
std::lock_guard<std::mutex> lock(m_lock);
if(!m_index)
{
return false;
}
res = m_value[0];
if (max_count > 1) for (u32 i = 1; i < max_count; i++) // FIFO
{
m_value[i-1] = m_value[i];
}
m_value[max_count-1] = 0;
m_index--;
return true;
}
else
{ //lock-free
if ((m_indval & 0xffffffff) == 0)
return false;
else
{
res = (m_indval >> 32);
m_indval = 0;
return true;
}
}
}
__forceinline bool Push(u32 value)
{
if (max_count > 1)
{
std::lock_guard<std::mutex> lock(m_lock);
if(m_index >= max_count)
{
return false;
}
m_value[m_index++] = value;
return true;
}
else
{ //lock-free
if (m_indval & 0xffffffff)
return false;
else
{
const u64 new_value = ((u64)value << 32) | 1;
m_indval = new_value;
return true;
}
}
}
__forceinline void PushUncond(u32 value)
{
if (max_count > 1)
{
std::lock_guard<std::mutex> lock(m_lock);
if(m_index >= max_count)
m_value[max_count-1] = value; //last message is overwritten
else
m_value[m_index++] = value;
}
else
{ //lock-free
const u64 new_value = ((u64)value << 32) | 1;
m_indval = new_value;
}
}
__forceinline void PushUncond_OR(u32 value)
{
if (max_count > 1)
{
std::lock_guard<std::mutex> lock(m_lock);
if(m_index >= max_count)
m_value[max_count-1] |= value; //last message is logically ORed
else
m_value[m_index++] = value;
}
else
{
InterlockedOr64((volatile s64*)m_indval, ((u64)value << 32) | 1);
m_data[i].write_relaxed({});
}
m_push = 0;
m_pop = 0;
}
__forceinline void PopUncond(u32& res)
{
if (max_count > 1)
{
std::lock_guard<std::mutex> lock(m_lock);
if(!m_index)
res = 0; //result is undefined
else
{
res = m_value[--m_index];
m_value[m_index] = 0;
}
}
else
{ //lock-free
if(!m_index)
res = 0;
else
{
res = (m_indval >> 32);
m_indval = 0;
}
}
res = m_data[m_pop].read_relaxed().value;
m_data[m_pop].write_relaxed({});
m_pop = (m_pop + 1) % max_count;
}
__forceinline u32 GetCount()
__forceinline bool Pop(u32& res)
{
if (max_count > 1)
const auto data = m_data[m_pop].read_relaxed();
if (data.is_set)
{
std::lock_guard<std::mutex> lock(m_lock);
return m_index;
res = data.value;
m_data[m_pop].write_relaxed({});
m_pop = (m_pop + 1) % max_count;
return true;
}
else
{
return m_index;
return false;
}
}
__forceinline u32 GetFreeCount()
__forceinline bool Pop_XCHG(u32& res) // not barrier-free, not tested
{
if (max_count > 1)
const auto data = m_data[m_pop].exchange({});
if (data.is_set)
{
std::lock_guard<std::mutex> lock(m_lock);
return max_count - m_index;
res = data.value;
m_pop = (m_pop + 1) % max_count;
return true;
}
else
{
return max_count - m_index;
return false;
}
}
void SetValue(u32 value)
__forceinline void PushUncond_OR(const u32 value) // not barrier-free, not tested
{
m_value[0] = value;
m_data[m_push]._or({ value, 1 });
m_push = (m_push + 1) % max_count;
}
u32 GetValue() const
__forceinline void PushUncond(const u32 value)
{
return m_value[0];
m_data[m_push].write_relaxed({ value, 1 });
m_push = (m_push + 1) % max_count;
}
__forceinline bool Push(const u32 value)
{
if (m_data[m_push].read_relaxed().is_set)
{
return false;
}
else
{
PushUncond(value);
return true;
}
}
__forceinline u32 GetCount() const
{
u32 res = 0;
for (size_t i = 0; i < max_count; i++)
{
res += m_data[i].read_relaxed().is_set ? 1 : 0;
}
return res;
}
__forceinline u32 GetFreeCount() const
{
u32 res = 0;
for (size_t i = 0; i < max_count; i++)
{
res += m_data[i].read_relaxed().is_set ? 0 : 1;
}
return res;
}
__forceinline void SetValue(const u32 value)
{
m_data[m_push].direct_op([value](ChannelData& v)
{
v.value = value;
});
}
__forceinline u32 GetValue() const
{
return m_data[m_pop].read_relaxed().value;
}
};
@ -473,7 +480,7 @@ public:
struct { u32 EAH, EAL; };
};
DMAC dmac;
u32 ls_offset;
void ProcessCmd(u32 cmd, u32 tag, u32 lsa, u64 ea, u32 size);
@ -503,6 +510,9 @@ public:
void WriteLS64 (const u32 lsa, const u64& data) const { vm::write64 (lsa + m_offset, data); }
void WriteLS128(const u32 lsa, const u128& data) const { vm::write128(lsa + m_offset, data); }
std::function<void(SPUThread& SPU)> m_custom_task;
std::function<u64(SPUThread& SPU)> m_code3_func;
public:
SPUThread(CPUThreadType type = CPU_THREAD_SPU);
virtual ~SPUThread();
@ -560,6 +570,8 @@ public:
public:
virtual void InitRegs();
virtual void Task();
void FastCall(u32 ls_addr);
void FastStop();
protected:
virtual void DoReset();
@ -571,3 +583,49 @@ protected:
};
SPUThread& GetCurrentSPUThread();
class spu_thread : cpu_thread
{
static const u32 stack_align = 0x10;
vm::ptr<u64> argv;
u32 argc;
vm::ptr<u64> envp;
public:
spu_thread(u32 entry, const std::string& name = "", u32 stack_size = 0, u32 prio = 0);
cpu_thread& args(std::initializer_list<std::string> values) override
{
if (!values.size())
return *this;
assert(argc == 0);
envp.set(Memory.MainMem.AllocAlign((u32)sizeof(envp), stack_align));
*envp = 0;
argv.set(Memory.MainMem.AllocAlign(u32(sizeof(argv)* values.size()), stack_align));
for (auto &arg : values)
{
u32 arg_size = align(u32(arg.size() + 1), stack_align);
u32 arg_addr = Memory.MainMem.AllocAlign(arg_size, stack_align);
std::strcpy(vm::get_ptr<char>(arg_addr), arg.c_str());
argv[argc++] = arg_addr;
}
return *this;
}
cpu_thread& run() override
{
thread->Run();
static_cast<SPUThread*>(thread)->GPR[3].from64(argc);
static_cast<SPUThread*>(thread)->GPR[4].from64(argv.addr());
static_cast<SPUThread*>(thread)->GPR[5].from64(envp.addr());
return *this;
}
};

View File

@ -4,33 +4,94 @@
#include "Emu/HDD/HDD.h"
#include "vfsDeviceLocalFile.h"
#include "Ini.h"
#include "Emu/System.h"
#undef CreateFile // TODO: what's wrong with it?
#undef CreateFile
int sort_devices(const void* _a, const void* _b)
{
const vfsDevice& a = **(const vfsDevice**)_a;
const vfsDevice& b = **(const vfsDevice**)_b;
if(a.GetPs3Path().length() > b.GetPs3Path().length()) return 1;
if(a.GetPs3Path().length() < b.GetPs3Path().length()) return -1;
if (a.GetPs3Path().length() > b.GetPs3Path().length()) return 1;
if (a.GetPs3Path().length() < b.GetPs3Path().length()) return -1;
return 0;
}
std::vector<std::string> simplify_path_blocks(const std::string& path)
{
std::string lower_path = path;
std::transform(lower_path.begin(), lower_path.end(), lower_path.begin(), ::tolower);
std::vector<std::string> path_blocks = std::move(fmt::split(lower_path, { "/", "\\" }));
for (size_t i = 0; i < path_blocks.size(); ++i)
{
if (path_blocks[i] == ".")
{
path_blocks.erase(path_blocks.begin() + i--);
}
else if (i && path_blocks[i] == "..")
{
path_blocks.erase(path_blocks.begin() + (i - 1), path_blocks.begin() + (i + 1));
i--;
}
}
return path_blocks;
}
std::string simplify_path(const std::string& path, bool is_dir)
{
std::vector<std::string> path_blocks = simplify_path_blocks(path);
std::string result;
if (path_blocks.empty())
return result;
if (is_dir)
{
for (auto &dir : path_blocks)
{
result += dir + "/";
}
}
else
{
for (size_t i = 0; i < path_blocks.size() - 1; ++i)
{
result += path_blocks[i] + "/";
}
result += path_blocks[path_blocks.size() - 1];
}
return result;
}
VFS::~VFS()
{
UnMountAll();
}
std::string VFS::FindEntry(const std::string &path)
{
return path;
return cwd + "/" + path;
}
void VFS::Mount(const std::string& ps3_path, const std::string& local_path, vfsDevice* device)
{
UnMount(ps3_path);
std::string simpl_ps3_path = simplify_path(ps3_path, true);
device->SetPath(ps3_path, local_path);
UnMount(simpl_ps3_path);
device->SetPath(simpl_ps3_path, simplify_path(local_path, true));
m_devices.push_back(device);
if(m_devices.size() > 1)
if (m_devices.size() > 1)
{
//std::qsort(m_devices.GetPtr(), m_devices.GetCount(), sizeof(vfsDevice*), sort_devices);
}
@ -38,11 +99,14 @@ void VFS::Mount(const std::string& ps3_path, const std::string& local_path, vfsD
void VFS::UnMount(const std::string& ps3_path)
{
for(u32 i=0; i<m_devices.size(); ++i)
std::string simpl_ps3_path = simplify_path(ps3_path, true);
for (u32 i = 0; i < m_devices.size(); ++i)
{
if(!m_devices[i]->GetPs3Path().compare(ps3_path))
if (!strcmp(m_devices[i]->GetPs3Path().c_str(), simpl_ps3_path.c_str()))
{
delete m_devices[i];
m_devices.erase(m_devices.begin() +i);
return;
@ -63,9 +127,9 @@ void VFS::UnMountAll()
vfsFileBase* VFS::OpenFile(const std::string& ps3_path, vfsOpenMode mode) const
{
std::string path;
if(vfsDevice* dev = GetDevice(ps3_path, path))
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
if(vfsFileBase* res = dev->GetNewFileStream())
if (vfsFileBase* res = dev->GetNewFileStream())
{
res->Open(path, mode);
return res;
@ -79,9 +143,9 @@ vfsDirBase* VFS::OpenDir(const std::string& ps3_path) const
{
std::string path;
if(vfsDevice* dev = GetDevice(ps3_path, path))
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
if(vfsDirBase* res = dev->GetNewDirStream())
if (vfsDirBase* res = dev->GetNewDirStream())
{
res->Open(path);
return res;
@ -94,11 +158,11 @@ vfsDirBase* VFS::OpenDir(const std::string& ps3_path) const
bool VFS::CreateFile(const std::string& ps3_path) const
{
std::string path;
if(vfsDevice* dev = GetDevice(ps3_path, path))
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
std::shared_ptr<vfsFileBase> res(dev->GetNewFileStream());
if(res)
if (res)
{
return res->Create(path);
}
@ -110,11 +174,11 @@ bool VFS::CreateFile(const std::string& ps3_path) const
bool VFS::CreateDir(const std::string& ps3_path) const
{
std::string path;
if(vfsDevice* dev = GetDevice(ps3_path, path))
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
std::shared_ptr<vfsDirBase> res(dev->GetNewDirStream());
if(res)
if (res)
{
return res->Create(path);
}
@ -126,11 +190,11 @@ bool VFS::CreateDir(const std::string& ps3_path) const
bool VFS::RemoveFile(const std::string& ps3_path) const
{
std::string path;
if(vfsDevice* dev = GetDevice(ps3_path, path))
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
std::shared_ptr<vfsFileBase> res(dev->GetNewFileStream());
if(res)
if (res)
{
return res->Remove(path);
}
@ -142,11 +206,11 @@ bool VFS::RemoveFile(const std::string& ps3_path) const
bool VFS::RemoveDir(const std::string& ps3_path) const
{
std::string path;
if(vfsDevice* dev = GetDevice(ps3_path, path))
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
std::shared_ptr<vfsDirBase> res(dev->GetNewDirStream());
if(res)
if (res)
{
return res->Remove(path);
}
@ -158,11 +222,11 @@ bool VFS::RemoveDir(const std::string& ps3_path) const
bool VFS::ExistsFile(const std::string& ps3_path) const
{
std::string path;
if(vfsDevice* dev = GetDevice(ps3_path, path))
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
std::shared_ptr<vfsFileBase> res(dev->GetNewFileStream());
if(res)
if (res)
{
return res->Exists(path);
}
@ -174,11 +238,11 @@ bool VFS::ExistsFile(const std::string& ps3_path) const
bool VFS::ExistsDir(const std::string& ps3_path) const
{
std::string path;
if(vfsDevice* dev = GetDevice(ps3_path, path))
if (vfsDevice* dev = GetDevice(ps3_path, path))
{
std::shared_ptr<vfsDirBase> res(dev->GetNewDirStream());
if(res)
if (res)
{
return res->IsExists(path);
}
@ -190,11 +254,11 @@ bool VFS::ExistsDir(const std::string& ps3_path) const
bool VFS::RenameFile(const std::string& ps3_path_from, const std::string& ps3_path_to) const
{
std::string path;
if(vfsDevice* dev = GetDevice(ps3_path_from, path))
if (vfsDevice* dev = GetDevice(ps3_path_from, path))
{
std::shared_ptr<vfsFileBase> res(dev->GetNewFileStream());
if(res)
if (res)
{
return res->Rename(path, ps3_path_to);
}
@ -206,11 +270,11 @@ bool VFS::RenameFile(const std::string& ps3_path_from, const std::string& ps3_pa
bool VFS::RenameDir(const std::string& ps3_path_from, const std::string& ps3_path_to) const
{
std::string path;
if(vfsDevice* dev = GetDevice(ps3_path_from, path))
if (vfsDevice* dev = GetDevice(ps3_path_from, path))
{
std::shared_ptr<vfsDirBase> res(dev->GetNewDirStream());
if(res)
if (res)
{
return res->Rename(path, ps3_path_to);
}
@ -221,53 +285,107 @@ bool VFS::RenameDir(const std::string& ps3_path_from, const std::string& ps3_pat
vfsDevice* VFS::GetDevice(const std::string& ps3_path, std::string& path) const
{
u32 max_eq;
s32 max_i=-1;
for(u32 i=0; i<m_devices.size(); ++i)
auto try_get_device = [this, &path](const std::vector<std::string>& ps3_path_blocks) -> vfsDevice*
{
const u32 eq = m_devices[i]->CmpPs3Path(ps3_path);
size_t max_eq = 0;
int max_i = -1;
if(max_i < 0 || eq > max_eq)
for (u32 i = 0; i < m_devices.size(); ++i)
{
max_eq = eq;
max_i = i;
}
}
std::vector<std::string> dev_ps3_path_blocks = simplify_path_blocks(m_devices[i]->GetPs3Path());
if(max_i < 0) return nullptr;
path = vfsDevice::GetWinPath(m_devices[max_i]->GetLocalPath(), ps3_path.substr(max_eq, ps3_path.length() - max_eq));
return m_devices[max_i];
if (ps3_path_blocks.size() < dev_ps3_path_blocks.size())
continue;
size_t eq = 0;
for (; eq < dev_ps3_path_blocks.size(); ++eq)
{
if (strcmp(ps3_path_blocks[eq].c_str(), dev_ps3_path_blocks[eq].c_str()))
{
break;
}
}
if (eq > max_eq)
{
max_eq = eq;
max_i = i;
}
}
if (max_i < 0)
return nullptr;
path = m_devices[max_i]->GetLocalPath();
for (u32 i = max_eq; i < ps3_path_blocks.size(); i++)
{
path += "/" + ps3_path_blocks[i];
}
path = simplify_path(path, false);
return m_devices[max_i];
};
if (auto res = try_get_device(simplify_path_blocks(ps3_path)))
return res;
if (auto res = try_get_device(simplify_path_blocks(cwd + ps3_path)))
return res;
return nullptr;
}
vfsDevice* VFS::GetDeviceLocal(const std::string& local_path, std::string& path) const
{
u32 max_eq;
s32 max_i=-1;
size_t max_eq = 0;
int max_i = -1;
rFileName file_path(local_path);
file_path.Normalize();
std::string mormalized_path = file_path.GetFullPath();
std::vector<std::string> local_path_blocks = simplify_path_blocks(local_path);
for(u32 i=0; i<m_devices.size(); ++i)
for (u32 i = 0; i < m_devices.size(); ++i)
{
const u32 eq = m_devices[i]->CmpLocalPath(mormalized_path);
std::vector<std::string> dev_local_path_blocks_blocks = simplify_path_blocks(m_devices[i]->GetLocalPath());
if(max_i < 0 || eq > max_eq)
if (local_path_blocks.size() < dev_local_path_blocks_blocks.size())
continue;
size_t eq = 0;
for (; eq < dev_local_path_blocks_blocks.size(); ++eq)
{
if (strcmp(local_path_blocks[eq].c_str(), dev_local_path_blocks_blocks[eq].c_str()))
{
break;
}
}
if (eq > max_eq)
{
max_eq = eq;
max_i = i;
}
}
if(max_i < 0) return nullptr;
if (max_i < 0)
return nullptr;
path = m_devices[max_i]->GetPs3Path();
for (u32 i = max_eq; i < local_path_blocks.size(); i++)
{
path += "/" + local_path_blocks[i];
}
path = simplify_path(path, false);
path = vfsDevice::GetPs3Path(m_devices[max_i]->GetPs3Path(), local_path.substr(max_eq, local_path.length() - max_eq));
return m_devices[max_i];
}
void VFS::Init(const std::string& path)
{
cwd = simplify_path(path, true);
UnMountAll();
std::vector<VFSManagerEntry> entries;
@ -293,8 +411,8 @@ void VFS::Init(const std::string& path)
std::string mpath = entry.path;
// TODO: This shouldn't use current dir
fmt::Replace(mpath,"$(EmulatorDir)", ".");
fmt::Replace(mpath,"$(GameDir)", vfsDevice::GetRoot(path));
fmt::Replace(mpath, "$(EmulatorDir)", Emu.GetEmulatorPath());
fmt::Replace(mpath, "$(GameDir)", cwd);
Mount(entry.mount, mpath, dev);
}
}
@ -305,11 +423,11 @@ void VFS::SaveLoadDevices(std::vector<VFSManagerEntry>& res, bool is_load)
entries_count.Init("count", "VFSManager");
int count = 0;
if(is_load)
if (is_load)
{
count = entries_count.LoadValue(count);
if(!count)
if (!count)
{
res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_hdd0/", "/dev_hdd0/");
res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_hdd1/", "/dev_hdd1/");
@ -319,7 +437,6 @@ void VFS::SaveLoadDevices(std::vector<VFSManagerEntry>& res, bool is_load)
res.emplace_back(vfsDevice_LocalFile, "$(GameDir)", "/app_home/");
res.emplace_back(vfsDevice_LocalFile, "$(GameDir)/../", "/dev_bdvd/");
res.emplace_back(vfsDevice_LocalFile, "", "/host_root/");
res.emplace_back(vfsDevice_LocalFile, "$(GameDir)", "/");
return;
}
@ -344,7 +461,7 @@ void VFS::SaveLoadDevices(std::vector<VFSManagerEntry>& res, bool is_load)
entry_mount.Init(fmt::Format("mount[%d]", i), "VFSManager");
entry_device.Init(fmt::Format("device[%d]", i), "VFSManager");
if(is_load)
if (is_load)
{
res[i] = VFSManagerEntry();
res[i].path = entry_path.LoadValue("");

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
{
~VFS();
std::string cwd;
std::string FindEntry(const std::string &path);
//TODO: find out where these are supposed to be deleted or just make it shared_ptr
//and also make GetDevice and GetDeviceLocal return shared_ptr then.
// A vfsDevice will be deleted when they're unmounted or the VFS struct is destroyed.

View File

@ -1,6 +1,7 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "vfsDevice.h"
#include "VFS.h"
#include "vfsDir.h"
@ -10,7 +11,7 @@ vfsDir::vfsDir()
{
// TODO: proper implementation
// m_stream is nullptr here. So open root until a proper dir is given
Open("/");
//Open("/");
}
vfsDir::vfsDir(const std::string& path)
@ -26,37 +27,78 @@ bool vfsDir::Open(const std::string& path)
m_stream.reset(Emu.GetVFS().OpenDir(path));
return m_stream && m_stream->IsOpened();
DirEntryInfo info;
m_cwd = simplify_path(0 && m_stream && m_stream->IsOpened() ? m_stream->GetPath() : path, true);
auto blocks = simplify_path_blocks(GetPath());
for (auto dev : Emu.GetVFS().m_devices)
{
auto dev_blocks = simplify_path_blocks(dev->GetPs3Path());
if (dev_blocks.size() < (blocks.size() + 1))
{
continue;
}
bool is_ok = true;
for (size_t i = 0; i < blocks.size(); ++i)
{
if (strcmp(dev_blocks[i].c_str(), blocks[i].c_str()))
{
is_ok = false;
break;
}
}
if (is_ok)
{
info.name = dev_blocks[blocks.size()];
m_entries.push_back(info);
}
}
if (m_stream && m_stream->IsOpened())
{
m_entries.insert(m_entries.begin(), m_stream->GetEntries().begin(), m_stream->GetEntries().end());
}
return !m_entries.empty();
}
bool vfsDir::Create(const std::string& path)
{
return m_stream->Create(path);
return Emu.GetVFS().CreateDir(path);
}
bool vfsDir::IsExists(const std::string& path) const
{
return m_stream->IsExists(path);
}
auto path_blocks = simplify_path_blocks(path);
const std::vector<DirEntryInfo>& vfsDir::GetEntries() const
{
return m_stream->GetEntries();
if (path_blocks.empty())
return false;
std::string dir_name = path_blocks[path_blocks.size() - 1];
for (const auto entry : vfsDir(path + "/.."))
{
if (!strcmp(entry->name.c_str(), dir_name.c_str()))
return true;
}
return false;
}
bool vfsDir::Rename(const std::string& from, const std::string& to)
{
return m_stream->Rename(from, to);
return Emu.GetVFS().RenameDir(from, to);
}
bool vfsDir::Remove(const std::string& path)
{
return m_stream->Remove(path);
}
const DirEntryInfo* vfsDir::Read()
{
return m_stream->Read();
return Emu.GetVFS().RemoveDir(path);
}
void vfsDir::Close()
@ -64,12 +106,7 @@ void vfsDir::Close()
m_stream.reset();
}
std::string vfsDir::GetPath() const
{
return m_stream->GetPath();
}
bool vfsDir::IsOpened() const
{
return m_stream && m_stream->IsOpened();
return !m_entries.empty();
}

View File

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

View File

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

View File

@ -53,4 +53,57 @@ public:
virtual bool Rename(const std::string& from, const std::string& to) = 0;
virtual bool Remove(const std::string& path) = 0;
virtual const DirEntryInfo* Read();
virtual const DirEntryInfo* First();
class iterator
{
vfsDirBase *parent;
const DirEntryInfo* data;
public:
iterator(vfsDirBase* parent)
: parent(parent)
, data(parent->First())
{
}
iterator(const DirEntryInfo* data)
: parent(parent)
, data(data)
{
}
iterator& operator++()
{
data = parent->Read();
return *this;
}
iterator operator++(int)
{
const DirEntryInfo* olddata = data;
data = parent->Read();
return iterator(olddata);
}
const DirEntryInfo* operator *()
{
return data;
}
bool operator!=(iterator other) const
{
return data != other.data;
}
};
iterator begin()
{
return iterator(this);
}
iterator end()
{
return iterator((const DirEntryInfo*)nullptr);
}
};

View File

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

View File

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

View File

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

View File

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

View File

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

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
// first mappable space is used)
virtual u64 Map(u64 realaddr, u32 size, u64 addr = 0);
virtual bool Map(u64 realaddr, u32 size, u64 addr);
virtual u64 Map(u64 realaddr, u32 size);
// Unmap real address (please specify only starting point, no midway memory will be unmapped), returns the size of the unmapped area
virtual u32 UnmapRealAddress(u64 realaddr);
virtual bool UnmapRealAddress(u64 realaddr, u32& size);
// Unmap address (please specify only starting point, no midway memory will be unmapped), returns the size of the unmapped area
virtual u32 UnmapAddress(u64 addr);
virtual bool UnmapAddress(u64 addr, u32& size);
// Reserve a certain amount so no one can use it, returns true on succces, false on failure
virtual bool Reserve(u32 size);

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 "Memory.h"
#ifdef _WIN32
#include <Windows.h>
void* const m_base_addr = VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS);
#else
#include <sys/mman.h>
/* OS X uses MAP_ANON instead of MAP_ANONYMOUS */
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
void* const m_base_addr = ::mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
#endif
namespace vm
{
#ifdef _WIN32
#include <Windows.h>
void* const g_base_addr = VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS);
#else
#include <sys/mman.h>
/* OS X uses MAP_ANON instead of MAP_ANONYMOUS */
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
void* const g_base_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
#endif
bool check_addr(u32 addr)
{
// Checking address before using it is unsafe.
@ -28,20 +27,120 @@ namespace vm
//TODO
bool map(u32 addr, u32 size, u32 flags)
{
return false;
return Memory.Map(addr, size);
}
bool unmap(u32 addr, u32 size, u32 flags)
{
return false;
return Memory.Unmap(addr);
}
u32 alloc(u32 size)
u32 alloc(u32 addr, u32 size, memory_location location)
{
return 0;
return g_locations[location].fixed_allocator(addr, size);
}
void unalloc(u32 addr)
u32 alloc(u32 size, memory_location location)
{
return g_locations[location].allocator(size);
}
void dealloc(u32 addr, memory_location location)
{
return g_locations[location].deallocator(addr);
}
namespace ps3
{
u32 main_alloc(u32 size)
{
return Memory.MainMem.AllocAlign(size, 1);
}
u32 main_fixed_alloc(u32 addr, u32 size)
{
return Memory.MainMem.AllocFixed(addr, size) ? addr : 0;
}
void main_dealloc(u32 addr)
{
Memory.MainMem.Free(addr);
}
u32 g_stack_offset = 0;
u32 stack_alloc(u32 size)
{
return Memory.StackMem.AllocAlign(size, 0x10);
}
u32 stack_fixed_alloc(u32 addr, u32 size)
{
return Memory.StackMem.AllocFixed(addr, size) ? addr : 0;
}
void stack_dealloc(u32 addr)
{
Memory.StackMem.Free(addr);
}
u32 sprx_alloc(u32 size)
{
return Memory.SPRXMem.AllocAlign(size, 1);
}
u32 sprx_fixed_alloc(u32 addr, u32 size)
{
return Memory.SPRXMem.AllocFixed(Memory.SPRXMem.GetStartAddr() + addr, size) ? Memory.SPRXMem.GetStartAddr() + addr : 0;
}
void sprx_dealloc(u32 addr)
{
Memory.SPRXMem.Free(addr);
}
u32 user_space_alloc(u32 size)
{
return Memory.PRXMem.AllocAlign(size, 1);
}
u32 user_space_fixed_alloc(u32 addr, u32 size)
{
return Memory.PRXMem.AllocFixed(addr, size) ? addr : 0;
}
void user_space_dealloc(u32 addr)
{
Memory.PRXMem.Free(addr);
}
void init()
{
Memory.Init(Memory_PS3);
}
}
namespace psv
{
void init()
{
Memory.Init(Memory_PSV);
}
}
namespace psp
{
void init()
{
Memory.Init(Memory_PSP);
}
}
location_info g_locations[memory_location_count] =
{
{ 0x00010000, 0x2FFF0000, ps3::main_alloc, ps3::main_fixed_alloc, ps3::main_dealloc },
{ 0xD0000000, 0x10000000, ps3::stack_alloc, ps3::stack_fixed_alloc, ps3::stack_dealloc },
//remove me
{ 0x00010000, 0x2FFF0000, ps3::sprx_alloc, ps3::sprx_fixed_alloc, ps3::sprx_dealloc },
{ 0x30000000, 0x10000000, ps3::user_space_alloc, ps3::user_space_fixed_alloc, ps3::user_space_dealloc },
};
void close()
{
Memory.Close();
}
}

View File

@ -1,83 +1,72 @@
#pragma once
#include "Memory.h"
namespace vm
{
enum memory_location : uint
{
main,
stack,
//remove me
sprx,
user_space,
memory_location_count
};
static void set_stack_size(u32 size) {}
static void initialize_stack() {}
extern void* const g_base_addr;
bool map(u32 addr, u32 size, u32 flags);
bool unmap(u32 addr, u32 size = 0, u32 flags = 0);
u32 alloc(u32 size);
void unalloc(u32 addr);
u32 alloc(u32 size, memory_location location = user_space);
u32 alloc(u32 addr, u32 size, memory_location location = user_space);
void dealloc(u32 addr, memory_location location = user_space);
template<typename T>
template<typename T = void>
T* const get_ptr(u32 addr)
{
return (T*)((u8*)m_base_addr + addr);
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>
T& get_ref(u32 addr)
{
return *get_ptr<T>(addr);
}
template<typename T>
T& get_ref(u64 addr)
{
return get_ref<T>((u32)addr);
}
namespace ps3
{
void init();
static u8 read8(u32 addr)
{
return *((u8*)m_base_addr + addr);
}
static u8 read8(u64 addr)
{
return read8((u32)addr);
return *((u8*)g_base_addr + addr);
}
static void write8(u32 addr, u8 value)
{
*((u8*)m_base_addr + addr) = value;
}
static void write8(u64 addr, u8 value)
{
write8((u32)addr, value);
*((u8*)g_base_addr + addr) = value;
}
static u16 read16(u32 addr)
{
return re16(*(u16*)((u8*)m_base_addr + addr));
return re16(*(u16*)((u8*)g_base_addr + addr));
}
static u16 read16(u64 addr)
static void write16(u32 addr, be_t<u16> value)
{
return read16((u32)addr);
}
static void write16(u32 addr, u16 value)
{
*(u16*)((u8*)m_base_addr + addr) = re16(value);
}
static void write16(u64 addr, u16 value)
{
write16((u32)addr, value);
*(be_t<u16>*)((u8*)g_base_addr + addr) = value;
}
static u32 read32(u32 addr)
{
if (addr < RAW_SPU_BASE_ADDR || (addr % RAW_SPU_OFFSET) < RAW_SPU_PROB_OFFSET)
{
return re32(*(u32*)((u8*)m_base_addr + addr));
return re32(*(u32*)((u8*)g_base_addr + addr));
}
else
{
@ -85,16 +74,11 @@ namespace vm
}
}
static u32 read32(u64 addr)
{
return read32((u32)addr);
}
static void write32(u32 addr, u32 value)
static void write32(u32 addr, be_t<u32> value)
{
if (addr < RAW_SPU_BASE_ADDR || (addr % RAW_SPU_OFFSET) < RAW_SPU_PROB_OFFSET)
{
*(u32*)((u8*)m_base_addr + addr) = re32(value);
*(be_t<u32>*)((u8*)g_base_addr + addr) = value;
}
else
{
@ -102,106 +86,170 @@ namespace vm
}
}
static void write32(u64 addr, u32 value)
{
write32((u32)addr, value);
}
static u64 read64(u32 addr)
{
return re64(*(u64*)((u8*)m_base_addr + addr));
return re64(*(u64*)((u8*)g_base_addr + addr));
}
static u64 read64(u64 addr)
static void write64(u32 addr, be_t<u64> value)
{
return read64((u32)addr);
*(be_t<u64>*)((u8*)g_base_addr + addr) = value;
}
static void write16(u32 addr, u16 value)
{
write16(addr, be_t<u16>::make(value));
}
static void write32(u32 addr, u32 value)
{
write32(addr, be_t<u32>::make(value));
}
static void write64(u32 addr, u64 value)
{
*(u64*)((u8*)m_base_addr + addr) = re64(value);
}
static void write64(u64 addr, u64 value)
{
write64((u32)addr, value);
write64(addr, be_t<u64>::make(value));
}
static u128 read128(u32 addr)
{
return re128(*(u128*)((u8*)m_base_addr + addr));
}
static u128 read128(u64 addr)
{
return read128((u32)addr);
return re128(*(u128*)((u8*)g_base_addr + addr));
}
static void write128(u32 addr, u128 value)
{
*(u128*)((u8*)m_base_addr + addr) = re128(value);
}
static void write128(u64 addr, u128 value)
{
write128((u32)addr, value);
*(u128*)((u8*)g_base_addr + addr) = re128(value);
}
}
namespace psv
{
void init();
static u8 read8(u32 addr)
{
return *((u8*)m_base_addr + addr);
return *((u8*)g_base_addr + addr);
}
static void write8(u32 addr, u8 value)
{
*((u8*)m_base_addr + addr) = value;
*((u8*)g_base_addr + addr) = value;
}
static u16 read16(u32 addr)
{
return *(u16*)((u8*)m_base_addr + addr);
return *(u16*)((u8*)g_base_addr + addr);
}
static void write16(u32 addr, u16 value)
{
*(u16*)((u8*)m_base_addr + addr) = value;
*(u16*)((u8*)g_base_addr + addr) = value;
}
static u32 read32(u32 addr)
{
return *(u32*)((u8*)m_base_addr + addr);
return *(u32*)((u8*)g_base_addr + addr);
}
static void write32(u32 addr, u32 value)
{
*(u32*)((u8*)m_base_addr + addr) = value;
*(u32*)((u8*)g_base_addr + addr) = value;
}
static u64 read64(u32 addr)
{
return *(u64*)((u8*)m_base_addr + addr);
return *(u64*)((u8*)g_base_addr + addr);
}
static void write64(u32 addr, u64 value)
{
*(u64*)((u8*)m_base_addr + addr) = value;
*(u64*)((u8*)g_base_addr + addr) = value;
}
static u128 read128(u32 addr)
{
return *(u128*)((u8*)m_base_addr + addr);
return *(u128*)((u8*)g_base_addr + addr);
}
static void write128(u32 addr, u128 value)
{
*(u128*)((u8*)m_base_addr + addr) = value;
*(u128*)((u8*)g_base_addr + addr) = value;
}
}
namespace psp
{
using namespace psv;
void init();
}
void close();
}
#include "vm_ref.h"
#include "vm_ptr.h"
#include "vm_var.h"
#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;
public:
typedef T type;
typedef typename std::remove_cv<T>::type type;
_ptr_base operator++ (int)
{
@ -38,41 +38,41 @@ namespace vm
return *this;
}
_ptr_base& operator += (int count)
_ptr_base& operator += (AT count)
{
m_addr += count * sizeof(AT);
return *this;
}
_ptr_base& operator -= (int count)
_ptr_base& operator -= (AT count)
{
m_addr -= count * sizeof(AT);
return *this;
}
_ptr_base operator + (int count) const
_ptr_base operator + (typename remove_be_t<AT>::type count) const { return make(m_addr + count * sizeof(AT)); }
_ptr_base operator + (typename to_be_t<AT>::type count) const { return make(m_addr + count * sizeof(AT)); }
_ptr_base operator - (typename remove_be_t<AT>::type count) const { return make(m_addr - count * sizeof(AT)); }
_ptr_base operator - (typename to_be_t<AT>::type count) const { return make(m_addr - count * sizeof(AT)); }
__forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; }
__forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; }
__forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; }
__forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; }
__forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; }
__forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; }
__forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; }
__forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; }
explicit operator bool() const { return m_addr != 0; }
__forceinline _ptr_base<T, lvl - 1, std::conditional<is_be_t<T>::value, typename to_be_t<AT>::type, AT>>& operator *() const
{
return make(m_addr + count * sizeof(AT));
return vm::get_ref<_ptr_base<T, lvl - 1, std::conditional<is_be_t<T>::value, typename to_be_t<AT>::type, AT>>>(m_addr);
}
_ptr_base operator - (int count) const
__forceinline _ptr_base<T, lvl - 1, std::conditional<is_be_t<T>::value, typename to_be_t<AT>::type, AT>>& operator [](AT index) const
{
return make(m_addr - count * sizeof(AT));
}
__forceinline _ptr_base<T, lvl - 1, AT>& operator *() const
{
return vm::get_ref<_ptr_base<T, lvl - 1, AT>>(m_addr);
}
__forceinline _ptr_base<T, lvl - 1, AT>& operator [](int index) const
{
return vm::get_ref<_ptr_base<T, lvl - 1, AT>>(m_addr + sizeof(AT) * index);
}
operator bool() const
{
return m_addr != 0;
return vm::get_ref<_ptr_base<T, lvl - 1, std::conditional<is_be_t<T>::value, typename to_be_t<AT>::type, AT>>>(m_addr + sizeof(AT)* index);
}
//typedef typename invert_be_t<AT>::type AT2;
@ -80,7 +80,7 @@ namespace vm
template<typename AT2>
operator const _ptr_base<T, lvl, AT2>() const
{
typename std::remove_const<AT2>::type addr; addr = m_addr;
typename std::remove_const<AT2>::type addr = convert_le_be<AT2>(m_addr);
return (_ptr_base<T, lvl, AT2>&)addr;
}
@ -108,6 +108,8 @@ namespace vm
AT m_addr;
public:
typedef typename std::remove_cv<T>::type type;
__forceinline T* const operator -> () const
{
return vm::get_ptr<T>(m_addr);
@ -139,38 +141,49 @@ namespace vm
return *this;
}
_ptr_base& operator += (int count)
_ptr_base& operator += (AT count)
{
m_addr += count * sizeof(T);
return *this;
}
_ptr_base& operator -= (int count)
_ptr_base& operator -= (AT count)
{
m_addr -= count * sizeof(T);
return *this;
}
_ptr_base operator + (int count) const
{
return make(m_addr + count * sizeof(T));
}
_ptr_base operator - (int count) const
{
return make(m_addr - count * sizeof(T));
}
_ptr_base operator + (typename remove_be_t<AT>::type count) const { return make(m_addr + count * sizeof(T)); }
_ptr_base operator + (typename to_be_t<AT>::type count) const { return make(m_addr + count * sizeof(T)); }
_ptr_base operator - (typename remove_be_t<AT>::type count) const { return make(m_addr - count * sizeof(T)); }
_ptr_base operator - (typename to_be_t<AT>::type count) const { return make(m_addr - count * sizeof(T)); }
__forceinline T& operator *() const
{
return get_ref<T>(m_addr);
return vm::get_ref<T>(m_addr);
}
__forceinline T& operator [](int index) const
__forceinline T& operator [](typename remove_be_t<AT>::type index) const
{
return get_ref<T>(m_addr + sizeof(T) * index);
return vm::get_ref<T>(m_addr + sizeof(T)* index);
}
__forceinline T& operator [](typename to_be_t<AT>::forced_type index) const
{
return vm::get_ref<T>(m_addr + sizeof(T)* index);
}
__forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; }
__forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; }
__forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; }
__forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; }
__forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; }
__forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; }
__forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; }
__forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; }
explicit operator bool() const { return m_addr != 0; }
explicit operator T*() const { return get_ptr(); }
/*
operator _ref_base<T, AT>()
{
@ -188,26 +201,28 @@ namespace vm
return m_addr;
}
void set(const AT value)
template<typename U>
void set(U&& value)
{
m_addr = value;
m_addr = convert_le_be<AT>(value);
}
operator bool() const
/*
operator T*() const
{
return m_addr != 0;
return get_ptr();
}
*/
//typedef typename invert_be_t<AT>::type AT2;
template<typename AT2>
operator const _ptr_base<T, 1, AT2>() const
{
typename std::remove_const<AT2>::type addr; addr = m_addr;
typename std::remove_const<AT2>::type addr = convert_le_be<AT2>(m_addr);
return (_ptr_base<T, 1, AT2>&)addr;
}
T* const get_ptr() const
T* get_ptr() const
{
return vm::get_ptr<T>(m_addr);
}
@ -236,29 +251,39 @@ namespace vm
m_addr = value;
}
void* const get_ptr() const
void* get_ptr() const
{
return vm::get_ptr<void>(m_addr);
}
operator bool() const
explicit operator void*() const
{
return m_addr != 0;
return get_ptr();
}
__forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; }
__forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; }
__forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; }
__forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; }
__forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; }
__forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; }
__forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; }
__forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; }
explicit operator bool() const { return m_addr != 0; }
//typedef typename invert_be_t<AT>::type AT2;
template<typename AT2>
operator const _ptr_base<void, 1, AT2>() const
{
typename std::remove_const<AT2>::type addr; addr = m_addr;
typename std::remove_const<AT2>::type addr = convert_le_be<AT2>(m_addr);
return (_ptr_base<void, 1, AT2>&)addr;
}
template<typename AT2>
operator const _ptr_base<const void, 1, AT2>() const
{
typename std::remove_const<AT2>::type addr; addr = m_addr;
typename std::remove_const<AT2>::type addr = convert_le_be<AT2>(m_addr);
return (_ptr_base<const void, 1, AT2>&)addr;
}
@ -286,22 +311,32 @@ namespace vm
m_addr = value;
}
const void* const get_ptr() const
const void* get_ptr() const
{
return vm::get_ptr<const void>(m_addr);
}
operator bool() const
explicit operator const void*() const
{
return m_addr != 0;
return get_ptr();
}
__forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; }
__forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; }
__forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; }
__forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; }
__forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; }
__forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; }
__forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; }
__forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; }
explicit operator bool() const { return m_addr != 0; }
//typedef typename invert_be_t<AT>::type AT2;
template<typename AT2>
operator const _ptr_base<const void, 1, AT2>() const
{
typename std::remove_const<AT2>::type addr; addr = m_addr;
typename std::remove_const<AT2>::type addr = convert_le_be<AT2>(m_addr);
return (_ptr_base<const void, 1, AT2>&)addr;
}
@ -335,17 +370,22 @@ namespace vm
m_addr = value;
}
operator bool() const
{
return m_addr != 0;
}
__forceinline bool operator <(const _ptr_base& right) const { return m_addr < right.m_addr; }
__forceinline bool operator <=(const _ptr_base& right) const { return m_addr <= right.m_addr; }
__forceinline bool operator >(const _ptr_base& right) const { return m_addr > right.m_addr; }
__forceinline bool operator >=(const _ptr_base& right) const { return m_addr >= right.m_addr; }
__forceinline bool operator ==(const _ptr_base& right) const { return m_addr == right.m_addr; }
__forceinline bool operator !=(const _ptr_base& right) const { return m_addr != right.m_addr; }
__forceinline bool operator ==(const nullptr_t& right) const { return m_addr == 0; }
__forceinline bool operator !=(const nullptr_t& right) const { return m_addr != 0; }
explicit operator bool() const { return m_addr != 0; }
//typedef typename invert_be_t<AT>::type AT2;
template<typename AT2>
operator const _ptr_base<RT(*)(T...), 1, AT2>() const
{
typename std::remove_const<AT2>::type addr; addr = m_addr;
typename std::remove_const<AT2>::type addr = convert_le_be<AT2>(m_addr);
return (_ptr_base<RT(*)(T...), 1, AT2>&)addr;
}
@ -356,7 +396,7 @@ namespace vm
operator const std::function<RT(T...)>() const
{
typename std::remove_const<AT>::type addr; addr = m_addr;
typename std::remove_const<AT>::type addr = convert_le_be<AT>(m_addr);
return [addr](T... args) -> RT { return make(addr)(args...); };
}
@ -413,7 +453,7 @@ namespace vm
namespace ps3
{
//default pointer for HLE functions (LE ptrerence to BE data)
//default pointer for HLE functions (LE pointer to BE data)
template<typename T, int lvl = 1, typename AT = u32> struct ptr : public lptrb<T, lvl, AT>
{
static ptr make(AT addr)
@ -425,7 +465,7 @@ namespace vm
//using lptrb<T, lvl, AT>::operator const _ptr_base<typename to_be_t<T>::type, lvl, AT>;
};
//default pointer for HLE structures (BE ptrerence to BE data)
//default pointer for HLE structures (BE pointer to BE data)
template<typename T, int lvl = 1, typename AT = u32> struct bptr : public bptrb<T, lvl, AT>
{
static bptr make(AT addr)
@ -440,7 +480,7 @@ namespace vm
namespace psv
{
//default pointer for HLE functions & structures (LE ptrerence to LE data)
//default pointer for HLE functions & structures (LE pointer to LE data)
template<typename T, int lvl = 1, typename AT = u32> struct ptr : public lptrl<T, lvl, AT>
{
static ptr make(AT addr)

View File

@ -90,7 +90,7 @@ std::string GLFragmentDecompilerThread::AddConst()
return name;
}
auto data = vm::ptr<be_t<u32>>::make(m_addr + m_size + m_offset);
auto data = vm::ptr<u32>::make(m_addr + m_size + m_offset);
m_offset += 4 * 4;
u32 x = GetData(data[0]);
@ -279,7 +279,7 @@ std::string GLFragmentDecompilerThread::BuildCode()
void GLFragmentDecompilerThread::Task()
{
auto data = vm::ptr<be_t<u32>>::make(m_addr);
auto data = vm::ptr<u32>::make(m_addr);
m_size = 0;
m_location = 0;
m_loop_count = 0;

View File

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

View File

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

View File

@ -3,6 +3,7 @@
#include "Utilities/Log.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/RSX/GSManager.h"
#include "RSXThread.h"
#include "Emu/SysCalls/Callback.h"
@ -45,15 +46,40 @@ void RSXThread::nativeRescale(float width, float height)
u32 GetAddress(u32 offset, u32 location)
{
u32 res = 0;
switch(location)
{
case CELL_GCM_LOCATION_LOCAL: return (u32)Memory.RSXFBMem.GetStartAddr() + offset;
case CELL_GCM_LOCATION_MAIN: return (u32)Memory.RSXIOMem.RealAddr(Memory.RSXIOMem.GetStartAddr() + offset); // TODO: Error Check?
case CELL_GCM_LOCATION_LOCAL:
{
res = (u32)Memory.RSXFBMem.GetStartAddr() + offset;
break;
}
case CELL_GCM_LOCATION_MAIN:
{
res = (u32)Memory.RSXIOMem.RealAddr(offset); // TODO: Error Check?
if (res == 0)
{
LOG_ERROR(RSX, "GetAddress(offset=0x%x): RSXIO memory not mapped", offset);
Emu.Pause();
break;
}
if (Emu.GetGSManager().GetRender().m_strict_ordering[offset >> 20])
{
_mm_mfence(); // probably doesn't have any effect on current implementation
}
break;
}
default:
{
LOG_ERROR(RSX, "GetAddress(offset=0x%x, location=0x%x): invalid location", offset, location);
Emu.Pause();
break;
}
}
LOG_ERROR(RSX, "GetAddress(offset=0x%x, location=0x%x)", location);
assert(0);
return 0;
return res;
}
RSXVertexData::RSXVertexData()
@ -144,7 +170,7 @@ u32 RSXVertexData::GetTypeSize()
u32 RSXThread::OutOfArgsCount(const uint x, const u32 cmd, const u32 count, const u32 args_addr)
{
auto args = vm::ptr<be_t<u32>>::make(args_addr);
auto args = vm::ptr<u32>::make(args_addr);
std::string debug = GetMethodName(cmd);
debug += "(";
for(u32 i=0; i<count; ++i) debug += (i ? ", " : "") + fmt::Format("0x%x", ARGS(i));
@ -211,7 +237,7 @@ u32 RSXThread::OutOfArgsCount(const uint x, const u32 cmd, const u32 count, cons
void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const u32 count)
{
auto args = vm::ptr<be_t<u32>>::make(args_addr);
auto args = vm::ptr<u32>::make(args_addr);
#if CMD_DEBUG
std::string debug = GetMethodName(cmd);
@ -239,7 +265,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV406E_SET_CONTEXT_DMA_SEMAPHORE:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV406E_SET_CONTEXT_DMA_SEMAPHORE: %x", ARGS(0));
LOG_WARNING(RSX, "NV406E_SET_CONTEXT_DMA_SEMAPHORE: 0x%x", ARGS(0));
}
break;
@ -254,7 +280,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV406E_SEMAPHORE_ACQUIRE:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV406E_SEMAPHORE_ACQUIRE: %x", ARGS(0));
LOG_WARNING(RSX, "NV406E_SEMAPHORE_ACQUIRE: 0x%x", ARGS(0));
}
break;
@ -315,21 +341,21 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_NOTIFY:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV4097_NOTIFY: %x", ARGS(0));
LOG_WARNING(RSX, "NV4097_NOTIFY: 0x%x", ARGS(0));
}
break;
case NV4097_WAIT_FOR_IDLE:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV4097_WAIT_FOR_IDLE: %x", ARGS(0));
LOG_WARNING(RSX, "NV4097_WAIT_FOR_IDLE: 0x%x", ARGS(0));
}
break;
case NV4097_PM_TRIGGER:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV4097_PM_TRIGGER: %x", ARGS(0));
LOG_WARNING(RSX, "NV4097_PM_TRIGGER: 0x%x", ARGS(0));
}
break;
@ -458,7 +484,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_SET_VERTEX_ATTRIB_INPUT_MASK:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV4097_SET_VERTEX_ATTRIB_INPUT_MASK: %x", ARGS(0));
LOG_WARNING(RSX, "NV4097_SET_VERTEX_ATTRIB_INPUT_MASK: 0x%x", ARGS(0));
//VertexData[0].prog.attributeInputMask = ARGS(0);
}
@ -467,7 +493,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK: %x", ARGS(0));
LOG_WARNING(RSX, "NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK: 0x%x", ARGS(0));
//VertexData[0].prog.attributeOutputMask = ARGS(0);
//FragmentData.prog.attributeInputMask = ARGS(0)/* & ~0x20*/;
@ -490,7 +516,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_SET_COLOR_MASK_MRT:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV4097_SET_COLOR_MASK_MRT: %x", ARGS(0));
LOG_WARNING(RSX, "NV4097_SET_COLOR_MASK_MRT: 0x%x", ARGS(0));
}
break;
@ -829,14 +855,14 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_SET_CLEAR_RECT_HORIZONTAL:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV4097_SET_CLEAR_RECT_HORIZONTAL: %x", ARGS(0));
LOG_WARNING(RSX, "NV4097_SET_CLEAR_RECT_HORIZONTAL: 0x%x", ARGS(0));
}
break;
case NV4097_SET_CLEAR_RECT_VERTICAL:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV4097_SET_CLEAR_RECT_VERTICAL: %x", ARGS(0));
LOG_WARNING(RSX, "NV4097_SET_CLEAR_RECT_VERTICAL: 0x%x", ARGS(0));
}
break;
@ -933,7 +959,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
{
const u32 a0 = ARGS(0);
//LOG_WARNING(RSX, "NV4097_SET_BEGIN_END: %x", a0);
//LOG_WARNING(RSX, "NV4097_SET_BEGIN_END: 0x%x", a0);
m_read_buffer = false;
@ -1066,7 +1092,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_INVALIDATE_L2:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV4097_INVALIDATE_L2: %x", ARGS(0));
LOG_WARNING(RSX, "NV4097_INVALIDATE_L2: 0x%x", ARGS(0));
}
break;
@ -1085,7 +1111,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_INVALIDATE_ZCULL:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV4097_INVALIDATE_ZCULL: %x", ARGS(0));
LOG_WARNING(RSX, "NV4097_INVALIDATE_ZCULL: 0x%x", ARGS(0));
}
break;
@ -1249,7 +1275,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_SET_SCULL_CONTROL:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV4097_SET_SCULL_CONTROL: %x", ARGS(0));
LOG_WARNING(RSX, "NV4097_SET_SCULL_CONTROL: 0x%x", ARGS(0));
//This is stencil culling , nothing to do with stencil masking on regular color or depth buffer
//const u32 a0 = ARGS(0);
@ -1287,7 +1313,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_SET_POINT_PARAMS_ENABLE:
{
if (ARGS(0))
LOG_ERROR(RSX, "NV4097_SET_POINT_PARAMS_ENABLE: %x", ARGS(0));
LOG_ERROR(RSX, "NV4097_SET_POINT_PARAMS_ENABLE: 0x%x", ARGS(0));
}
break;
@ -1427,7 +1453,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_SET_SURFACE_PITCH_D:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV4097_SET_SURFACE_PITCH_D: %x", ARGS(0));
LOG_WARNING(RSX, "NV4097_SET_SURFACE_PITCH_D: 0x%x", ARGS(0));
}
break;
@ -1467,7 +1493,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_SET_CONTEXT_DMA_COLOR_D:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV4097_SET_CONTEXT_DMA_COLOR_D: %x", ARGS(0));
LOG_WARNING(RSX, "NV4097_SET_CONTEXT_DMA_COLOR_D: 0x%x", ARGS(0));
}
break;
@ -1481,14 +1507,14 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_SET_CONTEXT_DMA_SEMAPHORE:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV4097_SET_CONTEXT_DMA_SEMAPHORE: %x", ARGS(0));
LOG_WARNING(RSX, "NV4097_SET_CONTEXT_DMA_SEMAPHORE: 0x%x", ARGS(0));
}
break;
case NV4097_SET_CONTEXT_DMA_NOTIFIES:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV4097_SET_CONTEXT_DMA_NOTIFIES: %x", ARGS(0));
LOG_WARNING(RSX, "NV4097_SET_CONTEXT_DMA_NOTIFIES: 0x%x", ARGS(0));
}
break;
@ -1529,7 +1555,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
const u8 alphaToOne = (a0 >> 8) & 0xf;
const u16 sampleMask = a0 >> 16;
LOG_WARNING(RSX, "TODO: NV4097_SET_ANTI_ALIASING_CONTROL: %x", a0);
LOG_WARNING(RSX, "TODO: NV4097_SET_ANTI_ALIASING_CONTROL: 0x%x", a0);
}
break;
@ -1599,7 +1625,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_SET_ZCULL_CONTROL0:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV4097_SET_ZCULL_CONTROL0: %x", ARGS(0));
LOG_WARNING(RSX, "NV4097_SET_ZCULL_CONTROL0: 0x%x", ARGS(0));
//m_set_depth_func = true;
//m_depth_func = ARGS(0) >> 4;
@ -1609,7 +1635,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_SET_ZCULL_CONTROL1:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV4097_SET_ZCULL_CONTROL1: %x", ARGS(0));
LOG_WARNING(RSX, "NV4097_SET_ZCULL_CONTROL1: 0x%x", ARGS(0));
//m_set_depth_func = true;
//m_depth_func = ARGS(0) >> 4;
@ -1619,14 +1645,14 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV4097_SET_ZCULL_STATS_ENABLE:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV4097_SET_ZCULL_STATS_ENABLE: %x", ARGS(0));
LOG_WARNING(RSX, "NV4097_SET_ZCULL_STATS_ENABLE: 0x%x", ARGS(0));
}
break;
case NV4097_ZCULL_SYNC:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV4097_ZCULL_SYNC: %x", ARGS(0));
LOG_WARNING(RSX, "NV4097_ZCULL_SYNC: 0x%x", ARGS(0));
}
break;
@ -1745,7 +1771,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
{
const u32 offset = ARGS(0) & 0xffffff;
const u8 mode = ARGS(0) >> 24;
LOG_WARNING(RSX, "NV4097_SET_RENDER_ENABLE: Offset=%06x, Mode=%x", offset, mode);
LOG_WARNING(RSX, "NV4097_SET_RENDER_ENABLE: Offset=0x%06x, Mode=0x%x", offset, mode);
}
break;
@ -1812,14 +1838,14 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV0039_PITCH_IN:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV0039_PITCH_IN: %x", ARGS(0));
LOG_WARNING(RSX, "NV0039_PITCH_IN: 0x%x", ARGS(0));
}
break;
case NV0039_BUFFER_NOTIFY:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV0039_BUFFER_NOTIFY: %x", ARGS(0));
LOG_WARNING(RSX, "NV0039_BUFFER_NOTIFY: 0x%x", ARGS(0));
}
break;
@ -1848,7 +1874,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
case NV309E_SET_CONTEXT_DMA_IMAGE:
{
if (ARGS(0))
LOG_WARNING(RSX, "NV309E_SET_CONTEXT_DMA_IMAGE: %x", ARGS(0));
LOG_WARNING(RSX, "NV309E_SET_CONTEXT_DMA_IMAGE: 0x%x", ARGS(0));
}
break;
@ -1947,13 +1973,17 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const
u8* pixels_src = vm::get_ptr<u8>(GetAddress(offset, m_context_dma_img_src - 0xfeed0000));
u8* pixels_dst = vm::get_ptr<u8>(GetAddress(m_dst_offset, m_context_dma_img_dst - 0xfeed0000));
LOG_WARNING(RSX, "NV3089_IMAGE_IN_SIZE: width=%d, height=%d, pitch=%d, origin=%d, inter=%d, offset=0x%x, u=%d, v=%d", width, height, pitch, origin, inter, offset, u, v);
LOG_WARNING(RSX, "*** m_dst_offset=0x%x, m_color: conv_in_h=0x%x, format_src_pitch=0x%x, conv_in_x=0x%x, conv_in_y=0x%x, conv_out_x=0x%x, conv_out_y=0x%x",
m_dst_offset, m_color_conv_in_h, m_color_format_src_pitch, m_color_conv_in_x, m_color_conv_in_y, m_color_conv_out_x, m_color_conv_out_y);
for(u16 y=0; y<m_color_conv_in_h; ++y)
{
for(u16 x=0; x<m_color_format_src_pitch/4/*m_color_conv_in_w*/; ++x)
{
const u32 src_offset = (m_color_conv_in_y + y) * m_color_format_src_pitch + (m_color_conv_in_x + x) * 4;
const u32 dst_offset = (m_color_conv_out_y + y) * m_color_format_dst_pitch + (m_color_conv_out_x + x) * 4;
(u32&)pixels_dst[dst_offset] = (u32&)pixels_src[src_offset];
//(u32&)pixels_dst[dst_offset] = (u32&)pixels_src[src_offset];
}
}
}
@ -2201,6 +2231,11 @@ void RSXThread::Task()
const u32 count = (cmd >> 18) & 0x7ff;
//if(cmd == 0) continue;
if (Ini.RSXLogging.GetValue())
LOG_NOTICE(Log::RSX, "%s (cmd=0x%x)", GetMethodName(cmd & 0xffff).c_str(), cmd);
//LOG_NOTICE(Log::RSX, "put=0x%x, get=0x%x, cmd=0x%x (%s)", put, get, cmd, GetMethodName(cmd & 0xffff).c_str());
if(cmd & CELL_GCM_METHOD_FLAG_JUMP)
{
u32 addr = cmd & ~(CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_NON_INCREMENT);
@ -2212,7 +2247,7 @@ void RSXThread::Task()
{
m_call_stack.push(get + 4);
u32 offs = cmd & ~CELL_GCM_METHOD_FLAG_CALL;
//u32 addr = Memory.RSXIOMem.GetStartAddr() + offs;
//u32 addr = offs;
//LOG_WARNING(RSX, "rsx call(0x%x) #0x%x - 0x%x - 0x%x", offs, addr, cmd, get);
m_ctrl->get = offs;
continue;
@ -2229,19 +2264,19 @@ void RSXThread::Task()
if(cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT)
{
//LOG_WARNING(RSX, "non increment cmd! 0x%x", cmd);
inc=0;
inc = 0;
}
if(cmd == 0)
{
//HACK! We couldn't be here
//ConLog.Error("null cmd: addr=0x%x, put=0x%x, get=0x%x", Memory.RSXIOMem.GetStartAddr() + get, m_ctrl->put, get);
LOG_ERROR(Log::RSX, "null cmd: cmd=0x%x, put=0x%x, get=0x%x (addr=0x%x)", cmd, put, get, (u32)Memory.RSXIOMem.RealAddr(get));
//Emu.Pause();
//HACK! We shouldn't be here
m_ctrl->get = get + (count + 1) * 4;
continue;
}
auto args = vm::ptr<be_t<u32>>::make((u32)Memory.RSXIOMem.RealAddr(Memory.RSXIOMem.GetStartAddr() + get + 4));
auto args = vm::ptr<u32>::make((u32)Memory.RSXIOMem.RealAddr(get + 4));
for(u32 i=0; i<count; i++)
{
@ -2295,7 +2330,7 @@ void RSXThread::Init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddres
u32 RSXThread::ReadIO32(u32 addr)
{
u32 value;
if (!Memory.RSXIOMem.Read32(Memory.RSXIOMem.GetStartAddr() + addr, &value))
if (!Memory.RSXIOMem.Read32(addr, &value))
{
throw fmt::Format("%s(rsxio_addr=0x%x): RSXIO memory not mapped", __FUNCTION__, addr);
}
@ -2304,7 +2339,7 @@ u32 RSXThread::ReadIO32(u32 addr)
void RSXThread::WriteIO32(u32 addr, u32 value)
{
if (!Memory.RSXIOMem.Write32(Memory.RSXIOMem.GetStartAddr() + addr, value))
if (!Memory.RSXIOMem.Write32(addr, value))
{
throw fmt::Format("%s(rsxio_addr=0x%x): RSXIO memory not mapped", __FUNCTION__, addr);
}

View File

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

View File

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

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