]>
Commit | Line | Data |
---|---|---|
2c0262af FB |
1 | /* |
2 | * i386 micro operations | |
5fafdf24 | 3 | * |
2c0262af FB |
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, write to the Free Software | |
18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
19 | */ | |
f68dd770 | 20 | |
f68dd770 | 21 | #define ASM_SOFTMMU |
2c0262af FB |
22 | #include "exec.h" |
23 | ||
2c0262af FB |
24 | /* we define the various pieces of code used by the JIT */ |
25 | ||
26 | #define REG EAX | |
27 | #define REGNAME _EAX | |
28 | #include "opreg_template.h" | |
29 | #undef REG | |
30 | #undef REGNAME | |
31 | ||
32 | #define REG ECX | |
33 | #define REGNAME _ECX | |
34 | #include "opreg_template.h" | |
35 | #undef REG | |
36 | #undef REGNAME | |
37 | ||
38 | #define REG EDX | |
39 | #define REGNAME _EDX | |
40 | #include "opreg_template.h" | |
41 | #undef REG | |
42 | #undef REGNAME | |
43 | ||
44 | #define REG EBX | |
45 | #define REGNAME _EBX | |
46 | #include "opreg_template.h" | |
47 | #undef REG | |
48 | #undef REGNAME | |
49 | ||
50 | #define REG ESP | |
51 | #define REGNAME _ESP | |
52 | #include "opreg_template.h" | |
53 | #undef REG | |
54 | #undef REGNAME | |
55 | ||
56 | #define REG EBP | |
57 | #define REGNAME _EBP | |
58 | #include "opreg_template.h" | |
59 | #undef REG | |
60 | #undef REGNAME | |
61 | ||
62 | #define REG ESI | |
63 | #define REGNAME _ESI | |
64 | #include "opreg_template.h" | |
65 | #undef REG | |
66 | #undef REGNAME | |
67 | ||
68 | #define REG EDI | |
69 | #define REGNAME _EDI | |
70 | #include "opreg_template.h" | |
71 | #undef REG | |
72 | #undef REGNAME | |
73 | ||
14ce26e7 FB |
74 | #ifdef TARGET_X86_64 |
75 | ||
76 | #define REG (env->regs[8]) | |
77 | #define REGNAME _R8 | |
78 | #include "opreg_template.h" | |
79 | #undef REG | |
80 | #undef REGNAME | |
81 | ||
82 | #define REG (env->regs[9]) | |
83 | #define REGNAME _R9 | |
84 | #include "opreg_template.h" | |
85 | #undef REG | |
86 | #undef REGNAME | |
87 | ||
88 | #define REG (env->regs[10]) | |
89 | #define REGNAME _R10 | |
90 | #include "opreg_template.h" | |
91 | #undef REG | |
92 | #undef REGNAME | |
93 | ||
94 | #define REG (env->regs[11]) | |
95 | #define REGNAME _R11 | |
96 | #include "opreg_template.h" | |
97 | #undef REG | |
98 | #undef REGNAME | |
99 | ||
100 | #define REG (env->regs[12]) | |
101 | #define REGNAME _R12 | |
102 | #include "opreg_template.h" | |
103 | #undef REG | |
104 | #undef REGNAME | |
105 | ||
106 | #define REG (env->regs[13]) | |
107 | #define REGNAME _R13 | |
108 | #include "opreg_template.h" | |
109 | #undef REG | |
110 | #undef REGNAME | |
111 | ||
112 | #define REG (env->regs[14]) | |
113 | #define REGNAME _R14 | |
114 | #include "opreg_template.h" | |
115 | #undef REG | |
116 | #undef REGNAME | |
117 | ||
118 | #define REG (env->regs[15]) | |
119 | #define REGNAME _R15 | |
120 | #include "opreg_template.h" | |
121 | #undef REG | |
122 | #undef REGNAME | |
123 | ||
124 | #endif | |
125 | ||
2c0262af | 126 | /* multiply/divide */ |
d36cd60e FB |
127 | |
128 | /* XXX: add eflags optimizations */ | |
129 | /* XXX: add non P4 style flags */ | |
130 | ||
2c0262af FB |
131 | void OPPROTO op_mulb_AL_T0(void) |
132 | { | |
133 | unsigned int res; | |
134 | res = (uint8_t)EAX * (uint8_t)T0; | |
14ce26e7 | 135 | EAX = (EAX & ~0xffff) | res; |
d36cd60e | 136 | CC_DST = res; |
2c0262af FB |
137 | CC_SRC = (res & 0xff00); |
138 | } | |
139 | ||
140 | void OPPROTO op_imulb_AL_T0(void) | |
141 | { | |
142 | int res; | |
143 | res = (int8_t)EAX * (int8_t)T0; | |
14ce26e7 | 144 | EAX = (EAX & ~0xffff) | (res & 0xffff); |
d36cd60e | 145 | CC_DST = res; |
2c0262af FB |
146 | CC_SRC = (res != (int8_t)res); |
147 | } | |
148 | ||
149 | void OPPROTO op_mulw_AX_T0(void) | |
150 | { | |
151 | unsigned int res; | |
152 | res = (uint16_t)EAX * (uint16_t)T0; | |
14ce26e7 FB |
153 | EAX = (EAX & ~0xffff) | (res & 0xffff); |
154 | EDX = (EDX & ~0xffff) | ((res >> 16) & 0xffff); | |
d36cd60e | 155 | CC_DST = res; |
2c0262af FB |
156 | CC_SRC = res >> 16; |
157 | } | |
158 | ||
159 | void OPPROTO op_imulw_AX_T0(void) | |
160 | { | |
161 | int res; | |
162 | res = (int16_t)EAX * (int16_t)T0; | |
14ce26e7 FB |
163 | EAX = (EAX & ~0xffff) | (res & 0xffff); |
164 | EDX = (EDX & ~0xffff) | ((res >> 16) & 0xffff); | |
d36cd60e | 165 | CC_DST = res; |
2c0262af FB |
166 | CC_SRC = (res != (int16_t)res); |
167 | } | |
168 | ||
169 | void OPPROTO op_mull_EAX_T0(void) | |
170 | { | |
171 | uint64_t res; | |
172 | res = (uint64_t)((uint32_t)EAX) * (uint64_t)((uint32_t)T0); | |
14ce26e7 FB |
173 | EAX = (uint32_t)res; |
174 | EDX = (uint32_t)(res >> 32); | |
175 | CC_DST = (uint32_t)res; | |
176 | CC_SRC = (uint32_t)(res >> 32); | |
2c0262af FB |
177 | } |
178 | ||
179 | void OPPROTO op_imull_EAX_T0(void) | |
180 | { | |
181 | int64_t res; | |
182 | res = (int64_t)((int32_t)EAX) * (int64_t)((int32_t)T0); | |
31313213 FB |
183 | EAX = (uint32_t)(res); |
184 | EDX = (uint32_t)(res >> 32); | |
d36cd60e | 185 | CC_DST = res; |
2c0262af FB |
186 | CC_SRC = (res != (int32_t)res); |
187 | } | |
188 | ||
189 | void OPPROTO op_imulw_T0_T1(void) | |
190 | { | |
191 | int res; | |
192 | res = (int16_t)T0 * (int16_t)T1; | |
193 | T0 = res; | |
d36cd60e | 194 | CC_DST = res; |
2c0262af FB |
195 | CC_SRC = (res != (int16_t)res); |
196 | } | |
197 | ||
198 | void OPPROTO op_imull_T0_T1(void) | |
199 | { | |
200 | int64_t res; | |
201 | res = (int64_t)((int32_t)T0) * (int64_t)((int32_t)T1); | |
202 | T0 = res; | |
d36cd60e | 203 | CC_DST = res; |
2c0262af FB |
204 | CC_SRC = (res != (int32_t)res); |
205 | } | |
206 | ||
14ce26e7 FB |
207 | #ifdef TARGET_X86_64 |
208 | void OPPROTO op_mulq_EAX_T0(void) | |
209 | { | |
b8b6a50b | 210 | helper_mulq_EAX_T0(T0); |
14ce26e7 FB |
211 | } |
212 | ||
213 | void OPPROTO op_imulq_EAX_T0(void) | |
214 | { | |
b8b6a50b | 215 | helper_imulq_EAX_T0(T0); |
14ce26e7 FB |
216 | } |
217 | ||
218 | void OPPROTO op_imulq_T0_T1(void) | |
219 | { | |
b8b6a50b | 220 | T0 = helper_imulq_T0_T1(T0, T1); |
14ce26e7 FB |
221 | } |
222 | #endif | |
223 | ||
2c0262af FB |
224 | /* constant load & misc op */ |
225 | ||
14ce26e7 | 226 | /* XXX: consistent names */ |
2c0262af FB |
227 | void OPPROTO op_addl_T1_im(void) |
228 | { | |
229 | T1 += PARAM1; | |
230 | } | |
231 | ||
232 | void OPPROTO op_movl_T1_A0(void) | |
233 | { | |
234 | T1 = A0; | |
235 | } | |
236 | ||
2c0262af FB |
237 | void OPPROTO op_addl_A0_AL(void) |
238 | { | |
14ce26e7 FB |
239 | A0 = (uint32_t)(A0 + (EAX & 0xff)); |
240 | } | |
241 | ||
0573fbfc TS |
242 | #ifdef TARGET_X86_64 |
243 | ||
14ce26e7 FB |
244 | void OPPROTO op_addq_A0_AL(void) |
245 | { | |
246 | A0 = (A0 + (EAX & 0xff)); | |
247 | } | |
248 | ||
249 | #endif | |
250 | ||
2c0262af FB |
251 | void OPPROTO op_into(void) |
252 | { | |
253 | int eflags; | |
254 | eflags = cc_table[CC_OP].compute_all(); | |
255 | if (eflags & CC_O) { | |
256 | raise_interrupt(EXCP04_INTO, 1, 0, PARAM1); | |
257 | } | |
258 | FORCE_RET(); | |
259 | } | |
260 | ||
2c0262af FB |
261 | void OPPROTO op_cmpxchg8b(void) |
262 | { | |
b8b6a50b | 263 | helper_cmpxchg8b(A0); |
2c0262af FB |
264 | } |
265 | ||
2c0262af FB |
266 | /* multiple size ops */ |
267 | ||
268 | #define ldul ldl | |
269 | ||
270 | #define SHIFT 0 | |
271 | #include "ops_template.h" | |
272 | #undef SHIFT | |
273 | ||
274 | #define SHIFT 1 | |
275 | #include "ops_template.h" | |
276 | #undef SHIFT | |
277 | ||
278 | #define SHIFT 2 | |
279 | #include "ops_template.h" | |
280 | #undef SHIFT | |
281 | ||
14ce26e7 FB |
282 | #ifdef TARGET_X86_64 |
283 | ||
284 | #define SHIFT 3 | |
285 | #include "ops_template.h" | |
286 | #undef SHIFT | |
287 | ||
288 | #endif | |
289 | ||
2c0262af FB |
290 | /* sign extend */ |
291 | ||
292 | void OPPROTO op_movsbl_T0_T0(void) | |
293 | { | |
294 | T0 = (int8_t)T0; | |
295 | } | |
296 | ||
297 | void OPPROTO op_movzbl_T0_T0(void) | |
298 | { | |
299 | T0 = (uint8_t)T0; | |
300 | } | |
301 | ||
302 | void OPPROTO op_movswl_T0_T0(void) | |
303 | { | |
304 | T0 = (int16_t)T0; | |
305 | } | |
306 | ||
307 | void OPPROTO op_movzwl_T0_T0(void) | |
308 | { | |
309 | T0 = (uint16_t)T0; | |
310 | } | |
311 | ||
312 | void OPPROTO op_movswl_EAX_AX(void) | |
313 | { | |
0499e4a0 | 314 | EAX = (uint32_t)((int16_t)EAX); |
2c0262af FB |
315 | } |
316 | ||
14ce26e7 | 317 | #ifdef TARGET_X86_64 |
664e0f19 FB |
318 | void OPPROTO op_movslq_T0_T0(void) |
319 | { | |
320 | T0 = (int32_t)T0; | |
321 | } | |
322 | ||
14ce26e7 FB |
323 | void OPPROTO op_movslq_RAX_EAX(void) |
324 | { | |
325 | EAX = (int32_t)EAX; | |
326 | } | |
327 | #endif | |
328 | ||
2c0262af FB |
329 | void OPPROTO op_movsbw_AX_AL(void) |
330 | { | |
14ce26e7 | 331 | EAX = (EAX & ~0xffff) | ((int8_t)EAX & 0xffff); |
2c0262af FB |
332 | } |
333 | ||
334 | void OPPROTO op_movslq_EDX_EAX(void) | |
335 | { | |
0499e4a0 | 336 | EDX = (uint32_t)((int32_t)EAX >> 31); |
2c0262af FB |
337 | } |
338 | ||
339 | void OPPROTO op_movswl_DX_AX(void) | |
340 | { | |
14ce26e7 FB |
341 | EDX = (EDX & ~0xffff) | (((int16_t)EAX >> 15) & 0xffff); |
342 | } | |
343 | ||
344 | #ifdef TARGET_X86_64 | |
345 | void OPPROTO op_movsqo_RDX_RAX(void) | |
346 | { | |
347 | EDX = (int64_t)EAX >> 63; | |
2c0262af | 348 | } |
14ce26e7 | 349 | #endif |
2c0262af FB |
350 | |
351 | /* string ops helpers */ | |
352 | ||
353 | void OPPROTO op_addl_ESI_T0(void) | |
354 | { | |
14ce26e7 | 355 | ESI = (uint32_t)(ESI + T0); |
2c0262af FB |
356 | } |
357 | ||
358 | void OPPROTO op_addw_ESI_T0(void) | |
359 | { | |
360 | ESI = (ESI & ~0xffff) | ((ESI + T0) & 0xffff); | |
361 | } | |
362 | ||
363 | void OPPROTO op_addl_EDI_T0(void) | |
364 | { | |
14ce26e7 | 365 | EDI = (uint32_t)(EDI + T0); |
2c0262af FB |
366 | } |
367 | ||
368 | void OPPROTO op_addw_EDI_T0(void) | |
369 | { | |
370 | EDI = (EDI & ~0xffff) | ((EDI + T0) & 0xffff); | |
371 | } | |
372 | ||
373 | void OPPROTO op_decl_ECX(void) | |
374 | { | |
14ce26e7 | 375 | ECX = (uint32_t)(ECX - 1); |
2c0262af FB |
376 | } |
377 | ||
378 | void OPPROTO op_decw_ECX(void) | |
379 | { | |
380 | ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff); | |
381 | } | |
382 | ||
14ce26e7 FB |
383 | #ifdef TARGET_X86_64 |
384 | void OPPROTO op_addq_ESI_T0(void) | |
385 | { | |
386 | ESI = (ESI + T0); | |
387 | } | |
388 | ||
389 | void OPPROTO op_addq_EDI_T0(void) | |
390 | { | |
391 | EDI = (EDI + T0); | |
392 | } | |
393 | ||
394 | void OPPROTO op_decq_ECX(void) | |
395 | { | |
396 | ECX--; | |
397 | } | |
398 | #endif | |
399 | ||
2c0262af FB |
400 | /* bcd */ |
401 | ||
2c0262af FB |
402 | void OPPROTO op_aam(void) |
403 | { | |
b5b38f61 | 404 | helper_aam(PARAM1); |
2c0262af FB |
405 | } |
406 | ||
407 | void OPPROTO op_aad(void) | |
408 | { | |
b5b38f61 | 409 | helper_aad(PARAM1); |
2c0262af FB |
410 | } |
411 | ||
412 | void OPPROTO op_aaa(void) | |
413 | { | |
b5b38f61 | 414 | helper_aaa(); |
2c0262af FB |
415 | } |
416 | ||
417 | void OPPROTO op_aas(void) | |
418 | { | |
b5b38f61 | 419 | helper_aas(); |
2c0262af FB |
420 | } |
421 | ||
422 | void OPPROTO op_daa(void) | |
423 | { | |
b5b38f61 | 424 | helper_daa(); |
2c0262af FB |
425 | } |
426 | ||
427 | void OPPROTO op_das(void) | |
428 | { | |
b5b38f61 | 429 | helper_das(); |
2c0262af FB |
430 | } |
431 | ||
432 | /* segment handling */ | |
433 | ||
2c0262af FB |
434 | /* faster VM86 version */ |
435 | void OPPROTO op_movl_seg_T0_vm(void) | |
436 | { | |
437 | int selector; | |
438 | SegmentCache *sc; | |
3b46e624 | 439 | |
2c0262af FB |
440 | selector = T0 & 0xffff; |
441 | /* env->segs[] access */ | |
442 | sc = (SegmentCache *)((char *)env + PARAM1); | |
443 | sc->selector = selector; | |
14ce26e7 | 444 | sc->base = (selector << 4); |
2c0262af FB |
445 | } |
446 | ||
447 | void OPPROTO op_movl_T0_seg(void) | |
448 | { | |
449 | T0 = env->segs[PARAM1].selector; | |
450 | } | |
451 | ||
2c0262af FB |
452 | void OPPROTO op_lsl(void) |
453 | { | |
b8b6a50b FB |
454 | uint32_t val; |
455 | val = helper_lsl(T0); | |
456 | if (CC_SRC & CC_Z) | |
457 | T1 = val; | |
458 | FORCE_RET(); | |
2c0262af FB |
459 | } |
460 | ||
461 | void OPPROTO op_lar(void) | |
462 | { | |
b8b6a50b FB |
463 | uint32_t val; |
464 | val = helper_lar(T0); | |
465 | if (CC_SRC & CC_Z) | |
466 | T1 = val; | |
467 | FORCE_RET(); | |
2c0262af FB |
468 | } |
469 | ||
3ab493de FB |
470 | void OPPROTO op_verr(void) |
471 | { | |
b5b38f61 | 472 | helper_verr(T0); |
3ab493de FB |
473 | } |
474 | ||
475 | void OPPROTO op_verw(void) | |
476 | { | |
b5b38f61 | 477 | helper_verw(T0); |
3ab493de FB |
478 | } |
479 | ||
480 | void OPPROTO op_arpl(void) | |
481 | { | |
482 | if ((T0 & 3) < (T1 & 3)) { | |
483 | /* XXX: emulate bug or 0xff3f0000 oring as in bochs ? */ | |
484 | T0 = (T0 & ~3) | (T1 & 3); | |
485 | T1 = CC_Z; | |
486 | } else { | |
487 | T1 = 0; | |
488 | } | |
489 | FORCE_RET(); | |
490 | } | |
3b46e624 | 491 | |
3ab493de FB |
492 | void OPPROTO op_arpl_update(void) |
493 | { | |
494 | int eflags; | |
495 | eflags = cc_table[CC_OP].compute_all(); | |
496 | CC_SRC = (eflags & ~CC_Z) | T1; | |
497 | } | |
3b46e624 | 498 | |
2c0262af FB |
499 | void OPPROTO op_movl_T0_env(void) |
500 | { | |
501 | T0 = *(uint32_t *)((char *)env + PARAM1); | |
502 | } | |
503 | ||
504 | void OPPROTO op_movl_env_T0(void) | |
505 | { | |
506 | *(uint32_t *)((char *)env + PARAM1) = T0; | |
507 | } | |
508 | ||
509 | void OPPROTO op_movl_env_T1(void) | |
510 | { | |
511 | *(uint32_t *)((char *)env + PARAM1) = T1; | |
512 | } | |
513 | ||
14ce26e7 FB |
514 | void OPPROTO op_movtl_T0_env(void) |
515 | { | |
516 | T0 = *(target_ulong *)((char *)env + PARAM1); | |
517 | } | |
518 | ||
519 | void OPPROTO op_movtl_env_T0(void) | |
520 | { | |
521 | *(target_ulong *)((char *)env + PARAM1) = T0; | |
522 | } | |
523 | ||
524 | void OPPROTO op_movtl_T1_env(void) | |
525 | { | |
526 | T1 = *(target_ulong *)((char *)env + PARAM1); | |
527 | } | |
528 | ||
529 | void OPPROTO op_movtl_env_T1(void) | |
530 | { | |
531 | *(target_ulong *)((char *)env + PARAM1) = T1; | |
532 | } | |
533 | ||
2c0262af FB |
534 | /* flags handling */ |
535 | ||
14ce26e7 FB |
536 | void OPPROTO op_jmp_label(void) |
537 | { | |
538 | GOTO_LABEL_PARAM(1); | |
2c0262af FB |
539 | } |
540 | ||
14ce26e7 | 541 | void OPPROTO op_jnz_T0_label(void) |
2c0262af FB |
542 | { |
543 | if (T0) | |
14ce26e7 | 544 | GOTO_LABEL_PARAM(1); |
39c61f49 | 545 | FORCE_RET(); |
14ce26e7 FB |
546 | } |
547 | ||
548 | void OPPROTO op_jz_T0_label(void) | |
549 | { | |
550 | if (!T0) | |
551 | GOTO_LABEL_PARAM(1); | |
39c61f49 | 552 | FORCE_RET(); |
2c0262af FB |
553 | } |
554 | ||
555 | /* slow set cases (compute x86 flags) */ | |
556 | void OPPROTO op_seto_T0_cc(void) | |
557 | { | |
558 | int eflags; | |
559 | eflags = cc_table[CC_OP].compute_all(); | |
560 | T0 = (eflags >> 11) & 1; | |
561 | } | |
562 | ||
563 | void OPPROTO op_setb_T0_cc(void) | |
564 | { | |
565 | T0 = cc_table[CC_OP].compute_c(); | |
566 | } | |
567 | ||
568 | void OPPROTO op_setz_T0_cc(void) | |
569 | { | |
570 | int eflags; | |
571 | eflags = cc_table[CC_OP].compute_all(); | |
572 | T0 = (eflags >> 6) & 1; | |
573 | } | |
574 | ||
575 | void OPPROTO op_setbe_T0_cc(void) | |
576 | { | |
577 | int eflags; | |
578 | eflags = cc_table[CC_OP].compute_all(); | |
579 | T0 = (eflags & (CC_Z | CC_C)) != 0; | |
580 | } | |
581 | ||
582 | void OPPROTO op_sets_T0_cc(void) | |
583 | { | |
584 | int eflags; | |
585 | eflags = cc_table[CC_OP].compute_all(); | |
586 | T0 = (eflags >> 7) & 1; | |
587 | } | |
588 | ||
589 | void OPPROTO op_setp_T0_cc(void) | |
590 | { | |
591 | int eflags; | |
592 | eflags = cc_table[CC_OP].compute_all(); | |
593 | T0 = (eflags >> 2) & 1; | |
594 | } | |
595 | ||
596 | void OPPROTO op_setl_T0_cc(void) | |
597 | { | |
598 | int eflags; | |
599 | eflags = cc_table[CC_OP].compute_all(); | |
600 | T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1; | |
601 | } | |
602 | ||
603 | void OPPROTO op_setle_T0_cc(void) | |
604 | { | |
605 | int eflags; | |
606 | eflags = cc_table[CC_OP].compute_all(); | |
607 | T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0; | |
608 | } | |
609 | ||
610 | void OPPROTO op_xor_T0_1(void) | |
611 | { | |
612 | T0 ^= 1; | |
613 | } | |
614 | ||
0b9dc5e4 FB |
615 | void OPPROTO op_mov_T0_cc(void) |
616 | { | |
617 | T0 = cc_table[CC_OP].compute_all(); | |
618 | } | |
619 | ||
4136f33c | 620 | /* XXX: clear VIF/VIP in all ops ? */ |
2c0262af FB |
621 | |
622 | void OPPROTO op_movl_eflags_T0(void) | |
623 | { | |
4b7aba51 | 624 | load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK)); |
2c0262af FB |
625 | } |
626 | ||
627 | void OPPROTO op_movw_eflags_T0(void) | |
628 | { | |
4b7aba51 | 629 | load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff); |
4136f33c FB |
630 | } |
631 | ||
632 | void OPPROTO op_movl_eflags_T0_io(void) | |
633 | { | |
4b7aba51 | 634 | load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK)); |
4136f33c FB |
635 | } |
636 | ||
637 | void OPPROTO op_movw_eflags_T0_io(void) | |
638 | { | |
4b7aba51 | 639 | load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff); |
2c0262af FB |
640 | } |
641 | ||
642 | void OPPROTO op_movl_eflags_T0_cpl0(void) | |
643 | { | |
4b7aba51 | 644 | load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK)); |
2c0262af FB |
645 | } |
646 | ||
647 | void OPPROTO op_movw_eflags_T0_cpl0(void) | |
648 | { | |
4b7aba51 | 649 | load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff); |
2c0262af FB |
650 | } |
651 | ||
652 | #if 0 | |
653 | /* vm86plus version */ | |
654 | void OPPROTO op_movw_eflags_T0_vm(void) | |
655 | { | |
656 | int eflags; | |
657 | eflags = T0; | |
658 | CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); | |
659 | DF = 1 - (2 * ((eflags >> 10) & 1)); | |
660 | /* we also update some system flags as in user mode */ | |
661 | env->eflags = (env->eflags & ~(FL_UPDATE_MASK16 | VIF_MASK)) | | |
662 | (eflags & FL_UPDATE_MASK16); | |
663 | if (eflags & IF_MASK) { | |
664 | env->eflags |= VIF_MASK; | |
665 | if (env->eflags & VIP_MASK) { | |
666 | EIP = PARAM1; | |
667 | raise_exception(EXCP0D_GPF); | |
668 | } | |
669 | } | |
670 | FORCE_RET(); | |
671 | } | |
672 | ||
673 | void OPPROTO op_movl_eflags_T0_vm(void) | |
674 | { | |
675 | int eflags; | |
676 | eflags = T0; | |
677 | CC_SRC = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); | |
678 | DF = 1 - (2 * ((eflags >> 10) & 1)); | |
679 | /* we also update some system flags as in user mode */ | |
680 | env->eflags = (env->eflags & ~(FL_UPDATE_MASK32 | VIF_MASK)) | | |
681 | (eflags & FL_UPDATE_MASK32); | |
682 | if (eflags & IF_MASK) { | |
683 | env->eflags |= VIF_MASK; | |
684 | if (env->eflags & VIP_MASK) { | |
685 | EIP = PARAM1; | |
686 | raise_exception(EXCP0D_GPF); | |
687 | } | |
688 | } | |
689 | FORCE_RET(); | |
690 | } | |
691 | #endif | |
692 | ||
693 | /* XXX: compute only O flag */ | |
694 | void OPPROTO op_movb_eflags_T0(void) | |
695 | { | |
696 | int of; | |
697 | of = cc_table[CC_OP].compute_all() & CC_O; | |
698 | CC_SRC = (T0 & (CC_S | CC_Z | CC_A | CC_P | CC_C)) | of; | |
699 | } | |
700 | ||
701 | void OPPROTO op_movl_T0_eflags(void) | |
702 | { | |
703 | int eflags; | |
704 | eflags = cc_table[CC_OP].compute_all(); | |
705 | eflags |= (DF & DF_MASK); | |
706 | eflags |= env->eflags & ~(VM_MASK | RF_MASK); | |
707 | T0 = eflags; | |
708 | } | |
709 | ||
710 | /* vm86plus version */ | |
711 | #if 0 | |
712 | void OPPROTO op_movl_T0_eflags_vm(void) | |
713 | { | |
714 | int eflags; | |
715 | eflags = cc_table[CC_OP].compute_all(); | |
716 | eflags |= (DF & DF_MASK); | |
717 | eflags |= env->eflags & ~(VM_MASK | RF_MASK | IF_MASK); | |
718 | if (env->eflags & VIF_MASK) | |
719 | eflags |= IF_MASK; | |
720 | T0 = eflags; | |
721 | } | |
722 | #endif | |
723 | ||
2c0262af FB |
724 | void OPPROTO op_clc(void) |
725 | { | |
726 | int eflags; | |
727 | eflags = cc_table[CC_OP].compute_all(); | |
728 | eflags &= ~CC_C; | |
729 | CC_SRC = eflags; | |
730 | } | |
731 | ||
732 | void OPPROTO op_stc(void) | |
733 | { | |
734 | int eflags; | |
735 | eflags = cc_table[CC_OP].compute_all(); | |
736 | eflags |= CC_C; | |
737 | CC_SRC = eflags; | |
738 | } | |
739 | ||
740 | void OPPROTO op_cmc(void) | |
741 | { | |
742 | int eflags; | |
743 | eflags = cc_table[CC_OP].compute_all(); | |
744 | eflags ^= CC_C; | |
745 | CC_SRC = eflags; | |
746 | } | |
747 | ||
748 | void OPPROTO op_salc(void) | |
749 | { | |
750 | int cf; | |
751 | cf = cc_table[CC_OP].compute_c(); | |
752 | EAX = (EAX & ~0xff) | ((-cf) & 0xff); | |
753 | } | |
754 | ||
755 | static int compute_all_eflags(void) | |
756 | { | |
757 | return CC_SRC; | |
758 | } | |
759 | ||
760 | static int compute_c_eflags(void) | |
761 | { | |
762 | return CC_SRC & CC_C; | |
763 | } | |
764 | ||
2c0262af FB |
765 | CCTable cc_table[CC_OP_NB] = { |
766 | [CC_OP_DYNAMIC] = { /* should never happen */ }, | |
767 | ||
768 | [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags }, | |
769 | ||
d36cd60e FB |
770 | [CC_OP_MULB] = { compute_all_mulb, compute_c_mull }, |
771 | [CC_OP_MULW] = { compute_all_mulw, compute_c_mull }, | |
772 | [CC_OP_MULL] = { compute_all_mull, compute_c_mull }, | |
2c0262af FB |
773 | |
774 | [CC_OP_ADDB] = { compute_all_addb, compute_c_addb }, | |
775 | [CC_OP_ADDW] = { compute_all_addw, compute_c_addw }, | |
776 | [CC_OP_ADDL] = { compute_all_addl, compute_c_addl }, | |
777 | ||
778 | [CC_OP_ADCB] = { compute_all_adcb, compute_c_adcb }, | |
779 | [CC_OP_ADCW] = { compute_all_adcw, compute_c_adcw }, | |
780 | [CC_OP_ADCL] = { compute_all_adcl, compute_c_adcl }, | |
781 | ||
782 | [CC_OP_SUBB] = { compute_all_subb, compute_c_subb }, | |
783 | [CC_OP_SUBW] = { compute_all_subw, compute_c_subw }, | |
784 | [CC_OP_SUBL] = { compute_all_subl, compute_c_subl }, | |
3b46e624 | 785 | |
2c0262af FB |
786 | [CC_OP_SBBB] = { compute_all_sbbb, compute_c_sbbb }, |
787 | [CC_OP_SBBW] = { compute_all_sbbw, compute_c_sbbw }, | |
788 | [CC_OP_SBBL] = { compute_all_sbbl, compute_c_sbbl }, | |
3b46e624 | 789 | |
2c0262af FB |
790 | [CC_OP_LOGICB] = { compute_all_logicb, compute_c_logicb }, |
791 | [CC_OP_LOGICW] = { compute_all_logicw, compute_c_logicw }, | |
792 | [CC_OP_LOGICL] = { compute_all_logicl, compute_c_logicl }, | |
3b46e624 | 793 | |
2c0262af FB |
794 | [CC_OP_INCB] = { compute_all_incb, compute_c_incl }, |
795 | [CC_OP_INCW] = { compute_all_incw, compute_c_incl }, | |
796 | [CC_OP_INCL] = { compute_all_incl, compute_c_incl }, | |
3b46e624 | 797 | |
2c0262af FB |
798 | [CC_OP_DECB] = { compute_all_decb, compute_c_incl }, |
799 | [CC_OP_DECW] = { compute_all_decw, compute_c_incl }, | |
800 | [CC_OP_DECL] = { compute_all_decl, compute_c_incl }, | |
3b46e624 | 801 | |
2c0262af FB |
802 | [CC_OP_SHLB] = { compute_all_shlb, compute_c_shlb }, |
803 | [CC_OP_SHLW] = { compute_all_shlw, compute_c_shlw }, | |
804 | [CC_OP_SHLL] = { compute_all_shll, compute_c_shll }, | |
805 | ||
806 | [CC_OP_SARB] = { compute_all_sarb, compute_c_sarl }, | |
807 | [CC_OP_SARW] = { compute_all_sarw, compute_c_sarl }, | |
808 | [CC_OP_SARL] = { compute_all_sarl, compute_c_sarl }, | |
14ce26e7 FB |
809 | |
810 | #ifdef TARGET_X86_64 | |
811 | [CC_OP_MULQ] = { compute_all_mulq, compute_c_mull }, | |
812 | ||
813 | [CC_OP_ADDQ] = { compute_all_addq, compute_c_addq }, | |
814 | ||
815 | [CC_OP_ADCQ] = { compute_all_adcq, compute_c_adcq }, | |
816 | ||
817 | [CC_OP_SUBQ] = { compute_all_subq, compute_c_subq }, | |
3b46e624 | 818 | |
14ce26e7 | 819 | [CC_OP_SBBQ] = { compute_all_sbbq, compute_c_sbbq }, |
3b46e624 | 820 | |
14ce26e7 | 821 | [CC_OP_LOGICQ] = { compute_all_logicq, compute_c_logicq }, |
3b46e624 | 822 | |
14ce26e7 FB |
823 | [CC_OP_INCQ] = { compute_all_incq, compute_c_incl }, |
824 | ||
825 | [CC_OP_DECQ] = { compute_all_decq, compute_c_incl }, | |
826 | ||
827 | [CC_OP_SHLQ] = { compute_all_shlq, compute_c_shlq }, | |
828 | ||
829 | [CC_OP_SARQ] = { compute_all_sarq, compute_c_sarl }, | |
830 | #endif | |
2c0262af FB |
831 | }; |
832 | ||
19e6c4b8 | 833 | void OPPROTO op_fcomi_dummy(void) |
2c0262af | 834 | { |
19e6c4b8 | 835 | T0 = 0; |
2c0262af FB |
836 | } |
837 | ||
14ce26e7 | 838 | /* SSE support */ |
5af45186 | 839 | void OPPROTO op_com_dummy(void) |
14ce26e7 | 840 | { |
5af45186 | 841 | T0 = 0; |
664e0f19 | 842 | } |