/*
	-----------------------------------------------
	(C) 2005, Saotome/TheMirek


	thanks for bugfixing help to: ps2devman

	changelog:
	20050409 first release
	20070223 wait argument (wait for transfer to finish) was wrong way round, fixed! (1=wait, 0=don't)

	-----------------------------------------------
*/

#include <tamtypes.h>
#include "vu.h"

#define vu0_micromem ((volatile int*)0x11000000)
#define vu0_mem ((volatile float*)0x11004000)
#define vu1_micromem ((volatile int*)0x11008000)
#define vu1_mem ((volatile float*)0x1100c000)

#define VIF0FIFO *((volatile u32*)0x10004000)
#define VIF0STAT *((volatile u32*)0x10003800)

#define D0_CHCR *((volatile unsigned int*)0x10008000)
#define D0_MADR *((volatile unsigned int*)0x10008010)
#define D0_QWC *((volatile unsigned int*)0x10008020)
#define D0_TADR *((volatile unsigned int*)0x10008030)

#define VIF1FIFO *((volatile u32*)0x10005000)
#define VIF1STAT *((volatile u32*)0x10003c00)

#define D1_CHCR *((volatile unsigned int*)0x10009000)
#define D1_MADR *((volatile unsigned int*)0x10009010)
#define D1_QWC *((volatile unsigned int*)0x10009020)
#define D1_TADR *((volatile unsigned int*)0x10009030)

//If global method is used, we need a big buffer!
u32 vifDMAtag[14124] __attribute__((aligned(16)));
//for 32767 non striped faces max (max 3DS capability)
//=> a bit less than 300.000 qwords : 3x(uv+norm+xyz)+1Gif-Tag every 85*3 qwords
//=> 1177 ref dma-tags with UNPACK vif-tags (handles 256 qwords) + 1177 MSCNT + 1177 FLUSH
//=> 3531 qwords =  14124 dwords = 56496 bytes

//-----------------------------------------------
void vu0UploadCode(void *code, u32 size, u32 destoffset, u32 wait)
{	
	asm __volatile__("
		.set noreorder
		addiu	%1,%1,0xf
		lui		$8,0x3000
		srl		%1,%1,4
		or		$11,%4,$8
		lui		$10,0x4a00		#// VIF-MPG-code
		lui		$8,0x1000
		or		$10,$10,%2
		ori		$8,$8,0x8000	#// VIF0-DMA-channel
		ori		$13,$0,256
		dsll32	$10,$10,0
		dsll32	$13,$13,0

vu0upcwait0:
		lw		$9,0x00($8)
		nop
		nop
		nop
		andi	$9,$9,0x100
		nop
		bgtz	$9,vu0upcwait0
		nop

		.align 3
vu0upcloop:
		addi	$12,%1,-128
		lui		$9,0x3000		#// DMA-Tag, Tag-ID:'ref'
		blez	$12,vu0upclast
		ori		$9,$9,128
		dsll32	$12,%0,0
		addi	%0,%0,2048		#// src +2048 bytes
		or		$9,$9,$12
		addi	%1,%1,-128
		pcpyld	$12,$10,$9
		daddu	$10,$10,$13		#// dst +256 dwords
		sq		$12,0x0($11)	#// save DMATAG+VIFcode uncached-accelerated
		beq		$0,$0,vu0upcloop
		addi	$11,$11,16

vu0upclast:
		andi	$13,%1,127
		dsll32	$12,%0,0
		dsll32	$13,$13,17
		or		$9,$12,%1
		or		$10,$10,$13
		
		pcpyld	$12,$10,$9
		
		sq		$12,0x0($11)	#// save DMATAG+VIFcode uncached-accelerated


		sw		%4,0x30($8)		#// tadr = vifDMAtag
		ori		$9,$0,0x145
		sw		$0,0x20($8)		#// qwc = 0
		sync					#// sync: flush uncached accelerated buffer
		sw		$9,0x00($8)		#// chcr = 0x145, -> start
		beq		%3,$0,vu0upcend

vu0upcwait1:
		lw		$9,0x00($8)
		nop
		nop
		nop
		nop
		nop
		andi	$9,$9,0x100
		nop
		bgtz	$9,vu0upcwait1
		nop
vu0upcend:
		.set reorder
		"
		:
		: "r"(code), "r"(size), "r"(destoffset), "r"(wait), "r"(vifDMAtag)
		: "$8", "$9", "$10", "$11", "$12", "$13", "memory"
	);
}
//-----------------------------------------------
void vu0UploadData(void *data, u32 size, u32 destoffset, u32 wait)
{	
	asm __volatile__("
		.set noreorder
		addiu	%1,%1,0xf
		lui		$8,0x3000
		srl		%1,%1,4
		or		$11,%4,$8
		lui		$10,0x6c00		#// VIF-UNPACK-code (V4-32)
		lui		$8,0x1000
		or		$10,$10,%2
		ori		$8,$8,0x8000	#// VIF0-DMA-channel
		ori		$13,$0,256
		dsll32	$10,$10,0
		dsll32	$13,$13,0

vu0updwait0:
		lw		$9,0x00($8)
		nop
		nop
		nop
		andi	$9,$9,0x100
		nop
		bgtz	$9,vu0updwait0
		nop

		.align 3
vu0updloop:
		addi	$12,%1,-256
		lui		$9,0x3000		#// DMA-Tag, Tag-ID:'ref'
		blez	$12,vu0updlast
		ori		$9,$9,256
		dsll32	$12,%0,0
		addi	%0,%0,4096		#// src +4096 bytes
		or		$9,$9,$12
		addi	%1,%1,-256
		pcpyld	$12,$10,$9
		daddu	$10,$10,$13		#// dst +256 qwords
		sq		$12,0x0($11)	#// save DMATAG+VIFcode uncached-accelerated
		beq		$0,$0,vu0updloop
		addi	$11,$11,16

vu0updlast:
		andi	$13,%1,255
		dsll32	$12,%0,0
		dsll32	$13,$13,16
		or		$9,$12,%1
		or		$10,$10,$13
		
		pcpyld	$12,$10,$9
		
		sq		$12,0x0($11)	#// save DMATAG+VIFcode uncached-accelerated


		sw		%4,0x30($8)		#// tadr = vifDMAtag
		ori		$9,$0,0x145
		sw		$0,0x20($8)		#// qwc = 0
		sync					#// sync: flush uncached accelerated buffer
		sw		$9,0x00($8)		#// chcr = 0x145, -> start
		beq		%3,$0,vu0updend

vu0updwait1:
		lw		$9,0x00($8)
		nop
		nop
		nop
		nop
		nop
		andi	$9,$9,0x100
		nop
		bgtz	$9,vu0updwait1
		nop
vu0updend:
		.set reorder
		"
		:
		: "r"(data), "r"(size), "r"(destoffset), "r"(wait), "r"(vifDMAtag)
		: "$8", "$9", "$10", "$11", "$12", "$13", "memory"
	);
}
//-----------------------------------------------
void vu0ClearData()
{
	asm __volatile__("
		addiu	$8,$0,1024
		.align 3
loopvu0clear:
		sq	$0,0x0(%0)
		sq	$0,0x10(%0)
		sq	$0,0x20(%0)
		addi	$8,$8,-4
		sq	$0,0x30(%0)
		addiu	%0,%0,0x40
		bgtz	$8,loopvu0clear
		"
		:
		: "r"(vu0_mem)
		: "$8", "memory"
	);
}
//-----------------------------------------------
void vu0Wait()
{
	//asm __volatile__("qmfc2.i $8,vf01":::"$8"); // read vu0 register with interlock

	asm __volatile__("
		.set noreorder
		lui		$8,0x1000
vu0wait0:
		lw		$9,0x3800($8)
		nop		
		nop
		nop
		andi	$9,$9,4
		nop
		bgtz	$9,vu0wait0
		nop
		.set reorder
		"
		:
		:
		: "$8", "$9", "memory"
	);
}
//-----------------------------------------------
void vu0Start(u32 offset)
{
	/* asm __volatile__("vcallms 0"); //old version offset=0 */

	u32 vif0mscaltag = 0x14000000 | offset;

	asm __volatile__("
		mtsah	$0,2
		qfsrv	$8,%0,$0	/* shift tag by 96 bits left */
		sq	$8,0x0(%1)		/* send MSCAL-code to Vif0-FIFO */
		"
		:
		: "r"(vif0mscaltag), "r"(&VIF0FIFO)
		: "$8", "memory"
	);
}
//-----------------------------------------------
void vu1UploadCode(void *code, u32 size, u32 destoffset, u32 wait)
{
	asm __volatile__("
		.set noreorder
		addiu	%1,%1,0xf
		lui		$8,0x3000
		srl		%1,%1,4
		or		$11,%4,$8
		lui		$10,0x4a00		#// VIF-MPG-code
		lui		$8,0x1000
		or		$10,$10,%2
		ori		$8,$8,0x9000	#// VIF1-DMA-channel
		ori		$13,$0,256
		dsll32	$10,$10,0
		dsll32	$13,$13,0

vu1upcwait0:
		lw		$9,0x00($8)
		nop
		nop
		nop
		andi	$9,$9,0x100
		nop
		bgtz	$9,vu1upcwait0
		nop

		.align 3
vu1upcloop:
		addi	$12,%1,-128
		lui		$9,0x3000		#// DMA-Tag, Tag-ID:'ref'
		blez	$12,vu1upclast
		ori		$9,$9,128
		dsll32	$12,%0,0
		addi	%0,%0,2048		#// src +2048 bytes
		or		$9,$9,$12
		addi	%1,%1,-128
		pcpyld	$12,$10,$9
		daddu	$10,$10,$13		#// dst +256 dwords
		sq		$12,0x0($11)	#// save DMATAG+VIFcode uncached-accelerated
		beq		$0,$0,vu1upcloop
		addi	$11,$11,16

vu1upclast:
		andi	$13,%1,127
		dsll32	$12,%0,0
		dsll32	$13,$13,17
		or		$9,$12,%1
		or		$10,$10,$13
		
		pcpyld	$12,$10,$9
		
		sq		$12,0x0($11)	#// save DMATAG+VIFcode uncached-accelerated


		sw		%4,0x30($8)		#// tadr = vifDMAtag
		ori		$9,$0,0x145
		sw		$0,0x20($8)		#// qwc = 0
		sync					#// sync: flush uncached accelerated buffer
		sw		$9,0x00($8)		#// chcr = 0x145, -> start
		beq		%3,$0,vu1upcend

vu1upcwait1:
		lw		$9,0x00($8)
		nop		
		nop
		nop
		nop
		nop
		andi	$9,$9,0x100
		nop
		bgtz	$9,vu1upcwait1
		nop
vu1upcend:
		.set reorder
		"
		:
		: "r"(code), "r"(size), "r"(destoffset), "r"(wait), "r"(vifDMAtag)
		: "$8", "$9", "$10", "$11", "$12", "$13", "memory"
	);
	/*FlushCache(0);
	for (i = 0; i < 8; i++)
		printf("dmatag:%x %x %x %x\n", vifDMAtag[4*i+0],vifDMAtag[4*i+1],vifDMAtag[4*i+2],vifDMAtag[4*i+3]);
	*/
}
//-----------------------------------------------
void vu1UploadData(void *data, u32 size, u32 destoffset, u32 wait)
{
	asm __volatile__("
		.set noreorder
		addiu	%1,%1,0xf
		lui		$8,0x3000
		srl		%1,%1,4
		or		$11,%4,$8
		lui		$10,0x6c00		#// VIF-UNPACK-code (V4-32)
		lui		$8,0x1000
		or		$10,$10,%2
		ori		$8,$8,0x9000	#// VIF1-DMA-channel
		ori		$13,$0,256
		dsll32	$10,$10,0
		dsll32	$13,$13,0

vu1updwait0:
		lw		$9,0x00($8)
		nop
		nop
		nop
		andi	$9,$9,0x100
		nop
		bgtz	$9,vu1updwait0
		nop

		.align 3
vu1updloop:
		addi	$12,%1,-256
		lui		$9,0x3000		#// DMA-Tag, Tag-ID:'ref'
		blez	$12,vu1updlast
		ori		$9,$9,256
		dsll32	$12,%0,0
		addi	%0,%0,4096		#// src +4096 bytes
		or		$9,$9,$12
		addi	%1,%1,-256
		pcpyld	$12,$10,$9
		daddu	$10,$10,$13		#// dst +256 qwords
		sq		$12,0x0($11)	#// save DMATAG+VIFcode uncached-accelerated
		beq		$0,$0,vu1updloop
		addi	$11,$11,16

vu1updlast:
		andi	$13,%1,255
		dsll32	$12,%0,0
		dsll32	$13,$13,16
		or		$9,$12,%1
		or		$10,$10,$13
		
		pcpyld	$12,$10,$9
		
		sq		$12,0x0($11)	#// save DMATAG+VIFcode uncached-accelerated


		sw		%4,0x30($8)		#// tadr = vifDMAtag
		ori		$9,$0,0x145
		sw		$0,0x20($8)		#// qwc = 0
		sync					#// sync: flush uncached accelerated buffer
		sw		$9,0x00($8)		#// chcr = 0x145, -> start
		beq		%3,$0,vu1updend

vu1updwait1:
		lw		$9,0x00($8)
		nop
		nop
		nop
		nop
		nop
		andi	$9,$9,0x100
		nop
		bgtz	$9,vu1updwait1
		nop
vu1updend:
		.set reorder
		"
		:
		: "r"(data), "r"(size), "r"(destoffset), "r"(wait), "r"(vifDMAtag)
		: "$8", "$9", "$10", "$11", "$12", "$13", "memory"
	);
	/*FlushCache(0);
	for (i = 0; i < 4; i++)
		printf("dmatag:%x %x %x %x\n", vifDMAtag[4*i+0],vifDMAtag[4*i+1],vifDMAtag[4*i+2],vifDMAtag[4*i+3]);
	*/
}
//-----------------------------------------------
void vu1ClearData()
{
	asm __volatile__("
		addiu	$8,$0,1024
		.align 3
loopvu1clear:
		sq	$0,0x0(%0)
		sq	$0,0x10(%0)
		sq	$0,0x20(%0)
		addi	$8,$8,-4
		sq	$0,0x30(%0)
		addiu	%0,%0,0x40
		bgtz	$8,loopvu1clear
		"
		:
		: "r"(vu1_mem)
		: "$8", "memory"
	);
}
//-----------------------------------------------
void vu1Wait()
{
  asm __volatile__(
		   "loop00:\n"
		   "nop\n"
		   "nop\n"
		   "nop\n"
		   "nop\n"
		   "nop\n"
		   "nop\n"
		   "bc2t loop00\n"
		   "nop\n");
}
//-----------------------------------------------
void vu1Start(u32 offset)
{	
	u32 vif1mscaltag = 0x14000000 | offset;

	asm __volatile__("
		mtsah	$0,2
		qfsrv	$8,%0,$0	/* shift tag by 96 bits left */
		sq	$8,0x0(%1)		/* send MSCAL-code to Vif1-FIFO */
		"
		:
		: "r"(vif1mscaltag), "r"(&VIF1FIFO)
		: "$8", "memory"
	);
}
//-----------------------------------------------
void vu1UploadDataCont(void *data, u32 size, u32 destoffset, u32 wait)
{
	asm __volatile__("
		.set noreorder
		addiu	%1,%1,0xf
		lui		$8,0x3000
		srl		%1,%1,4
		or		$11,%4,$8
		lui		$10,0x6c00		#// VIF-UNPACK-code (V4-32)
		lui		$8,0x1000
		or		$10,$10,%2
		ori		$8,$8,0x9000	#// VIF1-DMA-channel
		ori		$13,$0,256
		dsll32	$10,$10,0
		dsll32	$13,$13,0

vu1updcwait0:
		lw		$9,0x00($8)
		nop
		nop
		nop
		andi	$9,$9,0x100
		nop
		bgtz	$9,vu1updcwait0
		nop

		.align 3
vu1updcloop:
		addi	$12,%1,-256
		lui		$9,0x3000		#// DMA-Tag, Tag-ID:'ref'
		blez	$12,vu1updclast
		ori		$9,$9,256
		dsll32	$12,%0,0
		addi	%0,%0,4096		#// src +4096 bytes
		or		$9,$9,$12
		addi	%1,%1,-256
		pcpyld	$12,$10,$9
		daddu	$10,$10,$13		#// dst +256 qwords
		sq		$12,0x0($11)	#// save DMATAG(ref)+VIFcode uncached-accelerated
		beq		$0,$0,vu1updcloop
		addi	$11,$11,16

vu1updclast:
		andi	$13,%1,255
		dsll32	$12,%0,0	#//$12=src<<32
		dsll32	$13,$13,16	#//$13=n<<48
		lui		$9,0x3000		#// DMA-Tag, Tag-ID:'ref' (instead of 'refe') (p59 EE user manual)
		or		$9,$9,%1	#//$10:$9=0x6c000000<<(32+64)+n<<(48+64)+dst<<64+src<<32+Tag-ID<<28+index
		or		$9,$9,$12
		or		$10,$10,$13
		
		pcpyld	$12,$10,$9
		
		sq		$12,0x0($11)	#// save DMATAG(refe)+VIFcode uncached-accelerated
		addi	$11,$11,16

		lui	$10,0x1700	#//Vif-Tag MSCNT
		dsll32	$10,$10,0
		lui		$9,0x7000		#// DMA-Tag, Tag-ID:'end'
						
		
		pcpyld	$12,$10,$9	#//$10:$9=0x17000000<<(32+64)+n<<(48+64)+dst<<64+src<<32+(Tag-ID)<<28+index
		
		sq		$12,0x0($11)	#// save DMATAG(end)+VIFcode(MSCNT) uncached-accelerated


		sw		%4,0x30($8)		#// tadr = vifDMAtag
		ori		$9,$0,0x145
		sw		$0,0x20($8)		#// qwc = 0
		sync					#// sync: flush uncached accelerated buffer
		sw		$9,0x00($8)		#// chcr = 0x145, -> start
		beq		%3,$0,vu1updcend

vu1updcwait1:
		lw		$9,0x00($8)
		nop
		nop
		nop
		nop
		nop
		andi	$9,$9,0x100
		nop
		bgtz	$9,vu1updcwait1
		nop
vu1updcend:
		.set reorder
		"
		:
		: "r"(data), "r"(size), "r"(destoffset), "r"(wait), "r"(vifDMAtag)
		: "$8", "$9", "$10", "$11", "$12", "$13", "memory"
	);
	/*FlushCache(0);
	for (i = 0; i < 4; i++)
		printf("dmatag:%x %x %x %x\n", vifDMAtag[4*i+0],vifDMAtag[4*i+1],vifDMAtag[4*i+2],vifDMAtag[4*i+3]);
	*/
}
//-----------------------------------------------
void vu1UploadDataContFlush(void *data, u32 size, u32 destoffset, u32 wait)
{
	asm __volatile__("
		.set noreorder
		addiu	%1,%1,0xf
		lui		$8,0x3000
		srl		%1,%1,4
		or		$11,%4,$8
		lui		$10,0x6c00		#// VIF-UNPACK-code (V4-32)
		lui		$8,0x1000
		or		$10,$10,%2
		ori		$8,$8,0x9000	#// VIF1-DMA-channel
		ori		$13,$0,256
		dsll32	$10,$10,0
		dsll32	$13,$13,0

vu1updfcwait0:
		lw		$9,0x00($8)
		nop
		nop
		nop
		andi	$9,$9,0x100
		nop
		bgtz	$9,vu1updfcwait0
		nop

		.align 3
vu1updfcloop:
		addi	$12,%1,-256
		lui		$9,0x3000		#// DMA-Tag, Tag-ID:'ref'
		blez	$12,vu1updfclast
		ori		$9,$9,256
		dsll32	$12,%0,0
		addi	%0,%0,4096		#// src +4096 bytes
		or		$9,$9,$12
		addi	%1,%1,-256
		pcpyld	$12,$10,$9
		daddu	$10,$10,$13		#// dst +256 qwords
		sq		$12,0x0($11)	#// save DMATAG(ref)+VIFcode uncached-accelerated
		beq		$0,$0,vu1updfcloop
		addi	$11,$11,16

vu1updfclast:
		andi	$13,%1,255
		dsll32	$12,%0,0	#//$12=src<<32
		dsll32	$13,$13,16	#//$13=n<<48
		lui		$9,0x3000		#// DMA-Tag, Tag-ID:'ref' (instead of 'refe') (p59 EE user manual)
		or		$9,$9,%1	#//$10:$9=0x6c000000<<(32+64)+n<<(48+64)+dst<<64+src<<32+Tag-ID<<28+index
		or		$9,$9,$12
		or		$10,$10,$13
		
		pcpyld	$12,$10,$9
		
		sq		$12,0x0($11)	#// save DMATAG(refe)+VIFcode uncached-accelerated
		addi	$11,$11,16




		lui	$10,0x1700	#//Vif-Tag MSCNT
		dsll32	$10,$10,0
		lui		$9,0x1000		#// DMA-Tag, Tag-ID:'cnt'
		
		pcpyld	$12,$10,$9	#//$10:$9=0x17000000<<(32+64)+n<<(48+64)+dst<<64+src<<32+(Tag-ID)<<28+index
		
		sq		$12,0x0($11)	#// save DMATAG(end)+VIFcode(MSCNT) uncached-accelerated
		addi	$11,$11,16




		lui	$10,0x1100	#//Vif-Tag FLUSH
		dsll32	$10,$10,0
		lui		$9,0x7000		#// DMA-Tag, Tag-ID:'end'
		
		pcpyld	$12,$10,$9	#//$10:$9=0x11000000<<(32+64)+n<<(48+64)+dst<<64+src<<32+(Tag-ID)<<28+index
		
		sq		$12,0x0($11)	#// save DMATAG(end)+VIFcode(FLUSH) uncached-accelerated



		sw		%4,0x30($8)		#// tadr = vifDMAtag
		ori		$9,$0,0x145
		sw		$0,0x20($8)		#// qwc = 0
		sync					#// sync: flush uncached accelerated buffer
		sw		$9,0x00($8)		#// chcr = 0x145, -> start
		beq		%3,$0,vu1updfcend

vu1updfcwait1:
		lw		$9,0x00($8)
		nop
		nop
		nop
		nop
		nop
		andi	$9,$9,0x100
		nop
		bgtz	$9,vu1updfcwait1
		nop
vu1updfcend:
		.set reorder
		"
		:
		: "r"(data), "r"(size), "r"(destoffset), "r"(wait), "r"(vifDMAtag)
		: "$8", "$9", "$10", "$11", "$12", "$13", "memory"
	);
	/*FlushCache(0);
	for (i = 0; i < 4; i++)
		printf("dmatag:%x %x %x %x\n", vifDMAtag[4*i+0],vifDMAtag[4*i+1],vifDMAtag[4*i+2],vifDMAtag[4*i+3]);
	*/
}
//-----------------------------------------------
void vu1Set(u32 cmd, u32 value)
{	
	u32 vif1tag = cmd | value;

	asm __volatile__("
		mtsah	$0,2
		qfsrv	$8,%0,$0	/* shift tag by 96 bits left */
		sq	$8,0x0(%1)		/* send MSCAL-code to Vif1-FIFO */
		"
		:
		: "r"(vif1tag), "r"(&VIF1FIFO)
		: "$8", "memory"
	);
}
//-----------------------------------------------
void vu1UploadHugeDataCont(void *data, u32 size, u32 destoffset, u32 wait)
{
	//special case : 1 Gif-tag plus 85 triple qwords sent per batch
	//= 256*16 bytes sent, exactly the amount of data handled by 1 dma-tag ref
	//that means we can insert MSCNT in the same loop and process all batches at once
	//(and we can stop incrementing dst offset : we always target offset 0)
	asm __volatile__("
		.set noreorder
		addiu	%1,%1,0xf
		lui		$8,0x3000
		srl		%1,%1,4
		or		$11,%4,$8
		lui		$10,0x6c00		#// VIF-UNPACK-code (V4-32)
		lui		$8,0x1000
		or		$10,$10,%2
		ori		$8,$8,0x9000	#// VIF1-DMA-channel
		ori		$13,$0,256
		dsll32	$10,$10,0
		dsll32	$13,$13,0

vu1uphdcwait0:
		lw		$9,0x00($8)
		nop
		nop
		nop
		andi	$9,$9,0x100
		nop
		bgtz	$9,vu1uphdcwait0
		nop

		.align 3
vu1uphdcloop:
		addi	$12,%1,-256
		lui		$9,0x3000		#// DMA-Tag, Tag-ID:'ref'
		blez	$12,vu1uphdclast
		ori		$9,$9,256
		dsll32	$12,%0,0
		addi	%0,%0,4096		#// src +4096 bytes
		or		$9,$9,$12
		addi	%1,%1,-256
		pcpyld	$12,$10,$9
		sq		$12,0x0($11)	#// save DMATAG(ref)+VIFcode uncached-accelerated
		addi	$11,$11,16


		lui	$14,0x1700	#//Vif-Tag MSCNT
		dsll32	$14,$14,0
		lui		$9,0x1000		#// DMA-Tag, Tag-ID:'cnt'
		pcpyld	$12,$14,$9	#//$14:$9=0x17000000<<(32+64)+n<<(48+64)+dst<<64+src<<32+(Tag-ID)<<28+index
		sq		$12,0x0($11)	#// save DMATAG(end)+VIFcode(MSCNT) uncached-accelerated
		beq		$0,$0,vu1uphdcloop
		addi	$11,$11,16

vu1uphdclast:
		andi	$13,%1,255
		dsll32	$12,%0,0	#//$12=src<<32
		dsll32	$13,$13,16	#//$13=n<<48
		lui		$9,0x3000		#// DMA-Tag, Tag-ID:'ref' (instead of 'refe') (p59 EE user manual)
		or		$9,$9,%1	#//$10:$9=0x6c000000<<(32+64)+n<<(48+64)+dst<<64+src<<32+Tag-ID<<28+index
		or		$9,$9,$12
		or		$10,$10,$13
		pcpyld	$12,$10,$9
		sq		$12,0x0($11)	#// save DMATAG(refe)+VIFcode uncached-accelerated
		addi	$11,$11,16

		lui	$10,0x1700	#//Vif-Tag MSCNT
		dsll32	$10,$10,0
		lui		$9,0x7000		#// DMA-Tag, Tag-ID:'end'
		pcpyld	$12,$10,$9	#//$10:$9=0x17000000<<(32+64)+n<<(48+64)+dst<<64+src<<32+(Tag-ID)<<28+index
		sq		$12,0x0($11)	#// save DMATAG(end)+VIFcode(MSCNT) uncached-accelerated
		beq		%3,$0,vu1uphdcend

vu1uphdcwait1:
		lw		$9,0x00($8)
		nop
		nop
		nop
		nop
		nop
		andi	$9,$9,0x100
		nop
		bgtz	$9,vu1uphdcwait1
		nop
vu1uphdcend:

		sw		%4,0x30($8)		#// tadr = vifDMAtag
		ori		$9,$0,0x145
		sw		$0,0x20($8)		#// qwc = 0
		sync					#// sync: flush uncached accelerated buffer
		sw		$9,0x00($8)		#// chcr = 0x145, -> start

		.set reorder
		"
		:
		: "r"(data), "r"(size), "r"(destoffset), "r"(wait), "r"(vifDMAtag)
		: "$8", "$9", "$10", "$11", "$12", "$13", "$14", "memory"
	);
	/*FlushCache(0);
	for (i = 0; i < 4; i++)
		printf("dmatag:%x %x %x %x\n", vifDMAtag[4*i+0],vifDMAtag[4*i+1],vifDMAtag[4*i+2],vifDMAtag[4*i+3]);
	*/
}
//-----------------------------------------------
void vu1UploadHugeDataContFlush(void *data, u32 size, u32 destoffset, u32 wait)
{
	//special case : 1 Gif-tag plus 85 triple qwords sent per batch
	//= 256*16 bytes sent, exactly the amount of data handled by 1 dma-tag ref
	//that means we can insert MSCNT+FLUSH in the same loop and process all batches at once
	//(and we can stop incrementing dst offset : we always target offset 0)
	asm __volatile__("
		.set noreorder
		addiu	%1,%1,0xf
		lui		$8,0x3000
		srl		%1,%1,4
		or		$11,%4,$8
		lui		$10,0x6c00		#// VIF-UNPACK-code (V4-32)
		lui		$8,0x1000
		or		$10,$10,%2
		ori		$8,$8,0x9000	#// VIF1-DMA-channel
		ori		$13,$0,256
		dsll32	$10,$10,0
		dsll32	$13,$13,0

vu1uphdcfwait0:
		lw		$9,0x00($8)
		nop
		nop
		nop
		andi	$9,$9,0x100
		nop
		bgtz	$9,vu1uphdcfwait0
		nop

		.align 3
vu1uphdcfloop:
		addi	$12,%1,-256
		lui		$9,0x3000		#// DMA-Tag, Tag-ID:'ref'
		blez	$12,vu1uphdcflast
		ori		$9,$9,256
		dsll32	$12,%0,0
		addi	%0,%0,4096		#// src +4096 bytes
		or		$9,$9,$12
		addi	%1,%1,-256
		pcpyld	$12,$10,$9
		sq		$12,0x0($11)	#// save DMATAG(ref)+VIFcode uncached-accelerated
		addi	$11,$11,16

		lui	$14,0x1700	#//Vif-Tag MSCNT
		dsll32	$14,$14,0
		lui		$9,0x1000		#// DMA-Tag, Tag-ID:'cnt'
		pcpyld	$12,$14,$9	#//$14:$9=0x17000000<<(32+64)+n<<(48+64)+dst<<64+src<<32+(Tag-ID)<<28+index
		sq		$12,0x0($11)	#// save DMATAG(end)+VIFcode(MSCNT) uncached-accelerated
		addi	$11,$11,16

		lui	$14,0x1100	#//Vif-Tag FLUSH
		dsll32	$14,$14,0
		lui		$9,0x1000		#// DMA-Tag, Tag-ID:'cnt'
		pcpyld	$12,$14,$9	#//$14:$9=0x11000000<<(32+64)+n<<(48+64)+dst<<64+src<<32+(Tag-ID)<<28+index
		sq		$12,0x0($11)	#// save DMATAG(end)+VIFcode(MSCNT) uncached-accelerated
		beq		$0,$0,vu1uphdcfloop
		addi	$11,$11,16

vu1uphdcflast:
		andi	$13,%1,255
		dsll32	$12,%0,0	#//$12=src<<32
		dsll32	$13,$13,16	#//$13=n<<48
		lui		$9,0x3000		#// DMA-Tag, Tag-ID:'ref' (instead of 'refe') (p59 EE user manual)
		or		$9,$9,%1	#//$10:$9=0x6c000000<<(32+64)+n<<(48+64)+dst<<64+src<<32+Tag-ID<<28+index
		or		$9,$9,$12
		or		$10,$10,$13
		pcpyld	$12,$10,$9
		sq		$12,0x0($11)	#// save DMATAG(refe)+VIFcode uncached-accelerated
		addi	$11,$11,16

		lui	$10,0x1700	#//Vif-Tag MSCNT
		dsll32	$10,$10,0
		lui		$9,0x1000		#// DMA-Tag, Tag-ID:'cnt'
		pcpyld	$12,$10,$9	#//$10:$9=0x17000000<<(32+64)+n<<(48+64)+dst<<64+src<<32+(Tag-ID)<<28+index
		sq		$12,0x0($11)	#// save DMATAG(end)+VIFcode(MSCNT) uncached-accelerated
		addi	$11,$11,16

		lui	$10,0x1100	#//Vif-Tag FLUSH
		dsll32	$10,$10,0
		lui		$9,0x7000		#// DMA-Tag, Tag-ID:'end'
		pcpyld	$12,$10,$9	#//$10:$9=0x11000000<<(32+64)+n<<(48+64)+dst<<64+src<<32+(Tag-ID)<<28+index
		sq		$12,0x0($11)	#// save DMATAG(end)+VIFcode(MSCNT) uncached-accelerated

		beq		%3,$0,vu1uphdcfend

vu1uphdcfwait1:
		lw		$9,0x00($8)
		nop
		nop
		nop
		nop
		nop
		andi	$9,$9,0x100
		nop
		bgtz	$9,vu1uphdcfwait1
		nop
vu1uphdcfend:

		sw		%4,0x30($8)		#// tadr = vifDMAtag
		ori		$9,$0,0x145
		sw		$0,0x20($8)		#// qwc = 0
		sync					#// sync: flush uncached accelerated buffer
		sw		$9,0x00($8)		#// chcr = 0x145, -> start

		.set reorder
		"
		:
		: "r"(data), "r"(size), "r"(destoffset), "r"(wait), "r"(vifDMAtag)
		: "$8", "$9", "$10", "$11", "$12", "$13", "$14", "memory"
	);
	/*FlushCache(0);
	for (i = 0; i < 4; i++)
		printf("dmatag:%x %x %x %x\n", vifDMAtag[4*i+0],vifDMAtag[4*i+1],vifDMAtag[4*i+2],vifDMAtag[4*i+3]);
	*/
}
//-----------------------------------------------
void vu1WaitEndOfVu1()
{
	asm __volatile__("
		.set noreorder
		lui		$8,0x1000
		ori		$8,$8,0x9000	#// VIF1-DMA-channel
vu1waite0:
		lw		$9,0x00($8)
		nop
		nop
		nop
		nop
		nop
		andi	$9,$9,0x100
		nop
		bgtz	$9,vu1waite0
		nop
		.set reorder
		"
		:
		:
		: "$8", "$9", "memory"
	);
}
