changeset 134:ab50421b1b7a

Improve disassembler
author Mike Pavone <pavone@retrodev.com>
date Sun, 30 Dec 2012 09:55:18 -0800
parents c4d10c2aaee2
children a81c548cf353
files 68kinst.c 68kinst.h dis.c
diffstat 3 files changed, 123 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/68kinst.c	Sun Dec 30 09:55:07 2012 -0800
+++ b/68kinst.c	Sun Dec 30 09:55:18 2012 -0800
@@ -1156,7 +1156,7 @@
 	"le"
 };
 
-int m68k_disasm_op(m68k_op_info *decoded, char *dst, int need_comma)
+int m68k_disasm_op(m68k_op_info *decoded, char *dst, int need_comma, uint8_t labels, uint32_t address)
 {
 	char * c = need_comma ? "," : "";
 	switch(decoded->addr_mode)
@@ -1179,11 +1179,23 @@
 	case MODE_IMMEDIATE_WORD:
 		return sprintf(dst, (decoded->params.immed <= 128 ? "%s #%d" : "%s #$%X"), c, decoded->params.immed);
 	case MODE_ABSOLUTE_SHORT:
-		return sprintf(dst, "%s $%X.w", c, decoded->params.immed);
+		if (labels) {
+			return sprintf(dst, "%s ADDR_%X.w", c, decoded->params.immed);
+		} else {
+			return sprintf(dst, "%s $%X.w", c, decoded->params.immed);
+		}
 	case MODE_ABSOLUTE:
-		return sprintf(dst, "%s $%X", c, decoded->params.immed);
+		if (labels) {
+			return sprintf(dst, "%s ADDR_%X.l", c, decoded->params.immed);
+		} else {
+			return sprintf(dst, "%s $%X", c, decoded->params.immed);
+		}
 	case MODE_PC_DISPLACE:
-		return sprintf(dst, "%s (%d, pc)", c, decoded->params.regs.displacement);
+		if (labels) {
+			return sprintf(dst, "%s ADDR_%X(pc)", c, address + 2 + decoded->params.regs.displacement);
+		} else {
+			return sprintf(dst, "%s (%d, pc)", c, decoded->params.regs.displacement);
+		}
 	case MODE_PC_INDEX_DISP8:
 		return sprintf(dst, "%s (%d, pc, %c%d.%c)", c, decoded->params.regs.displacement, (decoded->params.regs.sec & 0x10) ? 'a': 'd', (decoded->params.regs.sec >> 1) & 0x7, (decoded->params.regs.sec & 1) ? 'l': 'w');
 	default:
@@ -1191,7 +1203,7 @@
 	}
 }
 
-int m68k_disasm_movem_op(m68k_op_info *decoded, m68k_op_info *other, char *dst, int need_comma)
+int m68k_disasm_movem_op(m68k_op_info *decoded, m68k_op_info *other, char *dst, int need_comma, uint8_t labels, uint32_t address)
 {
 	int8_t dir, reg, bit, regnum, last=-1, lastreg, first=-1;
 	char *rtype, *last_rtype;
@@ -1245,11 +1257,11 @@
 		}
 		return oplen;
 	} else {
-		return m68k_disasm_op(decoded, dst, need_comma);
+		return m68k_disasm_op(decoded, dst, need_comma, labels, address);
 	}
 }
 
-int m68k_disasm(m68kinst * decoded, char * dst)
+int m68k_disasm_ex(m68kinst * decoded, char * dst, uint8_t labels)
 {
 	int ret,op1len;
 	uint8_t size;
@@ -1265,21 +1277,34 @@
 		strcpy(dst+ret, cond_mnem[decoded->extra.cond]);
 		ret = strlen(dst);
 		if (decoded->op != M68K_SCC) {
-			if (decoded->op == M68K_DBCC) {
-				ret += sprintf(dst+ret, " d%d, #%d <%X>", decoded->dst.params.regs.pri, decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed);
+			if (labels) {
+				if (decoded->op == M68K_DBCC) {
+					ret += sprintf(dst+ret, " d%d, ADDR_%X", decoded->dst.params.regs.pri, decoded->address + 2 + decoded->src.params.immed);
+				} else {
+					ret += sprintf(dst+ret, " ADDR_%X", decoded->address + 2 + decoded->src.params.immed);
+				}
 			} else {
-				ret += sprintf(dst+ret, " #%d <%X>", decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed);
+				if (decoded->op == M68K_DBCC) {
+					ret += sprintf(dst+ret, " d%d, #%d <%X>", decoded->dst.params.regs.pri, decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed);
+				} else {
+					ret += sprintf(dst+ret, " #%d <%X>", decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed);
+				}
 			}
 			return ret;
 		}
 		break;
 	case M68K_BSR:
-		ret = sprintf(dst, "bsr%s #%d <%X>", decoded->variant == VAR_BYTE ? ".s" : "", decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed);
+		if (labels) {
+			ret = sprintf(dst, "bsr%s ADDR_%X", decoded->variant == VAR_BYTE ? ".s" : "", 
+			decoded->address + 2 + decoded->src.params.immed);
+		} else {
+			ret = sprintf(dst, "bsr%s #%d <%X>", decoded->variant == VAR_BYTE ? ".s" : "", decoded->src.params.immed, decoded->address + 2 + decoded->src.params.immed);
+		}
 		return ret;
 	case M68K_MOVE_FROM_SR:
 		ret = sprintf(dst, "%s", mnemonics[decoded->op]);
 		ret += sprintf(dst + ret, " SR");
-		ret += m68k_disasm_op(&(decoded->dst), dst + ret, 1);
+		ret += m68k_disasm_op(&(decoded->dst), dst + ret, 1, labels, decoded->address);
 		return ret;
 	case M68K_ANDI_SR:
 	case M68K_EORI_SR:
@@ -1291,17 +1316,17 @@
 	case M68K_MOVE_CCR:
 	case M68K_ORI_CCR:
 		ret = sprintf(dst, "%s", mnemonics[decoded->op]);
-		ret += m68k_disasm_op(&(decoded->src), dst + ret, 0);
+		ret += m68k_disasm_op(&(decoded->src), dst + ret, 0, labels, decoded->address);
 		ret += sprintf(dst + ret, ", %s", special_op);
 		return ret;
 	case M68K_MOVE_USP:
 		ret = sprintf(dst, "%s", mnemonics[decoded->op]);
 		if (decoded->src.addr_mode != MODE_UNUSED) {
-			ret += m68k_disasm_op(&(decoded->src), dst + ret, 0);
+			ret += m68k_disasm_op(&(decoded->src), dst + ret, 0, labels, decoded->address);
 			ret += sprintf(dst + ret, ", USP");
 		} else {
 			ret += sprintf(dst + ret, "USP, ");
-			ret += m68k_disasm_op(&(decoded->dst), dst + ret, 0);
+			ret += m68k_disasm_op(&(decoded->dst), dst + ret, 0, labels, decoded->address);
 		}
 		return ret;
 	default:
@@ -1312,14 +1337,23 @@
 				size == OPSIZE_BYTE ? ".b" : (size == OPSIZE_WORD ? ".w" : (size == OPSIZE_LONG ? ".l" : "")));
 	}
 	if (decoded->op == M68K_MOVEM) {
-		op1len = m68k_disasm_movem_op(&(decoded->src), &(decoded->dst), dst + ret, 0);
+		op1len = m68k_disasm_movem_op(&(decoded->src), &(decoded->dst), dst + ret, 0, labels, decoded->address);
 		ret += op1len;
-		ret += m68k_disasm_movem_op(&(decoded->dst), &(decoded->src), dst + ret, op1len);
+		ret += m68k_disasm_movem_op(&(decoded->dst), &(decoded->src), dst + ret, op1len, labels, decoded->address);
 	} else {
-		op1len = m68k_disasm_op(&(decoded->src), dst + ret, 0);
+		op1len = m68k_disasm_op(&(decoded->src), dst + ret, 0, labels, decoded->address);
 		ret += op1len;
-		ret += m68k_disasm_op(&(decoded->dst), dst + ret, op1len);
+		ret += m68k_disasm_op(&(decoded->dst), dst + ret, op1len, labels, decoded->address);
 	}
 	return ret;
 }
 
+int m68k_disasm(m68kinst * decoded, char * dst)
+{
+	return m68k_disasm_ex(decoded, dst, 0);
+}
+
+int m68k_disasm_labels(m68kinst * decoded, char * dst)
+{
+	return m68k_disasm_ex(decoded, dst, 1);
+}
--- a/68kinst.h	Sun Dec 30 09:55:07 2012 -0800
+++ b/68kinst.h	Sun Dec 30 09:55:18 2012 -0800
@@ -185,6 +185,7 @@
 uint16_t * m68k_decode(uint16_t * istream, m68kinst * dst, uint32_t address);
 uint32_t m68k_cycles(m68kinst * inst);
 int m68k_disasm(m68kinst * decoded, char * dst);
+int m68k_disasm_labels(m68kinst * decoded, char * dst);
 
 #endif
 
--- a/dis.c	Sun Dec 30 09:55:07 2012 -0800
+++ b/dis.c	Sun Dec 30 09:55:18 2012 -0800
@@ -3,6 +3,7 @@
 #include <stdlib.h>
 
 uint8_t visited[(16*1024*1024)/16];
+uint8_t label[(16*1024*1024)/16];
 
 void visit(uint32_t address)
 {
@@ -10,12 +11,25 @@
 	visited[address/16] |= 1 << ((address / 2) % 8);
 }
 
+void reference(uint32_t address)
+{
+	address &= 0xFFFFFF;
+	//printf("referenced: %X\n", address);
+	label[address/16] |= 1 << ((address / 2) % 8);
+}
+
 uint8_t is_visited(uint32_t address)
 {
 	address &= 0xFFFFFF;
 	return visited[address/16] & (1 << ((address / 2) % 8));
 }
 
+uint8_t is_label(uint32_t address)
+{
+	address &= 0xFFFFFF;
+	return label[address/16] & (1 << ((address / 2) % 8));
+}
+
 typedef struct deferred {
 	uint32_t address;
 	struct deferred *next;
@@ -33,7 +47,22 @@
 	return d;
 }
 
-#define SIMPLE 0
+void check_reference(m68kinst * inst, m68k_op_info * op)
+{
+	switch(op->addr_mode)
+	{
+	case MODE_PC_DISPLACE:
+		reference(inst->address + 2 + op->params.regs.displacement);
+		break;
+	case MODE_ABSOLUTE:
+	case MODE_ABSOLUTE_SHORT:
+		reference(op->params.immed);
+		break;
+	}
+}
+
+uint8_t labels = 0;
+uint8_t addr = 0;
 
 int main(int argc, char ** argv)
 {
@@ -49,12 +78,24 @@
 	filebuf = malloc(filesize);
 	fread(filebuf, 2, filesize/2, f);
 	fclose(f);
+	for(uint8_t opt = 2; opt < argc; ++opt) {
+		if (argv[opt][0] == '-') {
+			switch (argv[opt][1])
+			{
+			case 'l':
+				labels = 1;
+				break;
+			case 'a':
+				addr = 1;
+				break;
+			}
+		}
+	}
 	for(cur = filebuf; cur - filebuf < (filesize/2); ++cur)
 	{
 		*cur = (*cur >> 8) | (*cur << 8);
 	}
 	uint32_t address = filebuf[2] << 16 | filebuf[3], tmp_addr;
-	#if !SIMPLE
 	uint16_t *encoded, *next;
 	uint32_t size;
 	deferred *def = NULL, *tmpd;
@@ -86,17 +127,21 @@
 			encoded = next;
 			//m68k_disasm(&instbuf, disbuf);
 			//printf("%X: %s\n", instbuf.address, disbuf);
+			check_reference(&instbuf, &(instbuf.src));
+			check_reference(&instbuf, &(instbuf.dst));
 			if (instbuf.op == M68K_ILLEGAL || instbuf.op == M68K_RTS || instbuf.op == M68K_RTE) {
 				break;
 			} else if (instbuf.op == M68K_BCC || instbuf.op == M68K_DBCC || instbuf.op == M68K_BSR) {
 				if (instbuf.op == M68K_BCC && instbuf.extra.cond == COND_TRUE) {
 					address = instbuf.address + 2 + instbuf.src.params.immed;
 					encoded = filebuf + address/2;
+					reference(address);
 					if (is_visited(address)) {
 						break;
 					}
 				} else {
 					tmp_addr = instbuf.address + 2 + instbuf.src.params.immed;
+					reference(tmp_addr);
 					def = defer(tmp_addr, def);
 				}
 			} else if(instbuf.op == M68K_JMP) {
@@ -124,22 +169,33 @@
 			}
 		}
 	}
+	if (labels) {
+		for (address = filesize; address < (16*1024*1024); address++) {
+			if (is_label(address)) {
+				printf("ADR_%X equ $%X\n", address, address);
+			}
+		}
+		puts("");
+	}
 	for (address = 0; address < filesize; address+=2) {
 		if (is_visited(address)) {
 			encoded = filebuf + address/2;
 			m68k_decode(encoded, &instbuf, address);
-			m68k_disasm(&instbuf, disbuf);
-			printf("%X: %s\n", instbuf.address, disbuf);
+			if (labels) {
+				m68k_disasm_labels(&instbuf, disbuf);
+				if (is_label(instbuf.address)) {
+					printf("ADR_%X:\n", instbuf.address);
+				}
+				if (addr) {
+					printf("\t%s\t;%X\n", disbuf, instbuf.address);
+				} else {
+					printf("\t%s\n", disbuf);
+				}
+			} else {
+				m68k_disasm(&instbuf, disbuf);
+				printf("%X: %s\n", instbuf.address, disbuf);
+			}
 		}
 	}
-	#else
-	for(cur = filebuf + 0x100; (cur - filebuf) < (filesize/2); )
-	{
-		unsigned short * start = cur;
-		cur = m68k_decode(cur, &instbuf, (start - filebuf)*2);
-		m68k_disasm(&instbuf, disbuf);
-		printf("%X: %s\n", instbuf.address, disbuf);
-	}
-	#endif
 	return 0;
 }