aboutsummaryrefslogtreecommitdiff
path: root/helper-i386.c
diff options
context:
space:
mode:
Diffstat (limited to 'helper-i386.c')
-rw-r--r--helper-i386.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/helper-i386.c b/helper-i386.c
index 72b75a5c21..3f63704d5a 100644
--- a/helper-i386.c
+++ b/helper-i386.c
@@ -788,6 +788,37 @@ static inline void load_seg_vm(int seg, int selector)
sc->limit = 0xffff;
}
+/* real mode iret */
+void helper_iret_real(int shift)
+{
+ uint32_t sp, new_cs, new_eip, new_eflags, new_esp;
+ uint8_t *ssp;
+ int eflags_mask;
+
+ sp = env->regs[R_ESP] & 0xffff;
+ ssp = env->segs[R_SS].base + sp;
+ if (shift == 1) {
+ /* 32 bits */
+ new_eflags = ldl(ssp + 8);
+ new_cs = ldl(ssp + 4) & 0xffff;
+ new_eip = ldl(ssp) & 0xffff;
+ } else {
+ /* 16 bits */
+ new_eflags = lduw(ssp + 4);
+ new_cs = lduw(ssp + 2);
+ new_eip = lduw(ssp);
+ }
+ new_esp = sp + (6 << shift);
+ env->regs[R_ESP] = (env->regs[R_ESP] & 0xffff0000) |
+ (new_esp & 0xffff);
+ load_seg_vm(R_CS, new_cs);
+ env->eip = new_eip;
+ eflags_mask = FL_UPDATE_CPL0_MASK;
+ if (shift == 0)
+ eflags_mask &= 0xffff;
+ load_eflags(new_eflags, eflags_mask);
+}
+
/* protected mode iret */
void helper_iret_protected(int shift)
{