mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-01 20:41:19 +12:00
199 lines
3.7 KiB
C++
199 lines
3.7 KiB
C++
#pragma once
|
|
|
|
namespace Espresso
|
|
{
|
|
enum CR_BIT
|
|
{
|
|
CR_BIT_INDEX_LT = 0,
|
|
CR_BIT_INDEX_GT = 1,
|
|
CR_BIT_INDEX_EQ = 2,
|
|
CR_BIT_INDEX_SO = 3,
|
|
};
|
|
|
|
enum class PrimaryOpcode
|
|
{
|
|
// underscore at the end of the name means that this instruction always updates CR0 (as if RC bit is set)
|
|
ZERO = 0,
|
|
VIRTUAL_HLE = 1,
|
|
|
|
// 3 = TWI
|
|
GROUP_4 = 4,
|
|
MULLI = 7,
|
|
SUBFIC = 8,
|
|
CMPLI = 10,
|
|
CMPI = 11,
|
|
ADDIC = 12,
|
|
ADDIC_ = 13,
|
|
ADDI = 14,
|
|
ADDIS = 15,
|
|
BC = 16, // conditional branch
|
|
GROUP_17 = 17, // SC
|
|
B = 18, // unconditional branch
|
|
GROUP_19 = 19,
|
|
RLWIMI = 20,
|
|
RLWINM = 21,
|
|
// 22 ?
|
|
RLWNM = 23,
|
|
ORI = 24,
|
|
ORIS = 25,
|
|
XORI = 26,
|
|
XORIS = 27,
|
|
ANDI_ = 28,
|
|
ANDIS_ = 29,
|
|
GROUP_31 = 31,
|
|
LWZ = 32,
|
|
LWZU = 33,
|
|
LBZ = 34,
|
|
LBZU = 35,
|
|
STW = 36,
|
|
STWU = 37,
|
|
STB = 38,
|
|
STBU = 39,
|
|
LHZ = 40,
|
|
LHZU = 41,
|
|
LHA = 42,
|
|
LHAU = 43,
|
|
STH = 44,
|
|
STHU = 45,
|
|
LMW = 46,
|
|
STMW = 47,
|
|
LFS = 48,
|
|
LFSU = 49,
|
|
LFD = 50,
|
|
LFDU = 51,
|
|
STFS = 52,
|
|
STFSU = 53,
|
|
STFD = 54,
|
|
STFDU = 55,
|
|
PSQ_L = 56,
|
|
PSQ_LU = 57,
|
|
// 58 ?
|
|
GROUP_59 = 59,
|
|
PSQ_ST = 60,
|
|
PSQ_STU = 61,
|
|
// 62 ?
|
|
GROUP_63 = 63,
|
|
};
|
|
|
|
enum class Opcode19
|
|
{
|
|
MCRF = 0,
|
|
BCLR = 16,
|
|
CRNOR = 33,
|
|
RFI = 50,
|
|
CRANDC = 129,
|
|
ISYNC = 150,
|
|
CRXOR = 193,
|
|
CRAND = 257,
|
|
CREQV = 289,
|
|
CRORC = 417,
|
|
CROR = 449,
|
|
BCCTR = 528
|
|
};
|
|
|
|
enum class Opcode31
|
|
{
|
|
TW = 4,
|
|
MFTB = 371,
|
|
};
|
|
|
|
inline PrimaryOpcode GetPrimaryOpcode(uint32 opcode) { return (PrimaryOpcode)(opcode >> 26); };
|
|
inline Opcode19 GetGroup19Opcode(uint32 opcode) { return (Opcode19)((opcode >> 1) & 0x3FF); };
|
|
inline Opcode31 GetGroup31Opcode(uint32 opcode) { return (Opcode31)((opcode >> 1) & 0x3FF); };
|
|
|
|
struct BOField
|
|
{
|
|
BOField() = default;
|
|
BOField(uint8 bo) : bo(bo) {};
|
|
|
|
bool conditionInverted() const
|
|
{
|
|
return (bo & 8) == 0;
|
|
}
|
|
|
|
bool decrementerIgnore() const
|
|
{
|
|
return (bo & 4) != 0;
|
|
}
|
|
|
|
bool decrementerMustBeZero() const
|
|
{
|
|
return (bo & 2) != 0;
|
|
}
|
|
|
|
bool conditionIgnore() const
|
|
{
|
|
return (bo & 16) != 0;
|
|
}
|
|
|
|
bool branchAlways()
|
|
{
|
|
return conditionIgnore() && decrementerIgnore();
|
|
}
|
|
|
|
uint8 bo;
|
|
};
|
|
|
|
// returns true if LK bit is set, only valid for branch instructions
|
|
inline bool DecodeLK(uint32 opcode)
|
|
{
|
|
return (opcode & 1) != 0;
|
|
}
|
|
|
|
inline void _decodeForm_I(uint32 opcode, uint32& LI, bool& AA, bool& LK)
|
|
{
|
|
LI = opcode & 0x3fffffc;
|
|
if (LI & 0x02000000)
|
|
LI |= 0xfc000000;
|
|
AA = (opcode & 2) != 0;
|
|
LK = (opcode & 1) != 0;
|
|
}
|
|
|
|
inline void _decodeForm_D_branch(uint32 opcode, uint32& BD, BOField& BO, uint32& BI, bool& AA, bool& LK)
|
|
{
|
|
BD = opcode & 0xfffc;
|
|
if (BD & 0x8000)
|
|
BD |= 0xffff0000;
|
|
BO = { (uint8)((opcode >> 21) & 0x1F) };
|
|
BI = (opcode >> 16) & 0x1F;
|
|
AA = (opcode & 2) != 0;
|
|
LK = (opcode & 1) != 0;
|
|
}
|
|
|
|
inline void _decodeForm_D_SImm(uint32 opcode, uint32& rD, uint32& rA, uint32& imm)
|
|
{
|
|
rD = (opcode >> 21) & 0x1F;
|
|
rA = (opcode >> 16) & 0x1F;
|
|
imm = (uint32)(sint32)(sint16)(opcode & 0xFFFF);
|
|
}
|
|
|
|
inline void _decodeForm_XL(uint32 opcode, BOField& BO, uint32& BI, bool& LK)
|
|
{
|
|
BO = { (uint8)((opcode >> 21) & 0x1F) };
|
|
BI = (opcode >> 16) & 0x1F;
|
|
LK = (opcode & 1) != 0;
|
|
}
|
|
|
|
inline void decodeOp_ADDI(uint32 opcode, uint32& rD, uint32& rA, uint32& imm)
|
|
{
|
|
_decodeForm_D_SImm(opcode, rD, rA, imm);
|
|
}
|
|
|
|
inline void decodeOp_B(uint32 opcode, uint32& LI, bool& AA, bool& LK)
|
|
{
|
|
// form I
|
|
_decodeForm_I(opcode, LI, AA, LK);
|
|
}
|
|
|
|
inline void decodeOp_BC(uint32 opcode, uint32& BD, BOField& BO, uint32& BI, bool& AA, bool& LK)
|
|
{
|
|
// form D
|
|
_decodeForm_D_branch(opcode, BD, BO, BI, AA, LK);
|
|
}
|
|
|
|
inline void decodeOp_BCSPR(uint32 opcode, BOField& BO, uint32& BI, bool& LK) // BCLR and BCSPR
|
|
{
|
|
// form XL (with BD field expected to be zero)
|
|
_decodeForm_XL(opcode, BO, BI, LK);
|
|
}
|
|
}
|