]> asedeno.scripts.mit.edu Git - PuTTY.git/blob - sshbn.h
Move BignumInt definitions into a header file.
[PuTTY.git] / sshbn.h
1 /*
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
6  * it too.
7  */
8
9 /*
10  * Usage notes:
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
15  *    to avoid this case.
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.
21  */
22
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) \
31     __asm__("div %2" : \
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 { \
45     __asm mov edx, hi \
46     __asm mov eax, lo \
47     __asm div w \
48     __asm mov r, edx \
49     __asm mov q, eax \
50 } while(0)
51 #elif defined _LP64
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; \
61     q = n / w; \
62     r = n % w; \
63 } while (0)
64 #elif defined _LLP64
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; \
74     q = n / w; \
75     r = n % w; \
76 } while (0)
77 #else
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; \
87     q = n / w; \
88     r = n % w; \
89 } while (0)
90 #endif
91
92 #define BIGNUM_INT_BYTES (BIGNUM_INT_BITS / 8)