Coverage Report

Created: 2025-11-09 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libtorrent/src/crc32c.cpp
Line
Count
Source
1
/*
2
3
Copyright (c) 2014-2020, Arvid Norberg
4
Copyright (c) 2016, Alden Torres
5
Copyright (c) 2018, Pavel Pimenov
6
All rights reserved.
7
8
Redistribution and use in source and binary forms, with or without
9
modification, are permitted provided that the following conditions
10
are met:
11
12
    * Redistributions of source code must retain the above copyright
13
      notice, this list of conditions and the following disclaimer.
14
    * Redistributions in binary form must reproduce the above copyright
15
      notice, this list of conditions and the following disclaimer in
16
      the documentation and/or other materials provided with the distribution.
17
    * Neither the name of the author nor the names of its
18
      contributors may be used to endorse or promote products derived
19
      from this software without specific prior written permission.
20
21
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31
POSSIBILITY OF SUCH DAMAGE.
32
33
*/
34
35
#include "libtorrent/config.hpp"
36
#include "libtorrent/crc32c.hpp"
37
#include "libtorrent/aux_/cpuid.hpp"
38
#include "libtorrent/aux_/byteswap.hpp"
39
#include "libtorrent/aux_/disable_warnings_push.hpp"
40
41
#include <boost/crc.hpp>
42
#if (defined _MSC_VER && _MSC_VER >= 1600 && (defined _M_IX86 || defined _M_X64))
43
#include <nmmintrin.h>
44
#endif
45
46
#include "libtorrent/aux_/disable_warnings_pop.hpp"
47
48
#if TORRENT_HAS_ARM_CRC32
49
#include <arm_acle.h>
50
#endif
51
52
namespace libtorrent {
53
54
  std::uint32_t crc32c_32(std::uint32_t v)
55
32
  {
56
32
#if TORRENT_HAS_SSE
57
32
    if (aux::sse42_support)
58
32
    {
59
32
      std::uint32_t ret = 0xffffffff;
60
32
#ifdef __GNUC__
61
      // we can't use these because then we'd have to tell
62
      // -msse4.2 to gcc on the command line
63
//      return __builtin_ia32_crc32si(ret, v) ^ 0xffffffff;
64
32
      asm ("crc32l\t" "(%1), %0"
65
32
        : "=r"(ret)
66
32
        : "r"(&v), "0"(ret));
67
32
      return ret ^ 0xffffffff;
68
#else
69
      return _mm_crc32_u32(ret, v) ^ 0xffffffff;
70
#endif
71
32
    }
72
0
#endif
73
74
#if TORRENT_HAS_ARM_CRC32
75
    if (aux::arm_crc32c_support)
76
    {
77
      std::uint32_t ret = 0xffffffff;
78
      return __crc32cw(ret, v) ^ 0xffffffff;
79
    }
80
#endif
81
82
0
    boost::crc_optimal<32, 0x1EDC6F41, 0xFFFFFFFF, 0xFFFFFFFF, true, true> crc;
83
0
    crc.process_bytes(&v, 4);
84
0
    return crc.checksum();
85
32
  }
86
87
  std::uint32_t crc32c(std::uint64_t const* buf, int num_words)
88
0
  {
89
0
#if TORRENT_HAS_SSE
90
0
    if (aux::sse42_support)
91
0
    {
92
0
#if defined _M_AMD64 || defined __x86_64__ \
93
0
  || defined __x86_64 || defined _M_X64 || defined __amd64__
94
0
      std::uint64_t ret = 0xffffffff;
95
0
      for (int i = 0; i < num_words; ++i)
96
0
      {
97
0
#ifdef __GNUC__
98
        // we can't use these because then we'd have to tell
99
        // -msse4.2 to gcc on the command line
100
//        ret = __builtin_ia32_crc32di(ret, buf[i]);
101
0
        __asm__("crc32q\t" "(%1), %0"
102
0
          : "=r"(ret)
103
0
          : "r"(buf+i), "0"(ret));
104
#else
105
        ret = _mm_crc32_u64(ret, buf[i]);
106
#endif
107
0
      }
108
0
      return std::uint32_t(ret) ^ 0xffffffff;
109
#else
110
      std::uint32_t ret = 0xffffffff;
111
      std::uint32_t const* buf0 = reinterpret_cast<std::uint32_t const*>(buf);
112
      for (int i = 0; i < num_words; ++i)
113
      {
114
#ifdef __GNUC__
115
        // we can't use these because then we'd have to tell
116
        // -msse4.2 to gcc on the command line
117
//        ret = __builtin_ia32_crc32si(ret, buf0[i*2]);
118
//        ret = __builtin_ia32_crc32si(ret, buf0[i*2+1]);
119
        asm ("crc32l\t" "(%1), %0"
120
          : "=r"(ret)
121
          : "r"(buf0+i*2), "0"(ret));
122
        asm ("crc32l\t" "(%1), %0"
123
          : "=r"(ret)
124
          : "r"(buf0+i*2+1), "0"(ret));
125
#else
126
        ret = _mm_crc32_u32(ret, buf0[i*2]);
127
        ret = _mm_crc32_u32(ret, buf0[i*2+1]);
128
#endif
129
      }
130
      return ret ^ 0xffffffff;
131
#endif // amd64 or x86
132
0
    }
133
0
#endif // x86 or amd64 and gcc or msvc
134
135
#if TORRENT_HAS_ARM_CRC32
136
    if (aux::arm_crc32c_support)
137
    {
138
      std::uint32_t ret = 0xffffffff;
139
      for (int i = 0; i < num_words; ++i)
140
      {
141
        ret = __crc32cd(ret, buf[i]);
142
      }
143
      return ret ^ 0xffffffff;
144
    }
145
#endif
146
147
0
    boost::crc_optimal<32, 0x1EDC6F41, 0xFFFFFFFF, 0xFFFFFFFF, true, true> crc;
148
0
    crc.process_bytes(buf, std::size_t(num_words) * 8);
149
0
    return crc.checksum();
150
0
  }
151
}