Commit 5a91de8c902e8de43d80df2db6f056710d414e56

Authored by bellard
1 parent e3b32540

precise exception support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@189 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 137 additions and 49 deletions
translate-i386.c
@@ -160,7 +160,7 @@ enum { @@ -160,7 +160,7 @@ enum {
160 }; 160 };
161 161
162 enum { 162 enum {
163 -#define DEF(s, n) INDEX_op_ ## s, 163 +#define DEF(s, n, copy_size) INDEX_op_ ## s,
164 #include "opc-i386.h" 164 #include "opc-i386.h"
165 #undef DEF 165 #undef DEF
166 NB_OPS, 166 NB_OPS,
@@ -1215,9 +1215,13 @@ static void gen_setcc(DisasContext *s, int b) @@ -1215,9 +1215,13 @@ static void gen_setcc(DisasContext *s, int b)
1215 } 1215 }
1216 1216
1217 /* move T0 to seg_reg and compute if the CPU state may change */ 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) 1218 +static void gen_movl_seg_T0(DisasContext *s, int seg_reg, unsigned int cur_eip)
1219 { 1219 {
1220 - gen_op_movl_seg_T0(seg_reg); 1220 + if (!s->vm86)
  1221 + gen_op_movl_seg_T0(seg_reg, cur_eip);
  1222 + else
  1223 + gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[seg_reg]),
  1224 + offsetof(CPUX86State,seg_cache[seg_reg].base));
1221 if (!s->addseg && seg_reg < R_FS) 1225 if (!s->addseg && seg_reg < R_FS)
1222 s->is_jmp = 2; /* abort translation because the register may 1226 s->is_jmp = 2; /* abort translation because the register may
1223 have a non zero base */ 1227 have a non zero base */
@@ -1374,6 +1378,18 @@ static void gen_exception(DisasContext *s, int trapno, unsigned int cur_eip) @@ -1374,6 +1378,18 @@ static void gen_exception(DisasContext *s, int trapno, unsigned int cur_eip)
1374 s->is_jmp = 1; 1378 s->is_jmp = 1;
1375 } 1379 }
1376 1380
  1381 +/* an interrupt is different from an exception because of the
  1382 + priviledge checks */
  1383 +static void gen_interrupt(DisasContext *s, int intno,
  1384 + unsigned int cur_eip, unsigned int next_eip)
  1385 +{
  1386 + if (s->cc_op != CC_OP_DYNAMIC)
  1387 + gen_op_set_cc_op(s->cc_op);
  1388 + gen_op_jmp_im(cur_eip);
  1389 + gen_op_raise_interrupt(intno, next_eip);
  1390 + s->is_jmp = 1;
  1391 +}
  1392 +
1377 /* generate a jump to eip. No segment change must happen before as a 1393 /* generate a jump to eip. No segment change must happen before as a
1378 direct call to the next block may occur */ 1394 direct call to the next block may occur */
1379 static void gen_jmp(DisasContext *s, unsigned int eip) 1395 static void gen_jmp(DisasContext *s, unsigned int eip)
@@ -1650,28 +1666,28 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -1650,28 +1666,28 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
1650 case 6: /* div */ 1666 case 6: /* div */
1651 switch(ot) { 1667 switch(ot) {
1652 case OT_BYTE: 1668 case OT_BYTE:
1653 - gen_op_divb_AL_T0(); 1669 + gen_op_divb_AL_T0(pc_start - s->cs_base);
1654 break; 1670 break;
1655 case OT_WORD: 1671 case OT_WORD:
1656 - gen_op_divw_AX_T0(); 1672 + gen_op_divw_AX_T0(pc_start - s->cs_base);
1657 break; 1673 break;
1658 default: 1674 default:
1659 case OT_LONG: 1675 case OT_LONG:
1660 - gen_op_divl_EAX_T0(); 1676 + gen_op_divl_EAX_T0(pc_start - s->cs_base);
1661 break; 1677 break;
1662 } 1678 }
1663 break; 1679 break;
1664 case 7: /* idiv */ 1680 case 7: /* idiv */
1665 switch(ot) { 1681 switch(ot) {
1666 case OT_BYTE: 1682 case OT_BYTE:
1667 - gen_op_idivb_AL_T0(); 1683 + gen_op_idivb_AL_T0(pc_start - s->cs_base);
1668 break; 1684 break;
1669 case OT_WORD: 1685 case OT_WORD:
1670 - gen_op_idivw_AX_T0(); 1686 + gen_op_idivw_AX_T0(pc_start - s->cs_base);
1671 break; 1687 break;
1672 default: 1688 default:
1673 case OT_LONG: 1689 case OT_LONG:
1674 - gen_op_idivl_EAX_T0(); 1690 + gen_op_idivl_EAX_T0(pc_start - s->cs_base);
1675 break; 1691 break;
1676 } 1692 }
1677 break; 1693 break;
@@ -1738,7 +1754,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -1738,7 +1754,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
1738 gen_op_ld_T1_A0[ot](); 1754 gen_op_ld_T1_A0[ot]();
1739 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); 1755 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1740 gen_op_lduw_T0_A0(); 1756 gen_op_lduw_T0_A0();
1741 - gen_movl_seg_T0(s, R_CS); 1757 + gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
1742 gen_op_movl_T0_T1(); 1758 gen_op_movl_T0_T1();
1743 gen_op_jmp_T0(); 1759 gen_op_jmp_T0();
1744 s->is_jmp = 1; 1760 s->is_jmp = 1;
@@ -1753,7 +1769,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -1753,7 +1769,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
1753 gen_op_ld_T1_A0[ot](); 1769 gen_op_ld_T1_A0[ot]();
1754 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); 1770 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
1755 gen_op_lduw_T0_A0(); 1771 gen_op_lduw_T0_A0();
1756 - gen_movl_seg_T0(s, R_CS); 1772 + gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
1757 gen_op_movl_T0_T1(); 1773 gen_op_movl_T0_T1();
1758 gen_op_jmp_T0(); 1774 gen_op_jmp_T0();
1759 s->is_jmp = 1; 1775 s->is_jmp = 1;
@@ -1970,13 +1986,13 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -1970,13 +1986,13 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
1970 case 0x17: /* pop ss */ 1986 case 0x17: /* pop ss */
1971 case 0x1f: /* pop ds */ 1987 case 0x1f: /* pop ds */
1972 gen_pop_T0(s); 1988 gen_pop_T0(s);
1973 - gen_movl_seg_T0(s, b >> 3); 1989 + gen_movl_seg_T0(s, b >> 3, pc_start - s->cs_base);
1974 gen_pop_update(s); 1990 gen_pop_update(s);
1975 break; 1991 break;
1976 case 0x1a1: /* pop fs */ 1992 case 0x1a1: /* pop fs */
1977 case 0x1a9: /* pop gs */ 1993 case 0x1a9: /* pop gs */
1978 gen_pop_T0(s); 1994 gen_pop_T0(s);
1979 - gen_movl_seg_T0(s, (b >> 3) & 7); 1995 + gen_movl_seg_T0(s, (b >> 3) & 7, pc_start - s->cs_base);
1980 gen_pop_update(s); 1996 gen_pop_update(s);
1981 break; 1997 break;
1982 1998
@@ -2030,7 +2046,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2030,7 +2046,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2030 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0); 2046 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 0);
2031 if (reg >= 6 || reg == R_CS) 2047 if (reg >= 6 || reg == R_CS)
2032 goto illegal_op; 2048 goto illegal_op;
2033 - gen_movl_seg_T0(s, reg); 2049 + gen_movl_seg_T0(s, reg, pc_start - s->cs_base);
2034 break; 2050 break;
2035 case 0x8c: /* mov Gv, seg */ 2051 case 0x8c: /* mov Gv, seg */
2036 ot = dflag ? OT_LONG : OT_WORD; 2052 ot = dflag ? OT_LONG : OT_WORD;
@@ -2231,7 +2247,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2231,7 +2247,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2231 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); 2247 gen_op_addl_A0_im(1 << (ot - OT_WORD + 1));
2232 /* load the segment first to handle exceptions properly */ 2248 /* load the segment first to handle exceptions properly */
2233 gen_op_lduw_T0_A0(); 2249 gen_op_lduw_T0_A0();
2234 - gen_movl_seg_T0(s, op); 2250 + gen_movl_seg_T0(s, op, pc_start - s->cs_base);
2235 /* then put the data */ 2251 /* then put the data */
2236 gen_op_mov_reg_T1[ot][reg](); 2252 gen_op_mov_reg_T1[ot][reg]();
2237 break; 2253 break;
@@ -2914,7 +2930,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2914,7 +2930,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2914 gen_pop_update(s); 2930 gen_pop_update(s);
2915 /* pop selector */ 2931 /* pop selector */
2916 gen_pop_T0(s); 2932 gen_pop_T0(s);
2917 - gen_movl_seg_T0(s, R_CS); 2933 + gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
2918 gen_pop_update(s); 2934 gen_pop_update(s);
2919 /* add stack offset */ 2935 /* add stack offset */
2920 if (s->ss32) 2936 if (s->ss32)
@@ -2933,7 +2949,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2933,7 +2949,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2933 gen_pop_update(s); 2949 gen_pop_update(s);
2934 /* pop selector */ 2950 /* pop selector */
2935 gen_pop_T0(s); 2951 gen_pop_T0(s);
2936 - gen_movl_seg_T0(s, R_CS); 2952 + gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
2937 gen_pop_update(s); 2953 gen_pop_update(s);
2938 s->is_jmp = 1; 2954 s->is_jmp = 1;
2939 break; 2955 break;
@@ -2950,7 +2966,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2950,7 +2966,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2950 gen_pop_update(s); 2966 gen_pop_update(s);
2951 /* pop selector */ 2967 /* pop selector */
2952 gen_pop_T0(s); 2968 gen_pop_T0(s);
2953 - gen_movl_seg_T0(s, R_CS); 2969 + gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
2954 gen_pop_update(s); 2970 gen_pop_update(s);
2955 /* pop eflags */ 2971 /* pop eflags */
2956 gen_pop_T0(s); 2972 gen_pop_T0(s);
@@ -2995,7 +3011,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -2995,7 +3011,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
2995 3011
2996 /* change cs and pc */ 3012 /* change cs and pc */
2997 gen_op_movl_T0_im(selector); 3013 gen_op_movl_T0_im(selector);
2998 - gen_movl_seg_T0(s, R_CS); 3014 + gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
2999 gen_op_jmp_im((unsigned long)offset); 3015 gen_op_jmp_im((unsigned long)offset);
3000 s->is_jmp = 1; 3016 s->is_jmp = 1;
3001 } 3017 }
@@ -3018,7 +3034,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -3018,7 +3034,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3018 3034
3019 /* change cs and pc */ 3035 /* change cs and pc */
3020 gen_op_movl_T0_im(selector); 3036 gen_op_movl_T0_im(selector);
3021 - gen_movl_seg_T0(s, R_CS); 3037 + gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base);
3022 gen_op_jmp_im((unsigned long)offset); 3038 gen_op_jmp_im((unsigned long)offset);
3023 s->is_jmp = 1; 3039 s->is_jmp = 1;
3024 } 3040 }
@@ -3255,14 +3271,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -3255,14 +3271,15 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3255 case 0x9b: /* fwait */ 3271 case 0x9b: /* fwait */
3256 break; 3272 break;
3257 case 0xcc: /* int3 */ 3273 case 0xcc: /* int3 */
3258 - gen_exception(s, EXCP03_INT3, s->pc - s->cs_base); 3274 + gen_interrupt(s, EXCP03_INT3, pc_start - s->cs_base, s->pc - s->cs_base);
3259 break; 3275 break;
3260 case 0xcd: /* int N */ 3276 case 0xcd: /* int N */
3261 val = ldub(s->pc++); 3277 val = ldub(s->pc++);
3262 - if (s->cc_op != CC_OP_DYNAMIC)  
3263 - gen_op_set_cc_op(s->cc_op);  
3264 - gen_op_int_im(val, pc_start - s->cs_base);  
3265 - s->is_jmp = 1; 3278 + /* XXX: add error code for vm86 GPF */
  3279 + if (!s->vm86)
  3280 + gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base);
  3281 + else
  3282 + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3266 break; 3283 break;
3267 case 0xce: /* into */ 3284 case 0xce: /* into */
3268 if (s->cc_op != CC_OP_DYNAMIC) 3285 if (s->cc_op != CC_OP_DYNAMIC)
@@ -3309,9 +3326,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) @@ -3309,9 +3326,9 @@ long disas_insn(DisasContext *s, uint8_t *pc_start)
3309 gen_op_mov_reg_T0[ot][reg](); 3326 gen_op_mov_reg_T0[ot][reg]();
3310 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr); 3327 gen_lea_modrm(s, modrm, &reg_addr, &offset_addr);
3311 if (ot == OT_WORD) 3328 if (ot == OT_WORD)
3312 - gen_op_boundw(); 3329 + gen_op_boundw(pc_start - s->cs_base);
3313 else 3330 else
3314 - gen_op_boundl(); 3331 + gen_op_boundl(pc_start - s->cs_base);
3315 break; 3332 break;
3316 case 0x1c8 ... 0x1cf: /* bswap reg */ 3333 case 0x1c8 ... 0x1cf: /* bswap reg */
3317 reg = b & 7; 3334 reg = b & 7;
@@ -3670,13 +3687,13 @@ static void optimize_flags(uint16_t *opc_buf, int opc_buf_len) @@ -3670,13 +3687,13 @@ static void optimize_flags(uint16_t *opc_buf, int opc_buf_len)
3670 3687
3671 #ifdef DEBUG_DISAS 3688 #ifdef DEBUG_DISAS
3672 static const char *op_str[] = { 3689 static const char *op_str[] = {
3673 -#define DEF(s, n) #s, 3690 +#define DEF(s, n, copy_size) #s,
3674 #include "opc-i386.h" 3691 #include "opc-i386.h"
3675 #undef DEF 3692 #undef DEF
3676 }; 3693 };
3677 3694
3678 static uint8_t op_nb_args[] = { 3695 static uint8_t op_nb_args[] = {
3679 -#define DEF(s, n) n, 3696 +#define DEF(s, n, copy_size) n,
3680 #include "opc-i386.h" 3697 #include "opc-i386.h"
3681 #undef DEF 3698 #undef DEF
3682 }; 3699 };
@@ -3706,7 +3723,6 @@ static void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf) @@ -3706,7 +3723,6 @@ static void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf)
3706 3723
3707 #endif 3724 #endif
3708 3725
3709 -/* XXX: make this buffer thread safe */  
3710 /* XXX: make safe guess about sizes */ 3726 /* XXX: make safe guess about sizes */
3711 #define MAX_OP_PER_INSTR 32 3727 #define MAX_OP_PER_INSTR 32
3712 #define OPC_BUF_SIZE 512 3728 #define OPC_BUF_SIZE 512
@@ -3716,30 +3732,27 @@ static void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf) @@ -3716,30 +3732,27 @@ static void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf)
3716 3732
3717 static uint16_t gen_opc_buf[OPC_BUF_SIZE]; 3733 static uint16_t gen_opc_buf[OPC_BUF_SIZE];
3718 static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE]; 3734 static uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
  3735 +static uint32_t gen_opc_pc[OPC_BUF_SIZE];
  3736 +static uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
3719 3737
3720 -/* return non zero if the very first instruction is invalid so that  
3721 - the virtual CPU can trigger an exception.  
3722 -  
3723 - '*code_size_ptr' contains the target code size including the  
3724 - instruction which triggered an exception, except in case of invalid  
3725 - illegal opcode. It must never exceed one target page.  
3726 -  
3727 - '*gen_code_size_ptr' contains the size of the generated code (host  
3728 - code).  
3729 -*/  
3730 -int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,  
3731 - int *gen_code_size_ptr,  
3732 - uint8_t *pc_start, uint8_t *cs_base, int flags,  
3733 - int *code_size_ptr, TranslationBlock *tb) 3738 +/* generate intermediate code in gen_opc_buf and gen_opparam_buf for
  3739 + basic block 'tb'. If search_pc is TRUE, also generate PC
  3740 + information for each intermediate instruction. */
  3741 +static inline int gen_intermediate_code(TranslationBlock *tb, int search_pc)
3734 { 3742 {
3735 DisasContext dc1, *dc = &dc1; 3743 DisasContext dc1, *dc = &dc1;
3736 uint8_t *pc_ptr; 3744 uint8_t *pc_ptr;
3737 uint16_t *gen_opc_end; 3745 uint16_t *gen_opc_end;
3738 - int gen_code_size; 3746 + int flags, j, lj;
3739 long ret; 3747 long ret;
  3748 + uint8_t *pc_start;
  3749 + uint8_t *cs_base;
3740 3750
3741 /* generate intermediate code */ 3751 /* generate intermediate code */
3742 - 3752 + pc_start = (uint8_t *)tb->pc;
  3753 + cs_base = (uint8_t *)tb->cs_base;
  3754 + flags = tb->flags;
  3755 +
3743 dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1; 3756 dc->code32 = (flags >> GEN_FLAG_CODE32_SHIFT) & 1;
3744 dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1; 3757 dc->ss32 = (flags >> GEN_FLAG_SS32_SHIFT) & 1;
3745 dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1; 3758 dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1;
@@ -3758,7 +3771,18 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, @@ -3758,7 +3771,18 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
3758 3771
3759 dc->is_jmp = 0; 3772 dc->is_jmp = 0;
3760 pc_ptr = pc_start; 3773 pc_ptr = pc_start;
  3774 + lj = -1;
3761 do { 3775 do {
  3776 + if (search_pc) {
  3777 + j = gen_opc_ptr - gen_opc_buf;
  3778 + if (lj < j) {
  3779 + lj++;
  3780 + while (lj < j)
  3781 + gen_opc_instr_start[lj++] = 0;
  3782 + gen_opc_pc[lj] = (uint32_t)pc_ptr;
  3783 + gen_opc_instr_start[lj] = 1;
  3784 + }
  3785 + }
3762 ret = disas_insn(dc, pc_ptr); 3786 ret = disas_insn(dc, pc_ptr);
3763 if (ret == -1) { 3787 if (ret == -1) {
3764 /* we trigger an illegal instruction operation only if it 3788 /* we trigger an illegal instruction operation only if it
@@ -3819,10 +3843,31 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, @@ -3819,10 +3843,31 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
3819 fprintf(logfile, "\n"); 3843 fprintf(logfile, "\n");
3820 } 3844 }
3821 #endif 3845 #endif
  3846 + if (!search_pc)
  3847 + tb->size = pc_ptr - pc_start;
  3848 + return 0;
  3849 +}
  3850 +
  3851 +
  3852 +/* return non zero if the very first instruction is invalid so that
  3853 + the virtual CPU can trigger an exception.
  3854 +
  3855 + '*gen_code_size_ptr' contains the size of the generated code (host
  3856 + code).
  3857 +*/
  3858 +int cpu_x86_gen_code(TranslationBlock *tb,
  3859 + int max_code_size, int *gen_code_size_ptr)
  3860 +{
  3861 + uint8_t *gen_code_buf;
  3862 + int gen_code_size;
  3863 +
  3864 + if (gen_intermediate_code(tb, 0) < 0)
  3865 + return -1;
3822 3866
3823 /* generate machine code */ 3867 /* generate machine code */
3824 tb->tb_next_offset[0] = 0xffff; 3868 tb->tb_next_offset[0] = 0xffff;
3825 tb->tb_next_offset[1] = 0xffff; 3869 tb->tb_next_offset[1] = 0xffff;
  3870 + gen_code_buf = tb->tc_ptr;
3826 gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset, 3871 gen_code_size = dyngen_code(gen_code_buf, tb->tb_next_offset,
3827 #ifdef USE_DIRECT_JUMP 3872 #ifdef USE_DIRECT_JUMP
3828 tb->tb_jmp_offset, 3873 tb->tb_jmp_offset,
@@ -3831,13 +3876,12 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, @@ -3831,13 +3876,12 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
3831 #endif 3876 #endif
3832 gen_opc_buf, gen_opparam_buf); 3877 gen_opc_buf, gen_opparam_buf);
3833 flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size)); 3878 flush_icache_range((unsigned long)gen_code_buf, (unsigned long)(gen_code_buf + gen_code_size));
3834 - 3879 +
3835 *gen_code_size_ptr = gen_code_size; 3880 *gen_code_size_ptr = gen_code_size;
3836 - *code_size_ptr = pc_ptr - pc_start;  
3837 #ifdef DEBUG_DISAS 3881 #ifdef DEBUG_DISAS
3838 if (loglevel) { 3882 if (loglevel) {
3839 fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr); 3883 fprintf(logfile, "OUT: [size=%d]\n", *gen_code_size_ptr);
3840 - disas(logfile, gen_code_buf, *gen_code_size_ptr, DISAS_TARGET); 3884 + disas(logfile, gen_code_buf, *gen_code_size_ptr, DISAS_TARGET);
3841 fprintf(logfile, "\n"); 3885 fprintf(logfile, "\n");
3842 fflush(logfile); 3886 fflush(logfile);
3843 } 3887 }
@@ -3845,6 +3889,50 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, @@ -3845,6 +3889,50 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size,
3845 return 0; 3889 return 0;
3846 } 3890 }
3847 3891
  3892 +static const unsigned short opc_copy_size[] = {
  3893 +#define DEF(s, n, copy_size) copy_size,
  3894 +#include "opc-i386.h"
  3895 +#undef DEF
  3896 +};
  3897 +
  3898 +/* The simulated PC corresponding to
  3899 + 'searched_pc' in the generated code is searched. 0 is returned if
  3900 + found. *found_pc contains the found PC.
  3901 + */
  3902 +int cpu_x86_search_pc(TranslationBlock *tb,
  3903 + uint32_t *found_pc, unsigned long searched_pc)
  3904 +{
  3905 + int j, c;
  3906 + unsigned long tc_ptr;
  3907 + uint16_t *opc_ptr;
  3908 +
  3909 + if (gen_intermediate_code(tb, 1) < 0)
  3910 + return -1;
  3911 +
  3912 + /* find opc index corresponding to search_pc */
  3913 + tc_ptr = (unsigned long)tb->tc_ptr;
  3914 + if (searched_pc < tc_ptr)
  3915 + return -1;
  3916 + j = 0;
  3917 + opc_ptr = gen_opc_buf;
  3918 + for(;;) {
  3919 + c = *opc_ptr;
  3920 + if (c == INDEX_op_end)
  3921 + return -1;
  3922 + tc_ptr += opc_copy_size[c];
  3923 + if (searched_pc < tc_ptr)
  3924 + break;
  3925 + opc_ptr++;
  3926 + }
  3927 + j = opc_ptr - gen_opc_buf;
  3928 + /* now find start of instruction before */
  3929 + while (gen_opc_instr_start[j] == 0)
  3930 + j--;
  3931 + *found_pc = gen_opc_pc[j];
  3932 + return 0;
  3933 +}
  3934 +
  3935 +
3848 CPUX86State *cpu_x86_init(void) 3936 CPUX86State *cpu_x86_init(void)
3849 { 3937 {
3850 CPUX86State *env; 3938 CPUX86State *env;