mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-19 02:15:33 +00:00
93 lines
2.7 KiB
C
93 lines
2.7 KiB
C
|
/*
|
||
|
* Copyright (c) 2018 Atmosphère-NX
|
||
|
*
|
||
|
* This program is free software; you can redistribute it and/or modify it
|
||
|
* under the terms and conditions of the GNU General Public License,
|
||
|
* version 2, as published by the Free Software Foundation.
|
||
|
*
|
||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||
|
* more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
|
||
|
#pragma once
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
extern "C" {
|
||
|
#endif
|
||
|
|
||
|
/* Code taken from Yazen Ghannam <yazen.ghannam@linaro.org>, licensed GPLv2. */
|
||
|
|
||
|
#define CRC32X(crc, value) __asm__("crc32x %w[c], %w[c], %x[v]":[c]"+r"(crc):[v]"r"(value))
|
||
|
#define CRC32W(crc, value) __asm__("crc32w %w[c], %w[c], %w[v]":[c]"+r"(crc):[v]"r"(value))
|
||
|
#define CRC32H(crc, value) __asm__("crc32h %w[c], %w[c], %w[v]":[c]"+r"(crc):[v]"r"(value))
|
||
|
#define CRC32B(crc, value) __asm__("crc32b %w[c], %w[c], %w[v]":[c]"+r"(crc):[v]"r"(value))
|
||
|
#define CRC32CX(crc, value) __asm__("crc32cx %w[c], %w[c], %x[v]":[c]"+r"(crc):[v]"r"(value))
|
||
|
#define CRC32CW(crc, value) __asm__("crc32cw %w[c], %w[c], %w[v]":[c]"+r"(crc):[v]"r"(value))
|
||
|
#define CRC32CH(crc, value) __asm__("crc32ch %w[c], %w[c], %w[v]":[c]"+r"(crc):[v]"r"(value))
|
||
|
#define CRC32CB(crc, value) __asm__("crc32cb %w[c], %w[c], %w[v]":[c]"+r"(crc):[v]"r"(value))
|
||
|
|
||
|
static inline uint16_t __get_unaligned_le16(const uint8_t *p)
|
||
|
{
|
||
|
return p[0] | p[1] << 8;
|
||
|
}
|
||
|
|
||
|
static inline uint32_t __get_unaligned_le32(const uint8_t *p)
|
||
|
{
|
||
|
return p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24;
|
||
|
}
|
||
|
|
||
|
static inline uint64_t __get_unaligned_le64(const uint8_t *p)
|
||
|
{
|
||
|
return (uint64_t)__get_unaligned_le32(p + 4) << 32 |
|
||
|
__get_unaligned_le32(p);
|
||
|
}
|
||
|
|
||
|
static inline uint16_t get_unaligned_le16(const void *p)
|
||
|
{
|
||
|
return __get_unaligned_le16((const uint8_t *)p);
|
||
|
}
|
||
|
|
||
|
static inline uint32_t get_unaligned_le32(const void *p)
|
||
|
{
|
||
|
return __get_unaligned_le32((const uint8_t *)p);
|
||
|
}
|
||
|
|
||
|
static inline uint64_t get_unaligned_le64(const void *p)
|
||
|
{
|
||
|
return __get_unaligned_le64((const uint8_t *)p);
|
||
|
}
|
||
|
|
||
|
|
||
|
static u32 crc32_arm64_le_hw(const u8 *p, unsigned int len) {
|
||
|
u32 crc = 0xFFFFFFFF;
|
||
|
|
||
|
s64 length = len;
|
||
|
|
||
|
while ((length -= sizeof(u64)) >= 0) {
|
||
|
CRC32X(crc, get_unaligned_le64(p));
|
||
|
p += sizeof(u64);
|
||
|
}
|
||
|
|
||
|
/* The following is more efficient than the straight loop */
|
||
|
if (length & sizeof(u32)) {
|
||
|
CRC32W(crc, get_unaligned_le32(p));
|
||
|
p += sizeof(u32);
|
||
|
}
|
||
|
if (length & sizeof(u16)) {
|
||
|
CRC32H(crc, get_unaligned_le16(p));
|
||
|
p += sizeof(u16);
|
||
|
}
|
||
|
if (length & sizeof(u8))
|
||
|
CRC32B(crc, *p);
|
||
|
|
||
|
return crc ^ 0xFFFFFFFF;
|
||
|
}
|
||
|
|
||
|
#ifdef __cplusplus
|
||
|
}
|
||
|
#endif
|