From 1543acc696e7c97e0cc797914d6764c5cdedcd67 Mon Sep 17 00:00:00 2001 From: Maxim Poliakovski Date: Thu, 13 Feb 2020 03:16:47 +0100 Subject: [PATCH] ppcdisasm: fix bcctr and bclr instructions. --- cpu/ppc/ppcdisasm.cpp | 115 +++++++++++++++------------------ cpu/ppc/test/ppcdisasmtest.csv | 45 +++++++++++++ cpu/ppc/test/testdisasm.cpp | 3 +- 3 files changed, 99 insertions(+), 64 deletions(-) diff --git a/cpu/ppc/ppcdisasm.cpp b/cpu/ppc/ppcdisasm.cpp index 1015191..cb4bfb1 100644 --- a/cpu/ppc/ppcdisasm.cpp +++ b/cpu/ppc/ppcdisasm.cpp @@ -36,11 +36,11 @@ const char* bx_mnem[4] = { }; const char* bclrx_mnem[2] = { - "bclr", "bclrl" + "blr", "blrl" }; const char* bcctrx_mnem[2] = { - "bcctr", "bcctrl" + "bctr", "bctrl" }; const char* br_cond[8] = { /* simplified branch conditions */ @@ -376,7 +376,7 @@ void opc_bool_im(PPCDisasmContext* ctx) if (ctx->simplified) { if (index == 0) { if (imm == 0 && !ra && !rs && !imm) { /* unofficial, produced by IDA */ - ctx->instr_str = "nop"; + ctx->instr_str = my_sprintf("%-8s", "nop"); return; } } @@ -482,12 +482,16 @@ void opc_bcctrx(PPCDisasmContext* ctx) { uint32_t bo, bi, cr; char opcode[10] = "b"; - char operands[10] = ""; + char operands[4] = ""; bo = (ctx->instr_code >> 21) & 0x1F; bi = (ctx->instr_code >> 16) & 0x1F; cr = bi >> 2; + if (!(bo & 4)) { /* bcctr with BO[2] = 0 is invalid */ + opc_illegal(ctx); + } + if (!ctx->simplified || ((bo & 0x10) && bi) || (((bo & 0x14) == 0x14) && (bo & 0xB) && bi)) { generic_bcctrx(ctx, bo, bi); @@ -495,7 +499,45 @@ void opc_bcctrx(PPCDisasmContext* ctx) } 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; } @@ -509,77 +551,26 @@ void opc_bcctrx(PPCDisasmContext* ctx) 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, "); + strcat(operands, "cr0"); operands[2] = cr + '0'; } } + strcat(opcode, "lr"); + 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) ? "-" : "+"); + strcat(opcode, "+"); } - ctx->instr_str = my_sprintf("%-8s%s0x%08X", 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); + ctx->instr_str = my_sprintf("%-8s%s", opcode, operands); } void opc_bx(PPCDisasmContext* ctx) @@ -597,7 +588,7 @@ void opc_ori(PPCDisasmContext* ctx) auto imm = ctx->instr_code & 0xFFFF; if (!ra && !rs && !imm && ctx->simplified) { - ctx->instr_str = "nop"; + ctx->instr_str = my_sprintf("%-8s", "nop"); return; } if (imm == 0 && ctx->simplified) { /* inofficial, produced by IDA */ diff --git a/cpu/ppc/test/ppcdisasmtest.csv b/cpu/ppc/test/ppcdisasmtest.csv index 2db4746..cdd7231 100644 --- a/cpu/ppc/test/ppcdisasmtest.csv +++ b/cpu/ppc/test/ppcdisasmtest.csv @@ -7,6 +7,50 @@ 0xFFF03008,0x48000355,bl,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 0xFFF0011C,0x409E2EE4,bne,cr7,0xFFF03000 0xFFF00100,0x40A60098,bne+,cr1,0xFFF00198 @@ -14,6 +58,7 @@ 0xFFF03004,0x41200054,bdnzt+,lt,0xFFF03058 0xFFF03004,0x40000054,bdnzf,lt,0xFFF03058 0xFFF03000,0x4106FFF4,bdnzt,4*cr1+eq,0xFFF02FF4 +0xFFF03000,0x4001558F,bdnzfla,gt,0x0000558C # indexed load/store instructions, primary opcode 0x1F 0xFFF00100,0x7D49F02E,lwzx,r10,r9,r30 diff --git a/cpu/ppc/test/testdisasm.cpp b/cpu/ppc/test/testdisasm.cpp index a2b4896..3163e36 100644 --- a/cpu/ppc/test/testdisasm.cpp +++ b/cpu/ppc/test/testdisasm.cpp @@ -53,8 +53,7 @@ static vector read_test_data() /* put instruction mnemonic padded with trailing spaces */ 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 */ for (i = 3; i < tokens.size(); i++) {