xref: /linux/arch/arm64/lib/crc32.S (revision 5f2f5eaa)
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