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