PPU Analyzer: GPR-assisted jump table analysis

This commit is contained in:
Elad 2025-01-31 17:15:51 +02:00
parent c497136431
commit 57b05717dd
3 changed files with 955 additions and 135 deletions

File diff suppressed because it is too large Load diff

View file

@ -187,6 +187,7 @@ struct ppu_module : public Type
addr_to_seg_index = info.addr_to_seg_index;
parent = const_cast<ppu_module*>(&info);
attr = info.attr;
is_relocatable = info.is_relocatable;
local_bounds = {u32{umax}, 0}; // Initially empty range
}
@ -340,7 +341,10 @@ struct ppu_pattern_matrix
struct ppu_itype
{
static constexpr struct branch_tag{} branch{}; // Branch Instructions
static constexpr struct trap_tag{} trap{}; // Branch Instructions
static constexpr struct trap_tag{} trap{}; // Trap Instructions
static constexpr struct store_tag{} store{}; // Memory store Instructions
static constexpr struct load_tag{} load{}; // Memory load Instructions (TODO: Fill it)
static constexpr struct memory_tag{} memory{}; // Memory Instructions
enum class type
{
@ -505,8 +509,6 @@ struct ppu_itype
VXOR,
MULLI,
SUBFIC,
CMPLI,
CMPI,
ADDIC,
ADDI,
ADDIS,
@ -536,7 +538,6 @@ struct ppu_itype
RLDIMI,
RLDCL,
RLDCR,
CMP,
LVSL,
LVEBX,
SUBFC,
@ -553,13 +554,11 @@ struct ppu_itype
CNTLZW,
SLD,
AND,
CMPL,
LVSR,
LVEHX,
SUBF,
SUBFO,
LDUX,
DCBST,
LWZUX,
CNTLZD,
ANDC,
@ -574,26 +573,15 @@ struct ppu_itype
NEGO,
LBZUX,
NOR,
STVEBX,
SUBFE,
SUBFEO,
ADDE,
ADDEO,
MTOCRF,
STDX,
STWCX,
STWX,
STVEHX,
STDUX,
STWUX,
STVEWX,
SUBFZE,
SUBFZEO,
ADDZE,
ADDZEO,
STDCX,
STBX,
STVX,
SUBFME,
SUBFMEO,
MULLD,
@ -602,11 +590,8 @@ struct ppu_itype
ADDMEO,
MULLW,
MULLWO,
DCBTST,
STBUX,
ADD,
ADDO,
DCBT,
LHZX,
EQV,
ECIWX,
@ -614,26 +599,20 @@ struct ppu_itype
XOR,
MFSPR,
LWAX,
DST,
LHAX,
LVXL,
MFTB,
LWAUX,
DSTST,
LHAUX,
STHX,
ORC,
ECOWX,
STHUX,
OR,
DIVDU,
DIVDUO,
DIVWU,
DIVWUO,
MTSPR,
DCBI,
NAND,
STVXL,
DIVD,
DIVDO,
DIVW,
@ -648,66 +627,34 @@ struct ppu_itype
LVRX,
LSWI,
LFSUX,
SYNC,
LFDX,
LFDUX,
STVLX,
STDBRX,
STSWX,
STWBRX,
STFSX,
STVRX,
STFSUX,
STSWI,
STFDX,
STFDUX,
LVLXL,
LHBRX,
SRAW,
SRAD,
LVRXL,
DSS,
SRAWI,
SRADI,
EIEIO,
STVLXL,
STHBRX,
EXTSH,
STVRXL,
EXTSB,
STFIWX,
EXTSW,
ICBI,
DCBZ,
LWZ,
LWZU,
LBZ,
LBZU,
STW,
STWU,
STB,
STBU,
LHZ,
LHZU,
LHA,
LHAU,
STH,
STHU,
LMW,
STMW,
LFS,
LFSU,
LFD,
LFDU,
STFS,
STFSU,
STFD,
STFDU,
LD,
LDU,
LWA,
STD,
STDU,
FDIVS,
FSUBS,
FADDS,
@ -854,6 +801,65 @@ struct ppu_itype
FCTIDZ_,
FCFID_,
CMPLI,
CMPI,
CMP,
CMPL,
STMW, // store_tag first
STSWX,
STSWI,
STVXL,
STVLX,
STVRX,
STVEBX,
STVEHX,
STVEWX,
STVX,
STVLXL,
STVRXL,
STDX,
STDUX,
STDCX,
STDBRX,
STD,
STDU,
STFDUX,
STFDX,
STFDU,
STFD,
STFS,
STFSU,
STFSX,
STFSUX,
STFIWX,
STWCX,
STWX,
STWUX,
STWBRX,
STWU,
STW,
STHBRX,
STHX,
STHUX,
STH,
STBX,
STBU,
STB,
STHU,
STBUX,
DCBZ,
DCBI, // Perceive memory barrier or flag instructions as stores
DCBTST,
DCBT,
DCBST,
DST,
DSS,
ICBI,
SYNC,
EIEIO,
DSTST, // store_tag last
B, // branch_tag first
BC,
BCLR,
@ -882,6 +888,11 @@ struct ppu_itype
{
return value >= TD && value <= TWI;
}
friend constexpr bool operator &(type value, store_tag)
{
return value >= STMW && value <= DSTST;
}
};
struct ppu_iname

View file

@ -132,22 +132,7 @@ std::pair<PPUDisAsm::const_op, u64> PPUDisAsm::try_get_const_op_gpr_value(u32 re
switch (type)
{
case ppu_itype::ADDI:
{
if (op.rd != reg)
{
// Destination register is not relevant to us
break;
}
u64 reg_ra = 0;
if (op.ra)
{
GET_CONST_REG(reg_ra, op.ra);
}
return { form, reg_ra + op.simm16 };
}
case ppu_itype::ADDIC:
case ppu_itype::ADDIS:
{
if (op.rd != reg)
@ -157,12 +142,12 @@ std::pair<PPUDisAsm::const_op, u64> PPUDisAsm::try_get_const_op_gpr_value(u32 re
u64 reg_ra = 0;
if (op.ra)
if (op.ra || type == ppu_itype::ADDIC)
{
GET_CONST_REG(reg_ra, op.ra);
}
return { form, reg_ra + op.simm16 * 65536 };
return { form, reg_ra + (type == ppu_itype::ADDIS ? op.simm16 * 65536 : op.simm16) };
}
case ppu_itype::ORI:
{
@ -1286,6 +1271,12 @@ void PPUDisAsm::CMPI(ppu_opcode_t op)
void PPUDisAsm::ADDIC(ppu_opcode_t op)
{
DisAsm_R2_IMM(op.main & 1 ? "addic." : "addic", op.rd, op.ra, op.simm16);
if (auto [is_const, value] = try_get_const_gpr_value(op.ra); is_const)
{
// Comment constant formation
comment_constant(last_opcode, value + op.simm16);
}
}
void PPUDisAsm::ADDI(ppu_opcode_t op)