page@swan.ulowell.edu (Bob Page) (03/16/89)
Submitted-by: gmg@hcx.uucp (Greg Garner) Posting-number: Volume 89, Issue 55 Archive-name: langauges/moto-assem.1 These files came from the Motorola Freeware BBS. Their BBS now has an amiga upload/download section (YEA!). I obtained explicit permission to post these to comp.sources.amiga and also to give these files to Fred Dish for inclusion in one of his disks. # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # AS.C # AS.H # AS0.C # AS1.C # AS11.C # AS4.C # AS5.C # AS9.C # DO0.C # DO1.C # DO11.C # DO4.C # DO5.C # DO9.C # FFWD.C # OUTPUT.C # PSEUDO.C # This archive created: Wed Mar 15 13:33:52 1989 cat << \SHAR_EOF > AS.C char mapdn(); char *alloc(); /* * as --- cross assembler main program */ main(argc,argv) int argc; char **argv; { char **np; char *i; FILE *fopen(); int j = 0; if(argc < 2){ printf("Usage: %s [files]\n",argv[j]); exit(1); } Argv = argv; initialize(); while ((*argv[j] != '-') && (j<argc)) j++; N_files = j-1; if (j < argc ) { argv[j]++; while (j<argc) { for (i = argv[j]; *i != 0; i++) if ((*i <= 'Z') && (*i >= 'A')) *i = *i + 32; if (strcmp(argv[j],"l")==0) Lflag = 1; else if (strcmp(argv[j],"nol")==0) Lflag = 0; else if (strcmp(argv[j],"c")==0) Cflag = 1; else if (strcmp(argv[j],"noc")==0) Cflag = 0; else if (strcmp(argv[j],"s")==0) Sflag = 1; else if (strcmp(argv[j],"cre")==0) CREflag = 1; j++; } } root = NULL; Cfn = 0; np = argv; Line_num = 0; /* reset line number */ while( ++Cfn <= N_files ) if((Fd = fopen(*++np,"r")) == NULL) printf("as: can't open %s\n",*np); else{ make_pass(); fclose(Fd); } if( Err_count == 0 ){ Pass++; re_init(); Cfn = 0; np = argv; Line_num = 0; while( ++Cfn <= N_files) if((Fd = fopen(*++np,"r")) != NULL) { make_pass(); fclose(Fd); } if (Sflag == 1) { printf ("\f"); stable (root); } if (CREflag == 1) { printf ("\f"); cross (root); } fprintf(Objfil,"S9030000FC\r\n"); /* at least give a decent ending */ } exit(Err_count); } initialize() { FILE *fopen(); int i = 0; #ifdef DEBUG printf("Initializing\n"); #endif Err_count = 0; Pc = 0; Pass = 1; Lflag = 0; Cflag = 0; Ctotal = 0; Sflag = 0; CREflag = 0; N_page = 0; Line[MAXBUF-1] = NEWLINE; strcpy(Obj_name,Argv[1]); /* copy first file name into array */ do { if (Obj_name[i]=='.') Obj_name[i]=0; } while (Obj_name[i++] != 0); strcat(Obj_name,".s19"); /* append .out to file name. */ if( (Objfil = fopen(Obj_name,"w")) == NULL) fatal("Can't create object file"); fwdinit(); /* forward ref init */ localinit(); /* target machine specific init. */ } re_init() { #ifdef DEBUG printf("Reinitializing\n"); #endif Pc = 0; E_total = 0; P_total = 0; Ctotal = 0; N_page = 0; fwdreinit(); } make_pass() { char *fgets(); #ifdef DEBUG printf("Pass %d\n",Pass); #endif while( fgets(Line,MAXBUF-1,Fd) != (char *)NULL ){ Line_num++; P_force = 0; /* No force unless bytes emitted */ N_page = 0; if(parse_line()) process(); if(Pass == 2 && Lflag && !N_page) print_line(); P_total = 0; /* reset byte count */ Cycles = 0; /* and per instruction cycle count */ } f_record(); } /* * parse_line --- split input line into label, op and operand */ parse_line() { register char *ptrfrm = Line; register char *ptrto = Label; char *skip_white(); if( *ptrfrm == '*' || *ptrfrm == '\n' ) return(0); /* a comment line */ while( delim(*ptrfrm)== NO ) *ptrto++ = *ptrfrm++; if(*--ptrto != ':')ptrto++; /* allow trailing : */ *ptrto = EOS; ptrfrm = skip_white(ptrfrm); ptrto = Op; while( delim(*ptrfrm) == NO) *ptrto++ = mapdn(*ptrfrm++); *ptrto = EOS; ptrfrm = skip_white(ptrfrm); ptrto = Operand; while( *ptrfrm != NEWLINE ) *ptrto++ = *ptrfrm++; *ptrto = EOS; #ifdef DEBUG printf("Label-%s-\n",Label); printf("Op----%s-\n",Op); printf("Operand-%s-\n",Operand); #endif return(1); } /* * process --- determine mnemonic class and act on it */ process() { register struct oper *i; struct oper *mne_look(); Old_pc = Pc; /* setup `old' program counter */ Optr = Operand; /* point to beginning of operand field */ if(*Op==EOS){ /* no mnemonic */ if(*Label != EOS) install(Label,Pc); } else if( (i = mne_look(Op))== NULL) error("Unrecognized Mnemonic"); else if( i->class == PSEUDO ) do_pseudo(i->opcode); else{ if( *Label )install(Label,Pc); if(Cflag)Cycles = i->cycles; do_op(i->opcode,i->class); if(Cflag)Ctotal += Cycles; } } SHAR_EOF cat << \SHAR_EOF > AS.H /* * machine independent definitions and global variables */ #define YES 1 #define NO 0 #define ERR (-1) #define MAXBUF 128 #define MAXOP 10 /* longest mnemonic */ #define MAXLAB 16 #define E_LIMIT 32 #define P_LIMIT 64 /* Character Constants */ #define NEWLINE '\n' #define TAB '\t' #define BLANK ' ' #define EOS '\0' /* Opcode Classes */ #define INH 0 /* Inherent */ #define GEN 1 /* General Addressing */ #define IMM 2 /* Immediate only */ #define REL 3 /* Short Relative */ #define P2REL 4 /* Long Relative */ #define P1REL 5 /* Long Relative (LBRA and LBSR)*/ #define NOIMM 6 /* General except for Immediate */ #define P2GEN 7 /* Page 2 General */ #define P3GEN 8 /* Page 3 General */ #define RTOR 9 /* Register To Register */ #define INDEXED 10 /* Indexed only */ #define RLIST 11 /* Register List */ #define P2NOIMM 12 /* Page 2 No Immediate */ #define P2INH 13 /* Page 2 Inherent */ #define P3INH 14 /* Page 3 Inherent */ #define GRP2 15 /* Group 2 (Read/Modify/Write) */ #define LONGIMM 16 /* Immediate mode takes 2 bytes */ #define BTB 17 /* Bit test and branch */ #define SETCLR 18 /* Bit set or clear */ #define CPD 19 /* compare d 6811 */ #define XLIMM 20 /* LONGIMM for X 6811 */ #define XNOIMM 21 /* NOIMM for X 6811 */ #define YLIMM 22 /* LONGIMM for Y 6811 */ #define YNOIMM 23 /* NOIMM for Y 6811 */ #define FAKE 24 /* convenience mnemonics 6804 */ #define APOST 25 /* A accum after opcode 6804 */ #define BPM 26 /* branch reg plus/minus 6804 */ #define CLRX 27 /* mvi x,0 6804 */ #define CLRY 28 /* mvi y,0 6804 */ #define LDX 29 /* mvi x,expr 6804 */ #define LDY 30 /* mvi y,expr 6804 */ #define MVI 31 /* mvi 6804 */ #define EXT 32 /* extended 6804 */ #define BIT 33 /* bit manipulation 6301 */ #define SYS 34 /* syscalls (really swi) */ #define PSEUDO 35 /* Pseudo ops */ /* global variables */ int Line_num =0; /* current line number */ int Err_count =0; /* total number of errors */ char Line[MAXBUF] = {0}; /* input line buffer */ char Label[MAXLAB] = {0}; /* label on current line */ char Op[MAXOP] = {0}; /* opcode mnemonic on current line */ char Operand[MAXBUF] = {0}; /* remainder of line after op */ char *Optr =0; /* pointer into current Operand field */ int Result =0; /* result of expression evaluation */ int Force_word =0; /* Result should be a word when set */ int Force_byte =0; /* Result should be a byte when set */ int Pc =0; /* Program Counter */ int Old_pc =0; /* Program Counter at beginning */ int Last_sym =0; /* result of last lookup */ int Pass =0; /* Current pass # */ int N_files =0; /* Number of files to assemble */ FILE *Fd =0; /* Current input file structure */ int Cfn =0; /* Current file number 1...n */ int Ffn =0; /* forward ref file # */ int F_ref =0; /* next line with forward ref */ char **Argv =0; /* pointer to file names */ int E_total =0; /* total # bytes for one line */ int E_bytes[E_LIMIT] = {0}; /* Emitted held bytes */ int E_pc =0; /* Pc at beginning of collection*/ int Lflag = 0; /* listing flag 0=nolist, 1=list*/ int P_force = 0; /* force listing line to include Old_pc */ int P_total =0; /* current number of bytes collected */ int P_bytes[P_LIMIT] = {0}; /* Bytes collected for listing */ int Cflag = 0; /* cycle count flag */ int Cycles = 0; /* # of cycles per instruction */ long Ctotal = 0; /* # of cycles seen so far */ int Sflag = 0; /* symbol table flag, 0=no symbol */ int N_page = 0; /* new page flag */ int Page_num = 2; /* page number */ int CREflag = 0; /* cross reference table flag */ struct link { /* linked list to hold line numbers */ int L_num; /* line number */ struct link *next; /* pointer to next node */ }; struct nlist { /* basic symbol table entry */ char *name; int def; struct nlist *Lnext ; /* left node of the tree leaf */ struct nlist *Rnext; /* right node of the tree leaf */ struct link *L_list; /* pointer to linked list of line numbers */ }; struct oper { /* an entry in the mnemonic table */ char *mnemonic; /* its name */ char class; /* its class */ int opcode; /* its base opcode */ char cycles; /* its base # of cycles */ }; struct nlist *root; /* root node of the tree */ FILE *Objfil =0; /* object file's file descriptor*/ char Obj_name[] = {" "}; SHAR_EOF cat << \SHAR_EOF > AS0.C #include <stdio.h> #include "as.h" #include "table0.h" #include "as.c" #include "do0.c" #include "pseudo.c" #include "eval.c" #include "symtab.c" #include "util.c" #include "ffwd.c" #include "output.c" SHAR_EOF cat << \SHAR_EOF > AS1.C #include <stdio.h> #include "as.h" #include "table1.h" #include "as.c" #include "do1.c" #include "pseudo.c" #include "eval.c" #include "symtab.c" #include "util.c" #include "ffwd.c" #include "output.c" SHAR_EOF cat << \SHAR_EOF > AS11.C #include <stdio.h> #include "as.h" #include "table11.h" #include "as.c" #include "do11.c" #include "pseudo.c" #include "eval.c" #include "symtab.c" #include "util.c" #include "ffwd.c" #include "output.c" SHAR_EOF cat << \SHAR_EOF > AS4.C #include <stdio.h> #include "as.h" #include "table4.h" #include "as.c" #include "do4.c" #include "pseudo.c" #include "eval.c" #include "symtab.c" #include "util.c" #include "ffwd.c" #include "output.c" SHAR_EOF cat << \SHAR_EOF > AS5.C #include <stdio.h> #include "as.h" #include "table5.h" #include "as.c" #include "do5.c" #include "pseudo.c" #include "eval.c" #include "symtab.c" #include "util.c" #include "ffwd.c" #include "output.c" SHAR_EOF cat << \SHAR_EOF > AS9.C #include <stdio.h> #include "as.h" #include "table9.h" #include "as.c" #include "do9.c" #include "pseudo.c" #include "eval.c" #include "symtab.c" #include "util.c" #include "ffwd.c" #include "output.c" SHAR_EOF cat << \SHAR_EOF > DO0.C /* * MC6800/02 specific processing */ /* addressing modes */ #define IMMED 0 /* immediate */ #define IND 1 /* indexed */ #define OTHER 2 /* NOTA */ /* * localinit --- machine specific initialization */ localinit() { } /* * do_op --- process mnemonic * * Called with the base opcode and it's class. Optr points to * the beginning of the operand field. */ do_op(opcode,class) int opcode; /* base opcode */ int class; /* mnemonic class */ { int dist; /* relative branch distance */ int amode; /* indicated addressing mode */ char *peek; /* guess at addressing mode */ peek = Optr; amode = OTHER; while( !delim(*peek) && *peek != EOS) /* check for comma in operand field */ if( *peek++ == ',' ){ amode = IND; break; } if( *Optr == '#' ) amode = IMMED; switch(class){ case INH: /* inherent addressing */ emit(opcode); return; case GEN: /* general addressing */ do_gen(opcode,amode); return; case REL: /* relative branches */ eval(); dist = Result - (Pc+2); emit(opcode); if( (dist >127 || dist <-128) && Pass==2){ error("Branch out of Range"); emit(lobyte(-2)); return; } emit(lobyte(dist)); return; case NOIMM: if( amode == IMMED){ error("Immediate Addressing Illegal"); return; } if((opcode == 0x8D) && (amode == IND)){ Cycles-=2; } do_gen(opcode,amode); return; case LONGIMM: if( amode == IMMED ){ emit(opcode); Optr++; eval(); eword(Result); return; } do_gen(opcode,amode); return; case GRP2: if( amode == IND ){ Cycles++; do_indexed(opcode); return; } /* extended addressing */ eval(); emit(opcode+0x10); eword(Result); return; default: fatal("Error in Mnemonic table"); } } /* * do_gen --- process general addressing modes */ do_gen(op,mode) int op; int mode; { if( mode == IMMED){ Optr++; emit(op); eval(); emit(lobyte(Result)); return; } else if( mode == IND ){ Cycles+=3; do_indexed(op+0x20); return; } else if( mode == OTHER){ eval(); if(Force_word){ emit(op+0x30); eword(Result); Cycles+=2; return; } if(Force_byte){ emit(op+0x10); emit(lobyte(Result)); Cycles++; return; } if(Result>=0 && Result <=0xFF){ emit(op+0x10); emit(lobyte(Result)); Cycles++; return; } else { emit(op+0x30); eword(Result); Cycles+=2; return; } } else { error("Unknown Addressing Mode"); return; } } /* * do_indexed --- handle all wierd stuff for indexed addressing */ do_indexed(op) int op; { emit(op); eval(); if( mapdn(*++Optr) != 'x' ) warn("Indexed Addressing Assumed"); if( Result < 0 || Result > 255) warn("Value Truncated"); emit(lobyte(Result)); } SHAR_EOF cat << \SHAR_EOF > DO1.C /* * MC6801 specific processing */ /* addressing modes */ #define IMMED 0 /* immediate */ #define IND 1 /* indexed */ #define OTHER 2 /* NOTA */ /* * localinit --- machine specific initialization */ localinit() { } /* * do_op --- process mnemonic * * Called with the base opcode and it's class. Optr points to * the beginning of the operand field. */ do_op(opcode,class) int opcode; /* base opcode */ int class; /* mnemonic class */ { int dist; /* relative branch distance */ int amode; /* indicated addressing mode */ char *peek; /* guess at addressing mode */ peek = Optr; amode = OTHER; while( !delim(*peek) && *peek != EOS) /* check for comma in operand field */ if( *peek++ == ',' ){ amode = IND; break; } if( *Optr == '#' ) amode = IMMED; switch(class){ case INH: /* inherent addressing */ emit(opcode); return; case GEN: /* general addressing */ do_gen(opcode,amode); return; case REL: /* relative branches */ eval(); dist = Result - (Pc+2); emit(opcode); if( (dist >127 || dist <-128) && Pass==2){ error("Branch out of Range"); emit(lobyte(-2)); return; } emit(lobyte(dist)); return; case NOIMM: if( amode == IMMED){ error("Immediate Addressing Illegal"); return; } do_gen(opcode,amode); return; case LONGIMM: if( amode == IMMED ){ emit(opcode); Optr++; eval(); eword(Result); return; } do_gen(opcode,amode); return; case GRP2: if( amode == IND ){ do_indexed(opcode); return; } /* extended addressing */ eval(); emit(opcode+0x10); eword(Result); return; default: fatal("Error in Mnemonic table"); } } /* * do_gen --- process general addressing modes */ do_gen(op,mode) int op; int mode; { if( mode == IMMED){ Optr++; emit(op); eval(); emit(lobyte(Result)); return; } else if( mode == IND ){ Cycles+=2; do_indexed(op+0x20); return; } else if( mode == OTHER){ eval(); if(Force_word){ emit(op+0x30); eword(Result); Cycles+=2; return; } if(Force_byte){ emit(op+0x10); emit(lobyte(Result)); Cycles++; return; } if(Result>=0 && Result <=0xFF){ emit(op+0x10); emit(lobyte(Result)); Cycles++; return; } else { emit(op+0x30); eword(Result); Cycles+=2; return; } } else { error("Unknown Addressing Mode"); return; } } /* * do_indexed --- handle all wierd stuff for indexed addressing */ do_indexed(op) int op; { emit(op); eval(); if( mapdn(*++Optr) != 'x' ) warn("Indexed Addressing Assumed"); if( Result < 0 || Result > 255) warn("Value Truncated"); emit(lobyte(Result)); } SHAR_EOF cat << \SHAR_EOF > DO11.C /* * MC68HC11 specific processing */ #define PAGE1 0x00 #define PAGE2 0x18 #define PAGE3 0x1A #define PAGE4 0xCD /* addressing modes */ #define IMMED 0 #define INDX 1 #define INDY 2 #define LIMMED 3 /* long immediate */ #define OTHER 4 int yflag = 0; /* YNOIMM, YLIMM, and CPD flag */ /* * localinit --- machine specific initialization */ localinit() { } /* * do_op --- process mnemonic * * Called with the base opcode and it's class. Optr points to * the beginning of the operand field. */ do_op(opcode,class) int opcode; /* base opcode */ int class; /* mnemonic class */ { int dist; /* relative branch distance */ int amode; /* indicated addressing mode */ char *peek; /* guess at addressing mode */ peek = Optr; amode = OTHER; while( !delim(*peek) && *peek != EOS) /* check for comma in operand field */ if( *peek++ == ',' ){ if( mapdn(*peek) == 'y' ) amode = INDY; else amode = INDX; break; } if( *Optr == '#' ) amode = IMMED; yflag = 0; switch(class){ case P2INH: emit(PAGE2); case INH: /* inherent addressing */ emit(opcode); return; case REL: /* relative branches */ eval(); dist = Result - (Pc+2); emit(opcode); if( (dist >127 || dist <-128) && Pass==2){ error("Branch out of Range"); emit(lobyte(-2)); return; } emit(lobyte(dist)); return; case LONGIMM: if( amode == IMMED ) amode = LIMMED; case NOIMM: if( amode == IMMED ){ error("Immediate Addressing Illegal"); return; } case GEN: /* general addressing */ do_gen(opcode,amode,PAGE1,PAGE1,PAGE2); return; case GRP2: if( amode == INDY ){ Cycles++; emit(PAGE2); amode = INDX; } if( amode == INDX ) do_indexed(opcode); else{ /* extended addressing */ eval(); emit(opcode+0x10); eword(Result); } return; case CPD: /* cmpd */ if( amode == IMMED ) amode = LIMMED; if( amode == INDY ) yflag=1; do_gen(opcode,amode,PAGE3,PAGE3,PAGE4); return; case XNOIMM: /* stx */ if( amode == IMMED ){ error("Immediate Addressing Illegal"); return; } case XLIMM: /* cpx, ldx */ if( amode == IMMED ) amode = LIMMED; do_gen(opcode,amode,PAGE1,PAGE1,PAGE4); return; case YNOIMM: /* sty */ if( amode == IMMED ){ error("Immediate Addressing Illegal"); return; } case YLIMM: /* cpy, ldy */ if(amode == INDY) yflag=1; if( amode == IMMED ) amode = LIMMED; do_gen(opcode,amode,PAGE2,PAGE3,PAGE2); return; case BTB: /* bset, bclr */ case SETCLR: /* brset, brclr */ opcode = bitop(opcode,amode,class); if (amode == INDX) Cycles++; if( amode == INDY ){ Cycles+=2; emit(PAGE2); amode = INDX; } emit(opcode); eval(); emit(lobyte(Result)); /* address */ if( amode == INDX ) Optr += 2; /* skip ,x or ,y */ Optr = skip_white(Optr); eval(); emit(lobyte(Result)); /* mask */ if( class == SETCLR ) return; Optr = skip_white(Optr); eval(); dist = Result - (Pc+1); if( (dist >127 || dist <-128) && Pass==2){ error("Branch out of Range"); dist = Old_pc - (Pc+1); } emit(lobyte(dist)); return; default: fatal("Error in Mnemonic table"); } } /* * bitop --- adjust opcode on bit manipulation instructions */ bitop(op,mode,class) int op; int mode; int class; { if( mode == INDX || mode == INDY ) return(op); if( class == SETCLR ) return(op-8); else if(class==BTB) return(op-12); else fatal("bitop"); } /* * do_gen --- process general addressing modes */ do_gen(op,mode,pnorm,px,py) int op; /* base opcode */ int mode; /* addressing mode */ int pnorm; /* page for normal addressing modes: IMM,DIR,EXT */ int px; /* page for INDX addressing */ int py; /* page for INDY addressing */ { switch(mode){ case LIMMED: Optr++; epage(pnorm); emit(op); eval(); eword(Result); break; case IMMED: Optr++; epage(pnorm); emit(op); eval(); emit(lobyte(Result)); break; case INDY: if(yflag) Cycles += 2; else Cycles += 3; epage(py); do_indexed(op+0x20); break; case INDX: Cycles+=2; epage(px); do_indexed(op+0x20); break; case OTHER: eval(); epage(pnorm); if(Force_word){ emit(op+0x30); eword(Result); Cycles+=2; break; } if(Force_byte){ emit(op+0x10); emit(lobyte(Result)); Cycles++; break; } if(Result>=0 && Result <=0xFF){ emit(op+0x10); emit(lobyte(Result)); Cycles++; break; } else { emit(op+0x30); eword(Result); Cycles+=2; break; } break; default: error("Unknown Addressing Mode"); } } /* * do_indexed --- handle all wierd stuff for indexed addressing */ do_indexed(op) int op; { char c; emit(op); eval(); if( *Optr++ != ',' ) error("Syntax"); c = mapdn(*Optr++); if( c != 'x' && c != 'y') warn("Indexed Addressing Assumed"); if( Result < 0 || Result > 255) warn("Value Truncated"); emit(lobyte(Result)); } /* * epage --- emit page prebyte */ epage(p) int p; { if( p != PAGE1 ) /* PAGE1 means no prebyte */ emit(p); } SHAR_EOF cat << \SHAR_EOF > DO4.C /* * MC6804 specific processing */ #define IMMED 0 #define IND 1 #define OTHER 2 /* special addresses */ #define XREG 0x80 #define YREG 0x81 #define SD1REG 0x82 #define SD2REG 0x83 #define ACCUM 0xFF /* * localinit --- machine specific initialization */ localinit() { install("x",XREG); install("X",XREG); install("y",YREG); install("Y",YREG); install("a",ACCUM); install("A",ACCUM); } /* * do_op --- process mnemonic */ do_op(opcode,class) { int dist; /* relative branch distance */ int amode; /* indicated addressing mode */ int r1; /* first eval() for mvi */ if (( *Operand == '[' ) || ( *Operand == ',')) amode = IND; else if( *Operand == '#' ) amode = IMMED; else amode = OTHER; switch(class){ case INH: /* inherent addressing */ emit(opcode); return; case APOST: /* A address in mem follows opcode */ emit(opcode); emit(ACCUM); return; case REL: /* short relative branches */ eval(); dist = Result - (Pc+1); if( (dist >15 || dist <-16) && Pass==2){ error("Branch out of Range"); dist = -1; } emit(opcode + (dist&0x1F)); return; case BTB: case SETCLR: eval(); if(Result <0 || Result >7){ error("Bit Number must be 0-7"); return; } emit( opcode + Result); if(*Optr++ != ',')error("SYNTAX"); eval(); emit(lobyte(Result)); if( class == SETCLR ) return; if(*Optr++ != ',')error("SYNTAX"); eval(); dist = Result - (Old_pc+3); if( (dist >127 || dist <-128) && Pass==2){ error("Branch out of Range"); dist = -3; return; } emit(lobyte(dist)); return; case EXT: /* jsr, jmp */ eval(); emit(opcode | (hibyte(Result) & 0x0F)); emit(lobyte(Result)); return; case BPM: /* brset/clr 7,accum,target */ emit(opcode); emit(ACCUM); eval(); dist = Result - (Old_pc + 3); if ((dist > 127 || dist < -128) && Pass == 2) { error("Branch out of range"); dist = -3; return; } emit(lobyte(dist)); return; case MVI: eval(); r1 = Result; /* save result */ if (*Optr++ != ',') warn("Missing ','"); eval(); mvi(opcode,r1,Result); return; case CLRX: /* mvi xreg,0 */ mvi(opcode,XREG,0); return; case CLRY: /* mvi yreg,0 */ mvi(opcode,YREG,0); return; case LDX: /* mvi xreg data */ if (amode == IMMED) Optr++; eval(); mvi(opcode,XREG,Result); return; case LDY: /* mvi yreg data */ if (amode == IMMED) Optr++; eval(); mvi(opcode,YREG,Result); return; case NOIMM: if( amode == IMMED ){ error("Immediate Addressing Illegal"); return; } case GEN: if ( amode == IMMED ) { Optr++; eval(); emit(opcode | 0x08); emit(Result); return; } if( amode == IND ){ Optr++; eval(); if ((*Optr != ']') && (*Operand != ',')) warn("Missing ']'"); if (Result != XREG && Result != YREG) { error("Operand must be $80 or $81"); emit(opcode); return; } emit(opcode | ((Result&0x01)<<4)); return; } eval(); if (XREG <= Result && Result <=SD2REG){ /*check for short direct cases*/ if ( opcode==0xE6 ) { /* inc */ emit(0xA8 + (Result-XREG)); return; } if ( opcode==0xE7 ) { /* dec */ emit(0xB8 + (Result-XREG)); return; } if ( opcode==0xE0 ) { /* lda */ emit(0xAC | (Result-XREG)); return; } if ( opcode==0xE1 ) { /* sta */ emit(0xBC | (Result-XREG)); return; } } /* else direct addressing */ emit( opcode | 0x18); emit(lobyte(Result)); return; default: fatal("Error in Mnemonic table"); } } mvi(op,to,from) int op,to,from; { emit(op); emit(to); emit(from); } SHAR_EOF cat << \SHAR_EOF > DO5.C /* * MC6805 specific processing */ /* addressing modes */ #define IMMED 0 /* immediate */ #define IND 1 /* indexed */ #define OTHER 2 /* NOTA */ /* * localinit --- machine specific initialization */ localinit() { } /* * do_op --- process mnemonic * * Called with the base opcode and it's class. Optr points to * the beginning of the operand field. */ do_op(opcode,class) int opcode; /* base opcode */ int class; /* mnemonic class */ { int dist; /* relative branch distance */ int amode; /* indicated addressing mode */ char *peek; /* guess at addressing mode */ peek = Optr; amode = OTHER; while( !delim(*peek) && *peek != EOS) /* check for comma in operand field */ if( *peek++ == ',' ){ amode = IND; break; } if( *Optr == '#' ) amode = IMMED; switch(class){ case INH: /* inherent addressing */ emit(opcode); return; case GEN: /* general addressing */ do_gen(opcode,amode); return; case REL: /* short relative branches */ eval(); dist = Result - (Pc+2); emit(opcode); if( (dist >127 || dist <-128) && Pass==2){ error("Branch out of Range"); emit(lobyte(-2)); return; } emit(lobyte(dist)); return; case NOIMM: if( amode == IMMED ){ error("Immediate Addressing Illegal"); return; } do_gen(opcode,amode); return; case GRP2: if( amode == IND ){ do_indexed(opcode+0x20); return; } eval(); Cycles += 2; if(Force_byte){ emit(opcode); emit(lobyte(Result)); return; } if(Result>=0 && Result <=0xFF){ emit(opcode); emit(lobyte(Result)); return; } error("Extended Addressing not allowed"); return; case SETCLR: case BTB: eval(); if(Result <0 || Result >7){ error("Bit Number must be 0-7"); return; } emit( opcode | (Result << 1)); if(*Optr++ != ',')error("SYNTAX"); eval(); emit(lobyte(Result)); if(class==SETCLR) return; /* else it's bit test and branch */ if(*Optr++ != ',')error("SYNTAX"); eval(); dist = Result - (Old_pc+3); if( (dist >127 || dist <-128) && Pass==2){ error("Branch out of Range"); emit(lobyte(-3)); return; } emit(lobyte(dist)); return; default: fatal("Error in Mnemonic table"); } } /* * do_gen --- process general addressing */ do_gen(op,mode) int op; int mode; { if( mode == IMMED){ Optr++; emit(op); eval(); emit(lobyte(Result)); return; } else if( mode == IND ){ do_indexed(op+0x30); return; } else if( mode == OTHER){ /* direct or extended addressing */ eval(); if(Force_word){ emit(op+0x20); eword(Result); Cycles += 3; return; } if(Force_byte){ emit(op+0x10); emit(lobyte(Result)); Cycles += 2; return; } if(Result >= 0 && Result <= 0xFF){ emit(op+0x10); emit(lobyte(Result)); Cycles += 2; return; } else { emit(op+0x20); eword(Result); Cycles += 3; return; } } else { error("Unknown Addressing Mode"); return; } } /* * do_indexed --- handle all wierd stuff for indexed addressing */ do_indexed(op) int op; { eval(); if(!(*Optr++ == ',' && (*Optr == 'x' || *Optr == 'X'))) warn("Indexed Addressing Assumed"); if(Force_word){ if(op < 0x80 ){ /* group 2, no extended addressing */ emit(op+0x10); /* default to one byte indexed */ emit(lobyte(Result)); Cycles += 3; return; } emit(op); eword(Result); Cycles += 4; return; } Cycles += 3; /* assume 1 byte indexing */ if(Force_byte){ emit(op+0x10); emit(lobyte(Result)); return; } if(Result==0){ emit(op+0x20); Cycles--; /* ,x slightly faster */ return; } if(Result>0 && Result <=0xFF){ emit(op+0x10); emit(lobyte(Result)); return; } if( op < 0x80 ){ warn("Value Truncated"); emit(op+0x10); emit(lobyte(Result)); return; } emit(op); eword(Result); Cycles++; /* 2 byte slightly slower */ return; } SHAR_EOF cat << \SHAR_EOF > DO9.C /* * MC6809 specific processing */ #define PAGE2 0x10 #define PAGE3 0x11 #define IPBYTE 0x9F /* extended indirect postbyte */ #define SWI 0x3F /* register names */ #define RD 0 #define RX 1 #define RY 2 #define RU 3 #define RS 4 #define RPC 5 #define RA 8 #define RB 9 #define RCC 10 #define RDP 11 #define RPCR 12 /* convert tfr/exg reg number into psh/pul format */ int regs[] = { 6,16,32,64,64,128,0,0,2,4,1,8,0}; int rcycl[]= { 2,2, 2, 2, 2, 2, 0,0,1,1,1,1,0}; /* addressing modes */ #define IMMED 0 /* immediate */ #define IND 1 /* indexed */ #define INDIR 2 /* indirect */ #define OTHER 3 /* NOTA */ /* * localinit --- machine specific initialization */ localinit() { } /* * do_op --- process mnemonic * * Called with the base opcode and it's class. Optr points to * the beginning of the operand field. */ do_op(opcode,class) int opcode; /* base opcode */ int class; /* mnemonic class */ { int dist; /* relative branch distance */ int src,dst;/* source and destination registers */ int pbyte; /* postbyte value */ int amode; /* indicated addressing mode */ int j; amode = set_mode(); /* pickup indicated addressing mode */ switch(class){ case INH: /* inherent addressing */ emit(opcode); return; case GEN: /* general addressing */ do_gen(opcode,amode); return; case IMM: /* immediate addressing */ if( amode != IMMED ){ error("Immediate Operand Required"); return; } Optr++; eval(); emit(opcode); emit(lobyte(Result)); return; case REL: /* short relative branches */ eval(); dist = Result - (Pc+2); emit(opcode); if( (dist >127 || dist <-128) && Pass==2){ error("Branch out of Range"); emit(lobyte(-2)); return; } emit(lobyte(dist)); return; case P2REL: /* long relative branches */ eval(); dist = Result - (Pc+4); emit(PAGE2); emit(opcode); eword(dist); return; case P1REL: /* lbra and lbsr */ if( amode == IMMED) Optr++; /* kludge for C compiler */ eval(); dist = Result - (Pc+3); emit(opcode); eword(dist); return; case NOIMM: if( amode == IMMED ){ error("Immediate Addressing Illegal"); return; } do_gen(opcode,amode); return; case P2GEN: emit(PAGE2); if( amode == IMMED ){ emit(opcode); Optr++; eval(); eword(Result); return; } do_gen(opcode,amode); return; case P3GEN: emit(PAGE3); if( amode == IMMED ){ emit(opcode); Optr++; eval(); eword(Result); return; } do_gen(opcode,amode); return; case RTOR: /* tfr and exg */ emit(opcode); src = regnum(); while(alpha(*Optr))Optr++; if(src==ERR){ error("Register Name Required"); emit(0); return; } if(*Optr++ != ','){ error("Missing ,"); emit(0); return; } dst = regnum(); while(alpha(*Optr))Optr++; if(dst==ERR){ error("Register Name Required"); emit(0); return; } if( src==RPCR || dst==RPCR){ error("PCR illegal here"); emit(0); return; } if( (src <=5 && dst >=8) || (src >=8 && dst <=5)){ error("Register Size Mismatch"); emit(0); return; } emit( (src<<4)+dst ); return; case INDEXED: /* indexed addressing only */ if( *Optr == '#'){ Optr++; /* kludge city */ amode = IND; } if( amode != IND ){ error("Indexed Addressing Required"); return; } do_indexed(opcode); return; case RLIST: /* pushes and pulls */ if(*Operand == EOS){ error("Register List Required"); return; } emit(opcode); pbyte = 0; do{ j = regnum(); if( j == ERR || j==RPCR) error("Illegal Register Name"); else if(j==RS && (opcode==52)) error("Can't Push S on S"); else if(j==RU && (opcode==54)) error("Can't Push U on U"); else if(j==RS && (opcode==53)) error("Can't Pull S from S"); else if(j==RU && (opcode==55)) error("Can't Pull U from U"); else{ pbyte |= regs[j]; Cycles += rcycl[j]; } while(*Optr != EOS && alpha(*Optr))Optr++; }while( *Optr++ == ',' ); emit(lobyte(pbyte)); return; case P2NOIMM: if( amode == IMMED ) error("Immediate Addressing Illegal"); else{ emit(PAGE2); do_gen(opcode,amode); } return; case P2INH: /* Page 2 inherent */ emit(PAGE2); emit(opcode); return; case P3INH: /* Page 3 inherent */ emit(PAGE3); emit(opcode); return; case LONGIMM: if( amode == IMMED ){ emit(opcode); Optr++; eval(); eword(Result); } else do_gen(opcode,amode); return; case GRP2: if( amode == IND ){ do_indexed(opcode+0x60); return; } else if( amode == INDIR){ Optr++; emit(opcode + 0x60); emit(IPBYTE); eval(); eword(Result); Cycles += 7; if(*Optr == ']'){ Optr++; return; } error("Missing ']'"); return; } eval(); if(Force_word){ emit(opcode+0x70); eword(Result); Cycles += 3; return; } if(Force_byte){ emit(opcode); emit(lobyte(Result)); Cycles += 2; return; } if(Result>=0 && Result <=0xFF){ emit(opcode); emit(lobyte(Result)); Cycles += 2; return; } else { emit(opcode+0x70); eword(Result); Cycles += 3; return; } case SYS: /* system call */ emit(SWI); eval(); emit(lobyte(Result)); return; default: fatal("Error in Mnemonic table"); } } /* * do_gen --- process general addressing mode stuff */ do_gen(op,mode) int op; int mode; { if( mode == IMMED){ Optr++; emit(op); eval(); emit(lobyte(Result)); return; } else if( mode == IND ){ do_indexed(op+0x20); return; } else if( mode == INDIR){ Optr++; emit(op+0x20); emit(IPBYTE); eval(); eword(Result); Cycles += 7; if(*Optr == ']'){ Optr++; return; } error("Missing ']'"); return; } else if( mode == OTHER){ eval(); if(Force_word){ emit(op+0x30); eword(Result); Cycles += 3; return; } if(Force_byte){ emit(op+0x10); emit(lobyte(Result)); Cycles += 2; return; } if(Result>=0 && Result <=0xFF){ emit(op+0x10); emit(lobyte(Result)); Cycles += 2; return; } else { emit(op+0x30); eword(Result); Cycles += 3; return; } } else { error("Unknown Addressing Mode"); return; } } /* * do_indexed --- handle all wierd stuff for indexed addressing */ do_indexed(op) int op; { int pbyte; int j,k; int predec,pstinc; Cycles += 2; /* indexed is always 2+ base cycle count */ predec=0; pstinc=0; pbyte=128; emit(op); if(*Optr=='['){ pbyte |= 0x10; /* set indirect bit */ Optr++; if( !any((char)']',Optr)) error("Missing ']'"); Cycles += 3; /* indirection takes this much longer */ } j=regnum(); if(j==RA){ Cycles++; abd_index(pbyte+6); return; } if(j==RB){ Cycles++; abd_index(pbyte+5); return; } if(j==RD){ Cycles += 4; abd_index(pbyte+11); return; } eval(); Optr++; while(*Optr=='-'){ predec++; Optr++; } j=regnum(); while( alpha(*Optr) )Optr++; while(*Optr=='+'){ pstinc++; Optr++; } if(j==RPC || j==RPCR){ if( pstinc || predec ){ error("Auto Inc/Dec Illegal on PC"); return; } if(j==RPC){ if(Force_word){ emit(pbyte+13); eword(Result); Cycles += 5; return; } if(Force_byte){ emit(pbyte+12); emit(lobyte(Result)); Cycles++; return; } if(Result>=-128 && Result <=127){ emit(pbyte+12); emit(lobyte(Result)); Cycles++; return; } else { emit(pbyte+13); eword(Result); Cycles += 5; return; } } /* PCR addressing */ if(Force_word){ emit(pbyte+13); eword(Result-(Pc+2)); Cycles += 5; return; } if(Force_byte){ emit(pbyte+12); emit(lobyte(Result-(Pc+1))); Cycles++; return; } k=Result-(Pc+2); if( k >= -128 && k <= 127){ emit(pbyte+12); emit(lobyte(Result-(Pc+1))); Cycles++; return; } else{ emit(pbyte+13); eword(Result-(Pc+2)); Cycles += 5; return; } } if(predec || pstinc){ if(Result != 0){ error("Offset must be Zero"); return; } if(predec>2 || pstinc>2){ error("Auto Inc/Dec by 1 or 2 only"); return; } if((predec==1 && (pbyte&0x10) != 0) || (pstinc==1 && (pbyte&0x10) != 0)){ error("No Auto Inc/Dec by 1 for Indirect"); return; } if(predec && pstinc){ error("Can't do both!"); return; } if(predec) pbyte += predec+1; if(pstinc) pbyte += pstinc-1; pbyte += rtype(j); emit(pbyte); Cycles += 1 + predec + pstinc; return; } pbyte += rtype(j); if(Force_word){ emit(pbyte+0x09); eword(Result); Cycles += 4; return; } if(Force_byte){ emit(pbyte+0x08); emit(lobyte(Result)); Cycles++; return; } if(Result==0){ emit(pbyte+0x04); return; } if((Result >= -16) && (Result <= 15) && ((pbyte&16)==0)){ pbyte &= 127; pbyte += Result&31; emit(pbyte); Cycles++; return; } if(Result >= -128 && Result <= 127){ emit(pbyte+0x08); emit(lobyte(Result)); Cycles++; return; } emit(pbyte+0x09); eword(Result); Cycles += 4; return; } /* * abd_index --- a,b or d indexed */ abd_index(pbyte) int pbyte; { int k; Optr += 2; k=regnum(); pbyte += rtype(k); emit(pbyte); return; } /* * rtype --- return register type in post-byte format */ rtype(r) int r; { switch(r){ case RX: return(0x00); case RY: return(0x20); case RU: return(0x40); case RS: return(0x60); } error("Illegal Register for Indexed"); return(0); } /* * set_mode --- determine addressing mode from operand field */ set_mode() { register char *p; if( *Operand == '#' ) return(IMMED); /* immediate addressing */ p = Operand; while( *p != EOS && *p != BLANK && *p != TAB){/* any , before break */ if( *p == ',') return(IND); /* indexed addressing */ p++; } if( *Operand == '[') return(INDIR); /* indirect addressing */ return(OTHER); /* NOTA */ } /* * regnum --- return register number of *Optr */ regnum() { if( head(Optr,"D" ))return(RD); if( head(Optr,"d" ))return(RD); if( head(Optr,"X" ))return(RX); if( head(Optr,"x" ))return(RX); if( head(Optr,"Y" ))return(RY); if( head(Optr,"y" ))return(RY); if( head(Optr,"U" ))return(RU); if( head(Optr,"u" ))return(RU); if( head(Optr,"S" ))return(RS); if( head(Optr,"s" ))return(RS); if( head(Optr,"PC" ))return(RPC); if( head(Optr,"pc" ))return(RPC); if( head(Optr,"PCR" ))return(RPCR); if( head(Optr,"pcr" ))return(RPCR); if( head(Optr,"A" ))return(RA); if( head(Optr,"a" ))return(RA); if( head(Optr,"B" ))return(RB); if( head(Optr,"b" ))return(RB); if( head(Optr,"CC" ))return(RCC); if( head(Optr,"cc" ))return(RCC); if( head(Optr,"DP" ))return(RDP); if( head(Optr,"dp" ))return(RDP); return(ERR); } SHAR_EOF cat << \SHAR_EOF > FFWD.C /* * file I/O version of forward ref handler */ #define FILEMODE 0644 /* file creat mode */ #define UPDATE 2 /* file open mode */ #define ABS 0 /* absolute seek */ int Forward =0; /* temp file's file descriptor */ char Fwd_name[] = { "Fwd_refs" } ; /* * fwdinit --- initialize forward ref file */ fwdinit() { Forward = creat(Fwd_name,FILEMODE); if(Forward <0) fatal("Can't create temp file"); close(Forward); /* close and reopen for reads and writes */ Forward = open(Fwd_name,UPDATE); if(Forward <0) fatal("Forward ref file has gone."); #ifndef DEBUG unlink(Fwd_name); #endif } /* * fwdreinit --- reinitialize forward ref file */ fwdreinit() { F_ref = 0; Ffn = 0; lseek(Forward,0L,ABS); /* rewind forward refs */ read(Forward,&Ffn,sizeof(Ffn)); read(Forward,&F_ref,sizeof(F_ref)); /* read first forward ref into mem */ #ifdef DEBUG printf("First fwd ref: %d,%d\n",Ffn,F_ref); #endif } /* * fwdmark --- mark current file/line as containing a forward ref */ fwdmark() { write(Forward,&Cfn,sizeof(Cfn)); write(Forward,&Line_num,sizeof(Line_num)); } /* * fwdnext --- get next forward ref */ fwdnext() { int stat; stat = read(Forward,&Ffn,sizeof(Ffn)); #ifdef DEBUG printf("Ffn stat=%d ",stat); #endif stat = read(Forward,&F_ref,sizeof(F_ref)); #ifdef DEBUG printf("F_ref stat=%d ",stat); #endif if( stat < 2 ){ F_ref=0;Ffn=0; } #ifdef DEBUG printf("Next Fwd ref: %d,%d\n",Ffn,F_ref); #endif } SHAR_EOF cat << \SHAR_EOF > OUTPUT.C /* * stable --- prints the symbol table in alphabetical order */ stable(ptr) struct nlist *ptr; { if (ptr != NULL) { stable (ptr->Lnext); printf ("%-10s %04x\n",ptr->name,ptr->def); stable (ptr->Rnext); } } /* * cross -- prints the cross reference table */ cross(point) struct nlist *point; { struct link *tp; int i = 1; if (point != NULL) { cross (point->Lnext); printf ("%-10s %04x *",point->name,point->def); tp = point->L_list; while (tp != NULL) { if (i++>10) { i=1; printf("\n "); } printf ("%04d ",tp->L_num); tp = tp->next; } printf ("\n"); cross (point->Rnext); } } SHAR_EOF cat << \SHAR_EOF > PSEUDO.C /* * pseudo --- pseudo op processing */ #define RMB 0 /* Reserve Memory Bytes */ #define FCB 1 /* Form Constant Bytes */ #define FDB 2 /* Form Double Bytes (words) */ #define FCC 3 /* Form Constant Characters */ #define ORG 4 /* Origin */ #define EQU 5 /* Equate */ #define ZMB 6 /* Zero memory bytes */ #define FILL 7 /* block fill constant bytes */ #define OPT 8 /* assembler option */ #define NULL_OP 9 /* null pseudo op */ #define PAGE 10 /* new page */ struct oper pseudo[] = { "bsz", PSEUDO, ZMB, 0, "end", PSEUDO, NULL_OP,0, "equ", PSEUDO, EQU, 0, "fcb", PSEUDO, FCB, 0, "fcc", PSEUDO, FCC, 0, "fdb", PSEUDO, FDB, 0, "fill", PSEUDO, FILL, 0, "nam", PSEUDO, NULL_OP,0, "name", PSEUDO, NULL_OP,0, "opt", PSEUDO, OPT, 0, "org", PSEUDO, ORG, 0, "pag", PSEUDO, PAGE, 0, "page", PSEUDO, PAGE, 0, "rmb", PSEUDO, RMB, 0, "spc", PSEUDO, NULL_OP,0, "ttl", PSEUDO, NULL_OP,0, "zmb", PSEUDO, ZMB, 0 }; /* * do_pseudo --- do pseudo op processing */ do_pseudo(op) int op; /* which op */ { char fccdelim; int j; int fill; char *skip_white(); if( op != EQU && *Label ) install(Label,Pc); P_force++; switch(op){ case RMB: /* reserve memory bytes */ if( eval() ){ Pc += Result; f_record(); /* flush out bytes */ } else error("Undefined Operand during Pass One"); break; case ZMB: /* zero memory bytes */ if( eval() ) while( Result-- ) emit(0); else error("Undefined Operand during Pass One"); break; case FILL: /* fill memory with constant */ eval(); fill = Result; if( *Optr++ != ',' ) error("Bad fill"); else{ Optr = skip_white(Optr); eval(); while( Result-- ) emit(fill); } break; case FCB: /* form constant byte(s) */ do{ Optr = skip_white(Optr); eval(); if( Result > 0xFF ){ if(!Force_byte) warn("Value truncated"); Result = lobyte(Result); } emit(Result); }while( *Optr++ == ',' ); break; case FDB: /* form double byte(s) */ do{ Optr = skip_white(Optr); eval(); eword(Result); }while( *Optr++ == ',' ); break; case FCC: /* form constant characters */ if(*Operand==EOS) break; fccdelim = *Optr++; while( *Optr != EOS && *Optr != fccdelim) emit(*Optr++); if(*Optr == fccdelim) Optr++; else error("Missing Delimiter"); break; case ORG: /* origin */ if( eval() ){ Old_pc = Pc = Result; f_record(); /* flush out any bytes */ } else error("Undefined Operand during Pass One"); break; case EQU: /* equate */ if(*Label==EOS){ error("EQU requires label"); break; } if( eval() ){ install(Label,Result); Old_pc = Result; /* override normal */ } else error("Undefined Operand during Pass One"); break; case OPT: /* assembler option */ P_force=0; if( head(Operand,"l") ) Lflag=1; else if( head(Operand,"nol")) Lflag=0; else if( head(Operand,"c")){ Cflag=1; Ctotal=0; } else if( head(Operand,"noc")) Cflag=0; else if( head(Operand,"contc")){ Cflag=1; } else if ( head(Operand,"s")) Sflag = 1; else if ( head(Operand,"cre")) CREflag = 1; else error("Unrecognized OPT"); break; case PAGE: /* go to a new page */ P_force=0; N_page = 1; if (Pass == 2 ) if (Lflag) { printf ("\f"); printf ("%-10s",Argv[Cfn]); printf (" "); printf ("page %3d\n",Page_num++); } break; case NULL_OP: /* ignored psuedo ops */ P_force=0; break; default: fatal("Pseudo error"); } } SHAR_EOF # End of shell archive exit 0 -- Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page Have five nice days.