| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- /*
- * Copyright (c) 2019 Nuclei Limited. All rights reserved.
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Licensed under the Apache License, Version 2.0 (the License); you may
- * not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an AS IS BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- #ifndef __CORE_COMPATIABLE_H__
- #define __CORE_COMPATIABLE_H__
- /*!
- * @file core_compatiable.h
- * @brief ARM compatiable function definitions header file
- */
- #ifdef __cplusplus
- extern "C" {
- #endif
- #include "core_feature_base.h"
- /* ===== ARM Compatiable Functions ===== */
- /**
- * \defgroup NMSIS_Core_ARMCompatiable_Functions ARM Compatiable Functions
- * \ingroup NMSIS_Core
- * \brief A few functions that compatiable with ARM CMSIS-Core.
- * \details
- *
- * Here we provided a few functions that compatiable with ARM CMSIS-Core,
- * mostly used in the DSP and NN library.
- * @{
- */
- /** \brief Instruction Synchronization Barrier, compatiable with ARM */
- #define __ISB() __RWMB()
- /** \brief Data Synchronization Barrier, compatiable with ARM */
- #define __DSB() __RWMB()
- /** \brief Data Memory Barrier, compatiable with ARM */
- #define __DMB() __RWMB()
- /** \brief LDRT Unprivileged (8 bit), ARM Compatiable */
- #define __LDRBT(ptr) __LB((ptr))
- /** \brief LDRT Unprivileged (16 bit), ARM Compatiable */
- #define __LDRHT(ptr) __LH((ptr))
- /** \brief LDRT Unprivileged (32 bit), ARM Compatiable */
- #define __LDRT(ptr) __LW((ptr))
- /** \brief STRT Unprivileged (8 bit), ARM Compatiable */
- #define __STRBT(val, ptr) __SB((ptr), (val))
- /** \brief STRT Unprivileged (16 bit), ARM Compatiable */
- #define __STRHT(val, ptr) __SH((ptr), (val))
- /** \brief STRT Unprivileged (32 bit), ARM Compatiable */
- #define __STRT(val, ptr) __SW((ptr), (val))
- /* ===== Saturation Operations ===== */
- /**
- * \brief Signed Saturate
- * \details Saturates a signed value.
- * \param [in] value Value to be saturated
- * \param [in] sat Bit position to saturate to (1..32)
- * \return Saturated value
- */
- #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1)
- #define __SSAT(val, sat) __RV_SCLIP32((val), (sat-1))
- #else
- __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat)
- {
- if ((sat >= 1U) && (sat <= 32U)) {
- const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U);
- const int32_t min = -1 - max ;
- if (val > max) {
- return max;
- } else if (val < min) {
- return min;
- }
- }
- return val;
- }
- #endif
- /**
- * \brief Unsigned Saturate
- * \details Saturates an unsigned value.
- * \param [in] value Value to be saturated
- * \param [in] sat Bit position to saturate to (0..31)
- * \return Saturated value
- */
- #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1)
- #define __USAT(val, sat) __RV_UCLIP32((val), (sat))
- #else
- __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat)
- {
- if (sat <= 31U) {
- const uint32_t max = ((1U << sat) - 1U);
- if (val > (int32_t)max) {
- return max;
- } else if (val < 0) {
- return 0U;
- }
- }
- return (uint32_t)val;
- }
- #endif
- /* ===== Data Processing Operations ===== */
- /**
- * \brief Reverse byte order (32 bit)
- * \details Reverses the byte order in unsigned integer value.
- * For example, 0x12345678 becomes 0x78563412.
- * \param [in] value Value to reverse
- * \return Reversed value
- */
- __STATIC_FORCEINLINE uint32_t __REV(uint32_t value)
- {
- uint32_t result;
- result = ((value & 0xff000000) >> 24)
- | ((value & 0x00ff0000) >> 8 )
- | ((value & 0x0000ff00) << 8 )
- | ((value & 0x000000ff) << 24);
- return result;
- }
- /**
- * \brief Reverse byte order (16 bit)
- * \details Reverses the byte order within each halfword of a word.
- * For example, 0x12345678 becomes 0x34127856.
- * \param [in] value Value to reverse
- * \return Reversed value
- */
- __STATIC_FORCEINLINE uint32_t __REV16(uint32_t value)
- {
- uint32_t result;
- result = ((value & 0xff000000) >> 8)
- | ((value & 0x00ff0000) << 8 )
- | ((value & 0x0000ff00) >> 8 )
- | ((value & 0x000000ff) << 8) ;
- return result;
- }
- /**
- * \brief Reverse byte order (16 bit)
- * \details Reverses the byte order in a 16-bit value
- * and returns the signed 16-bit result.
- * For example, 0x0080 becomes 0x8000.
- * \param [in] value Value to reverse
- * \return Reversed value
- */
- __STATIC_FORCEINLINE int16_t __REVSH(int16_t value)
- {
- int16_t result;
- result = ((value & 0xff00) >> 8) | ((value & 0x00ff) << 8);
- return result;
- }
- /**
- * \brief Rotate Right in unsigned value (32 bit)
- * \details Rotate Right (immediate) provides the value of
- * the contents of a register rotated by a variable number of bits.
- * \param [in] op1 Value to rotate
- * \param [in] op2 Number of Bits to rotate(0-31)
- * \return Rotated value
- */
- __STATIC_FORCEINLINE uint32_t __ROR(uint32_t op1, uint32_t op2)
- {
- op2 = op2 & 0x1F;
- if (op2 == 0U) {
- return op1;
- }
- return (op1 >> op2) | (op1 << (32U - op2));
- }
- /**
- * \brief Rotate Right in uint32x2 value (64 bit)
- * \details Rotate Right (immediate) provides the value of
- * the contents of a register rotated by a variable number of bits.
- * \param [in] op1 Value to rotate([63:32] and [31:0] rotate separately)
- * \param [in] op2 Number of Bits to rotate
- * \return Rotated value([63:32] | [31:0])
- */
- __STATIC_INLINE uint64_t __ROR64(uint64_t op1, uint32_t op2)
- {
- op2 = op2 & 0x1F;
- if (op2 == 0U) {
- return op1;
- }
- uint32_t tmp1 = (uint32_t)op1;
- uint32_t tmp2 = (uint32_t)(op1 >> 32);
- return (uint64_t)((tmp1 >> op2) | (tmp1 << (32U - op2)))
- | ((uint64_t)((tmp2 >> op2) | (tmp2 << (32U - op2))) << 32);
- }
- /**
- * \brief Reverse bit order of value
- * \details Reverses the bit order of the given value.
- * \param [in] value Value to reverse
- * \return Reversed value
- */
- #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1)
- #define __RBIT(value) __RV_BITREVI((value), 31)
- #else
- __STATIC_INLINE uint32_t __RBIT(uint32_t value)
- {
- uint32_t result;
- uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */
- result = value; /* r will be reversed bits of v; first get LSB of v */
- for (value >>= 1U; value != 0U; value >>= 1U) {
- result <<= 1U;
- result |= value & 1U;
- s--;
- }
- result <<= s; /* shift when v's highest bits are zero */
- return result;
- }
- #endif /* defined(__DSP_PRESENT) && (__DSP_PRESENT == 1) */
- /**
- * \brief Count leading zeros
- * \details Counts the number of leading zeros of a data value.
- * \param [in] data Value to count the leading zeros
- * \return number of leading zeros in value
- */
- #if defined(__DSP_PRESENT) && (__DSP_PRESENT == 1)
- #define __CLZ(data) __RV_CLZ32(data)
- #else
- __STATIC_INLINE uint8_t __CLZ(uint32_t data)
- {
- uint8_t ret = 0;
- uint32_t temp = ~data;
- while (temp & 0x80000000) {
- temp <<= 1;
- ret++;
- }
- return ret;
- }
- #endif /* defined(__DSP_PRESENT) && (__DSP_PRESENT == 1) */
- /**
- * \brief Count tailing zero
- * \details Return the count of least-significant bit zero.for example, return 3 if x=0bxxx1000
- * \param [in] data Value to count the tailing zeros
- * \return number of tailing zeros in value
- * \remark
- * - The value mustn't be 0, or else it will spin here
- */
- __STATIC_INLINE unsigned long __CTZ(unsigned long data)
- {
- unsigned long ret = 0;
- while (!(data & 1UL)) {
- ret++;
- data = data >> 1;
- }
- return ret;
- }
- /**
- * \brief Expand byte to unsigned long value
- * \details Expand byte value x to unsigned long value's each byte.
- * \param [in] x the byte value to be expand, the input must be uint8_t type
- * \return Expanded value in unsigned long
- */
- #if __RISCV_XLEN == 32
- #define __EXPD_BYTE(x) ((unsigned long)(((unsigned long)(x) << 0) | \
- ((unsigned long)(x) << 8) | \
- ((unsigned long)(x) << 16) | \
- ((unsigned long)(x) << 24)))
- #elif __RISCV_XLEN == 64
- #define __EXPD_BYTE(x) ((unsigned long)(((unsigned long)(x) << 0) | \
- ((unsigned long)(x) << 8) | \
- ((unsigned long)(x) << 16) | \
- ((unsigned long)(x) << 24) | \
- ((unsigned long)(x) << 32) | \
- ((unsigned long)(x) << 40) | \
- ((unsigned long)(x) << 48) | \
- ((unsigned long)(x) << 56)))
- #endif
- /** @} */ /* End of Doxygen Group NMSIS_Core_ARMCompatiable_Functions */
- #ifdef __cplusplus
- }
- #endif
- #endif /* __CORE_COMPATIABLE_H__ */
|