Commit 5e06910cf73286209f0b134f2c969c22da434c03
1 parent
0f27ef74
Implemented. Testing and debugging...
Showing
11 changed files
with
433 additions
and
27 deletions
.idea/synacorvm.iml
... | ... | @@ -4,13 +4,13 @@ |
4 | 4 | <content url="file://$MODULE_DIR$"> |
5 | 5 | <sourceFolder url="file://$MODULE_DIR$/cpu.h" isTestSource="false" /> |
6 | 6 | <sourceFolder url="file://$MODULE_DIR$/CMakeLists.txt" isTestSource="false" /> |
7 | - <sourceFolder url="file://$MODULE_DIR$/binary_decoder.c" isTestSource="false" /> | |
7 | + <sourceFolder url="file://$MODULE_DIR$/main.c" isTestSource="false" /> | |
8 | 8 | <sourceFolder url="file://$MODULE_DIR$/stack.c" isTestSource="false" /> |
9 | 9 | <sourceFolder url="file://$MODULE_DIR$/mem.h" isTestSource="false" /> |
10 | - <sourceFolder url="file://$MODULE_DIR$/main.c" isTestSource="false" /> | |
11 | 10 | <sourceFolder url="file://$MODULE_DIR$/cpu.c" isTestSource="false" /> |
11 | + <sourceFolder url="file://$MODULE_DIR$/mem.c" isTestSource="false" /> | |
12 | 12 | <sourceFolder url="file://$MODULE_DIR$/registers.h" isTestSource="false" /> |
13 | - <sourceFolder url="file://$MODULE_DIR$/binary_decoder.h" isTestSource="false" /> | |
13 | + <sourceFolder url="file://$MODULE_DIR$/registers.c" isTestSource="false" /> | |
14 | 14 | <sourceFolder url="file://$MODULE_DIR$/stack.h" isTestSource="false" /> |
15 | 15 | </content> |
16 | 16 | <orderEntry type="sourceFolder" forTests="false" /> | ... | ... |
CMakeLists.txt
... | ... | @@ -3,5 +3,5 @@ project(synacorvm) |
3 | 3 | |
4 | 4 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") |
5 | 5 | |
6 | -set(SOURCE_FILES main.c cpu.c cpu.h binary_decoder.c binary_decoder.h registers.h mem.h stack.c stack.h) | |
6 | +set(SOURCE_FILES main.c cpu.c cpu.h registers.h mem.h stack.c stack.h registers.c mem.c) | |
7 | 7 | add_executable(synacorvm ${SOURCE_FILES}) |
8 | 8 | \ No newline at end of file | ... | ... |
cpu.c
... | ... | @@ -2,15 +2,333 @@ |
2 | 2 | // Created by imanol on 12/25/16. |
3 | 3 | // |
4 | 4 | |
5 | +#include <stdlib.h> | |
5 | 6 | #include "cpu.h" |
6 | 7 | |
8 | +void mov(short dst, short src) | |
9 | +{ | |
10 | + if(src > MAX_INT) | |
11 | + { | |
12 | + regs[dst] = regs[src % (MAX_INT+1)]; | |
13 | + } | |
14 | + else | |
15 | + { | |
16 | + regs[dst] = src; | |
17 | + } | |
18 | +} | |
19 | + | |
20 | +void push(short src) | |
21 | +{ | |
22 | + if(src > MAX_INT) | |
23 | + { | |
24 | + stack_push(regs[src % (MAX_INT+1)]); | |
25 | + } | |
26 | + else | |
27 | + { | |
28 | + stack_push(src); | |
29 | + } | |
30 | +} | |
31 | + | |
32 | +void pop(short dst) | |
33 | +{ | |
34 | + short value = stack_pop(); | |
35 | + if(STACK_FAULT) | |
36 | + { | |
37 | + fprintf(stderr,"CRITICAL: STACK VIOLATION\n"); | |
38 | + core_dump(); | |
39 | + } | |
40 | + regs[dst] = value; | |
41 | +} | |
42 | + | |
43 | +void teq(short dst, short a, short b) | |
44 | +{ | |
45 | + if(a > MAX_INT) | |
46 | + { | |
47 | + a = regs[a % (MAX_INT+1)]; | |
48 | + } | |
49 | + if(b > MAX_INT) | |
50 | + { | |
51 | + b = regs[b % (MAX_INT+1)]; | |
52 | + } | |
53 | + regs[dst % (MAX_INT+1)] = (a == b); | |
54 | +} | |
55 | + | |
56 | +void tgt(short dst, short a, short b) | |
57 | +{ | |
58 | + if(a > MAX_INT) | |
59 | + { | |
60 | + a = regs[a % (MAX_INT+1)]; | |
61 | + } | |
62 | + if(b > MAX_INT) | |
63 | + { | |
64 | + b = regs[b % (MAX_INT+1)]; | |
65 | + } | |
66 | + regs[dst % (MAX_INT+1)] = (a > b); | |
67 | +} | |
68 | + | |
69 | +void jmp(short dst) | |
70 | +{ | |
71 | + if(dst > MAX_INT) | |
72 | + { | |
73 | + pc = regs[dst % (MAX_INT+1)]; | |
74 | + } | |
75 | + else | |
76 | + { | |
77 | + pc = dst; | |
78 | + } | |
79 | +} | |
80 | + | |
81 | +void jnz(short cond, short dst) | |
82 | +{ | |
83 | + if(cond) | |
84 | + { | |
85 | + jmp(dst); | |
86 | + } | |
87 | +} | |
88 | + | |
89 | +void jz(short cond, short dst) | |
90 | +{ | |
91 | + if(!cond) | |
92 | + { | |
93 | + jmp(dst); | |
94 | + } | |
95 | +} | |
96 | + | |
97 | +void add(short dst, short a, short b) | |
98 | +{ | |
99 | + if(a > MAX_INT) | |
100 | + { | |
101 | + a = regs[a % (MAX_INT+1)]; | |
102 | + } | |
103 | + if(b > MAX_INT) | |
104 | + { | |
105 | + b = regs[b % (MAX_INT+1)]; | |
106 | + } | |
107 | + regs[dst % (MAX_INT+1)] = (a + b) % (MAX_INT+1); | |
108 | +} | |
109 | + | |
110 | +void mult(short dst, short a, short b) | |
111 | +{ | |
112 | + if(a > MAX_INT) | |
113 | + { | |
114 | + a = regs[a % (MAX_INT+1)]; | |
115 | + } | |
116 | + if(b > MAX_INT) | |
117 | + { | |
118 | + b = regs[b % (MAX_INT+1)]; | |
119 | + } | |
120 | + regs[dst % (MAX_INT+1)] = (a * b) % (MAX_INT+1); | |
121 | +} | |
122 | + | |
123 | +void mod(short dst, short a, short b) | |
124 | +{ | |
125 | + if(a > MAX_INT) | |
126 | + { | |
127 | + a = regs[a % (MAX_INT+1)]; | |
128 | + } | |
129 | + if(b > MAX_INT) | |
130 | + { | |
131 | + b = regs[b % (MAX_INT+1)]; | |
132 | + } | |
133 | + regs[dst % (MAX_INT+1)] = (a % b); | |
134 | +} | |
135 | + | |
136 | +void and(short dst, short a, short b) | |
137 | +{ | |
138 | + if(a > MAX_INT) | |
139 | + { | |
140 | + a = regs[a % (MAX_INT+1)]; | |
141 | + } | |
142 | + if(b > MAX_INT) | |
143 | + { | |
144 | + b = regs[b % (MAX_INT+1)]; | |
145 | + } | |
146 | + regs[dst % (MAX_INT+1)] = (a & b); | |
147 | +} | |
148 | + | |
149 | +void or(short dst, short a, short b) | |
150 | +{ | |
151 | + if(a > MAX_INT) | |
152 | + { | |
153 | + a = regs[a % (MAX_INT+1)]; | |
154 | + } | |
155 | + if(b > MAX_INT) | |
156 | + { | |
157 | + b = regs[b % (MAX_INT+1)]; | |
158 | + } | |
159 | + regs[dst % (MAX_INT+1)] = (a | b); | |
160 | +} | |
161 | + | |
162 | +void not(short dst, short src) | |
163 | +{ | |
164 | + if(src > MAX_INT) | |
165 | + { | |
166 | + src = regs[src % (MAX_INT+1)]; | |
167 | + } | |
168 | + regs[dst % (MAX_INT+1)] = ~src & 0x7FFF; | |
169 | +} | |
170 | + | |
171 | +void load(short src, short dst) | |
172 | +{ | |
173 | + if(src > MAX_INT) | |
174 | + { | |
175 | + src = regs[src % (MAX_INT+1)]; | |
176 | + } | |
177 | + regs[dst % (MAX_INT+1)] = src; | |
178 | +} | |
179 | + | |
180 | +void stor(short dst, short src) | |
181 | +{ | |
182 | + if(src > MAX_INT) | |
183 | + { | |
184 | + src = regs[src % (MAX_INT+1)]; | |
185 | + } | |
186 | + if(dst > MAX_INT) | |
187 | + { | |
188 | + mem[regs[dst % (MAX_INT+1)]] = src; | |
189 | + } | |
190 | + else | |
191 | + { | |
192 | + mem[dst] = src; | |
193 | + } | |
194 | +} | |
195 | + | |
196 | +void call(short dst) | |
197 | +{ | |
198 | + stack_push(pc); | |
199 | + jmp(dst); | |
200 | +} | |
201 | + | |
202 | +uint8_t ret() | |
203 | +{ | |
204 | + pc = stack_pop(); | |
205 | + return STACK_FAULT; | |
206 | +} | |
207 | + | |
208 | +void out(unsigned char a) | |
209 | +{ | |
210 | + putchar(a); | |
211 | +} | |
212 | + | |
213 | +void in(short dst) | |
214 | +{ | |
215 | + int c = getchar(); | |
216 | + regs[dst] = (short)c; | |
217 | +} | |
218 | + | |
7 | 219 | void nop() |
8 | 220 | { |
9 | 221 | return; |
10 | 222 | } |
11 | 223 | |
12 | -void out(unsigned char a) | |
224 | +void start_execution() | |
13 | 225 | { |
14 | - printf("%c",a); | |
226 | + for(;;) | |
227 | + { | |
228 | + short opcode = mem[pc++]; | |
229 | + switch(opcode) | |
230 | + { | |
231 | + case HALT: | |
232 | + return; | |
233 | + case MOV: | |
234 | + mov(mem[pc],mem[pc+1]); | |
235 | + pc += 2; | |
236 | + break; | |
237 | + case PUSH: | |
238 | + push(mem[pc++]); | |
239 | + break; | |
240 | + case POP: | |
241 | + pop(mem[pc++]); | |
242 | + break; | |
243 | + case TEQ: | |
244 | + teq(mem[pc],mem[pc+1],mem[pc+2]); | |
245 | + pc += 3; | |
246 | + break; | |
247 | + case TGT: | |
248 | + tgt(mem[pc],mem[pc+1],mem[pc+2]); | |
249 | + pc += 3; | |
250 | + break; | |
251 | + case JMP: | |
252 | + jmp(mem[pc++]); | |
253 | + break; | |
254 | + case JNZ: | |
255 | + jnz(mem[pc],mem[pc+1]); | |
256 | + pc += 2; | |
257 | + break; | |
258 | + case JZ: | |
259 | + jz(mem[pc],mem[pc+1]); | |
260 | + pc += 2; | |
261 | + break; | |
262 | + case ADD: | |
263 | + add(mem[pc],mem[pc+1],mem[pc+2]); | |
264 | + pc += 3; | |
265 | + break; | |
266 | + case MULT: | |
267 | + mult(mem[pc],mem[pc+1],mem[pc+2]); | |
268 | + pc += 3; | |
269 | + break; | |
270 | + case MOD: | |
271 | + mod(mem[pc],mem[pc+1],mem[pc+2]); | |
272 | + pc += 3; | |
273 | + break; | |
274 | + case AND: | |
275 | + and(mem[pc],mem[pc+1],mem[pc+2]); | |
276 | + pc += 3; | |
277 | + break; | |
278 | + case OR: | |
279 | + or(mem[pc],mem[pc+1],mem[pc+2]); | |
280 | + pc += 3; | |
281 | + break; | |
282 | + case NOT: | |
283 | + not(mem[pc],mem[pc+1]); | |
284 | + pc += 2; | |
285 | + break; | |
286 | + case LOAD: | |
287 | + load(mem[pc],mem[pc+1]); | |
288 | + pc += 2; | |
289 | + break; | |
290 | + case STOR: | |
291 | + stor(mem[pc],mem[pc+1]); | |
292 | + pc += 2; | |
293 | + break; | |
294 | + case CALL: | |
295 | + call(mem[pc++]); | |
296 | + break; | |
297 | + case RET: | |
298 | + if(ret()) | |
299 | + { | |
300 | + return; | |
301 | + } | |
302 | + break; | |
303 | + case OUT: | |
304 | + out((unsigned char)mem[pc++]); | |
305 | + break; | |
306 | + case IN: | |
307 | + in(mem[pc++]); | |
308 | + break; | |
309 | + case NOP: | |
310 | + nop(); | |
311 | + break; | |
312 | + default: | |
313 | + fprintf(stderr,"CRITICAL: UNKNOWN OPCODE %2x FOUND IN %2x\n",opcode,pc); | |
314 | + core_dump(); | |
315 | + break; | |
316 | + } | |
317 | + } | |
15 | 318 | } |
16 | 319 | |
320 | +void core_dump() | |
321 | +{ | |
322 | + fprintf(stderr,"r0: %2x\n",regs[0]); | |
323 | + fprintf(stderr,"r1: %2x\n",regs[1]); | |
324 | + fprintf(stderr,"r2: %2x\n",regs[2]); | |
325 | + fprintf(stderr,"r3: %2x\n",regs[3]); | |
326 | + fprintf(stderr,"r4: %2x\n",regs[4]); | |
327 | + fprintf(stderr,"r5: %2x\n",regs[5]); | |
328 | + fprintf(stderr,"r6: %2x\n",regs[6]); | |
329 | + fprintf(stderr,"r7: %2x\n",regs[7]); | |
330 | + fprintf(stderr,"pc: %2x\n",pc); | |
331 | + //dump memory to file | |
332 | + //dump stack to file | |
333 | + exit(1); | |
334 | +} | |
17 | 335 | \ No newline at end of file | ... | ... |
cpu.h
... | ... | @@ -6,5 +6,37 @@ |
6 | 6 | #define SYNACORVM_CPU_H |
7 | 7 | |
8 | 8 | #include <stdio.h> |
9 | +#include "mem.h" | |
10 | +#include "stack.h" | |
11 | +#include "registers.h" | |
12 | + | |
13 | +#define MAX_INT 32767 | |
14 | + | |
15 | +#define HALT 0x0000 | |
16 | +#define MOV 0x0001 | |
17 | +#define PUSH 0x0002 | |
18 | +#define POP 0x0003 | |
19 | +#define TEQ 0x0004 | |
20 | +#define TGT 0x0005 | |
21 | +#define JMP 0x0006 | |
22 | +#define JNZ 0x0007 | |
23 | +#define JZ 0x0008 | |
24 | +#define ADD 0x0009 | |
25 | +#define MULT 0x000A | |
26 | +#define MOD 0x000B | |
27 | +#define AND 0x000C | |
28 | +#define OR 0x000D | |
29 | +#define NOT 0x000E | |
30 | +#define LOAD 0x000F | |
31 | +#define STOR 0x0010 | |
32 | +#define CALL 0x0011 | |
33 | +#define RET 0x0012 | |
34 | +#define OUT 0x0013 | |
35 | +#define IN 0x0014 | |
36 | +#define NOP 0x0015 | |
37 | + | |
38 | + | |
39 | +void start_execution(); | |
40 | +void core_dump(); | |
9 | 41 | |
10 | 42 | #endif //SYNACORVM_CPU_H | ... | ... |
main.c
1 | 1 | #include <stdio.h> |
2 | +#include <string.h> | |
3 | +#include "mem.h" | |
4 | +#include "stack.h" | |
5 | + | |
6 | +void load_program(const char* path) | |
7 | +{ | |
8 | + FILE *fp = fopen(path,"r"); | |
9 | + fseek(fp, 0L, SEEK_END); | |
10 | + long file_size = ftell(fp); | |
11 | + rewind(fp); | |
12 | + fread(mem,1,(size_t)file_size,fp); | |
13 | + fclose(fp); | |
14 | +} | |
2 | 15 | |
3 | 16 | int main(int argc, char** argv) |
4 | 17 | { |
18 | + if(argc != 2) | |
19 | + { | |
20 | + printf("Invalid argument\n\n"); | |
21 | + printf(argv[0]); | |
22 | + printf(" path_to_binary\n"); | |
23 | + return 1; | |
24 | + } | |
25 | + initialize_stack(); | |
26 | + memset(regs,0x00,sizeof(short)*NUM_REGISTERS); | |
27 | + memset(mem,0x00,sizeof(short)*MEMSIZE); | |
28 | + load_program(argv[1]); | |
29 | + start_execution(); | |
30 | + free_stack(); | |
5 | 31 | return 0; |
6 | 32 | } |
7 | 33 | \ No newline at end of file | ... | ... |
binary_decoder.c renamed to mem.c
mem.h
binary_decoder.h renamed to registers.c
... | ... | @@ -2,7 +2,7 @@ |
2 | 2 | // Created by imanol on 12/25/16. |
3 | 3 | // |
4 | 4 | |
5 | -#ifndef SYNACORVM_BINARY_DECODER_H | |
6 | -#define SYNACORVM_BINARY_DECODER_H | |
5 | +#include "registers.h" | |
7 | 6 | |
8 | -#endif //SYNACORVM_BINARY_DECODER_H | |
7 | +short regs[NUM_REGISTERS]; | |
8 | +short pc = 0; | |
9 | 9 | \ No newline at end of file | ... | ... |
registers.h
... | ... | @@ -5,15 +5,9 @@ |
5 | 5 | #ifndef SYNACORVM_REGISTERS_H |
6 | 6 | #define SYNACORVM_REGISTERS_H |
7 | 7 | |
8 | -short r0 = 0; | |
9 | -short r1 = 0; | |
10 | -short r2 = 0; | |
11 | -short r3 = 0; | |
12 | -short r4 = 0; | |
13 | -short r5 = 0; | |
14 | -short r6 = 0; | |
15 | -short r7 = 0; | |
8 | +#define NUM_REGISTERS 8 | |
16 | 9 | |
17 | -short pc = 0; | |
10 | +extern short regs[NUM_REGISTERS]; | |
11 | +extern short pc; | |
18 | 12 | |
19 | 13 | #endif //SYNACORVM_REGISTERS_H | ... | ... |
stack.c
... | ... | @@ -7,6 +7,7 @@ |
7 | 7 | |
8 | 8 | #define EXTEND_SIZE 10 |
9 | 9 | |
10 | +uint8_t STACK_FAULT = 0; | |
10 | 11 | uint32_t stack_size = EXTEND_SIZE; |
11 | 12 | uint32_t stack_pos = 0; |
12 | 13 | short *stack; |
... | ... | @@ -16,19 +17,39 @@ void initialize_stack() |
16 | 17 | stack = calloc(EXTEND_SIZE,sizeof(short)); |
17 | 18 | } |
18 | 19 | |
20 | +void free_stack() | |
21 | +{ | |
22 | + free(stack); | |
23 | + stack_size = 0; | |
24 | + stack_pos = 0; | |
25 | + stack = NULL; | |
26 | +} | |
27 | + | |
19 | 28 | void extend_stack() |
20 | 29 | { |
21 | 30 | stack_size += EXTEND_SIZE; |
22 | - realloc(stack,stack_size*sizeof(short)); | |
31 | + void *new_ptr = realloc(stack,stack_size*sizeof(short)); | |
32 | + if(new_ptr == NULL) | |
33 | + { | |
34 | + fprintf(stderr,"CRITICAL: STACK ALLOCATION ERROR\n"); | |
35 | + core_dump(); | |
36 | + } | |
37 | + stack = new_ptr; | |
23 | 38 | } |
24 | 39 | |
25 | 40 | void shrink_stack() |
26 | 41 | { |
27 | 42 | stack_size -= EXTEND_SIZE; |
28 | - realloc(stack,stack_size*sizeof(short)); | |
43 | + void *new_ptr = realloc(stack,stack_size*sizeof(short)); | |
44 | + if(new_ptr == NULL) | |
45 | + { | |
46 | + fprintf(stderr,"CRITICAL: STACK ALLOCATION ERROR\n"); | |
47 | + core_dump(); | |
48 | + } | |
49 | + stack = new_ptr; | |
29 | 50 | } |
30 | 51 | |
31 | -void push(short value) | |
52 | +void stack_push(short value) | |
32 | 53 | { |
33 | 54 | stack[stack_pos++] = value; |
34 | 55 | if(stack_pos == stack_size-1) |
... | ... | @@ -36,12 +57,19 @@ void push(short value) |
36 | 57 | extend_stack(); |
37 | 58 | } |
38 | 59 | } |
39 | -short pop() | |
60 | + | |
61 | +short stack_pop() | |
40 | 62 | { |
63 | + if(!stack_pos) | |
64 | + { | |
65 | + STACK_FAULT = 1; | |
66 | + return -1; | |
67 | + } | |
41 | 68 | short value = stack[stack_pos--]; |
42 | 69 | if(stack_size - stack_pos == 2*EXTEND_SIZE) |
43 | 70 | { |
44 | 71 | shrink_stack(); |
45 | 72 | } |
46 | 73 | return value; |
47 | -} | |
48 | 74 | \ No newline at end of file |
75 | +} | |
76 | + | ... | ... |
stack.h
... | ... | @@ -6,9 +6,13 @@ |
6 | 6 | #define SYNACORVM_STACK_H |
7 | 7 | |
8 | 8 | #include <stdint.h> |
9 | +#include "cpu.h" | |
10 | + | |
11 | +extern uint8_t STACK_FAULT; | |
9 | 12 | |
10 | 13 | void initialize_stack(); |
11 | -void push(short value); | |
12 | -short pop(); | |
14 | +void free_stack(); | |
15 | +void stack_push(short value); | |
16 | +short stack_pop(); | |
13 | 17 | |
14 | 18 | #endif //SYNACORVM_STACK_H | ... | ... |