Skip to content

Commit

Permalink
doc: READMEs for remaining "real world" examples
Browse files Browse the repository at this point in the history
  • Loading branch information
mmcloughlin committed Jan 2, 2019
1 parent 85a7299 commit 0eb66fe
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 0 deletions.
8 changes: 8 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,11 @@ Features:
* **[returns](returns):** Building return values.
* **[complex](complex):** Working with `complex{64,128}` types.
* **[data](data):** Defining `DATA` sections.

"Real" examples:

* **[fnv1a](fnv1a):** [FNV-1a](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash) hash function.
* **[dot](dot):** Vector dot product.
* **[geohash](geohash):** Integer [geohash](https://en.wikipedia.org/wiki/Geohash) encoding.
* **[sha1](sha1):** [SHA-1](https://en.wikipedia.org/wiki/SHA-1) cryptographic hash.
* **[stadtx](stadtx):** [`StadtX` hash](https://github.com/demerphq/BeagleHash) port from [dgryski/go-stadtx](https://github.com/dgryski/go-stadtx).
39 changes: 39 additions & 0 deletions examples/fnv1a/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# fnv1a

[FNV-1a](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash) in `avo`.

[embedmd]:# (asm.go /const/ $)
```go
const (
OffsetBasis = 0xcbf29ce484222325
Prime = 0x100000001b3
)

func main() {
TEXT("Hash64", "func(data []byte) uint64")
Doc("Hash64 computes the FNV-1a hash of data.")
ptr := Load(Param("data").Base(), GP64v())
n := Load(Param("data").Len(), GP64v())

h := reg.RAX
MOVQ(operand.Imm(OffsetBasis), h)
p := GP64v()
MOVQ(operand.Imm(Prime), p)

LABEL("loop")
CMPQ(n, operand.Imm(0))
JE(operand.LabelRef("done"))
b := GP64v()
MOVBQZX(operand.Mem{Base: ptr}, b)
XORQ(b, h)
MULQ(p)
INCQ(ptr)
DECQ(n)

JMP(operand.LabelRef("loop"))
LABEL("done")
Store(h, ReturnIndex(0))
RET()
Generate()
}
```
41 changes: 41 additions & 0 deletions examples/geohash/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# geohash

Integer [geohash](https://en.wikipedia.org/wiki/Geohash) encoding.

Refer to ["Geohash in Golang Assembly"](https://mmcloughlin.com/posts/geohash-assembly) for implementation details.

[embedmd]:# (asm.go /func main/ $)
```go
func main() {
TEXT("EncodeInt", "func(lat, lng float64) uint64")
Doc("EncodeInt computes the 64-bit integer geohash of (lat, lng).")
lat := Load(Param("lat"), Xv())
lng := Load(Param("lng"), Xv())

MULSD(ConstData("reciprocal180", F64(1/180.0)), lat)
onepointfive := ConstData("onepointfive", F64(1.5))
ADDSD(onepointfive, lat)

MULSD(ConstData("reciprocal360", F64(1/360.0)), lng)
ADDSD(onepointfive, lng)

lngi, lati := GP64v(), GP64v()
MOVQ(lat, lati)
SHRQ(U8(20), lati)
MOVQ(lng, lngi)
SHRQ(U8(20), lngi)

mask := ConstData("mask", U64(0x5555555555555555))
ghsh := GP64v()
PDEPQ(mask, lati, ghsh)
temp := GP64v()
PDEPQ(mask, lngi, temp)
SHLQ(U8(1), temp)
XORQ(temp, ghsh)

Store(ghsh, ReturnIndex(0))
RET()

Generate()
}
```
96 changes: 96 additions & 0 deletions examples/sha1/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# sha1

[SHA-1](https://en.wikipedia.org/wiki/SHA-1) in `avo`.

Compare to the [`crypto/sha1`](https://github.com/golang/go/blob/204a8f55dc2e0ac8d27a781dab0da609b98560da/src/crypto/sha1/sha1block_amd64.s#L16-L225) assembly.

[embedmd]:# (asm.go /func main/ /^}/)
```go
func main() {
TEXT("block", "func(h *[5]uint32, m []byte)")
Doc("block SHA-1 hashes the 64-byte message m into the running state h.")
h := Mem{Base: Load(Param("h"), GP64v())}
m := Mem{Base: Load(Param("m").Base(), GP64v())}

// Store message values on the stack.
w := AllocLocal(64)
W := func(r int) Mem { return w.Offset((r % 16) * 4) }

// Load initial hash.
h0, h1, h2, h3, h4 := GP32v(), GP32v(), GP32v(), GP32v(), GP32v()

MOVL(h.Offset(0), h0)
MOVL(h.Offset(4), h1)
MOVL(h.Offset(8), h2)
MOVL(h.Offset(12), h3)
MOVL(h.Offset(16), h4)

// Initialize registers.
a, b, c, d, e := GP32v(), GP32v(), GP32v(), GP32v(), GP32v()

MOVL(h0, a)
MOVL(h1, b)
MOVL(h2, c)
MOVL(h3, d)
MOVL(h4, e)

// Generate round updates.
quarter := []struct {
F func(Register, Register, Register) Register
K uint32
}{
{choose, 0x5a827999},
{xor, 0x6ed9eba1},
{majority, 0x8f1bbcdc},
{xor, 0xca62c1d6},
}

for r := 0; r < 80; r++ {
q := quarter[r/20]

// Load message value.
u := GP32v()
if r < 16 {
MOVL(m.Offset(4*r), u)
BSWAPL(u)
} else {
MOVL(W(r-3), u)
XORL(W(r-8), u)
XORL(W(r-14), u)
XORL(W(r-16), u)
ROLL(U8(1), u)
}
MOVL(u, W(r))

// Compute the next state register.
t := GP32v()
MOVL(a, t)
ROLL(U8(5), t)
ADDL(q.F(b, c, d), t)
ADDL(e, t)
ADDL(U32(q.K), t)
ADDL(u, t)

// Update registers.
ROLL(Imm(30), b)
a, b, c, d, e = t, a, b, c, d
}

// Final add.
ADDL(a, h0)
ADDL(b, h1)
ADDL(c, h2)
ADDL(d, h3)
ADDL(e, h4)

// Store results back.
MOVL(h0, h.Offset(0))
MOVL(h1, h.Offset(4))
MOVL(h2, h.Offset(8))
MOVL(h3, h.Offset(12))
MOVL(h4, h.Offset(16))
RET()

Generate()
}
```

0 comments on commit 0eb66fe

Please sign in to comment.