summaryrefslogtreecommitdiff
path: root/dis.c
diff options
context:
space:
mode:
Diffstat (limited to 'dis.c')
-rw-r--r--dis.c203
1 files changed, 152 insertions, 51 deletions
diff --git a/dis.c b/dis.c
index 8ec5bb2..17dbc56 100644
--- a/dis.c
+++ b/dis.c
@@ -1,14 +1,17 @@
/*
Copyright 2013 Michael Pavone
- This file is part of BlastEm.
+ This file is part of BlastEm.
BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
*/
#include "68kinst.h"
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
+#include "vos_program_module.h"
+#include "tern.h"
uint8_t visited[(16*1024*1024)/16];
-uint8_t label[(16*1024*1024)/8];
+uint16_t label[(16*1024*1024)/8];
void visit(uint32_t address)
{
@@ -20,7 +23,7 @@ void reference(uint32_t address)
{
address &= 0xFFFFFF;
//printf("referenced: %X\n", address);
- label[address/16] |= 1 << (address % 8);
+ label[address/16] |= 1 << (address % 16);
}
uint8_t is_visited(uint32_t address)
@@ -29,10 +32,40 @@ uint8_t is_visited(uint32_t address)
return visited[address/16] & (1 << ((address / 2) % 8));
}
-uint8_t is_label(uint32_t address)
+uint16_t is_label(uint32_t address)
{
address &= 0xFFFFFF;
- return label[address/16] & (1 << (address % 8));
+ return label[address/16] & (1 << (address % 16));
+}
+
+typedef struct {
+ uint32_t num_labels;
+ uint32_t storage;
+ char *labels[];
+} label_names;
+
+tern_node * add_label(tern_node * head, char * name, uint32_t address)
+{
+ char key[MAX_INT_KEY_SIZE];
+ address &= 0xFFFFFF;
+ reference(address);
+ tern_int_key(address, key);
+ label_names * names = tern_find_ptr(head, key);
+ if (names)
+ {
+ if (names->num_labels == names->storage)
+ {
+ names->storage = names->storage + (names->storage >> 1);
+ names = realloc(names, sizeof(label_names) + names->storage * sizeof(char *));
+ }
+ } else {
+ names = malloc(sizeof(label_names) + 4 * sizeof(char *));
+ names->num_labels = 0;
+ names->storage = 4;
+ head = tern_insert_ptr(head, key, names);
+ }
+ names->labels[names->num_labels++] = strdup(name);
+ return head;
}
typedef struct deferred {
@@ -42,7 +75,7 @@ typedef struct deferred {
deferred * defer(uint32_t address, deferred * next)
{
- if (is_visited(address)) {
+ if (is_visited(address) || address & 1) {
return next;
}
//printf("deferring %X\n", address);
@@ -66,9 +99,18 @@ void check_reference(m68kinst * inst, m68k_op_info * op)
}
}
-uint8_t labels = 0;
-uint8_t addr = 0;
-uint8_t only = 0;
+int label_fun(char *dst, uint32_t address, void * data)
+{
+ tern_node * labels = data;
+ char key[MAX_INT_KEY_SIZE];
+ label_names * names = tern_find_ptr(labels, tern_int_key(address & 0xFFFFFF, key));
+ if (names)
+ {
+ return sprintf(dst, "%s", names->labels[0]);
+ } else {
+ return m68k_default_label_fun(dst, address, NULL);
+ }
+}
int main(int argc, char ** argv)
{
@@ -77,14 +119,10 @@ int main(int argc, char ** argv)
char disbuf[1024];
m68kinst instbuf;
unsigned short * cur;
- FILE * f = fopen(argv[1], "rb");
- fseek(f, 0, SEEK_END);
- filesize = ftell(f);
- fseek(f, 0, SEEK_SET);
- filebuf = malloc(filesize);
- fread(filebuf, 2, filesize/2, f);
- fclose(f);
deferred *def = NULL, *tmpd;
+
+ uint8_t labels = 0, addr = 0, only = 0, vos = 0, reset = 0;
+
for(uint8_t opt = 2; opt < argc; ++opt) {
if (argv[opt][0] == '-') {
FILE * address_log;
@@ -99,6 +137,12 @@ int main(int argc, char ** argv)
case 'o':
only = 1;
break;
+ case 'v':
+ vos = 1;
+ break;
+ case 'r':
+ reset = 1;
+ break;
case 'f':
opt++;
if (opt >= argc) {
@@ -126,29 +170,85 @@ int main(int argc, char ** argv)
reference(address);
}
}
- for(cur = filebuf; cur - filebuf < (filesize/2); ++cur)
+
+ FILE * f = fopen(argv[1], "rb");
+ fseek(f, 0, SEEK_END);
+ filesize = ftell(f);
+ fseek(f, 0, SEEK_SET);
+
+ tern_node * named_labels = NULL;
+ char int_key[MAX_INT_KEY_SIZE];
+ uint32_t address_off, address_end;
+ if (vos)
{
- *cur = (*cur >> 8) | (*cur << 8);
+ vos_program_module header;
+ vos_read_header(f, &header);
+ vos_read_alloc_module_map(f, &header);
+ address_off = header.user_boundary;
+ address_end = address_off + filesize - 0x1000;
+ def = defer(header.main_entry_link.code_address, def);
+ named_labels = add_label(named_labels, "main_entry_link", header.main_entry_link.code_address);
+ for (int i = 0; i < header.n_modules; i++)
+ {
+ if (!reset || header.module_map_entries[i].code_address != header.user_boundary)
+ {
+ def = defer(header.module_map_entries[i].code_address, def);
+ }
+ named_labels = add_label(named_labels, header.module_map_entries[i].name.str, header.module_map_entries[i].code_address);
+ }
+ fseek(f, 0x1000, SEEK_SET);
+ filebuf = malloc(filesize - 0x1000);
+ if (fread(filebuf, 2, (filesize - 0x1000)/2, f) != (filesize - 0x1000)/2)
+ {
+ fprintf(stderr, "Failure while reading file %s\n", argv[1]);
+ }
+ fclose(f);
+ for(cur = filebuf; cur - filebuf < ((filesize - 0x1000)/2); ++cur)
+ {
+ *cur = (*cur >> 8) | (*cur << 8);
+ }
+ if (reset)
+ {
+ def = defer(filebuf[2] << 16 | filebuf[3], def);
+ named_labels = add_label(named_labels, "reset", filebuf[2] << 16 | filebuf[3]);
+ }
+ } else {
+ address_off = 0;
+ address_end = filesize;
+ filebuf = malloc(filesize);
+ if (fread(filebuf, 2, filesize/2, f) != filesize/2)
+ {
+ fprintf(stderr, "Failure while reading file %s\n", argv[1]);
+ }
+ fclose(f);
+ for(cur = filebuf; cur - filebuf < (filesize/2); ++cur)
+ {
+ *cur = (*cur >> 8) | (*cur << 8);
+ }
+ uint32_t start = filebuf[2] << 16 | filebuf[3];
+ uint32_t int_2 = filebuf[0x68/2] << 16 | filebuf[0x6A/2];
+ uint32_t int_4 = filebuf[0x70/2] << 16 | filebuf[0x72/2];
+ uint32_t int_6 = filebuf[0x78/2] << 16 | filebuf[0x7A/2];
+ named_labels = add_label(named_labels, "start", start);
+ named_labels = add_label(named_labels, "int_2", int_2);
+ named_labels = add_label(named_labels, "int_4", int_4);
+ named_labels = add_label(named_labels, "int_6", int_6);
+ if (!def || !only) {
+ def = defer(start, def);
+ def = defer(int_2, def);
+ def = defer(int_4, def);
+ def = defer(int_6, def);
+ }
}
- uint32_t start = filebuf[2] << 16 | filebuf[3], tmp_addr;
- uint32_t int_2 = filebuf[0x68/2] << 16 | filebuf[0x6A/2];
- uint32_t int_4 = filebuf[0x70/2] << 16 | filebuf[0x72/2];
- uint32_t int_6 = filebuf[0x78/2] << 16 | filebuf[0x7A/2];
uint16_t *encoded, *next;
- uint32_t size;
- if (!def || !only) {
- def = defer(start, def);
- def = defer(int_2, def);
- def = defer(int_4, def);
- def = defer(int_6, def);
- }
+ uint32_t size, tmp_addr;
uint32_t address;
while(def) {
do {
encoded = NULL;
address = def->address;
if (!is_visited(address)) {
- encoded = filebuf + address/2;
+ encoded = filebuf + (address - address_off)/2;
}
tmpd = def;
def = def->next;
@@ -158,7 +258,7 @@ int main(int argc, char ** argv)
break;
}
for(;;) {
- if (address > filesize) {
+ if (address > address_end || address < address_off) {
break;
}
visit(address);
@@ -175,7 +275,7 @@ int main(int argc, char ** argv)
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;
+ encoded = filebuf + (address - address_off)/2;
reference(address);
if (is_visited(address)) {
break;
@@ -188,13 +288,13 @@ int main(int argc, char ** argv)
} else if(instbuf.op == M68K_JMP) {
if (instbuf.src.addr_mode == MODE_ABSOLUTE || instbuf.src.addr_mode == MODE_ABSOLUTE_SHORT) {
address = instbuf.src.params.immed;
- encoded = filebuf + address/2;
+ encoded = filebuf + (address - address_off)/2;
if (is_visited(address)) {
break;
}
- } else if (instbuf.src.addr_mode = MODE_PC_DISPLACE) {
+ } else if (instbuf.src.addr_mode == MODE_PC_DISPLACE) {
address = instbuf.src.params.regs.displacement + instbuf.address + 2;
- encoded = filebuf + address/2;
+ encoded = filebuf + (address - address_off)/2;
if (is_visited(address)) {
break;
}
@@ -211,6 +311,11 @@ int main(int argc, char ** argv)
}
}
if (labels) {
+ for (address = 0; address < address_off; address++) {
+ if (is_label(address)) {
+ printf("ADR_%X equ $%X\n", address, address);
+ }
+ }
for (address = filesize; address < (16*1024*1024); address++) {
if (is_label(address)) {
printf("ADR_%X equ $%X\n", address, address);
@@ -218,25 +323,21 @@ int main(int argc, char ** argv)
}
puts("");
}
- for (address = 0; address < filesize; address+=2) {
+ for (address = address_off; address < address_end; address+=2) {
if (is_visited(address)) {
- encoded = filebuf + address/2;
+ encoded = filebuf + (address-address_off)/2;
m68k_decode(encoded, &instbuf, address);
if (labels) {
- m68k_disasm_labels(&instbuf, disbuf);
- if (address == start) {
- puts("start:");
- }
- if(address == int_2) {
- puts("int_2:");
- }
- if(address == int_4) {
- puts("int_4:");
- }
- if(address == int_6) {
- puts("int_6:");
- }
- if (is_label(instbuf.address)) {
+ m68k_disasm_labels(&instbuf, disbuf, label_fun, named_labels);
+ char keybuf[MAX_INT_KEY_SIZE];
+ label_names * names = tern_find_ptr(named_labels, tern_int_key(address, keybuf));
+ if (names)
+ {
+ for (int i = 0; i < names->num_labels; i++)
+ {
+ printf("%s:\n", names->labels[i]);
+ }
+ } else if (is_label(instbuf.address)) {
printf("ADR_%X:\n", instbuf.address);
}
if (addr) {