.\" Introduction .\" .\" $Id$ .NH INTRODUCTION. .PP This document describes an EM interpreter which does extensive checking. The interpreter exists in two versions: the normal version with full checking and debugging facilities, and a fast stripped version that does interpretation only. This document assumes that the full version is used. .LP First the virtual EM machine embodied by the interpreter (called \fBint\fP) is described, followed by some remarks on performance. The second section gives some specific implementation decisions. Section three explains the usage of the built-in debugging tool. .LP Appendix A gives an overview of the various warnings \fBint\fP gives, with possible causes and solutions. Appendix B is a simple tutorial on the use of \fBint\fP. A separate manual page exists. .PP The document assumes a good understanding of what EM is and what the assembly code looks like [1]. Notions like 'procedure descriptor', 'mini', 'shortie' etc. are not explained. In the sequel, any word in \fIthis font\fP refers to the name of a variable, constant, function or whatever, used in the source code under the same name. .LP To avoid confusion: \fBint\fP interprets EM machine language (e.out files), \fInot\fP the assembly language (.e files) and \fInot\fP the compact code (.k files). .NH 2 The virtual EM machine. .PP The memory layout of the virtual EM machine represented by the interpreter differs in details from the description in [1]. Virtual memory is split up into two separate spaces: one space containing the instructions, the other all the data, including stack and heap (D-space). The procedure descriptors are preprocessed and stored in a separate array, \fIproctab[]\fP. Both spaces start off at address 0. This is possible because pointers in the two different spaces are distinguishable by context (and shadow-bytes: see 2.6). .NH 3 Instruction Space .PP Figure 1 shows the I-space, together with the position of some important EM registers. .Dr 12 NEXT --> |________________| <-- DB \e | | | | | | T | | <-- PC | | Program | | e | | | | Text | | x | | | | | | t 0 --> |________________| <--(PB) / .Df \fI Fig 1. Virtual instruction space (I-space).\fP .De .PP The I-space is just big enough to contain all the instructions. The size needed for the program text (\fINTEXT\fP) is found from the header-bytes of the loadfile. Legal values for the program counter (\fIPC\fP) consist of all addresses in the range from 0 through \fINTEXT\fP \- 1. If the \fIPC\fP is made to point to an illegal address, a trap will occur. .NH 3 The Procedure Table .PP The \fINProc\fP constant indicates how many procedure descriptors there are in the proctab array. Elements of this array contain for each procedure: the number of locals, the entry point and the entry point of the textually following procedure. This is used in testing the restriction that the program counter may not wander from procedure to procedure. .NH 3 The Data Space .PP Figure 2 shows the layout of the data space, which closely conforms to the EM Manual. .Dr 36 __________________ maxaddr(psize) --> | | <-- ML \e | | | S | Locals | | t | & | | a | RSBs | | c | | | k |________________| <-- SP / . . . . . Unused . . . . . . . . . . . . Unused . . . . . |________________| <-- HP | | \e | Heap | | |________________| <-- HB | | | | D | Arguments | | | Environ | | a | _ _ _ _ | | | | | t | | | | | | a | Global data | | | | | | | | 0 --> |________________| <--(EB) / .Df \fI Fig 2. Virtual dataspace (D-space).\fP .De .PP D-space begins at address 0, and ends at the largest address representable by the pointer size (\fIpsize\fP) being used; for a 2-byte pointer size this maximum address is .DS ((2 ^ 16 \- 1) / word size * word size) \- 1 .DE for a 4-byte pointer size it is .DS ((2 ^ 31 \- 1) / word size * word size) \- 1 .DE (not 2 ^ 32, to allow illegal pointers to be implemented in the future). The funny rounding construction is required to make ML+1 expressible as the initialisation value of LB and SP. .PP D-space is split into two partitions: Data and Stack (indicated by the brackets). The Data partition holds the global data area (GDA) and the heap. Its initial size is given by the loadfile constant SZDATA. Some space is added to it, because arguments and environment are stored here also. This total size is static while interpreting. However, as the heap may grow during execution (e.g. caused by dynamic allocation) this results in a variable size for the Data partition. Initially, the size for the Data partition is the sum of the space needed by the GDA (including the space needed for arguments and environment) and the initial heapspace. The lowest legal Data address is 0; the highest \fIHP\fP \- 1. .LP The Stack partition holds the stack. It begins at the highest available D-space address, and grows towards the low addresses, so the Stack partition is of variable size too. The lowest legal Stack address is the stackpointer (\fISP\fP), the highest is the memory limit (\fIML\fP). .NH 2 Physical lay-out .PP Each partition is mapped onto a piece of physical memory with the same name: \fItext\fP (fig. 1), \fIstack\fP and \fIdata\fP (fig. 2). These are the storage structures which \fBint\fP uses to physically store the contents of the virtual EM spaces. Figure 2 thus shows the mapping of D-space onto two different physical parts: \fIstack\fP and \fIdata\fP. The I-space is represented by one physical part: \fItext\fP. .LP Each time more space is needed, the actual partition is reallocated, with the new size being computed with the formula: .DS \fInew size\fP = 1.5 \(mu (\fIold size\fP + \fIextra\fP) .DE \fIextra\fP is the number of bytes exceeding the \fIold size\fP. One can prove that using this method, there is a linear relationship between allocation time and needed partition size. .PP A virtual D-space starting at address 0 is in correspondence with the definition in [1], p. 3\-6. The main reason for having D-space start at address 0, is that it induces a one-one correspondence between the heap \- and GDA addresses on the virtual machine (and hence the definition) on one hand, and the offset within the \fIdata\fP partition on the other. This implies that no extra calculation is needed to perform load and storage operations. .LP Some calculation however cannot be avoided, because the stack part of the D-space grows downwards by EM definition. The first address of the virtual stack (\fIML\fP, the maximum address for the given \fIpsize\fP) is mapped onto the beginning of the \fIstack\fP partition. When the stack grows (i.e. EM addresses get lower), the offset within the \fIstack\fP partition gets higher. By taking offset \fIML \- A\fP in the stack partition, one obtains the physical address corresponding to some virtual EM (stack) address \fIA\fP. .NH 2 Speed. .PP From several test results with both versions of the interpreter, the following may be concluded. The speed of the interpreter depends strongly on the type of program being interpreted. If plain CPU arithmetic is performed, the interpreter is relatively slow (1000 \(mu the cc version). When stack manipulation is at hand, the interpreter is quite fast (100 \(mu the cc version). .LP Most programs however will not be this extreme, so an interpretation time of somewhere between 300 and 500 times direct execution for a normal program is to be expected. .LP The fast version runs in about 60% of the time of the full version, at the expense of a considerably lower functionality. Tallying costs about 10%.