.lg 0 .ta 8 16 24 32 40 48 56 64 72 80 .hw iden-ti-fi-er .nr a 0 1 .nr f 1 1 .de x1 'sp 2 'tl '''%' 'sp 2 .ns .. .wh 0 x1 .de fo 'bp .. .wh 60 fo .ll 79 .lt 79 .de HT .ti -4 .. .de PP .sp .ne 2 .ti +5 .. .de SE .bp \fB\\n+a. \\$1\fR .nr b 0 1 .. .de SB .br .ne 10 .sp 5 \fB\\na.\\n+b. \\$1\fR .. .de DC .ti -14 DECISION~\\$1: .. .de IN .in +6 .. .de OU .in -6 .. .tr ~ .sp 5 .rs .sp 10 .ce 3 Changes in EM-1 Addendum to Informatica Rapport IR-54 .sp 5 .PP This document describes a revision of EM-1. A list of differences is presented roughly in the order IR-54 describes the original architecture. A complete list of EM-1 pseudo's and instructions is also included. .SE Introduction .PP EM is a family of intermediate languages, resembling assembly language for a stack machine. EM defines the layout of data memory and a partitioning of instruction memory. EM has can do operations on five basic types: pointers, signed integers, unsigned integers, floating point numbers and sets of bits. The size of pointers is fixed in each member, in contrast to the sizes of the other types. Each member has one more fixed size: the word size. This is the mimimum size of any object on the stack. The sizes of all objects on the stack are assumed to multiples of the word size. We assume that pointer and word-sizes are both powers of two. .PP It is possible to load objects smaller then the word size from memory. These objects are converted to objects of the word size by clearing the most significant bytes. (A separate conversion instruction can do sign extension). While storing objects smaller then the word size are stored in memory, the most significant bytes are ignored. The size of such objects has to be a divisor of the word size. .PP Put in other terms, instructions such as LOC, LOL, LOE, STF, etc. manipulate WORDS. Up until now, a word was defined as 16 bits. It is now possible to define a word size other than 16 bits. For example, MES 2,1,2 defines a word to be 8 bits and a pointer to be 16 bits. As another example, MES 2,4,4 defines a word to be 32 bits and a pointer to be 32 bits. .PP If a compiler receives flags telling it to use 32 bit integers, it now has a choice of setting the word length to 16 bits and using LDL etc for dealing with integers, or setting the word length to 32 bits and using LOL etc for integers. For example, x:=a+b for 32-bit integers would become: MES 2,2,4 MES 2,4,4 LDL a LOL a LDL b LOL b ADI 4 ADI 4 SDL x STL x In many cases, the target machine code that is finally produced from either of the above sequences will not show any traces of the stack machine, however for some instructions actual pushes and pops at run time will be necessary. Choosing a wider EM word will usually produce fewer stack operations than a narrower word, but it eliminates the possibility of doing arithmetic on quantities smaller than a word. If, for example, a compiler chooses a 32-bit EM word, it will be difficult to add two 16 bit integers with ADI, since the argument must be multiple of the word size. (The operation can be done by converting the operands to 32 bits using CII, adding the 32-bit numbers, and reconverting the result.) On the other hand, choosing a 16-bit EM word makes it possible to do both 16-bit adds (ADI 2) and 32-bit adds (ADI 4), but the price paid is that 32-bit operations will be viewed as double precision, and may be slightly less efficient on target machines with a 32-bit word, i.e. the EM to target translator may not take full advantage of the 32 bit facilities. .PP Note that since LOC pushes a WORD on the stack, the argument of LOC must fit ina word. LOC 256 on an EM machine with a 1-byte word length is not allowed. LDC 256 is allowed, however. .PP A general rule of thumb is that the compiler should choose an EM word length equal to the width of a single precision integer. Obviously, compilers should be well parameterized to allow the integer size(s) and word size(s) to be changed by just changing a few constants. .PP The size of a instruction space pointer in is the same as the size of a data space pointer. .PP EM assumes two's complement arithmetic on signed integers, but does not define an ordering of the bytes in a integer. The lowest numbered byte of a two-byte object can contain either the most or the least significant part. .SE Memory .PP EM has two separate addressing spaces, instruction and data. The sizes of these spaces are not specified. The layout of instruction space in not defined. Any interpreter or translator may assume a layout fitting his/her needs. The layout of data memory is specified by EM. EM data memory consists of a sequence of 8-bit bytes each separately addressable. Certain alignment restrictions exist for object consisting of multiple bytes. Objects smaller then the word size can only be addressed at multiples of the object size. For example: in a member with a four-byte word size, two-byte integers can only be accessed from even addresses. Objects larger then the word size can only be placed at multiples of the word size. For example: in a member with a four-byte word size, eight-byte floating point numbers can be fetched at addresses 0, 4, 8, 12, etc. .SB "Procedure identifiers" .PP Procedure identifiers in EM have the same size as pointers. Any implementation of EM is free to use any method of identifying procedures. Common methods are indices into tables containing further information and addresses of the first instructions of procedures. .SB "Heap and Stack in global data" .PP The stack grows downward, the heap grows upward. The stack pointer points to the lowest occupied word on the stack. The heap pointer marks the first free word in the heap area. .br .ne 39 .sp 1 .nf 65534 -> |-------------------------------| |///////////////////////////////| |//// unimplemented memory /////| |///////////////////////////////| SB -> |-------------------------------| | | | stack and local area | <- LB | | | | |-------------------------------| <- SP |///////////////////////////////| |// implementation dependent //| |///////////////////////////////| |-------------------------------| <- HP | | | heap area | | | | | |-------------------------------| | | | global area | | | EB -> |-------------------------------| | | | | | program text | <- PC | | | | PB -> |-------------------------------| |///////////////////////////////| |////////// undefined //////////| |///////////////////////////////| 0 -> |-------------------------------| Fig. \nf. Example of memory layout showing typical register positions during execution of an EM program. .fi .SB "Data addresses as arguments" .PP Anywhere previous versions of the EM assembly language allowed identifiers of objects in data space, it is also possible to use 'identifier+constant' or 'identifier-constant'. For example, both "CON LABEL+4" and "LAE SAVED+3" are allowed. More complicated expressions are illegal. .SB "Local data area" .PP The mark block has been banished. When calling a procedure, the calling routine first has to push the actual parameters. All language implementations currently push their arguments in reverse order, to be compatible with C. Then the procedure is called using a CAL or CAI instruction. Either the call or the procedure prolog somehow has to save the return address and dynamic link. The prolog allocates the space needed for locals and is free to surround this space with saved registers and other information it deems necessary. .PP The locals are now accessed using negative offsets in LOL, LDL, SDL, LAL, LIL, SIL and STL instructions. The parameters are accessed using positive offsets in LOL, LDL, SDL, LAL, LIL, STL and STL instructions. The prolog might have stored information in the area between parameters and locals. As a consequence there are two bases, AB(virtual) and LB. AB stands for Argument Base and LB stands for Local Base. Positive arguments to LOL etc ... are interpreted as offsets from AB, negative arguments as offsets from LB. .PP The BEG instruction is not needed to allocate the locals because storage for locals is set aside in the prolog. The instruction still exists under the name ASP (Adjust Stack Pointer). .PP Procedures return using the RET instruction. The RET pops the function result from the stack and brings the stack pointer and other relevant registers to the state they had just before the procedure was called. The RET instruction expects that - aside from possible function results - the stack pointer has the value it had after execution of the prolog. RET finally returns control to the calling routine. The actual parameters have to be removed from the stack by the calling routine, and not by the called procedure. .sp 1 .ne 38 .nf |===============================| | actual argument n | |-------------------------------| | . | | . | | . | |-------------------------------| | actual argument 1 | ( <- AB ) |===============================| |///////////////////////////////| |// implementation dependent //| |///////////////////////////////| <- LB |===============================| | | | local variables | | | |-------------------------------| | | | compiler temporaries | | | |===============================| |///////////////////////////////| |// implementation dependent //| |///////////////////////////////| |===============================| | | | dynamic local generators | | | |===============================| | operand | |-------------------------------| | operand | <- SP |===============================| A sample procedure frame. .fi .sp 1 This scheme allows procedures to be called with a variable number of parameters. The parameters have to be pushed in reverse order, because the called procedure has to be able to locate the first one. .PP .PP Since the mark block has disappeared, a new mechanism for static links had to be created. All compilers use the convention that EM procedures needing a static link will find a link in their zero'th parameter, i.e. the last one pushed on the stack. This parameter should be invisible to users of the compiler. The link needs to be in a fixed place because the lexical instructions have to locate it. The LEX instruction is replaced by two instructions: LXL and LXA. \&"LXL~n" finds the LB of a procedure n static levels removed. \&"LXA~n" finds the (virtual) AB. The value used for static link is LB. .PP When a procedure needing a static link is called, first the actual parameters are pushed, then the static link is pushed using LXL and finally the procedure is called with a CAL with the procedure's name as argument. .br .ne 40 .nf |===============================| | actual argument n | |-------------------------------| | . | | . | | . | |-------------------------------| | actual argument 1 | |-------------------------------| | static link | ( <- AB ) |===============================| |///////////////////////////////| |// implementation dependent //| |///////////////////////////////| <- LB |===============================| | | | local variables | | | |-------------------------------| | | | compiler temporaries | | | |===============================| |///////////////////////////////| |// implementation dependent //| |///////////////////////////////| |===============================| | | | dynamic local generators | | | |===============================| | operand | |-------------------------------| | operand | <- SP |===============================| A procedure frame with static link. .fi .sp 1 .sp 1 .PP Pascal and other languages have to use procedure instance identifiers containing the procedure identifier 'ul and the static link the procedure has to be called with. A static link having a value of zero signals that the called procedure does not need a static link. C uses the same convention for pointers to C-routines. In pointers to C-routines the static link is set to zero. .PP Note: The distance from LB to AB must be known for each procedure, otherwise LXA can not be implemented. Most implementations will have a fixed size area between the parameter and local storage. The zone between the compiler temporaries and the dynamic local generators can be used to save a variable number of registers. .PP .ne 11 Prolog examples: .sp 2 .nf proc1 proc2 mov lb,-(sp) mov lb,-(sp) mov sp,lb mov sp,lb sub $loc_size,sp sub $loc_size,sp mov r2,-(sp) ; save r2 mov r2,-(sp) mov r4,-(sp) ; save r4 .fi .SB "Return values" .PP The return value popped by RET is stored in an unnamed 'function return area'. This area can be different for different sized objects returned, e.g. one register for two byte objects, two registers for four byte objects, memory for larger objects. The area is available for 'READ-ONCE' access using the LFR instruction. The result of a LFR is only defined if the sizes used to store and fetch are identical. The only instructions guaranteed not to destroy the contents of any 'function return area' are ASP and BRA. Thus parameters can be popped before fetching the function result. The maximum size of all function return areas is implementation dependant, but allows procedure instance identifiers and all implemented objects of type integer, unsigned, float and pointer to be returned. .SE "EM Assembly Language" .nr b 0 1 .SB "Object types and instructions" .PP EM knows five basic object types: pointers, signed integers, unsigned integers, floating point numbers and sets of bits. Operations on objects of the last four types do not assume a specific size. Pointers (including procedure identifiers) have a fixed size in each implementation. Instructions acting on one or more objects of the last four types need explicit size information. This information can be given either as the argument of the instruction or on top of the stack. .sp 1 For example: .nf addition of integers LOL a, LOL b, ADI 2 subtraction of two floats LDL a, LDL b, SBF 4 integer to float LOL a, LOC 2, LOC 4, CIF, SDL b .fi .sp Note that conversion instructions always expect size before and size after conversion on the stack. .sp No obligation exists to implement all operations on all possible sizes. .PP The EM assembly language allows constants as instruction arguments up to a size of four bytes. In all EM's it is possible to initialize any type and size object. BSS, HOL, CON and ROM allow type and size indication in initializers. .SB "Conversion instructions" .PP The conversion operators can convert from any type and size to any type and size. The types are specified by the instruction, the sizes should be in words on top of the stack. Normally the sizes are multiples of the word size, There is one exception: the CII instructions sign-extends if the size of the source is a divisor of the word size. .SB "CSA and CSB" .PP The tables used by these instructions do not contain the procedure identifier any more. See also "Descriptors". .SB EXG .PP The EXG instruction is deleted from the EM instruction set. If future applications show any need for this instruction, it will be added again. .SB "FIL" .PP A FIL instruction has been introduced. When using separate compilation, the LIN feature of EM was insufficient. FIL expects as argument an address in global data. This address is stored in a fixed place in memory, where it can be used by any implementation for diagnostics etc. Like LIN, it provides access to the ABS fragment at the start of external data. .SB "LAI and SAI" .PP LAI and SAI have been dropped, they thwarted register optimization. .SB LNC .PP The LNC instruction is deleted from the instruction set. LOC -n wil do what it is supposed to. .SB "Branch instructions" .PP The branch instructions are allowed to branch both forward and backward. Consequently BRF and BRB are deleted and a BRA instruction is added. BRA branches unconditionally in any direction. .SB LDC .PP Loads a double word constant on the stack. .SB LEX .PP LXA and LXL replace LEX. .SB LFR .PP LFR loads the function result stored by RET. .SB "LIL and SIL" .PP They replace LOP and STP. (Name change only) .SB "Traps and Interrupts" .PP The numbers used for distinguishing the various types of traps and interrupts have been reassigned. The new instructions LIM and SIM allow setting and clearing of bits in a mask. The bits in the mask control the action taken upon encountering certain errors at runtime. A 1 bit causes the corresponding error to be ignored, a 0 bit causes the run-time system to trap. .SB LPI .PP Loads a procedure identifier on the stack. LOC cannot be used to do this anymore. .SB "ZER and ZRF" .PP ZER loads S zero bytes on the stack. ZRF loads a floating point zero of size S. .SB "Descriptors" .PP All instructions using descriptors have the size of the integer used in the descriptor as argument. The descriptors are: case descriptors (CSA and CSB), range check descriptors (RCK) and array descriptors ( LAR, SAR, AAR). .SB "Case descriptors" .PP The value used in a case descriptor to indicate the absence of a label is zero instead of -1. .SE "EM assembly language" .SB "Instruction arguments" .PP The previous EM had different instructions for distinguishing between operand on the stack and explicit argument in the instruction. For example, LOI and LOS. This distinction has been removed. Several instructions have two possible forms: with explicit argument and with implicit argument on top of the stack. The size of the implicit argument is the word size. The implicit argument is always popped before all other operands. Appendix 1 shows what is allowed for each instruction. .SB Notation .PP First the notation used for the arguments of instructions and pseudo instructions. .in +12 .ti -11 ~~=~~an integer number in the range -32768..32767 .ti -11 ~~=~~an offset -2**31..2**31~-~1 .ti -11 ~~=~~an identifier .ti -11 ~~=~~ or or + or - .ti -11 ~~=~~integer constant, unsigned constant, floating point constant .ti -11 ~~=~~string constant (surrounded by double quotes), .ti -11 ~~=~~instruction label ('*' followed by an integer in the range 0..32767). .ti -11 ~~=~~procedure number ('$' followed by a procedure name) .ti -11 ~~=~~, , or . .ti -11 <...>*~=~~zero or more of <...> .ti -11 <...>+~=~~one or more of <...> .ti -11 [...]~~=~~optional ... .in -12 .SB Labels .PP No label, instruction or data, can have a (pseudo) instruction on the same line. .SB Constants .PP All constants in EM are interpreted in the decimal base. .PP In BSS, HOL, CON and ROM pseudo-instructions numbers must be followed by I, U or F indicating Integer, Unsigned or Float. If no character is present I is assumed. This character can be followed by an even positive number or a 1. The number indicates the size in bytes of the object to be initialized, up to 32766. Double precision integers can no longer be indicated by a trailing L. As said before CON and ROM also allow expressions of the form: \&"LABEL+offset" and "LABEL-offset". The offset must be an unsigned decimal number. The 'IUF' indicators cannot be used with the offsets. .PP Areas reserved in the global data area by HOL or BSS can be initialized. BSS and HOL have a third parameter indicating whether the initialization is mandatory or optional. .PP Since EM needs aligment of objects, this alignment is enforced by the pseudo instructions. All objects are aligned on a multiple of their size or the word size whichever is smaller. Switching to another type of fragment or placing a label forces word-alignment. There are three types of fragments in global data space: CON, ROM and BSS-HOL. .sp .SB "Pseudo instructions" .PP The LET, IMC and FWC pseudo's have disappeared. The only application of these pseudo's was in postponing the specification of the size of the local storage to just before the END of the procedure. A new mechanism has been introduced to handle this problem. .ti +5 The pseudos involved in separate compilation and linking have been reorganized. .ti +5 PRO and END are altered and reflect the new calling sequence. EOF has disappeared. .ti +5 BSS and HOL allow initialization of the requested data areas. .sp 2 Four pseudo instructions request global data: .sp 2 BSS ,, .IN Reserve bytes. is the value used to initialize the area. must be a multiple of the size of . is 0 if the initialization is not strictly necessary, 1 otherwise. .OU .sp HOL ,, .IN Idem, but all following absolute global data references will refer to this block. Only one HOL is allowed per procedure, it has to be placed before the first instruction. .OU .sp CON + .IN Assemble global data words initialized with the constants. .OU .sp ROM + .IN Idem, but the initialized data will never be changed by the program. .OU .sp 2 Two pseudo instructions partition the input into procedures: .sp 2 PRO [,] .IN Start of procedure. is the procedure name. is the number of bytes for locals. The number of bytes for locals must be specified in the PRO or END pseudo-instruction. When specified in both, they must be identical. .OU .sp END [] .IN End of Procedure. is the number of bytes for locals. The number of bytes for locals must be specified in either the PRO or END pseudo-instruction or both. .OU .PP Names of data and procedures in a EM module can either be internal or external. External names are known outside the module and are used to link several pieces of a program. Internal names are not known outside the modules they are used in. Other modules will not 'see' an internal name. .ti +5 In order to reduce the number of passes needed, it must be known at the first occurrence whether a name is internal or external. If the first occurrence of a name is in a definition, the name is considered to be internal. If the first occurrence of a name is a reference, the name is considered to be external. If the first occurrence is in one of the following pseudo instructions, the effect of the pseudo has precedence. .sp 2 EXA .IN External name. is external to this module. Note that may be defined in the same module. .OU .sp EXP .IN External procedure identifier. Note that may be defined in the same module. .OU .sp INA .IN Internal name. is internal to this module and must be defined in this module. .OU .sp INP .IN Internal procedure. is internal to this module and must be defined in this module. .OU .sp 2 Two other pseudo instructions provide miscellaneous features: .sp 2 EXC , .IN Two blocks of instructions preceding this one are interchanged before being processed. gives the number of lines of the first block. gives the number of lines of the second one. Blank and pure comment lines do not count. This instruction is obsolete. Its use is strongly discouraged. .OU .sp MES ,* .IN A special type of comment. Used by compilers to communicate with the optimizer, assembler, etc. as follows: .br MES 0 - .IN An error has occurred, stop further processing. .OU .br MES 1 - .IN Suppress optimization .OU .br MES 2,, .IN Use word-size and pointer size . .OU .br MES 3,,, - .IN Indicates that a local variable is never referenced indirectly. is offset in bytes from LB if positive and offset from AB if negative. gives the size of the variable. indicates the class of the variable. .OU .br MES 4,, .IN Number of source lines in file (for profiler). .OU .br MES 5 - .IN Floating point used. .OU .br MES 6,* - .IN Comment. Used to provide comments in compact assembly language (see below). .OU .sp 1 Each back end is free to skip irrelevant MES pseudos. .OU .SB "The Compact Assembly Language" .PP The assembler accepts input in a highly encoded form. This form is intended to reduce the amount of file transport between the compiler and assembler, and also reduce the amount of storage required for storing libraries. Libraries are stored as archived compact assembly language, not machine language. .PP When beginning to read the input, the assembler is in neutral state, and expects either a label or an instruction (including the pseudoinstructions). The meaning of the next byte(s) when in neutral state is as follows, where b1, b2 etc. represent the succeeding bytes. .sp 0 Reserved for future use 1-129 Machine instructions, see Appendix 2, alphabetical list 130-149 Reserved for future use 150-161 BSS,CON,END,EXC,EXA,EXP,HOL,INA,INP,MES,PRO,ROM 162-179 Reserved for future pseudoinstructions 180-239 Instruction labels 0 - 59 (180 is local label 0 etc.) 240-244 See the Common Table below 245-255 Not used After a label, the assembler is back in neutral state; it can immediately accept another label or an instruction in the very next byte. There are no linefeeds used to separate lines. .PP If an opcode expects no arguments, the assembler is back in neutral state after reading the one byte containing the instruction number. If it has one or more arguments (only pseudos have more than 1), the arguments follow directly, encoded as follows: .sp 0-239 Offsets from -120 to 119 .br 240-255 See the Common Table below .sp 2 If an opcode has one optional argument, a special byte is used to announce that the argument is not present. .ce 1 Common Table for Neutral State and Arguments .sp .nf 240 b1 Instruction label b1 (Not used for branches) 241 b1 b2 16 bit instruction label (256*b2 + b1) 242 b1 Global label .0-.255, with b1 being the label 243 b1 b2 Global label .0-.32767 with 256*b2+b1 being the label 244 Global symbol not of the form .nnn . \" Only the previous can occur in neutral state. 245 b1 b2 (16 bit constant) 256*b2+b1 246 b1 b2 b3 b4 (32 bit constant) (256*(256*(256*b4)+b3)+b2)+b1 247 Global label + (possibly negative) constant 248 Procedure name (not including $) 249 String used in CON or ROM (no quotes) 250 Integer constant, size bytes 251 Unsigned constant, size bytes 252 Floating constant, size bytes 255 Delimiter for argument lists or indicates absence of optional argument .fi .PP The notation consists first of a length field, and then an arbitrary string of bytes. The length is specified by a . .PP .ne 8 The pseudoinstructions fall into several categories, depending on their arguments: .sp Group 1 -- EXC, BSS, HOL have a known number of arguments Group 2 -- EXA, EXP, INA, INP start with a string Group 3 -- CON, MES, ROM have a variable number of various things Group 4 -- END, PRO have a trailing optional argument. Groups 1 and 2 use the encoding described above. Group 3 also uses the encoding listed above, with a byte after the last argument to indicate the end of the list. Group 4 uses a byte if the trailing argument is not present. .ad .fi .sp 2 .ne 12 .nf Example ASCII Example compact (LOC = 66, BRA = 18 here): 2 182 1 181 LOC 10 66 130 LOC -10 66 110 LOC 300 66 245 44 1 BRA 19 18 139 300 241 44 1 .3 242 3 CON 4,9,*2,$foo 151 124 130 240 2 248 3 102 111 111 255 LOC .35 66 242 35 .fi .nr a 0 1 .SE "ASSEMBLY LANGUAGE INSTRUCTION LIST" .PP For each instruction in the list the range of operand values in the assembly language is given. All constants, offsets and sizes are in the range -2**31~..~2**31-1. The column headed \fIassem\fP contains the mnemonics defined in 4.1. The following column indicates restrictions in the range of the operand. Addresses have to obey the restrictions mentioned in chapter 2 - Memory -. The size parameter of most instructions has to be a multiple of the word size. The classes of operands are indicated by letters: .ds b \fBb\fP .ds c \fBc\fP .ds d \fBd\fP .ds g \fBg\fP .ds f \fBf\fP .ds l \fBl\fP .ds n \fBn\fP .ds i \fBi\fP .ds p \fBp\fP .ds r \fBr\fP .ds s \fBs\fP .ds z \fBz\fP .ds - \fB-\fP .nf \fIassem\fP constraints rationale \&\*c off 1-word constant \&\*d off 2-word constant \&\*l off local offset \&\*g arg >= 0 global offset \&\*f off fragment offset \&\*n num >= 0 counter \&\*s off > 0 object size \&\*z off >= 0 object size \&\*i off > 0 object size * \&\*p pro pro identifier \&\*b lab >= 0 label number \&\*r num 0,1,2 register number \&\*- no operand .fi .PP The * at the rationale for \*i indicates that the operand can either be given as argument or on top of the stack. If the operand has to be fetched from the stack, it is assumed to be a word-sized unsigned integer. .PP Instructions that check for undefined operands and underflow or overflow are indicated by (*). .nf GROUP 1 - LOAD LOC \*c : Load constant (i.e. push one word onto the stack) LDC \*d : Load double constant ( push two words ) LOL \*l : Load word at \*l-th local (l<0) or parameter (l>=0) LOE \*g : Load external word \*g LIL \*l : Load word pointed to by \*l-th local or parameter LOF \*f : Load offsetted. (top of stack + \*f yield address) LAL \*l : Load address of local or parameter LAE \*g : Load address of external LXL \*n : Load lexical. (address of LB \*n static levels back) LXA \*n : Load lexical. (address of AB \*n static levels back) LOI \*s : Load indirect \*s bytes (address is popped from the stack) LOS \*i : Load indirect. \*i-byte integer on top of stack gives object size LDL \*l : Load double local or parameter (two consecutive words are stacked) LDE \*g : Load double external (two consecutive externals are stacked) LDF \*f : Load double offsetted (top of stack + \*f yield address) LPI \*p : Load procedure identifier GROUP 2 - STORE STL \*l : Store local or parameter STE \*g : Store external SIL \*l : Store into word pointed to by \*l-th local or parameter STF \*f : Store offsetted STI \*s : Store indirect \*s bytes (pop address, then data) STS \*i : Store indirect. \*i-byte integer on top of stack gives object size SDL \*l : Store double local or parameter SDE \*g : Store double external SDF \*f : Store double offsetted GROUP 3 - INTEGER ARITHMETIC ADI \*i : Addition (*) SBI \*i : Subtraction (*) MLI \*i : Multiplication (*) DVI \*i : Division (*) RMI \*i : Remainder (*) NGI \*i : Negate (two's complement) (*) SLI \*i : Shift left (*) SRI \*i : Shift right (*) GROUP 4 - UNSIGNED ARITHMETIC ADU \*i : Addition SBU \*i : Subtraction MLU \*i : Multiplication DVU \*i : Division RMU \*i : Remainder SLU \*i : Shift left SRU \*i : Shift right GROUP 5 - FLOATING POINT ARITHMETIC (Format not defined) ADF \*i : Floating add (*) SBF \*i : Floating subtract (*) MLF \*i : Floating multiply (*) DVF \*i : Floating divide (*) NGF \*i : Floating negate (*) FIF \*i : Floating multiply and split integer and fraction part (*) FEF \*i : Split floating number in exponent and fraction part (*) GROUP 6 - POINTER ARITHMETIC ADP \*f : Add \*c to pointer on top of stack ADS \*i : Add \*i-byte value and pointer SBS \*i : Subtract pointers in same fragment and push diff as size \*i integer GROUP 7 - INCREMENT/DECREMENT/ZERO INC \*- : Increment top of stack by 1 (*) INL \*l : Increment local or parameter (*) INE \*g : Increment external (*) DEC \*- : Decrement top of stack by 1 (*) DEL \*l : Decrement local or parameter (*) DEE \*g : Decrement external (*) ZRL \*l : Zero local or parameter ZRE \*g : Zero external ZRF \*i : Load a floating zero of size \*i ZER \*i : Load \*i zero bytes GROUP 8 - CONVERT ( stack: source, source size, dest. size (top) ) CII \*- : Convert integer to integer (*) CUI \*- : Convert unsigned to integer (*) CFI \*- : Convert floating to integer (*) CIF \*- : Convert integer to floating (*) CUF \*- : Convert unsigned to floating (*) CFF \*- : Convert floating to floating (*) CIU \*- : Convert integer to unsigned CUU \*- : Convert unsigned to unsigned CFU \*- : Convert floating to unsigned GROUP 9 - LOGICAL AND \*i : Boolean and on two groups of \*i bytes IOR \*i : Boolean inclusive or on two groups of \*i bytes XOR \*i : Boolean exclusive or on two groups of \*i bytes COM \*i : Complement (one's complement of top \*i bytes) ROL \*i : Rotate left a group of \*i bytes ROR \*i : Rotate right a group of \*i bytes GROUP 10 - SETS INN \*i : Bit test on \*i byte set (bit number on top of stack) SET \*i : Create singleton \*i byte set with bit n on (n is top of stack) GROUP 11 - ARRAY LAR \*i : Load array element, descriptor contains integers of size \*i SAR \*i : Store array element AAR \*i : Load address of array element GROUP 12 - COMPARE CMI \*i : Compare \*i byte integers. Push negative, zero, positive for <, = or > CMF \*i : Compare \*i byte reals CMU \*i : Compare \*i byte unsigneds CMS \*i : Compare \*i byte sets. can only be used for equality test. CMP \*- : Compare pointers TLT \*- : True if less, i.e. iff top of stack < 0 TLE \*- : True if less or equal, i.e. iff top of stack <= 0 TEQ \*- : True if equal, i.e. iff top of stack = 0 TNE \*- : True if not equal, i.e. iff top of stack non zero TGE \*- : True if greater or equal, i.e. iff top of stack >= 0 TGT \*- : True if greater, i.e. iff top of stack > 0 GROUP 13 - BRANCH BRA \*b : Branch unconditionally to label \*b BLT \*b : Branch less (pop 2 words, branch if top > second) BLE \*b : Branch less or equal BEQ \*b : Branch equal BNE \*b : Branch not equal BGE \*b : Branch greater or equal BGT \*b : Branch greater ZLT \*b : Branch less than zero (pop 1 word, branch negative) ZLE \*b : Branch less or equal to zero ZEQ \*b : Branch equal zero ZNE \*b : Branch not zero ZGE \*b : Branch greater or equal zero ZGT \*b : Branch greater than zero GROUP 14 - PROCEDURE CALL CAI \*- : Call procedure (procedure instance identifier on stack) CAL \*p : Call procedure (with name \*p) LFR \*s : Load function result RET \*z : Return (function result consists of top \*z bytes) GROUP 15 - MISCELLANEOUS ASP \*f : Adjust the stack pointer by \*f ASS \*i : Adjust the stack pointer by \*i-byte integer BLM \*z : Block move \*z bytes; first pop destination addr, then source addr BLS \*i : Block move, size is in \*i-byte integer on top of stack CSA \*i : Case jump; address of jump table at top of stack CSB \*i : Table lookup jump; address of jump table at top of stack DUP \*s : Duplicate top \*s bytes DUS \*i : Duplicate top \*i bytes FIL \*g : File name (external 4 := \*g) LIM \*- : Load 16 bit ignore mask LIN \*n : Line number (external 0 := \*n) LNI \*- : Line number increment LOR \*r : Load register (0=LB, 1=SP, 2=HP) MON \*- : Monitor call NOP \*- : No operation RCK \*i : Range check; trap on error RTT \*- : Return from trap SIG \*- : Trap errors to proc nr on top of stack (-2 resets default). Static link of procedure is below procedure number. Old values returned SIM \*- : Store 16 bit ignore mask STR \*r : Store register (0=LB, 1=SP, 2=HP) TRP \*- : Cause trap to occur (Error number on stack) .fi