tcg-target.c

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

C
1,300
字号
            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], (uint32_t)args[1]);        break;    case INDEX_op_movi_i64:        tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);        break;    case INDEX_op_ld8u_i32:    case INDEX_op_ld8u_i64:        /* 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_ld8s_i64:        /* movsbq */        tcg_out_modrm_offset(s, 0xbe | P_EXT | P_REXW, args[0], args[1], args[2]);        break;    case INDEX_op_ld16u_i32:    case INDEX_op_ld16u_i64:        /* 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_ld16s_i64:        /* movswq */        tcg_out_modrm_offset(s, 0xbf | P_EXT | P_REXW, args[0], args[1], args[2]);        break;    case INDEX_op_ld_i32:    case INDEX_op_ld32u_i64:        /* movl */        tcg_out_modrm_offset(s, 0x8b, args[0], args[1], args[2]);        break;    case INDEX_op_ld32s_i64:        /* movslq */        tcg_out_modrm_offset(s, 0x63 | P_REXW, args[0], args[1], args[2]);        break;    case INDEX_op_ld_i64:        /* movq */        tcg_out_modrm_offset(s, 0x8b | P_REXW, args[0], args[1], args[2]);        break;            case INDEX_op_st8_i32:    case INDEX_op_st8_i64:        /* movb */        tcg_out_modrm_offset(s, 0x88 | P_REXB, args[0], args[1], args[2]);        break;    case INDEX_op_st16_i32:    case INDEX_op_st16_i64:        /* movw */        tcg_out8(s, 0x66);        tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);        break;    case INDEX_op_st_i32:    case INDEX_op_st32_i64:        /* movl */        tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);        break;    case INDEX_op_st_i64:        /* movq */        tcg_out_modrm_offset(s, 0x89 | P_REXW, args[0], args[1], args[2]);        break;    case INDEX_op_sub_i32:        c = ARITH_SUB;        goto gen_arith32;    case INDEX_op_and_i32:        c = ARITH_AND;        goto gen_arith32;    case INDEX_op_or_i32:        c = ARITH_OR;        goto gen_arith32;    case INDEX_op_xor_i32:        c = ARITH_XOR;        goto gen_arith32;    case INDEX_op_add_i32:        c = ARITH_ADD;    gen_arith32:        if (const_args[2]) {            tgen_arithi32(s, c, args[0], args[2]);        } else {            tcg_out_modrm(s, 0x01 | (c << 3), args[2], args[0]);        }        break;    case INDEX_op_sub_i64:        c = ARITH_SUB;        goto gen_arith64;    case INDEX_op_and_i64:        c = ARITH_AND;        goto gen_arith64;    case INDEX_op_or_i64:        c = ARITH_OR;        goto gen_arith64;    case INDEX_op_xor_i64:        c = ARITH_XOR;        goto gen_arith64;    case INDEX_op_add_i64:        c = ARITH_ADD;    gen_arith64:        if (const_args[2]) {            tgen_arithi64(s, c, args[0], args[2]);        } else {            tcg_out_modrm(s, 0x01 | (c << 3) | P_REXW, 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_mul_i64:        if (const_args[2]) {            int32_t val;            val = args[2];            if (val == (int8_t)val) {                tcg_out_modrm(s, 0x6b | P_REXW, args[0], args[0]);                tcg_out8(s, val);            } else {                tcg_out_modrm(s, 0x69 | P_REXW, args[0], args[0]);                tcg_out32(s, val);            }        } else {            tcg_out_modrm(s, 0xaf | P_EXT | P_REXW, args[0], args[2]);        }        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_div2_i64:        tcg_out_modrm(s, 0xf7 | P_REXW, 7, args[4]);        break;    case INDEX_op_divu2_i64:        tcg_out_modrm(s, 0xf7 | P_REXW, 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_shl_i64:        c = SHIFT_SHL;    gen_shift64:        if (const_args[2]) {            if (args[2] == 1) {                tcg_out_modrm(s, 0xd1 | P_REXW, c, args[0]);            } else {                tcg_out_modrm(s, 0xc1 | P_REXW, c, args[0]);                tcg_out8(s, args[2]);            }        } else {            tcg_out_modrm(s, 0xd3 | P_REXW, c, args[0]);        }        break;    case INDEX_op_shr_i64:        c = SHIFT_SHR;        goto gen_shift64;    case INDEX_op_sar_i64:        c = SHIFT_SAR;        goto gen_shift64;            case INDEX_op_brcond_i32:        tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],                        args[3], 0);        break;    case INDEX_op_brcond_i64:        tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],                        args[3], P_REXW);        break;    case INDEX_op_bswap_i32:        tcg_out_opc(s, (0xc8 + (args[0] & 7)) | P_EXT, 0, args[0], 0);        break;    case INDEX_op_bswap_i64:        tcg_out_opc(s, (0xc8 + (args[0] & 7)) | P_EXT | P_REXW, 0, args[0], 0);        break;    case INDEX_op_neg_i32:        tcg_out_modrm(s, 0xf7, 3, args[0]);        break;    case INDEX_op_neg_i64:        tcg_out_modrm(s, 0xf7 | P_REXW, 3, args[0]);        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_ld32s:        tcg_out_qemu_ld(s, args, 2 | 4);        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 int tcg_target_callee_save_regs[] = {    TCG_REG_RBP,    TCG_REG_RBX,    TCG_REG_R12,    TCG_REG_R13,    /*    TCG_REG_R14, */ /* currently used for the global env, so no                             need to save */    TCG_REG_R15,};static inline void tcg_out_push(TCGContext *s, int reg){    tcg_out_opc(s, (0x50 + (reg & 7)), 0, reg, 0);}static inline void tcg_out_pop(TCGContext *s, int reg){    tcg_out_opc(s, (0x58 + (reg & 7)), 0, reg, 0);}/* 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 = 8 + ARRAY_SIZE(tcg_target_callee_save_regs) * 8;    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_RSP, -stack_addend);    tcg_out_modrm(s, 0xff, 4, TCG_REG_RDI); /* jmp *%rdi */        /* TB epilogue */    tb_ret_addr = s->code_ptr;    tcg_out_addi(s, TCG_REG_RSP, 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 */}static const TCGTargetOpDef x86_64_op_defs[] = {    { INDEX_op_exit_tb, { } },    { INDEX_op_goto_tb, { } },    { INDEX_op_call, { "ri" } }, /* XXX: might need a specific constant constraint */    { INDEX_op_jmp, { "ri" } }, /* XXX: might need a specific constant constraint */    { 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, { "r", "r" } },    { INDEX_op_st16_i32, { "r", "r" } },    { INDEX_op_st_i32, { "r", "r" } },    { INDEX_op_add_i32, { "r", "0", "ri" } },    { INDEX_op_mul_i32, { "r", "0", "ri" } },    { INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } },    { INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } },    { INDEX_op_sub_i32, { "r", "0", "ri" } },    { 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_mov_i64, { "r", "r" } },    { INDEX_op_movi_i64, { "r" } },    { INDEX_op_ld8u_i64, { "r", "r" } },    { INDEX_op_ld8s_i64, { "r", "r" } },    { INDEX_op_ld16u_i64, { "r", "r" } },    { INDEX_op_ld16s_i64, { "r", "r" } },    { INDEX_op_ld32u_i64, { "r", "r" } },    { INDEX_op_ld32s_i64, { "r", "r" } },    { INDEX_op_ld_i64, { "r", "r" } },    { INDEX_op_st8_i64, { "r", "r" } },    { INDEX_op_st16_i64, { "r", "r" } },    { INDEX_op_st32_i64, { "r", "r" } },    { INDEX_op_st_i64, { "r", "r" } },    { INDEX_op_add_i64, { "r", "0", "re" } },    { INDEX_op_mul_i64, { "r", "0", "re" } },    { INDEX_op_div2_i64, { "a", "d", "0", "1", "r" } },    { INDEX_op_divu2_i64, { "a", "d", "0", "1", "r" } },    { INDEX_op_sub_i64, { "r", "0", "re" } },    { INDEX_op_and_i64, { "r", "0", "reZ" } },    { INDEX_op_or_i64, { "r", "0", "re" } },    { INDEX_op_xor_i64, { "r", "0", "re" } },    { INDEX_op_shl_i64, { "r", "0", "ci" } },    { INDEX_op_shr_i64, { "r", "0", "ci" } },    { INDEX_op_sar_i64, { "r", "0", "ci" } },    { INDEX_op_brcond_i64, { "r", "re" } },    { INDEX_op_bswap_i32, { "r", "0" } },    { INDEX_op_bswap_i64, { "r", "0" } },    { INDEX_op_neg_i32, { "r", "0" } },    { INDEX_op_neg_i64, { "r", "0" } },    { 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_ld32s, { "r", "L" } },    { INDEX_op_qemu_ld64, { "r", "L" } },    { INDEX_op_qemu_st8, { "L", "L" } },    { INDEX_op_qemu_st16, { "L", "L" } },    { INDEX_op_qemu_st32, { "L", "L" } },    { INDEX_op_qemu_st64, { "L", "L", "L" } },    { -1 },};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, 0xffff);    tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff);    tcg_regset_set32(tcg_target_call_clobber_regs, 0,                     (1 << TCG_REG_RDI) |                      (1 << TCG_REG_RSI) |                      (1 << TCG_REG_RDX) |                     (1 << TCG_REG_RCX) |                     (1 << TCG_REG_R8) |                     (1 << TCG_REG_R9) |                     (1 << TCG_REG_RAX) |                     (1 << TCG_REG_R10) |                     (1 << TCG_REG_R11));        tcg_regset_clear(s->reserved_regs);    tcg_regset_set_reg(s->reserved_regs, TCG_REG_RSP);    tcg_add_target_add_op_defs(x86_64_op_defs);}

⌨️ 快捷键说明

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