Commit c50c0c3fbf65ce7a1cf42a2ea8974a930be7b667

Authored by bellard
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