mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-21 03:55:32 +00:00
ppu disasm: Implement BCLR's, BCCTR's and BC's extended mnemonics
Also: BCCTR cr bit is now shown as cr(bit/4)[bit % 4] BLRL is now shown properly BDN?Z[TF](LR?)L?A? branches are now implemented.
This commit is contained in:
parent
5978b1f28f
commit
1e303e9f97
2 changed files with 209 additions and 117 deletions
|
@ -11,6 +11,136 @@ u32 PPUDisAsm::disasm(u32 pc)
|
|||
return 4;
|
||||
}
|
||||
|
||||
constexpr std::pair<const char*, char> get_BC_info(u32 bo, u32 bi)
|
||||
{
|
||||
std::pair<const char*, char> info{};
|
||||
|
||||
switch (bo)
|
||||
{
|
||||
case 0b00000:
|
||||
case 0b00001:
|
||||
{
|
||||
info = {"bdnzf", 'f'}; break;
|
||||
}
|
||||
case 0b00010:
|
||||
case 0b00011:
|
||||
{
|
||||
info = {"bdzf", 'f'}; break;
|
||||
}
|
||||
case 0b01000:
|
||||
case 0b01001:
|
||||
{
|
||||
info = {"bdnzt", 't'}; break;
|
||||
}
|
||||
case 0b01010:
|
||||
case 0b01011:
|
||||
{
|
||||
info = {"bdzt", 't'}; break;
|
||||
}
|
||||
case 0b10010:
|
||||
{
|
||||
info.first = "bdz"; break;
|
||||
}
|
||||
case 0b11010:
|
||||
{
|
||||
info = {"bdz", '-'}; break;
|
||||
}
|
||||
case 0b11011:
|
||||
{
|
||||
info = {"bdz", '+'}; break;
|
||||
}
|
||||
case 0b10000:
|
||||
{
|
||||
info.first = "bdnz"; break;
|
||||
}
|
||||
case 0b11000:
|
||||
{
|
||||
info = {"bdnz", '-'}; break;
|
||||
}
|
||||
case 0b11001:
|
||||
{
|
||||
info = {"bdnz", '+'}; break;
|
||||
}
|
||||
case 0b00100:
|
||||
{
|
||||
switch (bi % 4)
|
||||
{
|
||||
case 0x0: info.first = "bge"; break;
|
||||
case 0x1: info.first = "ble"; break;
|
||||
case 0x2: info.first = "bne"; break;
|
||||
case 0x3: info.first = "bns"; break;
|
||||
default: ASSUME(0); break;
|
||||
}
|
||||
}
|
||||
case 0b00110:
|
||||
{
|
||||
info.second = '-';
|
||||
switch (bi % 4)
|
||||
{
|
||||
case 0x0: info.first = "bge"; break;
|
||||
case 0x1: info.first = "ble"; break;
|
||||
case 0x2: info.first = "bne"; break;
|
||||
case 0x3: info.first = "bns"; break;
|
||||
default: ASSUME(0); break;
|
||||
}
|
||||
}
|
||||
case 0b00111:
|
||||
{
|
||||
info.second = '+';
|
||||
switch (bi % 4)
|
||||
{
|
||||
case 0x0: info.first = "bge"; break;
|
||||
case 0x1: info.first = "ble"; break;
|
||||
case 0x2: info.first = "bne"; break;
|
||||
case 0x3: info.first = "bns"; break;
|
||||
default: ASSUME(0); break;
|
||||
}
|
||||
}
|
||||
case 0b01100:
|
||||
{
|
||||
switch (bi % 4)
|
||||
{
|
||||
case 0x0: info.first = "blt"; break;
|
||||
case 0x1: info.first = "bgt"; break;
|
||||
case 0x2: info.first = "beq"; break;
|
||||
case 0x3: info.first = "bso"; break;
|
||||
default: ASSUME(0); break;
|
||||
}
|
||||
}
|
||||
case 0b01110:
|
||||
{
|
||||
info.second = '-';
|
||||
switch (bi % 4)
|
||||
{
|
||||
case 0x0: info.first = "blt"; break;
|
||||
case 0x1: info.first = "bgt"; break;
|
||||
case 0x2: info.first = "beq"; break;
|
||||
case 0x3: info.first = "bso"; break;
|
||||
default: ASSUME(0); break;
|
||||
}
|
||||
}
|
||||
case 0b01111:
|
||||
{
|
||||
info.second = '+';
|
||||
switch (bi % 4)
|
||||
{
|
||||
case 0x0: info.first = "blt"; break;
|
||||
case 0x1: info.first = "bgt"; break;
|
||||
case 0x2: info.first = "beq"; break;
|
||||
case 0x3: info.first = "bso"; break;
|
||||
default: ASSUME(0); break;
|
||||
}
|
||||
}
|
||||
//case 0b10100:
|
||||
//{
|
||||
// info.first = "b"; break;
|
||||
//}
|
||||
default: break;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
void PPUDisAsm::MFVSCR(ppu_opcode_t op)
|
||||
{
|
||||
DisAsm_V1("mfvscr", op.vd);
|
||||
|
@ -804,122 +934,38 @@ void PPUDisAsm::BC(ppu_opcode_t op)
|
|||
return;
|
||||
}
|
||||
|
||||
const u8 bo0 = (bo & 0x10) ? 1 : 0;
|
||||
const u8 bo1 = (bo & 0x08) ? 1 : 0;
|
||||
const u8 bo2 = (bo & 0x04) ? 1 : 0;
|
||||
const u8 bo3 = (bo & 0x02) ? 1 : 0;
|
||||
const u8 bo4 = (bo & 0x01) ? 1 : 0;
|
||||
const auto [inst, sign] = get_BC_info(bo, bi);
|
||||
|
||||
std::add_pointer_t<const char> inst{""}, sign = inst;
|
||||
|
||||
if (bo0 && !bo1 && !bo2 && bo3 && !bo4)
|
||||
if (!inst)
|
||||
{
|
||||
inst = "bdz";
|
||||
}
|
||||
else if (bo0 && bo1 && !bo2 && bo3 && !bo4)
|
||||
{
|
||||
inst = "bdz", sign = "-";
|
||||
}
|
||||
else if (bo0 && bo1 && !bo2 && bo3 && bo4)
|
||||
{
|
||||
inst = "bdz", sign = "+";
|
||||
}
|
||||
else if (bo0 && !bo1 && !bo2 && !bo3 && !bo4)
|
||||
{
|
||||
inst = "bdnz";
|
||||
}
|
||||
else if (bo0 && bo1 && !bo2 && !bo3 && !bo4)
|
||||
{
|
||||
inst = "bdnz", sign = "-";
|
||||
}
|
||||
else if (bo0 && bo1 && !bo2 && !bo3 && bo4)
|
||||
{
|
||||
inst = "bdnz", sign = "+";
|
||||
}
|
||||
else if (!bo0 && !bo1 && bo2 && !bo3 && !bo4)
|
||||
{
|
||||
switch (bi % 4)
|
||||
{
|
||||
case 0x0: inst = "bge"; break;
|
||||
case 0x1: inst = "ble"; break;
|
||||
case 0x2: inst = "bne"; break;
|
||||
case 0x3: inst = "bns"; break;
|
||||
default: ASSUME(0); break;
|
||||
}
|
||||
}
|
||||
else if (!bo0 && !bo1 && bo2 && bo3 && !bo4)
|
||||
{
|
||||
sign = "-";
|
||||
switch (bi % 4)
|
||||
{
|
||||
case 0x0: inst = "bge"; break;
|
||||
case 0x1: inst = "ble"; break;
|
||||
case 0x2: inst = "bne"; break;
|
||||
case 0x3: inst = "bns"; break;
|
||||
default: ASSUME(0); break;
|
||||
}
|
||||
}
|
||||
else if (!bo0 && !bo1 && bo2 && bo3 && bo4)
|
||||
{
|
||||
sign = "+";
|
||||
switch (bi % 4)
|
||||
{
|
||||
case 0x0: inst = "bge"; break;
|
||||
case 0x1: inst = "ble"; break;
|
||||
case 0x2: inst = "bne"; break;
|
||||
case 0x3: inst = "bns"; break;
|
||||
default: ASSUME(0); break;
|
||||
}
|
||||
}
|
||||
else if (!bo0 && bo1 && bo2 && !bo3 && !bo4)
|
||||
{
|
||||
switch (bi % 4)
|
||||
{
|
||||
case 0x0: inst = "blt"; break;
|
||||
case 0x1: inst = "bgt"; break;
|
||||
case 0x2: inst = "beq"; break;
|
||||
case 0x3: inst = "bso"; break;
|
||||
default: ASSUME(0); break;
|
||||
}
|
||||
}
|
||||
else if (!bo0 && bo1 && bo2 && bo3 && !bo4)
|
||||
{
|
||||
sign = "-";
|
||||
switch (bi % 4)
|
||||
{
|
||||
case 0x0: inst = "blt"; break;
|
||||
case 0x1: inst = "bgt"; break;
|
||||
case 0x2: inst = "beq"; break;
|
||||
case 0x3: inst = "bso"; break;
|
||||
default: ASSUME(0); break;
|
||||
}
|
||||
}
|
||||
else if (!bo0 && bo1 && bo2 && bo3 && bo4)
|
||||
{
|
||||
sign = "+";
|
||||
switch (bi % 4)
|
||||
{
|
||||
case 0x0: inst = "blt"; break;
|
||||
case 0x1: inst = "bgt"; break;
|
||||
case 0x2: inst = "beq"; break;
|
||||
case 0x3: inst = "bso"; break;
|
||||
default: ASSUME(0); break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return Write(fmt::format("bc 0x%x, 0x%x, 0x%x, %d, %d", bo, bi, bd, aa, lk));
|
||||
Write(fmt::format("bc 0x%x, 0x%x, 0x%x, %d, %d", bo, bi, bd, aa, lk));
|
||||
return;
|
||||
}
|
||||
|
||||
const auto msg = std::string(inst) + (lk ? "l" : "") + (aa ? "a" : "") + sign;
|
||||
const auto final = std::string(inst) + (lk ? "l" : "") + (aa ? "a" : "") + sign;
|
||||
|
||||
// Check if need to display full BI value
|
||||
if (sign == 't' || sign == 'f')
|
||||
{
|
||||
if (aa)
|
||||
{
|
||||
DisAsm_BI_BRANCH_A(final, bi, bd);
|
||||
}
|
||||
else
|
||||
{
|
||||
DisAsm_BI_BRANCH(final, bi, bd);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (aa)
|
||||
{
|
||||
DisAsm_CR_BRANCH_A(msg, bi / 4, bd);
|
||||
DisAsm_CR_BRANCH_A(final, bi / 4, bd);
|
||||
}
|
||||
else
|
||||
{
|
||||
DisAsm_CR_BRANCH(msg, bi / 4, bd);
|
||||
DisAsm_CR_BRANCH(final, bi / 4, bd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -974,14 +1020,33 @@ void PPUDisAsm::BCLR(ppu_opcode_t op)
|
|||
{
|
||||
const u32 bo = op.bo;
|
||||
const u32 bi = op.bi;
|
||||
const u32 bh = op.bh;
|
||||
const u32 lk = op.lk;
|
||||
|
||||
const u8 bo0 = (bo & 0x10) ? 1 : 0;
|
||||
const u8 bo1 = (bo & 0x08) ? 1 : 0;
|
||||
const u8 bo2 = (bo & 0x04) ? 1 : 0;
|
||||
const u8 bo3 = (bo & 0x02) ? 1 : 0;
|
||||
if (bo == 0b10100)
|
||||
{
|
||||
Write(lk ? "blrl" : "blr");
|
||||
return;
|
||||
}
|
||||
|
||||
if (bo0 && !bo1 && bo2 && !bo3) { Write("blr"); return; }
|
||||
Write(fmt::format("bclr [%x:%x:%x:%x], cr%d[%x], %d, %d", bo0, bo1, bo2, bo3, bi / 4, bi % 4, op.bh, op.lk));
|
||||
const auto [inst, sign] = get_BC_info(bo, bi);
|
||||
|
||||
if (!inst)
|
||||
{
|
||||
Write(fmt::format("bclr %d, cr%d[%x], %d, %d", bo, bi / 4, get_partial_BI_field(bi), bh, lk));
|
||||
return;
|
||||
}
|
||||
|
||||
const auto final = std::string(inst) + (lk ? "lrl" : "lr") + sign;
|
||||
|
||||
// Check if need to display full BI value
|
||||
if (sign == 't' || sign == 'f')
|
||||
{
|
||||
DisAsm_BI_BRANCH(final, bi, bh);
|
||||
return;
|
||||
}
|
||||
|
||||
DisAsm_CR_BRANCH(final, bi / 4, bh);
|
||||
}
|
||||
|
||||
void PPUDisAsm::CRNOR(ppu_opcode_t op)
|
||||
|
@ -1034,17 +1099,24 @@ void PPUDisAsm::BCCTR(ppu_opcode_t op)
|
|||
const u32 bo = op.bo;
|
||||
const u32 bi = op.bi;
|
||||
const u32 bh = op.bh;
|
||||
const u32 lk = op.lk;
|
||||
|
||||
if (bo == 20)
|
||||
if (bo == 0b10100)
|
||||
{
|
||||
return Write(op.lk ? "bctrl" : "bctr");
|
||||
Write(lk ? "bctrl" : "bctr");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (op.lk)
|
||||
const auto [inst, sign] = get_BC_info(bo, bi);
|
||||
|
||||
if (!inst || inst[1] == 'd')
|
||||
{
|
||||
case 0: DisAsm_INT3("bcctr", bo, bi, bh); break;
|
||||
case 1: DisAsm_INT3("bcctrl", bo, bi, bh); break;
|
||||
// Invalid or unknown bcctr form
|
||||
Write(fmt::format("bcctr %d, cr%d[%x], %d, %d", bo, bi / 4, bi % 4, bh, lk));
|
||||
return;
|
||||
}
|
||||
|
||||
DisAsm_CR_BRANCH(std::string(inst) + (lk ? "ctrl" : "clr") + sign, bi / 4, bh);
|
||||
}
|
||||
|
||||
void PPUDisAsm::RLWIMI(ppu_opcode_t op)
|
||||
|
|
|
@ -16,6 +16,18 @@ private:
|
|||
return dump_pc + (imm & ~3);
|
||||
}
|
||||
|
||||
constexpr const char* get_partial_BI_field(u32 bi)
|
||||
{
|
||||
switch (bi % 4)
|
||||
{
|
||||
case 0x0: return "lt";
|
||||
case 0x1: return "gt";
|
||||
case 0x2: return "eq";
|
||||
case 0x3: return "so";
|
||||
default: ASSUME(0); return {};
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void DisAsm_V4(const std::string& op, u32 v0, u32 v1, u32 v2, u32 v3)
|
||||
{
|
||||
|
@ -243,6 +255,14 @@ private:
|
|||
{
|
||||
Write(fmt::format("%s cr%d,0x%x ", FixOp(op).c_str(), cr, pc));
|
||||
}
|
||||
void DisAsm_BI_BRANCH(const std::string& op, u32 bi, const int pc)
|
||||
{
|
||||
Write(fmt::format("%s cr%d[%s],0x%x ", FixOp(op).c_str(), bi / 4, get_partial_BI_field(bi), DisAsmBranchTarget(pc)));
|
||||
}
|
||||
void DisAsm_BI_BRANCH_A(const std::string& op, u32 bi, const int pc)
|
||||
{
|
||||
Write(fmt::format("%s cr%d[%s],0x%x ", FixOp(op).c_str(), bi / 4, get_partial_BI_field(bi), pc));
|
||||
}
|
||||
|
||||
public:
|
||||
u32 disasm(u32 pc) override;
|
||||
|
|
Loading…
Add table
Reference in a new issue