-
Notifications
You must be signed in to change notification settings - Fork 5
/
lsh256_amd64.go
130 lines (104 loc) · 2.32 KB
/
lsh256_amd64.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
//go:build amd64 && gc && !purego
package lsh256
import (
"hash"
"golang.org/x/sys/cpu"
)
var (
hasSSSE3 = cpu.X86.HasSSSE3
hasAVX2 = cpu.X86.HasAVX2 && cpu.X86.HasAVX
useAVX2 = false
)
type simdSet struct {
init func(ctx *lsh256ContextAsmData)
update func(ctx *lsh256ContextAsmData, data []byte)
final func(ctx *lsh256ContextAsmData, hashval []byte)
}
var (
simdSetDefault simdSet
simdSetSSE2 = simdSet{
init: lsh256InitSSE2,
update: lsh256UpdateSSE2,
final: lsh256FinalSSE2,
}
simdSetSSSE3 = simdSet{
init: lsh256InitSSE2, // lsh256InitSSSE3,
update: lsh256UpdateSSSE3,
final: lsh256FinalSSSE3,
}
simdSetAVX2 = simdSet{
init: lsh256InitAVX2,
update: lsh256UpdateAVX2,
final: lsh256FinalAVX2,
}
)
func init() {
simdSetDefault = simdSetSSE2
if hasSSSE3 {
simdSetDefault = simdSetSSSE3
}
if hasAVX2 && useAVX2 {
simdSetDefault = simdSetAVX2
}
}
func init() {
newContext = func(size int) hash.Hash {
return newContextAsm(size, simdSetDefault)
}
}
func newContextAsm(size int, simd simdSet) hash.Hash {
ctx := new(lsh256ContextAsm)
initContextAsm(ctx, size, simd)
return ctx
}
func sumAsm(size int, data []byte) [Size]byte {
var b lsh256ContextAsm
initContextAsm(&b, size, simdSetDefault)
b.Reset()
b.Write(data)
return b.checkSum()
}
type lsh256ContextAsm struct {
simd simdSet
data lsh256ContextAsmData
}
type lsh256ContextAsmData struct {
// 16 aligned
algtype uint32
_ [4]byte
remain_databytelen uint64
cv_l [32]byte
cv_r [32]byte
last_block [128]byte
}
func initContextAsm(ctx *lsh256ContextAsm, size int, simd simdSet) {
ctx.simd = simd
ctx.data.algtype = uint32(size)
ctx.Reset()
}
func (ctx *lsh256ContextAsm) Size() int {
return int(ctx.data.algtype)
}
func (ctx *lsh256ContextAsm) BlockSize() int {
return BlockSize
}
func (ctx *lsh256ContextAsm) Reset() {
ctx.data.remain_databytelen = 0
ctx.simd.init(&ctx.data)
}
func (ctx *lsh256ContextAsm) Write(data []byte) (n int, err error) {
if len(data) == 0 {
return 0, nil
}
ctx.simd.update(&ctx.data, data)
return len(data), nil
}
func (ctx *lsh256ContextAsm) Sum(p []byte) []byte {
ctx0 := *ctx
hash := ctx0.checkSum()
return append(p, hash[:ctx.Size()]...)
}
func (ctx *lsh256ContextAsm) checkSum() (hash [Size]byte) {
ctx.simd.final(&ctx.data, hash[:])
return
}