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, &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)

Also available in: Unified diff