view src/gba/armdis.cpp @ 479:aa81beeb2500

adjusted mother.mid for easy mini-midi conversion.
author Robert McIntyre <rlm@mit.edu>
date Fri, 04 May 2012 08:06:17 -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 Opcodes
11 {
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-stack
40 "da", "ia", "db", "ib",
41 // stack store
42 "ed", "ea", "fd", "fa",
43 // stack load
44 "fa", "fd", "ea", "ed"
45 };
47 const Opcodes thumbOpcodes[] = {
48 // Format 1
49 { 0xf800, 0x0000, "lsl %r0, %r3, %o" },
50 { 0xf800, 0x0800, "lsr %r0, %r3, %o" },
51 { 0xf800, 0x1000, "asr %r0, %r3, %o" },
52 // Format 2
53 { 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 3
58 { 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 4
63 { 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 5
80 { 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 6
86 { 0xf800, 0x4800, "ldr %r8, [%I] (=%J)" },
87 // Format 7
88 { 0xfa00, 0x5000, "str%b %r0, [%r3, %r6]" },
89 { 0xfa00, 0x5800, "ldr%b %r0, [%r3, %r6]" },
90 // Format 8
91 { 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 9
96 { 0xe800, 0x6000, "str%B %r0, [%r3, %p]" },
97 { 0xe800, 0x6800, "ldr%B %r0, [%r3, %p]" },
98 // Format 10
99 { 0xf800, 0x8000, "strh %r0, [%r3, %e]" },
100 { 0xf800, 0x8800, "ldrh %r0, [%r3, %e]" },
101 // Format 11
102 { 0xf800, 0x9000, "str %r8, [sp, %w]" },
103 { 0xf800, 0x9800, "ldr %r8, [sp, %w]" },
104 // Format 12
105 { 0xf800, 0xa000, "add %r8, pc, %w (=%K)" },
106 { 0xf800, 0xa800, "add %r8, sp, %w" },
107 // Format 13
108 { 0xff00, 0xb000, "add sp, %s" },
109 // Format 14
110 { 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 15
117 { 0xf800, 0xc000, "stmia %r8!, {%l}" },
118 { 0xf800, 0xc800, "ldmia %r8!, {%l}" },
119 // Format 17
120 { 0xff00, 0xdf00, "swi %m" },
121 // Format 16
122 { 0xf000, 0xd000, "b%c %W" },
123 // Format 18
124 { 0xf800, 0xe000, "b %a" },
125 // Format 19
126 { 0xf800, 0xf000, "bl %A" },
127 { 0xf800, 0xf800, "blh %Z" },
128 { 0xff00, 0xbe00, "bkpt %O" },
129 // Unknown
130 { 0x0000, 0x0000, "[ ??? ]" }
131 };
133 const Opcodes armOpcodes[] = {
134 // Undefined
135 { 0x0e000010, 0x06000010, "[ undefined ]" },
136 // Branch instructions
137 { 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 transfer
142 { 0x0fbf0fff, 0x010f0000, "mrs%c %r3, %p" },
143 { 0x0db0f000, 0x0120f000, "msr%c %p, %i" },
144 // Multiply instructions
145 { 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 instructions
150 { 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 processing
159 { 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 operations
176 { 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 // Unknown
181 { 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 else
235 {
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 else
265 {
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 else
281 {
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 else
297 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 else
323 *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 else
339 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 else
355 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 else
364 {
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 else
389 {
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 else
400 {
401 int off;
402 if (opcode & (1 << 26))
403 off = opcode & 0xfff;
404 else
405 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 else
433 *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 else
441 dest = addStr(dest, armMultLoadStore[4 + ((opcode >> 23) & 3)]);
442 }
443 else
444 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 else
472 *dest++ = '-';
473 dest = addStr(dest, regs[to]);
474 }
475 not_first = 1;
476 }
477 else
478 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 else
497 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 else
529 adr -= add;
530 *dest++ = '$';
531 addHex(dest, 32, adr);
532 }
533 else
534 {
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 else
591 {
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 else
719 *dest++ = '-';
720 dest = addStr(dest, regs[to]);
721 }
722 not_first = 1;
723 }
724 else
725 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 }