FreeCalypso > hg > freecalypso-reveng
comparison arm7dis/thumbdis.c @ 97:fb5ea2758482
thumbdis written, compiles
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Sun, 30 Mar 2014 23:32:26 +0000 |
parents | |
children | 78e4702884e3 |
comparison
equal
deleted
inserted
replaced
96:dd6c92a1aa34 | 97:fb5ea2758482 |
---|---|
1 #include <sys/types.h> | |
2 #include <stdio.h> | |
3 #include <stdlib.h> | |
4 #include <string.h> | |
5 #include <strings.h> | |
6 | |
7 extern char *binfilename; | |
8 extern u_char *filemap; | |
9 extern unsigned disasm_len, base_vma; | |
10 | |
11 extern unsigned get_u16(), get_u32(); | |
12 | |
13 extern char *regnames[16], *condition_decode[16], *shift_types[4]; | |
14 | |
15 static void | |
16 format_1_2(word) | |
17 unsigned word; | |
18 { | |
19 unsigned op, imm; | |
20 | |
21 op = (word >> 11) & 3; | |
22 if (op != 3) { | |
23 /* format 1 */ | |
24 imm = (word >> 6) & 0x1F; | |
25 if (op != 0 && imm == 0) | |
26 imm = 32; | |
27 printf("%s\t%s, %s, #%u\n", shift_types[op], regnames[word&7], | |
28 regnames[(word>>3)&7], imm); | |
29 return; | |
30 } | |
31 /* format 2 */ | |
32 printf("%s\t%s, %s, ", word&0x200 ? "sub" : "add", regnames[word&7], | |
33 regnames[(word>>3)&7]); | |
34 if (word & 0x400) | |
35 printf("#%u\n", (word >> 6) & 7); | |
36 else | |
37 printf("%s\n", regnames[(word >> 6) & 7]); | |
38 } | |
39 | |
40 static void | |
41 format_3(word) | |
42 unsigned word; | |
43 { | |
44 static char *opctab[4] = {"mov", "cmp", "add", "sub"}; | |
45 unsigned imm; | |
46 | |
47 imm = word & 0xFF; | |
48 printf("%s\t%s, #%u", opctab[(word>>11)&3], regnames[(word>>8)&7], imm); | |
49 if (imm > 9) | |
50 printf("\t; 0x%x", imm); | |
51 putchar('\n'); | |
52 } | |
53 | |
54 static void | |
55 format_4(word) | |
56 unsigned word; | |
57 { | |
58 static char *opc[16] = {"and", "eor", "lsl", "lsr", | |
59 "asr", "adc", "sbc", "ror", | |
60 "tst", "neg", "cmp", "cmn", | |
61 "orr", "mul", "bic", "mvn"}; | |
62 | |
63 printf("%s\t%s, %s\n", opc[(word>>6)&0xF], regnames[word&7], | |
64 regnames[(word>>3)&7]); | |
65 } | |
66 | |
67 static void | |
68 format_5_bx(word) | |
69 unsigned word; | |
70 { | |
71 if (word & 0x80) | |
72 printf("<invalid: blx instead of bx>\n"); | |
73 else | |
74 printf("bx\t%s\n", regnames[(word>>3)&0xF]); | |
75 } | |
76 | |
77 static void | |
78 format_5_hiops(word) | |
79 unsigned word; | |
80 { | |
81 static char *opc[3] = {"add", "cmp", "mov"}; | |
82 int reg1, reg2; | |
83 | |
84 if (word & 0xC0) { | |
85 reg1 = word & 7; | |
86 if (word & 0x80) | |
87 reg1 += 8; | |
88 reg2 = (word >> 3) & 0xF; | |
89 printf("%s\t%s, %s\n", opc[(word>>8)&3], | |
90 regnames[reg1], regnames[reg2]); | |
91 } else | |
92 printf("<invalid: hi-reg format with both low regs>\n"); | |
93 } | |
94 | |
95 static void | |
96 format_5(word) | |
97 unsigned word; | |
98 { | |
99 if ((word & 0x300) == 0x300) | |
100 format_5_bx(word); | |
101 else | |
102 format_5_hiops(word); | |
103 } | |
104 | |
105 static void | |
106 format_6(off, word) | |
107 unsigned off, word; | |
108 { | |
109 unsigned loff, litoff; | |
110 | |
111 loff = (word & 0xFF) << 2; | |
112 off &= ~3; | |
113 off += 4; | |
114 litoff = off + loff; | |
115 if (litoff+4 <= disasm_len) | |
116 printf("ldr\t%s, =0x%x\t; via 0x%x\n", regnames[(word>>8)&7], | |
117 get_u32(filemap + litoff), base_vma + litoff); | |
118 else | |
119 printf("ldr\t%s, [pc, #%u]\t(0x%x)\n", regnames[(word>>8)&7], | |
120 loff, base_vma + litoff); | |
121 } | |
122 | |
123 static void | |
124 format_7(word) | |
125 unsigned word; | |
126 { | |
127 printf("%s%s\t%s, [%s, %s]\n", word&0x800 ? "ldr" : "str", | |
128 word&0x400 ? "b" : "", regnames[word&7], | |
129 regnames[(word>>3)&7], regnames[(word>>6)&7]); | |
130 } | |
131 | |
132 static void | |
133 format_8(word) | |
134 unsigned word; | |
135 { | |
136 static char *opc[4] = {"strh", "ldrsb", "ldrh", "ldrsh"}; | |
137 | |
138 printf("%s\t%s, [%s, %s]\n", opc[(word>>10)&3], regnames[word&7], | |
139 regnames[(word>>3)&7], regnames[(word>>6)&7]); | |
140 } | |
141 | |
142 static void | |
143 format_9(word) | |
144 unsigned word; | |
145 { | |
146 unsigned loff; | |
147 | |
148 loff = (word >> 6) & 0x1F; | |
149 if (!(word & 0x1000)) | |
150 loff <<= 2; | |
151 printf("%s%s\t%s, [%s, #%u]", word&0x800 ? "ldr" : "str", | |
152 word&0x1000 ? "b" : "", regnames[word&7], | |
153 regnames[(word>>3)&7], loff); | |
154 if (loff >= 10) | |
155 printf("\t; 0x%x", loff); | |
156 putchar('\n'); | |
157 } | |
158 | |
159 static void | |
160 format_10(word) | |
161 unsigned word; | |
162 { | |
163 unsigned loff; | |
164 | |
165 loff = (word >> 6) & 0x1F; | |
166 loff <<= 1; | |
167 printf("%sh\t%s, [%s, #%u]", word&0x800 ? "ldr" : "str", | |
168 regnames[word&7], regnames[(word>>3)&7], loff); | |
169 if (loff >= 10) | |
170 printf("\t; 0x%x", loff); | |
171 putchar('\n'); | |
172 } | |
173 | |
174 static void | |
175 format_11(word) | |
176 unsigned word; | |
177 { | |
178 unsigned loff; | |
179 | |
180 loff = (word & 0xFF) << 2; | |
181 printf("%s\t%s, [sp, #%u]", word&0x800 ? "ldr" : "str", | |
182 regnames[(word>>8)&7], loff); | |
183 if (loff >= 10) | |
184 printf("\t; 0x%x", loff); | |
185 putchar('\n'); | |
186 } | |
187 | |
188 static void | |
189 format_12(off, word) | |
190 unsigned off, word; | |
191 { | |
192 unsigned loff; | |
193 | |
194 loff = (word & 0xFF) << 2; | |
195 printf("add\t%s, %s, #%u", regnames[(word>>8)&7], | |
196 word&0x800 ? "sp" : "pc", loff); | |
197 if (loff >= 10) | |
198 printf("\t; 0x%x", loff); | |
199 putchar('\n'); | |
200 } | |
201 | |
202 static void | |
203 format_13(word) | |
204 unsigned word; | |
205 { | |
206 unsigned loff; | |
207 | |
208 if ((word & 0xFF00) != 0xB000) { | |
209 printf("<invalid format 13>\n"); | |
210 return; | |
211 } | |
212 loff = (word & 0xFF) << 2; | |
213 printf("%s\tsp, #%u", word&0x80 ? "sub" : "add", loff); | |
214 if (loff >= 10) | |
215 printf("\t; 0x%x", loff); | |
216 putchar('\n'); | |
217 } | |
218 | |
219 static void | |
220 format_14(word) | |
221 unsigned word; | |
222 { | |
223 int r, flag; | |
224 | |
225 if ((word & 0xF600) != 0xB400) { | |
226 printf("<invalid format 14>\n"); | |
227 return; | |
228 } | |
229 printf("%s\t{", word&0x800 ? "pop" : "push"); | |
230 flag = 0; | |
231 for (r = 0; r < 9; r++) | |
232 if (word & (1 << r)) { | |
233 if (flag) | |
234 fputs(", ", stdout); | |
235 if (r == 8) | |
236 fputs(word&0x800 ? "pc" : "lr", stdout); | |
237 else | |
238 fputs(regnames[r], stdout); | |
239 flag = 1; | |
240 } | |
241 putchar('}'); | |
242 putchar('\n'); | |
243 } | |
244 | |
245 static void | |
246 format_15(word) | |
247 unsigned word; | |
248 { | |
249 int r, flag; | |
250 | |
251 printf("%sia\t%s!, {", word&0x800 ? "ldm" : "stm", | |
252 regnames[(word>>8)&7]); | |
253 flag = 0; | |
254 for (r = 0; r < 8; r++) | |
255 if (word & (1 << r)) { | |
256 if (flag) | |
257 fputs(", ", stdout); | |
258 fputs(regnames[r], stdout); | |
259 flag = 1; | |
260 } | |
261 putchar('}'); | |
262 putchar('\n'); | |
263 } | |
264 | |
265 static void | |
266 format_16_17(off, word) | |
267 unsigned off, word; | |
268 { | |
269 unsigned cond; | |
270 unsigned dest; | |
271 | |
272 cond = (word >> 8) & 0xF; | |
273 switch (cond) { | |
274 case 0xE: | |
275 printf("<invalid: bal>\n"); | |
276 return; | |
277 case 0xF: | |
278 printf("swi\t0x%x\n", word & 0xFF); | |
279 return; | |
280 } | |
281 dest = (word & 0xFF) << 1; | |
282 if (dest & 0x00000100) | |
283 dest |= 0xFFFFFE00; | |
284 dest += base_vma + off + 4; | |
285 printf("b%s\t0x%x\n", condition_decode[cond], dest); | |
286 } | |
287 | |
288 static void | |
289 format_18(off, word) | |
290 unsigned off, word; | |
291 { | |
292 unsigned dest; | |
293 | |
294 if (word & 0x800) { | |
295 printf("<invalid format 18>\n"); | |
296 return; | |
297 } | |
298 dest = (word & 0x7FF) << 1; | |
299 if (dest & 0x00000800) | |
300 dest |= 0xFFFFF000; | |
301 dest += base_vma + off + 4; | |
302 printf("b\t0x%x\n", dest); | |
303 } | |
304 | |
305 void | |
306 thumb_disasm_line(off) | |
307 unsigned off; | |
308 { | |
309 unsigned word; | |
310 | |
311 word = get_u16(filemap + off); | |
312 printf("%8x:\t%04x\t\t", base_vma + off, word); | |
313 switch (word >> 12) { | |
314 case 0: | |
315 case 1: | |
316 format_1_2(word); | |
317 return; | |
318 case 2: | |
319 case 3: | |
320 format_3(word); | |
321 return; | |
322 case 4: | |
323 if (word & 0x800) | |
324 format_6(off, word); | |
325 else if (word & 0x400) | |
326 format_5(word); | |
327 else | |
328 format_4(word); | |
329 return; | |
330 case 5: | |
331 if (word & 0x200) | |
332 format_8(word); | |
333 else | |
334 format_7(word); | |
335 return; | |
336 case 6: | |
337 case 7: | |
338 format_9(word); | |
339 return; | |
340 case 8: | |
341 format_10(word); | |
342 return; | |
343 case 9: | |
344 format_11(word); | |
345 return; | |
346 case 0xA: | |
347 format_12(off, word); | |
348 return; | |
349 case 0xB: | |
350 if (word & 0x400) | |
351 format_14(word); | |
352 else | |
353 format_13(word); | |
354 return; | |
355 case 0xC: | |
356 format_15(word); | |
357 return; | |
358 case 0xD: | |
359 format_16_17(off, word); | |
360 return; | |
361 case 0xE: | |
362 format_18(off, word); | |
363 return; | |
364 case 0xF: | |
365 printf("<half-bl>\n"); | |
366 return; | |
367 } | |
368 } | |
369 | |
370 thumb_check_bl(off) | |
371 unsigned off; | |
372 { | |
373 unsigned ins1, ins2; | |
374 unsigned dest; | |
375 | |
376 if (off + 4 > disasm_len) | |
377 return(0); | |
378 ins1 = get_u16(filemap + off); | |
379 if ((ins1 & 0xF800) != 0xF000) | |
380 return(0); | |
381 ins2 = get_u16(filemap + off + 2); | |
382 if ((ins2 & 0xF800) != 0xF800) | |
383 return(0); | |
384 /* match */ | |
385 dest = ((ins1 & 0x7FF) << 12) | ((ins2 & 0x7FF) << 1); | |
386 if (dest & 0x00400000) | |
387 dest |= 0xFF800000; | |
388 dest += base_vma + off + 4; | |
389 printf("%8x:\t%04x %04x\tbl\t0x%x\n", base_vma + off, ins1, ins2, dest); | |
390 return(1); | |
391 } | |
392 | |
393 main(argc, argv) | |
394 char **argv; | |
395 { | |
396 unsigned off; | |
397 | |
398 common_init(argc, argv, 2); | |
399 for (off = 0; off < disasm_len; ) { | |
400 if (thumb_check_bl(off)) | |
401 off += 4; | |
402 else { | |
403 thumb_disasm_line(off); | |
404 off += 2; | |
405 } | |
406 } | |
407 exit(0); | |
408 } |