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