diff options
Diffstat (limited to 'src/arch/riscv/include/bits/bitops.h')
| -rw-r--r-- | src/arch/riscv/include/bits/bitops.h | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/src/arch/riscv/include/bits/bitops.h b/src/arch/riscv/include/bits/bitops.h new file mode 100644 index 000000000..2019db99a --- /dev/null +++ b/src/arch/riscv/include/bits/bitops.h @@ -0,0 +1,82 @@ +#ifndef _BITS_BITOPS_H +#define _BITS_BITOPS_H + +/** @file + * + * RISC-V bit operations + * + */ + +FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); + +#include <stdint.h> + +/** + * Test and set bit atomically + * + * @v bit Bit to set + * @v bits Bit field + * @ret old Old value of bit (zero or non-zero) + */ +static inline __attribute__ (( always_inline )) int +test_and_set_bit ( unsigned int bit, volatile void *bits ) { + unsigned int index = ( bit / 32 ); + unsigned int offset = ( bit % 32 ); + volatile uint32_t *word = ( ( ( volatile uint32_t * ) bits ) + index ); + uint32_t mask = ( 1U << offset ); + uint32_t old; + + __asm__ __volatile__ ( "amoor.w %0, %2, %1" + : "=r" ( old ), "+A" ( *word ) + : "r" ( mask ) ); + + return ( !! ( old & mask ) ); +} + +/** + * Test and clear bit atomically + * + * @v bit Bit to set + * @v bits Bit field + * @ret old Old value of bit (zero or non-zero) + */ +static inline __attribute__ (( always_inline )) int +test_and_clear_bit ( unsigned int bit, volatile void *bits ) { + unsigned int index = ( bit / 32 ); + unsigned int offset = ( bit % 32 ); + volatile uint32_t *word = ( ( ( volatile uint32_t * ) bits ) + index ); + uint32_t mask = ( 1U << offset ); + uint32_t old; + + __asm__ __volatile__ ( "amoand.w %0, %2, %1" + : "=r" ( old ), "+A" ( *word ) + : "r" ( ~mask ) ); + + return ( !! ( old & mask ) ); +} + +/** + * Set bit atomically + * + * @v bit Bit to set + * @v bits Bit field + */ +static inline __attribute__ (( always_inline )) void +set_bit ( unsigned int bit, volatile void *bits ) { + + test_and_set_bit ( bit, bits ); +} + +/** + * Clear bit atomically + * + * @v bit Bit to set + * @v bits Bit field + */ +static inline __attribute__ (( always_inline )) void +clear_bit ( unsigned int bit, volatile void *bits ) { + + test_and_clear_bit ( bit, bits ); +} + +#endif /* _BITS_BITOPS_H */ |
