-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstackvm.c
80 lines (61 loc) · 1.35 KB
/
stackvm.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
/*
* stack machine
*
gcc -Wall -O3 -std=gnu11 -ostackvm stackvm.c
*
* Author: Martin Uecker <uecker@eecs.berkeley.edu>
*/
#include <stdbool.h>
#include <assert.h>
#include <stdio.h>
enum byte_code {
ADD, SUB, MUL, DIV,
AND, OR , XOR, NOT,
JPC, JMP, CAL, RET,
LIT, INT, LOD,
};
int vm_run(int* code, int* stack, int i, int t, int a)
{
int pop(void) { return stack[--t]; }
void push(int x) { stack[t++] = x; }
int load(void) { return code[i++]; }
while (true) {
switch (load()) {
case ADD: { a += pop(); } break;
case SUB: { a -= pop(); } break;
case MUL: { a *= pop(); } break;
case DIV: { a /= pop(); } break;
case AND: { a &= pop(); } break;
case OR : { a |= pop(); } break;
case XOR: { a ^= pop(); } break;
case NOT: { a = ~a; } break;
case JPC: { int l = load(); if (a) i = l; } break;
case JMP: { i = load(); } break;
case LIT: { push(a); a = load(); } break;
case INT: { t -= load(); } break;
case LOD: { push(a); a = stack[t - 1 - load()]; } break;
case CAL: { a = vm_run(code, stack, load(), t, a); } break;
case RET: { return a; } break;
default: assert(0);
}
assert(t >= 0);
}
}
int main(void)
{
int stack[100];
int factorial[] = {
LIT, 1,
LOD, 1,
SUB,
JPC, 10,
LIT, 1,
RET,
CAL, 0, // 10:
LOD, 1,
MUL,
RET
};
printf("%d\n", vm_run(factorial, stack, 0, 0, 7));
return 0;
}