rlm@1: /************************************************************************/ rlm@1: /* Arm/Thumb command set disassembler */ rlm@1: /************************************************************************/ rlm@1: #include rlm@1: rlm@1: #include "GBAGlobals.h" rlm@1: #include "armdis.h" rlm@1: #include "elf.h" rlm@1: rlm@1: struct Opcodes rlm@1: { rlm@1: u32 mask; rlm@1: u32 cval; rlm@1: const char *mnemonic; rlm@1: }; rlm@1: rlm@1: const char hdig[] = "0123456789abcdef"; rlm@1: rlm@1: const char *decVals[16] = { rlm@1: "0", "1", "2", "3", "4", "5", "6", "7", "8", rlm@1: "9", "10", "11", "12", "13", "14", "15" rlm@1: }; rlm@1: rlm@1: const char *regs[16] = { rlm@1: "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", rlm@1: "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc" rlm@1: }; rlm@1: rlm@1: const char *conditions[16] = { rlm@1: "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", rlm@1: "hi", "ls", "ge", "lt", "gt", "le", "", "nv" rlm@1: }; rlm@1: rlm@1: const char *shifts[5] = { rlm@1: "lsl", "lsr", "asr", "ror", "rrx" rlm@1: }; rlm@1: rlm@1: const char *armMultLoadStore[12] = { rlm@1: // non-stack rlm@1: "da", "ia", "db", "ib", rlm@1: // stack store rlm@1: "ed", "ea", "fd", "fa", rlm@1: // stack load rlm@1: "fa", "fd", "ea", "ed" rlm@1: }; rlm@1: rlm@1: const Opcodes thumbOpcodes[] = { rlm@1: // Format 1 rlm@1: { 0xf800, 0x0000, "lsl %r0, %r3, %o" }, rlm@1: { 0xf800, 0x0800, "lsr %r0, %r3, %o" }, rlm@1: { 0xf800, 0x1000, "asr %r0, %r3, %o" }, rlm@1: // Format 2 rlm@1: { 0xfe00, 0x1800, "add %r0, %r3, %r6" }, rlm@1: { 0xfe00, 0x1a00, "sub %r0, %r3, %r6" }, rlm@1: { 0xfe00, 0x1c00, "add %r0, %r3, %i" }, rlm@1: { 0xfe00, 0x1e00, "sub %r0, %r3, %i" }, rlm@1: // Format 3 rlm@1: { 0xf800, 0x2000, "mov %r8, %O" }, rlm@1: { 0xf800, 0x2800, "cmp %r8, %O" }, rlm@1: { 0xf800, 0x3000, "add %r8, %O" }, rlm@1: { 0xf800, 0x3800, "sub %r8, %O" }, rlm@1: // Format 4 rlm@1: { 0xffc0, 0x4000, "and %r0, %r3" }, rlm@1: { 0xffc0, 0x4040, "eor %r0, %r3" }, rlm@1: { 0xffc0, 0x4080, "lsl %r0, %r3" }, rlm@1: { 0xffc0, 0x40c0, "lsr %r0, %r3" }, rlm@1: { 0xffc0, 0x4100, "asr %r0, %r3" }, rlm@1: { 0xffc0, 0x4140, "adc %r0, %r3" }, rlm@1: { 0xffc0, 0x4180, "sbc %r0, %r3" }, rlm@1: { 0xffc0, 0x41c0, "ror %r0, %r3" }, rlm@1: { 0xffc0, 0x4200, "tst %r0, %r3" }, rlm@1: { 0xffc0, 0x4240, "neg %r0, %r3" }, rlm@1: { 0xffc0, 0x4280, "cmp %r0, %r3" }, rlm@1: { 0xffc0, 0x42c0, "cmn %r0, %r3" }, rlm@1: { 0xffc0, 0x4300, "orr %r0, %r3" }, rlm@1: { 0xffc0, 0x4340, "mul %r0, %r3" }, rlm@1: { 0xffc0, 0x4380, "bic %r0, %r3" }, rlm@1: { 0xffc0, 0x43c0, "mvn %r0, %r3" }, rlm@1: // Format 5 rlm@1: { 0xff80, 0x4700, "bx %h36" }, rlm@1: { 0xfcc0, 0x4400, "[ ??? ]" }, rlm@1: { 0xff00, 0x4400, "add %h07, %h36" }, rlm@1: { 0xff00, 0x4500, "cmp %h07, %h36" }, rlm@1: { 0xff00, 0x4600, "mov %h07, %h36" }, rlm@1: // Format 6 rlm@1: { 0xf800, 0x4800, "ldr %r8, [%I] (=%J)" }, rlm@1: // Format 7 rlm@1: { 0xfa00, 0x5000, "str%b %r0, [%r3, %r6]" }, rlm@1: { 0xfa00, 0x5800, "ldr%b %r0, [%r3, %r6]" }, rlm@1: // Format 8 rlm@1: { 0xfe00, 0x5200, "strh %r0, [%r3, %r6]" }, rlm@1: { 0xfe00, 0x5600, "ldsb %r0, [%r3, %r6]" }, rlm@1: { 0xfe00, 0x5a00, "ldrh %r0, [%r3, %r6]" }, rlm@1: { 0xfe00, 0x5e00, "ldsh %r0, [%r3, %r6]" }, rlm@1: // Format 9 rlm@1: { 0xe800, 0x6000, "str%B %r0, [%r3, %p]" }, rlm@1: { 0xe800, 0x6800, "ldr%B %r0, [%r3, %p]" }, rlm@1: // Format 10 rlm@1: { 0xf800, 0x8000, "strh %r0, [%r3, %e]" }, rlm@1: { 0xf800, 0x8800, "ldrh %r0, [%r3, %e]" }, rlm@1: // Format 11 rlm@1: { 0xf800, 0x9000, "str %r8, [sp, %w]" }, rlm@1: { 0xf800, 0x9800, "ldr %r8, [sp, %w]" }, rlm@1: // Format 12 rlm@1: { 0xf800, 0xa000, "add %r8, pc, %w (=%K)" }, rlm@1: { 0xf800, 0xa800, "add %r8, sp, %w" }, rlm@1: // Format 13 rlm@1: { 0xff00, 0xb000, "add sp, %s" }, rlm@1: // Format 14 rlm@1: { 0xffff, 0xb500, "push {lr}" }, rlm@1: { 0xff00, 0xb400, "push {%l}" }, rlm@1: { 0xff00, 0xb500, "push {%l,lr}" }, rlm@1: { 0xffff, 0xbd00, "pop {pc}" }, rlm@1: { 0xff00, 0xbd00, "pop {%l,pc}" }, rlm@1: { 0xff00, 0xbc00, "pop {%l}" }, rlm@1: // Format 15 rlm@1: { 0xf800, 0xc000, "stmia %r8!, {%l}" }, rlm@1: { 0xf800, 0xc800, "ldmia %r8!, {%l}" }, rlm@1: // Format 17 rlm@1: { 0xff00, 0xdf00, "swi %m" }, rlm@1: // Format 16 rlm@1: { 0xf000, 0xd000, "b%c %W" }, rlm@1: // Format 18 rlm@1: { 0xf800, 0xe000, "b %a" }, rlm@1: // Format 19 rlm@1: { 0xf800, 0xf000, "bl %A" }, rlm@1: { 0xf800, 0xf800, "blh %Z" }, rlm@1: { 0xff00, 0xbe00, "bkpt %O" }, rlm@1: // Unknown rlm@1: { 0x0000, 0x0000, "[ ??? ]" } rlm@1: }; rlm@1: rlm@1: const Opcodes armOpcodes[] = { rlm@1: // Undefined rlm@1: { 0x0e000010, 0x06000010, "[ undefined ]" }, rlm@1: // Branch instructions rlm@1: { 0x0ff000f0, 0x01200010, "bx%c %r0" }, rlm@1: { 0x0f000000, 0x0a000000, "b%c %o" }, rlm@1: { 0x0f000000, 0x0b000000, "bl%c %o" }, rlm@1: { 0x0f000000, 0x0f000000, "swi%c %q" }, rlm@1: // PSR transfer rlm@1: { 0x0fbf0fff, 0x010f0000, "mrs%c %r3, %p" }, rlm@1: { 0x0db0f000, 0x0120f000, "msr%c %p, %i" }, rlm@1: // Multiply instructions rlm@1: { 0x0fe000f0, 0x00000090, "mul%c%s %r4, %r0, %r2" }, rlm@1: { 0x0fe000f0, 0x00200090, "mla%c%s %r4, %r0, %r2, %r3" }, rlm@1: { 0x0fa000f0, 0x00800090, "%umull%c%s %r3, %r4, %r0, %r2" }, rlm@1: { 0x0fa000f0, 0x00a00090, "%umlal%c%s %r3, %r4, %r0, %r2" }, rlm@1: // Load/Store instructions rlm@1: { 0x0fb00ff0, 0x01000090, "swp%c%b %r3, %r0, [%r4]" }, rlm@1: { 0x0fb000f0, 0x01000090, "[ ??? ]" }, rlm@1: { 0x0c100000, 0x04000000, "str%c%b%t %r3, %a" }, rlm@1: { 0x0c100000, 0x04100000, "ldr%c%b%t %r3, %a" }, rlm@1: { 0x0e100090, 0x00000090, "str%c%h %r3, %a" }, rlm@1: { 0x0e100090, 0x00100090, "ldr%c%h %r3, %a" }, rlm@1: { 0x0e100000, 0x08000000, "stm%c%m %r4%l" }, rlm@1: { 0x0e100000, 0x08100000, "ldm%c%m %r4%l" }, rlm@1: // Data processing rlm@1: { 0x0de00000, 0x00000000, "and%c%s %r3, %r4, %i" }, rlm@1: { 0x0de00000, 0x00200000, "eor%c%s %r3, %r4, %i" }, rlm@1: { 0x0de00000, 0x00400000, "sub%c%s %r3, %r4, %i" }, rlm@1: { 0x0de00000, 0x00600000, "rsb%c%s %r3, %r4, %i" }, rlm@1: { 0x0de00000, 0x00800000, "add%c%s %r3, %r4, %i" }, rlm@1: { 0x0de00000, 0x00a00000, "adc%c%s %r3, %r4, %i" }, rlm@1: { 0x0de00000, 0x00c00000, "sbc%c%s %r3, %r4, %i" }, rlm@1: { 0x0de00000, 0x00e00000, "rsc%c%s %r3, %r4, %i" }, rlm@1: { 0x0de00000, 0x01000000, "tst%c%s %r4, %i" }, rlm@1: { 0x0de00000, 0x01200000, "teq%c%s %r4, %i" }, rlm@1: { 0x0de00000, 0x01400000, "cmp%c%s %r4, %i" }, rlm@1: { 0x0de00000, 0x01600000, "cmn%c%s %r4, %i" }, rlm@1: { 0x0de00000, 0x01800000, "orr%c%s %r3, %r4, %i" }, rlm@1: { 0x0de00000, 0x01a00000, "mov%c%s %r3, %i" }, rlm@1: { 0x0de00000, 0x01c00000, "bic%c%s %r3, %r4, %i" }, rlm@1: { 0x0de00000, 0x01e00000, "mvn%c%s %r3, %i" }, rlm@1: // Coprocessor operations rlm@1: { 0x0f000010, 0x0e000000, "cdp%c %P, %N, %r3, %R4, %R0%V" }, rlm@1: { 0x0e100000, 0x0c000000, "stc%c%L %P, %r3, %A" }, rlm@1: { 0x0f100010, 0x0e000010, "mcr%c %P, %N, %r3, %R4, %R0%V" }, rlm@1: { 0x0f100010, 0x0e100010, "mrc%c %P, %N, %r3, %R4, %R0%V" }, rlm@1: // Unknown rlm@1: { 0x00000000, 0x00000000, "[ ??? ]" } rlm@1: }; rlm@1: rlm@1: char *addStr(char *dest, const char *src) rlm@1: { rlm@1: while (*src) rlm@1: { rlm@1: *dest++ = *src++; rlm@1: } rlm@1: return dest; rlm@1: } rlm@1: rlm@1: char *addHex(char *dest, int siz, u32 val) rlm@1: { rlm@1: if (siz == 0) rlm@1: { rlm@1: siz = 28; rlm@1: while ((((val >> siz) & 15) == 0) && (siz >= 4)) rlm@1: siz -= 4; rlm@1: siz += 4; rlm@1: } rlm@1: while (siz > 0) rlm@1: { rlm@1: siz -= 4; rlm@1: *dest++ = hdig[(val >> siz) & 15]; rlm@1: } rlm@1: return dest; rlm@1: } rlm@1: rlm@1: int disArm(u32 offset, char *dest, int flags) rlm@1: { rlm@1: u32 opcode = debuggerReadMemory(offset); rlm@1: rlm@1: const Opcodes *sp = armOpcodes; rlm@1: while (sp->cval != (opcode & sp->mask)) rlm@1: sp++; rlm@1: rlm@1: if (flags & DIS_VIEW_ADDRESS) rlm@1: { rlm@1: dest = addHex(dest, 32, offset); rlm@1: *dest++ = ' '; rlm@1: } rlm@1: if (flags & DIS_VIEW_CODE) rlm@1: { rlm@1: dest = addHex(dest, 32, opcode); rlm@1: *dest++ = ' '; rlm@1: } rlm@1: rlm@1: const char *src = sp->mnemonic; rlm@1: while (*src) rlm@1: { rlm@1: if (*src != '%') rlm@1: *dest++ = *src++; rlm@1: else rlm@1: { rlm@1: src++; rlm@1: switch (*src) rlm@1: { rlm@1: case 'c': rlm@1: dest = addStr(dest, conditions[opcode >> 28]); rlm@1: break; rlm@1: case 'r': rlm@1: dest = addStr(dest, regs[(opcode >> ((*(++src) - '0') * 4)) & 15]); rlm@1: break; rlm@1: case 'o': rlm@1: { rlm@1: *dest++ = '$'; rlm@1: int off = opcode & 0xffffff; rlm@1: if (off & 0x800000) rlm@1: off |= 0xff000000; rlm@1: off <<= 2; rlm@1: dest = addHex(dest, 32, offset + 8 + off); rlm@1: } rlm@1: break; rlm@1: case 'i': rlm@1: if (opcode & (1 << 25)) rlm@1: { rlm@1: dest = addStr(dest, "#0x"); rlm@1: int imm = opcode & 0xff; rlm@1: int rot = (opcode & 0xf00) >> 7; rlm@1: int val = (imm << (32 - rot)) | (imm >> rot); rlm@1: dest = addHex(dest, 0, val); rlm@1: } rlm@1: else rlm@1: { rlm@1: dest = addStr(dest, regs[opcode & 0x0f]); rlm@1: int shi = (opcode >> 5) & 3; rlm@1: int sdw = (opcode >> 7) & 0x1f; rlm@1: if ((sdw == 0) && (shi == 3)) rlm@1: shi = 4; rlm@1: if ((sdw) || (opcode & 0x10) || (shi)) rlm@1: { rlm@1: dest = addStr(dest, ", "); rlm@1: dest = addStr(dest, shifts[shi]); rlm@1: if (opcode & 0x10) rlm@1: { rlm@1: *dest++ = ' '; rlm@1: dest = addStr(dest, regs[(opcode >> 8) & 15]); rlm@1: } rlm@1: else rlm@1: { rlm@1: if (sdw == 0 && ((shi == 1) || (shi == 2))) rlm@1: sdw = 32; rlm@1: if (shi != 4) rlm@1: { rlm@1: dest = addStr(dest, " #0x"); rlm@1: dest = addHex(dest, 8, sdw); rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 'p': rlm@1: if (opcode & (1 << 22)) rlm@1: dest = addStr(dest, "spsr"); rlm@1: else rlm@1: dest = addStr(dest, "cpsr"); rlm@1: if (opcode & 0x00F00000) rlm@1: { rlm@1: *dest++ = '_'; rlm@1: if (opcode & 0x00080000) rlm@1: *dest++ = 'f'; rlm@1: if (opcode & 0x00040000) rlm@1: *dest++ = 's'; rlm@1: if (opcode & 0x00020000) rlm@1: *dest++ = 'x'; rlm@1: if (opcode & 0x00010000) rlm@1: *dest++ = 'c'; rlm@1: } rlm@1: break; rlm@1: case 's': rlm@1: if (opcode & (1 << 20)) rlm@1: *dest++ = 's'; rlm@1: break; rlm@1: case 'S': rlm@1: if (opcode & (1 << 22)) rlm@1: *dest++ = 's'; rlm@1: break; rlm@1: case 'u': rlm@1: if (opcode & (1 << 22)) rlm@1: *dest++ = 's'; rlm@1: else rlm@1: *dest++ = 'u'; rlm@1: break; rlm@1: case 'b': rlm@1: if (opcode & (1 << 22)) rlm@1: *dest++ = 'b'; rlm@1: break; rlm@1: case 'a': rlm@1: if ((opcode & 0x076f0000) == 0x004f0000) rlm@1: { rlm@1: *dest++ = '['; rlm@1: *dest++ = '$'; rlm@1: int adr = offset + 8; rlm@1: int add = (opcode & 15) | ((opcode >> 8) & 0xf0); rlm@1: if (opcode & (1 << 23)) rlm@1: adr += add; rlm@1: else rlm@1: adr -= add; rlm@1: dest = addHex(dest, 32, adr); rlm@1: *dest++ = ']'; rlm@1: dest = addStr(dest, " (="); rlm@1: *dest++ = '$'; rlm@1: dest = addHex(dest, 32, debuggerReadMemory(adr)); rlm@1: *dest++ = ')'; rlm@1: } rlm@1: if ((opcode & 0x072f0000) == 0x050f0000) rlm@1: { rlm@1: *dest++ = '['; rlm@1: *dest++ = '$'; rlm@1: int adr = offset + 8; rlm@1: if (opcode & (1 << 23)) rlm@1: adr += opcode & 0xfff; rlm@1: else rlm@1: adr -= opcode & 0xfff; rlm@1: dest = addHex(dest, 32, adr); rlm@1: *dest++ = ']'; rlm@1: dest = addStr(dest, " (="); rlm@1: *dest++ = '$'; rlm@1: dest = addHex(dest, 32, debuggerReadMemory(adr)); rlm@1: *dest++ = ')'; rlm@1: } rlm@1: else rlm@1: { rlm@1: int reg = (opcode >> 16) & 15; rlm@1: *dest++ = '['; rlm@1: dest = addStr(dest, regs[reg]); rlm@1: if (!(opcode & (1 << 24))) rlm@1: *dest++ = ']'; rlm@1: if (((opcode & (1 << 25)) && (opcode & (1 << 26))) || (!(opcode & (1 << 22)) && !(opcode & (1 << 26)))) rlm@1: { rlm@1: dest = addStr(dest, ", "); rlm@1: if (!(opcode & (1 << 23))) rlm@1: *dest++ = '-'; rlm@1: dest = addStr(dest, regs[opcode & 0x0f]); rlm@1: int shi = (opcode >> 5) & 3; rlm@1: if (opcode & (1 << 26)) rlm@1: { rlm@1: if (((opcode >> 7) & 0x1f) || (opcode & 0x10) || (shi == 1) || (shi == 2)) rlm@1: { rlm@1: dest = addStr(dest, ", "); rlm@1: dest = addStr(dest, shifts[shi]); rlm@1: if (opcode & 0x10) rlm@1: { rlm@1: *dest++ = ' '; rlm@1: dest = addStr(dest, regs[(opcode >> 8) & 15]); rlm@1: } rlm@1: else rlm@1: { rlm@1: int sdw = (opcode >> 7) & 0x1f; rlm@1: if (sdw == 0 && ((shi == 1) || (shi == 2))) rlm@1: sdw = 32; rlm@1: dest = addStr(dest, " #0x"); rlm@1: dest = addHex(dest, 8, sdw); rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: int off; rlm@1: if (opcode & (1 << 26)) rlm@1: off = opcode & 0xfff; rlm@1: else rlm@1: off = (opcode & 15) | ((opcode >> 4) & 0xf0); rlm@1: if (off) rlm@1: { rlm@1: dest = addStr(dest, ", "); rlm@1: if (!(opcode & (1 << 23))) rlm@1: *dest++ = '-'; rlm@1: dest = addStr(dest, "#0x"); rlm@1: dest = addHex(dest, 0, off); rlm@1: } rlm@1: } rlm@1: if (opcode & (1 << 24)) rlm@1: { rlm@1: *dest++ = ']'; rlm@1: if (opcode & (1 << 21)) rlm@1: *dest++ = '!'; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 't': rlm@1: if ((opcode & 0x01200000) == 0x01200000) rlm@1: *dest++ = 't'; rlm@1: break; rlm@1: case 'h': rlm@1: if (opcode & (1 << 6)) rlm@1: *dest++ = 's'; rlm@1: if (opcode & (1 << 5)) rlm@1: *dest++ = 'h'; rlm@1: else rlm@1: *dest++ = 'b'; rlm@1: break; rlm@1: case 'm': rlm@1: if (((opcode >> 16) & 15) == 13) rlm@1: { rlm@1: if (opcode & 0x00100000) rlm@1: dest = addStr(dest, armMultLoadStore[8 + ((opcode >> 23) & 3)]); rlm@1: else rlm@1: dest = addStr(dest, armMultLoadStore[4 + ((opcode >> 23) & 3)]); rlm@1: } rlm@1: else rlm@1: dest = addStr(dest, armMultLoadStore[(opcode >> 23) & 3]); rlm@1: break; rlm@1: case 'l': rlm@1: if (opcode & (1 << 21)) rlm@1: *dest++ = '!'; rlm@1: dest = addStr(dest, ", {"); rlm@1: { rlm@1: int rlst = opcode & 0xffff; rlm@1: int msk = 0; rlm@1: int not_first = 0; rlm@1: while (msk < 16) rlm@1: { rlm@1: if (rlst & (1 << msk)) rlm@1: { rlm@1: int fr = msk; rlm@1: while (rlst & (1 << msk)) rlm@1: msk++; rlm@1: int to = msk - 1; rlm@1: if (not_first) rlm@1: //dest = addStr(dest, ", "); rlm@1: *dest++ = ','; rlm@1: dest = addStr(dest, regs[fr]); rlm@1: if (fr != to) rlm@1: { rlm@1: if (fr == to - 1) rlm@1: //dest = addStr(", "); rlm@1: *dest++ = ','; rlm@1: else rlm@1: *dest++ = '-'; rlm@1: dest = addStr(dest, regs[to]); rlm@1: } rlm@1: not_first = 1; rlm@1: } rlm@1: else rlm@1: msk++; rlm@1: } rlm@1: *dest++ = '}'; rlm@1: if (opcode & (1 << 22)) rlm@1: *dest++ = '^'; rlm@1: } rlm@1: break; rlm@1: case 'q': rlm@1: *dest++ = '$'; rlm@1: dest = addHex(dest, 24, opcode & 0xffffff); rlm@1: break; rlm@1: case 'P': rlm@1: *dest++ = 'p'; rlm@1: dest = addStr(dest, decVals[(opcode >> 8) & 15]); rlm@1: break; rlm@1: case 'N': rlm@1: if (opcode & 0x10) rlm@1: dest = addStr(dest, decVals[(opcode >> 21) & 7]); rlm@1: else rlm@1: dest = addStr(dest, decVals[(opcode >> 20) & 15]); rlm@1: break; rlm@1: case 'R': rlm@1: { rlm@1: src++; rlm@1: int reg = 4 * (*src - '0'); rlm@1: *dest++ = 'c'; rlm@1: dest = addStr(dest, decVals[(opcode >> reg) & 15]); rlm@1: } rlm@1: break; rlm@1: case 'V': rlm@1: { rlm@1: int val = (opcode >> 5) & 7; rlm@1: if (val) rlm@1: { rlm@1: dest = addStr(dest, ", "); rlm@1: dest = addStr(dest, decVals[val]); rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 'L': rlm@1: if (opcode & (1 << 22)) rlm@1: *dest++ = 'l'; rlm@1: break; rlm@1: case 'A': rlm@1: if ((opcode & 0x012f0000) == 0x010f0000) rlm@1: { rlm@1: int adr = offset + 8; rlm@1: int add = (opcode & 0xff) << 2; rlm@1: if (opcode & (1 << 23)) rlm@1: adr += add; rlm@1: else rlm@1: adr -= add; rlm@1: *dest++ = '$'; rlm@1: addHex(dest, 32, adr); rlm@1: } rlm@1: else rlm@1: { rlm@1: *dest++ = '['; rlm@1: dest = addStr(dest, regs[(opcode >> 16) & 15]); rlm@1: if (!(opcode & (1 << 24))) rlm@1: *dest++ = ']'; rlm@1: int off = (opcode & 0xff) << 2; rlm@1: if (off) rlm@1: { rlm@1: dest = addStr(dest, ", "); rlm@1: if (!(opcode & (1 << 23))) rlm@1: *dest++ = '-'; rlm@1: dest = addStr(dest, "#0x"); rlm@1: dest = addHex(dest, 0, off); rlm@1: } rlm@1: if (opcode & (1 << 24)) rlm@1: { rlm@1: *dest++ = ']'; rlm@1: if (opcode & (1 << 21)) rlm@1: *dest++ = '!'; rlm@1: } rlm@1: } rlm@1: break; rlm@1: } rlm@1: src++; rlm@1: } rlm@1: } rlm@1: *dest++ = 0; rlm@1: rlm@1: return 4; rlm@1: } rlm@1: rlm@1: int disThumb(u32 offset, char *dest, int flags) rlm@1: { rlm@1: u32 opcode = debuggerReadHalfWord(offset); rlm@1: rlm@1: const Opcodes *sp = thumbOpcodes; rlm@1: int ret = 2; rlm@1: while (sp->cval != (opcode & sp->mask)) rlm@1: sp++; rlm@1: rlm@1: if (flags & DIS_VIEW_ADDRESS) rlm@1: { rlm@1: dest = addHex(dest, 32, offset); rlm@1: *dest++ = ' '; rlm@1: } rlm@1: if (flags & DIS_VIEW_CODE) rlm@1: { rlm@1: dest = addHex(dest, 16, opcode); rlm@1: *dest++ = ' '; rlm@1: } rlm@1: rlm@1: const char *src = sp->mnemonic; rlm@1: while (*src) rlm@1: { rlm@1: if (*src != '%') rlm@1: *dest++ = *src++; rlm@1: else rlm@1: { rlm@1: src++; rlm@1: switch (*src) rlm@1: { rlm@1: case 'r': rlm@1: src++; rlm@1: dest = addStr(dest, regs[(opcode >> (*src - '0')) & 7]); rlm@1: break; rlm@1: case 'o': rlm@1: dest = addStr(dest, "#0x"); rlm@1: { rlm@1: int val = (opcode >> 6) & 0x1f; rlm@1: dest = addHex(dest, 8, val); rlm@1: } rlm@1: break; rlm@1: case 'p': rlm@1: dest = addStr(dest, "#0x"); rlm@1: { rlm@1: int val = (opcode >> 6) & 0x1f; rlm@1: if (!(opcode & (1 << 12))) rlm@1: val <<= 2; rlm@1: dest = addHex(dest, 0, val); rlm@1: } rlm@1: break; rlm@1: case 'e': rlm@1: dest = addStr(dest, "#0x"); rlm@1: dest = addHex(dest, 0, ((opcode >> 6) & 0x1f) << 1); rlm@1: break; rlm@1: case 'i': rlm@1: dest = addStr(dest, "#0x"); rlm@1: dest = addHex(dest, 0, (opcode >> 6) & 7); rlm@1: break; rlm@1: case 'h': rlm@1: { rlm@1: src++; rlm@1: int reg = (opcode >> (*src - '0')) & 7; rlm@1: src++; rlm@1: if (opcode & (1 << (*src - '0'))) rlm@1: reg += 8; rlm@1: dest = addStr(dest, regs[reg]); rlm@1: } rlm@1: break; rlm@1: case 'O': rlm@1: dest = addStr(dest, "#0x"); rlm@1: dest = addHex(dest, 0, (opcode & 0xff)); rlm@1: break; rlm@1: case 'I': rlm@1: *dest++ = '$'; rlm@1: dest = addHex(dest, 32, (offset & 0xfffffffc) + 4 + ((opcode & 0xff) << 2)); rlm@1: break; rlm@1: case 'J': rlm@1: { rlm@1: u32 value = debuggerReadMemory((offset & 0xfffffffc) + 4 + rlm@1: ((opcode & 0xff) << 2)); rlm@1: *dest++ = '$'; rlm@1: dest = addHex(dest, 32, value); rlm@1: const char *s = elfGetAddressSymbol(value); rlm@1: if (*s) rlm@1: { rlm@1: *dest++ = ' '; rlm@1: dest = addStr(dest, s); rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 'K': rlm@1: { rlm@1: u32 value = (offset & 0xfffffffc) + 4 + ((opcode & 0xff) << 2); rlm@1: *dest++ = '$'; rlm@1: dest = addHex(dest, 32, value); rlm@1: const char *s = elfGetAddressSymbol(value); rlm@1: if (*s) rlm@1: { rlm@1: *dest++ = ' '; rlm@1: dest = addStr(dest, s); rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 'b': rlm@1: if (opcode & (1 << 10)) rlm@1: *dest++ = 'b'; rlm@1: break; rlm@1: case 'B': rlm@1: if (opcode & (1 << 12)) rlm@1: *dest++ = 'b'; rlm@1: break; rlm@1: case 'w': rlm@1: dest = addStr(dest, "#0x"); rlm@1: dest = addHex(dest, 0, (opcode & 0xff) << 2); rlm@1: break; rlm@1: case 'W': rlm@1: *dest++ = '$'; rlm@1: { rlm@1: int add = opcode & 0xff; rlm@1: if (add & 0x80) rlm@1: add |= 0xffffff00; rlm@1: dest = addHex(dest, 32, (offset & 0xfffffffe) + 4 + (add << 1)); rlm@1: } rlm@1: break; rlm@1: case 'c': rlm@1: dest = addStr(dest, conditions[(opcode >> 8) & 15]); rlm@1: break; rlm@1: case 's': rlm@1: if (opcode & (1 << 7)) rlm@1: *dest++ = '-'; rlm@1: dest = addStr(dest, "#0x"); rlm@1: dest = addHex(dest, 0, (opcode & 0x7f) << 2); rlm@1: break; rlm@1: case 'l': rlm@1: { rlm@1: int rlst = opcode & 0xff; rlm@1: int msk = 0; rlm@1: int not_first = 0; rlm@1: while (msk < 8) rlm@1: { rlm@1: if (rlst & (1 << msk)) rlm@1: { rlm@1: int fr = msk; rlm@1: while (rlst & (1 << msk)) rlm@1: msk++; rlm@1: int to = msk - 1; rlm@1: if (not_first) rlm@1: *dest++ = ','; rlm@1: dest = addStr(dest, regs[fr]); rlm@1: if (fr != to) rlm@1: { rlm@1: if (fr == to - 1) rlm@1: *dest++ = ','; rlm@1: else rlm@1: *dest++ = '-'; rlm@1: dest = addStr(dest, regs[to]); rlm@1: } rlm@1: not_first = 1; rlm@1: } rlm@1: else rlm@1: msk++; rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 'm': rlm@1: *dest++ = '$'; rlm@1: dest = addHex(dest, 8, opcode & 0xff); rlm@1: break; rlm@1: case 'Z': rlm@1: *dest++ = '$'; rlm@1: dest = addHex(dest, 16, (opcode & 0x7ff) << 1); rlm@1: break; rlm@1: case 'a': rlm@1: *dest++ = '$'; rlm@1: { rlm@1: int add = opcode & 0x07ff; rlm@1: if (add & 0x400) rlm@1: add |= 0xfffff800; rlm@1: add <<= 1; rlm@1: dest = addHex(dest, 32, offset + 4 + add); rlm@1: } rlm@1: break; rlm@1: case 'A': rlm@1: { rlm@1: int nopcode = debuggerReadHalfWord(offset + 2); rlm@1: int add = opcode & 0x7ff; rlm@1: if (add & 0x400) rlm@1: add |= 0xfff800; rlm@1: add = (add << 12) | ((nopcode & 0x7ff) << 1); rlm@1: *dest++ = '$'; rlm@1: dest = addHex(dest, 32, offset + 4 + add); rlm@1: const char *s = elfGetAddressSymbol(offset + 4 + add); rlm@1: if (*s) rlm@1: { rlm@1: *dest++ = ' '; rlm@1: *dest++ = '('; rlm@1: dest = addStr(dest, s); rlm@1: *dest++ = ')'; rlm@1: } rlm@1: ret = 4; rlm@1: } rlm@1: break; rlm@1: } rlm@1: src++; rlm@1: } rlm@1: } rlm@1: *dest++ = 0; rlm@1: return ret; rlm@1: } rlm@1: