mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-16 23:17:29 +00:00
SPU Debugger: SHUFB insertion patterns
This commit is contained in:
parent
86fc842c89
commit
5e8419af0d
@ -33,7 +33,18 @@ std::pair<bool, v128> SPUDisAsm::try_get_const_value(u32 reg, u32 pc) const
|
||||
|
||||
if (type & spu_itype::branch || type == spu_itype::UNK || !opcode)
|
||||
{
|
||||
return {};
|
||||
if (reg < 80u)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
// We do not care about function calls if register is non-volatile
|
||||
if ((type != spu_itype::BRSL && type != spu_itype::BRASL && type != spu_itype::BISL) || op0.rt == reg)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto flag = s_spu_iflag.decode(opcode);
|
||||
@ -56,6 +67,40 @@ std::pair<bool, v128> SPUDisAsm::try_get_const_value(u32 reg, u32 pc) const
|
||||
{
|
||||
return { true, v128::from32p(op0.i16 << 16) };
|
||||
}
|
||||
case spu_itype::CBD:
|
||||
case spu_itype::CHD:
|
||||
case spu_itype::CWD:
|
||||
case spu_itype::CDD:
|
||||
{
|
||||
// Aligned stack assumption
|
||||
if (op0.ra == 1u)
|
||||
{
|
||||
u32 size;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case spu_itype::CBD: size = 1; break;
|
||||
case spu_itype::CHD: size = 2; break;
|
||||
case spu_itype::CWD: size = 4; break;
|
||||
case spu_itype::CDD: size = 8; break;
|
||||
}
|
||||
|
||||
const u32 index = (~op0.i7 & 0xf) / size;
|
||||
auto res = v128::from64(0x18191A1B1C1D1E1Full, 0x1011121314151617ull);
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case 1: res._u8[index] = 0x03; break;
|
||||
case 2: res._u16[index] = 0x0203; break;
|
||||
case 4: res._u32[index] = 0x00010203; break;
|
||||
case 8: res._u64[index] = 0x0001020304050607ull; break;
|
||||
}
|
||||
|
||||
return {true, res};
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
case spu_itype::FSMBI:
|
||||
{
|
||||
v128 res;
|
||||
@ -106,6 +151,70 @@ std::pair<bool, v128> SPUDisAsm::try_get_const_value(u32 reg, u32 pc) const
|
||||
return {};
|
||||
}
|
||||
|
||||
typename SPUDisAsm::insert_mask_info SPUDisAsm::try_get_insert_mask_info(v128 mask)
|
||||
{
|
||||
if ((mask & v128::from8p(0xe0)) != v128{})
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
s32 first = -1, src_first = 0, last = 16;
|
||||
|
||||
auto access = [&](u32 index) -> u8
|
||||
{
|
||||
return mask._u8[index ^ 0xf];
|
||||
};
|
||||
|
||||
for (s32 i = 0; i < 16; i++)
|
||||
{
|
||||
if (access(i) & 0x10)
|
||||
{
|
||||
if ((access(i) & 0x0f) != i)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
if (first != -1 && last == 16)
|
||||
{
|
||||
last = i;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (last != 16)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
if (first == -1)
|
||||
{
|
||||
src_first = access(i);
|
||||
first = i;
|
||||
}
|
||||
|
||||
if (src_first + (i - first) != access(i))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
if (first == -1)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
const u32 size = last - first;
|
||||
|
||||
if ((size | src_first | first) & (size - 1))
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
// [type size, dst index, src index]
|
||||
return {size, first / size, src_first / size};
|
||||
}
|
||||
|
||||
void SPUDisAsm::WRCH(spu_opcode_t op)
|
||||
{
|
||||
const auto [is_const, value] = try_get_const_value(op.rt);
|
||||
|
@ -159,6 +159,15 @@ public:
|
||||
u32 disasm(u32 pc) override;
|
||||
std::pair<bool, v128> try_get_const_value(u32 reg, u32 pc = -1) const;
|
||||
|
||||
struct insert_mask_info
|
||||
{
|
||||
u32 type_size;
|
||||
u32 dst_index;
|
||||
u32 src_index;
|
||||
};
|
||||
|
||||
static insert_mask_info try_get_insert_mask_info(v128 mask);
|
||||
|
||||
//0 - 10
|
||||
void STOP(spu_opcode_t op)
|
||||
{
|
||||
@ -959,6 +968,27 @@ public:
|
||||
}
|
||||
void SHUFB(spu_opcode_t op)
|
||||
{
|
||||
const auto [is_const, value] = try_get_const_value(op.rc);
|
||||
|
||||
if (is_const)
|
||||
{
|
||||
const auto [size, dst, src] = try_get_insert_mask_info(value);
|
||||
|
||||
if (size)
|
||||
{
|
||||
if ((size >= 4u && !src) || (size == 2u && src == 1u) || (size == 1u && src == 3u))
|
||||
{
|
||||
// Comment insertion pattern for CWD-alike instruction
|
||||
DisAsm("shufb", spu_reg_name[op.rt4], spu_reg_name[op.ra], spu_reg_name[op.rb], fmt::format("%s #i%u[%u]", spu_reg_name[op.rc], size * 8, dst).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
// Comment insertion pattern for unknown instruction formations
|
||||
DisAsm("shufb", spu_reg_name[op.rt4], spu_reg_name[op.ra], spu_reg_name[op.rb], fmt::format("%s #i%u[%u] = [%u]", spu_reg_name[op.rc], size * 8, dst, src).c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DisAsm("shufb", spu_reg_name[op.rt4], spu_reg_name[op.ra], spu_reg_name[op.rb], spu_reg_name[op.rc]);
|
||||
}
|
||||
void MPYA(spu_opcode_t op)
|
||||
|
Loading…
Reference in New Issue
Block a user