2 * i386 on i386 translation
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
28 #include <sys/ucontext.h>
34 extern char exec_loop;
44 #define PREFIX_REPZ 0x01
45 #define PREFIX_REPNZ 0x02
46 #define PREFIX_LOCK 0x04
47 #define PREFIX_DATA 0x08
48 #define PREFIX_ADR 0x10
50 typedef struct DisasContext {
51 /* current insn context */
52 int override; /* -1 if no override */
55 uint8_t *pc; /* pc = eip + cs_base */
56 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
57 static state change (stop translation) */
59 uint8_t *gen_code_ptr;
60 uint8_t *gen_code_start;
62 /* current block context */
63 uint8_t *cs_base; /* base of CS segment */
64 int pe; /* protected mode */
65 int code32; /* 32 bit code segment */
66 int f_st; /* currently unused */
67 int vm86; /* vm86 mode */
70 struct TranslationBlock *tb;
73 #define CPU_FIELD_OFFSET(field) offsetof(CPUState, field)
75 #define CPU_SEG 0x64 /* fs override */
77 static inline void gb(DisasContext *s, uint32_t val)
79 *s->gen_code_ptr++ = val;
82 static inline void gw(DisasContext *s, uint32_t val)
84 *s->gen_code_ptr++ = val;
85 *s->gen_code_ptr++ = val >> 8;
88 static inline void gl(DisasContext *s, uint32_t val)
90 *s->gen_code_ptr++ = val;
91 *s->gen_code_ptr++ = val >> 8;
92 *s->gen_code_ptr++ = val >> 16;
93 *s->gen_code_ptr++ = val >> 24;
96 static inline void gjmp(DisasContext *s, long val)
98 gb(s, 0xe9); /* jmp */
99 gl(s, val - (long)(s->gen_code_ptr + 4));
102 static inline void gen_movl_addr_im(DisasContext *s,
103 uint32_t addr, uint32_t val)
105 gb(s, CPU_SEG); /* seg movl im, addr */
112 static inline void gen_movw_addr_im(DisasContext *s,
113 uint32_t addr, uint32_t val)
115 gb(s, CPU_SEG); /* seg movl im, addr */
124 static void gen_jmp(DisasContext *s, uint32_t target_eip)
126 TranslationBlock *tb = s->tb;
128 gb(s, 0xe9); /* jmp */
129 tb->tb_jmp_offset[0] = s->gen_code_ptr - s->gen_code_start;
132 tb->tb_next_offset[0] = s->gen_code_ptr - s->gen_code_start;
133 gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), target_eip);
134 gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb);
135 gjmp(s, (long)&exec_loop);
140 static void gen_jcc(DisasContext *s, int op,
141 uint32_t target_eip, uint32_t next_eip)
143 TranslationBlock *tb = s->tb;
145 gb(s, 0x0f); /* jcc */
147 tb->tb_jmp_offset[0] = s->gen_code_ptr - s->gen_code_start;
149 gb(s, 0xe9); /* jmp */
150 tb->tb_jmp_offset[1] = s->gen_code_ptr - s->gen_code_start;
153 tb->tb_next_offset[0] = s->gen_code_ptr - s->gen_code_start;
154 gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), target_eip);
155 gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb);
156 gjmp(s, (long)&exec_loop);
158 tb->tb_next_offset[1] = s->gen_code_ptr - s->gen_code_start;
159 gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), next_eip);
160 gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb | 1);
161 gjmp(s, (long)&exec_loop);
166 static void gen_eob(DisasContext *s)
168 gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), 0);
169 gjmp(s, (long)&exec_loop);
174 static inline void gen_lea_modrm(DisasContext *s, int modrm)
182 mod = (modrm >> 6) & 3;
194 code = ldub_code(s->pc++);
195 scale = (code >> 6) & 3;
196 index = (code >> 3) & 7;
204 disp = ldl_code(s->pc);
211 disp = (int8_t)ldub_code(s->pc++);
215 disp = ldl_code(s->pc);
224 disp = lduw_code(s->pc);
231 disp = (int8_t)ldub_code(s->pc++);
235 disp = lduw_code(s->pc);
242 static inline void parse_modrm(DisasContext *s, int modrm)
244 if ((modrm & 0xc0) != 0xc0)
245 gen_lea_modrm(s, modrm);
248 static inline uint32_t insn_get(DisasContext *s, int ot)
254 ret = ldub_code(s->pc);
258 ret = lduw_code(s->pc);
263 ret = ldl_code(s->pc);
270 /* convert one instruction. s->is_jmp is set if the translation must
272 static int disas_insn(DisasContext *s)
274 uint8_t *pc_start, *pc_tmp, *pc_start_insn;
275 int b, prefixes, aflag, dflag, next_eip, val;
285 b = ldub_code(s->pc);
290 prefixes |= PREFIX_REPZ;
293 prefixes |= PREFIX_REPNZ;
296 prefixes |= PREFIX_LOCK;
317 prefixes |= PREFIX_DATA;
320 prefixes |= PREFIX_ADR;
324 if (prefixes & PREFIX_DATA)
326 if (prefixes & PREFIX_ADR)
329 s->prefix = prefixes;
333 /* lock generation */
334 if (prefixes & PREFIX_LOCK)
336 if (s->override == R_FS || s->override == R_GS || s->override == R_CS)
339 pc_start_insn = s->pc - 1;
340 /* now check op code */
344 /**************************/
345 /* extended op code */
346 b = ldub_code(s->pc++) | 0x100;
349 /**************************/
366 ot = dflag ? OT_LONG : OT_WORD;
369 case 0: /* OP Ev, Gv */
370 modrm = ldub_code(s->pc++);
371 parse_modrm(s, modrm);
373 case 1: /* OP Gv, Ev */
374 modrm = ldub_code(s->pc++);
375 parse_modrm(s, modrm);
377 case 2: /* OP A, Iv */
384 case 0x80: /* GRP1 */
391 ot = dflag ? OT_LONG : OT_WORD;
393 modrm = ldub_code(s->pc++);
394 parse_modrm(s, modrm);
403 insn_get(s, OT_BYTE);
409 /**************************/
410 /* inc, dec, and other misc arith */
411 case 0x40 ... 0x47: /* inc Gv */
413 case 0x48 ... 0x4f: /* dec Gv */
415 case 0xf6: /* GRP3 */
420 ot = dflag ? OT_LONG : OT_WORD;
422 modrm = ldub_code(s->pc++);
423 op = (modrm >> 3) & 7;
424 parse_modrm(s, modrm);
447 case 0xfe: /* GRP4 */
448 case 0xff: /* GRP5 */
452 ot = dflag ? OT_LONG : OT_WORD;
454 modrm = ldub_code(s->pc++);
455 mod = (modrm >> 6) & 3;
456 op = (modrm >> 3) & 7;
457 if (op >= 2 && b == 0xfe) {
461 parse_modrm(s, modrm);
468 case 2: /* call Ev */
469 /* XXX: optimize and handle MEM exceptions specifically
470 fs movl %eax, regs[0]
476 case 3: /* lcall Ev */
479 /* XXX: optimize and handle MEM exceptions specifically
480 fs movl %eax, regs[0]
485 case 5: /* ljmp Ev */
487 case 6: /* push Ev */
493 case 0xa8: /* test eAX, Iv */
498 ot = dflag ? OT_LONG : OT_WORD;
502 case 0x98: /* CWDE/CBW */
504 case 0x99: /* CDQ/CWD */
506 case 0x1af: /* imul Gv, Ev */
507 case 0x69: /* imul Gv, Ev, I */
509 ot = dflag ? OT_LONG : OT_WORD;
510 modrm = ldub_code(s->pc++);
511 parse_modrm(s, modrm);
514 } else if (b == 0x6b) {
515 insn_get(s, OT_BYTE);
520 case 0x84: /* test Ev, Gv */
524 case 0x1c1: /* xadd Ev, Gv */
527 case 0x1b1: /* cmpxchg Ev, Gv */
529 case 0x8f: /* pop Ev */
532 case 0x89: /* mov Gv, Ev */
535 case 0x8b: /* mov Ev, Gv */
537 case 0x1b6: /* movzbS Gv, Eb */
538 case 0x1b7: /* movzwS Gv, Eb */
539 case 0x1be: /* movsbS Gv, Eb */
540 case 0x1bf: /* movswS Gv, Eb */
543 case 0x87: /* xchg Ev, Gv */
546 case 0xd1: /* shift Ev,1 */
549 case 0xd3: /* shift Ev,cl */
551 case 0x1a5: /* shld cl */
552 case 0x1ad: /* shrd cl */
554 case 0x190 ... 0x19f: /* setcc Gv */
556 /* XXX: emulate cmov if not available ? */
557 case 0x140 ... 0x14f: /* cmov Gv, Ev */
559 case 0x1a3: /* bt Gv, Ev */
560 case 0x1ab: /* bts */
561 case 0x1b3: /* btr */
562 case 0x1bb: /* btc */
564 case 0x1bc: /* bsf */
565 case 0x1bd: /* bsr */
567 modrm = ldub_code(s->pc++);
568 parse_modrm(s, modrm);
571 case 0x1c7: /* cmpxchg8b */
572 modrm = ldub_code(s->pc++);
573 mod = (modrm >> 6) & 3;
576 parse_modrm(s, modrm);
579 /**************************/
581 case 0x50 ... 0x57: /* push */
582 case 0x58 ... 0x5f: /* pop */
583 case 0x60: /* pusha */
584 case 0x61: /* popa */
587 case 0x68: /* push Iv */
589 ot = dflag ? OT_LONG : OT_WORD;
593 insn_get(s, OT_BYTE);
595 case 0xc8: /* enter */
600 case 0xc9: /* leave */
603 case 0x06: /* push es */
604 case 0x0e: /* push cs */
605 case 0x16: /* push ss */
606 case 0x1e: /* push ds */
608 push segs[n].selector
611 case 0x1a0: /* push fs */
612 case 0x1a8: /* push gs */
614 case 0x07: /* pop es */
615 case 0x17: /* pop ss */
616 case 0x1f: /* pop ds */
618 case 0x1a1: /* pop fs */
619 case 0x1a9: /* pop gs */
621 case 0x8e: /* mov seg, Gv */
624 movl segs[].selector, r
629 case 0x8c: /* mov Gv, seg */
631 case 0xc4: /* les Gv */
634 case 0xc5: /* lds Gv */
637 case 0x1b2: /* lss Gv */
640 case 0x1b4: /* lfs Gv */
643 case 0x1b5: /* lgs Gv */
648 /************************/
651 modrm = ldub_code(s->pc++);
652 mod = (modrm >> 6) & 3;
654 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
657 gen_lea_modrm(s, modrm, ®_addr, &offset_addr);
659 case 0x00 ... 0x07: /* fxxxs */
660 case 0x10 ... 0x17: /* fixxxl */
661 case 0x20 ... 0x27: /* fxxxl */
662 case 0x30 ... 0x37: /* fixxx */
669 gen_op_flds_FT0_A0();
672 gen_op_fildl_FT0_A0();
675 gen_op_fldl_FT0_A0();
679 gen_op_fild_FT0_A0();
683 gen_op_fp_arith_ST0_FT0[op1]();
685 /* fcomp needs pop */
690 case 0x08: /* flds */
691 case 0x0a: /* fsts */
692 case 0x0b: /* fstps */
693 case 0x18: /* fildl */
694 case 0x1a: /* fistl */
695 case 0x1b: /* fistpl */
696 case 0x28: /* fldl */
697 case 0x2a: /* fstl */
698 case 0x2b: /* fstpl */
699 case 0x38: /* filds */
700 case 0x3a: /* fists */
701 case 0x3b: /* fistps */
707 gen_op_flds_ST0_A0();
710 gen_op_fildl_ST0_A0();
713 gen_op_fldl_ST0_A0();
717 gen_op_fild_ST0_A0();
724 gen_op_fsts_ST0_A0();
727 gen_op_fistl_ST0_A0();
730 gen_op_fstl_ST0_A0();
734 gen_op_fist_ST0_A0();
742 case 0x0c: /* fldenv mem */
743 gen_op_fldenv_A0(s->dflag);
745 case 0x0d: /* fldcw mem */
748 case 0x0e: /* fnstenv mem */
749 gen_op_fnstenv_A0(s->dflag);
751 case 0x0f: /* fnstcw mem */
754 case 0x1d: /* fldt mem */
755 gen_op_fldt_ST0_A0();
757 case 0x1f: /* fstpt mem */
758 gen_op_fstt_ST0_A0();
761 case 0x2c: /* frstor mem */
762 gen_op_frstor_A0(s->dflag);
764 case 0x2e: /* fnsave mem */
765 gen_op_fnsave_A0(s->dflag);
767 case 0x2f: /* fnstsw mem */
770 case 0x3c: /* fbld */
771 gen_op_fbld_ST0_A0();
773 case 0x3e: /* fbstp */
774 gen_op_fbst_ST0_A0();
777 case 0x3d: /* fildll */
778 gen_op_fildll_ST0_A0();
780 case 0x3f: /* fistpll */
781 gen_op_fistll_ST0_A0();
788 /* register float ops */
792 case 0x08: /* fld sti */
794 gen_op_fmov_ST0_STN((opreg + 1) & 7);
796 case 0x09: /* fxchg sti */
797 gen_op_fxchg_ST0_STN(opreg);
799 case 0x0a: /* grp d9/2 */
807 case 0x0c: /* grp d9/4 */
817 gen_op_fcom_ST0_FT0();
826 case 0x0d: /* grp d9/5 */
862 case 0x0e: /* grp d9/6 */
876 case 4: /* fxtract */
882 case 6: /* fdecstp */
886 case 7: /* fincstp */
891 case 0x0f: /* grp d9/7 */
896 case 1: /* fyl2xp1 */
902 case 3: /* fsincos */
908 case 4: /* frndint */
920 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
921 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
922 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
928 gen_op_fp_arith_STN_ST0[op1](opreg);
932 gen_op_fmov_FT0_STN(opreg);
933 gen_op_fp_arith_ST0_FT0[op1]();
937 case 0x02: /* fcom */
938 gen_op_fmov_FT0_STN(opreg);
939 gen_op_fcom_ST0_FT0();
941 case 0x03: /* fcomp */
942 gen_op_fmov_FT0_STN(opreg);
943 gen_op_fcom_ST0_FT0();
946 case 0x15: /* da/5 */
948 case 1: /* fucompp */
949 gen_op_fmov_FT0_STN(1);
950 gen_op_fucom_ST0_FT0();
960 case 0: /* feni (287 only, just do nop here) */
962 case 1: /* fdisi (287 only, just do nop here) */
970 case 4: /* fsetpm (287 only, just do nop here) */
976 case 0x1d: /* fucomi */
977 if (s->cc_op != CC_OP_DYNAMIC)
978 gen_op_set_cc_op(s->cc_op);
979 gen_op_fmov_FT0_STN(opreg);
980 gen_op_fucomi_ST0_FT0();
981 s->cc_op = CC_OP_EFLAGS;
983 case 0x1e: /* fcomi */
984 if (s->cc_op != CC_OP_DYNAMIC)
985 gen_op_set_cc_op(s->cc_op);
986 gen_op_fmov_FT0_STN(opreg);
987 gen_op_fcomi_ST0_FT0();
988 s->cc_op = CC_OP_EFLAGS;
990 case 0x2a: /* fst sti */
991 gen_op_fmov_STN_ST0(opreg);
993 case 0x2b: /* fstp sti */
994 gen_op_fmov_STN_ST0(opreg);
997 case 0x2c: /* fucom st(i) */
998 gen_op_fmov_FT0_STN(opreg);
999 gen_op_fucom_ST0_FT0();
1001 case 0x2d: /* fucomp st(i) */
1002 gen_op_fmov_FT0_STN(opreg);
1003 gen_op_fucom_ST0_FT0();
1006 case 0x33: /* de/3 */
1008 case 1: /* fcompp */
1009 gen_op_fmov_FT0_STN(1);
1010 gen_op_fcom_ST0_FT0();
1018 case 0x3c: /* df/4 */
1021 gen_op_fnstsw_EAX();
1027 case 0x3d: /* fucomip */
1028 if (s->cc_op != CC_OP_DYNAMIC)
1029 gen_op_set_cc_op(s->cc_op);
1030 gen_op_fmov_FT0_STN(opreg);
1031 gen_op_fucomi_ST0_FT0();
1033 s->cc_op = CC_OP_EFLAGS;
1035 case 0x3e: /* fcomip */
1036 if (s->cc_op != CC_OP_DYNAMIC)
1037 gen_op_set_cc_op(s->cc_op);
1038 gen_op_fmov_FT0_STN(opreg);
1039 gen_op_fcomi_ST0_FT0();
1041 s->cc_op = CC_OP_EFLAGS;
1043 case 0x10 ... 0x13: /* fcmovxx */
1047 const static uint8_t fcmov_cc[8] = {
1053 op1 = fcmov_cc[op & 3] | ((op >> 3) & 1);
1055 gen_op_fcmov_ST0_STN_T0(opreg);
1064 /**************************/
1067 case 0xc7: /* mov Ev, Iv */
1071 ot = dflag ? OT_LONG : OT_WORD;
1072 modrm = ldub_code(s->pc++);
1073 parse_modrm(s, modrm);
1077 case 0x8d: /* lea */
1078 ot = dflag ? OT_LONG : OT_WORD;
1079 modrm = ldub_code(s->pc++);
1080 mod = (modrm >> 6) & 3;
1083 parse_modrm(s, modrm);
1086 case 0xa0: /* mov EAX, Ov */
1088 case 0xa2: /* mov Ov, EAX */
1093 ot = dflag ? OT_LONG : OT_WORD;
1095 insn_get(s, OT_LONG);
1097 insn_get(s, OT_WORD);
1099 case 0xd7: /* xlat */
1101 case 0xb0 ... 0xb7: /* mov R, Ib */
1102 insn_get(s, OT_BYTE);
1104 case 0xb8 ... 0xbf: /* mov R, Iv */
1105 ot = dflag ? OT_LONG : OT_WORD;
1109 case 0x91 ... 0x97: /* xchg R, EAX */
1112 /************************/
1115 case 0xc1: /* shift Ev,imm */
1117 case 0x1a4: /* shld imm */
1118 case 0x1ac: /* shrd imm */
1119 modrm = ldub_code(s->pc++);
1120 parse_modrm(s, modrm);
1124 /************************/
1127 case 0xa4: /* movsS */
1131 case 0xaa: /* stosS */
1135 case 0xac: /* lodsS */
1139 case 0xae: /* scasS */
1143 case 0xa6: /* cmpsS */
1147 case 0x6c: /* insS */
1149 goto unsupported_op;
1151 case 0x6e: /* outsS */
1153 goto unsupported_op;
1155 /************************/
1159 goto unsupported_op;
1163 goto unsupported_op;
1167 goto unsupported_op;
1171 goto unsupported_op;
1173 /************************/
1176 case 0xc2: /* ret im */
1177 val = ldsw_code(s->pc);
1180 gen_stack_update(s, val + (2 << s->dflag));
1182 gen_op_andl_T0_ffff();
1188 case 0xc3: /* ret */
1191 gb(s, 0x66); /* d16 */
1192 gb(s, 0x8f); /* pop addr */
1194 gl(s, CPU_FIELD_OFFSET(eip));
1196 /* reset high bits of EIP */
1197 gen_movw_addr_im(s, CPU_FIELD_OFFSET(eip) + 2, 0);
1201 case 0xca: /* lret im */
1202 case 0xcb: /* lret */
1203 case 0xcf: /* iret */
1204 case 0x9a: /* lcall im */
1205 case 0xea: /* ljmp im */
1206 goto unsupported_op;
1208 case 0xe8: /* call im */
1209 ot = dflag ? OT_LONG : OT_WORD;
1210 val = insn_get(s, ot);
1211 next_eip = s->pc - s->cs_base;
1214 gb(s, 0x68); /* pushl imm */
1217 gb(s, 0x66); /* pushw imm */
1224 case 0xe9: /* jmp */
1225 ot = dflag ? OT_LONG : OT_WORD;
1226 val = insn_get(s, ot);
1227 val += s->pc - s->cs_base;
1232 case 0xeb: /* jmp Jb */
1233 val = (int8_t)insn_get(s, OT_BYTE);
1234 val += s->pc - s->cs_base;
1239 case 0x70 ... 0x7f: /* jcc Jb */
1240 val = (int8_t)insn_get(s, OT_BYTE);
1242 case 0x180 ... 0x18f: /* jcc Jv */
1244 val = insn_get(s, OT_LONG);
1246 val = (int16_t)insn_get(s, OT_WORD);
1249 next_eip = s->pc - s->cs_base;
1253 gen_jcc(s, b & 0xf, val, next_eip);
1256 /************************/
1258 case 0x9c: /* pushf */
1259 /* XXX: put specific code ? */
1260 goto unsupported_op;
1261 case 0x9d: /* popf */
1262 goto unsupported_op;
1264 case 0x9e: /* sahf */
1265 case 0x9f: /* lahf */
1266 case 0xf5: /* cmc */
1267 case 0xf8: /* clc */
1268 case 0xf9: /* stc */
1269 case 0xfc: /* cld */
1270 case 0xfd: /* std */
1273 /************************/
1274 /* bit operations */
1275 case 0x1ba: /* bt/bts/btr/btc Gv, im */
1276 ot = dflag ? OT_LONG : OT_WORD;
1277 modrm = ldub_code(s->pc++);
1278 op = (modrm >> 3) & 7;
1279 parse_modrm(s, modrm);
1285 /************************/
1287 case 0x27: /* daa */
1289 case 0x2f: /* das */
1291 case 0x37: /* aaa */
1293 case 0x3f: /* aas */
1295 case 0xd4: /* aam */
1298 case 0xd5: /* aad */
1301 /************************/
1303 case 0x90: /* nop */
1305 case 0x9b: /* fwait */
1307 case 0xcc: /* int3 */
1308 goto unsupported_op;
1309 case 0xcd: /* int N */
1310 goto unsupported_op;
1311 case 0xce: /* into */
1312 goto unsupported_op;
1313 case 0xf1: /* icebp (undocumented, exits to external debugger) */
1314 goto unsupported_op;
1315 case 0xfa: /* cli */
1316 goto unsupported_op;
1317 case 0xfb: /* sti */
1318 goto unsupported_op;
1319 case 0x62: /* bound */
1320 modrm = ldub_code(s->pc++);
1321 mod = (modrm >> 6) & 3;
1324 parse_modrm(s, modrm);
1326 case 0x1c8 ... 0x1cf: /* bswap reg */
1328 case 0xd6: /* salc */
1330 case 0xe0: /* loopnz */
1331 case 0xe1: /* loopz */
1332 case 0xe2: /* loop */
1333 case 0xe3: /* jecxz */
1334 goto unsupported_op;
1336 case 0x130: /* wrmsr */
1337 case 0x132: /* rdmsr */
1338 goto unsupported_op;
1339 case 0x131: /* rdtsc */
1340 goto unsupported_op;
1341 case 0x1a2: /* cpuid */
1342 goto unsupported_op;
1343 case 0xf4: /* hlt */
1344 goto unsupported_op;
1346 goto unsupported_op;
1348 goto unsupported_op;
1349 case 0x108: /* invd */
1350 case 0x109: /* wbinvd */
1351 goto unsupported_op;
1352 case 0x63: /* arpl */
1353 goto unsupported_op;
1354 case 0x102: /* lar */
1355 case 0x103: /* lsl */
1356 goto unsupported_op;
1358 goto unsupported_op;
1359 case 0x120: /* mov reg, crN */
1360 case 0x122: /* mov crN, reg */
1361 goto unsupported_op;
1362 case 0x121: /* mov reg, drN */
1363 case 0x123: /* mov drN, reg */
1364 goto unsupported_op;
1365 case 0x106: /* clts */
1366 goto unsupported_op;
1371 /* just copy the code */
1373 /* no override yet */
1378 if (prefixes & PREFIX_REPZ)
1380 else if (prefixes & PREFIX_REPNZ)
1384 len = s->pc - pc_start_insn;
1385 for(i = 0; i < len; i++) {
1386 *s->gen_code_ptr++ = ldub_code(pc_start_insn + i);
1393 /* fall back to slower code gen necessary */
1398 #define GEN_CODE_MAX_SIZE 8192
1399 #define GEN_CODE_MAX_INSN_SIZE 512
1401 static inline int gen_intermediate_code_internal(CPUState *env,
1402 TranslationBlock *tb,
1403 uint8_t *gen_code_ptr,
1404 int *gen_code_size_ptr,
1408 DisasContext dc1, *dc = &dc1;
1409 uint8_t *pc_insn, *pc_start, *gen_code_end;
1413 if (env->nb_breakpoints > 0 ||
1414 env->singlestep_enabled)
1417 if (flags & (HF_TF_MASK | HF_ADDSEG_MASK |
1418 HF_SOFTMMU_MASK | HF_INHIBIT_IRQ_MASK))
1420 if (!(flags & HF_SS32_MASK))
1422 gen_code_end = gen_code_ptr +
1423 GEN_CODE_MAX_SIZE - GEN_CODE_MAX_INSN_SIZE;
1424 dc->gen_code_ptr = gen_code_ptr;
1425 dc->gen_code_start = gen_code_ptr;
1427 /* generate intermediate code */
1428 pc_start = (uint8_t *)tb->pc;
1429 cs_base = (uint8_t *)tb->cs_base;
1431 dc->cs_base = cs_base;
1432 dc->pe = (flags >> HF_PE_SHIFT) & 1;
1433 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
1435 dc->vm86 = (flags >> VM_SHIFT) & 1;
1436 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
1437 dc->iopl = (flags >> IOPL_SHIFT) & 3;
1444 ret = disas_insn(dc);
1446 /* unsupported insn */
1447 if (dc->pc == pc_start) {
1448 /* if first instruction, signal that no copying was done */
1451 gen_jmp(dc, dc->pc - dc->cs_base);
1456 /* search pc mode */
1457 if (tc_ptr < dc->gen_code_ptr) {
1458 env->eip = pc_insn - cs_base;
1462 /* stop translation if indicated */
1465 /* if too long translation, stop generation */
1466 if (dc->gen_code_ptr >= gen_code_end ||
1467 (dc->pc - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
1468 gen_jmp(dc, dc->pc - dc->cs_base);
1475 fprintf(logfile, "----------------\n");
1476 fprintf(logfile, "IN: COPY: %s\n", lookup_symbol(pc_start));
1477 disas(logfile, pc_start, dc->pc - pc_start, 0, !dc->code32);
1478 fprintf(logfile, "\n");
1483 *gen_code_size_ptr = dc->gen_code_ptr - dc->gen_code_start;
1484 tb->size = dc->pc - pc_start;
1485 tb->cflags = CF_CODE_COPY;
1492 /* generate code by just copying data. Return -1 if cannot generate
1493 any code. Return 0 if code was generated */
1494 int cpu_gen_code_copy(CPUState *env, TranslationBlock *tb,
1495 int max_code_size, int *gen_code_size_ptr)
1497 /* generate machine code */
1498 tb->tb_next_offset[0] = 0xffff;
1499 tb->tb_next_offset[1] = 0xffff;
1500 #ifdef USE_DIRECT_JUMP
1501 /* the following two entries are optional (only used for string ops) */
1502 tb->tb_jmp_offset[2] = 0xffff;
1503 tb->tb_jmp_offset[3] = 0xffff;
1505 return gen_intermediate_code_internal(env, tb,
1506 tb->tc_ptr, gen_code_size_ptr,
1510 static uint8_t dummy_gen_code_buf[GEN_CODE_MAX_SIZE];
1512 int cpu_restore_state_copy(TranslationBlock *tb,
1513 CPUState *env, unsigned long searched_pc,
1516 struct ucontext *uc = puc;
1519 /* find opc index corresponding to search_pc */
1520 if (searched_pc < (unsigned long)tb->tc_ptr)
1522 searched_pc = searched_pc - (long)tb->tc_ptr + (long)dummy_gen_code_buf;
1523 ret = gen_intermediate_code_internal(env, tb,
1524 dummy_gen_code_buf, NULL,
1525 1, (uint8_t *)searched_pc);
1528 /* restore all the CPU state from the CPU context from the
1531 env->regs[R_EAX] = uc->uc_mcontext.gregs[REG_EAX];
1532 env->regs[R_ECX] = uc->uc_mcontext.gregs[REG_ECX];
1533 env->regs[R_EDX] = uc->uc_mcontext.gregs[REG_EDX];
1534 env->regs[R_EBX] = uc->uc_mcontext.gregs[REG_EBX];
1535 env->regs[R_ESP] = uc->uc_mcontext.gregs[REG_ESP];
1536 env->regs[R_EBP] = uc->uc_mcontext.gregs[REG_EBP];
1537 env->regs[R_ESI] = uc->uc_mcontext.gregs[REG_ESI];
1538 env->regs[R_EDI] = uc->uc_mcontext.gregs[REG_EDI];
1539 eflags = uc->uc_mcontext.gregs[REG_EFL];
1540 env->df = 1 - (2 * ((eflags >> 10) & 1));
1541 env->cc_src = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1542 env->cc_op = CC_OP_EFLAGS;