Last active
February 23, 2022 00:01
-
-
Save r-lyeh-archived/0af42b2788bb75219061 to your computer and use it in GitHub Desktop.
pcode interpreter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
P-code for PL/0 machine | |
[ref] https://en.wikipedia.org/wiki/P-code_machine | |
[ref] http://blackmesatech.com/2011/12/pl0/pl0.xhtml | |
The PL/0 virtual machine was originally specified by Nicklaus Wirth in his book | |
Algorithms + Data Structures = Programs; it's used as the target machine for a | |
PL/0 compiler. | |
Just as PL/0 is simpler than full Pascal, so also the virtual machine used by | |
the PL/0 compiler is simpler than the p-code machines used by various Pascal | |
compilers (e.g. Pascal-P from ETH Zürich and UCSD Pascal's P-System). Students | |
learning about p-code and virtual machines may find the PL/0 p-code easier | |
to grasp than the p-code systems used by full Pascal compilers. | |
# General | |
The machine has four registers and two storage areas. The two storage areas are: | |
- stack | |
- a stack used as a datastore for mutable data. Variables, information on function invocations, and temporary data are all placed on the stack. All values are integers. | |
- code area | |
- an immutable array of instructions; all instructions have the same format | |
The registers are: | |
P: program counter: points to an instruction in the program area | |
T: stack-top register: points to the current top of the stack | |
B: base address: points to the base address in the stack for the current invocation of a given procedure | |
I: instruction register: contains the currently executing instruction | |
Integer is the only datatype. | |
There is no input or output; a useful convention is for programs to leave their results in a pre-arranged location on the stack. | |
*/ | |
enum fct { | |
lit,opr,lod,sto,cal,Int,jmp,jpc | |
} ; | |
struct opcode { | |
int f:3; // {fct} | |
int l:2; // [0..3(levmax)] | |
int a:11; // [0..2047(amax)] | |
}; | |
enum { stacksize = 500 }; | |
int p, b, t; //{program-, base-, topstack-registers} | |
int i; //{instruction register} | |
int s[stacksize]; //[1..stacksize]; | |
int base(int l) { | |
int b1 = b; // {find base l levels down} | |
while( l > 0 ) { | |
b1 = s[b1]; | |
l--; | |
} | |
return b1; | |
} | |
#include <stdio.h> | |
int main() { | |
struct opcode code[] = { | |
//f l a | |
{ jmp, 1, 1 }, | |
{ Int, 1, 5 }, | |
{ lit, 1, 0 }, | |
{ sto, 1, 3 }, | |
{ lit, 1, 1 }, | |
{ sto, 1, 4 }, | |
{ lod, 1, 3 }, | |
{ lit, 1, 16 }, | |
{ opr, 1, 9 }, | |
{ jpc, 1, 19 }, | |
{ lod, 1, 3 }, | |
{ lit, 1, 1 }, | |
{ opr, 1, 2 }, | |
{ sto, 1, 3 }, | |
{ lod, 1, 4 }, | |
{ lod, 1, 3 }, | |
{ opr, 1, 4 }, | |
{ sto, 1, 4 }, | |
{ jmp, 1, 6 }, | |
{ opr, 1, 0 }, | |
}; | |
puts(" start pl/0"); | |
t = 0; b = 1; p = 0; | |
s[1] = s[2] = s[3] = 0; | |
do { | |
printf("[%d]\n", p ); | |
struct opcode i = code[p]; p = p + 1; | |
switch(i.f) { default: | |
break; case lit: { t++; s[t] = i.a; } | |
break; case opr: | |
switch(i.a) { default: | |
break; case 0: | |
{ // {return} | |
t = b - 1; p = s[t + 3]; b = s[t + 2]; | |
} | |
break; case 1: s[t] = -s[t]; | |
break; case 2: t--; s[t] = s[t] + s[t + 1]; | |
break; case 3: t--; s[t] = s[t] - s[t + 1]; | |
break; case 4: t--; s[t] = s[t] * s[t + 1]; | |
break; case 5: t--; s[t] = s[t] / s[t + 1]; | |
break; case 6: s[t] = (s[t] & 1); //ord(odd(s[t])); | |
break; case 8: t--; s[t] = (s[t] == s[t + 1]); | |
break; case 9: t--; s[t] = (s[t] != s[t + 1]); | |
break; case 10: t--; s[t] = (s[t] < s[t + 1]); | |
break; case 11: t--; s[t] = (s[t] >= s[t + 1]); | |
break; case 12: t--; s[t] = (s[t] > s[t + 1]); | |
break; case 13: t--; s[t] = (s[t] <= s[t + 1]); | |
} | |
break; case lod: t++; s[t] = s[base(i.l) + i.a]; | |
break; case sto: s[base(i.l)+i.a] = s[t]; printf("%d\n",s[t]); t--; | |
break; case cal: | |
{ //{generate new block mark} | |
s[t + 1] = base(i.l); s[t + 2] = b; s[t + 3] = p; | |
b = t + 1; p = i.a; | |
} | |
break; case Int: t = t + i.a; | |
break; case jmp: p = i.a; | |
break; case jpc: if( s[t] == 0) { p = i.a; t = t - 1; } | |
} | |
} while( p != 1 ); //< (sizeof(code)/sizeof(struct opcode)) ); | |
puts(" end pl/0"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment