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)
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 /************************************************************************/
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] = {
75 const Opcodes thumbOpcodes
[] = {
77 {0xf800, 0x0000, "lsl %r0, %r3, %o"},
78 {0xf800, 0x0800, "lsr %r0, %r3, %o"},
79 {0xf800, 0x1000, "asr %r0, %r3, %o"},
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"},
86 {0xf800, 0x2000, "mov %r8, %O"},
87 {0xf800, 0x2800, "cmp %r8, %O"},
88 {0xf800, 0x3000, "add %r8, %O"},
89 {0xf800, 0x3800, "sub %r8, %O"},
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"},
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"},
114 {0xf800, 0x4800, "ldr %r8, [%I] (=%J)"},
116 {0xfa00, 0x5000, "str%b %r0, [%r3, %r6]"},
117 {0xfa00, 0x5800, "ldr%b %r0, [%r3, %r6]"},
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]"},
124 {0xe800, 0x6000, "str%B %r0, [%r3, %p]"},
125 {0xe800, 0x6800, "ldr%B %r0, [%r3, %p]"},
127 {0xf800, 0x8000, "strh %r0, [%r3, %e]"},
128 {0xf800, 0x8800, "ldrh %r0, [%r3, %e]"},
130 {0xf800, 0x9000, "str %r8, [sp, %w]"},
131 {0xf800, 0x9800, "ldr %r8, [sp, %w]"},
133 {0xf800, 0xa000, "add %r8, pc, %w (=%K)"},
134 {0xf800, 0xa800, "add %r8, sp, %w"},
136 {0xff00, 0xb000, "add sp, %s"},
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}"},
145 {0xf800, 0xc000, "stmia %r8!, {%l}"},
146 {0xf800, 0xc800, "ldmia %r8!, {%l}"},
148 {0xff00, 0xdf00, "swi %m"},
150 {0xf000, 0xd000, "b%c %W"},
152 {0xf800, 0xe000, "b %a"},
154 {0xf800, 0xf000, "bl %A"},
155 {0xf800, 0xf800, "blh %Z"},
156 {0xff00, 0xbe00, "bkpt %O"},
158 {0x0000, 0x0000, "[ ??? ]"}
161 const Opcodes armOpcodes
[] = {
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"},
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"},
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"},
209 {0x00000000, 0x00000000, "[ ??? ]"}
212 char* addStr(char *dest
, const char *src
){
219 char* addHex(char *dest
, int siz
, u32 val
){
222 while ( (((val
>>siz
)&15)==0) && (siz
>=4) )
228 *dest
++ = hdig
[(val
>>siz
)&15];
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
) )
240 if (flags
&DIS_VIEW_ADDRESS
){
241 dest
= addHex(dest
, 32, offset
);
244 if (flags
&DIS_VIEW_CODE
){
245 dest
= addHex(dest
, 32, opcode
);
249 char *src
= sp
->mnemonic
;
257 dest
= addStr(dest
, conditions
[opcode
>>28]);
260 dest
= addStr(dest
, regs
[(opcode
>>((*(++src
)-'0')*4))&15]);
265 int off
= opcode
&0xffffff;
269 dest
= addHex(dest
, 32, offset
+8+off
);
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
);
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))
285 if ( (sdw
) || (opcode
&0x10) || (shi
)) {
286 dest
= addStr(dest
, ", ");
287 dest
= addStr(dest
, shifts
[shi
]);
290 dest
= addStr(dest
, regs
[(opcode
>>8)&15]);
292 if (sdw
==0 && ( (shi
==1) || (shi
==2) ))
295 dest
= addStr(dest
, " #0x");
296 dest
= addHex(dest
, 8, sdw
);
304 dest
= addStr(dest
, "spsr");
306 dest
= addStr(dest
, "cpsr");
307 if(opcode
& 0x00F00000) {
309 if(opcode
& 0x00080000)
311 if(opcode
& 0x00040000)
313 if(opcode
& 0x00020000)
315 if(opcode
& 0x00010000)
338 if ((opcode
&0x076f0000)==0x004f0000){
342 int add
= (opcode
&15)|((opcode
>>8)&0xf0);
347 dest
= addHex(dest
, 32, adr
);
349 dest
= addStr(dest
, " (=");
351 dest
= addHex(dest
,32, debuggerReadMemory(adr
));
354 if ((opcode
&0x072f0000)==0x050f0000){
362 dest
= addHex(dest
, 32, adr
);
364 dest
= addStr(dest
, " (=");
366 dest
= addHex(dest
,32, debuggerReadMemory(adr
));
369 int reg
= (opcode
>>16)&15;
371 dest
= addStr(dest
, regs
[reg
]);
372 if (!(opcode
&(1<<24)))
374 if ( ((opcode
&(1<<25))&&(opcode
&(1<<26))) || (!(opcode
&(1<<22))&&!(opcode
&(1<<26))) ){
375 dest
= addStr(dest
, ", ");
376 if (!(opcode
&(1<<23)))
378 dest
= addStr(dest
, regs
[opcode
&0x0f]);
379 int shi
= (opcode
>>5)&3;
381 if ( ((opcode
>>7)&0x1f) || (opcode
&0x10) || (shi
==1) || (shi
==2)){
382 dest
= addStr(dest
, ", ");
383 dest
= addStr(dest
, shifts
[shi
]);
386 dest
= addStr(dest
, regs
[(opcode
>>8)&15]);
388 int sdw
= (opcode
>>7)&0x1f;
389 if (sdw
==0 && ( (shi
==1) || (shi
==2) ))
391 dest
= addStr(dest
, " #0x");
392 dest
= addHex(dest
, 8, sdw
);
401 off
= (opcode
&15)|((opcode
>>4)&0xf0);
403 dest
= addStr(dest
, ", ");
404 if (!(opcode
&(1<<23)))
406 dest
= addStr(dest
, "#0x");
407 dest
= addHex(dest
, 0, off
);
418 if ((opcode
&0x01200000)==0x01200000)
430 if (((opcode
>>16)&15)==13) {
431 if(opcode
& 0x00100000)
432 dest
= addStr(dest
, armMultLoadStore
[8+((opcode
>>23)&3)]);
434 dest
= addStr(dest
, armMultLoadStore
[4+((opcode
>>23)&3)]);
436 dest
= addStr(dest
, armMultLoadStore
[(opcode
>>23)&3]);
441 dest
= addStr(dest
, ", {");
443 int rlst
= opcode
&0xffff;
449 while (rlst
&(1<<msk
))
453 //dest = addStr(dest, ", ");
455 dest
= addStr(dest
, regs
[fr
]);
458 //dest = addStr(", ");
462 dest
= addStr(dest
, regs
[to
]);
475 dest
= addHex(dest
, 24, opcode
&0xffffff);
479 dest
= addStr(dest
, decVals
[(opcode
>>8)&15]);
483 dest
= addStr(dest
, decVals
[(opcode
>>21)&7]);
485 dest
= addStr(dest
, decVals
[(opcode
>>20)&15]);
490 int reg
= 4*(*src
-'0');
492 dest
= addStr(dest
, decVals
[(opcode
>>reg
)&15]);
497 int val
= (opcode
>>5)&7;
499 dest
= addStr(dest
, ", ");
500 dest
= addStr(dest
, decVals
[val
]);
509 if ((opcode
&0x012f0000)==0x010f0000){
511 int add
= (opcode
&0xff)<<2;
517 addHex(dest
, 32, adr
);
520 dest
= addStr(dest
, regs
[(opcode
>>16)&15]);
521 if (!(opcode
&(1<<24)))
523 int off
= (opcode
&0xff)<<2;
525 dest
= addStr(dest
, ", ");
526 if (!(opcode
&(1<<23)))
528 dest
= addStr(dest
, "#0x");
529 dest
= addHex(dest
, 0, off
);
547 int disThumb(u32 offset
, char *dest
, int flags
){
548 u32 opcode
= debuggerReadHalfWord(offset
);
550 const Opcodes
*sp
= thumbOpcodes
;
552 while( sp
->cval
!= (opcode
& sp
->mask
) )
555 if (flags
&DIS_VIEW_ADDRESS
){
556 dest
= addHex(dest
, 32, offset
);
559 if (flags
&DIS_VIEW_CODE
){
560 dest
= addHex(dest
, 16, opcode
);
564 char *src
= sp
->mnemonic
;
573 dest
= addStr(dest
, regs
[(opcode
>>(*src
-'0'))&7]);
576 dest
= addStr(dest
, "#0x");
578 int val
= (opcode
>>6)&0x1f;
579 dest
= addHex(dest
, 8, val
);
583 dest
= addStr(dest
, "#0x");
585 int val
= (opcode
>>6)&0x1f;
586 if (!(opcode
&(1<<12)))
588 dest
= addHex(dest
, 0, val
);
592 dest
= addStr(dest
, "#0x");
593 dest
= addHex(dest
, 0, ((opcode
>>6)&0x1f)<<1);
596 dest
= addStr(dest
, "#0x");
597 dest
= addHex(dest
, 0, (opcode
>>6)&7);
602 int reg
= (opcode
>>(*src
-'0'))&7;
604 if (opcode
&(1<<(*src
-'0')))
606 dest
= addStr(dest
, regs
[reg
]);
610 dest
= addStr(dest
, "#0x");
611 dest
= addHex(dest
, 0, (opcode
&0xff));
615 dest
= addHex(dest
, 32, (offset
&0xfffffffc)+4+((opcode
&0xff)<<2));
619 u32 value
= debuggerReadMemory((offset
&0xfffffffc)+4+
620 ((opcode
& 0xff)<<2));
622 dest
= addHex(dest
, 32, value
);
623 char *s
= elfGetAddressSymbol(value
);
626 dest
= addStr(dest
, s
);
632 u32 value
= (offset
&0xfffffffc)+4+((opcode
& 0xff)<<2);
634 dest
= addHex(dest
, 32, value
);
635 char *s
= elfGetAddressSymbol(value
);
638 dest
= addStr(dest
, s
);
651 dest
= addStr(dest
, "#0x");
652 dest
= addHex(dest
, 0, (opcode
&0xff)<<2);
657 int add
= opcode
&0xff;
660 dest
= addHex(dest
, 32, (offset
&0xfffffffe)+4+(add
<<1));
664 dest
= addStr(dest
, conditions
[(opcode
>>8)&15]);
669 dest
= addStr(dest
, "#0x");
670 dest
= addHex(dest
, 0, (opcode
&0x7f)<<2);
674 int rlst
= opcode
&0xff;
680 while (rlst
&(1<<msk
))
685 dest
= addStr(dest
, regs
[fr
]);
691 dest
= addStr(dest
, regs
[to
]);
701 dest
= addHex(dest
, 8, opcode
&0xff);
705 dest
= addHex(dest
, 16, (opcode
&0x7ff)<<1);
710 int add
= opcode
&0x07ff;
714 dest
= addHex(dest
, 32, offset
+4+add
);
719 int nopcode
= debuggerReadHalfWord(offset
+2);
720 int add
= opcode
&0x7ff;
723 add
= (add
<<12)|((nopcode
&0x7ff)<<1);
725 dest
= addHex(dest
,32, offset
+4+add
);
726 char *s
= elfGetAddressSymbol(offset
+4+add
);
730 dest
= addStr(dest
, s
);