mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-13 10:18:40 +12:00
Merge pull request #992 from Nekotekina/master
Reservations reimplemented
This commit is contained in:
commit
71292a7617
40 changed files with 2929 additions and 682 deletions
|
@ -109,7 +109,15 @@ struct FileListener : LogListener
|
||||||
if (mPrependChannelName)
|
if (mPrependChannelName)
|
||||||
{
|
{
|
||||||
text.insert(0, gTypeNameTable[static_cast<u32>(msg.mType)].mName);
|
text.insert(0, gTypeNameTable[static_cast<u32>(msg.mType)].mName);
|
||||||
|
|
||||||
|
if (msg.mType == Log::TTY)
|
||||||
|
{
|
||||||
|
text = fmt::escape(text);
|
||||||
|
if (text[text.length() - 1] != '\n')
|
||||||
|
{
|
||||||
|
text += '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mFile.Write(text);
|
mFile.Write(text);
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,7 +179,7 @@ std::string fmt::replace_all(const std::string &src, const std::string& from, co
|
||||||
pos += to.length();
|
pos += to.length();
|
||||||
}
|
}
|
||||||
|
|
||||||
return src;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: move this wx Stuff somewhere else
|
//TODO: move this wx Stuff somewhere else
|
||||||
|
@ -339,3 +339,34 @@ std::string fmt::tolower(std::string source)
|
||||||
|
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string fmt::toupper(std::string source)
|
||||||
|
{
|
||||||
|
std::transform(source.begin(), source.end(), source.begin(), ::toupper);
|
||||||
|
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string fmt::escape(std::string source)
|
||||||
|
{
|
||||||
|
const std::pair<std::string, std::string> escape_list[] =
|
||||||
|
{
|
||||||
|
{ "\\", "\\\\" },
|
||||||
|
{ "\a", "\\a" },
|
||||||
|
{ "\b", "\\b" },
|
||||||
|
{ "\f", "\\f" },
|
||||||
|
{ "\n", "\\n\n" },
|
||||||
|
{ "\r", "\\r" },
|
||||||
|
{ "\t", "\\t" },
|
||||||
|
{ "\v", "\\v" },
|
||||||
|
};
|
||||||
|
|
||||||
|
source = fmt::replace_all(source, escape_list);
|
||||||
|
|
||||||
|
for (char c = 0; c < 32; c++)
|
||||||
|
{
|
||||||
|
if (c != '\n') source = fmt::replace_all(source, std::string(1, c), fmt::Format("\\x%02X", c));
|
||||||
|
}
|
||||||
|
|
||||||
|
return source;
|
||||||
|
}
|
||||||
|
|
|
@ -177,6 +177,8 @@ namespace fmt
|
||||||
std::string to_udec(u64 value);
|
std::string to_udec(u64 value);
|
||||||
std::string to_sdec(s64 value);
|
std::string to_sdec(s64 value);
|
||||||
|
|
||||||
|
std::string toupper(std::string source);
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
size_t get_fmt_start(const char* fmt, size_t len);
|
size_t get_fmt_start(const char* fmt, size_t len);
|
||||||
|
@ -198,6 +200,10 @@ namespace fmt
|
||||||
{
|
{
|
||||||
return to_hex(arg, get_fmt_precision(fmt, len));
|
return to_hex(arg, get_fmt_precision(fmt, len));
|
||||||
}
|
}
|
||||||
|
else if (fmt[len - 1] == 'X')
|
||||||
|
{
|
||||||
|
return fmt::toupper(to_hex(arg, get_fmt_precision(fmt, len)));
|
||||||
|
}
|
||||||
else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u')
|
else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u')
|
||||||
{
|
{
|
||||||
return to_udec(arg);
|
return to_udec(arg);
|
||||||
|
@ -218,6 +224,10 @@ namespace fmt
|
||||||
{
|
{
|
||||||
return to_hex(arg, get_fmt_precision(fmt, len));
|
return to_hex(arg, get_fmt_precision(fmt, len));
|
||||||
}
|
}
|
||||||
|
else if (fmt[len - 1] == 'X')
|
||||||
|
{
|
||||||
|
return fmt::toupper(to_hex(arg, get_fmt_precision(fmt, len)));
|
||||||
|
}
|
||||||
else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u')
|
else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u')
|
||||||
{
|
{
|
||||||
return to_udec(arg);
|
return to_udec(arg);
|
||||||
|
@ -238,6 +248,10 @@ namespace fmt
|
||||||
{
|
{
|
||||||
return to_hex(arg, get_fmt_precision(fmt, len));
|
return to_hex(arg, get_fmt_precision(fmt, len));
|
||||||
}
|
}
|
||||||
|
else if (fmt[len - 1] == 'X')
|
||||||
|
{
|
||||||
|
return fmt::toupper(to_hex(arg, get_fmt_precision(fmt, len)));
|
||||||
|
}
|
||||||
else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u')
|
else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u')
|
||||||
{
|
{
|
||||||
return to_udec(arg);
|
return to_udec(arg);
|
||||||
|
@ -258,6 +272,10 @@ namespace fmt
|
||||||
{
|
{
|
||||||
return to_hex(arg, get_fmt_precision(fmt, len));
|
return to_hex(arg, get_fmt_precision(fmt, len));
|
||||||
}
|
}
|
||||||
|
else if (fmt[len - 1] == 'X')
|
||||||
|
{
|
||||||
|
return fmt::toupper(to_hex(arg, get_fmt_precision(fmt, len)));
|
||||||
|
}
|
||||||
else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u')
|
else if (fmt[len - 1] == 'd' || fmt[len - 1] == 'u')
|
||||||
{
|
{
|
||||||
return to_udec(arg);
|
return to_udec(arg);
|
||||||
|
@ -278,6 +296,10 @@ namespace fmt
|
||||||
{
|
{
|
||||||
return to_hex((u8)arg, get_fmt_precision(fmt, len));
|
return to_hex((u8)arg, get_fmt_precision(fmt, len));
|
||||||
}
|
}
|
||||||
|
else if (fmt[len - 1] == 'X')
|
||||||
|
{
|
||||||
|
return fmt::toupper(to_hex((u8)arg, get_fmt_precision(fmt, len)));
|
||||||
|
}
|
||||||
else if (fmt[len - 1] == 'd')
|
else if (fmt[len - 1] == 'd')
|
||||||
{
|
{
|
||||||
return to_sdec(arg);
|
return to_sdec(arg);
|
||||||
|
@ -298,6 +320,10 @@ namespace fmt
|
||||||
{
|
{
|
||||||
return to_hex((u16)arg, get_fmt_precision(fmt, len));
|
return to_hex((u16)arg, get_fmt_precision(fmt, len));
|
||||||
}
|
}
|
||||||
|
else if (fmt[len - 1] == 'X')
|
||||||
|
{
|
||||||
|
return fmt::toupper(to_hex((u16)arg, get_fmt_precision(fmt, len)));
|
||||||
|
}
|
||||||
else if (fmt[len - 1] == 'd')
|
else if (fmt[len - 1] == 'd')
|
||||||
{
|
{
|
||||||
return to_sdec(arg);
|
return to_sdec(arg);
|
||||||
|
@ -318,6 +344,10 @@ namespace fmt
|
||||||
{
|
{
|
||||||
return to_hex((u32)arg, get_fmt_precision(fmt, len));
|
return to_hex((u32)arg, get_fmt_precision(fmt, len));
|
||||||
}
|
}
|
||||||
|
else if (fmt[len - 1] == 'X')
|
||||||
|
{
|
||||||
|
return fmt::toupper(to_hex((u32)arg, get_fmt_precision(fmt, len)));
|
||||||
|
}
|
||||||
else if (fmt[len - 1] == 'd')
|
else if (fmt[len - 1] == 'd')
|
||||||
{
|
{
|
||||||
return to_sdec(arg);
|
return to_sdec(arg);
|
||||||
|
@ -338,6 +368,10 @@ namespace fmt
|
||||||
{
|
{
|
||||||
return to_hex((u64)arg, get_fmt_precision(fmt, len));
|
return to_hex((u64)arg, get_fmt_precision(fmt, len));
|
||||||
}
|
}
|
||||||
|
else if (fmt[len - 1] == 'X')
|
||||||
|
{
|
||||||
|
return fmt::toupper(to_hex((u64)arg, get_fmt_precision(fmt, len)));
|
||||||
|
}
|
||||||
else if (fmt[len - 1] == 'd')
|
else if (fmt[len - 1] == 'd')
|
||||||
{
|
{
|
||||||
return to_sdec(arg);
|
return to_sdec(arg);
|
||||||
|
@ -358,6 +392,10 @@ namespace fmt
|
||||||
{
|
{
|
||||||
return to_hex((u32&)arg, get_fmt_precision(fmt, len));
|
return to_hex((u32&)arg, get_fmt_precision(fmt, len));
|
||||||
}
|
}
|
||||||
|
else if (fmt[len - 1] == 'X')
|
||||||
|
{
|
||||||
|
return fmt::toupper(to_hex((u32&)arg, get_fmt_precision(fmt, len)));
|
||||||
|
}
|
||||||
else if (fmt[len - 1] == 'f')
|
else if (fmt[len - 1] == 'f')
|
||||||
{
|
{
|
||||||
return std::to_string(arg);
|
return std::to_string(arg);
|
||||||
|
@ -378,6 +416,10 @@ namespace fmt
|
||||||
{
|
{
|
||||||
return to_hex((u64&)arg, get_fmt_precision(fmt, len));
|
return to_hex((u64&)arg, get_fmt_precision(fmt, len));
|
||||||
}
|
}
|
||||||
|
else if (fmt[len - 1] == 'X')
|
||||||
|
{
|
||||||
|
return fmt::toupper(to_hex((u64&)arg, get_fmt_precision(fmt, len)));
|
||||||
|
}
|
||||||
else if (fmt[len - 1] == 'f')
|
else if (fmt[len - 1] == 'f')
|
||||||
{
|
{
|
||||||
return std::to_string(arg);
|
return std::to_string(arg);
|
||||||
|
@ -394,7 +436,7 @@ namespace fmt
|
||||||
{
|
{
|
||||||
static std::string text(const char* fmt, size_t len, bool arg)
|
static std::string text(const char* fmt, size_t len, bool arg)
|
||||||
{
|
{
|
||||||
if (fmt[len - 1] == 'x')
|
if (fmt[len - 1] == 'x' || fmt[len - 1] == 'X')
|
||||||
{
|
{
|
||||||
return to_hex(arg, get_fmt_precision(fmt, len));
|
return to_hex(arg, get_fmt_precision(fmt, len));
|
||||||
}
|
}
|
||||||
|
@ -579,4 +621,6 @@ namespace fmt
|
||||||
std::string merge(std::vector<std::string> source, const std::string& separator);
|
std::string merge(std::vector<std::string> source, const std::string& separator);
|
||||||
std::string merge(std::initializer_list<std::vector<std::string>> sources, const std::string& separator);
|
std::string merge(std::initializer_list<std::vector<std::string>> sources, const std::string& separator);
|
||||||
std::string tolower(std::string source);
|
std::string tolower(std::string source);
|
||||||
|
std::string toupper(std::string source);
|
||||||
|
std::string escape(std::string source);
|
||||||
}
|
}
|
||||||
|
|
|
@ -215,7 +215,8 @@ static const reg_table_t reg_table[17] =
|
||||||
|
|
||||||
bool handle_access_violation(const u32 addr, x64_context* context)
|
bool handle_access_violation(const u32 addr, x64_context* context)
|
||||||
{
|
{
|
||||||
if (addr - RAW_SPU_BASE_ADDR < (6 * RAW_SPU_OFFSET) && (addr % RAW_SPU_OFFSET) >= RAW_SPU_PROB_OFFSET) // RawSPU MMIO registers
|
// check if address is RawSPU MMIO register
|
||||||
|
if (addr - RAW_SPU_BASE_ADDR < (6 * RAW_SPU_OFFSET) && (addr % RAW_SPU_OFFSET) >= RAW_SPU_PROB_OFFSET)
|
||||||
{
|
{
|
||||||
// one x64 instruction is manually decoded and interpreted
|
// one x64 instruction is manually decoded and interpreted
|
||||||
x64_op_t op;
|
x64_op_t op;
|
||||||
|
@ -277,6 +278,12 @@ bool handle_access_violation(const u32 addr, x64_context* context)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if fault is caused by reservation
|
||||||
|
if (vm::reservation_query(addr))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: allow recovering from a page fault as a feature of PS3 virtual memory
|
// TODO: allow recovering from a page fault as a feature of PS3 virtual memory
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -303,6 +310,24 @@ void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp)
|
||||||
// else some fatal error (should crash)
|
// else some fatal error (should crash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern LPTOP_LEVEL_EXCEPTION_FILTER filter_set;
|
||||||
|
|
||||||
|
LONG __stdcall exception_filter(_EXCEPTION_POINTERS* pExp)
|
||||||
|
{
|
||||||
|
_se_translator(pExp->ExceptionRecord->ExceptionCode, pExp);
|
||||||
|
|
||||||
|
if (filter_set)
|
||||||
|
{
|
||||||
|
return filter_set(pExp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return EXCEPTION_CONTINUE_SEARCH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LPTOP_LEVEL_EXCEPTION_FILTER filter_set = SetUnhandledExceptionFilter(exception_filter);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
void signal_handler(int sig, siginfo_t* info, void* uct)
|
void signal_handler(int sig, siginfo_t* info, void* uct)
|
||||||
|
@ -352,6 +377,11 @@ void SetCurrentNamedThread(NamedThreadBase* value)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (old_value)
|
||||||
|
{
|
||||||
|
vm::reservation_free();
|
||||||
|
}
|
||||||
|
|
||||||
if (value && value->m_tls_assigned.exchange(true))
|
if (value && value->m_tls_assigned.exchange(true))
|
||||||
{
|
{
|
||||||
LOG_ERROR(GENERAL, "Thread '%s' was already assigned to g_tls_this_thread of another thread", value->GetThreadName());
|
LOG_ERROR(GENERAL, "Thread '%s' was already assigned to g_tls_this_thread of another thread", value->GetThreadName());
|
||||||
|
|
|
@ -10,17 +10,15 @@ enum ARMv7InstructionSet
|
||||||
ThumbEE
|
ThumbEE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum armv7_debug_flags : u32
|
||||||
|
{
|
||||||
|
DF_DISASM = 1 << 0,
|
||||||
|
DF_PRINT = 1 << 1,
|
||||||
|
DF_NO_EXE = 1 << 2,
|
||||||
|
};
|
||||||
|
|
||||||
struct ARMv7Context
|
struct ARMv7Context
|
||||||
{
|
{
|
||||||
ARMv7Thread& thread;
|
|
||||||
|
|
||||||
ARMv7Context(ARMv7Thread& thread) : thread(thread) {}
|
|
||||||
|
|
||||||
void write_pc(u32 value);
|
|
||||||
u32 read_pc();
|
|
||||||
u32 get_stack_arg(u32 pos);
|
|
||||||
void fast_call(u32 addr);
|
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
u32 GPR[15];
|
u32 GPR[15];
|
||||||
|
@ -116,9 +114,6 @@ struct ARMv7Context
|
||||||
|
|
||||||
u32 TLS;
|
u32 TLS;
|
||||||
|
|
||||||
u32 R_ADDR;
|
|
||||||
u64 R_DATA;
|
|
||||||
|
|
||||||
struct perf_counter
|
struct perf_counter
|
||||||
{
|
{
|
||||||
u32 event;
|
u32 event;
|
||||||
|
@ -127,6 +122,18 @@ struct ARMv7Context
|
||||||
|
|
||||||
std::array<perf_counter, 6> counters;
|
std::array<perf_counter, 6> counters;
|
||||||
|
|
||||||
|
ARMv7Thread& thread;
|
||||||
|
|
||||||
|
u32 debug; // debug flags
|
||||||
|
std::string debug_str;
|
||||||
|
|
||||||
|
ARMv7Context(ARMv7Thread& thread) : thread(thread), debug(/*DF_DISASM | DF_PRINT*/ 0) {}
|
||||||
|
|
||||||
|
void write_pc(u32 value);
|
||||||
|
u32 read_pc();
|
||||||
|
u32 get_stack_arg(u32 pos);
|
||||||
|
void fast_call(u32 addr);
|
||||||
|
|
||||||
void write_gpr(u32 n, u32 value)
|
void write_gpr(u32 n, u32 value)
|
||||||
{
|
{
|
||||||
assert(n < 16);
|
assert(n < 16);
|
||||||
|
|
|
@ -30,137 +30,147 @@ struct ARMv7_opcode_t
|
||||||
|
|
||||||
const ARMv7_opcode_t ARMv7_opcode_table[] =
|
const ARMv7_opcode_t ARMv7_opcode_table[] =
|
||||||
{
|
{
|
||||||
ARMv7_OP4(0xffff, 0x0000, 0xf870, 0x0000, T1, HACK), // "Undefined" Thumb opcode used
|
ARMv7_OP4(0xffff, 0x0000, 0xf870, 0x0000, T1, HACK, nullptr), // "Undefined" Thumb opcode used
|
||||||
ARMv7_OP4(0x0ff0, 0x00f0, 0x0070, 0x0090, A1, HACK), // "Undefined" ARM opcode used
|
ARMv7_OP4(0x0ff0, 0x00f0, 0x0070, 0x0090, A1, HACK), // "Undefined" ARM opcode used
|
||||||
|
|
||||||
ARMv7_OP4(0xfbe0, 0x8000, 0xf140, 0x0000, T1, ADC_IMM),
|
ARMv7_OP4(0xfbe0, 0x8000, 0xf140, 0x0000, T1, ADC_IMM, nullptr),
|
||||||
ARMv7_OP4(0x0fe0, 0x0000, 0x02a0, 0x0000, A1, ADC_IMM),
|
ARMv7_OP4(0x0fe0, 0x0000, 0x02a0, 0x0000, A1, ADC_IMM),
|
||||||
ARMv7_OP2(0xffc0, 0x4040, T1, ADC_REG),
|
ARMv7_OP2(0xffc0, 0x4140, T1, ADC_REG, nullptr),
|
||||||
ARMv7_OP4(0xffe0, 0x8000, 0xeb40, 0x0000, T2, ADC_REG),
|
ARMv7_OP4(0xffe0, 0x8000, 0xeb40, 0x0000, T2, ADC_REG, nullptr),
|
||||||
ARMv7_OP4(0x0fe0, 0x0010, 0x00a0, 0x0000, A1, ADC_REG),
|
ARMv7_OP4(0x0fe0, 0x0010, 0x00a0, 0x0000, A1, ADC_REG),
|
||||||
ARMv7_OP4(0x0fe0, 0x0090, 0x00a0, 0x0010, A1, ADC_RSR),
|
ARMv7_OP4(0x0fe0, 0x0090, 0x00a0, 0x0010, A1, ADC_RSR),
|
||||||
|
|
||||||
ARMv7_OP2(0xfe00, 0x1c00, T1, ADD_IMM),
|
ARMv7_OP2(0xfe00, 0x1c00, T1, ADD_IMM, nullptr),
|
||||||
ARMv7_OP2(0xf800, 0x3000, T2, ADD_IMM),
|
ARMv7_OP2(0xf800, 0x3000, T2, ADD_IMM, nullptr),
|
||||||
ARMv7_OP4(0xfbe0, 0x8000, 0xf100, 0x0000, T3, ADD_IMM, SKIP_IF( (BF(8, 11) == 15 && BT(20)) || BF(16, 19) == 13 )),
|
ARMv7_OP4(0xfbe0, 0x8000, 0xf100, 0x0000, T3, ADD_IMM, SKIP_IF( (BF(8, 11) == 15 && BT(20)) || BF(16, 19) == 13 )),
|
||||||
ARMv7_OP4(0xfbf0, 0x8000, 0xf200, 0x0000, T4, ADD_IMM, SKIP_IF( (BF(16, 19) & 13) == 13 )),
|
ARMv7_OP4(0xfbf0, 0x8000, 0xf200, 0x0000, T4, ADD_IMM, SKIP_IF( (BF(16, 19) & 13) == 13 )),
|
||||||
ARMv7_OP4(0x0fe0, 0x0000, 0x0280, 0x0000, A1, ADD_IMM),
|
ARMv7_OP4(0x0fe0, 0x0000, 0x0280, 0x0000, A1, ADD_IMM),
|
||||||
ARMv7_OP2(0xfe00, 0x1800, T1, ADD_REG),
|
ARMv7_OP2(0xfe00, 0x1800, T1, ADD_REG, nullptr),
|
||||||
ARMv7_OP2(0xff00, 0x4400, T2, ADD_REG, SKIP_IF( (c & 0x87) == 0x85 || BF(3, 6) == 13 )),
|
ARMv7_OP2(0xff00, 0x4400, T2, ADD_REG, SKIP_IF( (c & 0x87) == 0x85 || BF(3, 6) == 13 )),
|
||||||
ARMv7_OP4(0xffe0, 0x8000, 0xeb00, 0x0000, T3, ADD_REG, SKIP_IF( (BF(8, 11) == 15 && BT(20)) || BF(16, 19) == 13 )),
|
ARMv7_OP4(0xffe0, 0x8000, 0xeb00, 0x0000, T3, ADD_REG, SKIP_IF( (BF(8, 11) == 15 && BT(20)) || BF(16, 19) == 13 )),
|
||||||
ARMv7_OP4(0x0fe0, 0x0010, 0x0080, 0x0000, A1, ADD_REG),
|
ARMv7_OP4(0x0fe0, 0x0010, 0x0080, 0x0000, A1, ADD_REG),
|
||||||
ARMv7_OP4(0x0fe0, 0x0090, 0x0080, 0x0010, A1, ADD_RSR),
|
ARMv7_OP4(0x0fe0, 0x0090, 0x0080, 0x0010, A1, ADD_RSR),
|
||||||
ARMv7_OP2(0xf800, 0xa800, T1, ADD_SPI),
|
ARMv7_OP2(0xf800, 0xa800, T1, ADD_SPI, nullptr),
|
||||||
ARMv7_OP2(0xff80, 0xb000, T2, ADD_SPI),
|
ARMv7_OP2(0xff80, 0xb000, T2, ADD_SPI, nullptr),
|
||||||
ARMv7_OP4(0xfbef, 0x8000, 0xf10d, 0x0000, T3, ADD_SPI, SKIP_IF( BF(8, 11) == 15 && BT(20) )),
|
ARMv7_OP4(0xfbef, 0x8000, 0xf10d, 0x0000, T3, ADD_SPI, SKIP_IF( BF(8, 11) == 15 && BT(20) )),
|
||||||
ARMv7_OP4(0xfbff, 0x8000, 0xf20d, 0x0000, T4, ADD_SPI),
|
ARMv7_OP4(0xfbff, 0x8000, 0xf20d, 0x0000, T4, ADD_SPI, nullptr),
|
||||||
ARMv7_OP4(0x0fef, 0x0000, 0x028d, 0x0000, A1, ADD_SPI),
|
ARMv7_OP4(0x0fef, 0x0000, 0x028d, 0x0000, A1, ADD_SPI),
|
||||||
ARMv7_OP2(0xff78, 0x4468, T1, ADD_SPR),
|
ARMv7_OP2(0xff78, 0x4468, T1, ADD_SPR, nullptr),
|
||||||
ARMv7_OP2(0xff87, 0x4485, T2, ADD_SPR, SKIP_IF( BF(3, 6) == 13 )),
|
ARMv7_OP2(0xff87, 0x4485, T2, ADD_SPR, SKIP_IF( BF(3, 6) == 13 )),
|
||||||
ARMv7_OP4(0xffef, 0x8000, 0xeb0d, 0x0000, T3, ADD_SPR),
|
ARMv7_OP4(0xffef, 0x8000, 0xeb0d, 0x0000, T3, ADD_SPR, nullptr),
|
||||||
ARMv7_OP4(0x0fef, 0x0010, 0x008d, 0x0000, A1, ADD_SPR),
|
ARMv7_OP4(0x0fef, 0x0010, 0x008d, 0x0000, A1, ADD_SPR),
|
||||||
|
|
||||||
ARMv7_OP2(0xf800, 0xa000, T1, ADR),
|
ARMv7_OP2(0xf800, 0xa000, T1, ADR, nullptr),
|
||||||
ARMv7_OP4(0xfbff, 0x8000, 0xf2af, 0x0000, T2, ADR),
|
ARMv7_OP4(0xfbff, 0x8000, 0xf2af, 0x0000, T2, ADR, nullptr),
|
||||||
ARMv7_OP4(0xfbff, 0x8000, 0xf20f, 0x0000, T3, ADR),
|
ARMv7_OP4(0xfbff, 0x8000, 0xf20f, 0x0000, T3, ADR, nullptr),
|
||||||
ARMv7_OP4(0x0fff, 0x0000, 0x028f, 0x0000, A1, ADR),
|
ARMv7_OP4(0x0fff, 0x0000, 0x028f, 0x0000, A1, ADR),
|
||||||
ARMv7_OP4(0x0fff, 0x0000, 0x024f, 0x0000, A2, ADR),
|
ARMv7_OP4(0x0fff, 0x0000, 0x024f, 0x0000, A2, ADR),
|
||||||
|
|
||||||
ARMv7_OP4(0xfbe0, 0x8000, 0xf000, 0x0000, T1, AND_IMM),
|
ARMv7_OP4(0xfbe0, 0x8000, 0xf000, 0x0000, T1, AND_IMM, SKIP_IF( BF(8, 11) == 15 && BT(20) )),
|
||||||
ARMv7_OP4(0x0fe0, 0x0000, 0x0200, 0x0000, A1, AND_IMM),
|
ARMv7_OP4(0x0fe0, 0x0000, 0x0200, 0x0000, A1, AND_IMM),
|
||||||
ARMv7_OP2(0xffc0, 0x4000, T1, AND_REG),
|
ARMv7_OP2(0xffc0, 0x4000, T1, AND_REG, nullptr),
|
||||||
ARMv7_OP4(0xffe0, 0x8000, 0xea00, 0x0000, T2, AND_REG),
|
ARMv7_OP4(0xffe0, 0x8000, 0xea00, 0x0000, T2, AND_REG, SKIP_IF( BF(8, 11) == 15 && BT(20) )),
|
||||||
ARMv7_OP4(0x0fe0, 0x0010, 0x0000, 0x0000, A1, AND_REG),
|
ARMv7_OP4(0x0fe0, 0x0010, 0x0000, 0x0000, A1, AND_REG),
|
||||||
ARMv7_OP4(0x0fe0, 0x0090, 0x0000, 0x0010, A1, AND_RSR),
|
ARMv7_OP4(0x0fe0, 0x0090, 0x0000, 0x0010, A1, AND_RSR),
|
||||||
|
|
||||||
ARMv7_OP2(0xf800, 0x1000, T1, ASR_IMM),
|
ARMv7_OP2(0xf800, 0x1000, T1, ASR_IMM, nullptr),
|
||||||
ARMv7_OP4(0xffef, 0x8030, 0xea4f, 0x0020, T2, ASR_IMM),
|
ARMv7_OP4(0xffef, 0x8030, 0xea4f, 0x0020, T2, ASR_IMM, nullptr),
|
||||||
ARMv7_OP4(0x0fef, 0x0070, 0x01a0, 0x0040, A1, ASR_IMM),
|
ARMv7_OP4(0x0fef, 0x0070, 0x01a0, 0x0040, A1, ASR_IMM),
|
||||||
ARMv7_OP2(0xffc0, 0x4100, T1, ASR_REG),
|
ARMv7_OP2(0xffc0, 0x4100, T1, ASR_REG, nullptr),
|
||||||
ARMv7_OP4(0xffe0, 0xf0f0, 0xfa40, 0xf000, T2, ASR_REG),
|
ARMv7_OP4(0xffe0, 0xf0f0, 0xfa40, 0xf000, T2, ASR_REG, nullptr),
|
||||||
ARMv7_OP4(0x0fef, 0x00f0, 0x01a0, 0x0050, A1, ASR_REG),
|
ARMv7_OP4(0x0fef, 0x00f0, 0x01a0, 0x0050, A1, ASR_REG),
|
||||||
|
|
||||||
ARMv7_OP2(0xf000, 0xd000, T1, B),
|
ARMv7_OP2(0xf000, 0xd000, T1, B, SKIP_IF( BF(9, 11) == 0x7 )),
|
||||||
ARMv7_OP2(0xf800, 0xe000, T2, B),
|
ARMv7_OP2(0xf800, 0xe000, T2, B, nullptr),
|
||||||
ARMv7_OP4(0xf800, 0xd000, 0xf000, 0x8000, T3, B),
|
ARMv7_OP4(0xf800, 0xd000, 0xf000, 0x8000, T3, B, SKIP_IF( BF(23, 25) == 0x7 )),
|
||||||
ARMv7_OP4(0xf800, 0xd000, 0xf000, 0x9000, T4, B),
|
ARMv7_OP4(0xf800, 0xd000, 0xf000, 0x9000, T4, B, nullptr),
|
||||||
ARMv7_OP4(0x0f00, 0x0000, 0x0a00, 0x0000, A1, B),
|
ARMv7_OP4(0x0f00, 0x0000, 0x0a00, 0x0000, A1, B),
|
||||||
|
|
||||||
ARMv7_OP4(0xffff, 0x8020, 0xf36f, 0x0000, T1, BFC),
|
ARMv7_OP4(0xffff, 0x8020, 0xf36f, 0x0000, T1, BFC, nullptr),
|
||||||
ARMv7_OP4(0x0fe0, 0x007f, 0x07c0, 0x001f, A1, BFC),
|
ARMv7_OP4(0x0fe0, 0x007f, 0x07c0, 0x001f, A1, BFC),
|
||||||
ARMv7_OP4(0xfff0, 0x8020, 0xf360, 0x0000, T1, BFI),
|
|
||||||
|
ARMv7_OP4(0xfff0, 0x8020, 0xf360, 0x0000, T1, BFI, SKIP_IF( BF(16, 19) == 15 )),
|
||||||
ARMv7_OP4(0x0fe0, 0x0070, 0x07c0, 0x0010, A1, BFI),
|
ARMv7_OP4(0x0fe0, 0x0070, 0x07c0, 0x0010, A1, BFI),
|
||||||
|
|
||||||
ARMv7_OP4(0xfbe0, 0x8000, 0xf020, 0x0000, T1, BIC_IMM),
|
ARMv7_OP4(0xfbe0, 0x8000, 0xf020, 0x0000, T1, BIC_IMM, nullptr),
|
||||||
ARMv7_OP4(0x0fe0, 0x0000, 0x03c0, 0x0000, A1, BIC_IMM),
|
ARMv7_OP4(0x0fe0, 0x0000, 0x03c0, 0x0000, A1, BIC_IMM),
|
||||||
ARMv7_OP2(0xffc0, 0x4380, T1, BIC_REG),
|
ARMv7_OP2(0xffc0, 0x4380, T1, BIC_REG, nullptr),
|
||||||
ARMv7_OP4(0xffe0, 0x8000, 0xea20, 0x0000, T2, BIC_REG),
|
ARMv7_OP4(0xffe0, 0x8000, 0xea20, 0x0000, T2, BIC_REG, nullptr),
|
||||||
ARMv7_OP4(0x0fe0, 0x0010, 0x01c0, 0x0000, A1, BIC_REG),
|
ARMv7_OP4(0x0fe0, 0x0010, 0x01c0, 0x0000, A1, BIC_REG),
|
||||||
ARMv7_OP4(0x0fe0, 0x0090, 0x01c0, 0x0010, A1, BIC_RSR),
|
ARMv7_OP4(0x0fe0, 0x0090, 0x01c0, 0x0010, A1, BIC_RSR),
|
||||||
|
|
||||||
ARMv7_OP2(0xff00, 0xbe00, T1, BKPT),
|
ARMv7_OP2(0xff00, 0xbe00, T1, BKPT, nullptr),
|
||||||
ARMv7_OP4(0x0ff0, 0x00f0, 0x0120, 0x0070, A1, BKPT),
|
ARMv7_OP4(0x0ff0, 0x00f0, 0x0120, 0x0070, A1, BKPT),
|
||||||
|
|
||||||
ARMv7_OP4(0xf800, 0xd000, 0xf000, 0xd000, T1, BL),
|
ARMv7_OP4(0xf800, 0xd000, 0xf000, 0xd000, T1, BL, nullptr),
|
||||||
ARMv7_OP4(0x0f00, 0x0000, 0x0b00, 0x0000, A1, BL),
|
ARMv7_OP4(0x0f00, 0x0000, 0x0b00, 0x0000, A1, BL),
|
||||||
ARMv7_OP2(0xff80, 0x4780, T1, BLX),
|
ARMv7_OP2(0xff80, 0x4780, T1, BLX, nullptr),
|
||||||
ARMv7_OP4(0xf800, 0xc001, 0xf000, 0xc000, T2, BLX),
|
ARMv7_OP4(0xf800, 0xc001, 0xf000, 0xc000, T2, BLX, nullptr),
|
||||||
ARMv7_OP4(0x0fff, 0xfff0, 0x012f, 0xff30, A1, BLX),
|
ARMv7_OP4(0x0fff, 0xfff0, 0x012f, 0xff30, A1, BLX),
|
||||||
ARMv7_OP4(0xfe00, 0x0000, 0xfa00, 0x0000, A2, BLX),
|
ARMv7_OP4(0xfe00, 0x0000, 0xfa00, 0x0000, A2, BLX),
|
||||||
|
|
||||||
ARMv7_OP2(0xff87, 0x4700, T1, BX),
|
ARMv7_OP2(0xff87, 0x4700, T1, BX, nullptr),
|
||||||
ARMv7_OP4(0x0fff, 0xfff0, 0x012f, 0xff10, A1, BX),
|
ARMv7_OP4(0x0fff, 0xfff0, 0x012f, 0xff10, A1, BX),
|
||||||
|
|
||||||
ARMv7_OP2(0xf500, 0xb100, T1, CB_Z),
|
ARMv7_OP2(0xf500, 0xb100, T1, CB_Z, nullptr),
|
||||||
|
|
||||||
ARMv7_OP4(0xfff0, 0xf0f0, 0xfab0, 0xf080, T1, CLZ),
|
ARMv7_OP4(0xfff0, 0xf0f0, 0xfab0, 0xf080, T1, CLZ, nullptr),
|
||||||
ARMv7_OP4(0x0fff, 0x0ff0, 0x016f, 0x0f10, A1, CLZ),
|
ARMv7_OP4(0x0fff, 0x0ff0, 0x016f, 0x0f10, A1, CLZ),
|
||||||
|
|
||||||
ARMv7_OP4(0xfbf0, 0x8f00, 0xf110, 0x0f00, T1, CMN_IMM),
|
ARMv7_OP4(0xfbf0, 0x8f00, 0xf110, 0x0f00, T1, CMN_IMM, nullptr),
|
||||||
ARMv7_OP4(0x0ff0, 0xf000, 0x0370, 0x0000, A1, CMN_IMM),
|
ARMv7_OP4(0x0ff0, 0xf000, 0x0370, 0x0000, A1, CMN_IMM),
|
||||||
ARMv7_OP2(0xffc0, 0x42c0, T1, CMN_REG),
|
ARMv7_OP2(0xffc0, 0x42c0, T1, CMN_REG, nullptr),
|
||||||
ARMv7_OP4(0xfff0, 0x8f00, 0xeb10, 0x0f00, T2, CMN_REG),
|
ARMv7_OP4(0xfff0, 0x8f00, 0xeb10, 0x0f00, T2, CMN_REG, nullptr),
|
||||||
ARMv7_OP4(0x0ff0, 0xf010, 0x0170, 0x0000, A1, CMN_REG),
|
ARMv7_OP4(0x0ff0, 0xf010, 0x0170, 0x0000, A1, CMN_REG),
|
||||||
ARMv7_OP4(0x0ff0, 0xf090, 0x0170, 0x0010, A1, CMN_RSR),
|
ARMv7_OP4(0x0ff0, 0xf090, 0x0170, 0x0010, A1, CMN_RSR),
|
||||||
|
|
||||||
ARMv7_OP2(0xf800, 0x2800, T1, CMP_IMM),
|
ARMv7_OP2(0xf800, 0x2800, T1, CMP_IMM, nullptr),
|
||||||
ARMv7_OP4(0xfbf0, 0x8f00, 0xf1b0, 0x0f00, T2, CMP_IMM),
|
ARMv7_OP4(0xfbf0, 0x8f00, 0xf1b0, 0x0f00, T2, CMP_IMM, nullptr),
|
||||||
ARMv7_OP4(0x0ff0, 0xf000, 0x0350, 0x0000, A1, CMP_IMM),
|
ARMv7_OP4(0x0ff0, 0xf000, 0x0350, 0x0000, A1, CMP_IMM),
|
||||||
ARMv7_OP2(0xffc0, 0x4280, T1, CMP_REG),
|
ARMv7_OP2(0xffc0, 0x4280, T1, CMP_REG, nullptr),
|
||||||
ARMv7_OP2(0xff00, 0x4500, T2, CMP_REG),
|
ARMv7_OP2(0xff00, 0x4500, T2, CMP_REG, nullptr),
|
||||||
ARMv7_OP4(0xfff0, 0x8f00, 0xebb0, 0x0f00, T3, CMP_REG),
|
ARMv7_OP4(0xfff0, 0x8f00, 0xebb0, 0x0f00, T3, CMP_REG, nullptr),
|
||||||
ARMv7_OP4(0x0ff0, 0xf010, 0x0150, 0x0000, A1, CMP_REG),
|
ARMv7_OP4(0x0ff0, 0xf010, 0x0150, 0x0000, A1, CMP_REG),
|
||||||
ARMv7_OP4(0x0ff0, 0xf090, 0x0150, 0x0010, A1, CMP_RSR),
|
ARMv7_OP4(0x0ff0, 0xf090, 0x0150, 0x0010, A1, CMP_RSR),
|
||||||
|
|
||||||
ARMv7_OP4(0xfbe0, 0x8000, 0xf080, 0x0000, T1, EOR_IMM),
|
ARMv7_OP4(0xffff, 0xfff0, 0xf3af, 0x80f0, T1, DBG, nullptr),
|
||||||
|
ARMv7_OP4(0x0fff, 0xfff0, 0x0320, 0xf0f0, A1, DBG),
|
||||||
|
|
||||||
|
ARMv7_OP4(0xffff, 0xfff0, 0xf3bf, 0x8f50, T1, DMB, nullptr),
|
||||||
|
ARMv7_OP4(0xffff, 0xfff0, 0xf57f, 0xf050, A1, DMB),
|
||||||
|
|
||||||
|
ARMv7_OP4(0xffff, 0xfff0, 0xf3bf, 0x8f40, T1, DSB, nullptr),
|
||||||
|
ARMv7_OP4(0xffff, 0xfff0, 0xf57f, 0xf040, A1, DSB),
|
||||||
|
|
||||||
|
ARMv7_OP4(0xfbe0, 0x8000, 0xf080, 0x0000, T1, EOR_IMM, SKIP_IF( BF(8, 11) == 15 && BT(20) )),
|
||||||
ARMv7_OP4(0x0fe0, 0x0000, 0x0220, 0x0000, A1, EOR_IMM),
|
ARMv7_OP4(0x0fe0, 0x0000, 0x0220, 0x0000, A1, EOR_IMM),
|
||||||
ARMv7_OP2(0xffc0, 0x4040, T1, EOR_REG),
|
ARMv7_OP2(0xffc0, 0x4040, T1, EOR_REG, nullptr),
|
||||||
ARMv7_OP4(0xffe0, 0x8000, 0xea80, 0x0000, T2, EOR_REG),
|
ARMv7_OP4(0xffe0, 0x8000, 0xea80, 0x0000, T2, EOR_REG, SKIP_IF( BF(8, 11) == 15 && BT(20) )),
|
||||||
ARMv7_OP4(0x0fe0, 0x0010, 0x0020, 0x0000, A1, EOR_REG),
|
ARMv7_OP4(0x0fe0, 0x0010, 0x0020, 0x0000, A1, EOR_REG),
|
||||||
ARMv7_OP4(0x0fe0, 0x0090, 0x0020, 0x0010, A1, EOR_RSR),
|
ARMv7_OP4(0x0fe0, 0x0090, 0x0020, 0x0010, A1, EOR_RSR),
|
||||||
|
|
||||||
ARMv7_OP2(0xff00, 0xbf00, T1, IT, SKIP_IF( BF(0, 3) == 0 )),
|
ARMv7_OP2(0xff00, 0xbf00, T1, IT, SKIP_IF( BF(0, 3) == 0 )),
|
||||||
|
|
||||||
ARMv7_OP2(0xf800, 0xc800, T1, LDM),
|
ARMv7_OP2(0xf800, 0xc800, T1, LDM, nullptr),
|
||||||
ARMv7_OP4(0xffd0, 0x2000, 0xe890, 0x0000, T2, LDM),
|
ARMv7_OP4(0xffd0, 0x2000, 0xe890, 0x0000, T2, LDM, SKIP_IF( BT(21) && BF(16, 19) == 13 )),
|
||||||
ARMv7_OP4(0x0fd0, 0x0000, 0x0890, 0x0000, A1, LDM),
|
ARMv7_OP4(0x0fd0, 0x0000, 0x0890, 0x0000, A1, LDM),
|
||||||
ARMv7_OP4(0x0fd0, 0x0000, 0x0810, 0x0000, A1, LDMDA),
|
ARMv7_OP4(0x0fd0, 0x0000, 0x0810, 0x0000, A1, LDMDA),
|
||||||
ARMv7_OP4(0xffd0, 0x2000, 0xe910, 0x0000, T1, LDMDB),
|
ARMv7_OP4(0xffd0, 0x2000, 0xe910, 0x0000, T1, LDMDB, nullptr),
|
||||||
ARMv7_OP4(0x0fd0, 0x0000, 0x0910, 0x0000, A1, LDMDB),
|
ARMv7_OP4(0x0fd0, 0x0000, 0x0910, 0x0000, A1, LDMDB),
|
||||||
ARMv7_OP4(0x0fd0, 0x0000, 0x0990, 0x0000, A1, LDMIB),
|
ARMv7_OP4(0x0fd0, 0x0000, 0x0990, 0x0000, A1, LDMIB),
|
||||||
|
|
||||||
ARMv7_OP2(0xf800, 0x6800, T1, LDR_IMM),
|
ARMv7_OP2(0xf800, 0x6800, T1, LDR_IMM, nullptr),
|
||||||
ARMv7_OP2(0xf800, 0x9800, T2, LDR_IMM),
|
ARMv7_OP2(0xf800, 0x9800, T2, LDR_IMM, nullptr),
|
||||||
ARMv7_OP4(0xfff0, 0x0000, 0xf8d0, 0x0000, T3, LDR_IMM),
|
ARMv7_OP4(0xfff0, 0x0000, 0xf8d0, 0x0000, T3, LDR_IMM, SKIP_IF( BF(16, 19) == 15 )),
|
||||||
ARMv7_OP4(0xfff0, 0x0800, 0xf850, 0x0800, T4, LDR_IMM),
|
ARMv7_OP4(0xfff0, 0x0800, 0xf850, 0x0800, T4, LDR_IMM, SKIP_IF( BF(16, 19) == 15 || BF(8, 10) == 6 || (c & 0xf07ff) == 0xd0304 || (c & 0x500) == 0 )),
|
||||||
ARMv7_OP4(0x0e50, 0x0000, 0x0410, 0x0000, A1, LDR_IMM),
|
ARMv7_OP4(0x0e50, 0x0000, 0x0410, 0x0000, A1, LDR_IMM),
|
||||||
ARMv7_OP2(0xf800, 0x4800, T1, LDR_LIT),
|
ARMv7_OP2(0xf800, 0x4800, T1, LDR_LIT, nullptr),
|
||||||
ARMv7_OP4(0xff7f, 0x0000, 0xf85f, 0x0000, T2, LDR_LIT),
|
ARMv7_OP4(0xff7f, 0x0000, 0xf85f, 0x0000, T2, LDR_LIT, nullptr),
|
||||||
ARMv7_OP4(0x0f7f, 0x0000, 0x051f, 0x0000, A1, LDR_LIT),
|
ARMv7_OP4(0x0f7f, 0x0000, 0x051f, 0x0000, A1, LDR_LIT),
|
||||||
ARMv7_OP2(0xfe00, 0x5800, T1, LDR_REG),
|
ARMv7_OP2(0xfe00, 0x5800, T1, LDR_REG, nullptr),
|
||||||
ARMv7_OP4(0xfff0, 0x0fc0, 0xf850, 0x0000, T2, LDR_REG),
|
ARMv7_OP4(0xfff0, 0x0fc0, 0xf850, 0x0000, T2, LDR_REG, SKIP_IF( BF(16, 19) == 15 )),
|
||||||
ARMv7_OP4(0x0e50, 0x0010, 0x0610, 0x0000, A1, LDR_REG),
|
ARMv7_OP4(0x0e50, 0x0010, 0x0610, 0x0000, A1, LDR_REG),
|
||||||
|
|
||||||
ARMv7_OP2(0xf800, 0x7800, T1, LDRB_IMM),
|
ARMv7_OP2(0xf800, 0x7800, T1, LDRB_IMM),
|
||||||
ARMv7_OP4(0xfff0, 0x0000, 0xf890, 0x0000, T2, LDRB_IMM),
|
ARMv7_OP4(0xfff0, 0x0000, 0xf890, 0x0000, T2, LDRB_IMM),
|
||||||
ARMv7_OP4(0xfff0, 0x0800, 0xf810, 0x0800, T3, LDRB_IMM),
|
ARMv7_OP4(0xfff0, 0x0800, 0xf810, 0x0800, T3, LDRB_IMM),
|
||||||
|
@ -280,7 +290,7 @@ const ARMv7_opcode_t ARMv7_opcode_table[] =
|
||||||
ARMv7_OP4(0xfbe0, 0x8000, 0xf040, 0x0000, T1, ORR_IMM),
|
ARMv7_OP4(0xfbe0, 0x8000, 0xf040, 0x0000, T1, ORR_IMM),
|
||||||
ARMv7_OP4(0x0fe0, 0x0000, 0x0380, 0x0000, A1, ORR_IMM),
|
ARMv7_OP4(0x0fe0, 0x0000, 0x0380, 0x0000, A1, ORR_IMM),
|
||||||
ARMv7_OP2(0xffc0, 0x4300, T1, ORR_REG),
|
ARMv7_OP2(0xffc0, 0x4300, T1, ORR_REG),
|
||||||
ARMv7_OP4(0xffe0, 0x8000, 0xea40, 0x0000, T2, ORR_REG),
|
ARMv7_OP4(0xffe0, 0x8000, 0xea40, 0x0000, T2, ORR_REG, SKIP_IF( BF(16, 19) == 15 )),
|
||||||
ARMv7_OP4(0x0fe0, 0x0010, 0x0180, 0x0000, A1, ORR_REG),
|
ARMv7_OP4(0x0fe0, 0x0010, 0x0180, 0x0000, A1, ORR_REG),
|
||||||
ARMv7_OP4(0x0fe0, 0x0090, 0x0180, 0x0010, A1, ORR_RSR),
|
ARMv7_OP4(0x0fe0, 0x0090, 0x0180, 0x0010, A1, ORR_RSR),
|
||||||
|
|
||||||
|
@ -1105,6 +1115,7 @@ const ARMv7_opcode_t ARMv7_opcode_table[] =
|
||||||
struct ARMv7_op2_table_t
|
struct ARMv7_op2_table_t
|
||||||
{
|
{
|
||||||
const ARMv7_opcode_t* data[0x10000];
|
const ARMv7_opcode_t* data[0x10000];
|
||||||
|
u32 null_ops;
|
||||||
|
|
||||||
ARMv7_op2_table_t()
|
ARMv7_op2_table_t()
|
||||||
{
|
{
|
||||||
|
@ -1123,6 +1134,8 @@ struct ARMv7_op2_table_t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
null_ops = 0x10000;
|
||||||
|
|
||||||
for (u32 i = 0; i < 0x10000; i++)
|
for (u32 i = 0; i < 0x10000; i++)
|
||||||
{
|
{
|
||||||
data[i] = nullptr;
|
data[i] = nullptr;
|
||||||
|
@ -1132,6 +1145,7 @@ struct ARMv7_op2_table_t
|
||||||
if (((i << 16) & opcode->mask) == opcode->code && (!opcode->skip || !opcode->skip(i)))
|
if (((i << 16) & opcode->mask) == opcode->code && (!opcode->skip || !opcode->skip(i)))
|
||||||
{
|
{
|
||||||
data[i] = opcode;
|
data[i] = opcode;
|
||||||
|
null_ops--;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1201,11 +1215,12 @@ std::unordered_map<u32, const ARMv7_opcode_t*> g_opct;
|
||||||
|
|
||||||
void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump)
|
void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump)
|
||||||
{
|
{
|
||||||
// 1. Find every 4-byte thumb instruction and cache it
|
// 1. Find every 4-byte Thumb instruction and cache it
|
||||||
// 2. If some instruction is not recognized, print the error
|
// 2. If some instruction is not recognized, print the error
|
||||||
// 3. Possibly print disasm
|
// 3. Possibly print disasm
|
||||||
|
|
||||||
g_opct.clear();
|
//g_opct.clear();
|
||||||
|
//g_opct.reserve(end_addr - addr);
|
||||||
|
|
||||||
while (addr < end_addr)
|
while (addr < end_addr)
|
||||||
{
|
{
|
||||||
|
@ -1266,7 +1281,7 @@ void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump)
|
||||||
const u32 i2 = (code.data >> 11) & 0x1 ^ s ^ 1;
|
const u32 i2 = (code.data >> 11) & 0x1 ^ s ^ 1;
|
||||||
const u32 target = (addr + 4 & ~3) + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1);
|
const u32 target = (addr + 4 & ~3) + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1);
|
||||||
|
|
||||||
const u32 instr = vm::psv::read32(target);
|
const u32 instr = Memory.IsGoodAddr(target, 4) ? vm::psv::read32(target) : 0;
|
||||||
|
|
||||||
// possibly a call to imported function:
|
// possibly a call to imported function:
|
||||||
if (target >= end_addr && ((target - end_addr) % 16) == 0 && (instr & 0xfff000f0) == 0xe0700090)
|
if (target >= end_addr && ((target - end_addr) % 16) == 0 && (instr & 0xfff000f0) == 0xe0700090)
|
||||||
|
@ -1297,7 +1312,7 @@ void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump)
|
||||||
addr += found->length;
|
addr += found->length;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_NOTICE(ARMv7, "armv7_decoder_initialize() finished, g_opct.size() = %lld", (u64)g_opct.size());
|
LOG_NOTICE(ARMv7, "armv7_decoder_initialize() finished, g_opct.size() = %lld, g_op2t.null_ops=0x%x", (u64)g_opct.size(), g_op2t.null_ops);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 ARMv7Decoder::DecodeMemory(const u32 address)
|
u32 ARMv7Decoder::DecodeMemory(const u32 address)
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -18,12 +18,11 @@ enum ARMv7_encoding
|
||||||
|
|
||||||
enum SRType : u32
|
enum SRType : u32
|
||||||
{
|
{
|
||||||
SRType_None,
|
|
||||||
SRType_LSL,
|
SRType_LSL,
|
||||||
SRType_LSR,
|
SRType_LSR,
|
||||||
SRType_ASR,
|
SRType_ASR,
|
||||||
SRType_ROR,
|
SRType_ROR,
|
||||||
SRType_RRX
|
SRType_RRX,
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace ARMv7_instrs
|
namespace ARMv7_instrs
|
||||||
|
@ -79,6 +78,10 @@ namespace ARMv7_instrs
|
||||||
void CMP_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type);
|
void CMP_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type);
|
||||||
void CMP_RSR(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type);
|
void CMP_RSR(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type);
|
||||||
|
|
||||||
|
void DBG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type);
|
||||||
|
void DMB(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type);
|
||||||
|
void DSB(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type);
|
||||||
|
|
||||||
void EOR_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type);
|
void EOR_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type);
|
||||||
void EOR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type);
|
void EOR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type);
|
||||||
void EOR_RSR(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type);
|
void EOR_RSR(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type);
|
||||||
|
|
|
@ -18,7 +18,7 @@ void ARMv7Context::write_pc(u32 value)
|
||||||
|
|
||||||
u32 ARMv7Context::read_pc()
|
u32 ARMv7Context::read_pc()
|
||||||
{
|
{
|
||||||
return thread.PC;
|
return ISET == ARM ? thread.PC + 8 : thread.PC + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 ARMv7Context::get_stack_arg(u32 pos)
|
u32 ARMv7Context::get_stack_arg(u32 pos)
|
||||||
|
@ -118,7 +118,7 @@ void ARMv7Thread::InitRegs()
|
||||||
context.ITSTATE.IT = 0;
|
context.ITSTATE.IT = 0;
|
||||||
context.SP = m_stack_addr + m_stack_size;
|
context.SP = m_stack_addr + m_stack_size;
|
||||||
context.TLS = armv7_get_tls(GetId());
|
context.TLS = armv7_get_tls(GetId());
|
||||||
context.R_ADDR = 0;
|
context.debug |= DF_DISASM | DF_PRINT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ARMv7Thread::InitStack()
|
void ARMv7Thread::InitStack()
|
||||||
|
@ -230,14 +230,14 @@ void ARMv7Thread::FastStop()
|
||||||
m_status = Stopped;
|
m_status = Stopped;
|
||||||
}
|
}
|
||||||
|
|
||||||
armv7_thread::armv7_thread(u32 entry, const std::string& name, u32 stack_size, u32 prio)
|
armv7_thread::armv7_thread(u32 entry, const std::string& name, u32 stack_size, s32 prio)
|
||||||
{
|
{
|
||||||
thread = &Emu.GetCPU().AddThread(CPU_THREAD_ARMv7);
|
thread = &Emu.GetCPU().AddThread(CPU_THREAD_ARMv7);
|
||||||
|
|
||||||
thread->SetName(name);
|
thread->SetName(name);
|
||||||
thread->SetEntry(entry);
|
thread->SetEntry(entry);
|
||||||
thread->SetStackSize(stack_size ? stack_size : Emu.GetInfo().GetProcParam().primary_stacksize);
|
thread->SetStackSize(stack_size);
|
||||||
thread->SetPrio(prio ? prio : Emu.GetInfo().GetProcParam().primary_prio);
|
thread->SetPrio(prio);
|
||||||
|
|
||||||
argc = 0;
|
argc = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ class armv7_thread : cpu_thread
|
||||||
u32 argc;
|
u32 argc;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
armv7_thread(u32 entry, const std::string& name = "", u32 stack_size = 0, u32 prio = 0);
|
armv7_thread(u32 entry, const std::string& name, u32 stack_size, s32 prio);
|
||||||
|
|
||||||
cpu_thread& args(std::initializer_list<std::string> values) override;
|
cpu_thread& args(std::initializer_list<std::string> values) override;
|
||||||
|
|
||||||
|
|
13
rpcs3/Emu/ARMv7/Modules/psv_cond.cpp
Normal file
13
rpcs3/Emu/ARMv7/Modules/psv_cond.cpp
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "Emu/Memory/Memory.h"
|
||||||
|
#include "Emu/ARMv7/PSVFuncList.h"
|
||||||
|
#include "Emu/ARMv7/PSVObjectList.h"
|
||||||
|
#include "sceLibKernel.h"
|
||||||
|
#include "psv_cond.h"
|
||||||
|
|
||||||
|
psv_cond_t::psv_cond_t(const char* name, u32 attr, s32 mutexId)
|
||||||
|
: attr(attr)
|
||||||
|
, mutexId(mutexId)
|
||||||
|
{
|
||||||
|
strcpy_trunc(this->name, name);
|
||||||
|
}
|
24
rpcs3/Emu/ARMv7/Modules/psv_cond.h
Normal file
24
rpcs3/Emu/ARMv7/Modules/psv_cond.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct psv_cond_t
|
||||||
|
{
|
||||||
|
char name[32];
|
||||||
|
u32 attr;
|
||||||
|
s32 mutexId;
|
||||||
|
|
||||||
|
private:
|
||||||
|
psv_cond_t() = delete;
|
||||||
|
psv_cond_t(const psv_cond_t&) = delete;
|
||||||
|
psv_cond_t(psv_cond_t&&) = delete;
|
||||||
|
|
||||||
|
psv_cond_t& operator =(const psv_cond_t&) = delete;
|
||||||
|
psv_cond_t& operator =(psv_cond_t&&) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
psv_cond_t(const char* name, u32 attr, s32 mutexId);
|
||||||
|
void on_init(s32 id) {}
|
||||||
|
void on_stop() {}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
extern psv_object_list_t<psv_cond_t, SCE_KERNEL_THREADMGR_UID_CLASS_COND> g_psv_cond_list;
|
|
@ -16,6 +16,9 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
psv_event_flag_t(const char* name, u32 attr, u32 pattern);
|
psv_event_flag_t(const char* name, u32 attr, u32 pattern);
|
||||||
|
void on_init(s32 id) {}
|
||||||
|
void on_stop() {}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern psv_object_list_t<psv_event_flag_t, SCE_KERNEL_THREADMGR_UID_CLASS_EVENT_FLAG> g_psv_ef_list;
|
extern psv_object_list_t<psv_event_flag_t, SCE_KERNEL_THREADMGR_UID_CLASS_EVENT_FLAG> g_psv_ef_list;
|
||||||
|
|
13
rpcs3/Emu/ARMv7/Modules/psv_mutex.cpp
Normal file
13
rpcs3/Emu/ARMv7/Modules/psv_mutex.cpp
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "Emu/Memory/Memory.h"
|
||||||
|
#include "Emu/ARMv7/PSVFuncList.h"
|
||||||
|
#include "Emu/ARMv7/PSVObjectList.h"
|
||||||
|
#include "sceLibKernel.h"
|
||||||
|
#include "psv_mutex.h"
|
||||||
|
|
||||||
|
psv_mutex_t::psv_mutex_t(const char* name, u32 attr, s32 count)
|
||||||
|
: attr(attr)
|
||||||
|
, count(count)
|
||||||
|
{
|
||||||
|
strcpy_trunc(this->name, name);
|
||||||
|
}
|
24
rpcs3/Emu/ARMv7/Modules/psv_mutex.h
Normal file
24
rpcs3/Emu/ARMv7/Modules/psv_mutex.h
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
struct psv_mutex_t
|
||||||
|
{
|
||||||
|
char name[32];
|
||||||
|
u32 attr;
|
||||||
|
s32 count;
|
||||||
|
|
||||||
|
private:
|
||||||
|
psv_mutex_t() = delete;
|
||||||
|
psv_mutex_t(const psv_mutex_t&) = delete;
|
||||||
|
psv_mutex_t(psv_mutex_t&&) = delete;
|
||||||
|
|
||||||
|
psv_mutex_t& operator =(const psv_mutex_t&) = delete;
|
||||||
|
psv_mutex_t& operator =(psv_mutex_t&&) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
psv_mutex_t(const char* name, u32 attr, s32 count);
|
||||||
|
void on_init(s32 id) {}
|
||||||
|
void on_stop() {}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
extern psv_object_list_t<psv_mutex_t, SCE_KERNEL_THREADMGR_UID_CLASS_MUTEX> g_psv_mutex_list;
|
|
@ -17,6 +17,8 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
psv_sema_t(const char* name, u32 attr, s32 init_value, s32 max_value);
|
psv_sema_t(const char* name, u32 attr, s32 init_value, s32 max_value);
|
||||||
|
void on_init(s32 id) {}
|
||||||
|
void on_stop() {}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#include "sceLibKernel.h"
|
#include "sceLibKernel.h"
|
||||||
#include "psv_sema.h"
|
#include "psv_sema.h"
|
||||||
#include "psv_event_flag.h"
|
#include "psv_event_flag.h"
|
||||||
|
#include "psv_mutex.h"
|
||||||
|
#include "psv_cond.h"
|
||||||
|
|
||||||
#define RETURN_ERROR(code) { Emu.Pause(); sceLibKernel.Error("%s() failed: %s", __FUNCTION__, #code); return code; }
|
#define RETURN_ERROR(code) { Emu.Pause(); sceLibKernel.Error("%s() failed: %s", __FUNCTION__, #code); return code; }
|
||||||
|
|
||||||
|
@ -522,7 +524,13 @@ s32 sceKernelGetSemaInfo(s32 semaId, vm::psv::ptr<SceKernelSemaInfo> pInfo)
|
||||||
|
|
||||||
s32 sceKernelCreateMutex(vm::psv::ptr<const char> pName, u32 attr, s32 initCount, vm::psv::ptr<const SceKernelMutexOptParam> pOptParam)
|
s32 sceKernelCreateMutex(vm::psv::ptr<const char> pName, u32 attr, s32 initCount, vm::psv::ptr<const SceKernelMutexOptParam> pOptParam)
|
||||||
{
|
{
|
||||||
throw __FUNCTION__;
|
sceLibKernel.Error("sceKernelCreateMutex(pName=0x%x, attr=0x%x, initCount=%d, pOptParam=0x%x)", pName, attr, initCount, pOptParam);
|
||||||
|
|
||||||
|
std::shared_ptr<psv_mutex_t> mutex(new psv_mutex_t(pName.get_ptr(), attr, initCount));
|
||||||
|
|
||||||
|
const s32 id = g_psv_mutex_list.add(mutex);
|
||||||
|
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 sceKernelDeleteMutex(s32 mutexId)
|
s32 sceKernelDeleteMutex(s32 mutexId)
|
||||||
|
@ -616,7 +624,13 @@ s32 sceKernelGetLwMutexInfoById(s32 lwMutexId, vm::psv::ptr<SceKernelLwMutexInfo
|
||||||
|
|
||||||
s32 sceKernelCreateCond(vm::psv::ptr<const char> pName, u32 attr, s32 mutexId, vm::psv::ptr<const SceKernelCondOptParam> pOptParam)
|
s32 sceKernelCreateCond(vm::psv::ptr<const char> pName, u32 attr, s32 mutexId, vm::psv::ptr<const SceKernelCondOptParam> pOptParam)
|
||||||
{
|
{
|
||||||
throw __FUNCTION__;
|
sceLibKernel.Error("sceKernelCreateCond(pName=0x%x, attr=0x%x, mutexId=0x%x, pOptParam=0x%x)", pName, attr, mutexId, pOptParam);
|
||||||
|
|
||||||
|
std::shared_ptr<psv_cond_t> cond(new psv_cond_t(pName.get_ptr(), attr, mutexId));
|
||||||
|
|
||||||
|
const s32 id = g_psv_cond_list.add(cond);
|
||||||
|
|
||||||
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 sceKernelDeleteCond(s32 condId)
|
s32 sceKernelDeleteCond(s32 condId)
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "Utilities/Log.h"
|
#include "Utilities/Log.h"
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "Emu/ARMv7/PSVFuncList.h"
|
#include "Emu/ARMv7/PSVFuncList.h"
|
||||||
|
#include "Emu/ARMv7/ARMv7Thread.h"
|
||||||
#include "Emu/ARMv7/ARMv7Callback.h"
|
#include "Emu/ARMv7/ARMv7Callback.h"
|
||||||
|
|
||||||
extern psv_log_base sceLibc;
|
extern psv_log_base sceLibc;
|
||||||
|
@ -12,6 +13,139 @@ typedef void(atexit_func_t)(vm::psv::ptr<void>);
|
||||||
|
|
||||||
std::vector<std::function<void(ARMv7Context&)>> g_atexit;
|
std::vector<std::function<void(ARMv7Context&)>> g_atexit;
|
||||||
|
|
||||||
|
std::string armv7_fmt(ARMv7Context& context, vm::psv::ptr<const char> fmt, u32 g_count, u32 f_count, u32 v_count)
|
||||||
|
{
|
||||||
|
std::string result;
|
||||||
|
|
||||||
|
for (char c = *fmt++; c; c = *fmt++)
|
||||||
|
{
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case '%':
|
||||||
|
{
|
||||||
|
const auto start = fmt - 1;
|
||||||
|
|
||||||
|
// read flags
|
||||||
|
const bool plus_sign = *fmt == '+' ? fmt++, true : false;
|
||||||
|
const bool minus_sign = *fmt == '-' ? fmt++, true : false;
|
||||||
|
const bool space_sign = *fmt == ' ' ? fmt++, true : false;
|
||||||
|
const bool number_sign = *fmt == '#' ? fmt++, true : false;
|
||||||
|
const bool zero_padding = *fmt == '0' ? fmt++, true : false;
|
||||||
|
|
||||||
|
// read width
|
||||||
|
const u32 width = [&]() -> u32
|
||||||
|
{
|
||||||
|
u32 width = 0;
|
||||||
|
|
||||||
|
if (*fmt == '*')
|
||||||
|
{
|
||||||
|
fmt++;
|
||||||
|
return context.get_next_gpr_arg(g_count, f_count, v_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*fmt - '0' < 10)
|
||||||
|
{
|
||||||
|
width = width * 10 + (*fmt++ - '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
return width;
|
||||||
|
}();
|
||||||
|
|
||||||
|
// read precision
|
||||||
|
const u32 prec = [&]() -> u32
|
||||||
|
{
|
||||||
|
u32 prec = 0;
|
||||||
|
|
||||||
|
if (*fmt != '.')
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*++fmt == '*')
|
||||||
|
{
|
||||||
|
fmt++;
|
||||||
|
return context.get_next_gpr_arg(g_count, f_count, v_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*fmt - '0' < 10)
|
||||||
|
{
|
||||||
|
prec = prec * 10 + (*fmt++ - '0');
|
||||||
|
}
|
||||||
|
|
||||||
|
return prec;
|
||||||
|
}();
|
||||||
|
|
||||||
|
switch (char cf = *fmt++)
|
||||||
|
{
|
||||||
|
case '%':
|
||||||
|
{
|
||||||
|
if (plus_sign || minus_sign || space_sign || number_sign || zero_padding || width || prec) break;
|
||||||
|
|
||||||
|
result += '%';
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 'd':
|
||||||
|
case 'i':
|
||||||
|
{
|
||||||
|
// signed decimal
|
||||||
|
const s64 value = context.get_next_gpr_arg(g_count, f_count, v_count);
|
||||||
|
|
||||||
|
if (plus_sign || minus_sign || space_sign || number_sign || zero_padding || width || prec) break;
|
||||||
|
|
||||||
|
result += fmt::to_sdec(value);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 'x':
|
||||||
|
case 'X':
|
||||||
|
{
|
||||||
|
// hexadecimal
|
||||||
|
const u64 value = context.get_next_gpr_arg(g_count, f_count, v_count);
|
||||||
|
|
||||||
|
if (plus_sign || minus_sign || space_sign || prec) break;
|
||||||
|
|
||||||
|
if (number_sign && value)
|
||||||
|
{
|
||||||
|
result += cf == 'x' ? "0x" : "0X";
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& hex = cf == 'x' ? fmt::to_hex(value) : fmt::toupper(fmt::to_hex(value));
|
||||||
|
|
||||||
|
if (hex.length() >= width)
|
||||||
|
{
|
||||||
|
result += hex;
|
||||||
|
}
|
||||||
|
else if (zero_padding)
|
||||||
|
{
|
||||||
|
result += std::string(width - hex.length(), '0') + hex;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result += hex + std::string(width - hex.length(), ' ');
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
case 's':
|
||||||
|
{
|
||||||
|
// string
|
||||||
|
auto string = vm::psv::ptr<const char>::make(context.get_next_gpr_arg(g_count, f_count, v_count));
|
||||||
|
|
||||||
|
if (plus_sign || minus_sign || space_sign || number_sign || zero_padding || width || prec) break;
|
||||||
|
|
||||||
|
result += string.get_ptr();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw fmt::format("armv7_fmt(): unknown formatting: '%s'", start.get_ptr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result += c;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
namespace sce_libc_func
|
namespace sce_libc_func
|
||||||
{
|
{
|
||||||
void __cxa_atexit(vm::psv::ptr<atexit_func_t> func, vm::psv::ptr<void> arg, vm::psv::ptr<void> dso)
|
void __cxa_atexit(vm::psv::ptr<atexit_func_t> func, vm::psv::ptr<void> arg, vm::psv::ptr<void> dso)
|
||||||
|
@ -59,80 +193,24 @@ namespace sce_libc_func
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string armv7_fmt(ARMv7Context& context, vm::psv::ptr<const char> fmt, u32 g_count, u32 f_count, u32 v_count)
|
|
||||||
{
|
|
||||||
std::string result;
|
|
||||||
|
|
||||||
for (char c = *fmt++; c; c = *fmt++)
|
|
||||||
{
|
|
||||||
switch (c)
|
|
||||||
{
|
|
||||||
case '%':
|
|
||||||
{
|
|
||||||
const auto start = fmt - 1;
|
|
||||||
const bool number_sign = *fmt == '#' ? fmt++, true : false;
|
|
||||||
|
|
||||||
switch (*fmt++)
|
|
||||||
{
|
|
||||||
case '%':
|
|
||||||
{
|
|
||||||
result += '%';
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
case 'd':
|
|
||||||
case 'i':
|
|
||||||
{
|
|
||||||
// signed decimal
|
|
||||||
const s64 value = context.get_next_gpr_arg(g_count, f_count, v_count);
|
|
||||||
|
|
||||||
result += fmt::to_sdec(value);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
case 'x':
|
|
||||||
{
|
|
||||||
// hexadecimal
|
|
||||||
const u64 value = context.get_next_gpr_arg(g_count, f_count, v_count);
|
|
||||||
|
|
||||||
if (number_sign && value)
|
|
||||||
{
|
|
||||||
result += "0x";
|
|
||||||
}
|
|
||||||
|
|
||||||
result += fmt::to_hex(value);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
throw fmt::Format("armv7_fmt(): unknown formatting: '%s'", start.get_ptr());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result += c;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void printf(ARMv7Context& context, vm::psv::ptr<const char> fmt) // va_args...
|
void printf(ARMv7Context& context, vm::psv::ptr<const char> fmt) // va_args...
|
||||||
{
|
{
|
||||||
sceLibc.Warning("printf(fmt=0x%x)", fmt);
|
sceLibc.Warning("printf(fmt=0x%x)", fmt);
|
||||||
|
sceLibc.Log("*** *fmt = '%s'", fmt.get_ptr());
|
||||||
|
|
||||||
sceLibc.Notice("*** *fmt = '%s'", fmt.get_ptr());
|
const std::string& result = armv7_fmt(context, fmt, 1, 0, 0);
|
||||||
|
sceLibc.Log("*** -> '%s'", result);
|
||||||
|
|
||||||
LOG_NOTICE(TTY, armv7_fmt(context, fmt, 1, 0, 0));
|
LOG_NOTICE(TTY, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sprintf(ARMv7Context& context, vm::psv::ptr<char> str, vm::psv::ptr<const char> fmt) // va_args...
|
void sprintf(ARMv7Context& context, vm::psv::ptr<char> str, vm::psv::ptr<const char> fmt) // va_args...
|
||||||
{
|
{
|
||||||
sceLibc.Warning("sprintf(str=0x%x, fmt=0x%x)", str, fmt);
|
sceLibc.Warning("sprintf(str=0x%x, fmt=0x%x)", str, fmt);
|
||||||
|
sceLibc.Log("*** *fmt = '%s'", fmt.get_ptr());
|
||||||
sceLibc.Notice("*** *fmt = '%s'", fmt.get_ptr());
|
|
||||||
|
|
||||||
const std::string& result = armv7_fmt(context, fmt, 2, 0, 0);
|
const std::string& result = armv7_fmt(context, fmt, 2, 0, 0);
|
||||||
|
sceLibc.Log("*** -> '%s'", result);
|
||||||
sceLibc.Notice("*** res -> '%s'", result);
|
|
||||||
|
|
||||||
::memcpy(str.get_ptr(), result.c_str(), result.size() + 1);
|
::memcpy(str.get_ptr(), result.c_str(), result.size() + 1);
|
||||||
}
|
}
|
||||||
|
@ -158,11 +236,12 @@ namespace sce_libc_func
|
||||||
::memset(dst.get_ptr(), value, size);
|
::memset(dst.get_ptr(), value, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _Assert(vm::psv::ptr<const char> text, vm::psv::ptr<const char> func)
|
void _Assert(ARMv7Context& context, vm::psv::ptr<const char> text, vm::psv::ptr<const char> func)
|
||||||
{
|
{
|
||||||
sceLibc.Warning("_Assert(text=0x%x, func=0x%x)", text, func);
|
sceLibc.Error("_Assert(text=0x%x, func=0x%x)", text, func);
|
||||||
|
|
||||||
LOG_ERROR(TTY, "%s : %s\n", func.get_ptr(), text.get_ptr());
|
LOG_ERROR(TTY, "%s : %s\n", func.get_ptr(), text.get_ptr());
|
||||||
|
LOG_NOTICE(ARMv7, context.thread.RegsToString());
|
||||||
Emu.Pause();
|
Emu.Pause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,6 +134,11 @@ s32 scePerfArmPmonSelectEvent(ARMv7Context& context, s32 threadId, u32 counter,
|
||||||
|
|
||||||
case SCE_PERF_ARM_PMON_BRANCH_MISPREDICT:
|
case SCE_PERF_ARM_PMON_BRANCH_MISPREDICT:
|
||||||
case SCE_PERF_ARM_PMON_DCACHE_MISS:
|
case SCE_PERF_ARM_PMON_DCACHE_MISS:
|
||||||
|
case SCE_PERF_ARM_PMON_DCACHE_STALL:
|
||||||
|
case SCE_PERF_ARM_PMON_ICACHE_STALL:
|
||||||
|
case SCE_PERF_ARM_PMON_DATA_EVICTION:
|
||||||
|
case SCE_PERF_ARM_PMON_WRITE_STALL:
|
||||||
|
case SCE_PERF_ARM_PMON_MAINTLB_STALL:
|
||||||
case SCE_PERF_ARM_PMON_UNALIGNED:
|
case SCE_PERF_ARM_PMON_UNALIGNED:
|
||||||
{
|
{
|
||||||
value = 1; // these events will probably never be implemented
|
value = 1; // these events will probably never be implemented
|
||||||
|
|
|
@ -6,21 +6,21 @@ extern psv_log_base sceSysmodule;
|
||||||
|
|
||||||
s32 sceSysmoduleLoadModule(u16 id)
|
s32 sceSysmoduleLoadModule(u16 id)
|
||||||
{
|
{
|
||||||
sceSysmodule.Error("sceSysmoduleLoadModule(id=0x%04x) -> SCE_OK", id);
|
sceSysmodule.Warning("sceSysmoduleLoadModule(id=0x%04x) -> SCE_OK", id);
|
||||||
|
|
||||||
return SCE_OK; // loading succeeded
|
return SCE_OK; // loading succeeded
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 sceSysmoduleUnloadModule(u16 id)
|
s32 sceSysmoduleUnloadModule(u16 id)
|
||||||
{
|
{
|
||||||
sceSysmodule.Error("sceSysmoduleUnloadModule(id=0x%04x) -> SCE_OK", id);
|
sceSysmodule.Warning("sceSysmoduleUnloadModule(id=0x%04x) -> SCE_OK", id);
|
||||||
|
|
||||||
return SCE_OK; // unloading succeeded
|
return SCE_OK; // unloading succeeded
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 sceSysmoduleIsLoaded(u16 id)
|
s32 sceSysmoduleIsLoaded(u16 id)
|
||||||
{
|
{
|
||||||
sceSysmodule.Error("sceSysmoduleIsLoaded(id=0x%04x) -> SCE_OK", id);
|
sceSysmodule.Warning("sceSysmoduleIsLoaded(id=0x%04x) -> SCE_OK", id);
|
||||||
|
|
||||||
return SCE_OK; // module is loaded
|
return SCE_OK; // module is loaded
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ void add_psv_func(psv_func& data)
|
||||||
g_psv_func_list.push_back(data);
|
g_psv_func_list.push_back(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
psv_func* get_psv_func_by_nid(u32 nid)
|
const psv_func* get_psv_func_by_nid(u32 nid)
|
||||||
{
|
{
|
||||||
for (auto& f : g_psv_func_list)
|
for (auto& f : g_psv_func_list)
|
||||||
{
|
{
|
||||||
|
@ -23,7 +23,7 @@ psv_func* get_psv_func_by_nid(u32 nid)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 get_psv_func_index(psv_func* func)
|
u32 get_psv_func_index(const psv_func* func)
|
||||||
{
|
{
|
||||||
auto res = func - g_psv_func_list.data();
|
auto res = func - g_psv_func_list.data();
|
||||||
|
|
||||||
|
@ -32,14 +32,21 @@ u32 get_psv_func_index(psv_func* func)
|
||||||
return (u32)res;
|
return (u32)res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void execute_psv_func_by_index(ARMv7Context& context, u32 index)
|
const psv_func* get_psv_func_by_index(u32 index)
|
||||||
{
|
{
|
||||||
assert(index < g_psv_func_list.size());
|
assert(index < g_psv_func_list.size());
|
||||||
|
|
||||||
|
return &g_psv_func_list[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute_psv_func_by_index(ARMv7Context& context, u32 index)
|
||||||
|
{
|
||||||
|
auto func = get_psv_func_by_index(index);
|
||||||
|
|
||||||
auto old_last_syscall = context.thread.m_last_syscall;
|
auto old_last_syscall = context.thread.m_last_syscall;
|
||||||
context.thread.m_last_syscall = g_psv_func_list[index].nid;
|
context.thread.m_last_syscall = func->nid;
|
||||||
|
|
||||||
(*g_psv_func_list[index].func)(context);
|
(*func->func)(context);
|
||||||
|
|
||||||
context.thread.m_last_syscall = old_last_syscall;
|
context.thread.m_last_syscall = old_last_syscall;
|
||||||
}
|
}
|
||||||
|
@ -174,7 +181,7 @@ void initialize_psv_modules()
|
||||||
// setup special functions (without NIDs)
|
// setup special functions (without NIDs)
|
||||||
psv_func unimplemented;
|
psv_func unimplemented;
|
||||||
unimplemented.nid = 0;
|
unimplemented.nid = 0;
|
||||||
unimplemented.name = "Special function (unimplemented stub)";
|
unimplemented.name = "UNIMPLEMENTED";
|
||||||
unimplemented.func.reset(new psv_func_detail::func_binder<void, ARMv7Context&>([](ARMv7Context& context)
|
unimplemented.func.reset(new psv_func_detail::func_binder<void, ARMv7Context&>([](ARMv7Context& context)
|
||||||
{
|
{
|
||||||
context.thread.m_last_syscall = vm::psv::read32(context.thread.PC + 4);
|
context.thread.m_last_syscall = vm::psv::read32(context.thread.PC + 4);
|
||||||
|
@ -184,7 +191,7 @@ void initialize_psv_modules()
|
||||||
|
|
||||||
psv_func hle_return;
|
psv_func hle_return;
|
||||||
hle_return.nid = 1;
|
hle_return.nid = 1;
|
||||||
hle_return.name = "Special function (return from HLE)";
|
hle_return.name = "HLE_RETURN";
|
||||||
hle_return.func.reset(new psv_func_detail::func_binder<void, ARMv7Context&>([](ARMv7Context& context)
|
hle_return.func.reset(new psv_func_detail::func_binder<void, ARMv7Context&>([](ARMv7Context& context)
|
||||||
{
|
{
|
||||||
context.thread.FastStop();
|
context.thread.FastStop();
|
||||||
|
|
|
@ -492,9 +492,11 @@ template<typename RT, typename... T> void reg_psv_func(u32 nid, psv_log_base* mo
|
||||||
add_psv_func(f);
|
add_psv_func(f);
|
||||||
}
|
}
|
||||||
// Find registered HLE function by its ID
|
// Find registered HLE function by its ID
|
||||||
psv_func* get_psv_func_by_nid(u32 nid);
|
const psv_func* get_psv_func_by_nid(u32 nid);
|
||||||
// Get index of registered HLE function
|
// Get index of registered HLE function
|
||||||
u32 get_psv_func_index(psv_func* func);
|
u32 get_psv_func_index(const psv_func* func);
|
||||||
|
// Find registered HLE function by its index
|
||||||
|
const psv_func* get_psv_func_by_index(u32 index);
|
||||||
// Execute registered HLE function by its index
|
// Execute registered HLE function by its index
|
||||||
void execute_psv_func_by_index(ARMv7Context& context, u32 index);
|
void execute_psv_func_by_index(ARMv7Context& context, u32 index);
|
||||||
// Register all HLE functions
|
// Register all HLE functions
|
||||||
|
|
|
@ -5,12 +5,18 @@
|
||||||
#include "Modules/sceLibKernel.h"
|
#include "Modules/sceLibKernel.h"
|
||||||
#include "Modules/psv_sema.h"
|
#include "Modules/psv_sema.h"
|
||||||
#include "Modules/psv_event_flag.h"
|
#include "Modules/psv_event_flag.h"
|
||||||
|
#include "Modules/psv_mutex.h"
|
||||||
|
#include "Modules/psv_cond.h"
|
||||||
|
|
||||||
psv_object_list_t<psv_sema_t, SCE_KERNEL_THREADMGR_UID_CLASS_SEMA> g_psv_sema_list;
|
psv_object_list_t<psv_sema_t, SCE_KERNEL_THREADMGR_UID_CLASS_SEMA> g_psv_sema_list;
|
||||||
psv_object_list_t<psv_event_flag_t, SCE_KERNEL_THREADMGR_UID_CLASS_EVENT_FLAG> g_psv_ef_list;
|
psv_object_list_t<psv_event_flag_t, SCE_KERNEL_THREADMGR_UID_CLASS_EVENT_FLAG> g_psv_ef_list;
|
||||||
|
psv_object_list_t<psv_mutex_t, SCE_KERNEL_THREADMGR_UID_CLASS_MUTEX> g_psv_mutex_list;
|
||||||
|
psv_object_list_t<psv_cond_t, SCE_KERNEL_THREADMGR_UID_CLASS_COND> g_psv_cond_list;
|
||||||
|
|
||||||
void clear_all_psv_objects()
|
void clear_all_psv_objects()
|
||||||
{
|
{
|
||||||
g_psv_sema_list.clear();
|
g_psv_sema_list.clear();
|
||||||
g_psv_ef_list.clear();
|
g_psv_ef_list.clear();
|
||||||
|
g_psv_mutex_list.clear();
|
||||||
|
g_psv_cond_list.clear();
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,18 @@ template<typename T, u32 type>
|
||||||
class psv_object_list_t // Class for managing object data
|
class psv_object_list_t // Class for managing object data
|
||||||
{
|
{
|
||||||
std::array<std::shared_ptr<T>, 0x8000> m_data;
|
std::array<std::shared_ptr<T>, 0x8000> m_data;
|
||||||
|
std::atomic<u32> m_hint; // guessing next free position
|
||||||
std::mutex m_mutex; // TODO: remove it when shared_ptr atomic ops are fully available
|
std::mutex m_mutex; // TODO: remove it when shared_ptr atomic ops are fully available
|
||||||
|
|
||||||
|
public:
|
||||||
|
psv_object_list_t() : m_hint(0) {}
|
||||||
|
|
||||||
|
psv_object_list_t(const psv_object_list_t&) = delete;
|
||||||
|
psv_object_list_t(psv_object_list_t&&) = delete;
|
||||||
|
|
||||||
|
psv_object_list_t& operator =(const psv_object_list_t&) = delete;
|
||||||
|
psv_object_list_t& operator =(psv_object_list_t&&) = delete;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const u32 uid_class = type;
|
static const u32 uid_class = type;
|
||||||
|
|
||||||
|
@ -60,18 +70,18 @@ public:
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
for (auto& value : m_data)
|
for (u32 i = 0, j = m_hint % m_data.size(); i < m_data.size(); i++, j = (j + 1) % m_data.size())
|
||||||
{
|
{
|
||||||
// find an empty position and move the pointer
|
// find an empty position and copy the pointer
|
||||||
//std::shared_ptr<T> old_ptr = nullptr;
|
if (!m_data[j])
|
||||||
//if (std::atomic_compare_exchange_strong(&value, &old_ptr, data))
|
|
||||||
if (!value)
|
|
||||||
{
|
{
|
||||||
value = data;
|
m_data[j] = data;
|
||||||
|
m_hint = j + 1; // guess next position
|
||||||
psv_uid_t id = psv_uid_t::make(1); // odd number
|
psv_uid_t id = psv_uid_t::make(1); // odd number
|
||||||
id.type = uid_class; // set type
|
id.type = uid_class; // set type
|
||||||
id.number = &value - m_data.data(); // set position
|
id.number = j; // set position
|
||||||
return id.uid;
|
data->on_init(id.uid); // save UID
|
||||||
|
return id.uid; // return UID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,12 +96,14 @@ public:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const u32 pos = psv_uid_t::make(uid).number;
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
std::shared_ptr<T> old_ptr = nullptr;
|
std::shared_ptr<T> old_ptr = nullptr;
|
||||||
m_data[psv_uid_t::make(uid).number].swap(old_ptr);
|
m_data[pos].swap(old_ptr);
|
||||||
|
m_hint = pos;
|
||||||
return old_ptr;
|
return old_ptr;
|
||||||
//return std::atomic_exchange<std::shared_ptr<T>>(&m_data[psv_uid_t::make(uid).number], nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove all objects
|
// remove all objects
|
||||||
|
@ -99,10 +111,17 @@ public:
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
for (auto& value : m_data)
|
for (auto& object : m_data)
|
||||||
{
|
{
|
||||||
value = nullptr;
|
if (object)
|
||||||
|
{
|
||||||
|
object->on_stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
object = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_hint = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2500,39 +2500,16 @@ private:
|
||||||
}
|
}
|
||||||
void MFOCRF(u32 a, u32 rd, u32 crm)
|
void MFOCRF(u32 a, u32 rd, u32 crm)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
if(a)
|
|
||||||
{
|
|
||||||
u32 n = 0, count = 0;
|
|
||||||
for(u32 i = 0; i < 8; ++i)
|
|
||||||
{
|
|
||||||
if(crm & (1 << i))
|
|
||||||
{
|
|
||||||
n = i;
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(count == 1)
|
|
||||||
{
|
|
||||||
//RD[32+4*n : 32+4*n+3] = CR[4*n : 4*n+3];
|
|
||||||
u8 offset = n * 4;
|
|
||||||
CPU.GPR[rd] = (CPU.GPR[rd] & ~(0xf << offset)) | ((u32)CPU.GetCR(7 - n) << offset);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
CPU.GPR[rd] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*/
|
|
||||||
CPU.GPR[rd] = CPU.CR.CR;
|
CPU.GPR[rd] = CPU.CR.CR;
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
void LWARX(u32 rd, u32 ra, u32 rb)
|
void LWARX(u32 rd, u32 ra, u32 rb)
|
||||||
{
|
{
|
||||||
CPU.R_ADDR = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
const u32 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||||
CPU.R_VALUE = vm::get_ref<u32>(vm::cast(CPU.R_ADDR));
|
|
||||||
CPU.GPR[rd] = re32((u32)CPU.R_VALUE);
|
be_t<u32> value;
|
||||||
|
vm::reservation_acquire(&value, vm::cast(addr), sizeof(value));
|
||||||
|
|
||||||
|
CPU.GPR[rd] = value;
|
||||||
}
|
}
|
||||||
void LDX(u32 rd, u32 ra, u32 rb)
|
void LDX(u32 rd, u32 ra, u32 rb)
|
||||||
{
|
{
|
||||||
|
@ -2682,9 +2659,12 @@ private:
|
||||||
}
|
}
|
||||||
void LDARX(u32 rd, u32 ra, u32 rb)
|
void LDARX(u32 rd, u32 ra, u32 rb)
|
||||||
{
|
{
|
||||||
CPU.R_ADDR = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||||
CPU.R_VALUE = vm::get_ref<u64>(vm::cast(CPU.R_ADDR));
|
|
||||||
CPU.GPR[rd] = re64(CPU.R_VALUE);
|
be_t<u64> value;
|
||||||
|
vm::reservation_acquire(&value, vm::cast(addr), sizeof(value));
|
||||||
|
|
||||||
|
CPU.GPR[rd] = value;
|
||||||
}
|
}
|
||||||
void DCBF(u32 ra, u32 rb)
|
void DCBF(u32 ra, u32 rb)
|
||||||
{
|
{
|
||||||
|
@ -2800,15 +2780,8 @@ private:
|
||||||
{
|
{
|
||||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||||
|
|
||||||
if (CPU.R_ADDR == addr)
|
const be_t<u32> value = be_t<u32>::make((u32)CPU.GPR[rs]);
|
||||||
{
|
CPU.SetCR_EQ(0, vm::reservation_update(vm::cast(addr), &value, sizeof(value)));
|
||||||
CPU.SetCR_EQ(0, InterlockedCompareExchange(vm::get_ptr<volatile u32>(vm::cast(CPU.R_ADDR)), re32((u32)CPU.GPR[rs]), (u32)CPU.R_VALUE) == (u32)CPU.R_VALUE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CPU.SetCR_EQ(0, false);
|
|
||||||
}
|
|
||||||
CPU.R_ADDR = 0;
|
|
||||||
}
|
}
|
||||||
void STWX(u32 rs, u32 ra, u32 rb)
|
void STWX(u32 rs, u32 ra, u32 rb)
|
||||||
{
|
{
|
||||||
|
@ -2859,15 +2832,8 @@ private:
|
||||||
{
|
{
|
||||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||||
|
|
||||||
if (CPU.R_ADDR == addr)
|
const be_t<u64> value = be_t<u64>::make(CPU.GPR[rs]);
|
||||||
{
|
CPU.SetCR_EQ(0, vm::reservation_update(vm::cast(addr), &value, sizeof(value)));
|
||||||
CPU.SetCR_EQ(0, InterlockedCompareExchange(vm::get_ptr<volatile u64>(vm::cast(CPU.R_ADDR)), re64(CPU.GPR[rs]), CPU.R_VALUE) == CPU.R_VALUE);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CPU.SetCR_EQ(0, false);
|
|
||||||
}
|
|
||||||
CPU.R_ADDR = 0;
|
|
||||||
}
|
}
|
||||||
void STBX(u32 rs, u32 ra, u32 rb)
|
void STBX(u32 rs, u32 ra, u32 rb)
|
||||||
{
|
{
|
||||||
|
|
|
@ -2463,25 +2463,27 @@ void Compiler::MFOCRF(u32 a, u32 rd, u32 crm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::LWARX(u32 rd, u32 ra, u32 rb) {
|
void Compiler::LWARX(u32 rd, u32 ra, u32 rb) {
|
||||||
auto addr_i64 = GetGpr(rb);
|
throw __FUNCTION__;
|
||||||
if (ra) {
|
|
||||||
auto ra_i64 = GetGpr(ra);
|
//auto addr_i64 = GetGpr(rb);
|
||||||
addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
//if (ra) {
|
||||||
}
|
// auto ra_i64 = GetGpr(ra);
|
||||||
|
// addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||||
|
//}
|
||||||
|
|
||||||
auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR));
|
//auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR));
|
||||||
auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
|
//auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
|
||||||
m_ir_builder->CreateAlignedStore(addr_i64, resv_addr_i64_ptr, 8);
|
//m_ir_builder->CreateAlignedStore(addr_i64, resv_addr_i64_ptr, 8);
|
||||||
|
|
||||||
auto resv_val_i32 = ReadMemory(addr_i64, 32, 4, false, false);
|
//auto resv_val_i32 = ReadMemory(addr_i64, 32, 4, false, false);
|
||||||
auto resv_val_i64 = m_ir_builder->CreateZExt(resv_val_i32, m_ir_builder->getInt64Ty());
|
//auto resv_val_i64 = m_ir_builder->CreateZExt(resv_val_i32, m_ir_builder->getInt64Ty());
|
||||||
auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE));
|
//auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE));
|
||||||
auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
|
//auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
|
||||||
m_ir_builder->CreateAlignedStore(resv_val_i64, resv_val_i64_ptr, 8);
|
//m_ir_builder->CreateAlignedStore(resv_val_i64, resv_val_i64_ptr, 8);
|
||||||
|
|
||||||
resv_val_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt32Ty()), resv_val_i32);
|
//resv_val_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt32Ty()), resv_val_i32);
|
||||||
resv_val_i64 = m_ir_builder->CreateZExt(resv_val_i32, m_ir_builder->getInt64Ty());
|
//resv_val_i64 = m_ir_builder->CreateZExt(resv_val_i32, m_ir_builder->getInt64Ty());
|
||||||
SetGpr(rd, resv_val_i64);
|
//SetGpr(rd, resv_val_i64);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::LDX(u32 rd, u32 ra, u32 rb) {
|
void Compiler::LDX(u32 rd, u32 ra, u32 rb) {
|
||||||
|
@ -2739,23 +2741,25 @@ void Compiler::MULHW(u32 rd, u32 ra, u32 rb, bool rc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::LDARX(u32 rd, u32 ra, u32 rb) {
|
void Compiler::LDARX(u32 rd, u32 ra, u32 rb) {
|
||||||
auto addr_i64 = GetGpr(rb);
|
throw __FUNCTION__;
|
||||||
if (ra) {
|
|
||||||
auto ra_i64 = GetGpr(ra);
|
|
||||||
addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR));
|
//auto addr_i64 = GetGpr(rb);
|
||||||
auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
|
//if (ra) {
|
||||||
m_ir_builder->CreateAlignedStore(addr_i64, resv_addr_i64_ptr, 8);
|
// auto ra_i64 = GetGpr(ra);
|
||||||
|
// addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||||
|
//}
|
||||||
|
|
||||||
auto resv_val_i64 = ReadMemory(addr_i64, 64, 8, false);
|
//auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR));
|
||||||
auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE));
|
//auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
|
||||||
auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
|
//m_ir_builder->CreateAlignedStore(addr_i64, resv_addr_i64_ptr, 8);
|
||||||
m_ir_builder->CreateAlignedStore(resv_val_i64, resv_val_i64_ptr, 8);
|
|
||||||
|
|
||||||
resv_val_i64 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt64Ty()), resv_val_i64);
|
//auto resv_val_i64 = ReadMemory(addr_i64, 64, 8, false);
|
||||||
SetGpr(rd, resv_val_i64);
|
//auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE));
|
||||||
|
//auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
|
||||||
|
//m_ir_builder->CreateAlignedStore(resv_val_i64, resv_val_i64_ptr, 8);
|
||||||
|
|
||||||
|
//resv_val_i64 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, m_ir_builder->getInt64Ty()), resv_val_i64);
|
||||||
|
//SetGpr(rd, resv_val_i64);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::DCBF(u32 ra, u32 rb) {
|
void Compiler::DCBF(u32 ra, u32 rb) {
|
||||||
|
@ -2919,45 +2923,47 @@ void Compiler::STDX(u32 rs, u32 ra, u32 rb) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::STWCX_(u32 rs, u32 ra, u32 rb) {
|
void Compiler::STWCX_(u32 rs, u32 ra, u32 rb) {
|
||||||
auto addr_i64 = GetGpr(rb);
|
throw __FUNCTION__;
|
||||||
if (ra) {
|
|
||||||
auto ra_i64 = GetGpr(ra);
|
|
||||||
addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR));
|
//auto addr_i64 = GetGpr(rb);
|
||||||
auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
|
//if (ra) {
|
||||||
auto resv_addr_i64 = (Value *)m_ir_builder->CreateAlignedLoad(resv_addr_i64_ptr, 8);
|
// auto ra_i64 = GetGpr(ra);
|
||||||
auto cmp_i1 = m_ir_builder->CreateICmpEQ(addr_i64, resv_addr_i64);
|
// addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||||
|
//}
|
||||||
|
|
||||||
auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then");
|
//auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR));
|
||||||
auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "else");
|
//auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
|
||||||
auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge");
|
//auto resv_addr_i64 = (Value *)m_ir_builder->CreateAlignedLoad(resv_addr_i64_ptr, 8);
|
||||||
m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb);
|
//auto cmp_i1 = m_ir_builder->CreateICmpEQ(addr_i64, resv_addr_i64);
|
||||||
|
|
||||||
m_ir_builder->SetInsertPoint(then_bb);
|
//auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then");
|
||||||
auto rs_i32 = GetGpr(rs, 32);
|
//auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "else");
|
||||||
rs_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, rs_i32->getType()), rs_i32);
|
//auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge");
|
||||||
resv_addr_i64 = m_ir_builder->CreateAdd(resv_addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr<u8>(0)));
|
//m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb);
|
||||||
auto resv_addr_val_i32_ptr = m_ir_builder->CreateIntToPtr(resv_addr_i64, m_ir_builder->getInt32Ty()->getPointerTo());
|
|
||||||
auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE));
|
|
||||||
auto resv_val_i32_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo());
|
|
||||||
auto resv_val_i32 = m_ir_builder->CreateAlignedLoad(resv_val_i32_ptr, 8);
|
|
||||||
|
|
||||||
auto res_s = m_ir_builder->CreateAtomicCmpXchg(resv_addr_val_i32_ptr, resv_val_i32, rs_i32, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic);
|
//m_ir_builder->SetInsertPoint(then_bb);
|
||||||
auto success_i1 = m_ir_builder->CreateExtractValue(res_s, {1});
|
//auto rs_i32 = GetGpr(rs, 32);
|
||||||
auto cr_i32 = GetCr();
|
//rs_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, rs_i32->getType()), rs_i32);
|
||||||
cr_i32 = SetBit(cr_i32, 2, success_i1);
|
//resv_addr_i64 = m_ir_builder->CreateAdd(resv_addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr<u8>(0)));
|
||||||
SetCr(cr_i32);
|
//auto resv_addr_val_i32_ptr = m_ir_builder->CreateIntToPtr(resv_addr_i64, m_ir_builder->getInt32Ty()->getPointerTo());
|
||||||
m_ir_builder->CreateAlignedStore(m_ir_builder->getInt64(0), resv_addr_i64_ptr, 8);
|
//auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE));
|
||||||
m_ir_builder->CreateBr(merge_bb);
|
//auto resv_val_i32_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo());
|
||||||
|
//auto resv_val_i32 = m_ir_builder->CreateAlignedLoad(resv_val_i32_ptr, 8);
|
||||||
|
|
||||||
m_ir_builder->SetInsertPoint(else_bb);
|
//auto res_s = m_ir_builder->CreateAtomicCmpXchg(resv_addr_val_i32_ptr, resv_val_i32, rs_i32, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic);
|
||||||
cr_i32 = GetCr();
|
//auto success_i1 = m_ir_builder->CreateExtractValue(res_s, {1});
|
||||||
cr_i32 = ClrBit(cr_i32, 2);
|
//auto cr_i32 = GetCr();
|
||||||
SetCr(cr_i32);
|
//cr_i32 = SetBit(cr_i32, 2, success_i1);
|
||||||
m_ir_builder->CreateBr(merge_bb);
|
//SetCr(cr_i32);
|
||||||
m_ir_builder->SetInsertPoint(merge_bb);
|
//m_ir_builder->CreateAlignedStore(m_ir_builder->getInt64(0), resv_addr_i64_ptr, 8);
|
||||||
|
//m_ir_builder->CreateBr(merge_bb);
|
||||||
|
|
||||||
|
//m_ir_builder->SetInsertPoint(else_bb);
|
||||||
|
//cr_i32 = GetCr();
|
||||||
|
//cr_i32 = ClrBit(cr_i32, 2);
|
||||||
|
//SetCr(cr_i32);
|
||||||
|
//m_ir_builder->CreateBr(merge_bb);
|
||||||
|
//m_ir_builder->SetInsertPoint(merge_bb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::STWX(u32 rs, u32 ra, u32 rb) {
|
void Compiler::STWX(u32 rs, u32 ra, u32 rb) {
|
||||||
|
@ -3060,45 +3066,47 @@ void Compiler::SUBFZE(u32 rd, u32 ra, u32 oe, bool rc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::STDCX_(u32 rs, u32 ra, u32 rb) {
|
void Compiler::STDCX_(u32 rs, u32 ra, u32 rb) {
|
||||||
auto addr_i64 = GetGpr(rb);
|
throw __FUNCTION__;
|
||||||
if (ra) {
|
|
||||||
auto ra_i64 = GetGpr(ra);
|
|
||||||
addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR));
|
//auto addr_i64 = GetGpr(rb);
|
||||||
auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
|
//if (ra) {
|
||||||
auto resv_addr_i64 = (Value *)m_ir_builder->CreateAlignedLoad(resv_addr_i64_ptr, 8);
|
// auto ra_i64 = GetGpr(ra);
|
||||||
auto cmp_i1 = m_ir_builder->CreateICmpEQ(addr_i64, resv_addr_i64);
|
// addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||||
|
//}
|
||||||
|
|
||||||
auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then");
|
//auto resv_addr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_ADDR));
|
||||||
auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "else");
|
//auto resv_addr_i64_ptr = m_ir_builder->CreateBitCast(resv_addr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
|
||||||
auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge");
|
//auto resv_addr_i64 = (Value *)m_ir_builder->CreateAlignedLoad(resv_addr_i64_ptr, 8);
|
||||||
m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb);
|
//auto cmp_i1 = m_ir_builder->CreateICmpEQ(addr_i64, resv_addr_i64);
|
||||||
|
|
||||||
m_ir_builder->SetInsertPoint(then_bb);
|
//auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then");
|
||||||
auto rs_i64 = GetGpr(rs, 64);
|
//auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "else");
|
||||||
rs_i64 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, rs_i64->getType()), rs_i64);
|
//auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge");
|
||||||
resv_addr_i64 = m_ir_builder->CreateAdd(resv_addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr<u8>(0)));
|
//m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb);
|
||||||
auto resv_addr_val_i64_ptr = m_ir_builder->CreateIntToPtr(resv_addr_i64, m_ir_builder->getInt64Ty()->getPointerTo());
|
|
||||||
auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE));
|
|
||||||
auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
|
|
||||||
auto resv_val_i64 = m_ir_builder->CreateAlignedLoad(resv_val_i64_ptr, 8);
|
|
||||||
|
|
||||||
auto res_s = m_ir_builder->CreateAtomicCmpXchg(resv_addr_val_i64_ptr, resv_val_i64, rs_i64, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic);
|
//m_ir_builder->SetInsertPoint(then_bb);
|
||||||
auto success_i1 = m_ir_builder->CreateExtractValue(res_s, {1});
|
//auto rs_i64 = GetGpr(rs, 64);
|
||||||
auto cr_i32 = GetCr();
|
//rs_i64 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, rs_i64->getType()), rs_i64);
|
||||||
cr_i32 = SetBit(cr_i32, 2, success_i1);
|
//resv_addr_i64 = m_ir_builder->CreateAdd(resv_addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr<u8>(0)));
|
||||||
SetCr(cr_i32);
|
//auto resv_addr_val_i64_ptr = m_ir_builder->CreateIntToPtr(resv_addr_i64, m_ir_builder->getInt64Ty()->getPointerTo());
|
||||||
m_ir_builder->CreateAlignedStore(m_ir_builder->getInt64(0), resv_addr_i64_ptr, 8);
|
//auto resv_val_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, R_VALUE));
|
||||||
m_ir_builder->CreateBr(merge_bb);
|
//auto resv_val_i64_ptr = m_ir_builder->CreateBitCast(resv_val_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
|
||||||
|
//auto resv_val_i64 = m_ir_builder->CreateAlignedLoad(resv_val_i64_ptr, 8);
|
||||||
|
|
||||||
m_ir_builder->SetInsertPoint(else_bb);
|
//auto res_s = m_ir_builder->CreateAtomicCmpXchg(resv_addr_val_i64_ptr, resv_val_i64, rs_i64, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic);
|
||||||
cr_i32 = GetCr();
|
//auto success_i1 = m_ir_builder->CreateExtractValue(res_s, {1});
|
||||||
cr_i32 = ClrBit(cr_i32, 2);
|
//auto cr_i32 = GetCr();
|
||||||
SetCr(cr_i32);
|
//cr_i32 = SetBit(cr_i32, 2, success_i1);
|
||||||
m_ir_builder->CreateBr(merge_bb);
|
//SetCr(cr_i32);
|
||||||
m_ir_builder->SetInsertPoint(merge_bb);
|
//m_ir_builder->CreateAlignedStore(m_ir_builder->getInt64(0), resv_addr_i64_ptr, 8);
|
||||||
|
//m_ir_builder->CreateBr(merge_bb);
|
||||||
|
|
||||||
|
//m_ir_builder->SetInsertPoint(else_bb);
|
||||||
|
//cr_i32 = GetCr();
|
||||||
|
//cr_i32 = ClrBit(cr_i32, 2);
|
||||||
|
//SetCr(cr_i32);
|
||||||
|
//m_ir_builder->CreateBr(merge_bb);
|
||||||
|
//m_ir_builder->SetInsertPoint(merge_bb);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Compiler::STBX(u32 rs, u32 ra, u32 rb) {
|
void Compiler::STBX(u32 rs, u32 ra, u32 rb) {
|
||||||
|
|
|
@ -59,10 +59,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp
|
||||||
/// Time base register
|
/// Time base register
|
||||||
u64 TB;
|
u64 TB;
|
||||||
|
|
||||||
/// Reservations
|
|
||||||
u64 R_ADDR;
|
|
||||||
u64 R_VALUE;
|
|
||||||
|
|
||||||
/// Memory block
|
/// Memory block
|
||||||
u32 address;
|
u32 address;
|
||||||
u64 mem_block[64];
|
u64 mem_block[64];
|
||||||
|
@ -86,9 +82,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp
|
||||||
CTR = ppu.CTR;
|
CTR = ppu.CTR;
|
||||||
TB = ppu.TB;
|
TB = ppu.TB;
|
||||||
|
|
||||||
R_ADDR = ppu.R_ADDR;
|
|
||||||
R_VALUE = ppu.R_VALUE;
|
|
||||||
|
|
||||||
address = addr;
|
address = addr;
|
||||||
for (int i = 0; i < (sizeof(mem_block) / 8); i++) {
|
for (int i = 0; i < (sizeof(mem_block) / 8); i++) {
|
||||||
mem_block[i] = vm::read64(address + (i * 8));
|
mem_block[i] = vm::read64(address + (i * 8));
|
||||||
|
@ -114,9 +107,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp
|
||||||
ppu.CTR = CTR;
|
ppu.CTR = CTR;
|
||||||
ppu.TB = TB;
|
ppu.TB = TB;
|
||||||
|
|
||||||
ppu.R_ADDR = R_ADDR;
|
|
||||||
ppu.R_VALUE = R_VALUE;
|
|
||||||
|
|
||||||
for (int i = 0; i < (sizeof(mem_block) / 8); i++) {
|
for (int i = 0; i < (sizeof(mem_block) / 8); i++) {
|
||||||
vm::write64(address + (i * 8), mem_block[i]);
|
vm::write64(address + (i * 8), mem_block[i]);
|
||||||
}
|
}
|
||||||
|
@ -151,8 +141,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp
|
||||||
LR = rng();
|
LR = rng();
|
||||||
CTR = rng();
|
CTR = rng();
|
||||||
TB = rng();
|
TB = rng();
|
||||||
R_ADDR = rng();
|
|
||||||
R_VALUE = rng();
|
|
||||||
|
|
||||||
address = addr;
|
address = addr;
|
||||||
for (int i = 0; i < (sizeof(mem_block) / 8); i++) {
|
for (int i = 0; i < (sizeof(mem_block) / 8); i++) {
|
||||||
|
@ -187,7 +175,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp
|
||||||
// fmt::by_value(FPSCR.VXZDZ), fmt::by_value(FPSCR.VXIDI), fmt::by_value(FPSCR.VXISI), fmt::by_value(FPSCR.VXSNAN),
|
// 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));
|
// 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("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) {
|
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]);
|
ret += fmt::Format("mem_block[%d] = 0x%016llx mem_block[%d] = 0x%016llx\n", i, mem_block[i], i + 1, mem_block[i + 1]);
|
||||||
|
@ -724,8 +711,6 @@ void Compiler::RunAllTests() {
|
||||||
input.GPR[14] = 10;
|
input.GPR[14] = 10;
|
||||||
input.GPR[21] = 15;
|
input.GPR[21] = 15;
|
||||||
input.GPR[23] = 0x10000;
|
input.GPR[23] = 0x10000;
|
||||||
input.R_ADDR = 0x10000;
|
|
||||||
input.R_VALUE = 0x1122334455667788;
|
|
||||||
input.mem_block[0] = 0x8877665544332211;
|
input.mem_block[0] = 0x8877665544332211;
|
||||||
|
|
||||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LBZ, 0, input, 5, 0, 0x10000);
|
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LBZ, 0, input, 5, 0, 0x10000);
|
||||||
|
|
|
@ -536,11 +536,6 @@ public:
|
||||||
//TBR : Time-Base Registers
|
//TBR : Time-Base Registers
|
||||||
u64 TB; //TBR 0x10C - 0x10D
|
u64 TB; //TBR 0x10C - 0x10D
|
||||||
|
|
||||||
u64 cycle;
|
|
||||||
|
|
||||||
u64 R_ADDR; // reservation address
|
|
||||||
u64 R_VALUE; // reservation value (BE)
|
|
||||||
|
|
||||||
u32 owned_mutexes;
|
u32 owned_mutexes;
|
||||||
std::function<void(PPUThread& CPU)> custom_task;
|
std::function<void(PPUThread& CPU)> custom_task;
|
||||||
|
|
||||||
|
|
|
@ -99,8 +99,6 @@ void SPUThread::InitRegs()
|
||||||
|
|
||||||
m_event_mask = 0;
|
m_event_mask = 0;
|
||||||
m_events = 0;
|
m_events = 0;
|
||||||
|
|
||||||
R_ADDR = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SPUThread::InitStack()
|
void SPUThread::InitStack()
|
||||||
|
@ -437,103 +435,47 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
|
||||||
|
|
||||||
if (op == MFC_GETLLAR_CMD) // get reservation
|
if (op == MFC_GETLLAR_CMD) // get reservation
|
||||||
{
|
{
|
||||||
if (R_ADDR)
|
//std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||||
{
|
|
||||||
m_events |= SPU_EVENT_LR;
|
|
||||||
}
|
|
||||||
|
|
||||||
R_ADDR = ea;
|
vm::reservation_acquire(vm::get_ptr(ls_offset + lsa), ea, 128, [this]()
|
||||||
for (u32 i = 0; i < 16; i++)
|
|
||||||
{
|
{
|
||||||
R_DATA[i] = vm::get_ptr<u64>((u32)R_ADDR)[i];
|
//std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(tid);
|
||||||
vm::get_ptr<u64>(ls_offset + lsa)[i] = R_DATA[i];
|
|
||||||
}
|
//if (t && (t->GetType() == CPU_THREAD_SPU || t->GetType() == CPU_THREAD_RAW_SPU))
|
||||||
|
//{
|
||||||
|
// SPUThread& spu = static_cast<SPUThread&>(*t);
|
||||||
|
|
||||||
|
// spu.m_events |= SPU_EVENT_LR; // TODO: atomic op
|
||||||
|
// spu.Notify();
|
||||||
|
//}
|
||||||
|
|
||||||
|
m_events |= SPU_EVENT_LR; // TODO: atomic op
|
||||||
|
Notify();
|
||||||
|
});
|
||||||
|
|
||||||
MFCArgs.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS);
|
MFCArgs.AtomicStat.PushUncond(MFC_GETLLAR_SUCCESS);
|
||||||
}
|
}
|
||||||
else if (op == MFC_PUTLLC_CMD) // store conditional
|
else if (op == MFC_PUTLLC_CMD) // store conditional
|
||||||
{
|
{
|
||||||
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS);
|
if (vm::reservation_update(ea, vm::get_ptr(ls_offset + lsa), 128))
|
||||||
|
|
||||||
if (R_ADDR == ea)
|
|
||||||
{
|
{
|
||||||
u32 changed = 0, mask = 0;
|
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS);
|
||||||
u64 buf[16];
|
|
||||||
for (u32 i = 0; i < 16; 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>((u32)R_ADDR)[i] != R_DATA[i])
|
|
||||||
{
|
|
||||||
m_events |= SPU_EVENT_LR;
|
|
||||||
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE);
|
|
||||||
R_ADDR = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 i = 0; i < 16; i++)
|
|
||||||
{
|
|
||||||
if (buf[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);
|
|
||||||
|
|
||||||
if (changed > 1)
|
|
||||||
{
|
|
||||||
LOG_ERROR(Log::SPU, "MFC_PUTLLC_CMD: Memory corrupted (~x%d (mask=0x%x)) (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)",
|
|
||||||
changed, mask, op, cmd, lsa, ea, tag, size);
|
|
||||||
Emu.Pause();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changed > 1)
|
|
||||||
{
|
|
||||||
LOG_WARNING(Log::SPU, "MFC_PUTLLC_CMD: Reservation impossibru (~x%d (mask=0x%x)) (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)",
|
|
||||||
changed, mask, op, cmd, lsa, ea, tag, size);
|
|
||||||
|
|
||||||
SPUDisAsm dis_asm(CPUDisAsm_InterpreterMode);
|
|
||||||
for (s32 i = (s32)PC; i < (s32)PC + 4 * 7; i += 4)
|
|
||||||
{
|
|
||||||
dis_asm.dump_pc = i;
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
LOG_NOTICE(Log::SPU, "*** %s", dis_asm.last_opcode.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE);
|
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_FAILURE);
|
||||||
}
|
}
|
||||||
R_ADDR = 0;
|
|
||||||
}
|
}
|
||||||
else // store unconditional
|
else // store unconditional (may be wrong)
|
||||||
{
|
{
|
||||||
if (R_ADDR) // may be wrong
|
vm::reservation_break(ea);
|
||||||
{
|
|
||||||
m_events |= SPU_EVENT_LR;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128);
|
ProcessCmd(MFC_PUT_CMD, tag, lsa, ea, 128);
|
||||||
|
|
||||||
if (op == MFC_PUTLLUC_CMD)
|
if (op == MFC_PUTLLUC_CMD)
|
||||||
{
|
{
|
||||||
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLUC_SUCCESS);
|
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLUC_SUCCESS);
|
||||||
}
|
}
|
||||||
R_ADDR = 0;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -548,19 +490,6 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
|
||||||
bool SPUThread::CheckEvents()
|
bool SPUThread::CheckEvents()
|
||||||
{
|
{
|
||||||
// checks events:
|
// checks events:
|
||||||
// SPU_EVENT_LR:
|
|
||||||
if (R_ADDR)
|
|
||||||
{
|
|
||||||
for (u32 i = 0; i < 16; i++)
|
|
||||||
{
|
|
||||||
if (vm::get_ptr<u64>((u32)R_ADDR)[i] != R_DATA[i])
|
|
||||||
{
|
|
||||||
m_events |= SPU_EVENT_LR;
|
|
||||||
R_ADDR = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (m_events & m_event_mask) != 0;
|
return (m_events & m_event_mask) != 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -277,9 +277,6 @@ public:
|
||||||
u32 SRR0;
|
u32 SRR0;
|
||||||
SPU_SNRConfig_hdr cfg; // Signal Notification Registers Configuration (OR-mode enabled: 0x1 for SNR1, 0x2 for SNR2)
|
SPU_SNRConfig_hdr cfg; // Signal Notification Registers Configuration (OR-mode enabled: 0x1 for SNR1, 0x2 for SNR2)
|
||||||
|
|
||||||
u64 R_ADDR; // reservation address
|
|
||||||
u64 R_DATA[16]; // lock line data (BE)
|
|
||||||
|
|
||||||
std::shared_ptr<EventPort> SPUPs[64]; // SPU Thread Event Ports
|
std::shared_ptr<EventPort> SPUPs[64]; // SPU Thread Event Ports
|
||||||
EventManager SPUQs; // SPU Queue Mapping
|
EventManager SPUQs; // SPU Queue Mapping
|
||||||
std::shared_ptr<SpuGroupInfo> group; // associated SPU Thread Group (null for raw spu)
|
std::shared_ptr<SpuGroupInfo> group; // associated SPU Thread Group (null for raw spu)
|
||||||
|
|
|
@ -102,20 +102,17 @@ void MemoryBase::Init(MemoryType type)
|
||||||
memset(m_pages, 0, sizeof(m_pages));
|
memset(m_pages, 0, sizeof(m_pages));
|
||||||
memset(RawSPUMem, 0, sizeof(RawSPUMem));
|
memset(RawSPUMem, 0, sizeof(RawSPUMem));
|
||||||
|
|
||||||
|
LOG_NOTICE(MEMORY, "Initializing memory: base_addr = 0x%llx, priv_addr = 0x%llx", (u64)vm::g_base_addr, (u64)vm::g_priv_addr);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (!vm::g_base_addr)
|
if (!vm::g_base_addr || !vm::g_priv_addr)
|
||||||
#else
|
#else
|
||||||
if ((s64)vm::g_base_addr == (s64)-1)
|
if ((s64)vm::g_base_addr == (s64)-1 || (s64)vm::g_priv_addr == (s64)-1)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
LOG_ERROR(MEMORY, "Initializing memory failed");
|
LOG_ERROR(MEMORY, "Initializing memory failed");
|
||||||
assert(0);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_NOTICE(MEMORY, "Initializing memory: base_addr = 0x%llx", (u64)vm::g_base_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
@ -207,7 +204,7 @@ bool MemoryBase::Map(const u64 addr, const u32 size)
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryBlocks.push_back((new MemoryBlock())->SetRange(addr, size));
|
MemoryBlocks.push_back((new MemoryBlock())->SetRange(addr, size));
|
||||||
|
|
||||||
LOG_WARNING(MEMORY, "Memory mapped at 0x%llx: size=0x%x", addr, size);
|
LOG_WARNING(MEMORY, "Memory mapped at 0x%llx: size=0x%x", addr, size);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -231,20 +228,14 @@ bool MemoryBase::Unmap(const u64 addr)
|
||||||
MemBlockInfo::MemBlockInfo(u64 _addr, u32 _size)
|
MemBlockInfo::MemBlockInfo(u64 _addr, u32 _size)
|
||||||
: MemInfo(_addr, PAGE_4K(_size))
|
: MemInfo(_addr, PAGE_4K(_size))
|
||||||
{
|
{
|
||||||
void* real_addr = (void*)((u64)Memory.GetBaseAddr() + _addr);
|
void* real_addr = vm::get_ptr(vm::cast(_addr));
|
||||||
|
void* priv_addr = vm::get_priv_ptr(vm::cast(_addr));
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
mem = VirtualAlloc(real_addr, size, MEM_COMMIT, PAGE_READWRITE);
|
if (!VirtualAlloc(priv_addr, size, MEM_COMMIT, PAGE_READWRITE) || !VirtualAlloc(real_addr, size, MEM_COMMIT, PAGE_READWRITE))
|
||||||
#else
|
#else
|
||||||
if (::mprotect(real_addr, size, PROT_READ | PROT_WRITE))
|
if (mprotect(real_addr, size, PROT_READ | PROT_WRITE) || mprotect(priv_addr, size, PROT_READ | PROT_WRITE))
|
||||||
{
|
|
||||||
mem = nullptr;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mem = real_addr;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
if (mem != real_addr)
|
|
||||||
{
|
{
|
||||||
LOG_ERROR(MEMORY, "Memory allocation failed (addr=0x%llx, size=0x%x)", addr, size);
|
LOG_ERROR(MEMORY, "Memory allocation failed (addr=0x%llx, size=0x%x)", addr, size);
|
||||||
Emu.Pause();
|
Emu.Pause();
|
||||||
|
@ -252,7 +243,9 @@ MemBlockInfo::MemBlockInfo(u64 _addr, u32 _size)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Memory.RegisterPages(_addr, PAGE_4K(_size));
|
Memory.RegisterPages(_addr, PAGE_4K(_size));
|
||||||
memset(mem, 0, size);
|
|
||||||
|
mem = real_addr;
|
||||||
|
memset(mem, 0, size); // ???
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,9 +255,11 @@ void MemBlockInfo::Free()
|
||||||
{
|
{
|
||||||
Memory.UnregisterPages(addr, size);
|
Memory.UnregisterPages(addr, size);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (!VirtualFree(mem, size, MEM_DECOMMIT))
|
DWORD old;
|
||||||
|
|
||||||
|
if (!VirtualProtect(mem, size, PAGE_NOACCESS, &old) || !VirtualProtect(vm::get_priv_ptr(vm::cast(addr)), size, PAGE_NOACCESS, &old))
|
||||||
#else
|
#else
|
||||||
if (::mprotect(mem, size, PROT_NONE))
|
if (mprotect(mem, size, PROT_NONE) || mprotect(vm::get_priv_ptr(vm::cast(addr)), size, PROT_NONE))
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
LOG_ERROR(MEMORY, "Memory deallocation failed (addr=0x%llx, size=0x%x)", addr, size);
|
LOG_ERROR(MEMORY, "Memory deallocation failed (addr=0x%llx, size=0x%x)", addr, size);
|
||||||
|
@ -437,7 +432,7 @@ u64 DynamicMemoryBlockBase::AllocAlign(u32 size, u32 align)
|
||||||
LOG_ERROR(MEMORY, "DynamicMemoryBlockBase::AllocAlign(size=0x%x, align=0x%x): memory block not initialized", size, align);
|
LOG_ERROR(MEMORY, "DynamicMemoryBlockBase::AllocAlign(size=0x%x, align=0x%x): memory block not initialized", size, align);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size = PAGE_4K(size);
|
size = PAGE_4K(size);
|
||||||
u32 exsize;
|
u32 exsize;
|
||||||
|
|
||||||
|
@ -715,4 +710,4 @@ bool VirtualMemoryBlock::Unreserve(u32 size)
|
||||||
u32 VirtualMemoryBlock::GetReservedAmount()
|
u32 VirtualMemoryBlock::GetReservedAmount()
|
||||||
{
|
{
|
||||||
return m_reserve_size;
|
return m_reserve_size;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,322 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
#include "Utilities/Log.h"
|
||||||
#include "Memory.h"
|
#include "Memory.h"
|
||||||
|
#include "Emu/System.h"
|
||||||
#include "Emu/CPU/CPUThread.h"
|
#include "Emu/CPU/CPUThread.h"
|
||||||
#include "Emu/Cell/PPUThread.h"
|
#include "Emu/Cell/PPUThread.h"
|
||||||
#include "Emu/ARMv7/ARMv7Thread.h"
|
#include "Emu/ARMv7/ARMv7Thread.h"
|
||||||
|
|
||||||
|
#include "Emu/SysCalls/lv2/sys_time.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <Windows.h>
|
||||||
|
#else
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
/* OS X uses MAP_ANON instead of MAP_ANONYMOUS */
|
||||||
|
#ifndef MAP_ANONYMOUS
|
||||||
|
#define MAP_ANONYMOUS MAP_ANON
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace vm
|
namespace vm
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <Windows.h>
|
HANDLE g_memory_handle;
|
||||||
void* const g_base_addr = VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS);
|
#endif
|
||||||
#else
|
|
||||||
#include <sys/mman.h>
|
|
||||||
|
|
||||||
/* OS X uses MAP_ANON instead of MAP_ANONYMOUS */
|
void* g_priv_addr;
|
||||||
#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);
|
void* initialize()
|
||||||
#endif
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
g_memory_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_RESERVE, 0x1, 0x0, NULL);
|
||||||
|
|
||||||
|
void* base_addr = MapViewOfFile(g_memory_handle, PAGE_NOACCESS, 0, 0, 0x100000000); // main memory
|
||||||
|
g_priv_addr = MapViewOfFile(g_memory_handle, PAGE_NOACCESS, 0, 0, 0x100000000); // memory mirror for privileged access
|
||||||
|
|
||||||
|
return base_addr;
|
||||||
|
|
||||||
|
//return VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS);
|
||||||
|
#else
|
||||||
|
//shm_unlink("/rpcs3_vm");
|
||||||
|
|
||||||
|
int memory_handle = shm_open("/rpcs3_vm", O_RDWR | O_CREAT | O_EXCL, 0);
|
||||||
|
|
||||||
|
if (memory_handle == -1)
|
||||||
|
{
|
||||||
|
printf("shm_open() failed\n");
|
||||||
|
return (void*)-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ftruncate(memory_handle, 0x100000000);
|
||||||
|
|
||||||
|
void* base_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_SHARED, memory_handle, 0);
|
||||||
|
g_priv_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_SHARED, memory_handle, 0);
|
||||||
|
|
||||||
|
shm_unlink("/rpcs3_vm");
|
||||||
|
|
||||||
|
return base_addr;
|
||||||
|
|
||||||
|
//return mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void finalize()
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
UnmapViewOfFile(g_base_addr);
|
||||||
|
UnmapViewOfFile(g_priv_addr);
|
||||||
|
CloseHandle(g_memory_handle);
|
||||||
|
#else
|
||||||
|
munmap(g_base_addr, 0x100000000);
|
||||||
|
munmap(g_priv_addr, 0x100000000);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void* const g_base_addr = (atexit(finalize), initialize());
|
||||||
|
|
||||||
|
class reservation_mutex_t
|
||||||
|
{
|
||||||
|
std::atomic<NamedThreadBase*> m_owner;
|
||||||
|
std::condition_variable m_cv;
|
||||||
|
std::mutex m_cv_mutex;
|
||||||
|
|
||||||
|
public:
|
||||||
|
reservation_mutex_t()
|
||||||
|
: m_owner(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool do_notify;
|
||||||
|
|
||||||
|
__noinline void lock()
|
||||||
|
{
|
||||||
|
NamedThreadBase* owner = GetCurrentNamedThread();
|
||||||
|
NamedThreadBase* old = nullptr;
|
||||||
|
|
||||||
|
while (!m_owner.compare_exchange_strong(old, owner))
|
||||||
|
{
|
||||||
|
std::unique_lock<std::mutex> cv_lock(m_cv_mutex);
|
||||||
|
|
||||||
|
m_cv.wait_for(cv_lock, std::chrono::milliseconds(1));
|
||||||
|
|
||||||
|
if (old == owner)
|
||||||
|
{
|
||||||
|
throw __FUNCTION__;
|
||||||
|
}
|
||||||
|
|
||||||
|
old = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
do_notify = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
__noinline void unlock()
|
||||||
|
{
|
||||||
|
NamedThreadBase* owner = GetCurrentNamedThread();
|
||||||
|
|
||||||
|
if (!m_owner.compare_exchange_strong(owner, nullptr))
|
||||||
|
{
|
||||||
|
throw __FUNCTION__;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (do_notify)
|
||||||
|
{
|
||||||
|
m_cv.notify_one();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
std::function<void()> g_reservation_cb = nullptr;
|
||||||
|
NamedThreadBase* g_reservation_owner = nullptr;
|
||||||
|
|
||||||
|
u32 g_reservation_addr = 0;
|
||||||
|
|
||||||
|
reservation_mutex_t g_reservation_mutex;
|
||||||
|
|
||||||
|
void _reservation_set(u32 addr)
|
||||||
|
{
|
||||||
|
//const auto stamp0 = get_time();
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
DWORD old;
|
||||||
|
if (!VirtualProtect(vm::get_ptr(addr & ~0xfff), 4096, PAGE_READONLY, &old))
|
||||||
|
#else
|
||||||
|
if (mprotect(vm::get_ptr(addr & ~0xfff), 4096, PROT_READ))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
throw fmt::format("vm::_reservation_set() failed (addr=0x%x)", addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//LOG_NOTICE(MEMORY, "VirtualProtect: %f us", (get_time() - stamp0) / 80.f);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _reservation_break(u32 addr)
|
||||||
|
{
|
||||||
|
if (g_reservation_addr >> 12 == addr >> 12)
|
||||||
|
{
|
||||||
|
//const auto stamp0 = get_time();
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (!VirtualAlloc(vm::get_ptr(addr & ~0xfff), 4096, MEM_COMMIT, PAGE_READWRITE))
|
||||||
|
#else
|
||||||
|
if (mprotect(vm::get_ptr(addr & ~0xfff), 4096, PROT_READ | PROT_WRITE))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
throw fmt::format("vm::_reservation_break() failed (addr=0x%x)", addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
//LOG_NOTICE(MEMORY, "VirtualAlloc: %f us", (get_time() - stamp0) / 80.f);
|
||||||
|
|
||||||
|
if (g_reservation_cb)
|
||||||
|
{
|
||||||
|
g_reservation_cb();
|
||||||
|
g_reservation_cb = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_reservation_owner = nullptr;
|
||||||
|
g_reservation_addr = 0;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool reservation_break(u32 addr)
|
||||||
|
{
|
||||||
|
std::lock_guard<reservation_mutex_t> lock(g_reservation_mutex);
|
||||||
|
|
||||||
|
return _reservation_break(addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool reservation_acquire(void* data, u32 addr, u32 size, const std::function<void()>& callback)
|
||||||
|
{
|
||||||
|
//const auto stamp0 = get_time();
|
||||||
|
|
||||||
|
bool broken = false;
|
||||||
|
|
||||||
|
assert(size == 1 || size == 2 || size == 4 || size == 8 || size == 128);
|
||||||
|
assert((addr + size & ~0xfff) == (addr & ~0xfff));
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard<reservation_mutex_t> lock(g_reservation_mutex);
|
||||||
|
|
||||||
|
// silent unlocking to prevent priority boost for threads going to break reservation
|
||||||
|
//g_reservation_mutex.do_notify = false;
|
||||||
|
|
||||||
|
// break previous reservation
|
||||||
|
if (g_reservation_addr)
|
||||||
|
{
|
||||||
|
broken = _reservation_break(g_reservation_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// change memory protection to read-only
|
||||||
|
_reservation_set(addr);
|
||||||
|
|
||||||
|
// may not be necessary, just for sure:
|
||||||
|
_mm_mfence();
|
||||||
|
|
||||||
|
// set additional information
|
||||||
|
g_reservation_addr = addr;
|
||||||
|
g_reservation_owner = GetCurrentNamedThread();
|
||||||
|
g_reservation_cb = callback;
|
||||||
|
|
||||||
|
// copy data
|
||||||
|
memcpy(data, vm::get_ptr(addr), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return broken;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool reservation_update(u32 addr, const void* data, u32 size)
|
||||||
|
{
|
||||||
|
assert(size == 1 || size == 2 || size == 4 || size == 8 || size == 128);
|
||||||
|
assert((addr + size & ~0xfff) == (addr & ~0xfff));
|
||||||
|
|
||||||
|
std::lock_guard<reservation_mutex_t> lock(g_reservation_mutex);
|
||||||
|
|
||||||
|
if (g_reservation_addr != addr || g_reservation_owner != GetCurrentNamedThread())
|
||||||
|
{
|
||||||
|
// atomic update failed
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update memory using privileged access
|
||||||
|
memcpy(vm::get_priv_ptr(addr), data, size);
|
||||||
|
|
||||||
|
// free the reservation and restore memory protection
|
||||||
|
_reservation_break(addr);
|
||||||
|
|
||||||
|
// atomic update succeeded
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool reservation_query(u32 addr)
|
||||||
|
{
|
||||||
|
std::lock_guard<reservation_mutex_t> lock(g_reservation_mutex);
|
||||||
|
|
||||||
|
{
|
||||||
|
LV2_LOCK(0);
|
||||||
|
|
||||||
|
if (!Memory.IsGoodAddr(addr))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// break the reservation
|
||||||
|
_reservation_break(addr);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reservation_free()
|
||||||
|
{
|
||||||
|
std::lock_guard<reservation_mutex_t> lock(g_reservation_mutex);
|
||||||
|
|
||||||
|
if (g_reservation_owner == GetCurrentNamedThread())
|
||||||
|
{
|
||||||
|
_reservation_break(g_reservation_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void reservation_op(u32 addr, u32 size, std::function<void()> proc)
|
||||||
|
{
|
||||||
|
assert(size == 1 || size == 2 || size == 4 || size == 8 || size == 128);
|
||||||
|
assert((addr + size & ~0xfff) == (addr & ~0xfff));
|
||||||
|
|
||||||
|
std::lock_guard<reservation_mutex_t> lock(g_reservation_mutex);
|
||||||
|
|
||||||
|
// break previous reservation
|
||||||
|
if (g_reservation_addr)
|
||||||
|
{
|
||||||
|
_reservation_break(g_reservation_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// change memory protection to read-only
|
||||||
|
_reservation_set(addr);
|
||||||
|
|
||||||
|
// set additional information
|
||||||
|
g_reservation_addr = addr;
|
||||||
|
g_reservation_owner = GetCurrentNamedThread();
|
||||||
|
g_reservation_cb = nullptr;
|
||||||
|
|
||||||
|
// may not be necessary, just for sure:
|
||||||
|
_mm_mfence();
|
||||||
|
|
||||||
|
// do the operation
|
||||||
|
proc();
|
||||||
|
|
||||||
|
// remove the reservation
|
||||||
|
_reservation_break(addr);
|
||||||
|
}
|
||||||
|
|
||||||
bool check_addr(u32 addr)
|
bool check_addr(u32 addr)
|
||||||
{
|
{
|
||||||
|
@ -62,8 +360,12 @@ namespace vm
|
||||||
{
|
{
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(!real_pointer);
|
if (real_pointer)
|
||||||
|
{
|
||||||
|
throw fmt::format("vm::get_addr(0x%016llx) failed: not a part of virtual memory", (u64)real_pointer);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,4 +565,4 @@ namespace vm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,24 @@ namespace vm
|
||||||
static void set_stack_size(u32 size) {}
|
static void set_stack_size(u32 size) {}
|
||||||
static void initialize_stack() {}
|
static void initialize_stack() {}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
extern HANDLE g_memory_handle;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern void* g_priv_addr;
|
||||||
extern void* const g_base_addr;
|
extern void* const g_base_addr;
|
||||||
|
|
||||||
|
// break the reservation, return true if it was successfully broken
|
||||||
|
bool reservation_break(u32 addr);
|
||||||
|
// read memory and reserve it for further atomic update, return true if the previous reservation was broken
|
||||||
|
bool reservation_acquire(void* data, u32 addr, u32 size, const std::function<void()>& callback = nullptr);
|
||||||
|
// attempt to atomically update reserved memory
|
||||||
|
bool reservation_update(u32 addr, const void* data, u32 size);
|
||||||
|
bool reservation_query(u32 addr);
|
||||||
|
void reservation_free();
|
||||||
|
// perform complete operation
|
||||||
|
void reservation_op(u32 addr, u32 size, std::function<void()> proc);
|
||||||
|
|
||||||
bool map(u32 addr, u32 size, u32 flags);
|
bool map(u32 addr, u32 size, u32 flags);
|
||||||
bool unmap(u32 addr, u32 size = 0, u32 flags = 0);
|
bool unmap(u32 addr, u32 size = 0, u32 flags = 0);
|
||||||
u32 alloc(u32 size, memory_location location = user_space);
|
u32 alloc(u32 size, memory_location location = user_space);
|
||||||
|
@ -40,6 +57,18 @@ namespace vm
|
||||||
return *get_ptr<T>(addr);
|
return *get_ptr<T>(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T = void>
|
||||||
|
T* const get_priv_ptr(u32 addr)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<T*>(static_cast<u8*>(g_priv_addr) + addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
T& get_priv_ref(u32 addr)
|
||||||
|
{
|
||||||
|
return *get_priv_ptr<T>(addr);
|
||||||
|
}
|
||||||
|
|
||||||
u32 get_addr(const void* real_pointer);
|
u32 get_addr(const void* real_pointer);
|
||||||
|
|
||||||
__noinline void error(const u64 addr, const char* func);
|
__noinline void error(const u64 addr, const char* func);
|
||||||
|
|
|
@ -213,6 +213,11 @@ namespace vm
|
||||||
{
|
{
|
||||||
return vm::get_ptr<T>(vm::cast(m_addr));
|
return vm::get_ptr<T>(vm::cast(m_addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
T* get_priv_ptr() const
|
||||||
|
{
|
||||||
|
return vm::get_priv_ptr<T>(vm::cast(m_addr));
|
||||||
|
}
|
||||||
|
|
||||||
static const _ptr_base make(const AT& addr)
|
static const _ptr_base make(const AT& addr)
|
||||||
{
|
{
|
||||||
|
@ -243,6 +248,11 @@ namespace vm
|
||||||
return vm::get_ptr<void>(vm::cast(m_addr));
|
return vm::get_ptr<void>(vm::cast(m_addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* get_priv_ptr() const
|
||||||
|
{
|
||||||
|
return vm::get_priv_ptr<void>(vm::cast(m_addr));
|
||||||
|
}
|
||||||
|
|
||||||
explicit operator void*() const
|
explicit operator void*() const
|
||||||
{
|
{
|
||||||
return get_ptr();
|
return get_ptr();
|
||||||
|
@ -301,6 +311,11 @@ namespace vm
|
||||||
return vm::get_ptr<const void>(vm::cast(m_addr));
|
return vm::get_ptr<const void>(vm::cast(m_addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const void* get_priv_ptr() const
|
||||||
|
{
|
||||||
|
return vm::get_priv_ptr<const void>(vm::cast(m_addr));
|
||||||
|
}
|
||||||
|
|
||||||
explicit operator const void*() const
|
explicit operator const void*() const
|
||||||
{
|
{
|
||||||
return get_ptr();
|
return get_ptr();
|
||||||
|
|
|
@ -136,7 +136,7 @@ const char *getModuleName(int id) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return "UNKNOWN MODULE";
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellSysmoduleInitialize()
|
int cellSysmoduleInitialize()
|
||||||
|
@ -159,11 +159,12 @@ int cellSysmoduleSetMemcontainer(u32 ct_id)
|
||||||
|
|
||||||
int cellSysmoduleLoadModule(u16 id)
|
int cellSysmoduleLoadModule(u16 id)
|
||||||
{
|
{
|
||||||
|
cellSysmodule->Warning("cellSysmoduleLoadModule(id=0x%04x: %s)", id, getModuleName(id));
|
||||||
|
|
||||||
if (id == 0xf054)
|
if (id == 0xf054)
|
||||||
{
|
{
|
||||||
cellSysmodule->Todo("cellSysmoduleLoadModule: CELL_SYSMODULE_LIBATRAC3MULTI");
|
cellSysmodule->Todo("cellSysmoduleLoadModule: CELL_SYSMODULE_LIBATRAC3MULTI");
|
||||||
}
|
}
|
||||||
cellSysmodule->Warning("cellSysmoduleLoadModule(%s)", getModuleName(id));
|
|
||||||
|
|
||||||
if (Module* m = Emu.GetModuleManager().GetModuleById(id))
|
if (Module* m = Emu.GetModuleManager().GetModuleById(id))
|
||||||
{
|
{
|
||||||
|
@ -180,7 +181,8 @@ int cellSysmoduleLoadModule(u16 id)
|
||||||
|
|
||||||
int cellSysmoduleUnloadModule(u16 id)
|
int cellSysmoduleUnloadModule(u16 id)
|
||||||
{
|
{
|
||||||
cellSysmodule->Warning("cellSysmoduleUnloadModule(%s)", getModuleName(id));
|
cellSysmodule->Warning("cellSysmoduleUnloadModule(id=0x%04x: %s)", id, getModuleName(id));
|
||||||
|
|
||||||
Module* m = Emu.GetModuleManager().GetModuleById(id);
|
Module* m = Emu.GetModuleManager().GetModuleById(id);
|
||||||
|
|
||||||
if(!m)
|
if(!m)
|
||||||
|
@ -199,7 +201,8 @@ int cellSysmoduleUnloadModule(u16 id)
|
||||||
|
|
||||||
int cellSysmoduleIsLoaded(u16 id)
|
int cellSysmoduleIsLoaded(u16 id)
|
||||||
{
|
{
|
||||||
cellSysmodule->Warning("cellSysmoduleIsLoaded(%s)", getModuleName(id));
|
cellSysmodule->Warning("cellSysmoduleIsLoaded(id=0x%04x: %s)", id, getModuleName(id));
|
||||||
|
|
||||||
Module* m = Emu.GetModuleManager().GetModuleById(id);
|
Module* m = Emu.GetModuleManager().GetModuleById(id);
|
||||||
|
|
||||||
if(!m)
|
if(!m)
|
||||||
|
|
|
@ -395,7 +395,7 @@ s32 cellFsFsync(u32 fd)
|
||||||
|
|
||||||
s32 cellFsRmdir(vm::ptr<const char> path)
|
s32 cellFsRmdir(vm::ptr<const char> path)
|
||||||
{
|
{
|
||||||
sys_fs->Warning("cellFsRmdir(path=0x%x)", path.get_ptr());
|
sys_fs->Warning("cellFsRmdir(path=0x%x)", path);
|
||||||
|
|
||||||
std::string _path = path.get_ptr();
|
std::string _path = path.get_ptr();
|
||||||
|
|
||||||
|
|
|
@ -349,6 +349,8 @@ void Emulator::Resume()
|
||||||
GetCallbackManager().RunPauseCallbacks(false);
|
GetCallbackManager().RunPauseCallbacks(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern std::map<u32, std::string> g_armv7_dump;
|
||||||
|
|
||||||
void Emulator::Stop()
|
void Emulator::Stop()
|
||||||
{
|
{
|
||||||
if(IsStopped()) return;
|
if(IsStopped()) return;
|
||||||
|
@ -365,6 +367,14 @@ void Emulator::Stop()
|
||||||
|
|
||||||
finalize_psv_modules();
|
finalize_psv_modules();
|
||||||
clear_all_psv_objects();
|
clear_all_psv_objects();
|
||||||
|
|
||||||
|
for (auto& v : g_armv7_dump)
|
||||||
|
{
|
||||||
|
LOG_NOTICE(ARMv7, v.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_armv7_dump.clear();
|
||||||
|
|
||||||
m_rsx_callback = 0;
|
m_rsx_callback = 0;
|
||||||
|
|
||||||
// TODO: check finalization order
|
// TODO: check finalization order
|
||||||
|
|
|
@ -401,8 +401,8 @@ namespace loader
|
||||||
armv7_decoder_initialize(code_start, code_end);
|
armv7_decoder_initialize(code_start, code_end);
|
||||||
|
|
||||||
const std::string& thread_name = proc_param->sceUserMainThreadName ? proc_param->sceUserMainThreadName.get_ptr() : "main_thread";
|
const std::string& thread_name = proc_param->sceUserMainThreadName ? proc_param->sceUserMainThreadName.get_ptr() : "main_thread";
|
||||||
const u32 stack_size = proc_param->sceUserMainThreadStackSize ? *proc_param->sceUserMainThreadStackSize : 0;
|
const u32 stack_size = proc_param->sceUserMainThreadStackSize ? *proc_param->sceUserMainThreadStackSize : 256 * 1024;
|
||||||
const u32 priority = proc_param->sceUserMainThreadPriority ? *proc_param->sceUserMainThreadPriority : 0;
|
const u32 priority = proc_param->sceUserMainThreadPriority ? *proc_param->sceUserMainThreadPriority : 160;
|
||||||
|
|
||||||
armv7_thread(entry, thread_name, stack_size, priority).args({ Emu.GetPath(), "-emu" }).run();
|
armv7_thread(entry, thread_name, stack_size, priority).args({ Emu.GetPath(), "-emu" }).run();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -56,7 +56,9 @@
|
||||||
<ClCompile Include="Emu\ARMv7\ARMv7DisAsm.cpp" />
|
<ClCompile Include="Emu\ARMv7\ARMv7DisAsm.cpp" />
|
||||||
<ClCompile Include="Emu\ARMv7\ARMv7Interpreter.cpp" />
|
<ClCompile Include="Emu\ARMv7\ARMv7Interpreter.cpp" />
|
||||||
<ClCompile Include="Emu\ARMv7\ARMv7Thread.cpp" />
|
<ClCompile Include="Emu\ARMv7\ARMv7Thread.cpp" />
|
||||||
|
<ClCompile Include="Emu\ARMv7\Modules\psv_cond.cpp" />
|
||||||
<ClCompile Include="Emu\ARMv7\Modules\psv_event_flag.cpp" />
|
<ClCompile Include="Emu\ARMv7\Modules\psv_event_flag.cpp" />
|
||||||
|
<ClCompile Include="Emu\ARMv7\Modules\psv_mutex.cpp" />
|
||||||
<ClCompile Include="Emu\ARMv7\Modules\psv_sema.cpp" />
|
<ClCompile Include="Emu\ARMv7\Modules\psv_sema.cpp" />
|
||||||
<ClCompile Include="Emu\ARMv7\Modules\sceAppMgr.cpp" />
|
<ClCompile Include="Emu\ARMv7\Modules\sceAppMgr.cpp" />
|
||||||
<ClCompile Include="Emu\ARMv7\Modules\sceAppUtil.cpp" />
|
<ClCompile Include="Emu\ARMv7\Modules\sceAppUtil.cpp" />
|
||||||
|
@ -334,7 +336,9 @@
|
||||||
<ClInclude Include="Emu\ARMv7\ARMv7Interpreter.h" />
|
<ClInclude Include="Emu\ARMv7\ARMv7Interpreter.h" />
|
||||||
<ClInclude Include="Emu\ARMv7\ARMv7Opcodes.h" />
|
<ClInclude Include="Emu\ARMv7\ARMv7Opcodes.h" />
|
||||||
<ClInclude Include="Emu\ARMv7\ARMv7Thread.h" />
|
<ClInclude Include="Emu\ARMv7\ARMv7Thread.h" />
|
||||||
|
<ClInclude Include="Emu\ARMv7\Modules\psv_cond.h" />
|
||||||
<ClInclude Include="Emu\ARMv7\Modules\psv_event_flag.h" />
|
<ClInclude Include="Emu\ARMv7\Modules\psv_event_flag.h" />
|
||||||
|
<ClInclude Include="Emu\ARMv7\Modules\psv_mutex.h" />
|
||||||
<ClInclude Include="Emu\ARMv7\Modules\psv_sema.h" />
|
<ClInclude Include="Emu\ARMv7\Modules\psv_sema.h" />
|
||||||
<ClInclude Include="Emu\ARMv7\Modules\sceAppUtil.h" />
|
<ClInclude Include="Emu\ARMv7\Modules\sceAppUtil.h" />
|
||||||
<ClInclude Include="Emu\ARMv7\Modules\sceGxm.h" />
|
<ClInclude Include="Emu\ARMv7\Modules\sceGxm.h" />
|
||||||
|
|
|
@ -583,7 +583,7 @@
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="Emu\RSX\RSXDMA.cpp">
|
<ClCompile Include="Emu\RSX\RSXDMA.cpp">
|
||||||
<Filter>Emu\GPU\RSX</Filter>
|
<Filter>Emu\GPU\RSX</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="Emu\RSX\RSXTexture.cpp">
|
<ClCompile Include="Emu\RSX\RSXTexture.cpp">
|
||||||
<Filter>Emu\GPU\RSX</Filter>
|
<Filter>Emu\GPU\RSX</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -670,7 +670,7 @@
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="Emu\ARMv7\ARMv7Decoder.cpp">
|
<ClCompile Include="Emu\ARMv7\ARMv7Decoder.cpp">
|
||||||
<Filter>Emu\CPU\ARMv7</Filter>
|
<Filter>Emu\CPU\ARMv7</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="Emu\ARMv7\PSVObjectList.cpp">
|
<ClCompile Include="Emu\ARMv7\PSVObjectList.cpp">
|
||||||
<Filter>Emu\CPU\ARMv7</Filter>
|
<Filter>Emu\CPU\ARMv7</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -696,7 +696,7 @@
|
||||||
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="Emu\ARMv7\Modules\sceGxm.cpp">
|
<ClCompile Include="Emu\ARMv7\Modules\sceGxm.cpp">
|
||||||
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="Emu\ARMv7\Modules\sceAppMgr.cpp">
|
<ClCompile Include="Emu\ARMv7\Modules\sceAppMgr.cpp">
|
||||||
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
||||||
|
@ -848,6 +848,12 @@
|
||||||
<ClCompile Include="Emu\ARMv7\Modules\sceSha.cpp">
|
<ClCompile Include="Emu\ARMv7\Modules\sceSha.cpp">
|
||||||
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Emu\ARMv7\Modules\psv_mutex.cpp">
|
||||||
|
<Filter>Emu\CPU\ARMv7\Objects</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="Emu\ARMv7\Modules\psv_cond.cpp">
|
||||||
|
<Filter>Emu\CPU\ARMv7\Objects</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="Crypto\aes.h">
|
<ClInclude Include="Crypto\aes.h">
|
||||||
|
@ -1350,7 +1356,7 @@
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="Emu\RSX\RSXDMA.h">
|
<ClInclude Include="Emu\RSX\RSXDMA.h">
|
||||||
<Filter>Emu\GPU\RSX</Filter>
|
<Filter>Emu\GPU\RSX</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="Emu\RSX\RSXFragmentProgram.h">
|
<ClInclude Include="Emu\RSX\RSXFragmentProgram.h">
|
||||||
<Filter>Emu\GPU\RSX</Filter>
|
<Filter>Emu\GPU\RSX</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -1479,7 +1485,7 @@
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="Emu\ARMv7\Modules\sceLibKernel.h">
|
<ClInclude Include="Emu\ARMv7\Modules\sceLibKernel.h">
|
||||||
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="Emu\ARMv7\PSVObjectList.h">
|
<ClInclude Include="Emu\ARMv7\PSVObjectList.h">
|
||||||
<Filter>Emu\CPU\ARMv7</Filter>
|
<Filter>Emu\CPU\ARMv7</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
@ -1490,7 +1496,7 @@
|
||||||
<Filter>Emu\CPU\ARMv7\Objects</Filter>
|
<Filter>Emu\CPU\ARMv7\Objects</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="Emu\ARMv7\Modules\sceGxm.h">
|
<ClInclude Include="Emu\ARMv7\Modules\sceGxm.h">
|
||||||
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="Emu\ARMv7\Modules\sceAppUtil.h">
|
<ClInclude Include="Emu\ARMv7\Modules\sceAppUtil.h">
|
||||||
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
||||||
|
@ -1510,5 +1516,11 @@
|
||||||
<ClInclude Include="Emu\ARMv7\Modules\sceNpCommon.h">
|
<ClInclude Include="Emu\ARMv7\Modules\sceNpCommon.h">
|
||||||
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="Emu\ARMv7\Modules\psv_mutex.h">
|
||||||
|
<Filter>Emu\CPU\ARMv7\Objects</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="Emu\ARMv7\Modules\psv_cond.h">
|
||||||
|
<Filter>Emu\CPU\ARMv7\Objects</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Loading…
Add table
Add a link
Reference in a new issue