static inline void helper_ret_protected(CPUX86State *env, int shift,

                                        int is_iret, int addend)

{

    uint32_t new_cs, new_eflags, new_ss;

    uint32_t new_es, new_ds, new_fs, new_gs;

    uint32_t e1, e2, ss_e1, ss_e2;

    int cpl, dpl, rpl, eflags_mask, iopl;

    target_ulong ssp, sp, new_eip, new_esp, sp_mask;



#ifdef TARGET_X86_64

    if (shift == 2) {

        sp_mask = -1;

    } else

#endif

    {

        sp_mask = get_sp_mask(env->segs[R_SS].flags);

    }

    sp = env->regs[R_ESP];

    ssp = env->segs[R_SS].base;

    new_eflags = 0; /* avoid warning */

#ifdef TARGET_X86_64

    if (shift == 2) {

        POPQ(sp, new_eip);

        POPQ(sp, new_cs);

        new_cs &= 0xffff;

        if (is_iret) {

            POPQ(sp, new_eflags);

        }

    } else

#endif

    {

        if (shift == 1) {

            /* 32 bits */

            POPL(ssp, sp, sp_mask, new_eip);

            POPL(ssp, sp, sp_mask, new_cs);

            new_cs &= 0xffff;

            if (is_iret) {

                POPL(ssp, sp, sp_mask, new_eflags);

                if (new_eflags & VM_MASK) {

                    goto return_to_vm86;

                }

            }

        } else {

            /* 16 bits */

            POPW(ssp, sp, sp_mask, new_eip);

            POPW(ssp, sp, sp_mask, new_cs);

            if (is_iret) {

                POPW(ssp, sp, sp_mask, new_eflags);

            }

        }

    }

    LOG_PCALL("lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n",

              new_cs, new_eip, shift, addend);

    LOG_PCALL_STATE(CPU(x86_env_get_cpu(env)));

    if ((new_cs & 0xfffc) == 0) {

        raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);

    }

    if (load_segment(env, &e1, &e2, new_cs) != 0) {

        raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);

    }

    if (!(e2 & DESC_S_MASK) ||

        !(e2 & DESC_CS_MASK)) {

        raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);

    }

    cpl = env->hflags & HF_CPL_MASK;

    rpl = new_cs & 3;

    if (rpl < cpl) {

        raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);

    }

    dpl = (e2 >> DESC_DPL_SHIFT) & 3;

    if (e2 & DESC_C_MASK) {

        if (dpl > rpl) {

            raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);

        }

    } else {

        if (dpl != rpl) {

            raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);

        }

    }

    if (!(e2 & DESC_P_MASK)) {

        raise_exception_err(env, EXCP0B_NOSEG, new_cs & 0xfffc);

    }



    sp += addend;

    if (rpl == cpl && (!(env->hflags & HF_CS64_MASK) ||

                       ((env->hflags & HF_CS64_MASK) && !is_iret))) {

        /* return to same privilege level */

        cpu_x86_load_seg_cache(env, R_CS, new_cs,

                       get_seg_base(e1, e2),

                       get_seg_limit(e1, e2),

                       e2);

    } else {

        /* return to different privilege level */

#ifdef TARGET_X86_64

        if (shift == 2) {

            POPQ(sp, new_esp);

            POPQ(sp, new_ss);

            new_ss &= 0xffff;

        } else

#endif

        {

            if (shift == 1) {

                /* 32 bits */

                POPL(ssp, sp, sp_mask, new_esp);

                POPL(ssp, sp, sp_mask, new_ss);

                new_ss &= 0xffff;

            } else {

                /* 16 bits */

                POPW(ssp, sp, sp_mask, new_esp);

                POPW(ssp, sp, sp_mask, new_ss);

            }

        }

        LOG_PCALL("new ss:esp=%04x:" TARGET_FMT_lx "\n",

                  new_ss, new_esp);

        if ((new_ss & 0xfffc) == 0) {

#ifdef TARGET_X86_64

            /* NULL ss is allowed in long mode if cpl != 3 */

            /* XXX: test CS64? */

            if ((env->hflags & HF_LMA_MASK) && rpl != 3) {

                cpu_x86_load_seg_cache(env, R_SS, new_ss,

                                       0, 0xffffffff,

                                       DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |

                                       DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |

                                       DESC_W_MASK | DESC_A_MASK);

                ss_e2 = DESC_B_MASK; /* XXX: should not be needed? */

            } else

#endif

            {

                raise_exception_err(env, EXCP0D_GPF, 0);

            }

        } else {

            if ((new_ss & 3) != rpl) {

                raise_exception_err(env, EXCP0D_GPF, new_ss & 0xfffc);

            }

            if (load_segment(env, &ss_e1, &ss_e2, new_ss) != 0) {

                raise_exception_err(env, EXCP0D_GPF, new_ss & 0xfffc);

            }

            if (!(ss_e2 & DESC_S_MASK) ||

                (ss_e2 & DESC_CS_MASK) ||

                !(ss_e2 & DESC_W_MASK)) {

                raise_exception_err(env, EXCP0D_GPF, new_ss & 0xfffc);

            }

            dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;

            if (dpl != rpl) {

                raise_exception_err(env, EXCP0D_GPF, new_ss & 0xfffc);

            }

            if (!(ss_e2 & DESC_P_MASK)) {

                raise_exception_err(env, EXCP0B_NOSEG, new_ss & 0xfffc);

            }

            cpu_x86_load_seg_cache(env, R_SS, new_ss,

                                   get_seg_base(ss_e1, ss_e2),

                                   get_seg_limit(ss_e1, ss_e2),

                                   ss_e2);

        }



        cpu_x86_load_seg_cache(env, R_CS, new_cs,

                       get_seg_base(e1, e2),

                       get_seg_limit(e1, e2),

                       e2);

        cpu_x86_set_cpl(env, rpl);

        sp = new_esp;

#ifdef TARGET_X86_64

        if (env->hflags & HF_CS64_MASK) {

            sp_mask = -1;

        } else

#endif

        {

            sp_mask = get_sp_mask(ss_e2);

        }



        /* validate data segments */

        validate_seg(env, R_ES, rpl);

        validate_seg(env, R_DS, rpl);

        validate_seg(env, R_FS, rpl);

        validate_seg(env, R_GS, rpl);



        sp += addend;

    }

    SET_ESP(sp, sp_mask);

    env->eip = new_eip;

    if (is_iret) {

        /* NOTE: 'cpl' is the _old_ CPL */

        eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK;

        if (cpl == 0) {

            eflags_mask |= IOPL_MASK;

        }

        iopl = (env->eflags >> IOPL_SHIFT) & 3;

        if (cpl <= iopl) {

            eflags_mask |= IF_MASK;

        }

        if (shift == 0) {

            eflags_mask &= 0xffff;

        }

        cpu_load_eflags(env, new_eflags, eflags_mask);

    }

    return;



 return_to_vm86:

    POPL(ssp, sp, sp_mask, new_esp);

    POPL(ssp, sp, sp_mask, new_ss);

    POPL(ssp, sp, sp_mask, new_es);

    POPL(ssp, sp, sp_mask, new_ds);

    POPL(ssp, sp, sp_mask, new_fs);

    POPL(ssp, sp, sp_mask, new_gs);



    /* modify processor state */

    cpu_load_eflags(env, new_eflags, TF_MASK | AC_MASK | ID_MASK |

                    IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK |

                    VIP_MASK);

    load_seg_vm(env, R_CS, new_cs & 0xffff);

    cpu_x86_set_cpl(env, 3);

    load_seg_vm(env, R_SS, new_ss & 0xffff);

    load_seg_vm(env, R_ES, new_es & 0xffff);

    load_seg_vm(env, R_DS, new_ds & 0xffff);

    load_seg_vm(env, R_FS, new_fs & 0xffff);

    load_seg_vm(env, R_GS, new_gs & 0xffff);



    env->eip = new_eip & 0xffff;

    env->regs[R_ESP] = new_esp;

}

static inline void helper_ret_protected(CPUX86State *env, int shift,

                                        int is_iret, int addend)

{

    uint32_t new_cs, new_eflags, new_ss;

    uint32_t new_es, new_ds, new_fs, new_gs;

    uint32_t e1, e2, ss_e1, ss_e2;

    int cpl, dpl, rpl, eflags_mask, iopl;

    target_ulong ssp, sp, new_eip, new_esp, sp_mask;



#ifdef TARGET_X86_64

    if (shift == 2) {

        sp_mask = -1;

    } else

#endif

    {

        sp_mask = get_sp_mask(env->segs[R_SS].flags);

    }

    sp = env->regs[R_ESP];

    ssp = env->segs[R_SS].base;

    new_eflags = 0; 

#ifdef TARGET_X86_64

    if (shift == 2) {

        POPQ(sp, new_eip);

        POPQ(sp, new_cs);

        new_cs &= 0xffff;

        if (is_iret) {

            POPQ(sp, new_eflags);

        }

    } else

#endif

    {

        if (shift == 1) {

            

            POPL(ssp, sp, sp_mask, new_eip);

            POPL(ssp, sp, sp_mask, new_cs);

            new_cs &= 0xffff;

            if (is_iret) {

                POPL(ssp, sp, sp_mask, new_eflags);

                if (new_eflags & VM_MASK) {

                    goto return_to_vm86;

                }

            }

        } else {

            

            POPW(ssp, sp, sp_mask, new_eip);

            POPW(ssp, sp, sp_mask, new_cs);

            if (is_iret) {

                POPW(ssp, sp, sp_mask, new_eflags);

            }

        }

    }

    LOG_PCALL("lret new %04x:" TARGET_FMT_lx " s=%d addend=0x%x\n",

              new_cs, new_eip, shift, addend);

    LOG_PCALL_STATE(CPU(x86_env_get_cpu(env)));

    if ((new_cs & 0xfffc) == 0) {

        raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);

    }

    if (load_segment(env, &e1, &e2, new_cs) != 0) {

        raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);

    }

    if (!(e2 & DESC_S_MASK) ||

        !(e2 & DESC_CS_MASK)) {

        raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);

    }

    cpl = env->hflags & HF_CPL_MASK;

    rpl = new_cs & 3;

    if (rpl < cpl) {

        raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);

    }

    dpl = (e2 >> DESC_DPL_SHIFT) & 3;

    if (e2 & DESC_C_MASK) {

        if (dpl > rpl) {

            raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);

        }

    } else {

        if (dpl != rpl) {

            raise_exception_err(env, EXCP0D_GPF, new_cs & 0xfffc);

        }

    }

    if (!(e2 & DESC_P_MASK)) {

        raise_exception_err(env, EXCP0B_NOSEG, new_cs & 0xfffc);

    }



    sp += addend;

    if (rpl == cpl && (!(env->hflags & HF_CS64_MASK) ||

                       ((env->hflags & HF_CS64_MASK) && !is_iret))) {

        

        cpu_x86_load_seg_cache(env, R_CS, new_cs,

                       get_seg_base(e1, e2),

                       get_seg_limit(e1, e2),

                       e2);

    } else {

        

#ifdef TARGET_X86_64

        if (shift == 2) {

            POPQ(sp, new_esp);

            POPQ(sp, new_ss);

            new_ss &= 0xffff;

        } else

#endif

        {

            if (shift == 1) {

                

                POPL(ssp, sp, sp_mask, new_esp);

                POPL(ssp, sp, sp_mask, new_ss);

                new_ss &= 0xffff;

            } else {

                

                POPW(ssp, sp, sp_mask, new_esp);

                POPW(ssp, sp, sp_mask, new_ss);

            }

        }

        LOG_PCALL("new ss:esp=%04x:" TARGET_FMT_lx "\n",

                  new_ss, new_esp);

        if ((new_ss & 0xfffc) == 0) {

#ifdef TARGET_X86_64

            

            

            if ((env->hflags & HF_LMA_MASK) && rpl != 3) {

                cpu_x86_load_seg_cache(env, R_SS, new_ss,

                                       0, 0xffffffff,

                                       DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |

                                       DESC_S_MASK | (rpl << DESC_DPL_SHIFT) |

                                       DESC_W_MASK | DESC_A_MASK);

                ss_e2 = DESC_B_MASK; 

            } else

#endif

            {

                raise_exception_err(env, EXCP0D_GPF, 0);

            }

        } else {

            if ((new_ss & 3) != rpl) {

                raise_exception_err(env, EXCP0D_GPF, new_ss & 0xfffc);

            }

            if (load_segment(env, &ss_e1, &ss_e2, new_ss) != 0) {

                raise_exception_err(env, EXCP0D_GPF, new_ss & 0xfffc);

            }

            if (!(ss_e2 & DESC_S_MASK) ||

                (ss_e2 & DESC_CS_MASK) ||

                !(ss_e2 & DESC_W_MASK)) {

                raise_exception_err(env, EXCP0D_GPF, new_ss & 0xfffc);

            }

            dpl = (ss_e2 >> DESC_DPL_SHIFT) & 3;

            if (dpl != rpl) {

                raise_exception_err(env, EXCP0D_GPF, new_ss & 0xfffc);

            }

            if (!(ss_e2 & DESC_P_MASK)) {

                raise_exception_err(env, EXCP0B_NOSEG, new_ss & 0xfffc);

            }

            cpu_x86_load_seg_cache(env, R_SS, new_ss,

                                   get_seg_base(ss_e1, ss_e2),

                                   get_seg_limit(ss_e1, ss_e2),

                                   ss_e2);

        }



        cpu_x86_load_seg_cache(env, R_CS, new_cs,

                       get_seg_base(e1, e2),

                       get_seg_limit(e1, e2),

                       e2);

        cpu_x86_set_cpl(env, rpl);

        sp = new_esp;

#ifdef TARGET_X86_64

        if (env->hflags & HF_CS64_MASK) {

            sp_mask = -1;

        } else

#endif

        {

            sp_mask = get_sp_mask(ss_e2);

        }



        

        validate_seg(env, R_ES, rpl);

        validate_seg(env, R_DS, rpl);

        validate_seg(env, R_FS, rpl);

        validate_seg(env, R_GS, rpl);



        sp += addend;

    }

    SET_ESP(sp, sp_mask);

    env->eip = new_eip;

    if (is_iret) {

        

        eflags_mask = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK;

        if (cpl == 0) {

            eflags_mask |= IOPL_MASK;

        }

        iopl = (env->eflags >> IOPL_SHIFT) & 3;

        if (cpl <= iopl) {

            eflags_mask |= IF_MASK;

        }

        if (shift == 0) {

            eflags_mask &= 0xffff;

        }

        cpu_load_eflags(env, new_eflags, eflags_mask);

    }

    return;



 return_to_vm86:

    POPL(ssp, sp, sp_mask, new_esp);

    POPL(ssp, sp, sp_mask, new_ss);

    POPL(ssp, sp, sp_mask, new_es);

    POPL(ssp, sp, sp_mask, new_ds);

    POPL(ssp, sp, sp_mask, new_fs);

    POPL(ssp, sp, sp_mask, new_gs);



    

    cpu_load_eflags(env, new_eflags, TF_MASK | AC_MASK | ID_MASK |

                    IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK |

                    VIP_MASK);

    load_seg_vm(env, R_CS, new_cs & 0xffff);

    cpu_x86_set_cpl(env, 3);

    load_seg_vm(env, R_SS, new_ss & 0xffff);

    load_seg_vm(env, R_ES, new_es & 0xffff);

    load_seg_vm(env, R_DS, new_ds & 0xffff);

    load_seg_vm(env, R_FS, new_fs & 0xffff);

    load_seg_vm(env, R_GS, new_gs & 0xffff);



    env->eip = new_eip & 0xffff;

    env->regs[R_ESP] = new_esp;

}

static inline void FUNC_0(CPUX86State *VAR_0, int VAR_1,

                                        int VAR_2, int VAR_3)

{

    uint32_t new_cs, new_eflags, new_ss;

    uint32_t new_es, new_ds, new_fs, new_gs;

    uint32_t e1, e2, ss_e1, ss_e2;

    int VAR_4, VAR_5, VAR_6, VAR_7, VAR_8;

    target_ulong ssp, sp, new_eip, new_esp, sp_mask;



#ifdef TARGET_X86_64

    if (VAR_1 == 2) {

        sp_mask = -1;

    } else

#endif

    {

        sp_mask = get_sp_mask(VAR_0->segs[R_SS].flags);

    }

    sp = VAR_0->regs[R_ESP];

    ssp = VAR_0->segs[R_SS].base;

    new_eflags = 0; 

#ifdef TARGET_X86_64

    if (VAR_1 == 2) {

        POPQ(sp, new_eip);

        POPQ(sp, new_cs);

        new_cs &= 0xffff;

        if (VAR_2) {

            POPQ(sp, new_eflags);

        }

    } else

#endif

    {

        if (VAR_1 == 1) {

            

            POPL(ssp, sp, sp_mask, new_eip);

            POPL(ssp, sp, sp_mask, new_cs);

            new_cs &= 0xffff;

            if (VAR_2) {

                POPL(ssp, sp, sp_mask, new_eflags);

                if (new_eflags & VM_MASK) {

                    goto return_to_vm86;

                }

            }

        } else {

            

            POPW(ssp, sp, sp_mask, new_eip);

            POPW(ssp, sp, sp_mask, new_cs);

            if (VAR_2) {

                POPW(ssp, sp, sp_mask, new_eflags);

            }

        }

    }

    LOG_PCALL("lret new %04x:" TARGET_FMT_lx " s=%d VAR_3=0x%x\n",

              new_cs, new_eip, VAR_1, VAR_3);

    LOG_PCALL_STATE(CPU(x86_env_get_cpu(VAR_0)));

    if ((new_cs & 0xfffc) == 0) {

        raise_exception_err(VAR_0, EXCP0D_GPF, new_cs & 0xfffc);

    }

    if (load_segment(VAR_0, &e1, &e2, new_cs) != 0) {

        raise_exception_err(VAR_0, EXCP0D_GPF, new_cs & 0xfffc);

    }

    if (!(e2 & DESC_S_MASK) ||

        !(e2 & DESC_CS_MASK)) {

        raise_exception_err(VAR_0, EXCP0D_GPF, new_cs & 0xfffc);

    }

    VAR_4 = VAR_0->hflags & HF_CPL_MASK;

    VAR_6 = new_cs & 3;

    if (VAR_6 < VAR_4) {

        raise_exception_err(VAR_0, EXCP0D_GPF, new_cs & 0xfffc);

    }

    VAR_5 = (e2 >> DESC_DPL_SHIFT) & 3;

    if (e2 & DESC_C_MASK) {

        if (VAR_5 > VAR_6) {

            raise_exception_err(VAR_0, EXCP0D_GPF, new_cs & 0xfffc);

        }

    } else {

        if (VAR_5 != VAR_6) {

            raise_exception_err(VAR_0, EXCP0D_GPF, new_cs & 0xfffc);

        }

    }

    if (!(e2 & DESC_P_MASK)) {

        raise_exception_err(VAR_0, EXCP0B_NOSEG, new_cs & 0xfffc);

    }



    sp += VAR_3;

    if (VAR_6 == VAR_4 && (!(VAR_0->hflags & HF_CS64_MASK) ||

                       ((VAR_0->hflags & HF_CS64_MASK) && !VAR_2))) {

        

        cpu_x86_load_seg_cache(VAR_0, R_CS, new_cs,

                       get_seg_base(e1, e2),

                       get_seg_limit(e1, e2),

                       e2);

    } else {

        

#ifdef TARGET_X86_64

        if (VAR_1 == 2) {

            POPQ(sp, new_esp);

            POPQ(sp, new_ss);

            new_ss &= 0xffff;

        } else

#endif

        {

            if (VAR_1 == 1) {

                

                POPL(ssp, sp, sp_mask, new_esp);

                POPL(ssp, sp, sp_mask, new_ss);

                new_ss &= 0xffff;

            } else {

                

                POPW(ssp, sp, sp_mask, new_esp);

                POPW(ssp, sp, sp_mask, new_ss);

            }

        }

        LOG_PCALL("new ss:esp=%04x:" TARGET_FMT_lx "\n",

                  new_ss, new_esp);

        if ((new_ss & 0xfffc) == 0) {

#ifdef TARGET_X86_64

            

            

            if ((VAR_0->hflags & HF_LMA_MASK) && VAR_6 != 3) {

                cpu_x86_load_seg_cache(VAR_0, R_SS, new_ss,

                                       0, 0xffffffff,

                                       DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |

                                       DESC_S_MASK | (VAR_6 << DESC_DPL_SHIFT) |

                                       DESC_W_MASK | DESC_A_MASK);

                ss_e2 = DESC_B_MASK; 

            } else

#endif

            {

                raise_exception_err(VAR_0, EXCP0D_GPF, 0);

            }

        } else {

            if ((new_ss & 3) != VAR_6) {

                raise_exception_err(VAR_0, EXCP0D_GPF, new_ss & 0xfffc);

            }

            if (load_segment(VAR_0, &ss_e1, &ss_e2, new_ss) != 0) {

                raise_exception_err(VAR_0, EXCP0D_GPF, new_ss & 0xfffc);

            }

            if (!(ss_e2 & DESC_S_MASK) ||

                (ss_e2 & DESC_CS_MASK) ||

                !(ss_e2 & DESC_W_MASK)) {

                raise_exception_err(VAR_0, EXCP0D_GPF, new_ss & 0xfffc);

            }

            VAR_5 = (ss_e2 >> DESC_DPL_SHIFT) & 3;

            if (VAR_5 != VAR_6) {

                raise_exception_err(VAR_0, EXCP0D_GPF, new_ss & 0xfffc);

            }

            if (!(ss_e2 & DESC_P_MASK)) {

                raise_exception_err(VAR_0, EXCP0B_NOSEG, new_ss & 0xfffc);

            }

            cpu_x86_load_seg_cache(VAR_0, R_SS, new_ss,

                                   get_seg_base(ss_e1, ss_e2),

                                   get_seg_limit(ss_e1, ss_e2),

                                   ss_e2);

        }



        cpu_x86_load_seg_cache(VAR_0, R_CS, new_cs,

                       get_seg_base(e1, e2),

                       get_seg_limit(e1, e2),

                       e2);

        cpu_x86_set_cpl(VAR_0, VAR_6);

        sp = new_esp;

#ifdef TARGET_X86_64

        if (VAR_0->hflags & HF_CS64_MASK) {

            sp_mask = -1;

        } else

#endif

        {

            sp_mask = get_sp_mask(ss_e2);

        }



        

        validate_seg(VAR_0, R_ES, VAR_6);

        validate_seg(VAR_0, R_DS, VAR_6);

        validate_seg(VAR_0, R_FS, VAR_6);

        validate_seg(VAR_0, R_GS, VAR_6);



        sp += VAR_3;

    }

    SET_ESP(sp, sp_mask);

    VAR_0->eip = new_eip;

    if (VAR_2) {

        

        VAR_7 = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK;

        if (VAR_4 == 0) {

            VAR_7 |= IOPL_MASK;

        }

        VAR_8 = (VAR_0->eflags >> IOPL_SHIFT) & 3;

        if (VAR_4 <= VAR_8) {

            VAR_7 |= IF_MASK;

        }

        if (VAR_1 == 0) {

            VAR_7 &= 0xffff;

        }

        cpu_load_eflags(VAR_0, new_eflags, VAR_7);

    }

    return;



 return_to_vm86:

    POPL(ssp, sp, sp_mask, new_esp);

    POPL(ssp, sp, sp_mask, new_ss);

    POPL(ssp, sp, sp_mask, new_es);

    POPL(ssp, sp, sp_mask, new_ds);

    POPL(ssp, sp, sp_mask, new_fs);

    POPL(ssp, sp, sp_mask, new_gs);



    

    cpu_load_eflags(VAR_0, new_eflags, TF_MASK | AC_MASK | ID_MASK |

                    IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK |

                    VIP_MASK);

    load_seg_vm(VAR_0, R_CS, new_cs & 0xffff);

    cpu_x86_set_cpl(VAR_0, 3);

    load_seg_vm(VAR_0, R_SS, new_ss & 0xffff);

    load_seg_vm(VAR_0, R_ES, new_es & 0xffff);

    load_seg_vm(VAR_0, R_DS, new_ds & 0xffff);

    load_seg_vm(VAR_0, R_FS, new_fs & 0xffff);

    load_seg_vm(VAR_0, R_GS, new_gs & 0xffff);



    VAR_0->eip = new_eip & 0xffff;

    VAR_0->regs[R_ESP] = new_esp;

}

static inline void FUNC_0(CPUX86State *VAR_0, int VAR_1,
int VAR_2, int VAR_3)
{ uint32_t new_cs, new_eflags, new_ss; uint32_t new_es, new_ds, new_fs, new_gs; uint32_t e1, e2, ss_e1, ss_e2; int VAR_4, VAR_5, VAR_6, VAR_7, VAR_8; target_ulong ssp, sp, new_eip, new_esp, sp_mask; #ifdef TARGET_X86_64
if (VAR_1 == 2) { sp_mask = -1; } else #endif
{ sp_mask = get_sp_mask(VAR_0->segs[R_SS].flags); } sp = VAR_0->regs[R_ESP]; ssp = VAR_0->segs[R_SS].base; new_eflags = 0; #ifdef TARGET_X86_64
if (VAR_1 == 2) { POPQ(sp, new_eip); POPQ(sp, new_cs); new_cs &= 0xffff; if (VAR_2) { POPQ(sp, new_eflags); } } else #endif
{ if (VAR_1 == 1) { POPL(ssp, sp, sp_mask, new_eip); POPL(ssp, sp, sp_mask, new_cs); new_cs &= 0xffff; if (VAR_2) { POPL(ssp, sp, sp_mask, new_eflags); if (new_eflags & VM_MASK) { goto return_to_vm86; } } } else { POPW(ssp, sp, sp_mask, new_eip); POPW(ssp, sp, sp_mask, new_cs); if (VAR_2) { POPW(ssp, sp, sp_mask, new_eflags); } } } LOG_PCALL("lret new %04x:" TARGET_FMT_lx " s=%d VAR_3=0x%x\n",
new_cs, new_eip, VAR_1, VAR_3); LOG_PCALL_STATE(CPU(x86_env_get_cpu(VAR_0))); if ((new_cs & 0xfffc) == 0) { raise_exception_err(VAR_0, EXCP0D_GPF, new_cs & 0xfffc); } if (load_segment(VAR_0, &e1, &e2, new_cs) != 0) { raise_exception_err(VAR_0, EXCP0D_GPF, new_cs & 0xfffc); } if (!(e2 & DESC_S_MASK) ||
!(e2 & DESC_CS_MASK)) { raise_exception_err(VAR_0, EXCP0D_GPF, new_cs & 0xfffc); } VAR_4 = VAR_0->hflags & HF_CPL_MASK; VAR_6 = new_cs & 3; if (VAR_6 < VAR_4) { raise_exception_err(VAR_0, EXCP0D_GPF, new_cs & 0xfffc); } VAR_5 = (e2 >> DESC_DPL_SHIFT) & 3; if (e2 & DESC_C_MASK) { if (VAR_5 > VAR_6) { raise_exception_err(VAR_0, EXCP0D_GPF, new_cs & 0xfffc); } } else { if (VAR_5 != VAR_6) { raise_exception_err(VAR_0, EXCP0D_GPF, new_cs & 0xfffc); } } if (!(e2 & DESC_P_MASK)) { raise_exception_err(VAR_0, EXCP0B_NOSEG, new_cs & 0xfffc); } sp += VAR_3; if (VAR_6 == VAR_4 && (!(VAR_0->hflags & HF_CS64_MASK) ||
((VAR_0->hflags & HF_CS64_MASK) && !VAR_2))) { cpu_x86_load_seg_cache(VAR_0, R_CS, new_cs,
get_seg_base(e1, e2),
get_seg_limit(e1, e2),
e2); } else { #ifdef TARGET_X86_64
if (VAR_1 == 2) { POPQ(sp, new_esp); POPQ(sp, new_ss); new_ss &= 0xffff; } else #endif
{ if (VAR_1 == 1) { POPL(ssp, sp, sp_mask, new_esp); POPL(ssp, sp, sp_mask, new_ss); new_ss &= 0xffff; } else { POPW(ssp, sp, sp_mask, new_esp); POPW(ssp, sp, sp_mask, new_ss); } } LOG_PCALL("new ss:esp=%04x:" TARGET_FMT_lx "\n",
new_ss, new_esp); if ((new_ss & 0xfffc) == 0) { #ifdef TARGET_X86_64
if ((VAR_0->hflags & HF_LMA_MASK) && VAR_6 != 3) { cpu_x86_load_seg_cache(VAR_0, R_SS, new_ss,
0, 0xffffffff,
DESC_G_MASK | DESC_B_MASK | DESC_P_MASK |
DESC_S_MASK | (VAR_6 << DESC_DPL_SHIFT) |
DESC_W_MASK | DESC_A_MASK); ss_e2 = DESC_B_MASK; } else #endif
{ raise_exception_err(VAR_0, EXCP0D_GPF, 0); } } else { if ((new_ss & 3) != VAR_6) { raise_exception_err(VAR_0, EXCP0D_GPF, new_ss & 0xfffc); } if (load_segment(VAR_0, &ss_e1, &ss_e2, new_ss) != 0) { raise_exception_err(VAR_0, EXCP0D_GPF, new_ss & 0xfffc); } if (!(ss_e2 & DESC_S_MASK) ||
(ss_e2 & DESC_CS_MASK) ||
!(ss_e2 & DESC_W_MASK)) { raise_exception_err(VAR_0, EXCP0D_GPF, new_ss & 0xfffc); } VAR_5 = (ss_e2 >> DESC_DPL_SHIFT) & 3; if (VAR_5 != VAR_6) { raise_exception_err(VAR_0, EXCP0D_GPF, new_ss & 0xfffc); } if (!(ss_e2 & DESC_P_MASK)) { raise_exception_err(VAR_0, EXCP0B_NOSEG, new_ss & 0xfffc); } cpu_x86_load_seg_cache(VAR_0, R_SS, new_ss,
get_seg_base(ss_e1, ss_e2),
get_seg_limit(ss_e1, ss_e2),
ss_e2); } cpu_x86_load_seg_cache(VAR_0, R_CS, new_cs,
get_seg_base(e1, e2),
get_seg_limit(e1, e2),
e2); cpu_x86_set_cpl(VAR_0, VAR_6); sp = new_esp; #ifdef TARGET_X86_64
if (VAR_0->hflags & HF_CS64_MASK) { sp_mask = -1; } else #endif
{ sp_mask = get_sp_mask(ss_e2); } validate_seg(VAR_0, R_ES, VAR_6); validate_seg(VAR_0, R_DS, VAR_6); validate_seg(VAR_0, R_FS, VAR_6); validate_seg(VAR_0, R_GS, VAR_6); sp += VAR_3; } SET_ESP(sp, sp_mask); VAR_0->eip = new_eip; if (VAR_2) { VAR_7 = TF_MASK | AC_MASK | ID_MASK | RF_MASK | NT_MASK; if (VAR_4 == 0) { VAR_7 |= IOPL_MASK; } VAR_8 = (VAR_0->eflags >> IOPL_SHIFT) & 3; if (VAR_4 <= VAR_8) { VAR_7 |= IF_MASK; } if (VAR_1 == 0) { VAR_7 &= 0xffff; } cpu_load_eflags(VAR_0, new_eflags, VAR_7); } return; return_to_vm86:
POPL(ssp, sp, sp_mask, new_esp); POPL(ssp, sp, sp_mask, new_ss); POPL(ssp, sp, sp_mask, new_es); POPL(ssp, sp, sp_mask, new_ds); POPL(ssp, sp, sp_mask, new_fs); POPL(ssp, sp, sp_mask, new_gs); cpu_load_eflags(VAR_0, new_eflags, TF_MASK | AC_MASK | ID_MASK |
IF_MASK | IOPL_MASK | VM_MASK | NT_MASK | VIF_MASK |
VIP_MASK); load_seg_vm(VAR_0, R_CS, new_cs & 0xffff); cpu_x86_set_cpl(VAR_0, 3); load_seg_vm(VAR_0, R_SS, new_ss & 0xffff); load_seg_vm(VAR_0, R_ES, new_es & 0xffff); load_seg_vm(VAR_0, R_DS, new_ds & 0xffff); load_seg_vm(VAR_0, R_FS, new_fs & 0xffff); load_seg_vm(VAR_0, R_GS, new_gs & 0xffff); VAR_0->eip = new_eip & 0xffff; VAR_0->regs[R_ESP] = new_esp; }