mirror of
https://github.com/RPCSX/rpcsx.git
synced 2025-12-06 07:12:14 +01:00
138 lines
2.3 KiB
C++
138 lines
2.3 KiB
C++
#pragma once
|
|
#include "Emu/CPU/CPUDecoder.h"
|
|
#include "ARMv7Opcodes.h"
|
|
|
|
|
|
class ARMv7Decoder : public CPUDecoder
|
|
{
|
|
ARMv7Opcodes& m_op;
|
|
u8 m_last_instr_size;
|
|
|
|
public:
|
|
ARMv7Decoder(ARMv7Opcodes& op) : m_op(op)
|
|
{
|
|
}
|
|
|
|
u32 branchTarget(u32 imm)
|
|
{
|
|
return imm << 1;
|
|
}
|
|
|
|
virtual u8 DecodeMemory(const u64 address)
|
|
{
|
|
using namespace ARMv7_opcodes;
|
|
const u16 code0 = Memory.Read16(address);
|
|
const u16 code1 = Memory.Read16(address + 2);
|
|
|
|
switch(code0 >> 12) //15 - 12
|
|
{
|
|
case T1_CBZ:
|
|
switch((code0 >> 10) & 0x1)
|
|
{
|
|
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;
|
|
}
|
|
}
|
|
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);
|
|
return 2;
|
|
}
|
|
};
|