* 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. * Rev 2.6 - 9/25/86 - Modified boot routine for variable length download * for use with 'HC11E8. * Rev 3.0 1/15/87 - EEPROM programming routines consolidated into WRITE. * Fill, Assem, and breakpoints will now do EEPROM. * - Added compare a to $0D to WSKIP routine. * 2/11/87 - Set up load to detect receiver error. * Rev 3.2 7/7/87 - Add disassembly to trace. * - Add entries to jump table. * 9/20/87 - Rewrote trace to use XIRQ, added STOPAT Command * 11/24/87- Write block protect reg for 'E9 version * - Modified variable length download for use * with 'E9 bootloader (XBOOT command) * Rev 3.3 3/17/88 - Set I bit to block interrupts on Warm Start and * return from CALL command. * - Added EEMOD Command. * - Rearranged source so that HELP command overlaps * EEPROM in test mode. * 3/24/88 - Added '+', '-', '=', '.' to MEM and ASM commands. * - Added check for 16 byte boundary to MEM * space sub-command. * - LOAD command now puts dummy (~) command into * inbuff so that any stray cr's won`t hang. * Rev 3.4 8/15/88 - Changed WRITE subroutine so that config register * gets byte erased before programmed. The original * value of config is used for EEBYTE so that config * RAM value doesn't get changed in test mode. * 8/17/88 - Fixed MOVE command so that it doesn't hang when move * is done to a ROM location. * - Added OFFSET command for download offset capability. * **************************************************** * 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. * **************************************************** *************** * EQUATES * *************** *Author EQU Tony Fourcroy RAMBS EQU $0000 start of ram REGBS EQU $1000 start of registers ROMBS EQU $E000 start of rom DSTREE EQU $B600 start of eeprom DENDEE EQU $B7FF end of eeprom PORTE EQU REGBS+$0A port e CFORC EQU REGBS+$0B force output compare TCNT EQU REGBS+$0E timer count TOC5 EQU REGBS+$1E oc5 reg TCTL1 EQU REGBS+$20 timer control 1 TMSK1 EQU REGBS+$22 timer mask 1 TFLG1 EQU REGBS+$23 timer flag 1 TMSK2 EQU REGBS+$24 timer mask 2 BAUD EQU REGBS+$2B sci baud reg SCCR1 EQU REGBS+$2C sci control1 reg SCCR2 EQU REGBS+$2D sci control2 reg SCSR EQU REGBS+$2E sci status reg SCDAT EQU REGBS+$2F sci data reg BPROT EQU REGBS+$35 block protect reg OPTION EQU REGBS+$39 option reg COPRST EQU REGBS+$3A cop reset reg PPROG EQU REGBS+$3B ee prog reg HPRIO EQU REGBS+$3C hprio reg CONFIG EQU REGBS+$3F config register DFLOP EQU $4000 evb d flip flop DUART EQU $D000 duart address PORTA EQU DUART PORTB EQU DUART+8 ACIA EQU $9800 acia address PROMPT EQU '>' BUFFLNG EQU 35 CTLA EQU $01 exit host or assembler CTLB EQU $02 send break to host CTLW EQU $17 wait CTLX EQU $18 abort DEL EQU $7F abort EOT EQU $04 end of text/table SWI EQU $3F *************** * RAM * *************** ORG $2D *** Buffalo ram space *** RMB 20 user stack area USTACK RMB 30 monitor stack area STACK RMB 1 REGS RMB 9 user's pc,y,x,a,b,c SP RMB 2 user's sp INBUFF RMB BUFFLNG input buffer ENDBUFF EQU * COMBUFF RMB 8 command buffer SHFTREG RMB 2 input shift register STREE RMB 2 eeprom start address ENDEE RMB 2 eeprom end address BRKTABL RMB 8 breakpoint table AUTOLF RMB 1 auto lf flag for i/o IODEV RMB 1 0=sci, 1=acia, 2=duartA, 3=duartB EXTDEV RMB 1 0=none, 1=acia, 2=duart, HOSTDEV RMB 1 0=sci, 1=acia, 3=duartB COUNT RMB 1 # characters read CHRCNT RMB 1 # characters output on current line PTRMEM RMB 2 current memory location LDOFFST RMB 2 offset for download *** Buffalo variables - used by: *** PTR0 RMB 2 main,readbuff,incbuff,AS PTR1 RMB 2 main,BR,DU,MO,AS,EX PTR2 RMB 2 EX,DU,MO,AS PTR3 RMB 2 EX,HO,MO,AS PTR4 RMB 2 EX,AS PTR5 RMB 2 EX,AS,BOOT PTR6 RMB 2 EX,AS,BOOT PTR7 RMB 2 EX,AS PTR8 RMB 2 AS TMP1 RMB 1 main,hexbin,buffarg,termarg TMP2 RMB 1 GO,HO,AS,LOAD TMP3 RMB 1 AS,LOAD TMP4 RMB 1 TR,HO,ME,AS,LOAD *** Vector jump table *** JSCI RMB 3 JSPI RMB 3 JPAIE RMB 3 JPAO RMB 3 JTOF RMB 3 JTOC5 RMB 3 JTOC4 RMB 3 JTOC3 RMB 3 JTOC2 RMB 3 JTOC1 RMB 3 JTIC3 RMB 3 JTIC2 RMB 3 JTIC1 RMB 3 JRTI RMB 3 JIRQ RMB 3 JXIRQ RMB 3 JSWI RMB 3 JILLOP RMB 3 JCOP RMB 3 JCLM RMB 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,#01,BUFISIT if bit 0 of port e is 1 JMP DSTREE then jump to the start of EEPROM BUFISIT LDAA #$93 STAA OPTION adpu, dly, irqe, cop LDAA #$00 STAA TMSK2 timer pre = %1 for trace LDAA #$00 STAA BPROT clear 'E9 eeprom block protect LDX #DSTREE set up default eeprom address range STX STREE LDX #DENDEE STX ENDEE LDX #$0000 set up default download offset STX LDOFFST LDS #STACK monitor stack pointer JSR VECINIT LDX #USTACK STX SP default user stack LDAA TCTL1 ORAA #$03 STAA TCTL1 force oc5 pin high for trace LDAA #$D0 STAA REGS+8 default user ccr LDD #$3F0D 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 #$20 BEQ BUFF2 jump if single chip mode LDAA #$03 see if external acia exists STAA ACIA master reset LDAA ACIA ANDA #$7F mask irq bit from status register BNE BUFF1 jump if status reg not 0 LDAA #$12 STAA ACIA turn on acia LDAA ACIA ANDA #$02 BEQ BUFF1 jump if tdre not set LDAA #$01 STAA EXTDEV external device is acia BRA BUFF2 BUFF1 EQU * see if duart exists LDAA DUART+$0C read IRQ vector register CMPA #$0F should be out of reset BNE BUFF2 LDAA #$AA STAA DUART+$0C write irq vector register LDAA DUART+$0C read irq vector register CMPA #$AA BNE BUFF2 LDAA #$02 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 #$0D 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 #$0D 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 #$01 BEQ BUFF5 default host if term = acia LDAA #$03 STAA HOSTDEV else host is duart port b BUFF5 EQU * ***************** ** 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 SEI block interrupts 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 #$08 BNE MAIN2 jump if not bckspc DECB BLT MAIN jump if buffer empty BRA MAIN1 MAIN2 CMPA #$D 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 EQU * 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 EQU * JSR READBUFF read from buffer LDX #COMBUFF ABX JSR UPCASE convert to upper case STAA ,X put in command buffer CMPA #$0D BEQ SRCH jump if cr JSR WCHEK BEQ SRCH jump if wspac JSR INCBUFF move buffer pointer INCB CMPB #$8 BLE COMM2 LDX #MSG3 "long" JSR OUTSTRG JMP MAIN COMM2 EQU * CMPA #'/' BNE COMM4 jump if not "/" TST TMP1 BNE COMM3 jump if not enabled DECB STAB COUNT LDX #MSLASH JMP EXEC execute "/" COMM3 LDX #MSG8 "command?" JSR OUTSTRG JMP MAIN COMM4 EQU * 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 #$FF BNE SRCH2 LDX #MSG2 "command not found" JSR OUTSTRG JMP MAIN SRCH2 PSHX compute next table entry ADDB #$3 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 #$20 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 FCC 'PYXABCS' names FCB 0,2,4,6,7,8,9 offset FCB 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 < $30 CMPA #'9' BLE HEXNMB jump if 0-9 CMPA #'A' BLT HEXNOT jump if $39> a <$41 CMPA #'F' BGT HEXNOT jump if a > $46 ADDA #$9 convert $A-$F HEXNMB ANDA #$0F 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; CHGBYT TST COUNT BEQ CHGBYT4 quit if shftreg empty LDAA SHFTREG+1 get data into a JSR WRITE CHGBYT4 RTS ***************** * WRITE() - This routine is used to write the *contents of A to the address of X. If the *address is in EEPROM, it will be programmed *and if it is already programmed, it will be *byte erased first. ****************** *if(X == config) then * byte erase config; *if(X is eeprom)then * if(not erased) then erase; * program (x) = A; *write (x) = A; *if((x) != A) error(rom); WRITE EQU * CPX #CONFIG BEQ WRITE0 jump if config CPX STREE start of EE BLO WRITE2 jump if not EE CPX ENDEE end of EE BHI WRITE2 jump if not EE WRITEE PSHB check if byte erased LDAB 0,X CMPB #$FF PULB BEQ WRITE1 jump if erased WRITE0 JSR EEBYTE byte erase WRITE1 JSR EEWRIT byte program WRITE2 STAA 0,X write for non EE CMPA 0,X BEQ WRITE3 jump if write ok PSHX LDX #MSG6 "rom" JSR OUTSTRG PULX WRITE3 RTS ***************** * EEWRIT(), EEBYTE(), EEBULK() - * These routines are used to program and eeprom *locations. eewrite programs the address in X with *the value in A, eebyte does a byte address at X, *and eebulk does a bulk of eeprom. Whether eebulk *erases the config or not depends on the address it *receives in X. **************** EEWRIT EQU * program one byte at x PSHB LDAB #$02 STAB PPROG STAA 0,X LDAB #$03 BRA EEPROG *** EEBYTE EQU * byte erase address x PSHB LDAB #$16 STAB PPROG LDAB #$FF STAB 0,X LDAB #$17 BRA EEPROG *** EEBULK EQU * bulk erase eeprom PSHB LDAB #$06 STAB PPROG STAA 0,X erase config or not ... LDAB #$07 ... depends on X addr EEPROG BNE ACL1 CLRB fail safe ACL1 STAB PPROG PULB *** DLY10MS EQU * delay 10ms at E = 2MHz PSHX LDX #$0D06 DLYLP DEX BNE DLYLP PULX CLR PPROG 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 also compares a to * $0D (CR) and cond codes indicating the * results of that compare. ***************** WSKIP JSR READBUFF read character JSR WCHEK BNE WSKIP1 jump if not wspc JSR INCBUFF move pointer BRA WSKIP loop WSKIP1 CMPA #$0D RTS ***************** * WCHEK(a) - Returns z=1 if a holds a * whitespace character, else z=0. ***************** WCHEK CMPA #$2C comma BEQ WCHEK1 CMPA #$20 space BEQ WCHEK1 CMPA #$09 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 #$0D 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 #$01 STAA DFLOP send 1 to d-flop PULA RTS TARGCO PSHA LDAA #$00 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 #$7E03 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 #$50 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 EQU * PSHA save registers PSHX LDAA IODEV CMPA #$00 BNE INIT1 jump not sci JSR ONSCI initialize sci BRA INIT4 INIT1 CMPA #$01 BNE INIT2 jump not acia JSR ONACIA initialize acia BRA INIT4 INIT2 LDX #PORTA CMPA #$02 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 EQU * PSHX LDAA #$55 reset cop STAA COPRST LDAA #$AA STAA COPRST LDAA IODEV BNE INPUT1 jump not sci JSR INSCI read sci BRA INPUT4 INPUT1 CMPA #$01 BNE INPUT2 jump not acia JSR INACIA read acia BRA INPUT4 INPUT2 LDX #PORTA CMPA #$02 BEQ INPUT3 jump if duart a LDX #PORTB INPUT3 JSR INUART read uart INPUT4 PULX RTS ********** * OUTPUT() - Output character in A. * chrcnt indicates the current column on the *output display. It is incremented every time *a character is outputted, and cleared whenever *the subroutine outcrlf is called. ********** OUTPUT EQU * PSHA save registers PSHB PSHX LDAB IODEV BNE OUTPUT1 jump not sci JSR OUTSCI write sci BRA OUTPUT4 OUTPUT1 CMPB #$01 BNE OUTPUT2 jump not acia JSR OUTACIA write acia BRA OUTPUT4 OUTPUT2 LDX #PORTA CMPB #$02 BEQ OUTPUT3 jump if duart a LDX #PORTB OUTPUT3 JSR OUTUART write uart OUTPUT4 PULX PULB PULA INC CHRCNT increment column count RTS ********** * ONUART(port) - Initialize a duart port. * Sets duart to internal clock, divide by 16, * 8 data + 1 stop bits. ********** ONUART LDAA #$22 STAA 2,X reset receiver LDAA #$38 STAA 2,X reset transmitter LDAA #$40 STAA 2,X reset error status LDAA #$10 STAA 2,X reset pointer LDAA #$00 STAA DUART+4 clock source LDAA #$00 STAA DUART+5 interrupt mask LDAA #$13 STAA 0,X 8 data, no parity LDAA #$07 STAA 0,X 1 stop bits LDAA #$BB baud rate (9600) STAA 1,X tx and rcv baud rate LDAA #$05 STAA 2,X enable tx and rcv RTS ********** * INUART(port) - Check duart for any input. ********** INUART LDAA 1,X read status ANDA #$01 check rxrdy BEQ INUART1 jump if no data LDAA 3,X read data ANDA #$7F 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 #$0D BNE OUTUART1 LDAA #$0A if cr, output lf BRA OUTUART2 OUTUART1 CMPA #$0A BNE OUTUART3 LDAA #$0D if lf, output cr OUTUART2 LDAB 1,X check status ANDB #$4 BEQ OUTUART2 loop until tdre=1 ANDA #$7F mask parity STAA 3,X send character OUTUART3 RTS ********** * ONSCI() - Initialize the SCI for 9600 * baud at 8 MHz Extal. ********** ONSCI LDAA #$30 STAA BAUD baud register LDAA #$00 STAA SCCR1 LDAA #$0C STAA SCCR2 enable RTS ********** * INSCI() - Read from SCI. Return a=char or 0. ********** INSCI LDAA SCSR read status reg ANDA #$20 check rdrf BEQ INSCI1 jump if no data LDAA SCDAT read data ANDA #$7F 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 #$0D BNE OUTSCI1 LDAA #$0A if cr, send lf BRA OUTSCI2 OUTSCI1 CMPA #$0A BNE OUTSCI3 LDAA #$0D if lf, send cr OUTSCI2 LDAB SCSR read status BITB #$80 BEQ OUTSCI2 loop until tdre=1 ANDA #$7F 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 #$03 STAA 0,X master reset LDAA #$16 STAA 0,X setup RTS ********** * INACIA - Read from the ACIA, Return a=char or 0. * Tmp3 is used to flag overrun or framing error. ********** INACIA LDX #ACIA LDAA 0,X read status register PSHA ANDA #$30 check ov, fe PULA BEQ INACIA1 jump - no error LDAA #$01 STAA TMP3 flag reciever error BRA INACIA2 read data to clear status INACIA1 ANDA #$01 check rdrf BEQ INACIA3 jump if no data INACIA2 LDAA 1,X read data ANDA #$7F mask parity INACIA3 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 #$0D BNE OUTACIA1 LDAA #$0A BSR OUTACIA3 if cr, output lf BRA OUTACIA2 OUTACIA1 CMPA #$0A BNE OUTACIA2 LDAA #$0D BSR OUTACIA3 if lf, output cr OUTACIA2 RTS OUTACIA3 LDX #ACIA LDAB 0,X BITB #$2 BEQ OUTACIA3 loop until tdre ANDA #$7F mask parity STAA 1,X output RTS * * Space for modifying OUTACIA routine * FDB $FFFF,$FFFF,$FFFF,$FFFF ******************************* *** 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 $04. * OUTA-Output the ASCII character in A. * * TABTO-Output spaces until column 20 is reached. * * 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 #$0F mask top half ADDA #$30 convert to ascii CMPA #$39 BLE OUTA jump if 0-9 ADDA #$07 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 #$20 output a space JSR OUTPUT RTS ********** * OUTCRLF() - Output a Carriage return and * a line feed. Returns a = cr. ********** OUTCRLF LDAA #$0D cr JSR OUTPUT output a LDAA #$00 JSR OUTPUT output padding LDAA #$0D CLR CHRCNT zero the column counter RTS ********** * OUTSTRG(x) - Output string of ASCII bytes * starting at x until end of text ($04). 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 ********* * TABTO() - move cursor over to column 20. *while(chrcnt < 16) outspac. TABTO EQU * PSHA TABTOLP JSR OUTSPAC LDAA CHRCNT CMPA #20 BLE TABTOLP 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 EQU * FCB 5 FCC 'ASSEM' FDB ASSEM FCB 5 FCC 'BREAK' FDB BREAK FCB 4 FCC 'BULK' FDB BULK FCB 7 FCC 'BULKALL' FDB BULKALL FCB 4 FCC 'CALL' FDB CALL FCB 4 FCC 'DUMP' FDB DUMP FCB 5 FCC 'EEMOD' FDB EEMOD FCB 4 FCC 'FILL' FDB FILL FCB 2 FCC 'GO' FDB GO FCB 4 FCC 'HELP' FDB HELP FCB 4 FCC 'HOST' FDB HOST FCB 4 FCC 'LOAD' FDB LOAD FCB 6 LENGTH OF COMMAND FCC 'MEMORY' ASCII COMMAND FDB MEMORY COMMAND ADDRESS FCB 4 FCC 'MOVE' FDB MOVE FCB 6 FCC 'OFFSET' FDB OFFSET FCB 7 FCC 'PROCEED' FDB PROCEED FCB 8 FCC 'REGISTER' FDB REGISTER FCB 6 FCC 'STOPAT' FDB STOPAT FCB 5 FCC 'TRACE' FDB TRACE FCB 6 FCC 'VERIFY' FDB VERIFY FCB 1 FCC '?' initial command FDB HELP FCB 5 FCC 'XBOOT' FDB BOOT FCB 1 dummy command for load FCC '~' FDB TILDE * *** Command names for evm compatability *** * FCB 3 FCC 'ASM' FDB ASSEM FCB 2 FCC 'BF' FDB FILL FCB 4 FCC 'COPY' FDB MOVE FCB 5 FCC 'ERASE' FDB BULK FCB 2 FCC 'MD' FDB DUMP FCB 2 FCC 'MM' FDB MEMORY FCB 2 FCC 'RD' FDB REGISTER FCB 2 FCC 'RM' FDB REGISTER FCB 4 FCC 'READ' FDB MOVE FCB 2 FCC 'TM' FDB HOST FCB 4 FCC 'TEST' FDB EVBTEST FCB $FF ******************* *** TEXT TABLES *** MSG1 FCC 'BUFFALO 3.4 (ext) - Bit User Fast Friendly Aid to Logical Operation' FCB EOT MSG2 FCC 'What?' FCB EOT MSG3 FCC 'Too Long' FCB EOT MSG4 FCC 'Full' FCB EOT MSG5 FCC 'Op- ' FCB EOT MSG6 FCC 'rom-' FCB EOT MSG8 FCC 'Command?' FCB EOT MSG9 FCC 'Bad argument' FCB EOT MSG10 FCC 'No host port' FCB EOT MSG11 FCC 'done' FCB EOT MSG12 FCC 'chksum error' FCB EOT MSG13 FCC 'error addr ' FCB EOT MSG14 FCC 'rcvr error' FCB 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 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] = $3F * b = x[0]; x[0] = a; * if(b != $3F) 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 addr LDAA 0,X save original contents PSHA LDAA #SWI JSR WRITE write to entry addr LDAB 0,X read back PULA JSR WRITE restore original CMPB #SWI BEQ BRKDEF2 jump if writes ok STX PTR1 save address 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 #$6 BLE BPSRCH1 loop 4 times LDAB #$FF RTS ********** * bulk - Bulk erase the eeprom not config. * bulkall - Bulk erase eeprom and config. ********* BULK EQU * LDX STREE BRA BULK1 BULKALL LDX #CONFIG BULK1 LDAA #$FF JSR EEBULK 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 + $80; /* 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 + $80; /* 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 #$80 ABX STX PTR2 default end JSR WSKIP 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 #$80 ABX STX PTR2 default end address JSR WSKIP BEQ DUMP1 jump - 1 argument JSR BUFFARG read argument TST COUNT BEQ DUMPERR jump if no argument JSR WSKIP 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 & $fff0; DUMP1 LDD PTR1 STD PTRMEM new current location ANDB #$F0 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 #$10 BLT DUMPDAT loop 16 times * x = ptr1; * for(b=0; b=16; b++) * a = x[b]; * if($7A < a < $20) a = $20; * output ascii contents; CLRB loop counter DUMPASC LDX PTR1 base address ABX LDAA ,X ascii value loop CMPA #$20 BLO DUMP3 jump if non printable CMPA #$7A BLS DUMP4 jump if printable DUMP3 LDAA #$20 space for non printables DUMP4 JSR OUTPUT output ascii value INCB CMPB #$10 BLT DUMPASC loop 16 times * chkabrt(); * ptr1 = ptr1 + $10; *while(ptr1 <= ptr2); *return; JSR CHKABRT check abort or wait LDD PTR1 ADDD #$10 point to next 16 byte bound STD PTR1 update ptr1 CPD PTR2 BHI DUMP5 quit if ptr1 > ptr2 CPD #$00 check wraparound at $ffff BNE DUMPLP jump - no wraparound LDD PTR2 CPD #$FFF0 BLO DUMPLP upper bound not at top DUMP5 RTS quit ********** * eemod [ []] * Modifies the eeprom address range. * EEMOD -show ee address range * EEMOD -set range to addr1 -> addr1+2k * EEMOD -set range to addr1 -> addr2 ********** *if() * stree = addr1; * endee = addr1 + 2k bytes; *if() * endee = addr2; *print(stree,endee); EEMOD EQU * JSR WSKIP BEQ EEMOD2 jump - no arguments JSR BUFFARG read argument TST COUNT BEQ EEMODER jump if no argument JSR DCHEK BNE EEMODER jump if no delimeter LDD SHFTREG STD PTR1 ADDD #$07FF add 2k bytes to stree STD PTR2 default endee address JSR WSKIP BEQ EEMOD1 jump - 1 argument JSR BUFFARG read argument TST COUNT BEQ EEMODER jump if no argument JSR WSKIP BNE EEMODER jump if not cr LDX SHFTREG STX PTR2 EEMOD1 LDX PTR1 STX STREE new stree address LDX PTR2 STX ENDEE new endee address EEMOD2 JSR OUTCRLF display ee range LDX #STREE JSR OUT2BSP LDX #ENDEE JSR OUT2BSP RTS EEMODER LDX #MSG9 "bad argument" JSR OUTSTRG RTS ********** * fill [] - Block fill *memory from addr1 to addr2 with data. Data *defaults to $FF. ********** *get addr1 and addr2 FILL EQU * 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 #$FF STAA TMP2 default data JSR WSKIP BEQ FILL1 jump if default data JSR BUFFARG TST COUNT BEQ FILLERR jump if no argument JSR WSKIP BNE FILLERR jump if bad argument LDAA SHFTREG+1 STAA TMP2 *while(ptr1 <= ptr2) * *ptr1 = data * if(*ptr1 != data) abort FILL1 EQU * JSR CHKABRT check for abort LDX PTR1 starting address LDAA TMP2 data JSR WRITE write the data to 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 EQU * LDX #PTR1 output bad address JSR OUT2BSP 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 BEQ MEM1 jump if cr JSR BUFFARG JSR WSKIP 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[]++; * if(ptrmem%16 == 0) start new line; * case(linefeed | +): * chgbyt(); * ptrmem[]++; * case(up arrow | backspace | -): * chgbyt(); * ptrmem[]--; * case('/' | '='): * chgbyt(); * outcrlf(); * case(O): * d = ptrmem[0] - (shftreg); * if($80 < d < $ff81) * 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 #$20 BEQ MEMSP jump if space CMPA #$0A BEQ MEMLF jump if linefeed CMPA #$2B BEQ MEMPLUS jump if + CMPA #$5E BEQ MEMUA jump if up arrow CMPA #$2D BEQ MEMUA jump if - CMPA #$08 BEQ MEMUA jump if backspace CMPA #'/' BEQ MEMSL jump if / CMPA #'=' BEQ MEMSL jump if = CMPA #'O' BEQ MEMOFF jump if O CMPA #$0D BEQ MEMCR jump if carriage ret CMPA #'.' BEQ MEMEND jump if . LDX #MSG8 "command?" JSR OUTSTRG JMP MEM1 MEMSP JSR CHGBYT INX STX PTRMEM XGDX ANDB #$0F BEQ MEMSP1 jump if mod16=0 JMP MEM3 continue same line MEMSP1 JMP MEM1 .. else start new line MEMLF JSR CHGBYT INX STX PTRMEM JMP MEM2 output next address MEMPLUS JSR CHGBYT INX STX PTRMEM JMP MEM1 output cr, next address MEMUA JSR CHGBYT DEX STX PTRMEM JMP MEM1 output cr, previous address MEMSL JSR CHGBYT JMP MEM1 output cr, same address MEMOFF LDD SHFTREG destination addr SUBD PTRMEM CMPA #$0 BNE MEMOFF1 jump if not 0 CMPB #$80 BLS MEMOFF3 jump if in range BRA MEMOFF2 out of range MEMOFF1 CMPA #$FF BNE MEMOFF2 out of range CMPB #$81 BHS MEMOFF3 in range MEMOFF2 LDX #MSG3 "Too long" JSR OUTSTRG JMP MEM1 output cr, addr, contents MEMOFF3 SUBD #$1 b now has offset STAB TMP4 JSR OUTSPAC LDX #TMP4 JSR OUT1BSP output offset JMP MEM1 output cr, addr, contents MEMCR JSR CHGBYT MEMEND 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 EQU * 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 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 JSR WRITE write a to x CMPA 0,X BNE MOVEBAD jump if no write 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 JSR WRITE write a to x CMPA 0,X BNE MOVEBAD jump if no write INX STX PTR3 PULX CPX PTR2 BEQ MOVRTS INX BRA MOVELP2 Loop SRC2-SRC1 times MOVRTS RTS MOVEBAD PULX restore stack LDX #PTR3 JSR OUT2BSP output bad address RTS **************** * 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: * - Finds the next opcode for * assembly. If there was no assembly input, * the next opcode disassembled is retrieved * from the disassembler. * <+> - Works the same as carriage return * except if there was no assembly input, the * is incremented and the next is * disassembled. * <^><-> - Decrements and the previous * address is then disassembled. * <=> - Redisassembles the current address. * * To exit the assembler use CONTROL A or . (period). *Of course control X and DEL will also allow you to abort. *** Equates for assembler *** PAGE1 EQU $00 values for page opcodes PAGE2 EQU $18 PAGE3 EQU $1A PAGE4 EQU $CD IMMED EQU $0 addressing modes INDX EQU $1 INDY EQU $2 LIMMED EQU $3 (long immediate) OTHER EQU $4 *** Rename variables for assem/disassem *** AMODE EQU TMP2 addressing mode YFLAG EQU TMP3 PNORM EQU TMP4 page for normal opcode OLDPC EQU PTR8 PC EQU PTR1 program counter PX EQU PTR2 page for x indexed PY EQU PTR2+1 page for y indexed BASEOP EQU PTR3 base opcode CLASS EQU PTR3+1 class DISPC EQU PTR4 pc for disassembler BRADDR EQU PTR5 relative branch offset MNEPTR EQU PTR6 pointer to table for dis ASSCOMM EQU PTR7 subcommand for assembler *** Error messages for assembler *** MSGDIR FDB MSGA1 message table index FDB MSGA2 FDB MSGA3 FDB MSGA4 FDB MSGA5 FDB MSGA6 FDB MSGA7 FDB MSGA8 FDB MSGA9 MSGA1 FCC 'Immed mode illegal' FCB EOT MSGA2 FCC 'Error in Mne table' FCB EOT MSGA3 FCC 'Illegal bit op' FCB EOT MSGA4 FCC 'Bad argument' FCB EOT MSGA5 FCC 'Mnemonic not found' FCB EOT MSGA6 FCC 'Unknown addressing mode' FCB EOT MSGA7 FCC 'Indexed addressing assumed' FCB EOT MSGA8 FCC 'Syntax error' FCB EOT MSGA9 FCC 'Branch out of range' FCB EOT ********** *oldpc = rambase; *a = wskip(); *if (a != cr) * buffarg() * a = wskip(); * if ( a != cr ) return(error); * oldpc = a; ASSEM EQU * LDX #RAMBS STX OLDPC JSR WSKIP BEQ ASSLOOP jump if no argument JSR BUFFARG JSR WSKIP 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 == [^,+,-,/,=]) 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 TABTO LDAA #PROMPT prompt user JSR OUTA output prompt character JSR READLN read input for assembly STAA ASSCOMM CMPA #'^' BEQ ASSLP0 jump if '^' CMPA #'+' BEQ ASSLP0 jump if '+' CMPA #'-' BEQ ASSLP0 jump if '-' CMPA #'/' BEQ ASSLP0 jump if '/' CMPA #'=' BEQ ASSLP0 jump if '=' CMPA #$00 BNE ASSLP1 jump if none of above RTS return if bad input ASSLP0 JSR OUTCRLF ASSLP1 EQU * come here for cr or lf 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==$FF) * print("not found"); asscomm='/'; * else * a = doop(opcode,class); * if(a == 0) dispc=0; * else process error; asscomm='/'; JSR PARSE CMPB #$5 BLE ASSLP2 jump if mnemonic <= 5 chars LDX #MSGA5 "mnemonic not found" JSR OUTSTRG BRA ASSLP5 ASSLP2 EQU * CMPB #$0 BEQ ASSLP10 jump if no input JSR MSRCH LDAA CLASS CMPA #$FF BNE ASSLP3 LDX #MSGA5 "mnemonic not found" JSR OUTSTRG BRA ASSLP5 ASSLP3 JSR DOOP CMPA #$00 BNE ASSLP4 jump if doop error LDX #$00 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== ^ or -) oldpc--; * if(asscomm==(lf or + or cr) * if(dispc==0) oldpc=pc; /* good assembly */ * else * if(asscomm==lf or +) dispc= ++oldpc; * oldpc=dispc; *until(eot) ASSLP10 EQU * LDAA ASSCOMM CMPA #'^' BEQ ASSLPA jump if '^' CMPA #'-' BNE ASSLP11 jump not '-' ASSLPA LDX OLDPC back up for '^' or '-' DEX STX OLDPC BRA ASSLP15 ASSLP11 CMPA #$0A BEQ ASSLP12 jump if linefeed CMPA #'+' BEQ ASSLP12 jump if '+' CMPA #$0D BNE ASSLP15 jump if not cr ASSLP12 LDX DISPC BNE ASSLP13 jump if dispc != 0 LDX PC STX OLDPC BRA ASSLP15 ASSLP13 CMPA #$0A BEQ ASSLPB jump not lf CMPA #'+' BNE ASSLP14 jump not lf or '+' ASSLPB 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 #$0D 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 #$2E Period BEQ RLNQUIT CMPA #$03 Control C BEQ RLNQUIT CMPA #$04 Control D BEQ RLNQUIT CMPA #$08 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 #$20 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 #$5 BLE PARSLP loop 6 times PARSRT RTS **************** * asschek() -perform compares for * lf, cr, ^, /, +, -, = **************** ASSCHEK CMPA #$0A linefeed BEQ ASSCHK1 CMPA #$0D carriage ret BEQ ASSCHK1 CMPA #'^' up arrow BEQ ASSCHK1 CMPA #'/' slash BEQ ASSCHK1 CMPA #'+' plus BEQ ASSCHK1 CMPA #'-' minus BEQ ASSCHK1 CMPA #'=' equals 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 EQU * 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 #$FF 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 EQU * 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 EQU * *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 #$2 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 ($7f >= d >= $ff82) * return (out of range); * emit(opcode); * emit(offset); * return(0); DOREL JSR ASSARG CMPA #$04 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 CPD #$7F in range ? BLS DOREL2 jump if in range CPD #$FF80 BHS DOREL2 jump if in range LDAA #$09 '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 #$1 "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 EQU * LDAA AMODE CMPA #INDX BNE DOGRP2 JSR DOINDEX RTS DOGRP2 EQU * LDAA BASEOP ADDA #$10 JSR EMIT JSR ASSARG CMPA #$04 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 #$1 "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 #$1 "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 EQU * DOSET JSR BITOP CMPA #$00 BNE DOSET1 LDAA #$3 "illegal bit op" RTS DOSET1 LDAA AMODE CMPA #INDY BNE DOSET2 LDAA #PAGE2 JSR EMIT LDAA #INDX STAA AMODE DOSET2 EQU * * 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 #$04 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 EQU * * a = assarg(); * if(a = 4) return(a); * emit(mask); /* mask */ * if( class == SETCLR ) * return; JSR ASSARG CMPA #$04 BNE DOSET33 jump if arg ok RTS DOSET33 LDAA SHFTREG+1 mask JSR EMIT LDAA CLASS CMPA #SETCLR BNE DOSET4 CLRA RTS DOSET4 EQU * * a = assarg(); * if(a = 4) return(a); * d = (pc+1) - shftreg; * if ($7f >= d >= $ff82) * return (out of range); * emit(branch offset); * return(0); JSR ASSARG CMPA #$04 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 CPD #$7F BLS DOSET6 jump if in range CPD #$FF80 BHS DOSET6 jump if in range CLRA JSR EMIT LDAA #$09 '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 EQU * 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 #$06 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 #$04 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 #$04 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 #$20 STAA BASEOP JSR DOINDEX RTS *case INDX: epage(px); * a=doindex(op+0x20); * return(a); DOGINDX LDAA PX JSR EPAGE LDAA BASEOP ADDA #$20 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 #$04 BNE DOGOTH0 jump if arg ok RTS DOGOTH0 LDAA PNORM JSR EPAGE LDAA COUNT CMPA #$2 BGT DOGOTH1 LDAA BASEOP ADDA #$10 direct mode opcode JSR EMIT LDAA SHFTREG+1 JSR EMIT CLRA RTS DOGOTH1 LDAA BASEOP ADDA #$30 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 #$04 BNE DOINDX0 jump if arg ok RTS DOINDX0 CMPA #',' BEQ DOINDX1 LDAA #$08 "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 #$04 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 JSR WRITE write a to x JSR OUT1BSP STX PC RTS *Mnemonic table for hc11 line assembler NULL EQU $0 nothing INH EQU $1 inherent P2INH EQU $2 page 2 inherent GEN EQU $3 general addressing GRP2 EQU $4 group 2 REL EQU $5 relative IMM EQU $6 immediate NIMM EQU $7 general except for immediate LIMM EQU $8 2 byte immediate XLIMM EQU $9 longimm for x XNIMM EQU $10 no immediate for x YLIMM EQU $11 longimm for y YNIMM EQU $12 no immediate for y BTB EQU $13 bit test and branch SETCLR EQU $14 bit set or clear CPD EQU $15 compare d BTBD EQU $16 bit test and branch direct SETCLRD EQU $17 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 EQU * FCC 'ABA ' Mnemonic FCB $1B Base opcode FCB INH Class FCC 'ABX ' FCB $3A FCB INH FCC 'ABY ' FCB $3A FCB P2INH FCC 'ADCA' FCB $89 FCB GEN FCC 'ADCB' FCB $C9 FCB GEN FCC 'ADDA' FCB $8B FCB GEN FCC 'ADDB' FCB $CB FCB GEN FCC 'ADDD' FCB $C3 FCB LIMM FCC 'ANDA' FCB $84 FCB GEN FCC 'ANDB' FCB $C4 FCB GEN FCC 'ASL ' FCB $68 FCB GRP2 FCC 'ASLA' FCB $48 FCB INH FCC 'ASLB' FCB $58 FCB INH FCC 'ASLD' FCB $05 FCB INH FCC 'ASR ' FCB $67 FCB GRP2 FCC 'ASRA' FCB $47 FCB INH FCC 'ASRB' FCB $57 FCB INH FCC 'BCC ' FCB $24 FCB REL FCC 'BCLR' FCB $1D FCB SETCLR FCC 'BCS ' FCB $25 FCB REL FCC 'BEQ ' FCB $27 FCB REL FCC 'BGE ' FCB $2C FCB REL FCC 'BGT ' FCB $2E FCB REL FCC 'BHI ' FCB $22 FCB REL FCC 'BHS ' FCB $24 FCB REL FCC 'BITA' FCB $85 FCB GEN FCC 'BITB' FCB $C5 FCB GEN FCC 'BLE ' FCB $2F FCB REL FCC 'BLO ' FCB $25 FCB REL FCC 'BLS ' FCB $23 FCB REL FCC 'BLT ' FCB $2D FCB REL FCC 'BMI ' FCB $2B FCB REL FCC 'BNE ' FCB $26 FCB REL FCC 'BPL ' FCB $2A FCB REL FCC 'BRA ' FCB $20 FCB REL FCC 'BRCL' (BRCLR) FCB $1F FCB BTB FCC 'BRN ' FCB $21 FCB REL FCC 'BRSE' (BRSET) FCB $1E FCB BTB FCC 'BSET' FCB $1C FCB SETCLR FCC 'BSR ' FCB $8D FCB REL FCC 'BVC ' FCB $28 FCB REL FCC 'BVS ' FCB $29 FCB REL FCC 'CBA ' FCB $11 FCB INH FCC 'CLC ' FCB $0C FCB INH FCC 'CLI ' FCB $0E FCB INH FCC 'CLR ' FCB $6F FCB GRP2 FCC 'CLRA' FCB $4F FCB INH FCC 'CLRB' FCB $5F FCB INH FCC 'CLV ' FCB $0A FCB INH FCC 'CMPA' FCB $81 FCB GEN FCC 'CMPB' FCB $C1 FCB GEN FCC 'COM ' FCB $63 FCB GRP2 FCC 'COMA' FCB $43 FCB INH FCC 'COMB' FCB $53 FCB INH FCC 'CPD ' FCB $83 FCB CPD FCC 'CPX ' FCB $8C FCB XLIMM FCC 'CPY ' FCB $8C FCB YLIMM FCC 'DAA ' FCB $19 FCB INH FCC 'DEC ' FCB $6A FCB GRP2 FCC 'DECA' FCB $4A FCB INH FCC 'DECB' FCB $5A FCB INH FCC 'DES ' FCB $34 FCB INH FCC 'DEX ' FCB $09 FCB INH FCC 'DEY ' FCB $09 FCB P2INH FCC 'EORA' FCB $88 FCB GEN FCC 'EORB' FCB $C8 FCB GEN FCC 'FDIV' FCB $03 FCB INH FCC 'IDIV' FCB $02 FCB INH FCC 'INC ' FCB $6C FCB GRP2 FCC 'INCA' FCB $4C FCB INH FCC 'INCB' FCB $5C FCB INH FCC 'INS ' FCB $31 FCB INH FCC 'INX ' FCB $08 FCB INH FCC 'INY ' FCB $08 FCB P2INH FCC 'JMP ' FCB $6E FCB GRP2 FCC 'JSR ' FCB $8D FCB NIMM FCC 'LDAA' FCB $86 FCB GEN FCC 'LDAB' FCB $C6 FCB GEN FCC 'LDD ' FCB $CC FCB LIMM FCC 'LDS ' FCB $8E FCB LIMM FCC 'LDX ' FCB $CE FCB XLIMM FCC 'LDY ' FCB $CE FCB YLIMM FCC 'LSL ' FCB $68 FCB GRP2 FCC 'LSLA' FCB $48 FCB INH FCC 'LSLB' FCB $58 FCB INH FCC 'LSLD' FCB $05 FCB INH FCC 'LSR ' FCB $64 FCB GRP2 FCC 'LSRA' FCB $44 FCB INH FCC 'LSRB' FCB $54 FCB INH FCC 'LSRD' FCB $04 FCB INH FCC 'MUL ' FCB $3D FCB INH FCC 'NEG ' FCB $60 FCB GRP2 FCC 'NEGA' FCB $40 FCB INH FCC 'NEGB' FCB $50 FCB INH FCC 'NOP ' FCB $01 FCB INH FCC 'ORAA' FCB $8A FCB GEN FCC 'ORAB' FCB $CA FCB GEN FCC 'PSHA' FCB $36 FCB INH FCC 'PSHB' FCB $37 FCB INH FCC 'PSHX' FCB $3C FCB INH FCC 'PSHY' FCB $3C FCB P2INH FCC 'PULA' FCB $32 FCB INH FCC 'PULB' FCB $33 FCB INH FCC 'PULX' FCB $38 FCB INH FCC 'PULY' FCB $38 FCB P2INH FCC 'ROL ' FCB $69 FCB GRP2 FCC 'ROLA' FCB $49 FCB INH FCC 'ROLB' FCB $59 FCB INH FCC 'ROR ' FCB $66 FCB GRP2 FCC 'RORA' FCB $46 FCB INH FCC 'RORB' FCB $56 FCB INH FCC 'RTI ' FCB $3B FCB INH FCC 'RTS ' FCB $39 FCB INH FCC 'SBA ' FCB $10 FCB INH FCC 'SBCA' FCB $82 FCB GEN FCC 'SBCB' FCB $C2 FCB GEN FCC 'SEC ' FCB $0D FCB INH FCC 'SEI ' FCB $0F FCB INH FCC 'SEV ' FCB $0B FCB INH FCC 'STAA' FCB $87 FCB NIMM FCC 'STAB' FCB $C7 FCB NIMM FCC 'STD ' FCB $CD FCB NIMM FCC 'STOP' FCB $CF FCB INH FCC 'STS ' FCB $8F FCB NIMM FCC 'STX ' FCB $CF FCB XNIMM FCC 'STY ' FCB $CF FCB YNIMM FCC 'SUBA' FCB $80 FCB GEN FCC 'SUBB' FCB $C0 FCB GEN FCC 'SUBD' FCB $83 FCB LIMM FCC 'SWI ' FCB $3F FCB INH FCC 'TAB ' FCB $16 FCB INH FCC 'TAP ' FCB $06 FCB INH FCC 'TBA ' FCB $17 FCB INH FCC 'TPA ' FCB $07 FCB INH FCC 'TEST' FCB $00 FCB INH FCC 'TST ' FCB $6D FCB GRP2 FCC 'TSTA' FCB $4D FCB INH FCC 'TSTB' FCB $5D FCB INH FCC 'TSX ' FCB $30 FCB INH FCC 'TSY ' FCB $30 FCB P2INH FCC 'TXS ' FCB $35 FCB INH FCC 'TYS ' FCB $35 FCB P2INH FCC 'WAI ' FCB $3E FCB INH FCC 'XGDX' FCB $8F FCB INH FCC 'XGDY' FCB $8F FCB P2INH FCC 'BRSE' bit direct modes for FCB $12 disassembler. FCB BTBD FCC 'BRCL' FCB $13 FCB BTBD FCC 'BSET' FCB $14 FCB SETCLRD FCC 'BCLR' FCB $15 FCB SETCLRD FCB EOT End of table ********************************************** PG1 EQU $0 PG2 EQU $1 PG3 EQU $2 PG4 EQU $3 ****************** *disassem() - disassemble the opcode. ****************** *(check for page prebyte) *baseop=pc[0]; *pnorm=PG1; *if(baseop==$18) pnorm=PG2; *if(baseop==$1A) pnorm=PG3; *if(baseop==$CD) pnorm=PG4; *if(pnorm != PG1) dispc=pc+1; *else dispc=pc; (dispc points to next byte) DISASSM EQU * LDX PC address LDAA 0,X opcode LDAB #PG1 CMPA #$18 BEQ DISP2 jump if page2 CMPA #$1A BEQ DISP3 jump if page3 CMPA #$CD 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 == ($00-$5F or $8D or $8F or $CF)) * 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 #$5F BLS DIS1 jump if in range CMPA #$8D BEQ DIS1 jump if bsr CMPA #$8F BEQ DIS1 jump if xgdx CMPA #$CF 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==$8D) dissrch(opcode,REL); * if(opcode==($8F or $CF)) disrch(opcode,INH); DISPEC LDAA BASEOP CMPA #$8D BNE DISPEC1 LDAB #REL BRA DISPEC3 look for BSR opcode DISPEC1 CMPA #$8F BEQ DISPEC2 jump if XGDX opcode CMPA #$CF 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 EQU * 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 EQU * 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 $byte */ * else (class == (SETCLR or BTB)) * prntmne(); /* indexed */ * disindx(); * outspac(); * disdir(); * outspac(); * if(class == (BTB or BTBD)) * disrelad(); * return(); DISBTD EQU * 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 EQU * 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($60 <= opcode <= $7F) /* GRP2 */ * if(pnorm == (PG3 or PG4)) * disillop(); return(); * if((pnorm==PG2) and (opcode != $6x)) * disillop(); return(); * b=disrch(baseop & $6F,NULL); * if(b==0) disillop(); return(); * prntmne(); * if(opcode == $6x) * disindx(); * else * disext(); * return(); DISGRP EQU * CMPA #$7F 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 #$6F 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 #$F0 CMPA #$60 BNE DISGRP4 jump if not 6x JSR DISINDX operand(indexed) RTS DISGRP4 JSR DISEXT operand(extended) RTS *Else ($80 <= opcode <= $FF) * if(opcode == ($87 or $C7)) * disillop(); return(); * b=disrch(opcode&$CF,NULL); * if(b==0) disillop(); return(); DISNEXT EQU * CMPA #$87 a=opcode BEQ DISNEX1 CMPA #$C7 BNE DISNEX2 DISNEX1 JSR DISILLOP "illegal opcode" RTS DISNEX2 ANDA #$CF CLRB class=null JSR DISRCH TSTB BNE DISNEW jump if mne found JSR DISILLOP "illegal opcode" RTS * if(opcode&$CF==$8D) disrch(baseop,NIMM; (jsr) * if(opcode&$CF==$8F) disrch(baseop,NIMM; (sts) * if(opcode&$CF==$CF) disrch(baseop,XNIMM; (stx) * if(opcode&$CF==$83) disrch(baseop,LIMM); (subd) DISNEW LDAA BASEOP ANDA #$CF CMPA #$8D BNE DISNEW1 jump not jsr LDAB #NIMM BRA DISNEW4 DISNEW1 CMPA #$8F BNE DISNEW2 jump not sts LDAB #NIMM BRA DISNEW4 DISNEW2 CMPA #$CF BNE DISNEW3 jump not stx LDAB #XNIMM BRA DISNEW4 DISNEW3 CMPA #$83 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&$CF==$83) * if(pnorm==(PG3 or PG4)) disrch(opcode#$CF,CPD) * class=LIMM; * if((pnorm == (PG2 or PG4) and (opcode != ($Ax or $Ex))) * 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 #$CF CMPA #$83 BNE DISGEN3 jump if not #$83 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 #$B0 mask bits 6,3-0 CMPA #$A0 BEQ DISGEN5 jump if $Ax or $Ex 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&$CF,YLIMM); * else disrch(opcode&$CF,YNIMM); * if((pnorm == (PG3 or PG4)) * if(opcode != ($Ax or $Ex)) * 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 #$CF 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 #$B0 mask bits 6,3-0 CMPA #$A0 BEQ DISXLN5 jump opcode = $Ax or $Ex 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 EQU * 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 EQU * 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 EQU * JSR DISDIR output $byte 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 EQU * 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 == ($8x or $Cx)) /* immediate */ * outa('#'); * disdir(); * if(class == LIMM) * out1byt(dispc++); *elseif(baseop == ($9x or $Dx)) /* direct */ * disdir(); *elseif(baseop == ($Ax or $Ex)) /* indexed */ * disindx(); *else (baseop == ($Bx or $Fx)) /* extended */ * disext(); *return(); DISGENRL EQU * JSR PRNTMNE print mnemonic LDAA BASEOP get opcode ANDA #$B0 mask bits 6,3-0 CMPA #$80 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 #$90 BNE DISGRL3 jump not direct JSR DISDIR do direct RTS DISGRL3 CMPA #$A0 BNE DISGRL4 jump not indexed JSR DISINDX do extended RTS DISGRL4 JSR DISEXT do extended RTS ***************** *disdir() - output "$ next byte" ***************** DISDIR EQU * LDAA #'$' JSR OUTA LDX DISPC JSR OUT1BYT STX DISPC RTS ***************** *disext() - output "$ next 2 bytes" ***************** DISEXT EQU * LDAA #'$' JSR OUTA LDX DISPC JSR OUT2BSP STX DISPC RTS ***************** *disillop() - output "illegal opcode" ***************** DISMSG1 FCC 'ILLOP' FCB EOT DISILLOP EQU * PSHX LDX #DISMSG1 JSR OUTSTRG0 no cr PULX RTS ********** * help - List buffalo commands to terminal. ********** HELP EQU * LDX #HELPMSG1 JSR OUTSTRG print help screen RTS HELPMSG1 EQU * FCC 'ASM [] Line asm/disasm' FCB $0D FCC ' [/,=] Same addr, [^,-] Prev addr, [+,CTLJ] Next addr' FCB $0D FCC ' [CR] Next opcode, [CTLA,.] Quit' FCB $0D FCC 'BF [] Block fill memory' FCB $0D FCC 'BR [-][] Set up bkpt table' FCB $0D FCC 'BULK Erase EEPROM, BULKALL Erase EEPROM and CONFIG' FCB $0D FCC 'CALL [] Call subroutine' FCB $0D FCC 'GO [] Execute code at addr, PROCEED Continue execution' FCB $0D FCC 'EEMOD [ []] Modify EEPROM range' FCB $0D FCC 'LOAD, VERIFY [T] Load or verify S-records' FCB $0D FCC 'MD [ []] Memory dump' FCB $0D FCC 'MM [] or []/ Memory Modify' FCB $0D FCC ' [/,=] Same addr, [^,-,CTLH] Prev addr, [+,CTLJ,SPACE] Next addr' FCB $0D FCC ' O Compute offset, [CR] Quit' FCB $0D FCC 'MOVE [] Block move' FCB $0D FCC 'OFFSET [-] Offset for download' FCB $0D FCC 'RM [P,Y,X,A,B,C,S] Register modify' FCB $0D FCC 'STOPAT Trace until addr' FCB $0D FCC 'T [] Trace n instructions' FCB $0D FCC 'TM Transparent mode (CTLA = exit, CTLB = send brk)' FCB $0D FCC '[CTLW] Wait, [CTLX,DEL] Abort [CR] Repeat last cmd' FCB $0D FCB 4 ********** * call [] - Execute a jsr to or user *pc value. Return to monitor via rts or breakpoint. ********** *a = wskip(); *if(a != cr) * a = buffarg(); * a = wskip(); * if(a != cr) return(bad argument) * pc = shftreg; CALL JSR WSKIP BEQ CALL3 jump if no arg JSR BUFFARG JSR WSKIP BEQ CALL2 jump if cr LDX #MSG9 "bad argument" JSR OUTSTRG RTS CALL2 LDX SHFTREG STX REGS pc = *put return address on user stack *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 1=go, 0=call JMP RESTACK go to user code ********** * return() - Return here from rts after *call command. ********** RETURN PSHA save a register TPA STAA REGS+8 cc register SEI mask interrupts PULA STD REGS+6 a and b registers STX REGS+4 x register STY REGS+2 y register STS SP user stack pointer LDS PTR2 monitor stack pointer JSR REMBPS remove breakpoints JSR OUTCRLF JSR RPRINT print user registers RTS ********** * proceed - Same as go except it ignores *a breakpoint at the first opcode. Calls *runone for the first instruction only. ********** PROCEED EQU * JSR RUNONE run one instruction JSR CHKABRT check for abort CLR TMP2 flag for breakpoints INC TMP2 1=go 0=call JSR SETBPS JMP RESTACK go execute ********** * 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 BEQ GO2 jump if no arg JSR BUFFARG JSR WSKIP BEQ GO1 jump if cr LDX #MSG9 "bad argument" JSR OUTSTRG RTS GO1 LDX SHFTREG STX REGS pc = GO2 CLR TMP2 INC TMP2 1=go, 0=call JSR SETBPS JMP RESTACK go to user code ***** ** SWIIN - Breakpoints from go or call commands enter here. *Remove breakpoints, save user registers, return SWIIN EQU * swi entry point TSX user sp -> x LDS PTR2 restore monitor sp JSR SAVSTACK save user regs JSR REMBPS remove breakpoints from code LDX REGS DEX STX REGS save user pc value *if(call command) remove call return addr from user stack; TST TMP2 1=go, 0=call BNE GO3 jump if go command LDX SP remove return address INX user stack pointer INX STX SP GO3 JSR OUTCRLF print register values JSR RPRINT RTS done ********** * 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] = $3F; *Put monitor SWI vector into jump table SETBPS CLRB SETBPS1 LDX #BRKTABL LDY #PTR4 ABX ABY LDX 0,X breakpoint table entry BEQ SETBPS2 jump if 0 LDAA 0,X save user opcode STAA 0,Y LDAA #SWI JSR WRITE insert swi into code SETBPS2 ADDB #$2 CMPB #$6 BLE SETBPS1 loop 4 times LDX JSWI+1 STX PTR3 save user swi vector LDAA #$7E 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]; *Replace user's SWI vector REMBPS CLRB REMBPS1 LDX #BRKTABL LDY #PTR4 ABX ABY LDX 0,X breakpoint table entry BEQ REMBPS2 jump if 0 LDAA 0,Y JSR WRITE restore user opcode REMBPS2 ADDB #$2 CMPB #$6 BLE REMBPS1 loop 4 times LDX PTR3 restore user swi vector STX JSWI+1 RTS ********** * trace - Trace n instructions starting *at user's pc value. n is a hex number less than *$FF (defaults to 1). ********** *a = wskip(); *if(a != cr) * a = buffarg(); a = wskip(); * if(a != cr) return(bad argument); * countt1 = n TRACE CLR TMP4 INC TMP4 default count=1 CLR CHRCNT set up for display JSR WSKIP BEQ TRACE2 jump if cr JSR BUFFARG JSR WSKIP BEQ TRACE1 jump if cr LDX #MSG9 "bad argument" JSR OUTSTRG RTS TRACE1 LDAA SHFTREG+1 n STAA TMP4 *Disassemble the line about to be traced TRACE2 EQU * LDAB TMP4 PSHB LDX REGS STX PTR1 pc value for disass JSR DISASSM PULB STAB TMP4 *run one instruction *rprint(); *while(count > 0) continue trace; JSR RUNONE JSR CHKABRT check for abort JSR TABTO print registers for JSR RPRINT result of trace DEC TMP4 BEQ TRACDON quit if count=0 TRACE3 JSR OUTCRLF BRA TRACE2 TRACDON RTS ********** * stopat - Trace instructions until *is reached. ********** *if((a=wskip) != cr) * a = buffarg(); a = wskip(); * if(a != cr) return(bad argument); *else return(bad argument); STOPAT EQU * JSR WSKIP BEQ STOPGO jump if cr - no argument JSR BUFFARG JSR WSKIP BEQ STOPAT1 jump if cr LDX #MSG9 "bad argument" JSR OUTSTRG RTS STOPAT1 TST COUNT BEQ STOPGO jump if no argument LDX SHFTREG STX PTRMEM update "current location" *while(!(ptrmem <= userpc < ptrmem+10)) runone(); *rprint(); STOPGO LDD REGS userpc CPD PTRMEM BLO STOPNEXT if(userpc < ptrmem) runone LDD PTRMEM ADDD #10 CPD REGS BHI STOPDON quit if ptrmem+10 > userpc STOPNEXT JSR RUNONE JSR CHKABRT check for abort BRA STOPGO STOPDON JSR OUTCRLF JSR RPRINT result of trace RTS done ************************* * runone - This routine is used by the trace and * execute commands to run one only one user instruction. * Control is passed to the user code via an RTI. OC5 * is then used to trigger an XIRQ as soon as the first user * opcode is fetched. Control then returns to the monitor * through XIRQIN. * Externally, the OC5 pin must be wired to the XIRQ pin. ************************ * Disable oc5 interrupts * Put monitor XIRQ vector into jump table * Unmask x bit in user ccr * Setup OC5 to go low when first user instruction executed RUNONE EQU * LDAA #$7E put "jmp xirqin" in jump table STAA JTOC5 LDX #XIRQIN STX JXIRQ+1 LDAA REGS+8 x bit will be cleared when ANDA #$BF rti is executed below STAA REGS+8 LDAB #87 cycles to end of rti LDX TCNT ABX 3~ \ STX TOC5 oc5 match register 5~ \ LDAA TCTL1 4~ \ ANDA #$FE set up oc5 low on match 2~ \ STAA TCTL1 enable oc5 interrupt 4~ / 86~ ** RESTACK - Restore user stack and RTI to user code. * This code is the pathway to execution of user code. *(Force extended addressing to maintain cycle count) *Restore user stack and rti to user code RESTACK EQU * 68~ STS >PTR2 save monitor sp LDS >SP user 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 RTI ** Return here from run one line of user code. XIRQIN EQU * TSX user sp -> x LDS PTR2 restore monitor sp ** SAVSTACK - Save user's registers. * On entry - x points to top of user stack. SAVSTACK EQU * LDAA 0,X STAA REGS+8 user 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 user stack pointer LDAA TCTL1 force oc5 pin high which ORAA #$03 is tied to xirq line STAA TCTL1 LDAA #$08 STAA CFORC RTS ********** * 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 EQU * LDAA HOSTDEV CMPA #$03 BEQ TXBDU jump if duartb is host TXBSCI LDX #SCCR2 sci is host BSET 0,X,#01 set send break bit BSR TXBWAIT BCLR 0,X,#01 clear send break bit BRA TXB1 TXBDU LDX #PORTB duart host port LDAA #$60 start break cmd STAA 2,X port b command register BSR TXBWAIT LDAA #$70 stop break cmd STAA 2,X port b command register TXB1 LDAA #$0D JSR HOSTOUT send carriage return LDAA #$0A JSR HOSTOUT send linefeed RTS TXBWAIT LDY #$6F9B 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. * tmp3 is used as an error indication, 0=no errors, * 1=receiver, 2=rom error, 3=checksum error. ********** VERIFY CLR TMP2 INC TMP2 TMP2=1=verify BRA LOAD1 LOAD CLR TMP2 0=load *a=wskip(); *if(a = cr) goto transparent mode; *if(t option) hostdev = iodev; LOAD1 EQU * CLR TMP3 clear error flag JSR WSKIP BNE LOAD2 JMP HOST go to host if no args LOAD2 JSR UPCASE CMPA #'T' look for t option BNE LOAD3 jump not t option JSR INCBUFF JSR READBUFF get next character JSR DECBUFF CMPA #$0D BNE LOAD3 jump if not t option CLR AUTOLF LDAA IODEV STAA HOSTDEV set host port = terminal BRA LOAD10 go wait for s1 records *else while(not cr) * read character from input buffer; * send character to host; LOAD3 CLR AUTOLF JSR HOSTCO connect sci (evb board) JSR HOSTINIT initialize host port LOAD4 JSR READBUFF get next char JSR INCBUFF PSHA save char JSR HOSTOUT output to host JSR OUTPUT echo to terminal PULA CMPA #$0D BNE LOAD4 jump if not cr *repeat: /* look for s records */ * if(hostdev != iodev) check abort; * a = hostin(); * if(a = 'S') * a = hostin; * if(a = '1') * checksum = 0; * get byte count in b; * get base address in x; * while(byte count > 0) * byte(); * x++; b--; * if(tmp3=0) /* no error */ * if(load) x[0] = shftreg+1; * if(x[0] != shftreg+1) * tmp3 = 2; /* rom error */ * ptr3 = x; /* save address */ * if(tmp3 = 0) do checksum; * if(checksum err) tmp3 = 3; /* checksum error */ ** Look for s-record header LOAD10 EQU * LDAA HOSTDEV CMPA IODEV BEQ LOAD11 jump if hostdev=iodev JSR CHKABRT check for abort LOAD11 JSR HOSTIN read host TSTA BEQ LOAD10 jump if no input CMPA #'S' BNE LOAD10 jump if not S LOAD12 JSR HOSTIN read host TSTA BEQ LOAD12 jump if no input CMPA #'9' BEQ LOAD90 jump if S9 record CMPA #'1' BNE LOAD10 jump if not S1 CLR TMP4 clear checksum ** Get Byte Count and Starting Address JSR BYTE LDAB SHFTREG+1 SUBB #$2 b = byte count JSR BYTE JSR BYTE PSHB save byte count LDD SHFTREG ADDD LDOFFST add offset XGDX x = address+offset PULB restore byte count DEX condition for loop ** Get and Store Incoming Data Byte LOAD20 JSR BYTE get next byte INX DECB check byte count BEQ LOAD30 if b=0, go do checksum TST TMP3 BNE LOAD10 jump if error flagged TST TMP2 BNE LOAD21 jump if verify LDAA SHFTREG+1 JSR WRITE load only LOAD21 CMPA 0,X verify ram location BEQ LOAD20 jump if ram ok LDAA #$02 STAA TMP3 indicate rom error STX PTR3 save error address BRA LOAD20 finish download ** Get and Test Checksum LOAD30 TST TMP3 BNE LOAD10 jump if error already LDAA TMP4 INCA do checksum BEQ LOAD10 jump if s1 record okay LDAA #$03 STAA TMP3 indicate checksum error BRA LOAD10 * if(a = '9') * read rest of record; * if(tmp3=2) return("[ptr3]"); * if(tmp3=1) return("rcv error"); * if(tmp3=3) return("checksum err"); * else return("done"); LOAD90 JSR BYTE LDAB SHFTREG+1 b = byte count LOAD91 JSR BYTE DECB BNE LOAD91 loop until end of record LDAB #$64 LOAD91A JSR DLY10MS delay 1 sec -let host finish DECB BNE LOAD91A JSR INPUT clear comm device LDD #$7E0D put dummy command in inbuff STD INBUFF INC AUTOLF turn on autolf JSR TARGCO disconnect sci (evb) LDX #MSG11 "done" default msg LDAA TMP3 CMPA #$02 BNE LOAD92 jump not rom error LDX #PTR3 JSR OUT2BSP address of rom error BRA LOAD95 LOAD92 CMPA #$01 BNE LOAD93 jump not rcv error LDX #MSG14 "rcv error" BRA LOAD94 LOAD93 CMPA #$03 BNE LOAD94 jump not checksum error LDX #MSG12 "checksum error" LOAD94 JSR OUTSTRG LOAD95 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 ********** * offset [] * Specify offset to be added to s-record address when * downloading from the host. * OFFSET -show the current offset * OFFSET -current offset = data * OFFSET - -current offset = 0 - data ********** *if() then offset = data; *print(offset); OFFSET EQU * CLR TMP4 minus indicator JSR WSKIP BEQ OFFST3 jump if cr (no argument) CMPA #'-' BNE OFFST1 jump not - INC TMP4 set minus sign flag JSR INCBUFF move buffer pointer JSR WSKIP OFFST1 JSR BUFFARG read argument TST COUNT BEQ OFFSTER jump if bad argument JSR WSKIP BNE OFFSTER jump if not cr LDD SHFTREG get offset value TST TMP4 BEQ OFFST2 jump if positive LDD #$0000 negative - sub from 0 SUBD SHFTREG OFFST2 STD LDOFFST OFFST3 JSR OUTCRLF display current offset LDX #LDOFFST JSR OUT2BSP RTS OFFSTER LDX #MSG9 "bad argument" JSR OUTSTRG 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 #$D 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 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 #$D BNE REG5 jump if not cr REG9 RTS * Equates JPORTD EQU $08 JDDRD EQU $09 JBAUD EQU $2B JSCCR1 EQU $2C JSCCR2 EQU $2D JSCSR EQU $2E JSCDAT EQU $2F * ************ * xboot [ []] - Use SCI to talk to an 'hc11 in * boot mode. Downloads bytes from addr1 thru addr2. * Default addr1 = $C000 and addr2 = $C0ff. * * IMPORTANT: * if talking to an 'A8 or 'A2: use either default addresses or ONLY * addr1 - this sends 256 bytes * if talking to an 'E9: include BOTH addr1 and addr2 for variable * length ************ *Get arguments *If no args, default $C000 BOOT JSR WSKIP BNE BOT1 jump if arguments LDX #$C0FF addr2 default STX PTR5 LDY #$C000 addr1 default BRA BOT2 go - use default address *Else get arguments BOT1 JSR BUFFARG TST COUNT BEQ BOTERR jump if no address LDY SHFTREG start address (addr1) JSR WSKIP BNE BOT1A go get addr2 STY PTR5 default addr2... LDD PTR5 ...by taking addr1... ADDD #$FF ...and adding 255 to it... STD PTR5 ...for a total download of 256 BRA BOT2 continue * BOT1A JSR BUFFARG TST COUNT BEQ BOTERR jump if no address LDX SHFTREG end address (addr2) STX PTR5 JSR WSKIP BNE BOTERR go use addr1 and addr2 BRA BOT2 * BOTERR LDX #MSG9 "bad argument" JSR OUTSTRG RTS *Boot routine BOT2 LDAB #$FF control character ($ff -> download) JSR BTSUB set up SCI and send control char * initializes X as register pointer *Download block BLOP LDAA 0,Y STAA JSCDAT,X write to transmitter BRCLR JSCSR,X,#80,* wait for TDRE CPY PTR5 if last... BEQ BTDONE ...quit INY else... BRA BLOP ...send next BTDONE RTS ************************************************ *Subroutine * btsub - sets up SCI and outputs control character * On entry, B = control character * On exit, X = $1000 * A = $0C *************************** BTSUB EQU * LDX #$1000 to use indexed addressing LDAA #$02 STAA JPORTD,X drive transmitter line STAA JDDRD,X high CLR JSCCR2,X turn off XMTR and RCVR LDAA #$22 BAUD = /16 STAA JBAUD,X LDAA #$0C TURN ON XMTR & RCVR STAA JSCCR2,X STAB JSCDAT,X BRCLR JSCSR,X,#80,* wait for TDRE RTS *********** * TILDE - This command is put into the combuff by the * load command so that extraneous carriage returns after * the load will not hang up. TILDE RTS ****************** * * EVBTEST - This routine makes it a little easier * on us to test this board. * ****************** EVBTEST LDAA #$FF STAA $1000 Write ones to port A CLR AUTOLF Turn off auto lf JSR HOSTCO Connect host JSR HOSTINIT Initialize host LDAA #$7f JSR HOSTOUT Send Delete to Altos LDAA #$0d 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 $04 STAA 0,X INX next character INY BRA LOOP DONE CLR TMP2 Set load vs. verify JSR LOAD3 Jmp into middle of load LDS #STACK Reset Stack JMP $C0B3 Jump to Downloaded code MSGEVB FCC /cat evbtest.out/ FCB $0D FCB $04 *** Jump table *** ORG ROMBS+$1F7C .WARMST JMP MAIN warm start .BPCLR JMP BPCLR clear breakpoint table .RPRINT JMP RPRINT display user registers .HEXBIN JMP HEXBIN convert ascii hex char to binary .BUFFAR JMP BUFFARG build hex argument from buffer .TERMAR JMP TERMARG read hex argument from terminal .CHGBYT JMP CHGBYT modify memory at address in x .READBU JMP READBUFF read character from buffer .INCBUF JMP INCBUFF increment buffer pointer .DECBUF JMP DECBUFF decrement buffer pointer .WSKIP JMP WSKIP find non-whitespace char in buffer .CHKABR JMP CHKABRT check for abort from terminal ORG ROMBS+$1FA0 .UPCASE JMP UPCASE convert to upper case .WCHEK JMP WCHEK check for white space .DCHEK JMP DCHEK check for delimeter .INIT JMP INIT initialize i/o device .INPUT JMP INPUT low level input routine .OUTPUT JMP OUTPUT low level output routine .OUTLHL JMP OUTLHLF display top 4 bits as hex digit .OUTRHL JMP OUTRHLF display bottom 4 bits as hex digit .OUTA JMP OUTA output ascii character in A .OUT1BY JMP OUT1BYT display the hex value of byte at X .OUT1BS JMP OUT1BSP out1byt followed by space .OUT2BS JMP OUT2BSP display 2 hex bytes at x and a space .OUTCRL JMP OUTCRLF carriage return, line feed to terminal .OUTSTR JMP OUTSTRG display string at X (term with $04) .OUTST0 JMP OUTSTRG0 outstrg with no initial carr ret .INCHAR JMP INCHAR wait for and input a char from term .VECINT JMP VECINIT initialize RAM vector table ORG ROMBS+$1FD6 *** Vectors *** VSCI FDB JSCI VSPI FDB JSPI VPAIE FDB JPAIE VPAO FDB JPAO VTOF FDB JTOF VTOC5 FDB JTOC5 VTOC4 FDB JTOC4 VTOC3 FDB JTOC3 VTOC2 FDB JTOC2 VTOC1 FDB JTOC1 VTIC3 FDB JTIC3 VTIC2 FDB JTIC2 VTIC1 FDB JTIC1 VRTI FDB JRTI VIRQ FDB JIRQ VXIRQ FDB JXIRQ VSWI FDB JSWI VILLOP FDB JILLOP VCOP FDB JCOP VCLM FDB JCLM VRST FDB BUFFALO END