1// +build amd64,!appengine,!gccgo
2
3#define ROUND(v0, v1, v2, v3) \
4	ADDQ v1, v0; \
5	RORQ $51, v1; \
6	ADDQ v3, v2; \
7	XORQ v0, v1; \
8	RORQ $48, v3; \
9	RORQ $32, v0; \
10	XORQ v2, v3; \
11	ADDQ v1, v2; \
12	ADDQ v3, v0; \
13	RORQ $43, v3; \
14	RORQ $47, v1; \
15	XORQ v0, v3; \
16	XORQ v2, v1; \
17	RORQ $32, v2
18
19// blocks(d *digest, data []uint8)
20TEXT ·blocks(SB),4,$0-32
21	MOVQ d+0(FP), BX
22	MOVQ 0(BX), R9		// R9 = v0
23	MOVQ 8(BX), R10		// R10 = v1
24	MOVQ 16(BX), R11	// R11 = v2
25	MOVQ 24(BX), R12	// R12 = v3
26	MOVQ data+8(FP), DI	// DI = *uint64
27	MOVQ data_len+16(FP), SI// SI = nblocks
28	XORL DX, DX		// DX = index (0)
29	SHRQ $3, SI 		// SI /= 8
30body:
31	CMPQ DX, SI
32	JGE  end
33	MOVQ 0(DI)(DX*8), CX	// CX = m
34	XORQ CX, R12
35	ROUND(R9, R10, R11, R12)
36	ROUND(R9, R10, R11, R12)
37	XORQ CX, R9
38	ADDQ $1, DX
39	JMP  body
40end:
41	MOVQ R9, 0(BX)
42	MOVQ R10, 8(BX)
43	MOVQ R11, 16(BX)
44	MOVQ R12, 24(BX)
45	RET
46
47// once(d *digest)
48TEXT ·once(SB),4,$0-8
49	MOVQ d+0(FP), BX
50	MOVQ 0(BX), R9		// R9 = v0
51	MOVQ 8(BX), R10		// R10 = v1
52	MOVQ 16(BX), R11	// R11 = v2
53	MOVQ 24(BX), R12	// R12 = v3
54	MOVQ 48(BX), CX		// CX = d.x[:]
55	XORQ CX, R12
56	ROUND(R9, R10, R11, R12)
57	ROUND(R9, R10, R11, R12)
58	XORQ CX, R9
59	MOVQ R9, 0(BX)
60	MOVQ R10, 8(BX)
61	MOVQ R11, 16(BX)
62	MOVQ R12, 24(BX)
63	RET
64
65// finalize(d *digest) uint64
66TEXT ·finalize(SB),4,$0-16
67	MOVQ d+0(FP), BX
68	MOVQ 0(BX), R9		// R9 = v0
69	MOVQ 8(BX), R10		// R10 = v1
70	MOVQ 16(BX), R11	// R11 = v2
71	MOVQ 24(BX), R12	// R12 = v3
72	MOVQ 48(BX), CX		// CX = d.x[:]
73	XORQ CX, R12
74	ROUND(R9, R10, R11, R12)
75	ROUND(R9, R10, R11, R12)
76	XORQ CX, R9
77	NOTB R11
78	ROUND(R9, R10, R11, R12)
79	ROUND(R9, R10, R11, R12)
80	ROUND(R9, R10, R11, R12)
81	ROUND(R9, R10, R11, R12)
82	XORQ R12, R11
83	XORQ R10, R9
84	XORQ R11, R9
85	MOVQ R9, ret+8(FP)
86	RET
87
88