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