From 71c289dfbcb31d2a611ff281e9cc58a8e7cd63ea Mon Sep 17 00:00:00 2001 From: Juan Manuel Cruz Date: Fri, 2 Oct 2015 17:28:18 -0500 Subject: [PATCH] asm: add asm inline for system set/clear/test bit This commit adds asm implementation for the methods: sys_io_set_bit sys_io_clear_bit sys_io_test_bit sys_io_test_and_set_bit sys_io_test_and_clear_bit Change-Id: I144568e113316fa43d943cdc5457cb17e66839c3 Signed-off-by: Juan Manuel Cruz Signed-off-by: Tomasz Bursztyka --- include/arch/arc/v2/asm_inline_gcc.h | 68 ++++++++++++++++++++++++++ include/arch/x86/asm_inline_gcc.h | 73 ++++++++++++++++++++++++++++ include/sys_io.h | 62 ++++++++++++++++++++++- 3 files changed, 201 insertions(+), 2 deletions(-) diff --git a/include/arch/arc/v2/asm_inline_gcc.h b/include/arch/arc/v2/asm_inline_gcc.h index 6e26ce0daff..f1500f6c57f 100644 --- a/include/arch/arc/v2/asm_inline_gcc.h +++ b/include/arch/arc/v2/asm_inline_gcc.h @@ -65,6 +65,74 @@ static inline __attribute__((always_inline)) return _arc_v2_aux_reg_read(port); } +static inline __attribute__((always_inline)) + void sys_io_set_bit(io_port_t port, int bit) +{ + uint32_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 inline __attribute__((always_inline)) + void sys_io_clear_bit(io_port_t port, int bit) +{ + uint32_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 inline __attribute__((always_inline)) + int sys_io_test_bit(io_port_t port, int bit) +{ + uint32_t status = _ARC_V2_STATUS32; + uint32_t reg = 0; + uint32_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 inline __attribute__((always_inline)) + int sys_io_test_and_set_bit(io_port_t port, int bit) +{ + int ret; + + ret = sys_io_test_bit(port, bit); + sys_io_set_bit(port, bit); + + return ret; +} + +static inline __attribute__((always_inline)) + int sys_io_test_and_clear_bit(io_port_t port, int bit) +{ + int ret; + + ret = sys_io_test_bit(port, bit); + sys_io_clear_bit(port, bit); + + return ret; +} + static inline __attribute__((always_inline)) void sys_write8(uint8_t data, mm_reg_t addr) { diff --git a/include/arch/x86/asm_inline_gcc.h b/include/arch/x86/asm_inline_gcc.h index f17763b8f55..25d6117b1e2 100644 --- a/include/arch/x86/asm_inline_gcc.h +++ b/include/arch/x86/asm_inline_gcc.h @@ -286,6 +286,79 @@ static inline __attribute__((always_inline)) return ret; } + +static inline __attribute__((always_inline)) + void sys_io_set_bit(io_port_t port, int bit) +{ + uint32_t reg = 0; + + __asm__ volatile("inl %%dx, %%eax\n" + "mov %1, 1\n" + "shl %%cl, %1\n" + "or %%eax, %1\n" + "outl %%eax, %%dx;\n\t" + : + : "d" (port), + "r" (reg), "d" (bit) + : "memory", "cc"); +} + +static inline __attribute__((always_inline)) + void sys_io_clear_bit(io_port_t port, int bit) +{ + uint32_t reg = 0; + + __asm__ volatile("inl %%dx, %%eax\n" + "mov %1, 1\n" + "shl %%cl, %1\n" + "and %%eax, %1\n" + "outl %%eax, %%dx;\n\t" + : + : "d" (port), + "r" (reg), "d" (bit) + : "memory", "cc"); +} + +static inline __attribute__((always_inline)) + int sys_io_test_bit(io_port_t port, int bit) +{ + uint32_t ret; + + __asm__ volatile("inl %%dx, %%eax\n" + "bt %2, %%eax\n" + "lahf\n" + "mov %1, %%eax\n" + "clc;\n\t" + : "=r" (ret) + : "d" (port), + "Mr" (bit) + : "memory", "cc"); + + return (ret & 1); +} + +static inline __attribute__((always_inline)) + int sys_io_test_and_set_bit(io_port_t port, int bit) +{ + int ret; + + ret = sys_io_test_bit(port, bit); + sys_io_set_bit(port, bit); + + return ret; +} + +static inline __attribute__((always_inline)) + int sys_io_test_and_clear_bit(io_port_t port, int bit) +{ + int ret; + + ret = sys_io_test_bit(port, bit); + sys_io_clear_bit(port, bit); + + return ret; +} + static inline __attribute__((always_inline)) void sys_write8(uint8_t data, mm_reg_t addr) { diff --git a/include/sys_io.h b/include/sys_io.h index 1a03f908c34..beb377b475b 100644 --- a/include/sys_io.h +++ b/include/sys_io.h @@ -95,6 +95,64 @@ typedef uint32_t mem_addr_t; * @return the 32 bits read */ +/** + * @fn static inline void sys_io_set_bit(io_port_t port, int bit) + * @brief Set the designated bit from port to 1 + * + * This functions takes the designated bit starting from port and sets it to 1. + * + * @param port the port address from where to look for the bit + * @param bit the designated bit to set (from 0 to n) + */ + +/** + * @fn static inline void sys_io_clear_bit(io_port_t port, int bit) + * @brief Clear the designated bit from port to 0 + * + * This functions takes the designated bit starting from port and sets it to 0. + * + * @param port the port address from where to look for the bit + * @param bit the designated bit to clear (from 0 to n) + */ + +/** + * @fn static inline int sys_io_test_bit(io_port_t port, int bit) + * @brief Test the bit from port if it is set or not + * + * This functions takes the designated bit starting from port and tests its + * current setting. It will return the current setting. + * + * @param port the port address from where to look for the bit + * @param bit the designated bit to test (from 0 to n) + * + * @return 1 if it is set, 0 otherwise + */ + +/** + * @fn static inline int sys_io_test_and_set_bit(io_port_t port, int bit) + * @brief Test the bit from port and set it + * + * This functions takes the designated bit starting from port, tests its + * current setting and sets it. It will return the previous setting. + * + * @param port the port address from where to look for the bit + * @param bit the designated bit to test and set (from 0 to n) + * + * @return 1 if it was set, 0 otherwise + */ + +/** + * @fn static inline int sys_io_test_and_clear_bit(io_port_t port, int bit) + * @brief Test the bit from port and clear it + * + * This functions takes the designated bit starting from port, tests its + * current setting and clears it. It will return the previous setting. + * + * @param port the port address from where to look for the bit + * @param bit the designated bit to test and clear (from 0 to n) + * + * @return 0 if it was clear, 1 otherwise + */ /* Memory mapped registers I/O functions */ @@ -190,7 +248,7 @@ typedef uint32_t mem_addr_t; * @brief Test the bit if it is set or not * * This functions takes the designated bit starting from addr and tests its - * current setting. If it return the current setting. + * current setting. It will return the current setting. * * @param addr the memory address from where to look for the bit * @param bit the designated bit to test (from 0 to n) @@ -219,7 +277,7 @@ typedef uint32_t mem_addr_t; * current setting and clears it. It will return the previous setting. * * @param addr the memory address from where to look for the bit - * @param bit the designated bit to test (from 0 to n) + * @param bit the designated bit to test and clear (from 0 to n) * * @return 0 if it was clear, 1 otherwise */