]> git.cryptolib.org Git - avr-crypto-lib.git/blob - bmw/bmw_small-asm.S
fixing E-Mail-Address & Copyright
[avr-crypto-lib.git] / bmw / bmw_small-asm.S
1 /* bmw_small-asm.S */
2 /*
3     This file is part of the AVR-Crypto-Lib.
4     Copyright (C) 2006-2015 Daniel Otte (bg@nerilex.org)
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-asm.S
22  * Author:      Daniel Otte
23  * Date:        2009-11-13
24  * License:     GPLv3 or later
25  * Description: implementation of BlueMidnightWish
26  *
27  */
28
29 #include "avr-asm-macros.S"
30
31 shiftcodetable:
32 ;       .byte 0x00 ;  0
33 shiftcodetable_1:
34         .byte 0x01 ;  1
35         .byte 0x02 ;  2
36         .byte 0x03 ;  3
37         .byte 0x04 ;  4
38         .byte 0x1B ;  5
39         .byte 0x1A ;  6
40         .byte 0x19 ;  7
41         .byte 0x10 ;  8
42 shiftcodetable_9:
43         .byte 0x11 ;  9
44         .byte 0x12 ; 10
45         .byte 0x13 ; 11
46         .byte 0x2C ; 12
47         .byte 0x2B ; 13
48         .byte 0x2A ; 14
49         .byte 0x29 ; 15
50         .byte 0x20 ; 16
51 ;       .byte 0x21 ; 17 unused but necesseray for padding
52
53
54
55 /*******************************************************************************
56  * shiftl32
57  *   value: r25:r22
58  *   shift: r20
59  */
60 shiftl32:
61 1:
62 ;       clc
63         lsl r22
64         rol r23
65         rol r24
66         rol r25
67         dec r20
68         brne 1b
69         ret
70
71 /*******************************************************************************
72  * shiftr32
73  *   value: r25:r22
74  *   shift: r20
75  */
76 shiftr32:
77 1:
78 ;       clc
79         lsr r25
80         ror r24
81         ror r23
82         ror r22
83         dec r20
84         brne 1b
85         ret
86
87 /*******************************************************************************
88  * rotl32
89  *   value: r25:r22
90  *   shift: r20
91  */
92 rotl32:
93         mov r21, r25
94 1:
95         lsl r21
96         rol r22
97         rol r23
98         rol r24
99         rol r25
100         dec r20
101         brne 1b
102         ret
103
104 /*******************************************************************************
105  * rotr32
106  *   value: r25:r22
107  *   shift: r20
108  */
109 rotr32:
110         mov r21, r22
111 1:
112         lsr r21
113         ror r25
114         ror r24
115         ror r23
116         ror r22
117         dec r20
118         brne 1b
119 some_ret:
120         ret
121
122 /*******************************************************************************
123  * rotl32p9
124  *   value: r25:r22
125  *   shift: r20
126  */
127 rotl32p9:
128         push_range 30, 31
129         ldi r30, lo8(shiftcodetable_9)
130         ldi r31, hi8(shiftcodetable_9)
131         add r30, r20
132         adc r31, r1
133         lpm r20, Z
134         pop_range 30, 31
135         sbrs r20, 4
136         rjmp 2f
137         mov r0, r25
138         mov r25, r24
139         mov r24, r23
140         mov r23, r22
141         mov r22, r0
142 2:      sbrs r20, 5
143         rjmp 3f
144         movw r0, r24
145         movw r24, r22
146         movw r22, r0
147         clr r1
148 3:  bst r20, 3
149         andi r20, 0x07
150         breq some_ret
151         brts rotr32
152         rjmp rotl32
153
154
155 /*******************************************************************************
156 * uint32_t rotl_addel(uint32_t x, uint8_t v){
157 *       uint32_t r;
158 *       r =  ROTL32(x, (v&0xf)+1);
159 *       return r;
160 * }
161 * param x: r25:r22
162 * param v: r20
163 */
164 .global rotl_addel
165 rotl_addel:
166         andi r20, 0x0f
167         ldi r30, lo8(shiftcodetable_1)
168         ldi r31, hi8(shiftcodetable_1)
169         add r30, r20
170         adc r31, r1
171         lpm r20, Z
172         sbrs r20, 4
173         rjmp 1f
174         mov r21, r25
175         mov r25, r24
176         mov r24, r23
177         mov r23, r22
178         mov r22, r21
179 1:  sbrs r20, 5
180         rjmp 2f
181         movw r30, r24
182         movw r24, r22
183         movw r22, r30
184 2:  bst  r20, 3
185         andi r20, 0x07
186         breq some_ret
187 3:
188         brts rotr32; 4f
189         rjmp rotl32
190 ;4:     rjmp rotr32
191
192 /******************************************************************************/
193
194 preg0 = 22 /* preg for processing register */
195 preg1 = 23
196 preg2 = 24
197 preg3 = 25
198 breg0 = 26 /* breg for backup register */
199 breg1 = 27
200 breg2 = 18
201 breg3 = 19
202 areg0 =  0 /* areg for accumulator register */
203 areg1 =  1
204 areg2 = 30
205 areg3 = 31
206
207 /*******************************************************************************
208 * uint32_t bmw_small_s0(uint32_t x){
209 *       uint32_t r;
210 *       r =   SHR32(x, 1)
211 *               ^ SHL32(x, 3)
212 *               ^ ROTL32(x, 4)
213 *               ^ ROTR32(x, 13);
214 *       return r;
215 * }
216 */
217 .global bmw_small_s0
218 bmw_small_s0:
219         movw breg0, preg0
220         movw breg2, preg2
221         ldi r20, 1
222         rcall shiftr32
223         movw areg2, preg2
224         movw areg0, preg0
225         movw preg2, breg2
226         movw preg0, breg0
227         ldi r20, 3
228         rcall shiftl32
229         eor areg0, preg0
230         eor areg1, preg1
231         eor areg2, preg2
232         eor areg3, preg3
233         movw preg2, breg2
234         movw preg0, breg0
235         ldi r20, 4
236         rcall rotl32
237         eor areg0, preg0
238         eor areg1, preg1
239         eor areg2, preg2
240         eor areg3, preg3
241         /* now the trick, we simply can rotate the old value to the right by 17 */
242         movw breg0, preg0 /* first rotate by 16 */
243         movw preg0, preg2
244         movw preg2, breg0
245 outro_1:
246         ldi r20, 1
247         rcall rotr32
248 outro_2:
249         eor preg0, areg0
250         eor preg1, areg1
251         eor preg2, areg2
252         eor preg3, areg3
253         clr r1
254         ret
255
256 /*******************************************************************************
257 * uint32_t bmw_small_s1(uint32_t x){
258 *       uint32_t r;
259 *       r =   SHR32(x, 1)
260 *               ^ SHL32(x, 2)
261 *               ^ ROTL32(x, 8)
262 *               ^ ROTR32(x, 9);
263 *       return r;
264 * }
265 */
266 .global bmw_small_s1
267 bmw_small_s1:
268         movw breg0, preg0
269         movw breg2, preg2
270         ldi r20, 1
271         rcall shiftr32
272         movw areg2, preg2
273         movw areg0, preg0
274         movw preg2, breg2
275         movw preg0, breg0
276         ldi r20, 2
277         rcall shiftl32
278         eor areg0, preg0
279         eor areg1, preg1
280         eor areg2, preg2
281         eor areg3, preg3
282         eor areg0, breg3
283         eor areg1, breg0
284         eor areg2, breg1
285         eor areg3, breg2
286         mov preg0, breg1
287         mov preg1, breg2
288         mov preg2, breg3
289         mov preg3, breg0
290         rjmp outro_1
291
292 /*******************************************************************************
293 * uint32_t bmw_small_s2(uint32_t x){
294 *       uint32_t r;
295 *       r =   SHR32(x, 2)
296 *               ^ SHL32(x, 1)
297 *               ^ ROTL32(x, 12)
298 *               ^ ROTR32(x, 7);
299 *       return r;
300 * }
301 */
302 .global bmw_small_s2
303 bmw_small_s2:
304         movw breg0, preg0
305         movw breg2, preg2
306         ldi r20, 2
307         rcall shiftr32
308         movw areg2, preg2
309         movw areg0, preg0
310         movw preg2, breg2
311         movw preg0, breg0
312         ldi r20, 1
313         rcall shiftl32
314         eor areg0, preg0
315         eor areg1, preg1
316         eor areg2, preg2
317         eor areg3, preg3
318         movw preg0, breg2
319         movw preg2, breg0
320         ldi r20, 4
321         rcall rotr32
322         eor areg0, preg0
323         eor areg1, preg1
324         eor areg2, preg2
325         eor areg3, preg3
326         mov preg0, breg1
327         mov preg1, breg2
328         mov preg2, breg3
329         mov preg3, breg0
330         ldi r20, 1
331         rcall rotl32
332         rjmp outro_2
333
334 /*******************************************************************************
335 * uint32_t bmw_small_s3(uint32_t x){
336 *       uint32_t r;
337 *       r =   SHR32(x, 2)
338 *               ^ SHL32(x, 2)
339 *               ^ ROTL32(x, 15)
340 *               ^ ROTR32(x, 3);
341 *       return r;
342 * }
343 */
344 .global bmw_small_s3
345 bmw_small_s3:
346         movw breg0, preg0
347         movw breg2, preg2
348         ldi r20, 2
349         rcall shiftr32
350         movw areg2, preg2
351         movw areg0, preg0
352         movw preg2, breg2
353         movw preg0, breg0
354         ldi r20, 2
355         rcall shiftl32
356         eor areg0, preg0
357         eor areg1, preg1
358         eor areg2, preg2
359         eor areg3, preg3
360         movw preg0, breg2
361         movw preg2, breg0
362         ldi r20, 1
363         rcall rotr32
364         eor areg0, preg0
365         eor areg1, preg1
366         eor areg2, preg2
367         eor areg3, preg3
368         movw preg0, breg0
369         movw preg2, breg2
370         ldi r20, 3
371         rcall rotr32
372         rjmp outro_2
373
374 /*******************************************************************************
375 * uint32_t bmw_small_s4(uint32_t x){
376 *       uint32_t r;
377 *       r =  SHR32(x, 1)
378 *                ^ x;
379 *       return r;
380 * }
381 */
382 .global bmw_small_s4
383 bmw_small_s4:
384         movw areg0, preg0
385         movw areg2, preg2
386         ldi r20, 1
387         rcall shiftr32
388         rjmp outro_2
389
390 /*******************************************************************************
391 * uint32_t bmw_small_s5(uint32_t x){
392 *       uint32_t r;
393 *       r =  SHR32(x, 2)
394 *                ^ x;
395 *       return r;
396 * }
397 */
398 .global bmw_small_s5
399 bmw_small_s5:
400         movw areg0, preg0
401         movw areg2, preg2
402         ldi r20, 2
403         rcall shiftr32
404         rjmp outro_2
405
406 /*******************************************************************************
407 * uint32_t bmw_small_r1(uint32_t x){
408 *       uint32_t r;
409 *       r =  ROTL32(x, 3);
410 *       return r;
411 * }
412 */
413 .global bmw_small_r1
414 bmw_small_r1:
415         ldi r20, 3
416         rjmp rotl32
417
418 /*******************************************************************************
419 * uint32_t bmw_small_r2(uint32_t x){
420 *       uint32_t r;
421 *       r =  ROTL32(x, 7);
422 *       return r;
423 * }
424 */
425 .global bmw_small_r2
426 bmw_small_r2:
427         ldi r20, 7
428         rjmp rotl32
429
430 /*******************************************************************************
431 * uint32_t bmw_small_r3(uint32_t x){
432 *       uint32_t r;
433 *       r =  ROTL32(x, 13);
434 *       return r;
435 * }
436 */
437 .global bmw_small_r3
438 bmw_small_r3:
439         movw r18, r24
440         movw r24, r22
441         movw r22, r18
442         ldi r20, 3
443         rjmp rotr32
444
445
446 /*******************************************************************************
447 * uint32_t bmw_small_r4(uint32_t x){
448 *       uint32_t r;
449 *       r =  ROTL32(x, 16);
450 *       return r;
451 * }
452 */
453 .global bmw_small_r4
454 bmw_small_r4:
455         movw r18, r24
456         movw r24, r22
457         movw r22, r18
458         ret
459
460 /*******************************************************************************
461 * uint32_t bmw_small_r5(uint32_t x){
462 *       uint32_t r;
463 *       r =  ROTR32(x, 13);
464 *       return r;
465 * }
466 */
467 .global bmw_small_r5
468 bmw_small_r5:
469         movw r18, r24
470         movw r24, r22
471         movw r22, r18
472         ldi r20, 3
473         rjmp rotl32
474
475 /*******************************************************************************
476 * uint32_t bmw_small_r6(uint32_t x){
477 *       uint32_t r;
478 *       r =  ROTR32(x, 9);
479 *       return r;
480 * }
481 */
482 .global bmw_small_r6
483 bmw_small_r6:
484         mov r18, r22
485         mov r22, r23
486         mov r23, r24
487         mov r24, r25
488         mov r25, r18
489         ldi r20, 1
490         rjmp rotr32
491
492 /*******************************************************************************
493 * uint32_t bmw_small_r7(uint32_t x){
494 *       uint32_t r;
495 *       r =  ROTR32(x, 5);
496 *       return r;
497 * }
498 */
499 .global bmw_small_r7
500 bmw_small_r7:
501         ldi r20, 5
502         rjmp rotr32
503
504 /******************************************************************************/
505
506 const_lut:
507         .long 0x55555550, 0x5aaaaaa5, 0x5ffffffa, 0x6555554f
508         .long 0x6aaaaaa4, 0x6ffffff9, 0x7555554e, 0x7aaaaaa3
509         .long 0x7ffffff8, 0x8555554d, 0x8aaaaaa2, 0x8ffffff7
510         .long 0x9555554c, 0x9aaaaaa1, 0x9ffffff6, 0xa555554b
511
512 /*******************************************************************************
513 * uint32_t addelment(uint8_t j, const uint32_t *m, const uint32_t *h){
514 *       uint32_t r;
515 *       r  = pgm_read_dword(k_lut+j);
516 *       r += rotl_addel(((uint32_t*)m)[j&0xf], j+0);
517 *       r += rotl_addel(((uint32_t*)m)[(j+3)&0xf], j+3);
518 *       r -= rotl_addel(((uint32_t*)m)[(j+10)&0xf], j+10);
519 *       r ^= ((uint32_t*)h)[(j+7)&0xf];
520 *       return r;
521 * }
522 * param j: r24
523 * param m: r22:r23
524 * param h: r20:r21
525 */
526 j    = 16
527 acc2 =  8
528 acc3 =  9
529 h0   = 10
530 h1   = 11
531 m0   = 12
532 m1   = 13
533 acc0 = 14
534 acc1 = 15
535 .global addelement
536 addelement:
537         push_range 8, 16
538         mov j, r24
539         movw h0, r20
540         movw m0, r22
541         lsl r24
542         lsl r24
543         ldi r30, lo8(const_lut)
544         ldi r31, hi8(const_lut)
545         add r30, r24
546         adc r31, r1
547         lpm acc0, Z+
548         lpm acc1, Z+
549         lpm acc2, Z+
550         lpm acc3, Z+
551
552         mov r20, j
553         andi r20, 0x0f
554         lsl r20
555         lsl r20
556         movw r26, m0
557         add r26, r20
558         adc r27, r1
559         ld r22, X+
560         ld r23, X+
561         ld r24, X+
562         ld r25, X+
563         mov r20, j
564         rcall rotl_addel
565         add acc0, r22
566         adc acc1, r23
567         adc acc2, r24
568         adc acc3, r25
569
570         subi j, -3
571         mov r20, j
572         andi r20, 0x0f
573         lsl r20
574         lsl r20
575         movw r26, m0
576         add r26, r20
577         adc r27, r1
578         ld r22, X+
579         ld r23, X+
580         ld r24, X+
581         ld r25, X+
582         mov r20, j
583         rcall rotl_addel
584         add acc0, r22
585         adc acc1, r23
586         adc acc2, r24
587         adc acc3, r25
588
589         subi j, -7
590         mov r20, j
591         andi r20, 0x0f
592         lsl r20
593         lsl r20
594         movw r26, m0
595         add r26, r20
596         adc r27, r1
597         ld r22, X+
598         ld r23, X+
599         ld r24, X+
600         ld r25, X+
601         mov r20, j
602         rcall rotl_addel
603         sub acc0, r22
604         sbc acc1, r23
605         sbc acc2, r24
606         sbc acc3, r25
607
608         subi j, 3
609         mov r20, j
610         andi r20, 0x0f
611         lsl r20
612         lsl r20
613         movw r26, h0
614         add r26, r20
615         adc r27, r1
616         ld r22, X+
617         ld r23, X+
618         ld r24, X+
619         ld r25, X+
620         eor r22, acc0
621         eor r23, acc1
622         eor r24, acc2
623         eor r25, acc3
624         pop_range 8, 16
625         ret
626
627 /*******************************************************************************
628 * uint32_t bmw_small_expand1(uint8_t j, const void *m, const void *h, const uint32_t *q){
629 *       uint32_t(*s[])(uint32_t) = {bmw_small_s1, bmw_small_s2, bmw_small_s3, bmw_small_s0};
630 *       uint32_t r;
631 *       uint8_t i;
632 *       r = addelement(j, m, h);
633 *       i=15;
634 *       do{
635 *               r += s[i%4](q[j+i]);
636 *       }while(i--!=0);
637 *       return r;
638 *
639 * param j: r24
640 * param m: r22:r23
641 * param h: r20:r21
642 * param q: r18:r19
643 */
644 acc0 =  2
645 acc1 =  3
646 acc2 =  4
647 acc3 =  5
648 .global bmw_small_expand1
649 bmw_small_expand1:
650         push_range 28, 29
651         movw r28, r18
652         mov r18, r24
653         lsl r18
654         lsl r18
655         add r28, r18
656         adc r29, r1
657         rcall addelement
658         push_range 2, 5
659         push r16
660         ldi r16, 4
661         movw acc0, r22
662         movw acc2, r24
663 1:
664         ld r22, Y+
665         ld r23, Y+
666         ld r24, Y+
667         ld r25, Y+
668         rcall bmw_small_s1
669         add acc0, r22
670         adc acc1, r23
671         adc acc2, r24
672         adc acc3, r25
673         ld r22, Y+
674         ld r23, Y+
675         ld r24, Y+
676         ld r25, Y+
677         rcall bmw_small_s2
678         add acc0, r22
679         adc acc1, r23
680         adc acc2, r24
681         adc acc3, r25
682         ld r22, Y+
683         ld r23, Y+
684         ld r24, Y+
685         ld r25, Y+
686         rcall bmw_small_s3
687         add acc0, r22
688         adc acc1, r23
689         adc acc2, r24
690         adc acc3, r25
691         ld r22, Y+
692         ld r23, Y+
693         ld r24, Y+
694         ld r25, Y+
695         rcall bmw_small_s0
696         add acc0, r22
697         adc acc1, r23
698         adc acc2, r24
699         adc acc3, r25
700         dec r16
701         brne 1b
702 expand1_exit:
703         movw r22, acc0
704         movw r24, acc2
705         pop r16
706         pop_range 2, 5
707         pop_range 28, 29
708         ret
709
710 /*******************************************************************************
711 * uint32_t bmw_small_expand2(uint8_t j, const void *m, const void *h, const uint32_t *q){
712 *       uint32_t(*rf[])(uint32_t) = {bmw_small_r1, bmw_small_r2, bmw_small_r3,
713 *                                    bmw_small_r4, bmw_small_r5, bmw_small_r6,
714 *                                                            bmw_small_r7};
715 *       uint32_t r;
716 *       uint8_t i;
717 *       r = addelement(j, m, h);
718 *       for(i=0; i<14; i+=2){
719 *               r += q[j+i];
720 *       }
721 *       for(i=0; i<14; i+=2){
722 *               r += rf[i/2](q[j+i+1]);
723 *       }
724 *       r += bmw_small_s4(q[j+14]);
725 *       r += bmw_small_s5(q[j+15]);
726 *       return r;
727 * }
728 */
729 expand2_jumptable:
730         ret
731         rjmp bmw_small_r1
732         ret
733         rjmp bmw_small_r2
734         ret
735         rjmp bmw_small_r3
736         ret
737         rjmp bmw_small_r4
738         ret
739         rjmp bmw_small_r5
740         ret
741         rjmp bmw_small_r6
742         ret
743         rjmp bmw_small_r7
744         rjmp bmw_small_s4
745         rjmp bmw_small_s5
746
747 .global bmw_small_expand2
748 bmw_small_expand2:
749         push_range 28, 29
750         movw r28, r18
751         mov r18, r24
752         lsl r18
753         lsl r18
754         add r28, r18
755         adc r29, r1
756         rcall addelement
757         push_range 2, 5
758         push r16
759         ldi r16, 16
760         movw acc0, r22
761         movw acc2, r24
762         ldi r30, pm_lo8(expand2_jumptable)
763         ldi r31, pm_hi8(expand2_jumptable)
764 1:
765         ld r22, Y+
766         ld r23, Y+
767         ld r24, Y+
768         ld r25, Y+
769         push r30
770         push r31
771         icall
772         pop r31
773         pop r30
774         adiw r30, 1
775         add acc0, r22
776         adc acc1, r23
777         adc acc2, r24
778         adc acc3, r25
779         dec r16
780         brne 1b
781         rjmp expand1_exit
782
783 /*******************************************************************************
784 * void bmw_small_f1(uint32_t *q, const void *m, const void *h){
785 *       uint8_t i;
786 *       q[16] = bmw_small_expand1(0, m, h, q);
787 *       q[17] = bmw_small_expand1(1, m, h, q);
788 *       for(i=2; i<16; ++i){
789 *               q[16+i] = bmw_small_expand2(i, m, h, q);
790 *       }
791 * }
792 */
793 m0 =  2
794 m1 =  3
795 h0 =  4
796 h1 =  5
797 q0 =  6
798 q1 =  7
799 .global bmw_small_f1
800 bmw_small_f1:
801 ;       push_range 2, 7
802 ;       push_range 28, 29
803         push r16
804         movw q0, r24
805         movw m0, r22
806         movw h0, r20
807         movw r28, q0
808         adiw r28, 63
809         adiw r28, 1
810         clr r24
811         clr r25 /* not required */
812         movw r18, q0
813         rcall bmw_small_expand1
814         st Y+, r22
815         st Y+, r23
816         st Y+, r24
817         st Y+, r25
818         ldi r16, 1
819         mov r24, r16
820         clr r25 /* not required */
821         movw r22, m0
822         movw r20, h0
823         movw r18, q0
824         rcall bmw_small_expand1
825         st Y+, r22
826         st Y+, r23
827         st Y+, r24
828         st Y+, r25
829         inc r16
830 1:
831         mov r24, r16
832         movw r22, m0
833         movw r20, h0
834         movw r18, q0
835         rcall bmw_small_expand2
836         st Y+, r22
837         st Y+, r23
838         st Y+, r24
839         st Y+, r25
840         inc r16
841         cpi r16, 16
842         brne 1b
843         pop r16
844 ;       pop_range 28, 29
845 ;       pop_range 2, 7
846         ret
847
848 /*******************************************************************************
849 * uint16_t hack_table[5]   PROGMEM = { 0x0311, 0xDDB3, 0x2A79, 0x07AA, 0x51C2 };
850 * uint8_t  offset_table[5] PROGMEM = { 4+16, 6+16, 9+16, 12+16, 13+16 };
851 *
852 * void bmw_small_f0(uint32_t *h, const void *m, uint32_t *q){
853 *       uint16_t hack_reg;
854 *       uint8_t c,i,j;
855 *       uint32_t(*s[])(uint32_t)={ bmw_small_s0, bmw_small_s1, bmw_small_s2,
856 *                                  bmw_small_s3, bmw_small_s4 };
857 *       for(i=0; i<16; ++i){
858 *               ((uint32_t*)h)[i] ^= ((uint32_t*)m)[i];
859 *       }
860 *       dump_x(h, 16, 'T');
861 *       memset(q, 0, 4*16);
862 *       c=4;
863 *       do{
864 *               i=15;
865 *               j=pgm_read_byte(offset_table+c);
866 *               hack_reg=pgm_read_word(&(hack_table[c]));
867 *               do{
868 *                       if(hack_reg&1){
869 *                               q[i]-= h[j&15];
870 *                       }else{
871 *                               q[i]+= h[j&15];
872 *                       }
873 *                       --j;
874 *                       hack_reg>>= 1;
875 *               }while(i--!=0);
876 *       }while(c--!=0);
877 *       dump_x(q, 16, 'W');
878 *       for(i=0; i<16; ++i){
879 *               q[i] = s[i%5](q[i]);
880 *       }
881 *       for(i=0; i<16; ++i){
882 *               ((uint32_t*)h)[i] ^= ((uint32_t*)m)[i];
883 *       }
884 *       for(i=0; i<16; ++i){
885 *               q[i] += h[(i+1)&0xf];
886 *       }
887 * }
888 *
889 * param h: r24:r25
890 * param m: r22:r23
891 * param q: r20:r21
892 */
893 h0   =  24
894 h1   =  25
895 m0   =  22
896 m1   =  23
897 q0   =  20
898 q1   =  21
899 acc0 =  4
900 acc1 =  5
901 acc2 =  6
902 acc3 =  7
903 bcc0 =  8
904 bcc1 =  9
905 bcc2 = 10
906 bcc3 = 11
907 hack = 16
908
909 f0_helper:
910 20:
911         ldd acc0, Z+0
912         ldd acc1, Z+1
913         ldd acc2, Z+2
914         ldd acc3, Z+3
915         ld bcc0, X+
916         ld bcc1, X+
917         ld bcc2, X+
918         ld bcc3, X+
919         lsr r17
920         ror r16
921         brcs l20_sub
922         add acc0, bcc0
923         adc acc1, bcc1
924         adc acc2, bcc2
925         adc acc3, bcc3
926         rjmp l20_post
927 l20_sub:
928         sub acc0, bcc0
929         sbc acc1, bcc1
930         sbc acc2, bcc2
931         sbc acc3, bcc3
932 l20_post:
933         st Z+, acc0
934         st Z+, acc1
935         st Z+, acc2
936         st Z+, acc3
937         dec r18
938         brne 20b
939         ret
940
941 f0_jumptable:
942         rjmp bmw_small_s0
943         rjmp bmw_small_s1
944         rjmp bmw_small_s2
945         rjmp bmw_small_s3
946         rjmp bmw_small_s4
947         rjmp bmw_small_s0
948         rjmp bmw_small_s1
949         rjmp bmw_small_s2
950         rjmp bmw_small_s3
951         rjmp bmw_small_s4
952         rjmp bmw_small_s0
953         rjmp bmw_small_s1
954         rjmp bmw_small_s2
955         rjmp bmw_small_s3
956         rjmp bmw_small_s4
957         rjmp bmw_small_s0
958
959 .global bmw_small_f0
960 bmw_small_f0:
961 ;       push_range 28, 29
962 ;    push_range 4, 11
963 ;    push_range 16, 17
964     /* h[i] ^= m[i]; q[i]= 0 */
965         movw r26, h0 ; h
966         movw r30, m0 ; m
967         movw r28, q0 ; q
968         ldi r18, 64
969 1:  ld r0, X
970     ld r19, Z+
971     eor r0, r19
972     st X+, r0
973     st Y+, r1
974     dec r18
975     brne 1b
976 ;------
977     ldi r17, 0x88
978     ldi r16, 0xC0
979     movw r26, h0 ; X = h
980     adiw r26, 5*4
981     ldi r18, 16-5
982     movw r30, q0 ; Z = q
983     rcall f0_helper
984     movw r26, h0 ; X = h
985     ldi r18,    5
986     rcall f0_helper
987 ;---
988     ldi r17, 0xCD
989     ldi r16, 0xBB
990     movw r26, h0 ; X = h
991     adiw r26, 7*4
992     ldi r18, 16-7
993     movw r30, q0 ; Z = q
994     rcall f0_helper
995     movw r26, h0 ; X = h
996     ldi r18,    7
997     rcall f0_helper
998 ;---
999     ldi r17, 0x9E
1000     ldi r16, 0x54
1001     movw r26, h0 ; X = h
1002     adiw r26, 10*4
1003     ldi r18, 16-10
1004     movw r30, q0 ; Z = q
1005     rcall f0_helper
1006     movw r26, h0 ; X = h
1007     ldi r18,   10
1008     rcall f0_helper
1009 ;---
1010     ldi r17, 0x55
1011     ldi r16, 0xE0
1012     movw r26, h0 ; X = h
1013     adiw r26, 13*4
1014     ldi r18, 16-13
1015     movw r30, q0 ; Z = q
1016     rcall f0_helper
1017     movw r26, h0 ; X = h
1018     ldi r18,  13
1019     rcall f0_helper
1020 ;---
1021     ldi r17, 0x43
1022     ldi r16, 0x8A
1023     movw r26, h0 ; X = h
1024     adiw r26, 14*4
1025     ldi r18, 16-14
1026     movw r30, q0 ; Z = q
1027     rcall f0_helper
1028     movw r26, h0 ; X = h
1029     ldi r18,  14
1030     rcall f0_helper
1031 ;--------------- h[i] ^= m[i]
1032         movw r26, h0 ; h
1033         movw r30, m0 ; m
1034         ldi r18, 64
1035 25: ld r0, X
1036     ld r19, Z+
1037     eor r0, r19
1038     st X+, r0
1039     dec r18
1040     brne 25b
1041 ;--------------- q[i] = s[i%5](q[i])
1042         ldi r16, 16
1043         ldi r30, pm_lo8(f0_jumptable)
1044         ldi r31, pm_hi8(f0_jumptable)
1045     movw bcc0, r30
1046     movw bcc2, h0 ; h
1047     movw acc0, q0 ; q
1048     movw r28,  q0 ; Y = q
1049 30:
1050         ldd r22, Y+0
1051         ldd r23, Y+1
1052         ldd r24, Y+2
1053         ldd r25, Y+3
1054         icall
1055         st Y+, r22
1056         st Y+, r23
1057         st Y+, r24
1058         st Y+, r25
1059         movw r30, bcc0
1060         adiw r30, 1
1061         movw bcc0, r30
1062         dec r16
1063         brne 30b
1064 ;--------------- q[i] += h[(i+1)%16]
1065         movw r30, acc0 ; q
1066         movw r26, bcc2 ; h
1067         adiw r26, 4
1068         ldi r18, 15
1069 40:
1070         ld acc0, Z
1071         ld acc1, X+
1072         add acc0, acc1
1073         st Z+, acc0
1074         ld acc0, Z
1075         ld acc1, X+
1076         adc acc0, acc1
1077         st Z+, acc0
1078         ld acc0, Z
1079         ld acc1, X+
1080         adc acc0, acc1
1081         st Z+, acc0
1082         ld acc0, Z
1083         ld acc1, X+
1084         adc acc0, acc1
1085         st Z+, acc0
1086         dec r18
1087         brne 40b
1088         movw r26, bcc2 ; h
1089         ld acc0, Z
1090         ld acc1, X+
1091         add acc0, acc1
1092         st Z+, acc0
1093         ld acc0, Z
1094         ld acc1, X+
1095         adc acc0, acc1
1096         st Z+, acc0
1097         ld acc0, Z
1098         ld acc1, X+
1099         adc acc0, acc1
1100         st Z+, acc0
1101         ld acc0, Z
1102         ld acc1, X+
1103         adc acc0, acc1
1104         st Z+, acc0
1105
1106 ;   pop_range 16, 17
1107 ;   pop_range 4, 11
1108 ;       pop_range 28, 29
1109     ret
1110
1111 /*******************************************************************************
1112 * void bmw_small_f2(uint32_t *h, const uint32_t *q, const void *m){
1113 *       uint32_t xl=0, xh;
1114 *       uint8_t i;
1115 *       for(i=16;i<24;++i){
1116 *               xl ^= q[i];
1117 *       }
1118 *       xh = xl;
1119 *       for(i=24;i<32;++i){
1120 *               xh ^= q[i];
1121 *       }
1122 *       memcpy(h, m, 16*4);
1123 *       h[0] ^= SHL32(xh, 5) ^ SHR32(q[16], 5);
1124 *       h[5] ^= SHL32(xh, 6) ^ SHR32(q[21], 6);
1125 *       h[3] ^= SHR32(xh, 1) ^ SHL32(q[19], 5);
1126 *       h[4] ^= SHR32(xh, 3) ^ q[20];
1127 *       h[6] ^= SHR32(xh, 4) ^ SHL32(q[22], 6);
1128 *       h[2] ^= SHR32(xh, 5) ^ SHL32(q[18], 5);
1129 *       h[1] ^= SHR32(xh, 7) ^ SHL32(q[17], 8);
1130 *       h[7] ^= SHR32(xh,11) ^ SHL32(q[23], 2);
1131 *       for(i=0; i<8; ++i){
1132 *               h[i] += xl ^ q[24+i] ^ q[i];
1133 *       }
1134 *       for(i=0; i<8; ++i){
1135 *               h[8+i] ^= xh ^ q[24+i];
1136 *               h[8+i] += ROTL32(h[(4+i)%8],i+9);
1137 *       }
1138 *       h[11] += SHL32(xl, 4) ^ q[18] ^ q[11];
1139 *       h[10] += SHL32(xl, 6) ^ q[17] ^ q[10];
1140 *       h[ 8] += SHL32(xl, 8) ^ q[23] ^ q[ 8];
1141 *       h[15] += SHR32(xl, 2) ^ q[22] ^ q[15];
1142 *       h[12] += SHR32(xl, 3) ^ q[19] ^ q[12];
1143 *       h[13] += SHR32(xl, 4) ^ q[20] ^ q[13];
1144 *       h[ 9] += SHR32(xl, 6) ^ q[16] ^ q[ 9];
1145 *       h[14] += SHR32(xl, 7) ^ q[21] ^ q[14];
1146 * }
1147 *
1148 * param h: r24:r25
1149 * param q: r22:r23
1150 * param m: r20:r21
1151 */
1152 xl0 =  2
1153 xl1 =  3
1154 xl2 =  4
1155 xl3 =  5
1156 xh0 =  6
1157 xh1 =  7
1158 xh2 =  8
1159 xh3 =  9
1160 q0  = 10
1161 q1  = 11
1162 h0  = 12
1163 h1  = 13
1164 t0  = 14
1165 t1  = 15
1166 t2  = 16
1167 t3  = 17
1168
1169
1170 .macro modify_h_2 addr:req
1171         ldd r22, Y+\addr*4+0
1172         ldd r23, Y+\addr*4+1
1173         ldd r24, Y+\addr*4+2
1174         ldd r25, Y+\addr*4+3
1175         eor r22, t0
1176         eor r23, t1
1177         eor r24, t2
1178         eor r25, t3
1179         ldd r0, Z+\addr*4+0
1180         add r0, r22
1181         std Z+\addr*4+0, r0
1182         ldd r0, Z+\addr*4+1
1183         adc r0, r23
1184         std Z+\addr*4+1, r0
1185         ldd r0, Z+\addr*4+2
1186         adc r0, r24
1187         std Z+\addr*4+2, r0
1188         ldd r0, Z+\addr*4+3
1189         adc r0, r25
1190         std Z+\addr*4+3, r0
1191 .endm
1192
1193 tshiftr:
1194         lsr t3
1195         ror t2
1196         ror t1
1197         ror t0
1198         dec r20
1199         brne tshiftr
1200         ret
1201
1202 tshiftl:
1203         lsl t0
1204         rol t1
1205         rol t2
1206         rol t3
1207         dec r20
1208         brne tshiftl
1209         ret
1210
1211 .global bmw_small_f2
1212 bmw_small_f2:
1213     /* memcpy(h, m, 64) */
1214         movw r26, r24
1215         movw r30, r20
1216         ldi r18, 64
1217 1:      ld r0, Z+
1218         st X+, r0
1219         dec r18
1220         brne 1b
1221 ;       push_range 28, 29
1222 ;       push_range  2, 17
1223         movw q0, r22
1224         movw h0, r24
1225         /* calc xl */
1226 /*      for(i=16;i<24;++i){
1227                 xl ^= q[i];
1228         }
1229 */
1230         movw r26, q0
1231         adiw r26, 63
1232         adiw r26, 1 ; X points at q[16]
1233         ld xl0, X+
1234         ld xl1, X+
1235         ld xl2, X+
1236         ld xl3, X+
1237         ldi r18, 8-1
1238 20: ld r0, X+
1239         eor xl0, r0
1240         ld r0, X+
1241         eor xl1, r0
1242         ld r0, X+
1243         eor xl2, r0
1244         ld r0, X+
1245         eor xl3, r0
1246         dec r18
1247         brne 20b
1248         /* calc xh */
1249 /*  xh = xl
1250         for(i=24;i<32;++i){
1251                 xh ^= q[i];
1252         }
1253 */
1254         movw xh0, xl0
1255         movw xh2, xl2
1256         ldi r18, 8
1257 25: ld r0, X+
1258         eor xh0, r0
1259         ld r0, X+
1260         eor xh1, r0
1261         ld r0, X+
1262         eor xh2, r0
1263         ld r0, X+
1264         eor xh3, r0
1265         dec r18
1266         brne 25b
1267 /* h[0]..h[7] */
1268         movw r30, h0
1269         movw r28, q0
1270         adiw r28, 60 ; Y points at q[15]
1271 /*      h[0] ^= SHL32(xh, 5) ^ SHR32(q[16], 5); */
1272         movw t0, xh0
1273         movw t2, xh2
1274         ldi r20, 5
1275         rcall tshiftl
1276         ldd r22, Y+4
1277         ldd r23, Y+5
1278         ldd r24, Y+6
1279         ldd r25, Y+7
1280         ldi r20, 5
1281         rcall shiftr32
1282         eor r22, t0
1283         eor r23, t1
1284         eor r24, t2
1285         eor r25, t3
1286         ldd r0, Z+0
1287         eor r22, r0
1288         ldd r0, Z+1
1289         eor r23, r0
1290         ldd r0, Z+2
1291         eor r24, r0
1292         ldd r0, Z+3
1293         eor r25, r0
1294         std Z+0, r22
1295         std Z+1, r23
1296         std Z+2, r24
1297         std Z+3, r25
1298 /*      h[5] ^= SHL32(xh, 6) ^ SHR32(q[21], 6); */
1299         lsl t0
1300         rol t1
1301         rol t2
1302         rol t3
1303         ldd r22, Y+24
1304         ldd r23, Y+25
1305         ldd r24, Y+26
1306         ldd r25, Y+27
1307         ldi r20, 6
1308         rcall shiftr32
1309         eor r22, t0
1310         eor r23, t1
1311         eor r24, t2
1312         eor r25, t3
1313         ldd r0, Z+20
1314         eor r22, r0
1315         ldd r0, Z+21
1316         eor r23, r0
1317         ldd r0, Z+22
1318         eor r24, r0
1319         ldd r0, Z+23
1320         eor r25, r0
1321         std Z+20, r22
1322         std Z+21, r23
1323         std Z+22, r24
1324         std Z+23, r25
1325 /*      h[3] ^= SHR32(xh, 1) ^ SHL32(q[19], 5); */
1326         movw t0, xh0
1327         movw t2, xh2
1328         lsr t3
1329         ror t2
1330         ror t1
1331         ror t0
1332         ldd r22, Y+16
1333         ldd r23, Y+17
1334         ldd r24, Y+18
1335         ldd r25, Y+19
1336         ldi r20, 5
1337         rcall shiftl32
1338         eor r22, t0
1339         eor r23, t1
1340         eor r24, t2
1341         eor r25, t3
1342         ldd r0, Z+12
1343         eor r22, r0
1344         ldd r0, Z+13
1345         eor r23, r0
1346         ldd r0, Z+14
1347         eor r24, r0
1348         ldd r0, Z+15
1349         eor r25, r0
1350         std Z+12, r22
1351         std Z+13, r23
1352         std Z+14, r24
1353         std Z+15, r25
1354 /*      h[4] ^= SHR32(xh, 3) ^ q[20]; */
1355         ldi r20, 2
1356         rcall tshiftr
1357         ldd r22, Y+20
1358         ldd r23, Y+21
1359         ldd r24, Y+22
1360         ldd r25, Y+23
1361         eor r22, t0
1362         eor r23, t1
1363         eor r24, t2
1364         eor r25, t3
1365         ldd r0, Z+16
1366         eor r22, r0
1367         ldd r0, Z+17
1368         eor r23, r0
1369         ldd r0, Z+18
1370         eor r24, r0
1371         ldd r0, Z+19
1372         eor r25, r0
1373         std Z+16, r22
1374         std Z+17, r23
1375         std Z+18, r24
1376         std Z+19, r25
1377 /*      h[6] ^= SHR32(xh, 4) ^ SHL32(q[22], 6); */
1378         lsr t3
1379         ror t2
1380         ror t1
1381         ror t0
1382         ldd r22, Y+28
1383         ldd r23, Y+29
1384         ldd r24, Y+30
1385         ldd r25, Y+31
1386         ldi r20, 6
1387         rcall shiftl32
1388         eor r22, t0
1389         eor r23, t1
1390         eor r24, t2
1391         eor r25, t3
1392         ldd r0, Z+24
1393         eor r22, r0
1394         ldd r0, Z+25
1395         eor r23, r0
1396         ldd r0, Z+26
1397         eor r24, r0
1398         ldd r0, Z+27
1399         eor r25, r0
1400         std Z+24, r22
1401         std Z+25, r23
1402         std Z+26, r24
1403         std Z+27, r25
1404 /*      h[2] ^= SHR32(xh, 5) ^ SHL32(q[18], 5); */
1405         lsr t3
1406         ror t2
1407         ror t1
1408         ror t0
1409         ldd r22, Y+12
1410         ldd r23, Y+13
1411         ldd r24, Y+14
1412         ldd r25, Y+15
1413         ldi r20, 5
1414         rcall shiftl32
1415         eor r22, t0
1416         eor r23, t1
1417         eor r24, t2
1418         eor r25, t3
1419         ldd r0, Z+8
1420         eor r22, r0
1421         ldd r0, Z+9
1422         eor r23, r0
1423         ldd r0, Z+10
1424         eor r24, r0
1425         ldd r0, Z+11
1426         eor r25, r0
1427         std Z+8 , r22
1428         std Z+9 , r23
1429         std Z+10, r24
1430         std Z+11, r25
1431 /*      h[1] ^= SHR32(xh, 7) ^ SHL32(q[17], 8); */
1432         ldi r20, 2
1433         rcall tshiftr
1434         ldd r23, Y+8
1435         ldd r24, Y+9
1436         ldd r25, Y+10
1437         mov r22, t0
1438         eor r23, t1
1439         eor r24, t2
1440         eor r25, t3
1441         ldd r0, Z+4
1442         eor r22, r0
1443         ldd r0, Z+5
1444         eor r23, r0
1445         ldd r0, Z+6
1446         eor r24, r0
1447         ldd r0, Z+7
1448         eor r25, r0
1449         std Z+4 , r22
1450         std Z+5 , r23
1451         std Z+6 , r24
1452         std Z+7 , r25
1453 /*      h[7] ^= SHR32(xh,11) ^ SHL32(q[23], 2); */
1454         ldi r20, 4
1455         rcall tshiftr
1456         ldd r22, Y+32
1457         ldd r23, Y+33
1458         ldd r24, Y+34
1459         ldd r25, Y+35
1460         ldi r20, 2
1461         rcall shiftl32
1462         eor r22, t0
1463         eor r23, t1
1464         eor r24, t2
1465         eor r25, t3
1466         ldd r0, Z+28
1467         eor r22, r0
1468         ldd r0, Z+29
1469         eor r23, r0
1470         ldd r0, Z+30
1471         eor r24, r0
1472         ldd r0, Z+31
1473         eor r25, r0
1474         std Z+28, r22
1475         std Z+29, r23
1476         std Z+30, r24
1477         std Z+31, r25
1478 /*      for(i=0; i<8; ++i){
1479 *               h[i] += xl ^ q[24+i] ^ q[i];
1480 *       }
1481 */
1482         movw r26, q0
1483         movw r28, q0
1484         adiw r28, 63
1485         adiw r28, 24*4-63
1486         ldi r18, 8
1487 10:
1488         movw t0, xl0
1489         movw t2, xl2
1490         ld r0, X+
1491         eor t0, r0
1492         ld r0, X+
1493         eor t1, r0
1494         ld r0, X+
1495         eor t2, r0
1496         ld r0, X+
1497         eor t3, r0
1498         ld r0, Y+
1499         eor t0, r0
1500         ld r0, Y+
1501         eor t1, r0
1502         ld r0, Y+
1503         eor t2, r0
1504         ld r0, Y+
1505         eor t3, r0
1506         ldd r22, Z+0
1507         ldd r23, Z+1
1508         ldd r24, Z+2
1509         ldd r25, Z+3
1510         add r22, t0
1511         adc r23, t1
1512         adc r24, t2
1513         adc r25, t3
1514         st Z+, r22
1515         st Z+, r23
1516         st Z+, r24
1517         st Z+, r25
1518         dec r18
1519         brne 10b
1520         ; Z points to h[8]
1521 /*      for(i=0; i<8; ++i){
1522                 h[8+i] ^= xh ^ q[24+i];
1523                 h[8+i] += ROTL32(h[(4+i)%8],i+9);
1524         }
1525 */
1526         ; Z points at h[8]
1527 ;       clr r18
1528         sbiw r28, 8*4 ; Y points at q[24]
1529         movw r26, r30
1530         sbiw r26, 4*4 ; X points at h[4]
1531 15:
1532         ldd t0, Z+0
1533         ldd t1, Z+1
1534         ldd t2, Z+2
1535         ldd t3, Z+3
1536         eor t0, xh0
1537         eor t1, xh1
1538         eor t2, xh2
1539         eor t3, xh3
1540         ld r0, Y+
1541         eor t0, r0
1542         ld r0, Y+
1543         eor t1, r0
1544         ld r0, Y+
1545         eor t2, r0
1546         ld r0, Y+
1547         eor t3, r0
1548         ld r22, X+
1549         ld r23, X+
1550         ld r24, X+
1551         ld r25, X+
1552         mov r20, r18
1553         rcall rotl32p9
1554         add t0, r22
1555         adc t1, r23
1556         adc t2, r24
1557         adc t3, r25
1558         st Z+, t0
1559         st Z+, t1
1560         st Z+, t2
1561         st Z+, t3
1562         inc r18
1563         cpi r18, 4
1564         brne 16f
1565         movw r26, h0
1566 16:
1567         sbrs r18, 3
1568         rjmp 15b
1569         sbiw r30, 4*8 ; adjust Z to point at h[8]
1570         sbiw r28, 16*4-1
1571         sbiw r28, 1   ; adjust Y to point at q[16]
1572         movw r26, r28
1573         sbiw r26, 7*4 ; adjust X to point at q[9]
1574         ldi r18, 7*4
1575 20: /* now we do the memxor stuff */
1576         ld t0, X
1577         ld t1, Y+
1578         eor t0, t1
1579         st X+, t0
1580         dec r18
1581         brne 20b
1582         ; X points at q[16]
1583         ; Y points at q[23]
1584         sbiw r26, 4*8 ; X points at q[8]
1585
1586         clr t0
1587         mov t1, xl0
1588         mov t2, xl1
1589         mov t3, xl2
1590 /*      h[ 8] += SHL32(xl, 8) ^ q[23] ^ q[ 8]; */
1591         ld r22, X+
1592         ld r23, X+
1593         ld r24, X+
1594         ld r25, X+
1595         ld r0, Y+
1596         eor r22, r0
1597         ld r0, Y+
1598         eor r23, r0
1599         ld r0, Y+
1600         eor r24, r0
1601         ld r0, Y+
1602         eor r25, r0
1603         eor r22, t0
1604         eor r23, t1
1605         eor r24, t2
1606         eor r25, t3
1607         ld r0, Z
1608         add r0, r22
1609         st Z+, r0
1610         ld r0, Z
1611         adc r0, r23
1612         st Z+, r0
1613         ld r0, Z
1614         adc r0, r24
1615         st Z+, r0
1616         ld r0, Z
1617         adc r0, r25
1618         st Z+, r0
1619         movw r28, r26
1620         ; Z points at h[9]
1621         ; X points at q[9] but we won't need it anymore
1622         ; Y points at q[9]
1623 /*      h[11] += SHL32(xl, 4) ^ q[11]; */
1624         movw t0, xl0
1625         movw t2, xl2
1626         ldi r20, 4
1627         rcall tshiftl
1628         modify_h_2 2
1629 /*      h[10] += SHL32(xl, 6) ^ q[10]; */
1630         ldi r20, 2
1631         rcall tshiftl
1632         modify_h_2 1
1633 /*      h[15] += SHR32(xl, 2) ^ q[15]; */
1634         movw t0, xl0
1635         movw t2, xl2
1636         ldi r20, 2
1637         rcall tshiftr
1638         modify_h_2 6
1639 /*      h[12] += SHR32(xl, 3) ^ q[12]; */
1640         ldi r20, 1
1641         rcall tshiftr
1642         modify_h_2 3
1643 /*      h[13] += SHR32(xl, 4) ^ q[13]; */
1644         ldi r20, 1
1645         rcall tshiftr
1646         modify_h_2 4
1647 /*      h[ 9] += SHR32(xl, 6) ^ q[ 9]; */
1648         ldi r20, 2
1649         rcall tshiftr
1650         modify_h_2 0
1651 /*      h[14] += SHR32(xl, 7) ^ q[14]; */
1652         ldi r20, 1
1653         rcall tshiftr
1654         modify_h_2 5
1655 bmw_small_f2_exit:
1656 ;       pop_range  2, 17
1657 ;       pop_range 28, 29
1658         ret
1659
1660 #if DEBUG_FUNCTIONS
1661
1662 cli_putb:
1663         push r2
1664         push_range 18, 26
1665         push_range 30, 31
1666         mov r2, r24
1667         swap r24
1668         andi r24, 0xf
1669         ldi r30, lo8(hextable)
1670         ldi r31, hi8(hextable)
1671         add r30, r24
1672         adc r31, r1
1673         lpm r24, Z
1674         clr r25
1675         call cli_putc
1676         mov r24, r2
1677         andi r24, 0xf
1678         ldi r30, lo8(hextable)
1679         ldi r31, hi8(hextable)
1680         add r30, r24
1681         adc r31, r1
1682         lpm r24, Z
1683         clr r25
1684         call cli_putc
1685         pop_range 30, 31
1686         pop_range 18, 26
1687         pop r2
1688         ret
1689 hextable:
1690         .byte '0', '1', '2', '3', '4', '5', '6', '7'
1691         .byte '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
1692
1693 cli_putchar:
1694         push_range 18, 31
1695         call cli_putc
1696         pop_range 18, 31
1697         ret
1698
1699 #endif
1700
1701 /*******************************************************************************
1702 * void bmw_small_nextBlock(bmw_small_ctx_t *ctx, const void *block){
1703 *       uint32_t q[32];
1704 *       dump_x(block, 16, 'M');
1705 *       bmw_small_f0(ctx->h, block, q);
1706 *       dump_x(q, 16, 'Q');
1707 *       bmw_small_f1(q, block, ctx->h);
1708 *       dump_x(q, 32, 'Q');
1709 *       bmw_small_f2(ctx->h, q, block);
1710 *       ctx->counter += 1;
1711 *       ctx_dump(ctx);
1712 * }
1713 *
1714 * param ctx:   r24:r25
1715 * param block: r22:r23
1716 */
1717 h0 =  2
1718 h1 =  3
1719 b0 =  4
1720 b1 =  5
1721 q0 =  6
1722 q1 =  7
1723 .global bmw_small_nextBlock
1724 .global bmw224_nextBlock
1725 .global bmw256_nextBlock
1726 bmw_small_nextBlock:
1727 bmw224_nextBlock:
1728 bmw256_nextBlock:
1729         push_range 28, 29
1730         push_range  2, 17
1731         stack_alloc_large 32*4, 30, 31
1732         adiw r30, 1
1733         movw q0, r30
1734         movw h0, r24
1735         movw b0, r22
1736         /* increment counter */
1737         movw r30, r24
1738         adiw r30, 60
1739         ldd r22, Z+4
1740         ldd r23, Z+5
1741         ldd r24, Z+6
1742         ldd r25, Z+7
1743         ldi r21, 1
1744         add r22, r21
1745         adc r23, r1
1746         adc r24, r1
1747         adc r25, r1
1748         std Z+4, r22
1749         std Z+5, r23
1750         std Z+6, r24
1751         std Z+7, r25
1752         /* call bmw_small_f0(ctx->h, block, q) */
1753         movw r24, h0
1754         movw r22, b0
1755         movw r20, q0
1756         push_ q1, q0, b1, b0, h1, h0
1757         rcall bmw_small_f0
1758         /*      call bmw_small_f1(q, block, ctx->h) */
1759         pop_ 20, 21, 22, 23, 24, 25,
1760         push_ 21, 20, 25, 24, 23, 22
1761         rcall bmw_small_f1
1762         /*      call bmw_small_f2(ctx->h, q, block) */
1763         pop_ 20, 21, 22, 23, 24, 25,
1764         rcall bmw_small_f2
1765         stack_free_large3 32*4
1766         pop_range  2, 17
1767         pop_range 28, 29
1768         ret
1769
1770
1771 /*******************************************************************************
1772 * void bmw224_init(bmw224_ctx_t *ctx){
1773 *       uint8_t i;
1774 *       ctx->h[0] = 0x00010203;
1775 *       for(i=1; i<16; ++i){
1776 *               ctx->h[i] = ctx->h[i-1]+ 0x04040404;
1777 *       }
1778 *       ctx->counter=0;
1779 * }
1780 *
1781 * param ctx:  r24:r25
1782 */
1783 .global bmw224_init
1784 bmw224_init:
1785         movw r26, r24
1786         ldi r22, 0x03
1787         ldi r23, 0x02
1788         ldi r24, 0x01
1789         ldi r25, 0x00
1790 bmw_small_init:
1791         st X+, r22
1792         st X+, r23
1793         st X+, r24
1794         st X+, r25
1795         ldi r18, 16-1
1796         ldi r20, 0x04
1797 1:
1798         add r22, r20
1799         adc r23, r20
1800         adc r24, r20
1801         adc r25, r20
1802         st X+, r22
1803         st X+, r23
1804         st X+, r24
1805         st X+, r25
1806         dec r18
1807         brne 1b
1808         st X+, r1
1809         st X+, r1
1810         st X+, r1
1811         st X+, r1
1812         ret
1813
1814 .global bmw256_init
1815 bmw256_init:
1816         movw r26, r24
1817         ldi r22, 0x43
1818         ldi r23, 0x42
1819         ldi r24, 0x41
1820         ldi r25, 0x40
1821         rjmp bmw_small_init
1822
1823 /*******************************************************************************
1824 * void bmw_small_lastBlock(bmw_small_ctx_t *ctx, const void *block, uint16_t length_b){
1825 *       struct {
1826 *               uint8_t  buffer[64];
1827 *               uint32_t ctr;
1828 *       } pctx;
1829 *       while(length_b >= BMW_SMALL_BLOCKSIZE){
1830 *               bmw_small_nextBlock(ctx, block);
1831 *               length_b -= BMW_SMALL_BLOCKSIZE;
1832 *               block = (uint8_t*)block + BMW_SMALL_BLOCKSIZE_B;
1833 *       }
1834 *       memset(pctx.buffer, 0, 64);
1835 *       memcpy(pctx.buffer, block, (length_b+7)/8);
1836 *       pctx.buffer[length_b>>3] |= 0x80 >> (length_b&0x07);
1837 *       if(length_b+1>64*8-64){
1838 *               bmw_small_nextBlock(ctx, pctx.buffer);
1839 *               memset(pctx.buffer, 0, 64-8);
1840 *               ctx->counter -= 1;
1841 *       }
1842 *       *((uint64_t*)&(pctx.buffer[64-8])) = (uint64_t)(ctx->counter*512LL)+(uint64_t)length_b;
1843 *       bmw_small_nextBlock(ctx, pctx.buffer);
1844 *       uint8_t i;
1845 *       memset(pctx.buffer, 0xaa, 64);
1846 *       for(i=0; i<16;++i){
1847 *               pctx.buffer[i*4] = i+0xa0;
1848 *       }
1849 *       bmw_small_nextBlock((bmw_small_ctx_t*)&pctx, ctx->h);
1850 *       memcpy(ctx->h, pctx.buffer, 64);
1851 * }
1852 *
1853 * param ctx:      r24:r25
1854 * param block:    r22:r23
1855 * param length_b: r20:r21
1856 */
1857 ctx0 =  2
1858 ctx1 =  3
1859 blc0 =  4
1860 blc1 =  5
1861 len0 = 28
1862 len1 = 29
1863 buf0 =  6
1864 buf1 =  7
1865
1866 .global bmw_small_lastBlock
1867 .global bmw224_lastBlock
1868 .global bmw256_lastBlock
1869 bmw_small_lastBlock:
1870 bmw224_lastBlock:
1871 bmw256_lastBlock:
1872 /*      while(length_b >= BMW_SMALL_BLOCKSIZE){
1873                 bmw_small_nextBlock(ctx, block);
1874                 length_b -= BMW_SMALL_BLOCKSIZE;
1875                 block = (uint8_t*)block + BMW_SMALL_BLOCKSIZE_B;
1876         }
1877 */
1878         push_range 2, 7
1879         push_range 28, 29
1880         movw ctx0, r24
1881         movw blc0, r22
1882         movw len0, r20
1883 1:
1884         cpi len1, hi8(512)
1885         brlo 2f
1886         movw r24, ctx0
1887         movw r22, blc0
1888         rcall bmw_small_nextBlock
1889         ldi r24, 64
1890         add blc0, r24
1891         adc blc1, r1
1892         subi len1, hi8(512)
1893         rjmp 1b
1894 2:
1895 /*      struct {
1896                 uint8_t  buffer[64];
1897                 uint32_t ctr;
1898         } pctx;
1899 */
1900         stack_alloc_large 68
1901         adiw r30, 1
1902         movw buf0, r30
1903 /*      memset(pctx.buffer, 0, 64);
1904         memcpy(pctx.buffer, block, (length_b+7)/8);
1905         pctx.buffer[length_b>>3] |= 0x80 >> (length_b&0x07);
1906 */      movw r24, len0
1907         lsr r25
1908         ror r24
1909         lsr r24
1910         lsr r24
1911 ;       inc r24
1912         ldi r23, 63
1913         sub r23, r24
1914         movw r26, blc0
1915         tst r24
1916         breq 301f
1917 30: ld r20, X+
1918         st Z+, r20
1919         dec r24
1920         brne 30b
1921 301:
1922         clr r20
1923         mov r21, len0
1924         ldi r24, 0x80
1925         andi r21, 0x07
1926         breq 305f
1927         ld r20, X+
1928 303:
1929         lsr r24
1930         dec r21
1931         brne 303b
1932 305:
1933         or r20, r24
1934         st Z+, r20
1935         tst r23
1936         breq 32f
1937 31: st Z+, r1
1938         dec r23
1939         brne 31b
1940 32:
1941 /*      if(length_b+1>64*8-64){ ; = 64*7-1 = 447 max(length_b)=511
1942                 bmw_small_nextBlock(ctx, pctx.buffer);
1943                 memset(pctx.buffer, 0, 64-8);
1944                 ctx->counter -= 1;
1945         }
1946 */
1947         tst len1
1948         breq 400f
1949         cpi len0, 192
1950         brlo 400f
1951         movw r24, ctx0
1952         movw r22, buf0
1953         rcall bmw_small_nextBlock
1954         movw r26, buf0
1955         ldi r20, 64-8
1956 350:
1957         st X+, r1
1958         dec r20
1959         brne 350b
1960         movw r30, ctx0
1961         adiw r30, 60
1962         ldd r21, Z+4
1963         ldd r22, Z+5
1964         ldd r23, Z+6
1965         ldd r24, Z+7
1966         subi r21, 1
1967         sbc r22, r1
1968         sbc r23, r1
1969         sbc r24, r1
1970         rjmp 410f
1971 /*      *((uint64_t*)&(pctx.buffer[64-8])) = (uint64_t)(ctx->counter*512LL)+(uint64_t)length_b;
1972         bmw_small_nextBlock(ctx, pctx.buffer);
1973 */
1974 400:
1975         movw r30, ctx0
1976         adiw r30, 60
1977         ldd r21, Z+4
1978         ldd r22, Z+5
1979         ldd r23, Z+6
1980         ldd r24, Z+7
1981 410:
1982         clr r25
1983         lsl r21
1984         rol r22
1985         rol r23
1986         rol r24
1987         rol r25
1988         mov r20, len0
1989         add r21, len1
1990         adc r22, r1
1991         adc r23, r1
1992         adc r24, r1
1993         adc r25, r1
1994         movw r30, buf0
1995         adiw r30, 64-8
1996         st Z+, r20
1997         st Z+, r21
1998         st Z+, r22
1999         st Z+, r23
2000         st Z+, r24
2001         st Z+, r25
2002         st Z+, r1
2003         st Z+, r1
2004         movw r24, ctx0
2005         movw r22, buf0
2006         rcall bmw_small_nextBlock
2007 /*      memset(pctx.buffer, 0xaa, 64);
2008         for(i=0; i<16;++i){
2009                 pctx.buffer[i*4] = i+0xa0;
2010         }
2011 */
2012         ldi r18, 0xa0
2013         ldi r19, 0xaa
2014         movw r26, buf0
2015 500:
2016         st X+, r18
2017         st X+, r19
2018         st X+, r19
2019         st X+, r19
2020         inc r18
2021         sbrs r18, 4
2022         rjmp 500b
2023 /*      bmw_small_nextBlock((bmw_small_ctx_t*)&pctx, ctx->h);
2024         memcpy(ctx->h, pctx.buffer, 64);
2025 */
2026         movw r24, buf0
2027         movw r22, ctx0
2028         rcall bmw_small_nextBlock
2029         ldi r18, 64
2030         movw r26, ctx0
2031         movw r30, buf0
2032 600:
2033         ld r20, Z+
2034         st X+, r20
2035         dec r18
2036         brne 600b
2037
2038         stack_free_large 68
2039         pop_range 28, 29
2040         pop_range 2, 7
2041         ret
2042
2043 /*******************************************************************************
2044 * void bmw224_ctx2hash(void *dest, const bmw224_ctx_t *ctx){
2045 *       memcpy(dest, &(ctx->h[9]), 224/8);
2046 * }
2047 *
2048 * param dest:  r24:r25
2049 * param ctx:   r22:r23
2050 */
2051 .global bmw224_ctx2hash
2052 bmw224_ctx2hash:
2053         movw r26, r24
2054         movw r30, r22
2055         adiw r30, 9*4
2056         ldi r22, 28
2057         rjmp 1f
2058
2059 /*******************************************************************************
2060 * void bmw256_ctx2hash(void *dest, const bmw256_ctx_t *ctx){
2061 *       memcpy(dest, &(ctx->h[8]), 256/8);
2062 * }
2063 *
2064 * param dest:  r24:r25
2065 * param ctx:   r22:r23
2066 */
2067 .global bmw256_ctx2hash
2068 bmw256_ctx2hash:
2069         movw r26, r24
2070         movw r30, r22
2071         adiw r30, 8*4
2072         ldi r22, 32
2073 1:
2074         ld r23, Z+
2075         st X+, r23
2076         dec r22
2077         brne 1b
2078         ret
2079
2080 /*******************************************************************************
2081 * void bmw256(void *dest, const void *msg, uint32_t length_b){
2082 *       bmw_small_ctx_t ctx;
2083 *       bmw256_init(&ctx);
2084 *       while(length_b>=BMW_SMALL_BLOCKSIZE){
2085 *               bmw_small_nextBlock(&ctx, msg);
2086 *               length_b -= BMW_SMALL_BLOCKSIZE;
2087 *               msg = (uint8_t*)msg + BMW_SMALL_BLOCKSIZE_B;
2088 *       }
2089 *       bmw_small_lastBlock(&ctx, msg, length_b);
2090 *       bmw256_ctx2hash(dest, &ctx);
2091 * }
2092 *
2093 * param dest:     r24:r25
2094 * param msg:      r22:r23
2095 * param length_b: r18:r21
2096 */
2097 ctx0 =   2
2098 ctx1 =   3
2099 msg0 =   4
2100 msg1 =   5
2101 len0 =   6
2102 len1 =   7
2103 len2 =   8
2104 len3 =   9
2105 dst0 =  10
2106 dst1 =  11
2107 .global bmw256
2108 bmw256:
2109         push r16
2110         ldi r16, 1
2111         rjmp bmw_small_all
2112
2113 /*******************************************************************************
2114 * void bmw224(void *dest, const void *msg, uint32_t length_b){
2115 *       bmw_small_ctx_t ctx;
2116 *       bmw224_init(&ctx);
2117 *       while(length_b>=BMW_SMALL_BLOCKSIZE){
2118 *               bmw_small_nextBlock(&ctx, msg);
2119 *               length_b -= BMW_SMALL_BLOCKSIZE;
2120 *               msg = (uint8_t*)msg + BMW_SMALL_BLOCKSIZE_B;
2121 *       }
2122 *       bmw_small_lastBlock(&ctx, msg, length_b);
2123 *       bmw224_ctx2hash(dest, &ctx);
2124 * }
2125 *
2126 * param dest:     r24:r25
2127 * param msg:      r22:r23
2128 * param length_b: r18:r21
2129 */
2130 ctx0 =   2
2131 ctx1 =   3
2132 msg0 =   4
2133 msg1 =   5
2134 len0 =   6
2135 len1 =   7
2136 len2 =   8
2137 len3 =   9
2138 dst0 =  10
2139 dst1 =  11
2140 .global bmw224
2141 bmw224:
2142         push r16
2143         clr r16
2144
2145 bmw_small_all:
2146         push_range 2, 11
2147         stack_alloc_large 64+4
2148         adiw r30, 1
2149         movw ctx0, r30
2150         movw dst0, r24
2151         movw msg0, r22
2152         movw len0, r18
2153         movw len2, r20
2154         movw r24, ctx0
2155         ldi r30, pm_lo8(init_lut)
2156         ldi r31, pm_hi8(init_lut)
2157         add r30, r16
2158         adc r31, r1
2159         icall
2160 20:
2161         mov r18, len2
2162         or  r18, len3
2163         breq 50f
2164         movw r24, ctx0
2165         movw r22, msg0
2166         rcall bmw_small_nextBlock
2167         ldi r20, 2
2168         sub len1, r20
2169         sbc len2, r1
2170         sbc len3, r1
2171         ldi r20, 64
2172         add msg0, r20
2173         adc msg1, r1
2174         rjmp 20b
2175 50:
2176         movw r24, ctx0
2177         movw r22, msg0
2178         movw r20, len0
2179         rcall bmw_small_lastBlock
2180         movw r24, dst0
2181         movw r22, ctx0
2182         ldi r30, pm_lo8(c2h_lut)
2183         ldi r31, pm_hi8(c2h_lut)
2184         add r30, r16
2185         adc r31, r1
2186         icall
2187         stack_free_large 64+4
2188         pop_range 2, 11
2189         pop r16
2190         ret
2191
2192 init_lut:
2193         rjmp bmw224_init
2194         rjmp bmw256_init
2195 c2h_lut:
2196         rjmp bmw224_ctx2hash
2197         rjmp bmw256_ctx2hash