]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/sha512: add s390x assembly implementation
authorMichael Munday <munday@ca.ibm.com>
Mon, 25 Apr 2016 20:17:42 +0000 (16:17 -0400)
committerMichael Munday <munday@ca.ibm.com>
Tue, 26 Apr 2016 17:37:45 +0000 (17:37 +0000)
Renames block to blockGeneric so that it can be called when the
assembly feature check fails. This means making block a var on
platforms without an assembly implementation (similar to the sha1
package).

Also adds a test to check that the fallback path works correctly
when the feature check fails.

name        old speed      new speed       delta
Hash8Bytes  7.13MB/s ± 2%  19.89MB/s ± 1%  +178.82%   (p=0.000 n=9+10)
Hash1K       121MB/s ± 1%    661MB/s ± 1%  +444.54%   (p=0.000 n=10+9)
Hash8K       137MB/s ± 0%    918MB/s ± 1%  +569.29%  (p=0.000 n=10+10)

Change-Id: Id65dd6e943f14eeffe39a904dc88065fc6a60179
Reviewed-on: https://go-review.googlesource.com/22402
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Michael Munday <munday@ca.ibm.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/crypto/sha512/fallback_test.go [new file with mode: 0644]
src/crypto/sha512/sha512_test.go
src/crypto/sha512/sha512block.go
src/crypto/sha512/sha512block_decl.go
src/crypto/sha512/sha512block_generic.go [new file with mode: 0644]
src/crypto/sha512/sha512block_s390x.go [new file with mode: 0644]
src/crypto/sha512/sha512block_s390x.s [new file with mode: 0644]

diff --git a/src/crypto/sha512/fallback_test.go b/src/crypto/sha512/fallback_test.go
new file mode 100644 (file)
index 0000000..9024ce6
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build s390x
+
+package sha512
+
+import (
+       "fmt"
+       "io"
+       "testing"
+)
+
+// Tests the fallback code path in case the optimized asm
+// implementation cannot be used.
+// See also TestBlockGeneric.
+func TestGenericPath(t *testing.T) {
+       if useAsm == false {
+               t.Skipf("assembly implementation unavailable")
+       }
+       useAsm = false
+       defer func() { useAsm = true }()
+       c := New()
+       in := "ΑΒΓΔΕϜΖΗΘΙΚΛΜΝΞΟΠϺϘΡΣΤΥΦΧΨΩ"
+       gold := "6922e319366d677f34c504af31bfcb29" +
+               "e531c125ecd08679362bffbd6b6ebfb9" +
+               "0dcc27dfc1f3d3b16a16c0763cf43b91" +
+               "40bbf9bbb7233724e9a0c6655b185d76"
+       if _, err := io.WriteString(c, in); err != nil {
+               t.Fatalf("could not write to c: %v", err)
+       }
+       out := fmt.Sprintf("%x", c.Sum(nil))
+       if out != gold {
+               t.Fatalf("mismatch: got %s, wanted %s", out, gold)
+       }
+}
index 6992d125de4bb7d911f9aecbe62997c18873acbd..a3a136a19f820c48833b2164b1f2ece6495884e9 100644 (file)
@@ -7,6 +7,7 @@
 package sha512
 
 import (
+       "crypto/rand"
        "encoding/hex"
        "hash"
        "io"
@@ -304,6 +305,18 @@ func TestBlockSize(t *testing.T) {
        }
 }
 
+// Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match.
+func TestBlockGeneric(t *testing.T) {
+       gen, asm := New().(*digest), New().(*digest)
+       buf := make([]byte, BlockSize*20) // arbitrary factor
+       rand.Read(buf)
+       blockGeneric(gen, buf)
+       block(asm, buf)
+       if *gen != *asm {
+               t.Error("block and blockGeneric resulted in different states")
+       }
+}
+
 var bench = New()
 var buf = make([]byte, 8192)
 
index 648ae8f7e1f436de807b348f3a23e9ff3b86534d..42e8d19fe8c850c87e9dbb78facf7c292acab8c6 100644 (file)
@@ -2,8 +2,6 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build !amd64
-
 // SHA512 block step.
 // In its own file so that a faster assembly or C version
 // can be substituted easily.
@@ -93,7 +91,7 @@ var _K = []uint64{
        0x6c44198c4a475817,
 }
 
-func block(dig *digest, p []byte) {
+func blockGeneric(dig *digest, p []byte) {
        var w [80]uint64
        h0, h1, h2, h3, h4, h5, h6, h7 := dig.h[0], dig.h[1], dig.h[2], dig.h[3], dig.h[4], dig.h[5], dig.h[6], dig.h[7]
        for len(p) >= chunk {
index 80341537791de26ee804c0ca9c612b3d564f265e..47d656a7e4a1aaaae78c358037babd770ab4074f 100644 (file)
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-// +build amd64
+// +build amd64 s390x
 
 package sha512
 
diff --git a/src/crypto/sha512/sha512block_generic.go b/src/crypto/sha512/sha512block_generic.go
new file mode 100644 (file)
index 0000000..2c691ba
--- /dev/null
@@ -0,0 +1,9 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build !amd64,!s390x
+
+package sha512
+
+var block = blockGeneric
diff --git a/src/crypto/sha512/sha512block_s390x.go b/src/crypto/sha512/sha512block_s390x.go
new file mode 100644 (file)
index 0000000..f05dc18
--- /dev/null
@@ -0,0 +1,12 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package sha512
+
+// featureCheck reports whether the CPU supports the
+// SHA512 compute intermediate message digest (KIMD)
+// function code.
+func featureCheck() bool
+
+var useAsm = featureCheck()
diff --git a/src/crypto/sha512/sha512block_s390x.s b/src/crypto/sha512/sha512block_s390x.s
new file mode 100644 (file)
index 0000000..aab81e2
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "textflag.h"
+
+// func featureCheck() bool
+TEXT ·featureCheck(SB),NOSPLIT,$16-1
+       LA      tmp-16(SP), R1
+       XOR     R0, R0         // query function code is 0
+       WORD    $0xB93E0006    // KIMD (R6 is ignored)
+       MOVBZ   tmp-16(SP), R4 // get the first byte
+       AND     $0x10, R4      // bit 3 (big endian) for SHA512
+       CMPBEQ  R4, $0, nosha512
+       MOVB    $1, ret+0(FP)
+       RET
+nosha512:
+       MOVB    $0, ret+0(FP)
+       RET
+
+// func block(dig *digest, p []byte)
+TEXT ·block(SB),NOSPLIT,$0-32
+       MOVBZ   ·useAsm(SB), R4
+       LMG     dig+0(FP), R1, R3 // R2 = &p[0], R3 = len(p)
+       CMPBNE  R4, $1, generic
+       MOVBZ   $3, R0        // SHA512 function code
+loop:
+       WORD    $0xB93E0002   // KIMD R2
+       BVS     loop          // continue if interrupted
+done:
+       XOR     R0, R0        // restore R0
+       RET
+generic:
+       BR      ·blockGeneric(SB)