libfreerdp-codec: cleanup and fix __lzcnt on Windows
authorMarc-André Moreau <marcandre.moreau@gmail.com>
Mon, 11 Aug 2014 22:48:42 +0000 (18:48 -0400)
committerMarc-André Moreau <marcandre.moreau@gmail.com>
Mon, 11 Aug 2014 22:48:42 +0000 (18:48 -0400)
channels/encomsp/client/encomsp_main.c
channels/rdpgfx/client/rdpgfx_main.c
libfreerdp/codec/clear.c
libfreerdp/codec/rfx_rlgr.c
libfreerdp/core/tpdu.c
winpr/include/winpr/crt.h
winpr/include/winpr/sysinfo.h
winpr/libwinpr/crt/test/TestIntrinsics.c
winpr/libwinpr/sysinfo/sysinfo.c

index f941974..d801a58 100644 (file)
@@ -91,7 +91,7 @@ int encomsp_read_unicode_string(wStream* s, ENCOMSP_UNICODE_STRING* str)
        if (str->cchString > 1024)
                return -1;
 
-       if (Stream_GetRemainingLength(s) < (str->cchString * 2))
+       if (Stream_GetRemainingLength(s) < (size_t) (str->cchString * 2))
                return -1;
 
        Stream_Read(s, &(str->wString), (str->cchString * 2)); /* String (variable) */
@@ -126,7 +126,7 @@ int encomsp_recv_filter_updated_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_
 
        if ((beg + header->Length) > end)
        {
-               if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end))
+               if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end))
                        return -1;
 
                Stream_SetPosition(s, (beg + header->Length));
@@ -171,7 +171,7 @@ int encomsp_recv_application_created_pdu(encomspPlugin* encomsp, wStream* s, ENC
 
        if ((beg + header->Length) > end)
        {
-               if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end))
+               if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end))
                        return -1;
 
                Stream_SetPosition(s, (beg + header->Length));
@@ -212,7 +212,7 @@ int encomsp_recv_application_removed_pdu(encomspPlugin* encomsp, wStream* s, ENC
 
        if ((beg + header->Length) > end)
        {
-               if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end))
+               if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end))
                        return -1;
 
                Stream_SetPosition(s, (beg + header->Length));
@@ -258,7 +258,7 @@ int encomsp_recv_window_created_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_
 
        if ((beg + header->Length) > end)
        {
-               if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end))
+               if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end))
                        return -1;
 
                Stream_SetPosition(s, (beg + header->Length));
@@ -299,7 +299,7 @@ int encomsp_recv_window_removed_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_
 
        if ((beg + header->Length) > end)
        {
-               if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end))
+               if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end))
                        return -1;
 
                Stream_SetPosition(s, (beg + header->Length));
@@ -340,7 +340,7 @@ int encomsp_recv_show_window_pdu(encomspPlugin* encomsp, wStream* s, ENCOMSP_ORD
 
        if ((beg + header->Length) > end)
        {
-               if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end))
+               if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end))
                        return -1;
 
                Stream_SetPosition(s, (beg + header->Length));
@@ -386,7 +386,7 @@ int encomsp_recv_participant_created_pdu(encomspPlugin* encomsp, wStream* s, ENC
 
        if ((beg + header->Length) > end)
        {
-               if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end))
+               if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end))
                        return -1;
 
                Stream_SetPosition(s, (beg + header->Length));
@@ -429,7 +429,7 @@ int encomsp_recv_participant_removed_pdu(encomspPlugin* encomsp, wStream* s, ENC
 
        if ((beg + header->Length) > end)
        {
-               if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end))
+               if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end))
                        return -1;
 
                Stream_SetPosition(s, (beg + header->Length));
@@ -471,7 +471,7 @@ int encomsp_recv_change_participant_control_level_pdu(encomspPlugin* encomsp, wS
 
        if ((beg + header->Length) > end)
        {
-               if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end))
+               if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end))
                        return -1;
 
                Stream_SetPosition(s, (beg + header->Length));
@@ -531,7 +531,7 @@ int encomsp_recv_graphics_stream_paused_pdu(encomspPlugin* encomsp, wStream* s,
 
        if ((beg + header->Length) > end)
        {
-               if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end))
+               if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end))
                        return -1;
 
                Stream_SetPosition(s, (beg + header->Length));
@@ -567,7 +567,7 @@ int encomsp_recv_graphics_stream_resumed_pdu(encomspPlugin* encomsp, wStream* s,
 
        if ((beg + header->Length) > end)
        {
-               if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end))
+               if (Stream_GetRemainingLength(s) < (size_t) ((beg + header->Length) - end))
                        return -1;
 
                Stream_SetPosition(s, (beg + header->Length));
index 2093ad5..d715e65 100644 (file)
@@ -203,7 +203,7 @@ int rdpgfx_recv_reset_graphics_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s
 
        pad = 340 - (RDPGFX_HEADER_SIZE + 12 + (pdu.monitorCount * 20));
 
-       if (Stream_GetRemainingLength(s) < pad)
+       if (Stream_GetRemainingLength(s) < (size_t) pad)
                return -1;
 
        Stream_Seek(s, pad); /* pad (total size is 340 bytes) */
@@ -254,7 +254,7 @@ int rdpgfx_recv_cache_import_reply_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStrea
 
        Stream_Read_UINT16(s, pdu.importedEntriesCount); /* cacheSlot (2 bytes) */
 
-       if (Stream_GetRemainingLength(s) < (pdu.importedEntriesCount * 2))
+       if (Stream_GetRemainingLength(s) < (size_t) (pdu.importedEntriesCount * 2))
                return -1;
 
        pdu.cacheSlots = (UINT16*) calloc(pdu.importedEntriesCount, sizeof(UINT16));
@@ -525,7 +525,7 @@ int rdpgfx_recv_solid_fill_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s)
        rdpgfx_read_color32(s, &(pdu.fillPixel)); /* fillPixel (4 bytes) */
        Stream_Read_UINT16(s, pdu.fillRectCount); /* fillRectCount (2 bytes) */
 
-       if (Stream_GetRemainingLength(s) < (pdu.fillRectCount * 8))
+       if (Stream_GetRemainingLength(s) < (size_t) (pdu.fillRectCount * 8))
                return -1;
 
        pdu.fillRects = (RDPGFX_RECT16*) calloc(pdu.fillRectCount, sizeof(RDPGFX_RECT16));
@@ -566,7 +566,7 @@ int rdpgfx_recv_surface_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStrea
        rdpgfx_read_rect16(s, &(pdu.rectSrc)); /* rectSrc (8 bytes ) */
        Stream_Read_UINT16(s, pdu.destPtsCount); /* destPtsCount (2 bytes) */
 
-       if (Stream_GetRemainingLength(s) < (pdu.destPtsCount * 4))
+       if (Stream_GetRemainingLength(s) < (size_t) (pdu.destPtsCount * 4))
                        return -1;
 
        pdu.destPts = (RDPGFX_POINT16*) calloc(pdu.destPtsCount, sizeof(RDPGFX_POINT16));
@@ -637,7 +637,7 @@ int rdpgfx_recv_cache_to_surface_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream*
        Stream_Read_UINT16(s, pdu.surfaceId); /* surfaceId (2 bytes) */
        Stream_Read_UINT16(s, pdu.destPtsCount); /* destPtsCount (2 bytes) */
 
-       if (Stream_GetRemainingLength(s) < (pdu.destPtsCount * 4))
+       if (Stream_GetRemainingLength(s) < (size_t) (pdu.destPtsCount * 4))
                return -1;
 
        pdu.destPts = (RDPGFX_POINT16*) calloc(pdu.destPtsCount, sizeof(RDPGFX_POINT16));
@@ -847,7 +847,7 @@ static int rdpgfx_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
 
        s = Stream_New(pDstData, DstSize);
 
-       while (Stream_GetPosition(s) < Stream_Length(s))
+       while (((size_t) Stream_GetPosition(s)) < Stream_Length(s))
        {
                status = rdpgfx_recv_pdu(callback, s);
 
index 4b93e42..35b6c04 100644 (file)
@@ -135,14 +135,14 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize,
                        if (!glyphData)
                                return -1010;
 
-                       if ((nWidth * nHeight) > glyphEntry->count)
+                       if ((nWidth * nHeight) > (int) glyphEntry->count)
                                return -1011;
 
                        nSrcStep = nWidth * 4;
                        pSrcPixel8 = glyphData;
                        pDstPixel8 = &pDstData[(nYDst * nDstStep) + (nXDst * 4)];
 
-                       for (y = 0; y < nHeight; y++)
+                       for (y = 0; y < (UINT32) nHeight; y++)
                        {
                                CopyMemory(pDstPixel8, pSrcPixel8, nSrcStep);
                                pSrcPixel8 += nSrcStep;
@@ -177,7 +177,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize,
                suboffset = 0;
                residualData = &pSrcData[offset];
 
-               if ((nWidth * nHeight * 4) > clear->TempSize)
+               if ((nWidth * nHeight * 4) > (int) clear->TempSize)
                {
                        clear->TempSize = (nWidth * nHeight * 4);
                        clear->TempBuffer = (BYTE*) realloc(clear->TempBuffer, clear->TempSize);
@@ -238,7 +238,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize,
                if (pixelIndex != pixelCount)
                        return -1019;
 
-               for (y = 0; y < nHeight; y++)
+               for (y = 0; y < (UINT32) nHeight; y++)
                {
                        CopyMemory(pDstPixel8, pSrcPixel8, nSrcStep);
                        pSrcPixel8 += nSrcStep;
@@ -543,7 +543,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize,
                        if (height > nHeight)
                                return -1043;
 
-                       if ((width * height * 4) > clear->TempSize)
+                       if (((UINT32) (width * height * 4)) > clear->TempSize)
                        {
                                clear->TempSize = (width * height * 4);
                                clear->TempBuffer = (BYTE*) realloc(clear->TempBuffer, clear->TempSize);
@@ -732,7 +732,7 @@ int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize,
                pDstPixel8 = glyphData;
                pSrcPixel8 = &pDstData[(nYDst * nDstStep) + (nXDst * 4)];
 
-               for (y = 0; y < nHeight; y++)
+               for (y = 0; y < (UINT32) nHeight; y++)
                {
                        CopyMemory(pDstPixel8, pSrcPixel8, nSrcStep);
                        pDstPixel8 += nSrcStep;
index 1571dec..b625f45 100644 (file)
@@ -32,6 +32,7 @@
 
 #include <winpr/crt.h>
 #include <winpr/print.h>
+#include <winpr/sysinfo.h>
 #include <winpr/bitstream.h>
 
 #include "rfx_bitstream.h"
        _k = (_param >> LSGR); \
 }
 
+static BOOL g_LZCNT = FALSE;
+
+static INLINE UINT32 lzcnt_s(UINT32 x)
+{
+       if (!x)
+               return 32;
+       
+       if (!g_LZCNT)
+       {
+               UINT32 y;
+               int n = 32;
+               y = x >> 16;  if (y != 0) { n = n - 16; x = y; }
+               y = x >>  8;  if (y != 0) { n = n -  8; x = y; }
+               y = x >>  4;  if (y != 0) { n = n -  4; x = y; }
+               y = x >>  2;  if (y != 0) { n = n -  2; x = y; }
+               y = x >>  1;  if (y != 0) return n - 2;
+               return n - x;
+       }
+
+       return __lzcnt(x);
+}
+
 int rfx_rlgr_decode(const BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT32 DstSize, int mode)
 {
        int vk;
@@ -92,6 +115,8 @@ int rfx_rlgr_decode(const BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT3
        wBitStream* bs;
        wBitStream s_bs;
 
+       g_LZCNT = IsProcessorFeaturePresentEx(PF_EX_LZCNT);
+
        k = 1;
        kp = k << LSGR;
 
@@ -124,7 +149,7 @@ int rfx_rlgr_decode(const BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT3
 
                        /* count number of leading 0s */
 
-                       cnt = __lzcnt(bs->accumulator);
+                       cnt = lzcnt_s(bs->accumulator);
 
                        nbits = BitStream_GetRemainingLength(bs);
 
@@ -137,7 +162,7 @@ int rfx_rlgr_decode(const BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT3
                        {
                                BitStream_Shift32(bs);
 
-                               cnt = __lzcnt(bs->accumulator);
+                               cnt = lzcnt_s(bs->accumulator);
 
                                nbits = BitStream_GetRemainingLength(bs);
 
@@ -187,7 +212,7 @@ int rfx_rlgr_decode(const BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT3
 
                        /* count number of leading 1s */
 
-                       cnt = __lzcnt(~(bs->accumulator));
+                       cnt = lzcnt_s(~(bs->accumulator));
 
                        nbits = BitStream_GetRemainingLength(bs);
 
@@ -200,7 +225,7 @@ int rfx_rlgr_decode(const BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT3
                        {
                                BitStream_Shift32(bs);
 
-                               cnt = __lzcnt(~(bs->accumulator));
+                               cnt = lzcnt_s(~(bs->accumulator));
 
                                nbits = BitStream_GetRemainingLength(bs);
 
@@ -295,7 +320,7 @@ int rfx_rlgr_decode(const BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT3
 
                        /* count number of leading 1s */
 
-                       cnt = __lzcnt(~(bs->accumulator));
+                       cnt = lzcnt_s(~(bs->accumulator));
 
                        nbits = BitStream_GetRemainingLength(bs);
 
@@ -308,7 +333,7 @@ int rfx_rlgr_decode(const BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT3
                        {
                                BitStream_Shift32(bs);
 
-                               cnt = __lzcnt(~(bs->accumulator));
+                               cnt = lzcnt_s(~(bs->accumulator));
 
                                nbits = BitStream_GetRemainingLength(bs);
 
@@ -411,7 +436,7 @@ int rfx_rlgr_decode(const BYTE* pSrcData, UINT32 SrcSize, INT16* pDstData, UINT3
                                if (code)
                                {
                                        mag = (UINT32) code;
-                                       nIdx = 32 - __lzcnt(mag);
+                                       nIdx = 32 - lzcnt_s(mag);
                                }
 
                                if (BitStream_GetRemainingLength(bs) < nIdx)
index 0560d00..d06adf0 100644 (file)
@@ -182,7 +182,7 @@ BOOL tpdu_read_connection_confirm(wStream* s, BYTE* li)
         */
        bytes_read = (Stream_GetPosition(s) - position) - 1;
 
-       return (Stream_GetRemainingLength(s) >= (*li - bytes_read));
+       return (Stream_GetRemainingLength(s) >= (size_t) (*li - bytes_read));
 }
 
 /**
index ed136a2..4172be8 100644 (file)
@@ -104,10 +104,6 @@ static INLINE UINT16 __lzcnt16(UINT16 _val16) {
        return _val16 ? ((UINT16) (__builtin_clz((UINT32) _val16) - 16)) : 16;
 }
 
-static INLINE UINT64 __lzcnt64(UINT64 _val64) {
-       return _val64 ? ((UINT64) __builtin_clzll(_val64)) : 64;
-}
-
 #else
 
 static INLINE UINT32 __lzcnt(UINT32 x) {
@@ -125,10 +121,6 @@ static INLINE UINT16 __lzcnt16(UINT16 x) {
        return ((UINT16) __lzcnt((UINT32) x));
 }
 
-static INLINE UINT64 __lzcnt64(UINT64 x) {
-       return 0; /* TODO */
-}
-
 #endif
 
 #endif
index eca980a..120009a 100644 (file)
@@ -298,20 +298,21 @@ WINPR_API ULONGLONG GetTickCount64(void);
 WINPR_API BOOL IsProcessorFeaturePresentEx(DWORD ProcessorFeature);
 
 /* extended flags */
-#define PF_EX_3DNOW_PREFETCH           1
-#define PF_EX_SSSE3                    2
-#define PF_EX_SSE41                    3
-#define PF_EX_SSE42                    4
-#define PF_EX_AVX                      5
-#define PF_EX_FMA                      6
-#define PF_EX_AVX_AES                  7
-#define PF_EX_AVX2                     8
-#define PF_EX_ARM_VFP1                 9
-#define PF_EX_ARM_VFP3D16              10
-#define PF_EX_ARM_VFP4                 11
-#define PF_EX_ARM_IDIVA                        12
-#define PF_EX_ARM_IDIVT                        13
-#define PF_EX_AVX_PCLMULQDQ 14
+#define PF_EX_LZCNT                    1
+#define PF_EX_3DNOW_PREFETCH           2
+#define PF_EX_SSSE3                    3
+#define PF_EX_SSE41                    4
+#define PF_EX_SSE42                    5
+#define PF_EX_AVX                      6
+#define PF_EX_FMA                      7
+#define PF_EX_AVX_AES                  8
+#define PF_EX_AVX2                     9
+#define PF_EX_ARM_VFP1                 10
+#define PF_EX_ARM_VFP3D16              11
+#define PF_EX_ARM_VFP4                 12
+#define PF_EX_ARM_IDIVA                        13
+#define PF_EX_ARM_IDIVT                        14
+#define PF_EX_AVX_PCLMULQDQ            15
 
 /*
  * some "aliases" for the standard defines
index bb1f07b..5bbf915 100644 (file)
@@ -1,36 +1,53 @@
 
-#include <stdio.h>
 #include <winpr/crt.h>
+#include <winpr/sysinfo.h>
 #include <winpr/windows.h>
 
-int test_lzcnt()
+static BOOL g_LZCNT = FALSE;
+
+static INLINE UINT32 lzcnt_s(UINT32 x)
 {
-       if (__lzcnt(0x0) != 32) {
-               fprintf(stderr, "__lzcnt(0x0) != 32\n");
-               return -1;
-       }
+       if (!x)
+               return 32;
+       
+       if (!g_LZCNT)
+       {
+               UINT32 y;
+               int n = 32;
+               y = x >> 16;  if (y != 0) { n = n - 16; x = y; }
+               y = x >>  8;  if (y != 0) { n = n -  8; x = y; }
+               y = x >>  4;  if (y != 0) { n = n -  4; x = y; }
+               y = x >>  2;  if (y != 0) { n = n -  2; x = y; }
+               y = x >>  1;  if (y != 0) return n - 2;
+               return n - x;
+       }
+
+       return __lzcnt(x);
+}
 
-       if (__lzcnt(0x1) != 31) {
-               fprintf(stderr, "__lzcnt(0x1) != 31\n");
+int test_lzcnt()
+{
+       if (lzcnt_s(0x1) != 31) {
+               fprintf(stderr, "__lzcnt(0x1) != 31: %d\n", __lzcnt(0x1));
                return -1;
        }
 
-       if (__lzcnt(0xFF) != 24) {
+       if (lzcnt_s(0xFF) != 24) {
                fprintf(stderr, "__lzcnt(0xFF) != 24\n");
                return -1;
        }
 
-       if (__lzcnt(0xFFFF) != 16) {
+       if (lzcnt_s(0xFFFF) != 16) {
                fprintf(stderr, "__lzcnt(0xFFFF) != 16\n");
                return -1;
        }
 
-       if (__lzcnt(0xFFFFFF) != 8) {
+       if (lzcnt_s(0xFFFFFF) != 8) {
                fprintf(stderr, "__lzcnt(0xFFFFFF) != 8\n");
                return -1;
        }
 
-       if (__lzcnt(0xFFFFFFFF) != 0) {
+       if (lzcnt_s(0xFFFFFFFF) != 0) {
                fprintf(stderr, "__lzcnt(0xFFFFFFFF) != 0\n");
                return -1;
        }
@@ -40,11 +57,6 @@ int test_lzcnt()
 
 int test_lzcnt16()
 {
-       if (__lzcnt16(0x0) != 16) {
-               fprintf(stderr, "__lzcnt16(0x0) != 16\n");
-               return -1;
-       }
-
        if (__lzcnt16(0x1) != 15) {
                fprintf(stderr, "__lzcnt16(0x1) != 15\n");
                return -1;
@@ -63,47 +75,14 @@ int test_lzcnt16()
        return 1;
 }
 
-int test_lzcnt64()
+int TestIntrinsics(int argc, char* argv[])
 {
-       if (__lzcnt64(0x0) != 64) {
-               fprintf(stderr, "__lzcnt64(0x0) != 64\n");
-               return -1;
-       }
+       g_LZCNT = IsProcessorFeaturePresentEx(PF_EX_LZCNT);
 
-       if (__lzcnt64(0x1) != 63) {
-               fprintf(stderr, "__lzcnt64(0x1) != 63\n");
-               return -1;
-       }
+       printf("LZCNT available: %d\n", g_LZCNT);
 
-       if (__lzcnt64(0xFF) != 56) {
-               fprintf(stderr, "__lzcnt64(0xFF) != 56\n");
-               return -1;
-       }
-
-       if (__lzcnt64(0xFFFF) != 48) {
-               fprintf(stderr, "__lzcnt64(0xFFFF) != 48\n");
-               return -1;
-       }
-
-       if (__lzcnt64(0xFFFFFF) != 40) {
-               fprintf(stderr, "__lzcnt64(0xFFFFFF) != 40\n");
-               return -1;
-       }
-
-       if (__lzcnt64(0xFFFFFFFF) != 32) {
-               fprintf(stderr, "__lzcnt64(0xFFFFFFFF) != 32\n");
-               return -1;
-       }
-
-       return 1;
-}
-
-int TestIntrinsics(int argc, char* argv[])
-{
        test_lzcnt();
-       test_lzcnt16();
-       test_lzcnt64();
+       //test_lzcnt16();
 
        return 0;
 }
-
index fcef5b4..0084204 100644 (file)
@@ -438,6 +438,7 @@ ULONGLONG GetTickCount64(void)
 #define D_BIT_3DN       (1<<30)
 #define C_BIT_SSE3      (1<<0)
 #define C_BIT_PCLMULQDQ (1<<1)
+#define C_BIT_LZCNT     (1<<5)
 #define C_BIT_3DNP      (1<<8)
 #define C_BIT_3DNP      (1<<8)
 #define C_BIT_SSSE3     (1<<9)
@@ -691,6 +692,10 @@ BOOL IsProcessorFeaturePresentEx(DWORD ProcessorFeature)
 
        switch (ProcessorFeature)
        {
+               case PF_EX_LZCNT:
+                       if (c & C_BIT_LZCNT)
+                               ret = TRUE;
+                       break;
                case PF_EX_3DNOW_PREFETCH:
                        if (c & C_BIT_3DNP)
                                ret = TRUE;