helper.c

来自「xen虚拟机源代码安装包」· C语言 代码 · 共 2,185 行 · 第 1/5 页

C
2,185
字号
}void helper_aaa(void){    int icarry;    int al, ah, af;    int eflags;    eflags = cc_table[CC_OP].compute_all();    af = eflags & CC_A;    al = EAX & 0xff;    ah = (EAX >> 8) & 0xff;    icarry = (al > 0xf9);    if (((al & 0x0f) > 9 ) || af) {        al = (al + 6) & 0x0f;        ah = (ah + 1 + icarry) & 0xff;        eflags |= CC_C | CC_A;    } else {        eflags &= ~(CC_C | CC_A);        al &= 0x0f;    }    EAX = (EAX & ~0xffff) | al | (ah << 8);    CC_SRC = eflags;    FORCE_RET();}void helper_aas(void){    int icarry;    int al, ah, af;    int eflags;    eflags = cc_table[CC_OP].compute_all();    af = eflags & CC_A;    al = EAX & 0xff;    ah = (EAX >> 8) & 0xff;    icarry = (al < 6);    if (((al & 0x0f) > 9 ) || af) {        al = (al - 6) & 0x0f;        ah = (ah - 1 - icarry) & 0xff;        eflags |= CC_C | CC_A;    } else {        eflags &= ~(CC_C | CC_A);        al &= 0x0f;    }    EAX = (EAX & ~0xffff) | al | (ah << 8);    CC_SRC = eflags;    FORCE_RET();}void helper_daa(void){    int al, af, cf;    int eflags;    eflags = cc_table[CC_OP].compute_all();    cf = eflags & CC_C;    af = eflags & CC_A;    al = EAX & 0xff;    eflags = 0;    if (((al & 0x0f) > 9 ) || af) {        al = (al + 6) & 0xff;        eflags |= CC_A;    }    if ((al > 0x9f) || cf) {        al = (al + 0x60) & 0xff;        eflags |= CC_C;    }    EAX = (EAX & ~0xff) | al;    /* well, speed is not an issue here, so we compute the flags by hand */    eflags |= (al == 0) << 6; /* zf */    eflags |= parity_table[al]; /* pf */    eflags |= (al & 0x80); /* sf */    CC_SRC = eflags;    FORCE_RET();}void helper_das(void){    int al, al1, af, cf;    int eflags;    eflags = cc_table[CC_OP].compute_all();    cf = eflags & CC_C;    af = eflags & CC_A;    al = EAX & 0xff;    eflags = 0;    al1 = al;    if (((al & 0x0f) > 9 ) || af) {        eflags |= CC_A;        if (al < 6 || cf)            eflags |= CC_C;        al = (al - 6) & 0xff;    }    if ((al1 > 0x99) || cf) {        al = (al - 0x60) & 0xff;        eflags |= CC_C;    }    EAX = (EAX & ~0xff) | al;    /* well, speed is not an issue here, so we compute the flags by hand */    eflags |= (al == 0) << 6; /* zf */    eflags |= parity_table[al]; /* pf */    eflags |= (al & 0x80); /* sf */    CC_SRC = eflags;    FORCE_RET();}void helper_cmpxchg8b(void){    uint64_t d;    int eflags;    eflags = cc_table[CC_OP].compute_all();    d = ldq(A0);    if (d == (((uint64_t)EDX << 32) | EAX)) {        stq(A0, ((uint64_t)ECX << 32) | EBX);        eflags |= CC_Z;    } else {        EDX = d >> 32;        EAX = d;        eflags &= ~CC_Z;    }    CC_SRC = eflags;}void helper_single_step(void){    env->dr[6] |= 0x4000;    raise_exception(EXCP01_SSTP);}void helper_cpuid(void){    uint32_t index;    index = (uint32_t)EAX;    /* test if maximum index reached */    if (index & 0x80000000) {        if (index > env->cpuid_xlevel)            index = env->cpuid_level;    } else {        if (index > env->cpuid_level)            index = env->cpuid_level;    }    switch(index) {    case 0:        EAX = env->cpuid_level;        EBX = env->cpuid_vendor1;        EDX = env->cpuid_vendor2;        ECX = env->cpuid_vendor3;        break;    case 1:        EAX = env->cpuid_version;        EBX = (env->cpuid_apic_id << 24) | 8 << 8; /* CLFLUSH size in quad words, Linux wants it. */        ECX = env->cpuid_ext_features;        EDX = env->cpuid_features;        break;    case 2:        /* cache info: needed for Pentium Pro compatibility */        EAX = 1;        EBX = 0;        ECX = 0;        EDX = 0x2c307d;        break;    case 0x80000000:        EAX = env->cpuid_xlevel;        EBX = env->cpuid_vendor1;        EDX = env->cpuid_vendor2;        ECX = env->cpuid_vendor3;        break;    case 0x80000001:        EAX = env->cpuid_features;        EBX = 0;        ECX = env->cpuid_ext3_features;        EDX = env->cpuid_ext2_features;        break;    case 0x80000002:    case 0x80000003:    case 0x80000004:        EAX = env->cpuid_model[(index - 0x80000002) * 4 + 0];        EBX = env->cpuid_model[(index - 0x80000002) * 4 + 1];        ECX = env->cpuid_model[(index - 0x80000002) * 4 + 2];        EDX = env->cpuid_model[(index - 0x80000002) * 4 + 3];        break;    case 0x80000005:        /* cache info (L1 cache) */        EAX = 0x01ff01ff;        EBX = 0x01ff01ff;        ECX = 0x40020140;        EDX = 0x40020140;        break;    case 0x80000006:        /* cache info (L2 cache) */        EAX = 0;        EBX = 0x42004200;        ECX = 0x02008140;        EDX = 0;        break;    case 0x80000008:        /* virtual & phys address size in low 2 bytes. *//* XXX: This value must match the one used in the MMU code. */ #if defined(TARGET_X86_64)#  if defined(USE_KQEMU)        EAX = 0x00003020;	/* 48 bits virtual, 32 bits physical */#  else/* XXX: The physical address space is limited to 42 bits in exec.c. */        EAX = 0x00003028;	/* 48 bits virtual, 40 bits physical */#  endif#else# if defined(USE_KQEMU)        EAX = 0x00000020;	/* 32 bits physical */#  else        EAX = 0x00000024;	/* 36 bits physical */#  endif#endif        EBX = 0;        ECX = 0;        EDX = 0;        break;    case 0x8000000A:        EAX = 0x00000001;        EBX = 0;        ECX = 0;        EDX = 0;        break;    default:        /* reserved values: zero */        EAX = 0;        EBX = 0;        ECX = 0;        EDX = 0;        break;    }}void helper_enter_level(int level, int data32){    target_ulong ssp;    uint32_t esp_mask, esp, ebp;    esp_mask = get_sp_mask(env->segs[R_SS].flags);    ssp = env->segs[R_SS].base;    ebp = EBP;    esp = ESP;    if (data32) {        /* 32 bit */        esp -= 4;        while (--level) {            esp -= 4;            ebp -= 4;            stl(ssp + (esp & esp_mask), ldl(ssp + (ebp & esp_mask)));        }        esp -= 4;        stl(ssp + (esp & esp_mask), T1);    } else {        /* 16 bit */        esp -= 2;        while (--level) {            esp -= 2;            ebp -= 2;            stw(ssp + (esp & esp_mask), lduw(ssp + (ebp & esp_mask)));        }        esp -= 2;        stw(ssp + (esp & esp_mask), T1);    }}#ifdef TARGET_X86_64void helper_enter64_level(int level, int data64){    target_ulong esp, ebp;    ebp = EBP;    esp = ESP;    if (data64) {        /* 64 bit */        esp -= 8;        while (--level) {            esp -= 8;            ebp -= 8;            stq(esp, ldq(ebp));        }        esp -= 8;        stq(esp, T1);    } else {        /* 16 bit */        esp -= 2;        while (--level) {            esp -= 2;            ebp -= 2;            stw(esp, lduw(ebp));        }        esp -= 2;        stw(esp, T1);    }}#endifvoid helper_lldt(int selector){    SegmentCache *dt;    uint32_t e1, e2;    int index, entry_limit;    target_ulong ptr;    selector &= 0xffff;    if ((selector & 0xfffc) == 0) {        /* XXX: NULL selector case: invalid LDT */        env->ldt.base = 0;        env->ldt.limit = 0;    } else {        if (selector & 0x4)            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);        dt = &env->gdt;        index = selector & ~7;#ifdef TARGET_X86_64        if (env->hflags & HF_LMA_MASK)            entry_limit = 15;        else#endif            entry_limit = 7;        if ((index + entry_limit) > dt->limit)            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);        ptr = dt->base + index;        e1 = ldl_kernel(ptr);        e2 = ldl_kernel(ptr + 4);        if ((e2 & DESC_S_MASK) || ((e2 >> DESC_TYPE_SHIFT) & 0xf) != 2)            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);        if (!(e2 & DESC_P_MASK))            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);#ifdef TARGET_X86_64        if (env->hflags & HF_LMA_MASK) {            uint32_t e3;            e3 = ldl_kernel(ptr + 8);            load_seg_cache_raw_dt(&env->ldt, e1, e2);            env->ldt.base |= (target_ulong)e3 << 32;        } else#endif        {            load_seg_cache_raw_dt(&env->ldt, e1, e2);        }    }    env->ldt.selector = selector;}void helper_ltr(int selector){    SegmentCache *dt;    uint32_t e1, e2;    int index, type, entry_limit;    target_ulong ptr;    selector &= 0xffff;    if ((selector & 0xfffc) == 0) {        /* NULL selector case: invalid TR */        env->tr.base = 0;        env->tr.limit = 0;        env->tr.flags = 0;    } else {        if (selector & 0x4)            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);        dt = &env->gdt;        index = selector & ~7;#ifdef TARGET_X86_64        if (env->hflags & HF_LMA_MASK)            entry_limit = 15;        else#endif            entry_limit = 7;        if ((index + entry_limit) > dt->limit)            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);        ptr = dt->base + index;        e1 = ldl_kernel(ptr);        e2 = ldl_kernel(ptr + 4);        type = (e2 >> DESC_TYPE_SHIFT) & 0xf;        if ((e2 & DESC_S_MASK) ||            (type != 1 && type != 9))            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);        if (!(e2 & DESC_P_MASK))            raise_exception_err(EXCP0B_NOSEG, selector & 0xfffc);#ifdef TARGET_X86_64        if (env->hflags & HF_LMA_MASK) {            uint32_t e3, e4;            e3 = ldl_kernel(ptr + 8);            e4 = ldl_kernel(ptr + 12);            if ((e4 >> DESC_TYPE_SHIFT) & 0xf)                raise_exception_err(EXCP0D_GPF, selector & 0xfffc);            load_seg_cache_raw_dt(&env->tr, e1, e2);            env->tr.base |= (target_ulong)e3 << 32;        } else#endif        {            load_seg_cache_raw_dt(&env->tr, e1, e2);        }        e2 |= DESC_TSS_BUSY_MASK;        stl_kernel(ptr + 4, e2);    }    env->tr.selector = selector;}/* only works if protected mode and not VM86. seg_reg must be != R_CS */void helper_load_seg(int seg_reg, int selector){    uint32_t e1, e2;    int cpl, dpl, rpl;    SegmentCache *dt;    int index;    target_ulong ptr;    selector &= 0xffff;    cpl = env->hflags & HF_CPL_MASK;    if ((selector & 0xfffc) == 0) {        /* null selector case */        if (seg_reg == R_SS#ifdef TARGET_X86_64            && (!(env->hflags & HF_CS64_MASK) || cpl == 3)#endif            )            raise_exception_err(EXCP0D_GPF, 0);        cpu_x86_load_seg_cache(env, seg_reg, selector, 0, 0, 0);    } else {        if (selector & 0x4)            dt = &env->ldt;        else            dt = &env->gdt;        index = selector & ~7;        if ((index + 7) > dt->limit)            raise_exception_err(EXCP0D_GPF, selector & 0xfffc);        ptr = dt->base + index;        e1 = ldl_kernel(ptr);        e2 = ldl_kernel(ptr + 4)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?