;MAC80 - An 8085/Z80 cross assembler for the DECsystem-10 ; Copyright 1976,1977,1978,1983 ; Bruce Tanner / Cerritos College ; 11110 Alondra Blvd. ; Norwalk, CA 90650 SEARCH M80UNV,MACTEN TITLE. (M80,MAC80A,8085/Z80 Cross Assembler) M80TTL M80PTX TWOSEG RELOC 400000 EXTERN IBUF,OBUF,LBUF,SBUF,MBUF,NOFILE,FILNAM,FILEXT,PPN,OPNOBJ EXTERN CREFSW,SYMBSW MAC80A::MOVE T1,[PUSHJ P,UUO] MOVEM T1,.JB41## MOVE T1,[IOWD 20,MACSTK] MOVEM T1,MACPDL MOVE T1,[IOWD 20,ARGSTK] MOVEM T1,ARGPDL MOVEI T1,-1 MOVEM T1,INVECT MOVE T1,[POINT 7,MACARG] MOVEM T1,ARGPTR MOVEI T1,1 MOVEM T1,PAGENO SETZM LOCSYM MOVEI T1,PAGEMX MOVEM T1,PAGESZ SETOM STARTA SETZB E,LBTP SETZ BC, SETZM ORGXR TDO F,[FL.LNR,,FR.PS1!FR.HEX] RESTAR: TRNE F,FR.PS1 ;PASS1? JRST PASS1 ;YES OUTSTR [ASCIZ/Pass 2 /] SETZM PC SETZM LINENO SETZM LOCSYM MOVEI T1,1 MOVEM T1,LTYPE MOVEI T1,PAGEMX MOVEM T1,PAGESZ PUSHJ P,GTDATE PUSHJ P,DOHEAD ;OUTPUT THE HEADINGS ; JRST MAIN. ;JUMP TO THE MAIN LINE MAIN.: TRZ F,FR.LOP ;CLEAR LIST OP FLAG TRZE F,FR.END ;IF END JRST ENDIT ;FINI PUSHJ P,INCH ;SNEAK A LOOK FOR FF TRNN F,FR.LIB ;IF NOT IN MACLIB PUSHJ P,DOLINO ;PRINT LINE # PUSHJ P,TOKEN1 ;GET TOKEN WITH 1ST CHAR IN I JRST MAIN1 DUNTAG: TRZE F,FR.END ;DONE? JRST ENDIT ;YES PUSHJ P,TOKEN ;GET A TOKEN MAIN1: PUSHJ P,IFPOP ;AN "IF" TYPE PSEUDO OP? JRST NOTEST ;YES TRNE F,FR.OFF ;ASSEMBLING? JRST FLUSHX ;NO NOTEST: JUMPN TOK,.+4 ;SKIP IF SOMETHING CAIE I,CR ;EOL? CAIN I,SEMICO ;COMMENT? JRST FLUSHX ;YES CAIN I,COLON ;TAG? JRST DOTAG ;YES TLNE F,FL.Z80 JRST Z80P2 PUSHJ P,SRCH80 ;SEARCH OPCODE JRST [PUSHJ P,SETMAC JRST MAIN.] JRST FLUSHX ;BAD OP MOVE OP,OP8TAB(X) ;STORE THE OPCODE MOVE P1,TYPLSH(X) ;GET TYPE,,SHIFT TRNE P1,777770 ;A LARGE SHIFT? JRST [PUSHJ P,@TYPLSH(X) ;YES, ITS A PSEUDO OP JRST MAIN.] TLNE P1,T.1BYT ;JUST OPCODE? JRST ONEOP ;1 BYTE INSTRUCTION TLNE P1,T.NREG ;USES REGISTER? JRST BYTE3 ;NO REGISTER DOREG: PUSHJ P,TOKEN ;GET THE NEXT TOKEN PUSHJ P,EVAL ;EVALUATE THE TOKEN CAIL T1,10 ;LEGAL REGISTER? ERROR F.ILRG ;NO. ANDI T1,7 ;MAKE LEGAL TRNE P1,4 ;REGISTER PAIR? LSH T1,-1 ;YES, MAKE 2 BITS WIDE LSH T1,(P1) ;SHIFT ACCORDING TO LSH(X) OR OP,T1 ;MERGE TLZE P1,T.MOV ;A MOVE? JRST [TRZ P1,-1 ;YES - CLEAR LSH JRST DOREG] ;AND MERGE OTHER REG TLNE P1,T.2BYT!T.3BYT ;2 OR 3 BYTE INSTR? JRST BYTE3 ;GO ON AND DO DATA BYTES ONEOP: PUSHJ P,OUTOP ;OUTPUT THE ONE BYTE MOVEI T2,5 ;5 BYTES JRST SFLUSH BYTE3: PUSHJ P,OUTOP ;OUTPUT THE OPCODE PUSHJ P,TOKEN ;GET THE DATA BYTE(S) JUMPN TOK,NOTMT ;NOT EMPTY CAIE I,15 ;BREAK ON EOL? CAIN I,SEMICO WARN W.MT ;DEFENSIVE CODE NOTMT: PUSHJ P,DODATA ;COMP. EFFECTIVE ADDR MOVE T1,OP PUSHJ P,LSTOP ;OUTPUT THE LOWER 8 BITS LSH OP,-10 ;SHIFT DOWN TLNE P1,T.2BYT ;JUST 1 DATA BYTE? JRST NOP1 MOVE T1,OP PUSHJ P,LSTOP ;OUTPUT UPPER 8 BITS NOP1: IFN FTREL,< SETZ T1, ;CLEAR FOR TEST TRZE F,FR.REL ;RELOCATABLE? MOVEI T1,"'" ;FLAG AS TRZE F,FR.EXT ;EXTERNAL? MOVEI T1,"*" ;INDICATOR SKIPE T1 ;ANYTHING THERE? PUSHJ P,LOUCH ;YES, PRINT IT > ;END IFN FTREL MOVEI T2,3 ;ASSUME 3 BYTES DONE TLNE P1,T.2BYT ;NEED SPACES? MOVEI T2,4 JRST SFLUSH ;LOOP Z80P2: MOVEM TOK,OPCODE ;SAVE OPCODE PUSHJ P,SRCOP2 ;FIRST CHECK OPCODE JRST [PUSHJ P,SETMAC JRST MAIN.] JRST FLUSHX ;BAD OP SKIPN SIZTAB(X) ;IF ZERO SIZE, JRST [PUSHJ P,@ADRTAB(X) ;DO PSEUDO OP JRST MAIN.] PUSHJ P,DECODE ;DECODE ALL THE WONDERFUL ARGUMENT COMBINATIONS MOVE TOK,OPCODE ;GET OPCODE HRLZ OP,TYPE1 ;GET TYPE 1 HRR OP,TYPE2 ;AND TYPE 2 PUSHJ P,SRCOP1 ;SEARCH FOR OPCODE/AM IN TOK/OP JFCL ;NOT USED JRST [ERROR F.ILOP JRST FLUSHX] ;BAD OPCODE/ADDRESS MODE COMBO MOVE P1,CODTAB(X) ;GET ENTRY SKIPE ADRTAB(X) ;ANY SPECIAL ADDRESS? JRST @ADRTAB(X) ;YES, DO IT ANDI P1,7 ;GET LENGTH PUSHJ P,LSTPC MOVE T3,[POINT 8,CODTAB(X)] Z80P21: ILDB T1,T3 ;GET BYTE OF CODE PUSHJ P,LSTOP SOJG P1,Z80P21 ;LOOP ZEXIT: MOVE P1,SIZTAB(X) ;GET NUMBER OF BYTES MOVEI T2,6 SUB T2,P1 SFLUSH: PUSHJ P,SPACE4 SOJG T2,.-1 FLUSHX: PUSHJ P,FLUSH ;FLUSH THE REST OF THE LINE JRST MAIN. SPACE4: SKIPE LTYPE ;MULTI LINE SUPPRESS? SKIPE LINBLK ;AND ON MULTI LINE? CAIA ;NO POPJ P, ;YES MOVEI T1,SPACE TRNE F,FR.HEX JRST SPACE2 PUSHJ P,LOUCH PUSHJ P,LOUCH SPACE2: PUSHJ P,LOUCH PUSHJ P,LOUCH POPJ P, DECODE: SETZM TYPE1 ;1ST ARG TYPE SETZM TYPE2 ;2ND ARG TYPE DEC0: CAIE I,CR ;AT EOL? CAIN I,SEMICO POPJ P, ;YES, EXIT PUSHJ P,TOKEN ;GET 1ST ARG JUMPE TOK,DEC1 ;PAREN, SEMICO, EOL PUSHJ P,ISREG ;CHECK FOR REG JRST DOARG ;REG PUSHJ P,ISREGP ;CHECK FOR REG PAIR JRST [ADDI T1,20 ;MAKE 20-24 JRST DOARG] ;REG PAIR PUSHJ P,ISXR ;CHECK FOR IX,IY JRST DOARG ;XR PUSHJ P,ISCC ;CHECK FOR CONDITION CODE JRST [ADDI T1,50 ;MAKE 50-57 JRST DOARG] ;CC DECT7: MOVEI T1,70 ;GENERAL ARG; TYPE 70 DOARG: SKIPE TYPE1 ;1ST ARG? JRST DOARG2 ;NO, DO 2ND HRRZM T1,TYPE1 ;SAVE TYPE 1 MOVEM T2,ARG1 ;AND THE ARG CAIGE T1,60 ;GENERAL ARG TYPE? JRST DEC3 ;NO, LOOP FOR ARG 2 SETZM EXPLVL CAIN T1,60 ;IF (EXPR) AOS EXPLVL ;INDICATE TO DODATA THAT THE "(" WAS SEEN PUSHJ P,DODATA+1 ;EVALUATE TOKEN; RETURN VALUE ON OP MOVEM OP,ARG1 ;SAVE ARG JRST DEC3 ;LOOP DOARG2: SKIPE TYPE2 ;ARG 2 FULL? JRST [ERROR F.SYN1 ;TOO MANY ARGS POPJ P,] HRRZM T1,TYPE2 ;SAVE TYPE 2 MOVEM T2,ARG2 ;AND THE ARG CAIGE T1,60 ;GENERAL ARG TYPE? JRST DEC3 ;NO, LOOP SETZM EXPLVL CAIN T1,60 ;IF (EXPR) AOS EXPLVL ;INDICATE TO DODATA THAT THE "(" WAS SEEN PUSHJ P,DODATA+1 ;EVALUATE TOKEN; RETURN VALUE ON OP MOVEM OP,ARG2 ;SAVE ARG JRST DEC3 ;LOOP DEC1: CAIE I,SPACE CAIN I,TAB ;WHITE SPACE? JRST DEC0 ;YES, TRY AGAIN CAIE I,SEMICO CAIN I,CR POPJ P, ;EOL, ALL DONE CAIE I,COMMA ;COMMA? JRST DEC2 SKIPN TYPE1 ;AFTER 1ST ARG? ERROR F.SYN3 ;NO, BLANK 1ST ARG JRST DEC0 ;AND TRY AGAIN DEC2: CAIE I,"(" ;INDIRECT POINTER? JRST DECT7 ;NO, UNKNOWN BREAK CHAR PUSHJ P,TOKEN ;GET NEXT TOKEN PUSHJ P,ISREG1 ;CHECK FOR (REG) AS IN 'IN A,(C)' JRST [HRRZS T1 ;STRIP OFF LH CAIE T1,3 ;IS IT (C)? TDOA T1,T1 ;NO, MAKE -1 & SKIP MOVEI T1,35 ;YES JRST DOARG] PUSHJ P,ISRP1 ;CHECK FOR (RP) JRST [ADDI T1,30 ;30-34 JRST DOARG] PUSHJ P,ISXR1 ;CHECK FOR (XR) OR (XR+D) JRST [ADDI T1,10 ;ADD () OFFSET JRST DOARG] MOVEI T1,60 ;TYPE 60 JRST DOARG DEC3: CAIN I,")" ;END PAREN? PUSHJ P,INCH ;YES, SKIP IT JRST DEC0 ISREG: MOVSI T1,-REGTBL CAME TOK,REGTAB(T1) AOBJN T1,.-1 JUMPGE T1,CPOPJ2 POPJ P, ISREG1: PUSHJ P,ISREG ;IS REG POPJ P, ;YES JRST CPOPJ2 ;NOT AND REGTAB: -1 SIXBIT /A/ SIXBIT /B/ SIXBIT /C/ SIXBIT /D/ SIXBIT /E/ SIXBIT /H/ SIXBIT /L/ SIXBIT /I/ SIXBIT /R/ REGTBL==.-REGTAB ISREGP: MOVSI T1,-RPTABL CAME TOK,RPTAB(T1) AOBJN T1,.-1 JUMPGE T1,CPOPJ2 POPJ P, ISRP1: PUSHJ P,ISREGP ;IS REGP POPJ P, ;YES JRST CPOPJ2 ;NO RPTAB: SIXBIT /BC/ SIXBIT /DE/ SIXBIT /HL/ SIXBIT /SP/ SIXBIT /AF/ SIXBIT /PSW/ RPTABL==.-RPTAB ISXR: SETZ T1, CAMN TOK,[SIXBIT/IX/] MOVEI T1,26 ;IX IS 26 CAMN TOK,[SIXBIT/IY/] MOVEI T1,27 ;IY IS 27 JUMPE T1,CPOPJ2 ;NEITHER POPJ P, ISXR1: PUSHJ P,ISXR ;IS XR? CAIA ;YES JRST CPOPJ2 ;NO CAIN I,")" ;ENDS WITH ")"? POPJ P, ;YES, (XR) PUSHJ P,EATSP ;EAT SPACES CAIE I,"+" ; XR+ JRST CPOPJ2 ;NO, PROBABLY JUNK ADDI T1,2 ;ADD OFFSET BETWEEN (IX) AND (IX+D) PUSH P,T1 ;SAVE XR VALUE PUSHJ P,TOKEN ;GET DISPLACEMENT PUSHJ P,EVAL ;EVAL TOKEN MOVE T2,T1 ;DISP IN T2 POP P,T1 ;GET XR VALUE POPJ P, ;RETURN ISCC: MOVSI T1,-CCTABL CAME TOK,CCTAB(T1) AOBJN T1,.-1 JUMPGE T1,CPOPJ2 HRRZS T1 ;RETURN 0-7 POPJ P, CCTAB: SIXBIT /NZ/ SIXBIT /Z/ SIXBIT /NC/ SIXBIT /C/ SIXBIT /PO/ SIXBIT /PE/ SIXBIT /P/ SIXBIT /M/ CCTABL==.-CCTAB ;OUTPUT THE OPCODE BYTE(S) DOOP: PUSHJ P,LSTPC ANDI P1,7 ;GET LENGTH MOVE T3,[POINT 8,CODTAB(X)] ILDB T1,T3 ;GET BYTE OF CODE PUSHJ P,LSTOP SOJG P1,.-2 ;LOOP POPJ P, ;OPCODE & 1 BYTE OD: O1B: PUSHJ P,DOOP O1BX: HRRZ T1,ARG1 ;GET ARG PUSHJ P,LSTOP HRRZ T1,ARG1 LSH T1,-10 SKIPN T1 ;IF MORE THAN 1 BYTE JRST ZEXIT CAIE T1,377 ;AND NOT SIGN BITS WARN W.EXTR ;INDICATE EXTRA BITS JRST ZEXIT ;2 OPS, DISP, LAST OP ODO: PUSHJ P,DOOP1 PUSH P,T1 ;SAVE LAST OP HRRZ T1,ARG1 ;GET DISP PUSHJ P,LSTOP HRRZ T1,ARG1 LSH T1,-10 SKIPN T1 ;IF MORE THAN 1 BYTE JRST ODOX CAIE T1,377 ;AND NOT SIGN BITS WARN W.EXTR ;EXTRA BITS ODOX: POP P,T1 ;GET LAST OP JRST ZEXIT1 ;FINISH IT ;OPCODE, 1 BYTE FROM ARG2 OD2: O1B2: PUSHJ P,DOOP O1B2X: HRRZ T1,ARG2 PUSHJ P,LSTOP HRRZ T1,ARG2 LSH T1,-10 SKIPN T1 ;IF MORE THAN 1 BYTE JRST ZEXIT CAIE T1,377 ;AND NOT SIGN BITS WARN W.EXTR ;INDICATE EXTRA BITS JRST ZEXIT OD1B2: PUSHJ P,DOOP HRRZ T1,ARG1 PUSHJ P,LSTOP HRRZ T1,ARG1 LSH T1,-10 SKIPN T1 ;IF MORE THAN 1 BYTE JRST O1B2X CAIE T1,377 ;AND NOT SIGN BITS WARN W.EXTR ;INDICATE EXTRA BITS JRST O1B2X ;OPCODE & 2 BYTES O2B: PUSHJ P,DOOP MOVE T1,ARG1 ;GET ARG PUSHJ P,LSTOP MOVE T1,ARG1 LSH T1,-10 ZEXIT1: PUSHJ P,LSTOP JRST ZEXIT O2B2: PUSHJ P,DOOP MOVE T1,ARG2 PUSHJ P,LSTOP MOVE T1,ARG2 LSH T1,-10 JRST ZEXIT1 ;OUTPUT ALL BUT THE LAST OPCODE BYTE - RETURN IT IN T1 DOOP1: PUSHJ P,LSTPC ANDI P1,7 ;GET LENGTH MOVE T3,[POINT 8,CODTAB(X)] DOOP1A: ILDB T1,T3 ;GET BYTE OF CODE CAIN P1,1 ;ONE BYTE LEFT? POPJ P, ;YES, DONE PUSHJ P,LSTOP SOJA P1,DOOP1A ;LOOP ;BIT N,(IX+D) GENERATES XR,OP,DISP,OP+N OD2N: PUSHJ P,DOOP1 PUSH P,T1 ;SAVE LAST OP HRRZ T1,ARG2 ;GET DISP PUSHJ P,LSTOP POP P,T1 SKIPL T2,ARG1 CAILE T2,7 ERROR F.BIT LSH T2,3 OR T1,T2 JRST ZEXIT1 ON: PUSHJ P,DOOP1 SKIPL T2,ARG1 CAILE T2,7 ERROR F.BIT LSH T2,3 OR T1,T2 JRST ZEXIT1 RST: PUSHJ P,DOOP1 MOVE T4,ARG1 ;GET ARG CAIN T4,10 MOVEI T4,1 CAIN T4,20 MOVEI T4,2 CAIN T4,30 MOVEI T4,3 CAIN T4,40 MOVEI T4,4 CAIN T4,50 MOVEI T4,5 CAIN T4,60 MOVEI T4,6 CAIN T4,70 MOVEI T4,7 CAILE T4,7 ;LEGAL RST? ERROR F.ILRS ;NO LSH T4,3 ;SHIFT UP OR T1,T4 JRST ZEXIT1 E2: PUSHJ P,DOOP ;DO OP MOVE T1,ARG1 ;GET ARG E2X: SUB T1,PC ;MAKE THE OFFSET SUBI T1,1 ;MINUS 1 CAIG T1,277 ;OVER 127 CAMG T1,[-277] ;LESS THAN -127 ERROR F.RELR ;BAD RELATIVE RANGE JRST ZEXIT1 ;OUTPUT AND EXIT E22: PUSHJ P,DOOP ;DO OP MOVE T1,ARG2 ;GET ARG JRST E2X ;SAME AS E2 DOIM: PUSHJ P,DOOP ;DO OP MOVE T4,ARG1 ;GET ARG MOVEI T1,106 CAIN T4,1 MOVEI T1,126 CAIN T4,2 MOVEI T1,136 CAILE T4,2 ;LEGAL IM? ERROR F.SYN ;NO JRST ZEXIT1 ;EVAL TOKEN IN TOK (AND REST OF EXPR IF ANY) RETURN VALUE IN OP DODATA: SETZM EXPLVL ;INIT EXPR LEVEL (MUST BE 1ST INSTR) TRZ F,FR.UND ;CLEAR STATUS MOVE T4,[IOWD 20,OPSTK] PUSH T4,[0,,-1] ;FLAG TOP OF STACK SETZ T2, ;CLEAR FLAG PUSH P,T2 JRST DODT12 ;JUMP IN DODAT1: CAIE I,COMMA CAIN I,SEMICO ;KNOWN TERMINATORS? JRST DODAT4 ;YES CAIE I,")" ;END OF EXPR CAIN I,CR ;OR EOL? JRST DODAT4 ;YES CAIN I,">" JRST DODAT4 PUSH T4,I ;SAVE ON OP STACK CAIE I,SPACE CAIN I,TAB ;IF SPACE OR TAB CAIA ;KEEP LOOKING FOR OP JRST DODT10 ;HAVE OP ON STACK, GET 2ND ARG POP T4,(T4) ;OP IS JUST SPACE OR TAB PUSHJ P,TOKEN ;GET OP TOKEN JUMPE TOK,DODAT1 ;OP IS BREAK, DODAT1 WILL DO IT PUSH T4,TOK ;SAVE OP AS 6BIT TOKEN ;AT THIS POINT I MAY CONTAIN UNARY OP. CAIE I,SPACE CAIN I,TAB ;BETTER CONTAIN SPACE JRST DODT10 CAIN I,MINUS ;UNARY MINUS? JRST [PUSH P,T2 JRST DODT21] ;YES CAIE I,"(" ;THIS IS THE ONLY NON BLANK THING ALLOWED CAIN I,"<" CAIA ERROR F.ILEX DODT10: PUSH P,T2 CAIE I,"(" ;DON'T LET TOKEN BUST INTO EXPR CAIN I,"<" CAIA PUSHJ P,TOKEN ;GET NEXT TOKEN DODT12: SKIPE TOK ;IF NO TOKEN JRST DODT20 CAIN I,MINUS ;THEN THIS IS A UNARY MINUS DODT21: MOVEI I,"@" ;SPECIAL SYMBOL FOR UNARY MINUS DODT20: CAME TOK,[SIXBIT/NOT/] ;THE OTHER UNARY OPERATOR? CAMN TOK,[SIXBIT/HIGH/] JRST DODT23 ;YES CAME TOK,[SIXBIT/NUL/] CAMN TOK,[SIXBIT/LOW/] JRST DODT23 JRST DODT22 ;NO, SKIP DODT23: POP P,T2 ;RESTORE T2 PUSH T4,TOK ;SAVE OP SETZB T1,TOK ;CLEAR TOK IN CASE NOT(EXPR) SETZ TOK+1, PUSH P,T1 ;SAVE DUMMY ARG (DUMMY NOT FOO) JRST DODT10 ;NOW GET A TOKEN DODT22: PUSHJ P,EVALD ;EVAL TOKEN (OR EXPR) POP P,T2 DODT13: PUSH P,I ;SAVE I MOVE I,(T4) ;GET LAST OP CAIN I,-1 ;NO LAST OP? JRST DODT14 ;SKIP PUSHJ P,DINDEX ;GET INDEX IN T3 MOVE OP,PRIOR(T3) ;GET PRIORITY OF LAST OP IN T3 (1 IS HIGEST) MOVE I,-1(T4) ;GET OP PREVIOUS TO LAST OP CAIN I,-1 ;NOT THERE? JRST DODT14 ;SKIP PUSHJ P,DINDEX ;GET INDEX OF THIS ONE CAML OP,PRIOR(T3) ;CAN WE EVAL YET? JRST DODT15 ;YES ;NOTE: THIS IMPLIES LEFT-TO-RIGHT SCAN OF EQUAL PRI. UNARY OPS MAY NOT BE PUT TOGETHER. DODT14: POP P,I ;DONE WITH I PUSH P,T1 ;SAVE VALUE ON STACK IFN FTREL,< TRNN F,FR.REL!FR.EXT ;ABS? TRO T2,1 ;FLAG ABS TRNE F,FR.REL ;RELOC? TRC T2,2 ;ABS & REL = REL; REL & REL = ABS TRNE F,FR.EXT ;EXTERNAL? ADDI T2,10 > JRST DODAT1 ;KEEP GOING DODT15: POP P,I ;DONE WITH I (DODT13) MOVEM T1,SAVREG ;SAVE T1 POP T4,SAVREG+1 ;& LAST OPERATOR POP P,T1 POP P,OP MOVEM I,SAVREG+2 POP T4,I ;GET CURRENT OP PUSHJ P,DINDEX XCT EXPXCT(T3) ;DOIT TOIT PUSH P,OP ;SAVE NEW VALUE BACK ON STACK MOVE I,SAVREG+2 ;RESTORE I PUSH T4,SAVREG+1 ;PUT BACK LAST OP MOVE T1,SAVREG ;RESTORE LAST ARG JRST DODT13 ;SEE IF WE CAN COMPRESS MORE DODAT4: CAIE I,")" ;IF EOE CAIN I,">" CAIA JRST DODT4A SOSL EXPLVL ;IF WE WERE AT TOP LEVEL.. JRST DODT4B ERROR F.PARN ;PAREN ERROR JRST DODT4B DODT4A: SKIPN EXPLVL ;THE REST BETTER BE AT TOP LEVEL JRST DODT4B ERROR F.PARN DODT4B: POP P,OP ;GET VALUE MOVEM I,SAVREG+3 ;SAVE I DODAT5: POP T4,I ;GET OP CAIN I,-1 ;ALL DONE? JRST DODATX ;YES MOVE T1,OP POP P,OP ;GET 2ND ARG PUSHJ P,DINDEX ;GET INDEX IN T3 XCT EXPXCT(T3) ;DO IT JRST DODAT5 ;LOOP DODATX: MOVE I,SAVREG+3 ;RESTORE I ANDI OP,177777 ;JUST 16 BITS MOVE T1,OP ;GET NUMBER IFN FTREL,< CAIN T2,10 ;ONE EXTERN? JRST DODAT3 ;YES CAILE T2,3 ;1 (ABS) OR 2 OR 3 (REL) ? ERROR F.EXT ;NO POLISH FIXUPS IN THIS ASSEMBLER DODAT3: TRZ F,FR.REL!FR.EXT ;CLEAR STATUS OF LAST TOKEN TRNE T2,2 ;IF REL TRO F,FR.REL ;FLAG CAIN T2,10 ;IF EXTERN TRO F,FR.EXT ;FLAG TRNN F,FR.PS1 ;IF PASS1 SKIPN T2 ;OR NON-RELOCATABLE POPJ P, ;RETURN TRNE F,FR.HEX ;IF OCTAL FORMAT TRNE F,FR.EXT ;OR EXTERN POPJ P, ;EXIT CAIE T2,1 ;IF FLAGED AS ABS, TRNE F,FR.ORG ;OR NOT RELOCATING POPJ P, EXCH T1,RELPTR MOVE T2,PC MOVEM T2,RELTAB(T1) ;SAVE PC FOR NEXT LINK AOJ T1, ;BUMP POINTER EXCH T1,RELPTR > ;END IFN FTREL POPJ P, ;RETURN DEFINE OPRMAC,< E "+",,4 E "-",,4 E "@",,2 E "*",,3 E "/",,3 E 'AND ',,6 E 'OR ',,7 E 'MOD ',,3 E 'XOR ',,7 E 'SHR ',,3 E 'SHL ',,3 E 'NOT ',,2 E 'HIGH ',,10 E 'LOW ',,10 E 'EQ ',,5 E "=",,5 E 'NE ',,5 E 'LT ',,5 E 'GT ',,5 E 'GE ',,5 E 'LE ',,5 E 'NUL ',,1 > DEFINE E(CHAR,INSTR,PRI),< CHAR> OPRTAB: XLIST OPRMAC LIST OPRTBL==.-OPRTAB DEFINE E(CHAR,INSTR,PRI),< INSTR> EXPXCT: XLIST OPRMAC LIST ERROR F.ILEX ;EXECUTED IF OP IS NOT IN OPRMAC DEFINE E(CHAR,INSTR,PRI),< EXP PRI> PRIOR: XLIST OPRMAC LIST EXDIV: PUSH P,OP+1 IDIV OP,T1 POP P,OP+1 POPJ P, EXMOD: PUSH P,OP+1 IDIV OP,T1 MOVE OP,OP+1 POP P,OP+1 POPJ P, EXSHR: MOVNS T1 LSH OP,(T1) POPJ P, RELEQ: CAME OP,T1 FALSE: TDZA OP,OP ;0 = FALSE TRUE: SETO OP, ;-1 = TRUE POPJ P, RELNE: CAMN OP,T1 JRST FALSE JRST TRUE RELLT: CAML OP,T1 JRST FALSE JRST TRUE RELLE: CAMLE OP,T1 JRST FALSE JRST TRUE RELGT: CAMG OP,T1 JRST FALSE JRST TRUE RELGE: CAMGE OP,T1 JRST FALSE JRST TRUE ;NULL = LOCAL SYMBOL GENERATED FOR MISSING ARG, WHICH IS UNDEFINED DONULL: TLNN T1,S.UNDF ;IS THIS SYMBOL UNDEFINED? JRST FALSE ;NO SETZ E, ;YES, IT'S NULL; IGNORE THE 'UNDEFINED' ERROR JRST TRUE EVALD: CAIE I,"(" ;A WHOLE EXPR? CAIN I,"<" CAIA JRST EVAL ;NO, JUST EVAL AOS EXPLVL ;FLAG WHICH LEVEL WE'RE IN SETZ I, ;GET RID IF PAREN FOR TEST @ DODT10+1 PUSH T4,[0,,-1] ;DON'T PLOW THROUGH UPPER LEVEL STUFF PUSHJ P,DODT10 ;MUNCH ON (EXPR) CAIE I,CR CAIN I,SEMICO ;IF ERROR ON EOL, DODAT4 ALREADY HOLLERED POPJ P, ;RETAIN THIS BREAK FOR ANY OTHER LEVELS CAIE I,")" ;SHOULD END ON ) CAIN I,">" CAIA ERROR F.ILEX JRST INCH ;GET THE BREAK CHAR DINDEX: MOVSI T3,-OPRTBL CAME I,OPRTAB(T3) AOBJN T3,.-1 SKIPL T3 ERROR F.ILEX ;NOT IN TABLE POPJ P, TOKEN: CAIE I,CR PUSHJ P,INCH TOKEN1: PUSHJ P,EATSP ;EAT WHITE SPACE SETZB TOK,TOK+1 MOVE T1,[POINT 6,TOK] CAIA TOKENL: PUSHJ P,INCH PUSHJ P,BREAK ;BREAK CHARACTER? POPJ P, CAIL I,"A"+40 ;IF LOWER CASE SUBI I,40 ;MAKE UPPER CASE SUBI I,40 ;CONVERT TO SIXBIT CAMN T1,[600,,TOK+1] ;TOK,TOK+1 FULL? JRST TOKENW ;YES, THROW OUT READ OF TOKEN IDPB I,T1 ;PUT IN TOK JRST TOKENL TOKENW: PUSHJ P,INCH ;WASTE REST OF TOKEN PUSHJ P,BREAK CAIA JRST TOKENW ; TRNN F,FR.SNK ;DON'T GET UPSET ABOUT OVERFLOW OF '...' ; WARN W.TOK POPJ P, BREAK: CAIG I,"Z" CAIGE I,"A" ;A-Z? CAIA JRST CPOPJ2 CAIG I,"9" CAIGE I,"0" ;0-9? CAIA JRST CPOPJ2 ;YES CAIG I,"Z"+40 ;LC? CAIGE I,"A"+40 CAIA JRST CPOPJ2 CAIE I,"@" ;@ CAIN I,"?" ;AND ? ARE LEGAL JRST CPOPJ2 CAIE I,PERIOD ;PERIOD IS LEGAL, MAINLY FOR .8080, ETC. CAIN I,DOLLAR ;$ IS NOW A LEGAL SYMBOL CHARACTER JRST CPOPJ2 CAIN I,"_" ;UNDERSCORE TO KEEP MACRO-80 HAPPY JRST CPOPJ2 POPJ P, FLUSHL: CAIN I,LF ;IF ALREADY FLUSHED.. JRST TLCRLF ;NEW LINE FLUSH: CAIN I,LF POPJ P, PUSHJ P,INCH ;GET NEXT CHARACTER JRST FLUSH ;LOOP ;BINARY SEARCH OPNTAB SRCH80: SETO T1, ;RANGE START MOVEI T2,OPTABL ;RANGE END SRCH81: MOVE T3,T2 ;GET END SUB T3,T1 ;GET LENGTH OF RANGE IDIVI T3,2 ;GET 1/2 RANGE JUMPE T3,SRCH10 ;NOT THERE ADD T3,T1 ;GET OFFSET INTO RANGE MOVE X,T3 ;GET IN X CAMN TOK,OPNTAB(X) ;MATCH? (ALL TOKENS IN OPNTAB ARE LE 6 CHAR) JRST CPOPJ3 ;YES, SKIP RET CAML TOK,OPNTAB(X) MOVE T1,T3 ;SET NEW RANGE CAMG TOK,OPNTAB(X) MOVE T2,T3 JRST SRCH81 ;NO, LOOP SRCH10: MOVEI X,OPTABL ;POINT TO NULL ENTRY TRZE F,FR.EVL ;FROM EVAL? POPJ P, ;YES, QUIT NOW. DMOVE T2,TOK ;SAVE TOKEN IN CASE OF MACRO DEF CAIE I,CR ;IF AT EOL CAIN I,SEMICO ;.. JRST TSTMAC ;CAN'T BE EQU|SET|MACRO, CAN ONLY BE MACRO NAME CAIE I,SPACE CAIN I,TAB ;CHECK FOR WHITE SPACE CAIA ;OK, NOW CHECK FOR SET|EQU|MACRO JRST SRCERR ;JUNK AFTER LABEL PUSHJ P,SNEAK ;SEE IF MACRO DEFINITION CAMN TOK,[SIXBIT/MACRO/] ;IS IT? JRST SRCHOK CAME TOK,[SIXBIT/ASET/] CAMN TOK,[SIXBIT/EQU/] JRST SRCHOK TLNN F,FL.Z80 ;TEST FOR 8080 AND SET CAME TOK,[SIXBIT/SET/] JRST TSTMAC ;NO, SEE IF IT IS A MACRO ITSELF SRCHOK: PUSHJ P,TOKEN ;GET NEXT TOKEN CAMN TOK,[SIXBIT/ASET/] JRST ASET CAMN TOK,[SIXBIT/EQU/] JRST EQUAL TLNE F,FL.Z80 JRST SRCOK1 CAMN TOK,[SIXBIT/SET/] ;GOOD GUYS? JRST ASET ;YES SRCOK1: CAMN TOK,[SIXBIT/MACRO/] JRST DOMAC TSTMAC: DMOVE TOK,T2 ;PUT BACK TOKEN PUSHJ P,SRCSYM ;CHECK FOR MACRO JRST SRCERR ;NO MACRO TLNE T1,S.MAC ;MACRO? POPJ P, ;YES, SET UP MACRO SRCERR: ERROR F.ILOP ;NO. UNKNOWN OPCODE SETZB TOK,TOK+1 ;WASTE BAD TOKEN JRST CPOPJ2 ;BINARY SEARCH OPZTAB FOR OPCODE/ADDRESS MODE SRCOP1: SETO T1, ;RANGE START MOVEI T2,OPZTBL ;RANGE END SRCO1: MOVE T3,T2 ;GET END SUB T3,T1 ;GET LENGTH OF RANGE IDIVI T3,2 ;GET 1/2 RANGE JUMPE T3,SRCH10 ;NOT THERE ADD T3,T1 ;GET OFFSET INTO RANGE MOVE X,T3 ;GET IN X CAMN TOK,OPZTAB(X) ;MATCH? JRST SRCO2 ;YES, SEE IF AM MATCHES CAML TOK,OPZTAB(X) JRST [MOVE T1,T3 ;SET NEW RANGE JRST SRCO1] CAMG TOK,OPZTAB(X) JRST [MOVE T2,T3 JRST SRCO1] ;NO, LOOP HALT SRCO1 ;NOT = < OR > SRCO2: CAMN OP,OPMTAB(X) ;AM MATCH? JRST CPOPJ3 ;YES, SKIP RET CAML OP,OPMTAB(X) JRST [MOVE T1,T3 ;SET NEW RANGE JRST SRCO1] CAMG OP,OPMTAB(X) JRST [MOVE T2,T3 JRST SRCO1] ;NO, LOOP HALT SRCO1 ;NOT = < OR > ;SEARCH OPZTAB FOR OPCODE SRCOP2: SETO T1, ;RANGE START MOVEI T2,OPZTBL ;RANGE END SRC21: MOVE T3,T2 ;GET END SUB T3,T1 ;GET LENGTH OF RANGE IDIVI T3,2 ;GET 1/2 RANGE JUMPE T3,SRCH10 ;NOT THERE ADD T3,T1 ;GET OFFSET INTO RANGE MOVE X,T3 ;GET IN X CAMN TOK,OPZTAB(X) ;MATCH? JRST CPOPJ3 ;YES, SEE IF AM MATCHES CAML TOK,OPZTAB(X) JRST [MOVE T1,T3 ;SET NEW RANGE JRST SRC21] CAMG TOK,OPZTAB(X) JRST [MOVE T2,T3 JRST SRC21] ;NO, LOOP HALT SRC21 ;NOT = < OR > IFPOP: CAME TOK,[SIXBIT/IFE/] CAMN TOK,[SIXBIT/IFN/] POPJ P, CAME TOK,[SIXBIT/ENDIF/] CAMN TOK,[SIXBIT/END/] POPJ P, CAME TOK,[SIXBIT/IF/] CAMN TOK,[SIXBIT/ELSE/] POPJ P, AOS (P) POPJ P, ORG: TRO F,FR.ORG ;FLAG NO RELOCATION PUSHJ P,TOKEN ;GET ORG ARG PUSHJ P,DODATA ;GET THE NUMBER MOVEM OP,PC ;RESET PC TRNN F,FR.PS1 ;SKIP IF PASS1 JRST FLUSH ;NOPE, DONE MOVE T1,ORGXR ;GET INDEX MOVEM BC,ORGBLK(T1) ;STORE BYTE COUNT SKIPE BC ;IF BLOCK WAS VALID, ADDI T1,2 ;BUMP ORIGIN INDEX MOVEM OP,ORGBLK+1(T1) ;SAVE NEW START ADDRESS MOVEM T1,ORGXR ;SAVE INDEX SETZ BC, ;NO BYTES IN NEW BLOCK JRST FLUSH ;FLUSH DOEND: MOVE T1,INVECT ;GET INVECT CAIN T1,-2 ;END FROM MACLIB? JRST FLUSH ;YES, IGNORE IT TRO F,FR.END ;SAY WE'RE DONE CAIN I,CR ;JUST "END" & NO START ADDRESS? JRST FLUSH ;YES, FLUSH LINE. PUSHJ P,TOKEN ;GET END ADDRESS PUSHJ P,DODATA ;GET VALUE IF ANY MOVEM OP,STARTA PUSHJ P,NOPC ;LIST START ADDRESS IFN FTREL,< MOVEI T1,"'" TRZE F,FR.REL ;RELOC? PUSHJ P,LOUCH ;YES TRZN F,FR.EXT ;EXTERNAL? JRST FLUSH ;NO, DONE SETOM STARTA ;YES. THIS IS ILLEGAL ERROR W.EXSA > ;END IFN FTREL JRST FLUSH DS: PUSHJ P,TOKEN ;GET BLOCK ARG PUSHJ P,DODATA PUSHJ P,LSTPC TRO F,FR.LOP MOVEI T1,TAB PUSHJ P,LOUCH TRNN F,FR.HEX PUSHJ P,LOUCH MOVE T1,PC ;SAVE OLD PC ADDM T1,OP ;NEW PC JRST ORG+3 ;DS MEANS NEW BLOCK PHASE: PUSHJ P,TOKEN PUSHJ P,DODATA MOVEM OP,PC TRO F,FR.ORG ;NO RELOCATION JRST FLUSH PRINTX: TRNE F,FR.PS1 ;IF ON PASS1 JRST FLUSH ;SKIP IT PX1: PUSHJ P,INCH OUTCHR I CAIE I,LF JRST PX1 POPJ P, DOLALL: TDZA T1,T1 ;LALL = LTYPE:0 LIST EVERYTHING DOXALL: MOVEI T1,1 ;XALL = LTYPE:1 NO MULTI-LINE EXPANSIONS JRST SETLTP DOXMAC: SKIPA T1,[EXP 2] ;XMAC = LTYPE:2 NO MACRO TEXT EXPANSIONS DOSALL: MOVEI T1,3 ;SALL = LTYPE:3 NO MACRO CODE EXPANSION JRST SETLTP DOXLST: MOVEI T1,4 ;XLIST = LTYPE:4 STOP LISTING SETLTP: MOVEM T1,LTYPE JRST FLUSH .Z80: TLOA F,FL.Z80 DO8080: TLZ F,FL.Z80 JRST FLUSH DB: TLOA F,FL.DB DW: TLO F,FL.DW IFN FTREL, MOVE T4,[POINT 10,STRING] ;SET UP OPCODE OUTPUT IFE FTREL, MOVE T4,[POINT 8,STRING] MOVE T2,T4 ;AND INPUT PUSH P,T2 ;SAVE IT DC0: PUSHJ P,TOKEN ;GET ARG(S) CAIE I,"'" CAIN I,QUOTE JRST [MOVEM I,DELIM ;SAVE QUOTE PUSHJ P,CCONST;SEE IF SINGLE CHAR JRST DC4 ;NO, DO QUOTED STRING JRST .+1] ;DO CHARACTER CONSTANT PUSH P,T4 ;DODATA DESTROYS T4 PUSHJ P,DODATA POP P,T4 MOVE T2,OP ;SAVE IT ANDI OP,377 ;LOWER 8 BITS IDPB OP,T4 ;SAVE OP MOVE OP,T2 ;GET BACK ALL OF OP AOS BYTCNT ;COUNT TOTAL BYTES IN AOS PC ;FIX PC FOR EVAL AOS XTRAPC ;FOR FIXUP TLNN F,FL.DW ;WHOLE WORD? JRST DC1 ;NO LSH OP,-10 ANDI OP,377 ;JUST DATA BITS IFN FTREL,< TRZE F,FR.REL ;IF RELOC TRO OP,400 ;FLAG TRZE F,FR.EXT ;IF EXT TRO OP,1000 ;FLAG > IDPB OP,T4 AOS BYTCNT AOS PC AOS XTRAPC DC1: CAIN I,COMMA ;CONTINUE? JRST DC0 ;YES PUSHJ P,EATSP ;EAT WHITE SPACE POP P,OP ;GET START BYTE POINTER SETZ TOK, ;RESET COUNTER SKIPN BYTCNT ;ANY BYTES IN THERE? JRST DCX0 ;NO SOSGE XTRAPC JRST DC2 SOS PC JRST .-3 DC2: SETZM XTRAPC PUSHJ P,LSTPC ;LIST PC MOVEI TOK,6 ;TOKEN NOT INUSE NOW DC3: ILDB T1,OP PUSH P,T1 ;SAVE IT PUSHJ P,LSTOP ;OUTPUT OP WITHOUT UPDATING PC POP P,T1 SOSG BYTCNT ;ONE LESS BYTE IN STRING JRST DCX ;ALL GONE SOJG TOK,DC3 ;LOOP FOR 2 OR 3 BYTES IFN FTREL,< TRNE T1,400 ;IF RELOCATABLE JRST [MOVEI T1,"'" ;FLAG PUSHJ P,LOUCH JRST .+1] TRNE T1,1000 ;IF EXTERNAL JRST [MOVEI T1,"*" PUSHJ P,LOUCH JRST .+1] > PUSHJ P,FLUSHL ;PRINT LINE OF SOURCE (OR NEW LINE) JRST DC2 ;DO ANOTHER LINE DCX: SOJ TOK, ;COUNT BYTE PRINTED IFN FTREL,< MOVE T3,T1 ;GET FLAGS SETZ T1, TRNE T3,400 ;RELOC WORD? MOVEI T1,"'" TRNE T3,1000 ;EXTERN? MOVEI T1,"*" CAIE T1,"'" CAIN T1,"*" PUSHJ P,LOUCH ;OUTPUT IF ' OR * > ;END IFN FTREL DCX0: TLZ F,FL.DB!FL.DW ;DONE WITH FLAGS JUMPE TOK,DCX3 ;DONE PUSHJ P,SPACE4 ;SPACE OUT SOJG TOK,.-1 ;LOOP DCX3: CAIN I,SEMICO ;START OF COMMENT? PUSHJ P,FLUSH ;YES, GO TO EOL CAIE I,CR CAIN I,LF ;AT EOL? JRST FLUSHL ;YES WARN W.JUNK ;UNKNOWN JUNK JRST FLUSHL DC4: PUSHJ P,INCH ;GET LIT CAMN I,DELIM ;END QUOTE? JRST [PUSHJ P,INCH CAME I,DELIM ;QUOTE QUOTE? JRST DC1 ;NO, JUST COMMA JRST .+1] ;YES, STORE QUOTE IDPB I,T4 ;SAVE CHAR AOS BYTCNT CAIE I,CR ;EOL? CAIN I,LF CAIA ;YES JRST DC4 ;NO DC6: MOVE TOK,BYTCNT ;GET COUNT OF BYTES READY TO GO CAIGE TOK,6 ;ENOUGH FOR A LINE? JRST DC4 ;NO MOVEI TOK,6 ;SET UP BYTES/LINE PUSHJ P,LSTPC ;DO PC POP P,OP ;GET BYTE POINTER DC7: ILDB T1,OP ;GET BYTE SOS BYTCNT ;COUNT DOWN PUSH P,T1 PUSHJ P,LSTOP ;LIST IT POP P,T1 SOJG TOK,DC7 PUSH P,OP ;SAVE IT CAIN I,CR ;GOT HERE VIA CR? JRST DC4 ;YES, CAUSE LINE TO BE PRINTED PUSHJ P,TLCRLF ;NEXT LIST LINE JRST DC6 ;JUST BYTES FOR A WHILE ; CHECK FOR CHARACTER CONSTANT CCONST: TLNE F,FL.DW ;A STRING IN A DW JRST CPOPJ2 ;HAS TO BE A CHARACTER CONSTANT TRO F,FR.SNK ;SAY WE'RE SNEAKING AROUND PUSH P,I PUSH P,T1 PUSH P,T2 MOVE T2,[POINT 7,BAKBUF] ;SET UP POINTER FOR INCH MOVEM T2,BAKPTR ;SAVE IT PUSHJ P,INCH ;GET A QUOTED CHARACTER CAMN I,DELIM ;QUOTE QUOTE? JRST SNEAKX ;YES, LET STRING PROCESSOR DO IT PUSHJ P,INCH ;GET THE NEXT CHARACTER CAMN I,DELIM ;WAS IT A SINGLE QUOTED CHARACTER? AOS -3(P) ;YES, CAUSE A SKIP RETURN FROM CCONST JRST SNEAKX ;SETUP THE INVECT, ETC. IFN FTREL,< DOINT: SKIPA T2,[XWD S.INT,0] DOEXT: MOVSI T2,S.EXT PUSHJ P,TOKEN ;GET TOKEN PUSHJ P,SRCSYM ;FIND IT (OR EMPTY LOC) DMOVEM TOK,(S) ;NOT THERE, STUFF IT IORM T2,2(S) ;FLAG SYMBOL TLNE T2,S.EXT ;EXTERNAL? HLLOS 2(S) ;YES, MAKE RH -1 (FOR END OF CHAIN) CAIN I,COMMA ;MORE TO COME? JRST DOEXT+1 ;YES JRST FLUSH ;NO > DOMAC: DMOVE TOK,T2 ;GET MACRO NAME POP P,(P) ;CAME VIA JRST FROM SUBROUTINE TRO F,FR.NRF ;WE WANT TO KNOW IF MACRO WAS NEVER REFERENCED PUSHJ P,SRCSYM ;FIND IN SYMBOL TABLE DMOVEM TOK,(S) ;SAVE IT PUSHJ P,SYMDEF ;LINE DEFINED ON MOVSI T1,S.MAC ;FLAG AS A MACRO REFERENCE IORM T1,2(S) ;PUT IN SYMBOL TABLE MOVE T2,[MACDUM,,MACDUM+1] SETZM MACDUM BLT T2,MACDND ;CLEAR MACRO ARG TABLE MOVEI T1,2 ;INDICATE NOT A REPT MOVEM T1,EOMFLG SETZ T2, ;MACDUM INDEX PUSH P,S DOMAC4: PUSHJ P,TOKEN DMOVEM TOK,MACDUM(T2) ;SAVE DUMMY ARG NAME JUMPE TOK,DOMC4A ;SINCE NULL ENTRY MEANS END, IGNORE REST CAIE I,COMMA ;MORE? JRST DOMC4A ;NO, SKIP AOJ T2, AOJA T2,DOMAC4 ;LOOP UNTIL NO MORE ARGS DOMC4A: POP P,S DOMC4B: PUSHJ P,FLUSH ;WASTE REST OF THE LINE MOVE T1,.JBFF## ;GET JOBFF HRRM T1,2(S) ;SAVE HOME OF MACRO MOVE T2,T1 HRLI T2,(POINT 7,0) ;POINTER TO MACRO BODY DOMAC1: PUSHJ P,INCH DOMAC3: HRRZI T1,1(T2) ;GET ADDRESS PART OF POINTER (+1) PUSHJ P,MEMXPN ;SEE IF MEMORY NEEDS TO BE EXPANDED CAIE I,SEMICO ;";"? JRST DOM10 ;NO LDB I,T2 ;GET LAST CHAR CAIE I,SEMICO ;DOUBLE ;;? JRST DOM11 ;NO SOJ T2, ;BACKUP BTP DOM9: ILDB I,T2 CAIN I,SEMICO JRST DOM12 ;FOUND IT CAIE I,TAB ;TRY TO ELIMINATE TRAILING TABS CAIN SPACE ;OR SPACES JRST DOM9 MOVEM T2,SAVREG ;SAVE FOR A WHILE JRST DOM9 MEMXPN: CAMG T1,.JBREL## ;WILL T1 FIT IN CORE? POPJ P, ;YES, EXIT PUSH P,T1 ;SAVE T1 CORE T1, ERROR F.NCOR POP P,T1 ;RESTORE T1 POPJ P, DOM12: PUSHJ P,FLUSH ;WASTE COMMENT MOVE T2,SAVREG ;GET POINTER MOVEI I,CR IDPB I,T2 ;STUFF CR MOVEM I,LASTMC ;SAVE LAST MACRO CHAR SKIPA I,[LF] ;SET UP LF DOM11: MOVEI I,SEMICO ;PUT BACK ; DOM10: SKIPG MACLEV ;PASS THRU CONCAT INSIDE MACRO DEF CAIE I,"&" ;CONCATENATE? IDPB I,T2 ;STUFF IT CAIN I,"&" ;IF CONCAT SKIPE MACLEV ;AND NOT PASS THRU JRST DOM13 ;NOT AND CAMN I,LASTMC ;CHECK FOR && IDPB I,T2 ;IF SO, SAVE ONE & DOM13: MOVEM I,LASTMC ;SAVE IN CASE OF && CAIE I,LF ;END OF LINE JRST DOMAC6 TRZ F,FR.MCM ;FLAG END OF ANY POSSIBLE COMMENT JRST DOMC2A ;CHECK FOR ENDM, ETC. DOMAC6: PUSHJ P,BREAK ;IS IT WORTHWHILE TO LOOK FOR NEXT TOKEN? JRST DOMAC2 ;YES JRST DOMAC1 ;NO DOMAC5: SOSL MACLEV ;IN A NESTED MACRO? JRST DOMAC1 ;YES SETZM MACLEV ;DON'T LEAVE IT NEG. LDB I,T2 ;GET LAST CHAR OF MACRO CAIN I,12 ;END WITH LF? JRST DOMC5A ;YES, SKIP MOVEI I,15 IDPB I,T2 MOVEI I,12 ;END MACRO TEXT WITH CRLF IDPB I,T2 DOMC5A: MOVEI I,177 IDPB I,T2 MOVE I,EOMFLG ;177,2 IS END OF MACRO IDPB I,T2 SETZ I, IDPB I,T2 ;END WITH NULL AOJ T2, ;POINT TO 1ST FREE WORD HRRM T2,.JBFF## ;UPDATE JOBFF MOVE T1,EOMFLG ;ARE WE FROM REPT? CAIN T1,3 POPJ P, ;YES, GO BACK TO REPT CODE TRNE F,FR.PS1 ;PASS1? JRST FPASS1 ;FLUSH REST OF LINE, RETURN TO NORMAL INPUT JRST FLUSHX ;FOR PASS2 DOMAC2: CAIN I,SEMICO TRO F,FR.MCM ;FLAG IGNORE REST OF LINE CAIN I,QUOTE TRC F,FR.MQT ;TOGGLE QUOTE IN MACRO TRNE F,FR.MCM ;IN COMMENT? JRST DOMAC1 ;YES DOMC2A: PUSHJ P,DOMC13 ;GET NEXT TOKEN DOMAC7: JUMPE TOK,DOMAC1 ;NOTHING THERE CAMN TOK,[SIXBIT/ENDM/];END OF MACRO? JRST DOMAC5 ;YES CAME TOK,[SIXBIT/REPT/] CAMN TOK,[SIXBIT/MACRO/] ;NESTING A MACRO? JRST [TRNN F,FR.MCM!FR.MQT ;IN COMMENT OR QUOTE? AOS MACLEV ;NO, COUNT LEVEL OF NEST JRST DOMAC1] CAMN TOK,[SIXBIT/LOCAL/] ;LOCAL SYMBOL? JRST DOMAC9 ;YES MOVSI T3,-MACDML DOMC7A: SKIPN MACDUM(T3) JRST DOMAC1 CAMN TOK,MACDUM(T3) CAME TOK+1,MACDUM+1(T3) ;WHAT? NO DOUBLE WORD COMPARE? CAIA JRST DOMAC8 AOBJN T3,.+1 AOBJN T3,DOMC7A JUMPGE T3,DOMAC1 DOMAC8: PUSHJ P,TOKEN PUSH P,I MOVEI I,177 IDPB I,T2 HRRZS T3 LSH T3,-1 ;ACCOUNT FOR DOUBLE SIZE TOKENS MOVEI I,100(T3) IDPB I,T2 POP P,I JRST DOMAC3 DOMAC9: SKIPG MACLEV ;IN A MACRO? TRNE F,FR.MCM!FR.MQT ;IN COMMENT OR QUOTE? JRST DOMAC1 ;YES, IGNORE IT PUSHJ P,TOKEN ;EAT "LOCAL" MOVSI T3,-MACDML DOMC9A: SKIPN MACDUM(T3) ;FIND FIRST FREE MACDUM ENTRY JRST DOMC9B AOBJN T3,.+1 AOBJN T3,DOMC9A ERROR F.TMMA ;TOO MANY MACRO ARGS (MAKE MACDUM BIGGER) DOMC9B: PUSHJ P,TOKEN DMOVEM TOK,MACDUM(T3) ;SAVE LOCAL SYMBOL CAIN I,"," ;MORE LOCALS? JRST DOMC9A ;YES CAIN I,CR ;THROW OUT REST OF LINE JRST DOMAC3 PUSHJ P,INCH JRST .-3 DOMC13: HRRZ T1,INVECT ;GET INVECT POINTER CAIG T1,BAKPTR CAIGE T1,BAKBUF ;POINTS TO BAKBUF?? (IF SO, DON'T SNEAK) PJRST SNEAK ;LOOK AT NEXT TOKEN PUSH P,INVECT ;SAVE POINTER ILDB I,INVECT POP P,INVECT CAIE I,177 ;END OF BAKBUF? JRST [POP P,(P) ;WASTE RETURN ADDR JRST DOMAC1] ;JUST PROCESS CHARACTER MOVE T1,MACPDL POP T1,INVECT ;RESTORE OLD POINTER MOVEM T1,MACPDL JRST SNEAK ;AND GET A NEW TOKEN ASET: TLO F,FL.SET ;FLAG NO ERROR ON REDEFINITION EQUAL: DMOVE TOK,T2 ;RESET TOKEN TLO F,FL.EQU ;FLAG IN EQU TRO F,FR.NRF ;DEFINITION IS NOT REFERENCE PUSHJ P,SRCSYM DMOVEM TOK,(S) ;LOAD SYMBOL IF NOT THERE PUSH P,S ;SAVE S PUSHJ P,TOKEN ;GET ARG PUSHJ P,DODATA ;GET VALUE POP P,S ;RESTORE S MOVE T1,2(S) ;GET VALUE OF SYMBOL TLNN F,FL.SET ;IF EQU CAIN OP,(T1) ;AND NOT SAME CAIA ERROR F.EQU ;FLAG BAD EQU HRRM OP,2(S) ;SET SYMBOL TABLE VALUE PUSHJ P,SYMDEF ;FLAG LINE DEFINED ON TRNN F,FR.UND ;IS EXPR UNDEFINED? JRST EQU1 ;NO, SKIP MOVE T1,2(S) ;GET FLAGS TLO T1,S.UNDF ;FLAG UNDEFINED HLLZM T1,2(S) ;PUT BACK, CLEAR VALUE OF EQU SETZ OP, ;A LITTLE HINT THAT ALL IS NOT OK JRST EQU2 ;SKIP EQU1: MOVE T1,2(S) ;GET FLAGS &C TLZ T1,S.UNDF!S.MAC ;MAKE SURE THAT THIS SYMBOL IS NOT UNDEFINED MOVEM T1,2(S) ;FOR CIRCULAR EQU MESS EQU2: POP P,(P) ;CAME VIA PUSHJ,.. TLZ F,FL.EQU!FL.SET ;DONE WITH EQU FLAG TRNN F,FR.LIB ;SKIP OUTPUT IF IN MACLIB PUSHJ P,NOPC TRNE F,FR.PS1 ;PASS1? JRST FPASS1 ;YES JRST FLUSHX ;NO DOOCT: TRZA F,FR.HEX DOHEX: TRO F,FR.HEX JRST FLUSH MACLIB: PUSHJ P,TOKEN ;GET LIBRARY NAME PUSHJ P,FLUSH ;FORCE SOURCE LINE OUT FIRST TRO F,FR.LIB ;FLAG IN MACLIB JRST MACLB0 INCLUD: PUSHJ P,TOKEN ;GET LIBRARY NAME PUSHJ P,FLUSH ;FORCE SOURCE LINE OUT FIRST MACLB0: SKIPN TOK ;FILE NAME POPJ P, ;IF NO NAME, QUIT MOVE T3,[POINT 6,TOK];CHECK OUT THE FILE NAME MOVE T4,[POINT 6,LIBNAM] SETZM LIBNAM ;INIT LIBNAM SETZM LIBEXT MACLB1: ILDB T1,T3 CAIN T1,'.' ;PERIOD? JRST MACLB2 ;YES JUMPE T1,MACLB3 ;END OF STRING CAMN T3,[600,,TOK+1] ;END OF TOK? JRST MACLB3 ;YES IDPB T1,T4 ;STORE IT JRST MACLB1 ;LOOP MACLB2: MOVE T4,[POINT 6,LIBEXT] JRST MACLB1 MACLB3: MOVE T1,LIBNAM SKIPN T2,LIBEXT MOVSI T2,'LIB' ;DEFAULT EXT IS .LIB SETZB T3,T4 ;IN DEFAULT PATH LOOKUP LIB,T1 ;LOOKUP FILE JRST [OUTSTR [ASCIZ/MACLIB file not found /] JRST FLUSH] PUSHJ P,FLUSH ;THROW OUT REST OF MACLIB LINE MOVE T1,MACPDL PUSH T1,INVECT ;SAVE INPUT VECTOR MOVEM T1,MACPDL MOVEI T1,-2 ;SIGNAL MACLIB INPUT MOVEM T1,INVECT POPJ P, ;RETURN DOPAGE: PUSHJ P,TOKEN PUSHJ P,DODATA SKIPE OP ;IF ARG GIVEN FOR PAGE MOVEM OP,PAGESZ ;SAVE IT AS THE NEW PAGE SIZE HLLOS LINCTR ;FORCE A PAGE BREAK JRST FLUSH EXITM: HRRZ T1,INVECT ;FIRST CHECK TO SEE IF WE'RE IN A MACRO CAIE T1,-1 ;SOURCE? CAIN T1,-2 ;MACLIB? JRST EXITX ;YES, ERROR CAIG T1,BAKPTR CAIGE T1,BAKBUF ;POINTS TO BAKBUF? JRST EXITM1 ;NO, MUST POINT TO MACRO PUSHJ P,EXITM1 ;YES, GET RID OF IT JRST EXITM ;AND CHECK AGAIN TO SEE IT THIS IS A MACRO EXITM1: PUSHJ P,FLUSH ;MAKE EVERYTHING LOOK NICE MOVE T1,MACPDL ;GET THE INVECT STACK POP T1,INVECT ;BAIL OUT OF THE MACRO MOVEM T1,MACPDL POPJ P, ;ALL DONE EXITX: WARN W.EXM ;WARN THAT WE'RE NOT IN A MACRO JRST FLUSH REPT: PUSHJ P,TOKEN PUSHJ P,DODATA ;GET THE REPT VALUE MOVEM OP,REPCNT ;SAVE IT MOVE T2,[MACDUM,,MACDUM+1] SETZM MACDUM BLT T2,MACDND ;CLEAR MACRO ARG TABLE MOVEI T1,3 ;INDICATE REPT AND NOT MACRO MOVEM T1,EOMFLG MOVEI S,REPADR-2 ;FAKE UP SYMTAB POINTER PUSHJ P,DOMC4B ;MAKE IT A MACRO IN REPBUF SKIPN REPCNT ;IF REPT 0 POPJ P, ;FORGET IT PUSHJ P,SETARG ;SET UP MACARG IN CASE LOCALS USED MOVEI I,177 IDPB I,T1 MOVEI I,1 IDPB I,T1 SETZ I, IDPB I,T1 ;END WITH NULL PUSHJ P,FLUSH MOVE T1,MACPDL PUSH T1,INVECT ;SAVE INPUT VECTOR ON SPECIAL STACK MOVE T2,REPADR ;POINT TO REPT HRLI T2,(POINT 7,0) MOVEM T2,INVECT MOVEM T1,MACPDL POPJ P, DOIFN: PUSHJ P,TOKEN PUSHJ P,DODATA AOS IFLEVL ;ONE MORE IF TRNE F,FR.OFF ;ALREADY OFF? JRST FLUSH SKIPE OP ;GOING OFF? JRST FLUSH ;NO TRNOFF: MOVE T1,IFLEVL MOVEM T1,OFFLVL ;YES, SAVE LEVEL OF OFF TRO F,FR.OFF ;SHUT OFF JRST FLUSH ;RETURN DOIFE: PUSHJ P,TOKEN PUSHJ P,DODATA AOS IFLEVL TRNE F,FR.OFF JRST FLUSH SKIPN OP JRST FLUSH JRST TRNOFF ;TURN OFF ELSE: TRNN F,FR.OFF ;ARE WE OFF? JRST TRNOFF ;NO, TURN OFF MOVE T1,OFFLVL ;GET OFF LEVEL CAMN T1,IFLEVL ;TURNED OFF AT THIS LEVEL? TRZ F,FR.OFF ;YES, TURN BACK ON JRST FLUSH ;FLUSH & RETURN ENDIF: TRNN F,FR.OFF ;OFF ALREADY? JRST ENDI2 ;NO, JUST DECR. & LEAVE MOVE T1,OFFLVL ;GET OFF LEVEL CAMN T1,IFLEVL ;WAS TURNED OFF AT THIS LEVEL? TRZ F,FR.OFF ;YES, TURN BACK ON ENDI2: SOSGE IFLEVL ;COUNT DOWN IF LEVELS WARN W.IF1 ;THERE WERE NO LEVELS! SKIPGE IFLEVL ;IF MESSED UP, SETZM IFLEVL ;FIX JRST FLUSH DOTITL: MOVE T1,[POINT 7,TITL] MOVEI T2,^D66 PUSHJ P,INCH CAIN I,15 JRST FLUSH IDPB I,T1 SOJG T2,.-4 JRST FLUSH DOSUBT: TRNE F,FR.PS1 ;IGNORE WHILE PASS1 JRST FLUSH PUSHJ P,EATSP ;EAT WHITE SPACE MOVE T3,[POINT 7,SUBTTL] SKIPA SUB2: PUSHJ P,INCH CAIE I,SEMICO CAIN I,CR ;END OF STRING? JRST SUB3 ;YES IDPB I,T3 ;STUFF JRST SUB2 SUB3: SETZ T1, IDPB T1,T3 JRST FLUSH DOCOMM: CAIA ;TRY BREAK CHARACTER FIRST PUSHJ P,INCH ;GET DELIMITER CAIE I,TAB CAIN I,SPACE JRST .-3 ;FORGET SPACES MOVE T2,I DOCOM1: PUSHJ P,INCH CAME I,T2 ;END OF STRING? JRST DOCOM1 ;NO, LOOP POPJ P, ;YES EVAL: IFN FTREL, TRZ F,FR.REL!FR.EXT ;INIT SETZ T1, ;CLEAR OUTPUT CAMN TOK,[SIXBIT/$/] ;DOLLAR ALL BY ITSELF JRST $PC ;YES, IT'S THE PC JUMPN TOK,DOSYM ;JUMP IF TOK NOT ZERO CAIE I,"'" ;INTEL QUOTE CAIN I,QUOTE JRST DOQUOT ;LITERAL CHARACTER POPJ P, ;MUST BE ZERO $PC: MOVE T1,PC ;DOLLAR IS PC IFN FTREL, TRO F,FR.REL ;DOLLAR IS ALSO RELOCATABLE PUSH P,T2 TLNE F,FL.DB!FL.DW!FL.EQU ;FROM DB,DW OR EQU? CAIA ;NO, SKIP OVER SOJ SOJ T1, ;INDICATE THE PC OF THE INSTRUCTION POP P,T2 POPJ P, DOSYM: PUSHJ P,GETNUM ;EVALUATE NUMERICALLY POPJ P, ;RETURN WITH NUMBER IN T1 PUSHJ P,SRCSYM ;NOT NUMBER,SEARCH SYMBOL TABLE JRST .+3 ;NOT THERE HRRZS T1 POPJ P, ;RETURN WITH VALUE IN T1 PUSH P,T2 PUSH P,T3 PUSH P,T4 TRO F,FR.EVL ;TELL SRCHOP NOT TO FLAG ERROR PUSHJ P,SRCH80 ;CHECK FOR OPCODE JRST DOSYM3 ;NO OP JRST DOSYM3 ;ILLEGAL OP TRZ F,FR.EVL ;CLEAR FLAG MOVE T2,OP8TAB(X) ;GET OPCODE MOVE T3,TYPLSH(X) ;GET TYPE TLNE T3,T.NREG ;USES REGISTER? JRST DOSYM1 ;NO ;CONT. DOSYM2: CAIE I,76 CAIN I,")" ;END OF EXPR? JRST DOSYM1 ;YES PUSH P,T2 PUSH P,T3 PUSHJ P,TOKEN PUSHJ P,EVAL CAILE T1,7 ERROR F.ILRG ANDI T1,7 POP P,T3 POP P,T2 TRNE T3,4 LSH T1,-1 LSH T1,(T3) OR T2,T1 TLZE T3,T.MOV ;A MOVE? JRST [TRZ T3,-1 JRST DOSYM2] DOSYM1: REPEAT 0,< ;DON'T GET FUSSY ABOUT OPCODES AS DATA CAIE I,76 CAIN I,")" ;EOE? JRST DOSYM4 ;YES WARN W.ILO1 ;ONLY GENERATE 1 BYTE OF DATA >; END REPEAT 0 DOSYM4: MOVE T1,T2 POP P,T4 POP P,T3 POP P,T2 POPJ P, DOSYM3: POP P,T4 POP P,T3 POP P,T2 SKIPE (S) ;NO SYMBOL? JRST FLUNDF ;SYMBOL ALREADY UNDEFINED DMOVEM TOK,(S) ;SAVE SYMBOL MOVSI T1,S.UNDF ;FLAG UNDEFINED MOVEM T1,2(S) FLUNDF: PUSHJ P,SRCSYM ;REFERENCE SYMBOL JFCL ;NOT FOUND? TRO F,FR.UND ;FLAG UNDEFINED SYMBOL TRNN F,FR.PS1 ;SKIP IF PASS1 ERROR F.UNDF ;REALLY IS UNDEFINED POPJ P, ;BURP UP DOQUOT: PUSHJ P,INCH ;GET THE NEXT CHARACTER MOVE T1,I ;JUST SAVE IT PUSHJ P,INCH ;EAT TRAILING QUOTE CAIE I,"'" CAIN I,QUOTE JRST .+4 ;OK THEN LSH T1,10 ;SHIFT OVER ADD T1,I ;MERGE JRST .-6 ; PUSH P,T1 ;SAVE T1 ; PUSHJ P,TOKEN ;LOAD UP LIKE TOKEN ; POP P,T1 ;RESTORE T1 ; POPJ P, ;RETURN JRST INCH ;SEARCH SYMBOL TABLE FOR ENTRY IN TOK. ;NON-SKIP RETURN: SYMBOL UNDEFINED. S CONTAINS 1ST FREE ENTRY ;SKIP RETURN: T1 CONTAINS VALUE OF SYMBOL. S POINTS TO ENTRY IN SYMTAB ;SYMTAB ENTRY: SIXBIT/NAME/ ; SIXBIT/MORE NAME/ ; FLAGS,,VALUE ;SEE M80UNV FOR FLAGS (S.????) ; LINE#,,LINK TO NEXT LINE# ;1B0 SET IF DEFINED ON LINE# ; 0,,LINK TO OVERFLOW ; 0 IF NO MORE ENTRIES SRCSYM: IFN FTREL, TRZ F,FR.REL!FR.EXT TLNE F,FL.Z80 JRST SRCS2 ;Z80 CODE DOESN'T WANT TO KNOW ABOUT THIS MOVSI S,-PRELEN ;GET LENGTH OF PRE DEFINED TABLE HRRI S,PRETAB ;ADDRESS OF PERMANENT SYMBOLS SRCS1: CAMN TOK,(S) ;MATCH? JRST PREMAT AOBJN S,.+1 AOBJN S,SRCS1 ;NO, LOOP ;LOOK IN REGULAR SYMBOL TABLE SRCS2: PUSH P,T2 ;DON'T DESTROY T2 MOVE T2,[POINT 6,TOK];THIS ASSUMES SYMSIZ IS FAIRLY CLOSE TO 64 SETZ T1, TLNN T2,770000 ;ONLY HASH ON 1ST WORD OF SYMBOL JRST .+4 ILDB S,T2 ADD T1,S JRST .-4 IDIVI T1,SYMSIZ ;GET TOKEN MODULO TABLE LENGTH MOVE T1,T2 POP P,T2 IMULI T1,5 ;5 WORDS/ENTRY MOVEI S,SYMTAB(T1) ;GET HASHED TABLE LOCATION SRCL: CAMN TOK,(S) CAME TOK+1,1(S) CAIA JRST SRCF SKIPN (S) ;EMPTY? POPJ P, ;YES, RETURN WITH S SET UP SKIPN 4(S) ;LINK THERE? JRST MAKLNK ;NO. MAKE NEW ENTRY & RETURN HRRZ S,4(S) ;NEW LINK JRST SRCL ;LOOP PREMAT: MOVE T1,1(S) ;GET FLAGS,VALUE JRST CPOPJ2 ;SKIP RETURN MAKLNK: MOVE T1,.JBFF## ;GET JOBFF HRRM T1,4(S) ;MAKE NEW LINK HRRM T1,S ADDI T1,5 ;MAKE NEW JOBFF PUSHJ P,MEMXPN ;EXPAND CORE IF NECESSARY MOVEM T1,.JBFF## ;STUFF IT POPJ P, ;DONE SRCF: MOVE T1,2(S) ;GET FLAGS,VALUE PUSH P,T2 ;SAVE T2 MOVE T2,T1 ;IN T2 IFN FTREL,< TLNE T2,S.EXT ;EXTERNAL? HRR T2,PC ;YES, SAVE CURRENT PC FOR NEXT SYMBOL > TRZN F,FR.NRF ;A REFERENCEABLE SYMBOL? TLO T2,S.REF ;YES, REFERENCE SYMBOL MOVEM T2,2(S) ;SAVE FLAGS,VALUE TRNE F,FR.PS1 ;PASS1? JRST SRCX ;YES, NO REF ON PASS1 TRNN F,FR.LST ;LISTING REFERENCES? JRST SRCX ;NO USE GATHERING THEM THEN SKIPE 3(S) ;NO REFERENCE? JRST NXTREF ;NO MOVE T2,LINENO ;GET CURRENT LINENO PUSHJ P,CHKMAC ;IF IN LIMBO, SOJ T2, ;POINT TO LAST LINE HRLM T2,3(S) ;SAVE IN LH JRST SRCX ;DONE NXTREF: PUSH P,T1 ;SAVE T1 PUSH P,T3 ;AND T3 MOVEI T1,3(S) ;GET ADDRESS MOVE T2,3(S) ;GET LINE,,LINK SRCLNK: HLRZ T3,T2 ;GET LINE NUMBER IN CHAIN ANDI T3,377777 ;JUST LINE NUMBER PUSHJ P,CHKMAC ;ADJUST AOJ T3, ;INCASE IN MACRO THAT IS SUPPRESSED CAMN T3,LINENO JRST SRCX0 ;YES, QUIT NOW TRNN T2,-1 ;ANY LINK? JRST SRCI ;NO, END OF CHAIN HRRZ T1,T2 ;SAVE LINK MOVE T2,(T1) ;FOLLOW LINK JRST SRCLNK ;LOOP TO END OF CHAIN SRCI: HRR T2,.JBFF## ;GET FIRST FREE AS LINK MOVEM T2,(T1) ;SAVE WITH NEW LINK HRRZ T1,T2 ;LINK ADDRESS IN T1 MOVE T2,LINENO ;GET LINE NUMBER PUSHJ P,CHKMAC ;IF WE'RE IN LIMBO SOJ T2, ;BACK UP TO MACRO INVOCATION HRLZM T2,(T1) ;STORE IT AOJ T1, ;NEW JOBFF PUSHJ P,MEMXPN ;EXPAND CORE MOVEM T1,.JBFF## SRCX0: POP P,T3 ;RESTORE T3 POP P,T1 ;RESTORE T1 SRCX: POP P,T2 TLNE T1,S.UNDF ;UNDEFINED SYMBOL? POPJ P, ;YES, TIME TO LEAVE IFN FTREL,< TLZE T1,S.REL ;RELOCATABLE? TRO F,FR.REL ;YES, FLAG IT TLZE T1,S.EXT ;EXTERNAL? TRO F,FR.EXT ;YES > CAIA CPOPJ3: AOS (P) ;DOUBLE SKIP RETURN CPOPJ2: AOS (P) ;CAUSE SKIP RETURN CPOPJ: POPJ P, ;RETURN ;SNEAK ROUTINE. WHILE FR.SNK IS ON INCH WILL COPY ALL INPUT VIA BAKPTR ;WHEN DONE, SNEAK WILL TELL INCH THAT THE PREVIOUS INPUT IS NOW A MACRO ;IN EFFECT, NO INPUT WAS DONE (EXCEPT THAT TOK CONTAINS THE NEXT TOKEN) SNEAK: TRO F,FR.SNK ;SAY WE'RE SNEAKING AROUND PUSH P,I PUSH P,T1 PUSH P,T2 MOVE T2,[POINT 7,BAKBUF] ;SET UP POINTER FOR INCH MOVEM T2,BAKPTR ;SAVE IT PUSHJ P,TOKEN ;GET TOKEN SNEAKX: MOVEM I,SNEAKI ;SAVE THE BREAK CHARACTER MOVEI T1,177 IDPB T1,BAKPTR ;STORE "END OF BAKBUF" MOVEI T1,1 IDPB T1,BAKPTR MOVE T1,MACPDL ;GET MACPDL HRRZ T2,INVECT ;GET INVECT POINTER CAIG T2,BAKPTR CAIGE T2,BAKBUF ;POINTS TO BAKBUF?? (IF SO, DON'T SAVE) PUSH T1,INVECT ;SAVE OLD POINTER MOVE T2,[POINT 7,BAKBUF] ;POINT TO BACKUP BUFFER MOVEM T2,BAKPTR ;HELP OUT THE OTHER FOLKS WHO USE BAKPTR MOVEM T2,INVECT ;SOURCE IS NOW IN BAKBUF MOVEM T1,MACPDL ;PUT PDL BACK IN STORAGE TRZ F,FR.SNK ;DONE SNEAKING POP P,T2 POP P,T1 POP P,I POPJ P, ;DONE GETNUM: MOVE T3,[POINT 6,TOK] SETZ T1, ;CLEAR TOTAL ILDB T2,T3 ;GET THE 1ST CHARACTER CAIG T2,'9' CAIGE T2,'0' ;NUMERIC? JRST CPOPJ2 ;NO - SHOULDN'T BE HERE PUSH P,T4 ;SAVE T4 PUSH P,I ;AND I GETN1: JUMPE T2,GETN2 ;END OF TOKEN MOVE T4,T3 ;SAVE POINTER TO LAST CHAR ILDB T2,T3 ;GET NEXT CHAR JRST GETN1 ;LOOP GETN2: MOVE T3,T4 ;GET BACK POINTER LDB T4,T3 ;GET LAST CHARACTER MOVEI I,^D10 ;ASSUME DECIMAL CAIE T4,'O' CAIN T4,'Q' ;OCTAL MOVEI I,10 CAIN T4,'H' ;HEX MOVEI I,20 CAIN T4,'B' ;BINARY MOVEI I,2 CAIE T4,'D' ;GET RID OF THE LAST CHARACTER CAIN T4,'H' ;IF IT IS A RADIX CHARACTER DPB T1,T3 CAIE T4,'Q' CAIN T4,'O' DPB T1,T3 CAIN T4,'B' DPB T1,T3 MOVE T3,[POINT 6,TOK] GETNL: CAMN T3,[600,,TOK+1] JRST GETNX ILDB T2,T3 ;GET A CHARACTER JUMPE T2,GETNX ;DONE. NORMAL RETURN CAIN T2,'$' ;DUMMY DOLLAR? JRST GETNL ;YES, IGNORE IT IMUL T1,I ;SHIFT TOTAL BY RADIX CAILE T2,'9' ;IF GREATER THAN DECIMAL SUBI T2,'A'-'9'-1 ;THROW OUT OFFSET ADDI T1,-20(T2) JRST GETNL GETNX: POP P,I POP P,T4 POPJ P, SETARG: MOVE T2,ARGPDL PUSH T2,ARGPTR ;SAVE CURRENT MACRO'S ARGS MOVEM T2,ARGPDL MOVE T1,ARGPTR ILDB T2,T1 ;SEARCH FOR END OF CURRENT MACRO'S ARGS SKIPE T2 JRST .-2 MOVEM T1,ARGPTR ;SAVE START OF THIS MACRO'S ARGS POPJ P, EATSP: CAIE I,TAB CAIN I,SPACE CAIA POPJ P, PUSHJ P,INCH JRST EATSP SETMAC: PUSHJ P,SETARG PUSHJ P,EATSP CAIA SETM0: PUSHJ P,INCH PUSHJ P,BREAK JRST SETM1 IDPB I,T1 JRST SETM0 SETM1: SETZM BRAKLV CAIE I,QUOTE CAIN I,"'" JRST SETM3 ;DO QUOTED STRING CAIN I,"<" ;START EXPR? JRST SETM4 ;YES CAIN I,"%" ;EVAL ARG? JRST SETM5 STM1.5: PUSH P,I MOVEI I,177 IDPB I,T1 MOVEI I,1 IDPB I,T1 POP P,I CAIN I,"," ;ANOTHER ARG? JRST SETM0 ;YES SETM2: SETZ I, IDPB I,T1 ;END WITH NULL PUSHJ P,FLUSH MOVE T1,MACPDL PUSH T1,INVECT ;SAVE INPUT VECTOR ON SPECIAL STACK MOVE T2,2(S) ;GET POINTER TO MACRO HRLI T2,(POINT 7,0) MOVEM T2,INVECT MOVEM T1,MACPDL POPJ P, SETM3: MOVEM I,DELIM IDPB I,T1 PUSHJ P,INCH CAIE I,CR CAIN I,LF JRST SETM1 CAME I,DELIM JRST SETM3+1 IDPB I,T1 JRST SETM0 SETM4: AOS BRAKLV ;KEEP TRACK OF NESTED BRACKETS SETM4A: PUSHJ P,INCH TRNE F,FR.END ;END IS ONLY ABNORMAL EXIT JRST STM1.5 CAIE I,">" JRST [IDPB I,T1 CAIN I,"<" JRST SETM4 JRST SETM4A] SOSE BRAKLV JRST [IDPB I,T1 JRST SETM4A] JRST SETM0 SETM5: PUSH P,T1 ;SAVE POINTER PUSH P,S ;SAVE MACRO POINTER PUSHJ P,TOKEN ;GET THE DATA PUSHJ P,DODATA ;COMP. EFFECTIVE ADDR POP P,S POP P,T1 MOVE T2,OP PUSHJ P,SETM5A ;STORE NUMBER JRST SETM1 ;GO BACK SETM5A: IDIVI T2,^D10 ;DIVIDE BY DEFAULT RADIX JUMPE T2,.+4 PUSH P,T3 PUSHJ P,SETM5A POP P,T3 ADDI T3,"0" IDPB T3,T1 POPJ P, INCH: PUSH P,T1 ;SAVE T1 INCH1: MOVE T1,INVECT ;GET VECTOR CAIN T1,-1 ;DEFAULT TO SOURCE? JRST INCHS ;YES CAIN T1,-2 ;DEFAULT TO LIBRARY? JRST INCHL ;YES INCHM0: ILDB I,INVECT ;GET CHARACTER FROM MACRO BODY SKIPN I ;IS THERE A MACRO ARG? PUSHJ P,DOLSYM ;NEEDS LOCAL SYMBOL HERE CAIN I,177 JRST INCHM3 TRNE F,FR.LIB ;IN MACLIB? JRST TPOPJ ;YES, FINISHED HRRZ T1,INVECT ;GET INVECT POINTER CAIG T1,BAKPTR CAIGE T1,BAKBUF ;IN MACRO? CAIA ;YES JRST INCHM6 ;NO MOVE T1,LTYPE ;GET DEGREE OF LISTING CAIE T1,2 ;MACRO SUPPRESSION? CAIN T1,3 ;XMAC IMPLIES SALL CAIA JRST INCHX ;IN MACRO, NOT SUPPRESSED TRNE F,FR.SNK ;IN MACRO, SUPPRESSED, AND SNEAKING? IDPB I,BAKPTR ;YES, SAVE CHAR HERE POP P,T1 POPJ P, ;SUPPRESS ALL THIS FOOLISHNESS INCHM6: PUSH P,T2 ;HERE IF INVECT = BAKBUF ; MAKE SURE NOT IN MACRO MOVE T2,MACPDL ;GET INVECT PDL INCHM7: POP T2,T1 ;GET NEXT HIGHER LEVEL HRRZS T1 CAIE T1,-1 CAIN T2,-2 JRST INCHM8 ;SOURCE LEVEL CAIG T1,BAKPTR CAIGE T1,BAKBUF ;IN MACRO? CAIA ;YES JRST INCHM7 ;NO, TRY AGAIN MOVE T1,LTYPE CAIE T1,2 ;MACRO SUPPRESSION? CAIN T1,3 JRST T2POPJ ;YES, QUIT NOW INCHM8: POP P,T2 JRST INCHX INCHM3: ILDB I,INVECT ;GET CODE CAIE I,1 CAIN I,2 ;END OF MACRO? JRST INCHM1 ;YES CAIN I,3 ;END OF REPT? JRST INCHM5 ;YES MOVE T1,MACPDL PUSH T1,INVECT ;SAVE OLD INVECT MOVEM T1,MACPDL MOVE T1,ARGPTR ;INPUT IS FROM MACRO ARGS MOVEM T1,INVECT MOVE T1,I ;PUT ARG POSITION IN T1 ANDI T1,77 JUMPN T1,INCHM4 ;SKIP SPECIAL TEST IF NOT 1ST ARG PUSH P,INVECT ;SAVE INPUT VECTOR ILDB T1,INVECT CAIN T1,177 ;LOOKING FOR 1ST ARG AND NONE THERE? PUSHJ P,DOLSYM ;MAKE A LOCAL SYMBOL FOR THE NULL ARG POP P,INVECT ;RESTORE VECTOR JRST INCHM0 ;GO DOIT INCHM2: JUMPE T1,INCHM0 ;INVECT NOW POINTS TO RIGHT SPOT INCHM4: ILDB I,INVECT SKIPN I ;END OF ARGS? PUSHJ P,DOLSYM ;NEEDS LOCAL SYMBOL HERE CAIE I,177 ;END OF ARG? JRST INCHM4 ;NO, LOOP ILDB I,INVECT ;GET ^A SOJA T1,INCHM2 ;SEE IF WE'RE AT THE RIGHT SPOT INCHM1: MOVE T1,MACPDL POP T1,INVECT ;RESTORE OLD POINTER MOVEM T1,MACPDL CAIE I,2 ;END OF MACRO? CAIN I,3 JRST [MOVE T1,ARGPDL ;RESTORE MACRO ARG CONTEXT POP T1,ARGPTR MOVEM T1,ARGPDL JRST INCH1] JRST INCH1 DOLSYM: PUSH P,INVECT ;SAVE THE INPUT VECTOR MOVEI I,"." ;START THE SYMBOL WITH ".." DPB I,INVECT IDPB I,INVECT PUSH P,T1 ;SAVE T1 PUSH P,T2 PUSH P,T3 MOVE T1,LOCSYM ;GET THE VALUE OF THE LOCAL SYMBOL MOVEI T3,4 ;4 DIGITS PUSHJ P,DOSNUM ;PUT THE NUMBER IN INVECT AOS LOCSYM ;MAKE NEW SYMBOL VALUE MOVEI I,177 IDPB I,INVECT MOVEI I,1 ;CAP OFF SYMBOL IDPB I,INVECT SETZ I, IDPB I,INVECT POP P,T3 POP P,T2 POP P,T1 POP P,INVECT LDB I,INVECT ;GET FIRST BYTE IN I POPJ P, DOSNUM: IDIVI T1,^D10 ;OUTPUT T1 AS DECIMAL NUMBER SOJLE T3,.+4 PUSH P,T2 PUSHJ P,DOSNUM POP P,T2 ADDI T2,60 IDPB T2,INVECT POPJ P, INCHM5: SOSG REPCNT ;KNOCK DOWN REPT COUNT JRST INCHM1 MOVE T2,ARGPTR ;POINT TO ARGS MOVEI T1,177 ;START NEW REPT WITH A CLEAN START IDPB T1,T2 MOVEI T1,1 IDPB T1,T2 SETZ T1, IDPB T1,T2 MOVE T2,REPADR ;POINT TO REPT HRLI T2,(POINT 7,0) MOVEM T2,INVECT JRST INCHM0 ;DOIT OVER AGAIN INCHL:; POP P,T1 INCHL1: SOSGE MBUF+2 JRST INCHL2 ILDB I,MBUF+1 JUMPE I,INCHL1 JRST INCHX INCHL2: IN LIB, JRST INCHL1 CLOSE LIB, TRZ F,FR.LIB ;FLAG END OF MACLIB PUSH P,T1 MOVE T1,MACPDL POP T1,INVECT ;RESTORE ORIGINAL INVECT BEFORE MACLIB MOVEM T1,MACPDL POP P,T1 JRST INCH1 ;AND GET ANOTHER CHARACTER INCHS: SOSGE IBUF+2 JRST .+3 ILDB I,IBUF+1 JRST INCHX IN SRC, JRST INCHS ENDIT: TRZN F,FR.PS1 ;PASS1? JRST WRAPUP ;NO TRZ F,FR.END ;TURN OFF END FROM PASS1 (SHOULD ALREADY BE OFF BUT ...) SETZ E, ;FORGET ALL PASS1 ERRORS TRZE F,FR.OFF ;ARE WE ASSEMBLING? WARN W.IF2 ;NO SETZM IFLEVL SETZM OFFLVL MOVE T1,ORGXR ;GET INDEX MOVEM BC,ORGBLK(T1) ;STORE COUNT SETZ T1, ;YES PUSHJ P,OPNOBJ ;OPEN OBJECT DEVICE SETZM ORGXR ;RESET FOR OUTPUT IFN FTITLE,< MOVE T2,[POINT 7,TITL] PUSHJ P,NOALT3 > NOALT1: PUSHJ P,HEXHED ;DO HEDDER MOVE T1,FILNAM## MOVE T2,FILEXT## SETZ T3, MOVE T4,PPN## LOOKUP SRC,T1 JRST NOFILE## JRST RESTAR NOALT3: ILDB T1,T2 JUMPN T1,[PUSHJ P,HEXOX JRST NOALT3] BCRLF: MOVEI T1,15 PUSHJ P,HEXOX MOVEI T1,12 JRST HEXOX HEXHED: PUSHJ P,BCRLF IFN FTREL,< MOVE T1,RELPTR ;GET SIZE OF RELTAB CAIGE T1,^D15 ;ENOUGH TO DO A LINE? JRST HEXH2 ;NO MOVEI T2,^D15 ;YES, DO 15 PUSHJ P,TYPE04 ;DO RELOCATABLE TYPE HEXH2:> ;END IFN FTREL MOVE T4,ORGXR ;GET INDEX MOVE T1,ORGBLK(T4) ;GET BYTE COUNT LEFT IN BLOCK SUBI T1,^D30 ;SUBTRACT WHAT WE'RE GOING TO USE JUMPLE T1,.+4 ;<= 30 MOVEM T1,ORGBLK(T4) ;SAVE REST MOVEI T1,^D30 ;30 BYTES JRST .+3 MOVE T1,ORGBLK(T4) ;GET WHAT'S LEFT SETZM ORGBLK(T4) ;FLAG BLOCK EMPTY MOVEM T1,CHECK MOVE BC,T1 ;SAVE BYTES TO OUTPUT JUMPE BC,EOFBYT ;JUMP IF TIME TO DO EOF STUFF MOVEI T1,":" ;DO TYPE00 HEADER PUSHJ P,HEXOX MOVE T1,BC ;GET BYTE COUNT PUSHJ P,HEXBYT ;OUTPUT BYTE COUNT MOVE T1,ORGBLK+1(T4) ;GET START ADDRESS OF BLOCK LSH T1,-10 ;GET HIGH BYTE ADDM T1,CHECK PUSHJ P,HEXBYT ;OUTPUT HIGH ADDRESS MOVE T1,ORGBLK+1(T4) ADDM T1,CHECK PUSHJ P,HEXBYT ;OUTPUT LOW BYTE MOVE T1,ORGBLK+1(T4) ADD T1,BC ;LAST S.A. + BYTE COUNT MOVEM T1,ORGBLK+1(T4) ;= NEW S.A. SETZ T1, ;DATA (TYPE 00) SKIPN BC ;IF DATA, SKIP MOVEI T1,1 ;IF EOF, (TYPE 01) JRST HEXBYT ;OUTPUT RECORD TYPE IFN FTREL,< TYPE04: TRNE F,FR.ORG ;RELOCATING? POPJ P, ;NO MOVEI T1,DOLLAR ;FLAG NON-INTEL RECORD PUSHJ P,HEXOX MOVE T1,T2 ;GET WORD COUNT IMULI T1,2 ;MAKE BYTE COUNT MOVEM T1,CHECK ;CHECKSUM PUSHJ P,HEXBYT ;OUTPUT SETZ T1, ;NO START ADDRESS PUSHJ P,HEXBYT PUSHJ P,HEXBYT MOVEI T1,4 ;TYPE 04 (RELOCATABLE) ADDM T1,CHECK PUSHJ P,HEXBYT SETZ T3, ;ZERO XR T04.1: MOVE T1,RELTAB(T3) ;GET ADDRESS LSH T1,-10 ADDM T1,CHECK PUSHJ P,HEXBYT MOVE T1,RELTAB(T3) ;GET LO ADDRESS ANDI T1,377 ADDM T1,CHECK PUSHJ P,HEXBYT AOJ T3, SOJG T2,T04.1 ;LOOP MOVE T1,CHECK ANDI T1,377 MOVNS T1 PUSHJ P,HEXBYT ;OUTPUT CHECKSUM PUSHJ P,BCRLF ;CRLF ;SHUFFLE CONTENTS OF RELTAB BACK TO BOTTOM SETZ T2, SKIPN T1,RELTAB(T3) JRST T04.2 MOVEM T1,RELTAB(T2) AOJ T2, AOJA T3,.-4 T04.2: MOVEM T2,RELPTR ;RESET POINTER MOVSI T3,RELTAB(T2) HRRI T3,RELTAB+1(T2) SETZM RELTAB(T2) BLT T3,RELEND POPJ P, > ;END IFN FTREL EOFBYT: IFN FTREL,< TRNN F,FR.ORG ;RELOCATING? SKIPN RELPTR ;RELTAB EMPTY? JRST DOSYMT ;DO SYMBOL TYPE MOVE T2,RELPTR ;GET COUNT CAIL T2,^D15 MOVEI T2,^D15 ;MAX 15 AT A TIME PUSHJ P,TYPE04 ;DO A LINE OF TYPE 04 JRST EOFBYT ;LOOP DOSYMT: MOVEI S,SYMTAB ;XR EOFL: CAIL S,SYMEND ;END ON SYMTAB? JRST TYPE01 ;YES SKIPN (S) ;EMPTY? JRST EOFX ;YES, SKIP PUSH P,S ;SAVE POINTER EOFL1: MOVE T3,2(S) TLNE T3,S.INT!S.EXT ;GOOD STUFF? PUSHJ P,TYPE02 ;YES SKIPE S,4(S) JRST EOFL1 POP P,S EOFX: ADDI S,5 JRST EOFL ;LOOP TYPE02: MOVEI T1,DOLLAR ;TYPE 2 OR 3 LEADER PUSHJ P,HEXOX SETZM CHECK PUSH P,T3 DMOVE T2,(S) ;GET NAME MOVE T4,[POINT 6,T2] T02.1: ILDB T1,T4 ;GET BYTE ADDI T1,40 ;TO ASCII ADDM T1,CHECK PUSHJ P,HEXOX CAME T4,[600,,T3] ;ALL 12? JRST T02.1 ;NO POP P,T3 TLNE T3,S.INT ;INTERNAL MOVEI T1,2 ;IS TYPE 02 TLNE T3,S.EXT ;EXTERNAL MOVEI T1,3 ;IS TYPE 03 PUSHJ P,HEXBYT ;OUTPUT SYMBOL TYPE ADDM T1,CHECK HRRZ T1,T3 ;GET VALUE LSH T1,-10 ;GET HIGH PART ADDM T1,CHECK PUSHJ P,HEXBYT HRRZ T1,T3 ANDI T1,377 ADDM T1,CHECK PUSHJ P,HEXBYT MOVE T1,CHECK ANDI T1,377 MOVNS T1 PUSHJ P,HEXBYT PUSHJ P,BCRLF POPJ P, > ;END IFN FTREL TYPE01: MOVEI T1,":" ;OUTPUT HEADER PUSHJ P,HEXOX SETZ T1, ;LENGTH 0 PUSHJ P,HEXBYT MOVE T1,STARTA ;GET START ADDRESS LSH T1,-10 PUSHJ P,HEXBYT MOVE T1,STARTA ANDI T1,377 PUSHJ P,HEXBYT MOVEI T1,1 ;TYPE 01 PUSHJ P,HEXBYT JRST BCRLF ;CRLF INCHX: POP P,T1 JUMPE I,INCH ;CAST OFF NULLS TRNE F,FR.SNK ;IF SNEAKING, JRST [IDPB I,BAKPTR ;SAVE CHARACTER POPJ P,] ;DON'T PRINT TWICE TRNE F,FR.LIB ;IF IN MACLIB POPJ P, ;IGNORE IT TRNE F,FR.PS1 JRST PAS1IX ;SKIP ALL PROCESSING OF CHARACTER IF PASS1 SKIPN LBTP MOVE LBTP,[POINT 7,LINBLK] CAIE I,FF ;DON'T GO PUTTING FF IN LINBLK! IDPB I,LBTP CAIE I,LF ;IF LF, CAIN I,FF ;OR FF, CAIA ;SKIP INTO EOL ROUTINE POPJ P, ;ELSE WE'RE DONE PUSH P,T1 PUSH P,T2 CAIN I,FF JRST DOFFX ;IF FF, SKIP SOME STUFF MOVEI T1,TAB TRNE F,FR.LOP ;IF CODE GENERATED JRST INCHX1 ;JUST ONE TAB PUSHJ P,DOLINO ;PRINT LINE # AS A LAST RESORT TRNE F,FR.HEX JRST INCHX0 PUSHJ P,LOUCH PUSHJ P,LOUCH INCHX0: PUSHJ P,LOUCH PUSHJ P,LOUCH INCHX1: PUSHJ P,LOUCH TRZ F,FR.LIN ;CLEAR LINE # PRINTED FLAG FOR NEXT LINE MOVE LBTP,[POINT 7,LINBLK] ILDB T1,LBTP JUMPE T1,CHKERR PUSHJ P,LOUCH SKIPE E OUTCHR T1 JRST .-5 CHKERR: JUMPE E,NOERR HLRZ T1,E OUTCHR T1 PUSHJ P,LOUCH MOVE T2,ERRTAB-1(E) MOVE LBTP,[POINT 7,(T2)] ILDB T1,LBTP JUMPE T1,.+4 PUSHJ P,LOUCH OUTCHR T1 JRST .-4 PUSHJ P,LCRLF OUTSTR CRLF SETZ E, NOERR: SETZM LINBLK MOVE T1,[LINBLK,,LINBLK+1] BLT T1,LINEND SETZ LBTP, MOVE T1,LINCTR CAMG T1,PAGESZ ;ON NEW PAGE? JRST NOFF ;NO JRST DOFF ;YES, WRITE HEADER DOFFX: AOS PAGENO SETZM SUBPAG ;REAL PAGES HAVE NO SUB PAGE MARK DOFF: PUSHJ P,DOHDFF ;GO DO THE HEADING NOFF: POP P,T2 POP P,T1 PAS1IX: CAIN I,FF ;IF FF, JRST INCH ;EAT IT POPJ P, LOUCH: TRNE F,FR.LST ;IF NOT LISTING TRNE F,FR.PS1 ;OR ON PASS 1 POPJ P, ;FORGET IT PUSH P,T1 MOVE T1,LTYPE ;GET LTYPE CAIN T1,4 ;XLIST? JRST TPOPJ ;YES POP P,T1 ;NO SOSGE LBUF+2 JRST LOUCH1 IDPB T1,LBUF+1 CAIN T1,LF AOS LINCTR CAIN T1,CR TRO F,FR.BOL ;AT START OF LISTING LINE POPJ P, LOUCH1: OUTPUT LST, JRST LOUCH OUTOP: PUSHJ P,LSTPC MOVE T1,OP PUSHJ P,LSTOP POPJ P, ;RETURN NOPC: PUSHJ P,DOLINO ;PRINT THE LINE NUMBER TRZ FR.LIN ;READY TO PRINT A NEW LINE MOVEI T1,TAB PUSHJ P,LOUCH TRNN F,FR.HEX PUSHJ P,LOUCH MOVE T1,OP SKIPGE T1 ;IF NEGATIVE SETZ T1, ;MAKE ZERO MOVEI T3,6 TRO F,FR.LOP PUSHJ P,LSTNUM MOVEI T1,TAB PUSHJ P,LOUCH TRNN F,FR.HEX JRST LOUCH POPJ P, HEXOX: SOSL OBUF+2 JRST [IDPB T1,OBUF+1 POPJ P,] OUTPUT OBJ, JRST HEXOX HEXOUT: ADDM T1,CHECK PUSHJ P,HEXBYT SOJG BC,CPOPJ PUSH P,T1 PUSH P,T2 PUSH P,T3 PUSH P,T4 MOVE T1,CHECK ANDI T1,377 MOVNS T1 PUSHJ P,HEXBYT MOVE T4,ORGXR ;GET INDEX SKIPN ORGBLK(T4) ;STILL GOOD BYTE COUNT? ADDI T4,2 ;NEXT BLOCK MOVEM T4,ORGXR ;SAVE INDEX PUSHJ P,HEXHED ;DO HEADER T4POPJ: POP P,T4 T3POPJ: POP P,T3 T2POPJ: POP P,T2 TPOPJ: POP P,T1 POPJ P, HEXBYT: PUSH P,T1 LSH T1,-4 PUSHJ P,NYBBLE ;OUTPUT HIGH NYBBLE POP P,T1 PUSH P,T1 PUSHJ P,NYBBLE POP P,T1 POPJ P, NYBBLE: ANDI T1,17 CAILE T1,^D9 JRST .+3 ADDI T1,60 JRST HEXOX ADDI T1,"A"-^D10 JRST HEXOX WRAPUP: PUSHJ P,PRTSYM ;PRINT SYMBOL TABLE RELEAS SYM, RELEAS LST, RELEAS OBJ, IFN FTSTAT,< TLNE F,FL.LNR ;LIST NON-REF SYMBOLS? PUSHJ P,REFLOP ;YES > AND F,[XWD FL.CCL,0];CLEAR ALL FLAGS BUT FL.CCL JRST START## IFN FTSTAT,< ;PRINT ALL DEFINED BUT NOT REFERENCED SYMBOLS REFLOP: MOVEI S,SYMTAB RLOOP4: CAIN S,SYMEND ;END OF TABLE? POPJ P, ;DONE SKIPN (S) ;IF EMPTY JRST RLOOP5 ;GET NEXT PUSH P,S ;SAVE IT PUSHJ P,RLINK ;RUN OUT THIS BRANCH POP P,S ;DONE RLOOP5: ADDI S,5 ;GET NEXT JRST RLOOP4 ;LOOP RLINK: MOVE T2,2(S) TLNN T2,S.REF!S.MAC ;IS SYMBOL REFERENCED OR A MACRO? JRST RLOOP0 ;NO RLOOP: SKIPN S,4(S) ;IS THERE A LINK? POPJ P, ;NO JRST RLINK RLOOP0: SKIPN (S) JRST RLOOP TRON F,FL.HED OUTSTR [ASCIZ/Unreferenced labels: /] MOVE T4,[POINT 6,(S)] RLOOP1: ILDB T2,T4 JUMPE T2,RLOOP2 ADDI T2,40 OUTCHR T2 CAME T4,[600+S,,1] JRST RLOOP1 RLOOP2: OUTSTR [ASCIZ/ /] JRST RLOOP > ;END IFN FTSTAT PRTSYM: SKIPN CREFSW ;CREF? SKIPE SYMBSW ;OR SYMBOL FILE? CAIA ;YES, SKIP POPJ P, ;DON'T BE SILLY THEN SETZB BC,E ;CLEAR COUNTER SETOM PAGENO ;FLAG SYMBOL TABLE PAGE MOVEI T1,1 ;SYMBOL TABLE ALWAYS STARTS WITH SUBPAGE MOVEM T1,SUBPAG ;NUMBER 1 SKIPE CREFSW ;CREF? PUSHJ P,DOHDFX ;PRINT NEW HEADER PRTS: HRLOI T1,377777 ;+INFINITY SETZ P1, MOVEI S,SYMTAB PRT0: SKIPN (S) ;EMPTY? AOJA P1,PRT1 ;YES PUSH P,S ;SAVE S PUSHJ P,PRT10 ;CHECK OUT THIS BRANCH POP P,S PRT1: ADDI S,5 ;NEXT LINK CAIE S,SYMEND ;ALL DONE? JRST PRT0 ;NO, LOOP SKIPE T1 ;QUIT IF WE GOT TO BLANK SYMBOLS CAMN T1,[377777,,-1] ;NO SYMBOLS SMALLER THAN +INFINITY? JRST PRTX ;DONE AOJ BC, ;COUNT IT MOVE S,T2 SKIPN CREFSW ;IF NOT CREF JRST PRT1B ;DON'T PRINT STUFF DMOVE T2,(S) ;GET SMALLEST SYMBOL PUSHJ P,PUTSIX ;FOR LISTING MOVEI T1,TAB PUSHJ P,LOUCH MOVE T1,2(S) ;GET FLAGS,VALUE TLNE T1,S.UNDF ;UNDEFINED? JRST [MOVEI T2,[ASCIZ/Undf/] PUSHJ P,PUTSTR JRST PRT4] TLNE T1,S.MAC JRST [MOVEI T2,[ASCIZ/Macro/] PUSHJ P,PUTSTR JRST PRT4] HRRZ T1,2(S) ;JUST VALUE MOVEI T3,6 PUSHJ P,LSTNUM ;PRINT IT PRT1B: SKIPN SYMBSW ;DOING SYMBOL FILE? JRST PRT4 ;NO MOVE T1,SYMTYP ;GET 10 OR 20 JUMPE T1,PRT1A ;NEITHER, START OF FILE ADD T1,SYMCNT ANDI T1,7770 ;CUT TO TAB STOP MOVEM T1,SYMCNT CAIL T1,MAXSYM ;GOT TO END OF LINE? JRST [PUSHJ P,SCRLF SETZM SYMCNT JRST PRT1A] MOVEI T1,TAB ;END WITH A TAB PUSHJ P,SOUCH MOVEI T1,TAB MOVE T2,SYMTYP ;GET TYPE CAIN T2,20 ;NEED 2 TABS? PUSHJ P,SOUCH ;YES PRT1A: HRRZ T1,2(S) ;GET FLAGS,VALUE PUSHJ P,SYMNUM MOVEI T1,SPACE PUSHJ P,SOUCH MOVEI T1,5 ;COUNT 4 DIGITS AND A SPACE ADDM T1,SYMCNT DMOVE T2,(S) ;GET SMALLEST SYMBOL PUSHJ P,PUTSSX ;FOR SYMBOL FILE MOVEI T1,10 ;ACCOUNT FOR TAB MOVE T2,(S) ;CHECK FOR SHORT SYMBOLS TLNN T2,77 ;1 OR 2 CHAR SYMBOL? MOVEI T1,20 ;YES MOVE T2,1(S) ;CHECK FOR LONG SYMBOLS TRNE T2,77 ;12 CHAR SYMBOL? MOVEI T1,20 ;YES MOVEM T1,SYMTYP ;SAVE 'TYPE' 10 (NORMAL) OR 20 (SHORT OR LONG) IFN FTREL,< SETZ T1, MOVE T2,2(S) ;GET FLAGS TLNE T2,S.REL MOVEI T1,"'" ;FLAG RELOC TLNE T2,S.EXT!S.INT MOVEI T1,"*" SKIPE T1 PUSHJ P,LOUCH > ;END IFN FTREL PRT4: SKIPN CREFSW ;IF NOT CREF JRST PRT9A ;JUST FLAG SYMBOL AND LOOP MOVE T2,3(S) ;GET LINE,,LINK PRT3: MOVEI T4,^D13 ;MAX ENTRIES/LINE PRT2: PUSH P,T2 MOVEI T1,TAB PUSHJ P,LOUCH HLRZS T2 TRZ T2,(1B0) ;CLEAR FLAG MOVEI T1,SPACE CAIG T2,^D999 PUSHJ P,LOUCH CAIG T2,^D99 PUSHJ P,LOUCH CAIG T2,^D9 PUSHJ P,LOUCH MOVE T1,T2 PUSHJ P,PUTDEC POP P,T2 TLNN T2,(1B0) ;FLAG? JRST .+3 ;NO MOVEI T1,"#" PUSHJ P,LOUCH HRRZS T2 ;GET LINK JUMPE T2,PRT9 ;DONE WITH CHAIN MOVE T2,(T2) ;GET LINE,,LINK SOJG T4,PRT2 ;LOOP FOR LINE PUSHJ P,LCRLF ;END THE LINE MOVE T1,LINCTR CAMLE T1,PAGESZ ;IF ON NEW PAGE, PUSHJ P,DOHDFF ;DO HEADER MOVEI T1,TAB PUSHJ P,LOUCH PUSHJ P,LOUCH JRST PRT3 PRT9: PUSHJ P,LCRLF MOVE T1,LINCTR CAMLE T1,PAGESZ ;IF ON NEW PAGE, PUSHJ P,DOHDFF ;DO HEADER PRT9A: MOVE T3,2(S) ;GET FLAGS TLO T3,S.PRT ;FLAG SYMBOL PRINTED MOVEM T3,2(S) JRST PRTS PRTX: SKIPE SYMBSW ;IF SYMBOLS PUSHJ P,SCRLF ;DO CRLF SKIPN CREFSW ;IF NOT CREF POPJ P, ;EXIT IFN FTSTAT,< PUSHJ P,LCRLF ;NEW LINE MOVE T1,BC ;GET COUNT OF SYMBOLS USED PUSHJ P,PUTDEC MOVEI T2,[ASCIZ/ symbols used /] PUSHJ P,PUTSTR MOVE T1,P1 PUSHJ P,PUTDEC MOVEI T2,[ASCIZ/ empty slots in SYMTAB /] PUSHJ P,PUTSTR CAIG E,1 POPJ P, MOVE T1,E PUSHJ P,PUTDEC MOVEI T2,[ASCIZ/ links in longest symbol search/] PUSHJ P,PUTSTR > ;END IFN FTSTAT JRST LCRLF ;CRLF PRT10: SETZ T4, ;COUNT OF LINKS IN THIS BRANCH MOVE T3,2(S) ;GET FLAGS TLNE T3,S.PRT ;WAS ALREADY USED? JRST PRT11 ;YES CAMG T1,(S) ;GET SYMBOL THAT IS SMALLER JRST PRT11 ;(YES, WE ARE ONLY SORTING ON THE FIRST 6 CHARACTERS) MOVE T2,S ;SAVE INDEX OF LEAST ALPHABETICAL SYMBOL MOVE T1,(S) ;NEW MATCH SYMBOL PRT11: AOJ T4, SKIPE S,4(S) ;GET NEXT LINK JRST PRT10+1 ;GO ON CAMLE T4,E ;GT MAX? MOVE E,T4 ;NEW MAX POPJ P, ;NO LINK LSTNUM: TRNE F,FR.HEX ;HEX OUTPUT? JRST LSTHEX ;YES IDIVI T1,10 ;NO SOJLE T3,.+4 PUSH P,T2 PUSHJ P,LSTNUM POP P,T2 MOVEI T1,60(T2) LSTN1: PUSHJ P,LOUCH POPJ P, LSTHEX: IMULI T3,2 ;MULT BY 2/3 PUSH P,T4 IDIVI T3,3 POP P,T4 LSTH1: IDIVI T1,20 SOJLE T3,LSTH2 PUSH P,T2 PUSHJ P,LSTH1 POP P,T2 LSTH2: CAILE T2,11 JRST LSTH3 MOVEI T1,60(T2) JRST LSTN1 LSTH3: MOVEI T1,"A"-^D10(T2) JRST LSTN1 SYMNUM: MOVEI T3,4 SYMH1: IDIVI T1,20 SOJLE T3,SYMH2 PUSH P,T2 PUSHJ P,SYMH1 POP P,T2 SYMH2: CAILE T2,11 JRST SYMH3 MOVEI T1,60(T2) CAIA SYMH3: MOVEI T1,"A"-^D10(T2) SOUCH: SOSGE SBUF+2 JRST SOUCH1 IDPB T1,SBUF+1 POPJ P, SOUCH1: OUTPUT SYM, JRST SOUCH SCRLF: MOVEI T1,CR PUSHJ P,SOUCH MOVEI T1,LF JRST SOUCH ;LSTPC LIST THE PC AND A TAB LSTPC: MOVE T1,LTYPE ;GET LTYPE CAIE T1,4 ;XLIST? TRNE F,FR.PS1 ;PASS1? POPJ P, ;YES PUSHJ P,CHKLTP ;CHECK LTYPE POPJ P, ;EXTRA DC LINE AND LTYPE > 0 PUSHJ P,DOLINO ;IN CASE AT DC? TRZ F,FR.LIN ;LISTING PC CLEARS FR.LIN MOVEI T3,6 MOVE T1,PC PUSHJ P,LSTNUM TRNE F,FR.HEX ;HEX? JRST LSTPC1 ;YES MOVEI T1,"=" PUSHJ P,LOUCH MOVEI T3,3 ;3 FIGURES MOVE T1,PC ;GET PC LSH T1,-10 PUSHJ P,LSTNUM ;OUTPUT THE PC MOVEI T1,"/" PUSHJ P,LOUCH MOVE T1,PC ANDI T1,377 MOVEI T3,3 PUSHJ P,LSTNUM LSTPC1: IFN FTREL,< TRNE F,FR.ORG ;RELOCATING? JRST LSTPC2 ;NO MOVEI T1,"'" PUSHJ P,LOUCH > ;END IFN FTREL LSTPC2: MOVEI T1,TAB PUSHJ P,LOUCH ;OUTPUT ANOTHER TAB POPJ P, ;CHECK FOR LTYPE > 0 AND DC EXPANSION ;OR LTYPE = 3 AND MACRO EXPANSION ;NORMAL RETURN = DON'T PRINT ;SKIP RETURN = PRINT CHKLTP: SKIPE LTYPE ;LTYPE = 0 SKIPE LINBLK ;OR NOT IN EXPANSION? JRST CPOPJ2 ;YES, SKIP RETURN PUSH P,T1 PUSH P,T2 MOVE T2,MACPDL PUSH T2,INVECT CHKLT2: HRRZ T1,(T2) ;IS THIS A SOURCE LINE? CAIE T1,-2 ;.. CAIN T1,-1 ;.. JRST T2POPJ ;YES, LTYPE > 0 AND IN DC EXPANSION; DON'T PRINT CAIG T1,BAKPTR CAIGE T1,BAKBUF ;CAME FROM BAKBUF? CAIA ;NO CAME FROM MACRO SOJA T2,CHKLT2 MOVE T1,LTYPE ;GET LTYPE CAIE T1,1 ;XALL AND DC EXPANSION IN MACRO? CAIN T1,3 ;XMAC AND IN MACRO EXPANSION? JRST T2POPJ ;YES, DON'T PRINT CHKLTX: POP P,T2 POP P,T1 JRST CPOPJ2 ;NOT XMAC ;CHECK JUST FOR MACRO CHKMAC: PUSH P,T1 PUSH P,T2 MOVE T2,MACPDL PUSH T2,INVECT CHKMC2: HRRZ T1,(T2) ;IS THIS A SOURCE LINE? CAIN T1,-1 ;.. JRST CHKLTX CAIG T1,BAKPTR CAIGE T1,BAKBUF ;CAME FROM BAKBUF? CAIA ;NO CAME FROM MACRO SOJA T2,CHKMC2 MOVE T1,LTYPE ;GET LTYPE CAIN T1,3 ;XMAC AND IN MACRO EXPANSION? JRST T2POPJ ;YES, DON'T PRINT JRST CHKLTX TLCRLF: TRNN F,FR.BOL ;DON'T MAKE BLANK LINES PUSHJ P,CHKLTP ;SHALL WE PRINT? POPJ P, ;NO LCRLF: MOVEI T1,CR PUSHJ P,LOUCH MOVEI T1,LF JRST LOUCH ;LSTOP ENTER THE BYTE IN T1 IN THE OBJ FILE ; PRINT THE BYTE [AND A SPACE IF OCT] LSTOP: TRNE F,FR.PS1 JRST LSTOP1 TRO F,FR.LOP PUSH P,T3 MOVEI T3,3 PUSH P,T2 ANDI T1,377 PUSHJ P,HEXOUT PUSHJ P,CHKLTP ;CHECK LTYPE JRST LSTOP0 ;EXTRA DC LINE AND LTYPE > 0 PUSHJ P,LSTNUM ;OUTPUT BYTE MOVEI T1,SPACE TRNN F,FR.HEX PUSHJ P,LOUCH LSTOP0: POP P,T2 POP P,T3 LSTOP1: AOS PC TRNE F,FR.PS1 AOJ BC, POPJ P, DOTAG: JUMPE TOK,DUNTAG ;SKIP IF FOO:: TRO F,FR.NRF ;DEFINITION IS NOT REFERENCE PUSHJ P,EVAL PUSHJ P,SYMDEF ;FLAG DEFINITION HRRZS T1 ;CLEAR FLAGS CAME T1,PC ERROR F.MULT JRST DUNTAG SYMDEF: TRNE F,FR.PS1 ;PASS1? POPJ P, ;YES TRNN F,FR.LST ;LISTING? POPJ P, ;NO CAIGE S,SYMTAB ;POINTS TO SYMTAB? POPJ P, ;NO. PROB POINTS TO PRETAB PUSH P,T1 PUSH P,T2 MOVE T1,3(S) ;GET LINE,,LINK MOVEI T2,3(S) ;GET 1ST POINTER DEFS0: TRNN T1,-1 ;END OF CHAIN? JRST DEFS1 ;YES MOVE T2,T1 MOVE T1,(T2) ;LINK JRST DEFS0 ;LOOP DEFS1: TLO T1,(1B0) ;FLAG DEFINITION MOVEM T1,(T2) ;PUT BACK POP P,T2 POP P,T1 POPJ P, DOHDFF: SKIPN PAGESZ ;IF PAGE = 0 POPJ P, ;DON'T DO ANY HEADERS DOHDFX: MOVEI T1,FF PUSHJ P,LOUCH ;FORCE NEW PAGE DOHEAD: PUSH P,T1 ;SAVE ACS PUSH P,T2 PUSH P,T3 MOVEI T1,1 MOVEM T1,LINCTR ;SET LINE COUNT TO 1 MOVE T2,[POINT 7,TITL] MOVEI T3,^D66 ILDB T1,T2 JUMPE T1,.+3 PUSHJ P,LOUCH SOJG T3,.-3 MOVEI T1,11 ;LOAD A SKIPE TITL ;NOT IF NO TITLE PUSHJ P,LOUCH ;OUTPUT IT MOVEI T2,HEAD0 PUSHJ P,PUTSTR MOVEI T2,M80VER PUSHJ P,PUTOCT MOVEI T1,M80MIN JUMPE T1,.+3 MOVEI T1,"@"(T1) PUSHJ P,LOUCH MOVEI T1,"(" PUSHJ P,LOUCH MOVEI T2,M80EDT PUSHJ P,PUTOCT MOVEI T2,[ASCIZ/) /] PUSHJ P,PUTSTR SKIPL PAGENO MOVEI T2,HEAD1 SKIPG PAGENO MOVEI T2,HEAD3 PUSHJ P,PUTSTR MOVEI T2,DATE ;SO WHAT IF WE STARTED AT 11:59 DEC 31 PUSHJ P,PUTSTR ;WE STILL USE THE DATE OF THE START OF THE RUN MOVEI T2,HEAD2 PUSHJ P,PUTSTR SKIPL T1,PAGENO PUSHJ P,PUTDEC SKIPL PAGENO JRST .+3 MOVEI T1,"S" ;INDICATE SYMBOL TABLE PAGE PUSHJ P,LOUCH SKIPN SUBPAG JRST NOSUB MOVEI T1,"-" PUSHJ P,LOUCH MOVE T1,SUBPAG PUSHJ P,PUTDEC NOSUB: AOS SUBPAG ;BUMP SUBPAGE COUNTER HERE PUSHJ P,LCRLF MOVE T2,[POINT 6,FILNAM] ;LOAD THE SOURCE FILE NAME DOH1: ILDB T1,T2 JUMPE T1,.+5 ADDI T1,40 PUSHJ P,LOUCH TLNE T2,770K JRST DOH1 MOVEI T1,"." ;LOAD A "." PUSHJ P,LOUCH ;AND OUTPUT IT HLLZ T2,FILEXT ;LOAD THE SOURCE FILE EXT. SETZ T3, PUSHJ P,PUTSIX ;PRINT IT MOVE T2,[POINT 7,SUBTTL] MOVEI T3,^D66 ILDB T1,T2 JUMPE T1,.+3 PUSHJ P,LOUCH SOJG T3,.-3 PUSHJ P,LCRLF PUSHJ P,LCRLF POP P,T3 POP P,T2 POP P,T1 POPJ P, PUTSTR: HRLI T2,(POINT 7,0) ;MAKE A BTP ILDB T1,T2 ;LOAD THE BYTE JUMPE T1,CPOPJ ;IF LAST BYTE, RETURN PUSHJ P,LOUCH ;OUTPUT IT JRST .-3 ;AND LOOP PUTOCT: MOVE T3,[POINT 3,T2] ;LOAD THE BTP ILDB T1,T3 ;LOAD THE BYTE JUMPE T1,.-1 ;IGNORE LEADING ZEROS CAIA ILDB T1,T3 ADDI T1,60 ;MAKE IT ASCII PUSHJ P,LOUCH ;OUTPUT IT TLNE T3,770K ;LAST BYTE? JRST .-4 ;NO, THEN LOOP POPJ P, ;YES, RETURN PUTDEC: IDIVI T1,^D10 ;DIVIDE BY RADIX JUMPE T1,.+4 ;IF NULL, DO RETURN LOOP PUSH P,T2 ;SAVE T2 PUSHJ P,PUTDEC ;RECURSIVE CALL POP P,T2 ;RESTORE T2 MOVEI T1,60(T2) ;MAKE ASCII JRST LOUCH ;OUTPUT AND LOOP RETURN CRLF: ASCIZ/ / HEAD0: ASCIZ \MAC80 \ HEAD1: ASCIZ \8085/Z80 Cross Assembler \ HEAD2: ASCIZ \ Page \ HEAD3: ASCIZ \Symbol Table \ GTDATE: MOVE T3,[POINT 7,DATE] PUSH P,I ;SAVE I MOVE T1,[60,,11] ;LOAD THE DAY GETTAB T1, ;NOW JRST IPOPJ ;PA1050 DIES ON THIS GETTAB PUSHJ P,GETDEC ;MAKE DECIMAL ASCII MOVEI T1,"-" IDPB T1,T3 ;DEPOSIT A HYPHEN MOVE I,[57,,11] ;LOAD THE MONTH GETTAB I, JFCL MOVE T2,[POINT 7,MONTAB-1(I)] ;SET BTP ILDB T1,T2 ;LOAD THE BYTE JUMPE T1,.+3 IDPB T1,T3 ;DEPOSIT THE BYTE JRST .-3 ;AND LOOP MOVEI T1,"-" IDPB T1,T3 ;DEPOSIT ANOTHER BYTE MOVE T1,[56,,11] ;LOAD THE YEAR GETTAB T1, JFCL SUBI T1,^D1900 ;LAST TWO ONLY PUSHJ P,GETDEC ;DEPOSIT IT MOVEI T1,SPACE ;LOAD AND OUTPUT A SPACE IDPB T1,T3 IDPB T1,T3 ;2 SPACES MOVE T1,[61,,11] ;LOAD THE HOUR GETTAB T1, JFCL PUSHJ P,GETDEC ;AND DEPOSIT IT MOVEI T1,":" ;LOAD AND OUTPUT A COLON IDPB T1,T3 MOVE T1,[62,,11] ;LOAD MINUTES GETTAB T1, JFCL CAIL T1,^D10 ;TWO DIGITS? JRST .+5 ;YES, THEN DO IT PUSH P,T1 ;SAVE T1 MOVEI T1,"0" ;LOAD AND OUTPUT A ZERO IDPB T1,T3 POP P,T1 ;RESTORE T1 PUSHJ P,GETDEC ;AND OUTPUT IT IPOPJ: POP P,I ;RESTORE I POPJ P, ;RETURN GETDEC: IDIVI T1,^D10 ;DIVIDE BY RADIX JUMPE T1,.+4 ;IF DONE, JUMP OUT OF LOOP PUSH P,T2 ;SAVE T2 PUSHJ P,GETDEC ;AND LOOP POP P,T2 ;RESTORE T2 MOVEI T1,60(T2) ;MAKE ASCII IDPB T1,T3 ;DEPOSIT IT POPJ P, ;LOOP RETURN PUTSIX: MOVE T4,[POINT 6,T2] ILDB T1,T4 ADDI T1,40 PUSHJ P,LOUCH CAME T4,[600,,T3] JRST .-4 POPJ P, PUTSSX: MOVE T4,[POINT 6,T2] ILDB T1,T4 JUMPE T1,CPOPJ ADDI T1,40 PUSHJ P,SOUCH AOS SYMCNT CAME T4,[600,,T3] JRST PUTSSX+1 POPJ P, DOLINO: TROE F,FR.LIN ;ALREADY PRINTED? POPJ P, ;YES, DONE PUSH P,T1 MOVE T1,LTYPE CAIN T1,4 ;XLIST? JRST TPOPJ ;YES PUSH P,T2 TRNN F,FR.BOL ;AT START OF LINE? PUSHJ P,LCRLF ;WE ARE NOW MOVE T1,LINCTR ;GET LINE COUNT CAMLE T1,PAGESZ ;TEST IN CASE IN DC? CODE PUSHJ P,DOHDFF ;IF EXPANSION OF DB OVERFLOWS PAGE AOS T1,LINENO ;GET LINE # MOVEI T2,SPACE EXCH T1,T2 CAIG T2,^D999 PUSHJ P,LOUCH CAIG T2,^D99 PUSHJ P,LOUCH CAIG T2,^D9 PUSHJ P,LOUCH EXCH T1,T2 PUSHJ P,PUTDEC ;PRINT IT MOVE T2,MACPDL PUSH T2,INVECT DOLIN2: HRRZ T1,(T2) ;IS THIS A SOURCE LINE? CAIN T1,-1 ;.. JRST DOLIN1 ;YES, SKIP CAIN T1,-2 ;FROM INCLUDE FILE? JRST [MOVEI T1,"I" PUSHJ P,LOUCH JRST DOLIN1] CAIG T1,BAKPTR CAIGE T1,BAKBUF ;CAME FROM BAKBUF? JRST [MOVEI T1,"M" ;NO, FLAG AS A MACRO EXPANSION LINE MOVE T2,LTYPE;UNLESS WE ARE CAIE T2,3 ;SUPPRESSING MACRO CODE EXPANSION PUSHJ P,LOUCH JRST DOLIN1] SOJA T2,DOLIN2 DOLIN1: MOVEI T1,TAB PUSHJ P,LOUCH ;& A TAB TRZ F,FR.BOL ;WE ARE NOT AT THE START OF A LINE NOW POP P,T2 POP P,T1 POPJ P, MONTAB: ASCIZ /Jan/ ASCIZ /Feb/ ASCIZ /Mar/ ASCIZ /Apr/ ASCIZ /May/ ASCIZ /Jun/ ASCIZ /Jul/ ASCIZ /Aug/ ASCIZ /Sep/ ASCIZ /Oct/ ASCIZ /Nov/ ASCIZ /Dec/ ;ADD NEW MONTHS HERE PASS1: TRZE F,FR.END ;DONE? JRST ENDIT ;YES PUSHJ P,TOKEN PUSHJ P,IFPOP ;IF OR FRIENDS? JRST NOP1T ;YES TRNE F,FR.OFF JRST FPASS1 NOP1T: JUMPN TOK,.+4 CAIE I,CR CAIN I,SEMICO ;END OF LINE? JRST FPASS1 ;YES, DONE CAIN I,COLON ;BEFORE A COLON? JRST LOASYM ;YES, ITS A LABEL TLNE F,FL.Z80 JRST Z80P1 PUSHJ P,SRCH80 ;GET INDEX TO OPCODE JRST [PUSHJ P,SETMAC;SETUP MACRO JRST PASS1] JRST FPASS1 ;BAD OP MOVE P1,TYPLSH(X) ;GET TYPE,,SHIFT TRNE P1,777770 ;A LARGE SHIFT? JRST [PUSHJ P,@TYPLSH(X) ;YES, ITS A PSEUDO OP JRST PASS1] AOS PC ;ONE BYTE AOJ BC, TLNN P1,T.2BYT!T.3BYT JRST .+3 AOS PC ;TWO BYTES AOJ BC, TLNN P1,T.3BYTE JRST .+3 AOS PC ;THREE BYTES AOJ BC, JRST FPASS1 Z80P1: MOVEM TOK,OPCODE ;SAVE OPCODE PUSHJ P,SRCOP2 ;FIRST CHECK OPCODE JRST [PUSHJ P,SETMAC JRST FPASS1] JRST FPASS1 ;BAD OP SKIPN SIZTAB(X) ;IF ZERO SIZE, JRST [PUSHJ P,@ADRTAB(X) ;DO PSEUDO OP JRST FPASS1] PUSHJ P,DECODE ;GET ADDRESS MODE MOVE TOK,OPCODE ;GET OP HRLZ OP,TYPE1 ;GET TYPE 1 HRR OP,TYPE2 ;TYPE 2 PUSHJ P,SRCOP1 ;LOOK FOR OP/AM JFCL ;NOT USED JRST FPASS1 ;ERROR MOVE T1,PC ADD T1,SIZTAB(X) ;INC PC MOVEM T1,PC ADD BC,SIZTAB(X) ;INC BC FPASS1: PUSHJ P,FLUSH JRST PASS1 LOASYM: SKIPN TOK JRST PASS1 ;SKIP IF FOO:: PUSHJ P,SRCSYM DMOVEM TOK,(S) HRR T1,PC ;FLAGS,PC IFN FTREL,< TRNN F,FR.ORG ;IF RELOCATING, TLO T1,S.REL ;FLAG AS RELOCATABLE > TLZ T1,S.UNDF ;CLEAR UNDEFINED FLAG CAIL S,SYMTAB ;SKIP IF ILLEGAL MOVEM T1,2(S) JRST PASS1 UUO: LDB E,[POINT 9,.JBUUO##,8] JRST @UUOTAB-1(E) UUOTAB: EUUO WUUO WUUO: MOVSI E,"%" JRST EUUO+1 EUUO: MOVSI E,"?" HRR E,.JBUUO POPJ P, DEFINE X(A,B,C,D),< SIXBIT /A/ > OPNTAB: XLIST OP8080 LIST OPTABL==.-OPNTAB DEFINE X(A,B,C,D),< EXP B > OP8TAB: XLIST OP8080 LIST DEFINE X(A,B,C,D),< XWD C,D > TYPLSH: XLIST OP8080 T.ILOP,,0 ;SO THAT UNDEF OPCODES DON'T BUMP PC LIST DEFINE X(A,B1,B2,C,D,E),< > OPZTAB: XLIST OPZ80 LIST OPZTBL==.-OPZTAB DEFINE X(A,B1,B2,C,D,E),< XWD B1,B2> OPMTAB: XLIST OPZ80 LIST DEFINE BUILD(A,B),< +B> DEFINE X(A,B1,B2,C,D,E),< ZZ==0 IRP C,< ZZ==ZZ+1> BUILD (,ZZ)> CODTAB: XLIST OPZ80 LIST DEFINE X(A,B1,B2,C,D,E),< IFG D-4, PRINTX SIZE TOO BIG A B1 B2 C D E EXP D> SIZTAB: XLIST OPZ80 LIST DEFINE X(A,B1,B2,C,D,E),< IFB ,< EXP 0> IFNB,< EXP E>> ADRTAB: XLIST OPZ80 LIST DEFINE W(A,B),< [ASCIZ \B\]> ERRTAB: XLIST EFLAGS LIT LIST RELOC 0 PRETAB: SIXBIT /A/ EXP 7 SIXBIT /B/ EXP 0 SIXBIT /C/ EXP 1 SIXBIT /D/ EXP 2 SIXBIT /E/ EXP 3 SIXBIT /H/ EXP 4 SIXBIT /L/ EXP 5 SIXBIT /M/ EXP 6 SIXBIT /SP/ EXP 6 SIXBIT /PSW/ EXP 6 PRELEN==.-PRETAB SYMTAB::BLOCK 5*SYMSIZ SYMEND==. LINBLK: BLOCK ^D40 ;HOLDS MAX OF 200 CHARACTER LINE LINEND==.-1 STRING: BLOCK ^D200 ;ROOM FOR 1000(800) BYTES MACDUM: BLOCK ^D40 ;HOLDS 20 DUMMY MACRO ARGS MACDML==.-MACDUM MACDND==.-1 MACARG: BLOCK ^D100 ;500 CHARACTERS OF MACRO ARGS MACAND==.-1 LASTMC: 0 ARGPTR: 0 ;POINTER TO MACARG ARGSTK: BLOCK 20 ;POINTER TO ARGS OF NESTED MACROS ARGPDL: 0 ;POINTER TO ARGSTK REPCNT: 0 ;COUNT OF CURRENT REPT REPADR: 0 ;ADDRESS OF REPT STRING EOMFLG: 0 ;FLAG TO TELL THE DIFF BETWEED MACRO AND REPT PC: 0 BYTCNT: 0 XTRAPC: 0 ORGXR: 0 ;INDEX INTO ORGBLK ORGBLK: BLOCK 100 ;BYTE COUNT OF BLOCK ;START ADDRESS OF BLOCK MACSTK: BLOCK 20 ;INVECT GETS PUSHED ON THIS WHEN A MACRO IS CALLED MACPDL: 0 ;POINTER TO MACSTK MACLEV: 0 ;LEVEL OF NESTING IN MACRO LOCSYM: 0 ;VALUE OF LOCAL SYMBOL OPSTK: BLOCK 20 ;PDL FOR POLISH STACK (ENOUGH?) INVECT: 0 ;POINTS TO THE MACRO FROM WHICH INCH WILL GET ITS SOURCE BAKBUF: BLOCK ^D100 ;HOLDS NEXT 100 WORDS IN BUFFER WHILE DOING SNEAK BAKPTR: 0 ;POINTER TO BAKBUF SNEAKI: 0 ;CONTENTS OF REG I WHEN DONE SNEAKING TOKEN SAVREG: BLOCK 5 ;MISC. STORAGE WHEN STACK IS BUSY IFLEVL: 0 ;LEVEL OF CURRENT NESTED IF EXPLVL: 0 ;LEVEL OF CURRENT PAREN IN EXPRESSION OFFLVL: 0 ;IFLEVL THAT ASSEMBLY WAS TURNED OFF BRAKLV: 0 ;ANGLE BRACKET NESTING LEVEL CHECK: 0 ;CHECKSUM STARTA: 0 ;START ADDRESS TITL: BLOCK 20 ;TITLE BUFFER SUBTTL: BLOCK 40 SUBTLN==<.-SUBTTL>*5 IFN FTREL,< RELPTR: 0 RELTAB: BLOCK ^D50 ;50 RELOC ADDRESSES (DUMPED WHEN GT 15) RELEND==.-1 > LIBNAM: BLOCK 2 ;LIBNAME PLUS OVERFLOW LIBEXT: 0 LINENO: 0 LINCTR: 0 LTYPE: 0 ;LISTING TYPE DELIM: 0 ;USED TO TELL " FROM ' IN DC & SETMAC CODE PAGENO: 0 SUBPAG: 0 SYMCNT: 0 ;NUMBER OF CHARACTERS PER LINE IN SYMBOL FILE SYMTYP: 0 ;'TYPE' OF LAST SYMBOL IN SYMBOL FILE PAGESZ: 0 ;SIZE OF PAGE - SET BY 'PAGE' OPCODE: 0 TYPE1: 0 TYPE2: 0 ARG1: 0 ARG2: 0 DATE: 0 0 0 ENDHGH::0 END