/* This file is the public domain. */ /* ODT. We assume the cons driver is installed and has (a) put stdin/stdout into async, non-blocking, CBREAK, ~ECHO, and has set up a SIGIO handler. */ #include #include #include #include #define NEED_NAME #define NEED_FUNCTIONS #define NEED_EXTERN #include "instrtbl.h" #include "odt.h" #include "pdp11.h" #include "disas.h" #include "instrs.h" #include "cons__.h" #include "driverint.h" extern int notraps; extern jmp_buf notraps_jmp; #define CONS_I_STAT 0177560 #define CONS_I_DATA 0177562 #define CONS_O_STAT 0177564 #define CONS_O_DATA 0177566 typedef enum odt_state ODT_STATE; enum odt_state { ODT_PROMPT = 1, ODT_R, ODT_OPENLOC, ODT_OPENREG, ODT_LOC, ODT_REG, ODT_NEWVAL_LOC, ODT_NEWVAL_REG, ODT_PROMPT_PREV_REG, ODT_PROMPT_PREV_LOC, } ; static jmp_buf odtdone; static struct sigvec oldsigio; static ODT_STATE odtstate; static unsigned long int xaddr; static word xregno; static word newvalue; static int singlestep; static void Gcmd(word addr) { mmr0 = 0; mmr3 = 0; pirq = 0; fps = 0; cpu_error = 0; /* set ccr<8> (flush), clear mem_sys_err */ psw = 0; pc = addr; halted = 0; longjmp(odtdone,1); } static void Pcmd(void) { halted = 0; longjmp(odtdone,1); } static void Scmd(void) { halted = 1; singlestep = 1; longjmp(odtdone,1); } static void nullh(int sig __attribute__((__unused__))) { } static void setsigio(void) { struct sigvec sv; sv.sv_handler = nullh; sv.sv_mask = 0; sv.sv_flags = 0; sigvec(SIGIO,&sv,&oldsigio); } static void resetsigio(void) { sigvec(SIGIO,&oldsigio,0); } static void flushin(void) { char ch; while (read(0,&ch,1) == 1) ; } static int get(void) { char ch; while (1) { if (read(0,&ch,1) == 1) return(ch); sigpause(0); } } void put(char ch) { write(1,&ch,1); } void put_s(const char *s) { for (;*s;s++) put(*s); } static void put_q(void) { put_s("?\r\n@"); } void put_x8(unsigned long int val) { int i; val &= 0xffffffff; for (i=28;i>=0;i-=4) put("0123456789abcdef"[(val>>i)&0xf]); } void put_22(unsigned long int val) { int i; val &= 017777777; for (i=21;i>=0;i-=3) put('0'+((val>>i)&7)); } void put_6(word val) { int i; for (i=15;i>=0;i-=3) put('0'+((val>>i)&7)); } void put_3(word val) { put('0'+((val>>6)&3)); put('0'+((val>>3)&7)); put('0'+(val&7)); } void put_2(word val) { put('0'+((val>>3)&7)); put('0'+(val&7)); } static void xodt(void) { /* nothing here yet */ put_s("\r\n@"); } static int odt_fetchphys(unsigned long int pa, word *vp) { notraps = 1; if (setjmp(notraps_jmp)) { notraps = 0; return(0); } *vp = fetchphys(pa); notraps = 0; return(1); } void odt(void) { word val; setsigio(); if (setjmp(odtdone)) { fflush(stdout); resetsigio(); notraps = 0; return; } flushin(); notraps = 1; while (setjmp(notraps_jmp)) { put_s("(trap)"); } put_s("\r\n"); if (singlestep) { singlestep = 0; disas(pc); } else { put_6(pc); } put_s("\r\n@"); fflush(stdout); odtstate = ODT_PROMPT; while (1) { int ch; ch = 0x7f & get(); if (ch != 012) put(ch); switch (odtstate) { case ODT_PROMPT: switch (ch) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': odtstate = ODT_LOC; xaddr = ch - '0'; break; case 'r': case 'R': case '$': odtstate = ODT_R; xregno = 0; break; case 'g': case 'G': Gcmd(0); break; case 'p': case 'P': Pcmd(); break; case 's': case 'S': Scmd(); break; case 'Q': cons__reset(); exit(0); break; case 'X': xodt(); break; case 'Z': cons__reset(); kill(getpid(),SIGTSTP); cons__resume(); put_s("\r\n@"); break; default: odtstate = ODT_PROMPT; put_q(); break; } break; case ODT_R: switch (ch) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': odtstate = ODT_REG; xregno = (xregno << 3) | (ch - '0'); break; case 's': case 'S': odtstate = ODT_REG; xregno = 077; break; default: odtstate = ODT_PROMPT; put_q(); break; } break; case ODT_OPENLOC: switch (ch) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': odtstate = ODT_NEWVAL_LOC; newvalue = ch - '0'; break; case '\r': odtstate = ODT_PROMPT_PREV_LOC; put_s("\n@"); break; case '\n': xaddr = (xaddr & ~0xffff) | ((xaddr + 2) & 0xfffe); if (odt_fetchphys(xaddr,&val)) { odtstate = ODT_OPENLOC; put_s("\r\n@"); put_22(xaddr); put('/'); put_6(val); put(' '); } else { odtstate = ODT_PROMPT_PREV_LOC; put_s("\r\n?\r\n@"); } break; default: odtstate = ODT_PROMPT; put_q(); break; } break; case ODT_OPENREG: switch (ch) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': odtstate = ODT_NEWVAL_REG; newvalue = ch - '0'; break; case '\r': odtstate = ODT_PROMPT_PREV_REG; put_s("\n@"); break; case '\n': if (xregno > 7) { odtstate = ODT_PROMPT_PREV_REG; put_s("\r\n@"); } else { xregno = (xregno + 1) & 7; odtstate = ODT_OPENREG; put_s("\r\n@R"); put('0'+xregno); put('/'); put_6(*regs[xregno]); put(' '); } break; default: odtstate = ODT_PROMPT; put_q(); break; } break; case ODT_LOC: switch (ch) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': xaddr = (xaddr << 3) | (ch - '0'); break; case '/': xaddr &= 017777776; if (odt_fetchphys(xaddr,&val)) { odtstate = ODT_OPENLOC; put_6(val); put(' '); } else { odtstate = ODT_PROMPT_PREV_LOC; put_s("?\r\n@"); } break; case 'g': case 'G': Gcmd((word)(xaddr&0xffff)); break; case 's': case 'S': pc = xaddr & 0xffff; Scmd(); break; default: odtstate = ODT_PROMPT; put_q(); break; } break; case ODT_REG: switch (ch) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': xregno = (xregno << 3) | (ch - '0'); break; case 's': case 'S': xregno = 077; break; case '/': xregno &= 0377; if (xregno != 077) xregno &= 7; odtstate = ODT_OPENREG; put_6((xregno>7)?psw:*regs[xregno]); put(' '); break; default: odtstate = ODT_PROMPT; put_q(); break; } break; case ODT_NEWVAL_LOC: switch (ch) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': newvalue = (newvalue << 3) | (ch - '0'); break; case '\r': storephys(xaddr,newvalue); odtstate = ODT_PROMPT_PREV_LOC; put_s("\n@"); break; case '\n': storephys(xaddr,newvalue); xaddr = (xaddr & ~0xffff) | ((xaddr + 2) & 0xfffe); if (odt_fetchphys(xaddr,&val)) { odtstate = ODT_OPENLOC; put_s("\r\n@"); put_22(xaddr); put('/'); put_6(val); put(' '); } else { odtstate = ODT_PROMPT_PREV_LOC; put_s("\r\n?\r\n@"); } break; default: odtstate = ODT_PROMPT; put_q(); break; } break; case ODT_NEWVAL_REG: switch (ch) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': newvalue = (newvalue << 3) | (ch - '0'); break; case '\r': if (xregno > 7) { psw = (psw & PSW_T) | (newvalue & ~PSW_T); } else { *regs[xregno] = newvalue; } odtstate = ODT_PROMPT_PREV_REG; put_s("\n@"); break; case '\n': if (xregno > 7) { psw = (psw & PSW_T) | (newvalue & ~PSW_T); odtstate = ODT_PROMPT_PREV_REG; put_s("\r\n@"); } else { *regs[xregno] = newvalue; xregno = (xregno + 1) & 7; odtstate = ODT_OPENREG; put_s("\r\n@R"); put('0'+xregno); put('/'); put_6(*regs[xregno]); put(' '); } break; default: odtstate = ODT_PROMPT; put_q(); break; } break; case ODT_PROMPT_PREV_REG: switch (ch) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': odtstate = ODT_LOC; xaddr = ch - '0'; break; case 'r': case 'R': case '$': odtstate = ODT_R; xregno = 0; break; case 'g': case 'G': Gcmd((word)0); break; case 'p': case 'P': Pcmd(); break; case 's': case 'S': Scmd(); break; case 'Q': cons__reset(); exit(0); break; case 'X': xodt(); break; case 'Z': kill(getpid(),SIGTSTP); break; case '/': xregno &= 0377; if (xregno != 077) xregno &= 7; odtstate = ODT_OPENREG; put_6((xregno>7)?psw:*regs[xregno]); put(' '); break; default: odtstate = ODT_PROMPT; put_q(); break; } break; case ODT_PROMPT_PREV_LOC: switch (ch) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': odtstate = ODT_LOC; xaddr = ch - '0'; break; case 'r': case 'R': case '$': odtstate = ODT_R; xregno = 0; break; case 'g': case 'G': Gcmd((word)0); break; case 'p': case 'P': Pcmd(); break; case 's': case 'S': Scmd(); break; case 'Q': cons__reset(); exit(0); break; case 'X': xodt(); break; case 'Z': kill(getpid(),SIGTSTP); break; case '/': xaddr &= 017777776; if (odt_fetchphys(xaddr,&val)) { odtstate = ODT_OPENLOC; put_6(val); put(' '); } else { odtstate = ODT_PROMPT_PREV_LOC; put_s("?\r\n@"); } break; default: odtstate = ODT_PROMPT; put_q(); break; } break; } } }