.title assist09 - mc6809 monitor .module assist09 .radix d ;* Modification date: November 23, 1988 ;******************************************************** ;* miscelaneous equates ;******************************************************** dftchp = 0 ; default character pad count dftnlp = 0 ; default new line pad count prompt = '> ; prompt character numbkp = 8 ; number of breakpoints eot = 0x04 ; end of transmission bell = 0x07 ; bell character lf = 0x0a ; line feed cr = 0x0d ; carriage return can = 0x18 ; cancel (ctl-x) .page .sbttl SWI Functions ;******************************************************** ;* assist09 monitor swi functions ;* ;* the following equates define functions provided ;* by the assist09 monitor via the swi instruction. ;******************************************************** inchnp = 0 ; input char in a reg - no parity outch = 1 ; output char from a reg pdata1 = 2 ; output string pdata = 3 ; output cr/lf then string out2hs = 4 ; output two hex and space out4hs = 5 ; output four hex and space pcrlf = 6 ; output cr/lf space = 7 ; output a space monitr = 8 ; enter assist09 monitor vctrsw = 9 ; vector examine/switch brkpt = 10 ; user program breakpoint pause = 11 ; task pause function numfun = 11 ; number of available functions ;* sub-codes for accessing the vector table. ;* they are equivalent to offsets in the table. ;* relative positioning must be maintained. .avtbl = 0 ; address of vector table .cmdl1 = 2 ; first command list .rsvd = 4 ; reserved hardware vector .swi3 = 6 ; swi3 routine .swi2 = 8 ; swi2 routine .firq = 10 ; firq routine .irq = 12 ; irq routine .swi = 14 ; swi routine .nmi = 16 ; nmi routine .reset = 18 ; reset routine .cion = 20 ; console on .cidta = 22 ; console input data .cioff = 24 ; console input off .coon = 26 ; console output on .codta = 28 ; console output data .cooff = 30 ; console output off .hsdta = 32 ; high speed printdata .bson = 34 ; punch/load on .bsdta = 36 ; punch/load data .bsoff = 38 ; punch/load off .pause = 40 ; task pause routine .expan = 42 ; expression analyzer .cmdl2 = 44 ; second command list .pad = 46 ; character pad and new line pad .echo = 48 ; echo/load and null bkpt flag numvtr = 48/2+1 ; number of vectors hivtr = 48 ; highest vector offset .page .sbttl Work Area ;******************************************************** ;* work area ;* ;* The direct page register during most routine ;* operations will point to this work area. the Stack ;* initially starts under the reserved work areas as ;* defined herein. ;******************************************************** .area WORKPG (ABS,OVR) .setdp 0 workpg: ; beginning of work aera .blkb 0d256-(endpg-astack) ; stack space astack: ; top of assist09 stack tstack: .blkb 0d21 ; temporary stack hold delim: .blkb 1 ; expression delimiter/work byte misflg: .blkb 1 ; load cmd/thru breakpoint flag swicnt: .blkb 1 ; trace "swi" nest level count pcnter: .blkb 2 ; last program counter pstack: .blkb 2 ; command recovery stack rstack: .blkb 2 ; reset stack pointer anumber:.blkb 2 ; binary build area basepg: .blkb 1 ; base page value addr: .blkb 2 ; address pointer value window: .blkb 2 ; window bkptop: .blkb 0x10 ; breakpoint opcode table bkptbl: .blkb 0x10 ; breakpoint table vectab: .blkb 0x32 ; vector table bkptct: .blkb 1 ; breakpoint count swibfl: .blkb 1 ; bypass swi as breakpoint flag pauser: .blkb 4 ; pause routine endpg: .page .sbttl Assist09 Code .area ASSIST09 (ABS,OVR) ;******************************************************** ;* bldvtr - build assist09 vector table ;* ;* hardware reset calls this subroutine to build the ;* assist09 vector table. ;* ;* input: s->valid stack ram ;* output: u->vector table address ;* dpr->assist09 work area page ;* the vector table and defaults are initialized ;* ;* all registers volatile ;******************************************************** bldvtr: leax vectab,pcr ; address vector table tfr x,d ; obtain base page address tfr a,dp ; setup dpr sta *basepg ; store for quick reference leau ,x ; return table to caller stu ,x++ ; and init vector table address ldb #numvtr-3 ; number relocatable vectors pshs b ; store index on stack leay initvt,pcr ; load from addr 1$: tfr y,d ; prepare address resolve addd ,y++ ; to absolute address std ,x++ ; into vector table dec ,s ; count down bne 1$ ; branch if more to insert ldb #intve-intvs ; static value init length 2$: lda ,y+ ; load next byte sta ,x+ ; store into position decb ; count down bne 2$ ; loop until done puls pc,b ; return to initializer ;******************************************************** ;* reset entry point ;* ;* hardware reset enters here if assist09 is enabled ;* to receive the mc6809 hardware vectors. we call ;* the bldvtr subroutine to initialize the vector ;* table, stack, and then fireup the monitor via swi ;* call. ;******************************************************** reset: leas astack,pcr ; setup initial stack bsr bldvtr ; build vector table 1$: clra ; issue startup message tfr a,dp ; default to page zero swi ; perform monitor fireup .byte monitr ; to enter command processing bra 1$ ; reenter monitor if 'continue' .page .sbttl Vector Table ;******************************************************** ;* initvt - initialize vector table ;* ;* this table is relocated to ram and represents the ;* initial state of the vector table. all addresses ;* are converted to absolute form. this table starts ;* with the second entry, ends with static constant ;* initialization data which carries beyond the table. ;******************************************************** initvt: .word cmdtb1-. ; default first command table .word rsrvdr-. ; default undefined hardware vector .word swi3r-. ; default swi3 .word swi2r-. ; default swi2 .word firqr-. ; default firq .word irqr-. ; default irq routine .word swir-. ; default swi routine .word nmir-. ; default nmi routine .word reset-. ; restart vector .word cion-. ; default cion .word cidta-. ; default cidta .word cioff-. ; default cioff .word coon-. ; default coon .word codta-. ; default codta .word cooff-. ; default cooff .word hsdta-. ; default hsdta .word bson-. ; default bson .word bsdta-. ; default bsdta .word bsoff-. ; default bsoff .word cpause-. ; default pause routine .word exp1-. ; default expression analyzer .word cmdtb2-. ; default second command table ;* constants ;* intvs: .byte dftchp,dftnlp ; default null padds .word 0 ; default echo .byte 0 ; initial breakpoint count .byte 0 ; swi breakpoint level rts ; default pause routine intve = . .page .sbttl SWI Handler ;******************************************************** ;* assist09 swi handler ;* ;* the swi handler provides all interfacing necessary ;* for a user program. a function byte is assumed to ;* follow the swi instruction. it is bound checked ;* and the proper routine is given control. this ;* invocation may also be a breakpoint interrupt. ;* if so, the breakpoint handler is entered. ;* ;* input: machine state defined for swi ;* output: varies according to function called. pc on ;* ;* callers stack incremented by one if valid call. ;* volatile registers: see functions called ;* ;* state: runs disabled unless function clears i flag. ;******************************************************** ;* swi function vector table swivtb: .word zinch-swivtb ; inchnp .word zotch1-swivtb ; outch .word zpdta1-swivtb ; pdata1 .word zpdata-swivtb ; pdata .word zot2hs-swivtb ; out2hs .word zot4hs-swivtb ; out4hs .word zpcrlf-swivtb ; pcrlf .word zspace-swivtb ; space .word zmontr-swivtb ; monitr .word zvswth-swivtb ; vctrsw .word zbkpnt-swivtb ; breakpoint .word zpause-swivtb ; task pause swir: dec swicnt,pcr ; up "swi" level for trace lbsr lddp ; setup page and verify stack ;* check for breakpoint trap ldu 10,s ; load program counter leau -1,u ; back to swi address tst *swibfl ; this "swi" breakpoint ? bne 2$ ; no - branch to let through lbsr cbkldr ; obtain breakpoint pointers negb ; obtain positive count 1$: decb ; count down bmi 2$ ; branch when done cmpu ,y++ ; ? was this a breakpoint bne 1$ ; branch if not stu 10,s ; set program counter back lbra zbkpnt ; go do breakpoint 2$: clr *swibfl ; clear in case set pulu d ; obtain function byte, up pc cmpb #numfun ; ? too high lbhi error ; yes, do breakpoint stu 10,s ; bump program counter past swi aslb ; function code times two leau swivtb,pcr ; obtain vector branch address ldd b,u ; load offset jmp d,u ; jump to routine .page .sbttl Monitor Entry ;******************************************************** ;* registers to function routines: ;* dp-> work area page ;* d,y,u=unreliable x=as called from user ;* s=as from swi interrupt ;******************************************************** ;******************************************************** ;* [swi function 8] ;* monitor entry ;* ;* fireup the assist09 monitor. ;* the stack with its values for the direct page ;* register and condition code flags are used as is. ;* 1) initialize console i/o ;* 2) optionally print signon ;* 3) enter command processor ;* ;* input: a=0 init console and print startup message ;* a#0 omit console init and startup message ;******************************************************** signon: .ascii /Assist09 -- 6809 Monitor/ ; signon eye-catcher .byte eot zmontr: sts *rstack ; save for bad stack recovery tst 1,s ; ? init console and send msg bne 1$ ; branch if not jsr [vectab+.cion,pcr] ; ready console input jsr [vectab+.coon,pcr] ; ready console output leax signon,pcr ; ready signon eye-catcher swi ; perform .byte pdata ; print string 1$: ; fall through to cmd .page .sbttl Command Processor ;******************************************************** ;* command handler ;* ;* breakpoints are removed at this time. ;* prompt for a command, and store all characters ;* until a separator on the stack. ;* search for first matching command subset, ;* call it or give '?' response. ;* ;* during command search: ;* b=offset to next entry on x ;* u=saved s ;* u-1=entry size+2 ;* u-2=valid number flag (>=0 valid)/compare cnt ;* u-3=carriage return flag (0=cr has been done) ;* u-4=start of command store ;* s+0=end of command store ;******************************************************** ;******************************************************** ;* commands are entered as a subroutine with: ;* dpr->assist09 direct page work area ;* z=1 carriage return entered ;* z=0 non carriage return delimiter ;* s=normal return address ;* ;* the label "cmdbad" may be entered to issue an ;* an error flag (?). ;******************************************************** cmd: swi ; to new line .byte pcrlf ; function ;* disarm the breakpoints cmdnep: lbsr cbkldr ; obtain breakpoint pointers bpl 2$ ; branch if not armed or none negb ; make positive stb *bkptct ; flag as disarmed 1$: decb ; ? finished bmi 2$ ; branch if so lda -numbkp*2,y ; load opcode stored sta [,y++] ; store back over "swi" bra 1$ ; loop until done 2$: ldx 10,s ; load users program counter stx *pcnter ; save for expression analyzer lda #prompt ; load prompt character swi ; send to output handler .byte outch ; function leau ,s ; remember stack restore address stu *pstack ; remember stack for error use clra ; prepare zero clrb ; prepare zero std *anumber ; clear number build area std *misflg ; clear miscel. and swicnt flags ldb #2 ; set d to two pshs d,cc ; place defaults onto stack ;* check for "quick" commands. lbsr read ; obtain first character leax cmpadp+2,pcr ; ready memory entry point cmpa #'/ ; open last used memory ? beq 11$ ; yes - doit ;* process next character 3$: cmpa #' ; ? blank or delimiter bls 5$ ; branch yes, we have it pshs a ; build onto stack inc -1,u ; count this character cmpa #'/ ; ? memory command beq 12$ ; branch if so lbsr bldhxc ; treat as hex value beq 4$ ; branch if still valid number dec -2,u ; flag as invalid number 4$: lbsr read ; obtain next character bra 3$ ; test next character ;* got command, now search tables 5$: suba #cr ; set zero if carriage return sta -3,u ; setup flag ldx *vectab+.cmdl1 ; start with first cmd list 6$: ldb ,x+ ; load entry length bpl 7$ ; branch if not list end ldx *vectab+.cmdl2 ; now to second cmd list incb ; ? to continue to default list beq 6$ ; branch if so cmdbad=. lds *pstack ; restore stack leax errmsg,pcr ; point to error string swi ; send out .byte pdata1 ; to console bra cmd ; and try again ;* search next entry 7$: decb ; take account of length byte cmpb -1,u ; ? entered longer than entry bhs 9$ ; branch if not too long 8$: abx ; skip to next entry bra 6$ ; and try next 9$: leay -3,u ; prepare to compare lda -1,u ; load size+2 suba #2 ; to actual size entered sta -2,u ; save size for countdown 10$: decb ; down one byte lda ,x+ ; next command character cmpa ,-y ; ? same as that entered bne 8$ ; branch to flush if not dec -2,u ; count down length of entry bne 10$ ; branch if more to test abx ; to next entry ldd -2,x ; load offset leax d,x ; compute routine address+2 11$: tst -3,u ; set cc for carriage return test leas ,u ; delete stack work area jsr -2,x ; call command lbra 2$ ; go get next command 12$: tst -2,u ; ? valid hex number entered bmi cmdbad ; branch error if not leax cmemn-cmpadp,x ; to different entry ldd *anumber ; load number entered bra 11$ ; and enter memory command .page .sbttl assist09 Command Tables ;******************************************************** ;* assist09 command tables ;* ;* these are the default command tables. external ;* tables of the same format may extend/replace ;* these by using the vector swap function. ;* ;* entry format: ;* +0...total size of entry (including this byte) ;* +1...command string ;* +n...two byte offset to command (entryaddr-.) ;* ;* the tables terminate with a one byte -1 or -2. ;* the -1 continues the command search with the ;* second command table. ;* the -2 terminates command searches. ;******************************************************** ;* this is the default list for the second command ;* list entry. cmdtb2: .byte -2 ; stop command searches ;* this is the default list for the first command ;* list entry. cmdtb1: ; monitor command table .byte 4 .ascii /B/ ; 'breakpoint' command .word cbkpt-. .byte 4 .ascii /C/ ; 'call' command .word ccall-. .byte 4 .ascii /D/ ; 'display' command .word cdi-. .byte 4 .ascii /E/ ; 'encode' command .word cencde-. .byte 4 .ascii /G/ ; 'go' command .word cgo-. .byte 4 .ascii /L/ ; 'load' command .word cload-. .byte 4 .ascii /M/ ; 'memory' command .word cmem-. .byte 4 .ascii /N/ ; 'nulls' command .word cnulls-. .byte 4 .ascii /O/ ; 'offset' command .word coffs-. .byte 4 .ascii /P/ ; 'punch' command .word cpunch-. .byte 4 .ascii /R/ ; 'registers' command .word creg-. .byte 4 .ascii /V/ ; 'verify' command .word cver-. .byte 4 .ascii /W/ ; 'window' command .word cwindo-. .byte -1 ; end, continue with the second .page .sbttl SWI Functions ;******************************************************** ;* [swi functions 4 and 5] ;* ;* 4 - out2hs - decode byte to hex and add space ;* 5 - out4hs - decode word to hex and add space ;* ;* input: x->byte or word to decode ;* output: characters sent to output handler ;* x->next byte or word ;******************************************************** zout2h: lda ,x+ ; load next byte pshs d ; save - do not reread ldb #16 ; shift by 4 bits mul ; with multiply bsr zouthx ; send out as hex puls d ; restore bytes anda #0x0f ; isolate right hex zouthx: adda #0x90 ; prepare a-f adjust daa ; adjust adca #0x40 ; prepare character bits daa ; adjust send: jmp [vectab+.codta,pcr] ; send to out handler zot4hs: bsr zout2h ; convert first byte zot2hs: bsr zout2h ; convert byte to hex stx 4,s ; update users x register ;* fall into space routine ;******************************************************** ;* [swi function 7] ;* ace - send blank to output handler ;* ;* input: none ;* output: blank send to console handler ;******************************************************** zspace: lda #' ; load blank bra zotch2 ; send and return ;******************************************************** ;* [swi function 9] ;* swap vector table entry ;* ;* input: a=vector table code (offset) ;* x=0 or replacement value ;* output: x=previous value ;******************************************************** zvswth: lda 1,s ; load requesters a cmpa #hivtr ; ? sub-code too high bhi zotch3 ; ignore call if so ldy *vectab+.avtbl ; load vector table address ldu a,y ; u=old entry stu 4,s ; return old value to callers x stx -2,s ; ? x=0 beq zotch3 ; yes, do not change entry stx a,y ; replace entry bra zotch3 ; return from swi .page ;******************************************************** ;* [swi function 0] ;* inchnp - obtain input char in a (no parity) ;* ;* nulls and rubouts are ignored. ;* automatic line feed is sent upon recieving a ;* carriage return. ;* unless we are loading from tape. ;******************************************************** zinchp: bsr xqpaus ; release processor zinch: bsr xqcidt ; call input data appendage bcc zinchp ; loop if none available tsta ; test for null beq zinch ; ignore null cmpa #0x7f ; ? rubout beq zinch ; branch yes to ignore sta 1,s ; store into callers a tst *misflg ; ? load in progress bne zotch3 ; branch if so to not echo cmpa #cr ; ? carriage return bne 1$ ; no, test echo byte lda #lf ; load line feed bsr send ; always echo line feed 1$: tst *vectab+.echo ; ? echo desired bne zotch3 ; no, return ;* fall through to outch ;******************************************************** ;* [swi function 1] ;* outch - output character from a ;* ;* input: none ;* output: if linefeed is the output character then ;* c=0 no ctl-x recieved, c=1 ctl-x recieved ;******************************************************** zotch1: lda 1,s ; load character to send leax zpcrls,pcr ; default for line feed cmpa #lf ; ? line feed beq zpdtlp ; branch to check pause if so zotch2: bsr send ; send to output routine zotch3: inc *swicnt ; bump up "swi" trace nest level rti ; return from "swi" function ;******************************************************** ;* [swi function 6] ;* pcrlf - send cr/lf to console handler ;* ;* input: none ;* output: cr and lf sent to handler ;* c=0 no ctl-x, c=1 ctl-x recieved ;******************************************************** zpcrls: .byte eot ; null string zpcrlf: leax zpcrls,pcr ; ready cr,lf string ;* fall into cr/lf code ;******************************************************** ;* [swi function 3] ;* pdata - output cr/lf and string ;* ;* input: x->string ;* output: cr/lf and string sent to output console ;* handler. ;* c=0 no ctl-x, c=1 ctl-x recieved ;* ;* note: line feed must follow carriage return for ;* proper punch data. ;******************************************************** zpdata: lda #cr ; load carriage return bsr send ; send it lda #lf ; load line feed ;* fall into pdata1 ;******************************************************** ;* [swi function 2] ;* pdata1 - output string till eot (0x04) ;* ;* this routine pauses if an input byte becomes ;* available during output transmission until a ;* second is recieved. ;* ;* input: x->string ;* output: string sent to output console driver ;* c=0 no ctl-x, c=1 ctl-x recieved ;******************************************************** zpdtlp: bsr send ; send character to driver zpdta1: lda ,x+ ; load next character cmpa #eot ; ? eot bne zpdtlp ; loop if not ;* fall into pause check function ;******************************************************** ;* [swi function 12] ;* pause - return to task dispatching and check ;* ;* for freeze condition or ctl-x break ;* this function enters the task pause handler so ;* optionally other 6809 processes may gain control. ;* upon return, check for a 'freeze' condition ;* with a resulting wait loop, or condition code ;* return if a control-x is entered from the input ;* handler. ;* ;* output: c=1 if ctl-x has entered, c=0 otherwise ;******************************************************** zpause: bsr xqpaus ; release control at every line bsr chkabt ; check for freeze or abort tfr cc,b ; prepare to replace cc stb ,s ; overlay old one on stack bra zotch3 ; return from "swi" ;* chkabt - scan for input pause/abort during output ;* output: c=0 ok, c=1 abort (ctl-x issued) ;* volatile: u,x,d chkabt: bsr xqcidt ; attempt input bcc 2$ ; branch no to return cmpa #can ; ? ctl-x for abort bne 3$ ; branch no to pause 1$: comb ; set carry 2$: rts ; return to caller with cc set 3$: bsr xqpaus ; pause for a moment bsr xqcidt ; ? key for start bcc 3$ ; loop until recieved cmpa #can ; ? abort signaled from wait beq 1$ ; branch yes clra ; set c=0 for no abort rts ; and return ;* save memory with jumps xqpaus: jmp [vectab+.pause,pcr] ; to pause routine xqcidt: jsr [vectab+.cidta,pcr] ; to input routine anda #0x7f ; strip parity rts ; return to caller ;* lddp - setup direct page register, verify stack. ;* an invalid stack causes a return to the command ;* handler. ;* input: fully stacked registers from an interrupt ;* output: dpr loaded to work page errmsg: .byte '?,bell,0x20,eot ; error response ldrtn: rts lddp: ldb basepg,pcr ; load direct page high byte tfr b,dp ; setup direct page register cmpa 3,s ; ? is stack valid beq ldrtn ; yes, return lds *rstack ; reset to initial stack pointer error: leax errmsg,pcr ; load error report swi ; send out before registers .byte pdata ; on next line ;* fall into breakpoint handler ;******************************************************** ;* [swi function 10] ;* breakpoint program function ;* ;* print registers and go to command handler ;******************************************************** zbkpnt: bsr zbkstk ; stack an extra word zbkcmd: lbra cmdnep ; now enter command handler zbkstk: lbsr regprt ; print out registers rts ;******************************************************** ;* irq, reserved, swi2 and swi3 interrupt handlers ;* the default handling is to cause a breakpoint. ;******************************************************** swi2r: ; swi2 entry swi3r: ; swi3 entry irqr: ; irq entry nmir: ; nmi entry rsrvdr: bsr lddp ; set base page, validate stack bra zbkpnt ; force a breakpoint ;******************************************************** ;* firq handler ;* just return for the firq interrupt ;******************************************************** firqr: rti ; immediate return .page .sbttl Read / Verify / Punch Routines ;* bson - turn on read/verify/punch mechanism bson: inc *misflg ; set load in progress flag rts ; return to caller ;* bsoff - turn off read/verify/punch mechanism ;* a,x volatile bsoff: dec *misflg ; clear load in progress flag rts ; return to caller ;* bsdta - read/verify/punch handler ;* input: s+6=code byte, verify(-1),punch(0),load(1) ;* s+4=start address ;* s+2=stop address ;* s+0=return address ;* output: z=1 normal completion, z=0 invalid load/ver ;* registers are volatile bsdta: ldu 2,s ; u=to address or offset tst 6,s ; ? punch beq 10$ ; branch yes ;* during read/verify: s+2=msb address save byte ;* s+1=byte counter ;* s+0=checksum ;* u holds offset leas -3,s ; room for work/counter/checksum 1$: swi ; get next character .byte inchnp ; function 2$: cmpa #'S ; ? start of s1/s9 bne 1$ ; branch not swi ; get next character .byte inchnp ; function cmpa #'9 ; ? have s9 beq 5$ ; yes, return good code cmpa #'1 ; ? have new record bne 2$ ; branch if not clr ,s ; clear checksum bsr 9$ ; obtain byte count stb 1,s ; save for decrement ;* read address bsr 9$ ; obtain high value stb 2,s ; save it bsr 9$ ; obtain low value lda 2,s ; make d=value leay d,u ; y=address+offset ;* store text 3$: bsr 9$ ; next byte beq 6$ ; branch if checksum tst 9,s ; ? verify only bmi 4$ ; yes, only compare stb ,y ; store into memory 4$: cmpb ,y+ ; ? valid ram beq 3$ ; yes, continue reading 5$: puls pc,x,a ; return with z set proper 6$: inca ; ? valid checksum beq 1$ ; branch yes bra 5$ ; return z=0 invalid ;* byte builds 8 bit value from two hex digits in 7$: bsr 9$ ; obtain first hex ldb #16 ; prepare shift mul ; over to a bsr 9$ ; obtain second hex pshs b ; save high hex adda ,s+ ; combine both sides tfr a,b ; send back in b adda 2,s ; compute new checksum sta 2,s ; store back dec 3,s ; decrement byte count 8$: rts ; return to caller 9$: swi ; get next hex .byte inchnp ; character lbsr cnvhex ; convert to hex beq 8$ ; return if valid hex puls pc,u,y,x,a ; return to caller with z=0 ;* punch stack use: s+8=to address ;* s+6=return address ;* s+4=saved padding values ;* s+2 from address ;* s+1=frame count/checksum ;* s+0=byte count 10$: ldu *vectab+.pad ; load padding values ldx 4,s ; x=from address pshs u,x,d ; create stack work area ldd #24 ; set a=0, b=24 stb *vectab+.pad ; setup 24 character pads swi ; send nulls out .byte outch ; function ldb #4 ; setup new line pad to 4 std *vectab+.pad ; setup punch padding ;* calculate size 11$: ldd 8,s ; load to subd 2,s ; minus from=length cmpd #24 ; ? more than 23 blo 12$ ; no, ok ldb #23 ; force to 23 max 12$: incb ; prepare counter stb ,s ; store byte count addb #3 ; adjust to frame count stb 1,s ; save ;*punch cr,lf,nuls,s,1 leax 16$,pcr ; load start record header swi ; send out .byte pdata ; function ;* send frame count clrb ; initialize checksum leax 1,s ; point to frame count and addr bsr 14$ ; send frame count ;*data address bsr 14$ ; send address hi bsr 14$ ; send address low ;*punch data ldx 2,s ; load start data address 13$: bsr 14$ ; send out next byte dec ,s ; ? final byte bne 13$ ; loop if not done stx 2,s ; update from address value ;*punch checksum comb ; complement stb 1,s ; store for sendout leax 1,s ; point to it bsr 15$ ; send out as hex ldx 8,s ; load top address cmpx 2,s ; ? done bhs 11$ ; branch not leax 17$,pcr ; prepare end of file swi ; send out string .byte pdata ; function ldd 4,s ; recover pad counts std *vectab+.pad ; restore clra ; set z=1 for ok return puls pc,u,x,d ; return with ok code 14$: addb ,x ; add to checksum 15$: lbra zout2h ; send out as hex and return 16$: .byte 'S,'1,eot ; cr,lf,nulls,S,1 17$: .ascii /S9030000FC/ ; eof string .byte cr,lf,eot ;* hsdta - high speed print memory ;* input: s+4=start address ;* s+2=stop address ;* s+0=return address ;* x,d volatile ;* send title hsdta: swi ; send new line .byte pcrlf ; function ldb #6 ; prepare 6 spaces 1$: swi ; send blank .byte space ; function decb ; count down bne 1$ ; loop if more clrb ; setup byte count 2$: tfr b,a ; prepare for convert lbsr zouthx ; convert to a hex digit swi ; send blank .byte space ; function swi ; send another .byte space ; blank incb ; up another cmpb #0x10 ; ? past 'f' blo 2$ ; loop until so 3$: swi ; to next line .byte pcrlf ; function bcs 8$ ; return if user entered ctl-x leax 4,s ; point at address to convert swi ; print out address .byte out4hs ; function ldx 4,s ; load address proper ldb #16 ; next sixteen 4$: swi ; convert byte to hex and send .byte out2hs ; function decb ; count down bne 4$ ; loop if not sixteenth swi ; send blank .byte space ; function ldx 4,s ; reload from address ldb #16 ; count 5$: lda ,x+ ; next byte bmi 6$ ; too large, to a dot cmpa #' ; ? lower than a blank bhs 7$ ; no, branch ok 6$: lda #'. ; convert invalid to a blank 7$: swi ; send character .byte outch ; function decb ; ? done bne 5$ ; branch no cpx 2,s ; ? past last address bhs 8$ ; quit if so stx 4,s ; update from address lda 5,s ; load low byte address asla ; ? to section boundry bne 3$ ; branch if not bra hsdta ; branch if so 8$: swi ; send new line .byte pcrlf ; function rts ; return to caller ;******************************************************** ;* a s s i s t 0 9 c o m m a n d s ;******************************************************** ;********** registers - display and change registers creg: bsr regprt ; print registers inca ; set for change function bsr regchg ; go change, display registers rts ; return to command processor ;******************************************************** ;* regprt - print/change registers subroutine ;* will abort to 'cmdbad' if overflow detected during ;* a change operation. change displays registers when ;* done. ;* ;* register mask list consists of: ;* a) characters denoting register ;* b) zero for one byte, -1 for two ;* c) offset on stack to register position ;* ;* input: +4=stacked registers ;* a=0 print, a#0 print and change ;* output: (only for register display) ;* c=1 control-x entered, c=0 otherwise ;* ;* volatile: d,x (change) ;* b,x (display) ;******************************************************** regmsk: .byte 'P,'C,-1,19 ; pc reg .byte 'A,0,10 ; a reg .byte 'B,0,11 ; b reg .byte 'X,-1,13 ; x reg .byte 'Y,-1,15 ; y reg .byte 'U,-1,17 ; u reg .byte 'S,-1,1 ; s reg .byte 'C,'c,0,9 ; cc reg .byte 'D,'p,0,12 ; dp reg .byte 0 ; end of list regprt: clra ; setup print only flag regchg: leax 4+12,s ; ready stack value pshs y,x,a ; save on stack with option leay regmsk,pcr ; load register mask 1$: ldd ,y+ ; load next char or <=0 tsta ; ? end of characters ble 2$ ; branch not character swi ; send to console .byte outch ; function byte bra 1$ ; check next 2$: lda #'- ; ready '-' swi ; send out .byte outch ; with outch leax b,s ; x->register to print tst ,s ; ? change option bne 5$ ; branch yes tst -1,y ; ? one or two bytes beq 3$ ; branch zero means one swi ; perform word hex .byte out4hs ; function bra 4$ 3$: swi ; perform byte hex .byte out2hs ; function 4$: ldd ,y+ ; to front of next entry tstb ; ? end of entries bne 1$ ; loop if more swi ; force new line .byte pcrlf ; function puls pc,y,x,a ; restore stack and return 5$: bsr bldnnb ; input binary number beq 7$ ; if change then jump cmpa #cr ; ? no more desired beq 9$ ; branch nope ldb -1,y ; load size flag decb ; minus one negb ; make positive aslb ; times two (=2 or =4) 6$: swi ; perform spaces .byte space ; function decb bne 6$ ; loop if more bra 4$ ; continue with next register 7$: sta ,s ; save delimiter in option ;* (always > 0) ldd *anumber ; obtain binary result tst -1,y ; ? two bytes worth bne 8$ ; branch yes lda ,-x ; setup for two 8$: std ,x ; store in new value lda ,s ; recover delimiter cmpa #cr ; ? end of changes bne 4$ ; no, keep on truck'n ;* move stacked data to new stack in case stack ;* pointer has changed 9$: leax tstack,pcr ; load temp area ldb #21 ; load count 10$: puls a ; next byte sta ,x+ ; store into temp decb ; count down bne 10$ ; loop if more lds -20,x ; load new stack pointer ldb #21 ; load count again 11$: lda ,-x ; next to store pshs a ; back onto new stack decb ; count down bne 11$ ; loop if more puls pc,y,x,a ; restore stack and return ;******************************************************** ;* bldnum - builds binary value from input hex ;* the active expression handler is used. ;* ;* input: s=return address ;* output: a=delimiter which terminated value ;* (if delm not zero) ;* "number"=word binary result ;* z=1 if input recieved, z=0 if no hex recieved ;* ;* registers are transparent ;******************************************************** ;* execute single or extended rom expression handler ;* ;* the flag "delim" is used as follows: ;* delim=0 no leading blanks, no forced terminator ;* delim=chr accept leading 'chr's, forced terminator bldnnb: clra ; no dynamic delimiter sta *delim ; store as delimiter jmp [vectab+.expan,pcr] ; to exp analyzer ;* build with leading blanks bldnum: lda #' ; allow leading blanks sta *delim ; store as delimiter jmp [vectab+.expan,pcr] ; to exp analyzer ;* this is the default single rom analyzer. we accept: ;* 1) hex input ;* 2) 'M' for last memory examine address ;* 3) 'P' for program counter address ;* 4) 'W' for window value ;* 5) '@' for indirect value exp1: pshs x,b ; save registers 1$: bsr bldhxi ; clear number, check first char beq 3$ ; if hex digit continue building ;* skip blanks if desired cmpa *delim ; ? correct delimiter beq 1$ ; yes, ignore it ;* test for m or p ldx *addr ; default for 'm' cmpa #'M ; ? memory examine addr wanted beq 5$ ; branch if so ldx *pcnter ; default for 'p' cmpa #'P ; ? last program counter wanted beq 5$ ; branch if so ldx *window ; default to window cmpa #'W ; ? window wanted beq 5$ 2$: puls pc,x,b ; return and restore registers ;* got hex, now continue building 3$: bsr bldhex ; compute next digit beq 3$ ; continue if more bra 6$ ; search for +/- ;* store value and check if need delimiter 4$: ldx ,x ; indirection desired 5$: stx *anumber ; store result tst *delim ; ? to force a delimiter beq 2$ ; return if not with value bsr read ; obtain next character ;* test for + or - 6$: ldx *anumber ; load last value cmpa #'+ ; ? add operator bne 8$ ; branch not bsr 10$ ; compute next term pshs a ; save delimiter ldd *anumber ; load new term 7$: leax d,x ; add to x stx *anumber ; store as new result puls a ; restore delimiter bra 6$ ; now test it 8$: cmpa #'- ; ? subtract operator beq 9$ ; branch if so cmpa #'@ ; ? indirection desired beq 4$ ; branch if so clrb ; set delimiter return bra 2$ ; and return to caller 9$: bsr 10$ ; obtain next term pshs a ; save delimiter ldd *anumber ; load up next term nega ; negate a negb ; negate b sbca #0 ; correct for a bra 7$ ; go add to expresion ;* compute next expression term ;* output: x=old value ;* 'number'=next term 10$: bsr bldnum ; obtain next value lbne cmdbad ; abort command if invalid rts ; return if valid number ;******************************************************** ;* build binary value using input characters. ;* ;* input: a=ascii hex value or delimiter ;* +0=return address ;* +2=16 bit result area ;* output: z=1 a=binary value ;* z=0 if invalid hex character (a unchanged) ;* ;* volatile: d ;******************************************************** bldhxi: clr *anumber ; clear number clr *anumber+1 ; clear number bldhex: bsr read ; get input character bldhxc: bsr cnvhex ; convert and test character bne cnvrts ; return if not a number ldb #16 ; prepare shift mul ; by four places lda #4 ; rotate binary into value 1$: aslb ; obtain next bit rol *anumber+1 ; into low byte rol *anumber ; into hi byte deca ; count down bne 1$ ; branch if more to do bra cnvok ; set good return code ;******************************************************** ;* convert ascii character to binary byte ;* ;* input: a=ascii ;* output: z=1 a=binary value ;* z=0 if invalid ;* ;* all registers transparent ;* (a unaltered if invalid hex) ;******************************************************** cnvhex: cmpa #'0 ; ? lower tigh hex blo cnvrts ; branch not value cmpa #'9 ; ? possible a-f ble cnvgot ; branch no to accept cmpa #'A ; ? less than ten blo cnvrts ; return if minus (invalid) cmpa #'F ; ? not too large bhi cnvrts ; no, return too large suba #7 ; down to binary cnvgot: anda #0x0f ; clear high byte cnvok: orcc #4 ; force zero on for valid hex cnvrts: rts ; return to caller ;* get input char, abort command if control-x (cancel) read: swi ; get next character .byte inchnp ; function cmpa #can ; ? abort command lbeq cmdbad ; branch to abort if so rts ; return to caller ;************ console - dumby routines cidta: clc ; never a character codta: ; dumby character out cion: ; input console initialization coon: ; output console initialization cioff: ; console input off cooff: ; console output off cirtn: rts ;************ pause - process pause routine cpause: jmp pauser ; go to default pause routine ;************ go - start program execution cgo: bsr goaddr ; build address if needed rti ; start executing ;* find optional new program counter. also arm the ;* breakpoints. goaddr: puls y,x ; pop return addresses from cmd and cgo pshs x ; restore return from cgo beq 1$ ; ? yes - use current pc ;* obtain new program counter lbsr cdnum ; obtain new program counter std 12,s ; store into stack 1$: ldx 12,s ; load program counter lbsr cbkldr ; obtain table neg *bkptct ; complement to show armed 2$: decb ; ? done bmi 5$ ; return when done lda [,y] ; load opcode sta -numbkp*2,y ; store into opcode table lda #0x3f ; ready "swi" opcode cmpx ,y ; starting at a breakpoint ? bne 4$ ; no - go set breakpoint cmpa [,y++] ; ? swi breakpointed bne 2$ ; no, skip setting of flag sta *swibfl ; show upcomming swi not brkpnt bra 2$ ; check others 4$: sta [,y++] ; store and move up table bra 2$ ; and continue 5$: rts ;************ call - call address as subroutine ccall: bsr goaddr ; fetch address if needed puls u,y,x,dp,d,cc ; restore users registers jsr [,s++] ; call user subroutine 1$: swi ; perform breakpoint .byte brkpt ; function bra 1$ ; loop until user changes pc ;************ memory - display/change memory ;* cmem and cmpadp are direct entry points from ;* the command handler for quick commands cmem: lbsr cdnum ; obtain address cmemn: std *addr ; store default 1$: ldx *addr ; load pointer lbsr zout2h ; send out hex value of byte lda #'- ; load delimiter swi ; send out .byte outch ; function 2$: lbsr bldnnb ; obtain new byte value beq 3$ ; branch if number ;* coma - skip byte cmpa #', ; ? comma bne 4$ ; branch not stx *addr ; update pointer leax 1,x ; to next byte bra 2$ ; and input it 3$: ldb *anumber+1 ; load low byte value bsr 13$ ; go overlay memory byte cmpa #', ; ? continue with no display beq 2$ ; branch yes ;* quoted string 4$: cmpa #'' ; ? quoted string bne 6$ ; branch no 5$: bsr read ; obtain next character cmpa #'' ; ? end of quoted string beq 7$ ; yes, quit string mode tfr a,b ; to b for subroutine bsr 13$ ; go update byte bra 5$ ; get next character ;* blank - next byte 6$: cmpa #0x20 ; ? blank for next byte bne 8$ ; branch not stx *addr ; update pointer 7$: swi ; give space .byte space ; function bra 1$ ;* dot - next byte with address 8$: cmpa #'. ; ? dot for next byte bne 9$ ; branch no swi ; force new line .byte pcrlf ; function stx *addr ; store next address bra cmpadp ; branch to show ;* up arrow - previous byte and address 9$: cmpa #'^ ; ? up arrow for previous byte bne 11$ ; branch not leax -2,x ; down to previous byte stx *addr ; store new pointer 10$: swi ; force new line .byte pcrlf ; function cmpadp=. bsr 12$ ; go print its value bra 1$ ; then prompt for input ;* slash - for current byte with address 11$: cmpa #'/ ; ? slash for current display beq 10$ ; yes, send address rts ; return from command ;* print current address 12$: ldx *addr ; load pointer value pshs x ; save x on stack leax ,s ; point to it for display swi ; display pointer in hex .byte out4hs ; function puls pc,x ; recover pointer and return ;* update byte 13$: ldx *addr ; load next byte pointer stb ,x+ ; store and increment x cmpb -1,x ; ? successfull store bne 14$ ; branch for '?' if not stx *addr ; store new pointer value rts ; back to caller 14$: pshs a ; save a register lda #'? ; show invalid swi ; send out .byte outch ; function puls pc,a ; return to caller ;************ window - set window value cwindo: bsr cdnum ; obtain window value std *window ; store it in rts ; end command ;************ display - high speed display memory cdi: bsr cdnum ; fetch address andb #0xf0 ; force to 16 boundry tfr d,y ; save in y leax 15,y ; default length bcs 1$ ; branch if end of input bsr cdnum ; obtain count leax d,y ; assume count, compute end addr 1$: pshs y,x ; setup parameters for hsdata cmpd 2,s ; ? was it count bls 2$ ; branch yes std ,s ; store high address 2$: jsr [vectab+.hsdta,pcr] ; call print routine puls pc,u,y ; clean stack and end command ;* obtain number - abort if none ;* only delimiters of cr, blank, or '/' are accepted ;* output: d=value, c=1 if carriage return delmiter, ;* else c=0 cdnum: lbsr bldnum ; obtain number lbne cmdbad ; branch if invalid cmpa #'/ ; ? valid delimiter lbhi cmdbad ; branch if not for error cmpa #cr+1 ; leave compare for carriage ret ldd *anumber ; load number rts ;************ punch - punch memory in s1-s9 format cpunch: bsr cdnum ; obtain start address tfr d,y ; save in y bsr cdnum ; obtain end address clr ,-s ; setup punch function code pshs y,d ; store values on stack ccalbs: jsr [vectab+.bson,pcr] ; initialize handler jsr [vectab+.bsdta,pcr] ; perform function pshs cc ; save return code jsr [vectab+.bsoff,pcr] ; turn off handler puls cc ; obtain condition code saved lbne cmdbad ; branch if error puls pc,y,x,a ; return from command ;************ load - load memory from s1-s9 format cload: bsr clvofs ; call setup and pass code .byte 1 ; load function code for packet clvofs: leau [,s++] ; load code in high byte of u leau [,u] ; not changing cc and restore s beq 1$ ; branch if carriage return next bsr cdnum ; obtain offset bra 2$ 1$: clra ; create zero offset clrb ; as default 2$: pshs u,dp,d ; setup code, null word, offset bra ccalbs ; enter call to bs routines ;************ verify - compare memory with files cver: bsr clvofs ; compute offset if any .byte -1 ; verify fnctn code for packet ;************ nulls - set new line and char padding cnulls: bsr cdnum ; obtain new line pad std *vectab+.pad ; reset values rts ; end command ;************ offset - compute short and long ;* branch offsets coffs: bsr cdnum ; obtain instruction address tfr d,x ; use as from address bsr cdnum ; obtain to address ;* d=to instruction, x=from instruction offset byte(s) leax 1,x ; adjust for *+2 short branch pshs y,x ; store work word and value on s subd ,s ; find offset std ,s ; save over stack leax 1,s ; point for one byte display sex ; sign extend low byte cmpa ,s ; ? valid one byte offset bne 1$ ; branch if not swi ; show one byte offset .byte out2hs ; function 1$: ldu ,s ; reload offset leau -1,u ; convert to long branch offset stu ,x ; store back where x points now swi ; show two byte offset .byte out4hs ; function swi ; force new line .byte pcrlf ; function puls pc,x,d ; restore stack and end command ;************ breakpoint - display/enter/delete/clear ;* breakpoints cbkpt: beq 5$ ; branch display of just 'b' lbsr bldnum ; attempt value entry beq 7$ ; branch to add if so cmpa #'- ; ? correct delimiter bne 9$ ; no, branch for error lbsr bldnum ; attempt delete value beq 2$ ; got one, go delete it clr *bkptct ; was 'b -', so zero count 1$: rts ; end command ;* delete the entry 2$: bsr 11$ ; setup registers and value 3$: decb ; ? any entries in table bmi 9$ ; branch no, error cmpx ,y++ ; ? is this the entry bne 3$ ; no, try next ;* found, now move others up in its place 4$: ldx ,y++ ; load next one up stx -4,y ; move down by one decb ; ? done bpl 4$ ; no, continue move dec *bkptct ; decrement breakpoint count 5$: bsr 11$ ; setup registers and load value beq 1$ ; return if none to delete 6$: leax ,y++ ; point to next entry swi ; display in hex .byte out4hs ; function decb ; count down bne 6$ ; loop if more to do swi ; skip to new line .byte pcrlf ; function rts ; return to end command ;* add new entry 7$: bsr 11$ ; setup registers cmpb #numbkp ; ? already full beq 9$ ; branch error if so lda ,x ; load byte to trap stb ,x ; try to change cmpb ,x ; ? changable ram bne 9$ ; branch error if not sta ,x ; restore byte 8$: decb ; count down bmi 10$ ; branch if done to add it cmpx ,y++ ; ? entry already here bne 8$ ; loop if not 9$: lbra cmdbad ; exit with error 10$: stx ,y ; add this entry clr -numbkp*2+1,y ; clear optional byte inc *bkptct ; add one to count bra 5$ ; and now display all of 'em ;* setup registers for scan 11$: ldx *anumber ; load value desired cbkldr: leay bkptbl,pcr ; load start of table ldb *bkptct ; load entry count rts ; return ;************ encode - encode a postbyte cencde: clr ,-s ; default to not indirect clrb ; zero postbyte value leax conv1,pcr ; start table search swi ; obtain first character .byte inchnp ; function cmpa #'[ ; ? indirect here bne 2$ ; branch if not lda #0x10 ; set indirect bit on sta ,s ; save for later 1$: swi ; obtain next character .byte inchnp ; function 2$: cmpa #cr ; ? end of entry beq 4$ ; branch yes 3$: tst ,x ; ? end of table lbmi cmdbad ; exit with error cmpa ,x++ ; ? this the character bne 3$ ; branch if not addb -1,x ; add this value bra 1$ ; get next input 4$: leax conv2,pcr ; point at table 2 tfr b,a ; save copy in a anda #0x60 ; isolate register mask ora ,s ; add in indirection bit sta ,s ; save back as postbyte skeleton andb #0x9f ; clear register bits 5$: tst ,x ; ? end of table lbeq cmdbad ; exit with error cmpb ,x++ ; ? same value bne 5$ ; loop if not ldb -1,x ; load result value orb ,s ; add to base skeleton stb ,s ; save postbyte on stack leax ,s ; point to it swi ; send out as hex .byte out2hs ; function swi ; to next line .byte pcrlf ; function puls pc,b ; end of command ;* table one defines valid input in sequence conv1: .byte 'A,0x04,'B,0x05,'D,0x06,'H,0x01 .byte 'H,0x01,'H,0x01,'H,0x00,',,0x00 .byte '-,0x09,'-,0x01,'S,0x70,'Y,0x30 .byte 'U,0x50,'X,0x10,'+,0x07,'+,0x01 .byte 'P,0x80,'C,0x00,'R,0x00,'],0x00 .byte 0xff ; end of table ;*conv2 uses above conversion to set postbyte ;* bit skeleton. conv2: .word 0x1084,0x1100 ; R, H,R .word 0x1288,0x1389 ; HH,R HHHH,R .word 0x1486,0x1585 ; A,R B,R .word 0x168b,0x1780 ; D,R ,R+ .word 0x1881,0x1982 ; ,R++ ,-R .word 0x1a83,0x828c ; ,--R HH,pcr .word 0x838d,0x039f ; HHHH,pcr [HHHH] .byte 0 ; end of table ;**************************************************** ;* default interrupt transfers * ;**************************************************** rsrvd: jmp [vectab+.rsvd,pcr] ; reserved vector swi3: jmp [vectab+.swi3,pcr] ; swi3 vector swi2: jmp [vectab+.swi2,pcr] ; swi2 vector firq: jmp [vectab+.firq,pcr] ; firq vector irq: jmp [vectab+.irq,pcr] ; irq vector swi: jmp [vectab+.swi,pcr] ; swi vector nmi: jmp [vectab+.nmi,pcr] ; nmi vector .page .sbttl Hardware Interrupt Tables ;******************************************************** ;* assist09 hardware vector table ;* ;* this table is used if the assist09 rom addresses ;* the mc6809 hardware vectors. ;******************************************************** .= bldvtr+0d2048-0d16 ; assume 2K ROM .word rsrvd ; reserved slot .word swi3 ; software interrupt 3 .word swi2 ; software interrupt 2 .word firq ; fast interrupt request .word irq ; interrupt request .word swi ; software interrupt .word nmi ; non-maskable interrupt .word reset ; restart