2 * sshbn.h: the assorted conditional definitions of BignumInt and
3 * multiply/divide macros used throughout the bignum code to treat
4 * numbers as arrays of the most conveniently sized word for the
5 * target machine. Exported so that other code (e.g. poly1305) can use
11 * * Do not call the DIVMOD_WORD macro with expressions such as array
12 * subscripts, as some implementations object to this (see below).
13 * * Note that none of the division methods below will cope if the
14 * quotient won't fit into BIGNUM_INT_BITS. Callers should be careful
16 * If this condition occurs, in the case of the x86 DIV instruction,
17 * an overflow exception will occur, which (according to a correspondent)
18 * will manifest on Windows as something like
19 * 0xC0000095: Integer overflow
20 * The C variant won't give the right answer, either.
23 #if defined __GNUC__ && defined __i386__
24 typedef unsigned long BignumInt;
25 typedef unsigned long long BignumDblInt;
26 #define BIGNUM_INT_MASK 0xFFFFFFFFUL
27 #define BIGNUM_TOP_BIT 0x80000000UL
28 #define BIGNUM_INT_BITS 32
29 #define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
30 #define DIVMOD_WORD(q, r, hi, lo, w) \
32 "=d" (r), "=a" (q) : \
33 "r" (w), "d" (hi), "a" (lo))
34 #elif defined _MSC_VER && defined _M_IX86
35 typedef unsigned __int32 BignumInt;
36 typedef unsigned __int64 BignumDblInt;
37 #define BIGNUM_INT_MASK 0xFFFFFFFFUL
38 #define BIGNUM_TOP_BIT 0x80000000UL
39 #define BIGNUM_INT_BITS 32
40 #define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
41 /* Note: MASM interprets array subscripts in the macro arguments as
42 * assembler syntax, which gives the wrong answer. Don't supply them.
43 * <http://msdn2.microsoft.com/en-us/library/bf1dw62z.aspx> */
44 #define DIVMOD_WORD(q, r, hi, lo, w) do { \
52 /* 64-bit architectures can do 32x32->64 chunks at a time */
53 typedef unsigned int BignumInt;
54 typedef unsigned long BignumDblInt;
55 #define BIGNUM_INT_MASK 0xFFFFFFFFU
56 #define BIGNUM_TOP_BIT 0x80000000U
57 #define BIGNUM_INT_BITS 32
58 #define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
59 #define DIVMOD_WORD(q, r, hi, lo, w) do { \
60 BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \
65 /* 64-bit architectures in which unsigned long is 32 bits, not 64 */
66 typedef unsigned long BignumInt;
67 typedef unsigned long long BignumDblInt;
68 #define BIGNUM_INT_MASK 0xFFFFFFFFUL
69 #define BIGNUM_TOP_BIT 0x80000000UL
70 #define BIGNUM_INT_BITS 32
71 #define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
72 #define DIVMOD_WORD(q, r, hi, lo, w) do { \
73 BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \
78 /* Fallback for all other cases */
79 typedef unsigned short BignumInt;
80 typedef unsigned long BignumDblInt;
81 #define BIGNUM_INT_MASK 0xFFFFU
82 #define BIGNUM_TOP_BIT 0x8000U
83 #define BIGNUM_INT_BITS 16
84 #define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
85 #define DIVMOD_WORD(q, r, hi, lo, w) do { \
86 BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \
92 #define BIGNUM_INT_BYTES (BIGNUM_INT_BITS / 8)