--- qemu/tcg/x86_64/tcg-target.c 2018/04/24 16:51:10 1.1.1.1 +++ qemu/tcg/x86_64/tcg-target.c 2018/04/24 17:35:27 1.1.1.3 @@ -44,22 +44,21 @@ static const char * const tcg_target_reg #endif static const int tcg_target_reg_alloc_order[] = { - TCG_REG_RDI, - TCG_REG_RSI, - TCG_REG_RDX, - TCG_REG_RCX, - TCG_REG_R8, - TCG_REG_R9, - TCG_REG_RAX, - TCG_REG_R10, - TCG_REG_R11, - TCG_REG_RBP, TCG_REG_RBX, TCG_REG_R12, TCG_REG_R13, TCG_REG_R14, TCG_REG_R15, + TCG_REG_R10, + TCG_REG_R11, + TCG_REG_R9, + TCG_REG_R8, + TCG_REG_RCX, + TCG_REG_RDX, + TCG_REG_RSI, + TCG_REG_RDI, + TCG_REG_RAX, }; static const int tcg_target_call_iarg_regs[6] = { @@ -194,6 +193,8 @@ static inline int tcg_target_const_match #define ARITH_XOR 6 #define ARITH_CMP 7 +#define SHIFT_ROL 0 +#define SHIFT_ROR 1 #define SHIFT_SHL 4 #define SHIFT_SHR 5 #define SHIFT_SAR 7 @@ -243,7 +244,7 @@ static inline void tcg_out_opc(TCGContex } if (opc & P_EXT) tcg_out8(s, 0x0f); - tcg_out8(s, opc); + tcg_out8(s, opc & 0xff); } static inline void tcg_out_modrm(TCGContext *s, int opc, int r, int rm) @@ -362,6 +363,20 @@ static inline void tcg_out_movi(TCGConte } } +static void tcg_out_goto(TCGContext *s, int call, uint8_t *target) +{ + int32_t disp; + + disp = target - s->code_ptr - 5; + if (disp == (target - s->code_ptr - 5)) { + tcg_out8(s, call ? 0xe8 : 0xe9); + tcg_out32(s, disp); + } else { + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R10, (tcg_target_long) target); + tcg_out_modrm(s, 0xff, call ? 2 : 4, TCG_REG_R10); + } +} + static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret, int arg1, tcg_target_long arg2) { @@ -382,7 +397,13 @@ static inline void tcg_out_st(TCGContext static inline void tgen_arithi32(TCGContext *s, int c, int r0, int32_t val) { - if (val == (int8_t)val) { + if ((c == ARITH_ADD && val == 1) || (c == ARITH_SUB && val == -1)) { + /* inc */ + tcg_out_modrm(s, 0xff, 0, r0); + } else if ((c == ARITH_ADD && val == -1) || (c == ARITH_SUB && val == 1)) { + /* dec */ + tcg_out_modrm(s, 0xff, 1, r0); + } else if (val == (int8_t)val) { tcg_out_modrm(s, 0x83, c, r0); tcg_out8(s, val); } else if (c == ARITH_AND && val == 0xffu) { @@ -399,7 +420,13 @@ static inline void tgen_arithi32(TCGCont static inline void tgen_arithi64(TCGContext *s, int c, int r0, int64_t val) { - if (val == (int8_t)val) { + if ((c == ARITH_ADD && val == 1) || (c == ARITH_SUB && val == -1)) { + /* inc */ + tcg_out_modrm(s, 0xff | P_REXW, 0, r0); + } else if ((c == ARITH_ADD && val == -1) || (c == ARITH_SUB && val == 1)) { + /* dec */ + tcg_out_modrm(s, 0xff | P_REXW, 1, r0); + } else if (val == (int8_t)val) { tcg_out_modrm(s, 0x83 | P_REXW, c, r0); tcg_out8(s, val); } else if (c == ARITH_AND && val == 0xffu) { @@ -507,6 +534,7 @@ static void tcg_out_qemu_ld(TCGContext * int opc) { int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw; + int32_t offset; #if defined(CONFIG_SOFTMMU) uint8_t *label1_ptr, *label2_ptr; #endif @@ -557,9 +585,7 @@ static void tcg_out_qemu_ld(TCGContext * /* XXX: move that code at the end of the TB */ tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RSI, mem_index); - tcg_out8(s, 0xe8); - tcg_out32(s, (tcg_target_long)qemu_ld_helpers[s_bits] - - (tcg_target_long)s->code_ptr - 4); + tcg_out_goto(s, 1, qemu_ld_helpers[s_bits]); switch(opc) { case 0 | 4: @@ -603,8 +629,20 @@ static void tcg_out_qemu_ld(TCGContext * /* add x(r1), r0 */ tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) - offsetof(CPUTLBEntry, addr_read)); + offset = 0; #else - r0 = addr_reg; + if (GUEST_BASE == (int32_t)GUEST_BASE) { + r0 = addr_reg; + offset = GUEST_BASE; + } else { + offset = 0; + /* movq $GUEST_BASE, r0 */ + tcg_out_opc(s, (0xb8 + (r0 & 7)) | P_REXW, 0, r0, 0); + tcg_out32(s, GUEST_BASE); + tcg_out32(s, GUEST_BASE >> 32); + /* addq addr_reg, r0 */ + tcg_out_modrm(s, 0x01 | P_REXW, addr_reg, r0); + } #endif #ifdef TARGET_WORDS_BIGENDIAN @@ -615,15 +653,15 @@ static void tcg_out_qemu_ld(TCGContext * switch(opc) { case 0: /* movzbl */ - tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, offset); break; case 0 | 4: /* movsbX */ - tcg_out_modrm_offset(s, 0xbe | P_EXT | rexw, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0xbe | P_EXT | rexw, data_reg, r0, offset); break; case 1: /* movzwl */ - tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, offset); if (bswap) { /* rolw $8, data_reg */ tcg_out8(s, 0x66); @@ -634,7 +672,7 @@ static void tcg_out_qemu_ld(TCGContext * case 1 | 4: if (bswap) { /* movzwl */ - tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, offset); /* rolw $8, data_reg */ tcg_out8(s, 0x66); tcg_out_modrm(s, 0xc1, 0, data_reg); @@ -644,12 +682,12 @@ static void tcg_out_qemu_ld(TCGContext * tcg_out_modrm(s, 0xbf | P_EXT | rexw, data_reg, data_reg); } else { /* movswX */ - tcg_out_modrm_offset(s, 0xbf | P_EXT | rexw, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0xbf | P_EXT | rexw, data_reg, r0, offset); } break; case 2: /* movl (r0), data_reg */ - tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0x8b, data_reg, r0, offset); if (bswap) { /* bswap */ tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0); @@ -658,19 +696,19 @@ static void tcg_out_qemu_ld(TCGContext * case 2 | 4: if (bswap) { /* movl (r0), data_reg */ - tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0x8b, data_reg, r0, offset); /* bswap */ tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0); /* movslq */ tcg_out_modrm(s, 0x63 | P_REXW, data_reg, data_reg); } else { /* movslq */ - tcg_out_modrm_offset(s, 0x63 | P_REXW, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0x63 | P_REXW, data_reg, r0, offset); } break; case 3: /* movq (r0), data_reg */ - tcg_out_modrm_offset(s, 0x8b | P_REXW, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0x8b | P_REXW, data_reg, r0, offset); if (bswap) { /* bswap */ tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT | P_REXW, 0, data_reg, 0); @@ -690,6 +728,7 @@ static void tcg_out_qemu_st(TCGContext * int opc) { int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw; + int32_t offset; #if defined(CONFIG_SOFTMMU) uint8_t *label1_ptr, *label2_ptr; #endif @@ -759,9 +798,7 @@ static void tcg_out_qemu_st(TCGContext * break; } tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, 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_goto(s, 1, qemu_st_helpers[s_bits]); /* jmp label2 */ tcg_out8(s, 0xeb); @@ -774,8 +811,20 @@ static void tcg_out_qemu_st(TCGContext * /* add x(r1), r0 */ tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) - offsetof(CPUTLBEntry, addr_write)); + offset = 0; #else - r0 = addr_reg; + if (GUEST_BASE == (int32_t)GUEST_BASE) { + r0 = addr_reg; + offset = GUEST_BASE; + } else { + offset = 0; + /* movq $GUEST_BASE, r0 */ + tcg_out_opc(s, (0xb8 + (r0 & 7)) | P_REXW, 0, r0, 0); + tcg_out32(s, GUEST_BASE); + tcg_out32(s, GUEST_BASE >> 32); + /* addq addr_reg, r0 */ + tcg_out_modrm(s, 0x01 | P_REXW, addr_reg, r0); + } #endif #ifdef TARGET_WORDS_BIGENDIAN @@ -786,7 +835,7 @@ static void tcg_out_qemu_st(TCGContext * switch(opc) { case 0: /* movb */ - tcg_out_modrm_offset(s, 0x88 | P_REXB, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0x88 | P_REXB, data_reg, r0, offset); break; case 1: if (bswap) { @@ -798,7 +847,7 @@ static void tcg_out_qemu_st(TCGContext * } /* movw */ tcg_out8(s, 0x66); - tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0x89, data_reg, r0, offset); break; case 2: if (bswap) { @@ -808,7 +857,7 @@ static void tcg_out_qemu_st(TCGContext * data_reg = r1; } /* movl */ - tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0x89, data_reg, r0, offset); break; case 3: if (bswap) { @@ -818,7 +867,7 @@ static void tcg_out_qemu_st(TCGContext * data_reg = r1; } /* movq */ - tcg_out_modrm_offset(s, 0x89 | P_REXW, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0x89 | P_REXW, data_reg, r0, offset); break; default: tcg_abort(); @@ -838,8 +887,7 @@ static inline void tcg_out_op(TCGContext switch(opc) { case INDEX_op_exit_tb: tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RAX, args[0]); - tcg_out8(s, 0xe9); /* jmp tb_ret_addr */ - tcg_out32(s, tb_ret_addr - s->code_ptr - 4); + tcg_out_goto(s, 0, tb_ret_addr); break; case INDEX_op_goto_tb: if (s->tb_jmp_offset) { @@ -858,16 +906,14 @@ static inline void tcg_out_op(TCGContext 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); + tcg_out_goto(s, 1, (void *) args[0]); } 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); + tcg_out_goto(s, 0, (void *) args[0]); } else { tcg_out_modrm(s, 0xff, 4, args[0]); } @@ -1049,7 +1095,13 @@ static inline void tcg_out_op(TCGContext case INDEX_op_sar_i32: c = SHIFT_SAR; goto gen_shift32; - + case INDEX_op_rotl_i32: + c = SHIFT_ROL; + goto gen_shift32; + case INDEX_op_rotr_i32: + c = SHIFT_ROR; + goto gen_shift32; + case INDEX_op_shl_i64: c = SHIFT_SHL; gen_shift64: @@ -1070,7 +1122,13 @@ static inline void tcg_out_op(TCGContext case INDEX_op_sar_i64: c = SHIFT_SAR; goto gen_shift64; - + case INDEX_op_rotl_i64: + c = SHIFT_ROL; + goto gen_shift64; + case INDEX_op_rotr_i64: + c = SHIFT_ROR; + goto gen_shift64; + case INDEX_op_brcond_i32: tcg_out_brcond(s, args[2], args[0], args[1], const_args[1], args[3], 0); @@ -1080,10 +1138,17 @@ static inline void tcg_out_op(TCGContext args[3], P_REXW); break; - case INDEX_op_bswap_i32: + case INDEX_op_bswap16_i32: + case INDEX_op_bswap16_i64: + tcg_out8(s, 0x66); + tcg_out_modrm(s, 0xc1, SHIFT_ROL, args[0]); + tcg_out8(s, 8); + break; + case INDEX_op_bswap32_i32: + case INDEX_op_bswap32_i64: tcg_out_opc(s, (0xc8 + (args[0] & 7)) | P_EXT, 0, args[0], 0); break; - case INDEX_op_bswap_i64: + case INDEX_op_bswap64_i64: tcg_out_opc(s, (0xc8 + (args[0] & 7)) | P_EXT | P_REXW, 0, args[0], 0); break; @@ -1094,6 +1159,13 @@ static inline void tcg_out_op(TCGContext tcg_out_modrm(s, 0xf7 | P_REXW, 3, args[0]); break; + case INDEX_op_not_i32: + tcg_out_modrm(s, 0xf7, 2, args[0]); + break; + case INDEX_op_not_i64: + tcg_out_modrm(s, 0xf7 | P_REXW, 2, args[0]); + break; + case INDEX_op_ext8s_i32: tcg_out_modrm(s, 0xbe | P_EXT | P_REXB, args[0], args[1]); break; @@ -1109,6 +1181,21 @@ static inline void tcg_out_op(TCGContext case INDEX_op_ext32s_i64: tcg_out_modrm(s, 0x63 | P_REXW, args[0], args[1]); break; + case INDEX_op_ext8u_i32: + tcg_out_modrm(s, 0xb6 | P_EXT | P_REXB, args[0], args[1]); + break; + case INDEX_op_ext16u_i32: + tcg_out_modrm(s, 0xb7 | P_EXT, args[0], args[1]); + break; + case INDEX_op_ext8u_i64: + tcg_out_modrm(s, 0xb6 | P_EXT | P_REXW, args[0], args[1]); + break; + case INDEX_op_ext16u_i64: + tcg_out_modrm(s, 0xb7 | P_EXT | P_REXW, args[0], args[1]); + break; + case INDEX_op_ext32u_i64: + tcg_out_modrm(s, 0x8b, args[0], args[1]); + break; case INDEX_op_qemu_ld8u: tcg_out_qemu_ld(s, args, 0); @@ -1230,6 +1317,8 @@ static const TCGTargetOpDef x86_64_op_de { INDEX_op_shl_i32, { "r", "0", "ci" } }, { INDEX_op_shr_i32, { "r", "0", "ci" } }, { INDEX_op_sar_i32, { "r", "0", "ci" } }, + { INDEX_op_rotl_i32, { "r", "0", "ci" } }, + { INDEX_op_rotr_i32, { "r", "0", "ci" } }, { INDEX_op_brcond_i32, { "r", "ri" } }, @@ -1259,20 +1348,33 @@ static const TCGTargetOpDef x86_64_op_de { INDEX_op_shl_i64, { "r", "0", "ci" } }, { INDEX_op_shr_i64, { "r", "0", "ci" } }, { INDEX_op_sar_i64, { "r", "0", "ci" } }, + { INDEX_op_rotl_i64, { "r", "0", "ci" } }, + { INDEX_op_rotr_i64, { "r", "0", "ci" } }, { INDEX_op_brcond_i64, { "r", "re" } }, - { INDEX_op_bswap_i32, { "r", "0" } }, - { INDEX_op_bswap_i64, { "r", "0" } }, + { INDEX_op_bswap16_i32, { "r", "0" } }, + { INDEX_op_bswap16_i64, { "r", "0" } }, + { INDEX_op_bswap32_i32, { "r", "0" } }, + { INDEX_op_bswap32_i64, { "r", "0" } }, + { INDEX_op_bswap64_i64, { "r", "0" } }, { INDEX_op_neg_i32, { "r", "0" } }, { INDEX_op_neg_i64, { "r", "0" } }, + { INDEX_op_not_i32, { "r", "0" } }, + { INDEX_op_not_i64, { "r", "0" } }, + { INDEX_op_ext8s_i32, { "r", "r"} }, { INDEX_op_ext16s_i32, { "r", "r"} }, { INDEX_op_ext8s_i64, { "r", "r"} }, { INDEX_op_ext16s_i64, { "r", "r"} }, { INDEX_op_ext32s_i64, { "r", "r"} }, + { INDEX_op_ext8u_i32, { "r", "r"} }, + { INDEX_op_ext16u_i32, { "r", "r"} }, + { INDEX_op_ext8u_i64, { "r", "r"} }, + { INDEX_op_ext16u_i64, { "r", "r"} }, + { INDEX_op_ext32u_i64, { "r", "r"} }, { INDEX_op_qemu_ld8u, { "r", "L" } }, { INDEX_op_qemu_ld8s, { "r", "L" } }, @@ -1285,7 +1387,7 @@ static const TCGTargetOpDef x86_64_op_de { 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" } }, + { INDEX_op_qemu_st64, { "L", "L" } }, { -1 }, };