tcg-target.c

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

C
1,215
字号
        break;    case TCG_COND_LEU:        tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3], args[5]);        tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);        tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2], args[5]);        break;    case TCG_COND_GTU:        tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3], args[5]);        tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);        tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2], args[5]);        break;    case TCG_COND_GEU:        tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3], args[5]);        tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3], label_next);        tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2], args[5]);        break;    default:        tcg_abort();    }    tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);}#if defined(CONFIG_SOFTMMU)extern void __ldb_mmu(void);extern void __ldw_mmu(void);extern void __ldl_mmu(void);extern void __ldq_mmu(void);extern void __stb_mmu(void);extern void __stw_mmu(void);extern void __stl_mmu(void);extern void __stq_mmu(void);static void *qemu_ld_helpers[4] = {    __ldb_mmu,    __ldw_mmu,    __ldl_mmu,    __ldq_mmu,};static void *qemu_st_helpers[4] = {    __stb_mmu,    __stw_mmu,    __stl_mmu,    __stq_mmu,};#endif/* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and   EAX. It will be useful once fixed registers globals are less   common. */static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,                            int opc){    int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;#if defined(CONFIG_SOFTMMU)    uint8_t *label1_ptr, *label2_ptr;#endif#if TARGET_LONG_BITS == 64#if defined(CONFIG_SOFTMMU)    uint8_t *label3_ptr;#endif    int addr_reg2;#endif    data_reg = *args++;    if (opc == 3)        data_reg2 = *args++;    else        data_reg2 = 0;    addr_reg = *args++;#if TARGET_LONG_BITS == 64    addr_reg2 = *args++;#endif    mem_index = *args;    s_bits = opc & 3;    r0 = TCG_REG_EAX;    r1 = TCG_REG_EDX;#if defined(CONFIG_SOFTMMU)    tcg_out_mov(s, r1, addr_reg);     tcg_out_mov(s, r0, addr_reg);      tcg_out_modrm(s, 0xc1, 5, r1); /* shr $x, r1 */    tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);         tcg_out_modrm(s, 0x81, 4, r0); /* andl $x, r0 */    tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));        tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */    tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);    tcg_out_opc(s, 0x8d); /* lea offset(r1, %ebp), r1 */    tcg_out8(s, 0x80 | (r1 << 3) | 0x04);    tcg_out8(s, (5 << 3) | r1);    tcg_out32(s, offsetof(CPUState, tlb_table[mem_index][0].addr_read));    /* cmp 0(r1), r0 */    tcg_out_modrm_offset(s, 0x3b, r0, r1, 0);        tcg_out_mov(s, r0, addr_reg);    #if TARGET_LONG_BITS == 32    /* je label1 */    tcg_out8(s, 0x70 + JCC_JE);    label1_ptr = s->code_ptr;    s->code_ptr++;#else    /* jne label3 */    tcg_out8(s, 0x70 + JCC_JNE);    label3_ptr = s->code_ptr;    s->code_ptr++;        /* cmp 4(r1), addr_reg2 */    tcg_out_modrm_offset(s, 0x3b, addr_reg2, r1, 4);    /* je label1 */    tcg_out8(s, 0x70 + JCC_JE);    label1_ptr = s->code_ptr;    s->code_ptr++;        /* label3: */    *label3_ptr = s->code_ptr - label3_ptr - 1;#endif    /* XXX: move that code at the end of the TB */#if TARGET_LONG_BITS == 32    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EDX, mem_index);#else    tcg_out_mov(s, TCG_REG_EDX, addr_reg2);    tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);#endif    tcg_out8(s, 0xe8);    tcg_out32(s, (tcg_target_long)qemu_ld_helpers[s_bits] -               (tcg_target_long)s->code_ptr - 4);    switch(opc) {    case 0 | 4:        /* movsbl */        tcg_out_modrm(s, 0xbe | P_EXT, data_reg, TCG_REG_EAX);        break;    case 1 | 4:        /* movswl */        tcg_out_modrm(s, 0xbf | P_EXT, data_reg, TCG_REG_EAX);        break;    case 0:    case 1:    case 2:    default:        tcg_out_mov(s, data_reg, TCG_REG_EAX);        break;    case 3:        if (data_reg == TCG_REG_EDX) {            tcg_out_opc(s, 0x90 + TCG_REG_EDX); /* xchg %edx, %eax */            tcg_out_mov(s, data_reg2, TCG_REG_EAX);        } else {            tcg_out_mov(s, data_reg, TCG_REG_EAX);            tcg_out_mov(s, data_reg2, TCG_REG_EDX);        }        break;    }    /* jmp label2 */    tcg_out8(s, 0xeb);    label2_ptr = s->code_ptr;    s->code_ptr++;        /* label1: */    *label1_ptr = s->code_ptr - label1_ptr - 1;    /* add x(r1), r0 */    tcg_out_modrm_offset(s, 0x03, r0, r1, offsetof(CPUTLBEntry, addend) -                          offsetof(CPUTLBEntry, addr_read));#else    r0 = addr_reg;#endif#ifdef TARGET_WORDS_BIGENDIAN    bswap = 1;#else    bswap = 0;#endif    switch(opc) {    case 0:        /* movzbl */        tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, 0);        break;    case 0 | 4:        /* movsbl */        tcg_out_modrm_offset(s, 0xbe | P_EXT, data_reg, r0, 0);        break;    case 1:        /* movzwl */        tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, 0);        if (bswap) {            /* rolw $8, data_reg */            tcg_out8(s, 0x66);             tcg_out_modrm(s, 0xc1, 0, data_reg);            tcg_out8(s, 8);        }        break;    case 1 | 4:        /* movswl */        tcg_out_modrm_offset(s, 0xbf | P_EXT, data_reg, r0, 0);        if (bswap) {            /* rolw $8, data_reg */            tcg_out8(s, 0x66);             tcg_out_modrm(s, 0xc1, 0, data_reg);            tcg_out8(s, 8);            /* movswl data_reg, data_reg */            tcg_out_modrm(s, 0xbf | P_EXT, data_reg, data_reg);        }        break;    case 2:        /* movl (r0), data_reg */        tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0);        if (bswap) {            /* bswap */            tcg_out_opc(s, (0xc8 + data_reg) | P_EXT);        }        break;    case 3:        /* XXX: could be nicer */        if (r0 == data_reg) {            r1 = TCG_REG_EDX;            if (r1 == data_reg)                r1 = TCG_REG_EAX;            tcg_out_mov(s, r1, r0);            r0 = r1;        }        if (!bswap) {            tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0);            tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, 4);        } else {            tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 4);            tcg_out_opc(s, (0xc8 + data_reg) | P_EXT);            tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, 0);            /* bswap */            tcg_out_opc(s, (0xc8 + data_reg2) | P_EXT);        }        break;    default:        tcg_abort();    }#if defined(CONFIG_SOFTMMU)    /* label2: */    *label2_ptr = s->code_ptr - label2_ptr - 1;#endif}static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,                            int opc){    int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;#if defined(CONFIG_SOFTMMU)    uint8_t *label1_ptr, *label2_ptr;#endif#if TARGET_LONG_BITS == 64#if defined(CONFIG_SOFTMMU)    uint8_t *label3_ptr;#endif    int addr_reg2;#endif    data_reg = *args++;    if (opc == 3)        data_reg2 = *args++;    else        data_reg2 = 0;    addr_reg = *args++;#if TARGET_LONG_BITS == 64    addr_reg2 = *args++;#endif    mem_index = *args;    s_bits = opc;    r0 = TCG_REG_EAX;    r1 = TCG_REG_EDX;#if defined(CONFIG_SOFTMMU)    tcg_out_mov(s, r1, addr_reg);     tcg_out_mov(s, r0, addr_reg);      tcg_out_modrm(s, 0xc1, 5, r1); /* shr $x, r1 */    tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);         tcg_out_modrm(s, 0x81, 4, r0); /* andl $x, r0 */    tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));        tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */    tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);    tcg_out_opc(s, 0x8d); /* lea offset(r1, %ebp), r1 */    tcg_out8(s, 0x80 | (r1 << 3) | 0x04);    tcg_out8(s, (5 << 3) | r1);    tcg_out32(s, offsetof(CPUState, tlb_table[mem_index][0].addr_write));    /* cmp 0(r1), r0 */    tcg_out_modrm_offset(s, 0x3b, r0, r1, 0);        tcg_out_mov(s, r0, addr_reg);    #if TARGET_LONG_BITS == 32    /* je label1 */    tcg_out8(s, 0x70 + JCC_JE);    label1_ptr = s->code_ptr;    s->code_ptr++;#else    /* jne label3 */    tcg_out8(s, 0x70 + JCC_JNE);    label3_ptr = s->code_ptr;    s->code_ptr++;        /* cmp 4(r1), addr_reg2 */    tcg_out_modrm_offset(s, 0x3b, addr_reg2, r1, 4);    /* je label1 */    tcg_out8(s, 0x70 + JCC_JE);    label1_ptr = s->code_ptr;    s->code_ptr++;        /* label3: */    *label3_ptr = s->code_ptr - label3_ptr - 1;#endif    /* XXX: move that code at the end of the TB */#if TARGET_LONG_BITS == 32    if (opc == 3) {        tcg_out_mov(s, TCG_REG_EDX, data_reg);        tcg_out_mov(s, TCG_REG_ECX, data_reg2);        tcg_out8(s, 0x6a); /* push Ib */        tcg_out8(s, mem_index);        tcg_out8(s, 0xe8);        tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] -                   (tcg_target_long)s->code_ptr - 4);        tcg_out_addi(s, TCG_REG_ESP, 4);    } else {        switch(opc) {        case 0:            /* movzbl */            tcg_out_modrm(s, 0xb6 | P_EXT, TCG_REG_EDX, data_reg);            break;        case 1:            /* movzwl */            tcg_out_modrm(s, 0xb7 | P_EXT, TCG_REG_EDX, data_reg);            break;        case 2:            tcg_out_mov(s, TCG_REG_EDX, data_reg);            break;        }        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);        tcg_out8(s, 0xe8);        tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] -                   (tcg_target_long)s->code_ptr - 4);    }#else    if (opc == 3) {        tcg_out_mov(s, TCG_REG_EDX, addr_reg2);        tcg_out8(s, 0x6a); /* push Ib */        tcg_out8(s, mem_index);        tcg_out_opc(s, 0x50 + data_reg2); /* push */        tcg_out_opc(s, 0x50 + data_reg); /* push */        tcg_out8(s, 0xe8);        tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] -                   (tcg_target_long)s->code_ptr - 4);        tcg_out_addi(s, TCG_REG_ESP, 12);    } else {        tcg_out_mov(s, TCG_REG_EDX, addr_reg2);        switch(opc) {        case 0:            /* movzbl */            tcg_out_modrm(s, 0xb6 | P_EXT, TCG_REG_ECX, data_reg);            break;        case 1:            /* movzwl */            tcg_out_modrm(s, 0xb7 | P_EXT, TCG_REG_ECX, data_reg);            break;        case 2:            tcg_out_mov(s, TCG_REG_ECX, data_reg);            break;        }        tcg_out8(s, 0x6a); /* push Ib */        tcg_out8(s, mem_index);        tcg_out8(s, 0xe8);        tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] -                   (tcg_target_long)s->code_ptr - 4);        tcg_out_addi(s, TCG_REG_ESP, 4);    }#endif        /* jmp label2 */    tcg_out8(s, 0xeb);    label2_ptr = s->code_ptr;    s->code_ptr++;        /* label1: */    *label1_ptr = s->code_ptr - label1_ptr - 1;

⌨️ 快捷键说明

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