# HG changeset patch # User Shinji KONO # Date 1530465151 -32400 # Node ID 9a224bd9b45f3b6ad7ffce880ff05af123b684ce os9 emulation diff -r 000000000000 -r 9a224bd9b45f Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Mon Jul 02 02:12:31 2018 +0900 @@ -0,0 +1,87 @@ +# +# Makefile Sim6809 +# +# created 1994 by L.C. Benschop +# 2013-10-28 - Jens Diemer: add "clean" section +# 2014-06-25 - J.E. Klasek +# +# copyleft (c) 1994-2014 by the sbc09 team, see AUTHORS for more details. +# license: GNU General Public License version 2, see LICENSE for more details. +# + +# CFLAGS=-O3 -fomit-frame-pointer -DTERM_CONTROL +CFLAGS=-g -DTERM_CONTROL + +V09FLAGS= -DUSE_TERMIOS #-DBIG_ENDIAN + + +SIM_BIN=v09s v09st + +APPS=mon2.s + +# will be installed to ".." +BIN=a09 v09 $(SIM_BIN) v09.rom + +TARGETS=$(BIN) $(APPS) + +OTHER=monitor.s makerom + +all: $(TARGETS) + +# ------------------------------------ + +a09: a09.c os9crc.c + +v09: v09.o engine.o io.o os9disass.o + $(CC) -o v09 $(CFLAGS) v09.o engine.o io.o os9disass.o + +v09.o: v09.c v09.h + $(CC) -c $(CFLAGS) $(V09FLAGS) v09.c + +os9disass.o : os9/os9disass.c + $(CC) -c -DNO_MAIN -Wno-format-security $(CFLAGS) $(V09FLAGS) $< -o os9disass.o + +engine.o: engine.c v09.h + $(CC) -c $(CFLAGS) $(V09FLAGS) engine.c + +io.o: io.c v09.h + $(CC) -c $(CFLAGS) $(V09FLAGS) io.c + +v09.rom: makerom monitor.s + ./makerom +#include +#include +#include + +#define NLABELS 2048 +#define MAXIDLEN 16 +#define MAXLISTBYTES 8 +#define FNLEN 30 +#define LINELEN 128 + +static int debug=0; + +struct oprecord{char * name; + unsigned char cat; + unsigned short code;}; + +/* Instruction categories: + 0 one byte oprcodes NOP + 1 two byte opcodes SWI2 + 2 opcodes w. imm byte ANDCC + 3 LEAX etc. + 4 short branches. BGE + 5 long branches 2byte opc LBGE + 6 long branches 1byte opc LBRA + 7 accumulator instr. ADDA + 8 double reg instr 1byte opc LDX + 9 double reg instr 2 byte opc LDY + 10 single address instrs NEG + 11 TFR, EXG + 12 push,pull + 13 pseudoops +*/ + +struct oprecord optable[]={ + {"ABX",0,0x3a},{"ADCA",7,0x89},{"ADCB",7,0xc9}, + {"ADDA",7,0x8b},{"ADDB",7,0xcb},{"ADDD",8,0xc3}, + {"ANDA",7,0X84},{"ANDB",7,0xc4},{"ANDCC",2,0x1c}, + {"ASL",10,0x08},{"ASLA",0,0x48},{"ASLB",0,0x58}, + {"ASR",10,0x07},{"ASRA",0,0x47},{"ASRB",0,0x57}, + {"BCC",4,0x24},{"BCS",4,0x25},{"BEQ",4,0x27}, + {"BGE",4,0x2c},{"BGT",4,0x2e},{"BHI",4,0x22}, + {"BHS",4,0x24},{"BITA",7,0x85},{"BITB",7,0xc5}, + {"BLE",4,0x2f},{"BLO",4,0x25},{"BLS",4,0x23}, + {"BLT",4,0x2d},{"BMI",4,0x2b},{"BNE",4,0x26}, + {"BPL",4,0x2a},{"BRA",4,0x20},{"BRN",4,0x21}, + {"BSR",4,0x8d}, + {"BVC",4,0x28},{"BVS",4,0x29}, + {"CLC",1,0x1cfe},{"CLF",1,0x1cbf},{"CLI",1,0x1cef}, + {"CLIF",1,0x1caf}, + {"CLR",10,0x0f},{"CLRA",0,0x4f},{"CLRB",0,0x5f}, + {"CLV",1,0x1cfd}, + {"CMPA",7,0x81},{"CMPB",7,0xc1},{"CMPD",9,0x1083}, + {"CMPS",9,0x118c},{"CMPU",9,0x1183},{"CMPX",8,0x8c}, + {"CMPY",9,0x108c}, + {"COM",10,0x03},{"COMA",0,0x43},{"COMB",0,0x53}, + {"CWAI",2,0x3c},{"DAA",0,0x19}, + {"DEC",10,0x0a},{"DECA",0,0x4a},{"DECB",0,0x5a}, + {"DES",1,0x327f},{"DEU",1,0x335f},{"DEX",1,0x301f}, + {"DEY",1,0x313f}, + {"ELSE",13,1}, + {"EMOD",13,25}, + {"END",13,2}, + {"ENDC",13,3}, + {"ENDIF",13,3}, + {"ENDM",13,4}, + {"EORA",7,0x88},{"EORB",7,0xc8}, + {"EQU",13,5},{"EXG",11,0x1e},{"EXTERN",13,6}, + {"FCB",13,7},{"FCC",13,8}, + {"FCS",13,23}, + {"FCW",13,9}, + {"FDB",13,9}, + {"IF",13,10}, + {"IFEQ",13,29}, + {"IFGT",13,30}, + {"IFNE",13,28}, + {"IFP1",13,21}, + {"INC",10,0x0c},{"INCA",0,0x4c},{"INCB",0,0x5c}, + {"INCLUDE",13,16}, + {"INS",1,0x3261},{"INU",1,0x3341},{"INX",1,0x3001}, + {"INY",1,0x3121},{"JMP",10,0x0e},{"JSR",8,0x8d}, + {"LBCC",5,0x1024},{"LBCS",5,0x1025},{"LBEQ",5,0x1027}, + {"LBGE",5,0x102c},{"LBGT",5,0x102e},{"LBHI",5,0x1022}, + {"LBHS",5,0x1024}, + {"LBLE",5,0x102f},{"LBLO",5,0x1025},{"LBLS",5,0x1023}, + {"LBLT",5,0x102d},{"LBMI",5,0x102b},{"LBNE",5,0x1026}, + {"LBPL",5,0x102a},{"LBRA",6,0x16},{"LBRN",5,0x1021}, + {"LBSR",6,0x17}, + {"LBVC",5,0x1028},{"LBVS",5,0x1029}, + {"LDA",7,0x86},{"LDB",7,0xc6},{"LDD",8,0xcc}, + {"LDS",9,0x10ce},{"LDU",8,0xce},{"LDX",8,0x8e}, + {"LDY",9,0x108e},{"LEAS",3,0x32}, + {"LEAU",3,0x33},{"LEAX",3,0x30},{"LEAY",3,0x31}, + {"LSL",10,0x08},{"LSLA",0,0x48},{"LSLB",0,0x58}, + {"LSR",10,0x04},{"LSRA",0,0x44},{"LSRB",0,0x54}, + {"MACRO",13,11}, + {"MOD",13,24}, + {"MUL",0,0x3d}, + {"NAM",13,26}, + {"NEG",10,0x00},{"NEGA",0,0x40},{"NEGB",0,0x50}, + {"NOP",0,0x12}, + {"OPT",13,19}, + {"ORA",7,0x8a},{"ORB",7,0xca},{"ORCC",2,0x1a}, + {"ORG",13,12}, + {"OS9",13,32}, + {"PAG",13,20}, {"PAGE",13,20}, + {"PSHS",12,0x34},{"PSHU",12,0x36},{"PUBLIC",13,13}, + {"PULS",12,0x35},{"PULU",12,0x37},{"RMB",13,0}, + {"ROL",10,0x09},{"ROLA",0,0x49},{"ROLB",0,0x59}, + {"ROR",10,0x06},{"RORA",0,0x46},{"RORB",0,0x56}, + {"RTI",0,0x3b},{"RTS",0,0x39}, + {"SBCA",7,0x82},{"SBCB",7,0xc2}, + {"SEC",1,0x1a01},{"SEF",1,0x1a40},{"SEI",1,0x1a10}, + {"SEIF",1,0x1a50},{"SET",13,15}, + {"SETDP",13,14},{"SEV",1,0x1a02},{"SEX",0,0x1d}, + {"STA",7,0x87},{"STB",7,0xc7},{"STD",8,0xcd}, + {"STS",9,0x10cf},{"STU",8,0xcf},{"STX",8,0x8f}, + {"STY",9,0x108f}, + {"SUBA",7,0x80},{"SUBB",7,0xc0},{"SUBD",8,0x83}, + {"SWI",0,0x3f},{"SWI2",1,0x103f},{"SWI3",1,0x113f}, + {"SYNC",0,0x13},{"TFR",11,0x1f}, + {"TITLE",13,18}, + {"TST",10,0x0d},{"TSTA",0,0x4d},{"TSTB",0,0x5d}, + {"TTL",13,18}, + {"USE",13,27}, +}; + +struct symrecord{char name[MAXIDLEN+1]; + char cat; + unsigned short value; + }; + +int symcounter=0; + +/* Symbol categories. + 0 Constant value (from equ). + 1 Variable value (from set) + 2 Address within program module (label). + 3 Variable containing address. + 4 Adress in other program module (extern) + 5 Variable containing external address. + 6 Unresolved address. + 7 Variable containing unresolved address. + 8 Public label. + 9 Macro definition. + 10 Public label (yet undefined). + 11 parameter name. + 12 local label. + 13 empty. +*/ + +struct symrecord symtable[NLABELS]; + +void processfile(char *name); + +struct oprecord * findop(char * nm) +/* Find operation (mnemonic) in table using binary search */ +{ + int lo,hi,i,s; + lo=0;hi=sizeof(optable)/sizeof(optable[0])-1; + do { + i=(lo+hi)/2; + s=strcmp(optable[i].name,nm); + if(s<0) lo=i+1; + else if(s>0) hi=i-1; + else break; + } while(hi>=lo); + if (s) return NULL; + return optable+i; +} + +struct symrecord * findsym(char * nm) +/* finds symbol table record; inserts if not found + uses binary search, maintains sorted table */ +{ + int lo,hi,i,j,s; + lo=0;hi=symcounter-1; + s=1;i=0; + while (hi>=lo) { + i=(lo+hi)/2; + s=strcmp(symtable[i].name,nm); + if(s<0) lo=i+1; + else if(s>0) hi=i-1; + else break; + } + if(s) { + i=(s<0?i+1:i); + if(symcounter==NLABELS) { + fprintf(stderr,"Sorry, no storage for symbols!!!"); + exit(4); + } + for(j=symcounter;j>i;j--) symtable[j]=symtable[j-1]; + symcounter++; + strcpy(symtable[i].name,nm); + symtable[i].cat=13; + } + return symtable+i; +} + +FILE *listfile,*objfile; +char *listname,*objname,*srcname,*curname; +int lineno; + +void +outsymtable() +{ + int i,j=0; + fprintf(listfile,"\nSYMBOL TABLE"); + for(i=0;i='a'&&c<='z')c-=32; + if(c!='.'&&c!='$'&&(c<'0'||c>'9')&&(c<'A'||c>'Z'))break; + if(i='0'&&namebuf[i]<='F') { + t=t*16+namebuf[i]-'0'; + if(namebuf[i]>'9')t-=7; + i++; + } + if(i==0)error|=1; + return t; +} + +short scanchar() +{ + short t; + srcptr++; + t=*srcptr; + if(t)srcptr++; + if (*srcptr=='\'')srcptr++; + return t; +} + +short scanbin() +{ + char c; + short t=0; + srcptr++; + c=*srcptr++; + while(c=='0'||c=='1') { + t=t*2+c-'0'; + c=*srcptr++; + } + srcptr--; + return t; +} + +short scanoct() +{ + char c; + short t=0; + srcptr++; + c=*srcptr++; + while(c>='0'&&c<='7') { + t=t*8+c-'0'; + c=*srcptr++; + } + srcptr--; + return t; +} + + +short scanlabel() +{ + struct symrecord * p; + scanname(); + p=findsym(namebuf); + if(p->cat==13) { + p->cat=6; + p->value=0; + } + if(p->cat==9||p->cat==11)error|=1; + exprcat=p->cat&14; + if(exprcat==6||exprcat==10)unknown=1; + if(((exprcat==2||exprcat==8) + && (unsigned short)(p->value)>(unsigned short)loccounter)|| + exprcat==4) + certain=0; + if(exprcat==8||exprcat==6||exprcat==10)exprcat=2; + return p->value; +} + +/* expression categories... + all zeros is ordinary constant. + bit 1 indicates address within module. + bit 2 indicates external address. + bit 4 indicates this can't be relocated if it's an address. + bit 5 indicates address (if any) is negative. +*/ + + + +short scanfactor() +{ + char c; + short t; + skipspace(); + c=*srcptr; + if(isalpha(c))return scanlabel(); + else if(isdigit(c))return scandecimal(); + else switch(c) { + case '.' : + case '*' : srcptr++;exprcat|=2;return loccounter; + case '$' : return scanhex(); + case '%' : return scanbin(); + case '&' : /* compatibility */ + case '@' : return scanoct(); + case '\'' : return scanchar(); + case '(' : srcptr++;t=scanexpr(0);skipspace(); + if(*srcptr==')')srcptr++;else error|=1; + return t; + case '-' : srcptr++;exprcat^=32;return -scanfactor(); + case '+' : srcptr++;return scanfactor(); + case '!' : srcptr++;exprcat|=16;return !scanfactor(); + case '^' : + case '~' : srcptr++;exprcat|=16;return ~scanfactor(); + } + error|=1; + return 0; +} + +#define EXITEVAL {srcptr--;return t;} + +#define RESOLVECAT if((oldcat&15)==0)oldcat=0;\ + if((exprcat&15)==0)exprcat=0;\ + if((exprcat==2&&oldcat==34)||(exprcat==34&&oldcat==2)) {\ + exprcat=0;\ + oldcat=0;}\ + exprcat|=oldcat;\ +/* resolve such cases as constant added to address or difference between + two addresses in same module */ + + +short scanexpr(int level) /* This is what you call _recursive_ descent!!!*/ +{ + short t,u; + char oldcat,c; + exprcat=0; + if(level==10)return scanfactor(); + t=scanexpr(level+1); + while(1) { + skipspace(); + c=*srcptr++; + switch(c) { + case '*':oldcat=exprcat; + t*=scanexpr(10); + exprcat|=oldcat|16; + break; + case '/':oldcat=exprcat; + u=scanexpr(10); + if(u)t/=u;else error|=1; + exprcat|=oldcat|16; + break; + case '%':oldcat=exprcat; + u=scanexpr(10); + if(u)t%=u;else error|=1; + exprcat|=oldcat|16; + break; + case '+':if(level==9)EXITEVAL + oldcat=exprcat; + t+=scanexpr(9); + RESOLVECAT + break; + case '-':if(level==9)EXITEVAL + oldcat=exprcat; + t-=scanexpr(9); + exprcat^=32; + RESOLVECAT + break; + case '<':if(*(srcptr)=='<') { + if(level>=8)EXITEVAL + srcptr++; + oldcat=exprcat; + t<<=scanexpr(8); + exprcat|=oldcat|16; + break; + } else if(*(srcptr)=='=') { + if(level>=7)EXITEVAL + srcptr++; + oldcat=exprcat; + t=t<=scanexpr(7); + exprcat|=oldcat|16; + break; + } else { + if(level>=7)EXITEVAL + oldcat=exprcat; + t=t':if(*(srcptr)=='>') { + if(level>=8)EXITEVAL + srcptr++; + oldcat=exprcat; + t>>=scanexpr(8); + exprcat|=oldcat|16; + break; + } else if(*(srcptr)=='=') { + if(level>=7)EXITEVAL + srcptr++; + oldcat=exprcat; + t=t>=scanexpr(7); + exprcat|=oldcat|16; + break; + } else { + if(level>=7)EXITEVAL + oldcat=exprcat; + t=t>scanexpr(7); + exprcat|=oldcat|16; + break; + } + case '!':if(level>=6||*srcptr!='=')EXITEVAL + srcptr++; + oldcat=exprcat; + t=t!=scanexpr(6); + exprcat|=oldcat|16; + break; + case '=':if(level>=6)EXITEVAL + if(*srcptr=='=')srcptr++; + oldcat=exprcat; + t=t==scanexpr(6); + exprcat|=oldcat|16; + break; + case '&':if(level>=5)EXITEVAL + oldcat=exprcat; + t&=scanexpr(5); + exprcat|=oldcat|16; + break; + case '^':if(level>=4)EXITEVAL + oldcat=exprcat; + t^=scanexpr(4); + exprcat|=oldcat|16; + break; + case '|':if(level>=3)EXITEVAL + oldcat=exprcat; + t|=scanexpr(3); + exprcat|=oldcat|16; + default: EXITEVAL + } + } +} + +char mode; /* addressing mode 0=immediate,1=direct,2=extended,3=postbyte + 4=pcrelative(with postbyte) 5=indirect 6=pcrel&indirect*/ +char opsize; /*desired operand size 0=dunno,1=5,2=8,3=16*/ +short operand; +unsigned char postbyte; + +int dpsetting; + + +int scanindexreg() +{ + char c; + c=*srcptr; + if(islower(c))c-=32; + if (debug) fprintf(stderr,"DEBUG: scanindexreg: indexreg=%d, mode=%d, opsize=%d, error=%d, postbyte=%02X\n",c,mode,opsize,error,postbyte); + switch(c) { + case 'X':return 1; + case 'Y':postbyte|=0x20;return 1; + case 'U':postbyte|=0x40;return 1; + case 'S':postbyte|=0x60;return 1; + default: return 0; + } +} + +void +set3() +{ + if(mode<3)mode=3; +} + +void +scanspecial() +{ + set3(); + skipspace(); + if(*srcptr=='-') { + srcptr++; + if(*srcptr=='-') { + srcptr++; + postbyte=0x83; + } else postbyte=0x82; + if(!scanindexreg())error|=2;else srcptr++; + } else { + postbyte=0x80; + if(!scanindexreg())error|=2;else srcptr++; + if(*srcptr=='+') { + srcptr++; + if(*srcptr=='+') { + srcptr++; + postbyte+=1; + } + } else postbyte+=4; + } +} + +void +scanindexed() +{ + set3(); + postbyte=0; + if(scanindexreg()) { + srcptr++; + if(opsize==0) { + if(unknown||!certain)opsize=3; + else if(operand>=-16&&operand<16&&mode==3)opsize=1; + else if(operand>=-128&&operand<128)opsize=2; + else opsize=3; + } + switch(opsize) { + case 1:postbyte+=(operand&31);opsize=0;break; + case 2:postbyte+=0x88;break; + case 3:postbyte+=0x89;break; + } + } else { /*pc relative*/ + if(toupper(*srcptr)!='P')error|=2; + else { + srcptr++; + if(toupper(*srcptr)!='C')error|=2; + else { + srcptr++; + if(toupper(*srcptr)=='R')srcptr++; + } + } + mode++;postbyte+=0x8c; + if(opsize==1)opsize=2; + } +} + +#define RESTORE {srcptr=oldsrcptr;c=*srcptr;goto dodefault;} + +void +scanoperands() +{ + char c,d,*oldsrcptr; + unknown=0; + opsize=0; + certain=1; + skipspace(); + c=*srcptr; + mode=0; + if(c=='[') { + srcptr++; + c=*srcptr; + mode=5; + } + if (debug) fprintf(stderr,"DEBUG: scanoperands: c=%c (%02X)\n",c,c); + switch(c) { + case 'D': case 'd': + oldsrcptr=srcptr; + srcptr++; + skipspace(); + if(*srcptr!=',')RESTORE else { + postbyte=0x8b; + srcptr++; + if(!scanindexreg())RESTORE else {srcptr++;set3();} + } + break; + case 'A': case 'a': + oldsrcptr=srcptr; + srcptr++; + skipspace(); + if(*srcptr!=',')RESTORE else { + postbyte=0x86; + srcptr++; + if(!scanindexreg())RESTORE else {srcptr++;set3();} + } + break; + case 'B': case 'b': + oldsrcptr=srcptr; + srcptr++; + skipspace(); + if(*srcptr!=',')RESTORE else { + postbyte=0x85; + srcptr++; + if (debug) fprintf(stderr,"DEBUG: scanoperands: breg preindex: c=%c (%02X)\n",*srcptr,*srcptr); + if(!scanindexreg())RESTORE else {srcptr++;set3();} + if (debug) fprintf(stderr,"DEBUG: scanoperands: breg: postindex c=%c (%02X)\n",*srcptr,*srcptr); + } + break; + case ',': + srcptr++; + scanspecial(); + break; + case '#': + if(mode==5)error|=2;else mode=0; + srcptr++; + operand=scanexpr(0); + break; + case '<': + srcptr++; + if(*srcptr=='<') { + srcptr++; + opsize=1; + } else opsize=2; + goto dodefault; + case '>': + srcptr++; + opsize=3; + default: dodefault: + operand=scanexpr(0); + skipspace(); + if(*srcptr==',') { + srcptr++; + scanindexed(); + } else { + if(opsize==0) { + if(unknown||!certain||dpsetting==-1|| + (unsigned short)(operand-dpsetting*256)>=256) + opsize=3; else opsize=2; + } + if(opsize==1)opsize=2; + if(mode==5){ + postbyte=0x8f; + opsize=3; + } else mode=opsize-1; + } + } + if (debug) fprintf(stderr,"DEBUG: scanoperands: mode=%d, error=%d, postbyte=%02X\n",mode,error,postbyte); + if(mode>=5) { + skipspace(); + postbyte|=0x10; + if(*srcptr!=']')error|=2;else srcptr++; + } + if(pass==2&&unknown)error|=4; +} + +unsigned char codebuf[128]; +int codeptr; /* byte offset within instruction */ +int suppress; /* 0=no suppress 1=until ENDIF 2=until ELSE 3=until ENDM */ +int ifcount; /* count of nested IFs within suppressed text */ + +unsigned char outmode; /* 0 is binary, 1 is s-records */ + +unsigned short hexaddr; +int hexcount; +unsigned char hexbuffer[16]; +unsigned int chksum; + +extern int os9crc(unsigned char c, int crcp); +int crc; + +void +reset_crc() +{ + crc = -1; +} + + +void +flushhex() +{ + int i; + if(hexcount){ + fprintf(objfile,"S1%02X%04X",(hexcount+3)&0xff,hexaddr&0xffff); + for(i=0;i>8)&0xff)+hexcount+3; + fprintf(objfile,"%02X\n",0xff-(chksum&0xff)); + hexaddr+=hexcount; + hexcount=0; + chksum=0; + } +} + +void +outhex(unsigned char x) +{ + if(hexcount==16)flushhex(); + hexbuffer[hexcount++]=x; + chksum+=x; +} + +void +outbuffer() +{ + int i; + for(i=0;i>=1; + } + errors++; +} + +void +outlist() +{ + int i; + fprintf(listfile,"%04X: ",oldlc); + for(i=0;icat!=13&&lp->cat!=6) { + if(lp->cat!=2||lp->value!=loccounter) + error|=8; + } else { + lp->cat=2; + lp->value=loccounter; + } + } +} + +void +putbyte(unsigned char b) +{ + codebuf[codeptr++]=b; +} + +void +putword(unsigned short w) +{ + codebuf[codeptr++]=w>>8; + codebuf[codeptr++]=w&0x0ff; +} + +void +doaddress() /* assemble the right addressing bytes for an instruction */ +{ + int offs; + switch(mode) { + case 0: if(opsize==2)putbyte(operand);else putword(operand);break; + case 1: putbyte(operand);break; + case 2: putword(operand);break; + case 3: case 5: putbyte(postbyte); + switch(opsize) { + case 2: putbyte(operand);break; + case 3: putword(operand); + } + break; + case 4: case 6: offs=(unsigned short)operand-loccounter-codeptr-2; + if(offs<-128||offs>=128||opsize==3||unknown||!certain) { + if((!unknown)&&opsize==2&&(offs<-128||offs>=128) ) + error|=16; + offs--; + opsize=3; + postbyte++; + } + putbyte(postbyte); + if (debug) fprintf(stderr,"DEBUG: doaddress: mode=%d, opsize=%d, error=%d, postbyte=%02X, operand=%04X offs=%d\n",mode,opsize,error,postbyte,operand,offs); + if(opsize==3)putword(offs); + else putbyte(offs); + } +} + +void +onebyte(int co) +{ + putbyte(co); +} + +void +twobyte(int co) +{ + putword(co); +} + +void +oneimm(int co) +{ + scanoperands(); + if(mode>=3)error|=2; + putbyte(co); + putbyte(operand); +} + +void +lea(int co) +{ + putbyte(co); + scanoperands(); + if(mode==0) error|=2; + if(mode<3) { + opsize=3; + postbyte=0x8f; + mode=3; + } + if (debug) fprintf(stderr,"DEBUG: lea: mode=%d, opsize=%d, error=%d, postbyte=%02X, *src=%c\n",mode,opsize,error,postbyte,*srcptr); + doaddress(); +} + +void +sbranch(int co) +{ + int offs; + scanoperands(); + if(mode!=1&&mode!=2)error|=2; + offs=(unsigned short)operand-loccounter-2; + if(!unknown&&(offs<-128||offs>=128))error|=16; + if(pass==2&&unknown)error|=4; + putbyte(co); + putbyte(offs); +} + +void +lbra(int co) +{ + scanoperands(); + if(mode!=1&&mode!=2)error|=2; + putbyte(co); + putword(operand-loccounter-3); +} + +void +lbranch(int co) +{ + scanoperands(); + if(mode!=1&&mode!=2)error|=2; + putword(co); + putword(operand-loccounter-4); +} + +void +arith(int co) +{ + scanoperands(); + switch(mode) { + case 0:opsize=2;putbyte(co);break; + case 1:putbyte(co+0x010);break; + case 2:putbyte(co+0x030);break; + default:putbyte(co+0x020); + } + doaddress(); +} + +void +darith(int co) +{ + scanoperands(); + switch(mode) { + case 0:opsize=3;putbyte(co);break; + case 1:putbyte(co+0x010);break; + case 2:putbyte(co+0x030);break; + default:putbyte(co+0x020); + } + doaddress(); +} + +void +d2arith(int co) +{ + scanoperands(); + switch(mode) { + case 0:opsize=3;putword(co);break; + case 1:putword(co+0x010);break; + case 2:putword(co+0x030);break; + default:putword(co+0x020); + } + doaddress(); +} + +void +oneaddr(int co) +{ + scanoperands(); + switch(mode) { + case 0: error|=2;break; + case 1: putbyte(co);break; + case 2: putbyte(co+0x70);break; + default: putbyte(co+0x60);break; + } + doaddress(); +} + +void +tfrexg(int co) +{ + struct regrecord * p; + putbyte(co); + skipspace(); + scanname(); + if((p=findreg(namebuf))==0)error|=2; + else postbyte=(p->tfr)<<4; + skipspace(); + if(*srcptr==',')srcptr++;else error|=2; + skipspace(); + scanname(); + if((p=findreg(namebuf))==0)error|=2; + else postbyte|=p->tfr; + putbyte(postbyte); +} + +void +pshpul(int co) +{ + struct regrecord *p; + putbyte(co); + postbyte=0; + do { + if(*srcptr==',')srcptr++; + skipspace(); + scanname(); + if((p=findreg(namebuf))==0)error|=2; + else postbyte|=p->psh; + skipspace(); + }while (*srcptr==','); + putbyte(postbyte); +} + +void +skipComma() +{ + while(*srcptr && *srcptr!='\n' && *srcptr!=',')srcptr++; + if (*srcptr==',') { + srcptr++; + } else { + error|=1; + } +} + +int modStart; + +void os9begin() +{ + generating=1; + modStart = loccounter; + reset_crc(); + putword(0x87cd); + putword(scanexpr(0)-loccounter); // module size + skipComma(); + putword(scanexpr(0)-loccounter); // offset to module name + skipComma(); + putbyte(scanexpr(0)); // type / language + skipComma(); + putbyte(scanexpr(0)); // attribute + int parity=0; + for(int i=0; i< 8; i++) parity^=codebuf[i]; + putbyte(parity^0xff); // header parity + skipspace(); + while (*srcptr==',') { // there are some more + srcptr++; + putword(scanexpr(0)); + skipspace(); + } +} + +void os9end() +{ + crc = crc ^ 0xffffff; + + putbyte((crc>>16)&0xff); + putbyte((crc>>8)&0xff); + putbyte(crc&0xff); +} + + +void +pseudoop(int co,struct symrecord * lp) +{ + int i; + char c; + char *fname; + int locsave; + + switch(co) { + case 0:/* RMB */ + setlabel(lp); + operand=scanexpr(0); + if(unknown)error|=4; + loccounter+=operand; + if(generating&&pass==2) { + if(!outmode)for(i=0;icat==13||lp->cat==6|| + (lp->value==(unsigned short)operand&&pass==2)) { + if(exprcat==2)lp->cat=2; + else lp->cat=0; + lp->value=operand; + } else error|=8; + } + break; + case 7:/* FCB */ + setlabel(lp); + generating=1; + do { + if(*srcptr==',')srcptr++; + skipspace(); + if(*srcptr=='\"') { + srcptr++; + while(*srcptr!='\"'&&*srcptr) + putbyte(*srcptr++); + if(*srcptr=='\"')srcptr++; + } else { + putbyte(scanexpr(0)); + if(unknown&&pass==2)error|=4; + } + skipspace(); + } while(*srcptr==','); + break; + case 8:/* FCC */ + setlabel(lp); + skipspace(); + c=*srcptr++; + while(*srcptr!=c&&*srcptr) + putbyte(*srcptr++); + if(*srcptr==c)srcptr++; + break; + case 9:/* FDB */ + setlabel(lp); + generating=1; + do { + if(*srcptr==',')srcptr++; + skipspace(); + putword(scanexpr(0)); + if(unknown&&pass==2)error|=4; + skipspace(); + } while(*srcptr==','); + break; + case 23 :/* FCS */ + setlabel(lp); + generating=1; + skipspace(); + int sep = *srcptr; + if(sep=='\"' || sep=='/') { + srcptr++; + while(*srcptr!=sep&&*srcptr) + putbyte(*srcptr++); + if(*srcptr==sep)srcptr++; + codebuf[codeptr-1] |= 0x80; // os9 string termination + } + break; + case 1: /* ELSE */ + suppress=1; + break; + case 21: /* IFP1 */ + if(pass==2)suppress=2; + break; + case 29: /* IFGT */ + operand=scanexpr(0); + if(unknown)error|=4; + if(operand>0)suppress=2; + break; + case 31: /* IFLT */ + operand=scanexpr(0); + if(unknown)error|=4; + if(operand<0)suppress=2; + break; + case 28: /* IFNE */ + operand=scanexpr(0); + if(unknown)error|=4; + if(operand==0)suppress=2; + break; + case 30: /* IFEQ */ + case 10: /* IF */ + operand=scanexpr(0); + if(unknown)error|=4; + if(!operand)suppress=2; + break; + case 12: /* ORG */ + operand=scanexpr(0); + if(unknown)error|=4; + if(generating&&pass==2) { + for(i=0;i<(unsigned short)operand-loccounter;i++) + if(!outmode)fputc(0,objfile);else flushhex(); + } + loccounter=operand; + hexaddr=loccounter; + break; + case 14: /* SETDP */ + operand=scanexpr(0); + if(unknown)error|=4; + if(!(operand&255))operand=(unsigned short)operand>>8; + if((unsigned)operand>255)operand=-1; + dpsetting=operand; + break; + case 15: /* SET */ + operand=scanexpr(0); + if(!lp)error|=32; + else { + if(lp->cat&1||lp->cat==6) { + if(exprcat==2)lp->cat=3; + else lp->cat=1; + lp->value=operand; + } else error|=8; + } + break; + case 2: /* END */ + terminate=1; + break; + case 27: /* USE */ + locsave = loccounter ; + case 16: /* INCLUDE */ + skipspace(); + if(*srcptr=='"')srcptr++; + i = 0; + for(i=0; !(srcptr[i]==0||srcptr[i]=='"'); i++); + int len = i; + fname = calloc(1,len); + for(i=0;icat!=13){ + setlabel(lp); + generating=1; + } + co=op->code; + switch(op->cat) { + case 0:onebyte(co);break; + case 1:twobyte(co);break; + case 2:oneimm(co);break; + case 3:lea(co);break; + case 4:sbranch(co);break; + case 5:lbranch(co);break; + case 6:lbra(co);break; + case 7:arith(co);break; + case 8:darith(co);break; + case 9:d2arith(co);break; + case 10:oneaddr(co);break; + case 11:tfrexg(co);break; + case 12:pshpul(co);break; + case 13:pseudoop(co,lp); + } + c=*srcptr; + if (debug) fprintf(stderr,"DEBUG: processline: mode=%d, opsize=%d, error=%d, postbyte=%02X c=%c\n",mode,opsize,error,postbyte,c); + if(c!=' '&&*(srcptr-1)!=' '&&c!=0&&c!=';')error|=2; + } + else error|=0x8000; + }else setlabel(lp); + if(pass==2) { + outbuffer(); + if(listing)outlist(); + } + if(error)report(); + loccounter+=codeptr; +} + +void +suppressline() +{ + struct oprecord * op; + srcptr=srcline; + oldlc=loccounter; + codeptr=0; + if(isalnum(*srcptr)) { + scanname(); + if(*srcptr==':')srcptr++; + } + skipspace(); + scanname();op=findop(namebuf); + if(op && op->cat==13) { + if(op->code==10||op->code==13||op->code==29||op->code==28||op->code==21||op->code==30) ifcount++; + else if(op->code==3) { + if(ifcount>0)ifcount--;else if(suppress==1|suppress==2)suppress=0; + } else if(op->code==1) { + if(ifcount==0 && suppress==2)suppress=0; + } + } + if(pass==2&&listing)outlist(); +} + +void +usage(char*nm) +{ + fprintf(stderr,"Usage: %s [-o objname] [-l listname] [-s srecord-file] srcname\n",nm); + exit(2); +} + +char * +strconcat(char *s,int spos,char *d) +{ + int slen = strlen(s); + int dlen = strlen(d); + if ( spos == 0) spos = slen; + char *out = calloc(1,spos+dlen+1); + int i = 0; + for(; i< spos; i++ ) out[i] = s[i]; + for(; i< spos+dlen+1; i++ ) out[i] = *d++; + return out; +} + + +void +getoptions(int c,char*v[]) +{ + int i=0; + if(c==1)usage(v[0]); + if(strcmp(v[1],"-d")==0) { + debug=1; + i++; + } + if(strcmp(v[1],"-o")==0) { + if(c<4)usage(v[0]); + objname = v[2]; + i+=2; + } + if(strcmp(v[i+1],"-s")==0) { + if(c<4+i)usage(v[0]); + objname=v[i+2]; + outmode=1; + i+=2; + } + if(strcmp(v[i+1],"-l")==0) { + if(c<4+i)usage(v[0]); + listname=v[2+i]; + i+=2; + } + srcname=v[1+i]; + if(objname==0) { + for(i=0;srcname[i]!='.' && srcname[i]!=0 ;i++) ; + objname = strconcat(srcname,i,".b"); + } + listing=(listname!=0); +} + +void +expandline() +{ + int i=0,j=0,k,j1; + for(i=0;i<128&&j<128;i++) + { + if(inpline[i]=='\n') { + srcline[j]=0;break; + } + if(inpline[i]=='\t') { + j1=j; + for(k=0;k<8-j1%8 && j<128;k++)srcline[j++]=' '; + }else srcline[j++]=inpline[i]; + } + srcline[127]=0; +} + + +void +processfile(char *name) +{ + char *oldname; + int oldno; + FILE *srcfile; + oldname=curname; + curname=name; + oldno=lineno; + lineno=0; + if((srcfile=fopen(name,"r"))==0) { + int i = strlen(oldname); + while(i>0 && oldname[i]!='/') i--; + if (i>0) { + char *next = strconcat(oldname,i+1,name); + if((srcfile=fopen(next,"r"))==0) { + fprintf(stderr,"Cannot open source file %s\n",next); + exit(4); + } + curname = next; + } else { + fprintf(stderr,"Cannot open source file %s\n",name); + exit(4); + } + } + while(!terminate&&fgets(inpline,128,srcfile)) { + expandline(); + lineno++; + srcptr=srcline; + if(suppress)suppressline(); else processline(); + } + fclose(srcfile); + if(suppress) { + fprintf(stderr,"improperly nested IF statements in %s",curname); + errors++; + suppress=0; + } + lineno=oldno; + curname=oldname; +} + +int +main(int argc,char *argv[]) +{ + char c; + getoptions(argc,argv); + pass=1; + errors=0; + generating=0; + terminate=0; + processfile(srcname); + if(errors) { + fprintf(stderr,"%d Pass 1 Errors, Continue?",errors); + c=getchar(); + if(c=='n'||c=='N') exit(3); + } + pass=2; + loccounter=0; + errors=0; + generating=0; + terminate=0; + if(listing&&((listfile=fopen(listname,"w"))==0)) { + fprintf(stderr,"Cannot open list file"); + exit(4); + } + if((objfile=fopen(objname,outmode?"w":"wb"))==0) { + fprintf(stderr,"Cannot write object file\n"); + exit(4); + } + processfile(srcname); + fprintf(stderr,"%d Pass 2 errors.\n",errors); + if(listing) { + fprintf(listfile,"%d Pass 2 errors.\n",errors); + outsymtable(); + fclose(listfile); + } + if(outmode){ + flushhex(); + fprintf(objfile,"S9030000FC\n"); + } + fclose(objfile); + return 0; +} + diff -r 000000000000 -r 9a224bd9b45f engine.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/engine.c Mon Jul 02 02:12:31 2018 +0900 @@ -0,0 +1,1170 @@ +/* 6809 Simulator V09. + + created 1994,1995 by L.C. Benschop. + copyleft (c) 1994-2014 by the sbc09 team, see AUTHORS for more details. + license: GNU General Public License version 2, see LICENSE for more details. + + This program simulates a 6809 processor. + + System dependencies: short must be 16 bits. + char must be 8 bits. + long must be more than 16 bits. + arrays up to 65536 bytes must be supported. + machine must be twos complement. + Most Unix machines will work. For MSODS you need long pointers + and you may have to malloc() the mem array of 65536 bytes. + + Special instructions: + SWI2 writes char to stdout from register B. + SWI3 reads char from stdout to register B, sets carry at EOF. + (or when no key available when using term control). + SWI retains its normal function. + CWAI and SYNC stop simulator. + Note: special instructions are gone for now. + + ACIA emulation at port $E000 + + Note: BIG_ENDIAN option is no longer needed. +*/ + +#include +#include + +#define engine +#include "v09.h" + +#define USLEEP 1000 +Byte aca,acb; +Byte *breg=&aca,*areg=&acb; +static int tracetrick=0; +extern int romstart; + +#define GETWORD(a) (mem[a]<<8|mem[(a)+1]) +#define SETBYTE(a,n) {if(!(a>=romstart))mem[a]=n;} +#define SETWORD(a,n) if(!(a>=romstart)){mem[a]=(n)>>8;mem[(a)+1]=n;} +/* Two bytes of a word are fetched separately because of + the possible wrap-around at address $ffff and alignment +*/ + +#define IMMBYTE(b) b=mem[ipcreg++]; +#define IMMWORD(w) {w=GETWORD(ipcreg);ipcreg+=2;} + +#define PUSHBYTE(b) {--isreg;SETBYTE(isreg,b)} +#define PUSHWORD(w) {isreg-=2;SETWORD(isreg,w)} +#define PULLBYTE(b) b=mem[isreg++]; +#define PULLWORD(w) {w=GETWORD(isreg);isreg+=2;} +#define PSHUBYTE(b) {--iureg;SETBYTE(iureg,b)} +#define PSHUWORD(w) {iureg-=2;SETWORD(iureg,w)} +#define PULUBYTE(b) b=mem[iureg++]; +#define PULUWORD(w) {w=GETWORD(iureg);iureg+=2;} + +#define SIGNED(b) ((Word)(b&0x80?b|0xff00:b)) + +#define GETDREG ((iareg<<8)|ibreg) +#define SETDREG(n) {iareg=(n)>>8;ibreg=(n);} + +/* Macros for addressing modes (postbytes have their own code) */ +#define DIRECT {IMMBYTE(eaddr) eaddr|=(idpreg<<8);} +#define IMM8 {eaddr=ipcreg++;} +#define IMM16 {eaddr=ipcreg;ipcreg+=2;} +#define EXTENDED {IMMWORD(eaddr)} + +/* macros to set status flags */ +#define SEC iccreg|=0x01; +#define CLC iccreg&=0xfe; +#define SEZ iccreg|=0x04; +#define CLZ iccreg&=0xfb; +#define SEN iccreg|=0x08; +#define CLN iccreg&=0xf7; +#define SEV iccreg|=0x02; +#define CLV iccreg&=0xfd; +#define SEH iccreg|=0x20; +#define CLH iccreg&=0xdf; + +/* set N and Z flags depending on 8 or 16 bit result */ +#define SETNZ8(b) {if(b)CLZ else SEZ if(b&0x80)SEN else CLN} +#define SETNZ16(b) {if(b)CLZ else SEZ if(b&0x8000)SEN else CLN} + +#define SETSTATUS(a,b,res) if((a^b^res)&0x10) SEH else CLH \ + if((a^b^res^(res>>1))&0x80)SEV else CLV \ + if(res&0x100)SEC else CLC SETNZ8((Byte)res) + +#define SETSTATUSD(a,b,res) {if(res&0x10000) SEC else CLC \ + if(((res>>1)^a^b^res)&0x8000) SEV else CLV \ + SETNZ16((Word)res)} + +/* Macros for branch instructions */ +#define BRANCH(f) if(!iflag){IMMBYTE(tb) if(f)ipcreg+=SIGNED(tb);}\ + else{IMMWORD(tw) if(f)ipcreg+=tw;} +#define NXORV ((iccreg&0x08)^((iccreg&0x02)<<2)) + +/* MAcros for setting/getting registers in TFR/EXG instructions */ +#define GETREG(val,reg) switch(reg) {\ + case 0: val=GETDREG;break;\ + case 1: val=ixreg;break;\ + case 2: val=iyreg;break;\ + case 3: val=iureg;break;\ + case 4: val=isreg;break;\ + case 5: val=ipcreg;break;\ + case 8: val=iareg;break;\ + case 9: val=ibreg;break;\ + case 10: val=iccreg;break;\ + case 11: val=idpreg;break;} + +#define SETREG(val,reg) switch(reg) {\ + case 0: SETDREG(val) break;\ + case 1: ixreg=val;break;\ + case 2: iyreg=val;break;\ + case 3: iureg=val;break;\ + case 4: isreg=val;break;\ + case 5: ipcreg=val;break;\ + case 8: iareg=val;break;\ + case 9: ibreg=val;break;\ + case 10: iccreg=val;break;\ + case 11: idpreg=val;break;} + +/* Macros for load and store of accumulators. Can be modified to check + for port addresses */ +#define LOADAC(reg) if((eaddr&0xff00)!=IOPAGE)reg=mem[eaddr];else\ + reg=do_input(eaddr&0xff); +#define STOREAC(reg) if((eaddr&0xff00)!=IOPAGE)SETBYTE(eaddr,reg)else\ + do_output(eaddr&0xff,reg); + +#define LOADREGS ixreg=xreg;iyreg=yreg;\ + iureg=ureg;isreg=sreg;\ + ipcreg=pcreg;\ + iareg=*areg;ibreg=*breg;\ + idpreg=dpreg;iccreg=ccreg; + +#define SAVEREGS xreg=ixreg;yreg=iyreg;\ + ureg=iureg;sreg=isreg;\ + pcreg=ipcreg;\ + *areg=iareg;*breg=ibreg;\ + dpreg=idpreg;ccreg=iccreg; + + +unsigned char haspostbyte[] = { + /*0*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + /*1*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + /*2*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + /*3*/ 1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0, + /*4*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + /*5*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + /*6*/ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + /*7*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + /*8*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + /*9*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + /*A*/ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + /*B*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + /*C*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + /*D*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + /*E*/ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + /*F*/ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + }; + +void interpr(void) +{ + Word ixreg,iyreg,iureg,isreg,ipcreg; + Byte idpreg,iccreg,iareg,ibreg; + /* Make local variables for the registers. On a real processor (non-Intel) + these could be implemented as fast registers. */ + Word eaddr; /* effective address */ + Byte ireg; /* instruction register */ + Byte iflag; /* flag to indicate $10 or $11 prebyte */ + Byte tb;Word tw; + LOADREGS + for(;;){ + if(attention) { + if(tracing && ipcreg>=tracelo && ipcreg<=tracehi) + {SAVEREGS do_trace(tracefile); } + if(escape){ SAVEREGS do_escape(); LOADREGS } + if(irq) { + if(irq==1&&!(iccreg&0x10)) { /* standard IRQ */ + PUSHWORD(ipcreg) + PUSHWORD(iureg) + PUSHWORD(iyreg) + PUSHWORD(ixreg) + PUSHBYTE(idpreg) + PUSHBYTE(ibreg) + PUSHBYTE(iareg) + PUSHBYTE(iccreg) + iccreg|=0x90; + ipcreg=GETWORD(0xfff8); + } + if(irq==2&&!(iccreg&0x40)) { /* Fast IRQ */ + PUSHWORD(ipcreg) + PUSHBYTE(iccreg) + iccreg&=0x7f; + iccreg|=0x50; + ipcreg=GETWORD(0xfff6); + } + if(!tracing)attention=0; + irq=0; + } + } + iflag=0; + flaginstr: /* $10 and $11 instructions return here */ + ireg=mem[ipcreg++]; + if(haspostbyte[ireg]) { + Byte postbyte=mem[ipcreg++]; + switch(postbyte) { + case 0x00: eaddr=ixreg;break; + case 0x01: eaddr=ixreg+1;break; + case 0x02: eaddr=ixreg+2;break; + case 0x03: eaddr=ixreg+3;break; + case 0x04: eaddr=ixreg+4;break; + case 0x05: eaddr=ixreg+5;break; + case 0x06: eaddr=ixreg+6;break; + case 0x07: eaddr=ixreg+7;break; + case 0x08: eaddr=ixreg+8;break; + case 0x09: eaddr=ixreg+9;break; + case 0x0A: eaddr=ixreg+10;break; + case 0x0B: eaddr=ixreg+11;break; + case 0x0C: eaddr=ixreg+12;break; + case 0x0D: eaddr=ixreg+13;break; + case 0x0E: eaddr=ixreg+14;break; + case 0x0F: eaddr=ixreg+15;break; + case 0x10: eaddr=ixreg-16;break; + case 0x11: eaddr=ixreg-15;break; + case 0x12: eaddr=ixreg-14;break; + case 0x13: eaddr=ixreg-13;break; + case 0x14: eaddr=ixreg-12;break; + case 0x15: eaddr=ixreg-11;break; + case 0x16: eaddr=ixreg-10;break; + case 0x17: eaddr=ixreg-9;break; + case 0x18: eaddr=ixreg-8;break; + case 0x19: eaddr=ixreg-7;break; + case 0x1A: eaddr=ixreg-6;break; + case 0x1B: eaddr=ixreg-5;break; + case 0x1C: eaddr=ixreg-4;break; + case 0x1D: eaddr=ixreg-3;break; + case 0x1E: eaddr=ixreg-2;break; + case 0x1F: eaddr=ixreg-1;break; + case 0x20: eaddr=iyreg;break; + case 0x21: eaddr=iyreg+1;break; + case 0x22: eaddr=iyreg+2;break; + case 0x23: eaddr=iyreg+3;break; + case 0x24: eaddr=iyreg+4;break; + case 0x25: eaddr=iyreg+5;break; + case 0x26: eaddr=iyreg+6;break; + case 0x27: eaddr=iyreg+7;break; + case 0x28: eaddr=iyreg+8;break; + case 0x29: eaddr=iyreg+9;break; + case 0x2A: eaddr=iyreg+10;break; + case 0x2B: eaddr=iyreg+11;break; + case 0x2C: eaddr=iyreg+12;break; + case 0x2D: eaddr=iyreg+13;break; + case 0x2E: eaddr=iyreg+14;break; + case 0x2F: eaddr=iyreg+15;break; + case 0x30: eaddr=iyreg-16;break; + case 0x31: eaddr=iyreg-15;break; + case 0x32: eaddr=iyreg-14;break; + case 0x33: eaddr=iyreg-13;break; + case 0x34: eaddr=iyreg-12;break; + case 0x35: eaddr=iyreg-11;break; + case 0x36: eaddr=iyreg-10;break; + case 0x37: eaddr=iyreg-9;break; + case 0x38: eaddr=iyreg-8;break; + case 0x39: eaddr=iyreg-7;break; + case 0x3A: eaddr=iyreg-6;break; + case 0x3B: eaddr=iyreg-5;break; + case 0x3C: eaddr=iyreg-4;break; + case 0x3D: eaddr=iyreg-3;break; + case 0x3E: eaddr=iyreg-2;break; + case 0x3F: eaddr=iyreg-1;break; + case 0x40: eaddr=iureg;break; + case 0x41: eaddr=iureg+1;break; + case 0x42: eaddr=iureg+2;break; + case 0x43: eaddr=iureg+3;break; + case 0x44: eaddr=iureg+4;break; + case 0x45: eaddr=iureg+5;break; + case 0x46: eaddr=iureg+6;break; + case 0x47: eaddr=iureg+7;break; + case 0x48: eaddr=iureg+8;break; + case 0x49: eaddr=iureg+9;break; + case 0x4A: eaddr=iureg+10;break; + case 0x4B: eaddr=iureg+11;break; + case 0x4C: eaddr=iureg+12;break; + case 0x4D: eaddr=iureg+13;break; + case 0x4E: eaddr=iureg+14;break; + case 0x4F: eaddr=iureg+15;break; + case 0x50: eaddr=iureg-16;break; + case 0x51: eaddr=iureg-15;break; + case 0x52: eaddr=iureg-14;break; + case 0x53: eaddr=iureg-13;break; + case 0x54: eaddr=iureg-12;break; + case 0x55: eaddr=iureg-11;break; + case 0x56: eaddr=iureg-10;break; + case 0x57: eaddr=iureg-9;break; + case 0x58: eaddr=iureg-8;break; + case 0x59: eaddr=iureg-7;break; + case 0x5A: eaddr=iureg-6;break; + case 0x5B: eaddr=iureg-5;break; + case 0x5C: eaddr=iureg-4;break; + case 0x5D: eaddr=iureg-3;break; + case 0x5E: eaddr=iureg-2;break; + case 0x5F: eaddr=iureg-1;break; + case 0x60: eaddr=isreg;break; + case 0x61: eaddr=isreg+1;break; + case 0x62: eaddr=isreg+2;break; + case 0x63: eaddr=isreg+3;break; + case 0x64: eaddr=isreg+4;break; + case 0x65: eaddr=isreg+5;break; + case 0x66: eaddr=isreg+6;break; + case 0x67: eaddr=isreg+7;break; + case 0x68: eaddr=isreg+8;break; + case 0x69: eaddr=isreg+9;break; + case 0x6A: eaddr=isreg+10;break; + case 0x6B: eaddr=isreg+11;break; + case 0x6C: eaddr=isreg+12;break; + case 0x6D: eaddr=isreg+13;break; + case 0x6E: eaddr=isreg+14;break; + case 0x6F: eaddr=isreg+15;break; + case 0x70: eaddr=isreg-16;break; + case 0x71: eaddr=isreg-15;break; + case 0x72: eaddr=isreg-14;break; + case 0x73: eaddr=isreg-13;break; + case 0x74: eaddr=isreg-12;break; + case 0x75: eaddr=isreg-11;break; + case 0x76: eaddr=isreg-10;break; + case 0x77: eaddr=isreg-9;break; + case 0x78: eaddr=isreg-8;break; + case 0x79: eaddr=isreg-7;break; + case 0x7A: eaddr=isreg-6;break; + case 0x7B: eaddr=isreg-5;break; + case 0x7C: eaddr=isreg-4;break; + case 0x7D: eaddr=isreg-3;break; + case 0x7E: eaddr=isreg-2;break; + case 0x7F: eaddr=isreg-1;break; + case 0x80: eaddr=ixreg;ixreg++;break; + case 0x81: eaddr=ixreg;ixreg+=2;break; + case 0x82: ixreg--;eaddr=ixreg;break; + case 0x83: ixreg-=2;eaddr=ixreg;break; + case 0x84: eaddr=ixreg;break; + case 0x85: eaddr=ixreg+SIGNED(ibreg);break; + case 0x86: eaddr=ixreg+SIGNED(iareg);break; + case 0x87: eaddr=0;break; /*ILELGAL*/ + case 0x88: IMMBYTE(eaddr);eaddr=ixreg+SIGNED(eaddr);break; + case 0x89: IMMWORD(eaddr);eaddr+=ixreg;break; + case 0x8A: eaddr=0;break; /*ILLEGAL*/ + case 0x8B: eaddr=ixreg+GETDREG;break; + case 0x8C: IMMBYTE(eaddr);eaddr=ipcreg+SIGNED(eaddr);break; + case 0x8D: IMMWORD(eaddr);eaddr+=ipcreg;break; + case 0x8E: eaddr=0;break; /*ILLEGAL*/ + case 0x8F: IMMWORD(eaddr);break; + case 0x90: eaddr=ixreg;ixreg++;eaddr=GETWORD(eaddr);break; + case 0x91: eaddr=ixreg;ixreg+=2;eaddr=GETWORD(eaddr);break; + case 0x92: ixreg--;eaddr=ixreg;eaddr=GETWORD(eaddr);break; + case 0x93: ixreg-=2;eaddr=ixreg;eaddr=GETWORD(eaddr);break; + case 0x94: eaddr=ixreg;eaddr=GETWORD(eaddr);break; + case 0x95: eaddr=ixreg+SIGNED(ibreg);eaddr=GETWORD(eaddr);break; + case 0x96: eaddr=ixreg+SIGNED(iareg);eaddr=GETWORD(eaddr);break; + case 0x97: eaddr=0;break; /*ILELGAL*/ + case 0x98: IMMBYTE(eaddr);eaddr=ixreg+SIGNED(eaddr); + eaddr=GETWORD(eaddr);break; + case 0x99: IMMWORD(eaddr);eaddr+=ixreg;eaddr=GETWORD(eaddr);break; + case 0x9A: eaddr=0;break; /*ILLEGAL*/ + case 0x9B: eaddr=ixreg+GETDREG;eaddr=GETWORD(eaddr);break; + case 0x9C: IMMBYTE(eaddr);eaddr=ipcreg+SIGNED(eaddr); + eaddr=GETWORD(eaddr);break; + case 0x9D: IMMWORD(eaddr);eaddr+=ipcreg;eaddr=GETWORD(eaddr);break; + case 0x9E: eaddr=0;break; /*ILLEGAL*/ + case 0x9F: IMMWORD(eaddr);eaddr=GETWORD(eaddr);break; + case 0xA0: eaddr=iyreg;iyreg++;break; + case 0xA1: eaddr=iyreg;iyreg+=2;break; + case 0xA2: iyreg--;eaddr=iyreg;break; + case 0xA3: iyreg-=2;eaddr=iyreg;break; + case 0xA4: eaddr=iyreg;break; + case 0xA5: eaddr=iyreg+SIGNED(ibreg);break; + case 0xA6: eaddr=iyreg+SIGNED(iareg);break; + case 0xA7: eaddr=0;break; /*ILELGAL*/ + case 0xA8: IMMBYTE(eaddr);eaddr=iyreg+SIGNED(eaddr);break; + case 0xA9: IMMWORD(eaddr);eaddr+=iyreg;break; + case 0xAA: eaddr=0;break; /*ILLEGAL*/ + case 0xAB: eaddr=iyreg+GETDREG;break; + case 0xAC: IMMBYTE(eaddr);eaddr=ipcreg+SIGNED(eaddr);break; + case 0xAD: IMMWORD(eaddr);eaddr+=ipcreg;break; + case 0xAE: eaddr=0;break; /*ILLEGAL*/ + case 0xAF: IMMWORD(eaddr);break; + case 0xB0: eaddr=iyreg;iyreg++;eaddr=GETWORD(eaddr);break; + case 0xB1: eaddr=iyreg;iyreg+=2;eaddr=GETWORD(eaddr);break; + case 0xB2: iyreg--;eaddr=iyreg;eaddr=GETWORD(eaddr);break; + case 0xB3: iyreg-=2;eaddr=iyreg;eaddr=GETWORD(eaddr);break; + case 0xB4: eaddr=iyreg;eaddr=GETWORD(eaddr);break; + case 0xB5: eaddr=iyreg+SIGNED(ibreg);eaddr=GETWORD(eaddr);break; + case 0xB6: eaddr=iyreg+SIGNED(iareg);eaddr=GETWORD(eaddr);break; + case 0xB7: eaddr=0;break; /*ILELGAL*/ + case 0xB8: IMMBYTE(eaddr);eaddr=iyreg+SIGNED(eaddr); + eaddr=GETWORD(eaddr);break; + case 0xB9: IMMWORD(eaddr);eaddr+=iyreg;eaddr=GETWORD(eaddr);break; + case 0xBA: eaddr=0;break; /*ILLEGAL*/ + case 0xBB: eaddr=iyreg+GETDREG;eaddr=GETWORD(eaddr);break; + case 0xBC: IMMBYTE(eaddr);eaddr=ipcreg+SIGNED(eaddr); + eaddr=GETWORD(eaddr);break; + case 0xBD: IMMWORD(eaddr);eaddr+=ipcreg;eaddr=GETWORD(eaddr);break; + case 0xBE: eaddr=0;break; /*ILLEGAL*/ + case 0xBF: IMMWORD(eaddr);eaddr=GETWORD(eaddr);break; + case 0xC0: eaddr=iureg;iureg++;break; + case 0xC1: eaddr=iureg;iureg+=2;break; + case 0xC2: iureg--;eaddr=iureg;break; + case 0xC3: iureg-=2;eaddr=iureg;break; + case 0xC4: eaddr=iureg;break; + case 0xC5: eaddr=iureg+SIGNED(ibreg);break; + case 0xC6: eaddr=iureg+SIGNED(iareg);break; + case 0xC7: eaddr=0;break; /*ILELGAL*/ + case 0xC8: IMMBYTE(eaddr);eaddr=iureg+SIGNED(eaddr);break; + case 0xC9: IMMWORD(eaddr);eaddr+=iureg;break; + case 0xCA: eaddr=0;break; /*ILLEGAL*/ + case 0xCB: eaddr=iureg+GETDREG;break; + case 0xCC: IMMBYTE(eaddr);eaddr=ipcreg+SIGNED(eaddr);break; + case 0xCD: IMMWORD(eaddr);eaddr+=ipcreg;break; + case 0xCE: eaddr=0;break; /*ILLEGAL*/ + case 0xCF: IMMWORD(eaddr);break; + case 0xD0: eaddr=iureg;iureg++;eaddr=GETWORD(eaddr);break; + case 0xD1: eaddr=iureg;iureg+=2;eaddr=GETWORD(eaddr);break; + case 0xD2: iureg--;eaddr=iureg;eaddr=GETWORD(eaddr);break; + case 0xD3: iureg-=2;eaddr=iureg;eaddr=GETWORD(eaddr);break; + case 0xD4: eaddr=iureg;eaddr=GETWORD(eaddr);break; + case 0xD5: eaddr=iureg+SIGNED(ibreg);eaddr=GETWORD(eaddr);break; + case 0xD6: eaddr=iureg+SIGNED(iareg);eaddr=GETWORD(eaddr);break; + case 0xD7: eaddr=0;break; /*ILELGAL*/ + case 0xD8: IMMBYTE(eaddr);eaddr=iureg+SIGNED(eaddr); + eaddr=GETWORD(eaddr);break; + case 0xD9: IMMWORD(eaddr);eaddr+=iureg;eaddr=GETWORD(eaddr);break; + case 0xDA: eaddr=0;break; /*ILLEGAL*/ + case 0xDB: eaddr=iureg+GETDREG;eaddr=GETWORD(eaddr);break; + case 0xDC: IMMBYTE(eaddr);eaddr=ipcreg+SIGNED(eaddr); + eaddr=GETWORD(eaddr);break; + case 0xDD: IMMWORD(eaddr);eaddr+=ipcreg;eaddr=GETWORD(eaddr);break; + case 0xDE: eaddr=0;break; /*ILLEGAL*/ + case 0xDF: IMMWORD(eaddr);eaddr=GETWORD(eaddr);break; + case 0xE0: eaddr=isreg;isreg++;break; + case 0xE1: eaddr=isreg;isreg+=2;break; + case 0xE2: isreg--;eaddr=isreg;break; + case 0xE3: isreg-=2;eaddr=isreg;break; + case 0xE4: eaddr=isreg;break; + case 0xE5: eaddr=isreg+SIGNED(ibreg);break; + case 0xE6: eaddr=isreg+SIGNED(iareg);break; + case 0xE7: eaddr=0;break; /*ILELGAL*/ + case 0xE8: IMMBYTE(eaddr);eaddr=isreg+SIGNED(eaddr);break; + case 0xE9: IMMWORD(eaddr);eaddr+=isreg;break; + case 0xEA: eaddr=0;break; /*ILLEGAL*/ + case 0xEB: eaddr=isreg+GETDREG;break; + case 0xEC: IMMBYTE(eaddr);eaddr=ipcreg+SIGNED(eaddr);break; + case 0xED: IMMWORD(eaddr);eaddr+=ipcreg;break; + case 0xEE: eaddr=0;break; /*ILLEGAL*/ + case 0xEF: IMMWORD(eaddr);break; + case 0xF0: eaddr=isreg;isreg++;eaddr=GETWORD(eaddr);break; + case 0xF1: eaddr=isreg;isreg+=2;eaddr=GETWORD(eaddr);break; + case 0xF2: isreg--;eaddr=isreg;eaddr=GETWORD(eaddr);break; + case 0xF3: isreg-=2;eaddr=isreg;eaddr=GETWORD(eaddr);break; + case 0xF4: eaddr=isreg;eaddr=GETWORD(eaddr);break; + case 0xF5: eaddr=isreg+SIGNED(ibreg);eaddr=GETWORD(eaddr);break; + case 0xF6: eaddr=isreg+SIGNED(iareg);eaddr=GETWORD(eaddr);break; + case 0xF7: eaddr=0;break; /*ILELGAL*/ + case 0xF8: IMMBYTE(eaddr);eaddr=isreg+SIGNED(eaddr); + eaddr=GETWORD(eaddr);break; + case 0xF9: IMMWORD(eaddr);eaddr+=isreg;eaddr=GETWORD(eaddr);break; + case 0xFA: eaddr=0;break; /*ILLEGAL*/ + case 0xFB: eaddr=isreg+GETDREG;eaddr=GETWORD(eaddr);break; + case 0xFC: IMMBYTE(eaddr);eaddr=ipcreg+SIGNED(eaddr); + eaddr=GETWORD(eaddr);break; + case 0xFD: IMMWORD(eaddr);eaddr+=ipcreg;eaddr=GETWORD(eaddr);break; + case 0xFE: eaddr=0;break; /*ILLEGAL*/ + case 0xFF: IMMWORD(eaddr);eaddr=GETWORD(eaddr);break; + } + } + switch(ireg) { + case 0x00: /*NEG direct*/ DIRECT tw=-mem[eaddr];SETSTATUS(0,mem[eaddr],tw) + SETBYTE(eaddr,tw)break; + case 0x01: break;/*ILLEGAL*/ + case 0x02: break;/*ILLEGAL*/ + case 0x03: /*COM direct*/ DIRECT tb=~mem[eaddr];SETNZ8(tb);SEC CLV + SETBYTE(eaddr,tb)break; + case 0x04: /*LSR direct*/ DIRECT tb=mem[eaddr];if(tb&0x01)SEC else CLC + if(tb&0x10)SEH else CLH tb>>=1;SETNZ8(tb) + SETBYTE(eaddr,tb)break; + case 0x05: break;/* ILLEGAL*/ + case 0x06: /*ROR direct*/ DIRECT tb=(iccreg&0x01)<<7; + if(mem[eaddr]&0x01)SEC else CLC + tw=(mem[eaddr]>>1)+tb;SETNZ8(tw) + SETBYTE(eaddr,tw) + break; + case 0x07: /*ASR direct*/ DIRECT tb=mem[eaddr];if(tb&0x01)SEC else CLC + if(tb&0x10)SEH else CLH tb>>=1; + if(tb&0x40)tb|=0x80;SETBYTE(eaddr,tb)SETNZ8(tb) + break; + case 0x08: /*ASL direct*/ DIRECT tw=mem[eaddr]<<1; + SETSTATUS(mem[eaddr],mem[eaddr],tw) + SETBYTE(eaddr,tw)break; + case 0x09: /*ROL direct*/ DIRECT tb=mem[eaddr];tw=iccreg&0x01; + if(tb&0x80)SEC else CLC + if((tb&0x80)^((tb<<1)&0x80))SEV else CLV + tb=(tb<<1)+tw;SETNZ8(tb) SETBYTE(eaddr,tb)break; + case 0x0A: /*DEC direct*/ DIRECT tb=mem[eaddr]-1;if(tb==0x7F)SEV else CLV + SETNZ8(tb) SETBYTE(eaddr,tb)break; + case 0x0B: break; /*ILLEGAL*/ + case 0x0C: /*INC direct*/ DIRECT tb=mem[eaddr]+1;if(tb==0x80)SEV else CLV + SETNZ8(tb) SETBYTE(eaddr,tb)break; + case 0x0D: /*TST direct*/ DIRECT tb=mem[eaddr];SETNZ8(tb) break; + case 0x0E: /*JMP direct*/ DIRECT ipcreg=eaddr;break; + case 0x0F: /*CLR direct*/ DIRECT SETBYTE(eaddr,0);CLN CLV SEZ CLC break; + case 0x10: /* flag10 */ iflag=1;goto flaginstr; + case 0x11: /* flag11 */ iflag=2;goto flaginstr; + case 0x12: /* NOP */ break; + case 0x13: /* SYNC */ + do usleep(USLEEP); /* Wait for IRQ */ + while(!irq && !attention); + if(iccreg&0x40)tracetrick=1; + break; + case 0x14: break; /*ILLEGAL*/ + case 0x15: break; /*ILLEGAL*/ + case 0x16: /*LBRA*/ IMMWORD(eaddr) ipcreg+=eaddr;break; + case 0x17: /*LBSR*/ IMMWORD(eaddr) PUSHWORD(ipcreg) ipcreg+=eaddr;break; + case 0x18: break; /*ILLEGAL*/ + case 0x19: /* DAA*/ tw=iareg; + if(iccreg&0x20)tw+=6; + if((tw&0x0f)>9)tw+=6; + if(iccreg&0x01)tw+=0x60; + if((tw&0xf0)>0x90)tw+=0x60; + if(tw&0x100)SEC + iareg=tw;break; + case 0x1A: /* ORCC*/ IMMBYTE(tb) iccreg|=tb;break; + case 0x1B: break; /*ILLEGAL*/ + case 0x1C: /* ANDCC*/ IMMBYTE(tb) iccreg&=tb;break; + case 0x1D: /* SEX */ tw=SIGNED(ibreg); SETNZ16(tw) SETDREG(tw) break; + case 0x1E: /* EXG */ IMMBYTE(tb) {Word t2;GETREG(tw,tb>>4) GETREG(t2,tb&15) + SETREG(t2,tb>>4) SETREG(tw,tb&15) } break; + case 0x1F: /* TFR */ IMMBYTE(tb) GETREG(tw,tb>>4) SETREG(tw,tb&15) break; + case 0x20: /* (L)BRA*/ BRANCH(1) break; + case 0x21: /* (L)BRN*/ BRANCH(0) break; + case 0x22: /* (L)BHI*/ BRANCH(!(iccreg&0x05)) break; + case 0x23: /* (L)BLS*/ BRANCH(iccreg&0x05) break; + case 0x24: /* (L)BCC*/ BRANCH(!(iccreg&0x01)) break; + case 0x25: /* (L)BCS*/ BRANCH(iccreg&0x01) break; + case 0x26: /* (L)BNE*/ BRANCH(!(iccreg&0x04)) break; + case 0x27: /* (L)BEQ*/ BRANCH(iccreg&0x04) break; + case 0x28: /* (L)BVC*/ BRANCH(!(iccreg&0x02)) break; + case 0x29: /* (L)BVS*/ BRANCH(iccreg&0x02) break; + case 0x2A: /* (L)BPL*/ BRANCH(!(iccreg&0x08)) break; + case 0x2B: /* (L)BMI*/ BRANCH(iccreg&0x08) break; + case 0x2C: /* (L)BGE*/ BRANCH(!NXORV) break; + case 0x2D: /* (L)BLT*/ BRANCH(NXORV) break; + case 0x2E: /* (L)BGT*/ BRANCH(!(NXORV||iccreg&0x04)) break; + case 0x2F: /* (L)BLE*/ BRANCH(NXORV||iccreg&0x04) break; + case 0x30: /* LEAX*/ ixreg=eaddr; if(ixreg) CLZ else SEZ break; + case 0x31: /* LEAY*/ iyreg=eaddr; if(iyreg) CLZ else SEZ break; + case 0x32: /* LEAS*/ isreg=eaddr;break; + case 0x33: /* LEAU*/ iureg=eaddr;break; + case 0x34: /* PSHS*/ IMMBYTE(tb) + if(tb&0x80)PUSHWORD(ipcreg) + if(tb&0x40)PUSHWORD(iureg) + if(tb&0x20)PUSHWORD(iyreg) + if(tb&0x10)PUSHWORD(ixreg) + if(tb&0x08)PUSHBYTE(idpreg) + if(tb&0x04)PUSHBYTE(ibreg) + if(tb&0x02)PUSHBYTE(iareg) + if(tb&0x01)PUSHBYTE(iccreg) break; + case 0x35: /* PULS*/ IMMBYTE(tb) + if(tb&0x01)PULLBYTE(iccreg) + if(tb&0x02)PULLBYTE(iareg) + if(tb&0x04)PULLBYTE(ibreg) + if(tb&0x08)PULLBYTE(idpreg) + if(tb&0x10)PULLWORD(ixreg) + if(tb&0x20)PULLWORD(iyreg) + if(tb&0x40)PULLWORD(iureg) + if(tb&0x80)PULLWORD(ipcreg) + if(tracetrick&&tb==0xff) { /* Arrange fake FIRQ after next insn + for hardware tracing */ + tracetrick=0; + irq=2; + attention=1; + goto flaginstr; + } + break; + case 0x36: /* PSHU*/ IMMBYTE(tb) + if(tb&0x80)PSHUWORD(ipcreg) + if(tb&0x40)PSHUWORD(isreg) + if(tb&0x20)PSHUWORD(iyreg) + if(tb&0x10)PSHUWORD(ixreg) + if(tb&0x08)PSHUBYTE(idpreg) + if(tb&0x04)PSHUBYTE(ibreg) + if(tb&0x02)PSHUBYTE(iareg) + if(tb&0x01)PSHUBYTE(iccreg) break; + case 0x37: /* PULU*/ IMMBYTE(tb) + if(tb&0x01)PULUBYTE(iccreg) + if(tb&0x02)PULUBYTE(iareg) + if(tb&0x04)PULUBYTE(ibreg) + if(tb&0x08)PULUBYTE(idpreg) + if(tb&0x10)PULUWORD(ixreg) + if(tb&0x20)PULUWORD(iyreg) + if(tb&0x40)PULUWORD(isreg) + if(tb&0x80)PULUWORD(ipcreg) break; + case 0x39: /* RTS*/ PULLWORD(ipcreg) break; + case 0x3A: /* ABX*/ ixreg+=ibreg; break; + case 0x3B: /* RTI*/ tb=iccreg&0x80; + PULLBYTE(iccreg) + if(tb) + { + PULLBYTE(iareg) + PULLBYTE(ibreg) + PULLBYTE(idpreg) + PULLWORD(ixreg) + PULLWORD(iyreg) + PULLWORD(iureg) + } + PULLWORD(ipcreg) break; + case 0x3C: /* CWAI*/ IMMBYTE(tb) + PUSHWORD(ipcreg) + PUSHWORD(iureg) + PUSHWORD(iyreg) + PUSHWORD(ixreg) + PUSHBYTE(idpreg) + PUSHBYTE(ibreg) + PUSHBYTE(iareg) + PUSHBYTE(iccreg) + iccreg&=tb; + iccreg|=0x80; + do usleep(USLEEP); /* Wait for IRQ */ + while(!attention && !((irq==1&&!(iccreg&0x10))||(irq==2&&!(iccreg&0x040)))); + if(irq==1)ipcreg=GETWORD(0xfff8); + else ipcreg=GETWORD(0xfff6); + irq=0; + if(!tracing)attention=0; + break; + case 0x3D: /* MUL*/ tw=iareg*ibreg; if(tw)CLZ else SEZ + if(tw&0x80) SEC else CLC SETDREG(tw) break; + case 0x3E: break; /*ILLEGAL*/ + case 0x3F: /* SWI (SWI2 SWI3)*/ { + PUSHWORD(ipcreg) + PUSHWORD(iureg) + PUSHWORD(iyreg) + PUSHWORD(ixreg) + PUSHBYTE(idpreg) + PUSHBYTE(ibreg) + PUSHBYTE(iareg) + PUSHBYTE(iccreg) + iccreg|=0x80; + if(!iflag)iccreg|=0x50; + switch(iflag) { + case 0:ipcreg=GETWORD(0xfffa);break; + case 1:ipcreg=GETWORD(0xfff4);break; + case 2:ipcreg=GETWORD(0xfff2);break; + } + }break; + case 0x40: /*NEGA*/ tw=-iareg;SETSTATUS(0,iareg,tw) + iareg=tw;break; + case 0x41: break;/*ILLEGAL*/ + case 0x42: break;/*ILLEGAL*/ + case 0x43: /*COMA*/ tb=~iareg;SETNZ8(tb);SEC CLV + iareg=tb;break; + case 0x44: /*LSRA*/ tb=iareg;if(tb&0x01)SEC else CLC + if(tb&0x10)SEH else CLH tb>>=1;SETNZ8(tb) + iareg=tb;break; + case 0x45: break;/* ILLEGAL*/ + case 0x46: /*RORA*/ tb=(iccreg&0x01)<<7; + if(iareg&0x01)SEC else CLC + iareg=(iareg>>1)+tb;SETNZ8(iareg) + break; + case 0x47: /*ASRA*/ tb=iareg;if(tb&0x01)SEC else CLC + if(tb&0x10)SEH else CLH tb>>=1; + if(tb&0x40)tb|=0x80;iareg=tb;SETNZ8(tb) + break; + case 0x48: /*ASLA*/ tw=iareg<<1; + SETSTATUS(iareg,iareg,tw) + iareg=tw;break; + case 0x49: /*ROLA*/ tb=iareg;tw=iccreg&0x01; + if(tb&0x80)SEC else CLC + if((tb&0x80)^((tb<<1)&0x80))SEV else CLV + tb=(tb<<1)+tw;SETNZ8(tb) iareg=tb;break; + case 0x4A: /*DECA*/ tb=iareg-1;if(tb==0x7F)SEV else CLV + SETNZ8(tb) iareg=tb;break; + case 0x4B: break; /*ILLEGAL*/ + case 0x4C: /*INCA*/ tb=iareg+1;if(tb==0x80)SEV else CLV + SETNZ8(tb) iareg=tb;break; + case 0x4D: /*TSTA*/ SETNZ8(iareg) break; + case 0x4E: break; /*ILLEGAL*/ + case 0x4F: /*CLRA*/ iareg=0;CLN CLV SEZ CLC break; + case 0x50: /*NEGB*/ tw=-ibreg;SETSTATUS(0,ibreg,tw) + ibreg=tw;break; + case 0x51: break;/*ILLEGAL*/ + case 0x52: break;/*ILLEGAL*/ + case 0x53: /*COMB*/ tb=~ibreg;SETNZ8(tb);SEC CLV + ibreg=tb;break; + case 0x54: /*LSRB*/ tb=ibreg;if(tb&0x01)SEC else CLC + if(tb&0x10)SEH else CLH tb>>=1;SETNZ8(tb) + ibreg=tb;break; + case 0x55: break;/* ILLEGAL*/ + case 0x56: /*RORB*/ tb=(iccreg&0x01)<<7; + if(ibreg&0x01)SEC else CLC + ibreg=(ibreg>>1)+tb;SETNZ8(ibreg) + break; + case 0x57: /*ASRB*/ tb=ibreg;if(tb&0x01)SEC else CLC + if(tb&0x10)SEH else CLH tb>>=1; + if(tb&0x40)tb|=0x80;ibreg=tb;SETNZ8(tb) + break; + case 0x58: /*ASLB*/ tw=ibreg<<1; + SETSTATUS(ibreg,ibreg,tw) + ibreg=tw;break; + case 0x59: /*ROLB*/ tb=ibreg;tw=iccreg&0x01; + if(tb&0x80)SEC else CLC + if((tb&0x80)^((tb<<1)&0x80))SEV else CLV + tb=(tb<<1)+tw;SETNZ8(tb) ibreg=tb;break; + case 0x5A: /*DECB*/ tb=ibreg-1;if(tb==0x7F)SEV else CLV + SETNZ8(tb) ibreg=tb;break; + case 0x5B: break; /*ILLEGAL*/ + case 0x5C: /*INCB*/ tb=ibreg+1;if(tb==0x80)SEV else CLV + SETNZ8(tb) ibreg=tb;break; + case 0x5D: /*TSTB*/ SETNZ8(ibreg) break; + case 0x5E: break; /*ILLEGAL*/ + case 0x5F: /*CLRB*/ ibreg=0;CLN CLV SEZ CLC break; + case 0x60: /*NEG indexed*/ tw=-mem[eaddr];SETSTATUS(0,mem[eaddr],tw) + SETBYTE(eaddr,tw)break; + case 0x61: break;/*ILLEGAL*/ + case 0x62: break;/*ILLEGAL*/ + case 0x63: /*COM indexed*/ tb=~mem[eaddr];SETNZ8(tb);SEC CLV + SETBYTE(eaddr,tb)break; + case 0x64: /*LSR indexed*/ tb=mem[eaddr];if(tb&0x01)SEC else CLC + if(tb&0x10)SEH else CLH tb>>=1;SETNZ8(tb) + SETBYTE(eaddr,tb)break; + case 0x65: break;/* ILLEGAL*/ + case 0x66: /*ROR indexed*/ tb=(iccreg&0x01)<<7; + if(mem[eaddr]&0x01)SEC else CLC + tw=(mem[eaddr]>>1)+tb;SETNZ8(tw) + SETBYTE(eaddr,tw) + break; + case 0x67: /*ASR indexed*/ tb=mem[eaddr];if(tb&0x01)SEC else CLC + if(tb&0x10)SEH else CLH tb>>=1; + if(tb&0x40)tb|=0x80;SETBYTE(eaddr,tb)SETNZ8(tb) + break; + case 0x68: /*ASL indexed*/ tw=mem[eaddr]<<1; + SETSTATUS(mem[eaddr],mem[eaddr],tw) + SETBYTE(eaddr,tw)break; + case 0x69: /*ROL indexed*/ tb=mem[eaddr];tw=iccreg&0x01; + if(tb&0x80)SEC else CLC + if((tb&0x80)^((tb<<1)&0x80))SEV else CLV + tb=(tb<<1)+tw;SETNZ8(tb) SETBYTE(eaddr,tb)break; + case 0x6A: /*DEC indexed*/ tb=mem[eaddr]-1;if(tb==0x7F)SEV else CLV + SETNZ8(tb) SETBYTE(eaddr,tb)break; + case 0x6B: break; /*ILLEGAL*/ + case 0x6C: /*INC indexed*/ tb=mem[eaddr]+1;if(tb==0x80)SEV else CLV + SETNZ8(tb) SETBYTE(eaddr,tb)break; + case 0x6D: /*TST indexed*/ tb=mem[eaddr];SETNZ8(tb) break; + case 0x6E: /*JMP indexed*/ ipcreg=eaddr;break; + case 0x6F: /*CLR indexed*/ SETBYTE(eaddr,0)CLN CLV SEZ CLC break; + case 0x70: /*NEG ext*/ EXTENDED tw=-mem[eaddr];SETSTATUS(0,mem[eaddr],tw) + SETBYTE(eaddr,tw)break; + case 0x71: break;/*ILLEGAL*/ + case 0x72: break;/*ILLEGAL*/ + case 0x73: /*COM ext*/ EXTENDED tb=~mem[eaddr];SETNZ8(tb);SEC CLV + SETBYTE(eaddr,tb)break; + case 0x74: /*LSR ext*/ EXTENDED tb=mem[eaddr];if(tb&0x01)SEC else CLC + if(tb&0x10)SEH else CLH tb>>=1;SETNZ8(tb) + SETBYTE(eaddr,tb)break; + case 0x75: break;/* ILLEGAL*/ + case 0x76: /*ROR ext*/ EXTENDED tb=(iccreg&0x01)<<7; + if(mem[eaddr]&0x01)SEC else CLC + tw=(mem[eaddr]>>1)+tb;SETNZ8(tw) + SETBYTE(eaddr,tw) + break; + case 0x77: /*ASR ext*/ EXTENDED tb=mem[eaddr];if(tb&0x01)SEC else CLC + if(tb&0x10)SEH else CLH tb>>=1; + if(tb&0x40)tb|=0x80;SETBYTE(eaddr,tb)SETNZ8(tb) + break; + case 0x78: /*ASL ext*/ EXTENDED tw=mem[eaddr]<<1; + SETSTATUS(mem[eaddr],mem[eaddr],tw) + SETBYTE(eaddr,tw)break; + case 0x79: /*ROL ext*/ EXTENDED tb=mem[eaddr];tw=iccreg&0x01; + if(tb&0x80)SEC else CLC + if((tb&0x80)^((tb<<1)&0x80))SEV else CLV + tb=(tb<<1)+tw;SETNZ8(tb) SETBYTE(eaddr,tb)break; + case 0x7A: /*DEC ext*/ EXTENDED tb=mem[eaddr]-1;if(tb==0x7F)SEV else CLV + SETNZ8(tb) SETBYTE(eaddr,tb)break; + case 0x7B: break; /*ILLEGAL*/ + case 0x7C: /*INC ext*/ EXTENDED tb=mem[eaddr]+1;if(tb==0x80)SEV else CLV + SETNZ8(tb) SETBYTE(eaddr,tb)break; + case 0x7D: /*TST ext*/ EXTENDED tb=mem[eaddr];SETNZ8(tb) break; + case 0x7E: /*JMP ext*/ EXTENDED ipcreg=eaddr;break; + case 0x7F: /*CLR ext*/ EXTENDED SETBYTE(eaddr,0)CLN CLV SEZ CLC break; + case 0x80: /*SUBA immediate*/ IMM8 tw=iareg-mem[eaddr]; + SETSTATUS(iareg,mem[eaddr],tw) + iareg=tw;break; + case 0x81: /*CMPA immediate*/ IMM8 tw=iareg-mem[eaddr]; + SETSTATUS(iareg,mem[eaddr],tw) break; + case 0x82: /*SBCA immediate*/ IMM8 tw=iareg-mem[eaddr]-(iccreg&0x01); + SETSTATUS(iareg,mem[eaddr],tw) + iareg=tw;break; + case 0x83: /*SUBD (CMPD CMPU) immediate*/ IMM16 + {unsigned long res,dreg,breg; + if(iflag==2)dreg=iureg;else dreg=GETDREG; + breg=GETWORD(eaddr); + res=dreg-breg; + SETSTATUSD(dreg,breg,res) + if(iflag==0) SETDREG(res) + }break; + case 0x84: /*ANDA immediate*/ IMM8 iareg=iareg&mem[eaddr];SETNZ8(iareg) + CLV break; + case 0x85: /*BITA immediate*/ IMM8 tb=iareg&mem[eaddr];SETNZ8(tb) + CLV break; + case 0x86: /*LDA immediate*/ IMM8 LOADAC(iareg) CLV SETNZ8(iareg) + break; + case 0x87: /*STA immediate (for the sake of orthogonality) */ IMM8 + SETNZ8(iareg) CLV STOREAC(iareg) break; + case 0x88: /*EORA immediate*/ IMM8 iareg=iareg^mem[eaddr];SETNZ8(iareg) + CLV break; + case 0x89: /*ADCA immediate*/ IMM8 tw=iareg+mem[eaddr]+(iccreg&0x01); + SETSTATUS(iareg,mem[eaddr],tw) + iareg=tw;break; + case 0x8A: /*ORA immediate*/ IMM8 iareg=iareg|mem[eaddr];SETNZ8(iareg) + CLV break; + case 0x8B: /*ADDA immediate*/ IMM8 tw=iareg+mem[eaddr]; + SETSTATUS(iareg,mem[eaddr],tw) + iareg=tw;break; + case 0x8C: /*CMPX (CMPY CMPS) immediate */ IMM16 + {unsigned long dreg,breg,res; + if(iflag==0)dreg=ixreg;else if(iflag==1) + dreg=iyreg;else dreg=isreg;breg=GETWORD(eaddr); + res=dreg-breg; + SETSTATUSD(dreg,breg,res) + }break; + case 0x8D: /*BSR */ IMMBYTE(tb) PUSHWORD(ipcreg) ipcreg+=SIGNED(tb); + break; + case 0x8E: /* LDX (LDY) immediate */ IMM16 tw=GETWORD(eaddr); + CLV SETNZ16(tw) if(!iflag)ixreg=tw; else + iyreg=tw;break; + case 0x8F: /* STX (STY) immediate (orthogonality) */ IMM16 + if(!iflag) tw=ixreg; else tw=iyreg; + CLV SETNZ16(tw) SETWORD(eaddr,tw) break; + case 0x90: /*SUBA direct*/ DIRECT tw=iareg-mem[eaddr]; + SETSTATUS(iareg,mem[eaddr],tw) + iareg=tw;break; + case 0x91: /*CMPA direct*/ DIRECT tw=iareg-mem[eaddr]; + SETSTATUS(iareg,mem[eaddr],tw) break; + case 0x92: /*SBCA direct*/ DIRECT tw=iareg-mem[eaddr]-(iccreg&0x01); + SETSTATUS(iareg,mem[eaddr],tw) + iareg=tw;break; + case 0x93: /*SUBD (CMPD CMPU) direct*/ DIRECT + {unsigned long res,dreg,breg; + if(iflag==2)dreg=iureg;else dreg=GETDREG; + breg=GETWORD(eaddr); + res=dreg-breg; + SETSTATUSD(dreg,breg,res) + if(iflag==0) SETDREG(res) + }break; + case 0x94: /*ANDA direct*/ DIRECT iareg=iareg&mem[eaddr];SETNZ8(iareg) + CLV break; + case 0x95: /*BITA direct*/ DIRECT tb=iareg&mem[eaddr];SETNZ8(tb) + CLV break; + case 0x96: /*LDA direct*/ DIRECT LOADAC(iareg) CLV SETNZ8(iareg) + break; + case 0x97: /*STA direct */ DIRECT + SETNZ8(iareg) CLV STOREAC(iareg) break; + case 0x98: /*EORA direct*/ DIRECT iareg=iareg^mem[eaddr];SETNZ8(iareg) + CLV break; + case 0x99: /*ADCA direct*/ DIRECT tw=iareg+mem[eaddr]+(iccreg&0x01); + SETSTATUS(iareg,mem[eaddr],tw) + iareg=tw;break; + case 0x9A: /*ORA direct*/ DIRECT iareg=iareg|mem[eaddr];SETNZ8(iareg) + CLV break; + case 0x9B: /*ADDA direct*/ DIRECT tw=iareg+mem[eaddr]; + SETSTATUS(iareg,mem[eaddr],tw) + iareg=tw;break; + case 0x9C: /*CMPX (CMPY CMPS) direct */ DIRECT + {unsigned long dreg,breg,res; + if(iflag==0)dreg=ixreg;else if(iflag==1) + dreg=iyreg;else dreg=isreg;breg=GETWORD(eaddr); + res=dreg-breg; + SETSTATUSD(dreg,breg,res) + }break; + case 0x9D: /*JSR direct */ DIRECT PUSHWORD(ipcreg) ipcreg=eaddr; + break; + case 0x9E: /* LDX (LDY) direct */ DIRECT tw=GETWORD(eaddr); + CLV SETNZ16(tw) if(!iflag)ixreg=tw; else + iyreg=tw;break; + case 0x9F: /* STX (STY) direct */ DIRECT + if(!iflag) tw=ixreg; else tw=iyreg; + CLV SETNZ16(tw) SETWORD(eaddr,tw) break; + case 0xA0: /*SUBA indexed*/ tw=iareg-mem[eaddr]; + SETSTATUS(iareg,mem[eaddr],tw) + iareg=tw;break; + case 0xA1: /*CMPA indexed*/ tw=iareg-mem[eaddr]; + SETSTATUS(iareg,mem[eaddr],tw) break; + case 0xA2: /*SBCA indexed*/ tw=iareg-mem[eaddr]-(iccreg&0x01); + SETSTATUS(iareg,mem[eaddr],tw) + iareg=tw;break; + case 0xA3: /*SUBD (CMPD CMPU) indexed*/ + {unsigned long res,dreg,breg; + if(iflag==2)dreg=iureg;else dreg=GETDREG; + breg=GETWORD(eaddr); + res=dreg-breg; + SETSTATUSD(dreg,breg,res) + if(iflag==0) SETDREG(res) + }break; + case 0xA4: /*ANDA indexed*/ iareg=iareg&mem[eaddr];SETNZ8(iareg) + CLV break; + case 0xA5: /*BITA indexed*/ tb=iareg&mem[eaddr];SETNZ8(tb) + CLV break; + case 0xA6: /*LDA indexed*/ LOADAC(iareg) CLV SETNZ8(iareg) + break; + case 0xA7: /*STA indexed */ + SETNZ8(iareg) CLV STOREAC(iareg) break; + case 0xA8: /*EORA indexed*/ iareg=iareg^mem[eaddr];SETNZ8(iareg) + CLV break; + case 0xA9: /*ADCA indexed*/ tw=iareg+mem[eaddr]+(iccreg&0x01); + SETSTATUS(iareg,mem[eaddr],tw) + iareg=tw;break; + case 0xAA: /*ORA indexed*/ iareg=iareg|mem[eaddr];SETNZ8(iareg) + CLV break; + case 0xAB: /*ADDA indexed*/ tw=iareg+mem[eaddr]; + SETSTATUS(iareg,mem[eaddr],tw) + iareg=tw;break; + case 0xAC: /*CMPX (CMPY CMPS) indexed */ + {unsigned long dreg,breg,res; + if(iflag==0)dreg=ixreg;else if(iflag==1) + dreg=iyreg;else dreg=isreg;breg=GETWORD(eaddr); + res=dreg-breg; + SETSTATUSD(dreg,breg,res) + }break; + case 0xAD: /*JSR indexed */ PUSHWORD(ipcreg) ipcreg=eaddr; + break; + case 0xAE: /* LDX (LDY) indexed */ tw=GETWORD(eaddr); + CLV SETNZ16(tw) if(!iflag)ixreg=tw; else + iyreg=tw;break; + case 0xAF: /* STX (STY) indexed */ + if(!iflag) tw=ixreg; else tw=iyreg; + CLV SETNZ16(tw) SETWORD(eaddr,tw) break; + case 0xB0: /*SUBA ext*/ EXTENDED tw=iareg-mem[eaddr]; + SETSTATUS(iareg,mem[eaddr],tw) + iareg=tw;break; + case 0xB1: /*CMPA ext*/ EXTENDED tw=iareg-mem[eaddr]; + SETSTATUS(iareg,mem[eaddr],tw) break; + case 0xB2: /*SBCA ext*/ EXTENDED tw=iareg-mem[eaddr]-(iccreg&0x01); + SETSTATUS(iareg,mem[eaddr],tw) + iareg=tw;break; + case 0xB3: /*SUBD (CMPD CMPU) ext*/ EXTENDED + {unsigned long res,dreg,breg; + if(iflag==2)dreg=iureg;else dreg=GETDREG; + breg=GETWORD(eaddr); + res=dreg-breg; + SETSTATUSD(dreg,breg,res) + if(iflag==0) SETDREG(res) + }break; + case 0xB4: /*ANDA ext*/ EXTENDED iareg=iareg&mem[eaddr];SETNZ8(iareg) + CLV break; + case 0xB5: /*BITA ext*/ EXTENDED tb=iareg&mem[eaddr];SETNZ8(tb) + CLV break; + case 0xB6: /*LDA ext*/ EXTENDED LOADAC(iareg) CLV SETNZ8(iareg) + break; + case 0xB7: /*STA ext */ EXTENDED + SETNZ8(iareg) CLV STOREAC(iareg) break; + case 0xB8: /*EORA ext*/ EXTENDED iareg=iareg^mem[eaddr];SETNZ8(iareg) + CLV break; + case 0xB9: /*ADCA ext*/ EXTENDED tw=iareg+mem[eaddr]+(iccreg&0x01); + SETSTATUS(iareg,mem[eaddr],tw) + iareg=tw;break; + case 0xBA: /*ORA ext*/ EXTENDED iareg=iareg|mem[eaddr];SETNZ8(iareg) + CLV break; + case 0xBB: /*ADDA ext*/ EXTENDED tw=iareg+mem[eaddr]; + SETSTATUS(iareg,mem[eaddr],tw) + iareg=tw;break; + case 0xBC: /*CMPX (CMPY CMPS) ext */ EXTENDED + {unsigned long dreg,breg,res; + if(iflag==0)dreg=ixreg;else if(iflag==1) + dreg=iyreg;else dreg=isreg;breg=GETWORD(eaddr); + res=dreg-breg; + SETSTATUSD(dreg,breg,res) + }break; + case 0xBD: /*JSR ext */ EXTENDED PUSHWORD(ipcreg) ipcreg=eaddr; + break; + case 0xBE: /* LDX (LDY) ext */ EXTENDED tw=GETWORD(eaddr); + CLV SETNZ16(tw) if(!iflag)ixreg=tw; else + iyreg=tw;break; + case 0xBF: /* STX (STY) ext */ EXTENDED + if(!iflag) tw=ixreg; else tw=iyreg; + CLV SETNZ16(tw) SETWORD(eaddr,tw) break; + case 0xC0: /*SUBB immediate*/ IMM8 tw=ibreg-mem[eaddr]; + SETSTATUS(ibreg,mem[eaddr],tw) + ibreg=tw;break; + case 0xC1: /*CMPB immediate*/ IMM8 tw=ibreg-mem[eaddr]; + SETSTATUS(ibreg,mem[eaddr],tw) break; + case 0xC2: /*SBCB immediate*/ IMM8 tw=ibreg-mem[eaddr]-(iccreg&0x01); + SETSTATUS(ibreg,mem[eaddr],tw) + ibreg=tw;break; + case 0xC3: /*ADDD immediate*/ IMM16 + {unsigned long res,dreg,breg; + dreg=GETDREG; + breg=GETWORD(eaddr); + res=dreg+breg; + SETSTATUSD(dreg,breg,res) + SETDREG(res) + }break; + case 0xC4: /*ANDB immediate*/ IMM8 ibreg=ibreg&mem[eaddr];SETNZ8(ibreg) + CLV break; + case 0xC5: /*BITB immediate*/ IMM8 tb=ibreg&mem[eaddr];SETNZ8(tb) + CLV break; + case 0xC6: /*LDB immediate*/ IMM8 LOADAC(ibreg) CLV SETNZ8(ibreg) + break; + case 0xC7: /*STB immediate (for the sake of orthogonality) */ IMM8 + SETNZ8(ibreg) CLV STOREAC(ibreg) break; + case 0xC8: /*EORB immediate*/ IMM8 ibreg=ibreg^mem[eaddr];SETNZ8(ibreg) + CLV break; + case 0xC9: /*ADCB immediate*/ IMM8 tw=ibreg+mem[eaddr]+(iccreg&0x01); + SETSTATUS(ibreg,mem[eaddr],tw) + ibreg=tw;break; + case 0xCA: /*ORB immediate*/ IMM8 ibreg=ibreg|mem[eaddr];SETNZ8(ibreg) + CLV break; + case 0xCB: /*ADDB immediate*/ IMM8 tw=ibreg+mem[eaddr]; + SETSTATUS(ibreg,mem[eaddr],tw) + ibreg=tw;break; + case 0xCC: /*LDD immediate */ IMM16 tw=GETWORD(eaddr);SETNZ16(tw) + CLV SETDREG(tw) break; + case 0xCD: /*STD immediate (orthogonality) */ IMM16 + tw=GETDREG; SETNZ16(tw) CLV + SETWORD(eaddr,tw) break; + case 0xCE: /* LDU (LDS) immediate */ IMM16 tw=GETWORD(eaddr); + CLV SETNZ16(tw) if(!iflag)iureg=tw; else + isreg=tw;break; + case 0xCF: /* STU (STS) immediate (orthogonality) */ IMM16 + if(!iflag) tw=iureg; else tw=isreg; + CLV SETNZ16(tw) SETWORD(eaddr,tw) break; + case 0xD0: /*SUBB direct*/ DIRECT tw=ibreg-mem[eaddr]; + SETSTATUS(ibreg,mem[eaddr],tw) + ibreg=tw;break; + case 0xD1: /*CMPB direct*/ DIRECT tw=ibreg-mem[eaddr]; + SETSTATUS(ibreg,mem[eaddr],tw) break; + case 0xD2: /*SBCB direct*/ DIRECT tw=ibreg-mem[eaddr]-(iccreg&0x01); + SETSTATUS(ibreg,mem[eaddr],tw) + ibreg=tw;break; + case 0xD3: /*ADDD direct*/ DIRECT + {unsigned long res,dreg,breg; + dreg=GETDREG; + breg=GETWORD(eaddr); + res=dreg+breg; + SETSTATUSD(dreg,breg,res) + SETDREG(res) + }break; + case 0xD4: /*ANDB direct*/ DIRECT ibreg=ibreg&mem[eaddr];SETNZ8(ibreg) + CLV break; + case 0xD5: /*BITB direct*/ DIRECT tb=ibreg&mem[eaddr];SETNZ8(tb) + CLV break; + case 0xD6: /*LDB direct*/ DIRECT LOADAC(ibreg) CLV SETNZ8(ibreg) + break; + case 0xD7: /*STB direct */ DIRECT + SETNZ8(ibreg) CLV STOREAC(ibreg) break; + case 0xD8: /*EORB direct*/ DIRECT ibreg=ibreg^mem[eaddr];SETNZ8(ibreg) + CLV break; + case 0xD9: /*ADCB direct*/ DIRECT tw=ibreg+mem[eaddr]+(iccreg&0x01); + SETSTATUS(ibreg,mem[eaddr],tw) + ibreg=tw;break; + case 0xDA: /*ORB direct*/ DIRECT ibreg=ibreg|mem[eaddr];SETNZ8(ibreg) + CLV break; + case 0xDB: /*ADDB direct*/ DIRECT tw=ibreg+mem[eaddr]; + SETSTATUS(ibreg,mem[eaddr],tw) + ibreg=tw;break; + case 0xDC: /*LDD direct */ DIRECT tw=GETWORD(eaddr);SETNZ16(tw) + CLV SETDREG(tw) break; + case 0xDD: /*STD direct */ DIRECT + tw=GETDREG; SETNZ16(tw) CLV + SETWORD(eaddr,tw) break; + case 0xDE: /* LDU (LDS) direct */ DIRECT tw=GETWORD(eaddr); + CLV SETNZ16(tw) if(!iflag)iureg=tw; else + isreg=tw;break; + case 0xDF: /* STU (STS) direct */ DIRECT + if(!iflag) tw=iureg; else tw=isreg; + CLV SETNZ16(tw) SETWORD(eaddr,tw) break; + case 0xE0: /*SUBB indexed*/ tw=ibreg-mem[eaddr]; + SETSTATUS(ibreg,mem[eaddr],tw) + ibreg=tw;break; + case 0xE1: /*CMPB indexed*/ tw=ibreg-mem[eaddr]; + SETSTATUS(ibreg,mem[eaddr],tw) break; + case 0xE2: /*SBCB indexed*/ tw=ibreg-mem[eaddr]-(iccreg&0x01); + SETSTATUS(ibreg,mem[eaddr],tw) + ibreg=tw;break; + case 0xE3: /*ADDD indexed*/ + {unsigned long res,dreg,breg; + dreg=GETDREG; + breg=GETWORD(eaddr); + res=dreg+breg; + SETSTATUSD(dreg,breg,res) + SETDREG(res) + }break; + case 0xE4: /*ANDB indexed*/ ibreg=ibreg&mem[eaddr];SETNZ8(ibreg) + CLV break; + case 0xE5: /*BITB indexed*/ tb=ibreg&mem[eaddr];SETNZ8(tb) + CLV break; + case 0xE6: /*LDB indexed*/ LOADAC(ibreg) CLV SETNZ8(ibreg) + break; + case 0xE7: /*STB indexed */ + SETNZ8(ibreg) CLV STOREAC(ibreg) break; + case 0xE8: /*EORB indexed*/ ibreg=ibreg^mem[eaddr];SETNZ8(ibreg) + CLV break; + case 0xE9: /*ADCB indexed*/ tw=ibreg+mem[eaddr]+(iccreg&0x01); + SETSTATUS(ibreg,mem[eaddr],tw) + ibreg=tw;break; + case 0xEA: /*ORB indexed*/ ibreg=ibreg|mem[eaddr];SETNZ8(ibreg) + CLV break; + case 0xEB: /*ADDB indexed*/ tw=ibreg+mem[eaddr]; + SETSTATUS(ibreg,mem[eaddr],tw) + ibreg=tw;break; + case 0xEC: /*LDD indexed */ tw=GETWORD(eaddr);SETNZ16(tw) + CLV SETDREG(tw) break; + case 0xED: /*STD indexed */ + tw=GETDREG; SETNZ16(tw) CLV + SETWORD(eaddr,tw) break; + case 0xEE: /* LDU (LDS) indexed */ tw=GETWORD(eaddr); + CLV SETNZ16(tw) if(!iflag)iureg=tw; else + isreg=tw;break; + case 0xEF: /* STU (STS) indexed */ + if(!iflag) tw=iureg; else tw=isreg; + CLV SETNZ16(tw) SETWORD(eaddr,tw) break; + case 0xF0: /*SUBB ext*/ EXTENDED tw=ibreg-mem[eaddr]; + SETSTATUS(ibreg,mem[eaddr],tw) + ibreg=tw;break; + case 0xF1: /*CMPB ext*/ EXTENDED tw=ibreg-mem[eaddr]; + SETSTATUS(ibreg,mem[eaddr],tw) break; + case 0xF2: /*SBCB ext*/ EXTENDED tw=ibreg-mem[eaddr]-(iccreg&0x01); + SETSTATUS(ibreg,mem[eaddr],tw) + ibreg=tw;break; + case 0xF3: /*ADDD ext*/ EXTENDED + {unsigned long res,dreg,breg; + dreg=GETDREG; + breg=GETWORD(eaddr); + res=dreg+breg; + SETSTATUSD(dreg,breg,res) + SETDREG(res) + }break; + case 0xF4: /*ANDB ext*/ EXTENDED ibreg=ibreg&mem[eaddr];SETNZ8(ibreg) + CLV break; + case 0xF5: /*BITB ext*/ EXTENDED tb=ibreg&mem[eaddr];SETNZ8(tb) + CLV break; + case 0xF6: /*LDB ext*/ EXTENDED LOADAC(ibreg) CLV SETNZ8(ibreg) + break; + case 0xF7: /*STB ext */ EXTENDED + SETNZ8(ibreg) CLV STOREAC(ibreg) break; + case 0xF8: /*EORB ext*/ EXTENDED ibreg=ibreg^mem[eaddr];SETNZ8(ibreg) + CLV break; + case 0xF9: /*ADCB ext*/ EXTENDED tw=ibreg+mem[eaddr]+(iccreg&0x01); + SETSTATUS(ibreg,mem[eaddr],tw) + ibreg=tw;break; + case 0xFA: /*ORB ext*/ EXTENDED ibreg=ibreg|mem[eaddr];SETNZ8(ibreg) + CLV break; + case 0xFB: /*ADDB ext*/ EXTENDED tw=ibreg+mem[eaddr]; + SETSTATUS(ibreg,mem[eaddr],tw) + ibreg=tw;break; + case 0xFC: /*LDD ext */ EXTENDED tw=GETWORD(eaddr);SETNZ16(tw) + CLV SETDREG(tw) break; + case 0xFD: /*STD ext */ EXTENDED + tw=GETDREG; SETNZ16(tw) CLV + SETWORD(eaddr,tw) break; + case 0xFE: /* LDU (LDS) ext */ EXTENDED tw=GETWORD(eaddr); + CLV SETNZ16(tw) if(!iflag)iureg=tw; else + isreg=tw;break; + case 0xFF: /* STU (STS) ext */ EXTENDED + if(!iflag) tw=iureg; else tw=isreg; + CLV SETNZ16(tw) SETWORD(eaddr,tw) break; + + + } + } +} + diff -r 000000000000 -r 9a224bd9b45f io.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/io.c Mon Jul 02 02:12:31 2018 +0900 @@ -0,0 +1,479 @@ +/* 6809 Simulator V09. + + created 1993,1994 by L.C. Benschop. + copyleft (c) 1994-2014 by the sbc09 team, see AUTHORS for more details. + license: GNU General Public License version 2, see LICENSE for more details. + + This program simulates a 6809 processor. + + System dependencies: short must be 16 bits. + char must be 8 bits. + long must be more than 16 bits. + arrays up to 65536 bytes must be supported. + machine must be twos complement. + Most Unix machines will work. For MSODS you need long pointers + and you may have to malloc() the mem array of 65536 bytes. + + Define BIG_ENDIAN if you have a big-endian machine (680x0 etc) + + Special instructions: + SWI2 writes char to stdout from register B. + SWI3 reads char from stdout to register B, sets carry at EOF. + (or when no key available when using term control). + SWI retains its normal function. + CWAI and SYNC stop simulator. + +*/ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef USE_TERMIOS +#include +#endif + +#define engine extern +#include "v09.h" + +int tflags; +int timer = 1; +struct termios termsetting; + +int xmstat; /* 0= no XMODEM transfer, 1=send, 2=receiver */ +unsigned char xmbuf[132]; +int xidx; +int acknak; +int rcvdnak; +int blocknum; + +FILE *logfile; +FILE *infile; +FILE *xfile; + +extern void hexadump( unsigned char *b, int l, int loc, int w); +extern void disasm(int,int); + + +int char_input(void) { + int c, w, sum; + if (!xmstat) { + if (infile) { + c = getc(infile); + if (c == EOF) { + fclose(infile); + infile = 0; + return char_input(); + } + if (c == '\n') + c = '\r'; + return c; + } else + return getchar(); + } else if (xmstat == 1) { + if (xidx) { + c = xmbuf[xidx++]; + if (xidx == 132) { + xidx = 0; + rcvdnak = EOF; + acknak = 6; + } + } else { + if ((acknak == 21 && rcvdnak == 21) || (acknak == 6 && rcvdnak == 6)) { + rcvdnak = 0; + memset(xmbuf, 0, 132); + w = fread(xmbuf + 3, 1, 128, xfile); + if (w) { + printf("Block %3d transmitted, ", blocknum); + xmbuf[0] = 1; + xmbuf[1] = blocknum; + xmbuf[2] = 255 - blocknum; + blocknum = (blocknum + 1) & 255; + sum = 0; + for (w = 3; w < 131; w++) + sum = (sum + xmbuf[w]) & 255; + xmbuf[131] = sum; + acknak = 6; + c = 1; + xidx = 1; + } else { + printf("EOT transmitted, "); + acknak = 4; + c = 4; + } + } else if (rcvdnak == 21) { + rcvdnak = 0; + printf("Block %3d retransmitted, ", xmbuf[1]); + c = xmbuf[xidx++]; /*retransmit the same block */ + } else + c = EOF; + } + return c; + } else { + if (acknak == 4) { + c = 6; + acknak = 0; + fclose(xfile); + xfile = 0; + xmstat = 0; + } else if (acknak) { + c = acknak; + acknak = 0; + } else + c = EOF; + if (c == 6) + printf("ACK\n"); + if (c == 21) + printf("NAK\n"); + return c; + } +} + +int do_input( a) { + static int c, f = EOF; + if (a == 0) { + if (f == EOF) + f = char_input(); + if (f != EOF) + c = f; + return 2 + (f != EOF); + } else if (a == 1) { /*data port*/ + if (f == EOF) + f = char_input(); + if (f != EOF) { + c = f; + f = EOF; + } + return c; + } + return 0; +} + +void do_output(int a, int c) { + int i, sum; + if (a == 1) { /* ACIA data port,ignore address */ + if (!xmstat) { + if (logfile && c != 127 && (c >= ' ' || c == '\n')) + putc(c, logfile); + putchar(c); + fflush(stdout); + } else if (xmstat == 1) { + rcvdnak = c; + if (c == 6 && acknak == 4) { + fclose(xfile); + xfile = 0; + xmstat = 0; + } + if (c == 6) + printf("ACK\n"); + if (c == 21) + printf("NAK\n"); + if (c == 24) { + printf("CAN\n"); + fclose(xfile); + xmstat = 0; + xfile = 0; + } + } else { + if (xidx == 0 && c == 4) { + acknak = 4; + printf("EOT received, "); + } + xmbuf[xidx++] = c; + if (xidx == 132) { + sum = 0; + for (i = 3; i < 131; i++) + sum = (sum + xmbuf[i]) & 255; + if (xmbuf[0] == 1 && xmbuf[1] == 255 - xmbuf[2] + && sum == xmbuf[131]) + acknak = 6; + else + acknak = 21; + printf("Block %3d received, ", xmbuf[1]); + if (blocknum == xmbuf[1]) { + blocknum = (blocknum + 1) & 255; + fwrite(xmbuf + 3, 1, 128, xfile); + } + xidx = 0; + } + } + } +} + +void restore_term(void) { + tcsetattr(0, TCSAFLUSH, &termsetting); + fcntl(0, F_SETFL, tflags); + signal(SIGALRM, SIG_IGN); +} + +void do_exit(void) { + restore_term(); + exit(0); +} + +typedef struct bp { + int address; + int count; + struct bp *next; +} BP, *BPTR; + +BPTR breakpoint = 0; +int bpskip = 0; +int trskip = 0; +int stkskip = 0; + +int getarg(char *buf, char** next) { + return strtol(buf,(char**)next,0); +} + +void printhelp(void) +{ + printf( + " s [count] one step trace\n" + " n step over\n" + " f finish this call (until stack pop)\n" + " b [adr] set break point\n" + " l break point list\n" + " d [n] delte break point list\n" + " c [count] continue;\n" + " x [adr] dump\n" + " xi [adr] disassemble\n" + " L file start log to file\n" + " S file set input file\n" + " X exit\n" + " q exit\n" + " U file upload from srecord file \n" + " D file download to srecord file \n" + " R do reset\n" + " h,? print this\n" + ); +} + +void do_escape(void) { + char s[80]; + int adr,skip; + if (bpskip) { // skip unbreak instruction + bpskip--; + for(BPTR b = breakpoint; b ; b=b->next) { + if (pcreg==b->address) { + if (b->count) b->count--; + if (b->count==0) { + goto restart0; + } + } + } + return; + } + if (stkskip) { // skip until return + if (sreg < stkskip ) return; + } +restart0: + stkskip = 0; + restore_term(); + do_trace(stdout); + if (trskip>1) { // show trace and step + trskip--; + set_term(escchar); + return; + } +restart: + printf("v09>"); + fgets(s, 80, stdin); + if (s[0]) + s[strlen(s) - 1] = 0; + switch (s[0]) { + case 's': // one step trace + trskip = 1; + if (s[1]) { + trskip = getarg(s+1,0); + } + bpskip = 0; + attention = escape = 1; + break; + case 'n': // step over + stkskip = sreg; + attention = escape = 1; + break; + case 'f': // finish this call (until stack pop) + stkskip = sreg + 2; + attention = escape = 1; + break; + case 'b': // set break point + { + BPTR bp = calloc(1,sizeof(BP)); + bp->next = breakpoint; + breakpoint = bp; + bp->count = 1; + if (s[1]) { + char *next; + bp->address = getarg(s+1,&next); + if (next[0]) { + bp->count = getarg(next,&next); + } + } else { + bp->address = pcreg; + } + } + bpskip = -1; + goto restart; + case 'l': // break point list + for(BPTR bp = breakpoint; bp ; bp = bp->next) { + printf("%x %i\n", bp->address, bp->count); + } + goto restart; + case 'd': // delte break point list + if (s[1]) { + int trskip = getarg(s+1,0); + BPTR *prev = &breakpoint; + for(BPTR bp = breakpoint; bp ; bp = bp->next) { + if (trskip-- == 0) { + if (bp) { + *prev = bp->next; + } + break; + } + prev = &bp->next; + } + } + goto restart; + case 'c': // continue; + bpskip = -1; + attention = escape = 1; + if (s[1]) { + bpskip = getarg(s+1,0); + } + break; + case 'x': // dump + skip = 1; + if (s[1]=='i') skip=2; + if (s[skip]) { + char *next; + int adr = getarg(s+skip,&next); + int len = 32; + if (next[0]) { + len = getarg(next,&next); + } + if (skip==2) { + disasm(adr,adr+len); + } else { + for(int i=0; len > 0 ; i+=16, len-=16) { + hexadump(mem+adr+i,len>16?16:len,adr+i,16); + } + } + } else + disasm(pcreg,pcreg+32); + goto restart; + case 'L': + if (logfile) + fclose(logfile); + logfile = 0; + if (s[1]) { + logfile = fopen(s + 1, "w"); + } + break; + case 'S': + if (infile) + fclose(infile); + infile = 0; + if (s[1]) { + infile = fopen(s + 1, "r"); + } + break; + case 'h': + case '?': + printhelp(); + goto restart; + case 'X': + case 'q': + if (!xmstat) + do_exit(); + else { + xmstat = 0; + fclose(xfile); + xfile = 0; + } + break; + case 'U': + if (xfile) + fclose(xfile); + xfile = 0; + if (s[1]) { + xfile = fopen(s + 1, "rb"); + } + if (xfile) + xmstat = 1; + else + xmstat = 0; + xidx = 0; + acknak = 21; + rcvdnak = EOF; + blocknum = 1; + break; + case 'D': + if (xfile) + fclose(xfile); + xfile = 0; + if (s[1]) { + xfile = fopen(s + 1, "wb"); + } + if (xfile) + xmstat = 2; + else + xmstat = 0; + xidx = 0; + acknak = 21; + blocknum = 1; + break; + case 'R': + pcreg = (mem[0xfffe] << 8) + mem[0xffff]; + break; + } + if (tracing||breakpoint||trskip||bpskip||stkskip) { attention = escape = 1; } + else attention = 0; + set_term(escchar); +} + +void timehandler(int sig) { + attention = 1; + irq = 2; + signal(SIGALRM, timehandler); +} + +void handler(int sig) { + escape = 1; + attention = 1; + bpskip = 0; + stkskip = 0; +} + +void set_term(char c) { + struct termios newterm; + struct itimerval timercontrol; + signal(SIGQUIT, SIG_IGN); + signal(SIGTSTP, SIG_IGN); + signal(SIGINT, handler); + signal(SIGUSR1, handler); + tcgetattr(0, &termsetting); + newterm = termsetting; + newterm.c_iflag = newterm.c_iflag & ~INLCR & ~ICRNL; + newterm.c_lflag = newterm.c_lflag & ~ECHO & ~ICANON; + newterm.c_cc[VTIME] = 0; + newterm.c_cc[VMIN] = 1; + newterm.c_cc[VINTR] = escchar; + tcsetattr(0, TCSAFLUSH, &newterm); + tflags = fcntl(0, F_GETFL, 0); + fcntl(0, F_SETFL, tflags | O_NDELAY); /* Make input from stdin non-blocking */ + signal(SIGALRM, timehandler); + timercontrol.it_interval.tv_sec = 0; + timercontrol.it_interval.tv_usec = 20000; + timercontrol.it_value.tv_sec = 0; + timercontrol.it_value.tv_usec = 20000; + if (timer) + setitimer(ITIMER_REAL, &timercontrol, NULL); +} diff -r 000000000000 -r 9a224bd9b45f makerom.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/makerom.c Mon Jul 02 02:12:31 2018 +0900 @@ -0,0 +1,78 @@ +/* makerom.c + Read standard input as S-records and build ROM image file v09.rom + ROM starts at 0x8000 and is 32K. +*/ + +#include +#include +#include + +static int sum,charindex; +unsigned char mem[0x8000]; +char linebuf[130]; + +void +hexerr() +{ + fprintf(stderr,"Illegal character in hex number\n"); + exit(1); +} + +int gethex() +{ + int c; + c=linebuf[charindex++]; + if(c<'0')hexerr(); + if(c>'9') { if(c<'A')hexerr();else c-=7; } + c-='0'; + return c; +} + +int getbyte() +{ + int b; + b=gethex(); + b=b*16+gethex(); + sum=(sum+b)&0xff; + return b; +} + +int +main() +{ + FILE *romfile; + unsigned int i,length,addr; + for(i=0;i<0x8000;i++)mem[i]=0xff; /*set unused locations to FF */ + for(;;) { + if(fgets(linebuf,128,stdin)==NULL)break; + if(strlen(linebuf))linebuf[strlen(linebuf)]=0; + if(linebuf[0]=='S'&&linebuf[1]=='1') { + sum=0;charindex=2; + length=getbyte(); + if(length<3) { + fprintf(stderr,"Illegal length in data record\n"); + exit(1); + } + addr=getbyte(); + addr=(addr<<8)+getbyte(); + if((long)addr+length-3>0x10000||addr<0x8000) { + fprintf(stderr,"Address 0x%x out of range\n",addr); + exit(1); + } + for(i=0;i!=length-3;i++)mem[addr-0x8000+i]=getbyte(); + getbyte(); + if(sum!=0xff) { + fprintf(stderr,"Checksum error\n"); + exit(1); + } + } + } + romfile=fopen("v09.rom","wb"); + if(!romfile) { + fprintf(stderr,"Cannot create file v09.rom\n"); + exit(1); + } + fwrite(mem,0x8000,1,romfile); + fclose(romfile); + exit(0); +} diff -r 000000000000 -r 9a224bd9b45f mon2.asm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mon2.asm Mon Jul 02 02:12:31 2018 +0900 @@ -0,0 +1,3080 @@ + ;Buggy machine language monitor and rudimentary O.S. version 1.0 + +* Memory map of SBC +* $0-$40 Zero page variables reserved by monitor and O.S. +* $40-$FF Zero page portion for user programs. +* $100-$17F Xmodem buffer 0, terminal input buffer, +* $180-$1FF Xmodem buffer 1, terminal output buffer. +* $200-$27F Terminal input line. +* $280-$2FF Variables reserved by monitor and O.S. +* $300-$400 System stack. +* $400-$7FFF RAM for user programs and data. +* $8000-$DFFF PROM for user programs. +* $E000-$E1FF I/O addresses. +* $E200-$E3FF Reserved. +* $E400-$FFFF Monitor ROM + +* Reserved Zero page addresses + org $0000 +* First the I/O routine vectors. +getchar rmb 3 ;Jump to getchar routine. +putchar rmb 3 ;Jump to putchar routine. +getline rmb 3 ;Jump to getline routine. +putline rmb 3 ;Jump to putline routine. +putcr rmb 3 ;Jump to putcr routine. +getpoll rmb 3 ;Jump to getpoll routine. +xopenin rmb 3 ;Jump to xopenin routine. +xopenout rmb 3 ;Jump to xopenout routine. +xabortin rmb 3 ;Jump to xabortin routine. +xclosein rmb 3 ;Jump to xclosein routine. +xcloseout rmb 3 ;Jump to xcloseout routine. +delay rmb 3 ;Jump to delay routine. + +*Next the system variables in the zero page. +temp rmb 2 ;hex scanning/disasm +temp2 rmb 2 ;Hex scanning/disasm +temp3 rmb 2 ;Used in Srecords, H command +timer rmb 3 ;3 byte timer, incremented every 20ms +xpacknum rmb 1 ;Packet number for XMODEM block, +xsum rmb 1 ;XMODEM checksum +lastok rmb 1 ;flag to indicate last block was OK +xcount rmb 1 ;Count of characters in buffer. +xmode rmb 1 ;XMODEM mode, 0 none, 1 out, 2 in. +disflg rmb 1 + +* I/O buffers. +buflen equ 128 ;Length of input line buffer. + org $100 +buf0 rmb 128 ;Xmodem buffer 0, serial input buffer. +buf1 rmb 128 ;Xmodem buffer 1, serial output buffer. +linebuf rmb buflen ;Input line buffer. + + +* Interrupt vectors (start at $280) +* All interrupts except RESET are vectored through jumps. +* FIRQ is timer interrupt, IRQ is ACIA interrupt. +swi3vec rmb 3 +swi2vec rmb 3 +firqvec rmb 3 +irqvec rmb 3 +swivec rmb 3 +nmivec rmb 3 +xerrvec rmb 3 ;Error handler for XMODEM error. +exprvec rmb 3 ;Expression evaluator in assembler. +asmerrvec rmb 3 ;Error handler for assembler errors. +pseudovec rmb 3 ;Vector for asm pseudo instructions. + +* Next the non zero page system variables. +oldpc rmb 2 ;Saved pc value for J command. +addr rmb 2 ;Address parameter. +length rmb 2 ;Length parameter. + +brkpoints equ 8 ;Number of settable breakpoints. +bpaddr rmb brkpoints*3 ;Address and byte for each break point. +stepbp rmb 3 ;Address of P command break point. + +sorg rmb 2 ;Origin address of S record entry. +soffs rmb 2 ;Offset load adrr-addr in record + +oldgetc rmb 2 ;Old getchar address. +oldputc rmb 2 ;Old putchar address. +oldputcr rmb 2 ;Old putcr address. +lastterm rmb 1 ;Last terminating character. +filler rmb 1 ;Filler at end of XMODEM file. +xmcr rmb 1 ;end-of-line characters for XMODEM send. +savesp rmb 2 ;Save sp to restore it on error. +nxtadd rmb 2 + +* Following variables are used by assembler/disassembler. +prebyte rmb 1 +opc1 rmb 1 +opcode rmb 1 +postbyte rmb 1 +amode rmb 1 +operand rmb 2 +mnembuf rmb 5 ;Buffer to store capitalized mnemonic. +opsize rmb 1 ;SIze (in bytes) of extra oeprand (0--2) +uncert rmb 1 ;Flag to indicate that op is unknown. +dpsetting rmb 2 + +endvars equ * + +ramstart equ $400 ;first free RAM address. + +ramtop equ $8000 ;top of RAM. + +* I/O port addresses +aciactl equ $e000 ;Control port of ACIA +aciasta equ $e000 ;Status port of ACIA +aciadat equ $e001 ;Data port of ACIA + +* ASCII control characters. +SOH equ 1 +EOT equ 4 +ACK equ 6 +BS equ 8 +TAB equ 9 +LF equ 10 +CR equ 13 +NAK equ 21 +CAN equ 24 +DEL equ 127 + +CASEMASK equ $DF ;Mask to make lowercase into uppercase. + +* Monitor ROM starts here. + org $E400 + +reset orcc #$FF ;Disable interrupts. + clra + tfr a,dp ;Set direct page register to 0. + clr disflg + lds #ramstart + ldx #intvectbl + ldu #swi3vec + ldb #osvectbl-intvectbl + bsr blockmove ;Initialize interrupt vectors from ROM. + ldx #osvectbl + ldu #0 + ldb #endvecs-osvectbl + bsr blockmove ;Initialize I/O vectors from ROM. + bsr initacia ;Initialize serial port. + andcc #$0 ;Enable interrupts +* Put the 'saved' registers of the program being monitored on top of the +* stack. There are 12 bytes on the stack for cc,b,a,dp,x,y,u and pc +* pc is initialized to $400, the rest to zero. + ldx #0 + tfr x,y + ldu #ramstart + pshs x,u + pshs x,y + pshs x,y + ldx #oldpc + ldb #endvars-oldpc +clvar clr ,x+ + decb + bne clvar ;Clear the variable area. + ldd #$1A03 + std filler ;Set XMODEM filler and end-of-line. + ldx #welcome + jsr outcount + jsr putcr ;Print a welcome message. + jmp cmdline +* Block move routine, from X to U length B. Modifies them all and A. +blockmove lda ,x+ + sta ,u+ + decb + bne blockmove + rts + +* Initialize serial communications port, buffers, interrupts. +initacia ldb #$03 + stb aciactl + ldb #%00110101 + rts + +* O.S. routine to read a character into B register. +osgetc ldb aciasta + bitb #$01 + beq osgetc + ldb aciadat + rts + +;O.S. rotuine to check if there is a character ready to be read. +osgetpoll ldb aciasta + bitb #$01 + bne poltrue + clrb + rts +poltrue ldb #$ff + rts + +* O.S. routine to write the character in the B register. +osputc pshs a +putcloop lda aciasta + bita #$02 + beq putcloop + stb aciadat + puls a + rts + +* O.S. routine to read a line into memory at address X, at most B chars +* long, return actual length in B. Permit backspace editing. +osgetl pshs a,x + stb temp + clra +osgetl1 jsr getchar + andb #$7F + cmpb #BS + beq backsp + cmpb #DEL + bne osgetl2 +backsp tsta ;Recognize BS and DEL as backspace key. + beq osgetl1 ;ignore if line already zero length. + ldb #BS + jsr putchar + ldb #' ' + jsr putchar + ldb #BS ;Send BS,space,BS. This erases last + jsr putchar ;character on most terminals. + leax -1,x ;Decrement address. + deca + bra osgetl1 +osgetl2 cmpb #CR + beq newline + cmpb #LF + bne osgetl3 ;CR or LF character ends line. + ldb lastterm + cmpb #CR + beq osgetl1 ;Ignore LF if it comes after CR + ldb #LF +newline stb lastterm + jsr putcr + tfr a,b ;Move length to B + puls a,x ;restore registers. + rts ;<--- Here is the exit point. +osgetl3 cmpb #TAB + beq dotab + cmpb #' ' + blo osgetl1 ;Ignore control characters. + cmpa temp + beq osgetl1 ;Ignore char if line full. + jsr putchar ;Echo the character. + stb ,x+ ;Store it in memory. + inca + bra osgetl1 +dotab ldb #' ' + cmpa temp + beq osgetl1 + jsr putchar + stb ,x+ + inca + bita #7 ;Insert spaces until length mod 8=0 + bne dotab + bra osgetl1 + +* O.S. routine to write a line starting at address X, B chars long. +osputl pshs a,b,x + tfr b,a + tsta + beq osputl1 +osputl2 ldb ,x+ + jsr putchar + deca + bne osputl2 +osputl1 puls a,b,x + rts + +* O.S. routine to terminate a line. +oscr pshs b + ldb #CR + jsr putchar + ldb #LF + jsr putchar ;Send the CR and LF characters. + puls b + rts + +* Output a counted string at addr X +outcount pshs x,b + ldb ,x+ + jsr putline + puls x,b + rts + +timerirq inc timer+2 + bne endirq + inc timer+1 + bne endirq + inc timer + rti +aciairq nop +endirq rti + +* Wait D times 20ms. +osdly addd timer+1 +dlyloop cmpd timer+1 + bne dlyloop + rts + +* This table will be copied to the interrupt vector area in RAM. +intvectbl jmp endirq + jmp endirq + jmp timerirq + jmp aciairq + jmp unlaunch + jmp endirq + jmp xerrhand + jmp expr + jmp asmerrvec + jmp pseudo +* And this one to the I/O vector table. +osvectbl jmp osgetc + jmp osputc + jmp osgetl + jmp osputl + jmp oscr + jmp osgetpoll + jmp xopin + jmp xopout + jmp xabtin + jmp xclsin + jmp xclsout + jmp osdly +endvecs equ * + +* The J command returns here. +stakregs pshs x ;Stack something where the pc comes + pshs ccr,b,a,dp,x,y,u ;Stack the normal registers. + ldx oldpc + stx 10,s ;Stack the old pc value. + bra unlaunch1 +* The G and P commands return here through a breakpoint. +* Registers are already stacked. +unlaunch ldd 10,s + subd #1 + std 10,s ;Decrement pc before breakpoint +unlaunch1 andcc #$0 ;reenable the interrupts. + jsr disarm ;Disarm the breakpoints. + jsr dispregs +cmdline jsr xcloseout + sts savesp + ldb #'.' + jsr putchar + ldx #linebuf + ldb #buflen + jsr getline + tstb + beq cmdline ;Ignore line if it is empty + abx + clr ,x ;Make location after line zero. + ldx #linebuf + ldb ,x+ + andb #CASEMASK ;Make 1st char uppercase. + subb #'A' + bcs unk + cmpb #26 + bcc unk ;Unknown cmd if it is not a letter. + ldx #cmdtab + aslb ;Index into command table. + jmp [b,x] + +cmdtab fdb asm,break,calc,dump + fdb enter,find,go,help + fdb inp,jump,unk,unk + fdb move,unk,unk,prog + fdb unk,regs,srec,trace + fdb unasm,unk,unk,xmodem + fdb unk,unk + +* Unknown command handling routine. +unk jsr xabortin + ldx #unknown + jsr outcount + jsr putcr + jmp cmdline + +help ldx #mhelp ;Print a help message. +help1 ldb ,x+ + beq endhlp + lbsr osputc + bra help1 +endhlp jmp cmdline +mhelp fcb CR,LF + fcc 'Commands list' + fcb CR,LF + + fcc '-------------' + fcb CR,LF + + fcc 'Asm ' + fcc '{Aaddr}' + fcb CR,LF + + fcc 'Unasm ' + fcc '{U or Uaddr or Uaddr,length}' + fcb CR,LF + + fcc 'Dump ' + fcc '{D or D or D,}' + fcb CR,LF + + fcc 'Enter ' + fcc '{E or E or E or Estring}' + fcb CR,LF + + fcc 'Break ' + fcc '{B or B. B displays, B sets or clears breakpoint}' + fcb CR,LF + + fcc 'Find ' + fcb "{Faddr bytes or Faddr",34,"ascii",34,"}" + fcb CR,LF + + fcc 'Go ' + fcc '{G or G}' + fcb CR,LF + + fcc 'Calc ' + fcc '{Chexnum{+|-hexnum}}' + fcb CR,LF + + fcc 'Inp ' + fcc '{Iaddr}' + fcb CR,LF + + fcc 'Jump ' + fcc '{J}' + fcb CR,LF + + fcc 'Move ' + fcc '{M,,}' + fcb CR,LF + + fcc 'Prog ' + fcc '{P}' + fcb CR,LF + + fcc 'Regs ' + fcc '{R or R}' + fcb CR,LF + + fcc 'Srec ' + fcc '{SO or SS, or S1 or S9}' + fcb CR,LF + + fcc 'Trace ' + fcc '{T}' + fcb CR,LF + + fcc 'Xmodem ' + fcc '{XSaddr,len XLaddr,len XX XOcrlf,filler, XSSaddr,len}' + fcb CR,LF + + fcc 'Help ' + fcc '{H}' + fcb CR,LF,0 + + + +* Here are some useful messages. +welcome fcb unknown-welcome-1 + fcc "Welcome to BUGGY version 1.0" +unknown fcb brkmsg-unknown-1 + fcc "Unknown command" +brkmsg fcb clrmsg-brkmsg-1 + fcc "Breakpoint set" +clrmsg fcb fullmsg-clrmsg-1 + fcc "Breakpoint cleared" +fullmsg fcb smsg-fullmsg-1 + fcc "Breakpoints full" +smsg fcb lastrec-smsg-1 + fcc "Error in S record" +lastrec fcb xsmsg-lastrec-1 + fcc "S9030000FC" +xsmsg fcb xrmsg-xsmsg-1 + fcc "Start XMODEM Send" +xrmsg fcb xamsg-xrmsg-1 + fcc "Start XMODEM Receive" +xamsg fcb invmmsg-xamsg-1 + fcc "XMODEM transfer aborted" +invmmsg fcb exprmsg-invmmsg-1 + fcc "Invalid mnemonic" +exprmsg fcb modemsg-exprmsg-1 + fcc "Expression error" +modemsg fcb brmsg-modemsg-1 + fcc "Addressing mode error" +brmsg fcb endmsg-brmsg-1 + fcc "Branch too long" +endmsg equ * + +* Output hex digit contained in A +hexdigit adda #$90 + daa + adca #$40 + daa ;It's the standard conversion trick ascii + tfr a,b ;to hex without branching. + jsr putchar + rts + +* Output contents of A as two hex digits +outbyte pshs a + lsra + lsra + lsra + lsra + bsr hexdigit + puls a + anda #$0f + bra hexdigit + +* Output contents of d as four hex digits +outd pshs b + bsr outbyte + puls a + bsr outbyte + rts + +* Skip X past spaces, B is first non-space character. +skipspace ldb ,x+ + cmpb #' ' + beq skipspace + rts + +* Convert ascii hex digit in B register to binary Z flag set if no hex digit. +convb subb #'0' + blo convexit + cmpb #9 + bls cb2 + andb #CASEMASK ;Make uppercase. + subb #7 ;If higher than digit 9 it must be a letter. + cmpb #9 + bls convexit + cmpb #15 + bhi convexit +cb2 andcc #$FB ;clear zero + rts +convexit orcc #$04 + rts + +scanexit ldd temp + leax -1,x + tst temp2 + rts <-- exit point of scanhex + +* Scan for hexadecimal number at address X return in D, Z flag is set it no +* number found. +scanhex clr temp + clr temp+1 + clr temp2 + bsr skipspace +scloop jsr convb + beq scanexit + pshs b + ldd temp + aslb + rola + aslb + rola + aslb + rola + aslb + rola + addb ,s+ + std temp + inc temp2 + ldb ,x+ + bra scloop + +scan2parms std length + bsr scanhex + beq sp2 + std addr + bsr skipspace + cmpb #',' + bne sp2 + bsr scanhex + beq sp2 + std length +sp2 rts + +* Scan two hexdigits at in and convert to byte into A, Z flag if error. +scanbyte bsr skipspace + bsr convb + beq sb1 + tfr b,a + ldb ,x+ + bsr convb + beq sb1 + asla + asla + asla + asla + stb temp + adda temp + andcc #$fb ;Clear zero flag +sb1 rts + + +* This is the code for the D command, hex/ascii dump of memory +* Syntax: D or D or D, +dump ldx #linebuf+1 + ldd #$40 + jsr scan2parms ;Scan address and length, default length=64 + ldy addr +dh1 lda #16 + sta temp+1 + tfr y,d + jsr outd + ldb #' ' + jsr putchar +dh2 lda ,y+ ;display row of 16 mem locations as hex + jsr outbyte + ldb #' ' + lda temp+1 + cmpa #9 + bne dh6 + ldb #'-' ;Do a - after the eighth byte. +dh6 jsr putchar + dec temp+1 + bne dh2 + leay -16,y ;And now for the ascii dump. + lda #16 +dh3 ldb ,y+ + cmpb #' ' + bhs dh4 + ldb #'.' +dh4 cmpb #DEL + blo dh5 + ldb #'.' ;Convert all nonprintables to . +dh5 jsr putchar + deca + bne dh3 + jsr putcr + ldd length + subd #16 + std length + bhi dh1 + sty addr + jmp cmdline + +* This is the code for the E command, enter hex bytes or ascii string. +* Syntax E or E or E or E"string" +enter ldx #linebuf+1 + jsr scanhex + beq ent1 + std addr +ent1 bsr entline + lbne cmdline ;No bytes, then enter interactively. +ent2 ldb #'E' + jsr putchar + ldd addr + jsr outd + ldb #' ' + jsr putchar ;Display Eaddr + space + lda [addr] + jsr outbyte + ldb #' ' + jsr putchar + ldx #linebuf + ldb #buflen + jsr getline ;Get the line. + tstb + beq skipbyte + abx + clr ,x + ldx #linebuf + bsr entline + bne ent2 + jmp cmdline +skipbyte ldd addr + addd #1 + std addr + bra ent2 + +* Enter a line of hex bytes or ascci string at address X, Z if empty. +entline jsr skipspace + tstb + beq entexit + cmpb #'.' + beq entexit + cmpb #'"' + beq entasc + leax -1,x + ldy addr +entl2 jsr scanbyte ;Enter hex digits. + beq entdone + sta ,y+ + bra entl2 +entasc ldy addr +entl3 lda ,x+ + tsta + beq entdone + cmpa #'"' + beq entdone + sta ,y+ + bra entl3 +entdone sty addr + andcc #$fb + rts +entexit orcc #$04 + rts + +*This is the code for the I command, display the contents of an address +* Syntax: Iaddr +inp ldx #linebuf+1 + jsr scanhex + tfr d,x + lda ,x ;Read the byte from memory. + jsr outbyte ;Display itin hex. + jsr putcr + jmp cmdline + +*This is the code for the H command, display result of simple hex expression +*Syntax Hhexnum{+|-hexnum} +calc ldx #linebuf+1 + jsr scanhex + std temp3 +hexloop jsr skipspace + cmpb #'+' + bne hex1 + jsr scanhex + addd temp3 + std temp3 + bra hexloop +hex1 cmpb #'-' + bne hexend + jsr scanhex + comb + coma + addd #1 + addd temp3 + std temp3 + bra hexloop +hexend ldd temp3 + jsr outd + jsr putcr + jmp cmdline + +* This is the code for the G command, jump to the program +* Syntax G or G +go ldx #linebuf+1 + jsr scanhex + beq launch + std 10,s ;Store parameter in pc location. +launch jsr arm ;Arm the breakpoints. + puls ccr,b,a,dp,x,y,u,pc + +* This is the code for the J command, run a subroutine. +* Syntax J +jump ldx #linebuf+1 + ldd 10,s + std oldpc ;Save old pc + jsr scanhex + std 10,s ;Store parameter in PC location + tfr s,x + leas -2,s + tfr s,u + ldb #12 ;Move the saved register set 2 addresses + jsr blockmove ;down on the stack. + ldd #stakregs + std 12,s ;Prepare subroutine return address. + bra launch ;Jump to the routine. + + +* This is the code for the P command, run instruction followed by breakpoint +* Syntax P +prog ldy 10,s ;Get program counter value. + jsr disdecode ;Find out location past current insn. + sty stepbp + bra launch + +* This is the code for the T command, single step trace an instruction. +* Syntax T +trace jsr traceone + jsr dispregs + jmp cmdline + +traceone orcc #$50 ;Disable the interrupts. + ldd ,s++ + std oldpc ;Remove saved pc from stack. + ldd #traceret + std firqvec+1 ;Adjust timer IRQ vector. + sync ;Synchronize on the next timer interrupt. + ;1 cycle + ldx #4441 ;3 cycles +traceloop leax -1,x ;6 cycles\x4441= 39969 cycles. + bne traceloop ;3 cycles/ + nop ;2 cycles. + nop ;2 cycles. + nop ;2 cycles. + brn traceret ;3 cycles. + puls x,y,u,a,b,dp,cc,pc ;17 cycles, total=39999 20ms @ 2MHz + ;Pull all registers and execute. + ;Is timed such that next timer IRQ + ;occurs right after it. +traceret puls cc + pshs x,y,u,a,b,dp,cc;Store full register set instead of cc. + ldd #timerirq + std firqvec+1 ;Restore timer IRQ vector. + jmp [oldpc] + + +* Display the contents of 8 bit register, name in B, contents in A +disp8 jsr putchar + ldb #'=' + jsr putchar + jsr outbyte + ldb #' ' + jsr putchar + rts + +* Display the contents of 16 bit register, name in B, contents in Y +disp16 jsr putchar + ldb #'=' + jsr putchar + tfr y,d + jsr outd + ldb #' ' + jsr putchar + rts + +* Display the contents of the registers and disassemble instruction at +* PC location. +dispregs ldb #'X' + ldy 6,s ;Note that there's one return address on + bsr disp16 ;stack so saved register offsets are + ldb #'Y' ;inremented by 2. + ldy 8,s + bsr disp16 + ldb #'U' + ldy 10,s + bsr disp16 + ldb #'S' + tfr s,y + leay 14,y ;S of the running program is 12 higher, + ;because regs are not stacked when running. + bsr disp16 + ldb #'A' + lda 3,s + bsr disp8 + ldb #'B' + lda 4,s + bsr disp8 + ldb #'D' + lda 5,s + bsr disp8 + ldb #'C' + lda 2,s + bsr disp8 + jsr putcr + ldb #'P' + ldy 12,s + bsr disp16 + jsr disdecode + jsr disdisp ;Disassemble instruction at PC + jsr putcr + rts + + +* This is the code for the R command, display or alter the registers. +* Syntax R or R +regs ldx #linebuf+1 + jsr skipspace + tstb + bne setreg + bsr dispregs ;Display regs ifnothing follows. + jmp cmdline +setreg ldy #regtab + clra + andb #CASEMASK ;Make letter uppercase. +sr1 tst ,y + lbeq unk ;At end of register tab, unknown reg + cmpb ,y+ + beq sr2 ;Found the register? + inca + bra sr1 +sr2 pshs a + jsr scanhex ;Convert the hex argument. + pshs d + lda 2,s ;Get register number. + cmpa #4 + bcc sr3 + ldb 1,s ;It's 8 bit. + leas 3,s ;Remove temp stuff from stack. + stb a,s ;Store it in the reg on stack. + jmp cmdline +sr3 cmpa #8 + bcc sr4 + puls x ;It's 16 bit. + leas 1,s + lsla + suba #4 ;Convert reg no to stack offset. + stx a,s + jmp cmdline +sr4 puls u ;It's the stack pointer. + leas 1,s + leau -12,u + tfr s,x + tfr u,s ;Set new stack pointer. + ldb #12 + jsr blockmove ;Move register set to new stack location. + jmp cmdline + +regtab FCC "CABDXYUPS " + +* Disarm the breakpoints, this is replace the SWI instructions with the +* original byte. +disarm ldx #bpaddr + lda #brkpoints+1 +disarm1 ldu ,x++ + ldb ,x+ ;Get address in u, byte in b + cmpu #0 + beq disarm2 + stb ,u +disarm2 deca + bne disarm1 + ldu #0 + stu -3,x ;Clear the step breakpoint. + rts + +* Arm the breakponts, this is replace the byte at the breakpoint address +* with an SWI instruction. +arm ldx #bpaddr+brkpoints*3 + lda #brkpoints+1 ;Arm them in reverse order of disarming. +arm1 ldu ,x ;Get address in u. + beq arm2 + ldb ,u + stb 2,x + cmpu 12,s ;Compare to program counter location + beq arm2 + ldb #$3F + stb ,u ;Store SWI instruction if not equal. +arm2 leax -3,x + deca + bne arm1 + rts + +* This is the code for the break command, set, clear display breakpoints. +* Syntax B or B. B displays, B sets or clears breakpoint. +break lda #brkpoints + sta temp2+1 ;Store number of breakpoints to visit. + ldx #linebuf+1 + jsr scanhex + beq dispbp ;No number then display breakpoints + ldx #bpaddr + ldu #0 + tfr u,y +bp1 cmpd ,x + beq clearit ;Found the breakpoint, so clear it, + cmpu ,x ;Is location zero + bne bp2 + tfr x,y ;Set free address to y +bp2 leax 3,x + dec temp2+1 + bne bp1 + cmpy #0 ;Address not found in list of breakpoints + beq bpfull ;Was free address found. + std ,y ;If so, store breakpoint there. + ldx #brkmsg +bpexit jsr outcount + jsr putcr + jmp cmdline +clearit clra + clrb + std ,x + ldx #clrmsg + bra bpexit +bpfull ldx #fullmsg + bra bpexit + +dispbp ldx #bpaddr +dbp1 ldd ,x + beq dbp2 + jsr outd + ldb #' ' + jsr putchar +dbp2 leax 3,x + dec temp2+1 + bne dbp1 + jsr putcr + jmp cmdline + +* Scan hex byte into a and add it to check sum in temp2+1 +addchk jsr scanbyte + lbeq srecerr + tfr a,b + addb temp2+1 + stb temp2+1 + rts + +* This tis the code for the S command, the Motorola S records entry. +* Syntax SO or SS, or S1 or S9 +srec ldx #linebuf+1 + ldb ,x+ + andb #CASEMASK + cmpb #'O' + beq setsorg + cmpb #'S' + beq sendrec + ldb -1,x + clr temp3 + cmpb #'1' + beq readrec + cmpb #'9' + bne srecerr + inc temp3 +readrec clr temp2+1 ;clear checksum. + bsr addchk + suba #2 ;discount the address bytes from the count. + sta temp3+1 ;Read length byte. + bsr addchk + pshs a + bsr addchk + puls b + exg a,b ;Read address into d. + ldu sorg + beq rr1 + ldu soffs + bne rr1 + pshs d ;Sorg is nonzero and soffs is zero, now + subd sorg ;set soffs + std soffs + puls d +rr1 subd soffs ;Subtract the address offset. + tfr d,y +rr2 bsr addchk + dec temp3+1 + beq endrec + sta ,y+ + bra rr2 +endrec inc temp2+1 ;Check checksum. + bne srecerr + tst temp3 + lbeq cmdline ;Was it no S9 record? + cmpy #0 + beq endrec1 + sty 10,s ;Store address into program counter. +endrec1 clra + clrb + std sorg ;Reset sorg, next S loads will be normal. + std soffs + jmp cmdline +srecerr jsr xabortin + ldx #smsg ;Error in srecord, display message. + jsr outcount + jsr putcr + jmp cmdline +setsorg jsr scanhex ;Set S record origin. + std sorg + clra + clrb + std soffs + jmp cmdline +* Send a memory region as S-records. +sendrec ldd #$100 ;Scan address and length parameter. + jsr scan2parms + ldd sorg + beq ss1 + ldd addr + subd sorg + std soffs ;Compute offset for origin. +ss1 ldd length + beq endss ;All bytes sent? + cmpd #16 + blo ss2 + ldb #16 ;If more than 16 left, then send 16. +ss2 stb temp + negb + ldu length + leau b,u + stu length ;Discount line length from length. + ldb #'S' + jsr putchar + ldb #'1' + jsr putchar + clr temp+1 ;Clear check sum + ldb temp + addb #3 + bsr checkout ;Output byte b as hex and add to check sum. + ldd addr + tfr d,y + subd soffs + exg a,b + bsr checkout + exg a,b + bsr checkout ;Output address (add into check sum) +ss3 ldb ,y+ + bsr checkout + dec temp + bne ss3 + sty addr + ldb temp+1 + comb + bsr checkout ;Output checksum byte. + jsr putcr + bra ss1 +endss ldx #lastrec + jsr outcount + jsr putcr + jmp cmdline +* Output byte in register B and add it into check sum at temp+1 +checkout pshs a + tfr b,a + addb temp+1 + stb temp+1 + jsr outbyte + puls a + rts + +* This is the code for the M command, move memory region. +* Syntax: Maddr1,addr2,length +move ldx #linebuf+1 + jsr scanhex + lbeq unk + std temp3 + jsr skipspace + cmpb #',' + lbne unk + jsr scanhex + lbeq unk + tfr d,u + jsr skipspace + cmpb #',' + lbne unk + jsr scanhex + lbeq unk + tfr d,y ;Read the argument separated by commas + ldx temp3 ;src addr to x, dest addr to u, length to y + ;Don't tolerate syntax deviations. +mvloop lda ,x+ + sta ,u+ + leay -1,y + bne mvloop ;Perform the block move. + jmp cmdline + + +* This is the code for the F command, find byte/ascii string in memory. +* Syntax: Faddr bytes or Faddr "ascii" +find ldx #linebuf+1 + jsr scanhex + tfr d,y ;Scan the start address. + jsr skipspace + cmpb #'"' + bne findhex + ldu #linebuf ;Quote found, so scan for quoted string. + clra +fstrloop ldb ,x+ + beq startsrch ;End of line without final quote. + cmpb #'"' + beq startsrch ;End quote found + stb ,u+ + inca + bra fstrloop +findhex ldu #linebuf ;Convert string of hex bytes. + leax -1,x ;String will be stored at start of line + clra ;buffer and may overwrite part of the +fhexloop pshs a ;already converted string. + jsr scanbyte + tfr a,b + puls a + beq startsrch + stb ,u+ + inca + bra fhexloop +startsrch tsta ;Start searching, start addr in Y, + ;string starts at linebuf, length A + lbeq cmdline ;Quit with zero length string. + clr temp3 + sta temp3+1 +srchloop tfr y,x + lda temp3+1 + cmpx #$e100 + bcc srch1 + leax a,x + cmpx #$e000 ;Stop at I/O addresses. + lbcc cmdline +srch1 tfr y,x + ldu #linebuf +srch2 ldb ,x+ + cmpb ,u+ + bne srch3 ;Not equal, try next address. + deca + bne srch2 + tfr y,d + jsr outd ;String found + jsr putcr + inc temp3 + lda temp3 + cmpa #$10 + lbeq cmdline ;If 10 matches found, just stop. +srch3 leay 1,y + bra srchloop + +* Send the contents of the xmodem buffer and get it acknowledged, zero flag +* is set if transfer aborted. +xsendbuf ldb #SOH + jsr osputc ;Send SOH + ldb xpacknum + jsr osputc ;Send block number. + comb + jsr osputc ;and its complement. + clr xsum + lda #128 + ldx #buf0 +xsloop ldb ,x + addb xsum + stb xsum + ldb ,x+ + jsr osputc + deca + bne xsloop ;Send the buffer contents. + ldb xsum + jsr osputc ;Send the check sum +waitack jsr osgetc + cmpb #CAN + beq xsabt ;^X for abort. + cmpb #NAK + beq xsendbuf ;Send again if NAK + cmpb #ACK + bne waitack + inc xpacknum +xsok andcc #$fb ;Clear zero flag after ACK +xsabt rts + +* Start an XMODEM send session. +xsendinit ldb #1 + stb xpacknum ;Initialize block number. +waitnak jsr osgetc + cmpb #CAN + beq xsabt ;If ^X exit with zero flag. + cmpb #NAK + beq xsok + bra waitnak ;Wait until NAK received. + +* Send ETX and wait for ack. +xsendeot ldb #EOT + jsr osputc +waitack2 jsr osgetc + cmpb #CAN + beq xsabt + cmpb #NAK + beq xsendeot + cmpb #ACK + beq xsok + bra waitack2 + +* Read character into B with a timeout of A seconds, Carry set if timeout. +gettimeout asla + ldb #50 + mul + tfr b,a + adda timer+2 +gt1 jsr osgetpoll + tstb + bne gtexit + cmpa timer+2 + bne gt1 + orcc #$1 + rts +gtexit jsr osgetc + andcc #$fe + rts + +* Wait until line becomes quiet. +purge lda #3 + jsr gettimeout + bcc purge + rts + +* Receive an XMODEM block and wait till it is OK, Z set if etx. +xrcvbuf lda #3 + tst lastok + beq sendnak + ldb #ACK + jsr osputc ;Send an ack. + lda #5 + bra startblock +sendnak ldb #NAK + jsr osputc ;Send a NAK +startblock clr lastok + bsr gettimeout + lda #3 + bcs sendnak ;Keep sending NAKs when timed out. + cmpb #EOT + beq xrcveot ;End of file reached, acknowledge EOT. + cmpb #SOH + bne purgeit ;Not, SOH, bad block. + lda #1 + bsr gettimeout + bcs purgeit + cmpb xpacknum ;Is it the right block? + beq xr1 + incb + cmpb xpacknum ;Was it the previous block. + bne purgeit + inc lastok +xr1 stb xsum + lda #1 + bsr gettimeout + bcs purgeit + comb + cmpb xsum ;Is the complement of the block number OK + bne purgeit + ldx #buf0 + clr xsum +xrloop lda #1 + bsr gettimeout + bcs purgeit + stb ,x+ + addb xsum + stb xsum + cmpx #buf0+128 + bne xrloop ;Get the data bytes. + lda #1 + bsr gettimeout + bcs purgeit + cmpb xsum + bne purgeit ;Check the check sum. + tst lastok + bne xrcvbuf ;Block was the previous block, get next one + inc lastok + inc xpacknum + andcc #$fb + rts +purgeit jsr purge + bra sendnak +xrcveot lda #3 ;EOT was received. + ldb #ACK +ackloop jsr osputc + deca + bne ackloop ;Send 3 acks in a row. + rts + + +savevecs ldx getchar+1 + stx oldgetc + ldx putchar+1 + stx oldputc + ldx putcr+1 + stx oldputcr + clr lastterm + rts + +rstvecs ldx oldgetc + stx getchar+1 + ldx oldputc + stx putchar+1 + ldx oldputcr + stx putcr+1 + clr lastterm + rts + +* O.S. routine to open input through XMODEM transfer. +xopin pshs x,a,b + ldx #xsmsg + jsr outcount + jsr putcr ;Display message to start XMODEM send. + bsr savevecs + ldx #noop + stx putchar+1 ;Disable character output. + ldx #xgetc + stx getchar+1 ; + clr lastok + clr xcount + lda #1 + sta xpacknum + inca + sta xmode ;set xmode to 2. + puls x,a,b,pc + +* O.S. routine to open output through XMODEM transfer. +xopout pshs x,a,b + bsr savevecs + ldx #xrmsg + jsr outcount ;Display message to start XMODEM receive + jsr putcr + ldx #xputc + stx putchar+1 + ldx #xputcr + stx putcr+1 + jsr xsendinit + lbeq xerror + clr xcount + lda #1 + sta xmode + puls x,a,b,pc + + +* O.S. routine to abort input through XMODEM transfer. +xabtin lda xmode + cmpa #2 + bne xclsend + jsr purge + ldb #CAN + lda #8 +xabtloop jsr osputc + deca + bne xabtloop ;Send 8 CAN characters to kill transfer. + bsr rstvecs + clr xmode + ldx #xamsg + jsr outcount + jsr putcr ;Send diagnostic message. + rts + +* O.S. routine to close output through XMODEM transfer. +xclsout lda xmode + cmpa #1 + bne xclsend + tst xcount + beq xclsdone + lda #128 + suba xcount +xclsloop ldb filler + bsr xputc + deca + bne xclsloop ;Transfer filler chars to force block out. +xclsdone jsr xsendeot ;Send EOT + lbeq xerror + jsr rstvecs + clr xmode +xclsend rts + +* O.S. routine to close input through XMODEM, by gobbling up the remaining +* bytes. +xclsin ldb xmode + cmpb #2 + bne xclsend + jsr putchar + bra xclsin + +* putchar routine for XMODEM +xputc pshs x,a,b + lda xcount + inc xcount + ldx #buf0 + stb a,x ;Store character in XMODEM buffer. + cmpa #127 + bne xputc1 ;is buffer full? + clr xcount + pshs y,u + jsr xsendbuf + lbeq xerror + puls y,u +xputc1 puls x,a,b,pc + +* putcr routine for XMODEM +xputcr pshs b + ldb xmcr + bitb #2 + beq xputcr1 + ldb #CR + bsr xputc +xputcr1 ldb xmcr + bitb #1 + beq xputcr2 + ldb #LF + bsr xputc +xputcr2 puls b + rts + +* getchar routine for XMODEM +xgetc pshs x,a + tst xcount ;No characters left? + bne xgetc1 + pshs y,u + jsr xrcvbuf ;Receive new block. + puls y,u + beq xgetcterm ;End of input? + lda #128 + sta xcount +xgetc1 lda xcount + nega + ldx #buf0+128 + ldb a,x ;Get character from buffer + dec xcount + puls x,a,pc +xgetcterm jsr rstvecs + clr xmode + ldb filler + puls x,a,pc + +xerror jsr rstvecs ;Restore I/O vectors + clr xmode + ldx #xamsg + jsr outcount + jsr putcr + jmp xerrvec + +xerrhand lds savesp + jmp cmdline + +* This is the code for the X command, various XMODEM related commands. +* Syntax: XSaddr,len XLaddr,len XX XOcrlf,filler, XSSaddr,len +xmodem ldx #linebuf+1 + lda ,x+ + anda #CASEMASK ;Convert to uppercase. + cmpa #'X' + beq xeq + cmpa #'L' + beq xload + cmpa #'O' + beq xopts + cmpa #'S' + lbne unk + lda ,x + anda #CASEMASK + cmpa #'S' + beq xss + ldd #$100 ;XSaddr,len command. + jsr scan2parms ;Send binary through XMODEM + jsr xopenout + ldu addr + ldy length +xsbinloop ldb ,u+ + jsr putchar + leay -1,y + bne xsbinloop ;Send all the bytes through XMODEM. + jmp cmdline +xss leax 1,x ;XSSaddr,len command. + jsr xopenout ;Send Srecords through XMODEM + jmp sendrec +xload jsr scanhex ;XLaddr command + tfr d,y ;Load binary through XMODEM + jsr xopenin +xlodloop jsr getchar + tst xmode ;File ended? then done + lbeq cmdline + stb ,y+ + bra xlodloop +xeq jsr xopenin ;XX command + jmp cmdline ;Execute commands received from XMODEM +xopts ldd #$1a + jsr scan2parms + lda addr+1 + sta xmcr + lda length+1 + sta filler + jmp cmdline + +* mnemonics table, ordered alphabetically. +* 5 bytes name, 1 byte category, 2 bytes opcode, 8 bytes total. +mnemtab fcc "ABX " + fcb 0 + fdb $3a + fcc "ADCA " + fcb 7 + fdb $89 + fcc "ADCB " + fcb 7 + fdb $c9 + fcc "ADDA " + fcb 7 + fdb $8b + fcc "ADDB " + fcb 7 + fdb $cb + fcc "ADDD " + fcb 8 + fdb $c3 + fcc "ANDA " + fcb 7 + fdb $84 + fcc "ANDB " + fcb 7 + fdb $c4 + fcc "ANDCC" + fcb 2 + fdb $1c + fcc "ASL " + fcb 10 + fdb $08 + fcc "ASLA " + fcb 0 + fdb $48 + fcc "ASLB " + fcb 0 + fdb $58 + fcc "ASR " + fcb 10 + fdb $07 + fcc "ASRA " + fcb 0 + fdb $47 + fcc "ASRB " + fcb 0 + fdb $57 + fcc "BCC " + fcb 4 + fdb $24 + fcc "BCS " + fcb 4 + fdb $25 + fcc "BEQ " + fcb 4 + fdb $27 + fcc "BGE " + fcb 4 + fdb $2c + fcc "BGT " + fcb 4 + fdb $2e + fcc "BHI " + fcb 4 + fdb $22 + fcc "BHS " + fcb 4 + fdb $24 + fcc "BITA " + fcb 7 + fdb $85 + fcc "BITB " + fcb 7 + fdb $c5 + fcc "BLE " + fcb 4 + fdb $2f + fcc "BLO " + fcb 4 + fdb $25 + fcc "BLS " + fcb 4 + fdb $23 + fcc "BLT " + fcb 4 + fdb $2d + fcc "BMI " + fcb 4 + fdb $2b + fcc "BNE " + fcb 4 + fdb $26 + fcc "BPL " + fcb 4 + fdb $2a + fcc "BRA " + fcb 4 + fdb $20 + fcc "BRN " + fcb 4 + fdb $21 +mnembsr fcc "BSR " + fcb 4 + fdb $8d + fcc "BVC " + fcb 4 + fdb $28 + fcc "BVS " + fcb 4 + fdb $29 + fcc "CLR " + fcb 10 + fdb $0f + fcc "CLRA " + fcb 0 + fdb $4f + fcc "CLRB " + fcb 0 + fdb $5f + fcc "CMPA " + fcb 7 + fdb $81 + fcc "CMPB " + fcb 7 + fdb $c1 + fcc "CMPD " + fcb 9 + fdb $1083 + fcc "CMPS " + fcb 9 + fdb $118c + fcc "CMPU " + fcb 9 + fdb $1183 + fcc "CMPX " + fcb 8 + fdb $8c + fcc "CMPY " + fcb 9 + fdb $108c + fcc "COM " + fcb 10 + fdb $03 + fcc "COMA " + fcb 0 + fdb $43 + fcc "COMB " + fcb 0 + fdb $53 + fcc "CWAI " + fcb 2 + fdb $3c + fcc "DAA " + fcb 0 + fdb $19 + fcc "DEC " + fcb 10 + fdb $0a + fcc "DECA " + fcb 0 + fdb $4a + fcc "DECB " + fcb 0 + fdb $5a + fcc "EORA " + fcb 7 + fdb $88 + fcc "EORB " + fcb 7 + fdb $c8 + fcc "EQU " + fcb 13 + fdb 0 + fcc "EXG " + fcb 11 + fdb $1e +mnemfcb fcc "FCB " + fcb 13 + fdb 1 + fcc "FCC " + fcb 13 + fdb 2 + fcc "FDB " + fcb 13 + fdb 3 + fcc "INC " + fcb 10 + fdb $0c + fcc "INCA " + fcb 0 + fdb $4c + fcc "INCB " + fcb 0 + fdb $5c + fcc "JMP " + fcb 10 + fdb $0e +mnemjsr fcc "JSR " + fcb 8 + fdb $8d + fcc "LBCC " + fcb 5 + fdb $1024 + fcc "LBCS " + fcb 5 + fdb $1025 + fcc "LBEQ " + fcb 5 + fdb $1027 + fcc "LBGE " + fcb 5 + fdb $102c + fcc "LBGT " + fcb 5 + fdb $102e + fcc "LBHI " + fcb 5 + fdb $1022 + fcc "LBHS " + fcb 5 + fdb $1024 + fcc "LBLE " + fcb 5 + fdb $102f + fcc "LBLO " + fcb 5 + fdb $1025 + fcc "LBLS " + fcb 5 + fdb $1023 + fcc "LBLT " + fcb 5 + fdb $102d + fcc "LBMI " + fcb 5 + fdb $102b + fcc "LBNE " + fcb 5 + fdb $1026 + fcc "LBPL " + fcb 5 + fdb $102a + fcc "LBRA " + fcb 6 + fdb $16 + fcc "LBRN " + fcb 5 + fdb $1021 + fcc "LBSR " + fcb 6 + fdb $17 + fcc "LBVC " + fcb 5 + fdb $1028 + fcc "LBVS " + fcb 5 + fdb $1029 + fcc "LDA " + fcb 7 + fdb $86 + fcc "LDB " + fcb 7 + fdb $c6 + fcc "LDD " + fcb 8 + fdb $cc + fcc "LDS " + fcb 9 + fdb $10ce + fcc "LDU " + fcb 8 + fdb $ce + fcc "LDX " + fcb 8 + fdb $8e + fcc "LDY " + fcb 9 + fdb $108e + fcc "LEAS " + fcb 3 + fdb $32 + fcc "LEAU " + fcb 3 + fdb $33 + fcc "LEAX " + fcb 3 + fdb $30 + fcc "LEAY " + fcb 3 + fdb $31 + fcc "LSL " + fcb 10 + fdb $08 + fcc "LSLA " + fcb 0 + fdb $48 + fcc "LSLB " + fcb 0 + fdb $58 + fcc "LSR " + fcb 10 + fdb $04 + fcc "LSRA " + fcb 0 + fdb $44 + fcc "LSRB " + fcb 0 + fdb $54 + fcc "MUL " + fcb 0 + fdb $3d + fcc "NEG " + fcb 10 + fdb $00 + fcc "NEGA " + fcb 0 + fdb $40 + fcc "NEGB " + fcb 0 + fdb $50 + fcc "NOP " + fcb 0 + fdb $12 + fcc "ORA " + fcb 7 + fdb $8a + fcc "ORB " + fcb 7 + fdb $ca + fcc "ORCC " + fcb 2 + fdb $1a + fcc "ORG " + fcb 13 + fdb 4 + fcc "PSHS " + fcb 12 + fdb $34 + fcc "PSHU " + fcb 12 + fdb $36 + fcc "PULS " + fcb 12 + fdb $35 + fcc "PULU " + fcb 12 + fdb $37 + fcc "RMB " + fcb 13 + fdb 5 + fcc "ROL " + fcb 10 + fdb $09 + fcc "ROLA " + fcb 0 + fdb $49 + fcc "ROLB " + fcb 0 + fdb $59 + fcc "ROR " + fcb 10 + fdb $06 + fcc "RORA " + fcb 0 + fdb $46 + fcc "RORB " + fcb 0 + fdb $56 + fcc "RTI " + fcb 0 + fdb $3b + fcc "RTS " + fcb 0 + fdb $39 + fcc "SBCA " + fcb 7 + fdb $82 + fcc "SBCB " + fcb 7 + fdb $c2 + fcc "SET " + fcb 13 + fdb 6 + fcc "SETDP" + fcb 13 + fdb 7 + fcc "SEX " + fcb 0 + fdb $1d + fcc "STA " + fcb 7 + fdb $87 + fcc "STB " + fcb 7 + fdb $c7 + fcc "STD " + fcb 8 + fdb $cd + fcc "STS " + fcb 9 + fdb $10cf + fcc "STU " + fcb 8 + fdb $cf + fcc "STX " + fcb 8 + fdb $8f + fcc "STY " + fcb 9 + fdb $108f + fcc "SUBA " + fcb 7 + fdb $80 + fcc "SUBB " + fcb 7 + fdb $c0 + fcc "SUBD " + fcb 8 + fdb $83 + fcc "SWI " + fcb 0 + fdb $3f + fcb "SWI2 " + fcb 1 + fdb $103f + fcb "SWI3 " + fcb 1 + fdb $113f + fcc "SYNC " + fcb 0 + fdb $13 + fcc "TFR " + fcb 11 + fdb $1f + fcc "TST " + fcb 10 + fdb $0d + fcc "TSTA " + fcb 0 + fdb $4d + fcc "TSTB " + fcb 0 + fdb $5d + +mnemsize equ (*-mnemtab)/8 + +* Register table for PUSH/PULL and TFR/EXG instructions. +* 3 bytes for name, 1 for tfr/exg, 1 for push/pull, 5 total +asmregtab fcc "X " + fcb $01,$10 + fcc "Y " + fcb $02,$20 +aregu fcc "U " + fcb $03,$40 +aregs fcc "S " + fcb $04,$40 + fcc "PC " + fcb $05,$80 + fcc "A " + fcb $08,$02 + fcc "B " + fcb $09,$04 + fcc "D " + fcb $00,$06 + fcc "CC " + fcb $0a,$01 + fcc "CCR" + fcb $0a,$01 + fcc "DP " + fcb $0b,$08 + fcc "DPR" + fcb $0b,$08 +reginval fcc "? " + +ixregs fcc "XYUS" + +* opcode offsets to basic opcode, depends on first nibble. +opcoffs fcb 0,0,0,0,0,0,-$60,-$70 + fcb 0,-$10,-$20,-$30,0,-$10,-$20,-$30 +* mode depending on first nibble of opcode. +modetab fcb 3,0,0,0,0,0,5,4,1,3,5,4,1,3,5,4 +* mode depending on category code stored in mnemtab +modetab2 fcb 0,0,1,5,6,7,7,1,2,2,0,8,9 +* modes in this context: 0 no operands, 1 8-bit immediate, 2 16 bit imm, +* 3, 8-bit address, 4 16 bit address, 5 indexed with postbyte, 6 short +* relative, 7 long relative, 8 pushpul, 9 tftetx + +* Decode instruction pointed to by Y for disassembly (and to find out +* how long it is). On return, U points to appropriate mnemonic table entry, +* Y points past instruction. +* It's rather clumsy code, but we do want to reuse the same table +* as used with assembling. +disdecode clr prebyte + clr amode + lda ,y+ + cmpa #$10 + beq ddec1 + cmpa #$11 + bne ddec2 +ddec1 sta prebyte ;Store $10 or $11 prebyte. + lda ,y+ ;Get new opcode. +ddec2 sta opcode + lsra + lsra + lsra + lsra ;Get high nibble. + ldx #modetab + ldb a,x + stb amode + ldx #opcoffs + lda a,x + adda opcode ;Add opcode offset to opcode. +ddec4 sta opc1 ;Store the 'basis' opcode. + ldu #mnemtab + ldx #mnemsize +ddecloop ldb #13 + cmpb 5,u ;Compare category code with 13 + beq ddec3 ;13=pseudo op, no valid opcode + ldd prebyte + cmpd 6,u + beq ddecfound ;Opcode&prebyte agree, operation found. +ddec3 leau 8,u ;point to next mnemonic + leax -1,x + bne ddecloop + ldu #mnemfcb ;mnemonic not found, use FCB byte. + lda #3 + sta amode ;Store mode 3, 8 bit address. + lda opcode + tst prebyte + beq ddec5 + lda prebyte ;if it was the combination prebyte + clr prebyte ;and opcode that was not found, + leay -1,y ;FCB just the prebyte +ddec5 sta operand+1 ;The byte must be stored as operand. + rts +ddecfound cmpu #mnembsr + bne ddec6 + lda #$8d ;Is it really the BSR opcode? + cmpa opcode + beq ddec6 + ldu #mnemjsr ;We mistakenly found BSR instead of JSR +ddec6 lda amode + anda #$FE + bne ddec7 + lda 5,u ;nibble-dependent mode was 0 or 1, + ldx #modetab2 ;use category dependent mode instead. + lda a,x + sta amode +ddec7 lda amode + asla + ldx #disdectab + jmp [a,x] ;jump dependent on definitive mode. +disdectab fdb noop,opdec1,opdec2,opdec1,opdec2,opdecidx + fdb opdec1,opdec2,opdecpb,opdecpb +disdectab1 fdb noop,noop,noop,noop,noop,noop,noop,noop + fdb opdec1,opdec2,noop,noop,opdec1,opdec2,noop,opdec2 +opdec1 ldb ,y+ + sex +od1a std operand +noop rts +opdec2 ldd ,y++ + bra od1a +opdecpb ldb ,y+ +odpa stb postbyte + rts +opdecidx ldb ,y+ + bpl odpa ;postbytes <$80 have no extra operands. + stb postbyte + andb #$0f + aslb + ldx #disdectab1 + jmp [b,x] + +* Display disassembled instruction after the invocation of disdecode. +* U points to mnemonic table entry. +disdisp tfr u,x + ldb #5 + jsr putline ;Display the mnemonic. + ldb #' ' + jsr putchar + lda amode + asla + ldx #disdisptab + jmp [a,x] ;Perform action dependent on mode. +disdisptab fdb noop,disim8,disim16,disadr8,disadr16 + fdb disidx,disrel8,disrel16,distfr,dispush +disim8 bsr puthash + bra disadr8 +disim16 bsr puthash +disadr16 bsr putdol + ldd operand + jmp outd +disadr8 bsr putdol + lda operand+1 + jmp outbyte +disrel8 bsr putdol + ldb operand+1 + sex +dr8a sty temp + addd temp + jmp outd +disrel16 bsr putdol + ldd operand + bra dr8a + +puthash ldb #'#' + jmp putchar +putdol ldb #'$' + jmp putchar +putcomma ldb #',' + jmp putchar +putspace ldb #' ' + jmp putchar + +dispush ldb #12 + ldx #asmregtab ;Walk through the register table. + clr temp +regloop lda postbyte + anda 4,x + beq dispush1 ;Is bit corresponding to reg set in postbyte + cmpx #aregu + bne dispush3 + sta temp+1 + lda opcode + anda #2 + bne dispush1 ;no u register in pshu pulu. + lda temp+1 +dispush3 cmpx #aregs + bne dispush4 + sta temp+1 + lda opcode + anda #2 + beq dispush1 ;no s register in pshs puls. + lda temp+1 +dispush4 coma + anda postbyte ;remove the bits from postbyte. + sta postbyte + pshs b + tst temp + beq dispush2 + bsr putcomma ;print comma after first register. +dispush2 bsr disregname + inc temp + puls b +dispush1 leax 5,x + decb + bne regloop + rts + +distfr lda postbyte + lsra + lsra + lsra + lsra + bsr distfrsub + bsr putcomma + lda postbyte + anda #$0f +distfrsub ldb #12 + ldx #asmregtab +distfrloop cmpa 3,x + beq distfrend + leax 5,x + decb + bne distfrloop +distfrend bsr disregname + rts + +disregname lda #3 + tfr x,u +drnloop ldb ,u+ + cmpb #' ' + beq drnend + jsr putchar + deca + bne drnloop +drnend rts + +disidxreg lda postbyte + lsra + lsra + lsra + lsra + lsra + anda #3 + ldx #ixregs + ldb a,x + jmp putchar + +disidx clr temp + lda postbyte + bmi disidx1 + anda #$1f + bita #$10 + bne negoffs + jsr outdecbyte + bra discomma +negoffs ldb #'-' + jsr putchar + ora #$f0 + nega + jsr outdecbyte +discomma jsr putcomma ;Display ,Xreg and terminating ] +disindex bsr disidxreg +disindir tst temp ;Display ] if indirect. + beq disidxend + ldb #']' + jsr putchar +disidxend rts +disidx1 bita #$10 + beq disidx2 + ldb #'[' + jsr putchar + inc temp +disidx2 lda postbyte + anda #$0f + asla + ldx #disidxtab + jmp [a,x] ;Jump to routine for indexed mode +disadec2 lda #2 + bra disadeca +disadec1 lda #1 +disadeca jsr putcomma +disadloop ldb #'-' + jsr putchar + deca + bne disadloop + bra disindex +disainc2 lda #2 + bra disainca +disainc1 lda #1 +disainca sta temp+1 + jsr putcomma + jsr disidxreg + lda temp+1 +disailoop ldb #'+' + jsr putchar + deca + bne disailoop + jmp disindir +disax ldb #'A' + jsr putchar + jmp discomma +disbx ldb #'B' + jsr putchar + jmp discomma +disdx ldb #'D' + jsr putchar + jmp discomma +disinval ldb #'?' + jsr putchar + jmp disindir +disnx lda operand+1 + bmi disnxneg +disnx1 jsr putdol + jsr outbyte + jmp discomma +disnxneg ldb #'-' + jsr putchar + nega + bra disnx1 +disnnx jsr putdol + ldd operand + jsr outd + jmp discomma +disnpc jsr putdol + ldb operand+1 + sex +disnpca sty temp2 + addd temp2 + jsr outd + ldx #commapc + ldb #4 + jsr putline + jmp disindir +disnnpc jsr putdol + ldd operand + bra disnpca +disdirect jsr putdol + ldd operand + jsr outd + jmp disindir + +commapc fcc ",PCR" + +disidxtab fdb disainc1,disainc2,disadec1,disadec2 + fdb discomma,disbx,disax,disinval + fdb disnx,disnnx,disinval,disdx + fdb disnpc,disnnpc,disinval,disdirect + +* Display byte A in decimal (0<=A<20) +outdecbyte cmpa #10 + blo odb1 + suba #10 + ldb #'1' + jsr putchar +odb1 adda #'0' + tfr a,b + jmp putchar + +* This is the code for the U command, unassemble instructions in memory. +* Syntax: U or Uaddr or Uaddr,length +unasm bsr disasm + jmp cmdline +disasm ldx #linebuf+1 + ldd #20 + jsr scan2parms ;Scan address,length parameters. +dis1 ldd addr + addd length + std length + ldy addr +unasmloop tfr y,d + jsr outd ;Display instruction address + jsr putspace + pshs y + jsr disdecode + puls x + sty temp + clr temp2 +unadishex lda ,x+ + jsr outbyte + inc temp2 + inc temp2 + cmpx temp + bne unadishex ;Display instruction bytes as hex. +unadisspc ldb #' ' + jsr putchar + inc temp2 + lda #11 + cmpa temp2 ;Fill out with spaces to width 11. + bne unadisspc + bne unadishex + jsr disdisp ;Display disassembled instruction. + tst disflg + bne skipcr + jsr putcr +skipcr cmpy length + bls unasmloop + sty addr + rts + +* Simple 'expression evaluator' for assembler. +expr ldb ,x + cmpb #'-' + bne pos + clrb + leax 1,x +pos pshs b + bsr scanfact + beq exprend1 + tst ,s+ + bne exprend ;Was the minus sign there. + coma + comb + addd #1 + andcc #$fb ;Clear Z flag for valid result. +exprend rts +exprend1 puls b + rts + +scanfact ldb ,x+ + cmpb #'$' + lbeq scanhex ;Hex number if starting with dollar. + cmpb #''' + bne scandec ;char if starting with ' else decimal + ldb ,x+ + lda ,x + cmpa #''' + bne scanchar2 + leax 1,x ;Increment past final quote if it's there. +scanchar2 clra + andcc #$fb ;Clear zero flag. + rts +scandec cmpb #'0' + blo noexpr + cmpb #'9' + bhi noexpr + clr temp + clr temp+1 +scandloop subb #'0' + bcs sdexit + cmpb #10 + bcc sdexit + pshs b + ldd temp + aslb + rola + pshs d + aslb + rola + aslb + rola + addd ,s++ ;Multiply number by 10. + addb ,s+ + adca #0 ;Add digit to 10. + std temp + ldb ,x+ ;Get next character. + bra scandloop +sdexit ldd temp + leax -1,x + andcc #$fb + rts +noexpr orcc #$04 + rts + +* Assemble the instruction pointed to by X. +* Fisrt stage: copy mnemonic to mnemonic buffer. +asminstr lda #5 + ldu #mnembuf +mncploop ldb ,x+ + beq mncpexit + cmpb #' ' + beq mncpexit ;Mnemonic ends at first space or null + andb #CASEMASK + cmpb #'A' + blo nolet + cmpb #'Z' + bls mnemcp1 ;Capitalize letters, but only letters. +nolet ldb -1,x +mnemcp1 stb ,u+ ;Copy to mnemonic buffer. + deca + bne mncploop +mncpexit tsta + beq mncpdone + ldb #' ' +mnfilloop stb ,u+ + deca + bne mnfilloop ;Fill the rest of mnem buffer with spaces. +* Second stage: look mnemonic up using binary search. +mncpdone stx temp3 + clr temp ;Low index=0 + lda #mnemsize + sta temp+1 ;High index=mnemsize. +bsrchloop ldb temp+1 + cmpb #$ff + beq invmnem ;lower limit -1? + cmpb temp + blo invmnem ;hi index lower than low index? + clra + addb temp ;Add indexes. + adca #0 + lsra + rorb ;Divide by 2 to get average + stb temp2 + aslb + rola + aslb + rola + aslb + rola ;Multiply by 8 to get offset. + ldu #mnemtab + leau d,u ;Add offset to table base + tfr u,y + lda #5 + ldx #mnembuf +bscmploop ldb ,x+ + cmpb ,y+ + bne bscmpexit ;Characters don't match? + deca + bne bscmploop + jmp mnemfound ;We found the mnemonic. +bscmpexit ldb temp2 + bcc bscmplower + decb + stb temp+1 ;mnembuftable, adjust low limit. + bra bsrchloop +invmnem ldx #invmmsg + jmp asmerrvec +* Stage 3: Perform routine depending on category code. +mnemfound clr uncert + ldy addr + lda 5,u + asla + ldx #asmtab + jsr [a,x] + sty addr + rts +asmtab fdb onebyte,twobyte,immbyte,lea + fdb sbranch,lbranch,lbra,acc8 + fdb dreg1,dreg2,oneaddr,tfrexg + fdb pushpul,pseudovec + +putbyte stb ,y+ + rts +putword std ,y++ + rts + +onebyte ldb 7,u ;Cat 0, one byte opcode w/o operands RTS + bra putbyte +twobyte ldd 6,u ;Cat 1, two byte opcode w/o operands SWI2 + bra putword +immbyte ldb 7,u ;Cat 2, opcode w/ immdiate operand ANDCC + bsr putbyte + jsr scanops + ldb amode + cmpb #1 + lbne moderr + ldb operand+1 + bra putbyte +lea ldb 7,u ;Cat 3, LEA + bsr putbyte + jsr scanops + lda amode + cmpa #1 + lbeq moderr ;No immediate w/ lea + cmpa #3 + lbhs doaddr + jsr set3 + lda #$8f + sta postbyte + lda #2 + sta opsize ;Use 8F nn nn for direct mode. + jmp doaddr +sbranch ldb 7,u ;Cat 4, short branch instructions + bsr putbyte + jsr startop + leax -1,x + jsr exprvec + lbeq exprerr + jmp shortrel +lbranch ldd 6,u ;Cat 5, long brach w/ two byte opcode + bsr putword +lbra1 jsr startop + leax -1,x + jsr exprvec + lbeq exprerr + jmp longrel +lbra ldb 7,u ;Cat 6, long branch w/ one byte opcode. + jsr putbyte + bra lbra1 +acc8 lda #1 ;Cat 7, 8-bit two operand instructions ADDA + sta opsize + jsr scanops + jsr adjopc + jsr putbyte + jmp doaddr +dreg1 lda #2 ;Cat 8, 16-bit 2operand insns 1byte opc LDX + sta opsize + jsr scanops + jsr adjopc + jsr putbyte + jmp doaddr +dreg2 lda #2 ;Cat 9, 16-bit 2operand insns 2byte opc LDY + sta opsize + jsr scanops + jsr adjopc + lda 6,u + jsr putword + jmp doaddr +oneaddr jsr scanops ;Cat 10, one-operand insns NEG..CLR + ldb 7,u + lda amode + cmpa #1 + lbeq moderr ;No immediate mode + cmpa #3 + bhs oaind ;indexed etc + lda opsize + deca + beq oadir + addb #$10 ;Add $70 for extended direct. +oaind addb #$60 ;And $60 for indexed etc. +oadir jsr putbyte ;And nothing for direct8. + jmp doaddr +tfrexg jsr startop ;Cat 11, TFR and EXG + leax -1,x + ldb 7,u + jsr putbyte + jsr findreg + ldb ,u + aslb + aslb + aslb + aslb + stb postbyte + ldb ,x+ + cmpb #',' + lbne moderr + jsr findreg + ldb ,u + orb postbyte + jmp putbyte +pushpul jsr startop ;Cat 12, PSH and PUL + leax -1,x + ldb 7,u + jsr putbyte + clr postbyte +pploop jsr findreg + ldb 1,u + orb postbyte + stb postbyte + ldb ,x+ + cmpb #',' + beq pploop + leax -1,x + ldb postbyte + jmp putbyte +pseudo ldb 7,u ;Cat 13, pseudo oeprations + aslb + ldx #pseudotab + jmp [b,x] +pseudotab fdb pseudoend,dofcb,dofcc,dofdb + fdb doorg,dormb,pseudoend,pseudoend +dofcb jsr startop + leax -1,x +fcbloop jsr exprvec + lbeq exprerr + jsr putbyte + ldb ,x+ + cmpb #',' + beq fcbloop +pseudoend rts +dofcc jsr startop + tfr b,a ;Save delimiter. +fccloop ldb ,x+ + beq pseudoend + pshs a + cmpb ,s+ + beq pseudoend + jsr putbyte + bra fccloop +dofdb jsr startop + leax -1,x +fdbloop jsr exprvec + lbeq exprerr + jsr putword + ldb ,x+ + cmpb #',' + beq fdbloop + rts +doorg jsr startop + leax -1,x + jsr exprvec + lbeq exprerr + tfr d,y + rts +dormb jsr startop + leax -1,x + jsr exprvec + lbeq exprerr + leay d,y + rts + + +* Adjust opcdoe depending on mode (in $80-$FF range) +adjopc ldb 7,u + lda amode + cmpa #2 + beq adjdir ;Is it direct? + cmpa #3 + bhs adjind ;Indexed etc? + rts ;Not, then immediate, no adjust. +adjind addb #$20 ;Add $20 to opcode for indexed etc modes. + rts +adjdir addb #$10 ;Add $10 to opcode for direct8 + lda opsize + deca + bne adjind ;If opsize=2, add another $20 for extended16 + rts + +* Start scanning of operands. +startop ldx temp3 + clr amode + jmp skipspace + +* amode settings in assembler: 1=immediate, 2=direct/extended, 3=indexed +* etc. 4=pc relative, 5=indirect, 6=pcrelative and indirect. + +* This subroutine scans the assembler operands. +scanops bsr startop + cmpb #'[' + bne noindir + lda #5 ;operand starts with [, then indirect. + sta amode + ldb ,x+ +noindir cmpb #'#' + lbeq doimm + cmpb #',' + lbeq dospecial + andb #CASEMASK ;Convert to uppercase. + lda #$86 + cmpb #'A' + beq scanacidx + lda #$85 + cmpb #'B' + beq scanacidx + lda #$8B + cmpb #'D' + bne scanlab +scanacidx ldb ,x+ ;Could it be A,X B,X or D,X + cmpb #',' + bne nocomma + sta postbyte + clr opsize + jsr set3 + jsr scanixreg + bra scanend +nocomma leax -1,x +scanlab leax -1,x ;Point to the start of the operand + jsr exprvec + lbeq exprerr + std operand + tst uncert + bne opsz2 ;Go for extended if operand unknown. + subd dpsetting + tsta ;Can we use 8-bit operand? + bne opsz2 + inca + bra opsz1 +opsz2 lda #2 +opsz1 sta opsize ;Set opsize depending on magnitude of op. + lda amode + cmpa #5 + bne opsz3 ;Or was it indirect. + lda #2 ;Then we have postbyte and opsize=2 + sta opsize + lda #$8F + sta postbyte + bra opsz4 +opsz3 lda #2 + sta amode ;Assume direct or absolute addressing +opsz4 ldb ,x+ + cmpb #',' + lbeq doindex ;If followed by, then indexed. +scanend lda amode + cmpa #5 + blo scanend2 ;Was it an indirect mode? + lda postbyte + ora #$10 ;Set indirect bit. + sta postbyte + ldb ,x+ + cmpb #']' ;Check for the other ] + lbeq moderr +scanend2 rts +doimm jsr exprvec ;Immediate addressing. + lbeq exprerr + std operand + lda amode + cmpa #5 + lbeq moderr ;Inirect mode w/ imm is illegal. + lda #$01 + sta amode + rts +dospecial jsr set3 + clr opsize + clra +adecloop ldb ,x+ + cmpb #'-' + bne adecend + inca ;Count the - signs for autodecrement. + bra adecloop +adecend leax -1,x + cmpa #2 + lbhi moderr + tsta + bne autodec + clr postbyte + jsr scanixreg + clra +aincloop ldb ,x+ + cmpb #'+' + bne aincend + inca + bra aincloop ;Count the + signs for autoincrement. +aincend leax -1,x + cmpa #2 + lbhi moderr + tsta + bne autoinc + lda #$84 + ora postbyte + sta postbyte + bra scanend +autoinc adda #$7f + ora postbyte + sta postbyte + bra scanend +autodec adda #$81 + sta postbyte + jsr scanixreg + lbra scanend +doindex clr postbyte + jsr set3 + ldb ,x+ + andb #CASEMASK ;Convert to uppercase. + cmpb #'P' + lbeq dopcrel ;Check for PC relative. + leax -1,x + clr opsize + bsr scanixreg + ldd operand + tst uncert + bne longindex ;Go for long index if operand unknown. + cmpd #-16 + blt shortindex + cmpd #15 + bgt shortindex + lda amode + cmpa #5 + beq shortind1 ;Indirect may not be 5-bit index + ;It's a five-bit index. + andb #$1f + orb postbyte + stb postbyte + lbra scanend +shortindex cmpd #-128 + blt longindex + cmpd #127 + bgt longindex +shortind1 inc opsize + ldb #$88 + orb postbyte + stb postbyte + lbra scanend +longindex lda #$2 + sta opsize + ldb #$89 + orb postbyte + stb postbyte + lbra scanend +dopcrel ldb ,x+ + andb #CASEMASK ;Convert to uppercase + cmpb #'C' + blo pcrelend + cmpb #'R' + bhi pcrelend + bra dopcrel ;Scan past the ,PCR +pcrelend leax -1,x + ldb #$8C + orb postbyte ;Set postbyte + stb postbyte + inc amode ;Set addr mode to PCR + lbra scanend + +* Scan for one of the 4 index registers and adjust postbyte. +scanixreg ldb ,x+ + andb #CASEMASK ;Convert to uppercase. + pshs x + ldx #ixregs + clra +scidxloop cmpb ,x+ + beq ixfound + adda #$20 + bpl scidxloop + jmp moderr ;Index register not found where expected. +ixfound ora postbyte + sta postbyte ;Set index reg bits in postbyte. + puls x + rts + +* This routine sets amode to 3, if it was less. +set3 lda amode + cmpa #3 + bhs set3a + lda #3 + sta amode +set3a rts + +* This subroutine lays down the address. +doaddr lda amode + cmpa #3 + blo doa1 + ldb postbyte + jsr putbyte + lda amode + anda #1 + beq doapcrel ;pc rel modes. +doa1 lda opsize + tsta + beq set3a + deca + beq doa2 + ldd operand + jmp putword +doa2 ldb operand+1 + jmp putbyte +doapcrel sty addr + ldd operand + subd addr + subd #1 + tst uncert + bne pcrlong + cmpd #-128 + blt pcrlong + cmpd #-127 + bgt pcrlong + lda #1 + sta opsize + jmp putbyte +pcrlong subd #1 + leay -1,y + inc postbyte + pshs d + ldb postbyte + jsr putbyte + lda #2 + sta opsize + puls d + jmp putword + +* This routine checks and lays down short relative address. +shortrel sty addr + subd addr + subd #1 + cmpd #-128 + blt brerr + cmpd #127 + bgt brerr + jsr putbyte + lda #4 + sta amode + lda #1 + sta opsize + rts +* This routine lays down long relative address. +longrel sty addr + subd addr + subd #2 + jsr putword + lda #4 + sta amode + lda #2 + sta opsize + rts + +brerr ldx #brmsg + jmp asmerrvec +exprerr ldx #exprmsg + jmp asmerrvec +moderr ldx #modemsg + jmp asmerrvec +asmerr pshs x + jsr xabortin + puls x + jsr outcount + jsr putcr + lds savesp + jmp cmdline + +* Find register for TFR and PSH instruction +findreg ldb #12 + pshs y,b + ldu #asmregtab +findregloop tfr x,y + lda #3 +frcmps ldb ,u + cmpb #' ' + bne frcmps1 + ldb ,y + cmpb #'A' + blt frfound +frcmps1 ldb ,y+ + andb #CASEMASK + cmpb ,u+ + bne frnextreg + deca + bne frcmps + inca + bra frfound +frnextreg inca + leau a,u + dec ,s + bne findregloop + lbra moderr +frfound leau a,u + tfr y,x + puls y,b + rts + +* This is the code for the A command, assemble instructions. +* Syntax: Aaddr +asm ldx #linebuf+1 + jsr scanhex + std addr + inc disflg + + +asmloop ldy #0 + sty length + ldd addr + pshs d + jsr dis1 ;display unassembled line + ldd addr + std nxtadd + + puls d + std addr + +* ldd addr +* jsr outd + + ldb #TAB + jsr putchar ;Print TAB + ldx #linebuf + ldb #128 + jsr getline ;Get new line + tstb + beq next + +*** beq asmend ;Exit on empty line. + abx + clr ,x ;Make line zero terminated. + ldx #linebuf + lda ,x + cmpa #'.' + beq asmend + jsr asminstr + bra asmloop + +next ldd nxtadd + std addr + bra asmloop + +asmend clr disflg + jmp cmdline + + +* Jump table for monitor routines that are usable by other programs. + org $ffc0 + jmp outbyte + jmp outd + jmp scanbyte + jmp scanhex + jmp scanfact + jmp asminstr + + +* Interrupt vector addresses at top of ROM. Most are vectored through jumps +* in RAM. + org $fff2 + fdb swi3vec + fdb swi2vec + fdb firqvec + fdb irqvec + fdb swivec + fdb nmivec + fdb reset + + end diff -r 000000000000 -r 9a224bd9b45f monitor.asm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/monitor.asm Mon Jul 02 02:12:31 2018 +0900 @@ -0,0 +1,2905 @@ + ;Buggy machine language monitor and rudimentary O.S. version 1.0 + +* Memory map of SBC +* $0-$40 Zero page variables reserved by monitor and O.S. +* $40-$FF Zero page portion for user programs. +* $100-$17F Xmodem buffer 0, terminal input buffer, +* $180-$1FF Xmodem buffer 1, terminal output buffer. +* $200-$27F Terminal input line. +* $280-$2FF Variables reserved by monitor and O.S. +* $300-$400 System stack. +* $400-$7FFF RAM for user programs and data. +* $8000-$DFFF PROM for user programs. +* $E000-$E1FF I/O addresses. +* $E200-$E3FF Reserved. +* $E400-$FFFF Monitor ROM + +* Reserved Zero page addresses + org $0000 + setdp 0 +* First the I/O routine vectors. +getchar rmb 3 ;Jump to getchar routine. +putchar rmb 3 ;Jump to putchar routine. +getline rmb 3 ;Jump to getline routine. +putline rmb 3 ;Jump to putline routine. +putcr rmb 3 ;Jump to putcr routine. +getpoll rmb 3 ;Jump to getpoll routine. +xopenin rmb 3 ;Jump to xopenin routine. +xopenout rmb 3 ;Jump to xopenout routine. +xabortin rmb 3 ;Jump to xabortin routine. +xclosein rmb 3 ;Jump to xclosein routine. +xcloseout rmb 3 ;Jump to xcloseout routine. +delay rmb 3 ;Jump to delay routine. + +*Next the system variables in the zero page. +temp rmb 2 ;hex scanning/disasm +temp2 rmb 2 ;Hex scanning/disasm +temp3 rmb 2 ;Used in Srecords, H command +timer rmb 3 ;3 byte timer, incremented every 20ms +xpacknum rmb 1 ;Packet number for XMODEM block, +xsum rmb 1 ;XMODEM checksum +lastok rmb 1 ;flag to indicate last block was OK +xcount rmb 1 ;Count of characters in buffer. +xmode rmb 1 ;XMODEM mode, 0 none, 1 out, 2 in. + +* I/O buffers. +buflen equ 128 ;Length of input line buffer. + org $100 +buf0 rmb 128 ;Xmodem buffer 0, serial input buffer. +buf1 rmb 128 ;Xmodem buffer 1, serial output buffer. +linebuf rmb buflen ;Input line buffer. + + +* Interrupt vectors (start at $280) +* All interrupts except RESET are vectored through jumps. +* FIRQ is timer interrupt, IRQ is ACIA interrupt. +swi3vec rmb 3 +swi2vec rmb 3 +firqvec rmb 3 +irqvec rmb 3 +swivec rmb 3 +nmivec rmb 3 +xerrvec rmb 3 ;Error handler for XMODEM error. +exprvec rmb 3 ;Expression evaluator in assembler. +asmerrvec rmb 3 ;Error handler for assembler errors. + +* Next the non zero page system variables. +oldpc rmb 2 ;Saved pc value for J command. +addr rmb 2 ;Address parameter. +length rmb 2 ;Length parameter. + +brkpoints equ 4 ;Number of settable breakpoints. +bpaddr rmb brkpoints*3 ;Address and byte for each break point. +stepbp rmb 3 ;Address of P command break point. + +sorg rmb 2 ;Origin address of S record entry. +soffs rmb 2 ;Offset load adrr-addr in record + +oldgetc rmb 2 ;Old getchar address. +oldputc rmb 2 ;Old putchar address. +oldputcr rmb 2 ;Old putcr address. +lastterm rmb 1 ;Last terminating character. +filler rmb 1 ;Filler at end of XMODEM file. +xmcr rmb 1 ;end-of-line characters for XMODEM send. +savesp rmb 2 ;Save sp to restore it on error. + +* Following variables are used by assembler/disassembler. +prebyte rmb 1 +opc1 rmb 1 +opcode rmb 1 +postbyte rmb 1 +amode rmb 1 +operand rmb 2 +mnembuf rmb 5 ;Buffer to store capitalized mnemonic. +opsize rmb 1 ;SIze (in bytes) of extra oeprand (0--2) +uncert rmb 1 ;Flag to indicate that op is unknown. +dpsetting rmb 2 + +endvars equ * + +ramstart equ $400 ;first free RAM address. + +ramtop equ $8000 ;top of RAM. + +* I/O port addresses +aciactl equ $e000 ;Control port of ACIA +aciasta equ $e000 ;Status port of ACIA +aciadat equ $e001 ;Data port of ACIA + +* ASCII control characters. +SOH equ 1 +EOT equ 4 +ACK equ 6 +BS equ 8 +TAB equ 9 +LF equ 10 +CR equ 13 +NAK equ 21 +CAN equ 24 +DEL equ 127 + +CASEMASK equ $DF ;Mask to make lowercase into uppercase. + +* Monitor ROM starts here. + org $E400 + +reset orcc #$FF ;Disable interrupts. + clra + tfr a,dp ;Set direct page register to 0. + lds #ramstart + ldx #intvectbl + ldu #swi3vec + ldb #osvectbl-intvectbl + bsr blockmove ;Initialize interrupt vectors from ROM. + ldx #osvectbl + ldu #0 + ldb #endvecs-osvectbl + bsr blockmove ;Initialize I/O vectors from ROM. + bsr initacia ;Initialize serial port. + andcc #$0 ;Enable interrupts +* Put the 'saved' registers of the program being monitored on top of the +* stack. There are 12 bytes on the stack for cc,b,a,dp,x,y,u and pc +* pc is initialized to $400, the rest to zero. + ldx #0 + tfr x,y + ldu #ramstart + pshs x,u + pshs x,y + pshs x,y + ldx #oldpc + ldb #endvars-oldpc +clvar clr ,x+ + decb + bne clvar ;Clear the variable area. + ldd #$1A03 + std filler ;Set XMODEM filler and end-of-line. + ldx #welcome + jsr outcount + jsr putcr ;Print a welcome message. + jmp cmdline +* Block move routine, from X to U length B. Modifies them all and A. +blockmove lda ,x+ + sta ,u+ + decb + bne blockmove + rts + +* Initialize serial communications port, buffers, interrupts. +initacia ldb #$03 + stb aciactl + ldb #%00110101 + rts + +* O.S. routine to read a character into B register. +osgetc ldb aciasta + bitb #$01 + beq osgetc + ldb aciadat + rts + +;O.S. rotuine to check if there is a character ready to be read. +osgetpoll ldb aciasta + bitb #$01 + bne poltrue + clrb + rts +poltrue ldb #$ff + rts + +* O.S. routine to write the character in the B register. +osputc pshs a +putcloop lda aciasta + bita #$02 + beq putcloop + stb aciadat + puls a + rts + +* O.S. routine to read a line into memory at address X, at most B chars +* long, return actual length in B. Permit backspace editing. +osgetl pshs a,x + stb temp + clra +osgetl1 jsr getchar + andb #$7F + cmpb #BS + beq backsp + cmpb #DEL + bne osgetl2 +backsp tsta ;Recognize BS and DEL as backspace key. + beq osgetl1 ;ignore if line already zero length. + ldb #BS + jsr putchar + ldb #' ' + jsr putchar + ldb #BS ;Send BS,space,BS. This erases last + jsr putchar ;character on most terminals. + leax -1,x ;Decrement address. + deca + bra osgetl1 +osgetl2 cmpb #CR + beq newline + cmpb #LF + bne osgetl3 ;CR or LF character ends line. + ldb lastterm + cmpb #CR + beq osgetl1 ;Ignore LF if it comes after CR + ldb #LF +newline stb lastterm + jsr putcr + tfr a,b ;Move length to B + puls a,x ;restore registers. + rts ;<--- Here is the exit point. +osgetl3 cmpb #TAB + beq dotab + cmpb #' ' + blo osgetl1 ;Ignore control characters. + cmpa temp + beq osgetl1 ;Ignore char if line full. + jsr putchar ;Echo the character. + stb ,x+ ;Store it in memory. + inca + bra osgetl1 +dotab ldb #' ' + cmpa temp + beq osgetl1 + jsr putchar + stb ,x+ + inca + bita #7 ;Insert spaces until length mod 8=0 + bne dotab + bra osgetl1 + +* O.S. routine to write a line starting at address X, B chars long. +osputl pshs a,b,x + tfr b,a + tsta + beq osputl1 +osputl2 ldb ,x+ + jsr putchar + deca + bne osputl2 +osputl1 puls a,b,x + rts + +* O.S. routine to terminate a line. +oscr pshs b + ldb #CR + jsr putchar + ldb #LF + jsr putchar ;Send the CR and LF characters. + puls b + rts + +* Output a counted string at addr X +outcount pshs x,b + ldb ,x+ + jsr putline + puls x,b + rts + +timerirq inc timer+2 + bne endirq + inc timer+1 + bne endirq + inc timer + rti +aciairq nop +endirq rti + +* Wait D times 20ms. +osdly addd timer+1 +dlyloop cmpd timer+1 + bne dlyloop + rts + +* This table will be copied to the interrupt vector area in RAM. +intvectbl jmp endirq + jmp endirq + jmp timerirq + jmp aciairq + jmp unlaunch + jmp endirq + jmp xerrhand + jmp expr + jmp asmerrvec +* And this one to the I/O vector table. +osvectbl jmp osgetc + jmp osputc + jmp osgetl + jmp osputl + jmp oscr + jmp osgetpoll + jmp xopin + jmp xopout + jmp xabtin + jmp xclsin + jmp xclsout + jmp osdly +endvecs equ * + +* The J command returns here. +stakregs pshs x ;Stack something where the pc comes + pshs cc,b,a,dp,x,y,u ;Stack the normal registers. + ldx oldpc + stx 10,s ;Stack the old pc value. + bra unlaunch1 +* The G and P commands return here through a breakpoint. +* Registers are already stacked. +unlaunch ldd 10,s + subd #1 + std 10,s ;Decrement pc before breakpoint +unlaunch1 andcc #$0 ;reenable the interrupts. + jsr disarm ;Disarm the breakpoints. + jsr dispregs +cmdline jsr xcloseout + sts savesp + ldx #linebuf + ldb #buflen + jsr getline + tstb + beq cmdline ;Ignore line if it is empty + abx + clr ,x ;Make location after line zero. + ldx #linebuf + ldb ,x+ + andb #CASEMASK ;Make 1st char uppercase. + subb #'A' + bcs unk + cmpb #26 + bcc unk ;Unknown cmd if it is not a letter. + ldx #cmdtab + aslb ;Index into command table. + jmp [b,x] + +cmdtab fdb asm,break,unk,dump + fdb enter,find,go,hex + fdb inp,jump,unk,unk + fdb move,unk,unk,prog + fdb unk,regs,srec,trace + fdb unasm,unk,unk,xmodem + fdb unk,unk + +* Unknown command handling routine. +unk jsr xabortin + ldx #unknown + jsr outcount + jsr putcr + jmp cmdline + + + +* Here are some useful messages. +welcome fcb unknown-welcome-1 + fcc "Welcome to BUGGY version 1.0" +unknown fcb brkmsg-unknown-1 + fcc "Unknown command" +brkmsg fcb clrmsg-brkmsg-1 + fcc "Breakpoint set" +clrmsg fcb fullmsg-clrmsg-1 + fcc "Breakpoint cleared" +fullmsg fcb smsg-fullmsg-1 + fcc "Breakpoints full" +smsg fcb lastrec-smsg-1 + fcc "Error in S record" +lastrec fcb xsmsg-lastrec-1 + fcc "S9030000FC" +xsmsg fcb xrmsg-xsmsg-1 + fcc "Start XMODEM Send" +xrmsg fcb xamsg-xrmsg-1 + fcc "Start XMODEM Receive" +xamsg fcb invmmsg-xamsg-1 + fcc "XMODEM transfer aborted" +invmmsg fcb exprmsg-invmmsg-1 + fcc "Invalid mnemonic" +exprmsg fcb modemsg-exprmsg-1 + fcc "Expression error" +modemsg fcb brmsg-modemsg-1 + fcc "Addressing mode error" +brmsg fcb endmsg-brmsg-1 + fcc "Branch too long" +endmsg equ * + +* Output hex digit contained in A +hexdigit adda #$90 + daa + adca #$40 + daa ;It's the standard conversion trick ascii + tfr a,b ;to hex without branching. + jsr putchar + rts + +* Output contents of A as two hex digits +outbyte pshs a + lsra + lsra + lsra + lsra + bsr hexdigit + puls a + anda #$0f + bra hexdigit + +* Output contents of d as four hex digits +outd pshs b + bsr outbyte + puls a + bsr outbyte + rts + +* Skip X past spaces, B is first non-space character. +skipspace ldb ,x+ + cmpb #' ' + beq skipspace + rts + +* Convert ascii hex digit in B register to binary Z flag set if no hex digit. +convb subb #'0' + blo convexit + cmpb #9 + bls cb2 + andb #CASEMASK ;Make uppercase. + subb #7 ;If higher than digit 9 it must be a letter. + cmpb #9 + bls convexit + cmpb #15 + bhi convexit +cb2 andcc #$FB ;clear zero + rts +convexit orcc #$04 + rts + +scanexit ldd temp + leax -1,x + tst temp2 + rts ;<-- exit point of scanhex + +* Scan for hexadecimal number at address X return in D, Z flag is set it no +* number found. +scanhex clr temp + clr temp+1 + clr temp2 + bsr skipspace +scloop jsr convb + beq scanexit + pshs b + ldd temp + aslb + rola + aslb + rola + aslb + rola + aslb + rola + addb ,s+ + std temp + inc temp2 + ldb ,x+ + bra scloop + +scan2parms std length + bsr scanhex + beq sp2 + std addr + bsr skipspace + cmpb #',' + bne sp2 + bsr scanhex + beq sp2 + std length +sp2 rts + +* Scan two hexdigits at in and convert to byte into A, Z flag if error. +scanbyte bsr skipspace + bsr convb + beq sb1 + tfr b,a + ldb ,x+ + bsr convb + beq sb1 + asla + asla + asla + asla + stb temp + adda temp + andcc #$fb ;Clear zero flag +sb1 rts + + +* This is the code for the D command, hex/ascii dump of memory +* Syntax: D or D or D, +dump ldx #linebuf+1 + ldd #$40 + jsr scan2parms ;Scan address and length, default length=64 + ldy addr +dh1 lda #16 + sta temp+1 + tfr y,d + jsr outd + ldb #' ' + jsr putchar +dh2 lda ,y+ ;display row of 16 mem locations as hex + jsr outbyte + ldb #' ' + lda temp+1 + cmpa #9 + bne dh6 + ldb #'-' ;Do a - after the eighth byte. +dh6 jsr putchar + dec temp+1 + bne dh2 + leay -16,y ;And now for the ascii dump. + lda #16 +dh3 ldb ,y+ + cmpb #' ' + bhs dh4 + ldb #'.' +dh4 cmpb #DEL + blo dh5 + ldb #'.' ;Convert all nonprintables to . +dh5 jsr putchar + deca + bne dh3 + jsr putcr + ldd length + subd #16 + std length + bhi dh1 + sty addr + jmp cmdline + +* This is the code for the E command, enter hex bytes or ascii string. +* Syntax E or E or E or E"string" +enter ldx #linebuf+1 + jsr scanhex + beq ent1 + std addr +ent1 bsr entline + lbne cmdline ;No bytes, then enter interactively. +ent2 ldb #'E' + jsr putchar + ldd addr + jsr outd + ldb #' ' + jsr putchar ;Display Eaddr + space + ldx #linebuf + ldb #buflen + jsr getline ;Get the line. + abx + clr ,x + ldx #linebuf + bsr entline + bne ent2 + jmp cmdline + +* Enter a line of hex bytes or ascci string at address X, Z if empty. +entline jsr skipspace + tstb + beq entexit + cmpb #'"' + beq entasc + leax -1,x + ldy addr +entl2 jsr scanbyte ;Enter hex digits. + beq entdone + sta ,y+ + bra entl2 +entasc ldy addr +entl3 lda ,x+ + tsta + beq entdone + cmpa #'"' + beq entdone + sta ,y+ + bra entl3 +entdone sty addr + andcc #$fb + rts +entexit orcc #$04 + rts + +*This is the code for the I command, display the contents of an address +* Syntax: Iaddr +inp ldx #linebuf+1 + jsr scanhex + tfr d,x + lda ,x ;Read the byte from memory. + jsr outbyte ;Display itin hex. + jsr putcr + jmp cmdline + +*This is the code for the H command, display result of simple hex expression +*Syntax Hhexnum{+|-hexnum} +hex ldx #linebuf+1 + jsr scanhex + std temp3 +hexloop jsr skipspace + cmpb #'+' + bne hex1 + jsr scanhex + addd temp3 + std temp3 + bra hexloop +hex1 cmpb #'-' + bne hexend + jsr scanhex + comb + coma + addd #1 + addd temp3 + std temp3 + bra hexloop +hexend ldd temp3 + jsr outd + jsr putcr + jmp cmdline + +* This is the code for the G command, jump to the program +* Syntax G or G +go ldx #linebuf+1 + jsr scanhex + beq launch + std 10,s ;Store parameter in pc location. +launch jsr arm ;Arm the breakpoints. + puls cc,b,a,dp,x,y,u,pc + +* This is the code for the J command, run a subroutine. +* Syntax J +jump ldx #linebuf+1 + ldd 10,s + std oldpc ;Save old pc + jsr scanhex + std 10,s ;Store parameter in PC location + tfr s,x + leas -2,s + tfr s,u + ldb #12 ;Move the saved register set 2 addresses + jsr blockmove ;down on the stack. + ldd #stakregs + std 12,s ;Prepare subroutine return address. + bra launch ;Jump to the routine. + + +* This is the code for the P command, run instruction followed by breakpoint +* Syntax P +prog ldy 10,s ;Get program counter value. + jsr disdecode ;Find out location past current insn. + sty stepbp + bra launch + +* This is the code for the T command, single step trace an instruction. +* Syntax T +trace jsr traceone + jsr dispregs + jmp cmdline + +traceone orcc #$50 ;Disable the interrupts. + ldd ,s++ + std oldpc ;Remove saved pc from stack. + ldd #traceret + std firqvec+1 ;Adjust timer IRQ vector. + sync ;Synchronize on the next timer interrupt. + ;1 cycle + ldx #4441 ;3 cycles +traceloop leax -1,x ;6 cycles\x4441= 39969 cycles. + bne traceloop ;3 cycles/ + nop ;2 cycles. + nop ;2 cycles. + nop ;2 cycles. + brn traceret ;3 cycles. + puls x,y,u,a,b,dp,cc,pc ;17 cycles, total=39999 20ms @ 2MHz + ;Pull all registers and execute. + ;Is timed such that next timer IRQ + ;occurs right after it. +traceret puls cc + pshs x,y,u,a,b,dp,cc;Store full register set instead of cc. + ldd #timerirq + std firqvec+1 ;Restore timer IRQ vector. + jmp [oldpc] + + +* Display the contents of 8 bit register, name in B, contents in A +disp8 jsr putchar + ldb #'=' + jsr putchar + jsr outbyte + ldb #' ' + jsr putchar + rts + +* Display the contents of 16 bit register, name in B, contents in Y +disp16 jsr putchar + ldb #'=' + jsr putchar + tfr y,d + jsr outd + ldb #' ' + jsr putchar + rts + +* Display the contents of the registers and disassemble instruction at +* PC location. +dispregs ldb #'X' + ldy 6,s ;Note that there's one return address on + bsr disp16 ;stack so saved register offsets are + ldb #'Y' ;inremented by 2. + ldy 8,s + bsr disp16 + ldb #'U' + ldy 10,s + bsr disp16 + ldb #'S' + tfr s,y + leay 14,y ;S of the running program is 12 higher, + ;because regs are not stacked when running. + bsr disp16 + ldb #'A' + lda 3,s + bsr disp8 + ldb #'B' + lda 4,s + bsr disp8 + ldb #'D' + lda 5,s + bsr disp8 + ldb #'C' + lda 2,s + bsr disp8 + jsr putcr + ldb #'P' + ldy 12,s + bsr disp16 + jsr disdecode + jsr disdisp ;Disassemble instruction at PC + jsr putcr + rts + + +* This is the code for the R command, display or alter the registers. +* Syntax R or R +regs ldx #linebuf+1 + jsr skipspace + tstb + bne setreg + bsr dispregs ;Display regs ifnothing follows. + jmp cmdline +setreg ldy #regtab + clra + andb #CASEMASK ;Make letter uppercase. +sr1 tst ,y + lbeq unk ;At end of register tab, unknown reg + cmpb ,y+ + beq sr2 ;Found the register? + inca + bra sr1 +sr2 pshs a + jsr scanhex ;Convert the hex argument. + pshs d + lda 2,s ;Get register number. + cmpa #4 + bcc sr3 + ldb 1,s ;It's 8 bit. + leas 3,s ;Remove temp stuff from stack. + stb a,s ;Store it in the reg on stack. + jmp cmdline +sr3 cmpa #8 + bcc sr4 + puls x ;It's 16 bit. + leas 1,s + lsla + suba #4 ;Convert reg no to stack offset. + stx a,s + jmp cmdline +sr4 puls u ;It's the stack pointer. + leas 1,s + leau -12,u + tfr s,x + tfr u,s ;Set new stack pointer. + ldb #12 + jsr blockmove ;Move register set to new stack location. + jmp cmdline + +regtab FCC "CABDXYUPS " + +* Disarm the breakpoints, this is replace the SWI instructions with the +* original byte. +disarm ldx #bpaddr + lda #brkpoints+1 +disarm1 ldu ,x++ + ldb ,x+ ;Get address in u, byte in b + cmpu #0 + beq disarm2 + stb ,u +disarm2 deca + bne disarm1 + ldu #0 + stu -3,x ;Clear the step breakpoint. + rts + +* Arm the breakponts, this is replace the byte at the breakpoint address +* with an SWI instruction. +arm ldx #bpaddr+brkpoints*3 + lda #brkpoints+1 ;Arm them in reverse order of disarming. +arm1 ldu ,x ;Get address in u. + beq arm2 + ldb ,u + stb 2,x + cmpu 12,s ;Compare to program counter location + beq arm2 + ldb #$3F + stb ,u ;Store SWI instruction if not equal. +arm2 leax -3,x + deca + bne arm1 + rts + +* This is the code for the break command, set, clear display breakpoints. +* Syntax B or B. B displays, B sets or clears breakpoint. +break lda #brkpoints + sta temp2+1 ;Store number of breakpoints to visit. + ldx #linebuf+1 + jsr scanhex + beq dispbp ;No number then display breakpoints + ldx #bpaddr + ldu #0 + tfr u,y +bp1 cmpd ,x + beq clearit ;Found the breakpoint, so clear it, + cmpu ,x ;Is location zero + bne bp2 + tfr x,y ;Set free address to y +bp2 leax 3,x + dec temp2+1 + bne bp1 + cmpy #0 ;Address not found in list of breakpoints + beq bpfull ;Was free address found. + std ,y ;If so, store breakpoint there. + ldx #brkmsg +bpexit jsr outcount + jsr putcr + jmp cmdline +clearit clra + clrb + std ,x + ldx #clrmsg + bra bpexit +bpfull ldx #fullmsg + bra bpexit + +dispbp ldx #bpaddr +dbp1 ldd ,x + beq dbp2 + jsr outd + ldb #' ' + jsr putchar +dbp2 leax 3,x + dec temp2+1 + bne dbp1 + jsr putcr + jmp cmdline + +* Scan hex byte into a and add it to check sum in temp2+1 +addchk jsr scanbyte + lbeq srecerr + tfr a,b + addb temp2+1 + stb temp2+1 + rts + +* This tis the code for the S command, the Motorola S records entry. +* Syntax SO or SS, or S1 or S9 +srec ldx #linebuf+1 + ldb ,x+ + andb #CASEMASK + cmpb #'O' + beq setsorg + cmpb #'S' + beq sendrec + ldb -1,x + clr temp3 + cmpb #'1' + beq readrec + cmpb #'9' + bne srecerr + inc temp3 +readrec clr temp2+1 ;clear checksum. + bsr addchk + suba #2 ;discount the address bytes from the count. + sta temp3+1 ;Read length byte. + bsr addchk + pshs a + bsr addchk + puls b + exg a,b ;Read address into d. + ldu sorg + beq rr1 + ldu soffs + bne rr1 + pshs d ;Sorg is nonzero and soffs is zero, now + subd sorg ;set soffs + std soffs + puls d +rr1 subd soffs ;Subtract the address offset. + tfr d,y +rr2 bsr addchk + dec temp3+1 + beq endrec + sta ,y+ + bra rr2 +endrec inc temp2+1 ;Check checksum. + bne srecerr + tst temp3 + lbeq cmdline ;Was it no S9 record? + cmpy #0 + beq endrec1 + sty 10,s ;Store address into program counter. +endrec1 clra + clrb + std sorg ;Reset sorg, next S loads will be normal. + std soffs + jmp cmdline +srecerr jsr xabortin + ldx #smsg ;Error in srecord, display message. + jsr outcount + jsr putcr + jmp cmdline +setsorg jsr scanhex ;Set S record origin. + std sorg + clra + clrb + std soffs + jmp cmdline +* Send a memory region as S-records. +sendrec ldd #$100 ;Scan address and length parameter. + jsr scan2parms + ldd sorg + beq ss1 + ldd addr + subd sorg + std soffs ;Compute offset for origin. +ss1 ldd length + beq endss ;All bytes sent? + cmpd #16 + blo ss2 + ldb #16 ;If more than 16 left, then send 16. +ss2 stb temp + negb + ldu length + leau b,u + stu length ;Discount line length from length. + ldb #'S' + jsr putchar + ldb #'1' + jsr putchar + clr temp+1 ;Clear check sum + ldb temp + addb #3 + bsr checkout ;Output byte b as hex and add to check sum. + ldd addr + tfr d,y + subd soffs + exg a,b + bsr checkout + exg a,b + bsr checkout ;Output address (add into check sum) +ss3 ldb ,y+ + bsr checkout + dec temp + bne ss3 + sty addr + ldb temp+1 + comb + bsr checkout ;Output checksum byte. + jsr putcr + bra ss1 +endss ldx #lastrec + jsr outcount + jsr putcr + jmp cmdline +* Output byte in register B and add it into check sum at temp+1 +checkout pshs a + tfr b,a + addb temp+1 + stb temp+1 + jsr outbyte + puls a + rts + +* This is the code for the M command, move memory region. +* Syntax: Maddr1,addr2,length +move ldx #linebuf+1 + jsr scanhex + lbeq unk + std temp3 + jsr skipspace + cmpb #',' + lbne unk + jsr scanhex + lbeq unk + tfr d,u + jsr skipspace + cmpb #',' + lbne unk + jsr scanhex + lbeq unk + tfr d,y ;Read the argument separated by commas + ldx temp3 ;src addr to x, dest addr to u, length to y + ;Don't tolerate syntax deviations. +mvloop lda ,x+ + sta ,u+ + leay -1,y + bne mvloop ;Perform the block move. + jmp cmdline + + +* This is the code for the F command, find byte/ascii string in memory. +* Syntax: Faddr bytes or Faddr "ascii" +find ldx #linebuf+1 + jsr scanhex + tfr d,y ;Scan the start address. + jsr skipspace + cmpb #'"' + bne findhex + ldu #linebuf ;Quote found, so scan for quoted string. + clra +fstrloop ldb ,x+ + beq startsrch ;End of line without final quote. + cmpb #'"' + beq startsrch ;End quote found + stb ,u+ + inca + bra fstrloop +findhex ldu #linebuf ;Convert string of hex bytes. + leax -1,x ;String will be stored at start of line + clra ;buffer and may overwrite part of the +fhexloop pshs a ;already converted string. + jsr scanbyte + tfr a,b + puls a + beq startsrch + stb ,u+ + inca + bra fhexloop +startsrch tsta ;Start searching, start addr in Y, + ;string starts at linebuf, length A + lbeq cmdline ;Quit with zero length string. + clr temp3 + sta temp3+1 +srchloop tfr y,x + lda temp3+1 + cmpx #$e100 + bcc srch1 + leax a,x + cmpx #$e000 ;Stop at I/O addresses. + lbcc cmdline +srch1 tfr y,x + ldu #linebuf +srch2 ldb ,x+ + cmpb ,u+ + bne srch3 ;Not equal, try next address. + deca + bne srch2 + tfr y,d + jsr outd ;String found + jsr putcr + inc temp3 + lda temp3 + cmpa #$10 + lbeq cmdline ;If 10 matches found, just stop. +srch3 leay 1,y + bra srchloop + +* Send the contents of the xmodem buffer and get it acknowledged, zero flag +* is set if transfer aborted. +xsendbuf ldb #SOH + jsr osputc ;Send SOH + ldb xpacknum + jsr osputc ;Send block number. + comb + jsr osputc ;and its complement. + clr xsum + lda #128 + ldx #buf0 +xsloop ldb ,x + addb xsum + stb xsum + ldb ,x+ + jsr osputc + deca + bne xsloop ;Send the buffer contents. + ldb xsum + jsr osputc ;Send the check sum +waitack jsr osgetc + cmpb #CAN + beq xsabt ;^X for abort. + cmpb #NAK + beq xsendbuf ;Send again if NAK + cmpb #ACK + bne waitack + inc xpacknum +xsok andcc #$fb ;Clear zero flag after ACK +xsabt rts + +* Start an XMODEM send session. +xsendinit ldb #1 + stb xpacknum ;Initialize block number. +waitnak jsr osgetc + cmpb #CAN + beq xsabt ;If ^X exit with zero flag. + cmpb #NAK + beq xsok + bra waitnak ;Wait until NAK received. + +* Send ETX and wait for ack. +xsendeot ldb #EOT + jsr osputc +waitack2 jsr osgetc + cmpb #CAN + beq xsabt + cmpb #NAK + beq xsendeot + cmpb #ACK + beq xsok + bra waitack2 + +* Read character into B with a timeout of A seconds, Carry set if timeout. +gettimeout asla + ldb #50 + mul + tfr b,a + adda timer+2 +gt1 jsr osgetpoll + tstb + bne gtexit + cmpa timer+2 + bne gt1 + orcc #$1 + rts +gtexit jsr osgetc + andcc #$fe + rts + +* Wait until line becomes quiet. +purge lda #3 + jsr gettimeout + bcc purge + rts + +* Receive an XMODEM block and wait till it is OK, Z set if etx. +xrcvbuf lda #3 + tst lastok + beq sendnak + ldb #ACK + jsr osputc ;Send an ack. + lda #5 + bra startblock +sendnak ldb #NAK + jsr osputc ;Send a NAK +startblock clr lastok + bsr gettimeout + lda #3 + bcs sendnak ;Keep sending NAKs when timed out. + cmpb #EOT + beq xrcveot ;End of file reached, acknowledge EOT. + cmpb #SOH + bne purgeit ;Not, SOH, bad block. + lda #1 + bsr gettimeout + bcs purgeit + cmpb xpacknum ;Is it the right block? + beq xr1 + incb + cmpb xpacknum ;Was it the previous block. + bne purgeit + inc lastok +xr1 stb xsum + lda #1 + bsr gettimeout + bcs purgeit + comb + cmpb xsum ;Is the complement of the block number OK + bne purgeit + ldx #buf0 + clr xsum +xrloop lda #1 + bsr gettimeout + bcs purgeit + stb ,x+ + addb xsum + stb xsum + cmpx #buf0+128 + bne xrloop ;Get the data bytes. + lda #1 + bsr gettimeout + bcs purgeit + cmpb xsum + bne purgeit ;Check the check sum. + tst lastok + bne xrcvbuf ;Block was the previous block, get next one + inc lastok + inc xpacknum + andcc #$fb + rts +purgeit jsr purge + bra sendnak +xrcveot lda #3 ;EOT was received. + ldb #ACK +ackloop jsr osputc + deca + bne ackloop ;Send 3 acks in a row. + rts + + +savevecs ldx getchar+1 + stx oldgetc + ldx putchar+1 + stx oldputc + ldx putcr+1 + stx oldputcr + clr lastterm + rts + +rstvecs ldx oldgetc + stx getchar+1 + ldx oldputc + stx putchar+1 + ldx oldputcr + stx putcr+1 + clr lastterm + rts + +* O.S. routine to open input through XMODEM transfer. +xopin pshs x,a,b + ldx #xsmsg + jsr outcount + jsr putcr ;Display message to start XMODEM send. + bsr savevecs + ldx #noop + stx putchar+1 ;Disable character output. + ldx #xgetc + stx getchar+1 ; + clr lastok + clr xcount + lda #1 + sta xpacknum + inca + sta xmode ;set xmode to 2. + puls x,a,b,pc + +* O.S. routine to open output through XMODEM transfer. +xopout pshs x,a,b + bsr savevecs + ldx #xrmsg + jsr outcount ;Display message to start XMODEM receive + jsr putcr + ldx #xputc + stx putchar+1 + ldx #xputcr + stx putcr+1 + jsr xsendinit + lbeq xerror + clr xcount + lda #1 + sta xmode + puls x,a,b,pc + + +* O.S. routine to abort input through XMODEM transfer. +xabtin lda xmode + cmpa #2 + bne xclsend + jsr purge + ldb #CAN + lda #8 +xabtloop jsr osputc + deca + bne xabtloop ;Send 8 CAN characters to kill transfer. + bsr rstvecs + clr xmode + ldx #xamsg + jsr outcount + jsr putcr ;Send diagnostic message. + rts + +* O.S. routine to close output through XMODEM transfer. +xclsout lda xmode + cmpa #1 + bne xclsend + tst xcount + beq xclsdone + lda #128 + suba xcount +xclsloop ldb filler + bsr xputc + deca + bne xclsloop ;Transfer filler chars to force block out. +xclsdone jsr xsendeot ;Send EOT + lbeq xerror + jsr rstvecs + clr xmode +xclsend rts + +* O.S. routine to close input through XMODEM, by gobbling up the remaining +* bytes. +xclsin ldb xmode + cmpb #2 + bne xclsend + jsr putchar + bra xclsin + +* putchar routine for XMODEM +xputc pshs x,a,b + lda xcount + inc xcount + ldx #buf0 + stb a,x ;Store character in XMODEM buffer. + cmpa #127 + bne xputc1 ;is buffer full? + clr xcount + pshs y,u + jsr xsendbuf + lbeq xerror + puls y,u +xputc1 puls x,a,b,pc + +* putcr routine for XMODEM +xputcr pshs b + ldb xmcr + bitb #2 + beq xputcr1 + ldb #CR + bsr xputc +xputcr1 ldb xmcr + bitb #1 + beq xputcr2 + ldb #LF + bsr xputc +xputcr2 puls b + rts + +* getchar routine for XMODEM +xgetc pshs x,a + tst xcount ;No characters left? + bne xgetc1 + pshs y,u + jsr xrcvbuf ;Receive new block. + puls y,u + beq xgetcterm ;End of input? + lda #128 + sta xcount +xgetc1 lda xcount + nega + ldx #buf0+128 + ldb a,x ;Get character from buffer + dec xcount + puls x,a,pc +xgetcterm jsr rstvecs + clr xmode + ldb filler + puls x,a,pc + +xerror jsr rstvecs ;Restore I/O vectors + clr xmode + ldx #xamsg + jsr outcount + jsr putcr + jmp xerrvec + +xerrhand lds savesp + jmp cmdline + +* This is the code for the X command, various XMODEM related commands. +* Syntax: XSaddr,len XLaddr,len XX XOcrlf,filler, XSSaddr,len +xmodem ldx #linebuf+1 + lda ,x+ + anda #CASEMASK ;Convert to uppercase. + cmpa #'X' + beq xeq + cmpa #'L' + beq xload + cmpa #'O' + beq xopts + cmpa #'S' + lbne unk + lda ,x + anda #CASEMASK + cmpa #'S' + beq xss + ldd #$100 ;XSaddr,len command. + jsr scan2parms ;Send binary through XMODEM + jsr xopenout + ldu addr + ldy length +xsbinloop ldb ,u+ + jsr putchar + leay -1,y + bne xsbinloop ;Send all the bytes through XMODEM. + jmp cmdline +xss leax 1,x ;XSSaddr,len command. + jsr xopenout ;Send Srecords through XMODEM + jmp sendrec +xload jsr scanhex ;XLaddr command + tfr d,y ;Load binary through XMODEM + jsr xopenin +xlodloop jsr getchar + tst xmode ;File ended? then done + lbeq cmdline + stb ,y+ + bra xlodloop +xeq jsr xopenin ;XX command + jmp cmdline ;Execute commands received from XMODEM +xopts ldd #$1a + jsr scan2parms + lda addr+1 + sta xmcr + lda length+1 + sta filler + jmp cmdline + +* mnemonics table, ordered alphabetically. +* 5 bytes name, 1 byte category, 2 bytes opcode, 8 bytes total. +mnemtab fcc "ABX " + fcb 0 + fdb $3a + fcc "ADCA " + fcb 7 + fdb $89 + fcc "ADCB " + fcb 7 + fdb $c9 + fcc "ADDA " + fcb 7 + fdb $8b + fcc "ADDB " + fcb 7 + fdb $cb + fcc "ADDD " + fcb 8 + fdb $c3 + fcc "ANDA " + fcb 7 + fdb $84 + fcc "ANDB " + fcb 7 + fdb $c4 + fcc "ANDCC" + fcb 2 + fdb $1c + fcc "ASL " + fcb 10 + fdb $08 + fcc "ASLA " + fcb 0 + fdb $48 + fcc "ASLB " + fcb 0 + fdb $58 + fcc "ASR " + fcb 10 + fdb $07 + fcc "ASRA " + fcb 0 + fdb $47 + fcc "ASRB " + fcb 0 + fdb $57 + fcc "BCC " + fcb 4 + fdb $24 + fcc "BCS " + fcb 4 + fdb $25 + fcc "BEQ " + fcb 4 + fdb $27 + fcc "BGE " + fcb 4 + fdb $2c + fcc "BGT " + fcb 4 + fdb $2e + fcc "BHI " + fcb 4 + fdb $22 + fcc "BHS " + fcb 4 + fdb $24 + fcc "BITA " + fcb 7 + fdb $85 + fcc "BITB " + fcb 7 + fdb $c5 + fcc "BLE " + fcb 4 + fdb $2f + fcc "BLO " + fcb 4 + fdb $25 + fcc "BLS " + fcb 4 + fdb $23 + fcc "BLT " + fcb 4 + fdb $2d + fcc "BMI " + fcb 4 + fdb $2b + fcc "BNE " + fcb 4 + fdb $26 + fcc "BPL " + fcb 4 + fdb $2a + fcc "BRA " + fcb 4 + fdb $20 + fcc "BRN " + fcb 4 + fdb $21 +mnembsr fcc "BSR " + fcb 4 + fdb $8d + fcc "BVC " + fcb 4 + fdb $28 + fcc "BVS " + fcb 4 + fdb $29 + fcc "CLR " + fcb 10 + fdb $0f + fcc "CLRA " + fcb 0 + fdb $4f + fcc "CLRB " + fcb 0 + fdb $5f + fcc "CMPA " + fcb 7 + fdb $81 + fcc "CMPB " + fcb 7 + fdb $c1 + fcc "CMPD " + fcb 9 + fdb $1083 + fcc "CMPS " + fcb 9 + fdb $118c + fcc "CMPU " + fcb 9 + fdb $1183 + fcc "CMPX " + fcb 8 + fdb $8c + fcc "CMPY " + fcb 9 + fdb $108c + fcc "COM " + fcb 10 + fdb $03 + fcc "COMA " + fcb 0 + fdb $43 + fcc "COMB " + fcb 0 + fdb $53 + fcc "CWAI " + fcb 2 + fdb $3c + fcc "DAA " + fcb 0 + fdb $19 + fcc "DEC " + fcb 10 + fdb $0a + fcc "DECA " + fcb 0 + fdb $4a + fcc "DECB " + fcb 0 + fdb $5a + fcc "EORA " + fcb 7 + fdb $88 + fcc "EORB " + fcb 7 + fdb $c8 + fcc "EQU " + fcb 13 + fdb 5 + fcc "EXG " + fcb 11 + fdb $1e +mnemfcb fcc "FCB " + fcb 13 + fdb 7 + fcc "FCC " + fcb 13 + fdb 8 + fcc "FDB " + fcb 13 + fdb 9 + fcc "INC " + fcb 10 + fdb $0c + fcc "INCA " + fcb 0 + fdb $4c + fcc "INCB " + fcb 0 + fdb $5c + fcc "JMP " + fcb 10 + fdb $0e +mnemjsr fcc "JSR " + fcb 8 + fdb $8d + fcc "LBCC " + fcb 5 + fdb $1024 + fcc "LBCS " + fcb 5 + fdb $1025 + fcc "LBEQ " + fcb 5 + fdb $1027 + fcc "LBGE " + fcb 5 + fdb $102c + fcc "LBGT " + fcb 5 + fdb $102e + fcc "LBHI " + fcb 5 + fdb $1022 + fcc "LBHS " + fcb 5 + fdb $1024 + fcc "LBLE " + fcb 5 + fdb $102f + fcc "LBLO " + fcb 5 + fdb $1025 + fcc "LBLS " + fcb 5 + fdb $1023 + fcc "LBLT " + fcb 5 + fdb $102d + fcc "LBMI " + fcb 5 + fdb $102b + fcc "LBNE " + fcb 5 + fdb $1026 + fcc "LBPL " + fcb 5 + fdb $102a + fcc "LBRA " + fcb 6 + fdb $16 + fcc "LBRN " + fcb 5 + fdb $1021 + fcc "LBSR " + fcb 6 + fdb $17 + fcc "LBVC " + fcb 5 + fdb $1028 + fcc "LBVS " + fcb 5 + fdb $1029 + fcc "LDA " + fcb 7 + fdb $86 + fcc "LDB " + fcb 7 + fdb $c6 + fcc "LDD " + fcb 8 + fdb $cc + fcc "LDS " + fcb 9 + fdb $10ce + fcc "LDU " + fcb 8 + fdb $ce + fcc "LDX " + fcb 8 + fdb $8e + fcc "LDY " + fcb 9 + fdb $108e + fcc "LEAS " + fcb 3 + fdb $32 + fcc "LEAU " + fcb 3 + fdb $33 + fcc "LEAX " + fcb 3 + fdb $30 + fcc "LEAY " + fcb 3 + fdb $31 + fcc "LSL " + fcb 10 + fdb $08 + fcc "LSLA " + fcb 0 + fdb $48 + fcc "LSLB " + fcb 0 + fdb $58 + fcc "LSR " + fcb 10 + fdb $04 + fcc "LSRA " + fcb 0 + fdb $44 + fcc "LSRB " + fcb 0 + fdb $54 + fcc "MUL " + fcb 0 + fdb $3d + fcc "NEG " + fcb 10 + fdb $00 + fcc "NEGA " + fcb 0 + fdb $40 + fcc "NEGB " + fcb 0 + fdb $50 + fcc "NOP " + fcb 0 + fdb $12 + fcc "ORA " + fcb 7 + fdb $8a + fcc "ORB " + fcb 7 + fdb $ca + fcc "ORCC " + fcb 2 + fdb $1a + fcc "ORG " + fcb 13 + fdb 12 + fcc "PSHS " + fcb 12 + fdb $34 + fcc "PSHU " + fcb 12 + fdb $36 + fcc "PULS " + fcb 12 + fdb $35 + fcc "PULU " + fcb 12 + fdb $37 + fcc "RMB " + fcb 13 + fdb 0 + fcc "ROL " + fcb 10 + fdb $09 + fcc "ROLA " + fcb 0 + fdb $49 + fcc "ROLB " + fcb 0 + fdb $59 + fcc "ROR " + fcb 10 + fdb $06 + fcc "RORA " + fcb 0 + fdb $46 + fcc "RORB " + fcb 0 + fdb $56 + fcc "RTI " + fcb 0 + fdb $3b + fcc "RTS " + fcb 0 + fdb $39 + fcc "SBCA " + fcb 7 + fdb $82 + fcc "SBCB " + fcb 7 + fdb $c2 + fcc "SET " + fcb 13 + fdb 15 + fcc "SETDP" + fcb 13 + fdb 14 + fcc "SEX " + fcb 0 + fdb $1d + fcc "STA " + fcb 7 + fdb $87 + fcc "STB " + fcb 7 + fdb $c7 + fcc "STD " + fcb 8 + fdb $cd + fcc "STS " + fcb 9 + fdb $10cf + fcc "STU " + fcb 8 + fdb $cf + fcc "STX " + fcb 8 + fdb $8f + fcc "STY " + fcb 9 + fdb $108f + fcc "SUBA " + fcb 7 + fdb $80 + fcc "SUBB " + fcb 7 + fdb $c0 + fcc "SUBD " + fcb 8 + fdb $83 + fcc "SWI " + fcb 0 + fdb $3f + fcb "SWI2 " + fcb 1 + fdb $103f + fcb "SWI3 " + fcb 1 + fdb $113f + fcc "SYNC " + fcb 0 + fdb $13 + fcc "TFR " + fcb 11 + fdb $1f + fcc "TST " + fcb 10 + fdb $0d + fcc "TSTA " + fcb 0 + fdb $4d + fcc "TSTB " + fcb 0 + fdb $5d + +mnemsize equ (*-mnemtab)/8 + +* Register table for PUSH/PULL and TFR/EXG instructions. +* 3 bytes for name, 1 for tfr/exg, 1 for push/pull, 5 total +asmregtab fcc "X " + fcb $01,$10 + fcc "Y " + fcb $02,$20 +aregu fcc "U " + fcb $03,$40 +aregs fcc "S " + fcb $04,$40 + fcc "PC " + fcb $05,$80 + fcc "A " + fcb $08,$02 + fcc "B " + fcb $09,$04 + fcc "D " + fcb $00,$06 + fcc "CC " + fcb $0a,$01 + fcc "CCR" + fcb $0a,$01 + fcc "DP " + fcb $0b,$08 + fcc "DPR" + fcb $0b,$08 +reginval fcc "? " + +ixregs fcc "XYUS" + +* opcode offsets to basic opcode, depends on first nibble. +opcoffs fcb 0,0,0,0,0,0,-$60,-$70 + fcb 0,-$10,-$20,-$30,0,-$10,-$20,-$30 +* mode depending on first nibble of opcode. +modetab fcb 3,0,0,0,0,0,5,4,1,3,5,4,1,3,5,4 +* mode depending on category code stored in mnemtab +modetab2 fcb 0,0,1,5,6,7,7,1,2,2,0,8,9 +* modes in this context: 0 no operands, 1 8-bit immediate, 2 16 bit imm, +* 3, 8-bit address, 4 16 bit address, 5 indexed with postbyte, 6 short +* relative, 7 long relative, 8 pushpul, 9 tftetx + +* Decode instruction pointed to by Y for disassembly (and to find out +* how long it is). On return, U points to appropriate mnemonic table entry, +* Y points past instruction. +* It's rather clumsy code, but we do want to reuse the same table +* as used with assembling. +disdecode clr prebyte + clr amode + lda ,y+ + cmpa #$10 + beq ddec1 + cmpa #$11 + bne ddec2 +ddec1 sta prebyte ;Store $10 or $11 prebyte. + lda ,y+ ;Get new opcode. +ddec2 sta opcode + lsra + lsra + lsra + lsra ;Get high nibble. + ldx #modetab + ldb a,x + stb amode + ldx #opcoffs + lda a,x + adda opcode ;Add opcode offset to opcode. +ddec4 sta opc1 ;Store the 'basis' opcode. + ldu #mnemtab + ldx #mnemsize +ddecloop ldb #13 + cmpb 5,u ;Compare category code with 13 + beq ddec3 ;13=pseudo op, no valid opcode + ldd prebyte + cmpd 6,u + beq ddecfound ;Opcode&prebyte agree, operation found. +ddec3 leau 8,u ;point to next mnemonic + leax -1,x + bne ddecloop + ldu #mnemfcb ;mnemonic not found, use FCB byte. + lda #3 + sta amode ;Store mode 3, 8 bit address. + lda opcode + tst prebyte + beq ddec5 + lda prebyte ;if it was the combination prebyte + clr prebyte ;and opcode that was not found, + leay -1,y ;FCB just the prebyte +ddec5 sta operand+1 ;The byte must be stored as operand. + rts +ddecfound cmpu #mnembsr + bne ddec6 + lda #$8d ;Is it really the BSR opcode? + cmpa opcode + beq ddec6 + ldu #mnemjsr ;We mistakenly found BSR instead of JSR +ddec6 lda amode + anda #$FE + bne ddec7 + lda 5,u ;nibble-dependent mode was 0 or 1, + ldx #modetab2 ;use category dependent mode instead. + lda a,x + sta amode +ddec7 lda amode + asla + ldx #disdectab + jmp [a,x] ;jump dependent on definitive mode. +disdectab fdb noop,opdec1,opdec2,opdec1,opdec2,opdecidx + fdb opdec1,opdec2,opdecpb,opdecpb +disdectab1 fdb noop,noop,noop,noop,noop,noop,noop,noop + fdb opdec1,opdec2,noop,noop,opdec1,opdec2,noop,opdec2 +opdec1 ldb ,y+ + sex +od1a std operand +noop rts +opdec2 ldd ,y++ + bra od1a +opdecpb ldb ,y+ +odpa stb postbyte + rts +opdecidx ldb ,y+ + bpl odpa ;postbytes <$80 have no extra operands. + stb postbyte + andb #$0f + aslb + ldx #disdectab1 + jmp [b,x] + +* Display disassembled instruction after the invocation of disdecode. +* U points to mnemonic table entry. +disdisp tfr u,x + ldb #5 + jsr putline ;Display the mnemonic. + ldb #' ' + jsr putchar + lda amode + asla + ldx #disdisptab + jmp [a,x] ;Perform action dependent on mode. +disdisptab fdb noop,disim8,disim16,disadr8,disadr16 + fdb disidx,disrel8,disrel16,distfr,dispush +disim8 bsr puthash + bra disadr8 +disim16 bsr puthash +disadr16 bsr putdol + ldd operand + jmp outd +disadr8 bsr putdol + lda operand+1 + jmp outbyte +disrel8 bsr putdol + ldb operand+1 + sex +dr8a sty temp + addd temp + jmp outd +disrel16 bsr putdol + ldd operand + bra dr8a + +puthash ldb #'#' + jmp putchar +putdol ldb #'$' + jmp putchar +putcomma ldb #',' + jmp putchar +putspace ldb #' ' + jmp putchar + +dispush ldb #12 + ldx #asmregtab ;Walk through the register table. + clr temp +regloop lda postbyte + anda 4,x + beq dispush1 ;Is bit corresponding to reg set in postbyte + cmpx #aregu + bne dispush3 + sta temp+1 + lda opcode + anda #2 + bne dispush1 ;no u register in pshu pulu. + lda temp+1 +dispush3 cmpx #aregs + bne dispush4 + sta temp+1 + lda opcode + anda #2 + beq dispush1 ;no s register in pshs puls. + lda temp+1 +dispush4 coma + anda postbyte ;remove the bits from postbyte. + sta postbyte + pshs b + tst temp + beq dispush2 + bsr putcomma ;print comma after first register. +dispush2 bsr disregname + inc temp + puls b +dispush1 leax 5,x + decb + bne regloop + rts + +distfr lda postbyte + lsra + lsra + lsra + lsra + bsr distfrsub + bsr putcomma + lda postbyte + anda #$0f +distfrsub ldb #12 + ldx #asmregtab +distfrloop cmpa 3,x + beq distfrend + leax 5,x + decb + bne distfrloop +distfrend bsr disregname + rts + +disregname lda #3 + tfr x,u +drnloop ldb ,u+ + cmpb #' ' + beq drnend + jsr putchar + deca + bne drnloop +drnend rts + +disidxreg lda postbyte + lsra + lsra + lsra + lsra + lsra + anda #3 + ldx #ixregs + ldb a,x + jmp putchar + +disidx clr temp + lda postbyte + bmi disidx1 + anda #$1f + bita #$10 + bne negoffs + jsr outdecbyte + bra discomma +negoffs ldb #'-' + jsr putchar + ora #$f0 + nega + jsr outdecbyte +discomma jsr putcomma ;Display ,Xreg and terminating ] +disindex bsr disidxreg +disindir tst temp ;Display ] if indirect. + beq disidxend + ldb #']' + jsr putchar +disidxend rts +disidx1 bita #$10 + beq disidx2 + ldb #'[' + jsr putchar + inc temp +disidx2 lda postbyte + anda #$0f + asla + ldx #disidxtab + jmp [a,x] ;Jump to routine for indexed mode +disadec2 lda #2 + bra disadeca +disadec1 lda #1 +disadeca jsr putcomma +disadloop ldb #'-' + jsr putchar + deca + bne disadloop + bra disindex +disainc2 lda #2 + bra disainca +disainc1 lda #1 +disainca sta temp+1 + jsr putcomma + jsr disidxreg + lda temp+1 +disailoop ldb #'+' + jsr putchar + deca + bne disailoop + jmp disindir +disax ldb #'A' + jsr putchar + jmp discomma +disbx ldb #'B' + jsr putchar + jmp discomma +disdx ldb #'D' + jsr putchar + jmp discomma +disinval ldb #'?' + jsr putchar + jmp disindir +disnx lda operand+1 + bmi disnxneg +disnx1 jsr putdol + jsr outbyte + jmp discomma +disnxneg ldb #'-' + jsr putchar + nega + bra disnx1 +disnnx jsr putdol + ldd operand + jsr outd + jmp discomma +disnpc jsr putdol + ldb operand+1 + sex +disnpca sty temp2 + addd temp2 + jsr outd + ldx #commapc + ldb #4 + jsr putline + jmp disindir +disnnpc jsr putdol + ldd operand + bra disnpca +disdirect jsr putdol + ldd operand + jsr outd + jmp disindir + +commapc fcc ",PCR" + +disidxtab fdb disainc1,disainc2,disadec1,disadec2 + fdb discomma,disbx,disax,disinval + fdb disnx,disnnx,disinval,disdx + fdb disnpc,disnnpc,disinval,disdirect + +* Display byte A in decimal (0<=A<20) +outdecbyte cmpa #10 + blo odb1 + suba #10 + ldb #'1' + jsr putchar +odb1 adda #'0' + tfr a,b + jmp putchar + +* This is the code for the U command, unassemble instructions in memory. +* Syntax: U or Uaddr or Uaddr,length +unasm ldx #linebuf+1 + ldd #20 + jsr scan2parms ;Scan address,length parameters. + ldd addr + addd length + std length + ldy addr +unasmloop tfr y,d + jsr outd ;Display instruction address + jsr putspace + pshs y + jsr disdecode + puls x + sty temp + clr temp2 +unadishex lda ,x+ + jsr outbyte + inc temp2 + inc temp2 + cmpx temp + bne unadishex ;Display instruction bytes as hex. +unadisspc ldb #' ' + jsr putchar + inc temp2 + lda #11 + cmpa temp2 ;Fill out with spaces to width 11. + bne unadisspc + bne unadishex + jsr disdisp ;Display disassembled instruction. + jsr putcr + cmpy length + bls unasmloop + sty addr + jmp cmdline + +* Simple 'expression evaluator' for assembler. +expr ldb ,x + cmpb #'-' + bne pos + clrb + leax 1,x +pos pshs b + bsr scanfact + beq exprend1 + tst ,s+ + bne exprend ;Was the minus sign there. + coma + comb + addd #1 + andcc #$fb ;Clear Z flag for valid result. +exprend rts +exprend1 puls b + rts + +scanfact ldb ,x+ + cmpb #'$' + lbeq scanhex ;Hex number if starting with dollar. + cmpb #''' + bne scandec ;char if starting with ' else decimal + ldb ,x+ + lda ,x + cmpa #''' + bne scanchar2 + leax 1,x ;Increment past final quote if it's there. +scanchar2 clra + andcc #$fb ;Clear zero flag. + rts +scandec cmpb #'0' + blo noexpr + cmpb #'9' + bhi noexpr + clr temp + clr temp+1 +scandloop subb #'0' + bcs sdexit + cmpb #10 + bcc sdexit + pshs b + ldd temp + aslb + rola + pshs d + aslb + rola + aslb + rola + addd ,s++ ;Multiply number by 10. + addb ,s+ + adca #0 ;Add digit to 10. + std temp + ldb ,x+ ;Get next character. + bra scandloop +sdexit ldd temp + leax -1,x + andcc #$fb + rts +noexpr orcc #$04 + rts + +* Assemble the instruction pointed to by X. +* Fisrt stage: copy mnemonic to mnemonic buffer. +asminstr lda #5 + ldu #mnembuf +mncploop ldb ,x+ + beq mncpexit + cmpb #' ' + beq mncpexit ;Mnemonic ends at first space or null + andb #CASEMASK + cmpb #'A' + blo nolet + cmpb #'Z' + bls mnemcp1 ;Capitalize letters, but only letters. +nolet ldb -1,x +mnemcp1 stb ,u+ ;Copy to mnemonic buffer. + deca + bne mncploop +mncpexit tsta + beq mncpdone + ldb #' ' +mnfilloop stb ,u+ + deca + bne mnfilloop ;Fill the rest of mnem buffer with spaces. +* Second stage: look mnemonic up using binary search. +mncpdone stx temp3 + clr temp ;Low index=0 + lda #mnemsize + sta temp+1 ;High index=mnemsize. +bsrchloop ldb temp+1 + cmpb #$ff + beq invmnem ;lower limit -1? + cmpb temp + blo invmnem ;hi index lower than low index? + clra + addb temp ;Add indexes. + adca #0 + lsra + rorb ;Divide by 2 to get average + stb temp2 + aslb + rola + aslb + rola + aslb + rola ;Multiply by 8 to get offset. + ldu #mnemtab + leau d,u ;Add offset to table base + tfr u,y + lda #5 + ldx #mnembuf +bscmploop ldb ,x+ + cmpb ,y+ + bne bscmpexit ;Characters don't match? + deca + bne bscmploop + jmp mnemfound ;We found the mnemonic. +bscmpexit ldb temp2 + bcc bscmplower + decb + stb temp+1 ;mnembuftable, adjust low limit. + bra bsrchloop +invmnem ldx #invmmsg + jmp asmerrvec +* Stage 3: Perform routine depending on category code. +mnemfound clr uncert + ldy addr + lda 5,u + asla + ldx #asmtab + jsr [a,x] + sty addr + rts +asmtab fdb onebyte,twobyte,immbyte,lea + fdb sbranch,lbranch,lbra,acc8 + fdb dreg1,dreg2,oneaddr,tfrexg + fdb pushpul,pseudo + +putbyte stb ,y+ + rts +putword std ,y++ + rts + +onebyte ldb 7,u ;Cat 0, one byte opcode w/o operands RTS + bra putbyte +twobyte ldd 6,u ;Cat 1, two byte opcode w/o operands SWI2 + bra putword +immbyte ldb 7,u ;Cat 2, opcode w/ immdiate operand ANDCC + bsr putbyte + jsr scanops + ldb amode + cmpb #1 + lbne moderr + ldb operand+1 + bra putbyte +lea ldb 7,u ;Cat 3, LEA + bsr putbyte + jsr scanops + lda amode + cmpa #1 + lbeq moderr ;No immediate w/ lea + cmpa #3 + lbhs doaddr + jsr set3 + lda #$8f + sta postbyte + lda #2 + sta opsize ;Use 8F nn nn for direct mode. + jmp doaddr +sbranch ldb 7,u ;Cat 4, short branch instructions + bsr putbyte + jsr startop + leax -1,x + jsr exprvec + lbeq exprerr + jmp shortrel +lbranch ldd 6,u ;Cat 5, long brach w/ two byte opcode + bsr putword +lbra1 jsr startop + leax -1,x + jsr exprvec + lbeq exprerr + jmp longrel +lbra ldb 7,u ;Cat 6, long branch w/ one byte opcode. + jsr putbyte + bra lbra1 +acc8 lda #1 ;Cat 7, 8-bit two operand instructions ADDA + sta opsize + jsr scanops + jsr adjopc + jsr putbyte + jmp doaddr +dreg1 lda #2 ;Cat 8, 16-bit 2operand insns 1byte opc LDX + sta opsize + jsr scanops + jsr adjopc + jsr putbyte + jmp doaddr +dreg2 lda #2 ;Cat 9, 16-bit 2operand insns 2byte opc LDY + sta opsize + jsr scanops + jsr adjopc + lda 6,u + jsr putword + jmp doaddr +oneaddr jsr scanops ;Cat 10, one-operand insns NEG..CLR + ldb 7,u + lda amode + cmpa #1 + lbeq moderr ;No immediate mode + cmpa #3 + bhs oaind ;indexed etc + lda opsize + deca + beq oadir + addb #$10 ;Add $70 for extended direct. +oaind addb #$60 ;And $60 for indexed etc. +oadir jsr putbyte ;And nothing for direct8. + jmp doaddr +tfrexg jsr startop ;Cat 11, TFR and EXG + leax -1,x + ldb 7,u + jsr putbyte + jsr findreg + ldb ,u + aslb + aslb + aslb + aslb + stb postbyte + ldb ,x+ + cmpb #',' + lbne moderr + jsr findreg + ldb ,u + orb postbyte + jmp putbyte +pushpul jsr startop ;Cat 12, PSH and PUL + leax -1,x + ldb 7,u + jsr putbyte + clr postbyte +pploop jsr findreg + ldb 1,u + orb postbyte + stb postbyte + ldb ,x+ + cmpb #',' + beq pploop + leax -1,x + ldb postbyte + jmp putbyte +pseudo ;Cat 13, pseudo oeprations + rts + +* Adjust opcdoe depending on mode (in $80-$FF range) +adjopc ldb 7,u + lda amode + cmpa #2 + beq adjdir ;Is it direct? + cmpa #3 + bhs adjind ;Indexed etc? + rts ;Not, then immediate, no adjust. +adjind addb #$20 ;Add $20 to opcode for indexed etc modes. + rts +adjdir addb #$10 ;Add $10 to opcode for direct8 + lda opsize + deca + bne adjind ;If opsize=2, add another $20 for extended16 + rts + +* Start scanning of operands. +startop ldx temp3 + clr amode + jmp skipspace + +* amode settings in assembler: 1=immediate, 2=direct/extended, 3=indexed +* etc. 4=pc relative, 5=indirect, 6=pcrelative and indirect. + +* This subroutine scans the assembler operands. +scanops bsr startop + cmpb #'[' + bne noindir + lda #5 ;operand starts with [, then indirect. + sta amode + ldb ,x+ +noindir cmpb #'#' + lbeq doimm + cmpb #',' + lbeq dospecial + andb #CASEMASK ;Convert to uppercase. + lda #$86 + cmpb #'A' + beq scanacidx + lda #$85 + cmpb #'B' + beq scanacidx + lda #$8B + cmpb #'D' + bne scanlab +scanacidx ldb ,x+ ;Could it be A,X B,X or D,X + cmpb #',' + bne nocomma + sta postbyte + clr opsize + jsr set3 + jsr scanixreg + bra scanend +nocomma leax -1,x +scanlab leax -1,x ;Point to the start of the operand + jsr exprvec + lbeq exprerr + std operand + tst uncert + bne opsz2 ;Go for extended if operand unknown. + subd dpsetting + tsta ;Can we use 8-bit operand? + bne opsz2 + inca + bra opsz1 +opsz2 lda #2 +opsz1 sta opsize ;Set opsize depending on magnitude of op. + lda amode + cmpa #5 + bne opsz3 ;Or was it indirect. + lda #2 ;Then we have postbyte and opsize=2 + sta opsize + lda #$8F + sta postbyte + bra opsz4 +opsz3 lda #2 + sta amode ;Assume direct or absolute addressing +opsz4 ldb ,x+ + cmpb #',' + lbeq doindex ;If followed by, then indexed. +scanend lda amode + cmpa #5 + blo scanend2 ;Was it an indirect mode? + lda postbyte + ora #$10 ;Set indirect bit. + sta postbyte + ldb ,x+ + cmpb #']' ;Check for the other ] + lbeq moderr +scanend2 rts +doimm jsr exprvec ;Immediate addressing. + lbeq exprerr + std operand + lda amode + cmpa #5 + lbeq moderr ;Inirect mode w/ imm is illegal. + lda #$01 + sta amode + rts +dospecial jsr set3 + clr opsize + clra +adecloop ldb ,x+ + cmpb #'-' + bne adecend + inca ;Count the - signs for autodecrement. + bra adecloop +adecend leax -1,x + cmpa #2 + lbhi moderr + tsta + bne autodec + clr postbyte + jsr scanixreg + clra +aincloop ldb ,x+ + cmpb #'+' + bne aincend + inca + bra aincloop ;Count the + signs for autoincrement. +aincend leax -1,x + cmpa #2 + lbhi moderr + tsta + bne autoinc + lda #$84 + ora postbyte + sta postbyte + bra scanend +autoinc adda #$7f + ora postbyte + sta postbyte + bra scanend +autodec adda #$81 + sta postbyte + jsr scanixreg + lbra scanend +doindex clr postbyte + jsr set3 + ldb ,x+ + andb #CASEMASK ;Convert to uppercase. + cmpb #'P' + lbeq dopcrel ;Check for PC relative. + leax -1,x + clr opsize + bsr scanixreg + ldd operand + tst uncert + bne longindex ;Go for long index if operand unknown. + cmpd #-16 + blt shortindex + cmpd #15 + bgt shortindex + lda amode + cmpa #5 + beq shortind1 ;Indirect may not be 5-bit index + ;It's a five-bit index. + andb #$1f + orb postbyte + stb postbyte + lbra scanend +shortindex cmpd #-128 + blt longindex + cmpd #127 + bgt longindex +shortind1 inc opsize + ldb #$88 + orb postbyte + stb postbyte + lbra scanend +longindex lda #$2 + sta opsize + ldb #$89 + orb postbyte + stb postbyte + lbra scanend +dopcrel ldb ,x+ + andb #CASEMASK ;Convert to uppercase + cmpb #'C' + blo pcrelend + cmpb #'R' + bhi pcrelend + bra dopcrel ;Scan past the ,PCR +pcrelend leax -1,x + ldb #$8C + orb postbyte ;Set postbyte + stb postbyte + inc amode ;Set addr mode to PCR + lbra scanend + +* Scan for one of the 4 index registers and adjust postbyte. +scanixreg ldb ,x+ + andb #CASEMASK ;Convert to uppercase. + pshs x + ldx #ixregs + clra +scidxloop cmpb ,x+ + beq ixfound + adda #$20 + bpl scidxloop + jmp moderr ;Index register not found where expected. +ixfound ora postbyte + sta postbyte ;Set index reg bits in postbyte. + puls x + rts + +* This routine sets amode to 3, if it was less. +set3 lda amode + cmpa #3 + bhs set3a + lda #3 + sta amode +set3a rts + +* This subroutine lays down the address. +doaddr lda amode + cmpa #3 + blo doa1 + ldb postbyte + jsr putbyte + lda amode + anda #1 + beq doapcrel ;pc rel modes. +doa1 lda opsize + tsta + beq set3a + deca + beq doa2 + ldd operand + jmp putword +doa2 ldb operand+1 + jmp putbyte +doapcrel sty addr + ldd operand + subd addr + subd #1 + tst uncert + bne pcrlong + cmpd #-128 + blt pcrlong + cmpd #-127 + bgt pcrlong + lda #1 + sta opsize + jmp putbyte +pcrlong subd #1 + leay -1,y + inc postbyte + pshs d + ldb postbyte + jsr putbyte + lda #2 + sta opsize + puls d + jmp putword + +* This routine checks and lays down short relative address. +shortrel sty addr + subd addr + subd #1 + cmpd #-128 + blt brerr + cmpd #127 + bgt brerr + jsr putbyte + lda #4 + sta amode + lda #1 + sta opsize + rts +* This routine lays down long relative address. +longrel sty addr + subd addr + subd #2 + jsr putword + lda #4 + sta amode + lda #2 + sta opsize + rts + +brerr ldx #brmsg + jmp asmerrvec +exprerr ldx #exprmsg + jmp asmerrvec +moderr ldx #modemsg + jmp asmerrvec +asmerr pshs x + jsr xabortin + puls x + jsr outcount + jsr putcr + lds savesp + jmp cmdline + +* Find register for TFR and PSH instruction +findreg ldb #12 + pshs y,b + ldu #asmregtab +findregloop tfr x,y + lda #3 +frcmps ldb ,u + cmpb #' ' + bne frcmps1 + ldb ,y + cmpb #'A' + blt frfound +frcmps1 ldb ,y+ + andb #CASEMASK + cmpb ,u+ + bne frnextreg + deca + bne frcmps + inca + bra frfound +frnextreg inca + leau a,u + dec ,s + bne findregloop + lbra moderr +frfound leau a,u + tfr y,x + puls y,b + rts + +* This is the code for the A command, assemble instructions. +* Syntax: Aaddr +asm ldx #linebuf+1 + jsr scanhex + std addr +asmloop ldd addr + jsr outd + ldb #' ' + jsr putchar ;Print address and space. + ldx #linebuf + ldb #128 + jsr getline ;Get new line + tstb + lbeq cmdline ;Exit on empty line. + abx + clr ,x ;Make line zero terminated. + ldx #linebuf + jsr asminstr + bra asmloop + +* Jump table for monitor routines that are usable by other programs. + org $ffc0 + jmp outbyte + jmp outd + jmp scanbyte + jmp scanhex + jmp scanfact + jmp asminstr + + +* Interrupt vector addresses at top of ROM. Most are vectored through jumps +* in RAM. + org $fff2 + fdb swi3vec + fdb swi2vec + fdb firqvec + fdb irqvec + fdb swivec + fdb nmivec + fdb reset + + end diff -r 000000000000 -r 9a224bd9b45f os9/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os9/Makefile Mon Jul 02 02:12:31 2018 +0900 @@ -0,0 +1,20 @@ +all: os9mod makerom os9disass os9.rom + +CC=clang +CFLAGS = -g + +os9mod : crc.c os9.h os9mod.c os9.h + $(CC) $(CFLAGS) -o os9mod crc.c os9mod.c + +makerom : makerom.c + $(CC) $(CFLAGS) -o makerom makerom.c + +os9disass : os9disass.c + $(CC) $(CFLAGS) -Wno-format-security -o os9disass os9disass.c + +os9.rom : makerom modules/init.b modules/pty.b + ./makerom os9.rom modules/Shell modules/init.b modules/mdir modules/SysGo modules/IOMan modules/SCF modules/pty-dd.b modules/pty.b modules/OS9p2 modules/OS9 + +os9b.rom : makerom modules/init.b modules/pty.b + ./makerom os9b.rom modules/Basic09 modules/Shell modules/init.b modules/mdir modules/SysGo modules/IOMan modules/SCF modules/pty-dd.b modules/pty.b modules/OS9p2 modules/OS9 + diff -r 000000000000 -r 9a224bd9b45f os9/crc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os9/crc.c Mon Jul 02 02:12:31 2018 +0900 @@ -0,0 +1,49 @@ +#include + +#include "os9.h" + +int os9_crc(OS9_MODULE_t *mod) +{ + int i; + u_char crc[3] = {0xff, 0xff, 0xff}; + u_char *ptr = (u_char *) mod; + u_char a; + + for (i = 0; i < INT(mod->size); i++) + { + a = *(ptr++); + + a ^= crc[0]; + crc[0] = crc[1]; + crc[1] = crc[2]; + crc[1] ^= (a >> 7); + crc[2] = (a << 1); + crc[1] ^= (a >> 2); + crc[2] ^= (a << 6); + a ^= (a << 1); + a ^= (a << 2); + a ^= (a << 4); + if (a & 0x80) { + crc[0] ^= 0x80; + crc[2] ^= 0x21; + } + } + if ((crc[0] == OS9_CRC0) && + (crc[1] == OS9_CRC1) && + (crc[2] == OS9_CRC2)) + return 1; + + return 0; +} + +int os9_header(OS9_MODULE_t *mod) +{ + u_char tmp = 0x00; + u_char *ptr = (u_char *) mod; + int i; + + for (i = 0; i < OS9_HEADER_SIZE; i++) + tmp ^= *(ptr++); + + return tmp; +} diff -r 000000000000 -r 9a224bd9b45f os9/makerom.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os9/makerom.c Mon Jul 02 02:12:31 2018 +0900 @@ -0,0 +1,141 @@ +/* makerom.c + build ROM image file os9.rom from module list +*/ + +#include +#include +#include +#include + +#define IOBASE 0xe000 +#define IOSIZE 0x800 + +typedef struct os9module { + int size; + int location; + int ioflag; + unsigned char *mod; + char *name; + struct os9module *next; +} *MPTR ; + +struct os9module * +readOS9module(char *filename) +{ + FILE *fp = fopen(filename,"rb"); + if (fp==0) { + fprintf(stderr,"cannot read %s\n",filename); + exit(1); + } + struct stat st; + fstat(fileno(fp),&st); + int size = st.st_size; + struct os9module *m = malloc(size + sizeof(struct os9module)); + m->size = size; + m->next = 0; + m->ioflag = 0; + m->mod = (unsigned char*)m + sizeof(struct os9module); + fread(m->mod , size, 1, fp); + m->name = (char*) (m->mod + (m->mod[4]*256 + m->mod[5]) ); + fclose(fp); + return m; +} + +void +fputword(unsigned short x, FILE *fp) +{ + fputc((x>>8)&0xff,fp); + fputc(x&0xff,fp); +} + +void printOs9Str(char *p) +{ + while((*p & 0x80)==0) { + putchar(*p); + p++; + } + putchar(*p & 0x7f); +} + +int findLocation(MPTR m, int loc) { + if (m==0) return loc; + int top = findLocation(m->next, loc) - m->size; + if (m->next==0) top = 0xf800; // OS9p1 + if (!(( top+m->size < IOBASE ) || ( IOBASE+IOSIZE < top)) ) { + top = IOBASE-m->size-1; + m->ioflag = 1; + // printf("*"); + } + m->location = top; + // printf("mod "); + // printOs9Str(m->name); + // printf(" \t: 0x%x - 0x%x\n",top, top + m->size); + return top; +} + +int +main(int ac, char *av[]) +{ + int vectable = 0; + struct os9module *m = 0, root ; + root.size = 0; + root.mod = 0; + m = &root; + + for(int i = 2 ; inext = cur; + m = cur; + } + + FILE *romfile; + unsigned pos; + + romfile=fopen(av[1],"wb"); + if(!romfile) { + fprintf(stderr,"Cannot create file %s\n",av[1]); + exit(1); + } + + + int start = findLocation(root.next,0); + start = start&0xf800; + printf("\n\n"); + + pos = start; + for(struct os9module *cur = root.next; cur ; cur = cur->next ) { + if ( cur->size && (cur->name[0]=='O' && cur->name[1]=='S' && cur->name[2]== -71)) { + for(; pos < 0xf800 ; pos++) { + fputc(0xff,romfile); + } + } + printf("mod "); + printOs9Str(cur->name); + fwrite(cur->mod, cur->size, 1, romfile); + printf(" \t: 0x%x - 0x%x\n",pos, pos + cur->size); + // printf(" \t: 0x%x - 0x%x : 0x%lx \n",pos, pos + cur->size, ftell(romfile)+start); + pos = pos+cur->size; + if (cur->ioflag) { + for(; pos < IOBASE + IOSIZE; pos++) { + fputc(0xff,romfile); + } + printf("*"); + } + } + printf("os9 end %x\n",pos); + vectable = 0x10000 - 2*7; + for( ; pos +#include +#include +#include +#include +#include +#include + + +/*************************************************************************** + Originally posted to comp.sys.m6809 by Didier Derny (didier@aida.remcomp.fr) + + Minor hacks by Alan DeKok + + Fixed: D_Indexed addressing used prog[2] and prog[3] when it meant + prog[pc+2] and prog[pc+3]: Would produce flawed disassemblies! + + changed addresses in D_Indexed to be all hex. + added 2 instances of 'extrabyte' in D_Indexed: would not skip them.. + Added PC offsets to D_Indexed ,PCR formats + added SWI2 print out as OS9 + + To do: + + handle command-line options properly... + + Fix handling of illegal opcodes so it doesn't skip a byte + i.e. $87 is a skip 2 + + Move defines to another file + + Add 6309 support + also add 6309 native-mode support, and listing of clock cycles for opcodes. + + Add OS-9 support + + add proper label-disassembly. i.e. 2-pass. + +****************************************************************************/ + +// extern int errno; +// extern char *sys_errlist[]; + +static unsigned char prog0[65536]; +unsigned char *prog = prog0; + +FILE *fp; + +typedef struct { + char *name; + int clock; + int bytes; + int (*display)(); + int (*execute)(); +} Opcode; + +typedef struct { + int address; + int length; + int width; +} String; + +int D_Illegal(Opcode *, int, int, char *); +int D_Direct(Opcode *, int, int, char *); +int D_Page10(Opcode *, int, int, char *); +int D_Page11(Opcode *, int, int, char *); +int D_Immediat(Opcode *, int, int, char *); +int D_ImmediatL(Opcode *, int, int, char *); +int D_Inherent(Opcode *, int, int, char *); +int D_Indexed(Opcode *, int, int, char *); +int D_Extended(Opcode *, int, int, char *); +int D_Relative(Opcode *, int, int, char *); +int D_RelativeL(Opcode *, int, int, char *); +int D_Register0(Opcode *, int, int, char *); +int D_Register1(Opcode *, int, int, char *); +int D_Register2(Opcode *, int, int, char *); +int D_Page10(Opcode *, int, int, char *); +int D_Page11(Opcode *, int, int, char *); +int D_OS9(Opcode *, int, int, char *); +char *IndexRegister(int); + +String stringtable[] = { + { 0xc321, 16, 16 }, + { 0xc395, 258, 16 }, + { 0xeb15, 50, 16 }, + { 0xee6f, 128, 16 }, + { 0xfdf4, 492, 16 }, + { 0xfff0, 16, 2 }, +}; + +int adoffset = 0; +int laststring = 6; + +Opcode optable[] = { + { "NEG ", 6, 2, D_Direct, NULL }, /* 0x00 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x01 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x02 */ + { "COM ", 6, 2, D_Direct, NULL }, /* 0x03 */ + { "LSR ", 6, 2, D_Direct, NULL }, /* 0x04 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x05 */ + { "ROR ", 6, 2, D_Direct, NULL }, /* 0x06 */ + { "ASR ", 6, 2, D_Direct, NULL }, /* 0x07 */ + { "LSL ", 6, 2, D_Direct, NULL }, /* 0x08 */ + { "ROR ", 6, 2, D_Direct, NULL }, /* 0x09 */ + { "DEC ", 6, 2, D_Direct, NULL }, /* 0x0a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x0b */ + { "INC ", 6, 2, D_Direct, NULL }, /* 0x0c */ + { "TST ", 6, 2, D_Direct, NULL }, /* 0x0d */ + { "JMP ", 3, 2, D_Direct, NULL }, /* 0x0e */ + { "CLR ", 6, 2, D_Direct, NULL }, /* 0x0f */ + + { "", 0, 1, D_Page10, NULL }, /* 0x10 */ + { "", 0, 1, D_Page11, NULL }, /* 0x11 */ + { "NOP ", 2, 1, D_Inherent, NULL }, /* 0x12 */ + { "SYNC ", 4, 1, D_Inherent, NULL }, /* 0x13 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x14 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x15 */ + { "LBRA ", 5, 3, D_RelativeL, NULL }, /* 0x16 */ + { "LBSR ", 9, 3, D_RelativeL, NULL }, /* 0x17 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x18 */ + { "DAA ", 2, 1, D_Inherent, NULL }, /* 0x19 */ + { "ORCC ", 3, 2, D_Immediat, NULL }, /* 0x1a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x1b */ + { "ANDCC", 3, 2, D_Immediat, NULL }, /* 0x1c */ + { "SEX ", 2, 1, D_Inherent, NULL }, /* 0x1d */ + { "EXG ", 8, 2, D_Register0, NULL }, /* 0x1e */ + { "TFR ", 6, 2, D_Register0, NULL }, /* 0x1f */ + + { "BRA ", 3, 2, D_Relative, NULL }, /* 0x20 */ + { "BRN ", 3, 2, D_Relative, NULL }, /* 0x21 */ + { "BHI ", 3, 2, D_Relative, NULL }, /* 0x22 */ + { "BLS ", 3, 2, D_Relative, NULL }, /* 0x23 */ + { "BCC ", 3, 2, D_Relative, NULL }, /* 0x24 */ + { "BCS ", 3, 2, D_Relative, NULL }, /* 0x25 */ + { "BNE ", 3, 2, D_Relative, NULL }, /* 0x26 */ + { "BEQ ", 3, 2, D_Relative, NULL }, /* 0x27 */ + { "BVC ", 3, 2, D_Relative, NULL }, /* 0x28 */ + { "BVS ", 3, 2, D_Relative, NULL }, /* 0x29 */ + { "BPL ", 3, 2, D_Relative, NULL }, /* 0x2a */ + { "BMI ", 3, 2, D_Relative, NULL }, /* 0x2b */ + { "BGE ", 3, 2, D_Relative, NULL }, /* 0x2c */ + { "BLT ", 3, 2, D_Relative, NULL }, /* 0x2d */ + { "BGT ", 3, 2, D_Relative, NULL }, /* 0x2e */ + { "BLE ", 3, 2, D_Relative, NULL }, /* 0x2f */ + + { "LEAX ", 4, 2, D_Indexed, NULL }, /* 0x30 */ + { "LEAY ", 4, 2, D_Indexed, NULL }, /* 0x31 */ + { "LEAS ", 4, 2, D_Indexed, NULL }, /* 0x32 */ + { "LEAU ", 4, 2, D_Indexed, NULL }, /* 0x33 */ + { "PSHS ", 5, 2, D_Register1, NULL }, /* 0x34 */ + { "PULS ", 5, 2, D_Register1, NULL }, /* 0x35 */ + { "PSHU ", 5, 2, D_Register2, NULL }, /* 0x36 */ + { "PULU ", 5, 2, D_Register2, NULL }, /* 0x37 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x38 */ + { "RTS ", 5, 1, D_Inherent, NULL }, /* 0x39 */ + { "ABX ", 3, 1, D_Inherent, NULL }, /* 0x3a */ + { "RTI ", 6, 1, D_Inherent, NULL }, /* 0x3b */ + { "CWAI ", 20, 2, D_Inherent, NULL }, /* 0x3c */ + { "MUL ", 11, 1, D_Inherent, NULL }, /* 0x3d */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x3e */ + { "SWI ", 19, 1, D_Inherent, NULL }, /* 0x3f */ + + { "NEGA ", 2, 1, D_Inherent, NULL }, /* 0x40 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x41 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x42 */ + { "COMA ", 2, 1, D_Inherent, NULL }, /* 0x43 */ + { "LSRA ", 2, 1, D_Inherent, NULL }, /* 0x44 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x45 */ + { "RORA ", 2, 1, D_Inherent, NULL }, /* 0x46 */ + { "ASRA ", 2, 1, D_Inherent, NULL }, /* 0x47 */ + { "LSLA ", 2, 1, D_Inherent, NULL }, /* 0x48 */ + { "ROLA ", 2, 1, D_Inherent, NULL }, /* 0x49 */ + { "DECA ", 2, 1, D_Inherent, NULL }, /* 0x4a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x4b */ + { "INCA ", 2, 1, D_Inherent, NULL }, /* 0x4c */ + { "TSTA ", 2, 1, D_Inherent, NULL }, /* 0x4d */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x4e */ + { "CLRA ", 2, 1, D_Inherent, NULL }, /* 0x4f */ + + { "NEGB ", 2, 1, D_Inherent, NULL }, /* 0x50 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x51 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x52 */ + { "COMB ", 2, 1, D_Inherent, NULL }, /* 0x53 */ + { "LSRB ", 2, 1, D_Inherent, NULL }, /* 0x54 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x55 */ + { "RORB ", 2, 1, D_Inherent, NULL }, /* 0x56 */ + { "ASRB ", 2, 1, D_Inherent, NULL }, /* 0x57 */ + { "LSLB ", 2, 1, D_Inherent, NULL }, /* 0x58 */ + { "ROLB ", 2, 1, D_Inherent, NULL }, /* 0x59 */ + { "DECB ", 2, 1, D_Inherent, NULL }, /* 0x5a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x5b */ + { "INCB ", 2, 1, D_Inherent, NULL }, /* 0x5c */ + { "TSTB ", 2, 1, D_Inherent, NULL }, /* 0x5d */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x5e */ + { "CLRB ", 2, 1, D_Inherent, NULL }, /* 0x5f */ + + { "NEG ", 6, 2, D_Indexed, NULL }, /* 0x60 */ + { "?????", 0, 2, D_Illegal, NULL }, /* 0x61 */ + { "?????", 0, 2, D_Illegal, NULL }, /* 0x62 */ + { "COM ", 6, 2, D_Indexed, NULL }, /* 0x63 */ + { "LSR ", 6, 2, D_Indexed, NULL }, /* 0x64 */ + { "?????", 0, 2, D_Indexed, NULL }, /* 0x65 */ + { "ROR ", 6, 2, D_Indexed, NULL }, /* 0x66 */ + { "ASR ", 6, 2, D_Indexed, NULL }, /* 0x67 */ + { "LSL ", 6, 2, D_Indexed, NULL }, /* 0x68 */ + { "ROL ", 6, 2, D_Indexed, NULL }, /* 0x69 */ + { "DEC ", 6, 2, D_Indexed, NULL }, /* 0x6a */ + { "?????", 0, 2, D_Illegal, NULL }, /* 0x6b */ + { "INC ", 6, 2, D_Indexed, NULL }, /* 0x6c */ + { "TST ", 6, 2, D_Indexed, NULL }, /* 0x6d */ + { "JMP ", 3, 2, D_Indexed, NULL }, /* 0x6e */ + { "CLR ", 6, 2, D_Indexed, NULL }, /* 0x6f */ + + { "NEG ", 7, 3, D_Extended, NULL }, /* 0x70 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x71 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x72 */ + { "COM ", 7, 3, D_Extended, NULL }, /* 0x73 */ + { "LSR ", 7, 3, D_Extended, NULL }, /* 0x74 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x75 */ + { "ROR ", 7, 3, D_Extended, NULL }, /* 0x76 */ + { "ASR ", 7, 3, D_Extended, NULL }, /* 0x77 */ + { "LSL ", 7, 3, D_Extended, NULL }, /* 0x78 */ + { "ROL ", 7, 3, D_Extended, NULL }, /* 0x79 */ + { "DEC ", 7, 3, D_Extended, NULL }, /* 0x7a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x7b */ + { "INC ", 7, 3, D_Extended, NULL }, /* 0x7c */ + { "TST ", 7, 3, D_Extended, NULL }, /* 0x7d */ + { "JMP ", 4, 3, D_Extended, NULL }, /* 0x7e */ + { "CLR ", 7, 3, D_Extended, NULL }, /* 0x7f */ + + { "SUBA ", 2, 2, D_Immediat, NULL }, /* 0x80 */ + { "CMPA ", 2, 2, D_Immediat, NULL }, /* 0x81 */ + { "SBCA ", 2, 2, D_Immediat, NULL }, /* 0x82 */ + { "SUBD ", 4, 3, D_ImmediatL, NULL }, /* 0x83 */ + { "ANDA ", 2, 2, D_Immediat, NULL }, /* 0x84 */ + { "BITA ", 2, 2, D_Immediat, NULL }, /* 0x85 */ + { "LDA ", 2, 2, D_Immediat, NULL }, /* 0x86 */ + { "?????", 0, 2, D_Illegal, NULL }, /* 0x87 */ + { "EORA ", 2, 2, D_Immediat, NULL }, /* 0x88 */ + { "ADCA ", 2, 2, D_Immediat, NULL }, /* 0x89 */ + { "ORA ", 2, 2, D_Immediat, NULL }, /* 0x8a */ + { "ADDA ", 2, 2, D_Immediat, NULL }, /* 0x8b */ + { "CMPX ", 4, 3, D_ImmediatL, NULL }, /* 0x8c */ + { "BSR ", 7, 2, D_Relative, NULL }, /* 0x8d */ + { "LDX ", 3, 3, D_ImmediatL, NULL }, /* 0x8e */ + { "?????", 0, 2, D_Illegal, NULL }, /* 0x8f */ + + { "SUBA ", 4, 2, D_Direct, NULL }, /* 0x90 */ + { "CMPA ", 4, 2, D_Direct, NULL }, /* 0x91 */ + { "SBCA ", 4, 2, D_Direct, NULL }, /* 0x92 */ + { "SUBD ", 6, 2, D_Direct, NULL }, /* 0x93 */ + { "ANDA ", 4, 2, D_Direct, NULL }, /* 0x94 */ + { "BITA ", 4, 2, D_Direct, NULL }, /* 0x95 */ + { "LDA ", 4, 2, D_Direct, NULL }, /* 0x96 */ + { "STA ", 4, 2, D_Direct, NULL }, /* 0x97 */ + { "EORA ", 4, 2, D_Direct, NULL }, /* 0x98 */ + { "ADCA ", 4, 2, D_Direct, NULL }, /* 0x99 */ + { "ORA ", 4, 2, D_Direct, NULL }, /* 0x9a */ + { "ADDA ", 4, 2, D_Direct, NULL }, /* 0x9b */ + { "CMPX ", 6, 2, D_Direct, NULL }, /* 0x9c */ + { "JSR ", 7, 2, D_Direct, NULL }, /* 0x9d */ + { "LDX ", 5, 2, D_Direct, NULL }, /* 0x9e */ + { "STX ", 5, 2, D_Direct, NULL }, /* 0x9f */ + + { "SUBA ", 4, 2, D_Indexed, NULL }, /* 0xa0 */ + { "CMPA ", 4, 2, D_Indexed, NULL }, /* 0xa1 */ + { "SBCA ", 4, 2, D_Indexed, NULL }, /* 0xa2 */ + { "SUBD ", 6, 2, D_Indexed, NULL }, /* 0xa3 */ + { "ANDA ", 4, 2, D_Indexed, NULL }, /* 0xa4 */ + { "BITA ", 4, 2, D_Indexed, NULL }, /* 0xa5 */ + { "LDA ", 4, 2, D_Indexed, NULL }, /* 0xa6 */ + { "STA ", 4, 2, D_Indexed, NULL }, /* 0xa7 */ + { "EORA ", 4, 2, D_Indexed, NULL }, /* 0xa8 */ + { "ADCA ", 4, 2, D_Indexed, NULL }, /* 0xa9 */ + { "ORA ", 4, 2, D_Indexed, NULL }, /* 0xaa */ + { "ADDA ", 4, 2, D_Indexed, NULL }, /* 0xab */ + { "CMPX ", 6, 2, D_Indexed, NULL }, /* 0xac */ + { "JSR ", 7, 2, D_Indexed, NULL }, /* 0xad */ + { "LDX ", 5, 2, D_Indexed, NULL }, /* 0xae */ + { "STX ", 5, 2, D_Indexed, NULL }, /* 0xaf */ + + { "SUBA ", 5, 3, D_Extended, NULL }, /* 0xb0 */ + { "CMPA ", 5, 3, D_Extended, NULL }, /* 0xb1 */ + { "SBCA ", 5, 3, D_Extended, NULL }, /* 0xb2 */ + { "SUBD ", 7, 3, D_Extended, NULL }, /* 0xb3 */ + { "ANDA ", 5, 3, D_Extended, NULL }, /* 0xb4 */ + { "BITA ", 5, 3, D_Extended, NULL }, /* 0xb5 */ + { "LDA ", 5, 3, D_Extended, NULL }, /* 0xb6 */ + { "STA ", 5, 3, D_Extended, NULL }, /* 0xb7 */ + { "EORA ", 5, 3, D_Extended, NULL }, /* 0xb8 */ + { "ADCA ", 5, 3, D_Extended, NULL }, /* 0xb9 */ + { "ORA ", 5, 3, D_Extended, NULL }, /* 0xba */ + { "ADDA ", 5, 3, D_Extended, NULL }, /* 0xbb */ + { "CMPX ", 7, 3, D_Extended, NULL }, /* 0xbc */ + { "JSR ", 8, 3, D_Extended, NULL }, /* 0xbd */ + { "LDX ", 6, 3, D_Extended, NULL }, /* 0xbe */ + { "STX ", 6, 3, D_Extended, NULL }, /* 0xbf */ + + { "SUBB ", 2, 2, D_Immediat, NULL }, /* 0xc0 */ + { "CMPB ", 2, 2, D_Immediat, NULL }, /* 0xc1 */ + { "SBCB ", 2, 2, D_Immediat, NULL }, /* 0xc2 */ + { "ADDD ", 4, 3, D_ImmediatL, NULL }, /* 0xc3 */ + { "ANDB ", 2, 2, D_Immediat, NULL }, /* 0xc4 */ + { "BITB ", 2, 2, D_Immediat, NULL }, /* 0xc5 */ + { "LDB ", 2, 2, D_Immediat, NULL }, /* 0xc6 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xc7 */ + { "EORB ", 2, 2, D_Immediat, NULL }, /* 0xc8 */ + { "ADCB ", 2, 2, D_Immediat, NULL }, /* 0xc9 */ + { "ORB ", 2, 2, D_Immediat, NULL }, /* 0xca */ + { "ADDB ", 2, 2, D_Immediat, NULL }, /* 0xcb */ + { "LDD ", 3, 3, D_ImmediatL, NULL }, /* 0xcc */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xcd */ + { "LDU ", 3, 3, D_ImmediatL, NULL }, /* 0xce */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xcf */ + + { "SUBB ", 4, 2, D_Direct, NULL }, /* 0xd0 */ + { "CMPB ", 4, 2, D_Direct, NULL }, /* 0xd1 */ + { "SBCB ", 4, 2, D_Direct, NULL }, /* 0xd2 */ + { "ADDD ", 6, 2, D_Direct, NULL }, /* 0xd3 */ + { "ANDB ", 4, 2, D_Direct, NULL }, /* 0xd4 */ + { "BITB ", 4, 2, D_Direct, NULL }, /* 0xd5 */ + { "LDB ", 4, 2, D_Direct, NULL }, /* 0xd6 */ + { "STB ", 4, 2, D_Direct, NULL }, /* 0xd7 */ + { "EORB ", 4, 2, D_Direct, NULL }, /* 0xd8 */ + { "ADCB ", 4, 2, D_Direct, NULL }, /* 0xd9 */ + { "ORB ", 4, 2, D_Direct, NULL }, /* 0xda */ + { "ADDB ", 4, 2, D_Direct, NULL }, /* 0xdb */ + { "LDD ", 5, 2, D_Direct, NULL }, /* 0xdc */ + { "STD ", 5, 2, D_Direct, NULL }, /* 0xdd */ + { "LDU ", 5, 2, D_Direct, NULL }, /* 0xde */ + { "STU ", 5, 2, D_Direct, NULL }, /* 0xdf */ + + { "SUBB ", 4, 2, D_Indexed, NULL }, /* 0xe0 */ + { "CMPB ", 4, 2, D_Indexed, NULL }, /* 0xe1 */ + { "SBCB ", 4, 2, D_Indexed, NULL }, /* 0xe2 */ + { "ADDD ", 6, 2, D_Indexed, NULL }, /* 0xe3 */ + { "ANDB ", 4, 2, D_Indexed, NULL }, /* 0xe4 */ + { "BITB ", 4, 2, D_Indexed, NULL }, /* 0xe5 */ + { "LDB ", 4, 2, D_Indexed, NULL }, /* 0xe6 */ + { "STB ", 4, 2, D_Indexed, NULL }, /* 0xe7 */ + { "EORB ", 4, 2, D_Indexed, NULL }, /* 0xe8 */ + { "ADCB ", 4, 2, D_Indexed, NULL }, /* 0xe9 */ + { "ORB ", 4, 2, D_Indexed, NULL }, /* 0xea */ + { "ADDB ", 4, 2, D_Indexed, NULL }, /* 0xeb */ + { "LDD ", 5, 2, D_Indexed, NULL }, /* 0xec */ + { "STD ", 5, 2, D_Indexed, NULL }, /* 0xed */ + { "LDU ", 5, 2, D_Indexed, NULL }, /* 0xee */ + { "STU ", 5, 2, D_Indexed, NULL }, /* 0xef */ + + { "SUBB ", 5, 3, D_Extended, NULL }, /* 0xf0 */ + { "CMPB ", 5, 3, D_Extended, NULL }, /* 0xf1 */ + { "SBCB ", 5, 3, D_Extended, NULL }, /* 0xf2 */ + { "ADDD ", 7, 3, D_Extended, NULL }, /* 0xf3 */ + { "ANDB ", 5, 3, D_Extended, NULL }, /* 0xf4 */ + { "BITB ", 5, 3, D_Extended, NULL }, /* 0xf5 */ + { "LDB ", 5, 3, D_Extended, NULL }, /* 0xf6 */ + { "STB ", 5, 3, D_Extended, NULL }, /* 0xf7 */ + { "EORB ", 5, 3, D_Extended, NULL }, /* 0xf8 */ + { "ADCB ", 5, 3, D_Extended, NULL }, /* 0xf9 */ + { "ORB ", 5, 3, D_Extended, NULL }, /* 0xfa */ + { "ADDB ", 5, 3, D_Extended, NULL }, /* 0xfb */ + { "LDD ", 6, 3, D_Extended, NULL }, /* 0xfc */ + { "STD ", 6, 3, D_Extended, NULL }, /* 0xfd */ + { "LDU ", 6, 3, D_Extended, NULL }, /* 0xfe */ + { "STU ", 6, 3, D_Extended, NULL }, /* 0xff */ +}; + +Opcode optable10[] = { + { "?????", 0, 1, D_Illegal, NULL }, /* 0x00 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x01 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x02 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x03 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x04 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x05 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x06 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x07 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x08 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x09 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x0a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x0b */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x0c */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x0d */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x0e */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x0f */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0x10 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x11 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x12 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x13 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x14 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x15 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x16 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x17 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x18 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x19 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x1a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x1b */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x1c */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x1d */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x1e */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x1f */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0x20 */ + { "LBRN ", 5, 4, D_RelativeL, NULL }, /* 0x21 */ + { "LBHI ", 5, 4, D_RelativeL, NULL }, /* 0x22 */ + { "LBLS ", 5, 4, D_RelativeL, NULL }, /* 0x23 */ + { "LBCC ", 5, 4, D_RelativeL, NULL }, /* 0x24 */ + { "LBCS ", 5, 4, D_RelativeL, NULL }, /* 0x25 */ + { "LBNE ", 5, 4, D_RelativeL, NULL }, /* 0x26 */ + { "LBEQ ", 5, 4, D_RelativeL, NULL }, /* 0x27 */ + { "LBVC ", 5, 4, D_RelativeL, NULL }, /* 0x28 */ + { "LBVS ", 5, 4, D_RelativeL, NULL }, /* 0x29 */ + { "LBPL ", 5, 4, D_RelativeL, NULL }, /* 0x2a */ + { "LBMI ", 5, 4, D_RelativeL, NULL }, /* 0x2b */ + { "LBGE ", 5, 4, D_RelativeL, NULL }, /* 0x2c */ + { "LBLT ", 5, 4, D_RelativeL, NULL }, /* 0x2d */ + { "LBGT ", 5, 4, D_RelativeL, NULL }, /* 0x2e */ + { "LBLE ", 5, 4, D_RelativeL, NULL }, /* 0x2f */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0x30 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x31 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x32 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x33 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x34 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x35 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x36 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x37 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x38 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x39 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x3a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x3b */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x3c */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x3d */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x3e */ +/* Fake SWI2 as an OS9 F$xxx system call */ + { "OS9 ", 20, 3, D_OS9, NULL }, /* 0x3f */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0x40 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x41 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x42 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x43 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x44 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x45 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x46 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x47 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x48 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x49 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x4a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x4b */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x4c */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x4d */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x4e */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x4f */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0x50 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x51 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x52 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x53 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x54 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x55 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x56 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x57 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x58 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x59 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x5a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x5b */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x5c */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x5d */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x5e */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x5f */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0x60 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x61 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x62 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x63 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x64 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x65 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x66 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x67 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x68 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x69 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x6a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x6b */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x6c */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x6d */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x6e */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x6f */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0x70 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x71 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x72 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x73 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x74 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x75 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x76 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x77 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x78 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x79 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x7a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x7b */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x7c */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x7d */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x7e */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x7f */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0x80 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x81 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x82 */ + { "CMPD ", 5, 4, D_ImmediatL, NULL }, /* 0x83 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x84 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x85 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x86 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x87 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x88 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x89 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x8a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x8b */ + { "CMPY ", 5, 4, D_ImmediatL, NULL }, /* 0x8c */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x8d */ + { "LDY ", 4, 4, D_ImmediatL, NULL }, /* 0x8e */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x8f */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0x90 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x91 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x92 */ + { "CMPD ", 7, 3, D_Direct, NULL }, /* 0x93 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x94 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x95 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x96 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x97 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x98 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x99 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x9a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x9b */ + { "CMPY ", 7, 3, D_Direct, NULL }, /* 0x9c */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x9d */ + { "LDY ", 6, 3, D_Direct, NULL }, /* 0x9e */ + { "STY ", 6, 3, D_Direct, NULL }, /* 0x9f */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0xa0 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xa1 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xa2 */ + { "CMPD ", 7, 3, D_Indexed, NULL }, /* 0xa3 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xa4 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xa5 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xa6 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xa7 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xa8 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xa9 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xaa */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xab */ + { "CMPY ", 7, 3, D_Indexed, NULL }, /* 0xac */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xad */ + { "LDY ", 6, 3, D_Indexed, NULL }, /* 0xae */ + { "STY ", 6, 3, D_Indexed, NULL }, /* 0xaf */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0xb0 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xb1 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xb2 */ + { "CMPD ", 8, 4, D_Extended, NULL }, /* 0xb3 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xb4 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xb5 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xb6 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xb7 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xb8 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xb9 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xba */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xbb */ + { "CMPY ", 8, 4, D_Extended, NULL }, /* 0xbc */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xbd */ + { "LDY ", 7, 4, D_Extended, NULL }, /* 0xbe */ + { "STY ", 7, 4, D_Extended, NULL }, /* 0xbf */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0xc0 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xc1 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xc2 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xc3 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xc4 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xc5 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xc6 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xc7 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xc8 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xc9 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xca */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xcb */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xcc */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xcd */ + { "LDS ", 4, 4, D_ImmediatL, NULL }, /* 0xce */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xcf */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0xd0 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xd1 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xd2 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xd3 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xd4 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xd5 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xd6 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xd7 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xd8 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xd9 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xda */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xdb */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xdc */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xdd */ + { "LDS ", 6, 3, D_Direct, NULL }, /* 0xde */ + { "STS ", 6, 3, D_Direct, NULL }, /* 0xdf */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0xe0 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xe1 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xe2 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xe3 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xe4 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xe5 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xe6 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xe7 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xe8 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xe9 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xea */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xeb */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xec */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xed */ + { "LDS ", 6, 3, D_Indexed, NULL }, /* 0xee */ + { "STS ", 6, 3, D_Indexed, NULL }, /* 0xef */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0xf0 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xf1 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xf2 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xf3 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xf4 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xf5 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xf6 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xf7 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xf8 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xf9 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xfa */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xfb */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xfc */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xfd */ + { "LDS ", 7, 4, D_Extended, NULL }, /* 0xfe */ + { "STS ", 7, 4, D_Extended, NULL }, /* 0xff */ + +}; + + +Opcode optable11[] = { + { "?????", 0, 1, D_Illegal, NULL }, /* 0x00 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x01 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x02 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x03 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x04 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x05 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x06 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x07 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x08 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x09 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x0a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x0b */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x0c */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x0d */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x0e */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x0f */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0x10 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x11 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x12 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x13 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x14 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x15 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x16 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x17 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x18 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x19 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x1a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x1b */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x1c */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x1d */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x1e */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x1f */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0x20 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x21 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x22 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x23 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x24 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x25 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x26 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x27 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x28 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x29 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x2a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x2b */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x2c */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x2d */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x2e */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x2f */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0x30 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x31 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x32 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x33 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x34 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x35 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x36 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x37 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x38 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x39 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x3a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x3b */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x3c */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x3d */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x3e */ + { "SWI3 ", 20, 2, D_Inherent, NULL }, /* 0x3f */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0x40 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x41 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x42 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x43 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x44 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x45 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x46 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x47 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x48 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x49 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x4a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x4b */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x4c */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x4d */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x4e */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x4f */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0x50 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x51 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x52 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x53 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x54 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x55 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x56 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x57 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x58 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x59 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x5a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x5b */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x5c */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x5d */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x5e */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x5f */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0x60 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x61 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x62 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x63 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x64 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x65 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x66 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x67 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x68 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x69 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x6a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x6b */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x6c */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x6d */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x6e */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x6f */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0x70 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x71 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x72 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x73 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x74 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x75 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x76 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x77 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x78 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x79 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x7a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x7b */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x7c */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x7d */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x7e */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x7f */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0x80 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x81 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x82 */ + { "CMPU ", 5, 4, D_ImmediatL, NULL }, /* 0x83 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x84 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x85 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x86 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x87 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x88 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x89 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x8a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x8b */ + { "CMPS ", 5, 4, D_ImmediatL, NULL }, /* 0x8c */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x8d */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x8e */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x8f */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0x90 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x91 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x92 */ + { "CMPU ", 7, 3, D_Direct, NULL }, /* 0x93 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x94 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x95 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x96 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x97 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x98 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x99 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x9a */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x9b */ + { "CMPS ", 7, 3, D_Direct, NULL }, /* 0x9c */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x9d */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x9e */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0x9f */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0xa0 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xa1 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xa2 */ + { "CMPU ", 7, 3, D_Indexed, NULL }, /* 0xa3 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xa4 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xa5 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xa6 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xa7 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xa8 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xa9 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xaa */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xab */ + { "CMPS ", 7, 3, D_Indexed, NULL }, /* 0xac */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xad */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xae */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xaf */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0xb0 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xb1 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xb2 */ + { "CMPU ", 8, 4, D_Extended, NULL }, /* 0xb3 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xb4 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xb5 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xb6 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xb7 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xb8 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xb9 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xba */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xbb */ + { "CMPS ", 8, 4, D_Extended, NULL }, /* 0xbc */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xbd */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xbe */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xbf */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0xc0 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xc1 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xc2 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xc3 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xc4 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xc5 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xc6 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xc7 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xc8 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xc9 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xca */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xcb */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xcc */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xcd */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xce */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xcf */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0xd0 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xd1 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xd2 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xd3 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xd4 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xd5 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xd6 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xd7 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xd8 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xd9 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xda */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xdb */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xdc */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xdd */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xde */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xdf */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0xe0 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xe1 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xe2 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xe3 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xe4 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xe5 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xe6 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xe7 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xe8 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xe9 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xea */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xeb */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xec */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xed */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xee */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xef */ + + { "?????", 0, 1, D_Illegal, NULL }, /* 0xf0 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xf1 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xf2 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xf3 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xf4 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xf5 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xf6 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xf7 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xf8 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xf9 */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xfa */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xfb */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xfc */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xfd */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xfe */ + { "?????", 0, 1, D_Illegal, NULL }, /* 0xff */ +}; + +int iotable[32] = { + 0x0000, + 0x0001, + 0x0002, + 0x0003, + 0x0008, + 0x0009, + 0x000a, + 0x000b, + 0x000c, + 0x000d, + 0x000e, + 0x0010, + 0x0011, + 0x0012, + 0x0013, + 0x0014, + 0x8000, + 0x8001, + 0x8002, + 0x8003, + 0x8004, + 0x8005, + 0x8006, + 0x8007, + 0x8008, + 0x8009, + 0x800a, + 0x800b, + 0x800c, + 0x800d, + 0x800e, + 0x800f, +}; + +char *iocomment[32] = { + "Data direction register port 1", + "Data direction register port 2", + "I/O register port 1", + "I/O register port 2", + "Timer control and status", + "Counter high byte", + "Counter low byte", + "Output compare high byte", + "Output compare low byte", + "Input capture high byte", + "Input capture low byte", + "Serial rate and mode register", + "Serial control and status register", + "Serial receiver data register", + "Serial transmit data register", + "Ram control register", + "Modem port 0", + "Modem port 1", + "Modem port 2", + "Modem port 3", + "Modem port 4", + "Modem port 5", + "Modem port 6", + "Modem port 7", + "Modem port 8", + "Modem port 9", + "Modem port 10", + "Modem port 11", + "Modem port 12", + "Modem port 13", + "Modem port 14", + "Modem port 15", +}; + +char *Inter_Register[16]={"D","X","Y","U","S","PC","??","??","A","B","CC","DP","??","??","??","??"}; + +char *Indexed_Register[4]={"X","Y","U","S"}; + +int lastio = 32; + +#pragma argsused +int D_Illegal(op, code, pc, suffix) +Opcode *op; +int code; +int pc; +char *suffix; +{ + fprintf(fp,"%0.2X %s%s", code, suffix, op->name); + return op->bytes; +} + +#pragma argsused +int D_Direct(op, code, pc, suffix) +Opcode *op; +int code; +int pc; +char *suffix; +{ + int offset; + + offset = prog[pc+1]; + fprintf(fp,"%0.2X %0.2X %s%s $%0.2X", + code, offset, suffix, op->name, offset); + return op->bytes; +} + +#pragma argsused +int D_Page10(op, code, pc, suffix) +Opcode *op; +int code; +int pc; +char *suffix; +{ + fprintf(fp,"10 "); + code = prog[pc+1]; + return (*optable10[code].display)(&optable10[code], code, pc+1, ""); +} + +#pragma argsused +int D_Page11(op, code, pc, suffix) +Opcode *op; +int code; +int pc; +char *suffix; +{ + fprintf(fp,"11 "); + code = prog[pc+1]; + return (*optable11[code].display)(&optable11[code], code, pc+1, ""); +} + +#pragma argsused +int D_Immediat(op, code, pc, suffix) +Opcode *op; +int code; +int pc; +char *suffix; +{ + int offset; + + offset = prog[pc+1]; + fprintf(fp,"%0.2X %0.2X %s%s #$%0.2X", + code, offset, suffix, op->name, offset); + return op->bytes; +} + +#pragma argsused +int D_ImmediatL(op, code, pc, suffix) +Opcode *op; +int code; +int pc; +char *suffix; +{ + int offset; + + offset = prog[pc+1] * 256 + prog[pc+2]; + fprintf(fp,"%0.2X %0.2X %0.2X %s%s #$%0.4X", + code, prog[pc+1], prog[pc+2], suffix, op->name, offset); + return op->bytes; +} + +#pragma argsused +int D_Inherent(op, code, pc, suffix) +Opcode *op; +int code; +int pc; +char *suffix; +{ + fprintf(fp,"%0.2X %s%s", code, suffix, op->name); + return op->bytes; +} + +#pragma argsused +int D_OS9(op, code, pc, suffix) +Opcode *op; +int code; +int pc; +char *suffix; +{ + int offset; + + offset = prog[pc+2]; + + fprintf(fp,"%0.2X %0.2X %s%s $%0.2X", + code, offset, suffix, op->name, prog[pc+2]); + return op->bytes; +} + +#pragma argsused +char *IndexRegister(postbyte) +int postbyte; +{ + return Indexed_Register[ (postbyte>>5) & 0x03]; +} + +#pragma argsused +int D_Indexed(op, code, pc, suffix) +Opcode *op; +int code; +int pc; +char *suffix; +{ + int postbyte; + char *s; + int extrabytes; + int disp; + int address; + int offset; + + extrabytes = 0; + postbyte = prog[pc+1]; + if ((postbyte & 0x80) == 0x00) { + disp = postbyte & 0x1f; + if ((postbyte & 0x10) == 0x10) { + s = "-"; + disp=0x20-disp; + } + else + s = "+"; + fprintf(fp,"%0.2X %0.2X %s%s %s$%0.2X,%s", + code, postbyte, suffix, op->name, s,disp,IndexRegister(postbyte)); + } else { + switch(postbyte & 0x1f) { + case 0x00 : + fprintf(fp,"%0.2X %0.2X %s%s ,%s+", + code, postbyte, suffix, op->name, IndexRegister(postbyte)); + break; + case 0x01 : + fprintf(fp,"%0.2X %0.2X %s%s ,%s++", + code, postbyte, suffix, op->name, IndexRegister(postbyte)); + break; + case 0x02 : + fprintf(fp,"%0.2X %0.2X %s%s ,-%s", + code, postbyte, suffix, op->name, IndexRegister(postbyte)); + break; + case 0x03 : + fprintf(fp,"%0.2X %0.2X %s%s ,--%s", + code, postbyte, suffix, op->name, IndexRegister(postbyte)); + break; + case 0x04 : + fprintf(fp,"%0.2X %0.2X %s%s ,%s", + code, postbyte, suffix, op->name, IndexRegister(postbyte)); + break; + case 0x05 : + fprintf(fp,"%0.2X %0.2X %s%s B,%s", + code, postbyte, suffix, op->name, IndexRegister(postbyte)); + break; + case 0x06 : + fprintf(fp,"%0.2X %0.2X %s%s A,%s", + code, postbyte, suffix, op->name, IndexRegister(postbyte)); + break; + case 0x07 : + break; + case 0x08 : + offset = prog[pc+2]; + if (offset < 128) + s = "+"; + else { + s = "-"; + offset=0x0100-offset; + } + fprintf(fp,"%0.2X %0.2X %0.2X %s%s %s$%0.2X,%s", + code, postbyte, prog[pc+2], suffix, op->name, s, offset, + IndexRegister(postbyte)); + extrabytes=1; + break; + case 0x09 : + offset = prog[pc+2] * 256 + prog[pc+3]; + if (offset < 32768) + s = "+"; + else { + s = "-"; + offset=0xffff-offset+1; + } + fprintf(fp,"%0.2X %0.2X %0.2X %0.2X %s%s %s$%0.4X,%s", + code, postbyte, prog[pc+2], prog[pc+3], suffix, op->name, s, offset, + IndexRegister(postbyte)); + extrabytes=2; + break; + case 0x0a : + break; + case 0x0b : + fprintf(fp,"%0.2X %0.2X %s%s D,%s", + code, postbyte, suffix, op->name, IndexRegister(postbyte)); + break; + case 0x0c : + offset = (prog[pc+2]+pc+3) & 0xFFFF; + s = "<"; + fprintf(fp,"%0.2X %0.2X %0.2X %s%s %s$%0.2X,PCR", + code, postbyte, prog[pc+2], suffix, op->name, s, pc+3+offset+adoffset); + extrabytes = 1; + break; + case 0x0d : + offset = (prog[pc+2] * 256 + prog[pc+3]+pc+4) & 0xFFFF; + s = ">"; + fprintf(fp,"%0.2X %0.2X %0.2X %0.2X %s%s %s$%0.4X,PCR", + code, postbyte, prog[pc+2], prog[pc+3], suffix, op->name, s, offset+pc+4+adoffset); + extrabytes = 2; + break; + case 0x0e : + break; + case 0x0f : + fprintf(fp,"%0.2X %0.2X %s?????", + code, postbyte, suffix); + break; + case 0x10 : + fprintf(fp,"%0.2X %0.2X %s?????", + code, postbyte, suffix); + break; + case 0x11 : + fprintf(fp,"%0.2X %0.2X %s%s [,%s++]", + code, postbyte, suffix, op->name, IndexRegister(postbyte)); + break; + case 0x12 : + fprintf(fp,"%0.2X %0.2X %s?????", + code, postbyte, suffix); + break; + case 0x13 : + fprintf(fp,"%0.2X %0.2X %s%s [,--%s]", + code, postbyte, suffix, op->name, IndexRegister(postbyte)); + break; + case 0x14 : + fprintf(fp,"%0.2X %0.2X %s%s [,%s]", + code, postbyte, suffix, op->name, IndexRegister(postbyte)); + break; + case 0x15 : + fprintf(fp,"%0.2X %0.2X %s%s [B,%s]", + code, postbyte, suffix, op->name, IndexRegister(postbyte)); + break; + case 0x16 : + fprintf(fp,"%0.2X %0.2X %s%s [A,%s]", + code, postbyte, suffix, op->name, IndexRegister(postbyte)); + break; + case 0x17 : + break; + case 0x18 : + offset = prog[pc+2]; + if (offset < 128) + s = "+"; + else { + s = "-"; + offset=0x0100-offset; + } + fprintf(fp,"%0.2X %0.2X %0.2X %s%s [%s$%0.2X,%s]", + code, postbyte, prog[pc+2], suffix, op->name, s, offset, + IndexRegister(postbyte)); + break; + case 0x19 : + offset = prog[pc+2] * 256 + prog[pc+3]; + if (offset < 32768) + s = "+"; + else { + s = "-"; + offset=0xffff-offset+1; + } + fprintf(fp,"%0.2X %0.2X %0.2X %0.2X %s%s %s$%0.4X,%s", + code, postbyte, prog[pc+2], prog[pc+3], suffix, op->name, s, offset, + IndexRegister(postbyte)); + break; + case 0x1a : + break; + case 0x1b : + fprintf(fp,"%0.2X %0.2X %s%s [D,%s]", + code, postbyte, suffix, op->name, IndexRegister(postbyte)); + break; + case 0x1c : + offset = (prog[pc+2]+pc+3) & 0xFFFF; + s = "<"; + fprintf(fp,"%0.2X %0.2X %0.2X %s%s [%s$%0.2X,PCR]", + code, postbyte, prog[pc+2], suffix, op->name, s, offset); + extrabytes = 1; + break; + case 0x1d : + offset = (prog[pc+2] * 256 + prog[pc+3]+pc+4) & 0xFFFF; + s = ">"; + fprintf(fp,"%0.2X %0.2X %0.2X %0.2X %s%s [%s$%0.4X,PCR]", + code, postbyte, prog[pc+2], prog[pc+3], suffix, op->name, s, offset); + extrabytes = 2; + break; + case 0x1e : + break; + case 0x1f : + address = prog[pc+2] * 256 + prog[pc+3]; + extrabytes = 2; + fprintf(fp,"%0.2X %0.2X %0.2X %0.2X %s%s [$%4X]", + code, postbyte, prog[pc+2], prog[pc+3], suffix, op->name, address); + break; + } + } + return op->bytes + extrabytes; +} + +#pragma argsused +int D_Extended(op, code, pc, suffix) +Opcode *op; +int code; +int pc; +char *suffix; +{ + int offset; + + offset = prog[pc+1] * 256 + prog[pc+2]; + fprintf(fp,"%0.2X %0.2X %0.2X %s%s $%0.4X", + code, prog[pc+1], prog[pc+2], suffix, op->name, offset); + return op->bytes; +} + +#pragma argsused +int D_Relative(op, code, pc, suffix) +Opcode *op; +int code; +int pc; +char *suffix; +{ + int offset; + int disp; + + offset = prog[pc+1]; + if (offset < 127 ) + disp = pc + 2 + offset; + else + disp = pc + 2 - (256 - offset); + fprintf(fp,"%0.2X %0.2X %s%s $%0.4X", + code, offset, suffix, op->name, disp); + return op->bytes; +} + +#pragma argsused +int D_RelativeL(op, code, pc, suffix) +Opcode *op; +int code; +int pc; +char *suffix; +{ + int offset; + int disp; + + offset = prog[pc+1] * 256 + prog[pc+2]; + if (offset < 32767 ) + disp = pc + 3 + offset + adoffset; + else + disp = pc + 3 - (65536 - offset) + adoffset; + fprintf(fp,"%0.2X %0.2X %0.2X %s%s $%0.4X", + code, prog[pc+1], prog[pc+2], suffix, op->name, disp); + return op->bytes; +} + +#pragma argsused +int D_Register0(op, code, pc, suffix) +Opcode *op; +int code; +int pc; +char *suffix; +{ + int postbyte; + + postbyte = prog[pc+1]; + + fprintf(fp,"%0.2X %0.2X %s%s %s,%s", + code, postbyte, suffix, op->name, Inter_Register[postbyte>>4], Inter_Register[postbyte & 0x0F]); + + + return op->bytes; +} + +#pragma argsused +int D_Register1(op, code, pc, suffix) +Opcode *op; +int code; +int pc; +char *suffix; +{ + int postbyte; + int i; + int flag=0; + static char *s_stack[8]={"PC","U","Y","X","DP","B","A","CC"}; + static int bits[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}; + + postbyte = prog[pc+1]; + + fprintf(fp,"%0.2X %0.2X %s%s ", + code, postbyte, suffix, op->name); + + for(i=0;i<8;i++) { + if ((postbyte & bits[i]) !=0) { + if (flag !=0) { + fprintf(fp,","); + } else { + flag=1; + } + fprintf(fp,s_stack[i]); + } + } + return op->bytes; +} + +#pragma argsused +int D_Register2(op, code, pc, suffix) +Opcode *op; +int code; +int pc; +char *suffix; +{ + int postbyte; + int i; + int flag=0; + static char *u_stack[8]={"PC","S","Y","X","DP","B","A","CC"}; + static int bits[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}; + + postbyte = prog[pc+1]; + fprintf(fp,"%0.2X %0.2X %s%s ", + code, postbyte, suffix, op->name); + + for(i=0;i<8;i++) { + if ((postbyte & bits[i]) !=0) { + if (flag !=0) { + fprintf(fp,","); + } else { + flag=1; + } + fprintf(fp,u_stack[i]); + } + } + return op->bytes; +} + + +void hexadump(b, l, loc, w) +unsigned char *b; +int l; +int loc; +int w; +{ + int i; + int j; + int end; + // char b[4096]; + + // memset(b, '\0', 4096); + // memcpy(b, s, l); + //fprintf(fp,"\n"); + end = ((l%w)>0)?(l/w)+1:(l/w); + for (j=0;j= 0x20) && (b[j*w+i] < 0x7f)) { + fprintf(fp,"%c", b[j*w+i]); + } else { + fprintf(fp,"."); + } + } + fprintf(fp,"|\n"); + } + //fprintf(fp,"\n"); +} + +char *comment(arg) +int arg; +{ + int i; + + for (i=0;i 2 && *argv[1] == '-') { + if (argv[1][1]=='o') { + adoffset=strtol(argv[2],(char**)0,0); + argc-=2; + argv += 2; + } + } + if ( argc != 4 ) { + fprintf(stderr, "usage: disasm [-o offset] \n"); + fprintf(stderr, " where start and end are in hex.\n"); + exit(1); + } + + sscanf(argv[2],"%x",&start); start -= adoffset; + sscanf(argv[3],"%x",&end); end -= adoffset; + + fp = stdout; + + fd = open(argv[1], O_RDONLY, S_IREAD|S_IWRITE); + size = read(fd, &prog[0x0000], 0xffff); + + if (end > size) end=size; + + disasm(start, end); + close(fd); + return 0; +} + +#endif // NO_MAIN diff -r 000000000000 -r 9a224bd9b45f os9/os9mod.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os9/os9mod.c Mon Jul 02 02:12:31 2018 +0900 @@ -0,0 +1,187 @@ +#include +#include +#include +#include +#include "os9.h" + + +u_char *os9_string(u_char *string); +void ident(OS9_MODULE_t *mod); +void usage(void); +long pos; + +static char *types[16] = { + "???", "Prog", "Subr", "Multi", "Data", "USR 5", "USR 6", "USR 7", + "USR 8", "USR 9", "USR A", "USR B", "System", "File Manager", + "Device Driver", "Device Descriptor" +}; + +static char *langs[16] = { + "Data", "6809 Obj", "Basic09 I-Code", "Pascal P-Code", "C I-Code", + "Cobol I-Code", "Fortran I-Code", "6309 Obj", "???", "???", "???", + "???", "???", "???", "???", "???" +}; + +int offset = 0; + +int main(int argc, char **argv) +{ + char *filename = NULL; + FILE *fp; + u_char buffer[65536]; /* OS9 Module can't be larger than this */ + OS9_MODULE_t *mod = (OS9_MODULE_t *) buffer; + int i=0, j; + int flag = 0; + + argv++; /* skip my name */ + + if (argc == 1) + usage(); + + while ((argc >= 2) && (*argv[0] == '-')) { + if (*(argv[0] + 1) == 's') { + argc--; + flag = 1; + } else if (*(argv[0] + 1) == 'o') { + argc--; argc--; + argv++; + offset = strtol(argv[0],(char**)0,0); + } else + usage(); + argv++; + } + + + while (argc-- > 1) { + if (*argv==0) return 0; + filename = *(argv++); + + if ((fp = fopen(filename,"rb")) == NULL) { + fprintf(stderr, "Error opening file %s: %s\n", + filename, strerror(errno)); + return 1; + } + + while (!feof(fp)) { + + if (flag) { + int c; + while( !feof(fp) && (c = fgetc(fp)) != 0x87 ); + ungetc(c, fp); + } + + pos = ftell(fp); + if (fread(buffer, OS9_HEADER_SIZE, 1, fp) != 1) { + if (feof(fp)) + break; + else { + fprintf(stderr, "Error reading file %s: %s\n", + filename, strerror(errno)); + return 1; + } + } + + if ((mod->id[0] != OS9_ID0) && (mod->id[1] != OS9_ID1)) { + fprintf(stderr,"Not OS9 module, skipping.\n"); + return 1; + } + + if ((i = os9_header(mod))!=0xff) { + fprintf(stderr, "Bad header parity. Expected 0xFF, got 0x%02X\n", i); + return 1; + } + + i = INT(mod->size) - OS9_HEADER_SIZE; + if ((j = fread(buffer + OS9_HEADER_SIZE, 1, i, fp)) != i) { + fprintf(stderr,"Module short. Expected 0x%04X, got 0x%04X\n", + i + OS9_HEADER_SIZE, j + OS9_HEADER_SIZE); + return 1; + } + ident(mod); + } + fclose(fp); + } + return 0; + +} + +void ident(OS9_MODULE_t *mod) +{ + int i, j; + u_char *name, *ptr, tmp, *buffer = (u_char *) mod; + + i = INT(mod->name); + j = INT(mod->size); + name = os9_string(&buffer[i]); + printf("Offset : 0x%04lx\n", pos + offset); + printf("Header for : %s\n", name); + printf("Module size: $%X #%d\n", j, j); + ptr = &buffer[j - 3]; + printf("Module CRC : $%02X%02X%02X (%s)\n", ptr[0], ptr[1], ptr[2], + os9_crc(mod) ? "Good" : "Bad" ); + printf("Hdr parity : $%02X\n", mod->parity); + + switch ((mod->tyla & TYPE_MASK) >> 4) + { + + case Drivr: + case Prgrm: + i = INT(mod->data.program.exec); + printf("Exec. off : $%04X #%d\n", i, i); + i = INT(mod->data.program.mem); + printf("Data size : $%04X #%d\n", i, i); + break; + + case Devic: + printf("File Mgr : %s\n", + os9_string(&buffer[INT(mod->data.descriptor.fmgr)])); + printf("Driver : %s\n", + os9_string(&buffer[INT(mod->data.descriptor.driver)])); + break; + + case NULL_TYPE: + case TYPE_6: + case TYPE_7: + case TYPE_8: + case TYPE_9: + case TYPE_A: + case TYPE_B: + case Systm: + break; + } + + + + + tmp = buffer[i + strlen((const char *)name)]; + printf("Edition : $%02X #%d\n", tmp, tmp); + printf("Ty/La At/Rv: $%02X $%02x\n", mod->tyla, mod->atrv); + printf("%s mod, ", types[(mod->tyla & TYPE_MASK) >> 4]); + printf("%s, ", langs[mod->tyla & LANG_MASK]); + printf("%s, %s\n", (mod->atrv & ReEnt) ? "re-ent" : "non-share", + (mod->atrv & Modprot) ? "R/W" : "R/O" ); + printf("\n"); +} + +u_char *os9_string(u_char *string) +{ + static u_char cleaned[80]; /* strings shouldn't be longer than this */ + u_char *ptr = cleaned; + int i = 0; + + while (((*(ptr++) = *(string++)) < 0x7f) && + (i++ < sizeof(cleaned) - 1)) + ; + + *(ptr - 1) &= 0x7f; + *ptr = '\0'; + return cleaned; +} +void usage(void) +{ + printf("Usage: os9mod [-s] [-o offset] file [ file ... ]\n"); + printf("Performs an OS-9: 6809 'ident' on the specified files.\n"); + printf(" -s : skip to valid module\n"); + printf(" -o : offset \n\n"); + exit(0); +} diff -r 000000000000 -r 9a224bd9b45f os9crc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os9crc.c Mon Jul 02 02:12:31 2018 +0900 @@ -0,0 +1,52 @@ +/* + * Generate OS9 CRC value + * + * This is a direct replacement for the Microware/Ultra-C + * library function crc() + * by Steve Rance + * https://groups.google.com/forum/#!topic/comp.os.os9/jJONahOrBX8 + */ + +static long crctable[256] = { +0x000000, 0x800063, 0x8000a5, 0x0000c6, 0x800129, 0x00014a, 0x00018c, 0x8001ef, +0x800231, 0x000252, 0x000294, 0x8002f7, 0x000318, 0x80037b, 0x8003bd, 0x0003de, +0x800401, 0x000462, 0x0004a4, 0x8004c7, 0x000528, 0x80054b, 0x80058d, 0x0005ee, +0x000630, 0x800653, 0x800695, 0x0006f6, 0x800719, 0x00077a, 0x0007bc, 0x8007df, +0x800861, 0x000802, 0x0008c4, 0x8008a7, 0x000948, 0x80092b, 0x8009ed, 0x00098e, +0x000a50, 0x800a33, 0x800af5, 0x000a96, 0x800b79, 0x000b1a, 0x000bdc, 0x800bbf, +0x000c60, 0x800c03, 0x800cc5, 0x000ca6, 0x800d49, 0x000d2a, 0x000dec, 0x800d8f, +0x800e51, 0x000e32, 0x000ef4, 0x800e97, 0x000f78, 0x800f1b, 0x800fdd, 0x000fbe, +0x8010a1, 0x0010c2, 0x001004, 0x801067, 0x001188, 0x8011eb, 0x80112d, 0x00114e, +0x001290, 0x8012f3, 0x801235, 0x001256, 0x8013b9, 0x0013da, 0x00131c, 0x80137f, +0x0014a0, 0x8014c3, 0x801405, 0x001466, 0x801589, 0x0015ea, 0x00152c, 0x80154f, +0x801691, 0x0016f2, 0x001634, 0x801657, 0x0017b8, 0x8017db, 0x80171d, 0x00177e, +0x0018c0, 0x8018a3, 0x801865, 0x001806, 0x8019e9, 0x00198a, 0x00194c, 0x80192f, +0x801af1, 0x001a92, 0x001a54, 0x801a37, 0x001bd8, 0x801bbb, 0x801b7d, 0x001b1e, +0x801cc1, 0x001ca2, 0x001c64, 0x801c07, 0x001de8, 0x801d8b, 0x801d4d, 0x001d2e, +0x001ef0, 0x801e93, 0x801e55, 0x001e36, 0x801fd9, 0x001fba, 0x001f7c, 0x801f1f, +0x802121, 0x002142, 0x002184, 0x8021e7, 0x002008, 0x80206b, 0x8020ad, 0x0020ce, +0x002310, 0x802373, 0x8023b5, 0x0023d6, 0x802239, 0x00225a, 0x00229c, 0x8022ff, +0x002520, 0x802543, 0x802585, 0x0025e6, 0x802409, 0x00246a, 0x0024ac, 0x8024cf, +0x802711, 0x002772, 0x0027b4, 0x8027d7, 0x002638, 0x80265b, 0x80269d, 0x0026fe, +0x002940, 0x802923, 0x8029e5, 0x002986, 0x802869, 0x00280a, 0x0028cc, 0x8028af, +0x802b71, 0x002b12, 0x002bd4, 0x802bb7, 0x002a58, 0x802a3b, 0x802afd, 0x002a9e, +0x802d41, 0x002d22, 0x002de4, 0x802d87, 0x002c68, 0x802c0b, 0x802ccd, 0x002cae, +0x002f70, 0x802f13, 0x802fd5, 0x002fb6, 0x802e59, 0x002e3a, 0x002efc, 0x802e9f, +0x003180, 0x8031e3, 0x803125, 0x003146, 0x8030a9, 0x0030ca, 0x00300c, 0x80306f, +0x8033b1, 0x0033d2, 0x003314, 0x803377, 0x003298, 0x8032fb, 0x80323d, 0x00325e, +0x803581, 0x0035e2, 0x003524, 0x803547, 0x0034a8, 0x8034cb, 0x80340d, 0x00346e, +0x0037b0, 0x8037d3, 0x803715, 0x003776, 0x803699, 0x0036fa, 0x00363c, 0x80365f, +0x8039e1, 0x003982, 0x003944, 0x803927, 0x0038c8, 0x8038ab, 0x80386d, 0x00380e, +0x003bd0, 0x803bb3, 0x803b75, 0x003b16, 0x803af9, 0x003a9a, 0x003a5c, 0x803a3f, +0x003de0, 0x803d83, 0x803d45, 0x003d26, 0x803cc9, 0x003caa, 0x003c6c, 0x803c0f, +0x803fd1, 0x003fb2, 0x003f74, 0x803f17, 0x003ef8, 0x803e9b, 0x803e5d, 0x003e3e +}; + +#define UPDCRC(crc,i) (crctable[((crc) >> 16 ^ (i)) & 0xff] ^ (crc) << 8) + +int os9crc(unsigned char c, int crcp) +{ + return UPDCRC(crcp, c); +} + + diff -r 000000000000 -r 9a224bd9b45f v09.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/v09.c Mon Jul 02 02:12:31 2018 +0900 @@ -0,0 +1,146 @@ +/* 6809 Simulator V09. + + Copyright 1994, L.C. Benschop, Eidnhoven The Netherlands. + This version of the program is distributed under the terms and conditions + of the GNU General Public License version 2. See the file COPYING. + THERE IS NO WARRANTY ON THIS PROGRAM!!! + + This program simulates a 6809 processor. + + System dependencies: short must be 16 bits. + char must be 8 bits. + long must be more than 16 bits. + arrays up to 65536 bytes must be supported. + machine must be twos complement. + Most Unix machines will work. For MSODS you need long pointers + and you may have to malloc() the mem array of 65536 bytes. + + Define BIG_ENDIAN if you have a big-endian machine (680x0 etc) + + Special instructions: + SWI2 writes char to stdout from register B. + SWI3 reads char from stdout to register B, sets carry at EOF. + (or when no key available when using term control). + SWI retains its normal function. + CWAI and SYNC stop simulator. + +*/ + + +#include +#include +#include +#include + +#define engine extern + +#include "v09.h" + +FILE *tracefile; + +extern FILE *fp; +extern char *prog; +extern void disasm(int,int); + +void do_trace(FILE *tracefile) +{ + Word pc=pcreg; + Byte ir; + // fprintf(tracefile,"pc=%04x ",pc); + // ir=mem[pc++]; + // fprintf(tracefile,"i=%02x ",ir); if((ir&0xfe)==0x10) fprintf(tracefile,"%02x ",mem[pc]);else + // fprintf(tracefile," "); + fprintf(tracefile,"x=%04x y=%04x u=%04x s=%04x a=%02x b=%02x cc=%02x pc=", + xreg,yreg,ureg,sreg,*areg,*breg,ccreg); + fp = tracefile; + prog = (char*)mem; + disasm(pc,pc); +} + +char *romfile = "v09.rom"; +int romstart = 0x8000; + +long +filesize(FILE *image) +{ + struct stat buf; + fstat(fileno(image),&buf); + return buf.st_size; +} + + +void +read_image() +{ + FILE *image; + if((image=fopen(romfile,"rb"))==NULL) + if((image=fopen("../v09.rom","rb"))==NULL) + if((image=fopen("..\\v09.rom","rb"))==NULL) { + perror("v09, image file"); + exit(2); + } + long len = filesize(image); + fread(mem+romstart,len,1,image); + fclose(image); +} + +void usage(void) +{ + fprintf(stderr,"Usage: v09 [-l romstart] [-rom rom-image] [-t tracefile [-tl addr] [-nt]" + "[-th addr] ]\n[-e escchar] \n"); + exit(1); +} + + +#define CHECKARG if(i==argc)usage();else i++; + +int +main(int argc,char *argv[]) +{ + Word loadaddr=0x100; + char *imagename=0; + int i; + int setterm = 1; + escchar='\x1d'; + tracelo=0;tracehi=0xffff; + for(i=1;i +#ifdef TERM_CONTROL +#include +int tflags; +#endif +#include +#include +#include +#include +#include + +void finish(); + +static int fdump=0; + + +/* Default: no big endian ... */ +#ifndef CPU_BIG_ENDIAN +/* check if environment provides some information about this ... */ +# if defined(BIG_ENDIAN) && defined(BYTE_ORDER) +# if BIG_ENDIAN == BYTE_ORDER +# define CPU_BIG_ENDIAN 1 +# else +# define CPU_BIG_ENDIAN 0 +# endif +# endif +#endif + + +typedef unsigned char Byte; +typedef unsigned short Word; + +/* 6809 registers */ +Byte ccreg,dpreg; +Word xreg,yreg,ureg,sreg,ureg,pcreg; + +Byte fillreg = 0xff; +Word wfillreg = 0xffff; + +Word pcreg_prev; + +Byte d_reg[2]; +Word *dreg=(Word *)d_reg; + + +/* This is a dirty aliasing trick, but fast! */ +#if CPU_BIG_ENDIAN + Byte *areg=d_reg; + Byte *breg=d_reg+1; +#else + Byte *breg=d_reg; + Byte *areg=d_reg+1; +#endif + + +/* 6809 memory space */ +static Byte mem[65536]; + +#define GETWORD(a) (mem[a]<<8|mem[(a)+1]) +#define SETWORD(a,n) {mem[a]=(n)>>8;mem[(a)+1]=n;} +/* Two bytes of a word are fetched separately because of + the possible wrap-around at address $ffff and alignment +*/ + + +int iflag; /* flag to indicate prebyte $10 or $11 */ +Byte ireg; /* Instruction register */ + +#define IMMBYTE(b) b=mem[pcreg++]; +#define IMMWORD(w) {w=GETWORD(pcreg);pcreg+=2;} + +/* sreg */ +#define PUSHBYTE(b) mem[--sreg]=b; +#define PUSHWORD(w) {sreg-=2;SETWORD(sreg,w)} +#define PULLBYTE(b) b=mem[sreg++]; +#define PULLWORD(w) {w=GETWORD(sreg);sreg+=2;} + +/* ureg */ +#define PUSHUBYTE(b) mem[--ureg]=b; +#define PUSHUWORD(w) {ureg-=2;SETWORD(ureg,w)} +#define PULLUBYTE(b) b=mem[ureg++]; +#define PULLUWORD(w) {w=GETWORD(ureg);ureg+=2;} + +#define SIGNED(b) ((Word)(b&0x80?b|0xff00:b)) + +Word *ixregs[]={&xreg,&yreg,&ureg,&sreg}; + +static int idx; + +/* disassembled instruction buffer */ +static char dinst[6]; + +/* disassembled operand buffer */ +static char dops[32]; + +/* disassembled instruction len (optional, on demand) */ +static int da_len; + +/* instruction cycles */ +static int cycles; +unsigned long cycles_sum; + +void da_inst(char *inst, char *reg, int cyclecount) { + *dinst = 0; + *dops = 0; + if (inst != NULL) strcat(dinst, inst); + if (reg != NULL) strcat(dinst, reg); + cycles += cyclecount; +} + +void da_inst_cat(char *inst, int cyclecount) { + if (inst != NULL) strcat(dinst, inst); + cycles += cyclecount; +} + +void da_ops(char *part1, char* part2, int cyclecount) { + if (part1 != NULL) strcat(dops, part1); + if (part2 != NULL) strcat(dops, part2); + cycles += cyclecount; +} + +void da_reg(Byte b) +{ + char *reg[] = { "d", "x", "y", "u", "s", "pc", "?", "?", + "a", "b", "cc", "dp", "?", "?", "?", "?" }; + da_ops( reg[(b>>4) & 0xf], ",", 0); + da_ops( reg[b & 0xf], NULL, 0); +} + +/* Now follow the posbyte addressing modes. */ + +Word illaddr() /* illegal addressing mode, defaults to zero */ +{ + return 0; +} + +static char *dixreg[] = { "x", "y", "u", "s" }; + +Word ainc() +{ + da_ops(",",dixreg[idx],2); + da_ops("+",NULL,0); + return (*ixregs[idx])++; +} + +Word ainc2() +{ + Word temp; + da_ops(",",dixreg[idx],3); + da_ops("++",NULL,0); + temp=(*ixregs[idx]); + (*ixregs[idx])+=2; + return(temp); +} + +Word adec() +{ + da_ops(",-",dixreg[idx],2); + return --(*ixregs[idx]); +} + +Word adec2() +{ + Word temp; + da_ops(",--",dixreg[idx],3); + (*ixregs[idx])-=2; + temp=(*ixregs[idx]); + return(temp); +} + +Word plus0() +{ + da_ops(",",dixreg[idx],0); + return(*ixregs[idx]); +} + +Word plusa() +{ + da_ops("a,",dixreg[idx],1); + return(*ixregs[idx])+SIGNED(*areg); +} + +Word plusb() +{ + da_ops("b,",dixreg[idx],1); + return(*ixregs[idx])+SIGNED(*breg); +} + +Word plusn() +{ + Byte b; + char off[6]; + IMMBYTE(b) + /* negative offsets alway decimal, otherwise hex */ + if (b & 0x80) sprintf(off,"%d,", -(b ^ 0xff)-1); + else sprintf(off,"$%02x,",b); + da_ops(off,dixreg[idx],1); + return(*ixregs[idx])+SIGNED(b); +} + +Word plusnn() +{ + Word w; + IMMWORD(w) + char off[6]; + sprintf(off,"$%04x,",w); + da_ops(off,dixreg[idx],4); + return(*ixregs[idx])+w; +} + +Word plusd() +{ + da_ops("d,",dixreg[idx],4); + return(*ixregs[idx])+*dreg; +} + + +Word npcr() +{ + Byte b; + char off[11]; + + IMMBYTE(b) + sprintf(off,"$%04x,pcr",(pcreg+SIGNED(b))&0xffff); + da_ops(off,NULL,1); + return pcreg+SIGNED(b); +} + +Word nnpcr() +{ + Word w; + char off[11]; + + IMMWORD(w) + sprintf(off,"$%04x,pcr",(pcreg+w)&0xffff); + da_ops(off,NULL,5); + return pcreg+w; +} + +Word direct() +{ + Word(w); + char off[6]; + + IMMWORD(w) + sprintf(off,"$%04x",w); + da_ops(off,NULL,3); + return w; +} + +Word zeropage() +{ + Byte b; + char off[6]; + + IMMBYTE(b) + sprintf(off,"$%02x", b); + da_ops(off,NULL,2); + return dpreg<<8|b; +} + + +Word immediate() +{ + char off[6]; + + sprintf(off,"#$%02x", mem[pcreg]); + da_ops(off,NULL,0); + return pcreg++; +} + +Word immediate2() +{ + Word temp; + char off[7]; + + temp=pcreg; + sprintf(off,"#$%04x", (mem[pcreg]<<8)+mem[(pcreg+1)&0xffff]); + da_ops(off,NULL,0); + pcreg+=2; + return temp; +} + +Word (*pbtable[])()={ ainc, ainc2, adec, adec2, + plus0, plusb, plusa, illaddr, + plusn, plusnn, illaddr, plusd, + npcr, nnpcr, illaddr, direct, }; + +Word postbyte() +{ + Byte pb; + Word temp; + char off[6]; + + IMMBYTE(pb) + idx=((pb & 0x60) >> 5); + if(pb & 0x80) { + if( pb & 0x10) + da_ops("[",NULL,3); + temp=(*pbtable[pb & 0x0f])(); + if( pb & 0x10) { + temp=GETWORD(temp); + da_ops("]",NULL,0); + } + return temp; + } else { + temp=pb & 0x1f; + if(temp & 0x10) temp|=0xfff0; /* sign extend */ + sprintf(off,"%d,",(temp & 0x10) ? -(temp ^ 0xffff)-1 : temp); + da_ops(off,dixreg[idx],1); + return (*ixregs[idx])+temp; + } +} + +Byte * eaddr0() /* effective address for NEG..JMP as byte pointer */ +{ + switch( (ireg & 0x70) >> 4) + { + case 0: return mem+zeropage(); + default: + case 1:case 2:case 3: return 0; /*canthappen*/ + + case 4: da_inst_cat("a",-2); return areg; + case 5: da_inst_cat("b",-2); return breg; + case 6: da_inst_cat(NULL,2); return mem+postbyte(); + case 7: return mem+direct(); + } + +} + +Word eaddr8() /* effective address for 8-bits ops. */ +{ + switch( (ireg & 0x30) >> 4) + { + default: + case 0: return immediate(); + case 1: return zeropage(); + case 2: da_inst_cat(NULL,2); return postbyte(); + case 3: return direct(); + } +} + +Word eaddr16() /* effective address for 16-bits ops. */ +{ + switch( (ireg & 0x30) >> 4) + { + default: + case 0: da_inst_cat(NULL,-1); return immediate2(); + case 1: da_inst_cat(NULL,-1); return zeropage(); + case 2: da_inst_cat(NULL,1); return postbyte(); + case 3: da_inst_cat(NULL,-1); return direct(); + } +} + +void +ill() /* illegal opcode==noop */ +{ +} + +/* macros to set status flags */ +#define SEC ccreg|=0x01; +#define CLC ccreg&=0xfe; +#define SEZ ccreg|=0x04; +#define CLZ ccreg&=0xfb; +#define SEN ccreg|=0x08; +#define CLN ccreg&=0xf7; +#define SEV ccreg|=0x02; +#define CLV ccreg&=0xfd; +#define SEH ccreg|=0x20; +#define CLH ccreg&=0xdf; + +/* set N and Z flags depending on 8 or 16 bit result */ +#define SETNZ8(b) {if(b)CLZ else SEZ if(b&0x80)SEN else CLN} +#define SETNZ16(b) {if(b)CLZ else SEZ if(b&0x8000)SEN else CLN} + +#define SETSTATUS(a,b,res) if((a^b^res)&0x10) SEH else CLH \ + if((a^b^res^(res>>1))&0x80)SEV else CLV \ + if(res&0x100)SEC else CLC SETNZ8((Byte)res) + +void +add() +{ + Word aop,bop,res; + Byte* aaop; + da_inst("add",(ireg&0x40)?"b":"a",2); + aaop=(ireg&0x40)?breg:areg; + aop=*aaop; + bop=mem[eaddr8()]; + res=aop+bop; + SETSTATUS(aop,bop,res) + *aaop=res; +} + +void +sbc() +{ + Word aop,bop,res; + Byte* aaop; + da_inst("sbc",(ireg&0x40)?"b":"a",2); + aaop=(ireg&0x40)?breg:areg; + aop=*aaop; + bop=mem[eaddr8()]; + res=aop-bop-(ccreg&0x01); + SETSTATUS(aop,bop,res) + *aaop=res; +} + +void +sub() +{ + Word aop,bop,res; + Byte* aaop; + da_inst("sub",(ireg&0x40)?"b":"a",2); + aaop=(ireg&0x40)?breg:areg; + aop=*aaop; + bop=mem[eaddr8()]; + res=aop-bop; + SETSTATUS(aop,bop,res) + *aaop=res; +} + +void +adc() +{ + Word aop,bop,res; + Byte* aaop; + da_inst("adc",(ireg&0x40)?"b":"a",2); + aaop=(ireg&0x40)?breg:areg; + aop=*aaop; + bop=mem[eaddr8()]; + res=aop+bop+(ccreg&0x01); + SETSTATUS(aop,bop,res) + *aaop=res; +} + +void +cmp() +{ + Word aop,bop,res; + Byte* aaop; + da_inst("cmp",(ireg&0x40)?"b":"a",2); + aaop=(ireg&0x40)?breg:areg; + aop=*aaop; + bop=mem[eaddr8()]; + res=aop-bop; + SETSTATUS(aop,bop,res) +} + +void +and() +{ + Byte aop,bop,res; + Byte* aaop; + da_inst("and",(ireg&0x40)?"b":"a",2); + aaop=(ireg&0x40)?breg:areg; + aop=*aaop; + bop=mem[eaddr8()]; + res=aop&bop; + SETNZ8(res) + CLV + *aaop=res; +} + +void +or() +{ + Byte aop,bop,res; + Byte* aaop; + da_inst("or",(ireg&0x40)?"b":"a",2); + aaop=(ireg&0x40)?breg:areg; + aop=*aaop; + bop=mem[eaddr8()]; + res=aop|bop; + SETNZ8(res) + CLV + *aaop=res; +} + +void +eor() +{ + Byte aop,bop,res; + Byte* aaop; + da_inst("eor",(ireg&0x40)?"b":"a",2); + aaop=(ireg&0x40)?breg:areg; + aop=*aaop; + bop=mem[eaddr8()]; + res=aop^bop; + SETNZ8(res) + CLV + *aaop=res; +} + +void +bit() +{ + Byte aop,bop,res; + Byte* aaop; + da_inst("bit",(ireg&0x40)?"b":"a",2); + aaop=(ireg&0x40)?breg:areg; + aop=*aaop; + bop=mem[eaddr8()]; + res=aop&bop; + SETNZ8(res) + CLV +} + +void +ld() +{ + Byte res; + Byte* aaop; + da_inst("ld",(ireg&0x40)?"b":"a",2); + aaop=(ireg&0x40)?breg:areg; + res=mem[eaddr8()]; + SETNZ8(res) + CLV + *aaop=res; +} + +void +st() +{ + Byte res; + Byte* aaop; + da_inst("st",(ireg&0x40)?"b":"a",2); + aaop=(ireg&0x40)?breg:areg; + res=*aaop; + mem[eaddr8()]=res; + SETNZ8(res) + CLV +} + +void +jsr() +{ + Word w; + + da_inst("jsr",NULL,5); + da_len=-pcreg; + w=eaddr8(); + da_len += pcreg +1; + PUSHWORD(pcreg) + pcreg=w; +} + +void +bsr() +{ + Byte b; + char off[6]; + + IMMBYTE(b) + da_inst("bsr",NULL,7); + da_len = 2; + PUSHWORD(pcreg) + pcreg+=SIGNED(b); + sprintf(off,"$%04x", pcreg&0xffff); + da_ops(off,NULL,0); +} + +void +neg() +{ + Byte *ea; + Word a,r; + + a=0; + da_inst("neg",NULL,4); + ea=eaddr0(); + a=*ea; + r=-a; + SETSTATUS(0,a,r) + *ea=r; +} + +void +com() +{ + Byte *ea; + Byte r; + + da_inst("com",NULL,4); + ea=eaddr0(); +/* + fprintf(stderr,"DEBUG: com before r=%02X *ea=%02X\n", r, *ea); +*/ + r= ~*ea; +/* + fprintf(stderr,"DEBUG: com after r=%02X *ea=%02X\n", r, *ea); +*/ + SETNZ8(r) + SEC CLV + *ea=r; +} + +void +lsr() +{ + Byte *ea; + Byte r; + + da_inst("lsr",NULL,4); + ea=eaddr0(); + r=*ea; + if(r&0x01)SEC else CLC + if(r&0x10)SEH else CLH + r>>=1; + SETNZ8(r) + *ea=r; +} + +void +ror() +{ + Byte *ea; + Byte r,c; + + c=(ccreg&0x01)<<7; + da_inst("ror",NULL,4); + ea=eaddr0(); + r=*ea; + if(r&0x01)SEC else CLC + r=(r>>1)+c; + SETNZ8(r) + *ea=r; +} + +void +asr() +{ + Byte *ea; + Byte r; + + da_inst("asr",NULL,4); + ea=eaddr0(); + r=*ea; + if(r&0x01)SEC else CLC + if(r&0x10)SEH else CLH + r>>=1; + if(r&0x40)r|=0x80; + SETNZ8(r) + *ea=r; +} + +void +asl() +{ + Byte *ea; + Word a,r; + + da_inst("asl",NULL,4); + ea=eaddr0(); + a=*ea; + r=a<<1; + SETSTATUS(a,a,r) + *ea=r; +} + +void +rol() +{ + Byte *ea; + Byte r,c; + + c=(ccreg&0x01); + da_inst("rol",NULL,4); + ea=eaddr0(); + r=*ea; + if(r&0x80)SEC else CLC + if((r&0x80)^((r<<1)&0x80))SEV else CLV + r=(r<<1)+c; + SETNZ8(r) + *ea=r; +} + +void +inc() +{ + Byte *ea; + Byte r; + + da_inst("inc",NULL,4); + ea=eaddr0(); + r=*ea; + r++; + if(r==0x80)SEV else CLV + SETNZ8(r) + *ea=r; +} + +void +dec() +{ + Byte *ea; + Byte r; + + da_inst("dec",NULL,4); + ea=eaddr0(); + r=*ea; + r--; + if(r==0x7f)SEV else CLV + SETNZ8(r) + *ea=r; +} + +void +tst() +{ + Byte r; + Byte *ea; + + da_inst("tst",NULL,4); + ea=eaddr0(); + r=*ea; + SETNZ8(r) + CLV +} + +void +jmp() +{ + Byte *ea; + + da_len = -pcreg; + da_inst("jmp",NULL,1); + ea=eaddr0(); + da_len += pcreg + 1; + pcreg=ea-mem; +} + +void +clr() +{ + Byte *ea; + + da_inst("clr",NULL,4); + ea=eaddr0(); + *ea=0;CLN CLV SEZ CLC +} + +extern void (*instrtable[])(); + +void +flag0() +{ + if(iflag) /* in case flag already set by previous flag instr don't recurse */ + { + pcreg--; + return; + } + iflag=1; + ireg=mem[pcreg++]; + da_inst(NULL,NULL,1); + (*instrtable[ireg])(); + iflag=0; +} + +void +flag1() +{ + if(iflag) /* in case flag already set by previous flag instr don't recurse */ + { + pcreg--; + return; + } + iflag=2; + ireg=mem[pcreg++]; + da_inst(NULL,NULL,1); + (*instrtable[ireg])(); + iflag=0; +} + +void +nop() +{ + da_inst("nop",NULL,2); +} + +void +sync_inst() +{ + finish(); +} + +void +cwai() +{ + sync_inst(); +} + +void +lbra() +{ + Word w; + char off[6]; + + IMMWORD(w) + pcreg+=w; + da_len = 3; + da_inst("lbra",NULL,5); + sprintf(off,"$%04x", pcreg&0xffff); + da_ops(off,NULL,0); +} + +void +lbsr() +{ + Word w; + char off[6]; + + da_len = 3; + da_inst("lbsr",NULL,9); + IMMWORD(w) + PUSHWORD(pcreg) + pcreg+=w; + sprintf(off,"$%04x", pcreg&0xffff); + da_ops(off,NULL,0); +} + +void +daa() +{ + Word a; + da_inst("daa",NULL,2); + a=*areg; + if(ccreg&0x20)a+=6; + if((a&0x0f)>9)a+=6; + if(ccreg&0x01)a+=0x60; + if((a&0xf0)>0x90)a+=0x60; + if(a&0x100)SEC + *areg=a; +} + +void +orcc() +{ + Byte b; + char off[7]; + IMMBYTE(b) + sprintf(off,"#$%02x", b); + da_inst("orcc",NULL,3); + da_ops(off,NULL,0); + ccreg|=b; +} + +void +andcc() +{ + Byte b; + char off[6]; + IMMBYTE(b) + sprintf(off,"#$%02x", b); + da_inst("andcc",NULL,3); + da_ops(off,NULL,0); + + ccreg&=b; +} + +void +mul() +{ + Word w; + w=*areg * *breg; + da_inst("mul",NULL,11); + if(w)CLZ else SEZ + if(w&0x80) SEC else CLC + *dreg=w; +} + +void +sex() +{ + Word w; + da_inst("sex",NULL,2); + w=SIGNED(*breg); + SETNZ16(w) + *dreg=w; +} + +void +abx() +{ + da_inst("abx",NULL,3); + xreg += *breg; +} + +void +rts() +{ + da_inst("rts",NULL,5); + da_len = 1; + PULLWORD(pcreg) +} + +void +rti() +{ + Byte x; + x=ccreg&0x80; + da_inst("rti",NULL,(x?15:6)); + da_len = 1; + PULLBYTE(ccreg) + if(x) + { + PULLBYTE(*areg) + PULLBYTE(*breg) + PULLBYTE(dpreg) + PULLWORD(xreg) + PULLWORD(yreg) + PULLWORD(ureg) + } + PULLWORD(pcreg) +} + +void +swi() +{ + int w; + da_inst("swi",(iflag==1)?"2":(iflag==2)?"3":"",5); + switch(iflag) + { + case 0: + PUSHWORD(pcreg) + PUSHWORD(ureg) + PUSHWORD(yreg) + PUSHWORD(xreg) + PUSHBYTE(dpreg) + PUSHBYTE(*breg) + PUSHBYTE(*areg) + PUSHBYTE(ccreg) + ccreg|=0xd0; + pcreg=GETWORD(0xfffa); + break; + case 1: + putchar(*breg); + fflush(stdout); + break; + case 2: + w=getchar(); + if(w==EOF)SEC else CLC + *breg=w; + } +} + + +Word *wordregs[]={(Word*)d_reg,&xreg,&yreg,&ureg,&sreg,&pcreg,&wfillreg,&wfillreg}; + +#if CPU_BIG_ENDIAN +Byte *byteregs[]={d_reg,d_reg+1,&ccreg,&dpreg,&fillreg,&fillreg,&fillreg,&fillreg}; +#else +Byte *byteregs[]={d_reg+1,d_reg,&ccreg,&dpreg,&fillreg,&fillreg,&fillreg,&fillreg}; +#endif + +void +tfr() +{ + Byte b; + da_inst("tfr",NULL,7); + IMMBYTE(b) + da_reg(b); + Word v; + // source in higher nibble (highest bit set means 8 bit reg.) + if(b&0x80) { + v=*byteregs[(b&0x70)>>4] | (b&0x08 ? 0 : 0xff00); + } else { + v=*wordregs[(b&0x70)>>4]; + } + // dest in lower nibble (highest bit set means 8 bit reg.) + if(b&0x8) { + *byteregs[b&0x07]=v&0xff; + fillreg=0xff; // keep fillvalue + } else { + *wordregs[b&0x07]=v; + wfillreg = 0xffff; // keep fillvalue + } +} + +void +exg() +{ + Byte b; + Word f; + Word t; + da_inst("exg",NULL,8); + IMMBYTE(b) + da_reg(b); + if(b&0x80) { + f=*byteregs[(b&0x70)>>4] | 0xff00; + } else { + f=*wordregs[(b>>4)&0x07]; + } + if(b&0x8) { + t=*byteregs[b&0x07] | 0xff00; + } else { + t=*wordregs[b&0x07]; + } + if(b&0x80) { + *byteregs[(b&0x70)>>4] = t; + fillreg=0xff; // keep fillvalue + } else { + *wordregs[(b>>4)&0x07] = t; + wfillreg = 0xffff; // keep fillvalue + } + if(b&0x8) { + *byteregs[b&0x07] = f; + fillreg=0xff; // keep fillvalue + } else { + *wordregs[b&0x07] = f; + wfillreg = 0xffff; // keep fillvalue + } +} + +void +br(int f) +{ + Byte b; + Word w; + char off[7]; + Word dest; + + if(!iflag) { + IMMBYTE(b) + dest = pcreg+SIGNED(b); + if(f) pcreg+=SIGNED(b); + da_len = 2; + } else { + IMMWORD(w) + dest = pcreg+w; + if(f) pcreg+=w; + da_len = 3; + } + sprintf(off,"$%04x", dest&0xffff); + da_ops(off,NULL,0); +} + +#define NXORV ((ccreg&0x08)^(ccreg&0x02)) + +void +bra() +{ + da_inst(iflag?"l":"","bra",iflag?5:3); + br(1); +} + +void +brn() +{ + da_inst(iflag?"l":"","brn",iflag?5:3); + br(0); +} + +void +bhi() +{ + da_inst(iflag?"l":"","bhi",iflag?5:3); + br(!(ccreg&0x05)); +} + +void +bls() +{ + da_inst(iflag?"l":"","bls",iflag?5:3); + br(ccreg&0x05); +} + +void +bcc() +{ + da_inst(iflag?"l":"","bcc",iflag?5:3); + br(!(ccreg&0x01)); +} + +void +bcs() +{ + da_inst(iflag?"l":"","bcs",iflag?5:3); + br(ccreg&0x01); +} + +void +bne() +{ + da_inst(iflag?"l":"","bne",iflag?5:3); + br(!(ccreg&0x04)); +} + +void +beq() +{ + da_inst(iflag?"l":"","beq",iflag?5:3); + br(ccreg&0x04); +} + +void +bvc() +{ + da_inst(iflag?"l":"","bvc",iflag?5:3); + br(!(ccreg&0x02)); +} + +void +bvs() +{ + da_inst(iflag?"l":"","bvs",iflag?5:3); + br(ccreg&0x02); +} + +void +bpl() +{ + da_inst(iflag?"l":"","bpl",iflag?5:3); + br(!(ccreg&0x08)); +} + +void +bmi() +{ + da_inst(iflag?"l":"","bmi",iflag?5:3); + br(ccreg&0x08); +} + +void +bge() +{ + da_inst(iflag?"l":"","bge",iflag?5:3); + br(!NXORV); +} + +void +blt() +{ + da_inst(iflag?"l":"","blt",iflag?5:3); + br(NXORV); +} + +void +bgt() +{ + da_inst(iflag?"l":"","bgt",iflag?5:3); + br(!(NXORV||ccreg&0x04)); +} + +void +ble() +{ + da_inst(iflag?"l":"","ble",iflag?5:3); + br(NXORV||ccreg&0x04); +} + +void +leax() +{ + Word w; + da_inst("leax",NULL,4); + w=postbyte(); + if(w) CLZ else SEZ + xreg=w; +} + +void +leay() +{ + Word w; + da_inst("leay",NULL,4); + w=postbyte(); + if(w) CLZ else SEZ + yreg=w; +} + +void +leau() +{ + da_inst("leau",NULL,4); + ureg=postbyte(); +} + +void +leas() +{ + da_inst("leas",NULL,4); + sreg=postbyte(); +} + + +int bit_count(Byte b) +{ + Byte mask=0x80; + int count=0; + int i; + char *reg[] = { "pc", "u", "y", "x", "dp", "b", "a", "cc" }; + + for(i=0; i<=7; i++) { + if (b & mask) { + count++; + da_ops(count > 1 ? ",":"", reg[i],1+(i<4?1:0)); + } + mask >>= 1; + } + return count; +} + + +void +pshs() +{ + Byte b; + IMMBYTE(b) + da_inst("pshs",NULL,5); + bit_count(b); + if(b&0x80)PUSHWORD(pcreg) + if(b&0x40)PUSHWORD(ureg) + if(b&0x20)PUSHWORD(yreg) + if(b&0x10)PUSHWORD(xreg) + if(b&0x08)PUSHBYTE(dpreg) + if(b&0x04)PUSHBYTE(*breg) + if(b&0x02)PUSHBYTE(*areg) + if(b&0x01)PUSHBYTE(ccreg) +} + +void +puls() +{ + Byte b; + IMMBYTE(b) + da_inst("puls",NULL,5); + da_len = 2; + bit_count(b); + if(b&0x01)PULLBYTE(ccreg) + if(b&0x02)PULLBYTE(*areg) + if(b&0x04)PULLBYTE(*breg) + if(b&0x08)PULLBYTE(dpreg) + if(b&0x10)PULLWORD(xreg) + if(b&0x20)PULLWORD(yreg) + if(b&0x40)PULLWORD(ureg) + if(b&0x80)PULLWORD(pcreg) +} + +void +pshu() +{ + Byte b; + IMMBYTE(b) + da_inst("pshu",NULL,5); + bit_count(b); + if(b&0x80)PUSHUWORD(pcreg) + if(b&0x40)PUSHUWORD(ureg) + if(b&0x20)PUSHUWORD(yreg) + if(b&0x10)PUSHUWORD(xreg) + if(b&0x08)PUSHUBYTE(dpreg) + if(b&0x04)PUSHUBYTE(*breg) + if(b&0x02)PUSHUBYTE(*areg) + if(b&0x01)PUSHUBYTE(ccreg) +} + +void +pulu() +{ + Byte b; + IMMBYTE(b) + da_inst("pulu",NULL,5); + da_len = 2; + bit_count(b); + if(b&0x01)PULLUBYTE(ccreg) + if(b&0x02)PULLUBYTE(*areg) + if(b&0x04)PULLUBYTE(*breg) + if(b&0x08)PULLUBYTE(dpreg) + if(b&0x10)PULLUWORD(xreg) + if(b&0x20)PULLUWORD(yreg) + if(b&0x40)PULLUWORD(ureg) + if(b&0x80)PULLUWORD(pcreg) +} + +#define SETSTATUSD(a,b,res) {if(res&0x10000) SEC else CLC \ + if(((res>>1)^a^b^res)&0x8000) SEV else CLV \ + SETNZ16((Word)res)} + +void +addd() +{ + unsigned long aop,bop,res; + Word ea; + da_inst("addd",NULL,5); + aop=*dreg & 0xffff; + ea=eaddr16(); + bop=GETWORD(ea); + res=aop+bop; + SETSTATUSD(aop,bop,res) + *dreg=res; +} + +void +subd() +{ + unsigned long aop,bop,res; + Word ea; + aop=*dreg & 0xffff; + switch(iflag) { + case 0: + da_inst("subd",NULL,5); + break; + case 1: + da_inst("cmpd",NULL,5); + aop=*dreg & 0xffff; + break; + case 2: + da_inst("cmpu",NULL,5); + aop=ureg; + } + ea=eaddr16(); + bop=GETWORD(ea); + res=aop-bop; + SETSTATUSD(aop,bop,res) + if(iflag==0) *dreg=res; /* subd result */ +} + +void +cmpx() +{ + unsigned long aop,bop,res; + Word ea; + switch(iflag) { + case 0: + da_inst("cmpx",NULL,5); + aop=xreg; + break; + case 1: + da_inst("cmpy",NULL,5); + aop=yreg; + break; + case 2: + da_inst("cmps",NULL,5); + aop=sreg; + } + ea=eaddr16(); + bop=GETWORD(ea); + res=aop-bop; + SETSTATUSD(aop,bop,res) +} + +void +ldd() +{ + Word ea,w; + da_inst("ldd",NULL,4); + ea=eaddr16(); + w=GETWORD(ea); + SETNZ16(w) + *dreg=w; +} + +void +ldx() +{ + Word ea,w; + if (iflag) da_inst("ldy",NULL,4); + else da_inst("ldx",NULL,4); + ea=eaddr16(); + w=GETWORD(ea); + SETNZ16(w) + if (iflag==0) xreg=w; else yreg=w; +} + +void +ldu() +{ + Word ea,w; + if (iflag) da_inst("lds",NULL,4); + else da_inst("ldu",NULL,4); + ea=eaddr16(); + w=GETWORD(ea); + SETNZ16(w) + if (iflag==0) ureg=w; else sreg=w; +} + +void +std() +{ + Word ea,w; + da_inst("std",NULL,4); + ea=eaddr16(); + w=*dreg; + SETNZ16(w) + SETWORD(ea,w) +} + +void +stx() +{ + Word ea,w; + if (iflag) da_inst("sty",NULL,4); + else da_inst("stx",NULL,4); + ea=eaddr16(); + if (iflag==0) w=xreg; else w=yreg; + SETNZ16(w) + SETWORD(ea,w) +} + +void +stu() +{ + Word ea,w; + if (iflag) da_inst("sts",NULL,4); + else da_inst("stu",NULL,4); + ea=eaddr16(); + if (iflag==0) w=ureg; else w=sreg; + SETNZ16(w) + SETWORD(ea,w) +} + +void (*instrtable[])() = { + neg , ill , ill , com , lsr , ill , ror , asr , + asl , rol , dec , ill , inc , tst , jmp , clr , + flag0 , flag1 , nop , sync_inst , ill , ill , lbra , lbsr , + ill , daa , orcc , ill , andcc , sex , exg , tfr , + bra , brn , bhi , bls , bcc , bcs , bne , beq , + bvc , bvs , bpl , bmi , bge , blt , bgt , ble , + leax , leay , leas , leau , pshs , puls , pshu , pulu , + ill , rts , abx , rti , cwai , mul , ill , swi , + neg , ill , ill , com , lsr , ill , ror , asr , + asl , rol , dec , ill , inc , tst , ill , clr , + neg , ill , ill , com , lsr , ill , ror , asr , + asl , rol , dec , ill , inc , tst , ill , clr , + neg , ill , ill , com , lsr , ill , ror , asr , + asl , rol , dec , ill , inc , tst , jmp , clr , + neg , ill , ill , com , lsr , ill , ror , asr , + asl , rol , dec , ill , inc , tst , jmp , clr , +sub , cmp , sbc , subd , and , bit , ld , st , +eor , adc , or , add , cmpx , bsr , ldx , stx , +sub , cmp , sbc , subd , and , bit , ld , st , +eor , adc , or , add , cmpx , jsr , ldx , stx , +sub , cmp , sbc , subd , and , bit , ld , st , +eor , adc , or , add , cmpx , jsr , ldx , stx , +sub , cmp , sbc , subd , and , bit , ld , st , +eor , adc , or , add , cmpx , jsr , ldx , stx , +sub , cmp , sbc , addd , and , bit , ld , st , +eor , adc , or , add , ldd , std , ldu , stu , +sub , cmp , sbc , addd , and , bit , ld , st , +eor , adc , or , add , ldd , std , ldu , stu , +sub , cmp , sbc , addd , and , bit , ld , st , +eor , adc , or , add , ldd , std , ldu , stu , +sub , cmp , sbc , addd , and , bit , ld , st , +eor , adc , or , add , ldd , std , ldu , stu , +}; + +void +read_image(char* name) +{ + FILE *image; + if((image=fopen(name,"rb"))!=NULL) { + fread(mem+0x100,0xff00,1,image); + fclose(image); + } +} + +void +dump() +{ + FILE *image; + if((image=fopen("dump.v09","wb"))!=NULL) { + fwrite(mem,0x10000,1,image); + fclose(image); + } +} + +/* E F H I N Z V C */ + +char *to_bin(Byte b) +{ + static char binstr[9]; + Byte bm; + char *ccbit="EFHINZVC"; + int i; + + for(bm=0x80, i=0; bm>0; bm >>=1, i++) + binstr[i] = (b & bm) ? toupper(ccbit[i]) : tolower(ccbit[i]); + binstr[8] = 0; + return binstr; +} + + +void cr() { + #ifdef TERM_CONTROL + fprintf(stderr,"%s","\r\n"); /* CR+LF because raw terminal ... */ + #else + fprintf(stderr,"%s","\n"); + #endif +} + +#ifdef TRACE + +/* max. bytes of instruction code per trace line */ +#define I_MAX 4 + +void trace() +{ + int ilen; + int i; + + if ( + 1 || ( /* no trace filtering ... */ + !(ureg > 0x09c0 && ureg < 0x09f3) && ( /* CMOVE ausblenden! */ + pcreg_prev == 0x01de || /* DOLST */ + pcreg_prev == 0x037a || /* FDOVAR */ + /* + ureg >= 0x0300 && ureg < 0x03f0 || + ureg >=0x1900 || + ureg > 0x118b && ureg < 0x11b2 || + pcreg_prev >= 0x01de && pcreg_prev < 0x0300 || + xreg >=0x8000 || + pcreg_prev >= 0x01de && pcreg_prev < 0x0300 || + */ + 0 + )) + ) + { + fprintf(stderr,"%04x ",pcreg_prev); + if (da_len) ilen = da_len; + else { + ilen = pcreg-pcreg_prev; if (ilen < 0) ilen= -ilen; + } + for(i=0; i < I_MAX; i++) { + if (i < ilen) fprintf(stderr,"%02x",mem[(pcreg_prev+i)&0xffff]); + else fprintf(stderr," "); + } + fprintf(stderr," %-5s %-17s [%02d] ", dinst, dops, cycles); + //if((ireg&0xfe)==0x10) + // fprintf(stderr,"%02x ",mem[pcreg]);else fprintf(stderr," "); + fprintf(stderr,"x=%04x y=%04x u=%04x s=%04x a=%02x b=%02x cc=%s", + xreg,yreg,ureg,sreg,*areg,*breg,to_bin(ccreg)); + fprintf(stderr,", s: %04x %04x, r: %04x", + mem[sreg]<<8|mem[sreg+1], + mem[sreg+2]<<8|mem[sreg+3], + mem[yreg]<<8|mem[yreg+1] + ); + cr(); + } + da_len = 0; +} + +#endif + + +static char optstring[]="d"; + +int +main(int argc,char *argv[]) +{ + char c; + int a; + + /* initialize memory with pseudo random data ... */ + srandom(time(NULL)); + for(a=0x0100; a<0x10000;a++) { + mem[(Word)a] = (Byte) (random() & 0xff); + } + + while( (c=getopt(argc, argv, optstring)) >=0 ) { + switch(c) { + case 'd': + fdump = 1; + break; + default: + fprintf(stderr,"ERROR: Unknown option\n"); + exit(2); + } + } + + if (optind < argc) { + read_image(argv[optind]); + } + else { + fprintf(stderr,"ERROR: Missing image name\n"); + exit(2); + } + + pcreg=0x100; + sreg=0; + dpreg=0; + iflag=0; + /* raw disables SIGINT, brkint reenables it ... + */ +#if defined(TERM_CONTROL) && ! defined(TRACE) + /* raw, but still allow key signaling, especial if ^C is desired + - if not, remove brkint and isig! + */ + system("stty -echo nl raw brkint isig"); + tflags=fcntl(0,F_GETFL,0); + fcntl(0,F_SETFL,tflags|O_NDELAY); +#endif + +#ifdef TRACE + da_len = 0; +#endif + cycles_sum = 0; + pcreg_prev = pcreg; + + for(;;){ + + ireg=mem[pcreg++]; + cycles=0; + (*instrtable[ireg])(); /* process instruction */ + cycles_sum += cycles; + +#ifdef TRACE + trace(); +#endif + + pcreg_prev = pcreg; + + } /* for */ + return 0; +} + + + +void finish() +{ + cr(); + fprintf(stderr,"Cycles: %lu", cycles_sum); + cr(); +#if defined(TERM_CONTROL) && ! defined(TRACE) + system("stty -raw -nl echo brkint"); + fcntl(0,F_SETFL,tflags&~O_NDELAY); +#endif + if (fdump) dump(); + exit(0); +} diff -r 000000000000 -r 9a224bd9b45f v09st.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/v09st.c Mon Jul 02 02:12:31 2018 +0900 @@ -0,0 +1,1085 @@ +/* 6809 Simulator V09, + By L.C. Benschop, Eidnhoven The Netherlands. + This program is in the public domain. + + *** TURBO C VERSION **** + + This program simulates a 6809 processor. + + System dependencies: short must be 16 bits. + char must be 8 bits. + long must be more than 16 bits. + arrays up to 65536 bytes must be supported. + machine must be twos complement. + Most Unix machines will work. For MSODS you need long pointers + and you may have to malloc() the mem array of 65536 bytes. + + Define BIG_ENDIAN if you have a big-endian machine (680x0 etc) + + Define TRACE if you want an instruction trace on stderr. + Define TERM_CONTROL for raw, nonblocking IO. + + Special instructions: + SWI2 writes char to stdout from register B. + SWI3 reads char from stdout to register B, sets carry at EOF. + (or when no key available when using TERM Control). + SWI retains its normal function. + CWAI and SYNC stop simulator. + + The program reads a binary image file at $100 and runs it from there. + The file name must be given on the command line. +*/ + +#include +#include +#ifdef TERM_CONTROL +#include +#endif + +typedef unsigned char Byte; +typedef unsigned short Word; + +/* 6809 registers */ +Byte ccreg,dpreg; +Word xreg,yreg,ureg,sreg,ureg,pcreg; + +Byte d_reg[2]; +Word *dreg=(Word *)d_reg; +#ifdef BIG_ENDIAN /* This is a dirty aliasing trick, but fast! */ + Byte *areg=d_reg; + Byte *breg=d_reg+1; +#else + Byte *breg=d_reg; + Byte *areg=d_reg+1; +#endif + +/* 6809 memory space */ +Byte *mem; + +#define GETWORD(a) (mem[a]<<8|mem[(a)+1]) +#define SETWORD(a,n) {mem[a]=(n)>>8;mem[(a)+1]=n;} +/* Two bytes of a word are fetched separately because of + the possible wrap-around at address $ffff and alignment +*/ + + +int iflag; /* flag to indicate prebyte $10 or $11 */ +Byte ireg; /* Instruction register */ + +#define IMMBYTE(b) b=mem[pcreg++]; +#define IMMWORD(w) {w=GETWORD(pcreg);pcreg+=2;} + +#define PUSHBYTE(b) mem[--sreg]=b; +#define PUSHWORD(w) {sreg-=2;SETWORD(sreg,w)} +#define PULLBYTE(b) b=mem[sreg++]; +#define PULLWORD(w) {w=GETWORD(sreg);sreg+=2;} + +#define SIGNED(b) ((Word)(b&0x80?b|0xff00:b)) + +Word *ixregs[]={&xreg,&yreg,&ureg,&sreg}; + +int index; + +/* Now follow the posbyte addressing modes. */ + +Word illaddr() /* illegal addressing mode, defaults to zero */ +{ + return 0; +} + +Word ainc() +{ + return (*ixregs[index])++; +} + +Word ainc2() +{ + Word temp; + temp=(*ixregs[index]); + (*ixregs[index])+=2; + return(temp); +} + +Word adec() +{ + return --(*ixregs[index]); +} + +Word adec2() +{ + Word temp; + (*ixregs[index])-=2; + temp=(*ixregs[index]); + return(temp); +} + +Word plus0() +{ + return(*ixregs[index]); +} + +Word plusa() +{ + return(*ixregs[index])+SIGNED(*areg); +} + +Word plusb() +{ + return(*ixregs[index])+SIGNED(*breg); +} + +Word plusn() +{ + Byte b; + IMMBYTE(b) + return(*ixregs[index])+SIGNED(b); +} + +Word plusnn() +{ + Word w; + IMMWORD(w) + return(*ixregs[index])+w; +} + +Word plusd() +{ + return(*ixregs[index])+*dreg; +} + + +Word npcr() +{ + Byte b; + IMMBYTE(b) + return pcreg+SIGNED(b); +} + +Word nnpcr() +{ + Word w; + IMMWORD(w) + return pcreg+w; +} + +Word direct() +{ + Word(w); + IMMWORD(w) + return w; +} + +Word zeropage() +{ + Byte b; + IMMBYTE(b) + return dpreg<<8|b; +} + + +Word immediate() +{ + return pcreg++; +} + +Word immediate2() +{ + Word temp; + temp=pcreg; + pcreg+=2; + return temp; +} + +Word (*pbtable[])()={ ainc, ainc2, adec, adec2, + plus0, plusb, plusa, illaddr, + plusn, plusnn, illaddr, plusd, + npcr, nnpcr, illaddr, direct, }; + +Word postbyte() +{ + Byte pb; + Word temp; + IMMBYTE(pb) + index=(pb & 0x60) >> 5; + if(pb & 0x80) { + temp=(*pbtable[pb & 0x0f])(); + if( pb & 0x10) temp=GETWORD(temp); + return temp; + } else { + temp=pb & 0x1f; + if(temp & 0x10) temp|=0xfff0; + return (*ixregs[index])+temp; + } +} + +Byte * eaddr0() /* effective address for NEG..JMP as byte poitner */ +{ + switch( (ireg & 0x70) >> 4) + { + case 0: return mem+zeropage(); + case 1:case 2:case 3: return 0; /*canthappen*/ + case 4: return areg; + case 5: return breg; + case 6: return mem+postbyte(); + case 7: return mem+direct(); + } +} + +Word eaddr8() /* effective address for 8-bits ops. */ +{ + switch( (ireg & 0x30) >> 4) + { + case 0: return immediate(); + case 1: return zeropage(); + case 2: return postbyte(); + case 3: return direct(); + } +} + +Word eaddr16() /* effective address for 16-bits ops. */ +{ + switch( (ireg & 0x30) >> 4) + { + case 0: return immediate2(); + case 1: return zeropage(); + case 2: return postbyte(); + case 3: return direct(); + } +} + +ill() /* illegal opcode==noop */ +{ +} + +/* macros to set status flags */ +#define SEC ccreg|=0x01; +#define CLC ccreg&=0xfe; +#define SEZ ccreg|=0x04; +#define CLZ ccreg&=0xfb; +#define SEN ccreg|=0x08; +#define CLN ccreg&=0xf7; +#define SEV ccreg|=0x02; +#define CLV ccreg&=0xfd; +#define SEH ccreg|=0x20; +#define CLH ccreg&=0xdf; + +/* set N and Z flags depending on 8 or 16 bit result */ +#define SETNZ8(b) {if(b)CLZ else SEZ if(b&0x80)SEN else CLN} +#define SETNZ16(b) {if(b)CLZ else SEZ if(b&0x8000)SEN else CLN} + +#define SETSTATUS(a,b,res) if((a^b^res)&0x10) SEH else CLH \ + if((a^b^res^(res>>1))&0x80)SEV else CLV \ + if(res&0x100)SEC else CLC SETNZ8((Byte)res) + +add() +{ + Word aop,bop,res; + Byte* aaop; + aaop=(ireg&0x40)?breg:areg; + aop=*aaop; + bop=mem[eaddr8()]; + res=aop+bop; + SETSTATUS(aop,bop,res) + *aaop=res; +} + +sbc() +{ + Word aop,bop,res; + Byte* aaop; + aaop=(ireg&0x40)?breg:areg; + aop=*aaop; + bop=mem[eaddr8()]; + res=aop-bop-(ccreg&0x01); + SETSTATUS(aop,bop,res) + *aaop=res; +} + +sub() +{ + Word aop,bop,res; + Byte* aaop; + aaop=(ireg&0x40)?breg:areg; + aop=*aaop; + bop=mem[eaddr8()]; + res=aop-bop; + SETSTATUS(aop,bop,res) + *aaop=res; +} + +adc() +{ + Word aop,bop,res; + Byte* aaop; + aaop=(ireg&0x40)?breg:areg; + aop=*aaop; + bop=mem[eaddr8()]; + res=aop+bop+(ccreg&0x01); + SETSTATUS(aop,bop,res) + *aaop=res; +} + +cmp() +{ + Word aop,bop,res; + Byte* aaop; + aaop=(ireg&0x40)?breg:areg; + aop=*aaop; + bop=mem[eaddr8()]; + res=aop-bop; + SETSTATUS(aop,bop,res) +} + +and() +{ + Byte aop,bop,res; + Byte* aaop; + aaop=(ireg&0x40)?breg:areg; + aop=*aaop; + bop=mem[eaddr8()]; + res=aop&bop; + SETNZ8(res) + CLV + *aaop=res; +} + +or() +{ + Byte aop,bop,res; + Byte* aaop; + aaop=(ireg&0x40)?breg:areg; + aop=*aaop; + bop=mem[eaddr8()]; + res=aop|bop; + SETNZ8(res) + CLV + *aaop=res; +} + +eor() +{ + Byte aop,bop,res; + Byte* aaop; + aaop=(ireg&0x40)?breg:areg; + aop=*aaop; + bop=mem[eaddr8()]; + res=aop^bop; + SETNZ8(res) + CLV + *aaop=res; +} + +bit() +{ + Byte aop,bop,res; + Byte* aaop; + aaop=(ireg&0x40)?breg:areg; + aop=*aaop; + bop=mem[eaddr8()]; + res=aop&bop; + SETNZ8(res) + CLV +} + +ld() +{ + Byte res; + Byte* aaop; + aaop=(ireg&0x40)?breg:areg; + res=mem[eaddr8()]; + SETNZ8(res) + CLV + *aaop=res; +} + +st() +{ + Byte res; + Byte* aaop; + aaop=(ireg&0x40)?breg:areg; + res=*aaop; + mem[eaddr8()]=res; + SETNZ8(res) + CLV +} + +jsr() +{ + Word w; + w=eaddr8(); + PUSHWORD(pcreg) + pcreg=w; +} + +bsr() +{ + Byte b; + IMMBYTE(b) + PUSHWORD(pcreg) + pcreg+=SIGNED(b); +} + +neg() +{ + Byte *ea; + Word a,r; + a=0; + ea=eaddr0(); + a=*ea; + r=-a; + SETSTATUS(0,a,r) + *ea=r; +} + +com() +{ + Byte *ea; + Byte r; + ea=eaddr0(); + r=0^*ea; + SETNZ8(r) + SEC CLV + *ea=r; +} + +lsr() +{ + Byte *ea; + Byte r; + ea=eaddr0(); + r=*ea; + if(r&0x01)SEC else CLC + r>>=1; + SETNZ8(r) + *ea=r; +} + +ror() +{ + Byte *ea; + Byte r,c; + c=(ccreg&0x01)<<7; + ea=eaddr0(); + r=*ea; + if(r&0x01)SEC else CLC + r=(r>>1)+c; + SETNZ8(r) + *ea=r; +} + +asr() +{ + Byte *ea; + Byte r; + ea=eaddr0(); + r=*ea; + if(r&0x01)SEC else CLC + r>>=1; + if(r&0x40)r|=0x80; + SETNZ8(r) + *ea=r; +} + +asl() +{ + Byte *ea; + Word a,r; + ea=eaddr0(); + a=*ea; + r=a<<1; + SETSTATUS(a,a,r) + *ea=r; +} + +rol() +{ + Byte *ea; + Byte r,c; + c=(ccreg&0x01); + ea=eaddr0(); + r=*ea; + if(r&0x80)SEC else CLC + r=(r<<1)+c; + SETNZ8(r) + *ea=r; +} + +inc() +{ + Byte *ea; + Byte r; + ea=eaddr0(); + r=*ea; + r++; + if(r==0x80)SEV else CLV + SETNZ8(r) + *ea=r; +} + +dec() +{ + Byte *ea; + Byte r; + ea=eaddr0(); + r=*ea; + r--; + if(r==0x7f)SEV else CLV + SETNZ8(r) + *ea=r; +} + +tst() +{ + Byte r; + r=*eaddr0(); + SETNZ8(r) + CLV +} + +jmp() +{ + Byte *ea; + ea=eaddr0(); + pcreg=ea-mem; +} + +clr() +{ + Byte *ea; + ea=eaddr0(); + *ea=0;CLN CLV SEZ CLC +} + +extern (*instrtable[])(); + +flag0() +{ + if(iflag) /* in case flag already set by previous flag instr don't recurse */ + { + pcreg--; + return; + } + iflag=1; + ireg=mem[pcreg++]; + (*instrtable[ireg])(); + iflag=0; +} + +flag1() +{ + if(iflag) /* in case flag already set by previous flag instr don't recurse */ + { + pcreg--; + return; + } + iflag=2; + ireg=mem[pcreg++]; + (*instrtable[ireg])(); + iflag=0; +} + +nop() +{ +} + +sync() +{ + exit(0); +} + +cwai() +{ + sync(); +} + +lbra() +{ + Word w; + IMMWORD(w) + pcreg+=w; +} + +lbsr() +{ + Word w; + IMMWORD(w) + PUSHWORD(pcreg) + pcreg+=w; +} + +daa() +{ + Word a; + a=*areg; + if(ccreg&0x20)a+=6; + if((a&0x0f)>9)a+=6; + if(ccreg&0x01)a+=0x60; + if((a&0xf0)>0x90)a+=0x60; + if(a&0x100)SEC else CLC + *areg=a; +} + +orcc() +{ + Byte b; + IMMBYTE(b) + ccreg|=b; +} + +andcc() +{ + Byte b; + IMMBYTE(b) + ccreg&=b; +} + +mul() +{ + Word w; + w=*areg * *breg; + if(w)CLZ else SEZ + if(w&0xff00) SEC else CLC + *dreg=w; +} + +sex() +{ + Word w; + w=SIGNED(*breg); + SETNZ16(w) + *dreg=w; +} + +abx() +{ + xreg += *breg; +} + +rts() +{ + PULLWORD(pcreg) +} + +rti() +{ + Byte x; + x=ccreg&0x80; + PULLBYTE(ccreg) + if(x) + { + PULLBYTE(*areg) + PULLBYTE(*breg) + PULLBYTE(dpreg) + PULLWORD(xreg) + PULLWORD(yreg) + PULLWORD(ureg) + } + PULLWORD(pcreg) +} + +swi() +{ + int w; + switch(iflag) + { + case 0: + PUSHWORD(pcreg) + PUSHWORD(ureg) + PUSHWORD(yreg) + PUSHWORD(xreg) + PUSHBYTE(dpreg) + PUSHBYTE(*breg) + PUSHBYTE(*areg) + PUSHBYTE(ccreg) + ccreg|=0xd0; + pcreg=GETWORD(0xfffa); + break; + case 1: + putchar(*breg); + fflush(stdout); + break; + case 2: +#ifndef TERM_CONTROL + w=getchar(); + if(w==EOF)SEC else CLC +#else + if(kbhit()) { + w=getch(); + CLC + } else { + w=255; + SEC + } +#endif + *breg=w; + } +} + +Word *wordregs[]={(Word*)d_reg,&xreg,&yreg,&ureg,&sreg,&pcreg,&sreg,&pcreg}; +#ifdef BIG_ENDIAN +Byte *byteregs[]={d_reg,d_reg+1,&ccreg,&dpreg}; +#else +Byte *byteregs[]={d_reg+1,d_reg,&ccreg,&dpreg}; +#endif + +tfr() +{ + Byte b; + IMMBYTE(b) + if(b&0x80) { + *byteregs[b&0x03]=*byteregs[(b&0x30)>>4]; + } else { + *wordregs[b&0x07]=*wordregs[(b&0x70)>>4]; + } +} + +exg() +{ + Byte b; + Word w; + IMMBYTE(b) + if(b&0x80) { + w=*byteregs[b&0x03]; + *byteregs[b&0x03]=*byteregs[(b&0x30)>>4]; + *byteregs[(b&0x30)>>4]=w; + } else { + w=*wordregs[b&0x07]; + *wordregs[b&0x07]=*wordregs[(b&0x70)>>4]; + *wordregs[(b&0x70)>>4]=w; + } +} + +br(int f) +{ + Byte b; + Word w; + if(!iflag) { + IMMBYTE(b) + if(f) pcreg+=SIGNED(b); + } else { + IMMWORD(w) + if(f) pcreg+=w; + } +} + +#define NXORV ((ccreg&0x08)^(ccreg&0x02)) + +bra() +{ + br(1); +} + +brn() +{ + br(0); +} + +bhi() +{ + br(!(ccreg&0x05)); +} + +bls() +{ + br(ccreg&0x05); +} + +bcc() +{ + br(!(ccreg&0x01)); +} + +bcs() +{ + br(ccreg&0x01); +} + +bne() +{ + br(!(ccreg&0x04)); +} + +beq() +{ + br(ccreg&0x04); +} + +bvc() +{ + br(!(ccreg&0x02)); +} + +bvs() +{ + br(ccreg&0x02); +} + +bpl() +{ + br(!(ccreg&0x08)); +} + +bmi() +{ + br(ccreg&0x08); +} + +bge() +{ + br(!NXORV); +} + +blt() +{ + br(NXORV); +} + +bgt() +{ + br(!(NXORV||ccreg&0x04)); +} + +ble() +{ + br(NXORV||ccreg&0x04); +} + +leax() +{ + Word w; + w=postbyte(); + if(w) CLZ else SEZ + xreg=w; +} + +leay() +{ + Word w; + w=postbyte(); + if(w) CLZ else SEZ + yreg=w; +} + +leau() +{ + ureg=postbyte(); +} + +leas() +{ + sreg=postbyte(); +} + +#define SWAPUS {temp=sreg;sreg=ureg;ureg=temp;} + +pshs() +{ + Byte b; + IMMBYTE(b) + if(b&0x80)PUSHWORD(pcreg) + if(b&0x40)PUSHWORD(ureg) + if(b&0x20)PUSHWORD(yreg) + if(b&0x10)PUSHWORD(xreg) + if(b&0x08)PUSHBYTE(dpreg) + if(b&0x04)PUSHBYTE(*breg) + if(b&0x02)PUSHBYTE(*areg) + if(b&0x01)PUSHBYTE(ccreg) +} + +puls() +{ + Byte b; + IMMBYTE(b) + if(b&0x01)PULLBYTE(ccreg) + if(b&0x02)PULLBYTE(*areg) + if(b&0x04)PULLBYTE(*breg) + if(b&0x08)PULLBYTE(dpreg) + if(b&0x10)PULLWORD(xreg) + if(b&0x20)PULLWORD(yreg) + if(b&0x40)PULLWORD(ureg) + if(b&0x80)PULLWORD(pcreg) +} + +pshu() +{ + Word temp; + SWAPUS + pshs(); + SWAPUS +} + +pulu() +{ + Word temp; + SWAPUS + puls(); + SWAPUS +} + +#define SETSTATUSD(a,b,res) {if((res&0x10000l)!=0) SEC else CLC \ + if((((res>>1)^a^b^res)&0x8000l)!=0) SEV else CLV \ + SETNZ16((Word)res)} + +addd() +{ + unsigned long aop,bop,res; + Word ea; + aop=*dreg&0xffff; + ea=eaddr16(); + bop=GETWORD(ea)&0xffff; + res=aop+bop; + SETSTATUSD(aop,bop,res) + *dreg=res; +} + +subd() +{ + unsigned long aop,bop,res; + Word ea; + if(iflag==2)aop=ureg; else aop=*dreg; + aop&=0xffff; + ea=eaddr16(); + bop=GETWORD(ea)&0xffff; + res=aop-bop; + SETSTATUSD(aop,bop,res) + if(iflag==0) *dreg=res; +} + +cmpx() +{ + unsigned long aop,bop,res; + Word ea; + switch(iflag) { + case 0: aop=xreg;break; + case 1: aop=yreg;break; + case 2: aop=sreg; + } + aop&=0xffff; + ea=eaddr16(); + bop=GETWORD(ea)&0xffff; + res=aop-bop; + SETSTATUSD(aop,bop,res) +} + +ldd() +{ + Word ea,w; + ea=eaddr16(); + w=GETWORD(ea); + SETNZ16(w) + *dreg=w; +} + +ldx() +{ + Word ea,w; + ea=eaddr16(); + w=GETWORD(ea); + SETNZ16(w) + if (iflag==0) xreg=w; else yreg=w; +} + +ldu() +{ + Word ea,w; + ea=eaddr16(); + w=GETWORD(ea); + SETNZ16(w) + if (iflag==0) ureg=w; else sreg=w; +} + +std() +{ + Word ea,w; + ea=eaddr16(); + w=*dreg; + SETNZ16(w) + SETWORD(ea,w) +} + +stx() +{ + Word ea,w; + ea=eaddr16(); + if (iflag==0) w=xreg; else w=yreg; + SETNZ16(w) + SETWORD(ea,w) +} + +stu() +{ + Word ea,w; + ea=eaddr16(); + if (iflag==0) w=ureg; else w=sreg; + SETNZ16(w) + SETWORD(ea,w) +} + +int (*instrtable[])() = { + neg , ill , ill , com , lsr , ill , ror , asr , + asl , rol , dec , ill , inc , tst , jmp , clr , + flag0 , flag1 , nop , sync , ill , ill , lbra , lbsr , + ill , daa , orcc , ill , andcc , sex , exg , tfr , + bra , brn , bhi , bls , bcc , bcs , bne , beq , + bvc , bvs , bpl , bmi , bge , blt , bgt , ble , + leax , leay , leas , leau , pshs , puls , pshu , pulu , + ill , rts , abx , rti , cwai , mul , ill , swi , + neg , ill , ill , com , lsr , ill , ror , asr , + asl , rol , dec , ill , inc , tst , ill , clr , + neg , ill , ill , com , lsr , ill , ror , asr , + asl , rol , dec , ill , inc , tst , ill , clr , + neg , ill , ill , com , lsr , ill , ror , asr , + asl , rol , dec , ill , inc , tst , jmp , clr , + neg , ill , ill , com , lsr , ill , ror , asr , + asl , rol , dec , ill , inc , tst , jmp , clr , +sub , cmp , sbc , subd , and , bit , ld , st , +eor , adc , or , add , cmpx , bsr , ldx , stx , +sub , cmp , sbc , subd , and , bit , ld , st , +eor , adc , or , add , cmpx , jsr , ldx , stx , +sub , cmp , sbc , subd , and , bit , ld , st , +eor , adc , or , add , cmpx , jsr , ldx , stx , +sub , cmp , sbc , subd , and , bit , ld , st , +eor , adc , or , add , cmpx , jsr , ldx , stx , +sub , cmp , sbc , addd , and , bit , ld , st , +eor , adc , or , add , ldd , std , ldu , stu , +sub , cmp , sbc , addd , and , bit , ld , st , +eor , adc , or , add , ldd , std , ldu , stu , +sub , cmp , sbc , addd , and , bit , ld , st , +eor , adc , or , add , ldd , std , ldu , stu , +sub , cmp , sbc , addd , and , bit , ld , st , +eor , adc , or , add , ldd , std , ldu , stu , +}; + +read_image(char* name) +{ + FILE *image; + if((image=fopen(name,"rb"))!=NULL) { + fread(mem+0x100,0xff00,1,image); + fclose(image); + } +} + +main(int argc,char *argv[]) +{ + mem=farmalloc(65536); + read_image(argv[1]); + pcreg=0x100; + sreg=0; + dpreg=0; + iflag=0; + for(;;){ + #ifdef TRACE + fprintf(stderr,"pc=%04x ",pcreg); + #endif + ireg=mem[pcreg++]; + #ifdef TRACE + fprintf(stderr,"i=%02x ",ireg); + if((ireg&0xfe)==0x10) + fprintf(stderr,"%02x ",mem[pcreg]);else fprintf(stderr," "); + fprintf(stderr,"x=%04x y=%04x u=%04x s=%04x a=%02x b=%02x cc=%02x\n", + xreg,yreg,ureg,sreg,*areg,*breg,ccreg); + #endif + (*instrtable[ireg])(); + } +} +