commit cf44f20b548377927001084ff52add413899d31e Author: Eric Smith Date: Thu Apr 27 23:29:28 2000 +0000 Initial revision 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, }, +};