{$U-} {$R-} {===============================================================} { } { UCSD ADAPTABLE ASSEMBLER } { ---- --------- --------- } { Patterned after The Waterloo Last Assembler (TLA) } { Core Authors: William P. Franks and Dennis Volper } { } { } { Version : pdp 11 & LSI 11 } { Date : Sept. 27, 1978 } { Author : Dennis Volper } { Release : I.5.b.1 } { } { } { Institute for Information Systems } { UC San Diego, La Jolla, CA } { } { Kenneth L. Bowles, Director } { } { Copyright (C) 1978, } { Regents of the University of California, San Diego } { } {===============================================================} PROGRAM SYSTEMLEVEL; TYPE PHYLE=FILE; VAR FILLER:ARRAY[0..6] OF INTEGER; USERINFO:RECORD WORKSRC,WORKCODE:^PHYLE; ERRSYM,ERRBLK,ERRNUM:INTEGER; SLOWTERM,STUPID:BOOLEAN; ALTMODE:CHAR; FILLER2:ARRAY[0..21] OF INTEGER; {change with care...allows} WORKTITLE,SYMTITLE:STRING[15] {more compile time space} END; SEGMENT PROCEDURE TLA(III,JJJ:INTEGER); CONST RELEASEVERSION =TRUE; {Is this for the outside world?} NUMKWORDS =27; {The number of key words in this assembler} HASHRANGE =128; {The hash table size} HASHTOP =127; {One less than HASHRANGE} MACROSIZE =19; {The buffer size for a MACRO stored on heap} BUFBLKS =2; {# of blocks for output buffer} BUFLIMIT =1023; {(BUFBLKS*512) - 1} MAXPROC =10; {Maximum number of Procedures per Assembly} PAGESIZE =55; {Lines printed per page} VIEWSTACK =TRUE; {Display stack & heap while Assembling} DEBUG =FALSE; {for debugging Assembler} CODESIZE =20; {Testing values} RELEASENAME ='I.5 [b.1]'; {Below constants are Assembler dependent} NOP =160; {A one byte NOP} ASMNAME ='11'; BYTEFIT =5; {maximum bytes per output line} WORDFIT =3; {maximum words per output line} HIBYTEFIRST =FALSE; {First byte is the high-order byte?} LISTHIFIRST =TRUE; LCCHAR ='*'; {Location counter character} WORDADDRESSED =FALSE; {Word as opposed to byte addressed} AFTERPLUS =0; {An impossible character} AFTERMINUS ='('; { "-(" is always auto decrement} DEFRADIX =8; {Default radix} LISTRADIX =8; {Printed listing radix} HEXSWITCH ='H'; {Char following number which resets radix} DECSWITCH ='.'; OCTSWITCH =0; BINSWITCH ='B'; RELHI =FALSE; {Relative byte most significant passed PUTWORD} TYPE BITE=0..255; PACKNAME=PACKED ARRAY[0..7] OF CHAR; WORDSWAP=PACKED RECORD CASE INTEGER OF 0:(HWORD:INTEGER); 1:(HIBYTE,LOWBYTE:BITE); 2:(HEX1,HEX2,HEX3,HEX4:0..15); 3:(OCT2,OCT3,OCT4,OCT5,OCT6:0..7; OCT1:0..1); 4:(BIN:PACKED ARRAY[0..15] OF 0..1); END; HASHTYPE=RECORD CASE BOOLEAN OF TRUE:(INT:INTEGER); FALSE:(BOL:BOOLEAN) END; BYTESWAP=PACKED RECORD CASE INTEGER OF 0:(BWORD:INTEGER); 1:(BADBYTE,GOODBYTE:BITE); 2:(REGLOW:0..7; MODELOW:0..7; REGHI:0..7; MODEHI:0..7; DUM2:0..15); 3:(XOFFSET:0..255; DUM3:0..255); 4:(SOBSET:0..63; DUM4:0..1023) END; (*$I ASM1.TEXT*) {start of ASM1} {Copyright (c) 1978 Regents of the University of California} TOKENS=(EQUAL,NOTEQUAL,BITWISEOR,EXCLUSIVEOR,DIVIDE,MODULO,ONESCOMPLEMENT,TNOT, OPENPAREN,CLOSEPAREN,OPENBRACKET,CLOSEBRACKET,OPNBRACE,CLSBRACE, COMMA,OPNBROKEN,CLSBROKEN,QUERY,PLUS,MINUS, ASTERISK,AMPERSAND,ATSIGN,COLON,NUMBERSIGN,AUTOINCR,AUTODECR,LOCCTR, FIRSTOPCODE, REF,DEF,OP1,OP2,OP3,OP4,OP5,OP6,OP7,OP8,OP9,OP10,OP11,OP12,OP13, OP14,OP15,OP16,OP17,OP18,OP19,OP20,ALIGN, TEOF,BLOCK,WORD,BIGHT,ENDLINE,TMOD,PROC,FUNC,CONDEND,TELSE,ORG, ASCII,MACRODEF,CONDITION,EQU,PUBLIC,PRIVATE,TCONST, LIST,NOLIST,ASECT,PSECT,TEND,TPAGE,TITLE, LASTOPCODE, INCLUDE,TLABEL,LOCLABEL,TSTRING,CONSTANT,TIDENTIFIER,STARTFILE, MACROEND,EXPAND,TNULL); CODETYPE=(A,P); SOURCETYPE=(MACROSOURCE,PARMSOURCE,FILESOURCE); ATRIBUTETYPE=(DEFABS,PROCS, OPS1,OPS2,OPS3,OPS4,OPS5,OPS6,OPS7,OPS8,OPS9,OPS10,OPS11, OPS12,OPS13,OPS14,OPS15,OPS16,OPS17,OPS18,OPS19,OPS20, DEFRP,DEFREG,DEFCC,DEFIR, PUBLICS,CONSTS,PRIVATES,REFS,DEFS,FUNCS,ABS,LABELS,UNKNOWN,MACROS); MACROPTR=^MACROTYPE; MACROTYPE=PACKED ARRAY[0..MACROSIZE] OF CHAR; JTABPTR=^JTAB; JTAB=RECORD {Used for linkinfo references} PCOFFSET:INTEGER; LAST:JTABPTR END; BKLABELPTR=^BACKLABEL; SYMTABLEPTR=^SYMBOLTABLE; SYMBOLTABLE=RECORD {Symboltable entry} NAME:PACKNAME; LINK:SYMTABLEPTR; CASE ATTRIBUTE:ATRIBUTETYPE OF {OPS1,OPS2,OPS3,OPS4,OPS5,OPS6,OPS7,OPS8,OPS9,OPS10, OPS11,OPS12,OPS13,OPS14,OPS15,OPS16,OPS17,OPS18,OPS19,OPS20, ABS,DEFABS,DEFRP,DEFREG,DEFCC,DEFIR,LABELS,} UNKNOWN:(OFFSETORVALUE:INTEGER; FWDREF:BKLABELPTR); MACROS:(MACRO:MACROPTR; EXPANDMCRO:BOOLEAN); DEFS:(PROCNUM,CODEOFFSET:INTEGER; DEFFWDREF:BKLABELPTR); PUBLICS,PRIVATES,REFS,CONSTS:(NREFS,NWORDS:INTEGER; LINKOFFSET:JTABPTR); PROCS,FUNCS:(FUNCNUM,NPARAMS:INTEGER) END; TEMPTABLE=RECORD {Temporary table entry} TEMPNAME:PACKNAME; DEFOFFSET:INTEGER; FWDREF:BKLABELPTR; TEMPATRIB:ATRIBUTETYPE END; RELTYPE=(LLREL,LABELREL,LCREL,NOTSET); RESULTREC=RECORD {expression evaluator result record} ATTRIBUTE:ATRIBUTETYPE; OFFSETORVALUE:INTEGER; END; RELREC=RECORD {current expression's relocation info} TIPE:RELTYPE; OFFSETORVALUE,TEMPLABEL:INTEGER; ATTRIBUTE:ATRIBUTETYPE; SYM:SYMTABLEPTR END; BACKLABEL=PACKED RECORD {forward reference record} WORDLC,BYTESIZE:BOOLEAN; OFFSET,LC,VALUE:INTEGER; NEXT:BKLABELPTR END; JTABREC=ARRAY[0..6] OF INTEGER; {for storage of relocation info} BUFFERTYPE=PACKED ARRAY[0..511] OF BITE; SCRATCHREC=RECORD {scratch file for temporary storage} CLASS:INTEGER; CASE BOOLEAN OF TRUE:(JUMPS:JTABREC); FALSE:(FWDREF:BACKLABEL) END; {----------------------------------------------------------------------} VAR SYM:SYMTABLEPTR; {pointer to current symboltable entry} LEXTOKEN:TOKENS; {current token returned by LEX} OUTBLKNO, {next output block #} TEXTINDEX, {index into TEXTLINE, containing line of source text} MACROINDEX, {index into macro source sitting on heap} SPCIALSTKINDEX, {index into stack of outstanding special symbols} CODECOUNT:INTEGER; {index into array containing current line's code} OPBYTE:BYTESWAP; {used exclusively by ZOP1 - ZOP20} CH:CHAR; DISPLAY:BOOLEAN; {currently displaying output?} FULLLABEL:BKLABELPTR; {forward referenced labels still unresolved} RESULT:RESULTREC; {result of last call to expression evaluator} BUFBOTTOM, {start of BUFFER relative to start of output file} BUFFERPOS, {next output byte relative to start of BUFFER} BUFFERTOP, {next output byte relative to start of file} MAXBUFTOP, {maximum BUFFERTOP} OUTBLKTOP, {next block after current end of output file} PROCSTART, {start of procedure relative to start of file} JCOUNT1,JCOUNT2,JCOUNT3, {indexes for relocation records JTABREC's} TEMPTOP,TEMPLABEL, BLOCKPTR,BNUM,BLOCKNO,ALTBLOCNO,ALTBLOCPTR, PROCNUM,SEGSIZE,PAGENO, LINENUM,LISTNUM, NUMERRORS, OPVAL,CONSTVAL, PARMPTR,MCSTKINDEX,LINKEND,SCRATCHEND,CONDINDEX, LC,ALC,LASTLC,LOWLC :INTEGER; SYMLAST,FOUND,CONSOLE,STARTLINE,FROMPUTWORD,NOTSTRING,LISTING,JUMPINFO, ADVANCE,EXPANDMACRO,PARMCHECK,ALTINPUT,EXPRSSADVANCE,DEFMCHOOK :BOOLEAN; MCPTR:MACROPTR; BUFFER:^BUFFERTYPE; {buffer for output code in core} TAB:CHAR; LISTFILE:INTERACTIVE; TITLELINE,STRVAL,CURFNAME,FIRSTFNAME:STRING; TEXTLINE,BLANKLINE:PACKED ARRAY[0..79] OF CHAR; RELOCATE,OPERAND1,OPERAND2,OPERAND3,NULLREL:RELREC; NEXTJP:JTABPTR; JUMP1,JUMP2,JUMP3:JTABREC; FREELABEL:BKLABELPTR; CURRENTATRIB:ATRIBUTETYPE; SOURCE:SOURCETYPE; CODESECTION:CODETYPE; MACROSTACK:ARRAY[0..5] OF MACROPTR; PARMSTACK,MCINDEX:ARRAY[0..5] OF INTEGER; SPECIALSTK:ARRAY[0..5] OF TOKENS; TEMP:ARRAY[0..20] OF TEMPTABLE; HASH,HASHRES:ARRAY[0..HASHTOP] OF SYMTABLEPTR; LASTSYM:SYMTABLEPTR; ALTFILE:FILE; SCRATCH:FILE OF SCRATCHREC; KWORDS:ARRAY[0..NUMKWORDS] OF PACKNAME; KTOKEN:ARRAY [0..NUMKWORDS] OF TOKENS; XBLOCK:PACKED ARRAY[0..1023] OF CHAR; CONSTID,HEXCHAR:PACKED ARRAY[0..15] OF CHAR; CODE,BLANKCODE:PACKED ARRAY[0..CODESIZE] OF CHAR; HEAP:^INTEGER; SEGNAME,PROCNAME:PACKNAME; PROCTABLE:ARRAY[0..MAXPROC] OF INTEGER; PROCEDURE ERROR(ERRORNUM:INTEGER); FORWARD; PROCEDURE PATCHCODE(FWDREF:BACKLABEL; BUFINDEX:INTEGER); FORWARD; PROCEDURE IOCHECK(QUIT:BOOLEAN); FORWARD; PROCEDURE LLCHECK; FORWARD; PROCEDURE PRINTPAGE; FORWARD; PROCEDURE PRINTLINE; FORWARD; PROCEDURE PRINTNUM(WORD:INTEGER; BYTESIZE:BOOLEAN); FORWARD; PROCEDURE PUTBYTE(BYTE:BITE); FORWARD; PROCEDURE PUTRELWORD(WORD:INTEGER; BYTESIZE,WORDOFFSET:BOOLEAN); FORWARD; PROCEDURE PUTWORD(WORD:INTEGER); FORWARD; PROCEDURE GETCHAR; FORWARD; PROCEDURE LEX; FORWARD; FUNCTION EXPRESS(OPERANDREQUIRED:BOOLEAN):BOOLEAN; FORWARD; FUNCTION CHECKOPERAND(CKSPCSTK,CKABS,CKRANGE:BOOLEAN;LO,HI:INTEGER):BOOLEAN; FORWARD; {dummy segments necessary since compiled U-} SEGMENT PROCEDURE DUMMY2; BEGIN END; SEGMENT PROCEDURE DUMMY3; BEGIN END; SEGMENT PROCEDURE DUMMY4; BEGIN END; SEGMENT PROCEDURE DUMMY5; BEGIN END; SEGMENT PROCEDURE DUMMY6; BEGIN END; SEGMENT PROCEDURE DUMMY7; BEGIN END; SEGMENT PROCEDURE DUMMY8; BEGIN END; SEGMENT PROCEDURE DUMMY9; BEGIN END; SEGMENT PROCEDURE INITIALIZE; TYPE OPREC=RECORD OPNAME:PACKNAME; OPVALUE:INTEGER; OPATRIB:ATRIBUTETYPE END; VAR OK:BOOLEAN; COUNT:INTEGER; OPFILENAME,LISTNAME:STRING; OPFILE:FILE OF OPREC; PROCEDURE KEYTOKENSET; BEGIN KWORDS[0] :='ALIGN '; KTOKEN[0] :=ALIGN; KWORDS[1] :='ASCII '; KTOKEN[1] :=ASCII; KWORDS[2] :='BLOCK '; KTOKEN[2] :=BLOCK; KWORDS[3] :='BYTE '; KTOKEN[3] :=BIGHT; KWORDS[4] :='CONST '; KTOKEN[4] :=TCONST; KWORDS[5] :='EQU '; KTOKEN[5] :=EQU; KWORDS[6] :='FUNC '; KTOKEN[6] :=FUNC; KWORDS[7] :='PUBLIC '; KTOKEN[7] :=PUBLIC; KWORDS[8] :='PRIVATE '; KTOKEN[8] :=PRIVATE; KWORDS[9] :='PROC '; KTOKEN[9] :=PROC; KWORDS[10]:='WORD '; KTOKEN[10]:=WORD; KWORDS[11]:='EXPAND '; KTOKEN[11]:=EXPAND; KWORDS[12]:='MACRO '; KTOKEN[12]:=MACRODEF; KWORDS[13]:='ENDM '; KTOKEN[13]:=MACROEND; KWORDS[14]:='IF '; KTOKEN[14]:=CONDITION; KWORDS[15]:='ENDC '; KTOKEN[15]:=CONDEND; KWORDS[16]:='ELSE '; KTOKEN[16]:=TELSE; KWORDS[17]:='REF '; KTOKEN[17]:=REF; KWORDS[18]:='DEF '; KTOKEN[18]:=DEF; KWORDS[19]:='ORG '; KTOKEN[19]:=ORG; KWORDS[20]:='INCLUDE '; KTOKEN[20]:=INCLUDE; KWORDS[21]:='LIST '; KTOKEN[21]:=LIST; KWORDS[22]:='NOLIST '; KTOKEN[22]:=NOLIST; KWORDS[23]:='ASECT '; KTOKEN[23]:=ASECT; KWORDS[24]:='PSECT '; KTOKEN[24]:=PSECT; KWORDS[25]:='TITLE '; KTOKEN[25]:=TITLE; KWORDS[26]:='END '; KTOKEN[26]:=TEND; KWORDS[27]:='PAGE '; KTOKEN[27]:=TPAGE; END; PROCEDURE LEXINIT; VAR HASHA,HASHB:INTEGER; ID:PACKNAME; BEGIN FOR COUNT:=0 TO HASHTOP DO HASH[COUNT]:=NIL; KEYTOKENSET; REPEAT ID:=OPFILE^.OPNAME; HASHA:=0; FOUND:=FALSE; FOR COUNT:=0 TO 7 DO BEGIN HASHA:=HASHA + HASHA; {left shift} HASHB:=ORD(ID[COUNT]); HASHA:=ORD((NOT ODD(HASHA) AND ODD(HASHB)) OR (ODD(HASHA) AND NOT ODD(HASHB))); END; HASHB:=HASHA MOD HASHRANGE; {lo-order part} HASHA:=HASHA DIV HASHRANGE; {hi-order part} HASHA:=ORD((NOT ODD(HASHA) AND ODD(HASHB)) OR (ODD(HASHA) AND NOT ODD(HASHB))); {xor} HASHA:=HASHA MOD HASHRANGE; SYM:=HASH[HASHA]; WHILE (NOT FOUND) AND (SYM<>NIL) DO IF SYM^.NAME=ID THEN FOUND:=TRUE ELSE SYM:=SYM^.LINK; IF FOUND THEN WRITELN('Opcode declared twice=',ID) ELSE BEGIN NEW(SYM,UNKNOWN); {using UNKNOWN here is to save compile time space} SYM^.NAME:=ID; SYM^.ATTRIBUTE:=OPFILE^.OPATRIB; SYM^.OFFSETORVALUE:=OPFILE^.OPVALUE; SYM^.LINK:=HASH[HASHA]; HASH[HASHA]:=SYM; IF DEBUG THEN WRITELN(ID,HASHA:10); END; GET(OPFILE); UNTIL EOF(OPFILE); EXPANDMACRO:=TRUE; PARMCHECK:=FALSE; CURRENTATRIB:=UNKNOWN; BLOCKNO:=2; ADVANCE:=TRUE; MCSTKINDEX:=0; SOURCE:=FILESOURCE; BLOCKPTR:=1024; LEXTOKEN:=ENDLINE; TEMPTOP:=0; END; BEGIN {Segment INITIALIZE} (*$I-*) OPFILENAME:=CONCAT(ASMNAME,'.OPCODES'); OPFILENAME:=CONCAT('*',OPFILENAME); RESET(OPFILE,OPFILENAME); IF IORESULT<>0 THEN BEGIN WRITELN(OPFILENAME,' not on vol'); UNITCLEAR(3); EXIT(TLA); END; FOR COUNT:=0 TO 79 DO BLANKLINE[COUNT]:=CHR(0); TEXTLINE:=BLANKLINE; WRITELN(ASMNAME,' Assembler ',RELEASENAME); FOR COUNT:=0 TO CODESIZE DO BLANKCODE[COUNT]:=' '; CODE:=BLANKCODE; CODECOUNT:=0; HEXCHAR:='0123456789ABCDEF'; BUFFERPOS:=0; NUMERRORS:=0; TAB:=CHR(9); LINENUM:=0; SPCIALSTKINDEX:=-1; PROCNUM:=0; LISTNUM:=0; IF LENGTH(USERINFO.WORKTITLE)=0 THEN FIRSTFNAME:=USERINFO.SYMTITLE ELSE FIRSTFNAME:=USERINFO.WORKTITLE; CURFNAME:=FIRSTFNAME; REPEAT WRITE('Output file for assembled listing: ( for none)'); READLN(LISTNAME); DISPLAY:=(LISTNAME<>''); LISTING:=DISPLAY; CONSOLE:=(LISTNAME='CONSOLE:') OR (LISTNAME='#1:'); IF DISPLAY THEN IF CONSOLE THEN OPENNEW(LISTFILE,'CONSOLE:') ELSE OPENNEW(LISTFILE,CONCAT(LISTNAME,'.TEXT[*]')); OK:=(IORESULT=0); IOCHECK(FALSE); UNTIL OK; (*$I+*) IF NOT RELEASEVERSION THEN BEGIN WRITELN('Relocation info at file end?'); READ(KEYBOARD,CH); JUMPINFO:=(CH='Y') OR (CH='y'); END ELSE JUMPINFO:=TRUE; FOR COUNT:=1 TO 9 DO WRITELN; NULLREL.TIPE:=NOTSET; NULLREL.TEMPLABEL:=0; NULLREL.SYM:=NIL; NULLREL.ATTRIBUTE:=UNKNOWN; NULLREL.OFFSETORVALUE:=0; RELOCATE:=NULLREL; MARK(HEAP); {To initialize MEMAVAIL} EXPRSSADVANCE:=TRUE; NOTSTRING:=TRUE; DEFMCHOOK:=FALSE; ALTINPUT:=FALSE; SYMLAST:=FALSE; FROMPUTWORD:=FALSE; LC:=0; LASTLC:=0; LOWLC:=0; ALC:=0; CONDINDEX:=-1; PROCNAME:=' '; PAGENO:=0; TITLELINE:=' '; IF DISPLAY THEN BEGIN WRITELN(LISTFILE,'PAGE - ',PAGENO:3); PAGENO:=PAGENO + 1; END; (*$I-*) REWRITE(SCRATCH,'*LINKER.INFO'); LINKEND:=0; IOCHECK(TRUE); (*$I+*) NEW(SYM,UNKNOWN); {extra record on heap to garbage} LEXINIT; IF NOT (CONSOLE AND DISPLAY) THEN BEGIN WRITELN; WRITE('< 0>'); END; CODESECTION:=P; END; (*$I ASM2.TEXT*) (*$I ASM3.TEXT*) (*$I ASM4.TEXT*) (*$I ASM5.TEXT*) (*$I ASM6.TEXT*)