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_addl_T1_im(void)
232 void OPPROTO op_movl_T1_A0(void)
237 void OPPROTO op_addl_A0_AL(void)
239 A0 = (uint32_t)(A0 + (EAX & 0xff));
244 void OPPROTO op_addq_A0_AL(void)
246 A0 = (A0 + (EAX & 0xff));
251 void OPPROTO op_into(void)
254 eflags = cc_table[CC_OP].compute_all();
256 raise_interrupt(EXCP04_INTO, 1, 0, PARAM1);
261 void OPPROTO op_cmpxchg8b(void)
263 helper_cmpxchg8b(A0);
266 /* multiple size ops */
271 #include "ops_template.h"
275 #include "ops_template.h"
279 #include "ops_template.h"
285 #include "ops_template.h"
292 void OPPROTO op_movsbl_T0_T0(void)
297 void OPPROTO op_movzbl_T0_T0(void)
302 void OPPROTO op_movswl_T0_T0(void)
307 void OPPROTO op_movzwl_T0_T0(void)
312 void OPPROTO op_movswl_EAX_AX(void)
314 EAX = (uint32_t)((int16_t)EAX);
318 void OPPROTO op_movslq_T0_T0(void)
323 void OPPROTO op_movslq_RAX_EAX(void)
329 void OPPROTO op_movsbw_AX_AL(void)
331 EAX = (EAX & ~0xffff) | ((int8_t)EAX & 0xffff);
334 void OPPROTO op_movslq_EDX_EAX(void)
336 EDX = (uint32_t)((int32_t)EAX >> 31);
339 void OPPROTO op_movswl_DX_AX(void)
341 EDX = (EDX & ~0xffff) | (((int16_t)EAX >> 15) & 0xffff);
345 void OPPROTO op_movsqo_RDX_RAX(void)
347 EDX = (int64_t)EAX >> 63;
351 /* string ops helpers */
353 void OPPROTO op_addl_ESI_T0(void)
355 ESI = (uint32_t)(ESI + T0);
358 void OPPROTO op_addw_ESI_T0(void)
360 ESI = (ESI & ~0xffff) | ((ESI + T0) & 0xffff);
363 void OPPROTO op_addl_EDI_T0(void)
365 EDI = (uint32_t)(EDI + T0);
368 void OPPROTO op_addw_EDI_T0(void)
370 EDI = (EDI & ~0xffff) | ((EDI + T0) & 0xffff);
373 void OPPROTO op_decl_ECX(void)
375 ECX = (uint32_t)(ECX - 1);
378 void OPPROTO op_decw_ECX(void)
380 ECX = (ECX & ~0xffff) | ((ECX - 1) & 0xffff);
384 void OPPROTO op_addq_ESI_T0(void)
389 void OPPROTO op_addq_EDI_T0(void)
394 void OPPROTO op_decq_ECX(void)
402 void OPPROTO op_aam(void)
407 void OPPROTO op_aad(void)
412 void OPPROTO op_aaa(void)
417 void OPPROTO op_aas(void)
422 void OPPROTO op_daa(void)
427 void OPPROTO op_das(void)
432 /* segment handling */
434 /* faster VM86 version */
435 void OPPROTO op_movl_seg_T0_vm(void)
440 selector = T0 & 0xffff;
441 /* env->segs[] access */
442 sc = (SegmentCache *)((char *)env + PARAM1);
443 sc->selector = selector;
444 sc->base = (selector << 4);
447 void OPPROTO op_movl_T0_seg(void)
449 T0 = env->segs[PARAM1].selector;
452 void OPPROTO op_lsl(void)
455 val = helper_lsl(T0);
461 void OPPROTO op_lar(void)
464 val = helper_lar(T0);
470 void OPPROTO op_verr(void)
475 void OPPROTO op_verw(void)
480 void OPPROTO op_arpl(void)
482 if ((T0 & 3) < (T1 & 3)) {
483 /* XXX: emulate bug or 0xff3f0000 oring as in bochs ? */
484 T0 = (T0 & ~3) | (T1 & 3);
492 void OPPROTO op_arpl_update(void)
495 eflags = cc_table[CC_OP].compute_all();
496 CC_SRC = (eflags & ~CC_Z) | T1;
499 void OPPROTO op_movl_T0_env(void)
501 T0 = *(uint32_t *)((char *)env + PARAM1);
504 void OPPROTO op_movl_env_T0(void)
506 *(uint32_t *)((char *)env + PARAM1) = T0;
509 void OPPROTO op_movl_env_T1(void)
511 *(uint32_t *)((char *)env + PARAM1) = T1;
514 void OPPROTO op_movtl_T0_env(void)
516 T0 = *(target_ulong *)((char *)env + PARAM1);
519 void OPPROTO op_movtl_env_T0(void)
521 *(target_ulong *)((char *)env + PARAM1) = T0;
524 void OPPROTO op_movtl_T1_env(void)
526 T1 = *(target_ulong *)((char *)env + PARAM1);
529 void OPPROTO op_movtl_env_T1(void)
531 *(target_ulong *)((char *)env + PARAM1) = T1;
536 void OPPROTO op_jmp_label(void)
541 void OPPROTO op_jnz_T0_label(void)
548 void OPPROTO op_jz_T0_label(void)
555 /* slow set cases (compute x86 flags) */
556 void OPPROTO op_seto_T0_cc(void)
559 eflags = cc_table[CC_OP].compute_all();
560 T0 = (eflags >> 11) & 1;
563 void OPPROTO op_setb_T0_cc(void)
565 T0 = cc_table[CC_OP].compute_c();
568 void OPPROTO op_setz_T0_cc(void)
571 eflags = cc_table[CC_OP].compute_all();
572 T0 = (eflags >> 6) & 1;
575 void OPPROTO op_setbe_T0_cc(void)
578 eflags = cc_table[CC_OP].compute_all();
579 T0 = (eflags & (CC_Z | CC_C)) != 0;
582 void OPPROTO op_sets_T0_cc(void)
585 eflags = cc_table[CC_OP].compute_all();
586 T0 = (eflags >> 7) & 1;
589 void OPPROTO op_setp_T0_cc(void)
592 eflags = cc_table[CC_OP].compute_all();
593 T0 = (eflags >> 2) & 1;
596 void OPPROTO op_setl_T0_cc(void)
599 eflags = cc_table[CC_OP].compute_all();
600 T0 = ((eflags ^ (eflags >> 4)) >> 7) & 1;
603 void OPPROTO op_setle_T0_cc(void)
606 eflags = cc_table[CC_OP].compute_all();
607 T0 = (((eflags ^ (eflags >> 4)) & 0x80) || (eflags & CC_Z)) != 0;
610 void OPPROTO op_xor_T0_1(void)
615 void OPPROTO op_mov_T0_cc(void)
617 T0 = cc_table[CC_OP].compute_all();
620 /* XXX: clear VIF/VIP in all ops ? */
622 void OPPROTO op_movl_eflags_T0(void)
624 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK));
627 void OPPROTO op_movw_eflags_T0(void)
629 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK) & 0xffff);
632 void OPPROTO op_movl_eflags_T0_io(void)
634 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK));
637 void OPPROTO op_movw_eflags_T0_io(void)
639 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK) & 0xffff);
642 void OPPROTO op_movl_eflags_T0_cpl0(void)
644 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK));
647 void OPPROTO op_movw_eflags_T0_cpl0(void)
649 load_eflags(T0, (TF_MASK | AC_MASK | ID_MASK | NT_MASK | IF_MASK | IOPL_MASK) & 0xffff);
653 /* vm86plus version */
654 void OPPROTO op_movw_eflags_T0_vm(void)
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) {
667 raise_exception(EXCP0D_GPF);
673 void OPPROTO op_movl_eflags_T0_vm(void)
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) {
686 raise_exception(EXCP0D_GPF);
693 /* XXX: compute only O flag */
694 void OPPROTO op_movb_eflags_T0(void)
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;
701 void OPPROTO op_movl_T0_eflags(void)
704 eflags = cc_table[CC_OP].compute_all();
705 eflags |= (DF & DF_MASK);
706 eflags |= env->eflags & ~(VM_MASK | RF_MASK);
710 /* vm86plus version */
712 void OPPROTO op_movl_T0_eflags_vm(void)
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)
724 void OPPROTO op_clc(void)
727 eflags = cc_table[CC_OP].compute_all();
732 void OPPROTO op_stc(void)
735 eflags = cc_table[CC_OP].compute_all();
740 void OPPROTO op_cmc(void)
743 eflags = cc_table[CC_OP].compute_all();
748 void OPPROTO op_salc(void)
751 cf = cc_table[CC_OP].compute_c();
752 EAX = (EAX & ~0xff) | ((-cf) & 0xff);
755 static int compute_all_eflags(void)
760 static int compute_c_eflags(void)
762 return CC_SRC & CC_C;
765 CCTable cc_table[CC_OP_NB] = {
766 [CC_OP_DYNAMIC] = { /* should never happen */ },
768 [CC_OP_EFLAGS] = { compute_all_eflags, compute_c_eflags },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
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 },
811 [CC_OP_MULQ] = { compute_all_mulq, compute_c_mull },
813 [CC_OP_ADDQ] = { compute_all_addq, compute_c_addq },
815 [CC_OP_ADCQ] = { compute_all_adcq, compute_c_adcq },
817 [CC_OP_SUBQ] = { compute_all_subq, compute_c_subq },
819 [CC_OP_SBBQ] = { compute_all_sbbq, compute_c_sbbq },
821 [CC_OP_LOGICQ] = { compute_all_logicq, compute_c_logicq },
823 [CC_OP_INCQ] = { compute_all_incq, compute_c_incl },
825 [CC_OP_DECQ] = { compute_all_decq, compute_c_incl },
827 [CC_OP_SHLQ] = { compute_all_shlq, compute_c_shlq },
829 [CC_OP_SARQ] = { compute_all_sarq, compute_c_sarl },
833 void OPPROTO op_fcomi_dummy(void)
839 void OPPROTO op_com_dummy(void)