]> git.cryptolib.org Git - avr-crypto-lib.git/blob - bmw/bmw_small-tinyasm.S
ad4ee95ad1621378b484c646ed26f94df30af481
[avr-crypto-lib.git] / bmw / bmw_small-tinyasm.S
1 /* bmw_small-tinyasm.S */
2 /*
3     This file is part of the AVR-Crypto-Lib.
4     Copyright (C) 2009  Daniel Otte (daniel.otte@rub.de)
5
6     This program is free software: you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation, either version 3 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 /*
21  * File:        bmw_small-tinyasm.S
22  * Author:      Daniel Otte
23  * Date:        2010-03-28
24  * License:     GPLv3 or later
25  * Description: implementation of BlueMidnightWish
26  *
27  */
28
29 #include "avr-asm-macros.S"
30
31 acc2 =  8
32 acc3 =  9
33 acc0 = 14
34 acc1 = 15
35
36 #define DEBUG 0
37
38 /******************************************************************************/
39 /*
40   param a: r22:r23:r24:r25
41   param s: r20
42 */
43 shiftleft32:
44         tst r20
45         brpl 10f
46         neg r20
47         rjmp shiftright32
48 10:
49         clr r0
50         cpi r20, 8
51         brlo bitrotateleft_1
52         mov r25, r24
53         mov r24, r23
54         mov r23, r22
55         clr r22
56         subi r20, 8
57         rjmp 10b
58
59 /******************************************************************************/
60 /*
61   param a: r22:r23:r24:r25
62   param s: r20
63 */
64 shiftright32:
65         cpi r20, 8
66         brlo bitshiftright
67         mov r22, r23
68         mov r23, r24
69         mov r24, r25
70         clr r25
71         subi r20, 8
72         rjmp shiftright32
73 bitshiftright:
74         tst r20
75         breq 20f
76 10:     lsr r25
77         ror r24
78         ror r23
79         ror r22
80         dec r20
81         brne 10b
82 20: ret
83
84 /******************************************************************************/
85 /*
86   param a: r22:r23:r24:r25
87   param s: r20
88 */
89 rotateleft32:
90         cpi r20, 8
91         brlo bitrotateleft
92         mov r0, r25
93         mov r25, r24
94         mov r24, r23
95         mov r23, r22
96         mov r22, r0
97         subi r20, 8
98         rjmp rotateleft32
99 bitrotateleft:
100     mov r0, r25
101 bitrotateleft_1:
102         tst r20
103         breq 20f
104 10:
105         lsl r0
106 rol32:
107         rol r22
108         rol r23
109         rol r24
110         rol r25
111         dec r20
112         brne 10b
113 20: ret
114
115
116 /******************************************************************************/
117
118 sn_stub:
119         movw r22, r2
120         movw r24, r4
121         lpm r20, Z+
122         rcall rotateleft32
123 eor32_to_acc:
124         eor acc0, r22
125         eor acc1, r23
126         eor acc2, r24
127         eor acc3, r25
128         ret
129
130 s_table:
131 s0:  .byte 1, 3, 4,19
132 s1:  .byte 1, 2, 8,23
133 s2:  .byte 2, 1,12,25
134 s3:  .byte 2, 2,15,29
135 s4:  .byte 1, 0, 0, 0
136 s5:  .byte 2, 0, 0, 0
137
138 h0   = 10
139 h1   = 11
140 m0   = 12
141 m1   = 13
142
143 /*
144   param x: r22:r23:r24:25
145   param s: r20
146 */
147 sn:
148         push_range 2, 5
149         push acc0
150         push acc1
151         push acc2
152         push acc3
153         ldi r30, lo8(s_table)
154         ldi r31, hi8(s_table)
155         lsl r20
156         lsl r20
157         add r30, r20
158         adc r31, r1
159         movw r2, r22
160         movw r4, r24
161         lpm r20, Z+
162         rcall shiftright32
163         rcall mov32_to_acc
164 ;---
165         movw r22, r2
166         movw r24, r4
167         lpm r20, Z+
168         rcall shiftleft32
169         rcall eor32_to_acc
170 ;---
171         rcall sn_stub
172         rcall sn_stub
173
174         movw r22, acc0
175         movw r24, acc2
176         pop acc3
177         pop acc2
178         pop acc1
179         pop acc0
180         rjmp pop5
181
182 /******************************************************************************/
183 /*
184   param dest: r26:r27 (X)
185   param src:  r30:r31 (Z)
186   param len:  r20
187 */
188 memxor_64:
189 ;       tst r20
190 ;       breq memxor_exit
191         ldi r20, 64
192 memxor:
193 10: ld r21, X
194         ld r22, Z+
195         eor r21, r22
196         st X+, r21
197         dec r20
198         brne 10b
199 memxor_exit:
200         ret
201
202 /******************************************************************************/
203 q0 = 2
204 q1 = 3
205 h0 = 4
206 h1 = 5
207 m0 = 6
208 m1 = 7
209
210
211 /******************************************************************************/
212 load32_from_X:
213         ld r22, X+
214         ld r23, X+
215         ld r24, X+
216         ld r25, X+
217         ret
218
219 load32_from_Y:
220         ld r22, Y+
221         ld r23, Y+
222         ld r24, Y+
223         ld r25, Y+
224         ret
225
226 store32_to_Y:
227         st Y+, r22
228         st Y+, r23
229         st Y+, r24
230         st Y+, r25
231         ret
232
233 add_X_to_32:
234         ld r0, X+
235         add r22, r0
236         ld r0, X+
237         adc r23, r0
238         ld r0, X+
239         adc r24, r0
240         ld r0, X+
241         adc r25, r0
242         ret
243
244 store32_to_X:
245         st X+, r22
246         st X+, r23
247         st X+, r24
248         st X+, r25
249         ret
250
251 mov32_to_acc:
252         movw acc0, r22
253         movw acc2, r24
254         ret
255
256 /******************************************************************************/
257 /*
258   param q:  r28:r29 (Y)
259   param h:  r26:r27 (X)
260   param m:  r30:r31 (Z)
261 */
262
263 f2_1_shift_table:
264 ;       .byte 0x2B, 0x64, 0x66, 0x03, 0x51, 0x55, 0x87, 0x55
265 ;       .byte 0x55, 0x87, 0x55, 0x51, 0x03, 0x66, 0x64, 0x2B
266         .byte 5, -5, -7, 8, -5, 5, -1, 5, -3, 0, 6, -6, -4, 6, -11, 2
267 f2_2_shift_table:
268 ;       .byte (2<<1), (7<<1), (4<<1), (3<<1), (4<<1)+1, (6<<1)+1, (6<<1)
269         .byte 8, -6, 6, 4, -3, -4, -7, -2
270 expand2_rot_table:
271         .byte 3,7,13,16,19,23,27
272
273 f0_hacktable:
274         .byte 0x03, 0x11, 5*4
275         .byte 0xDD, 0xB3, 7*4
276         .byte 0x2A, 0x79, 10*4
277         .byte 0x07, 0xAA, 13*4
278         .byte 0x51, 0xC2, 14*4
279
280
281 /*******************************************************************************
282 * uint32_t addelment(uint8_t j, const uint32_t *m, const uint32_t *h){
283 *       uint32_t r;
284 *       r  = pgm_read_dword(k_lut+j);
285 *       r += rotl_addel(((uint32_t*)m)[j&0xf], j+0);
286 *       r += rotl_addel(((uint32_t*)m)[(j+3)&0xf], j+3);
287 *       r -= rotl_addel(((uint32_t*)m)[(j+10)&0xf], j+10);
288 *       r ^= ((uint32_t*)h)[(j+7)&0xf];
289 *       return r;
290 * }
291 * param j: r24
292 * param m: r22:r23
293 * param h: r20:r21
294 */
295 j    = 16
296 acc2 =  8
297 acc3 =  9
298 h0   = 10
299 h1   = 11
300 m0   = 12
301 m1   = 13
302 acc0 = 14
303 acc1 = 15
304
305 load_acc_from_X:
306         ld acc0, X+
307         ld acc1, X+
308         ld acc2, X+
309         ld acc3, X+
310         ret
311
312 add_acc_to_X:
313         ld r0, X
314         add r0, acc0
315         st X+, r0
316         ld r0, X
317         adc r0, acc1
318         st X+, r0
319         ld r0, X
320         adc r0, acc2
321         st X+, r0
322         ld r0, X
323         adc r0, acc3
324         st X+, r0
325         ret
326
327 load_rotate_add_M:
328         mov r20, j
329         andi r20, 0x0f
330         mov r0, r20
331         lsl r0
332         lsl r0
333         movw r26, m0
334         add r26, r0
335         adc r27, r1
336         rcall load32_from_X
337         inc r20
338         rcall rotateleft32
339         brts 10f
340         rjmp add32_to_acc
341 ;       ret
342 10:     sub acc0, r22
343         sbc acc1, r23
344         sbc acc2, r24
345         sbc acc3, r25
346         ret
347
348
349 ;---
350
351 /******************************************************************************/
352 load_sn_add:
353         rcall load32_from_X
354         rcall sn
355 add32_to_acc:
356         add acc0, r22
357         adc acc1, r23
358         adc acc2, r24
359         adc acc3, r25
360         ret
361
362 /*
363   param q: r26:r27
364   param m: r22:r23
365   param h: r20:r21
366   param j: r24
367 */
368
369 expand_intro:
370         push_range 26, 27
371         push r24
372 addelement:
373         mov j, r24
374         movw h0, r20
375         movw m0, r22
376         sbiw r26, 4
377         rcall load_acc_from_X
378         ldi r24, 0x55
379         add acc0, r24
380         adc acc1, r24
381         adc acc2, r24
382         ldi r24, 5
383         adc acc3, r24
384         rcall store_acc_to_dec_X
385         adiw r26, 4
386         clt
387         rcall load_rotate_add_M
388         subi j, -3
389         rcall load_rotate_add_M
390         set
391         subi j, -7
392         rcall load_rotate_add_M
393         lsl j
394         lsl j
395         subi j, -7*4+10*4
396         andi j, 0x3f
397         movw r26, h0
398         add r26, j
399         adc r27, r1
400         rcall load32_from_X
401         rcall eor32_to_acc
402 ;--
403         pop r24
404         pop_range 26, 27
405         lsl r24
406         lsl r24
407         add r26, r24
408         adc r27, r1
409         ret
410 expand1:
411         rcall expand_intro
412         ldi r19, 1
413 10:
414         mov r20, r19
415         andi r20, 3
416         rcall load_sn_add
417         inc r19
418         cpi r19, 17
419         brne 10b
420         rjmp expand2_exit
421
422
423 /******************************************************************************/
424 /*
425   param q: r26:r27
426   param m: r22:r23
427   param h: r20:r21
428   param j: r24
429 */
430
431
432 expand2:
433         rcall expand_intro
434         ldi r19, 14
435         ldi r30, lo8(expand2_rot_table)
436         ldi r31, hi8(expand2_rot_table)
437 10:
438         rcall load32_from_X
439         sbrs r19, 0
440         rjmp 12f
441         lpm r20, Z+
442         rcall rotateleft32
443 12:     rcall add32_to_acc
444         dec r19
445         brne 10b
446         ldi r20, 4
447         rcall load_sn_add
448         ldi r20, 5
449         rcall load_sn_add
450 expand2_exit:
451         adiw r26, 4
452 store_acc_to_dec_X:
453         st -X, acc3
454         st -X, acc2
455         st -X, acc1
456         st -X, acc0
457         ret
458
459 /******************************************************************************/
460 /*
461   param q: r24:r25
462   param m: r22:r23
463   param h: r20:r21
464 */
465 /* for calling expand1/2
466   param q: r26:r27
467   param m: r22:r23
468   param h: r20:r21
469   param j: r24
470 */
471
472 /******************************************************************************/
473 /*
474   param q: r24:r25
475   param m: r22:r23
476   param h: r20:r21
477 */
478
479 /******************************************************************************/
480 /*
481   param ctx:  r24:r25
482   param msg:  r22:r23
483 */
484 /* f0
485   param q:  r28:r29 (Y)
486   param h:  r26:r27 (X)
487   param m:  r30:r31 (Z)
488 */
489 /* f1
490   param q: r24:r25
491   param m: r22:r23
492   param h: r20:r21
493 */
494 /* f2
495   param q: r24:r25
496   param m: r22:r23
497   param h: r20:r21
498 */
499 q0 = 2
500 q1 = 3
501 h0 = 4
502 h1 = 5
503 m0 = 6
504 m1 = 7
505 ctx0 =   2
506 ctx1 =   3
507 msg0 =   4
508 msg1 =   5
509
510 restore_f1:
511         movw r26, r2
512         movw r22, r4
513     movw r20, r6
514         ret
515 bmw_small_nextBlock_early:
516         movw r24, ctx0
517         movw r22, msg0
518 .global bmw_small_nextBlock
519 .global bmw224_nextBlock
520 .global bmw256_nextBlock
521 bmw_small_nextBlock:
522 bmw224_nextBlock:
523 bmw256_nextBlock:
524         push_range  2, 7
525         push_range 28, 29
526         push_range  8, 17
527         stack_alloc_large 32*4, r28, r29
528         ldi r16, 0x4f
529         push r16
530         ldi r16, 0xff
531         push r16
532         push r16
533         ldi r16, 0xfb
534         push r16
535         adiw r28, 1
536 ;       push_range 28, 29 /* push Q */
537 ;       push_range 22, 25 /* push M & H */
538         /* increment counter */
539         movw r26, r24
540         movw r2, r26
541         adiw r26, 63
542         adiw r26,  1
543         rcall load_acc_from_X
544         ldi r19, 1
545         add acc0, r19
546         adc acc1, r1
547         adc acc2, r1
548         adc acc3, r1
549         rcall store_acc_to_dec_X
550         /* call f0 */
551         movw r30, r22
552         movw r26, r24
553 f0:
554         movw h0, r26
555         movw q0, r28
556         movw m0, r30
557         /* xor m into h */
558 ;       ldi r20, 64
559         rcall memxor_64
560         movw r30, m0
561         movw r26, h0
562
563         /* set q to zero */
564         ldi r22, 64
565 10:     st Y+, r1
566         dec r22
567         brne 10b
568         movw r28, q0
569         /* calculate W and store it in Q */
570         ldi r19, 5
571 30:
572         ldi r18, 16
573         /* load initial index */
574
575         /* load values from hacktable */
576         ldi r30, lo8(f0_hacktable-3)
577         ldi r31, hi8(f0_hacktable-3)
578         mov r16, r19
579         lsl r16
580         add r16, r19
581         add r30, r16
582         adc r31, r1
583         lpm r21, Z+
584         lpm r20, Z+
585         lpm r16, Z+
586 40:
587         ;call add_hx_to_w
588 add_hx_to_w:
589         movw r26, h0
590         add r26, r16
591         adc r27, r1
592         rcall load32_from_Y
593         sbiw r28, 4
594         lsl r20
595         rol r21
596         brcs 300f
597         /* addition */
598         rcall add_X_to_32
599         rjmp 500f
600 300: /* substract */
601         rcall load_acc_from_X
602         sub r22, acc0
603         sbc r23, acc1
604         sbc r24, acc2
605         sbc r25, acc3
606
607 500:
608         rcall store32_to_Y
609         subi r16, -4
610         andi r16, 0x0f<<2
611         dec r18
612         brne 40b
613         movw r28, q0
614         dec r19
615         brne 30b
616         movw r26, h0
617         /* xor m into h */
618 ;       ldi r20, 64
619         movw r26, h0
620         movw r30, m0
621         rcall memxor_64
622         sbiw r26, 60
623 ;---
624         clr r17
625         ldi r21, 15
626         mov r8, r21
627 50:
628         rcall load32_from_Y
629         sbiw r28, 4
630         mov r20, r17
631         rcall sn
632         inc r17
633         cpi r17, 5
634         brne 52f
635         clr r17
636 52:
637         rcall add_X_to_32
638         rcall store32_to_Y
639
640         dec r8
641         brne 50b
642 ;---
643         rcall load32_from_Y
644         clr r20
645         rcall sn
646         movw r26, h0
647         rcall add_X_to_32
648         sbiw r26, 4
649         sbiw r28, 4
650         rcall store32_to_Y
651         sbiw r28, 4
652         sbiw r28, 15*4
653         movw r20, h0
654         movw r22, m0
655
656         /* call f1*/
657         movw r2, r28
658 f1:
659         movw r4, r22
660         movw r6, r20
661         movw r26, r2
662         clr r24
663         rcall expand1
664         rcall restore_f1
665         ldi r24, 1
666         rcall expand1
667         ldi r17, 2
668 10: rcall restore_f1
669         mov r24, r17
670         rcall expand2
671         inc r17
672         sbrs r17, 4
673         rjmp 10b
674         rcall restore_f1
675         movw r24, r2
676
677
678         /* call f2 */
679 ;       pop_range 20, 25
680 ;       push_range 20, 25
681 ;       rcall printQ
682 ;       push r20
683 ;       push r21
684 acc2  =  8
685 acc3  =  9
686 acc0  = 14
687 acc1  = 15
688 xl0   =  2
689 xl1   =  3
690 xl2   =  4
691 xl3   =  5
692 xh0   =  6
693 xh1   =  7
694 xh2   = 10
695 xh3   = 11
696 q16_0 = 12
697 q16_1 = 13
698 h0   =  18
699 h1   =  19
700 f2:
701         movw r26, r24
702         /* calc XL & XH */
703         adiw r26, 63
704         adiw r26,  1
705         movw q16_0, r26
706         movw h0, r20
707 ;---
708 ;       push h0
709 ;       push h1
710 ;---
711         movw r28, r22
712         rcall load_acc_from_X
713         ldi r17, 15
714 10:     rcall load32_from_X
715         rcall eor32_to_acc
716         cpi r17, 9
717         brne 15f
718         movw xl0, acc0
719         movw xl2, acc2
720 15:
721         dec r17
722         brne 10b
723         movw xh0, acc0
724         movw xh2, acc2
725 ;--- DBG
726 ;       push_range 22, 25
727 ;       movw r22, xl0
728 ;       movw r24, xl2
729 ;       rcall print32
730 ;       movw r22, xh0
731 ;       movw r24, xh2
732 ;       rcall print32
733 ;       pop_range 22, 25
734 ;--- END DBG
735          /* copy m(Y) into h */
736         movw r26, h0
737         ldi r22, 64
738 10:
739         ld r23, Y+
740         st X+, r23
741         dec r22
742         brne 10b
743 ;--- /* calc first half of h0..h15 */
744         movw r28, q16_0
745         movw r26, h0
746         ldi r30, lo8(f2_1_shift_table)
747         ldi r31, hi8(f2_1_shift_table)
748         ldi r17, 15
749 10:
750 ;---
751         movw r22, xh0
752         movw r24, xh2
753         lpm r20, Z+
754         sbrc r17, 3
755         rcall shiftleft32
756     rcall mov32_to_acc
757 ;---
758         rcall load32_from_Y
759         lpm r20, Z+
760         sbrc r17, 3
761         rcall shiftleft32
762         rcall eor32_to_acc
763 ;---
764         rcall load32_from_X
765         rcall eor32_to_acc
766         rcall store_acc_to_dec_X
767         adiw r26, 4
768 ;---
769         dec r17
770         brpl 10b
771 ;-----
772         sbiw r28, 4*8 /* Y points to q[24] */
773         movw r30, r28
774         sbiw r28, 63
775         sbiw r28, 33 /* Y points to q[0] */
776         movw r26, r28
777         ldi r20, 8*4
778         /* xor q[24..31] into q[0..7] */
779         rcall memxor
780         /* xor q[23] into q[8] */
781         sbiw r30, 9*4
782         ldi r20, 4
783         rcall memxor
784         /* xor q[16..22] into q[9..15] */
785         sbiw r30, 8*4
786         ldi r20, 7*4
787         rcall memxor
788
789         movw r26, h0
790         ldi r17, 15
791         ldi r30, lo8(f2_2_shift_table-8)
792         ldi r31, hi8(f2_2_shift_table-8)
793 10:     movw r22, xl0
794         movw r24, xl2
795         lpm r20, Z+
796         sbrs r17, 3
797         rcall shiftleft32
798         rcall mov32_to_acc
799         rcall load32_from_Y
800         rcall eor32_to_acc
801         rcall add_acc_to_X
802         dec r17
803         brpl 10b
804 ;-----
805         sbiw r26, 8*4 /* X points to h8 */
806         movw r28, r26
807         sbiw r28, 4*4 /* Y points to h4 */
808         ldi r17, 8
809         ldi r18, 9
810 10:
811         rcall load32_from_Y
812         mov r20, r18
813         rcall rotateleft32
814         rcall mov32_to_acc
815         rcall add_acc_to_X
816         inc r18
817         cpi r17, 5
818         brne 20f
819         sbiw r28, 8*4
820 20:     dec r17
821         brne 10b
822
823 exit:
824 ;--- DBG
825 ;       pop r25
826 ;       pop r24
827 ;       ldi r22, 'H'
828 ;       rcall printX
829 ;--- END DBG
830         stack_free_large3 32*4+4
831         pop_range 10, 17
832 pop9:
833         pop_range 8, 9
834 pop28:
835         pop_range 28, 29
836 pop7:
837         pop_range 6, 7
838 pop5:
839         pop_range 2, 5
840         ret
841
842 /******************************************************************************/
843 ctx0 =  2
844 ctx1 =  3
845 blc0 =  4
846 blc1 =  5
847 len0 = 28
848 len1 = 29
849 buf0 =  6
850 buf1 =  7
851
852 load32_from_Z_stub:
853         movw r30, ctx0
854         adiw r30, 60
855         ldd r21, Z+4
856         ldd r22, Z+5
857         ldd r23, Z+6
858         ldd r24, Z+7
859         ret
860
861 /******************************************************************************/
862 /*
863   param ctx:  r24:r25
864   param msg:  r22:r23
865   param len:  r20:r21
866 */
867
868 .global bmw_small_lastBlock
869 .global bmw224_lastBlock
870 .global bmw256_lastBlock
871 bmw_small_lastBlock:
872 bmw224_lastBlock:
873 bmw256_lastBlock:
874 /*      while(length_b >= BMW_SMALL_BLOCKSIZE){
875                 bmw_small_nextBlock(ctx, block);
876                 length_b -= BMW_SMALL_BLOCKSIZE;
877                 block = (uint8_t*)block + BMW_SMALL_BLOCKSIZE_B;
878         }
879 */
880         push_range 2, 7
881         push_range 28, 29
882         movw ctx0, r24
883         movw blc0, r22
884         movw len0, r20
885 1:
886         cpi len1, hi8(512)
887         brlo 2f
888         rcall bmw_small_nextBlock_early
889         ldi r24, 64
890         add blc0, r24
891         adc blc1, r1
892         subi len1, hi8(512)
893         rjmp 1b
894 2:
895 /*      struct {
896                 uint8_t  buffer[64];
897                 uint32_t ctr;
898         } pctx;
899 */
900         stack_alloc_large 68
901         adiw r30, 1
902         movw buf0, r30
903 /*      memset(pctx.buffer, 0, 64);
904         memcpy(pctx.buffer, block, (length_b+7)/8);
905         pctx.buffer[length_b>>3] |= 0x80 >> (length_b&0x07);
906 */      movw r24, len0
907         ldi r23, 63
908         movw r26, blc0
909         lsr r25
910         ror r24
911         lsr r24
912         lsr r24
913         breq 301f
914         sub r23, r24
915         /* copy (#r24) bytes to stack buffer */
916 30: ld r20, X+
917         st Z+, r20
918         dec r24
919         brne 30b
920 301: /* calculate the appended byte */
921         clr r20
922         mov r21, len0
923         ldi r24, 0x80
924         andi r21, 0x07
925         breq 305f
926         ld r20, X+
927 303:
928         lsr r24
929         dec r21
930         brne 303b
931 305:
932         or r20, r24
933         st Z+, r20
934         tst r23
935         breq 32f
936 31: st Z+, r1
937         dec r23
938         brne 31b
939 32:
940 /*      if(length_b+1>64*8-64){ ; = 64*7-1 = 447 max(length_b)=511
941                 bmw_small_nextBlock(ctx, pctx.buffer);
942                 memset(pctx.buffer, 0, 64-8);
943                 ctx->counter -= 1;
944         }
945 */
946         tst len1
947         breq 400f
948         cpi len0, 192
949         brlo 400f
950         movw blc0, buf0
951         rcall bmw_small_nextBlock_early
952         movw r26, buf0
953         ldi r20, 64-8
954 350:
955         st X+, r1
956         dec r20
957         brne 350b
958         rcall load32_from_Z_stub
959         subi r21, 1
960         sbc r22, r1
961         sbc r23, r1
962         sbc r24, r1
963         rjmp 410f
964 /*      *((uint64_t*)&(pctx.buffer[64-8])) = (uint64_t)(ctx->counter*512LL)+(uint64_t)length_b;
965         bmw_small_nextBlock(ctx, pctx.buffer);
966 */
967 400:
968         rcall load32_from_Z_stub
969 410:
970         clr r25
971         ldi r20, 1
972         lsl r21
973         rcall rol32
974         mov r20, len0
975         add r21, len1
976         adc r22, r1
977         adc r23, r1
978         adc r24, r1
979         adc r25, r1
980         movw r26, buf0
981         adiw r26, 64-8
982         st X+, r20
983         st X+, r21
984         rcall store32_to_X
985         st X+, r1
986         st X+, r1
987         movw blc0, buf0
988         rcall bmw_small_nextBlock_early
989 /*      memset(pctx.buffer, 0xaa, 64);
990         for(i=0; i<16;++i){
991                 pctx.buffer[i*4] = i+0xa0;
992         }
993 */
994         ldi r22, 0xa0
995         ldi r23, 0xaa
996         ldi r24, 0xaa
997         ldi r25, 0xaa
998         movw r26, buf0
999 500:
1000         rcall store32_to_X
1001         inc r22
1002         sbrs r22, 4
1003         rjmp 500b
1004 /*      bmw_small_nextBlock((bmw_small_ctx_t*)&pctx, ctx->h);
1005         memcpy(ctx->h, pctx.buffer, 64);
1006 */
1007     movw r24, buf0
1008     movw r22, ctx0
1009     rcall bmw_small_nextBlock
1010         ldi r18, 64
1011         movw r26, ctx0
1012         movw r30, buf0
1013 600:
1014         ld r20, Z+
1015         st X+, r20
1016         dec r18
1017         brne 600b
1018
1019         stack_free_large 68
1020         rjmp pop28
1021
1022
1023 /*******************************************************************************
1024 * void bmw224_ctx2hash(void *dest, const bmw224_ctx_t *ctx){
1025 *       memcpy(dest, &(ctx->h[9]), 224/8);
1026 * }
1027 *
1028 * param dest:  r24:r25
1029 * param ctx:   r22:r23
1030 */
1031 .global bmw224_ctx2hash
1032 bmw224_ctx2hash:
1033         movw r30, r22
1034         adiw r30, 9*4
1035         ldi r18, 28
1036         rjmp 1f
1037
1038 /*******************************************************************************
1039 * void bmw256_ctx2hash(void *dest, const bmw256_ctx_t *ctx){
1040 *       memcpy(dest, &(ctx->h[8]), 256/8);
1041 * }
1042 *
1043 * param dest:  r24:r25
1044 * param ctx:   r22:r23
1045 */
1046 .global bmw256_ctx2hash
1047 bmw256_ctx2hash:
1048         movw r30, r22
1049         adiw r30, 8*4
1050         ldi r18, 32
1051 1:      movw r26, r24
1052 1:  ld r23, Z+
1053         st X+, r23
1054         dec r18
1055         brne 1b
1056         ret
1057
1058 /*******************************************************************************
1059 * void bmw256(void *dest, const void *msg, uint32_t length_b){
1060 *       bmw_small_ctx_t ctx;
1061 *       bmw256_init(&ctx);
1062 *       while(length_b>=BMW_SMALL_BLOCKSIZE){
1063 *               bmw_small_nextBlock(&ctx, msg);
1064 *               length_b -= BMW_SMALL_BLOCKSIZE;
1065 *               msg = (uint8_t*)msg + BMW_SMALL_BLOCKSIZE_B;
1066 *       }
1067 *       bmw_small_lastBlock(&ctx, msg, length_b);
1068 *       bmw256_ctx2hash(dest, &ctx);
1069 * }
1070 *
1071 * param dest:     r24:r25
1072 * param msg:      r22:r23
1073 * param length_b: r18:r21
1074 */
1075 ctx0 =   2
1076 ctx1 =   3
1077 msg0 =   4
1078 msg1 =   5
1079 len0 =   6
1080 len1 =   7
1081 len2 =   8
1082 len3 =   9
1083 dst0 =  10
1084 dst1 =  11
1085 .global bmw256
1086 bmw256:
1087         set
1088         rjmp bmw_small_all
1089
1090
1091 /*******************************************************************************
1092 * void bmw224(void *dest, const void *msg, uint32_t length_b){
1093 *       bmw_small_ctx_t ctx;
1094 *       bmw224_init(&ctx);
1095 *       while(length_b>=BMW_SMALL_BLOCKSIZE){
1096 *               bmw_small_nextBlock(&ctx, msg);
1097 *               length_b -= BMW_SMALL_BLOCKSIZE;
1098 *               msg = (uint8_t*)msg + BMW_SMALL_BLOCKSIZE_B;
1099 *       }
1100 *       bmw_small_lastBlock(&ctx, msg, length_b);
1101 *       bmw224_ctx2hash(dest, &ctx);
1102 * }
1103 *
1104 * param dest:     r24:r25
1105 * param msg:      r22:r23
1106 * param length_b: r18:r21
1107 */
1108 ctx0 =   2
1109 ctx1 =   3
1110 msg0 =   4
1111 msg1 =   5
1112 len0 =  28
1113 len1 =  29
1114 len2 =   8
1115 len3 =   9
1116 dst0 =   6
1117 dst1 =   7
1118 .global bmw224
1119 bmw224:
1120         clt
1121
1122
1123 bmw_small_all:
1124         push_range 2, 7
1125         push_range 28, 29
1126         push_range 8, 9
1127         push r16
1128         stack_alloc_large 64+4
1129         adiw r30, 1
1130         clr r16
1131         brtc 10f
1132         inc r16
1133 10:     movw ctx0, r30
1134         movw dst0, r24
1135         movw msg0, r22
1136         movw len0, r18
1137         movw len2, r20
1138         movw r24, ctx0
1139         ldi r30, pm_lo8(init_lut)
1140         ldi r31, pm_hi8(init_lut)
1141         add r30, r16
1142         adc r31, r1
1143         icall
1144 20:
1145         mov r18, len2
1146         or  r18, len3
1147         breq 50f
1148         rcall bmw_small_nextBlock_early
1149         subi len1, 2
1150         sbc len2, r1
1151         sbc len3, r1
1152         ldi r20, 64
1153         add msg0, r20
1154         adc msg1, r1
1155         rjmp 20b
1156 50:
1157         movw r24, ctx0
1158         movw r22, msg0
1159         movw r20, len0
1160         rcall bmw_small_lastBlock
1161         movw r24, dst0
1162         movw r22, ctx0
1163         ldi r30, pm_lo8(c2h_lut)
1164         ldi r31, pm_hi8(c2h_lut)
1165         add r30, r16
1166         adc r31, r1
1167         icall
1168         stack_free_large 64+4
1169         pop r16
1170         rjmp pop9
1171
1172 init_lut:
1173         rjmp bmw224_init
1174         rjmp bmw256_init
1175 c2h_lut:
1176         rjmp bmw224_ctx2hash
1177         rjmp bmw256_ctx2hash
1178
1179 /*******************************************************************************
1180 * void bmw224_init(bmw224_ctx_t *ctx){
1181 *       uint8_t i;
1182 *       ctx->h[0] = 0x00010203;
1183 *       for(i=1; i<16; ++i){
1184 *               ctx->h[i] = ctx->h[i-1]+ 0x04040404;
1185 *       }
1186 *       ctx->counter=0;
1187 * }
1188 *
1189 * param ctx:  r24:r25
1190 */
1191 .global bmw224_init
1192 bmw224_init:
1193         ldi r22, 0x00
1194         ldi r23, 0x40
1195 bmw_small_init:
1196         movw r26, r24
1197         adiw r26, 4
1198 10:
1199         st -X, r22
1200         inc r22
1201         mov r20, r22
1202         andi r20, 0x3
1203         brne 10b
1204         adiw r26, 8
1205 20: cp r22, r23
1206         brne 10b
1207         st -X, r1
1208         st -X, r1
1209         st -X, r1
1210         st -X, r1
1211         ret
1212
1213 .global bmw256_init
1214 bmw256_init:
1215         ldi r22, 0x40
1216         ldi r23, 0x80
1217         rjmp bmw_small_init
1218
1219
1220 /******************************************************************************/
1221
1222 #if DEBUG
1223
1224 printQ:
1225         push_range 20, 25
1226         ldi r16, 4
1227         mov r9, r16
1228         movw r16, r24
1229         ldi r24, lo8(qdbg_str)
1230         ldi r25, hi8(qdbg_str)
1231         call cli_putstr_P
1232         clr r8
1233 10:     ldi r24, lo8(qdbg_str1)
1234         ldi r25, hi8(qdbg_str1)
1235         call cli_putstr_P
1236         mov r24, r8
1237         call cli_hexdump_byte
1238         ldi r24, lo8(qdbg_str2)
1239         ldi r25, hi8(qdbg_str2)
1240         call cli_putstr_P
1241         movw r24, r16
1242         clr r23
1243         ldi r22, 4
1244         call cli_hexdump_rev
1245         add r16, r9
1246         adc r17, r1
1247         inc r8
1248         sbrs r8, 5
1249         rjmp 10b
1250         pop_range 20, 25
1251         ret
1252 qdbg_str:  .asciz "\r\nDBG Q: "
1253 qdbg_str1: .asciz "\r\n Q["
1254 qdbg_str2: .asciz "] =  "
1255
1256
1257 printX:
1258         push_range 6, 9
1259         push_range 16, 27
1260         push_range 30, 31
1261         ldi r16, 4
1262         mov r6, r22
1263         mov r9, r16
1264         movw r16, r24
1265         ldi r24, lo8(Xdbg_str)
1266         ldi r25, hi8(Xdbg_str)
1267         call cli_putstr_P
1268         mov r24, r6
1269         call cli_putc
1270         ldi r24, ':'
1271         call cli_putc
1272         clr r8
1273 10:     ldi r24, lo8(Xdbg_str1)
1274         ldi r25, hi8(Xdbg_str1)
1275         call cli_putstr_P
1276         mov r24, r6
1277         call cli_putc
1278         ldi r24, '['
1279         call cli_putc
1280         mov r24, r8
1281         call cli_hexdump_byte
1282         ldi r24, lo8(Xdbg_str2)
1283         ldi r25, hi8(Xdbg_str2)
1284         call cli_putstr_P
1285         movw r24, r16
1286         clr r23
1287         ldi r22, 4
1288         call cli_hexdump_rev
1289         add r16, r9
1290         adc r17, r1
1291         inc r8
1292         sbrs r8, 4
1293         rjmp 10b
1294         pop_range 30, 31
1295         pop_range 16, 27
1296         pop_range 6, 9
1297         ret
1298 Xdbg_str:  .asciz "\r\nDBG "
1299 Xdbg_str1: .asciz "\r\n "
1300 Xdbg_str2: .asciz "] = "
1301
1302 print32:
1303         push_range 6, 9
1304         push_range 16, 27
1305         push_range 30, 31
1306         movw r6, r22
1307         movw r8, r24
1308         ldi r24, lo8(Xdbg_str)
1309         ldi r25, hi8(Xdbg_str)
1310         call cli_putstr_P
1311         mov r24, r9
1312         call cli_hexdump_byte
1313         mov r24, r8
1314         call cli_hexdump_byte
1315         mov r24, r7
1316         call cli_hexdump_byte
1317         mov r24, r6
1318         call cli_hexdump_byte
1319         pop_range 30, 31
1320         pop_range 16, 27
1321         pop_range 6, 9
1322         ret
1323
1324
1325 print_acc:
1326         push_range 16, 27
1327         push_range 30, 31
1328         ldi r24, lo8(Xdbg_str)
1329         ldi r25, hi8(Xdbg_str)
1330         call cli_putstr_P
1331         mov r24, r9
1332         call cli_hexdump_byte
1333         mov r24, r8
1334         call cli_hexdump_byte
1335         mov r24, r15
1336         call cli_hexdump_byte
1337         mov r24, r14
1338         call cli_hexdump_byte
1339         pop_range 30, 31
1340         pop_range 16, 27
1341         ret
1342
1343 #endif
1344