mirror of
				https://gitlab.com/qemu-project/ipxe.git
				synced 2025-11-03 07:59:06 +08:00 
			
		
		
		
	Recent versions of the GNU assembler (observed with GNU as 2.35 on Fedora 33) will produce a warning message Warning: no instruction mnemonic suffix given and no register operands; using default for `bts' The operand size affects only the potential range for the bit number. Since we pass the bit number as an unsigned int, it is already constrained to 32 bits for both i386 and x86_64. Silence the assembler warning by specifying an explicit 32-bit operand size (and thereby matching the choice that the assembler would otherwise make automatically). Signed-off-by: Michael Brown <mcb30@ipxe.org>
		
			
				
	
	
		
			95 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			95 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#ifndef _BITS_BITOPS_H
 | 
						|
#define _BITS_BITOPS_H
 | 
						|
 | 
						|
/** @file
 | 
						|
 *
 | 
						|
 * x86 bit operations
 | 
						|
 *
 | 
						|
 * We perform atomic bit set and bit clear operations using "lock bts"
 | 
						|
 * and "lock btr".  We use the output constraint to inform the
 | 
						|
 * compiler that any memory from the start of the bit field up to and
 | 
						|
 * including the byte containing the bit may be modified.  (This is
 | 
						|
 * overkill but shouldn't matter in practice since we're unlikely to
 | 
						|
 * subsequently read other bits from the same bit field.)
 | 
						|
 */
 | 
						|
 | 
						|
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 | 
						|
 | 
						|
#include <stdint.h>
 | 
						|
 | 
						|
/**
 | 
						|
 * 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 ) {
 | 
						|
	volatile struct {
 | 
						|
		uint8_t byte[ ( bit / 8 ) + 1 ];
 | 
						|
	} *bytes = bits;
 | 
						|
 | 
						|
	__asm__ __volatile__ ( "lock btsl %k1, %0"
 | 
						|
			       : "+m" ( *bytes ) : "Ir" ( bit ) );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * 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 ) {
 | 
						|
	volatile struct {
 | 
						|
		uint8_t byte[ ( bit / 8 ) + 1 ];
 | 
						|
	} *bytes = bits;
 | 
						|
 | 
						|
	__asm__ __volatile__ ( "lock btrl %k1, %0"
 | 
						|
			       : "+m" ( *bytes ) : "Ir" ( bit ) );
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * 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 ) {
 | 
						|
	volatile struct {
 | 
						|
		uint8_t byte[ ( bit / 8 ) + 1 ];
 | 
						|
	} *bytes = bits;
 | 
						|
	int old;
 | 
						|
 | 
						|
	__asm__ __volatile__ ( "lock btsl %k2, %0\n\t"
 | 
						|
			       "sbb %1, %1\n\t"
 | 
						|
			       : "+m" ( *bytes ), "=r"  ( old )
 | 
						|
			       : "Ir" ( bit ) );
 | 
						|
	return old;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * 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 ) {
 | 
						|
	volatile struct {
 | 
						|
		uint8_t byte[ ( bit / 8 ) + 1 ];
 | 
						|
	} *bytes = bits;
 | 
						|
	int old;
 | 
						|
 | 
						|
	__asm__ __volatile__ ( "lock btrl %k2, %0\n\t"
 | 
						|
			       "sbb %1, %1\n\t"
 | 
						|
			       : "+m" ( *bytes ), "=r"  ( old )
 | 
						|
			       : "Ir" ( bit ) );
 | 
						|
	return old;
 | 
						|
}
 | 
						|
 | 
						|
#endif /* _BITS_BITOPS_H */
 |