ppcdisasm: fix bcctr and bclr instructions.

This commit is contained in:
Maxim Poliakovski 2020-02-13 03:16:47 +01:00
parent 4ecc48a6cc
commit 1543acc696
3 changed files with 99 additions and 64 deletions

View File

@ -36,11 +36,11 @@ const char* bx_mnem[4] = {
}; };
const char* bclrx_mnem[2] = { const char* bclrx_mnem[2] = {
"bclr", "bclrl" "blr", "blrl"
}; };
const char* bcctrx_mnem[2] = { const char* bcctrx_mnem[2] = {
"bcctr", "bcctrl" "bctr", "bctrl"
}; };
const char* br_cond[8] = { /* simplified branch conditions */ const char* br_cond[8] = { /* simplified branch conditions */
@ -376,7 +376,7 @@ void opc_bool_im(PPCDisasmContext* ctx)
if (ctx->simplified) { if (ctx->simplified) {
if (index == 0) { if (index == 0) {
if (imm == 0 && !ra && !rs && !imm) { /* unofficial, produced by IDA */ if (imm == 0 && !ra && !rs && !imm) { /* unofficial, produced by IDA */
ctx->instr_str = "nop"; ctx->instr_str = my_sprintf("%-8s", "nop");
return; return;
} }
} }
@ -482,12 +482,16 @@ void opc_bcctrx(PPCDisasmContext* ctx)
{ {
uint32_t bo, bi, cr; uint32_t bo, bi, cr;
char opcode[10] = "b"; char opcode[10] = "b";
char operands[10] = ""; char operands[4] = "";
bo = (ctx->instr_code >> 21) & 0x1F; bo = (ctx->instr_code >> 21) & 0x1F;
bi = (ctx->instr_code >> 16) & 0x1F; bi = (ctx->instr_code >> 16) & 0x1F;
cr = bi >> 2; cr = bi >> 2;
if (!(bo & 4)) { /* bcctr with BO[2] = 0 is invalid */
opc_illegal(ctx);
}
if (!ctx->simplified || ((bo & 0x10) && bi) || if (!ctx->simplified || ((bo & 0x10) && bi) ||
(((bo & 0x14) == 0x14) && (bo & 0xB) && bi)) { (((bo & 0x14) == 0x14) && (bo & 0xB) && bi)) {
generic_bcctrx(ctx, bo, bi); generic_bcctrx(ctx, bo, bi);
@ -495,7 +499,45 @@ void opc_bcctrx(PPCDisasmContext* ctx)
} }
if ((bo & 0x14) == 0x14) { if ((bo & 0x14) == 0x14) {
ctx->instr_str = my_sprintf("%-8s0x%08X", bcctrx_mnem[0]); ctx->instr_str = my_sprintf("%-8s", bcctrx_mnem[ctx->instr_code & 1]);
return;
}
strcat(opcode, br_cond[((bo >> 1) & 4) | (bi & 3)]);
strcat(opcode, "ctr");
if (cr) {
strcat(operands, "cr0");
operands[2] = cr + '0';
}
if (ctx->instr_code & 1) {
strcat(opcode, "l"); /* add suffix "l" if the LK bit is set */
}
if (bo & 1) { /* incorporate prediction bit if set */
strcat(opcode, "+");
}
ctx->instr_str = my_sprintf("%-8s%s", opcode, operands);
}
void opc_bclrx(PPCDisasmContext* ctx)
{
uint32_t bo, bi, cr;
char opcode[10] = "b";
char operands[12] = "";
bo = (ctx->instr_code >> 21) & 0x1F;
bi = (ctx->instr_code >> 16) & 0x1F;
cr = bi >> 2;
if (!ctx->simplified || ((bo & 0x10) && bi) ||
(((bo & 0x14) == 0x14) && (bo & 0xB) && bi)) {
generic_bclrx(ctx, bo, bi);
return;
}
if ((bo & 0x14) == 0x14) {
ctx->instr_str = my_sprintf("%-8s", bclrx_mnem[ctx->instr_code & 1]);
return; return;
} }
@ -509,77 +551,26 @@ void opc_bcctrx(PPCDisasmContext* ctx)
operands[4] = cr + '0'; operands[4] = cr + '0';
} }
strcat(operands, br_cond[4 + (bi & 3)]); strcat(operands, br_cond[4 + (bi & 3)]);
strcat(operands, ", ");
} }
} }
else { /* CTR ignored */ else { /* CTR ignored */
strcat(opcode, br_cond[((bo >> 1) & 4) | (bi & 3)]); strcat(opcode, br_cond[((bo >> 1) & 4) | (bi & 3)]);
if (cr) { if (cr) {
strcat(operands, "cr0, "); strcat(operands, "cr0");
operands[2] = cr + '0'; operands[2] = cr + '0';
} }
} }
strcat(opcode, "lr");
if (ctx->instr_code & 1) { if (ctx->instr_code & 1) {
strcat(opcode, "l"); /* add suffix "l" if the LK bit is set */ strcat(opcode, "l"); /* add suffix "l" if the LK bit is set */
} }
if (bo & 1) { /* incorporate prediction bit if set */ if (bo & 1) { /* incorporate prediction bit if set */
strcat(opcode, (ctx->instr_code & 0x8000) ? "-" : "+"); strcat(opcode, "+");
} }
ctx->instr_str = my_sprintf("%-8s%s0x%08X", opcode, operands); ctx->instr_str = my_sprintf("%-8s%s", opcode, operands);
}
void opc_bclrx(PPCDisasmContext* ctx)
{
uint32_t bo, bi, cr;
char opcode[10] = "b";
char operands[10] = "";
bo = (ctx->instr_code >> 21) & 0x1F;
bi = (ctx->instr_code >> 16) & 0x1F;
cr = bi >> 2;
if (!ctx->simplified || ((bo & 0x10) && bi) ||
(((bo & 0x14) == 0x14) && (bo & 0xB) && bi)) {
generic_bclrx(ctx, bo, bi);
return;
}
if ((bo & 0x14) == 0x14) {
ctx->instr_str = my_sprintf("%-8s0x%08X", bclrx_mnem[0]);
return;
}
if (!(bo & 4)) {
strcat(opcode, "d");
strcat(opcode, (bo & 2) ? "z" : "nz");
if (!(bo & 0x10)) {
strcat(opcode, (bo & 8) ? "tlr" : "flr");
if (cr) {
strcat(operands, "4*cr0+");
operands[4] = cr + '0';
}
strcat(operands, br_cond[4 + (bi & 3)]);
strcat(operands, ", ");
}
}
else { /* CTR ignored */
strcat(opcode, br_cond[((bo >> 1) & 4) | (bi & 3)]);
if (cr) {
strcat(operands, "cr0, ");
operands[2] = cr + '0';
}
}
if (ctx->instr_code & 1) {
strcat(opcode, "l"); /* add suffix "l" if the LK bit is set */
}
if (bo & 1) { /* incorporate prediction bit if set */
strcat(opcode, (ctx->instr_code & 0x8000) ? "-" : "+");
}
ctx->instr_str = my_sprintf("%-8s%s0x%08X", opcode, operands);
} }
void opc_bx(PPCDisasmContext* ctx) void opc_bx(PPCDisasmContext* ctx)
@ -597,7 +588,7 @@ void opc_ori(PPCDisasmContext* ctx)
auto imm = ctx->instr_code & 0xFFFF; auto imm = ctx->instr_code & 0xFFFF;
if (!ra && !rs && !imm && ctx->simplified) { if (!ra && !rs && !imm && ctx->simplified) {
ctx->instr_str = "nop"; ctx->instr_str = my_sprintf("%-8s", "nop");
return; return;
} }
if (imm == 0 && ctx->simplified) { /* inofficial, produced by IDA */ if (imm == 0 && ctx->simplified) { /* inofficial, produced by IDA */

View File

@ -7,6 +7,50 @@
0xFFF03008,0x48000355,bl,0xFFF0335C 0xFFF03008,0x48000355,bl,0xFFF0335C
0xFFF03000,0x4280035C,b,0xFFF0335C 0xFFF03000,0x4280035C,b,0xFFF0335C
# bcctr variants with simplified mnemonics
0xFFF03000,0x4E800420,bctr
0xFFF03000,0x4E800421,bctrl
0xFFF03000,0x4C820420,bnectr
0xFFF03000,0x4C820421,bnectrl
0xFFF03000,0x4C960420,bnectr,cr5
0xFFF03000,0x4C920421,bnectrl,cr4
0xFFF03000,0x4D980420,bltctr,cr6
0xFFF03000,0x4C9D0420,blectr,cr7
0xFFF03000,0x4D820420,beqctr
0xFFF03000,0x4D960420,beqctr,cr5
0xFFF03000,0x4CA80420,bgectr+,cr2
0xFFF03000,0x4C980421,bgectrl,cr6
0xFFF03000,0x4D810420,bgtctr
0xFFF03000,0x4D850420,bgtctr,cr1
0xFFF03000,0x4D8B0421,bsoctrl,cr2
0xFFF03000,0x4C830420,bnsctr
0xFFF03000,0x4C930420,bnsctr,cr4
# bclr variants with simplified mnemonics
0xFFF03000,0x4E800020,blr
0xFFF03000,0x4E800021,blrl
0xFFF03000,0x4D800020,bltlr
0xFFF03000,0x4D840020,bltlr,cr1
0xFFF03000,0x4C810021,blelrl
0xFFF03000,0x4C8D0020,blelr,cr3
0xFFF03000,0x4DA20020,beqlr+
0xFFF03000,0x4DBE0021,beqlrl+,cr7
0xFFF03000,0x4CA80020,bgelr+,cr2
0xFFF03000,0x4DB90020,bgtlr+,cr6
0xFFF03000,0x4C8A0021,bnelrl,cr2
0xFFF03000,0x4D930020,bsolr,cr4
0xFFF03000,0x4C8F0021,bnslrl,cr3
0xFFF03000,0x4E000020,bdnzlr
0xFFF03000,0x4E200020,bdnzlr+
0xFFF03000,0x4E400020,bdzlr
0xFFF03000,0x4E400021,bdzlrl
0xFFF03000,0x4E600020,bdzlr+
0xFFF03000,0x4C000020,bdnzflr,lt
0xFFF03000,0x4C040020,bdnzflr,4*cr1+lt
0xFFF03000,0x4C5D0021,bdzflrl,4*cr7+gt
0xFFF03000,0x4D020020,bdnztlr,eq
0xFFF03000,0x4D530021,bdztlrl,4*cr4+so
# conditional branches with simplified mnemonics, primary opcode 0x10 # conditional branches with simplified mnemonics, primary opcode 0x10
0xFFF0011C,0x409E2EE4,bne,cr7,0xFFF03000 0xFFF0011C,0x409E2EE4,bne,cr7,0xFFF03000
0xFFF00100,0x40A60098,bne+,cr1,0xFFF00198 0xFFF00100,0x40A60098,bne+,cr1,0xFFF00198
@ -14,6 +58,7 @@
0xFFF03004,0x41200054,bdnzt+,lt,0xFFF03058 0xFFF03004,0x41200054,bdnzt+,lt,0xFFF03058
0xFFF03004,0x40000054,bdnzf,lt,0xFFF03058 0xFFF03004,0x40000054,bdnzf,lt,0xFFF03058
0xFFF03000,0x4106FFF4,bdnzt,4*cr1+eq,0xFFF02FF4 0xFFF03000,0x4106FFF4,bdnzt,4*cr1+eq,0xFFF02FF4
0xFFF03000,0x4001558F,bdnzfla,gt,0x0000558C
# indexed load/store instructions, primary opcode 0x1F # indexed load/store instructions, primary opcode 0x1F
0xFFF00100,0x7D49F02E,lwzx,r10,r9,r30 0xFFF00100,0x7D49F02E,lwzx,r10,r9,r30

Can't render this file because it contains an unexpected character in line 4 and column 24.

View File

@ -53,8 +53,7 @@ static vector<PPCDisasmContext> read_test_data()
/* put instruction mnemonic padded with trailing spaces */ /* put instruction mnemonic padded with trailing spaces */
idisasm << tokens[2]; idisasm << tokens[2];
if (tokens.size() > 3) // don't pad operand-less instructions idisasm << setw(8 - tokens[2].length()) << "";
idisasm << setw(8 - tokens[2].length()) << "";
/* now add comma-separated operands */ /* now add comma-separated operands */
for (i = 3; i < tokens.size(); i++) { for (i = 3; i < tokens.size(); i++) {