From 0a3dff4d5aeb2ff4477dd56578218be728d13b58 Mon Sep 17 00:00:00 2001 From: Michael McLoughlin Date: Mon, 7 Jan 2019 22:21:16 -0800 Subject: [PATCH] doc: link to examples instead (#13) --- README.md | 143 ++++-------------------------------------------------- 1 file changed, 9 insertions(+), 134 deletions(-) diff --git a/README.md b/README.md index 0aea9b6..4f68764 100644 --- a/README.md +++ b/README.md @@ -154,145 +154,20 @@ done: Full example at [`examples/sum`](examples/sum). -### Parameter Load/Store +### Features -`avo` provides deconstruction of complex data datatypes into components. For example, load the length of a string argument with: +For demonstrations of `avo` features: -[embedmd]:# (examples/args/asm.go go /.*TEXT.*StringLen/ /Load.*/) -```go - TEXT("StringLen", NOSPLIT, "func(s string) int") - strlen := Load(Param("s").Len(), GP64()) -``` - -Index an array: - -[embedmd]:# (examples/args/asm.go go /.*TEXT.*ArrayThree/ /Load.*/) -```go - TEXT("ArrayThree", NOSPLIT, "func(a [7]uint64) uint64") - a3 := Load(Param("a").Index(3), GP64()) -``` - -Access a struct field (provided you have loaded your package with the `Package` function): - -[embedmd]:# (examples/args/asm.go go /.*TEXT.*FieldFloat64/ /Load.*/) -```go - TEXT("FieldFloat64", NOSPLIT, "func(s Struct) float64") - f64 := Load(Param("s").Field("Float64"), XMM()) -``` - -Component accesses can be arbitrarily nested: - -[embedmd]:# (examples/args/asm.go go /.*TEXT.*FieldArrayTwoBTwo/ /Load.*/) -```go - TEXT("FieldArrayTwoBTwo", NOSPLIT, "func(s Struct) byte") - b2 := Load(Param("s").Field("Array").Index(2).Field("B").Index(2), GP8()) -``` - -Very similar techniques apply to writing return values. See [`examples/args`](examples/args) and [`examples/returns`](examples/returns) for more. - -### SHA-1 - -[SHA-1](https://en.wikipedia.org/wiki/SHA-1) is an excellent example of how powerful this kind of technique can be. The following is a (hopefully) clearly structured implementation of SHA-1 in `avo`, which ultimately generates a [1000+ line impenetrable assembly file](examples/sha1/sha1.s). - -[embedmd]:# (examples/sha1/asm.go /func main/ /^}/) -```go -func main() { - TEXT("block", 0, "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"), GP64())} - m := Mem{Base: Load(Param("m").Base(), GP64())} - - // Store message values on the stack. - w := AllocLocal(64) - W := func(r int) Mem { return w.Offset((r % 16) * 4) } - - // Load initial hash. - hash := [5]Register{GP32(), GP32(), GP32(), GP32(), GP32()} - for i, r := range hash { - MOVL(h.Offset(4*i), r) - } - - // Initialize registers. - a, b, c, d, e := GP32(), GP32(), GP32(), GP32(), GP32() - for i, r := range []Register{a, b, c, d, e} { - MOVL(hash[i], r) - } - - // 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 := GP32() - 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 := GP32() - 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. - for i, r := range []Register{a, b, c, d, e} { - ADDL(r, hash[i]) - } - - // Store results back. - for i, r := range hash { - MOVL(r, h.Offset(4*i)) - } - RET() - - Generate() -} -``` - -This relies on the bitwise functions that are defined as subroutines. For example here is bitwise `choose`; the others are similar. - -[embedmd]:# (examples/sha1/asm.go /func choose/ /^}/) -```go -func choose(b, c, d Register) Register { - r := GP32() - MOVL(d, r) - XORL(c, r) - ANDL(b, r) - XORL(d, r) - return r -} -``` - -See the complete code at [`examples/sha1`](examples/sha1). +* **[args](examples/args):** Loading function arguments. +* **[returns](examples/returns):** Building return values. +* **[data](examples/data):** Defining `DATA` sections. +* **[complex](examples/complex):** Working with `complex{64,128}` types. ### Real Examples +Implementations of full algorithms: + +* **[sha1](examples/sha1):** [SHA-1](https://en.wikipedia.org/wiki/SHA-1) cryptographic hash. * **[fnv1a](examples/fnv1a):** [FNV-1a](https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function#FNV-1a_hash) hash function. * **[dot](examples/dot):** Vector dot product. * **[geohash](examples/geohash):** Integer [geohash](https://en.wikipedia.org/wiki/Geohash) encoding.