crc32_amd64.go 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. //+build !appengine,!gccgo
  2. // Copyright 2011 The Go Authors. All rights reserved.
  3. // Use of this source code is governed by a BSD-style
  4. // license that can be found in the LICENSE file.
  5. package crc32
  6. // This file contains the code to call the SSE 4.2 version of the Castagnoli
  7. // and IEEE CRC.
  8. // haveSSE41/haveSSE42/haveCLMUL are defined in crc_amd64.s and uses
  9. // CPUID to test for SSE 4.1, 4.2 and CLMUL support.
  10. func haveSSE41() bool
  11. func haveSSE42() bool
  12. func haveCLMUL() bool
  13. // castagnoliSSE42 is defined in crc_amd64.s and uses the SSE4.2 CRC32
  14. // instruction.
  15. // go:noescape
  16. func castagnoliSSE42(crc uint32, p []byte) uint32
  17. // ieeeCLMUL is defined in crc_amd64.s and uses the PCLMULQDQ
  18. // instruction as well as SSE 4.1.
  19. // go:noescape
  20. func ieeeCLMUL(crc uint32, p []byte) uint32
  21. var sse42 = haveSSE42()
  22. var useFastIEEE = haveCLMUL() && haveSSE41()
  23. func updateCastagnoli(crc uint32, p []byte) uint32 {
  24. if sse42 {
  25. return castagnoliSSE42(crc, p)
  26. }
  27. // only use slicing-by-8 when input is >= 16 Bytes
  28. if len(p) >= 16 {
  29. return updateSlicingBy8(crc, castagnoliTable8, p)
  30. }
  31. return update(crc, castagnoliTable, p)
  32. }
  33. func updateIEEE(crc uint32, p []byte) uint32 {
  34. if useFastIEEE && len(p) >= 64 {
  35. left := len(p) & 15
  36. do := len(p) - left
  37. crc := ^ieeeCLMUL(^crc, p[:do])
  38. if left > 0 {
  39. crc = update(crc, IEEETable, p[do:])
  40. }
  41. return crc
  42. }
  43. // only use slicing-by-8 when input is >= 16 Bytes
  44. if len(p) >= 16 {
  45. iEEETable8Once.Do(func() {
  46. iEEETable8 = makeTable8(IEEE)
  47. })
  48. return updateSlicingBy8(crc, iEEETable8, p)
  49. }
  50. return update(crc, IEEETable, p)
  51. }