1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * SHA-1 implementation for PowerPC.
4 *
5 * Copyright (C) 2005 Paul Mackerras <paulus@samba.org>
6 */
7
8#include <asm/ppc_asm.h>
9#include <asm/asm-offsets.h>
10#include <asm/asm-compat.h>
11
12#ifdef __BIG_ENDIAN__
13#define LWZ(rt, d, ra)	\
14	lwz	rt,d(ra)
15#else
16#define LWZ(rt, d, ra)	\
17	li	rt,d;	\
18	lwbrx	rt,rt,ra
19#endif
20
21/*
22 * We roll the registers for T, A, B, C, D, E around on each
23 * iteration; T on iteration t is A on iteration t+1, and so on.
24 * We use registers 7 - 12 for this.
25 */
26#define RT(t)	((((t)+5)%6)+7)
27#define RA(t)	((((t)+4)%6)+7)
28#define RB(t)	((((t)+3)%6)+7)
29#define RC(t)	((((t)+2)%6)+7)
30#define RD(t)	((((t)+1)%6)+7)
31#define RE(t)	((((t)+0)%6)+7)
32
33/* We use registers 16 - 31 for the W values */
34#define W(t)	(((t)%16)+16)
35
36#define LOADW(t)				\
37	LWZ(W(t),(t)*4,r4)
38
39#define STEPD0_LOAD(t)				\
40	andc	r0,RD(t),RB(t);		\
41	and	r6,RB(t),RC(t);		\
42	rotlwi	RT(t),RA(t),5;			\
43	or	r6,r6,r0;			\
44	add	r0,RE(t),r15;			\
45	add	RT(t),RT(t),r6;		\
46	add	r14,r0,W(t);			\
47	LWZ(W((t)+4),((t)+4)*4,r4);	\
48	rotlwi	RB(t),RB(t),30;			\
49	add	RT(t),RT(t),r14
50
51#define STEPD0_UPDATE(t)			\
52	and	r6,RB(t),RC(t);		\
53	andc	r0,RD(t),RB(t);		\
54	rotlwi	RT(t),RA(t),5;			\
55	rotlwi	RB(t),RB(t),30;			\
56	or	r6,r6,r0;			\
57	add	r0,RE(t),r15;			\
58	xor	r5,W((t)+4-3),W((t)+4-8);		\
59	add	RT(t),RT(t),r6;		\
60	xor	W((t)+4),W((t)+4-16),W((t)+4-14);	\
61	add	r0,r0,W(t);			\
62	xor	W((t)+4),W((t)+4),r5;			\
63	add	RT(t),RT(t),r0;		\
64	rotlwi	W((t)+4),W((t)+4),1
65
66#define STEPD1(t)				\
67	xor	r6,RB(t),RC(t);		\
68	rotlwi	RT(t),RA(t),5;			\
69	rotlwi	RB(t),RB(t),30;			\
70	xor	r6,r6,RD(t);			\
71	add	r0,RE(t),r15;			\
72	add	RT(t),RT(t),r6;		\
73	add	r0,r0,W(t);			\
74	add	RT(t),RT(t),r0
75
76#define STEPD1_UPDATE(t)				\
77	xor	r6,RB(t),RC(t);		\
78	rotlwi	RT(t),RA(t),5;			\
79	rotlwi	RB(t),RB(t),30;			\
80	xor	r6,r6,RD(t);			\
81	add	r0,RE(t),r15;			\
82	xor	r5,W((t)+4-3),W((t)+4-8);		\
83	add	RT(t),RT(t),r6;		\
84	xor	W((t)+4),W((t)+4-16),W((t)+4-14);	\
85	add	r0,r0,W(t);			\
86	xor	W((t)+4),W((t)+4),r5;			\
87	add	RT(t),RT(t),r0;		\
88	rotlwi	W((t)+4),W((t)+4),1
89
90#define STEPD2_UPDATE(t)			\
91	and	r6,RB(t),RC(t);		\
92	and	r0,RB(t),RD(t);		\
93	rotlwi	RT(t),RA(t),5;			\
94	or	r6,r6,r0;			\
95	rotlwi	RB(t),RB(t),30;			\
96	and	r0,RC(t),RD(t);		\
97	xor	r5,W((t)+4-3),W((t)+4-8);	\
98	or	r6,r6,r0;			\
99	xor	W((t)+4),W((t)+4-16),W((t)+4-14);	\
100	add	r0,RE(t),r15;			\
101	add	RT(t),RT(t),r6;		\
102	add	r0,r0,W(t);			\
103	xor	W((t)+4),W((t)+4),r5;		\
104	add	RT(t),RT(t),r0;		\
105	rotlwi	W((t)+4),W((t)+4),1
106
107#define STEP0LD4(t)				\
108	STEPD0_LOAD(t);				\
109	STEPD0_LOAD((t)+1);			\
110	STEPD0_LOAD((t)+2);			\
111	STEPD0_LOAD((t)+3)
112
113#define STEPUP4(t, fn)				\
114	STEP##fn##_UPDATE(t);			\
115	STEP##fn##_UPDATE((t)+1);		\
116	STEP##fn##_UPDATE((t)+2);		\
117	STEP##fn##_UPDATE((t)+3)
118
119#define STEPUP20(t, fn)				\
120	STEPUP4(t, fn);				\
121	STEPUP4((t)+4, fn);			\
122	STEPUP4((t)+8, fn);			\
123	STEPUP4((t)+12, fn);			\
124	STEPUP4((t)+16, fn)
125
126_GLOBAL(powerpc_sha_transform)
127	PPC_STLU r1,-INT_FRAME_SIZE(r1)
128	SAVE_8GPRS(14, r1)
129	SAVE_10GPRS(22, r1)
130
131	/* Load up A - E */
132	lwz	RA(0),0(r3)	/* A */
133	lwz	RB(0),4(r3)	/* B */
134	lwz	RC(0),8(r3)	/* C */
135	lwz	RD(0),12(r3)	/* D */
136	lwz	RE(0),16(r3)	/* E */
137
138	LOADW(0)
139	LOADW(1)
140	LOADW(2)
141	LOADW(3)
142
143	lis	r15,0x5a82	/* K0-19 */
144	ori	r15,r15,0x7999
145	STEP0LD4(0)
146	STEP0LD4(4)
147	STEP0LD4(8)
148	STEPUP4(12, D0)
149	STEPUP4(16, D0)
150
151	lis	r15,0x6ed9	/* K20-39 */
152	ori	r15,r15,0xeba1
153	STEPUP20(20, D1)
154
155	lis	r15,0x8f1b	/* K40-59 */
156	ori	r15,r15,0xbcdc
157	STEPUP20(40, D2)
158
159	lis	r15,0xca62	/* K60-79 */
160	ori	r15,r15,0xc1d6
161	STEPUP4(60, D1)
162	STEPUP4(64, D1)
163	STEPUP4(68, D1)
164	STEPUP4(72, D1)
165	lwz	r20,16(r3)
166	STEPD1(76)
167	lwz	r19,12(r3)
168	STEPD1(77)
169	lwz	r18,8(r3)
170	STEPD1(78)
171	lwz	r17,4(r3)
172	STEPD1(79)
173
174	lwz	r16,0(r3)
175	add	r20,RE(80),r20
176	add	RD(0),RD(80),r19
177	add	RC(0),RC(80),r18
178	add	RB(0),RB(80),r17
179	add	RA(0),RA(80),r16
180	mr	RE(0),r20
181	stw	RA(0),0(r3)
182	stw	RB(0),4(r3)
183	stw	RC(0),8(r3)
184	stw	RD(0),12(r3)
185	stw	RE(0),16(r3)
186
187	REST_8GPRS(14, r1)
188	REST_10GPRS(22, r1)
189	addi	r1,r1,INT_FRAME_SIZE
190	blr
191