		#
		# See circuit5.c for the code / idea behind this.
		#
		.text
		.globl life_xform
life_xform:	subu $sp,$sp,56
		sw $s0,4($sp)		# row_prev_l
		sw $s1,8($sp)		# row_prev
		sw $s2,12($sp)		# row_prev_r
		sw $s3,16($sp)		# row_cur_l
		sw $s4,20($sp)		# row_cur
		sw $s5,24($sp)		# row_cur_r
		sw $s6,28($sp)		# row_next_l
		sw $s7,32($sp)		# row_next
		sw $fp,36($sp)		# row_next_r	$fp aka $s8
		sw $a0,40($sp)		# misc		grid
		sw $a1,44($sp)		# r		grid2
		sw $a2,48($sp)		# c
		sw $a3,52($sp)		# status
		sw $ra,56($sp)

		lw $t0,width
		addu $t0,$t0,33
		sra $t0,$t0,5		# $t0 has words_per_row
		sll $t9,$t0,2		# bytes per row

life_xform_circuit:
		li $t1,0		# $t1 has c << 2
		b life_xform_main_c_loop_test
life_xform_main_c_loop:
		addu $t3,$t1,$t9	# bytes( c + words_per_row )
		addu $t2,$t3,$a0	# $t2 has src
		addu $t3,$t3,$a1	# $t3 has dst
		li $s3,0
		li $s4,0
		li $s5,0
		lw $s7,0($t2)		# row_next = *src
		srl $s6,$s7,1
		sll $s8,$s7,1
		lw $t6,4($t2)
		sll $t6,$t6,31
		or $s6,$s6,$t6
		lw $t6,-4($t2)
		srl $t6,$t6,31
		or $s8,$s8,$t6

		lw $t4,height		# $t4 has r
		b life_xform_main_r_loop_test
life_xform_main_r_loop:
		move $s0,$s3
		move $s1,$s4
		move $s2,$s5
		move $s3,$s6
		move $s4,$s7
		move $s5,$s8
		addu $t2,$t2,$t9	# src += words_per_row
		lw $s7,0($t2)		# row_next = *src
		srl $s6,$s7,1		# row_next_l = row_next >> 1
		sll $s8,$s7,1		# row_next_r = row_next << 1
		lw $t6,4($t2)
		sll $t6,$t6,31
		or $s6,$s6,$t6
		lw $t6,-4($t2)
		srl $t6,$t6,31
		or $s8,$s8,$t6

		xor $t5,$s0,$s1		# $t5 is bit0 = row_prev_l ^ row_prev
		and $t6,$s0,$s1		# $t6 is bit1 = row_prev_l & row_prev

		and $t7,$t5,$s2		# $t7 is carry = bit0 & row_prev_r
		and $t8,$t6,$t7		# $t8 is overflow = bit1 & carry
		xor $t6,$t6,$t7		# bit1 = bit1 ^ carry
		xor $t5,$t5,$s2		# bit0 = bit0 ^ row_prev_r

		and $t7,$t5,$s3
		and $v0,$t6,$t7
		or  $t8,$t8,$v0
		xor $t6,$t6,$t7
		xor $t5,$t5,$s3

		# omit $s4

		and $t7,$t5,$s5
		and $v0,$t6,$t7
		or  $t8,$t8,$v0
		xor $t6,$t6,$t7
		xor $t5,$t5,$s5

		and $t7,$t5,$s6
		and $v0,$t6,$t7
		or  $t8,$t8,$v0
		xor $t6,$t6,$t7
		xor $t5,$t5,$s6

		and $t7,$t5,$s7
		and $v0,$t6,$t7
		or  $t8,$t8,$v0
		xor $t6,$t6,$t7
		xor $t5,$t5,$s7

		and $t7,$t5,$s8
		and $v0,$t6,$t7
		nor $t8,$t8,$v0		# $t8 has ~overflow
		xor $t6,$t6,$t7
		xor $t5,$t5,$s8

		and $t8,$t8,$t6		# $t8 has ~overflow & bit1
		and $t7,$t8,$t5		# $t7:carry = ~overflow&bit1 & bit0 (3)
		not $t5,$t5		# $t5 is ~bit0
		and $t8,$t8,$t5		# $t8:overflow=~overflow&bit1&~bit0 (2)
		and $t8,$t8,$s4		# overflow & row_cur
		or  $t7,$t7,$t8		# carry = (.) | carry
		sw $t7,0($t3)		# *dst = ...
		addu $t3,$t3,$t9	# dst += bytes( words_per_row )

life_xform_main_r_loop_test:
		subu $t4,$t4,1
		bge $t4,$zero,life_xform_main_r_loop

		addu $t1,$t1,4		# 4 * ++c
life_xform_main_c_loop_test:
		blt $t1,$t9,life_xform_main_c_loop

		move $t2,$a1
		lw $t4,height
		addu $t4,$t4,2
		li $v1,0xfffffffe
		b life_xform_leading_loop_test
life_xform_leading_loop:
		lw $v0,0($t2)
		and $v0,$v0,$v1
		sw $v0,0($t2)
		addu $t2,$t2,$t9
life_xform_leading_loop_test:
		subu $t4,$t4,1
		bgez $t4,life_xform_leading_loop

		addu $t2,$a1,$t9	# $t2 has src
		subu $t2,$t2,4
		lw $t5,width		# $t5 has bit0
		addu $t5,$t5,1
		and $t5,$t5,0x1f

		li $t6,1		# $t6 has bit1
		sll $t6,$t6,$t5
		subu $t6,$t6,1

		lw $t4,height		# $t4 has r
		addu $t4,$t4,2
		b life_xform_clear_garbage_loop_test
life_xform_clear_garbage_loop:
		lw $v0,0($t2)
		and $v0,$v0,$t6
		sw $v0,0($t2)
		addu $t2,$t2,$t9	# src += words_per_row
life_xform_clear_garbage_loop_test:
		subu $t4,$t4,1
		bgez $t4,life_xform_clear_garbage_loop

		lw $s0,4($sp)
		lw $s1,8($sp)
		lw $s2,12($sp)
		lw $s3,16($sp)
		lw $s4,20($sp)
		lw $s5,24($sp)
		lw $s6,28($sp)
		lw $s7,32($sp)
		lw $fp,36($sp)
		lw $a0,40($sp)
		lw $a1,44($sp)
		lw $a2,48($sp)
		lw $a3,52($sp)
		lw $ra,56($sp)
		add $sp,$sp,56
		jr $ra
