mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-03 04:13:27 +00:00
ARMv7: branch instrs fixed, new instructions
BIC_IMM, BIC_REG, RSB_IMM, LDR_LIT, STRB_REG, STRH_REG Fixed initial stack size
This commit is contained in:
parent
c267ca2584
commit
5225ca8fc2
@ -228,9 +228,9 @@ namespace ARMv7_instrs
|
||||
}
|
||||
}
|
||||
|
||||
u32 ThumbExpandImm(ARMv7Context& context, u32 imm12)
|
||||
u32 ThumbExpandImm(u32 imm12)
|
||||
{
|
||||
bool carry = context.APSR.C;
|
||||
bool carry;
|
||||
return ThumbExpandImm_C(imm12, carry, carry);
|
||||
}
|
||||
|
||||
@ -418,7 +418,7 @@ void ARMv7_instrs::ADD_IMM(ARMv7Context& context, const ARMv7Code code, const AR
|
||||
d = (code.data & 0xf00) >> 8;
|
||||
n = (code.data & 0xf0000) >> 16;
|
||||
set_flags = (code.data & 0x100000);
|
||||
imm32 = ThumbExpandImm(context, (code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff));
|
||||
imm32 = ThumbExpandImm((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff));
|
||||
|
||||
reject(d == 15 && set_flags, "CMN (immediate)");
|
||||
reject(n == 13, "ADD (SP plus immediate)");
|
||||
@ -567,7 +567,7 @@ void ARMv7_instrs::ADD_SPI(ARMv7Context& context, const ARMv7Code code, const AR
|
||||
cond = context.ITSTATE.advance();
|
||||
d = (code.data & 0xf00) >> 8;
|
||||
set_flags = (code.data & 0x100000);
|
||||
imm32 = ThumbExpandImm(context, (code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff));
|
||||
imm32 = ThumbExpandImm((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff));
|
||||
|
||||
reject(d == 15 && set_flags, "CMN (immediate)");
|
||||
reject(d == 15, "UNPREDICTABLE");
|
||||
@ -770,14 +770,14 @@ void ARMv7_instrs::ASR_REG(ARMv7Context& context, const ARMv7Code code, const AR
|
||||
|
||||
void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
|
||||
{
|
||||
u32 cond, jump;
|
||||
u32 cond, imm32;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case T1:
|
||||
{
|
||||
cond = (code.data >> 8) & 0xf;
|
||||
jump = 4 + sign<9, u32>((code.data & 0xff) << 1);
|
||||
imm32 = sign<9, u32>((code.data & 0xff) << 1);
|
||||
|
||||
reject(cond == 14, "UNDEFINED");
|
||||
reject(cond == 15, "SVC");
|
||||
@ -787,7 +787,7 @@ void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_en
|
||||
case T2:
|
||||
{
|
||||
cond = context.ITSTATE.advance();
|
||||
jump = 4 + sign<12, u32>((code.data & 0x7ff) << 1);
|
||||
imm32 = sign<12, u32>((code.data & 0x7ff) << 1);
|
||||
|
||||
reject(context.ITSTATE, "UNPREDICTABLE");
|
||||
break;
|
||||
@ -799,7 +799,7 @@ void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_en
|
||||
const u32 s = (code.data >> 26) & 0x1;
|
||||
const u32 j1 = (code.data >> 13) & 0x1;
|
||||
const u32 j2 = (code.data >> 11) & 0x1;
|
||||
jump = 4 + sign<21, u32>(s << 20 | j2 << 19 | j1 << 18 | (code.data & 0x3f0000) >> 4 | (code.data & 0x7ff) << 1);
|
||||
imm32 = sign<21, u32>(s << 20 | j2 << 19 | j1 << 18 | (code.data & 0x3f0000) >> 4 | (code.data & 0x7ff) << 1);
|
||||
}
|
||||
|
||||
reject(cond >= 14, "Related encodings");
|
||||
@ -813,7 +813,7 @@ void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_en
|
||||
const u32 s = (code.data >> 26) & 0x1;
|
||||
const u32 i1 = (code.data >> 13) & 0x1 ^ s ^ 1;
|
||||
const u32 i2 = (code.data >> 11) & 0x1 ^ s ^ 1;
|
||||
jump = 4 + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1);
|
||||
imm32 = sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1);
|
||||
}
|
||||
|
||||
reject(context.ITSTATE, "UNPREDICTABLE");
|
||||
@ -822,7 +822,7 @@ void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_en
|
||||
case A1:
|
||||
{
|
||||
cond = code.data >> 28;
|
||||
jump = 1 + 4 + sign<26, u32>((code.data & 0xffffff) << 2);
|
||||
imm32 = sign<26, u32>((code.data & 0xffffff) << 2);
|
||||
break;
|
||||
}
|
||||
default: throw __FUNCTION__;
|
||||
@ -830,8 +830,7 @@ void ARMv7_instrs::B(ARMv7Context& context, const ARMv7Code code, const ARMv7_en
|
||||
|
||||
if (ConditionPassed(context, cond))
|
||||
{
|
||||
//LOG_NOTICE(ARMv7, "Branch to 0x%x (cond=0x%x)", context.thread.PC + jump, cond);
|
||||
context.thread.SetBranch(context.thread.PC + jump);
|
||||
context.thread.SetBranch(context.read_pc() + imm32);
|
||||
}
|
||||
}
|
||||
|
||||
@ -857,20 +856,86 @@ void ARMv7_instrs::BFI(ARMv7Context& context, const ARMv7Code code, const ARMv7_
|
||||
|
||||
void ARMv7_instrs::BIC_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
|
||||
{
|
||||
bool set_flags, carry = context.APSR.C;
|
||||
u32 cond, d, n, imm32;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case T1:
|
||||
{
|
||||
cond = context.ITSTATE.advance();
|
||||
d = (code.data & 0xf00) >> 8;
|
||||
n = (code.data & 0xf0000) >> 16;
|
||||
set_flags = (code.data & 0x100000);
|
||||
imm32 = ThumbExpandImm_C((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff), carry, carry);
|
||||
|
||||
reject(d == 13 || d == 15 || n == 13 || n == 15, "UNPREDICTABLE");
|
||||
break;
|
||||
}
|
||||
case A1: throw __FUNCTION__;
|
||||
default: throw __FUNCTION__;
|
||||
}
|
||||
|
||||
if (ConditionPassed(context, cond))
|
||||
{
|
||||
const u32 result = context.read_gpr(n) & ~imm32;
|
||||
context.write_gpr(d, result);
|
||||
|
||||
if (set_flags)
|
||||
{
|
||||
context.APSR.N = result >> 31;
|
||||
context.APSR.Z = result == 0;
|
||||
context.APSR.C = carry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv7_instrs::BIC_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
|
||||
{
|
||||
bool set_flags = !context.ITSTATE;
|
||||
u32 cond, d, n, m, shift_t, shift_n;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case T1:
|
||||
{
|
||||
cond = context.ITSTATE.advance();
|
||||
d = n = (code.data & 0x7);
|
||||
m = (code.data & 0x38) >> 3;
|
||||
shift_t = SRType_LSL;
|
||||
shift_n = 0;
|
||||
break;
|
||||
}
|
||||
case T2:
|
||||
{
|
||||
cond = context.ITSTATE.advance();
|
||||
d = (code.data & 0xf00) >> 8;
|
||||
n = (code.data & 0xf0000) >> 16;
|
||||
m = (code.data & 0xf);
|
||||
set_flags = (code.data & 0x100000);
|
||||
shift_t = DecodeImmShift((code.data & 0x30) >> 4, (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6, &shift_n);
|
||||
|
||||
reject(d == 13 || d == 15 || n == 13 || n == 15 || m == 13 || m == 15, "UNPREDICTABLE");
|
||||
break;
|
||||
}
|
||||
case A1: throw __FUNCTION__;
|
||||
default: throw __FUNCTION__;
|
||||
}
|
||||
|
||||
if (ConditionPassed(context, cond))
|
||||
{
|
||||
bool carry;
|
||||
const u32 shifted = Shift_C(context.read_gpr(m), shift_t, shift_n, context.APSR.C, carry);
|
||||
const u32 result = context.read_gpr(n) & ~shifted;
|
||||
context.write_gpr(d, result);
|
||||
|
||||
if (set_flags)
|
||||
{
|
||||
context.APSR.N = result >> 31;
|
||||
context.APSR.Z = result == 0;
|
||||
context.APSR.C = carry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv7_instrs::BIC_RSR(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
|
||||
@ -895,19 +960,18 @@ void ARMv7_instrs::BKPT(ARMv7Context& context, const ARMv7Code code, const ARMv7
|
||||
|
||||
void ARMv7_instrs::BL(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
|
||||
{
|
||||
u32 cond, imm32, newLR;
|
||||
u32 cond, imm32;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case T1:
|
||||
{
|
||||
cond = context.ITSTATE.advance();
|
||||
newLR = (context.thread.PC + 4) | 1;
|
||||
{
|
||||
const u32 s = (code.data >> 26) & 0x1;
|
||||
const u32 i1 = (code.data >> 13) & 0x1 ^ s ^ 1;
|
||||
const u32 i2 = (code.data >> 11) & 0x1 ^ s ^ 1;
|
||||
imm32 = 4 + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1);
|
||||
imm32 = sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1);
|
||||
}
|
||||
|
||||
reject(context.ITSTATE, "UNPREDICTABLE");
|
||||
@ -916,8 +980,7 @@ void ARMv7_instrs::BL(ARMv7Context& context, const ARMv7Code code, const ARMv7_e
|
||||
case A1:
|
||||
{
|
||||
cond = code.data >> 28;
|
||||
newLR = (context.thread.PC + 4) - 4;
|
||||
imm32 = 4 + sign<26, u32>((code.data & 0xffffff) << 2);
|
||||
imm32 = sign<26, u32>((code.data & 0xffffff) << 2);
|
||||
break;
|
||||
}
|
||||
default: throw __FUNCTION__;
|
||||
@ -925,8 +988,16 @@ void ARMv7_instrs::BL(ARMv7Context& context, const ARMv7Code code, const ARMv7_e
|
||||
|
||||
if (ConditionPassed(context, cond))
|
||||
{
|
||||
context.LR = newLR;
|
||||
context.thread.SetBranch(context.thread.PC + imm32);
|
||||
if (context.ISET == ARM)
|
||||
{
|
||||
context.LR = context.read_pc() - 4;
|
||||
context.thread.SetBranch((context.read_pc() & ~3) + imm32);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.LR = context.read_pc() | 1;
|
||||
context.thread.SetBranch(context.read_pc() + imm32);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -939,7 +1010,7 @@ void ARMv7_instrs::BLX(ARMv7Context& context, const ARMv7Code code, const ARMv7_
|
||||
case T1:
|
||||
{
|
||||
cond = context.ITSTATE.advance();
|
||||
newLR = (context.thread.PC + 2) | 1; // ???
|
||||
newLR = (context.thread.PC + 2) | 1;
|
||||
{
|
||||
const u32 m = (code.data >> 3) & 0xf;
|
||||
reject(m == 15, "UNPREDICTABLE");
|
||||
@ -957,7 +1028,7 @@ void ARMv7_instrs::BLX(ARMv7Context& context, const ARMv7Code code, const ARMv7_
|
||||
const u32 s = (code.data >> 26) & 0x1;
|
||||
const u32 i1 = (code.data >> 13) & 0x1 ^ s ^ 1;
|
||||
const u32 i2 = (code.data >> 11) & 0x1 ^ s ^ 1;
|
||||
target = (context.thread.PC + 4 & ~3) + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1);
|
||||
target = ~3 & context.thread.PC + 4 + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1);
|
||||
}
|
||||
|
||||
reject(context.ITSTATE, "UNPREDICTABLE");
|
||||
@ -966,15 +1037,15 @@ void ARMv7_instrs::BLX(ARMv7Context& context, const ARMv7Code code, const ARMv7_
|
||||
case A1:
|
||||
{
|
||||
cond = code.data >> 28;
|
||||
newLR = (context.thread.PC + 4) - 4;
|
||||
newLR = context.thread.PC + 4;
|
||||
target = context.read_gpr(code.data & 0xf);
|
||||
break;
|
||||
}
|
||||
case A2:
|
||||
{
|
||||
cond = 0xe; // always true
|
||||
newLR = (context.thread.PC + 4) - 4;
|
||||
target = (context.thread.PC + 4 | 1) + sign<25, u32>((code.data & 0xffffff) << 2 | (code.data & 0x1000000) >> 23);
|
||||
newLR = context.thread.PC + 4;
|
||||
target = 1 | context.thread.PC + 8 + sign<25, u32>((code.data & 0xffffff) << 2 | (code.data & 0x1000000) >> 23);
|
||||
break;
|
||||
}
|
||||
default: throw __FUNCTION__;
|
||||
@ -1038,7 +1109,7 @@ void ARMv7_instrs::CB_Z(ARMv7Context& context, const ARMv7Code code, const ARMv7
|
||||
|
||||
if ((context.read_gpr(n) == 0) ^ nonzero)
|
||||
{
|
||||
context.thread.SetBranch(context.thread.PC + 2 + imm32);
|
||||
context.thread.SetBranch(context.read_pc() + imm32);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1115,7 +1186,7 @@ void ARMv7_instrs::CMP_IMM(ARMv7Context& context, const ARMv7Code code, const AR
|
||||
{
|
||||
cond = context.ITSTATE.advance();
|
||||
n = (code.data & 0xf0000) >> 16;
|
||||
imm32 = ThumbExpandImm(context, (code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff));
|
||||
imm32 = ThumbExpandImm((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff));
|
||||
|
||||
reject(n == 15, "UNPREDICTABLE");
|
||||
break;
|
||||
@ -1127,11 +1198,14 @@ void ARMv7_instrs::CMP_IMM(ARMv7Context& context, const ARMv7Code code, const AR
|
||||
if (ConditionPassed(context, cond))
|
||||
{
|
||||
bool carry, overflow;
|
||||
const u32 res = AddWithCarry(context.read_gpr(n), ~imm32, true, carry, overflow);
|
||||
const u32 n_value = context.read_gpr(n);
|
||||
const u32 res = AddWithCarry(n_value, ~imm32, true, carry, overflow);
|
||||
context.APSR.N = res >> 31;
|
||||
context.APSR.Z = res == 0;
|
||||
context.APSR.C = carry;
|
||||
context.APSR.V = overflow;
|
||||
|
||||
//LOG_NOTICE(ARMv7, "CMP: r%d=0x%08x <> 0x%08x, res=0x%08x", n, n_value, imm32, res);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1369,11 +1443,40 @@ void ARMv7_instrs::LDR_IMM(ARMv7Context& context, const ARMv7Code code, const AR
|
||||
|
||||
void ARMv7_instrs::LDR_LIT(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
|
||||
{
|
||||
u32 cond, t, imm32;
|
||||
bool add;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case T1:
|
||||
{
|
||||
cond = context.ITSTATE.advance();
|
||||
t = (code.data & 0x700) >> 8;
|
||||
imm32 = (code.data & 0xff) << 2;
|
||||
add = true;
|
||||
break;
|
||||
}
|
||||
case T2:
|
||||
{
|
||||
cond = context.ITSTATE.advance();
|
||||
t = (code.data & 0xf000) >> 12;
|
||||
imm32 = (code.data & 0xfff);
|
||||
add = (code.data & 0x800000);
|
||||
|
||||
reject(t == 15 && context.ITSTATE, "UNPREDICTABLE");
|
||||
break;
|
||||
}
|
||||
case A1: throw __FUNCTION__;
|
||||
default: throw __FUNCTION__;
|
||||
}
|
||||
|
||||
if (ConditionPassed(context, cond))
|
||||
{
|
||||
const u32 base = context.read_pc() & ~3;
|
||||
const u32 addr = add ? base + imm32 : base - imm32;
|
||||
const u32 data = vm::psv::read32(addr);
|
||||
context.write_gpr(t, data);
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv7_instrs::LDR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
|
||||
@ -2544,11 +2647,48 @@ void ARMv7_instrs::RRX(ARMv7Context& context, const ARMv7Code code, const ARMv7_
|
||||
|
||||
void ARMv7_instrs::RSB_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
|
||||
{
|
||||
bool set_flags = !context.ITSTATE;
|
||||
u32 cond, d, n, imm32;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case T1:
|
||||
{
|
||||
cond = context.ITSTATE.advance();
|
||||
d = (code.data & 0x7);
|
||||
n = (code.data & 0x38) >> 3;
|
||||
imm32 = 0;
|
||||
break;
|
||||
}
|
||||
case T2:
|
||||
{
|
||||
cond = context.ITSTATE.advance();
|
||||
d = (code.data & 0xf00) >> 8;
|
||||
n = (code.data & 0xf0000) >> 16;
|
||||
set_flags = (code.data & 0x100000);
|
||||
imm32 = ThumbExpandImm((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff));
|
||||
|
||||
reject(d == 13 || d == 15 || n == 13 || n == 15, "UNPREDICTABLE");
|
||||
break;
|
||||
}
|
||||
case A1: throw __FUNCTION__;
|
||||
default: throw __FUNCTION__;
|
||||
}
|
||||
|
||||
if (ConditionPassed(context, cond))
|
||||
{
|
||||
bool carry, overflow;
|
||||
const u32 result = AddWithCarry(~context.read_gpr(n), imm32, true, carry, overflow);
|
||||
context.write_gpr(d, result);
|
||||
|
||||
if (set_flags)
|
||||
{
|
||||
context.APSR.N = result >> 31;
|
||||
context.APSR.Z = result == 0;
|
||||
context.APSR.C = carry;
|
||||
context.APSR.V = overflow;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv7_instrs::RSB_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
|
||||
@ -3167,11 +3307,57 @@ void ARMv7_instrs::STRB_IMM(ARMv7Context& context, const ARMv7Code code, const A
|
||||
|
||||
void ARMv7_instrs::STRB_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
|
||||
{
|
||||
u32 cond, t, n, m, shift_t, shift_n;
|
||||
bool index, add, wback;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case T1:
|
||||
{
|
||||
cond = context.ITSTATE.advance();
|
||||
t = (code.data & 0x7);
|
||||
n = (code.data & 0x38) >> 3;
|
||||
m = (code.data & 0x1c0) >> 6;
|
||||
index = true;
|
||||
add = true;
|
||||
wback = false;
|
||||
shift_t = SRType_LSL;
|
||||
shift_n = 0;
|
||||
break;
|
||||
}
|
||||
case T2:
|
||||
{
|
||||
cond = context.ITSTATE.advance();
|
||||
t = (code.data & 0xf000) >> 12;
|
||||
n = (code.data & 0xf0000) >> 16;
|
||||
m = (code.data & 0xf);
|
||||
index = true;
|
||||
add = true;
|
||||
wback = false;
|
||||
shift_t = SRType_LSL;
|
||||
shift_n = (code.data & 0x30) >> 4;
|
||||
|
||||
reject(n == 15, "UNDEFINED");
|
||||
reject(t == 13 || t == 15 || m == 13 || m == 15, "UNPREDICTABLE");
|
||||
break;
|
||||
}
|
||||
case A1: throw __FUNCTION__;
|
||||
default: throw __FUNCTION__;
|
||||
}
|
||||
|
||||
if (ConditionPassed(context, cond))
|
||||
{
|
||||
const u32 offset = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C);
|
||||
const u32 offset_addr = add ? context.read_gpr(n) + offset : context.read_gpr(n) - offset;
|
||||
const u32 addr = index ? offset_addr : context.read_gpr(n);
|
||||
|
||||
vm::psv::write8(addr, (u8)context.read_gpr(t));
|
||||
|
||||
if (wback)
|
||||
{
|
||||
context.write_gpr(n, offset_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3205,11 +3391,57 @@ void ARMv7_instrs::STRH_IMM(ARMv7Context& context, const ARMv7Code code, const A
|
||||
|
||||
void ARMv7_instrs::STRH_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
|
||||
{
|
||||
u32 cond, t, n, m, shift_t, shift_n;
|
||||
bool index, add, wback;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case T1:
|
||||
{
|
||||
cond = context.ITSTATE.advance();
|
||||
t = (code.data & 0x7);
|
||||
n = (code.data & 0x38) >> 3;
|
||||
m = (code.data & 0x1c0) >> 6;
|
||||
index = true;
|
||||
add = true;
|
||||
wback = false;
|
||||
shift_t = SRType_LSL;
|
||||
shift_n = 0;
|
||||
break;
|
||||
}
|
||||
case T2:
|
||||
{
|
||||
cond = context.ITSTATE.advance();
|
||||
t = (code.data & 0xf000) >> 12;
|
||||
n = (code.data & 0xf0000) >> 16;
|
||||
m = (code.data & 0xf);
|
||||
index = true;
|
||||
add = true;
|
||||
wback = false;
|
||||
shift_t = SRType_LSL;
|
||||
shift_n = (code.data & 0x30) >> 4;
|
||||
|
||||
reject(n == 15, "UNDEFINED");
|
||||
reject(t == 13 || t == 15 || m == 13 || m == 15, "UNPREDICTABLE");
|
||||
break;
|
||||
}
|
||||
case A1: throw __FUNCTION__;
|
||||
default: throw __FUNCTION__;
|
||||
}
|
||||
|
||||
if (ConditionPassed(context, cond))
|
||||
{
|
||||
const u32 offset = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C);
|
||||
const u32 offset_addr = add ? context.read_gpr(n) + offset : context.read_gpr(n) - offset;
|
||||
const u32 addr = index ? offset_addr : context.read_gpr(n);
|
||||
|
||||
vm::psv::write16(addr, (u16)context.read_gpr(t));
|
||||
|
||||
if (wback)
|
||||
{
|
||||
context.write_gpr(n, offset_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3302,7 +3534,7 @@ void ARMv7_instrs::SUB_IMM(ARMv7Context& context, const ARMv7Code code, const AR
|
||||
d = (code.data & 0xf00) >> 8;
|
||||
n = (code.data & 0xf0000) >> 16;
|
||||
set_flags = (code.data & 0x100000);
|
||||
imm32 = ThumbExpandImm(context, (code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff));
|
||||
imm32 = ThumbExpandImm((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff));
|
||||
|
||||
reject(d == 15 && set_flags, "CMP (immediate)");
|
||||
reject(n == 13, "SUB (SP minus immediate)");
|
||||
@ -3429,7 +3661,7 @@ void ARMv7_instrs::SUB_SPI(ARMv7Context& context, const ARMv7Code code, const AR
|
||||
cond = context.ITSTATE.advance();
|
||||
d = (code.data & 0xf00) >> 8;
|
||||
set_flags = (code.data & 0x100000);
|
||||
imm32 = ThumbExpandImm(context, (code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff));
|
||||
imm32 = ThumbExpandImm((code.data & 0x4000000) >> 15 | (code.data & 0x7000) >> 4 | (code.data & 0xff));
|
||||
|
||||
reject(d == 15 && set_flags, "CMP (immediate)");
|
||||
reject(d == 15, "UNPREDICTABLE");
|
||||
|
@ -18,7 +18,7 @@ void ARMv7Context::write_pc(u32 value)
|
||||
|
||||
u32 ARMv7Context::read_pc()
|
||||
{
|
||||
return thread.PC;
|
||||
return ISET == ARM ? thread.PC + 8 : thread.PC + 4;
|
||||
}
|
||||
|
||||
u32 ARMv7Context::get_stack_arg(u32 pos)
|
||||
@ -230,14 +230,14 @@ void ARMv7Thread::FastStop()
|
||||
m_status = Stopped;
|
||||
}
|
||||
|
||||
armv7_thread::armv7_thread(u32 entry, const std::string& name, u32 stack_size, u32 prio)
|
||||
armv7_thread::armv7_thread(u32 entry, const std::string& name, u32 stack_size, s32 prio)
|
||||
{
|
||||
thread = &Emu.GetCPU().AddThread(CPU_THREAD_ARMv7);
|
||||
|
||||
thread->SetName(name);
|
||||
thread->SetEntry(entry);
|
||||
thread->SetStackSize(stack_size ? stack_size : Emu.GetInfo().GetProcParam().primary_stacksize);
|
||||
thread->SetPrio(prio ? prio : Emu.GetInfo().GetProcParam().primary_prio);
|
||||
thread->SetStackSize(stack_size);
|
||||
thread->SetPrio(prio);
|
||||
|
||||
argc = 0;
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ class armv7_thread : cpu_thread
|
||||
u32 argc;
|
||||
|
||||
public:
|
||||
armv7_thread(u32 entry, const std::string& name = "", u32 stack_size = 0, u32 prio = 0);
|
||||
armv7_thread(u32 entry, const std::string& name, u32 stack_size, s32 prio);
|
||||
|
||||
cpu_thread& args(std::initializer_list<std::string> values) override;
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
struct psv_event_flag_t
|
||||
{
|
||||
s32 id;
|
||||
char name[32];
|
||||
u32 attr;
|
||||
u32 pattern;
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
struct psv_sema_t
|
||||
{
|
||||
s32 id;
|
||||
char name[32];
|
||||
u32 attr;
|
||||
s32 value;
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "Utilities/Log.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/ARMv7/PSVFuncList.h"
|
||||
#include "Emu/ARMv7/ARMv7Thread.h"
|
||||
#include "Emu/ARMv7/ARMv7Callback.h"
|
||||
|
||||
extern psv_log_base sceLibc;
|
||||
@ -12,6 +13,70 @@ typedef void(atexit_func_t)(vm::psv::ptr<void>);
|
||||
|
||||
std::vector<std::function<void(ARMv7Context&)>> g_atexit;
|
||||
|
||||
std::string armv7_fmt(ARMv7Context& context, vm::psv::ptr<const char> fmt, u32 g_count, u32 f_count, u32 v_count)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
for (char c = *fmt++; c; c = *fmt++)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '%':
|
||||
{
|
||||
const auto start = fmt - 1;
|
||||
const bool number_sign = *fmt == '#' ? fmt++, true : false;
|
||||
|
||||
switch (*fmt++)
|
||||
{
|
||||
case '%':
|
||||
{
|
||||
result += '%';
|
||||
continue;
|
||||
}
|
||||
case 'd':
|
||||
case 'i':
|
||||
{
|
||||
// signed decimal
|
||||
const s64 value = context.get_next_gpr_arg(g_count, f_count, v_count);
|
||||
|
||||
result += fmt::to_sdec(value);
|
||||
continue;
|
||||
}
|
||||
case 'x':
|
||||
{
|
||||
// hexadecimal
|
||||
const u64 value = context.get_next_gpr_arg(g_count, f_count, v_count);
|
||||
|
||||
if (number_sign && value)
|
||||
{
|
||||
result += "0x";
|
||||
}
|
||||
|
||||
result += fmt::to_hex(value);
|
||||
continue;
|
||||
}
|
||||
case 's':
|
||||
{
|
||||
// string
|
||||
auto string = vm::psv::ptr<const char>::make(context.get_next_gpr_arg(g_count, f_count, v_count));
|
||||
|
||||
result += string.get_ptr();
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw fmt::Format("armv7_fmt(): unknown formatting: '%s'", start.get_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result += c;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace sce_libc_func
|
||||
{
|
||||
void __cxa_atexit(vm::psv::ptr<atexit_func_t> func, vm::psv::ptr<void> arg, vm::psv::ptr<void> dso)
|
||||
@ -59,62 +124,6 @@ namespace sce_libc_func
|
||||
});
|
||||
}
|
||||
|
||||
std::string armv7_fmt(ARMv7Context& context, vm::psv::ptr<const char> fmt, u32 g_count, u32 f_count, u32 v_count)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
for (char c = *fmt++; c; c = *fmt++)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case '%':
|
||||
{
|
||||
const auto start = fmt - 1;
|
||||
const bool number_sign = *fmt == '#' ? fmt++, true : false;
|
||||
|
||||
switch (*fmt++)
|
||||
{
|
||||
case '%':
|
||||
{
|
||||
result += '%';
|
||||
continue;
|
||||
}
|
||||
case 'd':
|
||||
case 'i':
|
||||
{
|
||||
// signed decimal
|
||||
const s64 value = context.get_next_gpr_arg(g_count, f_count, v_count);
|
||||
|
||||
result += fmt::to_sdec(value);
|
||||
continue;
|
||||
}
|
||||
case 'x':
|
||||
{
|
||||
// hexadecimal
|
||||
const u64 value = context.get_next_gpr_arg(g_count, f_count, v_count);
|
||||
|
||||
if (number_sign && value)
|
||||
{
|
||||
result += "0x";
|
||||
}
|
||||
|
||||
result += fmt::to_hex(value);
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw fmt::Format("armv7_fmt(): unknown formatting: '%s'", start.get_ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result += c;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void printf(ARMv7Context& context, vm::psv::ptr<const char> fmt) // va_args...
|
||||
{
|
||||
sceLibc.Warning("printf(fmt=0x%x)", fmt);
|
||||
@ -158,11 +167,12 @@ namespace sce_libc_func
|
||||
::memset(dst.get_ptr(), value, size);
|
||||
}
|
||||
|
||||
void _Assert(vm::psv::ptr<const char> text, vm::psv::ptr<const char> func)
|
||||
void _Assert(ARMv7Context& context, vm::psv::ptr<const char> text, vm::psv::ptr<const char> func)
|
||||
{
|
||||
sceLibc.Warning("_Assert(text=0x%x, func=0x%x)", text, func);
|
||||
sceLibc.Error("_Assert(text=0x%x, func=0x%x)", text, func);
|
||||
|
||||
LOG_ERROR(TTY, "%s : %s\n", func.get_ptr(), text.get_ptr());
|
||||
LOG_NOTICE(ARMv7, context.thread.RegsToString());
|
||||
Emu.Pause();
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,18 @@ template<typename T, u32 type>
|
||||
class psv_object_list_t // Class for managing object data
|
||||
{
|
||||
std::array<std::shared_ptr<T>, 0x8000> m_data;
|
||||
std::atomic<u32> m_hint; // guessing next free position
|
||||
std::mutex m_mutex; // TODO: remove it when shared_ptr atomic ops are fully available
|
||||
|
||||
public:
|
||||
psv_object_list_t() : m_hint(0) {}
|
||||
|
||||
psv_object_list_t(const psv_object_list_t&) = delete;
|
||||
psv_object_list_t(psv_object_list_t&&) = delete;
|
||||
|
||||
psv_object_list_t& operator =(const psv_object_list_t&) = delete;
|
||||
psv_object_list_t& operator =(psv_object_list_t&&) = delete;
|
||||
|
||||
public:
|
||||
static const u32 uid_class = type;
|
||||
|
||||
@ -60,18 +70,18 @@ public:
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
for (auto& value : m_data)
|
||||
for (u32 i = 0, j = m_hint % m_data.size(); i < m_data.size(); i++, j = (j + 1) % m_data.size())
|
||||
{
|
||||
// find an empty position and move the pointer
|
||||
//std::shared_ptr<T> old_ptr = nullptr;
|
||||
//if (std::atomic_compare_exchange_strong(&value, &old_ptr, data))
|
||||
if (!value)
|
||||
// find an empty position and copy the pointer
|
||||
if (!m_data[j])
|
||||
{
|
||||
value = data;
|
||||
m_data[j] = data;
|
||||
m_hint = j + 1; // guess next position
|
||||
psv_uid_t id = psv_uid_t::make(1); // odd number
|
||||
id.type = uid_class; // set type
|
||||
id.number = &value - m_data.data(); // set position
|
||||
return id.uid;
|
||||
id.number = j; // set position
|
||||
data->id = id.uid; // save UID
|
||||
return id.uid; // return UID
|
||||
}
|
||||
}
|
||||
|
||||
@ -86,12 +96,14 @@ public:
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const u32 pos = psv_uid_t::make(uid).number;
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
std::shared_ptr<T> old_ptr = nullptr;
|
||||
m_data[psv_uid_t::make(uid).number].swap(old_ptr);
|
||||
m_data[pos].swap(old_ptr);
|
||||
m_hint = pos;
|
||||
return old_ptr;
|
||||
//return std::atomic_exchange<std::shared_ptr<T>>(&m_data[psv_uid_t::make(uid).number], nullptr);
|
||||
}
|
||||
|
||||
// remove all objects
|
||||
@ -103,6 +115,8 @@ public:
|
||||
{
|
||||
value = nullptr;
|
||||
}
|
||||
|
||||
m_hint = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -63,7 +63,11 @@ namespace vm
|
||||
return res;
|
||||
}
|
||||
|
||||
assert(!real_pointer);
|
||||
if (real_pointer)
|
||||
{
|
||||
throw fmt::format("vm::get_addr(0x%016llx) failed: not a part of virtual memory", (u64)real_pointer);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -401,8 +401,8 @@ namespace loader
|
||||
armv7_decoder_initialize(code_start, code_end);
|
||||
|
||||
const std::string& thread_name = proc_param->sceUserMainThreadName ? proc_param->sceUserMainThreadName.get_ptr() : "main_thread";
|
||||
const u32 stack_size = proc_param->sceUserMainThreadStackSize ? *proc_param->sceUserMainThreadStackSize : 0;
|
||||
const u32 priority = proc_param->sceUserMainThreadPriority ? *proc_param->sceUserMainThreadPriority : 0;
|
||||
const u32 stack_size = proc_param->sceUserMainThreadStackSize ? *proc_param->sceUserMainThreadStackSize : 256 * 1024;
|
||||
const u32 priority = proc_param->sceUserMainThreadPriority ? *proc_param->sceUserMainThreadPriority : 160;
|
||||
|
||||
armv7_thread(entry, thread_name, stack_size, priority).args({ Emu.GetPath(), "-emu" }).run();
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user