;* buffalo ;* "bit user's fast friendly aid to logical operation" ;* ;* rev 2.0 - 4/23/85 - added disassembler. ;* - variables now ptrn and tmpn. ;* rev 2.1 - 4/29/85 - added byte erase to chgbyt routine. ;* rev 2.2 - 5/16/85 - added hooks for evb board - acia ;* drivers, init and host routines. ;* 7/8/85 - fixed dump wraparound problem. ;* 7/10/85 - added evm board commands. ;* - added fill instruction. ;* 7/18/85 - added jump to eeprom. ;* rev 2.3 - 8/22/85 - call targco to disconnect sci from host ;* in reset routine for evb board. ;* 10/3/85 - modified load for download through terminal. ;* rev 2.4 - 7/1/86 - changed dflop address to fix conflicts with ;* eeprom. (was at a000) ;* rev 2.5 - 9/8/86 - modified to provide additional protection from ;* program run-away on power down. also fixed bugs ;* in mm and move. changed to 1 stop bit from 2. ;* ;******************************************************** ;* although the information contained herein, * ;* as well as any information provided relative * ;* thereto, has been carefully reviewed and is * ;* believed accurate, motorola assumes no * ;* liability arising out of its application or * ;* use, neither does it convey any license under * ;* its patent rights nor the rights of others. * ;******************************************************** .area BUF25 (ABS,OVR) .setdp ;************************ ;* equates * ;************************ rambs = 0x0000 ; start of ram regbs = 0x1000 ; start of registers rombs = 0xe000 ; start of rom porte = regbs+0x0a ; port e tcnt = regbs+0x0e ; timer count toc5 = regbs+0x1e ; oc5 reg tctl1 = regbs+0x20 ; timer control 1 tmsk1 = regbs+0x22 ; timer mask 1 tflg1 = regbs+0x23 ; timer flag 1 tmsk2 = regbs+0x24 ; timer mask 2 baud = regbs+0x2b ; sci baud reg sccr1 = regbs+0x2c ; sci control1 reg sccr2 = regbs+0x2d ; sci control2 reg scsr = regbs+0x2e ; sci status reg scdat = regbs+0x2f ; sci data reg option = regbs+0x39 ; option reg coprst = regbs+0x3a ; cop reset reg pprog = regbs+0x3b ; ee prog reg hprio = regbs+0x3c ; hprio reg config = regbs+0x3f ; config register dflop = 0x4000 ; evb d flip flop duart = 0xd000 ; duart address porta = duart portb = duart+8 acia = 0x9800 ; acia address prompt = '> bufflng = 35 ctla = 0x01 ; exit host or assembler ctlb = 0x02 ; send break to host ctlw = 0x17 ; wait ctlx = 0x18 ; abort del = 0x7f ; abort eot = 0x04 ; end of text/table swi = 0x3f ;*************** ;* ram * ;*************** .org 0x36 ;*** buffalo ram space *** .blkb 20 ; user stack area ustack: .blkb 30 ; monitor stack area stack: .blkb 1 inbuff: .blkb bufflng ; input buffer endbuff = . combuff: .blkb 8 ; command buffer shftreg: .blkb 2 ; input shift register brktabl: .blkb 8 ; breakpoint table regs: .blkb 9 ; user's pc,y,x,a,b,c sp: .blkb 2 ; user's sp autolf: .blkb 1 ; auto lf flag for i/o iodev: .blkb 1 ; 0=sci, 1=acia, 2=duarta, 3=duartb extdev: .blkb 1 ; 0=none, 1=acia, 2=duart, hostdev: .blkb 1 ; 0=sci, 1=acia, 3=duartb count: .blkb 1 ; # characters read ptrmem: .blkb 2 ; current memory location ;*** buffalo variables - used by: *** ptr0: .blkb 2 ; main,readbuff,incbuff,as ptr1: .blkb 2 ; main,br,du,mo,as ptr2: .blkb 2 ; du,go,mo,as ptr3: .blkb 2 ; ho,mo,as ptr4: .blkb 2 ; go,as ptr5: .blkb 2 ; as ptr6: .blkb 2 ; go,as ptr7: .blkb 2 ; go,as tmp1: .blkb 1 ; main,hexbin,buffarg,termarg tmp2: .blkb 1 ; go,ho,as tmp3: .blkb 1 ; as tmp4: .blkb 1 ; go,ho,me,as ;*** vector jump table *** jsci: .blkb 3 jspi: .blkb 3 jpaie: .blkb 3 jpao: .blkb 3 jtof: .blkb 3 jtoc5: .blkb 3 jtoc4: .blkb 3 jtoc3: .blkb 3 jtoc2: .blkb 3 jtoc1: .blkb 3 jtic3: .blkb 3 jtic2: .blkb 3 jtic1: .blkb 3 jrti: .blkb 3 jirq: .blkb 3 jxirq: .blkb 3 jswi: .blkb 3 jillop: .blkb 3 jcop: .blkb 3 jclm: .blkb 3 ;***************** ;* ;* rom starts here * ;* ;***************** .org rombs ;***************** ;** buffalo - this is where buffalo starts ;** out of reset. all initialization is done ;** here including determination of where the ;** user terminal is (sci,acia, or duart). ;***************** buffalo: ldx #porte brclr 0,x,#0x01,bufisit ; if bit 0 of port e is 1 jmp 0xb600 ; then jump to the start of eeprom bufisit: ldaa #0x93 staa option ; adpu, dly, irqe, cop ldaa #0x00 staa tmsk2 ; timer pre = %1 for trace lds #stack ; monitor stack pointer jsr vecinit ldx #ustack stx *sp ; default user stack ldaa #0xd0 staa *regs+8 ; default user ccr ldd #0x3f0d ; initial command is ? std *inbuff jsr bpclr ; clear breakpoints clr *autolf inc *autolf ; auto cr/lf = on ;* determine type of external comm device - none, or acia * clr *extdev ; default is none ldaa hprio anda #0x20 beq buff2 ; jump if single chip mode ldaa #0x03 ; see if external acia exists staa acia ; master reset ldaa acia anda #0x7f ; mask irq bit from status register bne buff1 ; jump if status reg not 0 ldaa #0x12 staa acia ; turn on acia ldaa acia anda #0x02 beq buff1 ; jump if tdre not set ldaa #0x01 staa *extdev ; external device is acia bra buff2 buff1 = . ; see if duart exists ldaa duart+0x0c ; read irq vector register cmpa #0x0f ; should be out of reset bne buff2 ldaa #0xaa staa duart+0x0c ; write irq vector register ldaa duart+0x0c ; read irq vector register cmpa #0xaa bne buff2 ldaa #0x02 staa *extdev ; external device is duart a ;* find terminal port - sci or external. * buff2: clr *iodev jsr targco ; disconnect sci for evb board jsr signon ; initialize sci ldaa *extdev beq buff3 ; jump if no external device staa *iodev jsr signon ; initialize external device buff3: clr *iodev jsr input ; get input from sci port cmpa #0x0d beq buff4 ; jump if cr - sci is terminal port ldaa *extdev beq buff3 ; jump if no external device staa *iodev jsr input ; get input from external device cmpa #0x0d beq buff4 ; jump if cr - terminal found ext bra buff3 signon: jsr init ; initialize device ldx #msg1 ; buffalo message jsr outstrg rts ;* determine where host port should be. buff4: clr *hostdev ; default - host = sci port ldaa *iodev cmpa #0x01 beq buff5 ; default host if term = acia ldaa #0x03 staa *hostdev ; else host is duart port b buff5 = . ;***************** ;** main - this module reads the user's input into ;** a buffer called inbuff. the first field (assumed ;** to be the command field) is then parsed into a ;** second buffer called combuff. the command table ;** is then searched for the contents of combuff and ;** if found, the address of the corresponding task ;** routine is fetched from the command table. the ;** task is then called as a subroutine so that ;** control returns back to here upon completion of ;** the task. buffalo expects the following format ;** for commands: ;** [...] ;** [] implies contents optional. ;** means whitespace character (space,comma,tab). ;** = command string of 1-8 characters. ;** = argument particular to the command. ;** = carriage return signifying end of input string. ;***************** ;* prompt user ;*do ;* a=input(); ;* if(a==(cntlx or del)) continue; ;* elseif(a==backspace) ;* b--; ;* if(b<0) b=0; ;* else ;* if(a==cr && buffer empty) ;* repeat last command; ;* else put a into buffer; ;* check if buffer full; ;*while(a != (cr or /) main: lds #stack ; initialize sp every time clr *autolf inc *autolf ; auto cr/lf = on jsr outcrlf ldaa #prompt ; prompt user jsr output clrb main1: jsr inchar ; read terminal ldx #inbuff abx ; pointer into buffer cmpa #ctlx beq main ; jump if cntl x cmpa #del beq main ; jump if del cmpa #0x08 bne main2 ; jump if not bckspc decb blt main ; jump if buffer empty bra main1 main2: cmpa #0xd bne main3 ; jump if not cr tstb beq comm0 ; jump if buffer empty staa ,x ; put a in buffer bra comm0 main3: staa ,x ; put a in buffer incb cmpb #bufflng ble main4 ; jump if not long ldx #msg3 ; "long" jsr outstrg bra main main4: cmpa #'/ bne main1 ; jump if not "/" ;* ******************* ;***************** ;* parse out and evaluate the command field. ;***************** ;*initialize comm0 = . clr *tmp1 ; enable "/" command clr *shftreg clr *shftreg+1 clrb ldx #inbuff ; ptrbuff[] = inbuff[] stx *ptr0 jsr wskip ; find first char ;*while((a=readbuff) != (cr or wspace)) ;* upcase(a); ;* buffptr[b] = a ;* b++ ;* if (b > 8) error(too long); ;* if(a == "/") ;* if(enabled) mslash(); ;* else error(command?); ;* else hexbin(a); comm1 = . jsr readbuff ; read from buffer ldx #combuff abx jsr upcase ; convert to upper case staa ,x ; put in command buffer cmpa #0x0d beq srch ; jump if cr jsr wchek beq srch ; jump if wspac jsr incbuff ; move buffer pointer incb cmpb #0x8 ble comm2 ldx #msg3 ; "long" jsr outstrg jmp main comm2 = . cmpa #'/ bne comm4 ; jump if not "/" tst *tmp1 bne comm3 ; jump if not enabled stab *count ldx #mslash jmp exec ; execute "/" comm3: ldx #msg8 ; "command?" jsr outstrg jmp main comm4 = . jsr hexbin bra comm1 ;***************** ;* search tables for command. at this point, ;* combuff holds the command field to be executed, ;* and b = # of characters in the command field. ;* the command table holds the whole command name ;* but only the first n characters of the command ;* must match what is in combuff where n is the ;* number of characters entered by the user. ;***************** ;*count = b; ;*ptr1 = comtabl; ;*while(ptr1[0] != end of table) ;* ptr1 = next entry ;* for(b=1; b=count; b++) ;* if(ptr1[b] == combuff[b]) continue; ;* else error(not found); ;* execute task; ;* return(); ;*return(command not found); srch: stab *count ; size of command entered ldx #comtabl ; pointer to table stx *ptr1 ; pointer to next entry srch1: ldx *ptr1 ldy #combuff ; pointer to command buffer ldab 0,x cmpb #0xff bne srch2 ldx #msg2 ; "command not found" jsr outstrg jmp main srch2: pshx ; compute next table entry addb #0x3 abx stx *ptr1 pulx clrb srchlp: incb ; match characters loop ldaa 1,x ; read table cmpa 0,y ; compare to combuff bne srch1 ; try next entry inx ; move pointers iny cmpb *count blt srchlp ; loop countu1 times ldx *ptr1 dex dex ldx 0,x ; jump address from table exec: jsr 0,x ; call task as subroutine jmp main ;* ;***************** ;* utility subroutines - these routines ;* are called by any of the task routines. ;***************** ;***************** ;* upcase(a) - if the contents of a is alpha, ;* returns a converted to uppercase. ;***************** upcase: cmpa #'a blt upcase1 ; jump if < a cmpa #'z bgt upcase1 ; jump if > z suba #0x20 ; convert upcase1: rts ;***************** ;* bpclr() - clear all entries in the ;* table of breakpoints. ;***************** bpclr: ldx #brktabl ldab #8 bpclr1: clr 0,x inx decb bgt bpclr1 ; loop 8 times rts ;***************** ;* rprnt1(x) - prints name and contents of a single ;* user register. on entry x points to name of register ;* in reglist. on exit, a=register name. ;***************** reglist: .ascii 'PYXABCS' ; names .byte 0,2,4,6,7,8,9 ; offset .byte 1,1,1,0,0,0,1 ; size rprnt1: ldaa 0,x psha pshx jsr output ; name ldaa #'- jsr output ; dash ldab 7,x ; contents offset ldaa 14,x ; bytesize ldx #regs ; address abx tsta beq rprn2 ; jump if 1 byte jsr out1byt ; 2 bytes rprn2: jsr out1bsp pulx pula rts ;***************** ;* rprint() - print the name and contents ;* of all the user registers. ;***************** rprint: pshx ldx #reglist rpri1: jsr rprnt1 ; print name inx cmpa #'S ; s is last register bne rpri1 ; jump if not done pulx rts ;***************** ;* hexbin(a) - convert the ascii character in a ;* to binary and shift into shftreg. returns value ;* in tmp1 incremented if a is not hex. ;***************** hexbin: psha pshb pshx jsr upcase ; convert to upper case cmpa #'0 blt hexnot ; jump if a < 0x30 cmpa #'9 ble hexnmb ; jump if 0-9 cmpa #'A blt hexnot ; jump if 0x39> a <0x41 cmpa #'F bgt hexnot ; jump if a > 0x46 adda #0x9 ; convert 0xa-0xf hexnmb: anda #0x0f ; convert to binary ldx #shftreg ldab #4 hexshft: asl 1,x ; 2 byte shift through rol 0,x ; carry bit decb bgt hexshft ; shift 4 times oraa 1,x staa 1,x bra hexrts hexnot: inc *tmp1 ; indicate not hex hexrts: pulx pulb pula rts ;***************** ;* buffarg() - build a hex argument from the ;* contents of the input buffer. characters are ;* converted to binary and shifted into shftreg ;* until a non-hex character is found. on exit ;* shftreg holds the last four digits read, count ;* holds the number of digits read, ptrbuff points ;* to the first non-hex character read, and a holds ;* that first non-hex character. ;***************** ;*initialize ;*while((a=readbuff()) not hex) ;* hexbin(a); ;*return(); buffarg: clr *tmp1 ; not hex indicator clr *count ; # or digits clr *shftreg clr *shftreg+1 jsr wskip bufflp: jsr readbuff ; read char jsr hexbin tst *tmp1 bne buffrts ; jump if not hex inc *count jsr incbuff ; move buffer pointer bra bufflp buffrts: rts ;***************** ;* termarg() - build a hex argument from the ;* terminal. characters are converted to binary ;* and shifted into shftreg until a non-hex character ;* is found. on exit shftreg holds the last four ;* digits read, count holds the number of digits ;* read, and a holds the first non-hex character. ;***************** ;*initialize ;*while((a=inchar()) == hex) ;* if(a = cntlx or del) ;* abort; ;* else ;* hexbin(a); countu1++; ;*return(); termarg: clr *count clr *shftreg clr *shftreg+1 term0: jsr inchar cmpa #ctlx beq term1 ; jump if controlx cmpa #del bne term2 ; jump if not delete term1: jmp main ; abort term2: clr *tmp1 ; hex indicator jsr hexbin tst *tmp1 bne term3 ; jump if not hex inc *count bra term0 term3: rts ;***************** ;* chgbyt() - if shftreg is not empty, put ;* contents of shftreg at address in x. if x ;* is an address in eeprom then program it. ;***************** ;*if(count != 0) ;* (x) = a; ;* if(((x) != a) && (x == eeprom location)) ;* if((x) != 0xff) byte erase (x); ;* if(a != 0xff) program(x) = a); ;* if((x) != a) error(rom) ;*return; chgbyt: tst *count beq chgbyt4 ; jump if shftreg empty ldaa *shftreg+1 staa 0,x ; attempt to write ldaa 0,x cmpa *shftreg+1 beq chgbyt3 ; jump if it worked cpx #config beq chgbyt1 ; jump if config reg cpx #0xb600 blo chgbyt3 ; jump if not ee cpx #0xb7ff bhi chgbyt3 ; jump if not ee chgbyt1 = . ldaa 0,x cmpa #0xff beq chgbyt2 ; jump if already erased ldaa #0x16 ; do byte erase staa pprog ldaa #0xff staa 0,x ldaa #0x17 bne acl1 clra ; fail safe acl1: staa pprog bsr chgwait ldaa #0x00 staa pprog ; end of byte erase chgbyt2 = . ldaa *shftreg+1 cmpa #0xff beq chgbyt3 ; jump if no need to program ldaa #0x02 ; do byte program staa pprog ldaa *shftreg+1 staa 0,x ldaa #0x03 bne acl2 clra ; fail safe acl2: staa pprog bsr chgwait ldaa #0x00 staa pprog ; end of byte program chgbyt3 = . ldaa ,x cmpa *shftreg+1 beq chgbyt4 pshx ldx #msg6 ; "rom" jsr outstrg jsr outcrlf pulx chgbyt4 = . rts chgwait = . ; delay 10 ms at E = 2mhz pshx ldx #0x0d06 chgwait1: dex bne chgwait1 pulx rts ;***************** ;* readbuff() - read the character in inbuff ;* pointed at by ptrbuff into a. returns ptrbuff ;* unchanged. ;***************** readbuff: pshx ldx *ptr0 ldaa 0,x pulx rts ;***************** ;* incbuff(), decbuff() - increment or decrement ;* ptrbuff. ;***************** incbuff: pshx ldx *ptr0 inx bra incdec decbuff: pshx ldx *ptr0 dex incdec: stx *ptr0 pulx rts ;***************** ;* wskip() - read from the inbuff until a ;* non whitespace (space, comma, tab) character ;* is found. returns ptrbuff pointing to the ;* first non-whitespace character and a holds ;* that character. ;***************** wskip: jsr readbuff ; read character jsr wchek bne wskip1 ; jump if not wspc jsr incbuff ; move pointer bra wskip ; loop wskip1: rts ;***************** ;* wchek(a) - returns z=1 if a holds a ;* whitespace character, else z=0. ;***************** wchek: cmpa #0x2c ; comma beq wchek1 cmpa #0x20 ; space beq wchek1 cmpa #0x09 ; tab wchek1: rts ;***************** ;* dchek(a) - returns z=1 if a = whitespace ;* or carriage return. else returns z=0. ;***************** dchek: jsr wchek beq dchek1 ; jump if whitespace cmpa #0x0d dchek1: rts ;***************** ;* chkabrt() - checks for a control x or delete ;* from the terminal. if found, the stack is ;* reset and the control is transferred to main. ;* note that this is an abnormal termination. ;* if the input from the terminal is a control w ;* then this routine keeps waiting until any other ;* character is read. ;***************** ;*a=input(); ;*if(a=cntl w) wait until any other key; ;*if(a = cntl x or del) abort; chkabrt: jsr input beq chk4 ; jump if no input cmpa #ctlw bne chk2 ; jump in not cntlw chkabrt1: jsr input beq chkabrt1 ; jump if no input chk2: cmpa #del beq chk3 ; jump if delete cmpa #ctlx beq chk3 ; jump if control x cmpa #ctla bne chk4 ; jump not control a chk3: jmp main ; abort chk4: rts ; return ;*********************** ;* hostco - connect sci to host for evb board. ;* targco - connect sci to target for evb board. ;*********************** hostco: psha ldaa #0x01 staa dflop ; send 1 to d-flop pula rts targco: psha ldaa #0x00 staa dflop ; send 0 to d-flop pula rts ;* ;********** ;* ;* vecinit - this routine checks for ;* vectors in the ram table. all ;* uninitialized vectors are programmed ;* to jmp stopit ;* ;********** ;* vecinit: ldx #jsci ; point to first ram vector ldy #stopit ; pointer to stopit routine ldd #0x7e03 ; a=jmp opcode; b=offset vecloop: cmpa 0,x beq vecnext ; if vector already in staa 0,x ; install jmp sty 1,x ; to stopit routine vecnext: abx ; add 3 to point at next vector cpx #jclm+3 ; done? bne vecloop ; if not, continue loop rts ;* stopit: ldaa #0x50 ; stop-enable; irq, xirq-off tap stop ; you are lost! shut down jmp stopit ; in case continue by xirq ;********** ;* ;* i/o module ;* communications with the outside world. ;* 3 i/o routines (init, input, and output) call ;* drivers specified by iodev (0=sci, 1=acia, ;* 2=duarta, 3=duartb). ;* ;********** ;* init() - initialize device specified by iodev. ;********* ;* init = . psha ; save registers pshx ldaa *iodev cmpa #0x00 bne init1 ; jump not sci jsr onsci ; initialize sci bra init4 init1: cmpa #0x01 bne init2 ; jump not acia jsr onacia ; initialize acia bra init4 init2: ldx #porta cmpa #0x02 beq init3 ; jump duart a ldx #portb init3: jsr onuart ; initialize duart init4: pulx ; restore registers pula rts ;********** ;* input() - read device. returns a=char or 0. ;* this routine also disarms the cop. ;********** input = . pshx ldaa #0x55 ; reset cop staa coprst ldaa #0xaa staa coprst ldaa *iodev bne input1 ; jump not sci jsr insci ; read sci bra input4 input1: cmpa #0x01 bne input2 ; jump not acia jsr inacia ; read acia bra input4 input2: ldx #porta cmpa #0x02 beq input3 ; jump if duart a ldx #portb input3: jsr inuart ; read uart input4: pulx rts ;********** ;* output() - output character in a. ;********** output = . psha ; save registers pshb pshx ldab *iodev bne output1 ; jump not sci jsr outsci ; write sci bra output4 output1: cmpb #0x01 bne output4 ; jump not acia jsr outacia ; write acia bra output4 output2: ldx #porta cmpb #0x02 beq output3 ; jump if duart a ldx #portb output3: jsr outuart ; write uart output4: pulx pulb pula rts ;********** ;* onuart(port) - initialize a duart port. ;* sets duart to internal clock, divide by 16, ;* 8 data + 1 stop bits. ;********** onuart: ldaa #0x22 staa 2,x ; reset receiver ldaa #0x38 staa 2,x ; reset transmitter ldaa #0x40 staa 2,x ; reset error status ldaa #0x10 staa 2,x ; reset pointer ldaa #0x00 staa duart+4 ; clock source ldaa #0x00 staa duart+5 ; interrupt mask ldaa #0x13 staa 0,x ; 8 data, no parity ldaa #0x07 staa 0,x ; 1 stop bits ldaa #0xbb ; baud rate (9600) staa 1,x ; tx and rcv baud rate ldaa #0x05 staa 2,x ; enable tx and rcv rts ;********** ;* inuart(port) - check duart for any input. ;********** inuart: ldaa 1,x ; read status anda #0x01 ; check rdrf beq inuart1 ; jump if no data ldaa 3,x ; read data anda #0x7f ; to mask parity inuart1: rts ;********** ;* outuart(port) - output the character in a. ;* if autolf=1, transmits cr or lf as crlf. ;********** outuart: tst *autolf beq outuart2 ; jump if no autolf bsr outuart2 cmpa #0x0d bne outuart1 ldaa #0x0a ; if cr, output lf bra outuart2 outuart1: cmpa #0x0a bne outuart3 ldaa #0x0d ; if lf, output cr outuart2: ldab 1,x ; check status andb #0x4 beq outuart2 ; loop until tdre=1 anda #0x7f ; mask parity staa 3,x ; send character outuart3: rts ;********** ;* onsci() - initialize the sci for 9600 ;* baud at 8 mhz extal. ;********** onsci: ldaa #0x30 staa baud ; baud register ldaa #0x00 staa sccr1 ldaa #0x0c staa sccr2 ; enable rts ;********** ;* insci() - read from sci. return a=char or 0. ;********** insci: ldaa scsr ; read status reg anda #0x20 beq insci1 ; jump if rdrf=0 ldaa scdat ; read data register anda #0x7f ; mask parity insci1: rts ;********** ;* outsci() - output a to sci. if autolf = 1, ;* cr and lf sent as crlf. ;********** outsci: tst *autolf beq outsci2 ; jump if autolf=0 bsr outsci2 cmpa #0x0d bne outsci1 ldaa #0x0a ; if cr, send lf bra outsci2 outsci1: cmpa #0x0a bne outsci3 ldaa #0x0d ; if lf, send cr outsci2: ldab scsr ; read status bitb #0x80 beq outsci2 ; loop until tdre=1 anda #0x7f ; mask parity staa scdat ; send character outsci3: rts ;********** ;* onacia - initialize the acia for ;* 8 data bits, 1 stop bit, divide by 64 clock. ;********** onacia: ldx #acia ldaa #0x03 staa 0,x ; master reset ldaa #0x16 staa 0,x ; setup rts ;********** ;* inacia - read from the acia, return a=char or 0. ;********** inacia: ldx #acia ldaa 0,x ; status psha anda #0x70 ; check pe, ov, fe pula beq inacia1 ; jump - no error bsr onacia ; reinitialize and try again bra inacia inacia1: lsra ; check rdrf bcs inacia2 ; jump if data clra ; return(no data) rts inacia2: ldaa 1,x ; read data anda #0x7f ; mask parity rts ;********** ;* outacia - output a to acia. if autolf = 1, ;* cr or lf sent as crlf. ;********** outacia: bsr outacia3 ; output char tst *autolf beq outacia2 ; jump no autolf cmpa #0x0d bne outacia1 ldaa #0x0a bsr outacia3 ; if cr, output lf bra outacia2 outacia1: cmpa #0x0a bne outacia2 ldaa #0x0d bsr outacia3 ; if lf, output cr outacia2: rts outacia3: ldx #acia ldab 0,x bitb #0x2 beq outacia3 ; loop until tdre anda #0x7f ; mask parity staa 1,x ; output rts ;* ;* space for modifying outacia routine ;* .word 0xffff,0xffff,0xffff,0xffff ;******************************* ;*** i/o utility subroutines *** ;***these subroutines perform the neccesary ;* data i/o operations. ;* outlhlf-convert left 4 bits of a from binary ;* to ascii and output. ;* outrhlf-convert right 4 bits of a from binary ;* to ascii and output. ;* out1byt-convert byte addresed by x from binary ;* to ascii and output. ;* out1bsp-convert byte addressed by x from binary ;* to ascii and output followed by a space. ;* out2bsp-convert 2 bytes addressed by x from binary ;* to ascii and output followed by a space. ;* outspac-output a space. ;* ;* outcrlf-output a line feed and carriage return. ;* ;* outstrg-output the string of ascii bytes addressed ;* by x until 0x04. ;* outa-output the ascii character in a. ;* ;* inchar-input to a and echo one character. loops ;* until character read. ;******************** ;********** ;* outrhlf(), outlhlf(), outa() ;*convert a from binary to ascii and output. ;*contents of a are destroyed.. ;********** outlhlf: lsra ; shift data to right lsra lsra lsra outrhlf: anda #0x0f ; mask top half adda #0x30 ; convert to ascii cmpa #0x39 ble outa ; jump if 0-9 adda #0x07 ; convert to hex a-f outa: jsr output ; output character rts ;********** ;* out1byt(x) - convert the byte at x to two ;* ascii characters and output. return x pointing ;* to next byte. ;********** out1byt: psha ldaa 0,x ; get data in a psha ; save copy bsr outlhlf ; output left half pula ; retrieve copy bsr outrhlf ; output right half pula inx rts ;********** ;* out1bsp(x), out2bsp(x) - output 1 or 2 bytes ;* at x followed by a space. returns x pointing to ;* next byte. ;********** out2bsp: jsr out1byt ; do first byte out1bsp: jsr out1byt ; do next byte outspac: ldaa #0x20 ; output a space jsr output rts ;********** ;* outcrlf() - output a carriage return and ;* a line feed. returns a = cr. ;********** outcrlf: ldaa #0x0d ; cr jsr output ; output a ldaa #0x00 jsr output ; output padding ldaa #0x0d rts ;********** ;* outstrg(x) - output string of ascii bytes ;* starting at x until end of text (0x04). can ;* be paused by control w (any char restarts). ;********** outstrg: jsr outcrlf outstrg0: psha outstrg1: ldaa 0,x ; read char into a cmpa #eot beq outstrg3 ; jump if eot jsr output ; output character inx jsr input beq outstrg1 ; jump if no input cmpa #ctlw bne outstrg1 ; jump if not cntlw outstrg2: jsr input beq outstrg2 ; jump if any input bra outstrg1 outstrg3: pula rts ;********** ;* inchar() - reads input until character sent. ;* echoes char and returns with a = char. inchar: jsr input tsta beq inchar ; jump if no input jsr output ; echo rts ;********************* ;*** command table *** comtabl = . .byte 5 .ascii 'ASSEM' .word #assem .byte 5 .ascii 'BREAK' .word #break .byte 4 .ascii 'BULK' .word #bulk .byte 7 .ascii 'BULKALL' .word #bulkall .byte 4 .ascii 'CALL' .word #call .byte 4 .ascii 'DUMP' .word #dump .byte 4 .ascii 'FILL' .word #fill .byte 2 .ascii 'GO' .word #go .byte 4 .ascii 'HELP' .word #help .byte 4 .ascii 'HOST' .word #host .byte 4 .ascii 'LOAD' .word #load .byte 6 ; length of command .ascii 'MEMORY' ; ascii command .word #memory ; command address .byte 4 .ascii 'MOVE' .word #move .byte 7 .ascii 'PROCEED' .word #proceed .byte 8 .ascii 'REGISTER' .word #register .byte 5 .ascii 'TRACE' .word #trace .byte 6 .ascii 'VERIFY' .word #verify .byte 1 .ascii '?' ; initial command .word #help .byte 5 .ascii 'XBOOT' .word #boot ;* ;*** command names for evm compatability *** ;* .byte 3 .ascii 'ASM' .word #assem .byte 2 .ascii 'BF' .word #fill .byte 4 .ascii 'COPY' .word #move .byte 5 .ascii 'ERASE' .word #bulk .byte 2 .ascii 'MD' .word #dump .byte 2 .ascii 'MM' .word #memory .byte 2 .ascii 'RD' .word #register .byte 2 .ascii 'RM' .word #register .byte 4 .ascii 'READ' .word #move .byte 2 .ascii 'TM' .word #host .byte 4 .ascii 'TEST' .word #evbtest .byte -1 ;******************* ;*** text tables *** msg1: .ascii 'BUFFALO 2.5 (ext) - ' .ascii 'Bit User Fast Friendly Aid to Logical Operation' .byte eot msg2: .ascii 'What?' .byte eot msg3: .ascii 'Too Long' .byte eot msg4: .ascii 'Full' .byte eot msg5: .ascii 'Op- ' .byte eot msg6: .ascii 'rom-' .byte eot msg8: .ascii 'Command?' .byte eot msg9: .ascii 'Bad argument' .byte eot msg10: .ascii 'No host port available' .byte eot msg11: .ascii 'done' .byte eot msg12: .ascii 'checksum error' .byte eot msg13: .ascii 'error addr ' .byte eot ;********** ;* break [-][] . . . ;* modifies the breakpoint table. more than ;* one argument can be entered on the command ;* line but the table will hold only 4 entries. ;* 4 types of arguments are implied above: ;* break prints table contents. ;* break inserts . ;* break - deletes . ;* break - clears all entries. ;********** ;* while 1 ;* a = wskip(); ;* switch(a) ;* case(cr): ;* bprint(); return; break: jsr wskip cmpa #0x0d bne brkdel ; jump if not cr jsr bprint ; print table rts ;* case("-"): ;* incbuff(); readbuff(); ;* if(dchek(a)) /* look for wspac or cr */ ;* bpclr(); ;* breaksw; ;* a = buffarg(); ;* if( !dchek(a) ) return(bad argument); ;* b = bpsrch(); ;* if(b >= 0) ;* brktabl[b] = 0; ;* breaksw; brkdel: cmpa #'- bne brkdef ; jump if not - jsr incbuff jsr readbuff jsr dchek bne brkdel1 ; jump if not delimeter jsr bpclr ; clear table jmp break ; do next argument brkdel1: jsr buffarg ; get address to delete jsr dchek beq brkdel2 ; jump if delimeter ldx #msg9 ; "bad argument" jsr outstrg rts brkdel2: jsr bpsrch ; look for addr in table tstb bmi brkdel3 ; jump if not found ldx #brktabl abx clr 0,x ; clear entry clr 1,x brkdel3: jmp break ; do next argument ;* default: ;* a = buffarg(); ;* if( !dchek(a) ) return(bad argument); ;* b = bpsrch(); ;* if(b < 0) /* not already in table */ ;* x = shftreg; ;* shftreg = 0; ;* a = x[0]; x[0] = 0x3f ;* b = x[0]; x[0] = a; ;* if(b != 0x3f) return(rom); ;* b = bpsrch(); /* look for hole */ ;* if(b >= 0) return(table full); ;* brktabl[b] = x; ;* breaksw; brkdef: jsr buffarg ; get argument jsr dchek beq brkdef1 ; jump if delimiter ldx #msg9 ; "bad argument" jsr outstrg rts brkdef1: jsr bpsrch ; look for entry in table tstb bge break ; jump if already in table ldx *shftreg ; x = new entry ldaa 0,x ldab #swi stab 0,x ldab 0,x staa 0,x cmpb #swi beq brkdef2 ; jump if writes ok stx *ptr1 ; save address ldx #msg6 ; "rom-" jsr outstrg ldx #ptr1 jsr out2bsp ; print address jsr bprint rts brkdef2: clr *shftreg clr *shftreg+1 pshx jsr bpsrch ; look for 0 entry pulx tstb bpl brkdef3 ; jump if table not full ldx #msg4 ; "full" jsr outstrg jsr bprint rts brkdef3: ldy #brktabl aby stx 0,y ; put new entry in jmp break ; do next argument ;********** ;* bprint() - print the contents of the table. ;********** bprint: jsr outcrlf ldx #brktabl ldab #4 bprint1: jsr out2bsp decb bgt bprint1 ; loop 4 times rts ;********** ;* bpsrch() - search table for address in ;* shftreg. returns b = index to entry or ;* b = -1 if not found. ;********** ;*for(b=0; b=6; b=+2) ;* x[] = brktabl + b; ;* if(x[0] = shftreg) ;* return(b); ;*return(-1); bpsrch: clrb bpsrch1: ldx #brktabl abx ldx 0,x ; get table entry cpx *shftreg bne bpsrch2 ; jump if no match rts bpsrch2: incb incb cmpb #0x6 ble bpsrch1 ; loop 4 times ldab #0xff rts ;********** ;* bulk - bulk erase the eeprom except the ;* config register. ;********** bulk: clr *tmp2 bra bulk1 ;********** ;* bulkall - bulk erase the eeprom and the ;* config register. ;********** bulkall: clr *tmp2 inc *tmp2 ;*set up pprog register for erase bulk1: psha ldaa #0x06 staa pprog ; set eelat, erase bits ;*if (ee only) write to 0xb600 ;*else write to config register ldaa #0xff tst *tmp2 bne bulk2 ; jump if config staa 0xb600 ; write to 0xb600 bra bulk3 bulk2: staa config bulk3 = . ;*start erasing ldaa #0x07 bne acl3 clra ; fail safe acl3: staa pprog ;*delay for 10 ms at E = 2 mhz pshx ldx #0x0d06 ; 6~ * 3334 = 20,004 * 0.5 mhz bulkdly: dex ; 2~ bne bulkdly ; 3~ pulx ;*stop programming clr pprog pula rts ;********** ;* dump [ []] - dump memory ;* in 16 byte lines from to . ;* default starting address is "current ;* location" and default number of lines is 8. ;********** ;*ptr1 = ptrmem; /* default start address */ ;*ptr2 = ptr1 + 0x80; /* default end address */ ;*a = wskip(); ;*if(a != cr) ;* a = buffarg(); ;* if(countu1 = 0) return(bad argument); ;* if( !dchek(a) ) return(bad argument); ;* ptr1 = shftreg; ;* ptr2 = ptr1 + 0x80; /* default end address */ ;* a = wskip(); ;* if(a != cr) ;* a = buffarg(); ;* if(countu1 = 0) return(bad argument); ;* a = wskip(); ;* if(a != cr) return(bad argument); ;* ptr2 = shftreg; dump: ldx *ptrmem ; current location stx *ptr1 ; default start ldab #0x80 abx stx *ptr2 ; default end jsr wskip cmpa #0xd beq dump1 ; jump - no arguments jsr buffarg ; read argument tst *count beq dumperr ; jump if no argument jsr dchek bne dumperr ; jump if delimiter ldx *shftreg stx *ptr1 ldab #0x80 abx stx *ptr2 ; default end address jsr wskip cmpa #0xd beq dump1 ; jump - 1 argument jsr buffarg ; read argument tst *count beq dumperr ; jump if no argument jsr wskip cmpa #0x0d bne dumperr ; jump if not cr ldx *shftreg stx *ptr2 bra dump1 ; jump - 2 arguments dumperr: ldx #msg9 ; "bad argument" jsr outstrg rts ;*ptrmem = ptr1; ;*ptr1 = ptr1 & 0xfff0; dump1: ldd *ptr1 std *ptrmem ; new current location andb #0xf0 std *ptr1 ; start dump at 16 byte boundary ;*** dump loop starts here *** ;*do: ;* output address of first byte; dumplp: jsr outcrlf ldx #ptr1 jsr out2bsp ; first address ;* x = ptr1; ;* for(b=0; b=16; b++) ;* output contents; ldx *ptr1 ; base address clrb ; loop counter dumpdat: jsr out1bsp ; hex value loop incb cmpb #0x10 blt dumpdat ; loop 16 times ;* x = ptr1; ;* for(b=0; b=16; b++) ;* a = x[b]; ;* if(0x7a < a < 0x20) a = 0x20; ;* output ascii contents; clrb ; loop counter dumpasc: ldx *ptr1 ; base address abx ldaa ,x ; ascii value loop cmpa #0x20 blo dump3 ; jump if non printable cmpa #0x7a bls dump4 ; jump if printable dump3: ldaa #0x20 ; space for non printables dump4: jsr output ; output ascii value incb cmpb #0x10 blt dumpasc ; loop 16 times ;* chkabrt(); ;* ptr1 = ptr1 + 0x10; ;*while(ptr1 <= ptr2); ;*return; jsr chkabrt ; check abort or wait ldd *ptr1 addd #0x10 ; point to next 16 byte bound std *ptr1 ; update ptr1 cpd *ptr2 bhi dump5 ; quit if ptr1 > ptr2 cpd #0x00 ; check wraparound at 0xffff bne dumplp ; jump - no wraparound ldd *ptr2 cpd #0xfff0 blo dumplp ; upper bound not at top dump5: rts ; quit ;********** ;* fill [] - block fill ;*memory from addr1 to addr2 with data. data ;*defaults to 0xff. ;********** ;*get addr1 and addr2 fill = . jsr wskip jsr buffarg tst *count beq fillerr ; jump if no argument jsr wchek bne fillerr ; jump if bad argument ldx *shftreg stx *ptr1 ; address1 jsr wskip jsr buffarg tst *count beq fillerr ; jump if no argument jsr dchek bne fillerr ; jump if bad argument ldx *shftreg stx *ptr2 ; address2 ;*get data if it exists ldaa #0xff staa *tmp2 ; default data jsr wskip cmpa #0x0d beq fill1 ; jump if default data jsr buffarg tst *count beq fillerr ; jump if no argument jsr wskip cmpa #0x0d bne fillerr ; jump if bad argument ldaa *shftreg+1 staa *tmp2 ;*while(ptr1 <= ptr2) ;* *ptr1 = data ;* if(*ptr1 != data) abort fill1 = . jsr chkabrt ; check for abort ldx *ptr1 ; starting address ldaa *tmp2 ; data staa 0,x cmpa 0,x bne fillbad ; jump if no write cpx *ptr2 beq fill2 ; quit yet? inx stx *ptr1 bra fill1 ; loop fill2: rts fillerr: ldx #msg9 ; "bad argument" jsr outstrg rts fillbad: ldx #msg6 ; "rom -" jsr outstrg ldx #ptr1 jsr out2bsp rts ;********** ;* call [] - execute a jsr to addr or ;*user's pc value. return to monitor by rts ;*or breakpoint. ;********** ;*a = wskip(); ;*if(a != cr) ;* a = buffarg(); ;* a = wskip(); ;* if(a != cr) return(bad argument) ;* pc = shftreg; call: jsr wskip cmpa #0xd beq call3 ; jump if no arg jsr buffarg jsr wskip cmpa #0xd beq call2 ; jump if cr ldx #msg9 ; "bad argument" jsr outstrg rts call2: ldx *shftreg stx *regs ; pc = ;*user_stack[0] = return_to_monitor; ;*setbps(); ;*restack(); /* restack and go*/ call3: ldx *sp dex ; user stack pointer ldd #return ; return address std 0,x dex stx *sp ; new user stack pointer jsr setbps clr *tmp2 ; flag for breakpoints jmp restack ; executes an rti ;********** ;* return() - return here from rts after ;*call command. ;********** return: psha ; save a register tpa staa *regs+8 ; cc register pula std *regs+6 ; a and b registers stx *regs+4 ; x register sty *regs+2 ; y register sts *sp ; user stack pointer lds #stack ; monitor stack pointer jsr rembps ; remove breakpoints jsr outcrlf jsr rprint ; print user registers jmp main ;********** ;* go [] - execute starting at or ;*user's pc value. executes an rti to user code. ;*returns to monitor via an swi through swiin. ;********** ;*a = wskip(); ;*if(a != cr) ;* a = buffarg(); ;* a = wskip(); ;* if(a != cr) return(bad argument) ;* pc = shftreg; ;*setbps(); ;*restack(); /* restack and go*/ go: jsr wskip cmpa #0x0d beq go2 ; jump if no arg jsr buffarg jsr wskip cmpa #0x0d beq go1 ; jump if cr ldx #msg9 ; "bad argument" jsr outstrg rts go1: ldx *shftreg stx *regs ; pc = go2: clr *tmp2 ; flag for breakpoints inc *tmp2 ; (1=go, 0=call) jsr setbps jmp restack ; execute an rti ;********** ;* swiin() - return from swi. set up ;*stack pointers, save user registers, and ;*return to main. ;********** swiin: tsx ; swi entry point lds #stack jsr savstack ; save user regs ldx *regs dex stx *regs ; save user pc ldx *ptr4 ; restore user swi vector stx *jswi+1 ;*if(flagt1 = 0) remove return addr from stack; tst *tmp2 ; 0=call, 1=go bne go3 ; jump if go command ldx *sp ; remove return address inx inx stx *sp go3: jsr outcrlf ; print register values jsr rprint jsr rembps jmp main ; return to monitor ;* ; (sp destroyed above) ;********** ;* proceed - same as go except it ignores ;*a breakpoint at the first opcode. calls ;*trace once and the go. ;********** proceed: clr *tmp2 ; flag for breakpoints inc *tmp2 ; 0=trace, 1=proceed jmp trace3 ;********** ;* trace - trace n instructions starting ;*at user's pc value. n is a hex number less than ;*0xff (defaults to 1). ;********** ;*countt1 = 1 ;*a = wskip(); ;*if(a != cr) ;* a = buffarg(); a = wskip(); ;* if(a != cr) return(bad argument); ;* countt1 = n trace: clr *tmp4 inc *tmp4 ; default countt1 = 1 clr *tmp2 ; 0 = trace jsr wskip cmpa #0x0d beq trace2 ; jump if cr jsr buffarg jsr wskip cmpa #0x0d beq trace1 ; jump if cr ldx #msg9 ; "bad argument" jsr outstrg rts trace1: ldaa *shftreg+1 ; n staa *tmp4 ;*print opcode trace2: jsr outcrlf ldx #msg5 ; "op-" jsr outstrg ldx *regs jsr out1bsp ; opcode ;*save user oc5 regs, setup monitor oc5 regs trace3: ldaa tctl1 staa *ptr2 ; save user mode/level anda #0xfc staa tctl1 ; disable oc5 output ldaa tmsk1 staa *ptr2+1 ; save user int masks clr tmsk2 ; disable tof and pac ints ;*put monitor toc5 vector into jump table ldx *jtoc5+1 stx *ptr4 ; save user's vector ldaa #0x7e ; jmp opcode staa *jtoc5 ldx #tracein stx *jtoc5+1 ; monitor toc5 vector ;*unmask i bit in user ccr ldaa *regs+8 ; user ccr anda #0xef ; clear i bit staa *regs+8 ;*arm oc5 interrupt ldab #87 ; cycles to end of rti ldx tcnt ; timer count value abx ; 3~ ) stx toc5 ; oc5 match register 5~ ) ldaa #0x08 ; 2~ ) staa tflg1 ; clear oc5 int flag 4~ ) 86~ staa tmsk1 ; enable oc5 interrupt 4~ ) cli ; 2~ ) jmp restack ; execute an rti 66~ ) ;********** ;* tracein - return from toc5 interrupt. ;********** ;*disable toc5 interrupt ;*replace user's toc5 vector tracein: sei clr tmsk1 ; disable timer ints tsx lds #stack jsr savstack ; save user regs ldx *ptr4 stx *jtoc5+1 jsr chkabrt ; check for abort ;*if(flagt1 = 1) jump to go command ( proceed ) tst *tmp2 beq trace9 ; jump if trace command jmp go2 ;*rprint(); ;*while(countt1 >= 0) continue trace; trace9: jsr outcrlf ; print registers for jsr rprint ; trace only. dec *tmp4 bhi trace2 ; jump if countt1 >= 0 jmp main ; return to monitor ;* ; (sp destroyed above) ;********** ;* setbps - replace user code with swi's at ;*breakpoint addresses. ;********** ;*for(b=0; b=6; b =+ 2) ;* x = brktabl[b]; ;* if(x != 0) ;* optabl[b] = x[0]; ;* x[0] = 0x3f; setbps: clrb setbps1: ldx #brktabl ldy #ptr6 abx aby ldx 0,x ; breakpoint table entry beq setbps2 ; jump if 0 ldaa 0,x ; save user opcode staa 0,y ldaa #swi ; insert swi into code staa 0,x setbps2: addb #0x2 cmpb #0x6 ble setbps1 ; loop 4 times ;*put monitor swi vector into jump table ldx *jswi+1 stx *ptr4 ; save user swi vector ldaa #0x7e ; jmp opcode staa *jswi ldx #swiin stx *jswi+1 ; monitor swi vector rts ;********** ;* rembps - remove breakpoints from user code. ;********** ;*for(b=0; b=6; b =+ 2) ;* x = brktabl[b]; ;* if(x != 0) ;* x[0] = optabl[b]; rembps: clrb rembps1: ldx #brktabl ldy #ptr6 abx aby ldx 0,x ; breakpoint table entry beq rembps2 ; jump if 0 ldaa 0,y ; restore user's opcode staa 0,x rembps2: addb #0x2 cmpb #0x6 ble rembps1 ; loop 4 times ;*replace user's swi vector ldx *ptr4 stx *jswi+1 rts ;********** ;* restack() - restore user stack and ;*execute an rti. extended addressing forced ;*to ensure count value for trace. ;********** restack: lds sp ; stack pointer ldx regs pshx ; pc ldx regs+2 pshx ; y ldx regs+4 pshx ; x ldd regs+6 psha ; a pshb ; b ldaa regs+8 psha ; ccr restack1: rti ;********** ;* savstack() - save user's registers. ;********** savstack: ldaa 0,x staa *regs+8 ; ccr ldd 1,x staa *regs+7 ; b stab *regs+6 ; a ldd 3,x std *regs+4 ; x ldd 5,x std *regs+2 ; y ldd 7,x std *regs ; pc ldab #8 abx stx *sp ; stack pointer rts ;********** ;* help - list buffalo commands to terminal. ;********** help = . ldx #helpmsg1 jsr outstrg ; print help screen rts helpmsg1 = . .ascii 'ASM [] Line assembler/disassembler.' .byte 0x0d .ascii ' / Do same address.' .ascii ' ^ Do previous address.' .byte 0x0d .ascii ' CTRL-J Do next address.' .ascii ' RETURN Do next opcode.' .byte 0x0d .ascii ' CTRL-A Quit.' .byte 0x0d .ascii 'BF [] Block fill.' .byte 0x0d .ascii 'BR [-][] Set up breakpoint table.' .byte 0x0d .ascii 'BULK Erase the EEPROM.' .ascii ' BULKALL Erase EEPROM and CONFIG.' .byte 0x0d .ascii 'CALL [] Call user subroutine.' .ascii ' G [] Execute user code.' .byte 0x0d .ascii 'LOAD, VERIFY [T] ' .ascii ' Load or verify S-records.' .byte 0x0d .ascii 'MD [ []] Memory dump.' .byte 0x0d .ascii 'MM [] Memory modify.' .byte 0x0d .ascii ' / Open same address. CTRL-H' .ascii ' or ^ Open previous address.' .byte 0x0d .ascii ' CTRL-J Open next address. SPACE' .ascii ' Open next address.' .byte 0x0d .ascii ' RETURN Quit. O' .ascii ' Compute offset to .' .byte 0x0d .ascii 'MOVE [] Block move.' .byte 0x0d .ascii 'P Proceed/continue execution.' .byte 0x0d .ascii 'RM [P, Y, X, A, B, C, or S] Register modify.' .byte 0x0d .ascii 'T [] Trace n instructions.' .byte 0x0d .ascii 'TM Transparent mode (CTRL-A = exit, CTRL-B = send break).' .byte 0x0d .ascii 'CTRL-H Backspace.' .ascii ' CTRL-W Wait for any key.' .byte 0x0d .ascii 'CTRL-X or DELETE Abort/cancel command.' .byte 0x0d .ascii 'RETURN Repeat last command.' .byte 4 ;********** ;* host() - establishes transparent link between ;* terminal and host. port used for host is ;* determined in the reset initialization routine ;* and stored in hostdev. ;* to exit type control a. ;* to send break to host type control b. ;*if(no external device) return; ;*initialize host port; ;*while( !(control a)) ;* input(terminal); output(host); ;* input(host); output(terminal); host: ldaa *extdev bne host0 ; jump if host port avail. ldx #msg10 ; "no host port avail" jsr outstrg rts host0: clr *autolf ; turn off autolf jsr hostco ; connect sci (evb board) jsr hostinit ; initialize host port host1: jsr input ; read terminal tsta beq host3 ; jump if no char cmpa #ctla beq hostend ; jump if control a cmpa #ctlb bne host2 ; jump if not control b jsr txbreak ; send break to host bra host3 host2: jsr hostout ; echo to host host3: jsr hostin ; read host tsta beq host1 ; jump if no char jsr output ; echo to terminal bra host1 hostend: inc *autolf ; turn on autolf jsr targco ; disconnect sci (evb board) rts ; return ;********** ;* txbreak() - transmit break to host port. ;* the duration of the transmitted break is ;* approximately 200,000 e-clock cycles, or ;* 100ms at 2.0 mhz. ;*********** txbreak = . ldaa *hostdev cmpa #0x03 beq txbdu ; jump if duartb is host txbsci: ldx #sccr2 ; sci is host bset 0,x ,#0x01 ; set send break bit bsr txbwait bclr 0,x ,#0x01 ; clear send break bit bra txb1 txbdu: ldx #portb ; duart host port ldaa #0x60 ; start break cmd staa 2,x ; port b command register bsr txbwait ldaa #0x70 ; stop break cmd staa 2,x ; port b command register txb1: ldaa #0x0d jsr hostout ; send carriage return ldaa #0x0a jsr hostout ; send linefeed rts txbwait: ldy #0x6f9b ; loop count = 28571 txbwait1: dey ; 7 cycle loop bne txbwait1 rts ;********** ;* hostinit(), hostin(), hostout() - host i/o ;*routines. restores original terminal device. ;********** hostinit: ldab *iodev ; save terminal pshb ldab *hostdev stab *iodev ; point to host jsr init ; initialize host bra termres ; restore terminal hostin: ldab *iodev ; save terminal pshb ldab *hostdev stab *iodev ; point to host jsr input ; read host bra termres ; restore terminal hostout: ldab *iodev ; save terminal pshb ldab *hostdev stab *iodev ; point to host jsr output ; write to host termres: pulb ; restore terminal device stab *iodev rts ;********** ;* load(ptrbuff[]) - load s1/s9 records from ;*host to memory. ptrbuff[] points to string in ;*input buffer which is a command to output s1/s9 ;*records from the host ("cat filename" for unix). ;* returns error and address if it can't write ;*to a particular location. ;********** ;* verify(ptrbuff[]) - verify memory from load ;*command. ptrbuff[] is same as for load. ;********** verify: clr *tmp2 inc *tmp2 ; flagt1 = 1 = verify bra load1 load: clr *tmp2 ; flagt1 = 0 = load ;*a=wskip(); ;*if(a = cr) goto transparent mode; ;*if(t option) hostdev = iodev; load1: jsr wskip cmpa #0x0d bne load1a jmp host ; go to host if no args load1a: jsr upcase cmpa #'T ; look for t option bne load1b ; jump not t option jsr incbuff jsr readbuff ; get next character jsr decbuff cmpa #0x0d bne load1b ; jump if not t option clr *autolf ldaa *iodev staa *hostdev ; set host port = terminal bra load6 ; go wait for s1 records ;*else while(not cr) ;* read character from input buffer; ;* send character to host; load1b: clr *autolf jsr hostco ; connect sci (evb board) jsr hostinit ; initialize host port load2: jsr readbuff ; get next char jsr incbuff psha ; save char jsr hostout ; output to host jsr output ; echo to terminal pula cmpa #0x0d bne load2 ; jump if not cr ;*repeat: ;* if(hostdev != iodev) check abort; ;* a = hostin(); ;* if(a = 's') ;* a = hostin; ;* if(a = '9') ;* read rest of record; ;* return(done); ;* if(a = '1') ;* checksum = 0; ;* byte(); b = shftreg+1; /* byte count */ ;* byte(); byte(); x = shftreg; /* base addr*/ ;* do ;* byte(); ;* if(flagt1 = 0) ;* x[0] = shftreg+1 ;* if(x[0] != shftreg+1) ;* return("rom-(x)"); ;* x++; b--; ;* until(b = 0) load6 = . ldaa *hostdev cmpa *iodev beq load65 ; jump if hostdev=iodev jsr chkabrt ; check for abort load65: jsr hostin ; read host tsta beq load6 ; jump if no input cmpa #'S bne load6 ; jump if not s load7: jsr hostin ; read host tsta beq load7 ; jump if no input cmpa #'9 bne load8 ; jump if not s9 jsr byte ldab *shftreg+1 ; b = byte count load75: jsr byte decb bne load75 ; loop until end of record inc *autolf ; turn on autolf jsr targco ; disconnect sci (evb) ldx #msg11 ; "done" jsr outstrg rts load8: cmpa #'1 bne load6 ; jump if not s1 clr *tmp4 ; clear checksum jsr byte ldab *shftreg+1 subb #0x2 ; b = byte count jsr byte jsr byte ldx *shftreg ; x = base address dex load10: jsr byte ; get next byte inx decb ; check byte count beq load12 ; if 0, go do checksum ldaa *shftreg+1 tst *tmp2 bne load11 ; jump if verify staa 0,x ; load only load11: cmpa 0,x ; verify ram location beq load10 ; jump if ram ok stx *ptr3 ; save error address inc *autolf ; turn on autolf jsr targco ; disconnect sci(evb) jsr outcrlf ldx #msg13 ; "error addr" jsr outstrg ldx #ptr3 jsr out2bsp ; address rts load12: ldaa *tmp4 inca ; do checksum bne load13 ; jump if s1 record okay jmp load6 load13: inc *autolf jsr targco ; disconnect sci(evb) jsr outcrlf ldx #msg12 ; "checksum error" jsr outstrg rts ;********** ;* byte() - read 2 ascii bytes from host and ;*convert to one hex byte. returns byte ;*shifted into shftreg and added to tmp4. ;********** byte: pshb pshx byte0: jsr hostin ; read host (1st byte) tsta beq byte0 ; loop until input jsr hexbin byte1: jsr hostin ; read host (2nd byte) tsta beq byte1 ; loop until input jsr hexbin ldaa *shftreg+1 adda *tmp4 staa *tmp4 ; add to checksum pulx pulb rts ;******************************************* ;* memory [] ;* []/ ;* opens memory and allows user to modify the ;*contents at or the last opened location. ;* subcommands: ;* [] - close current location and exit. ;* [] - close current and open next. ;* []<^> - close current and open previous. ;* [] - close current and open next. ;* []/ - reopen current location. ;* the contents of the current location is only ;* changed if valid data is entered before each ;* subcommand. ;* []o - compute relative offset from current ;* location to . the current location must ;* be the address of the offset byte. ;********** ;*a = wskip(); ;*if(a != cr) ;* a = buffarg(); ;* if(a != cr) return(bad argument); ;* if(countu1 != 0) ptrmem[] = shftreg; memory: jsr wskip cmpa #0xd beq mem1 ; jump if cr jsr buffarg jsr wskip cmpa #0xd beq mslash ; jump if cr ldx #msg9 ; "bad argument" jsr outstrg rts mslash: tst *count beq mem1 ; jump if no argument ldx *shftreg stx *ptrmem ; update "current location" ;********** ;* subcommands ;********** ;*outcrlf(); ;*out2bsp(ptrmem[]); ;*out1bsp(ptrmem[0]); mem1: jsr outcrlf mem2: ldx #ptrmem jsr out2bsp ; output address mem3: ldx *ptrmem jsr out1bsp ; output contents clr *shftreg clr *shftreg+1 ;*while 1 ;*a = termarg(); ;* switch(a) ;* case(space): ;* chgbyt(); ;* ptrmem[]++; ;* case(linefeed): ;* chgbyt(); ;* ptrmem[]++; ;* case(up arrow): ;* case(backspace): ;* chgbyt(); ;* ptrmem[]--; ;* case("/"): ;* chgbyt(); ;* outcrlf(); ;* case(o): ;* d = ptrmem[0] - (shftreg); ;* if(0x80 < d < 0xff81) ;* print(out of range); ;* countt1 = d-1; ;* out1bsp(countt1); ;* case(carriage return): ;* chgbyt(); ;* return; ;* default: return(command?) mem4: jsr termarg jsr upcase ldx *ptrmem cmpa #0x20 beq memsp ; jump if space cmpa #0x0a beq memlf ; jump if linefeed cmpa #0x5e beq memua ; jump if up arrow cmpa #0x08 beq membs ; jump if backspace cmpa #'/ beq memsl ; jump if / cmpa #'O beq memoff ; jump if o cmpa #0x0d beq memcr ; jump if carriage ret ldx #msg8 ; "command?" jsr outstrg jmp mem1 memsp: jsr chgbyt inx stx *ptrmem jmp mem3 ; output contents memlf: jsr chgbyt inx stx *ptrmem jmp mem2 ; output addr, contents memua = . membs: jsr chgbyt dex stx *ptrmem jmp mem1 ; output cr, addr, contents memsl: jsr chgbyt jmp mem1 ; output cr, addr, contents memoff: ldd *shftreg ; destination addr subd *ptrmem cmpa #0x0 bne memoff1 ; jump if not 0 cmpb #0x80 bls memoff3 ; jump if in range bra memoff2 ; out of range memoff1: cmpa #0xff bne memoff2 ; out of range cmpb #0x81 bhs memoff3 ; in range memoff2: ldx #msg3 ; "too long" jsr outstrg jmp mem1 ; output cr, addr, contents memoff3: subd #0x1 ; b now has offset stab *tmp4 jsr outspac ldx #tmp4 jsr out1bsp ; output offset jmp mem1 ; output cr, addr, contents memcr: jsr chgbyt rts ; exit task ;********** ;* move [] - move ;*block at to to . ;* moves block 1 byte up if no . ;********** ;*a = buffarg(); ;*if(countu1 = 0) return(bad argument); ;*if( !wchek(a) ) return(bad argument); ;*ptr1 = shftreg; /* src1 */ move = . jsr buffarg tst *count beq moverr ; jump if no arg jsr wchek bne moverr ; jump if no delim ldx *shftreg ; src1 stx *ptr1 ;*a = buffarg(); ;*if(countu1 = 0) return(bad argument); ;*if( !dchek(a) ) return(bad argument); ;*ptr2 = shftreg; /* src2 */ jsr buffarg tst *count beq moverr ; jump if no arg jsr dchek bne moverr ; jump if no delim ldx *shftreg ; src2 stx *ptr2 ;*a = buffarg(); ;*a = wskip(); ;*if(a != cr) return(bad argument); ;*if(countu1 != 0) tmp2 = shftreg; /* dest */ ;*else tmp2 = ptr1 + 1; jsr buffarg jsr wskip cmpa #0x0d bne moverr ; jump if not cr tst *count beq move1 ; jump if no arg ldx *shftreg ; dest bra move2 moverr: ldx #msg9 ; "bad argument" jsr outstrg rts move1: ldx *ptr1 inx ; default dest move2: stx *ptr3 ;*if(src1 < dest <= src2) ;* dest = dest+(src2-src1); ;* for(x = src2; x = src1; x--) ;* dest[0]-- = x[0]--; ldx *ptr3 ; dest cpx *ptr1 ; src1 bls move3 ; jump if dest =< src1 cpx *ptr2 ; src2 bhi move3 ; jump if dest > src2 ldd *ptr2 subd *ptr1 addd *ptr3 std *ptr3 ; dest = dest+(src2-src1) ldx *ptr2 movelp1: jsr chkabrt ; check for abort ldaa ,x ; char at src2 pshx ldx *ptr3 cpx #0xb600 ; jump if not eeprom blo movea cpx #0xb7ff ; jump if not eeprom bhi movea jsr movprog ; program eeprom movea: staa ,x ; dest dex stx *ptr3 pulx cpx *ptr1 beq movrts dex bra movelp1 ; loop src2 - src1 times ;* ;* else ;* for(x=src1; x=src2; x++) ;* dest[0]++ = x[0]++; move3: ldx *ptr1 ; srce1 movelp2: jsr chkabrt ; check for abort ldaa ,x pshx ldx *ptr3 ; dest cpx #0xb600 ; jump if not eeprom blo moveb cpx #0xb7ff ; jump if not eeprom bhi moveb jsr movprog ; program eeprom moveb: staa ,x inx stx *ptr3 pulx cpx *ptr2 beq movrts inx bra movelp2 ; loop src2-src1 times movrts: rts ;************* ;* movprog - program eeprom location in x with ;* data in a. ;************* movprog: pshb pshx ldab #0x02 stab pprog ; set eelat staa ,x ldab #0x03 bne acl4 clrb ; fail safe acl4: stab pprog ; set pgm ldx #0x0d06 movedly: dex bne movedly ; delay 10 ms at E = 2 mhz ldab #0x00 stab pprog pulx pulb rts ;********** ;* register [] - prints the user regs ;*and opens them for modification. is ;*the first register opened (default = p). ;* subcommands: ;* [] opens the next register. ;* [] return. ;* the register value is only changed if ;* is entered before the subcommand. ;********** ;*x[] = reglist ;*a = wskip(); a = upcase(a); ;*if(a != cr) ;* while( a != x[0] ) ;* if( x[0] = "s") return(bad argument); ;* x[]++; ;* incbuff(); a = wskip(); ;* if(a != cr) return(bad argument); register: ldx #reglist jsr wskip ; a = first char of arg jsr upcase ; convert to upper case cmpa #0xd beq reg4 ; jump if no argument reg1: cmpa 0,x beq reg3 ldab 0,x inx cmpb #'S bne reg1 ; jump if not "s" reg2: ldx #msg9 ; "bad argument" jsr outstrg rts reg3: pshx jsr incbuff jsr wskip ; next char after arg cmpa #0xd pulx bne reg2 ; jump if not cr ;*rprint(); ;* while(x[0] != "s") ;* rprnt1(x); ;* a = termarg(); /* read from terminal */ ;* if( ! dchek(a) ) return(bad argument); ;* if(countu1 != 0) ;* if(x[14] = 1) ;* regs[x[7]++ = shftreg; ;* regs[x[7]] = shftreg+1; ;* if(a = cr) break; ;*return; reg4: jsr rprint ; print all registers reg5: jsr outcrlf jsr rprnt1 ; print reg name clr *shftreg clr *shftreg+1 jsr termarg ; read subcommand jsr dchek beq reg6 ; jump if delimeter ldx #msg9 ; "bad argument" jsr outstrg rts reg6: psha pshx tst *count beq reg8 ; jump if no input ldab 7,x ; get reg offset ldaa 14,x ; byte size ldx #regs ; user registers abx tsta beq reg7 ; jump if 1 byte reg ldaa *shftreg staa 0,x ; put in top byte inx reg7: ldaa *shftreg+1 staa 0,x ; put in bottom byte reg8: pulx pula ldab 0,x ; check for register s cmpb #'S beq reg9 ; jump if "s" inx ; point to next register cmpa #0xd bne reg5 ; jump if not cr reg9: rts page1 = 0x00 ; values for page opcodes page2 = 0x18 page3 = 0x1a page4 = 0xcd immed = 0x0 ; addressing modes indx = 0x1 indy = 0x2 limmed = 0x3 ; (long immediate) other = 0x4 ;*** rename variables for assem/disassem *** amode = tmp2 ; addressing mode yflag = tmp3 pnorm = tmp4 ; page for normal opcode oldpc = ptrmem pc = ptr1 ; program counter px = ptr2 ; page for x indexed py = ptr2+1 ; page for y indexed baseop = ptr3 ; base opcode class = ptr3+1 ; class dispc = ptr4 ; pc for disassembler braddr = ptr5 ; relative branch offset mneptr = ptr6 ; pointer to table for dis asscomm = ptr7 ; subcommand for assembler ;*** error messages for assembler *** msgdir: .word #msga1 ; message table index .word #msga2 .word #msga3 .word #msga4 .word #msga5 .word #msga6 .word #msga7 .word #msga8 .word #msga9 msga1: .ascii 'Immediate mode illegal' .byte eot msga2: .ascii 'Error in mnemonic table' .byte eot msga3: .ascii 'Illegal bit op' .byte eot msga4: .ascii 'Bad argument' .byte eot msga5: .ascii 'Mnemonic not found' .byte eot msga6: .ascii 'Unknown addressing mode' .byte eot msga7: .ascii 'Indexed addressing assumed' .byte eot msga8: .ascii 'Syntax error' .byte eot msga9: .ascii 'Branch out of range' .byte eot ;**************** ;* assem(addr) -68hc11 line assembler/disassembler. ;* this routine will disassemble the opcode at ;* and then allow the user to enter a line for ;*assembly. rules for assembly are as follows: ;* -a '#' sign indicates immediate addressing. ;* -a ',' (comma) indicates indexed addressing ;* and the next character must be x or y. ;* -all arguments are assumed to be hex and the ;* '$' sign shouldn't be used. ;* -arguments should be separated by 1 or more ;* spaces or tabs. ;* -any input after the required number of ;* arguments is ignored. ;* -upper or lower case makes no difference. ;* ;* to signify end of input line, the following ;*commands are available and have the indicated action: ;* -carriage return finds the next opcode for ;* assembly. if there was no assembly input, ;* the next opcode disassembled is retrieved ;* from the disassembler. ;* -linefeed works the same as carriage return ;* except if there was no assembly input, the ;* is incremented and the next is ;* disassembled. ;* '^' -up arrow decrements and the previous ;* address is then disassembled. ;* '/' -slash redisassembles the current address. ;* ;* to exit the assembler use control a. of course ;*control x and del will also allow you to abort. ;********** ;*oldpc = rambase; ;*a = wskip(); ;*if (a != cr) ;* buffarg() ;* a = wskip(); ;* if ( a != cr ) return(error); ;* oldpc = a; assem = . ldx #rambs stx *oldpc jsr wskip cmpa #0x0d beq assloop ; jump if no argument jsr buffarg jsr wskip cmpa #0x0d beq assem1 ; jump if argument ok ldx #msga4 ; "bad argument" jsr outstrg rts assem1: ldx *shftreg stx *oldpc ;*repeat ;* pc = oldpc; ;* out2bsp(pc); ;* disassem(); ;* a=readln(); ;* asscomm = a; /* save command */ ;* if(a == ('^' or '/')) outcrlf; ;* if(a == 0) return(error); assloop: ldx *oldpc stx *pc jsr outcrlf ldx #pc jsr out2bsp ; output the address jsr disassm ; disassemble opcode jsr outcrlf jsr outspac jsr outspac jsr outspac jsr outspac ldaa #prompt ; prompt user jsr outa ; output prompt character jsr readln ; read input for assembly staa *asscomm cmpa #'^ beq asslp0 ; jump if up arrow cmpa #'/ beq asslp0 ; jump if slash cmpa #0x00 bne asslp1 ; jump if none of above rts ; return if bad input asslp0: jsr outcrlf asslp1 = . jsr outspac jsr outspac jsr outspac jsr outspac jsr outspac ;* b = parse(input); /* get mnemonic */ ;* if(b > 5) print("not found"); asscomm='/'; ;* elseif(b >= 1) ;* msrch(); ;* if(class==0xff) ;* print("not found"); asscomm='/'; ;* else ;* a = doop(opcode,class); ;* if(a == 0) dispc=0; ;* else process error; asscomm='/'; jsr parse cmpb #0x5 ble asslp2 ; jump if mnemonic <= 5 chars ldx #msga5 ; "mnemonic not found" jsr outstrg bra asslp5 asslp2 = . cmpb #0x0 beq asslp10 ; jump if no input jsr msrch ldaa *class cmpa #0xff bne asslp3 ldx #msga5 ; "mnemonic not found" jsr outstrg bra asslp5 asslp3: jsr doop cmpa #0x00 bne asslp4 ; jump if doop error ldx #0x00 stx *dispc ; indicate good assembly bra asslp10 asslp4: deca ; a = error message index tab ldx #msgdir abx abx ldx 0,x jsr outstrg ; output error message asslp5: clr *asscomm ; error command ;* /* compute next address - asscomm holds subcommand ;* and dispc indicates if valid assembly occured. */ ;* if(asscomm=='^') oldpc -= 1; ;* if(asscomm==(lf or cr) ;* if(dispc==0) oldpc=pc; ;* else ;* if(asscomm==lf) dispc=oldpc+1; ;* oldpc=dispc; ;*until(eot) asslp10 = . ldaa *asscomm cmpa #'^ bne asslp11 ; jump if not up arrow ldx *oldpc dex stx *oldpc ; back up bra asslp15 asslp11: cmpa #0x0a beq asslp12 ; jump if linefeed cmpa #0x0d bne asslp15 ; jump if not cr asslp12: ldx *dispc bne asslp13 ; jump if dispc != 0 ldx *pc stx *oldpc bra asslp15 asslp13: cmpa #0x0a bne asslp14 ; jump if not linefeed ldx *oldpc inx stx *dispc asslp14: ldx *dispc stx *oldpc asslp15: jmp assloop ;**************** ;* readln() --- read input from terminal into buffer ;* until a command character is read (cr,lf,/,^). ;* if more chars are typed than the buffer will hold, ;* the extra characters are overwritten on the end. ;* on exit: b=number of chars read, a=0 if quit, ;* else a=next command. ;**************** ;*for(b==0;b<=bufflng;b++) inbuff[b] = cr; readln: clrb ldaa #0x0d ; carriage ret rln0: ldx #inbuff abx staa 0,x ; initialize input buffer incb cmpb #bufflng blt rln0 ;*b=0; ;*repeat ;* if(a == (ctla, cntlc, cntld, cntlx, del)) ;* return(a=0); ;* if(a == backspace) ;* if(b > 0) b--; ;* else b=0; ;* else inbuff[b] = upcase(a); ;* if(b < bufflng) b++; ;*until (a == (cr,lf,^,/)) ;*return(a); clrb rln1: jsr inchar cmpa #del ; delete beq rlnquit cmpa #ctlx ; control x beq rlnquit cmpa #ctla ; control a beq rlnquit cmpa #0x03 ; control c beq rlnquit cmpa #0x04 ; control d beq rlnquit cmpa #0x08 ; backspace bne rln2 decb bgt rln1 bra readln ; start over rln2: ldx #inbuff abx jsr upcase staa 0,x ; put char in buffer cmpb #bufflng ; max buffer length bge rln3 ; jump if buffer full incb ; move buffer pointer rln3: jsr asschek ; check for subcommand bne rln1 rts rlnquit: clra ; quit rts ; return ;********** ;* parse() -parse out the mnemonic from inbuff ;* to combuff. on exit: b=number of chars parsed. ;********** ;*combuff[3] = ; initialize 4th character to space. ;*ptrbuff[] = inbuff[]; ;*a=wskip(); ;*for (b = 0; b = 5; b++) ;* a=readbuff(); incbuff(); ;* if (a = (cr,lf,^,/,wspace)) return(b); ;* combuff[b] = upcase(a); ;*return(b); parse: ldaa #0x20 staa *combuff+3 ldx #inbuff ; initialize buffer ptr stx *ptr0 jsr wskip ; find first character clrb parslp: jsr readbuff ; read character jsr incbuff jsr wchek beq parsrt ; jump if whitespace jsr asschek beq parsrt ; jump if end of line jsr upcase ; convert to upper case ldx #combuff abx staa 0,x ; store in combuff incb cmpb #0x5 ble parslp ; loop 6 times parsrt: rts ;**************** ;* asschek() -perform compares for ;* cr, lf, ^, / ;**************** asschek: cmpa #0x0a ; linefeed beq asschk1 cmpa #0x0d ; carriage ret beq asschk1 cmpa #'^ ; up arrow beq asschk1 cmpa #'/ ; slash asschk1: rts ;********* ;* msrch() --- search mnetabl for mnemonic in combuff. ;*stores base opcode at baseop and class at class. ;* class = ff if not found. ;********** ;*while ( != eof ) ;* if (combuff[0-3] = mnetabl[0-3]) ;* return(mnetabl[4],mnetabl[5]); ;* else *mnetabl =+ 6 msrch: ldx #mnetabl ; pointer to mnemonic table ldy #combuff ; pointer to string bra msrch1 msnext = . ldab #6 abx ; point to next table entry msrch1: ldaa 0,x ; read table cmpa #eot bne msrch2 ; jump if not end of table ldaa #0xff staa *class ; ff = not in table rts msrch2: cmpa 0,y ; op[0] = tabl[0] ? bne msnext ldaa 1,x cmpa 1,y ; op[1] = tabl[1] ? bne msnext ldaa 2,x cmpa 2,y ; op[2] = tabl[2] ? bne msnext ldaa 3,x cmpa 3,y ; op[2] = tabl[2] ? bne msnext ldd 4,x ; opcode, class staa *baseop stab *class rts ;********** ;** doop(baseop,class) --- process mnemonic. ;** on exit: a=error code corresponding to error ;** messages. ;********** ;*amode = other; /* addressing mode */ ;*yflag = 0; /* ynoimm, nlimm, and cpd flag */ ;*x[] = ptrbuff[] doop = . ldaa #other staa *amode ; mode clr *yflag ldx *ptr0 ;*while (*x != end of buffer) ;* if (x[0]++ == ',') ;* if (x[0] == 'y') amode = indy; ;* else amod = indx; ;* break; ;*a = wskip() ;*if( a == '#' ) amode = immed; doplp1: cpx #endbuff ; (end of buffer) beq doop1 ; jump if end of buffer ldd 0,x ; read 2 chars from buffer inx ; move pointer cmpa #', bne doplp1 cmpb #'Y ; look for ",y" bne doplp2 ldaa #indy staa *amode bra doop1 doplp2: cmpb #'X ; look for ",x" bne doop1 ; jump if not x ldaa #indx staa *amode bra doop1 doop1: jsr wskip cmpa #'# ; look for immediate mode bne doop2 jsr incbuff ; point at argument ldaa #immed staa *amode doop2 = . ;*switch(class) ldab *class cmpb #p2inh bne dosw1 jmp dop2i dosw1: cmpb #inh bne dosw2 jmp doinh dosw2: cmpb #rel bne dosw3 jmp dorel dosw3: cmpb #limm bne dosw4 jmp dolim dosw4: cmpb #nimm bne dosw5 jmp donoi dosw5: cmpb #gen bne dosw6 jmp dogene dosw6: cmpb #grp2 bne dosw7 jmp dogrp dosw7: cmpb #cpd bne dosw8 jmp docpd dosw8: cmpb #xnimm bne dosw9 jmp doxnoi dosw9: cmpb #xlimm bne dosw10 jmp doxli dosw10: cmpb #ynimm bne dosw11 jmp doynoi dosw11: cmpb #ylimm bne dosw12 jmp doyli dosw12: cmpb #btb bne dosw13 jmp dobtb dosw13: cmpb #setclr bne dodef jmp doset ;* default: return("error in mnemonic table"); dodef: ldaa #0x2 rts ;* case p2inh: emit(page2) dop2i: ldaa #page2 jsr emit ;* case inh: emit(baseop); ;* return(0); doinh: ldaa *baseop jsr emit clra rts ;* case rel: a = assarg(); ;* if(a=4) return(a); ;* d = address - pc + 2; ;* if (0x7f >= d >= 0xff82) ;* return (out of range); ;* emit(opcode); ;* emit(offset); ;* return(0); dorel: jsr assarg cmpa #0x04 bne dorel1 ; jump if arg ok rts dorel1: ldd *shftreg ; get branch address ldx *pc ; get program counter inx inx ; point to end of opcode stx *braddr subd *braddr ; calculate offset std *braddr ; save result cmpd #0x7f ; in range ? bls dorel2 ; jump if in range cmpd #0xff80 bhs dorel2 ; jump if in range ldaa #0x09 ; 'out of range' rts dorel2: ldaa *baseop jsr emit ; emit opcode ldaa *braddr+1 jsr emit ; emit offset clra ; normal return rts ;* case limm: if (amode == immed) amode = limmed; dolim: ldaa *amode cmpa #immed bne donoi ldaa #limmed staa *amode ;* case nimm: if (amode == immed) ;* return("immediate mode illegal"); donoi: ldaa *amode cmpa #immed bne dogene ; jump if not immediate ldaa #0x1 ; "immediate mode illegal" rts ;* case gen: dogen(baseop,amode,page1,page1,page2); ;* return; dogene: ldaa #page1 staa *pnorm staa *px ldaa #page2 staa *py jsr dogen rts ;* case grp2: if (amode == indy) ;* emit(page2); ;* amode = indx; ;* if( amode == indx ) ;* doindx(baseop); ;* else a = assarg(); ;* if(a=4) return(a); ;* emit(opcode+0x10); ;* emit(extended address); ;* return; dogrp: ldaa *amode cmpa #indy bne dogrp1 ldaa #page2 jsr emit ldaa #indx staa *amode dogrp1 = . ldaa *amode cmpa #indx bne dogrp2 jsr doindex rts dogrp2 = . ldaa *baseop adda #0x10 jsr emit jsr assarg cmpa #0x04 beq dogrprt ; jump if bad arg ldd *shftreg ; extended address jsr emit tba jsr emit clra dogrprt: rts ;* case cpd: if (amode == immed) ;* amode = limmed; /* cpd */ ;* if( amode == indy ) yflag = 1; ;* dogen(baseop,amode,page3,page3,page4); ;* return; docpd: ldaa *amode cmpa #immed bne docpd1 ldaa #limmed staa *amode docpd1: ldaa *amode cmpa #indy bne docpd2 inc *yflag docpd2: ldaa #page3 staa *pnorm staa *px ldaa #page4 staa *py jsr dogen rts ;* case xnimm: if (amode == immed) /* stx */ ;* return("immediate mode illegal"); doxnoi: ldaa *amode cmpa #immed bne doxli ldaa #0x1 ; "immediate mode illegal" rts ;* case xlimm: if (amode == immed) /* cpx, ldx */ ;* amode = limmed; ;* dogen(baseop,amode,page1,page1,page4); ;* return; doxli: ldaa *amode cmpa #immed bne doxli1 ldaa #limmed staa *amode doxli1: ldaa #page1 staa *pnorm staa *px ldaa #page4 staa *py jsr dogen rts ;* case ynimm: if (amode == immed) /* sty */ ;* return("immediate mode illegal"); doynoi: ldaa *amode cmpa #immed bne doyli ldaa #0x1 ; "immediate mode illegal" rts ;* case ylimm: if (amode == indy) yflag = 1;/* cpy, ldy */ ;* if(amode == immed) amode = limmed; ;* dogen(opcode,amode,page2,page3,page2); ;* return; doyli: ldaa *amode cmpa #indy bne doyli1 inc *yflag doyli1: cmpa #immed bne doyli2 ldaa #limmed staa *amode doyli2: ldaa #page2 staa *pnorm staa *py ldaa #page3 staa *px jsr dogen rts ;* case btb: /* bset, bclr */ ;* case setclr: a = bitop(baseop,amode,class); ;* if(a=0) return(a = 3); ;* if( amode == indy ) ;* emit(page2); ;* amode = indx; dobtb = . doset: jsr bitop cmpa #0x00 bne doset1 ldaa #0x3 ; "illegal bit op" rts doset1: ldaa *amode cmpa #indy bne doset2 ldaa #page2 jsr emit ldaa #indx staa *amode doset2 = . ;* emit(baseop); ;* a = assarg(); ;* if(a = 4) return(a); ;* emit(index offset); ;* if( amode == indx ) ;* buffptr += 2; /* skip ,x or ,y */ ldaa *baseop jsr emit jsr assarg cmpa #0x04 bne doset22 ; jump if arg ok rts doset22: ldaa *shftreg+1 ; index offset jsr emit ldaa *amode cmpa #indx bne doset3 jsr incbuff jsr incbuff doset3 = . ;* a = assarg(); ;* if(a = 4) return(a); ;* emit(mask); /* mask */ ;* if( class == setclr ) ;* return; jsr assarg cmpa #0x04 bne doset33 ; jump if arg ok rts doset33: ldaa *shftreg+1 ; mask jsr emit ldaa *class cmpa #setclr bne doset4 clra rts doset4 = . ;* a = assarg(); ;* if(a = 4) return(a); ;* d = (pc+1) - shftreg; ;* if (0x7f >= d >= 0xff82) ;* return (out of range); ;* emit(branch offset); ;* return(0); jsr assarg cmpa #0x04 bne doset5 ; jump if arg ok rts doset5: ldx *pc ; program counter inx ; point to next inst stx *braddr ; save pc value ldd *shftreg ; get branch address subd *braddr ; calculate offset cmpd #0x7f bls doset6 ; jump if in range cmpd #0xff80 bhs doset6 ; jump if in range clra jsr emit ldaa #0x09 ; 'out of range' rts doset6: tba ; offset jsr emit clra rts ;********** ;** bitop(baseop,amode,class) --- adjust opcode on bit ;** manipulation instructions. returns opcode in a ;** or a = 0 if error ;********** ;*if( amode == indx || amode == indy ) return(op); ;*if( class == setclr ) return(op-8); ;*else if(class==btb) return(op-12); ;*else fatal("bitop"); bitop = . ldaa *amode ldab *class cmpa #indx bne bitop1 rts bitop1: cmpa #indy bne bitop2 ; jump not indexed rts bitop2: cmpb #setclr bne bitop3 ; jump not bset,bclr ldaa *baseop ; get opcode suba #8 staa *baseop rts bitop3: cmpb #btb bne bitop4 ; jump not bit branch ldaa *baseop ; get opcode suba #12 staa *baseop rts bitop4: clra ; 0 = fatal bitop rts ;********** ;** dogen(baseop,mode,pnorm,px,py) - process ;** general addressing modes. returns a = error #. ;********** ;*pnorm = page for normal addressing modes: imm,dir,ext ;*px = page for indx addressing ;*py = page for indy addressing ;*switch(amode) dogen: ldaa *amode cmpa #limmed beq doglim cmpa #immed beq dogimm cmpa #indy beq dogindy cmpa #indx beq dogindx cmpa #other beq dogoth ;*default: error("unknown addressing mode"); dogdef: ldaa #0x06 ; unknown addre... rts ;*case limmed: epage(pnorm); ;* emit(baseop); ;* a = assarg(); ;* if(a = 4) return(a); ;* emit(2 bytes); ;* return(0); doglim: ldaa *pnorm jsr epage doglim1: ldaa *baseop jsr emit jsr assarg ; get next argument cmpa #0x04 bne doglim2 ; jump if arg ok rts doglim2: ldd *shftreg jsr emit tba jsr emit clra rts ;*case immed: epage(pnorm); ;* emit(baseop); ;* a = assarg(); ;* if(a = 4) return(a); ;* emit(lobyte); ;* return(0); dogimm: ldaa *pnorm jsr epage ldaa *baseop jsr emit jsr assarg cmpa #0x04 bne dogimm1 ; jump if arg ok rts dogimm1: ldaa *shftreg+1 jsr emit clra rts ;*case indy: epage(py); ;* a=doindex(op+0x20); ;* return(a); dogindy: ldaa *py jsr epage ldaa *baseop adda #0x20 staa *baseop jsr doindex rts ;*case indx: epage(px); ;* a=doindex(op+0x20); ;* return(a); dogindx: ldaa *px jsr epage ldaa *baseop adda #0x20 staa *baseop jsr doindex rts ;*case other: a = assarg(); ;* if(a = 4) return(a); ;* epage(pnorm); ;* if(countu1 <= 2 digits) /* direct */ ;* emit(op+0x10); ;* emit(lobyte(result)); ;* return(0); ;* else emit(op+0x30); /* extended */ ;* eword(result); ;* return(0) dogoth: jsr assarg cmpa #0x04 bne dogoth0 ; jump if arg ok rts dogoth0: ldaa *pnorm jsr epage ldaa *count cmpa #0x2 bgt dogoth1 ldaa *baseop adda #0x10 ; direct mode opcode jsr emit ldaa *shftreg+1 jsr emit clra rts dogoth1: ldaa *baseop adda #0x30 ; extended mode opcode jsr emit ldd *shftreg jsr emit tba jsr emit clra rts ;********** ;** doindex(op) --- handle all wierd stuff for ;** indexed addressing. returns a = error number. ;********** ;*emit(baseop); ;*a=assarg(); ;*if(a = 4) return(a); ;*if( a != ',' ) return("syntax"); ;*buffptr++ ;*a=readbuff() ;*if( a != 'x' && != 'y') warn("ind addr assumed"); ;*emit(lobyte); ;*return(0); doindex: ldaa *baseop jsr emit jsr assarg cmpa #0x04 bne doindx0 ; jump if arg ok rts doindx0: cmpa #', beq doindx1 ldaa #0x08 ; "syntax error" rts doindx1: jsr incbuff jsr readbuff cmpa #'Y beq doindx2 cmpa #'X beq doindx2 ldx msga7 ; "index addr assumed" jsr outstrg doindx2: ldaa *shftreg+1 jsr emit clra rts ;********** ;** assarg(); - get argument. returns a = 4 if bad ;** argument, else a = first non hex char. ;********** ;*a = buffarg() ;*if(asschk(aa) && countu1 != 0) return(a); ;*return(bad argument); assarg: jsr buffarg jsr asschek ; check for command beq assarg1 ; jump if ok jsr wchek ; check for whitespace bne assarg2 ; jump if not ok assarg1: tst *count beq assarg2 ; jump if no argument rts assarg2: ldaa #0x04 ; bad argument rts ;********** ;** epage(a) --- emit page prebyte ;********** ;*if( a != page1 ) emit(a); epage: cmpa #page1 beq epagrt ; jump if page 1 jsr emit epagrt: rts ;********** ;* emit(a) --- emit contents of a ;********** emit: ldx *pc staa 0,x jsr out1bsp stx *pc rts ;*mnemonic table for hc11 line assembler null = 0x0 ; nothing inh = 0x1 ; inherent p2inh = 0x2 ; page 2 inherent gen = 0x3 ; general addressing grp2 = 0x4 ; group 2 rel = 0x5 ; relative imm = 0x6 ; immediate nimm = 0x7 ; general except for immediate limm = 0x8 ; 2 byte immediate xlimm = 0x9 ; longimm for x xnimm = 0x10 ; no immediate for x ylimm = 0x11 ; longimm for y ynimm = 0x12 ; no immediate for y btb = 0x13 ; bit test and branch setclr = 0x14 ; bit set or clear cpd = 0x15 ; compare d btbd = 0x16 ; bit test and branch direct setclrd = 0x17 ; bit set or clear direct ;********** ;* mnetabl - includes all '11 mnemonics, base opcodes, ;* and type of instruction. the assembler search routine ;*depends on 4 characters for each mnemonic so that 3 char ;*mnemonics are extended with a space and 5 char mnemonics ;*are truncated. ;********** mnetabl = . .ascii 'ABA ' ; mnemonic .byte 0x1b ; base opcode .byte inh ; class .ascii 'ABX ' .byte 0x3a .byte inh .ascii 'ABY ' .byte 0x3a .byte p2inh .ascii 'ADCA' .byte 0x89 .byte gen .ascii 'ADCB' .byte 0xc9 .byte gen .ascii 'ADDA' .byte 0x8b .byte gen .ascii 'ADDB' .byte 0xcb .byte gen .ascii 'ADDD' .byte 0xc3 .byte limm .ascii 'ANDA' .byte 0x84 .byte gen .ascii 'ANDB' .byte 0xc4 .byte gen .ascii 'ASL ' .byte 0x68 .byte grp2 .ascii 'ASLA' .byte 0x48 .byte inh .ascii 'ASLB' .byte 0x58 .byte inh .ascii 'ASLD' .byte 0x05 .byte inh .ascii 'ASR ' .byte 0x67 .byte grp2 .ascii 'ASRA' .byte 0x47 .byte inh .ascii 'ASRB' .byte 0x57 .byte inh .ascii 'BCC ' .byte 0x24 .byte rel .ascii 'BCLR' .byte 0x1d .byte setclr .ascii 'BCS ' .byte 0x25 .byte rel .ascii 'BEQ ' .byte 0x27 .byte rel .ascii 'BGE ' .byte 0x2c .byte rel .ascii 'BGT ' .byte 0x2e .byte rel .ascii 'BHI ' .byte 0x22 .byte rel .ascii 'BHS ' .byte 0x24 .byte rel .ascii 'BITA' .byte 0x85 .byte gen .ascii 'BITB' .byte 0xc5 .byte gen .ascii 'BLE ' .byte 0x2f .byte rel .ascii 'BLO ' .byte 0x25 .byte rel .ascii 'BLS ' .byte 0x23 .byte rel .ascii 'BLT ' .byte 0x2d .byte rel .ascii 'BMI ' .byte 0x2b .byte rel .ascii 'BNE ' .byte 0x26 .byte rel .ascii 'BPL ' .byte 0x2a .byte rel .ascii 'BRA ' .byte 0x20 .byte rel .ascii 'BRCL' ; (brclr) .byte 0x1f .byte btb .ascii 'BRN ' .byte 0x21 .byte rel .ascii 'BRSE' ; (brset) .byte 0x1e .byte btb .ascii 'BSET' .byte 0x1c .byte setclr .ascii 'BSR ' .byte 0x8d .byte rel .ascii 'BVC ' .byte 0x28 .byte rel .ascii 'BVS ' .byte 0x29 .byte rel .ascii 'CBA ' .byte 0x11 .byte inh .ascii 'CLC ' .byte 0x0c .byte inh .ascii 'CLI ' .byte 0x0e .byte inh .ascii 'CLR ' .byte 0x6f .byte grp2 .ascii 'CLRA' .byte 0x4f .byte inh .ascii 'CLRB' .byte 0x5f .byte inh .ascii 'CLV ' .byte 0x0a .byte inh .ascii 'CMPA' .byte 0x81 .byte gen .ascii 'CMPB' .byte 0xc1 .byte gen .ascii 'COM ' .byte 0x63 .byte grp2 .ascii 'COMA' .byte 0x43 .byte inh .ascii 'COMB' .byte 0x53 .byte inh .ascii 'CPD ' .byte 0x83 .byte cpd .ascii 'CPX ' .byte 0x8c .byte xlimm .ascii 'CPY ' .byte 0x8c .byte ylimm .ascii 'DAA ' .byte 0x19 .byte inh .ascii 'DEC ' .byte 0x6a .byte grp2 .ascii 'DECA' .byte 0x4a .byte inh .ascii 'DECB' .byte 0x5a .byte inh .ascii 'DES ' .byte 0x34 .byte inh .ascii 'DEX ' .byte 0x09 .byte inh .ascii 'DEY ' .byte 0x09 .byte p2inh .ascii 'EORA' .byte 0x88 .byte gen .ascii 'EORB' .byte 0xc8 .byte gen .ascii 'FDIV' .byte 0x03 .byte inh .ascii 'IDIV' .byte 0x02 .byte inh .ascii 'INC ' .byte 0x6c .byte grp2 .ascii 'INCA' .byte 0x4c .byte inh .ascii 'INCB' .byte 0x5c .byte inh .ascii 'INS ' .byte 0x31 .byte inh .ascii 'INX ' .byte 0x08 .byte inh .ascii 'INY ' .byte 0x08 .byte p2inh .ascii 'JMP ' .byte 0x6e .byte grp2 .ascii 'JSR ' .byte 0x8d .byte nimm .ascii 'LDAA' .byte 0x86 .byte gen .ascii 'LDAB' .byte 0xc6 .byte gen .ascii 'LDD ' .byte 0xcc .byte limm .ascii 'LDS ' .byte 0x8e .byte limm .ascii 'LDX ' .byte 0xce .byte xlimm .ascii 'LDY ' .byte 0xce .byte ylimm .ascii 'LSL ' .byte 0x68 .byte grp2 .ascii 'LSLA' .byte 0x48 .byte inh .ascii 'LSLB' .byte 0x58 .byte inh .ascii 'LSLD' .byte 0x05 .byte inh .ascii 'LSR ' .byte 0x64 .byte grp2 .ascii 'LSRA' .byte 0x44 .byte inh .ascii 'LSRB' .byte 0x54 .byte inh .ascii 'LSRD' .byte 0x04 .byte inh .ascii 'MUL ' .byte 0x3d .byte inh .ascii 'NEG ' .byte 0x60 .byte grp2 .ascii 'NEGA' .byte 0x40 .byte inh .ascii 'NEGB' .byte 0x50 .byte inh .ascii 'NOP ' .byte 0x01 .byte inh .ascii 'ORAA' .byte 0x8a .byte gen .ascii 'ORAB' .byte 0xca .byte gen .ascii 'PSHA' .byte 0x36 .byte inh .ascii 'PSHB' .byte 0x37 .byte inh .ascii 'PSHX' .byte 0x3c .byte inh .ascii 'PSHY' .byte 0x3c .byte p2inh .ascii 'PULA' .byte 0x32 .byte inh .ascii 'PULB' .byte 0x33 .byte inh .ascii 'PULX' .byte 0x38 .byte inh .ascii 'PULY' .byte 0x38 .byte p2inh .ascii 'ROL ' .byte 0x69 .byte grp2 .ascii 'ROLA' .byte 0x49 .byte inh .ascii 'ROLB' .byte 0x59 .byte inh .ascii 'ROR ' .byte 0x66 .byte grp2 .ascii 'RORA' .byte 0x46 .byte inh .ascii 'RORB' .byte 0x56 .byte inh .ascii 'RTI ' .byte 0x3b .byte inh .ascii 'RTS ' .byte 0x39 .byte inh .ascii 'SBA ' .byte 0x10 .byte inh .ascii 'SBCA' .byte 0x82 .byte gen .ascii 'SBCB' .byte 0xc2 .byte gen .ascii 'SEC ' .byte 0x0d .byte inh .ascii 'SEI ' .byte 0x0f .byte inh .ascii 'SEV ' .byte 0x0b .byte inh .ascii 'STAA' .byte 0x87 .byte nimm .ascii 'STAB' .byte 0xc7 .byte nimm .ascii 'STD ' .byte 0xcd .byte nimm .ascii 'STOP' .byte 0xcf .byte inh .ascii 'STS ' .byte 0x8f .byte nimm .ascii 'STX ' .byte 0xcf .byte xnimm .ascii 'STY ' .byte 0xcf .byte ynimm .ascii 'SUBA' .byte 0x80 .byte gen .ascii 'SUBB' .byte 0xc0 .byte gen .ascii 'SUBD' .byte 0x83 .byte limm .ascii 'SWI ' .byte 0x3f .byte inh .ascii 'TAB ' .byte 0x16 .byte inh .ascii 'TAP ' .byte 0x06 .byte inh .ascii 'TBA ' .byte 0x17 .byte inh .ascii 'TPA ' .byte 0x07 .byte inh .ascii 'TEST' .byte 0x00 .byte inh .ascii 'TST ' .byte 0x6d .byte grp2 .ascii 'TSTA' .byte 0x4d .byte inh .ascii 'TSTB' .byte 0x5d .byte inh .ascii 'TSX ' .byte 0x30 .byte inh .ascii 'TSY ' .byte 0x30 .byte p2inh .ascii 'TXS ' .byte 0x35 .byte inh .ascii 'TYS ' .byte 0x35 .byte p2inh .ascii 'WAI ' .byte 0x3e .byte inh .ascii 'XGDX' .byte 0x8f .byte inh .ascii 'XGDY' .byte 0x8f .byte p2inh .ascii 'BRSE' ; bit direct modes for .byte 0x12 ; disassembler. .byte btbd .ascii 'BRCL' .byte 0x13 .byte btbd .ascii 'BSET' .byte 0x14 .byte setclrd .ascii 'BCLR' .byte 0x15 .byte setclrd .byte eot ; end of table ;********************************************** pg1 = 0x0 pg2 = 0x1 pg3 = 0x2 pg4 = 0x3 ;****************** ;*disassem() - disassemble the opcode. ;****************** ;*(check for page prebyte) ;*baseop=pc[0]; ;*pnorm=pg1; ;*if(baseop==0x18) pnorm=pg2; ;*if(baseop==0x1a) pnorm=pg3; ;*if(baseop==0xcd) pnorm=pg4; ;*if(pnorm != pg1) dispc=pc+1; ;*else dispc=pc; (dispc points to next byte) disassm = . ldx *pc ; address ldaa 0,x ; opcode ldab #pg1 cmpa #0x18 beq disp2 ; jump if page2 cmpa #0x1a beq disp3 ; jump if page3 cmpa #0xcd bne disp1 ; jump if not page4 disp4: incb ; set up page value disp3: incb disp2: incb inx disp1: stx *dispc ; point to opcode stab *pnorm ; save page ;*if(opcode == (0x00-0x5f or 0x8d or 0x8f or 0xcf)) ;* if(pnorm == (pg3 or pg4)) ;* disillop(); return(); ;* b=disrch(opcode,null); ;* if(b==0) disillop(); return(); ldaa 0,x ; get current opcode staa *baseop inx stx *dispc ; point to next byte cmpa #0x5f bls dis1 ; jump if in range cmpa #0x8d beq dis1 ; jump if bsr cmpa #0x8f beq dis1 ; jump if xgdx cmpa #0xcf beq dis1 ; jump if stop jmp disgrp ; try next part of map dis1: ldab *pnorm cmpb #pg3 blo dis2 ; jump if page 1 or 2 jsr disillop ; "illegal opcode" rts dis2: ldab *baseop ; opcode clrb ; class=null jsr disrch tstb bne dispec ; jump if opcode found jsr disillop ; "illegal opcode" rts ;* if(opcode==0x8d) dissrch(opcode,rel); ;* if(opcode==(0x8f or 0xcf)) disrch(opcode,inh); dispec: ldaa *baseop cmpa #0x8d bne dispec1 ldab #rel bra dispec3 ; look for bsr opcode dispec1: cmpa #0x8f beq dispec2 ; jump if xgdx opcode cmpa #0xcf bne disinh ; jump not stop opcode dispec2: ldab #inh dispec3: jsr disrch ; find other entry in table ;* if(class==inh) /* inh */ ;* if(pnorm==pg2) ;* b=disrch(baseop,p2inh); ;* if(b==0) disillop(); return(); ;* prntmne(); ;* return(); disinh = . ldab *class cmpb #inh bne disrel ; jump if not inherent ldab *pnorm cmpb #pg1 beq disinh1 ; jump if page1 ldaa *baseop ; get opcode ldab #p2inh ; class=p2inh jsr disrch tstb bne disinh1 ; jump if found jsr disillop ; "illegal opcode" rts disinh1: jsr prntmne rts ;* elseif(class=rel) /* rel */ ;* if(pnorm != pg1) ;* disillop(); return(); ;* prntmne(); ;* disrelad(); ;* return(); disrel = . ldab *class cmpb #rel bne disbtd tst *pnorm beq disrel1 ; jump if page1 jsr disillop ; "illegal opcode" rts disrel1: jsr prntmne ; output mnemonic jsr disrelad ; compute relative address rts ;* else /* setclr,setclrd,btb,btbd */ ;* if(class == (setclrd or btbd)) ;* if(pnorm != pg1) ;* disillop(); return(); /* illop */ ;* prntmne(); /* direct */ ;* disdir(); /* output 0xbyte */ ;* else (class == (setclr or btb)) ;* prntmne(); /* indexed */ ;* disindx(); ;* outspac(); ;* disdir(); ;* outspac(); ;* if(class == (btb or btbd)) ;* disrelad(); ;* return(); disbtd = . ldab *class cmpb #setclrd beq disbtd1 cmpb #btbd bne disbit ; jump not direct bitop disbtd1: tst *pnorm beq disbtd2 ; jump if page 1 jsr disillop rts disbtd2: jsr prntmne jsr disdir ; operand(direct) bra disbit1 disbit = . jsr prntmne jsr disindx ; operand(indexed) disbit1: jsr outspac jsr disdir ; mask ldab *class cmpb #btb beq disbit2 ; jump if btb cmpb #btbd bne disbit3 ; jump if not bit branch disbit2: jsr disrelad ; relative address disbit3: rts ;*elseif(0x60 <= opcode <= 0x7f) /* grp2 */ ;* if(pnorm == (pg3 or pg4)) ;* disillop(); return(); ;* if((pnorm==pg2) and (opcode != 0x6x)) ;* disillop(); return(); ;* b=disrch(baseop & 0x6f,null); ;* if(b==0) disillop(); return(); ;* prntmne(); ;* if(opcode == 0x6x) ;* disindx(); ;* else ;* disext(); ;* return(); disgrp = . cmpa #0x7f ; a=opcode bhi disnext ; try next part of map ldab *pnorm cmpb #pg3 blo disgrp2 ; jump if page 1 or 2 jsr disillop ; "illegal opcode" rts disgrp2: anda #0x6f ; mask bit 4 clrb ; class=null jsr disrch tstb bne disgrp3 ; jump if found jsr disillop ; "illegal opcode" rts disgrp3: jsr prntmne ldaa *baseop ; get opcode anda #0xf0 cmpa #0x60 bne disgrp4 ; jump if not 6x jsr disindx ; operand(indexed) rts disgrp4: jsr disext ; operand(extended) rts ;*else (0x80 <= opcode <= 0xff) ;* if(opcode == (0x87 or 0xc7)) ;* disillop(); return(); ;* b=disrch(opcode&0xcf,null); ;* if(b==0) disillop(); return(); disnext = . cmpa #0x87 ; a=opcode beq disnex1 cmpa #0xc7 bne disnex2 disnex1: jsr disillop ; "illegal opcode" rts disnex2: anda #0xcf clrb ; class=null jsr disrch tstb bne disnew ; jump if mne found jsr disillop ; "illegal opcode" rts ;* if(opcode&0xcf==0x8d) disrch(baseop,nimm; (jsr) ;* if(opcode&0xcf==0x8f) disrch(baseop,nimm; (sts) ;* if(opcode&0xcf==0xcf) disrch(baseop,xnimm; (stx) ;* if(opcode&0xcf==0x83) disrch(baseop,limm); (subd) disnew: ldaa *baseop anda #0xcf cmpa #0x8d bne disnew1 ; jump not jsr ldab #nimm bra disnew4 disnew1: cmpa #0x8f bne disnew2 ; jump not sts ldab #nimm bra disnew4 disnew2: cmpa #0xcf bne disnew3 ; jump not stx ldab #xnimm bra disnew4 disnew3: cmpa #0x83 bne disgen ; jump not subd ldab #limm disnew4: jsr disrch tstb bne disgen ; jump if found jsr disillop ; "illegal opcode" rts ;* if(class == (gen or nimm or limm )) /* gen,nimm,limm,cpd */ ;* if(opcode&0xcf==0x83) ;* if(pnorm==(pg3 or pg4)) disrch(opcode#0xcf,cpd) ;* class=limm; ;* if((pnorm == (pg2 or pg4) and (opcode != (0xax or 0xex))) ;* disillop(); return(); ;* disgenrl(); ;* return(); disgen: ldab *class ; get class cmpb #gen beq disgen1 cmpb #nimm beq disgen1 cmpb #limm bne disxln ; jump if other class disgen1: ldaa *baseop anda #0xcf cmpa #0x83 bne disgen3 ; jump if not #0x83 ldab *pnorm cmpb #pg3 blo disgen3 ; jump not pg3 or 4 ldab #cpd jsr disrch ; look for cpd mne ldab #limm stab *class ; set class to limm disgen3: ldab *pnorm cmpb #pg2 beq disgen4 ; jump if page 2 cmpb #pg4 bne #disgen5 ; jump not page 2 or 4 disgen4: ldaa *baseop anda #0xb0 ; mask bits 6,3-0 cmpa #0xa0 beq disgen5 ; jump if 0xax or 0xex jsr disillop ; "illegal opcode" rts disgen5: jsr disgenrl ; process general class rts ;* else /* xlimm,xnimm,ylimm,ynimm */ ;* if(pnorm==(pg2 or pg3)) ;* if(class==xlimm) disrch(opcode&0xcf,ylimm); ;* else disrch(opcode&0xcf,ynimm); ;* if((pnorm == (pg3 or pg4)) ;* if(opcode != (0xax or 0xex)) ;* disillop(); return(); ;* class=limm; ;* disgen(); ;* return(); disxln: ldab *pnorm cmpb #pg2 beq disxln1 ; jump if page2 cmpb #pg3 bne disxln4 ; jump not page3 disxln1: ldaa *baseop anda #0xcf ldab *class cmpb #xlimm bne disxln2 ldab #ylimm bra disxln3 ; look for ylimm disxln2: ldab #ynimm ; look for ynimm disxln3: jsr disrch disxln4: ldab *pnorm cmpb #pg3 blo disxln5 ; jump if page 1 or 2 ldaa *baseop ; get opcode anda #0xb0 ; mask bits 6,3-0 cmpa #0xa0 beq disxln5 ; jump opcode = 0xax or 0xex jsr disillop ; "illegal opcode" rts disxln5: ldab #limm stab *class jsr disgenrl ; process general class rts ;****************** ;*disrch(a=opcode,b=class) ;*return b=0 if not found ;* else mneptr=points to mnemonic ;* class=class of opcode ;****************** ;*x=#mnetabl ;*while(x[0] != eot) ;* if((opcode==x[4]) && ((class=null) || (class=x[5]))) ;* mneptr=x; ;* class=x[5]; ;* return(1); ;* x += 6; ;*return(0); /* not found */ disrch = . ldx #mnetabl ; point to top of table disrch1: cmpa 4,x ; test opcode bne disrch3 ; jump not this entry tstb beq disrch2 ; jump if class=null cmpb 5,x ; test class bne disrch3 ; jump not this entry disrch2: ldab 5,x stab *class stx *mneptr ; return ptr to mnemonic incb rts ; return found disrch3: pshb ; save class ldab #6 abx ldab 0,x cmpb #eot ; test end of table pulb bne disrch1 clrb rts ; return not found ;****************** ;*prntmne() - output the mnemonic pointed ;*at by mneptr. ;****************** ;*outa(mneptr[0-3]); ;*outspac; ;*return(); prntmne = . ldx *mneptr ldaa 0,x jsr outa ; output char1 ldaa 1,x jsr outa ; output char2 ldaa 2,x jsr outa ; output char3 ldaa 3,x jsr outa ; output char4 jsr outspac rts ;****************** ;*disindx() - process indexed mode ;****************** ;*disdir(); ;*outa(','); ;*if(pnorm == (pg2 or pg4)) outa('y'); ;*else outa('x'); ;*return(); disindx = . jsr disdir ; output 0xbyte ldaa #', jsr outa ; output , ldab *pnorm cmpb #pg2 beq disind1 ; jump if page2 cmpb #pg4 bne disind2 ; jump if not page4 disind1: ldaa #'Y bra disind3 disind2: ldaa #'X disind3: jsr outa ; output x or y rts ;****************** ;*disrelad() - compute and output relative address. ;****************** ;* braddr = dispc[0] + (dispc++);( 2's comp arith) ;*outa('$'); ;*out2bsp(braddr); ;*return(); disrelad = . ldx *dispc ldab 0,x ; get relative offset inx stx *dispc tstb bmi disrld1 ; jump if negative abx bra disrld2 disrld1: dex incb bne disrld1 ; subtract disrld2: stx *braddr ; save address jsr outspac ldaa #'$ jsr outa ldx #braddr jsr out2bsp ; output address rts ;****************** ;*disgenrl() - output data for the general cases which ;*includes immediate, direct, indexed, and extended modes. ;****************** ;*prntmne(); ;*if(baseop == (0x8x or 0xcx)) /* immediate */ ;* outa('#'); ;* disdir(); ;* if(class == limm) ;* out1byt(dispc++); ;*elseif(baseop == (0x9x or 0xdx)) /* direct */ ;* disdir(); ;*elseif(baseop == (0xax or 0xex)) /* indexed */ ;* disindx(); ;*else (baseop == (0xbx or 0xfx)) /* extended */ ;* disext(); ;*return(); disgenrl = . jsr prntmne ; print mnemonic ldaa *baseop ; get opcode anda #0xb0 ; mask bits 6,3-0 cmpa #0x80 bne disgrl2 ; jump if not immed ldaa #'# ; do immediate jsr outa jsr disdir ldab *class cmpb #limm beq disgrl1 ; jump class = limm rts disgrl1: ldx *dispc jsr out1byt stx *dispc rts disgrl2: cmpa #0x90 bne disgrl3 ; jump not direct jsr disdir ; do direct rts disgrl3: cmpa #0xa0 bne disgrl4 ; jump not indexed jsr disindx ; do extended rts disgrl4: jsr disext ; do extended rts ;***************** ;*disdir() - output "$ next byte" ;***************** disdir = . ldaa #'$ jsr outa ldx *dispc jsr out1byt stx *dispc rts ;***************** ;*disext() - output "$ next 2 bytes" ;***************** disext = . ldaa #'$ jsr outa ldx *dispc jsr out2bsp stx *dispc rts ;***************** ;*disillop() - output "illegal opcode" ;***************** dismsg1: .ascii 'ILLOP' .byte eot disillop = . pshx ldx #dismsg1 jsr outstrg0 ; no cr pulx rts ;* equates jportd = 0x08 jddrd = 0x09 jbaud = 0x2b jsccr1 = 0x2c jsccr2 = 0x2d jscsr = 0x2e jscdat = 0x2f ;* ;************ ;* boot [] - use sci to talk to an 'hc11 in ;* boot mode. downloads 256 bytes starting at addr. ;* default addr = 0x2000. ;************ ;*get arguments ;*if no args, default 0x2000 boot: jsr wskip cmpa #0x0d bne bot1 ; jump if arguments ldy #0x2000 bra bot2 ; go - use default address ;*else get arguments bot1: jsr buffarg tst *count beq boterr ; jump if no address jsr wskip ldy *shftreg ; start address cmpa #0xd beq bot2 ; go - use arguments boterr: ldx #msg9 ; "bad argument" jsr outstrg rts ;*boot routine bot2: ldab #0xff ; control character (0xff -> download) jsr btsub ; set up sci and send control char ;*download 256 byte block clrb ; counter blop: ldaa 0,y staa jscdat,x ; write to transmitter iny brclr jscsr,x ,#0x80, . ; wait for tdre decb bne blop rts ;************************************************ ;*subroutine ;* btsub - sets up sci and outputs control character ;* on entry, b = control character ;* on exit, x = 0x1000 ;* a = 0x0c ;*************************** btsub = . ldx #0x1000 ; to use indexed addressing ldaa #0x02 staa jportd,x ; drive transmitter line staa jddrd,x ; high clr jsccr2,x ; turn off xmtr and rcvr ldaa #0x22 ; baud = /16 staa jbaud,x ldaa #0x0c ; turn on xmtr & rcvr staa jsccr2,x stab jscdat,x brclr jscsr,x ,#0x80, . ; wait for tdre rts ;****************** ;* ;* evbtest - this routine makes it a little easier ;* on us to test this board. ;* ;****************** evbtest: ldaa #0xff staa 0x1000 ; write ones to port a clr *autolf ; turn off auto lf jsr hostco ; connect host jsr hostinit ; initialize host ldaa #0x7f jsr hostout ; send delete to altos ldaa #0x0d jsr hostout ; send inc *autolf ; turn on auto lf ldx #inbuff+5 ; point at load message stx *ptr0 ; set pointer for load command ldy #msgevb ; point at cat line loop: ldaa 0,y ; loop to xfer command line cmpa #04 ; into buffalo line buffer beq done ; quit on 0x04 staa 0,x inx ; next character iny bra loop done: clr *tmp2 ; set load vs. verify jsr load1b ; jmp into middle of load lds #stack ; reset stack jmp 0xc0b3 ; jump to downloaded code msgevb: .ascii /cat evbtest.out/ .byte 0x0d .byte 0x04 .org rombs+0x1fa0 ;*** jump table *** .upcase:jmp upcase .wchek: jmp wchek .dchek: jmp dchek .init: jmp init .input: jmp input .output:jmp output .outlhl:jmp outlhlf .outrhl:jmp outrhlf .outa: jmp outa .out1by:jmp out1byt .out1bs:jmp out1bsp .out2bs:jmp out2bsp .outcrl:jmp outcrlf .outstr:jmp outstrg .outst0:jmp outstrg0 .inchar:jmp inchar .vecint:jmp vecinit .org rombs+0x1fd6 ;*** vectors *** vsci: .word jsci vspi: .word jspi vpaie: .word jpaie vpao: .word jpao vtof: .word jtof vtoc5: .word jtoc5 vtoc4: .word jtoc4 vtoc3: .word jtoc3 vtoc2: .word jtoc2 vtoc1: .word jtoc1 vtic3: .word jtic3 vtic2: .word jtic2 vtic1: .word jtic1 vrti: .word jrti virq: .word jirq vxirq: .word jxirq vswi: .word jswi villop: .word jillop vcop: .word jcop vclm: .word jclm vrst: .word buffalo