1832 |
s->is_jmp = 1; |
s->is_jmp = 1; |
1833 |
break; |
break; |
1834 |
case 3: /* lcall Ev */ |
case 3: /* lcall Ev */ |
|
/* push return segment + offset */ |
|
|
gen_op_movl_T0_seg(R_CS); |
|
|
gen_push_T0(s); |
|
|
next_eip = s->pc - s->cs_base; |
|
|
gen_op_movl_T0_im(next_eip); |
|
|
gen_push_T0(s); |
|
|
|
|
1835 |
gen_op_ld_T1_A0[ot](); |
gen_op_ld_T1_A0[ot](); |
1836 |
gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
1837 |
gen_op_lduw_T0_A0(); |
gen_op_lduw_T0_A0(); |
1838 |
gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base); |
do_lcall: |
1839 |
gen_op_movl_T0_T1(); |
if (s->pe && !s->vm86) { |
1840 |
gen_op_jmp_T0(); |
if (s->cc_op != CC_OP_DYNAMIC) |
1841 |
|
gen_op_set_cc_op(s->cc_op); |
1842 |
|
gen_op_jmp_im(pc_start - s->cs_base); |
1843 |
|
gen_op_lcall_protected_T0_T1(dflag, s->pc - s->cs_base); |
1844 |
|
} else { |
1845 |
|
gen_op_lcall_real_T0_T1(dflag, s->pc - s->cs_base); |
1846 |
|
} |
1847 |
s->is_jmp = 1; |
s->is_jmp = 1; |
1848 |
break; |
break; |
1849 |
case 4: /* jmp Ev */ |
case 4: /* jmp Ev */ |
1856 |
gen_op_ld_T1_A0[ot](); |
gen_op_ld_T1_A0[ot](); |
1857 |
gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
gen_op_addl_A0_im(1 << (ot - OT_WORD + 1)); |
1858 |
gen_op_lduw_T0_A0(); |
gen_op_lduw_T0_A0(); |
1859 |
|
do_ljmp: |
1860 |
if (s->pe && !s->vm86) { |
if (s->pe && !s->vm86) { |
1861 |
/* we compute EIP to handle the exception case */ |
if (s->cc_op != CC_OP_DYNAMIC) |
1862 |
|
gen_op_set_cc_op(s->cc_op); |
1863 |
gen_op_jmp_im(pc_start - s->cs_base); |
gen_op_jmp_im(pc_start - s->cs_base); |
1864 |
gen_op_ljmp_T0_T1(); |
gen_op_ljmp_protected_T0_T1(); |
1865 |
} else { |
} else { |
1866 |
gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS])); |
gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS])); |
1867 |
gen_op_movl_T0_T1(); |
gen_op_movl_T0_T1(); |
2868 |
else |
else |
2869 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
2870 |
|
|
2871 |
if (prefixes & PREFIX_REPZ) { |
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
2872 |
gen_string_ds(s, ot, gen_op_movs + 9); |
gen_string_ds(s, ot, gen_op_movs + 9); |
2873 |
} else { |
} else { |
2874 |
gen_string_ds(s, ot, gen_op_movs); |
gen_string_ds(s, ot, gen_op_movs); |
2882 |
else |
else |
2883 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
2884 |
|
|
2885 |
if (prefixes & PREFIX_REPZ) { |
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
2886 |
gen_string_es(s, ot, gen_op_stos + 9); |
gen_string_es(s, ot, gen_op_stos + 9); |
2887 |
} else { |
} else { |
2888 |
gen_string_es(s, ot, gen_op_stos); |
gen_string_es(s, ot, gen_op_stos); |
2894 |
ot = OT_BYTE; |
ot = OT_BYTE; |
2895 |
else |
else |
2896 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
2897 |
if (prefixes & PREFIX_REPZ) { |
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
2898 |
gen_string_ds(s, ot, gen_op_lods + 9); |
gen_string_ds(s, ot, gen_op_lods + 9); |
2899 |
} else { |
} else { |
2900 |
gen_string_ds(s, ot, gen_op_lods); |
gen_string_ds(s, ot, gen_op_lods); |
2953 |
ot = OT_BYTE; |
ot = OT_BYTE; |
2954 |
else |
else |
2955 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
2956 |
if (prefixes & PREFIX_REPZ) { |
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
2957 |
gen_string_es(s, ot, gen_op_ins + 9); |
gen_string_es(s, ot, gen_op_ins + 9); |
2958 |
} else { |
} else { |
2959 |
gen_string_es(s, ot, gen_op_ins); |
gen_string_es(s, ot, gen_op_ins); |
2970 |
ot = OT_BYTE; |
ot = OT_BYTE; |
2971 |
else |
else |
2972 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
2973 |
if (prefixes & PREFIX_REPZ) { |
if (prefixes & (PREFIX_REPZ | PREFIX_REPNZ)) { |
2974 |
gen_string_ds(s, ot, gen_op_outs + 9); |
gen_string_ds(s, ot, gen_op_outs + 9); |
2975 |
} else { |
} else { |
2976 |
gen_string_ds(s, ot, gen_op_outs); |
gen_string_ds(s, ot, gen_op_outs); |
3063 |
val = ldsw(s->pc); |
val = ldsw(s->pc); |
3064 |
s->pc += 2; |
s->pc += 2; |
3065 |
do_lret: |
do_lret: |
3066 |
gen_stack_A0(s); |
if (s->pe && !s->vm86) { |
3067 |
/* pop offset */ |
if (s->cc_op != CC_OP_DYNAMIC) |
3068 |
gen_op_ld_T0_A0[1 + s->dflag](); |
gen_op_set_cc_op(s->cc_op); |
3069 |
if (s->dflag == 0) |
gen_op_jmp_im(pc_start - s->cs_base); |
3070 |
gen_op_andl_T0_ffff(); |
gen_op_lret_protected(s->dflag, val); |
3071 |
/* NOTE: keeping EIP updated is not a problem in case of |
} else { |
3072 |
exception */ |
gen_stack_A0(s); |
3073 |
gen_op_jmp_T0(); |
/* pop offset */ |
3074 |
/* pop selector */ |
gen_op_ld_T0_A0[1 + s->dflag](); |
3075 |
gen_op_addl_A0_im(2 << s->dflag); |
if (s->dflag == 0) |
3076 |
gen_op_ld_T0_A0[1 + s->dflag](); |
gen_op_andl_T0_ffff(); |
3077 |
gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base); |
/* NOTE: keeping EIP updated is not a problem in case of |
3078 |
/* add stack offset */ |
exception */ |
3079 |
gen_stack_update(s, val + (4 << s->dflag)); |
gen_op_jmp_T0(); |
3080 |
|
/* pop selector */ |
3081 |
|
gen_op_addl_A0_im(2 << s->dflag); |
3082 |
|
gen_op_ld_T0_A0[1 + s->dflag](); |
3083 |
|
gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS])); |
3084 |
|
/* add stack offset */ |
3085 |
|
gen_stack_update(s, val + (4 << s->dflag)); |
3086 |
|
} |
3087 |
s->is_jmp = 1; |
s->is_jmp = 1; |
3088 |
break; |
break; |
3089 |
case 0xcb: /* lret */ |
case 0xcb: /* lret */ |
3122 |
case 0x9a: /* lcall im */ |
case 0x9a: /* lcall im */ |
3123 |
{ |
{ |
3124 |
unsigned int selector, offset; |
unsigned int selector, offset; |
|
/* XXX: not restartable */ |
|
3125 |
|
|
3126 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
3127 |
offset = insn_get(s, ot); |
offset = insn_get(s, ot); |
3128 |
selector = insn_get(s, OT_WORD); |
selector = insn_get(s, OT_WORD); |
3129 |
|
|
|
/* push return segment + offset */ |
|
|
gen_op_movl_T0_seg(R_CS); |
|
|
gen_push_T0(s); |
|
|
next_eip = s->pc - s->cs_base; |
|
|
gen_op_movl_T0_im(next_eip); |
|
|
gen_push_T0(s); |
|
|
|
|
|
/* change cs and pc */ |
|
3130 |
gen_op_movl_T0_im(selector); |
gen_op_movl_T0_im(selector); |
3131 |
gen_movl_seg_T0(s, R_CS, pc_start - s->cs_base); |
gen_op_movl_T1_im(offset); |
|
gen_op_jmp_im((unsigned long)offset); |
|
|
s->is_jmp = 1; |
|
3132 |
} |
} |
3133 |
break; |
goto do_lcall; |
3134 |
case 0xe9: /* jmp */ |
case 0xe9: /* jmp */ |
3135 |
ot = dflag ? OT_LONG : OT_WORD; |
ot = dflag ? OT_LONG : OT_WORD; |
3136 |
val = insn_get(s, ot); |
val = insn_get(s, ot); |
3147 |
offset = insn_get(s, ot); |
offset = insn_get(s, ot); |
3148 |
selector = insn_get(s, OT_WORD); |
selector = insn_get(s, OT_WORD); |
3149 |
|
|
|
/* change cs and pc */ |
|
3150 |
gen_op_movl_T0_im(selector); |
gen_op_movl_T0_im(selector); |
3151 |
if (s->pe && !s->vm86) { |
gen_op_movl_T1_im(offset); |
|
/* we compute EIP to handle the exception case */ |
|
|
gen_op_jmp_im(pc_start - s->cs_base); |
|
|
gen_op_movl_T1_im(offset); |
|
|
gen_op_ljmp_T0_T1(); |
|
|
} else { |
|
|
gen_op_movl_seg_T0_vm(offsetof(CPUX86State,segs[R_CS])); |
|
|
gen_op_jmp_im((unsigned long)offset); |
|
|
} |
|
|
s->is_jmp = 1; |
|
3152 |
} |
} |
3153 |
break; |
goto do_ljmp; |
3154 |
case 0xeb: /* jmp Jb */ |
case 0xeb: /* jmp Jb */ |
3155 |
val = (int8_t)insn_get(s, OT_BYTE); |
val = (int8_t)insn_get(s, OT_BYTE); |
3156 |
val += s->pc - s->cs_base; |
val += s->pc - s->cs_base; |