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 | 132 | int vm86; /* vm86 mode */ |
133 | 133 | int cpl; |
134 | 134 | int iopl; |
135 | + int tf; /* TF cpu flag */ | |
135 | 136 | } DisasContext; |
136 | 137 | |
137 | 138 | /* i386 arith/logic operations */ |
... | ... | @@ -1366,6 +1367,15 @@ static void gen_enter(DisasContext *s, int esp_addend, int level) |
1366 | 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 | 1379 | /* return the next pc address. Return -1 if no insn found. *is_jmp_ptr |
1370 | 1380 | is set to true if the instruction sets the PC (last instruction of |
1371 | 1381 | a basic block) */ |
... | ... | @@ -2770,8 +2780,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
2770 | 2780 | case 0x6d: |
2771 | 2781 | if (s->cpl > s->iopl || s->vm86) { |
2772 | 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 | 2784 | } else { |
2776 | 2785 | if ((b & 1) == 0) |
2777 | 2786 | ot = OT_BYTE; |
... | ... | @@ -2788,8 +2797,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
2788 | 2797 | case 0x6f: |
2789 | 2798 | if (s->cpl > s->iopl || s->vm86) { |
2790 | 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 | 2801 | } else { |
2794 | 2802 | if ((b & 1) == 0) |
2795 | 2803 | ot = OT_BYTE; |
... | ... | @@ -2808,8 +2816,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
2808 | 2816 | case 0xe4: |
2809 | 2817 | case 0xe5: |
2810 | 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 | 2820 | } else { |
2814 | 2821 | if ((b & 1) == 0) |
2815 | 2822 | ot = OT_BYTE; |
... | ... | @@ -2824,8 +2831,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
2824 | 2831 | case 0xe6: |
2825 | 2832 | case 0xe7: |
2826 | 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 | 2835 | } else { |
2830 | 2836 | if ((b & 1) == 0) |
2831 | 2837 | ot = OT_BYTE; |
... | ... | @@ -2840,8 +2846,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
2840 | 2846 | case 0xec: |
2841 | 2847 | case 0xed: |
2842 | 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 | 2850 | } else { |
2846 | 2851 | if ((b & 1) == 0) |
2847 | 2852 | ot = OT_BYTE; |
... | ... | @@ -2855,8 +2860,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
2855 | 2860 | case 0xee: |
2856 | 2861 | case 0xef: |
2857 | 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 | 2864 | } else { |
2861 | 2865 | if ((b & 1) == 0) |
2862 | 2866 | ot = OT_BYTE; |
... | ... | @@ -2928,8 +2932,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
2928 | 2932 | break; |
2929 | 2933 | case 0xcf: /* iret */ |
2930 | 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 | 2936 | } else { |
2934 | 2937 | /* XXX: not restartable */ |
2935 | 2938 | /* pop offset */ |
... | ... | @@ -3066,8 +3069,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
3066 | 3069 | /* flags */ |
3067 | 3070 | case 0x9c: /* pushf */ |
3068 | 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 | 3073 | } else { |
3072 | 3074 | if (s->cc_op != CC_OP_DYNAMIC) |
3073 | 3075 | gen_op_set_cc_op(s->cc_op); |
... | ... | @@ -3077,8 +3079,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
3077 | 3079 | break; |
3078 | 3080 | case 0x9d: /* popf */ |
3079 | 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 | 3083 | } else { |
3083 | 3084 | gen_pop_T0(s); |
3084 | 3085 | if (s->dflag) { |
... | ... | @@ -3248,11 +3249,12 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
3248 | 3249 | case 0x90: /* nop */ |
3249 | 3250 | break; |
3250 | 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 | 3253 | break; |
3254 | 3254 | case 0xcd: /* int N */ |
3255 | 3255 | val = ldub(s->pc++); |
3256 | + if (s->cc_op != CC_OP_DYNAMIC) | |
3257 | + gen_op_set_cc_op(s->cc_op); | |
3256 | 3258 | gen_op_int_im(val, pc_start - s->cs_base); |
3257 | 3259 | s->is_jmp = 1; |
3258 | 3260 | break; |
... | ... | @@ -3266,15 +3268,13 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
3266 | 3268 | if (s->cpl <= s->iopl) { |
3267 | 3269 | gen_op_cli(); |
3268 | 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 | 3273 | } else { |
3273 | 3274 | if (s->iopl == 3) { |
3274 | 3275 | gen_op_cli(); |
3275 | 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 | 3280 | break; |
... | ... | @@ -3283,15 +3283,13 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
3283 | 3283 | if (s->cpl <= s->iopl) { |
3284 | 3284 | gen_op_sti(); |
3285 | 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 | 3288 | } else { |
3290 | 3289 | if (s->iopl == 3) { |
3291 | 3290 | gen_op_sti(); |
3292 | 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 | 3295 | break; |
... | ... | @@ -3343,8 +3341,7 @@ long disas_insn(DisasContext *s, uint8_t *pc_start) |
3343 | 3341 | break; |
3344 | 3342 | case 0xf4: /* hlt */ |
3345 | 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 | 3345 | break; |
3349 | 3346 | default: |
3350 | 3347 | goto illegal_op; |
... | ... | @@ -3453,7 +3450,6 @@ static uint16_t opc_read_flags[NB_OPS] = { |
3453 | 3450 | [INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z, |
3454 | 3451 | |
3455 | 3452 | [INDEX_op_movl_T0_eflags] = CC_OSZAPC, |
3456 | - [INDEX_op_movl_T0_eflags_vm] = CC_OSZAPC, | |
3457 | 3453 | [INDEX_op_cmc] = CC_C, |
3458 | 3454 | [INDEX_op_salc] = CC_C, |
3459 | 3455 | |
... | ... | @@ -3504,9 +3500,7 @@ static uint16_t opc_write_flags[NB_OPS] = { |
3504 | 3500 | |
3505 | 3501 | [INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C, |
3506 | 3502 | [INDEX_op_movw_eflags_T0] = CC_OSZAPC, |
3507 | - [INDEX_op_movw_eflags_T0_vm] = CC_OSZAPC, | |
3508 | 3503 | [INDEX_op_movl_eflags_T0] = CC_OSZAPC, |
3509 | - [INDEX_op_movl_eflags_T0_vm] = CC_OSZAPC, | |
3510 | 3504 | [INDEX_op_clc] = CC_C, |
3511 | 3505 | [INDEX_op_stc] = CC_C, |
3512 | 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 | 3720 | dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1; |
3727 | 3721 | dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3; |
3728 | 3722 | dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3; |
3723 | + dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1; | |
3729 | 3724 | dc->cc_op = CC_OP_DYNAMIC; |
3730 | 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 | 3742 | break; |
3748 | 3743 | } |
3749 | 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 | 3749 | } while (!dc->is_jmp && gen_opc_ptr < gen_opc_end); |
3751 | 3750 | /* we must store the eflags state if it is not already done */ |
3752 | 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 | 3754 | /* we add an additionnal jmp to update the simulated PC */ |
3756 | 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 | 3761 | *gen_opc_ptr = INDEX_op_end; |
3759 | 3762 | |
3760 | 3763 | #ifdef DEBUG_DISAS | ... | ... |