PVM (for PAXI Virtual Machine) is a very simple architecture intended to provide an emulated target machine for PAXI compilers. Its consists of:
The first 500 locations of the data store are used as the system stack. The stack pointer SP holds the address of the top of stack item. (Notice that for a non-empty stack this means that SP holds the address of an occupied position, not the next available free position.) The stack grows downwards in memory (i.e. towards lower addresses) so the "top" of stack is the lowest occupied stack location.
Opcode | Mnemonic | Arguments | Description |
1 | mov | D, E | Move - copy value from E to D in data store |
2 | mvi | D, N | Move immediate - put constant value N in D in data store |
3 | mif | D, E | Move indirect from - copy with source indirect and destination direct |
4 | mit | D, E | Move indirect to - copy with source direct and destination indirect |
5 | lri | R, N | Load register immediate - put constant value N in register R |
6 | ldr | R, D | Load register - copy value from D in data store to register R |
7 | str | D, R | Store register - copy value from register R to D in data store |
8 | mvr | R, S | Move register - copy value from register S to register R |
9 | add | D, E | Add - add values in D and E in data store and leave sum in D |
10 | addri | R, N | Add register immediate - add constant N to value in register R |
11 | sub | D, E | Subtract - subtract value in E from value in D in data store and leave difference in D |
12 | mul | D, E | Multiply - multiply values in D and E in data store and leave product in D |
13 | div | D, E | Divide - divide value in D by value in E in data store and leave quotient in D |
14 | or | D, E | Or - leave OR of Boolean values in D and E in data store in D |
15 | and | D, E | And - leave AND of Boolean values in D and E in data store in D |
16 | not | D, 0 | Not - replace value in data store at D with its logical complement |
17 | b | A, 0 | Branch - transfer control to location A in code store |
18 | beq | A, D | Branch on equal - if value at D in data store is zero branch to A in code store |
19 | bne | A, D | Branch on not equal - if value at D in data store is not zero branch to A in code store |
20 | bgt | A, D | Branch on greater than - if value at D in data store is > 0 branch to A in code store |
21 | bge | A, D | Branch on greater than or equal - if value at D in data store is >= 0 branch to A in code store |
22 | blt | A, D | Branch on less than - if value at D in data store is < 0 branch to A in code store |
23 | ble | A, D | Branch on less than or equal - if value at D in data store is <= 0 branch to A in code store |
24 | pushd | D, 0 | Push data - push value at D in data store onto the stack |
25 | pushr | R, 0 | Push register - push value from register R onto the stack |
26 | pushi | N, 0 | Push immediate - push constant N onto the stack |
27 | popd | D, 0 | Pop data - pop top of stack into data store at location D |
28 | popr | R, 0 | Pop register - pop top of stack into register R |
29 | puti | D, 0 | Put integer - display integer at D in data store |
30 | puts | D, 0 | Put string - display NULL-terminated string beginning at D in data store |
31 | line | 0, 0 | New line - move cursor to beginning of next line |
32 | geti | D, 0 | Get integer - accept integer from keyboard and store at D in data store |
33 | gets | D, 0 | Get string - accept string from keyboard and store NULL-terminated at D in data store |
34 | call | A, 0 | Call - push IP and enter the subprogram at A in code store |
35 | ret | N, 0 | Return - return from subprogram call removing N parameters from the stack |
36 | stop | 0, 0 | Stop - end program |
The mif and mit instructions use indirect addressing. In indirect addressing a memory location is used as a pointer. mif treats its second argument (the source) as a pointer and uses direct addressing for its first argument (the target). mit treats is first argument as a pointer and uses direct addressing for its second argument.
The ldr (load register) and str (store register) instructions copy values between memory and registers. ldr R, D copies the value from data store D to register R and str D, R copies the value from register R to data store D. lri R, N (load register immediate) puts the constant value N into register R. mvr (move register) is used to copy a value from one register to another.
The logical instructions and and or work in the same manner as the arithmetic instructions. not D, 0 replaces data_store[D] with its logical complement. These instructions assume the value used for true or false is 1 or 0. The result is undefined for other values, i.e. if applied to values other than 1 or 0, it doesn't matter what values are left by and, or, and not.
The remaining branching instructions are all conditional branching instructions. Each takes two arguments: code store address A and data store address D. It compares D to 0 and if a test is successful transfers control to location A in the code store. The test is given by the name of the instruction. For example bgt A, D branches to A if data_store[D] is greater than 0.
There are three push instructions: pushd pushes a value from the data store, pushr pushes a register value, and pushi pushes a constant. There are two pop instructions: popd pops top of stack into the data store and popr pops top of stack into a register.
puti D, 0 displays the integer stored at data_store[D] and geti D, 0 accepts an integer from the keyboard and stores it in data_store[D]. line displays newline (i.e. moves the cursor to the beginning of the next line).
gets and puts do character string input and output. A string is stored in the data store as an array of ASCII codes terminated by a 0. Each ASCII code is stored in one integer position in the data store since "byte" has no meaning in PVM.
puts D, 0 displays the string beginning at D in the data store. gets D, 0 accepts a string from the keyboard and stores it, with a 0 terminator, in the data store beginning at D. gets accepts all characters entered up to the point where the user hits the enter key. This means that gets behaves like "cin.getline()" rather than "cin >>". It does not store a newline (ASCII 10) at the end of the string.