Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | /* * Copyright (c) 2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #ifndef _ASM_INLINE_GCC_H #define _ASM_INLINE_GCC_H #ifdef __cplusplus extern "C" { #endif /* * The file must not be included directly * Include arch/cpu.h instead */ #ifndef _ASMLANGUAGE #include <sys_io.h> #include <toolchain.h> /** * * @brief find most significant bit set in a 32-bit word * * This routine finds the first bit set starting from the most significant bit * in the argument passed in and returns the index of that bit. Bits are * numbered starting at 1 from the least significant bit. A return value of * zero indicates that the value passed is zero. * * @return most significant bit set, 0 if @a op is 0 */ static ALWAYS_INLINE unsigned int find_msb_set(u32_t op) { if (!op) return 0; return 32 - __builtin_clz(op); } /** * * @brief find least significant bit set in a 32-bit word * * This routine finds the first bit set starting from the least significant bit * in the argument passed in and returns the index of that bit. Bits are * numbered starting at 1 from the least significant bit. A return value of * zero indicates that the value passed is zero. * * @return least significant bit set, 0 if @a op is 0 */ static ALWAYS_INLINE unsigned int find_lsb_set(u32_t op) { return __builtin_ffs(op); } /* Using the *io variants of these instructions to prevent issues on * devices that have an instruction/data cache */ static ALWAYS_INLINE void sys_write32(u32_t data, mm_reg_t addr) { __builtin_stwio((void *)addr, data); } static ALWAYS_INLINE u32_t sys_read32(mm_reg_t addr) { return __builtin_ldwio((void *)addr); } static ALWAYS_INLINE void sys_write8(u8_t data, mm_reg_t addr) { sys_write32(data, addr); } static ALWAYS_INLINE u8_t sys_read8(mm_reg_t addr) { return __builtin_ldbuio((void *)addr); } static ALWAYS_INLINE void sys_write16(u16_t data, mm_reg_t addr) { sys_write32(data, addr); } static ALWAYS_INLINE u16_t sys_read16(mm_reg_t addr) { return __builtin_ldhuio((void *)addr); } /* NIOS II does not have any special instructions for manipulating bits, * so just read, modify, write in C */ static ALWAYS_INLINE void sys_set_bit(mem_addr_t addr, unsigned int bit) { sys_write32(sys_read32(addr) | (1 << bit), addr); } static ALWAYS_INLINE void sys_clear_bit(mem_addr_t addr, unsigned int bit) { sys_write32(sys_read32(addr) & ~(1 << bit), addr); } static ALWAYS_INLINE int sys_test_bit(mem_addr_t addr, unsigned int bit) { return sys_read32(addr) & (1 << bit); } /* These are not required to be atomic, just do it in C */ static ALWAYS_INLINE int sys_test_and_set_bit(mem_addr_t addr, unsigned int bit) { int ret; ret = sys_test_bit(addr, bit); sys_set_bit(addr, bit); return ret; } static ALWAYS_INLINE int sys_test_and_clear_bit(mem_addr_t addr, unsigned int bit) { int ret; ret = sys_test_bit(addr, bit); sys_clear_bit(addr, bit); return ret; } static ALWAYS_INLINE void sys_bitfield_set_bit(mem_addr_t addr, unsigned int bit) { /* Doing memory offsets in terms of 32-bit values to prevent * alignment issues */ sys_set_bit(addr + ((bit >> 5) << 2), bit & 0x1F); } static ALWAYS_INLINE void sys_bitfield_clear_bit(mem_addr_t addr, unsigned int bit) { sys_clear_bit(addr + ((bit >> 5) << 2), bit & 0x1F); } static ALWAYS_INLINE int sys_bitfield_test_bit(mem_addr_t addr, unsigned int bit) { return sys_test_bit(addr + ((bit >> 5) << 2), bit & 0x1F); } static ALWAYS_INLINE int sys_bitfield_test_and_set_bit(mem_addr_t addr, unsigned int bit) { int ret; ret = sys_bitfield_test_bit(addr, bit); sys_bitfield_set_bit(addr, bit); return ret; } static ALWAYS_INLINE int sys_bitfield_test_and_clear_bit(mem_addr_t addr, unsigned int bit) { int ret; ret = sys_bitfield_test_bit(addr, bit); sys_bitfield_clear_bit(addr, bit); return ret; } #endif /* _ASMLANGUAGE */ #ifdef __cplusplus } #endif #endif /* _ASM_INLINE_GCC_PUBLIC_GCC_H */ |