1 | #ifndef NASM_IFLAG_H |
2 | #define NASM_IFLAG_H |
3 | |
4 | #include "compiler.h" |
5 | #include "ilog2.h" |
6 | |
7 | #include <string.h> |
8 | |
9 | #include "iflaggen.h" |
10 | |
11 | #define IF_GENBIT(bit) (UINT32_C(1) << (bit)) |
12 | |
13 | static inline bool iflag_test(const iflag_t *f, unsigned int bit) |
14 | { |
15 | return !!(f->field[bit >> 5] & IF_GENBIT(bit & 31)); |
16 | } |
17 | |
18 | static inline void iflag_set(iflag_t *f, unsigned int bit) |
19 | { |
20 | f->field[bit >> 5] |= IF_GENBIT(bit & 31); |
21 | } |
22 | |
23 | static inline void iflag_clear(iflag_t *f, unsigned int bit) |
24 | { |
25 | f->field[bit >> 5] &= ~IF_GENBIT(bit & 31); |
26 | } |
27 | |
28 | static inline void iflag_clear_all(iflag_t *f) |
29 | { |
30 | memset(f, 0, sizeof(*f)); |
31 | } |
32 | |
33 | static inline void iflag_set_all(iflag_t *f) |
34 | { |
35 | memset(f, ~0, sizeof(*f)); |
36 | } |
37 | |
38 | #define iflag_for_each_field(v) for ((v) = 0; (v) < IF_FIELD_COUNT; (v)++) |
39 | |
40 | static inline int iflag_cmp(const iflag_t *a, const iflag_t *b) |
41 | { |
42 | int i; |
43 | |
44 | /* This is intentionally a reverse loop! */ |
45 | for (i = IF_FIELD_COUNT-1; i >= 0; i--) { |
46 | if (a->field[i] == b->field[i]) |
47 | continue; |
48 | |
49 | return (int)(a->field[i] - b->field[i]); |
50 | } |
51 | |
52 | return 0; |
53 | } |
54 | |
55 | #define IF_GEN_HELPER(name, op) \ |
56 | static inline iflag_t iflag_##name(const iflag_t *a, const iflag_t *b) \ |
57 | { \ |
58 | unsigned int i; \ |
59 | iflag_t res; \ |
60 | \ |
61 | iflag_for_each_field(i) \ |
62 | res.field[i] = a->field[i] op b->field[i]; \ |
63 | \ |
64 | return res; \ |
65 | } |
66 | |
67 | IF_GEN_HELPER(xor, ^) |
68 | |
69 | /* Some helpers which are to work with predefined masks */ |
70 | #define IF_SMASK \ |
71 | (IF_GENBIT(IF_SB) |\ |
72 | IF_GENBIT(IF_SW) |\ |
73 | IF_GENBIT(IF_SD) |\ |
74 | IF_GENBIT(IF_SQ) |\ |
75 | IF_GENBIT(IF_SO) |\ |
76 | IF_GENBIT(IF_SY) |\ |
77 | IF_GENBIT(IF_SZ) |\ |
78 | IF_GENBIT(IF_SIZE)) |
79 | #define IF_ARMASK \ |
80 | (IF_GENBIT(IF_AR0) |\ |
81 | IF_GENBIT(IF_AR1) |\ |
82 | IF_GENBIT(IF_AR2) |\ |
83 | IF_GENBIT(IF_AR3) |\ |
84 | IF_GENBIT(IF_AR4)) |
85 | |
86 | #define _itemp_smask(idx) (insns_flags[(idx)].field[0] & IF_SMASK) |
87 | #define _itemp_armask(idx) (insns_flags[(idx)].field[0] & IF_ARMASK) |
88 | #define _itemp_arg(idx) ((_itemp_armask(idx) >> IF_AR0) - 1) |
89 | |
90 | #define itemp_smask(itemp) _itemp_smask((itemp)->iflag_idx) |
91 | #define itemp_arg(itemp) _itemp_arg((itemp)->iflag_idx) |
92 | #define itemp_armask(itemp) _itemp_armask((itemp)->iflag_idx) |
93 | |
94 | /* |
95 | * IF_8086 is the first CPU level flag and IF_PLEVEL the last |
96 | */ |
97 | #if IF_8086 & 31 |
98 | #error "IF_8086 must be on a uint32_t boundary" |
99 | #endif |
100 | #define IF_PLEVEL IF_IA64 |
101 | #define IF_CPU_FIELD (IF_8086 >> 5) |
102 | #define IF_CPU_LEVEL_MASK ((IF_GENBIT(IF_PLEVEL & 31) << 1) - 1) |
103 | |
104 | /* |
105 | * IF_PRIV is the firstr instruction filtering flag |
106 | */ |
107 | #if IF_PRIV & 31 |
108 | #error "IF_PRIV must be on a uint32_t boundary" |
109 | #endif |
110 | #define IF_FEATURE_FIELD (IF_PRIV >> 5) |
111 | |
112 | static inline int iflag_cmp_cpu(const iflag_t *a, const iflag_t *b) |
113 | { |
114 | return (int)(a->field[IF_CPU_FIELD] - b->field[IF_CPU_FIELD]); |
115 | } |
116 | |
117 | static inline uint32_t _iflag_cpu_level(const iflag_t *a) |
118 | { |
119 | return a->field[IF_CPU_FIELD] & IF_CPU_LEVEL_MASK; |
120 | } |
121 | |
122 | static inline int iflag_cmp_cpu_level(const iflag_t *a, const iflag_t *b) |
123 | { |
124 | uint32_t aa = _iflag_cpu_level(a); |
125 | uint32_t bb = _iflag_cpu_level(b); |
126 | |
127 | return (int)(aa - bb); |
128 | } |
129 | |
130 | /* Returns true if the CPU level is at least a certain value */ |
131 | static inline bool iflag_cpu_level_ok(const iflag_t *a, unsigned int bit) |
132 | { |
133 | return _iflag_cpu_level(a) >= IF_GENBIT(bit & 31); |
134 | } |
135 | |
136 | static inline void iflag_set_all_features(iflag_t *a) |
137 | { |
138 | size_t i; |
139 | |
140 | for (i = IF_FEATURE_FIELD; i < IF_CPU_FIELD; i++) |
141 | a->field[i] = ~UINT32_C(0); |
142 | } |
143 | |
144 | static inline void iflag_set_cpu(iflag_t *a, unsigned int cpu) |
145 | { |
146 | a->field[0] = 0; /* Not applicable to the CPU type */ |
147 | iflag_set_all_features(a); /* All feature masking bits set for now */ |
148 | a->field[IF_CPU_FIELD] &= ~IF_CPU_LEVEL_MASK; |
149 | iflag_set(a, cpu); |
150 | } |
151 | |
152 | static inline void iflag_set_default_cpu(iflag_t *a) |
153 | { |
154 | iflag_set_cpu(a, IF_PLEVEL); |
155 | } |
156 | |
157 | static inline iflag_t _iflag_pfmask(const iflag_t *a) |
158 | { |
159 | iflag_t r; |
160 | |
161 | iflag_clear_all(&r); |
162 | |
163 | if (iflag_test(a, IF_CYRIX)) |
164 | iflag_set(&r, IF_CYRIX); |
165 | if (iflag_test(a, IF_AMD)) |
166 | iflag_set(&r, IF_AMD); |
167 | |
168 | return r; |
169 | } |
170 | |
171 | #define iflag_pfmask(itemp) _iflag_pfmask(&insns_flags[(itemp)->iflag_idx]) |
172 | |
173 | #endif /* NASM_IFLAG_H */ |
174 | |