Interpreter

The compiler we construct will produce an intermediate code consisting of three address code (quads) that can be run on the interpreter defined below. As for the structure of the quads, each quad has the following form:

level operator operand1 operand2 operand3

Note: Not all operands will be used with each operator. Further, each operand consists of a mode and an adress which will be explained in detail later.

Each quad will execute through the interpreter as follows:

  1. The level is used to select which quads will be executed. Further, quads of different levels will be interspersed throughout the quad file.
  2. The PC (program counter) points to the next quad to be executed. The PC is initialized to the quad with the program begin opcode. Execution terminates when the end opcode is reached. Finally, quads whose level is greater than the current level will not be executed.
  3. The execution cycle is: fetch, decode, and execute.
  4. Our machine has enough memory to store 1500 quads and 5000 words of data.
  5. A runtime stack will be used for runtime storage allocation where: (a) each stack location stores one word (b) SP points to top of stack (c) AP points to the most recent activation record.
The runtime stack is as follows:

Addressing Modes are:

Number
Mode
Effective Operand
0
Immediate
address
1
global lvalue
address
2
global rvalue
stack[address]
3
local lvalue
ap +  address
4
local rvalue
stack[ap + address]

Our interpreter will read information from a file as follows:

line 1 to the program end quad
one quad per line
next line  
the number of initialized
memory words (n)
next n lines  
the initial contents of these words
                 
The interpreter will proceed as follows:
1) read quads into memory
2) read initial contents into memory
3) assign PC to the program begin quad
4) fetch, decode, and execute one quad at a time until program end quad
Our instruction set is:


      
Opcode 
Operands
Meaning
1
add
op1
op2
result
result <- op1 + op2
2
subtract
op1
op2
result
result <- op1 - op2
3
multiply
op1
op2
result
result <- op1 * op2
4
int divide
op1
op2
result
result <- op1 / op2
5
modulus
op1
op2
result
result <- op1 % op2
6
unary minus
op1
 
result
result <-  -op1 
7
increment
 
 
result
result <- result  + 1
8
decrement
 
 
result
result <- result  - 1
9
dereference
op1
 
result
results <- (op1)
10
blt
op1
op2
label
if op1 < op2 goto label
11
bgt
op1
op2
label
if op1 > op2 goto label
12
ble
op1
op2
label
if op1 <= op2 goto label
13
bge
op1
op2
label
if op1 >= op2 goto label
14
bne
op1
op2
label
if op1 != op2 goto label
15
beq
op1
op2
label
if op1 == op2 goto label
16
band
op1
op2
label
if op1 and op2 goto label
17
bor
op1
op2
label
if op1 or op2 goto label
18
bnot
op1
 
label
if op1 == 0 goto label
19
bra
 
 
label
goto label
20
load parameter
op1
 
 
push op1 on runtime stack
21
function call
op1
 
label
op1 = # of parameters already pushed
push op1
push PC
push AP
AP <- SP
PC <- label
22
function begin
op1
 
 
op1 = size of local data area
SP = SP + op1
23
function return
 
 
 
pop activation record off stack and
update AP, SP, and PC. Also, put
function result in location 0.
24
input
op1
 
 
op1 = # items to be read interactively.
Items will be read into the addresses found
on top of the stack.
25
output
op1
 
 
op1 = # items to be output. Items written
will come from the top of the stack.
26
assign
op1
 
result
result <- op1
27
program begin
 
 
 
marks beginning of the program
28
program end
 
 
 
end execution