FreeCalypso > hg > freecalypso-reveng
view arm7dis/armdis.c @ 89:c5d52666d2eb
armdis: BX/MRS/MSR decoding implemented
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Sat, 29 Mar 2014 21:36:22 +0000 |
parents | 691551f0635b |
children | f68d8e7a904f |
line wrap: on
line source
#include <sys/types.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <strings.h> extern char *binfilename; extern u_char *filemap; extern unsigned disasm_len, base_vma; extern unsigned get_u16(), get_u32(); extern char *regnames[16], *condition_decode[16]; static char *dataproc_ops[16] = {"and", "eor", "sub", "rsb", "add", "adc", "sbc", "rsc", "tst", "teq", "cmp", "cmn", "orr", "mov", "bic", "mvn"}; static char *shift_types[4] = {"lsl", "lsr", "asr", "ror"}; static void arm_branch(off, word) unsigned off, word; { unsigned dest; dest = (word & 0x00FFFFFF) << 2; if (dest & 0x02000000) dest |= 0xFC000000; dest += base_vma + off + 8; printf("b%s%s\t0x%x\n", word&0x1000000 ? "l" : "", condition_decode[word>>28], dest); } static void op2_immed(word) unsigned word; { unsigned low8, rot, val; low8 = word & 0xFF; rot = (word & 0xF00) >> 7; val = (low8 << (32 - rot)) | (low8 >> rot); if (val <= 9) printf("#%u\n", val); else printf("#%u\t; 0x%x\n", val, val); } static void op2_regbyconst(word) unsigned word; { unsigned c, t; c = (word >> 7) & 0x1F; t = (word >> 5) & 3; if (!c) { switch (t) { case 0: printf("%s\n", regnames[word&0xF]); return; case 3: printf("%s, rrx\n", regnames[word&0xF]); return; default: c = 32; } } printf("%s, %s #%u\n", regnames[word&0xF], shift_types[t], c); } static void op2_regbyreg(word) unsigned word; { printf("%s, %s %s\n", regnames[word&0xF], shift_types[(word>>5)&3], regnames[(word>>8)&0xF]); } static void op2_regshift(word) unsigned word; { if (word & 0x10) op2_regbyreg(word); else op2_regbyconst(word); } static void dataproc_op2(word) unsigned word; { if (word & 0x02000000) op2_immed(word); else op2_regshift(word); } static void dataproc_74_overlay(off, word) unsigned off, word; { printf("<dataproc overlay with 7&4 set>\n"); } static void dataproc_tstcmp_overlay(off, word) unsigned off, word; { char msrmask[5], *cp; if ((word & 0x0FFFFFF0) == 0x012FFF10) { printf("bx%s\t%s\n", condition_decode[word>>28], regnames[word&0xF]); return; } else if ((word & 0x0FBF0FFF) == 0x010F0000) { printf("mrs%s\t%s, %cPSR\n", condition_decode[word>>28], regnames[(word>>12)&0xF], word&0x400000 ? 'S' : 'C'); return; } else if ((word & 0x0DB0F000) == 0x0120F000) { if (!(word & 0x02000000) && (word & 0xFF0)) { printf("<invalid MSR>\n"); return; } if (word & 0xF0000) { cp = msrmask; if (word & 0x80000) *cp++ = 'f'; if (word & 0x40000) *cp++ = 's'; if (word & 0x20000) *cp++ = 'x'; if (word & 0x10000) *cp++ = 'c'; *cp = '\0'; } else strcpy(msrmask, "null"); printf("msr%s\t%cPSR_%s, ", condition_decode[word>>28], word&0x400000 ? 'S' : 'C', msrmask); dataproc_op2(word); return; } printf("<invalid BX/MRS/MSR>\n"); } static void dataproc(off, word) unsigned off, word; { unsigned opc; opc = (word >> 21) & 0xF; switch (opc) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 0xC: case 0xE: printf("%s%s%s\t%s, %s, ", dataproc_ops[opc], condition_decode[word>>28], word&0x100000 ? "s" : "", regnames[(word>>12)&0xF], regnames[(word>>16)&0xF]); dataproc_op2(word); return; case 0xD: case 0xF: printf("%s%s%s\t%s, ", dataproc_ops[opc], condition_decode[word>>28], word&0x100000 ? "s" : "", regnames[(word>>12)&0xF]); dataproc_op2(word); return; case 8: case 9: case 0xA: case 0xB: if (word & 0x100000) { printf("%s%s\t%s, ", dataproc_ops[opc], condition_decode[word>>28], regnames[(word>>16)&0xF]); dataproc_op2(word); } else dataproc_tstcmp_overlay(off, word); return; } } void arm_disasm_line(off) unsigned off; { unsigned word; word = get_u32(filemap + off); printf("%8x:\t%08x\t", base_vma + off, word); if ((word >> 28) == 0xF) { printf("invalid-F\n"); return; } switch ((word >> 24) & 0xF) { case 0: case 1: if ((word & 0x90) == 0x90) dataproc_74_overlay(off, word); else dataproc(off, word); return; case 2: case 3: dataproc(off, word); return; case 4: case 5: printf("<ldr/str, immediate offset>\n"); return; case 6: case 7: printf("<ldr/str, register offset>\n"); return; case 8: case 9: printf("<ldm/stm>\n"); return; case 0xA: case 0xB: arm_branch(off, word); return; case 0xC: case 0xD: case 0xE: printf("<COPROCESSOR>\n"); return; case 0xF: printf("swi%s\t0x%x\n", condition_decode[word>>28], word & 0xFFFFFF); return; } } main(argc, argv) char **argv; { unsigned off; common_init(argc, argv, 4); for (off = 0; off < disasm_len; off += 4) arm_disasm_line(off); exit(0); }