]> git.proxmox.com Git - qemu.git/blob - target-i386/cc_helper.c
x86: split off condition code helpers
[qemu.git] / target-i386 / cc_helper.c
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
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 #include "cpu.h"
21 #include "dyngen-exec.h"
22 #include "helper.h"
23
24 const uint8_t parity_table[256] = {
25 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
26 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
27 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
28 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
29 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
30 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
31 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
32 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
33 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
34 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
35 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
36 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
37 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
38 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
39 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
40 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
41 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
42 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
43 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
44 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
45 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
46 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
47 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
48 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
49 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
50 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
51 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
52 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
53 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
54 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
55 CC_P, 0, 0, CC_P, 0, CC_P, CC_P, 0,
56 0, CC_P, CC_P, 0, CC_P, 0, 0, CC_P,
57 };
58
59 #define SHIFT 0
60 #include "cc_helper_template.h"
61 #undef SHIFT
62
63 #define SHIFT 1
64 #include "cc_helper_template.h"
65 #undef SHIFT
66
67 #define SHIFT 2
68 #include "cc_helper_template.h"
69 #undef SHIFT
70
71 #ifdef TARGET_X86_64
72
73 #define SHIFT 3
74 #include "cc_helper_template.h"
75 #undef SHIFT
76
77 #endif
78
79 static int compute_all_eflags(void)
80 {
81 return CC_SRC;
82 }
83
84 static int compute_c_eflags(void)
85 {
86 return CC_SRC & CC_C;
87 }
88
89 uint32_t helper_cc_compute_all(int op)
90 {
91 switch (op) {
92 default: /* should never happen */
93 return 0;
94
95 case CC_OP_EFLAGS:
96 return compute_all_eflags();
97
98 case CC_OP_MULB:
99 return compute_all_mulb();
100 case CC_OP_MULW:
101 return compute_all_mulw();
102 case CC_OP_MULL:
103 return compute_all_mull();
104
105 case CC_OP_ADDB:
106 return compute_all_addb();
107 case CC_OP_ADDW:
108 return compute_all_addw();
109 case CC_OP_ADDL:
110 return compute_all_addl();
111
112 case CC_OP_ADCB:
113 return compute_all_adcb();
114 case CC_OP_ADCW:
115 return compute_all_adcw();
116 case CC_OP_ADCL:
117 return compute_all_adcl();
118
119 case CC_OP_SUBB:
120 return compute_all_subb();
121 case CC_OP_SUBW:
122 return compute_all_subw();
123 case CC_OP_SUBL:
124 return compute_all_subl();
125
126 case CC_OP_SBBB:
127 return compute_all_sbbb();
128 case CC_OP_SBBW:
129 return compute_all_sbbw();
130 case CC_OP_SBBL:
131 return compute_all_sbbl();
132
133 case CC_OP_LOGICB:
134 return compute_all_logicb();
135 case CC_OP_LOGICW:
136 return compute_all_logicw();
137 case CC_OP_LOGICL:
138 return compute_all_logicl();
139
140 case CC_OP_INCB:
141 return compute_all_incb();
142 case CC_OP_INCW:
143 return compute_all_incw();
144 case CC_OP_INCL:
145 return compute_all_incl();
146
147 case CC_OP_DECB:
148 return compute_all_decb();
149 case CC_OP_DECW:
150 return compute_all_decw();
151 case CC_OP_DECL:
152 return compute_all_decl();
153
154 case CC_OP_SHLB:
155 return compute_all_shlb();
156 case CC_OP_SHLW:
157 return compute_all_shlw();
158 case CC_OP_SHLL:
159 return compute_all_shll();
160
161 case CC_OP_SARB:
162 return compute_all_sarb();
163 case CC_OP_SARW:
164 return compute_all_sarw();
165 case CC_OP_SARL:
166 return compute_all_sarl();
167
168 #ifdef TARGET_X86_64
169 case CC_OP_MULQ:
170 return compute_all_mulq();
171
172 case CC_OP_ADDQ:
173 return compute_all_addq();
174
175 case CC_OP_ADCQ:
176 return compute_all_adcq();
177
178 case CC_OP_SUBQ:
179 return compute_all_subq();
180
181 case CC_OP_SBBQ:
182 return compute_all_sbbq();
183
184 case CC_OP_LOGICQ:
185 return compute_all_logicq();
186
187 case CC_OP_INCQ:
188 return compute_all_incq();
189
190 case CC_OP_DECQ:
191 return compute_all_decq();
192
193 case CC_OP_SHLQ:
194 return compute_all_shlq();
195
196 case CC_OP_SARQ:
197 return compute_all_sarq();
198 #endif
199 }
200 }
201
202 uint32_t cpu_cc_compute_all(CPUX86State *env1, int op)
203 {
204 CPUX86State *saved_env;
205 uint32_t ret;
206
207 saved_env = env;
208 env = env1;
209 ret = helper_cc_compute_all(op);
210 env = saved_env;
211 return ret;
212 }
213
214 uint32_t helper_cc_compute_c(int op)
215 {
216 switch (op) {
217 default: /* should never happen */
218 return 0;
219
220 case CC_OP_EFLAGS:
221 return compute_c_eflags();
222
223 case CC_OP_MULB:
224 return compute_c_mull();
225 case CC_OP_MULW:
226 return compute_c_mull();
227 case CC_OP_MULL:
228 return compute_c_mull();
229
230 case CC_OP_ADDB:
231 return compute_c_addb();
232 case CC_OP_ADDW:
233 return compute_c_addw();
234 case CC_OP_ADDL:
235 return compute_c_addl();
236
237 case CC_OP_ADCB:
238 return compute_c_adcb();
239 case CC_OP_ADCW:
240 return compute_c_adcw();
241 case CC_OP_ADCL:
242 return compute_c_adcl();
243
244 case CC_OP_SUBB:
245 return compute_c_subb();
246 case CC_OP_SUBW:
247 return compute_c_subw();
248 case CC_OP_SUBL:
249 return compute_c_subl();
250
251 case CC_OP_SBBB:
252 return compute_c_sbbb();
253 case CC_OP_SBBW:
254 return compute_c_sbbw();
255 case CC_OP_SBBL:
256 return compute_c_sbbl();
257
258 case CC_OP_LOGICB:
259 return compute_c_logicb();
260 case CC_OP_LOGICW:
261 return compute_c_logicw();
262 case CC_OP_LOGICL:
263 return compute_c_logicl();
264
265 case CC_OP_INCB:
266 return compute_c_incl();
267 case CC_OP_INCW:
268 return compute_c_incl();
269 case CC_OP_INCL:
270 return compute_c_incl();
271
272 case CC_OP_DECB:
273 return compute_c_incl();
274 case CC_OP_DECW:
275 return compute_c_incl();
276 case CC_OP_DECL:
277 return compute_c_incl();
278
279 case CC_OP_SHLB:
280 return compute_c_shlb();
281 case CC_OP_SHLW:
282 return compute_c_shlw();
283 case CC_OP_SHLL:
284 return compute_c_shll();
285
286 case CC_OP_SARB:
287 return compute_c_sarl();
288 case CC_OP_SARW:
289 return compute_c_sarl();
290 case CC_OP_SARL:
291 return compute_c_sarl();
292
293 #ifdef TARGET_X86_64
294 case CC_OP_MULQ:
295 return compute_c_mull();
296
297 case CC_OP_ADDQ:
298 return compute_c_addq();
299
300 case CC_OP_ADCQ:
301 return compute_c_adcq();
302
303 case CC_OP_SUBQ:
304 return compute_c_subq();
305
306 case CC_OP_SBBQ:
307 return compute_c_sbbq();
308
309 case CC_OP_LOGICQ:
310 return compute_c_logicq();
311
312 case CC_OP_INCQ:
313 return compute_c_incl();
314
315 case CC_OP_DECQ:
316 return compute_c_incl();
317
318 case CC_OP_SHLQ:
319 return compute_c_shlq();
320
321 case CC_OP_SARQ:
322 return compute_c_sarl();
323 #endif
324 }
325 }
326
327 void helper_write_eflags(target_ulong t0, uint32_t update_mask)
328 {
329 cpu_load_eflags(env, t0, update_mask);
330 }
331
332 target_ulong helper_read_eflags(void)
333 {
334 uint32_t eflags;
335
336 eflags = helper_cc_compute_all(CC_OP);
337 eflags |= (DF & DF_MASK);
338 eflags |= env->eflags & ~(VM_MASK | RF_MASK);
339 return eflags;
340 }
341
342 void helper_clts(void)
343 {
344 env->cr[0] &= ~CR0_TS_MASK;
345 env->hflags &= ~HF_TS_MASK;
346 }
347
348 void helper_reset_rf(void)
349 {
350 env->eflags &= ~RF_MASK;
351 }
352
353 void helper_cli(void)
354 {
355 env->eflags &= ~IF_MASK;
356 }
357
358 void helper_sti(void)
359 {
360 env->eflags |= IF_MASK;
361 }
362
363 #if 0
364 /* vm86plus instructions */
365 void helper_cli_vm(void)
366 {
367 env->eflags &= ~VIF_MASK;
368 }
369
370 void helper_sti_vm(void)
371 {
372 env->eflags |= VIF_MASK;
373 if (env->eflags & VIP_MASK) {
374 raise_exception(env, EXCP0D_GPF);
375 }
376 }
377 #endif
378
379 void helper_set_inhibit_irq(void)
380 {
381 env->hflags |= HF_INHIBIT_IRQ_MASK;
382 }
383
384 void helper_reset_inhibit_irq(void)
385 {
386 env->hflags &= ~HF_INHIBIT_IRQ_MASK;
387 }