mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 11:36:13 +00:00
ARMv7: new instructions
EOR_IMM, LDM, REV, STM
This commit is contained in:
parent
e93aaf3957
commit
5983813d12
2 changed files with 177 additions and 15 deletions
|
@ -1281,7 +1281,7 @@ void armv7_decoder_initialize(u32 addr, u32 end_addr, bool dump)
|
|||
const u32 i2 = (code.data >> 11) & 0x1 ^ s ^ 1;
|
||||
const u32 target = (addr + 4 & ~3) + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (code.data & 0x3ff0000) >> 4 | (code.data & 0x7ff) << 1);
|
||||
|
||||
const u32 instr = vm::psv::read32(target);
|
||||
const u32 instr = Memory.IsGoodAddr(target, 4) ? vm::psv::read32(target) : 0;
|
||||
|
||||
// possibly a call to imported function:
|
||||
if (target >= end_addr && ((target - end_addr) % 16) == 0 && (instr & 0xfff000f0) == 0xe0700090)
|
||||
|
|
|
@ -1574,7 +1574,7 @@ void ARMv7_instrs::CLZ(ARMv7Context& context, const ARMv7Code code, const ARMv7_
|
|||
d = (code.data & 0xf00) >> 8;
|
||||
m = (code.data & 0xf);
|
||||
|
||||
reject((code.data & 0xf0000) >> 16 != m, "UNPREDICTABLE");
|
||||
reject(m != (code.data & 0xf0000) >> 16, "UNPREDICTABLE");
|
||||
reject(d == 13 || d == 15 || m == 13 || m == 15, "UNPREDICTABLE");
|
||||
break;
|
||||
}
|
||||
|
@ -1772,11 +1772,45 @@ void ARMv7_instrs::DSB(ARMv7Context& context, const ARMv7Code code, const ARMv7_
|
|||
|
||||
void ARMv7_instrs::EOR_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 == 15 && set_flags, "TEQ (immediate)");
|
||||
reject(d == 13 || d == 15 || n == 13 || n == 15, "UNPREDICTABLE");
|
||||
break;
|
||||
}
|
||||
case A1: throw __FUNCTION__;
|
||||
default: throw __FUNCTION__;
|
||||
}
|
||||
|
||||
if (context.debug)
|
||||
{
|
||||
if (context.debug & DF_DISASM) context.debug_str = fmt::format("eor%s%s %s,%s,#0x%X", set_flags ? "s" : "", fmt_cond(cond), fmt_reg(d), fmt_reg(n), imm32);
|
||||
if (process_debug(context)) return;
|
||||
}
|
||||
|
||||
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::EOR_REG(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
|
||||
|
@ -1855,7 +1889,7 @@ void ARMv7_instrs::IT(ARMv7Context& context, const ARMv7Code code, const ARMv7_e
|
|||
|
||||
reject(mask == 0, "Related encodings");
|
||||
reject(first == 15, "UNPREDICTABLE");
|
||||
reject(first == 14 && BitCount(mask) != 1, "UNPREDICTABLE");
|
||||
reject(first == 14 && BitCount(mask, 4) != 1, "UNPREDICTABLE");
|
||||
reject(context.ITSTATE, "UNPREDICTABLE");
|
||||
|
||||
context.ITSTATE.IT = code.data & 0xff;
|
||||
|
@ -1874,11 +1908,61 @@ void ARMv7_instrs::IT(ARMv7Context& context, const ARMv7Code code, const ARMv7_e
|
|||
|
||||
void ARMv7_instrs::LDM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
|
||||
{
|
||||
u32 cond, n, reg_list;
|
||||
bool wback;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case T1:
|
||||
{
|
||||
cond = context.ITSTATE.advance();
|
||||
n = (code.data & 0x700) >> 8;
|
||||
reg_list = (code.data & 0xff);
|
||||
wback = !(reg_list & (1 << n));
|
||||
|
||||
reject(reg_list == 0, "UNPREDICTABLE");
|
||||
break;
|
||||
}
|
||||
case T2:
|
||||
{
|
||||
cond = context.ITSTATE.advance();
|
||||
n = (code.data & 0xf0000) >> 16;
|
||||
reg_list = (code.data & 0xdfff);
|
||||
wback = (code.data & 0x200000);
|
||||
|
||||
reject(wback && n == 13, "POP");
|
||||
reject(n == 15 || BitCount(reg_list, 16) < 2 || reg_list >= 0xc000, "UNPREDICTABLE");
|
||||
reject(reg_list & 0x8000 && context.ITSTATE, "UNPREDICTABLE");
|
||||
reject(wback && reg_list & (1 << n), "UNPREDICTABLE");
|
||||
break;
|
||||
}
|
||||
case A1: throw __FUNCTION__;
|
||||
default: throw __FUNCTION__;
|
||||
}
|
||||
|
||||
if (context.debug)
|
||||
{
|
||||
if (context.debug & DF_DISASM) context.debug_str = fmt::format("ldm%s %s%s,{%s}", fmt_cond(cond), fmt_reg(n), wback ? "!" : "", fmt_reg_list(reg_list));
|
||||
if (process_debug(context)) return;
|
||||
}
|
||||
|
||||
if (ConditionPassed(context, cond))
|
||||
{
|
||||
auto memory = vm::psv::ptr<u32>::make(context.read_gpr(n));
|
||||
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
{
|
||||
if (reg_list & (1 << i))
|
||||
{
|
||||
context.write_gpr(i, *memory++);
|
||||
}
|
||||
}
|
||||
|
||||
if (wback)
|
||||
{
|
||||
context.write_gpr(n, memory.addr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv7_instrs::LDMDA(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
|
||||
|
@ -3369,17 +3453,17 @@ void ARMv7_instrs::POP(ARMv7Context& context, const ARMv7Code code, const ARMv7_
|
|||
|
||||
if (ConditionPassed(context, cond))
|
||||
{
|
||||
u32 written = 0;
|
||||
for (u16 mask = 1, i = 0; mask; mask <<= 1, i++)
|
||||
auto stack = vm::psv::ptr<u32>::make(context.SP);
|
||||
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
{
|
||||
if (reg_list & mask)
|
||||
if (reg_list & (1 << i))
|
||||
{
|
||||
context.write_gpr(i, vm::psv::read32(context.SP + written));
|
||||
written += 4;
|
||||
context.write_gpr(i, *stack++);
|
||||
}
|
||||
}
|
||||
|
||||
context.SP += written;
|
||||
context.SP = stack.addr();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3440,17 +3524,17 @@ void ARMv7_instrs::PUSH(ARMv7Context& context, const ARMv7Code code, const ARMv7
|
|||
|
||||
if (ConditionPassed(context, cond))
|
||||
{
|
||||
u32 read = 0;
|
||||
for (u16 mask = 1 << 15, i = 15; mask; mask >>= 1, i--)
|
||||
auto memory = vm::psv::ptr<u32>::make(context.SP);
|
||||
|
||||
for (u32 i = 15; ~i; i--)
|
||||
{
|
||||
if (reg_list & mask)
|
||||
if (reg_list & (1 << i))
|
||||
{
|
||||
read += 4;
|
||||
vm::psv::write32(context.SP - read, context.read_gpr(i));
|
||||
*--memory = context.read_gpr(i);
|
||||
}
|
||||
}
|
||||
|
||||
context.SP -= read;
|
||||
context.SP = memory.addr();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3557,11 +3641,41 @@ void ARMv7_instrs::RBIT(ARMv7Context& context, const ARMv7Code code, const ARMv7
|
|||
|
||||
void ARMv7_instrs::REV(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
|
||||
{
|
||||
u32 cond, d, m;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case T1:
|
||||
{
|
||||
cond = context.ITSTATE.advance();
|
||||
d = (code.data & 0x7);
|
||||
m = (code.data & 0x38) >> 3;
|
||||
break;
|
||||
}
|
||||
case T2:
|
||||
{
|
||||
cond = context.ITSTATE.advance();
|
||||
d = (code.data & 0xf00) >> 8;
|
||||
m = (code.data & 0xf);
|
||||
|
||||
reject(m != (code.data & 0xf0000) >> 16, "UNPREDICTABLE");
|
||||
reject(d == 13 || d == 15 || m == 13 || m == 15, "UNPREDICTABLE");
|
||||
break;
|
||||
}
|
||||
case A1: throw __FUNCTION__;
|
||||
default: throw __FUNCTION__;
|
||||
}
|
||||
|
||||
if (context.debug)
|
||||
{
|
||||
if (context.debug & DF_DISASM) context.debug_str = fmt::format("rev%s %s,%s", fmt_cond(cond), fmt_reg(d), fmt_reg(m));
|
||||
if (process_debug(context)) return;
|
||||
}
|
||||
|
||||
if (ConditionPassed(context, cond))
|
||||
{
|
||||
context.write_gpr(d, re32(context.read_gpr(m)));
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv7_instrs::REV16(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
|
||||
|
@ -4122,11 +4236,59 @@ void ARMv7_instrs::SSUB8(ARMv7Context& context, const ARMv7Code code, const ARMv
|
|||
|
||||
void ARMv7_instrs::STM(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
|
||||
{
|
||||
u32 cond, n, reg_list;
|
||||
bool wback;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case T1:
|
||||
{
|
||||
cond = context.ITSTATE.advance();
|
||||
n = (code.data & 0x700) >> 8;
|
||||
reg_list = (code.data & 0xff);
|
||||
wback = true;
|
||||
|
||||
reject(reg_list == 0, "UNPREDICTABLE");
|
||||
break;
|
||||
}
|
||||
case T2:
|
||||
{
|
||||
cond = context.ITSTATE.advance();
|
||||
n = (code.data & 0xf0000) >> 16;
|
||||
reg_list = (code.data & 0x5fff);
|
||||
wback = (code.data & 0x200000);
|
||||
|
||||
reject(n == 15 || BitCount(reg_list, 16) < 2, "UNPREDICTABLE");
|
||||
reject(wback && reg_list & (1 << n), "UNPREDICTABLE");
|
||||
break;
|
||||
}
|
||||
case A1: throw __FUNCTION__;
|
||||
default: throw __FUNCTION__;
|
||||
}
|
||||
|
||||
if (context.debug)
|
||||
{
|
||||
if (context.debug & DF_DISASM) context.debug_str = fmt::format("stm%s %s%s,{%s}", fmt_cond(cond), fmt_reg(n), wback ? "!" : "", fmt_reg_list(reg_list));
|
||||
if (process_debug(context)) return;
|
||||
}
|
||||
|
||||
if (ConditionPassed(context, cond))
|
||||
{
|
||||
auto memory = vm::psv::ptr<u32>::make(context.read_gpr(n));
|
||||
|
||||
for (u32 i = 0; i < 16; i++)
|
||||
{
|
||||
if (reg_list & (1 << i))
|
||||
{
|
||||
*memory++ = context.read_gpr(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (wback)
|
||||
{
|
||||
context.write_gpr(n, memory.addr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv7_instrs::STMDA(ARMv7Context& context, const ARMv7Code code, const ARMv7_encoding type)
|
||||
|
|
Loading…
Add table
Reference in a new issue