.PAGE
;***********************************************************
;*							   *
;*		DEBUGING  UTILITIES			   *
;*							   *
;*   COPYRIGHT (c) 1982, 1983  SAGE Computer Technology	   *
;*   All Rights Reserved				   *
;*							   *
;***********************************************************

;Computed goto

;			D0 : Jump vector (lower 8 bits)
;	BSR	COMPGOTO
;			A1 : Address to jump to

COMPGOTO
	MOVEA.L (A7)+,A1	;Get return addr (jump vectors)
	ANDI.L	#00FH,D0	;Use only lower 8 bits
	ADD.L	D0,D0		;Convert index to offset
	ADD.L	A1,D0		;Compute address of jump vector
	EXG	A1,D0
	MOVEA.W (A1),A1		;Get jump vector
	ADDA.L	D0,A1		;Convert jump vector to abs addressing
	JMP	(A1)		;Jump to address given
	
;Check for memory at a given location

;		       A1 : Memory address to be tested
;	BSR	CHKMEM
;		       A1 : Memory address to be tested

CHKMEM
	MOVEM.L D0/A0/A2-A3,-(A7) ;Save working registers
	MOVEA.L BE_TRAP,A2	;Redirect trap to routine
	LEA	CHKMEM1,A3
	MOVE.L	A3,BE_TRAP
	MOVE.B	(A1),D0		;Memory there?
	MOVE.L	A2,BE_TRAP	;Restore Bus Error vector
	MOVEM.L (A7)+,D0/A0/A2-A3  ;Yes - restore working registers
	CMP.B	D0,D0		;Set EQ - No error
	RTS
	
;Error - Memory bad or does not exist at specified location


CHKMEM1
	ADDQ.L	#8,A7		;Skip unneeded stack infow
	MOVE.W	(A7)+,D1	;Restore status register
	MOVE	D1,SR
	LEA	MSG3,A0		;Print error message
	BSR	TERMTEXT
	ADDQ.L	#4,A7		;Clear stack
	MOVE.L	A1,D0		;Print bad memory address
	BSR	PRNTADDR
	MOVE.L	A2,BE_TRAP	;Restore Bus Error vector
	MOVEM.L (A7)+,D0/A0/A2-A3;Restore working registers
	ORI.B	#1,D0
	RTS
;Test terminal for waiting character

;	BSR	TESTTERM
;			D0 :  Z = No char waiting
;			     NZ = character waiting

TESTTERM
	BTST	#1,TERM_S	;Character waiting from keyboard
	RTS
	
;Print (colon and space) : 

;	BSR	TERMCOLN
;			No registers affected

TERMCOLN
	MOVE.L	D0,-(A7)	;Save D0
	MOVEQ	#COLON,D0	;Print colon
	BSR	TERMCHAR
	MOVE.L	(A7)+,D0	;Restore D0
	BSR	TERMSPAC	;Print space
	RTS
	
;Print comma

;	BSR	TERMCOMA
;			No registers affected

TERMCOMA
	MOVE.L	D0,-(A7)	;Save D0
	MOVEQ	#",",D0		;Print comma
	BSR	TERMCHAR
	MOVE.L	(A7)+,D0	;Restore D0
	RTS
	
;Sound bell

;	BSR	TERMBELL
;			No registers affected

TERMBELL
	MOVE.L	D0,-(A7)	;Save D0
	MOVEQ	#BELL,D0	;Print colon
	BSR	TERMCHAR
	MOVE.L	(A7)+,D0	;Restore D0
	RTS
	
;Print printable characters (all nonprinting chars converted to period)

;			D0 : Character to be printed
;	BSR	PRNTCHAR
;			D0 : Character printed

PRNTCHAR
	AND.B	#7FH,D0		;Strip off parity bit
	CMPI.B	#20H,D0		;Printable char?
	BLT.S	$1		;Char is not printable
	CMPI.B	#7EH,D0		;Printable char
	BLT.S	$2		;Yes
$1
	MOVEQ	#PERIOD,D0	;Use period for nonprint char
$2
	RTS
	
; Fill a buffer with an input line

;			A0 : Start of buffer
;			D2 : Buffer size - 2
;	BSR	READLINE
;			A0 : First character in buffer
;			D0 : ?
;			D2 : Number of unused bytes left in buffer
; <Input Buffer> := <Byte> ... <Last byte> . <0> . <Terminator char>

READLINE
	MOVE.L	A1,-(A7)	;Save working registers
	MOVE.L	D1,-(A7)
	MOVEA.L A0,A1		;Save start of buffer
$05
	CLR.L	D1
$1
	BSR	KEYBCH		;Get a char from keyboard
	CMPI.B	#ESC,D0		;Erase line
	BEQ	$52
	CMPI.B	#CNTRLR,D0	;Reprint input line?
	BEQ	$55
	CMPI.B	#0DH,D0		;Chariage return?
	BEQ.S	$4		;Yes
	
	CMPI.B	#08H,D0		; Back space = delete
	BNE.S	$19
	CMPA.L	A0,A1		;At beginning of buffer?
	BEQ	$1		;Yes - nothing to delete
$15
	BSR	TERMCHAR	;Backup one character
	BSR	TERMSPAC	;Clear char
	BSR	TERMCHAR	;Move to position just cleared
	DBF	D1,$15		;Repeat until erased all chars
	SUBQ.L	#1,A1		;Skip character
	ADDQ.L	#1,D2		;Number bytes left in buffer
	BRA	$05
$19
	CMPI.B	#7FH,D0		;Delete character?
	BNE.S	$3		;No
$2
	CMPA.L	A0,A1		;At beginning of buffr
	BEQ	$1		;Yes - nothing to delete
	BSR.S	$6		;Start delete display
	SUBQ.L	#1,A1		;Skip character
	ADDQ.L	#1,D2		;Number bytes left in buffer
	MOVE.B	(A1),D0		;Print deleted char
	BSR	TERMCHAR
	ADDQ.W	#2,D1		;Increment number of characters deleted
	BRA	$1
$3
	BSR.S	$5		;Print delete delimiter if needed
	CLR.L	D1		;Clear delete flag
	SUBQ.L	#1,D2		;Number of characters left in buffer
	BMI.S	$4		;Out of room in buffer
	MOVE.B	D0,(A1)+	;Store character in buffer
	BSR	TERMCHAR	;Print char read
	BRA	$1
$4
	BSR.S	$5		;Done
	CLR.B	(A1)+		;Set termination byte
	MOVE.B	D0,(A1)+	;Save termination character
	MOVE.L	(A7)+,D1	;Restore working registers
	MOVEA.L (A7)+,A1
	RTS
$5
	OR.L	D1,D1		;Any chars previosly deleted
	BEQ.S	$7		;No
	CLR.L	D1		;Clear flag
	BRA.S	$65

;Delete line

$52
	MOVEA.L A0,A1		;Move to beginning of buffer
	
;Reprint input line

$55
	CLR.L	D1		;Clear delete flag
	MOVE.L	A0,-(A7)	;Save beginning of buffer pointer
	MOVEQ	#"#",D0		;Notify buffer being reprinted
	BSR	TERMCHAR
	BSR	TERMCRLF	;Start on new line
	CMPA.L	A0,A1		;Anything to print
	BEQ	$58		;No
$57
	MOVE.B	(A0)+,D0	;Print char
	BSR	TERMCHAR
	CMPA.L	A0,A1		;Done?
	BNE	$57		;Repeat utill done
$58
	MOVEA.L (A7)+,A0	;Restore beginning of buffer pointer
	BRA	$1		;Get next char
$6
	OR.L	D1,D1		;1st character to be erased
	BNE.S	$7		;No - leave routine
	MOVEQ	#1,D1		;Set delete flag
$65
	MOVE.W	D0,-(A7)	;Save current char
	MOVE.B	#DELTERM,D0	;Print delete terminator
	BSR	TERMCHAR
	MOVE.W	(A7)+,D0	;Restore current char
$7
	RTS


;Get character from input buffer
;			A0 : Current input buffer position
;	BSR	GETCHAR
;			A0 : Next character inbuffer
;			D0 : Character (0 => end of buffer)

GETCHAR
	CLR.L	D0		;Clear all bits
	MOVE.B	(A0)+,D0	;Get char
	OR.B	D0,D0		;Set EOB flag if needed
	BNE.S	$1		;Char in buffer
	SUBQ.L	#1,A0		;Dont skip past terminator
$1
	RTS
	
; Get character and test for termination char or EOB
;
;			A0 : Buffer pointer
;	BSR	GETTCHAR
;	BSR	CHKCHAR
;			A0 : Next character
;			D0 : Character gotten
;		 Zero flag : termination condition reached

GETTCHAR
	BSR	GETCHAR		;Get next character
CHKCHAR
	OR.B	D0,D0		;End of buffer reached
	BEQ.S	$1		;End of buffer reached
	CMPI.B	#SPACE,D0	;End of arg
	BEQ.S	$1
	CMPI.B	#COMMA,D0	;End of arg
$1
	RTS
	
;Skip spaces in buffer
;			A0 : buffer pointer
;	BSR	SKIPSPAC
;			A0 : Next legal char
;			D0 : Next nonspace character

SKIPSPAC
	BSR	GETCHAR		;Get next character
	BEQ.S	$2		;End of buffer reached
	CMPI.B	#SPACE,D0	;Skip spaces
	BEQ	SKIPSPAC
	SUBQ.L	#1,A0		;Set buffer pointer to non space char
$2
	RTS

;Read and locate command in table then jump to it
;			A1 : Address of command table
;			A0 : Buffer address of command
; <Command table> := <#entries-1> . <entry> <address> ... <entry> <address>
;	BSR	SRCHCMND
;			A0 : Address of next character in buffer
;			     Jumps to address if command in table
;			     Jumps to command error if no command
;			A1 : ?
;			A2 : ?
;			D0 : ?
;			D1 : ?

SRCHCMND
	BSR	GETCHAR		;Get command from input buffer
	MOVEA.L A1,A2		;Save command table address
	CLR.W	D1
	MOVE.B	(A1)+,D1	;Set table size
$1
	CMP.B	(A1),D0		;Locate command in table
	ADDQ.L	#3,A1		;Move to next entry
	DBEQ	D1,$1		;Repeat until entry found or reach end
	BNE	CMNDERR		;Command not found
	MOVE.B	-(A1),D0	;Get upper 8 bits of relative addr
	ROL.W	#8,D0		;Move to upper 8 bits
	MOVE.B	-(A1),D0	;Move lower 8 bits of relative addr
	ADDA.W	D0,A2		;Compute physical address
	JMP	(A2)		;Jump to subroutine

;Get number from buffer
;
;			A0 : Buffer Address
;			D2 : Max number allowed
;	CALL	GETNUM
;			A0 : One char after delimiter char
;			D0 : Number
;			D1 : Termination character
;			 Z : Number is good
;			MI : Error detected during conversion

GETNUM:
	MOVEM.L D3-D4,-(A7)	;Save working registers
	CLR.L	D1		;Clear number accum
	MOVEQ	#1,D4		;Set hex number conversion flag
	ROR.L	#4,D4		; & maximum flag 10000000H
	BSR	GETTCHAR	;Hex or Decimal conversion?
	BEQ.S	$3		;No Data 
	CMPI.B	#"/",D0		;Decimal operator?
	BNE.S	$06		;No Process character as number
	MOVE.W	#3333H,D4	;Set decimal flag
	SWAP	D4		; & maximum flag * 2 = 33333334H
	MOVE.W	#3334H,D4
$05
	BSR	GETTCHAR	;Get next char from buffer
	BEQ.S	$3		;Done
$06
	SUBI.B	#ZERO,D0	;Convert to binary
	BLT.S	$2		;Error - out of range
	CMPI.B	#9,D0		; A - F
	BLE.S	$1		;No
	TST.B	D4		;Decimal number?
	BNE.S	$2		;Yes - Number out of range - Error
	SUBI.B	#07.,D0		;Convert A - F to binary
	CMPI.B	#0AH,D0		;In range?
	BLT.S	$2
	CMPI.B	#0FH,D0		;In range?
	BGT.S	$2		;Error - out of range
$1
	MOVE.L	D1,D3		;Make working copy
	TST.B	D4		;Hex number?
	BEQ.S	$15		;Yes - Process new digit as such
	ROL.L	#3,D1		;Multiply by 10 decimal
	ROL.L	#1,D3
	ADD.L	D3,D1
	BRA.S	$17		;Compute new digit
$15
	ROL.L	#4,D1		;Shift previous number
$17
	CMP.L	D4,D3		;Overflow
	BCC.S	$2		;Yes - report error
	ADD.L	D0,D1		;Add in new number
	OR.L	D2,D2		;Maximum number size
	BEQ	$05
	CMP.L	D1,D2		;Overflow?
	BCC	$05		;No
$2
	MOVEQ	#-1,D1		;Report error
$3
	EXG	D0,D1		;Exchange terminator and number (answer)
$4
	MOVEM.L (A7)+,D3-D4	;Restore registers
	
	RTS

;Converts Address located in buffer
;			A0 : Buffer address of number
;	BSR	CNVTADDR
;			A1 : Address calculated
;			D0 : 0 => [$X+]XXXXXX + => #XXXXXX, - => Error
;			A2 : Address of $X if used
;			D1 : ?
;			D2 : ?

CNVTADDR
	MOVE.L	D3,-(A7)	;Save D3
	BSR	SKIPSPAC	;Skip leading spaces
	CLR.L	D3		;Clear flag
	SUBA.L	A2,A2		;Set to 0 base register
	
	BSR	GETTCHAR	;What kind of address?
	BEQ	$5		;Error - EOL reached prematurely
	CMPI.B	#SWATH,D0	; #XXXXXX
	BEQ.S	$2
	CMPI.B	#BASEMARK,D0	; [$X+]XXXXXX
	BEQ.S	$1
	MOVEA.W LOCCNTR,A2	;Assume standard counter
	SUBQ.L	#1,A0		;Moves to beginning of address
	BRA.S	$6
$1
				;Format to [$X+]XXXXXX
	BSR	GETTCHAR	;Calculate base location counter
	BEQ	$5		;Error - Premature end of line
	SUBI.B	#ZERO,D0	;Convert to binary
	BCS.S	$5		;Error - Illegal number
	CMPI.B	#MAXBASE,D0	;Legal base register
	BCC.S	$5		;No - Error
	MOVEA.L D0,A2		;Compute address of base location cntr
	SUBA.L	A1,A1		;Clear result address register
	BSR	GETTCHAR	;Get next char (terminator, +)
	BEQ	$7		;Terminator reached
	CMPI.B	#BASETERM,D0	;Next char must be a +
	BNE.S	$5
	BRA.S	$6		;Process rest of address
$2
	ADDQ.L	#1,D3		;Set #XXXXXX flag

; Process address

$6
	CLR.L	D2		;No max number
	BSR	GETNUM		;Get next digit of address
	BEQ.S	$4		;Address read ok

; Error processing

$5
	SUBQ.L	#3,D3		;Set error flag
	
; Termination processing

$4
	MOVEA.L D0,A1		;Compute address
$7
	ADDA.L	A2,A2		;Compute base register offset
	ADDA.L	A2,A2
	ADDA.W	#BASEADDR,A2	;Initialize address of $X
	ADDA.L	(A2),A1		;Compute physical address
	MOVE.L	(A7)+,D0	;Restore D3
	EXG	D0,D3		;Set error flag
	OR.L	D0,D0
	RTS

;Get Data from buffer
;
;			A0 : Pointer to buffer
;			D1 : Maximum data size (0= no maximum)
;		    Buffer : <spaces> XXXXXX 
;			     <spaces> 'XXXXXX'
;	BSR	GETDATA
;			A0 : Point to delimiter after buffer
;			D0 : Data item from buffer
;			D1 : < 0 -> Error Detected
;			     = 0 -> Data Ok
;			     .	 -> Period detected
;			     1	 -> No data 

GETDATA
	MOVE.L	D2,-(A7)	;Save D2
	CLR.L	D2		;Clear result register
$05
	BSR	SKIPSPAC	;Skip spaces
	BEQ	$8		;No Data

	CMPI.B	#"'",D0		;Character string
	BEQ.S	$4		;Process character string
	CMPI.B	#PERIOD,D0	;No alteration character
	BEQ.S	$9

	MOVE.L	D1,D2		;Convert number to binary
	BSR	GETNUM
	BMI.S	$20		;Error detectected
$10
	MOVE.L	(A7)+,D2	;Restore D2
	SUB.L	D1,D1		;Set OK flag
	RTS
$20
	MOVE.L	(A7)+,D2	;Restore D2
	CLR.L	D1		;Set minus = error
	SUBQ.L	#1,D1
	RTS

;Process character string

$4
	BSR	GETCHAR		;Skip openning quote
$5
	BSR	GETCHAR		;Get char and note terminator
	BEQ	$7		;Terminator reached
	CMPI.B	#"'",D0		;Terminator?
	BEQ.S	$6		;Yes
	ROL.L	#8,D2		;Shift previous characters over
	TST.B	D2		;Assure no overflow
	BNE	$20		;Overflow - report error
	ADD.L	D0,D2		;Insert new character
	OR.L	D1,D1		;Verify character max?
	BEQ	$5		;No
	CMP.L	D2,D1		;Out of range
	BCC	$5		;No
	BRA	$20		;Yes
$6
	BSR	GETTCHAR	;Next character must be a terminator
	BNE	$20		;Next character not terminator
$7
	EXG	D0,D2		;Put answer in D0
	BRA	$10		;Not terminator
	
;No Data

$8
	MOVEQ	#1,D0		;Set no data flag

;Process peroid

$9
	MOVE.L	(A7)+,D2	;Restore D2
	MOVE.L	D0,D1		;Set period
	RTS

;Command error processing

CMNDERRA
CMNDERR
	BSR	TERMSPAC	;Print space
	MOVEQ	#"?",D0		;Display error
	BSR	TERMCHAR
	BSR	TERMBELL	;Audible warning
				;Falls thru to DEBUG
.PAGE
;*********************************************************
;*							 ;*   SAGE COMPUTER DEBUGING TOOL (SDT)			 ;*							 ;*********************************************************

DEBUG:
	LEA	SYSSTACK,A7	;Initialize system stack
	CLR.L	BASE0		;Assure base 0 is zero
	BSR	TERMCRLF	;Print header
	BTST	#TRACE,BMODE	;Tracing?
	BEQ	$05		;No
	MOVEQ	#"T",D0		;Print trace flag
	BSR	TERMCHAR
$05
	MOVE.W	LOCCNTR,D3	;Get standard base register
	BEQ.S	$1		;Skip if no counter
	MOVEQ	#BASEMARK,D0	;Print Current base pointer
	BSR	TERMCHAR
	MOVE.B	D3,D0		;Print current base number
	BSR	TERMDIGT
$1
	MOVEQ	#PROMPT,D0	   ;Print prompt char
	BSR	TERMCHAR
	
	MOVEQ	#CLINELEN,D2
	LEA	CMNDLINE,A0	;Input command line
	BSR	READLINE
	
	LEA	CMNDCHAR,A1	;Branch to command
	BSR	SRCHCMND
	BRA	DEBUG

                                                                                                                                                                                                                                                                                                                                                                