-h- 8085.CMD Sat Jan 02 18:00:53 1982 _DBB0:8085.CMD;1 $ allow no errors ! ! First the common compiler ! cc data/v cc expr/v cc lex/v cc list/v cc main/v cc out/v cc subr/v cc sym/v ! as data/d as expr/d as lex/d as list/d as main/d as out/d as subr/d as sym/d ! ! Now, the 8085-specific modules ! cc ext.85/v cc machin.85/v cc pst.85/v ! as ext/d as machin/d as pst/d ! ! Link it ! link as8085,as8085=data,expr,lex,list/b:2000// main,out,subr,sym ext,machin,pst c:suport,c:clib // ^Z -h- 8086.CMD Sat Jan 02 18:00:53 1982 _DBB0:8086.CMD;1 $ allow no errors ! ! First the common compiler ! cc data/v cc expr/v cc lex/v cc list/v cc main/v cc out/v cc subr/v cc sym/v ! as data/d as expr/d as lex/d as list/d as main/d as out/d as subr/d as sym/d ! ! Now, the 8086-specific modules ! cc addr.86/v cc ext.86/v cc machin.86/v cc pst.86/v ! as addr/d as ext/d as machin/d as pst/d ! ! Link it ! link as8086,as8086=data,expr,lex,list/b:2000// main,out,subr,sym addr,ext,machin,pst c:suport,c:clib // ^Z -h- 85.H Sat Jan 02 18:00:53 1982 _DBB0:85.H;2 /* * Symbol types. */ #define S_INH 50 /* One byte */ #define S_RST 51 /* Restart */ #define S_ADI 52 /* One byte immediate */ #define S_ADD 53 /* One reg. */ #define S_JMP 54 /* Jumps, calls, etc. */ #define S_INR 55 /* Reg. dest. */ #define S_LXI 56 /* Word immediate */ #define S_LDAX 57 /* B or D */ #define S_INX 58 /* Word reg. dest. */ #define S_PUSH 59 /* Push, pop */ #define S_MOV 60 /* Mov */ #define S_MVI 61 /* Mvi */ #define S_REG 62 /* Registers */ /* * Registers. */ #define B 0 #define C 1 #define D 2 #define E 3 #define H 4 #define L 5 #define M 6 #define A 7 #define SP 8 #define PSW 9 -h- 86.H Sat Jan 02 18:00:53 1982 _DBB0:86.H;2 /* * Symbol types. */ #define S_INH 50 /* One byte */ #define S_INT 51 /* Interrupt */ #define S_JMP 52 /* Jumps */ #define S_CALL 53 /* Call */ #define S_XOP 54 /* Xcall and xjmp */ #define S_RET 55 /* Return */ #define S_MUL 56 /* Mul, div */ #define S_MULB 57 /* Ditto, but byte op. */ #define S_DOP 59 /* Doubles */ #define S_IN 60 /* I/O instructions */ #define S_PUSH 61 /* Push/pop */ #define S_SHL 62 /* Shift */ #define S_MOV 63 /* Moves */ #define S_XCHG 64 /* Exchanges */ #define S_CMP 65 /* Compare */ #define S_CMPB 66 /* Compare bytes */ #define S_LEA 67 /* Load address */ #define S_SHLB 68 /* Shifts, byte */ #define S_OVER 69 /* Overide prefix */ #define S_SOP 70 /* Single op. */ #define S_SOPB 71 /* Ditto, but bytes */ #define S_MOVB 72 /* Move bytes */ #define S_ESC 73 /* Escape */ /* * These types are also used as * address modes. * The order is, therefore, very * critical. */ #define S_BXSI 80 #define S_BXDI 81 #define S_BPSI 82 #define S_BPDI 83 #define S_SI 84 #define S_DI 85 #define S_BP 86 #define S_BX 87 #define S_IDX 88 #define S_IMMED 91 #define S_R16 92 #define S_R8 93 #define S_SEG 94 #define S_FLAG 95 /* * Registers. */ #define AX 0 #define CX 1 #define DX 2 #define BX 3 #define SP 4 #define BP 5 #define SI 6 #define DI 7 #define AL 0 #define CL 1 #define DL 2 #define BL 3 #define AH 4 #define CH 5 #define DH 6 #define BH 7 #define ES 0 #define CS 1 #define SS 2 #define DS 3 -h- ADDR.86 Sat Jan 02 18:00:53 1982 _DBB0:ADDR.86;2 #include #include "asm.h" #include "86.h" int modes[] = { (1<e_mode = S_IMMED; } else if (c == '(') { addrx(esp); esp->e_flag = 0; esp->e_addr = 0; esp->e_base.e_ap = NULL; } else { unget(c); expr(esp, 0); if ((c = getnb()) == '(') { addrx(esp); if (esp->e_mode == S_IDX) aerr(); } else unget(c); } return (esp->e_mode); } /* * Read in the index part of an address * expression. Check for indexing by bad * registers, indexing twice by a register * and the special things. */ addrx(esp) struct expr *esp; { register struct sym *sp; register c, i; int mask, mode; char id[NCPS]; mode = 0; do { getid(id, -1); if ((sp = lookup(id, 0)) == NULL) aerr(); else { if (sp->s_type==S_R16 && sp->s_addr<8) mask = 1 << sp->s_addr; else aerr(); if ((mode&mask) != 0) /* Same twice */ aerr(); mode |= mask; } } while ((c = getnb()) == ','); if (c != ')') qerr(); for (i=0; i<9; ++i) { if (mode == modes[i]) { esp->e_mode = S_BXSI + i; return; } } esp->e_mode = S_USER; aerr(); } -h- ASM.H Sat Jan 02 18:00:53 1982 _DBB0:ASM.H;2 /* * Assembler header. */ #define NCPS 8 /* Chars. per symbol */ #define HUGE 1000 /* A huge number */ #define NERR 10 /* Errors per line */ #define NINPUT 128 /* Input buffer size */ #define NCODE 128 /* Listing code buffer size */ #define NTIT 64 /* Title buffer size */ #define NHASH 64 /* Buckets in hash table */ #define HMASK 077 /* Hash mask */ #define NLPP 60 /* Lines per page */ #define NLIST 0 /* No listing */ #define SLIST 1 /* Source only */ #define ALIST 2 /* Address only */ #define CLIST 3 /* Code */ #define dot (&sym[0]) /* Dot, current loc */ #define dda (&sym[1]) /* Dda, default data area */ typedef unsigned addr_t; struct area { struct area *a_ap; /* Area link */ struct sym *a_sp; /* Symbol back link */ int a_ref; /* Ref. number */ addr_t a_size; /* Area size */ addr_t a_fuzz; /* Area fuzz (bropt) */ int a_flag; /* Area flags */ }; #define A_D 00 /* D space */ #define A_I 01 /* I space */ #define A_PRV 00 /* Private */ #define A_SHR 02 /* Shared */ #define A_CON 00 /* Concatenating */ #define A_OVR 04 /* Overlaying */ struct sym { struct sym *s_sp; /* Hash link */ char s_id[NCPS]; /* Name */ char s_type; /* Symbol subtype */ char s_flag; /* Symbol flags */ struct area *s_area; /* Area line, 0 if absolute */ int s_ref; /* Ref. number */ addr_t s_addr; /* Address */ }; #define S_GBL 01 /* Global */ #define S_ASG 02 /* Assigned */ #define S_MDF 04 /* Mult. def */ #define S_END 010 /* End mark for pst. */ #define S_NEW 0 /* New name */ #define S_USER 1 /* User name */ #define S_AREA 2 /* Area name */ #define S_BYTE 3 /* .byte */ #define S_WORD 4 /* .word */ #define S_ASCII 5 /* .ascii */ #define S_ASCIZ 6 /* .asciz */ #define S_BLK 7 /* .blkb or .blkw */ #define S_INCL 8 /* .include */ #define S_DAREA 9 /* .area */ #define S_GLOBL 10 /* .globl */ #define S_PAGE 11 /* .page */ #define S_TITLE 12 /* .title */ #define S_IF 13 /* .if */ #define S_ELSE 14 /* .else */ #define S_ENDIF 15 /* .endif */ struct tsym { struct tsym *t_fp; /* Link to next */ struct area *t_area; /* Area */ addr_t t_addr; /* Address */ }; struct tsymp { struct tsym *tp_fp; /* Symbol for `n'f */ struct tsym *tp_bp; /* Symbol for `n'b */ struct tsym *tp_lfp; /* First symbol */ struct tsym *tp_llp; /* Last symbol */ }; extern int flevel; extern int tlevel; extern char *new(); extern struct sym sym[]; extern int line; extern int page; extern int lop; extern int pass; extern int lflag; extern int gflag; extern int oflag; extern int eflag; extern addr_t laddr; extern addr_t fuzz; extern int lmode; extern struct sym *symhash[NHASH]; extern struct area *areap; extern char *ep; extern char eb[NERR]; extern char *ip; extern char ib[NINPUT]; extern char *cp; extern char cb[NCODE]; extern char tb[NTIT]; extern struct tsymp tsymp[10]; extern FILE *lfp; extern FILE *ofp; extern FILE *sfp; extern char *cpu; extern char *dsft; extern char ctype[]; #define LETTER 0 #define DIGIT 1 #define BINOP 2 #define ETC 3 #define ILL 4 #define SPACE 5 /* * Expression. */ struct expr { char e_mode; /* Address mode */ char e_flag; /* Symbol baseed flag */ addr_t e_addr; /* Address */ union { struct area *e_ap; struct sym *e_sp; } e_base; /* Rel. base */ }; -h- DATA.C Sat Jan 02 18:00:53 1982 _DBB0:DATA.C;2 #include #include "asm.h" int flevel; int tlevel; int line; addr_t fuzz; int page; int lop; int pass; int lflag; int oflag; int gflag; int eflag; addr_t laddr; int lmode; char *ep; char eb[NERR]; char *ip; char ib[NINPUT]; char *cp; char cb[NCODE]; char tb[NTIT]; struct tsymp tsymp[10]; struct sym symhash[NHASH]; struct area *areap; FILE *lfp; FILE *ofp; FILE *sfp; 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 }; -h- EXPR.C Sat Jan 02 18:00:53 1982 _DBB0:EXPR.C;2 #include #include "asm.h" /* * Read an expression. The value of the * expression and its associated relocation * information is stored into the `expr' * structure supplied by the user. `N' is * a firewall priority; all top level calls * (from the user) should be made with `n' * set to 0. */ expr(esp, n) register struct expr *esp; { register c, p; struct area *ap; struct expr re; term(esp); if (esp->e_mode != S_USER) return; while (ctype[c = getnb()] == BINOP) { if ((p = oprio(c)) <= n) break; if ((c == '>' || c == '<') && c != get()) qerr(); expr(&re, p); if (c == '+') { if (esp->e_base.e_ap == NULL) { esp->e_flag = re.e_flag; esp->e_base.e_ap = re.e_base.e_ap; } else if (re.e_base.e_ap != NULL) rerr(); esp->e_addr += re.e_addr; } else if (c == '-') { if ((ap = re.e_base.e_ap) != NULL) if (esp->e_flag || re.e_flag || esp->e_base.e_ap != ap) rerr(); esp->e_addr -= re.e_addr; } else { abscheck(esp); abscheck(&re); switch (c) { case '*': esp->e_addr *= re.e_addr; break; case '/': esp->e_addr /= re.e_addr; break; case '&': esp->e_addr &= re.e_addr; break; case '|': esp->e_addr |= re.e_addr; break; case '<': esp->e_addr <<= re.e_addr; break; case '>': esp->e_addr >>= re.e_addr; break; } } } unget(c); } /* * Read an absolute expression. */ absexpr() { struct expr e; expr(&e, 0); abscheck(&e); return (e.e_addr); } /* * Read a term. * Handles unary operators, brackets, * constants in decimal, octal or hexadecimal * and identifiers. This routine is also * responsible for setting the relocation type * to symbol based (e.flag != 0) on global * references. */ term(esp) register struct expr *esp; { register c, n; struct area *ap; char id[NCPS]; struct sym *sp; struct tsym *tp; int r, v; c = getnb(); if (c == '[') { expr(esp, 0); if (getnb() != ']') qerr(); return; } if (c == '-') { expr(esp, 100); abscheck(esp); esp->e_addr = -esp->e_addr; return; } if (c == '~') { expr(esp, 100); abscheck(esp); esp->e_addr = ~esp->e_addr; return; } if (c == '\'') { esp->e_mode = S_USER; esp->e_flag = 0; esp->e_base.e_ap = NULL; esp->e_addr = getmap(-1); return; } if (ctype[c] == DIGIT) { esp->e_mode = S_USER; esp->e_flag = 0; esp->e_base.e_ap = NULL; 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].tp_fp; else tp = tsymp[n].tp_bp; if (tp != NULL) { esp->e_base.e_ap = tp->t_area; esp->e_addr = tp->t_addr; return; } } err('u'); esp->e_addr = 0; return; } unget(c); esp->e_addr = n; return; } if (ctype[c] == LETTER) { esp->e_mode = S_USER; esp->e_flag = 0; esp->e_base.e_ap = NULL; esp->e_addr = 0; getid(id, c); if ((sp = lookup(id, gflag)) != NULL) { if (sp->s_type == S_NEW) { if ((sp->s_flag&S_GBL) != 0) { esp->e_flag = 1; esp->e_base.e_sp = sp; return; } err('u'); return; } esp->e_mode = sp->s_type; esp->e_base.e_ap = sp->s_area; esp->e_addr = sp->s_addr; return; } err('u'); return; } qerr(); } /* * If `c' is a legal radix `r' digit * return its value; otherwise return * -1. */ 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); } /* * Check if the value of the supplied * expression is absolute; if not give * a relocation error and force the * type to absolute. */ abscheck(esp) register struct expr *esp; { if (esp->e_flag || esp->e_base.e_ap != NULL) { rerr(); esp->e_flag = 0; esp->e_base.e_ap = NULL; } } /* * Return the priority of the binary * operator `c'. */ oprio(c) register c; { if (c == '*' || c == '%') return (10); if (c == '+' || c == '-') return (7); if (c == '<' || c == '>') return (5); if (c == '&') return (3); if (c == '|') return (1); return (0); } -h- EXT.85 Sat Jan 02 18:00:53 1982 _DBB0:EXT.85;2 #include #include "asm.h" char *cpu = "Intel 8085"; char *dsft = "s"; -h- EXT.86 Sat Jan 02 18:00:53 1982 _DBB0:EXT.86;2 #include #include "asm.h" char *cpu = "Intel 8086"; char *dsft = "s"; -h- LEX.C Sat Jan 02 18:00:53 1982 _DBB0:LEX.C;2 #include #include "asm.h" getid(id, c) register c; char *id; { register char *p; if (c < 0) { c = getnb(); if (ctype[c] != LETTER) qerr(); } 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; } getmap(d) { register c, n, v; if ((c = get()) == '\0') qerr(); if (c == d) return (-1); if (c == '\\') { c = get(); switch (c) { case 'b': c = '\b'; break; case 'f': c = '\f'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': n = 0; v = 0; while (++n<=3 && c>='0' && c<='7') { v = (v<<3) + c - '0'; c = get(); } unget(c); c = v; break; } } return (c); } getline() { if (fgetss(ib, sizeof ib, sfp) == NULL) return (0); return (1); } more() { register c; c = getnb(); unget(c); if (c == '\0' || c == '/' || c == ';') return (0); return (1); } -h- LIST.C Sat Jan 02 18:00:53 1982 _DBB0:LIST.C;2 #include #include "asm.h" /* * Copy a block of source and code to * the listing file. If no listing file or * the current line is not to be listed * just return. Multiple code bytes get * put out on extra lines after the source * line. There is no way to output words * or (gasp) hexadecimal. */ 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, " %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); } } /* * Send up to four bytes of code to the * listing. A subroutine of `list'. */ list1(wp, nb, f) register char *wp; register nb; { register i; if (nb > 4) nb = 4; for (i=0; i= NLPP) { fprintf(lfp, "\fAssembler (%s), page %d.\n", cpu, ++page); fprintf(lfp, "%s\n\n", tb); lop = 4; } } -h- MACHIN.85 Sat Jan 02 18:00:53 1982 _DBB0:MACHIN.85;3 /*)BUILD $(PROGRAM) = ASM85 # untested $(INCLUDE) = { asm.h 85.h } $(FILES) = { data.c expr.c lex.c list.c main.c out.c subr.c sym.c ext.85 machin.85 pst.85 } */ #include #include "asm.h" #include "85.h" /* * Process machine ops. */ machine(sp) struct sym *sp; { register unsigned op, rd, rs; struct expr e; op = sp->s_addr; switch (sp->s_type) { case S_INH: if (flevel) break; outab(op); break; case S_RST: rd = absexpr(); if (flevel) break; if (rd > 7) aerr(); out3(op, rd); break; case S_ADI: expr(&e, 0); if (flevel) break; outab(op); outrb(&e, 0); break; case S_ADD: rd = reg(); if (flevel) break; if (rd > A) aerr(); outab(op | rd); break; case S_JMP: expr(&e, 0); if (flevel) break; outab(op); outrw(&e, 0); break; case S_INR: rd = reg(); if (flevel) break; if (rd > A) aerr(); out3(op, rd); break; case S_LXI: rd = reg(); comma(); expr(&e, 0); if (flevel) break; out3(op, regpair(rd, SP)); outrw(&e, 0); break; case S_LDAX: rd = reg(); if (flevel) break; if (rd!=B && rd!=D) aerr(); out3(op, rd); break; case S_INX: rd = reg(); if (flevel) break; out3(op, regpair(rd, SP)); break; case S_PUSH: rd = reg(); if (flevel) break; out3(op, regpair(rd, PSW)); break; case S_MOV: rd = reg(); comma(); rs = reg(); if (flevel) break; if (rs>A || rd>A) aerr(); outab(op | rs | (rd<<3)); break; case S_MVI: rd = reg(); comma(); expr(&e, 0); if (flevel) break; if (rd > A) aerr(); out3(op, rd); outrb(&e, 0); break; default: err('o'); } } /* * Is the next character a comma ? */ comma() { if (getnb() != ',') qerr(); } /* * Output a | (b<<3); */ out3(a, b) { outab(a | (b<<3)); } /* * Make sure that `r' is usable as a * register pair specifier. The extra * register (code 3) is `s'. */ regpair(r, s) { if (r < M) { if ((r&01) != 0) aerr(); } else if (r == s) r = 6; else aerr(); return (r); } /* * Read a register name. */ reg() { register struct sym *sp; char id[NCPS]; getid(id, -1); if ((sp = lookup(id, 0))==NULL || sp->s_type!=S_REG) { aerr(); return (0); } return (sp->s_addr); } /* * Dummy machine specific init. */ minit() { } -h- MACHIN.86 Sat Jan 02 18:00:53 1982 _DBB0:MACHIN.86;3 /*)BUILD PROGRAM = ASM86 # untested INCLUDE = { asm.h 86.h } FILES = { data.c expr.c lex.c list.c main.c out.c subr.c sym.c ext.86 machin.86 pst.86 } */ #include #include "asm.h" #include "86.h" /* * Many magic numbers. * In most cases there are machine * opcodes and/or bits. */ #define MULDIV 0366 #define INCDEC 0376 #define NOTNEG 0366 #define IDREG 0100 #define AAM 0324 #define AAD 0325 #define APB 0012 #define S 02 #define SEG 0046 #define SHL 0320 #define TESTB 0204 #define TESTAB 0250 #define TESTMB 0366 #define TESTW 0205 #define TESTAW 0251 #define TESTMW 0367 #define XCHGR 0220 #define W 01 #define D 02 #define V 02 #define CMPB 0246 #define CMPW 0247 #define DXOP 0202 #define XOP 0377 #define DCALL 0350 #define ICALL 0377 #define LJMP 0351 #define JMP 0353 #define IJMP 0377 #define DJMP 0351 #define INT3 0314 #define INT 0315 #define PUSHSR 0006 #define PUSHR 0120 #define PUSHF 0234 #define PUSH 0377 #define POPSR 0007 #define POPR 0130 #define POPF 0235 #define POP 0217 #define ESC 0330 #define MOVB 0244 #define MOVSEG 0214 #define MVIB 0260 #define MVIW 0270 #define MVI 0306 #define MOVAM 0242 #define MOVMA 0240 #define NB 128 int *bp; int bm; int bb[NB]; /* * Process a machine op. */ machine(sp) struct sym *sp; { register op, t1, t2; struct expr e1, e2; int disp, flag, ob, rf; addr_t a; op = sp->s_addr; switch (sp->s_type) { case S_INH: if (flevel) break; outab(op); if (op==AAM || op==AAD) outab(APB); break; case S_INT: expr(&e1, 0); if (flevel) break; if (isabsn(&e1, 3)) outab(INT3); else { outab(INT); outrb(&e1, 0); } break; case S_OVER: t1 = addr(&e1); if (flevel) break; if (t1 == S_SEG) { out3(SEG, e1.e_addr); break; } aerr(); break; case S_RET: if (more()) { expr(&e1, 0); if (flevel) break; outab(op-1); outrw(&e1, 0); } else if (flevel == 0) outab(op); break; case S_PUSH: t1 = addr(&e1); if (flevel) break; if (t1 == S_SEG) { if (op == PUSH) out3(PUSHSR, e1.e_addr); else { if (e1.e_addr == CS) aerr(); out3(POPSR, e1.e_addr); } break; } if (t1 == S_R16) { outab(((op==PUSH) ? PUSHR : POPR) | e1.e_addr); break; } if (t1 == S_FLAG) { outab((op==PUSH) ? PUSHF : POPF); break; } outgen(op, ((op==PUSH) ? 6 : 0), &e1); break; case S_IN: t1 = addr(&e1); if (flevel) break; if (t1 == S_IDX) { /* (dx) */ outab(op | 010); break; } if (t1 == S_USER) { outab(op); outrb(&e1, 0); break; } aerr(); break; case S_SHL: case S_SHLB: t1 = addr(&e1); comma(); t2 = addr(&e2); if (flevel) break; ob = SHL; if (sp->s_type == S_SHL) ob |= W; bytecheck(ob, t2, 0); if (t1==S_R8 && e1.e_addr==CL) ob |= V; else if (t1!=S_IMMED || !isabsn(&e1, 1)) aerr(); outgen(ob, op, &e2); break; case S_JMP: t1 = addr(&e1); if (flevel) break; if (t1 != S_USER) { outgen(IJMP, 4, &e1); break; } if (e1.e_flag || e1.e_base.e_ap!=dot->s_area) { outab(DJMP); outrw(&e1, 1); break; } if (pass == 0) { dot->s_addr += 3; if (op != JMP) dot->s_addr += 2; } else if (pass == 1) { if (e1.e_addr >= dot->s_addr) e1.e_addr -= fuzz; dot->s_addr += 2; disp = e1.e_addr - dot->s_addr; flag = 0; if (disp<-128 || disp>127) ++flag; setbit(flag); if (flag) { ++dot->s_addr; if (op != JMP) dot->s_addr += 2; } } else { if (getbit()) { disp = e1.e_addr - dot->s_addr - 3; if (op != JMP) { outab(op ^ 01); outab(3); disp -= 2; } outab(LJMP); outaw(disp); } else { disp = e1.e_addr - dot->s_addr - 2; outab(op); outab(disp); } } break; case S_CALL: t1 = addr(&e1); if (flevel) break; if (t1 != S_USER) outgen(ICALL, 2, &e1); else { outab(DCALL); outrw(&e1, 1); } break; case S_XOP: if (addr(&e1) != S_USER) { if (flevel) break; outgen(XOP, op, &e1); } else { if (getnb() != '$') qerr(); expr(&e2, 0); if (flevel) break; out3(DXOP, op); outrw(&e2, 0); outrw(&e1, 0); } break; case S_CMPB: if (!more()) { if (flevel == 0) outab(CMPB); break; } case S_CMP: case S_DOP: addr((sp->s_type!=S_DOP) ? &e2 : &e1); comma(); addr((sp->s_type!=S_DOP) ? &e1 : &e2); if (flevel) break; t1 = e1.e_mode; t2 = e2.e_mode; bytecheck(op, t1, t2); if (t1 == S_IMMED) { if (isa(&e2)) { if (op == TESTW) op = TESTAW; else if (op == TESTB) op = TESTAB; else op |= 04; outab(op); } else { if (op==TESTW || op==TESTB) { rf = 0; if (op == TESTW) op = TESTMW; else op = TESTMB; } else { rf = (op&070)>>3; op = (op&W)|0200; } outgen(op, rf, &e2); } if ((op&W) == 0) outrb(&e1, 0); else outrw(&e1, 0); break; } if (t1==S_R8 || t1==S_R16) { if (op!=TESTB && op!=TESTW) /* Swap test is ok */ op |= D; outgen(op, e1.e_addr, &e2); break; } outgen(op, e2.e_addr, &e1); break; case S_XCHG: t1 = addr(&e1); comma(); t2 = addr(&e2); if (flevel) break; bytecheck(op, t1, t2); if (t1==S_R16 && t2==S_R16) { if (e1.e_addr == AX) { outab(XCHGR | e2.e_addr); break; } if (e2.e_addr == AX) { outab(XCHGR | e1.e_addr); break; } } if (t1==S_R8 || t1==S_R16) { outgen(op, e1.e_addr, &e2); break; } if (t2==S_R8 || t2==S_R16) { outgen(op, e2.e_addr, &e1); break; } aerr(); break; case S_SOP: case S_SOPB: t1 = addr(&e1); if (flevel) break; ob = (op < 2) ? INCDEC : NOTNEG; if (sp->s_type == S_SOP) ob |= W; bytecheck(ob, t1, 0); if (op<2 && t1==S_R16) outab(IDREG | (op<<3) | e1.e_addr); else outgen(ob, op, &e1); break; case S_ESC: addr(&e1); if (flevel) break; outgen(ESC, 0, &e1); break; case S_LEA: t1 = addr(&e1); comma(); t2 = addr(&e2); if (flevel) break; if ((t1>S_USER && t1S_BX || t2!=S_R16) aerr(); outgen(op, e2.e_addr, &e1); break; case S_MOVB: if (!more()) { if (flevel == 0) outab(MOVB); break; } case S_MOV: t1 = addr(&e1); comma(); t2 = addr(&e2); if (flevel) break; bytecheck(op, t1, t2); if (t1 == S_IMMED) { if (t2 == S_R8) { outab(MVIB | e2.e_addr); outrb(&e1, 0); break; } if (t2 == S_R16) { outab(MVIW | e2.e_addr); outrw(&e1, 0); break; } outgen((MVI|(op&W)), 0, &e2); if ((op&W) == 0) outrb(&e1, 0); else outrw(&e1, 0); break; } if (isa(&e1) && t2==S_USER) { outab(MOVAM|(op&W)); outrw(&e2, 0); break; } if (t1==S_USER && isa(&e2)) { outab(MOVMA|(op&W)); outrw(&e1, 0); break; } if (t1==S_SEG || t2==S_SEG) op = MOVSEG; if (t1>=S_R16 && t1<=S_SEG) /* From reg */ outgen(op, e1.e_addr, &e2); else outgen(op|D, e2.e_addr, &e1); break; case S_MUL: case S_MULB: t1 = addr(&e1); comma(); t2 = addr(&e2); if (flevel) break; ob = MULDIV; if (sp->s_type == S_MUL) ob |= W; bytecheck(ob, t1, t2); if (!isa(&e2)) aerr(); outgen(ob, op, &e1); break; default: err('o'); } } /* * The next character must be a * comma. */ comma() { if (getnb() != ',') qerr(); } /* * Output `general' format instructions. * `Op' is the opcode, `r' is the general * register (bits 3-5 of the postbyte) and * `esp' is an address. * The address must not be the flags, a * segment register, (dx) or an immediate * thing. */ outgen(op, r, esp) register struct expr *esp; { register disp, mode; outab(op); mode = esp->e_mode; if (mode==S_IDX || mode==S_IMMED || mode>S_R8) { aerr(); return; } disp = esp->e_addr; if (mode==S_R8 || mode==S_R16) { outab(0300 + (r<<3) + disp); return; } if (mode == S_USER) { outab(0006 + (r<<3)); outrw(esp, 0); return; } mode -= S_BXSI; if (esp->e_flag==0 && esp->e_base.e_ap==NULL) { /* Abs */ if (mode!=6 && disp==0) { outab((r<<3) + mode); return; } if (disp>=-128 && disp<=127) { outab(0100 + (r<<3) + mode); outab(disp); return; } } outab(0200 + (r<<3) + mode); outrw(esp, 0); } /* * Output a byte of the general form * `bbbbbaaa'. A number of common instructions * have this format. */ out3(a, b) { outab(a | (b<<3)); } /* * Given an opcode with a valid `W' bit, * insure that the types `t1' and `t2' are * acceptable. This means that `t1' and `t2' * must be the same width and (if a byte * word or segment register) compatable * with the opcode. */ bytecheck(op, t1, t2) register op, t1, t2; { int bad; bad = 0; if (t1 == S_R8) { if ((op&W) != 0) ++bad; if (t2==S_R16 || t2==S_SEG) ++bad; } if (t1==S_R16 || t2==S_SEG) { if ((op&W) == 0) ++bad; if (t2 == S_R8) ++bad; } if (t2 == S_R8) { if ((op&W) != 0) ++bad; if (t1==S_R16 || t1==S_SEG) ++bad; } if (t2==S_R16 || t2==S_SEG) { if ((op&W) == 0) ++bad; if (t1 == S_R8) ++bad; } if (bad) aerr(); } /* * Is this an accumulator ? */ isa(esp) register struct expr *esp; { if (esp->e_mode==S_R8 && esp->e_addr==AL) return (1); if (esp->e_mode==S_R16 && esp->e_addr==AX) return (1); return (0); } /* * Machine specific initialization. * Set up the bit table. */ minit() { bp = bb; bm = 1; } /* * Store `b' in the next slot of the * bit table. * If no room, throw it away. */ setbit(b) { if (bp >= &bb[NB]) return; if (b) *bp |= bm; bm <<= 1; if (bm == 0) { bm = 1; ++bp; } } /* * Get the next bit from the bit * table. * If none left, return a `1'. * This will get the long form of * branches. */ getbit() { register f; if (bp >= &bb[NB]) return (1); f = *bp & bm; bm <<= 1; if (bm == 0) { bm = 1; ++bp; } return (f); } /* * Check if the value of an expression * is absolute and has value `n'. Return * true if yes. Used to check shifts and * interrupt instructions. */ isabsn(esp, n) register struct expr *esp; { if (esp->e_flag==0 && esp->e_base.e_ap==NULL && esp->e_addr==n) return (1); return (0); } -h- MAIN.C Sat Jan 02 18:00:53 1982 _DBB0:MAIN.C;2 #include #include "asm.h" main(argc, argv) char *argv[]; { register char *p; register c, i; struct area *ap; struct tsym *tp; char *fn; FILE *afile(); fn = NULL; for (i=1; ia_fuzz = 0; ap->a_size = 0; ap = ap->a_ap; } fuzz = 0; minit(); dot->s_addr = 0; dot->s_area = dda->s_addr; /* * Reset f-b table. */ if (pass != 0) { for (i=0; i<10; ++i) { tsymp[i].tp_bp = NULL; tsymp[i].tp_fp = tsymp[i].tp_lfp; } } while (getline()) { ++line; cp = cb; ep = eb; ip = ib; eflag = 0; setexit(); if (eflag == 0) asm(); if (pass == 2) { diag(); list(); } } newdot(dot->s_area); /* Flush area info */ if (flevel || tlevel) err('i'); } if (oflag) outchk(HUGE, HUGE); /* Flush */ } asm() { register struct sym *sp; register struct tsym *tp; register c; struct tsymp *tsp; struct area *ap; struct expr e1; char id[NCPS]; char *p; int d, n, uaf, uf; laddr = dot->s_addr; lmode = SLIST; loop: while ((c = getnb()) == ';') ; if (c == 0 || c == '/') return; if (ctype[c] == DIGIT) { if (get() != ':') qerr(); if (flevel) goto loop; tsp = &tsymp[c-'0']; if (pass == 0) { tp = (struct tsym *) new(sizeof(struct tsym)); tp->t_fp = NULL; tp->t_area = dot->s_area; tp->t_addr = dot->s_addr; if (tsp->tp_lfp == NULL) tsp->tp_lfp = tp; else tsp->tp_llp->t_fp = tp; tsp->tp_llp = tp; } else { tp = tsp->tp_fp; if (pass == 1) { fuzz = tp->t_addr - dot->s_addr; tp->t_area = dot->s_area; tp->t_addr = dot->s_addr; } else phase(tp->t_area, tp->t_addr); } tp = tsp->tp_fp; tsp->tp_bp = tp; tsp->tp_fp = tp->t_fp; goto loop; } if (ctype[c] != LETTER) qerr(); getid(id, c); c = getnb(); if (c == ':') { if (flevel) goto loop; sp = lookup(id, 1); if (sp == dot) err('.'); if (pass == 0) if (sp->s_type!=S_NEW && (sp->s_flag&S_ASG)==0) sp->s_flag |= S_MDF; if (pass != 2) { fuzz = sp->s_addr - dot->s_addr; sp->s_type = S_USER; sp->s_area = dot->s_area; sp->s_addr = dot->s_addr; } else { if ((sp->s_flag&S_MDF) != 0) err('m'); phase(sp->s_area, sp->s_addr); } lmode = ALIST; goto loop; } if (c == '=') { expr(&e1, 0); if (flevel) goto loop; sp = lookup(id, 1); if (sp == dot) { if (e1.e_flag || e1.e_base.e_ap != dot->s_area) err('.'); if (e1.e_addr < dot->s_addr) err('-'); } else if (sp->s_type!=S_NEW && (sp->s_flag&S_ASG)==0) err('m'); sp->s_type = S_USER; sp->s_area = e1.e_base.e_ap; sp->s_addr = laddr = e1.e_addr; sp->s_flag |= S_ASG; lmode = ALIST; goto loop; } unget(c); lmode = flevel ? SLIST : CLIST; if ((sp = lookup(id, 0)) == NULL) { err('o'); return; } switch (sp->s_type) { case S_BYTE: case S_WORD: do { expr(&e1, 0); if (flevel == 0) { if (sp->s_type == S_BYTE) outrb(&e1, 0); else outrw(&e1, 0); } } while ((c = getnb()) == ','); unget(c); break; case S_ASCII: case S_ASCIZ: if ((d = getnb()) == '\0') qerr(); while ((c = getmap(d)) >= 0) if (flevel == 0) outab(c); if (sp->s_type==S_ASCIZ && flevel==0) outab(0); break; case S_BLK: expr(&e1, 0); if (flevel) break; if (e1.e_flag || e1.e_base.e_ap!=NULL) err('a'); else dot->s_addr += e1.e_addr*sp->s_addr; lmode = SLIST; break; case S_TITLE: p = tb; if (c = getnb()) { do { if (p < &tb[NTIT-1]) *p++ = c; } while (c = get()); } *p = 0; unget(c); case S_PAGE: lop = NLPP; lmode = NLIST; break; case S_GLOBL: do { getid(id, -1); if (flevel == 0) { sp = lookup(id, 1); sp->s_flag |= S_GBL; } } while ((c = getnb()) == ','); unget(c); lmode = SLIST; break; case S_DAREA: getid(id, -1); uaf = 0; if ((c = getnb()) == ',') { ++uaf; uf = absexpr(); } else unget(c); if (flevel) break; sp = lookup(id, 1); if (sp->s_type == S_NEW) { if ((sp->s_flag&S_GBL) != 0) aerr(); ap = (struct area *) new(sizeof(struct area)); sp->s_type = S_AREA; sp->s_addr = ap; ap->a_ap = areap; areap = ap; ap->a_sp = sp; ap->a_size = 0; ap->a_fuzz = 0; ap->a_flag = uaf ? uf : (A_D|A_PRV|A_CON); newdot(ap); } else if (sp->s_type == S_AREA) { ap = sp->s_addr; if (uaf && uf != ap->a_flag) aerr(); newdot(ap); } else aerr(); lmode = SLIST; break; case S_IF: n = absexpr(); if (flevel==0 && n==0) ++tlevel; else ++flevel; lmode = ALIST; laddr = n; break; case S_ELSE: if (tlevel) { --tlevel; ++flevel; } else if (flevel) { if (flevel == 1) { ++tlevel; --flevel; } } else err('i'); lmode = SLIST; break; case S_ENDIF: if (tlevel) --tlevel; else if (flevel) --flevel; else err('i'); lmode = SLIST; break; default: machine(sp); } goto loop; } FILE * afile(fn, ft, wf) char *fn; char *ft; { register char *p1, *p2; register c; FILE *fp; char fb[40]; p1 = fn; while (c = *p1) { if (c == ';') { *p1 = 0; break; } ++p1; } p1 = fn; p2 = fb; while ((c = *p1++) && c != '.') *p2++ = c; *p2++ = '.'; p1 = ft; while (*p2++ = *p1++) ; if ((fp = fopen(fb, wf?"w":"r")) == NULL) { fprintf(stderr, "%s: cannot %s.\n", fb, wf?"create":"open"); exit(1); } return (fp); } newdot(nap) register struct area *nap; { register struct area *oap; oap = dot->s_area; oap->a_fuzz = fuzz; oap->a_size = dot->s_addr; fuzz = nap->a_fuzz; dot->s_area = nap; dot->s_addr = nap->a_size; if (oflag && pass==2) outchk(HUGE, HUGE); } usage() { fprintf(stderr, "Usage: as [-glo] file\n"); exit(1); } phase(ap, a) struct addr *ap; addr_t a; { if (ap != dot->s_area || a != dot->s_addr) err('p'); } -h- OUT.C Sat Jan 02 18:00:53 1982 _DBB0:OUT.C;2 #include #include "asm.h" #define R_WORD 0 /* 16 bit */ #define R_BYTE 01 #define R_AREA 0 /* Base type */ #define R_SYM 02 #define R_NORM 0 /* PC adjust */ #define R_PCR 04 #define R_DEF 00 /* Global def. */ #define R_REF 01 /* Global ref. */ #define R_REL 00 /* Relocatable */ #define R_ABS 02 /* Absolute */ #define R_GBL 00 /* Global */ #define R_LCL 04 /* Local */ #define NTXT 16 #define NREL 16 char txt[NTXT]; char rel[NREL]; char *txtp = { &txt[0] }; char *relp = { &rel[0] }; /* * Output absolute byte. */ outab(b) { if (pass == 2) { outlst(b); if (oflag) { outchk(1, 0); *txtp++ = lobyte(b); } } ++dot->s_addr; } /* * Output absolute word. * Low then high. */ outaw(w) { if (pass == 2) { outlst(lobyte(w)); outlst(hibyte(w)); if (oflag) { outchk(2, 0); *txtp++ = lobyte(w); *txtp++ = hibyte(w); } } dot->s_addr += 2; } /* * Output relocatable byte. */ outrb(esp, pcrf) register struct expr *esp; { register n, r; if (pass == 2) { outlst(esp->e_addr); if (oflag) { if (esp->e_flag==0 && esp->e_base.e_ap==NULL) { outchk(1, 0); *txtp++ = lobyte(esp->e_addr); } else { outchk(1, 4); *txtp++ = lobyte(esp->e_addr); r = R_BYTE; if (pcrf) r |= R_PCR; if (esp->e_flag) { n = esp->e_base.e_sp->s_ref; r |= R_SYM; } else n = esp->e_base.e_ap->a_ref; *relp++ = r; *relp++ = txtp - txt - 1; *relp++ = lobyte(n); *relp++ = hibyte(n); } } } ++dot->s_addr; } /* * Output relocatable word. * Low then high. */ outrw(esp, pcrf) register struct expr *esp; { register n, r; if (pass == 2) { outlst(lobyte(esp->e_addr)); outlst(hibyte(esp->e_addr)); if (oflag) { if (esp->e_flag==0 && esp->e_base.e_ap==NULL) { outchk(2, 0); *txtp++ = lobyte(esp->e_addr); *txtp++ = hibyte(esp->e_addr); } else { outchk(2, 4); *txtp++ = lobyte(esp->e_addr); *txtp++ = hibyte(esp->e_addr); r = R_WORD; if (pcrf) r |= R_PCR; if (esp->e_flag) { n = esp->e_base.e_sp->s_ref; r |= R_SYM; } else n = esp->e_base.e_ap->a_ref; *relp++ = r; *relp++ = txtp - txt - 2; *relp++ = lobyte(n); *relp++ = hibyte(n); } } } dot->s_addr += 2; } /* * Output a byte to the listing * buffer. */ outlst(b) { if (cp < &cb[NCODE]) *cp++ = b; } outchk(nt, nr) { register struct area *ap; if (txtp+nt > &txt[NTXT] || relp+nr > &rel[NREL]) { if (txtp > &txt[2]) { fprintf(ofp, "T"); out(txt, txtp-txt); fprintf(ofp, "\n"); txtp = txt; if (relp > rel) { fprintf(ofp, "R"); out(rel, relp-rel); fprintf(ofp, "\n"); relp = rel; } } } if (txtp == txt) { *txtp++ = lobyte(dot->s_addr); *txtp++ = hibyte(dot->s_addr); if ((ap = dot->s_area) != NULL) { *relp++ = R_WORD|R_AREA; *relp++ = 0; *relp++ = lobyte(ap->a_ref); *relp++ = hibyte(ap->a_ref); } } } /* * Walk through the symbol table and the * area list and put out the global * symbol information at the front of the * relocatable file. This routine is also * responsible for setting up the ref. * numbers in the symbols and areas. */ outgsd() { register struct area *ap; register struct sym *sp; register i; int narea, nglob, rn; narea = 0; ap = areap; while (ap != NULL) { ap->a_ref = narea; ++narea; ap = ap->a_ap; } nglob = 0; for (i = 0; i < NHASH; ++i) { sp = symhash[i]; while (sp != NULL) { if ((sp->s_flag&S_GBL) != 0) ++nglob; sp = sp->s_sp; } } fprintf(ofp, "H %d areas %d global symbols\n", narea, nglob); /* * Global relocatables. */ rn = 0; ap = areap; while (ap != NULL) { outarea(ap); for (i=0; is_area==ap && (sp->s_flag&S_GBL)!=0) { sp->s_ref = rn; ++rn; outsym(sp); } sp = sp->s_sp; } } ap = ap->a_ap; } /* * Global references and absolutes. */ for (i=0; is_area==NULL && (sp->s_flag&S_GBL)!=0) { sp->s_ref = rn; ++rn; outsym(sp); } sp = sp->s_sp; } } } /* * Output the relocatable item defining * an area. */ outarea(ap) register struct area *ap; { register char *p; register c; fprintf(ofp, "A "); p = &ap->a_sp->s_id[0]; while (p < &ap->a_sp->s_id[NCPS] && (c = *p++)) putc(c, ofp); fprintf(ofp, " size %o flags %o\n", ap->a_size, ap->a_flag); } /* * Output the relocatable item describing a * global symbol. */ outsym(sp) register struct sym *sp; { register char *p; register c; fprintf(ofp, "S "); p = &sp->s_id[0]; while (p < &sp->s_id[NCPS] && (c = *p++)) putc(c, ofp); fprintf(ofp, " %s", sp->s_type==S_NEW ? "Ref" : "Def"); fprintf(ofp, "%06o\n", sp->s_addr); } out(p, n) register char *p; register n; { while (n--) fprintf(ofp, " %03o", (*p++)&0377); } /* * Extract low half of a word. */ lobyte(n) { return (n&0377); } /* * Extract high half of a word. */ hibyte(n) { return ((n>>8)&0377); } -h- PST.85 Sat Jan 02 18:00:53 1982 _DBB0:PST.85;2 #include #include "asm.h" #include "85.h" struct sym sym[] = { 0, ".", S_USER, 0, NULL, 0, 0, 0, "_DATA", S_AREA, 0, NULL, 0, 0, 0, "b", S_REG, 0, NULL, 0, B, 0, "c", S_REG, 0, NULL, 0, C, 0, "d", S_REG, 0, NULL, 0, D, 0, "e", S_REG, 0, NULL, 0, E, 0, "h", S_REG, 0, NULL, 0, H, 0, "l", S_REG, 0, NULL, 0, L, 0, "m", S_REG, 0, NULL, 0, M, 0, "a", S_REG, 0, NULL, 0, A, 0, "sp", S_REG, 0, NULL, 0, SP, 0, "psw", S_REG, 0, NULL, 0, PSW, 0, ".byte", S_BYTE, 0, NULL, 0, 0, 0, ".word", S_WORD, 0, NULL, 0, 0, 0, ".ascii", S_ASCII, 0, NULL, 0, 0, 0, ".asciz", S_ASCIZ, 0, NULL, 0, 0, 0, ".blkb", S_BLK, 0, NULL, 0, 1, 0, ".blkw", S_BLK, 0, NULL, 0, 2, 0, ".page", S_PAGE, 0, NULL, 0, 0, 0, ".title", S_TITLE, 0, NULL, 0, 0, 0, ".globl", S_GLOBL, 0, NULL, 0, 0, 0, ".area", S_DAREA, 0, NULL, 0, 0, 0, ".if", S_IF, 0, NULL, 0, 0, 0, ".else", S_ELSE, 0, NULL, 0, 0, 0, ".endif", S_ENDIF, 0, NULL, 0, 0, 0, "xthl", S_INH, 0, NULL, 0, 0345, 0, "sphl", S_INH, 0, NULL, 0, 0371, 0, "xchg", S_INH, 0, NULL, 0, 0353, 0, "ret", S_INH, 0, NULL, 0, 0311, 0, "rc", S_INH, 0, NULL, 0, 0330, 0, "rnc", S_INH, 0, NULL, 0, 0320, 0, "rz", S_INH, 0, NULL, 0, 0310, 0, "rnz", S_INH, 0, NULL, 0, 0300, 0, "rp", S_INH, 0, NULL, 0, 0360, 0, "rm", S_INH, 0, NULL, 0, 0370, 0, "rpe", S_INH, 0, NULL, 0, 0350, 0, "rpo", S_INH, 0, NULL, 0, 0340, 0, "rim", S_INH, 0, NULL, 0, 0040, 0, "rlc", S_INH, 0, NULL, 0, 0007, 0, "rrc", S_INH, 0, NULL, 0, 0017, 0, "ral", S_INH, 0, NULL, 0, 0027, 0, "rar", S_INH, 0, NULL, 0, 0037, 0, "cma", S_INH, 0, NULL, 0, 0057, 0, "stc", S_INH, 0, NULL, 0, 0067, 0, "cmc", S_INH, 0, NULL, 0, 0077, 0, "daa", S_INH, 0, NULL, 0, 0047, 0, "ei", S_INH, 0, NULL, 0, 0373, 0, "di", S_INH, 0, NULL, 0, 0363, 0, "nop", S_INH, 0, NULL, 0, 0000, 0, "hlt", S_INH, 0, NULL, 0, 0166, 0, "sim", S_INH, 0, NULL, 0, 0060, 0, "rst", S_RST, 0, NULL, 0, 0307, 0, "in", S_ADI, 0, NULL, 0, 0333, 0, "out", S_ADI, 0, NULL, 0, 0323, 0, "adi", S_ADI, 0, NULL, 0, 0306, 0, "aci", S_ADI, 0, NULL, 0, 0316, 0, "sui", S_ADI, 0, NULL, 0, 0326, 0, "sbi", S_ADI, 0, NULL, 0, 0336, 0, "ani", S_ADI, 0, NULL, 0, 0346, 0, "xri", S_ADI, 0, NULL, 0, 0356, 0, "ori", S_ADI, 0, NULL, 0, 0366, 0, "cpi", S_ADI, 0, NULL, 0, 0376, 0, "add", S_ADD, 0, NULL, 0, 0200, 0, "adc", S_ADD, 0, NULL, 0, 0210, 0, "sub", S_ADD, 0, NULL, 0, 0220, 0, "sbb", S_ADD, 0, NULL, 0, 0230, 0, "ana", S_ADD, 0, NULL, 0, 0240, 0, "xra", S_ADD, 0, NULL, 0, 0250, 0, "ora", S_ADD, 0, NULL, 0, 0260, 0, "cmp", S_ADD, 0, NULL, 0, 0270, 0, "sta", S_JMP, 0, NULL, 0, 0062, 0, "lda", S_JMP, 0, NULL, 0, 0072, 0, "shld", S_JMP, 0, NULL, 0, 0042, 0, "lhld", S_JMP, 0, NULL, 0, 0052, 0, "jmp", S_JMP, 0, NULL, 0, 0303, 0, "jc", S_JMP, 0, NULL, 0, 0332, 0, "jnc", S_JMP, 0, NULL, 0, 0322, 0, "jz", S_JMP, 0, NULL, 0, 0312, 0, "jnz", S_JMP, 0, NULL, 0, 0302, 0, "jp", S_JMP, 0, NULL, 0, 0362, 0, "jm", S_JMP, 0, NULL, 0, 0372, 0, "jpe", S_JMP, 0, NULL, 0, 0352, 0, "jpo", S_JMP, 0, NULL, 0, 0342, 0, "call", S_JMP, 0, NULL, 0, 0315, 0, "cc", S_JMP, 0, NULL, 0, 0334, 0, "cnc", S_JMP, 0, NULL, 0, 0324, 0, "cz", S_JMP, 0, NULL, 0, 0314, 0, "cnz", S_JMP, 0, NULL, 0, 0304, 0, "cp", S_JMP, 0, NULL, 0, 0364, 0, "cm", S_JMP, 0, NULL, 0, 0374, 0, "cpe", S_JMP, 0, NULL, 0, 0354, 0, "cpo", S_JMP, 0, NULL, 0, 0344, 0, "inr", S_INR, 0, NULL, 0, 0004, 0, "dcr", S_INR, 0, NULL, 0, 0005, 0, "lxi", S_LXI, 0, NULL, 0, 0001, 0, "ldax", S_LDAX, 0, NULL, 0, 0012, 0, "stax", S_LDAX, 0, NULL, 0, 0002, 0, "inx", S_INX, 0, NULL, 0, 0003, 0, "dcx", S_INX, 0, NULL, 0, 0013, 0, "dad", S_INX, 0, NULL, 0, 0011, 0, "push", S_PUSH, 0, NULL, 0, 0305, 0, "pop", S_PUSH, 0, NULL, 0, 0301, 0, "mov", S_MOV, 0, NULL, 0, 0100, 0, "mvi", S_MVI, S_END, NULL, 0, 0006 }; -h- PST.86 Sat Jan 02 18:00:53 1982 _DBB0:PST.86;2 #include #include "asm.h" #include "86.h" struct sym sym[] = { 0, ".", S_USER, 0, NULL, 0, 0, 0, "_DATA", S_AREA, 0, NULL, 0, 0, 0, "es", S_SEG, 0, NULL, 0, 0, 0, "cs", S_SEG, 0, NULL, 0, 1, 0, "ss", S_SEG, 0, NULL, 0, 2, 0, "ds", S_SEG, 0, NULL, 0, 3, 0, "al", S_R8, 0, NULL, 0, 0, 0, "cl", S_R8, 0, NULL, 0, 1, 0, "dl", S_R8, 0, NULL, 0, 2, 0, "bl", S_R8, 0, NULL, 0, 3, 0, "ah", S_R8, 0, NULL, 0, 4, 0, "ch", S_R8, 0, NULL, 0, 5, 0, "dh", S_R8, 0, NULL, 0, 6, 0, "bh", S_R8, 0, NULL, 0, 7, 0, "flags", S_FLAG, 0, NULL, 0, 0, 0, "ax", S_R16, 0, NULL, 0, 0, 0, "cx", S_R16, 0, NULL, 0, 1, 0, "dx", S_R16, 0, NULL, 0, 2, 0, "bx", S_R16, 0, NULL, 0, 3, 0, "sp", S_R16, 0, NULL, 0, 4, 0, "bp", S_R16, 0, NULL, 0, 5, 0, "si", S_R16, 0, NULL, 0, 6, 0, "di", S_R16, 0, NULL, 0, 7, 0, ".byte", S_BYTE, 0, NULL, 0, 0, 0, ".word", S_WORD, 0, NULL, 0, 0, 0, ".ascii", S_ASCII, 0, NULL, 0, 0, 0, ".asciz", S_ASCIZ, 0, NULL, 0, 0, 0, ".blkb", S_BLK, 0, NULL, 0, 1, 0, ".blkw", S_BLK, 0, NULL, 0, 2, 0, ".page", S_PAGE, 0, NULL, 0, 0, 0, ".title", S_TITLE, 0, NULL, 0, 0, 0, ".globl", S_GLOBL, 0, NULL, 0, 0, 0, ".area", S_DAREA, 0, NULL, 0, 0, 0, ".if", S_IF, 0, NULL, 0, 0, 0, ".else", S_ELSE, 0, NULL, 0, 0, 0, ".endif", S_ENDIF, 0, NULL, 0, 0, 0, "xlat", S_INH, 0, NULL, 0, 0327, 0, "lahf", S_INH, 0, NULL, 0, 0237, 0, "sahf", S_INH, 0, NULL, 0, 0236, 0, "aaa", S_INH, 0, NULL, 0, 0067, 0, "daa", S_INH, 0, NULL, 0, 0047, 0, "aas", S_INH, 0, NULL, 0, 0077, 0, "das", S_INH, 0, NULL, 0, 0057, 0, "aam", S_INH, 0, NULL, 0, 0324, 0, "aad", S_INH, 0, NULL, 0, 0325, 0, "cbw", S_INH, 0, NULL, 0, 0230, 0, "cwd", S_INH, 0, NULL, 0, 0231, 0, "repz", S_INH, 0, NULL, 0, 0362, 0, "repnz", S_INH, 0, NULL, 0, 0363, 0, "scab", S_INH, 0, NULL, 0, 0256, 0, "scaw", S_INH, 0, NULL, 0, 0257, 0, "lodb", S_INH, 0, NULL, 0, 0254, 0, "lodw", S_INH, 0, NULL, 0, 0255, 0, "stob", S_INH, 0, NULL, 0, 0252, 0, "stow", S_INH, 0, NULL, 0, 0253, 0, "into", S_INH, 0, NULL, 0, 0316, 0, "iret", S_INH, 0, NULL, 0, 0317, 0, "clc", S_INH, 0, NULL, 0, 0370, 0, "cmc", S_INH, 0, NULL, 0, 0365, 0, "stc", S_INH, 0, NULL, 0, 0371, 0, "cld", S_INH, 0, NULL, 0, 0374, 0, "std", S_INH, 0, NULL, 0, 0375, 0, "cli", S_INH, 0, NULL, 0, 0372, 0, "sti", S_INH, 0, NULL, 0, 0373, 0, "hlt", S_INH, 0, NULL, 0, 0364, 0, "wait", S_INH, 0, NULL, 0, 0233, 0, "lock", S_INH, 0, NULL, 0, 0360, 0, "cmpw", S_INH, 0, NULL, 0, 0247, 0, "movw", S_INH, 0, NULL, 0, 0245, 0, "int", S_INT, 0, NULL, 0, 0, 0, "seg", S_OVER, 0, NULL, 0, 0, 0, "esc", S_ESC, 0, NULL, 0, 0330, 0, "ret", S_RET, 0, NULL, 0, 0303, 0, "xret", S_RET, 0, NULL, 0, 0313, 0, "push", S_PUSH, 0, NULL, 0, 0377, 0, "pop", S_PUSH, 0, NULL, 0, 0217, 0, "in", S_IN, 0, NULL, 0, 0345, 0, "inb", S_IN, 0, NULL, 0, 0344, 0, "out", S_IN, 0, NULL, 0, 0347, 0, "outb", S_IN, 0, NULL, 0, 0346, 0, "lea", S_LEA, 0, NULL, 0, 0215, 0, "lds", S_LEA, 0, NULL, 0, 0305, 0, "les", S_LEA, 0, NULL, 0, 0304, 0, "shl", S_SHL, 0, NULL, 0, 04, 0, "sal", S_SHL, 0, NULL, 0, 04, 0, "shr", S_SHL, 0, NULL, 0, 05, 0, "sar", S_SHL, 0, NULL, 0, 07, 0, "rol", S_SHL, 0, NULL, 0, 00, 0, "ror", S_SHL, 0, NULL, 0, 01, 0, "rcl", S_SHL, 0, NULL, 0, 02, 0, "rcr", S_SHL, 0, NULL, 0, 03, 0, "shlb", S_SHLB, 0, NULL, 0, 04, 0, "salb", S_SHLB, 0, NULL, 0, 04, 0, "shrb", S_SHLB, 0, NULL, 0, 05, 0, "sarb", S_SHLB, 0, NULL, 0, 07, 0, "rolb", S_SHLB, 0, NULL, 0, 00, 0, "rorb", S_SHLB, 0, NULL, 0, 01, 0, "rclb", S_SHLB, 0, NULL, 0, 02, 0, "rcrb", S_SHLB, 0, NULL, 0, 03, 0, "jmp", S_JMP, 0, NULL, 0, 0353, 0, "je", S_JMP, 0, NULL, 0, 0164, 0, "jz", S_JMP, 0, NULL, 0, 0164, 0, "jl", S_JMP, 0, NULL, 0, 0174, 0, "jnge", S_JMP, 0, NULL, 0, 0174, 0, "jle", S_JMP, 0, NULL, 0, 0176, 0, "jng", S_JMP, 0, NULL, 0, 0176, 0, "jb", S_JMP, 0, NULL, 0, 0162, 0, "jnae", S_JMP, 0, NULL, 0, 0162, 0, "jbe", S_JMP, 0, NULL, 0, 0166, 0, "jna", S_JMP, 0, NULL, 0, 0166, 0, "jp", S_JMP, 0, NULL, 0, 0172, 0, "jpe", S_JMP, 0, NULL, 0, 0172, 0, "jo", S_JMP, 0, NULL, 0, 0160, 0, "js", S_JMP, 0, NULL, 0, 0170, 0, "jne", S_JMP, 0, NULL, 0, 0165, 0, "jnz", S_JMP, 0, NULL, 0, 0165, 0, "jnl", S_JMP, 0, NULL, 0, 0175, 0, "jge", S_JMP, 0, NULL, 0, 0175, 0, "jnle", S_JMP, 0, NULL, 0, 0177, 0, "jg", S_JMP, 0, NULL, 0, 0177, 0, "jnb", S_JMP, 0, NULL, 0, 0163, 0, "jae", S_JMP, 0, NULL, 0, 0163, 0, "jnbe", S_JMP, 0, NULL, 0, 0167, 0, "ja", S_JMP, 0, NULL, 0, 0167, 0, "jnp", S_JMP, 0, NULL, 0, 0173, 0, "jpo", S_JMP, 0, NULL, 0, 0173, 0, "jno", S_JMP, 0, NULL, 0, 0161, 0, "jns", S_JMP, 0, NULL, 0, 0171, 0, "loop", S_JMP, 0, NULL, 0, 0342, 0, "loopz", S_JMP, 0, NULL, 0, 0341, 0, "loope", S_JMP, 0, NULL, 0, 0341, 0, "loopnz", S_JMP, 0, NULL, 0, 0340, 0, "loopne", S_JMP, 0, NULL, 0, 0340, 0, "jcxz", S_JMP, 0, NULL, 0, 0343, 0, "call", S_CALL, 0, NULL, 0, 0350, 0, "xcall", S_XOP, 0, NULL, 0, 03, 0, "xjmp", S_XOP, 0, NULL, 0, 05, 0, "add", S_DOP, 0, NULL, 0, 0001, 0, "adc", S_DOP, 0, NULL, 0, 0021, 0, "sub", S_DOP, 0, NULL, 0, 0051, 0, "sbb", S_DOP, 0, NULL, 0, 0031, 0, "cmp", S_CMP, 0, NULL, 0, 0071, 0, "and", S_DOP, 0, NULL, 0, 0041, 0, "or", S_DOP, 0, NULL, 0, 0011, 0, "test", S_DOP, 0, NULL, 0, 0205, 0, "xor", S_DOP, 0, NULL, 0, 0061, 0, "addb", S_DOP, 0, NULL, 0, 0000, 0, "adcb", S_DOP, 0, NULL, 0, 0020, 0, "subb", S_DOP, 0, NULL, 0, 0050, 0, "sbbb", S_DOP, 0, NULL, 0, 0030, 0, "cmpb", S_CMPB, 0, NULL, 0, 0070, 0, "andb", S_DOP, 0, NULL, 0, 0040, 0, "orb", S_DOP, 0, NULL, 0, 0010, 0, "testb", S_DOP, 0, NULL, 0, 0204, 0, "xorb", S_DOP, 0, NULL, 0, 0060, 0, "mov", S_MOV, 0, NULL, 0, 0211, 0, "movb", S_MOVB, 0, NULL, 0, 0210, 0, "mul", S_MUL, 0, NULL, 0, 04, 0, "imul", S_MUL, 0, NULL, 0, 05, 0, "div", S_MUL, 0, NULL, 0, 06, 0, "idiv", S_MUL, 0, NULL, 0, 07, 0, "mulb", S_MULB, 0, NULL, 0, 04, 0, "imulb", S_MULB, 0, NULL, 0, 05, 0, "divb", S_MULB, 0, NULL, 0, 06, 0, "idivb", S_MULB, 0, NULL, 0, 07, 0, "inc", S_SOP, 0, NULL, 0, 00, 0, "dec", S_SOP, 0, NULL, 0, 01, 0, "not", S_SOP, 0, NULL, 0, 02, 0, "neg", S_SOP, 0, NULL, 0, 03, 0, "incb", S_SOPB, 0, NULL, 0, 00, 0, "decb", S_SOPB, 0, NULL, 0, 01, 0, "notb", S_SOPB, 0, NULL, 0, 02, 0, "negb", S_SOPB, 0, NULL, 0, 03, 0, "xchg", S_XCHG, 0, NULL, 0, 0207, 0, "xchgb", S_XCHG, S_END, NULL, 0, 0206 }; -h- README.605 Sat Jan 02 18:00:53 1982 _DBB0:README.605;3 [6,5] Machine-independent Cross assemblers ------ ------------------- ----- ---------- This is a rewrite of the 6800 and Z80 cross assemblers (in [6,3]) in which machine-independent parts of the assembler are seperate from machine-dependent parts. Untested: you're on your own. Build statements are in MACHIN.85 and MACHIN.86, but they're untested. -h- REL.H Sat Jan 02 18:00:53 1982 _DBB0:REL.H;2 /* NOTE: this doesn't seem to be referenced by anybody */ /* * This file defines the format of the * relocatable binary file. Some of these * things will have to change (there is * no notion of the `bss' segment and no * place to put a symbol table). */ /* * Item types. */ #define R_HEAD 0 /* Header */ #define R_AREA 1 /* Area definition */ #define R_SYM 2 /* Symbol definition */ #define R_TEXT 3 /* Text */ #define R_RELOC 4 /* Relocation */ struct r_head { char r_type; /* Item type */ char r_flag; /* Flag byte */ int r_narea; /* # of areas */ int r_nglob; /* # of global symbols */ }; struct r_area { char r_type; /* Item type */ char r_flag; /* Flag byte */ addr_t r_size; /* Size of the area */ char r_id[NCPS]; /* Name */ }; struct r_sym { char r_type; /* Item type */ char r_flag; /* Flag byte */ addr_t r_addr; /* Address */ char r_id[NCPS]; /* Name */ }; struct r_txtrel { char r_type; /* Item type */ char r_nbyte; /* Number of bytes */ char r_data[NDATA]; /* Actual data */ }; -h- SUBR.C Sat Jan 02 18:00:53 1982 _DBB0:SUBR.C;2 #include #include "asm.h" /* * Note an error. * If the error is already in the * error buffer don't note it again. * If the error is serious enough to * stop the parse (a `q' error) just * give up. */ err(c) register c; { register char *p; p = eb; while (p < ep) if (*p++ == c) return; if (p < &eb[NERR]) { *p++ = c; ep = p; } if (c == 'q') unwind(); } /* * Send errors to the standard output. */ diag() { register char *p; p = eb; while (p < ep) printf("%c %04d\n", *p++, line); } /* * Note an 'r' error. */ rerr() { err('r'); } /* * Note an 'a' error. */ aerr() { err('a'); } /* * Note a 'q' error. */ qerr() { err('q'); } -h- SYM.C Sat Jan 02 18:00:53 1982 _DBB0:SYM.C;2 #include #include "asm.h" /* * This routine is called early in the * game to set up the hashtable. First all * buckets in the table are cleared. * Then a pass is made through the builtin * symbols, linking them into their hash * buckets. Finally the area list and `dda' * are set up. */ syminit() { register struct sym *sp; register struct area *ap; register h; struct sym **spp; spp = &symhash[0]; while (spp < &symhash[NHASH]) *spp++ = NULL; sp = &sym[0]; for (;;) { h = hash(sp->s_id); sp->s_sp = symhash[h]; symhash[h] = sp; if ((sp->s_flag&S_END) != 0) break; ++sp; } ap = (struct area *) new(sizeof(struct area)); ap->a_ap = NULL; areap = dda->s_addr = ap; ap->a_sp = dda; ap->a_flag = A_D|A_PRV|A_CON; ap->a_size = 0; ap->a_fuzz = 0; } /* * Lookup the name `id' in the hashtable. * If it is not found either return a * `NULL' (`f' is false) or a * pointer to a newly created hash table * entry (`f' is true). */ struct sym * lookup(id, f) char *id; { register struct sym *sp; register h; h = hash(id); sp = symhash[h]; while (sp != NULL) { if (symeq(id, sp->s_id)) return (sp); sp = sp->s_sp; } if (f == 0) return (NULL); sp = (struct sym *) new(sizeof(struct sym)); sp->s_sp = symhash[h]; symhash[h] = sp; sp->s_type = S_NEW; sp->s_flag = 0; sp->s_area = NULL; sp->s_addr = 0; copy(sp->s_id, id, NCPS); return (sp); } /* * Mark all symbols of type `S_NEW' * global. Called at the end of pass * 0 if `-g'. */ symglob() { register struct sym *sp; register i; for (i=0; is_type == S_NEW) sp->s_flag |= S_GBL; sp = sp->s_sp; } } } /* * Compare two symbol names. */ symeq(p1, p2) register char *p1, *p2; { register n; n = NCPS; do { if (*p1++ != *p2++) return (0); } while (--n); return (1); } /* * Given a pointer to a symbol name * compute and return the hash table * bucket. * The `sum of all the characters mod * table size' algorithm is perhaps * not the best. */ hash(p) register char *p; { register h, n; h = 0; n = NCPS; do { h += *p++; } while (--n); return (h&HMASK); } /* * Allocate a block of space. * Leave if there is no space left * at all. */ char * new(n) { register char *p; if ((p = malloc(n)) == NULL) { fprintf(stderr, "Out of space!\n"); exit(1); } return (p); }