1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-10 01:48:00 +00:00

Improvements from Spyros Blanas to the MSVC optimisations of r6469:

don't do a function call for each divmod, and don't rely on details of
the calling convention.
(This didn't actually make any measurable difference to runtime in any
of my tests, but we may as well keep it as it's neater.)
Also document some general caveats of the divmod macro.

[originally from svn r6475]
[r6469 == d72e4b718c]
This commit is contained in:
Jacob Nevins 2005-12-06 23:18:27 +00:00
parent 67b68bf145
commit d8b7de5435

47
sshbn.c
View File

@ -9,6 +9,20 @@
#include "misc.h"
/*
* Usage notes:
* * Do not call the DIVMOD_WORD macro with expressions such as array
* subscripts, as some implementations object to this (see below).
* * Note that none of the division methods below will cope if the
* quotient won't fit into BIGNUM_INT_BITS. Callers should be careful
* to avoid this case.
* If this condition occurs, in the case of the x86 DIV instruction,
* an overflow exception will occur, which (according to a correspondent)
* will manifest on Windows as something like
* 0xC0000095: Integer overflow
* The C variant won't give the right answer, either.
*/
#if defined __GNUC__ && defined __i386__
typedef unsigned long BignumInt;
typedef unsigned long long BignumDblInt;
@ -27,26 +41,16 @@ typedef unsigned __int64 BignumDblInt;
#define BIGNUM_TOP_BIT 0x80000000UL
#define BIGNUM_INT_BITS 32
#define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
typedef struct {
unsigned __int32 quot;
unsigned __int32 remd;
} msvc_quorem;
static __declspec(naked) msvc_quorem __stdcall msvc_divmod(
unsigned __int32 hi,
unsigned __int32 lo,
unsigned __int32 w)
{
__asm {
mov edx, dword ptr [esp+4]
mov eax, dword ptr [esp+8]
div dword ptr [esp+12]
ret 12
};
}
/* Note: MASM interprets array subscripts in the macro arguments as
* assembler syntax, which gives the wrong answer. Don't supply them.
* <http://msdn2.microsoft.com/en-us/library/bf1dw62z.aspx> */
#define DIVMOD_WORD(q, r, hi, lo, w) do { \
const msvc_quorem qr = msvc_divmod((hi), (lo), (w)); \
(q) = qr.quot; (r) = qr.remd; \
} while (0)
__asm mov edx, hi \
__asm mov eax, lo \
__asm div w \
__asm mov r, edx \
__asm mov q, eax \
} while(0)
#else
typedef unsigned short BignumInt;
typedef unsigned long BignumDblInt;
@ -230,7 +234,10 @@ static void internal_mod(BignumInt *a, int alen,
*/
q = BIGNUM_INT_MASK;
} else {
DIVMOD_WORD(q, r, h, a[i], m0);
/* Macro doesn't want an array subscript expression passed
* into it (see definition), so use a temporary. */
BignumInt tmplo = a[i];
DIVMOD_WORD(q, r, h, tmplo, m0);
/* Refine our estimate of q by looking at
h:a[i]:a[i+1] / m0:m1 */