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  }