LCOV - code coverage report
Current view: top level - src/crypto/x11/arm_neon - echo.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 85 85 100.0 %
Date: 2026-06-25 07:23:43 Functions: 6 6 100.0 %

          Line data    Source code
       1             : // Copyright (c) 2025 The Dash Core developers
       2             : // Distributed under the MIT software license, see the accompanying
       3             : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
       4             : 
       5             : #if defined(ENABLE_ARM_NEON)
       6             : #include <attributes.h>
       7             : #include <crypto/x11/util/util.hpp>
       8             : 
       9             : #include <cstdint>
      10             : 
      11             : #include <arm_neon.h>
      12             : 
      13             : namespace sapphire {
      14             : namespace {
      15   744749794 : uint8x16_t ALWAYS_INLINE gf8_mul2(const uint8x16_t& x)
      16             : {
      17             :     // (x << 1)
      18   744749794 :     const uint8x16_t lhs = vshlq_n_u8(x, 1);
      19             :     // (x & 0x80) ? 0xff : 0x00
      20   744749794 :     const uint8x16_t msb_set = vandq_u8(x, vmovq_n_u8(0x80));
      21   744749794 :     const uint8x16_t mask = vceqq_u8(msb_set, vmovq_n_u8(0x80));
      22             :     // Replace 0xff with 0x1b
      23   744749794 :     const uint8x16_t rhs = vandq_u8(mask, vmovq_n_u8(0x1b));
      24             :     // (x << 1) ^ ((x & 0x80) ? 0x1b : 0x00))
      25   744749794 :     return util::Xor(lhs, rhs);
      26             : }
      27             : 
      28   248310191 : void ALWAYS_INLINE MixColumn(uint8x16_t& Wa, uint8x16_t& Wb, uint8x16_t& Wc, uint8x16_t& Wd)
      29             : {
      30   248310191 :     const uint8x16_t a = Wa;
      31   248310191 :     const uint8x16_t b = Wb;
      32   248310191 :     const uint8x16_t c = Wc;
      33   248310191 :     const uint8x16_t d = Wd;
      34             : 
      35   248310191 :     const uint8x16_t ab = util::Xor(a, b);
      36   248310191 :     const uint8x16_t bc = util::Xor(b, c);
      37   248310191 :     const uint8x16_t cd = util::Xor(c, d);
      38             : 
      39   248310191 :     const uint8x16_t abx = gf8_mul2(ab);
      40   248310191 :     const uint8x16_t bcx = gf8_mul2(bc);
      41   248310191 :     const uint8x16_t cdx = gf8_mul2(cd);
      42             : 
      43             :     // Wa = abx ^ bc ^ d
      44   248310191 :     Wa = util::Xor(util::Xor(abx, bc), d);
      45             :     // Wb = bcx ^ a ^ cd
      46   248310191 :     Wb = util::Xor(util::Xor(bcx, a), cd);
      47             :     // Wc = cdx ^ ab ^ d
      48   248310191 :     Wc = util::Xor(util::Xor(cdx, ab), d);
      49             :     // Wd = abx ^ bcx ^ cdx ^ ab ^ c
      50   248310191 :     Wd = util::Xor(util::Xor(util::Xor(util::Xor(abx, bcx), cdx), ab), c);
      51   248310191 : }
      52             : 
      53    62097928 : void ALWAYS_INLINE ShiftRow1(uint8x16_t& Wa, uint8x16_t& Wb, uint8x16_t& Wc, uint8x16_t& Wd)
      54             : {
      55    62097928 :     uint8x16_t tmp = Wa;
      56    62097928 :     Wa = Wb;
      57    62097928 :     Wb = Wc;
      58    62097928 :     Wc = Wd;
      59    62097928 :     Wd = tmp;
      60    62097928 : }
      61             : 
      62    62099165 : void ALWAYS_INLINE ShiftRow2(uint8x16_t& Wa, uint8x16_t& Wb, uint8x16_t& Wc, uint8x16_t& Wd)
      63             : {
      64    62099165 :     uint8x16_t tmp1 = Wa;
      65    62099165 :     uint8x16_t tmp2 = Wb;
      66    62099165 :     Wa = Wc;
      67    62099165 :     Wb = Wd;
      68    62099165 :     Wc = tmp1;
      69    62099165 :     Wd = tmp2;
      70    62099165 : }
      71             : 
      72    62099052 : void ALWAYS_INLINE ShiftRow3(uint8x16_t& Wa, uint8x16_t& Wb, uint8x16_t& Wc, uint8x16_t& Wd)
      73             : {
      74    62099052 :     uint8x16_t tmp = Wd;
      75    62099052 :     Wd = Wc;
      76    62099052 :     Wc = Wb;
      77    62099052 :     Wb = Wa;
      78    62099052 :     Wa = tmp;
      79    62099052 : }
      80             : } // anonymous namespace
      81             : 
      82             : namespace arm_neon_echo {
      83    62097477 : void ShiftAndMix(uint64_t W[16][2])
      84             : {
      85             :     alignas(16) uint8x16_t w[16];
      86    62097477 :     w[0] = vreinterpretq_u8_u64(vld1q_u64(&W[0][0]));
      87    62097477 :     w[1] = vreinterpretq_u8_u64(vld1q_u64(&W[1][0]));
      88    62097477 :     w[2] = vreinterpretq_u8_u64(vld1q_u64(&W[2][0]));
      89    62097477 :     w[3] = vreinterpretq_u8_u64(vld1q_u64(&W[3][0]));
      90    62097477 :     w[4] = vreinterpretq_u8_u64(vld1q_u64(&W[4][0]));
      91    62097477 :     w[5] = vreinterpretq_u8_u64(vld1q_u64(&W[5][0]));
      92    62097477 :     w[6] = vreinterpretq_u8_u64(vld1q_u64(&W[6][0]));
      93    62097477 :     w[7] = vreinterpretq_u8_u64(vld1q_u64(&W[7][0]));
      94    62097477 :     w[8] = vreinterpretq_u8_u64(vld1q_u64(&W[8][0]));
      95    62097477 :     w[9] = vreinterpretq_u8_u64(vld1q_u64(&W[9][0]));
      96    62097477 :     w[10] = vreinterpretq_u8_u64(vld1q_u64(&W[10][0]));
      97    62097477 :     w[11] = vreinterpretq_u8_u64(vld1q_u64(&W[11][0]));
      98    62097477 :     w[12] = vreinterpretq_u8_u64(vld1q_u64(&W[12][0]));
      99    62097477 :     w[13] = vreinterpretq_u8_u64(vld1q_u64(&W[13][0]));
     100    62097477 :     w[14] = vreinterpretq_u8_u64(vld1q_u64(&W[14][0]));
     101    62097477 :     w[15] = vreinterpretq_u8_u64(vld1q_u64(&W[15][0]));
     102             : 
     103    62097477 :     ShiftRow1(w[1], w[5], w[9], w[13]);
     104    62097477 :     ShiftRow2(w[2], w[6], w[10], w[14]);
     105    62097477 :     ShiftRow3(w[3], w[7], w[11], w[15]);
     106             : 
     107    62097477 :     MixColumn(w[0], w[1], w[2], w[3]);
     108    62097477 :     MixColumn(w[4], w[5], w[6], w[7]);
     109    62097477 :     MixColumn(w[8], w[9], w[10], w[11]);
     110    62097477 :     MixColumn(w[12], w[13], w[14], w[15]);
     111             : 
     112    62097477 :     vst1q_u64(&W[0][0], vreinterpretq_u64_u8(w[0]));
     113    62097477 :     vst1q_u64(&W[1][0], vreinterpretq_u64_u8(w[1]));
     114    62097477 :     vst1q_u64(&W[2][0], vreinterpretq_u64_u8(w[2]));
     115    62097477 :     vst1q_u64(&W[3][0], vreinterpretq_u64_u8(w[3]));
     116    62097477 :     vst1q_u64(&W[4][0], vreinterpretq_u64_u8(w[4]));
     117    62097477 :     vst1q_u64(&W[5][0], vreinterpretq_u64_u8(w[5]));
     118    62097477 :     vst1q_u64(&W[6][0], vreinterpretq_u64_u8(w[6]));
     119    62097477 :     vst1q_u64(&W[7][0], vreinterpretq_u64_u8(w[7]));
     120    62097477 :     vst1q_u64(&W[8][0], vreinterpretq_u64_u8(w[8]));
     121    62097477 :     vst1q_u64(&W[9][0], vreinterpretq_u64_u8(w[9]));
     122    62097477 :     vst1q_u64(&W[10][0], vreinterpretq_u64_u8(w[10]));
     123    62097477 :     vst1q_u64(&W[11][0], vreinterpretq_u64_u8(w[11]));
     124    62097477 :     vst1q_u64(&W[12][0], vreinterpretq_u64_u8(w[12]));
     125    62097477 :     vst1q_u64(&W[13][0], vreinterpretq_u64_u8(w[13]));
     126    62097477 :     vst1q_u64(&W[14][0], vreinterpretq_u64_u8(w[14]));
     127    62097477 :     vst1q_u64(&W[15][0], vreinterpretq_u64_u8(w[15]));
     128    62097477 : }
     129             : } // namespace arm_neon_echo
     130             : } // namespace sapphire
     131             : 
     132             : #endif // ENABLE_ARM_NEON

Generated by: LCOV version 1.16