diff --git a/src/xenia/cpu/ppc/ppc_opcode_disasm.cc b/src/xenia/cpu/ppc/ppc_opcode_disasm.cc index 58742fbf7..8daf0191e 100644 --- a/src/xenia/cpu/ppc/ppc_opcode_disasm.cc +++ b/src/xenia/cpu/ppc/ppc_opcode_disasm.cc @@ -191,17 +191,147 @@ void PrintDisasm_bclrx(const PPCDecodeData& d, StringBuffer* str) { str->AppendFormat("%d", d.XL.BI()); } void PrintDisasm_bcx(const PPCDecodeData& d, StringBuffer* str) { - // bc[LK][AA] [BO], [BI], [ADDR] + // [bc][LK][AA][+-] [BO], [BI], [ADDR] size_t str_start = str->length(); - str->Append("bc"); - if (d.B.LK()) str->Append('l'); - if (d.B.AA()) str->Append('a'); - PadStringBuffer(str, str_start, kNamePad); - str->AppendFormat("%d", d.B.BO()); + + const uint32_t bo = d.B.BO(); + const uint32_t bi = d.B.BI(); + const uint32_t addr = d.B.ADDR(); + + const bool bo0 = bo & 0x10; + const bool bo1 = bo & 0x08; + const bool bo2 = bo & 0x04; + const bool bo3 = bo & 0x02; + const bool bo4 = bo & 0x01; + int sign_char = 0; // Default no sign + + if (bo0 && !bo1 && !bo2 && bo3 && !bo4) { + str->Append("bdz"); + } else if (bo0 && bo1 && !bo2 && bo3 && !bo4) { + str->Append("bdz"); + sign_char = -1; + } else if (bo0 && bo1 && !bo2 && bo3 && bo4) { + str->Append("bdz"); + sign_char = +1; + } else if (bo0 && !bo1 && !bo2 && !bo3 && !bo4) { + str->Append("bdnz"); + } else if (bo0 && bo1 && !bo2 && !bo3 && !bo4) { + str->Append("bdnz"); + sign_char = -1; + } else if (bo0 && bo1 && !bo2 && !bo3 && bo4) { + str->Append("bdnz"); + sign_char = +1; + } else if (!bo0 && !bo1 && bo2 && !bo3 && !bo4) { + switch (bi % 4) { + case 0x0: + str->Append("bge"); + break; + case 0x1: + str->Append("ble"); + break; + case 0x2: + str->Append("bne"); + break; + } + } else if (!bo0 && !bo1 && bo2 && bo3 && !bo4) { + switch (bi % 4) { + case 0x0: + str->Append("bge"); + sign_char = -1; + break; + case 0x1: + str->Append("ble"); + sign_char = -1; + break; + case 0x2: + str->Append("bne"); + sign_char = -1; + break; + } + } else if (!bo0 && !bo1 && bo2 && bo3 && bo4) { + switch (bi % 4) { + case 0x0: + str->Append("bge"); + sign_char = +1; + break; + case 0x1: + str->Append("ble"); + sign_char = +1; + break; + case 0x2: + str->Append("bne"); + sign_char = +1; + break; + } + } else if (!bo0 && bo1 && bo2 && !bo3 && !bo4) { + switch (bi % 4) { + case 0x0: + str->Append("blt"); + break; + case 0x1: + str->Append("bgt"); + break; + case 0x2: + str->Append("beq"); + break; + } + } else if (!bo0 && bo1 && bo2 && bo3 && !bo4) { + switch (bi % 4) { + case 0x0: + str->Append("blt"); + sign_char = -1; + break; + case 0x1: + str->Append("bgt"); + sign_char = -1; + break; + case 0x2: + str->Append("beq"); + sign_char = -1; + break; + } + } else if (!bo0 && bo1 && bo2 && bo3 && bo4) { + switch (bi % 4) { + case 0x0: + str->Append("blt"); + sign_char = +1; + break; + case 0x1: + str->Append("bgt"); + sign_char = +1; + break; + case 0x2: + str->Append("beq"); + sign_char = +1; + break; + } + } + + if (str_start == str->length()) { + // Default + str->Append("bc"); + if (d.B.LK()) str->Append('l'); + if (d.B.AA()) str->Append('a'); + PadStringBuffer(str, str_start, kNamePad); + str->AppendFormat("%d", bo); + str->Append(", "); + str->AppendFormat("%d", bi); + } else { + if (d.B.LK()) str->Append('l'); + if (d.B.AA()) str->Append('a'); + + if (sign_char > 0) { + str->Append('+'); + } else if (sign_char < 0) { + str->Append('-'); + } + + PadStringBuffer(str, str_start, kNamePad); + str->AppendFormat("crf%d", bi / 4); + } + str->Append(", "); - str->AppendFormat("%d", d.B.BI()); - str->Append(", "); - str->AppendFormat("0x%X", d.B.ADDR()); + str->AppendFormat("0x%X", addr); } void PrintDisasm_bx(const PPCDecodeData& d, StringBuffer* str) { // b[LK][AA] [ADDR]