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