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
37 #include <sys/ucontext.h>
39 extern char exec_loop;
49 #define PREFIX_REPZ 0x01
50 #define PREFIX_REPNZ 0x02
51 #define PREFIX_LOCK 0x04
52 #define PREFIX_DATA 0x08
53 #define PREFIX_ADR 0x10
55 typedef struct DisasContext {
56 /* current insn context */
57 int override; /* -1 if no override */
60 uint8_t *pc; /* pc = eip + cs_base */
61 int is_jmp; /* 1 = means jump (stop translation), 2 means CPU
62 static state change (stop translation) */
64 uint8_t *gen_code_ptr;
65 uint8_t *gen_code_start;
67 /* current block context */
68 uint8_t *cs_base; /* base of CS segment */
69 int pe; /* protected mode */
70 int code32; /* 32 bit code segment */
71 int f_st; /* currently unused */
72 int vm86; /* vm86 mode */
76 struct TranslationBlock *tb;
79 #define CPU_FIELD_OFFSET(field) offsetof(CPUState, field)
81 #define CPU_SEG 0x64 /* fs override */
83 static inline void gb(DisasContext *s, uint32_t val)
85 *s->gen_code_ptr++ = val;
88 static inline void gw(DisasContext *s, uint32_t val)
90 *s->gen_code_ptr++ = val;
91 *s->gen_code_ptr++ = val >> 8;
94 static inline void gl(DisasContext *s, uint32_t val)
96 *s->gen_code_ptr++ = val;
97 *s->gen_code_ptr++ = val >> 8;
98 *s->gen_code_ptr++ = val >> 16;
99 *s->gen_code_ptr++ = val >> 24;
102 static inline void gjmp(DisasContext *s, long val)
104 gb(s, 0xe9); /* jmp */
105 gl(s, val - (long)(s->gen_code_ptr + 4));
108 static inline void gen_movl_addr_im(DisasContext *s,
109 uint32_t addr, uint32_t val)
111 gb(s, CPU_SEG); /* seg movl im, addr */
118 static inline void gen_movw_addr_im(DisasContext *s,
119 uint32_t addr, uint32_t val)
121 gb(s, CPU_SEG); /* seg movl im, addr */
130 static void gen_jmp(DisasContext *s, uint32_t target_eip)
132 TranslationBlock *tb = s->tb;
134 gb(s, 0xe9); /* jmp */
135 tb->tb_jmp_offset[0] = s->gen_code_ptr - s->gen_code_start;
138 tb->tb_next_offset[0] = s->gen_code_ptr - s->gen_code_start;
139 gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), target_eip);
140 gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb);
141 gjmp(s, (long)&exec_loop);
146 static void gen_jcc(DisasContext *s, int op,
147 uint32_t target_eip, uint32_t next_eip)
149 TranslationBlock *tb = s->tb;
151 gb(s, 0x0f); /* jcc */
153 tb->tb_jmp_offset[0] = s->gen_code_ptr - s->gen_code_start;
155 gb(s, 0xe9); /* jmp */
156 tb->tb_jmp_offset[1] = s->gen_code_ptr - s->gen_code_start;
159 tb->tb_next_offset[0] = s->gen_code_ptr - s->gen_code_start;
160 gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), target_eip);
161 gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb);
162 gjmp(s, (long)&exec_loop);
164 tb->tb_next_offset[1] = s->gen_code_ptr - s->gen_code_start;
165 gen_movl_addr_im(s, CPU_FIELD_OFFSET(eip), next_eip);
166 gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), (uint32_t)tb | 1);
167 gjmp(s, (long)&exec_loop);
172 static void gen_eob(DisasContext *s)
174 gen_movl_addr_im(s, CPU_FIELD_OFFSET(tmp0), 0);
175 gjmp(s, (long)&exec_loop);
180 static inline void gen_lea_modrm(DisasContext *s, int modrm)
188 mod = (modrm >> 6) & 3;
200 code = ldub_code(s->pc++);
201 scale = (code >> 6) & 3;
202 index = (code >> 3) & 7;
210 disp = ldl_code(s->pc);
217 disp = (int8_t)ldub_code(s->pc++);
221 disp = ldl_code(s->pc);
230 disp = lduw_code(s->pc);
237 disp = (int8_t)ldub_code(s->pc++);
241 disp = lduw_code(s->pc);
248 static inline void parse_modrm(DisasContext *s, int modrm)
250 if ((modrm & 0xc0) != 0xc0)
251 gen_lea_modrm(s, modrm);
254 static inline uint32_t insn_get(DisasContext *s, int ot)
260 ret = ldub_code(s->pc);
264 ret = lduw_code(s->pc);
269 ret = ldl_code(s->pc);
276 /* convert one instruction. s->is_jmp is set if the translation must
278 static int disas_insn(DisasContext *s)
280 uint8_t *pc_start, *pc_tmp, *pc_start_insn;
281 int b, prefixes, aflag, dflag, next_eip, val;
283 int modrm, mod, op, rm;
291 b = ldub_code(s->pc);
296 prefixes |= PREFIX_REPZ;
299 prefixes |= PREFIX_REPNZ;
302 prefixes |= PREFIX_LOCK;
323 prefixes |= PREFIX_DATA;
326 prefixes |= PREFIX_ADR;
330 if (prefixes & PREFIX_DATA)
332 if (prefixes & PREFIX_ADR)
335 s->prefix = prefixes;
339 /* lock generation */
340 if (prefixes & PREFIX_LOCK)
342 if (s->override == R_FS || s->override == R_GS || s->override == R_CS)
345 pc_start_insn = s->pc - 1;
346 /* now check op code */
350 /**************************/
351 /* extended op code */
352 b = ldub_code(s->pc++) | 0x100;
355 /**************************/
372 ot = dflag ? OT_LONG : OT_WORD;
375 case 0: /* OP Ev, Gv */
376 modrm = ldub_code(s->pc++);
377 parse_modrm(s, modrm);
379 case 1: /* OP Gv, Ev */
380 modrm = ldub_code(s->pc++);
381 parse_modrm(s, modrm);
383 case 2: /* OP A, Iv */
390 case 0x80: /* GRP1 */
397 ot = dflag ? OT_LONG : OT_WORD;
399 modrm = ldub_code(s->pc++);
400 parse_modrm(s, modrm);
409 insn_get(s, OT_BYTE);
415 /**************************/
416 /* inc, dec, and other misc arith */
417 case 0x40 ... 0x47: /* inc Gv */
419 case 0x48 ... 0x4f: /* dec Gv */
421 case 0xf6: /* GRP3 */
426 ot = dflag ? OT_LONG : OT_WORD;
428 modrm = ldub_code(s->pc++);
429 op = (modrm >> 3) & 7;
430 parse_modrm(s, modrm);
453 case 0xfe: /* GRP4 */
454 case 0xff: /* GRP5 */
458 ot = dflag ? OT_LONG : OT_WORD;
460 modrm = ldub_code(s->pc++);
461 mod = (modrm >> 6) & 3;
462 op = (modrm >> 3) & 7;
463 if (op >= 2 && b == 0xfe) {
467 parse_modrm(s, modrm);
474 case 2: /* call Ev */
475 /* XXX: optimize and handle MEM exceptions specifically
476 fs movl %eax, regs[0]
482 case 3: /* lcall Ev */
485 /* XXX: optimize and handle MEM exceptions specifically
486 fs movl %eax, regs[0]
491 case 5: /* ljmp Ev */
493 case 6: /* push Ev */
499 case 0xa8: /* test eAX, Iv */
504 ot = dflag ? OT_LONG : OT_WORD;
508 case 0x98: /* CWDE/CBW */
510 case 0x99: /* CDQ/CWD */
512 case 0x1af: /* imul Gv, Ev */
513 case 0x69: /* imul Gv, Ev, I */
515 ot = dflag ? OT_LONG : OT_WORD;
516 modrm = ldub_code(s->pc++);
517 parse_modrm(s, modrm);
520 } else if (b == 0x6b) {
521 insn_get(s, OT_BYTE);
526 case 0x84: /* test Ev, Gv */
530 case 0x1c1: /* xadd Ev, Gv */
533 case 0x1b1: /* cmpxchg Ev, Gv */
535 case 0x8f: /* pop Ev */
538 case 0x89: /* mov Gv, Ev */
541 case 0x8b: /* mov Ev, Gv */
543 case 0x1b6: /* movzbS Gv, Eb */
544 case 0x1b7: /* movzwS Gv, Eb */
545 case 0x1be: /* movsbS Gv, Eb */
546 case 0x1bf: /* movswS Gv, Eb */
549 case 0x87: /* xchg Ev, Gv */
552 case 0xd1: /* shift Ev,1 */
555 case 0xd3: /* shift Ev,cl */
557 case 0x1a5: /* shld cl */
558 case 0x1ad: /* shrd cl */
560 case 0x190 ... 0x19f: /* setcc Gv */
562 /* XXX: emulate cmov if not available ? */
563 case 0x140 ... 0x14f: /* cmov Gv, Ev */
565 case 0x1a3: /* bt Gv, Ev */
566 case 0x1ab: /* bts */
567 case 0x1b3: /* btr */
568 case 0x1bb: /* btc */
570 case 0x1bc: /* bsf */
571 case 0x1bd: /* bsr */
573 modrm = ldub_code(s->pc++);
574 parse_modrm(s, modrm);
577 case 0x1c7: /* cmpxchg8b */
578 modrm = ldub_code(s->pc++);
579 mod = (modrm >> 6) & 3;
582 parse_modrm(s, modrm);
585 /**************************/
587 case 0x50 ... 0x57: /* push */
588 case 0x58 ... 0x5f: /* pop */
589 case 0x60: /* pusha */
590 case 0x61: /* popa */
593 case 0x68: /* push Iv */
595 ot = dflag ? OT_LONG : OT_WORD;
599 insn_get(s, OT_BYTE);
601 case 0xc8: /* enter */
606 case 0xc9: /* leave */
609 case 0x06: /* push es */
610 case 0x0e: /* push cs */
611 case 0x16: /* push ss */
612 case 0x1e: /* push ds */
614 push segs[n].selector
617 case 0x1a0: /* push fs */
618 case 0x1a8: /* push gs */
620 case 0x07: /* pop es */
621 case 0x17: /* pop ss */
622 case 0x1f: /* pop ds */
624 case 0x1a1: /* pop fs */
625 case 0x1a9: /* pop gs */
627 case 0x8e: /* mov seg, Gv */
630 movl segs[].selector, r
635 case 0x8c: /* mov Gv, seg */
637 case 0xc4: /* les Gv */
640 case 0xc5: /* lds Gv */
643 case 0x1b2: /* lss Gv */
646 case 0x1b4: /* lfs Gv */
649 case 0x1b5: /* lgs Gv */
653 /************************/
657 /* currently not stable enough */
660 if (s->flags & (HF_EM_MASK | HF_TS_MASK))
664 /* for testing FPU context switch */
667 count = (count + 1) % 3;
672 modrm = ldub_code(s->pc++);
673 mod = (modrm >> 6) & 3;
675 op = ((b & 7) << 3) | ((modrm >> 3) & 7);
678 parse_modrm(s, modrm);
680 case 0x00 ... 0x07: /* fxxxs */
681 case 0x10 ... 0x17: /* fixxxl */
682 case 0x20 ... 0x27: /* fxxxl */
683 case 0x30 ... 0x37: /* fixxx */
685 case 0x08: /* flds */
686 case 0x0a: /* fsts */
687 case 0x0b: /* fstps */
688 case 0x18: /* fildl */
689 case 0x1a: /* fistl */
690 case 0x1b: /* fistpl */
691 case 0x28: /* fldl */
692 case 0x2a: /* fstl */
693 case 0x2b: /* fstpl */
694 case 0x38: /* filds */
695 case 0x3a: /* fists */
696 case 0x3b: /* fistps */
697 case 0x0c: /* fldenv mem */
698 case 0x0d: /* fldcw mem */
699 case 0x0e: /* fnstenv mem */
700 case 0x0f: /* fnstcw mem */
701 case 0x1d: /* fldt mem */
702 case 0x1f: /* fstpt mem */
703 case 0x2c: /* frstor mem */
704 case 0x2e: /* fnsave mem */
705 case 0x2f: /* fnstsw mem */
706 case 0x3c: /* fbld */
707 case 0x3e: /* fbstp */
708 case 0x3d: /* fildll */
709 case 0x3f: /* fistpll */
715 /* register float ops */
717 case 0x08: /* fld sti */
718 case 0x09: /* fxchg sti */
720 case 0x0a: /* grp d9/2 */
728 case 0x0c: /* grp d9/4 */
739 case 0x0d: /* grp d9/5 */
753 case 0x0e: /* grp d9/6 */
755 case 0x0f: /* grp d9/7 */
757 case 0x00: case 0x01: case 0x04 ... 0x07: /* fxxx st, sti */
758 case 0x20: case 0x21: case 0x24 ... 0x27: /* fxxx sti, st */
759 case 0x30: case 0x31: case 0x34 ... 0x37: /* fxxxp sti, st */
761 case 0x02: /* fcom */
763 case 0x03: /* fcomp */
765 case 0x15: /* da/5 */
767 case 1: /* fucompp */
775 case 0: /* feni (287 only, just do nop here) */
776 case 1: /* fdisi (287 only, just do nop here) */
780 case 4: /* fsetpm (287 only, just do nop here) */
786 case 0x1d: /* fucomi */
788 case 0x1e: /* fcomi */
790 case 0x2a: /* fst sti */
792 case 0x2b: /* fstp sti */
794 case 0x2c: /* fucom st(i) */
796 case 0x2d: /* fucomp st(i) */
798 case 0x33: /* de/3 */
806 case 0x3c: /* df/4 */
814 case 0x3d: /* fucomip */
816 case 0x3e: /* fcomip */
818 case 0x10 ... 0x13: /* fcmovxx */
825 s->tb->cflags |= CF_TB_FP_USED;
828 /**************************/
831 case 0xc7: /* mov Ev, Iv */
835 ot = dflag ? OT_LONG : OT_WORD;
836 modrm = ldub_code(s->pc++);
837 parse_modrm(s, modrm);
842 ot = dflag ? OT_LONG : OT_WORD;
843 modrm = ldub_code(s->pc++);
844 mod = (modrm >> 6) & 3;
847 parse_modrm(s, modrm);
850 case 0xa0: /* mov EAX, Ov */
852 case 0xa2: /* mov Ov, EAX */
857 ot = dflag ? OT_LONG : OT_WORD;
859 insn_get(s, OT_LONG);
861 insn_get(s, OT_WORD);
863 case 0xd7: /* xlat */
865 case 0xb0 ... 0xb7: /* mov R, Ib */
866 insn_get(s, OT_BYTE);
868 case 0xb8 ... 0xbf: /* mov R, Iv */
869 ot = dflag ? OT_LONG : OT_WORD;
873 case 0x91 ... 0x97: /* xchg R, EAX */
876 /************************/
879 case 0xc1: /* shift Ev,imm */
881 case 0x1a4: /* shld imm */
882 case 0x1ac: /* shrd imm */
883 modrm = ldub_code(s->pc++);
884 parse_modrm(s, modrm);
888 /************************/
891 case 0xa4: /* movsS */
895 case 0xaa: /* stosS */
899 case 0xac: /* lodsS */
903 case 0xae: /* scasS */
907 case 0xa6: /* cmpsS */
911 case 0x6c: /* insS */
915 case 0x6e: /* outsS */
919 /************************/
937 /************************/
940 case 0xc2: /* ret im */
941 val = ldsw_code(s->pc);
944 gen_stack_update(s, val + (2 << s->dflag));
946 gen_op_andl_T0_ffff();
955 gb(s, 0x66); /* d16 */
956 gb(s, 0x8f); /* pop addr */
958 gl(s, CPU_FIELD_OFFSET(eip));
960 /* reset high bits of EIP */
961 gen_movw_addr_im(s, CPU_FIELD_OFFSET(eip) + 2, 0);
965 case 0xca: /* lret im */
966 case 0xcb: /* lret */
967 case 0xcf: /* iret */
968 case 0x9a: /* lcall im */
969 case 0xea: /* ljmp im */
972 case 0xe8: /* call im */
973 ot = dflag ? OT_LONG : OT_WORD;
974 val = insn_get(s, ot);
975 next_eip = s->pc - s->cs_base;
978 gb(s, 0x68); /* pushl imm */
981 gb(s, 0x66); /* pushw imm */
989 ot = dflag ? OT_LONG : OT_WORD;
990 val = insn_get(s, ot);
991 val += s->pc - s->cs_base;
996 case 0xeb: /* jmp Jb */
997 val = (int8_t)insn_get(s, OT_BYTE);
998 val += s->pc - s->cs_base;
1003 case 0x70 ... 0x7f: /* jcc Jb */
1004 val = (int8_t)insn_get(s, OT_BYTE);
1006 case 0x180 ... 0x18f: /* jcc Jv */
1008 val = insn_get(s, OT_LONG);
1010 val = (int16_t)insn_get(s, OT_WORD);
1013 next_eip = s->pc - s->cs_base;
1017 gen_jcc(s, b & 0xf, val, next_eip);
1020 /************************/
1022 case 0x9c: /* pushf */
1023 /* XXX: put specific code ? */
1024 goto unsupported_op;
1025 case 0x9d: /* popf */
1026 goto unsupported_op;
1028 case 0x9e: /* sahf */
1029 case 0x9f: /* lahf */
1030 case 0xf5: /* cmc */
1031 case 0xf8: /* clc */
1032 case 0xf9: /* stc */
1033 case 0xfc: /* cld */
1034 case 0xfd: /* std */
1037 /************************/
1038 /* bit operations */
1039 case 0x1ba: /* bt/bts/btr/btc Gv, im */
1040 ot = dflag ? OT_LONG : OT_WORD;
1041 modrm = ldub_code(s->pc++);
1042 op = (modrm >> 3) & 7;
1043 parse_modrm(s, modrm);
1049 /************************/
1051 case 0x27: /* daa */
1053 case 0x2f: /* das */
1055 case 0x37: /* aaa */
1057 case 0x3f: /* aas */
1059 case 0xd4: /* aam */
1062 case 0xd5: /* aad */
1065 /************************/
1067 case 0x90: /* nop */
1069 case 0x9b: /* fwait */
1070 if ((s->flags & (HF_MP_MASK | HF_TS_MASK)) ==
1071 (HF_MP_MASK | HF_TS_MASK)) {
1072 goto unsupported_op;
1075 case 0xcc: /* int3 */
1076 goto unsupported_op;
1077 case 0xcd: /* int N */
1078 goto unsupported_op;
1079 case 0xce: /* into */
1080 goto unsupported_op;
1081 case 0xf1: /* icebp (undocumented, exits to external debugger) */
1082 goto unsupported_op;
1083 case 0xfa: /* cli */
1084 goto unsupported_op;
1085 case 0xfb: /* sti */
1086 goto unsupported_op;
1087 case 0x62: /* bound */
1088 modrm = ldub_code(s->pc++);
1089 mod = (modrm >> 6) & 3;
1092 parse_modrm(s, modrm);
1094 case 0x1c8 ... 0x1cf: /* bswap reg */
1096 case 0xd6: /* salc */
1098 case 0xe0: /* loopnz */
1099 case 0xe1: /* loopz */
1100 case 0xe2: /* loop */
1101 case 0xe3: /* jecxz */
1102 goto unsupported_op;
1104 case 0x130: /* wrmsr */
1105 case 0x132: /* rdmsr */
1106 goto unsupported_op;
1107 case 0x131: /* rdtsc */
1108 goto unsupported_op;
1109 case 0x1a2: /* cpuid */
1110 goto unsupported_op;
1111 case 0xf4: /* hlt */
1112 goto unsupported_op;
1114 goto unsupported_op;
1116 goto unsupported_op;
1117 case 0x108: /* invd */
1118 case 0x109: /* wbinvd */
1119 goto unsupported_op;
1120 case 0x63: /* arpl */
1121 goto unsupported_op;
1122 case 0x102: /* lar */
1123 case 0x103: /* lsl */
1124 goto unsupported_op;
1126 goto unsupported_op;
1127 case 0x120: /* mov reg, crN */
1128 case 0x122: /* mov crN, reg */
1129 goto unsupported_op;
1130 case 0x121: /* mov reg, drN */
1131 case 0x123: /* mov drN, reg */
1132 goto unsupported_op;
1133 case 0x106: /* clts */
1134 goto unsupported_op;
1139 /* just copy the code */
1141 /* no override yet */
1146 if (prefixes & PREFIX_REPZ)
1148 else if (prefixes & PREFIX_REPNZ)
1152 len = s->pc - pc_start_insn;
1153 for(i = 0; i < len; i++) {
1154 *s->gen_code_ptr++ = ldub_code(pc_start_insn + i);
1161 /* fall back to slower code gen necessary */
1166 #define GEN_CODE_MAX_SIZE 8192
1167 #define GEN_CODE_MAX_INSN_SIZE 512
1169 static inline int gen_intermediate_code_internal(CPUState *env,
1170 TranslationBlock *tb,
1171 uint8_t *gen_code_ptr,
1172 int *gen_code_size_ptr,
1176 DisasContext dc1, *dc = &dc1;
1177 uint8_t *pc_insn, *pc_start, *gen_code_end;
1181 if (env->nb_breakpoints > 0 ||
1182 env->singlestep_enabled)
1185 if (flags & (HF_TF_MASK | HF_ADDSEG_MASK |
1186 HF_SOFTMMU_MASK | HF_INHIBIT_IRQ_MASK))
1188 if (!(flags & HF_SS32_MASK))
1190 gen_code_end = gen_code_ptr +
1191 GEN_CODE_MAX_SIZE - GEN_CODE_MAX_INSN_SIZE;
1192 dc->gen_code_ptr = gen_code_ptr;
1193 dc->gen_code_start = gen_code_ptr;
1195 /* generate intermediate code */
1196 pc_start = (uint8_t *)tb->pc;
1197 cs_base = (uint8_t *)tb->cs_base;
1199 dc->cs_base = cs_base;
1200 dc->pe = (flags >> HF_PE_SHIFT) & 1;
1201 dc->code32 = (flags >> HF_CS32_SHIFT) & 1;
1203 dc->vm86 = (flags >> VM_SHIFT) & 1;
1204 dc->cpl = (flags >> HF_CPL_SHIFT) & 3;
1205 dc->iopl = (flags >> IOPL_SHIFT) & 3;
1213 ret = disas_insn(dc);
1215 /* unsupported insn */
1216 if (dc->pc == pc_start) {
1217 /* if first instruction, signal that no copying was done */
1220 gen_jmp(dc, dc->pc - dc->cs_base);
1225 /* search pc mode */
1226 if (tc_ptr < dc->gen_code_ptr) {
1227 env->eip = pc_insn - cs_base;
1231 /* stop translation if indicated */
1234 /* if too long translation, stop generation */
1235 if (dc->gen_code_ptr >= gen_code_end ||
1236 (dc->pc - pc_start) >= (TARGET_PAGE_SIZE - 32)) {
1237 gen_jmp(dc, dc->pc - dc->cs_base);
1243 if (loglevel & CPU_LOG_TB_IN_ASM) {
1244 fprintf(logfile, "----------------\n");
1245 fprintf(logfile, "IN: COPY: %s fpu=%d\n",
1246 lookup_symbol(pc_start),
1247 tb->cflags & CF_TB_FP_USED ? 1 : 0);
1248 disas(logfile, pc_start, dc->pc - pc_start, 0, !dc->code32);
1249 fprintf(logfile, "\n");
1254 *gen_code_size_ptr = dc->gen_code_ptr - dc->gen_code_start;
1255 tb->size = dc->pc - pc_start;
1256 tb->cflags |= CF_CODE_COPY;
1263 /* generate code by just copying data. Return -1 if cannot generate
1264 any code. Return 0 if code was generated */
1265 int cpu_gen_code_copy(CPUState *env, TranslationBlock *tb,
1266 int max_code_size, int *gen_code_size_ptr)
1268 /* generate machine code */
1269 tb->tb_next_offset[0] = 0xffff;
1270 tb->tb_next_offset[1] = 0xffff;
1271 #ifdef USE_DIRECT_JUMP
1272 /* the following two entries are optional (only used for string ops) */
1273 tb->tb_jmp_offset[2] = 0xffff;
1274 tb->tb_jmp_offset[3] = 0xffff;
1276 return gen_intermediate_code_internal(env, tb,
1277 tb->tc_ptr, gen_code_size_ptr,
1281 static uint8_t dummy_gen_code_buf[GEN_CODE_MAX_SIZE];
1283 int cpu_restore_state_copy(TranslationBlock *tb,
1284 CPUState *env, unsigned long searched_pc,
1287 struct ucontext *uc = puc;
1290 /* find opc index corresponding to search_pc */
1291 if (searched_pc < (unsigned long)tb->tc_ptr)
1293 searched_pc = searched_pc - (long)tb->tc_ptr + (long)dummy_gen_code_buf;
1294 ret = gen_intermediate_code_internal(env, tb,
1295 dummy_gen_code_buf, NULL,
1296 1, (uint8_t *)searched_pc);
1299 /* restore all the CPU state from the CPU context from the
1300 signal. The FPU context stays in the host CPU. */
1302 env->regs[R_EAX] = uc->uc_mcontext.gregs[REG_EAX];
1303 env->regs[R_ECX] = uc->uc_mcontext.gregs[REG_ECX];
1304 env->regs[R_EDX] = uc->uc_mcontext.gregs[REG_EDX];
1305 env->regs[R_EBX] = uc->uc_mcontext.gregs[REG_EBX];
1306 env->regs[R_ESP] = uc->uc_mcontext.gregs[REG_ESP];
1307 env->regs[R_EBP] = uc->uc_mcontext.gregs[REG_EBP];
1308 env->regs[R_ESI] = uc->uc_mcontext.gregs[REG_ESI];
1309 env->regs[R_EDI] = uc->uc_mcontext.gregs[REG_EDI];
1310 eflags = uc->uc_mcontext.gregs[REG_EFL];
1311 env->df = 1 - (2 * ((eflags >> 10) & 1));
1312 env->cc_src = eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
1313 env->cc_op = CC_OP_EFLAGS;
1317 #endif /* USE_CODE_COPY */