github.com/mh-cbon/go@v0.0.0-20160603070303-9e112a3fe4c0/src/hash/crc32/crc32_s390x.go (about) 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 crc32 6 7 import ( 8 "unsafe" 9 ) 10 11 const ( 12 vxMinLen = 64 13 vxAlignment = 16 14 vxAlignMask = vxAlignment - 1 15 ) 16 17 // hasVectorFacility reports whether the machine has the z/Architecture 18 // vector facility installed and enabled. 19 func hasVectorFacility() bool 20 21 var hasVX = hasVectorFacility() 22 23 // vectorizedCastagnoli implements CRC32 using vector instructions. 24 // It is defined in crc32_s390x.s. 25 //go:noescape 26 func vectorizedCastagnoli(crc uint32, p []byte) uint32 27 28 // vectorizedIEEE implements CRC32 using vector instructions. 29 // It is defined in crc32_s390x.s. 30 //go:noescape 31 func vectorizedIEEE(crc uint32, p []byte) uint32 32 33 func genericCastagnoli(crc uint32, p []byte) uint32 { 34 // Use slicing-by-8 on larger inputs. 35 if len(p) >= sliceBy8Cutoff { 36 return updateSlicingBy8(crc, castagnoliTable8, p) 37 } 38 return update(crc, castagnoliTable, p) 39 } 40 41 func genericIEEE(crc uint32, p []byte) uint32 { 42 // Use slicing-by-8 on larger inputs. 43 if len(p) >= sliceBy8Cutoff { 44 ieeeTable8Once.Do(func() { 45 ieeeTable8 = makeTable8(IEEE) 46 }) 47 return updateSlicingBy8(crc, ieeeTable8, p) 48 } 49 return update(crc, IEEETable, p) 50 } 51 52 // updateCastagnoli calculates the checksum of p using genericCastagnoli to 53 // align the data appropriately for vectorCastagnoli. It avoids using 54 // vectorCastagnoli entirely if the length of p is less than or equal to 55 // vxMinLen. 56 func updateCastagnoli(crc uint32, p []byte) uint32 { 57 // Use vectorized function if vector facility is available and 58 // data length is above threshold. 59 if hasVX && len(p) > vxMinLen { 60 pAddr := uintptr(unsafe.Pointer(&p[0])) 61 if pAddr&vxAlignMask != 0 { 62 prealign := vxAlignment - int(pAddr&vxAlignMask) 63 crc = genericCastagnoli(crc, p[:prealign]) 64 p = p[prealign:] 65 } 66 aligned := len(p) & ^vxAlignMask 67 crc = vectorizedCastagnoli(crc, p[:aligned]) 68 p = p[aligned:] 69 // process remaining data 70 if len(p) > 0 { 71 crc = genericCastagnoli(crc, p) 72 } 73 return crc 74 } 75 return genericCastagnoli(crc, p) 76 } 77 78 // updateIEEE calculates the checksum of p using genericIEEE to align the data 79 // appropriately for vectorIEEE. It avoids using vectorIEEE entirely if the length 80 // of p is less than or equal to vxMinLen. 81 func updateIEEE(crc uint32, p []byte) uint32 { 82 // Use vectorized function if vector facility is available and 83 // data length is above threshold. 84 if hasVX && len(p) > vxMinLen { 85 pAddr := uintptr(unsafe.Pointer(&p[0])) 86 if pAddr&vxAlignMask != 0 { 87 prealign := vxAlignment - int(pAddr&vxAlignMask) 88 crc = genericIEEE(crc, p[:prealign]) 89 p = p[prealign:] 90 } 91 aligned := len(p) & ^vxAlignMask 92 crc = vectorizedIEEE(crc, p[:aligned]) 93 p = p[aligned:] 94 // process remaining data 95 if len(p) > 0 { 96 crc = genericIEEE(crc, p) 97 } 98 return crc 99 } 100 return genericIEEE(crc, p) 101 }