Add ARM asm from micro-ecc.

This commit is contained in:
Ken MacKay
2014-04-22 21:38:29 -07:00
parent fad4b3f0cb
commit 2dfbdc79cd
2 changed files with 426 additions and 6 deletions
+412
View File
@@ -0,0 +1,412 @@
#if !asm_add
static uint32_t vli_add(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right)
{
uint32_t l_counter = uECC_WORDS;
uint32_t l_carry = 0; /* carry = 0 initially */
uint32_t l_left;
uint32_t l_right;
__asm__ volatile (
".syntax unified \n\t"
"1: \n\t"
"ldmia %[lptr]!, {%[left]} \n\t" /* Load left word. */
"ldmia %[rptr]!, {%[right]} \n\t" /* Load right word. */
"lsrs %[carry], #1 \n\t" /* Set up carry flag (l_carry = 0 after this). */
"adcs %[left], %[right] \n\t" /* Add with carry. */
"adcs %[carry], %[carry] \n\t" /* Store carry bit in l_carry. */
"stmia %[dptr]!, {%[left]} \n\t" /* Store result word. */
"subs %[ctr], #1 \n\t" /* Decrement index. */
"bne 1b \n\t" /* Loop until index == 0. */
#if (uECC_PLATFORM != uECC_arm_thumb2)
".syntax divided \n\t"
#endif
#if (uECC_PLATFORM == uECC_arm_thumb)
: [dptr] "+l" (p_result), [lptr] "+l" (p_left), [rptr] "+l" (p_right),
[ctr] "+l" (l_counter), [carry] "+l" (l_carry), [left] "=l" (l_left), [right] "=l" (l_right)
#else
: [dptr] "+r" (p_result), [lptr] "+r" (p_left), [rptr] "+r" (p_right),
[ctr] "+r" (l_counter), [carry] "+r" (l_carry), [left] "=r" (l_left), [right] "=r" (l_right)
#endif
:
: "cc", "memory"
);
return l_carry;
}
#define asm_add 1
#endif
#if !asm_sub
static uint32_t vli_sub(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right)
{
uint32_t l_counter = uECC_WORDS;
uint32_t l_carry = 1; /* carry = 1 initially (means don't borrow) */
uint32_t l_left;
uint32_t l_right;
__asm__ volatile (
".syntax unified \n\t"
"1: \n\t"
"ldmia %[lptr]!, {%[left]} \n\t" /* Load left word. */
"ldmia %[rptr]!, {%[right]} \n\t" /* Load right word. */
"lsrs %[carry], #1 \n\t" /* Set up carry flag (l_carry = 0 after this). */
"sbcs %[left], %[right] \n\t" /* Subtract with borrow. */
"adcs %[carry], %[carry] \n\t" /* Store carry bit in l_carry. */
"stmia %[dptr]!, {%[left]} \n\t" /* Store result word. */
"subs %[ctr], #1 \n\t" /* Decrement index. */
"bne 1b \n\t" /* Loop until index == 0. */
#if (uECC_PLATFORM != uECC_arm_thumb2)
".syntax divided \n\t"
#endif
#if (uECC_PLATFORM == uECC_arm_thumb)
: [dptr] "+l" (p_result), [lptr] "+l" (p_left), [rptr] "+l" (p_right),
[ctr] "+l" (l_counter), [carry] "+l" (l_carry), [left] "=l" (l_left), [right] "=l" (l_right)
#else
: [dptr] "+r" (p_result), [lptr] "+r" (p_left), [rptr] "+r" (p_right),
[ctr] "+r" (l_counter), [carry] "+r" (l_carry), [left] "=r" (l_left), [right] "=r" (l_right)
#endif
:
: "cc", "memory"
);
return !l_carry;
}
#define asm_sub 1
#endif
#if !asm_mult
static void vli_mult(uint32_t *p_result, uint32_t *p_left, uint32_t *p_right)
{
#if (uECC_PLATFORM != uECC_arm_thumb)
uint32_t c0 = 0;
uint32_t c1 = 0;
uint32_t c2 = 0;
uint32_t k = 0;
uint32_t i;
uint32_t t0, t1;
__asm__ volatile (
".syntax unified \n\t"
"1: \n\t" /* outer loop (k < uECC_WORDS) */
"movs %[i], #0 \n\t" /* i = 0 */
"b 3f \n\t"
"2: \n\t" /* outer loop (k >= uECC_WORDS) */
"movs %[i], %[k] \n\t" /* i = k */
"subs %[i], %[eccdm1] \n\t" /* i = k - (uECC_WORDS - 1) (times 4) */
"3: \n\t" /* inner loop */
"subs %[t0], %[k], %[i] \n\t" /* t0 = k-i */
"ldr %[t1], [%[right], %[t0]] \n\t" /* t1 = p_right[k-i] */
"ldr %[t0], [%[left], %[i]] \n\t" /* t0 = p_left[i] */
"umull %[t0], %[t1], %[t0], %[t1] \n\t" /* (t0, t1) = p_left[i] * p_right[k-i] */
"adds %[c0], %[t0] \n\t" /* add low word to c0 */
"adcs %[c1], %[t1] \n\t" /* add high word to c1, including carry */
"adcs %[c2], #0 \n\t" /* add carry to c2 */
"adds %[i], #4 \n\t" /* i += 4 */
"cmp %[i], %[eccd] \n\t" /* i < uECC_WORDS (times 4)? */
"bge 4f \n\t" /* if not, exit the loop */
"cmp %[i], %[k] \n\t" /* i <= k? */
"ble 3b \n\t" /* if so, continue looping */
"4: \n\t" /* end inner loop */
"str %[c0], [%[result], %[k]] \n\t" /* p_result[k] = c0 */
"mov %[c0], %[c1] \n\t" /* c0 = c1 */
"mov %[c1], %[c2] \n\t" /* c1 = c2 */
"movs %[c2], #0 \n\t" /* c2 = 0 */
"adds %[k], #4 \n\t" /* k += 4 */
"cmp %[k], %[eccd] \n\t" /* k < uECC_WORDS (times 4) ? */
"blt 1b \n\t" /* if not, loop back, start with i = 0 */
"cmp %[k], %[eccd2m1] \n\t" /* k < uECC_WORDS * 2 - 1 (times 4) ? */
"blt 2b \n\t" /* if not, loop back, start with i = (k+1) - uECC_WORDS */
/* end outer loop */
"str %[c0], [%[result], %[k]] \n\t" /* p_result[uECC_WORDS * 2 - 1] = c0 */
#if (uECC_PLATFORM != uECC_arm_thumb2)
".syntax divided \n\t"
#endif
: [c0] "+r" (c0), [c1] "+r" (c1), [c2] "+r" (c2), [k] "+r" (k), [i] "=&r" (i), [t0] "=&r" (t0), [t1] "=&r" (t1)
: [result] "r" (p_result), [left] "r" (p_left), [right] "r" (p_right),
[eccd] "I" (uECC_WORDS * 4), [eccdm1] "I" ((uECC_WORDS-1) * 4), [eccd2m1] "I" ((uECC_WORDS * 2 - 1) * 4)
: "cc", "memory"
);
#else /* Thumb-1 */
register uint32_t *r0 __asm__("r0") = p_result;
register uint32_t *r1 __asm__("r1") = p_left;
register uint32_t *r2 __asm__("r2") = p_right;
__asm__ volatile (
".syntax unified \n\t"
"movs r3, #0 \n\t" /* c0 = 0 */
"movs r4, #0 \n\t" /* c1 = 0 */
"movs r5, #0 \n\t" /* c2 = 0 */
"movs r6, #0 \n\t" /* k = 0 */
"push {r0} \n\t" /* keep p_result on the stack */
"1: \n\t" /* outer loop (k < uECC_WORDS) */
"movs r7, #0 \n\t" /* r7 = i = 0 */
"b 3f \n\t"
"2: \n\t" /* outer loop (k >= uECC_WORDS) */
"movs r7, r6 \n\t" /* r7 = k */
"subs r7, %[eccdm1] \n\t" /* r7 = i = k - (uECC_WORDS - 1) (times 4) */
"3: \n\t" /* inner loop */
"push {r3, r4, r5, r6} \n\t" /* push things, r3 (c0) is at the top of stack. */
"subs r0, r6, r7 \n\t" /* r0 = k-i */
"ldr r4, [r2, r0] \n\t" /* r4 = p_right[k-i] */
"ldr r0, [r1, r7] \n\t" /* r0 = p_left[i] */
"lsrs r3, r0, #16 \n\t" /* r3 = a1 */
"uxth r0, r0 \n\t" /* r0 = a0 */
"lsrs r5, r4, #16 \n\t" /* r5 = b1 */
"uxth r4, r4 \n\t" /* r4 = b0 */
"movs r6, r3 \n\t" /* r6 = a1 */
"muls r6, r5, r6 \n\t" /* r6 = a1*b1 */
"muls r3, r4, r3 \n\t" /* r3 = b0*a1 */
"muls r5, r0, r5 \n\t" /* r5 = a0*b1 */
"muls r0, r4, r0 \n\t" /* r0 = a0*b0 */
"movs r4, #0 \n\t" /* r4 = 0 */
"adds r3, r5 \n\t" /* r3 = b0*a1 + a0*b1 */
"adcs r4, r4 \n\t" /* r4 = carry */
"lsls r4, #16 \n\t" /* r4 = carry << 16 */
"adds r6, r4 \n\t" /* r6 = a1*b1 + carry */
"lsls r4, r3, #16 \n\t" /* r4 = (b0*a1 + a0*b1) << 16 */
"lsrs r3, #16 \n\t" /* r3 = (b0*a1 + a0*b1) >> 16 */
"adds r0, r4 \n\t" /* r0 = low word = a0*b0 + ((b0*a1 + a0*b1) << 16) */
"adcs r6, r3 \n\t" /* r6 = high word = a1*b1 + carry + ((b0*a1 + a0*b1) >> 16) */
"pop {r3, r4, r5} \n\t" /* r3 = c0, r4 = c1, r5 = c2 */
"adds r3, r0 \n\t" /* add low word to c0 */
"adcs r4, r6 \n\t" /* add high word to c1, including carry */
"movs r0, #0 \n\t" /* r0 = 0 (does not affect carry bit) */
"adcs r5, r0 \n\t" /* add carry to c2 */
"pop {r6} \n\t" /* r6 = k */
"adds r7, #4 \n\t" /* i += 4 */
"cmp r7, %[eccd] \n\t" /* i < uECC_WORDS (times 4)? */
"bge 4f \n\t" /* if not, exit the loop */
"cmp r7, r6 \n\t" /* i <= k? */
"ble 3b \n\t" /* if so, continue looping */
"4: \n\t" /* end inner loop */
"ldr r0, [sp, #0] \n\t" /* r0 = p_result */
"str r3, [r0, r6] \n\t" /* p_result[k] = c0 */
"mov r3, r4 \n\t" /* c0 = c1 */
"mov r4, r5 \n\t" /* c1 = c2 */
"movs r5, #0 \n\t" /* c2 = 0 */
"adds r6, #4 \n\t" /* k += 4 */
"cmp r6, %[eccd] \n\t" /* k < uECC_WORDS (times 4) ? */
"blt 1b \n\t" /* if not, loop back, start with i = 0 */
"cmp r6, %[eccd2m1] \n\t" /* k < uECC_WORDS * 2 - 1 (times 4) ? */
"blt 2b \n\t" /* if not, loop back, start with i = (k+1) - uECC_WORDS */
/* end outer loop */
"str r3, [r0, r6] \n\t" /* p_result[uECC_WORDS * 2 - 1] = c0 */
"pop {r0} \n\t" /* pop p_result off the stack */
".syntax divided \n\t"
:
: [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)
: "r3", "r4", "r5", "r6", "r7", "cc", "memory"
);
#endif
}
#define asm_mult 1
#endif /* !asm_mult */
#if uECC_SQUARE_FUNC
#if !asm_square
static void vli_square(uint32_t *p_result, uint32_t *p_left)
{
#if (uECC_PLATFORM != uECC_arm_thumb)
uint32_t c0 = 0;
uint32_t c1 = 0;
uint32_t c2 = 0;
uint32_t k = 0;
uint32_t i, tt;
uint32_t t0, t1;
__asm__ volatile (
".syntax unified \n\t"
"1: \n\t" /* outer loop (k < uECC_WORDS) */
"movs %[i], #0 \n\t" /* i = 0 */
"b 3f \n\t"
"2: \n\t" /* outer loop (k >= uECC_WORDS) */
"movs %[i], %[k] \n\t" /* i = k */
"subs %[i], %[eccdm1] \n\t" /* i = k - (uECC_WORDS - 1) (times 4) */
"3: \n\t" /* inner loop */
"subs %[tt], %[k], %[i] \n\t" /* tt = k-i */
"ldr %[t1], [%[left], %[tt]] \n\t" /* t1 = p_left[k-i] */
"ldr %[t0], [%[left], %[i]] \n\t" /* t0 = p_left[i] */
"umull %[t0], %[t1], %[t0], %[t1] \n\t" /* (t0, t1) = p_left[i] * p_right[k-i] */
"cmp %[i], %[tt] \n\t" /* (i < k-i) ? */
"bge 4f \n\t" /* if i >= k-i, skip */
"lsls %[t1], #1 \n\t" /* high word << 1 */
"adc %[c2], #0 \n\t" /* add carry bit to c2 */
"lsls %[t0], #1 \n\t" /* low word << 1 */
"adc %[t1], #0 \n\t" /* add carry bit to high word */
"4: \n\t"
"adds %[c0], %[t0] \n\t" /* add low word to c0 */
"adcs %[c1], %[t1] \n\t" /* add high word to c1, including carry */
"adc %[c2], #0 \n\t" /* add carry to c2 */
"adds %[i], #4 \n\t" /* i += 4 */
"cmp %[i], %[k] \n\t" /* i <= k? */
"bge 5f \n\t" /* if not, exit the loop */
"subs %[tt], %[k], %[i] \n\t" /* tt = k-i */
"cmp %[i], %[tt] \n\t" /* i <= k-i? */
"ble 3b \n\t" /* if so, continue looping */
"5: \n\t" /* end inner loop */
"str %[c0], [%[result], %[k]] \n\t" /* p_result[k] = c0 */
"mov %[c0], %[c1] \n\t" /* c0 = c1 */
"mov %[c1], %[c2] \n\t" /* c1 = c2 */
"movs %[c2], #0 \n\t" /* c2 = 0 */
"adds %[k], #4 \n\t" /* k += 4 */
"cmp %[k], %[eccd] \n\t" /* k < uECC_WORDS (times 4) ? */
"blt 1b \n\t" /* if not, loop back, start with i = 0 */
"cmp %[k], %[eccd2m1] \n\t" /* k < uECC_WORDS * 2 - 1 (times 4) ? */
"blt 2b \n\t" /* if not, loop back, start with i = (k+1) - uECC_WORDS */
/* end outer loop */
"str %[c0], [%[result], %[k]] \n\t" /* p_result[uECC_WORDS * 2 - 1] = c0 */
#if (uECC_PLATFORM != uECC_arm_thumb2)
".syntax divided \n\t"
#endif
: [c0] "+r" (c0), [c1] "+r" (c1), [c2] "+r" (c2), [k] "+r" (k), [i] "=&r" (i), [tt] "=&r" (tt), [t0] "=&r" (t0), [t1] "=&r" (t1)
: [result] "r" (p_result), [left] "r" (p_left),
[eccd] "I" (uECC_WORDS * 4), [eccdm1] "I" ((uECC_WORDS-1) * 4), [eccd2m1] "I" ((uECC_WORDS * 2 - 1) * 4)
: "cc", "memory"
);
#else
register uint32_t *r0 __asm__("r0") = p_result;
register uint32_t *r1 __asm__("r1") = p_left;
__asm__ volatile (
".syntax unified \n\t"
"movs r2, #0 \n\t" /* c0 = 0 */
"movs r3, #0 \n\t" /* c1 = 0 */
"movs r4, #0 \n\t" /* c2 = 0 */
"movs r5, #0 \n\t" /* k = 0 */
"push {r0} \n\t" /* keep p_result on the stack */
"1: \n\t" /* outer loop (k < uECC_WORDS) */
"movs r6, #0 \n\t" /* r6 = i = 0 */
"b 3f \n\t"
"2: \n\t" /* outer loop (k >= uECC_WORDS) */
"movs r6, r5 \n\t" /* r6 = k */
"subs r6, %[eccdm1] \n\t" /* r6 = i = k - (uECC_WORDS - 1) (times 4) */
"3: \n\t" /* inner loop */
"push {r2, r3, r4, r5} \n\t" /* push things, r2 (c0) is at the top of stack. */
"subs r7, r5, r6 \n\t" /* r7 = k-i */
"ldr r3, [r1, r7] \n\t" /* r3 = p_left[k-i] */
"ldr r0, [r1, r6] \n\t" /* r0 = p_left[i] */
"lsrs r2, r0, #16 \n\t" /* r2 = a1 */
"uxth r0, r0 \n\t" /* r0 = a0 */
"lsrs r4, r3, #16 \n\t" /* r4 = b1 */
"uxth r3, r3 \n\t" /* r3 = b0 */
"movs r5, r2 \n\t" /* r5 = a1 */
"muls r5, r4, r5 \n\t" /* r5 = a1*b1 */
"muls r2, r3, r2 \n\t" /* r2 = b0*a1 */
"muls r4, r0, r4 \n\t" /* r4 = a0*b1 */
"muls r0, r3, r0 \n\t" /* r0 = a0*b0 */
"movs r3, #0 \n\t" /* r3 = 0 */
"adds r2, r4 \n\t" /* r2 = b0*a1 + a0*b1 */
"adcs r3, r3 \n\t" /* r3 = carry */
"lsls r3, #16 \n\t" /* r3 = carry << 16 */
"adds r5, r3 \n\t" /* r5 = a1*b1 + carry */
"lsls r3, r2, #16 \n\t" /* r3 = (b0*a1 + a0*b1) << 16 */
"lsrs r2, #16 \n\t" /* r2 = (b0*a1 + a0*b1) >> 16 */
"adds r0, r3 \n\t" /* r0 = low word = a0*b0 + ((b0*a1 + a0*b1) << 16) */
"adcs r5, r2 \n\t" /* r5 = high word = a1*b1 + carry + ((b0*a1 + a0*b1) >> 16) */
"movs r3, #0 \n\t" /* r3 = 0 */
"cmp r6, r7 \n\t" /* (i < k-i) ? */
"mov r7, r3 \n\t" /* r7 = 0 (does not affect condition)*/
"bge 4f \n\t" /* if i >= k-i, skip */
"lsls r5, #1 \n\t" /* high word << 1 */
"adcs r7, r3 \n\t" /* r7 = carry bit for c2 */
"lsls r0, #1 \n\t" /* low word << 1 */
"adcs r5, r3 \n\t" /* add carry from shift to high word */
"4: \n\t"
"pop {r2, r3, r4} \n\t" /* r2 = c0, r3 = c1, r4 = c2 */
"adds r2, r0 \n\t" /* add low word to c0 */
"adcs r3, r5 \n\t" /* add high word to c1, including carry */
"movs r0, #0 \n\t" /* r0 = 0 (does not affect carry bit) */
"adcs r4, r0 \n\t" /* add carry to c2 */
"adds r4, r7 \n\t" /* add carry from doubling (if any) */
"pop {r5} \n\t" /* r5 = k */
"adds r6, #4 \n\t" /* i += 4 */
"cmp r6, r5 \n\t" /* i <= k? */
"bge 5f \n\t" /* if not, exit the loop */
"subs r7, r5, r6 \n\t" /* r7 = k-i */
"cmp r6, r7 \n\t" /* i <= k-i? */
"ble 3b \n\t" /* if so, continue looping */
"5: \n\t" /* end inner loop */
"ldr r0, [sp, #0] \n\t" /* r0 = p_result */
"str r2, [r0, r5] \n\t" /* p_result[k] = c0 */
"mov r2, r3 \n\t" /* c0 = c1 */
"mov r3, r4 \n\t" /* c1 = c2 */
"movs r4, #0 \n\t" /* c2 = 0 */
"adds r5, #4 \n\t" /* k += 4 */
"cmp r5, %[eccd] \n\t" /* k < uECC_WORDS (times 4) ? */
"blt 1b \n\t" /* if not, loop back, start with i = 0 */
"cmp r5, %[eccd2m1] \n\t" /* k < uECC_WORDS * 2 - 1 (times 4) ? */
"blt 2b \n\t" /* if not, loop back, start with i = (k+1) - uECC_WORDS */
/* end outer loop */
"str r2, [r0, r5] \n\t" /* p_result[uECC_WORDS * 2 - 1] = c0 */
"pop {r0} \n\t" /* pop p_result off the stack */
".syntax divided \n\t"
: [r0] "+l" (r0), [r1] "+l" (r1)
: [eccd] "I" (uECC_WORDS * 4), [eccdm1] "I" ((uECC_WORDS-1) * 4), [eccd2m1] "I" ((uECC_WORDS * 2 - 1) * 4)
: "r2", "r3", "r4", "r5", "r6", "r7", "cc", "memory"
);
#endif
}
#define asm_square 1
#endif /* !asm_square */
#endif /* uECC_SQUARE_FUNC */
+14 -6
View File
@@ -42,17 +42,14 @@ def setup_osx():
global c
global link
flags = [("-arch", "x86_64"), "-fno-common", "-Wnewline-eof", "-mmacosx-version-min=10.7", "-D__DARWIN_UNIX03=0"]
flags = [("-arch", "x86_64"), "-fno-common", "-Wnewline-eof"]
c.flags.extend(flags)
c.cxx.flags += ["-stdlib=libc++"]
link.cxx.flags += ["-stdlib=libc++"]
link_flags = [("-arch", "x86_64"), "-mmacosx-version-min=10.7"]
link_flags = [("-arch", "x86_64")]
link.local_flags.extend(link_flags)
dylib_flags = [("-current_version", "1.0"), ("-compatibility_version", "1.0")]
link.local_libflags.extend(dylib_flags)
def setup_avr():
global c
global link
@@ -63,9 +60,20 @@ def setup_avr():
link.flags += ["-mmcu=atmega256rfr2", "-mrelax", "-Wl,--gc-sections"]
link.strip = True
def setup_arm_thumb():
global c
global link
c.compiler = c.GccCompiler("/cross/arm_cortex/bin/arm-none-eabi-")
link.linker = link.GccLinker("/cross/arm_cortex/bin/arm-none-eabi-")
c.flags += ["-march=armv6-m", "-mthumb", "-ffunction-sections", "-fdata-sections"]
link.local_flags += ["-march=armv6-m", "-mthumb", "-Wl,--gc-sections"]
link.strip = True
setup_build_dir()
setup_funcs = {"osx":setup_osx, "avr":setup_avr}
setup_funcs = {"osx":setup_osx, "avr":setup_avr, "arm_thumb":setup_arm_thumb}
if not emk.cleaning:
build_arch = emk.options["arch"]