]> asedeno.scripts.mit.edu Git - PuTTY.git/commitdiff
Add a case to sshbn.h for 64-bit Visual Studio.
authorSimon Tatham <anakin@pobox.com>
Wed, 16 Dec 2015 14:12:36 +0000 (14:12 +0000)
committerSimon Tatham <anakin@pobox.com>
Wed, 16 Dec 2015 14:21:09 +0000 (14:21 +0000)
This commit fulfills the promise of the previous one: now one of the
branches of sshbn.h's big ifdef _doesn't_ define a BignumDblInt, and
instead provides implementations of the primitive arithmetic macros in
terms of Visual Studio's x86-64 compiler intrinsics. So now, when this
codebase is compiled with 64-bit VS, it can use a 64-bit BignumInt and
everything still seems to work.

sshbn.h

diff --git a/sshbn.h b/sshbn.h
index 6f5877b00d369b4f691a48d5e0f144c0a7ea2a74..6ee97ee65785e70360631e818c6328fdd0677bf1 100644 (file)
--- a/sshbn.h
+++ b/sshbn.h
   #define BIGNUM_INT_BITS 64
   #define DEFINE_BIGNUMDBLINT typedef __uint128_t BignumDblInt
 
+#elif defined _MSC_VER && defined _M_AMD64
+
+  /*
+   * 64-bit BignumInt, using Visual Studio x86-64 compiler intrinsics.
+   *
+   * 64-bit Visual Studio doesn't provide very much in the way of help
+   * here: there's no int128 type, and also no inline assembler giving
+   * us direct access to the x86-64 MUL or ADC instructions. However,
+   * there are compiler intrinsics giving us that access, so we can
+   * use those - though it turns out we have to be a little careful,
+   * since they seem to generate wrong code if their pointer-typed
+   * output parameters alias their inputs. Hence all the internal temp
+   * variables inside the macros.
+   */
+
+  #include <intrin.h>
+  typedef unsigned char BignumCarry; /* the type _addcarry_u64 likes to use */
+  typedef unsigned __int64 BignumInt;
+  #define BIGNUM_INT_BITS 64
+  #define BignumADC(ret, retc, a, b, c) do                \
+      {                                                   \
+          BignumInt ADC_tmp;                              \
+          (retc) = _addcarry_u64(c, a, b, &ADC_tmp);      \
+          (ret) = ADC_tmp;                                \
+      } while (0)
+  #define BignumMUL(rh, rl, a, b) do              \
+      {                                           \
+          BignumInt MULADD_hi;                    \
+          (rl) = _umul128(a, b, &MULADD_hi);      \
+          (rh) = MULADD_hi;                       \
+      } while (0)
+  #define BignumMULADD(rh, rl, a, b, addend) do                           \
+      {                                                                   \
+          BignumInt MULADD_lo, MULADD_hi;                                 \
+          MULADD_lo = _umul128(a, b, &MULADD_hi);                         \
+          MULADD_hi += _addcarry_u64(0, MULADD_lo, (addend), &(rl));     \
+          (rh) = MULADD_hi;                                               \
+      } while (0)
+  #define BignumMULADD2(rh, rl, a, b, addend1, addend2) do                \
+      {                                                                   \
+          BignumInt MULADD_lo1, MULADD_lo2, MULADD_hi;                    \
+          MULADD_lo1 = _umul128(a, b, &MULADD_hi);                        \
+          MULADD_hi += _addcarry_u64(0, MULADD_lo1, (addend1), &MULADD_lo2); \
+          MULADD_hi += _addcarry_u64(0, MULADD_lo2, (addend2), &(rl));    \
+          (rh) = MULADD_hi;                                               \
+      } while (0)
+
 #elif defined __GNUC__ || defined _LLP64 || __STDC__ >= 199901L
 
   /* 32-bit BignumInt, using C99 unsigned long long as BignumDblInt */