Revision 982b4315 translate-i386.c
b/translate-i386.c | ||
---|---|---|
130 | 130 |
int addseg; /* non zero if either DS/ES/SS have a non zero base */ |
131 | 131 |
int f_st; /* currently unused */ |
132 | 132 |
int vm86; /* vm86 mode */ |
133 |
int cpl; |
|
134 |
int iopl; |
|
133 | 135 |
} DisasContext; |
134 | 136 |
|
135 | 137 |
/* i386 arith/logic operations */ |
... | ... | |
2766 | 2768 |
break; |
2767 | 2769 |
case 0x6c: /* insS */ |
2768 | 2770 |
case 0x6d: |
2769 |
if ((b & 1) == 0) |
|
2770 |
ot = OT_BYTE; |
|
2771 |
else |
|
2772 |
ot = dflag ? OT_LONG : OT_WORD; |
|
2773 |
if (prefixes & PREFIX_REPZ) { |
|
2774 |
gen_string_es(s, ot, gen_op_ins + 9); |
|
2771 |
if (s->cpl > s->iopl || s->vm86) { |
|
2772 |
/* NOTE: even for (E)CX = 0 the exception is raised */ |
|
2773 |
gen_op_gpf(pc_start - s->cs_base); |
|
2775 | 2774 |
} else { |
2776 |
gen_string_es(s, ot, gen_op_ins); |
|
2775 |
if ((b & 1) == 0) |
|
2776 |
ot = OT_BYTE; |
|
2777 |
else |
|
2778 |
ot = dflag ? OT_LONG : OT_WORD; |
|
2779 |
if (prefixes & PREFIX_REPZ) { |
|
2780 |
gen_string_es(s, ot, gen_op_ins + 9); |
|
2781 |
} else { |
|
2782 |
gen_string_es(s, ot, gen_op_ins); |
|
2783 |
} |
|
2777 | 2784 |
} |
2778 | 2785 |
break; |
2779 | 2786 |
case 0x6e: /* outsS */ |
2780 | 2787 |
case 0x6f: |
2781 |
if ((b & 1) == 0) |
|
2782 |
ot = OT_BYTE; |
|
2783 |
else |
|
2784 |
ot = dflag ? OT_LONG : OT_WORD; |
|
2785 |
if (prefixes & PREFIX_REPZ) { |
|
2786 |
gen_string_ds(s, ot, gen_op_outs + 9); |
|
2788 |
if (s->cpl > s->iopl || s->vm86) { |
|
2789 |
/* NOTE: even for (E)CX = 0 the exception is raised */ |
|
2790 |
gen_op_gpf(pc_start - s->cs_base); |
|
2787 | 2791 |
} else { |
2788 |
gen_string_ds(s, ot, gen_op_outs); |
|
2792 |
if ((b & 1) == 0) |
|
2793 |
ot = OT_BYTE; |
|
2794 |
else |
|
2795 |
ot = dflag ? OT_LONG : OT_WORD; |
|
2796 |
if (prefixes & PREFIX_REPZ) { |
|
2797 |
gen_string_ds(s, ot, gen_op_outs + 9); |
|
2798 |
} else { |
|
2799 |
gen_string_ds(s, ot, gen_op_outs); |
|
2800 |
} |
|
2789 | 2801 |
} |
2790 | 2802 |
break; |
2791 | 2803 |
|
... | ... | |
2793 | 2805 |
/* port I/O */ |
2794 | 2806 |
case 0xe4: |
2795 | 2807 |
case 0xe5: |
2796 |
if ((b & 1) == 0) |
|
2797 |
ot = OT_BYTE; |
|
2798 |
else |
|
2799 |
ot = dflag ? OT_LONG : OT_WORD; |
|
2800 |
val = ldub(s->pc++); |
|
2801 |
gen_op_movl_T0_im(val); |
|
2802 |
gen_op_in[ot](); |
|
2803 |
gen_op_mov_reg_T1[ot][R_EAX](); |
|
2808 |
if (s->cpl > s->iopl || s->vm86) { |
|
2809 |
gen_op_gpf(pc_start - s->cs_base); |
|
2810 |
} else { |
|
2811 |
if ((b & 1) == 0) |
|
2812 |
ot = OT_BYTE; |
|
2813 |
else |
|
2814 |
ot = dflag ? OT_LONG : OT_WORD; |
|
2815 |
val = ldub(s->pc++); |
|
2816 |
gen_op_movl_T0_im(val); |
|
2817 |
gen_op_in[ot](); |
|
2818 |
gen_op_mov_reg_T1[ot][R_EAX](); |
|
2819 |
} |
|
2804 | 2820 |
break; |
2805 | 2821 |
case 0xe6: |
2806 | 2822 |
case 0xe7: |
2807 |
if ((b & 1) == 0) |
|
2808 |
ot = OT_BYTE; |
|
2809 |
else |
|
2810 |
ot = dflag ? OT_LONG : OT_WORD; |
|
2811 |
val = ldub(s->pc++); |
|
2812 |
gen_op_movl_T0_im(val); |
|
2813 |
gen_op_mov_TN_reg[ot][1][R_EAX](); |
|
2814 |
gen_op_out[ot](); |
|
2823 |
if (s->cpl > s->iopl || s->vm86) { |
|
2824 |
gen_op_gpf(pc_start - s->cs_base); |
|
2825 |
} else { |
|
2826 |
if ((b & 1) == 0) |
|
2827 |
ot = OT_BYTE; |
|
2828 |
else |
|
2829 |
ot = dflag ? OT_LONG : OT_WORD; |
|
2830 |
val = ldub(s->pc++); |
|
2831 |
gen_op_movl_T0_im(val); |
|
2832 |
gen_op_mov_TN_reg[ot][1][R_EAX](); |
|
2833 |
gen_op_out[ot](); |
|
2834 |
} |
|
2815 | 2835 |
break; |
2816 | 2836 |
case 0xec: |
2817 | 2837 |
case 0xed: |
2818 |
if ((b & 1) == 0) |
|
2819 |
ot = OT_BYTE; |
|
2820 |
else |
|
2821 |
ot = dflag ? OT_LONG : OT_WORD; |
|
2822 |
gen_op_mov_TN_reg[OT_WORD][0][R_EDX](); |
|
2823 |
gen_op_in[ot](); |
|
2824 |
gen_op_mov_reg_T1[ot][R_EAX](); |
|
2838 |
if (s->cpl > s->iopl || s->vm86) { |
|
2839 |
gen_op_gpf(pc_start - s->cs_base); |
|
2840 |
} else { |
|
2841 |
if ((b & 1) == 0) |
|
2842 |
ot = OT_BYTE; |
|
2843 |
else |
|
2844 |
ot = dflag ? OT_LONG : OT_WORD; |
|
2845 |
gen_op_mov_TN_reg[OT_WORD][0][R_EDX](); |
|
2846 |
gen_op_in[ot](); |
|
2847 |
gen_op_mov_reg_T1[ot][R_EAX](); |
|
2848 |
} |
|
2825 | 2849 |
break; |
2826 | 2850 |
case 0xee: |
2827 | 2851 |
case 0xef: |
2828 |
if ((b & 1) == 0) |
|
2829 |
ot = OT_BYTE; |
|
2830 |
else |
|
2831 |
ot = dflag ? OT_LONG : OT_WORD; |
|
2832 |
gen_op_mov_TN_reg[OT_WORD][0][R_EDX](); |
|
2833 |
gen_op_mov_TN_reg[ot][1][R_EAX](); |
|
2834 |
gen_op_out[ot](); |
|
2852 |
if (s->cpl > s->iopl || s->vm86) { |
|
2853 |
gen_op_gpf(pc_start - s->cs_base); |
|
2854 |
} else { |
|
2855 |
if ((b & 1) == 0) |
|
2856 |
ot = OT_BYTE; |
|
2857 |
else |
|
2858 |
ot = dflag ? OT_LONG : OT_WORD; |
|
2859 |
gen_op_mov_TN_reg[OT_WORD][0][R_EDX](); |
|
2860 |
gen_op_mov_TN_reg[ot][1][R_EAX](); |
|
2861 |
gen_op_out[ot](); |
|
2862 |
} |
|
2835 | 2863 |
break; |
2836 | 2864 |
|
2837 | 2865 |
/************************/ |
... | ... | |
3219 | 3247 |
break; |
3220 | 3248 |
case 0xcd: /* int N */ |
3221 | 3249 |
val = ldub(s->pc++); |
3222 |
/* XXX: currently we ignore the interrupt number */ |
|
3223 |
gen_op_int_im(pc_start - s->cs_base); |
|
3250 |
gen_op_int_im(val, pc_start - s->cs_base); |
|
3224 | 3251 |
s->is_jmp = 1; |
3225 | 3252 |
break; |
3226 | 3253 |
case 0xce: /* into */ |
... | ... | |
3229 | 3256 |
gen_op_into(); |
3230 | 3257 |
break; |
3231 | 3258 |
case 0xfa: /* cli */ |
3232 |
if (s->vm86) |
|
3233 |
gen_op_cli_vm(); |
|
3234 |
else |
|
3235 |
gen_op_cli(); |
|
3259 |
if (!s->vm86) { |
|
3260 |
if (s->cpl <= s->iopl) |
|
3261 |
gen_op_cli(); |
|
3262 |
else |
|
3263 |
gen_op_gpf(pc_start - s->cs_base); |
|
3264 |
} else { |
|
3265 |
if (s->iopl == 3) |
|
3266 |
gen_op_cli(); |
|
3267 |
else |
|
3268 |
gen_op_cli_vm(); |
|
3269 |
} |
|
3236 | 3270 |
break; |
3237 | 3271 |
case 0xfb: /* sti */ |
3238 |
if (s->vm86) |
|
3239 |
gen_op_sti_vm(pc_start - s->cs_base); |
|
3240 |
else |
|
3241 |
gen_op_sti(); |
|
3272 |
if (!s->vm86) { |
|
3273 |
if (s->cpl <= s->iopl) |
|
3274 |
gen_op_sti(); |
|
3275 |
else |
|
3276 |
gen_op_gpf(pc_start - s->cs_base); |
|
3277 |
} else { |
|
3278 |
if (s->iopl == 3) |
|
3279 |
gen_op_sti(); |
|
3280 |
else |
|
3281 |
gen_op_sti_vm(pc_start - s->cs_base); |
|
3282 |
} |
|
3242 | 3283 |
break; |
3243 | 3284 |
case 0x62: /* bound */ |
3244 | 3285 |
ot = dflag ? OT_LONG : OT_WORD; |
... | ... | |
3286 | 3327 |
case 0x1a2: /* cpuid */ |
3287 | 3328 |
gen_op_cpuid(); |
3288 | 3329 |
break; |
3330 |
case 0xf4: /* hlt */ |
|
3331 |
if (s->cpl == 0) { |
|
3332 |
/* ignored */ |
|
3333 |
} else { |
|
3334 |
gen_op_gpf(pc_start - s->cs_base); |
|
3335 |
} |
|
3336 |
break; |
|
3289 | 3337 |
default: |
3290 | 3338 |
goto illegal_op; |
3291 | 3339 |
} |
... | ... | |
3315 | 3363 |
[INDEX_op_sbbw_T0_T1_cc] = CC_C, |
3316 | 3364 |
[INDEX_op_sbbl_T0_T1_cc] = CC_C, |
3317 | 3365 |
|
3366 |
/* subtle: due to the incl/decl implementation, C is used */ |
|
3367 |
[INDEX_op_incl_T0_cc] = CC_C, |
|
3368 |
[INDEX_op_decl_T0_cc] = CC_C, |
|
3369 |
|
|
3318 | 3370 |
[INDEX_op_into] = CC_O, |
3319 | 3371 |
|
3320 | 3372 |
[INDEX_op_jo_cc] = CC_O, |
... | ... | |
3416 | 3468 |
[INDEX_op_xorl_T0_T1_cc] = CC_OSZAPC, |
3417 | 3469 |
[INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC, |
3418 | 3470 |
[INDEX_op_negl_T0_cc] = CC_OSZAPC, |
3419 |
[INDEX_op_incl_T0_cc] = CC_OSZAP, |
|
3420 |
[INDEX_op_decl_T0_cc] = CC_OSZAP, |
|
3471 |
/* subtle: due to the incl/decl implementation, C is used */ |
|
3472 |
[INDEX_op_incl_T0_cc] = CC_OSZAPC, |
|
3473 |
[INDEX_op_decl_T0_cc] = CC_OSZAPC, |
|
3421 | 3474 |
[INDEX_op_testl_T0_T1_cc] = CC_OSZAPC, |
3422 | 3475 |
|
3423 | 3476 |
[INDEX_op_mulb_AL_T0] = CC_OSZAPC, |
... | ... | |
3659 | 3712 |
dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1; |
3660 | 3713 |
dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7; |
3661 | 3714 |
dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1; |
3715 |
dc->cpl = (flags >> GEN_FLAG_CPL_SHIFT) & 3; |
|
3716 |
dc->iopl = (flags >> GEN_FLAG_IOPL_SHIFT) & 3; |
|
3662 | 3717 |
dc->cc_op = CC_OP_DYNAMIC; |
3663 | 3718 |
dc->cs_base = cs_base; |
3664 | 3719 |
|
... | ... | |
3697 | 3752 |
disas(logfile, pc_start, pc_ptr - pc_start, |
3698 | 3753 |
dc->code32 ? DISAS_I386_I386 : DISAS_I386_I8086); |
3699 | 3754 |
fprintf(logfile, "\n"); |
3700 |
|
|
3755 |
|
|
3701 | 3756 |
fprintf(logfile, "OP:\n"); |
3702 | 3757 |
dump_ops(gen_opc_buf, gen_opparam_buf); |
3703 | 3758 |
fprintf(logfile, "\n"); |
Also available in: Unified diff