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
|
else
|
||||||
{
|
{
|
||||||
DisAsm_R2_IMM("addi", op.rd, op.ra, op.simm16);
|
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
|
else
|
||||||
{
|
{
|
||||||
DisAsm_R2_IMM("addis", op.rd, op.ra, op.simm16);
|
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; }
|
if (op.rs == 0 && op.ra == 0 && op.uimm16 == 0) { last_opcode += "nop"; return; }
|
||||||
DisAsm_R2_IMM("oris", op.ra, op.rs, op.uimm16);
|
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)
|
void PPUDisAsm::XORI(ppu_opcode_t op)
|
||||||
{
|
{
|
||||||
DisAsm_R2_IMM("xori", op.ra, op.rs, op.uimm16);
|
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)
|
void PPUDisAsm::XORIS(ppu_opcode_t op)
|
||||||
{
|
{
|
||||||
DisAsm_R2_IMM("xoris", op.ra, op.rs, op.uimm16);
|
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)
|
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);
|
DisAsm("iohl", spu_reg_name[op.rt], op.i16);
|
||||||
|
|
||||||
const auto [is_const, value] = try_get_const_value(op.rt);
|
const auto [is_const, value] = try_get_const_equal_value_array<u32>(op.rt);
|
||||||
|
|
||||||
u32 val0 = value._u32[0];
|
|
||||||
|
|
||||||
// Only print constant for a 4 equal 32-bit constants array
|
// Only print constant for a 4 equal 32-bit constants array
|
||||||
if (is_const && value == v128::from32p(val0))
|
if (is_const)
|
||||||
{
|
{
|
||||||
// Fixup value
|
comment_constant(last_opcode, value | op.i16);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
#include "PPCDisAsm.h"
|
#include "PPCDisAsm.h"
|
||||||
#include "SPUOpcodes.h"
|
#include "SPUOpcodes.h"
|
||||||
|
#include "util/v128.hpp"
|
||||||
|
|
||||||
union v128;
|
|
||||||
enum spu_stop_syscall : u32;
|
enum spu_stop_syscall : u32;
|
||||||
|
|
||||||
static constexpr const char* spu_reg_name[128] =
|
static constexpr const char* spu_reg_name[128] =
|
||||||
|
@ -74,6 +74,8 @@ namespace utils
|
||||||
class shm;
|
class shm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void comment_constant(std::string& last_opocde, u64 value);
|
||||||
|
|
||||||
class SPUDisAsm final : public PPCDisAsm
|
class SPUDisAsm final : public PPCDisAsm
|
||||||
{
|
{
|
||||||
std::shared_ptr<utils::shm> m_shm;
|
std::shared_ptr<utils::shm> m_shm;
|
||||||
|
@ -186,6 +188,35 @@ public:
|
||||||
std::unique_ptr<CPUDisAsm> copy_type_erased() const override;
|
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;
|
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
|
struct insert_mask_info
|
||||||
{
|
{
|
||||||
u32 type_size;
|
u32 type_size;
|
||||||
|
@ -860,6 +891,12 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
DisAsm("ori", spu_reg_name[op.rt], spu_reg_name[op.ra], op.si10);
|
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)
|
void ORHI(spu_opcode_t op)
|
||||||
{
|
{
|
||||||
|
@ -892,6 +929,12 @@ public:
|
||||||
void AI(spu_opcode_t op)
|
void AI(spu_opcode_t op)
|
||||||
{
|
{
|
||||||
DisAsm("ai", spu_reg_name[op.rt], spu_reg_name[op.ra], op.si10);
|
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)
|
void AHI(spu_opcode_t op)
|
||||||
{
|
{
|
||||||
|
@ -908,6 +951,12 @@ public:
|
||||||
void XORI(spu_opcode_t op)
|
void XORI(spu_opcode_t op)
|
||||||
{
|
{
|
||||||
DisAsm("xori", spu_reg_name[op.rt], spu_reg_name[op.ra], op.si10);
|
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)
|
void XORHI(spu_opcode_t op)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue