mirror of https://gitee.com/openkylin/qemu.git
Queued TCG patches
-----BEGIN PGP SIGNATURE----- iQEcBAABAgAGBQJZYy1gAAoJEK0ScMxN0CebY9gH/A6jcmXNdaG6bWLtOiCXy+gh uRs5jvy7vh5s4+tIUMuJFA6f1dEpoTv/jl7KEM8eA2xJfLKDxKCOnhQBWYL4Kekx PLinjJ4mPtN0R1Da2WgX9qmGpW2RCktITgiwKzM7VPznZ7+fAutfPvOyWe/KpUQ2 gEJq3jUEC0p/5AGTY/t/Ek1P8Hlu5EVTdCzzfIUtOPCkI/KelMqjkGHu6dNJieKT Tjoe+crx06xFBedb8WJsIEBICFy7J4JXSMScd6L374xyj0rj5LmAXuUg6SlU/FTC jLwnqEXSuFPEgpd2oKK9qnw1CUvHAqxJQLXGeA7E8Ic4c+GmAh0q5HtlSyb11sY= =qJgI -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/rth/tags/pull-tcg-20170709' into staging Queued TCG patches # gpg: Signature made Mon 10 Jul 2017 08:31:44 BST # gpg: using RSA key 0xAD1270CC4DD0279B # gpg: Good signature from "Richard Henderson <rth7680@gmail.com>" # gpg: aka "Richard Henderson <rth@redhat.com>" # gpg: aka "Richard Henderson <rth@twiddle.net>" # Primary key fingerprint: 9CB1 8DDA F8E8 49AD 2AFC 16A4 AD12 70CC 4DD0 279B * remotes/rth/tags/pull-tcg-20170709: tcg/mips: Bugfix for crash when running program with qemu-i386. util/cacheinfo: Fix warning generated by clang tcg/aarch64: Enable indirect jump path using LDR (literal) tcg/aarch64: Use ADRP+ADD to compute target address tcg/aarch64: Introduce and use long branch to register Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
6580476a14
|
@ -504,7 +504,7 @@ static inline PageDesc *page_find(tb_page_addr_t index)
|
|||
#elif defined(__powerpc__)
|
||||
# define MAX_CODE_GEN_BUFFER_SIZE (32u * 1024 * 1024)
|
||||
#elif defined(__aarch64__)
|
||||
# define MAX_CODE_GEN_BUFFER_SIZE (128ul * 1024 * 1024)
|
||||
# define MAX_CODE_GEN_BUFFER_SIZE (2ul * 1024 * 1024 * 1024)
|
||||
#elif defined(__s390x__)
|
||||
/* We have a +- 4GB range on the branches; leave some slop. */
|
||||
# define MAX_CODE_GEN_BUFFER_SIZE (3ul * 1024 * 1024 * 1024)
|
||||
|
|
|
@ -269,6 +269,8 @@ typedef enum {
|
|||
I3207_BLR = 0xd63f0000,
|
||||
I3207_RET = 0xd65f0000,
|
||||
|
||||
/* Load literal for loading the address at pc-relative offset */
|
||||
I3305_LDR = 0x58000000,
|
||||
/* Load/store register. Described here as 3.3.12, but the helper
|
||||
that emits them can transform to 3.3.10 or 3.3.13. */
|
||||
I3312_STRB = 0x38000000 | LDST_ST << 22 | MO_8 << 30,
|
||||
|
@ -372,6 +374,7 @@ typedef enum {
|
|||
I3510_EON = 0x4a200000,
|
||||
I3510_ANDS = 0x6a000000,
|
||||
|
||||
NOP = 0xd503201f,
|
||||
/* System instructions. */
|
||||
DMB_ISH = 0xd50338bf,
|
||||
DMB_LD = 0x00000100,
|
||||
|
@ -388,6 +391,11 @@ static inline uint32_t tcg_in32(TCGContext *s)
|
|||
#define tcg_out_insn(S, FMT, OP, ...) \
|
||||
glue(tcg_out_insn_,FMT)(S, glue(glue(glue(I,FMT),_),OP), ## __VA_ARGS__)
|
||||
|
||||
static void tcg_out_insn_3305(TCGContext *s, AArch64Insn insn, int imm19, TCGReg rt)
|
||||
{
|
||||
tcg_out32(s, insn | (imm19 & 0x7ffff) << 5 | rt);
|
||||
}
|
||||
|
||||
static void tcg_out_insn_3201(TCGContext *s, AArch64Insn insn, TCGType ext,
|
||||
TCGReg rt, int imm19)
|
||||
{
|
||||
|
@ -819,6 +827,17 @@ static inline void tcg_out_goto(TCGContext *s, tcg_insn_unit *target)
|
|||
tcg_out_insn(s, 3206, B, offset);
|
||||
}
|
||||
|
||||
static inline void tcg_out_goto_long(TCGContext *s, tcg_insn_unit *target)
|
||||
{
|
||||
ptrdiff_t offset = target - s->code_ptr;
|
||||
if (offset == sextract64(offset, 0, 26)) {
|
||||
tcg_out_insn(s, 3206, BL, offset);
|
||||
} else {
|
||||
tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, (intptr_t)target);
|
||||
tcg_out_insn(s, 3207, BR, TCG_REG_TMP);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void tcg_out_goto_noaddr(TCGContext *s)
|
||||
{
|
||||
/* We pay attention here to not modify the branch target by reading from
|
||||
|
@ -852,15 +871,35 @@ static inline void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef USE_DIRECT_JUMP
|
||||
|
||||
void aarch64_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr)
|
||||
{
|
||||
tcg_insn_unit *code_ptr = (tcg_insn_unit *)jmp_addr;
|
||||
tcg_insn_unit *target = (tcg_insn_unit *)addr;
|
||||
tcg_insn_unit i1, i2;
|
||||
TCGType rt = TCG_TYPE_I64;
|
||||
TCGReg rd = TCG_REG_TMP;
|
||||
uint64_t pair;
|
||||
|
||||
reloc_pc26_atomic(code_ptr, target);
|
||||
flush_icache_range(jmp_addr, jmp_addr + 4);
|
||||
ptrdiff_t offset = addr - jmp_addr;
|
||||
|
||||
if (offset == sextract64(offset, 0, 26)) {
|
||||
i1 = I3206_B | ((offset >> 2) & 0x3ffffff);
|
||||
i2 = NOP;
|
||||
} else {
|
||||
offset = (addr >> 12) - (jmp_addr >> 12);
|
||||
|
||||
/* patch ADRP */
|
||||
i1 = I3406_ADRP | (offset & 3) << 29 | (offset & 0x1ffffc) << (5 - 2) | rd;
|
||||
/* patch ADDI */
|
||||
i2 = I3401_ADDI | rt << 31 | (addr & 0xfff) << 10 | rd << 5 | rd;
|
||||
}
|
||||
pair = (uint64_t)i2 << 32 | i1;
|
||||
atomic_set((uint64_t *)jmp_addr, pair);
|
||||
flush_icache_range(jmp_addr, jmp_addr + 8);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static inline void tcg_out_goto_label(TCGContext *s, TCGLabel *l)
|
||||
{
|
||||
if (!l->has_value) {
|
||||
|
@ -1364,23 +1403,33 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
|
|||
case INDEX_op_exit_tb:
|
||||
/* Reuse the zeroing that exists for goto_ptr. */
|
||||
if (a0 == 0) {
|
||||
tcg_out_goto(s, s->code_gen_epilogue);
|
||||
tcg_out_goto_long(s, s->code_gen_epilogue);
|
||||
} else {
|
||||
tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_X0, a0);
|
||||
tcg_out_goto(s, tb_ret_addr);
|
||||
tcg_out_goto_long(s, tb_ret_addr);
|
||||
}
|
||||
break;
|
||||
|
||||
case INDEX_op_goto_tb:
|
||||
#ifndef USE_DIRECT_JUMP
|
||||
#error "USE_DIRECT_JUMP required for aarch64"
|
||||
#endif
|
||||
/* consistency for USE_DIRECT_JUMP */
|
||||
tcg_debug_assert(s->tb_jmp_insn_offset != NULL);
|
||||
s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s);
|
||||
/* actual branch destination will be patched by
|
||||
aarch64_tb_set_jmp_target later, beware retranslation. */
|
||||
tcg_out_goto_noaddr(s);
|
||||
if (s->tb_jmp_insn_offset != NULL) {
|
||||
/* USE_DIRECT_JUMP */
|
||||
/* Ensure that ADRP+ADD are 8-byte aligned so that an atomic
|
||||
write can be used to patch the target address. */
|
||||
if ((uintptr_t)s->code_ptr & 7) {
|
||||
tcg_out32(s, NOP);
|
||||
}
|
||||
s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s);
|
||||
/* actual branch destination will be patched by
|
||||
aarch64_tb_set_jmp_target later. */
|
||||
tcg_out_insn(s, 3406, ADRP, TCG_REG_TMP, 0);
|
||||
tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64, TCG_REG_TMP, TCG_REG_TMP, 0);
|
||||
} else {
|
||||
/* !USE_DIRECT_JUMP */
|
||||
tcg_debug_assert(s->tb_jmp_target_addr != NULL);
|
||||
intptr_t offset = tcg_pcrel_diff(s, (s->tb_jmp_target_addr + a0)) >> 2;
|
||||
tcg_out_insn(s, 3305, LDR, offset, TCG_REG_TMP);
|
||||
}
|
||||
tcg_out_insn(s, 3207, BR, TCG_REG_TMP);
|
||||
s->tb_jmp_reset_offset[a0] = tcg_current_code_size(s);
|
||||
break;
|
||||
|
||||
|
|
|
@ -1547,8 +1547,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64)
|
|||
} else if (guest_base == (int16_t)guest_base) {
|
||||
tcg_out_opc_imm(s, ALIAS_PADDI, base, addr_regl, guest_base);
|
||||
} else {
|
||||
tcg_out_movi(s, TCG_TYPE_PTR, base, guest_base);
|
||||
tcg_out_opc_reg(s, ALIAS_PADD, base, base, addr_regl);
|
||||
tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, guest_base);
|
||||
tcg_out_opc_reg(s, ALIAS_PADD, base, TCG_TMP0, addr_regl);
|
||||
}
|
||||
tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc, is_64);
|
||||
#endif
|
||||
|
@ -1652,8 +1652,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64)
|
|||
} else if (guest_base == (int16_t)guest_base) {
|
||||
tcg_out_opc_imm(s, ALIAS_PADDI, base, addr_regl, guest_base);
|
||||
} else {
|
||||
tcg_out_movi(s, TCG_TYPE_PTR, base, guest_base);
|
||||
tcg_out_opc_reg(s, ALIAS_PADD, base, base, addr_regl);
|
||||
tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, guest_base);
|
||||
tcg_out_opc_reg(s, ALIAS_PADD, base, TCG_TMP0, addr_regl);
|
||||
}
|
||||
tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
|
||||
#endif
|
||||
|
|
|
@ -112,7 +112,7 @@ static void sys_cache_info(int *isize, int *dsize)
|
|||
static void arch_cache_info(int *isize, int *dsize)
|
||||
{
|
||||
if (*isize == 0 || *dsize == 0) {
|
||||
unsigned ctr;
|
||||
unsigned long ctr;
|
||||
|
||||
/* The real cache geometry is in CCSIDR_EL1/CLIDR_EL1/CSSELR_EL1,
|
||||
but (at least under Linux) these are marked protected by the
|
||||
|
|
Loading…
Reference in New Issue