examples/sha1: single block
This commit is contained in:
19
ast.go
19
ast.go
@@ -10,15 +10,6 @@ type Asm interface {
|
|||||||
Asm() string
|
Asm() string
|
||||||
}
|
}
|
||||||
|
|
||||||
// GoType represents a Golang type.
|
|
||||||
type GoType interface{}
|
|
||||||
|
|
||||||
// Parameter represents a parameter to an assembly function.
|
|
||||||
type Parameter struct {
|
|
||||||
Name string
|
|
||||||
Type GoType
|
|
||||||
}
|
|
||||||
|
|
||||||
type Operand interface {
|
type Operand interface {
|
||||||
Asm
|
Asm
|
||||||
}
|
}
|
||||||
@@ -112,6 +103,7 @@ func NewFile() *File {
|
|||||||
type Function struct {
|
type Function struct {
|
||||||
Name string
|
Name string
|
||||||
Signature *gotypes.Signature
|
Signature *gotypes.Signature
|
||||||
|
LocalSize int
|
||||||
|
|
||||||
Nodes []Node
|
Nodes []Node
|
||||||
|
|
||||||
@@ -133,6 +125,12 @@ func (f *Function) SetSignature(s *gotypes.Signature) {
|
|||||||
f.Signature = s
|
f.Signature = s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *Function) AllocLocal(size int) operand.Mem {
|
||||||
|
ptr := operand.NewStackAddr(f.LocalSize)
|
||||||
|
f.LocalSize += size
|
||||||
|
return ptr
|
||||||
|
}
|
||||||
|
|
||||||
func (f *Function) AddInstruction(i *Instruction) {
|
func (f *Function) AddInstruction(i *Instruction) {
|
||||||
f.AddNode(i)
|
f.AddNode(i)
|
||||||
}
|
}
|
||||||
@@ -164,8 +162,7 @@ func (f *Function) Stub() string {
|
|||||||
|
|
||||||
// FrameBytes returns the size of the stack frame in bytes.
|
// FrameBytes returns the size of the stack frame in bytes.
|
||||||
func (f *Function) FrameBytes() int {
|
func (f *Function) FrameBytes() int {
|
||||||
// TODO(mbm): implement Function.FrameBytes()
|
return f.LocalSize
|
||||||
return 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ArgumentBytes returns the size of the arguments in bytes.
|
// ArgumentBytes returns the size of the arguments in bytes.
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
"github.com/mmcloughlin/avo"
|
"github.com/mmcloughlin/avo"
|
||||||
"github.com/mmcloughlin/avo/gotypes"
|
"github.com/mmcloughlin/avo/gotypes"
|
||||||
|
"github.com/mmcloughlin/avo/operand"
|
||||||
"github.com/mmcloughlin/avo/reg"
|
"github.com/mmcloughlin/avo/reg"
|
||||||
"golang.org/x/tools/go/packages"
|
"golang.org/x/tools/go/packages"
|
||||||
)
|
)
|
||||||
@@ -69,6 +70,10 @@ func (c *Context) types() *types.Package {
|
|||||||
return c.pkg.Types
|
return c.pkg.Types
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Context) AllocLocal(size int) operand.Mem {
|
||||||
|
return c.activefunc().AllocLocal(size)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Context) Instruction(i *avo.Instruction) {
|
func (c *Context) Instruction(i *avo.Instruction) {
|
||||||
c.activefunc().AddNode(i)
|
c.activefunc().AddNode(i)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/mmcloughlin/avo/gotypes"
|
"github.com/mmcloughlin/avo/gotypes"
|
||||||
|
"github.com/mmcloughlin/avo/operand"
|
||||||
|
|
||||||
"github.com/mmcloughlin/avo/reg"
|
"github.com/mmcloughlin/avo/reg"
|
||||||
|
|
||||||
@@ -47,3 +48,5 @@ func ReturnIndex(i int) gotypes.Component { return ctx.ReturnIndex(i) }
|
|||||||
|
|
||||||
func Load(src gotypes.Component, dst reg.Register) reg.Register { return ctx.Load(src, dst) }
|
func Load(src gotypes.Component, dst reg.Register) reg.Register { return ctx.Load(src, dst) }
|
||||||
func Store(src reg.Register, dst gotypes.Component) { ctx.Store(src, dst) }
|
func Store(src reg.Register, dst gotypes.Component) { ctx.Store(src, dst) }
|
||||||
|
|
||||||
|
func AllocLocal(size int) operand.Mem { return ctx.AllocLocal(size) }
|
||||||
|
|||||||
124
examples/sha1/asm.go
Normal file
124
examples/sha1/asm.go
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
// +build ignore
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "github.com/mmcloughlin/avo/build"
|
||||||
|
. "github.com/mmcloughlin/avo/operand"
|
||||||
|
"github.com/mmcloughlin/avo/reg"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
TEXT("block", "func(h *[5]uint32, m []byte)")
|
||||||
|
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.Idx((r % 16) * 4) }
|
||||||
|
|
||||||
|
// Load initial hash.
|
||||||
|
h0, h1, h2, h3, h4 := GP32v(), GP32v(), GP32v(), GP32v(), GP32v()
|
||||||
|
|
||||||
|
MOVL(h.Idx(0), h0)
|
||||||
|
MOVL(h.Idx(4), h1)
|
||||||
|
MOVL(h.Idx(8), h2)
|
||||||
|
MOVL(h.Idx(12), h3)
|
||||||
|
MOVL(h.Idx(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(reg.Register, reg.Register, reg.Register) reg.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.Idx(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(Imm(1), u)
|
||||||
|
}
|
||||||
|
MOVL(u, W(r))
|
||||||
|
|
||||||
|
// Compute the next state register.
|
||||||
|
t := GP32v()
|
||||||
|
MOVL(a, t)
|
||||||
|
ROLL(Imm(5), t)
|
||||||
|
ADDL(q.F(b, c, d), t)
|
||||||
|
ADDL(e, t)
|
||||||
|
ADDL(Imm(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.Idx(0))
|
||||||
|
MOVL(h1, h.Idx(4))
|
||||||
|
MOVL(h2, h.Idx(8))
|
||||||
|
MOVL(h3, h.Idx(12))
|
||||||
|
MOVL(h4, h.Idx(16))
|
||||||
|
RET()
|
||||||
|
|
||||||
|
Generate()
|
||||||
|
}
|
||||||
|
|
||||||
|
func choose(b, c, d reg.Register) reg.Register {
|
||||||
|
r := GP32v()
|
||||||
|
MOVL(d, r)
|
||||||
|
XORL(c, r)
|
||||||
|
ANDL(b, r)
|
||||||
|
XORL(d, r)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func xor(b, c, d reg.Register) reg.Register {
|
||||||
|
r := GP32v()
|
||||||
|
MOVL(b, r)
|
||||||
|
XORL(c, r)
|
||||||
|
XORL(d, r)
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
func majority(b, c, d reg.Register) reg.Register {
|
||||||
|
t, r := GP32v(), GP32v()
|
||||||
|
MOVL(b, t)
|
||||||
|
ORL(c, t)
|
||||||
|
ANDL(d, t)
|
||||||
|
MOVL(b, r)
|
||||||
|
ANDL(c, r)
|
||||||
|
ORL(t, r)
|
||||||
|
return r
|
||||||
|
}
|
||||||
1341
examples/sha1/sha1.s
Normal file
1341
examples/sha1/sha1.s
Normal file
File diff suppressed because it is too large
Load Diff
26
examples/sha1/sha1_test.go
Normal file
26
examples/sha1/sha1_test.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
package sha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate go run asm.go -out sha1.s -stubs stub.go
|
||||||
|
|
||||||
|
func TestEmptyString(t *testing.T) {
|
||||||
|
h := [...]uint32{0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0}
|
||||||
|
m := make([]byte, 64)
|
||||||
|
m[0] = 0x80
|
||||||
|
|
||||||
|
block(&h, m)
|
||||||
|
|
||||||
|
expect := [...]uint32{0xda39a3ee, 0x5e6b4b0d, 0x3255bfef, 0x95601890, 0xafd80709}
|
||||||
|
|
||||||
|
for i := 0; i < 5; i++ {
|
||||||
|
log.Printf("h[%d] = %08x", i, h[i])
|
||||||
|
}
|
||||||
|
if !reflect.DeepEqual(expect, h) {
|
||||||
|
t.Fatal("incorrect hash")
|
||||||
|
}
|
||||||
|
}
|
||||||
5
examples/sha1/stub.go
Normal file
5
examples/sha1/stub.go
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
// Code generated by command: go run asm.go -out sha1.s -stubs stub.go. DO NOT EDIT.
|
||||||
|
|
||||||
|
package sha1
|
||||||
|
|
||||||
|
func block(h *[5]uint32, m []byte)
|
||||||
@@ -44,6 +44,19 @@ func NewParamAddr(name string, offset int) Mem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewStackAddr(offset int) Mem {
|
||||||
|
return Mem{
|
||||||
|
Disp: offset,
|
||||||
|
Base: reg.StackPointer,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Mem) Idx(idx int) Mem {
|
||||||
|
a := m
|
||||||
|
a.Disp += idx
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
func (m Mem) Asm() string {
|
func (m Mem) Asm() string {
|
||||||
a := m.Symbol.String()
|
a := m.Symbol.String()
|
||||||
if m.Disp != 0 {
|
if m.Disp != 0 {
|
||||||
|
|||||||
Reference in New Issue
Block a user