132 |
int vm86; /* vm86 mode */ |
int vm86; /* vm86 mode */ |
133 |
int cpl; |
int cpl; |
134 |
int iopl; |
int iopl; |
135 |
|
int tf; /* TF cpu flag */ |
136 |
} DisasContext; |
} DisasContext; |
137 |
|
|
138 |
/* i386 arith/logic operations */ |
/* i386 arith/logic operations */ |
1367 |
gen_op_mov_reg_T1[ot][R_ESP](); |
gen_op_mov_reg_T1[ot][R_ESP](); |
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 |
|
|
1379 |
/* return the next pc address. Return -1 if no insn found. *is_jmp_ptr |
/* return the next pc address. Return -1 if no insn found. *is_jmp_ptr |
1380 |
is set to true if the instruction sets the PC (last instruction of |
is set to true if the instruction sets the PC (last instruction of |
1381 |
a basic block) */ |
a basic block) */ |
2780 |
case 0x6d: |
case 0x6d: |
2781 |
if (s->cpl > s->iopl || s->vm86) { |
if (s->cpl > s->iopl || s->vm86) { |
2782 |
/* NOTE: even for (E)CX = 0 the exception is raised */ |
/* NOTE: even for (E)CX = 0 the exception is raised */ |
2783 |
gen_op_gpf(pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
s->is_jmp = 1; |
|
2784 |
} else { |
} else { |
2785 |
if ((b & 1) == 0) |
if ((b & 1) == 0) |
2786 |
ot = OT_BYTE; |
ot = OT_BYTE; |
2797 |
case 0x6f: |
case 0x6f: |
2798 |
if (s->cpl > s->iopl || s->vm86) { |
if (s->cpl > s->iopl || s->vm86) { |
2799 |
/* NOTE: even for (E)CX = 0 the exception is raised */ |
/* NOTE: even for (E)CX = 0 the exception is raised */ |
2800 |
gen_op_gpf(pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
s->is_jmp = 1; |
|
2801 |
} else { |
} else { |
2802 |
if ((b & 1) == 0) |
if ((b & 1) == 0) |
2803 |
ot = OT_BYTE; |
ot = OT_BYTE; |
2816 |
case 0xe4: |
case 0xe4: |
2817 |
case 0xe5: |
case 0xe5: |
2818 |
if (s->cpl > s->iopl || s->vm86) { |
if (s->cpl > s->iopl || s->vm86) { |
2819 |
gen_op_gpf(pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
s->is_jmp = 1; |
|
2820 |
} else { |
} else { |
2821 |
if ((b & 1) == 0) |
if ((b & 1) == 0) |
2822 |
ot = OT_BYTE; |
ot = OT_BYTE; |
2831 |
case 0xe6: |
case 0xe6: |
2832 |
case 0xe7: |
case 0xe7: |
2833 |
if (s->cpl > s->iopl || s->vm86) { |
if (s->cpl > s->iopl || s->vm86) { |
2834 |
gen_op_gpf(pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
s->is_jmp = 1; |
|
2835 |
} else { |
} else { |
2836 |
if ((b & 1) == 0) |
if ((b & 1) == 0) |
2837 |
ot = OT_BYTE; |
ot = OT_BYTE; |
2846 |
case 0xec: |
case 0xec: |
2847 |
case 0xed: |
case 0xed: |
2848 |
if (s->cpl > s->iopl || s->vm86) { |
if (s->cpl > s->iopl || s->vm86) { |
2849 |
gen_op_gpf(pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
s->is_jmp = 1; |
|
2850 |
} else { |
} else { |
2851 |
if ((b & 1) == 0) |
if ((b & 1) == 0) |
2852 |
ot = OT_BYTE; |
ot = OT_BYTE; |
2860 |
case 0xee: |
case 0xee: |
2861 |
case 0xef: |
case 0xef: |
2862 |
if (s->cpl > s->iopl || s->vm86) { |
if (s->cpl > s->iopl || s->vm86) { |
2863 |
gen_op_gpf(pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
s->is_jmp = 1; |
|
2864 |
} else { |
} else { |
2865 |
if ((b & 1) == 0) |
if ((b & 1) == 0) |
2866 |
ot = OT_BYTE; |
ot = OT_BYTE; |
2932 |
break; |
break; |
2933 |
case 0xcf: /* iret */ |
case 0xcf: /* iret */ |
2934 |
if (s->vm86 && s->iopl != 3) { |
if (s->vm86 && s->iopl != 3) { |
2935 |
gen_op_gpf(pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
s->is_jmp = 1; |
|
2936 |
} else { |
} else { |
2937 |
/* XXX: not restartable */ |
/* XXX: not restartable */ |
2938 |
/* pop offset */ |
/* pop offset */ |
3069 |
/* flags */ |
/* flags */ |
3070 |
case 0x9c: /* pushf */ |
case 0x9c: /* pushf */ |
3071 |
if (s->vm86 && s->iopl != 3) { |
if (s->vm86 && s->iopl != 3) { |
3072 |
gen_op_gpf(pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
s->is_jmp = 1; |
|
3073 |
} else { |
} else { |
3074 |
if (s->cc_op != CC_OP_DYNAMIC) |
if (s->cc_op != CC_OP_DYNAMIC) |
3075 |
gen_op_set_cc_op(s->cc_op); |
gen_op_set_cc_op(s->cc_op); |
3079 |
break; |
break; |
3080 |
case 0x9d: /* popf */ |
case 0x9d: /* popf */ |
3081 |
if (s->vm86 && s->iopl != 3) { |
if (s->vm86 && s->iopl != 3) { |
3082 |
gen_op_gpf(pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
s->is_jmp = 1; |
|
3083 |
} else { |
} else { |
3084 |
gen_pop_T0(s); |
gen_pop_T0(s); |
3085 |
if (s->dflag) { |
if (s->dflag) { |
3249 |
case 0x90: /* nop */ |
case 0x90: /* nop */ |
3250 |
break; |
break; |
3251 |
case 0xcc: /* int3 */ |
case 0xcc: /* int3 */ |
3252 |
gen_op_int3((long)pc_start); |
gen_exception(s, EXCP03_INT3, pc_start - s->cs_base); |
|
s->is_jmp = 1; |
|
3253 |
break; |
break; |
3254 |
case 0xcd: /* int N */ |
case 0xcd: /* int N */ |
3255 |
val = ldub(s->pc++); |
val = ldub(s->pc++); |
3256 |
|
if (s->cc_op != CC_OP_DYNAMIC) |
3257 |
|
gen_op_set_cc_op(s->cc_op); |
3258 |
gen_op_int_im(val, pc_start - s->cs_base); |
gen_op_int_im(val, pc_start - s->cs_base); |
3259 |
s->is_jmp = 1; |
s->is_jmp = 1; |
3260 |
break; |
break; |
3268 |
if (s->cpl <= s->iopl) { |
if (s->cpl <= s->iopl) { |
3269 |
gen_op_cli(); |
gen_op_cli(); |
3270 |
} else { |
} else { |
3271 |
gen_op_gpf(pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
s->is_jmp = 1; |
|
3272 |
} |
} |
3273 |
} else { |
} else { |
3274 |
if (s->iopl == 3) { |
if (s->iopl == 3) { |
3275 |
gen_op_cli(); |
gen_op_cli(); |
3276 |
} else { |
} else { |
3277 |
gen_op_gpf(pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
s->is_jmp = 1; |
|
3278 |
} |
} |
3279 |
} |
} |
3280 |
break; |
break; |
3283 |
if (s->cpl <= s->iopl) { |
if (s->cpl <= s->iopl) { |
3284 |
gen_op_sti(); |
gen_op_sti(); |
3285 |
} else { |
} else { |
3286 |
gen_op_gpf(pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
s->is_jmp = 1; |
|
3287 |
} |
} |
3288 |
} else { |
} else { |
3289 |
if (s->iopl == 3) { |
if (s->iopl == 3) { |
3290 |
gen_op_sti(); |
gen_op_sti(); |
3291 |
} else { |
} else { |
3292 |
gen_op_gpf(pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
s->is_jmp = 1; |
|
3293 |
} |
} |
3294 |
} |
} |
3295 |
break; |
break; |
3341 |
break; |
break; |
3342 |
case 0xf4: /* hlt */ |
case 0xf4: /* hlt */ |
3343 |
/* XXX: if cpl == 0, then should do something else */ |
/* XXX: if cpl == 0, then should do something else */ |
3344 |
gen_op_gpf(pc_start - s->cs_base); |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
s->is_jmp = 1; |
|
3345 |
break; |
break; |
3346 |
default: |
default: |
3347 |
goto illegal_op; |
goto illegal_op; |
3450 |
[INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z, |
[INDEX_op_setle_T0_subl] = CC_O | CC_S | CC_Z, |
3451 |
|
|
3452 |
[INDEX_op_movl_T0_eflags] = CC_OSZAPC, |
[INDEX_op_movl_T0_eflags] = CC_OSZAPC, |
|
[INDEX_op_movl_T0_eflags_vm] = CC_OSZAPC, |
|
3453 |
[INDEX_op_cmc] = CC_C, |
[INDEX_op_cmc] = CC_C, |
3454 |
[INDEX_op_salc] = CC_C, |
[INDEX_op_salc] = CC_C, |
3455 |
|
|
3500 |
|
|
3501 |
[INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C, |
[INDEX_op_movb_eflags_T0] = CC_S | CC_Z | CC_A | CC_P | CC_C, |
3502 |
[INDEX_op_movw_eflags_T0] = CC_OSZAPC, |
[INDEX_op_movw_eflags_T0] = CC_OSZAPC, |
|
[INDEX_op_movw_eflags_T0_vm] = CC_OSZAPC, |
|
3503 |
[INDEX_op_movl_eflags_T0] = CC_OSZAPC, |
[INDEX_op_movl_eflags_T0] = CC_OSZAPC, |
|
[INDEX_op_movl_eflags_T0_vm] = CC_OSZAPC, |
|
3504 |
[INDEX_op_clc] = CC_C, |
[INDEX_op_clc] = CC_C, |
3505 |
[INDEX_op_stc] = CC_C, |
[INDEX_op_stc] = CC_C, |
3506 |
[INDEX_op_cmc] = CC_C, |
[INDEX_op_cmc] = CC_C, |
3720 |
dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1; |
dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1; |
3721 |
dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3; |
dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3; |
3722 |
dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3; |
dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3; |
3723 |
|
dc->tf = (flags >> GEN_FLAG_TF_SHIFT) & 1; |
3724 |
dc->cc_op = CC_OP_DYNAMIC; |
dc->cc_op = CC_OP_DYNAMIC; |
3725 |
dc->cs_base = cs_base; |
dc->cs_base = cs_base; |
3726 |
|
|
3742 |
break; |
break; |
3743 |
} |
} |
3744 |
pc_ptr = (void *)ret; |
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; |
3749 |
} while (!dc->is_jmp && gen_opc_ptr < gen_opc_end); |
} while (!dc->is_jmp && gen_opc_ptr < gen_opc_end); |
3750 |
/* we must store the eflags state if it is not already done */ |
/* we must store the eflags state if it is not already done */ |
3751 |
if (dc->cc_op != CC_OP_DYNAMIC) |
if (dc->cc_op != CC_OP_DYNAMIC) |
3754 |
/* we add an additionnal jmp to update the simulated PC */ |
/* we add an additionnal jmp to update the simulated PC */ |
3755 |
gen_op_jmp_im(ret - (unsigned long)dc->cs_base); |
gen_op_jmp_im(ret - (unsigned long)dc->cs_base); |
3756 |
} |
} |
3757 |
|
if (dc->tf) { |
3758 |
|
gen_op_raise_exception(EXCP01_SSTP); |
3759 |
|
} |
3760 |
|
|
3761 |
*gen_opc_ptr = INDEX_op_end; |
*gen_opc_ptr = INDEX_op_end; |
3762 |
|
|
3763 |
#ifdef DEBUG_DISAS |
#ifdef DEBUG_DISAS |