Commit 9ff101a8a3ee99925f58ed96d34e62e7a7220303
1 parent
91ff09d1
Improved general code structure (no longer a fucking mess), disassembler now pro…
…duces correct code and debugger doesn't suck so much (still has input issues)
Showing
12 changed files
with
460 additions
and
510 deletions
cpu.c
... | ... | @@ -239,149 +239,211 @@ uint16_t fetch() |
239 | 239 | return value; |
240 | 240 | } |
241 | 241 | |
242 | + | |
243 | +void decode_instruction(uint16_t opcode, uint16_t *arg1, uint16_t *arg2, uint16_t *arg3) | |
244 | +{ | |
245 | + switch(opcode) | |
246 | + { | |
247 | + case HALT: | |
248 | + break; | |
249 | + case MOV: | |
250 | + *arg1 = fetch(); | |
251 | + *arg2 = fetch(); | |
252 | + break; | |
253 | + case PUSH: | |
254 | + *arg1 = fetch(); | |
255 | + break; | |
256 | + case POP: | |
257 | + *arg1 = fetch(); | |
258 | + break; | |
259 | + case TEQ: | |
260 | + *arg1 = fetch(); | |
261 | + *arg2 = fetch(); | |
262 | + *arg3 = fetch(); | |
263 | + break; | |
264 | + case TGT: | |
265 | + *arg1 = fetch(); | |
266 | + *arg2 = fetch(); | |
267 | + *arg3 = fetch(); | |
268 | + break; | |
269 | + case JMP: | |
270 | + *arg1 = fetch(); | |
271 | + break; | |
272 | + case JNZ: | |
273 | + *arg1 = fetch(); | |
274 | + *arg2 = fetch(); | |
275 | + break; | |
276 | + case JZ: | |
277 | + *arg1 = fetch(); | |
278 | + *arg2 = fetch(); | |
279 | + break; | |
280 | + case ADD: | |
281 | + *arg1 = fetch(); | |
282 | + *arg2 = fetch(); | |
283 | + *arg3 = fetch(); | |
284 | + break; | |
285 | + case MUL: | |
286 | + *arg1 = fetch(); | |
287 | + *arg2 = fetch(); | |
288 | + *arg3 = fetch(); | |
289 | + break; | |
290 | + case MOD: | |
291 | + *arg1 = fetch(); | |
292 | + *arg2 = fetch(); | |
293 | + *arg3 = fetch(); | |
294 | + break; | |
295 | + case AND: | |
296 | + *arg1 = fetch(); | |
297 | + *arg2 = fetch(); | |
298 | + *arg3 = fetch(); | |
299 | + break; | |
300 | + case OR: | |
301 | + *arg1 = fetch(); | |
302 | + *arg2 = fetch(); | |
303 | + *arg3 = fetch(); | |
304 | + break; | |
305 | + case NOT: | |
306 | + *arg1 = fetch(); | |
307 | + *arg2 = fetch(); | |
308 | + break; | |
309 | + case LOAD: | |
310 | + *arg1 = fetch(); | |
311 | + *arg2 = fetch(); | |
312 | + break; | |
313 | + case STOR: | |
314 | + *arg1 = fetch(); | |
315 | + *arg2 = fetch(); | |
316 | + break; | |
317 | + case CALL: | |
318 | + *arg1 = fetch(); | |
319 | + break; | |
320 | + case RET: | |
321 | + break; | |
322 | + case OUT: | |
323 | + *arg1 = fetch(); | |
324 | + break; | |
325 | + case IN: | |
326 | + *arg1 = fetch(); | |
327 | + break; | |
328 | + case NOP: | |
329 | + break; | |
330 | + default: | |
331 | + break; | |
332 | + } | |
333 | +} | |
334 | + | |
335 | +uint8_t execute_instruction(uint16_t opcode, uint16_t arg1, uint16_t arg2, uint16_t arg3) | |
336 | +{ | |
337 | + switch(opcode) | |
338 | + { | |
339 | + case HALT: | |
340 | + return 1; | |
341 | + case MOV: | |
342 | + mov(arg1,arg2); | |
343 | + break; | |
344 | + case PUSH: | |
345 | + push(arg1); | |
346 | + break; | |
347 | + case POP: | |
348 | + pop(arg1); | |
349 | + break; | |
350 | + case TEQ: | |
351 | + teq(arg1,arg2,arg3); | |
352 | + break; | |
353 | + case TGT: | |
354 | + tgt(arg1,arg2,arg3); | |
355 | + break; | |
356 | + case JMP: | |
357 | + jmp(arg1); | |
358 | + break; | |
359 | + case JNZ: | |
360 | + jnz(arg1,arg2); | |
361 | + break; | |
362 | + case JZ: | |
363 | + jz(arg1,arg2); | |
364 | + break; | |
365 | + case ADD: | |
366 | + add(arg1,arg2,arg3); | |
367 | + break; | |
368 | + case MUL: | |
369 | + mul(arg1,arg2,arg3); | |
370 | + break; | |
371 | + case MOD: | |
372 | + mod(arg1,arg2,arg3); | |
373 | + break; | |
374 | + case AND: | |
375 | + and(arg1,arg2,arg3); | |
376 | + break; | |
377 | + case OR: | |
378 | + or(arg1,arg2,arg3); | |
379 | + break; | |
380 | + case NOT: | |
381 | + not(arg1,arg2); | |
382 | + break; | |
383 | + case LOAD: | |
384 | + load(arg1,arg2); | |
385 | + break; | |
386 | + case STOR: | |
387 | + stor(arg1,arg2); | |
388 | + break; | |
389 | + case CALL: | |
390 | + call(arg1); | |
391 | + break; | |
392 | + case RET: | |
393 | + if(ret()) | |
394 | + { | |
395 | + return 1; | |
396 | + } | |
397 | + break; | |
398 | + case OUT: | |
399 | + out(arg1); | |
400 | + break; | |
401 | + case IN: | |
402 | + in(arg1); | |
403 | + break; | |
404 | + case NOP: | |
405 | + nop(); | |
406 | + break; | |
407 | + default: | |
408 | + fprintf(stderr,"CRITICAL: UNKNOWN OPCODE %2x FOUND IN %2x\n",opcode,pc); | |
409 | + core_dump(); | |
410 | + break; | |
411 | + } | |
412 | + return 0; | |
413 | +} | |
414 | + | |
242 | 415 | void start_execution() |
243 | 416 | { |
244 | 417 | uint16_t arg1; |
245 | 418 | uint16_t arg2; |
246 | 419 | uint16_t arg3; |
420 | + | |
247 | 421 | for(;;) |
248 | 422 | { |
249 | 423 | uint16_t opcode = fetch(); |
250 | - switch(opcode) | |
424 | + decode_instruction(opcode, &arg1, &arg2, &arg3); | |
425 | + if(execute_instruction(opcode, arg1, arg2, arg3)) | |
251 | 426 | { |
252 | - case HALT: | |
253 | - return; | |
254 | - case MOV: | |
255 | - arg1 = fetch(); | |
256 | - arg2 = fetch(); | |
257 | - mov(arg1,arg2); | |
258 | - break; | |
259 | - case PUSH: | |
260 | - arg1 = fetch(); | |
261 | - push(arg1); | |
262 | - break; | |
263 | - case POP: | |
264 | - arg1 = fetch(); | |
265 | - pop(arg1); | |
266 | - break; | |
267 | - case TEQ: | |
268 | - arg1 = fetch(); | |
269 | - arg2 = fetch(); | |
270 | - arg3 = fetch(); | |
271 | - teq(arg1,arg2,arg3); | |
272 | - break; | |
273 | - case TGT: | |
274 | - arg1 = fetch(); | |
275 | - arg2 = fetch(); | |
276 | - arg3 = fetch(); | |
277 | - tgt(arg1,arg2,arg3); | |
278 | - break; | |
279 | - case JMP: | |
280 | - arg1 = fetch(); | |
281 | - jmp(arg1); | |
282 | - break; | |
283 | - case JNZ: | |
284 | - arg1 = fetch(); | |
285 | - arg2 = fetch(); | |
286 | - jnz(arg1,arg2); | |
287 | - break; | |
288 | - case JZ: | |
289 | - arg1 = fetch(); | |
290 | - arg2 = fetch(); | |
291 | - jz(arg1,arg2); | |
292 | - break; | |
293 | - case ADD: | |
294 | - arg1 = fetch(); | |
295 | - arg2 = fetch(); | |
296 | - arg3 = fetch(); | |
297 | - add(arg1,arg2,arg3); | |
298 | - break; | |
299 | - case MUL: | |
300 | - arg1 = fetch(); | |
301 | - arg2 = fetch(); | |
302 | - arg3 = fetch(); | |
303 | - mul(arg1,arg2,arg3); | |
304 | - break; | |
305 | - case MOD: | |
306 | - arg1 = fetch(); | |
307 | - arg2 = fetch(); | |
308 | - arg3 = fetch(); | |
309 | - mod(arg1,arg2,arg3); | |
310 | - break; | |
311 | - case AND: | |
312 | - arg1 = fetch(); | |
313 | - arg2 = fetch(); | |
314 | - arg3 = fetch(); | |
315 | - and(arg1,arg2,arg3); | |
316 | - break; | |
317 | - case OR: | |
318 | - arg1 = fetch(); | |
319 | - arg2 = fetch(); | |
320 | - arg3 = fetch(); | |
321 | - or(arg1,arg2,arg3); | |
322 | - break; | |
323 | - case NOT: | |
324 | - arg1 = fetch(); | |
325 | - arg2 = fetch(); | |
326 | - not(arg1,arg2); | |
327 | - break; | |
328 | - case LOAD: | |
329 | - arg1 = fetch(); | |
330 | - arg2 = fetch(); | |
331 | - load(arg1,arg2); | |
332 | - break; | |
333 | - case STOR: | |
334 | - arg1 = fetch(); | |
335 | - arg2 = fetch(); | |
336 | - stor(arg1,arg2); | |
337 | - break; | |
338 | - case CALL: | |
339 | - arg1 = fetch(); | |
340 | - call(arg1); | |
341 | - break; | |
342 | - case RET: | |
343 | - if(ret()) | |
344 | - { | |
345 | - return; | |
346 | - } | |
347 | - break; | |
348 | - case OUT: | |
349 | - arg1 = fetch(); | |
350 | - out(arg1); | |
351 | - break; | |
352 | - case IN: | |
353 | - arg1 = fetch(); | |
354 | - in(arg1); | |
355 | - break; | |
356 | - case NOP: | |
357 | - nop(); | |
358 | - break; | |
359 | - default: | |
360 | - fprintf(stderr,"CRITICAL: UNKNOWN OPCODE %2x FOUND IN %2x\n",opcode,pc); | |
361 | - core_dump(); | |
362 | - break; | |
427 | + return; | |
363 | 428 | } |
364 | 429 | } |
365 | 430 | } |
366 | 431 | |
367 | -void print_regs() | |
368 | -{ | |
369 | - fprintf(stderr,"r0: %2x\n",regs[0]); | |
370 | - fprintf(stderr,"r1: %2x\n",regs[1]); | |
371 | - fprintf(stderr,"r2: %2x\n",regs[2]); | |
372 | - fprintf(stderr,"r3: %2x\n",regs[3]); | |
373 | - fprintf(stderr,"r4: %2x\n",regs[4]); | |
374 | - fprintf(stderr,"r5: %2x\n",regs[5]); | |
375 | - fprintf(stderr,"r6: %2x\n",regs[6]); | |
376 | - fprintf(stderr,"r7: %2x\n",regs[7]); | |
377 | - fprintf(stderr,"pc: %2x\n",pc); | |
378 | -} | |
379 | - | |
380 | 432 | void core_dump() |
381 | 433 | { |
382 | 434 | print_regs(); |
383 | - //dump memory to file | |
384 | - //dump stack to file | |
435 | + uint16_t memdump[MEMSIZE]; | |
436 | + uint16_t *stackdump; | |
437 | + dump_memory(memdump); | |
438 | + uint32_t stacksize = stack_dump(&stackdump); | |
439 | + | |
440 | + FILE *fpm = fopen("synacor.mem","w"); | |
441 | + FILE *fps = fopen("synacor.stack","w"); | |
442 | + fwrite(memdump,MEMSIZE,sizeof(uint16_t),fpm); | |
443 | + fwrite(stackdump,stacksize,sizeof(uint16_t),fps); | |
444 | + fclose(fpm); | |
445 | + fclose(fps); | |
446 | + | |
385 | 447 | exit(1); |
386 | 448 | } |
387 | 449 | ... | ... |
cpu.h
... | ... | @@ -35,8 +35,11 @@ void out(uint16_t src); |
35 | 35 | void in(uint16_t dst); |
36 | 36 | void nop(); |
37 | 37 | |
38 | +uint8_t execute_instruction(uint16_t opcode, uint16_t arg1, uint16_t arg2, uint16_t arg3); | |
38 | 39 | void start_execution(); |
39 | 40 | void core_dump(); |
40 | -void print_regs(); | |
41 | +void print_instruction(uint16_t opcode, uint16_t arg1, uint16_t arg2, uint16_t arg3); | |
42 | +void decode_instruction(uint16_t opcode, uint16_t *arg1, uint16_t *arg2, uint16_t *arg3); | |
43 | + | |
41 | 44 | |
42 | 45 | #endif //SYNACORVM_CPU_H | ... | ... |
debug.c
... | ... | @@ -6,53 +6,74 @@ |
6 | 6 | #include <string.h> |
7 | 7 | #include "debug.h" |
8 | 8 | |
9 | -uint64_t cycle_count = 0; | |
9 | +//uint32_t cycle_count = 0; | |
10 | 10 | uint8_t breakpoint = 1; |
11 | 11 | uint16_t breakpoints[0xFF]; |
12 | 12 | uint16_t nbpoints = 0; |
13 | 13 | char lastchoice = 0; |
14 | 14 | |
15 | -uint8_t in_breakpoint(uint16_t pc) | |
15 | +void load_state(char *filename) | |
16 | 16 | { |
17 | - uint8_t i; | |
18 | - for(i = 0; i < nbpoints; i++) | |
19 | - { | |
20 | - if(breakpoints[i] == pc) | |
21 | - { | |
22 | - return 1; | |
23 | - } | |
24 | - } | |
25 | - return 0; | |
17 | + FILE *state = fopen(filename,"r"); | |
18 | + uint16_t regsdump[NUM_REGISTERS+1]; | |
19 | + uint16_t memdump[MEMSIZE]; | |
20 | + uint16_t *stackdump; | |
21 | + uint32_t stacksize, stackpos; | |
22 | + | |
23 | + fread(regsdump,sizeof(uint16_t),NUM_REGISTERS+1,state); | |
24 | + fread(memdump,sizeof(uint16_t),MEMSIZE,state); | |
25 | + stackpos = ftell(state); | |
26 | + fseek(state,0,SEEK_END); | |
27 | + stacksize = (ftell(state) - stackpos)/sizeof(uint16_t); | |
28 | + stackdump = calloc(stacksize,sizeof(uint16_t)); | |
29 | + fseek(state,stackpos,SEEK_SET); | |
30 | + fread(stackdump,sizeof(uint16_t),stacksize,state); | |
31 | + fclose(state); | |
32 | + | |
33 | + load_regs(regsdump); | |
34 | + load_memory(memdump); | |
35 | + stack_load(stackdump,stacksize); | |
36 | + | |
37 | + free(stackdump); | |
26 | 38 | } |
27 | 39 | |
28 | -uint16_t fetch_debug() | |
40 | +void save_state(char *filename) | |
29 | 41 | { |
30 | - if(in_breakpoint(pc)) | |
31 | - { | |
32 | - breakpoint = 1; | |
33 | - } | |
34 | - uint16_t value = mem[pc++]; | |
35 | - /*if(breakpoint) | |
36 | - { | |
37 | - fprintf(stderr,"0x%2x (0x%2x): %d", pc, pc * sizeof(uint16_t),value); | |
38 | - fprintf(stderr," cycle: %d\n", cycle_count++); | |
39 | - }*/ | |
40 | - return value; | |
42 | + FILE *state = fopen(filename,"w"); | |
43 | + uint16_t regsdump[NUM_REGISTERS+1]; | |
44 | + uint16_t memdump[MEMSIZE]; | |
45 | + uint16_t *stackdump; | |
46 | + uint32_t stacksize; | |
47 | + | |
48 | + dump_regs(regsdump); | |
49 | + dump_memory(memdump); | |
50 | + stacksize = stack_dump(&stackdump); | |
51 | + | |
52 | + fwrite(regsdump,sizeof(uint16_t),NUM_REGISTERS+1,state); | |
53 | + fwrite(memdump,sizeof(uint16_t),MEMSIZE,state); | |
54 | + fwrite(stackdump,sizeof(uint16_t),stacksize,state); | |
55 | + fclose(state); | |
56 | + free(stackdump); | |
41 | 57 | } |
42 | 58 | |
43 | 59 | void query() |
44 | 60 | { |
61 | + //TODO discard stdin | |
45 | 62 | uint8_t end = 0; |
46 | 63 | uint16_t bpoint; |
47 | 64 | uint16_t mempos; |
65 | + char input[100] = {0}; | |
66 | + char filename[32]; | |
67 | + uint8_t reg; | |
68 | + uint8_t value; | |
48 | 69 | while(!end) |
49 | 70 | { |
50 | 71 | printf("\n> "); |
51 | - char command; | |
52 | - scanf("%c", &command); | |
72 | + char command = 0; | |
73 | + fgets(input,100,stdin); | |
74 | + command = input[0]; | |
53 | 75 | if (command != '\n') |
54 | 76 | { |
55 | - getchar(); | |
56 | 77 | lastchoice = command; |
57 | 78 | } |
58 | 79 | else |
... | ... | @@ -62,15 +83,15 @@ void query() |
62 | 83 | switch (command) |
63 | 84 | { |
64 | 85 | case 'b': |
65 | - scanf("%d%*c",&bpoint); | |
86 | + sscanf(input,"b %d\n",&bpoint); | |
66 | 87 | fprintf(stderr,"Set breakpoint %d to %d",nbpoints,bpoint); |
67 | 88 | breakpoints[nbpoints] = bpoint; |
68 | 89 | nbpoints = nbpoints + 1 % 0xFF; |
69 | 90 | break; |
70 | 91 | case 'd': |
71 | - scanf("%d%*c",&bpoint); | |
92 | + sscanf(input,"d %d\n",&bpoint); | |
72 | 93 | fprintf(stderr,"Deleted breakpoint %d",bpoint); |
73 | - breakpoints[bpoint] = NULL; | |
94 | + breakpoints[bpoint] = 0; | |
74 | 95 | break; |
75 | 96 | case 'c': |
76 | 97 | breakpoint = 0; |
... | ... | @@ -83,15 +104,131 @@ void query() |
83 | 104 | print_regs(); |
84 | 105 | break; |
85 | 106 | case 'm': |
86 | - scanf("%d%*c",&mempos); | |
107 | + sscanf(input,"m %d\n",&mempos); | |
87 | 108 | fprintf(stderr,"%d: %02x\n",mempos,mem[mempos]); |
88 | 109 | break; |
110 | + case 's': | |
111 | + sscanf(input,"s %s\n",filename); | |
112 | + save_state(filename); | |
113 | + fprintf(stderr,"Saved state as %s",filename); | |
114 | + break; | |
115 | + case 'l': | |
116 | + sscanf(input,"l %s\n",filename); | |
117 | + load_state(filename); | |
118 | + fprintf(stderr,"Loaded state as %s",filename); | |
119 | + break; | |
120 | + case 'w': | |
121 | + sscanf(input,"w %d %d\n",®,&value); | |
122 | + fprintf(stderr,"Setting register %d to %d",reg,value); | |
123 | + regs[reg] = value; | |
124 | + break; | |
89 | 125 | default: |
90 | 126 | break; |
91 | 127 | } |
92 | 128 | } |
93 | 129 | } |
94 | 130 | |
131 | +uint8_t in_breakpoint(uint16_t pc) | |
132 | +{ | |
133 | + uint8_t i; | |
134 | + for(i = 0; i < nbpoints; i++) | |
135 | + { | |
136 | + if(breakpoints[i] == pc) | |
137 | + { | |
138 | + return 1; | |
139 | + } | |
140 | + } | |
141 | + return 0; | |
142 | +} | |
143 | + | |
144 | +uint16_t fetch_debug() | |
145 | +{ | |
146 | + uint16_t value = mem[pc++]; | |
147 | + /*if(breakpoint) | |
148 | + { | |
149 | + fprintf(stderr,"0x%2x (0x%2x): %d", pc, pc * sizeof(uint16_t),value); | |
150 | + fprintf(stderr," cycle: %d\n", cycle_count++); | |
151 | + }*/ | |
152 | + return value; | |
153 | +} | |
154 | + | |
155 | +void print_instruction(uint16_t opcode, uint16_t arg1, uint16_t arg2, uint16_t arg3) | |
156 | +{ | |
157 | + switch(opcode) | |
158 | + { | |
159 | + case HALT: | |
160 | + printf("HALT\n"); | |
161 | + break; | |
162 | + case MOV: | |
163 | + printf("MOV %d %d\n",arg1,arg2); | |
164 | + break; | |
165 | + case PUSH: | |
166 | + printf("PUSH %d\n",arg1); | |
167 | + break; | |
168 | + case POP: | |
169 | + printf("POP %d\n",arg1); | |
170 | + break; | |
171 | + case TEQ: | |
172 | + printf("TEQ %d %d %d\n",arg1,arg2,arg3); | |
173 | + break; | |
174 | + case TGT: | |
175 | + printf("TGT %d %d %d\n",arg1,arg2,arg3); | |
176 | + break; | |
177 | + case JMP: | |
178 | + printf("JMP %d\n",arg1); | |
179 | + break; | |
180 | + case JNZ: | |
181 | + printf("JNZ %d %d\n",arg1,arg2); | |
182 | + break; | |
183 | + case JZ: | |
184 | + printf("JZ %d %d\n",arg1,arg2); | |
185 | + break; | |
186 | + case ADD: | |
187 | + printf("ADD %d %d %d\n",arg1,arg2,arg3); | |
188 | + break; | |
189 | + case MUL: | |
190 | + printf("MUL %d %d %d\n",arg1,arg2,arg3); | |
191 | + break; | |
192 | + case MOD: | |
193 | + printf("MOD %d %d %d\n",arg1,arg2,arg3); | |
194 | + break; | |
195 | + case AND: | |
196 | + printf("AND %d %d %d\n",arg1,arg2,arg3); | |
197 | + break; | |
198 | + case OR: | |
199 | + printf("OR %d %d %d\n",arg1,arg2,arg3); | |
200 | + break; | |
201 | + case NOT: | |
202 | + printf("NOT %d %d\n",arg1,arg2); | |
203 | + break; | |
204 | + case LOAD: | |
205 | + printf("LOAD %d %d\n",arg1,arg2); | |
206 | + break; | |
207 | + case STOR: | |
208 | + printf("STOR %d %d\n",arg1,arg2); | |
209 | + break; | |
210 | + case CALL: | |
211 | + printf("CALL %d\n",arg1); | |
212 | + break; | |
213 | + case RET: | |
214 | + printf("RET\n"); | |
215 | + break; | |
216 | + case OUT: | |
217 | + printf("OUT %d\n",arg1); | |
218 | + break; | |
219 | + case IN: | |
220 | + printf("IN %d\n",arg1); | |
221 | + break; | |
222 | + case NOP: | |
223 | + printf("NOP\n"); | |
224 | + break; | |
225 | + default: | |
226 | + printf("UNK %d\n", opcode); | |
227 | + break; | |
228 | + } | |
229 | +} | |
230 | + | |
231 | + | |
95 | 232 | void debug_program() |
96 | 233 | { |
97 | 234 | memset(breakpoints,0x00,0xFF); |
... | ... | @@ -100,234 +237,18 @@ void debug_program() |
100 | 237 | uint16_t arg3; |
101 | 238 | for(;;) |
102 | 239 | { |
103 | - if(breakpoint) | |
240 | + if(in_breakpoint(pc) || breakpoint) | |
104 | 241 | { |
105 | - fprintf(stderr,"%d: ",pc); | |
242 | + breakpoint = 1; | |
243 | + fprintf(stderr, "%d: ", pc); | |
244 | + print_instruction(mem[pc], mem[pc+1], mem[pc+2], mem[pc+3]); | |
245 | + query(); | |
106 | 246 | } |
107 | 247 | uint16_t opcode = fetch_debug(); |
108 | - switch(opcode) | |
248 | + decode_instruction(opcode, &arg1, &arg2, &arg3); | |
249 | + if (execute_instruction(opcode, arg1, arg2, arg3)) | |
109 | 250 | { |
110 | - case HALT: | |
111 | - if(breakpoint) | |
112 | - { | |
113 | - fprintf(stderr,"HALT\n"); | |
114 | - query(); | |
115 | - } | |
116 | - return; | |
117 | - case MOV: | |
118 | - arg1 = fetch_debug(); | |
119 | - arg2 = fetch_debug(); | |
120 | - if(breakpoint) | |
121 | - { | |
122 | - fprintf(stderr,"MOV %d %d\n",arg1,arg2); | |
123 | - query(); | |
124 | - } | |
125 | - mov(arg1,arg2); | |
126 | - break; | |
127 | - case PUSH: | |
128 | - arg1 = fetch_debug(); | |
129 | - if(breakpoint) | |
130 | - { | |
131 | - fprintf(stderr,"PUSH %d\n",arg1); | |
132 | - query(); | |
133 | - } | |
134 | - push(arg1); | |
135 | - break; | |
136 | - case POP: | |
137 | - arg1 = fetch_debug(); | |
138 | - if(breakpoint) | |
139 | - { | |
140 | - fprintf(stderr,"POP %d\n",arg1); | |
141 | - query(); | |
142 | - } | |
143 | - pop(arg1); | |
144 | - break; | |
145 | - case TEQ: | |
146 | - arg1 = fetch_debug(); | |
147 | - arg2 = fetch_debug(); | |
148 | - arg3 = fetch_debug(); | |
149 | - if(breakpoint) | |
150 | - { | |
151 | - fprintf(stderr,"TEQ %d %d %d\n",arg1,arg2,arg3); | |
152 | - query(); | |
153 | - } | |
154 | - teq(arg1,arg2,arg3); | |
155 | - break; | |
156 | - case TGT: | |
157 | - arg1 = fetch_debug(); | |
158 | - arg2 = fetch_debug(); | |
159 | - arg3 = fetch_debug(); | |
160 | - if(breakpoint) | |
161 | - { | |
162 | - fprintf(stderr,"TGT %d %d %d\n",arg1,arg2,arg3); | |
163 | - query(); | |
164 | - } | |
165 | - tgt(arg1,arg2,arg3); | |
166 | - break; | |
167 | - case JMP: | |
168 | - arg1 = fetch_debug(); | |
169 | - if(breakpoint) | |
170 | - { | |
171 | - fprintf(stderr,"JMP %d\n",arg1); | |
172 | - query(); | |
173 | - } | |
174 | - jmp(arg1); | |
175 | - break; | |
176 | - case JNZ: | |
177 | - arg1 = fetch_debug(); | |
178 | - arg2 = fetch_debug(); | |
179 | - if(breakpoint) | |
180 | - { | |
181 | - fprintf(stderr,"JNZ %d %d\n",arg1,arg2); | |
182 | - query(); | |
183 | - } | |
184 | - jnz(arg1,arg2); | |
185 | - break; | |
186 | - case JZ: | |
187 | - arg1 = fetch_debug(); | |
188 | - arg2 = fetch_debug(); | |
189 | - if(breakpoint) | |
190 | - { | |
191 | - fprintf(stderr,"JZ %d %d\n",arg1,arg2); | |
192 | - query(); | |
193 | - } | |
194 | - jz(arg1,arg2); | |
195 | - break; | |
196 | - case ADD: | |
197 | - arg1 = fetch_debug(); | |
198 | - arg2 = fetch_debug(); | |
199 | - arg3 = fetch_debug(); | |
200 | - if(breakpoint) | |
201 | - { | |
202 | - fprintf(stderr,"ADD %d %d %d\n",arg1,arg2,arg3); | |
203 | - query(); | |
204 | - } | |
205 | - add(arg1,arg2,arg3); | |
206 | - break; | |
207 | - case MUL: | |
208 | - arg1 = fetch_debug(); | |
209 | - arg2 = fetch_debug(); | |
210 | - arg3 = fetch_debug(); | |
211 | - if(breakpoint) | |
212 | - { | |
213 | - fprintf(stderr,"MUL %d %d %d\n",arg1,arg2,arg3); | |
214 | - query(); | |
215 | - } | |
216 | - mul(arg1,arg2,arg3); | |
217 | - break; | |
218 | - case MOD: | |
219 | - arg1 = fetch_debug(); | |
220 | - arg2 = fetch_debug(); | |
221 | - arg3 = fetch_debug(); | |
222 | - if(breakpoint) | |
223 | - { | |
224 | - fprintf(stderr,"MOD %d %d %d\n",arg1,arg2,arg3); | |
225 | - query(); | |
226 | - } | |
227 | - mod(arg1,arg2,arg3); | |
228 | - break; | |
229 | - case AND: | |
230 | - arg1 = fetch_debug(); | |
231 | - arg2 = fetch_debug(); | |
232 | - arg3 = fetch_debug(); | |
233 | - if(breakpoint) | |
234 | - { | |
235 | - fprintf(stderr,"AND %d %d %d\n",arg1,arg2,arg3); | |
236 | - query(); | |
237 | - } | |
238 | - and(arg1,arg2,arg3); | |
239 | - break; | |
240 | - case OR: | |
241 | - arg1 = fetch_debug(); | |
242 | - arg2 = fetch_debug(); | |
243 | - arg3 = fetch_debug(); | |
244 | - if(breakpoint) | |
245 | - { | |
246 | - fprintf(stderr,"OR %d %d %d\n",arg1,arg2,arg3); | |
247 | - query(); | |
248 | - } | |
249 | - or(arg1,arg2,arg3); | |
250 | - break; | |
251 | - case NOT: | |
252 | - arg1 = fetch_debug(); | |
253 | - arg2 = fetch_debug(); | |
254 | - if(breakpoint) | |
255 | - { | |
256 | - fprintf(stderr,"NOT %d %d\n",arg1,arg2); | |
257 | - query(); | |
258 | - } | |
259 | - not(arg1,arg2); | |
260 | - break; | |
261 | - case LOAD: | |
262 | - arg1 = fetch_debug(); | |
263 | - arg2 = fetch_debug(); | |
264 | - if(breakpoint) | |
265 | - { | |
266 | - fprintf(stderr,"LOAD %d %d\n",arg1,arg2); | |
267 | - query(); | |
268 | - } | |
269 | - load(arg1,arg2); | |
270 | - break; | |
271 | - case STOR: | |
272 | - arg1 = fetch_debug(); | |
273 | - arg2 = fetch_debug(); | |
274 | - if(breakpoint) | |
275 | - { | |
276 | - fprintf(stderr,"STOR %d %d\n",arg1,arg2); | |
277 | - query(); | |
278 | - } | |
279 | - stor(arg1,arg2); | |
280 | - break; | |
281 | - case CALL: | |
282 | - arg1 = fetch_debug(); | |
283 | - if(breakpoint) | |
284 | - { | |
285 | - fprintf(stderr,"CALL %d\n",arg1); | |
286 | - query(); | |
287 | - } | |
288 | - call(arg1); | |
289 | - break; | |
290 | - case RET: | |
291 | - if(breakpoint) | |
292 | - { | |
293 | - fprintf(stderr,"RET\n"); | |
294 | - query(); | |
295 | - } | |
296 | - if(ret()) | |
297 | - { | |
298 | - return; | |
299 | - } | |
300 | - break; | |
301 | - case OUT: | |
302 | - arg1 = fetch_debug(); | |
303 | - if(breakpoint) | |
304 | - { | |
305 | - fprintf(stderr,"OUT %d\n",arg1); | |
306 | - query(); | |
307 | - } | |
308 | - out(arg1); | |
309 | - break; | |
310 | - case IN: | |
311 | - arg1 = fetch_debug(); | |
312 | - if(breakpoint) | |
313 | - { | |
314 | - fprintf(stderr,"IN %d\n",arg1); | |
315 | - query(); | |
316 | - } | |
317 | - in(arg1); | |
318 | - break; | |
319 | - case NOP: | |
320 | - if(breakpoint) | |
321 | - { | |
322 | - fprintf(stderr,"NOP\n"); | |
323 | - query(); | |
324 | - } | |
325 | - nop(); | |
326 | - break; | |
327 | - default: | |
328 | - fprintf(stderr,"CRITICAL: UNKNOWN OPCODE %2x FOUND IN %2x\n",opcode,pc); | |
329 | - core_dump(); | |
330 | - break; | |
251 | + return; | |
331 | 252 | } |
332 | 253 | } |
333 | 254 | } |
334 | 255 | \ No newline at end of file | ... | ... |
disasm.c
1 | 1 | #include "disasm.h" |
2 | 2 | |
3 | -void disassemble_program(uint64_t length) | |
3 | +void disassemble_program(uint32_t length) | |
4 | 4 | { |
5 | 5 | uint16_t arg1; |
6 | 6 | uint16_t arg2; |
... | ... | @@ -11,118 +11,9 @@ void disassemble_program(uint64_t length) |
11 | 11 | { |
12 | 12 | break; |
13 | 13 | } |
14 | - uint16_t opcode = fetch(); | |
15 | 14 | printf("%d: ",pc); |
16 | - switch(opcode) | |
17 | - { | |
18 | - case HALT: | |
19 | - printf("HALT\n"); | |
20 | - break; | |
21 | - case MOV: | |
22 | - arg1 = fetch(); | |
23 | - arg2 = fetch(); | |
24 | - printf("MOV %d %d\n",arg1,arg2); | |
25 | - break; | |
26 | - case PUSH: | |
27 | - arg1 = fetch(); | |
28 | - printf("PUSH %d\n",arg1); | |
29 | - break; | |
30 | - case POP: | |
31 | - arg1 = fetch(); | |
32 | - printf("POP %d\n",arg1); | |
33 | - break; | |
34 | - case TEQ: | |
35 | - arg1 = fetch(); | |
36 | - arg2 = fetch(); | |
37 | - arg3 = fetch(); | |
38 | - printf("TEQ %d %d %d\n",arg1,arg2,arg3); | |
39 | - break; | |
40 | - case TGT: | |
41 | - arg1 = fetch(); | |
42 | - arg2 = fetch(); | |
43 | - arg3 = fetch(); | |
44 | - printf("TGT %d %d %d\n",arg1,arg2,arg3); | |
45 | - break; | |
46 | - case JMP: | |
47 | - arg1 = fetch(); | |
48 | - printf("JMP %d\n",arg1); | |
49 | - break; | |
50 | - case JNZ: | |
51 | - arg1 = fetch(); | |
52 | - arg2 = fetch(); | |
53 | - printf("JNZ %d %d\n",arg1,arg2); | |
54 | - break; | |
55 | - case JZ: | |
56 | - arg1 = fetch(); | |
57 | - arg2 = fetch(); | |
58 | - printf("JZ %d %d\n",arg1,arg2); | |
59 | - break; | |
60 | - case ADD: | |
61 | - arg1 = fetch(); | |
62 | - arg2 = fetch(); | |
63 | - arg3 = fetch(); | |
64 | - printf("ADD %d %d %d\n",arg1,arg2,arg3); | |
65 | - break; | |
66 | - case MUL: | |
67 | - arg1 = fetch(); | |
68 | - arg2 = fetch(); | |
69 | - arg3 = fetch(); | |
70 | - printf("MUL %d %d %d\n",arg1,arg2,arg3); | |
71 | - break; | |
72 | - case MOD: | |
73 | - arg1 = fetch(); | |
74 | - arg2 = fetch(); | |
75 | - arg3 = fetch(); | |
76 | - printf("MOD %d %d %d\n",arg1,arg2,arg3); | |
77 | - break; | |
78 | - case AND: | |
79 | - arg1 = fetch(); | |
80 | - arg2 = fetch(); | |
81 | - arg3 = fetch(); | |
82 | - printf("AND %d %d %d\n",arg1,arg2,arg3); | |
83 | - break; | |
84 | - case OR: | |
85 | - arg1 = fetch(); | |
86 | - arg2 = fetch(); | |
87 | - arg3 = fetch(); | |
88 | - printf("OR %d %d %d\n",arg1,arg2,arg3); | |
89 | - break; | |
90 | - case NOT: | |
91 | - arg1 = fetch(); | |
92 | - arg2 = fetch(); | |
93 | - printf("NOT %d %d\n",arg1,arg2); | |
94 | - break; | |
95 | - case LOAD: | |
96 | - arg1 = fetch(); | |
97 | - arg2 = fetch(); | |
98 | - printf("LOAD %d %d\n",arg1,arg2); | |
99 | - break; | |
100 | - case STOR: | |
101 | - arg1 = fetch(); | |
102 | - arg2 = fetch(); | |
103 | - printf("STOR %d %d\n",arg1,arg2); | |
104 | - break; | |
105 | - case CALL: | |
106 | - arg1 = fetch(); | |
107 | - printf("CALL %d\n",arg1); | |
108 | - break; | |
109 | - case RET: | |
110 | - printf("RET\n"); | |
111 | - break; | |
112 | - case OUT: | |
113 | - arg1 = fetch(); | |
114 | - printf("OUT %d\n",arg1); | |
115 | - break; | |
116 | - case IN: | |
117 | - arg1 = fetch(); | |
118 | - printf("IN %d\n",arg1); | |
119 | - break; | |
120 | - case NOP: | |
121 | - printf("NOP\n"); | |
122 | - break; | |
123 | - default: | |
124 | - printf("UNK %d\n", opcode); | |
125 | - break; | |
126 | - } | |
15 | + uint16_t opcode = fetch(); | |
16 | + decode_instruction(opcode,&arg1,&arg2,&arg3); | |
17 | + print_instruction(opcode,arg1,arg2,arg3); | |
127 | 18 | } |
128 | 19 | } | ... | ... |
disasm.h
... | ... | @@ -10,8 +10,9 @@ |
10 | 10 | #include "registers.h" |
11 | 11 | #include "mem.h" |
12 | 12 | #include "instructions.h" |
13 | +#include "debug.h" | |
13 | 14 | |
14 | 15 | extern uint16_t fetch(); |
15 | -void disassemble_program(uint64_t length); | |
16 | +void disassemble_program(uint32_t length); | |
16 | 17 | |
17 | 18 | #endif //SYNACORVM_DISASM_H |
18 | 19 | \ No newline at end of file | ... | ... |
main.c
... | ... | @@ -6,7 +6,7 @@ |
6 | 6 | #include "disasm.h" |
7 | 7 | #include "debug.h" |
8 | 8 | |
9 | -uint64_t load_program(const char* path) | |
9 | +uint32_t load_program(const char* path) | |
10 | 10 | { |
11 | 11 | FILE *fp = fopen(path,"r"); |
12 | 12 | fseek(fp, 0L, SEEK_END); |
... | ... | @@ -20,8 +20,8 @@ uint64_t load_program(const char* path) |
20 | 20 | void startvm(char *program) |
21 | 21 | { |
22 | 22 | initialize_stack(); |
23 | - memset(regs,0x00,sizeof(short)*NUM_REGISTERS); | |
24 | - memset(mem,0x00,sizeof(short)*MEMSIZE); | |
23 | + memset(regs,0x00,sizeof(uint16_t)*NUM_REGISTERS); | |
24 | + memset(mem,0x00,sizeof(uint16_t)*MEMSIZE); | |
25 | 25 | load_program(program); |
26 | 26 | start_execution(); |
27 | 27 | free_stack(); |
... | ... | @@ -35,8 +35,8 @@ void disasm(char *program) |
35 | 35 | void debug(char *program) |
36 | 36 | { |
37 | 37 | initialize_stack(); |
38 | - memset(regs,0x00,sizeof(short)*NUM_REGISTERS); | |
39 | - memset(mem,0x00,sizeof(short)*MEMSIZE); | |
38 | + memset(regs,0x00,sizeof(uint16_t)*NUM_REGISTERS); | |
39 | + memset(mem,0x00,sizeof(uint16_t)*MEMSIZE); | |
40 | 40 | load_program(program); |
41 | 41 | debug_program(); |
42 | 42 | free_stack(); | ... | ... |
mem.c
... | ... | @@ -2,6 +2,18 @@ |
2 | 2 | // Created by imanol on 12/25/16. |
3 | 3 | // |
4 | 4 | |
5 | +#include <stdint.h> | |
6 | +#include <string.h> | |
5 | 7 | #include "mem.h" |
6 | 8 | |
7 | -short mem[MEMSIZE]; | |
8 | 9 | \ No newline at end of file |
10 | +uint16_t mem[MEMSIZE]; | |
11 | + | |
12 | +void dump_memory(uint16_t *dump) | |
13 | +{ | |
14 | + memcpy(dump,mem,MEMSIZE*sizeof(uint16_t)); | |
15 | +} | |
16 | + | |
17 | +void load_memory(uint16_t *dump) | |
18 | +{ | |
19 | + memcpy(mem,dump,MEMSIZE*sizeof(uint16_t)); | |
20 | +} | |
9 | 21 | \ No newline at end of file | ... | ... |
mem.h
... | ... | @@ -7,6 +7,11 @@ |
7 | 7 | |
8 | 8 | #define MEMSIZE 32768 |
9 | 9 | |
10 | -extern short mem[MEMSIZE]; //64KiB RAM | |
10 | +#include <stdint.h> | |
11 | + | |
12 | +extern uint16_t mem[MEMSIZE]; //64KiB RAM | |
13 | + | |
14 | +void dump_memory(uint16_t *dump); | |
15 | +void load_memory(uint16_t *dump); | |
11 | 16 | |
12 | 17 | #endif //SYNACORVM_MEM_H | ... | ... |
registers.c
... | ... | @@ -2,7 +2,34 @@ |
2 | 2 | // Created by imanol on 12/25/16. |
3 | 3 | // |
4 | 4 | |
5 | +#include <stdio.h> | |
6 | +#include <string.h> | |
5 | 7 | #include "registers.h" |
6 | 8 | |
7 | -short regs[NUM_REGISTERS]; | |
8 | -short pc = 0; | |
9 | 9 | \ No newline at end of file |
10 | +uint16_t regs[NUM_REGISTERS]; | |
11 | +uint16_t pc = 0; | |
12 | + | |
13 | +void print_regs() | |
14 | +{ | |
15 | + fprintf(stderr,"r0: %2x\n",regs[0]); | |
16 | + fprintf(stderr,"r1: %2x\n",regs[1]); | |
17 | + fprintf(stderr,"r2: %2x\n",regs[2]); | |
18 | + fprintf(stderr,"r3: %2x\n",regs[3]); | |
19 | + fprintf(stderr,"r4: %2x\n",regs[4]); | |
20 | + fprintf(stderr,"r5: %2x\n",regs[5]); | |
21 | + fprintf(stderr,"r6: %2x\n",regs[6]); | |
22 | + fprintf(stderr,"r7: %2x\n",regs[7]); | |
23 | + fprintf(stderr,"pc: %2x\n",pc); | |
24 | +} | |
25 | + | |
26 | +void dump_regs(uint16_t *dump) | |
27 | +{ | |
28 | + dump[0] = pc; | |
29 | + memcpy(dump+1,regs,NUM_REGISTERS*sizeof(uint16_t)); | |
30 | +} | |
31 | + | |
32 | +void load_regs(uint16_t *dump) | |
33 | +{ | |
34 | + pc = dump[0]; | |
35 | + memcpy(regs,dump+1,NUM_REGISTERS*sizeof(uint16_t)); | |
36 | +} | |
10 | 37 | \ No newline at end of file | ... | ... |
registers.h
... | ... | @@ -2,12 +2,18 @@ |
2 | 2 | // Created by imanol on 12/25/16. |
3 | 3 | // |
4 | 4 | |
5 | +#include <stdint.h> | |
6 | + | |
5 | 7 | #ifndef SYNACORVM_REGISTERS_H |
6 | 8 | #define SYNACORVM_REGISTERS_H |
7 | 9 | |
8 | 10 | #define NUM_REGISTERS 8 |
9 | 11 | |
10 | -extern short regs[NUM_REGISTERS]; | |
11 | -extern short pc; | |
12 | +extern uint16_t regs[NUM_REGISTERS]; | |
13 | +extern uint16_t pc; | |
14 | + | |
15 | +void print_regs(); | |
16 | +void dump_regs(uint16_t *dump); | |
17 | +void load_regs(uint16_t *dump); | |
12 | 18 | |
13 | 19 | #endif //SYNACORVM_REGISTERS_H | ... | ... |
stack.c
... | ... | @@ -53,8 +53,7 @@ void shrink_stack() |
53 | 53 | void stack_push(uint16_t value) |
54 | 54 | { |
55 | 55 | stack[++stack_pos] = value; |
56 | - stack_elems++; | |
57 | - if(stack_pos == stack_size-1) | |
56 | + if(++stack_elems == stack_size-1) | |
58 | 57 | { |
59 | 58 | extend_stack(); |
60 | 59 | } |
... | ... | @@ -68,11 +67,31 @@ uint16_t stack_pop() |
68 | 67 | return -1; |
69 | 68 | } |
70 | 69 | uint16_t value = stack[stack_pos--]; |
71 | - if(stack_size - stack_pos == 2*EXTEND_SIZE) | |
70 | + if(stack_size - --stack_elems == 2*EXTEND_SIZE) | |
72 | 71 | { |
73 | 72 | shrink_stack(); |
74 | 73 | } |
75 | 74 | return value; |
76 | 75 | } |
77 | 76 | |
77 | +uint32_t stack_dump(uint16_t **dump) | |
78 | +{ | |
79 | + *dump = calloc(stack_elems,sizeof(uint16_t)); | |
80 | + uint32_t i; | |
81 | + for(i = 0; i < stack_elems; i++) | |
82 | + { | |
83 | + (*dump)[i] = stack[i]; | |
84 | + } | |
85 | + return stack_elems; | |
86 | +} | |
87 | + | |
88 | +void stack_load(uint16_t *dump,uint32_t size) | |
89 | +{ | |
90 | + uint32_t i; | |
91 | + for(i = 0; i < size; i++) | |
92 | + { | |
93 | + stack_push(dump[i]); | |
94 | + } | |
95 | +} | |
96 | + | |
78 | 97 | ... | ... |