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,6 +749,43 @@ static GenOpFunc *gen_op_out_DX_T0[3] = {
749 gen_op_outl_DX_T0, 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 static inline void gen_movs(DisasContext *s, int ot) 789 static inline void gen_movs(DisasContext *s, int ot)
753 { 790 {
754 gen_string_movl_A0_ESI(s); 791 gen_string_movl_A0_ESI(s);
@@ -912,18 +949,6 @@ GEN_REPZ(outs) @@ -912,18 +949,6 @@ GEN_REPZ(outs)
912 GEN_REPZ2(scas) 949 GEN_REPZ2(scas)
913 GEN_REPZ2(cmps) 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 enum { 952 enum {
928 JCC_O, 953 JCC_O,
929 JCC_B, 954 JCC_B,
@@ -3221,36 +3246,28 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) @@ -3221,36 +3246,28 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
3221 break; 3246 break;
3222 case 0x6c: /* insS */ 3247 case 0x6c: /* insS */
3223 case 0x6d: 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 } else { 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 break; 3259 break;
3239 case 0x6e: /* outsS */ 3260 case 0x6e: /* outsS */
3240 case 0x6f: 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 } else { 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 break; 3272 break;
3256 3273
@@ -3258,61 +3275,49 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) @@ -3258,61 +3275,49 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
3258 /* port I/O */ 3275 /* port I/O */
3259 case 0xe4: 3276 case 0xe4:
3260 case 0xe5: 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 break; 3287 break;
3274 case 0xe6: 3288 case 0xe6:
3275 case 0xe7: 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 break; 3299 break;
3289 case 0xec: 3300 case 0xec:
3290 case 0xed: 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 break; 3310 break;
3303 case 0xee: 3311 case 0xee:
3304 case 0xef: 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 break; 3321 break;
3317 3322
3318 /************************/ 3323 /************************/
@@ -3370,8 +3375,13 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) @@ -3370,8 +3375,13 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
3370 /* real mode */ 3375 /* real mode */
3371 gen_op_iret_real(s->dflag); 3376 gen_op_iret_real(s->dflag);
3372 s->cc_op = CC_OP_EFLAGS; 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 } else { 3385 } else {
3376 if (s->cc_op != CC_OP_DYNAMIC) 3386 if (s->cc_op != CC_OP_DYNAMIC)
3377 gen_op_set_cc_op(s->cc_op); 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,11 +3685,11 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
3675 break; 3685 break;
3676 case 0xcd: /* int N */ 3686 case 0xcd: /* int N */
3677 val = ldub_code(s->pc++); 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 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 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 break; 3693 break;
3684 case 0xce: /* into */ 3694 case 0xce: /* into */
3685 if (s->cc_op != CC_OP_DYNAMIC) 3695 if (s->cc_op != CC_OP_DYNAMIC)
@@ -3799,6 +3809,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) @@ -3799,6 +3809,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
3799 op = (modrm >> 3) & 7; 3809 op = (modrm >> 3) & 7;
3800 switch(op) { 3810 switch(op) {
3801 case 0: /* sldt */ 3811 case 0: /* sldt */
  3812 + if (!s->pe || s->vm86)
  3813 + goto illegal_op;
3802 gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector)); 3814 gen_op_movl_T0_env(offsetof(CPUX86State,ldt.selector));
3803 ot = OT_WORD; 3815 ot = OT_WORD;
3804 if (mod == 3) 3816 if (mod == 3)
@@ -3806,6 +3818,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) @@ -3806,6 +3818,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
3806 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); 3818 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3807 break; 3819 break;
3808 case 2: /* lldt */ 3820 case 2: /* lldt */
  3821 + if (!s->pe || s->vm86)
  3822 + goto illegal_op;
3809 if (s->cpl != 0) { 3823 if (s->cpl != 0) {
3810 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 3824 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3811 } else { 3825 } else {
@@ -3815,6 +3829,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) @@ -3815,6 +3829,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
3815 } 3829 }
3816 break; 3830 break;
3817 case 1: /* str */ 3831 case 1: /* str */
  3832 + if (!s->pe || s->vm86)
  3833 + goto illegal_op;
3818 gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector)); 3834 gen_op_movl_T0_env(offsetof(CPUX86State,tr.selector));
3819 ot = OT_WORD; 3835 ot = OT_WORD;
3820 if (mod == 3) 3836 if (mod == 3)
@@ -3822,6 +3838,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) @@ -3822,6 +3838,8 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
3822 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1); 3838 gen_ldst_modrm(s, modrm, ot, OR_TMP0, 1);
3823 break; 3839 break;
3824 case 3: /* ltr */ 3840 case 3: /* ltr */
  3841 + if (!s->pe || s->vm86)
  3842 + goto illegal_op;
3825 if (s->cpl != 0) { 3843 if (s->cpl != 0) {
3826 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base); 3844 gen_exception(s, EXCP0D_GPF, pc_start - s->cs_base);
3827 } else { 3845 } else {
@@ -3832,6 +3850,17 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) @@ -3832,6 +3850,17 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
3832 break; 3850 break;
3833 case 4: /* verr */ 3851 case 4: /* verr */
3834 case 5: /* verw */ 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 default: 3864 default:
3836 goto illegal_op; 3865 goto illegal_op;
3837 } 3866 }
@@ -3908,6 +3937,31 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start) @@ -3908,6 +3937,31 @@ static uint8_t *disas_insn(DisasContext *s, uint8_t *pc_start)
3908 goto illegal_op; 3937 goto illegal_op;
3909 } 3938 }
3910 break; 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 case 0x102: /* lar */ 3965 case 0x102: /* lar */
3912 case 0x103: /* lsl */ 3966 case 0x103: /* lsl */
3913 if (!s->pe || s->vm86) 3967 if (!s->pe || s->vm86)