;
;------------------------------------------------------------------
;
; This code is form www.hendrikdettmer.de
;
; Copyright by 
;
;  Thomas Siebert		
;  Johannes Veerkamp
;& Hendrik Dettmer		(me@hendrikdettmer.de)
;
; Have fun!
; Questions? Just mail us!
;-------------------------------------------------------------------
;

.INCLUDE "m163def.inc"	;ATmega163 spezifische Konstanten einbinden
.include "defsenc.inc"

LDI R16, high(ramend)	;R16 ? Höherwertigen 8 Bit des SRAM Endes
LDI R17, low(ramend)	;R17 ? Niederwertigen 8 Bit des SRAM Endes
OUT SPH, R16			;Stack Pointer (high Byte) ? R16
OUT SPL, R17			;Stack Pointer (low Byte) ? R17

;set key
ldi r16,0
ldi r17,1
ldi r18,2
ldi r19,3
ldi r20,4
ldi r21,5
ldi r22,6
ldi r23,7
ldi r24,8


sts $0060,r16
sts $0061,r17
sts $0062,r16
sts $0063,r18
sts $0064,r16
sts $0065,r19
sts $0066,r16
sts $0067,r20
sts $0068,r16
sts $0069,r21
sts $006a,r16
sts $006b,r22
sts $006c,r16
sts $006d,r23
sts $006e,r16
sts $006f,r24

;set plaintext/ciphertext

sts $0070,r16
sts $0071,r16
sts $0072,r16
sts $0073,r17
sts $0074,r16
sts $0075,r18
sts $0076,r16
sts $0077,r19

;set parameter pointers

ldi r24,$70     ;pointer 1 to plaintext
ldi r25,$00
ldi r22,$60     ;pointer 2 to key
ldi r23,$00
ldi r20,$78     ;pointer 3 to 104 free bytes in SRAM
ldi r21,$00



;.... hier kommt Euer Programm rein


;--------------------------------------------------------------
;                           Encryption
;--------------------------------------------------------------

	push texth
	push textl
	
	mov xh, keyh		;load key
	mov xl, keyl
	ld k1h, x+
	ld k1l, x+
	ld k2h, x+
	ld k2l, x+
	ld k3h, x+
	ld k3l, x+
	ld k4h, x+
	ld k4l, x+
	ld k5h, x+
	ld k5l, x+
	ld k6h, x+
	ld k6l, x+
	ld k7h, x+
	ld k7l, x+
	ld k8h, x+
	ld k8l, x+

	mov xh, texth		;load plaintext
	mov xl, textl
	ld p1h, x+
	ld p1l, x+
	ld p2h, x+
	ld p2l, x+
	ld p3h, x+
	ld p3l, x+
	ld p4h, x+
	ld p4l, x+

	clr r0
	clr r1
	inc r1


;--------------------------------------------------------------
;                               Round 1
;--------------------------------------------------------------


;/
;/ p1 x k1 --> p1
;/

	mul	p1h, k1h_1				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k1_1		; Go on if mul nonzero

	mul	p1l, k1l_1
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k1_1		; Go on if mul nonzero

	mul	p1h, k1l_1				; ah * bl
	brne	C_Notzero_k1_1		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k1h_1, p1l				; bh * al
	brne	D_Notzero_k1_1

	add TMP0, k1l_1
	breq keyzerotest_k1_1
	add TMP1, k1h_1
	rjmp negresult_k1_1
keyzerotest_k1_1:
	add TMP1, k1h_1
	brne negresult_k1_1

	mov TMP0, p1l
	mov TMP1, p1h

negresult_k1_1:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k1_1

A_Notzero_k1_1:
	mul	p1l, k1l_1				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k1_1:
	mul	p1h, k1l_1				; ah * bl
C_Notzero_k1_1:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k1h_1, p1l				; bh * al
D_Notzero_k1_1:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k1_1		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k1_1:
	mov p1h, TMP1
	mov p1l, TMP0
	
	
;/	
;/ p2 + k2 --> p2
;/

	add p2l, k2l_1
	adc p2h, k2h_1


;/
;/ p3 + k3 --> p3
;/

	add p3l, k3l_1
	adc p3h, k3h_1

;/
;/ p4 x k4 --> p4
;/

	mul	p4h, k4h_1				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k4_1		; Go on if mul nonzero

	mul	p4l, k4l_1
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k4_1		; Go on if mul nonzero

	mul	p4h, k4l_1				; ah * bl
	brne	C_Notzero_k4_1		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k4h_1, p4l				; bh * al
	brne	D_Notzero_k4_1

	add TMP0, k4l_1
	breq keyzerotest_k4_1
	add TMP1, k4h_1
	rjmp negresult_k4_1
keyzerotest_k4_1:
	add TMP1, k4h_1
	brne negresult_k4_1

	mov TMP0, p4l
	mov TMP1, p4h

negresult_k4_1:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k4_1

A_Notzero_k4_1:
	mul	p4l, k4l_1				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k4_1:
	mul	p4h, k4l_1				; ah * bl
C_Notzero_k4_1:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k4h_1, p4l				; bh * al
D_Notzero_k4_1:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k4_1		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k4_1:
	mov p4h, TMP1
	mov p4l, TMP0


;/
;/ p1 XOR p3 --> i1
;/

	mov i1h, p1h
	mov i1l, p1l
	eor i1h, p3h
	eor i1l, p3l

;/
;/ i1 x k5 --> i1
;/

	mul	i1h, k5h_1				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k5_1		; Go on if mul nonzero

	mul	i1l, k5l_1
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k5_1		; Go on if mul nonzero

	mul	i1h, k5l_1				; ah * bl
	brne	C_Notzero_k5_1		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k5h_1, i1l				; bh * al
	brne	D_Notzero_k5_1

	add TMP0, k5l_1
	breq keyzerotest_k5_1
	add TMP1, k5h_1
	rjmp negresult_k5_1
keyzerotest_k5_1:
	add TMP1, k5h_1
	brne negresult_k5_1

	mov TMP0, i1l
	mov TMP1, i1h

negresult_k5_1:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k5_1

A_Notzero_k5_1:
	mul	i1l, k5l_1				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k5_1:
	mul	i1h, k5l_1				; ah * bl
C_Notzero_k5_1:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k5h_1, i1l				; bh * al
D_Notzero_k5_1:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0


	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k5_1		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k5_1:
	mov i1h, TMP1
	mov i1l, TMP0


;/
;/ p2 XOR p4 --> i2
;/

	mov i2h, p2h
	mov i2l, p2l
	eor i2h, p4h
	eor i2l, p4l

;/
;/ i2 + i1 --> i2
;/

	add i2l, i1l
	adc i2h, i1h

;/
;/ i2 x k6 --> i2
;/

	push i1h
	push i1l

	mov i1h, i2h
	mov i1l, i2l

	mul	i1h, k6h_1				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k6_1		; Go on if mul nonzero

	mul	i1l, k6l_1
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k6_1		; Go on if mul nonzero

	mul	i1h, k6l_1				; ah * bl
	brne	C_Notzero_k6_1		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k6h_1, i1l				; bh * al
	brne	D_Notzero_k6_1

	add TMP0, k6l_1
	breq keyzerotest_k6_1
	add TMP1, k6h_1
	rjmp negresult_k6_1
keyzerotest_k6_1:
	add TMP1, k6h_1
	brne negresult_k6_1

	mov TMP0, i1l
	mov TMP1, i1h

negresult_k6_1:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k6_1

A_Notzero_k6_1:
	mul	i1l, k6l_1				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k6_1:
	mul	i1h, k6l_1				; ah * bl
C_Notzero_k6_1:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k6h_1, i1l				; bh * al
D_Notzero_k6_1:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k6_1		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k6_1:
	mov i2h, TMP1
	mov i2l, TMP0

	pop i1l
	pop i1h 

;/
;/ i1 + i2 --> i1
;/

	add i1l, i2l
	adc i1h, i2h

;/
;/ p1 XOR i2 --> p1
;/

	eor p1h, i2h
	eor p1l, i2l

;/
;/ p3 XOR i2 --> p3
;/

	eor p3h, i2h
	eor p3l, i2l

;/
;/ p2 XOR i1 --> p2
;/

	eor p2h, i1h
	eor p2l, i1l

;/
;/ p4 XOR i1 --> p4
;/

	eor p4h, i1h
	eor p4l, i1l


;--------------------------------------------------------------
;                               Round 2
;--------------------------------------------------------------


;/
;/ p1 x k1 --> p1
;/

	mul	p1h, k1h_2				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k1_2		; Go on if mul nonzero

	mul	p1l, k1l_2
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k1_2		; Go on if mul nonzero

	mul	p1h, k1l_2				; ah * bl
	brne	C_Notzero_k1_2		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k1h_2, p1l				; bh * al
	brne	D_Notzero_k1_2

	add TMP0, k1l_2
	breq keyzerotest_k1_2
	add TMP1, k1h_2
	rjmp negresult_k1_2
keyzerotest_k1_2:
	add TMP1, k1h_2
	brne negresult_k1_2

	mov TMP0, p1l
	mov TMP1, p1h

negresult_k1_2:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k1_2

A_Notzero_k1_2:
	mul	p1l, k1l_2				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k1_2:
	mul	p1h, k1l_2				; ah * bl
C_Notzero_k1_2:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k1h_2, p1l				; bh * al
D_Notzero_k1_2:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0


	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k1_2		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k1_2:
	mov p1h, TMP1
	mov p1l, TMP0
	
	
;/	
;/ p2 + k2 --> p2
;/

	add p2l_g, k2l_2
	adc p2h_g, k2h_2

;/
;/ Key Shift
;/

	lsl k8l
	rol k8h
	rol k7l
	rol k7h
	rol k6l
	rol k6h
	rol k5l
	rol k5h
	rol k4l
	rol k4h
	rol k3l
	rol k3h
	rol k2l
	rol k2h
	rol k1l
	rol k1h
	adc k8l, r0

;/
;/ p3 + k3 --> p3
;/

	add p3l_g, k3l_2
	adc p3h_g, k3h_2

;/
;/ p4 x k4 --> p4
;/

	mul	p4h, k4h_2				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k4_2		; Go on if mul nonzero

	mul	p4l, k4l_2
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k4_2		; Go on if mul nonzero

	mul	p4h, k4l_2				; ah * bl
	brne	C_Notzero_k4_2		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k4h_2, p4l				; bh * al
	brne	D_Notzero_k4_2

	add TMP0, k4l_2
	breq keyzerotest_k4_2
	add TMP1, k4h_2
	rjmp negresult_k4_2
keyzerotest_k4_2:
	add TMP1, k4h_2
	brne negresult_k4_2

	mov TMP0, p4l
	mov TMP1, p4h

negresult_k4_2:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k4_2

A_Notzero_k4_2:
	mul	p4l, k4l_2				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k4_2:
	mul	p4h, k4l_2				; ah * bl
C_Notzero_k4_2:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k4h_2, p4l				; bh * al
D_Notzero_k4_2:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0


	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k4_2		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k4_2:
	mov p4h, TMP1
	mov p4l, TMP0


;/
;/ p1 XOR p3 --> i1
;/

	mov i1h, p1h
	mov i1l, p1l
	eor i1h, p3h_g
	eor i1l, p3l_g

;/
;/ i1 x k5 --> i1
;/

	mul	i1h, k5h_2				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k5_2		; Go on if mul nonzero

	mul	i1l, k5l_2
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k5_2		; Go on if mul nonzero

	mul	i1h, k5l_2				; ah * bl
	brne	C_Notzero_k5_2		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k5h_2, i1l				; bh * al
	brne	D_Notzero_k5_2

	add TMP0, k5l_2
	breq keyzerotest_k5_2
	add TMP1, k5h_2
	rjmp negresult_k5_2
keyzerotest_k5_2:
	add TMP1, k5h_2
	brne negresult_k5_2

	mov TMP0, i1l
	mov TMP1, i1h

negresult_k5_2:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k5_2

A_Notzero_k5_2:
	mul	i1l, k5l_2				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k5_2:
	mul	i1h, k5l_2				; ah * bl
C_Notzero_k5_2:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k5h_2, i1l				; bh * al
D_Notzero_k5_2:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k5_2		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k5_2:
	mov i1h, TMP1
	mov i1l, TMP0


;/
;/ p2 XOR p4 --> i2
;/

	mov i2h, p2h_g
	mov i2l, p2l_g
	eor i2h, p4h
	eor i2l, p4l

;/
;/ i2 + i1 --> i2
;/

	add i2l, i1l
	adc i2h, i1h

;/
;/ i2 x k6 --> i2
;/

	push i1h
	push i1l

	mov i1h, i2h
	mov i1l, i2l

	mul	i1h, k6h_2				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k6_2		; Go on if mul nonzero

	mul	i1l, k6l_2
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k6_2		; Go on if mul nonzero

	mul	i1h, k6l_2				; ah * bl
	brne	C_Notzero_k6_2		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k6h_2, i1l				; bh * al
	brne	D_Notzero_k6_2

	add TMP0, k6l_2
	breq keyzerotest_k6_2
	add TMP1, k6h_2
	rjmp negresult_k6_2
keyzerotest_k6_2:
	add TMP1, k6h_2
	brne negresult_k6_2

	mov TMP0, i1l
	mov TMP1, i1h

negresult_k6_2:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k6_2

A_Notzero_k6_2:
	mul	i1l, k6l_2				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k6_2:
	mul	i1h, k6l_2				; ah * bl
C_Notzero_k6_2:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k6h_2, i1l				; bh * al
D_Notzero_k6_2:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k6_2		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k6_2:
	mov i2h, TMP1
	mov i2l, TMP0

	pop i1l
	pop i1h 

;/
;/ i1 + i2 --> i1
;/

	add i1l, i2l
	adc i1h, i2h

;/
;/ p1 XOR i2 --> p1
;/

	eor p1h, i2h
	eor p1l, i2l

;/
;/ p3 XOR i2 --> p3
;/

	eor p3h_g, i2h
	eor p3l_g, i2l

;/
;/ p2 XOR i1 --> p2
;/

	eor p2h_g, i1h
	eor p2l_g, i1l

;/
;/ p4 XOR i1 --> p4
;/

	eor p4h, i1h
	eor p4l, i1l


;--------------------------------------------------------------
;                               Round 3
;--------------------------------------------------------------


;/
;/ p1 x k1 --> p1
;/

	mul	p1h, k1h_3				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k1_3		; Go on if mul nonzero

	mul	p1l, k1l_3
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k1_3		; Go on if mul nonzero

	mul	p1h, k1l_3				; ah * bl
	brne	C_Notzero_k1_3		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k1h_3, p1l				; bh * al
	brne	D_Notzero_k1_3

	add TMP0, k1l_3
	breq keyzerotest_k1_3
	add TMP1, k1h_3
	rjmp negresult_k1_3
keyzerotest_k1_3:
	add TMP1, k1h_3
	brne negresult_k1_3

	mov TMP0, p1l
	mov TMP1, p1h

negresult_k1_3:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k1_3

A_Notzero_k1_3:
	mul	p1l, k1l_3				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k1_3:
	mul	p1h, k1l_3				; ah * bl
C_Notzero_k1_3:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k1h_3, p1l				; bh * al
D_Notzero_k1_3:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0


	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k1_3		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k1_3:
	mov p1h, TMP1
	mov p1l, TMP0
	
	
;/	
;/ p2 + k2 --> p2
;/

	add p2l, k2l_3
	adc p2h, k2h_3


;/
;/ p3 + k3 --> p3
;/

	add p3l, k3l_3
	adc p3h, k3h_3

;/
;/ p4 x k4 --> p4
;/

	mul	p4h, k4h_3				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k4_3		; Go on if mul nonzero

	mul	p4l, k4l_3
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k4_3		; Go on if mul nonzero

	mul	p4h, k4l_3				; ah * bl
	brne	C_Notzero_k4_3		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k4h_3, p4l				; bh * al
	brne	D_Notzero_k4_3

	add TMP0, k4l_3
	breq keyzerotest_k4_3
	add TMP1, k4h_3
	rjmp negresult_k4_3
keyzerotest_k4_3:
	add TMP1, k4h_3
	brne negresult_k4_3

	mov TMP0, p4l
	mov TMP1, p4h

negresult_k4_3:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k4_3

A_Notzero_k4_3:
	mul	p4l, k4l_3				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k4_3:
	mul	p4h, k4l_3				; ah * bl
C_Notzero_k4_3:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k4h_3, p4l				; bh * al
D_Notzero_k4_3:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k4_3		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k4_3:
	mov p4h, TMP1
	mov p4l, TMP0


;/
;/ Key Shift
;/

	lsl k8l
	rol k8h
	rol k7l
	rol k7h
	rol k6l
	rol k6h
	rol k5l
	rol k5h
	rol k4l
	rol k4h
	rol k3l
	rol k3h
	rol k2l
	rol k2h
	rol k1l
	rol k1h
	adc k8l, r0

;/
;/ p1 XOR p3 --> i1
;/

	mov i1h, p1h
	mov i1l, p1l
	eor i1h, p3h
	eor i1l, p3l

;/
;/ i1 x k5 --> i1
;/

	mul	i1h, k5h_3				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k5_3		; Go on if mul nonzero

	mul	i1l, k5l_3
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k5_3		; Go on if mul nonzero

	mul	i1h, k5l_3				; ah * bl
	brne	C_Notzero_k5_3		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k5h_3, i1l				; bh * al
	brne	D_Notzero_k5_3

	add TMP0, k5l_3
	breq keyzerotest_k5_3
	add TMP1, k5h_3
	rjmp negresult_k5_3
keyzerotest_k5_3:
	add TMP1, k5h_3
	brne negresult_k5_3

	mov TMP0, i1l
	mov TMP1, i1h

negresult_k5_3:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k5_3

A_Notzero_k5_3:
	mul	i1l, k5l_3				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k5_3:
	mul	i1h, k5l_3				; ah * bl
C_Notzero_k5_3:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k5h_3, i1l				; bh * al
D_Notzero_k5_3:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k5_3		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k5_3:
	mov i1h, TMP1
	mov i1l, TMP0


;/
;/ p2 XOR p4 --> i2
;/

	mov i2h, p2h
	mov i2l, p2l
	eor i2h, p4h
	eor i2l, p4l

;/
;/ i2 + i1 --> i2
;/

	add i2l, i1l
	adc i2h, i1h

;/
;/ i2 x k6 --> i2
;/

	push i1h
	push i1l

	mov i1h, i2h
	mov i1l, i2l

	mul	i1h, k6h_3				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k6_3		; Go on if mul nonzero

	mul	i1l, k6l_3
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k6_3		; Go on if mul nonzero

	mul	i1h, k6l_3				; ah * bl
	brne	C_Notzero_k6_3		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k6h_3, i1l				; bh * al
	brne	D_Notzero_k6_3

	add TMP0, k6l_3
	breq keyzerotest_k6_3
	add TMP1, k6h_3
	rjmp negresult_k6_3
keyzerotest_k6_3:
	add TMP1, k6h_3
	brne negresult_k6_3

	mov TMP0, i1l
	mov TMP1, i1h

negresult_k6_3:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k6_3

A_Notzero_k6_3:
	mul	i1l, k6l_3				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k6_3:
	mul	i1h, k6l_3				; ah * bl
C_Notzero_k6_3:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k6h_3, i1l				; bh * al
D_Notzero_k6_3:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k6_3		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k6_3:
	mov i2h, TMP1
	mov i2l, TMP0

	pop i1l
	pop i1h 

;/
;/ i1 + i2 --> i1
;/

	add i1l, i2l
	adc i1h, i2h

;/
;/ p1 XOR i2 --> p1
;/

	eor p1h, i2h
	eor p1l, i2l

;/
;/ p3 XOR i2 --> p3
;/

	eor p3h, i2h
	eor p3l, i2l

;/
;/ p2 XOR i1 --> p2
;/

	eor p2h, i1h
	eor p2l, i1l

;/
;/ p4 XOR i1 --> p4
;/

	eor p4h, i1h
	eor p4l, i1l


;--------------------------------------------------------------
;                               Round 4
;--------------------------------------------------------------


;/
;/ p1 x k1 --> p1
;/

	mul	p1h, k1h_4				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k1_4		; Go on if mul nonzero

	mul	p1l, k1l_4
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k1_4		; Go on if mul nonzero

	mul	p1h, k1l_4				; ah * bl
	brne	C_Notzero_k1_4		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k1h_4, p1l				; bh * al
	brne	D_Notzero_k1_4

	add TMP0, k1l_4
	breq keyzerotest_k1_4
	add TMP1, k1h_4
	rjmp negresult_k1_4
keyzerotest_k1_4:
	add TMP1, k1h_4
	brne negresult_k1_4

	mov TMP0, p1l
	mov TMP1, p1h

negresult_k1_4:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k1_4

A_Notzero_k1_4:
	mul	p1l, k1l_4				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k1_4:
	mul	p1h, k1l_4				; ah * bl
C_Notzero_k1_4:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k1h_4, p1l				; bh * al
D_Notzero_k1_4:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0


	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k1_4		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k1_4:
	mov p1h, TMP1
	mov p1l, TMP0
	
	
;/	
;/ p2 + k2 --> p2
;/

	add p2l_g, k2l_4
	adc p2h_g, k2h_4

;/
;/ p3 + k3 --> p3
;/

	add p3l_g, k3l_4
	adc p3h_g, k3h_4

;/
;/ p4 x k4 --> p4
;/

	mul	p4h, k4h_4				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k4_4		; Go on if mul nonzero

	mul	p4l, k4l_4
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k4_4		; Go on if mul nonzero

	mul	p4h, k4l_4				; ah * bl
	brne	C_Notzero_k4_4		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k4h_4, p4l				; bh * al
	brne	D_Notzero_k4_4

	add TMP0, k4l_4
	breq keyzerotest_k4_4
	add TMP1, k4h_4
	rjmp negresult_k4_4
keyzerotest_k4_4:
	add TMP1, k4h_4
	brne negresult_k4_4

	mov TMP0, p4l
	mov TMP1, p4h

negresult_k4_4:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k4_4

A_Notzero_k4_4:
	mul	p4l, k4l_4				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k4_4:
	mul	p4h, k4l_4				; ah * bl
C_Notzero_k4_4:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k4h_4, p4l				; bh * al
D_Notzero_k4_4:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0


	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k4_4		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k4_4:
	mov p4h, TMP1
	mov p4l, TMP0


;/
;/ p1 XOR p3 --> i1
;/

	mov i1h, p1h
	mov i1l, p1l
	eor i1h, p3h_g
	eor i1l, p3l_g

;/
;/ i1 x k5 --> i1
;/

	mul	i1h, k5h_4				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k5_4		; Go on if mul nonzero

	mul	i1l, k5l_4
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k5_4		; Go on if mul nonzero

	mul	i1h, k5l_4				; ah * bl
	brne	C_Notzero_k5_4		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k5h_4, i1l				; bh * al
	brne	D_Notzero_k5_4

	add TMP0, k5l_4
	breq keyzerotest_k5_4
	add TMP1, k5h_4
	rjmp negresult_k5_4
keyzerotest_k5_4:
	add TMP1, k5h_4
	brne negresult_k5_4

	mov TMP0, i1l
	mov TMP1, i1h

negresult_k5_4:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k5_4

A_Notzero_k5_4:
	mul	i1l, k5l_4				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k5_4:
	mul	i1h, k5l_4				; ah * bl
C_Notzero_k5_4:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k5h_4, i1l				; bh * al
D_Notzero_k5_4:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0


	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k5_4		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k5_4:
	mov i1h, TMP1
	mov i1l, TMP0


;/
;/ p2 XOR p4 --> i2
;/

	mov i2h, p2h_g
	mov i2l, p2l_g
	eor i2h, p4h
	eor i2l, p4l

;/
;/ i2 + i1 --> i2
;/

	add i2l, i1l
	adc i2h, i1h

;/
;/ i2 x k6 --> i2
;/

	push i1h
	push i1l

	mov i1h, i2h
	mov i1l, i2l

	mul	i1h, k6h_4				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k6_4		; Go on if mul nonzero

	mul	i1l, k6l_4
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k6_4		; Go on if mul nonzero

	mul	i1h, k6l_4				; ah * bl
	brne	C_Notzero_k6_4		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k6h_4, i1l				; bh * al
	brne	D_Notzero_k6_4

	add TMP0, k6l_4
	breq keyzerotest_k6_4
	add TMP1, k6h_4
	rjmp negresult_k6_4
keyzerotest_k6_4:
	add TMP1, k6h_4
	brne negresult_k6_4

	mov TMP0, i1l
	mov TMP1, i1h

negresult_k6_4:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k6_4

A_Notzero_k6_4:
	mul	i1l, k6l_4				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k6_4:
	mul	i1h, k6l_4				; ah * bl
C_Notzero_k6_4:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k6h_4, i1l				; bh * al
D_Notzero_k6_4:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k6_4		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k6_4:
	mov i2h, TMP1
	mov i2l, TMP0

	pop i1l
	pop i1h 

;/
;/ i1 + i2 --> i1
;/

	add i1l, i2l
	adc i1h, i2h

;/
;/ p1 XOR i2 --> p1
;/

	eor p1h, i2h
	eor p1l, i2l

;/
;/ p3 XOR i2 --> p3
;/

	eor p3h_g, i2h
	eor p3l_g, i2l

;/
;/ p2 XOR i1 --> p2
;/

	eor p2h_g, i1h
	eor p2l_g, i1l

;/
;/ p4 XOR i1 --> p4
;/

	eor p4h, i1h
	eor p4l, i1l


;--------------------------------------------------------------
;                               Round 5
;--------------------------------------------------------------


;/
;/ Key Shift
;/

	lsl k8l
	rol k8h
	rol k7l
	rol k7h
	rol k6l
	rol k6h
	rol k5l
	rol k5h
	rol k4l
	rol k4h
	rol k3l
	rol k3h
	rol k2l
	rol k2h
	rol k1l
	rol k1h
	adc k8l, r0

;/
;/ p1 x k1 --> p1
;/

	mul	p1h, k1h_5				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k1_5		; Go on if mul nonzero

	mul	p1l, k1l_5
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k1_5		; Go on if mul nonzero

	mul	p1h, k1l_5				; ah * bl
	brne	C_Notzero_k1_5		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k1h_5, p1l				; bh * al
	brne	D_Notzero_k1_5

	add TMP0, k1l_5
	breq keyzerotest_k1_5
	add TMP1, k1h_5
	rjmp negresult_k1_5
keyzerotest_k1_5:
	add TMP1, k1h_5
	brne negresult_k1_5

	mov TMP0, p1l
	mov TMP1, p1h

negresult_k1_5:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k1_5

A_Notzero_k1_5:
	mul	p1l, k1l_5				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k1_5:
	mul	p1h, k1l_5				; ah * bl
C_Notzero_k1_5:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k1h_5, p1l				; bh * al
D_Notzero_k1_5:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k1_5		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k1_5:
	mov p1h, TMP1
	mov p1l, TMP0
	
	
;/	
;/ p2 + k2 --> p2
;/

	add p2l, k2l_5
	adc p2h, k2h_5


;/
;/ p3 + k3 --> p3
;/

	add p3l, k3l_5
	adc p3h, k3h_5

;/
;/ p4 x k4 --> p4
;/

	mul	p4h, k4h_5				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k4_5		; Go on if mul nonzero

	mul	p4l, k4l_5
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k4_5		; Go on if mul nonzero

	mul	p4h, k4l_5				; ah * bl
	brne	C_Notzero_k4_5		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k4h_5, p4l				; bh * al
	brne	D_Notzero_k4_5

	add TMP0, k4l_5
	breq keyzerotest_k4_5
	add TMP1, k4h_5
	rjmp negresult_k4_5
keyzerotest_k4_5:
	add TMP1, k4h_5
	brne negresult_k4_5

	mov TMP0, p4l
	mov TMP1, p4h

negresult_k4_5:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k4_5

A_Notzero_k4_5:
	mul	p4l, k4l_5				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k4_5:
	mul	p4h, k4l_5				; ah * bl
C_Notzero_k4_5:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k4h_5, p4l				; bh * al
D_Notzero_k4_5:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k4_5		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result)
mulmod216_end_k4_5:
	mov p4h, TMP1
	mov p4l, TMP0


;/
;/ p1 XOR p3 --> i1
;/

	mov i1h, p1h
	mov i1l, p1l
	eor i1h, p3h
	eor i1l, p3l

;/
;/ i1 x k5 --> i1
;/

	mul	i1h, k5h_5				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k5_5		; Go on if mul nonzero

	mul	i1l, k5l_5
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k5_5		; Go on if mul nonzero

	mul	i1h, k5l_5				; ah * bl
	brne	C_Notzero_k5_5		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k5h_5, i1l				; bh * al
	brne	D_Notzero_k5_5

	add TMP0, k5l_5
	breq keyzerotest_k5_5
	add TMP1, k5h_5
	rjmp negresult_k5_5
keyzerotest_k5_5:
	add TMP1, k5h_5
	brne negresult_k5_5

	mov TMP0, i1l
	mov TMP1, i1h

negresult_k5_5:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k5_5

A_Notzero_k5_5:
	mul	i1l, k5l_5				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k5_5:
	mul	i1h, k5l_5				; ah * bl
C_Notzero_k5_5:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k5h_5, i1l				; bh * al
D_Notzero_k5_5:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k5_5		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k5_5:
	mov i1h, TMP1
	mov i1l, TMP0


;/
;/ p2 XOR p4 --> i2
;/

	mov i2h, p2h
	mov i2l, p2l
	eor i2h, p4h
	eor i2l, p4l

;/
;/ i2 + i1 --> i2
;/

	add i2l, i1l
	adc i2h, i1h

;/
;/ i2 x k6 --> i2
;/

	push i1h
	push i1l

	mov i1h, i2h
	mov i1l, i2l

	mul	i1h, k6h_5				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k6_5		; Go on if mul nonzero

	mul	i1l, k6l_5
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k6_5		; Go on if mul nonzero

	mul	i1h, k6l_5				; ah * bl
	brne	C_Notzero_k6_5		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k6h_5, i1l				; bh * al
	brne	D_Notzero_k6_5

	add TMP0, k6l_5
	breq keyzerotest_k6_5
	add TMP1, k6h_5
	rjmp negresult_k6_5
keyzerotest_k6_5:
	add TMP1, k6h_5
	brne negresult_k6_5

	mov TMP0, i1l
	mov TMP1, i1h

negresult_k6_5:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k6_5

A_Notzero_k6_5:
	mul	i1l, k6l_5				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k6_5:
	mul	i1h, k6l_5				; ah * bl
C_Notzero_k6_5:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k6h_5, i1l				; bh * al
D_Notzero_k6_5:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k6_5		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k6_5:
	mov i2h, TMP1
	mov i2l, TMP0

	pop i1l
	pop i1h 

;/
;/ i1 + i2 --> i1
;/

	add i1l, i2l
	adc i1h, i2h

;/
;/ p1 XOR i2 --> p1
;/

	eor p1h, i2h
	eor p1l, i2l

;/
;/ p3 XOR i2 --> p3
;/

	eor p3h, i2h
	eor p3l, i2l

;/
;/ p2 XOR i1 --> p2
;/

	eor p2h, i1h
	eor p2l, i1l

;/
;/ p4 XOR i1 --> p4
;/

	eor p4h, i1h
	eor p4l, i1l


;--------------------------------------------------------------
;                               Round 6
;--------------------------------------------------------------


;/
;/ p1 x k1 --> p1
;/

	mul	p1h, k1h_6				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k1_6		; Go on if mul nonzero

	mul	p1l, k1l_6
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k1_6		; Go on if mul nonzero

	mul	p1h, k1l_6				; ah * bl
	brne	C_Notzero_k1_6		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k1h_6, p1l				; bh * al
	brne	D_Notzero_k1_6

	add TMP0, k1l_6
	breq keyzerotest_k1_6
	add TMP1, k1h_6
	rjmp negresult_k1_6
keyzerotest_k1_6:
	add TMP1, k1h_6
	brne negresult_k1_6

	mov TMP0, p1l
	mov TMP1, p1h

negresult_k1_6:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k1_6

A_Notzero_k1_6:
	mul	p1l, k1l_6				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k1_6:
	mul	p1h, k1l_6				; ah * bl
C_Notzero_k1_6:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k1h_6, p1l				; bh * al
D_Notzero_k1_6:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k1_6		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k1_6:
	mov p1h, TMP1
	mov p1l, TMP0
	
	
;/	
;/ p2 + k2 --> p2
;/

	add p2l_g, k2l_6
	adc p2h_g, k2h_6

;/
;/ Key Shift
;/

	lsl k8l
	rol k8h
	rol k7l
	rol k7h
	rol k6l
	rol k6h
	rol k5l
	rol k5h
	rol k4l
	rol k4h
	rol k3l
	rol k3h
	rol k2l
	rol k2h
	rol k1l
	rol k1h
	adc k8l, r0


;/
;/ p3 + k3 --> p3
;/

	add p3l_g, k3l_6
	adc p3h_g, k3h_6

;/
;/ p4 x k4 --> p4
;/

	mul	p4h, k4h_6				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k4_6		; Go on if mul nonzero

	mul	p4l, k4l_6
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k4_6		; Go on if mul nonzero

	mul	p4h, k4l_6				; ah * bl
	brne	C_Notzero_k4_6		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k4h_6, p4l				; bh * al
	brne	D_Notzero_k4_6

	add TMP0, k4l_6
	breq keyzerotest_k4_6
	add TMP1, k4h_6
	rjmp negresult_k4_6
keyzerotest_k4_6:
	add TMP1, k4h_6
	brne negresult_k4_6

	mov TMP0, p4l
	mov TMP1, p4h

negresult_k4_6:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k4_6

A_Notzero_k4_6:
	mul	p4l, k4l_6				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k4_6:
	mul	p4h, k4l_6				; ah * bl
C_Notzero_k4_6:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k4h_6, p4l				; bh * al
D_Notzero_k4_6:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k4_6		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k4_6:
	mov p4h, TMP1
	mov p4l, TMP0


;/
;/ p1 XOR p3 --> i1
;/

	mov i1h, p1h
	mov i1l, p1l
	eor i1h, p3h_g
	eor i1l, p3l_g

;/
;/ i1 x k5 --> i1
;/

	mul	i1h, k5h_6				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k5_6		; Go on if mul nonzero

	mul	i1l, k5l_6
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k5_6		; Go on if mul nonzero

	mul	i1h, k5l_6				; ah * bl
	brne	C_Notzero_k5_6		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k5h_6, i1l				; bh * al
	brne	D_Notzero_k5_6

	add TMP0, k5l_6
	breq keyzerotest_k5_6
	add TMP1, k5h_6
	rjmp negresult_k5_6
keyzerotest_k5_6:
	add TMP1, k5h_6
	brne negresult_k5_6

	mov TMP0, i1l
	mov TMP1, i1h

negresult_k5_6:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k5_6

A_Notzero_k5_6:
	mul	i1l, k5l_6				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k5_6:
	mul	i1h, k5l_6				; ah * bl
C_Notzero_k5_6:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k5h_6, i1l				; bh * al
D_Notzero_k5_6:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k5_6		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k5_6:
	mov i1h, TMP1
	mov i1l, TMP0


;/
;/ p2 XOR p4 --> i2
;/

	mov i2h, p2h_g
	mov i2l, p2l_g
	eor i2h, p4h
	eor i2l, p4l

;/
;/ i2 + i1 --> i2
;/

	add i2l, i1l
	adc i2h, i1h

;/
;/ i2 x k6 --> i2
;/

	push i1h
	push i1l

	mov i1h, i2h
	mov i1l, i2l

	mul	i1h, k6h_6				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k6_6		; Go on if mul nonzero

	mul	i1l, k6l_6
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k6_6		; Go on if mul nonzero

	mul	i1h, k6l_6				; ah * bl
	brne	C_Notzero_k6_6		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k6h_6, i1l				; bh * al
	brne	D_Notzero_k6_6

	add TMP0, k6l_6
	breq keyzerotest_k6_6
	add TMP1, k6h_6
	rjmp negresult_k6_6
keyzerotest_k6_6:
	add TMP1, k6h_6
	brne negresult_k6_6

	mov TMP0, i1l
	mov TMP1, i1h

negresult_k6_6:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k6_6

A_Notzero_k6_6:
	mul	i1l, k6l_6				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k6_6:
	mul	i1h, k6l_6				; ah * bl
C_Notzero_k6_6:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k6h_6, i1l				; bh * al
D_Notzero_k6_6:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k6_6		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k6_6:
	mov i2h, TMP1
	mov i2l, TMP0

	pop i1l
	pop i1h 

;/
;/ i1 + i2 --> i1
;/

	add i1l, i2l
	adc i1h, i2h

;/
;/ p1 XOR i2 --> p1
;/

	eor p1h, i2h
	eor p1l, i2l

;/
;/ p3 XOR i2 --> p3
;/

	eor p3h_g, i2h
	eor p3l_g, i2l

;/
;/ p2 XOR i1 --> p2
;/

	eor p2h_g, i1h
	eor p2l_g, i1l

;/
;/ p4 XOR i1 --> p4
;/

	eor p4h, i1h
	eor p4l, i1l


;--------------------------------------------------------------
;                               Round 7
;--------------------------------------------------------------


;/
;/ p1 x k1 --> p1
;/

	mul	p1h, k1h_7				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k1_7		; Go on if mul nonzero

	mul	p1l, k1l_7
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k1_7		; Go on if mul nonzero

	mul	p1h, k1l_7				; ah * bl
	brne	C_Notzero_k1_7		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k1h_7, p1l				; bh * al
	brne	D_Notzero_k1_7

	add TMP0, k1l_7
	breq keyzerotest_k1_7
	add TMP1, k1h_7
	rjmp negresult_k1_7
keyzerotest_k1_7:
	add TMP1, k1h_7
	brne negresult_k1_7

	mov TMP0, p1l
	mov TMP1, p1h

negresult_k1_7:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k1_7

A_Notzero_k1_7:
	mul	p1l, k1l_7				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k1_7:
	mul	p1h, k1l_7				; ah * bl
C_Notzero_k1_7:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k1h_7, p1l				; bh * al
D_Notzero_k1_7:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k1_7		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k1_7:
	mov p1h, TMP1
	mov p1l, TMP0
	
	
;/	
;/ p2 + k2 --> p2
;/

	add p2l, k2l_7
	adc p2h, k2h_7


;/
;/ p3 + k3 --> p3
;/

	add p3l, k3l_7
	adc p3h, k3h_7

;/
;/ p4 x k4 --> p4
;/

	mul	p4h, k4h_7				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k4_7		; Go on if mul nonzero

	mul	p4l, k4l_7
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k4_7		; Go on if mul nonzero

	mul	p4h, k4l_7				; ah * bl
	brne	C_Notzero_k4_7		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k4h_7, p4l				; bh * al
	brne	D_Notzero_k4_7

	add TMP0, k4l_7
	breq keyzerotest_k4_7
	add TMP1, k4h_7
	rjmp negresult_k4_7
keyzerotest_k4_7:
	add TMP1, k4h_7
	brne negresult_k4_7

	mov TMP0, p4l
	mov TMP1, p4h

negresult_k4_7:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k4_7

A_Notzero_k4_7:
	mul	p4l, k4l_7				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k4_7:
	mul	p4h, k4l_7				; ah * bl
C_Notzero_k4_7:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k4h_7, p4l				; bh * al
D_Notzero_k4_7:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k4_7		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k4_7:
	mov p4h, TMP1
	mov p4l, TMP0

;/
;/ Key Shift
;/

	lsl k8l
	rol k8h
	rol k7l
	rol k7h
	rol k6l
	rol k6h
	rol k5l
	rol k5h
	rol k4l
	rol k4h
	rol k3l
	rol k3h
	rol k2l
	rol k2h
	rol k1l
	rol k1h
	adc k8l, r0


;/
;/ p1 XOR p3 --> i1
;/

	mov i1h, p1h
	mov i1l, p1l
	eor i1h, p3h
	eor i1l, p3l

;/
;/ i1 x k5 --> i1
;/

	mul	i1h, k5h_7				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k5_7		; Go on if mul nonzero

	mul	i1l, k5l_7
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k5_7		; Go on if mul nonzero

	mul	i1h, k5l_7				; ah * bl
	brne	C_Notzero_k5_7		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k5h_7, i1l				; bh * al
	brne	D_Notzero_k5_7

	add TMP0, k5l_7
	breq keyzerotest_k5_7
	add TMP1, k5h_7
	rjmp negresult_k5_7
keyzerotest_k5_7:
	add TMP1, k5h_7
	brne negresult_k5_7

	mov TMP0, i1l
	mov TMP1, i1h

negresult_k5_7:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k5_7

A_Notzero_k5_7:
	mul	i1l, k5l_7				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k5_7:
	mul	i1h, k5l_7				; ah * bl
C_Notzero_k5_7:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k5h_7, i1l				; bh * al
D_Notzero_k5_7:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k5_7		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k5_7:
	mov i1h, TMP1
	mov i1l, TMP0


;/
;/ p2 XOR p4 --> i2
;/

	mov i2h, p2h
	mov i2l, p2l
	eor i2h, p4h
	eor i2l, p4l

;/
;/ i2 + i1 --> i2
;/

	add i2l, i1l
	adc i2h, i1h

;/
;/ i2 x k6 --> i2
;/

	push i1h
	push i1l

	mov i1h, i2h
	mov i1l, i2l

	mul	i1h, k6h_7				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k6_7		; Go on if mul nonzero

	mul	i1l, k6l_7
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k6_7		; Go on if mul nonzero

	mul	i1h, k6l_7				; ah * bl
	brne	C_Notzero_k6_7		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k6h_7, i1l				; bh * al
	brne	D_Notzero_k6_7

	add TMP0, k6l_7
	breq keyzerotest_k6_7
	add TMP1, k6h_7
	rjmp negresult_k6_7
keyzerotest_k6_7:
	add TMP1, k6h_7
	brne negresult_k6_7

	mov TMP0, i1l
	mov TMP1, i1h

negresult_k6_7:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k6_7

A_Notzero_k6_7:
	mul	i1l, k6l_7				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k6_7:
	mul	i1h, k6l_7				; ah * bl
C_Notzero_k6_7:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k6h_7, i1l				; bh * al
D_Notzero_k6_7:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k6_7		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k6_7:
	mov i2h, TMP1
	mov i2l, TMP0

	pop i1l
	pop i1h 

;/
;/ i1 + i2 --> i1
;/

	add i1l, i2l
	adc i1h, i2h

;/
;/ p1 XOR i2 --> p1
;/

	eor p1h, i2h
	eor p1l, i2l

;/
;/ p3 XOR i2 --> p3
;/

	eor p3h, i2h
	eor p3l, i2l

;/
;/ p2 XOR i1 --> p2
;/

	eor p2h, i1h
	eor p2l, i1l

;/
;/ p4 XOR i1 --> p4
;/

	eor p4h, i1h
	eor p4l, i1l


;--------------------------------------------------------------
;                               Round 8
;--------------------------------------------------------------


;/
;/ p1 x k1 --> p1
;/

	mul	p1h, k1h_8				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k1_8		; Go on if mul nonzero

	mul	p1l, k1l_8
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k1_8		; Go on if mul nonzero

	mul	p1h, k1l_8				; ah * bl
	brne	C_Notzero_k1_8		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k1h_8, p1l				; bh * al
	brne	D_Notzero_k1_8

	add TMP0, k1l_8
	breq keyzerotest_k1_8
	add TMP1, k1h_8
	rjmp negresult_k1_8
keyzerotest_k1_8:
	add TMP1, k1h_8
	brne negresult_k1_8

	mov TMP0, p1l
	mov TMP1, p1h

negresult_k1_8:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k1_8

A_Notzero_k1_8:
	mul	p1l, k1l_8				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k1_8:
	mul	p1h, k1l_8				; ah * bl
C_Notzero_k1_8:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k1h_8, p1l				; bh * al
D_Notzero_k1_8:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k1_8		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k1_8:
	mov p1h, TMP1
	mov p1l, TMP0
	
	
;/	
;/ p2 + k2 --> p2
;/

	add p2l_g, k2l_8
	adc p2h_g, k2h_8

;/
;/ p3 + k3 --> p3
;/

	add p3l_g, k3l_8
	adc p3h_g, k3h_8

;/
;/ p4 x k4 --> p4
;/

	mul	p4h, k4h_8				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k4_8		; Go on if mul nonzero

	mul	p4l, k4l_8
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k4_8		; Go on if mul nonzero

	mul	p4h, k4l_8				; ah * bl
	brne	C_Notzero_k4_8		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k4h_8, p4l				; bh * al
	brne	D_Notzero_k4_8

	add TMP0, k4l_8
	breq keyzerotest_k4_8
	add TMP1, k4h_8
	rjmp negresult_k4_8
keyzerotest_k4_8:
	add TMP1, k4h_8
	brne negresult_k4_8

	mov TMP0, p4l
	mov TMP1, p4h

negresult_k4_8:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k4_8

A_Notzero_k4_8:
	mul	p4l, k4l_8				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k4_8:
	mul	p4h, k4l_8				; ah * bl
C_Notzero_k4_8:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k4h_8, p4l				; bh * al
D_Notzero_k4_8:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k4_8		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k4_8:
	mov p4h, TMP1
	mov p4l, TMP0


;/
;/ p1 XOR p3 --> i1
;/

	mov i1h, p1h
	mov i1l, p1l
	eor i1h, p3h_g
	eor i1l, p3l_g

;/
;/ i1 x k5 --> i1
;/

	mul	i1h, k5h_8				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k5_8		; Go on if mul nonzero

	mul	i1l, k5l_8
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k5_8		; Go on if mul nonzero

	mul	i1h, k5l_8				; ah * bl
	brne	C_Notzero_k5_8		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k5h_8, i1l				; bh * al
	brne	D_Notzero_k5_8

	add TMP0, k5l_8
	breq keyzerotest_k5_8
	add TMP1, k5h_8
	rjmp negresult_k5_8
keyzerotest_k5_8:
	add TMP1, k5h_8
	brne negresult_k5_8

	mov TMP0, i1l
	mov TMP1, i1h

negresult_k5_8:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k5_8

A_Notzero_k5_8:
	mul	i1l, k5l_8				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k5_8:
	mul	i1h, k5l_8				; ah * bl
C_Notzero_k5_8:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k5h_8, i1l				; bh * al
D_Notzero_k5_8:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k5_8		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k5_8:
	mov i1h, TMP1
	mov i1l, TMP0


;/
;/ p2 XOR p4 --> i2
;/

	mov i2h, p2h_g
	mov i2l, p2l_g
	eor i2h, p4h
	eor i2l, p4l

;/
;/ i2 + i1 --> i2
;/

	add i2l, i1l
	adc i2h, i1h

;/
;/ i2 x k6 --> i2
;/

	push i1h
	push i1l

	mov i1h, i2h
	mov i1l, i2l

	mul	i1h, k6h_8				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k6_8		; Go on if mul nonzero

	mul	i1l, k6l_8
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k6_8		; Go on if mul nonzero

	mul	i1h, k6l_8				; ah * bl
	brne	C_Notzero_k6_8		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k6h_8, i1l				; bh * al
	brne	D_Notzero_k6_8

	add TMP0, k6l_8
	breq keyzerotest_k6_8
	add TMP1, k6h_8
	rjmp negresult_k6_8
keyzerotest_k6_8:
	add TMP1, k6h_8
	brne negresult_k6_8

	mov TMP0, i1l
	mov TMP1, i1h

negresult_k6_8:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k6_8

A_Notzero_k6_8:
	mul	i1l, k6l_8				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k6_8:
	mul	i1h, k6l_8				; ah * bl
C_Notzero_k6_8:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k6h_8, i1l				; bh * al
D_Notzero_k6_8:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k6_8		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k6_8:
	mov i2h, TMP1
	mov i2l, TMP0

	pop i1l
	pop i1h 

;/
;/ i1 + i2 --> i1
;/

	add i1l, i2l
	adc i1h, i2h

;/
;/ p1 XOR i2 --> p1
;/

	eor p1h, i2h
	eor p1l, i2l

;/
;/ p3 XOR i2 --> p3
;/

	eor p3h_g, i2h
	eor p3l_g, i2l

;/
;/ p2 XOR i1 --> p2
;/

	eor p2h_g, i1h
	eor p2l_g, i1l

;/
;/ p4 XOR i1 --> p4
;/

	eor p4h, i1h
	eor p4l, i1l


;--------------------------------------------------------------
;                               Round 9
;--------------------------------------------------------------

;/
;/ Key Shift
;/

	lsl k6h
	rol k5l
	rol k5h
	rol k4l
	rol k4h
	rol k3l
	rol k3h
	rol k2l
	rol k2h



;/
;/ p1 x k1 --> p1
;/

	mul	p1h, k1h_9				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k1_9		; Go on if mul nonzero

	mul	p1l, k1l_9
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k1_9		; Go on if mul nonzero

	mul	p1h, k1l_9				; ah * bl
	brne	C_Notzero_k1_9		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k1h_9, p1l				; bh * al
	brne	D_Notzero_k1_9

	add TMP0, k1l_9
	breq keyzerotest_k1_9
	add TMP1, k1h_9
	rjmp negresult_k1_9
keyzerotest_k1_9:
	add TMP1, k1h_9
	brne negresult_k1_9

	mov TMP0, p1l
	mov TMP1, p1h

negresult_k1_9:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k1_9

A_Notzero_k1_9:
	mul	p1l, k1l_9				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k1_9:
	mul	p1h, k1l_9				; ah * bl
C_Notzero_k1_9:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k1h_9, p1l				; bh * al
D_Notzero_k1_9:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k1_9		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k1_9:
	mov p1h, TMP1
	mov p1l, TMP0

;/
;/ p2 + k2 --> p2
;/

	add p2l_g, k2l_9
	adc p2h_g, k2h_9


;/
;/ p3 + k3 --> p3
;/

	add p3l_g, k3l_9
	adc p3h_g, k3h_9

;/
;/ p4 x k4 --> p4
;/

	mul	p4h, k4h_9				; ah * bh
	movw	TMP3:TMP2, r1:r0
	brne	A_Notzero_k4_9		; Go on if mul nonzero

	mul	p4l, k4l_9
	movw	TMP1:TMP0, r1:r0
	brne	B_Notzero_k4_9		; Go on if mul nonzero

	mul	p4h, k4l_9				; ah * bl
	brne	C_Notzero_k4_9		; Go on if mul nonzero
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k4h_9, p4l				; bh * al
	brne	D_Notzero_k4_9

	add TMP0, k4l_9
	breq keyzerotest_k4_9
	add TMP1, k4h_9
	rjmp negresult_k4_9
keyzerotest_k4_9:
	add TMP1, k4h_9
	brne negresult_k4_9

	mov TMP0, p4l
	mov TMP1, p4h

negresult_k4_9:
	neg TMP0
	clr r0
	adc TMP1, r0
	neg TMP1
	adiw TMP1:TMP0, 1
	
	rjmp mulmod216_end_k4_9

A_Notzero_k4_9:
	mul	p4l, k4l_9				; al * bl
	movw	TMP1:TMP0, r1:r0

B_Notzero_k4_9:
	mul	p4h, k4l_9				; ah * bl
C_Notzero_k4_9:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	mul	k4h_9, p4l				; bh * al
D_Notzero_k4_9:
	add	TMP1, r0
	adc	TMP2, r1
	clr r0
	adc	TMP3, r0

	sub TMP0, TMP2				;sub low16(result), high16(result)
	sbc TMP1, TMP3
	brsh mulmod216_end_k4_9		;if low16(result) <= high16(result)
	adiw TMP1:TMP0, 1			;    inc low16(result) 
mulmod216_end_k4_9:
	mov p4h, TMP1
	mov p4l, TMP0

	pop xl
	pop xh

	st x+, p1h
	st x+, p1l
	st x+, p2h_g
	st x+, p2l_g
	st x+, p3h_g
	st x+, p3l_g
	st x+, p4h
	st x+, p4l

	ret

.exit
