Commit b5e96df63922e1408460c3f96f7f8a3a2865b091
1 parent
086defff
VM implemented, debugger and disasm WIP
Showing
13 changed files
with
27119 additions
and
52 deletions
Too many changes to show.
To preserve performance only 4 of 13 files are displayed.
.idea/misc.xml
1 | <?xml version="1.0" encoding="UTF-8"?> | 1 | <?xml version="1.0" encoding="UTF-8"?> |
2 | <project version="4"> | 2 | <project version="4"> |
3 | <component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" /> | 3 | <component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" /> |
4 | + <component name="CidrRootsConfiguration"> | ||
5 | + <sourceRoots /> | ||
6 | + <libraryRoots /> | ||
7 | + <excludeRoots /> | ||
8 | + </component> | ||
4 | <component name="ProjectLevelVcsManager" settingsEditedManually="false"> | 9 | <component name="ProjectLevelVcsManager" settingsEditedManually="false"> |
5 | <OptionsSetting value="true" id="Add" /> | 10 | <OptionsSetting value="true" id="Add" /> |
6 | <OptionsSetting value="true" id="Remove" /> | 11 | <OptionsSetting value="true" id="Remove" /> |
.idea/vcs.xml
0 → 100644
cpu.c
@@ -5,19 +5,21 @@ | @@ -5,19 +5,21 @@ | ||
5 | #include <stdlib.h> | 5 | #include <stdlib.h> |
6 | #include "cpu.h" | 6 | #include "cpu.h" |
7 | 7 | ||
8 | -void mov(short dst, short src) | 8 | +uint64_t cycle_count = 0; |
9 | + | ||
10 | +void mov(uint16_t dst, uint16_t src) | ||
9 | { | 11 | { |
10 | if(src > MAX_INT) | 12 | if(src > MAX_INT) |
11 | { | 13 | { |
12 | - regs[dst] = regs[src % (MAX_INT+1)]; | 14 | + regs[dst % (MAX_INT+1)] = regs[src % (MAX_INT+1)]; |
13 | } | 15 | } |
14 | else | 16 | else |
15 | { | 17 | { |
16 | - regs[dst] = src; | 18 | + regs[dst % (MAX_INT+1)] = src; |
17 | } | 19 | } |
18 | } | 20 | } |
19 | 21 | ||
20 | -void push(short src) | 22 | +void push(uint16_t src) |
21 | { | 23 | { |
22 | if(src > MAX_INT) | 24 | if(src > MAX_INT) |
23 | { | 25 | { |
@@ -29,9 +31,9 @@ void push(short src) | @@ -29,9 +31,9 @@ void push(short src) | ||
29 | } | 31 | } |
30 | } | 32 | } |
31 | 33 | ||
32 | -void pop(short dst) | 34 | +void pop(uint16_t dst) |
33 | { | 35 | { |
34 | - short value = stack_pop(); | 36 | + uint16_t value = stack_pop(); |
35 | if(STACK_FAULT) | 37 | if(STACK_FAULT) |
36 | { | 38 | { |
37 | fprintf(stderr,"CRITICAL: STACK VIOLATION\n"); | 39 | fprintf(stderr,"CRITICAL: STACK VIOLATION\n"); |
@@ -40,7 +42,7 @@ void pop(short dst) | @@ -40,7 +42,7 @@ void pop(short dst) | ||
40 | regs[dst % (MAX_INT+1)] = value; | 42 | regs[dst % (MAX_INT+1)] = value; |
41 | } | 43 | } |
42 | 44 | ||
43 | -void teq(short dst, short a, short b) | 45 | +void teq(uint16_t dst, uint16_t a, uint16_t b) |
44 | { | 46 | { |
45 | if(a > MAX_INT) | 47 | if(a > MAX_INT) |
46 | { | 48 | { |
@@ -53,7 +55,7 @@ void teq(short dst, short a, short b) | @@ -53,7 +55,7 @@ void teq(short dst, short a, short b) | ||
53 | regs[dst % (MAX_INT+1)] = (a == b); | 55 | regs[dst % (MAX_INT+1)] = (a == b); |
54 | } | 56 | } |
55 | 57 | ||
56 | -void tgt(short dst, short a, short b) | 58 | +void tgt(uint16_t dst, uint16_t a, uint16_t b) |
57 | { | 59 | { |
58 | if(a > MAX_INT) | 60 | if(a > MAX_INT) |
59 | { | 61 | { |
@@ -66,7 +68,7 @@ void tgt(short dst, short a, short b) | @@ -66,7 +68,7 @@ void tgt(short dst, short a, short b) | ||
66 | regs[dst % (MAX_INT+1)] = (a > b); | 68 | regs[dst % (MAX_INT+1)] = (a > b); |
67 | } | 69 | } |
68 | 70 | ||
69 | -void jmp(short dst) | 71 | +void jmp(uint16_t dst) |
70 | { | 72 | { |
71 | if(dst > MAX_INT) | 73 | if(dst > MAX_INT) |
72 | { | 74 | { |
@@ -78,11 +80,11 @@ void jmp(short dst) | @@ -78,11 +80,11 @@ void jmp(short dst) | ||
78 | } | 80 | } |
79 | } | 81 | } |
80 | 82 | ||
81 | -void jnz(short cond, short dst) | 83 | +void jnz(uint16_t cond, uint16_t dst) |
82 | { | 84 | { |
83 | if(cond > MAX_INT) | 85 | if(cond > MAX_INT) |
84 | { | 86 | { |
85 | - cond = regs[dst % (MAX_INT+1)]; | 87 | + cond = regs[cond % (MAX_INT+1)]; |
86 | } | 88 | } |
87 | if(cond) | 89 | if(cond) |
88 | { | 90 | { |
@@ -90,11 +92,11 @@ void jnz(short cond, short dst) | @@ -90,11 +92,11 @@ void jnz(short cond, short dst) | ||
90 | } | 92 | } |
91 | } | 93 | } |
92 | 94 | ||
93 | -void jz(short cond, short dst) | 95 | +void jz(uint16_t cond, uint16_t dst) |
94 | { | 96 | { |
95 | if(cond > MAX_INT) | 97 | if(cond > MAX_INT) |
96 | { | 98 | { |
97 | - cond = regs[dst % (MAX_INT+1)]; | 99 | + cond = regs[cond % (MAX_INT+1)]; |
98 | } | 100 | } |
99 | if(!cond) | 101 | if(!cond) |
100 | { | 102 | { |
@@ -102,7 +104,7 @@ void jz(short cond, short dst) | @@ -102,7 +104,7 @@ void jz(short cond, short dst) | ||
102 | } | 104 | } |
103 | } | 105 | } |
104 | 106 | ||
105 | -void add(short dst, short a, short b) | 107 | +void add(uint16_t dst, uint16_t a, uint16_t b) |
106 | { | 108 | { |
107 | if(a > MAX_INT) | 109 | if(a > MAX_INT) |
108 | { | 110 | { |
@@ -115,7 +117,7 @@ void add(short dst, short a, short b) | @@ -115,7 +117,7 @@ void add(short dst, short a, short b) | ||
115 | regs[dst % (MAX_INT+1)] = (a + b) % (MAX_INT+1); | 117 | regs[dst % (MAX_INT+1)] = (a + b) % (MAX_INT+1); |
116 | } | 118 | } |
117 | 119 | ||
118 | -void mult(short dst, short a, short b) | 120 | +void mult(uint16_t dst, uint16_t a, uint16_t b) |
119 | { | 121 | { |
120 | if(a > MAX_INT) | 122 | if(a > MAX_INT) |
121 | { | 123 | { |
@@ -128,7 +130,7 @@ void mult(short dst, short a, short b) | @@ -128,7 +130,7 @@ void mult(short dst, short a, short b) | ||
128 | regs[dst % (MAX_INT+1)] = (a * b) % (MAX_INT+1); | 130 | regs[dst % (MAX_INT+1)] = (a * b) % (MAX_INT+1); |
129 | } | 131 | } |
130 | 132 | ||
131 | -void mod(short dst, short a, short b) | 133 | +void mod(uint16_t dst, uint16_t a, uint16_t b) |
132 | { | 134 | { |
133 | if(a > MAX_INT) | 135 | if(a > MAX_INT) |
134 | { | 136 | { |
@@ -141,7 +143,7 @@ void mod(short dst, short a, short b) | @@ -141,7 +143,7 @@ void mod(short dst, short a, short b) | ||
141 | regs[dst % (MAX_INT+1)] = (a % b); | 143 | regs[dst % (MAX_INT+1)] = (a % b); |
142 | } | 144 | } |
143 | 145 | ||
144 | -void and(short dst, short a, short b) | 146 | +void and(uint16_t dst, uint16_t a, uint16_t b) |
145 | { | 147 | { |
146 | if(a > MAX_INT) | 148 | if(a > MAX_INT) |
147 | { | 149 | { |
@@ -154,7 +156,7 @@ void and(short dst, short a, short b) | @@ -154,7 +156,7 @@ void and(short dst, short a, short b) | ||
154 | regs[dst % (MAX_INT+1)] = (a & b); | 156 | regs[dst % (MAX_INT+1)] = (a & b); |
155 | } | 157 | } |
156 | 158 | ||
157 | -void or(short dst, short a, short b) | 159 | +void or(uint16_t dst, uint16_t a, uint16_t b) |
158 | { | 160 | { |
159 | if(a > MAX_INT) | 161 | if(a > MAX_INT) |
160 | { | 162 | { |
@@ -167,7 +169,7 @@ void or(short dst, short a, short b) | @@ -167,7 +169,7 @@ void or(short dst, short a, short b) | ||
167 | regs[dst % (MAX_INT+1)] = (a | b); | 169 | regs[dst % (MAX_INT+1)] = (a | b); |
168 | } | 170 | } |
169 | 171 | ||
170 | -void not(short dst, short src) | 172 | +void not(uint16_t dst, uint16_t src) |
171 | { | 173 | { |
172 | if(src > MAX_INT) | 174 | if(src > MAX_INT) |
173 | { | 175 | { |
@@ -176,16 +178,16 @@ void not(short dst, short src) | @@ -176,16 +178,16 @@ void not(short dst, short src) | ||
176 | regs[dst % (MAX_INT+1)] = ~src & 0x7FFF; | 178 | regs[dst % (MAX_INT+1)] = ~src & 0x7FFF; |
177 | } | 179 | } |
178 | 180 | ||
179 | -void load(short src, short dst) | 181 | +void load(uint16_t dst, uint16_t src) |
180 | { | 182 | { |
181 | if(src > MAX_INT) | 183 | if(src > MAX_INT) |
182 | { | 184 | { |
183 | src = regs[src % (MAX_INT+1)]; | 185 | src = regs[src % (MAX_INT+1)]; |
184 | } | 186 | } |
185 | - regs[dst % (MAX_INT+1)] = src; | 187 | + regs[dst % (MAX_INT+1)] = mem[src]; |
186 | } | 188 | } |
187 | 189 | ||
188 | -void stor(short dst, short src) | 190 | +void stor(uint16_t dst, uint16_t src) |
189 | { | 191 | { |
190 | if(src > MAX_INT) | 192 | if(src > MAX_INT) |
191 | { | 193 | { |
@@ -201,7 +203,7 @@ void stor(short dst, short src) | @@ -201,7 +203,7 @@ void stor(short dst, short src) | ||
201 | } | 203 | } |
202 | } | 204 | } |
203 | 205 | ||
204 | -void call(short dst) | 206 | +void call(uint16_t dst) |
205 | { | 207 | { |
206 | stack_push(pc); | 208 | stack_push(pc); |
207 | jmp(dst); | 209 | jmp(dst); |
@@ -213,15 +215,19 @@ uint8_t ret() | @@ -213,15 +215,19 @@ uint8_t ret() | ||
213 | return STACK_FAULT; | 215 | return STACK_FAULT; |
214 | } | 216 | } |
215 | 217 | ||
216 | -void out(unsigned char a) | 218 | +void out(uint16_t src) |
217 | { | 219 | { |
218 | - putchar(a); | 220 | + if(src > MAX_INT) |
221 | + { | ||
222 | + src = regs[src % (MAX_INT+1)]; | ||
223 | + } | ||
224 | + putchar(src); | ||
219 | } | 225 | } |
220 | 226 | ||
221 | -void in(short dst) | 227 | +void in(uint16_t dst) |
222 | { | 228 | { |
223 | int c = getchar(); | 229 | int c = getchar(); |
224 | - regs[dst] = (short)c; | 230 | + regs[dst % (MAX_INT + 1)] = (uint16_t)c; |
225 | } | 231 | } |
226 | 232 | ||
227 | void nop() | 233 | void nop() |
@@ -229,24 +235,26 @@ void nop() | @@ -229,24 +235,26 @@ void nop() | ||
229 | return; | 235 | return; |
230 | } | 236 | } |
231 | 237 | ||
232 | -short fetch() | 238 | +uint16_t fetch() |
233 | { | 239 | { |
234 | - short value = mem[pc++]; | ||
235 | - if(value < 0) | 240 | + /*if(pc == 0x5bf-1) |
236 | { | 241 | { |
237 | - value *= -1; | ||
238 | - } | 242 | + //break |
243 | + }*/ | ||
244 | + uint16_t value = mem[pc++]; | ||
245 | + //printf("0x%2x (0x%2x)",pc,pc*sizeof(uint16_t)); | ||
246 | + //printf(" cycle: %d\n",cycle_count++); | ||
239 | return value; | 247 | return value; |
240 | } | 248 | } |
241 | 249 | ||
242 | void start_execution() | 250 | void start_execution() |
243 | { | 251 | { |
244 | - short arg1; | ||
245 | - short arg2; | ||
246 | - short arg3; | 252 | + uint16_t arg1; |
253 | + uint16_t arg2; | ||
254 | + uint16_t arg3; | ||
247 | for(;;) | 255 | for(;;) |
248 | { | 256 | { |
249 | - short opcode = fetch(); | 257 | + uint16_t opcode = fetch(); |
250 | switch(opcode) | 258 | switch(opcode) |
251 | { | 259 | { |
252 | case HALT: | 260 | case HALT: |
@@ -346,7 +354,8 @@ void start_execution() | @@ -346,7 +354,8 @@ void start_execution() | ||
346 | } | 354 | } |
347 | break; | 355 | break; |
348 | case OUT: | 356 | case OUT: |
349 | - out((unsigned char)fetch()); | 357 | + arg1 = fetch(); |
358 | + out(arg1); | ||
350 | break; | 359 | break; |
351 | case IN: | 360 | case IN: |
352 | arg1 = fetch(); | 361 | arg1 = fetch(); |
@@ -377,4 +386,4 @@ void core_dump() | @@ -377,4 +386,4 @@ void core_dump() | ||
377 | //dump memory to file | 386 | //dump memory to file |
378 | //dump stack to file | 387 | //dump stack to file |
379 | exit(1); | 388 | exit(1); |
380 | -} | ||
381 | \ No newline at end of file | 389 | \ No newline at end of file |
390 | +} |
data/arch-spec
0 → 100644
1 | +== Synacor Challenge == | ||
2 | +In this challenge, your job is to use this architecture spec to create a | ||
3 | +virtual machine capable of running the included binary. Along the way, | ||
4 | +you will find codes; submit these to the challenge website to track | ||
5 | +your progress. Good luck! | ||
6 | + | ||
7 | + | ||
8 | +== architecture == | ||
9 | +- three storage regions | ||
10 | + - memory with 15-bit address space storing 16-bit values | ||
11 | + - eight registers | ||
12 | + - an unbounded stack which holds individual 16-bit values | ||
13 | +- all numbers are unsigned integers 0..32767 (15-bit) | ||
14 | +- all math is modulo 32768; 32758 + 15 => 5 | ||
15 | + | ||
16 | +== binary format == | ||
17 | +- each number is stored as a 16-bit little-endian pair (low byte, high byte) | ||
18 | +- numbers 0..32767 mean a literal value | ||
19 | +- numbers 32768..32775 instead mean registers 0..7 | ||
20 | +- numbers 32776..65535 are invalid | ||
21 | +- programs are loaded into memory starting at address 0 | ||
22 | +- address 0 is the first 16-bit value, address 1 is the second 16-bit value, etc | ||
23 | + | ||
24 | +== execution == | ||
25 | +- After an operation is executed, the next instruction to read is immediately after the last argument of the current operation. If a jump was performed, the next operation is instead the exact destination of the jump. | ||
26 | +- Encountering a register as an operation argument should be taken as reading from the register or setting into the register as appropriate. | ||
27 | + | ||
28 | +== hints == | ||
29 | +- Start with operations 0, 19, and 21. | ||
30 | +- Here's a code for the challenge website: WdXrmkgDVVgK | ||
31 | +- The program "9,32768,32769,4,19,32768" occupies six memory addresses and should: | ||
32 | + - Store into register 0 the sum of 4 and the value contained in register 1. | ||
33 | + - Output to the terminal the character with the ascii code contained in register 0. | ||
34 | + | ||
35 | +== opcode listing == | ||
36 | +halt: 0 | ||
37 | + stop execution and terminate the program | ||
38 | +set: 1 a b | ||
39 | + set register <a> to the value of <b> | ||
40 | +push: 2 a | ||
41 | + push <a> onto the stack | ||
42 | +pop: 3 a | ||
43 | + remove the top element from the stack and write it into <a>; empty stack = error | ||
44 | +eq: 4 a b c | ||
45 | + set <a> to 1 if <b> is equal to <c>; set it to 0 otherwise | ||
46 | +gt: 5 a b c | ||
47 | + set <a> to 1 if <b> is greater than <c>; set it to 0 otherwise | ||
48 | +jmp: 6 a | ||
49 | + jump to <a> | ||
50 | +jt: 7 a b | ||
51 | + if <a> is nonzero, jump to <b> | ||
52 | +jf: 8 a b | ||
53 | + if <a> is zero, jump to <b> | ||
54 | +add: 9 a b c | ||
55 | + assign into <a> the sum of <b> and <c> (modulo 32768) | ||
56 | +mult: 10 a b c | ||
57 | + store into <a> the product of <b> and <c> (modulo 32768) | ||
58 | +mod: 11 a b c | ||
59 | + store into <a> the remainder of <b> divided by <c> | ||
60 | +and: 12 a b c | ||
61 | + stores into <a> the bitwise and of <b> and <c> | ||
62 | +or: 13 a b c | ||
63 | + stores into <a> the bitwise or of <b> and <c> | ||
64 | +not: 14 a b | ||
65 | + stores 15-bit bitwise inverse of <b> in <a> | ||
66 | +rmem: 15 a b | ||
67 | + read memory at address <b> and write it to <a> | ||
68 | +wmem: 16 a b | ||
69 | + write the value from <b> into memory at address <a> | ||
70 | +call: 17 a | ||
71 | + write the address of the next instruction to the stack and jump to <a> | ||
72 | +ret: 18 | ||
73 | + remove the top element from the stack and jump to it; empty stack = halt | ||
74 | +out: 19 a | ||
75 | + write the character represented by ascii code <a> to the terminal | ||
76 | +in: 20 a | ||
77 | + read a character from the terminal and write its ascii code to <a>; it can be assumed that once input starts, it will continue until a newline is encountered; this means that you can safely read whole lines from the keyboard and trust that they will be fully read | ||
78 | +noop: 21 | ||
79 | + no operation |