Add x86-64 const-time assembly

Signed-off-by: Dave Rodgman <dave.rodgman@arm.com>
diff --git a/library/constant_time_impl.h b/library/constant_time_impl.h
index 8da15a8..73e91cc 100644
--- a/library/constant_time_impl.h
+++ b/library/constant_time_impl.h
@@ -71,6 +71,8 @@
 #define MBEDTLS_CT_ARM_ASM
 #elif defined(__aarch64__)
 #define MBEDTLS_CT_AARCH64_ASM
+#elif defined(__amd64__) || defined(__x86_64__)
+#define MBEDTLS_CT_X86_64_ASM
 #endif
 #endif
 
@@ -175,6 +177,19 @@
                   "cc" /* clobbers flag bits */
                   );
     return (mbedtls_ct_condition_t) x;
+#elif defined(MBEDTLS_CT_X86_64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64))
+    uint64_t s;
+    asm volatile ("mov  %[x], %[s]                                \n\t"
+                  "neg  %[s]                                      \n\t"
+                  "or   %[x], %[s]                                \n\t"
+                  "sar  $63, %[s]                                 \n\t"
+                  :
+                  [s] "=&a" (s)
+                  :
+                  [x] "D" (x)
+                  :
+                  );
+    return (mbedtls_ct_condition_t) s;
 #else
     const mbedtls_ct_uint_t xo = mbedtls_ct_compiler_opaque(x);
 #if defined(_MSC_VER)
@@ -230,6 +245,19 @@
                   "cc"
                   );
     return (mbedtls_ct_uint_t) condition;
+#elif defined(MBEDTLS_CT_X86_64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64))
+    asm volatile ("and  %[condition], %[if1]                      \n\t"
+                  "not  %[condition]                              \n\t"
+                  "and  %[condition], %[if0]                      \n\t"
+                  "or   %[if1], %[if0]                            \n\t"
+                  :
+                  [condition] "+&D" (condition),
+                  [if1] "+&S" (if1),
+                  [if0] "+&a" (if0)
+                  :
+                  :
+                  );
+    return if0;
 #else
     mbedtls_ct_condition_t not_cond =
         (mbedtls_ct_condition_t) (~mbedtls_ct_compiler_opaque(condition));
@@ -274,6 +302,25 @@
         "cc"
         );
     return (mbedtls_ct_condition_t) x;
+#elif defined(MBEDTLS_CT_X86_64_ASM) && (defined(MBEDTLS_CT_SIZE_32) || defined(MBEDTLS_CT_SIZE_64))
+    uint64_t mask;
+    asm volatile ("mov %[x], %[mask]                              \n\t"
+                  "xor %[y], %[mask]                              \n\t"
+                  "sub %[y], %[x]                                 \n\t"
+                  "and %[mask], %[y]                              \n\t"
+                  "not %[mask]                                    \n\t"
+                  "and %[mask], %[x]                              \n\t"
+                  "or %[y], %[x]                                  \n\t"
+                  "mov %[x], %[mask]                              \n\t"
+                  "sar $63, %[mask]                               \n\t"
+                  :
+                  [mask] "=&a" (mask),
+                  [x] "+&S" (x),
+                  [y] "+&D" (y)
+                  :
+                  :
+                  );
+    return (mbedtls_ct_condition_t) mask;
 #else
     /* Ensure that the compiler cannot optimise the following operations over x and y,
      * even if it knows the value of x and y.