rspboot.s
3.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*
* rspboot.s
*
* Fri Apr 7 10:35:20 PDT 1995
*
* The RSP boot ucode is loaded by the host processor.
*
* The task header (OSTask) is loaded by the host processor into
* the very end of DMEM.
*
*/
#include <rcp.h>
#include <rsp.h>
#include <os.h>
#include <sptask.h>
.text RSPBOOTBASE
.name zero, $0
.name taskp, $1
.name tmp, $30
.name return, $31
RSPBoot:
/*
* Jump to beginning of Boot routine
*/
j checkDP
addi taskp, zero, ((SP_DMEM_END)+(-(OS_TASK_SIZE))+1)
### BRANCH OCCURS HERE TO checkDP:
# register $1 now has the task header address
#
# format for the task header:
# (see os.h)
#
#
# Load the ucode:
#
loadUCode:
lw $2, OS_TASK_OFF_UCODE(taskp) # ucode pointer
addi $3, zero, ((4096)+(-(32*4))+(-1)) # ucode size
.name task_base, $7
addi task_base, zero, TASKBASELO
mtc0 $7, DMA_CACHE
mtc0 $2, DMA_DRAM
mtc0 $3, DMA_READ_LENGTH
loadcodeloop: mfc0 $4, $6 # wait for the code to load
bne $4, zero, loadcodeloop
nop
jal YieldCheck # Do we need to yield?
nop
# jump to beginning of task.
jr task_base
mtc0 zero, SP_RESERVED # delay slot
.name yield, $8
YieldCheck:
mfc0 yield, SP_STATUS
andi yield, yield, SP_STATUS_YIELD
bne yield, zero, doYield
nop
jr return
#define BOOT_YIELD (SP_SET_TASKDONE|SP_SET_YIELDED|SP_CLR_YIELD)
doYield:
mtc0 zero, SP_RESERVED # delay slot
ori yield, zero, BOOT_YIELD
mtc0 yield, SP_STATUS # DONE, Boot Yield
break
nop
.unname yield
#################################################################
#### Stuff after this point may be overwritten by IMEM ####
#################################################################
#
# This is where the boot routine begins
#
#
# if the OS_TASK_DP_WAIT flag is set in the task header
# then wait for the DP to complete before loading
# DMEM (This is neccessary because the DP may be reading
# a display list which is still in DMEM).
#
.name flag, $2
checkDP:
lw flag, OS_TASK_OFF_FLAGS(taskp)
andi flag, flag, OS_TASK_DP_WAIT
beq flag, zero, LoadDMEM
nop
### BRANCH TO LoadDMEM IF OS_TASK_DP_WAIT FLAG IS NOT SET
#
# Spin until the 'dma busy' in DPC_STATUS_REG is clear (meaning the
# DP has read out all of the current display list). While waiting
# continuously check the yield bit by calling YieldCheck in case
# a yield is required before the audio task is complete
#
jal YieldCheck # Do we need to yield?
nop
doDPWait: mfc0 flag, CMD_STATUS
andi flag, flag, 0x100 # dma busy
bgtz flag, YieldCheck # Do we need to yield?
nop
### BRANCH TO YieldCheck (THEN LOOP TO doDPWait UNTIL DP IS FINISHED)
.unname flag
#
# Prepare to load the DMEM for the next task
#
.name daddr, $2
.name dsize, $3
LoadDMEM:
lw daddr, OS_TASK_OFF_UDATA(taskp)
lw dsize, OS_TASK_OFF_UDATA_SZ(taskp)
addi dsize, dsize, -1 # need length - 1
#if 0
# request DMA access: (get semaphore)
ReqDMA:
mfc0 tmp, SP_RESERVED
bne tmp, zero, ReqDMA
nop
#endif
#
# Wait until the DMA is available
#
DMAFull:
mfc0 tmp, DMA_FULL
bne tmp, zero, DMAFull
nop
### LOOP UNTIL DMA IS AVAILABLE
# WARNING!
# We should check here to enforce that we don't overwrite
# the task header. The ucode will need it...
#
# this is an optimization, the PDATA is first in dmem...
#
# Load DMEM for the next task
#
mtc0 zero, DMA_CACHE
mtc0 daddr, DMA_DRAM
mtc0 dsize, DMA_READ_LENGTH
#
# wait for the DMA to complete
#
loaddataloop: mfc0 $4, $6 # wait for the data to load
bne $4, zero, loaddataloop
nop
### LOOP UNTIL DMA IS COMPLETE
jal YieldCheck # Do we need to yield?
nop
j loadUCode
nop
.unname daddr
.unname dsize
.unname zero
.unname tmp
.unname return