PROPOSED FUNCTIONAL SPECIFICATION FOR HARDWARE / SOFTWARE INTERFACE ON TAMARIN LISP PROCESSOR October 1, 1986 Copyright (c) 1986, 1987 Xerox Corporation All Rights Reserved Xerox Internal use Only This document describes internal data structures and opcode specifications used in the Tamarin hardware and low-level software. Its primary purpose is to give the system software engineers the necessary information required to understand and to begin programming the processor. This is being circulated for comments. A final version will be generated on Oct 7 as the Tamarin hardware schedule commitment requires. Please send all comments in writing to Alan Bell and Bob Krivacic. Your comments will be incorporated to form the final version. TAMARIN ARCHITECTURE The Tamarin chip is a CMOS VLSI processor with specialized opcodes to run LISP efficiently. Some of the features which make this chip suitable to run Lisp are: tag bits, parallel type checking, parallel operand fetching, parallel stack manipulation, internal register & stack cache, binding stack operations, garbage collection primitives, and CDR coding. The combination of these features make it possible to implement most Lisp opcodes with one microinstruction, which gives the Tamarin chip a competative edge in speed and flexability. INTERNAL REGISTER CACHE The Tamarin chip contains eight internal register caches which are used to hold the equivalent of a function activation. Each register cache (or stack frame) contains the function parameters, local variables, special registers (such as stack pointer, program counter, flags, and other special pointers), and the current computational stack. Since these registers are contained in the processor, memory accesses are not required to perform many of the simple variable access & stack instructions. When the function depth exceeds the capacity of the internal frame cache, the processor pushes out the oldest frame into main memory at a high band width, to free up the frame for the new function call. The frame is not read back into the processor until being returned to, thus reducing the possibility of thrashing stack frames. The Tamarin also contains an extra frame which is called the global frame. These registers contain special global values used by the processor, along with a few global registers which are available to the Lisp system for storage of extremely critical variables. TAGGED ARCHITECTURE The Tamarin chip uses a tagged architecture, so that the type of any piece of datum is known. There are up to 8 bits of type information per word, which are broken up into 3 fields: tag bits, subtype bits, and flag bits. The tag bits indicate the four major types the datum is: pointer, integer, floating point, or immediate. Pointer and immediate datum is further broken down by the subtype bits, which indicate the type of a the object being referenced. The flag bits are special flags available with the subtype to mark special cases of a subtype. WORD FORMAT The Tamarin word size is 40 bits, with the following fields defined: 39 31 23 15 7 0 *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | GC |CDR|TAG|SUBTYPE|F|R| Rest of Word | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* With the following meanings for each field: TAG - Tag bits. 00: 32 bit 2's complement immediate integer type. 01: 32 bit IEEE standard floating point immediates. 10: Pointer. Indicates that the subtype & flag type bits are valid. 11: 26 bit Immediate type. The subtype & flag type bits are valid. SUBTYPE - Subtype bits. These bits are valid only when the tag bits are set to a pointer or immediate. This field indicates the type of the object being pointed to, or the type of the immediate datum for immediate items. F - Flag bit. This bit is only valid when the subtype field is valid. It is used to indicate special conditions based on the subtype bits. One example of the use of this bit is in stack frame pointers. The flag bit is used to indicate the end of the stack frame. R - Reference Count bit. This bit is only valid when the tag is a pointer. This bit is used in all storage memory operations to indicate when a pointer should be reference counted. GC - Garbage Collection Information. These bits contain the garbage collection reference count information. CDR - CDR Coding. These bits contain the CDR coding information for List cells. The full breakdown fo the different word formats is as follows: INTEGERS / INT 39 31 23 15 7 0 *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |0 0| 32 bit 2's Compliment Integer | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* Integers are implemented as 32 bit 2's compliment integers. The integer values are immediate in the datum item so that there is no need to "box" large integers (although larger integers such as Bignums must still be boxed). FLOATING POINT / FLT 39 31 23 15 7 0 *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |0 1| 32 bit IEEE Floating Point | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* Thirty two bit Floating point numbers are directly representable with immediate values in the Tamarin word. These are standard IEEE formats, with floating point operations being performed by an external floating point chip. POINTERS / PTR 39 31 23 15 7 0 *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |1 0|SUBTYPE|F|R| 26 bit Word Pointer | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* Pointers are used for all non-immediate type of data objects. They consist of a 26 bit word pointer which points to the object, a subtype field which indicates the general type of the object being pointed to, a flag bit which indicates further information about the subtype, and a reference count bit which indicates when objects are not reference counted. IMMEDIATES / IMM 39 31 23 15 7 0 *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |1 1|SUBTYPE|F|R| 26 bit Immediate Field | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* Immediate fields have a similar format to that of pointer objects except that the word contains the actual data instead of a pointer to the data. Special data objects (such as characters) are stored in this immediate format. SUBTYPE & FLAG BIT ASSIGNMENTS These are the current assignments for the subtype field of pointers: 0000: BlockP Untyped pointer to a block of storage. 0001: ShortConsP A pointer to a Short CONS cell. 01xx: CLObjectP A Common Loops Object. 1xxx: DefStructP A pointer to an object which is created by defstruct & the 1st word is an object header. 1001: LongConsP A pointer to a Long CONS cell. 1010: CCodeP Pointer to a CCodeP. 1011: SymbolP Pointer to an SymbolP object. 1100: FrameP Pointer to a Stack Frame object. 1101: NumberP Pointer to a number object. Used in EQL test. These are the current assignments for the subtype field of immediates: 0001: ObjectheaderP The PTR field contains the type index of the object. 0010: UnboundP Special constant unbound. 0011: CharacterP Character constant. The flag bit further describes the subtype field of a pointer or immediate. It is placed into the word to speed up access on certain operations. It is assumed that this bit can ALWAYS be reconstructed by following the pointer in all cases. This bit is mutually exclusive, so that the subtype bits are always a necessary part of a test for this bit. FrameRefill If Subtype = FrameP, indicates the need to allocate more stack frames in memory. The Reference Count bit is used to indicate that the object pointed to is reference countable. A 1 in this bit indicates that all memory storage operations should perform reference count operations. DEFSTRUCT DATA OBJECTS These are objects which are created defstruct to define datatypes. This object format consists of a header word which contains the type index of the object, followed by the object. Thus the format is: 39 31 23 15 7 0 *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | GC | |IMM|ObjHdrP|F|R| GC-Overflow | Type Index | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |INT| Optional Object Size | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | Object Data | | . . . | | . . . | | . . . | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* ObjHdrP Type bits indicating that the object is an object header. Type Index This is an index which describes the type of the object. GC-Overflow This field is reserved to handle extra information for garbage collection purposes. It is used solely by by software and UFN routines. TYPE INDEX This field is used to indicate the type of an object by being used as an index into the a type table. From the type table, a pointer to the type information can be found. DATATYPE DESCRIPTOR TABLE The type of an item is found be looking up its type in the type table. The size of the type table can grow to a maximum of 64K entries (using a 16 bit type index in object headers) with the only stipulation that the table be located contiguously in its virtual address space. Entries in the table will be one word pointers which point to the type information. The first 256 entries will be broken into four areas of 64 entries each, one for each of the major tag types. Thus to find the type of an item, the major tag, subtype, & flag bits are used as an 8 bit index into the type table. If a valid pointer exists at the indexed location, then it will point to the type of the item. Thus the type descriptors for immediates such as integers, floats, & typed constants can be found. When there is not a valid type pointer found from the 1st indexing operation, then the item must be a pointer to an object, in which case the object header is found to get the true type index. Thus the type table will look something like this: 39 31 23 15 7 0 Integers *=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=* 0: | |PTR| TypeP |F|R| Ptr to Type Info for Int | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR| TypeP |F|R| Ptr to Type Info for Int | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | . . . | | . . . | | . . . | | . . . | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR| TypeP |F|R| Ptr to Type Info for Int | *=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=* Floats *=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=* 64: | |PTR| TypeP |F|R| Ptr to Type Info for Float | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR| TypeP |F|R| Ptr to Type Info for Float | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | . . . | | . . . | | . . . | | . . . | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR| TypeP |F|R| Ptr to Type Info for Float | *=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=* Pointers *=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=* 128: | |PTR| TypeP |F|R| Ptr to Type Info for Untyped Block | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR| TypeP |F|R| Ptr to Type Info for Short Cons | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR| TypeP |F|R| Ptr to Type Info for Common Loops Object | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | . . . | | . . . | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR|SymbolP|F|R| NIL (Long Cons has type index in header) | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR|SymbolP|F|R| NIL (DefStructP has type index in header) | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR|SymbolP|F|R| NIL (CCodeP has type index in header) | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR|SymbolP|F|R| NIL (SymbolP has type index in header) | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | . . . | | . . . | | . . . | | . . . | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR|SymbolP|F|R| NIL | *=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=* Immediates *=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=* 192: | |PTR|SymbolP|F|R| NIL | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR| TypeP |F|R| Ptr to Type Info for ObjectHeaderP | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR| TypeP |F|R| Ptr to Type Info for UnboundP | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR| TypeP |F|R| Ptr to Type Info for CharacterP | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | . . . | | . . . | | . . . | | . . . | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR|SymbolP|F|R| NIL | *=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=* Declared Types *=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=* 256: | |PTR| TypeP |F|R| Ptr to Type Info | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR| TypeP |F|R| Ptr to Type Info | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR| TypeP |F|R| Ptr to Type Info | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | . . . | | . . . | | . . . | | . . . | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR| TypeP |F|R| Ptr to Type Info | *=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=* NOTE: There are actually 4 entries per subtype in the 1st 256 locations, since the two least significant bits represent special cases of the subtype. Only 1 entry per subtype is show above. The 1st 256 locations should be locked down since they will be referenced by all type opcodes. SHORT CONS CELLS Cons cells are stored in a special consing data area. The first word is the CAR and CDR is found via the CDR code: 39 31 23 15 7 0 *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | GC |CDR|TAG| CAR | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* The CDR code is as follows: 00 - CDR is NIL 01 - CDR is Prev Cell 10 - CDR is Next Cell 11 - CDR indirect (Pointer to a 3 word CONS cell) SYMBOLS To provide a large symbol space, all symbols are referenced by 3 bytes in the code stream. This will provide additional symbol space over the 64k atom limit in the current D-machine implementation. Symbols will be implemented as a standard object, with a special subtype associated with this kind of object. Some advantages of this method are that symbols can be alocated as needed using the normal system routines for handling objects, more entries can easily be added for symbols, symbol definitions might be "inspectable" (in the sense that all typed objects can be inspected), and the possiblity of garbage collecting them exists. The basic format for a symbol under this method would be: 39 31 23 15 7 0 *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | GC | |IMM|ObjHdrP|F|R| Type Index = Symbol | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | Value Cell | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | Function Cell | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | Property List | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | Pname Ptr | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | Package Ptr | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* Value Cell The current value of the atom if defined, else Unboundp. Function Cell A CCodeP pointer or Pointer to Expr if the function has a definition, else NIL. PropertyList A ListP if the atom has a property list, else NIL. Pname Ptr Pointer to the print name of the atom. Package Ptr Pointer to the package this symbol is defined in. STACK STRUCTURE Stack Frames (dumped in memory) are also represented by a standard object with the type index indicating that the object is a stack frame. The internal foramt of a stack frame is similar to the memory image except the first 4 words are not present. This object must be quadword alligned so that the tamarin hardware can swap the frames with quad word fetch & stores. Note that the tamarin hardware starts the swapping at the 4th word of the object. The n+16th quadword is the one which is initialized from the function header. The format is: 39 31 23 15 7 0 *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* 0: | GC | |IMM|ObjHdrP|F|R| Type Index = Stack Frame | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | . . . | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | . . . | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR| FrameP|F|R| Next Free Frame Ptr | *=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=* Start of Internal Stack Frame Layout *=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=* n: | VAR 0 | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | . . . | | . . . | | . . . | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | VAR 7 | *=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=* n+8: | VAR 8 | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | . . . | | . . . | | . . . | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | VAR 15 | *=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=* n+16: | |INT|R|E| | | | | | SP | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |INT| PC | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR| CCodeP|F|R| NAMETABLE | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR| CCodeP|F|R| Function Header | *=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=* | |PTR| FrameP|F|R| CLINK | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* n+21: | VAR 21 / STACK | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | . . . . . . . | | . . . . . . . | | . . . . . . . | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* n+63: | VAR 63 / STACK | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* Next Free Frame This field is used to chain the free memory stack frames. Memory frames are allocated from this list when a stack frame must be dumped out to memory. This field remains linked to the free list, even when the frame is used to save active stack frames, so that when a frame is read back into the processor, the memory stack frame is already linked into the free list. Free frames are allocated by following the CLINK of the last frame currently in the processor and using the next free frame as the location to place the next memory frame. Flags - Special Flags R: Trap on Return to,this frame, (reference count # 0). E: Trap on Exit from this frame. SP The Stack Pointer indicates the top item on the stack in the internal frame. CLINK - Control Link. This field points to the preveious frame in system memory. The CLink field is only valid if the previous frame has been dumped into memory. That is why the CLink instruction must dump the previous frame before returning a value. Nametable Points to a function header used to bind the names of the function. This field is copied from the compiled function header. It is usually the same as the CODE BASE. Function Header Points to the function header which contains the code for the function. Initialized when the stack frame header copied from function header. Vars section This section contains all of the variables used in the function, including the IVars, PVars, and FVars. The value for a variable is stored in the cell which corresponds to its offset. All of the variables are indexed from offset 0. Indirect pointers can be found in these fields when the variable is a FVar. The first 7 variable cells are reserved for IVars, and are always present. If more than 6 IVars are passed to a function, then variable cell 7 contains a pointer to the Ivar overflow area. If an overflow area is necessary for PVars, FVars, or more stack space, then some variable cell must point to the overflow area. Stack section This section contains the working stack. The start of the stack is determined by the number of FVars, and PVars. The SP field indexes the current top of stack. In some computations it may be necessary to move part of the stack out to memory to keep the stack from overflowing. This is done by moving the lower portion of the stack frame and writing it out to the frame overflow area. FUNCTION HEADER The function header format also consists of a normal object header with the type index set to a "CCodep". The function definition cell of the atom contains a pointer to the function header: Function Definition Cell: Interpreted: 39 31 23 15 7 0 *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR| ListP |F|R| Pointer to definition (list or NIL) | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* Compiled: 39 31 23 15 7 0 *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR| CCodeP|F|R| Pointer to CCodeP | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* Function Header: This object contains the header and code for the function. It must be quad word alligned so that a quadword read can get the function header information needed to initialize the stack frame. The quadword starting at offset 4 is the data which is used to initialize the stack frame. CCodeP: 39 31 23 15 7 0 *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* 0: | GC | |IMM|ObjHdrP|F|R| Type Index = CCodeP | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |INT| Object Size | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR|SymbolP|F|R| Function Name | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | . . . | *=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=* n+4: | |INT|R|E| | | | | | SP | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |INT| PC | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR| CCodeP|F|R| NAMETABLE | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |PTR| CCodeP|F|R| Function Header | *=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=*=+=+=+=+=+=+=+=* n+8: | |INT| PC Entry Vector 0 | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |INT| PC Entry Vector 1 | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |INT| PC Entry Vector 2 | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |INT| PC Entry Vector 3 | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |INT| PC Entry Vector 4 | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |INT| PC Entry Vector 5 | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |INT| PC Entry Vector 6 | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |INT| PC Entry Vector 7 | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | Other Function Data | | . . . | | . . . | | . . . | | . . . | | . . . | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | Compiled Code | | . . . . . . . | | . . . . . . . | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* FUNCTION NAME Atom index which is the name of this function. OBJECT SIZE Size (in words) of the object. SP - Stack Pointer This is the initial stack pointer location for the function, which is set to the last used variable slot in the frame. PC Entry Vector 0-7 This table indicates the different entry points for the function. Entries 0-6 are used if there are 0-6 parameters passed to the function, and entry 7 is used if 7 or more parameters are passed. Each entry contains the starting absolute PC of the entry code. NAMETABLE Self referencing pointer back to the function header. May be changed in the stack frame to reference another name space. Function Header Self referencing pointer back to the function header. VIRTUAL MEMORY The virtual memory page size will be 2000Q words per page. The maximum real memory size will be 400000000Q words, the maximum size of non-mapped memory will be 1000000Q words, and the maximum virtual address space will be 400000000Q words. There will be one entry in the virtual page map table for each page, with each entry being one word. Each entry will contain the physical translation address for the virtual address allong with 2 flags: valid, and write-protected. The software routines may define additional flags for other indications - dirty, accessed, etc. The software page fault routine will control these flags while the hardware will detect page faults on virtual accesses based on the valid and write-protected flags. The address breakdowns are as follows: Real (Non-Mapped)Address: 39 31 25 17 0 *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | | | |0 0 0 0 0 0 0 0| Real Memory Address | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* Virtual (Mapped) Address: 39 31 25 15 10 0 *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | | | | Virtual Memory Table Address | Lower bits of addr| *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* Virtual Memory Table Entry: 39 31 26 15 0 *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | |INT|Flags| | Physical Memory Address | *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* Resulting Mapped Address: 39 31 25 10 0 *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* | | | | Physical Memory Address | Lower bits of addr| *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-* GARBAGE COLLECTION Each cell contains a four bit GC reference count. This field is divided into a 3 bit reference count field and a 1 bit overflow flag. A value of zero in the whole field means that there is one pointer to the object in the zero count table. When an additional pointer to an object is created, the reference count is incremented. If the field overflows past 7, a UFN trap occurs. If the overflow bit is off, an overflow entry is created with a reference count of 0. Then the trap gets the overflow entry and incrementes it by 4. In the GC field, the reference count field is decremented by 4. When a pointer to a object is removed, its reference count field is decremented. If this decrements it past zero, a UFN trap occurs. The trap checks to see if the overflow flag is on. If so, the overflow field is decremented by 4. The objects reference count feld is incremented by 4. if this causes the hash entry to become zero, the entry is deleted and the overflow flag is turned off. if the overflow flag was not originally on, the reference count is incremented by one and the object is placed on the zero count queue. Periodically, the zero count queue is processed and each entry is examined. First the reference count field is examined. if it has the overflow flag set and the count is not 0, then the entry is removed from the queue and the reference count is decremented by one. if the entry is still on the stack, then the entry is requeued on the queue. If the entry is no longer on the stack, then it is deallocated. GLOBAL REGISTERS A global register frame will store various system constants and temporaries. Most have pre-defined meanings, but some will be available for system use. The pre-defined registers areas follows: UfnBase This register contains a pointer to the base of thesystem ufn table. Undefined Fn This register contains a CCodeP pointer to the function called when a illegal function call is attempted. PageFault Fn This register contains a CCodeP pointer to the function called when a page fault is encountered. The page fault address is passed as the only parameter. Interrupt Fn This register contains a CCodeP pointer to the function called when an external interrupt is requested. Stack Overflow Fn This register contains a CCodeP pointer to the function called when the stack requires adjusting. Rtemp1 This register contains an internal temporary used by the microcode. Irq Enable Count This register contains an internal temporary used by the microcode to count the number of interrupt disables that are active. DecRef This register contains an internal temporary used by the reference count microcode. IncRef This register contains an internal temporary used by the reference count microcode. Reference Count Fn This register contains a CCodeP pointer to the function called when a reference count operation requires theUfn logic. ConsInfo This register contains the next address used to make a new cons cell. It must be set by LISP using a IREGX_ opcode. TAMARIN OPCODES This section describes the opcode set used by implemented by tamarin chip. It describes ONLY those actions which are performed by the microcode, therefore the ufn routines are not described in this section. Note that all opcodes using Symbols in the code stream have the problem that only 3 bytes are allocated for the Symbol pointer value, thus limiting symbol allocation to the 1st 16 Mega-words of memory. Constants: 'T Push the constant T onto the stack. 'NIL Push the constant NIL onto the stack. '0 Push the integer constant 0 onto the stack. Optimization of SICX 0. '1 Pushes the integer constant 1 onto the stack. Optimization of SICX 1. 'UNBIND Pushes the funny constant UNBIND onto the stack (so that it can be copied into local-variable cells). SICX Pushes the non-negative integer constant found in alpha byte onto the stack. Optimization of SICXX. SICXX Pushes the non-negative integer constant found in next 2 bytes onto the stack. Optimization of ICONST. PCONST Push the pointer constant found in next 4 bytes onto the stack. The major type bits are set to 'pointerp'. ICONST Push the (signed) integer constant found in the next 4 bytes onto the stack. The major type bits are set to 'integerp'. FCONST Push the floating point constant found in the next 4 bytes onto the stack. The major type bits are set to 'floatp'. ACONST Push an atom constant made from the atom number found in the next 3 bytes onto the stack. Note the 3 byte limit, but this can be overcome by using the PCONST opcode. IMMCONST Push the 4 byte immediate constant made from next 4 bytes onto the stack. Variable Access: VARX Push the value of the local variable indicated by the alpha byte. VARX_ Store TOS into the local variable indicated by the alpha byte. VARX_^ Store TOS into the local variable indicated by the alpha byte and pop. VARK (0-15) Push the value of the local variable indicated by the opcode. Optimized version of VARX. VARK_ (0-15) Store TOS into the local variable indicated by the opcode. Optimized version of VARX_. VARK_^ (0-15) Store TOS into the local variable indicated by the opcode. The stack is popped after the value is stored. Optimizaton of VARK_ + POP. GVAR Push the global variable value cell indicated by the next three bytes, which are the atom number of the variable. Call the Ufn if the value cell of the atom is unbound. GVAR_^ Store TOS into the global variable indicated by the next three bytes, which are the atom number of the variable, and the proper reference counts can be adjusted (i.e. the object being smashed has its reference count decremented, and the object being stored has its reference count incremented). The reference count UFN will be called if the reference count operations overflow. The value being stored is popped from the stack. OVAR1.X Push the variable located at variable cell X, in the stack frame which is 1 frame back. If the previous frame is not in the processor then call the UFN. OVAR1.X_^ Store TOS into variable cell X, which is in the stack frame 1 frame back. If the previous frame is not in the processor then call the UFN. The value stored is popped from the stack. Binding Stack Operations: BIND Bind the symbol indicated by the next three bytes onto the binding stack, with the value popped from the stack. UNBIND.N Pop n symbols off the binding stack. This opcode will just subtrace n from the binding stack TOS pointer. FVARX Check the variable cell indicated by the alpha byte. If it contains a valid pointer to a value cell (i.e. NOT the constant Unbound) then push the value referenced by the cell, else lookup the symbol in the binding stack. The binding stack lookup proceeds by following the CLINK of the stack frame to the binding stack of the previous frame, looking for the symbol desired. If it is found then the cell in the stack frame is set to point to the corresponding value cell, and the value loaded. Otherwise the cell in the stack frame is set to reference the global value. FVARX_ Check the variable cell indicated by the alpha byte. If the cell contains Unbound, then the free variable lookup must be performed as in FVARX to find & set the cache value in the cell. Once the cell is set then store the value at TOS at the location referenced by the cell. If the reference count bit is set in the pointer then the reference counting operations are performed. Stack Modification: COPY Push a new copy of TOS back onto the stack. SWAP Swap the values at TOS and TOS-1. POP Pop the stack and discard the value. MOVETOS Save the value of the TOS cell. Next set the stack pointer to the value of the alpha byte. Then set the TOS cell to the saved value. SETTOS Set the stack pointer to the value of the alpha byte. Type Checking: INTEGERP Set TOS to NIL if TOS is not an Integerp . Note IntegerP is an item with tag bits = INT. FLOATP Set TOS to NIL if TOS is not a Floatp. POINTERP Set TOS to NIL if TOS is not a Pointerp. IMMEDIATEP Set TOS to NIL if TOS is not an ImmediateP. CONSP Set TOS to NIL if TOS is not a CONSP. Optimization of SUBTYPEP.N test. GETTYPEBITS Set TOS to the type bits of TOS (8 bits as a small nonnegative integer: 2 bits of type 4 of subtype and 2 flags). GETPTRBITS Replace TOS with an integerp which has the value of the pointer bits of TOS. (i.e. clear the subtype & flag bits of TOS and set the major type bits to integerp. If TOS is not a Pointerp then call the UFN. SUBTYPEBITSP.N Compare type bits (major & subtype bits) of TOS with the alpha byte (ignoring the least significant bit, i.e. the flag bit). Set TOS to NIL if no match. Call UFN if TOS is not a pointer. Note that the flag bits are ignored in this opcode so that the alpha bytes match the constants used in the FLAGTYPEP.N opcode. FLAGTYPEBITSP.N Compare type bits (major, sub, & flag type bit) of TOS with the alpha byte. Set TOS to NIL if no match. Call UFN if TOS is not a pointer. RCTYPEBITSP.N Compare type bits (major, sub, flag type, & reference count bit) of TOS with the alpha byte. Set TOS to NIL if no match. Call UFN if TOS is not a pointer. SETTYPE.N Set the type bits of TOS to the integer value in the alpha byte. This sets only the major type bits (2 of them), and NOT the subtype bits of TOS. SETSUBTYPE Set the major, subtype, flag, and reference count type bits of TOS-1. This sets the full 8 bits of the type bits to the integer value at TOS. TYPEP Compare type of object at TOS-1 to see if it is EQ to the type symbol at TOS. The object's type index must be retrieved from the header word. The type index is used as an index into the type table, which contains a pointer to the type information. The symbol of the type is then compared to that of TOS. If they match then pop the operands and return T. Otherwise follow the supertype field of the type, and perform the test again. This continues until there is not a supertype, at which time the operands are popped and NIL is returned. UFNTYPEP Same as TypeP except UFN is called if a match is not found. Binary Ops: EQ Compare TOS with TOS-1. Pop TOS and place the result back onto the stack at the new TOS. EQL Perform an EQ. If EQ returns T then leave T at TOS, otherwise if both operands are not FloatP, IntegerP, or SymbolP then call the UFN. EQUAL Perform an EQ. If EQ returns T then leave T at TOS, otherwise call the UFN routine. CEQUAL Perform an EQ. If EQ returns T then leave T at TOS, otherwise call the UFN routine. GREATERP If both TOS and TOS-1 are integers then compute [TOS-1 greater than TOS], pop TOS , and place the result at the new TOS. Ufn if either TOS or TOS-1 are not integers. PLUS If both TOS & TOS-1 are integers, then compute [TOS-1 plus TOS]. If an overflow does not occur, then pop TOS , and place the result at the new TOS. If either TOS or TOS-1 are not integers or an overflow occurs then the UFN is called. DIFFERENCE If both TOS & TOS-1 are integers, then compute [TOS-1 minus TOS]. If an overflow does not occur, then pop TOS , and place the result at the new TOS. If either TOS or TOS-1 are not integers or an overflow occurs then the UFN is called. TIMES If both TOS & TOS-1 are IntegerPs or FloatPs then perform the multiplication, popping off the arguments and pushing the result. If one operand is IntegerP and the other FloatP, then convewrt the integerP to a FloatP and multiply, leaving the result as a FloatP. The UFN is called if the operands are illegal or an overflow occurs. QUOTIENT If both TOS & TOS-1 are IntegerPs or FloatPs then perform the division, popping off the arguments and pushing the result. If one operand is IntegerP and the other FloatP, then convewrt the integerP to a FloatP and divide, leaving the result as a FloatP. The UFN is called if the operands are illegal or an overflow/underflow occurs. REMAINDER If both TOS & TOS-1 are IntegerPs then perform the division, popping off the arguments and pushing the Integer remainder as the result. The UFN is called if the operands are illegal or an overflow/underflow occurs. LOGAND If both TOS & TOS-1 are integers, then compute [TOS-1 and TOS], pop TOS , and place the result at the new TOS. If either TOS or TOS-1 are not integers then the UFN is called. LOGOR If both TOS & TOS-1 are integers, then compute [TOS-1 or TOS], pop TOS , and place the result at the new TOS. If either TOS or TOS-1 are not integers occurs then the UFN is called. LOGXOR If both TOS & TOS-1 are integers, then compute [TOS-1 xor TOS], pop TOS , and place the result at the new TOS. If either TOS or TOS-1 are not integers occurs then the UFN is called. Unary Ops: NEG Negate the IntegerP at TOS. If TOS is not an IntegerP or an overflow occurs, then the UFN is called. LOGNOT Set TOS to the Logical NOT of the IntegerP at TOS. If TOS is not an IntegerP then the UFN is called. Shift Operations: ASH If TOS and TOS-1 are integers, and TOS is 1 or -1, then perform an Arithmetic Shift of TOS-1 by TOS, filling with 0's for a right shift and the sign bit on left shifts. The shift direction is determined by the sign of the shift amount, with a positive value being a left shift and a negative value a right shift. The sign bit of the shifted item is NOT affected by this operation as it is in the logical shift. If either operand is not an integer, or the shift amount is not 1 (or -1), or an overflow occurs, the UFN routine is called, otherwise the shift amount is popped from the stack and the result is left at the new TOS. LLSH.N If TOS is an integer then Logical Left Shift TOS by the number of bits indicated in the alpha byte, filling with 0's on the right. If the operand is not an integer the UFN routine is called. Bits are shifted into the sign bit and the bit shifted out of the sign bit is lost. LRSH.N If TOS is an integer then Logical Right Shift of TOS by the number of bits indicated in the alpha byte, filling with 0's on the left into the sign bit. If the operand is not an integer the UFN routine is called. Pointer manipulation & Memory Access: ADDBASE Add the integer value at TOS to the pointer value at TOS-1 producing a new pointer as a result. The TOS operand is popped from the stack and the resulting pointer is placed at the new TOS. The type bits of the created pointer are those of the original type. If the TOS-1 operand is not a pointer or TOS is not an integer then the UFN routine is called. GETBASEPTR.N Add the alpha byte to the pointer value at TOS producing a new pointer as a result. The old pointer is popped from the stack and the data pointed to by the new pointer is pushed back. If the TOS operand is not a pointer then the UFN routine is called. PUTBASEPTR.N Add the alpha byte to the pointer value at TOS-1 producing a new pointer as a result. The data found at TOS is then stored at the location pointed to by the new pointer. The stored data is popped from the stack but the old pointer is left on the stack. No reference counts are affected by this opcode. If the pointer operand is not a pointer then the UFN routine is called. RPLPTR.N Add the alpha byte to the pointer value at TOS-1 producing a new pointer as a result. The data referenced by the resulting pointer is read & its reference count is decremented. The data found at TOS is then stored at the location pointed to by the new pointer, with the appropriate reference count incremented. The stored data is popped from the stack but the old pointer is left on the stack. If the pointer operand is not a pointer then the UFN routine is called. If there is an overflow or underflow from the reference count operations, the reference count UFN is called. GETFIELD TOS-2 is a pointer, TOS-1 is a field position, and TOS is a field width of the desired bit field. All are removed from the stack and the resulting field is pushed as an integerP. If TOS-2 is not a PointerP, or TOS-1 or TOS are not IntegerP's then the UFN is called. PUTFIELD TOS-3 is a pointer, TOS-2 is a field position, TOS-1 is a field width of the desired bit field, and TOS is the field value to store. All but the Pointer are removed from the stack and the resulting field is placed in the referenced word. If TOS-3 is not a PointerP, or TOS-2, TOS-1 or TOS are not IntegerP's then the UFN is called. Reference Counting GETREFCOUNT Retrieve the reference count bits from TOS and place them at TOS as an InteterP. SETREFCOUNT Set the reference count bits of TOS-1 from TOS and then pop TOS. If TOS is not an IntegerP then call the UFN. CMPLREFCOUNT Complement the high-order bit in the reference count field of the word pointed at by (TOS). This is equivelent to adding (or subtracting) a reference count of 4. List Operators & CDR Coding CONS A cell is created with the CDR field set to TOS and the CAR field set to TOS-1. Both operands must have their reference counts incremented. The operands are popped from the stack and a pointer to the created cell is pushed back. RPLCONS Create a new cons cell with TOS as the CAR and NIL as the CDR. Set the CDR of TOS-1 (which is a ConsP) to point the the new cons cell. The two operads are popped from the stack and a pointer to the new cons cell is pushed. Normal reference count operations must be performed. A UFN is called if TOS-1 is not a ConsP, or there are reference count overflows. CAR If TOS is NIL, then leave NIL on TOS, else fetch the CAR of the cell pointed to by TOS. TOS is replaced with the CAR value. The UFN is called when TOS is not a Listp. CDR If TOS is NIL, then leave NIL on TOS, else fetch the CDR of the cell pointed to by TOS. TOS is replaced with the CDR value. The UFN is called when TOS is not a Listp. SETF-CAR Replace the CAR field of TOS-1 with TOS, then pop TOS. If the reference count bit of TOS-1 is set then the reference count of the old CAR must be decremented, and the reference count of the new CAR object is incremented. The old TOS-1 is not changed. The UFN is called if TOS-1 is not a Listp. SETF-CDR Replace the CDR field of TOS-1 with TOS, then pop TOS. If the reference count bit of TOS-1 is set then the reference count of the old CDR must be decremented, and the reference count of the new CDR object is incremented. The old TOS-1 is not changed. The UFN is called if TOS-1 is not a Listp. GETCDRCODE Retrieve the CdrCode bits from TOS and place them at TOS as an InteterP. SETCDRCODE Set the CdrCode bits of TOS-1 from TOS and then pop TOS. If TOS is not an IntegerP then call the UFN. Jumps: NOP (0-4) Nop instructions can pretend to have up to 4 code stream argument bytes; the effect is a short forward jump of 0 to 4 bytes past the Nop instruction. JUMPK (5-15) Short forward jump. Jump offset is computed from the opcode minus the four least significant bits of the opcode. The jump offset is then added to the PC of the jump instruction plus 1, so the new address is: PC + 1 + offset. JUMPX Jump of up to +256 locations. The alpha byte is added to the PC of the next instruction following the jump instruction, to get the new PC, thus the new address is: PC + alpha + 2. JUMPXX Jump of up to 64K locations. The 2 bytes are added to the PC of the next instruction following the jump instruction to get the new PC, thus the new address is: PC + bytes + 2. JUMPABS Jump absolute to location indicated by the four data bytes in the code stream. NJUMPX Negative jump of up to -256 locations. The alpha byte is subtracted from the PC of the next instruction following the jump instruction, to get the new PC, thus the new address is: PC - alpha + 2. NJUMPXX Negative jump of up to 64K locations. The 2 bytes are subtracted from the PC of the next instruction following the jump instruction to get the new PC, thus the new address is: PC - bytes + 2. FJUMPK (0-15) TOS is popped from the stack, and is compared to NIL. The jump is taken if TOS was NIL. The jump offset is computed in the same manner as for JUMPK. FJUMPX TOS is popped from the stack, and is compared to NIL. The jump is taken if TOS was NIL. The jump offset is computed in the same manner as for JUMPX. TJUMPK (0-15) TOS is popped from the stack, and is compared to NIL. The jump is taken if TOS was not NIL. The jump offset is computed in the same manner as for JUMPK(. TJUMPX TOS is popped from the stack, and is compared to NIL. The jump is taken if TOS was not NIL. The jump offset is computed in the same manner as for JUMPX. FJUMPN^X TOS is compared to NIL. The jump is taken if TOS was NIL. If the jump is not taken, then TOS is popped from the stack. The jump offset is computed as for JUMPX. TJUMPN^X TOS is compared to NIL. The jump is taken if TOS was not NIL. If the jump is not taken, then TOS is popped from the stack. The jump offset is computed as for JUMPX. Function Call & Return: FN (0-7) Call a function with 0-7 arguments. The definition cell of the 3 byte symbol which follows in the code stream is the function to call. If more than 6 arguments are passed, the 7th argument slot is an indirect pointer to a frame extension which contains the extra arguments. This opcode must ensure that there is an available frame for the called function, dumping a previous frame out to memory if necessary. When the definition cell of the symbol contains a CCodeP, then the function call proceeds as follows: First words 4 through 7 of the function header are copied to locations 16 throuth 19 of the new stack frame. The new Stack Frame locations 0 through 7 are filled with NIL while locations 8 through 15 are set to Unbound. Then the arguments 0-7 are popped off the current stack and copied to the new stack frame with the 1st parameter going into slot 0, 2nd at slot 1, ... 7th at slot 6. The PC is then set to the indicated entry address in the function header according to the number of parameters & the new stack frame is set as the current one. If the definition cell is not a CCodeP, then the Undefined function is called as if it were the called function (as in above), except that cell 7 of the called frame is set to the symbol of the function call so that the name of the undefined function (or function to be interpreted) will be known. APPLYFN Call the function referenced at TOS with TOS-1 arguments (0 to 7). The n arguments for the function are from TOS-2 to TOS-(2+n-1), in exactly the same form they would be in from TOS to TOS-(n-1) if the function were being called with a FNn opcode. RETURN Return from a function. The CLINK is followed to find the previous stack frame (which is loaded if necessary). Execution continues at the PC indicated in the retrieved stack frame. This opcode will call the UFN routine when the slow return bit or the slow return to bit is set in the stack frame header. RETEI Return and enable interrupts, without pushing a result. Performs the same operation as the Return opcode except interrupts are enabled, and a result is not pushed onto the callers stack. Used by interrupt & trap routines where a result would invalidate the previous frame because the frame was not "called" by the normal function call mechanism, it was entered through an asynchronous event (such as an interrupt). Also used for ufns which do special "munching" of the previous stack frame. RETNP Return without pushing a result. Performs the same operation as the Return opcode except a result is not pushed onto the callers stack. Used by trap routines where a result would invalidate the previous frame because the frame was not "called" by the normal function call mechanism, it was entered through an asynchronous event (such as a page fault). MYCLINK Ensure that all previous frames are dumped out into memory, then push the CLINK of the current stack frame onto the stack. MYCLINK_^ Ensure that all previous frames are dumped out into memory, then set the CLINK of the current stack frame to the TOS value & pop. FINDKEY.N Search through the argument list starting at the nth argument, looking for the key indicated by TOS. Returns NIL if the item is not found, or the argument number of the if the argument is found. RESTLIST.N Create a list of the arguments starting at the nth argument. TOS-1 is a list to cons in front of, and TOS is the last argument number to cons. TOS and TOS-1 are popped and the constructed list is pushed onto the stack. This may UFN under certain conditions. CONTEXTSWITCH Switch to the context indicated by the operand. The operand is an index into the process table which has the process information for the next context. Reports an error if the context index was invalid. Array Accessing: ARRAYREAD TOS-2 is an pointer to a block of storage holding an array, TOS-1 is a type number indicating the size of the elements of the array, and TOS is an index in element units. Compute the address of the actual element being referenced, pop the three operands, and push the resulting element. UFN if the TOS index is not IntegerP or out of range. This may UFN on certain difficult cases. ARRAYWRITE TOS-3 is an pointer to a block of storage holding an array, TOS-2 is a type number indicating the size of the elements of the array, TOS-1 is an index in element units, and TOS is a value to store. Compute the address of the actual element being referenced & store the value. UFN if the TOS-1 index is not IntegerP or out of range, or if TOS is does not match the element type of the array. The value being stored is pushed back on the stack after the four operands are popped. This may UFN on certain difficult cases. ARRAYREF1 TOS-1 is a one dimensional ArrayP and TOS is an index. Compute the offset of the indicated array in element untis perform the array reference, popping the index & ArrayP and push the element referenced. UFN if the index is not IntegerP or the pointer is not a one dimensional ArrayP. This may UFN on certain difficult cases. ARRAYREF2 TOS-2 is a two dimensional ArrayP and TOS-1 & TOS are indexs. Compute the offset of the indicated array in element untis perform the array reference, popping the indexes & the ArrayP and push the element referenced. UFN if the indexes are not IntegerPs or the pointer is not a two dimensional ArrayP. This may UFN on certain difficult cases. ARRAYSET1 TOS-2 is a one dimensional ArrayP and TOS -1 is an index. Compute the offset of the indicated array in element untis perform the array reference and store TOS at the indicated array slot. Pop the index, ArrayP, & value from the stack; then push back the value stored. UFN if the index is not IntegerP or the pointer is not an ArrayP. This may UFN on certain difficult cases. ARRAYSET2 TOS-3 is a two dimensional ArrayP and TOS-2 & TOS-1 are indexs. Compute the offset of the indicated array in element untis perform the array reference and store TOS at the indicated array slot. Pop the indexes, ArrayP, & value from the stack; then push back the value stored. UFN if the indexes are not IntegerPs or the pointer is not an ArrayP. This may UFN on certain difficult cases. Special Purpose Instructions: DISINT Disable external interrupts. ENBINT Enable external interrupts. SETMEMLOCK Set the memory lock to prevent external memory accesses. CLRMEMLOCK Clear the memory lock to allow external memory accesses. SETOUTPUTIRQ Set the external interrupt request line. CLROUTPUTIRQ Set the external interrupt request line. IREGX Get Internal register X of the processor. This pushes the internal register (0-63), indicated by the alpha byte, of the "global" stack frame onto the current frame's stack.. IREGX_^ Set Internal register X of the processor. This stores TOS into the internal register (0-63), indicated by the alpha byte, of the "global" stack frame. WRITEOCT NIL.N Fill the 8 cells in the current stack frame beginning at N (where N must have bits 2 1 0 all 0) with NIL. WRITEOCTUNBOUND.N Fill the 8 cells in the current stack frame beginning at N (where N must have bits 2 1 0 all 0) with the constant Unbound. GETHIBYTE Return the 5th byte of the item at TOS as an IntegerP at TOS. SETHIBYTE Set the 5th byte of the item at TOS-1 to the integer value at TOS. UFN if TOS is not an IntegerP. Pop TOS operand off the stack. - X - Denotes end of function and is never executed. Should Ufn if ever encountered to report an error. :lllP:lljlP:HllP:T<lP@ll h:lP.H....(6(.((CLASSIC CLASSICCLASSICCLASSICCLASSIC CLASSIC CLASSIC TERMINALTERMINAL GACHAGACHA CLASSIC CLASSICD6(TEXTFONT 5 (CLASSIC 14) (TIMESROMAN 10) (CLASSIC 10))     +   A 2 E R S S S  , 7 7 G F)G>@   R S S S      R S S S      R S S S  g    R S S S    F  6 6 ( Q # 4 $ . / >  G  K , '  c   G     R S S S S S S S S S S    B D       R    S X S V S S S S S S V S    S W S V S S S S S S V S    S X S V S V S S S S V S V S V S V S S S S S S V S    S X S V S V S V S S S S S S V S    S W S V S V S S S S S S V S "  vR S S S         2   R S S S S S S S S S S S S S    E I  A 1 > (R S X S S S S S S S  ?  S X S S S S S T S X S S S S S S S X S V S S S S S S S X S S S S S X S     8 !M       R S S S    R S S S      R S X S V S S S S S X S V S S S S S X S V S V S V S V S V S V S V S S S S S S S S S S S S 0 x {8  R S S S   R S S S   R S S S    R S S S   c E j  hbETTw u    $&GGfehmzxL E@Ic` p j< -"$5  \') ,H v ?   !; YUU MO  hg  v % i  |HT   Q o  j-+ I f Q -3h{         K [ }    9 : ) )l~ > c kYz