rspboot0.s
6.54 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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
#----------------------------------------------------------------------#
# Copyright (C) 1997, Nintendo.
#
# File rspboot0.s
# Coded by Yoshitaka Yasumoto. Nov 28, 1997.
#
# $Id: rspboot0.s,v 1.1.1.1 2002/05/02 03:29:12 blythe Exp $
#----------------------------------------------------------------------#
#include <rcp.h>
#include <rsp.h>
#include <os.h>
#include <sptask.h>
#include "regdef.h"
.text 0x1000
#------ Data 領域のロード処理へ Jump ------
RSPBoot: j RSPBootCheck
lw sys2, OS_TASK_OFF_FLAGS-64(zero)
#------ Text 領域のロード処理 ------
#
# 0x1080 へ OS_TASK_OFF_UCODE で指定したコードを
# 0xfc0 バイト転送する.
# sys1 に OS_TASK_OFF_UCODE がロードされている.
#
LoadText: ori return, zero, TASKBASELO
ori sys0, zero, 0xf80-1
mtc0 sys1, DMA_DRAM
mtc0 return, DMA_CACHE
mtc0 sys0, DMA_READ_LENGTH
#
# DMA 終了待ち
# 終了後 Yield 要求を調べ, 要求が無ければ
# $31(=0x1080)へ Jump する
#
LoadTextWait: mfc0 sys0, DMA_BUSY
bne sys0, zero, LoadTextWait
#------ Yield 要求の調査 ------
#
# Status を調べ CPU からの Yield 要求があるかを調べる
#
YieldCheck: mfc0 sys0, SP_STATUS
andi sys0, sys0, SP_STATUS_YIELD
bne sys0, zero, doYield
ori sys0, zero, 0x1000-64
jr return
#------ Yield 処理 ------
#
# Yield 処理を行なう.
# BootYield の場合, SP_STATUS_YIELD はクリアしておく.
# これにより CPU に RSP が DMEM を使用していないことを
# 知らせる.
#
doYield: ori sys2, zero, \
SP_SET_TASKDONE|SP_SET_YIELDED|SP_CLR_YIELD # Delay
mtc0 sys2, SP_STATUS
break
#------------------------------------------------
# これ以降の IMEM は Overlay される可能性がある
#------------------------------------------------
##############################################
####### マイクロコードチェック ここから ######
##############################################
RSPBootCheck: #
# 不正の時の SP_STATUS へのコマンド
# SP_STATUS_SIG7 を 0 にする
#
lui sys0, SP_CLR_SIG7>>16
#
# boot_dmadram($11)=前回の DMA パラメータが 0x3d8 かどうか
#
ori tmp, zero, 0x3d8
bne boot_dmadram, tmp, RSPBootCheckFalse
addi sys1, zero, RSPBootOverNG
#
# boot_ipl3($4) = IPL3 の先頭(0x040) $4=0x03a04820
#
lui tmp, 0x03a0
ori tmp, tmp, 0x4820
bne boot_ipl3, tmp, RSPBootCheckFalse
#
# snap_ehandler($6) = exception handler の先頭 $6=0x25290004
#
lui tmp, 0x2529
ori tmp, tmp, 0x0004
bne snap_ehandler, tmp, RSPBootCheckFalse
#
# count_cpudma($5) = CPU が 1M の DMA を終了するまでの時間
# 通常 0x4c000-0x4efff 程度
#
srl tmp, count_cpudma, 12
addi tmp2, tmp, -0x4c
bltz tmp2, RSPBootCheckFalse
addi tmp2, tmp, -0x4f
bgtz tmp2, RSPBootCheckFalse
#
# 4k データのチェック
#
vxor vsum_4k, vsum_4k, vsum_4k[1q]
vaddc vsum_4k, vsum_4k, vsum_4k[2h]
vnxor vsum_4k, vsum_4k, vsum_4k[4]
mfc2 tmp, vsum_4k[0]
RSPBootCheck_Compare:
xori tmp, tmp, 0x1234
andi tmp, tmp, 0xffff
bne tmp, zero, RSPBootCheckFalse
#
# DMEM の先頭データ 0x00-0x0f まで (ALL 0/ALL F ではありえない)
#
mfc2 tmp, vboot_dmem[0]
addi tmp, tmp, 1
andi tmp, tmp, 0xfffe
bne tmp, zero, RSPBootCheck_e
vne vboot_dmem, vboot_dmem, vboot_dmem[0]
cfc2 tmp2, $vcc
beq tmp2, zero, RSPBootCheckFalse
RSPBootCheck_e: nop
#
# オーバーレイデータの決定
# 正しいときは Jump 先を RSPBootOK にし
# SP_STATUS_SIG7 を 1 にする
#
RSPBootCheckTrue:
lui sys0, SP_SET_SIG7>>16
addi sys1, zero, RSPBootOverOK
#
# SIG7 の変更
# オーバーレイの開始
#
RSPBootCheckFalse:
mtc0 sys0, SP_STATUS
lw sys0, OS_TASK_OFF_UBOOT-64(zero)
#
# DMA 転送を行なう
#
RSPBootDMA: mfc0 tmp, DMA_FULL # Delay
bne tmp, tmp, RSPBootDMA
nop
mtc0 sys1, DMA_CACHE
mtc0 sys0, DMA_DRAM # 0000000000+19bit+000
j RSPBootOKOK
mtc0 zero, DMA_WRITE_LENGTH
#------ RSPBOOT の自己書き換えコード ------
.align 8
#ifdef PROTECT
RSPBootOverOK: j RSPBootOK
lw sys2, OS_TASK_OFF_FLAGS-64(zero)
RSPBootOverNG: j RSPBootNG
lw sys2, OS_TASK_OFF_FLAGS-64(zero)
#else
RSPBootOverOK: j RSPBootOKOK
lw sys2, OS_TASK_OFF_FLAGS-64(zero)
RSPBootOverNG: j RSPBootOKOK
lw sys2, OS_TASK_OFF_FLAGS-64(zero)
#endif
#------ 正しいときの処理(SIG7 により改変を調べる) ------
RSPBootOK: mfc0 sys1, SP_STATUS
andi sys1, sys1, SP_STATUS_SIG7
bne sys1, zero, RSPBootOKOK
#------ 正しくないときの処理 ------
RSPBootNG: #
# CMD_CLOCK を処理に絡めることで原因を絞り難くする
#
mfc0 sys1, CMD_CLOCK
#
# CMD_CLOCK の値の下位 12 bit が 0 なら RDP を暴走させる
# 1 frame に 2 回評価されるとすると平均 8192/120=68 秒で
# 暴走する
#
andi sys0, sys1, 0x1fff
bne sys0, zero, RSPBootNG0
andi sys0, sys1, 0x7f # 0000-0000-0111-1111b
mtc0 sys1, CMD_END
#
# CMD_CLOCK を取り出してその値に応じた位置へ DMA
# 転送することでコードを徐々に破壊する.
# アドレス 0x000000-0x3fffff のうちの 8byte へ転送する
# ただしこれは平均 128 Boot に 1 度書換えることになる
#
RSPBootNG0: beq sys0, zero, RSPBootDMA
srl sys0, sys1, 2 # CLOCK の値に応じた位置へ DMA する
#------ RDP の処理終了待ち ------
RSPBootOKOK: #
# OS_TASK_DP_WAIT (=0x2) を処理する.
# xbus マイクロコードの場合, DMEM を RDP のコマンド領域として
# 使用するため, RDP の処理が終了するまで, DMEM への DMA 転送
# はできない.
# sys0 に OS_TASK_OFF_FLAGS の内容がロードされている.
#
sll sys2, sys2, 30 # OS_TASP_DP_WAIT を MSB へ
bgezal sys2, LoadData # return へ DPWait のアドレスが入る
lw sys1, OS_TASK_OFF_UDATA_SZ-64(zero)
#
# DP が BUSY かどうかを判定し BUSY なら YieldCheck へ Jump
# YieldCheck 終了後は DPWait へ戻ってくる.
#
DPWait: mfc0 sys0, CMD_STATUS
andi sys0, sys0, 0x100
bne sys0, zero, YieldCheck
#------ Data 領域のロード処理 ------
#
# DMA 受け付け可能待ち
#
LoadData: mfc0 sys0, DMA_FULL # Delay
bne sys0, zero, LoadData
#
# DMA 転送パラメータ設定
# 0x0000 へ OS_TASK_OFF_UDATA で指定したコードを
# OS_TASK_OFF_UDATA_SZ バイト転送する.
# sys1 には OS_TASK_OFF_UDATA_SZ がロードされている.
#
lw sys0, OS_TASK_OFF_UDATA-64(zero)
addi sys1, sys1, -1
mtc0 zero, DMA_CACHE
mtc0 sys0, DMA_DRAM
mtc0 sys1, DMA_READ_LENGTH
#
# DMA 終了待ち
# 終了後 Yield 要求を調べ, 要求が無ければ
# LoadText へ Jump する
#
LoadDataWait: mfc0 sys0, DMA_BUSY
bne sys0, zero, LoadDataWait
ori return, zero, LoadText
#
# Semaphone を 0 にする
# audio ucode のために必要.
#
mtc0 $0, SP_RESERVED
#
# マイクロコードで使用できるようにセットする
# これでマイクロコードと rspboot0 の依存性を高くする
# (例)
# vconst に $v16 を加算する.
#
vxor $v16, $v16, $v16
sw $4, OS_TASK_OFF_UBOOT-64(zero)
j YieldCheck
lw sys1, OS_TASK_OFF_UCODE-64(zero)
#======== End of rspboot0.s ========#