From cf44f20b548377927001084ff52add413899d31e Mon Sep 17 00:00:00 2001 From: Eric Smith Date: Thu, 27 Apr 2000 23:29:28 +0000 Subject: [PATCH] Initial revision --- Makefile | 42 ++++ README.Finkelstein | 49 +++++ dis.h | 103 +++++++++ dis6502.1 | 63 ++++++ initopts.c | 95 ++++++++ lex.l | 68 ++++++ main.c | 528 +++++++++++++++++++++++++++++++++++++++++++++ print.c | 295 +++++++++++++++++++++++++ ref.c | 90 ++++++++ tbl.c | 260 ++++++++++++++++++++++ 10 files changed, 1593 insertions(+) create mode 100644 Makefile create mode 100644 README.Finkelstein create mode 100644 dis.h create mode 100644 dis6502.1 create mode 100644 initopts.c create mode 100644 lex.l create mode 100644 main.c create mode 100644 print.c create mode 100644 ref.c create mode 100644 tbl.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..618e0c2 --- /dev/null +++ b/Makefile @@ -0,0 +1,42 @@ +OBJS = main.o initopts.o lex.o ref.o print.o tbl.o +SRCS = dis.h main.c initopts.c lex.l ref.c print.c tbl.c +CFLAGS = -g + +dis: $(OBJS) + cc $(OBJS) -o dis + +tbl.o: dis.h tbl.c + cc -c tbl.c + +initopts.o: dis.h initopts.c + +main.o: dis.h main.c + +lex.o: lex.c + +lex.c: dis.h lex.l + +ref.o: dis.h ref.c + +print.o: dis.h print.c + +dis.man: dis.1 + nroff -man dis.1 > dis.man + +install: dis + cp dis /a/rgb/bin/dis6502 + +clean: + rm -f $(OBJS) lex.c dis.man + +clobber: clean + rm -f dis + +ckpt: $(SRCS) + ci -l $(SRCS) + +lint: dis.h main.c initopts.c lex.c ref.c print.c tbl.c + lint dis.h main.c initopts.c lex.c ref.c print.c tbl.c + +shar: Makefile dis.1 $(SRCS) + shar -f shar Makefile dis.1 $(SRCS) diff --git a/README.Finkelstein b/README.Finkelstein new file mode 100644 index 0000000..756c03f --- /dev/null +++ b/README.Finkelstein @@ -0,0 +1,49 @@ + + + + Some notes about Robert Bond's 'dis' program, Amiga version. + + + +This is a quick & dirty port of a 6502 reverse assembler I that I had under +my hand for a long time. I didn't bother optimizing the stuff too much, I +just wanted to see it working. This is the sort of 'dirty' ports where you +first compiler the original file, then watch the compiler errors, and fix +the errors in the file, without looking anywhere else in it. Therefor: + +1) 'dis' requires C:Sort ( too much bother to replace ) & C:Type ( I AM + lazy!!!) + +2) I still don't understand why are the line numbers needed in the + c64.predef file. I don't have much UNIX experience, and no experience at + all with lex. lex code is like chinese to me, but reading the perdef + I think that the line numbers are ignored and are used only to easily + identify '.eq' lines. + +3) The program is recursive, too much recursive! the trace routine calls + itself not only on branches, but every instruction! large stacks ( even + 50K isn't too much for large programs ), are welcomed... I will modify + this as soon as I'll have time. it should be easy to remove recursion in + the non branch/jmp instructions. branches must have recursion. + +I also enhanced the original package, and added support for c64 binary file, +which wasn't there before. ( It had only ATARI load/boot files ). The C64 +file format was much simpler than those other 2 formats. To select C64 file +format, use the '-c' flag. I also included a c64.predefs file with some C64 +constant addresses. Also, FYI, lex.c was generated on a SUN from lex.l and +then downloaded to the Amiga. lex.c was also __edited__ before compilation. +I know that it's a no-no to edit machine-generated files, but it was +necessary. + + +Udi Finkelstein + +10 Glitzenstein st. +Tel Aviv 64686 Israel +Phone: 972-3-263-927 + +BITNET: finkel@taurus.BITNET ( Best ) +UUCP: ...!uunet!ulysses!attibr!althea!finkel ( Try avoiding this ) +ARPA: finkel%taurus@cunyvm.cuny.edu ( Same as BITNET ) +FIDO: Udi Finkelstein ( At 2:40/117 or 2:40/135 + If you can get there at all!) diff --git a/dis.h b/dis.h new file mode 100644 index 0000000..4a4a2ee --- /dev/null +++ b/dis.h @@ -0,0 +1,103 @@ +#include + +#define NPREDEF 10 + +extern char *predef[]; +extern int npredef; +extern char *file; +extern char *progname; + +extern int bopt; +enum boot_mode { UNKNOWN, RAW_BINARY, ATARI_LOAD, C64_LOAD, ATARI_BOOT }; +extern int base_address, vector_address; + +extern int asmout; +#ifndef AMIGA +extern unsigned char f[]; +extern unsigned char d[]; +#else +extern unsigned char *d,*f; +#endif + +#define getword(x) (d[x] + (d[x+1] << 8)) +#define getbyte(x) (d[x]) + +/* f bits */ + +#define LOADED 1 /* Location loaded */ +#define JREF 2 /* Referenced as jump/branch dest */ +#define DREF 4 /* Referenced as data */ +#define SREF 8 /* Referenced as subroutine dest */ +#define NAMED 0x10 /* Has a name */ +#define TDONE 0x20 /* Has been traced */ +#define ISOP 0x40 /* Is a valid instruction opcode */ + +struct info { + char opn[4]; + int nb; + int flag; +}; + +extern struct info optbl[]; + +/* Flags */ + +/* Where control goes */ + +#define NORM 1 +#define JUMP 2 +#define FORK 4 +#define STOP 8 + +#define CTLMASK (NORM|JUMP|FORK|STOP) + +/* Instruction format */ + +#define IMM 0x20 +#define ABS 0x40 +#define ACC 0x80 +#define IMP 0x100 +#define INX 0x200 +#define INY 0x400 +#define ZPX 0x800 +#define ABX 0x1000 +#define ABY 0x2000 +#define REL 0x4000 +#define IND 0x8000 +#define ZPY 0x10000 +#define ZPG 0x20000 +#define ILL 0x40000 + +#define ADRMASK (IMM|ABS|ACC|IMP|INX|INY|ZPX|ABX|ABY|REL|IND|ZPY|ZPG|ILL) + +struct ref_chain { + struct ref_chain *next; + int who; +}; + +struct ref_chain *get_ref(); +char *get_name(); + +/* lex junk */ + +#define EQ 256 +#define NUMBER 257 +#define NAME 258 +#define COMMENT 259 +#define LI 260 +#define TSTART 261 +#define TSTOP 262 +#define TRTSTAB 263 + +extern FILE *yyin, *yyout; +int lineno; + +int yywrap(), yyerror(); +char *emalloc(); + +typedef union { + int ival; + char *sval; +} VALUE; + +extern VALUE token; diff --git a/dis6502.1 b/dis6502.1 new file mode 100644 index 0000000..7887cbb --- /dev/null +++ b/dis6502.1 @@ -0,0 +1,63 @@ +.TH DIS6502 1 "1 OCT 1986" +.UC 4 +.SH NAME +dis6502 \- Disassemble 6502 object code +.SH SYNOPSIS +.I dis6502 +[ +.I \-b +] +[ +.I -p \fIpfile\fP +] +.I file +.LP +.SH DESCRIPTION +.I Dis6502 +disassembles 6502 binary files. Binary formats understood include +Atari binary files (L menu command) and boot files. +Equate and control files can be included via the +.I -p +option to name well known locations and to control the disassembly +process. The output includes a cross reference. +.PP +The disassembly process is a two pass operation: First the program +flow is traced starting with the init and run parameters in the file +headers. The dump routine then prints out the information. +.PP +The command line options are: +.TP +.I \-b +Assume that the file is a boot file, not a load file. +.TP +.I \-p \fIpfile\fP +Read in the predefine file \fIpfile\fP. +Up to 20 \fI-p\fP options may be included. +.PP +Lines in pfile consist of: +.PP + lineno name .eq number +.PP + .stop number +.PP + .trace number +.PP +.I Lineno +refers to a decimal number. +.I Number +may be a decimal number or +may be a hexadecimal number (the first character of the number +should be "$"). For example, "$21b5" is +the hexadecimal number 21b5. +.I Name +is a sequence of numbers and characters starting with a +letter. +.I .trace +causes +the trace process to continue at the address given. +.I .stop +causes the +trace process to stop at the address given. +.SH AUTHOR +Robert Bond +.SH BUGS diff --git a/initopts.c b/initopts.c new file mode 100644 index 0000000..9aa20e7 --- /dev/null +++ b/initopts.c @@ -0,0 +1,95 @@ + +/* + * + * dis [-p predefineds] file + * + * The -p option may be repeated. + */ + +#include "dis.h" + +char *predef[NPREDEF]; +int npredef = 0; +char *file; +char *progname = "dis"; +int bopt = UNKNOWN; +int base_address = 0; +int vector_address = 0x10000; +int asmout = 0; + +void usage (void) +{ + fprintf (stderr, "Usage: %s \n" + " format: -r
raw binary file\n" + " -b Atari boot format\n" + " -l Atari load format\n" + " -c Commodore 64\n" + " options: -a assembly output\n" + " -p predefs\n" + " -v
alternate vector address", + progname); + exit (1); +} + +initopts(argc,argv) +int argc; +char *argv[]; +{ + int ai; + char *ca; + char *p; + int fileset = 0; + + progname = argv[0]; + + while (--argc) + { + if ((*++argv)[0] == '-') + { + ca = *argv; + for(ai = 1; ca[ai] != '\0'; ai++) + switch (ca[ai]) + { + case 'a': + asmout = 1; + break; + case 'p': + predef[npredef] = *++argv; + npredef++; + argc--; + break; + case 'r': + base_address = strtoul (*++argv, &p, 0); + if (*p) + crash ("base address must be specified"); + bopt = RAW_BINARY; + argc--; + break; + case 'v': + vector_address = strtoul (*++argv, &p, 0); + if (*p) + crash ("address required"); + argc--; + break; + case 'l': + bopt = ATARI_LOAD; + break; + case 'c': + bopt = C64_LOAD; + break; + case 'b': + bopt = ATARI_BOOT; + break; + default: crash("Invalid option letter"); + } + } + else if (!fileset) + { + file = *argv; + fileset++; + } + else usage (); + } + if (!fileset) + usage (); +} diff --git a/lex.l b/lex.l new file mode 100644 index 0000000..1e550d0 --- /dev/null +++ b/lex.l @@ -0,0 +1,68 @@ +%{ +#undef ECHO +#include "dis.h" +int lineno = 0; +char *strcpy(); +%} + +digit [0-9] +hexdigit [0-9a-fA-F] +alpha [a-zA-Z] +alphanum [0-9a-zA-Z_] + +%% + +[ \t] { ; } + +[\n] { lineno++; return '\n'; } + +\.[Ee][Qq][Uu] { return EQ; } + +\.[Ee][Qq] { return EQ; } + +\.[Ll][Ii] { return LI; } + +\.[Tt][Rr][Aa][Cc][Ee] { return TSTART; } + +\.[Ss][Tt][Oo][Pp] { return TSTOP; } + +\.[Rr][Tt][Ss][Tt][Aa][Bb] { return TRTSTAB; } + +{digit}+ { + (void)sscanf(yytext, "%d", &token.ival); + return NUMBER; + } + +\${hexdigit}+ { + (void)sscanf(yytext+1, "%x", &token.ival); + return NUMBER; + } + +{alpha}{alphanum}* { + token.sval = emalloc((unsigned) strlen(yytext)+1); + (void)strcpy((char *)token.sval, (char *)yytext); + return NAME; + } +\*.* { + return COMMENT; + } +\;.* { + return COMMENT; + } + +. { return yytext[0]; } + +%% + +char * +emalloc(n) +unsigned n; +{ + char *ptr, *malloc(); + + if ((ptr = malloc(n)) == (char *) 0) { + (void) fprintf(stderr,"out of core"); + exit(1); + } + return ptr; +} diff --git a/main.c b/main.c new file mode 100644 index 0000000..6b79fde --- /dev/null +++ b/main.c @@ -0,0 +1,528 @@ +#include "dis.h" + +#define NTSTART 500 + +char *cur_file = NULL; /* the file thats open */ +int pre_index = 0; + +int tstart[NTSTART]; /* .trace directive keep locations */ +int tstarti = 0; + +#define RTSTAB 50 + +int rtstab_addr [RTSTAB]; /* .rtstab directive */ +int rtstab_size [RTSTAB]; +int rtstab_count = 0; + +VALUE token; + +#ifdef AMIGA +unsigned char *d,*f; /* Manx has a bug preventing us from declaring arrays >64K */ +extern unsigned char *calloc(); +#else +unsigned char d[0x10000]; /* The data */ +unsigned char f[0x10000]; /* Flags for memory usage */ +#endif + +#define RUNLOC 0x2e0 +#define INITLOC 0x2e2 + + +void do_ptrace (void) +{ + int i; + for (i = 0; i 0) { + cur_file = predef[0]; + pre_index++; + yyin = fopen(cur_file, "r"); + if (!yyin) + crash ("Cant open predefine file"); + get_predef(); + } + + switch (bopt) + { + case RAW_BINARY: + binaryloadfile(); + break; + case ATARI_LOAD: + loadfile(); + break; + case C64_LOAD: + c64loadfile(); + break; + case ATARI_BOOT: + loadboot(); + break; + default: + crash ("file format must be specified"); + } + + do_ptrace (); + do_rtstab (); + + dumpitout(); + +#ifdef AMIGA +free(d); +free(f); +#endif + + exit(0); +} + + + + + + +crash(p) +char *p; +{ + fprintf(stderr, "%s: %s\n", progname, p); + if (cur_file != NULL) + fprintf(stderr, "Line %d of %s\n", lineno+1, cur_file); +#ifdef AMIGA +free(d); +free(f); +#endif + exit(1); +} + +get_predef() +{ + int loc; + int size; + char *name; + + for(;;) + switch (yylex()) { + case '\n': + break; + case COMMENT: + break; + case 0: + return; + case TRTSTAB: + if (yylex() != NUMBER) + crash(".rtstab needs an address operand"); + loc = token.ival; + if (loc > 0x10000 || loc < 0) + crash("Number out of range"); + if (yylex() != ',') + crash(".rtstab needs a comma"); + if (yylex() != NUMBER) + crash(".rtstab needs a comma"); + size = token.ival; + rtstab_addr [rtstab_count] = loc; + rtstab_size [rtstab_count++] = size; + break; + case TSTART: + if (yylex() != NUMBER) + crash(".trace needs a number operand"); + loc = token.ival; + if (loc > 0x10000 || loc < 0) + crash("Number out of range"); + if (tstarti == NTSTART) + crash("Too many .trace directives"); + tstart[tstarti++] = loc; + while (yylex() != '\n') + ; + break; + case TSTOP: + if (yylex() != NUMBER) + crash(".stop needs a number operand"); + loc = token.ival; + if (loc > 0x10000 || loc < 0) + crash("Number out of range"); + f[loc] |= TDONE; + while (yylex() != '\n') + ; + break; + case NUMBER: + switch (yylex()) { + case LI: + case COMMENT: + while (yylex() != '\n') + ; + break; + case '\n': + break; + case NAME: + name = token.sval; + if (yylex() != EQ) + crash("Only EQ and LI supported in defines file"); + if (yylex() != NUMBER) + crash("EQ operand must be a number"); + loc = token.ival; + if (loc > 0x10000 || loc < 0) + crash("Number out of range"); + f[loc] |= NAMED; + save_name(loc, name); + while (yylex() != '\n') + ; + break; + default: + crash("Invalid line in predef file"); + } + break; + default: + crash("Invalid line in predef file"); + } +} + +loadboot() +{ + struct boot_hdr { + unsigned char flags; + unsigned char nsec; + unsigned char base_low; + unsigned char base_hi; + unsigned char init_low; + unsigned char init_hi; + } bh; + + FILE *fp; + int base_addr; + register int i; + int len; + + fp = fopen(file, "r"); + cur_file = NULL; + if (!fp) { + fprintf(stderr, "Cant open %s\n", file); + +#ifdef AMIGA +free(d); +free(f); +#endif + + exit(1); + } + + if(fread((char *)&bh, sizeof(bh), 1, fp) != 1) + crash("Input too short"); + + base_addr = bh.base_low + (bh.base_hi << 8); + len = bh.nsec * 128; + rewind(fp); + if (fread((char *)&d[base_addr], 1, len, fp) != len) + crash("input too short"); + + for(i = base_addr; len > 0; len--) + f[i++] |= LOADED; + + start_trace(base_addr+6, "**BOOT**"); +} + + +loadfile() +{ + FILE *fp; + int base_addr; + int last_addr; + register int i; + int had_header; + int tmp; + + had_header = 0; + fp = fopen(file, "r"); + cur_file = NULL; + if (!fp) { + fprintf(stderr, "Cant open %s\n", file); + +#ifdef AMIGA +free(d); +free(f); +#endif + + exit(1); + } + for(;;) { + + i = getc(fp); + + if (i == EOF) { + if (f[RUNLOC] & LOADED & f[RUNLOC+1]) { + i = getword(RUNLOC); + start_trace(i, "**RUN**"); + } + return; + } + + i = i | (getc(fp) << 8); + if (i == 0xffff) { + had_header = 1; + base_addr = getc(fp); + base_addr = base_addr | (getc(fp) << 8); + if (base_addr < 0 || base_addr > 0xffff) + crash("Invalid base addr in input file"); + } else { + if (!had_header) + crash("Invalid header in input file"); + base_addr = i; + } + + last_addr = getc(fp); + last_addr = last_addr | (getc(fp) << 8); + if (last_addr < base_addr || last_addr > 0xffff) + crash("Invalid length in input file"); + + printf("Load: %4x -> %4x\n", base_addr, last_addr); + for(i = base_addr; i <= last_addr; i++) { + tmp = getc(fp); + if (tmp == EOF) + crash("File too small"); + d[i] = tmp; + f[i] |= LOADED; + } + + if (f[INITLOC] & LOADED & f[INITLOC+1]) { + i = getword(INITLOC); + start_trace(i, "**INIT**"); + } + + f[INITLOC] &= ~LOADED; + f[INITLOC+1] &= ~LOADED; + } + +} + + +c64loadfile() +{ + FILE *fp; + unsigned int base_addr,i; + int c; + + fp = fopen(file, "r"); + cur_file = NULL; + if (!fp) { + fprintf(stderr, "Cant open %s\n", file); + +#ifdef AMIGA + free(d); + free(f); +#endif + + exit(1); + } + + base_addr = getc(fp); + i = ( base_addr += ( (unsigned int)getc(fp) << 8 ) ); + + while( (c = getc(fp)) != EOF) { + d[i] = c; + f[i++] |= LOADED; + } + + start_trace(base_addr, "**C64BIN**"); +} + + +binaryloadfile() +{ + FILE *fp; + unsigned int i; + int c; + unsigned int reset, irq, nmi; + + fp = fopen (file, "r"); + + cur_file = NULL; + + if (!fp) + { + fprintf (stderr, "Can't open %s\n", file); + exit (1); + } + + i = base_address; + + while ((c = getc(fp)) != EOF) + { + d [i] = c; + f [i++] |= LOADED; + } + + reset = vector_address - 4; + irq = vector_address - 2; + nmi = vector_address - 6; + + fprintf (stderr, "base: %04x reset: %04x irq: %04x nmi: %04x\n", base_address, reset, irq, nmi); + + start_trace ((d [reset+1] << 8) | d [reset], "RESET"); + start_trace ((d [irq +1] << 8) | d [irq ], "IRQ"); + start_trace ((d [nmi +1] << 8) | d [nmi ], "NMI"); +} + +start_trace(loc, name) +unsigned int loc; +char *name; +{ + fprintf(stderr, "Trace: %4x %s\n", loc, name); + f[loc] |= (NAMED | SREF); + if (!get_name(loc)) + save_name(loc, name); + save_ref(0, loc); + trace(loc); +} + +trace(addr) +register unsigned int addr; +{ + int opcode; + register struct info *ip; + int operand; + int istart; + + if (f[addr] & TDONE) + return; + else + f[addr] |= TDONE; + + istart = addr; + opcode = getbyte(addr); + ip = &optbl[opcode]; + + if (ip->flag & ILL) + return; + + f[addr] |= ISOP; + + addr++; + + /* Get the operand */ + + switch(ip->nb) { + case 1: + break; + case 2: + operand = getbyte(addr); + f[addr++] |= TDONE; + break; + case 3: + operand = getword(addr); + f[addr++] |= TDONE; + f[addr++] |= TDONE; + break; + } + + /* Mark data references */ + + switch (ip->flag & ADRMASK) { + case IMM: + case ACC: + case IMP: + case REL: + case IND: + break; + case ABS: + if (ip->flag & (JUMP | FORK)) + break; + /* Fall into */ + case ABX: + case ABY: + case INX: + case INY: + case ZPG: + case ZPX: + case ZPY: + f[operand] |= DREF; + save_ref(istart, operand); + break; + default: + crash("Optable error"); + break; + } + + /* Trace the next instruction */ + + switch (ip->flag & CTLMASK) { + case NORM: + trace(addr); + break; + case JUMP: + f[operand] |= JREF; + save_ref(istart, operand); + trace(operand); + break; + case FORK: + if (ip->flag & REL) { + if (operand > 127) + operand = (~0xff | operand); + operand = operand + addr; + f[operand] |= JREF; + } else { + f[operand] |= SREF; + } + save_ref(istart, operand); + trace(operand); + trace(addr); + break; + case STOP: + break; + default: + crash("Optable error"); + break; + } +} + +int +yywrap() +{ + (void)fclose(yyin); + if (npredef == pre_index) { + return(1); + } else { + lineno = 0; + cur_file = predef[pre_index]; + pre_index++; + yyin = fopen(cur_file, "r"); + if (!yyin) + crash("Can't open predefines file"); + return (0); + } +} diff --git a/print.c b/print.c new file mode 100644 index 0000000..bc0f055 --- /dev/null +++ b/print.c @@ -0,0 +1,295 @@ +#include +#include "dis.h" + +char *strcpy(); +char *strcat(); + +dumpitout() +{ + int i; + + for(i = 0; i<0x10000;) + { + if (f[i] & LOADED) + { + if ((i == 0) || (! (f[i-1] & LOADED))) + printf ("\t.org\t$%04x\n", i); + + if (f[i] & SREF && f[i] & ISOP) + printf("\n"); + + if (! asmout) + { + printf("%04x ",i); + print_bytes(i); + } + if (print_label(i)) + printf (":"); + printf ("\t"); + if (f[i] & ISOP) + i += print_inst(i); + else + i += print_data(i); + printf("\n"); + + } + else + { + if (print_label (i)) + { + if (i <= 0xff) + printf ("\t.equ\t$%02x\n", i); + else + printf ("\t.equ\t$%04x\n", i); + } + i++; + } + } + + if (! asmout) + print_refs(); +} + +pchar(c) +int c; +{ + if (isascii(c) && isprint(c)) + return(c); + return('.'); +} + +char * +lname(i) +int i; +{ + static char buf[20]; + char t; + + if (f[i] & NAMED) + return(get_name(i)); + if ((i > 0) && ((f[i-1] & (NAMED | DREF)) == (NAMED | DREF))) { + (void)strcpy(buf, get_name(i-1)); + (void)strcat(buf, "+1"); + return (buf); + } + if (f[i] & SREF) + t = 'S'; + else if (f[i] & JREF) + t = 'L'; + else if (f[i] & DREF) + { + if (i <= 0xff) + t = 'Z'; + else + t = 'D'; + } + else + t = 'X'; + + if (i <= 0xff) + (void)sprintf(buf, "%c%02x", t, i); + else + (void)sprintf(buf, "%c%04x", t, i); + + return (buf); +} + +print_label(i) +{ + if (f[i] & (NAMED | JREF | SREF | DREF)) + { + printf("%s", lname(i)); + return (1); + } + else + return (0); +} + +print_bytes(addr) +int addr; +{ + register struct info *ip; + + if ((f[addr] & ISOP) == 0) { + printf(" "); + return; + } + + ip = &optbl[getbyte(addr)]; + + switch (ip->nb) { + case 1: + printf("%02x ", getbyte(addr)); + break; + case 2: + printf("%02x %02x ", getbyte(addr), getbyte(addr+1)); + break; + case 3: + printf("%02x %02x %02x ", getbyte(addr), getbyte(addr+1), getbyte(addr+2)); + break; + } +} + + +print_inst(addr) +int addr; +{ + int opcode; + register struct info *ip; + int operand; + + opcode = getbyte(addr); + ip = &optbl[opcode]; + + printf("%s", ip->opn); + + addr++; + + switch(ip->nb) { + case 1: + break; + case 2: + operand = getbyte(addr); + break; + case 3: + operand = getword(addr); + break; + } + + if (ip->flag & REL) { + if (operand > 127) + operand = (~0xff | operand); + operand = operand + ip->nb + addr - 1; + } + + switch (ip->flag & ADRMASK) { + case IMM: + printf("\t#$%02x\t; %d %c", operand, operand, pchar(operand)); + break; + case ACC: + case IMP: + break; + case REL: + case ABS: + case ZPG: + printf("\t%s", lname(operand)); + break; + case IND: + printf("\t(%s)", lname(operand)); + break; + case ABX: + case ZPX: + printf("\t%s,X", lname(operand)); + break; + case ABY: + case ZPY: + printf("\t%s,Y", lname(operand)); + break; + case INX: + printf("\t(%s,X)", lname(operand)); + break; + case INY: + printf("\t(%s),Y", lname(operand)); + break; + default: + break; + } + + return(ip->nb); + +} + +print_data(i) +{ + int count; + int j; + int start; + + start = i; + printf(".byte\t$%02x", getbyte(i)); + count = 1; + i++; + + for (j = 1; j < 8; j++) { + if (f[i] & (JREF | SREF | DREF) || ((f[i] & LOADED) == 0)) + break; + else + printf(",$%02x", getbyte(i)); + i++; + count++; + } + for (j = count; j < 8; j++) + printf(" "); + + printf("\t; \""); + + for (j = start; j < i ; j++) + printf("%c", pchar((int)getbyte(j))); + + printf ("\""); + + return (count); +} + +print_refs() +{ + char tname[50]; + char cmd[200]; + FILE *fp; + register struct ref_chain *rp; + register int i; + int npline; + +#ifndef AMIGA + (void)sprintf(tname, "dis.%d", getpid()); + (void)sprintf(cmd, "sort %s; rm %s", tname, tname); +#else + (void)sprintf(tname, "dis.%ld", FindTask(0L)); + (void)sprintf(cmd, "Sort from %s to %s", tname, &tname[3] ); +#endif + + fp = fopen(tname, "w"); + if (!fp) + crash("Cant open temporary file/n"); + + for (i = 0; i<0x10000; i++) { + if(f[i] & (JREF|SREF|DREF)) { + rp = get_ref(i); + if (!rp) { + fprintf(stderr, "No ref %d\n", i); + break; + } + + fprintf(fp, "%-8s %04x ", lname(i), i); + npline = 0; + while (rp) { + fprintf(fp, "%04x ", rp->who); + npline++; + if (npline == 12) { + fprintf(fp,"\n"); + fprintf(fp,"%-8s %04x ",lname(i),i); + npline = 0; + } + rp = rp->next; + } + fprintf(fp, "\n"); + } + + } + + (void)fclose(fp); + + printf("\n\n\n\n\nCross References\n\n"); + printf("%-8s Value References\n", "Symbol"); + (void)fflush (stdout); + +#ifndef AMIGA + (void)system(cmd); +#else + (void)Execute(cmd,0L,0L); + (void)sprintf(cmd, "Type %s",&tname[3]); + (void)Execute(cmd,0L,Output()); + DeleteFile(tname); + DeleteFile(&tname[3]); +#endif +} diff --git a/ref.c b/ref.c new file mode 100644 index 0000000..bcb626b --- /dev/null +++ b/ref.c @@ -0,0 +1,90 @@ +#include "dis.h" + +#define HTSIZE 0x1000 /* Power of 2 */ +#define HTMASK (HTSIZE-1) + +struct hashslot { + int addr; /* The key */ + struct ref_chain *ref; /* Who references it */ + char *name; /* The symbolic name (if it has one) */ +}; + +struct hashslot hashtbl[HTSIZE]; /* the hash table */ + +struct hashslot * +hash(loc, allocate) +int loc; +int allocate; +{ + int probes; + register struct hashslot *hp; + + hp = &hashtbl[loc & HTMASK]; + probes = 0; + + while (probes< HTSIZE) { + if (hp->addr == loc) + return(hp); + if (hp->name == NULL && hp->ref == NULL) { + if (allocate) { + hp->addr = loc; + return(hp); + } else { + return(NULL); + } + } + hp++; + if (hp == &hashtbl[HTSIZE]) + hp = &hashtbl[0]; + probes++; + } + + crash("Hash table full"); + /*NOTREACHED*/ +} + +save_ref(refer, refee) +int refer; +int refee; +{ + struct ref_chain *rc; + struct hashslot *hp; + + rc = (struct ref_chain *)emalloc(sizeof(*rc)); + rc->who = refer; + hp = hash(refee, 1); + rc->next = hp->ref; + hp->ref = rc; +} + +save_name(loc, name) +int loc; +char *name; +{ + struct hashslot *hp; + + hp = hash(loc, 1); + hp->name = name; +} + +struct ref_chain * +get_ref(loc) +{ + struct hashslot *hp; + + hp = hash(loc, 0); + if (!hp) + return(NULL); + return(hp->ref); +} + +char * +get_name(loc) +{ + struct hashslot *hp; + + hp = hash(loc, 0); + if (!hp) + return(NULL); + return(hp->name); +} diff --git a/tbl.c b/tbl.c new file mode 100644 index 0000000..95948ed --- /dev/null +++ b/tbl.c @@ -0,0 +1,260 @@ +#include "dis.h" + +struct info optbl[256] = { + /* 00 */ { { 'B', 'R', 'K', 0, }, 1, IMP|STOP, }, + /* 01 */ { { 'O', 'R', 'A', 0, }, 2, INX|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 05 */ { { 'O', 'R', 'A', 0, }, 2, ZPG|NORM, }, + /* 06 */ { { 'A', 'S', 'L', 0, }, 2, ZPG|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 08 */ { { 'P', 'H', 'P', 0, }, 1, IMP|NORM, }, + /* 09 */ { { 'O', 'R', 'A', 0, }, 2, IMM|NORM, }, + /* 0a */ { { 'A', 'S', 'L', 0, }, 1, ACC|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 0d */ { { 'O', 'R', 'A', 0, }, 3, ABS|NORM, }, + /* 0e */ { { 'A', 'S', 'L', 0, }, 3, ABS|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 10 */ { { 'B', 'P', 'L', 0, }, 2, REL|FORK, }, + /* 11 */ { { 'O', 'R', 'A', 0, }, 2, INY|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 15 */ { { 'O', 'R', 'A', 0, }, 2, ZPX|NORM, }, + /* 16 */ { { 'A', 'S', 'L', 0, }, 2, ZPX|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 18 */ { { 'C', 'L', 'C', 0, }, 1, IMP|NORM, }, + /* 19 */ { { 'O', 'R', 'A', 0, }, 3, ABY|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 1d */ { { 'O', 'R', 'A', 0, }, 3, ABX|NORM, }, + /* 1e */ { { 'A', 'S', 'L', 0, }, 3, ABX|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 20 */ { { 'J', 'S', 'R', 0, }, 3, ABS|FORK, }, + /* 21 */ { { 'A', 'N', 'D', 0, }, 2, INX|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 24 */ { { 'B', 'I', 'T', 0, }, 2, ZPG|NORM, }, + /* 25 */ { { 'A', 'N', 'D', 0, }, 2, ZPG|NORM, }, + /* 26 */ { { 'R', 'O', 'L', 0, }, 2, ZPG|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 28 */ { { 'P', 'L', 'P', 0, }, 1, IMP|NORM, }, + /* 29 */ { { 'A', 'N', 'D', 0, }, 2, IMM|NORM, }, + /* 2a */ { { 'R', 'O', 'L', 0, }, 1, ACC|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 2c */ { { 'B', 'I', 'T', 0, }, 3, ABS|NORM, }, + /* 2d */ { { 'A', 'N', 'D', 0, }, 3, ABS|NORM, }, + /* 2e */ { { 'R', 'O', 'L', 0, }, 3, ABS|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 30 */ { { 'B', 'M', 'I', 0, }, 2, REL|FORK, }, + /* 31 */ { { 'A', 'N', 'D', 0, }, 2, INY|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 35 */ { { 'A', 'N', 'D', 0, }, 2, ZPX|NORM, }, + /* 36 */ { { 'R', 'O', 'L', 0, }, 2, ZPX|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 38 */ { { 'S', 'E', 'C', 0, }, 1, IMP|NORM, }, + /* 39 */ { { 'A', 'N', 'D', 0, }, 3, ABY|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 3d */ { { 'A', 'N', 'D', 0, }, 3, ABX|NORM, }, + /* 3e */ { { 'R', 'O', 'L', 0, }, 3, ABX|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 40 */ { { 'R', 'T', 'I', 0, }, 1, IMP|STOP, }, + /* 41 */ { { 'E', 'O', 'R', 0, }, 2, INX|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 45 */ { { 'E', 'O', 'R', 0, }, 2, ZPG|NORM, }, + /* 46 */ { { 'L', 'S', 'R', 0, }, 2, ZPG|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 48 */ { { 'P', 'H', 'A', 0, }, 1, IMP|NORM, }, + /* 49 */ { { 'E', 'O', 'R', 0, }, 2, IMM|NORM, }, + /* 4a */ { { 'L', 'S', 'R', 0, }, 1, ACC|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 4c */ { { 'J', 'M', 'P', 0, }, 3, ABS|JUMP, }, + /* 4d */ { { 'E', 'O', 'R', 0, }, 3, ABS|NORM, }, + /* 4e */ { { 'L', 'S', 'R', 0, }, 3, ABS|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 50 */ { { 'B', 'V', 'C', 0, }, 2, REL|FORK, }, + /* 51 */ { { 'E', 'O', 'R', 0, }, 2, INY|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 55 */ { { 'E', 'O', 'R', 0, }, 2, ZPX|NORM, }, + /* 56 */ { { 'L', 'S', 'R', 0, }, 2, ZPX|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 58 */ { { 'C', 'L', 'I', 0, }, 1, IMP|NORM, }, + /* 59 */ { { 'E', 'O', 'R', 0, }, 3, ABY|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 5d */ { { 'E', 'O', 'R', 0, }, 3, ABX|NORM, }, + /* 5e */ { { 'L', 'S', 'R', 0, }, 3, ABX|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 60 */ { { 'R', 'T', 'S', 0, }, 1, IMP|STOP, }, + /* 61 */ { { 'A', 'D', 'C', 0, }, 2, INX|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 65 */ { { 'A', 'D', 'C', 0, }, 2, ZPG|NORM, }, + /* 66 */ { { 'R', 'O', 'R', 0, }, 2, ZPG|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 68 */ { { 'P', 'L', 'A', 0, }, 1, IMP|NORM, }, + /* 69 */ { { 'A', 'D', 'C', 0, }, 2, IMM|NORM, }, + /* 6a */ { { 'R', 'O', 'R', 0, }, 1, ACC|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 6c */ { { 'J', 'M', 'P', 0, }, 3, IND|STOP, }, + /* 6d */ { { 'A', 'D', 'C', 0, }, 3, ABS|NORM, }, + /* 6e */ { { 'R', 'O', 'R', 0, }, 3, ABS|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 70 */ { { 'B', 'V', 'S', 0, }, 2, REL|FORK, }, + /* 71 */ { { 'A', 'D', 'C', 0, }, 2, INY|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 75 */ { { 'A', 'D', 'C', 0, }, 2, ZPX|NORM, }, + /* 76 */ { { 'R', 'O', 'R', 0, }, 2, ZPX|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 78 */ { { 'S', 'E', 'I', 0, }, 1, IMP|NORM, }, + /* 79 */ { { 'A', 'D', 'C', 0, }, 3, ABY|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 7d */ { { 'A', 'D', 'C', 0, }, 3, ABX|NORM, }, + /* 7e */ { { 'R', 'O', 'R', 0, }, 3, ABX|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 81 */ { { 'S', 'T', 'A', 0, }, 2, INX|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 84 */ { { 'S', 'T', 'Y', 0, }, 2, ZPG|NORM, }, + /* 85 */ { { 'S', 'T', 'A', 0, }, 2, ZPG|NORM, }, + /* 86 */ { { 'S', 'T', 'X', 0, }, 2, ZPG|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 88 */ { { 'D', 'E', 'Y', 0, }, 1, IMP|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 8a */ { { 'T', 'X', 'A', 0, }, 1, IMP|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 8c */ { { 'S', 'T', 'Y', 0, }, 3, ABS|NORM, }, + /* 8d */ { { 'S', 'T', 'A', 0, }, 3, ABS|NORM, }, + /* 8e */ { { 'S', 'T', 'X', 0, }, 3, ABS|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 90 */ { { 'B', 'C', 'C', 0, }, 2, REL|FORK, }, + /* 91 */ { { 'S', 'T', 'A', 0, }, 2, INY|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 94 */ { { 'S', 'T', 'Y', 0, }, 2, ZPX|NORM, }, + /* 95 */ { { 'S', 'T', 'A', 0, }, 2, ZPX|NORM, }, + /* 96 */ { { 'S', 'T', 'X', 0, }, 2, ZPY|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 98 */ { { 'T', 'Y', 'A', 0, }, 1, IMP|NORM, }, + /* 99 */ { { 'S', 'T', 'A', 0, }, 3, ABY|NORM, }, + /* 9a */ { { 'T', 'X', 'S', 0, }, 1, IMP|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 9d */ { { 'S', 'T', 'A', 0, }, 3, ABX|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* a0 */ { { 'L', 'D', 'Y', 0, }, 2, IMM|NORM, }, + /* a1 */ { { 'L', 'D', 'A', 0, }, 2, INX|NORM, }, + /* a2 */ { { 'L', 'D', 'X', 0, }, 2, IMM|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* a4 */ { { 'L', 'D', 'Y', 0, }, 2, ZPG|NORM, }, + /* a5 */ { { 'L', 'D', 'A', 0, }, 2, ZPG|NORM, }, + /* a6 */ { { 'L', 'D', 'X', 0, }, 2, ZPG|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* a8 */ { { 'T', 'A', 'Y', 0, }, 1, IMP|NORM, }, + /* a9 */ { { 'L', 'D', 'A', 0, }, 2, IMM|NORM, }, + /* aa */ { { 'T', 'A', 'X', 0, }, 1, IMP|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* ac */ { { 'L', 'D', 'Y', 0, }, 3, ABS|NORM, }, + /* ad */ { { 'L', 'D', 'A', 0, }, 3, ABS|NORM, }, + /* ae */ { { 'L', 'D', 'X', 0, }, 3, ABS|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* b0 */ { { 'B', 'C', 'S', 0, }, 2, REL|FORK, }, + /* b1 */ { { 'L', 'D', 'A', 0, }, 2, INY|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* b4 */ { { 'L', 'D', 'Y', 0, }, 2, ZPX|NORM, }, + /* b5 */ { { 'L', 'D', 'A', 0, }, 2, ZPX|NORM, }, + /* b6 */ { { 'L', 'D', 'X', 0, }, 2, ZPY|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* b8 */ { { 'C', 'L', 'V', 0, }, 1, IMP|NORM, }, + /* b9 */ { { 'L', 'D', 'A', 0, }, 3, ABY|NORM, }, + /* ba */ { { 'T', 'S', 'X', 0, }, 1, IMP|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* bc */ { { 'L', 'D', 'Y', 0, }, 3, ABX|NORM, }, + /* bd */ { { 'L', 'D', 'A', 0, }, 3, ABX|NORM, }, + /* be */ { { 'L', 'D', 'X', 0, }, 3, ABY|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* c0 */ { { 'C', 'P', 'Y', 0, }, 2, IMM|NORM, }, + /* c1 */ { { 'C', 'M', 'P', 0, }, 2, INX|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* c4 */ { { 'C', 'P', 'Y', 0, }, 2, ZPG|NORM, }, + /* c5 */ { { 'C', 'M', 'P', 0, }, 2, ZPG|NORM, }, + /* c6 */ { { 'D', 'E', 'C', 0, }, 2, ZPG|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* c8 */ { { 'I', 'N', 'Y', 0, }, 1, IMP|NORM, }, + /* c9 */ { { 'C', 'M', 'P', 0, }, 2, IMM|NORM, }, + /* ca */ { { 'D', 'E', 'X', 0, }, 1, IMP|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* cc */ { { 'C', 'P', 'Y', 0, }, 3, ABS|NORM, }, + /* cd */ { { 'C', 'M', 'P', 0, }, 3, ABS|NORM, }, + /* ce */ { { 'D', 'E', 'C', 0, }, 3, ABS|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* d0 */ { { 'B', 'N', 'E', 0, }, 2, REL|FORK, }, + /* d1 */ { { 'C', 'M', 'P', 0, }, 2, INY|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* d5 */ { { 'C', 'M', 'P', 0, }, 2, ZPX|NORM, }, + /* d6 */ { { 'D', 'E', 'C', 0, }, 2, ZPX|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* d8 */ { { 'C', 'L', 'D', 0, }, 1, IMP|NORM, }, + /* d9 */ { { 'C', 'M', 'P', 0, }, 3, ABY|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* dd */ { { 'C', 'M', 'P', 0, }, 3, ABX|NORM, }, + /* de */ { { 'D', 'E', 'C', 0, }, 3, ABX|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* e0 */ { { 'C', 'P', 'X', 0, }, 2, IMM|NORM, }, + /* e1 */ { { 'S', 'B', 'C', 0, }, 2, INX|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* e4 */ { { 'C', 'P', 'X', 0, }, 2, ZPG|NORM, }, + /* e5 */ { { 'S', 'B', 'C', 0, }, 2, ZPG|NORM, }, + /* e6 */ { { 'I', 'N', 'C', 0, }, 2, ZPG|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* e8 */ { { 'I', 'N', 'X', 0, }, 1, IMP|NORM, }, + /* e9 */ { { 'S', 'B', 'C', 0, }, 2, IMM|NORM, }, + /* ea */ { { 'N', 'O', 'P', 0, }, 1, IMP|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* ec */ { { 'C', 'P', 'X', 0, }, 3, ABS|NORM, }, + /* ed */ { { 'S', 'B', 'C', 0, }, 3, ABS|NORM, }, + /* ee */ { { 'I', 'N', 'C', 0, }, 3, ABS|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* f0 */ { { 'B', 'E', 'Q', 0, }, 2, REL|FORK, }, + /* f1 */ { { 'S', 'B', 'C', 0, }, 2, INY|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* f5 */ { { 'S', 'B', 'C', 0, }, 2, ZPX|NORM, }, + /* f6 */ { { 'I', 'N', 'C', 0, }, 2, ZPX|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* f8 */ { { 'S', 'E', 'D', 0, }, 1, IMP|NORM, }, + /* f9 */ { { 'S', 'B', 'C', 0, }, 3, ABY|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, + /* fd */ { { 'S', 'B', 'C', 0, }, 3, ABX|NORM, }, + /* fe */ { { 'I', 'N', 'C', 0, }, 3, ABX|NORM, }, + /* 00 */ { { '?', '?', '?', 0, }, 1, ILL|NORM, }, +};