mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-06 09:39:55 +00:00
Fixed conflicts
This commit is contained in:
commit
dfb2598e41
@ -109,7 +109,15 @@ struct FileListener : LogListener
|
||||
if (mPrependChannelName)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ std::string fmt::replace_all(const std::string &src, const std::string& from, co
|
||||
pos += to.length();
|
||||
}
|
||||
|
||||
return src;
|
||||
return target;
|
||||
}
|
||||
|
||||
//TODO: move this wx Stuff somewhere else
|
||||
@ -339,3 +339,34 @@ std::string fmt::tolower(std::string 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_sdec(s64 value);
|
||||
|
||||
std::string toupper(std::string source);
|
||||
|
||||
namespace detail
|
||||
{
|
||||
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));
|
||||
}
|
||||
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')
|
||||
{
|
||||
return to_udec(arg);
|
||||
@ -218,6 +224,10 @@ namespace fmt
|
||||
{
|
||||
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')
|
||||
{
|
||||
return to_udec(arg);
|
||||
@ -238,6 +248,10 @@ namespace fmt
|
||||
{
|
||||
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')
|
||||
{
|
||||
return to_udec(arg);
|
||||
@ -258,6 +272,10 @@ namespace fmt
|
||||
{
|
||||
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')
|
||||
{
|
||||
return to_udec(arg);
|
||||
@ -278,6 +296,10 @@ namespace fmt
|
||||
{
|
||||
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')
|
||||
{
|
||||
return to_sdec(arg);
|
||||
@ -298,6 +320,10 @@ namespace fmt
|
||||
{
|
||||
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')
|
||||
{
|
||||
return to_sdec(arg);
|
||||
@ -318,6 +344,10 @@ namespace fmt
|
||||
{
|
||||
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')
|
||||
{
|
||||
return to_sdec(arg);
|
||||
@ -338,6 +368,10 @@ namespace fmt
|
||||
{
|
||||
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')
|
||||
{
|
||||
return to_sdec(arg);
|
||||
@ -358,6 +392,10 @@ namespace fmt
|
||||
{
|
||||
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')
|
||||
{
|
||||
return std::to_string(arg);
|
||||
@ -378,6 +416,10 @@ namespace fmt
|
||||
{
|
||||
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')
|
||||
{
|
||||
return std::to_string(arg);
|
||||
@ -394,7 +436,7 @@ namespace fmt
|
||||
{
|
||||
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));
|
||||
}
|
||||
@ -579,4 +621,6 @@ namespace fmt
|
||||
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 tolower(std::string source);
|
||||
std::string toupper(std::string source);
|
||||
std::string escape(std::string source);
|
||||
}
|
||||
|
@ -213,9 +213,10 @@ static const reg_table_t reg_table[17] =
|
||||
|
||||
#endif
|
||||
|
||||
bool handle_access_violation(const u32 addr, x64_context* context)
|
||||
bool handle_access_violation(const u32 addr, bool is_writing, 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
|
||||
x64_op_t op;
|
||||
@ -277,6 +278,12 @@ bool handle_access_violation(const u32 addr, x64_context* context)
|
||||
return true;
|
||||
}
|
||||
|
||||
// check if fault is caused by reservation
|
||||
if (vm::reservation_query(addr, is_writing))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: allow recovering from a page fault as a feature of PS3 virtual memory
|
||||
return false;
|
||||
}
|
||||
@ -285,38 +292,49 @@ bool handle_access_violation(const u32 addr, x64_context* context)
|
||||
|
||||
void _se_translator(unsigned int u, EXCEPTION_POINTERS* pExp)
|
||||
{
|
||||
const u64 addr64 = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)Memory.GetBaseAddr();
|
||||
const u64 addr64 = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)vm::g_base_addr;
|
||||
const bool is_writing = pExp->ExceptionRecord->ExceptionInformation[0] != 0;
|
||||
|
||||
if (u == EXCEPTION_ACCESS_VIOLATION && (u32)addr64 == addr64)
|
||||
{
|
||||
if (handle_access_violation((u32)addr64, pExp->ContextRecord))
|
||||
{
|
||||
// restore context (further code shouldn't be reached)
|
||||
RtlRestoreContext(pExp->ContextRecord, nullptr);
|
||||
|
||||
// it's dangerous because destructors won't be executed
|
||||
}
|
||||
|
||||
throw fmt::format("Access violation %s location 0x%llx", is_writing ? "writing" : "reading", addr64);
|
||||
}
|
||||
|
||||
// else some fatal error (should crash)
|
||||
}
|
||||
|
||||
const PVOID exception_handler = (atexit([]{ RemoveVectoredExceptionHandler(exception_handler); }), AddVectoredExceptionHandler(1, [](PEXCEPTION_POINTERS pExp) -> LONG
|
||||
{
|
||||
const u64 addr64 = (u64)pExp->ExceptionRecord->ExceptionInformation[1] - (u64)vm::g_base_addr;
|
||||
const bool is_writing = pExp->ExceptionRecord->ExceptionInformation[0] != 0;
|
||||
|
||||
if (pExp->ExceptionRecord->ExceptionCode == EXCEPTION_ACCESS_VIOLATION &&
|
||||
(u32)addr64 == addr64 &&
|
||||
GetCurrentNamedThread() &&
|
||||
handle_access_violation((u32)addr64, is_writing, pExp->ContextRecord))
|
||||
{
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
else
|
||||
{
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
}));
|
||||
|
||||
#else
|
||||
|
||||
void signal_handler(int sig, siginfo_t* info, void* uct)
|
||||
{
|
||||
const u64 addr64 = (u64)info->si_addr - (u64)Memory.GetBaseAddr();
|
||||
const u64 addr64 = (u64)info->si_addr - (u64)vm::g_base_addr;
|
||||
const bool is_writing = ((ucontext_t*)uct)->uc_mcontext.gregs[REG_ERR] & 0x2;
|
||||
|
||||
if ((u32)addr64 == addr64 && GetCurrentNamedThread())
|
||||
{
|
||||
if (handle_access_violation((u32)addr64, (ucontext_t*)uct))
|
||||
if (handle_access_violation((u32)addr64, is_writing, (ucontext_t*)uct))
|
||||
{
|
||||
return; // proceed execution
|
||||
}
|
||||
|
||||
// TODO: this may be wrong
|
||||
throw fmt::format("Access violation at location 0x%llx", addr64);
|
||||
throw fmt::format("Access violation %s location 0x%llx", is_writing ? "writing" : "reading", addr64);
|
||||
}
|
||||
|
||||
// else some fatal error
|
||||
@ -352,6 +370,11 @@ void SetCurrentNamedThread(NamedThreadBase* value)
|
||||
return;
|
||||
}
|
||||
|
||||
if (old_value)
|
||||
{
|
||||
vm::reservation_free();
|
||||
}
|
||||
|
||||
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());
|
||||
@ -421,8 +444,17 @@ void ThreadBase::Start()
|
||||
|
||||
#ifdef _WIN32
|
||||
auto old_se_translator = _set_se_translator(_se_translator);
|
||||
if (!exception_handler)
|
||||
{
|
||||
LOG_ERROR(GENERAL, "exception_handler not set");
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (sigaction_result == -1) assert(!"sigaction() failed");
|
||||
if (sigaction_result == -1)
|
||||
{
|
||||
printf("sigaction() failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
|
||||
SetCurrentNamedThread(this);
|
||||
@ -560,8 +592,6 @@ void thread_t::start(std::function<void()> func)
|
||||
|
||||
#ifdef _WIN32
|
||||
auto old_se_translator = _set_se_translator(_se_translator);
|
||||
#else
|
||||
if (sigaction_result == -1) assert(!"sigaction() failed");
|
||||
#endif
|
||||
|
||||
NamedThreadBase info(name);
|
||||
|
@ -10,17 +10,15 @@ enum ARMv7InstructionSet
|
||||
ThumbEE
|
||||
};
|
||||
|
||||
enum armv7_debug_flags : u32
|
||||
{
|
||||
DF_DISASM = 1 << 0,
|
||||
DF_PRINT = 1 << 1,
|
||||
DF_NO_EXE = 1 << 2,
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
u32 GPR[15];
|
||||
@ -116,9 +114,6 @@ struct ARMv7Context
|
||||
|
||||
u32 TLS;
|
||||
|
||||
u32 R_ADDR;
|
||||
u64 R_DATA;
|
||||
|
||||
struct perf_counter
|
||||
{
|
||||
u32 event;
|
||||
@ -127,6 +122,18 @@ struct ARMv7Context
|
||||
|
||||
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)
|
||||
{
|
||||
assert(n < 16);
|
||||
|
@ -30,137 +30,147 @@ struct ARMv7_opcode_t
|
||||
|
||||
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(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_OP2(0xffc0, 0x4040, T1, ADC_REG),
|
||||
ARMv7_OP4(0xffe0, 0x8000, 0xeb40, 0x0000, T2, ADC_REG),
|
||||
ARMv7_OP2(0xffc0, 0x4140, T1, ADC_REG, nullptr),
|
||||
ARMv7_OP4(0xffe0, 0x8000, 0xeb40, 0x0000, T2, ADC_REG, nullptr),
|
||||
ARMv7_OP4(0x0fe0, 0x0010, 0x00a0, 0x0000, A1, ADC_REG),
|
||||
ARMv7_OP4(0x0fe0, 0x0090, 0x00a0, 0x0010, A1, ADC_RSR),
|
||||
|
||||
ARMv7_OP2(0xfe00, 0x1c00, T1, ADD_IMM),
|
||||
ARMv7_OP2(0xf800, 0x3000, T2, ADD_IMM),
|
||||
ARMv7_OP2(0xfe00, 0x1c00, T1, ADD_IMM, nullptr),
|
||||
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(0xfbf0, 0x8000, 0xf200, 0x0000, T4, ADD_IMM, SKIP_IF( (BF(16, 19) & 13) == 13 )),
|
||||
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_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, 0x0090, 0x0080, 0x0010, A1, ADD_RSR),
|
||||
ARMv7_OP2(0xf800, 0xa800, T1, ADD_SPI),
|
||||
ARMv7_OP2(0xff80, 0xb000, T2, ADD_SPI),
|
||||
ARMv7_OP2(0xf800, 0xa800, T1, ADD_SPI, nullptr),
|
||||
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(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_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_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_OP2(0xf800, 0xa000, T1, ADR),
|
||||
ARMv7_OP4(0xfbff, 0x8000, 0xf2af, 0x0000, T2, ADR),
|
||||
ARMv7_OP4(0xfbff, 0x8000, 0xf20f, 0x0000, T3, ADR),
|
||||
ARMv7_OP2(0xf800, 0xa000, T1, ADR, nullptr),
|
||||
ARMv7_OP4(0xfbff, 0x8000, 0xf2af, 0x0000, T2, ADR, nullptr),
|
||||
ARMv7_OP4(0xfbff, 0x8000, 0xf20f, 0x0000, T3, ADR, nullptr),
|
||||
ARMv7_OP4(0x0fff, 0x0000, 0x028f, 0x0000, A1, ADR),
|
||||
ARMv7_OP4(0x0fff, 0x0000, 0x024f, 0x0000, A2, ADR),
|
||||
|
||||
ARMv7_OP4(0xfbe0, 0x8000, 0xf000, 0x0000, T1, AND_IMM),
|
||||
ARMv7_OP4(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_OP2(0xffc0, 0x4000, T1, AND_REG),
|
||||
ARMv7_OP4(0xffe0, 0x8000, 0xea00, 0x0000, T2, AND_REG),
|
||||
ARMv7_OP2(0xffc0, 0x4000, T1, AND_REG, nullptr),
|
||||
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, 0x0090, 0x0000, 0x0010, A1, AND_RSR),
|
||||
|
||||
ARMv7_OP2(0xf800, 0x1000, T1, ASR_IMM),
|
||||
ARMv7_OP4(0xffef, 0x8030, 0xea4f, 0x0020, T2, ASR_IMM),
|
||||
ARMv7_OP2(0xf800, 0x1000, T1, ASR_IMM, nullptr),
|
||||
ARMv7_OP4(0xffef, 0x8030, 0xea4f, 0x0020, T2, ASR_IMM, nullptr),
|
||||
ARMv7_OP4(0x0fef, 0x0070, 0x01a0, 0x0040, A1, ASR_IMM),
|
||||
ARMv7_OP2(0xffc0, 0x4100, T1, ASR_REG),
|
||||
ARMv7_OP4(0xffe0, 0xf0f0, 0xfa40, 0xf000, T2, ASR_REG),
|
||||
ARMv7_OP2(0xffc0, 0x4100, T1, ASR_REG, nullptr),
|
||||
ARMv7_OP4(0xffe0, 0xf0f0, 0xfa40, 0xf000, T2, ASR_REG, nullptr),
|
||||
ARMv7_OP4(0x0fef, 0x00f0, 0x01a0, 0x0050, A1, ASR_REG),
|
||||
|
||||
ARMv7_OP2(0xf000, 0xd000, T1, B),
|
||||
ARMv7_OP2(0xf800, 0xe000, T2, B),
|
||||
ARMv7_OP4(0xf800, 0xd000, 0xf000, 0x8000, T3, B),
|
||||
ARMv7_OP4(0xf800, 0xd000, 0xf000, 0x9000, T4, B),
|
||||
ARMv7_OP2(0xf000, 0xd000, T1, B, SKIP_IF( BF(9, 11) == 0x7 )),
|
||||
ARMv7_OP2(0xf800, 0xe000, T2, B, nullptr),
|
||||
ARMv7_OP4(0xf800, 0xd000, 0xf000, 0x8000, T3, B, SKIP_IF( BF(23, 25) == 0x7 )),
|
||||
ARMv7_OP4(0xf800, 0xd000, 0xf000, 0x9000, T4, B, nullptr),
|
||||
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(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(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_OP2(0xffc0, 0x4380, T1, BIC_REG),
|
||||
ARMv7_OP4(0xffe0, 0x8000, 0xea20, 0x0000, T2, BIC_REG),
|
||||
ARMv7_OP2(0xffc0, 0x4380, T1, BIC_REG, nullptr),
|
||||
ARMv7_OP4(0xffe0, 0x8000, 0xea20, 0x0000, T2, BIC_REG, nullptr),
|
||||
ARMv7_OP4(0x0fe0, 0x0010, 0x01c0, 0x0000, A1, BIC_REG),
|
||||
ARMv7_OP4(0x0fe0, 0x0090, 0x01c0, 0x0010, A1, BIC_RSR),
|
||||
|
||||
ARMv7_OP2(0xff00, 0xbe00, T1, BKPT),
|
||||
ARMv7_OP2(0xff00, 0xbe00, T1, BKPT, nullptr),
|
||||
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_OP2(0xff80, 0x4780, T1, BLX),
|
||||
ARMv7_OP4(0xf800, 0xc001, 0xf000, 0xc000, T2, BLX),
|
||||
ARMv7_OP2(0xff80, 0x4780, T1, BLX, nullptr),
|
||||
ARMv7_OP4(0xf800, 0xc001, 0xf000, 0xc000, T2, BLX, nullptr),
|
||||
ARMv7_OP4(0x0fff, 0xfff0, 0x012f, 0xff30, A1, 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_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(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_OP2(0xffc0, 0x42c0, T1, CMN_REG),
|
||||
ARMv7_OP4(0xfff0, 0x8f00, 0xeb10, 0x0f00, T2, CMN_REG),
|
||||
ARMv7_OP2(0xffc0, 0x42c0, T1, CMN_REG, nullptr),
|
||||
ARMv7_OP4(0xfff0, 0x8f00, 0xeb10, 0x0f00, T2, CMN_REG, nullptr),
|
||||
ARMv7_OP4(0x0ff0, 0xf010, 0x0170, 0x0000, A1, CMN_REG),
|
||||
ARMv7_OP4(0x0ff0, 0xf090, 0x0170, 0x0010, A1, CMN_RSR),
|
||||
|
||||
ARMv7_OP2(0xf800, 0x2800, T1, CMP_IMM),
|
||||
ARMv7_OP4(0xfbf0, 0x8f00, 0xf1b0, 0x0f00, T2, CMP_IMM),
|
||||
ARMv7_OP2(0xf800, 0x2800, T1, CMP_IMM, nullptr),
|
||||
ARMv7_OP4(0xfbf0, 0x8f00, 0xf1b0, 0x0f00, T2, CMP_IMM, nullptr),
|
||||
ARMv7_OP4(0x0ff0, 0xf000, 0x0350, 0x0000, A1, CMP_IMM),
|
||||
ARMv7_OP2(0xffc0, 0x4280, T1, CMP_REG),
|
||||
ARMv7_OP2(0xff00, 0x4500, T2, CMP_REG),
|
||||
ARMv7_OP4(0xfff0, 0x8f00, 0xebb0, 0x0f00, T3, CMP_REG),
|
||||
ARMv7_OP2(0xffc0, 0x4280, T1, CMP_REG, nullptr),
|
||||
ARMv7_OP2(0xff00, 0x4500, T2, CMP_REG, nullptr),
|
||||
ARMv7_OP4(0xfff0, 0x8f00, 0xebb0, 0x0f00, T3, CMP_REG, nullptr),
|
||||
ARMv7_OP4(0x0ff0, 0xf010, 0x0150, 0x0000, A1, CMP_REG),
|
||||
ARMv7_OP4(0x0ff0, 0xf090, 0x0150, 0x0010, A1, CMP_RSR),
|
||||
|
||||
ARMv7_OP4(0xfbe0, 0x8000, 0xf080, 0x0000, T1, EOR_IMM),
|
||||
ARMv7_OP4(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_OP2(0xffc0, 0x4040, T1, EOR_REG),
|
||||
ARMv7_OP4(0xffe0, 0x8000, 0xea80, 0x0000, T2, EOR_REG),
|
||||
ARMv7_OP2(0xffc0, 0x4040, T1, EOR_REG, nullptr),
|
||||
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, 0x0090, 0x0020, 0x0010, A1, EOR_RSR),
|
||||
|
||||
ARMv7_OP2(0xff00, 0xbf00, T1, IT, SKIP_IF( BF(0, 3) == 0 )),
|
||||
|
||||
ARMv7_OP2(0xf800, 0xc800, T1, LDM),
|
||||
ARMv7_OP4(0xffd0, 0x2000, 0xe890, 0x0000, T2, LDM),
|
||||
ARMv7_OP2(0xf800, 0xc800, T1, LDM, nullptr),
|
||||
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, 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, 0x0990, 0x0000, A1, LDMIB),
|
||||
|
||||
ARMv7_OP2(0xf800, 0x6800, T1, LDR_IMM),
|
||||
ARMv7_OP2(0xf800, 0x9800, T2, LDR_IMM),
|
||||
ARMv7_OP4(0xfff0, 0x0000, 0xf8d0, 0x0000, T3, LDR_IMM),
|
||||
ARMv7_OP4(0xfff0, 0x0800, 0xf850, 0x0800, T4, LDR_IMM),
|
||||
ARMv7_OP2(0xf800, 0x6800, T1, LDR_IMM, nullptr),
|
||||
ARMv7_OP2(0xf800, 0x9800, T2, LDR_IMM, nullptr),
|
||||
ARMv7_OP4(0xfff0, 0x0000, 0xf8d0, 0x0000, T3, LDR_IMM, SKIP_IF( BF(16, 19) == 15 )),
|
||||
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_OP2(0xf800, 0x4800, T1, LDR_LIT),
|
||||
ARMv7_OP4(0xff7f, 0x0000, 0xf85f, 0x0000, T2, LDR_LIT),
|
||||
ARMv7_OP2(0xf800, 0x4800, T1, LDR_LIT, nullptr),
|
||||
ARMv7_OP4(0xff7f, 0x0000, 0xf85f, 0x0000, T2, LDR_LIT, nullptr),
|
||||
ARMv7_OP4(0x0f7f, 0x0000, 0x051f, 0x0000, A1, LDR_LIT),
|
||||
ARMv7_OP2(0xfe00, 0x5800, T1, LDR_REG),
|
||||
ARMv7_OP4(0xfff0, 0x0fc0, 0xf850, 0x0000, T2, LDR_REG),
|
||||
ARMv7_OP2(0xfe00, 0x5800, T1, LDR_REG, nullptr),
|
||||
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_OP2(0xf800, 0x7800, T1, LDRB_IMM),
|
||||
ARMv7_OP4(0xfff0, 0x0000, 0xf890, 0x0000, T2, 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(0x0fe0, 0x0000, 0x0380, 0x0000, A1, ORR_IMM),
|
||||
ARMv7_OP2(0xffc0, 0x4300, T1, ORR_REG),
|
||||
ARMv7_OP4(0xffe0, 0x8000, 0xea40, 0x0000, T2, ORR_REG),
|
||||
ARMv7_OP4(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, 0x0090, 0x0180, 0x0010, A1, ORR_RSR),
|
||||
|
||||
@ -1105,6 +1115,7 @@ const ARMv7_opcode_t ARMv7_opcode_table[] =
|
||||
struct ARMv7_op2_table_t
|
||||
{
|
||||
const ARMv7_opcode_t* data[0x10000];
|
||||
u32 null_ops;
|
||||
|
||||
ARMv7_op2_table_t()
|
||||
{
|
||||
@ -1123,6 +1134,8 @@ struct ARMv7_op2_table_t
|
||||
}
|
||||
}
|
||||
|
||||
null_ops = 0x10000;
|
||||
|
||||
for (u32 i = 0; i < 0x10000; i++)
|
||||
{
|
||||
data[i] = nullptr;
|
||||
@ -1132,6 +1145,7 @@ struct ARMv7_op2_table_t
|
||||
if (((i << 16) & opcode->mask) == opcode->code && (!opcode->skip || !opcode->skip(i)))
|
||||
{
|
||||
data[i] = opcode;
|
||||
null_ops--;
|
||||
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)
|
||||
{
|
||||
// 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
|
||||
// 3. Possibly print disasm
|
||||
|
||||
g_opct.clear();
|
||||
//g_opct.clear();
|
||||
//g_opct.reserve(end_addr - 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 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:
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -18,12 +18,11 @@ enum ARMv7_encoding
|
||||
|
||||
enum SRType : u32
|
||||
{
|
||||
SRType_None,
|
||||
SRType_LSL,
|
||||
SRType_LSR,
|
||||
SRType_ASR,
|
||||
SRType_ROR,
|
||||
SRType_RRX
|
||||
SRType_RRX,
|
||||
};
|
||||
|
||||
namespace ARMv7_instrs
|
||||
@ -79,6 +78,10 @@ namespace ARMv7_instrs
|
||||
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 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_REG(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()
|
||||
{
|
||||
return thread.PC;
|
||||
return ISET == ARM ? thread.PC + 8 : thread.PC + 4;
|
||||
}
|
||||
|
||||
u32 ARMv7Context::get_stack_arg(u32 pos)
|
||||
@ -118,7 +118,7 @@ void ARMv7Thread::InitRegs()
|
||||
context.ITSTATE.IT = 0;
|
||||
context.SP = m_stack_addr + m_stack_size;
|
||||
context.TLS = armv7_get_tls(GetId());
|
||||
context.R_ADDR = 0;
|
||||
context.debug |= DF_DISASM | DF_PRINT;
|
||||
}
|
||||
|
||||
void ARMv7Thread::InitStack()
|
||||
@ -230,14 +230,14 @@ void ARMv7Thread::FastStop()
|
||||
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->SetName(name);
|
||||
thread->SetEntry(entry);
|
||||
thread->SetStackSize(stack_size ? stack_size : Emu.GetInfo().GetProcParam().primary_stacksize);
|
||||
thread->SetPrio(prio ? prio : Emu.GetInfo().GetProcParam().primary_prio);
|
||||
thread->SetStackSize(stack_size);
|
||||
thread->SetPrio(prio);
|
||||
|
||||
argc = 0;
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ class armv7_thread : cpu_thread
|
||||
u32 argc;
|
||||
|
||||
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;
|
||||
|
||||
|
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:
|
||||
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;
|
||||
|
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:
|
||||
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 "psv_sema.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; }
|
||||
|
||||
@ -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)
|
||||
{
|
||||
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)
|
||||
@ -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)
|
||||
{
|
||||
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)
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/ARMv7/PSVFuncList.h"
|
||||
#include "Emu/ARMv7/ARMv7Thread.h"
|
||||
#include "Emu/ARMv7/ARMv7Callback.h"
|
||||
|
||||
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::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
|
||||
{
|
||||
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...
|
||||
{
|
||||
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...
|
||||
{
|
||||
sceLibc.Warning("sprintf(str=0x%x, fmt=0x%x)", str, fmt);
|
||||
|
||||
sceLibc.Notice("*** *fmt = '%s'", fmt.get_ptr());
|
||||
sceLibc.Log("*** *fmt = '%s'", fmt.get_ptr());
|
||||
|
||||
const std::string& result = armv7_fmt(context, fmt, 2, 0, 0);
|
||||
|
||||
sceLibc.Notice("*** res -> '%s'", result);
|
||||
sceLibc.Log("*** -> '%s'", result);
|
||||
|
||||
::memcpy(str.get_ptr(), result.c_str(), result.size() + 1);
|
||||
}
|
||||
@ -158,11 +236,12 @@ namespace sce_libc_func
|
||||
::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_NOTICE(ARMv7, context.thread.RegsToString());
|
||||
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_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:
|
||||
{
|
||||
value = 1; // these events will probably never be implemented
|
||||
|
@ -6,21 +6,21 @@ extern psv_log_base sceSysmodule;
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ void add_psv_func(psv_func& 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)
|
||||
{
|
||||
@ -23,7 +23,7 @@ psv_func* get_psv_func_by_nid(u32 nid)
|
||||
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();
|
||||
|
||||
@ -32,14 +32,21 @@ u32 get_psv_func_index(psv_func* func)
|
||||
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());
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
@ -174,7 +181,7 @@ void initialize_psv_modules()
|
||||
// setup special functions (without NIDs)
|
||||
psv_func unimplemented;
|
||||
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)
|
||||
{
|
||||
context.thread.m_last_syscall = vm::psv::read32(context.thread.PC + 4);
|
||||
@ -184,7 +191,7 @@ void initialize_psv_modules()
|
||||
|
||||
psv_func hle_return;
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
// 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
|
||||
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
|
||||
void execute_psv_func_by_index(ARMv7Context& context, u32 index);
|
||||
// Register all HLE functions
|
||||
|
@ -5,12 +5,18 @@
|
||||
#include "Modules/sceLibKernel.h"
|
||||
#include "Modules/psv_sema.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_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()
|
||||
{
|
||||
g_psv_sema_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
|
||||
{
|
||||
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
|
||||
|
||||
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:
|
||||
static const u32 uid_class = type;
|
||||
|
||||
@ -60,18 +70,18 @@ public:
|
||||
{
|
||||
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
|
||||
//std::shared_ptr<T> old_ptr = nullptr;
|
||||
//if (std::atomic_compare_exchange_strong(&value, &old_ptr, data))
|
||||
if (!value)
|
||||
// find an empty position and copy the pointer
|
||||
if (!m_data[j])
|
||||
{
|
||||
value = data;
|
||||
m_data[j] = data;
|
||||
m_hint = j + 1; // guess next position
|
||||
psv_uid_t id = psv_uid_t::make(1); // odd number
|
||||
id.type = uid_class; // set type
|
||||
id.number = &value - m_data.data(); // set position
|
||||
return id.uid;
|
||||
id.number = j; // set position
|
||||
data->on_init(id.uid); // save UID
|
||||
return id.uid; // return UID
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,12 +96,14 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const u32 pos = psv_uid_t::make(uid).number;
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
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 std::atomic_exchange<std::shared_ptr<T>>(&m_data[psv_uid_t::make(uid).number], nullptr);
|
||||
}
|
||||
|
||||
// remove all objects
|
||||
@ -99,10 +111,17 @@ public:
|
||||
{
|
||||
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)
|
||||
{
|
||||
/*
|
||||
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;
|
||||
//}
|
||||
}
|
||||
void LWARX(u32 rd, u32 ra, u32 rb)
|
||||
{
|
||||
CPU.R_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);
|
||||
const u32 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||
|
||||
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)
|
||||
{
|
||||
@ -2682,9 +2659,12 @@ private:
|
||||
}
|
||||
void LDARX(u32 rd, u32 ra, u32 rb)
|
||||
{
|
||||
CPU.R_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);
|
||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||
|
||||
be_t<u64> value;
|
||||
vm::reservation_acquire(&value, vm::cast(addr), sizeof(value));
|
||||
|
||||
CPU.GPR[rd] = value;
|
||||
}
|
||||
void DCBF(u32 ra, u32 rb)
|
||||
{
|
||||
@ -2800,15 +2780,8 @@ private:
|
||||
{
|
||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||
|
||||
if (CPU.R_ADDR == addr)
|
||||
{
|
||||
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;
|
||||
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)));
|
||||
}
|
||||
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];
|
||||
|
||||
if (CPU.R_ADDR == addr)
|
||||
{
|
||||
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;
|
||||
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)));
|
||||
}
|
||||
void STBX(u32 rs, u32 ra, u32 rb)
|
||||
{
|
||||
@ -2945,9 +2911,7 @@ private:
|
||||
}
|
||||
void ECIWX(u32 rd, u32 ra, u32 rb)
|
||||
{
|
||||
//HACK!
|
||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||
CPU.GPR[rd] = vm::read32(vm::cast(addr));
|
||||
throw __FUNCTION__;
|
||||
}
|
||||
void LHZUX(u32 rd, u32 ra, u32 rb)
|
||||
{
|
||||
@ -3020,9 +2984,7 @@ private:
|
||||
}
|
||||
void ECOWX(u32 rs, u32 ra, u32 rb)
|
||||
{
|
||||
//HACK!
|
||||
const u64 addr = ra ? CPU.GPR[ra] + CPU.GPR[rb] : CPU.GPR[rb];
|
||||
vm::write32(vm::cast(addr), (u32)CPU.GPR[rs]);
|
||||
throw __FUNCTION__;
|
||||
}
|
||||
void STHUX(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) {
|
||||
auto addr_i64 = GetGpr(rb);
|
||||
if (ra) {
|
||||
auto ra_i64 = GetGpr(ra);
|
||||
addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||
}
|
||||
throw __FUNCTION__;
|
||||
|
||||
//auto addr_i64 = GetGpr(rb);
|
||||
//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_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);
|
||||
//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());
|
||||
//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_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_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);
|
||||
//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_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_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());
|
||||
SetGpr(rd, resv_val_i64);
|
||||
//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());
|
||||
//SetGpr(rd, resv_val_i64);
|
||||
}
|
||||
|
||||
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) {
|
||||
auto addr_i64 = GetGpr(rb);
|
||||
if (ra) {
|
||||
auto ra_i64 = GetGpr(ra);
|
||||
addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||
}
|
||||
throw __FUNCTION__;
|
||||
|
||||
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());
|
||||
m_ir_builder->CreateAlignedStore(addr_i64, resv_addr_i64_ptr, 8);
|
||||
//auto addr_i64 = GetGpr(rb);
|
||||
//if (ra) {
|
||||
// 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_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);
|
||||
//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());
|
||||
//m_ir_builder->CreateAlignedStore(addr_i64, resv_addr_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);
|
||||
//auto resv_val_i64 = ReadMemory(addr_i64, 64, 8, false);
|
||||
//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) {
|
||||
@ -2919,45 +2923,47 @@ void Compiler::STDX(u32 rs, u32 ra, u32 rb) {
|
||||
}
|
||||
|
||||
void Compiler::STWCX_(u32 rs, u32 ra, u32 rb) {
|
||||
auto addr_i64 = GetGpr(rb);
|
||||
if (ra) {
|
||||
auto ra_i64 = GetGpr(ra);
|
||||
addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||
}
|
||||
throw __FUNCTION__;
|
||||
|
||||
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 = (Value *)m_ir_builder->CreateAlignedLoad(resv_addr_i64_ptr, 8);
|
||||
auto cmp_i1 = m_ir_builder->CreateICmpEQ(addr_i64, resv_addr_i64);
|
||||
//auto addr_i64 = GetGpr(rb);
|
||||
//if (ra) {
|
||||
// auto ra_i64 = GetGpr(ra);
|
||||
// addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||
//}
|
||||
|
||||
auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then");
|
||||
auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "else");
|
||||
auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge");
|
||||
m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb);
|
||||
//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 = (Value *)m_ir_builder->CreateAlignedLoad(resv_addr_i64_ptr, 8);
|
||||
//auto cmp_i1 = m_ir_builder->CreateICmpEQ(addr_i64, resv_addr_i64);
|
||||
|
||||
m_ir_builder->SetInsertPoint(then_bb);
|
||||
auto rs_i32 = GetGpr(rs, 32);
|
||||
rs_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, rs_i32->getType()), rs_i32);
|
||||
resv_addr_i64 = m_ir_builder->CreateAdd(resv_addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr<u8>(0)));
|
||||
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 then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then");
|
||||
//auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "else");
|
||||
//auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge");
|
||||
//m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb);
|
||||
|
||||
auto res_s = m_ir_builder->CreateAtomicCmpXchg(resv_addr_val_i32_ptr, resv_val_i32, rs_i32, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic);
|
||||
auto success_i1 = m_ir_builder->CreateExtractValue(res_s, {1});
|
||||
auto cr_i32 = GetCr();
|
||||
cr_i32 = SetBit(cr_i32, 2, success_i1);
|
||||
SetCr(cr_i32);
|
||||
m_ir_builder->CreateAlignedStore(m_ir_builder->getInt64(0), resv_addr_i64_ptr, 8);
|
||||
m_ir_builder->CreateBr(merge_bb);
|
||||
//m_ir_builder->SetInsertPoint(then_bb);
|
||||
//auto rs_i32 = GetGpr(rs, 32);
|
||||
//rs_i32 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, rs_i32->getType()), rs_i32);
|
||||
//resv_addr_i64 = m_ir_builder->CreateAdd(resv_addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr<u8>(0)));
|
||||
//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);
|
||||
|
||||
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);
|
||||
//auto res_s = m_ir_builder->CreateAtomicCmpXchg(resv_addr_val_i32_ptr, resv_val_i32, rs_i32, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic);
|
||||
//auto success_i1 = m_ir_builder->CreateExtractValue(res_s, {1});
|
||||
//auto cr_i32 = GetCr();
|
||||
//cr_i32 = SetBit(cr_i32, 2, success_i1);
|
||||
//SetCr(cr_i32);
|
||||
//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) {
|
||||
@ -3060,45 +3066,47 @@ void Compiler::SUBFZE(u32 rd, u32 ra, u32 oe, bool rc) {
|
||||
}
|
||||
|
||||
void Compiler::STDCX_(u32 rs, u32 ra, u32 rb) {
|
||||
auto addr_i64 = GetGpr(rb);
|
||||
if (ra) {
|
||||
auto ra_i64 = GetGpr(ra);
|
||||
addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||
}
|
||||
throw __FUNCTION__;
|
||||
|
||||
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 = (Value *)m_ir_builder->CreateAlignedLoad(resv_addr_i64_ptr, 8);
|
||||
auto cmp_i1 = m_ir_builder->CreateICmpEQ(addr_i64, resv_addr_i64);
|
||||
//auto addr_i64 = GetGpr(rb);
|
||||
//if (ra) {
|
||||
// auto ra_i64 = GetGpr(ra);
|
||||
// addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||
//}
|
||||
|
||||
auto then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then");
|
||||
auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "else");
|
||||
auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge");
|
||||
m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb);
|
||||
//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 = (Value *)m_ir_builder->CreateAlignedLoad(resv_addr_i64_ptr, 8);
|
||||
//auto cmp_i1 = m_ir_builder->CreateICmpEQ(addr_i64, resv_addr_i64);
|
||||
|
||||
m_ir_builder->SetInsertPoint(then_bb);
|
||||
auto rs_i64 = GetGpr(rs, 64);
|
||||
rs_i64 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, rs_i64->getType()), rs_i64);
|
||||
resv_addr_i64 = m_ir_builder->CreateAdd(resv_addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr<u8>(0)));
|
||||
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 then_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "then");
|
||||
//auto else_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "else");
|
||||
//auto merge_bb = GetBasicBlockFromAddress(m_state.current_instruction_address, "merge");
|
||||
//m_ir_builder->CreateCondBr(cmp_i1, then_bb, else_bb);
|
||||
|
||||
auto res_s = m_ir_builder->CreateAtomicCmpXchg(resv_addr_val_i64_ptr, resv_val_i64, rs_i64, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic);
|
||||
auto success_i1 = m_ir_builder->CreateExtractValue(res_s, {1});
|
||||
auto cr_i32 = GetCr();
|
||||
cr_i32 = SetBit(cr_i32, 2, success_i1);
|
||||
SetCr(cr_i32);
|
||||
m_ir_builder->CreateAlignedStore(m_ir_builder->getInt64(0), resv_addr_i64_ptr, 8);
|
||||
m_ir_builder->CreateBr(merge_bb);
|
||||
//m_ir_builder->SetInsertPoint(then_bb);
|
||||
//auto rs_i64 = GetGpr(rs, 64);
|
||||
//rs_i64 = m_ir_builder->CreateCall(Intrinsic::getDeclaration(m_module, Intrinsic::bswap, rs_i64->getType()), rs_i64);
|
||||
//resv_addr_i64 = m_ir_builder->CreateAdd(resv_addr_i64, m_ir_builder->getInt64((u64)vm::get_ptr<u8>(0)));
|
||||
//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);
|
||||
|
||||
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);
|
||||
//auto res_s = m_ir_builder->CreateAtomicCmpXchg(resv_addr_val_i64_ptr, resv_val_i64, rs_i64, AtomicOrdering::AcquireRelease, AtomicOrdering::Monotonic);
|
||||
//auto success_i1 = m_ir_builder->CreateExtractValue(res_s, {1});
|
||||
//auto cr_i32 = GetCr();
|
||||
//cr_i32 = SetBit(cr_i32, 2, success_i1);
|
||||
//SetCr(cr_i32);
|
||||
//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) {
|
||||
@ -3263,15 +3271,16 @@ void Compiler::EQV(u32 ra, u32 rs, u32 rb, bool rc) {
|
||||
}
|
||||
|
||||
void Compiler::ECIWX(u32 rd, u32 ra, u32 rb) {
|
||||
auto addr_i64 = GetGpr(rb);
|
||||
if (ra) {
|
||||
auto ra_i64 = GetGpr(ra);
|
||||
addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||
}
|
||||
throw __FUNCTION__;
|
||||
//auto addr_i64 = GetGpr(rb);
|
||||
//if (ra) {
|
||||
// auto ra_i64 = GetGpr(ra);
|
||||
// addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||
//}
|
||||
|
||||
auto mem_i32 = ReadMemory(addr_i64, 32);
|
||||
auto mem_i64 = m_ir_builder->CreateZExt(mem_i32, m_ir_builder->getInt64Ty());
|
||||
SetGpr(rd, mem_i64);
|
||||
//auto mem_i32 = ReadMemory(addr_i64, 32);
|
||||
//auto mem_i64 = m_ir_builder->CreateZExt(mem_i32, m_ir_builder->getInt64Ty());
|
||||
//SetGpr(rd, mem_i64);
|
||||
}
|
||||
|
||||
void Compiler::LHZUX(u32 rd, u32 ra, u32 rb) {
|
||||
@ -3422,13 +3431,14 @@ void Compiler::ORC(u32 ra, u32 rs, u32 rb, bool rc) {
|
||||
}
|
||||
|
||||
void Compiler::ECOWX(u32 rs, u32 ra, u32 rb) {
|
||||
auto addr_i64 = GetGpr(rb);
|
||||
if (ra) {
|
||||
auto ra_i64 = GetGpr(ra);
|
||||
addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||
}
|
||||
throw __FUNCTION__;
|
||||
//auto addr_i64 = GetGpr(rb);
|
||||
//if (ra) {
|
||||
// auto ra_i64 = GetGpr(ra);
|
||||
// addr_i64 = m_ir_builder->CreateAdd(ra_i64, addr_i64);
|
||||
//}
|
||||
|
||||
WriteMemory(addr_i64, GetGpr(rs, 32));
|
||||
//WriteMemory(addr_i64, GetGpr(rs, 32));
|
||||
}
|
||||
|
||||
void Compiler::STHUX(u32 rs, u32 ra, u32 rb) {
|
||||
|
@ -59,10 +59,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp
|
||||
/// Time base register
|
||||
u64 TB;
|
||||
|
||||
/// Reservations
|
||||
u64 R_ADDR;
|
||||
u64 R_VALUE;
|
||||
|
||||
/// Memory block
|
||||
u32 address;
|
||||
u64 mem_block[64];
|
||||
@ -86,9 +82,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp
|
||||
CTR = ppu.CTR;
|
||||
TB = ppu.TB;
|
||||
|
||||
R_ADDR = ppu.R_ADDR;
|
||||
R_VALUE = ppu.R_VALUE;
|
||||
|
||||
address = addr;
|
||||
for (int i = 0; i < (sizeof(mem_block) / 8); i++) {
|
||||
mem_block[i] = vm::read64(address + (i * 8));
|
||||
@ -114,9 +107,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp
|
||||
ppu.CTR = CTR;
|
||||
ppu.TB = TB;
|
||||
|
||||
ppu.R_ADDR = R_ADDR;
|
||||
ppu.R_VALUE = R_VALUE;
|
||||
|
||||
for (int i = 0; i < (sizeof(mem_block) / 8); i++) {
|
||||
vm::write64(address + (i * 8), mem_block[i]);
|
||||
}
|
||||
@ -151,8 +141,6 @@ VerifyInstructionAgainstInterpreter(fmt::Format("%s.%d", #fn, tc).c_str(), &Comp
|
||||
LR = rng();
|
||||
CTR = rng();
|
||||
TB = rng();
|
||||
R_ADDR = rng();
|
||||
R_VALUE = rng();
|
||||
|
||||
address = addr;
|
||||
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.XX), fmt::by_value(FPSCR.ZX), fmt::by_value(FPSCR.UX), fmt::by_value(FPSCR.OX), fmt::by_value(FPSCR.VX), fmt::by_value(FPSCR.FEX), fmt::by_value(FPSCR.FX));
|
||||
//ret += fmt::Format("VSCR = 0x%08x [NJ=%d | SAT=%d]\n", VSCR.VSCR, fmt::by_value(VSCR.NJ), fmt::by_value(VSCR.SAT)); // TODO: Uncomment after implementing VSCR.SAT
|
||||
ret += fmt::Format("R_ADDR = 0x%016llx R_VALUE = 0x%016llx\n", R_ADDR, R_VALUE);
|
||||
|
||||
for (int i = 0; i < (sizeof(mem_block) / 8); i += 2) {
|
||||
ret += fmt::Format("mem_block[%d] = 0x%016llx mem_block[%d] = 0x%016llx\n", i, mem_block[i], i + 1, mem_block[i + 1]);
|
||||
@ -724,8 +711,6 @@ void Compiler::RunAllTests() {
|
||||
input.GPR[14] = 10;
|
||||
input.GPR[21] = 15;
|
||||
input.GPR[23] = 0x10000;
|
||||
input.R_ADDR = 0x10000;
|
||||
input.R_VALUE = 0x1122334455667788;
|
||||
input.mem_block[0] = 0x8877665544332211;
|
||||
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LBZ, 0, input, 5, 0, 0x10000);
|
||||
@ -739,8 +724,8 @@ void Compiler::RunAllTests() {
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZU, 0, input, 5, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECIWX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECIWX, 1, input, 5, 14, 23);
|
||||
//VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECIWX, 0, input, 5, 0, 23);
|
||||
//VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECIWX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHZUX, 0, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHA, 0, input, 5, 0, 0x100F0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LHA, 1, input, 5, 14, 0x100F0);
|
||||
@ -780,10 +765,10 @@ void Compiler::RunAllTests() {
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LFDX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LFDX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LFDUX, 0, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWARX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWARX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDARX, 0, input, 5, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDARX, 1, input, 5, 14, 23);
|
||||
//VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWARX, 0, input, 5, 0, 23);
|
||||
//VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LWARX, 1, input, 5, 14, 23);
|
||||
//VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDARX, 0, input, 5, 0, 23);
|
||||
//VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LDARX, 1, input, 5, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LSWI, 0, input, 5, 23, 0);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LSWI, 1, input, 5, 23, 2);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(LSWI, 2, input, 5, 23, 7);
|
||||
@ -819,8 +804,8 @@ void Compiler::RunAllTests() {
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STB, 0, input, 3, 0, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STB, 1, input, 3, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBU, 0, input, 3, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDCX_, 0, input, 3, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDCX_, 1, input, 3, 14, 23);
|
||||
//VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDCX_, 0, input, 3, 0, 23);
|
||||
//VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDCX_, 1, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBX, 0, input, 3, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBX, 1, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STBUX, 0, input, 3, 14, 23);
|
||||
@ -829,8 +814,8 @@ void Compiler::RunAllTests() {
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHU, 0, input, 3, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHX, 0, input, 3, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHX, 1, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECOWX, 0, input, 3, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECOWX, 1, input, 3, 14, 23);
|
||||
//VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECOWX, 0, input, 3, 0, 23);
|
||||
//VERIFY_INSTRUCTION_AGAINST_INTERPRETER(ECOWX, 1, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHUX, 0, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STHBRX, 0, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STW, 0, input, 3, 0, 0x10000);
|
||||
@ -848,8 +833,8 @@ void Compiler::RunAllTests() {
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDU, 0, input, 3, 14, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDX, 0, input, 3, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDX, 1, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWCX_, 0, input, 3, 0, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWCX_, 1, input, 3, 14, 23);
|
||||
//VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWCX_, 0, input, 3, 0, 23);
|
||||
//VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STWCX_, 1, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STDUX, 0, input, 3, 14, 23);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFS, 0, input, 3, 0, 0x10000);
|
||||
VERIFY_INSTRUCTION_AGAINST_INTERPRETER(STFS, 1, input, 3, 14, 0x10000);
|
||||
|
@ -536,11 +536,6 @@ public:
|
||||
//TBR : Time-Base Registers
|
||||
u64 TB; //TBR 0x10C - 0x10D
|
||||
|
||||
u64 cycle;
|
||||
|
||||
u64 R_ADDR; // reservation address
|
||||
u64 R_VALUE; // reservation value (BE)
|
||||
|
||||
u32 owned_mutexes;
|
||||
std::function<void(PPUThread& CPU)> custom_task;
|
||||
|
||||
|
@ -99,8 +99,6 @@ void SPUThread::InitRegs()
|
||||
|
||||
m_event_mask = 0;
|
||||
m_events = 0;
|
||||
|
||||
R_ADDR = 0;
|
||||
}
|
||||
|
||||
void SPUThread::InitStack()
|
||||
@ -437,103 +435,48 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
|
||||
|
||||
if (op == MFC_GETLLAR_CMD) // get reservation
|
||||
{
|
||||
if (R_ADDR)
|
||||
{
|
||||
m_events |= SPU_EVENT_LR;
|
||||
}
|
||||
//std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
|
||||
|
||||
R_ADDR = ea;
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
vm::reservation_acquire(vm::get_ptr(ls_offset + lsa), ea, 128, [this]()
|
||||
{
|
||||
R_DATA[i] = vm::get_ptr<u64>((u32)R_ADDR)[i];
|
||||
vm::get_ptr<u64>(ls_offset + lsa)[i] = R_DATA[i];
|
||||
}
|
||||
//std::shared_ptr<CPUThread> t = Emu.GetCPU().GetThread(tid);
|
||||
|
||||
//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);
|
||||
}
|
||||
else if (op == MFC_PUTLLC_CMD) // store conditional
|
||||
{
|
||||
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS);
|
||||
|
||||
if (R_ADDR == ea)
|
||||
if (vm::reservation_update(ea, vm::get_ptr(ls_offset + lsa), 128))
|
||||
{
|
||||
u32 changed = 0, mask = 0;
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLC_SUCCESS);
|
||||
}
|
||||
else
|
||||
{
|
||||
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_op(ea, 128, [this, tag, lsa, 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)
|
||||
{
|
||||
MFCArgs.AtomicStat.PushUncond(MFC_PUTLLUC_SUCCESS);
|
||||
}
|
||||
R_ADDR = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -548,19 +491,6 @@ void SPUThread::EnqMfcCmd(MFCReg& MFCArgs)
|
||||
bool SPUThread::CheckEvents()
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
@ -277,9 +277,6 @@ public:
|
||||
u32 SRR0;
|
||||
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
|
||||
EventManager SPUQs; // SPU Queue Mapping
|
||||
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(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
|
||||
if (!vm::g_base_addr)
|
||||
if (!vm::g_base_addr || !vm::g_priv_addr)
|
||||
#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
|
||||
{
|
||||
LOG_ERROR(MEMORY, "Initializing memory failed");
|
||||
assert(0);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_NOTICE(MEMORY, "Initializing memory: base_addr = 0x%llx", (u64)vm::g_base_addr);
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
@ -207,7 +204,7 @@ bool MemoryBase::Map(const u64 addr, const u32 size)
|
||||
}
|
||||
|
||||
MemoryBlocks.push_back((new MemoryBlock())->SetRange(addr, size));
|
||||
|
||||
|
||||
LOG_WARNING(MEMORY, "Memory mapped at 0x%llx: size=0x%x", addr, size);
|
||||
return true;
|
||||
}
|
||||
@ -231,20 +228,14 @@ bool MemoryBase::Unmap(const u64 addr)
|
||||
MemBlockInfo::MemBlockInfo(u64 _addr, u32 _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
|
||||
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
|
||||
if (::mprotect(real_addr, size, PROT_READ | PROT_WRITE))
|
||||
{
|
||||
mem = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
mem = real_addr;
|
||||
}
|
||||
if (mprotect(real_addr, size, PROT_READ | PROT_WRITE) || mprotect(priv_addr, size, PROT_READ | PROT_WRITE))
|
||||
#endif
|
||||
if (mem != real_addr)
|
||||
{
|
||||
LOG_ERROR(MEMORY, "Memory allocation failed (addr=0x%llx, size=0x%x)", addr, size);
|
||||
Emu.Pause();
|
||||
@ -252,7 +243,9 @@ MemBlockInfo::MemBlockInfo(u64 _addr, u32 _size)
|
||||
else
|
||||
{
|
||||
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);
|
||||
#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
|
||||
if (::mprotect(mem, size, PROT_NONE))
|
||||
if (mprotect(mem, size, PROT_NONE) || mprotect(vm::get_priv_ptr(vm::cast(addr)), size, PROT_NONE))
|
||||
#endif
|
||||
{
|
||||
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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
size = PAGE_4K(size);
|
||||
u32 exsize;
|
||||
|
||||
@ -715,4 +710,4 @@ bool VirtualMemoryBlock::Unreserve(u32 size)
|
||||
u32 VirtualMemoryBlock::GetReservedAmount()
|
||||
{
|
||||
return m_reserve_size;
|
||||
}
|
||||
}
|
||||
|
@ -72,11 +72,6 @@ public:
|
||||
Close();
|
||||
}
|
||||
|
||||
static void* const GetBaseAddr()
|
||||
{
|
||||
return vm::g_base_addr;
|
||||
}
|
||||
|
||||
void RegisterPages(u64 addr, u32 size);
|
||||
|
||||
void UnregisterPages(u64 addr, u32 size);
|
||||
|
@ -1,24 +1,339 @@
|
||||
#include "stdafx.h"
|
||||
#include "Utilities/Log.h"
|
||||
#include "Memory.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/CPU/CPUThread.h"
|
||||
#include "Emu/Cell/PPUThread.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
|
||||
{
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
void* const g_base_addr = VirtualAlloc(nullptr, 0x100000000, MEM_RESERVE, PAGE_NOACCESS);
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#ifdef _WIN32
|
||||
HANDLE g_memory_handle;
|
||||
#endif
|
||||
|
||||
/* OS X uses MAP_ANON instead of MAP_ANONYMOUS */
|
||||
#ifndef MAP_ANONYMOUS
|
||||
#define MAP_ANONYMOUS MAP_ANON
|
||||
#endif
|
||||
void* g_priv_addr;
|
||||
|
||||
void* const g_base_addr = mmap(nullptr, 0x100000000, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
|
||||
#endif
|
||||
void* initialize()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
g_memory_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE | SEC_RESERVE, 0x1, 0x0, NULL);
|
||||
|
||||
void* base_addr = MapViewOfFile(g_memory_handle, FILE_MAP_WRITE, 0, 0, 0x100000000); // main memory
|
||||
g_priv_addr = MapViewOfFile(g_memory_handle, FILE_MAP_WRITE, 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;
|
||||
u32 g_reservation_size = 0;
|
||||
|
||||
reservation_mutex_t g_reservation_mutex;
|
||||
|
||||
void _reservation_set(u32 addr, bool no_access = false)
|
||||
{
|
||||
//const auto stamp0 = get_time();
|
||||
|
||||
#ifdef _WIN32
|
||||
DWORD old;
|
||||
if (!VirtualProtect(vm::get_ptr(addr & ~0xfff), 4096, no_access ? PAGE_NOACCESS : PAGE_READONLY, &old))
|
||||
#else
|
||||
if (mprotect(vm::get_ptr(addr & ~0xfff), 4096, no_access ? PROT_NONE : 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
|
||||
DWORD old;
|
||||
if (!VirtualProtect(vm::get_ptr(addr & ~0xfff), 4096, PAGE_READWRITE, &old))
|
||||
#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;
|
||||
g_reservation_size = 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 - 1 & ~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_owner)
|
||||
{
|
||||
broken = _reservation_break(g_reservation_addr);
|
||||
}
|
||||
|
||||
// change memory protection to read-only
|
||||
_reservation_set(addr);
|
||||
|
||||
// may not be necessary
|
||||
_mm_mfence();
|
||||
|
||||
// set additional information
|
||||
g_reservation_addr = addr;
|
||||
g_reservation_size = size;
|
||||
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 - 1 & ~0xfff) == (addr & ~0xfff));
|
||||
|
||||
std::lock_guard<reservation_mutex_t> lock(g_reservation_mutex);
|
||||
|
||||
if (g_reservation_owner != GetCurrentNamedThread() || g_reservation_addr != addr || g_reservation_size != size)
|
||||
{
|
||||
// atomic update failed
|
||||
return false;
|
||||
}
|
||||
|
||||
// change memory protection to no access
|
||||
_reservation_set(addr, true);
|
||||
|
||||
// update memory using privileged access
|
||||
memcpy(vm::get_priv_ptr(addr), data, size);
|
||||
|
||||
// remove callback to not call it on successful update
|
||||
g_reservation_cb = nullptr;
|
||||
|
||||
// free the reservation and restore memory protection
|
||||
_reservation_break(addr);
|
||||
|
||||
// atomic update succeeded
|
||||
return true;
|
||||
}
|
||||
|
||||
bool reservation_query(u32 addr, bool is_writing)
|
||||
{
|
||||
std::lock_guard<reservation_mutex_t> lock(g_reservation_mutex);
|
||||
|
||||
{
|
||||
LV2_LOCK(0);
|
||||
|
||||
if (!Memory.IsGoodAddr(addr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_writing)
|
||||
{
|
||||
// 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 - 1 & ~0xfff) == (addr & ~0xfff));
|
||||
|
||||
std::lock_guard<reservation_mutex_t> lock(g_reservation_mutex);
|
||||
|
||||
// break previous reservation
|
||||
if (g_reservation_owner != GetCurrentNamedThread() || g_reservation_addr != addr || g_reservation_size != size)
|
||||
{
|
||||
if (g_reservation_owner)
|
||||
{
|
||||
_reservation_break(g_reservation_addr);
|
||||
}
|
||||
}
|
||||
|
||||
// change memory protection to no access
|
||||
_reservation_set(addr, true);
|
||||
|
||||
// set additional information
|
||||
g_reservation_addr = addr;
|
||||
g_reservation_size = size;
|
||||
g_reservation_owner = GetCurrentNamedThread();
|
||||
g_reservation_cb = nullptr;
|
||||
|
||||
// may not be necessary
|
||||
_mm_mfence();
|
||||
|
||||
// do the operation
|
||||
proc();
|
||||
|
||||
// remove the reservation
|
||||
_reservation_break(addr);
|
||||
}
|
||||
|
||||
bool check_addr(u32 addr)
|
||||
{
|
||||
@ -62,8 +377,12 @@ namespace vm
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
@ -263,4 +582,4 @@ namespace vm
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,24 @@ namespace vm
|
||||
static void set_stack_size(u32 size) {}
|
||||
static void initialize_stack() {}
|
||||
|
||||
#ifdef _WIN32
|
||||
extern HANDLE g_memory_handle;
|
||||
#endif
|
||||
|
||||
extern void* g_priv_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, bool is_writing);
|
||||
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 unmap(u32 addr, u32 size = 0, u32 flags = 0);
|
||||
u32 alloc(u32 size, memory_location location = user_space);
|
||||
@ -40,6 +57,18 @@ namespace vm
|
||||
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);
|
||||
|
||||
__noinline void error(const u64 addr, const char* func);
|
||||
|
@ -213,6 +213,11 @@ namespace vm
|
||||
{
|
||||
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)
|
||||
{
|
||||
@ -243,6 +248,11 @@ namespace vm
|
||||
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
|
||||
{
|
||||
return get_ptr();
|
||||
@ -301,6 +311,11 @@ namespace vm
|
||||
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
|
||||
{
|
||||
return get_ptr();
|
||||
|
@ -136,7 +136,7 @@ const char *getModuleName(int id) {
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return "UNKNOWN MODULE";
|
||||
}
|
||||
|
||||
int cellSysmoduleInitialize()
|
||||
@ -159,11 +159,12 @@ int cellSysmoduleSetMemcontainer(u32 ct_id)
|
||||
|
||||
int cellSysmoduleLoadModule(u16 id)
|
||||
{
|
||||
cellSysmodule->Warning("cellSysmoduleLoadModule(id=0x%04x: %s)", id, getModuleName(id));
|
||||
|
||||
if (id == 0xf054)
|
||||
{
|
||||
cellSysmodule->Todo("cellSysmoduleLoadModule: CELL_SYSMODULE_LIBATRAC3MULTI");
|
||||
}
|
||||
cellSysmodule->Warning("cellSysmoduleLoadModule(%s)", getModuleName(id));
|
||||
|
||||
if (Module* m = Emu.GetModuleManager().GetModuleById(id))
|
||||
{
|
||||
@ -180,7 +181,8 @@ int cellSysmoduleLoadModule(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);
|
||||
|
||||
if(!m)
|
||||
@ -199,7 +201,8 @@ int cellSysmoduleUnloadModule(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);
|
||||
|
||||
if(!m)
|
||||
|
@ -69,6 +69,13 @@ struct sceNpTrophyInternal
|
||||
|
||||
sceNpTrophyInternal sceNpTrophyInstance;
|
||||
|
||||
static sceNpTrophyInternalContext& getContext(u32 context) {
|
||||
// The invalid context is 0, so remap contexts 1... to indices 0...
|
||||
if (context == 0)
|
||||
throw "getContext: context == 0";
|
||||
return sceNpTrophyInstance.contexts[context - 1];
|
||||
}
|
||||
|
||||
// Functions
|
||||
int sceNpTrophyInit(u32 pool_addr, u32 poolSize, u32 containerId, u64 options)
|
||||
{
|
||||
@ -114,6 +121,7 @@ int sceNpTrophyCreateContext(vm::ptr<u32> context, vm::ptr<SceNpCommunicationId>
|
||||
ctxt.trp_stream.reset(stream);
|
||||
ctxt.trp_name = entry->name;
|
||||
stream = nullptr;
|
||||
*context = sceNpTrophyInstance.contexts.size(); // contexts start from 1
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
@ -124,7 +132,7 @@ int sceNpTrophyCreateContext(vm::ptr<u32> context, vm::ptr<SceNpCommunicationId>
|
||||
|
||||
int sceNpTrophyCreateHandle(vm::ptr<u32> handle)
|
||||
{
|
||||
sceNpTrophy->Warning("sceNpTrophyCreateHandle(handle_addr=0x%x)", handle.addr());
|
||||
sceNpTrophy->Todo("sceNpTrophyCreateHandle(handle_addr=0x%x)", handle.addr());
|
||||
|
||||
if (!sceNpTrophyInstance.m_bInitialized)
|
||||
return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
|
||||
@ -144,11 +152,13 @@ int sceNpTrophyRegisterContext(u32 context, u32 handle, vm::ptr<SceNpTrophyStatu
|
||||
return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
|
||||
if (options & (~(u64)1))
|
||||
return SCE_NP_TROPHY_ERROR_NOT_SUPPORTED;
|
||||
if (context >= sceNpTrophyInstance.contexts.size())
|
||||
if (context == 0 || context > sceNpTrophyInstance.contexts.size()) {
|
||||
sceNpTrophy->Warning("sceNpTrophyRegisterContext: invalid context (%d)", context);
|
||||
return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT;
|
||||
}
|
||||
// TODO: There are other possible errors
|
||||
|
||||
sceNpTrophyInternalContext& ctxt = sceNpTrophyInstance.contexts[context];
|
||||
sceNpTrophyInternalContext& ctxt = getContext(context);
|
||||
if (!ctxt.trp_stream)
|
||||
return SCE_NP_TROPHY_ERROR_CONF_DOES_NOT_EXIST;
|
||||
|
||||
@ -219,11 +229,13 @@ int sceNpTrophyGetRequiredDiskSpace(u32 context, u32 handle, vm::ptr<u64> reqspa
|
||||
|
||||
if (!sceNpTrophyInstance.m_bInitialized)
|
||||
return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
|
||||
if (context >= sceNpTrophyInstance.contexts.size())
|
||||
if (context == 0 || context > sceNpTrophyInstance.contexts.size()) {
|
||||
sceNpTrophy->Warning("sceNpTrophyGetRequiredDiskSpace: invalid context (%d)", context);
|
||||
return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT;
|
||||
}
|
||||
// TODO: There are other possible errors
|
||||
|
||||
sceNpTrophyInternalContext& ctxt = sceNpTrophyInstance.contexts[context];
|
||||
const sceNpTrophyInternalContext& ctxt = getContext(context);
|
||||
if (!ctxt.trp_stream)
|
||||
return SCE_NP_TROPHY_ERROR_CONF_DOES_NOT_EXIST;
|
||||
|
||||
@ -260,7 +272,7 @@ int sceNpTrophyGetGameInfo(u32 context, u32 handle, vm::ptr<SceNpTrophyGameDetai
|
||||
|
||||
std::string path;
|
||||
rXmlDocument doc;
|
||||
sceNpTrophyInternalContext& ctxt = sceNpTrophyInstance.contexts[context];
|
||||
const sceNpTrophyInternalContext& ctxt = getContext(context);
|
||||
Emu.GetVFS().GetDevice("/dev_hdd0/home/00000001/trophy/" + ctxt.trp_name + "/TROPCONF.SFM", path); // TODO: Get the path of the current user
|
||||
doc.Load(path);
|
||||
|
||||
@ -316,7 +328,7 @@ int sceNpTrophyUnlockTrophy(u32 context, u32 handle, s32 trophyId, vm::ptr<u32>
|
||||
return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
|
||||
// TODO: There are other possible errors
|
||||
|
||||
sceNpTrophyInternalContext& ctxt = sceNpTrophyInstance.contexts[context];
|
||||
sceNpTrophyInternalContext& ctxt = getContext(context);
|
||||
if (trophyId >= (s32)ctxt.tropusr->GetTrophiesCount())
|
||||
return SCE_NP_TROPHY_ERROR_INVALID_TROPHY_ID;
|
||||
if (ctxt.tropusr->GetTrophyUnlockState(trophyId))
|
||||
@ -351,15 +363,20 @@ int sceNpTrophyGetTrophyUnlockState(u32 context, u32 handle, vm::ptr<SceNpTrophy
|
||||
|
||||
if (!sceNpTrophyInstance.m_bInitialized)
|
||||
return SCE_NP_TROPHY_ERROR_NOT_INITIALIZED;
|
||||
if (context == 0 || context > sceNpTrophyInstance.contexts.size()) {
|
||||
sceNpTrophy->Warning("sceNpTrophyGetTrophyUnlockState: invalid context (%d)", context);
|
||||
return SCE_NP_TROPHY_ERROR_UNKNOWN_CONTEXT;
|
||||
}
|
||||
// TODO: There are other possible errors
|
||||
|
||||
sceNpTrophyInternalContext& ctxt = sceNpTrophyInstance.contexts[context];
|
||||
*count = ctxt.tropusr->GetTrophiesCount();
|
||||
if (*count > 128)
|
||||
const sceNpTrophyInternalContext& ctxt = getContext(context);
|
||||
u32 count_ = ctxt.tropusr->GetTrophiesCount();
|
||||
*count = count_;
|
||||
if (count_ > 128)
|
||||
sceNpTrophy->Warning("sceNpTrophyGetTrophyUnlockState: More than 128 trophies detected!");
|
||||
|
||||
// Pack up to 128 bools in u32 flag_bits[4]
|
||||
for (u32 id=0; id<*count; id++)
|
||||
for (u32 id = 0; id < count_; id++)
|
||||
{
|
||||
if (ctxt.tropusr->GetTrophyUnlockState(id))
|
||||
flags->flag_bits[id/32] |= 1<<(id%32);
|
||||
@ -387,7 +404,7 @@ int sceNpTrophyGetTrophyInfo(u32 context, u32 handle, s32 trophyId, vm::ptr<SceN
|
||||
|
||||
std::string path;
|
||||
rXmlDocument doc;
|
||||
sceNpTrophyInternalContext& ctxt = sceNpTrophyInstance.contexts[context];
|
||||
const sceNpTrophyInternalContext& ctxt = getContext(context);
|
||||
Emu.GetVFS().GetDevice("/dev_hdd0/home/00000001/trophy/" + ctxt.trp_name + "/TROPCONF.SFM", path); // TODO: Get the path of the current user
|
||||
doc.Load(path);
|
||||
|
||||
|
@ -349,6 +349,8 @@ void Emulator::Resume()
|
||||
GetCallbackManager().RunPauseCallbacks(false);
|
||||
}
|
||||
|
||||
extern std::map<u32, std::string> g_armv7_dump;
|
||||
|
||||
void Emulator::Stop()
|
||||
{
|
||||
if(IsStopped()) return;
|
||||
@ -365,6 +367,14 @@ void Emulator::Stop()
|
||||
|
||||
finalize_psv_modules();
|
||||
clear_all_psv_objects();
|
||||
|
||||
for (auto& v : g_armv7_dump)
|
||||
{
|
||||
LOG_NOTICE(ARMv7, v.second);
|
||||
}
|
||||
|
||||
g_armv7_dump.clear();
|
||||
|
||||
m_rsx_callback = 0;
|
||||
|
||||
// TODO: check finalization order
|
||||
|
@ -401,8 +401,8 @@ namespace loader
|
||||
armv7_decoder_initialize(code_start, code_end);
|
||||
|
||||
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 priority = proc_param->sceUserMainThreadPriority ? *proc_param->sceUserMainThreadPriority : 0;
|
||||
const u32 stack_size = proc_param->sceUserMainThreadStackSize ? *proc_param->sceUserMainThreadStackSize : 256 * 1024;
|
||||
const u32 priority = proc_param->sceUserMainThreadPriority ? *proc_param->sceUserMainThreadPriority : 160;
|
||||
|
||||
armv7_thread(entry, thread_name, stack_size, priority).args({ Emu.GetPath(), "-emu" }).run();
|
||||
break;
|
||||
|
@ -56,7 +56,9 @@
|
||||
<ClCompile Include="Emu\ARMv7\ARMv7DisAsm.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\ARMv7Interpreter.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_mutex.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\psv_sema.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceAppMgr.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceAppUtil.cpp" />
|
||||
@ -334,7 +336,9 @@
|
||||
<ClInclude Include="Emu\ARMv7\ARMv7Interpreter.h" />
|
||||
<ClInclude Include="Emu\ARMv7\ARMv7Opcodes.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_mutex.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\psv_sema.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceAppUtil.h" />
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceGxm.h" />
|
||||
|
@ -583,7 +583,7 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\RSX\RSXDMA.cpp">
|
||||
<Filter>Emu\GPU\RSX</Filter>
|
||||
</ClCompile>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\RSX\RSXTexture.cpp">
|
||||
<Filter>Emu\GPU\RSX</Filter>
|
||||
</ClCompile>
|
||||
@ -670,7 +670,7 @@
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\ARMv7Decoder.cpp">
|
||||
<Filter>Emu\CPU\ARMv7</Filter>
|
||||
</ClCompile>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\PSVObjectList.cpp">
|
||||
<Filter>Emu\CPU\ARMv7</Filter>
|
||||
</ClCompile>
|
||||
@ -696,7 +696,7 @@
|
||||
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceGxm.cpp">
|
||||
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
||||
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceAppMgr.cpp">
|
||||
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
||||
@ -848,6 +848,12 @@
|
||||
<ClCompile Include="Emu\ARMv7\Modules\sceSha.cpp">
|
||||
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
||||
</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>
|
||||
<ClInclude Include="Crypto\aes.h">
|
||||
@ -1350,7 +1356,7 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\RSX\RSXDMA.h">
|
||||
<Filter>Emu\GPU\RSX</Filter>
|
||||
</ClInclude>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\RSX\RSXFragmentProgram.h">
|
||||
<Filter>Emu\GPU\RSX</Filter>
|
||||
</ClInclude>
|
||||
@ -1479,7 +1485,7 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceLibKernel.h">
|
||||
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\PSVObjectList.h">
|
||||
<Filter>Emu\CPU\ARMv7</Filter>
|
||||
</ClInclude>
|
||||
@ -1490,7 +1496,7 @@
|
||||
<Filter>Emu\CPU\ARMv7\Objects</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceGxm.h">
|
||||
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
||||
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceAppUtil.h">
|
||||
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
||||
@ -1510,5 +1516,11 @@
|
||||
<ClInclude Include="Emu\ARMv7\Modules\sceNpCommon.h">
|
||||
<Filter>Emu\CPU\ARMv7\Modules</Filter>
|
||||
</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>
|
||||
</Project>
|
Loading…
x
Reference in New Issue
Block a user