LCOV - code coverage report
Current view: top level - src/internal - bswap.h (source / functions) Coverage Total Hit
Test: pino Coverage Report Lines: 100.0 % 51 51
Test Date: 2026-01-22 09:45:38 Functions: 100.0 % 1 1
Legend: Lines: hit not hit

            Line data    Source code
       1              : /*
       2              :  * libpino - bswap.h
       3              :  *
       4              :  * This file is part of libpino.
       5              :  *
       6              :  * Author: Go Kudo <zeriyoshi@gmail.com>
       7              :  * SPDX-License-Identifier: MIT
       8              :  */
       9              : 
      10              : #ifndef PINO_INTERNAL_BSWAP_H
      11              : #define PINO_INTERNAL_BSWAP_H
      12              : 
      13              : #include <stddef.h>
      14              : #include <stdint.h>
      15              : #include <string.h>
      16              : 
      17              : #include <pino/portable.h>
      18              : 
      19              : #if PINO_USE_SIMD
      20              : #include "simd.h"
      21              : #endif
      22              : 
      23           49 : static inline void *pino_bswap_memcpy(void *dest, const void *src, size_t size, size_t elem_size)
      24              : {
      25              :     const uint8_t *sp;
      26              :     uint64_t *dest64, *src64;
      27              :     uint32_t *dest32, *src32;
      28              :     uint16_t *dest16, *src16;
      29              :     uint8_t *dp;
      30              :     size_t i, j, num_elements;
      31              : 
      32              : #if PINO_USE_SIMD && defined(PINO_SIMD_AVX2)
      33              :     __m256i shuffle_mask, data;
      34              :     size_t simd_elements;
      35              : 
      36           49 :     dp = (uint8_t *)dest;
      37           49 :     sp = (const uint8_t *)src;
      38              : 
      39           49 :     if (elem_size == 1 || size == 0) {
      40            4 :         return memcpy(dest, src, size);
      41              :     }
      42              : 
      43           45 :     if (size % elem_size != 0) {
      44            1 :         return memcpy(dest, src, size);
      45              :     }
      46              : 
      47           44 :     if (elem_size == 2 && (((uintptr_t)dest | (uintptr_t)src) & 0x1) == 0) {
      48            6 :         dest16 = (uint16_t *)dest;
      49            6 :         src16 = (uint16_t *)src;
      50            6 :         num_elements = size / 2;
      51              : 
      52           90 :         for (i = 0; i < num_elements; i++) {
      53           84 :             dest16[i] = pino_bswap16(src16[i]);
      54              :         }
      55              : 
      56            6 :         return dest;
      57           38 :     } else if (elem_size == 4 && (((uintptr_t)dest | (uintptr_t)src) & 0x3) == 0) {
      58           23 :         dest32 = (uint32_t *)dest;
      59           23 :         src32 = (uint32_t *)src;
      60           23 :         num_elements = size / 4;
      61              : 
      62           23 :         simd_elements = num_elements / 8;
      63              : 
      64           23 :         if (simd_elements > 0) {
      65            6 :             shuffle_mask = _mm256_set_epi8(28, 29, 30, 31, 24, 25, 26, 27, 20, 21, 22, 23, 16, 17, 18, 19, 12, 13, 14,
      66              :                                            15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3);
      67              : 
      68           24 :             for (i = 0; i < simd_elements; i++) {
      69           36 :                 data = _mm256_loadu_si256((__m256i *)(src32 + i * 8));
      70           18 :                 data = _mm256_shuffle_epi8(data, shuffle_mask);
      71           18 :                 _mm256_storeu_si256((__m256i *)(dest32 + i * 8), data);
      72              :             }
      73              : 
      74            6 :             i = simd_elements * 8;
      75              :         } else {
      76           17 :             i = 0;
      77              :         }
      78              : 
      79           47 :         for (; i < num_elements; i++) {
      80           24 :             dest32[i] = pino_bswap32(src32[i]);
      81              :         }
      82              : 
      83           23 :         return dest;
      84           15 :     } else if (elem_size == 8 && (((uintptr_t)dest | (uintptr_t)src) & 0x7) == 0) {
      85           12 :         dest64 = (uint64_t *)dest;
      86           12 :         src64 = (uint64_t *)src;
      87           12 :         num_elements = size / 8;
      88              : 
      89           12 :         simd_elements = num_elements / 4;
      90              : 
      91           12 :         if (simd_elements > 0) {
      92            5 :             shuffle_mask = _mm256_set_epi8(24, 25, 26, 27, 28, 29, 30, 31, 16, 17, 18, 19, 20, 21, 22, 23, 8, 9, 10, 11,
      93              :                                            12, 13, 14, 15, 0, 1, 2, 3, 4, 5, 6, 7);
      94              : 
      95           21 :             for (i = 0; i < simd_elements; i++) {
      96           32 :                 data = _mm256_loadu_si256((__m256i *)(src64 + i * 4));
      97           16 :                 data = _mm256_shuffle_epi8(data, shuffle_mask);
      98           16 :                 _mm256_storeu_si256((__m256i *)(dest64 + i * 4), data);
      99              :             }
     100              : 
     101            5 :             i = simd_elements * 4;
     102              :         } else {
     103            7 :             i = 0;
     104              :         }
     105              : 
     106           22 :         for (; i < num_elements; i++) {
     107           10 :             dest64[i] = pino_bswap64(src64[i]);
     108              :         }
     109              : 
     110           12 :         return dest;
     111              :     }
     112              : 
     113            3 :     num_elements = size / elem_size;
     114           13 :     for (i = 0; i < num_elements; i++) {
     115           46 :         for (j = 0; j < elem_size; j++) {
     116           36 :             dp[i * elem_size + j] = sp[i * elem_size + (elem_size - 1 - j)];
     117              :         }
     118              :     }
     119              : 
     120            3 :     return dest;
     121              : 
     122              : #elif PINO_USE_SIMD && defined(PINO_SIMD_NEON)
     123              :     uint16x8_t data16;
     124              :     uint32x4_t data32;
     125              :     uint64x2_t data64;
     126              :     size_t simd_elements;
     127              : 
     128              :     dp = (uint8_t *)dest;
     129              :     sp = (const uint8_t *)src;
     130              : 
     131              :     if (elem_size == 1 || size == 0) {
     132              :         return memcpy(dest, src, size);
     133              :     }
     134              : 
     135              :     if (size % elem_size != 0) {
     136              :         return memcpy(dest, src, size);
     137              :     }
     138              : 
     139              :     if (elem_size == 2 && (((uintptr_t)dest | (uintptr_t)src) & 0x1) == 0) {
     140              :         dest16 = (uint16_t *)dest;
     141              :         src16 = (uint16_t *)src;
     142              :         num_elements = size / 2;
     143              : 
     144              :         simd_elements = num_elements / 8;
     145              : 
     146              :         for (i = 0; i < simd_elements; i++) {
     147              :             data16 = vld1q_u16(src16 + i * 8);
     148              :             data16 = vreinterpretq_u16_u8(vrev16q_u8(vreinterpretq_u8_u16(data16)));
     149              :             vst1q_u16(dest16 + i * 8, data16);
     150              :         }
     151              : 
     152              :         i = simd_elements * 8;
     153              :         for (; i < num_elements; i++) {
     154              :             dest16[i] = pino_bswap16(src16[i]);
     155              :         }
     156              : 
     157              :         return dest;
     158              :     } else if (elem_size == 4 && (((uintptr_t)dest | (uintptr_t)src) & 0x3) == 0) {
     159              :         dest32 = (uint32_t *)dest;
     160              :         src32 = (uint32_t *)src;
     161              :         num_elements = size / 4;
     162              : 
     163              :         simd_elements = num_elements / 4;
     164              : 
     165              :         for (i = 0; i < simd_elements; i++) {
     166              :             data32 = vld1q_u32(src32 + i * 4);
     167              :             data32 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(data32)));
     168              :             vst1q_u32(dest32 + i * 4, data32);
     169              :         }
     170              : 
     171              :         i = simd_elements * 4;
     172              :         for (; i < num_elements; i++) {
     173              :             dest32[i] = pino_bswap32(src32[i]);
     174              :         }
     175              : 
     176              :         return dest;
     177              :     } else if (elem_size == 8 && (((uintptr_t)dest | (uintptr_t)src) & 0x7) == 0) {
     178              :         dest64 = (uint64_t *)dest;
     179              :         src64 = (uint64_t *)src;
     180              :         num_elements = size / 8;
     181              : 
     182              :         simd_elements = num_elements / 2;
     183              : 
     184              :         for (i = 0; i < simd_elements; i++) {
     185              :             data64 = vld1q_u64(src64 + i * 2);
     186              :             data64 = vreinterpretq_u64_u8(vrev64q_u8(vreinterpretq_u8_u64(data64)));
     187              :             vst1q_u64(dest64 + i * 2, data64);
     188              :         }
     189              : 
     190              :         i = simd_elements * 2;
     191              :         for (; i < num_elements; i++) {
     192              :             dest64[i] = pino_bswap64(src64[i]);
     193              :         }
     194              : 
     195              :         return dest;
     196              :     }
     197              : 
     198              :     num_elements = size / elem_size;
     199              :     for (i = 0; i < num_elements; i++) {
     200              :         for (j = 0; j < elem_size; j++) {
     201              :             dp[i * elem_size + j] = sp[i * elem_size + (elem_size - 1 - j)];
     202              :         }
     203              :     }
     204              : 
     205              :     return dest;
     206              : 
     207              : #elif PINO_USE_SIMD && defined(PINO_SIMD_WASM)
     208              :     v128_t data;
     209              :     size_t simd_elements;
     210              : 
     211              :     dp = (uint8_t *)dest;
     212              :     sp = (const uint8_t *)src;
     213              : 
     214              :     if (elem_size == 1 || size == 0) {
     215              :         return memcpy(dest, src, size);
     216              :     }
     217              : 
     218              :     if (size % elem_size != 0) {
     219              :         return memcpy(dest, src, size);
     220              :     }
     221              : 
     222              :     if (elem_size == 2 && (((uintptr_t)dest | (uintptr_t)src) & 0x1) == 0) {
     223              :         dest16 = (uint16_t *)dest;
     224              :         src16 = (uint16_t *)src;
     225              :         num_elements = size / 2;
     226              : 
     227              :         for (i = 0; i < num_elements; i++) {
     228              :             dest16[i] = pino_bswap16(src16[i]);
     229              :         }
     230              : 
     231              :         return dest;
     232              :     } else if (elem_size == 4 && (((uintptr_t)dest | (uintptr_t)src) & 0x3) == 0) {
     233              :         dest32 = (uint32_t *)dest;
     234              :         src32 = (uint32_t *)src;
     235              :         num_elements = size / 4;
     236              : 
     237              :         simd_elements = num_elements / 4;
     238              : 
     239              :         if (simd_elements > 0) {
     240              :             for (i = 0; i < simd_elements; i++) {
     241              :                 data = wasm_v128_load(src32 + i * 4);
     242              :                 data = wasm_i8x16_shuffle(data, data, 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12);
     243              :                 wasm_v128_store(dest32 + i * 4, data);
     244              :             }
     245              : 
     246              :             i = simd_elements * 4;
     247              :         } else {
     248              :             i = 0;
     249              :         }
     250              : 
     251              :         for (; i < num_elements; i++) {
     252              :             dest32[i] = pino_bswap32(src32[i]);
     253              :         }
     254              : 
     255              :         return dest;
     256              :     } else if (elem_size == 8 && (((uintptr_t)dest | (uintptr_t)src) & 0x7) == 0) {
     257              :         dest64 = (uint64_t *)dest;
     258              :         src64 = (uint64_t *)src;
     259              :         num_elements = size / 8;
     260              : 
     261              :         simd_elements = num_elements / 2;
     262              : 
     263              :         if (simd_elements > 0) {
     264              :             for (i = 0; i < simd_elements; i++) {
     265              :                 data = wasm_v128_load(src64 + i * 2);
     266              :                 data = wasm_i8x16_shuffle(data, data, 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8);
     267              :                 wasm_v128_store(dest64 + i * 2, data);
     268              :             }
     269              : 
     270              :             i = simd_elements * 2;
     271              :         } else {
     272              :             i = 0;
     273              :         }
     274              : 
     275              :         for (; i < num_elements; i++) {
     276              :             dest64[i] = pino_bswap64(src64[i]);
     277              :         }
     278              : 
     279              :         return dest;
     280              :     }
     281              : 
     282              :     num_elements = size / elem_size;
     283              :     for (i = 0; i < num_elements; i++) {
     284              :         for (j = 0; j < elem_size; j++) {
     285              :             dp[i * elem_size + j] = sp[i * elem_size + (elem_size - 1 - j)];
     286              :         }
     287              :     }
     288              : 
     289              :     return dest;
     290              : 
     291              : #else
     292              : 
     293              :     dp = (uint8_t *)dest;
     294              :     sp = (const uint8_t *)src;
     295              : 
     296              :     if (elem_size == 1 || size == 0) {
     297              :         return memcpy(dest, src, size);
     298              :     }
     299              : 
     300              :     if (size % elem_size != 0) {
     301              :         return memcpy(dest, src, size);
     302              :     }
     303              : 
     304              :     if (elem_size == 2 && (((uintptr_t)dest | (uintptr_t)src) & 0x1) == 0) {
     305              :         dest16 = (uint16_t *)dest;
     306              :         src16 = (uint16_t *)src;
     307              :         num_elements = size / 2;
     308              : 
     309              :         for (i = 0; i < num_elements; i++) {
     310              :             dest16[i] = pino_bswap16(src16[i]);
     311              :         }
     312              : 
     313              :         return dest;
     314              :     } else if (elem_size == 4 && (((uintptr_t)dest | (uintptr_t)src) & 0x3) == 0) {
     315              :         dest32 = (uint32_t *)dest;
     316              :         src32 = (uint32_t *)src;
     317              :         num_elements = size / 4;
     318              : 
     319              :         for (i = 0; i < num_elements; i++) {
     320              :             dest32[i] = pino_bswap32(src32[i]);
     321              :         }
     322              : 
     323              :         return dest;
     324              :     } else if (elem_size == 8 && (((uintptr_t)dest | (uintptr_t)src) & 0x7) == 0) {
     325              :         dest64 = (uint64_t *)dest;
     326              :         src64 = (uint64_t *)src;
     327              :         num_elements = size / 8;
     328              : 
     329              :         for (i = 0; i < num_elements; i++) {
     330              :             dest64[i] = pino_bswap64(src64[i]);
     331              :         }
     332              : 
     333              :         return dest;
     334              :     }
     335              : 
     336              :     num_elements = size / elem_size;
     337              :     for (i = 0; i < num_elements; i++) {
     338              :         for (j = 0; j < elem_size; j++) {
     339              :             dp[i * elem_size + j] = sp[i * elem_size + (elem_size - 1 - j)];
     340              :         }
     341              :     }
     342              : 
     343              :     return dest;
     344              : #endif
     345              : }
     346              : 
     347              : #endif /* PINO_INTERNAL_BSWAP_H */
        

Generated by: LCOV version 2.0-1