Commit f115e911d70dedbbab90efe589b267bf53178f10

Authored by bellard
1 parent 3ab493de

iret and int fix for vm86 - added undefined instructions for real and vm86 modes…

… - added verr, verrw, arpl - added port io map


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@454 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 142 additions and 88 deletions
target-i386/translate.c
... ... @@ -749,6 +749,43 @@ static GenOpFunc *gen_op_out_DX_T0[3] = {
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,18 +949,6 @@ GEN_REPZ(outs)
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,36 +3246,28 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
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,61 +3275,49 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
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,8 +3375,13 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
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,11 +3685,11 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
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,6 +3809,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
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,6 +3818,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
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,6 +3829,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
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,6 +3838,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
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,6 +3850,17 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
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,6 +3937,31 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
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, &reg_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)
... ...