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 |