162 lines
		
	
	
	
		
			5.8 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
			
		
		
	
	
			162 lines
		
	
	
	
		
			5.8 KiB
		
	
	
	
		
			Text
		
	
	
	
	
	
.SN 7
 | 
						|
.BP
 | 
						|
.S1 "DESCRIPTORS"
 | 
						|
Several instructions use descriptors, notably the range check instruction,
 | 
						|
the array instructions, the goto instruction and the case jump instructions.
 | 
						|
Descriptors reside in data space.
 | 
						|
They may be constructed at run time, but
 | 
						|
more often they are fixed and allocated in ROM data.
 | 
						|
.P
 | 
						|
All instructions using descriptors, except GTO, have as argument
 | 
						|
the size of the integers in the descriptor.
 | 
						|
All implementations have to allow integers of the size of a
 | 
						|
word in descriptors.
 | 
						|
All integers popped from the stack and used for indexing or comparing
 | 
						|
must have the same size as the integers in the descriptor.
 | 
						|
.S2 "Range check descriptors"
 | 
						|
Range check descriptors consist of two integers:
 | 
						|
.IS 2
 | 
						|
.PS 1 4 "" .
 | 
						|
.PT
 | 
						|
lower bound	signed
 | 
						|
.PT
 | 
						|
upper bound	signed
 | 
						|
.PE
 | 
						|
.IE
 | 
						|
The range check instruction checks an integer on the stack against
 | 
						|
these bounds and causes a trap if the value is outside the interval.
 | 
						|
The value itself is neither changed nor removed from the stack.
 | 
						|
.S2 "Array descriptors"
 | 
						|
Each array descriptor describes a single dimension.
 | 
						|
For multi-dimensional arrays, several array instructions are
 | 
						|
needed to access a single element.
 | 
						|
Array descriptors contain the following three integers:
 | 
						|
.IS 2
 | 
						|
.PS 1 4 "" .
 | 
						|
.PT
 | 
						|
lower bound		signed
 | 
						|
.PT
 | 
						|
upper bound \- lower bound	unsigned
 | 
						|
.PT
 | 
						|
number of bytes per element	unsigned
 | 
						|
.PE
 | 
						|
.IE
 | 
						|
The array instructions LAR, SAR and AAR have the pointer to the start
 | 
						|
of the descriptor as operand on the stack.
 | 
						|
.sp
 | 
						|
The element A[I] is fetched as follows:
 | 
						|
.IS 2
 | 
						|
.PS 1 4 "" .
 | 
						|
.PT
 | 
						|
Stack the address of A  (e.g., using LAE or LAL)
 | 
						|
.PT
 | 
						|
Stack the value of I (n-byte integer)
 | 
						|
.PT
 | 
						|
Stack the pointer to the descriptor (e.g., using LAE)
 | 
						|
.PT
 | 
						|
LAR n (n is the size of the integers in the descriptor and I)
 | 
						|
.PE
 | 
						|
.IE
 | 
						|
All array instructions first pop the address of the descriptor
 | 
						|
and the index.
 | 
						|
If the index is not within the bounds specified, a trap occurs.
 | 
						|
If ok, (I~\-~lower bound) is multiplied
 | 
						|
by the number of bytes per element (the third word).  The result is added
 | 
						|
to the address of A and replaces A on the stack.
 | 
						|
.A
 | 
						|
At this point LAR, SAR and AAR diverge.
 | 
						|
AAR is finished.  LAR pops the address and fetches the data
 | 
						|
item,
 | 
						|
the size being specified by the descriptor.
 | 
						|
The usual restrictions for memory access must be obeyed.
 | 
						|
SAR pops the address and stores the
 | 
						|
data item now exposed.
 | 
						|
.S2 "Non-local goto descriptors"
 | 
						|
The GTO instruction provides a way of returning directly to any
 | 
						|
active procedure invocation.
 | 
						|
The argument of the instruction is the address of a descriptor
 | 
						|
containing three pointers:
 | 
						|
.IS 2
 | 
						|
.PS 1 4 "" .
 | 
						|
.PT
 | 
						|
value of PC after the jump
 | 
						|
.PT
 | 
						|
value of SP after the jump
 | 
						|
.PT
 | 
						|
value of LB after the jump
 | 
						|
.PE
 | 
						|
.IE
 | 
						|
GTO replaces the loads PC, SP and LB from the descriptor,
 | 
						|
thereby jumping to a procedure
 | 
						|
and removing zero or more frames from the stack.
 | 
						|
The LB, SP and PC in the descriptor must belong to a
 | 
						|
dynamically enclosing procedure,
 | 
						|
because some EM implementations will need to backtrack through
 | 
						|
the dynamic chain and use the implementation dependent data
 | 
						|
in frames to restore registers etc.
 | 
						|
.S2 "Case descriptors"
 | 
						|
The case jump instructions CSA and CSB both
 | 
						|
provide multiway branches selected by a case index.
 | 
						|
Both fetch two operands from the stack:
 | 
						|
first a pointer to the low address of the case descriptor
 | 
						|
and then the case index.
 | 
						|
CSA uses the case index as index in the descriptor table, but CSB searches
 | 
						|
the table for an occurrence of the case index.
 | 
						|
Therefore, the descriptors for CSA and CSB,
 | 
						|
as shown in figure 4, are different.
 | 
						|
All pointers in the table must be addresses of instructions in the
 | 
						|
procedure executing the case instruction.
 | 
						|
.P
 | 
						|
CSA selects the new PC by indexing.
 | 
						|
If the index, a signed integer, is greater than or equal to
 | 
						|
the lower bound and less than or equal to the upper bound,
 | 
						|
then fetch the new PC from the list of instruction pointers by indexing with
 | 
						|
index-lower.
 | 
						|
The table does not contain the value of the upper bound,
 | 
						|
but the value of upper-lower as an unsigned integer.
 | 
						|
The default instruction pointer is used when the index is out of bounds.
 | 
						|
If the resulting PC is 0, then trap.
 | 
						|
.P
 | 
						|
CSB selects the new PC by searching.
 | 
						|
The table is searched for an entry with index value equal to the case index.
 | 
						|
That entry or, if none is found, the default entry contains the
 | 
						|
new PC.
 | 
						|
When the resulting PC is 0, a trap is performed.
 | 
						|
.P
 | 
						|
The choice of which case instruction to use for
 | 
						|
each source language case statement
 | 
						|
is up to the front end.
 | 
						|
If the range of the index value is dense, i.e
 | 
						|
.DS
 | 
						|
(highest value \- lowest value) / number of cases
 | 
						|
.DE 1
 | 
						|
is less than some threshold, then CSA is the obvious choice.
 | 
						|
If the range is sparse, CSB is better.
 | 
						|
.N 2
 | 
						|
.Dr 30
 | 
						|
   |--------------------|        |--------------------|  high address
 | 
						|
   | pointer for upb    |        |    pointer n-1     |
 | 
						|
   |--------------------|        |-  -  -  -  -  -  - |
 | 
						|
   |         .          |        |     index  n-1     |
 | 
						|
   |         .          |        |--------------------|
 | 
						|
   |         .          |        |          .         |
 | 
						|
   |         .          |        |          .         |
 | 
						|
   |         .          |        |          .         |
 | 
						|
   |         .          |        |--------------------|
 | 
						|
   |         .          |        |    pointer  1      |
 | 
						|
   |--------------------|        |-  -  -  -  -  -  - |
 | 
						|
   | pointer for lwb+1  |        |     index   1      |
 | 
						|
   |--------------------|        |--------------------|
 | 
						|
   | pointer for lwb    |        |    pointer  0      |
 | 
						|
   |--------------------|        |-  -  -  -  -  -  - |
 | 
						|
   |   upper - lower    |        |     index   0      |
 | 
						|
   |--------------------|        |--------------------|
 | 
						|
   |    lower bound     |        | number of entries  |
 | 
						|
   |--------------------|        |--------------------|
 | 
						|
   |  default pointer   |        |  default pointer   |  low address
 | 
						|
   |--------------------|        |--------------------|
 | 
						|
 | 
						|
       CSA descriptor                CSB descriptor
 | 
						|
.Df
 | 
						|
Figure 4. Descriptor layout for CSA and CSB
 | 
						|
.De
 |