libc/arm: optimize crc32/crc32c for arm

Optimize crc32 standard(poly:0x04C11DB7) and crc32
castagnoli(poly:0x1EDC6F41) with arm crc32 extension instructions.

For example, crc32 standard caculates(lookup crc32 table) 1812 bytes data,
reduced the time from 118 us to 14 us through optimization.

Performance improved ~700%

Signed-off-by: Jinliang Li <lijinliang1@lixiang.com>
This commit is contained in:
Jinliang Li
2025-03-19 22:48:47 +08:00
committed by Alan C. Assis
parent 586d216a40
commit d5db7d1cee
6 changed files with 223 additions and 68 deletions
+4
View File
@@ -68,4 +68,8 @@ if(CONFIG_PROFILE_MINI)
list(APPEND SRCS gnu/mcount.S)
endif()
if(CONFIG_LIBC_ARCH_CRC32)
list(APPEND SRCS arch_crc32.c)
endif()
target_sources(c PRIVATE ${SRCS})
+7
View File
@@ -31,3 +31,10 @@ endif
if ARCH_ARMV8R
source "libs/libc/machine/arm/armv8-r/Kconfig"
endif
config LIBC_ARCH_CRC32
bool "Enable optimized crc32 for ARM"
default n
depends on ARCH_HAVE_CRC32
---help---
Enable optimized arm neon specific crc32 library function
+4
View File
@@ -66,6 +66,10 @@ ifeq ($(CONFIG_PROFILE_MINI),y)
ASRCS += mcount.S
endif
ifeq ($(CONFIG_LIBC_ARCH_CRC32),y)
CSRCS += arch_crc32.c
endif
ifeq ($(CONFIG_ARCH_TOOLCHAIN_GNU),y)
DEPPATH += --dep-path machine/arm/gnu
VPATH += :machine/arm/gnu
+115
View File
@@ -0,0 +1,115 @@
/****************************************************************************
* libs/libc/machine/arm/arch_crc32.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <stdint.h>
#include <sys/types.h>
#include <arm_acle.h>
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: crc32part
*
* Description:
* crc32 polynomial 0x04C11DB7 (bitreflected 0xEDB88320)
*
****************************************************************************/
uint32_t crc32part(FAR const uint8_t *src, size_t len, uint32_t crc32val)
{
size_t i = 0;
for (; (i + 8) <= len; i += 8)
{
uint64_t data = *(uint64_t *)(src + i);
crc32val = __crc32d(crc32val, data);
}
if (i + 4 <= len)
{
uint32_t data = *(uint32_t *)(src + i);
crc32val = __crc32w(crc32val, data);
i += 4;
}
if (i + 2 <= len)
{
uint16_t data = *(uint16_t *)(src + i);
crc32val = __crc32h(crc32val, data);
i += 2;
}
if (i < len)
{
uint8_t data = *(uint8_t *)(src + i);
crc32val = __crc32b(crc32val, data);
}
return crc32val;
}
/****************************************************************************
* Name: crc32part_c
*
* Description:
* crc32 Castagnoli polynomial 0x1EDC6F41
*
****************************************************************************/
uint32_t crc32part_c(FAR const uint8_t *src, size_t len, uint32_t crc32val)
{
size_t i = 0;
for (; (i + 8) <= len; i += 8)
{
uint64_t data = *(uint64_t *)(src + i);
crc32val = __crc32cd(crc32val, data);
}
if (i + 4 <= len)
{
uint32_t data = *(uint32_t *)(src + i);
crc32val = __crc32cw(crc32val, data);
i += 4;
}
if (i + 2 <= len)
{
uint16_t data = *(uint16_t *)(src + i);
crc32val = __crc32ch(crc32val, data);
i += 2;
}
if (i < len)
{
uint8_t data = *(uint8_t *)(src + i);
crc32val = __crc32cb(crc32val, data);
}
return crc32val;
}