/************************************************/ /* */ /* Usual filename: SID03.C */ /* Remarks: Second C module for SID68K */ /* Author: Timothy M. Benson */ /* Control: 19 MAY 83 16:52 (TMB) */ /* */ /************************************************/ #include "lgcdef.h" #include "siddef.h" #include "ddtinc.h" #include "stdio.h" #include "bdosfunc.h" #include "disas.h" gocmd(cx,statep,nulist) /* begin executing (optional breakpoints) */ char *cx; struct cpustate *statep; int **nulist; { extern U16 pkawnt[HMPPTS]; extern U16 *plocus[HMPPTS]; extern U16 ancien[HMPPTS]; extern int minus; /* 1 => no intermediate display */ int nbp; long brkpt[MAXBP]; short brkwd[MAXBP]; long newpc; long x; int i; short itsapp; /* 1 => ILLEGAL identified as pass point */ short mor; /* 1 => nonzero pass count, so GO again */ union asis BEGIN long i32; char *p8; int *p16; END strand; /* General purpose pointer */ int jetsam; /* Place to save word after system call */ deblank(&cx); newpc = statep->pc; if (gethex(&cx, &x)) newpc = x; nbp = 0; while ( GETSEP ) { if (nbp >= MAXBP) {bad(); return;} else { if (gethex(&cx,&x)) brkpt[nbp++]=x; else {bad(); return;} } } if ( ! nomore(cx) ) {bad(); return(0);} statep->pc = newpc; /* Repeatedly set up pass points, break points, GO, restore */ /* after break, restore after pass, process pass point if */ /* applicable, continuing until pass point with count of one */ /* is encountered or until break point is encountered. */ for (mor = 1; mor and NOT keyhit();) BEGIN stick(); /* Set up pass points */ for (i=0; imemw; brkpt[i]->memw = ILLEGAL; } GO(statep); /* Restore previous contents at break points. */ for (i=0; imemw = brkwd[i]; yank(); /* Restore original contents at pass points. */ newpc = statep AT pc; /* Determine if pass point */ for(i=0,itsapp=0; i LT HMPPTS and NOT itsapp; i++) BLOCK strand.p16 = plocus[i]; If pkawnt[i] and strand.i32 EQ newpc then begin itsapp = 1; i--; end UNBLOCK strand.i32 = newpc; If *strand.p16 EQ ILLEGAL then BLOCK showstate(statep); stout("\nEncountered the ILLEGAL instruction\n"); goto trotz; UNBLOCK If itsapp then BLOCK If pkawnt[i] EQ (U16) 1 or NOT minus then begin shopas(i); showstate(statep); end If ancien[i] NE BDOSCALL and ancien[i] NE BIOSCALL then STEP(statep); else begin /* Execute system call normally */ strand.i32 = newpc + 2; jetsam = *strand.p16; *strand.p16 = ILLEGAL; GO(statep); *strand.p16 = jetsam; end newpc = statep AT pc; If pkawnt[i] GT (U16) 1 then --pkawnt[i]; otherwise begin mor = 0; showstate(statep); end UNBLOCK otherwise BLOCK mor = 0; showstate(statep); UNBLOCK END trotz: *nulist = statep AT pc; } /* end of go command */ /************************************************/ /* H alone: Spill symbol table */ /* Ha format: Print hex, ASCII, symbols */ /* Ha,b format: Do arithmetic */ /************************************************/ hexmath(cx) char *cx; { extern struct lmhedr *caput; extern int omega; extern int scope; long a, b; deblank(&cx); If nomore(cx) then BEGIN If omega GE 0 then deluge(caput AT sump,omega); else stout("\nNo symbols\n"); END otherwise BEGIN If gethex(&cx,&a) and nomore(cx) then BLOCK putchar('\n'); puthexl(a); putchar(' '); If qotbyt(a) then putchar(' '); spell(a,caput AT sump,scope,'b','h'); putchar('\n'); UNBLOCK else If GETSEP && gethex(&cx,&b) && nomore(cx) then BLOCK putchar('\n'); puthexl(a+b); putchar(' '); puthexl(a-b); putchar('\n'); UNBLOCK else bad(); END } incomtl(cx, valuep) char *cx; struct value *valuep; { /* process command tail */ register char *p; register char *q; register char nc; register struct basepage *bpp; if ( (valuep->kind) != 1 ) {bad(); return;} /* no pgm loaded */ bpp = valuep->bpa; p = cx + 1; q = &(bpp->comtail[1]); nc = 0; while (*p) { *q++ = *p++; nc += 1;} *q = *p; bpp->comtail[0] = nc; if ( parse(&cx, &(bpp->fcb1), " ") && GETSEP ) parse(&cx, &(bpp->fcb2), " "); } disasm(cx,dap) char *cx; char **dap; { /* display memory in assembly format */ extern struct lmhedr *caput; extern int scope; char *s; /* start address */ char *f; /* end address */ register short int deflt; register short int nl; /* parse command and extract parameters */ deblank(&cx); if ( ! gethex(&cx, &s) ) { /* get start address */ if (nomore(cx)) s = *dap; /* or use default */ else {bad(); return(0);} /* junk on the line */ } if ( s & 1) { bad(); return(0);} /* must use even address */ if ( GETSEP ) { /* get end address */ if ( gethex(&cx, &f) ) deflt=0; /* got it */ else { bad(); return(0); } } else { f = s; deflt = 1; } /* not there, use def */ if((!nomore(cx)) || (s>f)) {bad(); return(0);} /* junk or nonsense */ /* now do the display */ nl = 0; while ( (s<=f) || (deflt && (nl<12)) ) { if ( keyhit() ) return; If caput then nl INCBY spell((U32) s,caput AT sump,scope,'m','v'); putchar(' '); putchar(' '); puthexl(s); putchar(' '); dot = s; pinstr(); putchar('\n'); s += dotinc; nl++; *dap = s; } /* end of loop through instructions */ } /* end disassembly */ movemem(cx) char *cx; { /* move memory block */ char *s; /* start address */ char *f; /* end address */ char *d; /* destination address */ /* parse command and extract parameters */ deblank(&cx); if ( gethex(&cx, &s) ); /* get start address */ else {bad(); return(0);} /* not there, error */ if ( GETSEP && gethex(&cx, &f) ); /* get end address */ else { bad(); return(0); } /* not there, error */ if ( GETSEP && gethex(&cx, &d) ); /* get dest address */ else { bad(); return(0); } if ((!nomore(cx)) || (s>f) ) /* test for junk or nonsense */ { bad(); return(0); } /* now do the moving */ for ( ; s <= f; s++, d++ ) d->memb = s->memb; } /* end of movemem */ readfl(cx, basep, valuep, dap) char *cx; struct basepage *basep; struct value *valuep; char **dap; { /* read a file into memory */ struct fcb fcb1; long lotpa; long hitpa; long curdma; int endofile; deblank(&cx); if ( parse(&cx, &fcb1, " ") && nomore(cx)) { if ( (BDOS(OPEN, &fcb1) & 0xffL) == 0xffL) /* open failed */ { stout("Cannot open file\n"); return; } fcb1.cr = 0; lotpa = basep->lowtpa; hitpa = basep; curdma = lotpa; endofile = 0; while ( (! endofile) && (curdma+128 <= hitpa) ) { /* read a sector */ BDOS(SETDMA, curdma); endofile = (BDOS(READSEQ, &fcb1) & 0xffL); curdma += 128; } if ( ! endofile ) stout("\nFile too big -- read truncated.\n"); valuep->kind = 2; valuep->textbase = lotpa; valuep->textlen = curdma - lotpa - 128; showvals(valuep); *dap = lotpa; } else bad(); /* parsing error */ } setmem(cx) char *cx; { /* set memory */ register short int format; /* 1=byte, 2=word, 4=long word */ char *s; /* start address */ long v; /* value to stuff into memory */ char buf[BUFLEN]; /* input buffer */ char *bx; /* points into buf */ short int nc; /* num of hex digits input */ /* parse command and extract parameters */ format = getform(&cx); if ( gethex(&cx, &s) ); /* get start address */ else {bad(); return(0);} /* not there, error */ if ( (format != 1) && (s & 1) ) /* must be even address, error */ {bad(); return(0);} if (!nomore(cx)) { bad(); return(0); } /* test for junk */ /* now do the stuffing */ for ( ; ; s += format ) { puthexl(s); putchar(' '); switch ( format ) { case 1: puthexb(s->memb); break; case 2: puthexw(s->memw); break; case 4: puthexl(s->meml); break; } /* end of switch */ putchar(' '); *buf = BUFLEN - 2; BDOS ( READBUF, buf ); putchar('\n'); buf[2+(nc=buf[1])] = 0; if ( nc > 0 ) { if ( buf[2] == '.' ) {return(0);} for ( bx = &buf[1] ; *++bx ; ) *bx = toupper(*bx) ; bx = &buf[1]; if ( gethex( &bx, &v ) ); else { bad(); return(0); } while ( (*++bx) == 0x20 ) ; /* skip blanks */ if ( (*bx != 0) || /* test for bad input */ ( (format == 1) && ((v>255L) || (v<0)) ) || ( (format == 2) && ((v>65535L) || (v<0)) ) ) { bad(); return(0); } /* stuff the value */ switch ( format ) { case 1 : s->memb = (char)v ; if ( (s->memb ^ v) & 0x0ffL ) badram(s); break; case 2 : s->memw = (short int)v ; if ( (s->memw ^ v) & 0x0ffffL ) badram(s); break; case 4 : s->meml = (long)v ; if ( s->meml ^ v ) badram(s); break; } /* end of switch */ } /* end of nc > 0 */ } /* end of for */ } /* end of setmem */ trace(cx, statep, dap, tr) char *cx; struct cpustate *statep; char **dap; int tr; { /* trace program execution for n steps */ extern U16 pkawnt[HMPPTS]; extern U16 *plocus[HMPPTS]; extern U16 ancien[HMPPTS]; extern int minus; /* 1 => no intermediate display */ extern int omega; /* If negative, SID thinks no symbols */ int iota; /* Place to keep true value of "omega" */ /* while kidding oneself */ short itsapp; /* 1 => ILLEGAL identified as pass point */ union asis32 BEGIN long i32; char *p8; U16 *p16; END strand; /* General purpose pointer */ /**temp** Watch this: "strand" declared "*strand" elsewhere and */ /**temp** seems to work. Not sure why it works there, so it may */ /**temp** not work here. */ int jetsam; /* Place to save word after system call */ long nsteps; register int underw; /* 1 => trace without call */ int oxbow; /* 0 => trace; otherwise it = length */ register int inst; register long addr; int jt; /* General purpose loop index */ short mor; /* 1 => not finished with GO */ int kt; /* Loop index for GO */ iota = omega; /* Save true value of "omega" */ deblank(&cx); underw = vecina(&cx,'W'); if ( ! gethex(&cx, &nsteps)) nsteps = 1; if ( ! nomore(cx) ) {bad(); return;} /* Warning: Let there be no explicit returns here to end */ /* of function, lest symbols be accidentally zapped. */ If tr and minus then omega = -1; while(nsteps--) { inst = (addr = (statep->pc))->memw; If inst EQ ILLEGAL then BEGIN showstate(statep); stout("\nEncountered the ILLEGAL instruction\n"); goto reject; END /* GO thru traps, ignoring pass points */ If (inst & 0xFFF0) EQ 0x4E40 then BEGIN inst = (addr INCBY 2) AT memw; addr AT memw = ILLEGAL; GO(statep); addr AT memw = inst; goto refuse; END If underw and ((inst & 0xFF00) EQ 0x6100 or (inst & 0xFFC0) EQ 0x4E80) then BEGIN If NOT (inst & 0x00FF) then oxbow = 4; /* Long BSR */ else If (inst & 0xFF00) EQ 0x6100 then oxbow = 2; /* Short BSR */ else BLOCK /* JSR */ inst ANDWITH 0x003F; If inst GE 0x0038 then begin If inst EQ 0x0039 then oxbow = 6; otherwise oxbow = 4; end else begin inst ANDWITH 0x0038; If inst EQ 0x0010 then oxbow = 2; otherwise oxbow = 4; end UNBLOCK END otherwise oxbow = 0; strand.i32 = addr; for(jt=0,itsapp=0;jt LT HMPPTS and NOT itsapp;jt++) If pkawnt[jt] and strand.p16 EQ plocus[jt] then BEGIN itsapp = 1; jt--; END If itsapp then BEGIN If pkawnt[jt] GT (U16) 1 then --pkawnt[jt]; otherwise nsteps = 0; If NOT nsteps or NOT tr and NOT minus then BLOCK shopas(jt); showstate(statep); UNBLOCK END If oxbow then BEGIN inst = (addr INCBY oxbow) AT memw; addr AT memw = ILLEGAL; STEP(statep); for (mor=1;mor;) BLOCK stick(); GO(statep); yank(); If (strand.i32 = statep AT pc) EQ addr then mor = 0; otherwise begin for(kt=0,itsapp=0;kt LT HMPPTS and NOT itsapp;kt++) If pkawnt[kt] and strand.p16 EQ plocus[kt] then { itsapp = 1; kt--; } If itsapp and pkawnt[kt] GT (U16) 1 then --pkawnt[kt]; else {mor = 0; nsteps = 0;} If *strand.p16 EQ ILLEGAL then { showstate(statep); stout("\nEncountered the ILLEGAL instruction\n"); addr AT memw = inst; goto reject; } If NOT nsteps or NOT tr and NOT minus then { shopas(kt); showstate(statep); } STEP(statep); If keyhit() then {mor = 0; nsteps = 0; tr = 0;} end UNBLOCK addr AT memw = inst; END otherwise STEP(statep); refuse: if (tr) showstate(statep); if ( keyhit() ) nsteps = 0; } if ( ! tr ) showstate(statep); reject: *dap = statep->pc; omega = iota; /* Reenable symbols. */ } vcmd(cx, valuep) char *cx; struct value *valuep; {/* display start and end of stuff loaded with R or E commands */ if (nomore(cx)) showvals(valuep); otherwise bad(); } wrtfile(cx, valuep) char *cx; struct value *valuep; { /* write memory contents to disk */ struct fcb fcb1; long s; long f; deblank(&cx); if ( ! parse(&cx, &fcb1, " ") ) {bad(); return;} if ( nomore(cx) ) /* use default start and end */ { if ( (valuep->kind) != 2 ) {bad(); return;} s = valuep->textbase; f = s + valuep->textlen - 1; } else /* try to parse s & f values */ { if ( ( ! GETSEP ) || ( ! gethex(&cx, &s) ) || ( ! GETSEP ) || ( ! gethex(&cx, &f) ) || ( ! nomore(cx) ) ) {bad(); return;} } BDOS(DELETE, &fcb1); if ( (BDOS(MAKEFILE, &fcb1) & 0xffL) == 0xffL ) { stout("Cannot create file.\n"); return; } fcb1.cr = 0; while ( s <= f ) { BDOS(SETDMA, s); if ( BDOS(WRITSEQ, &fcb1) & 0xffL ) { stout("File write error.\n"); s = f + 1; } s += 128; } BDOS(CLOSE, &fcb1); } int dummy(s) char *s; { stout("\n\nUnimplemented Function: "); stout(s); stout("\n\n"); } shopas(jsh) /* Display pass-point data */ int jsh; { extern U16 pkawnt[HMPPTS]; extern U16 *plocus[HMPPTS]; putchar('\n'); puthexw(pkawnt[jsh]); stout(" PASS "); puthexl(plocus[jsh]); putchar('\n'); } stick() /* Set pass points, saving original contents. */ { extern U16 pkawnt[HMPPTS]; extern U16 *plocus[HMPPTS]; extern U16 ancien[HMPPTS]; int kst; for (kst=0; kst LT HMPPTS; kst++) If pkawnt[kst] then BLOCK ancien[kst] = *plocus[kst]; *plocus[kst] = ILLEGAL; UNBLOCK } yank() /* Restore original contents at pass points. */ { extern U16 pkawnt[HMPPTS]; extern U16 *plocus[HMPPTS]; extern U16 ancien[HMPPTS]; int kya; for (kya=0; kya LT HMPPTS; kya++) If pkawnt[kya] then *plocus[kya] = ancien[kya]; }