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
36 /* XXX: move that elsewhere */
37 static uint16_t *gen_opc_ptr;
38 static uint32_t *gen_opparam_ptr;
39 int __op_param1, __op_param2, __op_param3;
40 #ifdef USE_DIRECT_JUMP
41 int __op_jmp0, __op_jmp1;
45 static inline void flush_icache_range(unsigned long start, unsigned long stop)
51 static inline void flush_icache_range(unsigned long start, unsigned long stop)
57 static inline void flush_icache_range(unsigned long start, unsigned long stop)
64 #define MIN_CACHE_LINE_SIZE 8 /* conservative value */
66 static void inline flush_icache_range(unsigned long start, unsigned long stop)
70 p = start & ~(MIN_CACHE_LINE_SIZE - 1);
71 stop = (stop + MIN_CACHE_LINE_SIZE - 1) & ~(MIN_CACHE_LINE_SIZE - 1);
73 for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
74 asm volatile ("dcbst 0,%0" : : "r"(p) : "memory");
76 asm volatile ("sync" : : : "memory");
77 for (p = start; p < stop; p += MIN_CACHE_LINE_SIZE) {
78 asm volatile ("icbi 0,%0" : : "r"(p) : "memory");
80 asm volatile ("sync" : : : "memory");
81 asm volatile ("isync" : : : "memory");
86 static inline void flush_icache_range(unsigned long start, unsigned long stop)
94 static void inline flush_icache_range(unsigned long start, unsigned long stop)
98 p = start & ~(8UL - 1UL);
99 stop = (stop + (8UL - 1UL)) & ~(8UL - 1UL);
101 for (; p < stop; p += 8)
102 __asm__ __volatile__("flush\t%0" : : "r" (p));
107 extern FILE *logfile;
110 #define PREFIX_REPZ 0x01
111 #define PREFIX_REPNZ 0x02
112 #define PREFIX_LOCK 0x04
113 #define PREFIX_DATA 0x08
114 #define PREFIX_ADR 0x10
116 typedef struct DisasContext {
117 /* current insn context */
118 int override; /* -1 if no override */
121 uint8_t *pc; /* pc = eip + cs_base */
122 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
123 static state change (stop translation) */
124 /* current block context */
125 uint8_t *cs_base; /* base of CS segment */
126 int code32; /* 32 bit code segment */
127 int ss32; /* 32 bit stack segment */
128 int cc_op; /* current CC operation */
129 int addseg; /* non zero if either DS/ES/SS have a non zero base */
130 int f_st; /* currently unused */
131 int vm86; /* vm86 mode */
134 int tf; /* TF cpu flag */
135 TranslationBlock *tb;
138 /* i386 arith/logic operations */
158 OP_SHL1, /* undocumented */
163 #define DEF(s, n, copy_size) INDEX_op_ ## s,
164 #include "opc-i386.h"
180 /* I386 int registers */
181 OR_EAX, /* MUST be even numbered */
189 OR_TMP0, /* temporary operand register */
191 OR_A0, /* temporary register used when doing address evaluation */
192 OR_ZERO, /* fixed zero register */
196 typedef void (GenOpFunc)(void);
197 typedef void (GenOpFunc1)(long);
198 typedef void (GenOpFunc2)(long, long);
199 typedef void (GenOpFunc3)(long, long, long);
201 static GenOpFunc *gen_op_mov_reg_T0[3][8] = {
234 static GenOpFunc *gen_op_mov_reg_T1[3][8] = {
267 static GenOpFunc *gen_op_mov_reg_A0[2][8] = {
290 static GenOpFunc *gen_op_mov_TN_reg[3][2][8] =
360 static GenOpFunc *gen_op_movl_A0_reg[8] = {
371 static GenOpFunc *gen_op_addl_A0_reg_sN[4][8] = {
383 gen_op_addl_A0_EAX_s1,
384 gen_op_addl_A0_ECX_s1,
385 gen_op_addl_A0_EDX_s1,
386 gen_op_addl_A0_EBX_s1,
387 gen_op_addl_A0_ESP_s1,
388 gen_op_addl_A0_EBP_s1,
389 gen_op_addl_A0_ESI_s1,
390 gen_op_addl_A0_EDI_s1,
393 gen_op_addl_A0_EAX_s2,
394 gen_op_addl_A0_ECX_s2,
395 gen_op_addl_A0_EDX_s2,
396 gen_op_addl_A0_EBX_s2,
397 gen_op_addl_A0_ESP_s2,
398 gen_op_addl_A0_EBP_s2,
399 gen_op_addl_A0_ESI_s2,
400 gen_op_addl_A0_EDI_s2,
403 gen_op_addl_A0_EAX_s3,
404 gen_op_addl_A0_ECX_s3,
405 gen_op_addl_A0_EDX_s3,
406 gen_op_addl_A0_EBX_s3,
407 gen_op_addl_A0_ESP_s3,
408 gen_op_addl_A0_EBP_s3,
409 gen_op_addl_A0_ESI_s3,
410 gen_op_addl_A0_EDI_s3,
414 static GenOpFunc *gen_op_cmov_reg_T1_T0[2][8] = {
416 gen_op_cmovw_EAX_T1_T0,
417 gen_op_cmovw_ECX_T1_T0,
418 gen_op_cmovw_EDX_T1_T0,
419 gen_op_cmovw_EBX_T1_T0,
420 gen_op_cmovw_ESP_T1_T0,
421 gen_op_cmovw_EBP_T1_T0,
422 gen_op_cmovw_ESI_T1_T0,
423 gen_op_cmovw_EDI_T1_T0,
426 gen_op_cmovl_EAX_T1_T0,
427 gen_op_cmovl_ECX_T1_T0,
428 gen_op_cmovl_EDX_T1_T0,
429 gen_op_cmovl_EBX_T1_T0,
430 gen_op_cmovl_ESP_T1_T0,
431 gen_op_cmovl_EBP_T1_T0,
432 gen_op_cmovl_ESI_T1_T0,
433 gen_op_cmovl_EDI_T1_T0,
437 static GenOpFunc *gen_op_arith_T0_T1_cc[8] = {
438 gen_op_addl_T0_T1_cc,
442 gen_op_andl_T0_T1_cc,
443 gen_op_subl_T0_T1_cc,
444 gen_op_xorl_T0_T1_cc,
445 gen_op_cmpl_T0_T1_cc,
448 static GenOpFunc *gen_op_arithc_T0_T1_cc[3][2] = {
450 gen_op_adcb_T0_T1_cc,
451 gen_op_sbbb_T0_T1_cc,
454 gen_op_adcw_T0_T1_cc,
455 gen_op_sbbw_T0_T1_cc,
458 gen_op_adcl_T0_T1_cc,
459 gen_op_sbbl_T0_T1_cc,
463 static const int cc_op_arithb[8] = {
474 static GenOpFunc *gen_op_cmpxchg_T0_T1_EAX_cc[3] = {
475 gen_op_cmpxchgb_T0_T1_EAX_cc,
476 gen_op_cmpxchgw_T0_T1_EAX_cc,
477 gen_op_cmpxchgl_T0_T1_EAX_cc,
480 static GenOpFunc *gen_op_shift_T0_T1_cc[3][8] = {
482 gen_op_rolb_T0_T1_cc,
483 gen_op_rorb_T0_T1_cc,
484 gen_op_rclb_T0_T1_cc,
485 gen_op_rcrb_T0_T1_cc,
486 gen_op_shlb_T0_T1_cc,
487 gen_op_shrb_T0_T1_cc,
488 gen_op_shlb_T0_T1_cc,
489 gen_op_sarb_T0_T1_cc,
492 gen_op_rolw_T0_T1_cc,
493 gen_op_rorw_T0_T1_cc,
494 gen_op_rclw_T0_T1_cc,
495 gen_op_rcrw_T0_T1_cc,
496 gen_op_shlw_T0_T1_cc,
497 gen_op_shrw_T0_T1_cc,
498 gen_op_shlw_T0_T1_cc,
499 gen_op_sarw_T0_T1_cc,
502 gen_op_roll_T0_T1_cc,
503 gen_op_rorl_T0_T1_cc,
504 gen_op_rcll_T0_T1_cc,
505 gen_op_rcrl_T0_T1_cc,
506 gen_op_shll_T0_T1_cc,
507 gen_op_shrl_T0_T1_cc,
508 gen_op_shll_T0_T1_cc,
509 gen_op_sarl_T0_T1_cc,
513 static GenOpFunc1 *gen_op_shiftd_T0_T1_im_cc[2][2] = {
515 gen_op_shldw_T0_T1_im_cc,
516 gen_op_shrdw_T0_T1_im_cc,
519 gen_op_shldl_T0_T1_im_cc,
520 gen_op_shrdl_T0_T1_im_cc,
524 static GenOpFunc *gen_op_shiftd_T0_T1_ECX_cc[2][2] = {
526 gen_op_shldw_T0_T1_ECX_cc,
527 gen_op_shrdw_T0_T1_ECX_cc,
530 gen_op_shldl_T0_T1_ECX_cc,
531 gen_op_shrdl_T0_T1_ECX_cc,
535 static GenOpFunc *gen_op_btx_T0_T1_cc[2][4] = {
538 gen_op_btsw_T0_T1_cc,
539 gen_op_btrw_T0_T1_cc,
540 gen_op_btcw_T0_T1_cc,
544 gen_op_btsl_T0_T1_cc,
545 gen_op_btrl_T0_T1_cc,
546 gen_op_btcl_T0_T1_cc,
550 static GenOpFunc *gen_op_bsx_T0_cc[2][2] = {
561 static GenOpFunc *gen_op_lds_T0_A0[3] = {
566 static GenOpFunc *gen_op_ldu_T0_A0[3] = {
571 /* sign does not matter */
572 static GenOpFunc *gen_op_ld_T0_A0[3] = {
578 static GenOpFunc *gen_op_ld_T1_A0[3] = {
584 static GenOpFunc *gen_op_st_T0_A0[3] = {
590 /* the _a32 and _a16 string operations use A0 as the base register. */
592 #define STRINGOP(x) \
593 gen_op_ ## x ## b_fast, \
594 gen_op_ ## x ## w_fast, \
595 gen_op_ ## x ## l_fast, \
596 gen_op_ ## x ## b_a32, \
597 gen_op_ ## x ## w_a32, \
598 gen_op_ ## x ## l_a32, \
599 gen_op_ ## x ## b_a16, \
600 gen_op_ ## x ## w_a16, \
601 gen_op_ ## x ## l_a16,
603 static GenOpFunc *gen_op_movs[9 * 2] = {
608 static GenOpFunc *gen_op_stos[9 * 2] = {
613 static GenOpFunc *gen_op_lods[9 * 2] = {
618 static GenOpFunc *gen_op_scas[9 * 3] = {
624 static GenOpFunc *gen_op_cmps[9 * 3] = {
630 static GenOpFunc *gen_op_ins[9 * 2] = {
636 static GenOpFunc *gen_op_outs[9 * 2] = {
642 static inline void gen_string_ds(DisasContext *s, int ot, GenOpFunc **func)
646 override = s->override;
649 if (s->addseg && override < 0)
652 gen_op_movl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
660 gen_op_movl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
661 /* 16 address, always override */
667 static inline void gen_string_es(DisasContext *s, int ot, GenOpFunc **func)
684 static GenOpFunc *gen_op_in[3] = {
690 static GenOpFunc *gen_op_out[3] = {
707 static GenOpFunc3 *gen_jcc_sub[3][8] = {
739 static GenOpFunc2 *gen_op_loop[2][4] = {
754 static GenOpFunc *gen_setcc_slow[8] = {
765 static GenOpFunc *gen_setcc_sub[3][8] = {
770 gen_op_setbe_T0_subb,
774 gen_op_setle_T0_subb,
780 gen_op_setbe_T0_subw,
784 gen_op_setle_T0_subw,
790 gen_op_setbe_T0_subl,
794 gen_op_setle_T0_subl,
798 static GenOpFunc *gen_op_fp_arith_ST0_FT0[8] = {
804 gen_op_fsubr_ST0_FT0,
806 gen_op_fdivr_ST0_FT0,
809 /* NOTE the exception in "r" op ordering */
810 static GenOpFunc1 *gen_op_fp_arith_STN_ST0[8] = {
815 gen_op_fsubr_STN_ST0,
817 gen_op_fdivr_STN_ST0,
821 static void gen_op(DisasContext *s1, int op, int ot, int d, int s)
824 gen_op_mov_TN_reg[ot][0][d]();
826 gen_op_mov_TN_reg[ot][1][s]();
827 if (op == OP_ADCL || op == OP_SBBL) {
828 if (s1->cc_op != CC_OP_DYNAMIC)
829 gen_op_set_cc_op(s1->cc_op);
830 gen_op_arithc_T0_T1_cc[ot][op - OP_ADCL]();
831 s1->cc_op = CC_OP_DYNAMIC;
833 gen_op_arith_T0_T1_cc[op]();
834 s1->cc_op = cc_op_arithb[op] + ot;
836 if (d != OR_TMP0 && op != OP_CMPL)
837 gen_op_mov_reg_T0[ot][d]();
840 static void gen_opi(DisasContext *s1, int op, int ot, int d, int c)
842 gen_op_movl_T1_im(c);
843 gen_op(s1, op, ot, d, OR_TMP1);
846 static void gen_inc(DisasContext *s1, int ot, int d, int c)
849 gen_op_mov_TN_reg[ot][0][d]();
850 if (s1->cc_op != CC_OP_DYNAMIC)
851 gen_op_set_cc_op(s1->cc_op);
854 s1->cc_op = CC_OP_INCB + ot;
857 s1->cc_op = CC_OP_DECB + ot;
860 gen_op_mov_reg_T0[ot][d]();
863 static void gen_shift(DisasContext *s1, int op, int ot, int d, int s)
866 gen_op_mov_TN_reg[ot][0][d]();
868 gen_op_mov_TN_reg[ot][1][s]();
869 /* for zero counts, flags are not updated, so must do it dynamically */
870 if (s1->cc_op != CC_OP_DYNAMIC)
871 gen_op_set_cc_op(s1->cc_op);
873 gen_op_shift_T0_T1_cc[ot][op]();
876 gen_op_mov_reg_T0[ot][d]();
877 s1->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
880 static void gen_shifti(DisasContext *s1, int op, int ot, int d, int c)
882 /* currently not optimized */
883 gen_op_movl_T1_im(c);
884 gen_shift(s1, op, ot, d, OR_TMP1);
887 static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_ptr)
894 int mod, rm, code, override, must_add_seg;
896 override = s->override;
897 must_add_seg = s->addseg;
900 mod = (modrm >> 6) & 3;
912 code = ldub(s->pc++);
913 scale = (code >> 6) & 3;
914 index = (code >> 3) & 7;
929 disp = (int8_t)ldub(s->pc++);
939 gen_op_movl_A0_reg[base]();
941 gen_op_addl_A0_im(disp);
943 gen_op_movl_A0_im(disp);
945 if (havesib && (index != 4 || scale != 0)) {
946 gen_op_addl_A0_reg_sN[scale][index]();
950 if (base == R_EBP || base == R_ESP)
955 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
963 gen_op_movl_A0_im(disp);
964 rm = 0; /* avoid SS override */
971 disp = (int8_t)ldub(s->pc++);
981 gen_op_movl_A0_reg[R_EBX]();
982 gen_op_addl_A0_reg_sN[0][R_ESI]();
985 gen_op_movl_A0_reg[R_EBX]();
986 gen_op_addl_A0_reg_sN[0][R_EDI]();
989 gen_op_movl_A0_reg[R_EBP]();
990 gen_op_addl_A0_reg_sN[0][R_ESI]();
993 gen_op_movl_A0_reg[R_EBP]();
994 gen_op_addl_A0_reg_sN[0][R_EDI]();
997 gen_op_movl_A0_reg[R_ESI]();
1000 gen_op_movl_A0_reg[R_EDI]();
1003 gen_op_movl_A0_reg[R_EBP]();
1007 gen_op_movl_A0_reg[R_EBX]();
1011 gen_op_addl_A0_im(disp);
1012 gen_op_andl_A0_ffff();
1016 if (rm == 2 || rm == 3 || rm == 6)
1021 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
1031 /* generate modrm memory load or store of 'reg'. TMP0 is used if reg !=
1033 static void gen_ldst_modrm(DisasContext *s, int modrm, int ot, int reg, int is_store)
1035 int mod, rm, opreg, disp;
1037 mod = (modrm >> 6) & 3;
1042 gen_op_mov_TN_reg[ot][0][reg]();
1043 gen_op_mov_reg_T0[ot][rm]();
1045 gen_op_mov_TN_reg[ot][0][rm]();
1047 gen_op_mov_reg_T0[ot][reg]();
1050 gen_lea_modrm(s, modrm, &opreg, &disp);
1053 gen_op_mov_TN_reg[ot][0][reg]();
1054 gen_op_st_T0_A0[ot]();
1056 gen_op_ld_T0_A0[ot]();
1058 gen_op_mov_reg_T0[ot][reg]();
1063 static inline uint32_t insn_get(DisasContext *s, int ot)
1085 static inline void gen_jcc(DisasContext *s, int b, int val, int next_eip)
1087 TranslationBlock *tb;
1092 jcc_op = (b >> 1) & 7;
1094 /* we optimize the cmp/jcc case */
1098 func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1101 /* some jumps are easy to compute */
1128 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1131 func = gen_jcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1143 if (s->cc_op != CC_OP_DYNAMIC)
1144 gen_op_set_cc_op(s->cc_op);
1147 gen_setcc_slow[jcc_op]();
1153 func((long)tb, val, next_eip);
1155 func((long)tb, next_eip, val);
1160 static void gen_setcc(DisasContext *s, int b)
1166 jcc_op = (b >> 1) & 7;
1168 /* we optimize the cmp/jcc case */
1172 func = gen_setcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];
1177 /* some jumps are easy to compute */
1195 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1198 func = gen_setcc_sub[(s->cc_op - CC_OP_ADDB) % 3][jcc_op];
1206 if (s->cc_op != CC_OP_DYNAMIC)
1207 gen_op_set_cc_op(s->cc_op);
1208 func = gen_setcc_slow[jcc_op];
1217 /* move T0 to seg_reg and compute if the CPU state may change */
1218 static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip)
1221 gen_op_movl_seg_T0(seg_reg, cur_eip);
1223 gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]),
1224 offsetof(CPUX86State,seg_cache[seg_reg].base));
1225 if (!s->addseg && seg_reg < R_FS)
1226 s->is_jmp = 2; /* abort translation because the register may
1227 have a non zero base */
1230 /* generate a push. It depends on ss32, addseg and dflag */
1231 static void gen_push_T0(DisasContext *s)
1241 gen_op_pushl_ss32_T0();
1243 gen_op_pushw_ss32_T0();
1247 gen_op_pushl_ss16_T0();
1249 gen_op_pushw_ss16_T0();
1253 /* two step pop is necessary for precise exceptions */
1254 static void gen_pop_T0(DisasContext *s)
1264 gen_op_popl_ss32_T0();
1266 gen_op_popw_ss32_T0();
1270 gen_op_popl_ss16_T0();
1272 gen_op_popw_ss16_T0();
1276 static inline void gen_stack_update(DisasContext *s, int addend)
1280 gen_op_addl_ESP_2();
1281 else if (addend == 4)
1282 gen_op_addl_ESP_4();
1284 gen_op_addl_ESP_im(addend);
1287 gen_op_addw_ESP_2();
1288 else if (addend == 4)
1289 gen_op_addw_ESP_4();
1291 gen_op_addw_ESP_im(addend);
1295 static void gen_pop_update(DisasContext *s)
1297 gen_stack_update(s, 2 << s->dflag);
1300 static void gen_stack_A0(DisasContext *s)
1302 gen_op_movl_A0_ESP();
1304 gen_op_andl_A0_ffff();
1305 gen_op_movl_T1_A0();
1307 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
1310 /* NOTE: wrap around in 16 bit not fully handled */
1311 static void gen_pusha(DisasContext *s)
1314 gen_op_movl_A0_ESP();
1315 gen_op_addl_A0_im(-16 << s->dflag);
1317 gen_op_andl_A0_ffff();
1318 gen_op_movl_T1_A0();
1320 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
1321 for(i = 0;i < 8; i++) {
1322 gen_op_mov_TN_reg[OT_LONG][0][7 - i]();
1323 gen_op_st_T0_A0[OT_WORD + s->dflag]();
1324 gen_op_addl_A0_im(2 << s->dflag);
1326 gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1329 /* NOTE: wrap around in 16 bit not fully handled */
1330 static void gen_popa(DisasContext *s)
1333 gen_op_movl_A0_ESP();
1335 gen_op_andl_A0_ffff();
1336 gen_op_movl_T1_A0();
1337 gen_op_addl_T1_im(16 << s->dflag);
1339 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
1340 for(i = 0;i < 8; i++) {
1341 /* ESP is not reloaded */
1343 gen_op_ld_T0_A0[OT_WORD + s->dflag]();
1344 gen_op_mov_reg_T0[OT_WORD + s->dflag][7 - i]();
1346 gen_op_addl_A0_im(2 << s->dflag);
1348 gen_op_mov_reg_T1[OT_WORD + s->dflag][R_ESP]();
1351 /* NOTE: wrap around in 16 bit not fully handled */
1352 /* XXX: check this */
1353 static void gen_enter(DisasContext *s, int esp_addend, int level)
1355 int ot, level1, addend, opsize;
1357 ot = s->dflag + OT_WORD;
1360 opsize = 2 << s->dflag;
1362 gen_op_movl_A0_ESP();
1363 gen_op_addl_A0_im(-opsize);
1365 gen_op_andl_A0_ffff();
1366 gen_op_movl_T1_A0();
1368 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[R_SS].base));
1370 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1371 gen_op_st_T0_A0[ot]();
1374 gen_op_addl_A0_im(-opsize);
1375 gen_op_addl_T0_im(-opsize);
1376 gen_op_st_T0_A0[ot]();
1378 gen_op_addl_A0_im(-opsize);
1379 /* XXX: add st_T1_A0 ? */
1380 gen_op_movl_T0_T1();
1381 gen_op_st_T0_A0[ot]();
1383 gen_op_mov_reg_T1[ot][R_EBP]();
1384 addend = -esp_addend;
1386 addend -= opsize * (level1 + 1);
1387 gen_op_addl_T1_im(addend);
1388 gen_op_mov_reg_T1[ot][R_ESP]();
1391 static void gen_exception(DisasContext *s, int trapno, unsigned int cur_eip)
1393 if (s->cc_op != CC_OP_DYNAMIC)
1394 gen_op_set_cc_op(s->cc_op);
1395 gen_op_jmp_im(cur_eip);
1396 gen_op_raise_exception(trapno);
1400 /* an interrupt is different from an exception because of the
1401 priviledge checks */
1402 static void gen_interrupt(DisasContext *s, int intno,
1403 unsigned int cur_eip, unsigned int next_eip)
1405 if (s->cc_op != CC_OP_DYNAMIC)
1406 gen_op_set_cc_op(s->cc_op);
1407 gen_op_jmp_im(cur_eip);
1408 gen_op_raise_interrupt(intno, next_eip);
1412 /* generate a jump to eip. No segment change must happen before as a
1413 direct call to the next block may occur */
1414 static void gen_jmp(DisasContext *s, unsigned int eip)
1416 TranslationBlock *tb = s->tb;
1418 if (s->cc_op != CC_OP_DYNAMIC)
1419 gen_op_set_cc_op(s->cc_op);
1420 gen_op_jmp_tb_next((long)tb, eip);
1424 /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr
1425 is set to true if the instruction sets the PC (last instruction of
1427 long disas_insn(DisasContext *s, uint8_t *pc_start)
1429 int b, prefixes, aflag, dflag;
1431 int modrm, reg, rm, mod, reg_addr, op, opreg, offset_addr, val;
1432 unsigned int next_eip;
1442 /* check prefixes */
1445 prefixes |= PREFIX_REPZ;
1448 prefixes |= PREFIX_REPNZ;
1451 prefixes |= PREFIX_LOCK;
1472 prefixes |= PREFIX_DATA;
1475 prefixes |= PREFIX_ADR;
1479 if (prefixes & PREFIX_DATA)
1481 if (prefixes & PREFIX_ADR)
1484 s->prefix = prefixes;
1488 /* lock generation */
1489 if (prefixes & PREFIX_LOCK)
1492 /* now check op code */
1496 /**************************/
1497 /* extended op code */
1498 b = ldub(s->pc++) | 0x100;
1501 /**************************/
1519 ot = dflag ? OT_LONG : OT_WORD;
1522 case 0: /* OP Ev, Gv */
1523 modrm = ldub(s->pc++);
1524 reg = ((modrm >> 3) & 7) + OR_EAX;
1525 mod = (modrm >> 6) & 3;
1528 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1529 gen_op_ld_T0_A0[ot]();
1532 opreg = OR_EAX + rm;
1534 gen_op(s, op, ot, opreg, reg);
1535 if (mod != 3 && op != 7) {
1536 gen_op_st_T0_A0[ot]();
1539 case 1: /* OP Gv, Ev */
1540 modrm = ldub(s->pc++);
1541 mod = (modrm >> 6) & 3;
1542 reg = ((modrm >> 3) & 7) + OR_EAX;
1545 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1546 gen_op_ld_T1_A0[ot]();
1549 opreg = OR_EAX + rm;
1551 gen_op(s, op, ot, reg, opreg);
1553 case 2: /* OP A, Iv */
1554 val = insn_get(s, ot);
1555 gen_opi(s, op, ot, OR_EAX, val);
1561 case 0x80: /* GRP1 */
1570 ot = dflag ? OT_LONG : OT_WORD;
1572 modrm = ldub(s->pc++);
1573 mod = (modrm >> 6) & 3;
1575 op = (modrm >> 3) & 7;
1578 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1579 gen_op_ld_T0_A0[ot]();
1582 opreg = rm + OR_EAX;
1589 val = insn_get(s, ot);
1592 val = (int8_t)insn_get(s, OT_BYTE);
1596 gen_opi(s, op, ot, opreg, val);
1597 if (op != 7 && mod != 3) {
1598 gen_op_st_T0_A0[ot]();
1603 /**************************/
1604 /* inc, dec, and other misc arith */
1605 case 0x40 ... 0x47: /* inc Gv */
1606 ot = dflag ? OT_LONG : OT_WORD;
1607 gen_inc(s, ot, OR_EAX + (b & 7), 1);
1609 case 0x48 ... 0x4f: /* dec Gv */
1610 ot = dflag ? OT_LONG : OT_WORD;
1611 gen_inc(s, ot, OR_EAX + (b & 7), -1);
1613 case 0xf6: /* GRP3 */
1618 ot = dflag ? OT_LONG : OT_WORD;
1620 modrm = ldub(s->pc++);
1621 mod = (modrm >> 6) & 3;
1623 op = (modrm >> 3) & 7;
1625 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1626 gen_op_ld_T0_A0[ot]();
1628 gen_op_mov_TN_reg[ot][0][rm]();
1633 val = insn_get(s, ot);
1634 gen_op_movl_T1_im(val);
1635 gen_op_testl_T0_T1_cc();
1636 s->cc_op = CC_OP_LOGICB + ot;
1641 gen_op_st_T0_A0[ot]();
1643 gen_op_mov_reg_T0[ot][rm]();
1647 gen_op_negl_T0_cc();
1649 gen_op_st_T0_A0[ot]();
1651 gen_op_mov_reg_T0[ot][rm]();
1653 s->cc_op = CC_OP_SUBB + ot;
1658 gen_op_mulb_AL_T0();
1661 gen_op_mulw_AX_T0();
1665 gen_op_mull_EAX_T0();
1668 s->cc_op = CC_OP_MUL;
1673 gen_op_imulb_AL_T0();
1676 gen_op_imulw_AX_T0();
1680 gen_op_imull_EAX_T0();
1683 s->cc_op = CC_OP_MUL;
1688 gen_op_divb_AL_T0(pc_start - s->cs_base);
1691 gen_op_divw_AX_T0(pc_start - s->cs_base);
1695 gen_op_divl_EAX_T0(pc_start - s->cs_base);
1702 gen_op_idivb_AL_T0(pc_start - s->cs_base);
1705 gen_op_idivw_AX_T0(pc_start - s->cs_base);
1709 gen_op_idivl_EAX_T0(pc_start - s->cs_base);
1718 case 0xfe: /* GRP4 */
1719 case 0xff: /* GRP5 */
1723 ot = dflag ? OT_LONG : OT_WORD;
1725 modrm = ldub(s->pc++);
1726 mod = (modrm >> 6) & 3;
1728 op = (modrm >> 3) & 7;
1729 if (op >= 2 && b == 0xfe) {
1733 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1734 if (op != 3 && op != 5)
1735 gen_op_ld_T0_A0[ot]();
1737 gen_op_mov_TN_reg[ot][0][rm]();
1741 case 0: /* inc Ev */
1742 gen_inc(s, ot, OR_TMP0, 1);
1744 gen_op_st_T0_A0[ot]();
1746 gen_op_mov_reg_T0[ot][rm]();
1748 case 1: /* dec Ev */
1749 gen_inc(s, ot, OR_TMP0, -1);
1751 gen_op_st_T0_A0[ot]();
1753 gen_op_mov_reg_T0[ot][rm]();
1755 case 2: /* call Ev */
1756 /* XXX: optimize if memory (no and is necessary) */
1758 gen_op_andl_T0_ffff();
1760 next_eip = s->pc - s->cs_base;
1761 gen_op_movl_T0_im(next_eip);
1765 case 3: /* lcall Ev */
1766 /* push return segment + offset */
1767 gen_op_movl_T0_seg(R_CS);
1769 next_eip = s->pc - s->cs_base;
1770 gen_op_movl_T0_im(next_eip);
1773 gen_op_ld_T1_A0[ot]();
1774 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1775 gen_op_lduw_T0_A0();
1776 gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
1777 gen_op_movl_T0_T1();
1781 case 4: /* jmp Ev */
1783 gen_op_andl_T0_ffff();
1787 case 5: /* ljmp Ev */
1788 gen_op_ld_T1_A0[ot]();
1789 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1790 gen_op_lduw_T0_A0();
1791 gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
1792 gen_op_movl_T0_T1();
1796 case 6: /* push Ev */
1804 case 0x84: /* test Ev, Gv */
1809 ot = dflag ? OT_LONG : OT_WORD;
1811 modrm = ldub(s->pc++);
1812 mod = (modrm >> 6) & 3;
1814 reg = (modrm >> 3) & 7;
1816 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1817 gen_op_mov_TN_reg[ot][1][reg + OR_EAX]();
1818 gen_op_testl_T0_T1_cc();
1819 s->cc_op = CC_OP_LOGICB + ot;
1822 case 0xa8: /* test eAX, Iv */
1827 ot = dflag ? OT_LONG : OT_WORD;
1828 val = insn_get(s, ot);
1830 gen_op_mov_TN_reg[ot][0][OR_EAX]();
1831 gen_op_movl_T1_im(val);
1832 gen_op_testl_T0_T1_cc();
1833 s->cc_op = CC_OP_LOGICB + ot;
1836 case 0x98: /* CWDE/CBW */
1838 gen_op_movswl_EAX_AX();
1840 gen_op_movsbw_AX_AL();
1842 case 0x99: /* CDQ/CWD */
1844 gen_op_movslq_EDX_EAX();
1846 gen_op_movswl_DX_AX();
1848 case 0x1af: /* imul Gv, Ev */
1849 case 0x69: /* imul Gv, Ev, I */
1851 ot = dflag ? OT_LONG : OT_WORD;
1852 modrm = ldub(s->pc++);
1853 reg = ((modrm >> 3) & 7) + OR_EAX;
1854 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
1856 val = insn_get(s, ot);
1857 gen_op_movl_T1_im(val);
1858 } else if (b == 0x6b) {
1859 val = insn_get(s, OT_BYTE);
1860 gen_op_movl_T1_im(val);
1862 gen_op_mov_TN_reg[ot][1][reg]();
1865 if (ot == OT_LONG) {
1866 gen_op_imull_T0_T1();
1868 gen_op_imulw_T0_T1();
1870 gen_op_mov_reg_T0[ot][reg]();
1871 s->cc_op = CC_OP_MUL;
1874 case 0x1c1: /* xadd Ev, Gv */
1878 ot = dflag ? OT_LONG : OT_WORD;
1879 modrm = ldub(s->pc++);
1880 reg = (modrm >> 3) & 7;
1881 mod = (modrm >> 6) & 3;
1884 gen_op_mov_TN_reg[ot][0][reg]();
1885 gen_op_mov_TN_reg[ot][1][rm]();
1886 gen_op_addl_T0_T1_cc();
1887 gen_op_mov_reg_T0[ot][rm]();
1888 gen_op_mov_reg_T1[ot][reg]();
1890 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1891 gen_op_mov_TN_reg[ot][0][reg]();
1892 gen_op_ld_T1_A0[ot]();
1893 gen_op_addl_T0_T1_cc();
1894 gen_op_st_T0_A0[ot]();
1895 gen_op_mov_reg_T1[ot][reg]();
1897 s->cc_op = CC_OP_ADDB + ot;
1900 case 0x1b1: /* cmpxchg Ev, Gv */
1904 ot = dflag ? OT_LONG : OT_WORD;
1905 modrm = ldub(s->pc++);
1906 reg = (modrm >> 3) & 7;
1907 mod = (modrm >> 6) & 3;
1908 gen_op_mov_TN_reg[ot][1][reg]();
1911 gen_op_mov_TN_reg[ot][0][rm]();
1912 gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1913 gen_op_mov_reg_T0[ot][rm]();
1915 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1916 gen_op_ld_T0_A0[ot]();
1917 gen_op_cmpxchg_T0_T1_EAX_cc[ot]();
1918 gen_op_st_T0_A0[ot]();
1920 s->cc_op = CC_OP_SUBB + ot;
1922 case 0x1c7: /* cmpxchg8b */
1923 modrm = ldub(s->pc++);
1924 mod = (modrm >> 6) & 3;
1927 if (s->cc_op != CC_OP_DYNAMIC)
1928 gen_op_set_cc_op(s->cc_op);
1929 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
1931 s->cc_op = CC_OP_EFLAGS;
1934 /**************************/
1936 case 0x50 ... 0x57: /* push */
1937 gen_op_mov_TN_reg[OT_LONG][0][b & 7]();
1940 case 0x58 ... 0x5f: /* pop */
1941 ot = dflag ? OT_LONG : OT_WORD;
1943 gen_op_mov_reg_T0[ot][b & 7]();
1946 case 0x60: /* pusha */
1949 case 0x61: /* popa */
1952 case 0x68: /* push Iv */
1954 ot = dflag ? OT_LONG : OT_WORD;
1956 val = insn_get(s, ot);
1958 val = (int8_t)insn_get(s, OT_BYTE);
1959 gen_op_movl_T0_im(val);
1962 case 0x8f: /* pop Ev */
1963 ot = dflag ? OT_LONG : OT_WORD;
1964 modrm = ldub(s->pc++);
1966 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
1969 case 0xc8: /* enter */
1974 level = ldub(s->pc++);
1975 gen_enter(s, val, level);
1978 case 0xc9: /* leave */
1979 /* XXX: exception not precise (ESP is updated before potential exception) */
1981 gen_op_mov_TN_reg[OT_LONG][0][R_EBP]();
1982 gen_op_mov_reg_T0[OT_LONG][R_ESP]();
1984 gen_op_mov_TN_reg[OT_WORD][0][R_EBP]();
1985 gen_op_mov_reg_T0[OT_WORD][R_ESP]();
1988 ot = dflag ? OT_LONG : OT_WORD;
1989 gen_op_mov_reg_T0[ot][R_EBP]();
1992 case 0x06: /* push es */
1993 case 0x0e: /* push cs */
1994 case 0x16: /* push ss */
1995 case 0x1e: /* push ds */
1996 gen_op_movl_T0_seg(b >> 3);
1999 case 0x1a0: /* push fs */
2000 case 0x1a8: /* push gs */
2001 gen_op_movl_T0_seg((b >> 3) & 7);
2004 case 0x07: /* pop es */
2005 case 0x17: /* pop ss */
2006 case 0x1f: /* pop ds */
2008 gen_movl_seg_T0(s, b >> 3, pc_start - s->cs_base);
2011 case 0x1a1: /* pop fs */
2012 case 0x1a9: /* pop gs */
2014 gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
2018 /**************************/
2021 case 0x89: /* mov Gv, Ev */
2025 ot = dflag ? OT_LONG : OT_WORD;
2026 modrm = ldub(s->pc++);
2027 reg = (modrm >> 3) & 7;
2029 /* generate a generic store */
2030 gen_ldst_modrm(s, modrm, ot, OR_EAX + reg, 1);
2033 case 0xc7: /* mov Ev, Iv */
2037 ot = dflag ? OT_LONG : OT_WORD;
2038 modrm = ldub(s->pc++);
2039 mod = (modrm >> 6) & 3;
2041 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2042 val = insn_get(s, ot);
2043 gen_op_movl_T0_im(val);
2045 gen_op_st_T0_A0[ot]();
2047 gen_op_mov_reg_T0[ot][modrm & 7]();
2050 case 0x8b: /* mov Ev, Gv */
2054 ot = dflag ? OT_LONG : OT_WORD;
2055 modrm = ldub(s->pc++);
2056 reg = (modrm >> 3) & 7;
2058 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2059 gen_op_mov_reg_T0[ot][reg]();
2061 case 0x8e: /* mov seg, Gv */
2062 ot = dflag ? OT_LONG : OT_WORD;
2063 modrm = ldub(s->pc++);
2064 reg = (modrm >> 3) & 7;
2065 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2066 if (reg >= 6 || reg == R_CS)
2068 gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
2070 case 0x8c: /* mov Gv, seg */
2071 ot = dflag ? OT_LONG : OT_WORD;
2072 modrm = ldub(s->pc++);
2073 reg = (modrm >> 3) & 7;
2076 gen_op_movl_T0_seg(reg);
2077 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
2080 case 0x1b6: /* movzbS Gv, Eb */
2081 case 0x1b7: /* movzwS Gv, Eb */
2082 case 0x1be: /* movsbS Gv, Eb */
2083 case 0x1bf: /* movswS Gv, Eb */
2086 /* d_ot is the size of destination */
2087 d_ot = dflag + OT_WORD;
2088 /* ot is the size of source */
2089 ot = (b & 1) + OT_BYTE;
2090 modrm = ldub(s->pc++);
2091 reg = ((modrm >> 3) & 7) + OR_EAX;
2092 mod = (modrm >> 6) & 3;
2096 gen_op_mov_TN_reg[ot][0][rm]();
2097 switch(ot | (b & 8)) {
2099 gen_op_movzbl_T0_T0();
2102 gen_op_movsbl_T0_T0();
2105 gen_op_movzwl_T0_T0();
2109 gen_op_movswl_T0_T0();
2112 gen_op_mov_reg_T0[d_ot][reg]();
2114 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2116 gen_op_lds_T0_A0[ot]();
2118 gen_op_ldu_T0_A0[ot]();
2120 gen_op_mov_reg_T0[d_ot][reg]();
2125 case 0x8d: /* lea */
2126 ot = dflag ? OT_LONG : OT_WORD;
2127 modrm = ldub(s->pc++);
2128 reg = (modrm >> 3) & 7;
2129 /* we must ensure that no segment is added */
2133 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2135 gen_op_mov_reg_A0[ot - OT_WORD][reg]();
2138 case 0xa0: /* mov EAX, Ov */
2140 case 0xa2: /* mov Ov, EAX */
2145 ot = dflag ? OT_LONG : OT_WORD;
2147 offset_addr = insn_get(s, OT_LONG);
2149 offset_addr = insn_get(s, OT_WORD);
2150 gen_op_movl_A0_im(offset_addr);
2151 /* handle override */
2153 int override, must_add_seg;
2154 must_add_seg = s->addseg;
2155 if (s->override >= 0) {
2156 override = s->override;
2162 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
2166 gen_op_ld_T0_A0[ot]();
2167 gen_op_mov_reg_T0[ot][R_EAX]();
2169 gen_op_mov_TN_reg[ot][0][R_EAX]();
2170 gen_op_st_T0_A0[ot]();
2173 case 0xd7: /* xlat */
2174 gen_op_movl_A0_reg[R_EBX]();
2175 gen_op_addl_A0_AL();
2177 gen_op_andl_A0_ffff();
2178 /* handle override */
2180 int override, must_add_seg;
2181 must_add_seg = s->addseg;
2183 if (s->override >= 0) {
2184 override = s->override;
2190 gen_op_addl_A0_seg(offsetof(CPUX86State,seg_cache[override].base));
2193 gen_op_ldub_T0_A0();
2194 gen_op_mov_reg_T0[OT_BYTE][R_EAX]();
2196 case 0xb0 ... 0xb7: /* mov R, Ib */
2197 val = insn_get(s, OT_BYTE);
2198 gen_op_movl_T0_im(val);
2199 gen_op_mov_reg_T0[OT_BYTE][b & 7]();
2201 case 0xb8 ... 0xbf: /* mov R, Iv */
2202 ot = dflag ? OT_LONG : OT_WORD;
2203 val = insn_get(s, ot);
2204 reg = OR_EAX + (b & 7);
2205 gen_op_movl_T0_im(val);
2206 gen_op_mov_reg_T0[ot][reg]();
2209 case 0x91 ... 0x97: /* xchg R, EAX */
2210 ot = dflag ? OT_LONG : OT_WORD;
2215 case 0x87: /* xchg Ev, Gv */
2219 ot = dflag ? OT_LONG : OT_WORD;
2220 modrm = ldub(s->pc++);
2221 reg = (modrm >> 3) & 7;
2222 mod = (modrm >> 6) & 3;
2226 gen_op_mov_TN_reg[ot][0][reg]();
2227 gen_op_mov_TN_reg[ot][1][rm]();
2228 gen_op_mov_reg_T0[ot][rm]();
2229 gen_op_mov_reg_T1[ot][reg]();
2231 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2232 gen_op_mov_TN_reg[ot][0][reg]();
2233 /* for xchg, lock is implicit */
2234 if (!(prefixes & PREFIX_LOCK))
2236 gen_op_ld_T1_A0[ot]();
2237 gen_op_st_T0_A0[ot]();
2238 if (!(prefixes & PREFIX_LOCK))
2240 gen_op_mov_reg_T1[ot][reg]();
2243 case 0xc4: /* les Gv */
2246 case 0xc5: /* lds Gv */
2249 case 0x1b2: /* lss Gv */
2252 case 0x1b4: /* lfs Gv */
2255 case 0x1b5: /* lgs Gv */
2258 ot = dflag ? OT_LONG : OT_WORD;
2259 modrm = ldub(s->pc++);
2260 reg = (modrm >> 3) & 7;
2261 mod = (modrm >> 6) & 3;
2264 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2265 gen_op_ld_T1_A0[ot]();
2266 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2267 /* load the segment first to handle exceptions properly */
2268 gen_op_lduw_T0_A0();
2269 gen_movl_seg_T0(s, op, pc_start - s->cs_base);
2270 /* then put the data */
2271 gen_op_mov_reg_T1[ot][reg]();
2274 /************************/
2285 ot = dflag ? OT_LONG : OT_WORD;
2287 modrm = ldub(s->pc++);
2288 mod = (modrm >> 6) & 3;
2290 op = (modrm >> 3) & 7;
2293 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2294 gen_op_ld_T0_A0[ot]();
2297 opreg = rm + OR_EAX;
2302 gen_shift(s, op, ot, opreg, OR_ECX);
2305 shift = ldub(s->pc++);
2307 gen_shifti(s, op, ot, opreg, shift);
2311 gen_op_st_T0_A0[ot]();
2326 case 0x1a4: /* shld imm */
2330 case 0x1a5: /* shld cl */
2334 case 0x1ac: /* shrd imm */
2338 case 0x1ad: /* shrd cl */
2342 ot = dflag ? OT_LONG : OT_WORD;
2343 modrm = ldub(s->pc++);
2344 mod = (modrm >> 6) & 3;
2346 reg = (modrm >> 3) & 7;
2349 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2350 gen_op_ld_T0_A0[ot]();
2352 gen_op_mov_TN_reg[ot][0][rm]();
2354 gen_op_mov_TN_reg[ot][1][reg]();
2357 val = ldub(s->pc++);
2360 gen_op_shiftd_T0_T1_im_cc[ot - OT_WORD][op](val);
2361 if (op == 0 && ot != OT_WORD)
2362 s->cc_op = CC_OP_SHLB + ot;
2364 s->cc_op = CC_OP_SARB + ot;
2367 if (s->cc_op != CC_OP_DYNAMIC)
2368 gen_op_set_cc_op(s->cc_op);
2369 gen_op_shiftd_T0_T1_ECX_cc[ot - OT_WORD][op]();
2370 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2373 gen_op_st_T0_A0[ot]();
2375 gen_op_mov_reg_T0[ot][rm]();
2379 /************************/
2382 modrm = ldub(s->pc++);
2383 mod = (modrm >> 6) & 3;
2385 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
2389 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
2391 case 0x00 ... 0x07: /* fxxxs */
2392 case 0x10 ... 0x17: /* fixxxl */
2393 case 0x20 ... 0x27: /* fxxxl */
2394 case 0x30 ... 0x37: /* fixxx */
2401 gen_op_flds_FT0_A0();
2404 gen_op_fildl_FT0_A0();
2407 gen_op_fldl_FT0_A0();
2411 gen_op_fild_FT0_A0();
2415 gen_op_fp_arith_ST0_FT0[op1]();
2417 /* fcomp needs pop */
2422 case 0x08: /* flds */
2423 case 0x0a: /* fsts */
2424 case 0x0b: /* fstps */
2425 case 0x18: /* fildl */
2426 case 0x1a: /* fistl */
2427 case 0x1b: /* fistpl */
2428 case 0x28: /* fldl */
2429 case 0x2a: /* fstl */
2430 case 0x2b: /* fstpl */
2431 case 0x38: /* filds */
2432 case 0x3a: /* fists */
2433 case 0x3b: /* fistps */
2440 gen_op_flds_ST0_A0();
2443 gen_op_fildl_ST0_A0();
2446 gen_op_fldl_ST0_A0();
2450 gen_op_fild_ST0_A0();
2457 gen_op_fsts_ST0_A0();
2460 gen_op_fistl_ST0_A0();
2463 gen_op_fstl_ST0_A0();
2467 gen_op_fist_ST0_A0();
2475 case 0x0c: /* fldenv mem */
2476 gen_op_fldenv_A0(s->dflag);
2478 case 0x0d: /* fldcw mem */
2481 case 0x0e: /* fnstenv mem */
2482 gen_op_fnstenv_A0(s->dflag);
2484 case 0x0f: /* fnstcw mem */
2487 case 0x1d: /* fldt mem */
2489 gen_op_fldt_ST0_A0();
2491 case 0x1f: /* fstpt mem */
2492 gen_op_fstt_ST0_A0();
2495 case 0x2c: /* frstor mem */
2496 gen_op_frstor_A0(s->dflag);
2498 case 0x2e: /* fnsave mem */
2499 gen_op_fnsave_A0(s->dflag);
2501 case 0x2f: /* fnstsw mem */
2504 case 0x3c: /* fbld */
2506 gen_op_fbld_ST0_A0();
2508 case 0x3e: /* fbstp */
2509 gen_op_fbst_ST0_A0();
2512 case 0x3d: /* fildll */
2514 gen_op_fildll_ST0_A0();
2516 case 0x3f: /* fistpll */
2517 gen_op_fistll_ST0_A0();
2524 /* register float ops */
2528 case 0x08: /* fld sti */
2530 gen_op_fmov_ST0_STN((opreg + 1) & 7);
2532 case 0x09: /* fxchg sti */
2533 gen_op_fxchg_ST0_STN(opreg);
2535 case 0x0a: /* grp d9/2 */
2543 case 0x0c: /* grp d9/4 */
2553 gen_op_fcom_ST0_FT0();
2562 case 0x0d: /* grp d9/5 */
2571 gen_op_fldl2t_ST0();
2575 gen_op_fldl2e_ST0();
2583 gen_op_fldlg2_ST0();
2587 gen_op_fldln2_ST0();
2598 case 0x0e: /* grp d9/6 */
2609 case 3: /* fpatan */
2612 case 4: /* fxtract */
2615 case 5: /* fprem1 */
2618 case 6: /* fdecstp */
2622 case 7: /* fincstp */
2627 case 0x0f: /* grp d9/7 */
2632 case 1: /* fyl2xp1 */
2638 case 3: /* fsincos */
2641 case 5: /* fscale */
2644 case 4: /* frndint */
2656 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
2657 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
2658 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
2664 gen_op_fp_arith_STN_ST0[op1](opreg);
2668 gen_op_fmov_FT0_STN(opreg);
2669 gen_op_fp_arith_ST0_FT0[op1]();
2673 case 0x02: /* fcom */
2674 gen_op_fmov_FT0_STN(opreg);
2675 gen_op_fcom_ST0_FT0();
2677 case 0x03: /* fcomp */
2678 gen_op_fmov_FT0_STN(opreg);
2679 gen_op_fcom_ST0_FT0();
2682 case 0x15: /* da/5 */
2684 case 1: /* fucompp */
2685 gen_op_fmov_FT0_STN(1);
2686 gen_op_fucom_ST0_FT0();
2699 case 3: /* fninit */
2706 case 0x1d: /* fucomi */
2707 if (s->cc_op != CC_OP_DYNAMIC)
2708 gen_op_set_cc_op(s->cc_op);
2709 gen_op_fmov_FT0_STN(opreg);
2710 gen_op_fucomi_ST0_FT0();
2711 s->cc_op = CC_OP_EFLAGS;
2713 case 0x1e: /* fcomi */
2714 if (s->cc_op != CC_OP_DYNAMIC)
2715 gen_op_set_cc_op(s->cc_op);
2716 gen_op_fmov_FT0_STN(opreg);
2717 gen_op_fcomi_ST0_FT0();
2718 s->cc_op = CC_OP_EFLAGS;
2720 case 0x2a: /* fst sti */
2721 gen_op_fmov_STN_ST0(opreg);
2723 case 0x2b: /* fstp sti */
2724 gen_op_fmov_STN_ST0(opreg);
2727 case 0x2c: /* fucom st(i) */
2728 gen_op_fmov_FT0_STN(opreg);
2729 gen_op_fucom_ST0_FT0();
2731 case 0x2d: /* fucomp st(i) */
2732 gen_op_fmov_FT0_STN(opreg);
2733 gen_op_fucom_ST0_FT0();
2736 case 0x33: /* de/3 */
2738 case 1: /* fcompp */
2739 gen_op_fmov_FT0_STN(1);
2740 gen_op_fcom_ST0_FT0();
2748 case 0x3c: /* df/4 */
2751 gen_op_fnstsw_EAX();
2757 case 0x3d: /* fucomip */
2758 if (s->cc_op != CC_OP_DYNAMIC)
2759 gen_op_set_cc_op(s->cc_op);
2760 gen_op_fmov_FT0_STN(opreg);
2761 gen_op_fucomi_ST0_FT0();
2763 s->cc_op = CC_OP_EFLAGS;
2765 case 0x3e: /* fcomip */
2766 if (s->cc_op != CC_OP_DYNAMIC)
2767 gen_op_set_cc_op(s->cc_op);
2768 gen_op_fmov_FT0_STN(opreg);
2769 gen_op_fcomi_ST0_FT0();
2771 s->cc_op = CC_OP_EFLAGS;
2778 /************************/
2781 case 0xa4: /* movsS */
2786 ot = dflag ? OT_LONG : OT_WORD;
2788 if (prefixes & PREFIX_REPZ) {
2789 gen_string_ds(s, ot, gen_op_movs + 9);
2791 gen_string_ds(s, ot, gen_op_movs);
2795 case 0xaa: /* stosS */
2800 ot = dflag ? OT_LONG : OT_WORD;
2802 if (prefixes & PREFIX_REPZ) {
2803 gen_string_es(s, ot, gen_op_stos + 9);
2805 gen_string_es(s, ot, gen_op_stos);
2808 case 0xac: /* lodsS */
2813 ot = dflag ? OT_LONG : OT_WORD;
2814 if (prefixes & PREFIX_REPZ) {
2815 gen_string_ds(s, ot, gen_op_lods + 9);
2817 gen_string_ds(s, ot, gen_op_lods);
2820 case 0xae: /* scasS */
2825 ot = dflag ? OT_LONG : OT_WORD;
2826 if (prefixes & PREFIX_REPNZ) {
2827 if (s->cc_op != CC_OP_DYNAMIC)
2828 gen_op_set_cc_op(s->cc_op);
2829 gen_string_es(s, ot, gen_op_scas + 9 * 2);
2830 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2831 } else if (prefixes & PREFIX_REPZ) {
2832 if (s->cc_op != CC_OP_DYNAMIC)
2833 gen_op_set_cc_op(s->cc_op);
2834 gen_string_es(s, ot, gen_op_scas + 9);
2835 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2837 gen_string_es(s, ot, gen_op_scas);
2838 s->cc_op = CC_OP_SUBB + ot;
2842 case 0xa6: /* cmpsS */
2847 ot = dflag ? OT_LONG : OT_WORD;
2848 if (prefixes & PREFIX_REPNZ) {
2849 if (s->cc_op != CC_OP_DYNAMIC)
2850 gen_op_set_cc_op(s->cc_op);
2851 gen_string_ds(s, ot, gen_op_cmps + 9 * 2);
2852 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2853 } else if (prefixes & PREFIX_REPZ) {
2854 if (s->cc_op != CC_OP_DYNAMIC)
2855 gen_op_set_cc_op(s->cc_op);
2856 gen_string_ds(s, ot, gen_op_cmps + 9);
2857 s->cc_op = CC_OP_DYNAMIC; /* cannot predict flags after */
2859 gen_string_ds(s, ot, gen_op_cmps);
2860 s->cc_op = CC_OP_SUBB + ot;
2863 case 0x6c: /* insS */
2865 if (s->cpl > s->iopl || s->vm86) {
2866 /* NOTE: even for (E)CX = 0 the exception is raised */
2867 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2872 ot = dflag ? OT_LONG : OT_WORD;
2873 if (prefixes & PREFIX_REPZ) {
2874 gen_string_es(s, ot, gen_op_ins + 9);
2876 gen_string_es(s, ot, gen_op_ins);
2880 case 0x6e: /* outsS */
2882 if (s->cpl > s->iopl || s->vm86) {
2883 /* NOTE: even for (E)CX = 0 the exception is raised */
2884 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2889 ot = dflag ? OT_LONG : OT_WORD;
2890 if (prefixes & PREFIX_REPZ) {
2891 gen_string_ds(s, ot, gen_op_outs + 9);
2893 gen_string_ds(s, ot, gen_op_outs);
2898 /************************/
2902 if (s->cpl > s->iopl || s->vm86) {
2903 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2908 ot = dflag ? OT_LONG : OT_WORD;
2909 val = ldub(s->pc++);
2910 gen_op_movl_T0_im(val);
2912 gen_op_mov_reg_T1[ot][R_EAX]();
2917 if (s->cpl > s->iopl || s->vm86) {
2918 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2923 ot = dflag ? OT_LONG : OT_WORD;
2924 val = ldub(s->pc++);
2925 gen_op_movl_T0_im(val);
2926 gen_op_mov_TN_reg[ot][1][R_EAX]();
2932 if (s->cpl > s->iopl || s->vm86) {
2933 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2938 ot = dflag ? OT_LONG : OT_WORD;
2939 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2941 gen_op_mov_reg_T1[ot][R_EAX]();
2946 if (s->cpl > s->iopl || s->vm86) {
2947 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
2952 ot = dflag ? OT_LONG : OT_WORD;
2953 gen_op_mov_TN_reg[OT_WORD][0][R_EDX]();
2954 gen_op_mov_TN_reg[ot][1][R_EAX]();
2959 /************************/
2961 case 0xc2: /* ret im */
2965 gen_stack_update(s, val + (2 << s->dflag));
2967 gen_op_andl_T0_ffff();
2971 case 0xc3: /* ret */
2975 gen_op_andl_T0_ffff();
2979 case 0xca: /* lret im */
2985 gen_op_ld_T0_A0[1 + s->dflag]();
2987 gen_op_andl_T0_ffff();
2988 /* NOTE: keeping EIP updated is not a problem in case of
2992 gen_op_addl_A0_im(2 << s->dflag);
2993 gen_op_ld_T0_A0[1 + s->dflag]();
2994 gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
2995 /* add stack offset */
2996 gen_stack_update(s, val + (4 << s->dflag));
2999 case 0xcb: /* lret */
3002 case 0xcf: /* iret */
3003 if (s->vm86 && s->iopl != 3) {
3004 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3006 /* XXX: not restartable */
3009 gen_op_ld_T0_A0[1 + s->dflag]();
3011 gen_op_andl_T0_ffff();
3012 /* NOTE: keeping EIP updated is not a problem in case of
3016 gen_op_addl_A0_im(2 << s->dflag);
3017 gen_op_ld_T0_A0[1 + s->dflag]();
3019 gen_op_addl_A0_im(2 << s->dflag);
3020 gen_op_ld_T1_A0[1 + s->dflag]();
3021 gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
3022 gen_op_movl_T0_T1();
3024 gen_op_movl_eflags_T0();
3026 gen_op_movw_eflags_T0();
3028 gen_stack_update(s, (6 << s->dflag));
3029 s->cc_op = CC_OP_EFLAGS;
3033 case 0xe8: /* call im */
3035 unsigned int next_eip;
3036 ot = dflag ? OT_LONG : OT_WORD;
3037 val = insn_get(s, ot);
3038 next_eip = s->pc - s->cs_base;
3042 gen_op_movl_T0_im(next_eip);
3047 case 0x9a: /* lcall im */
3049 unsigned int selector, offset;
3050 /* XXX: not restartable */
3052 ot = dflag ? OT_LONG : OT_WORD;
3053 offset = insn_get(s, ot);
3054 selector = insn_get(s, OT_WORD);
3056 /* push return segment + offset */
3057 gen_op_movl_T0_seg(R_CS);
3059 next_eip = s->pc - s->cs_base;
3060 gen_op_movl_T0_im(next_eip);
3063 /* change cs and pc */
3064 gen_op_movl_T0_im(selector);
3065 gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
3066 gen_op_jmp_im((unsigned long)offset);
3070 case 0xe9: /* jmp */
3071 ot = dflag ? OT_LONG : OT_WORD;
3072 val = insn_get(s, ot);
3073 val += s->pc - s->cs_base;
3078 case 0xea: /* ljmp im */
3080 unsigned int selector, offset;
3082 ot = dflag ? OT_LONG : OT_WORD;
3083 offset = insn_get(s, ot);
3084 selector = insn_get(s, OT_WORD);
3086 /* change cs and pc */
3087 gen_op_movl_T0_im(selector);
3088 gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
3089 gen_op_jmp_im((unsigned long)offset);
3093 case 0xeb: /* jmp Jb */
3094 val = (int8_t)insn_get(s, OT_BYTE);
3095 val += s->pc - s->cs_base;
3100 case 0x70 ... 0x7f: /* jcc Jb */
3101 val = (int8_t)insn_get(s, OT_BYTE);
3103 case 0x180 ... 0x18f: /* jcc Jv */
3105 val = insn_get(s, OT_LONG);
3107 val = (int16_t)insn_get(s, OT_WORD);
3110 next_eip = s->pc - s->cs_base;
3114 gen_jcc(s, b, val, next_eip);
3117 case 0x190 ... 0x19f: /* setcc Gv */
3118 modrm = ldub(s->pc++);
3120 gen_ldst_modrm(s, modrm, OT_BYTE, OR_TMP0, 1);
3122 case 0x140 ... 0x14f: /* cmov Gv, Ev */
3123 ot = dflag ? OT_LONG : OT_WORD;
3124 modrm = ldub(s->pc++);
3125 reg = (modrm >> 3) & 7;
3126 mod = (modrm >> 6) & 3;
3129 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3130 gen_op_ld_T1_A0[ot]();
3133 gen_op_mov_TN_reg[ot][1][rm]();
3135 gen_op_cmov_reg_T1_T0[ot - OT_WORD][reg]();
3138 /************************/
3140 case 0x9c: /* pushf */
3141 if (s->vm86 && s->iopl != 3) {
3142 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3144 if (s->cc_op != CC_OP_DYNAMIC)
3145 gen_op_set_cc_op(s->cc_op);
3146 gen_op_movl_T0_eflags();
3150 case 0x9d: /* popf */
3151 if (s->vm86 && s->iopl != 3) {
3152 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3156 gen_op_movl_eflags_T0();
3158 gen_op_movw_eflags_T0();
3161 s->cc_op = CC_OP_EFLAGS;
3162 s->is_jmp = 2; /* abort translation because TF flag may change */
3165 case 0x9e: /* sahf */
3166 gen_op_mov_TN_reg[OT_BYTE][0][R_AH]();
3167 if (s->cc_op != CC_OP_DYNAMIC)
3168 gen_op_set_cc_op(s->cc_op);
3169 gen_op_movb_eflags_T0();
3170 s->cc_op = CC_OP_EFLAGS;
3172 case 0x9f: /* lahf */
3173 if (s->cc_op != CC_OP_DYNAMIC)
3174 gen_op_set_cc_op(s->cc_op);
3175 gen_op_movl_T0_eflags();
3176 gen_op_mov_reg_T0[OT_BYTE][R_AH]();
3178 case 0xf5: /* cmc */
3179 if (s->cc_op != CC_OP_DYNAMIC)
3180 gen_op_set_cc_op(s->cc_op);
3182 s->cc_op = CC_OP_EFLAGS;
3184 case 0xf8: /* clc */
3185 if (s->cc_op != CC_OP_DYNAMIC)
3186 gen_op_set_cc_op(s->cc_op);
3188 s->cc_op = CC_OP_EFLAGS;
3190 case 0xf9: /* stc */
3191 if (s->cc_op != CC_OP_DYNAMIC)
3192 gen_op_set_cc_op(s->cc_op);
3194 s->cc_op = CC_OP_EFLAGS;
3196 case 0xfc: /* cld */
3199 case 0xfd: /* std */
3203 /************************/
3204 /* bit operations */
3205 case 0x1ba: /* bt/bts/btr/btc Gv, im */
3206 ot = dflag ? OT_LONG : OT_WORD;
3207 modrm = ldub(s->pc++);
3208 op = (modrm >> 3) & 7;
3209 mod = (modrm >> 6) & 3;
3212 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3213 gen_op_ld_T0_A0[ot]();
3215 gen_op_mov_TN_reg[ot][0][rm]();
3218 val = ldub(s->pc++);
3219 gen_op_movl_T1_im(val);
3223 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3224 s->cc_op = CC_OP_SARB + ot;
3227 gen_op_st_T0_A0[ot]();
3229 gen_op_mov_reg_T0[ot][rm]();
3232 case 0x1a3: /* bt Gv, Ev */
3235 case 0x1ab: /* bts */
3238 case 0x1b3: /* btr */
3241 case 0x1bb: /* btc */
3244 ot = dflag ? OT_LONG : OT_WORD;
3245 modrm = ldub(s->pc++);
3246 reg = (modrm >> 3) & 7;
3247 mod = (modrm >> 6) & 3;
3249 gen_op_mov_TN_reg[OT_LONG][1][reg]();
3251 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3252 /* specific case: we need to add a displacement */
3254 gen_op_add_bitw_A0_T1();
3256 gen_op_add_bitl_A0_T1();
3257 gen_op_ld_T0_A0[ot]();
3259 gen_op_mov_TN_reg[ot][0][rm]();
3261 gen_op_btx_T0_T1_cc[ot - OT_WORD][op]();
3262 s->cc_op = CC_OP_SARB + ot;
3265 gen_op_st_T0_A0[ot]();
3267 gen_op_mov_reg_T0[ot][rm]();
3270 case 0x1bc: /* bsf */
3271 case 0x1bd: /* bsr */
3272 ot = dflag ? OT_LONG : OT_WORD;
3273 modrm = ldub(s->pc++);
3274 reg = (modrm >> 3) & 7;
3275 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3276 gen_op_bsx_T0_cc[ot - OT_WORD][b & 1]();
3277 /* NOTE: we always write back the result. Intel doc says it is
3278 undefined if T0 == 0 */
3279 gen_op_mov_reg_T0[ot][reg]();
3280 s->cc_op = CC_OP_LOGICB + ot;
3282 /************************/
3284 case 0x27: /* daa */
3285 if (s->cc_op != CC_OP_DYNAMIC)
3286 gen_op_set_cc_op(s->cc_op);
3288 s->cc_op = CC_OP_EFLAGS;
3290 case 0x2f: /* das */
3291 if (s->cc_op != CC_OP_DYNAMIC)
3292 gen_op_set_cc_op(s->cc_op);
3294 s->cc_op = CC_OP_EFLAGS;
3296 case 0x37: /* aaa */
3297 if (s->cc_op != CC_OP_DYNAMIC)
3298 gen_op_set_cc_op(s->cc_op);
3300 s->cc_op = CC_OP_EFLAGS;
3302 case 0x3f: /* aas */
3303 if (s->cc_op != CC_OP_DYNAMIC)
3304 gen_op_set_cc_op(s->cc_op);
3306 s->cc_op = CC_OP_EFLAGS;
3308 case 0xd4: /* aam */
3309 val = ldub(s->pc++);
3311 s->cc_op = CC_OP_LOGICB;
3313 case 0xd5: /* aad */
3314 val = ldub(s->pc++);
3316 s->cc_op = CC_OP_LOGICB;
3318 /************************/
3320 case 0x90: /* nop */
3322 case 0x9b: /* fwait */
3324 case 0xcc: /* int3 */
3325 gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
3327 case 0xcd: /* int N */
3328 val = ldub(s->pc++);
3329 /* XXX: add error code for vm86 GPF */
3331 gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
3333 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3335 case 0xce: /* into */
3336 if (s->cc_op != CC_OP_DYNAMIC)
3337 gen_op_set_cc_op(s->cc_op);
3338 gen_op_into(s->pc - s->cs_base);
3340 case 0xfa: /* cli */
3342 if (s->cpl <= s->iopl) {
3345 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3351 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3355 case 0xfb: /* sti */
3357 if (s->cpl <= s->iopl) {
3360 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3366 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3370 case 0x62: /* bound */
3371 ot = dflag ? OT_LONG : OT_WORD;
3372 modrm = ldub(s->pc++);
3373 reg = (modrm >> 3) & 7;
3374 mod = (modrm >> 6) & 3;
3377 gen_op_mov_reg_T0[ot][reg]();
3378 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
3380 gen_op_boundw(pc_start - s->cs_base);
3382 gen_op_boundl(pc_start - s->cs_base);
3384 case 0x1c8 ... 0x1cf: /* bswap reg */
3386 gen_op_mov_TN_reg[OT_LONG][0][reg]();
3388 gen_op_mov_reg_T0[OT_LONG][reg]();
3390 case 0xd6: /* salc */
3391 if (s->cc_op != CC_OP_DYNAMIC)
3392 gen_op_set_cc_op(s->cc_op);
3395 case 0xe0: /* loopnz */
3396 case 0xe1: /* loopz */
3397 if (s->cc_op != CC_OP_DYNAMIC)
3398 gen_op_set_cc_op(s->cc_op);
3400 case 0xe2: /* loop */
3401 case 0xe3: /* jecxz */
3402 val = (int8_t)insn_get(s, OT_BYTE);
3403 next_eip = s->pc - s->cs_base;
3407 gen_op_loop[s->aflag][b & 3](val, next_eip);
3410 case 0x131: /* rdtsc */
3413 case 0x1a2: /* cpuid */
3416 case 0xf4: /* hlt */
3417 /* XXX: if cpl == 0, then should do something else */
3418 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3420 case 0x102: /* lar */
3421 case 0x103: /* lsl */
3424 ot = dflag ? OT_LONG : OT_WORD;
3425 modrm = ldub(s->pc++);
3426 reg = (modrm >> 3) & 7;
3427 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
3428 gen_op_mov_TN_reg[ot][1][reg]();
3429 if (s->cc_op != CC_OP_DYNAMIC)
3430 gen_op_set_cc_op(s->cc_op);
3435 s->cc_op = CC_OP_EFLAGS;
3436 gen_op_mov_reg_T1[ot][reg]();
3441 /* lock generation */
3442 if (s->prefix & PREFIX_LOCK)
3446 /* XXX: ensure that no lock was generated */
3450 #define CC_OSZAPC (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C)
3451 #define CC_OSZAP (CC_O | CC_S | CC_Z | CC_A | CC_P)
3453 /* flags read by an operation */
3454 static uint16_t opc_read_flags[NB_OPS] = {
3455 [INDEX_op_aas] = CC_A,
3456 [INDEX_op_aaa] = CC_A,
3457 [INDEX_op_das] = CC_A | CC_C,
3458 [INDEX_op_daa] = CC_A | CC_C,
3460 [INDEX_op_adcb_T0_T1_cc] = CC_C,
3461 [INDEX_op_adcw_T0_T1_cc] = CC_C,
3462 [INDEX_op_adcl_T0_T1_cc] = CC_C,
3463 [INDEX_op_sbbb_T0_T1_cc] = CC_C,
3464 [INDEX_op_sbbw_T0_T1_cc] = CC_C,
3465 [INDEX_op_sbbl_T0_T1_cc] = CC_C,
3467 /* subtle: due to the incl/decl implementation, C is used */
3468 [INDEX_op_incl_T0_cc] = CC_C,
3469 [INDEX_op_decl_T0_cc] = CC_C,
3471 [INDEX_op_into] = CC_O,
3473 [INDEX_op_jb_subb] = CC_C,
3474 [INDEX_op_jb_subw] = CC_C,
3475 [INDEX_op_jb_subl] = CC_C,
3477 [INDEX_op_jz_subb] = CC_Z,
3478 [INDEX_op_jz_subw] = CC_Z,
3479 [INDEX_op_jz_subl] = CC_Z,
3481 [INDEX_op_jbe_subb] = CC_Z | CC_C,
3482 [INDEX_op_jbe_subw] = CC_Z | CC_C,
3483 [INDEX_op_jbe_subl] = CC_Z | CC_C,
3485 [INDEX_op_js_subb] = CC_S,
3486 [INDEX_op_js_subw] = CC_S,
3487 [INDEX_op_js_subl] = CC_S,
3489 [INDEX_op_jl_subb] = CC_O | CC_S,
3490 [INDEX_op_jl_subw] = CC_O | CC_S,
3491 [INDEX_op_jl_subl] = CC_O | CC_S,
3493 [INDEX_op_jle_subb] = CC_O | CC_S | CC_Z,
3494 [INDEX_op_jle_subw] = CC_O | CC_S | CC_Z,
3495 [INDEX_op_jle_subl] = CC_O | CC_S | CC_Z,
3497 [INDEX_op_loopnzw] = CC_Z,
3498 [INDEX_op_loopnzl] = CC_Z,
3499 [INDEX_op_loopzw] = CC_Z,
3500 [INDEX_op_loopzl] = CC_Z,
3502 [INDEX_op_seto_T0_cc] = CC_O,
3503 [INDEX_op_setb_T0_cc] = CC_C,
3504 [INDEX_op_setz_T0_cc] = CC_Z,
3505 [INDEX_op_setbe_T0_cc] = CC_Z | CC_C,
3506 [INDEX_op_sets_T0_cc] = CC_S,
3507 [INDEX_op_setp_T0_cc] = CC_P,
3508 [INDEX_op_setl_T0_cc] = CC_O | CC_S,
3509 [INDEX_op_setle_T0_cc] = CC_O | CC_S | CC_Z,
3511 [INDEX_op_setb_T0_subb] = CC_C,
3512 [INDEX_op_setb_T0_subw] = CC_C,
3513 [INDEX_op_setb_T0_subl] = CC_C,
3515 [INDEX_op_setz_T0_subb] = CC_Z,
3516 [INDEX_op_setz_T0_subw] = CC_Z,
3517 [INDEX_op_setz_T0_subl] = CC_Z,
3519 [INDEX_op_setbe_T0_subb] = CC_Z | CC_C,
3520 [INDEX_op_setbe_T0_subw] = CC_Z | CC_C,
3521 [INDEX_op_setbe_T0_subl] = CC_Z | CC_C,
3523 [INDEX_op_sets_T0_subb] = CC_S,
3524 [INDEX_op_sets_T0_subw] = CC_S,
3525 [INDEX_op_sets_T0_subl] = CC_S,
3527 [INDEX_op_setl_T0_subb] = CC_O | CC_S,
3528 [INDEX_op_setl_T0_subw] = CC_O | CC_S,
3529 [INDEX_op_setl_T0_subl] = CC_O | CC_S,
3531 [INDEX_op_setle_T0_subb] = CC_O | CC_S | CC_Z,
3532 [INDEX_op_setle_T0_subw] = CC_O | CC_S | CC_Z,
3533 [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z,
3535 [INDEX_op_movl_T0_eflags] = CC_OSZAPC,
3536 [INDEX_op_cmc] = CC_C,
3537 [INDEX_op_salc] = CC_C,
3539 [INDEX_op_rclb_T0_T1_cc] = CC_C,
3540 [INDEX_op_rclw_T0_T1_cc] = CC_C,
3541 [INDEX_op_rcll_T0_T1_cc] = CC_C,
3542 [INDEX_op_rcrb_T0_T1_cc] = CC_C,
3543 [INDEX_op_rcrw_T0_T1_cc] = CC_C,
3544 [INDEX_op_rcrl_T0_T1_cc] = CC_C,
3547 /* flags written by an operation */
3548 static uint16_t opc_write_flags[NB_OPS] = {
3549 [INDEX_op_addl_T0_T1_cc] = CC_OSZAPC,
3550 [INDEX_op_orl_T0_T1_cc] = CC_OSZAPC,
3551 [INDEX_op_adcb_T0_T1_cc] = CC_OSZAPC,
3552 [INDEX_op_adcw_T0_T1_cc] = CC_OSZAPC,
3553 [INDEX_op_adcl_T0_T1_cc] = CC_OSZAPC,
3554 [INDEX_op_sbbb_T0_T1_cc] = CC_OSZAPC,
3555 [INDEX_op_sbbw_T0_T1_cc] = CC_OSZAPC,
3556 [INDEX_op_sbbl_T0_T1_cc] = CC_OSZAPC,
3557 [INDEX_op_andl_T0_T1_cc] = CC_OSZAPC,
3558 [INDEX_op_subl_T0_T1_cc] = CC_OSZAPC,
3559 [INDEX_op_xorl_T0_T1_cc] = CC_OSZAPC,
3560 [INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC,
3561 [INDEX_op_negl_T0_cc] = CC_OSZAPC,
3562 /* subtle: due to the incl/decl implementation, C is used */
3563 [INDEX_op_incl_T0_cc] = CC_OSZAPC,
3564 [INDEX_op_decl_T0_cc] = CC_OSZAPC,
3565 [INDEX_op_testl_T0_T1_cc] = CC_OSZAPC,
3567 [INDEX_op_mulb_AL_T0] = CC_OSZAPC,
3568 [INDEX_op_imulb_AL_T0] = CC_OSZAPC,
3569 [INDEX_op_mulw_AX_T0] = CC_OSZAPC,
3570 [INDEX_op_imulw_AX_T0] = CC_OSZAPC,
3571 [INDEX_op_mull_EAX_T0] = CC_OSZAPC,
3572 [INDEX_op_imull_EAX_T0] = CC_OSZAPC,
3573 [INDEX_op_imulw_T0_T1] = CC_OSZAPC,
3574 [INDEX_op_imull_T0_T1] = CC_OSZAPC,
3577 [INDEX_op_aam] = CC_OSZAPC,
3578 [INDEX_op_aad] = CC_OSZAPC,
3579 [INDEX_op_aas] = CC_OSZAPC,
3580 [INDEX_op_aaa] = CC_OSZAPC,
3581 [INDEX_op_das] = CC_OSZAPC,
3582 [INDEX_op_daa] = CC_OSZAPC,
3584 [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C,
3585 [INDEX_op_movw_eflags_T0] = CC_OSZAPC,
3586 [INDEX_op_movl_eflags_T0] = CC_OSZAPC,
3587 [INDEX_op_clc] = CC_C,
3588 [INDEX_op_stc] = CC_C,
3589 [INDEX_op_cmc] = CC_C,
3591 [INDEX_op_rolb_T0_T1_cc] = CC_O | CC_C,
3592 [INDEX_op_rolw_T0_T1_cc] = CC_O | CC_C,
3593 [INDEX_op_roll_T0_T1_cc] = CC_O | CC_C,
3594 [INDEX_op_rorb_T0_T1_cc] = CC_O | CC_C,
3595 [INDEX_op_rorw_T0_T1_cc] = CC_O | CC_C,
3596 [INDEX_op_rorl_T0_T1_cc] = CC_O | CC_C,
3598 [INDEX_op_rclb_T0_T1_cc] = CC_O | CC_C,
3599 [INDEX_op_rclw_T0_T1_cc] = CC_O | CC_C,
3600 [INDEX_op_rcll_T0_T1_cc] = CC_O | CC_C,
3601 [INDEX_op_rcrb_T0_T1_cc] = CC_O | CC_C,
3602 [INDEX_op_rcrw_T0_T1_cc] = CC_O | CC_C,
3603 [INDEX_op_rcrl_T0_T1_cc] = CC_O | CC_C,
3605 [INDEX_op_shlb_T0_T1_cc] = CC_OSZAPC,
3606 [INDEX_op_shlw_T0_T1_cc] = CC_OSZAPC,
3607 [INDEX_op_shll_T0_T1_cc] = CC_OSZAPC,
3609 [INDEX_op_shrb_T0_T1_cc] = CC_OSZAPC,
3610 [INDEX_op_shrw_T0_T1_cc] = CC_OSZAPC,
3611 [INDEX_op_shrl_T0_T1_cc] = CC_OSZAPC,
3613 [INDEX_op_sarb_T0_T1_cc] = CC_OSZAPC,
3614 [INDEX_op_sarw_T0_T1_cc] = CC_OSZAPC,
3615 [INDEX_op_sarl_T0_T1_cc] = CC_OSZAPC,
3617 [INDEX_op_shldw_T0_T1_ECX_cc] = CC_OSZAPC,
3618 [INDEX_op_shldl_T0_T1_ECX_cc] = CC_OSZAPC,
3619 [INDEX_op_shldw_T0_T1_im_cc] = CC_OSZAPC,
3620 [INDEX_op_shldl_T0_T1_im_cc] = CC_OSZAPC,
3622 [INDEX_op_shrdw_T0_T1_ECX_cc] = CC_OSZAPC,
3623 [INDEX_op_shrdl_T0_T1_ECX_cc] = CC_OSZAPC,
3624 [INDEX_op_shrdw_T0_T1_im_cc] = CC_OSZAPC,
3625 [INDEX_op_shrdl_T0_T1_im_cc] = CC_OSZAPC,
3627 [INDEX_op_btw_T0_T1_cc] = CC_OSZAPC,
3628 [INDEX_op_btl_T0_T1_cc] = CC_OSZAPC,
3629 [INDEX_op_btsw_T0_T1_cc] = CC_OSZAPC,
3630 [INDEX_op_btsl_T0_T1_cc] = CC_OSZAPC,
3631 [INDEX_op_btrw_T0_T1_cc] = CC_OSZAPC,
3632 [INDEX_op_btrl_T0_T1_cc] = CC_OSZAPC,
3633 [INDEX_op_btcw_T0_T1_cc] = CC_OSZAPC,
3634 [INDEX_op_btcl_T0_T1_cc] = CC_OSZAPC,
3636 [INDEX_op_bsfw_T0_cc] = CC_OSZAPC,
3637 [INDEX_op_bsfl_T0_cc] = CC_OSZAPC,
3638 [INDEX_op_bsrw_T0_cc] = CC_OSZAPC,
3639 [INDEX_op_bsrl_T0_cc] = CC_OSZAPC,
3642 #define STRINGOP(x) \
3643 [INDEX_op_ ## x ## b_fast] = CC_OSZAPC, \
3644 [INDEX_op_ ## x ## w_fast] = CC_OSZAPC, \
3645 [INDEX_op_ ## x ## l_fast] = CC_OSZAPC, \
3646 [INDEX_op_ ## x ## b_a32] = CC_OSZAPC, \
3647 [INDEX_op_ ## x ## w_a32] = CC_OSZAPC, \
3648 [INDEX_op_ ## x ## l_a32] = CC_OSZAPC, \
3649 [INDEX_op_ ## x ## b_a16] = CC_OSZAPC, \
3650 [INDEX_op_ ## x ## w_a16] = CC_OSZAPC, \
3651 [INDEX_op_ ## x ## l_a16] = CC_OSZAPC,
3655 STRINGOP(repnz_scas)
3658 STRINGOP(repnz_cmps)
3660 [INDEX_op_cmpxchgb_T0_T1_EAX_cc] = CC_OSZAPC,
3661 [INDEX_op_cmpxchgw_T0_T1_EAX_cc] = CC_OSZAPC,
3662 [INDEX_op_cmpxchgl_T0_T1_EAX_cc] = CC_OSZAPC,
3664 [INDEX_op_cmpxchg8b] = CC_Z,
3665 [INDEX_op_lar] = CC_Z,
3666 [INDEX_op_lsl] = CC_Z,
3667 [INDEX_op_fcomi_ST0_FT0] = CC_Z | CC_P | CC_C,
3668 [INDEX_op_fucomi_ST0_FT0] = CC_Z | CC_P | CC_C,
3671 /* simpler form of an operation if no flags need to be generated */
3672 static uint16_t opc_simpler[NB_OPS] = {
3673 [INDEX_op_addl_T0_T1_cc] = INDEX_op_addl_T0_T1,
3674 [INDEX_op_orl_T0_T1_cc] = INDEX_op_orl_T0_T1,
3675 [INDEX_op_andl_T0_T1_cc] = INDEX_op_andl_T0_T1,
3676 [INDEX_op_subl_T0_T1_cc] = INDEX_op_subl_T0_T1,
3677 [INDEX_op_xorl_T0_T1_cc] = INDEX_op_xorl_T0_T1,
3678 [INDEX_op_negl_T0_cc] = INDEX_op_negl_T0,
3679 [INDEX_op_incl_T0_cc] = INDEX_op_incl_T0,
3680 [INDEX_op_decl_T0_cc] = INDEX_op_decl_T0,
3682 [INDEX_op_rolb_T0_T1_cc] = INDEX_op_rolb_T0_T1,
3683 [INDEX_op_rolw_T0_T1_cc] = INDEX_op_rolw_T0_T1,
3684 [INDEX_op_roll_T0_T1_cc] = INDEX_op_roll_T0_T1,
3686 [INDEX_op_rorb_T0_T1_cc] = INDEX_op_rorb_T0_T1,
3687 [INDEX_op_rorw_T0_T1_cc] = INDEX_op_rorw_T0_T1,
3688 [INDEX_op_rorl_T0_T1_cc] = INDEX_op_rorl_T0_T1,
3690 [INDEX_op_shlb_T0_T1_cc] = INDEX_op_shlb_T0_T1,
3691 [INDEX_op_shlw_T0_T1_cc] = INDEX_op_shlw_T0_T1,
3692 [INDEX_op_shll_T0_T1_cc] = INDEX_op_shll_T0_T1,
3694 [INDEX_op_shrb_T0_T1_cc] = INDEX_op_shrb_T0_T1,
3695 [INDEX_op_shrw_T0_T1_cc] = INDEX_op_shrw_T0_T1,
3696 [INDEX_op_shrl_T0_T1_cc] = INDEX_op_shrl_T0_T1,
3698 [INDEX_op_sarb_T0_T1_cc] = INDEX_op_sarb_T0_T1,
3699 [INDEX_op_sarw_T0_T1_cc] = INDEX_op_sarw_T0_T1,
3700 [INDEX_op_sarl_T0_T1_cc] = INDEX_op_sarl_T0_T1,
3703 static void optimize_flags_init(void)
3706 /* put default values in arrays */
3707 for(i = 0; i < NB_OPS; i++) {
3708 if (opc_simpler[i] == 0)
3713 /* CPU flags computation optimization: we move backward thru the
3714 generated code to see which flags are needed. The operation is
3715 modified if suitable */
3716 static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
3719 int live_flags, write_flags, op;
3721 opc_ptr = opc_buf + opc_buf_len;
3722 /* live_flags contains the flags needed by the next instructions
3723 in the code. At the end of the bloc, we consider that all the
3725 live_flags = CC_OSZAPC;
3726 while (opc_ptr > opc_buf) {
3728 /* if none of the flags written by the instruction is used,
3729 then we can try to find a simpler instruction */
3730 write_flags = opc_write_flags[op];
3731 if ((live_flags & write_flags) == 0) {
3732 *opc_ptr = opc_simpler[op];
3734 /* compute the live flags before the instruction */
3735 live_flags &= ~write_flags;
3736 live_flags |= opc_read_flags[op];
3742 static const char *op_str[] = {
3743 #define DEF(s, n, copy_size) #s,
3744 #include "opc-i386.h"
3748 static uint8_t op_nb_args[] = {
3749 #define DEF(s, n, copy_size) n,
3750 #include "opc-i386.h"
3754 static void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf)
3756 const uint16_t *opc_ptr;
3757 const uint32_t *opparam_ptr;
3761 opparam_ptr = opparam_buf;
3765 fprintf(logfile, "0x%04x: %s",
3766 (int)(opc_ptr - opc_buf - 1), op_str[c]);
3767 for(i = 0; i < n; i++) {
3768 fprintf(logfile, " 0x%x", opparam_ptr[i]);
3770 fprintf(logfile, "\n");
3771 if (c == INDEX_op_end)
3779 /* XXX: make safe guess about sizes */
3780 #define MAX_OP_PER_INSTR 32
3781 #define OPC_BUF_SIZE 512
3782 #define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
3784 #define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
3786 static uint16_t gen_opc_buf[OPC_BUF_SIZE];
3787 static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
3788 static uint32_t gen_opc_pc[OPC_BUF_SIZE];
3789 static uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
3791 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
3792 basic block 'tb'. If search_pc is TRUE, also generate PC
3793 information for each intermediate instruction. */
3794 static inline int gen_intermediate_code(TranslationBlock *tb, int search_pc)
3796 DisasContext dc1, *dc = &dc1;
3798 uint16_t *gen_opc_end;
3804 /* generate intermediate code */
3805 pc_start = (uint8_t *)tb->pc;
3806 cs_base = (uint8_t *)tb->cs_base;
3809 dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
3810 dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
3811 dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
3812 dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7;
3813 dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1;
3814 dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3;
3815 dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3;
3816 dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1;
3817 dc->cc_op = CC_OP_DYNAMIC;
3818 dc->cs_base = cs_base;
3821 gen_opc_ptr = gen_opc_buf;
3822 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
3823 gen_opparam_ptr = gen_opparam_buf;
3830 j = gen_opc_ptr - gen_opc_buf;
3834 gen_opc_instr_start[lj++] = 0;
3835 gen_opc_pc[lj] = (uint32_t)pc_ptr;
3836 gen_opc_instr_start[lj] = 1;
3839 ret = disas_insn(dc, pc_ptr);
3841 /* we trigger an illegal instruction operation only if it
3842 is the first instruction. Otherwise, we simply stop
3843 generating the code just before it */
3844 if (pc_ptr == pc_start)
3849 pc_ptr = (void *)ret;
3850 /* if single step mode, we generate only one instruction and
3851 generate an exception */
3854 } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end &&
3855 (pc_ptr - pc_start) < (TARGET_PAGE_SIZE - 32));
3856 /* we must store the eflags state if it is not already done */
3857 if (dc->is_jmp != 3) {
3858 if (dc->cc_op != CC_OP_DYNAMIC)
3859 gen_op_set_cc_op(dc->cc_op);
3860 if (dc->is_jmp != 1) {
3861 /* we add an additionnal jmp to update the simulated PC */
3862 gen_op_jmp_im(ret - (unsigned long)dc->cs_base);
3866 gen_op_raise_exception(EXCP01_SSTP);
3868 if (dc->is_jmp != 3) {
3869 /* indicate that the hash table must be used to find the next TB */
3873 *gen_opc_ptr = INDEX_op_end;
3877 fprintf(logfile, "----------------\n");
3878 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
3879 disas(logfile, pc_start, pc_ptr - pc_start,
3880 dc->code32 ? DISAS_I386_I386 : DISAS_I386_I8086);
3881 fprintf(logfile, "\n");
3883 fprintf(logfile, "OP:\n");
3884 dump_ops(gen_opc_buf, gen_opparam_buf);
3885 fprintf(logfile, "\n");
3889 /* optimize flag computations */
3890 optimize_flags(gen_opc_buf, gen_opc_ptr - gen_opc_buf);
3894 fprintf(logfile, "AFTER FLAGS OPT:\n");
3895 dump_ops(gen_opc_buf, gen_opparam_buf);
3896 fprintf(logfile, "\n");
3900 tb->size = pc_ptr - pc_start;
3905 /* return non zero if the very first instruction is invalid so that
3906 the virtual CPU can trigger an exception.
3908 '*gen_code_size_ptr' contains the size of the generated code (host
3911 int cpu_x86_gen_code(TranslationBlock *tb,
3912 int max_code_size, int *gen_code_size_ptr)
3914 uint8_t *gen_code_buf;
3917 if (gen_intermediate_code(tb, 0) < 0)
3920 /* generate machine code */
3921 tb->tb_next_offset[0] = 0xffff;
3922 tb->tb_next_offset[1] = 0xffff;
3923 gen_code_buf = tb->tc_ptr;
3924 gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset,
3925 #ifdef USE_DIRECT_JUMP
3930 gen_opc_buf, gen_opparam_buf);
3931 flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size));
3933 *gen_code_size_ptr = gen_code_size;
3936 fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
3937 disas(logfile, gen_code_buf, *gen_code_size_ptr, DISAS_TARGET);
3938 fprintf(logfile, "\n");
3945 static const unsigned short opc_copy_size[] = {
3946 #define DEF(s, n, copy_size) copy_size,
3947 #include "opc-i386.h"
3951 /* The simulated PC corresponding to
3952 'searched_pc' in the generated code is searched. 0 is returned if
3953 found. *found_pc contains the found PC.
3955 int cpu_x86_search_pc(TranslationBlock *tb,
3956 uint32_t *found_pc, unsigned long searched_pc)
3959 unsigned long tc_ptr;
3962 if (gen_intermediate_code(tb, 1) < 0)
3965 /* find opc index corresponding to search_pc */
3966 tc_ptr = (unsigned long)tb->tc_ptr;
3967 if (searched_pc < tc_ptr)
3970 opc_ptr = gen_opc_buf;
3973 if (c == INDEX_op_end)
3975 tc_ptr += opc_copy_size[c];
3976 if (searched_pc < tc_ptr)
3980 j = opc_ptr - gen_opc_buf;
3981 /* now find start of instruction before */
3982 while (gen_opc_instr_start[j] == 0)
3984 *found_pc = gen_opc_pc[j];
3989 CPUX86State *cpu_x86_init(void)
3995 cpu_x86_tblocks_init();
3997 env = malloc(sizeof(CPUX86State));
4000 memset(env, 0, sizeof(CPUX86State));
4001 /* basic FPU init */
4002 for(i = 0;i < 8; i++)
4005 /* flags setup : we activate the IRQs by default as in user mode */
4006 env->eflags = 0x2 | IF_MASK;
4008 /* init various static tables */
4011 optimize_flags_init();
4017 void cpu_x86_close(CPUX86State *env)
4022 static const char *cc_op_str[] = {
4055 void cpu_x86_dump_state(CPUX86State *env, FILE *f, int flags)
4058 char cc_op_name[32];
4060 eflags = env->eflags;
4061 fprintf(f, "EAX=%08x EBX=%08x ECX=%08x EDX=%08x\n"
4062 "ESI=%08x EDI=%08x EBP=%08x ESP=%08x\n"
4063 "EIP=%08x EFL=%08x [%c%c%c%c%c%c%c]\n",
4064 env->regs[R_EAX], env->regs[R_EBX], env->regs[R_ECX], env->regs[R_EDX],
4065 env->regs[R_ESI], env->regs[R_EDI], env->regs[R_EBP], env->regs[R_ESP],
4067 eflags & DF_MASK ? 'D' : '-',
4068 eflags & CC_O ? 'O' : '-',
4069 eflags & CC_S ? 'S' : '-',
4070 eflags & CC_Z ? 'Z' : '-',
4071 eflags & CC_A ? 'A' : '-',
4072 eflags & CC_P ? 'P' : '-',
4073 eflags & CC_C ? 'C' : '-');
4074 fprintf(f, "CS=%04x SS=%04x DS=%04x ES=%04x FS=%04x GS=%04x\n",
4081 if (flags & X86_DUMP_CCOP) {
4082 if ((unsigned)env->cc_op < CC_OP_NB)
4083 strcpy(cc_op_name, cc_op_str[env->cc_op]);
4085 snprintf(cc_op_name, sizeof(cc_op_name), "[%d]", env->cc_op);
4086 fprintf(f, "CCS=%08x CCD=%08x CCO=%-8s\n",
4087 env->cc_src, env->cc_dst, cc_op_name);
4089 if (flags & X86_DUMP_FPU) {
4090 fprintf(f, "ST0=%f ST1=%f ST2=%f ST3=%f\n",
4091 (double)env->fpregs[0],
4092 (double)env->fpregs[1],
4093 (double)env->fpregs[2],
4094 (double)env->fpregs[3]);
4095 fprintf(f, "ST4=%f ST5=%f ST6=%f ST7=%f\n",
4096 (double)env->fpregs[4],
4097 (double)env->fpregs[5],
4098 (double)env->fpregs[7],
4099 (double)env->fpregs[8]);