t-Code Virtual Machine - Instruction set and operation manual¶
This page describes tVM, a virtual machine that runs t-code, which is a low level 3-address code.
Is is called t-code because the virtual machine has a very simple set of instructions and thus it is necessary to use a lot of temporal registers to store intermediate results.
This document describes the instructions that the VM can process, as well as how to execute a program on it.
Executing a program in tVM¶
To execute a program, just run the VM with the name of the program file as an argument
./tvm myprogram.t
You can add the flag --debug to get details about the machine status
while it executes your program.
./tvm myprogram.t --debug
tVM program structure¶
A program for tVM is just a list of functions. Exactly one of the functions must
be named main
function main ;;; this is the main program
...
endfunction
function f1 ;;; another function
...
endfunction
... etc
The string ;;; starts a comment that will last until the end of the
line. Comments can appear anywhere.
Function structure¶
Each function has three sections:
Section
paramsis optional, and declares the parameters the function expects to find in the stack.Each parameter is declared with its name and type. If the parameter is an array, its name and element type, followed by the keyword
array. Array parameters are always passed by reference.Parameters are declared in the order they must be pushed.
Parameters must be pushed by the caller.
Function
maincan not haveparamssection.All parameters use exactly one memory position.
Section
varsis optional, and lists the function local variables, with their types. If the variable is an array, the type of its elements plus the number of elements is listed.Finally, there is the function body which is a list of instructions. The execution of the function ends when a
returninstruction is found.
Example function:
function f1
params
p1 integer
p2 float
a1 integer array
endparams
vars
v1 integer
a2 character 10
endvars
... instructions go here ...
return
endfunction
Memory usage, variables and temporal registers¶
tVM functions handle only parameters and local variables. All of them are stored in the stack.
Function result value is handled as an additional parameter, that has to be pushed and popped by the caller.
Function parameters use one memory position (32 bits).
Variables can use any number of memory positions.
Variables of sizes larger than 1 can be used as array base addresses and accessed with indexing instructions.
Apart from stack memory, tVM has temporal registers, identified as
%1,%2,%3, …There is no limit to the number of used temporal registers.
Temporal registers are local to each function activation, and saved automatically by the VM between calls.
Instruction set¶
Flow control instructions¶
Instruction
Effect
label label-name :Define a label in this position, to be jumped to.
goto label-nameContinue execution at given label.
ifFalse addr goto label-nameIf the content of variable/temporal
addris zero continue execution at given label.
All labels are local to functions. No jumps between functions are allowed.
Assignment instructions¶
Instruction
Effect
addr = 99Load integer value into variable/temporal
addr.
addr = 9.99Load float value into variable/temporal
addr.
addr = 'A'Load char value into variable/temporal
addr. Escaped chars'\t'and'\n'are allowed.
addr1 = addr2Copy value from variable/temporal
addr2to variable/temporaladdr1.
Aritmetic/relational/logical binary instructions¶
Instruction
Effect
addr1 = addr2 operation addr3Perform
operationwith variables/temporalsaddr2andaddr3and store result in variable/temporaladdr1.
Valid operations are:
+-*/Aritmetic operations with integer operands and integer result.
+.-.*./.Aritmetic operations with float operands and float result.
==<=<Comparison operators with integer operands and integer (0/1) result.
==.<=.<.Comparison operators with float operands and integer (0/1) result.
andorLogical operators with integer (0/1) operands and integer (0/1) result.
Aritmetic/logical unary instructions¶
Instruction
Effect
addr1 = operation addr2Perform unary
operationon variable/temporaladdr2and store result in variable/temporaladdr1.
Valid operations are:
-Sign change with integer operands and integer result.
-.Sign change with float operands and float result.
notLogical negation with integer (0/1) operands and integer (0/1) result.
floatInteger to float conversion with integer operand and float result.
Assignment instructions with indirections or indexing¶
Instruction
Effect
addr1[addr2] = addr3Copy content of variable/temporal
addr3toaddr2positions afteraddr1memory address. Ifaddr1is a variable or parameter, its address is used. If it is a temporal, it is assumed to contain a pointer to the base address to be used.
addr1 = addr2[addr3]Copy to variable/temporal
addr1the content ofaddr3positions afteraddr2memory address. Ifaddr2is a variable or parameter, its address is used. If it is a temporal, it is assumed to contain a pointer to the base address to be used.
temp = &varCopy to temporal
tempthe memory address ofvar.
addr1 = *tempCopy to variable/temporal
addr1the content of memory address contained in temporaltemp.
*temp = addr1Copy the content of variable/temporal
addr1to the memory address contained in temporaltemp.
Stack instructions¶
Instruction
Effect
pushparam addr1Push content of variable/temporal
addr1into the stack.
pushparamPush a zero into the stack (typically to reserve space, e.g. for a function result).
popparam addr1Get content of stack top into
addr1and pop it from the stack.
popparamPop top of the stack, ignoring its value.
Function calling instructions¶
Instruction
Effect
call fnameExecute function
fname.
returnEnd function execution and return control to caller.
Input/output instructions¶
Instruction
Effect
readi addr1Read an integer value and store it in
addr1.
readf addr1Read an float value and store it in
addr1.
readc addr1Read an character value and store it in
addr1.
writei addr1Write content of variable/temporal
addr1as integer.
writef addr1Write content of variable/temporal
addr1as float.
writec addr1Write content of variable/temporal
addr1as character.
writes "somestring"Write a string literal.
writelnWrite a newline.
Example programs¶
Factorial¶
;;; This program reads an integer and computes
;;; its factorial using a recursive function
function main
vars
x integer ;;; int x, y
y integer
endvars
readi x ;;; read x
pushparam ;;; make space for function result
pushparam x ;;; pass parameter x
call fact ;;; y = fact(x)
popparam ;;; remove passed parameter x
popparam y ;;; pop result and store in y
writei y ;;; print y
writeln
return
endfunction
function fact
params
_result integer ;;; _result is an internal variable used to
;;; access the result position in the stack
n integer ;;; received parameter
endparams
vars
f integer ;;; local variable
endvars
%1 = n == 0 ;;; compute %1 = (n==0)
ifFalse %1 goto else1
f = 1 ;;; n==0, so f=1
goto endif1
label else1 : ;;; n!=0, prepare recursive call
pushparam ;;; space for function result
%2 = n - 1 ;;; %2 = n-1
pushparam %2 ;;; pass n-1 as parameter
call fact ;;; f = fact(n-1)
popparam ;;; remove passed parameter n-1
popparam f ;;; pop result and store it in f
f = n * f ;;; f = n * f
label endif1 :
_result = f ;;; store f in space reserved for result
return
endfunction
Example - Computing number e¶
;;; This program computes number "e" with a precision "eps"
;;; using the formula e = sum 1/(i!) for all i>0
function main
vars
e float ;;; float e, eant, eps, f
eant float
eps float
f float
i integer ;;; int i
endvars
eant = 0.0
e = 1.0
eps = 0.00001
f = 1.0
i = 1
label while1 : ;;; while (eps < e-eant)
%1 = e -. eant
%1 = eps <. %1
ifFalse %1 goto endwhile1
eant = e
%2 = 1.0 /. f ;;; e = e + 1.0/f (e and f are float, note float
e = e +. %2 ;;; operations "+." and "/.")
i = i + 1 ;;; i = i + 1 (i is int -> integer addition "+")
%3 = float i ;;; f = f * i
f = f *. %3 ;;; (i is converted to float before
;;; performing a float product "*.")
goto while1
label endwhile1 : ;;; endwhile
writef e
writeln
return
endfunction
Example - Reversing a vector¶
;;; This program reads a number x, fills an array of 10
;;; elements with values x to x+9, reverses the array,
;;; and finally prints the array elements
function main
vars
x integer ;;; int x, i, n
i integer
n integer
a integer 10 ;;; int a[10]
endvars
readi x
n = 10 ;;; n=10
;;; fill array with numbers from x to x+9
i = 0 ;;; i=0
label for1 : ;;; while (i<n)
%1 = i < n
ifFalse %1 goto endfor1
%2 = x + i ;;; a[i] = x+i
a[i] = %2
%2 = 1 ;;; i = i + 1
i = i + %2
goto for1 ;;; endwhile
label endfor1 :
;;; reverse array, swapping x[i] with x[n-i-1] for all i<n/2
i = 0 ;;; i=0
label for2 : ;;; while (i<n/2)
%1 = 2
%2 = n / %1
%3 = i < %2
ifFalse %3 goto endfor2
x = a[i] ;;; x = a[i]
%1 = 1 ;;; a[i] = a[n-1-i]
%1 = n - %1
%1 = %1 - i
%2 = a[%1]
a[i] = %2
a[%1] = x ;;; a[n-1-i] = x
%2 = 1 ;;; i = i + 1
i = i + %2
goto for2 ;;; endwhile
label endfor2 :
;;; print array elements
i = 0 ;;; i=0
label for3 : ;;; while (i<n)
%1 = i < n
ifFalse %1 goto endfor3
%2 = a[i] ;;; write a[i]
writei %2
%2 = ' ' ;;; write ' '
writec %2
%2 = 1 ;;; i = i + 1
i = i + %2
goto for3 ;;; endwhile
label endfor3 :
writeln
return
endfunction
Example - Passing arrays per reference¶
;;; This program reads a number x, fills an array of 10
;;; elements with values x to x+9, passes it to a
;;; function that reverses the array and computes the sum of
;;; the elements, and finally prints the array elements
function reverse_and_sum
params
_result integer
b integer array
endparams
vars
i integer
n integer
x integer
s integer
endvars
;;; reverse array, swapping x[i] with x[n-i-1] for all i<n/2
;;; and add all elements in s
n = 10 ;;; n=10
s = 0 ;;; s=0
i = 0 ;;; i=0
label for2 : ;;; while (i<n/2)
%1 = 2
%2 = n / %1
%3 = i < %2
ifFalse %3 goto endfor2
%5 = b ;;; b is a pointer to a
x = %5[i] ;;; x = b[i]
s = s + x ;;; s = s + b[i]
%1 = 1 ;;; b[i] = b[n-1-i]
%1 = n - %1
%1 = %1 - i
%2 = %5[%1]
%5[i] = %2
%5[%1] = x ;;; b[n-1-i] = x
s = s + %2 ;;; s = s + b[n-1-i]
%2 = 1 ;;; i = i + 1
i = i + %2
goto for2 ;;; endwhile
label endfor2 :
_result = s
return
endfunction
function main
vars
x integer ;;; int x, i, n, sum
i integer
n integer
sum integer
a integer 10 ;;; int a[10]
endvars
readi x
n = 10 ;;; n=10
;;; fill array with numbers from x to x+9
i = 0 ;;; i=0
label for1 : ;;; while (i<n)
%1 = i < n
ifFalse %1 goto endfor1
%2 = x + i ;;; a[i] = x+i
a[i] = %2
%2 = 1 ;;; i = i + 1
i = i + %2
goto for1 ;;; endwhile
label endfor1 :
;;; call function
pushparam
%1 = &a ;;; pass array address (reference parameter)
pushparam %1
call reverse_and_sum
popparam
popparam sum ;;; sum = reverse_and_sum(a)
writei sum ;;; print sum
writeln
;;; print array elements
i = 0 ;;; i=0
label for3 : ;;; while (i<n)
%1 = i < n
ifFalse %1 goto endfor3
%2 = a[i] ;;; write a[i]
writei %2
%2 = ' ' ;;; write ' '
writec %2
%2 = 1 ;;; i = i + 1
i = i + %2
goto for3 ;;; endwhile
label endfor3 :
writeln
return
endfunction