FreeCalypso > hg > freecalypso-reveng
comparison arm7dis/armdis.c @ 92:708f2452d1ae
armdis: full ldr/str decoding implemented
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Sun, 30 Mar 2014 01:47:28 +0000 |
parents | daf69d5edb3f |
children | 5ebebbc74622 |
comparison
equal
deleted
inserted
replaced
91:daf69d5edb3f | 92:708f2452d1ae |
---|---|
207 regnames[word&0xF], regnames[(word>>8)&0xF]); | 207 regnames[word&0xF], regnames[(word>>8)&0xF]); |
208 else | 208 else |
209 printf("<invalid multiply>\n"); | 209 printf("<invalid multiply>\n"); |
210 } | 210 } |
211 | 211 |
212 static int | |
213 check_ldr_litpool(off, word, loff, size) | |
214 unsigned off, word, loff; | |
215 { | |
216 unsigned litoff, datum; | |
217 | |
218 /* base reg must be 15 */ | |
219 if (((word >> 16) & 0xF) != 15) | |
220 return(0); | |
221 /* must be a load */ | |
222 if (!(word & 0x100000)) | |
223 return(0); | |
224 /* no writeback allowed */ | |
225 if (word & 0x200000) | |
226 return(0); | |
227 /* alignment */ | |
228 if (loff & (size - 1)) | |
229 return(0); | |
230 /* range */ | |
231 off += 8; | |
232 if (word & 0x800000) | |
233 litoff = off + loff; | |
234 else { | |
235 if (loff > off) | |
236 return(0); | |
237 litoff = off - loff; | |
238 } | |
239 if (litoff >= disasm_len) | |
240 return(0); | |
241 /* all checks passed, proceed */ | |
242 switch (size) { | |
243 case 1: | |
244 datum = filemap[litoff]; | |
245 break; | |
246 case 2: | |
247 datum = get_u16(filemap + litoff); | |
248 break; | |
249 case 4: | |
250 datum = get_u32(filemap + litoff); | |
251 break; | |
252 } | |
253 printf("=0x%x\t; via 0x%x\n", datum, litoff); | |
254 return(1); | |
255 } | |
256 | |
212 static void | 257 static void |
213 ldr_str_imm_pre(off, word) | 258 ldr_str_imm_pre(off, word) |
214 unsigned off, word; | 259 unsigned off, word; |
215 { | 260 { |
216 unsigned loff = word & 0xFFF; | 261 unsigned loff = word & 0xFFF; |
217 | 262 |
218 /* check for literal pool fetches will go here */ | 263 printf("%s%s%s\t%s, ", word&0x100000 ? "ldr" : "str", |
219 printf("%s%s%s\t%s, [%s", word&0x100000 ? "ldr" : "str", | |
220 condition_decode[word>>28], word&0x400000 ? "b" : "", | 264 condition_decode[word>>28], word&0x400000 ? "b" : "", |
221 regnames[(word>>12)&0xF], regnames[(word>>16)&0xF]); | 265 regnames[(word>>12)&0xF]); |
266 if (check_ldr_litpool(off, word, loff, word&0x400000 ? 1 : 4)) | |
267 return; | |
268 printf("[%s", regnames[(word>>16)&0xF]); | |
222 if (loff || word&0x200000) | 269 if (loff || word&0x200000) |
223 printf(", #%s%u", word&0x800000 ? "" : "-", loff); | 270 printf(", #%s%u", word&0x800000 ? "" : "-", loff); |
224 putchar(']'); | 271 putchar(']'); |
225 if (word & 0x200000) | 272 if (word & 0x200000) |
226 putchar('!'); | 273 putchar('!'); |
285 | 332 |
286 static void | 333 static void |
287 ldr_str_ext(off, word) | 334 ldr_str_ext(off, word) |
288 unsigned off, word; | 335 unsigned off, word; |
289 { | 336 { |
290 printf("<extended ldr/str>\n"); | 337 unsigned loff; |
338 | |
339 if (!(word&0x01000000) && word&0x200000) { | |
340 printf("<invalid ldrh/strh: P=0, W=1>\n"); | |
341 return; | |
342 } | |
343 if (!(word&0x400000) && word&0xF00) { | |
344 printf("<invalid ldrh/strh: SBZ!=0>\n"); | |
345 return; | |
346 } | |
347 printf("%s%s%s%c\t%s, ", word&0x100000 ? "ldr" : "str", | |
348 condition_decode[word>>28], | |
349 word&0x40 ? "s" : "", | |
350 word&0x20 ? 'h' : 'b', | |
351 regnames[(word>>12)&0xF]); | |
352 if (word & 0x400000) | |
353 loff = ((word & 0xF00) >> 4) | (word & 0xF); | |
354 switch (word & 0x01400000) { | |
355 case 0: | |
356 /* reg post */ | |
357 printf("[%s], %s%s", regnames[(word>>16)&0xF], | |
358 word&0x800000 ? "" : "-", regnames[word&0xF]); | |
359 break; | |
360 case 0x400000: | |
361 /* imm post */ | |
362 printf("[%s], #%s%u", regnames[(word>>16)&0xF], | |
363 word&0x800000 ? "" : "-", loff); | |
364 if (loff >= 10) | |
365 printf("\t; 0x%x", loff); | |
366 break; | |
367 case 0x01000000: | |
368 /* reg pre */ | |
369 printf("[%s, %s%s]%s", regnames[(word>>16)&0xF], | |
370 word&0x800000 ? "" : "-", regnames[word&0xF], | |
371 word&0x200000 ? "!" : ""); | |
372 break; | |
373 case 0x01400000: | |
374 /* imm pre */ | |
375 if (check_ldr_litpool(off, word, loff, word&0x20 ? 2 : 1)) | |
376 return; | |
377 printf("[%s", regnames[(word>>16)&0xF]); | |
378 if (loff || word&0x200000) | |
379 printf(", #%s%u", word&0x800000 ? "" : "-", loff); | |
380 putchar(']'); | |
381 if (word & 0x200000) | |
382 putchar('!'); | |
383 if (loff >= 10) | |
384 printf("\t; 0x%x", loff); | |
385 break; | |
386 } | |
387 putchar('\n'); | |
291 } | 388 } |
292 | 389 |
293 static void | 390 static void |
294 dataproc_74_overlay(off, word) | 391 dataproc_74_overlay(off, word) |
295 unsigned off, word; | 392 unsigned off, word; |