Mercurial > hg > Members > kono > os9 > sbc09
view src/trace.c @ 84:9b661787d5ed
2Mbyte
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sat, 11 Aug 2018 18:16:04 +0900 |
parents | 8f3c0906adb9 |
children | 6f7276831219 |
line wrap: on
line source
/* 6808 Simulator V092 * * 2018 Shinji KONO * tracer * */ #include<stdio.h> #include<stdlib.h> #include<ctype.h> #include<signal.h> #include<sys/time.h> #include <unistd.h> #include <fcntl.h> #include <string.h> #include <time.h> #ifdef USE_TERMIOS #include <termios.h> #endif #define engine extern #include "v09.h" struct termios termsetting; int xmstat; /* 0= no XMODEM transfer, 1=send, 2=receiver */ unsigned char xmbuf[132]; int xidx; int acknak; int rcvdnak; int blocknum; extern FILE *logfile; extern FILE *infile; extern FILE *xfile; extern FILE *disk[]; extern void hexadump( unsigned char *b, int l, int loc, int w); extern int disasm(int,int); extern void restore_term(void) ; #ifdef USE_MMU extern char *prog ; // for disass extern Byte * mem0(Byte *iphymem, Word adr, Byte *immu) ; extern int paddr(Word adr, Byte *immu) ; #else #define paddr(a,m) (a) #endif void do_exit(void) { restore_term(); exit(0); } typedef struct bp { int address; // physical address int laddr; int count; int watch; // watch point struct bp *next; } BP, *BPTR; BPTR breakpoint = 0; int bpskip = 0; int trskip = 0; int stkskip = 0; int getterm(char *buf, char** next) { int value = 0; while (*buf==' ') buf++; if (*buf=='x') { value = xreg; buf++; *next = buf ; } else if (*buf=='y') { value = yreg; buf++; *next = buf; } else if (*buf=='u') { value = ureg; buf++; *next = buf; } else if (*buf=='s') { value = sreg; buf++; *next = buf; } else if (*buf=='p') { value = pcreg; buf++; *next = buf; } else if (*buf=='d') { value = (*areg<<8)+*breg; buf++; *next = buf; } else if (*buf=='a') { value = *areg; buf++; *next = buf; } else if (*buf=='b') { value = *breg; buf++; *next = buf; } else value = strtol(buf,next,0); return value; } int getarg(char *buf, char** next) { int value = 0; char *b = buf; if (next==0) next = &b; *next = buf; value=getterm(*next,next); for(;**next;) { if ( **next == '+' ) { value += getterm(*next+1,next); } else if ( **next == '*' ) { value *= getterm(*next+1,next); } else if ( **next == '/' ) { value /= getterm(*next+1,next); } else if ( **next == '-' ) { value -= getterm(*next+1,next); } else if ( **next == '&' ) { value &= getterm(*next+1,next); } else if ( **next == '|' ) { value |= getterm(*next+1,next); } else if ( **next == '(' ) { value = getarg(*next+1,next); if(**next==')') *next=*next+1; } else break; } return value; } void printhelp(void) { printf( "use 0x for hex inputs\n" " s [count] one step trace\n" " n step over\n" " f finish this call (until stack pop)\n" " b [adr] set break point (on current physical addreaa)\n" " B break point list\n" " d [n] delte break point list\n" " c [count] continue;\n" " p data print\n" " x [adr] [count] dump\n" " xi [adr] [count] disassemble\n" #ifdef USE_MMU " x [p page] [offset] [count] dump physical memory\n" " xi [p page] [offset] [count] disassemble\n" #endif " 0 file disk drive 0 image\n" " 1 file disk drive 1 image\n" " L file start log to file\n" " S file set input file\n" " X exit\n" " q exit\n" " U file upload from srecord file \n" " D file download to srecord file \n" " R do reset\n" " h,? print this\n" ); } void setbreak(int adr,int count, int page) ; int nexti(void); void do_escape(void) { char s[80]; int adr,page; int ppc = paddr(pcreg,mmu); if (bpskip) { // skip unbreak instruction bpskip--; BPTR *prev = &breakpoint; for(BPTR b = breakpoint; b ; prev=&b->next, b=b->next ) { #ifdef USE_MMU int watch = phymem[b->address]; #else int watch = mem[b->address]; #endif if (ppc==b->address || b->watch != watch ) { b->watch = watch; if (b->count==-1) { // temporaly break point BPTR next = b->next; free(b); *prev = next; goto restart0; } if (b->count) b->count--; if (b->count==0) { goto restart0; } } } return; } if (stkskip) { // skip until return #ifdef USE_MMU if (phymem[ppc]==0x3b||(phymem[ppc]==0x10&&phymem[ppc+1]==0x3f)) goto restart0; #else if (mem[ppc]==0x3b||(mem[ppc]==0x10&&mem[ppc+1]==0x3f)) goto restart0; #endif if (sreg < stkskip ) return; } restart0: stkskip = 0; restore_term(); #ifdef USE_MMU Byte *phyadr = phymem + ppc; prog = (char*)phyadr - pcreg; #endif do_trace(stdout); if (trskip>1) { // show trace and step trskip--; int watch; // watch point set_term(escchar); return; } restart: printf("v09>"); fgets(s, sizeof(s)-1, stdin); s[strlen(s)-1] = 0; // chop switch (s[0]) { case 'p': { int d = getarg(s+1,0); printf("0x%x %d '%c'\n",d,d,(d<' '||d>0x7f)?' ':d); goto restart; } case 'n': // step over if (nexti()) { bpskip = -1; break; } case 's': // one step trace trskip = 1; if (s[1]) { trskip = getarg(s+1,0); } bpskip = 0; attention = escape = 1; break; case 'f': // finish this call (until stack pop) stkskip = sreg + 2; attention = escape = 1; break; case 'b': { // set break point char *next = s; int page = -1; if (next[1]=='p') { next++; if (next[1]) page = getarg(next+1,&next); } if (next[1]) { int count = 0; int adr = getarg(next+1,&next); if (next[0]) { count = getarg(next,&next); } setbreak(adr,count,page); } else { setbreak(pcreg,0,page); } bpskip = -1; goto restart; } case 'B': // break point list for(BPTR bp = breakpoint; bp ; bp = bp->next) { #ifdef USE_MMU printf("0x%x p=0x%x c=%d w=0x%x\n", bp->laddr, bp->address, bp->count, bp->watch); #else printf("0x%x c=%d w=0x%x\n", bp->address, bp->count,bp->watch); #endif } goto restart; case 'd': // delte break point list if (s[1]) { int trskip = getarg(s+1,0); BPTR *prev = &breakpoint; for(BPTR bp = breakpoint; bp ; prev=&bp->next, bp = bp->next) { if (trskip-- == 0) { BPTR next = bp->next; free(bp); *prev = next; break; } prev = &bp->next; } } goto restart; case 'c': // continue; bpskip = -1; attention = escape = 1; if (s[1]) { bpskip = getarg(s+1,0); } break; /* * we should have disassembler for a mmu page */ case 'x': // dump { char d = 0; char p = 0; char *next = s+1; int len = 32; int adr = pcreg; if (*next=='i') { next++; d='i'; } if (*next=='p') { p = 'p'; next++; if (next[0]) { page = getarg(next,&next); } } if (next[0]) { adr = getarg(next,&next); #ifdef USE_MMU if (d!='i') // disassembler may fail on page boundary adr -= adr &0xf; #endif if (next[0]) { len = getarg(next,&next); } } for(; len > 0 ; len-=16,adr+=16) { Byte *phyadr = 0; #ifdef USE_MMU if (p=='p') { phyadr = phymem + (page * 0x2000 + adr); prog = (char*)phyadr - adr ; } else { phyadr = mem0(phymem,adr,mmu); prog = (char*)phyadr - adr ; } if (phyadr > phymem+memsize) goto restart; #else phyadr = mem+adr; if (phyadr > mem+0xffff) goto restart; #endif if (d=='i') { adr = disasm(adr,adr+(len>16?16:len))-16; } else { hexadump(phyadr,len>16?16:len,adr,16); } } goto restart; } case 'L': if (logfile) fclose(logfile); logfile = 0; if (s[1]) { int i=1; while(s[i]==' ') i++; logfile = fopen(s + i, "w"); } goto restart; break; case 'S': if (infile) fclose(infile); infile = 0; if (s[1]) { int i=1; while(s[i]==' ') i++; infile = fopen(s + i, "r"); } goto restart; break; case 'h': case '?': printhelp(); goto restart; case 'X': case 'q': if (!xmstat) do_exit(); else { xmstat = 0; fclose(xfile); xfile = 0; } goto restart; break; case '0': case '1': { FILE **drv = &disk[ s[0]-'0'] ; if (*drv) fclose(*drv); *drv = 0; if (s[1]) { int i=1; while(s[i]==' ') i++; *drv = fopen(s + i, "r+b"); if ( *drv == 0 ) { printf("can't open %s\n", &s[i]); } } } goto restart; break; case 'U': if (xfile) fclose(xfile); xfile = 0; if (s[1]) { int i=1; while(s[i]==' ') i++; xfile = fopen(s + i, "rb"); if ( xfile == 0 ) { printf("can't open %s\n", &s[i]); } } if (xfile) xmstat = 1; else xmstat = 0; xidx = 0; acknak = 21; rcvdnak = EOF; blocknum = 1; goto restart; break; case 'D': if (xfile) fclose(xfile); xfile = 0; if (s[1]) { int i=1; while(s[i]==' ') i++; xfile = fopen(s + i, "wb"); if ( xfile == 0 ) { printf("can't open %s\n", &s[i]); } } if (xfile) xmstat = 2; else xmstat = 0; xidx = 0; acknak = 21; blocknum = 1; goto restart; break; case 'R': pcreg = (mem[0xfffe] << 8) + mem[0xffff]; bpskip = 0; #ifdef USE_MMU mmu = &mem[0xffa0]; mem[0xffa7]=0x3f; #endif attention = escape = 1; // we have to reload romfile // readimage(); goto restart; break; default: // one step trace trskip = 1; bpskip = 0; attention = escape = 1; } if (tracing||breakpoint||trskip||bpskip||stkskip) { attention = escape = 1; } else attention = 0; set_term(escchar); } /* * keep break point / watch point in a list */ void setbreak(int adr, int count, int page) { BPTR bp = calloc(1,sizeof(BP)); bp->count = count; bp->laddr = adr; bp->address = paddr(adr,mmu); #ifdef USE_MMU if (page!=-1) { bp->address = page*0x2000 + adr; } if (bp->address >= memsize) { free(bp); return; } bp->watch = phymem[bp->address]; #else bp->watch = mem[adr]; #endif bp->next = breakpoint; breakpoint = bp; } /* * length of call instruction * * if next instruction is call or swi, put temporary break after the call instruction * (ignoring page boundary, sorry) */ int nexti(void) { #ifdef USE_MMU int op1 = *mem0(phymem,pcreg,mmu); int op2 = *mem0(phymem,pcreg+1,mmu); #else int op1 = mem[pcreg]; int op2 = mem[pcreg+1]; #endif int ofs = 0; switch(op1) { case 0x17: // LBSR case 0xbd: // JSR extended ofs=3; break; case 0x10: // page2 { if (op2==0x3f) { // os9 system call ofs=3; break; } } break; case 0x11: // page3 { if (op2==0x3f) { // SWI3 ofs=2; break; } } break; case 0x3f: // SWI ofs=1; break; case 0x3c: // CWAI case 0x8d: // BSR case 0x9d: // JSR direct ofs=2; break; case 0xad: // JSR index { if (op2<0x80) ofs = 2; // 5bit ofs else switch (op2&0xf) { case 8: case 0xc: ofs = 3; break; case 9: case 0xd: case 0xf: ofs = 4; break; default: ofs = 2; break; } } break; } if (ofs) setbreak(pcreg+ofs,-1,-1); return ofs; } /* end */