-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathvm.c
82 lines (77 loc) · 2.83 KB
/
vm.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
76
77
78
79
80
81
82
#include <stdio.h>
#include <assert.h>
#include <stdint.h>
int imTop = 0;
int16_t im[32768], m[65536];
#define BIT(i) (0x0001<<(i))
#define debug(...) printf(__VA_ARGS__)
// #define debug(...)
int run(uint16_t *im, int16_t *m) {
int16_t D = 0, A = 0, PC = 0;
uint16_t I = 0;
uint16_t a, c, d, j;
while (1) {
int16_t aluOut = 0, AM = 0;
if (PC >= imTop) {
debug("exit program !\n");
break;
}
I = im[PC];
debug("PC=%04X I=%04X", PC, I);
PC ++;
if ((I & 0x8000) == 0) { // A 指令
A = I;
} else { // C 指令
a = (I & 0x1000) >> 12;
c = (I & 0x0FC0) >> 6;
d = (I & 0x0038) >> 3;
j = (I & 0x0007) >> 0;
AM = (a == 0) ? A : m[A];
switch (c) { // 處理 c1..6, 計算 aluOut
case 0x2A: aluOut = 0; break; // "0", "101010"
case 0x3F: aluOut = 1; break; // "1", "111111"
case 0x3A: aluOut = -1; break; // "-1", "111010"
case 0x0C: aluOut = D; break; // "D", "001100"
case 0x30: aluOut = AM; break; // "AM", "110000"
case 0x0D: aluOut = D ^ 0xFFFF; break; // "!D", "001101"
case 0x31: aluOut = AM ^ 0xFFFF; break; // "!AM", "110001"
case 0x0F: aluOut = -D; break; // "-D", "001111"
case 0x33: aluOut = -AM; break; // "-AM", "110011"
case 0x1F: aluOut = D + 1; break; // "D+1", "011111"
case 0x37: aluOut = AM + 1; break; // "AM+1","110111"
case 0x0E: aluOut = D - 1; break; // "D-1", "001110"
case 0x32: aluOut = AM - 1; break; // "AM-1","110010"
case 0x02: aluOut = D + AM; break; // "D+AM","000010"
case 0x13: aluOut = D - AM; break; // "D-AM","010011"
case 0x07: aluOut = AM - D; break; // "AM-D","000111"
case 0x00: aluOut = D & AM; break; // "D&AM","000000"
case 0x15: aluOut = D | AM; break; // "D|AM","010101"
default: assert(0);
}
if (d & BIT(2)) A = aluOut;
if (d & BIT(1)) D = aluOut;
if (d & BIT(0)) m[A] = aluOut;
switch (j) {
case 0x0: break; //
case 0x1: if (aluOut > 0) PC = A; break; // JGT
case 0x2: if (aluOut == 0) PC = A; break; // JEQ
case 0x3: if (aluOut >= 0) PC = A; break; // JGE
case 0x4: if (aluOut < 0) PC = A; break; // JLT
case 0x5: if (aluOut != 0) PC = A; break; // JNE
case 0x6: if (aluOut <= 0) PC = A; break; // JLE
case 0x7: PC = A; break; // JMP
}
}
debug(" A=%04X D=%04X m[A]=%04X", A, D, m[A]);
if ((I & 0x8000) != 0) debug(" a=%X c=%02X d=%X j=%X", a, c, d, j);
debug("\n");
}
}
// run: ./vm <file.bin>
int main(int argc, char *argv[]) {
char *binFileName = argv[1];
FILE *binFile = fopen(binFileName, "rb");
imTop = fread(im, sizeof(uint16_t), 32768, binFile);
fclose(binFile);
run(im, m);
}