tcg-target.c

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

C
1,215
字号
    /* add x(r1), r0 */    tcg_out_modrm_offset(s, 0x03, r0, r1, offsetof(CPUTLBEntry, addend) -                          offsetof(CPUTLBEntry, addr_write));#else    r0 = addr_reg;#endif#ifdef TARGET_WORDS_BIGENDIAN    bswap = 1;#else    bswap = 0;#endif    switch(opc) {    case 0:        /* movb */        tcg_out_modrm_offset(s, 0x88, data_reg, r0, 0);        break;    case 1:        if (bswap) {            tcg_out_mov(s, r1, data_reg);            tcg_out8(s, 0x66); /* rolw $8, %ecx */            tcg_out_modrm(s, 0xc1, 0, r1);            tcg_out8(s, 8);            data_reg = r1;        }        /* movw */        tcg_out8(s, 0x66);        tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0);        break;    case 2:        if (bswap) {            tcg_out_mov(s, r1, data_reg);            /* bswap data_reg */            tcg_out_opc(s, (0xc8 + r1) | P_EXT);            data_reg = r1;        }        /* movl */        tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0);        break;    case 3:        if (bswap) {            tcg_out_mov(s, r1, data_reg2);            /* bswap data_reg */            tcg_out_opc(s, (0xc8 + r1) | P_EXT);            tcg_out_modrm_offset(s, 0x89, r1, r0, 0);            tcg_out_mov(s, r1, data_reg);            /* bswap data_reg */            tcg_out_opc(s, (0xc8 + r1) | P_EXT);            tcg_out_modrm_offset(s, 0x89, r1, r0, 4);        } else {            tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0);            tcg_out_modrm_offset(s, 0x89, data_reg2, r0, 4);        }        break;    default:        tcg_abort();    }#if defined(CONFIG_SOFTMMU)    /* label2: */    *label2_ptr = s->code_ptr - label2_ptr - 1;#endif}static inline void tcg_out_op(TCGContext *s, int opc,                               const TCGArg *args, const int *const_args){    int c;        switch(opc) {    case INDEX_op_exit_tb:        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EAX, args[0]);        tcg_out8(s, 0xe9); /* jmp tb_ret_addr */        tcg_out32(s, tb_ret_addr - s->code_ptr - 4);        break;    case INDEX_op_goto_tb:        if (s->tb_jmp_offset) {            /* direct jump method */            tcg_out8(s, 0xe9); /* jmp im */            s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;            tcg_out32(s, 0);        } else {            /* indirect jump method */            /* jmp Ev */            tcg_out_modrm_offset(s, 0xff, 4, -1,                                  (tcg_target_long)(s->tb_next + args[0]));        }        s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;        break;    case INDEX_op_call:        if (const_args[0]) {            tcg_out8(s, 0xe8);            tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4);        } else {            tcg_out_modrm(s, 0xff, 2, args[0]);        }        break;    case INDEX_op_jmp:        if (const_args[0]) {            tcg_out8(s, 0xe9);            tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4);        } else {            tcg_out_modrm(s, 0xff, 4, args[0]);        }        break;    case INDEX_op_br:        tcg_out_jxx(s, JCC_JMP, args[0]);        break;    case INDEX_op_movi_i32:        tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);        break;    case INDEX_op_ld8u_i32:        /* movzbl */        tcg_out_modrm_offset(s, 0xb6 | P_EXT, args[0], args[1], args[2]);        break;    case INDEX_op_ld8s_i32:        /* movsbl */        tcg_out_modrm_offset(s, 0xbe | P_EXT, args[0], args[1], args[2]);        break;    case INDEX_op_ld16u_i32:        /* movzwl */        tcg_out_modrm_offset(s, 0xb7 | P_EXT, args[0], args[1], args[2]);        break;    case INDEX_op_ld16s_i32:        /* movswl */        tcg_out_modrm_offset(s, 0xbf | P_EXT, args[0], args[1], args[2]);        break;    case INDEX_op_ld_i32:        /* movl */        tcg_out_modrm_offset(s, 0x8b, args[0], args[1], args[2]);        break;    case INDEX_op_st8_i32:        /* movb */        tcg_out_modrm_offset(s, 0x88, args[0], args[1], args[2]);        break;    case INDEX_op_st16_i32:        /* movw */        tcg_out8(s, 0x66);        tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);        break;    case INDEX_op_st_i32:        /* movl */        tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);        break;    case INDEX_op_sub_i32:        c = ARITH_SUB;        goto gen_arith;    case INDEX_op_and_i32:        c = ARITH_AND;        goto gen_arith;    case INDEX_op_or_i32:        c = ARITH_OR;        goto gen_arith;    case INDEX_op_xor_i32:        c = ARITH_XOR;        goto gen_arith;    case INDEX_op_add_i32:        c = ARITH_ADD;    gen_arith:        if (const_args[2]) {            tgen_arithi(s, c, args[0], args[2]);        } else {            tcg_out_modrm(s, 0x01 | (c << 3), args[2], args[0]);        }        break;    case INDEX_op_mul_i32:        if (const_args[2]) {            int32_t val;            val = args[2];            if (val == (int8_t)val) {                tcg_out_modrm(s, 0x6b, args[0], args[0]);                tcg_out8(s, val);            } else {                tcg_out_modrm(s, 0x69, args[0], args[0]);                tcg_out32(s, val);            }        } else {            tcg_out_modrm(s, 0xaf | P_EXT, args[0], args[2]);        }        break;    case INDEX_op_mulu2_i32:        tcg_out_modrm(s, 0xf7, 4, args[3]);        break;    case INDEX_op_div2_i32:        tcg_out_modrm(s, 0xf7, 7, args[4]);        break;    case INDEX_op_divu2_i32:        tcg_out_modrm(s, 0xf7, 6, args[4]);        break;    case INDEX_op_shl_i32:        c = SHIFT_SHL;    gen_shift32:        if (const_args[2]) {            if (args[2] == 1) {                tcg_out_modrm(s, 0xd1, c, args[0]);            } else {                tcg_out_modrm(s, 0xc1, c, args[0]);                tcg_out8(s, args[2]);            }        } else {            tcg_out_modrm(s, 0xd3, c, args[0]);        }        break;    case INDEX_op_shr_i32:        c = SHIFT_SHR;        goto gen_shift32;    case INDEX_op_sar_i32:        c = SHIFT_SAR;        goto gen_shift32;            case INDEX_op_add2_i32:        if (const_args[4])             tgen_arithi(s, ARITH_ADD, args[0], args[4]);        else            tcg_out_modrm(s, 0x01 | (ARITH_ADD << 3), args[4], args[0]);        if (const_args[5])             tgen_arithi(s, ARITH_ADC, args[1], args[5]);        else            tcg_out_modrm(s, 0x01 | (ARITH_ADC << 3), args[5], args[1]);        break;    case INDEX_op_sub2_i32:        if (const_args[4])             tgen_arithi(s, ARITH_SUB, args[0], args[4]);        else            tcg_out_modrm(s, 0x01 | (ARITH_SUB << 3), args[4], args[0]);        if (const_args[5])             tgen_arithi(s, ARITH_SBB, args[1], args[5]);        else            tcg_out_modrm(s, 0x01 | (ARITH_SBB << 3), args[5], args[1]);        break;    case INDEX_op_brcond_i32:        tcg_out_brcond(s, args[2], args[0], args[1], const_args[1], args[3]);        break;    case INDEX_op_brcond2_i32:        tcg_out_brcond2(s, args, const_args);        break;    case INDEX_op_qemu_ld8u:        tcg_out_qemu_ld(s, args, 0);        break;    case INDEX_op_qemu_ld8s:        tcg_out_qemu_ld(s, args, 0 | 4);        break;    case INDEX_op_qemu_ld16u:        tcg_out_qemu_ld(s, args, 1);        break;    case INDEX_op_qemu_ld16s:        tcg_out_qemu_ld(s, args, 1 | 4);        break;    case INDEX_op_qemu_ld32u:        tcg_out_qemu_ld(s, args, 2);        break;    case INDEX_op_qemu_ld64:        tcg_out_qemu_ld(s, args, 3);        break;            case INDEX_op_qemu_st8:        tcg_out_qemu_st(s, args, 0);        break;    case INDEX_op_qemu_st16:        tcg_out_qemu_st(s, args, 1);        break;    case INDEX_op_qemu_st32:        tcg_out_qemu_st(s, args, 2);        break;    case INDEX_op_qemu_st64:        tcg_out_qemu_st(s, args, 3);        break;    default:        tcg_abort();    }}static const TCGTargetOpDef x86_op_defs[] = {    { INDEX_op_exit_tb, { } },    { INDEX_op_goto_tb, { } },    { INDEX_op_call, { "ri" } },    { INDEX_op_jmp, { "ri" } },    { INDEX_op_br, { } },    { INDEX_op_mov_i32, { "r", "r" } },    { INDEX_op_movi_i32, { "r" } },    { INDEX_op_ld8u_i32, { "r", "r" } },    { INDEX_op_ld8s_i32, { "r", "r" } },    { INDEX_op_ld16u_i32, { "r", "r" } },    { INDEX_op_ld16s_i32, { "r", "r" } },    { INDEX_op_ld_i32, { "r", "r" } },    { INDEX_op_st8_i32, { "q", "r" } },    { INDEX_op_st16_i32, { "r", "r" } },    { INDEX_op_st_i32, { "r", "r" } },    { INDEX_op_add_i32, { "r", "0", "ri" } },    { INDEX_op_sub_i32, { "r", "0", "ri" } },    { INDEX_op_mul_i32, { "r", "0", "ri" } },    { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },    { INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } },    { INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } },    { INDEX_op_and_i32, { "r", "0", "ri" } },    { INDEX_op_or_i32, { "r", "0", "ri" } },    { INDEX_op_xor_i32, { "r", "0", "ri" } },    { INDEX_op_shl_i32, { "r", "0", "ci" } },    { INDEX_op_shr_i32, { "r", "0", "ci" } },    { INDEX_op_sar_i32, { "r", "0", "ci" } },    { INDEX_op_brcond_i32, { "r", "ri" } },    { INDEX_op_add2_i32, { "r", "r", "0", "1", "ri", "ri" } },    { INDEX_op_sub2_i32, { "r", "r", "0", "1", "ri", "ri" } },    { INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },#if TARGET_LONG_BITS == 32    { INDEX_op_qemu_ld8u, { "r", "L" } },    { INDEX_op_qemu_ld8s, { "r", "L" } },    { INDEX_op_qemu_ld16u, { "r", "L" } },    { INDEX_op_qemu_ld16s, { "r", "L" } },    { INDEX_op_qemu_ld32u, { "r", "L" } },    { INDEX_op_qemu_ld64, { "r", "r", "L" } },    { INDEX_op_qemu_st8, { "cb", "L" } },    { INDEX_op_qemu_st16, { "L", "L" } },    { INDEX_op_qemu_st32, { "L", "L" } },    { INDEX_op_qemu_st64, { "L", "L", "L" } },#else    { INDEX_op_qemu_ld8u, { "r", "L", "L" } },    { INDEX_op_qemu_ld8s, { "r", "L", "L" } },    { INDEX_op_qemu_ld16u, { "r", "L", "L" } },    { INDEX_op_qemu_ld16s, { "r", "L", "L" } },    { INDEX_op_qemu_ld32u, { "r", "L", "L" } },    { INDEX_op_qemu_ld64, { "r", "r", "L", "L" } },    { INDEX_op_qemu_st8, { "cb", "L", "L" } },    { INDEX_op_qemu_st16, { "L", "L", "L" } },    { INDEX_op_qemu_st32, { "L", "L", "L" } },    { INDEX_op_qemu_st64, { "L", "L", "L", "L" } },#endif    { -1 },};static int tcg_target_callee_save_regs[] = {    /*    TCG_REG_EBP, */ /* currently used for the global env, so no                             need to save */    TCG_REG_EBX,    TCG_REG_ESI,    TCG_REG_EDI,};static inline void tcg_out_push(TCGContext *s, int reg){    tcg_out_opc(s, 0x50 + reg);}static inline void tcg_out_pop(TCGContext *s, int reg){    tcg_out_opc(s, 0x58 + reg);}/* Generate global QEMU prologue and epilogue code */void tcg_target_qemu_prologue(TCGContext *s){    int i, frame_size, push_size, stack_addend;        /* TB prologue */    /* save all callee saved registers */    for(i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {        tcg_out_push(s, tcg_target_callee_save_regs[i]);    }    /* reserve some stack space */    push_size = 4 + ARRAY_SIZE(tcg_target_callee_save_regs) * 4;    frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE;    frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &         ~(TCG_TARGET_STACK_ALIGN - 1);    stack_addend = frame_size - push_size;    tcg_out_addi(s, TCG_REG_ESP, -stack_addend);    tcg_out_modrm(s, 0xff, 4, TCG_REG_EAX); /* jmp *%eax */        /* TB epilogue */    tb_ret_addr = s->code_ptr;    tcg_out_addi(s, TCG_REG_ESP, stack_addend);    for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {        tcg_out_pop(s, tcg_target_callee_save_regs[i]);    }    tcg_out8(s, 0xc3); /* ret */}void tcg_target_init(TCGContext *s){    /* fail safe */    if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))        tcg_abort();    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xff);    tcg_regset_set32(tcg_target_call_clobber_regs, 0,                     (1 << TCG_REG_EAX) |                      (1 << TCG_REG_EDX) |                      (1 << TCG_REG_ECX));        tcg_regset_clear(s->reserved_regs);    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ESP);    tcg_add_target_add_op_defs(x86_op_defs);}

⌨️ 快捷键说明

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