1// Copyright 2017 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
5package crc32
6
7import (
8	"unsafe"
9)
10
11const (
12	vecMinLen    = 16
13	vecAlignMask = 15 // align to 16 bytes
14	crcIEEE      = 1
15	crcCast      = 2
16)
17
18//go:noescape
19func ppc64SlicingUpdateBy8(crc uint32, table8 *slicing8Table, p []byte) uint32
20
21// this function requires the buffer to be 16 byte aligned and > 16 bytes long.
22//
23//go:noescape
24func vectorCrc32(crc uint32, poly uint32, p []byte) uint32
25
26var archCastagnoliTable8 *slicing8Table
27
28func archInitCastagnoli() {
29	archCastagnoliTable8 = slicingMakeTable(Castagnoli)
30}
31
32func archUpdateCastagnoli(crc uint32, p []byte) uint32 {
33	if len(p) >= 4*vecMinLen {
34		// If not aligned then process the initial unaligned bytes
35
36		if uint64(uintptr(unsafe.Pointer(&p[0])))&uint64(vecAlignMask) != 0 {
37			align := uint64(uintptr(unsafe.Pointer(&p[0]))) & uint64(vecAlignMask)
38			newlen := vecMinLen - align
39			crc = ppc64SlicingUpdateBy8(crc, archCastagnoliTable8, p[:newlen])
40			p = p[newlen:]
41		}
42		// p should be aligned now
43		aligned := len(p) & ^vecAlignMask
44		crc = vectorCrc32(crc, crcCast, p[:aligned])
45		p = p[aligned:]
46	}
47	if len(p) == 0 {
48		return crc
49	}
50	return ppc64SlicingUpdateBy8(crc, archCastagnoliTable8, p)
51}
52
53func archAvailableIEEE() bool {
54	return true
55}
56func archAvailableCastagnoli() bool {
57	return true
58}
59
60var archIeeeTable8 *slicing8Table
61
62func archInitIEEE() {
63	// We still use slicing-by-8 for small buffers.
64	archIeeeTable8 = slicingMakeTable(IEEE)
65}
66
67// archUpdateIEEE calculates the checksum of p using vectorizedIEEE.
68func archUpdateIEEE(crc uint32, p []byte) uint32 {
69
70	// Check if vector code should be used.  If not aligned, then handle those
71	// first up to the aligned bytes.
72
73	if len(p) >= 4*vecMinLen {
74		if uint64(uintptr(unsafe.Pointer(&p[0])))&uint64(vecAlignMask) != 0 {
75			align := uint64(uintptr(unsafe.Pointer(&p[0]))) & uint64(vecAlignMask)
76			newlen := vecMinLen - align
77			crc = ppc64SlicingUpdateBy8(crc, archIeeeTable8, p[:newlen])
78			p = p[newlen:]
79		}
80		aligned := len(p) & ^vecAlignMask
81		crc = vectorCrc32(crc, crcIEEE, p[:aligned])
82		p = p[aligned:]
83	}
84	if len(p) == 0 {
85		return crc
86	}
87	return ppc64SlicingUpdateBy8(crc, archIeeeTable8, p)
88}
89