Tamarin: Internal Software Structures
Alan Bell and Bill van Melle
May 14, 1985
Introduction
This document describes the internal data structures used in the Tamarin hardware and low-level software. This is intended to cover only the hardware. In places, it describes data formats when those are used by the hardware.
The Tamarin hardware is built around a 40 bit word size. Internally, the machine will contain a small number of fixed size stack frames.
Pointer Format
The word size will be 40 bits. The pointer will be 34 bits. There will be three different formats depending on the TYP field.
+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
|TYP| SUBTYP | PTR |
+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
|TYP| SUBTYP | IMMEAD |
+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
|TYP| VALUE |
+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
TYPThis field describes the basic type of the pointer.
00: 32 bit Integer
01: 32 bit Floating point
10: Pointer - subtype valid
11: Unused
SUBTYPThis field describes the exact type of the object. The size of this field may be reduced by 1 bit. Some of the subtypes, such as atom, will point at normal objects. The purpose of having the type in the pointer is in the ease of determing the type. Additional datatypes can be added.
0: Object Header
32:
Atom
33:
Array
34:
String Pointer
35:
Stack Header - "stk"
36,37:
Free Stack Frame - "sstk" (1 bit flag)
40:
Function pointer - "fnptr"
41:
Function Pointer
42:
OBJECT
PTRThis field contains a word pointer when TYP=ptr and SUBTYP >=32. Not all 27 address bits will be used in the first implemetation of Tamarin.
IMMEADThis field contains an immeadiate quantity when TYP=ptr and SUBTYP <32.
VALUEThis contains a 32 bit immeadiate value when the type field indicates floating or integer.
Types
The type of an object is represented in the pointer. If the pointer type is OBJECT then the type is represted in the first word of the object. These different representations result in a single type description called the composite type index. Although it will sometimes be possible to determine the type from the datum alone (not using the pointer), this is not always the case.
List Cells
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
| GC |CDR| PTR |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
GCThe GC field contains the reference count. See GC section.
CDRThis field contins CDR-coding information.
00 : CDR IS NIL
01: CDR IS PREV
10: CDR IS NEXT
11: CDR IN NEXT
Object Format
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
| GC |0 0| "objhdr" | TYPEINDEX |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
GCThe GC field contains the reference count. See GC section.
TYPEINDEXThis is an index which describes the type of the following object.
Atoms
Atoms will be represented by a standard object with the type field of atom. The object will contain 4 cells plus the header.
Atm *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
0: | GC | "objhdr" | TYPEINDEX = "atom" |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
1: | | VALUE CELL |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
2: | | FUNCTION CELL |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
3: | | PROPERTY LIST |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
4: | | PNAME PTR |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*

Stack Structure
1. Stack Frame
The processor will keep several separate frames in its internal memory. These internal frames will be imaged in main memory. The frames will contain only one part. The maximum length of a complete stack frame will be 32 words.
HDR *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
0: | | "stk" | FLAGS | TOS | USECNT |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
1: | | PC |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
2: | | FUNCTION HEADER |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
3: | | NAMETABLE |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
4: | | CLINK |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
5: | | ALINK |
VARS *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
6: | | VAR0 |
| | ... |
| | VARi |
STK *-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
| | STK0 |
| | ... |
| | STKj |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
FlagsThe flags include:
TrapEntry - UFN when this frame is entered by a return
TrapExit- UFN when this frame is about to be exited
Deref Alink- Dereference ALink on exiting. If this is set, TrapEntry must also be set.
Large Frame- This frame stk blk is large
No-Push- Don’t push result when returned to.
TOSThe TOS fields indicates where the end of the stack is. It points into the internal frame.
UsecntThe Usecnt field indicates if this frame is pointed to by any other frames or Stack pointers.
PCThis contains the program counter. It is represented as an integer with the low 3 bits selecting the byte. The high-order bits point directly at the word to be executed. There is no base value added in.
CLinkThis field points to the previous frame.
Function HeaderThis field points at the start of the function’s header.
ALinkThis field points to the frame which denotes the previous access environment. If this field is UNBOUND, then the CLink should be used for the ALink.(An alternative is to fill in both the ALink and CLink at the same time. But this is hard since that location only wants to be filled with AssignStackAddress and not LoadStackBlocks.)
NametableThis points to the nametable of the function. If it is unbound, then the function binds no names and the function should not be searched on free variable lookup. The field is set by the compiled code setting this location.
VarsThis section contains the IVars, PVars, and FVars. Each is indexed from a single offset . This field can contain indirect pointers.
StkThis section contains the working stack. The start of the stack is determined by the number of IVars and PVars.
2. Unused Stack Frames
There will be two lists of unused stack frames. One list will contain full length stack frames. The other list will contain shorter frames. The Short Frame flag in the function header will select the later size. Unused stack frames will be contained in a linked list. The pointer in the first word points to the beginning of the next stack frame. The pointer will contain a flag - F. The flag will indicate that the number of free frames is getting low. If the machine uses a frame with the flag set, an internal note is made and the next time an interruptable opcode is about to be executed, a trap is taken. The flag must be set on all frames past a certain point in the chain. The minimum number of frames with the flag set are nbr internal frames + max non-interruptable calls. The hardware will not check if the end of the list is exceeded. All stack frames on the chain may be required to be locked in memory. The frames will be quad word aligned.
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
0: | | "sstk" |F| NEXTFRAME |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
1: | | unused |
| | ... |
| | unused |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
3. Common Stack Operations
Function CallDump next internal frame if not empty
Fetch Function Def cell
Set new frame to "UNBOUND"
Copy first 4 words of Function Header into Frame.
Set low order three bits of PC from opcode.
Copy args from old frame STK to new frame VARS
Start at PC
Start FunctionThe function is started at the appropriate start address. All of the actions decribed here are performed by opcodes. See Argument preparation section for detailed description.
ReturnLoad previous frame if not present
UFN if TrapExit(Current) set
Fetch return value
Deallocate old frame
UFN if TrapEntry(prev) set
Push return value unless No`push set
Continue at PC
Load FrameRead first quad word
Read additional Quad word until TOS
Dump FrameIf no addresss then Assign Stack Address
Write quad words until TOS
Assign Stack Address
Set address to next frame ptr
Next frame ptr ← Read(NextFramePtr[size])
--size is determined by flag in the header.
4. Argument preparation
If the number of arguments is greater than 7 or the caller feels that the callee is a NLAMBDA*, then the arguments are presented as a vector. The callee is then required to reformat the opcodes to a useful form.
APPLY, APPLY*If the number of arguments are less than 8, then the arguements are put on the stack, else these functions prepare a vector.
Number of Args>7The caller writes all the args into a vector. It passes the vector and the number of args as the arguments of the function.
Function Header
1. Function definition cells
Function Definition cells are:
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
| | "fnptr" | pointer to function header |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
2. Function header
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
| | "fnhdr" | 0 | TOS | 0 |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
| |int| PC |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
| | FUNCTION HDR |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
| | NAMETABLE |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
| | "atom" | FUNCTION NAME |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
| | unused |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
| | unused |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
| |int| NTSIZE | NLOCALS | FVAROFFSET |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
| | "atom" | Var Name |
| | ... |
| | ... |
| | Var Name |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
| |int| Offset |
| | ... |
| | ... |
| | Offset |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
The first four words are loaded verbatim into the first four words of the stack. The function hdr and Nametable fields simply point to the structure.
3. Function entry vector
The function is started at a location determined by the number of arguments in the call and by type of call.
Entry0:Vector of arguments provided (>7 args or NLambda*)
1-7:
0-6 arguments respectively
In a normal Interlisp functions of 2 arguments, the opcodes will be 0: ERROR, 1: UFN(Move 2 args), 2: IVAR0←NIL, 3: IVar1←NIL, 4: JMP 12, 5: JMP 7, 6: NOP, 7: BINDUNB 3,3, 12: start of code.
Virtual Memory
The page size will be 1024 words per page. The maximum real memory size will be 2 million words. The maximum possible virtual memory size will be 128 million words. The maximum virtual memory size on the initial version of Tamarin will be 16 million words. This means that there will be 16K virtual pages in the system. The mapping of virtual page into real address will be done by taking bits 23 through 10 and using them to index a resident mapping table. Each entry in the table will be one word. This word will contain 3 flags and the real page number. The flags are: entry valid, dirty, accessed. The first 2 million words of the virtual address space will refer directly to the real memory. No address translation will occur on these addresses.
Map table entry:
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
| GC |CDR| "int" | FLG | PAGE NUMBER |
*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*-+-+-+-+-+-+-+-*
Garbage Collection
In each cell there is a four bit field that contains the GC reference count information for that cell. This field is divided into a 3 bit refernce 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. If there are no non-stack pointers, then there will be a 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 an reference count of 0. Then the trap gets the overflow entry the count in the entry is incremented by 4. In the GC field, the reference count field is decremented by 4.
When a pointer to a objec 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 field is incremented by 4. If this causes the has 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. Each entry is examined. First the reference count field is examined. If it has the overflow flag set of if 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.
OPCODES
1. Constants:
’T1Push "T" onto stack
’NIL1Push "NIL" onto stack
’01Push "0" onto stack
’11Push "1" onto stack
SIC3Push 1 byte positive integer onto stack
SNIC3Push 1 byte negative integer onto stack
PCONST5Push 4 byte pointer onto stack
FCONST5Push 4 byte floating onto stack
ICONST5Push 4 byte integer onto stack
2. Variable access:
VAR0-151Push Var i onto stack.
VARX.i2Push Var i onto stack.
VARX←.i2Set Var i from stack.
VARX←↑.i2Set Var i from stack, pop stack.
VVARX.i2Push Var i onto stack, don’t follow indirect.
VVARX←.i2Set Var i from stack, don’t follow indirect.
FVARX.i2Push Var i onto stack, UFN if unbound.
FVARX←.i2Set Var i from stack, UFN if unbound.
BINDNIL.n.k3Set Var k to k+n to "NIL".
BINDUNB.n.k3Set Var k to k+n to "UNBOUND".
VAR0-7←NIL1Set Var i to NIL.
OVAR.n.m←3Set Var m from frame current-n. This may trap to accomplish this function.
OVAR.n.m3Push Var m from frame current-n. This may trap to accomplish this function.
GVARX5Push GVar onto stack.
GVARX←5Set GVar from stack, do ref counts.
3. Stack modification
COPY1This copies the TOS onto the stack.
SWAP1This exchanges the TOS and TOS-1.
POP1This pops one entry off the stack.
SETTOSVAL.n2Saves the TOS val, sets TOS to n, pushs saved TOS val.
SETTOS.n2This sets TOS to n.
4. Testing and Type checking
EQ1Compare (TOS) and (TOS-1). Pushs T or NIL based on result of comparison.
LISTP1Return arg if LISTP, else NIL.
NTYPEX1Return composite type index of (TOS).
TYPEP.n3Return (TOS) if its composite type index is eq to n, else return NIL.
DTEST.n3Return (TOS) if its composite type index is eq to n, else UFN.
TYPECHECK.n3Same as DTEST.
TYPEMASK.n2This needs to be worked out.
5. Binary Ops:
PLUS1Add TOS and TOS-1, UFN if not int, ovfl
DIFFER1Sub TOS and TOS-1, UFN if not int, ovfl
LOGAND1And TOS and TOS-1, UFN if not int, ovfl
LOGOR1Or TOS and TOS-1, UFN if not int, ovfl
LOGXOR1Xor TOS and TOS-1, UFN if not int, ovfl
TIMES1Mul TOS and TOS-1, UFN if not int, ovfl
QUOTIENT1Div TOS and TOS-1, UFN if not int, ovfl
REMAINDER1Rem TOS and TOS-1, UFN if not int, ovfl
GREATERP1Cmp TOS and TOS-1, Push T or NIL, UFN if not int
LLSH.n2Logical Left shift. This takes (TOS), shifts it left n, and pushes back onto the stack. It traps if (TOS) is not an integer.
LRSH.n2Logical Right shift. This takes (TOS), shifts it right n, and pushes back onto the stack. It traps if (TOS) is not an integer.
FEXT.fd2Field Extract. This takes (TOS), extracts the field described by fd, and pushes the result onto the stack. It traps if (TOS) is not an integer. This does not sign extend the field.
FINS.fd2Field Insert. This takes (source, dest) on the stack, inserts source into the field described by fd in dest, and pushes the result onto the stack. It traps if source and dest are not an integer.
6. Memory Access:
GETBASEPTR.n2Takes (PTR) on stack. Retrives 34 bit ptr at PTR+n. The result will have the same data type as the word in memory.
PUTBASEPTR.n2Takes (PTR, newval) on stack, leaves PTR on stack, stores newval at PTR+n. Does not reference count anything. Does not trap.
RPLPTR.n2Takes (PTR, newval) on stack, leaves PTR on stcak, deleteref value at PTR+n, addref newval, stores newval at PTR+n. The reference count operations will be queued until this opcode finishs. Does not trap.
GETBITS.n.fd3Takes (PTR) on stack. Retrieves field specified by fd from location PTR+n. The type of the result is set to integer. This will actually be four opcodes since it takes 10 bits to specify all fields.
PUTBITS.n.fd3Takes (PTR, newval) on stack, leaves PTR on stack, stores newval into field specified by fd at location PTR+n. This is actualloy 4 opcodes. This punts if newval isn’t an integer.
GETBASEBYTE1Takes (PTR, offset) on stack. Shifts offset right 2 bits. Retrieves word at PTR+(offset rsh 2). Pushs byte selected by low low bits of offset onto stack.
PUTBASEBYTE1Takes (PTR, offset, byte) on stack, leaves PTR on stack. Stores byte at byte position selected by low 2 bits of offset at location PTR+(offset rsh 2). This traps if offset is not an integer.
ADDBASE1Takes (PTR, offset) on stack. Leaves PTR+int on stack. This traps if integer is not an integer.
7. List Operations
CONS1
RPLCONS1
CAR1This takes the CAR of the (TOS). It traps if the argument is not LISTP or if the CAR cell is an indirect pointer.
CDR1This takes the CDR of the (TOS). It traps if the argument is not listp of if the CAR cell is an indirect pointer. This may just implement the CDR next and CDR prev tags in hardware.
RPLACA1This replaces the CAR field of the (TOS). It traps if the argument is not LISTP or if the CAR cell is an indirect pointer.
RPLACD1This always traps.
8. Garbage Collection / Storage Allocation
INCREF1This increments the reference count of the word pointed at by TOS by 1. If the field is 7, the field is incremented and then a UFN trap occurs.
INCREFNT1This increments the reference count of the word pointed at by TOS by 1. This does not trap.
DECREF1This decrements the reference count of the word pointed at by TOS by 1. If the field is 0, the field is decremented and then a UFN trap occurs.
OFFSETREF1This complements 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.
9. Function Calls:
FN0-65Call function with k arguments
FNL5Call function with list of arguments
APPLYFN1Call function. This takes the name of the function and the entry vector offset on the stack.
RETURN1Return
CONTEXTSWITC1Context Switch - I need input on the requirements for this opcode.
MYALINK1This returns the address of the previous frame. If the previous frame does not have a frame assigned, it dumps the previous frame first.
10. Jumps:
NOP1No operation
JUMP2-171This unconditionally jumps k bytes forward.
JUMPX2This jumps up to (+128, -127) locations.
JUMPXX3The 2 bytes of the opcode are added to the PC to get the new PC.
FJUMP2-171This jumps k bytes forward if TOS is NIL It pops the stack..
FJUMPX2This jumps up to (+128, -127) locations if TOS is not NIL. It posp the stack.
TJUMP2-171This jumps k bytes forward if TOS is not NIL. It pops the stack.
TJUMPX2This jumps up to (+128, -127) locations if TOS is not NIL. It posp the stack.
NFJUMPX2This jumps up to (+128, -127) locations if TOS is NIL. It posp the stack if the jump is taken.
NTJUMPX2This jumps up to (+128, -127) locations if TOS is not NIL. It posp the stack if the jump is taken.