mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-04 05:51:27 +12:00
SPU/PPU DisAsm: Implement more constant formation patterns
This commit is contained in:
parent
a4bd1755cf
commit
12efd29121
3 changed files with 83 additions and 19 deletions
|
@ -1278,6 +1278,12 @@ void PPUDisAsm::ADDI(ppu_opcode_t op)
|
|||
else
|
||||
{
|
||||
DisAsm_R2_IMM("addi", 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1290,6 +1296,12 @@ void PPUDisAsm::ADDIS(ppu_opcode_t op)
|
|||
else
|
||||
{
|
||||
DisAsm_R2_IMM("addis", 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 * 65536);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1601,16 +1613,34 @@ void PPUDisAsm::ORIS(ppu_opcode_t op)
|
|||
{
|
||||
if (op.rs == 0 && op.ra == 0 && op.uimm16 == 0) { last_opcode += "nop"; return; }
|
||||
DisAsm_R2_IMM("oris", op.ra, op.rs, op.uimm16);
|
||||
|
||||
if (auto [is_const, value] = try_get_const_gpr_value(op.rs); is_const)
|
||||
{
|
||||
// Comment constant formation
|
||||
comment_constant(last_opcode, value | (op.uimm16 << 16));
|
||||
}
|
||||
}
|
||||
|
||||
void PPUDisAsm::XORI(ppu_opcode_t op)
|
||||
{
|
||||
DisAsm_R2_IMM("xori", op.ra, op.rs, op.uimm16);
|
||||
|
||||
if (auto [is_const, value] = try_get_const_gpr_value(op.rs); is_const)
|
||||
{
|
||||
// Comment constant formation
|
||||
comment_constant(last_opcode, value ^ op.uimm16);
|
||||
}
|
||||
}
|
||||
|
||||
void PPUDisAsm::XORIS(ppu_opcode_t op)
|
||||
{
|
||||
DisAsm_R2_IMM("xoris", op.ra, op.rs, op.uimm16);
|
||||
|
||||
if (auto [is_const, value] = try_get_const_gpr_value(op.rs); is_const)
|
||||
{
|
||||
// Comment constant formation
|
||||
comment_constant(last_opcode, value ^ (op.uimm16 << 16));
|
||||
}
|
||||
}
|
||||
|
||||
void PPUDisAsm::ANDI(ppu_opcode_t op)
|
||||
|
|
|
@ -347,27 +347,12 @@ void SPUDisAsm::IOHL(spu_opcode_t op)
|
|||
{
|
||||
DisAsm("iohl", spu_reg_name[op.rt], op.i16);
|
||||
|
||||
const auto [is_const, value] = try_get_const_value(op.rt);
|
||||
|
||||
u32 val0 = value._u32[0];
|
||||
const auto [is_const, value] = try_get_const_equal_value_array<u32>(op.rt);
|
||||
|
||||
// Only print constant for a 4 equal 32-bit constants array
|
||||
if (is_const && value == v128::from32p(val0))
|
||||
if (is_const)
|
||||
{
|
||||
// Fixup value
|
||||
val0 |= op.i16;
|
||||
|
||||
// Test if potentially a CELL error
|
||||
if ((val0 >> 28) == 0x8u)
|
||||
{
|
||||
// Comment as CELL error
|
||||
fmt::append(last_opcode, " #%s (0x%x)", CellError{val0}, val0);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Comment constant formation
|
||||
fmt::append(last_opcode, " #0x%x", val0);
|
||||
}
|
||||
comment_constant(last_opcode, value | op.i16);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
#include "PPCDisAsm.h"
|
||||
#include "SPUOpcodes.h"
|
||||
#include "util/v128.hpp"
|
||||
|
||||
union v128;
|
||||
enum spu_stop_syscall : u32;
|
||||
|
||||
static constexpr const char* spu_reg_name[128] =
|
||||
|
@ -74,6 +74,8 @@ namespace utils
|
|||
class shm;
|
||||
}
|
||||
|
||||
void comment_constant(std::string& last_opocde, u64 value);
|
||||
|
||||
class SPUDisAsm final : public PPCDisAsm
|
||||
{
|
||||
std::shared_ptr<utils::shm> m_shm;
|
||||
|
@ -186,6 +188,35 @@ public:
|
|||
std::unique_ptr<CPUDisAsm> copy_type_erased() const override;
|
||||
std::pair<bool, v128> try_get_const_value(u32 reg, u32 pc = -1, u32 TTL = 10) const;
|
||||
|
||||
// Get constant value if the original array is made of only repetitions of the same value
|
||||
template <typename T> requires (sizeof(T) < sizeof(v128) && !(sizeof(v128) % sizeof(T)))
|
||||
std::pair<bool, T> try_get_const_equal_value_array(u32 reg, u32 pc = -1, u32 TTL = 10) const
|
||||
{
|
||||
auto [ok, res] = try_get_const_value(reg, pc, TTL);
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
v128 test_value{};
|
||||
|
||||
T sample{};
|
||||
std::memcpy(&sample, res._bytes, sizeof(T));
|
||||
|
||||
for (u32 i = 0; i < sizeof(v128); i += sizeof(T))
|
||||
{
|
||||
std::memcpy(test_value._bytes + i, &sample, sizeof(T));
|
||||
}
|
||||
|
||||
if (test_value != res)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return {ok, sample};
|
||||
}
|
||||
|
||||
struct insert_mask_info
|
||||
{
|
||||
u32 type_size;
|
||||
|
@ -860,6 +891,12 @@ public:
|
|||
}
|
||||
|
||||
DisAsm("ori", spu_reg_name[op.rt], spu_reg_name[op.ra], op.si10);
|
||||
|
||||
if (auto [is_const, value] = try_get_const_equal_value_array<u32>(+op.ra); is_const)
|
||||
{
|
||||
// Comment constant formation
|
||||
comment_constant(last_opcode, value | static_cast<u32>(op.si10));
|
||||
}
|
||||
}
|
||||
void ORHI(spu_opcode_t op)
|
||||
{
|
||||
|
@ -892,6 +929,12 @@ public:
|
|||
void AI(spu_opcode_t op)
|
||||
{
|
||||
DisAsm("ai", spu_reg_name[op.rt], spu_reg_name[op.ra], op.si10);
|
||||
|
||||
if (auto [is_const, value] = try_get_const_equal_value_array<u32>(op.ra); is_const)
|
||||
{
|
||||
// Comment constant formation
|
||||
comment_constant(last_opcode, value + static_cast<u32>(op.si10));
|
||||
}
|
||||
}
|
||||
void AHI(spu_opcode_t op)
|
||||
{
|
||||
|
@ -908,6 +951,12 @@ public:
|
|||
void XORI(spu_opcode_t op)
|
||||
{
|
||||
DisAsm("xori", spu_reg_name[op.rt], spu_reg_name[op.ra], op.si10);
|
||||
|
||||
if (auto [is_const, value] = try_get_const_equal_value_array<u32>(op.ra); is_const)
|
||||
{
|
||||
// Comment constant formation
|
||||
comment_constant(last_opcode, value ^ static_cast<u32>(op.si10));
|
||||
}
|
||||
}
|
||||
void XORHI(spu_opcode_t op)
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue