Skip to content

Commit 525ae3f

Browse files
mundaymbradfitz
authored andcommitted
crypto/sha256: add s390x assembly implementation
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 6.42MB/s ± 1% 27.14MB/s ± 0% +323.01% (p=0.000 n=10+10) Hash1K 53.9MB/s ± 0% 511.1MB/s ± 0% +847.57% (p=0.000 n=10+9) Hash8K 57.1MB/s ± 1% 609.7MB/s ± 0% +967.04% (p=0.000 n=10+10) Change-Id: If962b2a5c9160b3a0b76ccee53b2fd809468ed3d Reviewed-on: https://go-review.googlesource.com/22460 Run-TryBot: Michael Munday <munday@ca.ibm.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Bill O'Farrell <billotosyr@gmail.com> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
1 parent 2a889b9 commit 525ae3f

File tree

7 files changed

+105
-4
lines changed

7 files changed

+105
-4
lines changed

src/crypto/sha256/fallback_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright 2016 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// +build s390x
6+
7+
package sha256
8+
9+
import (
10+
"fmt"
11+
"io"
12+
"testing"
13+
)
14+
15+
// Tests the fallback code path in case the optimized asm
16+
// implementation cannot be used.
17+
// See also TestBlockGeneric.
18+
func TestGenericPath(t *testing.T) {
19+
if useAsm == false {
20+
t.Skipf("assembly implementation unavailable")
21+
}
22+
useAsm = false
23+
defer func() { useAsm = true }()
24+
c := New()
25+
in := "ΑΒΓΔΕϜΖΗΘΙΚΛΜΝΞΟΠϺϘΡΣΤΥΦΧΨΩ"
26+
gold := "e93d84ec2b22383123be9f713697fb25" +
27+
"338c86e2f7d8d1ddc2d89d332dd9d76c"
28+
if _, err := io.WriteString(c, in); err != nil {
29+
t.Fatalf("could not write to c: %v", err)
30+
}
31+
out := fmt.Sprintf("%x", c.Sum(nil))
32+
if out != gold {
33+
t.Fatalf("mismatch: got %s, wanted %s", out, gold)
34+
}
35+
}

src/crypto/sha256/sha256_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
package sha256
88

99
import (
10+
"crypto/rand"
1011
"fmt"
1112
"io"
1213
"testing"
@@ -150,6 +151,18 @@ func TestBlockSize(t *testing.T) {
150151
}
151152
}
152153

154+
// Tests that blockGeneric (pure Go) and block (in assembly for some architectures) match.
155+
func TestBlockGeneric(t *testing.T) {
156+
gen, asm := New().(*digest), New().(*digest)
157+
buf := make([]byte, BlockSize*20) // arbitrary factor
158+
rand.Read(buf)
159+
blockGeneric(gen, buf)
160+
block(asm, buf)
161+
if *gen != *asm {
162+
t.Error("block and blockGeneric resulted in different states")
163+
}
164+
}
165+
153166
var bench = New()
154167
var buf = make([]byte, 8192)
155168

src/crypto/sha256/sha256block.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
// +build !386,!amd64
6-
75
// SHA256 block step.
86
// In its own file so that a faster assembly or C version
97
// can be substituted easily.
@@ -77,7 +75,7 @@ var _K = []uint32{
7775
0xc67178f2,
7876
}
7977

80-
func block(dig *digest, p []byte) {
78+
func blockGeneric(dig *digest, p []byte) {
8179
var w [64]uint32
8280
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]
8381
for len(p) >= chunk {

src/crypto/sha256/sha256block_decl.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Use of this source code is governed by a BSD-style
33
// license that can be found in the LICENSE file.
44

5-
// +build 386 amd64
5+
// +build 386 amd64 s390x
66

77
package sha256
88

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright 2016 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// +build !amd64,!386,!s390x
6+
7+
package sha256
8+
9+
var block = blockGeneric
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright 2016 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package sha256
6+
7+
// featureCheck reports whether the CPU supports the
8+
// SHA256 compute intermediate message digest (KIMD)
9+
// function code.
10+
func featureCheck() bool
11+
12+
var useAsm = featureCheck()
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Copyright 2016 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
#include "textflag.h"
6+
7+
// func featureCheck() bool
8+
TEXT ·featureCheck(SB),NOSPLIT,$16-1
9+
LA tmp-16(SP), R1
10+
XOR R0, R0 // query function code is 0
11+
WORD $0xB93E0006 // KIMD (R6 is ignored)
12+
MOVBZ tmp-16(SP), R4 // get the first byte
13+
AND $0x20, R4 // bit 2 (big endian) for SHA256
14+
CMPBEQ R4, $0, nosha256
15+
MOVB $1, ret+0(FP)
16+
RET
17+
nosha256:
18+
MOVB $0, ret+0(FP)
19+
RET
20+
21+
// func block(dig *digest, p []byte)
22+
TEXT ·block(SB),NOSPLIT,$0-32
23+
MOVBZ ·useAsm(SB), R4
24+
LMG dig+0(FP), R1, R3 // R2 = &p[0], R3 = len(p)
25+
CMPBNE R4, $1, generic
26+
MOVBZ $2, R0 // SHA256 function code
27+
loop:
28+
WORD $0xB93E0002 // KIMD R2
29+
BVS loop // continue if interrupted
30+
done:
31+
XOR R0, R0 // restore R0
32+
RET
33+
generic:
34+
BR ·blockGeneric(SB)

0 commit comments

Comments
 (0)