iflag: Introduce IFLAG_INIT helper
[platform/upstream/nasm.git] / iflag.h
1 #ifndef NASM_IFLAG_H
2 #define NASM_IFLAG_H
3
4 #include <inttypes.h>
5
6 #include <string.h>
7
8 #include "compiler.h"
9
10 int ilog2_32(uint32_t v);
11
12 #include "iflaggen.h"
13
14 #define IF_GENBIT(bit)          (UINT32_C(1) << (bit))
15
16 #define IFLAG_INIT              (iflag_t){ .field = { 0 }, }
17
18 static inline unsigned int iflag_test(const iflag_t *f, unsigned int bit)
19 {
20     unsigned int index = bit / 32;
21     return f->field[index] & (UINT32_C(1) << (bit - (index * 32)));
22 }
23
24 static inline void iflag_set(iflag_t *f, unsigned int bit)
25 {
26     unsigned int index = bit / 32;
27     f->field[index] |= (UINT32_C(1) << (bit - (index * 32)));
28 }
29
30 static inline void iflag_clear(iflag_t *f, unsigned int bit)
31 {
32     unsigned int index = bit / 32;
33     f->field[index] &= ~(UINT32_C(1) << (bit - (index * 32)));
34 }
35
36 static inline void iflag_clear_all(iflag_t *f)
37 {
38      memset(f, 0, sizeof(*f));
39 }
40
41 static inline void iflag_set_all(iflag_t *f)
42 {
43      memset(f, 0xff, sizeof(*f));
44 }
45
46 static inline int iflag_cmp(const iflag_t *a, const iflag_t *b)
47 {
48     int i;
49
50     for (i = sizeof(a->field) / sizeof(a->field[0]) - 1; i >= 0; i--) {
51         if (a->field[i] == b->field[i])
52             continue;
53
54         return (a->field[i] > b->field[i]) ? 1 : -1;
55     }
56
57     return 0;
58 }
59
60 static inline int iflag_cmp_cpu(const iflag_t *a, const iflag_t *b)
61 {
62     if (a->field[3] < b->field[3])
63         return -1;
64     else if (a->field[3] > b->field[3])
65         return 1;
66     return 0;
67 }
68
69 static inline unsigned int iflag_ffs(const iflag_t *a)
70 {
71     unsigned int i;
72
73     for (i = 0; i < sizeof(a->field) / sizeof(a->field[0]); i++) {
74         if (a->field[i])
75             return ilog2_32(a->field[i]) + (i * 32);
76     }
77
78     return 0;
79 }
80
81 #define IF_GEN_HELPER(name, op)                                         \
82     static inline iflag_t iflag_##name(const iflag_t *a, const iflag_t *b) \
83     {                                                                   \
84         unsigned int i;                                                 \
85         iflag_t res;                                                    \
86                                                                         \
87         for (i = 0; i < sizeof(a->field) / sizeof(a->field[0]); i++)    \
88             res.field[i] = a->field[i] op b->field[i];                  \
89                                                                         \
90         return res;                                                     \
91     }
92
93 IF_GEN_HELPER(xor, ^)
94
95
96 /* Use this helper to test instruction template flags */
97 #define itemp_has(itemp, bit)   iflag_test(&insns_flags[(itemp)->iflag_idx], bit)
98
99
100 /* Maximum processor level at moment */
101 #define IF_PLEVEL               IF_IA64
102 /* Some helpers which are to work with predefined masks */
103 #define IF_SMASK        \
104     (IF_GENBIT(IF_SB)  |\
105      IF_GENBIT(IF_SW)  |\
106      IF_GENBIT(IF_SD)  |\
107      IF_GENBIT(IF_SQ)  |\
108      IF_GENBIT(IF_SO)  |\
109      IF_GENBIT(IF_SY)  |\
110      IF_GENBIT(IF_SZ)  |\
111      IF_GENBIT(IF_SIZE))
112 #define IF_ARMASK       \
113     (IF_GENBIT(IF_AR0) |\
114      IF_GENBIT(IF_AR1) |\
115      IF_GENBIT(IF_AR2) |\
116      IF_GENBIT(IF_AR3) |\
117      IF_GENBIT(IF_AR4))
118
119 #define _itemp_smask(idx)      (insns_flags[(idx)].field[0] & IF_SMASK)
120 #define _itemp_armask(idx)     (insns_flags[(idx)].field[0] & IF_ARMASK)
121 #define _itemp_arg(idx)        ((_itemp_armask(idx) >> IF_AR0) - 1)
122
123 #define itemp_smask(itemp)      _itemp_smask((itemp)->iflag_idx)
124 #define itemp_arg(itemp)        _itemp_arg((itemp)->iflag_idx)
125 #define itemp_armask(itemp)     _itemp_armask((itemp)->iflag_idx)
126
127 static inline int iflag_cmp_cpu_level(const iflag_t *a, const iflag_t *b)
128 {
129     iflag_t v1 = *a;
130     iflag_t v2 = *b;
131
132     iflag_clear(&v1, IF_CYRIX);
133     iflag_clear(&v1, IF_AMD);
134
135     iflag_clear(&v2, IF_CYRIX);
136     iflag_clear(&v2, IF_AMD);
137
138     if (v1.field[3] < v2.field[3])
139         return -1;
140     else if (v1.field[3] > v2.field[3])
141         return 1;
142
143     return 0;
144 }
145
146 static inline iflag_t _iflag_pfmask(const iflag_t *a)
147 {
148         iflag_t r = IFLAG_INIT;
149
150         if (iflag_test(a, IF_CYRIX))
151                 iflag_set(&r, IF_CYRIX);
152         if (iflag_test(a, IF_AMD))
153                 iflag_set(&r, IF_AMD);
154
155         return r;
156 }
157
158 #define iflag_pfmask(itemp)     _iflag_pfmask(&insns_flags[(itemp)->iflag_idx])
159
160 #endif /* NASM_IFLAG_H */