shithub: 8080

ref: eee9501cb9a975d6b9c507db70feb338fa604b26
dir: /8080.c/

View raw version
#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();
}