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