/* cmon.c C monitor program for Lark L. Stewart September 24, 1982 10:27 AM L. Stewart December 2, 1982 7:55 PM, invert NMI I/O bit */ /* machine language assist */ extern setup(); /* setup I/O controllers. */ extern putchar(); /* put character to console */ extern putcrchar(); /* put character to console */ extern getchar(); /* return character from console */ extern chav(); /* returns true if getchar won't block */ extern outbyte(); /* outbyte(port, byte) */ extern inbyte(); /* read byte from io device */ extern fetchb(); /* return byte at address */ extern storeb(); /* store(byte, address) */ extern portstr(); /* load IO registers from command string */ /* monitor machine language assist */ extern dump(); /* extern tslc(); */ extern startm(); /* execute using register save area */ extern int mstate[14]; /* register save area */ extern int lip; extern int lnmi; extern int eitype; /* c runtime library */ extern int isdigit(); /* is character IN [0..9] */ extern lc(); /* lower case */ extern int eqstr(); /* case-insensitive string matcher */ extern wf(); extern wfcr(); extern wf1(); extern wf2(); extern ssenable(); extern ssreturn(); /* other packages */ extern InitAnalog(); extern GetPIO(); extern int stframe; extern int stbyte; extern loadhex(); /* extern setspeed(); */ extern int cmklo; extern int cmkhi; /* statics */ char cmd; char leftover; int any; int mlerr[3]; int result; char *rnary[14]; /* breakpoint */ int brkadr; char brkcb; int sscount; int audb; struct regs { int ax, bx, cx, dx; int sp, bp, si, di; int cs, ds, ss, es; int ip, fl; }; struct regs *regp; #define RESET 255 #define BREAK 3 #define TRACE 1 #define NMI 2 #define DIVERR 0 #define OVERR 4 #define EXTINT 254 main(why) int why; { /* execution comes here on system reset with why=0 */ switch (why) { case BREAK: { monbrk(); break; }; case TRACE: { montr(); break; }; case NMI: { monnmi(); break; }; case DIVERR: { monde(); break; }; case OVERR: { monov(); break; }; case EXTINT: { monei(); break; }; default: { moninit(); break; }; }; regp = (struct regs *) mstate; /* use mstate later */ /* we use NMI for refresh, and the nmi pushbutton is connected to a parallel port bit, which refresh tests */ /* (someday) */ for (;;) { result = ssenable(mlerr); if (result) wf(" ##\r"); wf("% "); StartEL(); cmd = lc(getchar()); switch (cmd) { case 'a': { togaudio(); break; }; case 'b': { setbrk(); break; }; case 'c': { clock(); break; }; case 'd': { dump(0); break; }; case 'e': { elcmd(); break; }; case 'f': { TraceStack(regp->bp); break; }; case 'g': { gocmd(); break; }; case 'i': { incmd(); break; }; case 'n': { sscount = 0; sings(); break; }; case 'o': { outcmd(); break; }; case 'r': { readcmd(); break; }; case 's': { subst(); break; }; case 't': { tslc(); break; }; case 'w': { dump(1); break; }; case 'x': { regcmd(); break; }; default: { unknown(); break; }; }; }; }; moninit() { setup(); /* start refresh, in particular */ datainit(); /* register names */ InitAnalog(); wf("Lark Monitor\r"); testbrk(); brkadr = 0; /* no breakpoint set */ audb = 0; }; monbrk() { wf1("\r Break at %04x\r", regp->ip-1); if (regp->ip != brkadr+1) wf("unknown breakpoint!\r"); else { /* put back code byte and back up ip */ storeb(brkcb, brkadr); regp->ip = brkadr; }; }; montr() { if (brkadr) { /* proceeding from breakpoint */ storeb(0xcc, brkadr); /* replace breakpoint */ regp->fl = regp->fl & 0xfeff; startm(); /* continue */ }; if ((sscount < 20) && (regp->ip == lip)) { sscount = sscount + 1; sings(); }; wf1(" ss at %04x", regp->ip); if (sscount > 1) wf1(", %d tries", sscount); wfcr(); }; monnmi() { wf1("\rNMI at %04x\r", regp->ip); while(!(GetPIO(2) & 1)); lnmi = 0; }; monov() { wf1("\rOverflow at %04x\r", regp->ip); }; monei() { wf1("\rExternal interrupt, type %x\r", eitype); }; monde() { wf1("\rDivide Error at %04x\r", regp->ip); }; setbrk() { int new; testbrk(); wf("Break at: "); brkadr = gethex(); innew('\r'); testbrk(); }; testbrk() { if (brkadr != 0 && fetchb(brkadr) == 0xcc) wf2("\r breakpoint at %04x! code might be %02x\r", brkadr, brkcb); }; clock() { wf2("Clock = %04x%04x\r", cmkhi, cmklo); }; elcmd() { wf1("EtherLoad, host %02x\r", GetPIO(1) & 0xff); StartEL(); }; readcmd() { putchar('R'); loadhex(); regp->cs = stframe; regp->ip = stbyte; wfcr(); }; sings() /* single step */ { testbrk(); brkadr = 0; regp->fl = regp->fl | 0x0100; startm(); }; gocmd() { wf("GO!\r"); regp->fl = regp->fl & 0xfeff; /* clear single step */ if (brkadr) { testbrk(); brkcb = fetchb(brkadr); if (brkadr == regp->ip) regp->fl = regp->fl | 0x0100; else storeb(0xcc, brkadr); }; startm(); }; unknown() { wf(" ??\r"); }; mlabort() { ssreturn(mlerr, 1); }; debug(s) char *s; { wf1("\rDebug: %s\r", s); mlabort(); }; int innewp(c) /* invalid number not ending with */ char c; { if (!any || leftover != c) return(1); return(0); }; innew(c) char c; { if (innewp(c)) mlabort(); }; regcmd() { int i; char name[3]; name[2] = 0; putchar('X'); name[0] = egetchar(); if (leftover == '\r') { printregs(); return; }; name[1] = egetchar(); for (i = 0; i < 14; i += 1) if (eqstr(rnary[i], name)) { modreg(i); return; }; mlabort(); }; modreg(i) int i; { int newval; wf1("=%04x -", mstate[i]); newval = gethex(); innew('\r'); mstate[i] = newval; }; printregs() { prseven(0); prseven(7); }; prseven(start) int start; { int i; for (i = start; i < (start+7); i += 1) printreg(i); wfcr(); }; printreg(i) int i; { wf2(" %s=%04x", rnary[i], mstate[i]); }; incmd() { int port; int first; putchar('I'); first = 1; port = gethex(); if (!any) mlabort() for (;;) { if (!first && innewp(',')) break; wf1("\r%02x", inbyte(port)); if (leftover=='\r') break; first = 0; egetchar(); }; if (first && (leftover=='\r')) wfcr(); }; int egetchar() /* getchar with echo */ { leftover = getchar() & 0177; putcrchar(leftover); if (leftover == 0177) mlabort(); return(leftover); }; outcmd() { int port, val; putchar('O'); port = gethex(); innew(','); for (;;) { val = gethex(); if (innewp(',') && innewp('\r')) mlabort(); outbyte(port, val) if (leftover == '\r') break; wf("\r- "); }; }; subst() { int adr, val; putchar('S'); adr = gethex(); if (innewp(',')) return; for (;;) { val = fetchb(adr); wf1(" %02x- ", val); val = gethex(); if (leftover != ',' && leftover != '\r') mlabort(); if (any) storeb(val, adr); adr += 1; if (leftover == '\r') return; else wfcr(); wf1("%04x- ", adr); }; }; int gethex() { int v; v = 0; any = 0; for (;;) { egetchar(); if (isdigit(leftover)) { v = (v<<4); v += (leftover-'0'); any = 1; continue; }; leftover = lc(leftover); if (leftover>='a' && leftover<='f') { v = (v<<4); v += (leftover-'a'+10); any = 1; continue; }; break; }; return(v); }; datainit() { rnary[0] = "AX"; rnary[1] = "BX"; rnary[2] = "CX"; rnary[3] = "DX"; rnary[4] = "SP"; rnary[5] = "BP"; rnary[6] = "SI"; rnary[7] = "DI"; rnary[8] = "CS"; rnary[9] = "DS"; rnary[10] = "SS"; rnary[11] = "ES"; rnary[12] = "IP"; rnary[13] = "FL"; };