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