#include "mpi_consts.h"
	
.globl global_sum_tree	
.globl global_sum_torus
.globl global_sum_var
.extern MPI_Allreduce

#define FIFO4_MASK	2047
#define FIFO4_SIZE	2048

	
#    global_sum_tree:
#    	mflr	0
#    	stw	0, 8(1)
#            stwu    1, -128(1)
#    
#    	stw	14, 88(1)
#    	stw	15, 92(1)
#    
#    	lfd	1, 0(3)
#            stfd	1, 64(1)
#    	lwz	3, 64(1)
#    	rlwinm	15, 3, 12, 21, 31	# biased exponent in 15
#    	
#    #determine max. exponent
#    	stw	15, 96(1)
#    	addi	3, 1, 96		# sendbuf
#    	addi	4, 1, 100		# recvbuf
#    	li	5, 1			# count
#    	li	6, ASM_MPI_INTEGER & 0xffff
#    	addis	6, 6, ASM_MPI_INTEGER / 0x10000
#    	li	7, ASM_MPI_MAX & 0xffff
#    	addis	7, 7, ASM_MPI_MAX / 0x10000
#    	li	8, ASM_MPI_COMM_WORLD & 0xffff
#    	addis	8, 8, ASM_MPI_COMM_WORLD / 0x10000
#    	bl	MPI_Allreduce
#    	
#    
#    	lwz	14, 100(1)		#r14 =  max. exponent
#    
#    
#    	
#    	subfc	4, 15, 14		# r4 = max expo. - expo.
#    
#    	
#    
#    	lwz	5, 64(1)
#    	lwz	6, 68(1)
#    
#    	andis.	7, 5, 0x8000		# sign bit
#    
#    
#    	cmpi	1, 15, 0
#    	beq-	1, gs_den
#    	oris	5, 5, 0x10		# add "implicit" 1 unless denormalized
#    	b	gs_den_fin
#    	
#    	
#    gs_den:		
#    # shift left 1 bit
#    	rlwinm	5, 5, 1, 0, 30
#    	rlwinm	7, 6, 1, 31, 31
#    	or	5, 5, 7
#    	rlwinm	6, 6, 1, 0, 30
#    	
#    gs_den_fin:		
#    	
#    # shift left mantissa by 11 bits
#    			
#    	rlwinm	5, 5, 11, 0, 20
#    	rlwinm	12, 6, 11, 21, 31
#    	or	5, 5, 12
#    	rlwinm	6, 6, 11, 0, 20
#    	
#    # shift right mantissa by (max_exponent-exponent) bits
#    	cmpi	1, 4, 63
#    	bgt-	1, gs_zero
#    		
#    	subfic	12, 4, 32
#    	srw	6, 6, 4
#    	slw	11, 5, 12
#    	or	6, 6, 11
#    	addi	12, 4, -32
#    	srw	11, 5, 12
#    	or	6, 6, 11
#    	srw	5, 5, 4			# now 5,6 contains shifted mantissa
#    	b	gs_cont_zero
#    
#    gs_zero:
#    	li	5, 0
#    	li	6, 0
#    gs_cont_zero:		
#    	li	7, 0
#    	beq+	gs_positive		# sign?
#    					# negative -> change sign
#    	nand	6, 6, 6
#    	nand	5, 5, 5
#    	nand	7, 7, 7
#    	addic	6, 6, 1
#    	addze	5, 5			#+carry
#    	addze	7, 7			#+carry
#    	
#    gs_positive:
#    
#    
#    #add mantissa	
#    
#    	li	3, 0
#    	stw	7, 96(1)
#    	stw	5, 100(1)
#    	stw	3, 104(1)
#    	stw	6, 108(1)
#    
#    	
#    	addi    3, 1, 96                # sendbuf
#    	addi    4, 1, 112               # recvbuf
#    	li      5, 2                    # count
#    	li      6, ASM_MPI_INTEGER8 & 0xffff
#    	addis   6, 6, ASM_MPI_INTEGER8 / 0x10000
#    	li      7, ASM_MPI_SUM & 0xffff
#    	addis   7, 7, ASM_MPI_SUM / 0x10000
#    	li      8, ASM_MPI_COMM_WORLD & 0xffff
#    	addis   8, 8, ASM_MPI_COMM_WORLD / 0x10000
#    	bl      MPI_Allreduce
#    	
#    
#    	
#    	lwz	7, 124(1)
#    	lwz	6, 120(1)
#    	lwz	3, 116(1)
#    	lwz	5, 112(1)
#    	addc	6, 6, 3
#    	addze	5, 5		# now 5,6,7 contain 96-bit mantissa
#    
#    
#    	andis.	8, 5, 0x8000	# test sign bit (cr0:2=sign bit)
#    	beq+	gs_sum_pos
#    
#    	nand	7, 7, 7
#    	nand	6, 6, 6
#    	nand	5, 5, 5
#    	addic	7, 7, 1
#    	addze	6, 6			#+carry
#    	addze	5, 5			#+carry
#    	
#    
#    
#    gs_sum_pos:
#    	cmpi	1, 5, 0
#    	bne+	1, gs_r96c
#    	mr	5, 6
#    	mr	6, 7
#    	li	7, 0
#    	addi	14, 14, -32
#    gs_r96:	
#    	cmpi	1, 5, 0
#    	bne+	1, gs_r96c
#    	mr	5, 6
#    	mr	6, 7
#    	li	7, 0
#    	addi	14, 14, -32
#    gs_r96b:	
#    	cmpi	1, 5, 0
#    	beq-	1, gs_res_zero
#    gs_r96c:	
#    
#    	cntlzw	3, 5
#    	subfc	14, 3, 14
#    	addi	14, 14, 32		# 14 = result exponent
#    
#    	subfic	12, 3, 32
#    	slw	5, 5, 3
#    	srw	11, 6, 12
#    	or	5, 5, 11
#    	slw	6, 6, 3
#    	srw	11, 7, 12
#    	or	6, 6, 11
#    	slw	7, 7, 3			# now 5:6:7 contains mantissa, left-aligned
#    
#    
#    	cmpi	1, 14, 0		# denormalized?
#    	bgt+	1, gs_not_den
#    
#    	#denormalized result		
#    	cmpi	1, 14, -62
#    	blt-	1, gs_zero
#    	cmpi	1, 14, -31
#    	bgt+	1, gs_den1
#    	addi	14, 14, 32
#    	mr	6, 5
#    	li	5, 0
#    gs_den1:		
#    	subfic	10, 14, 1
#    
#    	subfic	12, 10, 32
#    	srw	6, 6, 10
#    	slw	11, 5, 12
#    	or	6, 6, 11
#    	addi	12, 10, -32
#    	srw	11, 5, 12
#    	or	6, 6, 11
#    	srw	5, 5, 10			# now 5,6 contains shifted mantissa
#    	li	14, 0
#    	b	gs_comb
#    	
#    gs_not_den:
#    	cmpi	1, 14, 2046		# infinity/nan?
#    	bgt-	1, gs_inf
#    
#    	
#    	addis	5, 5, 0x8000		# remove implicit 1
#    
#    	
#    gs_comb:		
#    				
#    	#shift 5:6 right by 11 bits
#    
#    	rlwinm	6, 6, 21, 11, 31
#    	rlwinm	7, 5, 21, 0, 10
#    	or	6, 6, 7
#    	rlwinm	5, 5, 21, 11, 31
#    	
#    
#    
#    	
#    	rlwinm	14, 14, 20, 1, 11
#    	or	5, 5, 14
#    	beq+	gs_res_pos		# insert sign bit
#    	addis	5, 5, 0x8000
#    gs_res_pos:		
#    	b	gs_finished
#    gs_res_zero:	
#    	li	5, 0
#    	li	6, 0
#    	b	gs_finished
#    	
#    gs_inf:					# return qNaN
#    	li	5, -32767
#    	addis	5, 5, 0xffff
#    	li	6, -32767
#    	addis	6, 6, 0xffff
#    
#    gs_finished:		
#    
#    	
#    	stw	5, 64(1)
#    	stw	6, 68(1)
#    	lfd	1, 64(1)
#    
#    	lwz	14, 88(1)
#    	lwz	15, 92(1)
#    
#    	
#            addi    1, 1, 128
#            lwz     0, 8(1)
#            mtlr    0
#            bclr    20, 0
#    

#define WD_OFFS_POS    764
#define WD_OFFS_SIZE   768

	
global_sum_torus:

#	li	3, 0
#	li	4, 0x3ff0
#	stw	4, -8(1)
#	stw	3, -4(1)
#	lfd	1, -8(1)
#	blr
#	
#	
	
	mflr	0
	stw	0, 4(1)
        stwu    1, -32(1)
	stw	13, 16(1)

	lfd	1, 0(3)
		
	addis	3, 0, wilson_data@ha
	addi	3, 3, wilson_data@l


	lbz	4, WD_OFFS_POS+3(3)	 
	lbz	5, WD_OFFS_SIZE+3(3)

	
	
	cmpi	0, 5, 1
	beq-	gst_no4d

	addis	13, 0, send_fifo4_addr@ha
	addi	13, 13, send_fifo4_addr@l
	lwz	13, 0(13)	
	addis	12, 0, recv_fifo4_addr@ha
	addi	12, 12, recv_fifo4_addr@l
	lwz	12, 0(12)
	lwz	11, 128(13)		# own gs-counter
	cmpi	0, 4, 0
	beq	gst_master
	stfd	1, 256(13)
	addi	11, 11, 1
	mbar
	stw	11, 128(13)

gst_c4s_loop:	
	lwz	10, 128(12)		# nb gs-counter
	cmp	0, 10, 11
	bne	gst_c4s_loop
	lfd	1, 256(12)

	b	gst_done4


gst_master:
	addi	11, 11, 1
gst_c4_loop:	
	lwz	10, 128(12)		# nb gs-counter
	cmp	0, 10, 11
	bne	gst_c4_loop
	lfd	2, 256(12)
	fadd	1, 1, 2
	
	
	
gst_no4d:			
	
	
	lbz	4, WD_OFFS_POS(3)	 
	lbz	5, WD_OFFS_SIZE(3)

	addis	12,  0, recv_stat_addr@ha
	addi	12, 12, recv_stat_addr@l
	lwz	12, 0(12)
	addis	13,  0, send_stat_addr@ha
	addi	13, 13, send_stat_addr@l
	lwz	13, 0(13)
	addis	10,  0, recv_fifo_addr@ha
	addi	10, 10, recv_fifo_addr@l
	addis	11,  0, send_fifo_addr@ha
	addi	11, 11, send_fifo_addr@l
	addis	9, 0, send_header@ha
	addi	9, 9, send_header@l

	

	
	rlwinm	6, 5, 31, 1, 31
	cmp	0, 4, 6
	blt	gst_x1		# x<Lx/2? 
	bgt+	gst_x2		# x>LX/2?
				# x=Lx/2

	fmr	0, 1
	cmpi	0, 5, 1
	beq-	gst_nx1
	cmpi	0, 5, 2
	beq-	gst_nx2	
	li	0, 0
	bl	gst_recv_data
	fadd	1, 1, 0
gst_nx2:		
	li	0, 1
	bl	gst_recv_data
	fadd	1, 1, 0

# send data in y-direction
	lbz	4, WD_OFFS_POS+1(3)	 
	lbz	5, WD_OFFS_SIZE+1(3)

	rlwinm	6, 5, 31, 1, 31
	cmp	0, 4, 6
	blt	gst_y1		# y<Ly/2? 
	bgt+	gst_y2		# y>Ly/2?
				# y=Ly/2



	
	cmpi	0, 5, 1
	beq-	gst_ny1
	cmpi	0, 5, 2
	beq-	gst_ny2	
	li	0, 2
	bl	gst_recv_data
	fadd	1, 1, 0
gst_ny2:		
	li	0, 3
	bl	gst_recv_data
	fadd	1, 1, 0





# send data in z-direction
	lbz	4, WD_OFFS_POS+2(3)	 
	lbz	5, WD_OFFS_SIZE+2(3)

	rlwinm	6, 5, 31, 1, 31
	cmp	0, 4, 6
	blt	gst_z1		# z<Lz/2? 
	bgt+	gst_z2		# z>Lz/2?
				# z=Lz/2



	
	cmpi	0, 5, 1
	beq-	gst_nz1
	cmpi	0, 5, 2
	beq-	gst_nz2	
	li	0, 4
	bl	gst_recv_data
	fadd	1, 1, 0
gst_nz2:		
	li	0, 5
	bl	gst_recv_data
	fadd	0, 1, 0




	
gst_nz1:		
	lbz	5, WD_OFFS_SIZE+2(3)
	cmpi	0, 5, 1
	beq-	gst_nz2b
		
	li	0, 5
	bl	gst_send_data

	lbz	5, WD_OFFS_SIZE+2(3)
	cmpi	0, 5, 2
	beq-	gst_nz2b

	li	0, 4
	bl	gst_send_data

gst_nz2b:		

	fmr	1, 0
	b	send_y



gst_z1:	cmpi	0, 4, 0
	beq-	gst_z1a
	li	0, 5
	bl	gst_recv_data
	fadd	1, 0, 1
gst_z1a:	
	fmr	0, 1	
	li	0, 4
	bl	gst_send_data
	li	0, 4
	bl	gst_recv_data
	lbz	4, WD_OFFS_POS+2(3)
	cmpi	0, 4, 0
	beq-	gst_z1b
	li	0, 5
	bl	gst_send_data
gst_z1b:	
	fmr	1, 0
	b	send_y
	
	
	
gst_z2:	addi	4, 4, 1
	cmp	0, 4, 5
	beq-	gst_z2a
	li	0, 4
	bl	gst_recv_data
	fadd	1, 0, 1
gst_z2a:	
	fmr	0, 1
	li	0, 5
	bl	gst_send_data	
	li	0, 5
	bl	gst_recv_data

	
	lbz	4, WD_OFFS_POS+2(3)
	lbz	5, WD_OFFS_SIZE+2(3)
	addi	4, 4, 1
	cmp	0, 4, 5
	beq-	gst_z2b
	li	0, 4
	bl	gst_send_data
gst_z2b:		
	
	fmr	1, 0
	b	send_y

	




	

send_y:		
gst_ny1:		
	lbz	5, WD_OFFS_SIZE+1(3)
	cmpi	0, 5, 1
	beq-	gst_ny2b
		
	li	0, 3
	bl	gst_send_data

	lbz	5, WD_OFFS_SIZE+1(3)
	cmpi	0, 5, 2
	beq-	gst_ny2b

	li	0, 2
	bl	gst_send_data

gst_ny2b:		

	fmr	1, 0
	b	send_x





gst_y1:	cmpi	0, 4, 0
	beq-	gst_y1a
	li	0, 3
	bl	gst_recv_data
	fadd	1, 0, 1
gst_y1a:	
	fmr	0, 1	
	li	0, 2
	bl	gst_send_data
	li	0, 2
	bl	gst_recv_data
	lbz	4, WD_OFFS_POS+1(3)
	cmpi	0, 4, 0
	beq-	gst_y1b
	li	0, 3
	bl	gst_send_data
gst_y1b:	
	fmr	1, 0
	b	send_x
	
	
	
gst_y2:	addi	5, 5, -1
	cmp	0, 4, 5
	beq-	gst_y2a
	li	0, 2
	bl	gst_recv_data
	fadd	1, 0, 1
gst_y2a:	
	fmr	0, 1
	li	0, 3
	bl	gst_send_data	
	li	0, 3
	bl	gst_recv_data

        lbz     4, WD_OFFS_POS+1(3)
	lbz     5, WD_OFFS_SIZE+1(3)
	addi    4, 4, 1
	cmp     0, 4, 5
	beq-    gst_y2b
	li      0, 2
	bl      gst_send_data
gst_y2b:
	
	
	fmr	1, 0
	b	send_x

	


	



	

	
send_x:		
gst_nx1:		
	lbz	5, WD_OFFS_SIZE(3)
	cmpi	0, 5, 1
	beq-	gst_nx2b
	
	
	
	li	0, 1
	bl	gst_send_data

	lbz	5, WD_OFFS_SIZE(3)
	cmpi	0, 5, 2
	beq-	gst_nx2b

	li	0, 0

	bl	gst_send_data

gst_nx2b:		
	fmr	1, 0
	b	gst_done

	
gst_x1:

	cmpi	0, 4, 0
	beq-	gst_x1a
	li	0, 1
	bl	gst_recv_data
	fadd	1, 0, 1
gst_x1a:	
	fmr	0, 1	
	li	0, 0
	bl	gst_send_data
	li	0, 0
	bl	gst_recv_data

	lbz	4, WD_OFFS_POS(3)
	cmpi	0, 4, 0
	beq-	gst_x1b
	li	0, 1
	bl      gst_send_data
	
	
gst_x1b:	
	fmr	1, 0
	b	gst_done
	
	
	
gst_x2:	addi	5, 5, -1
	cmp	0, 4, 5
	beq-	gst_x2a
	li	0, 0
	bl	gst_recv_data
	fadd	1, 0, 1
gst_x2a:	
	fmr	0, 1
	li	0, 1
	bl	gst_send_data	
	li	0, 1
	bl	gst_recv_data


        lbz     4, WD_OFFS_POS(3)
	lbz     5, WD_OFFS_SIZE(3)
	addi    4, 4, 1
	cmp     0, 4, 5
	beq-    gst_x2b
	li      0, 0
	bl      gst_send_data
gst_x2b:
	
	
	fmr	1, 0
	b	gst_done
	

gst_done:				# only master gets here
					# copy data to slave if necessary

	lbz	5, WD_OFFS_SIZE+3(3)
	cmpi	0, 5, 2
	bne-	gst_done4
	addis	13, 0, send_fifo4_addr@ha
	addi	13, 13, send_fifo4_addr@l
	lwz	13, 0(13)	
	stfd	1, 256(13)
	lwz	11, 128(13)		# own gs-counter
	addi	11, 11, 1
	mbar
	stw	11, 128(13)
	

			
gst_done4:		
	lwz	13, 16(1)	
	addi	1, 1, 32
        lwz     0, 4(1)
        mtlr    0
	bclr	20, 0


	

gst_send_data:			# send data (f0) in direction given in r0
				# (0=x+, 1=x-, ...)
				# destroys r4, r5, r6, r7, r8, f3	

	
	rlwinm	4, 0, 31, 1, 31	# r4=r0/2
	andi.	5, 0, 1
	beq	gst_sd_l1
	li	5, 3		 
gst_sd_l1:	
	add	5, 5, 4
	add	5, 5, 5
	add	5, 5, 5		# r5:	 0=x+, 4=y+, 8=z+, 12=x-...
	addi	4, 4, 7
gst_sd_loop:	
	lfpdx	3, 0, 13
	stfpdx	3, 0, 1
	lbzx	6, 4, 1
	cmpi	0, 6, 28
	bgt-	gst_sd_loop
	lwzx	8, 5, 11	# send addr

	add	5, 5, 5
	add	5, 5, 5		# r5:	    0=x+, 16=y+, 32=z+, 48=x-...
	lfpdx	3, 5, 9		# header
	stfpdx	3, 0, 1
	lbz	7, 2(1)		# set size to 0 (=32 bytes)
	andi.	7, 7, 0x1f
	stb	7, 2(1)
	lfpdx	3, 0, 1
	stfpdx	3, 0, 8		# header
	stfpdx	0, 0, 8		# data
	blr

gst_recv_data:			# recv data (->f0) from direction given in r0
				# (0=x+, 1=x-, ...)
				# destroys r4, r5, r6, r7, r8	, f3


	
	rlwinm	4, 0, 31, 1, 31	# r4=r0/2
	andi.	5, 0, 1
	beq	gst_rd_l1
	li	5, 3		 
gst_rd_l1:	
	add	5, 5, 4
	add	5, 5, 5
	add	5, 5, 5		# r5:	 0=x+, 4=y+, 8=z+, 12=x-...
gst_rd_loop:		
	lfpdx	3, 0, 12	# load status
	stfpdx	3, 0, 1
	lbzx	6, 1, 0		# check for data
	cmpi	0, 6, 1

	blt	gst_rd_loop
	lwzx	8, 5, 10
	lfpdx	3, 0, 8		# header
	lfpdx	0, 0, 8		# data
	blr
	
	







#void global_sum_var(double* inp, double* outp, int n*, int op*)
# op:	 0 sum  
#	 1 max
#	 2 min
#	 3 sum (8-bit int)
#	 4 max (8-bit int)
#	 5 min (8-bit int)

	
global_sum_var:	

	
	
	mflr	0
	stw	0, 4(1)
        stwu    1, -192(1)
	stw	13, 32(1)
	stw	14, 36(1)

	lwz	5, 0(5)
	stw	3, 44(1)
	stw	4, 48(1)
	stw	6, 52(1)
	stw	5, 40(1)


	cmpi	0, 5, 0
	bne+	gsv_nnz

gsv_nnz:		
	cmpi	0, 5, 12
	ble+	gsv_nlt12
	li	12, 12
	addi	5, 5, -12
	addi	3, 3, 96
	addi	4, 4, 96
	stw	12, 40(1)
	stw	5, 56(1)
	addi	5, 1, 56
	
	bl	global_sum_var		
#-------------------
	

	
	
gsv_nlt12:		
	lwz	5, 40(1)
	lwz	3, 44(1)
	lwz	4, 48(1)
	lwz	6, 52(1)	
 	mtctr	5
	subfic	5, 5, 12
 	addi	3, 3, -8
 	li	14, 8
 	addi	13, 1, 56
 
 	
gsv_ld_loop:		
 	lfdux	0, 3, 14
 	stfdux	0, 13, 14
 	bdnz	gsv_ld_loop
	cmpi	0, 5, 0
	beq-	gsv_ld_loop2_done
	mtctr	5
	fsub	0, 0, 0
gsv_ld_loop2:		
 	stfdux	0, 13, 14
 	bdnz	gsv_ld_loop2
gsv_ld_loop2_done:		

	addi	3, 1, 48
	li	13, 16
		
	lfpdux	6, 3, 13 
	lfpdux	7, 3, 13 
	lfpdux	8, 3, 13 
	lfpdux	9, 3, 13 
	lfpdux	10, 3, 13 
	lfpdux	11, 3, 13 
 	

	lwz	6, 0(6)
	cmpi	0, 6, 0
	bne	gsv_no_add
	addis	13, 0, gsv_add@ha
	addi	13, 13, gsv_add@l
	b	gsv_got_op
gsv_no_add:	
	cmpi	0, 6, 1
	bne	gsv_no_max
	addis	13, 0, gsv_max@ha
	addi	13, 13, gsv_max@l
	b	gsv_got_op
gsv_no_max:	
	cmpi	0, 6, 2
	bne	gsv_no_min
	addis	13, 0, gsv_min@ha
	addi	13, 13, gsv_min@l
	b	gsv_got_op
gsv_no_min:	
	cmpi	0, 6, 3
	bne	gsv_no_sum_i8
	addis	13, 0, gsv_sum_i8@ha
	addi	13, 13, gsv_sum_i8@l
	b	gsv_got_op
gsv_no_sum_i8:	
	cmpi	0, 6, 4
	bne	gsv_no_max_i8
	addis	13, 0, gsv_max_i8@ha
	addi	13, 13, gsv_max_i8@l
	b	gsv_got_op
gsv_no_max_i8:	
	cmpi	0, 6, 5
	bne	gsv_no_min_i8
	addis	13, 0, gsv_min_i8@ha
	addi	13, 13, gsv_min_i8@l
	b	gsv_got_op
gsv_no_min_i8:	
	addi	13, 0, 0		# crash!!
gsv_got_op:	

	mtctr	13
	
#	addi	3, 3, -16
#	li	13, 16
#
#	lfpdux	6, 3, 13 
#	lfpdux	7, 3, 13 
#	lfpdux	8, 3, 13 
#	lfpdux	9, 3, 13 
#	lfpdux	10, 3, 13 
#	lfpdux	11, 3, 13 
#	

	mr	14, 4
	addis	3, 0, wilson_data@ha
	addi	3, 3, wilson_data@l


	lbz	4, WD_OFFS_POS+3(3)	 
	lbz	5, WD_OFFS_SIZE+3(3)

	
	
	cmpi	0, 5, 1
	beq-	gsv_no4d

	addis	13, 0, send_fifo4_addr@ha
	addi	13, 13, send_fifo4_addr@l
	lwz	13, 0(13)	
	addis	12, 0, recv_fifo4_addr@ha
	addi	12, 12, recv_fifo4_addr@l
	lwz	12, 0(12)

	
	cmpi	0, 4, 0
	li	11, 16
	beq	gsv_master
gsv_d4_rloop:		
	lwz	6,  0(13)	# rd offs
	lwz	7,  4(13)	# wr offs
	subf	6, 6, 7
	cmpi	0, 6, FIFO4_SIZE-128
	bge-	gsv_d4_rloop	


	addi	6, 7, 128

	andi.	7, 7, FIFO4_MASK
	add	7, 7, 13
	
		
	
	stfpdux	6, 7, 11
	stfpdux	7, 7, 11
	stfpdux	8, 7, 11
	stfpdux	9, 7, 11
	stfpdux	10, 7, 11
	stfpdux	11, 7, 11

	mbar
	stw	6, 4(13)

gsv_c4s_loop:


	lwz	6,  0(12)	# rd offs
	lwz	7,  4(12)	# wr offs
	cmp	0, 6, 7


	
#addi	31, 0, 0
#mtctr	31
#bctrl	
		
	beq-	gsv_c4s_loop

	addi	7, 6, 128
	andi.	6, 6, FIFO4_MASK
	add	6, 6, 12

	

	lfpdux	6, 6, 11 
	lfpdux	7, 6, 11 
	lfpdux	8, 6, 11 
	lfpdux	9, 6, 11 
	lfpdux	10, 6, 11 
	lfpdux	11, 6, 11 

	mbar
	stw	7, 0(12)
	
	b	gsv_done4


gsv_master:


gsv_c4_loop:	

	lwz	6,  0(12)	# rd offs
	lwz	7,  4(12)	# wr offs
	cmp	0, 6, 7

	
	beq-	gsv_c4_loop

	addi	7, 6, 128
	andi.	6, 6, FIFO4_MASK
	add	6, 6, 12


	lfpdux	0, 6, 11 
	lfpdux	1, 6, 11 
	lfpdux	2, 6, 11 
	lfpdux	3, 6, 11 
	lfpdux	4, 6, 11 
	lfpdux	5, 6, 11 

	mbar
	stw	7, 0(12)
	
	bctrl	
	
gsv_no4d:			
	
	
	lbz	4, WD_OFFS_POS(3)	 
	lbz	5, WD_OFFS_SIZE(3)

	addis	12,  0, recv_stat_addr@ha
	addi	12, 12, recv_stat_addr@l
	lwz	12, 0(12)
	addis	13,  0, send_stat_addr@ha
	addi	13, 13, send_stat_addr@l
	lwz	13, 0(13)
	addis	10,  0, recv_fifo_addr@ha
	addi	10, 10, recv_fifo_addr@l
	addis	11,  0, send_fifo_addr@ha
	addi	11, 11, send_fifo_addr@l
	addis	9, 0, send_header@ha
	addi	9, 9, send_header@l

	

	
	rlwinm	6, 5, 31, 1, 31
	cmp	0, 4, 6
	blt	gsv_x1		# x<Lx/2? 
	bgt+	gsv_x2		# x>LX/2?
				# x=Lx/2
	fpmr	0, 6
	fpmr	1, 7 
	fpmr	2, 8 
	fpmr	3, 9 
	fpmr	4, 10
	fpmr	5, 11

	cmpi	0, 5, 1
	beq-	gsv_nx1
	cmpi	0, 5, 2
	beq-	gsv_nx2	
	li	0, 0
	bl	gsv_recv_data

	bctrl
gsv_nx2:		
	li	0, 1
	bl	gsv_recv_data

	bctrl
	
# send data in y-direction
	lbz	4, WD_OFFS_POS+1(3)	 
	lbz	5, WD_OFFS_SIZE+1(3)

	rlwinm	6, 5, 31, 1, 31
	cmp	0, 4, 6
	blt	gsv_y1		# y<Ly/2? 
	bgt+	gsv_y2		# y>Ly/2?
				# y=Ly/2



	
	cmpi	0, 5, 1
	beq-	gsv_ny1
	cmpi	0, 5, 2
	beq-	gsv_ny2	
	li	0, 2
	bl	gsv_recv_data

	
	bctrl
gsv_ny2:		
	li	0, 3
	bl	gsv_recv_data

	
	bctrl





# send data in z-direction
	lbz	4, WD_OFFS_POS+2(3)	 
	lbz	5, WD_OFFS_SIZE+2(3)

	rlwinm	6, 5, 31, 1, 31
	cmp	0, 4, 6
	blt	gsv_z1		# z<Lz/2? 
	bgt+	gsv_z2		# z>Lz/2?
				# z=Lz/2



	
	cmpi	0, 5, 1
	beq-	gsv_nz1
	cmpi	0, 5, 2
	beq-	gsv_nz2	
	li	0, 4
	bl	gsv_recv_data
	bctrl
gsv_nz2:		
	li	0, 5
	bl	gsv_recv_data

	bctrl	

	fpmr	0, 6
	fpmr	1, 7
	fpmr	2, 8
	fpmr	3, 9
	fpmr	4, 10
	fpmr	5, 11

	
	
gsv_nz1:		
	lbz	5, WD_OFFS_SIZE+2(3)
	cmpi	0, 5, 1
	beq-	gsv_nz2b
		
	li	0, 5
	bl	gsv_send_data

	lbz	5, WD_OFFS_SIZE+2(3)
	cmpi	0, 5, 2
	beq-	gsv_nz2b

	li	0, 4
	bl	gsv_send_data

gsv_nz2b:		

	fpmr	6, 0
	fpmr	7, 1
	fpmr	8, 2
	fpmr	9, 3
	fpmr	10, 4
	fpmr	11, 5
	b	gsv_send_y



gsv_z1:	cmpi	0, 4, 0
	beq-	gsv_z1a
	li	0, 5
	bl	gsv_recv_data
	bctrl
gsv_z1a:	
	fpmr	0, 6 
	fpmr	1, 7 
	fpmr	2, 8 
	fpmr	3, 9 
	fpmr	4, 10
	fpmr	5, 11
	li	0, 4
	bl	gsv_send_data
	li	0, 4
	bl	gsv_recv_data
	lbz	4, WD_OFFS_POS+2(3)
	cmpi	0, 4, 0
	beq-	gsv_z1b
	li	0, 5
	bl	gsv_send_data
gsv_z1b:	
	fpmr	6, 0
	fpmr	7, 1
	fpmr	8, 2
	fpmr	9, 3
	fpmr	10, 4
	fpmr	11, 5
	b	gsv_send_y
	
	
	
gsv_z2:	addi	4, 4, 1
	cmp	0, 4, 5
	beq-	gsv_z2a
	li	0, 4
	bl	gsv_recv_data
	bctrl
gsv_z2a:	
	fpmr	0, 6 
	fpmr	1, 7 
	fpmr	2, 8 
	fpmr	3, 9 
	fpmr	4, 10
	fpmr	5, 11
	li	0, 5
	bl	gsv_send_data	
	li	0, 5
	bl	gsv_recv_data

	
	lbz	4, WD_OFFS_POS+2(3)
	lbz	5, WD_OFFS_SIZE+2(3)
	addi	4, 4, 1
	cmp	0, 4, 5
	beq-	gsv_z2b
	li	0, 4
	bl	gsv_send_data
gsv_z2b:		
	
	fpmr	6, 0
	fpmr	7, 1
	fpmr	8, 2
	fpmr	9, 3
	fpmr	10, 4
	fpmr	11, 5
	b	gsv_send_y

	




	

gsv_send_y:		
gsv_ny1:		
	lbz	5, WD_OFFS_SIZE+1(3)
	cmpi	0, 5, 1
	beq-	gsv_ny2b
		
	li	0, 3
	bl	gsv_send_data

	lbz	5, WD_OFFS_SIZE+1(3)
	cmpi	0, 5, 2
	beq-	gsv_ny2b

	li	0, 2
	bl	gsv_send_data

gsv_ny2b:		

	fpmr	6, 0
	fpmr	7, 1
	fpmr	8, 2
	fpmr	9, 3
	fpmr	10, 4
	fpmr	11, 5
	b	gsv_send_x





gsv_y1:	cmpi	0, 4, 0
	beq-	gsv_y1a
	li	0, 3
	bl	gsv_recv_data
	bctrl
gsv_y1a:	
	fpmr	0, 6 
	fpmr	1, 7 
	fpmr	2, 8 
	fpmr	3, 9 
	fpmr	4, 10
	fpmr	5, 11
	li	0, 2
	bl	gsv_send_data
	li	0, 2
	bl	gsv_recv_data
	lbz	4, WD_OFFS_POS+1(3)
	cmpi	0, 4, 0
	beq-	gsv_y1b
	li	0, 3
	bl	gsv_send_data
gsv_y1b:	
	fpmr	6, 0
	fpmr	7, 1
	fpmr	8, 2
	fpmr	9, 3
	fpmr	10, 4
	fpmr	11, 5
	b	gsv_send_x
	
	
	
gsv_y2:	addi	5, 5, -1
	cmp	0, 4, 5
	beq-	gsv_y2a
	li	0, 2
	bl	gsv_recv_data
	bctrl
gsv_y2a:	
	fpmr	0, 6 
	fpmr	1, 7 
	fpmr	2, 8 
	fpmr	3, 9 
	fpmr	4, 10
	fpmr	5, 11
	li	0, 3
	bl	gsv_send_data	
	li	0, 3
	bl	gsv_recv_data

        lbz     4, WD_OFFS_POS+1(3)
	lbz     5, WD_OFFS_SIZE+1(3)
	addi    4, 4, 1
	cmp     0, 4, 5
	beq-    gsv_y2b
	li      0, 2
	bl      gsv_send_data
gsv_y2b:
	
	
	fpmr	6, 0
	fpmr	7, 1
	fpmr	8, 2
	fpmr	9, 3
	fpmr	10, 4
	fpmr	11, 5
	b	gsv_send_x

	


	



	

	
gsv_send_x:		
gsv_nx1:		
	lbz	5, WD_OFFS_SIZE(3)
	cmpi	0, 5, 1
	beq-	gsv_nx2b
	
	
	
	li	0, 1
	bl	gsv_send_data

	lbz	5, WD_OFFS_SIZE(3)
	cmpi	0, 5, 2
	beq-	gsv_nx2b

	li	0, 0

	bl	gsv_send_data

gsv_nx2b:		
	fpmr	6, 0
	fpmr	7, 1
	fpmr	8, 2
	fpmr	9, 3
	fpmr	10, 4
	fpmr	11, 5
	b	gsv_done

	
gsv_x1:

	cmpi	0, 4, 0
	beq-	gsv_x1a
	li	0, 1
	bl	gsv_recv_data
	bctrl	
gsv_x1a:	
	fpmr	0, 6 
	fpmr	1, 7 
	fpmr	2, 8 
	fpmr	3, 9 
	fpmr	4, 10
	fpmr	5, 11
	li	0, 0
	bl	gsv_send_data
	li	0, 0
	bl	gsv_recv_data

	lbz	4, WD_OFFS_POS(3)
	cmpi	0, 4, 0
	beq-	gsv_x1b
	li	0, 1
	bl      gsv_send_data
	
	
gsv_x1b:	
	fpmr	6, 0
	fpmr	7, 1
	fpmr	8, 2
	fpmr	9, 3
	fpmr	10, 4
	fpmr	11, 5
	b	gsv_done
	
	
	
gsv_x2:	addi	5, 5, -1
	cmp	0, 4, 5
	beq-	gsv_x2a
	li	0, 0
	bl	gsv_recv_data
	bctrl
gsv_x2a:	
	fpmr	0, 6 
	fpmr	1, 7 
	fpmr	2, 8 
	fpmr	3, 9 
	fpmr	4, 10
	fpmr	5, 11
	li	0, 1
	bl	gsv_send_data	
	li	0, 1
	bl	gsv_recv_data


        lbz     4, WD_OFFS_POS(3)
	lbz     5, WD_OFFS_SIZE(3)
	addi    4, 4, 1
	cmp     0, 4, 5
	beq-    gsv_x2b
	li      0, 0
	bl      gsv_send_data
gsv_x2b:
	
	
	fpmr	6, 0
	fpmr	7, 1
	fpmr	8, 2
	fpmr	9, 3
	fpmr	10, 4
	fpmr	11, 5
	b	gsv_done
	

gsv_done:				# only master gets here
					# copy data to slave if necessary

	lbz	5, WD_OFFS_SIZE+3(3)
	cmpi	0, 5, 2
	bne-	gsv_done4
	addis	13, 0, send_fifo4_addr@ha
	addi	13, 13, send_fifo4_addr@l
	lwz	13, 0(13)	

	
	
	li	11, 16
gsv_d4_mloop2:		
	lwz	6,  0(13)	# rd offs
	lwz	7,  4(13)	# wr offs
	subf	6, 6, 7
	cmpi	0, 6, FIFO4_SIZE-128
	bge-	gsv_d4_mloop2


	addi	6, 7, 128

	andi.	7, 7, FIFO4_MASK
	add	7, 7, 13
	
		
	
	stfpdux	6, 7, 11
	stfpdux	7, 7, 11
	stfpdux	8, 7, 11
	stfpdux	9, 7, 11
	stfpdux	10, 7, 11
	stfpdux	11, 7, 11

	mbar
	stw	6, 4(13)
	
	


			
gsv_done4:		
	addi	14, 14, -8
	li	3, 16


	addi	13, 1, 48
	li	12, 16
	lwz	5, 40(1)
	li	11, 8
	addi	10, 1, 56		
	stfpdux 6, 13, 12
	stfpdux 7, 13, 12
	stfpdux 8, 13, 12
	mtctr	5
	stfpdux 9, 13, 12
	stfpdux 10, 13, 12
	stfpdux 11, 13, 12

gsv_st_loop:	
	lfdux	0, 10, 11
	stfdux	0, 14, 11
	bdnz	gsv_st_loop	
	
	
	
	lwz	13, 32(1)	
	lwz	14, 36(1)	
	addi	1, 1, 192
        lwz     0, 4(1)
        mtlr    0
	bclr	20, 0


	

gsv_send_data:			# send data (f0-f5) in direction given in r0
				# (0=x+, 1=x-, ...)
				# destroys r4, r5, r6, r7, r8, f12	

	
	rlwinm	4, 0, 31, 1, 31	# r4=r0/2
	andi.	5, 0, 1
	beq	gsv_sd_l1
	li	5, 3		 
gsv_sd_l1:	
	add	5, 5, 4
	add	5, 5, 5
	add	5, 5, 5		# r5:	 0=x+, 4=y+, 8=z+, 12=x-...
	addi	4, 4, 7
gsv_sd_loop:	
	lfpdx	12, 0, 13
	stfpdx	12, 0, 1
	lbzx	6, 4, 1
	cmpi	0, 6, 28
	bgt-	gsv_sd_loop
	lwzx	8, 5, 11	# send addr

	add	5, 5, 5
	add	5, 5, 5		# r5:	    0=x+, 16=y+, 32=z+, 48=x-...
	lfpdx	12, 5, 9	# header
	stfpdx	12, 0, 8	# header
	stfpdx	12, 0, 8	#   again
	stfpdx	0, 0, 8		# data
	stfpdx	1, 0, 8		# data
	stfpdx	2, 0, 8		# data
	stfpdx	3, 0, 8		# data
	stfpdx	4, 0, 8		# data
	stfpdx	5, 0, 8		# data
	blr

gsv_recv_data:			# recv data (->f0-f5) from direction given in r0
				# (0=x+, 1=x-, ...)
				# destroys r4, r5, r6, r7, r8


	
	rlwinm	4, 0, 31, 1, 31	# r4=r0/2
	andi.	5, 0, 1
	beq	gsv_rd_l1
	li	5, 3		 
gsv_rd_l1:	
	add	5, 5, 4
	add	5, 5, 5
	add	5, 5, 5		# r5:	 0=x+, 4=y+, 8=z+, 12=x-...
gsv_rd_loop:		
	lfpdx	0, 0, 12	# load status
	stfpdx	0, 0, 1
	lbzx	6, 1, 0		# check for data
	cmpi	0, 6, 1

	blt	gsv_rd_loop
	lwzx	8, 5, 10
	lfpdx	0, 0, 8		# header
	lfpdx	0, 0, 8		#    again
	lfpdx	0, 0, 8		# data
	lfpdx	1, 0, 8		# data
	lfpdx	2, 0, 8		# data
	lfpdx	3, 0, 8		# data
	lfpdx	4, 0, 8		# data
	lfpdx	5, 0, 8		# data
	blr
	
	
gsv_add:	
	fpadd	6, 6, 0
	fpadd	7, 7, 1
	fpadd	8, 8, 2
	fpadd	9, 9, 3
	fpadd	10, 10, 4
	fpadd	11, 11, 5
	blr

gsv_max:
	fpsub	12, 0, 6
	fpsub	13, 1, 7
	fpsel	6, 12, 0, 6
	fpsub	12, 2, 8
	fpsel	7, 13, 1, 7
	fpsub	13, 3, 9
	fpsel	8, 12, 2, 8
	fpsub	12, 4,10
	fpsel	9, 13, 3, 9
	fpsub	13, 5,11
	fpsel	10,12, 4,10
	fpsel	11,13, 5,11
	blr
		
gsv_min:
	fpsub	12, 0, 6
	fpsub	13, 1, 7
	fpsel	6, 12, 6, 0
	fpsub	12, 2, 8
	fpsel	7, 13, 7, 1
	fpsub	13, 3, 9
	fpsel	8, 12, 8, 2
	fpsub	12, 4,10
	fpsel	9, 13, 9, 3
	fpsub	13, 5,11
	fpsel	10,12,10, 4
	fpsel	11,13,11, 5
	blr
		
gsv_sum_i8:	
        stwu    1, -256(1)
	stw	3, 0(1)
	stw	4, 4(1)
	stw	5, 8(1)
	stw	6,12(1)
	stw	7,16(1)
	stw	8,20(1)
	stw	9,24(1)
	addi	3, 1, 16
	li	9, 16
	stfpdux   0, 3, 9
	stfpdux   1, 3, 9
	stfpdux   2, 3, 9
	stfpdux   3, 3, 9
	stfpdux   4, 3, 9
	stfpdux   5, 3, 9
	stfpdux   6, 3, 9
	stfpdux   7, 3, 9
	stfpdux   8, 3, 9
	stfpdux   9, 3, 9
	stfpdux  10, 3, 9
	stfpdux  11, 3, 9
	mfctr	8
	li	4, 12
	mtctr	4
	addi	3, 1, 32
gsv_si8_loop:	
	lwz	4,  0(3)
	lwz	5,  4(3)
	lwz	6, 96(3)
	lwz	7,100(3)
	addc	5, 5, 7
	adde	4, 4, 6
	stw	4, 0(3)
	stw	5, 4(3)
	addi	3, 3, 8
	bdnz	gsv_si8_loop
	mtctr	8
	addi	3, 1, 16
	lfpdux   6, 3, 9
	lfpdux   7, 3, 9
	lfpdux   8, 3, 9
	lfpdux   9, 3, 9
	lfpdux  10, 3, 9
	lfpdux  11, 3, 9

	lwz	3, 0(1)
	lwz	4, 4(1)
	lwz	5, 8(1)
	lwz	6,12(1)
	lwz	7,16(1)
	lwz	8,20(1)
	lwz	9,24(1)
	
	addi	1, 1, 256
	blr


gsv_max_i8:	
        stwu    1, -256(1)
	stw	3, 0(1)
	stw	4, 4(1)
	stw	5, 8(1)
	stw	6,12(1)
	stw	7,16(1)
	stw	8,20(1)
	stw	9,24(1)
	addi	3, 1, 16
	li	9, 16
	stfpdux   0, 3, 9
	stfpdux   1, 3, 9
	stfpdux   2, 3, 9
	stfpdux   3, 3, 9
	stfpdux   4, 3, 9
	stfpdux   5, 3, 9
	stfpdux   6, 3, 9
	stfpdux   7, 3, 9
	stfpdux   8, 3, 9
	stfpdux   9, 3, 9
	stfpdux  10, 3, 9
	stfpdux  11, 3, 9
	mfctr	8
	li	4, 12
	mtctr	4
	addi	3, 1, 32
gsv_mxi8_loop:	
	lwz	4,  0(3)
	lwz	5,  4(3)
	lwz	6, 96(3)
	lwz	7,100(3)
	cmp	0, 4, 6
	bne	gsv_mxi8_l1
	cmpl	0, 5, 7
gsv_mxi8_l1:
	bgt	gsv_mxi8_l2
	mr	4, 6
	mr	5, 7
gsv_mxi8_l2:		
	stw	4, 0(3)
	stw	5, 4(3)
	addi	3, 3, 8
	bdnz	gsv_mxi8_loop
	mtctr	8
	addi	3, 1, 16
	lfpdux   6, 3, 9
	lfpdux   7, 3, 9
	lfpdux   8, 3, 9
	lfpdux   9, 3, 9
	lfpdux  10, 3, 9
	lfpdux  11, 3, 9

	lwz	3, 0(1)
	lwz	4, 4(1)
	lwz	5, 8(1)
	lwz	6,12(1)
	lwz	7,16(1)
	lwz	8,20(1)
	lwz	9,24(1)
	
	addi	1, 1, 256
	blr


gsv_min_i8:	
        stwu    1, -256(1)
	stw	3, 0(1)
	stw	4, 4(1)
	stw	5, 8(1)
	stw	6,12(1)
	stw	7,16(1)
	stw	8,20(1)
	stw	9,24(1)
	addi	3, 1, 16
	li	9, 16
	stfpdux   0, 3, 9
	stfpdux   1, 3, 9
	stfpdux   2, 3, 9
	stfpdux   3, 3, 9
	stfpdux   4, 3, 9
	stfpdux   5, 3, 9
	stfpdux   6, 3, 9
	stfpdux   7, 3, 9
	stfpdux   8, 3, 9
	stfpdux   9, 3, 9
	stfpdux  10, 3, 9
	stfpdux  11, 3, 9
	mfctr	8
	li	4, 12
	mtctr	4
	addi	3, 1, 32
gsv_mni8_loop:	
	lwz	4,  0(3)
	lwz	5,  4(3)
	lwz	6, 96(3)
	lwz	7,100(3)
	cmp	0, 4, 6
	bne	gsv_mni8_l1
	cmpl	0, 5, 7
gsv_mni8_l1:
	bgt	gsv_mni8_l2
	mr	6, 4
	mr	7, 5
gsv_mni8_l2:		
	stw	6, 0(3)
	stw	7, 4(3)
	addi	3, 3, 8
	bdnz	gsv_mni8_loop
	mtctr	8
	addi	3, 1, 16
	lfpdux   6, 3, 9
	lfpdux   7, 3, 9
	lfpdux   8, 3, 9
	lfpdux   9, 3, 9
	lfpdux  10, 3, 9
	lfpdux  11, 3, 9

	lwz	3, 0(1)
	lwz	4, 4(1)
	lwz	5, 8(1)
	lwz	6,12(1)
	lwz	7,16(1)
	lwz	8,20(1)
	lwz	9,24(1)
	
	addi	1, 1, 256
	blr


	
