2000-06-21 22:51:29 +00:00
|
|
|
/*
|
|
|
|
+----------------------------------------------------------------------+
|
2019-01-30 09:03:12 +00:00
|
|
|
| Copyright (c) The PHP Group |
|
2000-06-21 22:51:29 +00:00
|
|
|
+----------------------------------------------------------------------+
|
2006-01-01 12:51:34 +00:00
|
|
|
| This source file is subject to version 3.01 of the PHP license, |
|
2000-06-21 22:51:29 +00:00
|
|
|
| that is bundled with this package in the file LICENSE, and is |
|
2003-06-10 20:04:29 +00:00
|
|
|
| available through the world-wide-web at the following url: |
|
2006-01-01 12:51:34 +00:00
|
|
|
| http://www.php.net/license/3_01.txt |
|
2000-06-21 22:51:29 +00:00
|
|
|
| If you did not receive a copy of the PHP license and are unable to |
|
|
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
|
|
| license@php.net so we can mail you a copy immediately. |
|
|
|
|
+----------------------------------------------------------------------+
|
2002-02-28 08:29:35 +00:00
|
|
|
| Author: Rasmus Lerdorf <rasmus@php.net> |
|
2000-06-21 22:51:29 +00:00
|
|
|
+----------------------------------------------------------------------+
|
2000-07-24 01:40:02 +00:00
|
|
|
*/
|
|
|
|
|
2000-06-21 22:51:29 +00:00
|
|
|
#include "php.h"
|
2000-08-21 09:50:53 +00:00
|
|
|
#include "basic_functions.h"
|
2002-02-20 18:18:39 +00:00
|
|
|
#include "crc32.h"
|
2020-09-02 10:53:29 +00:00
|
|
|
#include "crc32_x86.h"
|
2000-06-21 22:51:29 +00:00
|
|
|
|
2020-05-13 06:22:29 +00:00
|
|
|
#if HAVE_AARCH64_CRC32
|
2019-05-01 16:05:11 +00:00
|
|
|
# include <arm_acle.h>
|
|
|
|
# if defined(__linux__)
|
|
|
|
# include <sys/auxv.h>
|
|
|
|
# include <asm/hwcap.h>
|
|
|
|
# endif
|
|
|
|
|
|
|
|
static inline int has_crc32_insn() {
|
|
|
|
/* Only go through the runtime detection once. */
|
|
|
|
static int res = -1;
|
|
|
|
if (res != -1)
|
|
|
|
return res;
|
|
|
|
# if defined(HWCAP_CRC32)
|
|
|
|
res = getauxval(AT_HWCAP) & HWCAP_CRC32;
|
|
|
|
return res;
|
|
|
|
# elif defined(HWCAP2_CRC32)
|
|
|
|
res = getauxval(AT_HWCAP2) & HWCAP2_CRC32;
|
|
|
|
return res;
|
|
|
|
# else
|
|
|
|
res = 0;
|
|
|
|
return res;
|
|
|
|
# endif
|
|
|
|
}
|
2019-10-02 12:41:02 +00:00
|
|
|
|
|
|
|
# pragma GCC push_options
|
|
|
|
# pragma GCC target ("+nothing+crc")
|
|
|
|
static uint32_t crc32_aarch64(uint32_t crc, char *p, size_t nr) {
|
|
|
|
while (nr >= sizeof(uint64_t)) {
|
|
|
|
crc = __crc32d(crc, *(uint64_t *)p);
|
|
|
|
p += sizeof(uint64_t);
|
|
|
|
nr -= sizeof(uint64_t);
|
|
|
|
}
|
|
|
|
if (nr >= sizeof(int32_t)) {
|
|
|
|
crc = __crc32w(crc, *(uint32_t *)p);
|
|
|
|
p += sizeof(uint32_t);
|
|
|
|
nr -= sizeof(uint32_t);
|
|
|
|
}
|
|
|
|
if (nr >= sizeof(int16_t)) {
|
|
|
|
crc = __crc32h(crc, *(uint16_t *)p);
|
|
|
|
p += sizeof(uint16_t);
|
|
|
|
nr -= sizeof(uint16_t);
|
|
|
|
}
|
|
|
|
if (nr) {
|
|
|
|
crc = __crc32b(crc, *p);
|
|
|
|
}
|
|
|
|
return crc;
|
|
|
|
}
|
|
|
|
# pragma GCC pop_options
|
2019-05-01 16:05:11 +00:00
|
|
|
#endif
|
|
|
|
|
2020-07-01 13:32:55 +00:00
|
|
|
/* {{{ Calculate the crc32 polynomial of a string */
|
2020-02-21 14:33:58 +00:00
|
|
|
PHP_FUNCTION(crc32)
|
2000-06-21 22:51:29 +00:00
|
|
|
{
|
2001-10-26 21:07:59 +00:00
|
|
|
char *p;
|
2014-08-27 13:31:48 +00:00
|
|
|
size_t nr;
|
2016-01-28 16:11:53 +00:00
|
|
|
uint32_t crcinit = 0;
|
2020-09-02 10:53:29 +00:00
|
|
|
uint32_t crc;
|
2006-02-09 15:33:53 +00:00
|
|
|
|
2016-12-30 20:32:48 +00:00
|
|
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
|
|
|
Z_PARAM_STRING(p, nr)
|
|
|
|
ZEND_PARSE_PARAMETERS_END();
|
|
|
|
|
2006-02-09 15:33:53 +00:00
|
|
|
crc = crcinit^0xFFFFFFFF;
|
2000-06-21 22:51:29 +00:00
|
|
|
|
2020-05-13 06:22:29 +00:00
|
|
|
#if HAVE_AARCH64_CRC32
|
2019-05-01 16:05:11 +00:00
|
|
|
if (has_crc32_insn()) {
|
2019-10-02 12:41:02 +00:00
|
|
|
crc = crc32_aarch64(crc, p, nr);
|
2019-10-23 14:58:47 +00:00
|
|
|
RETURN_LONG(crc^0xFFFFFFFF);
|
2019-05-01 16:05:11 +00:00
|
|
|
}
|
|
|
|
#endif
|
2019-10-02 12:41:02 +00:00
|
|
|
|
2020-09-02 10:53:29 +00:00
|
|
|
#if ZEND_INTRIN_SSE4_2_PCLMUL_NATIVE || ZEND_INTRIN_SSE4_2_PCLMUL_RESOLVER
|
|
|
|
size_t nr_simd = crc32_x86_simd_update(X86_CRC32B, &crc, (const unsigned char *)p, nr);
|
|
|
|
nr -= nr_simd;
|
|
|
|
p += nr_simd;
|
|
|
|
#endif
|
|
|
|
|
2014-04-22 13:46:34 +00:00
|
|
|
for (; nr--; ++p) {
|
2006-02-09 15:33:53 +00:00
|
|
|
crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[(crc ^ (*p)) & 0xFF ];
|
2000-06-21 22:51:29 +00:00
|
|
|
}
|
2019-10-23 14:58:47 +00:00
|
|
|
RETURN_LONG(crc^0xFFFFFFFF);
|
2000-06-21 22:51:29 +00:00
|
|
|
}
|
2006-02-09 15:48:46 +00:00
|
|
|
/* }}} */
|