;(C)2005 wek   http://www.efton.sk
;free for personal use
;for commercial use, please contact wek@efton.sk

;for comments see skipfast.asm

;901 cycles including ret
;uses 3AEh=942 words = 1884 bytes of FLASH (including the 256-byte F-table)

.dseg




;register definitions
.def		ZL		= r30	
.def		ZH		= r31	

;r0 reserved for LPM
.def            key_0           = r1
.def            key_1           = r2
.def            key_2           = r3
.def            key_3           = r4
.def            key_4           = r5
.def            key_5           = r6
.def            key_6           = r7
.def            key_7           = r8
.def            key_8           = r9
.def            key_9           = r10


.def            w1              = r16
.def            w1_1            = r17
.def            w2              = r18
.def            w2_1            = r19
.def            w3              = r20
.def            w3_1            = r21
.def            w4              = r22
.def            w4_1            = r23

.include "m128def.inc"  ;just for the test to be able to define stack

.cseg
SkipJackTest:
   ldi   ZL,LOW(RAMEND)
   out   SPL,ZL
   ldi   ZH,HIGH(RAMEND)
   out   SPH,ZH

   ldi   ZL,LOW(TestVector*2)
   ldi   ZH,HIGH(TestVector*2)

SJTX1:
   lpm  key_0,Z+
   lpm  key_1,Z+
   lpm  key_2,Z+
   lpm  key_3,Z+
   lpm  key_4,Z+
   lpm  key_5,Z+
   lpm  key_6,Z+
   lpm  key_7,Z+
   lpm  key_8,Z+
   lpm  key_9,Z+

   lpm  w1_1,Z+
   lpm  w1,Z+
   lpm  w2_1,Z+
   lpm  w2,Z+
   lpm  w3_1,Z+
   lpm  w3,Z+
   lpm  w4_1,Z+
   lpm  w4,Z+

   push  ZL
   push  ZH
   rcall iSkipJack
   pop   ZH
   pop   ZL

   lpm  r0,Z+
   cp   r0,w1_1
   brne stopNG
   lpm  r0,Z+
   cp   r0,w1
   brne stopNG
   lpm  r0,Z+
   cp   r0,w2_1
   brne stopNG
   lpm  r0,Z+
   cp   r0,w2
   brne stopNG
   lpm  r0,Z+
   cp   r0,w3_1
   brne stopNG
   lpm  r0,Z+
   cp   r0,w3
   brne stopNG
   lpm  r0,Z+
   cp   r0,w4_1
   brne stopNG
   lpm  r0,Z+
   cp   r0,w4
   brne stopNG

   cpi  ZL,LOW(TestVectorEnd*2)
   brne SJTX1
   cpi  ZH,HIGH(TestVectorEnd*2)
   brne SJTX1

stopOK:
   rjmp stopOK

stopNG:
   rjmp stopNG



TestVector:
;This vector is from the SKIPJACK protocol specification:

 .db     $00,$99,$88,$77,$66,$55,$44,$33,$22,$11       ; key
 .db     $25,$87,$ca,$e2,$7a,$12,$d3,$00 ; ciphertext
 .db     $33,$22,$11,$00,$dd,$cc,$bb,$aa ; plaintext

; Unfortunately that's the only "official" vector we have.  It really
; sucks that the specification doesn't contain more vectorsh, as this one
; only covers 104 of the 256 entries of the F table.

; Here are some more that were posted to the Usenet newsgroup sci.crypt by
; Jason Stratos Papadopoulos <jasonp@glue.umd.edu> on 27-Jun-1998
; http://www.dejanews.com/getdoc.xp?AN=366465228

       .db      $f8,$da,$02,$64,$77,$22,$f7,$10,$3a,$df       ; key
       .db      $c9,$2d,$22,$32,$4c,$6b,$31,$ae ; ciphertext
       .db      $1d,$df,$39,$ab,$f5,$cd,$71,$1e ; plaintext

       .db      $82,$76,$0a,$c1,$37,$94,$88,$21,$ee,$e4       ; key
       .db      $e3,$28,$77,$c1,$d9,$52,$7f,$ff ; ciphertext
       .db      $dd,$6c,$6c,$ce,$8f,$83,$e6,$9e ; plaintext

       .db      $84,$3c,$16,$87,$d3,$cd,$ca,$5f,$c5,$c3       ; key
       .db      $47,$45,$78,$3f,$75,$b8,$86,$1a ; ciphertext
       .db      $be,$aa,$cf,$17,$7f,$a4,$1a,$11 ; plaintext

       .db      $ae,$87,$0c,$d7,$ff,$33,$a9,$95,$f7,$e5       ; key
       .db      $5c,$10,$16,$36,$b8,$a5,$7a,$72 ; ciphertext
       .db      $c4,$c0,$9f,$21,$6c,$1b,$c6,$0a ; plaintext

       .db      $5c,$cb,$d9,$13,$ea,$8b,$73,$bd,$63,$91       ; key
       .db      $b4,$fc,$0f,$8e,$54,$72,$8f,$91 ; ciphertext
       .db      $d3,$f8,$14,$b0,$00,$24,$58,$56 ; plaintext

       .db      $f6,$5e,$74,$cd,$59,$9c,$68,$a4,$0c,$c7       ; key
       .db      $93,$b7,$50,$60,$8f,$57,$01,$f8 ; ciphertext
       .db      $35,$6e,$c7,$d9,$38,$32,$32,$9c ; plaintext

       .db      $aa,$10,$6e,$46,$d7,$08,$7c,$4e,$93,$dc       ; key
       .db      $d8,$23,$d4,$55,$10,$09,$9e,$61 ; ciphertext
       .db      $20,$9e,$cf,$1c,$53,$7a,$d5,$6c ; plaintext

       .db      $a9,$3f,$97,$89,$a2,$0c,$3c,$c3,$4f,$ea       ; key
       .db      $09,$59,$e2,$31,$b2,$75,$d9,$5f ; ciphertext
       .db      $89,$2e,$ea,$9d,$64,$e1,$7d,$66 ; plaintext

       .db      $88,$b1,$63,$cb,$d6,$16,$16,$88,$88,$99       ; key
       .db      $e7,$70,$02,$09,$88,$67,$67,$ae ; ciphertext
       .db      $99,$13,$90,$fd,$76,$0f,$c9,$1b ; plaintext

       .db      $fb,$6c,$d1,$ff,$70,$48,$75,$61,$df,$10       ; key
       .db      $e7,$cc,$49,$a5,$6b,$d6,$a3,$22 ; ciphertext
       .db      $da,$eb,$c9,$47,$dd,$ca,$9c,$9e ; plaintext

       .db      $5e,$dc,$1a,$c0,$c4,$e7,$ef,$5f,$00,$2c       ; key
       .db      $e4,$8a,$05,$cf,$26,$e2,$42,$fd ; ciphertext
       .db      $64,$19,$dd,$ef,$e2,$cd,$8f,$2e ; plaintext

       .db      $8e,$30,$90,$c1,$9a,$a3,$2f,$94,$49,$6a       ; key
       .db      $62,$c0,$e5,$37,$b1,$4d,$f2,$c1 ; ciphertext
       .db      $32,$29,$98,$ec,$bd,$06,$81,$12 ; plaintext

       .db      $b9,$6e,$3f,$d4,$6f,$a4,$26,$3f,$90,$92       ; key
       .db      $54,$d1,$e5,$8a,$6b,$62,$4d,$71 ; ciphertext
       .db      $3a,$ae,$2a,$ee,$20,$da,$93,$cc ; plaintext

       .db      $9e,$66,$35,$ba,$ee,$28,$c5,$bc,$e2,$bc       ; key
       .db      $5d,$0f,$23,$5a,$9d,$22,$1c,$e0 ; ciphertext
       .db      $14,$31,$11,$12,$ca,$11,$f7,$27 ; plaintext

       .db      $04,$12,$7c,$e1,$6d,$c1,$b1,$72,$6a,$66       ; key
       .db      $8e,$5b,$03,$52,$2e,$68,$cb,$eb ; ciphertext
       .db      $30,$0e,$43,$13,$e7,$ad,$67,$96 ; plaintext

       .db      $f0,$b8,$9d,$75,$e9,$79,$cc,$c9,$b1,$72       ; key
       .db      $57,$2c,$9b,$40,$25,$a9,$13,$4b ; ciphertext
       .db      $09,$cd,$1c,$1a,$cc,$be,$77,$97 ; plaintext

       .db      $f9,$bf,$c7,$87,$98,$cb,$f1,$bc,$d4,$b5       ; key
       .db      $8c,$95,$9c,$90,$47,$89,$fb,$da ; ciphertext
       .db      $31,$b3,$0c,$a3,$54,$af,$3c,$d8 ; plaintext

       .db      $f4,$3a,$51,$b4,$27,$3b,$de,$27,$d2,$b0       ; key
       .db      $b7,$d7,$f5,$fa,$34,$29,$88,$fb ; ciphertext
       .db      $08,$c5,$9b,$0d,$b9,$9e,$c2,$67 ; plaintext

       .db      $cd,$51,$f0,$a7,$5a,$a7,$3c,$48,$ed,$d2       ; key
       .db      $76,$3a,$a8,$ee,$10,$93,$97,$b3 ; ciphertext
       .db      $97,$84,$b1,$e3,$e7,$e6,$0e,$60 ; plaintext

       .db      $b3,$31,$9a,$3f,$66,$22,$aa,$72,$6b,$b3       ; key
       .db      $03,$25,$60,$03,$37,$b8,$ad,$3c ; ciphertext
       .db      $f6,$52,$16,$37,$3d,$4b,$43,$c7 ; plaintext

       .db      $49,$32,$54,$c9,$59,$6e,$99,$3f,$5f,$9c       ; key
       .db      $68,$e1,$c5,$51,$c5,$91,$08,$c0 ; ciphertext
       .db      $cb,$a4,$c1,$21,$5d,$5d,$36,$ce ; plaintext

       .db      $76,$15,$0c,$2c,$3c,$ed,$1c,$7c,$a0,$21       ; key
       .db      $7e,$b6,$32,$5d,$82,$a2,$09,$6c ; ciphertext
       .db      $82,$29,$48,$51,$28,$8e,$75,$cb ; plaintext

       .db      $71,$40,$d6,$c5,$48,$63,$05,$87,$2d,$f6       ; key
       .db      $24,$83,$f3,$85,$a4,$2e,$e3,$c6 ; ciphertext
       .db      $c3,$a7,$b7,$e4,$a5,$2e,$40,$7b ; plaintext

       .db      $3c,$2c,$39,$01,$f0,$ee,$9a,$3b,$2b,$0e       ; key
       .db      $d6,$fa,$9d,$b8,$68,$5f,$d8,$8a ; ciphertext
       .db      $1b,$fd,$e3,$2a,$b5,$59,$e1,$3a ; plaintext

       .db      $60,$6a,$8b,$4b,$df,$aa,$e8,$a0,$ba,$51       ; key
       .db      $03,$30,$48,$91,$70,$b8,$52,$93 ; ciphertext
       .db      $d2,$05,$f7,$48,$6c,$78,$28,$38 ; plaintext

       .db      $78,$47,$a4,$7a,$0f,$e7,$9a,$b7,$70,$ce       ; key
       .db      $1f,$9b,$33,$01,$c9,$b2,$70,$8c ; ciphertext
       .db      $d9,$6f,$f1,$f7,$c7,$fc,$60,$e0 ; plaintext

       .db      $73,$b9,$ab,$0c,$36,$c9,$9e,$91,$a8,$91       ; key
       .db      $2b,$86,$c5,$7f,$fe,$16,$88,$95 ; ciphertext
       .db      $24,$1d,$4b,$de,$19,$a7,$5f,$8f ; plaintext

       .db      $a3,$7f,$2a,$d5,$a8,$5e,$17,$07,$41,$f5       ; key
       .db      $5a,$f7,$ce,$b3,$ee,$d9,$dc,$a1 ; ciphertext
       .db      $7b,$e1,$b8,$d5,$83,$21,$c6,$19 ; plaintext

       .db      $f7,$b0,$c2,$a8,$17,$0e,$3c,$4e,$48,$b3       ; key
       .db      $1b,$58,$77,$36,$e1,$16,$c0,$4b ; ciphertext
       .db      $c9,$21,$4e,$a0,$1e,$c1,$49,$48 ; plaintext

       .db      $a1,$fc,$67,$e4,$4e,$ac,$ac,$f4,$a9,$02       ; key
       .db      $f3,$ec,$f0,$f1,$78,$9a,$39,$23 ; ciphertext
       .db      $e2,$a3,$09,$1f,$eb,$58,$15,$88 ; plaintext

       .db      $f1,$44,$30,$af,$fc,$5f,$e8,$2a,$9a,$e9       ; key
       .db      $e8,$d1,$14,$c2,$0f,$fa,$1c,$79 ; ciphertext
       .db      $3c,$b4,$66,$d3,$01,$b6,$08,$54 ; plaintext

       .db      $fd,$26,$df,$50,$48,$6a,$4c,$d9,$6d,$9b       ; key
       .db      $22,$29,$03,$99,$4d,$64,$fe,$3a ; ciphertext
       .db      $b0,$68,$4f,$8a,$5e,$63,$d9,$35 ; plaintext

       .db      $a6,$d4,$6d,$46,$ca,$28,$7e,$1a,$33,$2a       ; key
       .db      $91,$f2,$ba,$ad,$6f,$a0,$de,$55 ; ciphertext
       .db      $ba,$1f,$37,$e8,$8e,$de,$c5,$5f ; plaintext

       .db      $83,$c3,$f1,$cb,$8d,$06,$ef,$c6,$19,$6b       ; key
       .db      $83,$f9,$f0,$8f,$89,$a8,$54,$ee ; ciphertext
       .db      $e9,$fe,$d8,$50,$1b,$7a,$65,$79 ; plaintext

       .db      $0e,$df,$a4,$4c,$7d,$4a,$4e,$f0,$72,$5e       ; key
       .db      $2b,$1b,$66,$70,$a6,$be,$03,$24 ; ciphertext
       .db      $eb,$5c,$a8,$b3,$fa,$1f,$cd,$bb ; plaintext

       .db      $b8,$ed,$cf,$16,$7d,$99,$a7,$11,$cc,$ee       ; key
       .db      $21,$1a,$69,$5d,$a4,$73,$76,$6f ; ciphertext
       .db      $b8,$b5,$25,$c6,$38,$2a,$f2,$77 ; plaintext

       .db      $4f,$63,$9e,$0d,$5a,$5d,$2a,$d7,$e9,$a4       ; key
       .db      $eb,$29,$76,$37,$0d,$22,$ef,$22 ; ciphertext
       .db      $91,$62,$e7,$81,$ff,$68,$38,$53 ; plaintext

       .db      $37,$e0,$06,$25,$6a,$4a,$e6,$d3,$20,$c4       ; key
       .db      $db,$a4,$c0,$ef,$0e,$a0,$98,$c0 ; ciphertext
       .db      $c9,$f2,$3a,$20,$a3,$9d,$ed,$11 ; plaintext

       .db      $e4,$1d,$0b,$d2,$5f,$93,$1b,$a1,$d8,$5c       ; key
       .db      $92,$3d,$ae,$e8,$00,$07,$09,$f9 ; ciphertext
       .db      $5a,$6f,$12,$f3,$2f,$7e,$ef,$df ; plaintext

       .db      $fd,$f6,$5b,$bc,$5f,$e6,$00,$f3,$cd,$68       ; key
       .db      $d5,$77,$1e,$78,$b6,$f1,$fe,$1e ; ciphertext
       .db      $ca,$d5,$41,$4c,$1c,$64,$f1,$94 ; plaintext

       .db      $1c,$26,$9a,$f2,$ff,$16,$6a,$cb,$27,$ef       ; key
       .db      $63,$4f,$7a,$38,$61,$af,$97,$a1 ; ciphertext
       .db      $06,$3a,$58,$a2,$0b,$45,$37,$8f ; plaintext

       .db      $11,$79,$f6,$4a,$cb,$61,$22,$cc,$f6,$49       ; key
       .db      $3a,$80,$3a,$4b,$d0,$e8,$c3,$e6 ; ciphertext
       .db      $08,$fb,$f4,$2b,$43,$13,$34,$7b ; plaintext

       .db      $07,$8c,$87,$26,$5e,$b8,$da,$32,$3e,$90       ; key
       .db      $f4,$fa,$37,$2e,$7e,$14,$41,$a1 ; ciphertext
       .db      $6d,$4e,$d0,$e9,$93,$05,$32,$d1 ; plaintext

       .db      $2f,$ff,$35,$f8,$eb,$77,$4c,$84,$3b,$b0       ; key
       .db      $63,$a9,$19,$7f,$7b,$75,$f5,$3f ; ciphertext
       .db      $40,$b6,$99,$81,$23,$45,$66,$1d ; plaintext

       .db      $09,$f7,$73,$46,$a4,$39,$3c,$e9,$98,$56       ; key
       .db      $e9,$1a,$05,$0a,$74,$81,$b3,$dd ; ciphertext
       .db      $22,$ed,$54,$62,$6a,$51,$e5,$05 ; plaintext

       .db      $5b,$87,$8e,$0b,$22,$a7,$05,$ac,$f8,$fb       ; key
       .db      $6e,$93,$70,$a9,$1b,$99,$48,$78 ; ciphertext
       .db      $0c,$48,$9b,$66,$e2,$da,$53,$1b ; plaintext

       .db      $9d,$72,$c1,$ab,$20,$92,$c1,$b1,$08,$77       ; key
       .db      $5b,$de,$cd,$ed,$96,$d6,$56,$c9 ; ciphertext
       .db      $c6,$4b,$10,$f8,$b1,$91,$bc,$2c ; plaintext

       .db      $72,$86,$5f,$28,$97,$25,$e1,$b5,$55,$02       ; key
       .db      $1a,$56,$80,$e5,$17,$36,$02,$6f ; ciphertext
       .db      $91,$fd,$f7,$23,$6f,$85,$bd,$d6 ; plaintext

       .db      $06,$e3,$c0,$e5,$41,$f4,$aa,$e6,$fe,$93       ; key
       .db      $0e,$7a,$ac,$e4,$21,$bc,$79,$d8 ; ciphertext
       .db      $40,$00,$9f,$8a,$46,$5a,$9f,$eb ; plaintext

       .db      $2e,$a0,$9f,$1c,$c8,$9e,$06,$4f,$09,$bc       ; key
       .db      $a9,$5d,$87,$fa,$d1,$2c,$35,$93 ; ciphertext
       .db      $54,$32,$08,$b0,$5b,$fa,$38,$58 ; plaintext

TestVectorEnd:




;======================================== SKIPJACK =============================================
iSkipJack:
    ldi   ZH,HIGH(FTable*2)
;inverse rule B
    mov   ZL,w2_1
    eor   ZL,key_7
    lpm
    eor   w2,r0
    mov   ZL,w2
    eor   ZL,key_6
    lpm
    eor   w2_1,r0
    mov   ZL,w2_1
    eor   ZL,key_5
    lpm
    eor   w2,r0
    mov   ZL,w2
    eor   ZL,key_4
    lpm
    eor   w2_1,r0
    eor   w3,w2
    eor   w3_1,w2_1
    ldi   ZL,32
    eor   w3,ZL

    mov   ZL,w3_1
    eor   ZL,key_3
    lpm
    eor   w3,r0
    mov   ZL,w3
    eor   ZL,key_2
    lpm
    eor   w3_1,r0
    mov   ZL,w3_1
    eor   ZL,key_1
    lpm
    eor   w3,r0
    mov   ZL,w3
    eor   ZL,key_0
    lpm
    eor   w3_1,r0
    eor   w4,w3
    eor   w4_1,w3_1
    ldi   ZL,31
    eor   w4,ZL

    mov   ZL,w4_1
    eor   ZL,key_9
    lpm
    eor   w4,r0
    mov   ZL,w4
    eor   ZL,key_8
    lpm
    eor   w4_1,r0
    mov   ZL,w4_1
    eor   ZL,key_7
    lpm
    eor   w4,r0
    mov   ZL,w4
    eor   ZL,key_6
    lpm
    eor   w4_1,r0
    eor   w1,w4
    eor   w1_1,w4_1
    ldi   ZL,30
    eor   w1,ZL

    mov   ZL,w1_1
    eor   ZL,key_5
    lpm
    eor   w1,r0
    mov   ZL,w1
    eor   ZL,key_4
    lpm
    eor   w1_1,r0
    mov   ZL,w1_1
    eor   ZL,key_3
    lpm
    eor   w1,r0
    mov   ZL,w1
    eor   ZL,key_2
    lpm
    eor   w1_1,r0
    eor   w2,w1
    eor   w2_1,w1_1
    ldi   ZL,29
    eor   w2,ZL

    mov   ZL,w2_1
    eor   ZL,key_1
    lpm
    eor   w2,r0
    mov   ZL,w2
    eor   ZL,key_0
    lpm
    eor   w2_1,r0
    mov   ZL,w2_1
    eor   ZL,key_9
    lpm
    eor   w2,r0
    mov   ZL,w2
    eor   ZL,key_8
    lpm
    eor   w2_1,r0
    eor   w3,w2
    eor   w3_1,w2_1
    ldi   ZL,28
    eor   w3,ZL

    mov   ZL,w3_1
    eor   ZL,key_7
    lpm
    eor   w3,r0
    mov   ZL,w3
    eor   ZL,key_6
    lpm
    eor   w3_1,r0
    mov   ZL,w3_1
    eor   ZL,key_5
    lpm
    eor   w3,r0
    mov   ZL,w3
    eor   ZL,key_4
    lpm
    eor   w3_1,r0
    eor   w4,w3
    eor   w4_1,w3_1
    ldi   ZL,27
    eor   w4,ZL

    mov   ZL,w4_1
    eor   ZL,key_3
    lpm
    eor   w4,r0
    mov   ZL,w4
    eor   ZL,key_2
    lpm
    eor   w4_1,r0
    mov   ZL,w4_1
    eor   ZL,key_1
    lpm
    eor   w4,r0
    mov   ZL,w4
    eor   ZL,key_0
    lpm
    eor   w4_1,r0
    eor   w1,w4
    eor   w1_1,w4_1
    ldi   ZL,26
    eor   w1,ZL

    mov   ZL,w1_1
    eor   ZL,key_9
    lpm
    eor   w1,r0
    mov   ZL,w1
    eor   ZL,key_8
    lpm
    eor   w1_1,r0
    mov   ZL,w1_1
    eor   ZL,key_7
    lpm
    eor   w1,r0
    mov   ZL,w1
    eor   ZL,key_6
    lpm
    eor   w1_1,r0
    eor   w2,w1
    eor   w2_1,w1_1
    ldi   ZL,25
    eor   w2,ZL

;now switch to inverse A rule
    eor   w1_1,w2_1
    eor   w1,w2
    ldi   ZL,24
    eor   w1,ZL
    mov   ZL,w2_1
    eor   ZL,key_5
    lpm
    eor   w2,r0
    mov   ZL,w2
    eor   ZL,key_4
    lpm
    eor   w2_1,r0
    mov   ZL,w2_1
    eor   ZL,key_3
    lpm
    eor   w2,r0
    mov   ZL,w2
    eor   ZL,key_2
    lpm
    eor   w2_1,r0

    eor   w2_1,w3_1
    eor   w2,w3
    ldi   ZL,23
    eor   w2,ZL
    mov   ZL,w3_1
    eor   ZL,key_1
    lpm
    eor   w3,r0
    mov   ZL,w3
    eor   ZL,key_0
    lpm
    eor   w3_1,r0
    mov   ZL,w3_1
    eor   ZL,key_9
    lpm
    eor   w3,r0
    mov   ZL,w3
    eor   ZL,key_8
    lpm
    eor   w3_1,r0

    eor   w3_1,w4_1
    eor   w3,w4
    ldi   ZL,22
    eor   w3,ZL
    mov   ZL,w4_1
    eor   ZL,key_7
    lpm
    eor   w4,r0
    mov   ZL,w4
    eor   ZL,key_6
    lpm
    eor   w4_1,r0
    mov   ZL,w4_1
    eor   ZL,key_5
    lpm
    eor   w4,r0
    mov   ZL,w4
    eor   ZL,key_4
    lpm
    eor   w4_1,r0

    eor   w4_1,w1_1
    eor   w4,w1
    ldi   ZL,21
    eor   w4,ZL
    mov   ZL,w1_1
    eor   ZL,key_3
    lpm
    eor   w1,r0
    mov   ZL,w1
    eor   ZL,key_2
    lpm
    eor   w1_1,r0
    mov   ZL,w1_1
    eor   ZL,key_1
    lpm
    eor   w1,r0
    mov   ZL,w1
    eor   ZL,key_0
    lpm
    eor   w1_1,r0

    eor   w1_1,w2_1
    eor   w1,w2
    ldi   ZL,20
    eor   w1,ZL
    mov   ZL,w2_1
    eor   ZL,key_9
    lpm
    eor   w2,r0
    mov   ZL,w2
    eor   ZL,key_8
    lpm
    eor   w2_1,r0
    mov   ZL,w2_1
    eor   ZL,key_7
    lpm
    eor   w2,r0
    mov   ZL,w2
    eor   ZL,key_6
    lpm
    eor   w2_1,r0

    eor   w2_1,w3_1
    eor   w2,w3
    ldi   ZL,19
    eor   w2,ZL
    mov   ZL,w3_1
    eor   ZL,key_5
    lpm
    eor   w3,r0
    mov   ZL,w3
    eor   ZL,key_4
    lpm
    eor   w3_1,r0
    mov   ZL,w3_1
    eor   ZL,key_3
    lpm
    eor   w3,r0
    mov   ZL,w3
    eor   ZL,key_2
    lpm
    eor   w3_1,r0

    eor   w3_1,w4_1
    eor   w3,w4
    ldi   ZL,18
    eor   w3,ZL
    mov   ZL,w4_1
    eor   ZL,key_1
    lpm
    eor   w4,r0
    mov   ZL,w4
    eor   ZL,key_0
    lpm
    eor   w4_1,r0
    mov   ZL,w4_1
    eor   ZL,key_9
    lpm
    eor   w4,r0
    mov   ZL,w4
    eor   ZL,key_8
    lpm
    eor   w4_1,r0

    eor   w4_1,w1_1
    eor   w4,w1
    ldi   ZL,17
    eor   w4,ZL
    mov   ZL,w1_1
    eor   ZL,key_7
    lpm
    eor   w1,r0
    mov   ZL,w1
    eor   ZL,key_6
    lpm
    eor   w1_1,r0
    mov   ZL,w1_1
    eor   ZL,key_5
    lpm
    eor   w1,r0
    mov   ZL,w1
    eor   ZL,key_4
    lpm
    eor   w1_1,r0

;inverse rule B 2nd time
    mov   ZL,w2_1
    eor   ZL,key_3
    lpm
    eor   w2,r0
    mov   ZL,w2
    eor   ZL,key_2
    lpm
    eor   w2_1,r0
    mov   ZL,w2_1
    eor   ZL,key_1
    lpm
    eor   w2,r0
    mov   ZL,w2
    eor   ZL,key_0
    lpm
    eor   w2_1,r0
    eor   w3,w2
    eor   w3_1,w2_1
    ldi   ZL,16
    eor   w3,ZL

    mov   ZL,w3_1
    eor   ZL,key_9
    lpm
    eor   w3,r0
    mov   ZL,w3
    eor   ZL,key_8
    lpm
    eor   w3_1,r0
    mov   ZL,w3_1
    eor   ZL,key_7
    lpm
    eor   w3,r0
    mov   ZL,w3
    eor   ZL,key_6
    lpm
    eor   w3_1,r0
    eor   w4,w3
    eor   w4_1,w3_1
    ldi   ZL,15
    eor   w4,ZL

    mov   ZL,w4_1
    eor   ZL,key_5
    lpm
    eor   w4,r0
    mov   ZL,w4
    eor   ZL,key_4
    lpm
    eor   w4_1,r0
    mov   ZL,w4_1
    eor   ZL,key_3
    lpm
    eor   w4,r0
    mov   ZL,w4
    eor   ZL,key_2
    lpm
    eor   w4_1,r0
    eor   w1,w4
    eor   w1_1,w4_1
    ldi   ZL,14
    eor   w1,ZL

    mov   ZL,w1_1
    eor   ZL,key_1
    lpm
    eor   w1,r0
    mov   ZL,w1
    eor   ZL,key_0
    lpm
    eor   w1_1,r0
    mov   ZL,w1_1
    eor   ZL,key_9
    lpm
    eor   w1,r0
    mov   ZL,w1
    eor   ZL,key_8
    lpm
    eor   w1_1,r0
    eor   w2,w1
    eor   w2_1,w1_1
    ldi   ZL,13
    eor   w2,ZL

    mov   ZL,w2_1
    eor   ZL,key_7
    lpm
    eor   w2,r0
    mov   ZL,w2
    eor   ZL,key_6
    lpm
    eor   w2_1,r0
    mov   ZL,w2_1
    eor   ZL,key_5
    lpm
    eor   w2,r0
    mov   ZL,w2
    eor   ZL,key_4
    lpm
    eor   w2_1,r0
    eor   w3,w2
    eor   w3_1,w2_1
    ldi   ZL,12
    eor   w3,ZL

    mov   ZL,w3_1
    eor   ZL,key_3
    lpm
    eor   w3,r0
    mov   ZL,w3
    eor   ZL,key_2
    lpm
    eor   w3_1,r0
    mov   ZL,w3_1
    eor   ZL,key_1
    lpm
    eor   w3,r0
    mov   ZL,w3
    eor   ZL,key_0
    lpm
    eor   w3_1,r0
    eor   w4,w3
    eor   w4_1,w3_1
    ldi   ZL,11
    eor   w4,ZL

    mov   ZL,w4_1
    eor   ZL,key_9
    lpm
    eor   w4,r0
    mov   ZL,w4
    eor   ZL,key_8
    lpm
    eor   w4_1,r0
    mov   ZL,w4_1
    eor   ZL,key_7
    lpm
    eor   w4,r0
    mov   ZL,w4
    eor   ZL,key_6
    lpm
    eor   w4_1,r0
    eor   w1,w4
    eor   w1_1,w4_1
    ldi   ZL,10
    eor   w1,ZL

    mov   ZL,w1_1
    eor   ZL,key_5
    lpm
    eor   w1,r0
    mov   ZL,w1
    eor   ZL,key_4
    lpm
    eor   w1_1,r0
    mov   ZL,w1_1
    eor   ZL,key_3
    lpm
    eor   w1,r0
    mov   ZL,w1
    eor   ZL,key_2
    lpm
    eor   w1_1,r0
    eor   w2,w1
    eor   w2_1,w1_1
    ldi   ZL,9
    eor   w2,ZL

;now switch to inverse A rule for the last round
    eor   w1_1,w2_1
    eor   w1,w2
    ldi   ZL,8
    eor   w1,ZL
    mov   ZL,w2_1
    eor   ZL,key_1
    lpm
    eor   w2,r0
    mov   ZL,w2
    eor   ZL,key_0
    lpm
    eor   w2_1,r0
    mov   ZL,w2_1
    eor   ZL,key_9
    lpm
    eor   w2,r0
    mov   ZL,w2
    eor   ZL,key_8
    lpm
    eor   w2_1,r0

    eor   w2_1,w3_1
    eor   w2,w3
    ldi   ZL,7
    eor   w2,ZL
    mov   ZL,w3_1
    eor   ZL,key_7
    lpm
    eor   w3,r0
    mov   ZL,w3
    eor   ZL,key_6
    lpm
    eor   w3_1,r0
    mov   ZL,w3_1
    eor   ZL,key_5
    lpm
    eor   w3,r0
    mov   ZL,w3
    eor   ZL,key_4
    lpm
    eor   w3_1,r0

    eor   w3_1,w4_1
    eor   w3,w4
    ldi   ZL,6
    eor   w3,ZL
    mov   ZL,w4_1
    eor   ZL,key_3
    lpm
    eor   w4,r0
    mov   ZL,w4
    eor   ZL,key_2
    lpm
    eor   w4_1,r0
    mov   ZL,w4_1
    eor   ZL,key_1
    lpm
    eor   w4,r0
    mov   ZL,w4
    eor   ZL,key_0
    lpm
    eor   w4_1,r0

    eor   w4_1,w1_1
    eor   w4,w1
    ldi   ZL,5
    eor   w4,ZL
    mov   ZL,w1_1
    eor   ZL,key_9
    lpm
    eor   w1,r0
    mov   ZL,w1
    eor   ZL,key_8
    lpm
    eor   w1_1,r0
    mov   ZL,w1_1
    eor   ZL,key_7
    lpm
    eor   w1,r0
    mov   ZL,w1
    eor   ZL,key_6
    lpm
    eor   w1_1,r0

    eor   w1_1,w2_1
    eor   w1,w2
    ldi   ZL,4
    eor   w1,ZL
    mov   ZL,w2_1
    eor   ZL,key_5
    lpm
    eor   w2,r0
    mov   ZL,w2
    eor   ZL,key_4
    lpm
    eor   w2_1,r0
    mov   ZL,w2_1
    eor   ZL,key_3
    lpm
    eor   w2,r0
    mov   ZL,w2
    eor   ZL,key_2
    lpm
    eor   w2_1,r0

    eor   w2_1,w3_1
    eor   w2,w3
    ldi   ZL,3
    eor   w2,ZL
    mov   ZL,w3_1
    eor   ZL,key_1
    lpm
    eor   w3,r0
    mov   ZL,w3
    eor   ZL,key_0
    lpm
    eor   w3_1,r0
    mov   ZL,w3_1
    eor   ZL,key_9
    lpm
    eor   w3,r0
    mov   ZL,w3
    eor   ZL,key_8
    lpm
    eor   w3_1,r0

    eor   w3_1,w4_1
    eor   w3,w4
    ldi   ZL,2
    eor   w3,ZL
    mov   ZL,w4_1
    eor   ZL,key_7
    lpm
    eor   w4,r0
    mov   ZL,w4
    eor   ZL,key_6
    lpm
    eor   w4_1,r0
    mov   ZL,w4_1
    eor   ZL,key_5
    lpm
    eor   w4,r0
    mov   ZL,w4
    eor   ZL,key_4
    lpm
    eor   w4_1,r0

    eor   w4_1,w1_1
    eor   w4,w1
    ldi   ZL,1
    eor   w4,ZL
    mov   ZL,w1_1
    eor   ZL,key_3
    lpm
    eor   w1,r0
    mov   ZL,w1
    eor   ZL,key_2
    lpm
    eor   w1_1,r0
    mov   ZL,w1_1
    eor   ZL,key_1
    lpm
    eor   w1,r0
    mov   ZL,w1
    eor   ZL,key_0
    lpm
    eor   w1_1,r0



    ret

   .org (PC+$FF)&$FF00

FTable:
   .db $a3,$d7,$09,$83,$f8,$48,$f6,$f4
   .db $b3,$21,$15,$78,$99,$b1,$af,$f9
   .db $e7,$2d,$4d,$8a,$ce,$4c,$ca,$2e
   .db $52,$95,$d9,$1e,$4e,$38,$44,$28
   .db $0a,$df,$02,$a0,$17,$f1,$60,$68
   .db $12,$b7,$7a,$c3,$e9,$fa,$3d,$53
   .db $96,$84,$6b,$ba,$f2,$63,$9a,$19
   .db $7c,$ae,$e5,$f5,$f7,$16,$6a,$a2
   .db $39,$b6,$7b,$0f,$c1,$93,$81,$1b
   .db $ee,$b4,$1a,$ea,$d0,$91,$2f,$b8
   .db $55,$b9,$da,$85,$3f,$41,$bf,$e0
   .db $5a,$58,$80,$5f,$66,$0b,$d8,$90
   .db $35,$d5,$c0,$a7,$33,$06,$65,$69
   .db $45,$00,$94,$56,$6d,$98,$9b,$76
   .db $97,$fc,$b2,$c2,$b0,$fe,$db,$20
   .db $e1,$eb,$d6,$e4,$dd,$47,$4a,$1d
   .db $42,$ed,$9e,$6e,$49,$3c,$cd,$43
   .db $27,$d2,$07,$d4,$de,$c7,$67,$18
   .db $89,$cb,$30,$1f,$8d,$c6,$8f,$aa
   .db $c8,$74,$dc,$c9,$5d,$5c,$31,$a4
   .db $70,$88,$61,$2c,$9f,$0d,$2b,$87
   .db $50,$82,$54,$64,$26,$7d,$03,$40
   .db $34,$4b,$1c,$73,$d1,$c4,$fd,$3b
   .db $cc,$fb,$7f,$ab,$e6,$3e,$5b,$a5
   .db $ad,$04,$23,$9c,$14,$51,$22,$f0
   .db $29,$79,$71,$7e,$ff,$8c,$0e,$e2
   .db $0c,$ef,$bc,$72,$75,$6f,$37,$a1
   .db $ec,$d3,$8e,$62,$8b,$86,$10,$e8
   .db $08,$77,$11,$be,$92,$4f,$24,$c5
   .db $32,$36,$9d,$cf,$f3,$a6,$bb,$ac
   .db $5e,$6c,$a9,$13,$57,$25,$b5,$e3
   .db $bd,$a8,$3a,$01,$05,$59,$2a,$46


