Add small ARM asm. (#50)
diff --git a/asm_arm_small.inc b/asm_arm_small.inc
new file mode 100644
index 0000000..2b1b0a7
--- /dev/null
+++ b/asm_arm_small.inc
@@ -0,0 +1,407 @@
+#if (uECC_PLATFORM == uECC_arm_thumb)
+    #define REG_RW "+l"
+    #define REG_WRITE "=l"
+#else
+    #define REG_RW "+r"
+    #define REG_WRITE "=r"
+#endif
+
+#if (uECC_PLATFORM == uECC_arm_thumb2)
+    #define RESUME_SYNTAX
+#else
+    #define RESUME_SYNTAX ".syntax divided \n\t"
+#endif
+
+static uECC_word_t vli_add(uECC_word_t *result,
+                           const uECC_word_t *left,
+                           const uECC_word_t *right,
+                           wordcount_t num_words) {
+    uint32_t carry = 0;
+    uint32_t left_word;
+    uint32_t right_word;
+    
+    __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 (carry = 0 after this). */
+        "adcs %[left], %[right] \n\t"     /* Add with carry. */
+        "adcs %[carry], %[carry] \n\t"    /* Store carry bit. */
+        "stmia %[dptr]!, {%[left]} \n\t"  /* Store result word. */
+        "subs %[ctr], #1 \n\t"            /* Decrement counter. */
+        "bne 1b \n\t"                     /* Loop until counter == 0. */
+        RESUME_SYNTAX
+        : [dptr] REG_RW (result), [lptr] REG_RW (left), [rptr] REG_RW (right),
+          [ctr] REG_RW (num_words), [carry] REG_RW (carry),
+          [left] REG_WRITE (left_word), [right] REG_WRITE (right_word)
+        :
+        : "cc", "memory"
+    );
+    return carry;
+}
+#define asm_add 1
+
+static uint32_t vli_sub(uECC_word_t *result,
+                        const uECC_word_t *left,
+                        const uECC_word_t *right,
+                        wordcount_t num_words) {
+    uint32_t carry = 1; /* carry = 1 initially (means don't borrow) */
+    uint32_t left_word;
+    uint32_t right_word;
+    
+    __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 (carry = 0 after this). */
+        "sbcs %[left], %[right] \n\t"     /* Subtract with borrow. */
+        "adcs %[carry], %[carry] \n\t"    /* Store carry bit. */
+        "stmia %[dptr]!, {%[left]} \n\t"  /* Store result word. */
+        "subs %[ctr], #1 \n\t"            /* Decrement counter. */
+        "bne 1b \n\t"                     /* Loop until counter == 0. */
+        RESUME_SYNTAX
+        : [dptr] REG_RW (result), [lptr] REG_RW (left), [rptr] REG_RW (right),
+          [ctr] REG_RW (num_words), [carry] REG_RW (carry),
+          [left] REG_WRITE (left_word), [right] REG_WRITE (right_word)
+        :
+        : "cc", "memory"
+    );
+    return !carry;
+}
+#define asm_sub 1
+
+static void vli_mult(uECC_word_t *result,
+                     const uECC_word_t *left,
+                     const uECC_word_t *right,
+                     wordcount_t num_words) {
+#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 < num_words) */
+        "movs %[i], #0 \n\t" /* i = 0 */
+        "b 3f \n\t"
+        
+        "2: \n\t" /* outer loop (k >= num_words) */
+        "movs %[i], %[k] \n\t"         /* i = k */
+        "subs %[i], %[last_word] \n\t" /* i = k - (num_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 = right[k - i] */
+        "ldr %[t0], [%[left], %[i]] \n\t"   /* t0 = left[i] */
+        
+        "umull %[t0], %[t1], %[t0], %[t1] \n\t" /* (t0, t1) = left[i] * 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], %[last_word] \n\t" /* i > (num_words - 1) (times 4)? */
+        "bgt 4f \n\t"                 /*   if so, 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" /* 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], %[last_word] \n\t" /* k <= (num_words - 1) (times 4) ? */
+        "ble 1b \n\t"                 /*   if so, loop back, start with i = 0 */
+        "cmp %[k], %[last_word], lsl #1 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */
+        "ble 2b \n\t"                 /*   if so, loop back, start with i = (k + 1) - num_words */
+        /* end outer loop */
+        
+        "str %[c0], [%[result], %[k]] \n\t" /* result[num_words * 2 - 1] = c0 */
+        RESUME_SYNTAX
+        : [c0] "+r" (c0), [c1] "+r" (c1), [c2] "+r" (c2),
+          [k] "+r" (k), [i] "=&r" (i), [t0] "=&r" (t0), [t1] "=&r" (t1)
+        : [result] "r" (result), [left] "r" (left), [right] "r" (right),
+          [last_word] "r" ((num_words - 1) * 4)
+        : "cc", "memory"
+    );
+    
+#else /* Thumb-1 */
+
+    register uint32_t *r0 __asm__("r0") = result;
+    register const uint32_t *r1 __asm__("r1") = left;
+    register const uint32_t *r2 __asm__("r2") = 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 result on the stack */
+        
+        "1: \n\t" /* outer loop (k < num_words) */
+        "movs r7, #0 \n\t" /* r7 = i = 0 */
+        "b 3f \n\t"
+        
+        "2: \n\t" /* outer loop (k >= num_words) */
+        "movs r7, r6 \n\t"           /* r7 = k */
+        "subs r7, %[last_word] \n\t" /* r7 = i = k - (num_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 = right[k - i] */
+        "ldr r0, [r1, r7] \n\t" /* r0 = 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, %[last_word] \n\t" /* i > (num_words - 1) (times 4)? */
+        "bgt 4f \n\t"               /*   if so, 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 = result */
+        
+        "str r3, [r0, r6] \n\t"     /* 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, %[last_word] \n\t" /* k <= (num_words - 1) (times 4) ? */
+        "ble 1b \n\t"               /*   if so, loop back, start with i = 0 */
+        "cmp r6, %[lw2] \n\t"       /* k <= (num_words * 2 - 2) (times 4) ? */
+        "ble 2b \n\t"               /*   if so, loop back, start with i = (k + 1) - num_words */
+        /* end outer loop */
+        
+        "str r3, [r0, r6] \n\t" /* result[num_words * 2 - 1] = c0 */
+        "pop {r0} \n\t"         /* pop result off the stack */
+        
+        ".syntax divided \n\t"
+        : 
+        : [r0] "l" (r0), [r1] "l" (r1), [r2] "l" (r2),
+          [last_word] "r" ((num_words - 1) * 4), [lw2] "r" ((num_words - 1) * 4 * 2)
+        : "r3", "r4", "r5", "r6", "r7", "cc", "memory"
+    );
+#endif
+}
+#define asm_mult 1
+
+#if uECC_SQUARE_FUNC
+static void vli_square(uECC_word_t *result, const uECC_word_t *left, wordcount_t num_words) {
+#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 < num_words) */
+        "movs %[i], #0 \n\t" /* i = 0 */
+        "b 3f \n\t"
+        
+        "2: \n\t" /* outer loop (k >= num_words) */
+        "movs %[i], %[k] \n\t"         /* i = k */
+        "subs %[i], %[last_word] \n\t" /* i = k - (num_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 = left[k - i] */
+        "ldr %[t0], [%[left], %[i]] \n\t"  /* t0 = left[i] */
+        
+        "umull %[t0], %[t1], %[t0], %[t1] \n\t" /* (t0, t1) = left[i] * 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 so, 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" /* 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], %[last_word] \n\t" /* k <= (num_words - 1) (times 4) ? */
+        "ble 1b \n\t"                 /*   if so, loop back, start with i = 0 */
+        "cmp %[k], %[last_word], lsl #1 \n\t" /* k <= (num_words * 2 - 2) (times 4) ? */
+        "ble 2b \n\t"                 /*   if so, loop back, start with i = (k + 1) - num_words */
+        /* end outer loop */
+        
+        "str %[c0], [%[result], %[k]] \n\t" /* result[num_words * 2 - 1] = c0 */
+        RESUME_SYNTAX
+        : [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" (result), [left] "r" (left), [last_word] "r" ((num_words - 1) * 4)
+        : "cc", "memory"
+    );
+    
+#else
+
+    register uint32_t *r0 __asm__("r0") = result;
+    register const uint32_t *r1 __asm__("r1") = 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 result on the stack */
+        
+        "1: \n\t" /* outer loop (k < num_words) */
+        "movs r6, #0 \n\t" /* r6 = i = 0 */
+        "b 3f \n\t"
+        
+        "2: \n\t" /* outer loop (k >= num_words) */
+        "movs r6, r5 \n\t"        /* r6 = k */
+        "subs r6, %[last_word] \n\t" /* r6 = i = k - (num_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 = left[k - i] */
+        "ldr r0, [r1, r6] \n\t" /* r0 = 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 so, 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 = result */
+        
+        "str r2, [r0, r5] \n\t"     /* 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, %[last_word] \n\t" /* k <= (num_words - 1) (times 4) ? */
+        "ble 1b \n\t"               /*   if so, loop back, start with i = 0 */
+        "cmp r5, %[lw2] \n\t"       /* k <= (num_words * 2 - 2) (times 4) ? */
+        "ble 2b \n\t"               /*   if so, loop back, start with i = (k + 1) - num_words */
+        /* end outer loop */
+        
+        "str r2, [r0, r5] \n\t" /* result[num_words * 2 - 1] = c0 */
+        "pop {r0} \n\t"        /* pop result off the stack */
+
+        ".syntax divided \n\t"
+        : [r0] "+l" (r0), [r1] "+l" (r1)
+        : [last_word] "r" ((num_words - 1) * 4), [lw2] "r" ((num_words - 1) * 4 * 2)
+        : "r2", "r3", "r4", "r5", "r6", "r7", "cc", "memory"
+    );
+#endif
+}
+#define asm_square 1
+#endif /* uECC_SQUARE_FUNC */
diff --git a/platform-specific.inc b/platform-specific.inc
index f259615..bf15ce2 100644
--- a/platform-specific.inc
+++ b/platform-specific.inc
@@ -7,6 +7,8 @@
         #define uECC_PLATFORM uECC_arm_thumb
     #elif defined(__arm__) || defined(_M_ARM)
         #define uECC_PLATFORM uECC_arm
+    #elif defined(__aarch64__)
+        #define uECC_PLATFORM uECC_arm64
     #elif defined(__i386__) || defined(_M_IX86) || defined(_X86_) || defined(__I86__)
         #define uECC_PLATFORM uECC_x86
     #elif defined(__amd64__) || defined(_M_X64)
@@ -19,7 +21,7 @@
 #ifndef uECC_WORD_SIZE
     #if uECC_PLATFORM == uECC_avr
         #define uECC_WORD_SIZE 1
-    #elif (uECC_PLATFORM == uECC_x86_64)
+    #elif (uECC_PLATFORM == uECC_x86_64 || uECC_PLATFORM == uECC_arm64)
         #define uECC_WORD_SIZE 8
     #else
         #define uECC_WORD_SIZE 4
@@ -30,6 +32,19 @@
     #error "Unsupported value for uECC_WORD_SIZE"
 #endif
 
+/* Optimization options... */
+#define uECC_asm_none  0
+#define uECC_asm_small 1
+#define uECC_asm_fast  2
+#ifndef uECC_ASM
+    #define uECC_ASM uECC_asm_small
+#endif
+
+#ifndef uECC_SQUARE_FUNC
+    #define uECC_SQUARE_FUNC 0
+#endif
+/* --- end --- */
+
 #if (uECC_ASM && (uECC_PLATFORM == uECC_avr) && (uECC_WORD_SIZE != 1))
     #pragma message ("uECC_WORD_SIZE must be 1 when using AVR asm")
     #undef uECC_WORD_SIZE
diff --git a/uECC.c b/uECC.c
index 17740b6..2820f6c 100644
--- a/uECC.c
+++ b/uECC.c
@@ -31,13 +31,20 @@
     void (*mmod_fast)(uECC_word_t *result, uECC_word_t *product);
 };
 
+#if (uECC_ASM == uECC_asm_small)
+    #if (uECC_PLATFORM == uECC_arm || uECC_PLATFORM == uECC_arm_thumb || \
+            uECC_PLATFORM == uECC_arm_thumb2)
+        #include "asm_arm_small.inc"
+    #endif
+#endif
+
 static uECC_RNG_Function g_rng_function = &default_RNG;
 
 void uECC_set_rng(uECC_RNG_Function rng_function) {
     g_rng_function = rng_function;
 }
 
-static void vli_clear(uECC_word_t *vli, const wordcount_t num_words) {
+static void vli_clear(uECC_word_t *vli, wordcount_t num_words) {
     wordcount_t i;
     for (i = 0; i < num_words; ++i) {
         vli[i] = 0;
@@ -45,7 +52,7 @@
 }
 
 /* Returns 1 if vli == 0, 0 otherwise. */
-static uECC_word_t vli_isZero(const uECC_word_t *vli, const wordcount_t num_words) {
+static uECC_word_t vli_isZero(const uECC_word_t *vli, wordcount_t num_words) {
     wordcount_t i;
     for (i = 0; i < num_words; ++i) {
         if (vli[i]) {
@@ -90,7 +97,7 @@
 }
 
 /* Sets dest = src. */
-static void vli_set(uECC_word_t *dest, const uECC_word_t *src, const wordcount_t num_words) {
+static void vli_set(uECC_word_t *dest, const uECC_word_t *src, wordcount_t num_words) {
     wordcount_t i;
     for (i = 0; i < num_words; ++i) {
         dest[i] = src[i];
@@ -100,7 +107,7 @@
 /* Returns sign of left - right. */
 static cmpresult_t vli_cmp(const uECC_word_t *left,
                            const uECC_word_t *right,
-                           const wordcount_t num_words) {
+                           wordcount_t num_words) {
     swordcount_t i;
     for (i = num_words - 1; i >= 0; --i) {
         if (left[i] > right[i]) {
@@ -113,7 +120,7 @@
 }
 
 /* Computes vli = vli >> 1. */
-static void vli_rshift1(uECC_word_t *vli, const wordcount_t num_words) {
+static void vli_rshift1(uECC_word_t *vli, wordcount_t num_words) {
     uECC_word_t *end = vli;
     uECC_word_t carry = 0;
     
@@ -126,10 +133,11 @@
 }
 
 /* Computes result = left + right, returning carry. Can modify in place. */
+#if !asm_add
 static uECC_word_t vli_add(uECC_word_t *result,
                            const uECC_word_t *left,
                            const uECC_word_t *right,
-                           const wordcount_t num_words) {
+                           wordcount_t num_words) {
     uECC_word_t carry = 0;
     wordcount_t i;
     for (i = 0; i < num_words; ++i) {
@@ -141,12 +149,14 @@
     }
     return carry;
 }
+#endif /* !asm_add */
 
 /* Computes result = left - right, returning borrow. Can modify in place. */
+#if !asm_sub
 static uECC_word_t vli_sub(uECC_word_t *result,
                            const uECC_word_t *left,
                            const uECC_word_t *right,
-                           const wordcount_t num_words) {
+                           wordcount_t num_words) {
     uECC_word_t borrow = 0;
     wordcount_t i;
     for (i = 0; i < num_words; ++i) {
@@ -158,6 +168,7 @@
     }
     return borrow;
 }
+#endif /* !asm_sub */
 
 static void muladd(uECC_word_t a,
                    uECC_word_t b,
@@ -199,10 +210,11 @@
 #endif
 }
 
+#if !asm_mult
 static void vli_mult(uECC_word_t *result,
                      const uECC_word_t *left,
                      const uECC_word_t *right,
-                     const wordcount_t num_words) {
+                     wordcount_t num_words) {
     uECC_word_t r0 = 0;
     uECC_word_t r1 = 0;
     uECC_word_t r2 = 0;
@@ -229,6 +241,7 @@
     }
     result[num_words * 2 - 1] = r0;
 }
+#endif /* !asm_mult */
 
 #if uECC_SQUARE_FUNC
 
@@ -279,7 +292,8 @@
 #endif
 }
 
-static void vli_square(uECC_word_t *result, const uECC_word_t *left, const wordcount_t num_words) {
+#if !asm_square
+static void vli_square(uECC_word_t *result, const uECC_word_t *left, wordcount_t num_words) {
     uECC_word_t r0 = 0;
     uECC_word_t r1 = 0;
     uECC_word_t r2 = 0;
@@ -303,6 +317,7 @@
     
     result[num_words * 2 - 1] = r0;
 }
+#endif /* !asm_square */
 
 #else /* uECC_SQUARE_FUNC */
 
@@ -316,7 +331,7 @@
                        const uECC_word_t *left,
                        const uECC_word_t *right,
                        const uECC_word_t *mod,
-                       const wordcount_t num_words) {
+                       wordcount_t num_words) {
     uECC_word_t carry = vli_add(result, left, right, num_words);
     if (carry || vli_cmp(result, mod, num_words) >= 0) {
         /* result > mod (result = mod + remainder), so subtract mod to get remainder. */
@@ -330,7 +345,7 @@
                        const uECC_word_t *left,
                        const uECC_word_t *right,
                        const uECC_word_t *mod,
-                       const wordcount_t num_words) {
+                       wordcount_t num_words) {
     uECC_word_t l_borrow = vli_sub(result, left, right, num_words);
     if (l_borrow) {
         /* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
@@ -344,7 +359,7 @@
 static void vli_mmod(uECC_word_t *result,
                      uECC_word_t *product,
                      const uECC_word_t *mod,
-                     const wordcount_t num_words) {
+                     wordcount_t num_words) {
     uECC_word_t mod_multiple[2 * uECC_MAX_WORDS];
     uECC_word_t tmp[2 * uECC_MAX_WORDS];
     uECC_word_t *v[2] = {tmp, product};
@@ -378,7 +393,7 @@
                         const uECC_word_t *left,
                         const uECC_word_t *right,
                         const uECC_word_t *mod,
-                        const wordcount_t num_words) {
+                        wordcount_t num_words) {
     uECC_word_t product[2 * uECC_MAX_WORDS];
     vli_mult(product, left, right, num_words);
     vli_mmod(result, product, mod, num_words);
@@ -399,7 +414,7 @@
 static void vli_modSquare(uECC_word_t *result,
                           const uECC_word_t *left,
                           const uECC_word_t *mod,
-                          const wordcount_t num_words) {
+                          wordcount_t num_words) {
     uECC_word_t product[2 * uECC_MAX_WORDS];
     vli_square(product, left, num_words);
     vli_mmod(result, product, mod, num_words);
@@ -430,7 +445,7 @@
 
 static void vli_modInv_update(uECC_word_t *uv,
                               const uECC_word_t *mod,
-                              const wordcount_t num_words) {
+                              wordcount_t num_words) {
     uECC_word_t carry = 0;
     if (!EVEN(uv)) {
         carry = vli_add(uv, uv, mod, num_words);
@@ -444,7 +459,7 @@
 static void vli_modInv(uECC_word_t *result,
                        const uECC_word_t *input,
                        const uECC_word_t *mod,
-                       const wordcount_t num_words) {
+                       wordcount_t num_words) {
     uECC_word_t a[uECC_MAX_WORDS], b[uECC_MAX_WORDS], u[uECC_MAX_WORDS], v[uECC_MAX_WORDS];
     cmpresult_t cmpResult;
     
@@ -751,7 +766,7 @@
 /* Generate a random integer with num_bits bits. The remaining high bits
    in the buffer (if any) are zeroed. */
 static cmpresult_t generate_random_int(uECC_word_t *random,
-                                       const wordcount_t num_words,
+                                       wordcount_t num_words,
                                        const wordcount_t num_bits) {
     if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) {
         return 0;
diff --git a/uECC.h b/uECC.h
index 52fa26a..6e416c3 100644
--- a/uECC.h
+++ b/uECC.h
@@ -13,34 +13,17 @@
 #define uECC_x86_64     2
 #define uECC_arm        3
 #define uECC_arm_thumb  4
-#define uECC_avr        5
-#define uECC_arm_thumb2 6
+#define uECC_arm_thumb2 5
+#define uECC_arm64      6
+#define uECC_avr        7
+
 
 /* If desired, you can define uECC_WORD_SIZE as appropriate for your platform (1, 4, or 8 bytes).
 If uECC_WORD_SIZE is not explicitly defined then it will be automatically set based on your
 platform. */
 
-/* Inline assembly options.
-uECC_asm_none  - Use standard C99 only.
-uECC_asm_small - Use GCC inline assembly for the target platform (if available), optimized for
-                 minimum size.
-uECC_asm_fast  - Use GCC inline assembly optimized for maximum speed. */
-#define uECC_asm_none  0
-#define uECC_asm_small 1
-#define uECC_asm_fast  2
-#ifndef uECC_ASM
-    #define uECC_ASM uECC_asm_fast
-#endif
-
-/* uECC_SQUARE_FUNC - If enabled (defined as nonzero), this will cause a specific function to be
-used for (scalar) squaring instead of the generic multiplication function. This will make things
-faster by about 8% but increases the code size. */
-#ifndef uECC_SQUARE_FUNC
-    #define uECC_SQUARE_FUNC 0
-#endif
-
 struct uECC_Curve_t;
-typedef const struct uECC_Curve_t * const uECC_Curve;
+typedef const struct uECC_Curve_t * uECC_Curve;
 
 #ifdef __cplusplus
 extern "C"