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 }