/* ------------------------------------------ * Copyright (c) 2016, Synopsys, Inc. All rights reserved. * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1) Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * 2) Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation and/or * other materials provided with the distribution. * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * \version 2016.05 * \date 2014-06-12 * \author Wayne Ren(Wei.Ren@synopsys.com) --------------------------------------------- */ /** * \file * \ingroup ARC_HAL_BUILTIN * \brief header file of builtin and helper functions * * The Metaware toolchain and the GNU toolchain are supported. The details please go to see the file. */ /** * \addtogroup ARC_HAL_BUILTIN * @{ */ #ifndef _ARC_HAL_BUILTIN_H_ #define _ARC_HAL_BUILTIN_H_ #include "inc/embARC_toolchain.h" #ifdef __cplusplus extern "C" { #endif #if defined (__MW__) /* Metaware toolchain */ #define _arc_nop _nop /*!< no operation, generate a nop instruction produces a single NOP instruction in the compiled code */ #define _arc_brk _brk /*!< generate a brk instruction */ #define _arc_clri _clri /*!< generate a clri instruction */ #define _arc_seti(c) _seti(c) /*!< generate a seti instruction */ #define _arc_core_write(regno, val) _core_write(val, regno) /*!< write core register */ #define _arc_core_read(regno) _core_read(regno) /*!< read core register */ #define _arc_lr_reg(aux) _lr(aux) /*!< read auxiliary register */ #define _arc_sr_reg(aux, val) _sr(val, aux) /*!< write auxiliary register */ #define _arc_sleep(a) _sleep(a) /*!< generate a sleep instruction */ #define _arc_flag(a) _flag(a) /*!< generate a flag instruction */ #define _arc_kflag(a) #define _arc_sync _sync /*!< generate a sync instruction */ /* * !< _arc_usually (expr) evaluates expression expr and * informs the compiler that the value is usually true. */ #define _arc_usually(a) _Usually((a)) /* * !< _arc_rarely (expr) evaluates expression expr and * informs the compiler that the value is rarely true. */ #define _arc_rarely(a) _Rarely((a)) #if 0 /** * \brief Reverses the byte order of the 16-bit operand, * reversing the endianness of the value. * Not for ARC HS family */ #define _arc_swap16(a) _swap16(a) /** * \brief Reverses the byte order of the 32-bit operand, * reversing the endianness of the value. * Not for ARC HS family */ #define _arc_swap32(a) _swap32(a) #else Inline uint32_t _arc_swap32(uint32_t val) { register uint32_t v; __asm__ volatile ("swape %0, %1" :"=r"(v): "r"(val)); return v; } Inline uint16_t _arc_swap16(uint32_t val) { register uint32_t temp; register uint32_t v; __asm__ volatile ("swape %0, %1" :"=r"(temp): "r"(val)); __asm__ volatile ("lsr16 %0, %1" :"=r"(v): "r"(temp)); return (unsigned short)v; } #endif /** * \brief Each call to _swi() generates one * software interrupt instruction (SWI) for processors * to support the SWI instruction. */ #define _arc_swi _swi /* \todo add more builtin functions of metaware tool */ #elif defined (__GNU__) /* GNU toolchain */ #define _arc_nop __builtin_arc_nop #define _arc_brk __builtin_arc_brk #define _arc_seti(c) __builtin_arc_seti(c) #define _arc_core_write(regno, val) __builtin_arc_core_write(regno,val) #define _arc_core_read(regno) __builtin_arc_core_read(regno) #define _arc_flag(a) __builtin_arc_flag(a) #define _arc_kflag(a) __builtin_arc_kflag(a) #define _arc_lr_reg(aux) __builtin_arc_lr(aux) /* don't uncomment this now */ //#define _arc_sr_reg(aux, val) __builtin_arc_sr(aux, val) #define _arc_sleep(a) __builtin_arc_sleep(a) //#define _arc_sync __builtin_arc_sync /** * \brief _arc_usually (expr) evaluates expression expr and * informs the compiler that the value is usually true. */ #define _arc_usually(a) __builtin_expect((int)(a), 1) /** * \brief _arc_rarely (expr) evaluates expression expr and * informs the compiler that the value is rarely true. */ #define _arc_rarely(a) __builtin_expect((int)(a), 0) /** * \brief Each call to _swi() generates one * software interrupt instruction (SWI) for processors * to support the SWI instruction. */ #define _arc_swi __builtin_arc_swi Inline uint32_t _arc_clri(void) { register uint32_t v; __asm__ volatile ("clri %0" :"=r"(v)); return v; } /* \todo add more builtin functions of gnu tool */ Inline uint32_t _arc_swap32(uint32_t val) { register uint32_t v; __asm__ volatile ("swape %0, %1" :"=r"(v): "r"(val)); return v; } Inline uint16_t _arc_swap16(uint32_t val) { register uint32_t temp; register uint32_t v; __asm__ volatile ("swape %0, %1" :"=r"(temp): "r"(val)); __asm__ volatile ("lsr16 %0, %1" :"=r"(v): "r"(temp)); return (unsigned short)v; } Inline void _arc_sync(void) { __asm__ volatile ("sync"); } /** * \note Following is a workaround for arc gcc * built-in function __builtin_arc_sr. * But it is wrong in GCC arc-4.8-R3-rc3 and shouldn't be used. */ /* * The auxiliary register address is specified as a long immediate operand by caller. * e.g. * write_aux_reg(0x69, some_val); * This generates the tightest code. */ #define write_aux_reg(reg_imm, val) \ ({ \ Asm( \ " sr %0, [%1] \n" \ : \ : "ir"(val), "r"(reg_imm)); \ }) #define _arc_sr_reg(aux, val) write_aux_reg(aux, val) #endif /* \todo add more helper functions here, such as memory operation */ #define _arc_aux_read(aux) _arc_lr_reg(aux) #define _arc_aux_write(aux, val) _arc_sr_reg(aux, val) /** * \name cache related helper function * @{ */ /** * \brief read memory and bypass the cache * \param[in] ptr memory address * \return value in the memory */ Inline uint32_t _arc_read_uncached_32(void *ptr) { uint32_t __ret; Asm("ld.di %0, [%1]":"=r"(__ret):"r"(ptr)); return __ret; } /** * \brief write memory and bypass the cache * \param[in] ptr memory address * \param[in] data vaule to be written */ Inline void _arc_write_uncached_32(void *ptr, uint32_t data) { Asm("st.di %0, [%1]":: "r"(data), "r"(ptr)); } /** * \brief read memory with cache * \param[in] ptr memory address * \returns value in the memory */ Inline uint32_t _arc_read_cached_32(void *ptr) { uint32_t __ret; Asm("ld %0, [%1]":"=r"(__ret):"r"(ptr)); return __ret; } /** * \brief read memory with cache * \param[in] ptr memory address * \param[in] data vaule to be written * \return description */ Inline void _arc_write_cached_32(void *ptr, uint32_t data) { Asm("st %0, [%1]":: "r"(data), "r"(ptr)); } /** * \brief go to main function with proper arguments * \param argc argument count * \param argv argument content array * \retval return value of main function */ Inline int32_t _arc_goto_main(int argc, char **argv) { int __ret; __asm__ volatile( "mov %%r0, %1\n" "mov %%r1, %2\n" "push_s %%blink\n" "jl main\n" "pop_s %%blink\n" "mov %0, %%r0" :"=r"(__ret): "r"(argc), "r"(argv)); return (int)__ret; } #ifdef __cplusplus } #endif #if defined(LIB_SECURESHIELD) && defined(LIB_SECURESHIELD_OVERRIDES) && (SECURESHIELD_VERSION == 1) #define OVERRIDE_ARC_HAL_BUILTIN_H #include "secureshield_overrides.h" #endif /** @} */ #endif /* _ARC_HAL_BUILTIN_H_ */ /** @} */