Files
cpu-check/crc32c.c
2020-05-08 13:33:05 -07:00

76 lines
1.8 KiB
C

// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "crc32c.h"
#ifdef __SSE4_2__
#include <x86intrin.h>
/* x86 version based using instrinsics */
uint32_t crc32c_hw(const char *src, size_t len) {
const unsigned char *s = (unsigned char *)src;
uint64_t hh = ~0;
#ifdef __x86_64__
while (len > 7) {
uint64_t v = *(uint64_t *)s;
hh = _mm_crc32_u64(hh, v);
s += 8;
len -= 8;
}
#endif /* __x86_64__ */
uint32_t h = (uint32_t)hh;
if (len > 3) {
uint32_t v = *(uint32_t *)s;
h = _mm_crc32_u32(h, v);
s += 4;
len -= 4;
}
if (len > 1) {
uint16_t v = *(uint16_t *)s;
h = _mm_crc32_u16(h, v);
s += 2;
len -= 2;
}
if (len > 0) {
uint8_t v = *(uint8_t *)s;
h = _mm_crc32_u8(h, v);
s += 1;
len -= 1;
}
return ~h;
}
#endif /* __SSE4_2__ */
/* CRC-32C (iSCSI) polynomial in reversed bit order. */
#define POLY 0x82f63b78
uint32_t crc32c_sw(const char *src, size_t len) {
const unsigned char *s = (unsigned char *)src;
uint32_t h = ~0;
while (len--) {
h ^= *s++;
for (int k = 0; k < 8; k++) h = h & 1 ? (h >> 1) ^ POLY : h >> 1;
}
return ~h;
}
uint32_t crc32c(const char *src, size_t len) {
#ifdef __SSE4_2__
return crc32c_hw(src, len);
#else
return crc32c_sw(src, len);
#endif
}