1
// Copyright 2018 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.
5
//go:build gc && !purego
10
"golang.org/x/sys/cpu"
13
// updateVX is an assembly implementation of Poly1305 that uses vector
14
// instructions. It must only be called if the vector facility (vx) is
18
func updateVX(state *macState, msg []byte)
20
// mac is a replacement for macGeneric that uses a larger buffer and redirects
21
// calls that would have gone to updateGeneric to updateVX if the vector
22
// facility is installed.
24
// A larger buffer is required for good performance because the vector
25
// implementation has a higher fixed cost per call than the generic
30
buffer [16 * TagSize]byte // size must be a multiple of block size (16)
34
func (h *mac) Write(p []byte) (int, error) {
37
n := copy(h.buffer[h.offset:], p)
38
if h.offset+n < len(h.buffer) {
45
updateVX(&h.macState, h.buffer[:])
47
updateGeneric(&h.macState, h.buffer[:])
51
tail := len(p) % len(h.buffer) // number of bytes to copy into buffer
52
body := len(p) - tail // number of bytes to process now
55
updateVX(&h.macState, p[:body])
57
updateGeneric(&h.macState, p[:body])
60
h.offset = copy(h.buffer[:], p[body:]) // copy tail bytes - can be 0
64
func (h *mac) Sum(out *[TagSize]byte) {
66
remainder := h.buffer[:h.offset]
68
// Use the generic implementation if we have 2 or fewer blocks left
69
// to sum. The vector implementation has a higher startup time.
70
if cpu.S390X.HasVX && len(remainder) > 2*TagSize {
71
updateVX(&state, remainder)
72
} else if len(remainder) > 0 {
73
updateGeneric(&state, remainder)
75
finalize(out, &state.h, &state.s)