mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-12-26 19:44:30 +01:00
51c26d82a5
This makes the point where execution starts more obvious compared to a start_of_test label at the end of the include, and allows putting other functions at the start of the file. This change also modifies the existing tests to build with this change.
284 lines
5.7 KiB
PHP
284 lines
5.7 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
|
|
|
|
WARNPC 0x10
|
|
ORG 0x10
|
|
|
|
; Main code (and normal entrypoint) at 0x10
|
|
; It is expected that IRQs were listed beforehand
|
|
; (e.g. by including dsp_base.inc instead of dsp_base_noirq.inc)
|
|
sbset #0x02
|
|
sbset #0x03
|
|
sbclr #0x04
|
|
sbset #0x05
|
|
sbset #0x06
|
|
|
|
s16
|
|
lri $CR, #0x00ff
|
|
|
|
clr $acc1
|
|
clr $acc0
|
|
|
|
; get address of memory dump and copy it to DRAM
|
|
call 0x807e
|
|
si @DMBH, #0x8888
|
|
si @DMBL, #0xdead
|
|
si @DIRQ, #0x0001
|
|
|
|
call 0x8078
|
|
andi $ac0.m, #0x7fff
|
|
lrs $ac1.m, @CMBL
|
|
|
|
sr @MEM_HI, $ac0.m
|
|
sr @MEM_LO, $ac1.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 0x807e
|
|
si @DMBH, #0x8888
|
|
si @DMBL, #0xbeef
|
|
si @DIRQ, #0x0001
|
|
|
|
call 0x8078
|
|
andi $ac0.m, #0x7fff
|
|
lrs $ac1.m, @CMBL
|
|
|
|
sr @MEM_HI, $ac0.m
|
|
sr @MEM_LO, $ac1.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 test_main
|
|
|
|
; This is where we jump when we're done testing, see above.
|
|
; We just fall into a loop, playing dead until someone resets the DSP.
|
|
end_of_test:
|
|
nop
|
|
jmp end_of_test
|
|
|
|
; Utility function to do DMA.
|
|
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.
|
|
wait_dma_finish:
|
|
lr $ac1.m, @DSCR
|
|
andcf $ac1.m, #0x4
|
|
jlz wait_dma_finish
|
|
ret
|
|
|
|
; IRQ handlers. Just send back exception# and die
|
|
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:
|
|
lrs $ac0.m, @DMBH
|
|
andcf $ac0.m, #0x8000
|
|
jlz irq5
|
|
si @DMBH, #0x8005
|
|
si @DMBL, #0x0000
|
|
si @DIRQ, #0x0001
|
|
lri $ac0.m, #0xbbbb
|
|
sr @0xffda, $ac0.m ; pred scale
|
|
sr @0xffdb, $ac0.m ; yn1
|
|
lr $ix2, @ARAM
|
|
sr @0xffdc, $ac0.m ; yn2
|
|
rti
|
|
irq6:
|
|
lri $ac0.m, #0x0006
|
|
jmp irq
|
|
irq7:
|
|
lri $ac0.m, #0x0007
|
|
|
|
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.
|
|
send_back:
|
|
; first, store $sr so we can modify it
|
|
sr @(REGS_BASE + 19), $sr
|
|
set16
|
|
; Now store $wr0, as it must be 0xffff for srri to work as we expect
|
|
sr @(REGS_BASE + 8), $wr0
|
|
lri $wr0, #0xffff
|
|
; 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
|
|
; skip $wr0 since we already stored and modified it
|
|
iar $ar0
|
|
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
|
|
; skip $sr since we already stored and modified it
|
|
iar $ar0
|
|
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.
|
|
; $cr must be 0x00ff because the ROM uses lrs and srs with the assumption that
|
|
; they will modify hardware registers.
|
|
lri $cr, #0x00ff
|
|
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
|
|
|
|
; Now, why are we looping here?
|
|
lri $ar1, #8+8
|
|
bloop $ar1, dma_copy
|
|
call do_dma
|
|
addi $ac0.m, #0x200
|
|
mrr $ac1.m, $ax0.l
|
|
addi $ac1.m, #0x100
|
|
dma_copy:
|
|
mrr $ax0.l, $ac1.m
|
|
|
|
; Wait for the CPU to send us a mail.
|
|
call 0x807e
|
|
si @DMBH, #0x8888
|
|
si @DMBL, #0xfeeb
|
|
si @DIRQ, #0x0001
|
|
|
|
; wait for the CPU to recieve our response before we execute the next op
|
|
call 0x8078
|
|
andi $ac0.m, #0x7fff
|
|
lrs $ac1.m, @CMBL
|
|
|
|
; 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
|
|
; leave $wr for later
|
|
iar $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
|
|
; leave $sr for later
|
|
iar $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
|
|
lr $wr0, @(REGS_BASE+8)
|
|
lr $sr, @(REGS_BASE+19)
|
|
|
|
ret ; from send_back
|