]>
git.proxmox.com Git - qemu.git/blob - target-i386/op.c
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 /* n must be a constant to be efficient */
25 static inline target_long
lshift(target_long x
, int n
)
33 /* we define the various pieces of code used by the JIT */
37 #include "opreg_template.h"
43 #include "opreg_template.h"
49 #include "opreg_template.h"
55 #include "opreg_template.h"
61 #include "opreg_template.h"
67 #include "opreg_template.h"
73 #include "opreg_template.h"
79 #include "opreg_template.h"
85 #define REG (env->regs[8])
87 #include "opreg_template.h"
91 #define REG (env->regs[9])
93 #include "opreg_template.h"
97 #define REG (env->regs[10])
99 #include "opreg_template.h"
103 #define REG (env->regs[11])
105 #include "opreg_template.h"
109 #define REG (env->regs[12])
111 #include "opreg_template.h"
115 #define REG (env->regs[13])
117 #include "opreg_template.h"
121 #define REG (env->regs[14])
123 #include "opreg_template.h"
127 #define REG (env->regs[15])
129 #include "opreg_template.h"
135 /* operations with flags */
137 /* update flags with T0 and T1 (add/sub case) */
138 void OPPROTO
op_update2_cc(void)
144 /* update flags with T0 (logic operation case) */
145 void OPPROTO
op_update1_cc(void)
150 void OPPROTO
op_update_neg_cc(void)
156 void OPPROTO
op_cmpl_T0_T1_cc(void)
162 void OPPROTO
op_update_inc_cc(void)
164 CC_SRC
= cc_table
[CC_OP
].compute_c();
168 void OPPROTO
op_testl_T0_T1_cc(void)
173 /* operations without flags */
175 void OPPROTO
op_negl_T0(void)
180 void OPPROTO
op_incl_T0(void)
185 void OPPROTO
op_decl_T0(void)
190 void OPPROTO
op_notl_T0(void)
195 /* multiply/divide */
197 /* XXX: add eflags optimizations */
198 /* XXX: add non P4 style flags */
200 void OPPROTO
op_mulb_AL_T0(void)
203 res
= (uint8_t)EAX
* (uint8_t)T0
;
204 EAX
= (EAX
& ~0xffff) | res
;
206 CC_SRC
= (res
& 0xff00);
209 void OPPROTO
op_imulb_AL_T0(void)
212 res
= (int8_t)EAX
* (int8_t)T0
;
213 EAX
= (EAX
& ~0xffff) | (res
& 0xffff);
215 CC_SRC
= (res
!= (int8_t)res
);
218 void OPPROTO
op_mulw_AX_T0(void)
221 res
= (uint16_t)EAX
* (uint16_t)T0
;
222 EAX
= (EAX
& ~0xffff) | (res
& 0xffff);
223 EDX
= (EDX
& ~0xffff) | ((res
>> 16) & 0xffff);
228 void OPPROTO
op_imulw_AX_T0(void)
231 res
= (int16_t)EAX
* (int16_t)T0
;
232 EAX
= (EAX
& ~0xffff) | (res
& 0xffff);
233 EDX
= (EDX
& ~0xffff) | ((res
>> 16) & 0xffff);
235 CC_SRC
= (res
!= (int16_t)res
);
238 void OPPROTO
op_mull_EAX_T0(void)
241 res
= (uint64_t)((uint32_t)EAX
) * (uint64_t)((uint32_t)T0
);
243 EDX
= (uint32_t)(res
>> 32);
244 CC_DST
= (uint32_t)res
;
245 CC_SRC
= (uint32_t)(res
>> 32);
248 void OPPROTO
op_imull_EAX_T0(void)
251 res
= (int64_t)((int32_t)EAX
) * (int64_t)((int32_t)T0
);
252 EAX
= (uint32_t)(res
);
253 EDX
= (uint32_t)(res
>> 32);
255 CC_SRC
= (res
!= (int32_t)res
);
258 void OPPROTO
op_imulw_T0_T1(void)
261 res
= (int16_t)T0
* (int16_t)T1
;
264 CC_SRC
= (res
!= (int16_t)res
);
267 void OPPROTO
op_imull_T0_T1(void)
270 res
= (int64_t)((int32_t)T0
) * (int64_t)((int32_t)T1
);
273 CC_SRC
= (res
!= (int32_t)res
);
277 void OPPROTO
op_mulq_EAX_T0(void)
279 helper_mulq_EAX_T0(T0
);
282 void OPPROTO
op_imulq_EAX_T0(void)
284 helper_imulq_EAX_T0(T0
);
287 void OPPROTO
op_imulq_T0_T1(void)
289 T0
= helper_imulq_T0_T1(T0
, T1
);
293 /* constant load & misc op */
295 /* XXX: consistent names */
296 void OPPROTO
op_addl_T1_im(void)
301 void OPPROTO
op_movl_T1_A0(void)
306 void OPPROTO
op_addl_A0_AL(void)
308 A0
= (uint32_t)(A0
+ (EAX
& 0xff));
311 #ifdef WORDS_BIGENDIAN
312 typedef union UREG64
{
313 struct { uint16_t v3
, v2
, v1
, v0
; } w
;
314 struct { uint32_t v1
, v0
; } l
;
318 typedef union UREG64
{
319 struct { uint16_t v0
, v1
, v2
, v3
; } w
;
320 struct { uint32_t v0
, v1
; } l
;
335 void OPPROTO
op_addq_A0_AL(void)
337 A0
= (A0
+ (EAX
& 0xff));
342 void OPPROTO
op_into(void)
345 eflags
= cc_table
[CC_OP
].compute_all();
347 raise_interrupt(EXCP04_INTO
, 1, 0, PARAM1
);
352 void OPPROTO
op_cmpxchg8b(void)
354 helper_cmpxchg8b(A0
);
357 /* multiple size ops */
362 #include "ops_template.h"
366 #include "ops_template.h"
370 #include "ops_template.h"
376 #include "ops_template.h"
383 void OPPROTO
op_movsbl_T0_T0(void)
388 void OPPROTO
op_movzbl_T0_T0(void)
393 void OPPROTO
op_movswl_T0_T0(void)
398 void OPPROTO
op_movzwl_T0_T0(void)
403 void OPPROTO
op_movswl_EAX_AX(void)
405 EAX
= (uint32_t)((int16_t)EAX
);
409 void OPPROTO
op_movslq_T0_T0(void)
414 void OPPROTO
op_movslq_RAX_EAX(void)
420 void OPPROTO
op_movsbw_AX_AL(void)
422 EAX
= (EAX
& ~0xffff) | ((int8_t)EAX
& 0xffff);
425 void OPPROTO
op_movslq_EDX_EAX(void)
427 EDX
= (uint32_t)((int32_t)EAX
>> 31);
430 void OPPROTO
op_movswl_DX_AX(void)
432 EDX
= (EDX
& ~0xffff) | (((int16_t)EAX
>> 15) & 0xffff);
436 void OPPROTO
op_movsqo_RDX_RAX(void)
438 EDX
= (int64_t)EAX
>> 63;
442 /* string ops helpers */
444 void OPPROTO
op_addl_ESI_T0(void)
446 ESI
= (uint32_t)(ESI
+ T0
);
449 void OPPROTO
op_addw_ESI_T0(void)
451 ESI
= (ESI
& ~0xffff) | ((ESI
+ T0
) & 0xffff);
454 void OPPROTO
op_addl_EDI_T0(void)
456 EDI
= (uint32_t)(EDI
+ T0
);
459 void OPPROTO
op_addw_EDI_T0(void)
461 EDI
= (EDI
& ~0xffff) | ((EDI
+ T0
) & 0xffff);
464 void OPPROTO
op_decl_ECX(void)
466 ECX
= (uint32_t)(ECX
- 1);
469 void OPPROTO
op_decw_ECX(void)
471 ECX
= (ECX
& ~0xffff) | ((ECX
- 1) & 0xffff);
475 void OPPROTO
op_addq_ESI_T0(void)
480 void OPPROTO
op_addq_EDI_T0(void)
485 void OPPROTO
op_decq_ECX(void)
493 void OPPROTO
op_aam(void)
498 void OPPROTO
op_aad(void)
503 void OPPROTO
op_aaa(void)
508 void OPPROTO
op_aas(void)
513 void OPPROTO
op_daa(void)
518 void OPPROTO
op_das(void)
523 /* segment handling */
525 /* faster VM86 version */
526 void OPPROTO
op_movl_seg_T0_vm(void)
531 selector
= T0
& 0xffff;
532 /* env->segs[] access */
533 sc
= (SegmentCache
*)((char *)env
+ PARAM1
);
534 sc
->selector
= selector
;
535 sc
->base
= (selector
<< 4);
538 void OPPROTO
op_movl_T0_seg(void)
540 T0
= env
->segs
[PARAM1
].selector
;
543 void OPPROTO
op_lsl(void)
546 val
= helper_lsl(T0
);
552 void OPPROTO
op_lar(void)
555 val
= helper_lar(T0
);
561 void OPPROTO
op_verr(void)
566 void OPPROTO
op_verw(void)
571 void OPPROTO
op_arpl(void)
573 if ((T0
& 3) < (T1
& 3)) {
574 /* XXX: emulate bug or 0xff3f0000 oring as in bochs ? */
575 T0
= (T0
& ~3) | (T1
& 3);
583 void OPPROTO
op_arpl_update(void)
586 eflags
= cc_table
[CC_OP
].compute_all();
587 CC_SRC
= (eflags
& ~CC_Z
) | T1
;
590 void OPPROTO
op_movl_T0_env(void)
592 T0
= *(uint32_t *)((char *)env
+ PARAM1
);
595 void OPPROTO
op_movl_env_T0(void)
597 *(uint32_t *)((char *)env
+ PARAM1
) = T0
;
600 void OPPROTO
op_movl_env_T1(void)
602 *(uint32_t *)((char *)env
+ PARAM1
) = T1
;
605 void OPPROTO
op_movtl_T0_env(void)
607 T0
= *(target_ulong
*)((char *)env
+ PARAM1
);
610 void OPPROTO
op_movtl_env_T0(void)
612 *(target_ulong
*)((char *)env
+ PARAM1
) = T0
;
615 void OPPROTO
op_movtl_T1_env(void)
617 T1
= *(target_ulong
*)((char *)env
+ PARAM1
);
620 void OPPROTO
op_movtl_env_T1(void)
622 *(target_ulong
*)((char *)env
+ PARAM1
) = T1
;
627 void OPPROTO
op_jmp_label(void)
632 void OPPROTO
op_jnz_T0_label(void)
639 void OPPROTO
op_jz_T0_label(void)
646 /* slow set cases (compute x86 flags) */
647 void OPPROTO
op_seto_T0_cc(void)
650 eflags
= cc_table
[CC_OP
].compute_all();
651 T0
= (eflags
>> 11) & 1;
654 void OPPROTO
op_setb_T0_cc(void)
656 T0
= cc_table
[CC_OP
].compute_c();
659 void OPPROTO
op_setz_T0_cc(void)
662 eflags
= cc_table
[CC_OP
].compute_all();
663 T0
= (eflags
>> 6) & 1;
666 void OPPROTO
op_setbe_T0_cc(void)
669 eflags
= cc_table
[CC_OP
].compute_all();
670 T0
= (eflags
& (CC_Z
| CC_C
)) != 0;
673 void OPPROTO
op_sets_T0_cc(void)
676 eflags
= cc_table
[CC_OP
].compute_all();
677 T0
= (eflags
>> 7) & 1;
680 void OPPROTO
op_setp_T0_cc(void)
683 eflags
= cc_table
[CC_OP
].compute_all();
684 T0
= (eflags
>> 2) & 1;
687 void OPPROTO
op_setl_T0_cc(void)
690 eflags
= cc_table
[CC_OP
].compute_all();
691 T0
= ((eflags
^ (eflags
>> 4)) >> 7) & 1;
694 void OPPROTO
op_setle_T0_cc(void)
697 eflags
= cc_table
[CC_OP
].compute_all();
698 T0
= (((eflags
^ (eflags
>> 4)) & 0x80) || (eflags
& CC_Z
)) != 0;
701 void OPPROTO
op_xor_T0_1(void)
706 void OPPROTO
op_mov_T0_cc(void)
708 T0
= cc_table
[CC_OP
].compute_all();
711 /* XXX: clear VIF/VIP in all ops ? */
713 void OPPROTO
op_movl_eflags_T0(void)
715 load_eflags(T0
, (TF_MASK
| AC_MASK
| ID_MASK
| NT_MASK
));
718 void OPPROTO
op_movw_eflags_T0(void)
720 load_eflags(T0
, (TF_MASK
| AC_MASK
| ID_MASK
| NT_MASK
) & 0xffff);
723 void OPPROTO
op_movl_eflags_T0_io(void)
725 load_eflags(T0
, (TF_MASK
| AC_MASK
| ID_MASK
| NT_MASK
| IF_MASK
));
728 void OPPROTO
op_movw_eflags_T0_io(void)
730 load_eflags(T0
, (TF_MASK
| AC_MASK
| ID_MASK
| NT_MASK
| IF_MASK
) & 0xffff);
733 void OPPROTO
op_movl_eflags_T0_cpl0(void)
735 load_eflags(T0
, (TF_MASK
| AC_MASK
| ID_MASK
| NT_MASK
| IF_MASK
| IOPL_MASK
));
738 void OPPROTO
op_movw_eflags_T0_cpl0(void)
740 load_eflags(T0
, (TF_MASK
| AC_MASK
| ID_MASK
| NT_MASK
| IF_MASK
| IOPL_MASK
) & 0xffff);
744 /* vm86plus version */
745 void OPPROTO
op_movw_eflags_T0_vm(void)
749 CC_SRC
= eflags
& (CC_O
| CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
);
750 DF
= 1 - (2 * ((eflags
>> 10) & 1));
751 /* we also update some system flags as in user mode */
752 env
->eflags
= (env
->eflags
& ~(FL_UPDATE_MASK16
| VIF_MASK
)) |
753 (eflags
& FL_UPDATE_MASK16
);
754 if (eflags
& IF_MASK
) {
755 env
->eflags
|= VIF_MASK
;
756 if (env
->eflags
& VIP_MASK
) {
758 raise_exception(EXCP0D_GPF
);
764 void OPPROTO
op_movl_eflags_T0_vm(void)
768 CC_SRC
= eflags
& (CC_O
| CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
);
769 DF
= 1 - (2 * ((eflags
>> 10) & 1));
770 /* we also update some system flags as in user mode */
771 env
->eflags
= (env
->eflags
& ~(FL_UPDATE_MASK32
| VIF_MASK
)) |
772 (eflags
& FL_UPDATE_MASK32
);
773 if (eflags
& IF_MASK
) {
774 env
->eflags
|= VIF_MASK
;
775 if (env
->eflags
& VIP_MASK
) {
777 raise_exception(EXCP0D_GPF
);
784 /* XXX: compute only O flag */
785 void OPPROTO
op_movb_eflags_T0(void)
788 of
= cc_table
[CC_OP
].compute_all() & CC_O
;
789 CC_SRC
= (T0
& (CC_S
| CC_Z
| CC_A
| CC_P
| CC_C
)) | of
;
792 void OPPROTO
op_movl_T0_eflags(void)
795 eflags
= cc_table
[CC_OP
].compute_all();
796 eflags
|= (DF
& DF_MASK
);
797 eflags
|= env
->eflags
& ~(VM_MASK
| RF_MASK
);
801 /* vm86plus version */
803 void OPPROTO
op_movl_T0_eflags_vm(void)
806 eflags
= cc_table
[CC_OP
].compute_all();
807 eflags
|= (DF
& DF_MASK
);
808 eflags
|= env
->eflags
& ~(VM_MASK
| RF_MASK
| IF_MASK
);
809 if (env
->eflags
& VIF_MASK
)
815 void OPPROTO
op_clc(void)
818 eflags
= cc_table
[CC_OP
].compute_all();
823 void OPPROTO
op_stc(void)
826 eflags
= cc_table
[CC_OP
].compute_all();
831 void OPPROTO
op_cmc(void)
834 eflags
= cc_table
[CC_OP
].compute_all();
839 void OPPROTO
op_salc(void)
842 cf
= cc_table
[CC_OP
].compute_c();
843 EAX
= (EAX
& ~0xff) | ((-cf
) & 0xff);
846 static int compute_all_eflags(void)
851 static int compute_c_eflags(void)
853 return CC_SRC
& CC_C
;
856 CCTable cc_table
[CC_OP_NB
] = {
857 [CC_OP_DYNAMIC
] = { /* should never happen */ },
859 [CC_OP_EFLAGS
] = { compute_all_eflags
, compute_c_eflags
},
861 [CC_OP_MULB
] = { compute_all_mulb
, compute_c_mull
},
862 [CC_OP_MULW
] = { compute_all_mulw
, compute_c_mull
},
863 [CC_OP_MULL
] = { compute_all_mull
, compute_c_mull
},
865 [CC_OP_ADDB
] = { compute_all_addb
, compute_c_addb
},
866 [CC_OP_ADDW
] = { compute_all_addw
, compute_c_addw
},
867 [CC_OP_ADDL
] = { compute_all_addl
, compute_c_addl
},
869 [CC_OP_ADCB
] = { compute_all_adcb
, compute_c_adcb
},
870 [CC_OP_ADCW
] = { compute_all_adcw
, compute_c_adcw
},
871 [CC_OP_ADCL
] = { compute_all_adcl
, compute_c_adcl
},
873 [CC_OP_SUBB
] = { compute_all_subb
, compute_c_subb
},
874 [CC_OP_SUBW
] = { compute_all_subw
, compute_c_subw
},
875 [CC_OP_SUBL
] = { compute_all_subl
, compute_c_subl
},
877 [CC_OP_SBBB
] = { compute_all_sbbb
, compute_c_sbbb
},
878 [CC_OP_SBBW
] = { compute_all_sbbw
, compute_c_sbbw
},
879 [CC_OP_SBBL
] = { compute_all_sbbl
, compute_c_sbbl
},
881 [CC_OP_LOGICB
] = { compute_all_logicb
, compute_c_logicb
},
882 [CC_OP_LOGICW
] = { compute_all_logicw
, compute_c_logicw
},
883 [CC_OP_LOGICL
] = { compute_all_logicl
, compute_c_logicl
},
885 [CC_OP_INCB
] = { compute_all_incb
, compute_c_incl
},
886 [CC_OP_INCW
] = { compute_all_incw
, compute_c_incl
},
887 [CC_OP_INCL
] = { compute_all_incl
, compute_c_incl
},
889 [CC_OP_DECB
] = { compute_all_decb
, compute_c_incl
},
890 [CC_OP_DECW
] = { compute_all_decw
, compute_c_incl
},
891 [CC_OP_DECL
] = { compute_all_decl
, compute_c_incl
},
893 [CC_OP_SHLB
] = { compute_all_shlb
, compute_c_shlb
},
894 [CC_OP_SHLW
] = { compute_all_shlw
, compute_c_shlw
},
895 [CC_OP_SHLL
] = { compute_all_shll
, compute_c_shll
},
897 [CC_OP_SARB
] = { compute_all_sarb
, compute_c_sarl
},
898 [CC_OP_SARW
] = { compute_all_sarw
, compute_c_sarl
},
899 [CC_OP_SARL
] = { compute_all_sarl
, compute_c_sarl
},
902 [CC_OP_MULQ
] = { compute_all_mulq
, compute_c_mull
},
904 [CC_OP_ADDQ
] = { compute_all_addq
, compute_c_addq
},
906 [CC_OP_ADCQ
] = { compute_all_adcq
, compute_c_adcq
},
908 [CC_OP_SUBQ
] = { compute_all_subq
, compute_c_subq
},
910 [CC_OP_SBBQ
] = { compute_all_sbbq
, compute_c_sbbq
},
912 [CC_OP_LOGICQ
] = { compute_all_logicq
, compute_c_logicq
},
914 [CC_OP_INCQ
] = { compute_all_incq
, compute_c_incl
},
916 [CC_OP_DECQ
] = { compute_all_decq
, compute_c_incl
},
918 [CC_OP_SHLQ
] = { compute_all_shlq
, compute_c_shlq
},
920 [CC_OP_SARQ
] = { compute_all_sarq
, compute_c_sarl
},
924 void OPPROTO
op_fcomi_dummy(void)
930 void OPPROTO
op_com_dummy(void)