Add a case to sshbn.h for 64-bit Visual Studio.

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.
This commit is contained in:
Simon Tatham 2015-12-16 14:12:36 +00:00
Родитель c2ec13c7e9
Коммит 84cd309295
1 изменённых файлов: 47 добавлений и 0 удалений

47
sshbn.h
Просмотреть файл

@ -67,6 +67,53 @@
#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 */