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