diff --git a/include/arch/arc/arch.h b/include/arch/arc/arch.h index e696e93d578..9ac0f37c875 100644 --- a/include/arch/arc/arch.h +++ b/include/arch/arc/arch.h @@ -28,6 +28,7 @@ #include #include #include +#include "v2/sys_io.h" #endif #ifdef __cplusplus diff --git a/include/arch/arc/v2/asm_inline_gcc.h b/include/arch/arc/v2/asm_inline_gcc.h index 593d70e837f..90dd1a0b497 100644 --- a/include/arch/arc/v2/asm_inline_gcc.h +++ b/include/arch/arc/v2/asm_inline_gcc.h @@ -15,9 +15,6 @@ extern "C" { #ifndef _ASMLANGUAGE -#include -#include - #include #include @@ -27,287 +24,6 @@ extern "C" { extern u64_t z_tsc_read(void); -/* Implementation of sys_io.h's documented functions */ - -static ALWAYS_INLINE - void sys_out8(u8_t data, io_port_t port) -{ - z_arc_v2_aux_reg_write(port, data); -} - -static ALWAYS_INLINE - u8_t sys_in8(io_port_t port) -{ - return (u8_t)(z_arc_v2_aux_reg_read(port) & 0x000000ff); -} - -static ALWAYS_INLINE - void sys_out16(u16_t data, io_port_t port) -{ - z_arc_v2_aux_reg_write(port, data); -} - -static ALWAYS_INLINE - u16_t sys_in16(io_port_t port) -{ - return (u16_t)(z_arc_v2_aux_reg_read(port) & 0x0000ffff); -} - -static ALWAYS_INLINE - void sys_out32(u32_t data, io_port_t port) -{ - z_arc_v2_aux_reg_write(port, data); -} - -static ALWAYS_INLINE - u32_t sys_in32(io_port_t port) -{ - return z_arc_v2_aux_reg_read(port); -} - -static ALWAYS_INLINE - void sys_io_set_bit(io_port_t port, unsigned int bit) -{ - u32_t reg = 0; - - __asm__ volatile("lr %1, [%0]\n" - "bset %1, %1, %2\n" - "sr %1, [%0];\n\t" - : - : "ir" (port), - "r" (reg), "Mr" (bit) - : "memory", "cc"); -} - -static ALWAYS_INLINE - void sys_io_clear_bit(io_port_t port, unsigned int bit) -{ - u32_t reg = 0; - - __asm__ volatile("lr %1, [%0]\n" - "bclr %1, %1, %2\n" - "sr %1, [%0];\n\t" - : - : "ir" (port), - "r" (reg), "Mr" (bit) - : "memory", "cc"); -} - -static ALWAYS_INLINE - int sys_io_test_bit(io_port_t port, unsigned int bit) -{ - u32_t status = _ARC_V2_STATUS32; - u32_t reg = 0; - u32_t ret; - - __asm__ volatile("lr %2, [%1]\n" - "btst %2, %3\n" - "lr %0, [%4];\n\t" - : "=r" (ret) - : "ir" (port), - "r" (reg), "Mr" (bit), "i" (status) - : "memory", "cc"); - - return !(ret & _ARC_V2_STATUS32_Z); -} - -static ALWAYS_INLINE - int sys_io_test_and_set_bit(io_port_t port, unsigned int bit) -{ - int ret; - - ret = sys_io_test_bit(port, bit); - sys_io_set_bit(port, bit); - - return ret; -} - -static ALWAYS_INLINE - int sys_io_test_and_clear_bit(io_port_t port, unsigned int bit) -{ - int ret; - - ret = sys_io_test_bit(port, bit); - sys_io_clear_bit(port, bit); - - return ret; -} - -static ALWAYS_INLINE - void sys_write8(u8_t data, mm_reg_t addr) -{ - __asm__ volatile("stb%U1 %0, %1;\n\t" - : - : "r" (data), "m" (*(volatile u8_t *) addr) - : "memory"); -} - -static ALWAYS_INLINE - u8_t sys_read8(mm_reg_t addr) -{ - u8_t ret; - - __asm__ volatile("ldb%U1 %0, %1;\n\t" - : "=r" (ret) - : "m" (*(volatile u8_t *) addr) - : "memory"); - - return ret; -} - -static ALWAYS_INLINE - void sys_write16(u16_t data, mm_reg_t addr) -{ - __asm__ volatile("sth%U1 %0, %1;\n\t" - : - : "r" (data), "m" (*(volatile u16_t *) addr) - : "memory"); -} - -static ALWAYS_INLINE - u16_t sys_read16(mm_reg_t addr) -{ - u16_t ret; - - __asm__ volatile("ldh%U1 %0, %1;\n\t" - : "=r" (ret) - : "m" (*(volatile u16_t *) addr) - : "memory"); - - return ret; -} - -static ALWAYS_INLINE - void sys_write32(u32_t data, mm_reg_t addr) -{ - __asm__ volatile("st%U1 %0, %1;\n\t" - : - : "r" (data), "m" (*(volatile u32_t *) addr) - : "memory"); -} - -static ALWAYS_INLINE - u32_t sys_read32(mm_reg_t addr) -{ - u32_t ret; - - __asm__ volatile("ld%U1 %0, %1;\n\t" - : "=r" (ret) - : "m" (*(volatile u32_t *) addr) - : "memory"); - - return ret; -} - -static ALWAYS_INLINE - void sys_set_bit(mem_addr_t addr, unsigned int bit) -{ - u32_t reg = 0; - - __asm__ volatile("ld %1, %0\n" - "bset %1, %1, %2\n" - "st %1, %0;\n\t" - : "+m" (*(volatile u32_t *) addr) - : "r" (reg), "Mr" (bit) - : "memory", "cc"); -} - -static ALWAYS_INLINE - void sys_clear_bit(mem_addr_t addr, unsigned int bit) -{ - u32_t reg = 0; - - __asm__ volatile("ld %1, %0\n" - "bclr %1, %1, %2\n" - "st %1, %0;\n\t" - : "+m" (*(volatile u32_t *) addr) - : "r" (reg), "Mr" (bit) - : "memory", "cc"); -} - -static ALWAYS_INLINE - int sys_test_bit(mem_addr_t addr, unsigned int bit) -{ - u32_t status = _ARC_V2_STATUS32; - u32_t reg = 0; - u32_t ret; - - __asm__ volatile("ld %2, %1\n" - "btst %2, %3\n" - "lr %0, [%4];\n\t" - : "=r" (ret) - : "m" (*(volatile u32_t *) addr), - "r" (reg), "Mr" (bit), "i" (status) - : "memory", "cc"); - - return !(ret & _ARC_V2_STATUS32_Z); -} - -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 */ diff --git a/include/arch/arc/v2/sys_io.h b/include/arch/arc/v2/sys_io.h new file mode 100644 index 00000000000..84152bd98fd --- /dev/null +++ b/include/arch/arc/v2/sys_io.h @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2015 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_ARC_V2_SYS_IO_H_ +#define ZEPHYR_INCLUDE_ARCH_ARC_V2_SYS_IO_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ASMLANGUAGE + +#include +#include + +#include +#include +/* Implementation of sys_io.h's documented functions */ + +static ALWAYS_INLINE + void sys_out8(u8_t data, io_port_t port) +{ + z_arc_v2_aux_reg_write(port, data); +} + +static ALWAYS_INLINE + u8_t sys_in8(io_port_t port) +{ + return (u8_t)(z_arc_v2_aux_reg_read(port) & 0x000000ff); +} + +static ALWAYS_INLINE + void sys_out16(u16_t data, io_port_t port) +{ + z_arc_v2_aux_reg_write(port, data); +} + +static ALWAYS_INLINE + u16_t sys_in16(io_port_t port) +{ + return (u16_t)(z_arc_v2_aux_reg_read(port) & 0x0000ffff); +} + +static ALWAYS_INLINE + void sys_out32(u32_t data, io_port_t port) +{ + z_arc_v2_aux_reg_write(port, data); +} + +static ALWAYS_INLINE + u32_t sys_in32(io_port_t port) +{ + return z_arc_v2_aux_reg_read(port); +} + +static ALWAYS_INLINE + void sys_io_set_bit(io_port_t port, unsigned int bit) +{ + u32_t reg = 0; + + __asm__ volatile("lr %1, [%0]\n" + "bset %1, %1, %2\n" + "sr %1, [%0];\n\t" + : + : "ir" (port), + "r" (reg), "Mr" (bit) + : "memory", "cc"); +} + +static ALWAYS_INLINE + void sys_io_clear_bit(io_port_t port, unsigned int bit) +{ + u32_t reg = 0; + + __asm__ volatile("lr %1, [%0]\n" + "bclr %1, %1, %2\n" + "sr %1, [%0];\n\t" + : + : "ir" (port), + "r" (reg), "Mr" (bit) + : "memory", "cc"); +} + +static ALWAYS_INLINE + int sys_io_test_bit(io_port_t port, unsigned int bit) +{ + u32_t status = _ARC_V2_STATUS32; + u32_t reg = 0; + u32_t ret; + + __asm__ volatile("lr %2, [%1]\n" + "btst %2, %3\n" + "lr %0, [%4];\n\t" + : "=r" (ret) + : "ir" (port), + "r" (reg), "Mr" (bit), "i" (status) + : "memory", "cc"); + + return !(ret & _ARC_V2_STATUS32_Z); +} + +static ALWAYS_INLINE + int sys_io_test_and_set_bit(io_port_t port, unsigned int bit) +{ + int ret; + + ret = sys_io_test_bit(port, bit); + sys_io_set_bit(port, bit); + + return ret; +} + +static ALWAYS_INLINE + int sys_io_test_and_clear_bit(io_port_t port, unsigned int bit) +{ + int ret; + + ret = sys_io_test_bit(port, bit); + sys_io_clear_bit(port, bit); + + return ret; +} + +static ALWAYS_INLINE + void sys_write8(u8_t data, mm_reg_t addr) +{ + __asm__ volatile("stb%U1 %0, %1;\n\t" + : + : "r" (data), "m" (*(volatile u8_t *) addr) + : "memory"); +} + +static ALWAYS_INLINE + u8_t sys_read8(mm_reg_t addr) +{ + u8_t ret; + + __asm__ volatile("ldb%U1 %0, %1;\n\t" + : "=r" (ret) + : "m" (*(volatile u8_t *) addr) + : "memory"); + + return ret; +} + +static ALWAYS_INLINE + void sys_write16(u16_t data, mm_reg_t addr) +{ + __asm__ volatile("sth%U1 %0, %1;\n\t" + : + : "r" (data), "m" (*(volatile u16_t *) addr) + : "memory"); +} + +static ALWAYS_INLINE + u16_t sys_read16(mm_reg_t addr) +{ + u16_t ret; + + __asm__ volatile("ldh%U1 %0, %1;\n\t" + : "=r" (ret) + : "m" (*(volatile u16_t *) addr) + : "memory"); + + return ret; +} + +static ALWAYS_INLINE + void sys_write32(u32_t data, mm_reg_t addr) +{ + __asm__ volatile("st%U1 %0, %1;\n\t" + : + : "r" (data), "m" (*(volatile u32_t *) addr) + : "memory"); +} + +static ALWAYS_INLINE + u32_t sys_read32(mm_reg_t addr) +{ + u32_t ret; + + __asm__ volatile("ld%U1 %0, %1;\n\t" + : "=r" (ret) + : "m" (*(volatile u32_t *) addr) + : "memory"); + + return ret; +} + +static ALWAYS_INLINE + void sys_set_bit(mem_addr_t addr, unsigned int bit) +{ + u32_t reg = 0; + + __asm__ volatile("ld %1, %0\n" + "bset %1, %1, %2\n" + "st %1, %0;\n\t" + : "+m" (*(volatile u32_t *) addr) + : "r" (reg), "Mr" (bit) + : "memory", "cc"); +} + +static ALWAYS_INLINE + void sys_clear_bit(mem_addr_t addr, unsigned int bit) +{ + u32_t reg = 0; + + __asm__ volatile("ld %1, %0\n" + "bclr %1, %1, %2\n" + "st %1, %0;\n\t" + : "+m" (*(volatile u32_t *) addr) + : "r" (reg), "Mr" (bit) + : "memory", "cc"); +} + +static ALWAYS_INLINE + int sys_test_bit(mem_addr_t addr, unsigned int bit) +{ + u32_t status = _ARC_V2_STATUS32; + u32_t reg = 0; + u32_t ret; + + __asm__ volatile("ld %2, %1\n" + "btst %2, %3\n" + "lr %0, [%4];\n\t" + : "=r" (ret) + : "m" (*(volatile u32_t *) addr), + "r" (reg), "Mr" (bit), "i" (status) + : "memory", "cc"); + + return !(ret & _ARC_V2_STATUS32_Z); +} + +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 /* ZEPHYR_INCLUDE_ARCH_ARC_V2_SYS_IO_H_ */ diff --git a/include/arch/arm/arch.h b/include/arch/arm/arch.h index 5d3bfd4a7ac..8156bfcc3c2 100644 --- a/include/arch/arm/arch.h +++ b/include/arch/arm/arch.h @@ -30,7 +30,8 @@ #include #include #include -#include +#include +#include #include #endif diff --git a/include/arch/arm/cortex_m/asm_inline_gcc.h b/include/arch/arm/cortex_m/asm_inline_gcc.h index dac869d7e37..0243f3a3cf0 100644 --- a/include/arch/arm/cortex_m/asm_inline_gcc.h +++ b/include/arch/arm/cortex_m/asm_inline_gcc.h @@ -33,46 +33,6 @@ extern "C" { #include #include -/** - * - * @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); -} - - /** * * @brief Disable all interrupts on the CPU diff --git a/include/arch/arm/cortex_m/sys_io.h b/include/arch/arm/cortex_m/sys_io.h deleted file mode 100644 index 56a8ce78507..00000000000 --- a/include/arch/arm/cortex_m/sys_io.h +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2016 Wind River Systems, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @brief ARM CORTEX-M Series memory mapped register I/O operations - */ - -#ifndef ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_M_SYS_IO_H_ -#define ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_M_SYS_IO_H_ - -#if !defined(_ASMLANGUAGE) - -#include - -/* Memory mapped registers I/O functions */ - -static inline u8_t sys_read8(mem_addr_t addr) -{ - return *(volatile u8_t *)addr; -} - -static inline void sys_write8(u8_t data, mem_addr_t addr) -{ - *(volatile u8_t *)addr = data; -} - -static inline u16_t sys_read16(mem_addr_t addr) -{ - return *(volatile u16_t *)addr; -} - -static inline void sys_write16(u16_t data, mem_addr_t addr) -{ - *(volatile u16_t *)addr = data; -} - -static inline u32_t sys_read32(mem_addr_t addr) -{ - return *(volatile u32_t *)addr; -} - -static inline void sys_write32(u32_t data, mem_addr_t addr) -{ - *(volatile u32_t *)addr = data; -} - - -/* Memory bit manipulation functions */ - -static inline void sys_set_bit(mem_addr_t addr, unsigned int bit) -{ - u32_t temp = *(volatile u32_t *)addr; - - *(volatile u32_t *)addr = temp | BIT(bit); -} - -static inline void sys_clear_bit(mem_addr_t addr, unsigned int bit) -{ - u32_t temp = *(volatile u32_t *)addr; - - *(volatile u32_t *)addr = temp & ~BIT(bit); -} - -static inline int sys_test_bit(mem_addr_t addr, unsigned int bit) -{ - u32_t temp = *(volatile u32_t *)addr; - - return temp & BIT(bit); -} - -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); -} - -#endif /* !_ASMLANGUAGE */ - -#endif /* ZEPHYR_INCLUDE_ARCH_ARM_CORTEX_M_SYS_IO_H_ */ diff --git a/include/arch/bits_portable.h b/include/arch/bits_portable.h deleted file mode 100644 index d4496665e86..00000000000 --- a/include/arch/bits_portable.h +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2015, Wind River Systems, Inc. - * Copyright (c) 2017, Oticon A/S - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/* "Arch" bit manipulation functions in non-arch-specific C code (uses some - * gcc builtins) - */ - -#ifndef ZEPHYR_INCLUDE_ARCH_BITS_PORTABLE_H_ -#define ZEPHYR_INCLUDE_ARCH_BITS_PORTABLE_H_ - -#include -#include - -/** - * - * @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 == 0) { - 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); -} - - -static ALWAYS_INLINE u8_t sys_read8(mem_addr_t addr) -{ - return *(volatile u8_t *)addr; -} - -static ALWAYS_INLINE void sys_write8(u8_t data, mem_addr_t addr) -{ - *(volatile u8_t *)addr = data; -} - -static ALWAYS_INLINE u16_t sys_read16(mem_addr_t addr) -{ - return *(volatile u16_t *)addr; -} - -static ALWAYS_INLINE void sys_write16(u16_t data, mem_addr_t addr) -{ - *(volatile u16_t *)addr = data; -} - -static ALWAYS_INLINE u32_t sys_read32(mem_addr_t addr) -{ - return *(volatile u32_t *)addr; -} - -static ALWAYS_INLINE void sys_write32(u32_t data, mem_addr_t addr) -{ - *(volatile u32_t *)addr = data; -} - -/* Memory bit manipulation functions */ - -static ALWAYS_INLINE void sys_set_bit(mem_addr_t addr, unsigned int bit) -{ - u32_t temp = *(volatile u32_t *)addr; - - *(volatile u32_t *)addr = temp | (1 << bit); -} - -static ALWAYS_INLINE void sys_clear_bit(mem_addr_t addr, unsigned int bit) -{ - u32_t temp = *(volatile u32_t *)addr; - - *(volatile u32_t *)addr = temp & ~(1 << bit); -} - -static ALWAYS_INLINE int sys_test_bit(mem_addr_t addr, unsigned int bit) -{ - u32_t temp = *(volatile u32_t *)addr; - - return temp & (1 << bit); -} - -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_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 - 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 /* ZEPHYR_INCLUDE_ARCH_BITS_PORTABLE_H_ */ diff --git a/include/arch/common/ffs.h b/include/arch/common/ffs.h new file mode 100644 index 00000000000..57ea6dc302b --- /dev/null +++ b/include/arch/common/ffs.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015, Wind River Systems, Inc. + * Copyright (c) 2017, Oticon A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_COMMON_FFS_H_ +#define ZEPHYR_INCLUDE_ARCH_COMMON_FFS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ASMLANGUAGE + +#include +/** + * + * @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 == 0) { + 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); +} + +#endif /* _ASMLANGUAGE */ + + +#ifdef __cplusplus +} +#endif + + +#endif /* ZEPHYR_INCLUDE_ARCH_COMMON_FFS_H_ */ diff --git a/include/arch/xtensa/sys_io.h b/include/arch/common/sys_io.h similarity index 73% rename from include/arch/xtensa/sys_io.h rename to include/arch/common/sys_io.h index b8734605b3f..ec90d550cc4 100644 --- a/include/arch/xtensa/sys_io.h +++ b/include/arch/common/sys_io.h @@ -1,25 +1,35 @@ /* - * Copyright (c) 2016 Cadence Design Systems, Inc. + * Copyright (c) 2015, Wind River Systems, Inc. + * Copyright (c) 2017, Oticon A/S + * * SPDX-License-Identifier: Apache-2.0 */ -#ifndef ZEPHYR_INCLUDE_ARCH_XTENSA_SYS_IO_H_ -#define ZEPHYR_INCLUDE_ARCH_XTENSA_SYS_IO_H_ +/* "Arch" bit manipulation functions in non-arch-specific C code (uses some + * gcc builtins) + */ -#if !defined(_ASMLANGUAGE) +#ifndef ZEPHYR_INCLUDE_ARCH_COMMON_SYS_IO_H_ +#define ZEPHYR_INCLUDE_ARCH_COMMON_SYS_IO_H_ +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ASMLANGUAGE + +#include #include -/* Memory mapped registers I/O functions */ -static ALWAYS_INLINE u32_t sys_read32(mem_addr_t addr) +static ALWAYS_INLINE u8_t sys_read8(mem_addr_t addr) { - return *(volatile u32_t *)addr; + return *(volatile u8_t *)addr; } -static ALWAYS_INLINE void sys_write32(u32_t data, mem_addr_t addr) +static ALWAYS_INLINE void sys_write8(u8_t data, mem_addr_t addr) { - *(volatile u32_t *)addr = data; + *(volatile u8_t *)addr = data; } static ALWAYS_INLINE u16_t sys_read16(mem_addr_t addr) @@ -32,15 +42,14 @@ static ALWAYS_INLINE void sys_write16(u16_t data, mem_addr_t addr) *(volatile u16_t *)addr = data; } - -static ALWAYS_INLINE u8_t sys_read8(mem_addr_t addr) +static ALWAYS_INLINE u32_t sys_read32(mem_addr_t addr) { - return *(volatile u8_t *)addr; + return *(volatile u32_t *)addr; } -static ALWAYS_INLINE void sys_write8(u8_t data, mem_addr_t addr) +static ALWAYS_INLINE void sys_write32(u32_t data, mem_addr_t addr) { - *(volatile u8_t *)addr = data; + *(volatile u32_t *)addr = data; } /* Memory bit manipulation functions */ @@ -61,24 +70,9 @@ static ALWAYS_INLINE void sys_clear_bit(mem_addr_t addr, unsigned int bit) static ALWAYS_INLINE int sys_test_bit(mem_addr_t addr, unsigned int bit) { - int temp = *(volatile int *)addr; + u32_t temp = *(volatile u32_t *)addr; - return (int)(temp & (1 << bit)); -} - -static ALWAYS_INLINE int sys_test_and_set_bit(mem_addr_t addr, unsigned int bit) -{ - int retval = (*(volatile int *)addr) & (1 << bit); - *(volatile int *)addr = (*(volatile int *)addr) | (1 << bit); - return retval; -} - -static ALWAYS_INLINE - int sys_test_and_clear_bit(mem_addr_t addr, unsigned int bit) -{ - int retval = (*(volatile int *)addr) & (1 << bit); - *(volatile int *)addr = (*(volatile int *)addr) & ~(1 << bit); - return retval; + return temp & (1 << bit); } static ALWAYS_INLINE @@ -102,6 +96,27 @@ static ALWAYS_INLINE return sys_test_bit(addr + ((bit >> 5) << 2), bit & 0x1F); } +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 int sys_bitfield_test_and_set_bit(mem_addr_t addr, unsigned int bit) @@ -124,7 +139,11 @@ static ALWAYS_INLINE return ret; } -#endif /* !_ASMLANGUAGE */ +#endif -#endif /* ZEPHYR_INCLUDE_ARCH_XTENSA_SYS_IO_H_ */ +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_ARCH_COMMON_SYS_IO_H_ */ diff --git a/include/arch/nios2/arch.h b/include/arch/nios2/arch.h index 756784dc4a1..d2f70f84c9b 100644 --- a/include/arch/nios2/arch.h +++ b/include/arch/nios2/arch.h @@ -18,6 +18,8 @@ #include #include #include "nios2.h" +#include +#include #ifdef __cplusplus extern "C" { diff --git a/include/arch/nios2/asm_inline_gcc.h b/include/arch/nios2/asm_inline_gcc.h index 252dffce900..8846e981de8 100644 --- a/include/arch/nios2/asm_inline_gcc.h +++ b/include/arch/nios2/asm_inline_gcc.h @@ -17,176 +17,8 @@ extern "C" { */ #ifndef _ASMLANGUAGE - -#include +#include #include - -/** - * - * @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 diff --git a/include/arch/nios2/nios2.h b/include/arch/nios2/nios2.h index 8fa616e7a6d..6c0aa76879b 100644 --- a/include/arch/nios2/nios2.h +++ b/include/arch/nios2/nios2.h @@ -53,13 +53,13 @@ extern "C" #include #include -#include +#include /* * Functions for accessing select Nios II general-purpose registers. */ -/* ET (Exception Temporary) register */ +/* ET (Exception Temporary) register */ static inline u32_t _nios2_read_et(void) { u32_t et; diff --git a/include/arch/posix/asm_inline_gcc.h b/include/arch/posix/asm_inline_gcc.h index 6a1721b1b0c..ae329c44c3e 100644 --- a/include/arch/posix/asm_inline_gcc.h +++ b/include/arch/posix/asm_inline_gcc.h @@ -28,8 +28,8 @@ extern "C" { #include #include -#include -#include +#include +#include #include "posix_soc_if.h" diff --git a/include/arch/riscv32/arch.h b/include/arch/riscv32/arch.h index 66c7810f594..86f13ebcb30 100644 --- a/include/arch/riscv32/arch.h +++ b/include/arch/riscv32/arch.h @@ -16,7 +16,8 @@ #define ZEPHYR_INCLUDE_ARCH_RISCV32_ARCH_H_ #include "exp.h" -#include "sys_io.h" +#include +#include #include #include diff --git a/include/arch/riscv32/riscv-privilege/asm_inline_gcc.h b/include/arch/riscv32/riscv-privilege/asm_inline_gcc.h index 2ea060ec769..eb60dc0eac7 100644 --- a/include/arch/riscv32/riscv-privilege/asm_inline_gcc.h +++ b/include/arch/riscv32/riscv-privilege/asm_inline_gcc.h @@ -21,40 +21,6 @@ extern "C" { #include -/** - * - * @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); -} - -/** - * - * @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); -} #endif /* _ASMLANGUAGE */ diff --git a/include/arch/riscv32/sys_io.h b/include/arch/riscv32/sys_io.h deleted file mode 100644 index 1131aa1b1cd..00000000000 --- a/include/arch/riscv32/sys_io.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2016 Jean-Paul Etienne - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @brief RISCV32 memory mapped register I/O operations - */ - -#ifndef ZEPHYR_INCLUDE_ARCH_RISCV32_SYS_IO_H_ -#define ZEPHYR_INCLUDE_ARCH_RISCV32_SYS_IO_H_ - -#if !defined(_ASMLANGUAGE) - -#include - -/* Memory mapped registers I/O functions */ - -static inline u32_t sys_read32(mem_addr_t addr) -{ - return *(volatile u32_t *)addr; -} - - -static inline void sys_write32(u32_t data, mem_addr_t addr) -{ - *(volatile u32_t *)addr = data; -} - -static inline u8_t sys_read8(mem_addr_t addr) -{ - return *(volatile u8_t *)addr; -} - -static inline void sys_write8(u8_t data, mem_addr_t addr) -{ - *(volatile u8_t *)addr = data; -} - -/* Memory bit manipulation functions */ - -static inline void sys_set_bit(mem_addr_t addr, unsigned int bit) -{ - u32_t temp = *(volatile u32_t *)addr; - - *(volatile u32_t *)addr = temp | (1 << bit); -} - -static inline void sys_clear_bit(mem_addr_t addr, unsigned int bit) -{ - u32_t temp = *(volatile u32_t *)addr; - - *(volatile u32_t *)addr = temp & ~(1 << bit); -} - -static ALWAYS_INLINE - int sys_test_bit(mem_addr_t addr, unsigned int bit) -{ - u32_t temp = *(volatile u32_t *)addr; - - return temp & (1 << bit); -} - -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 */ - -#endif /* ZEPHYR_INCLUDE_ARCH_RISCV32_SYS_IO_H_ */ diff --git a/include/arch/x86/arch.h b/include/arch/x86/arch.h index 39867f04a91..ff769bbf5af 100644 --- a/include/arch/x86/arch.h +++ b/include/arch/x86/arch.h @@ -20,6 +20,8 @@ #include #include #include +#include "sys_io.h" +#include "ffs.h" #ifndef _ASMLANGUAGE #include diff --git a/include/arch/x86/asm_inline_gcc.h b/include/arch/x86/asm_inline_gcc.h index c0856c3df25..e44f3011e8b 100644 --- a/include/arch/x86/asm_inline_gcc.h +++ b/include/arch/x86/asm_inline_gcc.h @@ -16,8 +16,6 @@ * Include kernel.h instead */ -#include - #ifdef __cplusplus extern "C" { #endif @@ -77,105 +75,6 @@ static ALWAYS_INLINE void z_do_irq_unlock(void) } -/** - * - * @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 - * - * @internal - * For Intel64 (x86_64) architectures, the 'cmovzl' can be removed and leverage - * the fact that the 'bsfl' doesn't modify the destination operand when the - * source operand is zero. The "bitpos" variable can be preloaded into the - * destination register, and given the unconditional ++bitpos that is performed - * after the 'cmovzl', the correct results are yielded. - */ - -static ALWAYS_INLINE unsigned int find_lsb_set(u32_t op) -{ - unsigned int bitpos; - - __asm__ volatile ( - -#if defined(CONFIG_CMOV) - - "bsfl %1, %0;\n\t" - "cmovzl %2, %0;\n\t" - : "=r" (bitpos) - : "rm" (op), "r" (-1) - : "cc" - -#else - - "bsfl %1, %0;\n\t" - "jnz 1f;\n\t" - "movl $-1, %0;\n\t" - "1:\n\t" - : "=r" (bitpos) - : "rm" (op) - : "cc" - -#endif /* CONFIG_CMOV */ - ); - - return (bitpos + 1); -} - - -/** - * - * @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 - * - * @internal - * For Intel64 (x86_64) architectures, the 'cmovzl' can be removed and leverage - * the fact that the 'bsfl' doesn't modify the destination operand when the - * source operand is zero. The "bitpos" variable can be preloaded into the - * destination register, and given the unconditional ++bitpos that is performed - * after the 'cmovzl', the correct results are yielded. - */ - -static ALWAYS_INLINE unsigned int find_msb_set(u32_t op) -{ - unsigned int bitpos; - - __asm__ volatile ( - -#if defined(CONFIG_CMOV) - - "bsrl %1, %0;\n\t" - "cmovzl %2, %0;\n\t" - : "=r" (bitpos) - : "rm" (op), "r" (-1) - -#else - - "bsrl %1, %0;\n\t" - "jnz 1f;\n\t" - "movl $-1, %0;\n\t" - "1:\n\t" - : "=r" (bitpos) - : "rm" (op) - : "cc" - -#endif /* CONFIG_CMOV */ - ); - - return (bitpos + 1); -} - - /** * @brief read timestamp register ensuring serialization */ @@ -227,258 +126,6 @@ static ALWAYS_INLINE } -/* Implementation of sys_io.h's documented functions */ - -static ALWAYS_INLINE -void sys_out8(u8_t data, io_port_t port) -{ - __asm__ volatile("outb %b0, %w1;\n\t" - : - : "a"(data), "Nd"(port)); -} - - -static ALWAYS_INLINE - u8_t sys_in8(io_port_t port) -{ - u8_t ret; - - __asm__ volatile("inb %w1, %b0;\n\t" - : "=a"(ret) - : "Nd"(port)); - return ret; -} - - -static ALWAYS_INLINE - void sys_out16(u16_t data, io_port_t port) -{ - __asm__ volatile("outw %w0, %w1;\n\t" - : - : "a"(data), "Nd"(port)); -} - - -static ALWAYS_INLINE - u16_t sys_in16(io_port_t port) -{ - u16_t ret; - - __asm__ volatile("inw %w1, %w0;\n\t" - : "=a"(ret) - : "Nd"(port)); - return ret; -} - - -static ALWAYS_INLINE - void sys_out32(u32_t data, io_port_t port) -{ - __asm__ volatile("outl %0, %w1;\n\t" - : - : "a"(data), "Nd"(port)); -} - - -static ALWAYS_INLINE - u32_t sys_in32(io_port_t port) -{ - u32_t ret; - - __asm__ volatile("inl %w1, %0;\n\t" - : "=a"(ret) - : "Nd"(port)); - return ret; -} - - -static ALWAYS_INLINE - void sys_io_set_bit(io_port_t port, unsigned int bit) -{ - u32_t reg = 0; - - __asm__ volatile("inl %w1, %0;\n\t" - "btsl %2, %0;\n\t" - "outl %0, %w1;\n\t" - : - : "a" (reg), "Nd" (port), "Ir" (bit)); -} - -static ALWAYS_INLINE - void sys_io_clear_bit(io_port_t port, unsigned int bit) -{ - u32_t reg = 0; - - __asm__ volatile("inl %w1, %0;\n\t" - "btrl %2, %0;\n\t" - "outl %0, %w1;\n\t" - : - : "a" (reg), "Nd" (port), "Ir" (bit)); -} - -static ALWAYS_INLINE - int sys_io_test_bit(io_port_t port, unsigned int bit) -{ - u32_t ret; - - __asm__ volatile("inl %w1, %0\n\t" - "btl %2, %0\n\t" - : "=a" (ret) - : "Nd" (port), "Ir" (bit)); - - return (ret & 1U); -} - -static ALWAYS_INLINE - int sys_io_test_and_set_bit(io_port_t port, unsigned int bit) -{ - int ret; - - ret = sys_io_test_bit(port, bit); - sys_io_set_bit(port, bit); - - return ret; -} - -static ALWAYS_INLINE - int sys_io_test_and_clear_bit(io_port_t port, unsigned int bit) -{ - int ret; - - ret = sys_io_test_bit(port, bit); - sys_io_clear_bit(port, bit); - - return ret; -} - -static ALWAYS_INLINE - void sys_write8(u8_t data, mm_reg_t addr) -{ - __asm__ volatile("movb %0, %1;\n\t" - : - : "q"(data), "m" (*(volatile u8_t *) addr) - : "memory"); -} - -static ALWAYS_INLINE - u8_t sys_read8(mm_reg_t addr) -{ - u8_t ret; - - __asm__ volatile("movb %1, %0;\n\t" - : "=q"(ret) - : "m" (*(volatile u8_t *) addr) - : "memory"); - - return ret; -} - -static ALWAYS_INLINE - void sys_write16(u16_t data, mm_reg_t addr) -{ - __asm__ volatile("movw %0, %1;\n\t" - : - : "r"(data), "m" (*(volatile u16_t *) addr) - : "memory"); -} - -static ALWAYS_INLINE - u16_t sys_read16(mm_reg_t addr) -{ - u16_t ret; - - __asm__ volatile("movw %1, %0;\n\t" - : "=r"(ret) - : "m" (*(volatile u16_t *) addr) - : "memory"); - - return ret; -} - -static ALWAYS_INLINE - void sys_write32(u32_t data, mm_reg_t addr) -{ - __asm__ volatile("movl %0, %1;\n\t" - : - : "r"(data), "m" (*(volatile u32_t *) addr) - : "memory"); -} - -static ALWAYS_INLINE - u32_t sys_read32(mm_reg_t addr) -{ - u32_t ret; - - __asm__ volatile("movl %1, %0;\n\t" - : "=r"(ret) - : "m" (*(volatile u32_t *) addr) - : "memory"); - - return ret; -} - - -static ALWAYS_INLINE - void sys_set_bit(mem_addr_t addr, unsigned int bit) -{ - __asm__ volatile("btsl %1, %0;\n\t" - : "+m" (*(volatile u32_t *) (addr)) - : "Ir" (bit) - : "memory"); -} - -static ALWAYS_INLINE - void sys_clear_bit(mem_addr_t addr, unsigned int bit) -{ - __asm__ volatile("btrl %1, %0;\n\t" - : "+m" (*(volatile u32_t *) (addr)) - : "Ir" (bit)); -} - -static ALWAYS_INLINE - int sys_test_bit(mem_addr_t addr, unsigned int bit) -{ - int ret; - - __asm__ volatile("btl %2, %1;\n\t" - "sbb %0, %0\n\t" - : "=r" (ret), "+m" (*(volatile u32_t *) (addr)) - : "Ir" (bit)); - - return ret; -} - -static ALWAYS_INLINE - int sys_test_and_set_bit(mem_addr_t addr, unsigned int bit) -{ - int ret; - - __asm__ volatile("btsl %2, %1;\n\t" - "sbb %0, %0\n\t" - : "=r" (ret), "+m" (*(volatile u32_t *) (addr)) - : "Ir" (bit)); - - return ret; -} - -static ALWAYS_INLINE - int sys_test_and_clear_bit(mem_addr_t addr, unsigned int bit) -{ - int ret; - - __asm__ volatile("btrl %2, %1;\n\t" - "sbb %0, %0\n\t" - : "=r" (ret), "+m" (*(volatile u32_t *) (addr)) - : "Ir" (bit)); - - return ret; -} - -#define sys_bitfield_set_bit sys_set_bit -#define sys_bitfield_clear_bit sys_clear_bit -#define sys_bitfield_test_bit sys_test_bit -#define sys_bitfield_test_and_set_bit sys_test_and_set_bit -#define sys_bitfield_test_and_clear_bit sys_test_and_clear_bit #endif /* _ASMLANGUAGE */ diff --git a/include/arch/x86/ffs.h b/include/arch/x86/ffs.h new file mode 100644 index 00000000000..dd3d2245cf5 --- /dev/null +++ b/include/arch/x86/ffs.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief X86 find-first-set interface + * + * X86-specific kernel ffs interface + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_X86_FFS_H_ +#define ZEPHYR_INCLUDE_ARCH_X86_FFS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _ASMLANGUAGE + +#include + +/** + * + * @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 + * + * @internal + * For Intel64 (x86_64) architectures, the 'cmovzl' can be removed and leverage + * the fact that the 'bsfl' doesn't modify the destination operand when the + * source operand is zero. The "bitpos" variable can be preloaded into the + * destination register, and given the unconditional ++bitpos that is performed + * after the 'cmovzl', the correct results are yielded. + */ + +static ALWAYS_INLINE unsigned int find_lsb_set(u32_t op) +{ + unsigned int bitpos; + + __asm__ volatile ( + +#if defined(CONFIG_CMOV) + + "bsfl %1, %0;\n\t" + "cmovzl %2, %0;\n\t" + : "=r" (bitpos) + : "rm" (op), "r" (-1) + : "cc" + +#else + + "bsfl %1, %0;\n\t" + "jnz 1f;\n\t" + "movl $-1, %0;\n\t" + "1:\n\t" + : "=r" (bitpos) + : "rm" (op) + : "cc" + +#endif /* CONFIG_CMOV */ + ); + + return (bitpos + 1); +} + + +/** + * + * @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 + * + * @internal + * For Intel64 (x86_64) architectures, the 'cmovzl' can be removed and leverage + * the fact that the 'bsfl' doesn't modify the destination operand when the + * source operand is zero. The "bitpos" variable can be preloaded into the + * destination register, and given the unconditional ++bitpos that is performed + * after the 'cmovzl', the correct results are yielded. + */ + +static ALWAYS_INLINE unsigned int find_msb_set(u32_t op) +{ + unsigned int bitpos; + + __asm__ volatile ( + +#if defined(CONFIG_CMOV) + + "bsrl %1, %0;\n\t" + "cmovzl %2, %0;\n\t" + : "=r" (bitpos) + : "rm" (op), "r" (-1) + +#else + + "bsrl %1, %0;\n\t" + "jnz 1f;\n\t" + "movl $-1, %0;\n\t" + "1:\n\t" + : "=r" (bitpos) + : "rm" (op) + : "cc" + +#endif /* CONFIG_CMOV */ + ); + + return (bitpos + 1); +} + + + +#endif /* _ASMLANGUAGE */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_ARCH_X86_FFS_H_ */ diff --git a/include/arch/x86/sys_io.h b/include/arch/x86/sys_io.h new file mode 100644 index 00000000000..e82a653c99d --- /dev/null +++ b/include/arch/x86/sys_io.h @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2015, Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Implementation of sys_io.h's documented functions */ + +#ifndef ZEPHYR_INCLUDE_ARCH_X86_SYS_IO_H_ +#define ZEPHYR_INCLUDE_ARCH_X86_SYS_IO_H_ + + +#if !defined(_ASMLANGUAGE) + +#include +#include +#include + +static ALWAYS_INLINE +void sys_out8(u8_t data, io_port_t port) +{ + __asm__ volatile("outb %b0, %w1;\n\t" + : + : "a"(data), "Nd"(port)); +} + + +static ALWAYS_INLINE + u8_t sys_in8(io_port_t port) +{ + u8_t ret; + + __asm__ volatile("inb %w1, %b0;\n\t" + : "=a"(ret) + : "Nd"(port)); + return ret; +} + + +static ALWAYS_INLINE + void sys_out16(u16_t data, io_port_t port) +{ + __asm__ volatile("outw %w0, %w1;\n\t" + : + : "a"(data), "Nd"(port)); +} + + +static ALWAYS_INLINE + u16_t sys_in16(io_port_t port) +{ + u16_t ret; + + __asm__ volatile("inw %w1, %w0;\n\t" + : "=a"(ret) + : "Nd"(port)); + return ret; +} + + +static ALWAYS_INLINE + void sys_out32(u32_t data, io_port_t port) +{ + __asm__ volatile("outl %0, %w1;\n\t" + : + : "a"(data), "Nd"(port)); +} + + +static ALWAYS_INLINE + u32_t sys_in32(io_port_t port) +{ + u32_t ret; + + __asm__ volatile("inl %w1, %0;\n\t" + : "=a"(ret) + : "Nd"(port)); + return ret; +} + + +static ALWAYS_INLINE + void sys_io_set_bit(io_port_t port, unsigned int bit) +{ + u32_t reg = 0; + + __asm__ volatile("inl %w1, %0;\n\t" + "btsl %2, %0;\n\t" + "outl %0, %w1;\n\t" + : + : "a" (reg), "Nd" (port), "Ir" (bit)); +} + +static ALWAYS_INLINE + void sys_io_clear_bit(io_port_t port, unsigned int bit) +{ + u32_t reg = 0; + + __asm__ volatile("inl %w1, %0;\n\t" + "btrl %2, %0;\n\t" + "outl %0, %w1;\n\t" + : + : "a" (reg), "Nd" (port), "Ir" (bit)); +} + +static ALWAYS_INLINE + int sys_io_test_bit(io_port_t port, unsigned int bit) +{ + u32_t ret; + + __asm__ volatile("inl %w1, %0\n\t" + "btl %2, %0\n\t" + : "=a" (ret) + : "Nd" (port), "Ir" (bit)); + + return (ret & 1U); +} + +static ALWAYS_INLINE + int sys_io_test_and_set_bit(io_port_t port, unsigned int bit) +{ + int ret; + + ret = sys_io_test_bit(port, bit); + sys_io_set_bit(port, bit); + + return ret; +} + +static ALWAYS_INLINE + int sys_io_test_and_clear_bit(io_port_t port, unsigned int bit) +{ + int ret; + + ret = sys_io_test_bit(port, bit); + sys_io_clear_bit(port, bit); + + return ret; +} + +static ALWAYS_INLINE + void sys_write8(u8_t data, mm_reg_t addr) +{ + __asm__ volatile("movb %0, %1;\n\t" + : + : "q"(data), "m" (*(volatile u8_t *) addr) + : "memory"); +} + +static ALWAYS_INLINE + u8_t sys_read8(mm_reg_t addr) +{ + u8_t ret; + + __asm__ volatile("movb %1, %0;\n\t" + : "=q"(ret) + : "m" (*(volatile u8_t *) addr) + : "memory"); + + return ret; +} + +static ALWAYS_INLINE + void sys_write16(u16_t data, mm_reg_t addr) +{ + __asm__ volatile("movw %0, %1;\n\t" + : + : "r"(data), "m" (*(volatile u16_t *) addr) + : "memory"); +} + +static ALWAYS_INLINE + u16_t sys_read16(mm_reg_t addr) +{ + u16_t ret; + + __asm__ volatile("movw %1, %0;\n\t" + : "=r"(ret) + : "m" (*(volatile u16_t *) addr) + : "memory"); + + return ret; +} + +static ALWAYS_INLINE + void sys_write32(u32_t data, mm_reg_t addr) +{ + __asm__ volatile("movl %0, %1;\n\t" + : + : "r"(data), "m" (*(volatile u32_t *) addr) + : "memory"); +} + +static ALWAYS_INLINE + u32_t sys_read32(mm_reg_t addr) +{ + u32_t ret; + + __asm__ volatile("movl %1, %0;\n\t" + : "=r"(ret) + : "m" (*(volatile u32_t *) addr) + : "memory"); + + return ret; +} + + +static ALWAYS_INLINE + void sys_set_bit(mem_addr_t addr, unsigned int bit) +{ + __asm__ volatile("btsl %1, %0;\n\t" + : "+m" (*(volatile u32_t *) (addr)) + : "Ir" (bit) + : "memory"); +} + +static ALWAYS_INLINE + void sys_clear_bit(mem_addr_t addr, unsigned int bit) +{ + __asm__ volatile("btrl %1, %0;\n\t" + : "+m" (*(volatile u32_t *) (addr)) + : "Ir" (bit)); +} + +static ALWAYS_INLINE + int sys_test_bit(mem_addr_t addr, unsigned int bit) +{ + int ret; + + __asm__ volatile("btl %2, %1;\n\t" + "sbb %0, %0\n\t" + : "=r" (ret), "+m" (*(volatile u32_t *) (addr)) + : "Ir" (bit)); + + return ret; +} + +static ALWAYS_INLINE + int sys_test_and_set_bit(mem_addr_t addr, unsigned int bit) +{ + int ret; + + __asm__ volatile("btsl %2, %1;\n\t" + "sbb %0, %0\n\t" + : "=r" (ret), "+m" (*(volatile u32_t *) (addr)) + : "Ir" (bit)); + + return ret; +} + +static ALWAYS_INLINE + int sys_test_and_clear_bit(mem_addr_t addr, unsigned int bit) +{ + int ret; + + __asm__ volatile("btrl %2, %1;\n\t" + "sbb %0, %0\n\t" + : "=r" (ret), "+m" (*(volatile u32_t *) (addr)) + : "Ir" (bit)); + + return ret; +} + +#define sys_bitfield_set_bit sys_set_bit +#define sys_bitfield_clear_bit sys_clear_bit +#define sys_bitfield_test_bit sys_test_bit +#define sys_bitfield_test_and_set_bit sys_test_and_set_bit +#define sys_bitfield_test_and_clear_bit sys_test_and_clear_bit + + +#endif /* _ASMLANGUAGE */ + +#endif /* ZEPHYR_INCLUDE_ARCH_X86_SYS_IO_H_ */ diff --git a/include/arch/x86_64/arch.h b/include/arch/x86_64/arch.h index 4c3330aa43c..e3408f0b69e 100644 --- a/include/arch/x86_64/arch.h +++ b/include/arch/x86_64/arch.h @@ -7,7 +7,8 @@ #define _X86_64_ARCH_H #include -#include +#include +#include #define STACK_ALIGN 8 diff --git a/include/arch/xtensa/arch.h b/include/arch/xtensa/arch.h index 9da0f0bb606..fce205c5a7f 100644 --- a/include/arch/xtensa/arch.h +++ b/include/arch/xtensa/arch.h @@ -21,7 +21,8 @@ extern "C" { #include #if !defined(_ASMLANGUAGE) && !defined(__ASSEMBLER__) -#include "sys_io.h" /* Include from the very same folder of this file */ +#include +#include #include #include #include @@ -41,42 +42,6 @@ extern "C" { #include -/** - * - * @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); -} - /* internal routine documented in C file, needed by IRQ_CONNECT() macro */ extern void z_irq_priority_set(u32_t irq, u32_t prio, u32_t flags);