SPU analyser: add spu_iflag

Register information about register accesses.
This commit is contained in:
Nekotekina 2019-04-28 03:36:17 +03:00
parent 716737ecf2
commit e09c6ea4b4
3 changed files with 244 additions and 0 deletions

View File

@ -240,6 +240,231 @@ struct spu_itype
}
};
struct spu_iflag
{
enum
{
use_ra = 1 << 8,
use_rb = 1 << 9,
use_rc = 1 << 10,
};
enum flag
{
UNK = 0,
HBRA,
HBRR,
STOP,
STOPD,
LNOP,
NOP,
SYNC,
DSYNC,
MFSPR,
MTSPR,
DFCEQ,
DFCMEQ,
DFCGT,
DFCMGT,
DFTSV,
RDCH,
RCHCNT,
LQA,
LQR,
ILH,
ILHU,
IL,
ILA,
FSMBI,
BR,
BRA,
BRSL,
BRASL,
IRET,
FSCRRD,
WRCH = use_rc,
IOHL,
STQA,
STQR,
BRNZ,
BRZ,
BRHNZ,
BRHZ,
STQD = use_ra | use_rc,
BIZ,
BINZ,
BIHZ,
BIHNZ,
STQX = use_ra | use_rb | use_rc,
ADDX,
CGX,
SFX,
BGX,
MPYHHA,
MPYHHAU,
MPYA,
SELB,
SHUFB,
DFMA,
DFNMS,
DFMS,
DFNMA,
FMA,
FNMS,
FMS,
HBR = use_ra,
HEQI,
HGTI,
HLGTI,
LQD,
CBD,
CHD,
CWD,
CDD,
AHI,
AI,
SFHI,
SFI,
MPYI,
MPYUI,
CLZ,
CNTB,
FSMB,
FSMH,
FSM,
GBB,
GBH,
GB,
XSBH,
XSHW,
XSWD,
ANDBI,
ANDHI,
ANDI,
ORBI,
ORHI,
ORI,
ORX,
XORBI,
XORHI,
XORI,
SHLHI,
SHLI,
SHLQBII,
SHLQBYI,
ROTHI,
ROTI,
ROTQBYI,
ROTQBII,
ROTHMI,
ROTMI,
ROTQMBYI,
ROTQMBII,
ROTMAHI,
ROTMAI,
CEQBI,
CEQHI,
CEQI,
CGTBI,
CGTHI,
CGTI,
CLGTBI,
CLGTHI,
CLGTI,
BI,
BISLED,
BISL,
FREST,
FRSQEST,
CSFLT,
CFLTS,
CUFLT,
CFLTU,
FRDS,
FESD,
FSCRWR,
HEQ = use_ra | use_rb,
HGT,
HLGT,
LQX,
CBX,
CHX,
CWX,
CDX,
AH,
A,
SFH,
SF,
CG,
BG,
MPYHHU,
MPY,
MPYU,
MPYH,
MPYS,
MPYHH,
AVGB,
ABSDB,
SUMB,
AND,
ANDC,
OR,
ORC,
XOR,
NAND,
NOR,
EQV,
SHLH,
SHL,
SHLQBI,
SHLQBY,
SHLQBYBI,
ROTH,
ROT,
ROTQBY,
ROTQBYBI,
ROTQBI,
ROTHM,
ROTM,
ROTQMBY,
ROTQMBYBI,
ROTQMBI,
ROTMAH,
ROTMA,
CEQB,
CEQH,
CEQ,
CGTB,
CGTH,
CGT,
CLGTB,
CLGTH,
CLGT,
FA,
DFA,
FS,
DFS,
FM,
DFM,
FI,
FCEQ,
FCMEQ,
FCGT,
FCMGT,
};
// Enable address-of operator for spu_decoder<>
friend constexpr flag operator &(flag value)
{
return value;
}
};
// Encode instruction name: 6 bits per character (0x20..0x5f), max 10
static constexpr u64 spu_iname_encode(const char* ptr, u64 value = 0)
{

View File

@ -20,6 +20,7 @@ extern atomic_t<u64> g_progr_pdone;
const spu_decoder<spu_itype> s_spu_itype;
const spu_decoder<spu_iname> s_spu_iname;
const spu_decoder<spu_iflag> s_spu_iflag;
extern u64 get_timebased_time();
@ -911,6 +912,9 @@ const std::vector<u32>& spu_recompiler_base::analyse(const be_t<u32>* ls, u32 en
workload.push_back(entry_point);
std::memset(m_regmod.data(), 0xff, sizeof(m_regmod));
std::memset(m_use_ra.data(), 0xff, sizeof(m_use_ra));
std::memset(m_use_rb.data(), 0xff, sizeof(m_use_rb));
std::memset(m_use_rc.data(), 0xff, sizeof(m_use_rc));
m_targets.clear();
m_preds.clear();
m_preds[entry_point];
@ -999,6 +1003,17 @@ const std::vector<u32>& spu_recompiler_base::analyse(const be_t<u32>* ls, u32 en
m_targets.erase(pos);
// Fill register access info
if (auto iflags = s_spu_iflag.decode(data))
{
if (iflags & spu_iflag::use_ra)
m_use_ra[pos / 4] = op.ra;
if (iflags & spu_iflag::use_rb)
m_use_rb[pos / 4] = op.rb;
if (iflags & spu_iflag::use_rc)
m_use_rc[pos / 4] = op.rc;
}
// Analyse instruction
switch (const auto type = s_spu_itype.decode(data))
{

View File

@ -194,6 +194,10 @@ protected:
// GPR modified by the instruction (-1 = not set)
std::array<u8, 0x10000> m_regmod;
std::array<u8, 0x10000> m_use_ra;
std::array<u8, 0x10000> m_use_rb;
std::array<u8, 0x10000> m_use_rc;
// List of possible targets for the instruction (entry shouldn't exist for simple instructions)
std::unordered_map<u32, std::basic_string<u32>, value_hash<u32, 2>> m_targets;