github.com/corona10/go@v0.0.0-20180224231303-7a218942be57/src/hash/crc32/crc32_ppc64le.go (about)

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