ref: 0d4a0e8b087756ce01fdfd7527409baff200281b
parent: eee9501cb9a975d6b9c507db70feb338fa604b26
author: Alex Musolino <alex@musolino.id.au>
date: Thu May 11 10:07:24 EDT 2023
misc. updates improvements
--- a/8080.c
+++ b/8080.c
@@ -1,6 +1,7 @@
#include <u.h>
#include <libc.h>
#include <bio.h>
+#include <ctype.h>
#include "dat.h"
#include "fns.h"
@@ -27,7 +28,7 @@
static void
usage(void)
{
- fprint(2, "usage: %s [-b addr] rom\n", argv0);
+ fprint(2, "usage: %s [-b addr] [-i script] [-t addr] [-T addr]\n", argv0);
exits("usage");
}
@@ -77,16 +78,20 @@
tracing++;
}
- for(i = 0; i < nbrkpts; i++)
- if(brkpts[i].enabled && cpu.PC == brkpts[i].addr){
- brkpts[i].enabled = 0;
+ for(i = 0; i < nbrkpts; i++){
+ if(brkpts[i].enabled && brkpts[i].hit == 0 && cpu.PC == brkpts[i].addr){
+ Bprint(stderr, "hit breakpoint %d @ pc=%#.4uhx\n", i+1, cpu.PC);
+ Bflush(stderr);
+ brkpts[i].hit = 1;
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);
+ Bprint(stderr, "illegal opcode %#.2uhhx @ pc=%#.4uhx\n", buf[0], cpu.PC);
+ Bflush(stderr);
trap();
}
switch(ilen = insnlen(insn.op)){
@@ -114,7 +119,7 @@
for(i = 0; i < nbrkpts; i++)
if(cpu.PC == brkpts[i].addr)
- brkpts[i].enabled = 1;
+ brkpts[i].hit = 0;
for(i = 0; i < ntraceops; i++)
if(cpu.PC == traceops[i].addr)
@@ -126,61 +131,217 @@
ocpu = cpu;
}
-static void
-prompt(void)
+enum
{
- static char prev[256] = "";
+ Cerror = -1,
+ Cnone,
+ Cdas,
+ Cbpls,
+ Cbpset,
+ Cbpdel,
+ Cload,
+ Creg,
+ Crun,
+ Cstep,
+ Cexit,
+ Creset,
+};
+
+static char *cmdtab[] = {
+ [Cnone] "",
+ [Cdas] "das",
+ [Cbpls] "bpls",
+ [Cbpset] "bpset",
+ [Cbpdel] "bpdel",
+ [Cload] "load",
+ [Creg] "reg",
+ [Crun] "run",
+ [Cstep] "step",
+ [Cexit] "exit",
+ [Creset] "reset",
+};
+
+typedef struct Cmd Cmd;
+struct Cmd
+{
char *buf;
+ int argc;
+ char *argv[16];
+};
- trapinit();
- if(interactive){
- Bprint(stdout, "8080> ");
- Bflush(stdout);
+static int
+cmd(char *s)
+{
+ int i;
+
+ for(i = 0; i < nelem(cmdtab); i++){
+ if(strcmp(s, cmdtab[i]) == 0)
+ return i;
}
- 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){
+ return Cerror;
+}
+
+static void
+docmd(Cmd *c)
+{
+ int i;
+
+ switch(cmd(c->argv[0])){
+ case Cerror:
+ Bprint(stderr, "unknown command: %s\n", c->argv[0]);
+ Bflush(stderr);
+ break;
+ case Cnone:
+ break;
+ case Cdas:
+ das(mem+cpu.PC,mem+nelem(mem), -1);
+ break;
+ case Cbpls:
+ if(c->argc != 1){
+ Bprint(stderr, "usage: bpls\n");
+ Bflush(stderr);
+ break;
+ }
+ for(i = 0; i < nbrkpts; i++){
+ if(brkpts[i].enabled == 0)
+ continue;
+ Bprint(stdout, "bp %d @ %#.4uhx\n", i+1, brkpts[i].addr);
+ }
+ Bflush(stdout);
+ break;
+ case Cbpset:
+ if(c->argc != 2){
+ Bprint(stderr, "usage: bpset ADDR\n");
+ Bflush(stderr);
+ break;
+ }
+ if(nbrkpts >= MAXBRKPTS){
+ Bprint(stderr, "too many breakpoints");
+ Bflush(stderr);
+ break;
+ }
+ brkpts[nbrkpts].addr = strtoul(c->argv[1], 0, 0);
+ brkpts[nbrkpts].enabled = 1;
+ nbrkpts++;
+ break;
+ case Cbpdel:
+ if(c->argc != 2){
+ Bprint(stderr, "usage: bpdel NUM\n");
+ Bflush(stderr);
+ break;
+ }
+ i = strtoul(c->argv[1], 0, 0);
+ if(i < 1 || i > nbrkpts){
+ Bprint(stderr, "bad breakpoint number\n");
+ Bflush(stderr);
+ break;
+ }
+ if(brkpts[i-1].enabled == 0){
+ Bprint(stderr, "no such breakpoint\n");
+ Bflush(stderr);
+ break;
+ }
+ brkpts[i-1].enabled = 0;
+ break;
+ case Cload:
+ if(c->argc != 2){
+ Bprint(stderr, "usage: load ROM\n");
+ Bflush(stderr);
+ break;
+ }
+ if(loadrom(c->argv[1], 0) < 0){
+ Bprint(stderr, "loading %s failed: %r\n", c->argv[1]);
+ Bflush(stderr);
+ }
+ break;
+ case Creg:
dumpregs();
- }else if(strcmp(buf, "run") == 0){
- if(wastrap())
+ break;
+ case Crun:
+ if(c->argc != 1){
+ Bprint(stderr, "usage: run\n");
+ Bflush(stderr);
+ break;
+ }
+ if(wastrap()){
+ Bflush(stdout);
cpu = ocpu;
- else
+ }else{
for(;;){
- Bprint(stdout, "%#.4uhx\t", cpu.PC);
- das(mem+cpu.PC,nelem(mem));
+ //Bprint(stdout, "%#.4uhx\t", cpu.PC);
+ //das1(mem+cpu.PC,nelem(mem)-cpu.PC);
cpustep();
}
- }else if(strcmp(buf, "step") == 0){
- if(wastrap())
+ }
+ break;
+ case Cstep:
+ if(wastrap()){
cpu = ocpu;
- else{
+ }else{
print("%#.4uhx\t", cpu.PC);
- das(mem+cpu.PC,nelem(mem));
+ das1(mem+cpu.PC,nelem(mem)-cpu.PC);
cpustep();
}
- }else if(strcmp(buf, "exit") == 0){
+ break;
+ case Cexit:
exits(0);
- }else if(strcmp(buf, "reset") == 0){
+ break;
+ case Creset:
cpureset();
+ break;
+ }
+}
+
+static Cmd prev;
+
+static int
+proc(Biobuf *in)
+{
+ char *buf;
+ Cmd cmd;
+
+ trapinit();
+ buf = Brdstr(in, '\n', 0);
+ Bflush(stderr);
+ if(Blinelen(in) <= 0)
+ return Blinelen(in);
+ while(isspace(*buf))
+ buf++;
+ if(*buf == '#')
+ return Blinelen(in);
+ cmd.argc = tokenize(buf, cmd.argv, nelem(cmd.argv));
+ if(cmd.argc == 0){
+ free(buf);
+ if(prev.argc > 0)
+ docmd(&prev);
}else{
- Bprint(stderr, "unknown command: %s\n", buf);
- buf[0] = 0;
+ cmd.buf = buf;
+ docmd(&cmd);
+ free(prev.buf);
+ prev = cmd;
}
- strcpy(prev, buf);
+ return Blinelen(in);
}
+static void
+procfile(char *file)
+{
+ Biobuf *b;
+
+ b = Bopen(file, OREAD);
+ if(b == nil)
+ sysfatal("could not open %s: %r", file);
+ for(;;){
+ switch(proc(b)){
+ case -1:
+ sysfatal("error processing %s", file);
+ case 0:
+ Bterm(b);
+ return;
+ }
+ }
+}
+
static int
isatty(void)
{
@@ -194,6 +355,10 @@
void
main(int argc, char **argv)
{
+ stdin = Bfdopen(0, OREAD);
+ stdout = Bfdopen(1, OWRITE);
+ stderr = Bfdopen(2, OWRITE);
+
ARGBEGIN{
case 'b':
if(nbrkpts >= MAXBRKPTS)
@@ -205,6 +370,9 @@
case 'd':
debug++;
break;
+ case 'i':
+ procfile(EARGF(usage()));
+ break;
case 't':
case 'T':
if(ntraceops >= MAXTRACEOPS)
@@ -218,12 +386,19 @@
}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();
+ for(;;){
+ if(interactive){
+ Bprint(stdout, "8080> ");
+ Bflush(stdout);
+ }
+ switch(proc(stdin)){
+ case -1:
+ sysfatal("error reading stdin: %r");
+ case 0:
+ exits(0);
+ }
+ }
}
--- a/das.c
+++ b/das.c
@@ -4,56 +4,57 @@
#include "dat.h"
#include "fns.h"
-static void Xshld(CPU*, Insn*);
-static void Xsbi(CPU*, Insn*);
-static void Xjm(CPU*, Insn*);
-static void Xdaa(CPU*, Insn*);
-static void Xcz(CPU*, Insn*);
-static void Xpchl(CPU*, Insn*);
-static void Xnop(CPU*, Insn*);
-static void Xjmp(CPU*, Insn*);
-static void Xlxi(CPU*, Insn*);
-static void Xmvi(CPU*, Insn*);
-static void Xpop(CPU*, Insn*);
-static void Xcall(CPU*, Insn*);
-static void Xldax(CPU*, Insn*);
-static void Xmov(CPU*, Insn*);
-static void Xinx(CPU*, Insn*);
-static void Xdcr(CPU*, Insn*);
-static void Xret(CPU*, Insn*);
-static void Xdad(CPU*, Insn*);
-static void Xsta(CPU*, Insn*);
-static void Xxra(CPU*, Insn*);
-static void Xout(CPU*, Insn*);
-static void Xora(CPU*, Insn*);
-static void Xlda(CPU*, Insn*);
+static void Xadi(CPU*, Insn*);
static void Xana(CPU*, Insn*);
-static void Xpush(CPU*, Insn*);
-static void Xxchg(CPU*, Insn*);
-static void Xinr(CPU*, Insn*);
static void Xani(CPU*, Insn*);
-static void Xrar(CPU*, Insn*);
-static void Xori(CPU*, Insn*);
+static void Xcall(CPU*, Insn*);
static void Xcmp(CPU*, Insn*);
-static void Xrlc(CPU*, Insn*);
-static void Xrim(CPU*, Insn*);
-static void Xrrc(CPU*, Insn*);
-static void Xdcx(CPU*, Insn*);
-static void Xstax(CPU*, Insn*);
static void Xcpi(CPU*, Insn*);
-static void Xadi(CPU*, Insn*);
-static void Xei(CPU*, Insn*);
+static void Xcz(CPU*, Insn*);
+static void Xdaa(CPU*, Insn*);
+static void Xdad(CPU*, Insn*);
+static void Xdcr(CPU*, Insn*);
+static void Xdcx(CPU*, Insn*);
static void Xdi(CPU*, Insn*);
+static void Xei(CPU*, Insn*);
static void Xin(CPU*, Insn*);
+static void Xinr(CPU*, Insn*);
+static void Xinx(CPU*, Insn*);
static void Xjc(CPU*, Insn*);
-static void Xjz(CPU*, Insn*);
+static void Xjm(CPU*, Insn*);
+static void Xjmp(CPU*, Insn*);
static void Xjnc(CPU*, Insn*);
static void Xjnz(CPU*, Insn*);
+static void Xjp(CPU*, Insn*);
+static void Xjz(CPU*, Insn*);
+static void Xlda(CPU*, Insn*);
+static void Xldax(CPU*, Insn*);
+static void Xlxi(CPU*, Insn*);
+static void Xmov(CPU*, Insn*);
+static void Xmvi(CPU*, Insn*);
+static void Xnop(CPU*, Insn*);
+static void Xora(CPU*, Insn*);
+static void Xori(CPU*, Insn*);
+static void Xout(CPU*, Insn*);
+static void Xpchl(CPU*, Insn*);
+static void Xpop(CPU*, Insn*);
+static void Xpush(CPU*, Insn*);
+static void Xrar(CPU*, Insn*);
static void Xrc(CPU*, Insn*);
+static void Xret(CPU*, Insn*);
+static void Xrim(CPU*, Insn*);
+static void Xrlc(CPU*, Insn*);
static void Xrnc(CPU*, Insn*);
static void Xrnz(CPU*, Insn*);
+static void Xrrc(CPU*, Insn*);
static void Xrz(CPU*, Insn*);
+static void Xsbi(CPU*, Insn*);
+static void Xshld(CPU*, Insn*);
+static void Xsta(CPU*, Insn*);
+static void Xstax(CPU*, Insn*);
static void Xsui(CPU*, Insn*);
+static void Xxchg(CPU*, Insn*);
+static void Xxra(CPU*, Insn*);
static void Xxthl(CPU*, Insn*);
static int dec0(Insn*, uchar*, long);
@@ -116,6 +117,7 @@
[Ojmp]{"JMP", Taddr, Xjmp},
[Ojnc]{"JNC", Taddr, Xjnc},
[Ojnz]{"JNZ", Taddr, Xjnz},
+ [Ojp]{"JP", Taddr, Xjp},
[Ojpo]{"JPO", Taddr},
[Ojz]{"JZ", Taddr, Xjz},
[Olda]{"LDA", Taddr, Xlda},
@@ -464,18 +466,43 @@
}
int
-das(uchar *mem, long mlen)
+das1(uchar *s, long len)
{
int n;
Insn insn;
- if((n = decode(&insn, mem, mlen)) < 0)
+ if((n = decode(&insn, s, len)) < 0)
return -1;
- Bprint(stdout, "\t%I\n", &insn);
+ Bprint(stdout, "%#.4ullx:\t%I\n", s - mem, &insn);
+ //Bflush(stdout);
return n;
}
int
+das(uchar *s, uchar *e, int max)
+{
+ int n, isz;
+
+ n = 0;
+ for(;;){
+ if(s >= e)
+ break;
+ if(max >= 0 && n >= max)
+ break;
+ if((isz = das1(s, e-s)) < 0){
+ n = -1;
+ break;
+ }
+ if(isz == 0)
+ break;
+ n++;
+ s += isz;
+ }
+ Bflush(stdout);
+ return n;
+}
+
+int
dasfile(char *file)
{
Biobuf *r;
@@ -522,11 +549,12 @@
}
}
while(buflen > 0){
- print("%#.4x\t???\t%#.2x\n", addr, buf[0]);
+ Bprint(stdout, "%#.4x\t???\t%#.2x\n", addr, buf[0]);
addr++;
bp++;
buflen--;
}
+ Bflush(stdout);
return 0;
}
@@ -535,6 +563,7 @@
{
if(isa[insn->op].exec == nil){
Bprint(stderr, "%s (%#.2uhhx) not implemented!\n", opstr(insn->op), insn->op);
+ Bflush(stderr);
trap();
}
itrace(opstr(insn->op));
@@ -544,10 +573,18 @@
static u16int
rpair(CPU *cpu, u8int rp)
{
+ u16int x;
+
switch(rp){
case BC: return cpu->r[B]<<8 | cpu->r[C];
case DE: return cpu->r[D]<<8 | cpu->r[E];
- case HL: return cpu->r[H]<<8 | cpu->r[L];
+ case HL:
+ x = cpu->r[H]<<8 | cpu->r[L];
+ if(rp == HL && x == 0){
+ Bprint(stderr, "HL = 0 @ pc=%#.4uhx\n", cpu->PC);
+ Bflush(stderr);
+ }
+ return x;
}
fatal("unknown register pair %d", rp);
return 0;
@@ -556,6 +593,10 @@
static void
wpair(CPU *cpu, u8int rp, u16int x)
{
+ if(rp == HL && x == 0){
+ Bprint(stderr, "HL ← 0 @ pc=%#.4uhx\n", cpu->PC);
+ Bflush(stderr);
+ }
cpu->r[(rp<<1)+B] = x>>8;
cpu->r[(rp<<1)+B+1] = x;
}
@@ -566,6 +607,13 @@
}
static void
+Xjp(CPU *cpu, Insn *insn)
+{
+ if((cpu->flg & Fsign) == 0)
+ cpu->PC = insn->addr;
+}
+
+static void
Xjmp(CPU *cpu, Insn *insn)
{
cpu->PC = insn->addr;
@@ -596,6 +644,8 @@
static void
Xcall(CPU *cpu, Insn *insn)
{
+ //Bprint(stderr, "CALL %#.4uhx @ pc=%#.4uhx\n", insn->addr, insn->pc);
+ //Bflush(stderr);
push16(cpu, cpu->PC);
cpu->PC = insn->addr;
}
@@ -669,8 +719,8 @@
x += rpair(cpu, HL);
if(x>>16 > 0)
cpu->flg |= Fcarry;
- //else
- //cpu->flg &= ~Fcarry;
+ else
+ cpu->flg &= ~Fcarry;
wpair(cpu, HL, x);
}
@@ -705,11 +755,6 @@
cpu->flg &= ~(Fcarry|Fhcarry);
}
-void
-iow(u16int a, u8int v)
-{
-}
-
static void
Xout(CPU *cpu, Insn *insn)
{
@@ -775,21 +820,37 @@
static void
Xpush(CPU *cpu, Insn *insn)
{
- if(insn->rp == 3){
+ u16int x;
+
+ if(insn->rp == MM){
push8(cpu, cpu->r[A]);
push8(cpu, cpu->flg);
- }else
- push16(cpu, rpair(cpu, insn->rp));
+ }else{
+ x = rpair(cpu, insn->rp);
+ if(insn->rp == HL && x == 0){
+ Bprint(stderr, "pushed %uhd from %s @ %#.4uhx\n", x, rpnam(insn->rp), insn->pc);
+ Bflush(stderr);
+ }
+ push16(cpu, x);
+ }
}
static void
Xpop(CPU *cpu, Insn *insn)
{
- if(insn->rp == 3){
+ u16int x;
+
+ if(insn->rp == MM){
cpu->flg = pop8(cpu);
cpu->r[A] = pop8(cpu);
- }else
- wpair(cpu, insn->rp, pop16(cpu));
+ }else{
+ x = pop16(cpu);
+ if(insn->rp == HL && x == 0){
+ Bprint(stderr, "popped %uhd into %s @ %#.4uhx\n", x, rpnam(insn->rp), insn->pc);
+ Bflush(stderr);
+ }
+ wpair(cpu, insn->rp, x);
+ }
}
static void
@@ -830,6 +891,19 @@
cpu->flg &= ~Fhcarry;
}
+static int
+evenpar(u8int x)
+{
+ u8int r;
+
+ r = 1;
+ while(x != 0){
+ r ^= x&1;
+ x >>= 1;
+ }
+ return r;
+}
+
static void
Xani(CPU *cpu, Insn *insn)
{
@@ -845,6 +919,11 @@
else
cpu->flg &= ~Fsign;
+ if(evenpar(cpu->r[A]))
+ cpu->flg |= Fparity;
+ else
+ cpu->flg &= ~Fparity;
+
cpu->flg &= ~(Fcarry|Fhcarry);
}
@@ -1007,9 +1086,9 @@
}
static void
-Xin(CPU *cpu, Insn*)
+Xin(CPU *cpu, Insn *insn)
{
- cpu->r[A] = 0;
+ cpu->r[A] = ior(insn->addr);
}
static void
--- a/dat.h
+++ b/dat.h
@@ -1,3 +1,6 @@
+typedef struct Biobuf Biobuf;
+typedef struct Fmt Fmt;
+
typedef struct CPU CPU;
typedef struct Insn Insn;
typedef struct ISA ISA;
@@ -27,6 +30,7 @@
BC,
DE,
HL,
+ MM,
};
enum{
@@ -184,6 +188,7 @@
{
u16int addr;
uchar enabled;
+ uchar hit;
};
enum{
--- a/debug.c
+++ b/debug.c
@@ -59,13 +59,20 @@
return "XX";
}
-void
-dumpinst(void)
+static void
+dumpinst0(void)
{
Bprint(stderr, "op: %#.2x [%#.2x %#.2x]\n",
mem[insn.pc+0], mem[insn.pc+1], mem[insn.pc+2]);
}
+void
+dumpinst(void)
+{
+ dumpinst0();
+ Bflush(stderr);
+}
+
static char
flagchar(int f)
{
@@ -79,8 +86,8 @@
return 0;
}
-void
-dumpregs(void)
+static void
+dumpregs0(void)
{
int i;
@@ -105,6 +112,13 @@
}
void
+dumpregs(void)
+{
+ dumpregs0();
+ Bflush(stderr);
+}
+
+void
dumpmem(u16int s, u16int e)
{
while(s < e){
@@ -111,6 +125,7 @@
Bprint(stderr, "%.4x: %.2x\n", s, mem[s]);
s++;
}
+ Bflush(stderr);
}
void
@@ -122,6 +137,7 @@
Bprint(stderr, "%#.4x ", insn.pc);
Bvprint(stderr, fmt, args);
Bprint(stderr, "\n");
+ Bflush(stderr);
va_end(args);
}
@@ -134,7 +150,8 @@
Bvprint(stderr, fmt, args);
Bprint(stderr, "\n");
va_end(args);
- dumpinst();
- dumpregs();
+ dumpinst0();
+ dumpregs0();
+ Bflush(stderr);
exits("fatal");
}
--- a/fns.h
+++ b/fns.h
@@ -1,3 +1,5 @@
+typedef struct Fmt Fmt;
+
/* debug */
void dumpregs(void);
void dumpmem(u16int, u16int);
@@ -12,7 +14,8 @@
/* disassembler */
#pragma varargck type "I" Insn*
int insnfmt(Fmt*);
-int das(uchar*, long);
+int das1(uchar*, long);
+int das(uchar*, uchar*, int);
int dasfile(char*);
/* isa */
@@ -34,3 +37,7 @@
u16int pop16(CPU*);
void push8(CPU*, u8int);
void push16(CPU*, u16int);
+
+/* i/o */
+u8int ior(u16int);
+void iow(u16int, u8int);
--- /dev/null
+++ b/io.c
@@ -1,0 +1,35 @@
+#include <u.h>
+#include "dat.h"
+#include "fns.h"
+
+typedef struct Shifter Shifter;
+struct Shifter {
+ u16int reg;
+ u8int off;
+};
+
+static Shifter shifter;
+
+u8int
+ior(u16int a)
+{
+ switch(a){
+ case 0x3:
+ return shifter.reg>>shifter.off;
+ }
+ return 0;
+}
+
+void
+iow(u16int a, u8int v)
+{
+ switch(a){
+ case 0x2:
+ shifter.off = v&0x7;
+ break;
+ case 0x4:
+ shifter.reg >>= 8;
+ shifter.reg |= ((u16int)v)<<8;
+ break;
+ }
+}
--- a/mem.c
+++ b/mem.c
@@ -9,6 +9,7 @@
{
if(a >= MEMSZ){
Bprint(stderr, "memread failed addr=%#.4x op=%#0.2x pc=%#.4x\n", a, insn.op, ocpu.PC);
+ Bflush(stderr);
trap();
}
return mem[a];
@@ -19,6 +20,7 @@
{
if(a < ROMSZ || a >= MEMSZ){
Bprint(stderr, "write failed addr=%#.4x op=%#0.2x pc=%#.4x\n", a, insn.op, ocpu.PC);
+ Bflush(stderr);
trap();
}
mem[a] = x;
@@ -29,6 +31,7 @@
{
if(cpu->PC >= ROMSZ){
Bprint(stderr, "ifetch failed pc=%#.4x\n", cpu->PC);
+ Bflush(stderr);
trap();
}
return memread(cpu->PC++);
--- a/mkfile
+++ b/mkfile
@@ -6,6 +6,7 @@
mem.$O\
debug.$O\
das.$O\
+ io.$O\
HFILES=\
dat.h\
--- a/test.rc
+++ b/test.rc
@@ -1,5 +1,7 @@
#!/bin/rc
-mk && 6.out >out.log <<EOF
-load
-run
+mk && 6.out -i <{cat <<EOF
+load invaders.rom
+bpset 0x18dc
+bpset 0x18df
EOF
+}