; Originally taken from came from Motorola's Dr. BuB DSP board.
; Obtained from Todd Day's FTP archive as sloader.asm
; Modified for TDSG56 project by Quinn Jensen (jensenq@npd.novell.com)
;
; Text from original:
;	Serial Loader for the DSP56000.
;	This loader initializes	the serial communications interface (SCI)
;	on the DSP56001	for 9600 baud and then loads OMF records (output
;	by the DSP56000	assembler) into	internal memory.  The loader takes
;	the upper 128 bytes of P memory	allowing the lower memory from
;	$0000-(LDRMEM-1) to be used by the user.  The following	records	are
;	interpreted:
;	    _DATA X ADDR
;	    _DATA Y ADDR
;	    _DATA P ADDR
;	    _END ADDR
;	After the END record is	encountered, the loader	jumps to the address
;	in the END record.  Note that an address MUST be present in the
;	END record (the	program	must contain at	least one P segment).
;
;	To generate a EPROM of this loader (8Kx8), perform the following:
;	$ asm56000 -b -l -a sloader
;	$ srec sloader
;
;	The EPROM is in	file SLOADER.P.	 To program the	EPROM, set the
;	programmer to MOTOROLA S record	format,	download the file with
;	a zero address offset and program the part.
;
;	BTW, S record format is	LSB MidSB MSB (what! Intel format? :-)
;	Took me	a few hours to figure this one out!  [Not really.  S records
;	are big-endian, its just the 56001 boot loader that wants LSB first.
;	-QJ]
;
;	If you don't have the program srec (where can I	get this?),
;	you have to do some gnarly contortions on the .LOD file.
;
;	So, if your .LOD file resulting	from compiling this program
;	looks like this:
;
;	_START SLOADER 0000 0000
;
;	_DATA P	0020
;	010203 040506 070809
;	_END 0020
;
;	then, program your PROM	with this sequence:
;	$0020	0302  0106  0504  0908	07.....	etc. (Fun, eh? :)
;
;
;	The loader loads the following memory spaces:
;	    X -	0 to FF
;	    Y -	0 to FF
;	    P -	0 to LDRMEM-1
;
	PAGE	68,66,1,1

SCR	EQU	$FFF0		;SCI CONTROL REGISTER
SCCR	EQU	$FFF2		;SCI CLOCK CONTROL REGISTER
PCC	EQU	$FFE1		;PORT C	CONTROL	REGISTER
RDRF	EQU	$2		;RECEIVE DATA REGISTER FULL FLAG
SSR	EQU	$FFF1		;SCI STATUS REGISTER
SRXH	EQU	$FFF6		;SCI RECEIVE IN	HIGH BYTE
PBC	equ	$FFE0		;port B	control
PBDDR	equ	$FFE2		;port B	data direction
PBD	equ	$FFE4		;port B	data
BCR	equ	$FFFE		;port a bus control reg
#ifdef ROM
LDRMEM	EQU	$198		;START OF LOADER IN P MEMORY
#else
#ifdef HIGH
LDRMEM	EQU	$F000		;START OF LOADER IN P MEMORY
#else
LDRMEM	EQU	$80		;START OF LOADER IN P MEMORY
#endif
#endif

	ORG	P:$0000		;RESET VECTOR FOR BOOTING
RVEC
	JMP	<LOAD		;GO EXECUTE LOADER

	ORG	P:LDRMEM,P:3*LDRMEM
LOAD
	MOVEP	#$0302,X:SCR	;ENABLE	TX,RX: 8 BIT 1 START, 1	STOP

				; *** You will probably	have to
				; *** change the line below!
	movep	#12,x:SCCR	;CD=12 (/13), int clk @ 31.25 Kbaud-4%
	MOVEP	#$0007,X:PCC	;ENABLE	SCI

#define MSG(m) movep	#m<<7,x:PBD

	MSG(0)
	movep	#0,x:PBC	;port B: parallel I/O
	movep	#-1,x:PBDDR	;port B: all output
	bset	#3,x:PBD	;assert "ROM"; allows RAM to respond in P space
        movep	#$2f2f,x:BCR    ;wait states: 0 for RAM, 15 for ROM and I/O
	MSG($c)
	MSG($c|3<<4)		;clear strobes

WTUS
	JSR	<GETCH		;INPUT CHARACTER
	MOVE	#'_',X0		;GET UNDERSCORE	CHARACTER
	CMP	X0,A		;SEE IF	"_" YET
	JNE	<WTUS		;NO
GOTUS
	JSR	<GETCH		;GET A CHARACTER
	MOVE	#'D',X0		;GET A D FOR DATA
	CMP	X0,A	#'E',X0	;COMPARE TO D, GET E
	JEQ	<DATAREC	;IF "D", THEN DATA RECORD
	CMP	X0,A		;SEE IF	END RECORD
	JNE	<WTUS		;NO, GO	WAIT FOR ANOTHER UNDERSCORE
_WTSPC
	MSG($e)
	JSR	<GETCH		;GET CHARACTER
	MOVE	#$20,X0		;GET SPACE
	CMP	X0,A		;WAIT FOR SPACE	AFTER "END"
	JNE	<_WTSPC		;WAIT FOR SPACE
	JSR	<IN4		;GET TRANSFER ADDRESS
	MOVE	B1,R0		;MOVE TRANSFER ADDRESS
	NOP			;CLEAR ADDRESS PIPE
	MSG($a)
	JMP	(R0)		;GO EXECUTE USER CODE
DATAREC
	MSG($d)
	JSR	<GETCH		;GET CHARACTER
	MOVE	#$20,X0		;GET SPACE
	CMP	X0,A		;SEE IF	SPACE
	JNE	<DATAREC	;NO
	JSR	<GETCH		;GET [P,X,Y]
	MOVE	A1,Y0		;SAVE CHARACTER
	JSR	<IN4		;GET ADDRESS OF	DATA RECORD
	MOVE	B1,R0		;SAVE ADDRESS
	MOVE		#'X',A	;GET X
	CMP	Y0,A	#'Y',A	;SEE IF	X, GET Y
	JEQ	<_LDX		;LOAD DATA INTO	X MEMORY
	CMP	Y0,A		;SEE IF	Y
	JEQ	<_LDY		;LOAD DATA INTO	Y MEMORY
_LDP
	JSR	<IN6		;GET DATA
	MOVEM	B1,P:(R0)+	;LOAD P	MEMORY
	JMP	<_LDP
_LDX
	JSR	<IN6		;GET DATA
	MOVE	B1,X:(R0)+	;LOAD X	MEMORY
	JMP	<_LDX
_LDY
	JSR	<IN6		;GET DATA
	MOVE	B1,Y:(R0)+	;LOAD Y	MEMORY
	JMP	<_LDY

GETCH
	JCLR	#RDRF,X:SSR,*	;WAIT FOR DATA IN SCI
	MOVEP	X:SRXH,A	;GET SCI DATA IN HIGH BYTE
	LSL	A		;SHIFT OUT PARITY
	LSR	A		;clear parity bit
	MOVE	A1,A		;SIGN EXTEND AND ZERO
	MOVEP	A,X:SRXH	;put sci data in high byte
        RTS
IN4
	MSG($4)
	CLR	B	#>4,X0	;CLEAR VALUE, GET 4
	JMP	<READHEX	;READ 4	HEX CHARACTERS
IN6
	MSG($6)
	CLR	B	#>6,X0	;CLEAR VALUE, GET 6
READHEX
	DO	X0,_READHEX	;READ ASCII HEX	AND CONVERT TO BINARY
_GET
	JSR	<GETCH		;GET A CHARACTER
	MOVE	#'_',X0		;GET UNDERSCORE
	CMP	X0,A	#'F',X0	;SEE IF	UNDERSCORE
	JNE	<_NOTUS		;NO
	ENDDO			;EXIT LOOP
	MOVEC	SSH,X0		;POP RETURN ADDRESS
	JMP	<GOTUS		;GO PROCESS NEW	INPUT RECORD
_NOTUS
	CMP	X0,A	#'0',X0	;SEE IF	GREATER	THAN F
	JGT	<_GET		;YES, IGNORE
	CMP	X0,A		;SEE IF	LESS THAN 0
	JLT	<_GET		;YES, IGNORE
	SUB	X0,A	#10,X0	;ADJUST	FOR ASCII TO BINARY
	CMP	X0,A	#7,X0	;SEE IF	A-F
	JLT	<_NOTALPHA	;NO
	SUB	X0,A		;ADJUST	FOR 1-F
_NOTALPHA
	REP	#4		;SHIFT OLD VALUE LEFT 1	NIBBLE
	LSL	B
	REP	#16		;SHIFT NEW NIBBLE DOWN TO LSB
	LSR	A
	ADD	A,B		;ADD NEW NIBBLE	IN
_READHEX
	RTS
	END

