; This ucode can copy the dsp instruction rom and coefficient table.
; irom:
;  0x8000 in instruction space
; coef:
;  0x1000 in data space
;
; Both irom and coef are 0x1000 words in length - remember, DSP
; uses 16bit words
;
; The DSP has two address spaces, to load data from instruction
; space you need to use 'i'-prefixed instructions.


/********************************/
/**        HANDY THANGERS      **/
/********************************/
; External
MEM_BASE:	equ	0x0000
MEM_HI:		equ	MEM_BASE
MEM_LO:		equ	MEM_BASE+1
; DSP
DRAM_BASE:	equ	0x0000

; Config reg controls dma behavior
CR_TO_DSP:	equ	0
CR_TO_CPU:	equ	1
CR_IRAM:	equ	2
CR_DRAM:	equ	0

IROM_BASE:	equ 0x8000
COEF_BASE:	equ 0x1000
DUMP_SIZE:	equ 0x2000 ; in bytes!


/**************************************************************/
/*                         CODE START                         */
/**************************************************************/
; iram 0x00 - Exception vectors
; 8 vectors, 2 opcodes each
	jmp		exception0
	jmp		exception1
	jmp		exception2
	jmp		exception3
	jmp		exception4
	jmp		exception5
	jmp		exception6
	jmp		exception7

; iram 0x10 - Our entry point
	sbset	#0x02
	sbset	#0x03
	sbclr	#0x04
	sbset	#0x05
	sbset	#0x06

; ???
	s16
	lri		$CR, #0x00ff

/**************************************************************/
/*                            MAIN                            */
/**************************************************************/
; This ucode is meant only to dump the ROMs, and as such is
; self-contained and skimpy
main:
	clr		$acc1
	clr		$acc0

; This consumes ALL of dram! We must be careful until we dma it!
	call	copy_irom_to_dram
; Send mail saying irom dump is done
	call	wait_for_dsp_mbox
	si		@DMBH, #0x8888
	si		@DMBL, #0xc0de
	si		@DIRQ, #0x0001
; Get address to dma to, dma, and wait till done
	call	dma_dram_to_cmbl

; Now we can start over for the coef
	call	copy_coef_to_dram
; Send mail saying coef dump is done
	call	wait_for_dsp_mbox
	si		@DMBH, #0x8888
	si		@DMBL, #0xda7a
	si		@DIRQ, #0x0001
; Get address to dma to, dma, and wait till done
	call	dma_dram_to_cmbl

; Die
do_halt:
	halt

/**************************************************************/
/*                      HELPER FUNCTIONS                      */
/**************************************************************/
/********************************/
/**      DUMPING FUNCTIONS     **/
/********************************/
; Dump irom from 0x8000 in instruction space
copy_irom_to_dram:
	lri		$ar0, #IROM_BASE
	lri		$ar1, #DRAM_BASE
	lri		$ar2, #DUMP_SIZE/2	; each iteration copies a word
	bloop	$ar2, copy_irom_to_dram_end
	ilrri	$ac0.m, @$ar0
	; Now ac0.m is 16bits of irom!
	srri	@$ar1, $ac0.m
copy_irom_to_dram_end:
	nop
	ret

; Dump coef from 0x1000 in data space
copy_coef_to_dram:
	lri		$ar0, #COEF_BASE
	lri		$ar1, #DRAM_BASE
	lri		$ar2, #DUMP_SIZE/2	; each iteration copies a word
	bloop	$ar2, copy_coef_to_dram_end
	lrri	$ac0.m, @$ar0
	; Now ac0.m is 16bits of coef!
	srri	@$ar1, $ac0.m
copy_coef_to_dram_end:
	nop
	ret

/********************************/
/**             DMA            **/
/********************************/
; DMA implementation which does not write to dram
; We take advantage of the fact that we know the mail is going to
; contain the address which we should dma to
dma_dram_to_cmbl:
	call	wait_for_cpu_mbox
	lrs		$ac0.m, @CMBL
	andi	$ac1.m, #0x7fff

; Directly do dma; writing the length kicks it off
	sr		@DSMAH, $ac1.m
	sr		@DSMAL, $ac0.m
	si		@DSPA, #DRAM_BASE
	si		@DSCR, #(CR_TO_CPU|CR_DRAM)
	si		@DSBL, #DUMP_SIZE

; Waits for previous DMA to complete by watching a bit in DSCR.
wait_dma:
	lrs		$ac1.m, @DSCR
	andcf	$ac1.m, #0x0004
	jlz		wait_dma
	ret

/********************************/
/**           MAILBOX          **/
/********************************/
; Waits for a mail to arrive in the DSP in-mailbox.
wait_for_dsp_mbox:
	lrs		$ac1.m, @DMBH
	andcf	$ac1.m, #0x8000
	jlz		wait_for_dsp_mbox
	ret

; Waits for the CPU to grab a mail that we just sent from the DSP.
wait_for_cpu_mbox:
	lrs		$ac1.m, @CMBH
	andcf	$ac1.m, #0x8000
	jlnz	wait_for_cpu_mbox
	ret

/********************************/
/**      EXCEPTION HANDLERS    **/
/********************************/
; ...zey do nutzing!
exception0:
	rti
exception1:
	rti
exception2:
	rti
exception3:
	rti
exception4:
	rti
exception5:
	rti
exception6:
	rti
exception7:
	rti