=?UTF-8?Q?Andr=C3=A9=20Hentschel=20?=: winedbg: Add partial Thumb disassembler.

Alexandre Julliard julliard at winehq.org
Fri Apr 13 11:03:22 CDT 2012


Module: wine
Branch: master
Commit: e94b8302e3e9a7aaffab851a22a00ec6c0158915
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=e94b8302e3e9a7aaffab851a22a00ec6c0158915

Author: André Hentschel <nerv at dawncrow.de>
Date:   Thu Apr 12 23:36:56 2012 +0200

winedbg: Add partial Thumb disassembler.

---

 programs/winedbg/be_arm.c |  141 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 139 insertions(+), 2 deletions(-)

diff --git a/programs/winedbg/be_arm.c b/programs/winedbg/be_arm.c
index 4cee5d2..8600256 100644
--- a/programs/winedbg/be_arm.c
+++ b/programs/winedbg/be_arm.c
@@ -57,6 +57,14 @@ static char const tbl_dataops[][4] = {
     "mov", "bic", "mvn"
 };
 
+static char const tbl_hiops_t[][4] = {
+"add", "cmp", "mov", "bx"
+};
+
+static char const tbl_immops_t[][4] = {
+"mov", "cmp", "add", "sub"
+};
+
 static UINT db_get_inst(void* addr, int size)
 {
     UINT result = 0;
@@ -249,6 +257,93 @@ static UINT arm_disasm_coprocdatatrans(UINT inst)
     return 0;
 }
 
+static WORD thumb_disasm_hireg(WORD inst)
+{
+    short dst = inst & 0x07;
+    short src = (inst >> 3) & 0x07;
+    short h2  = (inst >> 6) & 0x01;
+    short h1  = (inst >> 7) & 0x01;
+    short op  = (inst >> 8) & 0x03;
+
+    if (h1) dst += 8;
+    if (h2) src += 8;
+
+    if (op == 3)
+        dbg_printf("\n\tb%sx\tr%u", h1?"l":"", src);
+    else
+        dbg_printf("\n\t%s\tr%u, r%u", tbl_hiops_t[op], dst, src);
+
+    return 0;
+}
+
+static WORD thumb_disasm_blocktrans(WORD inst)
+{
+    short lrpc = (inst >> 8)  & 0x01;
+    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{", load ? "pop" : "push");
+
+    for (i=0;i<=7;i++)
+        if ((inst>>i) & 1)
+        {
+            if (i == last) dbg_printf("r%u", i);
+            else dbg_printf("r%u, ", i);
+        }
+    if (lrpc)
+        dbg_printf(", %s", load ? "pc" : "lr");
+
+    dbg_printf("}");
+    return 0;
+}
+
+static WORD thumb_disasm_swi(WORD inst)
+{
+    WORD comment = inst & 0x00ff;
+    dbg_printf("\n\tswi\t#%d", comment);
+    return 0;
+}
+
+static WORD thumb_disasm_nop(WORD inst)
+{
+    dbg_printf("\n\tnop");
+    return 0;
+}
+
+static WORD thumb_disasm_ldrpcrel(WORD inst)
+{
+    WORD offset = (inst & 0xff) << 2;
+    dbg_printf("\n\tldr\tr%u, [pc, #%u]", (inst >> 8) & 0x07, offset);
+    return 0;
+}
+
+static WORD thumb_disasm_ldrsprel(WORD inst)
+{
+    WORD offset = (inst & 0xff) << 2;
+    dbg_printf("\n\t%s\tr%u, [sp, #%u]", (inst & 0x0800)?"ldr":"str", (inst >> 8) & 0x07, offset);
+    return 0;
+}
+
+static WORD thumb_disasm_ldrimm(WORD inst)
+{
+    WORD offset = (inst & 0x07c0) >> 6;
+    dbg_printf("\n\t%s%s\tr%u, [r%u, #%u]", (inst & 0x0800)?"ldr":"str", (inst & 0x1000)?"b":"",
+               inst & 0x07, (inst >> 3) & 0x07, (inst & 0x1000)?offset:(offset << 2));
+    return 0;
+}
+
+static WORD thumb_disasm_immop(WORD inst)
+{
+    WORD op = (inst >> 11) & 0x03;
+    dbg_printf("\n\t%s\tr%u, #%u", tbl_immops_t[op], (inst >> 8) & 0x07, inst & 0xff);
+    return 0;
+}
+
 struct inst_arm
 {
         UINT mask;
@@ -269,6 +364,25 @@ static const struct inst_arm tbl_arm[] = {
     { 0x00000000, 0x00000000, NULL }
 };
 
+struct inst_thumb16
+{
+        WORD mask;
+        WORD pattern;
+        WORD (*func)(WORD);
+};
+
+static const struct inst_thumb16 tbl_thumb16[] = {
+    { 0xfc00, 0x4400, thumb_disasm_hireg },
+    { 0xf600, 0xb400, thumb_disasm_blocktrans },
+    { 0xf800, 0x4800, thumb_disasm_ldrpcrel },
+    { 0xf000, 0x9000, thumb_disasm_ldrsprel },
+    { 0xe000, 0x6000, thumb_disasm_ldrimm },
+    { 0xe000, 0x2000, thumb_disasm_immop },
+    { 0xff00, 0xdf00, thumb_disasm_swi },
+    { 0xff00, 0xbf00, thumb_disasm_nop },
+    { 0x0000, 0x0000, NULL }
+};
+
 /***********************************************************************
  *              disasm_one_insn
  *
@@ -278,7 +392,9 @@ static const struct inst_arm tbl_arm[] = {
 void be_arm_disasm_one_insn(ADDRESS64 *addr, int display)
 {
     struct inst_arm *a_ptr = (struct inst_arm *)&tbl_arm;
+    struct inst_thumb16 *t_ptr = (struct inst_thumb16 *)&tbl_thumb16;
     UINT inst;
+    WORD tinst;
     int size;
     int matched = 0;
 
@@ -323,8 +439,29 @@ void be_arm_disasm_one_insn(ADDRESS64 *addr, int display)
     }
     else
     {
-        dbg_printf("\n\tThumb disassembling not yet implemented\n");
-        addr->Offset += size;
+        tinst = inst;
+        while (t_ptr->func) {
+                if ((tinst & t_ptr->mask) ==  t_ptr->pattern) {
+                        matched = 1;
+                        break;
+                }
+                t_ptr++;
+        }
+
+        if (!matched) {
+                dbg_printf("\n\tUnknown Instruction: %08x\n", tinst);
+                addr->Offset += size;
+                return;
+        }
+        else
+        {
+            if (!t_ptr->func(tinst))
+            {
+                dbg_printf("\n");
+                addr->Offset += size;
+            }
+        }
+        return;
     }
 }
 




More information about the wine-cvs mailing list