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