From 27c35174bced685d6c64b07fe8ddccd8a793a89d Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 7 Nov 2014 22:30:04 +0300 Subject: [PATCH 01/10] ARMv7: ADD*, LSL*, shifts fixed --- rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp | 283 +++++++++++++++++++++++ rpcs3/Emu/ARMv7/ARMv7Interpreter.h | 75 +++--- rpcs3/Emu/ARMv7/ARMv7Opcodes.h | 18 +- rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp | 276 ++++++++++++++++++++-- rpcs3/Emu/ARMv7/Modules/sceLibc.cpp | 6 +- 5 files changed, 585 insertions(+), 73 deletions(-) diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp index 0e4f3a55e8..87d33e05c6 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp @@ -90,6 +90,46 @@ void ARMv7Interpreter::ADD_IMM(const u32 data, const ARMv7_encoding type) imm32 = (data & 0x1c0) >> 6; break; } + case T2: + { + d = n = (data & 0x700) >> 8; + imm32 = (data & 0xff); + break; + } + case T3: + { + d = (data & 0xf00) >> 8; + n = (data & 0xf0000) >> 16; + set_flags = (data & 0x100000); + imm32 = ThumbExpandImm((data & 0x4000000) >> 15 | (data & 0x7000) >> 4 | (data & 0xff)); + + if (d == 15 && set_flags) + { + throw "CMN (immediate)"; + } + if (n == 13) + { + throw "ADD (SP plus immediate)"; + } + break; + } + case T4: + { + d = (data & 0xf00) >> 8; + n = (data & 0xf0000) >> 16; + set_flags = false; + imm32 = (data & 0x4000000) >> 15 | (data & 0x7000) >> 4 | (data & 0xff); + + if (n == 15) + { + throw "ADR"; + } + if (n == 13) + { + throw "ADD (SP plus immediate)"; + } + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } @@ -115,11 +155,75 @@ void ARMv7Interpreter::ADD_IMM(const u32 data, const ARMv7_encoding type) void ARMv7Interpreter::ADD_REG(const u32 data, const ARMv7_encoding type) { + bool set_flags = !CPU.ITSTATE; + u32 cond = CPU.ITSTATE.advance(); + u32 d = 0; + u32 n = 0; + u32 m = 0; + auto shift_t = SRType_LSL; + u32 shift_n = 0; + switch (type) { + case T1: + { + d = (data & 0x7); + n = (data & 0x38) >> 3; + m = (data & 0x1c0) >> 6; + break; + } + case T2: + { + n = d = (data & 0x80) >> 4 | (data & 0x7); + m = (data & 0x78) >> 3; + set_flags = false; + + if (n == 13 || m == 13) + { + throw "ADD (SP plus register)"; + } + break; + } + case T3: + { + d = (data & 0xf00) >> 8; + n = (data & 0xf0000) >> 16; + m = (data & 0xf); + set_flags = (data & 0x100000); + shift_t = DecodeImmShift((data & 0x30) >> 4, (data & 0x7000) >> 10 | (data & 0xc0) >> 6, &shift_n); + + if (d == 15 && set_flags) + { + throw "CMN (register)"; + } + if (n == 13) + { + throw "ADD (SP plus register)"; + } + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(cond)) + { + const u32 shifted = Shift(CPU.read_gpr(m), shift_t, shift_n, true); + if (set_flags) + { + bool carry, overflow; + const u32 res = AddWithCarry(CPU.read_gpr(n), shifted, false, carry, overflow); + CPU.write_gpr(d, res); + CPU.APSR.N = res >> 31; + CPU.APSR.Z = res == 0; + CPU.APSR.C = carry; + CPU.APSR.V = overflow; + } + else + { + CPU.write_gpr(d, CPU.read_gpr(n) + shifted); + } + } } void ARMv7Interpreter::ADD_RSR(const u32 data, const ARMv7_encoding type) @@ -133,20 +237,122 @@ void ARMv7Interpreter::ADD_RSR(const u32 data, const ARMv7_encoding type) void ARMv7Interpreter::ADD_SPI(const u32 data, const ARMv7_encoding type) { + u32 cond = CPU.ITSTATE.advance(); + u32 d = 13; + bool set_flags = false; + u32 imm32 = 0; + switch (type) { + case T1: + { + d = (data & 0x700) >> 8; + imm32 = (data & 0xff) << 2; + break; + } + case T2: + { + imm32 = (data & 0x7f) << 2; + break; + } + case T3: + { + d = (data & 0xf00) >> 8; + set_flags = (data & 0x100000); + imm32 = ThumbExpandImm((data & 0x4000000) >> 15 | (data & 0x7000) >> 4 | (data & 0xff)); + + if (d == 15 && set_flags) + { + throw "CMN (immediate)"; + } + break; + } + case T4: + { + d = (data & 0xf00) >> 8; + set_flags = false; + imm32 = (data & 0x4000000) >> 15 | (data & 0x7000) >> 4 | (data & 0xff); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(cond)) + { + if (set_flags) + { + bool carry, overflow; + const u32 res = AddWithCarry(CPU.SP, imm32, false, carry, overflow); + CPU.write_gpr(d, res); + CPU.APSR.N = res >> 31; + CPU.APSR.Z = res == 0; + CPU.APSR.C = carry; + CPU.APSR.V = overflow; + } + else + { + CPU.write_gpr(d, CPU.SP + imm32); + } + } } void ARMv7Interpreter::ADD_SPR(const u32 data, const ARMv7_encoding type) { + u32 cond = CPU.ITSTATE.advance(); + u32 d = 13; + u32 m = 0; + bool set_flags = false; + auto shift_t = SRType_LSL; + u32 shift_n = 0; + switch (type) { + case T1: + { + m = d = (data & 0x80) >> 4 | (data & 0x7); + break; + } + case T2: + { + m = (data & 0x78) >> 3; + + if (m == 13) + { + throw "ADD_SPR_T2: T1"; + } + break; + } + case T3: + { + d = (data & 0xf00) >> 8; + m = (data & 0xf); + set_flags = (data & 0x100000); + shift_t = DecodeImmShift((data & 0x30) >> 4, (data & 0x7000) >> 10 | (data & 0xc0) >> 6, &shift_n); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(cond)) + { + const u32 shifted = Shift(CPU.read_gpr(m), shift_t, shift_n, CPU.APSR.C); + if (set_flags) + { + bool carry, overflow; + const u32 res = AddWithCarry(CPU.SP, shifted, false, carry, overflow); + CPU.write_gpr(d, res); + CPU.APSR.N = res >> 31; + CPU.APSR.Z = res == 0; + CPU.APSR.C = carry; + CPU.APSR.V = overflow; + } + else + { + CPU.write_gpr(d, CPU.SP + CPU.read_gpr(m)); + } + } } @@ -918,20 +1124,97 @@ void ARMv7Interpreter::LDRSH_REG(const u32 data, const ARMv7_encoding type) void ARMv7Interpreter::LSL_IMM(const u32 data, const ARMv7_encoding type) { + bool set_flags = !CPU.ITSTATE; + u32 cond = CPU.ITSTATE.advance(); + u32 d = 0; + u32 m = 0; + u32 shift_n = 0; + switch (type) { + case T1: + { + d = (data & 0x7); + m = (data & 0x38) >> 3; + shift_n = (data & 0x7c0) >> 6; + + if (!shift_n) + { + throw "MOV (register)"; + } + break; + } + case T2: + { + d = (data & 0xf00) >> 8; + m = (data & 0xf); + set_flags = (data & 0x100000); + shift_n = (data & 0x7000) >> 10 | (data & 0xc0) >> 6; + + if (!shift_n) + { + throw "MOV (register)"; + } + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(cond)) + { + bool carry; + const u32 res = Shift_C(CPU.read_gpr(m), SRType_LSL, shift_n, CPU.APSR.C, carry); + CPU.write_gpr(d, res); + if (set_flags) + { + CPU.APSR.N = res >> 31; + CPU.APSR.Z = res == 0; + CPU.APSR.C = carry; + } + } } void ARMv7Interpreter::LSL_REG(const u32 data, const ARMv7_encoding type) { + bool set_flags = !CPU.ITSTATE; + u32 cond = CPU.ITSTATE.advance(); + u32 d = 0; + u32 n = 0; + u32 m = 0; + switch (type) { + case T1: + { + d = n = (data & 0x7); + m = (data & 0x38) >> 3; + break; + } + case T2: + { + d = (data & 0xf00) >> 8; + n = (data & 0xf0000) >> 16; + m = (data & 0xf); + set_flags = (data & 0x100000); + break; + } case A1: throw __FUNCTION__; default: throw __FUNCTION__; } + + if (ConditionPassed(cond)) + { + bool carry; + const u32 res = Shift_C(CPU.read_gpr(n), SRType_LSL, (CPU.read_gpr(m) & 0xff), CPU.APSR.C, carry); + CPU.write_gpr(d, res); + if (set_flags) + { + CPU.APSR.N = res >> 31; + CPU.APSR.Z = res == 0; + CPU.APSR.C = carry; + } + } } diff --git a/rpcs3/Emu/ARMv7/ARMv7Interpreter.h b/rpcs3/Emu/ARMv7/ARMv7Interpreter.h index e9678fe245..bb8d71b1fc 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Interpreter.h +++ b/rpcs3/Emu/ARMv7/ARMv7Interpreter.h @@ -132,75 +132,72 @@ public: return shift_t; } - u32 LSL_C(u32 x, int shift, bool& carry_out) + u32 LSL_C(u32 x, s32 shift, bool& carry_out) { - u32 extended_x = x << shift; - carry_out = (extended_x >> 31) ? 1 : 0; - return extended_x & ~(1 << 31); + assert(shift > 0); + carry_out = shift <= 32 ? x & (1 << (32 - shift)) : false; + return shift < 32 ? x << shift : 0; } - u32 LSL(u32 x, int shift) + u32 LSL(u32 x, s32 shift) { - if(!shift) return x; - bool carry_out; - return LSL_C(x, shift, carry_out); + assert(shift >= 0); + return shift < 32 ? x << shift : 0; } - u32 LSR_C(u32 x, int shift, bool& carry_out) + u32 LSR_C(u32 x, s32 shift, bool& carry_out) { - carry_out = (x >> (shift - 1)) & 0x1; - return x >> shift; + assert(shift > 0); + carry_out = shift <= 32 ? x & (1 << (shift - 1)) : false; + return shift < 32 ? x >> shift : 0; } - u32 LSR(u32 x, int shift) + u32 LSR(u32 x, s32 shift) { - if(!shift) return x; - bool carry_out; - return LSR_C(x, shift, carry_out); + assert(shift >= 0); + return shift < 32 ? x >> shift : 0; } - s32 ASR_C(s32 x, int shift, bool& carry_out) + s32 ASR_C(s32 x, s32 shift, bool& carry_out) { - carry_out = (x >> (shift - 1)) & 0x1; - return x >> shift; + assert(shift > 0); + carry_out = shift <= 32 ? x & (1 << (shift - 1)) : false; + return shift < 32 ? x >> shift : x >> 31; } - s32 ASR(s32 x, int shift) + s32 ASR(s32 x, s32 shift) { - if(!shift) return x; - bool carry_out; - return ASR_C(x, shift, carry_out); + assert(shift >= 0); + return shift < 32 ? x >> shift : x >> 31; } - u32 ROR_C(u32 x, int shift, bool& carry_out) + u32 ROR_C(u32 x, s32 shift, bool& carry_out) { - u32 result = LSR(x, shift) | LSL(x, 32 - shift); - carry_out = (result >> 30) & 0x1; - return result; + assert(shift); + carry_out = x & (1 << (shift - 1)); + return x >> shift | x << (32 - shift); } - s32 ROR(s32 x, int shift) + u32 ROR(u32 x, s32 shift) { - if(!shift) return x; - bool carry_out; - return ROR_C(x, shift, carry_out); + return x >> shift | x << (32 - shift); } - template T RRX_C(T x, bool carry_in, bool& carry_out) + u32 RRX_C(u32 x, bool carry_in, bool& carry_out) { carry_out = x & 0x1; - return ((u32)carry_in << 31) | (x & 0x7ffffffe); + return ((u32)carry_in << 31) | (x >> 1); } - s32 RRX(s32 x, int shift) + u32 RRX(u32 x, bool carry_in) { - if(!shift) return x; - bool carry_out; - return RRX_C(x, shift, carry_out); + return ((u32)carry_in << 31) | (x >> 1); } - template T Shift_C(T value, SRType type, uint amount, bool carry_in, bool& carry_out) + template T Shift_C(T value, SRType type, s32 amount, bool carry_in, bool& carry_out) { + assert(type != SRType_RRX || amount == 1); + if(amount) { switch(type) @@ -209,7 +206,7 @@ public: case SRType_LSR: return LSR_C(value, amount, carry_out); case SRType_ASR: return ASR_C(value, amount, carry_out); case SRType_ROR: return ROR_C(value, amount, carry_out); - case SRType_RRX: return RRX_C(value, amount, carry_out); + case SRType_RRX: return RRX_C(value, carry_in, carry_out); } } @@ -217,7 +214,7 @@ public: return value; } - template T Shift(T value, SRType type, u32 amount, bool carry_in) + template T Shift(T value, SRType type, s32 amount, bool carry_in) { bool carry_out; return Shift_C(value, type, amount, carry_in, carry_out); diff --git a/rpcs3/Emu/ARMv7/ARMv7Opcodes.h b/rpcs3/Emu/ARMv7/ARMv7Opcodes.h index fb46013f1b..ddd6962885 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Opcodes.h +++ b/rpcs3/Emu/ARMv7/ARMv7Opcodes.h @@ -350,6 +350,15 @@ static const ARMv7_opcode_t ARMv7_opcode_table[] = ARMv7_OP4(0x0fe0, 0x0010, 0x00a0, 0x0000, A1, ADC_REG), ARMv7_OP4(0x0fe0, 0x0090, 0x00a0, 0x0010, A1, ADC_RSR), + ARMv7_OP2(0xf800, 0xa800, T1, ADD_SPI), + ARMv7_OP2(0xff80, 0xb000, T2, ADD_SPI), + ARMv7_OP4(0xfbef, 0x8000, 0xf10d, 0x0000, T3, ADD_SPI), + ARMv7_OP4(0xfbff, 0x8000, 0xf20d, 0x0000, T4, ADD_SPI), + ARMv7_OP4(0x0fef, 0x0000, 0x028d, 0x0000, A1, ADD_SPI), + ARMv7_OP2(0xff78, 0x4468, T1, ADD_SPR), + ARMv7_OP2(0xff87, 0x4485, T2, ADD_SPR), + ARMv7_OP4(0xffef, 0x8000, 0xeb0d, 0x0000, T3, ADD_SPR), + ARMv7_OP4(0x0fef, 0x0010, 0x008d, 0x0000, A1, ADD_SPR), ARMv7_OP2(0xfe00, 0x1c00, T1, ADD_IMM), ARMv7_OP2(0xf800, 0x3000, T2, ADD_IMM), ARMv7_OP4(0xfbe0, 0x8000, 0xf100, 0x0000, T3, ADD_IMM), @@ -360,15 +369,6 @@ static const ARMv7_opcode_t ARMv7_opcode_table[] = ARMv7_OP4(0xffe0, 0x8000, 0xeb00, 0x0000, T3, ADD_REG), ARMv7_OP4(0x0fe0, 0x0010, 0x0080, 0x0000, A1, ADD_REG), ARMv7_OP4(0x0fe0, 0x0090, 0x0080, 0x0010, A1, ADD_RSR), - ARMv7_OP2(0xf800, 0xa800, T1, ADD_SPI), - ARMv7_OP2(0xff80, 0xb000, T2, ADD_SPI), - ARMv7_OP4(0xfbef, 0x8000, 0xf10d, 0x0000, T3, ADD_SPI), - ARMv7_OP4(0xfbff, 0x8000, 0xf20d, 0x0000, T4, ADD_SPI), - ARMv7_OP4(0x0fef, 0x0000, 0x028d, 0x0000, A1, ADD_SPI), - ARMv7_OP2(0xff78, 0x4468, T1, ADD_SPR), - ARMv7_OP2(0xff87, 0x4485, T2, ADD_SPR), - ARMv7_OP4(0xffef, 0x8000, 0xeb0d, 0x0000, T3, ADD_SPR), - ARMv7_OP4(0x0fef, 0x0010, 0x008d, 0x0000, A1, ADD_SPR), ARMv7_OP2(0xf800, 0xa000, T1, ADR), ARMv7_OP4(0xfbff, 0x8000, 0xf2af, 0x0000, T2, ADR), diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp index 4f161201e8..529a0bdc42 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp @@ -5,14 +5,83 @@ extern psv_log_base sceLibKernel; +#pragma pack(push, 4) + typedef s32(*SceKernelThreadEntry)(u32 argSize, vm::psv::ptr pArgBlock); +union SceKernelSysClock +{ + struct + { + u32 low; + u32 hi; + }; + u64 quad; +}; + struct SceKernelThreadOptParam { u32 size; u32 attr; }; +struct SceKernelThreadInfo +{ + u32 size; + s32 processId; + char name[32]; + u32 attr; + u32 status; + SceKernelThreadEntry entry; + vm::psv::ptr pStack; + u32 stackSize; + s32 initPriority; + s32 currentPriority; + s32 initCpuAffinityMask; + s32 currentCpuAffinityMask; + s32 currentCpuId; + s32 lastExecutedCpuId; + u32 waitType; + s32 waitId; + s32 exitStatus; + SceKernelSysClock runClocks; + u32 intrPreemptCount; + u32 threadPreemptCount; + u32 threadReleaseCount; + s32 changeCpuCount; + s32 fNotifyCallback; + s32 reserved; +}; + +struct SceKernelThreadRunStatus +{ + u32 size; + + struct + { + s32 processId; + s32 threadId; + s32 priority; + + } cpuInfo[4]; +}; + +struct SceKernelSystemInfo +{ + u32 size; + u32 activeCpuMask; + + struct + { + SceKernelSysClock idleClock; + u32 comesOutOfIdleCount; + u32 threadSwitchCount; + + } cpuInfo[4]; +}; + +#pragma pack(pop, 4) + s32 sceKernelCreateThread( vm::psv::ptr pName, vm::psv::ptr entry, @@ -28,6 +97,167 @@ s32 sceKernelCreateThread( return SCE_OK; } +s32 sceKernelStartThread(s32 threadId, u32 argSize, vm::psv::ptr pArgBlock) +{ + sceLibKernel.Todo("sceKernelStartThread(threadId=%d, argSize=%d, pArgBlock_addr=0x%x)", threadId, argSize, pArgBlock.addr()); + + return SCE_OK; +} + +s32 sceKernelExitThread(s32 exitStatus) +{ + sceLibKernel.Todo("sceKernelExitThread(exitStatus=0x%x)", exitStatus); + + return SCE_OK; +} + +s32 sceKernelDeleteThread(s32 threadId) +{ + sceLibKernel.Todo("sceKernelDeleteThread(threadId=%d)", threadId); + + return SCE_OK; +} + +s32 sceKernelExitDeleteThread(s32 exitStatus) +{ + sceLibKernel.Todo("sceKernelExitDeleteThread(exitStatus=0x%x)", exitStatus); + + return SCE_OK; +} + +s32 sceKernelChangeThreadCpuAffinityMask(s32 threadId, s32 cpuAffinityMask) +{ + sceLibKernel.Todo("sceKernelChangeThreadCpuAffinityMask(threadId=%d, cpuAffinityMask=0x%x)", threadId, cpuAffinityMask); + + return SCE_OK; +} + +s32 sceKernelGetThreadCpuAffinityMask(s32 threadId) +{ + sceLibKernel.Todo("sceKernelGetThreadCpuAffinityMask(threadId=0x%x)", threadId); + + return SCE_OK; +} + +s32 sceKernelChangeThreadPriority(s32 threadId, s32 priority) +{ + sceLibKernel.Todo("sceKernelChangeThreadPriority(threadId=0x%x, priority=%d)", threadId, priority); + + return SCE_OK; +} + +s32 sceKernelGetThreadCurrentPriority() +{ + sceLibKernel.Todo("sceKernelGetThreadCurrentPriority()"); + + return SCE_OK; +} + +s32 sceKernelGetThreadId() +{ + sceLibKernel.Todo("sceKernelGetThreadId()"); + + return SCE_OK; +} + +s32 sceKernelChangeCurrentThreadAttr(u32 clearAttr, u32 setAttr) +{ + sceLibKernel.Todo("sceKernelChangeCurrentThreadAttr()"); + + return SCE_OK; +} + +s32 sceKernelGetThreadExitStatus(s32 threadId, vm::psv::ptr pExitStatus) +{ + sceLibKernel.Todo("sceKernelGetThreadExitStatus(threadId=%d, pExitStatus_addr=0x%x)", threadId, pExitStatus.addr()); + + return SCE_OK; +} + +s32 sceKernelGetProcessId() +{ + sceLibKernel.Todo("sceKernelGetProcessId()"); + + return SCE_OK; +} + +s32 sceKernelCheckWaitableStatus() +{ + sceLibKernel.Todo("sceKernelCheckWaitableStatus()"); + + return SCE_OK; +} + +s32 sceKernelGetThreadInfo(s32 threadId, vm::psv::ptr pInfo) +{ + sceLibKernel.Todo("sceKernelGetThreadInfo(threadId=%d, pInfo_addr=0x%x)", threadId, pInfo.addr()); + + return SCE_OK; +} + +s32 sceKernelGetThreadRunStatus(vm::psv::ptr pStatus) +{ + sceLibKernel.Todo("sceKernelGetThreadRunStatus(pStatus_addr=0x%x)", pStatus.addr()); + + return SCE_OK; +} + +s32 sceKernelGetSystemInfo(vm::psv::ptr pInfo) +{ + sceLibKernel.Todo("sceKernelGetSystemInfo(pInfo_addr=0x%x)", pInfo.addr()); + + return SCE_OK; +} + +s32 sceKernelGetThreadmgrUIDClass(s32 uid) +{ + sceLibKernel.Todo("sceKernelGetThreadmgrUIDClass(uid=%d)", uid); + + return SCE_OK; +} + +s32 sceKernelChangeThreadVfpException(s32 clearMask, s32 setMask) +{ + sceLibKernel.Todo("sceKernelChangeThreadVfpException(clearMask=0x%x, setMask=0x%x)", clearMask, setMask); + + return SCE_OK; +} + +s32 sceKernelGetCurrentThreadVfpException() +{ + sceLibKernel.Todo("sceKernelGetCurrentThreadVfpException()"); + + return SCE_OK; +} + +s32 sceKernelDelayThread(u32 usec) +{ + sceLibKernel.Todo("sceKernelDelayThread()"); + + return SCE_OK; +} + +s32 sceKernelDelayThreadCB(u32 usec) +{ + sceLibKernel.Todo("sceKernelDelayThreadCB()"); + + return SCE_OK; +} + +s32 sceKernelWaitThreadEnd(s32 threadId, vm::psv::ptr pExitStatus, vm::psv::ptr pTimeout) +{ + sceLibKernel.Todo("sceKernelWaitThreadEnd(threadId=%d, pExitStatus_addr=0x%x, pTimeout_addr=0x%x)", threadId, pExitStatus.addr(), pTimeout.addr()); + + return SCE_OK; +} + +s32 sceKernelWaitThreadEndCB(s32 threadId, vm::psv::ptr pExitStatus, vm::psv::ptr pTimeout) +{ + sceLibKernel.Todo("sceKernelWaitThreadEndCB(threadId=%d, pExitStatus_addr=0x%x, pTimeout_addr=0x%x)", threadId, pExitStatus.addr(), pTimeout.addr()); + + return SCE_OK; +} + #define REG_FUNC(nid, name) reg_psv_func(nid, &sceLibKernel, #name, &name) psv_log_base sceLibKernel = []() -> psv_log_base @@ -145,8 +375,8 @@ psv_log_base sceLibKernel = []() -> psv_log_base //REG_FUNC(0x4C7AD128, sceKernelPowerLock); //REG_FUNC(0xAF8E9C11, sceKernelPowerUnlock); //REG_FUNC(0xB295EB61, sceKernelGetTLSAddr); - //REG_FUNC(0xFB972F9, sceKernelGetThreadId); - //REG_FUNC(0xA37A6057, sceKernelGetCurrentThreadVfpException); + REG_FUNC(0xFB972F9, sceKernelGetThreadId); + REG_FUNC(0xA37A6057, sceKernelGetCurrentThreadVfpException); //REG_FUNC(0xCA71EA2, sceKernelSendMsgPipe); //REG_FUNC(0xA5CA74AC, sceKernelSendMsgPipeCB); //REG_FUNC(0xDFC670E0, sceKernelTrySendMsgPipe); @@ -158,23 +388,23 @@ psv_log_base sceLibKernel = []() -> psv_log_base //REG_FUNC(0x9EF798C1, sceKernelTryLockLwMutex); //REG_FUNC(0x499EA781, sceKernelUnlockLwMutex); //REG_FUNC(0xF7D8F1FC, sceKernelGetLwMutexInfo); - //REG_FUNC(0xDDB395A9, sceKernelWaitThreadEnd); - //REG_FUNC(0xC54941ED, sceKernelWaitThreadEndCB); - //REG_FUNC(0xD5DC26C4, sceKernelGetThreadExitStatus); + REG_FUNC(0xDDB395A9, sceKernelWaitThreadEnd); + REG_FUNC(0xC54941ED, sceKernelWaitThreadEndCB); + REG_FUNC(0xD5DC26C4, sceKernelGetThreadExitStatus); //REG_FUNC(0x4373B548, __sce_aeabi_idiv0); //REG_FUNC(0xFB235848, __sce_aeabi_ldiv0); - //REG_FUNC(0xF08DE149, sceKernelStartThread); - //REG_FUNC(0x58DDAC4F, sceKernelDeleteThread); - //REG_FUNC(0x5150577B, sceKernelChangeThreadCpuAffinityMask); - //REG_FUNC(0x8C57AC2A, sceKernelGetThreadCpuAffinityMask); - //REG_FUNC(0xDF7E6EDA, sceKernelChangeThreadPriority); + REG_FUNC(0xF08DE149, sceKernelStartThread); + REG_FUNC(0x58DDAC4F, sceKernelDeleteThread); + REG_FUNC(0x5150577B, sceKernelChangeThreadCpuAffinityMask); + REG_FUNC(0x8C57AC2A, sceKernelGetThreadCpuAffinityMask); + REG_FUNC(0xDF7E6EDA, sceKernelChangeThreadPriority); //REG_FUNC(0xBCB63B66, sceKernelGetThreadStackFreeSize); - //REG_FUNC(0x8D9C5461, sceKernelGetThreadInfo); - //REG_FUNC(0xD6B01013, sceKernelGetThreadRunStatus); - //REG_FUNC(0xE0241FAA, sceKernelGetSystemInfo); - //REG_FUNC(0xF994FE65, sceKernelGetThreadmgrUIDClass); + REG_FUNC(0x8D9C5461, sceKernelGetThreadInfo); + REG_FUNC(0xD6B01013, sceKernelGetThreadRunStatus); + REG_FUNC(0xE0241FAA, sceKernelGetSystemInfo); + REG_FUNC(0xF994FE65, sceKernelGetThreadmgrUIDClass); //REG_FUNC(0xB4DE10C7, sceKernelGetActiveCpuMask); - //REG_FUNC(0x2C1321A3, sceKernelChangeThreadVfpException); + REG_FUNC(0x2C1321A3, sceKernelChangeThreadVfpException); //REG_FUNC(0x3849359A, sceKernelCreateCallback); //REG_FUNC(0x88DD1BC8, sceKernelGetCallbackInfo); //REG_FUNC(0x464559D3, sceKernelDeleteCallback); @@ -380,15 +610,15 @@ psv_log_base sceLibKernel = []() -> psv_log_base //REG_FUNC(0x800EDCC1, sceKernelClearDipsw); /* SceThreadmgr */ - //REG_FUNC(0xC8A38E1, sceKernelExitThread); - //REG_FUNC(0x1D17DECF, sceKernelExitDeleteThread); - //REG_FUNC(0x4B675D05, sceKernelDelayThread); - //REG_FUNC(0x9C0180E1, sceKernelDelayThreadCB); + REG_FUNC(0xC8A38E1, sceKernelExitThread); + REG_FUNC(0x1D17DECF, sceKernelExitDeleteThread); + REG_FUNC(0x4B675D05, sceKernelDelayThread); + REG_FUNC(0x9C0180E1, sceKernelDelayThreadCB); //REG_FUNC(0x1173F8, sceKernelChangeActiveCpuMask); - //REG_FUNC(0x1414F0B, sceKernelGetThreadCurrentPriority); - //REG_FUNC(0x751C9B7A, sceKernelChangeCurrentThreadAttr); - //REG_FUNC(0xD9BD74EB, sceKernelCheckWaitableStatus); - //REG_FUNC(0x9DCB4B7A, sceKernelGetProcessId); + REG_FUNC(0x1414F0B, sceKernelGetThreadCurrentPriority); + REG_FUNC(0x751C9B7A, sceKernelChangeCurrentThreadAttr); + REG_FUNC(0xD9BD74EB, sceKernelCheckWaitableStatus); + REG_FUNC(0x9DCB4B7A, sceKernelGetProcessId); //REG_FUNC(0xE53E41F6, sceKernelCheckCallback); //REG_FUNC(0xF4EE4FA9, sceKernelGetSystemTimeWide); //REG_FUNC(0x47F6DE49, sceKernelGetSystemTimeLow); diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp index bf6646c7fa..8615526a68 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibc.cpp @@ -44,9 +44,11 @@ namespace sce_libc_func ::memcpy(dst.get_ptr(), src.get_ptr(), size); } - void _Assert() + void _Assert(vm::psv::ptr text, vm::psv::ptr func) { - sceLibc.Todo(__FUNCTION__); + sceLibc.Error("_Assert(text_addr=0x%x, func_addr=0x%x)", text.addr(), func.addr()); + + LOG_ERROR(TTY, "%s : %s", func.get_ptr(), text.get_ptr()); Emu.Pause(); } } From ac20cf006060ef2fd2c1309ee75820e109240312 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 8 Nov 2014 19:58:51 +0300 Subject: [PATCH 02/10] cellGcmCallback modified --- rpcs3/Emu/RSX/GCM.h | 6 ++- rpcs3/Emu/RSX/RSXThread.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp | 45 ++++++----------------- rpcs3/Emu/SysCalls/Modules/cellGcmSys.h | 7 +++- rpcs3/Emu/SysCalls/SysCalls.cpp | 4 +- 5 files changed, 25 insertions(+), 39 deletions(-) diff --git a/rpcs3/Emu/RSX/GCM.h b/rpcs3/Emu/RSX/GCM.h index b0d16bc667..e19e792652 100644 --- a/rpcs3/Emu/RSX/GCM.h +++ b/rpcs3/Emu/RSX/GCM.h @@ -216,12 +216,16 @@ struct CellGcmConfig be_t coreFrequency; }; +struct CellGcmContextData; + +typedef s32(*CellGcmContextCallback)(vm::ptr, u32); + struct CellGcmContextData { be_t begin; be_t end; be_t current; - be_t callback; + vm::bptr callback; }; struct gcmInfo diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index c3e0f4ff95..7bfc5daa6c 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -2266,7 +2266,7 @@ void RSXThread::Task() if(cmd == 0) { LOG_ERROR(Log::RSX, "null cmd: cmd=0x%x, put=0x%x, get=0x%x (addr=0x%x)", cmd, put, get, (u32)Memory.RSXIOMem.RealAddr(get)); - Emu.Pause(); + //Emu.Pause(); //HACK! We shouldn't be here m_ctrl->get = get + (count + 1) * 4; continue; diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index 31eae6d11c..9b61ce5ce3 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -368,7 +368,7 @@ s32 _cellGcmInitBody(vm::ptr context, u32 cmdSize, u32 ioSiz current_context.begin = ctx_begin; current_context.end = ctx_begin + ctx_size; current_context.current = current_context.begin; - current_context.callback = Emu.GetRSXCallback() - 4; + current_context.callback.set(be_t::make(Emu.GetRSXCallback() - 4)); gcm_info.context_addr = (u32)Memory.MainMem.AllocAlign(0x1000); gcm_info.control_addr = gcm_info.context_addr + 0x40; @@ -502,21 +502,11 @@ s32 cellGcmSetPrepareFlip(vm::ptr ctxt, u32 id) if(current + 8 >= end) { - cellGcmSys->Error("bad flip!"); - //cellGcmCallback(ctxt.addr(), current + 8 - end); - //copied: - - auto& ctrl = vm::get_ref(gcm_info.control_addr); - - const s32 res = ctxt->current - ctxt->begin - ctrl.put; - - memmove(vm::get_ptr(ctxt->begin), vm::get_ptr(ctxt->current - res), res); - - ctxt->current = ctxt->begin + res; - - //InterlockedExchange64((volatile long long*)((u8*)&ctrl + offsetof(CellGcmControl, put)), (u64)(u32)re(res)); - ctrl.put = res; - ctrl.get = 0; + if (s32 res = ctxt->callback(ctxt, 8 /* ??? */)) + { + cellGcmSys->Error("cellGcmSetPrepareFlip : callback failed (0x%08x)", res); + return res; + } } current = ctxt->current; @@ -1163,25 +1153,14 @@ int cellGcmSetTile(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u8 co // TODO: This function was originally located in lv2/SC_GCM and appears in RPCS3 as a lv2 syscall with id 1023, // which according to lv2 dumps isn't the case. So, is this a proper place for this function? -int cellGcmCallback(u32 context_addr, u32 count) +s32 cellGcmCallback(vm::ptr context, u32 count) { - cellGcmSys->Log("cellGcmCallback(context_addr=0x%x, count=0x%x)", context_addr, count); - - GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH); - - auto& ctx = vm::get_ref(context_addr); - auto& ctrl = vm::get_ref(gcm_info.control_addr); - - const s32 res = ctx.current - ctx.begin - ctrl.put; - - memmove(vm::get_ptr(ctx.begin), vm::get_ptr(ctx.current - res), res); - - ctx.current = ctx.begin + res; - - //InterlockedExchange64((volatile long long*)((u8*)&ctrl + offsetof(CellGcmControl, put)), (u64)(u32)re(res)); - ctrl.put = res; - ctrl.get = 0; + cellGcmSys->Log("cellGcmCallback(context_addr=0x%x, count=0x%x)", context.addr(), count); + // TODO: this may be wrong + + vm::write32(context->current, CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_NON_INCREMENT | (0)); // set JUMP cmd + context->current = context->begin; // rewind to the beginning return CELL_OK; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.h b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.h index 1473799882..1ee95bdfaf 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.h +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.h @@ -1,4 +1,5 @@ #pragma once +#include "Emu/RSX/GCM.h" enum { @@ -20,8 +21,7 @@ struct CellGcmOffsetTable void InitOffsetTable(); u32 gcmGetLocalMemorySize(); - -// SysCalls +// libgcm functions s32 cellGcmSetPrepareFlip(vm::ptr ctxt, u32 id); s32 cellGcmAddressToOffset(u64 address, vm::ptr> offset); @@ -35,3 +35,6 @@ s32 cellGcmReserveIoMapSize(u32 size); s32 cellGcmUnmapEaIoAddress(u64 ea); s32 cellGcmUnmapIoAddress(u64 io); s32 cellGcmUnreserveIoMapSize(u32 size); + +// Syscall +s32 cellGcmCallback(vm::ptr context, u32 count); diff --git a/rpcs3/Emu/SysCalls/SysCalls.cpp b/rpcs3/Emu/SysCalls/SysCalls.cpp index f055985e88..af6777ecff 100644 --- a/rpcs3/Emu/SysCalls/SysCalls.cpp +++ b/rpcs3/Emu/SysCalls/SysCalls.cpp @@ -26,6 +26,8 @@ #include "lv2/sys_tty.h" #include "lv2/sys_vm.h" +#include "Emu/SysCalls/Modules/cellGcmSys.h" + #include "SysCalls.h" namespace detail{ @@ -40,8 +42,6 @@ static func_caller *null_func = bind_func(default_syscall); static const int kSyscallTableLength = 1024; -extern int cellGcmCallback(u32 context_addr, u32 count); - // UNS = Unused // ROOT = Root // DBG = Debug From c8d4193f08db20682310b74a2048c7421704f859 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 10 Nov 2014 03:21:50 +0300 Subject: [PATCH 03/10] PSV: sceKernelCreateThread and sceKernelStartThread Some fixes in callback manager --- rpcs3/Emu/ARMv7/ARMv7Thread.h | 2 +- rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp | 44 ++++++++++++++++++-- rpcs3/Emu/Memory/vm_ptr.h | 6 +-- rpcs3/Emu/RSX/RSXThread.cpp | 1 + rpcs3/Emu/RSX/RSXThread.h | 1 - rpcs3/Emu/SysCalls/CB_FUNC.h | 4 +- rpcs3/Emu/SysCalls/Callback.cpp | 32 ++++++++++---- rpcs3/Emu/SysCalls/Callback.h | 5 ++- rpcs3/Emu/SysCalls/Modules/cellAdec.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/cellDmux.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/cellGame.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp | 17 ++++++-- rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp | 1 + rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp | 4 +- rpcs3/Emu/SysCalls/Modules/cellSync.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp | 1 + rpcs3/Emu/SysCalls/Modules/cellVdec.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/libmixer.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp | 2 +- rpcs3/Emu/SysCalls/Modules/sys_fs.cpp | 1 + rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp | 2 +- rpcs3/Emu/System.cpp | 1 + 24 files changed, 102 insertions(+), 38 deletions(-) diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.h b/rpcs3/Emu/ARMv7/ARMv7Thread.h index d80d5c9669..a7a12fb98b 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.h +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.h @@ -123,6 +123,7 @@ public: virtual void InitRegs(); virtual void InitStack(); u32 GetStackArg(u32 pos); + virtual void DoRun(); public: virtual std::string RegsToString(); @@ -131,7 +132,6 @@ public: protected: virtual void DoReset(); - virtual void DoRun(); virtual void DoPause(); virtual void DoResume(); virtual void DoStop(); diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp index 529a0bdc42..18a29f85eb 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp @@ -1,10 +1,14 @@ #include "stdafx.h" #include "Emu/System.h" #include "Emu/Memory/Memory.h" +#include "Emu/CPU/CPUThreadManager.h" +#include "Emu/ARMv7/ARMv7Thread.h" #include "Emu/ARMv7/PSVFuncList.h" extern psv_log_base sceLibKernel; +#define RETURN_ERROR(code) { Emu.Pause(); sceLibKernel.Error("%s() failed: %s", __FUNCTION__, #code); return code; } + #pragma pack(push, 4) typedef s32(*SceKernelThreadEntry)(u32 argSize, vm::psv::ptr pArgBlock); @@ -80,7 +84,7 @@ struct SceKernelSystemInfo } cpuInfo[4]; }; -#pragma pack(pop, 4) +#pragma pack(pop) s32 sceKernelCreateThread( vm::psv::ptr pName, @@ -91,16 +95,48 @@ s32 sceKernelCreateThread( s32 cpuAffinityMask, vm::psv::ptr pOptParam) { - sceLibKernel.Todo("sceKernelCreateThread(pName_addr=0x%x ('%s'), entry_addr=0x%x, initPriority=%d, stackSize=0x%x, attr=0x%x, cpuAffinityMask=0x%x, pOptParam_addr=0x%x)", + sceLibKernel.Error("sceKernelCreateThread(pName_addr=0x%x ('%s'), entry_addr=0x%x, initPriority=%d, stackSize=0x%x, attr=0x%x, cpuAffinityMask=0x%x, pOptParam_addr=0x%x)", pName.addr(), pName.get_ptr(), entry.addr(), initPriority, stackSize, attr, cpuAffinityMask, pOptParam.addr()); - return SCE_OK; + std::string name = pName.get_ptr(); + + ARMv7Thread& new_thread = *(ARMv7Thread*)&Emu.GetCPU().AddThread(CPU_THREAD_ARMv7); + + u32 id = new_thread.GetId(); + new_thread.SetEntry(entry.addr() ^ 1); + new_thread.SetPrio(initPriority); + new_thread.SetStackSize(stackSize); + new_thread.SetName(name); + + sceLibKernel.Error("*** New ARMv7 Thread [%s] (entry=0x%x): id = %d", name.c_str(), entry, id); + + new_thread.Run(); + + Emu.Pause(); + + return id; } s32 sceKernelStartThread(s32 threadId, u32 argSize, vm::psv::ptr pArgBlock) { - sceLibKernel.Todo("sceKernelStartThread(threadId=%d, argSize=%d, pArgBlock_addr=0x%x)", threadId, argSize, pArgBlock.addr()); + sceLibKernel.Error("sceKernelStartThread(threadId=%d, argSize=%d, pArgBlock_addr=0x%x)", threadId, argSize, pArgBlock.addr()); + CPUThread* t = Emu.GetCPU().GetThread(threadId); + + if (!t || t->GetType() != CPU_THREAD_ARMv7) + { + RETURN_ERROR(SCE_KERNEL_ERROR_INVALID_UID); + } + + // push arg block onto the stack + u32 pos = (static_cast(t)->SP -= argSize); + memcpy(vm::get_ptr(pos), pArgBlock.get_ptr(), argSize); + + // set SceKernelThreadEntry function arguments + static_cast(t)->write_gpr(0, argSize); + static_cast(t)->write_gpr(1, pos); + + t->Exec(); return SCE_OK; } diff --git a/rpcs3/Emu/Memory/vm_ptr.h b/rpcs3/Emu/Memory/vm_ptr.h index 7a956f9e4d..38988ce35a 100644 --- a/rpcs3/Emu/Memory/vm_ptr.h +++ b/rpcs3/Emu/Memory/vm_ptr.h @@ -1,6 +1,6 @@ #pragma once -class PPUThread; +class CPUThread; namespace vm { @@ -321,9 +321,9 @@ namespace vm public: typedef RT(*type)(T...); - RT call(PPUThread& CPU, T... args) const; // call using specified PPU thread context, defined in Callback.h (CB_FUNC.h) + RT call(CPUThread& CPU, T... args) const; // call using specified CPU thread context, defined in CB_FUNC.h - RT operator()(T... args) const; // call using current PPU thread context, defined in Callback.h (CB_FUNC.h) + RT operator()(T... args) const; // call using current CPU thread context, defined in CB_FUNC.h AT addr() const { diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 7bfc5daa6c..9d5c60a3df 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -7,6 +7,7 @@ #include "RSXThread.h" #include "Emu/SysCalls/Callback.h" +#include "Emu/SysCalls/CB_FUNC.h" #include "Emu/SysCalls/lv2/sys_time.h" #define ARGS(x) (x >= count ? OutOfArgsCount(x, cmd, count, args.addr()) : args[x].ToLE()) diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 2ad4dfe254..d38b45fec1 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -3,7 +3,6 @@ #include "RSXTexture.h" #include "RSXVertexProgram.h" #include "RSXFragmentProgram.h" -#include "Emu/SysCalls/Callback.h" #include #include "Utilities/SSemaphore.h" diff --git a/rpcs3/Emu/SysCalls/CB_FUNC.h b/rpcs3/Emu/SysCalls/CB_FUNC.h index 6d3ab37f40..35588da48a 100644 --- a/rpcs3/Emu/SysCalls/CB_FUNC.h +++ b/rpcs3/Emu/SysCalls/CB_FUNC.h @@ -165,12 +165,12 @@ namespace cb_detail namespace vm { template - __forceinline RT _ptr_base::call(PPUThread& CPU, T... args) const + __forceinline RT _ptr_base::call(CPUThread& CPU, T... args) const { const u32 pc = vm::get_ref>(m_addr); const u32 rtoc = vm::get_ref>(m_addr + 4); - return cb_detail::_func_caller::call(CPU, pc, rtoc, args...); + return cb_detail::_func_caller::call(static_cast(CPU), pc, rtoc, args...); } template diff --git a/rpcs3/Emu/SysCalls/Callback.cpp b/rpcs3/Emu/SysCalls/Callback.cpp index 310316a6cd..71fa8ba830 100644 --- a/rpcs3/Emu/SysCalls/Callback.cpp +++ b/rpcs3/Emu/SysCalls/Callback.cpp @@ -1,10 +1,10 @@ #include "stdafx.h" #include "Utilities/Log.h" #include "Emu/Memory/Memory.h" -#include "ErrorCodes.h" #include "Emu/System.h" #include "Emu/CPU/CPUThreadManager.h" #include "Emu/Cell/PPUThread.h" +#include "Emu/ARMv7/ARMv7Thread.h" #include "Callback.h" void CallbackManager::Register(const std::function& func) @@ -51,14 +51,28 @@ void CallbackManager::Init() { std::lock_guard lock(m_mutex); - m_cb_thread = (PPUThread*)&Emu.GetCPU().AddThread(CPU_THREAD_PPU); - m_cb_thread->SetName("Callback Thread"); - m_cb_thread->SetEntry(0); - m_cb_thread->SetPrio(1001); - m_cb_thread->SetStackSize(0x10000); - m_cb_thread->InitStack(); - m_cb_thread->InitRegs(); - m_cb_thread->DoRun(); + if (Memory.PSV.RAM.GetStartAddr()) + { + m_cb_thread = &Emu.GetCPU().AddThread(CPU_THREAD_ARMv7); + m_cb_thread->SetName("Callback Thread"); + m_cb_thread->SetEntry(0); + m_cb_thread->SetPrio(1001); + m_cb_thread->SetStackSize(0x10000); + m_cb_thread->InitStack(); + m_cb_thread->InitRegs(); + static_cast(m_cb_thread)->DoRun(); + } + else + { + m_cb_thread = &Emu.GetCPU().AddThread(CPU_THREAD_PPU); + m_cb_thread->SetName("Callback Thread"); + m_cb_thread->SetEntry(0); + m_cb_thread->SetPrio(1001); + m_cb_thread->SetStackSize(0x10000); + m_cb_thread->InitStack(); + m_cb_thread->InitRegs(); + static_cast(m_cb_thread)->DoRun(); + } thread cb_async_thread("CallbackManager::Async() thread", [this]() { diff --git a/rpcs3/Emu/SysCalls/Callback.h b/rpcs3/Emu/SysCalls/Callback.h index 7f5f00a3b7..ba16b38830 100644 --- a/rpcs3/Emu/SysCalls/Callback.h +++ b/rpcs3/Emu/SysCalls/Callback.h @@ -1,11 +1,12 @@ #pragma once -#include "CB_FUNC.h" + +class CPUThread; class CallbackManager { std::vector> m_cb_list; std::vector> m_async_list; - PPUThread* m_cb_thread; + CPUThread* m_cb_thread; std::mutex m_mutex; public: diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index e23461cda8..dd415ddb0a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -2,7 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" -#include "Emu/SysCalls/Callback.h" +#include "Emu/SysCalls/CB_FUNC.h" extern std::mutex g_mutex_avcodec_open2; diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index 116169406e..3aa36b77c4 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -2,7 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" -#include "Emu/SysCalls/Callback.h" +#include "Emu/SysCalls/CB_FUNC.h" #include "Emu/CPU/CPUThreadManager.h" #include "cellPamf.h" diff --git a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp index 2e320f6a49..07264be69a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp @@ -2,7 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" -#include "Emu/SysCalls/Callback.h" +#include "Emu/SysCalls/CB_FUNC.h" #include "Utilities/rMsgBox.h" #include "Emu/FS/VFS.h" diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index 9b61ce5ce3..1c47579895 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -2,6 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" +#include "Emu/SysCalls/CB_FUNC.h" #include "sysPrxForUser.h" //#include "Emu/RSX/GCM.h" @@ -288,9 +289,11 @@ int cellGcmGetConfiguration(vm::ptr config) int cellGcmGetFlipStatus() { - cellGcmSys->Log("cellGcmGetFlipStatus()"); + int status = Emu.GetGSManager().GetRender().m_flip_status; - return Emu.GetGSManager().GetRender().m_flip_status; + cellGcmSys->Log("cellGcmGetFlipStatus() -> %d", status); + + return status; } u32 cellGcmGetTiledPitchSize(u32 size) @@ -498,10 +501,16 @@ s32 cellGcmSetPrepareFlip(vm::ptr ctxt, u32 id) GSLockCurrent gslock(GS_LOCK_WAIT_FLUSH); u32 current = ctxt->current; - u32 end = ctxt->end; - if(current + 8 >= end) + if (current + 8 == ctxt->begin) { + cellGcmSys->Error("cellGcmSetPrepareFlip : queue is full"); + return CELL_GCM_ERROR_FAILURE; + } + + if (current + 8 >= ctxt->end) + { + cellGcmSys->Error("Bad flip!"); if (s32 res = ctxt->callback(ctxt, 8 /* ??? */)) { cellGcmSys->Error("cellGcmSetPrepareFlip : callback failed (0x%08x)", res); diff --git a/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp b/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp index 9ba08b4753..bbda084de9 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellMsgDialog.cpp @@ -3,6 +3,7 @@ #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Callback.h" +#include "Emu/SysCalls/CB_FUNC.h" #include "Utilities/Log.h" #include "Utilities/rMsgBox.h" diff --git a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp index e5796c775a..de2d5307a3 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSaveData.cpp @@ -2,7 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" -#include "Emu/SysCalls/Callback.h" +#include "Emu/SysCalls/CB_FUNC.h" #include "Emu/FS/VFS.h" #include "Emu/FS/vfsFile.h" diff --git a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp index 9a293f5476..a74cebba53 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSpurs.cpp @@ -2,7 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" -#include "Emu/SysCalls/Callback.h" +#include "Emu/SysCalls/CB_FUNC.h" #include "Emu/Cell/SPUThread.h" #include "Emu/SysCalls/lv2/sys_ppu_thread.h" @@ -953,7 +953,7 @@ s64 cellSpursAttributeEnableSystemWorkload(vm::ptr attr, vm: s64 cellSpursFinalize(vm::ptr spurs) { - cellSpurs->Warning("cellSpursFinalize(spurs_addr=0x%x)", spurs.addr()); + cellSpurs->Todo("cellSpursFinalize(spurs_addr=0x%x)", spurs.addr()); #ifdef PRX_DEBUG_XXX return GetCurrentPPUThread().FastCall2(libsre + 0x8568, libsre_rtoc); #endif diff --git a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp index e77004872a..6bc6afcca6 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSync.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSync.cpp @@ -2,7 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" -#include "Emu/SysCalls/Callback.h" +#include "Emu/SysCalls/CB_FUNC.h" #include "Emu/SysCalls/lv2/sys_process.h" #include "Emu/Event.h" diff --git a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp index 2c4271e8ff..aa7458e940 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellSysutil.cpp @@ -4,6 +4,7 @@ #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Callback.h" +#include "Emu/SysCalls/CB_FUNC.h" #include "Emu/DbgCommand.h" #include "rpcs3/Ini.h" diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index 55f4b9c2ec..12b28591c8 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -2,7 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" -#include "Emu/SysCalls/Callback.h" +#include "Emu/SysCalls/CB_FUNC.h" std::mutex g_mutex_avcodec_open2; diff --git a/rpcs3/Emu/SysCalls/Modules/libmixer.cpp b/rpcs3/Emu/SysCalls/Modules/libmixer.cpp index 76fae67e3f..bd7527c5cf 100644 --- a/rpcs3/Emu/SysCalls/Modules/libmixer.cpp +++ b/rpcs3/Emu/SysCalls/Modules/libmixer.cpp @@ -2,7 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" -#include "Emu/SysCalls/Callback.h" +#include "Emu/SysCalls/CB_FUNC.h" #include "Emu/CPU/CPUThreadManager.h" #include "Emu/Audio/cellAudio.h" diff --git a/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp b/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp index 375a830aa3..a145f5556b 100644 --- a/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sceNpTrophy.cpp @@ -2,7 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" -#include "Emu/SysCalls/Callback.h" +#include "Emu/SysCalls/CB_FUNC.h" #include "rpcs3/Ini.h" #include "Utilities/rXml.h" diff --git a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp index 78c7054e82..3c3caf9b7f 100644 --- a/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sysPrxForUser.cpp @@ -2,7 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" -#include "Emu/SysCalls/Callback.h" +#include "Emu/SysCalls/CB_FUNC.h" #include "Emu/FS/vfsFile.h" #include "Emu/SysCalls/lv2/sys_spu.h" diff --git a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp index 8cbefa8055..46e255925d 100644 --- a/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp +++ b/rpcs3/Emu/SysCalls/Modules/sys_fs.cpp @@ -3,6 +3,7 @@ #include "Emu/System.h" #include "Emu/SysCalls/Modules.h" #include "Emu/SysCalls/Callback.h" +#include "Emu/SysCalls/CB_FUNC.h" #include "Emu/FS/VFS.h" #include "Emu/FS/vfsFileBase.h" diff --git a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp index fb7772db2e..0b08bb7055 100644 --- a/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp +++ b/rpcs3/Emu/SysCalls/lv2/sys_ppu_thread.cpp @@ -2,7 +2,7 @@ #include "Emu/Memory/Memory.h" #include "Emu/System.h" #include "Emu/SysCalls/SysCalls.h" -#include "Emu/SysCalls/Callback.h" +#include "Emu/SysCalls/CB_FUNC.h" #include "Emu/Memory/atomic_type.h" #include "Emu/CPU/CPUThreadManager.h" diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index e6c3ff9e3f..4d9e63baf0 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -15,6 +15,7 @@ #include "Emu/DbgCommand.h" #include "Emu/CPU/CPUThreadManager.h" +#include "Emu/SysCalls/Callback.h" #include "Emu/IdManager.h" #include "Emu/Io/Pad.h" #include "Emu/Io/Keyboard.h" From 936aeed0a5c8b8e205f74c0df72d2e9a2c853b21 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Fri, 28 Nov 2014 21:56:16 +0300 Subject: [PATCH 04/10] SPU loader fix --- rpcs3/Loader/ELF32.cpp | 15 +++++++++++++-- rpcs3/Loader/ELF32.h | 6 +++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index 377ab7f5ae..3e68915494 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -86,7 +86,16 @@ namespace loader { case MACHINE_MIPS: break; case MACHINE_ARM: arm7_thread(m_ehdr.is_le() ? m_ehdr.data_le.e_entry : m_ehdr.data_be.e_entry, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); break; - case MACHINE_SPU: spu_thread(m_ehdr.is_le() ? m_ehdr.data_le.e_entry : m_ehdr.data_be.e_entry, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); break; + case MACHINE_SPU: + { + if (!Emu.IsStopped()) + { + break; + } + + spu_thread(m_ehdr.is_le() ? m_ehdr.data_le.e_entry : m_ehdr.data_be.e_entry, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); + break; + } } return ok; @@ -94,6 +103,8 @@ namespace loader handler::error_code elf32::load_data(u32 offset) { + Elf_Machine machine = (Elf_Machine)(u16)(m_ehdr.is_le() ? m_ehdr.data_le.e_machine : m_ehdr.data_be.e_machine); + for (auto &phdr : m_phdrs) { u32 memsz = m_ehdr.is_le() ? phdr.data_le.p_memsz : phdr.data_be.p_memsz; @@ -106,7 +117,7 @@ namespace loader case 0x00000001: //LOAD if (phdr.data_le.p_memsz) { - if (!vm::alloc(vaddr, memsz, vm::main)) + if (machine != MACHINE_SPU && !vm::alloc(vaddr, memsz, vm::main)) { LOG_ERROR(LOADER, "%s(): AllocFixed(0x%llx, 0x%x) failed", __FUNCTION__, vaddr, memsz); diff --git a/rpcs3/Loader/ELF32.h b/rpcs3/Loader/ELF32.h index dc37dd5f0b..d3d37f543c 100644 --- a/rpcs3/Loader/ELF32.h +++ b/rpcs3/Loader/ELF32.h @@ -27,7 +27,7 @@ namespace loader u16 e_type; u16 e_machine; u32 e_version; - u16 e_entry; + u32 e_entry; u32 e_phoff; u32 e_shoff; u32 e_flags; @@ -45,7 +45,7 @@ namespace loader be_t e_type; be_t e_machine; be_t e_version; - be_t e_entry; + be_t e_entry; be_t e_phoff; be_t e_shoff; be_t e_flags; @@ -59,7 +59,7 @@ namespace loader }; bool is_le() const { return e_data == 1; } - bool check() const { return e_magic == 0x7F454C46; } + bool check() const { return e_magic == 0x464C457F; } }; struct shdr From 9fc7197c4fa51d01af0485dc4179c1e169882849 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 29 Nov 2014 20:41:18 +0300 Subject: [PATCH 05/10] cellGameContentPermit: extremely DANGEROUS bug fixed And few tiny changes. --- rpcs3/Emu/ARMv7/ARMv7Thread.cpp | 29 +++++++++++++++++++++++- rpcs3/Emu/ARMv7/ARMv7Thread.h | 2 ++ rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp | 7 ++++-- rpcs3/Emu/ARMv7/PSVFuncList.cpp | 20 ++++++++++++---- rpcs3/Emu/Cell/PPUInterpreter.h | 12 +++++----- rpcs3/Emu/Cell/PPUThread.cpp | 4 ++-- rpcs3/Emu/Cell/SPURecompiler.h | 7 ++---- rpcs3/Emu/SysCalls/Modules/cellGame.cpp | 3 +-- rpcs3/Loader/ELF32.cpp | 13 ++--------- 9 files changed, 64 insertions(+), 33 deletions(-) diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp index 8c57c78485..7f98249d9d 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp @@ -102,6 +102,33 @@ void ARMv7Thread::DoCode() { } +void ARMv7Thread::FastCall(u32 addr) +{ + auto old_status = m_status; + auto old_PC = PC; + auto old_stack = SP; + auto old_LR = LR; + auto old_thread = GetCurrentNamedThread(); + + m_status = Running; + PC = addr; + LR = Emu.m_cpu_thr_stop; + SetCurrentNamedThread(this); + + CPUThread::Task(); + + m_status = old_status; + PC = old_PC; + SP = old_stack; + LR = old_LR; + SetCurrentNamedThread(old_thread); +} + +void ARMv7Thread::FastStop() +{ + m_status = Stopped; +} + arm7_thread::arm7_thread(u32 entry, const std::string& name, u32 stack_size, u32 prio) { thread = &Emu.GetCPU().AddThread(CPU_THREAD_ARMv7); @@ -112,4 +139,4 @@ arm7_thread::arm7_thread(u32 entry, const std::string& name, u32 stack_size, u32 thread->SetPrio(prio ? prio : Emu.GetInfo().GetProcParam().primary_prio); argc = 0; -} \ No newline at end of file +} diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.h b/rpcs3/Emu/ARMv7/ARMv7Thread.h index 1eeefff09c..8737454857 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.h +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.h @@ -123,6 +123,8 @@ public: virtual void InitRegs(); virtual void InitStack(); u32 GetStackArg(u32 pos); + void FastCall(u32 addr); + void FastStop(); virtual void DoRun(); public: diff --git a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp index 18a29f85eb..151d12ae21 100644 --- a/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp +++ b/rpcs3/Emu/ARMv7/Modules/sceLibKernel.cpp @@ -140,9 +140,12 @@ s32 sceKernelStartThread(s32 threadId, u32 argSize, vm::psv::ptr pAr return SCE_OK; } -s32 sceKernelExitThread(s32 exitStatus) +s32 sceKernelExitThread(ARMv7Thread& CPU, s32 exitStatus) { - sceLibKernel.Todo("sceKernelExitThread(exitStatus=0x%x)", exitStatus); + sceLibKernel.Error("sceKernelExitThread(exitStatus=0x%x)", exitStatus); + + // exit status is stored in r0 + CPU.Stop(); return SCE_OK; } diff --git a/rpcs3/Emu/ARMv7/PSVFuncList.cpp b/rpcs3/Emu/ARMv7/PSVFuncList.cpp index bde15b0dc9..5f644a6d10 100644 --- a/rpcs3/Emu/ARMv7/PSVFuncList.cpp +++ b/rpcs3/Emu/ARMv7/PSVFuncList.cpp @@ -6,20 +6,32 @@ std::vector g_psv_func_list = []() -> std::vector { std::vector v; - psv_func f = + psv_func unimplemented = { - 0xdeadbeef, + 0x00000000, // must not be a valid id "INVALID FUNCTION", new psv_func_detail::func_binder([]() -> u32 { - LOG_ERROR(HLE, "Unimplemented function found"); + LOG_ERROR(HLE, "Unimplemented function executed"); Emu.Pause(); return 0xffffffffu; }), nullptr, }; - v.push_back(f); + v.push_back(unimplemented); + + psv_func hle_return = + { + 0x00000001, // must not be a valid id + "INVALID FUNCTION", + new psv_func_detail::func_binder([](ARMv7Thread& CPU) + { + CPU.FastStop(); + }), + nullptr, + }; + v.push_back(hle_return); return v; }(); diff --git a/rpcs3/Emu/Cell/PPUInterpreter.h b/rpcs3/Emu/Cell/PPUInterpreter.h index c24509ea0f..85f86ef76c 100644 --- a/rpcs3/Emu/Cell/PPUInterpreter.h +++ b/rpcs3/Emu/Cell/PPUInterpreter.h @@ -1840,15 +1840,15 @@ private: { for (uint b = 0; b < 16; b++) { - s16 result = (s16)CPU.VPR[va]._u8[b] - (s16)CPU.VPR[vb]._u8[b]; + s16 result = (s16)CPU.VPR[va]._u8[b] - (s16)CPU.VPR[vb]._u8[b]; - if (result < 0) - { + if (result < 0) + { CPU.VPR[vd]._u8[b] = 0; CPU.VSCR.SAT = 1; - } - else - CPU.VPR[vd]._u8[b] = (u8)result; + } + else + CPU.VPR[vd]._u8[b] = (u8)result; } } void VSUBUHM(u32 vd, u32 va, u32 vb) diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 06b2c8b926..c9703c10ce 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -202,7 +202,7 @@ u64 PPUThread::FastCall2(u32 addr, u32 rtoc) m_status = Running; PC = addr; GPR[2] = rtoc; - LR = Emu.m_ppu_thr_stop; + LR = Emu.m_cpu_thr_stop; SetCurrentNamedThread(this); CPUThread::Task(); @@ -288,4 +288,4 @@ ppu_thread& ppu_thread::gpr(uint index, u64 value) static_cast(thread)->GPR[index] = value; return *this; -} \ No newline at end of file +} diff --git a/rpcs3/Emu/Cell/SPURecompiler.h b/rpcs3/Emu/Cell/SPURecompiler.h index 437ebbcd97..1b977a6e52 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.h +++ b/rpcs3/Emu/Cell/SPURecompiler.h @@ -1715,13 +1715,10 @@ private: } else { + // rotate left const XmmLink& va = XmmGet(ra, rt); - const XmmLink& v1 = XmmCopy(va); - c.pslldq(va.get(), s); - c.psrldq(v1.get(), 16 - s); - c.por(va.get(), v1.get()); + c.palignr(va.get(), va.get(), 16 - s); XmmFinalize(va, rt); - XmmFinalize(v1); } LOG_OPCODE(); } diff --git a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp index e480edc50f..3a11eedc17 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGame.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGame.cpp @@ -181,9 +181,8 @@ int cellGameContentPermit(vm::ptr contentInfoPath, vm: cellGame->Warning("cellGameContentPermit(contentInfoPath_addr=0x%x, usrdirPath_addr=0x%x)", contentInfoPath.addr(), usrdirPath.addr()); - if (!contentInfoPath && !usrdirPath) + if (!contentInfoPath || !usrdirPath) { - cellGame->Warning("cellGameContentPermit(): CELL_GAME_ERROR_PARAM"); return CELL_GAME_ERROR_PARAM; } diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index 3e68915494..fb83221f96 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -86,16 +86,7 @@ namespace loader { case MACHINE_MIPS: break; case MACHINE_ARM: arm7_thread(m_ehdr.is_le() ? m_ehdr.data_le.e_entry : m_ehdr.data_be.e_entry, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); break; - case MACHINE_SPU: - { - if (!Emu.IsStopped()) - { - break; - } - - spu_thread(m_ehdr.is_le() ? m_ehdr.data_le.e_entry : m_ehdr.data_be.e_entry, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); - break; - } + case MACHINE_SPU: spu_thread(m_ehdr.is_le() ? m_ehdr.data_le.e_entry : m_ehdr.data_be.e_entry, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); break; } return ok; @@ -117,7 +108,7 @@ namespace loader case 0x00000001: //LOAD if (phdr.data_le.p_memsz) { - if (machine != MACHINE_SPU && !vm::alloc(vaddr, memsz, vm::main)) + if ((machine != MACHINE_SPU || Emu.IsStopped()) && !vm::alloc(vaddr, memsz, vm::main)) { LOG_ERROR(LOADER, "%s(): AllocFixed(0x%llx, 0x%x) failed", __FUNCTION__, vaddr, memsz); From fd7a0950a78beb9169d3a995e62bf030e6933b75 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sun, 30 Nov 2014 15:08:23 +0300 Subject: [PATCH 06/10] Compilation fix --- rpcs3/Emu/System.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 63469f3467..36d8dd4011 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -113,7 +113,7 @@ public: std::string m_path; std::string m_elf_path; std::string m_title_id; - u32 m_ppu_thr_stop; + u32 m_cpu_thr_stop; s32 m_sdk_version; Emulator(); @@ -168,7 +168,7 @@ public: void SetPPUThreadStop(u32 addr) { - m_ppu_thr_stop = addr; + m_cpu_thr_stop = addr; } EmuInfo& GetInfo() { return m_info; } From 1568930da6476354c4f5df24c4dacf29d623de8d Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sun, 30 Nov 2014 22:23:51 +0300 Subject: [PATCH 07/10] /dev_bdvd/ and /app_home/ fixed --- rpcs3/Emu/FS/VFS.cpp | 4 ++-- rpcs3/Emu/RSX/GCM.h | 8 ++++--- rpcs3/Emu/RSX/RSXThread.cpp | 28 +++++++++++------------ rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp | 21 +++++++++++++---- rpcs3/Gui/RSXDebugger.cpp | 4 ++-- 5 files changed, 40 insertions(+), 25 deletions(-) diff --git a/rpcs3/Emu/FS/VFS.cpp b/rpcs3/Emu/FS/VFS.cpp index f36c39c045..d963d9c91f 100644 --- a/rpcs3/Emu/FS/VFS.cpp +++ b/rpcs3/Emu/FS/VFS.cpp @@ -422,7 +422,7 @@ void VFS::Init(const std::string& path) Mount(entry.mount, mpath, dev); } - Link("/app_home/", cwd); + Link("/app_home/", "/host_root/" + cwd); } void VFS::SaveLoadDevices(std::vector& res, bool is_load) @@ -442,7 +442,7 @@ void VFS::SaveLoadDevices(std::vector& res, bool is_load) res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_flash/", "/dev_flash/"); res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_usb000/", "/dev_usb000/"); res.emplace_back(vfsDevice_LocalFile, "$(EmulatorDir)/dev_usb000/", "/dev_usb/"); - res.emplace_back(vfsDevice_LocalFile, "$(GameDir)/../", "/dev_bdvd/"); + res.emplace_back(vfsDevice_LocalFile, "$(GameDir)/../../", "/dev_bdvd/"); res.emplace_back(vfsDevice_LocalFile, "", "/host_root/"); return; diff --git a/rpcs3/Emu/RSX/GCM.h b/rpcs3/Emu/RSX/GCM.h index e19e792652..7b216aa87f 100644 --- a/rpcs3/Emu/RSX/GCM.h +++ b/rpcs3/Emu/RSX/GCM.h @@ -1,5 +1,7 @@ #pragma once +#include "Emu/Memory/atomic_type.h" + enum { CELL_GCM_DISPLAY_HSYNC = 1, @@ -201,9 +203,9 @@ enum struct CellGcmControl { - be_t put; - be_t get; - be_t ref; + atomic_t put; + atomic_t get; + atomic_t ref; }; struct CellGcmConfig diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index ca9b35cca0..de0ff1aa8f 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -259,7 +259,7 @@ void RSXThread::DoCmd(const u32 fcmd, const u32 cmd, const u32 args_addr, const // NV406E case NV406E_SET_REFERENCE: { - m_ctrl->ref = ARGS(0); + m_ctrl->ref.exchange(be_t::make(ARGS(0))); } break; @@ -2204,14 +2204,8 @@ void RSXThread::Task() inc=1; - u32 put, get; - // this code produces only mov + bswap: - put = se_t::func(std::atomic_load((volatile std::atomic*)((u8*)m_ctrl + offsetof(CellGcmControl, put)))); - get = se_t::func(std::atomic_load((volatile std::atomic*)((u8*)m_ctrl + offsetof(CellGcmControl, get)))); - /* - se_t::func(put, InterlockedCompareExchange((volatile unsigned long*)((u8*)m_ctrl + offsetof(CellGcmControl, put)), 0, 0)); - se_t::func(get, InterlockedCompareExchange((volatile unsigned long*)((u8*)m_ctrl + offsetof(CellGcmControl, get)), 0, 0)); - */ + u32 get = m_ctrl->get.read_sync(); + u32 put = m_ctrl->put.read_sync(); if(put == get || !Emu.IsRunning()) { @@ -2241,7 +2235,7 @@ void RSXThread::Task() { u32 addr = cmd & ~(CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_NON_INCREMENT); //LOG_WARNING(RSX, "rsx jump(0x%x) #addr=0x%x, cmd=0x%x, get=0x%x, put=0x%x", addr, m_ioAddress + get, cmd, get, put); - m_ctrl->get = addr; + m_ctrl->get.exchange(be_t::make(addr)); continue; } if(cmd & CELL_GCM_METHOD_FLAG_CALL) @@ -2250,7 +2244,7 @@ void RSXThread::Task() u32 offs = cmd & ~CELL_GCM_METHOD_FLAG_CALL; //u32 addr = offs; //LOG_WARNING(RSX, "rsx call(0x%x) #0x%x - 0x%x - 0x%x", offs, addr, cmd, get); - m_ctrl->get = offs; + m_ctrl->get.exchange(be_t::make(offs)); continue; } if(cmd == CELL_GCM_METHOD_FLAG_RETURN) @@ -2259,7 +2253,7 @@ void RSXThread::Task() u32 get = m_call_stack.top(); m_call_stack.pop(); //LOG_WARNING(RSX, "rsx return(0x%x)", get); - m_ctrl->get = get; + m_ctrl->get.exchange(be_t::make(get)); continue; } if(cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT) @@ -2273,7 +2267,10 @@ void RSXThread::Task() LOG_ERROR(Log::RSX, "null cmd: cmd=0x%x, put=0x%x, get=0x%x (addr=0x%x)", cmd, put, get, (u32)Memory.RSXIOMem.RealAddr(get)); //Emu.Pause(); //HACK! We shouldn't be here - m_ctrl->get = get + (count + 1) * 4; + m_ctrl->get.atomic_op([](be_t& value) + { + value += 4; + }); continue; } @@ -2286,7 +2283,10 @@ void RSXThread::Task() DoCmd(cmd, cmd & 0x3ffff, args.addr(), count); - m_ctrl->get = get + (count + 1) * 4; + m_ctrl->get.atomic_op([count](be_t& value) + { + value += (count + 1) * 4; + }); //memset(Memory.GetMemFromAddr(p.m_ioAddress + get), 0, (count + 1) * 4); } catch (const std::string& e) diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index bb4146f8b4..5f53b45414 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -380,9 +380,9 @@ s32 _cellGcmInitBody(vm::ptr context, u32 cmdSize, u32 ioSiz vm::write32(context.addr(), gcm_info.context_addr); auto& ctrl = vm::get_ref(gcm_info.control_addr); - ctrl.put = 0; - ctrl.get = 0; - ctrl.ref = -1; + ctrl.put.write_relaxed(be_t::make(0)); + ctrl.get.write_relaxed(be_t::make(0)); + ctrl.ref.write_relaxed(be_t::make(-1)); auto& render = Emu.GetGSManager().GetRender(); render.m_ctxt_addr = context.addr(); @@ -526,7 +526,10 @@ s32 cellGcmSetPrepareFlip(vm::ptr ctxt, u32 id) if(ctxt.addr() == gcm_info.context_addr) { auto& ctrl = vm::get_ref(gcm_info.control_addr); - ctrl.put += 8; + ctrl.put.atomic_op([](be_t& value) + { + value += 8; + }); } return id; @@ -1166,6 +1169,16 @@ int cellGcmSetTile(u8 index, u8 location, u32 offset, u32 size, u32 pitch, u8 co s32 cellGcmCallback(vm::ptr context, u32 count) { cellGcmSys->Log("cellGcmCallback(context_addr=0x%x, count=0x%x)", context.addr(), count); + + auto& ctrl = vm::get_ref(gcm_info.control_addr); + + { + const u32 address = context->current; + const u32 upper = offsetTable.ioAddress[address >> 20]; // 12 bits + assert(upper != 0xFFFF); + u32 offset = (upper << 20) | (address & 0xFFFFF); + //ctrl.put.exchange(be_t::make(offset)); // update put pointer + } // TODO: this may be wrong diff --git a/rpcs3/Gui/RSXDebugger.cpp b/rpcs3/Gui/RSXDebugger.cpp index 85ab9a5672..69a09bc2cb 100644 --- a/rpcs3/Gui/RSXDebugger.cpp +++ b/rpcs3/Gui/RSXDebugger.cpp @@ -332,7 +332,7 @@ void RSXDebugger::GoToGet(wxCommandEvent& event) if (!RSXReady()) return; auto ctrl = vm::get_ptr(Emu.GetGSManager().GetRender().m_ctrlAddress); u64 realAddr; - if (Memory.RSXIOMem.getRealAddr(ctrl->get, realAddr)) { + if (Memory.RSXIOMem.getRealAddr(ctrl->get.read_relaxed(), realAddr)) { m_addr = realAddr; // WARNING: Potential Truncation? Cast from u64 to u32 t_addr->SetValue(wxString::Format("%08x", m_addr)); UpdateInformation(); @@ -346,7 +346,7 @@ void RSXDebugger::GoToPut(wxCommandEvent& event) if (!RSXReady()) return; auto ctrl = vm::get_ptr(Emu.GetGSManager().GetRender().m_ctrlAddress); u64 realAddr; - if (Memory.RSXIOMem.getRealAddr(ctrl->put, realAddr)) { + if (Memory.RSXIOMem.getRealAddr(ctrl->put.read_relaxed(), realAddr)) { m_addr = realAddr; // WARNING: Potential Truncation? Cast from u64 to u32 t_addr->SetValue(wxString::Format("%08x", m_addr)); UpdateInformation(); From 697b699873909ab89ba686215b2068261cc03826 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 1 Dec 2014 01:04:47 +0300 Subject: [PATCH 08/10] Some bugs fixed ARMv7 partially restored --- rpcs3/Emu/ARMv7/ARMv7Thread.cpp | 2 +- rpcs3/Emu/ARMv7/ARMv7Thread.h | 22 +++++++++++----------- rpcs3/Emu/Cell/PPUThread.cpp | 4 ++-- rpcs3/Emu/SysCalls/Modules.cpp | 2 ++ rpcs3/Emu/System.cpp | 6 +++--- rpcs3/Emu/System.h | 13 +++++++------ rpcs3/Loader/ELF32.cpp | 29 +++++++++++++++++++++++++---- rpcs3/Loader/ELF64.cpp | 4 ++-- 8 files changed, 53 insertions(+), 29 deletions(-) diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp index 7f98249d9d..40423d511d 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.cpp +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.cpp @@ -112,7 +112,7 @@ void ARMv7Thread::FastCall(u32 addr) m_status = Running; PC = addr; - LR = Emu.m_cpu_thr_stop; + LR = Emu.GetCPUThreadStop(); SetCurrentNamedThread(this); CPUThread::Task(); diff --git a/rpcs3/Emu/ARMv7/ARMv7Thread.h b/rpcs3/Emu/ARMv7/ARMv7Thread.h index 8737454857..543b19cf0c 100644 --- a/rpcs3/Emu/ARMv7/ARMv7Thread.h +++ b/rpcs3/Emu/ARMv7/ARMv7Thread.h @@ -155,20 +155,20 @@ public: if (!values.size()) return *this; - assert(argc == 0); + //assert(argc == 0); - envp.set(vm::alloc((u32)sizeof(envp), stack_align, vm::main)); - *envp = 0; - argv.set(vm::alloc(u32(sizeof(argv)* values.size()), stack_align, vm::main)); + //envp.set(vm::alloc((u32)sizeof(envp), stack_align, vm::main)); + //*envp = 0; + //argv.set(vm::alloc(u32(sizeof(argv)* values.size()), stack_align, vm::main)); for (auto &arg : values) { - u32 arg_size = align(u32(arg.size() + 1), stack_align); - u32 arg_addr = vm::alloc(arg_size, stack_align, vm::main); + //u32 arg_size = align(u32(arg.size() + 1), stack_align); + //u32 arg_addr = vm::alloc(arg_size, stack_align, vm::main); - std::strcpy(vm::get_ptr(arg_addr), arg.c_str()); + //std::strcpy(vm::get_ptr(arg_addr), arg.c_str()); - argv[argc++] = arg_addr; + //argv[argc++] = arg_addr; } return *this; @@ -178,9 +178,9 @@ public: { thread->Run(); - static_cast(thread)->GPR[3] = argc; - static_cast(thread)->GPR[4] = argv.addr(); - static_cast(thread)->GPR[5] = envp.addr(); + //static_cast(thread)->GPR[0] = argc; + //static_cast(thread)->GPR[1] = argv.addr(); + //static_cast(thread)->GPR[2] = envp.addr(); return *this; } diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index c9703c10ce..0364198974 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -92,7 +92,7 @@ void PPUThread::InitRegs() //GPR[12] = Emu.GetMallocPageSize(); GPR[13] = Memory.PRXMem.GetStartAddr() + 0x7060; - LR = Emu.GetPPUThreadExit(); + LR = Emu.GetCPUThreadExit(); CTR = PC; CR.CR = 0x22000082; VSCR.NJ = 1; @@ -202,7 +202,7 @@ u64 PPUThread::FastCall2(u32 addr, u32 rtoc) m_status = Running; PC = addr; GPR[2] = rtoc; - LR = Emu.m_cpu_thr_stop; + LR = Emu.GetCPUThreadStop(); SetCurrentNamedThread(this); CPUThread::Task(); diff --git a/rpcs3/Emu/SysCalls/Modules.cpp b/rpcs3/Emu/SysCalls/Modules.cpp index c11dcc4f33..26b6931544 100644 --- a/rpcs3/Emu/SysCalls/Modules.cpp +++ b/rpcs3/Emu/SysCalls/Modules.cpp @@ -81,6 +81,8 @@ void Module::Load() { Emu.GetModuleManager().AddFunc(i.second); } + + SetLoaded(true); } void Module::UnLoad() diff --git a/rpcs3/Emu/System.cpp b/rpcs3/Emu/System.cpp index fbd7f542ac..b13e6899df 100644 --- a/rpcs3/Emu/System.cpp +++ b/rpcs3/Emu/System.cpp @@ -203,7 +203,7 @@ void Emulator::Load() } LOG_NOTICE(LOADER, " ");//used to be skip_line - vfsFile sfo("/app_home/PARAM.SFO"); + vfsFile sfo("/app_home/../PARAM.SFO"); PSFLoader psf(sfo); psf.Load(false); std::string title = psf.GetString("TITLE"); @@ -212,7 +212,7 @@ void Emulator::Load() LOG_NOTICE(LOADER, "Serial: %s", title_id.c_str()); // bdvd inserting imitation - vfsFile f1("/app_home/dev_bdvd.path"); + vfsFile f1("/app_home/../dev_bdvd.path"); if (f1.IsOpened()) { std::string bdvd; @@ -246,7 +246,7 @@ void Emulator::Load() } // trying to load some info from PARAM.SFO - vfsFile f2("/app_home/PARAM.SFO"); + vfsFile f2("/app_home/../PARAM.SFO"); if (f2.IsOpened()) { PSFLoader psf(f2); diff --git a/rpcs3/Emu/System.h b/rpcs3/Emu/System.h index 8d47101caa..dd5409cc71 100644 --- a/rpcs3/Emu/System.h +++ b/rpcs3/Emu/System.h @@ -84,7 +84,8 @@ class Emulator uint m_mode; u32 m_rsx_callback; - u32 m_ppu_thr_exit; + u32 m_cpu_thr_exit; + u32 m_cpu_thr_stop; std::vector> m_modules_init; std::vector m_break_points; @@ -114,7 +115,6 @@ public: std::string m_elf_path; std::string m_emu_path; std::string m_title_id; - u32 m_cpu_thr_stop; s32 m_sdk_version; Emulator(); @@ -172,12 +172,12 @@ public: m_rsx_callback = addr; } - void SetPPUThreadExit(u32 addr) + void SetCPUThreadExit(u32 addr) { - m_ppu_thr_exit = addr; + m_cpu_thr_exit = addr; } - void SetPPUThreadStop(u32 addr) + void SetCPUThreadStop(u32 addr) { m_cpu_thr_stop = addr; } @@ -191,7 +191,8 @@ public: u32 GetMallocPageSize() { return m_info.GetProcParam().malloc_pagesize; } u32 GetRSXCallback() const { return m_rsx_callback; } - u32 GetPPUThreadExit() const { return m_ppu_thr_exit; } + u32 GetCPUThreadExit() const { return m_cpu_thr_exit; } + u32 GetCPUThreadStop() const { return m_cpu_thr_stop; } void CheckStatus(); bool BootGame(const std::string& path); diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index fb83221f96..1466d56f52 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -43,6 +43,7 @@ namespace loader m_phdrs.resize(m_ehdr.is_le() ? m_ehdr.data_le.e_phnum : m_ehdr.data_be.e_phnum); m_stream->Seek(handler::get_stream_offset() + (m_ehdr.is_le() ? m_ehdr.data_le.e_phoff : m_ehdr.data_be.e_phoff)); size_t size = (m_ehdr.is_le() ? m_ehdr.data_le.e_phnum : m_ehdr.data_be.e_phnum) * sizeof(phdr); + if (m_stream->Read(m_phdrs.data(), size) != size) return broken_file; } @@ -51,9 +52,9 @@ namespace loader if (m_ehdr.data_le.e_shnum) { - m_phdrs.resize(m_ehdr.is_le() ? m_ehdr.data_le.e_shnum : m_ehdr.data_be.e_shnum); + m_shdrs.resize(m_ehdr.is_le() ? m_ehdr.data_le.e_shnum : m_ehdr.data_be.e_shnum); m_stream->Seek(handler::get_stream_offset() + (m_ehdr.is_le() ? m_ehdr.data_le.e_shoff : m_ehdr.data_be.e_shoff)); - size_t size = (m_ehdr.is_le() ? m_ehdr.data_le.e_phnum : m_ehdr.data_be.e_phnum) * sizeof(phdr); + size_t size = (m_ehdr.is_le() ? m_ehdr.data_le.e_shnum : m_ehdr.data_be.e_shnum) * sizeof(phdr); if (m_stream->Read(m_shdrs.data(), size) != size) return broken_file; @@ -85,7 +86,27 @@ namespace loader switch (machine) { case MACHINE_MIPS: break; - case MACHINE_ARM: arm7_thread(m_ehdr.is_le() ? m_ehdr.data_le.e_entry : m_ehdr.data_be.e_entry, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); break; + case MACHINE_ARM: + { + auto armv7_thr_stop_data = vm::psv::ptr::make(Memory.PSV.RAM.AllocAlign(3 * 4)); + armv7_thr_stop_data[0] = 0xf870; // HACK + armv7_thr_stop_data[1] = 0x0001; // index 1 + Emu.SetCPUThreadExit(armv7_thr_stop_data.addr()); + + u32 entry = m_ehdr.data_le.e_entry + (u32)Memory.PSV.RAM.GetStartAddr(); + + auto code = vm::psv::ptr::make(entry & ~3); + + // very rough way to find entry point in .sceModuleInfo.rodata + while (code[0] != 0xffffffffu) + { + entry = code[0] + 0x81000000; + code++; + } + + arm7_thread(entry & ~1 /* TODO: Thumb/ARM encoding selection */, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); + break; + } case MACHINE_SPU: spu_thread(m_ehdr.is_le() ? m_ehdr.data_le.e_entry : m_ehdr.data_be.e_entry, "main_thread").args({ Emu.GetPath()/*, "-emu"*/ }).run(); break; } @@ -108,7 +129,7 @@ namespace loader case 0x00000001: //LOAD if (phdr.data_le.p_memsz) { - if ((machine != MACHINE_SPU || Emu.IsStopped()) && !vm::alloc(vaddr, memsz, vm::main)) + if (machine == MACHINE_ARM && !Memory.PSV.RAM.AllocFixed(vaddr, memsz)) { LOG_ERROR(LOADER, "%s(): AllocFixed(0x%llx, 0x%x) failed", __FUNCTION__, vaddr, memsz); diff --git a/rpcs3/Loader/ELF64.cpp b/rpcs3/Loader/ELF64.cpp index ea44995c02..09607fc407 100644 --- a/rpcs3/Loader/ELF64.cpp +++ b/rpcs3/Loader/ELF64.cpp @@ -350,12 +350,12 @@ namespace loader ppu_thr_exit_data[0] = ADDI(r11, 0, 41); ppu_thr_exit_data[1] = SC(2); ppu_thr_exit_data[2] = BLR(); - Emu.SetPPUThreadExit(ppu_thr_exit_data.addr()); + Emu.SetCPUThreadExit(ppu_thr_exit_data.addr()); auto ppu_thr_stop_data = vm::ptr::make(Memory.MainMem.AllocAlign(2 * 4)); ppu_thr_stop_data[0] = SC(4); ppu_thr_stop_data[1] = BLR(); - Emu.SetPPUThreadStop(ppu_thr_stop_data.addr()); + Emu.SetCPUThreadStop(ppu_thr_stop_data.addr()); vm::write64(Memory.PRXMem.AllocAlign(0x10000), 0xDEADBEEFABADCAFE); /* From c61fe621b02683035f8b85d32422b5f8a398fac9 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 1 Dec 2014 03:41:01 +0300 Subject: [PATCH 09/10] Memory leak fixed --- rpcs3/Emu/ARMv7/PSVFuncList.cpp | 42 ++++++++++++++------------------- rpcs3/Emu/ARMv7/PSVFuncList.h | 20 +++++++--------- 2 files changed, 27 insertions(+), 35 deletions(-) diff --git a/rpcs3/Emu/ARMv7/PSVFuncList.cpp b/rpcs3/Emu/ARMv7/PSVFuncList.cpp index 5f644a6d10..d9901d8aca 100644 --- a/rpcs3/Emu/ARMv7/PSVFuncList.cpp +++ b/rpcs3/Emu/ARMv7/PSVFuncList.cpp @@ -2,42 +2,36 @@ #include "Emu/System.h" #include "PSVFuncList.h" -std::vector g_psv_func_list = []() -> std::vector -{ - std::vector v; +std::vector g_psv_func_list; - psv_func unimplemented = +void add_psv_func(psv_func& data) +{ + if (!g_psv_func_list.size()) { - 0x00000000, // must not be a valid id - "INVALID FUNCTION", - new psv_func_detail::func_binder([]() -> u32 + psv_func unimplemented; + unimplemented.nid = 0x00000000; // must not be a valid id + unimplemented.name = "INVALID FUNCTION (0x0)"; + unimplemented.func.reset(new psv_func_detail::func_binder([]() -> u32 { LOG_ERROR(HLE, "Unimplemented function executed"); Emu.Pause(); return 0xffffffffu; - }), - nullptr, - }; - v.push_back(unimplemented); + })); + g_psv_func_list.push_back(unimplemented); - psv_func hle_return = - { - 0x00000001, // must not be a valid id - "INVALID FUNCTION", - new psv_func_detail::func_binder([](ARMv7Thread& CPU) + psv_func hle_return; + hle_return.nid = 0x00000001; // must not be a valid id + hle_return.name = "INVALID FUNCTION (0x1)"; + hle_return.func.reset(new psv_func_detail::func_binder([](ARMv7Thread& CPU) { CPU.FastStop(); - }), - nullptr, - }; - v.push_back(hle_return); - return v; -}(); + return; + })); + g_psv_func_list.push_back(hle_return); + } -void add_psv_func(psv_func& data) -{ g_psv_func_list.push_back(data); } diff --git a/rpcs3/Emu/ARMv7/PSVFuncList.h b/rpcs3/Emu/ARMv7/PSVFuncList.h index 8ae8282104..998225799d 100644 --- a/rpcs3/Emu/ARMv7/PSVFuncList.h +++ b/rpcs3/Emu/ARMv7/PSVFuncList.h @@ -643,10 +643,10 @@ namespace psv_func_detail struct psv_func { - const u32 nid; - const char* const name; - psv_func_caller* const func; - psv_log_base* const module; + u32 nid; + const char* name; + std::shared_ptr func; + psv_log_base* module; }; void add_psv_func(psv_func& data); @@ -654,13 +654,11 @@ void add_psv_func(psv_func& data); template void reg_psv_func(u32 nid, psv_log_base* module, const char* name, RT(*func)(T...)) { - psv_func f = - { - nid, - name, - new psv_func_detail::func_binder(func), - module - }; + psv_func f; + f.nid = nid; + f.name = name; + f.func.reset(new psv_func_detail::func_binder(func)); + f.module = module; add_psv_func(f); } From e4d5e7c78b52e4b2ec6b401f627814f2c06a4a0a Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 1 Dec 2014 19:34:18 +0300 Subject: [PATCH 10/10] Some draft --- rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp | 22 ++++++++++++++++++---- rpcs3/Loader/ELF32.cpp | 3 +++ 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp index 5f53b45414..c867a010c9 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellGcmSys.cpp @@ -1176,14 +1176,28 @@ s32 cellGcmCallback(vm::ptr context, u32 count) const u32 address = context->current; const u32 upper = offsetTable.ioAddress[address >> 20]; // 12 bits assert(upper != 0xFFFF); - u32 offset = (upper << 20) | (address & 0xFFFFF); + const u32 offset = (upper << 20) | (address & 0xFFFFF); //ctrl.put.exchange(be_t::make(offset)); // update put pointer } - - // TODO: this may be wrong - vm::write32(context->current, CELL_GCM_METHOD_FLAG_JUMP | CELL_GCM_METHOD_FLAG_NON_INCREMENT | (0)); // set JUMP cmd + // preparations for changing the place (for optimized FIFO mode) + //auto cmd = vm::ptr::make(context->current.ToLE()); + //cmd[0] = 0x41D6C; + //cmd[1] = 0x20; + //cmd[2] = 0x41D74; + //cmd[3] = 0; // some incrementing by module value + //context->current += 0x10; + + { + const u32 address = context->begin; + const u32 upper = offsetTable.ioAddress[address >> 20]; // 12 bits + assert(upper != 0xFFFF); + const u32 offset = (upper << 20) | (address & 0xFFFFF); + vm::write32(context->current, CELL_GCM_METHOD_FLAG_JUMP | offset); // set JUMP cmd + } + context->current = context->begin; // rewind to the beginning + // TODO: something is missing return CELL_OK; } diff --git a/rpcs3/Loader/ELF32.cpp b/rpcs3/Loader/ELF32.cpp index 1466d56f52..5430dc2ff7 100644 --- a/rpcs3/Loader/ELF32.cpp +++ b/rpcs3/Loader/ELF32.cpp @@ -6,6 +6,7 @@ #include "ELF32.h" #include "Emu/Cell/SPUThread.h" #include "Emu/ARMv7/ARMv7Thread.h" +#include "Emu/ARMv7/PSVFuncList.h" #include "Emu/System.h" namespace loader @@ -88,6 +89,8 @@ namespace loader case MACHINE_MIPS: break; case MACHINE_ARM: { + list_known_psv_modules(); + auto armv7_thr_stop_data = vm::psv::ptr::make(Memory.PSV.RAM.AllocAlign(3 * 4)); armv7_thr_stop_data[0] = 0xf870; // HACK armv7_thr_stop_data[1] = 0x0001; // index 1