diff --git a/asm_arm.inc b/asm_arm.inc new file mode 100644 index 0000000..ed306bb --- /dev/null +++ b/asm_arm.inc @@ -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 */ diff --git a/emk_project.py b/emk_project.py index fd08f3f..cad35a4 100644 --- a/emk_project.py +++ b/emk_project.py @@ -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"]