Source file src/hash/crc32/crc32_ppc64le.go

     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  //
    23  //go:noescape
    24  func vectorCrc32(crc uint32, poly uint32, p []byte) uint32
    25  
    26  var archCastagnoliTable8 *slicing8Table
    27  
    28  func archInitCastagnoli() {
    29  	archCastagnoliTable8 = slicingMakeTable(Castagnoli)
    30  }
    31  
    32  func 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  
    53  func archAvailableIEEE() bool {
    54  	return true
    55  }
    56  func archAvailableCastagnoli() bool {
    57  	return true
    58  }
    59  
    60  var archIeeeTable8 *slicing8Table
    61  
    62  func 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.
    68  func 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  

View as plain text