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 | 1 | <?xml version="1.0" encoding="UTF-8"?> |
2 | 2 | <project version="4"> |
3 | 3 | <component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" /> |
4 | + <component name="CidrRootsConfiguration"> | |
5 | + <sourceRoots /> | |
6 | + <libraryRoots /> | |
7 | + <excludeRoots /> | |
8 | + </component> | |
4 | 9 | <component name="ProjectLevelVcsManager" settingsEditedManually="false"> |
5 | 10 | <OptionsSetting value="true" id="Add" /> |
6 | 11 | <OptionsSetting value="true" id="Remove" /> | ... | ... |
.idea/vcs.xml
0 → 100644
cpu.c
... | ... | @@ -5,19 +5,21 @@ |
5 | 5 | #include <stdlib.h> |
6 | 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 | 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 | 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 | 24 | if(src > MAX_INT) |
23 | 25 | { |
... | ... | @@ -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 | 37 | if(STACK_FAULT) |
36 | 38 | { |
37 | 39 | fprintf(stderr,"CRITICAL: STACK VIOLATION\n"); |
... | ... | @@ -40,7 +42,7 @@ void pop(short dst) |
40 | 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 | 47 | if(a > MAX_INT) |
46 | 48 | { |
... | ... | @@ -53,7 +55,7 @@ void teq(short dst, short a, short b) |
53 | 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 | 60 | if(a > MAX_INT) |
59 | 61 | { |
... | ... | @@ -66,7 +68,7 @@ void tgt(short dst, short a, short b) |
66 | 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 | 73 | if(dst > MAX_INT) |
72 | 74 | { |
... | ... | @@ -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 | 85 | if(cond > MAX_INT) |
84 | 86 | { |
85 | - cond = regs[dst % (MAX_INT+1)]; | |
87 | + cond = regs[cond % (MAX_INT+1)]; | |
86 | 88 | } |
87 | 89 | if(cond) |
88 | 90 | { |
... | ... | @@ -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 | 97 | if(cond > MAX_INT) |
96 | 98 | { |
97 | - cond = regs[dst % (MAX_INT+1)]; | |
99 | + cond = regs[cond % (MAX_INT+1)]; | |
98 | 100 | } |
99 | 101 | if(!cond) |
100 | 102 | { |
... | ... | @@ -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 | 109 | if(a > MAX_INT) |
108 | 110 | { |
... | ... | @@ -115,7 +117,7 @@ void add(short dst, short a, short b) |
115 | 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 | 122 | if(a > MAX_INT) |
121 | 123 | { |
... | ... | @@ -128,7 +130,7 @@ void mult(short dst, short a, short b) |
128 | 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 | 135 | if(a > MAX_INT) |
134 | 136 | { |
... | ... | @@ -141,7 +143,7 @@ void mod(short dst, short a, short b) |
141 | 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 | 148 | if(a > MAX_INT) |
147 | 149 | { |
... | ... | @@ -154,7 +156,7 @@ void and(short dst, short a, short b) |
154 | 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 | 161 | if(a > MAX_INT) |
160 | 162 | { |
... | ... | @@ -167,7 +169,7 @@ void or(short dst, short a, short b) |
167 | 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 | 174 | if(src > MAX_INT) |
173 | 175 | { |
... | ... | @@ -176,16 +178,16 @@ void not(short dst, short src) |
176 | 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 | 183 | if(src > MAX_INT) |
182 | 184 | { |
183 | 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 | 192 | if(src > MAX_INT) |
191 | 193 | { |
... | ... | @@ -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 | 208 | stack_push(pc); |
207 | 209 | jmp(dst); |
... | ... | @@ -213,15 +215,19 @@ uint8_t ret() |
213 | 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 | 229 | int c = getchar(); |
224 | - regs[dst] = (short)c; | |
230 | + regs[dst % (MAX_INT + 1)] = (uint16_t)c; | |
225 | 231 | } |
226 | 232 | |
227 | 233 | void nop() |
... | ... | @@ -229,24 +235,26 @@ void nop() |
229 | 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 | 247 | return value; |
240 | 248 | } |
241 | 249 | |
242 | 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 | 255 | for(;;) |
248 | 256 | { |
249 | - short opcode = fetch(); | |
257 | + uint16_t opcode = fetch(); | |
250 | 258 | switch(opcode) |
251 | 259 | { |
252 | 260 | case HALT: |
... | ... | @@ -346,7 +354,8 @@ void start_execution() |
346 | 354 | } |
347 | 355 | break; |
348 | 356 | case OUT: |
349 | - out((unsigned char)fetch()); | |
357 | + arg1 = fetch(); | |
358 | + out(arg1); | |
350 | 359 | break; |
351 | 360 | case IN: |
352 | 361 | arg1 = fetch(); |
... | ... | @@ -377,4 +386,4 @@ void core_dump() |
377 | 386 | //dump memory to file |
378 | 387 | //dump stack to file |
379 | 388 | exit(1); |
380 | -} | |
381 | 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 | ... | ... |