1// +build !arm,!amd64 appengine gccgo
2
3package siphash
4
5func once(d *digest) {
6	blocks(d, d.x[:])
7}
8
9func finalize(d *digest) uint64 {
10	d0 := *d
11	once(&d0)
12
13	v0, v1, v2, v3 := d0.v0, d0.v1, d0.v2, d0.v3
14	v2 ^= 0xff
15
16	// Round 1.
17	v0 += v1
18	v1 = v1<<13 | v1>>(64-13)
19	v1 ^= v0
20	v0 = v0<<32 | v0>>(64-32)
21
22	v2 += v3
23	v3 = v3<<16 | v3>>(64-16)
24	v3 ^= v2
25
26	v0 += v3
27	v3 = v3<<21 | v3>>(64-21)
28	v3 ^= v0
29
30	v2 += v1
31	v1 = v1<<17 | v1>>(64-17)
32	v1 ^= v2
33	v2 = v2<<32 | v2>>(64-32)
34
35	// Round 2.
36	v0 += v1
37	v1 = v1<<13 | v1>>(64-13)
38	v1 ^= v0
39	v0 = v0<<32 | v0>>(64-32)
40
41	v2 += v3
42	v3 = v3<<16 | v3>>(64-16)
43	v3 ^= v2
44
45	v0 += v3
46	v3 = v3<<21 | v3>>(64-21)
47	v3 ^= v0
48
49	v2 += v1
50	v1 = v1<<17 | v1>>(64-17)
51	v1 ^= v2
52	v2 = v2<<32 | v2>>(64-32)
53
54	// Round 3.
55	v0 += v1
56	v1 = v1<<13 | v1>>(64-13)
57	v1 ^= v0
58	v0 = v0<<32 | v0>>(64-32)
59
60	v2 += v3
61	v3 = v3<<16 | v3>>(64-16)
62	v3 ^= v2
63
64	v0 += v3
65	v3 = v3<<21 | v3>>(64-21)
66	v3 ^= v0
67
68	v2 += v1
69	v1 = v1<<17 | v1>>(64-17)
70	v1 ^= v2
71	v2 = v2<<32 | v2>>(64-32)
72
73	// Round 4.
74	v0 += v1
75	v1 = v1<<13 | v1>>(64-13)
76	v1 ^= v0
77	v0 = v0<<32 | v0>>(64-32)
78
79	v2 += v3
80	v3 = v3<<16 | v3>>(64-16)
81	v3 ^= v2
82
83	v0 += v3
84	v3 = v3<<21 | v3>>(64-21)
85	v3 ^= v0
86
87	v2 += v1
88	v1 = v1<<17 | v1>>(64-17)
89	v1 ^= v2
90	v2 = v2<<32 | v2>>(64-32)
91
92	return v0 ^ v1 ^ v2 ^ v3
93}
94
95func blocks(d *digest, p []uint8) {
96	v0, v1, v2, v3 := d.v0, d.v1, d.v2, d.v3
97
98	for len(p) >= BlockSize {
99		m := uint64(p[0]) | uint64(p[1])<<8 | uint64(p[2])<<16 | uint64(p[3])<<24 |
100			uint64(p[4])<<32 | uint64(p[5])<<40 | uint64(p[6])<<48 | uint64(p[7])<<56
101
102		v3 ^= m
103
104		// Round 1.
105		v0 += v1
106		v1 = v1<<13 | v1>>(64-13)
107		v1 ^= v0
108		v0 = v0<<32 | v0>>(64-32)
109
110		v2 += v3
111		v3 = v3<<16 | v3>>(64-16)
112		v3 ^= v2
113
114		v0 += v3
115		v3 = v3<<21 | v3>>(64-21)
116		v3 ^= v0
117
118		v2 += v1
119		v1 = v1<<17 | v1>>(64-17)
120		v1 ^= v2
121		v2 = v2<<32 | v2>>(64-32)
122
123		// Round 2.
124		v0 += v1
125		v1 = v1<<13 | v1>>(64-13)
126		v1 ^= v0
127		v0 = v0<<32 | v0>>(64-32)
128
129		v2 += v3
130		v3 = v3<<16 | v3>>(64-16)
131		v3 ^= v2
132
133		v0 += v3
134		v3 = v3<<21 | v3>>(64-21)
135		v3 ^= v0
136
137		v2 += v1
138		v1 = v1<<17 | v1>>(64-17)
139		v1 ^= v2
140		v2 = v2<<32 | v2>>(64-32)
141
142		v0 ^= m
143
144		p = p[BlockSize:]
145	}
146
147	d.v0, d.v1, d.v2, d.v3 = v0, v1, v2, v3
148}
149