Commit c50c0c3fbf65ce7a1cf42a2ea8974a930be7b667
1 parent
cabb4d61
TF flag support - fixed eflags computation before exception
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@145 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
36 additions
and
33 deletions
translate-i386.c
@@ -132,6 +132,7 @@ typedef struct DisasContext { | @@ -132,6 +132,7 @@ typedef struct DisasContext { | ||
132 | int vm86; /* vm86 mode */ | 132 | int vm86; /* vm86 mode */ |
133 | int cpl; | 133 | int cpl; |
134 | int iopl; | 134 | int iopl; |
135 | + int tf; /* TF cpu flag */ | ||
135 | } DisasContext; | 136 | } DisasContext; |
136 | 137 | ||
137 | /* i386 arith/logic operations */ | 138 | /* i386 arith/logic operations */ |
@@ -1366,6 +1367,15 @@ static void gen_enter(DisasContext *s, int esp_addend, int level) | @@ -1366,6 +1367,15 @@ static void gen_enter(DisasContext *s, int esp_addend, int level) | ||
1366 | gen_op_mov_reg_T1[ot][R_ESP](); | 1367 | gen_op_mov_reg_T1[ot][R_ESP](); |
1367 | } | 1368 | } |
1368 | 1369 | ||
1370 | +static void gen_exception(DisasContext *s, int trapno, unsigned int cur_eip) | ||
1371 | +{ | ||
1372 | + if (s->cc_op != CC_OP_DYNAMIC) | ||
1373 | + gen_op_set_cc_op(s->cc_op); | ||
1374 | + gen_op_jmp_im(cur_eip); | ||
1375 | + gen_op_raise_exception(trapno); | ||
1376 | + s->is_jmp = 1; | ||
1377 | +} | ||
1378 | + | ||
1369 | /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr | 1379 | /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr |
1370 | is set to true if the instruction sets the PC (last instruction of | 1380 | is set to true if the instruction sets the PC (last instruction of |
1371 | a basic block) */ | 1381 | a basic block) */ |
@@ -2770,8 +2780,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2770,8 +2780,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
2770 | case 0x6d: | 2780 | case 0x6d: |
2771 | if (s->cpl > s->iopl || s->vm86) { | 2781 | if (s->cpl > s->iopl || s->vm86) { |
2772 | /* NOTE: even for (E)CX = 0 the exception is raised */ | 2782 | /* NOTE: even for (E)CX = 0 the exception is raised */ |
2773 | - gen_op_gpf(pc_start - s->cs_base); | ||
2774 | - s->is_jmp = 1; | 2783 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
2775 | } else { | 2784 | } else { |
2776 | if ((b & 1) == 0) | 2785 | if ((b & 1) == 0) |
2777 | ot = OT_BYTE; | 2786 | ot = OT_BYTE; |
@@ -2788,8 +2797,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2788,8 +2797,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
2788 | case 0x6f: | 2797 | case 0x6f: |
2789 | if (s->cpl > s->iopl || s->vm86) { | 2798 | if (s->cpl > s->iopl || s->vm86) { |
2790 | /* NOTE: even for (E)CX = 0 the exception is raised */ | 2799 | /* NOTE: even for (E)CX = 0 the exception is raised */ |
2791 | - gen_op_gpf(pc_start - s->cs_base); | ||
2792 | - s->is_jmp = 1; | 2800 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
2793 | } else { | 2801 | } else { |
2794 | if ((b & 1) == 0) | 2802 | if ((b & 1) == 0) |
2795 | ot = OT_BYTE; | 2803 | ot = OT_BYTE; |
@@ -2808,8 +2816,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2808,8 +2816,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
2808 | case 0xe4: | 2816 | case 0xe4: |
2809 | case 0xe5: | 2817 | case 0xe5: |
2810 | if (s->cpl > s->iopl || s->vm86) { | 2818 | if (s->cpl > s->iopl || s->vm86) { |
2811 | - gen_op_gpf(pc_start - s->cs_base); | ||
2812 | - s->is_jmp = 1; | 2819 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
2813 | } else { | 2820 | } else { |
2814 | if ((b & 1) == 0) | 2821 | if ((b & 1) == 0) |
2815 | ot = OT_BYTE; | 2822 | ot = OT_BYTE; |
@@ -2824,8 +2831,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2824,8 +2831,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
2824 | case 0xe6: | 2831 | case 0xe6: |
2825 | case 0xe7: | 2832 | case 0xe7: |
2826 | if (s->cpl > s->iopl || s->vm86) { | 2833 | if (s->cpl > s->iopl || s->vm86) { |
2827 | - gen_op_gpf(pc_start - s->cs_base); | ||
2828 | - s->is_jmp = 1; | 2834 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
2829 | } else { | 2835 | } else { |
2830 | if ((b & 1) == 0) | 2836 | if ((b & 1) == 0) |
2831 | ot = OT_BYTE; | 2837 | ot = OT_BYTE; |
@@ -2840,8 +2846,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2840,8 +2846,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
2840 | case 0xec: | 2846 | case 0xec: |
2841 | case 0xed: | 2847 | case 0xed: |
2842 | if (s->cpl > s->iopl || s->vm86) { | 2848 | if (s->cpl > s->iopl || s->vm86) { |
2843 | - gen_op_gpf(pc_start - s->cs_base); | ||
2844 | - s->is_jmp = 1; | 2849 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
2845 | } else { | 2850 | } else { |
2846 | if ((b & 1) == 0) | 2851 | if ((b & 1) == 0) |
2847 | ot = OT_BYTE; | 2852 | ot = OT_BYTE; |
@@ -2855,8 +2860,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2855,8 +2860,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
2855 | case 0xee: | 2860 | case 0xee: |
2856 | case 0xef: | 2861 | case 0xef: |
2857 | if (s->cpl > s->iopl || s->vm86) { | 2862 | if (s->cpl > s->iopl || s->vm86) { |
2858 | - gen_op_gpf(pc_start - s->cs_base); | ||
2859 | - s->is_jmp = 1; | 2863 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
2860 | } else { | 2864 | } else { |
2861 | if ((b & 1) == 0) | 2865 | if ((b & 1) == 0) |
2862 | ot = OT_BYTE; | 2866 | ot = OT_BYTE; |
@@ -2928,8 +2932,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -2928,8 +2932,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
2928 | break; | 2932 | break; |
2929 | case 0xcf: /* iret */ | 2933 | case 0xcf: /* iret */ |
2930 | if (s->vm86 && s->iopl != 3) { | 2934 | if (s->vm86 && s->iopl != 3) { |
2931 | - gen_op_gpf(pc_start - s->cs_base); | ||
2932 | - s->is_jmp = 1; | 2935 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
2933 | } else { | 2936 | } else { |
2934 | /* XXX: not restartable */ | 2937 | /* XXX: not restartable */ |
2935 | /* pop offset */ | 2938 | /* pop offset */ |
@@ -3066,8 +3069,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3066,8 +3069,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
3066 | /* flags */ | 3069 | /* flags */ |
3067 | case 0x9c: /* pushf */ | 3070 | case 0x9c: /* pushf */ |
3068 | if (s->vm86 && s->iopl != 3) { | 3071 | if (s->vm86 && s->iopl != 3) { |
3069 | - gen_op_gpf(pc_start - s->cs_base); | ||
3070 | - s->is_jmp = 1; | 3072 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3071 | } else { | 3073 | } else { |
3072 | if (s->cc_op != CC_OP_DYNAMIC) | 3074 | if (s->cc_op != CC_OP_DYNAMIC) |
3073 | gen_op_set_cc_op(s->cc_op); | 3075 | gen_op_set_cc_op(s->cc_op); |
@@ -3077,8 +3079,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3077,8 +3079,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
3077 | break; | 3079 | break; |
3078 | case 0x9d: /* popf */ | 3080 | case 0x9d: /* popf */ |
3079 | if (s->vm86 && s->iopl != 3) { | 3081 | if (s->vm86 && s->iopl != 3) { |
3080 | - gen_op_gpf(pc_start - s->cs_base); | ||
3081 | - s->is_jmp = 1; | 3082 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3082 | } else { | 3083 | } else { |
3083 | gen_pop_T0(s); | 3084 | gen_pop_T0(s); |
3084 | if (s->dflag) { | 3085 | if (s->dflag) { |
@@ -3248,11 +3249,12 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3248,11 +3249,12 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
3248 | case 0x90: /* nop */ | 3249 | case 0x90: /* nop */ |
3249 | break; | 3250 | break; |
3250 | case 0xcc: /* int3 */ | 3251 | case 0xcc: /* int3 */ |
3251 | - gen_op_int3((long)pc_start); | ||
3252 | - s->is_jmp = 1; | 3252 | + gen_exception(s, EXCP03_INT3, pc_start - s->cs_base); |
3253 | break; | 3253 | break; |
3254 | case 0xcd: /* int N */ | 3254 | case 0xcd: /* int N */ |
3255 | val = ldub(s->pc++); | 3255 | val = ldub(s->pc++); |
3256 | + if (s->cc_op != CC_OP_DYNAMIC) | ||
3257 | + gen_op_set_cc_op(s->cc_op); | ||
3256 | gen_op_int_im(val, pc_start - s->cs_base); | 3258 | gen_op_int_im(val, pc_start - s->cs_base); |
3257 | s->is_jmp = 1; | 3259 | s->is_jmp = 1; |
3258 | break; | 3260 | break; |
@@ -3266,15 +3268,13 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3266,15 +3268,13 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
3266 | if (s->cpl <= s->iopl) { | 3268 | if (s->cpl <= s->iopl) { |
3267 | gen_op_cli(); | 3269 | gen_op_cli(); |
3268 | } else { | 3270 | } else { |
3269 | - gen_op_gpf(pc_start - s->cs_base); | ||
3270 | - s->is_jmp = 1; | 3271 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3271 | } | 3272 | } |
3272 | } else { | 3273 | } else { |
3273 | if (s->iopl == 3) { | 3274 | if (s->iopl == 3) { |
3274 | gen_op_cli(); | 3275 | gen_op_cli(); |
3275 | } else { | 3276 | } else { |
3276 | - gen_op_gpf(pc_start - s->cs_base); | ||
3277 | - s->is_jmp = 1; | 3277 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3278 | } | 3278 | } |
3279 | } | 3279 | } |
3280 | break; | 3280 | break; |
@@ -3283,15 +3283,13 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3283,15 +3283,13 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
3283 | if (s->cpl <= s->iopl) { | 3283 | if (s->cpl <= s->iopl) { |
3284 | gen_op_sti(); | 3284 | gen_op_sti(); |
3285 | } else { | 3285 | } else { |
3286 | - gen_op_gpf(pc_start - s->cs_base); | ||
3287 | - s->is_jmp = 1; | 3286 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3288 | } | 3287 | } |
3289 | } else { | 3288 | } else { |
3290 | if (s->iopl == 3) { | 3289 | if (s->iopl == 3) { |
3291 | gen_op_sti(); | 3290 | gen_op_sti(); |
3292 | } else { | 3291 | } else { |
3293 | - gen_op_gpf(pc_start - s->cs_base); | ||
3294 | - s->is_jmp = 1; | 3292 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3295 | } | 3293 | } |
3296 | } | 3294 | } |
3297 | break; | 3295 | break; |
@@ -3343,8 +3341,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | @@ -3343,8 +3341,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) | ||
3343 | break; | 3341 | break; |
3344 | case 0xf4: /* hlt */ | 3342 | case 0xf4: /* hlt */ |
3345 | /* XXX: if cpl == 0, then should do something else */ | 3343 | /* XXX: if cpl == 0, then should do something else */ |
3346 | - gen_op_gpf(pc_start - s->cs_base); | ||
3347 | - s->is_jmp = 1; | 3344 | + gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3348 | break; | 3345 | break; |
3349 | default: | 3346 | default: |
3350 | goto illegal_op; | 3347 | goto illegal_op; |
@@ -3453,7 +3450,6 @@ static uint16_t opc_read_flags[NB_OPS] = { | @@ -3453,7 +3450,6 @@ static uint16_t opc_read_flags[NB_OPS] = { | ||
3453 | [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z, | 3450 | [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z, |
3454 | 3451 | ||
3455 | [INDEX_op_movl_T0_eflags] = CC_OSZAPC, | 3452 | [INDEX_op_movl_T0_eflags] = CC_OSZAPC, |
3456 | - [INDEX_op_movl_T0_eflags_vm] = CC_OSZAPC, | ||
3457 | [INDEX_op_cmc] = CC_C, | 3453 | [INDEX_op_cmc] = CC_C, |
3458 | [INDEX_op_salc] = CC_C, | 3454 | [INDEX_op_salc] = CC_C, |
3459 | 3455 | ||
@@ -3504,9 +3500,7 @@ static uint16_t opc_write_flags[NB_OPS] = { | @@ -3504,9 +3500,7 @@ static uint16_t opc_write_flags[NB_OPS] = { | ||
3504 | 3500 | ||
3505 | [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C, | 3501 | [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C, |
3506 | [INDEX_op_movw_eflags_T0] = CC_OSZAPC, | 3502 | [INDEX_op_movw_eflags_T0] = CC_OSZAPC, |
3507 | - [INDEX_op_movw_eflags_T0_vm] = CC_OSZAPC, | ||
3508 | [INDEX_op_movl_eflags_T0] = CC_OSZAPC, | 3503 | [INDEX_op_movl_eflags_T0] = CC_OSZAPC, |
3509 | - [INDEX_op_movl_eflags_T0_vm] = CC_OSZAPC, | ||
3510 | [INDEX_op_clc] = CC_C, | 3504 | [INDEX_op_clc] = CC_C, |
3511 | [INDEX_op_stc] = CC_C, | 3505 | [INDEX_op_stc] = CC_C, |
3512 | [INDEX_op_cmc] = CC_C, | 3506 | [INDEX_op_cmc] = CC_C, |
@@ -3726,6 +3720,7 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, | @@ -3726,6 +3720,7 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, | ||
3726 | dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1; | 3720 | dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1; |
3727 | dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3; | 3721 | dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3; |
3728 | dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3; | 3722 | dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3; |
3723 | + dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1; | ||
3729 | dc->cc_op = CC_OP_DYNAMIC; | 3724 | dc->cc_op = CC_OP_DYNAMIC; |
3730 | dc->cs_base = cs_base; | 3725 | dc->cs_base = cs_base; |
3731 | 3726 | ||
@@ -3747,6 +3742,10 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, | @@ -3747,6 +3742,10 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, | ||
3747 | break; | 3742 | break; |
3748 | } | 3743 | } |
3749 | pc_ptr = (void *)ret; | 3744 | pc_ptr = (void *)ret; |
3745 | + /* if single step mode, we generate only one instruction and | ||
3746 | + generate an exception */ | ||
3747 | + if (dc->tf) | ||
3748 | + break; | ||
3750 | } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end); | 3749 | } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end); |
3751 | /* we must store the eflags state if it is not already done */ | 3750 | /* we must store the eflags state if it is not already done */ |
3752 | if (dc->cc_op != CC_OP_DYNAMIC) | 3751 | if (dc->cc_op != CC_OP_DYNAMIC) |
@@ -3755,6 +3754,10 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, | @@ -3755,6 +3754,10 @@ int cpu_x86_gen_code(uint8_t *gen_code_buf, int max_code_size, | ||
3755 | /* we add an additionnal jmp to update the simulated PC */ | 3754 | /* we add an additionnal jmp to update the simulated PC */ |
3756 | gen_op_jmp_im(ret - (unsigned long)dc->cs_base); | 3755 | gen_op_jmp_im(ret - (unsigned long)dc->cs_base); |
3757 | } | 3756 | } |
3757 | + if (dc->tf) { | ||
3758 | + gen_op_raise_exception(EXCP01_SSTP); | ||
3759 | + } | ||
3760 | + | ||
3758 | *gen_opc_ptr = INDEX_op_end; | 3761 | *gen_opc_ptr = INDEX_op_end; |
3759 | 3762 | ||
3760 | #ifdef DEBUG_DISAS | 3763 | #ifdef DEBUG_DISAS |