Imported Upstream version 0.9.1
[platform/upstream/iotivity.git] / extlibs / tinydtls / ecc / asm_arm.inc
1 #define DEC_5 4
2 #define DEC_6 5
3 #define DEC_8 7
4
5 #define DEC(N) uECC_CONCAT(DEC_, N)
6
7 #define REPEAT_1(stuff) stuff
8 #define REPEAT_2(stuff) REPEAT_1(stuff) stuff
9 #define REPEAT_3(stuff) REPEAT_2(stuff) stuff
10 #define REPEAT_4(stuff) REPEAT_3(stuff) stuff
11 #define REPEAT_5(stuff) REPEAT_4(stuff) stuff
12 #define REPEAT_6(stuff) REPEAT_5(stuff) stuff
13 #define REPEAT_7(stuff) REPEAT_6(stuff) stuff
14 #define REPEAT_8(stuff) REPEAT_7(stuff) stuff
15
16 #define REPEAT(N, stuff) uECC_CONCAT(REPEAT_, N)(stuff)
17
18 #define STR2(thing) #thing
19 #define STR(thing) STR2(thing)
20
21 #if (uECC_ASM == uECC_asm_fast)
22
23 static uint32_t vli_add(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right)
24 {
25     uint32_t l_carry = 0;
26     uint32_t l_left;
27     uint32_t l_right;
28     
29     __asm__ volatile (
30         ".syntax unified \n\t"
31         "ldmia %[lptr]!, {%[left]} \n\t"  /* Load left word. */
32         "ldmia %[rptr]!, {%[right]} \n\t" /* Load right word. */
33         "adds %[left], %[right] \n\t"     /* Add first word. */
34         "stmia %[dptr]!, {%[left]} \n\t"  /* Store result word. */
35         
36         /* Now we just do the remaining words with the carry bit (using ADC) */
37         REPEAT(DEC(uECC_WORDS), "ldmia %[lptr]!, {%[left]} \n\t"
38             "ldmia %[rptr]!, {%[right]} \n\t"
39             "adcs %[left], %[right] \n\t"
40             "stmia %[dptr]!, {%[left]} \n\t")
41         
42         "adcs %[carry], %[carry] \n\t" /* Store carry bit in l_carry. */
43     #if (uECC_PLATFORM != uECC_arm_thumb2)
44         ".syntax divided \n\t"
45     #endif
46     #if (uECC_PLATFORM == uECC_arm_thumb)
47         : [dptr] "+l" (p_result), [lptr] "+l" (p_left), [rptr] "+l" (p_right),
48           [carry] "+l" (l_carry), [left] "=l" (l_left), [right] "=l" (l_right)
49     #else
50         : [dptr] "+r" (p_result), [lptr] "+r" (p_left), [rptr] "+r" (p_right),
51           [carry] "+r" (l_carry), [left] "=r" (l_left), [right] "=r" (l_right)
52     #endif
53         :
54         : "cc", "memory"
55     );
56     return l_carry;
57 }
58 #define asm_add 1
59
60 static uint32_t vli_sub(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right)
61 {
62     uint32_t l_carry = 0;
63     uint32_t l_left;
64     uint32_t l_right;
65     
66     __asm__ volatile (
67         ".syntax unified \n\t"
68         "ldmia %[lptr]!, {%[left]} \n\t"  /* Load left word. */
69         "ldmia %[rptr]!, {%[right]} \n\t" /* Load right word. */
70         "subs %[left], %[right] \n\t"     /* Subtract. */
71         "stmia %[dptr]!, {%[left]} \n\t"  /* Store result word. */
72         
73         /* Now we just do the remaining words with the carry bit (using SBC) */
74         REPEAT(DEC(uECC_WORDS), "ldmia %[lptr]!, {%[left]} \n\t"
75             "ldmia %[rptr]!, {%[right]} \n\t"
76             "sbcs %[left], %[right] \n\t"
77             "stmia %[dptr]!, {%[left]} \n\t")
78             
79         "adcs %[carry], %[carry] \n\t" /* Store carry bit in l_carry. */
80     #if (uECC_PLATFORM != uECC_arm_thumb2)
81         ".syntax divided \n\t"
82     #endif
83     #if (uECC_PLATFORM == uECC_arm_thumb)
84         : [dptr] "+l" (p_result), [lptr] "+l" (p_left), [rptr] "+l" (p_right),
85           [carry] "+l" (l_carry), [left] "=l" (l_left), [right] "=l" (l_right)
86     #else
87         : [dptr] "+r" (p_result), [lptr] "+r" (p_left), [rptr] "+r" (p_right),
88           [carry] "+r" (l_carry), [left] "=r" (l_left), [right] "=r" (l_right)
89     #endif
90         :
91         : "cc", "memory"
92     );
93     return !l_carry; // note that on ARM, carry flag set means "no borrow" when subtracting (for some reason...)
94 }
95 #define asm_sub 1
96
97 #if (uECC_PLATFORM != uECC_arm_thumb)
98 #if (uECC_WORDS == 5)
99 static void vli_mult(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right)
100 {
101     register uint32_t *r0 __asm__("r0") = p_result;
102     register uint32_t *r1 __asm__("r1") = p_left;
103     register uint32_t *r2 __asm__("r2") = p_right;
104     
105     __asm__ volatile (
106         ".syntax unified \n\t"
107         "add r0, 12 \n\t"
108         "add r2, 12 \n\t"
109         "ldmia r1!, {r3,r4} \n\t"
110         "ldmia r2!, {r6,r7} \n\t"
111
112         "umull r11, r12, r3, r6 \n\t"
113         "stmia r0!, {r11} \n\t"
114
115         "mov r10, #0 \n\t"
116         "umull r11, r9, r3, r7 \n\t"
117         "adds r12, r11 \n\t"
118         "adc r9, #0 \n\t"
119         "umull r11, r14, r4, r6 \n\t"
120         "adds r12, r11 \n\t"
121         "adcs r9, r14 \n\t"
122         "adc r10, #0 \n\t"
123         "stmia r0!, {r12} \n\t"
124
125         "umull r12, r14, r4, r7 \n\t"
126         "adds r9, r12 \n\t"
127         "adc r10, r14 \n\t"
128         "stmia r0!, {r9, r10} \n\t"
129
130         "sub r0, 28 \n\t"
131         "sub r2, 20 \n\t"
132         "ldmia r2!, {r6,r7,r8} \n\t"
133         "ldmia r1!, {r5} \n\t"
134
135         "umull r11, r12, r3, r6 \n\t"
136         "stmia r0!, {r11} \n\t"
137
138         "mov r10, #0 \n\t"
139         "umull r11, r9, r3, r7 \n\t"
140         "adds r12, r11 \n\t"
141         "adc r9, #0 \n\t"
142         "umull r11, r14, r4, r6 \n\t"
143         "adds r12, r11 \n\t"
144         "adcs r9, r14 \n\t"
145         "adc r10, #0 \n\t"
146         "stmia r0!, {r12} \n\t"
147
148         "mov r11, #0 \n\t"
149         "umull r12, r14, r3, r8 \n\t"
150         "adds r9, r12 \n\t"
151         "adcs r10, r14 \n\t"
152         "adc r11, #0 \n\t"
153         "umull r12, r14, r4, r7 \n\t"
154         "adds r9, r12 \n\t"
155         "adcs r10, r14 \n\t"
156         "adc r11, #0 \n\t"
157         "umull r12, r14, r5, r6 \n\t"
158         "adds r9, r12 \n\t"
159         "adcs r10, r14 \n\t"
160         "adc r11, #0 \n\t"
161         "stmia r0!, {r9} \n\t"
162
163         "ldmia r1!, {r3} \n\t"
164         "mov r12, #0 \n\t"
165         "umull r14, r9, r4, r8 \n\t"
166         "adds r10, r14 \n\t"
167         "adcs r11, r9 \n\t"
168         "adc r12, #0 \n\t"
169         "umull r14, r9, r5, r7 \n\t"
170         "adds r10, r14 \n\t"
171         "adcs r11, r9 \n\t"
172         "adc r12, #0 \n\t"
173         "umull r14, r9, r3, r6 \n\t"
174         "adds r10, r14 \n\t"
175         "adcs r11, r9 \n\t"
176         "adc r12, #0 \n\t"
177         "ldr r14, [r0] \n\t"
178         "adds r10, r14 \n\t"
179         "adcs r11, #0 \n\t"
180         "adc r12, #0 \n\t"
181         "stmia r0!, {r10} \n\t"
182
183         "ldmia r1!, {r4} \n\t"
184         "mov r14, #0 \n\t"
185         "umull r9, r10, r5, r8 \n\t"
186         "adds r11, r9 \n\t"
187         "adcs r12, r10 \n\t"
188         "adc r14, #0 \n\t"
189         "umull r9, r10, r3, r7 \n\t"
190         "adds r11, r9 \n\t"
191         "adcs r12, r10 \n\t"
192         "adc r14, #0 \n\t"
193         "umull r9, r10, r4, r6 \n\t"
194         "adds r11, r9 \n\t"
195         "adcs r12, r10 \n\t"
196         "adc r14, #0 \n\t"
197         "ldr r9, [r0] \n\t"
198         "adds r11, r9 \n\t"
199         "adcs r12, #0 \n\t"
200         "adc r14, #0 \n\t"
201         "stmia r0!, {r11} \n\t"
202
203         "ldmia r2!, {r6} \n\t"
204         "mov r9, #0 \n\t"
205         "umull r10, r11, r5, r6 \n\t"
206         "adds r12, r10 \n\t"
207         "adcs r14, r11 \n\t"
208         "adc r9, #0 \n\t"
209         "umull r10, r11, r3, r8 \n\t"
210         "adds r12, r10 \n\t"
211         "adcs r14, r11 \n\t"
212         "adc r9, #0 \n\t"
213         "umull r10, r11, r4, r7 \n\t"
214         "adds r12, r10 \n\t"
215         "adcs r14, r11 \n\t"
216         "adc r9, #0 \n\t"
217         "ldr r10, [r0] \n\t"
218         "adds r12, r10 \n\t"
219         "adcs r14, #0 \n\t"
220         "adc r9, #0 \n\t"
221         "stmia r0!, {r12} \n\t"
222
223         "ldmia r2!, {r7} \n\t"
224         "mov r10, #0 \n\t"
225         "umull r11, r12, r5, r7 \n\t"
226         "adds r14, r11 \n\t"
227         "adcs r9, r12 \n\t"
228         "adc r10, #0 \n\t"
229         "umull r11, r12, r3, r6 \n\t"
230         "adds r14, r11 \n\t"
231         "adcs r9, r12 \n\t"
232         "adc r10, #0 \n\t"
233         "umull r11, r12, r4, r8 \n\t"
234         "adds r14, r11 \n\t"
235         "adcs r9, r12 \n\t"
236         "adc r10, #0 \n\t"
237         "ldr r11, [r0] \n\t"
238         "adds r14, r11 \n\t"
239         "adcs r9, #0 \n\t"
240         "adc r10, #0 \n\t"
241         "stmia r0!, {r14} \n\t"
242
243         "mov r11, #0 \n\t"
244         "umull r12, r14, r3, r7 \n\t"
245         "adds r9, r12 \n\t"
246         "adcs r10, r14 \n\t"
247         "adc r11, #0 \n\t"
248         "umull r12, r14, r4, r6 \n\t"
249         "adds r9, r12 \n\t"
250         "adcs r10, r14 \n\t"
251         "adc r11, #0 \n\t"
252         "stmia r0!, {r9} \n\t"
253
254         "umull r14, r9, r4, r7 \n\t"
255         "adds r10, r14 \n\t"
256         "adc r11, r9 \n\t"
257         "stmia r0!, {r10, r11} \n\t"
258     #if (uECC_PLATFORM != uECC_arm_thumb2)
259         ".syntax divided \n\t"
260     #endif
261         : "+r" (r0), "+r" (r1), "+r" (r2)
262         :
263         : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
264     );
265 }
266 #define asm_mult 1
267 #endif /* (uECC_WORDS == 5) */
268
269 #if (uECC_WORDS == 6)
270 static void vli_mult(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right)
271 {
272     register uint32_t *r0 __asm__("r0") = p_result;
273     register uint32_t *r1 __asm__("r1") = p_left;
274     register uint32_t *r2 __asm__("r2") = p_right;
275     
276     __asm__ volatile (
277         ".syntax unified \n\t"
278         "add r0, 12 \n\t"
279         "add r2, 12 \n\t"
280         "ldmia r1!, {r3,r4,r5} \n\t"
281         "ldmia r2!, {r6,r7,r8} \n\t"
282
283         "umull r11, r12, r3, r6 \n\t"
284         "stmia r0!, {r11} \n\t"
285
286         "mov r10, #0 \n\t"
287         "umull r11, r9, r3, r7 \n\t"
288         "adds r12, r11 \n\t"
289         "adc r9, #0 \n\t"
290         "umull r11, r14, r4, r6 \n\t"
291         "adds r12, r11 \n\t"
292         "adcs r9, r14 \n\t"
293         "adc r10, #0 \n\t"
294         "stmia r0!, {r12} \n\t"
295
296         "mov r11, #0 \n\t"
297         "umull r12, r14, r3, r8 \n\t"
298         "adds r9, r12 \n\t"
299         "adcs r10, r14 \n\t"
300         "adc r11, #0 \n\t"
301         "umull r12, r14, r4, r7 \n\t"
302         "adds r9, r12 \n\t"
303         "adcs r10, r14 \n\t"
304         "adc r11, #0 \n\t"
305         "umull r12, r14, r5, r6 \n\t"
306         "adds r9, r12 \n\t"
307         "adcs r10, r14 \n\t"
308         "adc r11, #0 \n\t"
309         "stmia r0!, {r9} \n\t"
310
311         "mov r12, #0 \n\t"
312         "umull r14, r9, r4, r8 \n\t"
313         "adds r10, r14 \n\t"
314         "adcs r11, r9 \n\t"
315         "adc r12, #0 \n\t"
316         "umull r14, r9, r5, r7 \n\t"
317         "adds r10, r14 \n\t"
318         "adcs r11, r9 \n\t"
319         "adc r12, #0 \n\t"
320         "stmia r0!, {r10} \n\t"
321
322         "umull r9, r10, r5, r8 \n\t"
323         "adds r11, r9 \n\t"
324         "adc r12, r10 \n\t"
325         "stmia r0!, {r11, r12} \n\t"
326
327         "sub r0, 36 \n\t"
328         "sub r2, 24 \n\t"
329         "ldmia r2!, {r6,r7,r8} \n\t"
330
331         "umull r11, r12, r3, r6 \n\t"
332         "stmia r0!, {r11} \n\t"
333
334         "mov r10, #0 \n\t"
335         "umull r11, r9, r3, r7 \n\t"
336         "adds r12, r11 \n\t"
337         "adc r9, #0 \n\t"
338         "umull r11, r14, r4, r6 \n\t"
339         "adds r12, r11 \n\t"
340         "adcs r9, r14 \n\t"
341         "adc r10, #0 \n\t"
342         "stmia r0!, {r12} \n\t"
343
344         "mov r11, #0 \n\t"
345         "umull r12, r14, r3, r8 \n\t"
346         "adds r9, r12 \n\t"
347         "adcs r10, r14 \n\t"
348         "adc r11, #0 \n\t"
349         "umull r12, r14, r4, r7 \n\t"
350         "adds r9, r12 \n\t"
351         "adcs r10, r14 \n\t"
352         "adc r11, #0 \n\t"
353         "umull r12, r14, r5, r6 \n\t"
354         "adds r9, r12 \n\t"
355         "adcs r10, r14 \n\t"
356         "adc r11, #0 \n\t"
357         "stmia r0!, {r9} \n\t"
358
359         "ldmia r1!, {r3} \n\t"
360         "mov r12, #0 \n\t"
361         "umull r14, r9, r4, r8 \n\t"
362         "adds r10, r14 \n\t"
363         "adcs r11, r9 \n\t"
364         "adc r12, #0 \n\t"
365         "umull r14, r9, r5, r7 \n\t"
366         "adds r10, r14 \n\t"
367         "adcs r11, r9 \n\t"
368         "adc r12, #0 \n\t"
369         "umull r14, r9, r3, r6 \n\t"
370         "adds r10, r14 \n\t"
371         "adcs r11, r9 \n\t"
372         "adc r12, #0 \n\t"
373         "ldr r14, [r0] \n\t"
374         "adds r10, r14 \n\t"
375         "adcs r11, #0 \n\t"
376         "adc r12, #0 \n\t"
377         "stmia r0!, {r10} \n\t"
378
379         "ldmia r1!, {r4} \n\t"
380         "mov r14, #0 \n\t"
381         "umull r9, r10, r5, r8 \n\t"
382         "adds r11, r9 \n\t"
383         "adcs r12, r10 \n\t"
384         "adc r14, #0 \n\t"
385         "umull r9, r10, r3, r7 \n\t"
386         "adds r11, r9 \n\t"
387         "adcs r12, r10 \n\t"
388         "adc r14, #0 \n\t"
389         "umull r9, r10, r4, r6 \n\t"
390         "adds r11, r9 \n\t"
391         "adcs r12, r10 \n\t"
392         "adc r14, #0 \n\t"
393         "ldr r9, [r0] \n\t"
394         "adds r11, r9 \n\t"
395         "adcs r12, #0 \n\t"
396         "adc r14, #0 \n\t"
397         "stmia r0!, {r11} \n\t"
398
399         "ldmia r1!, {r5} \n\t"
400         "mov r9, #0 \n\t"
401         "umull r10, r11, r3, r8 \n\t"
402         "adds r12, r10 \n\t"
403         "adcs r14, r11 \n\t"
404         "adc r9, #0 \n\t"
405         "umull r10, r11, r4, r7 \n\t"
406         "adds r12, r10 \n\t"
407         "adcs r14, r11 \n\t"
408         "adc r9, #0 \n\t"
409         "umull r10, r11, r5, r6 \n\t"
410         "adds r12, r10 \n\t"
411         "adcs r14, r11 \n\t"
412         "adc r9, #0 \n\t"
413         "ldr r10, [r0] \n\t"
414         "adds r12, r10 \n\t"
415         "adcs r14, #0 \n\t"
416         "adc r9, #0 \n\t"
417         "stmia r0!, {r12} \n\t"
418
419         "ldmia r2!, {r6} \n\t"
420         "mov r10, #0 \n\t"
421         "umull r11, r12, r3, r6 \n\t"
422         "adds r14, r11 \n\t"
423         "adcs r9, r12 \n\t"
424         "adc r10, #0 \n\t"
425         "umull r11, r12, r4, r8 \n\t"
426         "adds r14, r11 \n\t"
427         "adcs r9, r12 \n\t"
428         "adc r10, #0 \n\t"
429         "umull r11, r12, r5, r7 \n\t"
430         "adds r14, r11 \n\t"
431         "adcs r9, r12 \n\t"
432         "adc r10, #0 \n\t"
433         "ldr r11, [r0] \n\t"
434         "adds r14, r11 \n\t"
435         "adcs r9, #0 \n\t"
436         "adc r10, #0 \n\t"
437         "stmia r0!, {r14} \n\t"
438
439         "ldmia r2!, {r7} \n\t"
440         "mov r11, #0 \n\t"
441         "umull r12, r14, r3, r7 \n\t"
442         "adds r9, r12 \n\t"
443         "adcs r10, r14 \n\t"
444         "adc r11, #0 \n\t"
445         "umull r12, r14, r4, r6 \n\t"
446         "adds r9, r12 \n\t"
447         "adcs r10, r14 \n\t"
448         "adc r11, #0 \n\t"
449         "umull r12, r14, r5, r8 \n\t"
450         "adds r9, r12 \n\t"
451         "adcs r10, r14 \n\t"
452         "adc r11, #0 \n\t"
453         "ldr r12, [r0] \n\t"
454         "adds r9, r12 \n\t"
455         "adcs r10, #0 \n\t"
456         "adc r11, #0 \n\t"
457         "stmia r0!, {r9} \n\t"
458
459         "ldmia r2!, {r8} \n\t"
460         "mov r12, #0 \n\t"
461         "umull r14, r9, r3, r8 \n\t"
462         "adds r10, r14 \n\t"
463         "adcs r11, r9 \n\t"
464         "adc r12, #0 \n\t"
465         "umull r14, r9, r4, r7 \n\t"
466         "adds r10, r14 \n\t"
467         "adcs r11, r9 \n\t"
468         "adc r12, #0 \n\t"
469         "umull r14, r9, r5, r6 \n\t"
470         "adds r10, r14 \n\t"
471         "adcs r11, r9 \n\t"
472         "adc r12, #0 \n\t"
473         "ldr r14, [r0] \n\t"
474         "adds r10, r14 \n\t"
475         "adcs r11, #0 \n\t"
476         "adc r12, #0 \n\t"
477         "stmia r0!, {r10} \n\t"
478
479         "mov r14, #0 \n\t"
480         "umull r9, r10, r4, r8 \n\t"
481         "adds r11, r9 \n\t"
482         "adcs r12, r10 \n\t"
483         "adc r14, #0 \n\t"
484         "umull r9, r10, r5, r7 \n\t"
485         "adds r11, r9 \n\t"
486         "adcs r12, r10 \n\t"
487         "adc r14, #0 \n\t"
488         "stmia r0!, {r11} \n\t"
489
490         "umull r10, r11, r5, r8 \n\t"
491         "adds r12, r10 \n\t"
492         "adc r14, r11 \n\t"
493         "stmia r0!, {r12, r14} \n\t"
494     #if (uECC_PLATFORM != uECC_arm_thumb2)
495         ".syntax divided \n\t"
496     #endif
497         : "+r" (r0), "+r" (r1), "+r" (r2)
498         :
499         : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
500     );
501 }
502 #define asm_mult 1
503 #endif /* (uECC_WORDS == 6) */
504
505 #if (uECC_WORDS == 8)
506 static void vli_mult(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right)
507 {
508     register uint32_t *r0 __asm__("r0") = p_result;
509     register uint32_t *r1 __asm__("r1") = p_left;
510     register uint32_t *r2 __asm__("r2") = p_right;
511     
512     __asm__ volatile (
513         ".syntax unified \n\t"
514         "add r0, 24 \n\t"
515         "add r2, 24 \n\t"
516         "ldmia r1!, {r3,r4} \n\t"
517         "ldmia r2!, {r6,r7} \n\t"
518
519         "umull r11, r12, r3, r6 \n\t"
520         "stmia r0!, {r11} \n\t"
521
522         "mov r10, #0 \n\t"
523         "umull r11, r9, r3, r7 \n\t"
524         "adds r12, r11 \n\t"
525         "adc r9, #0 \n\t"
526         "umull r11, r14, r4, r6 \n\t"
527         "adds r12, r11 \n\t"
528         "adcs r9, r14 \n\t"
529         "adc r10, #0 \n\t"
530         "stmia r0!, {r12} \n\t"
531
532         "umull r12, r14, r4, r7 \n\t"
533         "adds r9, r12 \n\t"
534         "adc r10, r14 \n\t"
535         "stmia r0!, {r9, r10} \n\t"
536
537         "sub r0, 28 \n\t"
538         "sub r2, 20 \n\t"
539         "ldmia r2!, {r6,r7,r8} \n\t"
540         "ldmia r1!, {r5} \n\t"
541
542         "umull r11, r12, r3, r6 \n\t"
543         "stmia r0!, {r11} \n\t"
544
545         "mov r10, #0 \n\t"
546         "umull r11, r9, r3, r7 \n\t"
547         "adds r12, r11 \n\t"
548         "adc r9, #0 \n\t"
549         "umull r11, r14, r4, r6 \n\t"
550         "adds r12, r11 \n\t"
551         "adcs r9, r14 \n\t"
552         "adc r10, #0 \n\t"
553         "stmia r0!, {r12} \n\t"
554
555         "mov r11, #0 \n\t"
556         "umull r12, r14, r3, r8 \n\t"
557         "adds r9, r12 \n\t"
558         "adcs r10, r14 \n\t"
559         "adc r11, #0 \n\t"
560         "umull r12, r14, r4, r7 \n\t"
561         "adds r9, r12 \n\t"
562         "adcs r10, r14 \n\t"
563         "adc r11, #0 \n\t"
564         "umull r12, r14, r5, r6 \n\t"
565         "adds r9, r12 \n\t"
566         "adcs r10, r14 \n\t"
567         "adc r11, #0 \n\t"
568         "stmia r0!, {r9} \n\t"
569
570         "ldmia r1!, {r3} \n\t"
571         "mov r12, #0 \n\t"
572         "umull r14, r9, r4, r8 \n\t"
573         "adds r10, r14 \n\t"
574         "adcs r11, r9 \n\t"
575         "adc r12, #0 \n\t"
576         "umull r14, r9, r5, r7 \n\t"
577         "adds r10, r14 \n\t"
578         "adcs r11, r9 \n\t"
579         "adc r12, #0 \n\t"
580         "umull r14, r9, r3, r6 \n\t"
581         "adds r10, r14 \n\t"
582         "adcs r11, r9 \n\t"
583         "adc r12, #0 \n\t"
584         "ldr r14, [r0] \n\t"
585         "adds r10, r14 \n\t"
586         "adcs r11, #0 \n\t"
587         "adc r12, #0 \n\t"
588         "stmia r0!, {r10} \n\t"
589
590         "ldmia r1!, {r4} \n\t"
591         "mov r14, #0 \n\t"
592         "umull r9, r10, r5, r8 \n\t"
593         "adds r11, r9 \n\t"
594         "adcs r12, r10 \n\t"
595         "adc r14, #0 \n\t"
596         "umull r9, r10, r3, r7 \n\t"
597         "adds r11, r9 \n\t"
598         "adcs r12, r10 \n\t"
599         "adc r14, #0 \n\t"
600         "umull r9, r10, r4, r6 \n\t"
601         "adds r11, r9 \n\t"
602         "adcs r12, r10 \n\t"
603         "adc r14, #0 \n\t"
604         "ldr r9, [r0] \n\t"
605         "adds r11, r9 \n\t"
606         "adcs r12, #0 \n\t"
607         "adc r14, #0 \n\t"
608         "stmia r0!, {r11} \n\t"
609
610         "ldmia r2!, {r6} \n\t"
611         "mov r9, #0 \n\t"
612         "umull r10, r11, r5, r6 \n\t"
613         "adds r12, r10 \n\t"
614         "adcs r14, r11 \n\t"
615         "adc r9, #0 \n\t"
616         "umull r10, r11, r3, r8 \n\t"
617         "adds r12, r10 \n\t"
618         "adcs r14, r11 \n\t"
619         "adc r9, #0 \n\t"
620         "umull r10, r11, r4, r7 \n\t"
621         "adds r12, r10 \n\t"
622         "adcs r14, r11 \n\t"
623         "adc r9, #0 \n\t"
624         "ldr r10, [r0] \n\t"
625         "adds r12, r10 \n\t"
626         "adcs r14, #0 \n\t"
627         "adc r9, #0 \n\t"
628         "stmia r0!, {r12} \n\t"
629
630         "ldmia r2!, {r7} \n\t"
631         "mov r10, #0 \n\t"
632         "umull r11, r12, r5, r7 \n\t"
633         "adds r14, r11 \n\t"
634         "adcs r9, r12 \n\t"
635         "adc r10, #0 \n\t"
636         "umull r11, r12, r3, r6 \n\t"
637         "adds r14, r11 \n\t"
638         "adcs r9, r12 \n\t"
639         "adc r10, #0 \n\t"
640         "umull r11, r12, r4, r8 \n\t"
641         "adds r14, r11 \n\t"
642         "adcs r9, r12 \n\t"
643         "adc r10, #0 \n\t"
644         "ldr r11, [r0] \n\t"
645         "adds r14, r11 \n\t"
646         "adcs r9, #0 \n\t"
647         "adc r10, #0 \n\t"
648         "stmia r0!, {r14} \n\t"
649
650         "mov r11, #0 \n\t"
651         "umull r12, r14, r3, r7 \n\t"
652         "adds r9, r12 \n\t"
653         "adcs r10, r14 \n\t"
654         "adc r11, #0 \n\t"
655         "umull r12, r14, r4, r6 \n\t"
656         "adds r9, r12 \n\t"
657         "adcs r10, r14 \n\t"
658         "adc r11, #0 \n\t"
659         "stmia r0!, {r9} \n\t"
660
661         "umull r14, r9, r4, r7 \n\t"
662         "adds r10, r14 \n\t"
663         "adc r11, r9 \n\t"
664         "stmia r0!, {r10, r11} \n\t"
665
666         "sub r0, 52 \n\t"
667         "sub r1, 20 \n\t"
668         "sub r2, 32 \n\t"
669         "ldmia r1!, {r3,r4,r5} \n\t"
670         "ldmia r2!, {r6,r7,r8} \n\t"
671
672         "umull r11, r12, r3, r6 \n\t"
673         "stmia r0!, {r11} \n\t"
674
675         "mov r10, #0 \n\t"
676         "umull r11, r9, r3, r7 \n\t"
677         "adds r12, r11 \n\t"
678         "adc r9, #0 \n\t"
679         "umull r11, r14, r4, r6 \n\t"
680         "adds r12, r11 \n\t"
681         "adcs r9, r14 \n\t"
682         "adc r10, #0 \n\t"
683         "stmia r0!, {r12} \n\t"
684
685         "mov r11, #0 \n\t"
686         "umull r12, r14, r3, r8 \n\t"
687         "adds r9, r12 \n\t"
688         "adcs r10, r14 \n\t"
689         "adc r11, #0 \n\t"
690         "umull r12, r14, r4, r7 \n\t"
691         "adds r9, r12 \n\t"
692         "adcs r10, r14 \n\t"
693         "adc r11, #0 \n\t"
694         "umull r12, r14, r5, r6 \n\t"
695         "adds r9, r12 \n\t"
696         "adcs r10, r14 \n\t"
697         "adc r11, #0 \n\t"
698         "stmia r0!, {r9} \n\t"
699
700         "ldmia r1!, {r3} \n\t"
701         "mov r12, #0 \n\t"
702         "umull r14, r9, r4, r8 \n\t"
703         "adds r10, r14 \n\t"
704         "adcs r11, r9 \n\t"
705         "adc r12, #0 \n\t"
706         "umull r14, r9, r5, r7 \n\t"
707         "adds r10, r14 \n\t"
708         "adcs r11, r9 \n\t"
709         "adc r12, #0 \n\t"
710         "umull r14, r9, r3, r6 \n\t"
711         "adds r10, r14 \n\t"
712         "adcs r11, r9 \n\t"
713         "adc r12, #0 \n\t"
714         "ldr r14, [r0] \n\t"
715         "adds r10, r14 \n\t"
716         "adcs r11, #0 \n\t"
717         "adc r12, #0 \n\t"
718         "stmia r0!, {r10} \n\t"
719
720         "ldmia r1!, {r4} \n\t"
721         "mov r14, #0 \n\t"
722         "umull r9, r10, r5, r8 \n\t"
723         "adds r11, r9 \n\t"
724         "adcs r12, r10 \n\t"
725         "adc r14, #0 \n\t"
726         "umull r9, r10, r3, r7 \n\t"
727         "adds r11, r9 \n\t"
728         "adcs r12, r10 \n\t"
729         "adc r14, #0 \n\t"
730         "umull r9, r10, r4, r6 \n\t"
731         "adds r11, r9 \n\t"
732         "adcs r12, r10 \n\t"
733         "adc r14, #0 \n\t"
734         "ldr r9, [r0] \n\t"
735         "adds r11, r9 \n\t"
736         "adcs r12, #0 \n\t"
737         "adc r14, #0 \n\t"
738         "stmia r0!, {r11} \n\t"
739
740         "ldmia r1!, {r5} \n\t"
741         "mov r9, #0 \n\t"
742         "umull r10, r11, r3, r8 \n\t"
743         "adds r12, r10 \n\t"
744         "adcs r14, r11 \n\t"
745         "adc r9, #0 \n\t"
746         "umull r10, r11, r4, r7 \n\t"
747         "adds r12, r10 \n\t"
748         "adcs r14, r11 \n\t"
749         "adc r9, #0 \n\t"
750         "umull r10, r11, r5, r6 \n\t"
751         "adds r12, r10 \n\t"
752         "adcs r14, r11 \n\t"
753         "adc r9, #0 \n\t"
754         "ldr r10, [r0] \n\t"
755         "adds r12, r10 \n\t"
756         "adcs r14, #0 \n\t"
757         "adc r9, #0 \n\t"
758         "stmia r0!, {r12} \n\t"
759
760         "ldmia r1!, {r3} \n\t"
761         "mov r10, #0 \n\t"
762         "umull r11, r12, r4, r8 \n\t"
763         "adds r14, r11 \n\t"
764         "adcs r9, r12 \n\t"
765         "adc r10, #0 \n\t"
766         "umull r11, r12, r5, r7 \n\t"
767         "adds r14, r11 \n\t"
768         "adcs r9, r12 \n\t"
769         "adc r10, #0 \n\t"
770         "umull r11, r12, r3, r6 \n\t"
771         "adds r14, r11 \n\t"
772         "adcs r9, r12 \n\t"
773         "adc r10, #0 \n\t"
774         "ldr r11, [r0] \n\t"
775         "adds r14, r11 \n\t"
776         "adcs r9, #0 \n\t"
777         "adc r10, #0 \n\t"
778         "stmia r0!, {r14} \n\t"
779
780         "ldmia r1!, {r4} \n\t"
781         "mov r11, #0 \n\t"
782         "umull r12, r14, r5, r8 \n\t"
783         "adds r9, r12 \n\t"
784         "adcs r10, r14 \n\t"
785         "adc r11, #0 \n\t"
786         "umull r12, r14, r3, r7 \n\t"
787         "adds r9, r12 \n\t"
788         "adcs r10, r14 \n\t"
789         "adc r11, #0 \n\t"
790         "umull r12, r14, r4, r6 \n\t"
791         "adds r9, r12 \n\t"
792         "adcs r10, r14 \n\t"
793         "adc r11, #0 \n\t"
794         "ldr r12, [r0] \n\t"
795         "adds r9, r12 \n\t"
796         "adcs r10, #0 \n\t"
797         "adc r11, #0 \n\t"
798         "stmia r0!, {r9} \n\t"
799
800         "ldmia r2!, {r6} \n\t"
801         "mov r12, #0 \n\t"
802         "umull r14, r9, r5, r6 \n\t"
803         "adds r10, r14 \n\t"
804         "adcs r11, r9 \n\t"
805         "adc r12, #0 \n\t"
806         "umull r14, r9, r3, r8 \n\t"
807         "adds r10, r14 \n\t"
808         "adcs r11, r9 \n\t"
809         "adc r12, #0 \n\t"
810         "umull r14, r9, r4, r7 \n\t"
811         "adds r10, r14 \n\t"
812         "adcs r11, r9 \n\t"
813         "adc r12, #0 \n\t"
814         "ldr r14, [r0] \n\t"
815         "adds r10, r14 \n\t"
816         "adcs r11, #0 \n\t"
817         "adc r12, #0 \n\t"
818         "stmia r0!, {r10} \n\t"
819
820         "ldmia r2!, {r7} \n\t"
821         "mov r14, #0 \n\t"
822         "umull r9, r10, r5, r7 \n\t"
823         "adds r11, r9 \n\t"
824         "adcs r12, r10 \n\t"
825         "adc r14, #0 \n\t"
826         "umull r9, r10, r3, r6 \n\t"
827         "adds r11, r9 \n\t"
828         "adcs r12, r10 \n\t"
829         "adc r14, #0 \n\t"
830         "umull r9, r10, r4, r8 \n\t"
831         "adds r11, r9 \n\t"
832         "adcs r12, r10 \n\t"
833         "adc r14, #0 \n\t"
834         "ldr r9, [r0] \n\t"
835         "adds r11, r9 \n\t"
836         "adcs r12, #0 \n\t"
837         "adc r14, #0 \n\t"
838         "stmia r0!, {r11} \n\t"
839
840         "ldmia r2!, {r8} \n\t"
841         "mov r9, #0 \n\t"
842         "umull r10, r11, r5, r8 \n\t"
843         "adds r12, r10 \n\t"
844         "adcs r14, r11 \n\t"
845         "adc r9, #0 \n\t"
846         "umull r10, r11, r3, r7 \n\t"
847         "adds r12, r10 \n\t"
848         "adcs r14, r11 \n\t"
849         "adc r9, #0 \n\t"
850         "umull r10, r11, r4, r6 \n\t"
851         "adds r12, r10 \n\t"
852         "adcs r14, r11 \n\t"
853         "adc r9, #0 \n\t"
854         "ldr r10, [r0] \n\t"
855         "adds r12, r10 \n\t"
856         "adcs r14, #0 \n\t"
857         "adc r9, #0 \n\t"
858         "stmia r0!, {r12} \n\t"
859
860         "ldmia r2!, {r6} \n\t"
861         "mov r10, #0 \n\t"
862         "umull r11, r12, r5, r6 \n\t"
863         "adds r14, r11 \n\t"
864         "adcs r9, r12 \n\t"
865         "adc r10, #0 \n\t"
866         "umull r11, r12, r3, r8 \n\t"
867         "adds r14, r11 \n\t"
868         "adcs r9, r12 \n\t"
869         "adc r10, #0 \n\t"
870         "umull r11, r12, r4, r7 \n\t"
871         "adds r14, r11 \n\t"
872         "adcs r9, r12 \n\t"
873         "adc r10, #0 \n\t"
874         "ldr r11, [r0] \n\t"
875         "adds r14, r11 \n\t"
876         "adcs r9, #0 \n\t"
877         "adc r10, #0 \n\t"
878         "stmia r0!, {r14} \n\t"
879
880         "ldmia r2!, {r7} \n\t"
881         "mov r11, #0 \n\t"
882         "umull r12, r14, r5, r7 \n\t"
883         "adds r9, r12 \n\t"
884         "adcs r10, r14 \n\t"
885         "adc r11, #0 \n\t"
886         "umull r12, r14, r3, r6 \n\t"
887         "adds r9, r12 \n\t"
888         "adcs r10, r14 \n\t"
889         "adc r11, #0 \n\t"
890         "umull r12, r14, r4, r8 \n\t"
891         "adds r9, r12 \n\t"
892         "adcs r10, r14 \n\t"
893         "adc r11, #0 \n\t"
894         "ldr r12, [r0] \n\t"
895         "adds r9, r12 \n\t"
896         "adcs r10, #0 \n\t"
897         "adc r11, #0 \n\t"
898         "stmia r0!, {r9} \n\t"
899
900         "mov r12, #0 \n\t"
901         "umull r14, r9, r3, r7 \n\t"
902         "adds r10, r14 \n\t"
903         "adcs r11, r9 \n\t"
904         "adc r12, #0 \n\t"
905         "umull r14, r9, r4, r6 \n\t"
906         "adds r10, r14 \n\t"
907         "adcs r11, r9 \n\t"
908         "adc r12, #0 \n\t"
909         "stmia r0!, {r10} \n\t"
910
911         "umull r9, r10, r4, r7 \n\t"
912         "adds r11, r9 \n\t"
913         "adc r12, r10 \n\t"
914         "stmia r0!, {r11, r12} \n\t"
915     #if (uECC_PLATFORM != uECC_arm_thumb2)
916         ".syntax divided \n\t"
917     #endif
918         : "+r" (r0), "+r" (r1), "+r" (r2)
919         :
920         : "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
921     );
922 }
923 #define asm_mult 1
924 #endif /* (uECC_WORDS == 8) */
925
926 #if (uECC_WORDS == 5)
927 static void vli_square(uint32_t *p_result, uint32_t *p_left)
928 {
929     register uint32_t *r0 __asm__("r0") = p_result;
930     register uint32_t *r1 __asm__("r1") = p_left;
931     
932     __asm__ volatile (
933         ".syntax unified \n\t"
934         "ldmia r1!, {r2,r3,r4,r5,r6} \n\t"
935
936         "umull r11, r12, r2, r2 \n\t"
937         "stmia r0!, {r11} \n\t"
938
939         "mov r9, #0 \n\t"
940         "umull r10, r11, r2, r3 \n\t"
941         "adds r12, r10 \n\t"
942         "adcs r8, r11, #0 \n\t"
943         "adc r9, #0 \n\t"
944         "adds r12, r10 \n\t"
945         "adcs r8, r11 \n\t"
946         "adc r9, #0 \n\t"
947         "stmia r0!, {r12} \n\t"
948
949         "mov r10, #0 \n\t"
950         "umull r11, r12, r2, r4 \n\t"
951         "adds r11, r11 \n\t"
952         "adcs r12, r12 \n\t"
953         "adc r10, #0 \n\t"
954         "adds r8, r11 \n\t"
955         "adcs r9, r12 \n\t"
956         "adc r10, #0 \n\t"
957         "umull r11, r12, r3, r3 \n\t"
958         "adds r8, r11 \n\t"
959         "adcs r9, r12 \n\t"
960         "adc r10, #0 \n\t"
961         "stmia r0!, {r8} \n\t"
962
963         "mov r12, #0 \n\t"
964         "umull r8, r11, r2, r5 \n\t"
965         "umull r1, r14, r3, r4 \n\t"
966         "adds r8, r1 \n\t"
967         "adcs r11, r14 \n\t"
968         "adc r12, #0 \n\t"
969         "adds r8, r8 \n\t"
970         "adcs r11, r11 \n\t"
971         "adc r12, r12 \n\t"
972         "adds r8, r9 \n\t"
973         "adcs r11, r10 \n\t"
974         "adc r12, #0 \n\t"
975         "stmia r0!, {r8} \n\t"
976
977         "mov r10, #0 \n\t"
978         "umull r8, r9, r2, r6 \n\t"
979         "umull r1, r14, r3, r5 \n\t"
980         "adds r8, r1 \n\t"
981         "adcs r9, r14 \n\t"
982         "adc r10, #0 \n\t"
983         "adds r8, r8 \n\t"
984         "adcs r9, r9 \n\t"
985         "adc r10, r10 \n\t"
986         "umull r1, r14, r4, r4 \n\t"
987         "adds r8, r1 \n\t"
988         "adcs r9, r14 \n\t"
989         "adc r10, #0 \n\t"
990         "adds r8, r11 \n\t"
991         "adcs r9, r12 \n\t"
992         "adc r10, #0 \n\t"
993         "stmia r0!, {r8} \n\t"
994
995         "mov r12, #0 \n\t"
996         "umull r8, r11, r3, r6 \n\t"
997         "umull r1, r14, r4, r5 \n\t"
998         "adds r8, r1 \n\t"
999         "adcs r11, r14 \n\t"
1000         "adc r12, #0 \n\t"
1001         "adds r8, r8 \n\t"
1002         "adcs r11, r11 \n\t"
1003         "adc r12, r12 \n\t"
1004         "adds r8, r9 \n\t"
1005         "adcs r11, r10 \n\t"
1006         "adc r12, #0 \n\t"
1007         "stmia r0!, {r8} \n\t"
1008
1009         "mov r8, #0 \n\t"
1010         "umull r1, r10, r4, r6 \n\t"
1011         "adds r1, r1 \n\t"
1012         "adcs r10, r10 \n\t"
1013         "adc r8, #0 \n\t"
1014         "adds r11, r1 \n\t"
1015         "adcs r12, r10 \n\t"
1016         "adc r8, #0 \n\t"
1017         "umull r1, r10, r5, r5 \n\t"
1018         "adds r11, r1 \n\t"
1019         "adcs r12, r10 \n\t"
1020         "adc r8, #0 \n\t"
1021         "stmia r0!, {r11} \n\t"
1022
1023         "mov r11, #0 \n\t"
1024         "umull r1, r10, r5, r6 \n\t"
1025         "adds r1, r1 \n\t"
1026         "adcs r10, r10 \n\t"
1027         "adc r11, #0 \n\t"
1028         "adds r12, r1 \n\t"
1029         "adcs r8, r10 \n\t"
1030         "adc r11, #0 \n\t"
1031         "stmia r0!, {r12} \n\t"
1032
1033         "umull r1, r10, r6, r6 \n\t"
1034         "adds r8, r1 \n\t"
1035         "adcs r11, r10 \n\t"
1036         "stmia r0!, {r8, r11} \n\t"
1037     #if (uECC_PLATFORM != uECC_arm_thumb2)
1038         ".syntax divided \n\t"
1039     #endif
1040         : "+r" (r0), "+r" (r1)
1041         :
1042         : "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
1043     );
1044 }
1045 #define asm_square 1
1046 #endif /* (uECC_WORDS == 5) */
1047
1048 #if (uECC_WORDS == 6)
1049 static void vli_square(uint32_t *p_result, uint32_t *p_left)
1050 {
1051     register uint32_t *r0 __asm__("r0") = p_result;
1052     register uint32_t *r1 __asm__("r1") = p_left;
1053     
1054     __asm__ volatile (
1055         ".syntax unified \n\t"
1056         "ldmia r1!, {r2,r3,r4,r5,r6,r7} \n\t"
1057
1058         "umull r11, r12, r2, r2 \n\t"
1059         "stmia r0!, {r11} \n\t"
1060
1061         "mov r9, #0 \n\t"
1062         "umull r10, r11, r2, r3 \n\t"
1063         "adds r12, r10 \n\t"
1064         "adcs r8, r11, #0 \n\t"
1065         "adc r9, #0 \n\t"
1066         "adds r12, r10 \n\t"
1067         "adcs r8, r11 \n\t"
1068         "adc r9, #0 \n\t"
1069         "stmia r0!, {r12} \n\t"
1070
1071         "mov r10, #0 \n\t"
1072         "umull r11, r12, r2, r4 \n\t"
1073         "adds r11, r11 \n\t"
1074         "adcs r12, r12 \n\t"
1075         "adc r10, #0 \n\t"
1076         "adds r8, r11 \n\t"
1077         "adcs r9, r12 \n\t"
1078         "adc r10, #0 \n\t"
1079         "umull r11, r12, r3, r3 \n\t"
1080         "adds r8, r11 \n\t"
1081         "adcs r9, r12 \n\t"
1082         "adc r10, #0 \n\t"
1083         "stmia r0!, {r8} \n\t"
1084
1085         "mov r12, #0 \n\t"
1086         "umull r8, r11, r2, r5 \n\t"
1087         "umull r1, r14, r3, r4 \n\t"
1088         "adds r8, r1 \n\t"
1089         "adcs r11, r14 \n\t"
1090         "adc r12, #0 \n\t"
1091         "adds r8, r8 \n\t"
1092         "adcs r11, r11 \n\t"
1093         "adc r12, r12 \n\t"
1094         "adds r8, r9 \n\t"
1095         "adcs r11, r10 \n\t"
1096         "adc r12, #0 \n\t"
1097         "stmia r0!, {r8} \n\t"
1098
1099         "mov r10, #0 \n\t"
1100         "umull r8, r9, r2, r6 \n\t"
1101         "umull r1, r14, r3, r5 \n\t"
1102         "adds r8, r1 \n\t"
1103         "adcs r9, r14 \n\t"
1104         "adc r10, #0 \n\t"
1105         "adds r8, r8 \n\t"
1106         "adcs r9, r9 \n\t"
1107         "adc r10, r10 \n\t"
1108         "umull r1, r14, r4, r4 \n\t"
1109         "adds r8, r1 \n\t"
1110         "adcs r9, r14 \n\t"
1111         "adc r10, #0 \n\t"
1112         "adds r8, r11 \n\t"
1113         "adcs r9, r12 \n\t"
1114         "adc r10, #0 \n\t"
1115         "stmia r0!, {r8} \n\t"
1116
1117         "mov r12, #0 \n\t"
1118         "umull r8, r11, r2, r7 \n\t"
1119         "umull r1, r14, r3, r6 \n\t"
1120         "adds r8, r1 \n\t"
1121         "adcs r11, r14 \n\t"
1122         "adc r12, #0 \n\t"
1123         "umull r1, r14, r4, r5 \n\t"
1124         "adds r8, r1 \n\t"
1125         "adcs r11, r14 \n\t"
1126         "adc r12, #0 \n\t"
1127         "adds r8, r8 \n\t"
1128         "adcs r11, r11 \n\t"
1129         "adc r12, r12 \n\t"
1130         "adds r8, r9 \n\t"
1131         "adcs r11, r10 \n\t"
1132         "adc r12, #0 \n\t"
1133         "stmia r0!, {r8} \n\t"
1134
1135         "mov r10, #0 \n\t"
1136         "umull r8, r9, r3, r7 \n\t"
1137         "umull r1, r14, r4, r6 \n\t"
1138         "adds r8, r1 \n\t"
1139         "adcs r9, r14 \n\t"
1140         "adc r10, #0 \n\t"
1141         "adds r8, r8 \n\t"
1142         "adcs r9, r9 \n\t"
1143         "adc r10, r10 \n\t"
1144         "umull r1, r14, r5, r5 \n\t"
1145         "adds r8, r1 \n\t"
1146         "adcs r9, r14 \n\t"
1147         "adc r10, #0 \n\t"
1148         "adds r8, r11 \n\t"
1149         "adcs r9, r12 \n\t"
1150         "adc r10, #0 \n\t"
1151         "stmia r0!, {r8} \n\t"
1152
1153         "mov r12, #0 \n\t"
1154         "umull r8, r11, r4, r7 \n\t"
1155         "umull r1, r14, r5, r6 \n\t"
1156         "adds r8, r1 \n\t"
1157         "adcs r11, r14 \n\t"
1158         "adc r12, #0 \n\t"
1159         "adds r8, r8 \n\t"
1160         "adcs r11, r11 \n\t"
1161         "adc r12, r12 \n\t"
1162         "adds r8, r9 \n\t"
1163         "adcs r11, r10 \n\t"
1164         "adc r12, #0 \n\t"
1165         "stmia r0!, {r8} \n\t"
1166
1167         "mov r8, #0 \n\t"
1168         "umull r1, r10, r5, r7 \n\t"
1169         "adds r1, r1 \n\t"
1170         "adcs r10, r10 \n\t"
1171         "adc r8, #0 \n\t"
1172         "adds r11, r1 \n\t"
1173         "adcs r12, r10 \n\t"
1174         "adc r8, #0 \n\t"
1175         "umull r1, r10, r6, r6 \n\t"
1176         "adds r11, r1 \n\t"
1177         "adcs r12, r10 \n\t"
1178         "adc r8, #0 \n\t"
1179         "stmia r0!, {r11} \n\t"
1180
1181         "mov r11, #0 \n\t"
1182         "umull r1, r10, r6, r7 \n\t"
1183         "adds r1, r1 \n\t"
1184         "adcs r10, r10 \n\t"
1185         "adc r11, #0 \n\t"
1186         "adds r12, r1 \n\t"
1187         "adcs r8, r10 \n\t"
1188         "adc r11, #0 \n\t"
1189         "stmia r0!, {r12} \n\t"
1190
1191         "umull r1, r10, r7, r7 \n\t"
1192         "adds r8, r1 \n\t"
1193         "adcs r11, r10 \n\t"
1194         "stmia r0!, {r8, r11} \n\t"
1195     #if (uECC_PLATFORM != uECC_arm_thumb2)
1196         ".syntax divided \n\t"
1197     #endif
1198         : "+r" (r0), "+r" (r1)
1199         :
1200         : "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
1201     );
1202 }
1203 #define asm_square 1
1204 #endif /* (uECC_WORDS == 6) */
1205
1206 #if (uECC_WORDS == 8)
1207 static void vli_square(uint32_t *p_result, uint32_t *p_left)
1208 {
1209     register uint32_t *r0 __asm__("r0") = p_result;
1210     register uint32_t *r1 __asm__("r1") = p_left;
1211     
1212     __asm__ volatile (
1213         ".syntax unified \n\t"
1214         "ldmia r1!, {r2, r3} \n\t"
1215         "add r1, 16 \n\t"
1216         "ldmia r1!, {r5, r6} \n\t"
1217         "add r0, 24 \n\t"
1218
1219         "umull r8, r9, r2, r5 \n\t"
1220         "stmia r0!, {r8} \n\t"
1221
1222         "umull r12, r10, r2, r6 \n\t"
1223         "adds r9, r12 \n\t"
1224         "adc r10, #0 \n\t"
1225         "stmia r0!, {r9} \n\t"
1226
1227         "umull r8, r9, r3, r6 \n\t"
1228         "adds r10, r8 \n\t"
1229         "adc r11, r9, #0 \n\t"
1230         "stmia r0!, {r10, r11} \n\t"
1231
1232         "sub r0, 40 \n\t"
1233         "sub r1, 32 \n\t"
1234         "ldmia r1!, {r2,r3,r4,r5,r6,r7} \n\t"
1235
1236         "umull r11, r12, r2, r2 \n\t"
1237         "stmia r0!, {r11} \n\t"
1238
1239         "mov r9, #0 \n\t"
1240         "umull r10, r11, r2, r3 \n\t"
1241         "adds r12, r10 \n\t"
1242         "adcs r8, r11, #0 \n\t"
1243         "adc r9, #0 \n\t"
1244         "adds r12, r10 \n\t"
1245         "adcs r8, r11 \n\t"
1246         "adc r9, #0 \n\t"
1247         "stmia r0!, {r12} \n\t"
1248
1249         "mov r10, #0 \n\t"
1250         "umull r11, r12, r2, r4 \n\t"
1251         "adds r11, r11 \n\t"
1252         "adcs r12, r12 \n\t"
1253         "adc r10, #0 \n\t"
1254         "adds r8, r11 \n\t"
1255         "adcs r9, r12 \n\t"
1256         "adc r10, #0 \n\t"
1257         "umull r11, r12, r3, r3 \n\t"
1258         "adds r8, r11 \n\t"
1259         "adcs r9, r12 \n\t"
1260         "adc r10, #0 \n\t"
1261         "stmia r0!, {r8} \n\t"
1262
1263         "mov r12, #0 \n\t"
1264         "umull r8, r11, r2, r5 \n\t"
1265         "mov r14, r11 \n\t"
1266         "umlal r8, r11, r3, r4 \n\t"
1267         "cmp r14, r11 \n\t"
1268         "it hi \n\t"
1269         "adchi r12, #0 \n\t"
1270         "adds r8, r8 \n\t"
1271         "adcs r11, r11 \n\t"
1272         "adc r12, r12 \n\t"
1273         "adds r8, r9 \n\t"
1274         "adcs r11, r10 \n\t"
1275         "adc r12, #0 \n\t"
1276         "stmia r0!, {r8} \n\t"
1277
1278         "mov r10, #0 \n\t"
1279         "umull r8, r9, r2, r6 \n\t"
1280         "mov r14, r9 \n\t"
1281         "umlal r8, r9, r3, r5 \n\t"
1282         "cmp r14, r9 \n\t"
1283         "it hi \n\t"
1284         "adchi r10, #0 \n\t"
1285         "adds r8, r8 \n\t"
1286         "adcs r9, r9 \n\t"
1287         "adc r10, r10 \n\t"
1288         "mov r14, r9 \n\t"
1289         "umlal r8, r9, r4, r4 \n\t"
1290         "cmp r14, r9 \n\t"
1291         "it hi \n\t"
1292         "adchi r10, #0 \n\t"
1293         "adds r8, r11 \n\t"
1294         "adcs r9, r12 \n\t"
1295         "adc r10, #0 \n\t"
1296         "stmia r0!, {r8} \n\t"
1297
1298         "mov r12, #0 \n\t"
1299         "umull r8, r11, r2, r7 \n\t"
1300         "mov r14, r11 \n\t"
1301         "umlal r8, r11, r3, r6 \n\t"
1302         "cmp r14, r11 \n\t"
1303         "it hi \n\t"
1304         "adchi r12, #0 \n\t"
1305         "mov r14, r11 \n\t"
1306         "umlal r8, r11, r4, r5 \n\t"
1307         "cmp r14, r11 \n\t"
1308         "it hi \n\t"
1309         "adchi r12, #0 \n\t"
1310         "adds r8, r8 \n\t"
1311         "adcs r11, r11 \n\t"
1312         "adc r12, r12 \n\t"
1313         "adds r8, r9 \n\t"
1314         "adcs r11, r10 \n\t"
1315         "adc r12, #0 \n\t"
1316         "stmia r0!, {r8} \n\t"
1317
1318         "ldmia r1!, {r2} \n\t"
1319         "mov r10, #0 \n\t"
1320         "umull r8, r9, r3, r7 \n\t"
1321         "mov r14, r9 \n\t"
1322         "umlal r8, r9, r4, r6 \n\t"
1323         "cmp r14, r9 \n\t"
1324         "it hi \n\t"
1325         "adchi r10, #0 \n\t"
1326         "ldr r14, [r0] \n\t"
1327         "adds r8, r14 \n\t"
1328         "adcs r9, #0 \n\t"
1329         "adc r10, #0 \n\t"
1330         "adds r8, r8 \n\t"
1331         "adcs r9, r9 \n\t"
1332         "adc r10, r10 \n\t"
1333         "mov r14, r9 \n\t"
1334         "umlal r8, r9, r5, r5 \n\t"
1335         "cmp r14, r9 \n\t"
1336         "it hi \n\t"
1337         "adchi r10, #0 \n\t"
1338         "adds r8, r11 \n\t"
1339         "adcs r9, r12 \n\t"
1340         "adc r10, #0 \n\t"
1341         "stmia r0!, {r8} \n\t"
1342
1343         "mov r12, #0 \n\t"
1344         "umull r8, r11, r3, r2 \n\t"
1345         "mov r14, r11 \n\t"
1346         "umlal r8, r11, r4, r7 \n\t"
1347         "cmp r14, r11 \n\t"
1348         "it hi \n\t"
1349         "adchi r12, #0 \n\t"
1350         "mov r14, r11 \n\t"
1351         "umlal r8, r11, r5, r6 \n\t"
1352         "cmp r14, r11 \n\t"
1353         "it hi \n\t"
1354         "adchi r12, #0 \n\t"
1355         "ldr r14, [r0] \n\t"
1356         "adds r8, r14 \n\t"
1357         "adcs r11, #0 \n\t"
1358         "adc r12, #0 \n\t"
1359         "adds r8, r8 \n\t"
1360         "adcs r11, r11 \n\t"
1361         "adc r12, r12 \n\t"
1362         "adds r8, r9 \n\t"
1363         "adcs r11, r10 \n\t"
1364         "adc r12, #0 \n\t"
1365         "stmia r0!, {r8} \n\t"
1366
1367         "ldmia r1!, {r3} \n\t"
1368         "mov r10, #0 \n\t"
1369         "umull r8, r9, r4, r2 \n\t"
1370         "mov r14, r9 \n\t"
1371         "umlal r8, r9, r5, r7 \n\t"
1372         "cmp r14, r9 \n\t"
1373         "it hi \n\t"
1374         "adchi r10, #0 \n\t"
1375         "ldr r14, [r0] \n\t"
1376         "adds r8, r14 \n\t"
1377         "adcs r9, #0 \n\t"
1378         "adc r10, #0 \n\t"
1379         "adds r8, r8 \n\t"
1380         "adcs r9, r9 \n\t"
1381         "adc r10, r10 \n\t"
1382         "mov r14, r9 \n\t"
1383         "umlal r8, r9, r6, r6 \n\t"
1384         "cmp r14, r9 \n\t"
1385         "it hi \n\t"
1386         "adchi r10, #0 \n\t"
1387         "adds r8, r11 \n\t"
1388         "adcs r9, r12 \n\t"
1389         "adc r10, #0 \n\t"
1390         "stmia r0!, {r8} \n\t"
1391
1392         "mov r12, #0 \n\t"
1393         "umull r8, r11, r4, r3 \n\t"
1394         "mov r14, r11 \n\t"
1395         "umlal r8, r11, r5, r2 \n\t"
1396         "cmp r14, r11 \n\t"
1397         "it hi \n\t"
1398         "adchi r12, #0 \n\t"
1399         "mov r14, r11 \n\t"
1400         "umlal r8, r11, r6, r7 \n\t"
1401         "cmp r14, r11 \n\t"
1402         "it hi \n\t"
1403         "adchi r12, #0 \n\t"
1404         "ldr r14, [r0] \n\t"
1405         "adds r8, r14 \n\t"
1406         "adcs r11, #0 \n\t"
1407         "adc r12, #0 \n\t"
1408         "adds r8, r8 \n\t"
1409         "adcs r11, r11 \n\t"
1410         "adc r12, r12 \n\t"
1411         "adds r8, r9 \n\t"
1412         "adcs r11, r10 \n\t"
1413         "adc r12, #0 \n\t"
1414         "stmia r0!, {r8} \n\t"
1415
1416         "mov r10, #0 \n\t"
1417         "umull r8, r9, r5, r3 \n\t"
1418         "mov r14, r9 \n\t"
1419         "umlal r8, r9, r6, r2 \n\t"
1420         "cmp r14, r9 \n\t"
1421         "it hi \n\t"
1422         "adchi r10, #0 \n\t"
1423         "adds r8, r8 \n\t"
1424         "adcs r9, r9 \n\t"
1425         "adc r10, r10 \n\t"
1426         "mov r14, r9 \n\t"
1427         "umlal r8, r9, r7, r7 \n\t"
1428         "cmp r14, r9 \n\t"
1429         "it hi \n\t"
1430         "adchi r10, #0 \n\t"
1431         "adds r8, r11 \n\t"
1432         "adcs r9, r12 \n\t"
1433         "adc r10, #0 \n\t"
1434         "stmia r0!, {r8} \n\t"
1435
1436         "mov r12, #0 \n\t"
1437         "umull r8, r11, r6, r3 \n\t"
1438         "mov r14, r11 \n\t"
1439         "umlal r8, r11, r7, r2 \n\t"
1440         "cmp r14, r11 \n\t"
1441         "it hi \n\t"
1442         "adchi r12, #0 \n\t"
1443         "adds r8, r8 \n\t"
1444         "adcs r11, r11 \n\t"
1445         "adc r12, r12 \n\t"
1446         "adds r8, r9 \n\t"
1447         "adcs r11, r10 \n\t"
1448         "adc r12, #0 \n\t"
1449         "stmia r0!, {r8} \n\t"
1450
1451         "mov r8, #0 \n\t"
1452         "umull r1, r10, r7, r3 \n\t"
1453         "adds r1, r1 \n\t"
1454         "adcs r10, r10 \n\t"
1455         "adc r8, #0 \n\t"
1456         "adds r11, r1 \n\t"
1457         "adcs r12, r10 \n\t"
1458         "adc r8, #0 \n\t"
1459         "umull r1, r10, r2, r2 \n\t"
1460         "adds r11, r1 \n\t"
1461         "adcs r12, r10 \n\t"
1462         "adc r8, #0 \n\t"
1463         "stmia r0!, {r11} \n\t"
1464
1465         "mov r11, #0 \n\t"
1466         "umull r1, r10, r2, r3 \n\t"
1467         "adds r1, r1 \n\t"
1468         "adcs r10, r10 \n\t"
1469         "adc r11, #0 \n\t"
1470         "adds r12, r1 \n\t"
1471         "adcs r8, r10 \n\t"
1472         "adc r11, #0 \n\t"
1473         "stmia r0!, {r12} \n\t"
1474
1475         "umull r1, r10, r3, r3 \n\t"
1476         "adds r8, r1 \n\t"
1477         "adcs r11, r10 \n\t"
1478         "stmia r0!, {r8, r11} \n\t"
1479     #if (uECC_PLATFORM != uECC_arm_thumb2)
1480         ".syntax divided \n\t"
1481     #endif
1482         : "+r" (r0), "+r" (r1)
1483         :
1484         : "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14", "cc", "memory"
1485     );
1486 }
1487 #define asm_square 1
1488 #endif /* (uECC_WORDS == 8) */
1489
1490 #endif /* (uECC_PLATFORM != uECC_arm_thumb) */
1491
1492 #endif /* (uECC_ASM == uECC_asm_fast) */
1493
1494 #if !asm_add
1495 static uint32_t vli_add(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right)
1496 {
1497     uint32_t l_counter = uECC_WORDS;
1498     uint32_t l_carry = 0; /* carry = 0 initially */
1499     uint32_t l_left;
1500     uint32_t l_right;
1501     
1502     __asm__ volatile (
1503         ".syntax unified \n\t"
1504         "1: \n\t"
1505         "ldmia %[lptr]!, {%[left]} \n\t"  /* Load left word. */
1506         "ldmia %[rptr]!, {%[right]} \n\t" /* Load right word. */
1507         "lsrs %[carry], #1 \n\t"          /* Set up carry flag (l_carry = 0 after this). */
1508         "adcs %[left], %[right] \n\t"     /* Add with carry. */
1509         "adcs %[carry], %[carry] \n\t"    /* Store carry bit in l_carry. */
1510         "stmia %[dptr]!, {%[left]} \n\t"  /* Store result word. */
1511         "subs %[ctr], #1 \n\t"            /* Decrement index. */
1512         "bne 1b \n\t"                     /* Loop until index == 0. */
1513     #if (uECC_PLATFORM != uECC_arm_thumb2)
1514         ".syntax divided \n\t"
1515     #endif
1516     #if (uECC_PLATFORM == uECC_arm_thumb)
1517         : [dptr] "+l" (p_result), [lptr] "+l" (p_left), [rptr] "+l" (p_right),
1518           [ctr] "+l" (l_counter), [carry] "+l" (l_carry), [left] "=l" (l_left), [right] "=l" (l_right)
1519     #else
1520         : [dptr] "+r" (p_result), [lptr] "+r" (p_left), [rptr] "+r" (p_right),
1521           [ctr] "+r" (l_counter), [carry] "+r" (l_carry), [left] "=r" (l_left), [right] "=r" (l_right)
1522     #endif
1523         :
1524         : "cc", "memory"
1525     );
1526     return l_carry;
1527 }
1528 #define asm_add 1
1529 #endif
1530
1531 #if !asm_sub
1532 static uint32_t vli_sub(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right)
1533 {
1534     uint32_t l_counter = uECC_WORDS;
1535     uint32_t l_carry = 1; /* carry = 1 initially (means don't borrow) */
1536     uint32_t l_left;
1537     uint32_t l_right;
1538     
1539     __asm__ volatile (
1540         ".syntax unified \n\t"
1541         "1: \n\t"
1542         "ldmia %[lptr]!, {%[left]} \n\t"  /* Load left word. */
1543         "ldmia %[rptr]!, {%[right]} \n\t" /* Load right word. */
1544         "lsrs %[carry], #1 \n\t"          /* Set up carry flag (l_carry = 0 after this). */
1545         "sbcs %[left], %[right] \n\t"     /* Subtract with borrow. */
1546         "adcs %[carry], %[carry] \n\t"    /* Store carry bit in l_carry. */
1547         "stmia %[dptr]!, {%[left]} \n\t"  /* Store result word. */
1548         "subs %[ctr], #1 \n\t"            /* Decrement index. */
1549         "bne 1b \n\t"                     /* Loop until index == 0. */
1550     #if (uECC_PLATFORM != uECC_arm_thumb2)
1551         ".syntax divided \n\t"
1552     #endif
1553     #if (uECC_PLATFORM == uECC_arm_thumb)
1554         : [dptr] "+l" (p_result), [lptr] "+l" (p_left), [rptr] "+l" (p_right),
1555           [ctr] "+l" (l_counter), [carry] "+l" (l_carry), [left] "=l" (l_left), [right] "=l" (l_right)
1556     #else
1557         : [dptr] "+r" (p_result), [lptr] "+r" (p_left), [rptr] "+r" (p_right),
1558           [ctr] "+r" (l_counter), [carry] "+r" (l_carry), [left] "=r" (l_left), [right] "=r" (l_right)
1559     #endif
1560         :
1561         : "cc", "memory"
1562     );
1563     return !l_carry;
1564 }
1565 #define asm_sub 1
1566 #endif
1567
1568 #if !asm_mult
1569 static void vli_mult(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right)
1570 {
1571 #if (uECC_PLATFORM != uECC_arm_thumb)
1572     uint32_t c0 = 0;
1573     uint32_t c1 = 0;
1574     uint32_t c2 = 0;
1575     uint32_t k = 0;
1576     uint32_t i;
1577     uint32_t t0, t1;
1578     
1579     __asm__ volatile (
1580         ".syntax unified \n\t"
1581         
1582         "1: \n\t" /* outer loop (k < uECC_WORDS) */
1583         "movs %[i], #0 \n\t" /* i = 0 */
1584         "b 3f \n\t"
1585         
1586         "2: \n\t" /* outer loop (k >= uECC_WORDS) */
1587         "movs %[i], %[k] \n\t"      /* i = k */
1588         "subs %[i], %[eccdm1] \n\t" /* i = k - (uECC_WORDS - 1) (times 4) */
1589         
1590         "3: \n\t" /* inner loop */
1591         "subs %[t0], %[k], %[i] \n\t" /* t0 = k-i */
1592         
1593         "ldr %[t1], [%[right], %[t0]] \n\t" /* t1 = p_right[k-i] */
1594         "ldr %[t0], [%[left], %[i]] \n\t"   /* t0 = p_left[i] */
1595         
1596         "umull %[t0], %[t1], %[t0], %[t1] \n\t" /* (t0, t1) = p_left[i] * p_right[k-i] */
1597         
1598         "adds %[c0], %[t0] \n\t" /* add low word to c0 */
1599         "adcs %[c1], %[t1] \n\t" /* add high word to c1, including carry */
1600         "adcs %[c2], #0 \n\t"    /* add carry to c2 */
1601
1602         "adds %[i], #4 \n\t"     /* i += 4 */
1603         "cmp %[i], %[eccd] \n\t" /* i < uECC_WORDS (times 4)? */
1604         "bge 4f \n\t" /* if not, exit the loop */
1605         "cmp %[i], %[k] \n\t"    /* i <= k? */
1606         "ble 3b \n\t" /* if so, continue looping */
1607         
1608         "4: \n\t" /* end inner loop */
1609         
1610         "str %[c0], [%[result], %[k]] \n\t" /* p_result[k] = c0 */
1611         "mov %[c0], %[c1] \n\t"     /* c0 = c1 */
1612         "mov %[c1], %[c2] \n\t"     /* c1 = c2 */
1613         "movs %[c2], #0 \n\t"       /* c2 = 0 */
1614         "adds %[k], #4 \n\t"        /* k += 4 */
1615         "cmp %[k], %[eccd] \n\t"    /* k < uECC_WORDS (times 4) ? */
1616         "blt 1b \n\t" /* if not, loop back, start with i = 0 */
1617         "cmp %[k], %[eccd2m1] \n\t" /* k < uECC_WORDS * 2 - 1 (times 4) ? */
1618         "blt 2b \n\t" /* if not, loop back, start with i = (k+1) - uECC_WORDS */
1619         /* end outer loop */
1620         
1621         "str %[c0], [%[result], %[k]] \n\t" /* p_result[uECC_WORDS * 2 - 1] = c0 */
1622     #if (uECC_PLATFORM != uECC_arm_thumb2)
1623         ".syntax divided \n\t"
1624     #endif
1625         : [c0] "+r" (c0), [c1] "+r" (c1), [c2] "+r" (c2), [k] "+r" (k), [i] "=&r" (i), [t0] "=&r" (t0), [t1] "=&r" (t1)
1626         : [result] "r" (p_result), [left] "r" (p_left), [right] "r" (p_right),
1627           [eccd] "I" (uECC_WORDS * 4), [eccdm1] "I" ((uECC_WORDS-1) * 4), [eccd2m1] "I" ((uECC_WORDS * 2 - 1) * 4)
1628         : "cc", "memory"
1629     );
1630     
1631 #else /* Thumb-1 */
1632
1633     register uint32_t *r0 __asm__("r0") = p_result;
1634     register uint32_t *r1 __asm__("r1") = p_left;
1635     register uint32_t *r2 __asm__("r2") = p_right;
1636     
1637     __asm__ volatile (
1638         ".syntax unified \n\t"
1639         "movs r3, #0 \n\t" /* c0 = 0 */
1640         "movs r4, #0 \n\t" /* c1 = 0 */
1641         "movs r5, #0 \n\t" /* c2 = 0 */
1642         "movs r6, #0 \n\t" /* k = 0 */
1643         
1644         "push {r0} \n\t" /* keep p_result on the stack */
1645         
1646         "1: \n\t" /* outer loop (k < uECC_WORDS) */
1647         "movs r7, #0 \n\t" /* r7 = i = 0 */
1648         "b 3f \n\t"
1649         
1650         "2: \n\t" /* outer loop (k >= uECC_WORDS) */
1651         "movs r7, r6 \n\t"        /* r7 = k */
1652         "subs r7, %[eccdm1] \n\t" /* r7 = i = k - (uECC_WORDS - 1) (times 4) */
1653         
1654         "3: \n\t" /* inner loop */
1655         "push {r3, r4, r5, r6} \n\t" /* push things, r3 (c0) is at the top of stack. */
1656         "subs r0, r6, r7 \n\t"       /* r0 = k-i */
1657         
1658         "ldr r4, [r2, r0] \n\t" /* r4 = p_right[k-i] */
1659         "ldr r0, [r1, r7] \n\t" /* r0 = p_left[i] */
1660         
1661         "lsrs r3, r0, #16 \n\t" /* r3 = a1 */
1662         "uxth r0, r0 \n\t"      /* r0 = a0 */
1663         
1664         "lsrs r5, r4, #16 \n\t" /* r5 = b1 */
1665         "uxth r4, r4 \n\t"      /* r4 = b0 */
1666         
1667         "movs r6, r3 \n\t"     /* r6 = a1 */
1668         "muls r6, r5, r6 \n\t" /* r6 = a1*b1 */
1669         "muls r3, r4, r3 \n\t" /* r3 = b0*a1 */
1670         "muls r5, r0, r5 \n\t" /* r5 = a0*b1 */
1671         "muls r0, r4, r0 \n\t" /* r0 = a0*b0 */
1672         
1673         "movs r4, #0 \n\t"  /* r4 = 0 */
1674         "adds r3, r5 \n\t"  /* r3 = b0*a1 + a0*b1 */
1675         "adcs r4, r4 \n\t"  /* r4 = carry */
1676         "lsls r4, #16 \n\t" /* r4 = carry << 16 */
1677         "adds r6, r4 \n\t"  /* r6 = a1*b1 + carry */
1678         
1679         "lsls r4, r3, #16 \n\t" /* r4 = (b0*a1 + a0*b1) << 16 */
1680         "lsrs r3, #16 \n\t"     /* r3 = (b0*a1 + a0*b1) >> 16 */
1681         "adds r0, r4 \n\t"      /* r0 = low word = a0*b0 + ((b0*a1 + a0*b1) << 16) */
1682         "adcs r6, r3 \n\t"      /* r6 = high word = a1*b1 + carry + ((b0*a1 + a0*b1) >> 16) */
1683         
1684         "pop {r3, r4, r5} \n\t" /* r3 = c0, r4 = c1, r5 = c2 */
1685         "adds r3, r0 \n\t"      /* add low word to c0 */
1686         "adcs r4, r6 \n\t"      /* add high word to c1, including carry */
1687         "movs r0, #0 \n\t"      /* r0 = 0 (does not affect carry bit) */
1688         "adcs r5, r0 \n\t"      /* add carry to c2 */
1689         
1690         "pop {r6} \n\t" /* r6 = k */
1691
1692         "adds r7, #4 \n\t"     /* i += 4 */
1693         "cmp r7, %[eccd] \n\t" /* i < uECC_WORDS (times 4)? */
1694         "bge 4f \n\t" /* if not, exit the loop */
1695         "cmp r7, r6 \n\t"      /* i <= k? */
1696         "ble 3b \n\t" /* if so, continue looping */
1697         
1698         "4: \n\t" /* end inner loop */
1699         
1700         "ldr r0, [sp, #0] \n\t" /* r0 = p_result */
1701         
1702         "str r3, [r0, r6] \n\t"   /* p_result[k] = c0 */
1703         "mov r3, r4 \n\t"         /* c0 = c1 */
1704         "mov r4, r5 \n\t"         /* c1 = c2 */
1705         "movs r5, #0 \n\t"        /* c2 = 0 */
1706         "adds r6, #4 \n\t"        /* k += 4 */
1707         "cmp r6, %[eccd] \n\t"    /* k < uECC_WORDS (times 4) ? */
1708         "blt 1b \n\t" /* if not, loop back, start with i = 0 */
1709         "cmp r6, %[eccd2m1] \n\t" /* k < uECC_WORDS * 2 - 1 (times 4) ? */
1710         "blt 2b \n\t" /* if not, loop back, start with i = (k+1) - uECC_WORDS */
1711         /* end outer loop */
1712         
1713         "str r3, [r0, r6] \n\t" /* p_result[uECC_WORDS * 2 - 1] = c0 */
1714         "pop {r0} \n\t"         /* pop p_result off the stack */
1715         
1716         ".syntax divided \n\t"
1717         : 
1718         : [r0] "l" (r0), [r1] "l" (r1), [r2] "l" (r2), [eccd] "I" (uECC_WORDS * 4), [eccdm1] "I" ((uECC_WORDS-1) * 4), [eccd2m1] "I" ((uECC_WORDS * 2 - 1) * 4)
1719         : "r3", "r4", "r5", "r6", "r7", "cc", "memory"
1720     );
1721 #endif
1722 }
1723 #define asm_mult 1
1724 #endif /* !asm_mult */
1725
1726 #if uECC_SQUARE_FUNC
1727 #if !asm_square
1728 static void vli_square(uint32_t *p_result, uint32_t *p_left)
1729 {
1730 #if (uECC_PLATFORM != uECC_arm_thumb)
1731     uint32_t c0 = 0;
1732     uint32_t c1 = 0;
1733     uint32_t c2 = 0;
1734     uint32_t k = 0;
1735     uint32_t i, tt;
1736     uint32_t t0, t1;
1737     
1738     __asm__ volatile (
1739         ".syntax unified \n\t"
1740         
1741         "1: \n\t" /* outer loop (k < uECC_WORDS) */
1742         "movs %[i], #0 \n\t" /* i = 0 */
1743         "b 3f \n\t"
1744         
1745         "2: \n\t" /* outer loop (k >= uECC_WORDS) */
1746         "movs %[i], %[k] \n\t"      /* i = k */
1747         "subs %[i], %[eccdm1] \n\t" /* i = k - (uECC_WORDS - 1) (times 4) */
1748         
1749         "3: \n\t" /* inner loop */
1750         "subs %[tt], %[k], %[i] \n\t" /* tt = k-i */
1751         
1752         "ldr %[t1], [%[left], %[tt]] \n\t" /* t1 = p_left[k-i] */
1753         "ldr %[t0], [%[left], %[i]] \n\t"  /* t0 = p_left[i] */
1754         
1755         "umull %[t0], %[t1], %[t0], %[t1] \n\t" /* (t0, t1) = p_left[i] * p_right[k-i] */
1756         
1757         "cmp %[i], %[tt] \n\t"   /* (i < k-i) ? */
1758         "bge 4f \n\t" /* if i >= k-i, skip */
1759         "lsls %[t1], #1 \n\t"    /* high word << 1 */
1760         "adc %[c2], #0 \n\t"     /* add carry bit to c2 */
1761         "lsls %[t0], #1 \n\t"       /* low word << 1 */
1762         "adc %[t1], #0 \n\t"     /* add carry bit to high word */
1763         
1764         "4: \n\t"
1765
1766         "adds %[c0], %[t0] \n\t" /* add low word to c0 */
1767         "adcs %[c1], %[t1] \n\t" /* add high word to c1, including carry */
1768         "adc %[c2], #0 \n\t"     /* add carry to c2 */
1769         
1770         "adds %[i], #4 \n\t"          /* i += 4 */
1771         "cmp %[i], %[k] \n\t"         /* i <= k? */
1772         "bge 5f \n\t" /* if not, exit the loop */
1773         "subs %[tt], %[k], %[i] \n\t" /* tt = k-i */
1774         "cmp %[i], %[tt] \n\t"        /* i <= k-i? */
1775         "ble 3b \n\t" /* if so, continue looping */
1776         
1777         "5: \n\t" /* end inner loop */
1778         
1779         "str %[c0], [%[result], %[k]] \n\t" /* p_result[k] = c0 */
1780         "mov %[c0], %[c1] \n\t"     /* c0 = c1 */
1781         "mov %[c1], %[c2] \n\t"     /* c1 = c2 */
1782         "movs %[c2], #0 \n\t"       /* c2 = 0 */
1783         "adds %[k], #4 \n\t"        /* k += 4 */
1784         "cmp %[k], %[eccd] \n\t"    /* k < uECC_WORDS (times 4) ? */
1785         "blt 1b \n\t" /* if not, loop back, start with i = 0 */
1786         "cmp %[k], %[eccd2m1] \n\t" /* k < uECC_WORDS * 2 - 1 (times 4) ? */
1787         "blt 2b \n\t" /* if not, loop back, start with i = (k+1) - uECC_WORDS */
1788         /* end outer loop */
1789         
1790         "str %[c0], [%[result], %[k]] \n\t" /* p_result[uECC_WORDS * 2 - 1] = c0 */
1791     #if (uECC_PLATFORM != uECC_arm_thumb2)
1792         ".syntax divided \n\t"
1793     #endif
1794         : [c0] "+r" (c0), [c1] "+r" (c1), [c2] "+r" (c2), [k] "+r" (k), [i] "=&r" (i), [tt] "=&r" (tt), [t0] "=&r" (t0), [t1] "=&r" (t1)
1795         : [result] "r" (p_result), [left] "r" (p_left),
1796           [eccd] "I" (uECC_WORDS * 4), [eccdm1] "I" ((uECC_WORDS-1) * 4), [eccd2m1] "I" ((uECC_WORDS * 2 - 1) * 4)
1797         : "cc", "memory"
1798     );
1799     
1800 #else
1801
1802     register uint32_t *r0 __asm__("r0") = p_result;
1803     register uint32_t *r1 __asm__("r1") = p_left;
1804     
1805     __asm__ volatile (
1806         ".syntax unified \n\t"
1807         "movs r2, #0 \n\t" /* c0 = 0 */
1808         "movs r3, #0 \n\t" /* c1 = 0 */
1809         "movs r4, #0 \n\t" /* c2 = 0 */
1810         "movs r5, #0 \n\t" /* k = 0 */
1811         
1812         "push {r0} \n\t" /* keep p_result on the stack */
1813         
1814         "1: \n\t" /* outer loop (k < uECC_WORDS) */
1815         "movs r6, #0 \n\t" /* r6 = i = 0 */
1816         "b 3f \n\t"
1817         
1818         "2: \n\t" /* outer loop (k >= uECC_WORDS) */
1819         "movs r6, r5 \n\t"        /* r6 = k */
1820         "subs r6, %[eccdm1] \n\t" /* r6 = i = k - (uECC_WORDS - 1) (times 4) */
1821         
1822         "3: \n\t" /* inner loop */
1823         "push {r2, r3, r4, r5} \n\t" /* push things, r2 (c0) is at the top of stack. */
1824         "subs r7, r5, r6 \n\t"       /* r7 = k-i */
1825         
1826         "ldr r3, [r1, r7] \n\t" /* r3 = p_left[k-i] */
1827         "ldr r0, [r1, r6] \n\t" /* r0 = p_left[i] */
1828         
1829         "lsrs r2, r0, #16 \n\t" /* r2 = a1 */
1830         "uxth r0, r0 \n\t"      /* r0 = a0 */
1831         
1832         "lsrs r4, r3, #16 \n\t" /* r4 = b1 */
1833         "uxth r3, r3 \n\t"      /* r3 = b0 */
1834         
1835         "movs r5, r2 \n\t"     /* r5 = a1 */
1836         "muls r5, r4, r5 \n\t" /* r5 = a1*b1 */
1837         "muls r2, r3, r2 \n\t" /* r2 = b0*a1 */
1838         "muls r4, r0, r4 \n\t" /* r4 = a0*b1 */
1839         "muls r0, r3, r0 \n\t" /* r0 = a0*b0 */
1840         
1841         "movs r3, #0 \n\t"  /* r3 = 0 */
1842         "adds r2, r4 \n\t"  /* r2 = b0*a1 + a0*b1 */
1843         "adcs r3, r3 \n\t"  /* r3 = carry */
1844         "lsls r3, #16 \n\t" /* r3 = carry << 16 */
1845         "adds r5, r3 \n\t"  /* r5 = a1*b1 + carry */
1846         
1847         "lsls r3, r2, #16 \n\t" /* r3 = (b0*a1 + a0*b1) << 16 */
1848         "lsrs r2, #16 \n\t"     /* r2 = (b0*a1 + a0*b1) >> 16 */
1849         "adds r0, r3 \n\t"      /* r0 = low word = a0*b0 + ((b0*a1 + a0*b1) << 16) */
1850         "adcs r5, r2 \n\t"      /* r5 = high word = a1*b1 + carry + ((b0*a1 + a0*b1) >> 16) */
1851     
1852         "movs r3, #0 \n\t"  /* r3 = 0 */
1853         "cmp r6, r7 \n\t"   /* (i < k-i) ? */
1854         "mov r7, r3 \n\t"   /* r7 = 0 (does not affect condition)*/
1855         "bge 4f \n\t" /* if i >= k-i, skip */
1856         "lsls r5, #1 \n\t"  /* high word << 1 */
1857         "adcs r7, r3 \n\t"  /* r7 = carry bit for c2 */
1858         "lsls r0, #1 \n\t"  /* low word << 1 */
1859         "adcs r5, r3 \n\t"  /* add carry from shift to high word */
1860         
1861         "4: \n\t"
1862         "pop {r2, r3, r4} \n\t" /* r2 = c0, r3 = c1, r4 = c2 */
1863         "adds r2, r0 \n\t"      /* add low word to c0 */
1864         "adcs r3, r5 \n\t"      /* add high word to c1, including carry */
1865         "movs r0, #0 \n\t"      /* r0 = 0 (does not affect carry bit) */
1866         "adcs r4, r0 \n\t"      /* add carry to c2 */
1867         "adds r4, r7 \n\t"      /* add carry from doubling (if any) */
1868         
1869         "pop {r5} \n\t" /* r5 = k */
1870         
1871         "adds r6, #4 \n\t"     /* i += 4 */
1872         "cmp r6, r5 \n\t"      /* i <= k? */
1873         "bge 5f \n\t" /* if not, exit the loop */
1874         "subs r7, r5, r6 \n\t" /* r7 = k-i */
1875         "cmp r6, r7 \n\t"      /* i <= k-i? */
1876         "ble 3b \n\t" /* if so, continue looping */
1877         
1878         "5: \n\t" /* end inner loop */
1879         
1880         "ldr r0, [sp, #0] \n\t" /* r0 = p_result */
1881         
1882         "str r2, [r0, r5] \n\t"   /* p_result[k] = c0 */
1883         "mov r2, r3 \n\t"         /* c0 = c1 */
1884         "mov r3, r4 \n\t"         /* c1 = c2 */
1885         "movs r4, #0 \n\t"        /* c2 = 0 */
1886         "adds r5, #4 \n\t"        /* k += 4 */
1887         "cmp r5, %[eccd] \n\t"    /* k < uECC_WORDS (times 4) ? */
1888         "blt 1b \n\t" /* if not, loop back, start with i = 0 */
1889         "cmp r5, %[eccd2m1] \n\t" /* k < uECC_WORDS * 2 - 1 (times 4) ? */
1890         "blt 2b \n\t" /* if not, loop back, start with i = (k+1) - uECC_WORDS */
1891         /* end outer loop */
1892         
1893         "str r2, [r0, r5] \n\t" /* p_result[uECC_WORDS * 2 - 1] = c0 */
1894         "pop {r0} \n\t"         /* pop p_result off the stack */
1895
1896         ".syntax divided \n\t"
1897         : [r0] "+l" (r0), [r1] "+l" (r1)
1898         : [eccd] "I" (uECC_WORDS * 4), [eccdm1] "I" ((uECC_WORDS-1) * 4), [eccd2m1] "I" ((uECC_WORDS * 2 - 1) * 4)
1899         : "r2", "r3", "r4", "r5", "r6", "r7", "cc", "memory"
1900     );
1901 #endif
1902 }
1903 #define asm_square 1
1904 #endif /* !asm_square */
1905 #endif /* uECC_SQUARE_FUNC */