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