Home | History | Annotate | Download | only in crc32
      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 const (
      8 	vxMinLen    = 64
      9 	vxAlignMask = 15 // align to 16 bytes
     10 )
     11 
     12 // hasVectorFacility reports whether the machine has the z/Architecture
     13 // vector facility installed and enabled.
     14 func hasVectorFacility() bool
     15 
     16 var hasVX = hasVectorFacility()
     17 
     18 // vectorizedCastagnoli implements CRC32 using vector instructions.
     19 // It is defined in crc32_s390x.s.
     20 //go:noescape
     21 func vectorizedCastagnoli(crc uint32, p []byte) uint32
     22 
     23 // vectorizedIEEE implements CRC32 using vector instructions.
     24 // It is defined in crc32_s390x.s.
     25 //go:noescape
     26 func vectorizedIEEE(crc uint32, p []byte) uint32
     27 
     28 func archAvailableCastagnoli() bool {
     29 	return hasVX
     30 }
     31 
     32 var archCastagnoliTable8 *slicing8Table
     33 
     34 func archInitCastagnoli() {
     35 	if !hasVX {
     36 		panic("not available")
     37 	}
     38 	// We still use slicing-by-8 for small buffers.
     39 	archCastagnoliTable8 = slicingMakeTable(Castagnoli)
     40 }
     41 
     42 // archUpdateCastagnoli calculates the checksum of p using
     43 // vectorizedCastagnoli.
     44 func archUpdateCastagnoli(crc uint32, p []byte) uint32 {
     45 	if !hasVX {
     46 		panic("not available")
     47 	}
     48 	// Use vectorized function if data length is above threshold.
     49 	if len(p) >= vxMinLen {
     50 		aligned := len(p) & ^vxAlignMask
     51 		crc = vectorizedCastagnoli(crc, p[:aligned])
     52 		p = p[aligned:]
     53 	}
     54 	if len(p) == 0 {
     55 		return crc
     56 	}
     57 	return slicingUpdate(crc, archCastagnoliTable8, p)
     58 }
     59 
     60 func archAvailableIEEE() bool {
     61 	return hasVX
     62 }
     63 
     64 var archIeeeTable8 *slicing8Table
     65 
     66 func archInitIEEE() {
     67 	if !hasVX {
     68 		panic("not available")
     69 	}
     70 	// We still use slicing-by-8 for small buffers.
     71 	archIeeeTable8 = slicingMakeTable(IEEE)
     72 }
     73 
     74 // archUpdateIEEE calculates the checksum of p using vectorizedIEEE.
     75 func archUpdateIEEE(crc uint32, p []byte) uint32 {
     76 	if !hasVX {
     77 		panic("not available")
     78 	}
     79 	// Use vectorized function if data length is above threshold.
     80 	if len(p) >= vxMinLen {
     81 		aligned := len(p) & ^vxAlignMask
     82 		crc = vectorizedIEEE(crc, p[:aligned])
     83 		p = p[aligned:]
     84 	}
     85 	if len(p) == 0 {
     86 		return crc
     87 	}
     88 	return slicingUpdate(crc, archIeeeTable8, p)
     89 }
     90