crc32c_ppc.c 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
  2. // Copyright (c) 2017 International Business Machines Corp.
  3. // All rights reserved.
  4. // This source code is licensed under both the GPLv2 (found in the
  5. // COPYING file in the root directory) and Apache 2.0 License
  6. // (found in the LICENSE.Apache file in the root directory).
  7. #define CRC_TABLE
  8. #include <stdint.h>
  9. #include <stdlib.h>
  10. #include <strings.h>
  11. #include "util/crc32c_ppc_constants.h"
  12. #define VMX_ALIGN 16
  13. #define VMX_ALIGN_MASK (VMX_ALIGN - 1)
  14. #ifdef REFLECT
  15. static unsigned int crc32_align(unsigned int crc, unsigned char const *p,
  16. unsigned long len) {
  17. while (len--) crc = crc_table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
  18. return crc;
  19. }
  20. #endif
  21. #ifdef HAVE_POWER8
  22. unsigned int __crc32_vpmsum(unsigned int crc, unsigned char const *p,
  23. unsigned long len);
  24. static uint32_t crc32_vpmsum(uint32_t crc, unsigned char const *data,
  25. unsigned len) {
  26. unsigned int prealign;
  27. unsigned int tail;
  28. #ifdef CRC_XOR
  29. crc ^= 0xffffffff;
  30. #endif
  31. if (len < VMX_ALIGN + VMX_ALIGN_MASK) {
  32. crc = crc32_align(crc, data, (unsigned long)len);
  33. goto out;
  34. }
  35. if ((unsigned long)data & VMX_ALIGN_MASK) {
  36. prealign = VMX_ALIGN - ((unsigned long)data & VMX_ALIGN_MASK);
  37. crc = crc32_align(crc, data, prealign);
  38. len -= prealign;
  39. data += prealign;
  40. }
  41. crc = __crc32_vpmsum(crc, data, (unsigned long)len & ~VMX_ALIGN_MASK);
  42. tail = len & VMX_ALIGN_MASK;
  43. if (tail) {
  44. data += len & ~VMX_ALIGN_MASK;
  45. crc = crc32_align(crc, data, tail);
  46. }
  47. out:
  48. #ifdef CRC_XOR
  49. crc ^= 0xffffffff;
  50. #endif
  51. return crc;
  52. }
  53. /* This wrapper function works around the fact that crc32_vpmsum
  54. * does not gracefully handle the case where the data pointer is NULL. There
  55. * may be room for performance improvement here.
  56. */
  57. uint32_t crc32c_ppc(uint32_t crc, unsigned char const *data, unsigned len) {
  58. unsigned char *buf2;
  59. if (!data) {
  60. buf2 = (unsigned char *)malloc(len);
  61. bzero(buf2, len);
  62. crc = crc32_vpmsum(crc, buf2, len);
  63. free(buf2);
  64. } else {
  65. crc = crc32_vpmsum(crc, data, (unsigned long)len);
  66. }
  67. return crc;
  68. }
  69. #else /* HAVE_POWER8 */
  70. /* This symbol has to exist on non-ppc architectures (and on legacy
  71. * ppc systems using power7 or below) in order to compile properly
  72. * there, even though it won't be called.
  73. */
  74. uint32_t crc32c_ppc(uint32_t crc, unsigned char const *data, unsigned len) {
  75. return 0;
  76. }
  77. #endif /* HAVE_POWER8 */