diff arm7dis/armdis.c @ 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
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: