1d2912cb1SThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */ 27481cddfSArd Biesheuvel/* 37481cddfSArd Biesheuvel * Accelerated CRC32(C) using AArch64 CRC instructions 47481cddfSArd Biesheuvel * 57481cddfSArd Biesheuvel * Copyright (C) 2016 - 2018 Linaro Ltd <ard.biesheuvel@linaro.org> 67481cddfSArd Biesheuvel */ 77481cddfSArd Biesheuvel 87481cddfSArd Biesheuvel#include <linux/linkage.h> 97481cddfSArd Biesheuvel#include <asm/alternative.h> 107481cddfSArd Biesheuvel#include <asm/assembler.h> 117481cddfSArd Biesheuvel 1230218da5SMark Brown .arch armv8-a+crc 137481cddfSArd Biesheuvel 14*5f2f5eaaSKevin Bracey .macro byteorder, reg, be 15*5f2f5eaaSKevin Bracey .if \be 16*5f2f5eaaSKevin BraceyCPU_LE( rev \reg, \reg ) 17*5f2f5eaaSKevin Bracey .else 18*5f2f5eaaSKevin BraceyCPU_BE( rev \reg, \reg ) 19*5f2f5eaaSKevin Bracey .endif 20*5f2f5eaaSKevin Bracey .endm 21*5f2f5eaaSKevin Bracey 22*5f2f5eaaSKevin Bracey .macro byteorder16, reg, be 23*5f2f5eaaSKevin Bracey .if \be 24*5f2f5eaaSKevin BraceyCPU_LE( rev16 \reg, \reg ) 25*5f2f5eaaSKevin Bracey .else 26*5f2f5eaaSKevin BraceyCPU_BE( rev16 \reg, \reg ) 27*5f2f5eaaSKevin Bracey .endif 28*5f2f5eaaSKevin Bracey .endm 29*5f2f5eaaSKevin Bracey 30*5f2f5eaaSKevin Bracey .macro bitorder, reg, be 31*5f2f5eaaSKevin Bracey .if \be 32*5f2f5eaaSKevin Bracey rbit \reg, \reg 33*5f2f5eaaSKevin Bracey .endif 34*5f2f5eaaSKevin Bracey .endm 35*5f2f5eaaSKevin Bracey 36*5f2f5eaaSKevin Bracey .macro bitorder16, reg, be 37*5f2f5eaaSKevin Bracey .if \be 38*5f2f5eaaSKevin Bracey rbit \reg, \reg 39*5f2f5eaaSKevin Bracey lsr \reg, \reg, #16 40*5f2f5eaaSKevin Bracey .endif 41*5f2f5eaaSKevin Bracey .endm 42*5f2f5eaaSKevin Bracey 43*5f2f5eaaSKevin Bracey .macro bitorder8, reg, be 44*5f2f5eaaSKevin Bracey .if \be 45*5f2f5eaaSKevin Bracey rbit \reg, \reg 46*5f2f5eaaSKevin Bracey lsr \reg, \reg, #24 47*5f2f5eaaSKevin Bracey .endif 48*5f2f5eaaSKevin Bracey .endm 49*5f2f5eaaSKevin Bracey 50*5f2f5eaaSKevin Bracey .macro __crc32, c, be=0 51*5f2f5eaaSKevin Bracey bitorder w0, \be 52efdb25efSArd Biesheuvel cmp x2, #16 53efdb25efSArd Biesheuvel b.lt 8f // less than 16 bytes 54efdb25efSArd Biesheuvel 55efdb25efSArd Biesheuvel and x7, x2, #0x1f 56efdb25efSArd Biesheuvel and x2, x2, #~0x1f 57efdb25efSArd Biesheuvel cbz x7, 32f // multiple of 32 bytes 58efdb25efSArd Biesheuvel 59efdb25efSArd Biesheuvel and x8, x7, #0xf 60efdb25efSArd Biesheuvel ldp x3, x4, [x1] 61efdb25efSArd Biesheuvel add x8, x8, x1 62efdb25efSArd Biesheuvel add x1, x1, x7 63efdb25efSArd Biesheuvel ldp x5, x6, [x8] 64*5f2f5eaaSKevin Bracey byteorder x3, \be 65*5f2f5eaaSKevin Bracey byteorder x4, \be 66*5f2f5eaaSKevin Bracey byteorder x5, \be 67*5f2f5eaaSKevin Bracey byteorder x6, \be 68*5f2f5eaaSKevin Bracey bitorder x3, \be 69*5f2f5eaaSKevin Bracey bitorder x4, \be 70*5f2f5eaaSKevin Bracey bitorder x5, \be 71*5f2f5eaaSKevin Bracey bitorder x6, \be 72efdb25efSArd Biesheuvel 73efdb25efSArd Biesheuvel tst x7, #8 74efdb25efSArd Biesheuvel crc32\c\()x w8, w0, x3 75efdb25efSArd Biesheuvel csel x3, x3, x4, eq 76efdb25efSArd Biesheuvel csel w0, w0, w8, eq 77efdb25efSArd Biesheuvel tst x7, #4 78efdb25efSArd Biesheuvel lsr x4, x3, #32 79efdb25efSArd Biesheuvel crc32\c\()w w8, w0, w3 80efdb25efSArd Biesheuvel csel x3, x3, x4, eq 81efdb25efSArd Biesheuvel csel w0, w0, w8, eq 82efdb25efSArd Biesheuvel tst x7, #2 83efdb25efSArd Biesheuvel lsr w4, w3, #16 84efdb25efSArd Biesheuvel crc32\c\()h w8, w0, w3 85efdb25efSArd Biesheuvel csel w3, w3, w4, eq 86efdb25efSArd Biesheuvel csel w0, w0, w8, eq 87efdb25efSArd Biesheuvel tst x7, #1 88efdb25efSArd Biesheuvel crc32\c\()b w8, w0, w3 89efdb25efSArd Biesheuvel csel w0, w0, w8, eq 90efdb25efSArd Biesheuvel tst x7, #16 91efdb25efSArd Biesheuvel crc32\c\()x w8, w0, x5 92efdb25efSArd Biesheuvel crc32\c\()x w8, w8, x6 93efdb25efSArd Biesheuvel csel w0, w0, w8, eq 94efdb25efSArd Biesheuvel cbz x2, 0f 95efdb25efSArd Biesheuvel 96efdb25efSArd Biesheuvel32: ldp x3, x4, [x1], #32 97efdb25efSArd Biesheuvel sub x2, x2, #32 98efdb25efSArd Biesheuvel ldp x5, x6, [x1, #-16] 99*5f2f5eaaSKevin Bracey byteorder x3, \be 100*5f2f5eaaSKevin Bracey byteorder x4, \be 101*5f2f5eaaSKevin Bracey byteorder x5, \be 102*5f2f5eaaSKevin Bracey byteorder x6, \be 103*5f2f5eaaSKevin Bracey bitorder x3, \be 104*5f2f5eaaSKevin Bracey bitorder x4, \be 105*5f2f5eaaSKevin Bracey bitorder x5, \be 106*5f2f5eaaSKevin Bracey bitorder x6, \be 1077481cddfSArd Biesheuvel crc32\c\()x w0, w0, x3 1087481cddfSArd Biesheuvel crc32\c\()x w0, w0, x4 109efdb25efSArd Biesheuvel crc32\c\()x w0, w0, x5 110efdb25efSArd Biesheuvel crc32\c\()x w0, w0, x6 111efdb25efSArd Biesheuvel cbnz x2, 32b 112*5f2f5eaaSKevin Bracey0: bitorder w0, \be 113*5f2f5eaaSKevin Bracey ret 1147481cddfSArd Biesheuvel 1157481cddfSArd Biesheuvel8: tbz x2, #3, 4f 1167481cddfSArd Biesheuvel ldr x3, [x1], #8 117*5f2f5eaaSKevin Bracey byteorder x3, \be 118*5f2f5eaaSKevin Bracey bitorder x3, \be 1197481cddfSArd Biesheuvel crc32\c\()x w0, w0, x3 1207481cddfSArd Biesheuvel4: tbz x2, #2, 2f 1217481cddfSArd Biesheuvel ldr w3, [x1], #4 122*5f2f5eaaSKevin Bracey byteorder w3, \be 123*5f2f5eaaSKevin Bracey bitorder w3, \be 1247481cddfSArd Biesheuvel crc32\c\()w w0, w0, w3 1257481cddfSArd Biesheuvel2: tbz x2, #1, 1f 1267481cddfSArd Biesheuvel ldrh w3, [x1], #2 127*5f2f5eaaSKevin Bracey byteorder16 w3, \be 128*5f2f5eaaSKevin Bracey bitorder16 w3, \be 1297481cddfSArd Biesheuvel crc32\c\()h w0, w0, w3 1307481cddfSArd Biesheuvel1: tbz x2, #0, 0f 1317481cddfSArd Biesheuvel ldrb w3, [x1] 132*5f2f5eaaSKevin Bracey bitorder8 w3, \be 1337481cddfSArd Biesheuvel crc32\c\()b w0, w0, w3 134*5f2f5eaaSKevin Bracey0: bitorder w0, \be 135*5f2f5eaaSKevin Bracey ret 1367481cddfSArd Biesheuvel .endm 1377481cddfSArd Biesheuvel 1387481cddfSArd Biesheuvel .align 5 1393ac0f452SMark BrownSYM_FUNC_START(crc32_le) 1407481cddfSArd Biesheuvelalternative_if_not ARM64_HAS_CRC32 1417481cddfSArd Biesheuvel b crc32_le_base 1427481cddfSArd Biesheuvelalternative_else_nop_endif 1437481cddfSArd Biesheuvel __crc32 1443ac0f452SMark BrownSYM_FUNC_END(crc32_le) 1457481cddfSArd Biesheuvel 1467481cddfSArd Biesheuvel .align 5 1473ac0f452SMark BrownSYM_FUNC_START(__crc32c_le) 1487481cddfSArd Biesheuvelalternative_if_not ARM64_HAS_CRC32 1497481cddfSArd Biesheuvel b __crc32c_le_base 1507481cddfSArd Biesheuvelalternative_else_nop_endif 1517481cddfSArd Biesheuvel __crc32 c 1523ac0f452SMark BrownSYM_FUNC_END(__crc32c_le) 153*5f2f5eaaSKevin Bracey 154*5f2f5eaaSKevin Bracey .align 5 155*5f2f5eaaSKevin BraceySYM_FUNC_START(crc32_be) 156*5f2f5eaaSKevin Braceyalternative_if_not ARM64_HAS_CRC32 157*5f2f5eaaSKevin Bracey b crc32_be_base 158*5f2f5eaaSKevin Braceyalternative_else_nop_endif 159*5f2f5eaaSKevin Bracey __crc32 be=1 160*5f2f5eaaSKevin BraceySYM_FUNC_END(crc32_be) 161