gzgfx.s 6.79 KB
/*---------------------------------------------------------------------
  $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 ========*/