iflag: remove C99 constructs, don't hardcode the number of words
[nasm.git] / iflag.h
blob72929eec81de7e59fdec2d9b1f7aa41aec007b5f
1 #ifndef NASM_IFLAG_H
2 #define NASM_IFLAG_H
4 #include <inttypes.h>
6 #include <string.h>
8 #include "compiler.h"
10 int ilog2_32(uint32_t v);
13 * Instruction template flags. These specify which processor
14 * targets the instruction is eligible for, whether it is
15 * privileged or undocumented, and also specify extra error
16 * checking on the matching of the instruction.
18 * IF_SM stands for Size Match: any operand whose size is not
19 * explicitly specified by the template is `really' intended to be
20 * the same size as the first size-specified operand.
21 * Non-specification is tolerated in the input instruction, but
22 * _wrong_ specification is not.
24 * IF_SM2 invokes Size Match on only the first _two_ operands, for
25 * three-operand instructions such as SHLD: it implies that the
26 * first two operands must match in size, but that the third is
27 * required to be _unspecified_.
29 * IF_SB invokes Size Byte: operands with unspecified size in the
30 * template are really bytes, and so no non-byte specification in
31 * the input instruction will be tolerated. IF_SW similarly invokes
32 * Size Word, and IF_SD invokes Size Doubleword.
34 * (The default state if neither IF_SM nor IF_SM2 is specified is
35 * that any operand with unspecified size in the template is
36 * required to have unspecified size in the instruction too...)
38 * iflag_t is defined to store these flags.
40 #include "iflaggen.h"
42 #define IF_GENBIT(bit) (UINT32_C(1) << (bit))
44 static inline unsigned int iflag_test(iflag_t *f,unsigned int bit)
46 unsigned int index = bit / 32;
47 return f->field[index] & (UINT32_C(1) << (bit - (index * 32)));
50 static inline void iflag_set(iflag_t *f, unsigned int bit)
52 unsigned int index = bit / 32;
53 f->field[index] |= (UINT32_C(1) << (bit - (index * 32)));
56 static inline void iflag_clear(iflag_t *f, unsigned int bit)
58 unsigned int index = bit / 32;
59 f->field[index] &= ~(UINT32_C(1) << (bit - (index * 32)));
62 static inline void iflag_clear_all(iflag_t *f)
64 memset(f, 0, sizeof(*f));
67 static inline void iflag_set_all(iflag_t *f)
69 memset(f, 0xff, sizeof(*f));
72 static inline int iflag_cmp(iflag_t *a, iflag_t *b)
74 unsigned int i;
76 for (i = 0; i < sizeof(a->field) / sizeof(a->field[0]); i++) {
77 if (a->field[i] < b->field[i])
78 return -1;
79 else if (a->field[i] > b->field[i])
80 return 1;
83 return 0;
86 static inline int iflag_cmp_cpu(iflag_t *a, iflag_t *b)
88 if (a->field[3] < b->field[3])
89 return -1;
90 else if (a->field[3] > b->field[3])
91 return 1;
92 return 0;
95 static inline unsigned int iflag_ffs(iflag_t *a)
97 unsigned int i;
99 for (i = 0; i < sizeof(a->field) / sizeof(a->field[0]); i++) {
100 if (a->field[i])
101 return ilog2_32(a->field[i]) + (i * 32);
104 return 0;
107 #define IF_GEN_HELPER(name, op) \
108 static inline iflag_t iflag_##name(iflag_t *a, iflag_t *b) \
110 unsigned int i; \
111 iflag_t res; \
113 for (i = 0; i < sizeof(a->field) / sizeof(a->field[0]); i++) \
114 res.field[i] = a->field[i] op b->field[i]; \
116 return res; \
119 IF_GEN_HELPER(xor, ^)
122 /* Use this helper to test instruction template flags */
123 #define itemp_has(itemp, bit) iflag_test(&insns_flags[(itemp)->iflag_idx], bit)
126 /* Maximum processor level at moment */
127 #define IF_PLEVEL IF_IA64
128 /* Some helpers which are to work with predefined masks */
129 #define IF_SMASK \
130 (IF_GENBIT(IF_SB) |\
131 IF_GENBIT(IF_SW) |\
132 IF_GENBIT(IF_SD) |\
133 IF_GENBIT(IF_SQ) |\
134 IF_GENBIT(IF_SO) |\
135 IF_GENBIT(IF_SY) |\
136 IF_GENBIT(IF_SZ) |\
137 IF_GENBIT(IF_SIZE))
138 #define IF_ARMASK \
139 (IF_GENBIT(IF_AR0) |\
140 IF_GENBIT(IF_AR1) |\
141 IF_GENBIT(IF_AR2) |\
142 IF_GENBIT(IF_AR3) |\
143 IF_GENBIT(IF_AR4))
145 #define __itemp_smask(idx) (insns_flags[(idx)].field[0] & IF_SMASK)
146 #define __itemp_armask(idx) (insns_flags[(idx)].field[0] & IF_ARMASK)
147 #define __itemp_arg(idx) ((__itemp_armask(idx) >> IF_AR0) - 1)
149 #define itemp_smask(itemp) __itemp_smask((itemp)->iflag_idx)
150 #define itemp_arg(itemp) __itemp_arg((itemp)->iflag_idx)
151 #define itemp_armask(itemp) __itemp_armask((itemp)->iflag_idx)
153 static inline int iflag_cmp_cpu_level(iflag_t *a, iflag_t *b)
155 iflag_t v1 = *a;
156 iflag_t v2 = *b;
158 iflag_clear(&v1, IF_CYRIX);
159 iflag_clear(&v1, IF_AMD);
161 iflag_clear(&v2, IF_CYRIX);
162 iflag_clear(&v2, IF_AMD);
164 if (v1.field[3] < v2.field[3])
165 return -1;
166 else if (v1.field[3] > v2.field[3])
167 return 1;
169 return 0;
172 static inline iflag_t __iflag_pfmask(iflag_t *a)
174 iflag_t r = (iflag_t) {
175 .field[1] = a->field[1],
176 .field[2] = a->field[2],
179 if (iflag_test(a, IF_CYRIX))
180 iflag_set(&r, IF_CYRIX);
181 if (iflag_test(a, IF_AMD))
182 iflag_set(&r, IF_AMD);
184 return r;
187 #define iflag_pfmask(itemp) __iflag_pfmask(&insns_flags[(itemp)->iflag_idx])
189 #endif /* NASM_IFLAG_H__ */