root / target-i386 / cc_helper_template.h @ 3523e4bd
History | View | Annotate | Download (6.6 kB)
1 |
/*
|
---|---|
2 |
* x86 condition code helpers
|
3 |
*
|
4 |
* Copyright (c) 2008 Fabrice Bellard
|
5 |
*
|
6 |
* This library is free software; you can redistribute it and/or
|
7 |
* modify it under the terms of the GNU Lesser General Public
|
8 |
* License as published by the Free Software Foundation; either
|
9 |
* version 2 of the License, or (at your option) any later version.
|
10 |
*
|
11 |
* This library is distributed in the hope that it will be useful,
|
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
14 |
* Lesser General Public License for more details.
|
15 |
*
|
16 |
* You should have received a copy of the GNU Lesser General Public
|
17 |
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
18 |
*/
|
19 |
|
20 |
#define DATA_BITS (1 << (3 + SHIFT)) |
21 |
|
22 |
#if DATA_BITS == 8 |
23 |
#define SUFFIX b
|
24 |
#define DATA_TYPE uint8_t
|
25 |
#elif DATA_BITS == 16 |
26 |
#define SUFFIX w
|
27 |
#define DATA_TYPE uint16_t
|
28 |
#elif DATA_BITS == 32 |
29 |
#define SUFFIX l
|
30 |
#define DATA_TYPE uint32_t
|
31 |
#elif DATA_BITS == 64 |
32 |
#define SUFFIX q
|
33 |
#define DATA_TYPE uint64_t
|
34 |
#else
|
35 |
#error unhandled operand size
|
36 |
#endif
|
37 |
|
38 |
#define SIGN_MASK (((DATA_TYPE)1) << (DATA_BITS - 1)) |
39 |
|
40 |
/* dynamic flags computation */
|
41 |
|
42 |
static int glue(compute_all_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
43 |
{ |
44 |
int cf, pf, af, zf, sf, of;
|
45 |
DATA_TYPE src2 = dst - src1; |
46 |
|
47 |
cf = dst < src1; |
48 |
pf = parity_table[(uint8_t)dst]; |
49 |
af = (dst ^ src1 ^ src2) & CC_A; |
50 |
zf = (dst == 0) * CC_Z;
|
51 |
sf = lshift(dst, 8 - DATA_BITS) & CC_S;
|
52 |
of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), 12 - DATA_BITS) & CC_O; |
53 |
return cf | pf | af | zf | sf | of;
|
54 |
} |
55 |
|
56 |
static int glue(compute_c_add, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
57 |
{ |
58 |
return dst < src1;
|
59 |
} |
60 |
|
61 |
static int glue(compute_all_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1, |
62 |
DATA_TYPE src3) |
63 |
{ |
64 |
int cf, pf, af, zf, sf, of;
|
65 |
DATA_TYPE src2 = dst - src1 - src3; |
66 |
|
67 |
cf = (src3 ? dst <= src1 : dst < src1); |
68 |
pf = parity_table[(uint8_t)dst]; |
69 |
af = (dst ^ src1 ^ src2) & 0x10;
|
70 |
zf = (dst == 0) << 6; |
71 |
sf = lshift(dst, 8 - DATA_BITS) & 0x80; |
72 |
of = lshift((src1 ^ src2 ^ -1) & (src1 ^ dst), 12 - DATA_BITS) & CC_O; |
73 |
return cf | pf | af | zf | sf | of;
|
74 |
} |
75 |
|
76 |
static int glue(compute_c_adc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1, |
77 |
DATA_TYPE src3) |
78 |
{ |
79 |
return src3 ? dst <= src1 : dst < src1;
|
80 |
} |
81 |
|
82 |
static int glue(compute_all_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2) |
83 |
{ |
84 |
int cf, pf, af, zf, sf, of;
|
85 |
DATA_TYPE src1 = dst + src2; |
86 |
|
87 |
cf = src1 < src2; |
88 |
pf = parity_table[(uint8_t)dst]; |
89 |
af = (dst ^ src1 ^ src2) & CC_A; |
90 |
zf = (dst == 0) * CC_Z;
|
91 |
sf = lshift(dst, 8 - DATA_BITS) & CC_S;
|
92 |
of = lshift((src1 ^ src2) & (src1 ^ dst), 12 - DATA_BITS) & CC_O;
|
93 |
return cf | pf | af | zf | sf | of;
|
94 |
} |
95 |
|
96 |
static int glue(compute_c_sub, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2) |
97 |
{ |
98 |
DATA_TYPE src1 = dst + src2; |
99 |
|
100 |
return src1 < src2;
|
101 |
} |
102 |
|
103 |
static int glue(compute_all_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2, |
104 |
DATA_TYPE src3) |
105 |
{ |
106 |
int cf, pf, af, zf, sf, of;
|
107 |
DATA_TYPE src1 = dst + src2 + src3; |
108 |
|
109 |
cf = (src3 ? src1 <= src2 : src1 < src2); |
110 |
pf = parity_table[(uint8_t)dst]; |
111 |
af = (dst ^ src1 ^ src2) & 0x10;
|
112 |
zf = (dst == 0) << 6; |
113 |
sf = lshift(dst, 8 - DATA_BITS) & 0x80; |
114 |
of = lshift((src1 ^ src2) & (src1 ^ dst), 12 - DATA_BITS) & CC_O;
|
115 |
return cf | pf | af | zf | sf | of;
|
116 |
} |
117 |
|
118 |
static int glue(compute_c_sbb, SUFFIX)(DATA_TYPE dst, DATA_TYPE src2, |
119 |
DATA_TYPE src3) |
120 |
{ |
121 |
DATA_TYPE src1 = dst + src2 + src3; |
122 |
|
123 |
return (src3 ? src1 <= src2 : src1 < src2);
|
124 |
} |
125 |
|
126 |
static int glue(compute_all_logic, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
127 |
{ |
128 |
int cf, pf, af, zf, sf, of;
|
129 |
|
130 |
cf = 0;
|
131 |
pf = parity_table[(uint8_t)dst]; |
132 |
af = 0;
|
133 |
zf = (dst == 0) * CC_Z;
|
134 |
sf = lshift(dst, 8 - DATA_BITS) & CC_S;
|
135 |
of = 0;
|
136 |
return cf | pf | af | zf | sf | of;
|
137 |
} |
138 |
|
139 |
static int glue(compute_all_inc, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
140 |
{ |
141 |
int cf, pf, af, zf, sf, of;
|
142 |
DATA_TYPE src2; |
143 |
|
144 |
cf = src1; |
145 |
src1 = dst - 1;
|
146 |
src2 = 1;
|
147 |
pf = parity_table[(uint8_t)dst]; |
148 |
af = (dst ^ src1 ^ src2) & CC_A; |
149 |
zf = (dst == 0) * CC_Z;
|
150 |
sf = lshift(dst, 8 - DATA_BITS) & CC_S;
|
151 |
of = (dst == SIGN_MASK) * CC_O; |
152 |
return cf | pf | af | zf | sf | of;
|
153 |
} |
154 |
|
155 |
static int glue(compute_all_dec, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
156 |
{ |
157 |
int cf, pf, af, zf, sf, of;
|
158 |
DATA_TYPE src2; |
159 |
|
160 |
cf = src1; |
161 |
src1 = dst + 1;
|
162 |
src2 = 1;
|
163 |
pf = parity_table[(uint8_t)dst]; |
164 |
af = (dst ^ src1 ^ src2) & CC_A; |
165 |
zf = (dst == 0) * CC_Z;
|
166 |
sf = lshift(dst, 8 - DATA_BITS) & CC_S;
|
167 |
of = (dst == SIGN_MASK - 1) * CC_O;
|
168 |
return cf | pf | af | zf | sf | of;
|
169 |
} |
170 |
|
171 |
static int glue(compute_all_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
172 |
{ |
173 |
int cf, pf, af, zf, sf, of;
|
174 |
|
175 |
cf = (src1 >> (DATA_BITS - 1)) & CC_C;
|
176 |
pf = parity_table[(uint8_t)dst]; |
177 |
af = 0; /* undefined */ |
178 |
zf = (dst == 0) * CC_Z;
|
179 |
sf = lshift(dst, 8 - DATA_BITS) & CC_S;
|
180 |
/* of is defined iff shift count == 1 */
|
181 |
of = lshift(src1 ^ dst, 12 - DATA_BITS) & CC_O;
|
182 |
return cf | pf | af | zf | sf | of;
|
183 |
} |
184 |
|
185 |
static int glue(compute_c_shl, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
186 |
{ |
187 |
return (src1 >> (DATA_BITS - 1)) & CC_C; |
188 |
} |
189 |
|
190 |
static int glue(compute_all_sar, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
191 |
{ |
192 |
int cf, pf, af, zf, sf, of;
|
193 |
|
194 |
cf = src1 & 1;
|
195 |
pf = parity_table[(uint8_t)dst]; |
196 |
af = 0; /* undefined */ |
197 |
zf = (dst == 0) * CC_Z;
|
198 |
sf = lshift(dst, 8 - DATA_BITS) & CC_S;
|
199 |
/* of is defined iff shift count == 1 */
|
200 |
of = lshift(src1 ^ dst, 12 - DATA_BITS) & CC_O;
|
201 |
return cf | pf | af | zf | sf | of;
|
202 |
} |
203 |
|
204 |
/* NOTE: we compute the flags like the P4. On olders CPUs, only OF and
|
205 |
CF are modified and it is slower to do that. Note as well that we
|
206 |
don't truncate SRC1 for computing carry to DATA_TYPE. */
|
207 |
static int glue(compute_all_mul, SUFFIX)(DATA_TYPE dst, target_long src1) |
208 |
{ |
209 |
int cf, pf, af, zf, sf, of;
|
210 |
|
211 |
cf = (src1 != 0);
|
212 |
pf = parity_table[(uint8_t)dst]; |
213 |
af = 0; /* undefined */ |
214 |
zf = (dst == 0) * CC_Z;
|
215 |
sf = lshift(dst, 8 - DATA_BITS) & CC_S;
|
216 |
of = cf * CC_O; |
217 |
return cf | pf | af | zf | sf | of;
|
218 |
} |
219 |
|
220 |
static int glue(compute_all_bmilg, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
221 |
{ |
222 |
int cf, pf, af, zf, sf, of;
|
223 |
|
224 |
cf = (src1 == 0);
|
225 |
pf = 0; /* undefined */ |
226 |
af = 0; /* undefined */ |
227 |
zf = (dst == 0) * CC_Z;
|
228 |
sf = lshift(dst, 8 - DATA_BITS) & CC_S;
|
229 |
of = 0;
|
230 |
return cf | pf | af | zf | sf | of;
|
231 |
} |
232 |
|
233 |
static int glue(compute_c_bmilg, SUFFIX)(DATA_TYPE dst, DATA_TYPE src1) |
234 |
{ |
235 |
return src1 == 0; |
236 |
} |
237 |
|
238 |
#undef DATA_BITS
|
239 |
#undef SIGN_MASK
|
240 |
#undef DATA_TYPE
|
241 |
#undef DATA_MASK
|
242 |
#undef SUFFIX
|