/*
 * (C) Copyright 2007-2009 Andre McCurdy, NXP Semiconductors
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 *
 * ---------------------------------------------------------------------
 *
 * Instruction counts for the inner loop of SHA1_Transform (each
 * iteration processes 64 bytes of input data).
 *
 *
 *              MIPS/EL      MIPS/EB     MIPS32r2/EL  MIPS32r2/EB
 *
 *   addu         325          325          325          325
 *   xor          312          312          312          312
 *   ror            -            -          240          224
 *   or           312          264           40           40
 *   sll          256          224            -            -
 *   srl          256          224            -            -
 *   and           92           60           60           60
 *   lw            21           21           21           21
 *   wsbh           -            -           16            -
 *   lui           11           11            4            4
 *   ori           11           11            4            4
 *   sw             5            5            5            5
 *   addiu          2            2            2            2
 *   bne            1            1            1            1
 *
 *   Total:      1604         1460         1030          998
 *
 * ---------------------------------------------------------------------
 */

#if 0
#include <asm/regdef.h> 	/* not found with some compilers... */
#else

#define zero	$0
#define AT	$1

#define v0	$2
#define v1	$3

#define a0	$4
#define a1	$5
#define a2	$6
#define a3	$7

#define t0	$8
#define t1	$9
#define t2	$10
#define t3	$11
#define t4	$12
#define t5	$13
#define t6	$14
#define t7	$15

#define s0	$16
#define s1	$17
#define s2	$18
#define s3	$19
#define s4	$20
#define s5	$21
#define s6	$22
#define s7	$23
#define s8	$30		/* == fp */

#define t8	$24
#define t9	$25

#define k0	$26
#define k1	$27

#define gp	$28
#define sp	$29
#define fp	$30		/* == s8 */
#define ra	$31

#endif


#if defined (_MIPS_ARCH_MIPS32R2)

  #define ROTR(y,x,n)		ror	y,x,n

  #define SWAB32(x,tmp1,tmp2)	wsbh	tmp1,x;		\
				ror	x,tmp1,16

  #define LUI_K1(x)		lui	AT,0x5A82
  #define LUI_K1_AGAIN(x)
  #define ORI_K1(x)		ori	AT,AT,0x7999
  #define ORI_K1_AGAIN(x)
  #define LUI_K2(x)		lui	AT,0x6ED9
  #define LUI_K2_AGAIN(x)
  #define ORI_K2(x)		ori	AT,AT,0xEBA1
  #define ORI_K2_AGAIN(x)
  #define LUI_K3(x)		lui	AT,0x8F1B
  #define LUI_K3_AGAIN(x)
  #define ORI_K3(x)		ori	AT,AT,0xBCDC
  #define ORI_K3_AGAIN(x)
  #define LUI_K4(x)		lui	AT,0xCA62
  #define LUI_K4_AGAIN(x)
  #define ORI_K4(x)		ori	AT,AT,0xC1D6
  #define ORI_K4_AGAIN(x)
  #define ADDU_K1(x,k)		addu	x,x,AT
  #define ADDU_K2(x,k)		addu	x,x,AT
  #define ADDU_K3(x,k)		addu	x,x,AT
  #define ADDU_K4(x,k)		addu	x,x,AT

#else

  #define ROTR(y,x,n)		srl	AT,x,n;		\
				sll	y,x,(32-n);	\
				or	y,y,AT

  #define SWAB32(x,tmp1,tmp2)	srl	AT,x,8;		\
				andi	tmp1,x,0xFF00;	\
				sll	tmp2,x,24;	\
				andi	AT,AT,0xFF00;	\
				sll	tmp1,tmp1,8;	\
				srl	x,x,24;		\
				or	tmp2,tmp2,tmp1; \
				or	x,x,AT;		\
				or	x,x,tmp2

  #define LUI_K1(x)		lui	x,0x5A82
  #define LUI_K1_AGAIN(x)		LUI_K1(x)
  #define ORI_K1(x)		ori	x,x,0x7999
  #define ORI_K1_AGAIN(x)		ORI_K1(x)
  #define LUI_K2(x)		lui	x,0x6ED9
  #define LUI_K2_AGAIN(x)		LUI_K2(x)
  #define ORI_K2(x)		ori	x,x,0xEBA1
  #define ORI_K2_AGAIN(x)		ORI_K2(x)
  #define LUI_K3(x)		lui	x,0x8F1B
  #define LUI_K3_AGAIN(x)		LUI_K3(x)
  #define ORI_K3(x)		ori	x,x,0xBCDC
  #define ORI_K3_AGAIN(x)		ORI_K3(x)
  #define LUI_K4(x)		lui	x,0xCA62
  #define LUI_K4_AGAIN(x)		LUI_K4(x)
  #define ORI_K4(x)		ori	x,x,0xC1D6
  #define ORI_K4_AGAIN(x)		ORI_K4(x)
  #define ADDU_K1(x,k)		addu	x,x,k
  #define ADDU_K2(x,k)		addu	x,x,k
  #define ADDU_K3(x,k)		addu	x,x,k
  #define ADDU_K4(x,k)		addu	x,x,k

#endif

/*
   FIXME: endian detection below doesn't always work... ??
*/
#if defined (__MIPSEL__)
  #define CPU_2_BE32(x,tmp1,tmp2)	SWAB32(x,tmp1,tmp2)
#elif defined (__MIPSEB__)
  #define CPU_2_BE32(x,tmp1,tmp2)	/* no-op */
#else
#error "error detecting target byte order"
#endif


	# ------------------------------------------------------------

	.text

	.globl	nxp_SHA1_Transform_asm
	.ent	nxp_SHA1_Transform_asm
	.type	nxp_SHA1_Transform_asm, @function

	#
	# void nxp_SHA1_Transform_asm (u32 *state, u32 *in, u32 iterations)
	#

nxp_SHA1_Transform_asm:

	.set	noreorder
	.set	nomacro
	.set	noat

#define SF_SIZE		64

#define SPO_RA		60(sp)
#define SPO_S8		56(sp)
#define SPO_S7		52(sp)
#define SPO_S6		48(sp)
#define SPO_S5		44(sp)
#define SPO_S4		40(sp)
#define SPO_S3		36(sp)
#define SPO_S2		32(sp)
#define SPO_S1		28(sp)
#define SPO_S0		24(sp)
#define SPO_STATE_PTR	20(sp)
#define SPO_STATE4	16(sp)
#define SPO_STATE3	12(sp)
#define SPO_STATE2	 8(sp)
#define SPO_STATE1	 4(sp)
#define SPO_STATE0	 0(sp)

	beqz		a2, 2f			# if (iterations == 0) then abort
	addiu		sp, sp, -SF_SIZE	# [bds] create stack frame
	sw		a0, SPO_STATE_PTR	# state pointer -> stack
	sw		s0, SPO_S0		# s0 -> stack
	sw		s1, SPO_S1		# s1 -> stack
	sw		s2, SPO_S2		# s2 -> stack
	sw		s3, SPO_S3		# s3 -> stack
	sw		s4, SPO_S4		# s4 -> stack
	sw		s5, SPO_S5		# s5 -> stack
	sw		s6, SPO_S6		# s6 -> stack
	sw		s7, SPO_S7		# s7 -> stack
	sw		s8, SPO_S8		# s8 -> stack
	sw		ra, SPO_RA		# ra -> stack
	lw		t0, 0(a0)		# t0 = A = state[0]
	lw		t1, 4(a0)		# t1 = B = state[1]
	lw		t2, 8(a0)		# t2 = C = state[2]
	lw		t3, 12(a0)		# t3 = D = state[3]
	lw		t4, 16(a0)		# t4 = E = state[4]
	move		ra, a2			# ra = iterations remaining

1:	sw		t0, SPO_STATE0		# state0 -> stack
	sw		t1, SPO_STATE1		# state1 -> stack
	sw		t2, SPO_STATE2		# state2 -> stack
	sw		t3, SPO_STATE3		# state3 -> stack
	sw		t4, SPO_STATE4		# state4 -> stack
	xor		v1, t2, t3
	lw		t8, 0(a1)		# t8 = in[0]
	and		v1, v1, t1
	CPU_2_BE32    ( t8, v0, s7 )		# t8 = x[0]
	xor		v1, v1, t3
	ROTR	      ( a3, t0, 27 )
	lw		t9, 4(a1)		# t9 = in[1]
	addu		a3, a3, v1
	ROTR	      ( t1, t1,	 2 )
	addu		a3, a3, t8
	CPU_2_BE32    ( t9, v0, v1 )		# t9 = x[1]
	addu		a3, a3, t4
	LUI_K1	      ( t4	   )
	xor		v1, t1, t2
	ORI_K1	      ( t4	   )
	lw		s7, 8(a1)		# s7 = in[2]
	and		v1, v1, t0
	ADDU_K1	      ( a3, t4	   )
	xor		v1, v1, t2
	ROTR	      ( a2, a3, 27 )
	ROTR	      ( t0, t0,	 2 )
	addu		a2, a2, v1
	CPU_2_BE32    ( s7, v0, v1 )		# s7 = x[2]
	addu		a2, a2, t9
	xor		v1, t0, t1
	addu		a2, t3, a2
	lw		s6, 12(a1)		# s6 = in[3]
	and		v1, v1, a3
	ADDU_K1	      ( a2, t4	   )
	xor		v1, v1, t1
	ROTR	      ( s8, a2, 27 )
	addu		s8, s8, v1
	ROTR	      ( a3, a3,	 2 )
	addu		s8, s8, s7
	CPU_2_BE32    ( s6, v0, t3 )		# s6 = x[3]
	xor		t3, a3, t0
	addu		s8, t2, s8
	lw		s5, 16(a1)		# s5 = in[4]
	ADDU_K1	      ( s8, t4	   )
	and		t3, t3, a2
	xor		t3, t3, t0
	ROTR	      ( v1, s8, 27 )
	addu		v1, v1, t3
	ROTR	      ( a2, a2,	 2 )
	addu		v1, v1, s6
	CPU_2_BE32    ( s5, v0, t3 )		# s5 = x[4]
	xor		t3, a2, a3
	addu		t1, t1, v1
	lw		s4, 20(a1)		# s4 = in[5]
	ADDU_K1	      ( t1, t4	   )
	and		t3, t3, s8
	xor		t3, t3, a3
	ROTR	      ( v1, t1, 27 )
	addu		v1, v1, t3
	ROTR	      ( s8, s8,	 2 )
	addu		v1, v1, s5
	CPU_2_BE32    ( s4, v0, t3 )		# s4 = x[5]
	xor		t3, s8, a2
	addu		t0, t0, v1
	lw		s3, 24(a1)		# s3 = in[6]
	ADDU_K1	      ( t0, t4	   )
	and		t3, t3, t1
	xor		t3, t3, a2
	ROTR	      ( v1, t0, 27 )
	addu		v1, v1, t3
	ROTR	      ( t1, t1,	 2 )
	addu		v1, v1, s4
	CPU_2_BE32    ( s3, v0, t3 )		# s3 = x[6]
	xor		t3, t1, s8
	addu		a3, a3, v1
	lw		s2, 28(a1)		# s2 = in[7]
	ADDU_K1	      ( a3, t4	   )
	and		t3, t3, t0
	xor		t3, t3, s8
	ROTR	      ( v1, a3, 27 )
	addu		v1, v1, t3
	ROTR	      ( t0, t0,	 2 )
	addu		v1, v1, s3
	CPU_2_BE32    ( s2, v0, t3 )		# s2 = x[7]
	xor		t3, t0, t1
	addu		a2, a2, v1
	lw		s1, 32(a1)		# s1 = in[8]
	ADDU_K1	      ( a2, t4	   )
	and		t3, t3, a3
	xor		t3, t3, t1
	ROTR	      ( v1, a2, 27 )
	addu		v1, v1, t3
	ROTR	      ( a3, a3,	 2 )
	addu		v1, v1, s2
	CPU_2_BE32    ( s1, v0, t3 )		# s1 = x[8]
	xor		t3, a3, t0
	addu		s8, s8, v1
	lw		s0, 36(a1)		# s0 = in[9]
	ADDU_K1	      ( s8, t4	   )
	and		t3, t3, a2
	xor		t3, t3, t0
	ROTR	      ( v1, s8, 27 )
	addu		v1, v1, t3
	ROTR	      ( a2, a2,	 2 )
	addu		v1, v1, s1
	CPU_2_BE32    ( s0, v0, t3 )		# s0 = x[9]
	xor		t3, a2, a3
	addu		t1, t1, v1
	lw		t7, 40(a1)		# t7 = in[10]
	ADDU_K1	      ( t1, t4	   )
	and		t3, t3, s8
	xor		t3, t3, a3
	ROTR	      ( v1, t1, 27 )
	addu		v1, v1, t3
	ROTR	      ( s8, s8,	 2 )
	addu		v1, v1, s0
	CPU_2_BE32    ( t7, v0, t3 )		# t7 = x[10]
	xor		t3, s8, a2
	addu		t0, t0, v1
	lw		t6, 44(a1)		# t6 = in[11]
	ADDU_K1	      ( t0, t4	   )
	and		t3, t3, t1
	xor		t3, t3, a2
	ROTR	      ( v1, t0, 27 )
	addu		v1, v1, t3
	ROTR	      ( t1, t1,	 2 )
	addu		v1, v1, t7
	CPU_2_BE32    ( t6, v0, t3 )		# t6 = x[11]
	xor		t3, t1, s8
	addu		a3, a3, v1
	lw		t2, 48(a1)		# t2 = in[12]
	ADDU_K1	      ( a3, t4	   )
	and		t3, t3, t0
	xor		t3, t3, s8
	ROTR	      ( v1, a3, 27 )
	addu		v1, v1, t3
	ROTR	      ( t0, t0,	 2 )
	addu		v1, v1, t6
	CPU_2_BE32    ( t2, v0, t3 )		# t2 = x[12]
	xor		t3, t0, t1
	addu		a2, a2, v1
	lw		t5, 52(a1)		# t5 = in[13]
	ADDU_K1	      ( a2, t4	   )
	and		t3, t3, a3
	xor		t3, t3, t1
	ROTR	      ( v1, a2, 27 )
	addu		v1, v1, t3
	ROTR	      ( a3, a3,	 2 )
	addu		v1, v1, t2
	CPU_2_BE32    ( t5, v0, t3 )		# t5 = x[13]
	xor		t3, a3, t0
	addu		s8, s8, v1
	ADDU_K1	      ( s8, t4	   )
	and		t3, t3, a2
	lw		a0, 56(a1)		# a0 = in[14]
	xor		t3, t3, t0
	ROTR	      ( v1, s8, 27 )
	addu		v1, v1, t3
	ROTR	      ( a2, a2,	 2 )
	addu		v1, v1, t5
	CPU_2_BE32    ( a0, v0, t3 )		# a0 = x[14]
	addu		t1, t1, v1
	xor		v1, a2, a3
	ADDU_K1	      ( t1, t4	   )
	and		v1, v1, s8
	xor		v1, v1, a3
	ROTR	      ( t3, t1, 27 )
	addu		t3, t3, v1
	addu		t3, t3, a0
	addu		t0, t0, t3
	ADDU_K1	      ( t0, t4	   )
	lw		t4, 60(a1)		# t4 = in[15]
	ROTR	      ( s8, s8,	 2 )
	xor		t3, s8, a2
	and		t3, t3, t1
	CPU_2_BE32    ( t4, v0, v1 )		# t4 = x[15]
	xor		t3, t3, a2
	ROTR	      ( v0, t0, 27 )
	addu		v0, v0, t3
	ROTR	      ( t1, t1,	 2 )
	addu		v0, v0, t4
	LUI_K1_AGAIN  ( t3	   )
	xor		v1, t1, s8
	ORI_K1_AGAIN  ( t3	   )
	addu		a3, a3, v0
	xor		t8, t8, s7
	ADDU_K1	      ( a3, t3	   )
	and		v1, v1, t0
	xor		t8, t8, s1
	xor		v1, v1, s8
	xor		t8, t8, t5
	ROTR	      ( v0, a3, 27 )
	ROTR	      ( t8, t8, 31 )
	addu		v0, v0, v1
	ROTR	      ( t0, t0,	 2 )
	addu		v0, v0, t8
	xor		v1, t0, t1
	addu		a2, a2, v0
	xor		t9, t9, s6
	ADDU_K1	      ( a2, t3	   )
	xor		t9, t9, s0
	and		v1, v1, a3
	xor		v1, v1, t1
	xor		t9, t9, a0
	ROTR	      ( v0, a2, 27 )
	ROTR	      ( t9, t9, 31 )
	addu		v0, v0, v1
	ROTR	      ( a3, a3,	 2 )
	addu		v0, v0, t9
	xor		v1, a3, t0
	addu		s8, s8, v0
	xor		s7, s7, s5
	ADDU_K1	      ( s8, t3	   )
	xor		s7, s7, t7
	and		v1, v1, a2
	xor		v1, v1, t0
	xor		s7, s7, t4
	ROTR	      ( v0, s8, 27 )
	ROTR	      ( s7, s7, 31 )
	addu		v0, v0, v1
	addu		v0, v0, s7
	ROTR	      ( a2, a2,	 2 )
	xor		v1, a2, a3
	addu		t1, t1, v0
	xor		s6, s6, s4
	ADDU_K1	      ( t1, t3	   )
	xor		s6, s6, t6
	and		v1, v1, s8
	xor		v1, v1, a3
	xor		s6, s6, t8
	ROTR	      ( v0, t1, 27 )
	ROTR	      ( s6, s6, 31 )
	addu		v0, v0, v1
	addu		v0, v0, s6
	ROTR	      ( s8, s8,	 2 )
	addu		t0, t0, v0
	xor		s5, s5, s3
	ADDU_K1	      ( t0, t3	   )
	xor		v1, t1, s8
	xor		s5, s5, t2
	xor		v1, v1, a2
	xor		s5, s5, t9
	ROTR	      ( v0, t0, 27 )
	ROTR	      ( s5, s5, 31 )
	addu		v0, v0, v1
	addu		v0, v0, s5
	addu		a3, a3, v0
	LUI_K2	      ( v0	   )
	ROTR	      ( t1, t1,	 2 )
	xor		s4, s4, s2
	ORI_K2	      ( v0	   )
	ADDU_K2	      ( a3, v0	   )
	xor		v1, t0, t1
	xor		s4, s4, t5
	xor		v1, v1, s8
	xor		s4, s4, s7
	ROTR	      ( v0, a3, 27 )
	ROTR	      ( s4, s4, 31 )
	addu		v0, v0, v1
	addu		v0, v0, s4
	LUI_K2_AGAIN  ( v1	   )
	ROTR	      ( t0, t0,	 2 )
	addu		a2, a2, v0
	xor		s3, s3, s1
	ORI_K2_AGAIN  ( v1	   )
	ADDU_K2	      ( a2, v1	   )
	xor		v1, a3, t0
	xor		s3, s3, a0
	xor		v1, v1, t1
	xor		s3, s3, s6
	ROTR	      ( v0, a2, 27 )
	ROTR	      ( s3, s3, 31 )
	addu		v0, v0, v1
	LUI_K2_AGAIN  ( t3	   )
	addu		v0, v0, s3
	ORI_K2_AGAIN  ( t3	   )
	ROTR	      ( a3, a3,	 2 )
	addu		s8, s8, v0
	xor		s2, s2, s0
	ADDU_K2	      ( s8, t3	   )
	xor		v1, a2, a3
	xor		s2, s2, t4
	xor		v1, v1, t0
	xor		s2, s2, s5
	ROTR	      ( v0, s8, 27 )
	ROTR	      ( s2, s2, 31 )
	addu		v0, v0, v1
	addu		v0, v0, s2
	ROTR	      ( a2, a2,	 2 )
	addu		t1, t1, v0
	xor		s1, s1, t7
	ADDU_K2	      ( t1, t3	   )
	xor		v1, s8, a2
	xor		s1, s1, t8
	xor		v1, v1, a3
	xor		s1, s1, s4
	ROTR	      ( v0, t1, 27 )
	ROTR	      ( s1, s1, 31 )
	addu		v0, v0, v1
	addu		v0, v0, s1
	ROTR	      ( s8, s8,	 2 )
	addu		t0, t0, v0
	xor		s0, s0, t6
	ADDU_K2	      ( t0, t3	   )
	xor		v1, t1, s8
	xor		s0, s0, t9
	xor		v1, v1, a2
	xor		s0, s0, s3
	ROTR	      ( v0, t0, 27 )
	ROTR	      ( s0, s0, 31 )
	addu		v0, v0, v1
	addu		v0, v0, s0
	ROTR	      ( t1, t1,	 2 )
	addu		a3, a3, v0
	xor		t7, t7, t2
	ADDU_K2	      ( a3, t3	   )
	xor		v1, t0, t1
	xor		t7, t7, s7
	xor		v1, v1, s8
	xor		t7, t7, s2
	ROTR	      ( v0, a3, 27 )
	ROTR	      ( t7, t7, 31 )
	addu		v0, v0, v1
	addu		v0, v0, t7
	ROTR	      ( t0, t0,	 2 )
	addu		a2, a2, v0
	xor		t6, t6, t5
	ADDU_K2	      ( a2, t3	   )
	xor		v1, a3, t0
	xor		t6, t6, s6
	xor		v1, v1, t1
	xor		t6, t6, s1
	ROTR	      ( v0, a2, 27 )
	ROTR	      ( t6, t6, 31 )
	addu		v0, v0, v1
	addu		v0, v0, t6
	ROTR	      ( a3, a3,	 2 )
	addu		s8, s8, v0
	xor		t2, t2, a0
	ADDU_K2	      ( s8, t3	   )
	xor		v1, a2, a3
	xor		t2, t2, s5
	xor		v1, v1, t0
	xor		t2, t2, s0
	ROTR	      ( v0, s8, 27 )
	ROTR	      ( t2, t2, 31 )
	addu		v0, v0, v1
	addu		v0, v0, t2
	ROTR	      ( a2, a2,	 2 )
	addu		t1, t1, v0
	xor		t5, t5, t4
	ADDU_K2	      ( t1, t3	   )
	xor		v1, s8, a2
	xor		t5, t5, s4
	xor		v1, v1, a3
	xor		t5, t5, t7
	ROTR	      ( v0, t1, 27 )
	ROTR	      ( t5, t5, 31 )
	addu		v0, v0, v1
	addu		v0, v0, t5
	ROTR	      ( s8, s8,	 2 )
	addu		t0, t0, v0
	xor		a0, a0, t8
	ADDU_K2	      ( t0, t3	   )
	xor		v1, t1, s8
	xor		a0, a0, s3
	xor		v1, v1, a2
	xor		a0, a0, t6
	ROTR	      ( v0, t0, 27 )
	ROTR	      ( a0, a0, 31 )
	addu		v0, v0, v1
	addu		v0, v0, a0
	ROTR	      ( t1, t1,	 2 )
	addu		a3, a3, v0
	xor		t4, t4, t9
	ADDU_K2	      ( a3, t3	   )
	xor		v1, t0, t1
	xor		t4, t4, s2
	xor		v1, v1, s8
	xor		t4, t4, t2
	ROTR	      ( v0, a3, 27 )
	ROTR	      ( t4, t4, 31 )
	addu		v0, v0, v1
	addu		v0, v0, t4
	ROTR	      ( t0, t0,	 2 )
	addu		a2, a2, v0
	xor		t8, t8, s7
	ADDU_K2	      ( a2, t3	   )
	xor		v1, a3, t0
	xor		t8, t8, s1
	xor		v1, v1, t1
	xor		t8, t8, t5
	ROTR	      ( v0, a2, 27 )
	ROTR	      ( t8, t8, 31 )
	addu		v0, v0, v1
	addu		v0, v0, t8
	ROTR	      ( a3, a3,	 2 )
	addu		s8, s8, v0
	xor		t9, t9, s6
	ADDU_K2	      ( s8, t3	   )
	xor		v1, a2, a3
	xor		t9, t9, s0
	xor		v1, v1, t0
	xor		t9, t9, a0
	ROTR	      ( v0, s8, 27 )
	ROTR	      ( t9, t9, 31 )
	addu		v0, v0, v1
	addu		v0, v0, t9
	ROTR	      ( a2, a2,	 2 )
	addu		t1, t1, v0
	xor		s7, s7, s5
	ADDU_K2	      ( t1, t3	   )
	xor		v1, s8, a2
	xor		s7, s7, t7
	xor		v1, v1, a3
	xor		s7, s7, t4
	ROTR	      ( v0, t1, 27 )
	ROTR	      ( s7, s7, 31 )
	addu		v0, v0, v1
	addu		v0, v0, s7
	ROTR	      ( s8, s8,	 2 )
	addu		t0, t0, v0
	xor		s6, s6, s4
	ADDU_K2	      ( t0, t3	   )
	xor		v1, t1, s8
	xor		s6, s6, t6
	xor		v1, v1, a2
	xor		s6, s6, t8
	ROTR	      ( v0, t0, 27 )
	ROTR	      ( s6, s6, 31 )
	addu		v0, v0, v1
	addu		v0, v0, s6
	ROTR	      ( t1, t1,	 2 )
	addu		a3, a3, v0
	xor		s5, s5, s3
	ADDU_K2	      ( a3, t3	   )
	xor		v1, t0, t1
	xor		s5, s5, t2
	xor		v1, v1, s8
	xor		s5, s5, t9
	ROTR	      ( v0, a3, 27 )
	ROTR	      ( s5, s5, 31 )
	addu		v0, v0, v1
	addu		v0, v0, s5
	ROTR	      ( t0, t0,	 2 )
	addu		a2, a2, v0
	xor		s4, s4, s2
	ADDU_K2	      ( a2, t3	   )
	xor		v1, a3, t0
	xor		s4, s4, t5
	xor		v1, v1, t1
	xor		s4, s4, s7
	ROTR	      ( v0, a2, 27 )
	ROTR	      ( s4, s4, 31 )
	addu		v0, v0, v1
	addu		v0, v0, s4
	ROTR	      ( a3, a3,	 2 )
	addu		s8, s8, v0
	xor		s3, s3, s1
	ADDU_K2	      ( s8, t3	   )
	xor		v1, a2, a3
	xor		s3, s3, a0
	xor		v1, v1, t0
	xor		s3, s3, s6
	ROTR	      ( v0, s8, 27 )
	ROTR	      ( s3, s3, 31 )
	addu		v0, v0, v1
	addu		v0, v0, s3
	ROTR	      ( a2, a2,	 2 )
	addu		t1, t1, v0
	xor		s2, s2, s0
	ADDU_K2	      ( t1, t3	   )
	xor		v1, s8, a2
	xor		s2, s2, t4
	xor		v1, v1, a3
	xor		s2, s2, s5
	ROTR	      ( v0, t1, 27 )
	ROTR	      ( s2, s2, 31 )
	addu		v0, v0, v1
	ROTR	      ( s8, s8,	 2 )
	addu		v0, v0, s2
	or		v1, t1, s8
	addu		t0, t0, v0
	xor		s1, s1, t7
	ADDU_K2	      ( t0, t3	   )
	and		v0, t1, s8
	xor		s1, s1, t8
	and		v1, v1, a2
	or		v1, v1, v0
	xor		s1, s1, s4
	ROTR	      ( v0, t0, 27 )
	ROTR	      ( s1, s1, 31 )
	addu		v0, v0, v1
	addu		v0, v0, s1
	ROTR	      ( t1, t1,	 2 )
	addu		a3, a3, v0
	LUI_K3	      ( v0	   )
	or		v1, t0, t1
	xor		s0, s0, t6
	ORI_K3	      ( v0	   )
	ADDU_K3	      ( a3, v0	   )
	xor		s0, s0, t9
	and		v0, t0, t1
	and		v1, v1, s8
	xor		s0, s0, s3
	or		v1, v1, v0
	ROTR	      ( v0, a3, 27 )
	ROTR	      ( s0, s0, 31 )
	addu		v0, v0, v1
	ROTR	      ( t0, t0,	 2 )
	addu		v0, v0, s0
	LUI_K3_AGAIN  ( t3	   )
	or		v1, a3, t0
	ORI_K3_AGAIN  ( t3	   )
	addu		a2, a2, v0
	xor		t7, t7, t2
	ADDU_K3	      ( a2, t3	   )
	and		v0, a3, t0
	xor		t7, t7, s7
	and		v1, v1, t1
	or		v1, v1, v0
	xor		t7, t7, s2
	ROTR	      ( v0, a2, 27 )
	ROTR	      ( t7, t7, 31 )
	addu		v0, v0, v1
	ROTR	      ( a3, a3,	 2 )
	addu		v0, v0, t7
	or		v1, a2, a3
	addu		s8, s8, v0
	xor		t6, t6, t5
	ADDU_K3	      ( s8, t3	   )
	and		v0, a2, a3
	xor		t6, t6, s6
	and		v1, v1, t0
	or		v1, v1, v0
	xor		t6, t6, s1
	ROTR	      ( v0, s8, 27 )
	ROTR	      ( t6, t6, 31 )
	addu		v0, v0, v1
	ROTR	      ( a2, a2,	 2 )
	addu		v0, v0, t6
	or		v1, s8, a2
	addu		t1, t1, v0
	xor		t2, t2, a0
	ADDU_K3	      ( t1, t3	   )
	and		v0, s8, a2
	xor		t2, t2, s5
	and		v1, v1, a3
	or		v1, v1, v0
	xor		t2, t2, s0
	ROTR	      ( v0, t1, 27 )
	ROTR	      ( t2, t2, 31 )
	addu		v0, v0, v1
	ROTR	      ( s8, s8,	 2 )
	addu		v0, v0, t2
	or		v1, t1, s8
	addu		t0, t0, v0
	xor		t5, t5, t4
	ADDU_K3	      ( t0, t3	   )
	and		v0, t1, s8
	xor		t5, t5, s4
	and		v1, v1, a2
	or		v1, v1, v0
	xor		t5, t5, t7
	ROTR	      ( v0, t0, 27 )
	ROTR	      ( t5, t5, 31 )
	addu		v0, v0, v1
	ROTR	      ( t1, t1,	 2 )
	addu		v0, v0, t5
	or		v1, t0, t1
	addu		a3, a3, v0
	xor		a0, a0, t8
	ADDU_K3	      ( a3, t3	   )
	and		v0, t0, t1
	xor		a0, a0, s3
	and		v1, v1, s8
	or		v1, v1, v0
	xor		a0, a0, t6
	ROTR	      ( v0, a3, 27 )
	ROTR	      ( a0, a0, 31 )
	addu		v0, v0, v1
	ROTR	      ( t0, t0,	 2 )
	addu		v0, v0, a0
	or		v1, a3, t0
	addu		a2, a2, v0
	xor		t4, t4, t9
	ADDU_K3	      ( a2, t3	   )
	and		v0, a3, t0
	xor		t4, t4, s2
	and		v1, v1, t1
	or		v1, v1, v0
	xor		t4, t4, t2
	ROTR	      ( v0, a2, 27 )
	ROTR	      ( t4, t4, 31 )
	addu		v0, v0, v1
	ROTR	      ( a3, a3,	 2 )
	addu		v0, v0, t4
	or		v1, a2, a3
	addu		s8, s8, v0
	xor		t8, t8, s7
	ADDU_K3	      ( s8, t3	   )
	and		v0, a2, a3
	xor		t8, t8, s1
	and		v1, v1, t0
	or		v1, v1, v0
	xor		t8, t8, t5
	ROTR	      ( v0, s8, 27 )
	ROTR	      ( t8, t8, 31 )
	addu		v0, v0, v1
	ROTR	      ( a2, a2,	 2 )
	addu		v0, v0, t8
	or		v1, s8, a2
	addu		t1, t1, v0
	xor		t9, t9, s6
	ADDU_K3	      ( t1, t3	   )
	and		v0, s8, a2
	xor		t9, t9, s0
	and		v1, v1, a3
	or		v1, v1, v0
	xor		t9, t9, a0
	ROTR	      ( v0, t1, 27 )
	ROTR	      ( t9, t9, 31 )
	addu		v0, v0, v1
	ROTR	      ( s8, s8,	 2 )
	addu		v0, v0, t9
	or		v1, t1, s8
	addu		t0, t0, v0
	xor		s7, s7, s5
	ADDU_K3	      ( t0, t3	   )
	and		v0, t1, s8
	xor		s7, s7, t7
	and		v1, v1, a2
	or		v1, v1, v0
	xor		s7, s7, t4
	ROTR	      ( v0, t0, 27 )
	ROTR	      ( s7, s7, 31 )
	addu		v0, v0, v1
	ROTR	      ( t1, t1,	 2 )
	addu		v0, v0, s7
	or		v1, t0, t1
	addu		a3, a3, v0
	xor		s6, s6, s4
	ADDU_K3	      ( a3, t3	   )
	and		v0, t0, t1
	xor		s6, s6, t6
	and		v1, v1, s8
	or		v1, v1, v0
	xor		s6, s6, t8
	ROTR	      ( v0, a3, 27 )
	ROTR	      ( s6, s6, 31 )
	addu		v0, v0, v1
	ROTR	      ( t0, t0,	 2 )
	addu		v0, v0, s6
	or		v1, a3, t0
	addu		a2, a2, v0
	xor		s5, s5, s3
	ADDU_K3	      ( a2, t3	   )
	and		v0, a3, t0
	xor		s5, s5, t2
	and		v1, v1, t1
	or		v1, v1, v0
	xor		s5, s5, t9
	ROTR	      ( v0, a2, 27 )
	ROTR	      ( s5, s5, 31 )
	addu		v0, v0, v1
	ROTR	      ( a3, a3,	 2 )
	addu		v0, v0, s5
	or		v1, a2, a3
	addu		s8, s8, v0
	xor		s4, s4, s2
	ADDU_K3	      ( s8, t3	   )
	and		v0, a2, a3
	xor		s4, s4, t5
	and		v1, v1, t0
	or		v1, v1, v0
	xor		s4, s4, s7
	ROTR	      ( v0, s8, 27 )
	ROTR	      ( s4, s4, 31 )
	addu		v0, v0, v1
	ROTR	      ( a2, a2,	 2 )
	addu		v0, v0, s4
	or		v1, s8, a2
	addu		t1, t1, v0
	xor		s3, s3, s1
	ADDU_K3	      ( t1, t3	   )
	and		v0, s8, a2
	xor		s3, s3, a0
	and		v1, v1, a3
	or		v1, v1, v0
	xor		s3, s3, s6
	ROTR	      ( v0, t1, 27 )
	ROTR	      ( s3, s3, 31 )
	addu		v0, v0, v1
	ROTR	      ( s8, s8,	 2 )
	addu		v0, v0, s3
	or		v1, t1, s8
	addu		t0, t0, v0
	xor		s2, s2, s0
	ADDU_K3	      ( t0, t3	   )
	and		v0, t1, s8
	xor		s2, s2, t4
	and		v1, v1, a2
	or		v1, v1, v0
	xor		s2, s2, s5
	ROTR	      ( v0, t0, 27 )
	ROTR	      ( s2, s2, 31 )
	addu		v0, v0, v1
	ROTR	      ( t1, t1,	 2 )
	addu		v0, v0, s2
	or		v1, t0, t1
	addu		a3, a3, v0
	xor		s1, s1, t7
	ADDU_K3	      ( a3, t3	   )
	and		v0, t0, t1
	xor		s1, s1, t8
	and		v1, v1, s8
	or		v1, v1, v0
	xor		s1, s1, s4
	ROTR	      ( v0, a3, 27 )
	ROTR	      ( s1, s1, 31 )
	addu		v0, v0, v1
	ROTR	      ( t0, t0,	 2 )
	addu		v0, v0, s1
	or		v1, a3, t0
	addu		a2, a2, v0
	xor		s0, s0, t6
	ADDU_K3	      ( a2, t3	   )
	and		v0, a3, t0
	xor		s0, s0, t9
	and		v1, v1, t1
	or		v1, v1, v0
	xor		s0, s0, s3
	ROTR	      ( v0, a2, 27 )
	ROTR	      ( s0, s0, 31 )
	addu		v0, v0, v1
	ROTR	      ( a3, a3,	 2 )
	addu		v0, v0, s0
	or		v1, a2, a3
	addu		s8, s8, v0
	xor		t7, t7, t2
	ADDU_K3	      ( s8, t3	   )
	and		v0, a2, a3
	xor		t7, t7, s7
	and		v1, v1, t0
	or		v1, v1, v0
	xor		t7, t7, s2
	ROTR	      ( v0, s8, 27 )
	ROTR	      ( t7, t7, 31 )
	addu		v0, v0, v1
	ROTR	      ( a2, a2,	 2 )
	addu		v0, v0, t7
	or		v1, s8, a2
	addu		t1, t1, v0
	xor		t6, t6, t5
	ADDU_K3	      ( t1, t3	   )
	and		v0, s8, a2
	xor		t6, t6, s6
	and		v1, v1, a3
	or		v1, v1, v0
	xor		t6, t6, s1
	ROTR	      ( v0, t1, 27 )
	ROTR	      ( t6, t6, 31 )
	addu		v0, v0, v1
	addu		v0, v0, t6
	ROTR	      ( s8, s8,	 2 )
	addu		t0, t0, v0
	xor		t2, t2, a0
	ADDU_K3	      ( t0, t3	   )
	xor		v1, t1, s8
	xor		t2, t2, s5
	xor		v1, v1, a2
	xor		t2, t2, s0
	ROTR	      ( v0, t0, 27 )
	ROTR	      ( t2, t2, 31 )
	addu		v0, v0, v1
	addu		v0, v0, t2
	addu		a3, a3, v0
	LUI_K4	      ( v0	   )
	ROTR	      ( t1, t1,	 2 )
	xor		t5, t5, t4
	ORI_K4	      ( v0	   )
	ADDU_K4	      ( a3, v0	   )
	xor		v1, t0, t1
	xor		t5, t5, s4
	xor		v1, v1, s8
	xor		t5, t5, t7
	ROTR	      ( v0, a3, 27 )
	ROTR	      ( t5, t5, 31 )
	addu		v0, v0, v1
	addu		v0, v0, t5
	LUI_K4_AGAIN  ( v1	   )
	ROTR	      ( t0, t0,	 2 )
	addu		a2, a2, v0
	xor		a0, a0, t8
	ORI_K4_AGAIN  ( v1	   )
	ADDU_K4	      ( a2, v1	   )
	xor		v1, a3, t0
	xor		a0, a0, s3
	xor		v1, v1, t1
	xor		a0, a0, t6
	ROTR	      ( v0, a2, 27 )
	ROTR	      ( a0, a0, 31 )
	addu		v0, v0, v1
	LUI_K4_AGAIN  ( t3	   )
	addu		v0, v0, a0
	ORI_K4_AGAIN  ( t3	   )
	ROTR	      ( a3, a3,	 2 )
	addu		s8, s8, v0
	xor		t4, t4, t9
	ADDU_K4	      ( s8, t3	   )
	xor		v1, a2, a3
	xor		t4, t4, s2
	xor		v1, v1, t0
	xor		t4, t4, t2
	ROTR	      ( v0, s8, 27 )
	ROTR	      ( t4, t4, 31 )
	addu		v0, v0, v1
	addu		v0, v0, t4
	ROTR	      ( a2, a2,	 2 )
	addu		t1, t1, v0
	xor		t8, t8, s7
	ADDU_K4	      ( t1, t3	   )
	xor		v1, s8, a2
	xor		t8, t8, s1
	xor		v1, v1, a3
	xor		t8, t8, t5
	ROTR	      ( v0, t1, 27 )
	ROTR	      ( t8, t8, 31 )
	addu		v0, v0, v1
	addu		v0, v0, t8
	ROTR	      ( s8, s8,	 2 )
	addu		t0, t0, v0
	xor		t9, t9, s6
	ADDU_K4	      ( t0, t3	   )
	xor		v1, t1, s8
	xor		t9, t9, s0
	xor		v1, v1, a2
	xor		t9, t9, a0
	ROTR	      ( v0, t0, 27 )
	ROTR	      ( t9, t9, 31 )
	addu		v0, v0, v1
	addu		v0, v0, t9
	ROTR	      ( t1, t1,	 2 )
	addu		a3, a3, v0
	xor		s7, s7, s5
	ADDU_K4	      ( a3, t3	   )
	xor		v1, t0, t1
	xor		s7, s7, t7
	xor		v1, v1, s8
	xor		s7, s7, t4
	ROTR	      ( v0, a3, 27 )
	ROTR	      ( s7, s7, 31 )
	addu		v0, v0, v1
	addu		v0, v0, s7
	ROTR	      ( t0, t0,	 2 )
	addu		a2, a2, v0
	xor		s6, s6, s4
	ADDU_K4	      ( a2, t3	   )
	xor		v1, a3, t0
	xor		s6, s6, t6
	xor		v1, v1, t1
	ROTR	      ( v0, a2, 27 )
	xor		s6, s6, t8
	ROTR	      ( s6, s6, 31 )
	addu		v0, v0, v1
	addu		v0, v0, s6
	ROTR	      ( a3, a3,	 2 )
	addu		s8, s8, v0
	xor		s5, s5, s3
	ADDU_K4	      ( s8, t3	   )
	xor		v1, a2, a3
	xor		s5, s5, t2
	xor		v1, v1, t0
	ROTR	      ( v0, s8, 27 )
	xor		s5, s5, t9
	ROTR	      ( s5, s5, 31 )
	addu		v0, v0, v1
	addu		v0, v0, s5
	ROTR	      ( a2, a2,	 2 )
	addu		t1, t1, v0
	xor		s4, s4, s2
	ADDU_K4	      ( t1, t3	   )
	xor		v1, s8, a2
	xor		s4, s4, t5
	xor		v1, v1, a3
	ROTR	      ( v0, t1, 27 )
	xor		s4, s4, s7
	ROTR	      ( s4, s4, 31 )
	addu		v0, v0, v1
	addu		v0, v0, s4
	ROTR	      ( s8, s8,	 2 )
	addu		t0, t0, v0
	xor		s3, s3, s1
	ADDU_K4	      ( t0, t3	   )
	xor		v1, t1, s8
	xor		s3, s3, a0
	xor		v1, v1, a2
	ROTR	      ( v0, t0, 27 )
	xor		s3, s3, s6
	ROTR	      ( s3, s3, 31 )
	addu		v0, v0, v1
	addu		v0, v0, s3
	ROTR	      ( t1, t1,	 2 )
	addu		a3, a3, v0
	xor		s2, s2, s0
	ADDU_K4	      ( a3, t3	   )
	xor		v1, t0, t1
	xor		s2, s2, t4
	xor		v1, v1, s8
	ROTR	      ( v0, a3, 27 )
	xor		s2, s2, s5
	ROTR	      ( s2, s2, 31 )
	addu		v0, v0, v1
	addu		v0, v0, s2
	ROTR	      ( t0, t0,	 2 )
	addu		a2, a2, v0
	xor		s1, s1, t7
	ADDU_K4	      ( a2, t3	   )
	xor		v1, a3, t0
	xor		s1, s1, t8
	xor		v1, v1, t1
	ROTR	      ( v0, a2, 27 )
	xor		s1, s1, s4
	addu		v0, v0, v1
	ROTR	      ( s1, s1, 31 )
	addu		v0, v0, s1
	ROTR	      ( a3, a3,	 2 )
	addu		s8, s8, v0
	xor		s0, s0, t6
	ADDU_K4	      ( s8, t3	   )
	xor		v1, a2, a3
	xor		s0, s0, t9
	xor		v1, v1, t0
	ROTR	      ( v0, s8, 27 )
	xor		s0, s0, s3
	addu		v0, v0, v1
	ROTR	      ( s0, s0, 31 )
	addu		v0, v0, s0
	ROTR	      ( a2, a2,	 2 )
	addu		t1, t1, v0
	xor		t7, t7, t2
	ADDU_K4	      ( t1, t3	   )
	xor		v1, s8, a2
	xor		t7, t7, s7
	xor		v1, v1, a3
	ROTR	      ( v0, t1, 27 )
	xor		t7, t7, s2
	addu		v0, v0, v1
	ROTR	      ( t7, t7, 31 )
	addu		v0, v0, t7
	ROTR	      ( s8, s8,	 2 )
	addu		t0, t0, v0
	xor		t6, t6, t5
	ADDU_K4	      ( t0, t3	   )
	xor		v1, t1, s8
	xor		t6, t6, s6
	xor		v1, v1, a2
	ROTR	      ( v0, t0, 27 )
	xor		t6, t6, s1
	addu		v0, v0, v1
	ROTR	      ( t6, t6, 31 )
	addu		v0, v0, t6
	ROTR	      ( t1, t1,	 2 )
	addu		a3, a3, v0
	xor		t2, t2, a0
	ADDU_K4	      ( a3, t3	   )
	xor		v1, t0, t1
	xor		t2, t2, s5
	xor		v1, v1, s8
	ROTR	      ( v0, a3, 27 )
	xor		t2, t2, s0
	ROTR	      ( t2, t2, 31 )
	addu		v0, v0, v1
	addu		v0, v0, t2
	ROTR	      ( t0, t0,	 2 )
	addu		a2, a2, v0
	xor		t5, t5, t4
	ADDU_K4	      ( a2, t3	   )
	xor		v1, a3, t0
	xor		t5, t5, s4
	xor		v1, v1, t1
	ROTR	      ( v0, a2, 27 )
	xor		t5, t5, t7
	addu		v0, v0, v1
	ROTR	      ( t5, t5, 31 )
	addu		v0, v0, t5
	ROTR	      ( a3, a3,	 2 )
	addu		s8, s8, v0
	xor		a0, a0, t8
	ADDU_K4	      ( s8, t3	   )
	xor		v1, a2, a3
	xor		a0, a0, s3
	xor		v1, v1, t0
	ROTR	      ( v0, s8, 27 )
	xor		a0, a0, t6
	addu		v0, v0, v1
	ROTR	      ( a0, a0, 31 )
	addu		v0, v0, a0
	xor		t4, t4, t9
	addu		t1, t1, v0
	ROTR	      ( a2, a2,	 2 )
	xor		t4, t4, s2
	ADDU_K4	      ( t1, t3	   )
	xor		v0, s8, a2
	xor		t4, t4, t2
	xor		v0, v0, a3
	ROTR	      ( v1, t1, 27 )
	addu		v1, v1, v0
	ROTR	      ( t4, t4, 31 )
	addu		v1, v1, t4
	addu		t0, t0, v1
	lw		v0, SPO_STATE0		# v0 = state0
	lw		t3, SPO_STATE1		# t3 = state1
	lw		t4, SPO_STATE2		# t4 = state2
	lw		a0, SPO_STATE3		# a0 = state3
	lw		t5, SPO_STATE4		# t5 = state4
	LUI_K4_AGAIN  ( v1	   )
	ORI_K4_AGAIN  ( v1	   )
	ROTR	      ( s8, s8,	 2 )
	ADDU_K4	      ( t0, v1	   )
	addu		t2, s8, t4		# t2 = state2 + C
	addu		t4, a3, t5		# t4 = state4 + E
	addu		t0, t0, v0		# t0 = state0 + A
	addu		t1, t1, t3		# t1 = state1 + B
	addu		t3, a2, a0		# t3 = state3 + D
	addiu		ra, ra, -1		# iterations--
	bnez		ra, 1b			# loop if (iterations != 0)
	addiu		a1, a1, 64		# [bds] in += 16

	lw		t5, SPO_STATE_PTR	# t5 = &state[0]
	lw		s0, SPO_S0
	lw		s1, SPO_S1
	lw		s2, SPO_S2
	lw		s3, SPO_S3
	lw		s4, SPO_S4
	lw		s5, SPO_S5
	lw		s6, SPO_S6
	lw		s7, SPO_S7
	lw		s8, SPO_S8
	lw		ra, SPO_RA
	sw		t0, 0(t5)		# return final result : state[0]
	sw		t1, 4(t5)		# return final result : state[1]
	sw		t2, 8(t5)		# return final result : state[2]
	sw		t3, 12(t5)		# return final result : state[3]
	sw		t4, 16(t5)		# return final result : state[4]

2:	jr		ra
	addiu		sp, sp, SF_SIZE		# [bds] return stack frame

	# ------------------------------------------------------------

	.byte	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
	.byte	0x41,0x6e,0x64,0x72,0x65,0x20,0x4d,0x63,0x43,0x75,0x72,0x64
	.byte	0x79,0x20,0x20,0x20,0x32,0x30,0x30,0x37,0x2d,0x30,0x37,0x2d
	.byte	0x31,0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00,0x00,0x00

	# ------------------------------------------------------------

	.set		at
	.set		macro
	.set		reorder

	.end		nxp_SHA1_Transform_asm

