Revision f115e911
b/target-i386/translate.c | ||
---|---|---|
749 | 749 |
gen_op_outl_DX_T0, |
750 | 750 |
}; |
751 | 751 |
|
752 |
static GenOpFunc *gen_op_in[3] = { |
|
753 |
gen_op_inb_T0_T1, |
|
754 |
gen_op_inw_T0_T1, |
|
755 |
gen_op_inl_T0_T1, |
|
756 |
}; |
|
757 |
|
|
758 |
static GenOpFunc *gen_op_out[3] = { |
|
759 |
gen_op_outb_T0_T1, |
|
760 |
gen_op_outw_T0_T1, |
|
761 |
gen_op_outl_T0_T1, |
|
762 |
}; |
|
763 |
|
|
764 |
static GenOpFunc *gen_check_io_T0[3] = { |
|
765 |
gen_op_check_iob_T0, |
|
766 |
gen_op_check_iow_T0, |
|
767 |
gen_op_check_iol_T0, |
|
768 |
}; |
|
769 |
|
|
770 |
static GenOpFunc *gen_check_io_DX[3] = { |
|
771 |
gen_op_check_iob_DX, |
|
772 |
gen_op_check_iow_DX, |
|
773 |
gen_op_check_iol_DX, |
|
774 |
}; |
|
775 |
|
|
776 |
static void gen_check_io(DisasContext *s, int ot, int use_dx, int cur_eip) |
|
777 |
{ |
|
778 |
if (s->pe && (s->cpl > s->iopl || s->vm86)) { |
|
779 |
if (s->cc_op != CC_OP_DYNAMIC) |
|
780 |
gen_op_set_cc_op(s->cc_op); |
|
781 |
gen_op_jmp_im(cur_eip); |
|
782 |
if (use_dx) |
|
783 |
gen_check_io_DX[ot](); |
|
784 |
else |
|
785 |
gen_check_io_T0[ot](); |
|
786 |
} |
|
787 |
} |
|
788 |
|
|
752 | 789 |
static inline void gen_movs(DisasContext *s, int ot) |
753 | 790 |
{ |
754 | 791 |
gen_string_movl_A0_ESI(s); |
... | ... | |
912 | 949 |
GEN_REPZ2(scas) |
913 | 950 |
GEN_REPZ2(cmps) |
914 | 951 |
|
915 |
static GenOpFunc *gen_op_in[3] = { |
|
916 |
gen_op_inb_T0_T1, |
|
917 |
gen_op_inw_T0_T1, |
|
918 |
gen_op_inl_T0_T1, |
|
919 |
}; |
|
920 |
|
|
921 |
static GenOpFunc *gen_op_out[3] = { |
|
922 |
gen_op_outb_T0_T1, |
|
923 |
gen_op_outw_T0_T1, |
|
924 |
gen_op_outl_T0_T1, |
|
925 |
}; |
|
926 |
|
|
927 | 952 |
enum { |
928 | 953 |
JCC_O, |
929 | 954 |
JCC_B, |
... | ... | |
3221 | 3246 |
break; |
3222 | 3247 |
case 0x6c: /* insS */ |
3223 | 3248 |
case 0x6d: |
3224 |
if (s->pe && (s->cpl > s->iopl || s->vm86)) { |
|
3225 |
/* NOTE: even for (E)CX = 0 the exception is raised */ |
|
3226 |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
3249 |
if ((b & 1) == 0) |
|
3250 |
ot = OT_BYTE; |
|
3251 |
else |
|
3252 |
ot = dflag ? OT_LONG : OT_WORD; |
|
3253 |
gen_check_io(s, ot, 1, pc_start - s->cs_base); |
|
3254 |
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
|
3255 |
gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); |
|
3227 | 3256 |
} else { |
3228 |
if ((b & 1) == 0) |
|
3229 |
ot = OT_BYTE; |
|
3230 |
else |
|
3231 |
ot = dflag ? OT_LONG : OT_WORD; |
|
3232 |
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
|
3233 |
gen_repz_ins(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); |
|
3234 |
} else { |
|
3235 |
gen_ins(s, ot); |
|
3236 |
} |
|
3257 |
gen_ins(s, ot); |
|
3237 | 3258 |
} |
3238 | 3259 |
break; |
3239 | 3260 |
case 0x6e: /* outsS */ |
3240 | 3261 |
case 0x6f: |
3241 |
if (s->pe && (s->cpl > s->iopl || s->vm86)) { |
|
3242 |
/* NOTE: even for (E)CX = 0 the exception is raised */ |
|
3243 |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
3262 |
if ((b & 1) == 0) |
|
3263 |
ot = OT_BYTE; |
|
3264 |
else |
|
3265 |
ot = dflag ? OT_LONG : OT_WORD; |
|
3266 |
gen_check_io(s, ot, 1, pc_start - s->cs_base); |
|
3267 |
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
|
3268 |
gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); |
|
3244 | 3269 |
} else { |
3245 |
if ((b & 1) == 0) |
|
3246 |
ot = OT_BYTE; |
|
3247 |
else |
|
3248 |
ot = dflag ? OT_LONG : OT_WORD; |
|
3249 |
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
|
3250 |
gen_repz_outs(s, ot, pc_start - s->cs_base, s->pc - s->cs_base); |
|
3251 |
} else { |
|
3252 |
gen_outs(s, ot); |
|
3253 |
} |
|
3270 |
gen_outs(s, ot); |
|
3254 | 3271 |
} |
3255 | 3272 |
break; |
3256 | 3273 |
|
... | ... | |
3258 | 3275 |
/* port I/O */ |
3259 | 3276 |
case 0xe4: |
3260 | 3277 |
case 0xe5: |
3261 |
if (s->pe && (s->cpl > s->iopl || s->vm86)) { |
|
3262 |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
3263 |
} else { |
|
3264 |
if ((b & 1) == 0) |
|
3265 |
ot = OT_BYTE; |
|
3266 |
else |
|
3267 |
ot = dflag ? OT_LONG : OT_WORD; |
|
3268 |
val = ldub_code(s->pc++); |
|
3269 |
gen_op_movl_T0_im(val); |
|
3270 |
gen_op_in[ot](); |
|
3271 |
gen_op_mov_reg_T1[ot][R_EAX](); |
|
3272 |
} |
|
3278 |
if ((b & 1) == 0) |
|
3279 |
ot = OT_BYTE; |
|
3280 |
else |
|
3281 |
ot = dflag ? OT_LONG : OT_WORD; |
|
3282 |
val = ldub_code(s->pc++); |
|
3283 |
gen_op_movl_T0_im(val); |
|
3284 |
gen_check_io(s, ot, 0, pc_start - s->cs_base); |
|
3285 |
gen_op_in[ot](); |
|
3286 |
gen_op_mov_reg_T1[ot][R_EAX](); |
|
3273 | 3287 |
break; |
3274 | 3288 |
case 0xe6: |
3275 | 3289 |
case 0xe7: |
3276 |
if (s->pe && (s->cpl > s->iopl || s->vm86)) { |
|
3277 |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
3278 |
} else { |
|
3279 |
if ((b & 1) == 0) |
|
3280 |
ot = OT_BYTE; |
|
3281 |
else |
|
3282 |
ot = dflag ? OT_LONG : OT_WORD; |
|
3283 |
val = ldub_code(s->pc++); |
|
3284 |
gen_op_movl_T0_im(val); |
|
3285 |
gen_op_mov_TN_reg[ot][1][R_EAX](); |
|
3286 |
gen_op_out[ot](); |
|
3287 |
} |
|
3290 |
if ((b & 1) == 0) |
|
3291 |
ot = OT_BYTE; |
|
3292 |
else |
|
3293 |
ot = dflag ? OT_LONG : OT_WORD; |
|
3294 |
val = ldub_code(s->pc++); |
|
3295 |
gen_op_movl_T0_im(val); |
|
3296 |
gen_check_io(s, ot, 0, pc_start - s->cs_base); |
|
3297 |
gen_op_mov_TN_reg[ot][1][R_EAX](); |
|
3298 |
gen_op_out[ot](); |
|
3288 | 3299 |
break; |
3289 | 3300 |
case 0xec: |
3290 | 3301 |
case 0xed: |
3291 |
if (s->pe && (s->cpl > s->iopl || s->vm86)) { |
|
3292 |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
3293 |
} else { |
|
3294 |
if ((b & 1) == 0) |
|
3295 |
ot = OT_BYTE; |
|
3296 |
else |
|
3297 |
ot = dflag ? OT_LONG : OT_WORD; |
|
3298 |
gen_op_mov_TN_reg[OT_WORD][0][R_EDX](); |
|
3299 |
gen_op_in[ot](); |
|
3300 |
gen_op_mov_reg_T1[ot][R_EAX](); |
|
3301 |
} |
|
3302 |
if ((b & 1) == 0) |
|
3303 |
ot = OT_BYTE; |
|
3304 |
else |
|
3305 |
ot = dflag ? OT_LONG : OT_WORD; |
|
3306 |
gen_op_mov_TN_reg[OT_WORD][0][R_EDX](); |
|
3307 |
gen_check_io(s, ot, 0, pc_start - s->cs_base); |
|
3308 |
gen_op_in[ot](); |
|
3309 |
gen_op_mov_reg_T1[ot][R_EAX](); |
|
3302 | 3310 |
break; |
3303 | 3311 |
case 0xee: |
3304 | 3312 |
case 0xef: |
3305 |
if (s->pe && (s->cpl > s->iopl || s->vm86)) { |
|
3306 |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
3307 |
} else { |
|
3308 |
if ((b & 1) == 0) |
|
3309 |
ot = OT_BYTE; |
|
3310 |
else |
|
3311 |
ot = dflag ? OT_LONG : OT_WORD; |
|
3312 |
gen_op_mov_TN_reg[OT_WORD][0][R_EDX](); |
|
3313 |
gen_op_mov_TN_reg[ot][1][R_EAX](); |
|
3314 |
gen_op_out[ot](); |
|
3315 |
} |
|
3313 |
if ((b & 1) == 0) |
|
3314 |
ot = OT_BYTE; |
|
3315 |
else |
|
3316 |
ot = dflag ? OT_LONG : OT_WORD; |
|
3317 |
gen_op_mov_TN_reg[OT_WORD][0][R_EDX](); |
|
3318 |
gen_check_io(s, ot, 0, pc_start - s->cs_base); |
|
3319 |
gen_op_mov_TN_reg[ot][1][R_EAX](); |
|
3320 |
gen_op_out[ot](); |
|
3316 | 3321 |
break; |
3317 | 3322 |
|
3318 | 3323 |
/************************/ |
... | ... | |
3370 | 3375 |
/* real mode */ |
3371 | 3376 |
gen_op_iret_real(s->dflag); |
3372 | 3377 |
s->cc_op = CC_OP_EFLAGS; |
3373 |
} else if (s->vm86 && s->iopl != 3) { |
|
3374 |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
3378 |
} else if (s->vm86) { |
|
3379 |
if (s->iopl != 3) { |
|
3380 |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
|
3381 |
} else { |
|
3382 |
gen_op_iret_real(s->dflag); |
|
3383 |
s->cc_op = CC_OP_EFLAGS; |
|
3384 |
} |
|
3375 | 3385 |
} else { |
3376 | 3386 |
if (s->cc_op != CC_OP_DYNAMIC) |
3377 | 3387 |
gen_op_set_cc_op(s->cc_op); |
... | ... | |
3675 | 3685 |
break; |
3676 | 3686 |
case 0xcd: /* int N */ |
3677 | 3687 |
val = ldub_code(s->pc++); |
3678 |
/* XXX: add error code for vm86 GPF */ |
|
3679 |
if (!s->vm86) |
|
3680 |
gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base); |
|
3681 |
else |
|
3688 |
if (s->vm86 && s->iopl != 3) { |
|
3682 | 3689 |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3690 |
} else { |
|
3691 |
gen_interrupt(s, val, pc_start - s->cs_base, s->pc - s->cs_base); |
|
3692 |
} |
|
3683 | 3693 |
break; |
3684 | 3694 |
case 0xce: /* into */ |
3685 | 3695 |
if (s->cc_op != CC_OP_DYNAMIC) |
... | ... | |
3799 | 3809 |
op = (modrm >> 3) & 7; |
3800 | 3810 |
switch(op) { |
3801 | 3811 |
case 0: /* sldt */ |
3812 |
if (!s->pe || s->vm86) |
|
3813 |
goto illegal_op; |
|
3802 | 3814 |
gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector)); |
3803 | 3815 |
ot = OT_WORD; |
3804 | 3816 |
if (mod == 3) |
... | ... | |
3806 | 3818 |
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); |
3807 | 3819 |
break; |
3808 | 3820 |
case 2: /* lldt */ |
3821 |
if (!s->pe || s->vm86) |
|
3822 |
goto illegal_op; |
|
3809 | 3823 |
if (s->cpl != 0) { |
3810 | 3824 |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3811 | 3825 |
} else { |
... | ... | |
3815 | 3829 |
} |
3816 | 3830 |
break; |
3817 | 3831 |
case 1: /* str */ |
3832 |
if (!s->pe || s->vm86) |
|
3833 |
goto illegal_op; |
|
3818 | 3834 |
gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector)); |
3819 | 3835 |
ot = OT_WORD; |
3820 | 3836 |
if (mod == 3) |
... | ... | |
3822 | 3838 |
gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); |
3823 | 3839 |
break; |
3824 | 3840 |
case 3: /* ltr */ |
3841 |
if (!s->pe || s->vm86) |
|
3842 |
goto illegal_op; |
|
3825 | 3843 |
if (s->cpl != 0) { |
3826 | 3844 |
gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); |
3827 | 3845 |
} else { |
... | ... | |
3832 | 3850 |
break; |
3833 | 3851 |
case 4: /* verr */ |
3834 | 3852 |
case 5: /* verw */ |
3853 |
if (!s->pe || s->vm86) |
|
3854 |
goto illegal_op; |
|
3855 |
gen_ldst_modrm(s, modrm, OT_WORD, OR_TMP0, 0); |
|
3856 |
if (s->cc_op != CC_OP_DYNAMIC) |
|
3857 |
gen_op_set_cc_op(s->cc_op); |
|
3858 |
if (op == 4) |
|
3859 |
gen_op_verr(); |
|
3860 |
else |
|
3861 |
gen_op_verw(); |
|
3862 |
s->cc_op = CC_OP_EFLAGS; |
|
3863 |
break; |
|
3835 | 3864 |
default: |
3836 | 3865 |
goto illegal_op; |
3837 | 3866 |
} |
... | ... | |
3908 | 3937 |
goto illegal_op; |
3909 | 3938 |
} |
3910 | 3939 |
break; |
3940 |
case 0x63: /* arpl */ |
|
3941 |
if (!s->pe || s->vm86) |
|
3942 |
goto illegal_op; |
|
3943 |
ot = dflag ? OT_LONG : OT_WORD; |
|
3944 |
modrm = ldub_code(s->pc++); |
|
3945 |
reg = (modrm >> 3) & 7; |
|
3946 |
mod = (modrm >> 6) & 3; |
|
3947 |
rm = modrm & 7; |
|
3948 |
if (mod != 3) { |
|
3949 |
gen_lea_modrm(s, modrm, ®_addr, &offset_addr); |
|
3950 |
gen_op_ld_T0_A0[ot + s->mem_index](); |
|
3951 |
} else { |
|
3952 |
gen_op_mov_TN_reg[ot][0][rm](); |
|
3953 |
} |
|
3954 |
if (s->cc_op != CC_OP_DYNAMIC) |
|
3955 |
gen_op_set_cc_op(s->cc_op); |
|
3956 |
gen_op_arpl(); |
|
3957 |
s->cc_op = CC_OP_EFLAGS; |
|
3958 |
if (mod != 3) { |
|
3959 |
gen_op_st_T0_A0[ot + s->mem_index](); |
|
3960 |
} else { |
|
3961 |
gen_op_mov_reg_T0[ot][rm](); |
|
3962 |
} |
|
3963 |
gen_op_arpl_update(); |
|
3964 |
break; |
|
3911 | 3965 |
case 0x102: /* lar */ |
3912 | 3966 |
case 0x103: /* lsl */ |
3913 | 3967 |
if (!s->pe || s->vm86) |
Also available in: Unified diff