130 |
int addseg; /* non zero if either DS/ES/SS have a non zero base */ |
int addseg; /* non zero if either DS/ES/SS have a non zero base */ |
131 |
int f_st; /* currently unused */ |
int f_st; /* currently unused */ |
132 |
int vm86; /* vm86 mode */ |
int vm86; /* vm86 mode */ |
133 |
|
int cpl; |
134 |
|
int iopl; |
135 |
} DisasContext; |
} DisasContext; |
136 |
|
|
137 |
/* i386 arith/logic operations */ |
/* i386 arith/logic operations */ |
2768 |
break; |
break; |
2769 |
case 0x6c: /* insS */ |
case 0x6c: /* insS */ |
2770 |
case 0x6d: |
case 0x6d: |
2771 |
if ((b & 1) == 0) |
if (s->cpl > s->iopl || s->vm86) { |
2772 |
ot = OT_BYTE; |
/* NOTE: even for (E)CX = 0 the exception is raised */ |
2773 |
else |
gen_op_gpf(pc_start - s->cs_base); |
|
ot = dflag ? OT_LONG : OT_WORD; |
|
|
if (prefixes & PREFIX_REPZ) { |
|
|
gen_string_es(s, ot, gen_op_ins + 9); |
|
2774 |
} else { |
} else { |
2775 |
gen_string_es(s, ot, gen_op_ins); |
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 |
|
} |
2784 |
} |
} |
2785 |
break; |
break; |
2786 |
case 0x6e: /* outsS */ |
case 0x6e: /* outsS */ |
2787 |
case 0x6f: |
case 0x6f: |
2788 |
if ((b & 1) == 0) |
if (s->cpl > s->iopl || s->vm86) { |
2789 |
ot = OT_BYTE; |
/* NOTE: even for (E)CX = 0 the exception is raised */ |
2790 |
else |
gen_op_gpf(pc_start - s->cs_base); |
|
ot = dflag ? OT_LONG : OT_WORD; |
|
|
if (prefixes & PREFIX_REPZ) { |
|
|
gen_string_ds(s, ot, gen_op_outs + 9); |
|
2791 |
} else { |
} else { |
2792 |
gen_string_ds(s, ot, gen_op_outs); |
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 |
|
} |
2801 |
} |
} |
2802 |
break; |
break; |
2803 |
|
|
2805 |
/* port I/O */ |
/* port I/O */ |
2806 |
case 0xe4: |
case 0xe4: |
2807 |
case 0xe5: |
case 0xe5: |
2808 |
if ((b & 1) == 0) |
if (s->cpl > s->iopl || s->vm86) { |
2809 |
ot = OT_BYTE; |
gen_op_gpf(pc_start - s->cs_base); |
2810 |
else |
} else { |
2811 |
ot = dflag ? OT_LONG : OT_WORD; |
if ((b & 1) == 0) |
2812 |
val = ldub(s->pc++); |
ot = OT_BYTE; |
2813 |
gen_op_movl_T0_im(val); |
else |
2814 |
gen_op_in[ot](); |
ot = dflag ? OT_LONG : OT_WORD; |
2815 |
gen_op_mov_reg_T1[ot][R_EAX](); |
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 |
|
} |
2820 |
break; |
break; |
2821 |
case 0xe6: |
case 0xe6: |
2822 |
case 0xe7: |
case 0xe7: |
2823 |
if ((b & 1) == 0) |
if (s->cpl > s->iopl || s->vm86) { |
2824 |
ot = OT_BYTE; |
gen_op_gpf(pc_start - s->cs_base); |
2825 |
else |
} else { |
2826 |
ot = dflag ? OT_LONG : OT_WORD; |
if ((b & 1) == 0) |
2827 |
val = ldub(s->pc++); |
ot = OT_BYTE; |
2828 |
gen_op_movl_T0_im(val); |
else |
2829 |
gen_op_mov_TN_reg[ot][1][R_EAX](); |
ot = dflag ? OT_LONG : OT_WORD; |
2830 |
gen_op_out[ot](); |
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 |
|
} |
2835 |
break; |
break; |
2836 |
case 0xec: |
case 0xec: |
2837 |
case 0xed: |
case 0xed: |
2838 |
if ((b & 1) == 0) |
if (s->cpl > s->iopl || s->vm86) { |
2839 |
ot = OT_BYTE; |
gen_op_gpf(pc_start - s->cs_base); |
2840 |
else |
} else { |
2841 |
ot = dflag ? OT_LONG : OT_WORD; |
if ((b & 1) == 0) |
2842 |
gen_op_mov_TN_reg[OT_WORD][0][R_EDX](); |
ot = OT_BYTE; |
2843 |
gen_op_in[ot](); |
else |
2844 |
gen_op_mov_reg_T1[ot][R_EAX](); |
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 |
|
} |
2849 |
break; |
break; |
2850 |
case 0xee: |
case 0xee: |
2851 |
case 0xef: |
case 0xef: |
2852 |
if ((b & 1) == 0) |
if (s->cpl > s->iopl || s->vm86) { |
2853 |
ot = OT_BYTE; |
gen_op_gpf(pc_start - s->cs_base); |
2854 |
else |
} else { |
2855 |
ot = dflag ? OT_LONG : OT_WORD; |
if ((b & 1) == 0) |
2856 |
gen_op_mov_TN_reg[OT_WORD][0][R_EDX](); |
ot = OT_BYTE; |
2857 |
gen_op_mov_TN_reg[ot][1][R_EAX](); |
else |
2858 |
gen_op_out[ot](); |
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 |
|
} |
2863 |
break; |
break; |
2864 |
|
|
2865 |
/************************/ |
/************************/ |
3247 |
break; |
break; |
3248 |
case 0xcd: /* int N */ |
case 0xcd: /* int N */ |
3249 |
val = ldub(s->pc++); |
val = ldub(s->pc++); |
3250 |
/* XXX: currently we ignore the interrupt number */ |
gen_op_int_im(val, pc_start - s->cs_base); |
|
gen_op_int_im(pc_start - s->cs_base); |
|
3251 |
s->is_jmp = 1; |
s->is_jmp = 1; |
3252 |
break; |
break; |
3253 |
case 0xce: /* into */ |
case 0xce: /* into */ |
3256 |
gen_op_into(); |
gen_op_into(); |
3257 |
break; |
break; |
3258 |
case 0xfa: /* cli */ |
case 0xfa: /* cli */ |
3259 |
if (s->vm86) |
if (!s->vm86) { |
3260 |
gen_op_cli_vm(); |
if (s->cpl <= s->iopl) |
3261 |
else |
gen_op_cli(); |
3262 |
gen_op_cli(); |
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 |
|
} |
3270 |
break; |
break; |
3271 |
case 0xfb: /* sti */ |
case 0xfb: /* sti */ |
3272 |
if (s->vm86) |
if (!s->vm86) { |
3273 |
gen_op_sti_vm(pc_start - s->cs_base); |
if (s->cpl <= s->iopl) |
3274 |
else |
gen_op_sti(); |
3275 |
gen_op_sti(); |
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 |
|
} |
3283 |
break; |
break; |
3284 |
case 0x62: /* bound */ |
case 0x62: /* bound */ |
3285 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
3327 |
case 0x1a2: /* cpuid */ |
case 0x1a2: /* cpuid */ |
3328 |
gen_op_cpuid(); |
gen_op_cpuid(); |
3329 |
break; |
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; |
3337 |
default: |
default: |
3338 |
goto illegal_op; |
goto illegal_op; |
3339 |
} |
} |
3363 |
[INDEX_op_sbbw_T0_T1_cc] = CC_C, |
[INDEX_op_sbbw_T0_T1_cc] = CC_C, |
3364 |
[INDEX_op_sbbl_T0_T1_cc] = CC_C, |
[INDEX_op_sbbl_T0_T1_cc] = CC_C, |
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 |
|
|
3370 |
[INDEX_op_into] = CC_O, |
[INDEX_op_into] = CC_O, |
3371 |
|
|
3372 |
[INDEX_op_jo_cc] = CC_O, |
[INDEX_op_jo_cc] = CC_O, |
3468 |
[INDEX_op_xorl_T0_T1_cc] = CC_OSZAPC, |
[INDEX_op_xorl_T0_T1_cc] = CC_OSZAPC, |
3469 |
[INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC, |
[INDEX_op_cmpl_T0_T1_cc] = CC_OSZAPC, |
3470 |
[INDEX_op_negl_T0_cc] = CC_OSZAPC, |
[INDEX_op_negl_T0_cc] = CC_OSZAPC, |
3471 |
[INDEX_op_incl_T0_cc] = CC_OSZAP, |
/* subtle: due to the incl/decl implementation, C is used */ |
3472 |
[INDEX_op_decl_T0_cc] = CC_OSZAP, |
[INDEX_op_incl_T0_cc] = CC_OSZAPC, |
3473 |
|
[INDEX_op_decl_T0_cc] = CC_OSZAPC, |
3474 |
[INDEX_op_testl_T0_T1_cc] = CC_OSZAPC, |
[INDEX_op_testl_T0_T1_cc] = CC_OSZAPC, |
3475 |
|
|
3476 |
[INDEX_op_mulb_AL_T0] = CC_OSZAPC, |
[INDEX_op_mulb_AL_T0] = CC_OSZAPC, |
3712 |
dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1; |
dc->addseg = (flags >> GEN_FLAG_ADDSEG_SHIFT) & 1; |
3713 |
dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7; |
dc->f_st = (flags >> GEN_FLAG_ST_SHIFT) & 7; |
3714 |
dc->vm86 = (flags >> GEN_FLAG_VM_SHIFT) & 1; |
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; |
3717 |
dc->cc_op = CC_OP_DYNAMIC; |
dc->cc_op = CC_OP_DYNAMIC; |
3718 |
dc->cs_base = cs_base; |
dc->cs_base = cs_base; |
3719 |
|
|
3752 |
disas(logfile, pc_start, pc_ptr - pc_start, |
disas(logfile, pc_start, pc_ptr - pc_start, |
3753 |
dc->code32 ? DISAS_I386_I386 : DISAS_I386_I8086); |
dc->code32 ? DISAS_I386_I386 : DISAS_I386_I8086); |
3754 |
fprintf(logfile, "\n"); |
fprintf(logfile, "\n"); |
3755 |
|
|
3756 |
fprintf(logfile, "OP:\n"); |
fprintf(logfile, "OP:\n"); |
3757 |
dump_ops(gen_opc_buf, gen_opparam_buf); |
dump_ops(gen_opc_buf, gen_opparam_buf); |
3758 |
fprintf(logfile, "\n"); |
fprintf(logfile, "\n"); |