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