annotate src/gba/armdis.cpp @ 539:a64485223afa

cleanup.
author Robert McIntyre <rlm@mit.edu>
date Mon, 25 Jun 2012 14:55:55 -0500
parents f9f4f1b99eed
children
rev   line source
rlm@1 1 /************************************************************************/
rlm@1 2 /* Arm/Thumb command set disassembler */
rlm@1 3 /************************************************************************/
rlm@1 4 #include <cstdio>
rlm@1 5
rlm@1 6 #include "GBAGlobals.h"
rlm@1 7 #include "armdis.h"
rlm@1 8 #include "elf.h"
rlm@1 9
rlm@1 10 struct Opcodes
rlm@1 11 {
rlm@1 12 u32 mask;
rlm@1 13 u32 cval;
rlm@1 14 const char *mnemonic;
rlm@1 15 };
rlm@1 16
rlm@1 17 const char hdig[] = "0123456789abcdef";
rlm@1 18
rlm@1 19 const char *decVals[16] = {
rlm@1 20 "0", "1", "2", "3", "4", "5", "6", "7", "8",
rlm@1 21 "9", "10", "11", "12", "13", "14", "15"
rlm@1 22 };
rlm@1 23
rlm@1 24 const char *regs[16] = {
rlm@1 25 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
rlm@1 26 "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc"
rlm@1 27 };
rlm@1 28
rlm@1 29 const char *conditions[16] = {
rlm@1 30 "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc",
rlm@1 31 "hi", "ls", "ge", "lt", "gt", "le", "", "nv"
rlm@1 32 };
rlm@1 33
rlm@1 34 const char *shifts[5] = {
rlm@1 35 "lsl", "lsr", "asr", "ror", "rrx"
rlm@1 36 };
rlm@1 37
rlm@1 38 const char *armMultLoadStore[12] = {
rlm@1 39 // non-stack
rlm@1 40 "da", "ia", "db", "ib",
rlm@1 41 // stack store
rlm@1 42 "ed", "ea", "fd", "fa",
rlm@1 43 // stack load
rlm@1 44 "fa", "fd", "ea", "ed"
rlm@1 45 };
rlm@1 46
rlm@1 47 const Opcodes thumbOpcodes[] = {
rlm@1 48 // Format 1
rlm@1 49 { 0xf800, 0x0000, "lsl %r0, %r3, %o" },
rlm@1 50 { 0xf800, 0x0800, "lsr %r0, %r3, %o" },
rlm@1 51 { 0xf800, 0x1000, "asr %r0, %r3, %o" },
rlm@1 52 // Format 2
rlm@1 53 { 0xfe00, 0x1800, "add %r0, %r3, %r6" },
rlm@1 54 { 0xfe00, 0x1a00, "sub %r0, %r3, %r6" },
rlm@1 55 { 0xfe00, 0x1c00, "add %r0, %r3, %i" },
rlm@1 56 { 0xfe00, 0x1e00, "sub %r0, %r3, %i" },
rlm@1 57 // Format 3
rlm@1 58 { 0xf800, 0x2000, "mov %r8, %O" },
rlm@1 59 { 0xf800, 0x2800, "cmp %r8, %O" },
rlm@1 60 { 0xf800, 0x3000, "add %r8, %O" },
rlm@1 61 { 0xf800, 0x3800, "sub %r8, %O" },
rlm@1 62 // Format 4
rlm@1 63 { 0xffc0, 0x4000, "and %r0, %r3" },
rlm@1 64 { 0xffc0, 0x4040, "eor %r0, %r3" },
rlm@1 65 { 0xffc0, 0x4080, "lsl %r0, %r3" },
rlm@1 66 { 0xffc0, 0x40c0, "lsr %r0, %r3" },
rlm@1 67 { 0xffc0, 0x4100, "asr %r0, %r3" },
rlm@1 68 { 0xffc0, 0x4140, "adc %r0, %r3" },
rlm@1 69 { 0xffc0, 0x4180, "sbc %r0, %r3" },
rlm@1 70 { 0xffc0, 0x41c0, "ror %r0, %r3" },
rlm@1 71 { 0xffc0, 0x4200, "tst %r0, %r3" },
rlm@1 72 { 0xffc0, 0x4240, "neg %r0, %r3" },
rlm@1 73 { 0xffc0, 0x4280, "cmp %r0, %r3" },
rlm@1 74 { 0xffc0, 0x42c0, "cmn %r0, %r3" },
rlm@1 75 { 0xffc0, 0x4300, "orr %r0, %r3" },
rlm@1 76 { 0xffc0, 0x4340, "mul %r0, %r3" },
rlm@1 77 { 0xffc0, 0x4380, "bic %r0, %r3" },
rlm@1 78 { 0xffc0, 0x43c0, "mvn %r0, %r3" },
rlm@1 79 // Format 5
rlm@1 80 { 0xff80, 0x4700, "bx %h36" },
rlm@1 81 { 0xfcc0, 0x4400, "[ ??? ]" },
rlm@1 82 { 0xff00, 0x4400, "add %h07, %h36" },
rlm@1 83 { 0xff00, 0x4500, "cmp %h07, %h36" },
rlm@1 84 { 0xff00, 0x4600, "mov %h07, %h36" },
rlm@1 85 // Format 6
rlm@1 86 { 0xf800, 0x4800, "ldr %r8, [%I] (=%J)" },
rlm@1 87 // Format 7
rlm@1 88 { 0xfa00, 0x5000, "str%b %r0, [%r3, %r6]" },
rlm@1 89 { 0xfa00, 0x5800, "ldr%b %r0, [%r3, %r6]" },
rlm@1 90 // Format 8
rlm@1 91 { 0xfe00, 0x5200, "strh %r0, [%r3, %r6]" },
rlm@1 92 { 0xfe00, 0x5600, "ldsb %r0, [%r3, %r6]" },
rlm@1 93 { 0xfe00, 0x5a00, "ldrh %r0, [%r3, %r6]" },
rlm@1 94 { 0xfe00, 0x5e00, "ldsh %r0, [%r3, %r6]" },
rlm@1 95 // Format 9
rlm@1 96 { 0xe800, 0x6000, "str%B %r0, [%r3, %p]" },
rlm@1 97 { 0xe800, 0x6800, "ldr%B %r0, [%r3, %p]" },
rlm@1 98 // Format 10
rlm@1 99 { 0xf800, 0x8000, "strh %r0, [%r3, %e]" },
rlm@1 100 { 0xf800, 0x8800, "ldrh %r0, [%r3, %e]" },
rlm@1 101 // Format 11
rlm@1 102 { 0xf800, 0x9000, "str %r8, [sp, %w]" },
rlm@1 103 { 0xf800, 0x9800, "ldr %r8, [sp, %w]" },
rlm@1 104 // Format 12
rlm@1 105 { 0xf800, 0xa000, "add %r8, pc, %w (=%K)" },
rlm@1 106 { 0xf800, 0xa800, "add %r8, sp, %w" },
rlm@1 107 // Format 13
rlm@1 108 { 0xff00, 0xb000, "add sp, %s" },
rlm@1 109 // Format 14
rlm@1 110 { 0xffff, 0xb500, "push {lr}" },
rlm@1 111 { 0xff00, 0xb400, "push {%l}" },
rlm@1 112 { 0xff00, 0xb500, "push {%l,lr}" },
rlm@1 113 { 0xffff, 0xbd00, "pop {pc}" },
rlm@1 114 { 0xff00, 0xbd00, "pop {%l,pc}" },
rlm@1 115 { 0xff00, 0xbc00, "pop {%l}" },
rlm@1 116 // Format 15
rlm@1 117 { 0xf800, 0xc000, "stmia %r8!, {%l}" },
rlm@1 118 { 0xf800, 0xc800, "ldmia %r8!, {%l}" },
rlm@1 119 // Format 17
rlm@1 120 { 0xff00, 0xdf00, "swi %m" },
rlm@1 121 // Format 16
rlm@1 122 { 0xf000, 0xd000, "b%c %W" },
rlm@1 123 // Format 18
rlm@1 124 { 0xf800, 0xe000, "b %a" },
rlm@1 125 // Format 19
rlm@1 126 { 0xf800, 0xf000, "bl %A" },
rlm@1 127 { 0xf800, 0xf800, "blh %Z" },
rlm@1 128 { 0xff00, 0xbe00, "bkpt %O" },
rlm@1 129 // Unknown
rlm@1 130 { 0x0000, 0x0000, "[ ??? ]" }
rlm@1 131 };
rlm@1 132
rlm@1 133 const Opcodes armOpcodes[] = {
rlm@1 134 // Undefined
rlm@1 135 { 0x0e000010, 0x06000010, "[ undefined ]" },
rlm@1 136 // Branch instructions
rlm@1 137 { 0x0ff000f0, 0x01200010, "bx%c %r0" },
rlm@1 138 { 0x0f000000, 0x0a000000, "b%c %o" },
rlm@1 139 { 0x0f000000, 0x0b000000, "bl%c %o" },
rlm@1 140 { 0x0f000000, 0x0f000000, "swi%c %q" },
rlm@1 141 // PSR transfer
rlm@1 142 { 0x0fbf0fff, 0x010f0000, "mrs%c %r3, %p" },
rlm@1 143 { 0x0db0f000, 0x0120f000, "msr%c %p, %i" },
rlm@1 144 // Multiply instructions
rlm@1 145 { 0x0fe000f0, 0x00000090, "mul%c%s %r4, %r0, %r2" },
rlm@1 146 { 0x0fe000f0, 0x00200090, "mla%c%s %r4, %r0, %r2, %r3" },
rlm@1 147 { 0x0fa000f0, 0x00800090, "%umull%c%s %r3, %r4, %r0, %r2" },
rlm@1 148 { 0x0fa000f0, 0x00a00090, "%umlal%c%s %r3, %r4, %r0, %r2" },
rlm@1 149 // Load/Store instructions
rlm@1 150 { 0x0fb00ff0, 0x01000090, "swp%c%b %r3, %r0, [%r4]" },
rlm@1 151 { 0x0fb000f0, 0x01000090, "[ ??? ]" },
rlm@1 152 { 0x0c100000, 0x04000000, "str%c%b%t %r3, %a" },
rlm@1 153 { 0x0c100000, 0x04100000, "ldr%c%b%t %r3, %a" },
rlm@1 154 { 0x0e100090, 0x00000090, "str%c%h %r3, %a" },
rlm@1 155 { 0x0e100090, 0x00100090, "ldr%c%h %r3, %a" },
rlm@1 156 { 0x0e100000, 0x08000000, "stm%c%m %r4%l" },
rlm@1 157 { 0x0e100000, 0x08100000, "ldm%c%m %r4%l" },
rlm@1 158 // Data processing
rlm@1 159 { 0x0de00000, 0x00000000, "and%c%s %r3, %r4, %i" },
rlm@1 160 { 0x0de00000, 0x00200000, "eor%c%s %r3, %r4, %i" },
rlm@1 161 { 0x0de00000, 0x00400000, "sub%c%s %r3, %r4, %i" },
rlm@1 162 { 0x0de00000, 0x00600000, "rsb%c%s %r3, %r4, %i" },
rlm@1 163 { 0x0de00000, 0x00800000, "add%c%s %r3, %r4, %i" },
rlm@1 164 { 0x0de00000, 0x00a00000, "adc%c%s %r3, %r4, %i" },
rlm@1 165 { 0x0de00000, 0x00c00000, "sbc%c%s %r3, %r4, %i" },
rlm@1 166 { 0x0de00000, 0x00e00000, "rsc%c%s %r3, %r4, %i" },
rlm@1 167 { 0x0de00000, 0x01000000, "tst%c%s %r4, %i" },
rlm@1 168 { 0x0de00000, 0x01200000, "teq%c%s %r4, %i" },
rlm@1 169 { 0x0de00000, 0x01400000, "cmp%c%s %r4, %i" },
rlm@1 170 { 0x0de00000, 0x01600000, "cmn%c%s %r4, %i" },
rlm@1 171 { 0x0de00000, 0x01800000, "orr%c%s %r3, %r4, %i" },
rlm@1 172 { 0x0de00000, 0x01a00000, "mov%c%s %r3, %i" },
rlm@1 173 { 0x0de00000, 0x01c00000, "bic%c%s %r3, %r4, %i" },
rlm@1 174 { 0x0de00000, 0x01e00000, "mvn%c%s %r3, %i" },
rlm@1 175 // Coprocessor operations
rlm@1 176 { 0x0f000010, 0x0e000000, "cdp%c %P, %N, %r3, %R4, %R0%V" },
rlm@1 177 { 0x0e100000, 0x0c000000, "stc%c%L %P, %r3, %A" },
rlm@1 178 { 0x0f100010, 0x0e000010, "mcr%c %P, %N, %r3, %R4, %R0%V" },
rlm@1 179 { 0x0f100010, 0x0e100010, "mrc%c %P, %N, %r3, %R4, %R0%V" },
rlm@1 180 // Unknown
rlm@1 181 { 0x00000000, 0x00000000, "[ ??? ]" }
rlm@1 182 };
rlm@1 183
rlm@1 184 char *addStr(char *dest, const char *src)
rlm@1 185 {
rlm@1 186 while (*src)
rlm@1 187 {
rlm@1 188 *dest++ = *src++;
rlm@1 189 }
rlm@1 190 return dest;
rlm@1 191 }
rlm@1 192
rlm@1 193 char *addHex(char *dest, int siz, u32 val)
rlm@1 194 {
rlm@1 195 if (siz == 0)
rlm@1 196 {
rlm@1 197 siz = 28;
rlm@1 198 while ((((val >> siz) & 15) == 0) && (siz >= 4))
rlm@1 199 siz -= 4;
rlm@1 200 siz += 4;
rlm@1 201 }
rlm@1 202 while (siz > 0)
rlm@1 203 {
rlm@1 204 siz -= 4;
rlm@1 205 *dest++ = hdig[(val >> siz) & 15];
rlm@1 206 }
rlm@1 207 return dest;
rlm@1 208 }
rlm@1 209
rlm@1 210 int disArm(u32 offset, char *dest, int flags)
rlm@1 211 {
rlm@1 212 u32 opcode = debuggerReadMemory(offset);
rlm@1 213
rlm@1 214 const Opcodes *sp = armOpcodes;
rlm@1 215 while (sp->cval != (opcode & sp->mask))
rlm@1 216 sp++;
rlm@1 217
rlm@1 218 if (flags & DIS_VIEW_ADDRESS)
rlm@1 219 {
rlm@1 220 dest = addHex(dest, 32, offset);
rlm@1 221 *dest++ = ' ';
rlm@1 222 }
rlm@1 223 if (flags & DIS_VIEW_CODE)
rlm@1 224 {
rlm@1 225 dest = addHex(dest, 32, opcode);
rlm@1 226 *dest++ = ' ';
rlm@1 227 }
rlm@1 228
rlm@1 229 const char *src = sp->mnemonic;
rlm@1 230 while (*src)
rlm@1 231 {
rlm@1 232 if (*src != '%')
rlm@1 233 *dest++ = *src++;
rlm@1 234 else
rlm@1 235 {
rlm@1 236 src++;
rlm@1 237 switch (*src)
rlm@1 238 {
rlm@1 239 case 'c':
rlm@1 240 dest = addStr(dest, conditions[opcode >> 28]);
rlm@1 241 break;
rlm@1 242 case 'r':
rlm@1 243 dest = addStr(dest, regs[(opcode >> ((*(++src) - '0') * 4)) & 15]);
rlm@1 244 break;
rlm@1 245 case 'o':
rlm@1 246 {
rlm@1 247 *dest++ = '$';
rlm@1 248 int off = opcode & 0xffffff;
rlm@1 249 if (off & 0x800000)
rlm@1 250 off |= 0xff000000;
rlm@1 251 off <<= 2;
rlm@1 252 dest = addHex(dest, 32, offset + 8 + off);
rlm@1 253 }
rlm@1 254 break;
rlm@1 255 case 'i':
rlm@1 256 if (opcode & (1 << 25))
rlm@1 257 {
rlm@1 258 dest = addStr(dest, "#0x");
rlm@1 259 int imm = opcode & 0xff;
rlm@1 260 int rot = (opcode & 0xf00) >> 7;
rlm@1 261 int val = (imm << (32 - rot)) | (imm >> rot);
rlm@1 262 dest = addHex(dest, 0, val);
rlm@1 263 }
rlm@1 264 else
rlm@1 265 {
rlm@1 266 dest = addStr(dest, regs[opcode & 0x0f]);
rlm@1 267 int shi = (opcode >> 5) & 3;
rlm@1 268 int sdw = (opcode >> 7) & 0x1f;
rlm@1 269 if ((sdw == 0) && (shi == 3))
rlm@1 270 shi = 4;
rlm@1 271 if ((sdw) || (opcode & 0x10) || (shi))
rlm@1 272 {
rlm@1 273 dest = addStr(dest, ", ");
rlm@1 274 dest = addStr(dest, shifts[shi]);
rlm@1 275 if (opcode & 0x10)
rlm@1 276 {
rlm@1 277 *dest++ = ' ';
rlm@1 278 dest = addStr(dest, regs[(opcode >> 8) & 15]);
rlm@1 279 }
rlm@1 280 else
rlm@1 281 {
rlm@1 282 if (sdw == 0 && ((shi == 1) || (shi == 2)))
rlm@1 283 sdw = 32;
rlm@1 284 if (shi != 4)
rlm@1 285 {
rlm@1 286 dest = addStr(dest, " #0x");
rlm@1 287 dest = addHex(dest, 8, sdw);
rlm@1 288 }
rlm@1 289 }
rlm@1 290 }
rlm@1 291 }
rlm@1 292 break;
rlm@1 293 case 'p':
rlm@1 294 if (opcode & (1 << 22))
rlm@1 295 dest = addStr(dest, "spsr");
rlm@1 296 else
rlm@1 297 dest = addStr(dest, "cpsr");
rlm@1 298 if (opcode & 0x00F00000)
rlm@1 299 {
rlm@1 300 *dest++ = '_';
rlm@1 301 if (opcode & 0x00080000)
rlm@1 302 *dest++ = 'f';
rlm@1 303 if (opcode & 0x00040000)
rlm@1 304 *dest++ = 's';
rlm@1 305 if (opcode & 0x00020000)
rlm@1 306 *dest++ = 'x';
rlm@1 307 if (opcode & 0x00010000)
rlm@1 308 *dest++ = 'c';
rlm@1 309 }
rlm@1 310 break;
rlm@1 311 case 's':
rlm@1 312 if (opcode & (1 << 20))
rlm@1 313 *dest++ = 's';
rlm@1 314 break;
rlm@1 315 case 'S':
rlm@1 316 if (opcode & (1 << 22))
rlm@1 317 *dest++ = 's';
rlm@1 318 break;
rlm@1 319 case 'u':
rlm@1 320 if (opcode & (1 << 22))
rlm@1 321 *dest++ = 's';
rlm@1 322 else
rlm@1 323 *dest++ = 'u';
rlm@1 324 break;
rlm@1 325 case 'b':
rlm@1 326 if (opcode & (1 << 22))
rlm@1 327 *dest++ = 'b';
rlm@1 328 break;
rlm@1 329 case 'a':
rlm@1 330 if ((opcode & 0x076f0000) == 0x004f0000)
rlm@1 331 {
rlm@1 332 *dest++ = '[';
rlm@1 333 *dest++ = '$';
rlm@1 334 int adr = offset + 8;
rlm@1 335 int add = (opcode & 15) | ((opcode >> 8) & 0xf0);
rlm@1 336 if (opcode & (1 << 23))
rlm@1 337 adr += add;
rlm@1 338 else
rlm@1 339 adr -= add;
rlm@1 340 dest = addHex(dest, 32, adr);
rlm@1 341 *dest++ = ']';
rlm@1 342 dest = addStr(dest, " (=");
rlm@1 343 *dest++ = '$';
rlm@1 344 dest = addHex(dest, 32, debuggerReadMemory(adr));
rlm@1 345 *dest++ = ')';
rlm@1 346 }
rlm@1 347 if ((opcode & 0x072f0000) == 0x050f0000)
rlm@1 348 {
rlm@1 349 *dest++ = '[';
rlm@1 350 *dest++ = '$';
rlm@1 351 int adr = offset + 8;
rlm@1 352 if (opcode & (1 << 23))
rlm@1 353 adr += opcode & 0xfff;
rlm@1 354 else
rlm@1 355 adr -= opcode & 0xfff;
rlm@1 356 dest = addHex(dest, 32, adr);
rlm@1 357 *dest++ = ']';
rlm@1 358 dest = addStr(dest, " (=");
rlm@1 359 *dest++ = '$';
rlm@1 360 dest = addHex(dest, 32, debuggerReadMemory(adr));
rlm@1 361 *dest++ = ')';
rlm@1 362 }
rlm@1 363 else
rlm@1 364 {
rlm@1 365 int reg = (opcode >> 16) & 15;
rlm@1 366 *dest++ = '[';
rlm@1 367 dest = addStr(dest, regs[reg]);
rlm@1 368 if (!(opcode & (1 << 24)))
rlm@1 369 *dest++ = ']';
rlm@1 370 if (((opcode & (1 << 25)) && (opcode & (1 << 26))) || (!(opcode & (1 << 22)) && !(opcode & (1 << 26))))
rlm@1 371 {
rlm@1 372 dest = addStr(dest, ", ");
rlm@1 373 if (!(opcode & (1 << 23)))
rlm@1 374 *dest++ = '-';
rlm@1 375 dest = addStr(dest, regs[opcode & 0x0f]);
rlm@1 376 int shi = (opcode >> 5) & 3;
rlm@1 377 if (opcode & (1 << 26))
rlm@1 378 {
rlm@1 379 if (((opcode >> 7) & 0x1f) || (opcode & 0x10) || (shi == 1) || (shi == 2))
rlm@1 380 {
rlm@1 381 dest = addStr(dest, ", ");
rlm@1 382 dest = addStr(dest, shifts[shi]);
rlm@1 383 if (opcode & 0x10)
rlm@1 384 {
rlm@1 385 *dest++ = ' ';
rlm@1 386 dest = addStr(dest, regs[(opcode >> 8) & 15]);
rlm@1 387 }
rlm@1 388 else
rlm@1 389 {
rlm@1 390 int sdw = (opcode >> 7) & 0x1f;
rlm@1 391 if (sdw == 0 && ((shi == 1) || (shi == 2)))
rlm@1 392 sdw = 32;
rlm@1 393 dest = addStr(dest, " #0x");
rlm@1 394 dest = addHex(dest, 8, sdw);
rlm@1 395 }
rlm@1 396 }
rlm@1 397 }
rlm@1 398 }
rlm@1 399 else
rlm@1 400 {
rlm@1 401 int off;
rlm@1 402 if (opcode & (1 << 26))
rlm@1 403 off = opcode & 0xfff;
rlm@1 404 else
rlm@1 405 off = (opcode & 15) | ((opcode >> 4) & 0xf0);
rlm@1 406 if (off)
rlm@1 407 {
rlm@1 408 dest = addStr(dest, ", ");
rlm@1 409 if (!(opcode & (1 << 23)))
rlm@1 410 *dest++ = '-';
rlm@1 411 dest = addStr(dest, "#0x");
rlm@1 412 dest = addHex(dest, 0, off);
rlm@1 413 }
rlm@1 414 }
rlm@1 415 if (opcode & (1 << 24))
rlm@1 416 {
rlm@1 417 *dest++ = ']';
rlm@1 418 if (opcode & (1 << 21))
rlm@1 419 *dest++ = '!';
rlm@1 420 }
rlm@1 421 }
rlm@1 422 break;
rlm@1 423 case 't':
rlm@1 424 if ((opcode & 0x01200000) == 0x01200000)
rlm@1 425 *dest++ = 't';
rlm@1 426 break;
rlm@1 427 case 'h':
rlm@1 428 if (opcode & (1 << 6))
rlm@1 429 *dest++ = 's';
rlm@1 430 if (opcode & (1 << 5))
rlm@1 431 *dest++ = 'h';
rlm@1 432 else
rlm@1 433 *dest++ = 'b';
rlm@1 434 break;
rlm@1 435 case 'm':
rlm@1 436 if (((opcode >> 16) & 15) == 13)
rlm@1 437 {
rlm@1 438 if (opcode & 0x00100000)
rlm@1 439 dest = addStr(dest, armMultLoadStore[8 + ((opcode >> 23) & 3)]);
rlm@1 440 else
rlm@1 441 dest = addStr(dest, armMultLoadStore[4 + ((opcode >> 23) & 3)]);
rlm@1 442 }
rlm@1 443 else
rlm@1 444 dest = addStr(dest, armMultLoadStore[(opcode >> 23) & 3]);
rlm@1 445 break;
rlm@1 446 case 'l':
rlm@1 447 if (opcode & (1 << 21))
rlm@1 448 *dest++ = '!';
rlm@1 449 dest = addStr(dest, ", {");
rlm@1 450 {
rlm@1 451 int rlst = opcode & 0xffff;
rlm@1 452 int msk = 0;
rlm@1 453 int not_first = 0;
rlm@1 454 while (msk < 16)
rlm@1 455 {
rlm@1 456 if (rlst & (1 << msk))
rlm@1 457 {
rlm@1 458 int fr = msk;
rlm@1 459 while (rlst & (1 << msk))
rlm@1 460 msk++;
rlm@1 461 int to = msk - 1;
rlm@1 462 if (not_first)
rlm@1 463 //dest = addStr(dest, ", ");
rlm@1 464 *dest++ = ',';
rlm@1 465 dest = addStr(dest, regs[fr]);
rlm@1 466 if (fr != to)
rlm@1 467 {
rlm@1 468 if (fr == to - 1)
rlm@1 469 //dest = addStr(", ");
rlm@1 470 *dest++ = ',';
rlm@1 471 else
rlm@1 472 *dest++ = '-';
rlm@1 473 dest = addStr(dest, regs[to]);
rlm@1 474 }
rlm@1 475 not_first = 1;
rlm@1 476 }
rlm@1 477 else
rlm@1 478 msk++;
rlm@1 479 }
rlm@1 480 *dest++ = '}';
rlm@1 481 if (opcode & (1 << 22))
rlm@1 482 *dest++ = '^';
rlm@1 483 }
rlm@1 484 break;
rlm@1 485 case 'q':
rlm@1 486 *dest++ = '$';
rlm@1 487 dest = addHex(dest, 24, opcode & 0xffffff);
rlm@1 488 break;
rlm@1 489 case 'P':
rlm@1 490 *dest++ = 'p';
rlm@1 491 dest = addStr(dest, decVals[(opcode >> 8) & 15]);
rlm@1 492 break;
rlm@1 493 case 'N':
rlm@1 494 if (opcode & 0x10)
rlm@1 495 dest = addStr(dest, decVals[(opcode >> 21) & 7]);
rlm@1 496 else
rlm@1 497 dest = addStr(dest, decVals[(opcode >> 20) & 15]);
rlm@1 498 break;
rlm@1 499 case 'R':
rlm@1 500 {
rlm@1 501 src++;
rlm@1 502 int reg = 4 * (*src - '0');
rlm@1 503 *dest++ = 'c';
rlm@1 504 dest = addStr(dest, decVals[(opcode >> reg) & 15]);
rlm@1 505 }
rlm@1 506 break;
rlm@1 507 case 'V':
rlm@1 508 {
rlm@1 509 int val = (opcode >> 5) & 7;
rlm@1 510 if (val)
rlm@1 511 {
rlm@1 512 dest = addStr(dest, ", ");
rlm@1 513 dest = addStr(dest, decVals[val]);
rlm@1 514 }
rlm@1 515 }
rlm@1 516 break;
rlm@1 517 case 'L':
rlm@1 518 if (opcode & (1 << 22))
rlm@1 519 *dest++ = 'l';
rlm@1 520 break;
rlm@1 521 case 'A':
rlm@1 522 if ((opcode & 0x012f0000) == 0x010f0000)
rlm@1 523 {
rlm@1 524 int adr = offset + 8;
rlm@1 525 int add = (opcode & 0xff) << 2;
rlm@1 526 if (opcode & (1 << 23))
rlm@1 527 adr += add;
rlm@1 528 else
rlm@1 529 adr -= add;
rlm@1 530 *dest++ = '$';
rlm@1 531 addHex(dest, 32, adr);
rlm@1 532 }
rlm@1 533 else
rlm@1 534 {
rlm@1 535 *dest++ = '[';
rlm@1 536 dest = addStr(dest, regs[(opcode >> 16) & 15]);
rlm@1 537 if (!(opcode & (1 << 24)))
rlm@1 538 *dest++ = ']';
rlm@1 539 int off = (opcode & 0xff) << 2;
rlm@1 540 if (off)
rlm@1 541 {
rlm@1 542 dest = addStr(dest, ", ");
rlm@1 543 if (!(opcode & (1 << 23)))
rlm@1 544 *dest++ = '-';
rlm@1 545 dest = addStr(dest, "#0x");
rlm@1 546 dest = addHex(dest, 0, off);
rlm@1 547 }
rlm@1 548 if (opcode & (1 << 24))
rlm@1 549 {
rlm@1 550 *dest++ = ']';
rlm@1 551 if (opcode & (1 << 21))
rlm@1 552 *dest++ = '!';
rlm@1 553 }
rlm@1 554 }
rlm@1 555 break;
rlm@1 556 }
rlm@1 557 src++;
rlm@1 558 }
rlm@1 559 }
rlm@1 560 *dest++ = 0;
rlm@1 561
rlm@1 562 return 4;
rlm@1 563 }
rlm@1 564
rlm@1 565 int disThumb(u32 offset, char *dest, int flags)
rlm@1 566 {
rlm@1 567 u32 opcode = debuggerReadHalfWord(offset);
rlm@1 568
rlm@1 569 const Opcodes *sp = thumbOpcodes;
rlm@1 570 int ret = 2;
rlm@1 571 while (sp->cval != (opcode & sp->mask))
rlm@1 572 sp++;
rlm@1 573
rlm@1 574 if (flags & DIS_VIEW_ADDRESS)
rlm@1 575 {
rlm@1 576 dest = addHex(dest, 32, offset);
rlm@1 577 *dest++ = ' ';
rlm@1 578 }
rlm@1 579 if (flags & DIS_VIEW_CODE)
rlm@1 580 {
rlm@1 581 dest = addHex(dest, 16, opcode);
rlm@1 582 *dest++ = ' ';
rlm@1 583 }
rlm@1 584
rlm@1 585 const char *src = sp->mnemonic;
rlm@1 586 while (*src)
rlm@1 587 {
rlm@1 588 if (*src != '%')
rlm@1 589 *dest++ = *src++;
rlm@1 590 else
rlm@1 591 {
rlm@1 592 src++;
rlm@1 593 switch (*src)
rlm@1 594 {
rlm@1 595 case 'r':
rlm@1 596 src++;
rlm@1 597 dest = addStr(dest, regs[(opcode >> (*src - '0')) & 7]);
rlm@1 598 break;
rlm@1 599 case 'o':
rlm@1 600 dest = addStr(dest, "#0x");
rlm@1 601 {
rlm@1 602 int val = (opcode >> 6) & 0x1f;
rlm@1 603 dest = addHex(dest, 8, val);
rlm@1 604 }
rlm@1 605 break;
rlm@1 606 case 'p':
rlm@1 607 dest = addStr(dest, "#0x");
rlm@1 608 {
rlm@1 609 int val = (opcode >> 6) & 0x1f;
rlm@1 610 if (!(opcode & (1 << 12)))
rlm@1 611 val <<= 2;
rlm@1 612 dest = addHex(dest, 0, val);
rlm@1 613 }
rlm@1 614 break;
rlm@1 615 case 'e':
rlm@1 616 dest = addStr(dest, "#0x");
rlm@1 617 dest = addHex(dest, 0, ((opcode >> 6) & 0x1f) << 1);
rlm@1 618 break;
rlm@1 619 case 'i':
rlm@1 620 dest = addStr(dest, "#0x");
rlm@1 621 dest = addHex(dest, 0, (opcode >> 6) & 7);
rlm@1 622 break;
rlm@1 623 case 'h':
rlm@1 624 {
rlm@1 625 src++;
rlm@1 626 int reg = (opcode >> (*src - '0')) & 7;
rlm@1 627 src++;
rlm@1 628 if (opcode & (1 << (*src - '0')))
rlm@1 629 reg += 8;
rlm@1 630 dest = addStr(dest, regs[reg]);
rlm@1 631 }
rlm@1 632 break;
rlm@1 633 case 'O':
rlm@1 634 dest = addStr(dest, "#0x");
rlm@1 635 dest = addHex(dest, 0, (opcode & 0xff));
rlm@1 636 break;
rlm@1 637 case 'I':
rlm@1 638 *dest++ = '$';
rlm@1 639 dest = addHex(dest, 32, (offset & 0xfffffffc) + 4 + ((opcode & 0xff) << 2));
rlm@1 640 break;
rlm@1 641 case 'J':
rlm@1 642 {
rlm@1 643 u32 value = debuggerReadMemory((offset & 0xfffffffc) + 4 +
rlm@1 644 ((opcode & 0xff) << 2));
rlm@1 645 *dest++ = '$';
rlm@1 646 dest = addHex(dest, 32, value);
rlm@1 647 const char *s = elfGetAddressSymbol(value);
rlm@1 648 if (*s)
rlm@1 649 {
rlm@1 650 *dest++ = ' ';
rlm@1 651 dest = addStr(dest, s);
rlm@1 652 }
rlm@1 653 }
rlm@1 654 break;
rlm@1 655 case 'K':
rlm@1 656 {
rlm@1 657 u32 value = (offset & 0xfffffffc) + 4 + ((opcode & 0xff) << 2);
rlm@1 658 *dest++ = '$';
rlm@1 659 dest = addHex(dest, 32, value);
rlm@1 660 const char *s = elfGetAddressSymbol(value);
rlm@1 661 if (*s)
rlm@1 662 {
rlm@1 663 *dest++ = ' ';
rlm@1 664 dest = addStr(dest, s);
rlm@1 665 }
rlm@1 666 }
rlm@1 667 break;
rlm@1 668 case 'b':
rlm@1 669 if (opcode & (1 << 10))
rlm@1 670 *dest++ = 'b';
rlm@1 671 break;
rlm@1 672 case 'B':
rlm@1 673 if (opcode & (1 << 12))
rlm@1 674 *dest++ = 'b';
rlm@1 675 break;
rlm@1 676 case 'w':
rlm@1 677 dest = addStr(dest, "#0x");
rlm@1 678 dest = addHex(dest, 0, (opcode & 0xff) << 2);
rlm@1 679 break;
rlm@1 680 case 'W':
rlm@1 681 *dest++ = '$';
rlm@1 682 {
rlm@1 683 int add = opcode & 0xff;
rlm@1 684 if (add & 0x80)
rlm@1 685 add |= 0xffffff00;
rlm@1 686 dest = addHex(dest, 32, (offset & 0xfffffffe) + 4 + (add << 1));
rlm@1 687 }
rlm@1 688 break;
rlm@1 689 case 'c':
rlm@1 690 dest = addStr(dest, conditions[(opcode >> 8) & 15]);
rlm@1 691 break;
rlm@1 692 case 's':
rlm@1 693 if (opcode & (1 << 7))
rlm@1 694 *dest++ = '-';
rlm@1 695 dest = addStr(dest, "#0x");
rlm@1 696 dest = addHex(dest, 0, (opcode & 0x7f) << 2);
rlm@1 697 break;
rlm@1 698 case 'l':
rlm@1 699 {
rlm@1 700 int rlst = opcode & 0xff;
rlm@1 701 int msk = 0;
rlm@1 702 int not_first = 0;
rlm@1 703 while (msk < 8)
rlm@1 704 {
rlm@1 705 if (rlst & (1 << msk))
rlm@1 706 {
rlm@1 707 int fr = msk;
rlm@1 708 while (rlst & (1 << msk))
rlm@1 709 msk++;
rlm@1 710 int to = msk - 1;
rlm@1 711 if (not_first)
rlm@1 712 *dest++ = ',';
rlm@1 713 dest = addStr(dest, regs[fr]);
rlm@1 714 if (fr != to)
rlm@1 715 {
rlm@1 716 if (fr == to - 1)
rlm@1 717 *dest++ = ',';
rlm@1 718 else
rlm@1 719 *dest++ = '-';
rlm@1 720 dest = addStr(dest, regs[to]);
rlm@1 721 }
rlm@1 722 not_first = 1;
rlm@1 723 }
rlm@1 724 else
rlm@1 725 msk++;
rlm@1 726 }
rlm@1 727 }
rlm@1 728 break;
rlm@1 729 case 'm':
rlm@1 730 *dest++ = '$';
rlm@1 731 dest = addHex(dest, 8, opcode & 0xff);
rlm@1 732 break;
rlm@1 733 case 'Z':
rlm@1 734 *dest++ = '$';
rlm@1 735 dest = addHex(dest, 16, (opcode & 0x7ff) << 1);
rlm@1 736 break;
rlm@1 737 case 'a':
rlm@1 738 *dest++ = '$';
rlm@1 739 {
rlm@1 740 int add = opcode & 0x07ff;
rlm@1 741 if (add & 0x400)
rlm@1 742 add |= 0xfffff800;
rlm@1 743 add <<= 1;
rlm@1 744 dest = addHex(dest, 32, offset + 4 + add);
rlm@1 745 }
rlm@1 746 break;
rlm@1 747 case 'A':
rlm@1 748 {
rlm@1 749 int nopcode = debuggerReadHalfWord(offset + 2);
rlm@1 750 int add = opcode & 0x7ff;
rlm@1 751 if (add & 0x400)
rlm@1 752 add |= 0xfff800;
rlm@1 753 add = (add << 12) | ((nopcode & 0x7ff) << 1);
rlm@1 754 *dest++ = '$';
rlm@1 755 dest = addHex(dest, 32, offset + 4 + add);
rlm@1 756 const char *s = elfGetAddressSymbol(offset + 4 + add);
rlm@1 757 if (*s)
rlm@1 758 {
rlm@1 759 *dest++ = ' ';
rlm@1 760 *dest++ = '(';
rlm@1 761 dest = addStr(dest, s);
rlm@1 762 *dest++ = ')';
rlm@1 763 }
rlm@1 764 ret = 4;
rlm@1 765 }
rlm@1 766 break;
rlm@1 767 }
rlm@1 768 src++;
rlm@1 769 }
rlm@1 770 }
rlm@1 771 *dest++ = 0;
rlm@1 772 return ret;
rlm@1 773 }
rlm@1 774