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