]> git.cryptolib.org Git - avr-crypto-lib.git/blob - bmw/bmw_224-tinyasm.S
fixing E-Mail-Address & Copyright
[avr-crypto-lib.git] / bmw / bmw_224-tinyasm.S
1 /* bmw_small-tinyasm.S */
2 /*
3     This file is part of the AVR-Crypto-Lib.
4     Copyright (C) 2006-2015 Daniel Otte (bg@nerilex.org)
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 bmw224_nextBlock
519 bmw_small_nextBlock:
520 bmw224_nextBlock:
521 bmw256_nextBlock:
522         push_range  2, 7
523         push_range 28, 29
524         push_range  8, 17
525         stack_alloc_large 32*4, r28, r29
526         ldi r16, 0x4f
527         push r16
528         ldi r16, 0xff
529         push r16
530         push r16
531         ldi r16, 0xfb
532         push r16
533         adiw r28, 1
534 ;       push_range 28, 29 /* push Q */
535 ;       push_range 22, 25 /* push M & H */
536         /* increment counter */
537         movw r26, r24
538         movw r2, r26
539         adiw r26, 63
540         adiw r26,  1
541         rcall load_acc_from_X
542         ldi r19, 1
543         add acc0, r19
544         adc acc1, r1
545         adc acc2, r1
546         adc acc3, r1
547         rcall store_acc_to_dec_X
548         /* call f0 */
549         movw r30, r22
550         movw r26, r24
551 f0:
552         movw h0, r26
553         movw q0, r28
554         movw m0, r30
555         /* xor m into h */
556 ;       ldi r20, 64
557         rcall memxor_64
558         movw r30, m0
559         movw r26, h0
560
561         /* set q to zero */
562         ldi r22, 64
563 10:     st Y+, r1
564         dec r22
565         brne 10b
566         movw r28, q0
567         /* calculate W and store it in Q */
568         ldi r19, 5
569 30:
570         ldi r18, 16
571         /* load initial index */
572
573         /* load values from hacktable */
574         ldi r30, lo8(f0_hacktable-3)
575         ldi r31, hi8(f0_hacktable-3)
576         mov r16, r19
577         lsl r16
578         add r16, r19
579         add r30, r16
580         adc r31, r1
581         lpm r21, Z+
582         lpm r20, Z+
583         lpm r16, Z+
584 40:
585         ;call add_hx_to_w
586 add_hx_to_w:
587         movw r26, h0
588         add r26, r16
589         adc r27, r1
590         rcall load32_from_Y
591         sbiw r28, 4
592         lsl r20
593         rol r21
594         brcs 300f
595         /* addition */
596         rcall add_X_to_32
597         rjmp 500f
598 300: /* substract */
599         rcall load_acc_from_X
600         sub r22, acc0
601         sbc r23, acc1
602         sbc r24, acc2
603         sbc r25, acc3
604
605 500:
606         rcall store32_to_Y
607         subi r16, -4
608         andi r16, 0x0f<<2
609         dec r18
610         brne 40b
611         movw r28, q0
612         dec r19
613         brne 30b
614         movw r26, h0
615         /* xor m into h */
616 ;       ldi r20, 64
617         movw r26, h0
618         movw r30, m0
619         rcall memxor_64
620         sbiw r26, 60
621 ;---
622         clr r17
623         ldi r21, 15
624         mov r8, r21
625 50:
626         rcall load32_from_Y
627         sbiw r28, 4
628         mov r20, r17
629         rcall sn
630         inc r17
631         cpi r17, 5
632         brne 52f
633         clr r17
634 52:
635         rcall add_X_to_32
636         rcall store32_to_Y
637
638         dec r8
639         brne 50b
640 ;---
641         rcall load32_from_Y
642         clr r20
643         rcall sn
644         movw r26, h0
645         rcall add_X_to_32
646         sbiw r26, 4
647         sbiw r28, 4
648         rcall store32_to_Y
649         sbiw r28, 4
650         sbiw r28, 15*4
651         movw r20, h0
652         movw r22, m0
653
654         /* call f1*/
655         movw r2, r28
656 f1:
657         movw r4, r22
658         movw r6, r20
659         movw r26, r2
660         clr r24
661         rcall expand1
662         rcall restore_f1
663         ldi r24, 1
664         rcall expand1
665         ldi r17, 2
666 10: rcall restore_f1
667         mov r24, r17
668         rcall expand2
669         inc r17
670         sbrs r17, 4
671         rjmp 10b
672         rcall restore_f1
673         movw r24, r2
674
675
676         /* call f2 */
677 ;       pop_range 20, 25
678 ;       push_range 20, 25
679 ;       rcall printQ
680 ;       push r20
681 ;       push r21
682 acc2  =  8
683 acc3  =  9
684 acc0  = 14
685 acc1  = 15
686 xl0   =  2
687 xl1   =  3
688 xl2   =  4
689 xl3   =  5
690 xh0   =  6
691 xh1   =  7
692 xh2   = 10
693 xh3   = 11
694 q16_0 = 12
695 q16_1 = 13
696 h0   =  18
697 h1   =  19
698 f2:
699         movw r26, r24
700         /* calc XL & XH */
701         adiw r26, 63
702         adiw r26,  1
703         movw q16_0, r26
704         movw h0, r20
705 ;---
706 ;       push h0
707 ;       push h1
708 ;---
709         movw r28, r22
710         rcall load_acc_from_X
711         ldi r17, 15
712 10:     rcall load32_from_X
713         rcall eor32_to_acc
714         cpi r17, 9
715         brne 15f
716         movw xl0, acc0
717         movw xl2, acc2
718 15:
719         dec r17
720         brne 10b
721         movw xh0, acc0
722         movw xh2, acc2
723 ;--- DBG
724 ;       push_range 22, 25
725 ;       movw r22, xl0
726 ;       movw r24, xl2
727 ;       rcall print32
728 ;       movw r22, xh0
729 ;       movw r24, xh2
730 ;       rcall print32
731 ;       pop_range 22, 25
732 ;--- END DBG
733          /* copy m(Y) into h */
734         movw r26, h0
735         ldi r22, 64
736 10:
737         ld r23, Y+
738         st X+, r23
739         dec r22
740         brne 10b
741 ;--- /* calc first half of h0..h15 */
742         movw r28, q16_0
743         movw r26, h0
744         ldi r30, lo8(f2_1_shift_table)
745         ldi r31, hi8(f2_1_shift_table)
746         ldi r17, 15
747 10:
748 ;---
749         movw r22, xh0
750         movw r24, xh2
751         lpm r20, Z+
752         sbrc r17, 3
753         rcall shiftleft32
754     rcall mov32_to_acc
755 ;---
756         rcall load32_from_Y
757         lpm r20, Z+
758         sbrc r17, 3
759         rcall shiftleft32
760         rcall eor32_to_acc
761 ;---
762         rcall load32_from_X
763         rcall eor32_to_acc
764         rcall store_acc_to_dec_X
765         adiw r26, 4
766 ;---
767         dec r17
768         brpl 10b
769 ;-----
770         sbiw r28, 4*8 /* Y points to q[24] */
771         movw r30, r28
772         sbiw r28, 63
773         sbiw r28, 33 /* Y points to q[0] */
774         movw r26, r28
775         ldi r20, 8*4
776         /* xor q[24..31] into q[0..7] */
777         rcall memxor
778         /* xor q[23] into q[8] */
779         sbiw r30, 9*4
780         ldi r20, 4
781         rcall memxor
782         /* xor q[16..22] into q[9..15] */
783         sbiw r30, 8*4
784         ldi r20, 7*4
785         rcall memxor
786
787         movw r26, h0
788         ldi r17, 15
789         ldi r30, lo8(f2_2_shift_table-8)
790         ldi r31, hi8(f2_2_shift_table-8)
791 10:     movw r22, xl0
792         movw r24, xl2
793         lpm r20, Z+
794         sbrs r17, 3
795         rcall shiftleft32
796         rcall mov32_to_acc
797         rcall load32_from_Y
798         rcall eor32_to_acc
799         rcall add_acc_to_X
800         dec r17
801         brpl 10b
802 ;-----
803         sbiw r26, 8*4 /* X points to h8 */
804         movw r28, r26
805         sbiw r28, 4*4 /* Y points to h4 */
806         ldi r17, 8
807         ldi r18, 9
808 10:
809         rcall load32_from_Y
810         mov r20, r18
811         rcall rotateleft32
812         rcall mov32_to_acc
813         rcall add_acc_to_X
814         inc r18
815         cpi r17, 5
816         brne 20f
817         sbiw r28, 8*4
818 20:     dec r17
819         brne 10b
820
821 exit:
822 ;--- DBG
823 ;       pop r25
824 ;       pop r24
825 ;       ldi r22, 'H'
826 ;       rcall printX
827 ;--- END DBG
828         stack_free_large3 32*4+4
829         pop_range 10, 17
830 pop9:
831         pop_range 8, 9
832 pop28:
833         pop_range 28, 29
834 pop7:
835         pop_range 6, 7
836 pop5:
837         pop_range 2, 5
838         ret
839
840 /******************************************************************************/
841 ctx0 =  2
842 ctx1 =  3
843 blc0 =  4
844 blc1 =  5
845 len0 = 28
846 len1 = 29
847 buf0 =  6
848 buf1 =  7
849
850 load32_from_Z_stub:
851         movw r30, ctx0
852         adiw r30, 60
853         ldd r21, Z+4
854         ldd r22, Z+5
855         ldd r23, Z+6
856         ldd r24, Z+7
857         ret
858
859 /******************************************************************************/
860 /*
861   param ctx:  r24:r25
862   param msg:  r22:r23
863   param len:  r20:r21
864 */
865
866 .global bmw224_lastBlock
867 bmw_small_lastBlock:
868 bmw224_lastBlock:
869 bmw256_lastBlock:
870 /*      while(length_b >= BMW_SMALL_BLOCKSIZE){
871                 bmw_small_nextBlock(ctx, block);
872                 length_b -= BMW_SMALL_BLOCKSIZE;
873                 block = (uint8_t*)block + BMW_SMALL_BLOCKSIZE_B;
874         }
875 */
876         push_range 2, 7
877         push_range 28, 29
878         movw ctx0, r24
879         movw blc0, r22
880         movw len0, r20
881 1:
882         cpi len1, hi8(512)
883         brlo 2f
884         rcall bmw_small_nextBlock_early
885         ldi r24, 64
886         add blc0, r24
887         adc blc1, r1
888         subi len1, hi8(512)
889         rjmp 1b
890 2:
891 /*      struct {
892                 uint8_t  buffer[64];
893                 uint32_t ctr;
894         } pctx;
895 */
896         stack_alloc_large 68
897         adiw r30, 1
898         movw buf0, r30
899 /*      memset(pctx.buffer, 0, 64);
900         memcpy(pctx.buffer, block, (length_b+7)/8);
901         pctx.buffer[length_b>>3] |= 0x80 >> (length_b&0x07);
902 */      movw r24, len0
903         ldi r23, 63
904         movw r26, blc0
905         lsr r25
906         ror r24
907         lsr r24
908         lsr r24
909         breq 301f
910         sub r23, r24
911         /* copy (#r24) bytes to stack buffer */
912 30: ld r20, X+
913         st Z+, r20
914         dec r24
915         brne 30b
916 301: /* calculate the appended byte */
917         clr r20
918         mov r21, len0
919         ldi r24, 0x80
920         andi r21, 0x07
921         breq 305f
922         ld r20, X+
923 303:
924         lsr r24
925         dec r21
926         brne 303b
927 305:
928         or r20, r24
929         st Z+, r20
930         tst r23
931         breq 32f
932 31: st Z+, r1
933         dec r23
934         brne 31b
935 32:
936 /*      if(length_b+1>64*8-64){ ; = 64*7-1 = 447 max(length_b)=511
937                 bmw_small_nextBlock(ctx, pctx.buffer);
938                 memset(pctx.buffer, 0, 64-8);
939                 ctx->counter -= 1;
940         }
941 */
942         tst len1
943         breq 400f
944         cpi len0, 192
945         brlo 400f
946         movw blc0, buf0
947         rcall bmw_small_nextBlock_early
948         movw r26, buf0
949         ldi r20, 64-8
950 350:
951         st X+, r1
952         dec r20
953         brne 350b
954         rcall load32_from_Z_stub
955         subi r21, 1
956         sbc r22, r1
957         sbc r23, r1
958         sbc r24, r1
959         rjmp 410f
960 /*      *((uint64_t*)&(pctx.buffer[64-8])) = (uint64_t)(ctx->counter*512LL)+(uint64_t)length_b;
961         bmw_small_nextBlock(ctx, pctx.buffer);
962 */
963 400:
964         rcall load32_from_Z_stub
965 410:
966         clr r25
967         ldi r20, 1
968         lsl r21
969         rcall rol32
970         mov r20, len0
971         add r21, len1
972         adc r22, r1
973         adc r23, r1
974         adc r24, r1
975         adc r25, r1
976         movw r26, buf0
977         adiw r26, 64-8
978         st X+, r20
979         st X+, r21
980         rcall store32_to_X
981         st X+, r1
982         st X+, r1
983         movw blc0, buf0
984         rcall bmw_small_nextBlock_early
985 /*      memset(pctx.buffer, 0xaa, 64);
986         for(i=0; i<16;++i){
987                 pctx.buffer[i*4] = i+0xa0;
988         }
989 */
990         ldi r22, 0xa0
991         ldi r23, 0xaa
992         ldi r24, 0xaa
993         ldi r25, 0xaa
994         movw r26, buf0
995 500:
996         rcall store32_to_X
997         inc r22
998         sbrs r22, 4
999         rjmp 500b
1000 /*      bmw_small_nextBlock((bmw_small_ctx_t*)&pctx, ctx->h);
1001         memcpy(ctx->h, pctx.buffer, 64);
1002 */
1003     movw r24, buf0
1004     movw r22, ctx0
1005     rcall bmw_small_nextBlock
1006         ldi r18, 64
1007         movw r26, ctx0
1008         movw r30, buf0
1009 600:
1010         ld r20, Z+
1011         st X+, r20
1012         dec r18
1013         brne 600b
1014
1015         stack_free_large 68
1016         rjmp pop28
1017
1018
1019 /*******************************************************************************
1020 * void bmw224_ctx2hash(void *dest, const bmw224_ctx_t *ctx){
1021 *       memcpy(dest, &(ctx->h[9]), 224/8);
1022 * }
1023 *
1024 * param dest:  r24:r25
1025 * param ctx:   r22:r23
1026 */
1027 .global bmw224_ctx2hash
1028 bmw224_ctx2hash:
1029         movw r30, r22
1030         adiw r30, 9*4
1031         ldi r18, 28
1032 1:      movw r26, r24
1033 1:  ld r23, Z+
1034         st X+, r23
1035         dec r18
1036         brne 1b
1037         ret
1038
1039
1040 /*******************************************************************************
1041 * void bmw224(void *dest, const void *msg, uint32_t length_b){
1042 *       bmw_small_ctx_t ctx;
1043 *       bmw224_init(&ctx);
1044 *       while(length_b>=BMW_SMALL_BLOCKSIZE){
1045 *               bmw_small_nextBlock(&ctx, msg);
1046 *               length_b -= BMW_SMALL_BLOCKSIZE;
1047 *               msg = (uint8_t*)msg + BMW_SMALL_BLOCKSIZE_B;
1048 *       }
1049 *       bmw_small_lastBlock(&ctx, msg, length_b);
1050 *       bmw224_ctx2hash(dest, &ctx);
1051 * }
1052 *
1053 * param dest:     r24:r25
1054 * param msg:      r22:r23
1055 * param length_b: r18:r21
1056 */
1057 ctx0 =   2
1058 ctx1 =   3
1059 msg0 =   4
1060 msg1 =   5
1061 len0 =  28
1062 len1 =  29
1063 len2 =   8
1064 len3 =   9
1065 dst0 =   6
1066 dst1 =   7
1067 .global bmw224
1068 bmw224:
1069         push_range 2, 7
1070         push_range 28, 29
1071         push_range 8, 9
1072         stack_alloc_large 64+4
1073         adiw r30, 1
1074 10:     movw ctx0, r30
1075         movw dst0, r24
1076         movw msg0, r22
1077         movw len0, r18
1078         movw len2, r20
1079         movw r24, ctx0
1080         rcall bmw224_init
1081 20:
1082         mov r18, len2
1083         or  r18, len3
1084         breq 50f
1085         rcall bmw_small_nextBlock_early
1086         subi len1, 2
1087         sbc len2, r1
1088         sbc len3, r1
1089         ldi r20, 64
1090         add msg0, r20
1091         adc msg1, r1
1092         rjmp 20b
1093 50:
1094         movw r24, ctx0
1095         movw r22, msg0
1096         movw r20, len0
1097         rcall bmw_small_lastBlock
1098         movw r24, dst0
1099         movw r22, ctx0
1100         rcall bmw224_ctx2hash
1101         stack_free_large 64+4
1102         rjmp pop9
1103
1104 /*******************************************************************************
1105 * void bmw224_init(bmw224_ctx_t *ctx){
1106 *       uint8_t i;
1107 *       ctx->h[0] = 0x00010203;
1108 *       for(i=1; i<16; ++i){
1109 *               ctx->h[i] = ctx->h[i-1]+ 0x04040404;
1110 *       }
1111 *       ctx->counter=0;
1112 * }
1113 *
1114 * param ctx:  r24:r25
1115 */
1116 .global bmw224_init
1117 bmw224_init:
1118         ldi r22, 0x00
1119         ldi r23, 0x40
1120         movw r26, r24
1121         adiw r26, 4
1122 10:
1123         st -X, r22
1124         inc r22
1125         mov r20, r22
1126         andi r20, 0x3
1127         brne 10b
1128         adiw r26, 8
1129 20: cp r22, r23
1130         brne 10b
1131         st -X, r1
1132         st -X, r1
1133         st -X, r1
1134         st -X, r1
1135         ret
1136
1137
1138 /******************************************************************************/
1139
1140 #if DEBUG
1141
1142 printQ:
1143         push_range 20, 25
1144         ldi r16, 4
1145         mov r9, r16
1146         movw r16, r24
1147         ldi r24, lo8(qdbg_str)
1148         ldi r25, hi8(qdbg_str)
1149         call cli_putstr_P
1150         clr r8
1151 10:     ldi r24, lo8(qdbg_str1)
1152         ldi r25, hi8(qdbg_str1)
1153         call cli_putstr_P
1154         mov r24, r8
1155         call cli_hexdump_byte
1156         ldi r24, lo8(qdbg_str2)
1157         ldi r25, hi8(qdbg_str2)
1158         call cli_putstr_P
1159         movw r24, r16
1160         clr r23
1161         ldi r22, 4
1162         call cli_hexdump_rev
1163         add r16, r9
1164         adc r17, r1
1165         inc r8
1166         sbrs r8, 5
1167         rjmp 10b
1168         pop_range 20, 25
1169         ret
1170 qdbg_str:  .asciz "\r\nDBG Q: "
1171 qdbg_str1: .asciz "\r\n Q["
1172 qdbg_str2: .asciz "] =  "
1173
1174
1175 printX:
1176         push_range 6, 9
1177         push_range 16, 27
1178         push_range 30, 31
1179         ldi r16, 4
1180         mov r6, r22
1181         mov r9, r16
1182         movw r16, r24
1183         ldi r24, lo8(Xdbg_str)
1184         ldi r25, hi8(Xdbg_str)
1185         call cli_putstr_P
1186         mov r24, r6
1187         call cli_putc
1188         ldi r24, ':'
1189         call cli_putc
1190         clr r8
1191 10:     ldi r24, lo8(Xdbg_str1)
1192         ldi r25, hi8(Xdbg_str1)
1193         call cli_putstr_P
1194         mov r24, r6
1195         call cli_putc
1196         ldi r24, '['
1197         call cli_putc
1198         mov r24, r8
1199         call cli_hexdump_byte
1200         ldi r24, lo8(Xdbg_str2)
1201         ldi r25, hi8(Xdbg_str2)
1202         call cli_putstr_P
1203         movw r24, r16
1204         clr r23
1205         ldi r22, 4
1206         call cli_hexdump_rev
1207         add r16, r9
1208         adc r17, r1
1209         inc r8
1210         sbrs r8, 4
1211         rjmp 10b
1212         pop_range 30, 31
1213         pop_range 16, 27
1214         pop_range 6, 9
1215         ret
1216 Xdbg_str:  .asciz "\r\nDBG "
1217 Xdbg_str1: .asciz "\r\n "
1218 Xdbg_str2: .asciz "] = "
1219
1220 print32:
1221         push_range 6, 9
1222         push_range 16, 27
1223         push_range 30, 31
1224         movw r6, r22
1225         movw r8, r24
1226         ldi r24, lo8(Xdbg_str)
1227         ldi r25, hi8(Xdbg_str)
1228         call cli_putstr_P
1229         mov r24, r9
1230         call cli_hexdump_byte
1231         mov r24, r8
1232         call cli_hexdump_byte
1233         mov r24, r7
1234         call cli_hexdump_byte
1235         mov r24, r6
1236         call cli_hexdump_byte
1237         pop_range 30, 31
1238         pop_range 16, 27
1239         pop_range 6, 9
1240         ret
1241
1242
1243 print_acc:
1244         push_range 16, 27
1245         push_range 30, 31
1246         ldi r24, lo8(Xdbg_str)
1247         ldi r25, hi8(Xdbg_str)
1248         call cli_putstr_P
1249         mov r24, r9
1250         call cli_hexdump_byte
1251         mov r24, r8
1252         call cli_hexdump_byte
1253         mov r24, r15
1254         call cli_hexdump_byte
1255         mov r24, r14
1256         call cli_hexdump_byte
1257         pop_range 30, 31
1258         pop_range 16, 27
1259         ret
1260
1261 #endif
1262