dolphin/Source/DSPSpy/tests/dsp_base.inc

359 lines
7.0 KiB
PHP

; This is the trojan program we send to the DSP from DSPSpy to figure it out.
REGS_BASE: equ 0x0f80
MEM_HI: equ 0x0f7E
MEM_LO: equ 0x0f7F
;
; CODE STARTS HERE.
; Interrupt vectors 8 vectors, 2 opcodes each
jmp irq0
jmp irq1
jmp irq2
jmp irq3
jmp irq4
jmp irq5
jmp irq6
jmp irq7
; Main code at 0x10
sbset #0x02
sbset #0x03
sbclr #0x04
sbset #0x05
sbset #0x06
s16
lri $CR, #0x00ff
; Why do we have a main label here?
main:
clr $acc1
clr $acc0
; get address of memory dump and copy it to DRAM
call wait_for_dsp_mbox
si @DMBH, #0x8888
si @DMBL, #0xdead
si @DIRQ, #0x0001
call wait_for_cpu_mbox
lrs $ac0.m, @CMBL
andi $ac1.m, #0x7fff
sr @MEM_HI, $ac1.m
sr @MEM_LO, $ac0.m
lri $ax0.l, #0
lri $ax1.l, #0 ;(DSP_CR_IMEM | DSP_CR_TO_CPU)
lri $ax0.h, #0x2000
lr $ac0.l, @MEM_HI
lr $ac0.m, @MEM_LO
call do_dma
; get address of registers and DMA them to ram
call wait_for_dsp_mbox
si @DMBH, #0x8888
si @DMBL, #0xbeef
si @DIRQ, #0x0001
call wait_for_cpu_mbox
lrs $ac0.m, @CMBL
andi $ac1.m, #0x7fff
sr @MEM_HI, $ac1.m
sr @MEM_LO, $ac0.m
lri $ax0.l, #REGS_BASE
lri $ax1.l, #0 ;(DSP_CR_IMEM | DSP_CR_TO_CPU)
lri $ax0.h, #0x80
lr $ac0.l, @MEM_HI
lr $ac0.m, @MEM_LO
call do_dma
; Read in all the registers from RAM
lri $ar0, #REGS_BASE+1
lrri $ar1, @$ar0
lrri $ar2, @$ar0
lrri $ar3, @$ar0
lrri $ix0, @$ar0
lrri $ix1, @$ar0
lrri $ix2, @$ar0
lrri $ix3, @$ar0
lrri $wr0, @$ar0
lrri $wr1, @$ar0
lrri $wr2, @$ar0
lrri $wr3, @$ar0
lrri $st0, @$ar0
lrri $st1, @$ar0
lrri $st2, @$ar0
lrri $st3, @$ar0
lrri $ac0.h, @$ar0
lrri $ac1.h, @$ar0
lrri $cr, @$ar0
lrri $sr, @$ar0
lrri $prod.l, @$ar0
lrri $prod.m1, @$ar0
lrri $prod.h, @$ar0
lrri $prod.m2, @$ar0
lrri $ax0.l, @$ar0
lrri $ax1.l, @$ar0
lrri $ax0.h, @$ar0
lrri $ax1.h, @$ar0
lrri $ac0.l, @$ar0
lrri $ac1.l, @$ar0
lrri $ac0.m, @$ar0
lrri $ac1.m, @$ar0
lr $ar0, @REGS_BASE
jmp start_of_test
; This is where we jump when we're done testing, see above.
end_of_test:
nop
nop
nop
nop
nop
nop
nop
; We just fall into a loop, playing dead until someone resets the DSP.
dead_loop:
jmp dead_loop
; Utility function to do DMA.
; ac0.l:ac0.m - external address.
; ax0.l - address in DSP
do_dma:
sr @DSMAH, $ac0.l
sr @DSMAL, $ac0.m
sr @DSPA, $ax0.l
sr @DSCR, $ax1.l
sr @DSBL, $ax0.h ; This kicks off the DMA.
; Waits for said DMA to complete by watching a bit in DSCR.
wait_dma:
lrs $ac1.m, @DSCR
andcf $ac1.m, #0x0004
jlz wait_dma
ret
; This 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
; This 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
; IRQ handlers. Not entirely sure what good they do currently.
irq0:
lri $ac0.m, #0x0000
jmp irq
irq1:
lri $ac0.m, #0x0001
jmp irq
irq2:
lri $ac0.m, #0x0002
jmp irq
irq3:
lri $ac0.m, #0x0003
jmp irq
irq4:
lri $ac0.m, #0x0004
jmp irq
irq5:
; No idea what this code is doing.
s16
mrr $st1, $ac0.l
mrr $st1, $ac0.m
clr $acc0
mrr $ac0.m, $st1
mrr $ac0.l, $st1
nop ; Or why there's a nop sled here.
nop
nop
nop
nop
nop
rti
lri $ac0.m, #0x0005
jmp irq
irq6:
lri $ac0.m, #0x0006
jmp irq
irq7:
lri $ac0.m, #0x0007
jmp irq
irq:
lrs $ac1.m, @DMBH
andcf $ac1.m, #0x8000
jlz irq
si @DMBH, #0x8bad
;sr @DMBL, $wr3 ; ???
sr @DMBL, $ac0.m ; Exception number
si @DIRQ, #0x0001
halt ; Through some magic this allows us to properly ack the exception in dspspy
;rti ; allow dumping of ucodes which cause exceptions...probably not safe at all
; DMA:s the current state of the registers back to the PowerPC. To do this,
; it must write the contents of all regs to DRAM.
; Unfortunately, this loop uses ar0 so it's best to use AR1 and friends for testing
; when messing with indexing.
send_back:
; make state safe.
set16
; store registers to reg table
sr @REGS_BASE, $ar0
lri $ar0, #(REGS_BASE + 1)
srri @$ar0, $ar1
srri @$ar0, $ar2
srri @$ar0, $ar3
srri @$ar0, $ix0
srri @$ar0, $ix1
srri @$ar0, $ix2
srri @$ar0, $ix3
srri @$ar0, $wr0
srri @$ar0, $wr1
srri @$ar0, $wr2
srri @$ar0, $wr3
srri @$ar0, $st0
srri @$ar0, $st1
srri @$ar0, $st2
srri @$ar0, $st3
srri @$ar0, $ac0.h
srri @$ar0, $ac1.h
srri @$ar0, $cr
srri @$ar0, $sr
srri @$ar0, $prod.l
srri @$ar0, $prod.m1
srri @$ar0, $prod.h
srri @$ar0, $prod.m2
srri @$ar0, $ax0.l
srri @$ar0, $ax1.l
srri @$ar0, $ax0.h
srri @$ar0, $ax1.h
srri @$ar0, $ac0.l
srri @$ar0, $ac1.l
srri @$ar0, $ac0.m
srri @$ar0, $ac1.m
; Regs are stored. Prepare DMA.
lri $ax0.l, #0x0000
lri $ax1.l, #1 ;(DSP_CR_IMEM | DSP_CR_TO_CPU)
lri $ax0.h, #0x200
lr $ac0.l, @MEM_HI
lr $ac0.m, @MEM_LO
lri $ar1, #8+8
; Now, why are we looping here?
bloop $ar1, dma_copy
call do_dma
addi $ac0.m, #0x200
mrr $ac1.m, $ax0.l
addi $ac1.m, #0x100
mrr $ax0.l, $ac1.m
nop
dma_copy:
nop
; Wait for the CPU to send us a mail.
call wait_for_dsp_mbox
si @DMBH, #0x8888
si @DMBL, #0xfeeb
si @DIRQ, #0x0001
; wait for the CPU to recieve our response before we execute the next op
call wait_for_cpu_mbox
lrs $ac0.m, @CMBL
andi $ac1.m, #0x7fff
; Restore all regs again so we're ready to execute another op.
lri $ar0, #REGS_BASE+1
lrri $ar1, @$ar0
lrri $ar2, @$ar0
lrri $ar3, @$ar0
lrri $ix0, @$ar0
lrri $ix1, @$ar0
lrri $ix2, @$ar0
lrri $ix3, @$ar0
lrri $wr0, @$ar0
lrri $wr1, @$ar0
lrri $wr2, @$ar0
lrri $wr3, @$ar0
lrri $st0, @$ar0
lrri $st1, @$ar0
lrri $st2, @$ar0
lrri $st3, @$ar0
lrri $ac0.h, @$ar0
lrri $ac1.h, @$ar0
lrri $cr, @$ar0
lrri $sr, @$ar0
lrri $prod.l, @$ar0
lrri $prod.m1, @$ar0
lrri $prod.h, @$ar0
lrri $prod.m2, @$ar0
lrri $ax0.l, @$ar0
lrri $ax1.l, @$ar0
lrri $ax0.h, @$ar0
lrri $ax1.h, @$ar0
lrri $ac0.l, @$ar0
lrri $ac1.l, @$ar0
lrri $ac0.m, @$ar0
lrri $ac1.m, @$ar0
lr $ar0, @REGS_BASE
ret ; from send_back
; If you are in set40 mode, use this instead of send_back if you want to stay
; in set40 mode.
send_back_40:
set16
call send_back
set40
ret
; This one's odd. Doesn't look like it should work since it uses ac0.m but
; increments acm0... (acc0)
; -- It's ok as addis adds short immediate to mid accumulator $acD.hm
dump_memory:
lri $ar2, #0x0000
lri $ac0.m, #0x1000
lri $ar1, #0x1000
bloop $ar1, _fill_loop2
mrr $ar3, $ac0.m
nx'ld : $ax0.h, $ax1.h, @$ar0
mrr $ac1.m, $ar0
mrr $ar0, $ar2
srri @$ar0, $ax1.h
mrr $ar2, $ar0
mrr $ar0, $ac1.m
addis $ac0.m, #0x1
_fill_loop2:
nop
ret ; from dump_memory
; Obviously this must be included directly before your test code
start_of_test: