Skip to content

Commit 0eb66fe

Browse files
committed
doc: READMEs for remaining "real world" examples
Updates mmcloughlin#14
1 parent 85a7299 commit 0eb66fe

File tree

4 files changed

+184
-0
lines changed

4 files changed

+184
-0
lines changed

examples/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,11 @@ Features:
1111
* **[returns](returns):** Building return values.
1212
* **[complex](complex):** Working with `complex{64,128}` types.
1313
* **[data](data):** Defining `DATA` sections.
14+
15+
"Real" examples:
16+
17+
* **[fnv1a](fnv1a):** [FNV-1a](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash) hash function.
18+
* **[dot](dot):** Vector dot product.
19+
* **[geohash](geohash):** Integer [geohash](https://en.wikipedia.org/wiki/Geohash) encoding.
20+
* **[sha1](sha1):** [SHA-1](https://en.wikipedia.org/wiki/SHA-1) cryptographic hash.
21+
* **[stadtx](stadtx):** [`StadtX` hash](https://github.com/demerphq/BeagleHash) port from [dgryski/go-stadtx](https://github.com/dgryski/go-stadtx).

examples/fnv1a/README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
# fnv1a
2+
3+
[FNV-1a](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash) in `avo`.
4+
5+
[embedmd]:# (asm.go /const/ $)
6+
```go
7+
const (
8+
OffsetBasis = 0xcbf29ce484222325
9+
Prime = 0x100000001b3
10+
)
11+
12+
func main() {
13+
TEXT("Hash64", "func(data []byte) uint64")
14+
Doc("Hash64 computes the FNV-1a hash of data.")
15+
ptr := Load(Param("data").Base(), GP64v())
16+
n := Load(Param("data").Len(), GP64v())
17+
18+
h := reg.RAX
19+
MOVQ(operand.Imm(OffsetBasis), h)
20+
p := GP64v()
21+
MOVQ(operand.Imm(Prime), p)
22+
23+
LABEL("loop")
24+
CMPQ(n, operand.Imm(0))
25+
JE(operand.LabelRef("done"))
26+
b := GP64v()
27+
MOVBQZX(operand.Mem{Base: ptr}, b)
28+
XORQ(b, h)
29+
MULQ(p)
30+
INCQ(ptr)
31+
DECQ(n)
32+
33+
JMP(operand.LabelRef("loop"))
34+
LABEL("done")
35+
Store(h, ReturnIndex(0))
36+
RET()
37+
Generate()
38+
}
39+
```

examples/geohash/README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# geohash
2+
3+
Integer [geohash](https://en.wikipedia.org/wiki/Geohash) encoding.
4+
5+
Refer to ["Geohash in Golang Assembly"](https://mmcloughlin.com/posts/geohash-assembly) for implementation details.
6+
7+
[embedmd]:# (asm.go /func main/ $)
8+
```go
9+
func main() {
10+
TEXT("EncodeInt", "func(lat, lng float64) uint64")
11+
Doc("EncodeInt computes the 64-bit integer geohash of (lat, lng).")
12+
lat := Load(Param("lat"), Xv())
13+
lng := Load(Param("lng"), Xv())
14+
15+
MULSD(ConstData("reciprocal180", F64(1/180.0)), lat)
16+
onepointfive := ConstData("onepointfive", F64(1.5))
17+
ADDSD(onepointfive, lat)
18+
19+
MULSD(ConstData("reciprocal360", F64(1/360.0)), lng)
20+
ADDSD(onepointfive, lng)
21+
22+
lngi, lati := GP64v(), GP64v()
23+
MOVQ(lat, lati)
24+
SHRQ(U8(20), lati)
25+
MOVQ(lng, lngi)
26+
SHRQ(U8(20), lngi)
27+
28+
mask := ConstData("mask", U64(0x5555555555555555))
29+
ghsh := GP64v()
30+
PDEPQ(mask, lati, ghsh)
31+
temp := GP64v()
32+
PDEPQ(mask, lngi, temp)
33+
SHLQ(U8(1), temp)
34+
XORQ(temp, ghsh)
35+
36+
Store(ghsh, ReturnIndex(0))
37+
RET()
38+
39+
Generate()
40+
}
41+
```

examples/sha1/README.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# sha1
2+
3+
[SHA-1](https://en.wikipedia.org/wiki/SHA-1) in `avo`.
4+
5+
Compare to the [`crypto/sha1`](https://github.com/golang/go/blob/204a8f55dc2e0ac8d27a781dab0da609b98560da/src/crypto/sha1/sha1block_amd64.s#L16-L225) assembly.
6+
7+
[embedmd]:# (asm.go /func main/ /^}/)
8+
```go
9+
func main() {
10+
TEXT("block", "func(h *[5]uint32, m []byte)")
11+
Doc("block SHA-1 hashes the 64-byte message m into the running state h.")
12+
h := Mem{Base: Load(Param("h"), GP64v())}
13+
m := Mem{Base: Load(Param("m").Base(), GP64v())}
14+
15+
// Store message values on the stack.
16+
w := AllocLocal(64)
17+
W := func(r int) Mem { return w.Offset((r % 16) * 4) }
18+
19+
// Load initial hash.
20+
h0, h1, h2, h3, h4 := GP32v(), GP32v(), GP32v(), GP32v(), GP32v()
21+
22+
MOVL(h.Offset(0), h0)
23+
MOVL(h.Offset(4), h1)
24+
MOVL(h.Offset(8), h2)
25+
MOVL(h.Offset(12), h3)
26+
MOVL(h.Offset(16), h4)
27+
28+
// Initialize registers.
29+
a, b, c, d, e := GP32v(), GP32v(), GP32v(), GP32v(), GP32v()
30+
31+
MOVL(h0, a)
32+
MOVL(h1, b)
33+
MOVL(h2, c)
34+
MOVL(h3, d)
35+
MOVL(h4, e)
36+
37+
// Generate round updates.
38+
quarter := []struct {
39+
F func(Register, Register, Register) Register
40+
K uint32
41+
}{
42+
{choose, 0x5a827999},
43+
{xor, 0x6ed9eba1},
44+
{majority, 0x8f1bbcdc},
45+
{xor, 0xca62c1d6},
46+
}
47+
48+
for r := 0; r < 80; r++ {
49+
q := quarter[r/20]
50+
51+
// Load message value.
52+
u := GP32v()
53+
if r < 16 {
54+
MOVL(m.Offset(4*r), u)
55+
BSWAPL(u)
56+
} else {
57+
MOVL(W(r-3), u)
58+
XORL(W(r-8), u)
59+
XORL(W(r-14), u)
60+
XORL(W(r-16), u)
61+
ROLL(U8(1), u)
62+
}
63+
MOVL(u, W(r))
64+
65+
// Compute the next state register.
66+
t := GP32v()
67+
MOVL(a, t)
68+
ROLL(U8(5), t)
69+
ADDL(q.F(b, c, d), t)
70+
ADDL(e, t)
71+
ADDL(U32(q.K), t)
72+
ADDL(u, t)
73+
74+
// Update registers.
75+
ROLL(Imm(30), b)
76+
a, b, c, d, e = t, a, b, c, d
77+
}
78+
79+
// Final add.
80+
ADDL(a, h0)
81+
ADDL(b, h1)
82+
ADDL(c, h2)
83+
ADDL(d, h3)
84+
ADDL(e, h4)
85+
86+
// Store results back.
87+
MOVL(h0, h.Offset(0))
88+
MOVL(h1, h.Offset(4))
89+
MOVL(h2, h.Offset(8))
90+
MOVL(h3, h.Offset(12))
91+
MOVL(h4, h.Offset(16))
92+
RET()
93+
94+
Generate()
95+
}
96+
```

0 commit comments

Comments
 (0)