ARMv7: new instructions, bugfix

LDRD_LIT, LDRH_IMM, LDRH_LIT, LSR_IMM, ORR_IMM, STRD_IMM, STRD_REG,
UMULL
This commit is contained in:
Nekotekina 2015-02-03 17:48:20 +03:00
parent 60f6566c78
commit 2494fcf8d8
6 changed files with 342 additions and 83 deletions

View File

@ -1105,6 +1105,7 @@ const ARMv7_opcode_t ARMv7_opcode_table[] =
struct ARMv7_op2_table_t struct ARMv7_op2_table_t
{ {
const ARMv7_opcode_t* data[0x10000]; const ARMv7_opcode_t* data[0x10000];
u32 null_ops;
ARMv7_op2_table_t() ARMv7_op2_table_t()
{ {
@ -1123,6 +1124,8 @@ struct ARMv7_op2_table_t
} }
} }
null_ops = 0x10000;
for (u32 i = 0; i < 0x10000; i++) for (u32 i = 0; i < 0x10000; i++)
{ {
data[i] = nullptr; data[i] = nullptr;
@ -1132,6 +1135,7 @@ struct ARMv7_op2_table_t
if (((i << 16) & opcode->mask) == opcode->code && (!opcode->skip || !opcode->skip(i))) if (((i << 16) & opcode->mask) == opcode->code && (!opcode->skip || !opcode->skip(i)))
{ {
data[i] = opcode; data[i] = opcode;
null_ops--;
break; break;
} }
} }
@ -1201,11 +1205,12 @@ std::unordered_map<u32, const ARMv7_opcode_t*> g_opct;
void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump) void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump)
{ {
// 1. Find every 4-byte thumb instruction and cache it // 1. Find every 4-byte Thumb instruction and cache it
// 2. If some instruction is not recognized, print the error // 2. If some instruction is not recognized, print the error
// 3. Possibly print disasm // 3. Possibly print disasm
g_opct.clear(); //g_opct.clear();
//g_opct.reserve(end_addr - addr);
while (addr < end_addr) while (addr < end_addr)
{ {
@ -1297,7 +1302,7 @@ void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump)
addr += found->length; addr += found->length;
} }
LOG_NOTICE(ARMv7, "armv7_decoder_initialize() finished, g_opct.size() = %lld", (u64)g_opct.size()); LOG_NOTICE(ARMv7, "armv7_decoder_initialize() finished, g_opct.size() = %lld, g_op2t.null_ops=0x%x", (u64)g_opct.size(), g_op2t.null_ops);
} }
u32 ARMv7Decoder::DecodeMemory(const u32 address) u32 ARMv7Decoder::DecodeMemory(const u32 address)

View File

@ -444,20 +444,17 @@ void ARMv7_instrs::ADD_IMM(ARMv7Context& context, const ARMv7Code code, const AR
if (ConditionPassed(context, cond)) if (ConditionPassed(context, cond))
{ {
bool carry, overflow;
const u32 result = AddWithCarry(context.read_gpr(n), imm32, false, carry, overflow);
context.write_gpr(d, result);
if (set_flags) if (set_flags)
{ {
bool carry, overflow; context.APSR.N = result >> 31;
const u32 res = AddWithCarry(context.read_gpr(n), imm32, false, carry, overflow); context.APSR.Z = result == 0;
context.write_gpr(d, res);
context.APSR.N = res >> 31;
context.APSR.Z = res == 0;
context.APSR.C = carry; context.APSR.C = carry;
context.APSR.V = overflow; context.APSR.V = overflow;
} }
else
{
context.write_gpr(d, context.read_gpr(n) + imm32);
}
} }
} }
@ -512,21 +509,18 @@ void ARMv7_instrs::ADD_REG(ARMv7Context& context, const ARMv7Code code, const AR
if (ConditionPassed(context, cond)) if (ConditionPassed(context, cond))
{ {
bool carry, overflow;
const u32 shifted = Shift(context.read_gpr(m), shift_t, shift_n, true); const u32 shifted = Shift(context.read_gpr(m), shift_t, shift_n, true);
const u32 result = AddWithCarry(context.read_gpr(n), shifted, false, carry, overflow);
context.write_gpr(d, result);
if (set_flags) if (set_flags)
{ {
bool carry, overflow; context.APSR.N = result >> 31;
const u32 res = AddWithCarry(context.read_gpr(n), shifted, false, carry, overflow); context.APSR.Z = result == 0;
context.write_gpr(d, res);
context.APSR.N = res >> 31;
context.APSR.Z = res == 0;
context.APSR.C = carry; context.APSR.C = carry;
context.APSR.V = overflow; context.APSR.V = overflow;
} }
else
{
context.write_gpr(d, context.read_gpr(n) + shifted);
}
} }
} }
@ -589,20 +583,17 @@ void ARMv7_instrs::ADD_SPI(ARMv7Context& context, const ARMv7Code code, const AR
if (ConditionPassed(context, cond)) if (ConditionPassed(context, cond))
{ {
bool carry, overflow;
const u32 result = AddWithCarry(context.SP, imm32, false, carry, overflow);
context.write_gpr(d, result);
if (set_flags) if (set_flags)
{ {
bool carry, overflow; context.APSR.N = result >> 31;
const u32 res = AddWithCarry(context.SP, imm32, false, carry, overflow); context.APSR.Z = result == 0;
context.write_gpr(d, res);
context.APSR.N = res >> 31;
context.APSR.Z = res == 0;
context.APSR.C = carry; context.APSR.C = carry;
context.APSR.V = overflow; context.APSR.V = overflow;
} }
else
{
context.write_gpr(d, context.SP + imm32);
}
} }
} }
@ -652,21 +643,18 @@ void ARMv7_instrs::ADD_SPR(ARMv7Context& context, const ARMv7Code code, const AR
if (ConditionPassed(context, cond)) if (ConditionPassed(context, cond))
{ {
bool carry, overflow;
const u32 shifted = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); const u32 shifted = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C);
const u32 result = AddWithCarry(context.SP, shifted, false, carry, overflow);
context.write_gpr(d, result);
if (set_flags) if (set_flags)
{ {
bool carry, overflow; context.APSR.N = result >> 31;
const u32 res = AddWithCarry(context.SP, shifted, false, carry, overflow); context.APSR.Z = result == 0;
context.write_gpr(d, res);
context.APSR.N = res >> 31;
context.APSR.Z = res == 0;
context.APSR.C = carry; context.APSR.C = carry;
context.APSR.V = overflow; context.APSR.V = overflow;
} }
else
{
context.write_gpr(d, context.SP + context.read_gpr(m));
}
} }
} }
@ -1549,7 +1537,7 @@ void ARMv7_instrs::LDRB_IMM(ARMv7Context& context, const ARMv7Code code, const A
cond = context.ITSTATE.advance(); cond = context.ITSTATE.advance();
t = (code.data & 0x7); t = (code.data & 0x7);
n = (code.data & 0x38) >> 3; n = (code.data & 0x38) >> 3;
imm32 = (code.data & 0x7c0) >> 4; imm32 = (code.data & 0x7c0) >> 6;
index = true; index = true;
add = true; add = true;
wback = false; wback = false;
@ -1657,7 +1645,6 @@ void ARMv7_instrs::LDRD_IMM(ARMv7Context& context, const ARMv7Code code, const A
const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32; const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32;
const u32 addr = index ? offset_addr : context.read_gpr(n); const u32 addr = index ? offset_addr : context.read_gpr(n);
const u64 value = vm::psv::read64(addr); const u64 value = vm::psv::read64(addr);
context.write_gpr(t, (u32)(value)); context.write_gpr(t, (u32)(value));
context.write_gpr(t2, (u32)(value >> 32)); context.write_gpr(t2, (u32)(value >> 32));
@ -1670,11 +1657,35 @@ void ARMv7_instrs::LDRD_IMM(ARMv7Context& context, const ARMv7Code code, const A
void ARMv7_instrs::LDRD_LIT(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) void ARMv7_instrs::LDRD_LIT(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
{ {
u32 cond, t, t2, imm32;
bool add;
switch (type) switch (type)
{ {
case T1:
{
cond = context.ITSTATE.advance();
t = (code.data & 0xf000) >> 12;
t2 = (code.data & 0xf00) >> 8;
imm32 = (code.data & 0xff) << 2;
add = (code.data & 0x800000);
reject(!(code.data & 0x1000000), "Related encodings"); // ???
reject(t == 13 || t == 15 || t2 == 13 || t2 == 15 || t == t2, "UNPREDICTABLE");
break;
}
case A1: throw __FUNCTION__; case A1: throw __FUNCTION__;
default: 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 u64 value = vm::psv::read64(addr);
context.write_gpr(t, (u32)(value));
context.write_gpr(t2, (u32)(value >> 32));
}
} }
void ARMv7_instrs::LDRD_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) void ARMv7_instrs::LDRD_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
@ -1689,11 +1700,70 @@ void ARMv7_instrs::LDRD_REG(ARMv7Context& context, const ARMv7Code code, const A
void ARMv7_instrs::LDRH_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) void ARMv7_instrs::LDRH_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
{ {
u32 cond, t, n, imm32;
bool index, add, wback;
switch (type) switch (type)
{ {
case T1:
{
cond = context.ITSTATE.advance();
t = (code.data & 0x7);
n = (code.data & 0x38) >> 3;
imm32 = (code.data & 0x7c0) >> 5;
index = true;
add = true;
wback = false;
break;
}
case T2:
{
cond = context.ITSTATE.advance();
t = (code.data & 0xf000) >> 12;
n = (code.data & 0xf0000) >> 16;
imm32 = (code.data & 0xfff);
index = true;
add = true;
wback = false;
reject(t == 15, "Unallocated memory hints");
reject(n == 15, "LDRH (literal)");
reject(t == 13, "UNPREDICTABLE");
break;
}
case T3:
{
cond = context.ITSTATE.advance();
t = (code.data & 0xf000) >> 12;
n = (code.data & 0xf0000) >> 16;
imm32 = (code.data & 0xff);
index = (code.data & 0x400);
add = (code.data & 0x200);
wback = (code.data & 0x100);
reject(n == 15, "LDRH (literal)");
reject(t == 15 && index && !add && !wback, "Unallocated memory hints");
reject(index && add && !wback, "LDRHT");
reject(!index && !wback, "UNDEFINED");
reject(t == 13 || t == 15 || (wback && n == t), "UNPREDICTABLE");
break;
}
case A1: throw __FUNCTION__; case A1: throw __FUNCTION__;
default: throw __FUNCTION__; default: throw __FUNCTION__;
} }
if (ConditionPassed(context, cond))
{
const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32;
const u32 addr = index ? offset_addr : context.read_gpr(n);
context.write_gpr(t, vm::psv::read16(addr));
if (wback)
{
context.write_gpr(n, offset_addr);
}
}
} }
void ARMv7_instrs::LDRH_LIT(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) void ARMv7_instrs::LDRH_LIT(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
@ -1891,7 +1961,7 @@ void ARMv7_instrs::LSL_IMM(ARMv7Context& context, const ARMv7Code code, const AR
cond = context.ITSTATE.advance(); cond = context.ITSTATE.advance();
d = (code.data & 0x7); d = (code.data & 0x7);
m = (code.data & 0x38) >> 3; m = (code.data & 0x38) >> 3;
shift_n = (code.data & 0x7c0) >> 6; DecodeImmShift(0, (code.data & 0x7c0) >> 6, &shift_n);
reject(!shift_n, "MOV (register)"); reject(!shift_n, "MOV (register)");
break; break;
@ -1902,7 +1972,7 @@ void ARMv7_instrs::LSL_IMM(ARMv7Context& context, const ARMv7Code code, const AR
d = (code.data & 0xf00) >> 8; d = (code.data & 0xf00) >> 8;
m = (code.data & 0xf); m = (code.data & 0xf);
set_flags = (code.data & 0x100000); set_flags = (code.data & 0x100000);
shift_n = (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6; DecodeImmShift(0, (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6, &shift_n);
reject(!shift_n, "MOV (register)"); reject(!shift_n, "MOV (register)");
reject(d == 13 || d == 15 || m == 13 || m == 15, "UNPREDICTABLE"); reject(d == 13 || d == 15 || m == 13 || m == 15, "UNPREDICTABLE");
@ -1917,6 +1987,7 @@ void ARMv7_instrs::LSL_IMM(ARMv7Context& context, const ARMv7Code code, const AR
bool carry; bool carry;
const u32 res = Shift_C(context.read_gpr(m), SRType_LSL, shift_n, context.APSR.C, carry); const u32 res = Shift_C(context.read_gpr(m), SRType_LSL, shift_n, context.APSR.C, carry);
context.write_gpr(d, res); context.write_gpr(d, res);
if (set_flags) if (set_flags)
{ {
context.APSR.N = res >> 31; context.APSR.N = res >> 31;
@ -1960,6 +2031,7 @@ void ARMv7_instrs::LSL_REG(ARMv7Context& context, const ARMv7Code code, const AR
bool carry; bool carry;
const u32 res = Shift_C(context.read_gpr(n), SRType_LSL, (context.read_gpr(m) & 0xff), context.APSR.C, carry); const u32 res = Shift_C(context.read_gpr(n), SRType_LSL, (context.read_gpr(m) & 0xff), context.APSR.C, carry);
context.write_gpr(d, res); context.write_gpr(d, res);
if (set_flags) if (set_flags)
{ {
context.APSR.N = res >> 31; context.APSR.N = res >> 31;
@ -1972,11 +2044,47 @@ void ARMv7_instrs::LSL_REG(ARMv7Context& context, const ARMv7Code code, const AR
void ARMv7_instrs::LSR_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) void ARMv7_instrs::LSR_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
{ {
bool set_flags = !context.ITSTATE;
u32 cond, d, m, shift_n;
switch (type) switch (type)
{ {
case T1:
{
cond = context.ITSTATE.advance();
d = (code.data & 0x7);
m = (code.data & 0x38) >> 3;
DecodeImmShift(1, (code.data & 0x7c0) >> 6, &shift_n);
break;
}
case T2:
{
cond = context.ITSTATE.advance();
d = (code.data & 0xf00) >> 8;
m = (code.data & 0xf);
set_flags = (code.data & 0x100000);
DecodeImmShift(1, (code.data & 0x7000) >> 10 | (code.data & 0xc0) >> 6, &shift_n);
reject(d == 13 || d == 15 || m == 13 || m == 15, "UNPREDICTABLE");
break;
}
case A1: throw __FUNCTION__; case A1: throw __FUNCTION__;
default: throw __FUNCTION__; default: throw __FUNCTION__;
} }
if (ConditionPassed(context, cond))
{
bool carry;
const u32 result = Shift_C(context.read_gpr(m), SRType_LSR, shift_n, context.APSR.C, carry);
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::LSR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) void ARMv7_instrs::LSR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
@ -2049,6 +2157,7 @@ void ARMv7_instrs::MOV_IMM(ARMv7Context& context, const ARMv7Code code, const AR
if (ConditionPassed(context, cond)) if (ConditionPassed(context, cond))
{ {
context.write_gpr(d, imm32); context.write_gpr(d, imm32);
if (set_flags) if (set_flags)
{ {
context.APSR.N = imm32 >> 31; context.APSR.N = imm32 >> 31;
@ -2102,12 +2211,13 @@ void ARMv7_instrs::MOV_REG(ARMv7Context& context, const ARMv7Code code, const AR
if (ConditionPassed(context, cond)) if (ConditionPassed(context, cond))
{ {
const u32 res = context.read_gpr(m); const u32 result = context.read_gpr(m);
context.write_gpr(d, res); context.write_gpr(d, result);
if (set_flags) if (set_flags)
{ {
context.APSR.N = res >> 31; context.APSR.N = result >> 31;
context.APSR.Z = res == 0; context.APSR.Z = result == 0;
//context.APSR.C = ? //context.APSR.C = ?
} }
} }
@ -2319,11 +2429,39 @@ void ARMv7_instrs::ORN_REG(ARMv7Context& context, const ARMv7Code code, const AR
void ARMv7_instrs::ORR_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) void ARMv7_instrs::ORR_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
{ {
u32 cond, d, n, imm32;
bool set_flags, carry = context.APSR.C;
switch (type) 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(n == 15, "MOV (immediate)");
reject(d == 13 || d == 15 || n == 13, "UNPREDICTABLE");
break;
}
case A1: throw __FUNCTION__; case A1: throw __FUNCTION__;
default: 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::ORR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) void ARMv7_instrs::ORR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
@ -3252,7 +3390,7 @@ void ARMv7_instrs::STRB_IMM(ARMv7Context& context, const ARMv7Code code, const A
cond = context.ITSTATE.advance(); cond = context.ITSTATE.advance();
t = (code.data & 0x7); t = (code.data & 0x7);
n = (code.data & 0x38) >> 3; n = (code.data & 0x38) >> 3;
imm32 = (code.data & 0x7c0) >> 4; imm32 = (code.data & 0x7c0) >> 6;
index = true; index = true;
add = true; add = true;
wback = false; wback = false;
@ -3363,11 +3501,43 @@ void ARMv7_instrs::STRB_REG(ARMv7Context& context, const ARMv7Code code, const A
void ARMv7_instrs::STRD_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) void ARMv7_instrs::STRD_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
{ {
u32 cond, t, t2, n, imm32;
bool index, add, wback;
switch (type) switch (type)
{ {
case T1:
{
cond = context.ITSTATE.advance();
t = (code.data & 0xf000) >> 12;
t2 = (code.data & 0xf00) >> 8;
n = (code.data & 0xf0000) >> 16;
imm32 = (code.data & 0xff) << 2;
index = (code.data & 0x1000000);
add = (code.data & 0x800000);
wback = (code.data & 0x200000);
reject(!index && !wback, "Related encodings");
reject(wback && (n == t || n == t2), "UNPREDICTABLE");
reject(n == 15 || t == 13 || t == 15 || t2 == 13 || t2 == 15, "UNPREDICTABLE");
break;
}
case A1: throw __FUNCTION__; case A1: throw __FUNCTION__;
default: throw __FUNCTION__; default: throw __FUNCTION__;
} }
if (ConditionPassed(context, cond))
{
const u32 n_value = context.read_gpr(n);
const u32 offset = add ? n_value + imm32 : n_value - imm32;
const u32 addr = index ? offset : n_value;
vm::psv::write64(addr, (u64)context.read_gpr(t2) << 32 | context.read_gpr(t));
if (wback)
{
context.write_gpr(n, offset);
}
}
} }
void ARMv7_instrs::STRD_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) void ARMv7_instrs::STRD_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
@ -3382,11 +3552,67 @@ void ARMv7_instrs::STRD_REG(ARMv7Context& context, const ARMv7Code code, const A
void ARMv7_instrs::STRH_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) void ARMv7_instrs::STRH_IMM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
{ {
u32 cond, t, n, imm32;
bool index, add, wback;
switch (type) switch (type)
{ {
case T1:
{
cond = context.ITSTATE.advance();
t = (code.data & 0x7);
n = (code.data & 0x38) >> 3;
imm32 = (code.data & 0x7c0) >> 5;
index = true;
add = true;
wback = false;
break;
}
case T2:
{
cond = context.ITSTATE.advance();
t = (code.data & 0xf000) >> 12;
n = (code.data & 0xf0000) >> 16;
imm32 = (code.data & 0xfff);
index = true;
add = true;
wback = false;
reject(n == 15, "UNDEFINED");
reject(t == 13 || t == 15, "UNPREDICTABLE");
break;
}
case T3:
{
cond = context.ITSTATE.advance();
t = (code.data & 0xf000) >> 12;
n = (code.data & 0xf0000) >> 16;
imm32 = (code.data & 0xff);
index = (code.data & 0x400);
add = (code.data & 0x200);
wback = (code.data & 0x100);
reject(index && add && !wback, "STRHT");
reject(n == 15 || (!index && !wback), "UNDEFINED");
reject(t == 13 || t == 15 || (wback && n == t), "UNPREDICTABLE");
break;
}
case A1: throw __FUNCTION__; case A1: throw __FUNCTION__;
default: throw __FUNCTION__; default: throw __FUNCTION__;
} }
if (ConditionPassed(context, cond))
{
const u32 offset_addr = add ? context.read_gpr(n) + imm32 : context.read_gpr(n) - imm32;
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);
}
}
} }
void ARMv7_instrs::STRH_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) void ARMv7_instrs::STRH_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
@ -3560,20 +3786,17 @@ void ARMv7_instrs::SUB_IMM(ARMv7Context& context, const ARMv7Code code, const AR
if (ConditionPassed(context, cond)) 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) if (set_flags)
{ {
bool carry, overflow; context.APSR.N = result >> 31;
const u32 res = AddWithCarry(context.read_gpr(n), ~imm32, true, carry, overflow); context.APSR.Z = result == 0;
context.write_gpr(d, res);
context.APSR.N = res >> 31;
context.APSR.Z = res == 0;
context.APSR.C = carry; context.APSR.C = carry;
context.APSR.V = overflow; context.APSR.V = overflow;
} }
else
{
context.write_gpr(d, context.read_gpr(n) - imm32);
}
} }
} }
@ -3614,21 +3837,18 @@ void ARMv7_instrs::SUB_REG(ARMv7Context& context, const ARMv7Code code, const AR
if (ConditionPassed(context, cond)) if (ConditionPassed(context, cond))
{ {
bool carry, overflow;
const u32 shifted = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C); const u32 shifted = Shift(context.read_gpr(m), shift_t, shift_n, context.APSR.C);
const u32 result = AddWithCarry(context.read_gpr(n), ~shifted, true, carry, overflow);
context.write_gpr(d, result);
if (set_flags) if (set_flags)
{ {
bool carry, overflow; context.APSR.N = result >> 31;
const u32 res = AddWithCarry(context.read_gpr(n), ~shifted, true, carry, overflow); context.APSR.Z = result == 0;
context.write_gpr(d, res);
context.APSR.N = res >> 31;
context.APSR.Z = res == 0;
context.APSR.C = carry; context.APSR.C = carry;
context.APSR.V = overflow; context.APSR.V = overflow;
} }
else
{
context.write_gpr(d, context.read_gpr(n) - shifted);
}
} }
} }
@ -3683,20 +3903,17 @@ void ARMv7_instrs::SUB_SPI(ARMv7Context& context, const ARMv7Code code, const AR
if (ConditionPassed(context, cond)) if (ConditionPassed(context, cond))
{ {
bool carry, overflow;
const u32 result = AddWithCarry(context.SP, ~imm32, true, carry, overflow);
context.write_gpr(d, result);
if (set_flags) if (set_flags)
{ {
bool carry, overflow; context.APSR.N = result >> 31;
const u32 res = AddWithCarry(context.SP, ~imm32, true, carry, overflow); context.APSR.Z = result == 0;
context.write_gpr(d, res);
context.APSR.N = res >> 31;
context.APSR.Z = res == 0;
context.APSR.C = carry; context.APSR.C = carry;
context.APSR.V = overflow; context.APSR.V = overflow;
} }
else
{
context.write_gpr(d, context.SP - imm32);
}
} }
} }
@ -3960,11 +4177,40 @@ void ARMv7_instrs::UMLAL(ARMv7Context& context, const ARMv7Code code, const ARMv
void ARMv7_instrs::UMULL(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) void ARMv7_instrs::UMULL(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
{ {
u32 cond, d0, d1, n, m;
bool set_flags;
switch (type) switch (type)
{ {
case T1:
{
cond = context.ITSTATE.advance();
d0 = (code.data & 0xf000) >> 12;
d1 = (code.data & 0xf00) >> 8;
n = (code.data & 0xf0000) >> 16;
m = (code.data & 0xf);
set_flags = false;
reject(d0 == 13 || d0 == 15 || d1 == 13 || d1 == 15 || n == 13 || n == 15 || m == 13 || m == 15, "UNPREDICTABLE");
reject(d0 == d1, "UNPREDICTABLE");
break;
}
case A1: throw __FUNCTION__; case A1: throw __FUNCTION__;
default: throw __FUNCTION__; default: throw __FUNCTION__;
} }
if (ConditionPassed(context, cond))
{
const u64 result = (u64)context.read_gpr(n) * (u64)context.read_gpr(m);
context.write_gpr(d1, (u32)(result >> 32));
context.write_gpr(d0, (u32)(result));
if (set_flags)
{
context.APSR.N = result >> 63 != 0;
context.APSR.Z = result == 0;
}
}
} }
void ARMv7_instrs::UQADD16(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type) void ARMv7_instrs::UQADD16(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)

View File

@ -2,7 +2,6 @@
struct psv_event_flag_t struct psv_event_flag_t
{ {
s32 id;
char name[32]; char name[32];
u32 attr; u32 attr;
u32 pattern; u32 pattern;
@ -17,6 +16,9 @@ private:
public: public:
psv_event_flag_t(const char* name, u32 attr, u32 pattern); psv_event_flag_t(const char* name, u32 attr, u32 pattern);
void on_init(s32 id) {}
void on_stop() {}
}; };
extern psv_object_list_t<psv_event_flag_t, SCE_KERNEL_THREADMGR_UID_CLASS_EVENT_FLAG> g_psv_ef_list; extern psv_object_list_t<psv_event_flag_t, SCE_KERNEL_THREADMGR_UID_CLASS_EVENT_FLAG> g_psv_ef_list;

View File

@ -2,7 +2,6 @@
struct psv_sema_t struct psv_sema_t
{ {
s32 id;
char name[32]; char name[32];
u32 attr; u32 attr;
s32 value; s32 value;
@ -18,6 +17,8 @@ private:
public: public:
psv_sema_t(const char* name, u32 attr, s32 init_value, s32 max_value); psv_sema_t(const char* name, u32 attr, s32 init_value, s32 max_value);
void on_init(s32 id) {}
void on_stop() {}
}; };

View File

@ -6,21 +6,21 @@ extern psv_log_base sceSysmodule;
s32 sceSysmoduleLoadModule(u16 id) s32 sceSysmoduleLoadModule(u16 id)
{ {
sceSysmodule.Error("sceSysmoduleLoadModule(id=0x%04x) -> SCE_OK", id); sceSysmodule.Warning("sceSysmoduleLoadModule(id=0x%04x) -> SCE_OK", id);
return SCE_OK; // loading succeeded return SCE_OK; // loading succeeded
} }
s32 sceSysmoduleUnloadModule(u16 id) s32 sceSysmoduleUnloadModule(u16 id)
{ {
sceSysmodule.Error("sceSysmoduleUnloadModule(id=0x%04x) -> SCE_OK", id); sceSysmodule.Warning("sceSysmoduleUnloadModule(id=0x%04x) -> SCE_OK", id);
return SCE_OK; // unloading succeeded return SCE_OK; // unloading succeeded
} }
s32 sceSysmoduleIsLoaded(u16 id) s32 sceSysmoduleIsLoaded(u16 id)
{ {
sceSysmodule.Error("sceSysmoduleIsLoaded(id=0x%04x) -> SCE_OK", id); sceSysmodule.Warning("sceSysmoduleIsLoaded(id=0x%04x) -> SCE_OK", id);
return SCE_OK; // module is loaded return SCE_OK; // module is loaded
} }

View File

@ -80,7 +80,7 @@ public:
psv_uid_t id = psv_uid_t::make(1); // odd number psv_uid_t id = psv_uid_t::make(1); // odd number
id.type = uid_class; // set type id.type = uid_class; // set type
id.number = j; // set position id.number = j; // set position
data->id = id.uid; // save UID data->on_init(id.uid); // save UID
return id.uid; // return UID return id.uid; // return UID
} }
} }
@ -111,9 +111,14 @@ public:
{ {
std::lock_guard<std::mutex> lock(m_mutex); std::lock_guard<std::mutex> lock(m_mutex);
for (auto& value : m_data) for (auto& object : m_data)
{ {
value = nullptr; if (object)
{
object->on_stop();
}
object = nullptr;
} }
m_hint = 0; m_hint = 0;