From ddbfc283ea51ba2f4fc56a62080be3abe7e5ee78 Mon Sep 17 00:00:00 2001 From: bulk88 Date: Mon, 13 Jan 2014 20:05:02 -0500 Subject: [PATCH] _BitScanForward on Visual C <2005 support --- Makefile.PL | 20 ++++++++++++++++++++ util.c | 26 ++++++++++++++++++++++++++ util.h | 19 +++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/Makefile.PL b/Makefile.PL index f0ddf698..424e4675 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -1,4 +1,5 @@ use ExtUtils::MakeMaker; +use Config; my $broken64 = (18446744073709550592 == ~0); if ($broken64) { @@ -15,6 +16,24 @@ I highly recommend upgrading to a newer version of Perl. EOW } +my $msvc_Oi = !!0; +{ + my ($cc, $ver) = $Config{cc}; + if ($cc eq 'cl') { + my @ver = `$cc 2>&1`; # Interesting output in STDERR + $ver = join('', @ver); + + #print 'VER:'.$ver.':'."\n"; + if ($ver =~ /Version (\d[\d\.]+)/ms) { + $ver = $1; + } + else { + die "Unknown version of Microsoft Visual C"; + } + $msvc_Oi = '-Oi' if $ver < 14 && $ver >= 13; #VC2002/2003 only + } +} + WriteMakefile1( NAME => 'Math::Prime::Util', ABSTRACT => 'Utilities related to prime numbers, including fast sieves and factoring', @@ -81,6 +100,7 @@ WriteMakefile1( }, MIN_PERL_VERSION => 5.006002, + DEFINE => $msvc_Oi, ); sub WriteMakefile1 { # Cribbed from eumm-upgrade by Alexandr Ciornii diff --git a/util.c b/util.c index 9a3515ca..d12a33f6 100644 --- a/util.c +++ b/util.c @@ -147,6 +147,32 @@ static UV count_zero_bits(const unsigned char* m, UV nbytes) return count; } +#if defined(_MSC_VER) && _MSC_VER < 1300 +/* used for testing + unsigned char __fastcall _2BitScanForward(unsigned long* Index, unsigned long Mask) { + return _BitScanForward(Index,Mask); +} +unsigned char __fastcall _2BitScanReverse(unsigned long* Index, unsigned long Mask) { + return _BitScanReverse(Index,Mask); +}*/ + +unsigned char __declspec( naked ) __fastcall _BitScanForward(unsigned long* Index, unsigned long Mask) { + __asm { + bsf eax, edx /* edx is Mask */ + mov [ecx], eax /*ecx is Index */ + setnz al + retn + }; +} +unsigned char __declspec( naked ) __fastcall _BitScanReverse(unsigned long* Index, unsigned long Mask) { + __asm { + bsr eax, edx /* edx is Mask */ + mov [ecx], eax /*ecx is Index */ + setnz al + retn + }; +} +#endif /* Does trial division or prob tests, assuming x not divisible by 2, 3, or 5 */ static int _is_prime7(UV n) diff --git a/util.h b/util.h index 672f8c79..c8ba6a83 100644 --- a/util.h +++ b/util.h @@ -137,7 +137,26 @@ static int is_perfect_square(UV n) #define log2floor(n) ((n) ? 31-__builtin_clzl(n) : 0) #endif #elif defined (_MSC_VER) + #if _MSC_VER >= 1400 #include + #elif _MSC_VER >= 1300 +/* undocumented for VC 2003, not in headers or .libs + -Oi required for this to work in -O1 or -Od mode + http://www.geoffchappell.com/studies/msvc/language/preprocessor/directives/pragma/intrinsic.htm +*/ + unsigned char _BitScanForward(unsigned long* Index, unsigned long Mask); + unsigned char _BitScanReverse(unsigned long* Index, unsigned long Mask); + unsigned char _BitScanForward64(unsigned long * Index,unsigned __int64 Mask); + unsigned char _BitScanReverse64(unsigned long * Index,unsigned __int64 Mask); + #pragma intrinsic(_BitScanForward) + #pragma intrinsic(_BitScanReverse) + #pragma intrinsic(_BitScanForward64) + #pragma intrinsic(_BitScanReverse64) + #else + unsigned char __fastcall _BitScanForward(unsigned long* Index, unsigned long Mask); + unsigned char __fastcall _BitScanReverse(unsigned long* Index, unsigned long Mask); + #endif + #ifdef FUNC_ctz static int ctz(UV n) { UV tz = 0;