]>
Commit | Line | Data |
---|---|---|
5918fffb BS |
1 | /* |
2 | * x86 condition code helpers | |
3 | * | |
4 | * Copyright (c) 2003 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 | |
d9ff33ad | 9 | * version 2.1 of the License, or (at your option) any later version. |
5918fffb BS |
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 | ||
b6a0aa05 | 20 | #include "qemu/osdep.h" |
5918fffb | 21 | #include "cpu.h" |
2ef6175a | 22 | #include "exec/helper-proto.h" |
ed69e831 | 23 | #include "helper-tcg.h" |
5918fffb BS |
24 | |
25 | const uint8_t parity_table[256] = { | |
26 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
27 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
28 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
29 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
30 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
31 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
32 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
33 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
34 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
35 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
36 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
37 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
38 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
39 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
40 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
41 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
42 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
43 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
44 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
45 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
46 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
47 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
48 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
49 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
50 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
51 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
52 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
53 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
54 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
55 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
56 | CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0, | |
57 | 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P, | |
58 | }; | |
59 | ||
60 | #define SHIFT 0 | |
61 | #include "cc_helper_template.h" | |
62 | #undef SHIFT | |
63 | ||
64 | #define SHIFT 1 | |
65 | #include "cc_helper_template.h" | |
66 | #undef SHIFT | |
67 | ||
68 | #define SHIFT 2 | |
69 | #include "cc_helper_template.h" | |
70 | #undef SHIFT | |
71 | ||
72 | #ifdef TARGET_X86_64 | |
73 | ||
74 | #define SHIFT 3 | |
75 | #include "cc_helper_template.h" | |
76 | #undef SHIFT | |
77 | ||
78 | #endif | |
79 | ||
cd7f97ca RH |
80 | static target_ulong compute_all_adcx(target_ulong dst, target_ulong src1, |
81 | target_ulong src2) | |
82 | { | |
83 | return (src1 & ~CC_C) | (dst * CC_C); | |
84 | } | |
85 | ||
86 | static target_ulong compute_all_adox(target_ulong dst, target_ulong src1, | |
87 | target_ulong src2) | |
88 | { | |
89 | return (src1 & ~CC_O) | (src2 * CC_O); | |
90 | } | |
91 | ||
92 | static target_ulong compute_all_adcox(target_ulong dst, target_ulong src1, | |
93 | target_ulong src2) | |
94 | { | |
95 | return (src1 & ~(CC_C | CC_O)) | (dst * CC_C) | (src2 * CC_O); | |
96 | } | |
97 | ||
988c3eb0 RH |
98 | target_ulong helper_cc_compute_all(target_ulong dst, target_ulong src1, |
99 | target_ulong src2, int op) | |
5918fffb BS |
100 | { |
101 | switch (op) { | |
102 | default: /* should never happen */ | |
103 | return 0; | |
104 | ||
105 | case CC_OP_EFLAGS: | |
8601c0b6 | 106 | return src1; |
436ff2d2 | 107 | case CC_OP_CLR: |
d2fe51bd | 108 | return CC_Z | CC_P; |
4885c3c4 RH |
109 | case CC_OP_POPCNT: |
110 | return src1 ? 0 : CC_Z; | |
5918fffb BS |
111 | |
112 | case CC_OP_MULB: | |
8601c0b6 | 113 | return compute_all_mulb(dst, src1); |
5918fffb | 114 | case CC_OP_MULW: |
8601c0b6 | 115 | return compute_all_mulw(dst, src1); |
5918fffb | 116 | case CC_OP_MULL: |
8601c0b6 | 117 | return compute_all_mull(dst, src1); |
5918fffb BS |
118 | |
119 | case CC_OP_ADDB: | |
8601c0b6 | 120 | return compute_all_addb(dst, src1); |
5918fffb | 121 | case CC_OP_ADDW: |
8601c0b6 | 122 | return compute_all_addw(dst, src1); |
5918fffb | 123 | case CC_OP_ADDL: |
8601c0b6 | 124 | return compute_all_addl(dst, src1); |
5918fffb BS |
125 | |
126 | case CC_OP_ADCB: | |
988c3eb0 | 127 | return compute_all_adcb(dst, src1, src2); |
5918fffb | 128 | case CC_OP_ADCW: |
988c3eb0 | 129 | return compute_all_adcw(dst, src1, src2); |
5918fffb | 130 | case CC_OP_ADCL: |
988c3eb0 | 131 | return compute_all_adcl(dst, src1, src2); |
5918fffb BS |
132 | |
133 | case CC_OP_SUBB: | |
8601c0b6 | 134 | return compute_all_subb(dst, src1); |
5918fffb | 135 | case CC_OP_SUBW: |
8601c0b6 | 136 | return compute_all_subw(dst, src1); |
5918fffb | 137 | case CC_OP_SUBL: |
8601c0b6 | 138 | return compute_all_subl(dst, src1); |
5918fffb BS |
139 | |
140 | case CC_OP_SBBB: | |
988c3eb0 | 141 | return compute_all_sbbb(dst, src1, src2); |
5918fffb | 142 | case CC_OP_SBBW: |
988c3eb0 | 143 | return compute_all_sbbw(dst, src1, src2); |
5918fffb | 144 | case CC_OP_SBBL: |
988c3eb0 | 145 | return compute_all_sbbl(dst, src1, src2); |
5918fffb BS |
146 | |
147 | case CC_OP_LOGICB: | |
8601c0b6 | 148 | return compute_all_logicb(dst, src1); |
5918fffb | 149 | case CC_OP_LOGICW: |
8601c0b6 | 150 | return compute_all_logicw(dst, src1); |
5918fffb | 151 | case CC_OP_LOGICL: |
8601c0b6 | 152 | return compute_all_logicl(dst, src1); |
5918fffb BS |
153 | |
154 | case CC_OP_INCB: | |
8601c0b6 | 155 | return compute_all_incb(dst, src1); |
5918fffb | 156 | case CC_OP_INCW: |
8601c0b6 | 157 | return compute_all_incw(dst, src1); |
5918fffb | 158 | case CC_OP_INCL: |
8601c0b6 | 159 | return compute_all_incl(dst, src1); |
5918fffb BS |
160 | |
161 | case CC_OP_DECB: | |
8601c0b6 | 162 | return compute_all_decb(dst, src1); |
5918fffb | 163 | case CC_OP_DECW: |
8601c0b6 | 164 | return compute_all_decw(dst, src1); |
5918fffb | 165 | case CC_OP_DECL: |
8601c0b6 | 166 | return compute_all_decl(dst, src1); |
5918fffb BS |
167 | |
168 | case CC_OP_SHLB: | |
8601c0b6 | 169 | return compute_all_shlb(dst, src1); |
5918fffb | 170 | case CC_OP_SHLW: |
8601c0b6 | 171 | return compute_all_shlw(dst, src1); |
5918fffb | 172 | case CC_OP_SHLL: |
8601c0b6 | 173 | return compute_all_shll(dst, src1); |
5918fffb BS |
174 | |
175 | case CC_OP_SARB: | |
8601c0b6 | 176 | return compute_all_sarb(dst, src1); |
5918fffb | 177 | case CC_OP_SARW: |
8601c0b6 | 178 | return compute_all_sarw(dst, src1); |
5918fffb | 179 | case CC_OP_SARL: |
8601c0b6 | 180 | return compute_all_sarl(dst, src1); |
5918fffb | 181 | |
bc4b43dc RH |
182 | case CC_OP_BMILGB: |
183 | return compute_all_bmilgb(dst, src1); | |
184 | case CC_OP_BMILGW: | |
185 | return compute_all_bmilgw(dst, src1); | |
186 | case CC_OP_BMILGL: | |
187 | return compute_all_bmilgl(dst, src1); | |
188 | ||
cd7f97ca RH |
189 | case CC_OP_ADCX: |
190 | return compute_all_adcx(dst, src1, src2); | |
191 | case CC_OP_ADOX: | |
192 | return compute_all_adox(dst, src1, src2); | |
193 | case CC_OP_ADCOX: | |
194 | return compute_all_adcox(dst, src1, src2); | |
195 | ||
5918fffb BS |
196 | #ifdef TARGET_X86_64 |
197 | case CC_OP_MULQ: | |
8601c0b6 | 198 | return compute_all_mulq(dst, src1); |
5918fffb | 199 | case CC_OP_ADDQ: |
8601c0b6 | 200 | return compute_all_addq(dst, src1); |
5918fffb | 201 | case CC_OP_ADCQ: |
988c3eb0 | 202 | return compute_all_adcq(dst, src1, src2); |
5918fffb | 203 | case CC_OP_SUBQ: |
8601c0b6 | 204 | return compute_all_subq(dst, src1); |
5918fffb | 205 | case CC_OP_SBBQ: |
988c3eb0 | 206 | return compute_all_sbbq(dst, src1, src2); |
5918fffb | 207 | case CC_OP_LOGICQ: |
8601c0b6 | 208 | return compute_all_logicq(dst, src1); |
5918fffb | 209 | case CC_OP_INCQ: |
8601c0b6 | 210 | return compute_all_incq(dst, src1); |
5918fffb | 211 | case CC_OP_DECQ: |
8601c0b6 | 212 | return compute_all_decq(dst, src1); |
5918fffb | 213 | case CC_OP_SHLQ: |
8601c0b6 | 214 | return compute_all_shlq(dst, src1); |
5918fffb | 215 | case CC_OP_SARQ: |
8601c0b6 | 216 | return compute_all_sarq(dst, src1); |
bc4b43dc RH |
217 | case CC_OP_BMILGQ: |
218 | return compute_all_bmilgq(dst, src1); | |
5918fffb BS |
219 | #endif |
220 | } | |
221 | } | |
222 | ||
f0967a1a | 223 | uint32_t cpu_cc_compute_all(CPUX86State *env, int op) |
5918fffb | 224 | { |
988c3eb0 | 225 | return helper_cc_compute_all(CC_DST, CC_SRC, CC_SRC2, op); |
5918fffb BS |
226 | } |
227 | ||
988c3eb0 RH |
228 | target_ulong helper_cc_compute_c(target_ulong dst, target_ulong src1, |
229 | target_ulong src2, int op) | |
5918fffb BS |
230 | { |
231 | switch (op) { | |
232 | default: /* should never happen */ | |
8601c0b6 RH |
233 | case CC_OP_LOGICB: |
234 | case CC_OP_LOGICW: | |
235 | case CC_OP_LOGICL: | |
236 | case CC_OP_LOGICQ: | |
436ff2d2 | 237 | case CC_OP_CLR: |
4885c3c4 | 238 | case CC_OP_POPCNT: |
5918fffb BS |
239 | return 0; |
240 | ||
241 | case CC_OP_EFLAGS: | |
8601c0b6 RH |
242 | case CC_OP_SARB: |
243 | case CC_OP_SARW: | |
244 | case CC_OP_SARL: | |
245 | case CC_OP_SARQ: | |
cd7f97ca | 246 | case CC_OP_ADOX: |
8601c0b6 RH |
247 | return src1 & 1; |
248 | ||
249 | case CC_OP_INCB: | |
250 | case CC_OP_INCW: | |
251 | case CC_OP_INCL: | |
252 | case CC_OP_INCQ: | |
253 | case CC_OP_DECB: | |
254 | case CC_OP_DECW: | |
255 | case CC_OP_DECL: | |
256 | case CC_OP_DECQ: | |
257 | return src1; | |
5918fffb BS |
258 | |
259 | case CC_OP_MULB: | |
5918fffb | 260 | case CC_OP_MULW: |
5918fffb | 261 | case CC_OP_MULL: |
8601c0b6 RH |
262 | case CC_OP_MULQ: |
263 | return src1 != 0; | |
5918fffb | 264 | |
cd7f97ca RH |
265 | case CC_OP_ADCX: |
266 | case CC_OP_ADCOX: | |
267 | return dst; | |
268 | ||
5918fffb | 269 | case CC_OP_ADDB: |
8601c0b6 | 270 | return compute_c_addb(dst, src1); |
5918fffb | 271 | case CC_OP_ADDW: |
8601c0b6 | 272 | return compute_c_addw(dst, src1); |
5918fffb | 273 | case CC_OP_ADDL: |
8601c0b6 | 274 | return compute_c_addl(dst, src1); |
5918fffb BS |
275 | |
276 | case CC_OP_ADCB: | |
988c3eb0 | 277 | return compute_c_adcb(dst, src1, src2); |
5918fffb | 278 | case CC_OP_ADCW: |
988c3eb0 | 279 | return compute_c_adcw(dst, src1, src2); |
5918fffb | 280 | case CC_OP_ADCL: |
988c3eb0 | 281 | return compute_c_adcl(dst, src1, src2); |
5918fffb BS |
282 | |
283 | case CC_OP_SUBB: | |
8601c0b6 | 284 | return compute_c_subb(dst, src1); |
5918fffb | 285 | case CC_OP_SUBW: |
8601c0b6 | 286 | return compute_c_subw(dst, src1); |
5918fffb | 287 | case CC_OP_SUBL: |
8601c0b6 | 288 | return compute_c_subl(dst, src1); |
5918fffb BS |
289 | |
290 | case CC_OP_SBBB: | |
988c3eb0 | 291 | return compute_c_sbbb(dst, src1, src2); |
5918fffb | 292 | case CC_OP_SBBW: |
988c3eb0 | 293 | return compute_c_sbbw(dst, src1, src2); |
5918fffb | 294 | case CC_OP_SBBL: |
988c3eb0 | 295 | return compute_c_sbbl(dst, src1, src2); |
5918fffb BS |
296 | |
297 | case CC_OP_SHLB: | |
8601c0b6 | 298 | return compute_c_shlb(dst, src1); |
5918fffb | 299 | case CC_OP_SHLW: |
8601c0b6 | 300 | return compute_c_shlw(dst, src1); |
5918fffb | 301 | case CC_OP_SHLL: |
8601c0b6 | 302 | return compute_c_shll(dst, src1); |
5918fffb | 303 | |
bc4b43dc RH |
304 | case CC_OP_BMILGB: |
305 | return compute_c_bmilgb(dst, src1); | |
306 | case CC_OP_BMILGW: | |
307 | return compute_c_bmilgw(dst, src1); | |
308 | case CC_OP_BMILGL: | |
309 | return compute_c_bmilgl(dst, src1); | |
310 | ||
5918fffb | 311 | #ifdef TARGET_X86_64 |
5918fffb | 312 | case CC_OP_ADDQ: |
8601c0b6 | 313 | return compute_c_addq(dst, src1); |
5918fffb | 314 | case CC_OP_ADCQ: |
988c3eb0 | 315 | return compute_c_adcq(dst, src1, src2); |
5918fffb | 316 | case CC_OP_SUBQ: |
8601c0b6 | 317 | return compute_c_subq(dst, src1); |
5918fffb | 318 | case CC_OP_SBBQ: |
988c3eb0 | 319 | return compute_c_sbbq(dst, src1, src2); |
5918fffb | 320 | case CC_OP_SHLQ: |
8601c0b6 | 321 | return compute_c_shlq(dst, src1); |
bc4b43dc RH |
322 | case CC_OP_BMILGQ: |
323 | return compute_c_bmilgq(dst, src1); | |
5918fffb BS |
324 | #endif |
325 | } | |
326 | } | |
327 | ||
f0967a1a BS |
328 | void helper_write_eflags(CPUX86State *env, target_ulong t0, |
329 | uint32_t update_mask) | |
5918fffb BS |
330 | { |
331 | cpu_load_eflags(env, t0, update_mask); | |
332 | } | |
333 | ||
f0967a1a | 334 | target_ulong helper_read_eflags(CPUX86State *env) |
5918fffb BS |
335 | { |
336 | uint32_t eflags; | |
337 | ||
db9f2597 | 338 | eflags = cpu_cc_compute_all(env, CC_OP); |
80cf2c81 | 339 | eflags |= (env->df & DF_MASK); |
5918fffb BS |
340 | eflags |= env->eflags & ~(VM_MASK | RF_MASK); |
341 | return eflags; | |
342 | } | |
343 | ||
f0967a1a | 344 | void helper_clts(CPUX86State *env) |
5918fffb BS |
345 | { |
346 | env->cr[0] &= ~CR0_TS_MASK; | |
347 | env->hflags &= ~HF_TS_MASK; | |
348 | } |