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 | ... | ... |