Skip to content

Commit

Permalink
amd64 finalizer
Browse files Browse the repository at this point in the history
  • Loading branch information
philhofer committed Sep 11, 2015
1 parent 3ed1405 commit bcb5cb3
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 90 deletions.
90 changes: 90 additions & 0 deletions blocks.go
Expand Up @@ -2,6 +2,96 @@

package siphash

func once(d *digest) {
blocks(d, d.x[:])
}

func finalize(d *digest) uint64 {
d0 := *d
once(&d0)

v0, v1, v2, v3 := d0.v0, d0.v1, d0.v2, d0.v3
v2 ^= 0xff

// Round 1.
v0 += v1
v1 = v1<<13 | v1>>(64-13)
v1 ^= v0
v0 = v0<<32 | v0>>(64-32)

v2 += v3
v3 = v3<<16 | v3>>(64-16)
v3 ^= v2

v0 += v3
v3 = v3<<21 | v3>>(64-21)
v3 ^= v0

v2 += v1
v1 = v1<<17 | v1>>(64-17)
v1 ^= v2
v2 = v2<<32 | v2>>(64-32)

// Round 2.
v0 += v1
v1 = v1<<13 | v1>>(64-13)
v1 ^= v0
v0 = v0<<32 | v0>>(64-32)

v2 += v3
v3 = v3<<16 | v3>>(64-16)
v3 ^= v2

v0 += v3
v3 = v3<<21 | v3>>(64-21)
v3 ^= v0

v2 += v1
v1 = v1<<17 | v1>>(64-17)
v1 ^= v2
v2 = v2<<32 | v2>>(64-32)

// Round 3.
v0 += v1
v1 = v1<<13 | v1>>(64-13)
v1 ^= v0
v0 = v0<<32 | v0>>(64-32)

v2 += v3
v3 = v3<<16 | v3>>(64-16)
v3 ^= v2

v0 += v3
v3 = v3<<21 | v3>>(64-21)
v3 ^= v0

v2 += v1
v1 = v1<<17 | v1>>(64-17)
v1 ^= v2
v2 = v2<<32 | v2>>(64-32)

// Round 4.
v0 += v1
v1 = v1<<13 | v1>>(64-13)
v1 ^= v0
v0 = v0<<32 | v0>>(64-32)

v2 += v3
v3 = v3<<16 | v3>>(64-16)
v3 ^= v2

v0 += v3
v3 = v3<<21 | v3>>(64-21)
v3 ^= v0

v2 += v1
v1 = v1<<17 | v1>>(64-17)
v1 ^= v2
v2 = v2<<32 | v2>>(64-32)

return v0 ^ v1 ^ v2 ^ v3
}

func blocks(d *digest, p []uint8) {
v0, v1, v2, v3 := d.v0, d.v1, d.v2, d.v3

Expand Down
42 changes: 42 additions & 0 deletions blocks_amd64.s
Expand Up @@ -43,3 +43,45 @@ end:
MOVQ R11, 16(BX)
MOVQ R12, 24(BX)
RET

// once(d *digest)
TEXT ·once(SB),4,$0-8
MOVQ d+0(FP), BX
MOVQ 0(BX), R9 // R9 = v0
MOVQ 8(BX), R10 // R10 = v1
MOVQ 16(BX), R11 // R11 = v2
MOVQ 24(BX), R12 // R12 = v3
MOVQ 48(BX), CX // CX = d.x[:]
XORQ CX, R12
ROUND(R9, R10, R11, R12)
ROUND(R9, R10, R11, R12)
XORQ CX, R9
MOVQ R9, 0(BX)
MOVQ R10, 8(BX)
MOVQ R11, 16(BX)
MOVQ R12, 24(BX)
RET

// finalize(d *digest) uint64
TEXT ·finalize(SB),4,$0-16
MOVQ d+0(FP), BX
MOVQ 0(BX), R9 // R9 = v0
MOVQ 8(BX), R10 // R10 = v1
MOVQ 16(BX), R11 // R11 = v2
MOVQ 24(BX), R12 // R12 = v3
MOVQ 48(BX), CX // CX = d.x[:]
XORQ CX, R12
ROUND(R9, R10, R11, R12)
ROUND(R9, R10, R11, R12)
XORQ CX, R9
NOTB R11
ROUND(R9, R10, R11, R12)
ROUND(R9, R10, R11, R12)
ROUND(R9, R10, R11, R12)
ROUND(R9, R10, R11, R12)
XORQ R12, R11
XORQ R10, R9
XORQ R11, R9
MOVQ R9, ret+8(FP)
RET

2 changes: 1 addition & 1 deletion hash_amd64.s
@@ -1,7 +1,7 @@
// +build amd64,!appengine,!gccgo

// This is a translation of the gcc output of FloodyBerry's pure-C public
// domain siphash implementation at https://github.com/floodyberry/siphash
// domain siphash implementation at https://github.com/floodyberry/siphash
// func Hash(k0, k1 uint64, b []byte) uint64
TEXT ·Hash(SB),4,$0-48
MOVQ k0+0(FP),CX
Expand Down
6 changes: 6 additions & 0 deletions hash_asm.go
Expand Up @@ -25,3 +25,9 @@ func Hash128(k0, k1 uint64, b []byte) (uint64, uint64)

//go:noescape
func blocks(d *digest, p []uint8)

//go:noescape
func finalize(d *digest) uint64

//go:noescape
func once(d *digest)
94 changes: 5 additions & 89 deletions siphash.go
Expand Up @@ -25,10 +25,10 @@ const (
type digest struct {
v0, v1, v2, v3 uint64 // state
k0, k1 uint64 // two parts of key
t uint8 // message bytes counter (mod 256)
nx int // number of bytes in buffer x
x [8]byte // buffer for unprocessed bytes
nx int // number of bytes in buffer x
size int // output size in bytes (8 or 16)
t uint8 // message bytes counter (mod 256)
}

// newDigest returns a new digest with the given output size in bytes (must be 8 or 16).
Expand Down Expand Up @@ -84,7 +84,7 @@ func (d *digest) Write(p []byte) (nn int, err error) {
}
d.nx += copy(d.x[d.nx:], p)
if d.nx == BlockSize {
blocks(d, d.x[:])
once(d)
d.nx = 0
}
p = p[n:]
Expand All @@ -100,96 +100,12 @@ func (d *digest) Write(p []byte) (nn int, err error) {
return
}

func (d0 *digest) Sum64() uint64 {
// Make a copy of d0 so that caller can keep writing and summing.
d := *d0

func (d *digest) Sum64() uint64 {
for i := d.nx; i < BlockSize-1; i++ {
d.x[i] = 0
}
d.x[7] = d.t
blocks(&d, d.x[:])

v0, v1, v2, v3 := d.v0, d.v1, d.v2, d.v3
v2 ^= 0xff

// Round 1.
v0 += v1
v1 = v1<<13 | v1>>(64-13)
v1 ^= v0
v0 = v0<<32 | v0>>(64-32)

v2 += v3
v3 = v3<<16 | v3>>(64-16)
v3 ^= v2

v0 += v3
v3 = v3<<21 | v3>>(64-21)
v3 ^= v0

v2 += v1
v1 = v1<<17 | v1>>(64-17)
v1 ^= v2
v2 = v2<<32 | v2>>(64-32)

// Round 2.
v0 += v1
v1 = v1<<13 | v1>>(64-13)
v1 ^= v0
v0 = v0<<32 | v0>>(64-32)

v2 += v3
v3 = v3<<16 | v3>>(64-16)
v3 ^= v2

v0 += v3
v3 = v3<<21 | v3>>(64-21)
v3 ^= v0

v2 += v1
v1 = v1<<17 | v1>>(64-17)
v1 ^= v2
v2 = v2<<32 | v2>>(64-32)

// Round 3.
v0 += v1
v1 = v1<<13 | v1>>(64-13)
v1 ^= v0
v0 = v0<<32 | v0>>(64-32)

v2 += v3
v3 = v3<<16 | v3>>(64-16)
v3 ^= v2

v0 += v3
v3 = v3<<21 | v3>>(64-21)
v3 ^= v0

v2 += v1
v1 = v1<<17 | v1>>(64-17)
v1 ^= v2
v2 = v2<<32 | v2>>(64-32)

// Round 4.
v0 += v1
v1 = v1<<13 | v1>>(64-13)
v1 ^= v0
v0 = v0<<32 | v0>>(64-32)

v2 += v3
v3 = v3<<16 | v3>>(64-16)
v3 ^= v2

v0 += v3
v3 = v3<<21 | v3>>(64-21)
v3 ^= v0

v2 += v1
v1 = v1<<17 | v1>>(64-17)
v1 ^= v2
v2 = v2<<32 | v2>>(64-32)

return v0 ^ v1 ^ v2 ^ v3
return finalize(d)
}

func (d0 *digest) sum128() (r0, r1 uint64) {
Expand Down

0 comments on commit bcb5cb3

Please sign in to comment.