.bl 10 .ce 4 PDP-11 L110 System Description Forrest Howard 5/28/75 .bp .fo ''-%-' .nf Core Allocation D-Space Systems !-------------------------------! ! .psect startc ! !-------------------------------! ! .psect nil ! !-------------------------------! ! .psect shbydat ! !-------------------------------! ! .psect shrwddat ! !-------------------------------! ! .psect shrcode ! !-------------------------------! ! .psect dsubr ! !-------------------------------! ^sharable^ ---------- !private ! v v !-------------------------------! ! .psect uswdda ! !-------------------------------! ! .psect usportd ! !-------------------------------! ! .psect usbyda ! !-------------------------------! ! ! ! ! !-------------------------------! x00000000 boundary ! .psect ddtpr ! 2 !-------------------------------! ! .psect datom ! !-------------------------------! x00000000 boundary ! .psect initcode ! 2 !-------------------------------! ! .psect errorm ! !-------------------------------! runtime core allocation space !-------------------------------! ! control stack ^ ! !-------------------------------! ! name stack ! ! ! v ! !-------------------------------! ! job data region ! !-------------------------------! smallints also occupy the last 1280. bytes with the stacks. .bp i&d space i space !-------------------------------! ! .psect startc ! !-------------------------------! ! .psect shrcode ! ! ! ! ! !-------------------------------! ! .psect initcode ! !-------------------------------! d space !-------------------------------! ! .psect nil ! !-------------------------------! ! data ! ! ! !-------------------------------! x00000000 boundary ! .psect dsubr ! 2 ! ! 2 !-------------------------------! ! .psect ddtpr ! !-------------------------------! ! .psect datom ! !-------------------------------! x00000000 boundary ! .psect errorm ! 2 !-------------------------------! !-------------------------------! ! ! ! ! ! ! ! stacks ! ! ! ! ! !-------------------------------! note all the data is non-sharable smallints occupy the highest 1280. locations .bp .fi .ti +5 One Page is 400 Octal Bytes. .bl .ti +5 As more core is needed by L110 for port buffers, or pages for atoms , ints, or dtprs, the routine GLOBALLOC searches out core for blank pages (such as those returned from ports when closed) and requests more core from UNIX as needed. .bl .ti +5 The monitor automatically keeps track of the control stack and allocates more core to it as needed. .bl .ti +5 The data region expands upwards (i.e. from 0 to 177776) in 400 Octal chunks. .bl .ti +5 The control stack expands down (towards 0). .bl .ti +5 One should note that the psects "initcode" and "errorm" go away. Errorm has the text for the error message file; this file is written out when a "pure" lisp (one that has not had a SAVEME done on it) is called with more than one arguement (that is with more than just its name as arg). The algorithim for this writing is to do a creat on the errorfil path name; if this succeds, then write the entire psect into it, and then close it. Obviously, this requires write permission on the errorfile. .bl .ti +5 The initcode section is thrown away in data-space only lisp by being overwritten by data that is added. In i&d lisp, it is eliminated from the file by the SAVEME function. .bp .ce 1 Data Objects .bl INTEGERS--2 16 bit words as follow: .nf foo: --------------------------------------- ! !garbage collect bit ! ! low 16 bits ! --------------------------------------- .fi The instruction ASL x is used to clear the GC bit when forming an INTEGER; V bit will be set if the number cannot be represented. .bl .ti +5 The instruction ASR x will get the original number back; the sign bit is retained. As an assembly switch Small Integers can also be selected. These have an address above -1280. Note that the address determines the value, not the contents. For this reason, all integer manipulation should be done thruogh the "useful numeric macros" (see below). .bl 2 DOTTED PAIRS--2 16 bit words. .bl .nf foo: ----------------------- ! car ! gc bit ! ! cdr ! ----------------------- .fi Note that all addresses in L110 are even, so that the 0 bit of the car is never set, save by the garbage collector. The 0 bit of the cdr is always 0. .bl .ti +5 Dotted Pairs always start on 0 or 4 byte boundaries. .bl 2 ATOMS--length 3+<+1>/2 16 bit words .bl .nf foo: ----------------------- ! plist!gc bit ! ! tlb ! ! function ! ! 'a 'n ! ! 'e 'm ! ! 0 's ! ----------------------- .fi Plist is similar to car of dtpr. .bl Tlb is similar to cdr of dtpr. .bp Binary#Code .bl .ti +5 (For D Space) .bl The Length of Binary Code is Dependent on t;he number of instructions in it. .bl .ti +5 If Type is 0 if Lambda and 1 if Nlambda then: .bl .nf foo: ----------------------------------------------- ! Type*100000+Args*1000+ !gc ! ! anil ! ! jsr pc,chas(chanl) ! ! ! ! ! ! ! fooend: ! last word of code ! ----------------------------------------------- (For I&D Space) .bl Length is always 3 16 bit words: foo: ----------------------------------------------- ! type*100000+args*1000+!gc ! ! anil ! ! pointer to instruction space ! ----------------------------------------------- .fi Note that the Binary Code object is always in data space, although it may point to instruction space. .bp Ports--5 16 bit words .nf --------------------------------------- input: ! savedc ! fdsn*2!gc ! ! ptr to next char ! ! ptr to buffer start ! ! chars left ! ! length ! --------------------------------------- --------------------------------------- output: ! count ! 200!fdsn*2!gcbit ! ! ptr to next char ! ! ptr to buffer start ! ! chars left ! ! length ! --------------------------------------- .fi Where count in output buffer is number of characters since last Terpr. .bl Savedc in input buffer is the character saved by savec. .bp Free list formats .nf !------! !-----! !-----! fnumber:-------->! ! +-->! ! ... -->! nil ! ! ---+-----^ ! --+----^ ! ! !------! !-----! !-----! !------! !-----! !-----! fdtpr:---------->! ! +-->! ! ... -->! nil ! ! ---+-----^ ! --+----^ ! ! !------! !-----! !-----! !-------! !-------! !-------! fratom:-------->! ---+----> ! ---+---> .... ! anil ! !length ! !length ! !length ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !-------! !-------! ! ! ! ! !-------! !------! !-----! !-----! fbcd:----------->!size ! +-->!size ! ... -->!size ! ! ---+-----^ ! --+----^ ! nil ! ! ! !-----! !-----! !------! For i&d space, bcd free size is ignored as it is all 3 words. .bl All lengths are in words. .bp .fi Telling what things are .bl .ti +5 Each data object has a type code: .nf 0 int 1 dtpr 2 atom 3 bcd 4 port In addition, there are several other types: -1 system code (not used) -2 i-o buffer -3 free page owned by us -4 stack space -5 owned by monitor .fi There is a code associated with each 400 Octal byte page of which there are 400 Octal). .bl This type information is kept in the QMAP, which is 400 bytes long. To get the type of the address 1000 in register j1, for example, then .bl .nf Ldtype #1000,j1 .bl expands as: .bl mov #1000,j1 clrb j1 swab j1 movb qmap(j1),j1 .bl .fi Note that due to the index, the second arguement to ldtype must be a register. .bl .ti +5 If the object whose type we wish to know is already in a register, and we want to clobber the very same register with the type code, then .bl .nf Ldtype Rx .fi .bl will do the trick. .bp Stacks: .bl Stack pointers .bl SP=%6 is the control stack pointer. .bl NP=%5 is the name stack pointer. .bl LTOP (a core location) points to top of name stack before current function call. .bl CONVENTIONS Namestack entrys are 4 byte entrys that are pairs. NP points to the last form pushed on. NP-2 points to the last atom pushed on. NPLIM is highest possible location to be used by namestack. Name stack grows upwards. .bl Control stack entrys are of several types. The first is a standard even address, i.e. return addresses, nstack addresses, etc. These are ignored during garbage collection. The second type of entrys are odd addresses. Odd address imply that the address&177776 is to be protected during garbage collection. The user is cautioned not to push spurious odd addresses on the stack. The third entry type is a Function Block: .bl .nf sp-> ! eexit ! ! function ! ! old ltop ! ! form ! ! caller ! .fi The form and Function are protected. The fourth type of object is a "saved register" block generated by break: .bl .nf sp-> ! bksnag ! ! np ! ! ltop ! ! j3 ! ! j2 ! ! j1 ! ! b ! ! return ! .fi None of these objects are garbage collected. .bl other snags recognized have to do with register saving, specifically, the r4rres, r3rres, r2rres, and r1rres snags. their format is .bp .nf sp-> ! rnrres ! ! register ! ...... ! ! ! return address ! .bl .fi where there are n registers in between the snag and address. The instalation of register saves blocks on the stack must be done carefully, least the user find himself with an illegal object on top of the stack. Simarily, in order to take the registers off, care must be exercised. .bl .ti +5 The prototype for using register snags is: .bl .nf foo: save3 ;save three registers ... ... end: saveret ;which is a mov (sp),pc ;which will flush regs + return to my caller .bl .fi .bp Debugging note .bl .ti +5 As implied earlier, each page for data objects must begin on a 400 byte boundary. When L110 is linked with DDT for debugging, it is likely that the begining of the first page will not be on a 400 byte boundary. Therefor the file filler.m11 is used to pad out the data so that the first atom (atmnil ) is in the correct place. .bp .ul 1 Use of Saveme .bl The saveme command writes out the current lisp data enviroment to a file in an executable format. This is usefull to produce a copy of Lisp that is already initilized, has the non-primatives loaded, etc. .bl .ti +5 The function of saveme for data-space only systems is simple;make a file header, write out the text, and write out the data. For I&D space systems, life is a little harder. There are two flavors of output; one for Harvard I&D, the other for Bell I&D. Saveme has to know the difference. .bl .ti +5 Secondly, saveme cannot directly write out instruction space. Rather, it opens itself for reading. The pathname that it uses is defined in the dstuf.m11 file. It then uses the data-space information and the file to build an executable file, minus the instruction space code for initilization and for saveme itself. .bl .ti +5 A reset is then executed. .bl .ti +5 Previous to the saveme, and implicit resetio is preformed. .bp .ce 1 Major System Modules .bl .nf 1) Conversion a String to Number Name: strnum Args: String in strbuf, null terminated. Return: a/ptr to Int b/NIL b Number to String Name: numstr Arg: a/ptr to int Return: a/NIL b/Pointer to string, null terminated. c String to Atom Name: Strat Args: String in strbuf b/length of strin in words j2/hash index Return: a/pointer to atom b/garbage 2) iO all iO routines take a port on top of the name stack NIL is the port for the tty. a Get a Character Name: xgetc call: getc (macro expanding to call xgetc) Return: next char of port in char. b Save a Character Name: xsavec Call: savec (macro expanding to call xcavec) Arg: char in CHAR Return: nothing c Output a String Name: putstr Arg: ptr to asciz string in B Return: Nil in b d Read an Atom Name: Ratomr Args: none Return: a/pointer to form clobbers all registers!!!! e Print Number, Atom, Port, Bcd Names: numout,atmout,portout,bcdout Arg: a/ptr to object Return: a,b NIL 3) Form I/O Read a Form Name: Reader Arg: Port on top of nstk Return: a/ptr to form b,j1-j3 clobbered b Print a Form Name: printr Arg: a/ptr to form port on top of np Return: a,b NIL 4) Integer Handlers a Numga---Macro Arg: a/ptr to INT leaves: High 16 bits in A Low 16 bits in B b Numgj1 same as above except leaves result in j1,j2 c Numga0--Macro Arg: a/ptr to int leaves floating representation of int in AC0 d Numga1 same as above except leaves result in ac1 e Nmstore--Macro Arg: a/high 16 bits of int b/low 16 bits of int Result: a/ptr to int b/NIL f Nmstac0--Macro Arg: AC0 has floating representation of int Result: a/ptr to int 5) Atom Handlers a Get Atom Name Gatom Arg a/number of words needed for string Result: a/pointer to atom with NILs in bindings 6) Dtpr Handlers a CONSA--Macro calling Name: xconsa Args: a/car b/cdr Return: a/pointer to dtpr CONSB--Macro calling Name: xconsb Args: a/car b/cdr Return: b/pointer to dtpr CONSBNIL--Macro calling Name: xconsbn Args: a/car Return: b/pointer to dtpr with NIL as cdr. Consa, consb, and consbnil all protect a and b from garbage collection d Allocate Dtpr Name: gdtpr Arg: none Return: a/ptr to dtpr .bp Useful Macros register save save1 -- puts j3 in register snag on stack save2 -- puts j2+j2 in stack block save3 -- j1,j2,j3 save4 -- b,j1,j2,j3 saveret --Returns from register save push x puts x onto control stack pop x puts top entry of stack into x npush x pushs onto stack npop x pops top entry(form) of stack into x propush x pushs x onto control stack and marks it for garbage collection unpropop x undoes propush and puts result in x call x jsr pc,x ret rts pc car x,y puts car of what x points to into y cdr x,y puts cdr of what x points to into y jmpifinil x,y,flag generates code to test x=nil and branch to y if true. flag is for nilas0#0, when previous operation mov manipulated x so that condition codes were set jmpiftrue x,y generates code to test x=true and branch to y if so. getca calls getc, moves char to a loadnil x loads nil into x retnil rettrue ldtype y or ldtype x,y loads the type of the first arg into y. y must be a register cmptype x,y,z using y as scratch generate code to compare the type of the first arguement to z. generm All sorts of perversions are preformed to get the string into errorm psect, from which it will be written to the errorfile. Most importantly, psect changes are made; beware therefore for local symbols. The psect eventually returned to is the psect of the last ".rsect" (see below). A template for using this is: noway: generm //> mov #tmp-<^pl errorm>,a call geterr ;reads the error message file call putstr ;return with b pointing ;to string or asciz ;string of digits (if ;file not available) error error ,where code is generated to call the error package, and return to to "where" when continue is evaled (or to cantcont if blank). rsect sectname This is esentally a psect directive, except that it assigns a number corresponding to the "sectname" to a variable that it keeps. This allows things like generm to leave the cur- rent psect, screw around, and then return the user to the place that he was in. dispatch generates call to routine which returns: dispatch jmp 1$ ;if a is int jmp 2$ ;if a is dtpr jmp 3$ ;if a is atom jmp 4$ ;if a is bcd jmp 5$ ;if a is port the 5 instructions following dispatch must be of the two word variety outstr x generates code to print the string at label x to port on top of np Note! The following macros will work only(!) if the ctable constants are not redefined!!! isalph x,y generates code to branch to y if the contents of x(a register) is alphabetic (more or less) isnum x,y generates code ... is -,0,1...9 issep x,y generates code ... is space, tab, cr, lf, ... isbrk x,y generates code if seperator or (, ), ., [, or ]. isalnum x,y same as isalph x,y isnum x,y .bp Control Flow --------------- ------------- ------------- ! ! ! ! ! ! ! print ! ! lisp ! ! read ! ! ! ! ! ! ! --------------- ------------- ------------- ^ ! ^ v ------------- ! ! ! eval ! ! ! ------------- ^ ! ! v ------------- ! ! ! subrs ! ! ! ------------- ------- ------- ------- ------ ! alloc ! ! alloc ! ! alloc ! !alloc ! ! atom ! ! dtpr ! ! int ! !buffer! ------- ------- ------- ------ ! ! ! ! ! ! ! ! ! v v ! ! ----------------------- ! ! ! garbage collection ! ! ! ! ! ! ! ----------------------- ! ! ! ! v v v --------------- v v ! global !<-------------------------------- ! allocate ! --------------- ! v --------------- !monitor ! ! ! ---------------- .bp ------- ----------------! print !-------------------- ! ! ------- ! ! ! ! ! ! ! ! v v v v ! --------- --------- -------- -------- ! ! numout ! ! atmout ! !bcdout ! !portout! ! --------- --------- -------- -------- ! ! ! ! ! ! v ! ! ! ! -------- ! ! ! ! ! numstr ! ! ! ! ! -------- ! ! ! ! ! ! ! ! ! v v ------ v v v ---------------!putstr!--------------------- ------ ------ ! read ! ------ ! v ----- ---------- ------ !getc! <---------!ratomr !------------>!savec! ----- ---------- ------ ! ! v v ------ -------- ! find ! ! strnum ! ------ -------- ! ! v v ----- ------- !strat! !nmstore! ----- ------- ! ! v v ----- ----- !gatom! !gdtpr! ----- -----