Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 31 additions & 1 deletion Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,15 @@ crc32.o: $(SRCDIR)crc32.c
crc32_vx.o: $(SRCDIR)contrib/crc32vx/crc32_vx.c
$(CC) $(CFLAGS) $(VGFMAFLAG) $(ZINC) -c -o $@ $(SRCDIR)contrib/crc32vx/crc32_vx.c

crc32_x86_pclmul.o: $(SRCDIR)contrib/x86_64/crc32_x86_pclmul.c
$(CC) $(CFLAGS) $(VGFMAFLAG) $(ZINC) -c -o $@ $(SRCDIR)contrib/x86_64/crc32_x86_pclmul.c

crc32_x86_vpclmulqdq.o: $(SRCDIR)contrib/x86_64/crc32_x86_vpclmulqdq.c
$(CC) $(CFLAGS) $(VGFMAFLAG) $(ZINC) -c -o $@ $(SRCDIR)contrib/x86_64/crc32_x86_vpclmulqdq.c

crc32_x86.o: $(SRCDIR)contrib/x86_64/crc32_x86.c
$(CC) $(CFLAGS) $(VGFMAFLAG) $(ZINC) -c -o $@ $(SRCDIR)contrib/x86_64/crc32_x86.c

deflate.o: $(SRCDIR)deflate.c
$(CC) $(CFLAGS) $(ZINC) -c -o $@ $(SRCDIR)deflate.c

Expand Down Expand Up @@ -219,6 +228,21 @@ crc32_vx.lo: $(SRCDIR)contrib/crc32vx/crc32_vx.c
$(CC) $(SFLAGS) $(VGFMAFLAG) $(ZINC) -DPIC -c -o objs/crc32_vx.o $(SRCDIR)contrib/crc32vx/crc32_vx.c
-@mv objs/crc32_vx.o $@

crc32_x86_pclmul.lo: $(SRCDIR)contrib/x86_64/crc32_x86_pclmul.c
-@mkdir objs 2>/dev/null || test -d objs
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/crc32_x86_pclmul.o $(SRCDIR)contrib/x86_64/crc32_x86_pclmul.c
-@mv objs/crc32_x86_pclmul.o $@

crc32_x86_vpclmulqdq.lo: $(SRCDIR)contrib/x86_64/crc32_x86_vpclmulqdq.c
-@mkdir objs 2>/dev/null || test -d objs
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/crc32_x86_vpclmulqdq.o $(SRCDIR)contrib/x86_64/crc32_x86_vpclmulqdq.c
-@mv objs/crc32_x86_vpclmulqdq.o $@

crc32_x86.lo: $(SRCDIR)contrib/x86_64/crc32_x86.c
-@mkdir objs 2>/dev/null || test -d objs
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/crc32_x86.o $(SRCDIR)contrib/x86_64/crc32_x86.c
-@mv objs/crc32_x86.o $@

deflate.lo: $(SRCDIR)deflate.c
-@mkdir objs 2>/dev/null || test -d objs
$(CC) $(SFLAGS) $(ZINC) -DPIC -c -o objs/deflate.o $(SRCDIR)deflate.c
Expand Down Expand Up @@ -412,6 +436,9 @@ inffast.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR
inftrees.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h
trees.o: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)trees.h
crc32_vx.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)contrib/crc32vx/crc32_vx_hooks.h
crc32_pclmul.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)contrib/x86_64/crc32_x86_hooks.h
crc32_vpclmulqdq.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)contrib/x86_64/crc32_x86_hooks.h
crc32_x86.o: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)contrib/x86_64/crc32_x86_hooks.h

adler32.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h
zutil.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)gzguts.h
Expand All @@ -423,4 +450,7 @@ infback.lo inflate.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftree
inffast.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h $(SRCDIR)inflate.h $(SRCDIR)inffast.h
inftrees.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)inftrees.h
trees.lo: $(SRCDIR)deflate.h $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)trees.h
crc32_vx.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)contrib/crc32vx/crc32_vx_hooks.h
crc32_vx.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)contrib/crc32vx/crc32_vx_hooks.h
crc32_pclmul.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)contrib/x86_64/crc32_x86_hooks.h
crc32_vpclmulqdq.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)contrib/x86_64/crc32_x86_hooks.h
crc32_x86.lo: $(SRCDIR)zutil.h $(SRCDIR)zlib.h zconf.h $(SRCDIR)contrib/x86_64/crc32_x86_hooks.h
8 changes: 8 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -979,6 +979,14 @@ EOF
fi
fi

# prepare compiling for x86_64
#ifdef __x86_64__
CFLAGS="$CFLAGS -DUNALIGNED_OK"
SFLAGS="$SFLAGS -DUNALIGNED_OK"
OBJC="$OBJC crc32_x86_pclmul.o crc32_x86_vpclmulqdq.o crc32_x86.o"
PIC_OBJC="$PIC_OBJC crc32_x86_pclmul.lo crc32_x86_vpclmulqdq.lo crc32_x86.lo"
#endif

# show the results in the log
echo >> configure.log
echo ALL = $ALL >> configure.log
Expand Down
117 changes: 117 additions & 0 deletions contrib/x86_64/crc32_x86.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>

#define Z_ONCE
#include "../../zutil.h"
#include "crc32_x86_hooks.h"

#ifdef __x86_64__

static inline int has_osxsave(void)
{
uint32_t eax, ebx, ecx, edx;
__asm__ volatile (
"cpuid"
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
: "a"(0x01)
: "memory"
);

return ((ecx >> 27) & 0x01);
}

// check XCR0 Bits
static inline uint64_t xgetbv(uint32_t ecx)
{
uint32_t eax, edx;
__asm__ volatile (
"xgetbv"
: "=a"(eax), "=d"(edx)
: "c"(ecx)
: "memory"
);

return ((uint64_t)edx << 32) | eax;
}

static inline int xcr0_ymm_enabled(void)
{
uint64_t xcr0 = xgetbv(0);

// Check XCR0[2:1] == '11'(YMM state enabled)
return ((xcr0 >> 1) & 0x03) == 0x03;
}


static inline int xcr0_zmm_enabled(void) {

uint64_t xcr0 = xgetbv(0);

// Check XCR0[7:5] == '111'(ZMM + OPMASK state enabled)
return ((xcr0 >> 5) & 0x07) == 0x07;
}

static inline int has_pclmul(void) {
uint32_t eax, ebx, ecx, edx;

__asm__ volatile (
"cpuid"
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
: "a"(0x01), "b"(0x00)
: "memory"
);

return ((ecx >> 28) & 0x01) && ((ecx >> 1) & 0x01);//support avx && pclmulqdq instruction
}

static inline int has_vpclmulqdq(void)
{
uint32_t eax, ebx, ecx, edx;
if (!has_osxsave())
return 0;
if (!xcr0_ymm_enabled())
return 0;

if (!xcr0_zmm_enabled())
return 0;

__asm__ volatile (
"cpuid"
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
: "a"(0x07), "b"(0x00)
: "memory"
);

return ((ebx >> 16) & 0x01) && ((ebx >> 31) & 0x01) && ((ecx >> 10) & 0x01);
}


/* SIMD optimized variants of crc32_z */
unsigned long crc32_z_impl_x86_avx(unsigned long crc, const unsigned char FAR* buf, z_size_t len); // pclmul
#if defined(__GNUC__) && (__GNUC__ >= 8)
unsigned long crc32_z_impl_x86_avx512(unsigned long crc, const unsigned char FAR* buf, z_size_t len); // vpclmulqdq
#endif

local z_once_t x86_crc32_made = Z_ONCE_INIT;
local void x86_crc32_setup() {
#if defined(__GNUC__) && (__GNUC__ >= 8)
if (has_vpclmulqdq()) {
crc32_z_hook = crc32_z_impl_x86_avx512;
} else
#endif
if (has_pclmul())
crc32_z_hook = crc32_z_impl_x86_avx;
else
crc32_z_hook = crc32_z;
}

local unsigned long x86_crc32_init(unsigned long crc, const unsigned char FAR *buf, z_size_t len)
{
z_once(&x86_crc32_made,x86_crc32_setup);
return crc32_z_hook(crc, buf, len);
}

ZLIB_INTERNAL unsigned long (*crc32_z_hook)(unsigned long crc, const unsigned char FAR *buf, z_size_t len) = x86_crc32_init;

#endif /* end of __x86_64__ */
Loading