Cemu/src/Cafe/HW/Espresso/EspressoISA.h
Exzap b089ae5b32
Some checks failed
Build check / build (push) Failing after 0s
Generate translation template / generate-pot (push) Failing after 0s
PowerPC recompiler rework (#641)
2025-04-26 17:59:32 +02:00

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);
}
}