	PROCESSOR 68HC11

*                  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	$BE00      start of eeprom  HC11F1
DENDEE	EQU	$BFFF      end of eeprom    HC11F1
***
APORT   EQU	REGBS+$00  port a
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
***  HC11F1 EXTRA	EQUATES
CSCTL	EQU	REGBS+$5D  chip select control
CSGADR	EQU	REGBS+$5E  general purpose cs
CSGSIZ	EQU	REGBS+$5F  chip select size
***
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
CS5D	EQU	$05	CSPROG @ $8OOO-$FFFF
CS5E	EQU	$00	CSGEN  @ $0000
CS5F	EQU	$01	CSGSIZ = 32K BYTES
* original values
*CS5D	EQU	$07	CSPROG @ $EOOO-$FFFF
*CS5E	EQU	$C0	CSGEN  @ $C000
*CS5F	EQU	$03	CSGSIZ = 8K BYTES

***************
*     RAM     *
***************
	RSEG.z	BUFF_RAM
*** 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
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

	RSEG.z	BUFF_RAM2

*****************
*
* ROM starts here *
*
*****************

	RSEG	CODE

*****************
**  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
**********************
* HC11F1 EXTRA INITS *
**********************
	LDAA	#CS5D
	STAA	CSCTL
	LDAA	#CS5E
	STAA	CSGADR
	LDAA	#CS5F
	STAA	CSGSIZ
*********************
	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    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

*****************
**  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     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    CLR  TMP1        Enable "/" command
	CLR  SHFTREG
	CLR  SHFTREG+1
	CLRB
	LDX  #INBUFF     ptrbuff[] = inbuff[]
	STX  PTR0
	JSR  WSKIP       find first char

*while((a=readbuff) != (cr or wspace))
*     upcase(a);
*     buffptr[b] = a
*     b++
*     if (b > 8) error(too long);
*     if(a == "/")
*          if(enabled) mslash();
*          else error(command?);
*     else hexbin(a);

COMM1    JSR  READBUFF  read from buffer
	LDX  #COMBUFF
	ABX
	JSR  UPCASE    convert to upper case
	STAA ,X        put in command buffer
	CMPA #$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    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    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   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  PSHB
	LDAB #$02
	STAB PPROG
	STAA 0,X
	LDAB #$03
	BRA  EEPROG
***
EEBYTE  PSHB
	LDAB #$16
	STAB PPROG
	LDAB #$FF
	STAB 0,X
	LDAB #$17
	BRA  EEPROG
***
EEBULK  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 PSHX	  delay 10ms at E = 2MHz
	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     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    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   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 f0OČ+Jšary
*           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   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  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 [-][<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
	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    LDX  STREE
	BRA  BULK1
BULKALL LDX  #CONFIG
BULK1   LDAA #$FF
	JSR  EEBULK
	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
	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 [<addr1> [<addr2>]]
* Modifies the eeprom address range.
*  EEMOD                 -show ee address range
*  EEMOD <addr1>         -set range to addr1 -> addr1+2k
*  EEMOD <addr1> <addr2> -set range to addr1 -> addr2
**********
*if(<addr1>)
*    stree = addr1;
*    endee = addr1 + 2k bytes;
*if(<addr2>)
*    endee = addr2;
*print(stree,endee);
EEMOD    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 <addr1> <addr2> [<data>]  - Block fill
*memory from addr1 to addr2 with data.  Data
*defaults to $FF.
**********
*get addr1 and addr2
FILL    JSR  WSKIP
	JSR  BUFFARG
	TST  COUNT
	BEQ  FILLERR    jump if no argument
	JSR  WCHEK
	BNE  FILLERR    jump if bad argument
	LDX  SHFTREG
	STX  PTR1       address1
	JSR  WSKIP
	JSR  BUFFARG
	TST  COUNT
	BEQ  FILLERR    jump if no argument
	JSR  DCHEK
	BNE  FILLERR    jump if bad argument
	LDX  SHFTREG
	STX  PTR2       address2

*Get data if it exists
	LDAA #$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   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 LDX  #PTR1     output bad address
	JSR  OUT2BSP
	RTS



*******************************************
*   MEMORY [<addr>]
*   [<addr>]/
* Opens memory and allows user to modify the
*contents at <addr> or the last opened location.
*    Subcommands:
* [<data>]<cr>       - Close current location and exit.
* [<data>]<lf><+>    - Close current and open next.
* [<data>]<^><-><bs> - Close current and open previous.
* [<data>]<sp>       - Close current and open next.
* [<data>]</><=>     - Reopen current location.
*     The contents of the current location is only
*  changed if valid data is entered before each
*  subcommand.
* [<addr>]O - Compute relative offset from current
*     location to <addr>.  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 <src1> <src2> [<dest>]  - move
*block at <src1> to <src2> to <dest>.
*  Moves block 1 byte up if no <dest>.
**********
*a = buffarg();
*if(countu1 = 0) return(bad argument);
*if( !wchek(a) ) return(bad argument);
*ptr1 = shftreg;         /* src1 */

MOVE     JSR  BUFFARG
	TST  COUNT
	BEQ  MOVERR    jump if no arg
	JSR  WCHEK
	BNE  MOVERR    jump if no delim
	LDX  SHFTREG   src1
	STX  PTR1

*a = buffarg();
*if(countu1 = 0) return(bad argument);
*if( !dchek(a) ) return(bad argument);
*ptr2 = shftreg;         /* src2 */

	JSR  BUFFARG
	TST  COUNT
	BEQ  MOVERR    jump if no arg
	JSR  DCHEK
	BNE  MOVERR    jump if no delim
	LDX  SHFTREG   src2
	STX  PTR2

*a = buffarg();
*a = wskip();
*if(a != cr) return(bad argument);
*if(countu1 != 0) tmp2 = shftreg;  /* dest */
*else tmp2 = ptr1 + 1;

	JSR  BUFFARG
	JSR  WSKIP
	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
*<addr> 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:
*   <cr>      - Finds the next opcode for
*          assembly.  If there was no assembly input,
*          the next opcode disassembled is retrieved
*          from the disassembler.
*   <lf><+>   - Works the same as carriage return
*          except if there was no assembly input, the
*          <addr> is incremented and the next <addr> is
*          disassembled.
*    <^><->   - Decrements <addr> 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   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  JSR  OUTSPAC   come here for cr or lf
	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  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 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] = <space>;   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  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    LDAA #OTHER
	STAA AMODE   mode
	CLR  YFLAG
	LDX  PTR0

*while (*x != end of buffer)
*   if (x[0]++ == ',')
*      if (x[0] == 'y') amode = INDY;
*      else amod = INDX;
*      break;
*a = wskip()
*if( a == '#' ) amode = IMMED;

DOPLP1  CPX  #ENDBUFF (end of buffer)
	BEQ  DOOP1   jump if end of buffer
	LDD  0,X     read 2 chars from buffer
	INX	move pointer
	CMPA #','
	BNE  DOPLP1
	CMPB #'Y'    look for ",y"
	BNE  DOPLP2
	LDAA #INDY
	STAA AMODE
	BRA  DOOP1
DOPLP2  CMPB #'X'    look for ",x"
	BNE  DOOP1   jump if not x
	LDAA #INDX
	STAA AMODE
	BRA  DOOP1
DOOP1   JSR  WSKIP
	CMPA #'#'    look for immediate mode
	BNE  DOOP2
	JSR  INCBUFF point at argument
	LDAA #IMMED
	STAA AMODE
DOOP2

*switch(class)
	LDAB CLASS
	CMPB #P2INH
	BNE  DOSW1
	JMP  DOP2I
DOSW1   CMPB #INH
	BNE  DOSW2
	JMP  DOINH
DOSW2   CMPB #REL
	BNE  DOSW3
	JMP  DOREL
DOSW3   CMPB #LIMM
	BNE  DOSW4
	JMP  DOLIM
DOSW4   CMPB #NIMM
	BNE  DOSW5
	JMP  DONOI
DOSW5   CMPB #GEN
	BNE  DOSW6
	JMP  DOGENE
DOSW6   CMPB #GRP2
	BNE  DOSW7
	JMP  DOGRP
DOSW7   CMPB #CPD
	BNE  DOSW8
	JMP  DOCPD
DOSW8   CMPB #XNIMM
	BNE  DOSW9
	JMP  DOXNOI
DOSW9   CMPB #XLIMM
	BNE  DOSW10
	JMP  DOXLI
DOSW10  CMPB #YNIMM
	BNE  DOSW11
	JMP  DOYNOI
DOSW11  CMPB #YLIMM
	BNE  DOSW12
	JMP  DOYLI
DOSW12  CMPB #BTB
	BNE  DOSW13
	JMP  DOBTB
DOSW13  CMPB #SETCLR
	BNE  DODEF
	JMP  DOSET

*   default: return("error in mnemonic table");

DODEF   LDAA #$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
	CMPD #$7F    in range ?
	BLS  DOREL2  jump if in range
	CMPD #$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  LDAA AMODE
	CMPA #INDX
	BNE  DOGRP2
	JSR  DOINDEX
	RTS
DOGRP2  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
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

*               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

*               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

*               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
	CMPD #$7F
	BLS  DOSET6	jump if in range
	CMPD #$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   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 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 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  LDAB CLASS
	CMPB #INH
	BNE  DISREL     jump if not inherent
	LDAB PNORM
	CMPB #PG1
	BEQ  DISINH1    jump if page1
	LDAA BASEOP     get opcode
	LDAB #P2INH     class=p2inh
	JSR  DISRCH
	TSTB
	BNE  DISINH1    jump if found
	JSR  DISILLOP   "illegal opcode"
	RTS
DISINH1 JSR  PRNTMNE
	RTS

*   elseif(class=REL)       /* REL */
*      if(pnorm != PG1)
*         disillop(); return();
*      prntmne();
*      disrelad();
*      return();

DISREL  LDAB CLASS
	CMPB #REL
	BNE  DISBTD
	TST  PNORM
	BEQ  DISREL1    jump if page1
	JSR  DISILLOP   "illegal opcode"
	RTS
DISREL1 JSR  PRNTMNE    output mnemonic
	JSR  DISRELAD   compute relative address
	RTS

*   else           /* SETCLR,SETCLRD,BTB,BTBD */
*      if(class == (SETCLRD or BTBD))
*         if(pnorm != PG1)
*            disillop(); return();   /* illop */
*         prntmne();           /* direct */
*         disdir();           /* output $byte */
*      else (class == (SETCLR or BTB))
*         prntmne();           /* indexed */
*         disindx();
*      outspac();
*      disdir();
*      outspac();
*      if(class == (BTB or BTBD))
*         disrelad();
*   return();

DISBTD  LDAB CLASS
	CMPB #SETCLRD
	BEQ  DISBTD1
	CMPB #BTBD
	BNE  DISBIT     jump not direct bitop
DISBTD1 TST  PNORM
	BEQ  DISBTD2    jump if page 1
	JSR  DISILLOP
	RTS
DISBTD2 JSR  PRNTMNE
	JSR  DISDIR     operand(direct)
	BRA  DISBIT1
DISBIT  JSR  PRNTMNE
	JSR  DISINDX    operand(indexed)
DISBIT1 JSR  OUTSPAC
	JSR  DISDIR     mask
	LDAB CLASS
	CMPB #BTB
	BEQ  DISBIT2    jump if btb
	CMPB #BTBD
	BNE  DISBIT3    jump if not bit branch
DISBIT2 JSR  DISRELAD   relative address
DISBIT3 RTS


*Elseif($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  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 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  LDX  #MNETABL   point to top of table
DISRCH1 CMPA 4,X        test opcode
	BNE  DISRCH3    jump not this entry
	TSTB
	BEQ  DISRCH2    jump if class=null
	CMPB 5,X        test class
	BNE  DISRCH3    jump not this entry
DISRCH2 LDAB 5,X
	STAB CLASS
	STX  MNEPTR     return ptr to mnemonic
	INCB
	RTS	   return found
DISRCH3 PSHB	  save class
	LDAB #6
	ABX
	LDAB 0,X
	CMPB #EOT       test end of table
	PULB
	BNE  DISRCH1
	CLRB
	RTS	   return not found

******************
*prntmne() - output the mnemonic pointed
*at by mneptr.
******************
*outa(mneptr[0-3]);
*outspac;
*return();

PRNTMNE LDX  MNEPTR
	LDAA 0,X
	JSR  OUTA       output char1
	LDAA 1,X
	JSR  OUTA       output char2
	LDAA 2,X
	JSR  OUTA       output char3
	LDAA 3,X
	JSR  OUTA       output char4
	JSR  OUTSPAC
	RTS

******************
*disindx() - process indexed mode
******************
*disdir();
*outa(',');
*if(pnorm == (PG2 or PG4)) outa('Y');
*else outa('X');
*return();

DISINDX JSR  DISDIR     output $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 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 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  LDAA #'$'
	JSR  OUTA
	LDX  DISPC
	JSR  OUT1BYT
	STX  DISPC
	RTS

*****************
*disext() - output "$ next 2 bytes"
*****************
DISEXT  LDAA #'$'
	JSR  OUTA
	LDX  DISPC
	JSR  OUT2BSP
	STX  DISPC
	RTS


*****************
*disillop() - output "illegal opcode"
*****************
DISMSG1 FCC	"ILLOP"
	FCB	EOT
DISILLOP PSHX
	LDX  #DISMSG1
	JSR  OUTSTRG0   no cr
	PULX
	RTS



**********
*   help  -  List buffalo commands to terminal.
**********
HELP     LDX  #HELPMSG1
	JSR  OUTSTRG    print help screen
	RTS

HELPMSG1 FCC	"ASM [<addr>]  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 <addr1> <addr2> [<data>]  Block fill memory"
	FCB	$0D
	FCC	"BR [-][<addr>] Set up bkpt table"
	FCB	$0D
	FCC	"BULK  Erase EEPROM,                 BULKALL  Erase EEPROM and CONFIG"
	FCB	$0D
	FCC	"CALL [<addr>] Call subroutine"
	FCB	$0D
	FCC	"GO [<addr>] Execute code at addr,        PROCEED  Continue execution"
	FCB	$0D
	FCC	"EEMOD [<addr> [<addr>]] Modify EEPROM range"
	FCB	$0D
	FCC	"LOAD, VERIFY [T] <host dwnld command>  Load or verify S-records"
	FCB	$0D
	FCC	"MD [<addr1> [<addr2>]]  Memory dump"
	FCB	$0D
	FCC	"MM [<addr>] or [<addr>]/  Memory Modify"
	FCB	$0D
	FCC	"  [/,=]  Same addr,  [^,-,CTLH] Prev addr,  [+,CTLJ,SPACE] Next addr"
	FCB	$0D
	FCC	"  <addr>O Compute offset,                   [CR]  Quit"
	FCB	$0D
	FCC	"MOVE <s1> <s2> [<d>]  Block move"
	FCB	$0D
	FCC	"OFFSET [-]<arg>  Offset for download"
	FCB	$0D
	FCC	"RM [P,Y,X,A,B,C,S]  Register modify"
	FCB	$0D
	FCC	"STOPAT <addr>  Trace until addr"
	FCB	$0D
	FCC	"T [<n>]  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 [<addr>] - Execute a jsr to <addr> 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 = <addr>

*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  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 [<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
	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 = <addr>
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    TSX	  swi entry point
*		   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] = opTałl[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 <n> - 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   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 <addr> - Trace instructions until <addr>
*is reached.
**********
*if((a=wskip) != cr)
*     a = buffarg(); a = wskip();
*     if(a != cr) return(bad argument);
*else return(bad argument);
STOPAT   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  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~

** 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 STS.e	PTR2      save monitor sp
	LDS.e	SP        user stack pointer
	LDX.e	REGS
	PSHX	pc
	LDX.e	REGS+2
	PSHX	y
	LDX.e	REGS+4
	PSHX	x
	LDD.e	REGS+6
	PSHA	a
	PSHB	b
	LDAA.e	REGS+8
	PSHA	ccr
	RTI

** Return here from run one line of user code.
XIRQIN  TSX	   user sp -> x
	LDS  PTR2       restore monitor sp

** SAVSTACK - Save user's registers.
* On entry - x points to top of user stack.
SAVSTACK 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   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     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    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 [<addr>]
* Specify offset to be added to s-record address when
* downloading from the host.
*  OFFSET                -show the current offset
*  OFFSET <data>         -current offset = data
*  OFFSET -<data>        -current offset = 0 - data
**********
*if(<data>) then offset = data;
*print(offset);
OFFSET   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 [<name>]  - prints the user regs
*and opens them for modification.  <name> is
*the first register opened (default = P).
*   Subcommands:
* [<nn>]<space>  Opens the next register.
* [<nn>]<cr>     Return.
*    The register value is only changed if
*    <nn> 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 [<addr1> [<addr2>]] - 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   LDX   #APORT    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  APORT    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 <CR>
	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 ***
	RSEG	BUF_VECTS1
.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

	RSEG	BUF_VECTS2
.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

	RSEG	VECTORS
*** 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
