crc32_ppc64le.mx raw

   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