Merge pull request #11897 from kjbracey-arm/crc

MbedCRC: improve init value handling and tests
pull/12225/head
Martin Kojtal 2020-01-09 13:31:30 +01:00 committed by GitHub
commit 8c4ed4a6cb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 304 additions and 164 deletions

View File

@ -63,6 +63,26 @@ void test_supported_polynomials()
TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc));
TEST_ASSERT_EQUAL(0x57, crc);
}
{
MbedCRC<POLY_7BIT_SD, 7> ct(0x2B, 0, true, false);
TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc));
TEST_ASSERT_EQUAL(0x1D, crc);
}
{
MbedCRC<POLY_7BIT_SD, 7> ct(0x2B, 0, false, true);
TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc));
TEST_ASSERT_EQUAL(0x2E, crc);
}
{
MbedCRC<POLY_7BIT_SD, 7> ct(0x2B, 0, true, true);
TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc));
TEST_ASSERT_EQUAL(0x5C, crc);
}
{
MbedCRC<POLY_7BIT_SD, 7> ct(0, 0x2B, false, true);
TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc));
TEST_ASSERT_EQUAL(0x7C, crc);
}
{
MbedCRC<POLY_8BIT_CCITT, 8> ct;
TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc));
@ -98,6 +118,51 @@ void test_partial_crc()
TEST_ASSERT_EQUAL(0x29B1, crc);
}
{
MbedCRC<POLY_32BIT_ANSI, 32> ct;
TEST_ASSERT_EQUAL(0, ct.compute_partial_start(&crc));
TEST_ASSERT_EQUAL(0, ct.compute_partial(test, 8, &crc));
TEST_ASSERT_EQUAL(0, ct.compute_partial(&test[8], 1, &crc));
TEST_ASSERT_EQUAL(0, ct.compute_partial_stop(&crc));
TEST_ASSERT_EQUAL(0xCBF43926, crc);
}
{
MbedCRC<POLY_32BIT_ANSI, 32> ct(0xFFFFFFFF, 0, true, false);
TEST_ASSERT_EQUAL(0, ct.compute_partial_start(&crc));
TEST_ASSERT_EQUAL(0, ct.compute_partial(test, 8, &crc));
TEST_ASSERT_EQUAL(0, ct.compute_partial_stop(&crc));
}
{
MbedCRC<POLY_32BIT_ANSI, 32> ct(crc, 0xFFFFFFFF, true, true);
TEST_ASSERT_EQUAL(0, ct.compute_partial_start(&crc));
TEST_ASSERT_EQUAL(0, ct.compute_partial(&test[8], 1, &crc));
TEST_ASSERT_EQUAL(0, ct.compute_partial_stop(&crc));
TEST_ASSERT_EQUAL(0xCBF43926, crc);
}
}
void test_mode_limit()
{
const char test[] = "123456789";
uint32_t crc;
{
MbedCRC<POLY_32BIT_ANSI, 32, CrcMode::BITWISE> ct;
TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc));
TEST_ASSERT_EQUAL(0xCBF43926, crc);
}
{
MbedCRC<POLY_32BIT_ANSI, 32, CrcMode::TABLE> ct;
TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc));
TEST_ASSERT_EQUAL(0xCBF43926, crc);
}
{
MbedCRC<POLY_32BIT_ANSI, 32, CrcMode::HARDWARE> ct;
TEST_ASSERT_EQUAL(0, ct.compute(test, strlen(test), &crc));
TEST_ASSERT_EQUAL(0xCBF43926, crc);
}
}
void test_sd_crc()
@ -189,6 +254,7 @@ void test_thread_safety()
Case cases[] = {
Case("Test supported polynomials", test_supported_polynomials),
Case("Test partial CRC", test_partial_crc),
Case("Test mode-limited CRC", test_mode_limit),
Case("Test SD CRC polynomials", test_sd_crc),
#if defined(MBED_CONF_RTOS_PRESENT)
Case("Test thread safety", test_thread_safety),

View File

@ -27,8 +27,6 @@
using namespace utest::v1;
#define POLY_8BIT_MAXIM 0x31
#define POLY_16BIT_MAXIM 0x8005
#define POLY_32BIT_POSIX 0x4C11DB7
#define UNSUPPORTED (-1)
#define POL_CNT (2)
@ -201,70 +199,78 @@ int main()
// *INDENT-OFF*
TEST_CASE local_test_cases[] = {
/* Predefined polynomials. */
/* 00 */{ {POLY_7BIT_SD , 7, 0x00000000, 0x00000000, false, false}, 0x75 },
/* 01 */{ {POLY_7BIT_SD , 7, 0x0000007F, 0x00000000, false, false}, 0x50 },
/* 02 */{ {POLY_7BIT_SD , 7, 0x0000002B, 0x00000000, false, false}, 0x3A },
/* 03 */{ {POLY_7BIT_SD , 7, 0x00000000, 0x0000007F, false, false}, 0x0A },
/* 04 */{ {POLY_7BIT_SD , 7, 0x00000000, 0x0000002B, false, false}, 0x5E },
/* 05 */{ {POLY_7BIT_SD , 7, 0x00000000, 0x00000000, true , false}, 0x52 },
/* 06 */{ {POLY_7BIT_SD , 7, 0x00000000, 0x00000000, false, true }, 0x57 },
{ {POLY_7BIT_SD , 7, 0x00000000, 0x00000000, false, false}, 0x75 },
{ {POLY_7BIT_SD , 7, 0x0000007F, 0x00000000, false, false}, 0x50 },
{ {POLY_7BIT_SD , 7, 0x0000002B, 0x00000000, false, false}, 0x3A },
{ {POLY_7BIT_SD , 7, 0x00000000, 0x0000007F, false, false}, 0x0A },
{ {POLY_7BIT_SD , 7, 0x00000000, 0x0000002B, false, false}, 0x5E },
{ {POLY_7BIT_SD , 7, 0x00000000, 0x00000000, true , false}, 0x52 },
{ {POLY_7BIT_SD , 7, 0x00000000, 0x00000000, false, true }, 0x57 },
{ {POLY_7BIT_SD , 7, 0x0000002B, 0x00000000, true , false}, 0x1D },
{ {POLY_7BIT_SD , 7, 0x0000002B, 0x00000000, false, true }, 0x2E },
{ {POLY_7BIT_SD , 7, 0x0000002B, 0x00000000, true , true }, 0x5C },
{ {POLY_7BIT_SD , 7, 0x00000000, 0x0000002B, false, true }, 0x7C },
/* 07 */{ {POLY_8BIT_CCITT , 8, 0x00000000, 0x00000000, false, false}, 0xF4 },
/* 08 */{ {POLY_8BIT_CCITT , 8, 0x000000FF, 0x00000000, false, false}, 0xFB },
/* 09 */{ {POLY_8BIT_CCITT , 8, 0x000000AB, 0x00000000, false, false}, 0x87 },
/* 10 */{ {POLY_8BIT_CCITT , 8, 0x00000000, 0x000000FF, false, false}, 0x0B },
/* 11 */{ {POLY_8BIT_CCITT , 8, 0x00000000, 0x000000AB, false, false}, 0x5F },
/* 12 */{ {POLY_8BIT_CCITT , 8, 0x00000000, 0x00000000, true , false}, 0x04 },
/* 13 */{ {POLY_8BIT_CCITT , 8, 0x00000000, 0x00000000, false, true }, 0x2F },
{ {POLY_8BIT_CCITT , 8, 0x00000000, 0x00000000, false, false}, 0xF4 },
{ {POLY_8BIT_CCITT , 8, 0x000000FF, 0x00000000, false, false}, 0xFB },
{ {POLY_8BIT_CCITT , 8, 0x000000AB, 0x00000000, false, false}, 0x87 },
{ {POLY_8BIT_CCITT , 8, 0x00000000, 0x000000FF, false, false}, 0x0B },
{ {POLY_8BIT_CCITT , 8, 0x00000000, 0x000000AB, false, false}, 0x5F },
{ {POLY_8BIT_CCITT , 8, 0x00000000, 0x00000000, true , false}, 0x04 },
{ {POLY_8BIT_CCITT , 8, 0x00000000, 0x00000000, false, true }, 0x2F },
{ {POLY_8BIT_CCITT , 8, 0x000000AB, 0x00000000, true, false}, 0x77 },
{ {POLY_8BIT_CCITT , 8, 0x000000AB, 0x00000000, false, true }, 0xE1 },
{ {POLY_8BIT_CCITT , 8, 0x000000AB, 0x00000000, true, true }, 0xEE },
{ {POLY_8BIT_CCITT , 8, 0x00000000, 0x000000AB, false, true }, 0x84 },
/* 14 */{ {POLY_16BIT_CCITT , 16, 0x00000000, 0x00000000, false, false}, 0x31C3 },
/* 15 */{ {POLY_16BIT_CCITT , 16, 0x0000FFFF, 0x00000000, false, false}, 0x29B1 },
/* 16 */{ {POLY_16BIT_CCITT , 16, 0x0000ABAB, 0x00000000, false, false}, 0x7D70 },
/* 17 */{ {POLY_16BIT_CCITT , 16, 0x00000000, 0x0000FFFF, false, false}, 0xCE3C },
/* 18 */{ {POLY_16BIT_CCITT , 16, 0x00000000, 0x0000ABAB, false, false}, 0x9A68 },
/* 19 */{ {POLY_16BIT_CCITT , 16, 0x00000000, 0x00000000, true , false}, 0x9184 },
/* 20 */{ {POLY_16BIT_CCITT , 16, 0x00000000, 0x00000000, false, true }, 0xC38C },
{ {POLY_16BIT_CCITT , 16, 0x00000000, 0x00000000, false, false}, 0x31C3 },
{ {POLY_16BIT_CCITT , 16, 0x0000FFFF, 0x00000000, false, false}, 0x29B1 },
{ {POLY_16BIT_CCITT , 16, 0x0000ABAB, 0x00000000, false, false}, 0x7D70 },
{ {POLY_16BIT_CCITT , 16, 0x00000000, 0x0000FFFF, false, false}, 0xCE3C },
{ {POLY_16BIT_CCITT , 16, 0x00000000, 0x0000ABAB, false, false}, 0x9A68 },
{ {POLY_16BIT_CCITT , 16, 0x00000000, 0x00000000, true , false}, 0x9184 },
{ {POLY_16BIT_CCITT , 16, 0x00000000, 0x00000000, false, true }, 0xC38C },
{ {POLY_16BIT_CCITT , 16, 0x0000ABAB, 0x00000000, true, false}, 0xDD37 },
{ {POLY_16BIT_CCITT , 16, 0x0000ABAB, 0x00000000, false, true }, 0x0EBE },
{ {POLY_16BIT_CCITT , 16, 0x0000ABAB, 0x00000000, true, true }, 0xECBB },
{ {POLY_16BIT_CCITT , 16, 0x00000000, 0x0000ABAB, false, true }, 0x6827 },
/* 21 */{ {POLY_16BIT_IBM , 16, 0x00000000, 0x00000000, false, false}, 0xFEE8 },
/* 22 */{ {POLY_16BIT_IBM , 16, 0x0000FFFF, 0x00000000, false, false}, 0xAEE7 },
/* 23 */{ {POLY_16BIT_IBM , 16, 0x0000ABAB, 0x00000000, false, false}, 0x0887 },
/* 24 */{ {POLY_16BIT_IBM , 16, 0x00000000, 0x0000FFFF, false, false}, 0x0117 },
/* 25 */{ {POLY_16BIT_IBM , 16, 0x00000000, 0x0000ABAB, false, false}, 0x5543 },
/* 26 */{ {POLY_16BIT_IBM , 16, 0x00000000, 0x00000000, true , false}, 0xBCDD },
/* 27 */{ {POLY_16BIT_IBM , 16, 0x00000000, 0x00000000, false, true }, 0x177F },
{ {POLY_16BIT_IBM , 16, 0x00000000, 0x00000000, false, false}, 0xFEE8 },
{ {POLY_16BIT_IBM , 16, 0x0000FFFF, 0x00000000, false, false}, 0xAEE7 },
{ {POLY_16BIT_IBM , 16, 0x0000ABAB, 0x00000000, false, false}, 0x0887 },
{ {POLY_16BIT_IBM , 16, 0x00000000, 0x0000FFFF, false, false}, 0x0117 },
{ {POLY_16BIT_IBM , 16, 0x00000000, 0x0000ABAB, false, false}, 0x5543 },
{ {POLY_16BIT_IBM , 16, 0x00000000, 0x00000000, true , false}, 0xBCDD },
{ {POLY_16BIT_IBM , 16, 0x00000000, 0x00000000, false, true }, 0x177F },
{ {POLY_16BIT_IBM , 16, 0x0000ABAB, 0x00000000, true, false}, 0x4AB2 },
{ {POLY_16BIT_IBM , 16, 0x0000ABAB, 0x00000000, false, true }, 0xE110 },
{ {POLY_16BIT_IBM , 16, 0x0000ABAB, 0x00000000, true, true }, 0x4D52 },
{ {POLY_16BIT_IBM , 16, 0x00000000, 0x0000ABAB, false, true }, 0xBCD4 },
/* 28 */{ {POLY_32BIT_ANSI , 32, 0x00000000, 0x00000000, false, false}, 0x89A1897F },
/* 29 */{ {POLY_32BIT_ANSI , 32, 0xFFFFFFFF, 0x00000000, false, false}, 0x0376E6E7 },
/* 30 */{ {POLY_32BIT_ANSI , 32, 0xABABABAB, 0x00000000, false, false}, 0x871A2FAA },
/* 31 */{ {POLY_32BIT_ANSI , 32, 0x00000000, 0xFFFFFFFF, false, false}, 0x765E7680 },
/* 32 */{ {POLY_32BIT_ANSI , 32, 0x00000000, 0xABABABAB, false, false}, 0x220A22D4 },
/* 33 */{ {POLY_32BIT_ANSI , 32, 0x00000000, 0x00000000, true , false}, 0x11B4BFB4 },
/* 34 */{ {POLY_32BIT_ANSI , 32, 0x00000000, 0x00000000, false, true }, 0xFE918591 },
{ {POLY_32BIT_ANSI , 32, 0x00000000, 0x00000000, false, false}, 0x89A1897F },
{ {POLY_32BIT_ANSI , 32, 0xFFFFFFFF, 0x00000000, false, false}, 0x0376E6E7 },
{ {POLY_32BIT_ANSI , 32, 0xABABABAB, 0x00000000, false, false}, 0x871A2FAA },
{ {POLY_32BIT_ANSI , 32, 0x00000000, 0xFFFFFFFF, false, false}, 0x765E7680 },
{ {POLY_32BIT_ANSI , 32, 0x00000000, 0xABABABAB, false, false}, 0x220A22D4 },
{ {POLY_32BIT_ANSI , 32, 0x00000000, 0x00000000, true , false}, 0x11B4BFB4 },
{ {POLY_32BIT_ANSI , 32, 0x00000000, 0x00000000, false, true }, 0xFE918591 },
{ {POLY_32BIT_ANSI , 32, 0xABABABAB, 0x00000000, true, false}, 0x1F0F1961 },
{ {POLY_32BIT_ANSI , 32, 0xABABABAB, 0x00000000, false, true }, 0x55F458E1 },
{ {POLY_32BIT_ANSI , 32, 0xABABABAB, 0x00000000, true, true }, 0x8698F0F8 },
{ {POLY_32BIT_ANSI , 32, 0x00000000, 0xABABABAB, false, true }, 0x553A2E3A },
/* Not-predefined polynomials. */
/* 35 */{ {POLY_8BIT_MAXIM , 8, 0x00000000, 0x00000000, false, false}, 0xA2 },
/* 36 */{ {POLY_8BIT_MAXIM , 8, 0x000000FF, 0x00000000, false, false}, 0xF7 },
/* 37 */{ {POLY_8BIT_MAXIM , 8, 0x000000AB, 0x00000000, false, false}, 0x71 },
/* 38 */{ {POLY_8BIT_MAXIM , 8, 0x00000000, 0x000000FF, false, false}, 0x5D },
/* 39 */{ {POLY_8BIT_MAXIM , 8, 0x00000000, 0x000000AB, false, false}, 0x09 },
/* 40 */{ {POLY_8BIT_MAXIM , 8, 0x00000000, 0x00000000, true , false}, 0x85 },
/* 41 */{ {POLY_8BIT_MAXIM , 8, 0x00000000, 0x00000000, false, true }, 0x45 },
/* 42 */{ {POLY_16BIT_MAXIM , 16, 0x00000000, 0x00000000, false, false}, 0xFEE8 },
/* 43 */{ {POLY_16BIT_MAXIM , 16, 0x0000FFFF, 0x00000000, false, false}, 0xAEE7 },
/* 44 */{ {POLY_16BIT_MAXIM , 16, 0x0000ABAB, 0x00000000, false, false}, 0x0887 },
/* 45 */{ {POLY_16BIT_MAXIM , 16, 0x00000000, 0x0000FFFF, false, false}, 0x0117 },
/* 46 */{ {POLY_16BIT_MAXIM , 16, 0x00000000, 0x0000ABAB, false, false}, 0x5543 },
/* 47 */{ {POLY_16BIT_MAXIM , 16, 0x00000000, 0x00000000, true , false}, 0xBCDD },
/* 48 */{ {POLY_16BIT_MAXIM , 16, 0x00000000, 0x00000000, false, true }, 0x177F },
/* 49 */{ {POLY_32BIT_POSIX , 32, 0x00000000, 0x00000000, false, false}, 0x89A1897F },
/* 50 */{ {POLY_32BIT_POSIX , 32, 0xFFFFFFFF, 0x00000000, false, false}, 0x0376E6E7 },
/* 51 */{ {POLY_32BIT_POSIX , 32, 0xABABABAB, 0x00000000, false, false}, 0x871A2FAA },
/* 52 */{ {POLY_32BIT_POSIX , 32, 0x00000000, 0xFFFFFFFF, false, false}, 0x765E7680 },
/* 53 */{ {POLY_32BIT_POSIX , 32, 0x00000000, 0xABABABAB, false, false}, 0x220A22D4 },
/* 54 */{ {POLY_32BIT_POSIX , 32, 0x00000000, 0x00000000, true , false}, 0x11B4BFB4 },
/* 55 */{ {POLY_32BIT_POSIX , 32, 0x00000000, 0x00000000, false, true }, 0xFE918591 },
/* Not-predefined polynomials. */
{ {POLY_8BIT_MAXIM , 8, 0x00000000, 0x00000000, false, false}, 0xA2 },
{ {POLY_8BIT_MAXIM , 8, 0x000000FF, 0x00000000, false, false}, 0xF7 },
{ {POLY_8BIT_MAXIM , 8, 0x000000AB, 0x00000000, false, false}, 0x71 },
{ {POLY_8BIT_MAXIM , 8, 0x00000000, 0x000000FF, false, false}, 0x5D },
{ {POLY_8BIT_MAXIM , 8, 0x00000000, 0x000000AB, false, false}, 0x09 },
{ {POLY_8BIT_MAXIM , 8, 0x00000000, 0x00000000, true , false}, 0x85 },
{ {POLY_8BIT_MAXIM , 8, 0x00000000, 0x00000000, false, true }, 0x45 },
{ {POLY_8BIT_MAXIM , 8, 0x000000AB, 0x00000000, true, false}, 0x56 },
{ {POLY_8BIT_MAXIM , 8, 0x000000AB, 0x00000000, false, true }, 0x8E },
{ {POLY_8BIT_MAXIM , 8, 0x000000AB, 0x00000000, true, true }, 0x6A },
{ {POLY_8BIT_MAXIM , 8, 0x00000000, 0x000000AB, false, true }, 0xEE },
};
// *INDENT-ON*

View File

@ -29,7 +29,12 @@
#include "platform/SingletonPtr.h"
#include "platform/PlatformMutex.h"
#ifdef UNITTEST
#include <type_traits>
#define MSTD_CONSTEXPR_IF_HAS_IS_CONSTANT_EVALUATED
#else
#include <mstd_type_traits>
#endif
namespace mbed {
/** \addtogroup drivers-public-api */
@ -175,12 +180,40 @@ public:
* polynomials with different initial/final/reflect values
*
*/
constexpr
MbedCRC(uint32_t initial_xor, uint32_t final_xor, bool reflect_data, bool reflect_remainder) :
crc_impl(initial_xor, final_xor, reflect_data, reflect_remainder)
{
}
MbedCRC();
/* Default values for different types of polynomials
*/
// *INDENT-OFF*
template<uint32_t poly = polynomial, std::enable_if_t<poly == POLY_32BIT_ANSI && width == 32, int> = 0>
constexpr MbedCRC() : MbedCRC(0xFFFFFFFF, 0xFFFFFFFF, true, true)
{
}
template<uint32_t poly = polynomial, std::enable_if_t<poly == POLY_16BIT_IBM && width == 16, int> = 0>
constexpr MbedCRC() : MbedCRC(0, 0, true, true)
{
}
template<uint32_t poly = polynomial, std::enable_if_t<poly == POLY_16BIT_CCITT && width == 16, int> = 0>
constexpr MbedCRC() : MbedCRC(0xFFFF, 0, false, false)
{
}
template<uint32_t poly = polynomial, std::enable_if_t<poly == POLY_7BIT_SD && width == 7, int> = 0>
constexpr MbedCRC() : MbedCRC(0, 0, false, false)
{
}
template<uint32_t poly = polynomial, std::enable_if_t<poly == POLY_8BIT_CCITT && width == 8, int> = 0>
constexpr MbedCRC() : MbedCRC(0, 0, false, false)
{
}
// *INDENT-ON*
/** Compute CRC for the data input
* Compute CRC performs the initialization, computation and collection of
@ -279,6 +312,7 @@ class MbedCRC {
public:
typedef size_t crc_data_size_t;
constexpr
MbedCRC(uint32_t initial_xor, uint32_t final_xor, bool reflect_data, bool reflect_remainder) :
_initial_value(adjust_initial_value(initial_xor, reflect_data)),
_final_xor(final_xor),
@ -400,7 +434,7 @@ public:
}
} else {
/* CRC has MSB in top bit of register */
p_crc = _reflect_remainder ? reflect_register(p_crc) : shift_right(p_crc);
p_crc = _reflect_remainder ? reflect(p_crc) : shift_right(p_crc);
}
} else { // TABLE
/* CRC has MSB in bottom bit of register */
@ -417,45 +451,91 @@ public:
}
private:
/** Guaranteed constexpr reflection (all toolchains)
*
* @note This should never be run-time evaluated - very inefficient
* @param Register value to be reflected (full 32-bit value)
* @return Reflected value (full 32-bit value)
*/
static constexpr uint32_t reflect_constant(uint32_t data)
{
/* Doing this hard way to keep it C++11 constexpr and hence ARM C 5 compatible */
return ((data & 0x00000001) << 31) |
((data & 0x00000002) << 29) |
((data & 0x00000004) << 27) |
((data & 0x00000008) << 25) |
((data & 0x00000010) << 23) |
((data & 0x00000020) << 21) |
((data & 0x00000040) << 19) |
((data & 0x00000080) << 17) |
((data & 0x00000100) << 15) |
((data & 0x00000200) << 13) |
((data & 0x00000400) << 11) |
((data & 0x00000800) << 9) |
((data & 0x00001000) << 7) |
((data & 0x00002000) << 5) |
((data & 0x00004000) << 3) |
((data & 0x00008000) << 1) |
((data & 0x00010000) >> 1) |
((data & 0x00020000) >> 3) |
((data & 0x00040000) >> 5) |
((data & 0x00080000) >> 7) |
((data & 0x00100000) >> 9) |
((data & 0x00200000) >> 11) |
((data & 0x00400000) >> 13) |
((data & 0x00800000) >> 15) |
((data & 0x01000000) >> 17) |
((data & 0x02000000) >> 19) |
((data & 0x04000000) >> 21) |
((data & 0x08000000) >> 23) |
((data & 0x10000000) >> 25) |
((data & 0x20000000) >> 27) |
((data & 0x40000000) >> 29) |
((data & 0x80000000) >> 31);
}
/** General reflection
*
* @note This is used when we may need to perform run-time computation, so
* we need the possibility to produce the optimal run-time RBIT instruction. But
* if the compiler doesn't treat RBIT as a built-in, it's useful to have a C fallback
* for the constant case, avoiding runtime RBIT(0) computations. This is an
* optimization only available for some toolchains; others will always use runtime
* RBIT. If we require a constant expression, use reflect_constant instead.
*
* @param Register value to be reflected (full 32-bit value)
* @return Reflected value (full 32-bit value)
*/
#ifdef MSTD_HAS_IS_CONSTANT_EVALUATED
static constexpr uint32_t reflect(uint32_t data)
{
return mstd::is_constant_evaluated() ? reflect_constant(data) : __RBIT(data);
}
#else
static uint32_t reflect(uint32_t data)
{
return __RBIT(data);
}
#endif
/** Data bytes may need to be reflected.
*
* @param data value to be reflected (bottom 8 bits)
* @return Reflected value (bottom 8 bits)
*/
static MSTD_CONSTEXPR_IF_HAS_IS_CONSTANT_EVALUATED
uint_fast32_t reflect_byte(uint_fast32_t data)
{
return reflect(data) >> 24;
}
/** Get the current CRC polynomial, reflected at bottom of register.
*
* @return Reflected polynomial value (so x^width term would be at bit -1)
*/
static constexpr uint32_t get_reflected_polynomial()
{
/* Doing this hard way to keep it C++11 constexpr and hence ARM C 5 compatible */
return shift_right(((polynomial & 0x00000001) << 31) |
((polynomial & 0x00000002) << 29) |
((polynomial & 0x00000004) << 27) |
((polynomial & 0x00000008) << 25) |
((polynomial & 0x00000010) << 23) |
((polynomial & 0x00000020) << 21) |
((polynomial & 0x00000040) << 19) |
((polynomial & 0x00000080) << 17) |
((polynomial & 0x00000100) << 15) |
((polynomial & 0x00000200) << 13) |
((polynomial & 0x00000400) << 11) |
((polynomial & 0x00000800) << 9) |
((polynomial & 0x00001000) << 7) |
((polynomial & 0x00002000) << 5) |
((polynomial & 0x00004000) << 3) |
((polynomial & 0x00008000) << 1) |
((polynomial & 0x00010000) >> 1) |
((polynomial & 0x00020000) >> 3) |
((polynomial & 0x00040000) >> 5) |
((polynomial & 0x00080000) >> 7) |
((polynomial & 0x00100000) >> 9) |
((polynomial & 0x00200000) >> 11) |
((polynomial & 0x00400000) >> 13) |
((polynomial & 0x00800000) >> 15) |
((polynomial & 0x01000000) >> 17) |
((polynomial & 0x02000000) >> 19) |
((polynomial & 0x04000000) >> 21) |
((polynomial & 0x08000000) >> 23) |
((polynomial & 0x10000000) >> 25) |
((polynomial & 0x20000000) >> 27) |
((polynomial & 0x40000000) >> 29) |
((polynomial & 0x80000000) >> 31));
return shift_right(reflect_constant(polynomial));
}
/** Get the current CRC polynomial, at top of register.
@ -479,27 +559,13 @@ private:
>>;
// *INDENT-ON*
/* Not [MBED_CRC_TABLE_SIZE] as that could be [0], which is illegal.
* We do need the declaration to always exist so that do_compute_partial<TABLE> is always well-formed,
* but we never actually use it MBED_CRC_TABLE_SIZE is 0.
*/
static const crc_table_t _crc_table[];
#if MBED_CRC_TABLE_SIZE > 0
/* Tables only actually defined for mode == TABLE, and certain polynomials - see below */
static const crc_table_t _crc_table[MBED_CRC_TABLE_SIZE];
#endif
static uint32_t adjust_initial_value(uint32_t initial_xor, bool reflect_data)
static constexpr uint32_t adjust_initial_value(uint32_t initial_xor, bool reflect_data)
{
/* As initial_xor is almost certain to be constant all zeros or ones, try to
* process that a constant, avoiding an RBIT instruction (or worse).
*/
if (initial_xor == 0 || initial_xor == (get_crc_mask() & -1U)) {
/* Only possible adjustment is shifting to top for bitwise */
if (mode == CrcMode::BITWISE && !reflect_data) {
return shift_left(initial_xor);
} else {
return initial_xor;
}
}
/* Weird or non-constant initial value - need to think about reflection */
if (mode == CrcMode::BITWISE) {
/* For bitwise calculation, CRC register is reflected if data is, to match input.
* (MSB at bottom of register). If not reflected, it is at the top of the register
@ -546,34 +612,15 @@ private:
return (uint32_t)((uint32_t)2U << (width - 1)) - 1U;
}
/** Data bytes may need to be reflected.
*
* @param data value to be reflected (bottom 8 bits)
* @return Reflected value (bottom 8 bits)
*/
static uint_fast32_t reflect_byte(uint_fast32_t data)
{
return __RBIT(data) >> 24;
}
/** CRC values may need to be reflected.
*
* @param CRC value to be reflected (width bits at bottom of 32-bit word)
* @return Reflected value (still at bottom of 32-bit word)
*/
static uint32_t reflect_crc(uint32_t data)
static MSTD_CONSTEXPR_IF_HAS_IS_CONSTANT_EVALUATED
uint32_t reflect_crc(uint32_t data)
{
return __RBIT(data) >> (32 - width);
}
/** Register values may need to be reflected.
*
* @param Register value to be reflected (full 32-bit value)
* @return Reflected value (full 32-bit value)
*/
static uint32_t reflect_register(uint32_t data)
{
return __RBIT(data);
return reflect(data) >> (32 - width);
}
/** Register values may need to be shifted left.
@ -742,6 +789,7 @@ private:
return 0;
}
#if MBED_CRC_TABLE_SIZE > 0
/** CRC computation using ROM tables.
*
* @param buffer data buffer
@ -774,6 +822,7 @@ private:
*crc = p_crc;
return 0;
}
#endif
#ifdef DEVICE_CRC
/** Hardware CRC computation.
@ -793,37 +842,32 @@ private:
};
#if MBED_CRC_TABLE_SIZE > 0
/* Declarations of the tables we provide. (Not strictly needed, but compilers
* can warn if they see us using the template without a generic definition, so
* let it know we have provided these specialisations.)
*/
template<>
const uint8_t MbedCRC<POLY_7BIT_SD, 7, CrcMode::TABLE>::_crc_table[MBED_CRC_TABLE_SIZE];
template<>
const uint8_t MbedCRC<POLY_8BIT_CCITT, 8, CrcMode::TABLE>::_crc_table[MBED_CRC_TABLE_SIZE];
template<>
const uint16_t MbedCRC<POLY_16BIT_CCITT, 16, CrcMode::TABLE>::_crc_table[MBED_CRC_TABLE_SIZE];
template<>
const uint16_t MbedCRC<POLY_16BIT_IBM, 16, CrcMode::TABLE>::_crc_table[MBED_CRC_TABLE_SIZE];
template<>
const uint32_t MbedCRC<POLY_32BIT_ANSI, 32, CrcMode::TABLE>::_crc_table[MBED_CRC_TABLE_SIZE];
#endif // MBED_CRC_TABLE_SIZE > 0
} // namespace impl
#endif // !defined(DOXYGEN_ONLY)
/* Default values for different types of polynomials
*/
template<>
inline MbedCRC<POLY_32BIT_ANSI, 32>::MbedCRC() : MbedCRC(0xFFFFFFFF, 0xFFFFFFFF, true, true)
{
}
template<>
inline MbedCRC<POLY_16BIT_IBM, 16>::MbedCRC() : MbedCRC(0, 0, true, true)
{
}
template<>
inline MbedCRC<POLY_16BIT_CCITT, 16>::MbedCRC() : MbedCRC(0xFFFF, 0, false, false)
{
}
template<>
inline MbedCRC<POLY_7BIT_SD, 7>::MbedCRC(): MbedCRC(0, 0, false, false)
{
}
template<>
inline MbedCRC<POLY_8BIT_CCITT, 8>::MbedCRC(): MbedCRC(0, 0, false, false)
{
}
/** @}*/
/** @}*/

View File

@ -47,6 +47,7 @@
* - mstd::is_invocable, mbed::is_invocable_r, etc
* - mstd::invoke_result
* - logical operator traits (mstd::conjunction, mstd::disjunction, mstd::negation)
* - mstd::is_constant_evaluated
*/
#include <mstd_cstddef>
@ -1361,6 +1362,29 @@ struct is_nothrow_invocable_r : impl::is_invocable_r<R, invoke_result<F, Args...
#endif // __cpp_lib_is_invocable
/* C++20 is_constant_evaluated */
constexpr bool is_constant_evaluated() noexcept
{
#ifdef __clang__
#if __has_builtin(__builtin_is_constant_evaluated)
#define MSTD_HAS_IS_CONSTANT_EVALUATED 1
return __builtin_is_constant_evaluated();
#else
return false;
#endif
#elif __GNUC__ >= 9
#define MSTD_HAS_IS_CONSTANT_EVALUATED 1
return __builtin_is_constant_evaluated();
#else
return false;
#endif
}
#if MSTD_HAS_IS_CONSTANT_EVALUATED
#define MSTD_CONSTEXPR_IF_HAS_IS_CONSTANT_EVALUATED constexpr
#else
#define MSTD_CONSTEXPR_IF_HAS_IS_CONSTANT_EVALUATED
#endif
} // namespace mstd