]> git.cryptolib.org Git - avr-crypto-lib.git/blob - bmw/bmw_small-asm.S
even more asm fun for BMW
[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) 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-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         mov r25, r24
542         lsl r25
543         lsl r25
544         ldi r30, lo8(const_lut)
545         ldi r31, hi8(const_lut)
546         add r30, r25
547         adc r31, r1
548         lpm acc0, Z+
549         lpm acc1, Z+
550         lpm acc2, Z+
551         lpm acc3, Z+
552
553         mov r20, j
554         andi r20, 0x0f
555         lsl r20
556         lsl r20
557         movw r26, m0
558         add r26, r20
559         adc r27, r1
560         ld r22, X+
561         ld r23, X+
562         ld r24, X+
563         ld r25, X+
564         mov r20, j
565         rcall rotl_addel
566         add acc0, r22
567         adc acc1, r23
568         adc acc2, r24
569         adc acc3, r25
570
571         subi j, -3
572         mov r20, j
573         andi r20, 0x0f
574         lsl r20
575         lsl r20
576         movw r26, m0
577         add r26, r20
578         adc r27, r1
579         ld r22, X+
580         ld r23, X+
581         ld r24, X+
582         ld r25, X+
583         mov r20, j
584         rcall rotl_addel
585         add acc0, r22
586         adc acc1, r23
587         adc acc2, r24
588         adc acc3, r25
589
590         subi j, -7
591         mov r20, j
592         andi r20, 0x0f
593         lsl r20
594         lsl r20
595         movw r26, m0
596         add r26, r20
597         adc r27, r1
598         ld r22, X+
599         ld r23, X+
600         ld r24, X+
601         ld r25, X+
602         mov r20, j
603         rcall rotl_addel
604         sub acc0, r22
605         sbc acc1, r23
606         sbc acc2, r24
607         sbc acc3, r25
608
609         subi j, 3
610         mov r20, j
611         andi r20, 0x0f
612         lsl r20
613         lsl r20
614         movw r26, h0
615         add r26, r20
616         adc r27, r1
617         ld r22, X+
618         ld r23, X+
619         ld r24, X+
620         ld r25, X+
621         eor r22, acc0
622         eor r23, acc1
623         eor r24, acc2
624         eor r25, acc3
625         pop_range 8, 16
626         ret
627
628 /*******************************************************************************
629 * uint32_t bmw_small_expand1(uint8_t j, const void* m, const void* h, const uint32_t* q){
630 *       uint32_t(*s[])(uint32_t) = {bmw_small_s1, bmw_small_s2, bmw_small_s3, bmw_small_s0};
631 *       uint32_t r;
632 *       uint8_t i;
633 *       r = addelement(j, m, h);
634 *       i=15;
635 *       do{
636 *               r += s[i%4](q[j+i]);
637 *       }while(i--!=0);
638 *       return r;
639 *
640 * param j: r24
641 * param m: r22:r23
642 * param h: r20:r21
643 * param q: r18:r19
644 */
645 acc0 =  2
646 acc1 =  3
647 acc2 =  4
648 acc3 =  5
649 .global bmw_small_expand1
650 bmw_small_expand1:
651         push_range 28, 29
652         movw r28, r18
653         mov r18, r24
654         lsl r18
655         lsl r18
656         add r28, r18
657         adc r29, r1
658         rcall addelement
659         push_range 2, 5
660         push r16
661         ldi r16, 4
662         movw acc0, r22
663         movw acc2, r24
664 1:
665         ld r22, Y+
666         ld r23, Y+
667         ld r24, Y+
668         ld r25, Y+
669         rcall bmw_small_s1
670         add acc0, r22
671         adc acc1, r23
672         adc acc2, r24
673         adc acc3, r25
674         ld r22, Y+
675         ld r23, Y+
676         ld r24, Y+
677         ld r25, Y+
678         rcall bmw_small_s2
679         add acc0, r22
680         adc acc1, r23
681         adc acc2, r24
682         adc acc3, r25
683         ld r22, Y+
684         ld r23, Y+
685         ld r24, Y+
686         ld r25, Y+
687         rcall bmw_small_s3
688         add acc0, r22
689         adc acc1, r23
690         adc acc2, r24
691         adc acc3, r25
692         ld r22, Y+
693         ld r23, Y+
694         ld r24, Y+
695         ld r25, Y+
696         rcall bmw_small_s0
697         add acc0, r22
698         adc acc1, r23
699         adc acc2, r24
700         adc acc3, r25
701         dec r16
702         brne 1b
703 expand1_exit:
704         movw r22, acc0
705         movw r24, acc2
706         pop r16
707         pop_range 2, 5
708         pop_range 28, 29
709         ret
710
711 /*******************************************************************************
712 * uint32_t bmw_small_expand2(uint8_t j, const void* m, const void* h, const uint32_t* q){
713 *       uint32_t(*rf[])(uint32_t) = {bmw_small_r1, bmw_small_r2, bmw_small_r3,
714 *                                    bmw_small_r4, bmw_small_r5, bmw_small_r6,
715 *                                                            bmw_small_r7};
716 *       uint32_t r;
717 *       uint8_t i;
718 *       r = addelement(j, m, h);
719 *       for(i=0; i<14; i+=2){
720 *               r += q[j+i];
721 *       }
722 *       for(i=0; i<14; i+=2){
723 *               r += rf[i/2](q[j+i+1]);
724 *       }
725 *       r += bmw_small_s4(q[j+14]);
726 *       r += bmw_small_s5(q[j+15]);
727 *       return r;
728 * }
729 */
730 expand2_jumptable:
731         ret
732         rjmp bmw_small_r1
733         ret
734         rjmp bmw_small_r2
735         ret
736         rjmp bmw_small_r3
737         ret
738         rjmp bmw_small_r4
739         ret
740         rjmp bmw_small_r5
741         ret
742         rjmp bmw_small_r6
743         ret
744         rjmp bmw_small_r7
745         rjmp bmw_small_s4
746         rjmp bmw_small_s5
747
748 .global bmw_small_expand2
749 bmw_small_expand2:
750         push_range 28, 29
751         movw r28, r18
752         mov r18, r24
753         lsl r18
754         lsl r18
755         add r28, r18
756         adc r29, r1
757         rcall addelement
758         push_range 2, 5
759         push r16
760         ldi r16, 16
761         movw acc0, r22
762         movw acc2, r24
763         ldi r30, pm_lo8(expand2_jumptable)
764         ldi r31, pm_hi8(expand2_jumptable)
765 1:
766         ld r22, Y+
767         ld r23, Y+
768         ld r24, Y+
769         ld r25, Y+
770         push r30
771         push r31
772         icall
773         pop r31
774         pop r30
775         adiw r30, 1
776         add acc0, r22
777         adc acc1, r23
778         adc acc2, r24
779         adc acc3, r25
780         dec r16
781         brne 1b
782         rjmp expand1_exit
783
784 /*******************************************************************************
785 * void bmw_small_f1(uint32_t* q, const void* m, const void* h){
786 *       uint8_t i;
787 *       q[16] = bmw_small_expand1(0, m, h, q);
788 *       q[17] = bmw_small_expand1(1, m, h, q);
789 *       for(i=2; i<16; ++i){
790 *               q[16+i] = bmw_small_expand2(i, m, h, q);
791 *       }
792 * }
793 */
794 m0 =  2
795 m1 =  3
796 h0 =  4
797 h1 =  5
798 q0 =  6
799 q1 =  7
800 .global bmw_small_f1
801 bmw_small_f1:
802 ;       push_range 2, 7
803 ;       push_range 28, 29
804         push r16
805         movw q0, r24
806         movw m0, r22
807         movw h0, r20
808         movw r28, q0
809         adiw r28, 63
810         adiw r28, 1
811         clr r24
812         clr r25 /* not required */
813         movw r18, q0
814         rcall bmw_small_expand1
815         st Y+, r22
816         st Y+, r23
817         st Y+, r24
818         st Y+, r25
819         ldi r16, 1
820         mov r24, r16
821         clr r25 /* not required */
822         movw r22, m0
823         movw r20, h0
824         movw r18, q0
825         rcall bmw_small_expand1
826         st Y+, r22
827         st Y+, r23
828         st Y+, r24
829         st Y+, r25
830         inc r16
831 1:
832         mov r24, r16
833         movw r22, m0
834         movw r20, h0
835         movw r18, q0
836         rcall bmw_small_expand2
837         st Y+, r22
838         st Y+, r23
839         st Y+, r24
840         st Y+, r25
841         inc r16
842         cpi r16, 16
843         brne 1b
844         pop r16
845 ;       pop_range 28, 29
846 ;       pop_range 2, 7
847         ret
848
849 /*******************************************************************************
850 * uint16_t hack_table[5]   PROGMEM = { 0x0311, 0xDDB3, 0x2A79, 0x07AA, 0x51C2 };
851 * uint8_t  offset_table[5] PROGMEM = { 4+16, 6+16, 9+16, 12+16, 13+16 };
852 *
853 * void bmw_small_f0(uint32_t* h, const void* m, uint32_t* q){
854 *       uint16_t hack_reg;
855 *       uint8_t c,i,j;
856 *       uint32_t(*s[])(uint32_t)={ bmw_small_s0, bmw_small_s1, bmw_small_s2,
857 *                                  bmw_small_s3, bmw_small_s4 };
858 *       for(i=0; i<16; ++i){
859 *               ((uint32_t*)h)[i] ^= ((uint32_t*)m)[i];
860 *       }
861 *       dump_x(h, 16, 'T');
862 *       memset(q, 0, 4*16);
863 *       c=4;
864 *       do{
865 *               i=15;
866 *               j=pgm_read_byte(offset_table+c);
867 *               hack_reg=pgm_read_word(&(hack_table[c]));
868 *               do{
869 *                       if(hack_reg&1){
870 *                               q[i]-= h[j&15];
871 *                       }else{
872 *                               q[i]+= h[j&15];
873 *                       }
874 *                       --j;
875 *                       hack_reg>>= 1;
876 *               }while(i--!=0);
877 *       }while(c--!=0);
878 *       dump_x(q, 16, 'W');
879 *       for(i=0; i<16; ++i){
880 *               q[i] = s[i%5](q[i]);
881 *       }
882 *       for(i=0; i<16; ++i){
883 *               ((uint32_t*)h)[i] ^= ((uint32_t*)m)[i];
884 *       }
885 *       for(i=0; i<16; ++i){
886 *               q[i] += h[(i+1)&0xf];
887 *       }
888 * }
889 *
890 * param h: r24:r25
891 * param m: r22:r23
892 * param q: r20:r21
893 */
894 h0   =  24
895 h1   =  25
896 m0   =  22
897 m1   =  23
898 q0   =  20
899 q1   =  21
900 acc0 =  4
901 acc1 =  5
902 acc2 =  6
903 acc3 =  7
904 bcc0 =  8
905 bcc1 =  9
906 bcc2 = 10
907 bcc3 = 11
908 hack = 16
909
910 f0_helper:
911 20:
912         ldd acc0, Z+0
913         ldd acc1, Z+1
914         ldd acc2, Z+2
915         ldd acc3, Z+3
916         ld bcc0, X+
917         ld bcc1, X+
918         ld bcc2, X+
919         ld bcc3, X+
920         lsr r17
921         ror r16
922         brcs l20_sub
923         add acc0, bcc0
924         adc acc1, bcc1
925         adc acc2, bcc2
926         adc acc3, bcc3
927         rjmp l20_post
928 l20_sub:
929         sub acc0, bcc0
930         sbc acc1, bcc1
931         sbc acc2, bcc2
932         sbc acc3, bcc3
933 l20_post:
934         st Z+, acc0
935         st Z+, acc1
936         st Z+, acc2
937         st Z+, acc3
938         dec r18
939         brne 20b
940         ret
941
942 f0_jumptable:
943         rjmp bmw_small_s0
944         rjmp bmw_small_s1
945         rjmp bmw_small_s2
946         rjmp bmw_small_s3
947         rjmp bmw_small_s4
948         rjmp bmw_small_s0
949         rjmp bmw_small_s1
950         rjmp bmw_small_s2
951         rjmp bmw_small_s3
952         rjmp bmw_small_s4
953         rjmp bmw_small_s0
954         rjmp bmw_small_s1
955         rjmp bmw_small_s2
956         rjmp bmw_small_s3
957         rjmp bmw_small_s4
958         rjmp bmw_small_s0
959
960 .global bmw_small_f0
961 bmw_small_f0:
962 ;       push_range 28, 29
963 ;    push_range 4, 11
964 ;    push_range 16, 17
965     /* h[i] ^= m[i]; q[i]= 0 */
966         movw r26, h0 ; h
967         movw r30, m0 ; m
968         movw r28, q0 ; q
969         ldi r18, 64
970 1:  ld r0, X
971     ld r19, Z+
972     eor r0, r19
973     st X+, r0
974     st Y+, r1
975     dec r18
976     brne 1b
977 ;------
978     ldi r17, 0x88
979     ldi r16, 0xC0
980     movw r26, h0 ; X = h
981     adiw r26, 5*4
982     ldi r18, 16-5
983     movw r30, q0 ; Z = q
984     rcall f0_helper
985     movw r26, h0 ; X = h
986     ldi r18,    5
987     rcall f0_helper
988 ;---
989     ldi r17, 0xCD
990     ldi r16, 0xBB
991     movw r26, h0 ; X = h
992     adiw r26, 7*4
993     ldi r18, 16-7
994     movw r30, q0 ; Z = q
995     rcall f0_helper
996     movw r26, h0 ; X = h
997     ldi r18,    7
998     rcall f0_helper
999 ;---
1000     ldi r17, 0x9E
1001     ldi r16, 0x54
1002     movw r26, h0 ; X = h
1003     adiw r26, 10*4
1004     ldi r18, 16-10
1005     movw r30, q0 ; Z = q
1006     rcall f0_helper
1007     movw r26, h0 ; X = h
1008     ldi r18,   10
1009     rcall f0_helper
1010 ;---
1011     ldi r17, 0x55
1012     ldi r16, 0xE0
1013     movw r26, h0 ; X = h
1014     adiw r26, 13*4
1015     ldi r18, 16-13
1016     movw r30, q0 ; Z = q
1017     rcall f0_helper
1018     movw r26, h0 ; X = h
1019     ldi r18,  13
1020     rcall f0_helper
1021 ;---
1022     ldi r17, 0x43
1023     ldi r16, 0x8A
1024     movw r26, h0 ; X = h
1025     adiw r26, 14*4
1026     ldi r18, 16-14
1027     movw r30, q0 ; Z = q
1028     rcall f0_helper
1029     movw r26, h0 ; X = h
1030     ldi r18,  14
1031     rcall f0_helper
1032 ;--------------- h[i] ^= m[i]
1033         movw r26, h0 ; h
1034         movw r30, m0 ; m
1035         ldi r18, 64
1036 25: ld r0, X
1037     ld r19, Z+
1038     eor r0, r19
1039     st X+, r0
1040     dec r18
1041     brne 25b
1042 ;--------------- q[i] = s[i%5](q[i])
1043         ldi r16, 16
1044         ldi r30, pm_lo8(f0_jumptable)
1045         ldi r31, pm_hi8(f0_jumptable)
1046     movw bcc0, r30
1047     movw bcc2, h0 ; h
1048     movw acc0, q0 ; q
1049     movw r28,  q0 ; Y = q
1050 30:
1051         ldd r22, Y+0
1052         ldd r23, Y+1
1053         ldd r24, Y+2
1054         ldd r25, Y+3
1055         icall
1056         st Y+, r22
1057         st Y+, r23
1058         st Y+, r24
1059         st Y+, r25
1060         movw r30, bcc0
1061         adiw r30, 1
1062         movw bcc0, r30
1063         dec r16
1064         brne 30b
1065 ;--------------- q[i] += h[(i+1)%16]
1066         movw r30, acc0 ; q
1067         movw r26, bcc2 ; h
1068         adiw r26, 4
1069         ldi r18, 15
1070 40:
1071         ld acc0, Z
1072         ld acc1, X+
1073         add acc0, acc1
1074         st Z+, acc0
1075         ld acc0, Z
1076         ld acc1, X+
1077         adc acc0, acc1
1078         st Z+, acc0
1079         ld acc0, Z
1080         ld acc1, X+
1081         adc acc0, acc1
1082         st Z+, acc0
1083         ld acc0, Z
1084         ld acc1, X+
1085         adc acc0, acc1
1086         st Z+, acc0
1087         dec r18
1088         brne 40b
1089         movw r26, bcc2 ; h
1090         ld acc0, Z
1091         ld acc1, X+
1092         add acc0, acc1
1093         st Z+, acc0
1094         ld acc0, Z
1095         ld acc1, X+
1096         adc acc0, acc1
1097         st Z+, acc0
1098         ld acc0, Z
1099         ld acc1, X+
1100         adc acc0, acc1
1101         st Z+, acc0
1102         ld acc0, Z
1103         ld acc1, X+
1104         adc acc0, acc1
1105         st Z+, acc0
1106
1107 ;   pop_range 16, 17
1108 ;   pop_range 4, 11
1109 ;       pop_range 28, 29
1110     ret
1111
1112 /*******************************************************************************
1113 * void bmw_small_f2(uint32_t* h, const uint32_t* q, const void* m){
1114 *       uint32_t xl=0, xh;
1115 *       uint8_t i;
1116 *       for(i=16;i<24;++i){
1117 *               xl ^= q[i];
1118 *       }
1119 *       xh = xl;
1120 *       for(i=24;i<32;++i){
1121 *               xh ^= q[i];
1122 *       }
1123 *       memcpy(h, m, 16*4);
1124 *       h[0] ^= SHL32(xh, 5) ^ SHR32(q[16], 5);
1125 *       h[5] ^= SHL32(xh, 6) ^ SHR32(q[21], 6);
1126 *       h[3] ^= SHR32(xh, 1) ^ SHL32(q[19], 5);
1127 *       h[4] ^= SHR32(xh, 3) ^ q[20];
1128 *       h[6] ^= SHR32(xh, 4) ^ SHL32(q[22], 6);
1129 *       h[2] ^= SHR32(xh, 5) ^ SHL32(q[18], 5);
1130 *       h[1] ^= SHR32(xh, 7) ^ SHL32(q[17], 8);
1131 *       h[7] ^= SHR32(xh,11) ^ SHL32(q[23], 2);
1132 *       for(i=0; i<8; ++i){
1133 *               h[i] += xl ^ q[24+i] ^ q[i];
1134 *       }
1135 *       for(i=0; i<8; ++i){
1136 *               h[8+i] ^= xh ^ q[24+i];
1137 *               h[8+i] += ROTL32(h[(4+i)%8],i+9);
1138 *       }
1139 *       h[11] += SHL32(xl, 4) ^ q[18] ^ q[11];
1140 *       h[10] += SHL32(xl, 6) ^ q[17] ^ q[10];
1141 *       h[ 8] += SHL32(xl, 8) ^ q[23] ^ q[ 8];
1142 *       h[15] += SHR32(xl, 2) ^ q[22] ^ q[15];
1143 *       h[12] += SHR32(xl, 3) ^ q[19] ^ q[12];
1144 *       h[13] += SHR32(xl, 4) ^ q[20] ^ q[13];
1145 *       h[ 9] += SHR32(xl, 6) ^ q[16] ^ q[ 9];
1146 *       h[14] += SHR32(xl, 7) ^ q[21] ^ q[14];
1147 * }
1148 *
1149 * param h: r24:r25
1150 * param q: r22:r23
1151 * param m: r20:r21
1152 */
1153 xl0 =  2
1154 xl1 =  3
1155 xl2 =  4
1156 xl3 =  5
1157 xh0 =  6
1158 xh1 =  7
1159 xh2 =  8
1160 xh3 =  9
1161 q0  = 10
1162 q1  = 11
1163 h0  = 12
1164 h1  = 13
1165 t0  = 14
1166 t1  = 15
1167 t2  = 16
1168 t3  = 17
1169
1170
1171 .macro modify_h_2 addr:req
1172         ldd r22, Y+\addr*4+0
1173         ldd r23, Y+\addr*4+1
1174         ldd r24, Y+\addr*4+2
1175         ldd r25, Y+\addr*4+3
1176         eor r22, t0
1177         eor r23, t1
1178         eor r24, t2
1179         eor r25, t3
1180         ldd r0, Z+\addr*4+0
1181         add r0, r22
1182         std Z+\addr*4+0, r0
1183         ldd r0, Z+\addr*4+1
1184         adc r0, r23
1185         std Z+\addr*4+1, r0
1186         ldd r0, Z+\addr*4+2
1187         adc r0, r24
1188         std Z+\addr*4+2, r0
1189         ldd r0, Z+\addr*4+3
1190         adc r0, r25
1191         std Z+\addr*4+3, r0
1192 .endm
1193
1194 tshiftr:
1195         lsr t3
1196         ror t2
1197         ror t1
1198         ror t0
1199         dec r20
1200         brne tshiftr
1201         ret
1202
1203 tshiftl:
1204         lsl t0
1205         rol t1
1206         rol t2
1207         rol t3
1208         dec r20
1209         brne tshiftl
1210         ret
1211
1212 .global bmw_small_f2
1213 bmw_small_f2:
1214     /* memcpy(h, m, 64) */
1215         movw r26, r24
1216         movw r30, r20
1217         ldi r18, 64
1218 1:      ld r0, Z+
1219         st X+, r0
1220         dec r18
1221         brne 1b
1222 ;       push_range 28, 29
1223 ;       push_range  2, 17
1224         movw q0, r22
1225         movw h0, r24
1226         /* calc xl */
1227 /*      for(i=16;i<24;++i){
1228                 xl ^= q[i];
1229         }
1230 */
1231         movw r26, q0
1232         adiw r26, 63
1233         adiw r26, 1 ; X points at q[16]
1234         ld xl0, X+
1235         ld xl1, X+
1236         ld xl2, X+
1237         ld xl3, X+
1238         ldi r18, 8-1
1239 20: ld r0, X+
1240         eor xl0, r0
1241         ld r0, X+
1242         eor xl1, r0
1243         ld r0, X+
1244         eor xl2, r0
1245         ld r0, X+
1246         eor xl3, r0
1247         dec r18
1248         brne 20b
1249         /* calc xh */
1250 /*  xh = xl
1251         for(i=24;i<32;++i){
1252                 xh ^= q[i];
1253         }
1254 */
1255         movw xh0, xl0
1256         movw xh2, xl2
1257         ldi r18, 8
1258 25: ld r0, X+
1259         eor xh0, r0
1260         ld r0, X+
1261         eor xh1, r0
1262         ld r0, X+
1263         eor xh2, r0
1264         ld r0, X+
1265         eor xh3, r0
1266         dec r18
1267         brne 25b
1268 /* h[0]..h[7] */
1269         movw r30, h0
1270         movw r28, q0
1271         adiw r28, 60 ; Y points at q[15]
1272 /*      h[0] ^= SHL32(xh, 5) ^ SHR32(q[16], 5); */
1273         movw t0, xh0
1274         movw t2, xh2
1275         ldi r20, 5
1276         rcall tshiftl
1277         ldd r22, Y+4
1278         ldd r23, Y+5
1279         ldd r24, Y+6
1280         ldd r25, Y+7
1281         ldi r20, 5
1282         rcall shiftr32
1283         eor r22, t0
1284         eor r23, t1
1285         eor r24, t2
1286         eor r25, t3
1287         ldd r0, Z+0
1288         eor r22, r0
1289         ldd r0, Z+1
1290         eor r23, r0
1291         ldd r0, Z+2
1292         eor r24, r0
1293         ldd r0, Z+3
1294         eor r25, r0
1295         std Z+0, r22
1296         std Z+1, r23
1297         std Z+2, r24
1298         std Z+3, r25
1299 /*      h[5] ^= SHL32(xh, 6) ^ SHR32(q[21], 6); */
1300         lsl t0
1301         rol t1
1302         rol t2
1303         rol t3
1304         ldd r22, Y+24
1305         ldd r23, Y+25
1306         ldd r24, Y+26
1307         ldd r25, Y+27
1308         ldi r20, 6
1309         rcall shiftr32
1310         eor r22, t0
1311         eor r23, t1
1312         eor r24, t2
1313         eor r25, t3
1314         ldd r0, Z+20
1315         eor r22, r0
1316         ldd r0, Z+21
1317         eor r23, r0
1318         ldd r0, Z+22
1319         eor r24, r0
1320         ldd r0, Z+23
1321         eor r25, r0
1322         std Z+20, r22
1323         std Z+21, r23
1324         std Z+22, r24
1325         std Z+23, r25
1326 /*      h[3] ^= SHR32(xh, 1) ^ SHL32(q[19], 5); */
1327         movw t0, xh0
1328         movw t2, xh2
1329         lsr t3
1330         ror t2
1331         ror t1
1332         ror t0
1333         ldd r22, Y+16
1334         ldd r23, Y+17
1335         ldd r24, Y+18
1336         ldd r25, Y+19
1337         ldi r20, 5
1338         rcall shiftl32
1339         eor r22, t0
1340         eor r23, t1
1341         eor r24, t2
1342         eor r25, t3
1343         ldd r0, Z+12
1344         eor r22, r0
1345         ldd r0, Z+13
1346         eor r23, r0
1347         ldd r0, Z+14
1348         eor r24, r0
1349         ldd r0, Z+15
1350         eor r25, r0
1351         std Z+12, r22
1352         std Z+13, r23
1353         std Z+14, r24
1354         std Z+15, r25
1355 /*      h[4] ^= SHR32(xh, 3) ^ q[20]; */
1356         ldi r20, 2
1357         rcall tshiftr
1358         ldd r22, Y+20
1359         ldd r23, Y+21
1360         ldd r24, Y+22
1361         ldd r25, Y+23
1362         eor r22, t0
1363         eor r23, t1
1364         eor r24, t2
1365         eor r25, t3
1366         ldd r0, Z+16
1367         eor r22, r0
1368         ldd r0, Z+17
1369         eor r23, r0
1370         ldd r0, Z+18
1371         eor r24, r0
1372         ldd r0, Z+19
1373         eor r25, r0
1374         std Z+16, r22
1375         std Z+17, r23
1376         std Z+18, r24
1377         std Z+19, r25
1378 /*      h[6] ^= SHR32(xh, 4) ^ SHL32(q[22], 6); */
1379         lsr t3
1380         ror t2
1381         ror t1
1382         ror t0
1383         ldd r22, Y+28
1384         ldd r23, Y+29
1385         ldd r24, Y+30
1386         ldd r25, Y+31
1387         ldi r20, 6
1388         rcall shiftl32
1389         eor r22, t0
1390         eor r23, t1
1391         eor r24, t2
1392         eor r25, t3
1393         ldd r0, Z+24
1394         eor r22, r0
1395         ldd r0, Z+25
1396         eor r23, r0
1397         ldd r0, Z+26
1398         eor r24, r0
1399         ldd r0, Z+27
1400         eor r25, r0
1401         std Z+24, r22
1402         std Z+25, r23
1403         std Z+26, r24
1404         std Z+27, r25
1405 /*      h[2] ^= SHR32(xh, 5) ^ SHL32(q[18], 5); */
1406         lsr t3
1407         ror t2
1408         ror t1
1409         ror t0
1410         ldd r22, Y+12
1411         ldd r23, Y+13
1412         ldd r24, Y+14
1413         ldd r25, Y+15
1414         ldi r20, 5
1415         rcall shiftl32
1416         eor r22, t0
1417         eor r23, t1
1418         eor r24, t2
1419         eor r25, t3
1420         ldd r0, Z+8
1421         eor r22, r0
1422         ldd r0, Z+9
1423         eor r23, r0
1424         ldd r0, Z+10
1425         eor r24, r0
1426         ldd r0, Z+11
1427         eor r25, r0
1428         std Z+8 , r22
1429         std Z+9 , r23
1430         std Z+10, r24
1431         std Z+11, r25
1432 /*      h[1] ^= SHR32(xh, 7) ^ SHL32(q[17], 8); */
1433         ldi r20, 2
1434         rcall tshiftr
1435         ldd r23, Y+8
1436         ldd r24, Y+9
1437         ldd r25, Y+10
1438         mov r22, t0
1439         eor r23, t1
1440         eor r24, t2
1441         eor r25, t3
1442         ldd r0, Z+4
1443         eor r22, r0
1444         ldd r0, Z+5
1445         eor r23, r0
1446         ldd r0, Z+6
1447         eor r24, r0
1448         ldd r0, Z+7
1449         eor r25, r0
1450         std Z+4 , r22
1451         std Z+5 , r23
1452         std Z+6 , r24
1453         std Z+7 , r25
1454 /*      h[7] ^= SHR32(xh,11) ^ SHL32(q[23], 2); */
1455         ldi r20, 4
1456         rcall tshiftr
1457         ldd r22, Y+32
1458         ldd r23, Y+33
1459         ldd r24, Y+34
1460         ldd r25, Y+35
1461         ldi r20, 2
1462         rcall shiftl32
1463         eor r22, t0
1464         eor r23, t1
1465         eor r24, t2
1466         eor r25, t3
1467         ldd r0, Z+28
1468         eor r22, r0
1469         ldd r0, Z+29
1470         eor r23, r0
1471         ldd r0, Z+30
1472         eor r24, r0
1473         ldd r0, Z+31
1474         eor r25, r0
1475         std Z+28, r22
1476         std Z+29, r23
1477         std Z+30, r24
1478         std Z+31, r25
1479 /*      for(i=0; i<8; ++i){
1480 *               h[i] += xl ^ q[24+i] ^ q[i];
1481 *       }
1482 */
1483         movw r26, q0
1484         movw r28, q0
1485         adiw r28, 63
1486         adiw r28, 24*4-63
1487         ldi r18, 8
1488 10:
1489         movw t0, xl0
1490         movw t2, xl2
1491         ld r0, X+
1492         eor t0, r0
1493         ld r0, X+
1494         eor t1, r0
1495         ld r0, X+
1496         eor t2, r0
1497         ld r0, X+
1498         eor t3, r0
1499         ld r0, Y+
1500         eor t0, r0
1501         ld r0, Y+
1502         eor t1, r0
1503         ld r0, Y+
1504         eor t2, r0
1505         ld r0, Y+
1506         eor t3, r0
1507         ldd r22, Z+0
1508         ldd r23, Z+1
1509         ldd r24, Z+2
1510         ldd r25, Z+3
1511         add r22, t0
1512         adc r23, t1
1513         adc r24, t2
1514         adc r25, t3
1515         st Z+, r22
1516         st Z+, r23
1517         st Z+, r24
1518         st Z+, r25
1519         dec r18
1520         brne 10b
1521         ; Z points to h[8]
1522 /*      for(i=0; i<8; ++i){
1523                 h[8+i] ^= xh ^ q[24+i];
1524                 h[8+i] += ROTL32(h[(4+i)%8],i+9);
1525         }
1526 */
1527         ; Z points at h[8]
1528 ;       clr r18
1529         sbiw r28, 8*4 ; Y points at q[24]
1530         movw r26, r30
1531         sbiw r26, 4*4 ; X points at h[4]
1532 15:
1533         ldd t0, Z+0
1534         ldd t1, Z+1
1535         ldd t2, Z+2
1536         ldd t3, Z+3
1537         eor t0, xh0
1538         eor t1, xh1
1539         eor t2, xh2
1540         eor t3, xh3
1541         ld r0, Y+
1542         eor t0, r0
1543         ld r0, Y+
1544         eor t1, r0
1545         ld r0, Y+
1546         eor t2, r0
1547         ld r0, Y+
1548         eor t3, r0
1549         ld r22, X+
1550         ld r23, X+
1551         ld r24, X+
1552         ld r25, X+
1553         mov r20, r18
1554         rcall rotl32p9
1555         add t0, r22
1556         adc t1, r23
1557         adc t2, r24
1558         adc t3, r25
1559         st Z+, t0
1560         st Z+, t1
1561         st Z+, t2
1562         st Z+, t3
1563         inc r18
1564         cpi r18, 4
1565         brne 16f
1566         movw r26, h0
1567 16:
1568         sbrs r18, 3
1569         rjmp 15b
1570         sbiw r30, 4*8 ; adjust Z to point at h[8]
1571         sbiw r28, 16*4-1
1572         sbiw r28, 1   ; adjust Y to point at q[16]
1573         movw r26, r28
1574         sbiw r26, 7*4 ; adjust X to point at q[9]
1575         ldi r18, 7*4
1576 20: /* now we do the memxor stuff */
1577         ld t0, X
1578         ld t1, Y+
1579         eor t0, t1
1580         st X+, t0
1581         dec r18
1582         brne 20b
1583         ; X points at q[16]
1584         ; Y points at q[23]
1585         sbiw r26, 4*8 ; X points at q[8]
1586
1587         clr t0
1588         mov t1, xl0
1589         mov t2, xl1
1590         mov t3, xl2
1591 /*      h[ 8] += SHL32(xl, 8) ^ q[23] ^ q[ 8]; */
1592         ld r22, X+
1593         ld r23, X+
1594         ld r24, X+
1595         ld r25, X+
1596         ld r0, Y+
1597         eor r22, r0
1598         ld r0, Y+
1599         eor r23, r0
1600         ld r0, Y+
1601         eor r24, r0
1602         ld r0, Y+
1603         eor r25, r0
1604         eor r22, t0
1605         eor r23, t1
1606         eor r24, t2
1607         eor r25, t3
1608         ld r0, Z
1609         add r0, r22
1610         st Z+, r0
1611         ld r0, Z
1612         adc r0, r23
1613         st Z+, r0
1614         ld r0, Z
1615         adc r0, r24
1616         st Z+, r0
1617         ld r0, Z
1618         adc r0, r25
1619         st Z+, r0
1620         movw r28, r26
1621         ; Z points at h[9]
1622         ; X points at q[9] but we won't need it anymore
1623         ; Y points at q[9]
1624 /*      h[11] += SHL32(xl, 4) ^ q[11]; */
1625         movw t0, xl0
1626         movw t2, xl2
1627         ldi r20, 4
1628         rcall tshiftl
1629         modify_h_2 2
1630 /*      h[10] += SHL32(xl, 6) ^ q[10]; */
1631         ldi r20, 2
1632         rcall tshiftl
1633         modify_h_2 1
1634 /*      h[15] += SHR32(xl, 2) ^ q[15]; */
1635         movw t0, xl0
1636         movw t2, xl2
1637         ldi r20, 2
1638         rcall tshiftr
1639         modify_h_2 6
1640 /*      h[12] += SHR32(xl, 3) ^ q[12]; */
1641         ldi r20, 1
1642         rcall tshiftr
1643         modify_h_2 3
1644 /*      h[13] += SHR32(xl, 4) ^ q[13]; */
1645         ldi r20, 1
1646         rcall tshiftr
1647         modify_h_2 4
1648 /*      h[ 9] += SHR32(xl, 6) ^ q[ 9]; */
1649         ldi r20, 2
1650         rcall tshiftr
1651         modify_h_2 0
1652 /*      h[14] += SHR32(xl, 7) ^ q[14]; */
1653         ldi r20, 1
1654         rcall tshiftr
1655         modify_h_2 5
1656 bmw_small_f2_exit:
1657 ;       pop_range  2, 17
1658 ;       pop_range 28, 29
1659         ret
1660
1661 #if DEBUG_FUNCTIONS
1662
1663 cli_putb:
1664         push r2
1665         push_range 18, 26
1666         push_range 30, 31
1667         mov r2, r24
1668         swap r24
1669         andi r24, 0xf
1670         ldi r30, lo8(hextable)
1671         ldi r31, hi8(hextable)
1672         add r30, r24
1673         adc r31, r1
1674         lpm r24, Z
1675         clr r25
1676         call cli_putc
1677         mov r24, r2
1678         andi r24, 0xf
1679         ldi r30, lo8(hextable)
1680         ldi r31, hi8(hextable)
1681         add r30, r24
1682         adc r31, r1
1683         lpm r24, Z
1684         clr r25
1685         call cli_putc
1686         pop_range 30, 31
1687         pop_range 18, 26
1688         pop r2
1689         ret
1690 hextable:
1691         .byte '0', '1', '2', '3', '4', '5', '6', '7'
1692         .byte '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
1693
1694 cli_putchar:
1695         push_range 18, 31
1696         call cli_putc
1697         pop_range 18, 31
1698         ret
1699
1700 #endif
1701
1702 /*******************************************************************************
1703 * void bmw_small_nextBlock(bmw_small_ctx_t* ctx, const void* block){
1704 *       uint32_t q[32];
1705 *       dump_x(block, 16, 'M');
1706 *       bmw_small_f0(ctx->h, block, q);
1707 *       dump_x(q, 16, 'Q');
1708 *       bmw_small_f1(q, block, ctx->h);
1709 *       dump_x(q, 32, 'Q');
1710 *       bmw_small_f2(ctx->h, q, block);
1711 *       ctx->counter += 1;
1712 *       ctx_dump(ctx);
1713 * }
1714 *
1715 * param ctx:   r24:r25
1716 * param block: r22:r23
1717 */
1718 h0 =  2
1719 h1 =  3
1720 b0 =  4
1721 b1 =  5
1722 q0 =  6
1723 q1 =  7
1724 .global bmw_small_nextBlock
1725 .global bmw224_nextBlock
1726 .global bmw256_nextBlock
1727 bmw_small_nextBlock:
1728 bmw224_nextBlock:
1729 bmw256_nextBlock:
1730         push_range 28, 29
1731         push_range  2, 17
1732         stack_alloc_large 32*4, 30, 31
1733         adiw r30, 1
1734         movw q0, r30
1735         movw h0, r24
1736         movw b0, r22
1737         /* increment counter */
1738         movw r30, r24
1739         adiw r30, 60
1740         ldd r22, Z+4
1741         ldd r23, Z+5
1742         ldd r24, Z+6
1743         ldd r25, Z+7
1744         ldi r21, 1
1745         add r22, r21
1746         adc r23, r1
1747         adc r24, r1
1748         adc r25, r1
1749         std Z+4, r22
1750         std Z+5, r23
1751         std Z+6, r24
1752         std Z+7, r25
1753         /* call bmw_small_f0(ctx->h, block, q) */
1754         movw r24, h0
1755         movw r22, b0
1756         movw r20, q0
1757         push_ q1, q0, b1, b0, h1, h0
1758         rcall bmw_small_f0
1759         /*      call bmw_small_f1(q, block, ctx->h) */
1760         pop_ 20, 21, 22, 23, 24, 25,
1761         push_ 21, 20, 25, 24, 23, 22
1762         rcall bmw_small_f1
1763         /*      call bmw_small_f2(ctx->h, q, block) */
1764         pop_ 20, 21, 22, 23, 24, 25,
1765         rcall bmw_small_f2
1766         stack_free_large3 32*4
1767         pop_range  2, 17
1768         pop_range 28, 29
1769         ret
1770
1771
1772 /*******************************************************************************
1773 * void bmw224_init(bmw224_ctx_t* ctx){
1774 *       uint8_t i;
1775 *       ctx->h[0] = 0x00010203;
1776 *       for(i=1; i<16; ++i){
1777 *               ctx->h[i] = ctx->h[i-1]+ 0x04040404;
1778 *       }
1779 *       ctx->counter=0;
1780 * }
1781 *
1782 * param ctx:  r24:r25
1783 */
1784 .global bmw224_init
1785 bmw224_init:
1786         movw r26, r24
1787         ldi r22, 0x03
1788         ldi r23, 0x02
1789         ldi r24, 0x01
1790         ldi r25, 0x00
1791 bmw_small_init:
1792         st X+, r22
1793         st X+, r23
1794         st X+, r24
1795         st X+, r25
1796         ldi r18, 16-1
1797         ldi r20, 0x04
1798 1:
1799         add r22, r20
1800         adc r23, r20
1801         adc r24, r20
1802         adc r25, r20
1803         st X+, r22
1804         st X+, r23
1805         st X+, r24
1806         st X+, r25
1807         dec r18
1808         brne 1b
1809         st X+, r1
1810         st X+, r1
1811         st X+, r1
1812         st X+, r1
1813         ret
1814
1815 .global bmw256_init
1816 bmw256_init:
1817         movw r26, r24
1818         ldi r22, 0x43
1819         ldi r23, 0x42
1820         ldi r24, 0x41
1821         ldi r25, 0x40
1822         rjmp bmw_small_init
1823
1824 /*******************************************************************************
1825 * void bmw_small_lastBlock(bmw_small_ctx_t* ctx, const void* block, uint16_t length_b){
1826 *       struct {
1827 *               uint8_t  buffer[64];
1828 *               uint32_t ctr;
1829 *       } pctx;
1830 *       while(length_b >= BMW_SMALL_BLOCKSIZE){
1831 *               bmw_small_nextBlock(ctx, block);
1832 *               length_b -= BMW_SMALL_BLOCKSIZE;
1833 *               block = (uint8_t*)block + BMW_SMALL_BLOCKSIZE_B;
1834 *       }
1835 *       memset(pctx.buffer, 0, 64);
1836 *       memcpy(pctx.buffer, block, (length_b+7)/8);
1837 *       pctx.buffer[length_b>>3] |= 0x80 >> (length_b&0x07);
1838 *       if(length_b+1>64*8-64){
1839 *               bmw_small_nextBlock(ctx, pctx.buffer);
1840 *               memset(pctx.buffer, 0, 64-8);
1841 *               ctx->counter -= 1;
1842 *       }
1843 *       *((uint64_t*)&(pctx.buffer[64-8])) = (uint64_t)(ctx->counter*512LL)+(uint64_t)length_b;
1844 *       bmw_small_nextBlock(ctx, pctx.buffer);
1845 *       uint8_t i;
1846 *       memset(pctx.buffer, 0xaa, 64);
1847 *       for(i=0; i<16;++i){
1848 *               pctx.buffer[i*4] = i+0xa0;
1849 *       }
1850 *       bmw_small_nextBlock((bmw_small_ctx_t*)&pctx, ctx->h);
1851 *       memcpy(ctx->h, pctx.buffer, 64);
1852 * }
1853 *
1854 * param ctx:      r24:r25
1855 * param block:    r22:r23
1856 * param length_b: r20:r21
1857 */
1858 ctx0 =  2
1859 ctx1 =  3
1860 blc0 =  4
1861 blc1 =  5
1862 len0 = 28
1863 len1 = 29
1864 buf0 =  6
1865 buf1 =  7
1866
1867 .global bmw_small_lastBlock
1868 .global bmw224_lastBlock
1869 .global bmw256_lastBlock
1870 bmw_small_lastBlock:
1871 bmw224_lastBlock:
1872 bmw256_lastBlock:
1873 /*      while(length_b >= BMW_SMALL_BLOCKSIZE){
1874                 bmw_small_nextBlock(ctx, block);
1875                 length_b -= BMW_SMALL_BLOCKSIZE;
1876                 block = (uint8_t*)block + BMW_SMALL_BLOCKSIZE_B;
1877         }
1878 */
1879         push_range 2, 7
1880         push_range 28, 29
1881         movw ctx0, r24
1882         movw blc0, r22
1883         movw len0, r20
1884 1:
1885         cpi len1, hi8(512)
1886         brlo 2f
1887         movw r24, ctx0
1888         movw r22, blc0
1889         rcall bmw_small_nextBlock
1890         ldi r24, 64
1891         add blc0, r24
1892         adc blc1, r1
1893         subi len1, hi8(512)
1894         rjmp 1b
1895 2:
1896 /*      struct {
1897                 uint8_t  buffer[64];
1898                 uint32_t ctr;
1899         } pctx;
1900 */
1901         stack_alloc_large 68
1902         adiw r30, 1
1903         movw buf0, r30
1904 /*      memset(pctx.buffer, 0, 64);
1905         memcpy(pctx.buffer, block, (length_b+7)/8);
1906         pctx.buffer[length_b>>3] |= 0x80 >> (length_b&0x07);
1907 */      movw r24, len0
1908         lsr r25
1909         ror r24
1910         lsr r24
1911         lsr r24
1912 ;       inc r24
1913         ldi r23, 63
1914         sub r23, r24
1915         movw r26, blc0
1916         tst r24
1917         breq 301f
1918 30: ld r20, X+
1919         st Z+, r20
1920         dec r24
1921         brne 30b
1922 301:
1923         clr r20
1924         mov r21, len0
1925         ldi r24, 0x80
1926         andi r21, 0x07
1927         breq 305f
1928         ld r20, X+
1929 303:
1930         lsr r24
1931         dec r21
1932         brne 303b
1933 305:
1934         or r20, r24
1935         st Z+, r20
1936         tst r23
1937         breq 32f
1938 31: st Z+, r1
1939         dec r23
1940         brne 31b
1941 32:
1942 /*      if(length_b+1>64*8-64){ ; = 64*7-1 = 447 max(length_b)=511
1943                 bmw_small_nextBlock(ctx, pctx.buffer);
1944                 memset(pctx.buffer, 0, 64-8);
1945                 ctx->counter -= 1;
1946         }
1947 */
1948         tst len1
1949         breq 400f
1950         cpi len0, 192
1951         brlo 400f
1952         movw r24, ctx0
1953         movw r22, buf0
1954         rcall bmw_small_nextBlock
1955         movw r26, buf0
1956         ldi r20, 64-8
1957 350:
1958         st X+, r1
1959         dec r20
1960         brne 350b
1961         movw r30, ctx0
1962         adiw r30, 60
1963         ldd r21, Z+4
1964         ldd r22, Z+5
1965         ldd r23, Z+6
1966         ldd r24, Z+7
1967         subi r21, 1
1968         sbc r22, r1
1969         sbc r23, r1
1970         sbc r24, r1
1971         rjmp 410f
1972 /*      *((uint64_t*)&(pctx.buffer[64-8])) = (uint64_t)(ctx->counter*512LL)+(uint64_t)length_b;
1973         bmw_small_nextBlock(ctx, pctx.buffer);
1974 */
1975 400:
1976         movw r30, ctx0
1977         adiw r30, 60
1978         ldd r21, Z+4
1979         ldd r22, Z+5
1980         ldd r23, Z+6
1981         ldd r24, Z+7
1982 410:
1983         clr r25
1984         lsl r21
1985         rol r22
1986         rol r23
1987         rol r24
1988         rol r25
1989         mov r20, len0
1990         add r21, len1
1991         adc r22, r1
1992         adc r23, r1
1993         adc r24, r1
1994         adc r25, r1
1995         movw r30, buf0
1996         adiw r30, 64-8
1997         st Z+, r20
1998         st Z+, r21
1999         st Z+, r22
2000         st Z+, r23
2001         st Z+, r24
2002         st Z+, r25
2003         st Z+, r1
2004         st Z+, r1
2005         movw r24, ctx0
2006         movw r22, buf0
2007         rcall bmw_small_nextBlock
2008 /*      memset(pctx.buffer, 0xaa, 64);
2009         for(i=0; i<16;++i){
2010                 pctx.buffer[i*4] = i+0xa0;
2011         }
2012 */
2013         ldi r18, 0xa0
2014         ldi r19, 0xaa
2015         movw r26, buf0
2016 500:
2017         st X+, r18
2018         st X+, r19
2019         st X+, r19
2020         st X+, r19
2021         inc r18
2022         sbrs r18, 4
2023         rjmp 500b
2024 /*      bmw_small_nextBlock((bmw_small_ctx_t*)&pctx, ctx->h);
2025         memcpy(ctx->h, pctx.buffer, 64);
2026 */
2027         movw r24, buf0
2028         movw r22, ctx0
2029         rcall bmw_small_nextBlock
2030         ldi r18, 64
2031         movw r26, ctx0
2032         movw r30, buf0
2033 600:
2034         ld r20, Z+
2035         st X+, r20
2036         dec r18
2037         brne 600b
2038
2039         stack_free_large 68
2040         pop_range 28, 29
2041         pop_range 2, 7
2042         ret
2043
2044 /*******************************************************************************
2045 * void bmw224_ctx2hash(void* dest, const bmw224_ctx_t* ctx){
2046 *       memcpy(dest, &(ctx->h[9]), 224/8);
2047 * }
2048 *
2049 * param dest:  r24:r25
2050 * param ctx:   r22:r23
2051 */
2052 .global bmw224_ctx2hash
2053 bmw224_ctx2hash:
2054         movw r26, r24
2055         movw r30, r22
2056         adiw r30, 9*4
2057         ldi r22, 28
2058         rjmp 1f
2059
2060 /*******************************************************************************
2061 * void bmw256_ctx2hash(void* dest, const bmw256_ctx_t* ctx){
2062 *       memcpy(dest, &(ctx->h[8]), 256/8);
2063 * }
2064 *
2065 * param dest:  r24:r25
2066 * param ctx:   r22:r23
2067 */
2068 .global bmw256_ctx2hash
2069 bmw256_ctx2hash:
2070         movw r26, r24
2071         movw r30, r22
2072         adiw r30, 8*4
2073         ldi r22, 32
2074 1:
2075         ld r23, Z+
2076         st X+, r23
2077         dec r22
2078         brne 1b
2079         ret