mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-02-22 21:40:47 +00:00
Merge pull request #878 from Nekotekina/master
PSV progression, loader fixes
This commit is contained in:
commit
7ba0bda244
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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<typename T> 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<typename T> T Shift_C(T value, SRType type, uint amount, bool carry_in, bool& carry_out)
|
||||
template<typename T> 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<typename T> T Shift(T value, SRType type, u32 amount, bool carry_in)
|
||||
template<typename T> T Shift(T value, SRType type, s32 amount, bool carry_in)
|
||||
{
|
||||
bool carry_out;
|
||||
return Shift_C(value, type, amount, carry_in, carry_out);
|
||||
|
@ -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),
|
||||
|
@ -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.GetCPUThreadStop();
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -123,6 +123,9 @@ public:
|
||||
virtual void InitRegs();
|
||||
virtual void InitStack();
|
||||
u32 GetStackArg(u32 pos);
|
||||
void FastCall(u32 addr);
|
||||
void FastStop();
|
||||
virtual void DoRun();
|
||||
|
||||
public:
|
||||
virtual std::string RegsToString();
|
||||
@ -131,7 +134,6 @@ public:
|
||||
|
||||
protected:
|
||||
virtual void DoReset();
|
||||
virtual void DoRun();
|
||||
virtual void DoPause();
|
||||
virtual void DoResume();
|
||||
virtual void DoStop();
|
||||
@ -153,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<char>(arg_addr), arg.c_str());
|
||||
//std::strcpy(vm::get_ptr<char>(arg_addr), arg.c_str());
|
||||
|
||||
argv[argc++] = arg_addr;
|
||||
//argv[argc++] = arg_addr;
|
||||
}
|
||||
|
||||
return *this;
|
||||
@ -176,10 +178,10 @@ public:
|
||||
{
|
||||
thread->Run();
|
||||
|
||||
static_cast<ARMv7Thread*>(thread)->GPR[3] = argc;
|
||||
static_cast<ARMv7Thread*>(thread)->GPR[4] = argv.addr();
|
||||
static_cast<ARMv7Thread*>(thread)->GPR[5] = envp.addr();
|
||||
//static_cast<ARMv7Thread*>(thread)->GPR[0] = argc;
|
||||
//static_cast<ARMv7Thread*>(thread)->GPR[1] = argv.addr();
|
||||
//static_cast<ARMv7Thread*>(thread)->GPR[2] = envp.addr();
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -1,18 +1,91 @@
|
||||
#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<void> 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<void> 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)
|
||||
|
||||
s32 sceKernelCreateThread(
|
||||
vm::psv::ptr<const char> pName,
|
||||
vm::psv::ptr<SceKernelThreadEntry> entry,
|
||||
@ -22,9 +95,205 @@ s32 sceKernelCreateThread(
|
||||
s32 cpuAffinityMask,
|
||||
vm::psv::ptr<const SceKernelThreadOptParam> pOptParam)
|
||||
{
|
||||
sceLibKernel.Todo("sceKernelCreateThread(pName_addr=0x%x ('%s'), entry_addr=0x%x, initPriority=%d, stackSize=0x%x, attr=0x%x, cpuAffinityMask=0x%x, pOptParam_addr=0x%x)",
|
||||
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());
|
||||
|
||||
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<const void> pArgBlock)
|
||||
{
|
||||
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<ARMv7Thread*>(t)->SP -= argSize);
|
||||
memcpy(vm::get_ptr<void>(pos), pArgBlock.get_ptr(), argSize);
|
||||
|
||||
// set SceKernelThreadEntry function arguments
|
||||
static_cast<ARMv7Thread*>(t)->write_gpr(0, argSize);
|
||||
static_cast<ARMv7Thread*>(t)->write_gpr(1, pos);
|
||||
|
||||
t->Exec();
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
s32 sceKernelExitThread(ARMv7Thread& CPU, s32 exitStatus)
|
||||
{
|
||||
sceLibKernel.Error("sceKernelExitThread(exitStatus=0x%x)", exitStatus);
|
||||
|
||||
// exit status is stored in r0
|
||||
CPU.Stop();
|
||||
|
||||
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<s32> 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<SceKernelThreadInfo> pInfo)
|
||||
{
|
||||
sceLibKernel.Todo("sceKernelGetThreadInfo(threadId=%d, pInfo_addr=0x%x)", threadId, pInfo.addr());
|
||||
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
s32 sceKernelGetThreadRunStatus(vm::psv::ptr<SceKernelThreadRunStatus> pStatus)
|
||||
{
|
||||
sceLibKernel.Todo("sceKernelGetThreadRunStatus(pStatus_addr=0x%x)", pStatus.addr());
|
||||
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
s32 sceKernelGetSystemInfo(vm::psv::ptr<SceKernelSystemInfo> 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<s32> pExitStatus, vm::psv::ptr<u32> 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<s32> pExitStatus, vm::psv::ptr<u32> pTimeout)
|
||||
{
|
||||
sceLibKernel.Todo("sceKernelWaitThreadEndCB(threadId=%d, pExitStatus_addr=0x%x, pTimeout_addr=0x%x)", threadId, pExitStatus.addr(), pTimeout.addr());
|
||||
|
||||
return SCE_OK;
|
||||
}
|
||||
|
||||
@ -145,8 +414,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 +427,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 +649,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);
|
||||
|
@ -44,9 +44,11 @@ namespace sce_libc_func
|
||||
::memcpy(dst.get_ptr(), src.get_ptr(), size);
|
||||
}
|
||||
|
||||
void _Assert()
|
||||
void _Assert(vm::psv::ptr<const char> text, vm::psv::ptr<const char> 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();
|
||||
}
|
||||
}
|
||||
|
@ -2,30 +2,36 @@
|
||||
#include "Emu/System.h"
|
||||
#include "PSVFuncList.h"
|
||||
|
||||
std::vector<psv_func> g_psv_func_list = []() -> std::vector<psv_func>
|
||||
{
|
||||
std::vector<psv_func> v;
|
||||
|
||||
psv_func f =
|
||||
{
|
||||
0xdeadbeef,
|
||||
"INVALID FUNCTION",
|
||||
new psv_func_detail::func_binder<u32>([]() -> u32
|
||||
{
|
||||
LOG_ERROR(HLE, "Unimplemented function found");
|
||||
Emu.Pause();
|
||||
|
||||
return 0xffffffffu;
|
||||
}),
|
||||
nullptr,
|
||||
};
|
||||
v.push_back(f);
|
||||
|
||||
return v;
|
||||
}();
|
||||
std::vector<psv_func> g_psv_func_list;
|
||||
|
||||
void add_psv_func(psv_func& data)
|
||||
{
|
||||
if (!g_psv_func_list.size())
|
||||
{
|
||||
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>([]() -> u32
|
||||
{
|
||||
LOG_ERROR(HLE, "Unimplemented function executed");
|
||||
Emu.Pause();
|
||||
|
||||
return 0xffffffffu;
|
||||
}));
|
||||
g_psv_func_list.push_back(unimplemented);
|
||||
|
||||
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<void, ARMv7Thread&>([](ARMv7Thread& CPU)
|
||||
{
|
||||
CPU.FastStop();
|
||||
|
||||
return;
|
||||
}));
|
||||
g_psv_func_list.push_back(hle_return);
|
||||
}
|
||||
|
||||
g_psv_func_list.push_back(data);
|
||||
}
|
||||
|
||||
|
@ -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<psv_func_caller> func;
|
||||
psv_log_base* module;
|
||||
};
|
||||
|
||||
void add_psv_func(psv_func& data);
|
||||
@ -654,13 +654,11 @@ void add_psv_func(psv_func& data);
|
||||
template<typename RT, typename... T>
|
||||
void reg_psv_func(u32 nid, psv_log_base* module, const char* name, RT(*func)(T...))
|
||||
{
|
||||
psv_func f =
|
||||
{
|
||||
nid,
|
||||
name,
|
||||
new psv_func_detail::func_binder<RT, T...>(func),
|
||||
module
|
||||
};
|
||||
psv_func f;
|
||||
f.nid = nid;
|
||||
f.name = name;
|
||||
f.func.reset(new psv_func_detail::func_binder<RT, T...>(func));
|
||||
f.module = module;
|
||||
|
||||
add_psv_func(f);
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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_ppu_thr_stop;
|
||||
LR = Emu.GetCPUThreadStop();
|
||||
SetCurrentNamedThread(this);
|
||||
|
||||
CPUThread::Task();
|
||||
@ -288,4 +288,4 @@ ppu_thread& ppu_thread::gpr(uint index, u64 value)
|
||||
static_cast<PPUThread*>(thread)->GPR[index] = value;
|
||||
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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<VFSManagerEntry>& res, bool is_load)
|
||||
@ -442,7 +442,7 @@ void VFS::SaveLoadDevices(std::vector<VFSManagerEntry>& 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;
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
class PPUThread;
|
||||
class CPUThread;
|
||||
|
||||
namespace vm
|
||||
{
|
||||
@ -356,9 +356,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
|
||||
{
|
||||
|
@ -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<u32> put;
|
||||
be_t<u32> get;
|
||||
be_t<u32> ref;
|
||||
atomic_t<u32> put;
|
||||
atomic_t<u32> get;
|
||||
atomic_t<u32> ref;
|
||||
};
|
||||
|
||||
struct CellGcmConfig
|
||||
@ -216,12 +218,16 @@ struct CellGcmConfig
|
||||
be_t<u32> coreFrequency;
|
||||
};
|
||||
|
||||
struct CellGcmContextData;
|
||||
|
||||
typedef s32(*CellGcmContextCallback)(vm::ptr<CellGcmContextData>, u32);
|
||||
|
||||
struct CellGcmContextData
|
||||
{
|
||||
be_t<u32> begin;
|
||||
be_t<u32> end;
|
||||
be_t<u32> current;
|
||||
be_t<u32> callback;
|
||||
vm::bptr<CellGcmContextCallback> callback;
|
||||
};
|
||||
|
||||
struct gcmInfo
|
||||
|
@ -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())
|
||||
@ -258,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<u32>::make(ARGS(0)));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -2203,14 +2204,8 @@ void RSXThread::Task()
|
||||
|
||||
inc=1;
|
||||
|
||||
u32 put, get;
|
||||
// this code produces only mov + bswap:
|
||||
put = se_t<u32>::func(std::atomic_load((volatile std::atomic<u32>*)((u8*)m_ctrl + offsetof(CellGcmControl, put))));
|
||||
get = se_t<u32>::func(std::atomic_load((volatile std::atomic<u32>*)((u8*)m_ctrl + offsetof(CellGcmControl, get))));
|
||||
/*
|
||||
se_t<u32>::func(put, InterlockedCompareExchange((volatile unsigned long*)((u8*)m_ctrl + offsetof(CellGcmControl, put)), 0, 0));
|
||||
se_t<u32>::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())
|
||||
{
|
||||
@ -2240,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<u32>::make(addr));
|
||||
continue;
|
||||
}
|
||||
if(cmd & CELL_GCM_METHOD_FLAG_CALL)
|
||||
@ -2249,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<u32>::make(offs));
|
||||
continue;
|
||||
}
|
||||
if(cmd == CELL_GCM_METHOD_FLAG_RETURN)
|
||||
@ -2258,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<u32>::make(get));
|
||||
continue;
|
||||
}
|
||||
if(cmd & CELL_GCM_METHOD_FLAG_NON_INCREMENT)
|
||||
@ -2272,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<u32>& value)
|
||||
{
|
||||
value += 4;
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -2285,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<u32>& value)
|
||||
{
|
||||
value += (count + 1) * 4;
|
||||
});
|
||||
//memset(Memory.GetMemFromAddr(p.m_ioAddress + get), 0, (count + 1) * 4);
|
||||
}
|
||||
catch (const std::string& e)
|
||||
|
@ -3,7 +3,6 @@
|
||||
#include "RSXTexture.h"
|
||||
#include "RSXVertexProgram.h"
|
||||
#include "RSXFragmentProgram.h"
|
||||
#include "Emu/SysCalls/Callback.h"
|
||||
|
||||
#include <stack>
|
||||
#include "Utilities/SSemaphore.h"
|
||||
|
@ -165,12 +165,12 @@ namespace cb_detail
|
||||
namespace vm
|
||||
{
|
||||
template<typename AT, typename RT, typename... T>
|
||||
__forceinline RT _ptr_base<RT(*)(T...), 1, AT>::call(PPUThread& CPU, T... args) const
|
||||
__forceinline RT _ptr_base<RT(*)(T...), 1, AT>::call(CPUThread& CPU, T... args) const
|
||||
{
|
||||
const u32 pc = vm::get_ref<be_t<u32>>(m_addr);
|
||||
const u32 rtoc = vm::get_ref<be_t<u32>>(m_addr + 4);
|
||||
|
||||
return cb_detail::_func_caller<RT, T...>::call(CPU, pc, rtoc, args...);
|
||||
return cb_detail::_func_caller<RT, T...>::call(static_cast<PPUThread&>(CPU), pc, rtoc, args...);
|
||||
}
|
||||
|
||||
template<typename AT, typename RT, typename... T>
|
||||
|
@ -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<s32()>& func)
|
||||
@ -51,14 +51,28 @@ void CallbackManager::Init()
|
||||
{
|
||||
std::lock_guard<std::mutex> 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<ARMv7Thread*>(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<PPUThread*>(m_cb_thread)->DoRun();
|
||||
}
|
||||
|
||||
thread cb_async_thread("CallbackManager::Async() thread", [this]()
|
||||
{
|
||||
|
@ -1,11 +1,12 @@
|
||||
#pragma once
|
||||
#include "CB_FUNC.h"
|
||||
|
||||
class CPUThread;
|
||||
|
||||
class CallbackManager
|
||||
{
|
||||
std::vector<std::function<s32()>> m_cb_list;
|
||||
std::vector<std::function<void()>> m_async_list;
|
||||
PPUThread* m_cb_thread;
|
||||
CPUThread* m_cb_thread;
|
||||
std::mutex m_mutex;
|
||||
|
||||
public:
|
||||
|
@ -81,6 +81,8 @@ void Module::Load()
|
||||
{
|
||||
Emu.GetModuleManager().AddFunc(i.second);
|
||||
}
|
||||
|
||||
SetLoaded(true);
|
||||
}
|
||||
|
||||
void Module::UnLoad()
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
@ -181,9 +181,8 @@ int cellGameContentPermit(vm::ptr<char[CELL_GAME_PATH_MAX]> 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;
|
||||
}
|
||||
|
||||
|
@ -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<CellGcmConfig> 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)
|
||||
@ -368,7 +371,7 @@ s32 _cellGcmInitBody(vm::ptr<CellGcmContextData> 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<u32>::make(Emu.GetRSXCallback() - 4));
|
||||
|
||||
gcm_info.context_addr = (u32)Memory.MainMem.AllocAlign(0x1000);
|
||||
gcm_info.control_addr = gcm_info.context_addr + 0x40;
|
||||
@ -377,9 +380,9 @@ s32 _cellGcmInitBody(vm::ptr<CellGcmContextData> context, u32 cmdSize, u32 ioSiz
|
||||
vm::write32(context.addr(), gcm_info.context_addr);
|
||||
|
||||
auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr);
|
||||
ctrl.put = 0;
|
||||
ctrl.get = 0;
|
||||
ctrl.ref = -1;
|
||||
ctrl.put.write_relaxed(be_t<u32>::make(0));
|
||||
ctrl.get.write_relaxed(be_t<u32>::make(0));
|
||||
ctrl.ref.write_relaxed(be_t<u32>::make(-1));
|
||||
|
||||
auto& render = Emu.GetGSManager().GetRender();
|
||||
render.m_ctxt_addr = context.addr();
|
||||
@ -498,25 +501,21 @@ s32 cellGcmSetPrepareFlip(vm::ptr<CellGcmContextData> 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("bad flip!");
|
||||
//cellGcmCallback(ctxt.addr(), current + 8 - end);
|
||||
//copied:
|
||||
|
||||
auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr);
|
||||
|
||||
const s32 res = ctxt->current - ctxt->begin - ctrl.put;
|
||||
|
||||
memmove(vm::get_ptr<void>(ctxt->begin), vm::get_ptr<void>(ctxt->current - res), res);
|
||||
cellGcmSys->Error("cellGcmSetPrepareFlip : queue is full");
|
||||
return CELL_GCM_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
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 (current + 8 >= ctxt->end)
|
||||
{
|
||||
cellGcmSys->Error("Bad flip!");
|
||||
if (s32 res = ctxt->callback(ctxt, 8 /* ??? */))
|
||||
{
|
||||
cellGcmSys->Error("cellGcmSetPrepareFlip : callback failed (0x%08x)", res);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
current = ctxt->current;
|
||||
@ -527,7 +526,10 @@ s32 cellGcmSetPrepareFlip(vm::ptr<CellGcmContextData> ctxt, u32 id)
|
||||
if(ctxt.addr() == gcm_info.context_addr)
|
||||
{
|
||||
auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr);
|
||||
ctrl.put += 8;
|
||||
ctrl.put.atomic_op([](be_t<u32>& value)
|
||||
{
|
||||
value += 8;
|
||||
});
|
||||
}
|
||||
|
||||
return id;
|
||||
@ -1164,25 +1166,38 @@ 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<CellGcmContextData> context, u32 count)
|
||||
{
|
||||
cellGcmSys->Log("cellGcmCallback(context_addr=0x%x, count=0x%x)", context_addr, 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<CellGcmContextData>(context_addr);
|
||||
auto& ctrl = vm::get_ref<CellGcmControl>(gcm_info.control_addr);
|
||||
|
||||
const s32 res = ctx.current - ctx.begin - ctrl.put;
|
||||
{
|
||||
const u32 address = context->current;
|
||||
const u32 upper = offsetTable.ioAddress[address >> 20]; // 12 bits
|
||||
assert(upper != 0xFFFF);
|
||||
const u32 offset = (upper << 20) | (address & 0xFFFFF);
|
||||
//ctrl.put.exchange(be_t<u32>::make(offset)); // update put pointer
|
||||
}
|
||||
|
||||
memmove(vm::get_ptr<void>(ctx.begin), vm::get_ptr<void>(ctx.current - res), res);
|
||||
// preparations for changing the place (for optimized FIFO mode)
|
||||
//auto cmd = vm::ptr<u32>::make(context->current.ToLE());
|
||||
//cmd[0] = 0x41D6C;
|
||||
//cmd[1] = 0x20;
|
||||
//cmd[2] = 0x41D74;
|
||||
//cmd[3] = 0; // some incrementing by module value
|
||||
//context->current += 0x10;
|
||||
|
||||
ctx.current = ctx.begin + res;
|
||||
|
||||
//InterlockedExchange64((volatile long long*)((u8*)&ctrl + offsetof(CellGcmControl, put)), (u64)(u32)re(res));
|
||||
ctrl.put = res;
|
||||
ctrl.get = 0;
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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<CellGcmContextData> ctxt, u32 id);
|
||||
|
||||
s32 cellGcmAddressToOffset(u64 address, vm::ptr<be_t<u32>> 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<CellGcmContextData> context, u32 count);
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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<CellSpursAttribute> attr, vm:
|
||||
|
||||
s64 cellSpursFinalize(vm::ptr<CellSpurs> 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
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
@ -202,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");
|
||||
@ -211,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;
|
||||
@ -245,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);
|
||||
|
@ -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<std::unique_ptr<ModuleInitializer>> m_modules_init;
|
||||
|
||||
std::vector<u64> 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_ppu_thr_stop;
|
||||
s32 m_sdk_version;
|
||||
|
||||
Emulator();
|
||||
@ -172,14 +172,14 @@ 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_ppu_thr_stop = addr;
|
||||
m_cpu_thr_stop = addr;
|
||||
}
|
||||
|
||||
EmuInfo& GetInfo() { return m_info; }
|
||||
@ -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);
|
||||
|
@ -332,7 +332,7 @@ void RSXDebugger::GoToGet(wxCommandEvent& event)
|
||||
if (!RSXReady()) return;
|
||||
auto ctrl = vm::get_ptr<CellGcmControl>(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<CellGcmControl>(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();
|
||||
|
@ -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
|
||||
@ -43,6 +44,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 +53,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 +87,29 @@ 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:
|
||||
{
|
||||
list_known_psv_modules();
|
||||
|
||||
auto armv7_thr_stop_data = vm::psv::ptr<u32>::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<const u32>::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;
|
||||
}
|
||||
|
||||
@ -94,6 +118,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 +132,7 @@ namespace loader
|
||||
case 0x00000001: //LOAD
|
||||
if (phdr.data_le.p_memsz)
|
||||
{
|
||||
if (!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);
|
||||
|
||||
|
@ -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<u16> e_type;
|
||||
be_t<u16> e_machine;
|
||||
be_t<u32> e_version;
|
||||
be_t<u16> e_entry;
|
||||
be_t<u32> e_entry;
|
||||
be_t<u32> e_phoff;
|
||||
be_t<u32> e_shoff;
|
||||
be_t<u32> 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
|
||||
|
@ -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<u32>::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);
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user