1 // Copyright 2026 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4
5 //go:build !purego
6
7 // SHA-3 (Keccak-f[1600]) for LoongArch LSX, two lanes per register.
8 // Column x is stored as:
9 // V(0+x) = [L(x,0), L(x,1)]
10 // V(5+x) = [L(x,2), L(x,3)]
11 // V(10+x) = [L(x,4), x] (element 1 undefined; masked by V31 in theta)
12 // V15-V19 parity/pi-A, V20-V24 D/pi-B, V25-V29 pi-C, V30 tmp, V31 mask.
13
14 #include "textflag.h"
15
16 TEXT ·keccakF1600LSX(SB), NOSPLIT, $200-8
17 MOVV a+0(FP), R4
18 MOVV $round_consts<>(SB), R6
19 MOVV $rho_pairs<>(SB), R8
20 MOVV $24, R7
21
22 // V31 = [-1, 0] mask (element 0 set, element 1 clear).
23 VXORV V31, V31, V31
24 MOVV $-1, R5
25 VMOVQ R5, V31.V[0]
26
27 // Load state: A_x = lanes (x, x+5), B_x = (x+10, x+15), C_x = (x+20, 0).
28 MOVV 0(R4), R5
29 VMOVQ R5, V0.V[0]
30 MOVV 40(R4), R5
31 VMOVQ R5, V0.V[1]
32 MOVV 8(R4), R5
33 VMOVQ R5, V1.V[0]
34 MOVV 48(R4), R5
35 VMOVQ R5, V1.V[1]
36 MOVV 16(R4), R5
37 VMOVQ R5, V2.V[0]
38 MOVV 56(R4), R5
39 VMOVQ R5, V2.V[1]
40 MOVV 24(R4), R5
41 VMOVQ R5, V3.V[0]
42 MOVV 64(R4), R5
43 VMOVQ R5, V3.V[1]
44 MOVV 32(R4), R5
45 VMOVQ R5, V4.V[0]
46 MOVV 72(R4), R5
47 VMOVQ R5, V4.V[1]
48
49 MOVV 80(R4), R5
50 VMOVQ R5, V5.V[0]
51 MOVV 120(R4), R5
52 VMOVQ R5, V5.V[1]
53 MOVV 88(R4), R5
54 VMOVQ R5, V6.V[0]
55 MOVV 128(R4), R5
56 VMOVQ R5, V6.V[1]
57 MOVV 96(R4), R5
58 VMOVQ R5, V7.V[0]
59 MOVV 136(R4), R5
60 VMOVQ R5, V7.V[1]
61 MOVV 104(R4), R5
62 VMOVQ R5, V8.V[0]
63 MOVV 144(R4), R5
64 VMOVQ R5, V8.V[1]
65 MOVV 112(R4), R5
66 VMOVQ R5, V9.V[0]
67 MOVV 152(R4), R5
68 VMOVQ R5, V9.V[1]
69
70 VXORV V10, V10, V10
71 VXORV V11, V11, V11
72 VXORV V12, V12, V12
73 VXORV V13, V13, V13
74 VXORV V14, V14, V14
75 MOVV 160(R4), R5
76 VMOVQ R5, V10.V[0]
77 MOVV 168(R4), R5
78 VMOVQ R5, V11.V[0]
79 MOVV 176(R4), R5
80 VMOVQ R5, V12.V[0]
81 MOVV 184(R4), R5
82 VMOVQ R5, V13.V[0]
83 MOVV 192(R4), R5
84 VMOVQ R5, V14.V[0]
85
86 loop:
87 // Theta: C[x] = parity of column x -> V15+x, both elements.
88 // T = A^B^(C&mask); PC = T ^ swap(T).
89 VXORV V0, V5, V30
90 VANDV V31, V10, V29
91 VXORV V30, V29, V30
92 VILVHV V30, V30, V29
93 VILVLV V29, V30, V29
94 VXORV V30, V29, V15 // C[0]
95
96 VXORV V1, V6, V30
97 VANDV V31, V11, V29
98 VXORV V30, V29, V30
99 VILVHV V30, V30, V29
100 VILVLV V29, V30, V29
101 VXORV V30, V29, V16 // C[1]
102
103 VXORV V2, V7, V30
104 VANDV V31, V12, V29
105 VXORV V30, V29, V30
106 VILVHV V30, V30, V29
107 VILVLV V29, V30, V29
108 VXORV V30, V29, V17 // C[2]
109
110 VXORV V3, V8, V30
111 VANDV V31, V13, V29
112 VXORV V30, V29, V30
113 VILVHV V30, V30, V29
114 VILVLV V29, V30, V29
115 VXORV V30, V29, V18 // C[3]
116
117 VXORV V4, V9, V30
118 VANDV V31, V14, V29
119 VXORV V30, V29, V30
120 VILVHV V30, V30, V29
121 VILVLV V29, V30, V29
122 VXORV V30, V29, V19 // C[4]
123
124 // D_x = C[x-1] ^ rotl(C[x+1],1) -> V20+x (broadcast both elements).
125 VROTRV $63, V16, V30
126 VXORV V19, V30, V20 // D0
127 VROTRV $63, V17, V30
128 VXORV V15, V30, V21 // D1
129 VROTRV $63, V18, V30
130 VXORV V16, V30, V22 // D2
131 VROTRV $63, V19, V30
132 VXORV V17, V30, V23 // D3
133 VROTRV $63, V15, V30
134 VXORV V18, V30, V24 // D4
135
136 // Theta apply + rho: per reg, R = rotr(R ^ D_x, rho-pair).
137 VXORV V20, V0, V0
138 VMOVQ 0(R8), V30
139 VROTRV V30, V0, V0
140 VXORV V21, V1, V1
141 VMOVQ 16(R8), V30
142 VROTRV V30, V1, V1
143 VXORV V22, V2, V2
144 VMOVQ 32(R8), V30
145 VROTRV V30, V2, V2
146 VXORV V23, V3, V3
147 VMOVQ 48(R8), V30
148 VROTRV V30, V3, V3
149 VXORV V24, V4, V4
150 VMOVQ 64(R8), V30
151 VROTRV V30, V4, V4
152
153 VXORV V20, V5, V5
154 VMOVQ 80(R8), V30
155 VROTRV V30, V5, V5
156 VXORV V21, V6, V6
157 VMOVQ 96(R8), V30
158 VROTRV V30, V6, V6
159 VXORV V22, V7, V7
160 VMOVQ 112(R8), V30
161 VROTRV V30, V7, V7
162 VXORV V23, V8, V8
163 VMOVQ 128(R8), V30
164 VROTRV V30, V8, V8
165 VXORV V24, V9, V9
166 VMOVQ 144(R8), V30
167 VROTRV V30, V9, V9
168
169 VXORV V20, V10, V10
170 VMOVQ 160(R8), V30
171 VROTRV V30, V10, V10
172 VXORV V21, V11, V11
173 VMOVQ 176(R8), V30
174 VROTRV V30, V11, V11
175 VXORV V22, V12, V12
176 VMOVQ 192(R8), V30
177 VROTRV V30, V12, V12
178 VXORV V23, V13, V13
179 VMOVQ 208(R8), V30
180 VROTRV V30, V13, V13
181 VXORV V24, V14, V14
182 VMOVQ 224(R8), V30
183 VROTRV V30, V14, V14
184
185 // Pi: gather post-rho lanes into V15-V29.
186 // A'_x' = [L'(x',x'), L'((x'+3)%5, x')]
187 VILVLV V0, V3, V15 // [L'(0,0), L'(3,0)]
188 VILVHV V1, V4, V16 // [L'(1,1), L'(4,1)]
189 VILVLV V7, V5, V17 // [L'(2,2), L'(0,2)]
190 VILVHV V8, V6, V18 // [L'(3,3), L'(1,3)]
191 VILVLV V14, V12, V19 // [L'(4,4), L'(2,4)]
192
193 // B'_x' = [L'((x'+1)%5, x'), L'((x'+4)%5, x')]
194 VILVLV V1, V4, V20 // [L'(1,0), L'(4,0)]
195 VILVHV V2, V0, V21 // [L'(2,1), L'(0,1)]
196 VILVLV V8, V6, V22 // [L'(3,2), L'(1,2)]
197 VILVHV V9, V7, V23 // [L'(4,3), L'(2,3)]
198 VILVLV V10, V13, V24 // [L'(0,4), L'(3,4)]
199
200 // C'_x' = [L'((x'+2)%5, x'), 0] (V31.e1 = 0 supplies the zero)
201 VILVLV V2, V31, V25 // [L'(2,0), 0]
202 VILVHV V3, V31, V26 // [L'(3,1), 0]
203 VILVLV V9, V31, V27 // [L'(4,2), 0]
204 VILVHV V5, V31, V28 // [L'(0,3), 0]
205 VILVLV V11, V31, V29 // [L'(1,4), 0]
206
207 // Chi: out_x = in_x ^ (~in_{x+1} & in_{x+2}), per group, mod 5.
208 // Group A: sources V15-V19 -> dests V0-V4.
209 VANDNV V17, V16, V30
210 VXORV V15, V30, V0
211 VANDNV V18, V17, V30
212 VXORV V16, V30, V1
213 VANDNV V19, V18, V30
214 VXORV V17, V30, V2
215 VANDNV V15, V19, V30
216 VXORV V18, V30, V3
217 VANDNV V16, V15, V30
218 VXORV V19, V30, V4
219
220 // Group B: sources V20-V24 -> dests V5-V9.
221 VANDNV V22, V21, V30
222 VXORV V20, V30, V5
223 VANDNV V23, V22, V30
224 VXORV V21, V30, V6
225 VANDNV V24, V23, V30
226 VXORV V22, V30, V7
227 VANDNV V20, V24, V30
228 VXORV V23, V30, V8
229 VANDNV V21, V20, V30
230 VXORV V24, V30, V9
231
232 // Group C: sources V25-V29 -> dests V10-V14.
233 VANDNV V27, V26, V30
234 VXORV V25, V30, V10
235 VANDNV V28, V27, V30
236 VXORV V26, V30, V11
237 VANDNV V29, V28, V30
238 VXORV V27, V30, V12
239 VANDNV V25, V29, V30
240 VXORV V28, V30, V13
241 VANDNV V26, V25, V30
242 VXORV V29, V30, V14
243
244 // Iota: lane(0,0) = V0.e0 ^= RC[round] (mask to element 0).
245 MOVV (R6), R5
246 VXORV V30, V30, V30
247 VMOVQ R5, V30.V[0]
248 VXORV V30, V0, V0
249
250 ADDV $8, R6
251 SUBV $1, R7
252 BNE R7, R0, loop
253
254 // Store lanes back.
255 VMOVQ V0.V[0], 0(R4)
256 VMOVQ V0.V[1], 40(R4)
257 VMOVQ V1.V[0], 8(R4)
258 VMOVQ V1.V[1], 48(R4)
259 VMOVQ V2.V[0], 16(R4)
260 VMOVQ V2.V[1], 56(R4)
261 VMOVQ V3.V[0], 24(R4)
262 VMOVQ V3.V[1], 64(R4)
263 VMOVQ V4.V[0], 32(R4)
264 VMOVQ V4.V[1], 72(R4)
265 VMOVQ V5.V[0], 80(R4)
266 VMOVQ V5.V[1], 120(R4)
267 VMOVQ V6.V[0], 88(R4)
268 VMOVQ V6.V[1], 128(R4)
269 VMOVQ V7.V[0], 96(R4)
270 VMOVQ V7.V[1], 136(R4)
271 VMOVQ V8.V[0], 104(R4)
272 VMOVQ V8.V[1], 144(R4)
273 VMOVQ V9.V[0], 112(R4)
274 VMOVQ V9.V[1], 152(R4)
275 VMOVQ V10.V[0], 160(R4)
276 VMOVQ V11.V[0], 168(R4)
277 VMOVQ V12.V[0], 176(R4)
278 VMOVQ V13.V[0], 184(R4)
279 VMOVQ V14.V[0], 192(R4)
280 RET
281
282 // rho_pairs: per-register right-rotation amounts = 64 - rho[lane].
283 // Order: A_0..A_4, B_0..B_4, C_0..C_4.
284 DATA rho_pairs<>+0x00(SB)/8, $0x0000000000000000 // r(0,0)=0
285 DATA rho_pairs<>+0x08(SB)/8, $0x000000000000001c // r(0,1)=36 -> 28
286 DATA rho_pairs<>+0x10(SB)/8, $0x000000000000003f // r(1,0)=1 -> 63
287 DATA rho_pairs<>+0x18(SB)/8, $0x0000000000000014 // r(1,1)=44 -> 20
288 DATA rho_pairs<>+0x20(SB)/8, $0x0000000000000002 // r(2,0)=62 -> 2
289 DATA rho_pairs<>+0x28(SB)/8, $0x000000000000003a // r(2,1)=6 -> 58
290 DATA rho_pairs<>+0x30(SB)/8, $0x0000000000000024 // r(3,0)=28 -> 36
291 DATA rho_pairs<>+0x38(SB)/8, $0x0000000000000009 // r(3,1)=55 -> 9
292 DATA rho_pairs<>+0x40(SB)/8, $0x0000000000000025 // r(4,0)=27 -> 37
293 DATA rho_pairs<>+0x48(SB)/8, $0x000000000000002c // r(4,1)=20 -> 44
294
295 DATA rho_pairs<>+0x50(SB)/8, $0x000000000000003d // r(0,2)=3 -> 61
296 DATA rho_pairs<>+0x58(SB)/8, $0x0000000000000017 // r(0,3)=41 -> 23
297 DATA rho_pairs<>+0x60(SB)/8, $0x0000000000000036 // r(1,2)=10 -> 54
298 DATA rho_pairs<>+0x68(SB)/8, $0x0000000000000013 // r(1,3)=45 -> 19
299 DATA rho_pairs<>+0x70(SB)/8, $0x0000000000000015 // r(2,2)=43 -> 21
300 DATA rho_pairs<>+0x78(SB)/8, $0x0000000000000031 // r(2,3)=15 -> 49
301 DATA rho_pairs<>+0x80(SB)/8, $0x0000000000000027 // r(3,2)=25 -> 39
302 DATA rho_pairs<>+0x88(SB)/8, $0x000000000000002b // r(3,3)=21 -> 43
303 DATA rho_pairs<>+0x90(SB)/8, $0x0000000000000019 // r(4,2)=39 -> 25
304 DATA rho_pairs<>+0x98(SB)/8, $0x0000000000000038 // r(4,3)=8 -> 56
305
306 DATA rho_pairs<>+0xa0(SB)/8, $0x000000000000002e // r(0,4)=18 -> 46
307 DATA rho_pairs<>+0xa8(SB)/8, $0
308 DATA rho_pairs<>+0xb0(SB)/8, $0x000000000000003e // r(1,4)=2 -> 62
309 DATA rho_pairs<>+0xb8(SB)/8, $0
310 DATA rho_pairs<>+0xc0(SB)/8, $0x0000000000000003 // r(2,4)=61 -> 3
311 DATA rho_pairs<>+0xc8(SB)/8, $0
312 DATA rho_pairs<>+0xd0(SB)/8, $0x0000000000000008 // r(3,4)=56 -> 8
313 DATA rho_pairs<>+0xd8(SB)/8, $0
314 DATA rho_pairs<>+0xe0(SB)/8, $0x0000000000000032 // r(4,4)=14 -> 50
315 DATA rho_pairs<>+0xe8(SB)/8, $0
316 GLOBL rho_pairs<>(SB), NOPTR|RODATA, $240
317
318 // Round constants
319 DATA round_consts<>+0x00(SB)/8, $0x0000000000000001
320 DATA round_consts<>+0x08(SB)/8, $0x0000000000008082
321 DATA round_consts<>+0x10(SB)/8, $0x800000000000808a
322 DATA round_consts<>+0x18(SB)/8, $0x8000000080008000
323 DATA round_consts<>+0x20(SB)/8, $0x000000000000808b
324 DATA round_consts<>+0x28(SB)/8, $0x0000000080000001
325 DATA round_consts<>+0x30(SB)/8, $0x8000000080008081
326 DATA round_consts<>+0x38(SB)/8, $0x8000000000008009
327 DATA round_consts<>+0x40(SB)/8, $0x000000000000008a
328 DATA round_consts<>+0x48(SB)/8, $0x0000000000000088
329 DATA round_consts<>+0x50(SB)/8, $0x0000000080008009
330 DATA round_consts<>+0x58(SB)/8, $0x000000008000000a
331 DATA round_consts<>+0x60(SB)/8, $0x000000008000808b
332 DATA round_consts<>+0x68(SB)/8, $0x800000000000008b
333 DATA round_consts<>+0x70(SB)/8, $0x8000000000008089
334 DATA round_consts<>+0x78(SB)/8, $0x8000000000008003
335 DATA round_consts<>+0x80(SB)/8, $0x8000000000008002
336 DATA round_consts<>+0x88(SB)/8, $0x8000000000000080
337 DATA round_consts<>+0x90(SB)/8, $0x000000000000800a
338 DATA round_consts<>+0x98(SB)/8, $0x800000008000000a
339 DATA round_consts<>+0xA0(SB)/8, $0x8000000080008081
340 DATA round_consts<>+0xA8(SB)/8, $0x8000000000008080
341 DATA round_consts<>+0xB0(SB)/8, $0x0000000080000001
342 DATA round_consts<>+0xB8(SB)/8, $0x8000000080008008
343 GLOBL round_consts<>(SB), NOPTR|RODATA, $192
344
View as plain text