changeset 91:daf69d5edb3f

armdis: ldr/str decoding implemented (but not PC-relative ldr yet)
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sun, 30 Mar 2014 00:27:25 +0000
parents f68d8e7a904f
children 708f2452d1ae
files arm7dis/armdis.c
diffstat 1 files changed, 86 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/arm7dis/armdis.c	Sat Mar 29 22:19:21 2014 +0000
+++ b/arm7dis/armdis.c	Sun Mar 30 00:27:25 2014 +0000
@@ -58,23 +58,23 @@
 	if (!c) {
 		switch (t) {
 		case 0:
-			printf("%s\n", regnames[word&0xF]);
+			printf("%s", regnames[word&0xF]);
 			return;
 		case 3:
-			printf("%s, rrx\n", regnames[word&0xF]);
+			printf("%s, rrx", regnames[word&0xF]);
 			return;
 		default:
 			c = 32;
 		}
 	}
-	printf("%s, %s #%u\n", regnames[word&0xF], shift_types[t], c);
+	printf("%s, %s #%u", 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],
+	printf("%s, %s %s", regnames[word&0xF], shift_types[(word>>5)&3],
 		regnames[(word>>8)&0xF]);
 }
 
@@ -86,6 +86,7 @@
 		op2_regbyreg(word);
 	else
 		op2_regbyconst(word);
+	putchar('\n');
 }
 
 static void
@@ -209,6 +210,80 @@
 }
 
 static void
+ldr_str_imm_pre(off, word)
+	unsigned off, word;
+{
+	unsigned loff = word & 0xFFF;
+
+	/* check for literal pool fetches will go here */
+	printf("%s%s%s\t%s, [%s", word&0x100000 ? "ldr" : "str",
+		condition_decode[word>>28], word&0x400000 ? "b" : "",
+		regnames[(word>>12)&0xF], regnames[(word>>16)&0xF]);
+	if (loff || word&0x200000)
+		printf(", #%s%u", word&0x800000 ? "" : "-", loff);
+	putchar(']');
+	if (word & 0x200000)
+		putchar('!');
+	if (loff >= 10)
+		printf("\t; 0x%x", loff);
+	putchar('\n');
+}
+
+static void
+ldr_str_imm_post(word)
+	unsigned word;
+{
+	unsigned loff = word & 0xFFF;
+
+	printf("%s%s%s%s\t%s, [%s], #%s%u", word&0x100000 ? "ldr" : "str",
+		condition_decode[word>>28], word&0x400000 ? "b" : "",
+		word&0x200000 ? "t" : "",
+		regnames[(word>>12)&0xF], regnames[(word>>16)&0xF],
+		word&0x800000 ? "" : "-", loff);
+	if (loff >= 10)
+		printf("\t; 0x%x", loff);
+	putchar('\n');
+}
+
+static void
+ldr_str_reg_pre(word)
+	unsigned word;
+{
+	if (word & 0x10) {
+		printf("<invalid ldr/str: offset reg shift by reg>\n");
+		return;
+	}
+	printf("%s%s%s\t%s, [%s, ", word&0x100000 ? "ldr" : "str",
+		condition_decode[word>>28], word&0x400000 ? "b" : "",
+		regnames[(word>>12)&0xF], regnames[(word>>16)&0xF]);
+	if (!(word & 0x800000))
+		putchar('-');
+	op2_regbyconst(word);
+	putchar(']');
+	if (word & 0x200000)
+		putchar('!');
+	putchar('\n');
+}
+
+static void
+ldr_str_reg_post(word)
+	unsigned word;
+{
+	if (word & 0x10) {
+		printf("<invalid ldr/str: offset reg shift by reg>\n");
+		return;
+	}
+	printf("%s%s%s%s\t%s, [%s], ", word&0x100000 ? "ldr" : "str",
+		condition_decode[word>>28], word&0x400000 ? "b" : "",
+		word&0x200000 ? "t" : "",
+		regnames[(word>>12)&0xF], regnames[(word>>16)&0xF]);
+	if (!(word & 0x800000))
+		putchar('-');
+	op2_regbyconst(word);
+	putchar('\n');
+}
+
+static void
 ldr_str_ext(off, word)
 	unsigned off, word;
 {
@@ -234,7 +309,7 @@
 	word = get_u32(filemap + off);
 	printf("%8x:\t%08x\t", base_vma + off, word);
 	if ((word >> 28) == 0xF) {
-		printf("invalid-F\n");
+		printf("<invalid-F>\n");
 		return;
 	}
 	switch ((word >> 24) & 0xF) {
@@ -250,12 +325,16 @@
 		dataproc(word);
 		return;
 	case 4:
+		ldr_str_imm_post(word);
+		return;
 	case 5:
-		printf("<ldr/str, immediate offset>\n");
+		ldr_str_imm_pre(off, word);
 		return;
 	case 6:
+		ldr_str_reg_post(word);
+		return;
 	case 7:
-		printf("<ldr/str, register offset>\n");
+		ldr_str_reg_pre(word);
 		return;
 	case 8:
 	case 9: