]> Joshua Wise's Git repositories - jwcc.git/blame_incremental - sim/blargcpu2.c
Add the break.c example
[jwcc.git] / sim / blargcpu2.c
... / ...
CommitLineData
1/*
2 * BlargCPU2
3 *
4 * A dummy CPU emulated on a microcode level, suitable for implementation in hardware.
5 *
6 * Copyright (c) 2005 Joshua Wise <joshua@joshuawise.com>.
7 * Copyright (c) 2005 Matthew Maurer <Fallen.Azrael@gmail.com>.
8 *
9 * All rights reserved.
10 */
11
12/*
13four registers + flag + pc + stack pointer
14
15Insns:
16 0000 mov reg, lit16
17 0001 ldr reg, [reg]
18 0010 sto [reg], reg
19 0011 mov reg, reg
20 0100 add reg, reg
21 0101 tst reg, reg
22 0110 and reg, reg
23 0111 not reg
24 1000 push reg, reg
25 1001 pop reg, reg
26 1010 call reg, reg
27 1011 shr reg, reg
28 1100 shl reg, reg
29
30Predicates:
31 000 Never
32 001 Not-Equal
33 010 Equal
34 011 Less than
35 100 Greater than
36 111 Always
37
38Opcode format:
3915 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
40|--INSN---| |-PRED-| |TREGISTER| |SREGISTER|
41
42Vectors:
43 0 - start
44 4 - ISR
45*/
46
47#include <stdio.h>
48#include <sys/types.h>
49#include <sys/stat.h>
50#include <fcntl.h>
51#include <unistd.h>
52#include <stdlib.h>
53#include <string.h>
54
55#define STACK_LOC 0x8000
56
57#define PRED_NV 0x0
58#define PRED_NE 0x1
59#define PRED_EQ 0x2
60#define PRED_LT 0x3
61#define PRED_GT 0x4
62#define PRED_AL 0x7
63
64#define FLAG_LT 0x1
65#define FLAG_GT 0x2
66#define FLAG_EQ 0x4
67
68#define REG_R0 0x0
69#define REG_R1 0x1
70#define REG_R2 0x2
71#define REG_R3 0x3
72#define REG_FR 0x4
73#define REG_PC 0x5
74#define REG_SP 0x6
75
76#define INSN_MOV_REG_LIT16 0x0
77#define INSN_LDR_REG_ADR_REG 0x1
78#define INSN_STO_ADR_REG_REG 0x2
79#define INSN_MOV_REG_REG 0x3
80#define INSN_ADD_REG_REG 0x4
81#define INSN_TST_REG_REG 0x5
82#define INSN_AND_REG_REG 0x6
83#define INSN_NOT_REG 0x7
84#define INSN_PUSH_REG_REG 0x8
85#define INSN_POP_REG_REG 0x9
86#define INSN_CALL_REG_REG 0xA
87#define INSN_SHR_REG_REG 0xB
88#define INSN_SHL_REG_REG 0xC
89
90#define INSN(insn, pred, treg, sreg) (((insn) << 12) | ((pred) << 9) | ((treg) << 4) | ((sreg)))
91
92/*******************************************************************/
93/*******************************************************************/
94
95struct peripheral {
96 struct peripheral *next;
97
98 char *name;
99 unsigned short start;
100 unsigned short length;
101 unsigned short (*read)(struct peripheral*, unsigned short);
102 void (*write)(struct peripheral*, unsigned short, unsigned short);
103 void *priv;
104};
105
106struct peripheral *plist = NULL;
107
108unsigned short null_read(struct peripheral *device, unsigned short address)
109{
110 printf("%s: read to address %04x disallowed\n", device->name, address);
111 abort();
112}
113
114void null_write(struct peripheral *device, unsigned short address, unsigned short data)
115{
116 printf("%s: write to address %04x disallowed\n", device->name, address);
117 abort();
118}
119
120unsigned short nodev_read(struct peripheral *device, unsigned short address)
121{
122 printf("peripherals: no device to read from at address %04x\n", address);
123 abort();
124}
125
126void nodev_write(struct peripheral *device, unsigned short address, unsigned short data)
127{
128 printf("peripherals: no device to write %04x to at address %04x\n", data, address);
129 abort();
130}
131
132struct peripheral noperiph = { NULL, "noperiph", 0x0, 0x0, nodev_read, nodev_write, NULL };
133
134struct peripheral* peripheral_cache[65536 /* ouch! */];
135
136/* this could be done in a more optimized manner by stepping through each periph and just setting the bits where it's at, but ... */
137void peripheral_rehash()
138{
139 int address;
140
141 for (address = 0; address < 65536; address++)
142 {
143 struct peripheral *p;
144
145 peripheral_cache[address] = &noperiph; /* No'bdy has harmed me!, quoth the Cyclops */
146
147 for (p=plist; p; p = p->next)
148 if ((p->start <= address) && ((p->start + p->length) > address))
149 {
150 peripheral_cache[address] = p;
151 break;
152 }
153 }
154}
155
156#define peripheral_get(address) (peripheral_cache[address])
157
158void peripheral_add(struct peripheral *device)
159{
160 device->next = plist;
161 plist = device;
162 if (!device->read)
163 device->read = null_read;
164 if (!device->write)
165 device->write = null_write;
166 peripheral_rehash();
167}
168
169void peripheral_remove(struct peripheral *device)
170{
171 struct peripheral *temp, *ptemp;
172
173 if (plist == device)
174 {
175 plist = device->next;
176 return;
177 }
178
179 ptemp = plist;
180 for (temp = plist; temp; temp->next)
181 if (temp == device)
182 ptemp->next = device->next;
183 peripheral_rehash();
184}
185
186/*******************************************************************/
187
188#define ROMSIZE 0x4000
189unsigned short rom_data[ROMSIZE]= {
190 INSN(INSN_MOV_REG_LIT16, PRED_AL, REG_R3,0 ), 9, /*mov r3, 9*/
191 INSN(INSN_MOV_REG_LIT16, PRED_AL, REG_R0,0 ), '9', /*mov r0, '9'*/
192 INSN(INSN_MOV_REG_LIT16, PRED_AL, REG_R1,0 ), 0x4000, /*mov r1, 0x4000*/
193 INSN(INSN_MOV_REG_LIT16, PRED_AL, REG_R2,0 ), 0xFFFF, /*mov r2, 0xFFFF*/
194 INSN(INSN_STO_ADR_REG_REG, PRED_AL, REG_R1,REG_R0 ), /* loop 0x0008 *//*mov [r1], r0*/
195 INSN(INSN_ADD_REG_REG, PRED_AL, REG_R3,REG_R2 ), /*add r3,r2*/
196 INSN(INSN_ADD_REG_REG, PRED_AL, REG_R0,REG_R2 ), /*add r0,r2*/
197 INSN(INSN_TST_REG_REG, PRED_AL, REG_R3,REG_R2 ), /* loop 0x0011 *//*test r3, r2*/
198 INSN(INSN_MOV_REG_LIT16, PRED_NE, REG_PC,0 ), 0x0008, /*jne 0x0008*/
199 INSN(INSN_MOV_REG_LIT16, PRED_AL, REG_R0,0 ), '\n', /*mov r0,0*/
200 INSN(INSN_STO_ADR_REG_REG, PRED_AL, REG_R1,REG_R0 ), /*mov [r1], r0*/
201 INSN(INSN_MOV_REG_LIT16, PRED_AL, REG_PC,0 ), 0x0011, /*jmp 0x0011*/
202};
203
204/*ROM Read*/
205unsigned short rom_read(struct peripheral *device, unsigned short address)
206{
207 return ((unsigned short*)device->priv)[address - device->start];
208}
209
210unsigned short rom_optread(struct peripheral *device, unsigned short address)
211{
212 return ((unsigned short*)device->priv)[address];
213}
214
215void rom_add()
216{
217 struct peripheral *p = (struct peripheral*)malloc(sizeof(struct peripheral));
218 p->name = "rom";
219 p->start = 0x0;
220 p->length = ROMSIZE;
221 p->read = (p->start == 0x0) ? &rom_optread : &rom_read;
222 p->write = NULL;
223 p->priv = &rom_data;
224 peripheral_add(p);
225}
226
227/*******************************************************************/
228
229#define RAMSIZE 32768
230unsigned short ram_data[RAMSIZE];
231
232unsigned short ram_read(struct peripheral *device, unsigned short address)
233{
234 return ((unsigned short*)device->priv)[address - device->start];
235}
236
237void ram_write(struct peripheral *device, unsigned short address, unsigned short data)
238{
239 ((unsigned short*)device->priv)[address - device->start] = data;
240}
241
242void ram_add()
243{
244 struct peripheral *p = (struct peripheral*)malloc(sizeof(struct peripheral));
245 p->name = "ram";
246 p->start = 0x8000;
247 p->length = RAMSIZE;
248 p->read = &ram_read;
249 p->write = &ram_write;
250 p->priv = &ram_data;
251 peripheral_add(p);
252}
253
254/*******************************************************************/
255
256#include "SDL.h"
257
258struct blargfb {
259 SDL_Surface* screen;
260 SDL_Color palette[256];
261 unsigned short row, col;
262};
263
264Uint32 fb_events(Uint32 interval)
265{
266 SDL_Event event;
267
268 while (SDL_PollEvent(&event)) {
269 switch (event.type) {
270 case SDL_KEYDOWN:
271 if (event.key.keysym.sym == SDLK_q)
272 exit(0);
273 break;
274 case SDL_QUIT:
275 exit(0);
276 }
277 }
278 return interval;
279}
280
281void fb_initsurface(struct blargfb *fb)
282{
283 if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_NOPARACHUTE) < 0)
284 {
285 printf("SDL init failed: %s, FB disabled\n", SDL_GetError());
286 fb->screen = NULL;
287 return;
288 }
289 atexit(SDL_Quit);
290
291 fb->screen = SDL_SetVideoMode(320,240,8,SDL_SWSURFACE);
292 if (!fb->screen)
293 {
294 printf("SDL video init failed: %s, FB disabled\n", SDL_GetError());
295 return;
296 }
297
298 SDL_WM_SetCaption("BlargCPU Framebuffer", "BlargFB");
299
300 fb->palette[0].r = 0; fb->palette[0].g = 0; fb->palette[0].b = 0;
301 fb->palette[1].r = 127; fb->palette[1].g = 0; fb->palette[1].b = 0;
302 fb->palette[2].r = 0; fb->palette[2].g = 127; fb->palette[2].b = 0;
303 fb->palette[3].r = 0; fb->palette[3].g = 0; fb->palette[3].b = 127;
304 fb->palette[4].r = 255; fb->palette[4].g = 0; fb->palette[4].b = 0;
305 fb->palette[5].r = 0; fb->palette[5].g = 255; fb->palette[5].b = 0;
306 fb->palette[6].r = 0; fb->palette[6].g = 0; fb->palette[6].b = 255;
307 fb->palette[7].r = 255; fb->palette[7].g = 255; fb->palette[7].b = 255;
308 SDL_SetColors(fb->screen, fb->palette, 0, 8);
309
310 SDL_SetTimer(50, fb_events);
311}
312
313void fb_init(struct peripheral *device)
314{
315 struct blargfb *priv = (struct blargfb*)device->priv;
316 priv->row = 0;
317 priv->col = 0;
318}
319
320unsigned short fb_read(struct peripheral *device, unsigned short address)
321{
322 struct blargfb *priv = (struct blargfb*)device->priv;
323 unsigned char res;
324
325 if (!priv->screen) fb_initsurface(priv);
326
327 switch (address - device->start)
328 {
329 case 0: return priv->row;
330 case 1: return priv->col;
331 case 2: SDL_LockSurface(priv->screen);
332 res = *((unsigned char*)(priv->screen->pixels + priv->row * priv->screen->pitch + priv->col));
333 SDL_UnlockSurface(priv->screen);
334 return res;
335 case 3: return 0;
336 default:printf("%s: read: incorrect offset %d\n", device->name, address - device->start);
337 };
338}
339
340void fb_write(struct peripheral *device, unsigned short address, unsigned short data)
341{
342 struct blargfb *priv = (struct blargfb*)device->priv;
343
344 if (!priv->screen) fb_initsurface(priv);
345
346 switch (address - device->start)
347 {
348 case 0: priv->row = data; break;
349 case 1: priv->col = data; break;
350 case 2: SDL_LockSurface(priv->screen);
351 *((unsigned char*)(priv->screen->pixels + priv->row * priv->screen->pitch + priv->col)) = data;
352 SDL_UnlockSurface(priv->screen);
353 break;
354 case 3: SDL_UpdateRect(priv->screen, 0, 0, 0, 0); break;
355 default:printf("%s: write: incorrect offset %d\n", device->name, address - device->start);
356 }
357}
358
359void fb_add()
360{
361 struct peripheral *p = (struct peripheral*)malloc(sizeof(struct peripheral));
362 struct blargfb *fb = (struct blargfb*)malloc(sizeof(struct blargfb));
363 p->name = "fb";
364 p->start = 0x4100;
365 p->length = 0x4;
366 p->read = &fb_read;
367 p->write = &fb_write;
368 p->priv = fb;
369 fb_init(p);
370 peripheral_add(p);
371}
372
373/*******************************************************************/
374
375void console_write(struct peripheral *device, unsigned short address, unsigned short data)
376{
377// write(1, &data, 1);
378 printf("Console write: data: %04x (%d)\n", data, data);
379}
380
381void console_add()
382{
383 struct peripheral *p = (struct peripheral*)malloc(sizeof(struct peripheral));
384 p->name = "console";
385 p->start = 0x4000;
386 p->length = 0x1;
387 p->read = NULL;
388 p->write = &console_write;
389 p->priv = NULL;
390 peripheral_add(p);
391}
392
393/*******************************************************************/
394
395unsigned short fetch(unsigned short address)
396{
397 struct peripheral* temp = peripheral_get(address);
398 return temp->read(temp, address);
399}
400
401void store(unsigned short address, unsigned short data)
402{
403 struct peripheral* temp = peripheral_get(address);
404 temp->write(temp, address, data);
405}
406
407/*******************************************************************/
408/*******************************************************************/
409
410#include <readline/readline.h>
411#include <readline/history.h>
412
413static int indebugger = 0;
414static int trace = 0;
415static int breakpoint = -1;
416
417unsigned short regs[7];
418
419char* insntostr(unsigned short opc)
420{
421 static char insn[] = "inspr rx,rx";
422 switch ((opc >> 12) & 0xF)
423 {
424 case INSN_MOV_REG_LIT16: memcpy(insn, "mvc", 3); break;
425 case INSN_STO_ADR_REG_REG: memcpy(insn, "sto", 3); break;
426 case INSN_LDR_REG_ADR_REG: memcpy(insn, "ldr", 3); break;
427 case INSN_MOV_REG_REG: memcpy(insn, "mov", 3); break;
428 case INSN_ADD_REG_REG: memcpy(insn, "add", 3); break;
429 case INSN_TST_REG_REG: memcpy(insn, "tst", 3); break;
430 case INSN_AND_REG_REG: memcpy(insn, "and", 3); break;
431 case INSN_NOT_REG: memcpy(insn, "not", 3); break;
432 case INSN_PUSH_REG_REG: memcpy(insn, "psh", 3); break;
433 case INSN_POP_REG_REG: memcpy(insn, "pop", 3); break;
434 case INSN_CALL_REG_REG: memcpy(insn, "cal", 3); break;
435 default: memcpy(insn, "bad", 3); break;
436 }
437 switch ((opc >> 9) & 0x7)
438 {
439 case PRED_NV: memcpy(insn+3, "nv", 2); break;
440 case PRED_NE: memcpy(insn+3, "ne", 2); break;
441 case PRED_EQ: memcpy(insn+3, "eq", 2); break;
442 case PRED_LT: memcpy(insn+3, "lt", 2); break;
443 case PRED_GT: memcpy(insn+3, "gt", 2); break;
444 case PRED_AL: memcpy(insn+3, " ", 2); break;
445 default: memcpy(insn+3, "!!", 2); break;
446 }
447
448 sprintf(insn+6, "r%x,r%x", (opc >> 4) & 0xF, opc & 0xF);
449 return insn;
450}
451
452void debugger()
453{
454 char *line;
455 static char *oldline;
456 int loopmore = 1;
457 unsigned short insn = fetch(regs[5]);
458
459 if (trace)
460 printf("r0:%04x r1:%04x r2:%04x r3:%04x fr:%04x pc:%04x sp:%04x -- %04x[%s]\n",
461 regs[0], regs[1], regs[2], regs[3], regs[4], regs[5], regs[6],
462 insn, insntostr(insn));
463
464 if (regs[5] == breakpoint)
465 {
466 printf("Breakpoint reached (pc %04x)\n", breakpoint);
467 indebugger = 1;
468 }
469
470 if (!indebugger)
471 return;
472
473 while (loopmore && (line = readline("blargcpu> ")))
474 {
475 if (!*line)
476 {
477 free(line);
478 line = oldline;
479 } else
480 free(oldline);
481
482 if ((strcmp(line, "exit") == 0) || (strcmp(line, "quit") == 0) || (strcmp(line, "bye") == 0))
483 {
484 printf("Bye.\n");
485 exit(0);
486 } else if ((strcmp(line, "cont") == 0) || (strcmp(line, "continue") == 0)) {
487 loopmore = 0;
488 indebugger = 0;
489 } else if ((strcmp(line, "step") == 0) || (strcmp(line, "stepi") == 0))
490 loopmore = 0;
491 else if (strcmp(line, "trace") == 0) {
492 trace = !trace;
493 printf("Trace is now %s.\n", trace ? "ON" : "OFF");
494 } else if (strcmp(line, "status") == 0) {
495 int i;
496 printf("blargCPU status report\n");
497 printf("Register status:\n");
498 printf(" r0: %04x\n", regs[0]);
499 printf(" r1: %04x\n", regs[1]);
500 printf(" r2: %04x\n", regs[2]);
501 printf(" r3: %04x\n", regs[3]);
502 printf(" FR: %04x\n", regs[4]);
503 printf(" PC: %04x\n", regs[5]);
504 printf(" SP: %04x [%04x]\n", regs[6], fetch(regs[6]));
505 printf("Context:\n");
506 i = regs[5] - 3;
507 for (i=(((regs[5] - 3) < 0) ? 0 : (regs[5] - 3)); i < (regs[5] + 4); i++)
508 printf(" %s[%04x] %04x [%s]\n", (i == regs[5]) ? "==>" : " ", i, fetch(i), insntostr(fetch(i)));
509 } else if (strncmp(line, "break", 5) == 0) {
510 if (line[5] == ' ') {
511 unsigned short addr;
512 addr = strtol(line+6, NULL, 16);
513 breakpoint = addr;
514 printf("Breakpoint set to %04x.\n", addr);
515 } else {
516 breakpoint = -1;
517 printf("Breakpoint reset.\n");
518 }
519 } else if (strncmp(line, "xa ", 3) == 0) {
520 unsigned short addr, len = 0;
521 int i;
522 char *next;
523 addr = strtol(line+3, &next, 16);
524 if (*next)
525 len = strtol(next+1, NULL, 16);
526 if (len == 0)
527 len = 1;
528 printf("Memory examination of %04x words at %04x:\n", len, addr);
529 for (i=addr; i<(addr+len); i++)
530 printf(" [%04x] %04x\n", i, fetch(i));
531 } else
532 printf("Come again?\n");
533 oldline = line;
534 }
535}
536
537void reset()
538{
539 regs[REG_PC] = 0x0;
540 regs[REG_FR] = 0x0;
541 regs[REG_SP] = STACK_LOC;
542}
543
544void cpuloop()
545{
546 while(1)
547 {
548 unsigned short insn;
549 unsigned char pred_match;
550 unsigned short tmp;
551
552 debugger();
553
554 insn = fetch(regs[REG_PC]);
555 switch ((insn >> 9) & 0x7)
556 {
557 case PRED_NV: pred_match = 0; break;
558 case PRED_NE: pred_match = regs[REG_FR] & (FLAG_LT | FLAG_GT); break;
559 case PRED_EQ: pred_match = regs[REG_FR] & FLAG_EQ; break;
560 case PRED_LT: pred_match = regs[REG_FR] & FLAG_LT; break;
561 case PRED_GT: pred_match = regs[REG_FR] & FLAG_GT; break;
562 case PRED_AL: pred_match = 1; break;
563 default: printf("Invalid predicate %1x, aborting.\n", (insn >> 9) & 0x7);
564 abort();
565 }
566
567#define UCODE_NEXT_INSN break;
568#define UCODE_INC_PC regs[REG_PC]++;
569#define UCODE_INC_LATCH tmp++;
570#define UCODE_DEC_LATCH tmp--;
571#define UCODE_LATCH_ADR_PC tmp = fetch(regs[REG_PC]);
572#define UCODE_LATCH_PC tmp = regs[REG_PC];
573
574#define UCODE_STORE_TREG regs[(insn >> 4) & 0xF] = tmp;
575#define UCODE_LATCH_TREG tmp = regs[(insn >> 4) & 0xF];
576#define UCODE_LATCH_ADR_TREG tmp = fetch(regs[(insn >> 4) & 0xF]);
577
578#define UCODE_STORE_SREG regs[insn & 0xF] = tmp;
579#define UCODE_LATCH_SREG tmp = regs[insn & 0xF];
580#define UCODE_LATCH_ADR_SREG tmp = fetch(regs[insn & 0xF]);
581
582#define UCODE_STORE_ADR_TREG store(regs[(insn >> 4) & 0xF], tmp);
583#define UCODE_STORE_PC regs[REG_PC] = tmp;
584#define UCODE_ADD_TREG tmp += regs[(insn >> 4) & 0xF];
585#define UCODE_ZERO_FR regs[REG_FR] = 0;
586#define UCODE_SET_FR_EQ if (tmp == regs[(insn >> 4) & 0xF]) regs[REG_FR] |= FLAG_EQ;
587#define UCODE_SET_FR_LT if (tmp < regs[(insn >> 4) & 0xF]) regs[REG_FR] |= FLAG_LT;
588#define UCODE_SET_FR_GT if (tmp > regs[(insn >> 4) & 0xF]) regs[REG_FR] |= FLAG_GT;
589#define UCODE_AND_TREG tmp &= regs[(insn >> 4) & 0xF];
590#define UCODE_LATCH_NOT_TREG tmp = ~regs[(insn >> 4) & 0xF];
591
592#define UCODE_SHIFT_RIGHT tmp = tmp >> (regs[(insn >> 4) & 0xF]);
593#define UCODE_SHIFT_LEFT tmp = tmp << (regs[(insn << 4) & 0xF]);
594
595 switch ((insn >> 12) & 0xF)
596 {
597 case INSN_MOV_REG_LIT16: UCODE_INC_PC
598 if (pred_match) UCODE_LATCH_ADR_PC
599 UCODE_INC_PC
600 if (pred_match) UCODE_STORE_TREG
601 UCODE_NEXT_INSN
602
603 case INSN_STO_ADR_REG_REG: if (pred_match) UCODE_LATCH_SREG
604 UCODE_INC_PC
605 if (pred_match) UCODE_STORE_ADR_TREG
606 UCODE_NEXT_INSN
607
608 case INSN_LDR_REG_ADR_REG: if (pred_match) UCODE_LATCH_ADR_SREG
609 UCODE_INC_PC
610 if (pred_match) UCODE_STORE_TREG
611 UCODE_NEXT_INSN
612
613 case INSN_MOV_REG_REG: if (pred_match) UCODE_LATCH_SREG
614 UCODE_INC_PC
615 if (pred_match) UCODE_STORE_TREG
616 UCODE_NEXT_INSN
617
618 case INSN_ADD_REG_REG: if (pred_match) UCODE_LATCH_SREG
619 UCODE_INC_PC
620 if (pred_match) UCODE_ADD_TREG
621 if (pred_match) UCODE_STORE_TREG
622 UCODE_NEXT_INSN
623
624 case INSN_TST_REG_REG: if (pred_match) UCODE_LATCH_SREG
625 UCODE_INC_PC
626 if (pred_match) UCODE_ZERO_FR
627 if (pred_match) UCODE_SET_FR_EQ
628 if (pred_match) UCODE_SET_FR_LT
629 if (pred_match) UCODE_SET_FR_GT
630 UCODE_NEXT_INSN
631
632 case INSN_AND_REG_REG: if (pred_match) UCODE_LATCH_SREG
633 UCODE_INC_PC
634 if (pred_match) UCODE_AND_TREG
635 if (pred_match) UCODE_STORE_TREG
636 UCODE_NEXT_INSN
637
638 case INSN_NOT_REG: if (pred_match) UCODE_LATCH_NOT_TREG
639 UCODE_INC_PC
640 if (pred_match) UCODE_STORE_TREG
641 UCODE_NEXT_INSN
642
643 case INSN_PUSH_REG_REG: if (pred_match) UCODE_LATCH_SREG
644 if (pred_match) UCODE_STORE_ADR_TREG
645 if (pred_match) UCODE_LATCH_TREG
646 if (pred_match) UCODE_INC_LATCH
647 if (pred_match) UCODE_STORE_TREG
648 UCODE_INC_PC
649 UCODE_NEXT_INSN
650
651 case INSN_POP_REG_REG: UCODE_INC_PC
652 if (pred_match) UCODE_LATCH_TREG
653 if (pred_match) UCODE_DEC_LATCH
654 if (pred_match) UCODE_STORE_TREG
655 if (pred_match) UCODE_LATCH_ADR_TREG
656 if (pred_match) UCODE_STORE_SREG
657 UCODE_NEXT_INSN
658
659 case INSN_CALL_REG_REG: UCODE_INC_PC
660 if (pred_match) UCODE_LATCH_PC
661 if (pred_match) UCODE_STORE_ADR_TREG
662 if (pred_match) UCODE_LATCH_TREG
663 if (pred_match) UCODE_INC_LATCH
664 if (pred_match) UCODE_STORE_TREG
665 if (pred_match) UCODE_LATCH_SREG
666 if (pred_match) UCODE_STORE_PC
667 UCODE_NEXT_INSN
668
669 case INSN_SHR_REG_REG: if (pred_match) UCODE_LATCH_SREG
670 UCODE_INC_PC
671 if (pred_match) UCODE_SHIFT_RIGHT
672 if (pred_match) UCODE_STORE_SREG
673 UCODE_NEXT_INSN
674
675 case INSN_SHL_REG_REG: if (pred_match) UCODE_LATCH_SREG
676 UCODE_INC_PC
677 if (pred_match) UCODE_SHIFT_LEFT
678 if (pred_match) UCODE_STORE_SREG
679 UCODE_NEXT_INSN
680/*
681* Two concerns as of right now about this microcode:
682* 1.) We latch to some things, but then access the registers directly in others. As far as I can tell, we need a second latch.
683* 2.) We increment the program counter before storing to tregs and the like sometimes, but don't others. For example, in
684* call, we increment, then proceed to store to the address in treg. However, at other times, such as in tst, we latch to a
685* register, first, almost giving the impression that we couldn't afterwards. I'm not sure which way it is, but it should
686* be one way throughout the entire system.
687* --Matthew Maurer
688*/
689 default: printf("Internal emulation error: Out of range opcode\n");
690 abort();
691 }
692 }
693}
694
695/*******************************************************************/
696/*******************************************************************/
697
698#include <signal.h>
699#include <getopt.h>
700
701void dbghandler(int sig)
702{
703 char *str;
704 if (indebugger)
705 {
706 str = "Caught signal in debugger; bailing out!\n";
707 write(2, str, strlen(str));
708 exit(1);
709 }
710 str = "^C hit; breaking into debugger\n";
711 write(2, str, strlen(str));
712 indebugger = 1;
713}
714
715struct option longopts[] = {
716 {"rom", required_argument, NULL, 'r'},
717 {"debugger", no_argument, NULL, 'd'},
718 {"help", no_argument, NULL, 'h'},
719 {0,0,0,0} /* sentinel */
720};
721
722int main(int argc, char** argv)
723{
724 int arg;
725 while ((arg = getopt_long(argc, argv, "r:d", longopts, NULL)) != -1)
726 {
727 switch(arg)
728 {
729 case 'r':
730 {
731 int fd;
732 fd = open(optarg, O_RDONLY);
733 if (fd < 0)
734 {
735 perror("open");
736 exit(0);
737 }
738 read(fd, rom_data, ROMSIZE*sizeof(short));
739 close(fd);
740 }
741 case 'd':
742 indebugger = 1;
743 break;
744 case 'h':
745 printf(
746 "blargCPU2\n"
747 "\n"
748 "Usage: %s [OPTION] ...\n"
749 "Simulates a blargCPU.\n"
750 "\n"
751 "Mandatory arguments to long options are mandatory for short options too.\n"
752 " -r, --rom=ROMFILE preloads ROM with a boot image\n"
753 " -d, --debugger immediately drops into the debugger\n"
754 " --help shows this help\n"
755 "\n"
756 "Written by Joshua Wise <joshua@joshuawise.com> and Matthew Maurer <Fallen.Azrael@gmail.com>.\n"
757 , argv[0]
758 );
759 exit(2);
760 case '?': case ':':
761 printf("Try `%s --help' for more information.\n", argv[0]);
762 exit(2);
763 default:
764 printf("Oh God I am not good with computers how did this get here?\n");
765 exit(127);
766 }
767 }
768 signal(SIGINT, dbghandler);
769 rom_add();
770 ram_add();
771 console_add();
772 fb_add();
773 reset();
774 cpuloop();
775 return 0;
776}
This page took 0.029236 seconds and 5 git commands to generate.