FreeCalypso > hg > freecalypso-reveng
changeset 88:691551f0635b
armdis: implemented decoding of data processing instructions
author | Michael Spacefalcon <msokolov@ivan.Harhan.ORG> |
---|---|
date | Sat, 29 Mar 2014 20:28:13 +0000 |
parents | f7fba8518fa2 |
children | c5d52666d2eb |
files | arm7dis/armdis.c |
diffstat | 1 files changed, 136 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/arm7dis/armdis.c Sat Mar 29 00:23:16 2014 +0000 +++ b/arm7dis/armdis.c Sat Mar 29 20:28:13 2014 +0000 @@ -10,6 +10,12 @@ 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; @@ -24,6 +30,131 @@ 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; +{ + printf("<dataproc overlay with S=0 for tst/cmp>\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; @@ -39,11 +170,14 @@ switch ((word >> 24) & 0xF) { case 0: case 1: - printf("<data processing, register operand>\n"); + if ((word & 0x90) == 0x90) + dataproc_74_overlay(off, word); + else + dataproc(off, word); return; case 2: case 3: - printf("<data processing, immediate operand>\n"); + dataproc(off, word); return; case 4: case 5: