/* * 6800.c * Updated (?) for the new compiler */ /*)BUILD # untested */ #include #define NCPS 8 #define NTSYM 128 #define NERR 10 #define NINPUT 128 #define NCODE 128 #define NTIT 64 #define NSYM 256 #define NLIST 0 #define SLIST 1 #define ALIST 2 #define CLIST 3 #define CMP 0x81 #define ADD 0x8B #define SUB 0x80 #define CPX 0x8C #define ABA 0x1B #define SBA 0x10 #define CBA 0x11 #define JMP 0x4E #define JSR 0x8D #define TAB 0x16 #define TBA 0x17 #define TAP 0x06 #define TPA 0x07 #define TSX 0x30 #define TXS 0x35 #define LDA 0x86 #define STA 0x87 #define LDS 0x8E #define STS 0x8F #define INC 0x4C #define DEC 0x4A #define INX 0x08 #define DEX 0x09 #define INS 0x31 #define DES 0x34 #define dot (&sym[0]) struct sym { char s_name[NCPS]; char s_type; char s_flag; int s_addr; }; #define S_UND 0 #define S_ABS 1 #define S_OP0 2 #define S_OP1 3 #define S_OP2 4 #define S_OP3 5 #define S_OP4 6 #define S_OP5 7 #define S_A 8 #define S_B 9 #define S_X 10 #define S_S 11 #define S_LIT 12 #define S_INDEX 13 #define S_P 14 #define S_BYTE 24 #define S_WORD 25 #define S_ASCII 26 #define S_ASCIZ 27 #define S_BLKB 28 #define S_PAGE 29 #define S_TITLE 30 #define S_BYTE 31 #define S_HLIST 32 #define S_OLIST 33 #define S_MDF 01 /* Mult. def */ #define S_ASG 02 /* Assigned def */ #define S_LV 04 /* Lvalue required */ #define S_16 010 /* 16 bit */ struct tsym { int t_num; int t_addr; }; struct tsymp { struct tsym *t_fp; struct tsym *t_bp; }; struct addr { int a_type; int a_addr; }; int line; int page; int lop; int pass; int nsym; int ntsym; int lflag; int oflag; int eflag; int sflag; int laddr; int lmode; int hlist; char *ep; char eb[NERR]; char *ip; char ib[NINPUT]; char *cp; char cb[NCODE]; char tb[NTIT]; extern struct sym sym[]; struct tsym tsym[NTSYM]; struct tsymp tsymp[10]; FILE *lfp; FILE *ofp; FILE *sfp; #define LETTER 0 #define DIGIT 1 #define BINOP 2 #define ETC 3 #define ILL 4 #define SPACE 5 char ctype[128] = { ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, SPACE, ILL, ILL, SPACE, ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, ILL, SPACE, ETC, ETC, ETC, ETC, BINOP, BINOP, ETC, ETC, ETC, BINOP, BINOP, ETC, BINOP, LETTER, ETC, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, DIGIT, ETC, ETC, BINOP, ETC, BINOP, ETC, ETC, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, ETC, ETC, ETC, BINOP, LETTER, ETC, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, LETTER, ETC, BINOP, ETC, ETC, ETC }; main(argc, argv) char *argv[]; { register char *p; register c, i; struct tsym *tp; char *fn; FILE *afile(); fn = NULL; for (i=1; is_type = S_ABS; dot->s_flag = S_ASG; dot->s_addr = 0; line = 0; page = 0; lop = 60; rewind(sfp); /* * If second pass, reset the * f-b table. */ if (pass == 1) { for (i=0; i<10; ++i) { tsymp[i].t_fp = NULL; tsymp[i].t_bp = NULL; tp = tsym; while (tp < &tsym[ntsym]) { if (tp->t_num == i) { tsymp[i].t_fp = tp; break; } ++tp; } } } while (fgetss(ib, sizeof ib, sfp) != NULL) { /* MM */ ++line; cp = cb; ep = eb; ip = ib; eflag = 0; setexit(); if (eflag == 0) asm(); if (pass == 1) { diag(); list(); } } } } FILE * afile(fn, wf) char *fn; { register FILE *fp; fp = fopen(fn, wf?"w":"r"); if (fp == NULL) { fprintf(stderr, "%s: cannot open.\n", fn); exit(1); } return (fp); } asm() { register c, t1, t2; struct tsym *tp; struct sym *sp; struct addr a1, a2; int a, b, d, op; char id[NCPS], *p; struct sym *lookup(); laddr = dot->s_addr; lmode = SLIST; loop: while ((c = getnb()) == ';') ; if (c == '\0' || c == '/') return; if (ctype[c] == DIGIT) { if (getnb() != ':') qerr(); c -= '0'; if (pass == 0) { if (ntsym >= NTSYM) { fprintf(stderr, "Too many temp. symbols!\n"); exit(1); } tsym[ntsym].t_num = c; tsym[ntsym].t_addr = dot->s_addr; ++ntsym; } tp = tsymp[c].t_fp; tsymp[c].t_bp = tp; tsymp[c].t_fp = NULL; ++tp; while (tp < &tsym[ntsym]) { if (tp->t_num == c) { tsymp[c].t_fp = tp; break; } ++tp; } goto loop; } if (ctype[c] != LETTER) qerr(); getid(c, id); if ((c = getnb()) == ':') { sp = lookup(id, 1); if (pass == 0) { if (sp->s_type!=S_UND && (sp->s_flag&S_ASG)==0) sp->s_flag |= S_MDF; sp->s_type = S_ABS; sp->s_addr = dot->s_addr; } else { if ((sp->s_flag&S_MDF) != 0) err('m'); if (sp->s_type!=S_ABS || sp->s_addr!=dot->s_addr) err('p'); } lmode = ALIST; goto loop; } if (c == '=') { sp = lookup(id, 1); if (sp->s_type!=S_UND && (sp->s_flag&S_ASG)==0) err('m'); expr(&a1); sp->s_type = a1.a_type; sp->s_addr = laddr = a1.a_addr; sp->s_flag = S_ASG; lmode = ALIST; goto loop; } unget(c); lmode = CLIST; if ((sp = lookup(id, 0)) == NULL) { err('o'); return; } op = sp->s_addr; switch (sp->s_type) { case S_BYTE: case S_WORD: do { expr(&a1); a = a1.a_addr; if (sp->s_type == S_BYTE) { byte(a); outb(a); } else outw(a); } while ((c = getnb()) == ','); unget(c); break; case S_ASCII: case S_ASCIZ: if ((d = getnb()) == '\0') qerr(); while ((c = get())!='\0' && c!=d) outb(c); if (c == '\0') qerr(); if (sp->s_type == S_ASCIZ) outb(0); break; case S_BLKB: expr(&a1); a = a1.a_addr; if ((c = getnb()) == ',') { expr(&a1); b = a1.a_addr; } else { unget(c); b = 0; } while (a--) outb(b); lmode = ALIST; break; case S_TITLE: p = tb; if ((c = getnb()) != '\0') { do { if (p < &tb[NTIT-1]) *p++ = c; } while ((c = get()) != '\0'); } *p = '\0'; unget(c); case S_PAGE: lop = 60; lmode = NLIST; break; case S_HLIST: hlist = 1; lmode = NLIST; break; case S_OLIST: hlist = 0; lmode = NLIST; break; case S_OP0: outb(op); break; case S_OP1: t1 = addr(&a1); if (op == INC) { if (t1 == S_X) { outb(INX); break; } if (t1 == S_S) { outb(INS); break; } } if (op == DEC) { if (t1 == S_X) { outb(DEX); break; } if (t1 == S_S) { outb(DES); break; } } if (t1==S_A || t1==S_B) { if (op==JSR || op==JMP) aerr(); if (t1 == S_B) op |= 0x10; outb(op); break; } if (t1 == S_INDEX) { outx(op, a1.a_addr); break; } if (t1 == S_ABS) { outb(op | 0x30); outw(a1.a_addr); break; } aerr(); break; case S_OP2: expr(&a1); a = a1.a_addr - dot->s_addr - 2; outb(op); byte(a); outb(a); break; case S_OP3: addr(op==CMP ? &a2 : &a1); comma(); addr(op==CMP ? &a1 : &a2); t1 = a1.a_type; t2 = a2.a_type; if (t1==S_B && t2==S_A) { if (op == ADD) { outb(ABA); break; } if (op == SUB) { outb(SBA); break; } if (op == CMP) { outb(CBA); break; } } if (t2 == S_X) { if (op != CMP) aerr(); outd(CPX, 0, &a1, S_16); break; } if (t2==S_A || t2==S_B) { outd(op, t2, &a1, 0); break; } aerr(); break; case S_OP4: t1 = addr(&a1); comma(); t2 = addr(&a2); if (t1==S_A && t2==S_P) { outb(TAP); break; } if (t1==S_P && t2==S_A) { outb(TPA); break; } if (t1==S_A && t2==S_B) { outb(TAB); break; } if (t1==S_B && t2==S_A) { outb(TBA); break; } if (t1==S_S && t2==S_X) { outb(TSX); break; } if (t1==S_X && t2==S_S) { outb(TXS); break; } if (t1==S_A || t1==S_B) { outd(STA, t1, &a2, S_LV); break; } if (t2==S_A || t2==S_B) { outd(LDA, t2, &a1, 0); break; } if (t1==S_S || t1==S_X) { outd(STS, t1, &a2, S_LV|S_16); break; } if (t2==S_S || t2==S_X) { outd(LDS, t2, &a1, S_16); break; } aerr(); break; case S_OP5: t1 = addr(&a1); if (t1==S_A || t1==S_B) { if (t1 == S_B) op |= 0x01; outb(op); break; } aerr(); break; default: err('o'); } goto loop; } addr(ap) register struct addr *ap; { register c; struct addr x; if ((c = getnb()) == '$') { expr(ap); ap->a_type = S_LIT; return (S_LIT); } if (c == '(') { expr(&x); if (x.a_type!=S_X || getnb()!=')') qerr(); ap->a_type = S_INDEX; ap->a_addr = 0; return (S_INDEX); } unget(c); expr(ap); if (ap->a_type == S_ABS) { c = getnb(); if (c == '(') { expr(&x); if (x.a_type!=S_X || getnb()!=')') qerr(); ap->a_type = S_INDEX; } else unget(c); } return (ap->a_type); } expr(ap) register struct addr *ap; { register c; struct addr rop; term(ap); if (ap->a_type != S_ABS) return; for (;;) { c = getnb(); if ((c=='<' || c=='>') && c!=getnb()) qerr(); if (ctype[c] != BINOP) { unget(c); break; } term(&rop); if (c == '^') { ap->a_type = rop.a_type; continue; } switch(c) { case '+': ap->a_addr += rop.a_addr; break; case '-': ap->a_addr -= rop.a_addr; break; case '*': ap->a_addr *= rop.a_addr; break; case '%': ap->a_addr /= rop.a_addr; break; case '&': ap->a_addr &= rop.a_addr; break; case '|': ap->a_addr |= rop.a_addr; break; case '>': ap->a_addr >>= rop.a_addr; break; case '<': ap->a_addr <<= rop.a_addr; } } } term(ap) register struct addr *ap; { register c, n; char id[NCPS]; struct sym *sp; struct tsym *tp; int r, v; if ((c = getnb()) == '[') { expr(ap); if (getnb() != ']') qerr(); return; } if (c == '-') { expr(ap); ap->a_addr = -ap->a_addr; return; } if (c == '!') { expr(ap); ap->a_addr = ~ap->a_addr; return; } if (c == '\'') { if ((c = get()) == '\0') qerr(); ap->a_type = S_ABS; ap->a_addr = c; return; } if (ctype[c] == DIGIT) { ap->a_type = S_ABS; r = 10; if (c == '0') { r = 8; if ((c = get()) == 'x') { r = 16; c = get(); } } n = 0; while ((v = digit(c, r)) >= 0) { n = r*n + v; c = get(); } if (c=='f' || c=='b') { if (n < 10) { if (c == 'f') tp = tsymp[n].t_fp; else tp = tsymp[n].t_bp; if (tp != NULL) { ap->a_addr = tp->t_addr; return; } } err('u'); ap->a_addr = 256; return; } unget(c); ap->a_addr = n; return; } if (ctype[c] == LETTER) { getid(c, id); if ((sp = lookup(id, 0)) != NULL) { ap->a_type = sp->s_type; ap->a_addr = sp->s_addr; return; } err('u'); ap->a_type = S_ABS; ap->a_addr = 256; return; } qerr(); } digit(c, r) register c, r; { if (r == 16) { if (c >= 'A' && c <= 'F') return (c - 'A' + 10); if (c >= 'a' && c <= 'f') return (c - 'a' + 10); } if (c >= '0' && c <= '9') return (c - '0'); return (-1); } list() { register char *wp; register nb; if (lfp==NULL || lmode==NLIST) return; slew(); while (ep < &eb[NERR]) *ep++ = ' '; fprintf(lfp, "%.10s", eb); if (lmode == SLIST) { fprintf(lfp, "%24s%5d %s\n", "", line, ib); return; } fprintf(lfp, hlist?" %04x":" %06o", laddr); if (lmode == ALIST) { fprintf(lfp, "%17s%5d %s\n", "", line, ib); return; } wp = cb; nb = cp - cb; list1(wp, nb, 1); fprintf(lfp, " %5d %s\n", line, ib); while ((nb -= 4) > 0) { wp += 4; slew(); fprintf(lfp, "%17s", ""); list1(wp, nb, 0); putc('\n', lfp); } } list1(wp, nb, f) register char *wp; register nb; { register i; if (nb > 4) nb = 4; for (i=0; i= 60) { fprintf(lfp, "\fM6800 assembler, page %d\n", ++page); fprintf(lfp, "%s\n\n", tb); lop = 4; } } byte(n) register n; { if ((n&0200) != 0) n |= ~0377; if (n<-128 || n>127) err('a'); } comma() { if (getnb() != ',') qerr(); } getid(c, id) register c; char *id; { register char *p; p = id; do { if (p < &id[NCPS]) *p++ = c; } while (ctype[c=get()]==LETTER || ctype[c]==DIGIT); unget(c); while (p < &id[NCPS]) *p++ = 0; } getnb() { register c; while ((c=get())==' ' || c=='\t') ; return (c); } get() { register c; if ((c = *ip) != '\0') ++ip; return (c); } unget(c) { if (c != '\0') --ip; } usage() { fprintf(stderr, "Usage: 6800 [-los] file.\n"); exit(1); } syminit() { register struct sym *sp; sp = &sym[0]; while (sp < &sym[NSYM]) { if (sp->s_name[0] == 0) break; ++nsym; ++sp; } } struct sym * lookup(id, f) char *id; { register struct sym *sp; register char *p1, *p2; sp = sym; while (sp < &sym[nsym]) { p1 = id; p2 = sp->s_name; while (p1 < &id[NCPS]) { if (*p1 != *p2++) break; ++p1; } if (p1 == &id[NCPS]) return (sp); ++sp; } if (f == 0) return (NULL); if (nsym >= NSYM) { fprintf(stderr, "Too many symbols!\n"); exit(1); } p1 = id; p2 = sp->s_name; while (p1 < &id[NCPS]) *p2++ = *p1++; sp->s_type = S_UND; sp->s_flag = 0; sp->s_addr = 256; /* Force ext. */ ++nsym; return (sp); } aerr() { err('a'); } qerr() { err('q'); } err(c) register c; { register char *p; p = eb; while (p < ep) if (c == *p++) return; if (p < &eb[NERR]) { *p++ = c; ep = p; } if (c == 'q') { ++eflag; unwind(); } } diag() { register char *p; register n; if (ep > eb) { p = eb; n = 0; while (p < ep) { putchar(*p++); ++n; } while (n < NERR) { putchar(' '); ++n; } printf(" %4d %s\n", line, ib); } } outd(op, r, ap, f) register struct addr *ap; { register a, t; a = ap->a_addr; t = ap->a_type; if (r==S_B || r==S_X) op |= 0x40; if (t == S_LIT) { if ((f&S_LV) != 0) aerr(); outb(op); if ((f&S_16) != 0) outw(ap->a_addr); else outb(ap->a_addr); return; } if (t == S_INDEX) { outx(op, a); return; } if (t == S_ABS) { if (a < 0x100) { outb(op | 0x10); outb(a); } else { outb(op | 0x30); outw(a); } return; } aerr(); } outx(op, a) { outb(op | 0x20); byte(a); outb(a); } outw(w) register w; { outb(w>>8); outb(w); } outb(b) register b; { if (cp < &cb[NCODE]) *cp++ = b; ++dot->s_addr; } struct sym sym[NSYM] = { ".", S_ABS, 0, 0, ".byte", S_BYTE, 0, 0, ".word", S_WORD, 0, 0, ".ascii", S_ASCII, 0, 0, ".asciz", S_ASCIZ, 0, 0, ".blkb", S_BLKB, 0, 0, ".page", S_PAGE, 0, 0, ".title", S_TITLE, 0, 0, ".hlist", S_HLIST, 0, 0, ".olist", S_OLIST, 0, 0, "a", S_A, 0, 0, "b", S_B, 0, 0, "s", S_S, 0, 0, "x", S_X, 0, 0, "p", S_P, 0, 0, "nop", S_OP0, 0, 0x01, "clv", S_OP0, 0, 0x0A, "sev", S_OP0, 0, 0x0B, "clc", S_OP0, 0, 0x0C, "sec", S_OP0, 0, 0x0D, "cli", S_OP0, 0, 0x0E, "sei", S_OP0, 0, 0x0F, "daa", S_OP0, 0, 0x19, "rts", S_OP0, 0, 0x39, "rti", S_OP0, 0, 0x3B, "wait", S_OP0, 0, 0x3E, "sys", S_OP0, 0, 0x3F, "neg", S_OP1, 0, 0x40, "com", S_OP1, 0, 0x43, "lsr", S_OP1, 0, 0x44, "ror", S_OP1, 0, 0x46, "asr", S_OP1, 0, 0x47, "asl", S_OP1, 0, 0x48, "rol", S_OP1, 0, 0x49, "dec", S_OP1, 0, 0x4A, "inc", S_OP1, 0, 0x4C, "tst", S_OP1, 0, 0x4D, "clr", S_OP1, 0, 0x4F, "jmp", S_OP1, S_LV, 0x4E, "jsr", S_OP1, S_LV, 0x8D, "br", S_OP2, 0, 0x20, "bhi", S_OP2, 0, 0x22, "blos", S_OP2, 0, 0x23, "bcc", S_OP2, 0, 0x24, "bcs", S_OP2, 0, 0x25, "bne", S_OP2, 0, 0x26, "beq", S_OP2, 0, 0x27, "bvc", S_OP2, 0, 0x28, "bvs", S_OP2, 0, 0x29, "bpl", S_OP2, 0, 0x2A, "bmi", S_OP2, 0, 0x2B, "bge", S_OP2, 0, 0x2C, "blt", S_OP2, 0, 0x2D, "bgt", S_OP2, 0, 0x2E, "ble", S_OP2, 0, 0x2F, "bhis", S_OP2, 0, 0x24, "blo", S_OP2, 0, 0x25, "bsr", S_OP2, 0, 0x8D, "sub", S_OP3, 0, 0x80, "cmp", S_OP3, 0, 0x81, "sbc", S_OP3, 0, 0x82, "and", S_OP3, 0, 0x84, "bit", S_OP3, 0, 0x85, "xor", S_OP3, 0, 0x88, "adc", S_OP3, 0, 0x89, "or", S_OP3, 0, 0x8A, "add", S_OP3, 0, 0x8B, "mov", S_OP4, 0, 0, "push", S_OP5, 0, 0x36, "pop", S_OP5, 0, 0x32 };