~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/ipxe/src/arch/arm64/include/bits/bitops.h

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#ifndef _BITS_BITOPS_H
 
2
#define _BITS_BITOPS_H
 
3
 
 
4
/** @file
 
5
 *
 
6
 * ARM bit operations
 
7
 *
 
8
 */
 
9
 
 
10
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 
11
 
 
12
#include <stdint.h>
 
13
 
 
14
/**
 
15
 * Test and set bit atomically
 
16
 *
 
17
 * @v bit               Bit to set
 
18
 * @v bits              Bit field
 
19
 * @ret old             Old value of bit (zero or non-zero)
 
20
 */
 
21
static inline __attribute__ (( always_inline )) int
 
22
test_and_set_bit ( unsigned int bit, volatile void *bits ) {
 
23
        unsigned int index = ( bit / 64 );
 
24
        unsigned int offset = ( bit % 64 );
 
25
        volatile uint64_t *qword = ( ( ( volatile uint64_t * ) bits ) + index );
 
26
        uint64_t mask = ( 1UL << offset );
 
27
        uint64_t old;
 
28
        uint64_t new;
 
29
        uint32_t flag;
 
30
 
 
31
        __asm__ __volatile__ ( "\n1:\n\t"
 
32
                               "ldxr %0, %3\n\t"
 
33
                               "orr %1, %0, %4\n\t"
 
34
                               "stxr %w2, %1, %3\n\t"
 
35
                               "tst %w2, %w2\n\t"
 
36
                               "bne 1b\n\t"
 
37
                               : "=&r" ( old ), "=&r" ( new ), "=&r" ( flag ),
 
38
                                 "+Q" ( *qword )
 
39
                               : "r" ( mask )
 
40
                               : "cc" );
 
41
 
 
42
        return ( !! ( old & mask ) );
 
43
}
 
44
 
 
45
/**
 
46
 * Test and clear bit atomically
 
47
 *
 
48
 * @v bit               Bit to set
 
49
 * @v bits              Bit field
 
50
 * @ret old             Old value of bit (zero or non-zero)
 
51
 */
 
52
static inline __attribute__ (( always_inline )) int
 
53
test_and_clear_bit ( unsigned int bit, volatile void *bits ) {
 
54
        unsigned int index = ( bit / 64 );
 
55
        unsigned int offset = ( bit % 64 );
 
56
        volatile uint64_t *qword = ( ( ( volatile uint64_t * ) bits ) + index );
 
57
        uint64_t mask = ( 1UL << offset );
 
58
        uint64_t old;
 
59
        uint64_t new;
 
60
        uint32_t flag;
 
61
 
 
62
        __asm__ __volatile__ ( "\n1:\n\t"
 
63
                               "ldxr %0, %3\n\t"
 
64
                               "bic %1, %0, %4\n\t"
 
65
                               "stxr %w2, %1, %3\n\t"
 
66
                               "tst %w2, %w2\n\t"
 
67
                               "bne 1b\n\t"
 
68
                               : "=&r" ( old ), "=&r" ( new ), "=&r" ( flag ),
 
69
                                 "+Q" ( *qword )
 
70
                               : "r" ( mask )
 
71
                               : "cc" );
 
72
 
 
73
        return ( !! ( old & mask ) );
 
74
}
 
75
 
 
76
/**
 
77
 * Set bit atomically
 
78
 *
 
79
 * @v bit               Bit to set
 
80
 * @v bits              Bit field
 
81
 */
 
82
static inline __attribute__ (( always_inline )) void
 
83
set_bit ( unsigned int bit, volatile void *bits ) {
 
84
 
 
85
        test_and_set_bit ( bit, bits );
 
86
}
 
87
 
 
88
/**
 
89
 * Clear bit atomically
 
90
 *
 
91
 * @v bit               Bit to set
 
92
 * @v bits              Bit field
 
93
 */
 
94
static inline __attribute__ (( always_inline )) void
 
95
clear_bit ( unsigned int bit, volatile void *bits ) {
 
96
 
 
97
        test_and_clear_bit ( bit, bits );
 
98
}
 
99
 
 
100
#endif /* _BITS_BITOPS_H */