ref: eee9501cb9a975d6b9c507db70feb338fa604b26
dir: /8080.c/
#include <u.h> #include <libc.h> #include <bio.h> #include "dat.h" #include "fns.h" Biobuf *stdin; Biobuf *stdout; Biobuf *stderr; CPU ocpu, cpu; Insn insn; uchar mem[MEMSZ]; uchar *rom = &mem[0]; uchar *ram = &mem[ROMSZ]; uchar *vid = &mem[ROMSZ+RAMSZ]; int interactive; int debug; int nbrkpts; int tracing; int ntraceops; TraceOp traceops[MAXTRACEOPS]; BrkPt brkpts[MAXBRKPTS]; static void usage(void) { fprint(2, "usage: %s [-b addr] rom\n", argv0); exits("usage"); } int loadrom(char *file, u16int base) { uchar *mp, *romend; int c; Biobuf *r; r = Bopen(file, OREAD); if(r == nil) return -1; romend = rom + ROMSZ; for(;;){ for(mp = &rom[base]; mp < romend; mp++){ c = Bgetc(r); if(c < 0) goto Done; *mp = c; } } Done: Bterm(r); return 0; } static void cpureset(void) { memset(&ocpu, 0, sizeof(ocpu)); memset(&cpu, 0, sizeof(cpu)); } static void cpustep(void) { int i; int ilen; uchar buf[3]; static u64int counter; for(i = 0; i < ntraceops; i++) if(cpu.PC == traceops[i].addr) if(traceops[i].op == Tpush){ dprint("@@@@ Tpush @ %2x\n", traceops[i].addr); tracing++; } for(i = 0; i < nbrkpts; i++) if(brkpts[i].enabled && cpu.PC == brkpts[i].addr){ brkpts[i].enabled = 0; trap(); } insn.pc = cpu.PC; insn.op = decodeop(buf[0] = ifetch(&cpu)); if(insn.op == -1){ Bprint(stderr, "illegal opcode %#.2uhhx @ pc=%#.4uhx\n", buf[0], insn.pc); trap(); } switch(ilen = insnlen(insn.op)){ case 2: buf[1] = ifetch(&cpu); break; case 3: buf[1] = ifetch(&cpu); buf[2] = ifetch(&cpu); break; } decodeinsn(&insn, buf, ilen); cpuexec(&cpu, &insn); counter++; if((cpu.intr&Ienabled) != 0){ if(counter % 512 == 0){ push16(&cpu, cpu.PC); cpu.PC = 2<<3; }else if(counter % 256 == 0){ push16(&cpu, cpu.PC); cpu.PC = 1<<3; } } for(i = 0; i < nbrkpts; i++) if(cpu.PC == brkpts[i].addr) brkpts[i].enabled = 1; for(i = 0; i < ntraceops; i++) if(cpu.PC == traceops[i].addr) if(traceops[i].op == Tpop){ dprint("@@@@ Tpop @ %2x\n", traceops[i].addr); tracing--; } ocpu = cpu; } static void prompt(void) { static char prev[256] = ""; char *buf; trapinit(); if(interactive){ Bprint(stdout, "8080> "); Bflush(stdout); } buf = Brdstr(stdin, '\n', 1); if(Blinelen(stdin) <= 0) exits("eof"); if(strcmp(buf, "") == 0){ if(strcmp(prev, "") == 0) return; strcpy(buf, prev); } if(strcmp(buf, "das") == 0){ //das(&insn, mem); }else if(strcmp(buf, "bpset") == 0){ }else if(strcmp(buf, "load") == 0){ if(loadrom("invaders.rom", 0) < 0) Bprint(stderr, "load failed: %r\n"); }else if(strcmp(buf, "reg") == 0){ dumpregs(); }else if(strcmp(buf, "run") == 0){ if(wastrap()) cpu = ocpu; else for(;;){ Bprint(stdout, "%#.4uhx\t", cpu.PC); das(mem+cpu.PC,nelem(mem)); cpustep(); } }else if(strcmp(buf, "step") == 0){ if(wastrap()) cpu = ocpu; else{ print("%#.4uhx\t", cpu.PC); das(mem+cpu.PC,nelem(mem)); cpustep(); } }else if(strcmp(buf, "exit") == 0){ exits(0); }else if(strcmp(buf, "reset") == 0){ cpureset(); }else{ Bprint(stderr, "unknown command: %s\n", buf); buf[0] = 0; } strcpy(prev, buf); } static int isatty(void) { char buf[64]; if(fd2path(0, buf, sizeof(buf)) != 0) return 0; return strcmp(buf, "/dev/cons") == 0; } void main(int argc, char **argv) { ARGBEGIN{ case 'b': if(nbrkpts >= MAXBRKPTS) sysfatal("too many breakpoints"); brkpts[nbrkpts].addr = strtoul(EARGF(usage()), 0, 0); brkpts[nbrkpts].enabled = 1; nbrkpts++; break; case 'd': debug++; break; case 't': case 'T': if(ntraceops >= MAXTRACEOPS) sysfatal("too many trace ops"); traceops[ntraceops].addr = strtoul(EARGF(usage()), 0, 0); traceops[ntraceops].op = ARGC() == 'T' ? Tpush : Tpop; ntraceops++; break; default: usage(); }ARGEND; if(argc != 0) usage(); stdin = Bfdopen(0, OREAD); stdout = Bfdopen(1, OWRITE); stderr = Bfdopen(2, OWRITE); interactive = isatty(); fmtinstall('I', insnfmt); cpureset(); for(;;) prompt(); }