-
Notifications
You must be signed in to change notification settings - Fork 5
/
lsh256_amd64.go
132 lines (106 loc) · 2.37 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
131
132
//go:build amd64
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, databitlen uint32)
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
int uint32
_pad0 [16 - 4]byte
// 16 aligned
remain_databitlen uint32
_pad1 [16 - 4]byte
cv_l [32 / 4]uint32
cv_r [32 / 4]uint32
last_block [128]byte
}
func initContextAsm(ctx *lsh256ContextAsm, size int, simd simdSet) {
ctx.simd = simd
ctx.data.int = uint32(size)
ctx.Reset()
}
func (ctx *lsh256ContextAsm) Size() int {
return int(ctx.data.int)
}
func (ctx *lsh256ContextAsm) BlockSize() int {
return BlockSize
}
func (ctx *lsh256ContextAsm) Reset() {
ctx.data.remain_databitlen = 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, uint32(len(data)*8))
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
}