Module: wine Branch: master Commit: f86ea4cbe9fb81c3c8edc583214f8149d6df2fcc URL: http://source.winehq.org/git/wine.git/?a=commit;h=f86ea4cbe9fb81c3c8edc58321...
Author: André Hentschel nerv@dawncrow.de Date: Tue May 1 19:45:45 2012 +0200
winedbg: Complete the Thumb disassembler.
---
programs/winedbg/be_arm.c | 77 +++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 71 insertions(+), 6 deletions(-)
diff --git a/programs/winedbg/be_arm.c b/programs/winedbg/be_arm.c index 7da28b6..8ceb14c 100644 --- a/programs/winedbg/be_arm.c +++ b/programs/winedbg/be_arm.c @@ -67,7 +67,7 @@ static char const tbl_shifts[][4] = { };
static char const tbl_hiops_t[][4] = { -"add", "cmp", "mov", "bx" + "add", "cmp", "mov", "bx" };
static char const tbl_aluops_t[][4] = { @@ -76,7 +76,11 @@ static char const tbl_aluops_t[][4] = { };
static char const tbl_immops_t[][4] = { -"mov", "cmp", "add", "sub" + "mov", "cmp", "add", "sub" +}; + +static char const tbl_sregops_t[][5] = { + "strh", "ldsb", "ldrh", "ldsh" };
static UINT db_get_inst(void* addr, int size) @@ -368,7 +372,7 @@ static WORD thumb_disasm_aluop(WORD inst, ADDRESS64 *addr) return 0; }
-static WORD thumb_disasm_blocktrans(WORD inst, ADDRESS64 *addr) +static WORD thumb_disasm_pushpop(WORD inst, ADDRESS64 *addr) { short lrpc = (inst >> 8) & 0x01; short load = (inst >> 11) & 0x01; @@ -388,7 +392,30 @@ static WORD thumb_disasm_blocktrans(WORD inst, ADDRESS64 *addr) else dbg_printf("%s, ", tbl_regs[i]); } if (lrpc) - dbg_printf(", %s", load ? "pc" : "lr"); + dbg_printf("%s%s", last ? ", " : "", load ? "pc" : "lr"); + + dbg_printf("}"); + return 0; +} + +static WORD thumb_disasm_blocktrans(WORD inst, ADDRESS64 *addr) +{ + short load = (inst >> 11) & 0x01; + short i; + short last; + + for (i=7;i>=0;i--) + if ((inst>>i) & 1) break; + last = i; + + dbg_printf("\n\t%s\t%s!, {", load ? "ldmia" : "stmia", tbl_regs[(inst >> 8) & 0x07]); + + for (i=0;i<=7;i++) + if ((inst>>i) & 1) + { + if (i == last) dbg_printf("%s", tbl_regs[i]); + else dbg_printf("%s, ", tbl_regs[i]); + }
dbg_printf("}"); return 0; @@ -417,6 +444,18 @@ static WORD thumb_disasm_condbranch(WORD inst, ADDRESS64 *addr) return 0; }
+static WORD thumb_disasm_uncondbranch(WORD inst, ADDRESS64 *addr) +{ + short offset = (inst & 0x07ff) << 1; + + if (offset & 0x0800) offset |= 0xf000; + offset += 4; + + dbg_printf("\n\tb\t"); + db_printsym(addr->Offset + offset); + return 0; +} + static WORD thumb_disasm_loadadr(WORD inst, ADDRESS64 *addr) { WORD src = (inst >> 11) & 0x01; @@ -471,6 +510,28 @@ static WORD thumb_disasm_ldrimm(WORD inst, ADDRESS64 *addr) return 0; }
+static WORD thumb_disasm_ldrhimm(WORD inst, ADDRESS64 *addr) +{ + WORD offset = (inst & 0x07c0) >> 5; + dbg_printf("\n\t%s\t%s, [%s, #%u]", (inst & 0x0800)?"ldrh":"strh", + tbl_regs[inst & 0x07], tbl_regs[(inst >> 3) & 0x07], offset); + return 0; +} + +static WORD thumb_disasm_ldrreg(WORD inst, ADDRESS64 *addr) +{ + dbg_printf("\n\t%s%s\t%s, [%s, %s]", (inst & 0x0800)?"ldr":"str", (inst & 0x0400)?"b":"", + tbl_regs[inst & 0x07], tbl_regs[(inst >> 3) & 0x07], tbl_regs[(inst >> 6) & 0x07]); + return 0; +} + +static WORD thumb_disasm_ldrsreg(WORD inst, ADDRESS64 *addr) +{ + dbg_printf("\n\t%s\t%s, [%s, %s]", tbl_sregops_t[(inst >> 10) & 0x03], + tbl_regs[inst & 0x07], tbl_regs[(inst >> 3) & 0x07], tbl_regs[(inst >> 6) & 0x07]); + return 0; +} + static WORD thumb_disasm_immop(WORD inst, ADDRESS64 *addr) { WORD op = (inst >> 11) & 0x03; @@ -531,16 +592,20 @@ struct inst_thumb16 static const struct inst_thumb16 tbl_thumb16[] = { { 0xfc00, 0x4400, thumb_disasm_hireg }, { 0xfc00, 0x4000, thumb_disasm_aluop }, - { 0xf600, 0xb400, thumb_disasm_blocktrans }, + { 0xf600, 0xb400, thumb_disasm_pushpop }, + { 0xf000, 0xc000, thumb_disasm_blocktrans }, { 0xf800, 0xf000, thumb_disasm_longbl }, { 0xf000, 0xd000, thumb_disasm_condbranch }, + { 0xf800, 0xe000, thumb_disasm_uncondbranch }, { 0xf000, 0xa000, thumb_disasm_loadadr }, { 0xf800, 0x4800, thumb_disasm_ldrpcrel }, { 0xf000, 0x9000, thumb_disasm_ldrsprel }, { 0xff00, 0xb000, thumb_disasm_addsprel }, { 0xe000, 0x6000, thumb_disasm_ldrimm }, + { 0xf000, 0x8000, thumb_disasm_ldrhimm }, + { 0xf200, 0x5000, thumb_disasm_ldrreg }, + { 0xf200, 0x5200, thumb_disasm_ldrsreg }, { 0xe000, 0x2000, thumb_disasm_immop }, - { 0xf000, 0xd000, thumb_disasm_condbranch }, { 0xff00, 0xdf00, thumb_disasm_swi }, { 0xff00, 0xbf00, thumb_disasm_nop }, { 0xf800, 0x1800, thumb_disasm_addsub },