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 145f2f5eaaSKevin Bracey .macro byteorder, reg, be 155f2f5eaaSKevin Bracey .if \be 165f2f5eaaSKevin BraceyCPU_LE( rev \reg, \reg ) 175f2f5eaaSKevin Bracey .else 185f2f5eaaSKevin BraceyCPU_BE( rev \reg, \reg ) 195f2f5eaaSKevin Bracey .endif 205f2f5eaaSKevin Bracey .endm 215f2f5eaaSKevin Bracey 225f2f5eaaSKevin Bracey .macro byteorder16, reg, be 235f2f5eaaSKevin Bracey .if \be 245f2f5eaaSKevin BraceyCPU_LE( rev16 \reg, \reg ) 255f2f5eaaSKevin Bracey .else 265f2f5eaaSKevin BraceyCPU_BE( rev16 \reg, \reg ) 275f2f5eaaSKevin Bracey .endif 285f2f5eaaSKevin Bracey .endm 295f2f5eaaSKevin Bracey 305f2f5eaaSKevin Bracey .macro bitorder, reg, be 315f2f5eaaSKevin Bracey .if \be 325f2f5eaaSKevin Bracey rbit \reg, \reg 335f2f5eaaSKevin Bracey .endif 345f2f5eaaSKevin Bracey .endm 355f2f5eaaSKevin Bracey 365f2f5eaaSKevin Bracey .macro bitorder16, reg, be 375f2f5eaaSKevin Bracey .if \be 385f2f5eaaSKevin Bracey rbit \reg, \reg 395f2f5eaaSKevin Bracey lsr \reg, \reg, #16 405f2f5eaaSKevin Bracey .endif 415f2f5eaaSKevin Bracey .endm 425f2f5eaaSKevin Bracey 435f2f5eaaSKevin Bracey .macro bitorder8, reg, be 445f2f5eaaSKevin Bracey .if \be 455f2f5eaaSKevin Bracey rbit \reg, \reg 465f2f5eaaSKevin Bracey lsr \reg, \reg, #24 475f2f5eaaSKevin Bracey .endif 485f2f5eaaSKevin Bracey .endm 495f2f5eaaSKevin Bracey 505f2f5eaaSKevin Bracey .macro __crc32, c, be=0 515f2f5eaaSKevin 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] 645f2f5eaaSKevin Bracey byteorder x3, \be 655f2f5eaaSKevin Bracey byteorder x4, \be 665f2f5eaaSKevin Bracey byteorder x5, \be 675f2f5eaaSKevin Bracey byteorder x6, \be 685f2f5eaaSKevin Bracey bitorder x3, \be 695f2f5eaaSKevin Bracey bitorder x4, \be 705f2f5eaaSKevin Bracey bitorder x5, \be 715f2f5eaaSKevin 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] 995f2f5eaaSKevin Bracey byteorder x3, \be 1005f2f5eaaSKevin Bracey byteorder x4, \be 1015f2f5eaaSKevin Bracey byteorder x5, \be 1025f2f5eaaSKevin Bracey byteorder x6, \be 1035f2f5eaaSKevin Bracey bitorder x3, \be 1045f2f5eaaSKevin Bracey bitorder x4, \be 1055f2f5eaaSKevin Bracey bitorder x5, \be 1065f2f5eaaSKevin 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 1125f2f5eaaSKevin Bracey0: bitorder w0, \be 1135f2f5eaaSKevin Bracey ret 1147481cddfSArd Biesheuvel 1157481cddfSArd Biesheuvel8: tbz x2, #3, 4f 1167481cddfSArd Biesheuvel ldr x3, [x1], #8 1175f2f5eaaSKevin Bracey byteorder x3, \be 1185f2f5eaaSKevin Bracey bitorder x3, \be 1197481cddfSArd Biesheuvel crc32\c\()x w0, w0, x3 1207481cddfSArd Biesheuvel4: tbz x2, #2, 2f 1217481cddfSArd Biesheuvel ldr w3, [x1], #4 1225f2f5eaaSKevin Bracey byteorder w3, \be 1235f2f5eaaSKevin Bracey bitorder w3, \be 1247481cddfSArd Biesheuvel crc32\c\()w w0, w0, w3 1257481cddfSArd Biesheuvel2: tbz x2, #1, 1f 1267481cddfSArd Biesheuvel ldrh w3, [x1], #2 1275f2f5eaaSKevin Bracey byteorder16 w3, \be 1285f2f5eaaSKevin Bracey bitorder16 w3, \be 1297481cddfSArd Biesheuvel crc32\c\()h w0, w0, w3 1307481cddfSArd Biesheuvel1: tbz x2, #0, 0f 1317481cddfSArd Biesheuvel ldrb w3, [x1] 1325f2f5eaaSKevin Bracey bitorder8 w3, \be 1337481cddfSArd Biesheuvel crc32\c\()b w0, w0, w3 1345f2f5eaaSKevin Bracey0: bitorder w0, \be 1355f2f5eaaSKevin 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) 1535f2f5eaaSKevin Bracey 1545f2f5eaaSKevin Bracey .align 5 1555f2f5eaaSKevin BraceySYM_FUNC_START(crc32_be) 1565f2f5eaaSKevin Braceyalternative_if_not ARM64_HAS_CRC32 1575f2f5eaaSKevin Bracey b crc32_be_base 1585f2f5eaaSKevin Braceyalternative_else_nop_endif 1595f2f5eaaSKevin Bracey __crc32 be=1 1605f2f5eaaSKevin BraceySYM_FUNC_END(crc32_be) 161