return 0xffff;
}
+#ifdef TARGET_X86_64
+#define SET_ESP(val, sp_mask)\
+do {\
+ if ((sp_mask) == 0xffff)\
+ ESP = (ESP & ~0xffff) | ((val) & 0xffff);\
+ else if ((sp_mask) == 0xffffffffLL)\
+ ESP = (uint32_t)(val);\
+ else\
+ ESP = (val);\
+} while (0)
+#else
+#define SET_ESP(val, sp_mask) ESP = (ESP & ~(sp_mask)) | ((val) & (sp_mask))
+#endif
+
/* XXX: add a is_user flag to have proper security support */
#define PUSHW(ssp, sp, sp_mask, val)\
{\
{
SegmentCache *dt;
target_ulong ptr, ssp;
- int type, dpl, selector, ss_dpl, cpl, sp_mask;
+ int type, dpl, selector, ss_dpl, cpl;
int has_error_code, new_stack, shift;
uint32_t e1, e2, offset, ss, esp, ss_e1, ss_e2;
- uint32_t old_eip;
+ uint32_t old_eip, sp_mask;
has_error_code = 0;
if (!is_int && !is_hw) {
raise_exception_err(EXCP0B_NOSEG, intno * 8 + 2);
switch_tss(intno * 8, e1, e2, SWITCH_TSS_CALL, old_eip);
if (has_error_code) {
- int mask, type;
+ int type;
+ uint32_t mask;
/* push the error code */
type = (env->tr.flags >> DESC_TYPE_SHIFT) & 0xf;
shift = type >> 3;
stl_kernel(ssp, error_code);
else
stw_kernel(ssp, error_code);
- ESP = (esp & mask) | (ESP & ~mask);
+ SET_ESP(esp, mask);
}
return;
case 6: /* 286 interrupt gate */
cpu_x86_load_seg_cache(env, R_SS, ss,
ssp, get_seg_limit(ss_e1, ss_e2), ss_e2);
}
- ESP = (ESP & ~sp_mask) | (esp & sp_mask);
+ SET_ESP(esp, sp_mask);
selector = (selector & ~3) | dpl;
cpu_x86_load_seg_cache(env, R_CS, selector,
PUSHW(ssp, esp, esp_mask, next_eip);
}
- ESP = (ESP & ~esp_mask) | (esp & esp_mask);
+ SET_ESP(esp, esp_mask);
env->eip = new_eip;
env->segs[R_CS].selector = new_cs;
env->segs[R_CS].base = (new_cs << 4);
if (new_eip > limit)
raise_exception_err(EXCP0D_GPF, new_cs & 0xfffc);
/* from this point, not restartable */
- ESP = (ESP & ~sp_mask) | (sp & sp_mask);
+ SET_ESP(sp, sp_mask);
cpu_x86_load_seg_cache(env, R_CS, (new_cs & 0xfffc) | cpl,
get_seg_base(e1, e2), limit, e2);
EIP = new_eip;
get_seg_limit(e1, e2),
e2);
cpu_x86_set_cpl(env, dpl);
- ESP = (ESP & ~sp_mask) | (sp & sp_mask);
+ SET_ESP(sp, sp_mask);
EIP = offset;
}
#ifdef USE_KQEMU
sp += addend;
}
- ESP = (ESP & ~sp_mask) | (sp & sp_mask);
+ SET_ESP(sp, sp_mask);
env->eip = new_eip;
if (is_iret) {
/* NOTE: 'cpl' is the _old_ CPL */