Commit | Line | Data |
---|---|---|
f85d8186 MW |
1 | /* |
2 | * Internals details of the bignum representation. | |
3 | */ | |
4 | ||
5 | #ifndef PUTTY_BN_INTERNAL_H | |
6 | #define PUTTY_BN_INTERNAL_H | |
7 | ||
8 | /* | |
9 | * Usage notes: | |
10 | * * Do not call the DIVMOD_WORD macro with expressions such as array | |
11 | * subscripts, as some implementations object to this (see below). | |
12 | * * Note that none of the division methods below will cope if the | |
13 | * quotient won't fit into BIGNUM_INT_BITS. Callers should be careful | |
14 | * to avoid this case. | |
15 | * If this condition occurs, in the case of the x86 DIV instruction, | |
16 | * an overflow exception will occur, which (according to a correspondent) | |
17 | * will manifest on Windows as something like | |
18 | * 0xC0000095: Integer overflow | |
19 | * The C variant won't give the right answer, either. | |
20 | */ | |
21 | ||
22 | #if defined __GNUC__ && defined __i386__ | |
23 | typedef unsigned long BignumInt; | |
24 | typedef unsigned long long BignumDblInt; | |
25 | #define BIGNUM_INT_MASK 0xFFFFFFFFUL | |
26 | #define BIGNUM_TOP_BIT 0x80000000UL | |
27 | #define BIGNUM_INT_BITS 32 | |
28 | #define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2) | |
29 | #define DIVMOD_WORD(q, r, hi, lo, w) \ | |
30 | __asm__("div %2" : \ | |
31 | "=d" (r), "=a" (q) : \ | |
32 | "r" (w), "d" (hi), "a" (lo)) | |
33 | #elif defined _MSC_VER && defined _M_IX86 | |
34 | typedef unsigned __int32 BignumInt; | |
35 | typedef unsigned __int64 BignumDblInt; | |
36 | #define BIGNUM_INT_MASK 0xFFFFFFFFUL | |
37 | #define BIGNUM_TOP_BIT 0x80000000UL | |
38 | #define BIGNUM_INT_BITS 32 | |
39 | #define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2) | |
40 | /* Note: MASM interprets array subscripts in the macro arguments as | |
41 | * assembler syntax, which gives the wrong answer. Don't supply them. | |
42 | * <http://msdn2.microsoft.com/en-us/library/bf1dw62z.aspx> */ | |
43 | #define DIVMOD_WORD(q, r, hi, lo, w) do { \ | |
44 | __asm mov edx, hi \ | |
45 | __asm mov eax, lo \ | |
46 | __asm div w \ | |
47 | __asm mov r, edx \ | |
48 | __asm mov q, eax \ | |
49 | } while(0) | |
50 | #elif defined _LP64 | |
51 | /* 64-bit architectures can do 32x32->64 chunks at a time */ | |
52 | typedef unsigned int BignumInt; | |
53 | typedef unsigned long BignumDblInt; | |
54 | #define BIGNUM_INT_MASK 0xFFFFFFFFU | |
55 | #define BIGNUM_TOP_BIT 0x80000000U | |
56 | #define BIGNUM_INT_BITS 32 | |
57 | #define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2) | |
58 | #define DIVMOD_WORD(q, r, hi, lo, w) do { \ | |
59 | BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \ | |
60 | q = n / w; \ | |
61 | r = n % w; \ | |
62 | } while (0) | |
63 | #elif defined _LLP64 | |
64 | /* 64-bit architectures in which unsigned long is 32 bits, not 64 */ | |
65 | typedef unsigned long BignumInt; | |
66 | typedef unsigned long long BignumDblInt; | |
67 | #define BIGNUM_INT_MASK 0xFFFFFFFFUL | |
68 | #define BIGNUM_TOP_BIT 0x80000000UL | |
69 | #define BIGNUM_INT_BITS 32 | |
70 | #define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2) | |
71 | #define DIVMOD_WORD(q, r, hi, lo, w) do { \ | |
72 | BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \ | |
73 | q = n / w; \ | |
74 | r = n % w; \ | |
75 | } while (0) | |
76 | #else | |
77 | /* Fallback for all other cases */ | |
78 | typedef unsigned short BignumInt; | |
79 | typedef unsigned long BignumDblInt; | |
80 | #define BIGNUM_INT_MASK 0xFFFFU | |
81 | #define BIGNUM_TOP_BIT 0x8000U | |
82 | #define BIGNUM_INT_BITS 16 | |
83 | #define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2) | |
84 | #define DIVMOD_WORD(q, r, hi, lo, w) do { \ | |
85 | BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \ | |
86 | q = n / w; \ | |
87 | r = n % w; \ | |
88 | } while (0) | |
89 | #endif | |
90 | ||
91 | #define BIGNUM_INT_BYTES (BIGNUM_INT_BITS / 8) | |
92 | ||
93 | #define BIGNUM_INTERNAL | |
94 | typedef BignumInt *Bignum; | |
95 | ||
96 | #endif |