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