;;; ************************************************************** ;;; ***** MACLISP ****** FASLOAD ******************************** ;;; ************************************************************** ;;; ** (C) COPYRIGHT 1981 MASSACHUSETTS INSTITUTE OF TECHNOLOGY ** ;;; ****** THIS IS A READ-ONLY FILE! (ALL WRITES RESERVED) ******* ;;; ************************************************************** PGBOT FSL SUBTTL HAIRY RELOCATING LOADER (FASLOAD) ;;; BUFFER PARAMETERS LLDAT==:770 ;LENGTH OF LOADER'S ATOMTABLE ARRAY ILDAT==:1000 ;AMOUNT TO INCREMENT ATOMTABLE ARRAY LLDSTB==:400 ;SIZE OF LDPUT'S SYMBOL TABLE ARRAY (IN 2-WD ENTRIES) ;;; PDL OFFSETS LDAGEN==:0 ;SAR FOR ATOMTABLE LDPRLS==:-1 ;PURE CLOBBERING LIST LDDDTP==:-2 ;DDT FLAG LDBGEN==:-3 ;SAR FOR I/O BUFFER LDNPDS==:4 ;NUMBER OF REGPDL SLOTS TAKE UP BY FASLOAD TEMPORARIES ;;; FASLOAD USES AN ARRAY OF ATOMS TO AVOID CONSTANTLY CREATING ;;; THE SAME ATOMS OVER AND OVER; IN PARTICULAR, THIS SAVES MUCH ;;; TIME IN INTERN FOR ATOMIC SYMBOLS. THIS TABLE IS CREATED ;;; INCREMENTALLY DURING THE LOAD FROM DATA IN THE FASL FILE. THE ;;; ARRAY HAS ONE ONE-WORD ENTRY FOR EACH ATOM. ENTRY 0 IS FOR NIL; ;;; THE OTHERS MAY BE IN ANY ORDER. THE FORMAT OF EACH ATOMTABLE ;;; ENTRY IS AS FOLLOWS: ;;; 4.9-4.1 IF NON-ZERO, THE THE LEFT HALF OF THE ENTRY ;;; (4.9-3.1) CONTAINS THE ADDRESS OF THE VALUE ;;; CELL OF THE ATOM (SYMBOLS ONLY). THIS WORKS ;;; BECAUSE ALL VALUE CELLS ARE ABOVE ADDRESS 777. ;;; NOTE THAT OTHER LEFT HALF BITS DESCRIBED HERE ;;; HAVE MEANING ONLY IF BITS 4.9-4.1 ARE ZERO. ;;; 3.4 THIS BIT IS TURNED ON IF THE ATOM IS PROTECTED ;;; FROM THE GARBAGE COLLECTOR BECAUSE IT IS POINTED ;;; BY SOME LIST STRUCTURE WHICH IS PROTECTED. THIS ;;; IS A HACK SO THAT USELESS ENTRIES WON'T BE MADE ;;; IN THE GC PROTECTION ARRAY (SEE GCPRO). ;;; 3.3-3.2 INDICATES THE TYPE OF ATOM: 0 => SYMBOL, ;;; 1 => FIXNUM, 2 => FLONUM, 3 => BIGNUM. ;;; 3.1 THIS BIT IS TURNED ON IF THE ATOM IS EVER ;;; REFERENCED, DIRECTLY OR INDIRECTLY, BY COMPILED ;;; CODE (IT MIGHT NOT BE IF USED ONLY IN MUNGABLES). ;;; IT INDICATES THAT THE ATOM MUST SOMEHOW BE ;;; PROTECTED FROM THE FEROCIOUS GARBAGE COLLECTOR. ;;; 2.9-1.1 CONTAINS THE ADDRESS OF THE ATOM. (SURPRISE!) ;;; NOTE THAT ONCE AN ATOM IS IN THE TABLE, THE FASL FILE WILL ;;; REFER TO THE ATOM BY ITS TABLE INDEX, SO THAT IT CAN BE ;;; RETRIEVED EXTREMELY QUICKLY. ;;; FORMAT OF FASL FILES: ;;; ;;; THE "NEW" FASLOAD SCHEME (AS OF 1/31/73) USES A NEW FORMAT FOR ;;; ITS FILES. A FASL FILE CONSISTS OF TWO HEADER WORDS, FOLLOWED BY ;;; A SERIES OF FASL BLOCKS; THE TWO HEADER WORDS ARE BOTH SIXBIT, ;;; THE FIRST BEING "*FASL+" (FOR HISTORICAL REASONS, "*FASL* IS ;;; ALSO ACCEPTED) AND THE SECOND THE CONTENTS OF LOCATION LDFNM2 IN ;;; THE LISP WHICH ASSEMBLED THE FILE (A VERSION NUMBER IN SIXBIT). ;;; EACH FASL BLOCK CONSISTS OF A WORD OF NINE FOUR-BIT RELOCATION ;;; BYTES, FOLLOWED BY NINE PIECES OF FASL DATA. THE LENGTH OF EACH ;;; DATA ITEM IS DEPENDENT ON THE RELOCATION TYPE; THUS FASLBLOCKS ;;; ARE OF VARYING LENGTH. THE LAST BLOCK MAY HAVE FEWER THAN NINE ;;; DATA ITEMS. THE RELOCATION TYPES AND THE FORMATS OF THE ;;; ASSOCIATED DATA ITEMS ARE AS FOLLOWS: ;;; ;;; TYPE 0 ABSOLUTE ;;; ONE ABSOLUTE WORD TO BE LOADED. ;;; ;;; TYPE 1 RELOCATABLE ;;; ONE WORD, THE RIGHT HALF OF WHICH IS RELOCATABLE; I.E. AT LOAD ;;; TIME THE LOAD OFFSET IS TO BE ADDED TO THE RIGHT HALF. ;;; ;;; TYPE 2 SPECIAL ;;; A WORD TO BE LOADED, WHOSE RIGHT HALF CONTAINS THE INDEX OF AN ;;; ATOM (HOPEFULLY OF TYPE PNAME) THE ADDRESS OF THE VALUE CELL OF ;;; WHICH IS TO REPLACE THE RIGHT HALF OF THE LOADED WORD. (IF NO ;;; VALUE CELL EXISTS, ONE IS TO BE CREATED.) ;;; ;;; TYPE 3 SMASHABLE CALL ;;; SIMILAR TO TYPE 4 (Q.V.) EXCEPT THAT THE INSTRUCTION IS ONE OF ;;; THE SERIES OF CALL UUOS WHICH MAY BE "SMASHED" FOR PURIFICATION ;;; PURPOSES. AT PRESENT THESE UUOS ARE: CALL, JCALL, NCALL, NJCALL. ;;; ;;; TYPE 4 QUOTED ATOM ;;; ONE WORD TO BE LOADED WHOSE RIGHT HALF CONTAINS THE INDEX OF AN ;;; ATOM WHOSE ADDRESS IS TO REPLACE THE RIGHT HALF OF THE WORD ;;; LOADED. ;;; ;;; TYPE 5 QUOTED LIST ;;; A SERIES OF WORDS REPRESENTING AN S-EXPRESSION TO BE CONSTRUCTED ;;; BY THE LOADER. THE FORMAT OF THESE WORDS IS BEST EXPLAINED BY ;;; THE ALGORITHM USED TO CONTRUCT THE S-EXPRESSION: THE LOADER ;;; EXAMINES BITS 4.7-4.9 OF SUCCESSIVELY READ WORDS, AND DISPATCHES ;;; ON THEM: ;;; 0 THE ATOM WHOSE INDEX IS IN THE RIGHT HALF OF THE WORD ;;; IS PUSHED ONTO A STACK. ;;; 1 THE LOADER POPS AS MANY ITEMS OFF THE STACK AS ;;; SPECIFIED BY THE NUMBER IN THE RIGHT HALF OF THE WORD ;;; AND MAKES A LIST OF THEM, SO THAT THE LAST ITEM POPPED ;;; BECOMES THE FIRST ITEM OF THE LIST; THIS LIST IS THEN ;;; PUSHED ONTO THE STACK. ;;; 2 THE LOADER POPS ONE ITEM OFF THE STACK AND PROCEEDS AS ;;; FOR 1, EXCEPT THAT THE ITEM FIRST POPPED IS USED TO ;;; END THE LIST INSTEAD IF NIL. (THIS ALLOWS FOR DOTTED ;;; PAIRS.) ;;; 3 THE TOP ITEM ON THE STACK IS EVALUATED AND STORED BACK ;;; ON THE TOP OF THE STACK. ;;; 4 THE RIGHT HALF OR THE WORD SPECIFIES THE LENGTH OF A ;;; HUNK TO BE MADE BY TAKING THAT MANY ITEMS FROM THE TOP ;;; OF THE STACK; THIS HUNK IS THEN PUSHED BACK. ;;; 5 UNUSED. ;;; 6 UNUSED. ;;; 7 THE LEFT HALF OF THE WORD SHOULD BE -1 OR -2, ;;; INDICATING THE SECOND LAST WORD OF THE DATA; IF -1, ;;; THE RIGHT HALF OF THIS WORD AND THE ADDRESS OF (WHAT ;;; SHOULD BE) THE SINGLE ITEM ON THE STACK (WHICH IS ;;; POPPED OFF) ARE MADE RESPECTIVELY INTO THE LEFT AND ;;; RIGHT HALVES OF A WORD TO BE LOADED INTO BINARY ;;; PROGRAM SPACE; IF -2, THE S-EXPRESSION IS PLACED INTO ;;; THE NEXT SLOT OF THE ATOMTABLE (SEE TYPE 12). THE ONE ;;; WORD REMAINING IS THE HASH KEY OF THE S-EXPRESSION AS ;;; COMPUTED BY SXHASH; THIS IS USED BY THE LOADER TO SAVE ;;; GCPRO SOME WORK. ;;; ;;; TYPE 6 GLOBALSYM ;;; ONE WORD; THE RIGHT HALF IS AN INDEX INTO THE TABLE LSYMS IN ;;; LISP. THE INDICATED VALUE IS RETRIEVED, NEGATED IF BIT 4.9 OF ;;; THE DATA WORD IS 1, AND ADDED TO THE RIGHT HALF OF THE LAST ;;; WORD LOADED INTO BINARY PROGRAM SPACE. THIS ALLOWS LAP CODE ;;; TO REFER TO SELECTED LOCATIONS INTERNAL TO LISP WITHOUT ;;; GETTING SYMBOLS FROM DDT. ;;; ;;; TYPE 7 GETDDTSYM ;;; IF THE FIRST WORD IS -1, THEN THE LOAD OFFSET IF ADDED INTO ;;; THE LEFT HALF OF THE WORD MOST RECENTLY LOADED INTO BINARY ;;; PROGRAM SPACE (THIS IS HOW LEFT HALF RELOCATION IS ;;; ACCOMPLISHED). OTHERWISE, THE FIRST WORD CONTAINS IN BITS ;;; 1.1-4.5 A SYMBOL IN SQUOZE CODE. THE LOADER GETS THE VALUE OF ;;; THIS SYMBOL FROM DDT IF POSSIBLE, NEGATES IT IF BIT 4.9 IS 1, ;;; THEN ADDS THE RESULT TO THE FIELD OF THE LAST WORD LOADED AS ;;; SPECIFIED BY BITS 4.6-4.7: ;;; 3 = ENTIRE WORD ;;; 2 = AC FIELD ONLY ;;; 1 = RIGHT HALF ONLY ;;; 0 = ENTIRE WORD, BUT SWAP HALVES OF VALUE BEFORE ADDING. ;;; THESE FOUR FIELDS CORRESPOND TO OPCODE, AC, ADDRESS, AND INDEX ;;; FIELDS RESPECTIVELY IN A LAP INSTRUCTION. IF BIT 4.8 IS A 1, ;;; THEN ANOTHER WORD FOLLOWS, CONTAINING THE VALUE OF THE SYMBOL ;;; AS OBTAINED FROM DDT AT ASSEMBLE TIME. IF THE VERSION NUMBER ;;; OF THAT LISP (AS DETERMINED FROM THE SECOND FILE HEADER WORD) ;;; IS THE SAME AS THAT OF THE LISP BEING LOADED INTO, THEN THIS ;;; VALUE IS USED AND DDT IS NOT CONSULTED AT LOAD TIME; THIS IS ;;; FOR SPEED. IF THE VERSION NUMBERS ARE DIFFERENT, THEN DDT IS ;;; CONSULTED. ;;; ;;; TYPE 10 ARRAY REFERENCE ;;; ONE WORD TO BE LOADED, WHOSE RIGHT HALF CONTAINS THE ATOMINDEX ;;; OF AN ATOMIC SYMBOL. IF THE SYMBOL HAS AN ARRAY PROPERTY, IT ;;; IS FETCHED; OTHERWISE ONE IS CREATED. THE RIGHT HALF OF THE ;;; WORD TO BE LOADED IS REPLACED WITH THE ADDRESS OF THE SECOND ;;; WORD OF THE ARRAY POINTER (I.E. OF THE TTSAR). IN THIS WAY ;;; ACCESSES TO ARRAYS CAN BE OPEN-CODED. ;;; ;;; TYPE 11 UNUSED ;;; ;;; TYPE 12 ATOMTABLE INFO ;;; A HEADER WORD, POSSIBLY FOLLOWED BY OTHERS, DEPENDING ON BITS ;;; 4.7-4.9: ;;; 0 THE RIGHT HALF IS THE NUMBER OF WORDS FOLLOWING, WHICH ;;; CONSTITUTE THE PNAME OF A PNAME-TYPE ATOM, IN THE ;;; ORDER OF THEIR APPEARANCE ON A PROPERTY LIST. THE ATOM ;;; IS INTERNED. ;;; 1 THE ONE WORD FOLLOWING IS THE VALUE OF A FIXNUM TO BE ;;; CREATED. ;;; 2 THE FOLLOWING WORD IS THE VALUE OF A FLONUM. ;;; 3 THE RIGHT HALF IS THE NUMBER OF FIXNUM COMPONENTS OF A ;;; BIGNUM FOLLOWING, MOST SIGNIFICANT WORD FIRST. BIT 3.1 ;;; IS THE SIGN OF THE BIGNUM. ;;; 4 THE FOLLOWING TWO WORDS ARE A DOUBLE-PRECISION NUMBER. ;;; 5 THE FOLLOWING TWO WORDS ARE A COMPLEX NUMBER. ;;; 6 THE FOLLOWING FOUR WORDS ARE A DUPLEX NUMBER. ;;; 7 UNUSED. ;;; THE ATOM THUS CREATED IS ASSIGNED A PLACE IN THE ATOMTABLE ;;; MAINTAINED BY THE LOADER (AS AN ARRAY) USING CONSECUTIVE ;;; LOCATIONS; FROM THAT POINT ON OTHER DATA ITEMS REFERRING TO ;;; THAT ITEM CAN DO SO BY THE INDEX OF THE ATOM IN THIS TABLE. ;;; SEE ALSO TYPES 5 AND 16, WHICH ALSO MAKE ENTRIES IN THE ;;; ATOMTABLE. ;;; ;;; TYPE 13 ENTRY INFO ;;; TWO WORDS. THE LEFT HALF OF THE FIRST WORD IS THE ATOMINDEX ;;; OF THE NAME OF THE FUNCTION BEING DEFINED; THE RIGHT HALF ;;; THAT OF THE SUBR TYPE (THE PROPERTY UNDER WHICH TO CREATE THE ;;; ENTRY POINT, E.G. SUBR OR FSUBR). THE RIGHT HALF OF THE ;;; SECOND WORD IS THE LOCATION OF THE ENTRY POINT AS A ;;; RELOCATABLE POINTER: THE LOAD OFFSET MUST BE ADDED TO IT. THE ;;; LEFT HALF OF THE SECOND WORD CONTAINS THE ARGS PROPERTY, IN ;;; INTERNAL ARGS PROPERTY FORMAT, AS SPECIFIED IN THE ORIGINAL ;;; LAP CODE BY THE ARGS CONSTRUCT. ;;; ;;; TYPE 14 LOC ;;; THE WORD IS A RELOCATABLE QUANTITY SPECIFYING WHERE TO ;;; CONTINUE LOADING. IT IS NOT PERMITTED TO LOC BELOW THE ;;; ORIGIN OF THE ASSEMBLY. IF THE LOC IS TO A LOCATION HIGHER ;;; THAN ANY YET LOADED INTO, THEN FASLOAD ZEROS OUT ALL WORDS ;;; ABOVE THAT HIGHEST LOCATION UP TO THE LOCATION SPECIFIED. ;;; FASLOAD KEEPS TRACK OF THE HIGHEST LOCATION EVER LOADED INTO; ;;; THIS VALUE PLUS ONE BECOMES THE VALUE OF BPORG AT THE END OF ;;; ASSEMBLY, REGARDLESS OF THE STATE OF THE LOCATION POINTER ;;; WHEN LOADING TERMINATES. THIS TYPE IS NEVER USED BY LAP ;;; CODE, BUT ONLY BY MIDAS .FASL CODE. ;;; ;;; TYPE 15 PUTDDTSYM ;;; FIRST WORD, THE SYMBOL IN SQUOZE CODE. IF BIT 4.9=0, THE ;;; SYMBOL IS DEFINED TO DDT IF POSSIBLE WITH THE ADDRESS OF THE ;;; WORD OF BINARY PROGRAM SPACE ABOUT TO BE LOADED INTO AS ITS ;;; VALUE. IF BIT 4.9=1, THE VALUE IS GOBBLED FROM THE FOLLOWING ;;; WORD. BIT 4.8 (OF THE WORD CONTAINING THE SQUOZE) MEANS ;;; RELOCATE THE LEFT HALF OF THE VALUE BY THE LOAD OFFSET, AND ;;; BIT 4.7 LIKEWISE FOR THE RIGHT HALF. WHETHER OR NOT THE ;;; SYMBOL ACTUALLY GETS PUT IN DDT'S SYMBOL TABLE IS A FUNCTION ;;; OF THREE CONDITIONS: FIRST, THAT THERE IS A DDT WITH A SYMBOL ;;; TABLE; SECOND, THE VALUE OF THE LISP VARIABLE "SYMBOLS"; ;;; THIRD, BIT 4.6 OF THE FIRST PUTDDTSYM WORD. THE FIRST ;;; CONDITION OF COURSE MUST BE SATISFIED. IF SO, THEN THE SYMBOL ;;; IS PUT IN THE SYMBOL TABLE ONLY IF SYMBOLS HAS A NON-NIL ;;; VALUE. FURTHERMORE, IF THAT VALUE IS THE ATOM SYMBOLS ITSELF, ;;; THEN THE SYMBOL IS PUT ONLY IF BIT 4.6 IS ON (INDICATING A ;;; "GLOBAL" SYMBOL). ;;; ;;; TYPE 16 EVAL MUNGEABLE ;;; A SERIES OF WORDS SIMILAR TO THOSE FOR TYPE 5, BUT WITH NO ;;; FOLLOWING HASH KEY. AN S-EXPRESSION IS CONSTRUCTED AND ;;; EVALUATED. THIS IS USED FOR THE SO-CALLED "MUNGEABLES" IN A ;;; FILE OF LAP CODE. IF THE LEFT HALF OF THE LAST WORD IS -1, ;;; THE VALUE IS THROWN AWAY. IF IT IS -2, THE VALUE IS ENTERED ;;; IN THE ATOMTABLE. ;;; ;;; TYPE 17 END OF BINARY ;;; ONE WORD, WHICH MUST BE "*FASL+" (OR "*FASL*") IN SIXBIT. ;;; THIS SHOULD BE THE LAST DATA WORD IN THE FILE. ANY RELOCATION ;;; BYTES LEFT OVER AFTER A TYPE 17 ARE IGNORED. THIS SHOULD BE ;;; FOLLOWED EITHER BY END OF FILE OR A WORD FULL OF ^C'S. ;;; INTERNAL AUTOLOAD ROUTINE IALB: HRRZ A,(A) ;SUBR 1 MOVEI B,QA%DDD PUSHJ P,MERGEF JRST LOAD FASLOAD: JSP TT,FWNACK FA01234,,QFASLOAD SKIPE FASLP JRST LDALREADY PUSH P,FLP ;FOR DEBUGGING PURPOSES PUSH P,FXP .SEE LDEOMM PUSH P,SP 10$ SETOM LDEOFP ;FLAG FOR CRUFTY D10 DUMP MODE I/O EOF PUSHJ P,FIL6BT MOVE T,DFNWD ;DEFAULT FILE-NAME WORD - "*" MOVE TT,DFFNWD ;DEFAULT FASL-FILE-NAME WORD - "FASL" 20$ SKIPE -L.6VRS-L.6EXT+1(FXP) ;EXTENSION (2ND FILE NAME) NULL? CAMN T,-L.6VRS-L.6EXT+1(FXP) ; OR EQUAL TO *? IF EITHER CASE, MOVEM TT,-L.6VRS-L.6EXT+1(FXP) ; THEN USE "FASL" IFN D20,[ MOVE TT,[ASCII \0\] SKIPE -L.6VRS+1(FXP) ;VERSION NUMBER NULL? CAMN T,-L.6VRS+1(FXP) ; OR EQUAL TO *? IF EITHER CASE, MOVEM TT,-L.6VRS+1(FXP) ; THEN USE "0" ] ;END OF IFN D20 PUSHJ P,DMRGF PUSHJ P,6BTNML MOVEI B,TRUTH MOVE AR2A,VFEXDEFAULT JSP T,SPECBIND 0 A,LDFNAM ;Must bind LDFNAM for recursive fasloading 0 B,VNORET 0 AR2A,VFEXITFUNCTIONS FASLP PUSH P,[LDXXY1] PUSH P,A PUSH P,[QFIXNUM] MOVNI T,2 JRST $OPEN LDXXY1: MOVEM A,FASLP PUSH P,A ;Save the file to be hacked on for exit JSP TT,UNWINC ;Arrange to do stuff on finish CAIA ; Do the FASLOAD JRST EOFEV ; And go do the associated cleanup, ; including closing the file. PUSH P,A HRRZM A,LDBSAR MOVE A,LDFNAM SETZM LDTEMP ;CROCK! ;FALLS THROUGH ;FALLS IN ;;; COME HERE TO "DO IT SOME MORE" LDDISM: PUSHJ P,LDGDDT ;SET UP DDT FLAG: 0 => NO DDT; PUSH P,TT ;-1,,0 => DDT, NO SYMBOLS; 1,,X => DDT, SYMBOLS ;X MAY BE 0, OR SAR FOR SYMBOL TABLE ARRAY ; (SEE LDPUT) SKIPN F,VPURE ;SET UP CALL PURIFY FLAGS: ;400000,,XXX => NO PURIFY HACKERY TLOA F,400000 ;200000,,XXX => SUBST XCTS FOR CALLS, ; PUT CALLS IN SEPARATE PAGES ;100000 BIT MEANS FASLOAD INTO HISEG (D10 ONLY) HRRZ F,VPURCLOBRL ;0,, => SUBST PUSHJS AND ; JRSTS FOR CALLS PUSH P,F ; ANY CALLS NOT IMMEDIATELY SMASHABLE MOVE A,VPURE ; ARE CONSED ONTO THE PURE LIST PUSHJ P,FIXP ;LEAVES VALUE IN TT IF INDEED FIXNUM JUMPE A,LDXXX1 MOVSI F,200000 IORM F,(P) IFN *HISEGMENT,[ JUMPGE TT,LDXQQ7 ;IF PURE IS A NEGATIVE FIXNUM, DO HISEG HACKERY IFE SAIL,[ HRROI T,.GTSGN ;FIND WHETHER HISEG SHARABLE (FROM GETTAB T, ;6.03 MONITOR CALLS) JRST .+2 TLNN T,(SN%SHR) ] ;END OF IFE SAIL SA$ SKIPL .JBHRL ;IS HISEG CURRENTLY WRITE-PROTECTED? JRST LDXQQ5 PUSH FXP,TT LOCKI ;LOCK OUT INTS AROUND USE OF TMPC SKIPN SGANAM JSP T,FASLUH MOVEI T,.IODMP MOVE TT,SGADEV SETZ D, OPEN TMPC,T ;OPEN UP .SHR FILE DEVICE IN DUMP MODE JSP T,FASLUH MOVE T,SGANAM MOVE TT,SGAEXT SETZ D, MOVE R,SGAPPN LOOKUP TMPC,T JSP T,FASLUR SA$ MOVS T,R SA% JUMPGE R,FASLUR SA% HLRE T,R MOVNS T ;T GETS LENGTH OF .SHR FILE PUSHJ P,LDRIHS ;GO READ IN HIGH SEGMENT (FROM WITHIN LOSEG!) LDRTHS: RELEASE TMPC, ;FLUSH TEMP CHANNEL UNLOCKI POP FXP,TT MOVE F,SVPRLK ;CAN NOW USE SAVED PURE SEGMENTS FROM LAST TIME SETZM SVPRLK MOVEM F,PRSGLK LDXQQ5: MOVSI F,100000 IORM F,(P) ;SET FLAG SAYING WE'RE HACKING THE HISEG MOVMS TT PUSHJ P,LDXHHK ;SET UP XCT PAGES USING HISEG MOVE A,V.PURE PUSHJ P,FIXP ;LEAVES VALUE IN TT IN INDEED FIXNUM JUMPE A,LDXXX1 ;IF FIXNUM, IT IS AN ESTIMATE OF PURE FREE STG CAIG TT,10 ;IF 10 OR LESS, MULTIPLY BY 1024. LSH TT,12 CAILE TT,0 ;CHECK FOR REASONABLENESS CAILE TT,MEMORY+.RL1-ENDHI JRST LDYERR MOVSI D,-NFF-1 SUB TT,PFSSIZ(D) ;SUBTRACT FROM ESTIMATE THE CURRENT AOBJN D,.-1 ; SIZES OF EXISTING PURE AREAS MOVE D,PRSGLK LDXQQ2: JUMPE D,LDXQQ3 ;ALSO ACCOUNT FOR ANY PURE SEGMENTS SUBI TT,SEGSIZ ; ALREADY IN THE FREELIST LDB D,[SEGBYT,,GCST(D)] JRST LDXQQ2 LDXQQ3: JUMPLE TT,LDXXX1 ;JUMP IF GUESSTIMATE ALREADY SATISFIED ADDI TT,SEGSIZ-1 ;ROUND UP TO AN INTEGRAL ANDI TT,SEGMSK ; NUMBER OF SEGMENTS MOVE D,HBPORG ADDI D,SEGSIZ-1 ;ALSO ROUND UP HISEG BPORG ANDI D,SEGMSK MOVE R,D ADD D,TT SUBI D,1 TLNE D,-1 JRST FASLNX ;COMPLAIN IF NOT ENOUGH MEMORY MOVEM D,HBPORG ;UPDATE HISEG BPORG PAST ALLOCATED SEGMENTS AOS HBPORG CAMG D,HBPEND JRST LDXQQ6 MOVEM D,HBPEND ;IF NEW HISEG BPORG TOO LARGE, SA% HRLZI D,(D) SA% CORE D, SA$ CORE2 D, ; MUST REQUEST MORE CORE FOR HISEG JRST FASLNX ;COMPLAIN IF NOT ENOUGH MEMORY LDXQQ6: LSH R,-SEGLOG ;UPDATE SEGMENT TABLES, LSH TT,-SEGLOG ; AND ADD PURE SEGMENTS TO FREELIST MOVE D,[$XM+PUR,,QRANDOM] MOVE F,PRSGLK LDXQQ8: MOVEM D,ST(R) SETZM GCST(R) DPB F,[SEGBYT,,GCST(R)] MOVEI F,(R) ADDI R,1 SOJG TT,LDXQQ8 MOVEM F,PRSGLK JRST LDXXX1 ] ;END OF IFN *HISEGMENT IFN D10*,[ LDXQQ7: HS% MOVMS TT PUSHJ P,LDXHAK ;SET UP XCT HACK PAGES WITHOUT HISEG ] ;END IFN D10* ;FALLS THROUGH ;FALLS IN LDXXX1: MOVE TT,[-LLDAT+1,,1] ;INIT ATOMTABLE AOBJN INDEX MOVEM TT,LDAAOB MOVEI TT,LLDAT ;CREATE ATOMTABLE ARRAY MOVSI A,400000 PUSHJ P,MKLSAR PUSH P,A ;SAVE SAR OF ATOM-TABLE ARRAY FOR GC PROTECTION HRRZM B,LDASAR ;SAVE ADDRESS OF SAR PUSHJ P,LDLRSP ;LOCKI, AND SET UP ARRAY POINTERS SETZ TT, ;ENTRY 0 IN ATOMTABLE IS FOR NIL SETZM @LDAPTR MOVEI TT,LDFERR ;INIT ADDRESS FOR PREMATURE EOF MOVEM TT,LDEOFJ SKIPE F,LDTEMP ;IF LDTEMP IS NON-NIL, IT IS THE SAVED I/O BUFFER POINTER JRST LDXXX9 JSP T,LDGTW1 ;GET FIRST WORD OF FILE TRZ TT,1 ;COMPATIBILITY CROCK CAME TT,[SIXBIT \*FASL*\] ;IT BETTER BE THIS VALUE! JSP D,LDFERR LDXXX9: JSP T,LDGTWD ;GET VERSION OF LISP FILE WAS ASSEMBLED IN XOR TT,LDFNM2 MOVEM TT,LDF2DP ;NON-ZERO IFF VERSIONS DIFFERENT MOVE AR1,[000400,,LDBYTS] ;INIT RELOCATION BYTES POINTER SETZM LDHLOC HRRZ R,@VBPORG HS$ 10$ MOVE TT,LDPRLS(P) HS$ 10$ TLNE TT,100000 ;SKIP UNLESS LOADING INTO HISEG HS$ 10$ HRRZ R,HBPORG HRRM R,LDOFST ;INITIALIZE LOAD OFFSET JRST LDABS0 ;R HAS ADDRESS TO LOAD NEXT WORD INTO SUBTTL ROUTINE TO SET UP PAGES FOR XCT HACK (NON-PAGING, FIXED NUMBER OF SLOTS) IFE PAGING,[ ;;; TT HAS NUMBER OF WORDS (1K BLOCKS IF <8) DESIRED. LDXHHK: HRROS (P) ;THIS ENTRY USES THE HISEG LDXHAK: SKIPE LDXSIZ ;MAYBE WE NEED TO SET UP PAGES FOR XCT HACKERY POPJ P, ;IF NOT, JUST EXIT JUMPLE TT,LDXERR CAIG TT,10 ;IF 10 OR LESS, MULTIPLY BY 1024. LSH TT,12 ADDI TT,PAGSIZ-1 ;ROUND UP TO A WHOLE NUMBER OF PAGES ANDI TT,PAGMSK TLNE TT,-1 JRST LDXERR PUSH FXP,TT MOVE D,(FXP) ;GET ESTIMATED NUMBER OF LINKS MOVEM D,LDXSIZ ;SAVE AS SIZE OF XCT AREA MOVEM D,LDXSM1 ;ALSO NEED THAT VALUE MINUS 1 SOS LDXSM1 MOVE TT,@VBPORG ;CREATE TWO AREAS IN BPS THAT BIG: HRRZ T,TT ; THE FIRST FOR THE XCTS TO POINT TO, ADD TT,D ; THE SECOND TO RESTORE THE FIRST FROM HRL T,TT MOVE R,(P) TLNE R,1 HRL T,HBPORG MOVEM T,LDXBLT ;SAVE BLT POINTER FOR RESTORING TLNN R,1 ;USING HISEG, DON'T TAKE SECOND AREA FROM LOSEG ADD TT,D ;ADD IN FOR SECOND AREA JSP T,FXCONS ;NEW VALUE FOR BPORG PUSH P,A TLNN R,1 LSH D,1 MOVE TT,D PUSHJ P,LGTSPC ;NOW TRY TO GET REQUIRED CORE JUMPE TT,FASLNX MOVE R,-1(P) TLNN R,1 JRST LDXHK3 MOVE D,(FXP) ;GOBBLE SECOND AREA OUT OF HISEG ADD D,HBPORG TLNN D,-1 JRST LDXHK2 LDXHK1: SETZM LDXSIZ ;HAVEN'T REALLY WON AFTER ALL JRST FASLNX LDXHK2: MOVEM D,HBPORG SUBI D,1 CAMG D,HBPEND ;MAY NEED TO EXTEND HISEG JRST LDXHK3 MOVEM D,HBPEND SA% HRLZI D,(D) SA% CORE D, SA$ CORE2 D, JRST LDXHK1 LDXHK3: POP P,VBPORG ;GIVE BPORG NEW VALUE MOVE T,LDXBLT ;ZERO OUT BOTH AREAS MOVE TT,@VBPORG HRL T,T SETZM (T) ADDI T,1 BLT T,-1(TT) TLNN R,1 JRST LDXHK5 MOVS T,LDXBLT ;WHEN USING HISEG, NEED AN EXTRA MOVE TT,HBPORG ; BLT TO ZERO OUT SECOND AREA BLT T,-1(TT) LDXHK5: HRRZ T,LDXBLT ;SET UP LDXDIF WITH THE DIFFERENCE HLRZ TT,LDXBLT ; BETWEEN THE ORIGINS OF AREA 1 AND SUB T,TT .SEE LDPRC6 HRRM T,LDXDIF ; AREA 2 TO MAKE INSTALLING ENTRIES EASIER POPI FXP,1 JRST TRUE ] ;END IFE PAGING SUBTTL PAGING, VARIABLE NUMBER OF XCT PAGES, DYNAMICALLY ALLOCATED IFN PAGING,[ LDXHAK: PUSH FXP,AR1 ;AR1 MUST BE PRESERVED, AT ALL COSTS! LOCKI ;INTERRUPTS MUST BE OFF OVER CALL TO GRBSEG PUSHJ P,GRBSEG ;GET ONE SEGMENT OF TYPE RANDOM JRST LDXIRL ;RELEASE INTERRUPTS AND GIVE NON-SKIP RETURN UNLOCKI PUSHJ P,GRBPSG ;GET ONE PURE SEGMENT INTO AC T POP FXP,AR1 LSH T,SEGLOG ;MAKE PURE SEGMENT INTO ADDRESS HRRZM T,LDXPSP(TT) ;REMEMBER PURE SEGMENT ADDRESS HRLI T,(T) ;BUILD A BLT POINTER TO ZERO PURE PAGE HRRZI D,SEGSIZ-1(T) ;LAST LOC TO ZERO SETZM (T) ;ZERO FIRST LOC ADDI T,1 BLT T,(D) ;AND ALL THE REST HRLZI T,LDXOFS(TT) ;BUILD BLT POINTER TO CLEAR NEW IMPURE SEG HRRI T,LDXOFS+1(TT) SETZM LDXOFS(TT) BLT T,SEGSIZ-1(TT) ;CLEAR THE WHOLE SEGMENT MOVNI T,LDHSH1+1 ;NUMBER OF ENTRIES IN TABLE IMULI T,LDX%FU ;MAKE INTO NEGATIVE PERCENTAGE PUSH FXP,TT IDIVI T,100. POP FXP,TT MOVEM T,LDXLPC ;AND THE COUNT MOVE T,LDXLPL ;REMEMBER LOC OF LAST PAGE USED MOVEM TT,LDXLPL ;SAVE THIS PAGE LOCATION JUMPE T,LDXFLC ;STORE IN POINTER LOC IF NO PREVIOUS SEGMENTS HRLM TT,(T) ;LINK INTO LIST AOS (P) POPJ P, LDXFLC: MOVEM TT,LDXPNT AOS (P) POPJ P, LDXIRL: UNLOCKI POP FXP,AR1 POPJ P, ] ;END IFN PAGING SUBTTL MAIN FASLOAD LOOP ;;; FROM THIS POINT ON, UNTIL A FATAL ERROR OCCURS OR LOCATION LDFEND IS REACHED, ;;; THESE ACCUMULATORS ARE DEDICATED TO THE FOLLOWING PURPOSES: ;;; AR1 BYTE POINTER FOR GETTING SUCCESSIVE RELOCATION TYPES ;;; R AOBJN POINTER FOR PUTTING WORDS INTO BINARY PROGRAM SPACE ;;; F AOBJN INDEX FOR ACCESSING WORDS FROM INPUT BUFFER ARRAY LDREL: HRRI TT,@LDOFST ;[RELOCATABLE WORD] LDABS: MOVEM TT,(R) ;[ABSOLUTE WORD] LDABS1: AOBJN R,LDBIN ;JUMP IF ROOM LEFT OF WHAT WE GRABBED LDABS0: 10$ MOVE TT,LDPRLS(P) ;FOR D10, MUST PASS LDPRLS IN TT TO LDGTSP PUSHJ P,LDGTSP PUSHJ P,LDRSPT LDBIN: SKIPE INTFLG ;[LOAD BINARY WORD (OR SOME OTHER MESS)] PUSHJ P,LDTRYI ;GIVE A POOR INTERRUPT A CHANCE IN LIFE TLNN AR1,770000 JRST LDBIN2 ;OUT OF RELOCATION BYTES - MUST GET MORE LDBIN1: JSP T,LDGTWD ;GET WORD FROM INPUT FILE ILDB T,AR1 ;GET CORRESPONDING RELOCATION BYTE JSP D,@LDTTBL(T) ; - IT TELLS US WHERE TO GO LDBIN2: JSP T,LDGTWD ;GET WORD OF RELOCATION BYTES MOVEM TT,LDBYTS SOJA AR1,LDBIN1 ;INIT BYTE POINTER AND GO GET DATA WORD LDTTBL: LDABS ; 0 ABSOLUTE LDREL ; 1 RELOCATABLE LDSPC ; 2 SPECIAL LDPRC ; 3 PURIFIABLE CALL LDQAT ; 4 QUOTED ATOM LDQLS ; 5 QUOTED LIST LDGLB ; 6 GLOBALSYM PATCH LDGET ; 7 GET DDT SYMBOL PATCH LDAREF ; 10 ARRAY REFERENCE LDFERR ; 11 UNUSED LDATM ; 12 ATOMTABLE ENTRY LDENT ; 13 ENTRY POINT INFO LDLOC ; 14 LOC TO ANOTHER PLACE LDPUT ; 15 PUT DDT SYMBOL LDEVAL ; 16 EVALUATE MUNGEABLE LDBEND ; 17 END OF BINARY ;;; LOADER GET SPACE ROUTINE. PUTS SOME DISTANCE BETWEEN BPORG AND BPEND. ;;; R MUST BE SET UP ALREADY. FOR D10, TT MUST HAVE LDPRLS. ;;; THE LEFT HALF OF R IS ADJECTED TO REFLECT THE SPACE OBTAINED. LDGTSP: HS$ 10$ TLNE TT,100000 ;CHECK IF LOADING INTO HISEG HS$ 10$ JRST LDGSP3 ;IF SO, EXPAND THAT MOVE TT,@VBPEND ;SEE IF ENOUGH ROOM LEFT TO GRAB MORE SUB TT,@VBPORG SUBI TT,100 ;RANDOMLY CHOSEN QUANTITY JUMPGE TT,LDGSP1 ;YES - GO GRAB IT SOVEFX AR1 D R F MOVEI TT,4*PAGSIZ ;GET MANY BLOCKS OF BPS LDGS0A: MOVEM TT,GAMNT PUSHJ P,GTSPC1 JUMPN TT,LDGS0H MOVE TT,GAMNT CAIG TT,100 JRST FASLNC MOVEI TT,100 JRST LDGS0A LDGS0H: RSTRFX F R D AR1 LDGSP1: MOVEI TT,(R) ADDI TT,PAGSIZ ;TRY TO GOBBLE CAMLE TT,@VBPEND ; WORDS, BUT IN ANY CASE MOVE TT,@VBPEND ; NO MORE THAN BEYOND BPEND JSP T,FIX1A MOVEM A,VBPORG MOVEI TT,(R) SUB TT,@VBPORG HRLI R,(TT) ;INIT AOBJN POINTER IN R POPJ P, IFE PAGING+<1-D10>,[ LDGSP3: MOVE TT,HBPEND SUBI TT,(R) ;DO NOT MERGE THIS WITH FOLLOWING SUBI! MAYBE R>777700 SUBI TT,100 ;RANDOMLY CHOSEN QUANTITY JUMPGE TT,LDGSP6 MOVE TT,HBPEND ADDI TT,4*PAGSIZ TLNE TT,-1 MOVSI TT,(MEMORY) ADDI TT,PAGSIZ-1 ANDCMI TT,#PAGMSK ;*NOT* SAME AS ANDI TT,PAGMSK !!! MOVE T,TT SUBI T,1 CAMG T,HBPEND JRST LDGSP4 SA% HRLZI T,(T) SA% CORE T, SA$ CORE2 T, JRST FASLNC MOVE AR2A,[$XM+PUR,,QRANDOM] AOS B,HBPEND MOVEI C,(B) SUBI C,(TT) LSHC B,-SEGLOG HRLI B,(C) LDGSP5: MOVEM AR2A,ST(B) SETZM GCST(B) AOBJN B,LDGSP5 LDGSP4: MOVEM TT,HBPEND SOS HBPEND LDGSP6: MOVE TT,HBPEND MOVEM TT,HBPORG SUBM R,TT HRLI R,(TT) POPJ P, ] ;END OF IFE IFE PAGING+<1-D10> SUBTTL SPECIAL VALUE CELL AND QUOTED ATOM REFERENCES LDSPC: MOVE T,TT ;[SPECIAL] HLR TT,@LDAPTR ;GET ADDRESS OF SPECIAL CELL TRNE TT,777000 ;WAS SUCH AN ADDRESS REALLY THERE? JRST LDABS ;YES, WIN TRNE TT,6 ;NO, IF THIS ATOM ISN'T A SYMBOL JSP D,LDFERR ; THEN LOSE!!! HRRZ TT,T ;IS THERE AN ATOM THERE AT ALL HRRZ A,@LDAPTR SKIPN D,A JSP D,LDFERR ;NO, LOSE HLRZ B,(A) HRRZ A,(B) CAIE A,SUNBOUND JRST LDSPC1 PUSH P,D ;NONE THERE - MUST MAKE ONE MOVEI B,QUNBOUND JSP TT,MAKVC ;RETURN SY2 POINTER IN B LDSPC1: HLRZ TT,(B) ;GET SYMBOL FLAG BITS TRO TT,SY.CCN\SY.OTC ;NEEDED-BY-COMPILED-CODE, OTHER THAN CALL TRNN TT,SY.PUR ;WAS VALUE CELL PURE? HRLM TT,(B) ;NO, THEN MUST PROTECT VALUE CELL MOVE TT,T ;SAVE ADDRESS OF VALUE CELL HRLM A,@LDAPTR ; IN ATOMTABLE HRR TT,A ;AT LAST WE WIN JRST LDABS LDQAT: MOVE D,@LDAPTR ;[QUOTED ATOM] TRNE D,-1 ;DON'T HACK ANYTHING FOR NIL TLNE D,777000 ;EXIT IF SPECIAL, OR SYM BLK ALREADY HACKED JRST LDQATX TLON D,1 ;ELSE TURN ON REFERENCE BIT MOVEM D,@LDAPTR TLNE D,6 ;IF NON-SYMBOL, THEN MAYBE GCPROTECT IT JRST LDQAT1 HLRZ T,(D) ;IF SYMBOL, THEN MAYBE SET ITS "CCN" BITS HLL T,(T) ;FETCH SYMBOL BITS TLO T,SY.CCN\SY.OTC ;FLAG SYMBOL AS NEEDED FOR OTHER THAN CALL TLNN T,SY.PUR ;DON'T TRY TO WRITE IF PURE HLLM T,(T) LDQATX: HRRI TT,(D) JRST LDABS LDQAT1: TLOE D,10 ;IF NON-SYMBOL, AND IF NOT YET GC PROTECTED JRST LDQATX MOVEI A,(D) CAIGE A,IN0+XHINUM CAIGE A,IN0-XLONUM CAIA JRST LDQAT2 PUSHJ P,SAVX3 PUSH P,AR1 PUSHJ P,%GCPRO PUSHJ P,LDRSPT POP P,AR1 PUSHJ P,RSTX3 HRRI D,(A) LDQAT2: MOVEM D,@LDAPTR JRST LDQATX SUBTTL QUOTED LIST REFERENCES LDQLS: MOVSI D,11 ;[QUOTED LIST] SKIPL LDPRLS(P) ;CAN'T COUNT ON ANYTHING IN PURE MOVSI D,1 ; FREE STORAGE PROTECTING ANYTHING PUSHJ P,LDLIST ;GOBBLE UP A LIST MOVEM TT,(R) ;PUT WORD IN BPS JSP T,LDGTWD ;GET HASH KEY FOR LIST TLZ A,-1 SKIPE VGCPRO JRST LDQLS4 PUSH FXP,D PUSH FXP,AR1 TLZ A,-1 SKIPE D,TT JRST LDQLS3 PUSH P,A PUSH FXP,R ;SXHSH0 can call user code! PUSH FXP,F ;So we had better save all our state PUSH FXP,AR1 ;From the ferocious user code! PUSHJ P,SXHSH0 POP FXP,AR1 POP FXP,F POP FXP,R POP P,A LDQLS3: SKIPN V.PURE ;SKIP FOR PURE HACKERY JRST LDQLS1 PUSH FXP,D ;SAVE HASH KEY PUSH P,A ;SAVE LIST MOVNI T,1 ;THIS MEANS JUST LOOKUP PUSHJ P,LDGPRO POP P,B POP FXP,D JUMPN A,LDQLS2 ;ON GCPRO LIST, SO USE IT MOVE A,B PUSHJ P,PURCOPY ;NOT ON GCPRO LIST, SO PURCOPY IT LDQLS1: MOVEI T,1 ;THIS MEANS PROTECT OR HAND BACK COPY PUSHJ P,LDGPRO ;PROTECT LIST FROM FEROCIOUS GC! LDQLS2: POP FXP,AR1 POP FXP,D LDQLS5: JUMPE D,LDEVL7 ;MAYBE THIS LIST GOES INTO ATOMTABLE HRRM A,(R) ;SAVE ADDRESS OF LIST (WHICH MAY JRST LDABS1 ; BE DIFFERENT NOW) BACK INTO WORD LDQLS4: JSP T,LDQLPRO JRST LDQLS5 LDQLPRO: CAIL A,IN0-XLONUM ;JUST EXIT IF INUM CAILE A,IN0+XHINUM-1 JRST .+2 JRST (T) HRRZ B,LDEVPRO JUMPE B,LDQPR1 LDQPR0: HLRZ TT,(B) CAIN A,(TT) JRST (T) ;JUST EXIT IF ALREADY THERE HRRZ B,(B) JUMPN B,LDQPR0 LDQPR1: HRRZ B,LDEVPRO ;GC-PROTECT HAPPENS BY PUSHING ONTO A LIST PUSHJ P,CONS MOVEM A,LDEVPRO JRST %CAR LDGPRO: SKIPE GCPSAR ;PROTECT SOMETHING ON THE GCPSAR JRST .GCPRO PUSHJ P,.GCPRO ;THE LOOKUP CAUSES THE CREATION OF A NEW ARRAY JRST LDRSPT ;SO WE HAVE TO RESTORE PTRS AFTERWARDS SUBTTL PURIFIABLE CALL LDPRC: MOVE D,@LDAPTR ;[PURIFIABLE CALL] TRNN D,-1 ;MUST HAVE NON-NIL ATOM TO CALL JSP D,LDFERR TLNE D,777000 JRST LDPRC1 ;JUMP IF ATOM HAS SPECIAL CELL TLNE D,6 JSP D,LDFERR ;LOSE IF NUMBER TLO D,1 ;ELSE TURN ON REFERENCE BIT MOVEM D,@LDAPTR HLRZ T,(D) ;FETCH SY2 DATA HLL T,(T) TLO T,SY.CCN ;ONLY CCN, NOT OTC!! TLNN T,SY.PUR ;ONLY IF IMPURE HLLM T,(T) LDPRC1: HRR TT,D ;PUT ADDRESS OF ATOM IN CALL SKIPGE T,LDPRLS(P) ;SKIP FOR PURIFYING HACKERY JRST LDABS ;OTHERWISE WE'RE DONE TLNN T,200000 ;SKIP FOR XCT STUFF SETZ T, ;ELSE DO ORDINARY SMASH PUSHJ P,PRCHAK ;*** SMASH! *** JRST LDABS1 MOVEI A,(R) ;NOT SMASHED - CONS ONTO PURE LIST MOVE B,LDPRLS(P) PUSHJ P,CONS MOVEM A,LDPRLS(P) JRST LDABS1 ;;; ROUTINE TO CLOBBER A CALL INTO BPS, POSSIBLY DOING XCT HACK. ;;; SKIPS ON *** FAILURE *** TO CLOBBER. ;;; T NON-ZERO => TRY XCT HACK; OTHERWISE ORDINARY SMASH. ;;; TT HAS UUO INSTRUCTION TO HACK. ;;; R HAS ADDRESS TO PUT UUO INTO. ;;; MUST PRESERVE AR1, R, F. IFE PAGING,[ ;VERSION FOR NON-PAGING ONLY, NEWER VERSION SUPPORTS EXTENDABLE NUMBER OF SEGMENTS PRCHAK: JUMPE T,LDPRC5 ;T ZERO => ORDINARY SMASH MOVE T,TT ;SAVE CALL IN T IDIV TT,LDXSM1 ;COMPUTE HASH CODE FOR CALL MOVNM D,LDTEMP ;SAVE NEGATIVE THEREOF HLRZ TT,LDXBLT ADD D,TT ;ADDRESS TO BEGIN SEARCH CAMN T,(D) ;WE MAY WIN IMMEDIATELY JRST LDPRC7 SKIPN (D) JRST LDPRC6 ADD TT,LDXSM1 ;ELSE MAKE UP AN AOBJN POINTER SUBI TT,-1(D) ; AND SEARCH FOR MATCHING CALL MOVNI TT,(TT) HRL D,TT LDPRC2: CAMN T,(D) JRST LDPRC7 ;FOUND MATCHING CALL SKIPN (D) JRST LDPRC6 ;FOUND EMPTY SLOT AOBJN D,LDPRC2 HRLZ D,LDTEMP ;WRAPPED OFF THE END OF THE XCT AREA HLR D,LDXBLT ; - MAKE UP NEW AOBJN POINTER LDPRC3: CAMN T,(D) ;SECOND COPY OF THE LOOP JRST LDPRC7 ;FOUND MATCHING CALL SKIPN (D) JRST LDPRC6 ;FOUND EMPTY SLOT AOBJN D,LDPRC3 LDPRC4: MOVE TT,T ;TOTAL LOSS - MUST DO SMASH LDPRC5: HRRZ AR2A,R ;PUT ADDRESS OF CALL IN AR2A MOVEM TT,(AR2A) ;PUT CALL IN THAT PLACE JRST LDSMSH ;NOW TRY TO SMASH IT, EXITING WITH SKIP ON FAILURE LDPRC6: SKIPG LDXSIZ ;FOUND EMPTY SLOT JRST LDPRC4 ;CAN'T USE IT IF PAGES PURIFIED MOVEM T,(D) ;SAVE CALL INTO XCT AREA 2 MOVEM T,@LDXDIF ;ALSO SAVE INTO AREA 1 LDPRC7: ADD D,LDXDIF ;MAKE UP AN XCT TO POINT TO HRLI D,(XCT) ; CALL IN AREA 1 MOVEM D,(R) POPJ P, ] ;END IFE PAGING IFN PAGING,[ ;NEW STYLE SEARCH FOR PROPER LINK LOCATION; ADDS A NEW UUOLINKS SEGMENT IF ; OUT OF SPACE OR IF PARTIALLY EMPTY UUOLINK SEGMENT HAS BEEN PURIFIED PRCHAK: JUMPN T,PRCHA1 ;DON'T SMASH IMMEDIATLY IF T NON-ZERO PRCSMS: HRRZ AR2A,R ;PUT ADDRESS OF CALL IN AR2A MOVEM TT,(AR2A) ;PUT CALL IN THAT PLACE JRST LDSMSH ;TRY TO SMASH IT, EXITING WITH SKIP ON FAILURE PRCHA1: PUSH FXP,R ;NEED D/R PAIR OF ACS MOVE D,TT ;GET COPY OF THE CALL IDIVI D,LDHSH1 ;COMPUTE FIRST HASH VALUE MOVEM R,LDXHS1 MOVE D,TT ;THEN THE SECOND HASH VALUE IDIVI D,LDHSH2 AOS R ;IT BEING ZERO COULD BE A DISASTER MOVEM R,LDXHS2 SKIPN T,LDXPNT ;GET POINTER JRST PRCH2A ;FIRST TIME THROUGH ALWAYS ADD NEW SEGMENT PRCH1A: HRRZ D,LDXPSP(T) ;GET POINTER TO PURE PAGE MOVEI R,LDXOFS(D) ;POINTER TO FIRST WORD OF DATA ADDI D,SEGSIZ-1 ;THIS IS THE LAST WORD IN THE SEGMENT ADD R,LDXHS1 ;START FROM THE FIRST HASH VALUE PRCH1B: CAMN TT,(R) ;MATCH? JRST PRCHA3 ;YUP, SO USE THIS SLOT SKIPN (R) ;END OF CHAIN? JRST PRCHA4 ;YES, ON TO NEXT SEGMENT ADD R,LDXHS2 ;STEP BY HASH VALUE CAILE R,(D) ;MUST NOT RUN OFF END OF SEGMENT SUBI R,LDHSH1 ;SO TAKE IT MOD LDHSH1 JRST PRCH1B ;AND TRY THIS SLOT PRCHA4: HLRZ D,LDXPSP(T) ;GET POINTER TO NEXT SEGMENT JUMPE D,PRCHA2 MOVEI T,(D) JRST PRCH1A PRCHA3: HRRZ D,LDXPSP(T) ;SUBTRACTING THIS WILL GIVE ABSOLUTE SEG OFFSET SUBM R,D ADDI D,(T) ;THEN PRODUCE POINTER TO FROB TO XCT POP FXP,R ;RESTORE POINTER TO CODE HRLI D,(XCT) MOVEM D,(R) ;THEN STORE THE NEW INSTRUCTION POPJ P, ;GET HERE WITH C(R) POINTING TO SLOT TO ADD NEW ENTRY TO IN PURE TABLE, DUE TO ; THE DESIGN OF THE MECHANISM, IN THE CASES THAT R IS INVALID, A NEW UUO PAGE ; WILL HAVE TO BE ADDED AND R WILL NOT BE USED. IF THAT IS CHANGED, THIS ; ROUTINE MUST BE FIXED PRCHA2: AOSLE LDXLPC ;IF THIS SEGMENT IS FULL JRST PRCH2A ; ADD A NEW ONE MOVEM TT,(R) ;STORE THE CALL IN THE POTENTIALLY PURE SEGMENT HRRZ D,LDXPSP(T) ;THEN BUILD POINTER TO IMPURE SEGMENT SUBM R,D ADDI D,(T) ;D CONTAINS ADR IN IMPURE SEGMENT MOVEM TT,(D) ;STORE THE CALL INSTRUCTION THERE POP FXP,R ;GET ADR OF ACTUAL CODE HRLI D,(XCT) ;THEN INSTRUCTION TO PLANT THERE MOVEM D,(R) POPJ P, PRCH2A: PUSH FXP,TT ;SAVE TT OVER SEGMENT GRAB PUSHJ P,LDXHAK ;ADD A NEW SEGMENT LERR [SIXBIT \CANNOT ADD NEW UUOLINKS SEGMENT - FASLOAD!\] POP FXP,TT MOVE T,LDXLPL ;GET POINTER TO THE PAGE JUST ADDED MOVEI D,LDXOFS(T) ;FIRST DATA ADR ADD D,LDXHS1 ;ADR TO INSTALL CALL INTO MOVEM TT,(D) ;STORE THE CALL TO BE POTENTIALLY SMASHED HRLI D,(XCT) ;THE XCT INSTRUCTION POP FXP,R MOVEM D,(R) ;PLANT IN CODE HRRZ D,LDXPSP(T) ;PURE SEGMENT POINTER ADD D,LDXHS1 ADDI D,LDXOFS MOVEM TT,(D) ;PLANT CALL IN POTENTIALLY PURE SEGMENT POPJ P, ;HERE TO TRY TO SMASH CALL IN IMPURE SEGMENT. CALLED ONLY IF FLAG IS SET. ; POINTER TO WORD IN THE SEGMENT IS IN D. DESTROYS A, B, C, T PRTRTS: HRRZ AR2A,D ;PUT ADDRESS OF CALL IN AR2A PUSH FXP,D ;SAVE VALUABLE AC'S PUSH FXP,TT PUSH FXP,T PUSHJ P,LDSMSH ;TRY TO SMASH THE CALL JFCL ;WE DON'T REALLY CARE IF IT WINS OR NOT POP FXP,T POP FXP,TT POP FXP,D POPJ P, ] ;END IFN PAGING ;;; SMASH A CALL-TYPE UUO IN MEMORY TO BE A PUSHJ OR JRST OR WHATEVER. ;;; AR2A HAS THE LOCATION OF THE CALL. ;;; RETURN SKIPS IF IT CAN'T BE SMASHED. ;;; DESTROYS A, B, C, T, TT, D; SAVES AR1, AR2A, R, F. ;;; MUST NOT USER ANY PDL EXCEPT THE REGPDL (P). .SEE PURIFY LDSMSH: MOVE T,(AR2A) LSH T,-33 ;T GETS THE CALL UUO OPCODE CAIL T,CALL_-33 CAILE T,CALL_-33+NUUOCLS POPJ P, ;RETURN IF NOT REALLY A CALL HRRZ A,(AR2A) MOVEI B,SBRL PUSHJ P,GETLA ;TRY TO GET SUBR, FSUBR, OR LSUBR PROP LDB D,[270400,,(AR2A)] JUMPE A,LDSMNS ;JUMP IF NOT ANY OF THOSE HLRZ B,(A) HRRZ T,(AR2A) HLRZ T,(T) HLRZ T,1(T) ;GET ARGS PROPERTY FOR FUNCTION NAME SOJL T,LDZA2 ;JUMP IF THERE ISN'T ANY CAIG T,NACS ;ARGS PROPERTY IS SCREWY IF THIS SKIPS! TLOA T,(CAIE D,) ;IF ARGS PROP OK, TEST FOR THAT EXACT NUMBER OF ARGS IN UUO LDZA2: MOVE T,[CAILE D,NACS] ;IF NO OR BAD ARGS PROP, JUST CHECK FOR RANGE CAIN B,QFSUBR MOVE T,[CAIE D,17] CAIN B,QLSUBR MOVE T,[CAIE D,16] XCT T ;AC FIELD OF CALL IS 0-5 FOR SUBRS, 16 LSUBR, 17 FSUBR JRST POPJ1 ;SKIP RETURN IF CALL DOESN'T MATCH FUNCTION TYPE OR # ARGS HRRZ A,(A) ;ELSE WIN - SMASH THE CALL HLRZ A,(A) ;SUBR ADDRESS NOW IN A SKIPA TT,(AR2A) LDZAOK: HRLI A,(@) .SEE ASAR MOVSI T,(PUSHJ P,) ;CALL BECOMES PUSHJ TLNE TT,20000 ADDI A,1 ;HACK NCALLS CORRECTLY - ENTER AT ROUTINE+1 TLNE TT,1000 MOVSI T,(JRST) ;JCALL BECOMES JRST LDZA1: IOR T,A MOVEM T,(AR2A) ;***SMASH!*** POPJ P, LDSMNS: HRRZ A,(AR2A) ;TRY TO GET ARRAY PROPERTY MOVEI B,QARRAY PUSHJ P,$GET MOVEI T,(A) LSH T,-SEGLOG MOVE T,ST(T) TLNN T,SA JRST POPJ1 ;LOSE IF NOT SAR LDB T,[TTSDIM,,TTSAR(A)] CAIE T,(D) ;MUST HAVE CORRECT NUMBER OF ARGS JRST POP1J MOVSI T,TTS IORM T,TTSAR(A) ;SET "COMPILED-CODE-NEEDS-ME" BIT IN SAR MOVE TT,(AR2A) TLNN TT,20000 JRST LDZAOK MOVSI T,(ACALL) ;FOR AN NCALL-TYPE UUO, SMASH IT TO TLNE TT,1000 ; BE A CROCKISH ACALL OR AJCALL MOVSI T,(AJCALL) JRST LDZA1 SUBTTL GETDDTSYM HACKERY LDGET: CAMN TT,XC-1 JRST LDLHRL MOVE D,TT ;[GET DDT SYMBOL PATCH] TLNN D,200000 ;MAYBE THE ASSEMBLER LEFT US A VALUE? JRST LDGET2 JSP T,LDGTWD ;FETCH IT THEN SKIPE LDF2DP JRST LDGET2 ;CAN'T USE IT IF VERSIONS DIFFER LDGET1: TLNE D,400000 ;MAYBE NEGATE SYMBOL? MOVNS TT LDB D,[400200,,D] ;GET FIELD NUMBER XCT LDXCT(D) ;HASH UP VALUE FOR FIELD MOVE T,LDMASK(D) ;ADD INTO FIELD ADD TT,-1(R) ; MASKED APPROPRIATELY AND TT,T ANDCAM T,-1(R) IORM TT,-1(R) JRST LDBIN LDGET2: UNLOCKI ;UNLOCK INTERRUPTS PUSH FXP,. ;RANDOM FXP SLOT PUSH FXP,AR1 ;SAVE UP ACS PUSH FXP,D PUSH FXP,R PUSH FXP,F MOVEI R,0 TLZ D,740000 REPEAT LOG2LL5,[ CAML D,LAPFIV+<1_>(R) ADDI R,1_ ] ;END OF REPEAT LOG2LL5 CAME D,LAPFIV(R) ;IF DDTSYM REQUEST IS FOR A GLOBAL SYM JRST LDGT5A ;THEN FIND IT IN THE LAPFIV TABLE, AND GET ITS LSHC R,-2 ;GLOBALSYM INDEX FROM THE PERMUTATION TABLE LSH F,-42 LDB TT,LDGET6(F) MOVE TT,LSYMS(TT) JRST LDGT5B LDGT5A: MOVEI TT,R70 CAMN D,[SQUOZE 0,R70] JRST LDGT5B PUSHJ P,UNSQOZ ;CONVERT SQUOZE TO A LISP SYMBOL MOVEI C,(A) MOVEI B,QSYM ;TRY TO FIND SYM PROPERTY PUSHJ P,$GET JUMPN A,LDGETJ ;WIN IFN ITS,[ JSP T,SIDDTP ;MAYBE WE CAN GET VALUE FROM DDT? JRST LDGETX LDB T,[004000,,-2(FXP)] .BREAK 12,[..RSYM,,T] JUMPE T,LDGETX ;LOSE, LOSE, LOSE ] ;END OF IFN ITS IFN D10,[ SKIPN .JBSYM" JRST LDGETX LDB D,[004000,,-2(FXP)] LDGET4: MOVE TT,D IDIVI D,50 JUMPE R,LDGET4 PUSHJ P,GETDDJ JRST LDGETX ] ;END OF IFN D10 LDGT5B: MOVEM TT,-4(FXP) ;WIN, WIN - USE RANDOM FXP SLOT MOVEI A,-4(FXP) ; TO FAKE UP A FIXNUM JRST LDGETJ LDGETX: MOVEI A,(C) PUSHJ P,NCONS MOVEI B,QGETDDTSYM ;DO A FAIL-ACT PUSHJ P,XCONS PUSHJ P,LDGETQ LDGETJ: POP FXP,F ;RESTORE ACS POP FXP,R POP FXP,D POP FXP,AR1 PUSHJ P,LDLRSP ;LOCKI AND RESTORE ARRAY POINTERS MOVE TT,(A) PUSHJ P,TYPEP ;FIGURE OUT WHAT WE GOT BACK POP FXP,-1(FXP) ;POP RANDOM SLOT (REMEMBER THE LOCKI!) CAIN A,QFIXNUM JRST LDGET1 LDGETV: CAIN A,QFLONUM ;USE A FLONUM IF WE GET ONE JRST LDGET1 LDGETW: PUSHJ P,LDGDDT ;FOR ANYTHING ELSE TRY DDT AGAIN MOVEM TT,LDDDTP(P) JRST LDGET2 LDGET6: REPEAT 4,[<11_24.>+<<<3-.RPCNT>*11>_30.> LAP5P(R) ] IFN ITS,[ LDGDDT: JSP T,SIDDTP JRST ZPOPJ ;0 => TOP LEVEL, OR NOT INFERIOR TO DDT .BREAK 12,[..RSTP,,TT] ;-1,,0 => INFERIOR TO DDT, BUT NO SYMBOL TABLE SKIPN TT ;1,,0 => INFERIOR TO DDT WITH SYMBOL TABLE TLOA TT,-1 MOVSI TT,1 POPJ P, ] ;END OF IFN ITS IFN D20,[ LDGDDT==:ZPOPJ ;FOR NOW, NEVER A DDT ] ;END IFN D20 IFN D10,[ LDGDDT: SKIPE TT,.JBSYM" MOVSI TT,1 POPJ P, ] ;END OF IFN D10 LDXCT: MOVSS TT ;INDEX FIELD HRRZS TT ;ADDRESS FIELD LSH TT,23. ;AC FIELD JFCL ;OPCODE FIELD LDMASK: -1 ;INDEX FIELD 0,,-1 ;ADDRESS FIELD 0 17, ;AC FIELD -1 ;OPCODE FIELD LDLHRL: HRLZ TT,LDOFST ADDM TT,-1(R) JRST LDBIN SUBTTL ARRAY, GLOBALSYM, AND ATOMTABLE ENTRY STUFF LDAREF: PUSH FXP,TT ;[ARRAY REFERENCE] MOVE D,@LDAPTR TLNN D,777001 TLO D,11 MOVEM D,@LDAPTR TRNN D,-1 JRST LDARE1 ;SKIP IF HACKING 'NIL' TLNE D,777000 ;IF NO VC THEN MUST HACK SYMBOL JRST LDARE1 HLRZ T,(D) HLL T,(T) TLO T,SY.CCN\SY.OTC ;COMPILED CODE NEEDS, OTHER THAN CALL REF TLNN T,SY.PUR ;CAN'T WRITE IF PURE HLLM T,(T) LDARE1: MOVEI A,(D) PUSHJ P,TTSR+1 ;NCALL TO TTSR HLL TT,(FXP) SUB FXP,R70+1 JRST LDABS LDGLB: SKIPL TT ;[GLOBALSYM PATCH] SKIPA TT,LSYMS(TT) ;GET VALUE OF GLOBAL SYMBOL MOVN TT,LSYMS(TT) ;OR MAYBE NEGATIVE THEREOF ADD TT,-1(R) ;ADD TO ADDRESS FIELD OF HRRM TT,-1(R) ; LAST WORD LOADED JRST LDBIN LDATM: LDB T,[410300,,TT] ;[ATOMTABLE ENTRY] JRST LDATBL(T) LDATBL: JRST LDATPN ;PNAME JRST LDATFX ;FIXNUM JRST LDATFL ;FLONUM BG$ JRST LDATBN ;BIGNUM BG% JRST LDATER DB$ JRST LDATDB ;DOUBLE DB% JRST LDATER CX$ JRST LDATCX ;COMPLEX CX% JRST LDATER DX$ JRST LDATDX ;DUPLEX DX% JRST LDATER .VALUE ;UNDEFINED LDATPN: MOVEI D,(TT) ;[ATOMTABLE PNAME ENTRY] PUSH FXP,R CAILE D,LPNBUF JRST LDATP2 MOVEI C,PNBUF-1 LDATP1: JSP T,LDGTWD ADDI C,1 MOVEM TT,(C) SOJG D,LDATP1 SETOM LPNF JRST LDATP4 LDATP2: PUSH FXP,D LDATP3: JSP T,LDGTWD JSP T,FWCONS PUSH P,A SOJG D,LDATP3 POP FXP,T MOVNS T PUSHJ FXP,LISTX SETZM LPNF LDATP4: PUSH FXP,AR1 PUSHJ P,RINTERN POP FXP,AR1 POP FXP,R LDATP8: MOVE TT,LDAAOB MOVEM A,@LDAPTR AOBJP TT,LDAEXT MOVEM TT,LDAAOB JRST LDBIN LDATFX: JSP T,LDGTWD ;[ATOMTABLE FIXNUM ENTRY] PUSH FXP,TT MOVEI A,(FXP) PUSH P,AR1 PUSHJ P,GCLOOK POP P,AR1 POP FXP,TT SKIPE A LDATX0: TLOA A,10 JRST LDATX2 LDATX1: TLO A,2 JRST LDATP8 LDATX2: SKIPE V.PURE JRST LDATX3 JSP T,FXCONS JRST LDATX1 LDATX3: PUSHJ P,PFXCONS JRST LDATX0 LDATFL: JSP T,LDGTWD ;[ATOMTABLE FLONUM ENTRY] PUSH FLP,TT MOVEI A,(FLP) PUSH P,AR1 PUSHJ P,GCLOOK POP P,AR1 POP FLP,TT SKIPE A LDATL0: TLOA A,10 JRST LDATL2 LDATL1: TLO A,4 JRST LDATP8 LDATL2: SKIPE V.PURE JRST LDATL3 JSP T,FLCONS JRST LDATL1 LDATL3: PUSHJ P,PFLCONS JRST LDATL0 IFN BIGNUM,[ LDATBN: PUSH FXP,TT ;[ATOMTABLE BIGNUM ENTRY] MOVEI D,(TT) MOVEI B,NIL LDATB1: JSP T,LDGTWD SKIPE V.PURE JRST LDATB2 JSP T,FWCONS PUSHJ P,CONS JRST LDATB3 LDATB2: PUSHJ P,PFXCONS PUSHJ P,PCONS LDATB3: MOVE B,A SOJG D,LDATB1 POP FXP,TT TLNE TT,1 TLO A,-1 SKIPE V.PURE JRST LDATB6 PUSH P,AR1 PUSHJ P,BNCONS PUSH P,A ;SAVE NEWLY-CONSTRUCTED BIGNUM PUSHJ P,GCLOOK ;SEE IF ONE ALREADY AVAILABLE POP P,B POP P,AR1 JUMPN A,LDATB8 MOVE A,B JRST LDATB7 LDATB6: PUSHJ P,PBNCONS LDATB8: TLO A,10 LDATB7: TLO A,6 JRST LDATP8 ] ;END OF IFN BIGNUM LDAEXT: MOVE T,TT ;[ATOMTABLE EXTEND] HRLI T,-ILDAT MOVEM T,LDAAOB ADDI TT,ILDAT ASH TT,1 UNLOCKI .SEE ERROR5 ;.REARRAY MAY PULL AN ERINT PUSH FXP,AR1 PUSH FXP,R PUSH FXP,F PUSH P,[LDRFRF] PUSH P,LDASAR PUSH P,[TRUTH] PUSH FXP,TT MOVEI A,(FXP) PUSH P,A MOVNI T,3 JRST .REARRAY LDRFRF: SUB FXP,R70+1 ;[RETURN FROM .REARRAY FUNCTION] POP FXP,F POP FXP,R POP FXP,AR1 PUSHJ P,LDLRSP JRST LDBIN SUBTTL ENTRY POINT LDENT: HRRZ C,@LDAPTR ;[ENTRY POINT INFO] MOVSS TT HRRZ A,@LDAPTR PUSH P,A PUSH P,C SKIPN B,VFASLOAD JRST LDNRDF CAIN B,TRUTH ;IF C(FASLOAD) IS T MOVEI B,SBRL ;THEN USE (SUBR LSUBR FSUBR) HRRZ A,(P) ;IS PROPERTY BEING DEFINED ONE OF INTEREST? PUSHJ P,MEMQ1 JUMPE A,LDNRDF ;NOPE, SO PRINT NO MESSAGES MOVE B,VFASLOAD CAIN B,TRUTH ;IF C(FASLOAD) IS T MOVEI B,SBRL ;THEN USE (SUBR LSUBR FSUBR) HRRZ A,-1(P) ;ATOM THAT IS BEING HACKED PUSHJ P,GETL ;DID THIS PREVIOUSLY HAVE A PROP OF INTEREST? JUMPE A,LDNRDF ;NOPE, NO MESSAGES TO BE PRINTED PUSH P,A PUSH FXP,AR1 PUSH FXP,R PUSH FXP,F MOVEI A,TRUTH JSP T,SPECBIND 0 A,V%TERPRI STRT 17,[SIXBIT \^M;CAUTION#! !\] MOVE A,-2(P) PUSHJ P,MSGFCK TLO AR1,200000 PUSHJ P,$PRIN1 ;SAVES AR1 HRRZ B,@(P) HLRZ B,(B) MOVEI TT,[SIXBIT \, A SYSTEM !\] 10% CAIL B,ENDFUN 10$ CAIGE B,BEGFUN MOVEI TT,[SIXBIT \, A USER !\] STRT 17,(TT) HLRZ A,@(P) PUSHJ P,$PRIN1 ;AR1 IS STILL GOOD HRRZ TT,@(P) HLRZ TT,(TT) MOVEI T,(TT) LSH T,-SEGLOG HRRZ T,ST(T) CAIE T,QRANDOM JRST LDENT4 STRT 17,[SIXBIT \ AT !\] ;USE OF PRINL4 HERE DEPENDS ON PRIN1 PUSHJ P,PRINL4 ; LEAVING ADDRESS OF TYO IN R (AND FILES IN AR1) LDENT4: STRT 17,[SIXBIT \, IS BEING REDEFINED^M; AS A !\] HRRZ A,-1(P) PUSHJ P,$PRIN1 STRT 17,[SIXBIT \ BY FASL FILE !\] MOVE A,LDFNAM PUSHJ P,$PRIN1 PUSHJ P,TERP1 PUSHJ P,UNBIND POP FXP,F POP FXP,R POP FXP,AR1 SUB P,R70+1 LDNRDF: MOVE B,(P) MOVE A,-1(P) PUSHJ P,REMPROP POP P,C MOVE A,(P) JSP T,LDGTWD PUSH FXP,TT MOVEI B,@LDOFST CAILE B,(R) JSP D,LDFERR PUSHJ P,PUTPROP POP FXP,TT HLRZ T,TT HLRZ B,@(P) HLRZ D,1(B) CAIN D,(T) ;NEEDN'T DO IT IF ALREADY SAME JRST LDPRG3 JUMPN T,LDPARG MOVEI D,1(B) ;IF COMPLR DIDN'T HAVE ANY INFO LSH D,-SEGLOG ;BOUT ARGS, THEN CLOBBER ONLY IF MOVE D,ST(D) ;IT IS IMPURE TLNE D,ST.PUR JRST LDPRG3 LDPARG: ;ELSE TRY TO CLOBBER IT IN PURTRAP LDPRG9,B, HRLM T,1(B) LDPRG3: SUB P,R70+1 JRST LDBIN SUBTTL PUTDDTSYM FROM FASL FILE ;;; THE WORD IN TT HAS SQUOZE FOR DEFINED SYMBOL, PLUS FOUR BITS: ;;; 4.9 1 => FOLLOWING WORD IS VALUE, 0 => LOAD LOC IS VALUE ;;; 4.8 LH IS RELOCATABLE ;;; 4.7 RH IS RELOCATABLE ;;; 4.6 IS GLOBAL (0 => SYMBOLS = 'T LOADS, BUT = 'SYMBOLS DOES NOT) LDPUT: SKIPN A,V$SYMBOLS JRST LDPUT3 ;FORGET IT IF "SYMBOLS" IS () CAIE A,Q$SYMBOLS JRST LDPUT7 TLNN TT,40000 ;IF "SYMBOLS" IS BOUND TO "SYMBOLS", THEN JRST LDPUT3 ; LOAD ONLY GLOBALS LDPUT7: IFE ITS,[ SKIPN .JBSYM" JRST LDPUT3 PUSH FXP,AR1 ] ;END OF IFE ITS JUMPL TT,LDPUT2 MOVE D,R LDPUT0: IT% PUSH FXP,D IT% PUSH FXP,F TLZ TT,740000 TLO T,%SYGBL+%SYHKL ;GLOBAL AND HALF-KILLED IFN ITS,[ SKIPG A,LDDDTP(P) JRST LDBIN ;FORGET IT IF DDT HAS NO SYMBOL TABLE MOVE T,TT TRNE A,-1 ;MAY HAVE TO CREATE SYMBOL TABLE ARRAY JRST LDPUT5 UNLOCKI PUSH FXP,AR1 PUSHJ P,SAVX5 MOVEI TT,LLDSTB*2+1 MOVSI A,-1 PUSHJ P,MKFXAR PUSHJ P,RSTX5 POP FXP,AR1 PUSHJ P,LDLRSP HRRM A,LDDDTP(P) LDPUT4: MOVSI TT,-LLDSTB ;USE TT FOR TWO THINGS HERE! MOVEM TT,@TTSAR(A) LDPUT5: SETZ TT, AOS TT,@TTSAR(A) ;GET AOBJN POINTER JUMPGE TT,LDPUT4 MOVEM T,@TTSAR(A) ;SAVE SQUOZE FOR SYMBOL ADD TT,R70+1 MOVEM D,@TTSAR(A) ;SAVE ITS VALUE MOVE T,TT SETZ TT, MOVEM T,@TTSAR(A) ;SAVE BACK INCREMENTED AOBJN PTR JUMPL T,LDBIN PUSHJ P,LDPUTM ;MAY BE TIME TO OUTPUT BUFFER ] ;END OF IFN ITS IFN D10,[ LDPUT1: MOVE T,TT IDIVI TT,50 JUMPE D,LDPUT1 MOVEI B,-1(FXP) MOVSI R,400000 PUSHJ P,PUTDD0 POP FXP,F POP FXP,R POP FXP,AR1 ] ;END OF IFN D10 JRST LDBIN IFN ITS,[ LDPUTM: SETZ TT, MOVN T,@TTSAR(A) MOVSI T,(T) HRR T,TTSAR(A) AOSGE T .BREAK 12,[..SSTB,,T] POPJ P, ] ;END OF IFN ITS, LDPUT2: MOVE D,TT JSP T,LDGTWD EXCH TT,D TLNN TT,100000 JRST LDPT2A MOVE T,LDOFST ADD T,D HRRM T,D LDPT2A: TLNN TT,200000 JRST LDPUT0 HRLZ T,LDOFST ADD D,T JRST LDPUT0 LDPUT3: JUMPGE TT,LDBIN ;DON'T WANT TO PUT DDT SYM, BUT JSP T,LDGTWD ; MAYBE NEED TO FLUSH EXTRA WORD JRST LDBIN LDLOC: MOVEI TT,@LDOFST MOVEI D,(R) CAMLE D,LDHLOC MOVEM D,LDHLOC CAMG TT,LDHLOC JRST LDLOC5 MOVE D,LDHLOC SUBI D,(R) MOVSI D,(D) ADD R,D HRR R,LDHLOC SETZ TT, SUB F,R70+1 ;BEWARE THIS BACK-UP CROCK! ADD AR1,[040000,,] JRST LDABS LDLOC5: HRRZ D,LDOFST CAIGE TT,(D) JSP D,LDFERR MOVEI D,(TT) SUBI D,(R) MOVSI D,(D) ADD R,D HRRI R,(TT) JRST LDBIN SUBTTL EVALUATE MUNGEABLE LDEVAL: SETZ D, ;[EVALUATE MUNGEABLE] PUSHJ P,LDLIST ;IF D IS LEFT 0 AFTER LDLIST, THEN WANT ENTRY INTO ATOMTABLE MOVEI B,(P) ;B HAS ADDR OF FASLOAD TEMPS ON STACK PUSH P,A PUSHJ P,LDEV0 SUB P,R70+1 JUMPN D,LDBIN ;;; THIS WILL PUT A MUNGEABLE/SQUIDIFIED SYMBOL ONTO THE LDEVPRO LIST, DUE TO ;;; THE BUG IN THE GC NOTED IN LISP BUG MAIL OF 9/2/79 BY JONL. SKOTT A,SY JRST LDEVL7 SKIPE B,V.PURE CAIN B,QSYMBOL JRST LDEVL6 ;NO PURE COPY NEEDED PUSHJ P,PURCOPY JRST LDEVL7 LDEVL6: JSP T,LDQLPRO ;PUSHES GOODY ONTO THE LDEVPRO LIST LDEVL7: TLO A,16 ;AND GOES OFF TO ENTER INTO THE ATOMTABLE SKOTT A,SY+FL+FX JRST LDATP8 TLNE TT,SY TLZ A,6 TLNE TT,FX TLZ A,4 TLNE TT,FL TLZ A,2 JRST LDATP8 LDEV0: UNLOCKI ;EVALUATES AN S-EXPRESSION IN A JUMPE D,LDEV2 ;ALLOWS FOR RECURSIVE FASLOADING SETZM FASLP ;EXCEPT WHEN EVALUATING FOR ENTRY INTO ATOMTABLE PUSH P,A MOVE C,LDPRLS(B) TLNN C,600000 HRRZM C,VPURCLOBRL IFN D10*HISEGMENT,[ TLNN C,100000 JRST LDEV4 HRRZM R,HBPORG JRST LDEV5 LDEV4: ] ;END OF IFN D10*HISEGMENNT MOVEI TT,(R) JSP T,FXCONS MOVEM A,VBPORG LDEV5: HRRZ TT,LDOFST ;IN CASE EVALUATION CHANGES BPORG, SUBI TT,(R) ; MUST CHANGE LDOFST TO BE AN HRRM TT,LDOFST ; ABSOLUTE QUANTITY MOVNI T,LFTMPS PUSH FXP,BFTMPS+LFTMPS(T) AOJL T,.-1 POP P,A LDEV2: PUSH FXP,B PUSH FXP,AR1 PUSH FXP,D PUSH FXP,R PUSH FXP,F PUSHJ P,EVAL POP FXP,F POP FXP,R POP FXP,D POP FXP,AR1 POP FXP,B JUMPE D,LDEV1 HS$ 10$ MOVE C,LDPRLS(B) HS$ 10$ TLNE C,100000 HS$ 10$ SKIPA R,HBPORG MOVE R,@VBPORG HRRZ T,LDBGEN(B) MOVEM T,FASLP MOVEI T,LFTMPS-1 POP FXP,BFTMPS(T) SOJGE T,.-1 HRRZ TT,LDOFST ;NOW RE-RELOCATE THE LOAD OFFSET ADDI TT,(R) HRRM TT,LDOFST HRRZ T,VPURCLOBRL HRRM T,LDPRLS(B) LDEV1: PUSH P,A 10$ MOVE TT,LDPRLS(B) ;FOR D10, PASS LDPRLS IN TT TO LDGTSP PUSHJ P,LDGTSP POP P,A JRST LDLRSP ;GET SPACE, LOCKI, AND RESTORE PTRS SUBTTL END OF FASLOAD FILE LDBEND: TRZ TT,1 ;CROCK! CAME TT,[SIXBIT \*FASL*\] JSP D,LDFERR MOVEI TT,LDFEND MOVEM TT,LDEOFJ IFN ITS,[ SKIPLE A,LDDDTP(P) TRNN A,-1 CAIA PUSHJ P,LDPUTM ;MAYBE HAVE TO FORCE LDPUT'S BUFFER ] ;END OF IFN ITS HLLZS LDDDTP(P) ;WILL USE FOR SWITCH LATER JSP T,LDGTWD TRZ TT,1 ;COMPATIBILITY CROCK CAME TT,[SIXBIT \*FASL*\] JRST LDBEN1 HLLOS LDDDTP(P) MOVEM F,LDTEMP JRST LDFEND LDBEN1: TRZ TT,1 CAME TT,[14060301406] 10% JSP D,LDFERR 10$ JUMPN TT,LDFERR LDFEND: TLZ R,-1 ;END OF FILE CAMGE R,LDHLOC MOVE R,LDHLOC HRRZS TT,R IFE PAGING,[ MOVE C,LDPRLS(P) TLNN C,100000 JRST LDFEN2 HRRZM R,HBPORG JRST LDFEN3 LDFEN2: JSP T,FXCONS MOVEM A,VBPORG LDFEN3: ] ;END OF IFE PAGING IFN PAGING,[ JSP T,FXCONS MOVE D,(A) EXCH A,VBPORG MOVE TT,(A) SKIPL LDPRLS(P) JRST LDZPUR HLLOS NOQUIT ANDI TT,PAGMSK ANDI D,PAGMSK LSHC TT,-PAGLOG SUBI D,(TT) ROT TT,-4 ADDI TT,(TT) ROT TT,-1 TLC TT,770000 ADD TT,[450200,,PURTBL] MOVEI T,1 LDNPUR: TLNN TT,730000 TLZ TT,770000 IDPB T,TT SOJGE D,LDNPUR PUSHJ P,CZECHI LDZPUR: ] ;END OF IFN PAGING PUSH FXP,F ;SAVE POINTER TO I/O BUFFER ;FALLS THROUGH ;FALLS IN ;;; "GROVELING" OVER THE ATOMTABLE USED TO OCCUR HERE, TO GCPROTECT ;;; BY PLACEING IN THE GCPSAR ANY ATOM NOT OTHERWISE PROTECTED. BUT ;;; NOWADAYS, THEY ARE ALL PROTECTED, EITHER BY BEING POINTED TO BY ;;; SOME PROTECTED LIST STRUCTURE, OR BY THE CODE AT LDQATX. SUBTTL SMASH DOWN PURE LIST LDSDPL: SKIPL TT,LDPRLS(P) ;[SMASH DOWN PURE LIST] TLNE TT,200000 JRST LDEOMM MOVEM TT,VPURCLOBRL MOVEI F,VPURCLOBRL LDSDP1: SKIPN TT,LDPRLS(P) JRST LDEOMM SKIPN INTFLG JRST LDSDP2 SKIPE INTFLG PUSHJ P,LDTRYI LDSDP2: HRRZ T,(TT) MOVEM T,LDPRLS(P) HLRZ AR2A,(TT) PUSHJ P,LDSMSH JRST LDSDP3 HRRZ F,(F) JRST LDSDP1 LDSDP3: MOVE TT,LDPRLS(P) HRRM TT,(F) JRST LDSDP1 SUBTTL END OF FASLOAD, AND RANDOM ROUTINES ;[END OF MOBY MESS!!!] LDEOMM: POP FXP,LDTEMP ;GET POINTER TO I/O BUFFER MOVE TT,LDDDTP(P) MOVE A,LDBSAR TRNE TT,-1 JRST LDEOM1 PUSHJ P,$CLOSE ;CLOSE FILE ARRAY SETZM LDBSAR MOVE A,VBPORG IFN D10*HISEGMENT,[ MOVE TT,HBPORG MOVE T,LDPRLS(P) TLNE T,100000 JSP T,FXCONS ] ;END OF D10*HISEGMENT UNLOCKI POPI P,LDNPDS SETZM -LERSTP-1(P) ;Flag that we have completed our read JSP TT,UNWINE ;Perform our cleanup handling, etc PUSHJ P,UNBIND HRRZ TT,-3(P) ;For debugging purposes, HRRZ D,-2(P) ; make sure PDLs are okay HRRZ R,-1(P) POPI P,3+1 JRST PDLCHK LDEOM1: UNLOCKI POPI P,LDNPDS ;POP OFF REGPDL SLOTS, BUT PUSH P,A ;PUT LDBSAR BACK ON PDL JRST LDDISM LDTRYI: UNLOCKI ;[TRY AN INTERRUPT] LDLRSP: LOCKI ;[LOCKI AND RESTORE POINTERS] LDRSPT: HRRZ TT,LDASAR ;[RESTORE ARRAY POINTERS] HRRZ TT,TTSAR(TT) HRRM TT,LDAPTR HRRZ TT,LDBSAR IFE D10,[ HRRZ TT,TTSAR(TT) HRRM TT,LDBPTR ] ;END IFE QIO*D10 .ELSE HLLZS LDBPTR POPJ P, LDLIST: MOVEI C,-1(P) .SEE LDOWL JRST LDLIS1 LDLIS0: JSP T,LDGTWD LDLIS1: LDB T,[410300,,TT] ;[CONSTRUCT LIST] JRST LDLTBL(T) LDLTBL: JRST LDLATM ;ATOM JRST LDLLST ;LIST JRST LDLDLS ;DOTTED LIST JRST LDOWL ;EVALUATE TOP FROB ON STACK IFN HNKLOG, JRST LDLHNK ;HUNK .ELSE JRST FASHNE REPEAT 2, .VALUE JRST LDLEND ;END OF LIST LDLATM: MOVE A,@LDAPTR ;FOR ATOM, MAYBE SET USAGE BIT, TLNN A,777011 ; THEN SHOVE ON STACK IOR A,D MOVEM A,@LDAPTR PUSH P,A TRNN A,-1 JRST LDLIS0 ;SKIP SY2 CHECK IF SYMBOL 'NIL' TLNN A,777006 ;IF HAS VALUE CELL, OR IS NUMBER, DON'T DO SY2 TLNN D,1 ;IF SETTING USAGE BIT THEN ALSO DO SO IN SY2 JRST LDLIS0 HLRZ T,(A) ;GET SY2 WORD HLL T,(T) TLO T,SY.CCN\SY.OTC ;MUST FLAG ATOM AS NEEDED TLNN T,SY.PUR ;SET MEMORY UNLESS PURIFIED HLLM T,(T) JRST LDLIS0 LDLLST: TDZA A,A ;FOR LIST, USE NIL AS END LDLDLS: POP P,A ;FOR DOTTED LIST, USE TOP ITEM HRRZS TT JUMPE TT,LDLLS3 LDLLS1: POP P,B ;NOW POP N THINGS AND CONS THEM UP PUSHJ P,XCONS SOJG TT,LDLLS1 LDLLS3: PUSH P,A SKIPE INTFLG PUSHJ P,LDTRYI JRST LDLIS0 LDOWL: MOVE A,(P) MOVEI B,(C) ;B HAS ADDR OF FASLOAD TEMPS ON STACK PUSH P,C PUSHJ P,LDEV0 POP P,C MOVEM A,(P) JRST LDLIS0 IFN HNKLOG,[ LDLHNK: ANDI TT,-1 ;FLUSH LH CONTROL BITS PUSH FXP,D PUSHJ FXP,ALHNKL ;(TT) HAS NUMBER OF ITEMS WANTED POP FXP,D PUSH P,A ; POP THEM OFF PDL INTO A HUNK JRST LDLIS0 ;SAVES C ] ;END OF IFN HNKLOG LDLEND: HLRZ D,TT TRC D,777776 TRNE D,777776 JSP D,LDFERR POP P,A MOVSS TT HRRI TT,(A) POPJ P, ;;; SECOND FILE NAME OF THIS LISP WHEN ASSEMBLED (VERSION NUMBER ;;; THIS LOCATION IS REFERENCED BY FASLAP WHEN CREATING A BINARY ;;; FILE. IT CONTAINS THE VALUE OF .FNAM2 PLUS EXTRA BITS ;;; TO DISTINGUISH SOME CONDITIONAL ASSEMBLY FLAGS. ;;; THE CONTENTS OF THIS LOCATION ARE PRIMARILY USED TO DETERMINE ;;; WHETHER FASLOAD MAY USE VALUES OF DDT SYMBOLS SUPPLIED BY ;;; FASLAP; IT DOES SO ONLY IF FASLAP'S VERSION NUMBER, AS ;;; DETERMINED BY THIS LOCATION, IS THE SAME AS FASLOAD'S. ZZ==-1 ZZZ==0 ;;; 2nd item used to be "ML", but it really meant "ITS" ;;; 3rd item used to be "BIBOP", but is now for D20 IRP X,,[D10,ITS,D20,BIGNUM,CMU,SAIL,HISEGMENT,PAGING] ZZ==ZZ_1 ZZZ==\X TERMIN LDFNM2: <.FNAM2&ZZ>\ZZZ EXPUNGE ZZ ZZZ IFN ITS,[ LDGTW0: SUB F,FB.BFL(TT) HRLZI F,(F) HRRI F,FB.BUF LDGTWD: MOVE TT,@LDBPTR AOBJN F,(T) LDGTW1: HRRZ TT,LDBSAR HRRZ TT,TTSAR(TT) PUSH FXP,FB.IBP(TT) MOVE F,FB.BFL(TT) SUBI F,1 .CALL LDGTW9 .LOSE 1400 POPI FXP,1 ADDI F,1 CAME F,FB.BFL(TT) SOJA F,LDGTW0 JSP D,@LDEOFJ LDGTW9: SETZ SIXBIT \SIOT\ ;"STRING" I/O TRANSFER ,,F.CHAN(TT) ;CHANNEL # ,,0(FXP) ;BYTE POINTER 400000,,F ;BYTE COUNT ];END IFN ITS IFN D20,[ LDGTW0: SUB F,FB.BFL(TT) ;MAKE F INTO AOBJN POINTER HRLZI F,(F) HRRI F,FB.BUF ;POINTING INTO THE BUFFER LDGTWD: AOBJP F,LDGTW1 SUBI F,1 ;READJUST TO ACCESS CORRECT WORD MOVE TT,@LDBPTR AOJA F,(T) ;FIXUP AOBJN POINTER THEN RETURN LDGTW1: HRRZ TT,LDBSAR HRRZ TT,TTSAR(TT) PUSHJ FXP,SAV3 ;SAVE ACS WHICH WILL BE DESTROYED HRRZ 1,F.JFN(TT) ;JFN INTO AC 1 MOVE 2,FB.IBP(TT) ;BYTE POINTER INTO AC 2 MOVN 3,FB.BFL(TT) ;READ THIS MANY BYTES SIN ;DO THE INPUT ERJMP LDGTWE ;WE CAN IGNORE ERROR IF IT IS EOF LDGTE1: MOVN F,3 ;GET POSITIVE NUMBER OF BYTES LEFT UNREAD PUSHJ FXP,RST3 ;RESTORE SAVED ACS CAME F,FB.BFL(TT) ;DID WE READ ANYTHING? SOJA F,LDGTW0 ;YES, SO EMPTY THE BUFFER BEFORE GIVING EOF JSP D,@LDEOFJ ;;; ON TENEX, GETER CLOBBERS ACS 4 THROUGH 10! ARGGH... LDGTWE: PUSHJ FXP,SAV5M3 ;SAVE ALL ACS CLOBBERED BY GETER JSYS PUSHJ P,SAVX5 MOVEI 1,.FHSLF ;GET OUR LAST ERROR GETER PUSHJ P,RSTX5 PUSHJ FXP,RST5M3 ;AND RESTORE ACS HRRZS 2 ;ONLY WANT ERROR CODE CAIN 2,IOX4 ;EOF? JRST LDGTE1 MOVEI 1,.PRIOU ;OUTPUT ERROR TO PRIMARY OUTPUT CHANNEL HRLOI 2,.FHSLF ;LAST ERROR FOR OUR PROCESS SETZ 3, ;NO LIMIT TO AMOUNT OF OUTPUT ERSTR .LOSE ;FAILED .LOSE ;FAILED PUSHJ FXP,RST3 ;RESTORE SAVED AC'S JSP D,@LDEOFJ ;MAKE BELIEVE WE HIT EOF ] ;END IFN D20 IFN D10,[ LDGTW0: POP P,AR1 POP P,T MOVE TT,FB.HED(TT) ;GET BUFFER HEADER ADDRESS MOVN F,2(TT) ;NUMBER OF WORDS IN BUFFER HRLZI F,-1(F) ADDI F,1 ;NOW THE ACTUAL FIRST WORD LDGTWD: MOVE TT,LDBSAR ;GET POINTER TO SAR HRRZ TT,TTSAR(TT) MOVE TT,FB.HED(TT) ;GET PTR TO BUFFER HEADER HRRZ TT,1(TT) ;GET PTR TO FIRST WORD OF BUFFER - 1 HRLI TT,F ;INDEXED OFF OF F MOVE TT,@TT AOBJN F,(T) LDGTW1: PUSH P,T PUSH P,AR1 MOVE AR1,LDBSAR MOVE TT,TTSAR(AR1) ;WAIT! YOU LOSER, TT MUST HAVE TTSAR IN IT MOVE T,F.CHAN(TT) LSH T,27 IFE SAIL,[ TLNN TT,TTS.BM JRST LDGTW6 ;$DEV5R PUSH FLP,F HRRZ T,FB.HED(TT) ;MAYBE BUFFER HAS BEEN RELOCATED? THEN FOR MOVSI F,(BF.IOU) ANDCAB F,@(T) ;TURNS OFF BUFFER-IN-USE BIT AND ADVANCES BUFFER SKIPGE (F) ;BF.IOU MUST BE BIT 4.9 FOR THIS TO WORK JRST LDGTW4 ;$DEV5S MOVSI T,TTS.BM ANDCAM T,TTSAR(AR1) ;TURN OFF "BUFFER-MOVED" BIT, BUT LEAVE BUF ADDR IN F MOVE T,F.CHAN(TT) ;$DEV5Q: LSH T,27 HRR T,F POP FLP,F ] ;END OF IFE SAIL LDGTW6: TLO T,(IN 0,) ;$DEV5R: XCT T ;READ A NEW BUFFERFUL JRST LDGTW0 ;$DEV5M (?) ;SUCCESS! POP P,AR1 POP P,T JSP D,@LDEOFJ IFE SAIL,[ LDGTW4: HRRZ T,FB.HED(TT) HRRZM F,(T) ;STORE CURRENT BUFFER ADDR IN CONTROL BLOCK TLZ F,-1 ADD F,[4400,,1] MOVEM F,1(T) ;CONSTRUCT NEW BP FOR BUFFER MOVE F,(F) MOVEM F,2(T) ;STORE NEW BYTE COUNT INITO BUFFERCONTROL-BLOCK POP FLP,F JRST LDGTW0 ] ;END OF IFE SAIL ] ;END OF IFN D10 PGTOP FSL,[FASLOAD]