2 * i386 micro operations
4 * Copyright (c) 2003 Fabrice Bellard
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.
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.
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
24 /* we define the various pieces of code used by the JIT */
28 #include "opreg_template.h"
34 #include "opreg_template.h"
40 #include "opreg_template.h"
46 #include "opreg_template.h"
52 #include "opreg_template.h"
58 #include "opreg_template.h"
64 #include "opreg_template.h"
70 #include "opreg_template.h"
76 #define REG (env->regs[8])
78 #include "opreg_template.h"
82 #define REG (env->regs[9])
84 #include "opreg_template.h"
88 #define REG (env->regs[10])
90 #include "opreg_template.h"
94 #define REG (env->regs[11])
96 #include "opreg_template.h"
100 #define REG (env->regs[12])
102 #include "opreg_template.h"
106 #define REG (env->regs[13])
108 #include "opreg_template.h"
112 #define REG (env->regs[14])
114 #include "opreg_template.h"
118 #define REG (env->regs[15])
120 #include "opreg_template.h"
126 /* multiply/divide */
128 /* XXX: add eflags optimizations */
129 /* XXX: add non P4 style flags */
131 void OPPROTO
op_mulb_AL_T0(void)
134 res
= (uint8_t)EAX
* (uint8_t)T0
;
135 EAX
= (EAX
& ~0xffff) | res
;
137 CC_SRC
= (res
& 0xff00);
140 void OPPROTO
op_imulb_AL_T0(void)
143 res
= (int8_t)EAX
* (int8_t)T0
;
144 EAX
= (EAX
& ~0xffff) | (res
& 0xffff);
146 CC_SRC
= (res
!= (int8_t)res
);
149 void OPPROTO
op_mulw_AX_T0(void)
152 res
= (uint16_t)EAX
* (uint16_t)T0
;
153 EAX
= (EAX
& ~0xffff) | (res
& 0xffff);
154 EDX
= (EDX
& ~0xffff) | ((res
>> 16) & 0xffff);
159 void OPPROTO
op_imulw_AX_T0(void)
162 res
= (int16_t)EAX
* (int16_t)T0
;
163 EAX
= (EAX
& ~0xffff) | (res
& 0xffff);
164 EDX
= (EDX
& ~0xffff) | ((res
>> 16) & 0xffff);
166 CC_SRC
= (res
!= (int16_t)res
);
169 void OPPROTO
op_mull_EAX_T0(void)
172 res
= (uint64_t)((uint32_t)EAX
) * (uint64_t)((uint32_t)T0
);
174 EDX
= (uint32_t)(res
>> 32);
175 CC_DST
= (uint32_t)res
;
176 CC_SRC
= (uint32_t)(res
>> 32);
179 void OPPROTO
op_imull_EAX_T0(void)
182 res
= (int64_t)((int32_t)EAX
) * (int64_t)((int32_t)T0
);
183 EAX
= (uint32_t)(res
);
184 EDX
= (uint32_t)(res
>> 32);
186 CC_SRC
= (res
!= (int32_t)res
);
189 void OPPROTO
op_imulw_T0_T1(void)
192 res
= (int16_t)T0
* (int16_t)T1
;
195 CC_SRC
= (res
!= (int16_t)res
);
198 void OPPROTO
op_imull_T0_T1(void)
201 res
= (int64_t)((int32_t)T0
) * (int64_t)((int32_t)T1
);
204 CC_SRC
= (res
!= (int32_t)res
);
208 void OPPROTO
op_mulq_EAX_T0(void)
210 helper_mulq_EAX_T0(T0
);
213 void OPPROTO
op_imulq_EAX_T0(void)
215 helper_imulq_EAX_T0(T0
);
218 void OPPROTO
op_imulq_T0_T1(void)
220 T0
= helper_imulq_T0_T1(T0
, T1
);
224 /* constant load & misc op */
226 /* XXX: consistent names */
227 void OPPROTO
op_into(void)
230 eflags
= cc_table
[CC_OP
].compute_all();
232 raise_interrupt(EXCP04_INTO
, 1, 0, PARAM1
);
237 void OPPROTO
op_cmpxchg8b(void)
239 helper_cmpxchg8b(A0
);
242 /* multiple size ops */
247 #include "ops_template.h"
251 #include "ops_template.h"
255 #include "ops_template.h"
261 #include "ops_template.h"
266 /* string ops helpers */
268 void OPPROTO
op_addl_ESI_T0(void)
270 ESI
= (uint32_t)(ESI
+ T0
);
273 void OPPROTO
op_addw_ESI_T0(void)
275 ESI
= (ESI
& ~0xffff) | ((ESI
+ T0
) & 0xffff);
278 void OPPROTO
op_addl_EDI_T0(void)
280 EDI
= (uint32_t)(EDI
+ T0
);
283 void OPPROTO
op_addw_EDI_T0(void)
285 EDI
= (EDI
& ~0xffff) | ((EDI
+ T0
) & 0xffff);
288 void OPPROTO
op_decl_ECX(void)
290 ECX
= (uint32_t)(ECX
- 1);
293 void OPPROTO
op_decw_ECX(void)
295 ECX
= (ECX
& ~0xffff) | ((ECX
- 1) & 0xffff);
299 void OPPROTO
op_addq_ESI_T0(void)
304 void OPPROTO
op_addq_EDI_T0(void)
309 void OPPROTO
op_decq_ECX(void)
317 void OPPROTO
op_aam(void)
322 void OPPROTO
op_aad(void)
327 void OPPROTO
op_aaa(void)
332 void OPPROTO
op_aas(void)
337 void OPPROTO
op_daa(void)
342 void OPPROTO
op_das(void)
347 /* segment handling */
349 /* faster VM86 version */
350 void OPPROTO
op_movl_seg_T0_vm(void)
355 selector
= T0
& 0xffff;
356 /* env->segs[] access */
357 sc
= (SegmentCache
*)((char *)env
+ PARAM1
);
358 sc
->selector
= selector
;
359 sc
->base
= (selector
<< 4);
362 void OPPROTO
op_movl_T0_seg(void)
364 T0
= env
->segs
[PARAM1
].selector
;
367 void OPPROTO
op_lsl(void)
370 val
= helper_lsl(T0
);
376 void OPPROTO
op_lar(void)
379 val
= helper_lar(T0
);
385 void OPPROTO
op_verr(void)
390 void OPPROTO
op_verw(void)
395 void OPPROTO
op_arpl(void)
397 if ((T0
& 3) < (T1
& 3)) {
398 /* XXX: emulate bug or 0xff3f0000 oring as in bochs ? */
399 T0
= (T0
& ~3) | (T1
& 3);
407 void OPPROTO
op_arpl_update(void)
410 eflags
= cc_table
[CC_OP
].compute_all();
411 CC_SRC
= (eflags
& ~CC_Z
) | T1
;
414 void OPPROTO
op_movl_T0_env(void)
416 T0
= *(uint32_t *)((char *)env
+ PARAM1
);
419 void OPPROTO
op_movl_env_T0(void)
421 *(uint32_t *)((char *)env
+ PARAM1
) = T0
;
424 void OPPROTO
op_movl_env_T1(void)
426 *(uint32_t *)((char *)env
+ PARAM1
) = T1
;
429 void OPPROTO
op_movtl_T0_env(void)
431 T0
= *(target_ulong
*)((char *)env
+ PARAM1
);
434 void OPPROTO
op_movtl_env_T0(void)
436 *(target_ulong
*)((char *)env
+ PARAM1
) = T0
;
439 void OPPROTO
op_movtl_T1_env(void)
441 T1
= *(target_ulong
*)((char *)env
+ PARAM1
);
444 void OPPROTO
op_movtl_env_T1(void)
446 *(target_ulong
*)((char *)env
+ PARAM1
) = T1
;
451 void OPPROTO
op_jmp_label(void)
456 void OPPROTO
op_jnz_T0_label(void)
463 void OPPROTO
op_jz_T0_label(void)
470 /* slow set cases (compute x86 flags) */
471 void OPPROTO
op_seto_T0_cc(void)
474 eflags
= cc_table
[CC_OP
].compute_all();
475 T0
= (eflags
>> 11) & 1;
478 void OPPROTO
op_setb_T0_cc(void)
480 T0
= cc_table
[CC_OP
].compute_c();
483 void OPPROTO
op_setz_T0_cc(void)
486 eflags
= cc_table
[CC_OP
].compute_all();
487 T0
= (eflags
>> 6) & 1;
490 void OPPROTO
op_setbe_T0_cc(void)
493 eflags
= cc_table
[CC_OP
].compute_all();
494 T0
= (eflags
& (CC_Z
| CC_C
)) != 0;
497 void OPPROTO
op_sets_T0_cc(void)
500 eflags
= cc_table
[CC_OP
].compute_all();
501 T0
= (eflags
>> 7) & 1;
504 void OPPROTO
op_setp_T0_cc(void)
507 eflags
= cc_table
[CC_OP
].compute_all();
508 T0
= (eflags
>> 2) & 1;
511 void OPPROTO
op_setl_T0_cc(void)
514 eflags
= cc_table
[CC_OP
].compute_all();
515 T0
= ((eflags
^ (eflags
>> 4)) >> 7) & 1;
518 void OPPROTO
op_setle_T0_cc(void)
521 eflags
= cc_table
[CC_OP
].compute_all();
522 T0
= (((eflags
^ (eflags
>> 4)) & 0x80) || (eflags
& CC_Z
)) != 0;
525 void OPPROTO
op_xor_T0_1(void)
530 void OPPROTO
op_mov_T0_cc(void)
532 T0
= cc_table
[CC_OP
].compute_all();
535 /* XXX: clear VIF/VIP in all ops ? */
537 void OPPROTO
op_movl_eflags_T0(void)
539 load_eflags(T0
, (TF_MASK
| AC_MASK
| ID_MASK
| NT_MASK
));
542 void OPPROTO
op_movw_eflags_T0(void)
544 load_eflags(T0
, (TF_MASK
| AC_MASK
| ID_MASK
| NT_MASK
) & 0xffff);
547 void OPPROTO
op_movl_eflags_T0_io(void)
549 load_eflags(T0
, (TF_MASK
| AC_MASK
| ID_MASK
| NT_MASK
| IF_MASK
));
552 void OPPROTO
op_movw_eflags_T0_io(void)
554 load_eflags(T0
, (TF_MASK
| AC_MASK
| ID_MASK
| NT_MASK
| IF_MASK
) & 0xffff);
557 void OPPROTO
op_movl_eflags_T0_cpl0(void)
559 load_eflags(T0
, (TF_MASK
| AC_MASK
| ID_MASK
| NT_MASK
| IF_MASK
| IOPL_MASK
));
562 void OPPROTO
op_movw_eflags_T0_cpl0(void)
564 load_eflags(T0
, (TF_MASK
| AC_MASK
| ID_MASK
| NT_MASK
| IF_MASK
| IOPL_MASK
) & 0xffff);
568 /* vm86plus version */
569 void OPPROTO
op_movw_eflags_T0_vm(void)
573 CC_SRC
= eflags
& (CC_O
| CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
);
574 DF
= 1 - (2 * ((eflags
>> 10) & 1));
575 /* we also update some system flags as in user mode */
576 env
->eflags
= (env
->eflags
& ~(FL_UPDATE_MASK16
| VIF_MASK
)) |
577 (eflags
& FL_UPDATE_MASK16
);
578 if (eflags
& IF_MASK
) {
579 env
->eflags
|= VIF_MASK
;
580 if (env
->eflags
& VIP_MASK
) {
582 raise_exception(EXCP0D_GPF
);
588 void OPPROTO
op_movl_eflags_T0_vm(void)
592 CC_SRC
= eflags
& (CC_O
| CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
);
593 DF
= 1 - (2 * ((eflags
>> 10) & 1));
594 /* we also update some system flags as in user mode */
595 env
->eflags
= (env
->eflags
& ~(FL_UPDATE_MASK32
| VIF_MASK
)) |
596 (eflags
& FL_UPDATE_MASK32
);
597 if (eflags
& IF_MASK
) {
598 env
->eflags
|= VIF_MASK
;
599 if (env
->eflags
& VIP_MASK
) {
601 raise_exception(EXCP0D_GPF
);
608 /* XXX: compute only O flag */
609 void OPPROTO
op_movb_eflags_T0(void)
612 of
= cc_table
[CC_OP
].compute_all() & CC_O
;
613 CC_SRC
= (T0
& (CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
)) | of
;
616 void OPPROTO
op_movl_T0_eflags(void)
619 eflags
= cc_table
[CC_OP
].compute_all();
620 eflags
|= (DF
& DF_MASK
);
621 eflags
|= env
->eflags
& ~(VM_MASK
| RF_MASK
);
625 /* vm86plus version */
627 void OPPROTO
op_movl_T0_eflags_vm(void)
630 eflags
= cc_table
[CC_OP
].compute_all();
631 eflags
|= (DF
& DF_MASK
);
632 eflags
|= env
->eflags
& ~(VM_MASK
| RF_MASK
| IF_MASK
);
633 if (env
->eflags
& VIF_MASK
)
639 void OPPROTO
op_clc(void)
642 eflags
= cc_table
[CC_OP
].compute_all();
647 void OPPROTO
op_stc(void)
650 eflags
= cc_table
[CC_OP
].compute_all();
655 void OPPROTO
op_cmc(void)
658 eflags
= cc_table
[CC_OP
].compute_all();
663 void OPPROTO
op_salc(void)
666 cf
= cc_table
[CC_OP
].compute_c();
667 EAX
= (EAX
& ~0xff) | ((-cf
) & 0xff);
670 void OPPROTO
op_fcomi_dummy(void)
676 void OPPROTO
op_com_dummy(void)