Home | History | Annotate | Download | only in crc32
      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 }
     88