Revision c50c0c3f translate-i386.c
b/translate-i386.c | ||
---|---|---|
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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 |
Also available in: Unified diff