* BUFFALO
* "Bit User's Fast Friendly Aid to Logical Operation"
*
* Rev 2.0 - 4/23/85 - added disassembler.
* - variables now PTRn and TMPn.
* Rev 2.1 - 4/29/85 - added byte erase to chgbyt routine.
* Rev 2.2 - 5/16/85 - added hooks for evb board - acia
* drivers, init and host routines.
* 7/8/85 - fixed dump wraparound problem.
* 7/10/85 - added evm board commands.
* - added fill instruction.
* 7/18/85 - added jump to EEPROM.
* Rev 2.3 - 8/22/85 - call targco to disconnect sci from host
* in reset routine for evb board.
* 10/3/85 - modified load for download through terminal.
* Rev 2.4 - 7/1/86 - Changed DFLOP address to fix conflicts with
* EEPROM. (was at A000)
* Rev 2.5 - 9/8/86 - Modified to provide additional protection from
* program run-away on power down. Also fixed bugs
* in MM and MOVE. Changed to 1 stop bit from 2.
*
****************************************************
* Although the information contained herein, *
* as well as any information provided relative *
* thereto, has been carefully reviewed and is *
* believed accurate, Motorola assumes no *
* liability arising out of its application or *
* use, neither does it convey any license under *
* its patent rights nor the rights of others. *
****************************************************
***************
* EQUATES *
***************
RAMBS EQU $0000 start of ram
REGBS EQU $1000 start of registers
ROMBS EQU $E000 start of rom
PORTE EQU REGBS+$0A port e
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
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 $36
*** Buffalo ram space ***
RMB 20 user stack area
USTACK RMB 30 monitor stack area
STACK RMB 1
INBUFF RMB BUFFLNG input buffer
ENDBUFF EQU *
COMBUFF RMB 8 command buffer
SHFTREG RMB 2 input shift register
BRKTABL RMB 8 breakpoint table
REGS RMB 9 user's pc,y,x,a,b,c
SP RMB 2 user's sp
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
PTRMEM RMB 2 current memory location
*** Buffalo variables - used by: ***
PTR0 RMB 2 main,readbuff,incbuff,AS
PTR1 RMB 2 main,BR,DU,MO,AS
PTR2 RMB 2 DU,GO,MO,AS
PTR3 RMB 2 HO,MO,AS
PTR4 RMB 2 GO,AS
PTR5 RMB 2 AS
PTR6 RMB 2 GO,AS
PTR7 RMB 2 GO,AS
TMP1 RMB 1 main,hexbin,buffarg,termarg
TMP2 RMB 1 GO,HO,AS
TMP3 RMB 1 AS
TMP4 RMB 1 GO,HO,ME,AS
*** 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 $B600 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
LDS #STACK monitor stack pointer
JSR VECINIT
LDX #USTACK
STX SP default user stack
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:
** <cmd>[<wsp><arg><wsp><arg>...]<cr>
** [] implies contents optional.
** <wsp> means whitespace character (space,comma,tab).
** <cmd> = command string of 1-8 characters.
** <arg> = Argument particular to the command.
** <cr> = Carriage return signifying end of input string.
*****************
* Prompt user
*do
* a=input();
* if(a==(cntlx or del)) continue;
* elseif(a==backspace)
* b--;
* if(b<0) b=0;
* else
* if(a==cr && buffer empty)
* repeat last command;
* else put a into buffer;
* check if buffer full;
*while(a != (cr or /)
MAIN LDS #STACK initialize sp every time
CLR AUTOLF
INC AUTOLF auto cr/lf = on
JSR OUTCRLF
LDAA #PROMPT prompt user
JSR OUTPUT
CLRB
MAIN1 JSR INCHAR read terminal
LDX #INBUFF
ABX pointer into buffer
CMPA #CTLX
BEQ MAIN jump if cntl X
CMPA #DEL
BEQ MAIN jump if del
CMPA #$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
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;
* if(((x) != a) && (x == eeprom location))
* if((x) != $FF) byte erase (x);
* if(a != $FF) program(x) = a);
* if((x) != a) error(ROM)
*return;
CHGBYT TST COUNT
BEQ CHGBYT4 jump if shftreg empty
LDAA SHFTREG+1
STAA 0,X attempt to write
LDAA 0,X
CMPA SHFTREG+1
BEQ CHGBYT3 jump if it worked
CPX #CONFIG
BEQ CHGBYT1 jump if config reg
CPX #$B600
BLO CHGBYT3 jump if not EE
CPX #$B7FF
BHI CHGBYT3 jump if not EE
CHGBYT1 EQU *
LDAA 0,X
CMPA #$FF
BEQ CHGBYT2 jump if already erased
LDAA #$16 do byte erase
STAA PPROG
LDAA #$FF
STAA 0,X
LDAA #$17
BNE ACL1
CLRA fail safe
ACL1 STAA PPROG
BSR CHGWAIT
LDAA #$00
STAA PPROG end of byte erase
CHGBYT2 EQU *
LDAA SHFTREG+1
CMPA #$FF
BEQ CHGBYT3 jump if no need to program
LDAA #$02 do byte program
STAA PPROG
LDAA SHFTREG+1
STAA 0,X
LDAA #$03
BNE ACL2
CLRA fail safe
ACL2 STAA PPROG
BSR CHGWAIT
LDAA #$00
STAA PPROG end of byte program
CHGBYT3 EQU *
LDAA ,X
CMPA SHFTREG+1
BEQ CHGBYT4
PSHX
LDX #MSG6 "rom"
JSR OUTSTRG
JSR OUTCRLF
PULX
CHGBYT4 EQU *
RTS
CHGWAIT EQU * delay 10 ms at E = 2MHz
PSHX
LDX #$0D06
CHGWAIT1 DEX
BNE CHGWAIT1
PULX
RTS
*****************
* READBUFF() - Read the character in INBUFF
* pointed at by ptrbuff into A. Returns ptrbuff
* unchanged.
*****************
READBUFF PSHX
LDX PTR0
LDAA 0,X
PULX
RTS
*****************
* INCBUFF(), DECBUFF() - Increment or decrement
* ptrbuff.
*****************
INCBUFF PSHX
LDX PTR0
INX
BRA INCDEC
DECBUFF PSHX
LDX PTR0
DEX
INCDEC STX PTR0
PULX
RTS
*****************
* WSKIP() - Read from the INBUFF until a
* non whitespace (space, comma, tab) character
* is found. Returns ptrbuff pointing to the
* first non-whitespace character and a holds
* that character.
*****************
WSKIP JSR READBUFF read character
JSR WCHEK
BNE WSKIP1 jump if not wspc
JSR INCBUFF move pointer
BRA WSKIP loop
WSKIP1 RTS
*****************
* WCHEK(a) - Returns z=1 if a holds a
* whitespace character, else z=0.
*****************
WCHEK CMPA #$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.
**********
OUTPUT EQU *
PSHA save registers
PSHB
PSHX
LDAB IODEV
BNE OUTPUT1 jump not sci
JSR OUTSCI write sci
BRA OUTPUT4
OUTPUT1 CMPB #$01
BNE OUTPUT4 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
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 rdrf
BEQ INUART1 jump if no data
LDAA 3,X read data
ANDA #$7F to mask parity
INUART1 RTS
**********
* OUTUART(port) - Output the character in a.
* if autolf=1, transmits cr or lf as crlf.
**********
OUTUART TST AUTOLF
BEQ OUTUART2 jump if no autolf
BSR OUTUART2
CMPA #$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
BEQ INSCI1 jump if rdrf=0
LDAA SCDAT read data register
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.
**********
INACIA LDX #ACIA
LDAA 0,X status
PSHA
ANDA #$70 check pe, ov, fe
PULA
BEQ INACIA1 jump - no error
BSR ONACIA reinitialize and try again
BRA INACIA
INACIA1 LSRA check rdrf
BCS INACIA2 jump if data
CLRA return(no data)
RTS
INACIA2 LDAA 1,X read data
ANDA #$7F mask parity
RTS
**********
* OUTACIA - Output A to acia. IF autolf = 1,
* cr or lf sent as crlf.
**********
OUTACIA BSR OUTACIA3 output char
TST AUTOLF
BEQ OUTACIA2 jump no autolf
CMPA #$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.
*
* 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
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
**********
* 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 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 7
FCC 'PROCEED'
FDB #PROCEED
FCB 8
FCC 'REGISTER'
FDB #REGISTER
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
*
*** 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 -1
*******************
*** TEXT TABLES ***
MSG1 FCC 'BUFFALO 2.5 (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 available'
FCB EOT
MSG11 FCC 'done'
FCB EOT
MSG12 FCC 'checksum error'
FCB EOT
MSG13 FCC 'error addr '
FCB EOT
**********
* break [-][<addr>] . . .
* 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 <addr> Inserts <addr>.
* break -<addr> Deletes <addr>.
* break - Clears all entries.
**********
* while 1
* a = wskip();
* switch(a)
* case(cr):
* bprint(); return;
BREAK JSR WSKIP
CMPA #$0D
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
LDAA 0,X
LDAB #SWI
STAB 0,X
LDAB 0,X
STAA 0,X
CMPB #SWI
BEQ BRKDEF2 jump if writes ok
STX PTR1 save address
LDX #MSG6 "ROM-"
JSR OUTSTRG
LDX #PTR1
JSR OUT2BSP print address
JSR BPRINT
RTS
BRKDEF2 CLR SHFTREG
CLR SHFTREG+1
PSHX
JSR BPSRCH look for 0 entry
PULX
TSTB
BPL BRKDEF3 jump if table not full
LDX #MSG4 "full"
JSR OUTSTRG
JSR BPRINT
RTS
BRKDEF3 LDY #BRKTABL
ABY
STX 0,Y put new entry in
JMP BREAK do next argument
**********
* bprint() - print the contents of the table.
**********
BPRINT JSR OUTCRLF
LDX #BRKTABL
LDAB #4
BPRINT1 JSR OUT2BSP
DECB
BGT BPRINT1 loop 4 times
RTS
**********
* bpsrch() - search table for address in
* shftreg. Returns b = index to entry or
* b = -1 if not found.
**********
*for(b=0; b=6; b=+2)
* x[] = brktabl + b;
* if(x[0] = shftreg)
* return(b);
*return(-1);
BPSRCH CLRB
BPSRCH1 LDX #BRKTABL
ABX
LDX 0,X get table entry
CPX SHFTREG
BNE BPSRCH2 jump if no match
RTS
BPSRCH2 INCB
INCB
CMPB #$6
BLE BPSRCH1 loop 4 times
LDAB #$FF
RTS
**********
* bulk - Bulk erase the eeprom except the
* config register.
**********
BULK CLR TMP2
BRA BULK1
**********
* bulkall - Bulk erase the eeprom and the
* config register.
**********
BULKALL CLR TMP2
INC TMP2
*Set up PPROG register for erase
BULK1 PSHA
LDAA #$06
STAA PPROG set eelat, erase bits
*If (EE only) write to $b600
*Else write to config register
LDAA #$FF
TST TMP2
BNE BULK2 jump if config
STAA $B600 write to $b600
BRA BULK3
BULK2 STAA CONFIG
BULK3 EQU *
*Start erasing
LDAA #$07
BNE ACL3
CLRA fail safe
ACL3 STAA PPROG
*Delay for 10 ms at E = 2 MHz
PSHX
LDX #$0D06 6~ * 3334 = 20,004 * 0.5 MHz
BULKDLY DEX 2~
BNE BULKDLY 3~
PULX
*Stop programming
CLR PPROG
PULA
RTS
**********
* dump [<addr1> [<addr2>]] - Dump memory
* in 16 byte lines from <addr1> to <addr2>.
* 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
CMPA #$D
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
CMPA #$D
BEQ DUMP1 jump - 1 argument
JSR BUFFARG read argument
TST COUNT
BEQ DUMPERR jump if no argument
JSR WSKIP
CMPA #$0D
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
**********
* fill <addr1> <addr2> [<data>] - 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
CMPA #$0D
BEQ FILL1 jump if default data
JSR BUFFARG
TST COUNT
BEQ FILLERR jump if no argument
JSR WSKIP
CMPA #$0D
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
STAA 0,X
CMPA 0,X
BNE FILLBAD jump if no write
CPX PTR2
BEQ FILL2 quit yet?
INX
STX PTR1
BRA FILL1 loop
FILL2 RTS
FILLERR LDX #MSG9 "bad argument"
JSR OUTSTRG
RTS
FILLBAD LDX #MSG6 "rom -"
JSR OUTSTRG
LDX #PTR1
JSR OUT2BSP
RTS
**********
* call [<addr>] - Execute a jsr to addr or
*user's pc value. Return to monitor by rts
*or breakpoint.
**********
*a = wskip();
*if(a != cr)
* a = buffarg();
* a = wskip();
* if(a != cr) return(bad argument)
* pc = shftreg;
CALL JSR WSKIP
CMPA #$D
BEQ CALL3 jump if no arg
JSR BUFFARG
JSR WSKIP
CMPA #$D
BEQ CALL2 jump if cr
LDX #MSG9 "bad argument"
JSR OUTSTRG
RTS
CALL2 LDX SHFTREG
STX REGS pc = <addr>
*user_stack[0] = return_to_monitor;
*setbps();
*restack(); /* restack and go*/
CALL3 LDX SP
DEX user stack pointer
LDD #RETURN return address
STD 0,X
DEX
STX SP new user stack pointer
JSR SETBPS
CLR TMP2 flag for breakpoints
JMP RESTACK executes an rti
**********
* return() - Return here from rts after
*call command.
**********
RETURN PSHA save a register
TPA
STAA REGS+8 cc register
PULA
STD REGS+6 a and b registers
STX REGS+4 x register
STY REGS+2 y register
STS SP user stack pointer
LDS #STACK monitor stack pointer
JSR REMBPS remove breakpoints
JSR OUTCRLF
JSR RPRINT print user registers
JMP MAIN
**********
* go [<addr>] - Execute starting at <addr> or
*user's pc value. Executes an rti to user code.
*Returns to monitor via an swi through swiin.
**********
*a = wskip();
*if(a != cr)
* a = buffarg();
* a = wskip();
* if(a != cr) return(bad argument)
* pc = shftreg;
*setbps();
*restack(); /* restack and go*/
GO JSR WSKIP
CMPA #$0D
BEQ GO2 jump if no arg
JSR BUFFARG
JSR WSKIP
CMPA #$0D
BEQ GO1 jump if cr
LDX #MSG9 "bad argument"
JSR OUTSTRG
RTS
GO1 LDX SHFTREG
STX REGS pc = <addr>
GO2 CLR TMP2 flag for breakpoints
INC TMP2 (1=go, 0=call)
JSR SETBPS
JMP RESTACK execute an rti
**********
* swiin() - return from SWI. Set up
*stack pointers, save user registers, and
*return to main.
**********
SWIIN TSX swi entry point
LDS #STACK
JSR SAVSTACK save user regs
LDX REGS
DEX
STX REGS save user pc
LDX PTR4 restore user swi vector
STX JSWI+1
*if(flagt1 = 0) remove return addr from stack;
TST TMP2 0=call, 1=go
BNE GO3 jump if go command
LDX SP remove return address
INX
INX
STX SP
GO3 JSR OUTCRLF print register values
JSR RPRINT
JSR REMBPS
JMP MAIN return to monitor
* (sp destroyed above)
**********
* proceed - Same as go except it ignores
*a breakpoint at the first opcode. Calls
*trace once and the go.
**********
PROCEED CLR TMP2 flag for breakpoints
INC TMP2 0=trace, 1=proceed
JMP TRACE3
**********
* trace <n> - Trace n instructions starting
*at user's pc value. n is a hex number less than
*$FF (defaults to 1).
**********
*countt1 = 1
*a = wskip();
*if(a != cr)
* a = buffarg(); a = wskip();
* if(a != cr) return(bad argument);
* countt1 = n
TRACE CLR TMP4
INC TMP4 default countt1 = 1
CLR TMP2 0 = trace
JSR WSKIP
CMPA #$0D
BEQ TRACE2 jump if cr
JSR BUFFARG
JSR WSKIP
CMPA #$0D
BEQ TRACE1 jump if cr
LDX #MSG9 "bad argument"
JSR OUTSTRG
RTS
TRACE1 LDAA SHFTREG+1 n
STAA TMP4
*Print opcode
TRACE2 JSR OUTCRLF
LDX #MSG5 "op-"
JSR OUTSTRG
LDX REGS
JSR OUT1BSP opcode
*Save user OC5 regs, setup monitor OC5 regs
TRACE3 LDAA TCTL1
STAA PTR2 save user mode/level
ANDA #$FC
STAA TCTL1 disable oc5 output
LDAA TMSK1
STAA PTR2+1 save user int masks
CLR TMSK2 disable tof and pac ints
*Put monitor TOC5 vector into jump table
LDX JTOC5+1
STX PTR4 save user's vector
LDAA #$7E jmp opcode
STAA JTOC5
LDX #TRACEIN
STX JTOC5+1 monitor toc5 vector
*Unmask i bit in user ccr
LDAA REGS+8 user ccr
ANDA #$EF clear i bit
STAA REGS+8
*Arm OC5 interrupt
LDAB #87 cycles to end of rti
LDX TCNT timer count value
##### To see the rest of this file, please download it #####