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>
36 extern char exec_loop;
46 #define PREFIX_REPZ 0x01
47 #define PREFIX_REPNZ 0x02
48 #define PREFIX_LOCK 0x04
49 #define PREFIX_DATA 0x08
50 #define PREFIX_ADR 0x10
52 typedef struct DisasContext {
53 /* current insn context */
54 int override; /* -1 if no override */
57 uint8_t *pc; /* pc = eip + cs_base */
58 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
59 static state change (stop translation) */
61 uint8_t *gen_code_ptr;
62 uint8_t *gen_code_start;
64 /* current block context */
65 uint8_t *cs_base; /* base of CS segment */
66 int pe; /* protected mode */
67 int code32; /* 32 bit code segment */
68 int f_st; /* currently unused */
69 int vm86; /* vm86 mode */
73 struct TranslationBlock *tb;
76 #define CPU_FIELD_OFFSET(field) offsetof(CPUState, field)
78 #define CPU_SEG 0x64 /* fs override */
80 static inline void gb(DisasContext *s, uint32_t val)
82 *s->gen_code_ptr++ = val;
85 static inline void gw(DisasContext *s, uint32_t val)
87 *s->gen_code_ptr++ = val;
88 *s->gen_code_ptr++ = val >> 8;
91 static inline void gl(DisasContext *s, uint32_t val)
93 *s->gen_code_ptr++ = val;
94 *s->gen_code_ptr++ = val >> 8;
95 *s->gen_code_ptr++ = val >> 16;
96 *s->gen_code_ptr++ = val >> 24;
99 static inline void gjmp(DisasContext *s, long val)
101 gb(s, 0xe9); /* jmp */
102 gl(s, val - (long)(s->gen_code_ptr + 4));
105 static inline void gen_movl_addr_im(DisasContext *s,
106 uint32_t addr, uint32_t val)
108 gb(s, CPU_SEG); /* seg movl im, addr */
115 static inline void gen_movw_addr_im(DisasContext *s,
116 uint32_t addr, uint32_t val)
118 gb(s, CPU_SEG); /* seg movl im, addr */
127 static void gen_jmp(DisasContext *s, uint32_t target_eip)
129 TranslationBlock *tb = s->tb;
131 gb(s, 0xe9); /* jmp */
132 tb->tb_jmp_offset[0] = s->gen_code_ptr - s->gen_code_start;
135 tb->tb_next_offset[0] = s->gen_code_ptr - s->gen_code_start;
136 gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), target_eip);
137 gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb);
138 gjmp(s, (long)&exec_loop);
143 static void gen_jcc(DisasContext *s, int op,
144 uint32_t target_eip, uint32_t next_eip)
146 TranslationBlock *tb = s->tb;
148 gb(s, 0x0f); /* jcc */
150 tb->tb_jmp_offset[0] = s->gen_code_ptr - s->gen_code_start;
152 gb(s, 0xe9); /* jmp */
153 tb->tb_jmp_offset[1] = s->gen_code_ptr - s->gen_code_start;
156 tb->tb_next_offset[0] = s->gen_code_ptr - s->gen_code_start;
157 gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), target_eip);
158 gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb);
159 gjmp(s, (long)&exec_loop);
161 tb->tb_next_offset[1] = s->gen_code_ptr - s->gen_code_start;
162 gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), next_eip);
163 gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb | 1);
164 gjmp(s, (long)&exec_loop);
169 static void gen_eob(DisasContext *s)
171 gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), 0);
172 gjmp(s, (long)&exec_loop);
177 static inline void gen_lea_modrm(DisasContext *s, int modrm)
185 mod = (modrm >> 6) & 3;
197 code = ldub_code(s->pc++);
198 scale = (code >> 6) & 3;
199 index = (code >> 3) & 7;
207 disp = ldl_code(s->pc);
214 disp = (int8_t)ldub_code(s->pc++);
218 disp = ldl_code(s->pc);
227 disp = lduw_code(s->pc);
234 disp = (int8_t)ldub_code(s->pc++);
238 disp = lduw_code(s->pc);
245 static inline void parse_modrm(DisasContext *s, int modrm)
247 if ((modrm & 0xc0) != 0xc0)
248 gen_lea_modrm(s, modrm);
251 static inline uint32_t insn_get(DisasContext *s, int ot)
257 ret = ldub_code(s->pc);
261 ret = lduw_code(s->pc);
266 ret = ldl_code(s->pc);
273 /* convert one instruction. s->is_jmp is set if the translation must
275 static int disas_insn(DisasContext *s)
277 uint8_t *pc_start, *pc_tmp, *pc_start_insn;
278 int b, prefixes, aflag, dflag, next_eip, val;
280 int modrm, mod, op, rm;
288 b = ldub_code(s->pc);
293 prefixes |= PREFIX_REPZ;
296 prefixes |= PREFIX_REPNZ;
299 prefixes |= PREFIX_LOCK;
320 prefixes |= PREFIX_DATA;
323 prefixes |= PREFIX_ADR;
327 if (prefixes & PREFIX_DATA)
329 if (prefixes & PREFIX_ADR)
332 s->prefix = prefixes;
336 /* lock generation */
337 if (prefixes & PREFIX_LOCK)
339 if (s->override == R_FS || s->override == R_GS || s->override == R_CS)
342 pc_start_insn = s->pc - 1;
343 /* now check op code */
347 /**************************/
348 /* extended op code */
349 b = ldub_code(s->pc++) | 0x100;
352 /**************************/
369 ot = dflag ? OT_LONG : OT_WORD;
372 case 0: /* OP Ev, Gv */
373 modrm = ldub_code(s->pc++);
374 parse_modrm(s, modrm);
376 case 1: /* OP Gv, Ev */
377 modrm = ldub_code(s->pc++);
378 parse_modrm(s, modrm);
380 case 2: /* OP A, Iv */
387 case 0x80: /* GRP1 */
394 ot = dflag ? OT_LONG : OT_WORD;
396 modrm = ldub_code(s->pc++);
397 parse_modrm(s, modrm);
406 insn_get(s, OT_BYTE);
412 /**************************/
413 /* inc, dec, and other misc arith */
414 case 0x40 ... 0x47: /* inc Gv */
416 case 0x48 ... 0x4f: /* dec Gv */
418 case 0xf6: /* GRP3 */
423 ot = dflag ? OT_LONG : OT_WORD;
425 modrm = ldub_code(s->pc++);
426 op = (modrm >> 3) & 7;
427 parse_modrm(s, modrm);
450 case 0xfe: /* GRP4 */
451 case 0xff: /* GRP5 */
455 ot = dflag ? OT_LONG : OT_WORD;
457 modrm = ldub_code(s->pc++);
458 mod = (modrm >> 6) & 3;
459 op = (modrm >> 3) & 7;
460 if (op >= 2 && b == 0xfe) {
464 parse_modrm(s, modrm);
471 case 2: /* call Ev */
472 /* XXX: optimize and handle MEM exceptions specifically
473 fs movl %eax, regs[0]
479 case 3: /* lcall Ev */
482 /* XXX: optimize and handle MEM exceptions specifically
483 fs movl %eax, regs[0]
488 case 5: /* ljmp Ev */
490 case 6: /* push Ev */
496 case 0xa8: /* test eAX, Iv */
501 ot = dflag ? OT_LONG : OT_WORD;
505 case 0x98: /* CWDE/CBW */
507 case 0x99: /* CDQ/CWD */
509 case 0x1af: /* imul Gv, Ev */
510 case 0x69: /* imul Gv, Ev, I */
512 ot = dflag ? OT_LONG : OT_WORD;
513 modrm = ldub_code(s->pc++);
514 parse_modrm(s, modrm);
517 } else if (b == 0x6b) {
518 insn_get(s, OT_BYTE);
523 case 0x84: /* test Ev, Gv */
527 case 0x1c1: /* xadd Ev, Gv */
530 case 0x1b1: /* cmpxchg Ev, Gv */
532 case 0x8f: /* pop Ev */
535 case 0x89: /* mov Gv, Ev */
538 case 0x8b: /* mov Ev, Gv */
540 case 0x1b6: /* movzbS Gv, Eb */
541 case 0x1b7: /* movzwS Gv, Eb */
542 case 0x1be: /* movsbS Gv, Eb */
543 case 0x1bf: /* movswS Gv, Eb */
546 case 0x87: /* xchg Ev, Gv */
549 case 0xd1: /* shift Ev,1 */
552 case 0xd3: /* shift Ev,cl */
554 case 0x1a5: /* shld cl */
555 case 0x1ad: /* shrd cl */
557 case 0x190 ... 0x19f: /* setcc Gv */
559 /* XXX: emulate cmov if not available ? */
560 case 0x140 ... 0x14f: /* cmov Gv, Ev */
562 case 0x1a3: /* bt Gv, Ev */
563 case 0x1ab: /* bts */
564 case 0x1b3: /* btr */
565 case 0x1bb: /* btc */
567 case 0x1bc: /* bsf */
568 case 0x1bd: /* bsr */
570 modrm = ldub_code(s->pc++);
571 parse_modrm(s, modrm);
574 case 0x1c7: /* cmpxchg8b */
575 modrm = ldub_code(s->pc++);
576 mod = (modrm >> 6) & 3;
579 parse_modrm(s, modrm);
582 /**************************/
584 case 0x50 ... 0x57: /* push */
585 case 0x58 ... 0x5f: /* pop */
586 case 0x60: /* pusha */
587 case 0x61: /* popa */
590 case 0x68: /* push Iv */
592 ot = dflag ? OT_LONG : OT_WORD;
596 insn_get(s, OT_BYTE);
598 case 0xc8: /* enter */
603 case 0xc9: /* leave */
606 case 0x06: /* push es */
607 case 0x0e: /* push cs */
608 case 0x16: /* push ss */
609 case 0x1e: /* push ds */
611 push segs[n].selector
614 case 0x1a0: /* push fs */
615 case 0x1a8: /* push gs */
617 case 0x07: /* pop es */
618 case 0x17: /* pop ss */
619 case 0x1f: /* pop ds */
621 case 0x1a1: /* pop fs */
622 case 0x1a9: /* pop gs */
624 case 0x8e: /* mov seg, Gv */
627 movl segs[].selector, r
632 case 0x8c: /* mov Gv, seg */
634 case 0xc4: /* les Gv */
637 case 0xc5: /* lds Gv */
640 case 0x1b2: /* lss Gv */
643 case 0x1b4: /* lfs Gv */
646 case 0x1b5: /* lgs Gv */
650 /************************/
654 /* currently not stable enough */
657 if (s->flags & (HF_EM_MASK | HF_TS_MASK))
661 /* for testing FPU context switch */
664 count = (count + 1) % 3;
669 modrm = ldub_code(s->pc++);
670 mod = (modrm >> 6) & 3;
672 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
675 parse_modrm(s, modrm);
677 case 0x00 ... 0x07: /* fxxxs */
678 case 0x10 ... 0x17: /* fixxxl */
679 case 0x20 ... 0x27: /* fxxxl */
680 case 0x30 ... 0x37: /* fixxx */
682 case 0x08: /* flds */
683 case 0x0a: /* fsts */
684 case 0x0b: /* fstps */
685 case 0x18: /* fildl */
686 case 0x1a: /* fistl */
687 case 0x1b: /* fistpl */
688 case 0x28: /* fldl */
689 case 0x2a: /* fstl */
690 case 0x2b: /* fstpl */
691 case 0x38: /* filds */
692 case 0x3a: /* fists */
693 case 0x3b: /* fistps */
694 case 0x0c: /* fldenv mem */
695 case 0x0d: /* fldcw mem */
696 case 0x0e: /* fnstenv mem */
697 case 0x0f: /* fnstcw mem */
698 case 0x1d: /* fldt mem */
699 case 0x1f: /* fstpt mem */
700 case 0x2c: /* frstor mem */
701 case 0x2e: /* fnsave mem */
702 case 0x2f: /* fnstsw mem */
703 case 0x3c: /* fbld */
704 case 0x3e: /* fbstp */
705 case 0x3d: /* fildll */
706 case 0x3f: /* fistpll */
712 /* register float ops */
714 case 0x08: /* fld sti */
715 case 0x09: /* fxchg sti */
717 case 0x0a: /* grp d9/2 */
725 case 0x0c: /* grp d9/4 */
736 case 0x0d: /* grp d9/5 */
750 case 0x0e: /* grp d9/6 */
752 case 0x0f: /* grp d9/7 */
754 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
755 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
756 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
758 case 0x02: /* fcom */
760 case 0x03: /* fcomp */
762 case 0x15: /* da/5 */
764 case 1: /* fucompp */
772 case 0: /* feni (287 only, just do nop here) */
773 case 1: /* fdisi (287 only, just do nop here) */
777 case 4: /* fsetpm (287 only, just do nop here) */
783 case 0x1d: /* fucomi */
785 case 0x1e: /* fcomi */
787 case 0x2a: /* fst sti */
789 case 0x2b: /* fstp sti */
791 case 0x2c: /* fucom st(i) */
793 case 0x2d: /* fucomp st(i) */
795 case 0x33: /* de/3 */
803 case 0x3c: /* df/4 */
811 case 0x3d: /* fucomip */
813 case 0x3e: /* fcomip */
815 case 0x10 ... 0x13: /* fcmovxx */
822 s->tb->cflags |= CF_TB_FP_USED;
825 /**************************/
828 case 0xc7: /* mov Ev, Iv */
832 ot = dflag ? OT_LONG : OT_WORD;
833 modrm = ldub_code(s->pc++);
834 parse_modrm(s, modrm);
839 ot = dflag ? OT_LONG : OT_WORD;
840 modrm = ldub_code(s->pc++);
841 mod = (modrm >> 6) & 3;
844 parse_modrm(s, modrm);
847 case 0xa0: /* mov EAX, Ov */
849 case 0xa2: /* mov Ov, EAX */
854 ot = dflag ? OT_LONG : OT_WORD;
856 insn_get(s, OT_LONG);
858 insn_get(s, OT_WORD);
860 case 0xd7: /* xlat */
862 case 0xb0 ... 0xb7: /* mov R, Ib */
863 insn_get(s, OT_BYTE);
865 case 0xb8 ... 0xbf: /* mov R, Iv */
866 ot = dflag ? OT_LONG : OT_WORD;
870 case 0x91 ... 0x97: /* xchg R, EAX */
873 /************************/
876 case 0xc1: /* shift Ev,imm */
878 case 0x1a4: /* shld imm */
879 case 0x1ac: /* shrd imm */
880 modrm = ldub_code(s->pc++);
881 parse_modrm(s, modrm);
885 /************************/
888 case 0xa4: /* movsS */
892 case 0xaa: /* stosS */
896 case 0xac: /* lodsS */
900 case 0xae: /* scasS */
904 case 0xa6: /* cmpsS */
908 case 0x6c: /* insS */
912 case 0x6e: /* outsS */
916 /************************/
934 /************************/
937 case 0xc2: /* ret im */
938 val = ldsw_code(s->pc);
941 gen_stack_update(s, val + (2 << s->dflag));
943 gen_op_andl_T0_ffff();
952 gb(s, 0x66); /* d16 */
953 gb(s, 0x8f); /* pop addr */
955 gl(s, CPU_FIELD_OFFSET(eip));
957 /* reset high bits of EIP */
958 gen_movw_addr_im(s, CPU_FIELD_OFFSET(eip) + 2, 0);
962 case 0xca: /* lret im */
963 case 0xcb: /* lret */
964 case 0xcf: /* iret */
965 case 0x9a: /* lcall im */
966 case 0xea: /* ljmp im */
969 case 0xe8: /* call im */
970 ot = dflag ? OT_LONG : OT_WORD;
971 val = insn_get(s, ot);
972 next_eip = s->pc - s->cs_base;
975 gb(s, 0x68); /* pushl imm */
978 gb(s, 0x66); /* pushw imm */
986 ot = dflag ? OT_LONG : OT_WORD;
987 val = insn_get(s, ot);
988 val += s->pc - s->cs_base;
993 case 0xeb: /* jmp Jb */
994 val = (int8_t)insn_get(s, OT_BYTE);
995 val += s->pc - s->cs_base;
1000 case 0x70 ... 0x7f: /* jcc Jb */
1001 val = (int8_t)insn_get(s, OT_BYTE);
1003 case 0x180 ... 0x18f: /* jcc Jv */
1005 val = insn_get(s, OT_LONG);
1007 val = (int16_t)insn_get(s, OT_WORD);
1010 next_eip = s->pc - s->cs_base;
1014 gen_jcc(s, b & 0xf, val, next_eip);
1017 /************************/
1019 case 0x9c: /* pushf */
1020 /* XXX: put specific code ? */
1021 goto unsupported_op;
1022 case 0x9d: /* popf */
1023 goto unsupported_op;
1025 case 0x9e: /* sahf */
1026 case 0x9f: /* lahf */
1027 case 0xf5: /* cmc */
1028 case 0xf8: /* clc */
1029 case 0xf9: /* stc */
1030 case 0xfc: /* cld */
1031 case 0xfd: /* std */
1034 /************************/
1035 /* bit operations */
1036 case 0x1ba: /* bt/bts/btr/btc Gv, im */
1037 ot = dflag ? OT_LONG : OT_WORD;
1038 modrm = ldub_code(s->pc++);
1039 op = (modrm >> 3) & 7;
1040 parse_modrm(s, modrm);
1046 /************************/
1048 case 0x27: /* daa */
1050 case 0x2f: /* das */
1052 case 0x37: /* aaa */
1054 case 0x3f: /* aas */
1056 case 0xd4: /* aam */
1059 case 0xd5: /* aad */
1062 /************************/
1064 case 0x90: /* nop */
1066 case 0x9b: /* fwait */
1067 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
1068 (HF_MP_MASK | HF_TS_MASK)) {
1069 goto unsupported_op;
1072 case 0xcc: /* int3 */
1073 goto unsupported_op;
1074 case 0xcd: /* int N */
1075 goto unsupported_op;
1076 case 0xce: /* into */
1077 goto unsupported_op;
1078 case 0xf1: /* icebp (undocumented, exits to external debugger) */
1079 goto unsupported_op;
1080 case 0xfa: /* cli */
1081 goto unsupported_op;
1082 case 0xfb: /* sti */
1083 goto unsupported_op;
1084 case 0x62: /* bound */
1085 modrm = ldub_code(s->pc++);
1086 mod = (modrm >> 6) & 3;
1089 parse_modrm(s, modrm);
1091 case 0x1c8 ... 0x1cf: /* bswap reg */
1093 case 0xd6: /* salc */
1095 case 0xe0: /* loopnz */
1096 case 0xe1: /* loopz */
1097 case 0xe2: /* loop */
1098 case 0xe3: /* jecxz */
1099 goto unsupported_op;
1101 case 0x130: /* wrmsr */
1102 case 0x132: /* rdmsr */
1103 goto unsupported_op;
1104 case 0x131: /* rdtsc */
1105 goto unsupported_op;
1106 case 0x1a2: /* cpuid */
1107 goto unsupported_op;
1108 case 0xf4: /* hlt */
1109 goto unsupported_op;
1111 goto unsupported_op;
1113 goto unsupported_op;
1114 case 0x108: /* invd */
1115 case 0x109: /* wbinvd */
1116 goto unsupported_op;
1117 case 0x63: /* arpl */
1118 goto unsupported_op;
1119 case 0x102: /* lar */
1120 case 0x103: /* lsl */
1121 goto unsupported_op;
1123 goto unsupported_op;
1124 case 0x120: /* mov reg, crN */
1125 case 0x122: /* mov crN, reg */
1126 goto unsupported_op;
1127 case 0x121: /* mov reg, drN */
1128 case 0x123: /* mov drN, reg */
1129 goto unsupported_op;
1130 case 0x106: /* clts */
1131 goto unsupported_op;
1136 /* just copy the code */
1138 /* no override yet */
1143 if (prefixes & PREFIX_REPZ)
1145 else if (prefixes & PREFIX_REPNZ)
1149 len = s->pc - pc_start_insn;
1150 for(i = 0; i < len; i++) {
1151 *s->gen_code_ptr++ = ldub_code(pc_start_insn + i);
1158 /* fall back to slower code gen necessary */
1163 #define GEN_CODE_MAX_SIZE 8192
1164 #define GEN_CODE_MAX_INSN_SIZE 512
1166 static inline int gen_intermediate_code_internal(CPUState *env,
1167 TranslationBlock *tb,
1168 uint8_t *gen_code_ptr,
1169 int *gen_code_size_ptr,
1173 DisasContext dc1, *dc = &dc1;
1174 uint8_t *pc_insn, *pc_start, *gen_code_end;
1178 if (env->nb_breakpoints > 0 ||
1179 env->singlestep_enabled)
1182 if (flags & (HF_TF_MASK | HF_ADDSEG_MASK |
1183 HF_SOFTMMU_MASK | HF_INHIBIT_IRQ_MASK))
1185 if (!(flags & HF_SS32_MASK))
1187 gen_code_end = gen_code_ptr +
1188 GEN_CODE_MAX_SIZE - GEN_CODE_MAX_INSN_SIZE;
1189 dc->gen_code_ptr = gen_code_ptr;
1190 dc->gen_code_start = gen_code_ptr;
1192 /* generate intermediate code */
1193 pc_start = (uint8_t *)tb->pc;
1194 cs_base = (uint8_t *)tb->cs_base;
1196 dc->cs_base = cs_base;
1197 dc->pe = (flags >> HF_PE_SHIFT) & 1;
1198 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
1200 dc->vm86 = (flags >> VM_SHIFT) & 1;
1201 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
1202 dc->iopl = (flags >> IOPL_SHIFT) & 3;
1210 ret = disas_insn(dc);
1212 /* unsupported insn */
1213 if (dc->pc == pc_start) {
1214 /* if first instruction, signal that no copying was done */
1217 gen_jmp(dc, dc->pc - dc->cs_base);
1222 /* search pc mode */
1223 if (tc_ptr < dc->gen_code_ptr) {
1224 env->eip = pc_insn - cs_base;
1228 /* stop translation if indicated */
1231 /* if too long translation, stop generation */
1232 if (dc->gen_code_ptr >= gen_code_end ||
1233 (dc->pc - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
1234 gen_jmp(dc, dc->pc - dc->cs_base);
1241 fprintf(logfile, "----------------\n");
1242 fprintf(logfile, "IN: COPY: %s fpu=%d\n",
1243 lookup_symbol(pc_start),
1244 tb->cflags & CF_TB_FP_USED ? 1 : 0);
1245 disas(logfile, pc_start, dc->pc - pc_start, 0, !dc->code32);
1246 fprintf(logfile, "\n");
1251 *gen_code_size_ptr = dc->gen_code_ptr - dc->gen_code_start;
1252 tb->size = dc->pc - pc_start;
1253 tb->cflags |= CF_CODE_COPY;
1260 /* generate code by just copying data. Return -1 if cannot generate
1261 any code. Return 0 if code was generated */
1262 int cpu_gen_code_copy(CPUState *env, TranslationBlock *tb,
1263 int max_code_size, int *gen_code_size_ptr)
1265 /* generate machine code */
1266 tb->tb_next_offset[0] = 0xffff;
1267 tb->tb_next_offset[1] = 0xffff;
1268 #ifdef USE_DIRECT_JUMP
1269 /* the following two entries are optional (only used for string ops) */
1270 tb->tb_jmp_offset[2] = 0xffff;
1271 tb->tb_jmp_offset[3] = 0xffff;
1273 return gen_intermediate_code_internal(env, tb,
1274 tb->tc_ptr, gen_code_size_ptr,
1278 static uint8_t dummy_gen_code_buf[GEN_CODE_MAX_SIZE];
1280 int cpu_restore_state_copy(TranslationBlock *tb,
1281 CPUState *env, unsigned long searched_pc,
1284 struct ucontext *uc = puc;
1287 /* find opc index corresponding to search_pc */
1288 if (searched_pc < (unsigned long)tb->tc_ptr)
1290 searched_pc = searched_pc - (long)tb->tc_ptr + (long)dummy_gen_code_buf;
1291 ret = gen_intermediate_code_internal(env, tb,
1292 dummy_gen_code_buf, NULL,
1293 1, (uint8_t *)searched_pc);
1296 /* restore all the CPU state from the CPU context from the
1297 signal. The FPU context stays in the host CPU. */
1299 env->regs[R_EAX] = uc->uc_mcontext.gregs[REG_EAX];
1300 env->regs[R_ECX] = uc->uc_mcontext.gregs[REG_ECX];
1301 env->regs[R_EDX] = uc->uc_mcontext.gregs[REG_EDX];
1302 env->regs[R_EBX] = uc->uc_mcontext.gregs[REG_EBX];
1303 env->regs[R_ESP] = uc->uc_mcontext.gregs[REG_ESP];
1304 env->regs[R_EBP] = uc->uc_mcontext.gregs[REG_EBP];
1305 env->regs[R_ESI] = uc->uc_mcontext.gregs[REG_ESI];
1306 env->regs[R_EDI] = uc->uc_mcontext.gregs[REG_EDI];
1307 eflags = uc->uc_mcontext.gregs[REG_EFL];
1308 env->df = 1 - (2 * ((eflags >> 10) & 1));
1309 env->cc_src = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1310 env->cc_op = CC_OP_EFLAGS;
1314 #endif /* USE_CODE_COPY */