mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-22 12:35:21 +00:00
Tiny ARMv7 interpreter update
This commit is contained in:
parent
0f602e0e13
commit
bf6415accd
9 changed files with 509 additions and 219 deletions
|
@ -13,125 +13,22 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
u32 branchTarget(u32 imm)
|
||||
{
|
||||
return imm << 1;
|
||||
}
|
||||
|
||||
virtual u8 DecodeMemory(const u32 address)
|
||||
{
|
||||
using namespace ARMv7_opcodes;
|
||||
const u16 code0 = vm::psv::read16(address);
|
||||
const u16 code1 = vm::psv::read16(address + 2);
|
||||
const u32 code0 = vm::psv::read16(address & ~1);
|
||||
const u32 code1 = vm::psv::read16(address + 2 & ~1);
|
||||
const u32 data = code0 << 16 | code1;
|
||||
|
||||
switch(code0 >> 12) //15 - 12
|
||||
for (auto& opcode : ARMv7_opcode_table)
|
||||
{
|
||||
case T1_CBZ:
|
||||
switch((code0 >> 10) & 0x1)
|
||||
if ((opcode.type >= A1) == ((address & 1) == 0) && (data & opcode.mask) == opcode.code)
|
||||
{
|
||||
case 0:
|
||||
switch((code0 >> 8) & 0x1)
|
||||
{
|
||||
case 1:
|
||||
m_op.CBZ((code0 >> 11) & 0x1, branchTarget((((code0 >> 9) & 0x1) << 5) | ((code0 >> 3) & 0x1f)), code0 & 0x7, 2);
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case T1_B:
|
||||
m_op.B((code0 >> 8) & 0xf, branchTarget(code0 & 0xff), 2);
|
||||
return 2;
|
||||
}
|
||||
|
||||
switch(code0 >> 11) //15 - 11
|
||||
{
|
||||
case T2_B:
|
||||
m_op.B(0xf, branchTarget(code0 & 0xfff), 2);
|
||||
return 2;
|
||||
|
||||
case T3_B:
|
||||
{
|
||||
u8 S = (code0 >> 10) & 0x1;
|
||||
u8 J1 = (code1 >> 13) & 0x1;
|
||||
u8 J2 = (code1 >> 11) & 0x1;
|
||||
u8 I1 = 1 - (J1 ^ S);
|
||||
u8 I2 = 1 - (J2 ^ S);
|
||||
u16 imm11 = code1 & 0x7ff;
|
||||
u32 imm32 = 0;
|
||||
|
||||
switch(code1 >> 14)
|
||||
{
|
||||
case 2: //B
|
||||
{
|
||||
u8 cond;
|
||||
switch((code1 >> 12) & 0x1)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
cond = (code0 >> 6) & 0xf;
|
||||
u32 imm6 = code0 & 0x3f;
|
||||
imm32 = sign<19, u32>((S << 19) | (I1 << 18) | (I2 << 17) | (imm6 << 11) | imm11);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
cond = 0xf;
|
||||
u32 imm10 = code0 & 0x7ff;
|
||||
imm32 = sign<23, u32>((S << 23) | (I1 << 22) | (I2 << 21) | (imm10 << 11) | imm11);
|
||||
break;
|
||||
}
|
||||
|
||||
m_op.B(cond, branchTarget(imm32), 4);
|
||||
}
|
||||
return 4;
|
||||
|
||||
case 3: //BL
|
||||
switch((code1 >> 12) & 0x1)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case 1:
|
||||
u32 imm10 = code0 & 0x7ff;
|
||||
imm32 = sign<23, u32>((S << 23) | (I1 << 22) | (I2 << 21) | (imm10 << 11) | imm11);
|
||||
m_op.BL(branchTarget(imm32), 4);
|
||||
return 4;
|
||||
}
|
||||
break;
|
||||
(m_op.*opcode.func)(opcode.length == 2 ? code0 : data, opcode.type);
|
||||
return opcode.length;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch(code0 >> 9)
|
||||
{
|
||||
case T1_PUSH:
|
||||
m_op.PUSH((((code0 >> 8) & 0x1) << 14) | (code0 & 0xff));
|
||||
return 2;
|
||||
|
||||
case T1_POP:
|
||||
m_op.POP((((code0 >> 8) & 0x1) << 15) | (code0 & 0xff));
|
||||
return 2;
|
||||
}
|
||||
|
||||
switch(code0)
|
||||
{
|
||||
case T2_PUSH:
|
||||
m_op.PUSH(code1);
|
||||
return 4;
|
||||
|
||||
case T2_POP:
|
||||
m_op.POP(code1);
|
||||
return 4;
|
||||
|
||||
case T1_NOP:
|
||||
m_op.NOP();
|
||||
return 2;
|
||||
}
|
||||
|
||||
m_op.UNK(code0, code1);
|
||||
m_op.UNK(data);
|
||||
return 2;
|
||||
}
|
||||
};
|
||||
|
|
92
rpcs3/Emu/ARMv7/ARMv7DisAsm.cpp
Normal file
92
rpcs3/Emu/ARMv7/ARMv7DisAsm.cpp
Normal file
|
@ -0,0 +1,92 @@
|
|||
#include "stdafx.h"
|
||||
#include "ARMv7DisAsm.h"
|
||||
|
||||
void ARMv7DisAsm::UNK(const u32 data)
|
||||
{
|
||||
Write("Unknown/illegal opcode");
|
||||
}
|
||||
|
||||
void ARMv7DisAsm::NULL_OP(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
Write("NULL");
|
||||
}
|
||||
|
||||
void ARMv7DisAsm::PUSH(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
Write("PUSH...");
|
||||
//Write(fmt::Format("push {%s}", GetRegsListString(regs_list).c_str()));
|
||||
}
|
||||
|
||||
void ARMv7DisAsm::POP(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
Write("POP...");
|
||||
//Write(fmt::Format("pop {%s}", GetRegsListString(regs_list).c_str()));
|
||||
}
|
||||
|
||||
void ARMv7DisAsm::NOP(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
Write("NOP");
|
||||
}
|
||||
|
||||
void ARMv7DisAsm::B(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
Write("B...");
|
||||
//if ((cond & 0xe) == 0xe)
|
||||
//{
|
||||
// Write(fmt::Format("b 0x%x", DisAsmBranchTarget(imm) + intstr_size));
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// Write(fmt::Format("b[%s] 0x%x", g_arm_cond_name[cond], DisAsmBranchTarget(imm) + intstr_size));
|
||||
//}
|
||||
}
|
||||
|
||||
void ARMv7DisAsm::CBZ(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
Write("CBZ...");
|
||||
//Write(fmt::Format("cbz 0x%x,%s", DisAsmBranchTarget(imm) + intstr_size, g_arm_reg_name[rn]));
|
||||
}
|
||||
|
||||
void ARMv7DisAsm::CBNZ(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
Write("CBNZ...");
|
||||
//Write(fmt::Format("cbnz 0x%x,%s", DisAsmBranchTarget(imm) + intstr_size, g_arm_reg_name[rn]));
|
||||
}
|
||||
|
||||
void ARMv7DisAsm::BL(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
Write("BL...");
|
||||
//Write(fmt::Format("bl 0x%x", DisAsmBranchTarget(imm) + intstr_size));
|
||||
}
|
||||
|
||||
void ARMv7DisAsm::BLX(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
Write("BLX...");
|
||||
//Write(fmt::Format("bl 0x%x", DisAsmBranchTarget(imm) + intstr_size));
|
||||
}
|
||||
|
||||
void ARMv7DisAsm::SUB_IMM(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
Write("SUB...");
|
||||
}
|
||||
|
||||
void ARMv7DisAsm::SUB_REG(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
Write("SUB...");
|
||||
}
|
||||
|
||||
void ARMv7DisAsm::SUB_RSR(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
Write("SUB...");
|
||||
}
|
||||
|
||||
void ARMv7DisAsm::SUB_SPI(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
Write("SUB SP...");
|
||||
}
|
||||
|
||||
void ARMv7DisAsm::SUB_SPR(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
Write("SUB SP...");
|
||||
}
|
||||
|
|
@ -45,50 +45,23 @@ protected:
|
|||
return regs_str;
|
||||
}
|
||||
|
||||
void NULL_OP()
|
||||
{
|
||||
Write("null");
|
||||
}
|
||||
void UNK(const u32 data);
|
||||
|
||||
void PUSH(u16 regs_list)
|
||||
{
|
||||
Write(fmt::Format("push {%s}", GetRegsListString(regs_list).c_str()));
|
||||
}
|
||||
void NULL_OP(const u32 data, const ARMv7_encoding type);
|
||||
void NOP(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
void POP(u16 regs_list)
|
||||
{
|
||||
Write(fmt::Format("pop {%s}", GetRegsListString(regs_list).c_str()));
|
||||
}
|
||||
void PUSH(const u32 data, const ARMv7_encoding type);
|
||||
void POP(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
void NOP()
|
||||
{
|
||||
Write("nop");
|
||||
}
|
||||
void B(const u32 data, const ARMv7_encoding type);
|
||||
void CBZ(const u32 data, const ARMv7_encoding type);
|
||||
void CBNZ(const u32 data, const ARMv7_encoding type);
|
||||
void BL(const u32 data, const ARMv7_encoding type);
|
||||
void BLX(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
void B(u8 cond, u32 imm, u8 intstr_size)
|
||||
{
|
||||
if((cond & 0xe) == 0xe)
|
||||
{
|
||||
Write(fmt::Format("b 0x%x", DisAsmBranchTarget(imm) + intstr_size));
|
||||
}
|
||||
else
|
||||
{
|
||||
Write(fmt::Format("b[%s] 0x%x", g_arm_cond_name[cond], DisAsmBranchTarget(imm) + intstr_size));
|
||||
}
|
||||
}
|
||||
|
||||
virtual void CBZ(u8 op, u32 imm, u8 rn, u8 intstr_size)
|
||||
{
|
||||
Write(fmt::Format("cb%sz 0x%x,%s", (op ? "n" : ""), DisAsmBranchTarget(imm) + intstr_size, g_arm_reg_name[rn]));
|
||||
}
|
||||
|
||||
void BL(u32 imm, u8 intstr_size)
|
||||
{
|
||||
Write(fmt::Format("bl 0x%x", DisAsmBranchTarget(imm) + intstr_size));
|
||||
}
|
||||
|
||||
void UNK(const u16 code0, const u16 code1)
|
||||
{
|
||||
Write(fmt::Format("Unknown/Illegal opcode! (0x%04x : 0x%04x)", code0, code1));
|
||||
}
|
||||
void SUB_IMM(const u32 data, const ARMv7_encoding type);
|
||||
void SUB_REG(const u32 data, const ARMv7_encoding type);
|
||||
void SUB_RSR(const u32 data, const ARMv7_encoding type);
|
||||
void SUB_SPI(const u32 data, const ARMv7_encoding type);
|
||||
void SUB_SPR(const u32 data, const ARMv7_encoding type);
|
||||
};
|
||||
|
|
291
rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp
Normal file
291
rpcs3/Emu/ARMv7/ARMv7Interpreter.cpp
Normal file
|
@ -0,0 +1,291 @@
|
|||
#include "stdafx.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/Memory/Memory.h"
|
||||
#include "Emu/CPU/CPUDecoder.h"
|
||||
#include "ARMv7Thread.h"
|
||||
#include "ARMv7Interpreter.h"
|
||||
|
||||
void ARMv7Interpreter::UNK(const u32 data)
|
||||
{
|
||||
LOG_ERROR(HLE, "Unknown/illegal opcode! (0x%04x : 0x%04x)", data >> 16, data & 0xffff);
|
||||
Emu.Pause();
|
||||
}
|
||||
|
||||
void ARMv7Interpreter::NULL_OP(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
LOG_ERROR(HLE, "Null opcode found");
|
||||
Emu.Pause();
|
||||
}
|
||||
|
||||
void ARMv7Interpreter::NOP(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case T1: break;
|
||||
case T2: break;
|
||||
case A1: break;
|
||||
default: throw __FUNCTION__;
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv7Interpreter::PUSH(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
u16 reg_list = 0;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case T1:
|
||||
{
|
||||
reg_list = ((data & 0x100) << 6) | (data & 0xff);
|
||||
break;
|
||||
}
|
||||
case T2:
|
||||
{
|
||||
reg_list = data & 0x5fff;
|
||||
break;
|
||||
}
|
||||
case T3:
|
||||
{
|
||||
reg_list = 1 << (data >> 12);
|
||||
break;
|
||||
}
|
||||
case A1:
|
||||
{
|
||||
reg_list = data & 0xffff; if (BitCount(reg_list) < 2) throw "STMDB / STMFD";
|
||||
if (!ConditionPassed(data >> 28)) return;
|
||||
break;
|
||||
}
|
||||
case A2:
|
||||
{
|
||||
reg_list = 1 << ((data >> 12) & 0xf);
|
||||
if (!ConditionPassed(data >> 28)) return;
|
||||
break;
|
||||
}
|
||||
default: throw __FUNCTION__;
|
||||
}
|
||||
|
||||
for (u16 mask = 1 << 15, i = 15; mask; mask >>= 1, i--)
|
||||
{
|
||||
if (reg_list & mask)
|
||||
{
|
||||
CPU.SP -= 4;
|
||||
vm::psv::write32(CPU.SP, CPU.read_gpr(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv7Interpreter::POP(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
u16 reg_list = 0;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case T1:
|
||||
{
|
||||
reg_list = ((data & 0x100) << 6) | (data & 0xff);
|
||||
break;
|
||||
}
|
||||
case T2:
|
||||
{
|
||||
reg_list = data & 0xdfff;
|
||||
break;
|
||||
}
|
||||
case T3:
|
||||
{
|
||||
reg_list = 1 << (data >> 12);
|
||||
break;
|
||||
}
|
||||
case A1:
|
||||
{
|
||||
reg_list = data & 0xffff; if (BitCount(reg_list) < 2) throw "LDM / LDMIA / LDMFD";
|
||||
if (!ConditionPassed(data >> 28)) return;
|
||||
break;
|
||||
}
|
||||
case A2:
|
||||
{
|
||||
reg_list = 1 << ((data >> 12) & 0xf);
|
||||
if (!ConditionPassed(data >> 28)) return;
|
||||
break;
|
||||
}
|
||||
default: throw __FUNCTION__;
|
||||
}
|
||||
|
||||
for (u16 mask = 1, i = 0; mask; mask <<= 1, i++)
|
||||
{
|
||||
if (reg_list & mask)
|
||||
{
|
||||
CPU.write_gpr(i, vm::psv::read32(CPU.SP));
|
||||
CPU.SP += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv7Interpreter::B(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
u8 cond = 0xf;
|
||||
u32 jump = 0; // jump = instr_size + imm32
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case T1:
|
||||
{
|
||||
jump = 2 + sign<9, u32>((data & 0xff) << 1);
|
||||
cond = (data >> 8) & 0xf; if (cond == 0xf) throw "SVC";
|
||||
break;
|
||||
}
|
||||
case T2:
|
||||
{
|
||||
jump = 2 + sign<12, u32>((data & 0x7ff) << 1);
|
||||
break;
|
||||
}
|
||||
case T3:
|
||||
{
|
||||
u32 s = (data >> 26) & 0x1;
|
||||
u32 j1 = (data >> 13) & 0x1;
|
||||
u32 j2 = (data >> 11) & 0x1;
|
||||
jump = 4 + sign<21, u32>(s << 20 | j2 << 19 | j1 << 18 | (data & 0x3f0000) >> 4 | (data & 0x7ff) << 1);
|
||||
cond = (data >> 6) & 0xf; if (cond >= 0xe) throw "Related encodings";
|
||||
break;
|
||||
}
|
||||
case T4:
|
||||
{
|
||||
u32 s = (data >> 26) & 0x1;
|
||||
u32 i1 = (data >> 13) & 0x1 ^ s ^ 1;
|
||||
u32 i2 = (data >> 11) & 0x1 ^ s ^ 1;
|
||||
jump = 4 + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (data & 0x3ff0000) >> 4 | (data & 0x7ff) << 1);
|
||||
break;
|
||||
}
|
||||
case A1:
|
||||
{
|
||||
jump = 1 + 4 + sign<26, u32>((data & 0xffffff) << 2);
|
||||
cond = (data >> 28) & 0xf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ConditionPassed(cond))
|
||||
{
|
||||
CPU.SetBranch(CPU.PC + jump);
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv7Interpreter::CBZ(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case T1: break;
|
||||
default: throw __FUNCTION__;
|
||||
}
|
||||
|
||||
if (CPU.GPR[data & 0x7] == 0)
|
||||
{
|
||||
CPU.SetBranch(CPU.PC + 2 + ((data & 0xf8) >> 2) + ((data & 0x200) >> 3));
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv7Interpreter::CBNZ(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case T1: break;
|
||||
default: throw __FUNCTION__;
|
||||
}
|
||||
|
||||
if (CPU.GPR[data & 0x7] != 0)
|
||||
{
|
||||
CPU.SetBranch(CPU.PC + 2 + ((data & 0xf8) >> 2) + ((data & 0x200) >> 3));
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv7Interpreter::BL(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
u32 jump = 0;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case T1:
|
||||
{
|
||||
u32 s = (data >> 26) & 0x1;
|
||||
u32 i1 = (data >> 13) & 0x1 ^ s ^ 1;
|
||||
u32 i2 = (data >> 11) & 0x1 ^ s ^ 1;
|
||||
jump = 4 + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (data & 0x3ff0000) >> 4 | (data & 0x7ff) << 1);
|
||||
break;
|
||||
}
|
||||
case A1:
|
||||
{
|
||||
jump = 4 + sign<26, u32>((data & 0xffffff) << 2);
|
||||
break;
|
||||
}
|
||||
default: throw __FUNCTION__;
|
||||
}
|
||||
|
||||
CPU.LR = (CPU.PC & 1) ? CPU.PC - 4 : CPU.PC;
|
||||
CPU.SetBranch(CPU.PC + jump);
|
||||
}
|
||||
|
||||
void ARMv7Interpreter::BLX(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
u32 target;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case T1:
|
||||
{
|
||||
target = CPU.GPR[(data >> 3) & 0xf];
|
||||
break;
|
||||
}
|
||||
case T2:
|
||||
{
|
||||
u32 s = (data >> 26) & 0x1;
|
||||
u32 i1 = (data >> 13) & 0x1 ^ s ^ 1;
|
||||
u32 i2 = (data >> 11) & 0x1 ^ s ^ 1;
|
||||
target = CPU.PC + 4 + sign<25, u32>(s << 24 | i2 << 23 | i1 << 22 | (data & 0x3ff0000) >> 4 | (data & 0x7ff) << 1) & ~1;
|
||||
break;
|
||||
}
|
||||
case A1:
|
||||
{
|
||||
target = CPU.GPR[data & 0xf];
|
||||
if (!ConditionPassed(data >> 28)) return;
|
||||
break;
|
||||
}
|
||||
case A2:
|
||||
{
|
||||
target = CPU.PC + 5 + sign<25, u32>((data & 0xffffff) << 2 | (data & 0x1000000) >> 23);
|
||||
break;
|
||||
}
|
||||
default: throw __FUNCTION__;
|
||||
}
|
||||
|
||||
CPU.LR = (CPU.PC & 1) ? CPU.PC - (type == T1 ? 2 : 4) : CPU.PC - 4; // ???
|
||||
CPU.SetBranch(target);
|
||||
}
|
||||
|
||||
void ARMv7Interpreter::SUB_IMM(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ARMv7Interpreter::SUB_REG(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ARMv7Interpreter::SUB_RSR(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void ARMv7Interpreter::SUB_SPI(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case T1: CPU.SP -= (data & 0x7f) << 2; return;
|
||||
default: throw __FUNCTION__;
|
||||
}
|
||||
}
|
||||
|
||||
void ARMv7Interpreter::SUB_SPR(const u32 data, const ARMv7_encoding type)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -258,65 +258,23 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
void NULL_OP()
|
||||
{
|
||||
LOG_ERROR(HLE, "null");
|
||||
Emu.Pause();
|
||||
}
|
||||
void UNK(const u32 data);
|
||||
|
||||
void NOP()
|
||||
{
|
||||
}
|
||||
void NULL_OP(const u32 data, const ARMv7_encoding type);
|
||||
void NOP(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
void PUSH(u16 regs_list)
|
||||
{
|
||||
for(u16 mask=0x1, i=0; mask; mask <<= 1, i++)
|
||||
{
|
||||
if(regs_list & mask)
|
||||
{
|
||||
CPU.SP -= 4;
|
||||
vm::psv::write32(CPU.SP, CPU.read_gpr(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
void PUSH(const u32 data, const ARMv7_encoding type);
|
||||
void POP(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
void POP(u16 regs_list)
|
||||
{
|
||||
for(u16 mask=(0x1 << 15), i=15; mask; mask >>= 1, i--)
|
||||
{
|
||||
if(regs_list & mask)
|
||||
{
|
||||
CPU.write_gpr(i, vm::psv::read32(CPU.SP));
|
||||
CPU.SP += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
void B(const u32 data, const ARMv7_encoding type);
|
||||
void CBZ(const u32 data, const ARMv7_encoding type);
|
||||
void CBNZ(const u32 data, const ARMv7_encoding type);
|
||||
void BL(const u32 data, const ARMv7_encoding type);
|
||||
void BLX(const u32 data, const ARMv7_encoding type);
|
||||
|
||||
void B(u8 cond, u32 imm, u8 intstr_size)
|
||||
{
|
||||
if(ConditionPassed(cond))
|
||||
{
|
||||
CPU.SetBranch(CPU.PC + intstr_size + imm);
|
||||
}
|
||||
}
|
||||
|
||||
void CBZ(u8 op, u32 imm, u8 rn, u8 intstr_size)
|
||||
{
|
||||
if((CPU.GPR[rn] == 0) ^ op)
|
||||
{
|
||||
CPU.SetBranch(CPU.PC + intstr_size + imm);
|
||||
}
|
||||
}
|
||||
|
||||
void BL(u32 imm, u8 intstr_size)
|
||||
{
|
||||
CPU.LR = (CPU.PC + intstr_size) | 1;
|
||||
CPU.SetBranch(CPU.PC + intstr_size + imm);
|
||||
}
|
||||
|
||||
void UNK(const u16 code0, const u16 code1)
|
||||
{
|
||||
LOG_ERROR(HLE, "Unknown/Illegal opcode! (0x%04x : 0x%04x)", code0, code1);
|
||||
Emu.Pause();
|
||||
}
|
||||
void SUB_IMM(const u32 data, const ARMv7_encoding type);
|
||||
void SUB_REG(const u32 data, const ARMv7_encoding type);
|
||||
void SUB_RSR(const u32 data, const ARMv7_encoding type);
|
||||
void SUB_SPI(const u32 data, const ARMv7_encoding type);
|
||||
void SUB_SPR(const u32 data, const ARMv7_encoding type);
|
||||
};
|
||||
|
|
|
@ -32,18 +32,88 @@ namespace ARMv7_opcodes
|
|||
};
|
||||
}
|
||||
|
||||
enum ARMv7_encoding
|
||||
{
|
||||
T1,
|
||||
T2,
|
||||
T3,
|
||||
T4,
|
||||
A1,
|
||||
A2,
|
||||
};
|
||||
|
||||
class ARMv7Opcodes
|
||||
{
|
||||
public:
|
||||
virtual void NULL_OP() = 0;
|
||||
virtual void NOP() = 0;
|
||||
virtual void UNK(const u32 data) = 0;
|
||||
|
||||
virtual void PUSH(u16 regs_list) = 0;
|
||||
virtual void POP(u16 regs_list) = 0;
|
||||
virtual void NULL_OP(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void NOP(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void B(u8 cond, u32 imm, u8 intstr_size) = 0;
|
||||
virtual void CBZ(u8 op, u32 imm, u8 rn, u8 intstr_size) = 0;
|
||||
virtual void BL(u32 imm, u8 intstr_size)=0;
|
||||
|
||||
virtual void UNK(const u16 code0, const u16 code1) = 0;
|
||||
virtual void PUSH(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void POP(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void B(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void CBZ(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void CBNZ(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void BL(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void BLX(const u32 data, const ARMv7_encoding type) = 0;
|
||||
|
||||
virtual void SUB_IMM(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SUB_REG(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SUB_RSR(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SUB_SPI(const u32 data, const ARMv7_encoding type) = 0;
|
||||
virtual void SUB_SPR(const u32 data, const ARMv7_encoding type) = 0;
|
||||
};
|
||||
|
||||
struct ARMv7_opcode_t
|
||||
{
|
||||
u32 mask;
|
||||
u32 code;
|
||||
u32 length; // 2 or 4
|
||||
char* name;
|
||||
ARMv7_encoding type;
|
||||
void (ARMv7Opcodes::*func)(const u32 data, const ARMv7_encoding type);
|
||||
};
|
||||
|
||||
// single 16-bit value
|
||||
#define ARMv7_OP2(mask, code, type, name) { (mask) << 16, (code) << 16, 2, #name, type, &ARMv7Opcodes::name }
|
||||
// two 16-bit values
|
||||
#define ARMv7_OP4(mask0, mask1, code0, code1, type, name) { ((mask0) << 16) | (mask1), ((code0) << 16) | (code1), 4, #name, type, &ARMv7Opcodes::name }
|
||||
|
||||
static const ARMv7_opcode_t ARMv7_opcode_table[] =
|
||||
{
|
||||
ARMv7_OP2(0xffff, 0x0000, T1, NULL_OP),
|
||||
ARMv7_OP2(0xffff, 0xbf00, T1, NOP),
|
||||
ARMv7_OP4(0xffff, 0xffff, 0xf3af, 0x8000, T2, NOP),
|
||||
ARMv7_OP4(0x0fff, 0xffff, 0x0320, 0xf000, A1, NOP),
|
||||
ARMv7_OP2(0xfe00, 0xb400, T1, PUSH),
|
||||
ARMv7_OP4(0xffff, 0x0000, 0xe92d, 0x0000, T2, PUSH), // had an error in arch ref
|
||||
ARMv7_OP4(0xffff, 0x0fff, 0xf84d, 0x0d04, T3, PUSH),
|
||||
ARMv7_OP4(0x0fff, 0x0000, 0x092d, 0x0000, A1, PUSH),
|
||||
ARMv7_OP4(0x0fff, 0x0fff, 0x052d, 0x0004, A2, PUSH),
|
||||
ARMv7_OP2(0xfe00, 0xbc00, T1, POP),
|
||||
ARMv7_OP4(0xffff, 0x0000, 0xe8bd, 0x0000, T2, POP),
|
||||
ARMv7_OP4(0xffff, 0x0fff, 0xf85d, 0x0b04, T3, POP),
|
||||
ARMv7_OP4(0x0fff, 0x0000, 0x08bd, 0x0000, A1, POP),
|
||||
ARMv7_OP4(0x0fff, 0x0fff, 0x049d, 0x0004, A2, POP),
|
||||
ARMv7_OP2(0xf000, 0xd000, T1, B),
|
||||
ARMv7_OP2(0xf800, 0xe000, T2, B),
|
||||
ARMv7_OP4(0xf800, 0xd000, 0xf000, 0x8000, T3, B),
|
||||
ARMv7_OP4(0xf800, 0xd000, 0xf000, 0x9000, T4, B),
|
||||
ARMv7_OP4(0x0f00, 0x0000, 0x0a00, 0x0000, A1, B),
|
||||
ARMv7_OP2(0xfd00, 0xb100, T1, CBZ),
|
||||
ARMv7_OP2(0xfd00, 0xb900, T1, CBNZ),
|
||||
ARMv7_OP4(0xf800, 0xd000, 0xf000, 0xd000, T1, BL),
|
||||
ARMv7_OP4(0x0f00, 0x0000, 0x0b00, 0x0000, A1, BL),
|
||||
ARMv7_OP2(0xff80, 0x4780, T1, BLX),
|
||||
ARMv7_OP4(0xf800, 0xc001, 0xf000, 0xc000, T2, BLX),
|
||||
ARMv7_OP4(0x0fff, 0xfff0, 0x012f, 0xff30, A1, BLX),
|
||||
ARMv7_OP4(0xfe00, 0x0000, 0xfa00, 0x0000, A2, BLX),
|
||||
|
||||
ARMv7_OP2(0xff80, 0xb080, T1, SUB_SPI),
|
||||
};
|
||||
|
||||
#undef ARMv7_OP
|
||||
#undef ARMv7_OPP
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ void ARMv7Thread::InitRegs()
|
|||
memset(GPR, 0, sizeof(GPR[0]) * 15);
|
||||
APSR.APSR = 0;
|
||||
IPSR.IPSR = 0;
|
||||
PC |= 1;
|
||||
SP = m_stack_addr + m_stack_size;
|
||||
}
|
||||
|
||||
|
|
|
@ -54,6 +54,8 @@
|
|||
<ClCompile Include="Crypto\unpkg.cpp" />
|
||||
<ClCompile Include="Crypto\unself.cpp" />
|
||||
<ClCompile Include="Crypto\utils.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\ARMv7DisAsm.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\ARMv7Interpreter.cpp" />
|
||||
<ClCompile Include="Emu\ARMv7\ARMv7Thread.cpp" />
|
||||
<ClCompile Include="Emu\Audio\AL\OpenALThread.cpp" />
|
||||
<ClCompile Include="Emu\Audio\AudioDumper.cpp" />
|
||||
|
|
|
@ -632,6 +632,12 @@
|
|||
<ClCompile Include="Emu\Cell\PPULLVMRecompilerTests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\ARMv7Interpreter.cpp">
|
||||
<Filter>Emu\ARMv7</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Emu\ARMv7\ARMv7DisAsm.cpp">
|
||||
<Filter>Emu\ARMv7</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Crypto\aes.h">
|
||||
|
|
Loading…
Add table
Reference in a new issue