Mercurial > hg-old > index.cgi
changeset 409:cba03436c720
Checkpoint disassembler
author | lost@l-w.ca |
---|---|
date | Mon, 02 Aug 2010 18:07:04 -0600 |
parents | 2a94b2e64621 |
children | acaafc70044b |
files | lwdisasm/Makefile.am lwdisasm/do_raw.c lwdisasm/insn.c lwdisasm/instab.c lwdisasm/instab6309.c lwdisasm/lwdisasm.h lwdisasm/main.c lwdisasm/misc.c lwdisasm/range.c lwdisasm/symbol.c |
diffstat | 10 files changed, 1012 insertions(+), 16 deletions(-) [+] |
line wrap: on
line diff
--- a/lwdisasm/Makefile.am Mon Aug 02 13:24:07 2010 -0600 +++ b/lwdisasm/Makefile.am Mon Aug 02 18:07:04 2010 -0600 @@ -1,5 +1,5 @@ AM_CPPFLAGS = -I$(top_builddir)/lib -I$(top_srcdir)/lib -I$(top_builddir)/lwlib -I$(top_srcdir)/lwlib bin_PROGRAMS = lwdisasm -lwdisasm_SOURCES = main.c instab.c instab6309.c +lwdisasm_SOURCES = main.c instab.c instab6309.c range.c do_raw.c insn.c misc.c symbol.c lwdisasm_LDADD = -L$(top_builddir)/lib -L$(top_srcdir)/lib -L$(top_builddir)/lwlib -L$(top_srcdir)/lwlib -lgnu -llw EXTRA_DIST = lwdisasm.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwdisasm/do_raw.c Mon Aug 02 18:07:04 2010 -0600 @@ -0,0 +1,74 @@ +/* +do_raw.c + +Copyright © 2010 William Astle + +This file is part of LWTOOLS. + +LWTOOLS is free software: you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> + +#include "lwdisasm.h" + +void do_disasm_raw(disasmstate_t *as) +{ + linedata_t *l; + symbol_t *s; + char bytebuf[11]; + int i; + + // initialize disassembly + as -> curoff = as -> entry; + as -> crange = lookup_range(as, as -> curoff); + + + while (l = disasm_insn(as)) + { + if (!as -> ltail) + as -> lhead = l; + else + as -> ltail -> next = l; + l -> prev = as -> ltail; + as -> ltail = l; + + if (l -> target != -1) + { + s = register_symbol(as, l -> target, l -> sectionref, NULL); + l -> symbol = s; + } + } + + attach_symbols(as); + + for (l = as -> lhead; l; l = l -> next) + { + if (l -> target != -1) + redisasm_insn(as, l); + } + + for (l = as -> lhead; l; l = l -> next) + { + bytebuf[0] = 0; + for (i = 0; i < l -> length; i++) + { + sprintf(bytebuf, "%s%02X", bytebuf, l -> bytes[i]); + } + printf("%04X %-10s %-15s %s\n", l -> address, bytebuf, l -> isref ? l -> symbol -> symbol : "", l -> disasm); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwdisasm/insn.c Mon Aug 02 18:07:04 2010 -0600 @@ -0,0 +1,568 @@ +/* +insn.c + +Copyright © 2010 William Astle + +This file is part of LWTOOLS. + +LWTOOLS is free software: you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <lw_alloc.h> +#include <lw_string.h> + +#include "lwdisasm.h" + +/* +this function creates a linedata_t with the disassembly of the +current location; returns NULL if the current disassembly point +is not a valid instruction or we are at the end of the input +*/ + +#define fb(d) do { int ____t; ____t = fetch_byte(as); if (____t < 0) return NULL; bytes[len++] = ____t; (d) = ____t; } while (0) +#define fb2(d) do { int ____t; ____t = fetch_byte(as); if (____t < 0) return "?"; bytes[(*len)++] = ____t; (d) = ____t; } while (0) + +char *encode_target(disasmstate_t *as, int addr, int section) +{ + symbol_t *s; + static char buffer[256]; + + s = find_symbol(as, addr, section); + if (!s) + { + sprintf(buffer, "$%04X", addr); + return buffer; + } + else + { + return s -> symbol; + } +} + +char *decode_indexed(disasmstate_t *as, char *bytes, int *len, int *target, int section) +{ + int pb, b1, b2; + int rn; + static char *rs[] = { "x", "y", "u", "s", "pcr" }; + static char str[40]; + char *i1 = "", *i2 = ""; + char *tstr; + *target = -1; + + fb2(pb); + + rn = (pb >> 5) & 3; + + if (pb < 0x80) + { + // 5 bit + b1 = pb & 15; + if (pb & 16) + b1 = b1 - 16; + + sprintf(str, "%d,%s", b1, rs[rn]); + return str; + } + if ((pb & 0x1F) == 0x1F) + { + // extended indirect + fb2(b1); + fb2(b2); + sprintf(str, "[$%04X]", (b1 << 8) | b2); + return str; + } + + if (pb & 0x10) + { + i1 = "["; + i2 = "]"; + } + + switch (pb & 0x0F) + { + case 0: // ,r+ + if (*i1 == '[') + { + break; + } + sprintf(str, "%s,%s+%s", i1, rs[rn], i2); + return str; + + case 1: // ,r++ + sprintf(str, "%s,%s++%s", i1, rs[rn], i2); + return str; + + case 2: // ,-r + if (*i1 == '[') + { + break; + } + sprintf(str, "%s,-%s%s", i1, rs[rn], i2); + return str; + + case 3: // ,--r + sprintf(str, "%s,--%s%s", i1, rs[rn], i2); + return str; + + case 4: // ,r + sprintf(str, "%s,%s%s", i1, rs[rn], i2); + return str; + + case 5: // B,r + sprintf(str, "%sb,%s%s", i1, rs[rn], i2); + return str; + + case 6: // A,r + sprintf(str, "%sa,%s%s", i1, rs[rn], i2); + return str; + + case 8: // 8 bit,r + fb2(b1); + if (b1 > 128) + b1 -= 256; + sprintf(str, "%s<$%02X,%s%s", i1, b1, rs[rn], i2); + return str; + + case 9: // 16 bit,r + fb2(b1); + fb2(b2); + b1 = (b1 << 8) | b2; + if (b2 > 32768) + b2 -= 65536; + sprintf(str, "%s>$%04X,%s%s", i1, b1, rs[rn], i2); + return str; + + case 11: // D,r + sprintf(str, "%sd,%s%s", i1, rs[rn], i2); + return str; + + case 12: // 8 bit,PCR + fb2(b1); + if (b1 > 127) + b1 -= 256; + b1 += as -> curoff; + b1 &= 0xFFFF; + sprintf(str, "%s<%s,pcr%s", i1, encode_target(as, b1, section), i2); + *target = b1; + return str; + + case 13: // 16 bit,PCR + fb2(b1); + fb2(b2); + b1 = (b1 << 8) | b2; + b1 += as -> curoff; + b1 &= 0xFFFF; + sprintf(str, "%s>%s,pcr%s", i1, encode_target(as, b1, section), i2); + *target = b1; + return str; + } + + // if we got here, we have an illegal 6809 + if (as -> target == TARGET_6809) + { + sprintf(str, "?"); + return str; + } + + // now sort out 6309 operations + pb &= 0x1F; + + switch (pb) + { + case 0x07: + case 0x17: + // E,r + sprintf(str, "%se,%s%s", i1, rs[rn], i2); + return str; + + case 0x0A: + case 0x1A: + // F,r + sprintf(str, "%sf,%s%s", i1, rs[rn], i2); + return str; + + case 0x0E: + case 0x1E: + // W,r + sprintf(str, "%sw,%s%s", i1, rs[rn], i2); + return str; + + case 0x0F: + case 0x10: + // W indexing + switch (rn) + { + case 0: // ,W + sprintf(str, "%s,w%s", i1, i2); + return str; + + case 1: // 16 bit,W + fb2(b1); + fb2(b2); + b1 = (b1 << 8) | b2; + if (b1 > 32768) + b1 -= 65536; + sprintf(str, "%s>$%04X,w%s", i1, b1, i2); + return str; + + case 2: // ,W++ + sprintf(str, "%s,w++%s", i1, i2); + return str; + + case 3: // ,--W + sprintf(str, "%s,--w%s", i1, i2); + return str; + } + } + + sprintf(str, "?"); + return str; +} + +char *decode_operand(disasmstate_t *as, int addrmode, uint8_t *bytes, int *len, int *target, int section) +{ + int b1, b2, b3, b4; + static char insnbuffer[256]; + char *t; + static char *rlist3[] = { "D", "X", "Y", "U", "S", "PC", "W", "V", "A", "B", "CC", "DP", "0", "0", "E", "F" }; + static char *rlist8[] = { "D", "X", "Y", "U", "S", "PC", "?", "?", "A", "B", "CC", "DP", "?", "?", "?", "?" }; + char **rlist = (as -> target == TARGET_6809) ? rlist8 : rlist3; + + switch (addrmode) + { + case ADDR_IMM8: + fb2(b1); + sprintf(insnbuffer, "#$%02X", b1); + break; + + case ADDR_IMM16: + fb2(b1); + fb2(b2); + sprintf(insnbuffer, "#$%04X", (b1 << 8) | b2); + break; + + case ADDR_IMM32: + fb2(b1); + fb2(b2); + fb2(b3); + fb2(b4); + sprintf(insnbuffer, "#$%08X", (b1 << 24) | (b2 << 16) | (b3 << 8) | b4); + break; + + case ADDR_DIR: + fb2(b1); + sprintf(insnbuffer, "<%s", encode_target(as, (as -> dpval << 8) | b1, section)); + *target = as -> dpval * 256 + b1; + break; + + case ADDR_EXT: + fb2(b1); + fb2(b2); + sprintf(insnbuffer, ">%s", encode_target(as, (b1 << 8) | b2, section)); + *target = (b1 << 8) | b2; + break; + + case ADDR_INH: + *insnbuffer = 0; + break; + + case ADDR_IMM8DIR: + fb2(b1); + fb2(b2); + sprintf(insnbuffer, "#$%02X;<%s", b1, encode_target(as, (as -> dpval << 8) | b2, section)); + *target = (as -> dpval << 8) | b2; + break; + + case ADDR_IMM8EXT: + fb2(b1); + fb2(b2); + fb2(b3); + sprintf(insnbuffer, "#$%02X;>%s", b1, encode_target(as, (b2 << 8) | b3, section)); + *target = (b2 << 8) | b3; + break; + + case ADDR_IMM8IND: + fb2(b1); + t = decode_indexed(as, bytes, len, target, section); + sprintf(insnbuffer, "#$%02X;%s", b1, t); + break; + + case ADDR_IND: + t = decode_indexed(as, bytes, len, target, section); + sprintf(insnbuffer, "%s", t); + break; + + case ADDR_RTOR: + fb2(b1); + b2 = b1 & 0x0F; + b1 = b1 >> 4; + sprintf(insnbuffer, "%s,%s", rlist[b1], rlist[b2]); + break; + + case ADDR_BITBIT: + fb2(b1); + fb2(b2); + sprintf(insnbuffer, "%s,%d,%d;<%s", + (b1 >> 6 == 0) ? "CC" : ((b1 >> 6 == 1) ? "A" : ((b1 >> 6 == 2) ? "B" : "?")), + (b1 >> 3) & 7, b1 & 7, encode_target(as, (as -> dpval << 8) | b2, section)); + *target = (as -> dpval << 8) | b2; + break; + + case ADDR_PSHPULS: + insnbuffer[0] = 0; + fb2(b1); + if (b1 & 0x01) + { + strcat(insnbuffer, ",cc"); + } + if (b1 & 0x02) + { + strcat(insnbuffer, ",a"); + } + if (b1 & 0x04) + { + strcat(insnbuffer, ",b"); + } + if (b1 & 0x08) + { + strcat(insnbuffer, ",dp"); + } + if (b1 & 0x10) + { + strcat(insnbuffer, "x"); + } + if (b1 & 0x20) + { + strcat(insnbuffer, "y"); + } + if (b1 & 0x40) + { + strcat(insnbuffer, "u"); + } + if (b1 & 0x80) + { + strcat(insnbuffer, "pc"); + } + return insnbuffer + 1; + break; + + case ADDR_PSHPULU: + insnbuffer[0] = 0; + fb2(b1); + if (b1 & 0x01) + { + strcat(insnbuffer, ",cc"); + } + if (b1 & 0x02) + { + strcat(insnbuffer, ",a"); + } + if (b1 & 0x04) + { + strcat(insnbuffer, ",b"); + } + if (b1 & 0x08) + { + strcat(insnbuffer, ",dp"); + } + if (b1 & 0x10) + { + strcat(insnbuffer, "x"); + } + if (b1 & 0x20) + { + strcat(insnbuffer, "y"); + } + if (b1 & 0x40) + { + strcat(insnbuffer, "s"); + } + if (b1 & 0x80) + { + strcat(insnbuffer, "pc"); + } + return insnbuffer + 1; + + case ADDR_REL8: + fb2(b1); + if (b1 > 127) + b1 -= 256; + b1 += as -> curoff; + b1 &= 0xFFFF; + sprintf(insnbuffer, "%s", encode_target(as, b1, section)); + *target = b1; + break; + + case ADDR_REL16: + fb2(b1); + if (b1 > 32767) + b1 -= 65536; + b1 += as -> curoff; + b1 &= 0xFFFF; + sprintf(insnbuffer, "%s", encode_target(as, b1, section)); + *target = b2; + break; + + case ADDR_TFMPP: + fb2(b1); + b2 = b1 & 0x0F; + b1 >>= 4; + sprintf(insnbuffer, "%s+,%s+", rlist[b1], rlist[b2]); + break; + + case ADDR_TFMMM: + fb2(b1); + b2 = b1 & 0x0F; + b1 >>= 4; + sprintf(insnbuffer, "%s-,%s-", rlist[b1], rlist[b2]); + break; + + case ADDR_TFMPC: + fb2(b1); + b2 = b1 & 0x0F; + b1 >>= 4; + sprintf(insnbuffer, "%s+,%s", rlist[b1], rlist[b2]); + break; + + case ADDR_TFMCP: + fb2(b1); + b2 = b1 & 0x0F; + b1 >>= 4; + sprintf(insnbuffer, "%s,%s+", rlist[b1], rlist[b2]); + break; + + default: + sprintf(insnbuffer, "????"); + break; + } + + return insnbuffer; +} + +linedata_t *disasm_insn(disasmstate_t *as) +{ + int curbyte; + int b1; + linedata_t *l; + char *opcode; + int addrmode; + char insnbuffer[256]; + char *t; + int addr; + int len = 0; + int8_t bytes[10]; + int target = -1; + + addr = as -> curoff; + + fb(curbyte); + if (curbyte < 0) + return NULL; + + opcode = as->page0[curbyte].op; + addrmode = as->page0[curbyte].addrmode; + + if (addrmode == ADDR_PAGE1) + { + fb(b1); + if (b1 < 0) + return NULL; + opcode = as->page1[b1].op; + addrmode = as->page1[b1].addrmode; + curbyte = (curbyte << 8) | b1; + } + else if (addrmode == ADDR_PAGE2) + { + fb(b1); + if (b1 < 0) + return NULL; + opcode = as->page2[b1].op; + addrmode = as->page2[b1].addrmode; + curbyte = (curbyte << 8) | b1; + } + + if (opcode == NULL) + return NULL; + + t = decode_operand(as, addrmode, bytes, &len, &target, 0); + + if (!t) + return NULL; + + // now create the line structure + l = lw_alloc(sizeof(linedata_t)); + l -> next = NULL; + l -> prev = NULL; + l -> address = addr; + l -> type = type_code; + l -> length = len; + l -> bytes = lw_alloc(len); + memmove(l -> bytes, bytes, len); + l -> isref = 0; + l -> symbol = NULL; + l -> sectionref = 0; + sprintf(insnbuffer, "%s %s", opcode, t); + l -> disasm = lw_strdup(insnbuffer); + l -> target = target; + return l; +} + +void redisasm_insn(disasmstate_t *as, linedata_t *l) +{ + char *opcode; + int addrmode; + int len = 0; + char bytes[15]; + int target = -1; + char *t; + char insnbuf[256]; + int ta; + int ts; + + // short circuit if no target in this one + if (l -> target == -1) + return; + + opcode = as -> page0[l -> bytes[0]].op; + addrmode = as -> page0[l -> bytes[0]].addrmode; + + ta = as -> curoff; + as -> curoff = l -> address + 1; + + if (addrmode == ADDR_PAGE1) + { + opcode = as -> page1[l -> bytes[1]].op; + addrmode = as -> page1[l -> bytes[1]].addrmode; + as -> curoff++; + } + else if (addrmode == ADDR_PAGE2) + { + opcode = as -> page2[l -> bytes[1]].op; + addrmode = as -> page2[l -> bytes[1]].addrmode; + as -> curoff++; + } + + t = decode_operand(as, addrmode, bytes, &len, &target, l -> sectionref); + + // now create the line structure + lw_free(l -> disasm); + sprintf(insnbuf, "%s %s", opcode, t); + l -> disasm = lw_strdup(insnbuf); +}
--- a/lwdisasm/instab.c Mon Aug 02 13:24:07 2010 -0600 +++ b/lwdisasm/instab.c Mon Aug 02 18:07:04 2010 -0600 @@ -88,10 +88,10 @@ { "leay", ADDR_IND }, { "leas", ADDR_IND }, { "leau", ADDR_IND }, - { "pshs", ADDR_PSHPUL }, - { "puls", ADDR_PSHPUL }, - { "pshu", ADDR_PSHPUL }, - { "pulu", ADDR_PSHPUL }, + { "pshs", ADDR_PSHPULS }, + { "puls", ADDR_PSHPULS }, + { "pshu", ADDR_PSHPULU }, + { "pulu", ADDR_PSHPULU }, { NULL }, { "rts", ADDR_INH }, { "abx", ADDR_INH },
--- a/lwdisasm/instab6309.c Mon Aug 02 13:24:07 2010 -0600 +++ b/lwdisasm/instab6309.c Mon Aug 02 18:07:04 2010 -0600 @@ -88,10 +88,10 @@ { "leay", ADDR_IND }, { "leas", ADDR_IND }, { "leau", ADDR_IND }, - { "pshs", ADDR_PSHPUL }, - { "puls", ADDR_PSHPUL }, - { "pshu", ADDR_PSHPUL }, - { "pulu", ADDR_PSHPUL }, + { "pshs", ADDR_PSHPULS }, + { "puls", ADDR_PSHPULS }, + { "pshu", ADDR_PSHPULU }, + { "pulu", ADDR_PSHPULU }, { NULL }, { "rts", ADDR_INH }, { "abx", ADDR_INH },
--- a/lwdisasm/lwdisasm.h Mon Aug 02 13:24:07 2010 -0600 +++ b/lwdisasm/lwdisasm.h Mon Aug 02 18:07:04 2010 -0600 @@ -48,7 +48,8 @@ ADDR_IMM32, ADDR_INH, ADDR_RTOR, - ADDR_PSHPUL, + ADDR_PSHPULS, + ADDR_PSHPULU, ADDR_IMM8DIR, ADDR_IMM8IND, ADDR_IMM8EXT, @@ -63,6 +64,47 @@ ADDR_TFMCP }; + +typedef struct rangedata_s rangedata_t; +struct rangedata_s +{ + int min; + int max; + int type; + rangedata_t *next; + rangedata_t *prev; +}; + +typedef struct symbol_s symbol_t; +struct symbol_s +{ + int address; + int section; + char *symbol; + symbol_t *next; +}; + +typedef struct linedata_s linedata_t; +struct linedata_s +{ + int address; + int sectionref; + int length; + int type; + int target; + char *disasm; + uint8_t *bytes; + int isref; + symbol_t *symbol; + linedata_t *next; + linedata_t *prev; +}; +typedef struct instab_s +{ + char *op; // mneumonic + int addrmode; // addressing mode +} instab_t; + typedef struct disasmstate_s { int input_type; @@ -74,16 +116,24 @@ long filelen; // length of the file data int base; // base address (raw) int entry; // entry address + int dpval; // DP value + linedata_t *lhead; // start of lines table + linedata_t *ltail; // end of lines table + rangedata_t *rhead; // start of range table + rangedata_t *rtail; // end of range table + + instab_t *page0; // instruction table 0 + instab_t *page1; // instruction table 1 + instab_t *page2; // instruction table 2 + + int curoff; // current disassembly point + rangedata_t *crange; // current range + + symbol_t *symbols; // symbol tables } disasmstate_t; -typedef struct instab_s -{ - char *op; // mneumonic - int addrmode; // addressing mode -} instab_t; - extern instab_t page0_6809[]; extern instab_t page1_6809[]; extern instab_t page2_6809[]; @@ -92,4 +142,18 @@ extern instab_t page1_6309[]; extern instab_t page2_6309[]; +enum +{ + type_code = 0, + type_data = 1 +}; + +extern void register_range(disasmstate_t *as, int min, int max, int type); +extern rangedata_t *lookup_range(disasmstate_t *as, int addr); +extern int fetch_byte(disasmstate_t *as); +extern linedata_t *disasm_insn(disasmstate_t *as); +extern symbol_t *register_symbol(disasmstate_t *as, int addr, int section, char *symbol); +extern void attach_symbols(disasmstate_t *as); +extern void redisasm_insn(disasmstate_t *as, linedata_t *l); +extern symbol_t *find_symbol(disasmstate_t *as, int addr, int section); #endif // ____lwdisasm_h_seen____
--- a/lwdisasm/main.c Mon Aug 02 13:24:07 2010 -0600 +++ b/lwdisasm/main.c Mon Aug 02 18:07:04 2010 -0600 @@ -76,6 +76,7 @@ exit(1); } // register the range as data + register_range(as, rangelow, rangehigh, type_data); break; case 0x102: // code range @@ -92,6 +93,7 @@ exit(1); } // register the range as code + register_range(as, rangelow, rangehigh, type_code); break; case 0x103: // entry @@ -182,6 +184,8 @@ disassembler on the first file */ +void do_disasm_raw(disasmstate_t *as); + int main(int argc, char **argv) { disasmstate_t as = { 0 }; @@ -215,5 +219,38 @@ fclose(fp); + switch (as.target) + { + case TARGET_6309: + as.page0 = page0_6309; + as.page1 = page1_6309; + as.page2 = page2_6309; + break; + + case TARGET_6809: + as.page0 = page0_6809; + as.page1 = page1_6809; + as.page2 = page2_6809; + break; + + default: + as.page0 = page0_6809; + as.page1 = page1_6809; + as.page2 = page2_6809; + break; + + } + + switch (as.input_type) + { + case INPUT_RAW: + do_disasm_raw(&as); + break; + + default: + fprintf(stderr, "Input type is not currently implemented\n"); + exit(1); + } + exit(0); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwdisasm/misc.c Mon Aug 02 18:07:04 2010 -0600 @@ -0,0 +1,36 @@ +/* +misc.c + +Copyright © 2010 William Astle + +This file is part of LWTOOLS. + +LWTOOLS is free software: you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <config.h> + +#include <stdlib.h> + +#include "lwdisasm.h" + +/* add support for misc fetchers here */ +/* return -1 if no more input */ +int fetch_byte(disasmstate_t *as) +{ + if (as -> curoff == as -> filelen) + return -1; + + return as -> filedata[as -> curoff++]; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwdisasm/range.c Mon Aug 02 18:07:04 2010 -0600 @@ -0,0 +1,124 @@ +/* +range.c + +Copyright © 2010 William Astle + +This file is part of LWTOOLS. + +LWTOOLS is free software: you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <config.h> + +#include <stdlib.h> + +#include <lw_alloc.h> + +#include "lwdisasm.h" + +void register_range(disasmstate_t *as, int min, int max, int type) +{ + rangedata_t *nr; + rangedata_t *r; + + // first remove any complete subsets of the new range +subsetagain: + for (r = as -> rhead; r; r = r -> next) + { + // if we haven't run into an existing range yet, short circuit + if (r -> min >= min && r -> max <= max) + { + if (r -> prev) + r -> prev -> next = r -> next; + else + as -> rhead = r -> next; + if (r -> next) + r -> next -> prev = r -> prev; + else + as -> rtail = r -> prev; + goto subsetagain; + } + } + + // now shorten any subset that overlaps below or overlaps above + for (r = as -> rhead; r; r = r -> next) + { + // are we a subset of this range? + if (r -> min <= min && r -> max >= max) + { + // proper subset; split + nr = lw_alloc(sizeof(rangedata_t)); + *nr = *r; + r -> next = nr; + nr -> prev = r; + r -> max = min - 1; + nr -> min = max + 1; + break; + } + // overlap above us + if (r -> max > max && r -> min < max) + { + r -> min = max + 1; + } + // overlap on the bottom + if (r -> min < min && r -> max > min) + { + r -> max = min - 1; + } + } + + // now add new range + for (r = as -> rhead; r; r = r -> next) + { + if (r -> min < max) + { + break; + } + } + + nr = lw_alloc(sizeof(rangedata_t)); + nr -> min = min; + nr -> max = max; + nr -> type = type; + + if (r) + { + if (r -> prev) + r -> prev -> next = nr; + else + as -> rhead = nr; + nr -> prev = r -> prev; + nr -> next = r; + r -> prev = nr; + } + else + { + nr -> next = NULL; + nr -> prev = as -> rtail; + as -> rtail -> next = nr; + as -> rtail = nr; + } +} + +rangedata_t *lookup_range(disasmstate_t *as, int addr) +{ + rangedata_t *r; + + for (r = as -> rhead; r; r = r -> next) + { + if (r -> min <= addr && r -> max >= addr) + return r; + } + return NULL; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lwdisasm/symbol.c Mon Aug 02 18:07:04 2010 -0600 @@ -0,0 +1,93 @@ +/* +symbol.c + +Copyright © 2010 William Astle + +This file is part of LWTOOLS. + +LWTOOLS is free software: you can redistribute it and/or modify it under the +terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <config.h> + +#include <stdio.h> + +#include <lw_alloc.h> +#include <lw_string.h> + +#include "lwdisasm.h" + +symbol_t *find_symbol(disasmstate_t *as, int addr, int section) +{ + symbol_t *s; + + for (s = as -> symbols; s; s = s -> next) + { + if (s -> address == addr && s -> section == section) + return s; + } + return NULL; +} + +symbol_t *register_symbol(disasmstate_t *as, int addr, int section, char *symbol) +{ + char symbuf[200]; + symbol_t *s; + + for (s = as -> symbols; s; s = s -> next) + { + if (s -> address == addr && s -> section == section) + return s; + } + + if (!symbol) + { + if (section) + { + sprintf(symbuf, "L%d_%04X", section, addr); + } + else + { + sprintf(symbuf, "L%04X", addr); + } + symbol = symbuf; + } + + s = lw_alloc(sizeof(symbol_t)); + s -> symbol = lw_strdup(symbol); + s -> address = addr; + s -> section = section; + s -> next = as -> symbols; + as -> symbols = s; + return s; +} + +void attach_symbols(disasmstate_t *as) +{ + symbol_t *s; + linedata_t *l; + + for (s = as -> symbols; s; s = s -> next) + { + for (l = as -> lhead; l; l = l -> next) + { + if (l -> isref == 0 && l -> address == s -> address && l -> sectionref == s -> section) + { + l -> symbol = s; + l -> isref = 1; + break; + } + } + } +}