gzgfx.s
6.79 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
/*---------------------------------------------------------------------
$Id: gzgfx.s,v 1.1.1.1 2002/05/02 03:29:12 blythe Exp $
File : gzgfx.s
Coded by Yoshitaka Yasumoto. Jun 18, 1997.
Copyright by Nintendo, Co., Ltd. 1997.
---------------------------------------------------------------------*/
#-----------------------------------------------------------------
# case_G_DL
# Display List のリンクを行なう.
#-----------------------------------------------------------------
case_G_DL:
Assign(param, 1)
Assign(stackp, 2)
Assign(return_inp, 3)
Assign(stacksw, 4)
Assign(dram_adrs, 19)
#------ 新しい Gfx アドレスの計算 ------
#
# gfx1 に代入されているセグメントアドレスを変換し, 新しい
# Gfx アドレスを取得する.
#
slti stacksw, gfxdone, 0 # Main なら 0 Sub なら 1
lbu stackp, RSP_STATEP_DL_N(stacksw)# DL スタックのポインタ
add return_inp, inp, dinp # 次の DL のアドレス保存
jal AdrsFixup_DMA # Segment アドレスの変換
# Branch のとき gfx0 の Bit 16 が 1 となる. (dinp を使わない表現)
sll param, gfx0, 15
bltz param, StartDLload # Branch の時 DMA ロード開始
_mov (inp, dram_adrs) # 新 Gfx アドレスの取得
#------ 呼び出し側の DL アドレスの保存 ------
#
sw return_inp, RSP_DLSTACK_OFFSET(stackp)
addiu stackp, stackp, 4
j StartDLload
sb stackp, RSP_STATEP_DL_N(stacksw)
EndAssign(param, 1)
EndAssign(stackp, 2)
EndAssign(return_inp, 3)
EndAssign(stacksw, 4)
EndAssign(dram_adrs, 19)
#----------------------------------------------------------------
# case_G_ENDDL
# DL スタックを POP して 呼び出し側の DL へ処理を移す
#----------------------------------------------------------------
case_G_ENDDL:
Assign(stackp, 1)
Assign(stacksw, 2)
Assign(sbottom, 3)
srl stacksw, gfxdone, 31 # Main なら 0 Sub なら 1
lbu stackp, RSP_STATEP_DL_N(stacksw)
lbu sbottom, RSP_DLSTACK_BOTTOM(stacksw)
beq stackp, sbottom, case_G_ENDDL_Done
addi stackp, stackp, -4
sb stackp, RSP_STATEP_DL_N(stacksw)
j StartDLload
lw inp, RSP_DLSTACK_OFFSET(stackp)
#------ Stack が空になった時の処理 -----
case_G_ENDDL_Done:
bgtz gfxdone, TaskDone # Main DL なら終了
_li (dinp, 0) # DL カウンタをクリア
jr gfxdone # 終了する
_li (inp, 0)
EndAssign(stackp, 1)
EndAssign(stacksw, 2)
EndAssign(sbottom, 3)
#----------------------------------------------------------------
# case_G_MOVEWORD
# DMEM 内の指定位置に WORD データを書き込む
# 現状では SEGMENT の設定にしか使用していない.
#----------------------------------------------------------------
case_G_MOVEWORD:
Assign(index, 1)
Assign(adrs, 2)
srl index, gfx0, 16
andi index, index, 0xff
lhu adrs, (RSP_MOVEWORD_TBL-MOVEWORD_TBL_BEGIN)(index)
add adrs, adrs, gfx0
jr gfxdone
sw gfx1, 0(adrs)
EndAssign(index, 1)
EndAssign(adrs, 2)
#----------------------------------------------------------------
# case_G_MOVEMEM_EX
#
# DRAM <--> DMEM 間のデータ転送を行なう
# +-----+------+------+----+-+
# |CMD:8|Len :9|Ofs: 9|ID:5|D|
# +-----+------+------+----+-+
# | Dram Adrs:32 |
# +--------------------------+
# D が 0 なら DRAM->DMEM, D が 1 なら DMEM->DRAM
#----------------------------------------------------------------
case_G_MOVEMEM_EX:
AssignForDMAproc
andi iswrite, gfx0, 0x3e # DMEM 領域 ID の取得
jal AdrsFixup_DMA # DRAM アドレスの変換
lhu dmem_adrs, RSP_MOVEMEM_TBL(iswrite) # DMEM 領域 Base
srl dma_len, gfx0, 12 # 転送サイズ取得
andi dma_len, dma_len, 0x0ff8
srl sys0, gfx0, 3 # DMEM 領域 Offset
andi sys0, sys0, 0x0ff8
add dmem_adrs, dmem_adrs, sys0 # DMEM 領域 Base+Offset
jal DMAproc
andi iswrite, gfx0, 1 # R/W フラグ取得
j DMAwait
_mov (return, gfxdone)
EndAssignForDMAproc
#----------------------------------------------------------------
# case_G_SENDSIGNAL
#
# CPU へ SP_BREAK メッセージを送り,
# その際に Adrs へ Param 値を DMA 転送する.
#
# 実際には, SP_STATUS へ Param2 を書き込むので
# Param2 に
# SP_SET_RSPSIGNAL|SP_CLR_TASKDONE|SP_CLR_YIELDED|SP_SET_INTR
# を設定しておく. また Param1 に SP_STATUS_RSPSIGNAL を代入し
# ておく.
#
# +-----+------------------+
# |CMD:8| Param1:24 |
# +-----+------------------+
# | Param2:32 |
# +------------------------+
#----------------------------------------------------------------
AssignForDMAproc
case_G_SENDSIGNAL:
#------ CPU に SP_BREAK メッセージを送る ------
mtc0 gfx1, SP_STATUS
#------ CPU が受信するのを待つ ------
case_G_SENDSIGNAL_1:
andi gfx0, gfx0, SP_STATUS_RSPSIGNAL
bne gfx0, zero, case_G_SENDSIGNAL_1
mfc0 gfx0, SP_STATUS
case_G_SENDSIGNAL_2:
jr gfxdone
sw gfx1, RSP_STATEP_RDPHALF_1L(zero)
EndAssignForDMAproc
#----------------------------------------------------------------
# case_G_SAVEHALF_1
# Gfx1 をセーブしておく
# case_G_SENDSIGNAL_2 と同じで問題なし
#----------------------------------------------------------------
.symbol case_G_SAVEHALF_1, case_G_SENDSIGNAL_2
#-----------------------------------------------------------------
# case_G_SPNOOP
# 何もしない.
# このエントリを他のルーチンから使用している.
# ---> case_G_MULMTX
#-----------------------------------------------------------------
.symbol case_G_SPNOOP, case_G_SENDSIGNAL_2
#----------------------------------------------------------------
# case_G_WAITSIGNAL
#
# SP_STATUS の SP_STATUS_CPUSIGNAL が 1 ならパラメータを
# 取得に行き, その値が Param 以上になるまで待つ.
# +-----+------------------+
# |CMD:8| Adrs:24 |
# +-----+------------------+
# | Param:32 |
# +------------------------+
#
#----------------------------------------------------------------
AssignForDMAproc
Assign(flag, 1)
case_G_WAITSIGNAL:
#------ SP_STATUS_CPUSIGNAL が 1 になるまで待機 ------
mfc0 iswrite, SP_STATUS
andi iswrite, iswrite, SP_STATUS_CPUSIGNAL
beq iswrite, zero, case_G_WAITSIGNAL_1
#------ SP_STATUS_CPUSIGNAL = 1 を確認したら 0 にする ------
lui flag, (SP_CLR_CPUSIGNAL>>16)
mtc0 flag, SP_STATUS
#------ DRAM から 8 byte DMA 転送する ------
_liu (dmem_adrs, RSP_WAITSIGNAL_STATUS)
_li (dma_len, 7)
jal DMAread
_mov (dram_adrs, gfx0)
jal DMAwait
case_G_WAITSIGNAL_1:
lw sys1, RSP_WAITSIGNAL_STATUS(zero)
sltu sys1, sys1, gfx1 # STATUS < Param なら 1
sll sys1, sys1, 3 # 8 倍する
jr gfxdone
sub dinp, dinp, sys1 # DL 位置の操作
EndAssign(flag, 1)
EndAssignForDMAproc
#---------------------------------------------------------------------
# セグメントアドレスの変換処理 (DMA 用)
# gfx1 の値を変換し, dram_adrs に代入する.
# DMA 処理においては bit 23-0 のみ有効なので, 上位 8 bit は
# ケアしない.
#---------------------------------------------------------------------
AdrsFixup_DMA:
srl $19, gfx1, 22
andi $19, $19, 0x3c
lw $19, RSP_SEG_OFFSET($19)
jr return
add $19, gfx1, $19
/*======== End of gzgfx.s ========*/