1 | Second pull for this week, since this set is large enough by itself. | 1 | The following changes since commit b300c134465465385045ab705b68a42699688332: |
---|---|---|---|
2 | 2 | ||
3 | 3 | Merge tag 'pull-vfio-20230524' of https://github.com/legoater/qemu into staging (2023-05-24 14:23:41 -0700) | |
4 | r~ | ||
5 | |||
6 | |||
7 | The following changes since commit 7c9236d6d61f30583d5d860097d88dbf0fe487bf: | ||
8 | |||
9 | Merge tag 'pull-tcg-20230116' of https://gitlab.com/rth7680/qemu into staging (2023-01-17 10:24:16 +0000) | ||
10 | 4 | ||
11 | are available in the Git repository at: | 5 | are available in the Git repository at: |
12 | 6 | ||
13 | https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20230117 | 7 | https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20230525 |
14 | 8 | ||
15 | for you to fetch changes up to 493c9b19a7fb7f387c4fcf57d3836504d5242bf5: | 9 | for you to fetch changes up to a30498fcea5a8b9c544324ccfb0186090104b229: |
16 | 10 | ||
17 | tcg/riscv: Implement direct branch for goto_tb (2023-01-17 22:36:17 +0000) | 11 | tcg/riscv: Support CTZ, CLZ from Zbb (2023-05-25 15:29:36 +0000) |
18 | 12 | ||
19 | ---------------------------------------------------------------- | 13 | ---------------------------------------------------------------- |
20 | tcg: Fix race conditions in (most) goto_tb implementations | 14 | tcg/mips: |
15 | - Constant formation improvements | ||
16 | - Replace MIPS_BE with HOST_BIG_ENDIAN | ||
17 | - General cleanups | ||
18 | tcg/riscv: | ||
19 | - Improve setcond | ||
20 | - Support movcond | ||
21 | - Support Zbb, Zba | ||
21 | 22 | ||
22 | ---------------------------------------------------------------- | 23 | ---------------------------------------------------------------- |
23 | Richard Henderson (22): | 24 | Richard Henderson (23): |
24 | tcg: Split out tcg_out_exit_tb | 25 | tcg/mips: Move TCG_AREG0 to S8 |
25 | tcg/i386: Remove unused goto_tb code for indirect jump | 26 | tcg/mips: Move TCG_GUEST_BASE_REG to S7 |
26 | tcg/ppc: Remove unused goto_tb code for indirect jump | 27 | tcg/mips: Unify TCG_GUEST_BASE_REG tests |
27 | tcg/sparc64: Remove unused goto_tb code for indirect jump | 28 | tcg/mips: Create and use TCG_REG_TB |
28 | tcg: Replace asserts on tcg_jmp_insn_offset | 29 | tcg/mips: Split out tcg_out_movi_one |
29 | tcg: Introduce set_jmp_insn_offset | 30 | tcg/mips: Split out tcg_out_movi_two |
30 | tcg: Introduce get_jmp_target_addr | 31 | tcg/mips: Use the constant pool for 64-bit constants |
31 | tcg: Split out tcg_out_goto_tb | 32 | tcg/mips: Aggressively use the constant pool for n64 calls |
32 | tcg: Rename TB_JMP_RESET_OFFSET_INVALID to TB_JMP_OFFSET_INVALID | 33 | tcg/mips: Try tb-relative addresses in tcg_out_movi |
33 | tcg: Add gen_tb to TCGContext | 34 | tcg/mips: Try three insns with shift and add in tcg_out_movi |
34 | tcg: Add TranslationBlock.jmp_insn_offset | 35 | tcg/mips: Use qemu_build_not_reached for LO/HI_OFF |
35 | tcg: Change tb_target_set_jmp_target arguments | 36 | tcg/mips: Replace MIPS_BE with HOST_BIG_ENDIAN |
36 | tcg: Move tb_target_set_jmp_target declaration to tcg.h | 37 | disas/riscv: Decode czero.{eqz,nez} |
37 | tcg: Always define tb_target_set_jmp_target | 38 | tcg/riscv: Probe for Zba, Zbb, Zicond extensions |
38 | tcg: Remove TCG_TARGET_HAS_direct_jump | 39 | tcg/riscv: Support ANDN, ORN, XNOR from Zbb |
39 | tcg/aarch64: Reorg goto_tb implementation | 40 | tcg/riscv: Support ADD.UW, SEXT.B, SEXT.H, ZEXT.H from Zba+Zbb |
40 | tcg/ppc: Reorg goto_tb implementation | 41 | tcg/riscv: Use ADD.UW for guest address generation |
41 | tcg/sparc64: Remove USE_REG_TB | 42 | tcg/riscv: Support rotates from Zbb |
42 | tcg/sparc64: Reorg goto_tb implementation | 43 | tcg/riscv: Support REV8 from Zbb |
43 | tcg/arm: Implement direct branch for goto_tb | 44 | tcg/riscv: Support CPOP from Zbb |
44 | tcg/riscv: Introduce OPC_NOP | 45 | tcg/riscv: Improve setcond expansion |
45 | tcg/riscv: Implement direct branch for goto_tb | 46 | tcg/riscv: Implement movcond |
47 | tcg/riscv: Support CTZ, CLZ from Zbb | ||
46 | 48 | ||
47 | include/exec/exec-all.h | 5 +- | 49 | tcg/mips/tcg-target.h | 3 +- |
48 | include/tcg/tcg.h | 14 ++- | 50 | tcg/riscv/tcg-target-con-set.h | 3 + |
49 | tcg/aarch64/tcg-target.h | 6 +- | 51 | tcg/riscv/tcg-target-con-str.h | 1 + |
50 | tcg/arm/tcg-target.h | 5 - | 52 | tcg/riscv/tcg-target.h | 48 ++-- |
51 | tcg/i386/tcg-target.h | 9 -- | 53 | disas/riscv.c | 6 + |
52 | tcg/loongarch64/tcg-target.h | 3 - | 54 | tcg/mips/tcg-target.c.inc | 308 ++++++++++++++++----- |
53 | tcg/mips/tcg-target.h | 5 - | 55 | tcg/riscv/tcg-target.c.inc | 612 ++++++++++++++++++++++++++++++++++++----- |
54 | tcg/ppc/tcg-target.h | 7 +- | 56 | 7 files changed, 825 insertions(+), 156 deletions(-) |
55 | tcg/riscv/tcg-target.h | 4 - | ||
56 | tcg/s390x/tcg-target.h | 11 --- | ||
57 | tcg/sparc64/tcg-target.h | 4 - | ||
58 | tcg/tci/tcg-target.h | 4 - | ||
59 | accel/tcg/cpu-exec.c | 21 ++-- | ||
60 | accel/tcg/translate-all.c | 10 +- | ||
61 | tcg/tcg-op.c | 14 +-- | ||
62 | tcg/tcg.c | 42 +++++--- | ||
63 | tcg/aarch64/tcg-target.c.inc | 106 ++++++++++----------- | ||
64 | tcg/arm/tcg-target.c.inc | 89 +++++++++++------ | ||
65 | tcg/i386/tcg-target.c.inc | 68 +++++++------ | ||
66 | tcg/loongarch64/tcg-target.c.inc | 66 +++++++------ | ||
67 | tcg/mips/tcg-target.c.inc | 59 +++++++----- | ||
68 | tcg/ppc/tcg-target.c.inc | 193 ++++++++++++------------------------- | ||
69 | tcg/riscv/tcg-target.c.inc | 65 +++++++++---- | ||
70 | tcg/s390x/tcg-target.c.inc | 67 ++++++++----- | ||
71 | tcg/sparc64/tcg-target.c.inc | 201 +++++++++++++++------------------------ | ||
72 | tcg/tci/tcg-target.c.inc | 31 +++--- | ||
73 | 26 files changed, 528 insertions(+), 581 deletions(-) | diff view generated by jsdifflib |
1 | Stop overloading jmp_target_arg for both offset and address, | 1 | No functional change; just moving the saved reserved regs to the end. |
---|---|---|---|
2 | depending on TCG_TARGET_HAS_direct_jump. Instead, add a new | ||
3 | field to hold the jump insn offset and always set the target | ||
4 | address in jmp_target_addr[]. This will allow a tcg backend | ||
5 | to use either direct or indirect depending on displacement. | ||
6 | 2 | ||
7 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | 3 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> |
8 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 4 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
9 | --- | 5 | --- |
10 | include/exec/exec-all.h | 3 ++- | 6 | tcg/mips/tcg-target.h | 2 +- |
11 | accel/tcg/cpu-exec.c | 5 ++--- | 7 | tcg/mips/tcg-target.c.inc | 4 ++-- |
12 | tcg/tcg.c | 6 ++++-- | 8 | 2 files changed, 3 insertions(+), 3 deletions(-) |
13 | 3 files changed, 8 insertions(+), 6 deletions(-) | ||
14 | 9 | ||
15 | diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h | 10 | diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h |
16 | index XXXXXXX..XXXXXXX 100644 | 11 | index XXXXXXX..XXXXXXX 100644 |
17 | --- a/include/exec/exec-all.h | 12 | --- a/tcg/mips/tcg-target.h |
18 | +++ b/include/exec/exec-all.h | 13 | +++ b/tcg/mips/tcg-target.h |
19 | @@ -XXX,XX +XXX,XX @@ struct TranslationBlock { | 14 | @@ -XXX,XX +XXX,XX @@ typedef enum { |
20 | */ | 15 | TCG_REG_RA, |
21 | #define TB_JMP_OFFSET_INVALID 0xffff /* indicates no jump generated */ | 16 | |
22 | uint16_t jmp_reset_offset[2]; /* offset of original jump target */ | 17 | TCG_REG_CALL_STACK = TCG_REG_SP, |
23 | - uintptr_t jmp_target_arg[2]; /* target address or offset */ | 18 | - TCG_AREG0 = TCG_REG_S0, |
24 | + uint16_t jmp_insn_offset[2]; /* offset of direct jump insn */ | 19 | + TCG_AREG0 = TCG_REG_S8, |
25 | + uintptr_t jmp_target_addr[2]; /* target address */ | 20 | } TCGReg; |
26 | 21 | ||
27 | /* | 22 | /* used for function call generation */ |
28 | * Each TB has a NULL-terminated list (jmp_list_head) of incoming jumps. | 23 | diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc |
29 | diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c | ||
30 | index XXXXXXX..XXXXXXX 100644 | 24 | index XXXXXXX..XXXXXXX 100644 |
31 | --- a/accel/tcg/cpu-exec.c | 25 | --- a/tcg/mips/tcg-target.c.inc |
32 | +++ b/accel/tcg/cpu-exec.c | 26 | +++ b/tcg/mips/tcg-target.c.inc |
33 | @@ -XXX,XX +XXX,XX @@ void cpu_exec_step_atomic(CPUState *cpu) | 27 | @@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) |
34 | |||
35 | void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr) | ||
36 | { | ||
37 | + tb->jmp_target_addr[n] = addr; | ||
38 | if (TCG_TARGET_HAS_direct_jump) { | ||
39 | - uintptr_t offset = tb->jmp_target_arg[n]; | ||
40 | + uintptr_t offset = tb->jmp_insn_offset[n]; | ||
41 | uintptr_t tc_ptr = (uintptr_t)tb->tc.ptr; | ||
42 | uintptr_t jmp_rx = tc_ptr + offset; | ||
43 | uintptr_t jmp_rw = jmp_rx - tcg_splitwx_diff; | ||
44 | tb_target_set_jmp_target(tc_ptr, jmp_rx, jmp_rw, addr); | ||
45 | - } else { | ||
46 | - tb->jmp_target_arg[n] = addr; | ||
47 | } | ||
48 | } | 28 | } |
49 | 29 | ||
50 | diff --git a/tcg/tcg.c b/tcg/tcg.c | 30 | static const int tcg_target_callee_save_regs[] = { |
51 | index XXXXXXX..XXXXXXX 100644 | 31 | - TCG_REG_S0, /* used for the global env (TCG_AREG0) */ |
52 | --- a/tcg/tcg.c | 32 | + TCG_REG_S0, |
53 | +++ b/tcg/tcg.c | 33 | TCG_REG_S1, |
54 | @@ -XXX,XX +XXX,XX @@ static void G_GNUC_UNUSED set_jmp_insn_offset(TCGContext *s, int which) | 34 | TCG_REG_S2, |
55 | * tcg_gen_code, where we bound tcg_current_code_size to UINT16_MAX. | 35 | TCG_REG_S3, |
56 | */ | 36 | @@ -XXX,XX +XXX,XX @@ static const int tcg_target_callee_save_regs[] = { |
57 | tcg_debug_assert(TCG_TARGET_HAS_direct_jump); | 37 | TCG_REG_S5, |
58 | - s->gen_tb->jmp_target_arg[which] = tcg_current_code_size(s); | 38 | TCG_REG_S6, |
59 | + s->gen_tb->jmp_insn_offset[which] = tcg_current_code_size(s); | 39 | TCG_REG_S7, |
60 | } | 40 | - TCG_REG_S8, |
61 | 41 | + TCG_REG_S8, /* used for the global env (TCG_AREG0) */ | |
62 | static uintptr_t G_GNUC_UNUSED get_jmp_target_addr(TCGContext *s, int which) | 42 | TCG_REG_RA, /* should be last for ABI compliance */ |
63 | @@ -XXX,XX +XXX,XX @@ static uintptr_t G_GNUC_UNUSED get_jmp_target_addr(TCGContext *s, int which) | 43 | }; |
64 | * Return the read-execute version of the pointer, for the benefit | ||
65 | * of any pc-relative addressing mode. | ||
66 | */ | ||
67 | - return (uintptr_t)tcg_splitwx_to_rx(s->gen_tb->jmp_target_arg + which); | ||
68 | + return (uintptr_t)tcg_splitwx_to_rx(&s->gen_tb->jmp_target_addr[which]); | ||
69 | } | ||
70 | |||
71 | /* Signal overflow, starting over with fewer guest insns. */ | ||
72 | @@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, target_ulong pc_start) | ||
73 | /* Initialize goto_tb jump offsets. */ | ||
74 | tb->jmp_reset_offset[0] = TB_JMP_OFFSET_INVALID; | ||
75 | tb->jmp_reset_offset[1] = TB_JMP_OFFSET_INVALID; | ||
76 | + tb->jmp_insn_offset[0] = TB_JMP_OFFSET_INVALID; | ||
77 | + tb->jmp_insn_offset[1] = TB_JMP_OFFSET_INVALID; | ||
78 | |||
79 | tcg_reg_alloc_start(s); | ||
80 | 44 | ||
81 | -- | 45 | -- |
82 | 2.34.1 | 46 | 2.34.1 |
83 | 47 | ||
84 | 48 | diff view generated by jsdifflib |
1 | This can replace four other variables that are references | 1 | No functional change; just moving the saved reserved regs to the end. |
---|---|---|---|
2 | into the TranslationBlock structure. | ||
3 | 2 | ||
4 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | 3 | Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> |
5 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 4 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
6 | --- | 5 | --- |
7 | include/tcg/tcg.h | 11 +++-------- | 6 | tcg/mips/tcg-target.c.inc | 4 ++-- |
8 | accel/tcg/translate-all.c | 2 +- | 7 | 1 file changed, 2 insertions(+), 2 deletions(-) |
9 | tcg/tcg-op.c | 14 +++++++------- | ||
10 | tcg/tcg.c | 14 +++----------- | ||
11 | 4 files changed, 14 insertions(+), 27 deletions(-) | ||
12 | 8 | ||
13 | diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h | 9 | diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc |
14 | index XXXXXXX..XXXXXXX 100644 | 10 | index XXXXXXX..XXXXXXX 100644 |
15 | --- a/include/tcg/tcg.h | 11 | --- a/tcg/mips/tcg-target.c.inc |
16 | +++ b/include/tcg/tcg.h | 12 | +++ b/tcg/mips/tcg-target.c.inc |
17 | @@ -XXX,XX +XXX,XX @@ struct TCGContext { | 13 | @@ -XXX,XX +XXX,XX @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { |
18 | int nb_indirects; | 14 | #define TCG_TMP3 TCG_REG_T7 |
19 | int nb_ops; | 15 | |
20 | 16 | #ifndef CONFIG_SOFTMMU | |
21 | - /* goto_tb support */ | 17 | -#define TCG_GUEST_BASE_REG TCG_REG_S1 |
22 | - tcg_insn_unit *code_buf; | 18 | +#define TCG_GUEST_BASE_REG TCG_REG_S7 |
23 | - uint16_t *tb_jmp_reset_offset; /* tb->jmp_reset_offset */ | 19 | #endif |
24 | - uintptr_t *tb_jmp_insn_offset; /* tb->jmp_target_arg if direct_jump */ | 20 | |
25 | - uintptr_t *tb_jmp_target_addr; /* tb->jmp_target_arg if !direct_jump */ | 21 | /* check if we really need so many registers :P */ |
26 | - | 22 | @@ -XXX,XX +XXX,XX @@ static const int tcg_target_callee_save_regs[] = { |
27 | TCGRegSet reserved_regs; | 23 | TCG_REG_S4, |
28 | - uint32_t tb_cflags; /* cflags of the current TB */ | 24 | TCG_REG_S5, |
29 | intptr_t current_frame_offset; | 25 | TCG_REG_S6, |
30 | intptr_t frame_start; | 26 | - TCG_REG_S7, |
31 | intptr_t frame_end; | 27 | + TCG_REG_S7, /* used for guest_base */ |
32 | TCGTemp *frame_temp; | 28 | TCG_REG_S8, /* used for the global env (TCG_AREG0) */ |
33 | 29 | TCG_REG_RA, /* should be last for ABI compliance */ | |
34 | - tcg_insn_unit *code_ptr; | 30 | }; |
35 | + TranslationBlock *gen_tb; /* tb for which code is being generated */ | ||
36 | + tcg_insn_unit *code_buf; /* pointer for start of tb */ | ||
37 | + tcg_insn_unit *code_ptr; /* pointer for running end of tb */ | ||
38 | |||
39 | #ifdef CONFIG_PROFILER | ||
40 | TCGProfile prof; | ||
41 | diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c | ||
42 | index XXXXXXX..XXXXXXX 100644 | ||
43 | --- a/accel/tcg/translate-all.c | ||
44 | +++ b/accel/tcg/translate-all.c | ||
45 | @@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu, | ||
46 | tb->trace_vcpu_dstate = *cpu->trace_dstate; | ||
47 | tb_set_page_addr0(tb, phys_pc); | ||
48 | tb_set_page_addr1(tb, -1); | ||
49 | - tcg_ctx->tb_cflags = cflags; | ||
50 | + tcg_ctx->gen_tb = tb; | ||
51 | tb_overflow: | ||
52 | |||
53 | #ifdef CONFIG_PROFILER | ||
54 | diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c | ||
55 | index XXXXXXX..XXXXXXX 100644 | ||
56 | --- a/tcg/tcg-op.c | ||
57 | +++ b/tcg/tcg-op.c | ||
58 | @@ -XXX,XX +XXX,XX @@ void tcg_gen_op6(TCGOpcode opc, TCGArg a1, TCGArg a2, TCGArg a3, | ||
59 | |||
60 | void tcg_gen_mb(TCGBar mb_type) | ||
61 | { | ||
62 | - if (tcg_ctx->tb_cflags & CF_PARALLEL) { | ||
63 | + if (tcg_ctx->gen_tb->cflags & CF_PARALLEL) { | ||
64 | tcg_gen_op1(INDEX_op_mb, mb_type); | ||
65 | } | ||
66 | } | ||
67 | @@ -XXX,XX +XXX,XX @@ void tcg_gen_exit_tb(const TranslationBlock *tb, unsigned idx) | ||
68 | void tcg_gen_goto_tb(unsigned idx) | ||
69 | { | ||
70 | /* We tested CF_NO_GOTO_TB in translator_use_goto_tb. */ | ||
71 | - tcg_debug_assert(!(tcg_ctx->tb_cflags & CF_NO_GOTO_TB)); | ||
72 | + tcg_debug_assert(!(tcg_ctx->gen_tb->cflags & CF_NO_GOTO_TB)); | ||
73 | /* We only support two chained exits. */ | ||
74 | tcg_debug_assert(idx <= TB_EXIT_IDXMAX); | ||
75 | #ifdef CONFIG_DEBUG_TCG | ||
76 | @@ -XXX,XX +XXX,XX @@ void tcg_gen_lookup_and_goto_ptr(void) | ||
77 | { | ||
78 | TCGv_ptr ptr; | ||
79 | |||
80 | - if (tcg_ctx->tb_cflags & CF_NO_GOTO_PTR) { | ||
81 | + if (tcg_ctx->gen_tb->cflags & CF_NO_GOTO_PTR) { | ||
82 | tcg_gen_exit_tb(NULL, 0); | ||
83 | return; | ||
84 | } | ||
85 | @@ -XXX,XX +XXX,XX @@ void tcg_gen_atomic_cmpxchg_i32(TCGv_i32 retv, TCGv addr, TCGv_i32 cmpv, | ||
86 | { | ||
87 | memop = tcg_canonicalize_memop(memop, 0, 0); | ||
88 | |||
89 | - if (!(tcg_ctx->tb_cflags & CF_PARALLEL)) { | ||
90 | + if (!(tcg_ctx->gen_tb->cflags & CF_PARALLEL)) { | ||
91 | TCGv_i32 t1 = tcg_temp_new_i32(); | ||
92 | TCGv_i32 t2 = tcg_temp_new_i32(); | ||
93 | |||
94 | @@ -XXX,XX +XXX,XX @@ void tcg_gen_atomic_cmpxchg_i64(TCGv_i64 retv, TCGv addr, TCGv_i64 cmpv, | ||
95 | { | ||
96 | memop = tcg_canonicalize_memop(memop, 1, 0); | ||
97 | |||
98 | - if (!(tcg_ctx->tb_cflags & CF_PARALLEL)) { | ||
99 | + if (!(tcg_ctx->gen_tb->cflags & CF_PARALLEL)) { | ||
100 | TCGv_i64 t1 = tcg_temp_new_i64(); | ||
101 | TCGv_i64 t2 = tcg_temp_new_i64(); | ||
102 | |||
103 | @@ -XXX,XX +XXX,XX @@ static void * const table_##NAME[(MO_SIZE | MO_BSWAP) + 1] = { \ | ||
104 | void tcg_gen_atomic_##NAME##_i32 \ | ||
105 | (TCGv_i32 ret, TCGv addr, TCGv_i32 val, TCGArg idx, MemOp memop) \ | ||
106 | { \ | ||
107 | - if (tcg_ctx->tb_cflags & CF_PARALLEL) { \ | ||
108 | + if (tcg_ctx->gen_tb->cflags & CF_PARALLEL) { \ | ||
109 | do_atomic_op_i32(ret, addr, val, idx, memop, table_##NAME); \ | ||
110 | } else { \ | ||
111 | do_nonatomic_op_i32(ret, addr, val, idx, memop, NEW, \ | ||
112 | @@ -XXX,XX +XXX,XX @@ void tcg_gen_atomic_##NAME##_i32 \ | ||
113 | void tcg_gen_atomic_##NAME##_i64 \ | ||
114 | (TCGv_i64 ret, TCGv addr, TCGv_i64 val, TCGArg idx, MemOp memop) \ | ||
115 | { \ | ||
116 | - if (tcg_ctx->tb_cflags & CF_PARALLEL) { \ | ||
117 | + if (tcg_ctx->gen_tb->cflags & CF_PARALLEL) { \ | ||
118 | do_atomic_op_i64(ret, addr, val, idx, memop, table_##NAME); \ | ||
119 | } else { \ | ||
120 | do_nonatomic_op_i64(ret, addr, val, idx, memop, NEW, \ | ||
121 | diff --git a/tcg/tcg.c b/tcg/tcg.c | ||
122 | index XXXXXXX..XXXXXXX 100644 | ||
123 | --- a/tcg/tcg.c | ||
124 | +++ b/tcg/tcg.c | ||
125 | @@ -XXX,XX +XXX,XX @@ static void set_jmp_reset_offset(TCGContext *s, int which) | ||
126 | * We will check for overflow at the end of the opcode loop in | ||
127 | * tcg_gen_code, where we bound tcg_current_code_size to UINT16_MAX. | ||
128 | */ | ||
129 | - s->tb_jmp_reset_offset[which] = tcg_current_code_size(s); | ||
130 | + s->gen_tb->jmp_reset_offset[which] = tcg_current_code_size(s); | ||
131 | } | ||
132 | |||
133 | static void G_GNUC_UNUSED set_jmp_insn_offset(TCGContext *s, int which) | ||
134 | @@ -XXX,XX +XXX,XX @@ static void G_GNUC_UNUSED set_jmp_insn_offset(TCGContext *s, int which) | ||
135 | * tcg_gen_code, where we bound tcg_current_code_size to UINT16_MAX. | ||
136 | */ | ||
137 | tcg_debug_assert(TCG_TARGET_HAS_direct_jump); | ||
138 | - s->tb_jmp_insn_offset[which] = tcg_current_code_size(s); | ||
139 | + s->gen_tb->jmp_target_arg[which] = tcg_current_code_size(s); | ||
140 | } | ||
141 | |||
142 | static uintptr_t G_GNUC_UNUSED get_jmp_target_addr(TCGContext *s, int which) | ||
143 | @@ -XXX,XX +XXX,XX @@ static uintptr_t G_GNUC_UNUSED get_jmp_target_addr(TCGContext *s, int which) | ||
144 | * Return the read-execute version of the pointer, for the benefit | ||
145 | * of any pc-relative addressing mode. | ||
146 | */ | ||
147 | - return (uintptr_t)tcg_splitwx_to_rx(&s->tb_jmp_target_addr[which]); | ||
148 | + return (uintptr_t)tcg_splitwx_to_rx(s->gen_tb->jmp_target_arg + which); | ||
149 | } | ||
150 | |||
151 | /* Signal overflow, starting over with fewer guest insns. */ | ||
152 | @@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, target_ulong pc_start) | ||
153 | /* Initialize goto_tb jump offsets. */ | ||
154 | tb->jmp_reset_offset[0] = TB_JMP_OFFSET_INVALID; | ||
155 | tb->jmp_reset_offset[1] = TB_JMP_OFFSET_INVALID; | ||
156 | - tcg_ctx->tb_jmp_reset_offset = tb->jmp_reset_offset; | ||
157 | - if (TCG_TARGET_HAS_direct_jump) { | ||
158 | - tcg_ctx->tb_jmp_insn_offset = tb->jmp_target_arg; | ||
159 | - tcg_ctx->tb_jmp_target_addr = NULL; | ||
160 | - } else { | ||
161 | - tcg_ctx->tb_jmp_insn_offset = NULL; | ||
162 | - tcg_ctx->tb_jmp_target_addr = tb->jmp_target_arg; | ||
163 | - } | ||
164 | |||
165 | tcg_reg_alloc_start(s); | ||
166 | |||
167 | -- | 31 | -- |
168 | 2.34.1 | 32 | 2.34.1 |
169 | 33 | ||
170 | 34 | diff view generated by jsdifflib |
New patch | |||
---|---|---|---|
1 | In tcg_out_qemu_ld/st, we already check for guest_base matching int16_t. | ||
2 | Mirror that when setting up TCG_GUEST_BASE_REG in the prologue. | ||
1 | 3 | ||
4 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | ||
5 | --- | ||
6 | tcg/mips/tcg-target.c.inc | 2 +- | ||
7 | 1 file changed, 1 insertion(+), 1 deletion(-) | ||
8 | |||
9 | diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc | ||
10 | index XXXXXXX..XXXXXXX 100644 | ||
11 | --- a/tcg/mips/tcg-target.c.inc | ||
12 | +++ b/tcg/mips/tcg-target.c.inc | ||
13 | @@ -XXX,XX +XXX,XX @@ static void tcg_target_qemu_prologue(TCGContext *s) | ||
14 | } | ||
15 | |||
16 | #ifndef CONFIG_SOFTMMU | ||
17 | - if (guest_base) { | ||
18 | + if (guest_base != (int16_t)guest_base) { | ||
19 | tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base); | ||
20 | tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG); | ||
21 | } | ||
22 | -- | ||
23 | 2.34.1 | diff view generated by jsdifflib |
1 | The INDEX_op_goto_tb opcode needs no register allocation. | 1 | This vastly reduces the size of code generated for 64-bit addresses. |
---|---|---|---|
2 | Split out a dedicated helper function for it. | 2 | The code for exit_tb, for instance, where we load a (tagged) pointer |
3 | to the current TB, goes from | ||
3 | 4 | ||
4 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | 5 | 0x400aa9725c: li v0,64 |
5 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> | 6 | 0x400aa97260: dsll v0,v0,0x10 |
7 | 0x400aa97264: ori v0,v0,0xaa9 | ||
8 | 0x400aa97268: dsll v0,v0,0x10 | ||
9 | 0x400aa9726c: j 0x400aa9703c | ||
10 | 0x400aa97270: ori v0,v0,0x7083 | ||
11 | |||
12 | to | ||
13 | |||
14 | 0x400aa97240: j 0x400aa97040 | ||
15 | 0x400aa97244: daddiu v0,s6,-189 | ||
16 | |||
6 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 17 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
7 | --- | 18 | --- |
8 | tcg/tcg.c | 4 ++ | 19 | tcg/mips/tcg-target.c.inc | 69 +++++++++++++++++++++++++++++++++------ |
9 | tcg/aarch64/tcg-target.c.inc | 40 ++++++++++--------- | 20 | 1 file changed, 59 insertions(+), 10 deletions(-) |
10 | tcg/arm/tcg-target.c.inc | 49 ++++++++++++----------- | ||
11 | tcg/i386/tcg-target.c.inc | 33 ++++++++-------- | ||
12 | tcg/loongarch64/tcg-target.c.inc | 38 +++++++++--------- | ||
13 | tcg/mips/tcg-target.c.inc | 21 +++++----- | ||
14 | tcg/ppc/tcg-target.c.inc | 52 ++++++++++++------------ | ||
15 | tcg/riscv/tcg-target.c.inc | 20 +++++----- | ||
16 | tcg/s390x/tcg-target.c.inc | 31 ++++++++------- | ||
17 | tcg/sparc64/tcg-target.c.inc | 68 +++++++++++++++++--------------- | ||
18 | tcg/tci/tcg-target.c.inc | 16 ++++---- | ||
19 | 11 files changed, 199 insertions(+), 173 deletions(-) | ||
20 | 21 | ||
21 | diff --git a/tcg/tcg.c b/tcg/tcg.c | ||
22 | index XXXXXXX..XXXXXXX 100644 | ||
23 | --- a/tcg/tcg.c | ||
24 | +++ b/tcg/tcg.c | ||
25 | @@ -XXX,XX +XXX,XX @@ static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg); | ||
26 | static void tcg_out_movi(TCGContext *s, TCGType type, | ||
27 | TCGReg ret, tcg_target_long arg); | ||
28 | static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg); | ||
29 | +static void tcg_out_goto_tb(TCGContext *s, int which); | ||
30 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
31 | const TCGArg args[TCG_MAX_OP_ARGS], | ||
32 | const int const_args[TCG_MAX_OP_ARGS]); | ||
33 | @@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, target_ulong pc_start) | ||
34 | case INDEX_op_exit_tb: | ||
35 | tcg_out_exit_tb(s, op->args[0]); | ||
36 | break; | ||
37 | + case INDEX_op_goto_tb: | ||
38 | + tcg_out_goto_tb(s, op->args[0]); | ||
39 | + break; | ||
40 | case INDEX_op_dup2_vec: | ||
41 | if (tcg_reg_alloc_dup2(s, op)) { | ||
42 | break; | ||
43 | diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc | ||
44 | index XXXXXXX..XXXXXXX 100644 | ||
45 | --- a/tcg/aarch64/tcg-target.c.inc | ||
46 | +++ b/tcg/aarch64/tcg-target.c.inc | ||
47 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) | ||
48 | } | ||
49 | } | ||
50 | |||
51 | +static void tcg_out_goto_tb(TCGContext *s, int which) | ||
52 | +{ | ||
53 | + /* | ||
54 | + * Ensure that ADRP+ADD are 8-byte aligned so that an atomic | ||
55 | + * write can be used to patch the target address. | ||
56 | + */ | ||
57 | + if ((uintptr_t)s->code_ptr & 7) { | ||
58 | + tcg_out32(s, NOP); | ||
59 | + } | ||
60 | + set_jmp_insn_offset(s, which); | ||
61 | + /* | ||
62 | + * actual branch destination will be patched by | ||
63 | + * tb_target_set_jmp_target later | ||
64 | + */ | ||
65 | + tcg_out_insn(s, 3406, ADRP, TCG_REG_TMP, 0); | ||
66 | + tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64, TCG_REG_TMP, TCG_REG_TMP, 0); | ||
67 | + tcg_out_insn(s, 3207, BR, TCG_REG_TMP); | ||
68 | + set_jmp_reset_offset(s, which); | ||
69 | +} | ||
70 | + | ||
71 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
72 | const TCGArg args[TCG_MAX_OP_ARGS], | ||
73 | const int const_args[TCG_MAX_OP_ARGS]) | ||
74 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
75 | #define REG0(I) (const_args[I] ? TCG_REG_XZR : (TCGReg)args[I]) | ||
76 | |||
77 | switch (opc) { | ||
78 | - case INDEX_op_goto_tb: | ||
79 | - /* | ||
80 | - * Ensure that ADRP+ADD are 8-byte aligned so that an atomic | ||
81 | - * write can be used to patch the target address. | ||
82 | - */ | ||
83 | - if ((uintptr_t)s->code_ptr & 7) { | ||
84 | - tcg_out32(s, NOP); | ||
85 | - } | ||
86 | - set_jmp_insn_offset(s, a0); | ||
87 | - /* | ||
88 | - * actual branch destination will be patched by | ||
89 | - * tb_target_set_jmp_target later | ||
90 | - */ | ||
91 | - tcg_out_insn(s, 3406, ADRP, TCG_REG_TMP, 0); | ||
92 | - tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64, TCG_REG_TMP, TCG_REG_TMP, 0); | ||
93 | - tcg_out_insn(s, 3207, BR, TCG_REG_TMP); | ||
94 | - set_jmp_reset_offset(s, a0); | ||
95 | - break; | ||
96 | - | ||
97 | case INDEX_op_goto_ptr: | ||
98 | tcg_out_insn(s, 3207, BR, a0); | ||
99 | break; | ||
100 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
101 | case INDEX_op_mov_i64: | ||
102 | case INDEX_op_call: /* Always emitted via tcg_out_call. */ | ||
103 | case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ | ||
104 | + case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */ | ||
105 | default: | ||
106 | g_assert_not_reached(); | ||
107 | } | ||
108 | diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc | ||
109 | index XXXXXXX..XXXXXXX 100644 | ||
110 | --- a/tcg/arm/tcg-target.c.inc | ||
111 | +++ b/tcg/arm/tcg-target.c.inc | ||
112 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg) | ||
113 | tcg_out_epilogue(s); | ||
114 | } | ||
115 | |||
116 | +static void tcg_out_goto_tb(TCGContext *s, int which) | ||
117 | +{ | ||
118 | + /* Indirect jump method */ | ||
119 | + intptr_t ptr, dif, dil; | ||
120 | + TCGReg base = TCG_REG_PC; | ||
121 | + | ||
122 | + qemu_build_assert(!TCG_TARGET_HAS_direct_jump); | ||
123 | + ptr = get_jmp_target_addr(s, which); | ||
124 | + dif = tcg_pcrel_diff(s, (void *)ptr) - 8; | ||
125 | + dil = sextract32(dif, 0, 12); | ||
126 | + if (dif != dil) { | ||
127 | + /* | ||
128 | + * The TB is close, but outside the 12 bits addressable by | ||
129 | + * the load. We can extend this to 20 bits with a sub of a | ||
130 | + * shifted immediate from pc. In the vastly unlikely event | ||
131 | + * the code requires more than 1MB, we'll use 2 insns and | ||
132 | + * be no worse off. | ||
133 | + */ | ||
134 | + base = TCG_REG_R0; | ||
135 | + tcg_out_movi32(s, COND_AL, base, ptr - dil); | ||
136 | + } | ||
137 | + tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, base, dil); | ||
138 | + set_jmp_reset_offset(s, which); | ||
139 | +} | ||
140 | + | ||
141 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
142 | const TCGArg args[TCG_MAX_OP_ARGS], | ||
143 | const int const_args[TCG_MAX_OP_ARGS]) | ||
144 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
145 | int c; | ||
146 | |||
147 | switch (opc) { | ||
148 | - case INDEX_op_goto_tb: | ||
149 | - { | ||
150 | - /* Indirect jump method */ | ||
151 | - intptr_t ptr, dif, dil; | ||
152 | - TCGReg base = TCG_REG_PC; | ||
153 | - | ||
154 | - qemu_build_assert(!TCG_TARGET_HAS_direct_jump); | ||
155 | - ptr = get_jmp_target_addr(s, args[0]); | ||
156 | - dif = tcg_pcrel_diff(s, (void *)ptr) - 8; | ||
157 | - dil = sextract32(dif, 0, 12); | ||
158 | - if (dif != dil) { | ||
159 | - /* The TB is close, but outside the 12 bits addressable by | ||
160 | - the load. We can extend this to 20 bits with a sub of a | ||
161 | - shifted immediate from pc. In the vastly unlikely event | ||
162 | - the code requires more than 1MB, we'll use 2 insns and | ||
163 | - be no worse off. */ | ||
164 | - base = TCG_REG_R0; | ||
165 | - tcg_out_movi32(s, COND_AL, base, ptr - dil); | ||
166 | - } | ||
167 | - tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, base, dil); | ||
168 | - set_jmp_reset_offset(s, args[0]); | ||
169 | - } | ||
170 | - break; | ||
171 | case INDEX_op_goto_ptr: | ||
172 | tcg_out_b_reg(s, COND_AL, args[0]); | ||
173 | break; | ||
174 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
175 | case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ | ||
176 | case INDEX_op_call: /* Always emitted via tcg_out_call. */ | ||
177 | case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ | ||
178 | + case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */ | ||
179 | default: | ||
180 | tcg_abort(); | ||
181 | } | ||
182 | diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc | ||
183 | index XXXXXXX..XXXXXXX 100644 | ||
184 | --- a/tcg/i386/tcg-target.c.inc | ||
185 | +++ b/tcg/i386/tcg-target.c.inc | ||
186 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) | ||
187 | } | ||
188 | } | ||
189 | |||
190 | +static void tcg_out_goto_tb(TCGContext *s, int which) | ||
191 | +{ | ||
192 | + /* | ||
193 | + * Jump displacement must be aligned for atomic patching; | ||
194 | + * see if we need to add extra nops before jump | ||
195 | + */ | ||
196 | + int gap = QEMU_ALIGN_PTR_UP(s->code_ptr + 1, 4) - s->code_ptr; | ||
197 | + if (gap != 1) { | ||
198 | + tcg_out_nopn(s, gap - 1); | ||
199 | + } | ||
200 | + tcg_out8(s, OPC_JMP_long); /* jmp im */ | ||
201 | + set_jmp_insn_offset(s, which); | ||
202 | + tcg_out32(s, 0); | ||
203 | + set_jmp_reset_offset(s, which); | ||
204 | +} | ||
205 | + | ||
206 | static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
207 | const TCGArg args[TCG_MAX_OP_ARGS], | ||
208 | const int const_args[TCG_MAX_OP_ARGS]) | ||
209 | @@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
210 | const_a2 = const_args[2]; | ||
211 | |||
212 | switch (opc) { | ||
213 | - case INDEX_op_goto_tb: | ||
214 | - { | ||
215 | - /* | ||
216 | - * Jump displacement must be aligned for atomic patching; | ||
217 | - * see if we need to add extra nops before jump | ||
218 | - */ | ||
219 | - int gap = QEMU_ALIGN_PTR_UP(s->code_ptr + 1, 4) - s->code_ptr; | ||
220 | - if (gap != 1) { | ||
221 | - tcg_out_nopn(s, gap - 1); | ||
222 | - } | ||
223 | - tcg_out8(s, OPC_JMP_long); /* jmp im */ | ||
224 | - set_jmp_insn_offset(s, a0); | ||
225 | - tcg_out32(s, 0); | ||
226 | - } | ||
227 | - set_jmp_reset_offset(s, a0); | ||
228 | - break; | ||
229 | case INDEX_op_goto_ptr: | ||
230 | /* jmp to the given host address (could be epilogue) */ | ||
231 | tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, a0); | ||
232 | @@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
233 | case INDEX_op_mov_i64: | ||
234 | case INDEX_op_call: /* Always emitted via tcg_out_call. */ | ||
235 | case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ | ||
236 | + case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */ | ||
237 | default: | ||
238 | tcg_abort(); | ||
239 | } | ||
240 | diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc | ||
241 | index XXXXXXX..XXXXXXX 100644 | ||
242 | --- a/tcg/loongarch64/tcg-target.c.inc | ||
243 | +++ b/tcg/loongarch64/tcg-target.c.inc | ||
244 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) | ||
245 | } | ||
246 | } | ||
247 | |||
248 | +static void tcg_out_goto_tb(TCGContext *s, int which) | ||
249 | +{ | ||
250 | + /* | ||
251 | + * Ensure that patch area is 8-byte aligned so that an | ||
252 | + * atomic write can be used to patch the target address. | ||
253 | + */ | ||
254 | + if ((uintptr_t)s->code_ptr & 7) { | ||
255 | + tcg_out_nop(s); | ||
256 | + } | ||
257 | + set_jmp_insn_offset(s, which); | ||
258 | + /* | ||
259 | + * actual branch destination will be patched by | ||
260 | + * tb_target_set_jmp_target later | ||
261 | + */ | ||
262 | + tcg_out_opc_pcaddu18i(s, TCG_REG_TMP0, 0); | ||
263 | + tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_TMP0, 0); | ||
264 | + set_jmp_reset_offset(s, which); | ||
265 | +} | ||
266 | + | ||
267 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
268 | const TCGArg args[TCG_MAX_OP_ARGS], | ||
269 | const int const_args[TCG_MAX_OP_ARGS]) | ||
270 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
271 | int c2 = const_args[2]; | ||
272 | |||
273 | switch (opc) { | ||
274 | - case INDEX_op_goto_tb: | ||
275 | - /* | ||
276 | - * Ensure that patch area is 8-byte aligned so that an | ||
277 | - * atomic write can be used to patch the target address. | ||
278 | - */ | ||
279 | - if ((uintptr_t)s->code_ptr & 7) { | ||
280 | - tcg_out_nop(s); | ||
281 | - } | ||
282 | - set_jmp_insn_offset(s, a0); | ||
283 | - /* | ||
284 | - * actual branch destination will be patched by | ||
285 | - * tb_target_set_jmp_target later | ||
286 | - */ | ||
287 | - tcg_out_opc_pcaddu18i(s, TCG_REG_TMP0, 0); | ||
288 | - tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_TMP0, 0); | ||
289 | - set_jmp_reset_offset(s, a0); | ||
290 | - break; | ||
291 | - | ||
292 | case INDEX_op_mb: | ||
293 | tcg_out_mb(s, a0); | ||
294 | break; | ||
295 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
296 | case INDEX_op_mov_i64: | ||
297 | case INDEX_op_call: /* Always emitted via tcg_out_call. */ | ||
298 | case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ | ||
299 | + case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */ | ||
300 | default: | ||
301 | g_assert_not_reached(); | ||
302 | } | ||
303 | diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc | 22 | diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc |
304 | index XXXXXXX..XXXXXXX 100644 | 23 | index XXXXXXX..XXXXXXX 100644 |
305 | --- a/tcg/mips/tcg-target.c.inc | 24 | --- a/tcg/mips/tcg-target.c.inc |
306 | +++ b/tcg/mips/tcg-target.c.inc | 25 | +++ b/tcg/mips/tcg-target.c.inc |
307 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) | 26 | @@ -XXX,XX +XXX,XX @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { |
308 | tcg_out_opc_imm(s, OPC_ORI, TCG_REG_V0, b0, a0 & 0xffff); | 27 | #ifndef CONFIG_SOFTMMU |
28 | #define TCG_GUEST_BASE_REG TCG_REG_S7 | ||
29 | #endif | ||
30 | +#if TCG_TARGET_REG_BITS == 64 | ||
31 | +#define TCG_REG_TB TCG_REG_S6 | ||
32 | +#else | ||
33 | +#define TCG_REG_TB (qemu_build_not_reached(), TCG_REG_ZERO) | ||
34 | +#endif | ||
35 | |||
36 | /* check if we really need so many registers :P */ | ||
37 | static const int tcg_target_reg_alloc_order[] = { | ||
38 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_clz(TCGContext *s, MIPSInsn opcv2, MIPSInsn opcv6, | ||
39 | |||
40 | static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) | ||
41 | { | ||
42 | - TCGReg b0 = TCG_REG_ZERO; | ||
43 | + TCGReg base = TCG_REG_ZERO; | ||
44 | + int16_t lo = 0; | ||
45 | |||
46 | - if (a0 & ~0xffff) { | ||
47 | - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, a0 & ~0xffff); | ||
48 | - b0 = TCG_REG_V0; | ||
49 | + if (a0) { | ||
50 | + intptr_t ofs; | ||
51 | + if (TCG_TARGET_REG_BITS == 64) { | ||
52 | + ofs = tcg_tbrel_diff(s, (void *)a0); | ||
53 | + lo = ofs; | ||
54 | + if (ofs == lo) { | ||
55 | + base = TCG_REG_TB; | ||
56 | + } else { | ||
57 | + base = TCG_REG_V0; | ||
58 | + tcg_out_movi(s, TCG_TYPE_PTR, base, ofs - lo); | ||
59 | + tcg_out_opc_reg(s, ALIAS_PADD, base, base, TCG_REG_TB); | ||
60 | + } | ||
61 | + } else { | ||
62 | + ofs = a0; | ||
63 | + lo = ofs; | ||
64 | + base = TCG_REG_V0; | ||
65 | + tcg_out_movi(s, TCG_TYPE_PTR, base, ofs - lo); | ||
66 | + } | ||
67 | } | ||
68 | if (!tcg_out_opc_jmp(s, OPC_J, tb_ret_addr)) { | ||
69 | tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, (uintptr_t)tb_ret_addr); | ||
70 | tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0); | ||
71 | } | ||
72 | - tcg_out_opc_imm(s, OPC_ORI, TCG_REG_V0, b0, a0 & 0xffff); | ||
73 | + /* delay slot */ | ||
74 | + tcg_out_opc_imm(s, ALIAS_PADDI, TCG_REG_V0, base, lo); | ||
309 | } | 75 | } |
310 | 76 | ||
311 | +static void tcg_out_goto_tb(TCGContext *s, int which) | 77 | static void tcg_out_goto_tb(TCGContext *s, int which) |
312 | +{ | 78 | { |
313 | + /* indirect jump method */ | 79 | + intptr_t ofs = get_jmp_target_addr(s, which); |
314 | + qemu_build_assert(!TCG_TARGET_HAS_direct_jump); | 80 | + TCGReg base, dest; |
315 | + tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_REG_ZERO, | ||
316 | + get_jmp_target_addr(s, which)); | ||
317 | + tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0); | ||
318 | + tcg_out_nop(s); | ||
319 | + set_jmp_reset_offset(s, which); | ||
320 | +} | ||
321 | + | 81 | + |
322 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 82 | /* indirect jump method */ |
323 | const TCGArg args[TCG_MAX_OP_ARGS], | 83 | - tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_REG_ZERO, |
324 | const int const_args[TCG_MAX_OP_ARGS]) | 84 | - get_jmp_target_addr(s, which)); |
85 | - tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0); | ||
86 | + if (TCG_TARGET_REG_BITS == 64) { | ||
87 | + dest = TCG_REG_TB; | ||
88 | + base = TCG_REG_TB; | ||
89 | + ofs = tcg_tbrel_diff(s, (void *)ofs); | ||
90 | + } else { | ||
91 | + dest = TCG_TMP0; | ||
92 | + base = TCG_REG_ZERO; | ||
93 | + } | ||
94 | + tcg_out_ld(s, TCG_TYPE_PTR, dest, base, ofs); | ||
95 | + tcg_out_opc_reg(s, OPC_JR, 0, dest, 0); | ||
96 | + /* delay slot */ | ||
97 | tcg_out_nop(s); | ||
98 | + | ||
99 | set_jmp_reset_offset(s, which); | ||
100 | + if (TCG_TARGET_REG_BITS == 64) { | ||
101 | + /* For the unlinked case, need to reset TCG_REG_TB. */ | ||
102 | + tcg_out_ldst(s, ALIAS_PADDI, TCG_REG_TB, TCG_REG_TB, | ||
103 | + -tcg_current_code_size(s)); | ||
104 | + } | ||
105 | } | ||
106 | |||
107 | void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | ||
325 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 108 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, |
326 | c2 = const_args[2]; | ||
327 | |||
328 | switch (opc) { | ||
329 | - case INDEX_op_goto_tb: | ||
330 | - /* indirect jump method */ | ||
331 | - qemu_build_assert(!TCG_TARGET_HAS_direct_jump); | ||
332 | - tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_REG_ZERO, | ||
333 | - get_jmp_target_addr(s, a0)); | ||
334 | - tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0); | ||
335 | - tcg_out_nop(s); | ||
336 | - set_jmp_reset_offset(s, a0); | ||
337 | - break; | ||
338 | case INDEX_op_goto_ptr: | 109 | case INDEX_op_goto_ptr: |
339 | /* jmp to the given host address (could be epilogue) */ | 110 | /* jmp to the given host address (could be epilogue) */ |
340 | tcg_out_opc_reg(s, OPC_JR, 0, a0, 0); | 111 | tcg_out_opc_reg(s, OPC_JR, 0, a0, 0); |
341 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 112 | - tcg_out_nop(s); |
342 | case INDEX_op_mov_i64: | 113 | + if (TCG_TARGET_REG_BITS == 64) { |
343 | case INDEX_op_call: /* Always emitted via tcg_out_call. */ | 114 | + tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_TB, a0); |
344 | case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ | 115 | + } else { |
345 | + case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */ | ||
346 | default: | ||
347 | tcg_abort(); | ||
348 | } | ||
349 | diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc | ||
350 | index XXXXXXX..XXXXXXX 100644 | ||
351 | --- a/tcg/ppc/tcg-target.c.inc | ||
352 | +++ b/tcg/ppc/tcg-target.c.inc | ||
353 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg) | ||
354 | tcg_out_b(s, 0, tcg_code_gen_epilogue); | ||
355 | } | ||
356 | |||
357 | +static void tcg_out_goto_tb(TCGContext *s, int which) | ||
358 | +{ | ||
359 | + /* Direct jump. */ | ||
360 | + if (TCG_TARGET_REG_BITS == 64) { | ||
361 | + /* Ensure the next insns are 8 or 16-byte aligned. */ | ||
362 | + while ((uintptr_t)s->code_ptr & (have_isa_2_07 ? 15 : 7)) { | ||
363 | + tcg_out32(s, NOP); | ||
364 | + } | ||
365 | + set_jmp_insn_offset(s, which); | ||
366 | + tcg_out32(s, ADDIS | TAI(TCG_REG_TB, TCG_REG_TB, 0)); | ||
367 | + tcg_out32(s, ADDI | TAI(TCG_REG_TB, TCG_REG_TB, 0)); | ||
368 | + tcg_out32(s, MTSPR | RS(TCG_REG_TB) | CTR); | ||
369 | + tcg_out32(s, BCCTR | BO_ALWAYS); | ||
370 | + set_jmp_reset_offset(s, which); | ||
371 | + if (USE_REG_TB) { | ||
372 | + /* For the unlinked case, need to reset TCG_REG_TB. */ | ||
373 | + tcg_out_mem_long(s, ADDI, ADD, TCG_REG_TB, TCG_REG_TB, | ||
374 | + -tcg_current_code_size(s)); | ||
375 | + } | ||
376 | + } else { | ||
377 | + set_jmp_insn_offset(s, which); | ||
378 | + tcg_out32(s, B); | ||
379 | + set_jmp_reset_offset(s, which); | ||
380 | + } | ||
381 | +} | ||
382 | + | ||
383 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
384 | const TCGArg args[TCG_MAX_OP_ARGS], | ||
385 | const int const_args[TCG_MAX_OP_ARGS]) | ||
386 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
387 | TCGArg a0, a1, a2; | ||
388 | |||
389 | switch (opc) { | ||
390 | - case INDEX_op_goto_tb: | ||
391 | - /* Direct jump. */ | ||
392 | - if (TCG_TARGET_REG_BITS == 64) { | ||
393 | - /* Ensure the next insns are 8 or 16-byte aligned. */ | ||
394 | - while ((uintptr_t)s->code_ptr & (have_isa_2_07 ? 15 : 7)) { | ||
395 | - tcg_out32(s, NOP); | ||
396 | - } | ||
397 | - set_jmp_insn_offset(s, args[0]); | ||
398 | - tcg_out32(s, ADDIS | TAI(TCG_REG_TB, TCG_REG_TB, 0)); | ||
399 | - tcg_out32(s, ADDI | TAI(TCG_REG_TB, TCG_REG_TB, 0)); | ||
400 | - } else { | ||
401 | - set_jmp_insn_offset(s, args[0]); | ||
402 | - tcg_out32(s, B); | ||
403 | - set_jmp_reset_offset(s, args[0]); | ||
404 | - break; | ||
405 | - } | ||
406 | - tcg_out32(s, MTSPR | RS(TCG_REG_TB) | CTR); | ||
407 | - tcg_out32(s, BCCTR | BO_ALWAYS); | ||
408 | - set_jmp_reset_offset(s, args[0]); | ||
409 | - if (USE_REG_TB) { | ||
410 | - /* For the unlinked case, need to reset TCG_REG_TB. */ | ||
411 | - tcg_out_mem_long(s, ADDI, ADD, TCG_REG_TB, TCG_REG_TB, | ||
412 | - -tcg_current_code_size(s)); | ||
413 | - } | ||
414 | - break; | ||
415 | case INDEX_op_goto_ptr: | ||
416 | tcg_out32(s, MTSPR | RS(args[0]) | CTR); | ||
417 | if (USE_REG_TB) { | ||
418 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
419 | case INDEX_op_mov_i64: | ||
420 | case INDEX_op_call: /* Always emitted via tcg_out_call. */ | ||
421 | case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ | ||
422 | + case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */ | ||
423 | default: | ||
424 | tcg_abort(); | ||
425 | } | ||
426 | diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc | ||
427 | index XXXXXXX..XXXXXXX 100644 | ||
428 | --- a/tcg/riscv/tcg-target.c.inc | ||
429 | +++ b/tcg/riscv/tcg-target.c.inc | ||
430 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) | ||
431 | } | ||
432 | } | ||
433 | |||
434 | +static void tcg_out_goto_tb(TCGContext *s, int which) | ||
435 | +{ | ||
436 | + qemu_build_assert(!TCG_TARGET_HAS_direct_jump); | ||
437 | + /* indirect jump method */ | ||
438 | + tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO, | ||
439 | + get_jmp_target_addr(s, which)); | ||
440 | + tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_TMP0, 0); | ||
441 | + set_jmp_reset_offset(s, which); | ||
442 | +} | ||
443 | + | ||
444 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
445 | const TCGArg args[TCG_MAX_OP_ARGS], | ||
446 | const int const_args[TCG_MAX_OP_ARGS]) | ||
447 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
448 | int c2 = const_args[2]; | ||
449 | |||
450 | switch (opc) { | ||
451 | - case INDEX_op_goto_tb: | ||
452 | - qemu_build_assert(!TCG_TARGET_HAS_direct_jump); | ||
453 | - /* indirect jump method */ | ||
454 | - tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO, | ||
455 | - get_jmp_target_addr(s, a0)); | ||
456 | - tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_TMP0, 0); | ||
457 | - set_jmp_reset_offset(s, a0); | ||
458 | - break; | ||
459 | - | ||
460 | case INDEX_op_goto_ptr: | ||
461 | tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, a0, 0); | ||
462 | break; | ||
463 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
464 | case INDEX_op_mov_i64: | ||
465 | case INDEX_op_call: /* Always emitted via tcg_out_call. */ | ||
466 | case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ | ||
467 | + case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */ | ||
468 | default: | ||
469 | g_assert_not_reached(); | ||
470 | } | ||
471 | diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc | ||
472 | index XXXXXXX..XXXXXXX 100644 | ||
473 | --- a/tcg/s390x/tcg-target.c.inc | ||
474 | +++ b/tcg/s390x/tcg-target.c.inc | ||
475 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) | ||
476 | } | ||
477 | } | ||
478 | |||
479 | +static void tcg_out_goto_tb(TCGContext *s, int which) | ||
480 | +{ | ||
481 | + /* | ||
482 | + * Branch displacement must be aligned for atomic patching; | ||
483 | + * see if we need to add extra nop before branch | ||
484 | + */ | ||
485 | + if (!QEMU_PTR_IS_ALIGNED(s->code_ptr + 1, 4)) { | ||
486 | + tcg_out16(s, NOP); | ||
487 | + } | ||
488 | + tcg_out16(s, RIL_BRCL | (S390_CC_ALWAYS << 4)); | ||
489 | + set_jmp_insn_offset(s, which); | ||
490 | + s->code_ptr += 2; | ||
491 | + set_jmp_reset_offset(s, which); | ||
492 | +} | ||
493 | + | ||
494 | # define OP_32_64(x) \ | ||
495 | case glue(glue(INDEX_op_,x),_i32): \ | ||
496 | case glue(glue(INDEX_op_,x),_i64) | ||
497 | @@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
498 | TCGArg a0, a1, a2; | ||
499 | |||
500 | switch (opc) { | ||
501 | - case INDEX_op_goto_tb: | ||
502 | - a0 = args[0]; | ||
503 | - /* | ||
504 | - * branch displacement must be aligned for atomic patching; | ||
505 | - * see if we need to add extra nop before branch | ||
506 | - */ | ||
507 | - if (!QEMU_PTR_IS_ALIGNED(s->code_ptr + 1, 4)) { | ||
508 | - tcg_out16(s, NOP); | ||
509 | - } | ||
510 | - tcg_out16(s, RIL_BRCL | (S390_CC_ALWAYS << 4)); | ||
511 | - set_jmp_insn_offset(s, a0); | ||
512 | - s->code_ptr += 2; | ||
513 | - set_jmp_reset_offset(s, a0); | ||
514 | - break; | ||
515 | - | ||
516 | case INDEX_op_goto_ptr: | ||
517 | a0 = args[0]; | ||
518 | tcg_out_insn(s, RR, BCR, S390_CC_ALWAYS, a0); | ||
519 | @@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
520 | case INDEX_op_mov_i64: | ||
521 | case INDEX_op_call: /* Always emitted via tcg_out_call. */ | ||
522 | case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ | ||
523 | + case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */ | ||
524 | default: | ||
525 | tcg_abort(); | ||
526 | } | ||
527 | diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc | ||
528 | index XXXXXXX..XXXXXXX 100644 | ||
529 | --- a/tcg/sparc64/tcg-target.c.inc | ||
530 | +++ b/tcg/sparc64/tcg-target.c.inc | ||
531 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) | ||
532 | tcg_out_arithi(s, TCG_REG_O0, TCG_REG_O0, a0 & 0x3ff, ARITH_OR); | ||
533 | } | ||
534 | |||
535 | +static void tcg_out_goto_tb(TCGContext *s, int which) | ||
536 | +{ | ||
537 | + /* Direct jump. */ | ||
538 | + if (USE_REG_TB) { | ||
539 | + /* make sure the patch is 8-byte aligned. */ | ||
540 | + if ((intptr_t)s->code_ptr & 4) { | ||
541 | + tcg_out_nop(s); | 116 | + tcg_out_nop(s); |
542 | + } | 117 | + } |
543 | + set_jmp_insn_offset(s, which); | 118 | break; |
544 | + tcg_out_sethi(s, TCG_REG_T1, 0); | 119 | case INDEX_op_br: |
545 | + tcg_out_arithi(s, TCG_REG_T1, TCG_REG_T1, 0, ARITH_OR); | 120 | tcg_out_brcond(s, TCG_COND_EQ, TCG_REG_ZERO, TCG_REG_ZERO, |
546 | + tcg_out_arith(s, TCG_REG_G0, TCG_REG_TB, TCG_REG_T1, JMPL); | 121 | @@ -XXX,XX +XXX,XX @@ static const int tcg_target_callee_save_regs[] = { |
547 | + tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD); | 122 | TCG_REG_S3, |
548 | + } else { | 123 | TCG_REG_S4, |
549 | + set_jmp_insn_offset(s, which); | 124 | TCG_REG_S5, |
550 | + tcg_out32(s, CALL); | 125 | - TCG_REG_S6, |
551 | + tcg_out_nop(s); | 126 | + TCG_REG_S6, /* used for the tb base (TCG_REG_TB) */ |
127 | TCG_REG_S7, /* used for guest_base */ | ||
128 | TCG_REG_S8, /* used for the global env (TCG_AREG0) */ | ||
129 | TCG_REG_RA, /* should be last for ABI compliance */ | ||
130 | @@ -XXX,XX +XXX,XX @@ static void tcg_target_qemu_prologue(TCGContext *s) | ||
131 | tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG); | ||
132 | } | ||
133 | #endif | ||
134 | + if (TCG_TARGET_REG_BITS == 64) { | ||
135 | + tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_TB, tcg_target_call_iarg_regs[1]); | ||
552 | + } | 136 | + } |
553 | + set_jmp_reset_offset(s, which); | 137 | |
554 | + | 138 | /* Call generated code */ |
555 | + /* | 139 | tcg_out_opc_reg(s, OPC_JR, 0, tcg_target_call_iarg_regs[1], 0); |
556 | + * For the unlinked path of goto_tb, we need to reset TCG_REG_TB | 140 | @@ -XXX,XX +XXX,XX @@ static void tcg_target_init(TCGContext *s) |
557 | + * to the beginning of this TB. | 141 | tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); /* return address */ |
558 | + */ | 142 | tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */ |
559 | + if (USE_REG_TB) { | 143 | tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP); /* global pointer */ |
560 | + int c = -tcg_current_code_size(s); | 144 | + if (TCG_TARGET_REG_BITS == 64) { |
561 | + if (check_fit_i32(c, 13)) { | 145 | + tcg_regset_set_reg(s->reserved_regs, TCG_REG_TB); /* tc->tc_ptr */ |
562 | + tcg_out_arithi(s, TCG_REG_TB, TCG_REG_TB, c, ARITH_ADD); | ||
563 | + } else { | ||
564 | + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, c); | ||
565 | + tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD); | ||
566 | + } | ||
567 | + } | 146 | + } |
568 | +} | ||
569 | + | ||
570 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
571 | const TCGArg args[TCG_MAX_OP_ARGS], | ||
572 | const int const_args[TCG_MAX_OP_ARGS]) | ||
573 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
574 | c2 = const_args[2]; | ||
575 | |||
576 | switch (opc) { | ||
577 | - case INDEX_op_goto_tb: | ||
578 | - /* Direct jump. */ | ||
579 | - if (USE_REG_TB) { | ||
580 | - /* make sure the patch is 8-byte aligned. */ | ||
581 | - if ((intptr_t)s->code_ptr & 4) { | ||
582 | - tcg_out_nop(s); | ||
583 | - } | ||
584 | - set_jmp_insn_offset(s, a0); | ||
585 | - tcg_out_sethi(s, TCG_REG_T1, 0); | ||
586 | - tcg_out_arithi(s, TCG_REG_T1, TCG_REG_T1, 0, ARITH_OR); | ||
587 | - tcg_out_arith(s, TCG_REG_G0, TCG_REG_TB, TCG_REG_T1, JMPL); | ||
588 | - tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD); | ||
589 | - } else { | ||
590 | - set_jmp_insn_offset(s, a0); | ||
591 | - tcg_out32(s, CALL); | ||
592 | - tcg_out_nop(s); | ||
593 | - } | ||
594 | - set_jmp_reset_offset(s, a0); | ||
595 | - | ||
596 | - /* For the unlinked path of goto_tb, we need to reset | ||
597 | - TCG_REG_TB to the beginning of this TB. */ | ||
598 | - if (USE_REG_TB) { | ||
599 | - c = -tcg_current_code_size(s); | ||
600 | - if (check_fit_i32(c, 13)) { | ||
601 | - tcg_out_arithi(s, TCG_REG_TB, TCG_REG_TB, c, ARITH_ADD); | ||
602 | - } else { | ||
603 | - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, c); | ||
604 | - tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, | ||
605 | - TCG_REG_T1, ARITH_ADD); | ||
606 | - } | ||
607 | - } | ||
608 | - break; | ||
609 | case INDEX_op_goto_ptr: | ||
610 | tcg_out_arithi(s, TCG_REG_G0, a0, 0, JMPL); | ||
611 | if (USE_REG_TB) { | ||
612 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
613 | case INDEX_op_mov_i64: | ||
614 | case INDEX_op_call: /* Always emitted via tcg_out_call. */ | ||
615 | case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ | ||
616 | + case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */ | ||
617 | default: | ||
618 | tcg_abort(); | ||
619 | } | ||
620 | diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc | ||
621 | index XXXXXXX..XXXXXXX 100644 | ||
622 | --- a/tcg/tci/tcg-target.c.inc | ||
623 | +++ b/tcg/tci/tcg-target.c.inc | ||
624 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg) | ||
625 | tcg_out_op_p(s, INDEX_op_exit_tb, (void *)arg); | ||
626 | } | 147 | } |
627 | 148 | ||
628 | +static void tcg_out_goto_tb(TCGContext *s, int which) | 149 | typedef struct { |
629 | +{ | ||
630 | + qemu_build_assert(!TCG_TARGET_HAS_direct_jump); | ||
631 | + /* indirect jump method. */ | ||
632 | + tcg_out_op_p(s, INDEX_op_goto_tb, (void *)get_jmp_target_addr(s, which)); | ||
633 | + set_jmp_reset_offset(s, which); | ||
634 | +} | ||
635 | + | ||
636 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
637 | const TCGArg args[TCG_MAX_OP_ARGS], | ||
638 | const int const_args[TCG_MAX_OP_ARGS]) | ||
639 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
640 | TCGOpcode exts; | ||
641 | |||
642 | switch (opc) { | ||
643 | - case INDEX_op_goto_tb: | ||
644 | - qemu_build_assert(!TCG_TARGET_HAS_direct_jump); | ||
645 | - /* indirect jump method. */ | ||
646 | - tcg_out_op_p(s, opc, (void *)get_jmp_target_addr(s, args[0])); | ||
647 | - set_jmp_reset_offset(s, args[0]); | ||
648 | - break; | ||
649 | - | ||
650 | case INDEX_op_goto_ptr: | ||
651 | tcg_out_op_r(s, opc, args[0]); | ||
652 | break; | ||
653 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
654 | case INDEX_op_mov_i64: | ||
655 | case INDEX_op_call: /* Always emitted via tcg_out_call. */ | ||
656 | case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ | ||
657 | + case INDEX_op_goto_tb: /* Always emitted via tcg_out_goto_tb. */ | ||
658 | default: | ||
659 | tcg_abort(); | ||
660 | } | ||
661 | -- | 150 | -- |
662 | 2.34.1 | 151 | 2.34.1 |
663 | |||
664 | diff view generated by jsdifflib |
1 | Install empty versions for !TCG_TARGET_HAS_direct_jump hosts. | 1 | Emit all constants that can be loaded in exactly one insn. |
---|---|---|---|
2 | 2 | ||
3 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
4 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> | 3 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> |
5 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 4 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
6 | --- | 5 | --- |
7 | tcg/arm/tcg-target.c.inc | 6 ++++++ | 6 | tcg/mips/tcg-target.c.inc | 26 ++++++++++++++++++++------ |
8 | tcg/mips/tcg-target.c.inc | 6 ++++++ | 7 | 1 file changed, 20 insertions(+), 6 deletions(-) |
9 | tcg/riscv/tcg-target.c.inc | 6 ++++++ | ||
10 | tcg/tci/tcg-target.c.inc | 6 ++++++ | ||
11 | 4 files changed, 24 insertions(+) | ||
12 | 8 | ||
13 | diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc | ||
14 | index XXXXXXX..XXXXXXX 100644 | ||
15 | --- a/tcg/arm/tcg-target.c.inc | ||
16 | +++ b/tcg/arm/tcg-target.c.inc | ||
17 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_goto_tb(TCGContext *s, int which) | ||
18 | set_jmp_reset_offset(s, which); | ||
19 | } | ||
20 | |||
21 | +void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | ||
22 | + uintptr_t jmp_rx, uintptr_t jmp_rw) | ||
23 | +{ | ||
24 | + /* Always indirect, nothing to do */ | ||
25 | +} | ||
26 | + | ||
27 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
28 | const TCGArg args[TCG_MAX_OP_ARGS], | ||
29 | const int const_args[TCG_MAX_OP_ARGS]) | ||
30 | diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc | 9 | diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc |
31 | index XXXXXXX..XXXXXXX 100644 | 10 | index XXXXXXX..XXXXXXX 100644 |
32 | --- a/tcg/mips/tcg-target.c.inc | 11 | --- a/tcg/mips/tcg-target.c.inc |
33 | +++ b/tcg/mips/tcg-target.c.inc | 12 | +++ b/tcg/mips/tcg-target.c.inc |
34 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_goto_tb(TCGContext *s, int which) | 13 | @@ -XXX,XX +XXX,XX @@ static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) |
35 | set_jmp_reset_offset(s, which); | 14 | return true; |
36 | } | 15 | } |
37 | 16 | ||
38 | +void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | 17 | +static bool tcg_out_movi_one(TCGContext *s, TCGReg ret, tcg_target_long arg) |
39 | + uintptr_t jmp_rx, uintptr_t jmp_rw) | ||
40 | +{ | 18 | +{ |
41 | + /* Always indirect, nothing to do */ | 19 | + if (arg == (int16_t)arg) { |
20 | + tcg_out_opc_imm(s, OPC_ADDIU, ret, TCG_REG_ZERO, arg); | ||
21 | + return true; | ||
22 | + } | ||
23 | + if (arg == (uint16_t)arg) { | ||
24 | + tcg_out_opc_imm(s, OPC_ORI, ret, TCG_REG_ZERO, arg); | ||
25 | + return true; | ||
26 | + } | ||
27 | + if (arg == (int32_t)arg && (arg & 0xffff) == 0) { | ||
28 | + tcg_out_opc_imm(s, OPC_LUI, ret, TCG_REG_ZERO, arg >> 16); | ||
29 | + return true; | ||
30 | + } | ||
31 | + return false; | ||
42 | +} | 32 | +} |
43 | + | 33 | + |
44 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 34 | static void tcg_out_movi(TCGContext *s, TCGType type, |
45 | const TCGArg args[TCG_MAX_OP_ARGS], | 35 | TCGReg ret, tcg_target_long arg) |
46 | const int const_args[TCG_MAX_OP_ARGS]) | 36 | { |
47 | diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc | 37 | if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) { |
48 | index XXXXXXX..XXXXXXX 100644 | 38 | arg = (int32_t)arg; |
49 | --- a/tcg/riscv/tcg-target.c.inc | 39 | } |
50 | +++ b/tcg/riscv/tcg-target.c.inc | 40 | - if (arg == (int16_t)arg) { |
51 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_goto_tb(TCGContext *s, int which) | 41 | - tcg_out_opc_imm(s, OPC_ADDIU, ret, TCG_REG_ZERO, arg); |
52 | set_jmp_reset_offset(s, which); | 42 | - return; |
53 | } | 43 | - } |
54 | 44 | - if (arg == (uint16_t)arg) { | |
55 | +void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | 45 | - tcg_out_opc_imm(s, OPC_ORI, ret, TCG_REG_ZERO, arg); |
56 | + uintptr_t jmp_rx, uintptr_t jmp_rw) | ||
57 | +{ | ||
58 | + /* Always indirect, nothing to do */ | ||
59 | +} | ||
60 | + | 46 | + |
61 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 47 | + if (tcg_out_movi_one(s, ret, arg)) { |
62 | const TCGArg args[TCG_MAX_OP_ARGS], | 48 | return; |
63 | const int const_args[TCG_MAX_OP_ARGS]) | 49 | } |
64 | diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc | ||
65 | index XXXXXXX..XXXXXXX 100644 | ||
66 | --- a/tcg/tci/tcg-target.c.inc | ||
67 | +++ b/tcg/tci/tcg-target.c.inc | ||
68 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_goto_tb(TCGContext *s, int which) | ||
69 | set_jmp_reset_offset(s, which); | ||
70 | } | ||
71 | |||
72 | +void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | ||
73 | + uintptr_t jmp_rx, uintptr_t jmp_rw) | ||
74 | +{ | ||
75 | + /* Always indirect, nothing to do */ | ||
76 | +} | ||
77 | + | 50 | + |
78 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 51 | if (TCG_TARGET_REG_BITS == 32 || arg == (int32_t)arg) { |
79 | const TCGArg args[TCG_MAX_OP_ARGS], | 52 | tcg_out_opc_imm(s, OPC_LUI, ret, TCG_REG_ZERO, arg >> 16); |
80 | const int const_args[TCG_MAX_OP_ARGS]) | 53 | } else { |
81 | -- | 54 | -- |
82 | 2.34.1 | 55 | 2.34.1 |
83 | 56 | ||
84 | 57 | diff view generated by jsdifflib |
1 | Similar to the existing set_jmp_reset_offset. Move any assert for | 1 | Emit all 32-bit signed constants, which can be loaded in two insns. |
---|---|---|---|
2 | TCG_TARGET_HAS_direct_jump into the new function (which now cannot | ||
3 | be build-time). Will be unused if TCG_TARGET_HAS_direct_jump is | ||
4 | constant 0, but we can't test for constant in the preprocessor, | ||
5 | so just mark it G_GNUC_UNUSED. | ||
6 | 2 | ||
7 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
8 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 3 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
9 | --- | 4 | --- |
10 | tcg/tcg.c | 10 ++++++++++ | 5 | tcg/mips/tcg-target.c.inc | 35 ++++++++++++++++++++++++----------- |
11 | tcg/aarch64/tcg-target.c.inc | 3 +-- | 6 | 1 file changed, 24 insertions(+), 11 deletions(-) |
12 | tcg/i386/tcg-target.c.inc | 3 +-- | ||
13 | tcg/loongarch64/tcg-target.c.inc | 3 +-- | ||
14 | tcg/ppc/tcg-target.c.inc | 7 +++---- | ||
15 | tcg/s390x/tcg-target.c.inc | 2 +- | ||
16 | tcg/sparc64/tcg-target.c.inc | 5 ++--- | ||
17 | 7 files changed, 19 insertions(+), 14 deletions(-) | ||
18 | 7 | ||
19 | diff --git a/tcg/tcg.c b/tcg/tcg.c | 8 | diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc |
20 | index XXXXXXX..XXXXXXX 100644 | 9 | index XXXXXXX..XXXXXXX 100644 |
21 | --- a/tcg/tcg.c | 10 | --- a/tcg/mips/tcg-target.c.inc |
22 | +++ b/tcg/tcg.c | 11 | +++ b/tcg/mips/tcg-target.c.inc |
23 | @@ -XXX,XX +XXX,XX @@ static void set_jmp_reset_offset(TCGContext *s, int which) | 12 | @@ -XXX,XX +XXX,XX @@ static bool tcg_out_movi_one(TCGContext *s, TCGReg ret, tcg_target_long arg) |
24 | s->tb_jmp_reset_offset[which] = tcg_current_code_size(s); | 13 | return false; |
25 | } | 14 | } |
26 | 15 | ||
27 | +static void G_GNUC_UNUSED set_jmp_insn_offset(TCGContext *s, int which) | 16 | +static bool tcg_out_movi_two(TCGContext *s, TCGReg ret, tcg_target_long arg) |
28 | +{ | 17 | +{ |
29 | + /* | 18 | + /* |
30 | + * We will check for overflow at the end of the opcode loop in | 19 | + * All signed 32-bit constants are loadable with two immediates, |
31 | + * tcg_gen_code, where we bound tcg_current_code_size to UINT16_MAX. | 20 | + * and everything else requires more work. |
32 | + */ | 21 | + */ |
33 | + tcg_debug_assert(TCG_TARGET_HAS_direct_jump); | 22 | + if (arg == (int32_t)arg) { |
34 | + s->tb_jmp_insn_offset[which] = tcg_current_code_size(s); | 23 | + if (!tcg_out_movi_one(s, ret, arg)) { |
24 | + tcg_out_opc_imm(s, OPC_LUI, ret, TCG_REG_ZERO, arg >> 16); | ||
25 | + tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg & 0xffff); | ||
26 | + } | ||
27 | + return true; | ||
28 | + } | ||
29 | + return false; | ||
35 | +} | 30 | +} |
36 | + | 31 | + |
37 | /* Signal overflow, starting over with fewer guest insns. */ | 32 | static void tcg_out_movi(TCGContext *s, TCGType type, |
38 | static G_NORETURN | 33 | TCGReg ret, tcg_target_long arg) |
39 | void tcg_raise_tb_overflow(TCGContext *s) | 34 | { |
40 | diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc | 35 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_movi(TCGContext *s, TCGType type, |
41 | index XXXXXXX..XXXXXXX 100644 | 36 | arg = (int32_t)arg; |
42 | --- a/tcg/aarch64/tcg-target.c.inc | 37 | } |
43 | +++ b/tcg/aarch64/tcg-target.c.inc | 38 | |
44 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 39 | - if (tcg_out_movi_one(s, ret, arg)) { |
45 | 40 | + /* Load all 32-bit constants. */ | |
46 | switch (opc) { | 41 | + if (tcg_out_movi_two(s, ret, arg)) { |
47 | case INDEX_op_goto_tb: | 42 | return; |
48 | - qemu_build_assert(TCG_TARGET_HAS_direct_jump); | 43 | } |
49 | /* | 44 | |
50 | * Ensure that ADRP+ADD are 8-byte aligned so that an atomic | 45 | - if (TCG_TARGET_REG_BITS == 32 || arg == (int32_t)arg) { |
51 | * write can be used to patch the target address. | 46 | - tcg_out_opc_imm(s, OPC_LUI, ret, TCG_REG_ZERO, arg >> 16); |
52 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 47 | + tcg_out_movi(s, TCG_TYPE_I32, ret, arg >> 31 >> 1); |
53 | if ((uintptr_t)s->code_ptr & 7) { | 48 | + if (arg & 0xffff0000ull) { |
54 | tcg_out32(s, NOP); | 49 | + tcg_out_dsll(s, ret, ret, 16); |
55 | } | 50 | + tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg >> 16); |
56 | - s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s); | 51 | + tcg_out_dsll(s, ret, ret, 16); |
57 | + set_jmp_insn_offset(s, a0); | 52 | } else { |
58 | /* | 53 | - tcg_out_movi(s, TCG_TYPE_I32, ret, arg >> 31 >> 1); |
59 | * actual branch destination will be patched by | 54 | - if (arg & 0xffff0000ull) { |
60 | * tb_target_set_jmp_target later | 55 | - tcg_out_dsll(s, ret, ret, 16); |
61 | diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc | 56 | - tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg >> 16); |
62 | index XXXXXXX..XXXXXXX 100644 | 57 | - tcg_out_dsll(s, ret, ret, 16); |
63 | --- a/tcg/i386/tcg-target.c.inc | 58 | - } else { |
64 | +++ b/tcg/i386/tcg-target.c.inc | 59 | - tcg_out_dsll(s, ret, ret, 32); |
65 | @@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, | 60 | - } |
66 | 61 | + tcg_out_dsll(s, ret, ret, 32); | |
67 | switch (opc) { | 62 | } |
68 | case INDEX_op_goto_tb: | 63 | if (arg & 0xffff) { |
69 | - qemu_build_assert(TCG_TARGET_HAS_direct_jump); | 64 | tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg & 0xffff); |
70 | { | ||
71 | /* | ||
72 | * Jump displacement must be aligned for atomic patching; | ||
73 | @@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
74 | tcg_out_nopn(s, gap - 1); | ||
75 | } | ||
76 | tcg_out8(s, OPC_JMP_long); /* jmp im */ | ||
77 | - s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s); | ||
78 | + set_jmp_insn_offset(s, a0); | ||
79 | tcg_out32(s, 0); | ||
80 | } | ||
81 | set_jmp_reset_offset(s, a0); | ||
82 | diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc | ||
83 | index XXXXXXX..XXXXXXX 100644 | ||
84 | --- a/tcg/loongarch64/tcg-target.c.inc | ||
85 | +++ b/tcg/loongarch64/tcg-target.c.inc | ||
86 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
87 | |||
88 | switch (opc) { | ||
89 | case INDEX_op_goto_tb: | ||
90 | - qemu_build_assert(TCG_TARGET_HAS_direct_jump); | ||
91 | /* | ||
92 | * Ensure that patch area is 8-byte aligned so that an | ||
93 | * atomic write can be used to patch the target address. | ||
94 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
95 | if ((uintptr_t)s->code_ptr & 7) { | ||
96 | tcg_out_nop(s); | ||
97 | } | ||
98 | - s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s); | ||
99 | + set_jmp_insn_offset(s, a0); | ||
100 | /* | ||
101 | * actual branch destination will be patched by | ||
102 | * tb_target_set_jmp_target later | ||
103 | diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc | ||
104 | index XXXXXXX..XXXXXXX 100644 | ||
105 | --- a/tcg/ppc/tcg-target.c.inc | ||
106 | +++ b/tcg/ppc/tcg-target.c.inc | ||
107 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
108 | |||
109 | switch (opc) { | ||
110 | case INDEX_op_goto_tb: | ||
111 | - qemu_build_assert(TCG_TARGET_HAS_direct_jump); | ||
112 | /* Direct jump. */ | ||
113 | if (TCG_TARGET_REG_BITS == 64) { | ||
114 | /* Ensure the next insns are 8 or 16-byte aligned. */ | ||
115 | while ((uintptr_t)s->code_ptr & (have_isa_2_07 ? 15 : 7)) { | ||
116 | tcg_out32(s, NOP); | ||
117 | } | ||
118 | - s->tb_jmp_insn_offset[args[0]] = tcg_current_code_size(s); | ||
119 | + set_jmp_insn_offset(s, args[0]); | ||
120 | tcg_out32(s, ADDIS | TAI(TCG_REG_TB, TCG_REG_TB, 0)); | ||
121 | tcg_out32(s, ADDI | TAI(TCG_REG_TB, TCG_REG_TB, 0)); | ||
122 | } else { | ||
123 | - s->tb_jmp_insn_offset[args[0]] = tcg_current_code_size(s); | ||
124 | + set_jmp_insn_offset(s, args[0]); | ||
125 | tcg_out32(s, B); | ||
126 | - s->tb_jmp_reset_offset[args[0]] = tcg_current_code_size(s); | ||
127 | + set_jmp_reset_offset(s, args[0]); | ||
128 | break; | ||
129 | } | ||
130 | tcg_out32(s, MTSPR | RS(TCG_REG_TB) | CTR); | ||
131 | diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc | ||
132 | index XXXXXXX..XXXXXXX 100644 | ||
133 | --- a/tcg/s390x/tcg-target.c.inc | ||
134 | +++ b/tcg/s390x/tcg-target.c.inc | ||
135 | @@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
136 | tcg_out16(s, NOP); | ||
137 | } | ||
138 | tcg_out16(s, RIL_BRCL | (S390_CC_ALWAYS << 4)); | ||
139 | - s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s); | ||
140 | + set_jmp_insn_offset(s, a0); | ||
141 | s->code_ptr += 2; | ||
142 | set_jmp_reset_offset(s, a0); | ||
143 | break; | ||
144 | diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc | ||
145 | index XXXXXXX..XXXXXXX 100644 | ||
146 | --- a/tcg/sparc64/tcg-target.c.inc | ||
147 | +++ b/tcg/sparc64/tcg-target.c.inc | ||
148 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
149 | |||
150 | switch (opc) { | ||
151 | case INDEX_op_goto_tb: | ||
152 | - qemu_build_assert(TCG_TARGET_HAS_direct_jump); | ||
153 | /* Direct jump. */ | ||
154 | if (USE_REG_TB) { | ||
155 | /* make sure the patch is 8-byte aligned. */ | ||
156 | if ((intptr_t)s->code_ptr & 4) { | ||
157 | tcg_out_nop(s); | ||
158 | } | ||
159 | - s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s); | ||
160 | + set_jmp_insn_offset(s, a0); | ||
161 | tcg_out_sethi(s, TCG_REG_T1, 0); | ||
162 | tcg_out_arithi(s, TCG_REG_T1, TCG_REG_T1, 0, ARITH_OR); | ||
163 | tcg_out_arith(s, TCG_REG_G0, TCG_REG_TB, TCG_REG_T1, JMPL); | ||
164 | tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD); | ||
165 | } else { | ||
166 | - s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s); | ||
167 | + set_jmp_insn_offset(s, a0); | ||
168 | tcg_out32(s, CALL); | ||
169 | tcg_out_nop(s); | ||
170 | } | ||
171 | -- | 65 | -- |
172 | 2.34.1 | 66 | 2.34.1 |
173 | |||
174 | diff view generated by jsdifflib |
1 | Replace 'tc_ptr' and 'addr' with 'tb' and 'n'. | 1 | During normal processing, the constant pool is accessible via |
---|---|---|---|
2 | TCG_REG_TB. During the prologue, it is accessible via TCG_REG_T9. | ||
2 | 3 | ||
3 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
4 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 4 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
5 | --- | 5 | --- |
6 | tcg/aarch64/tcg-target.h | 3 ++- | 6 | tcg/mips/tcg-target.h | 1 + |
7 | tcg/arm/tcg-target.h | 3 ++- | 7 | tcg/mips/tcg-target.c.inc | 65 +++++++++++++++++++++++++++++---------- |
8 | tcg/i386/tcg-target.h | 9 ++------- | 8 | 2 files changed, 49 insertions(+), 17 deletions(-) |
9 | tcg/loongarch64/tcg-target.h | 3 ++- | ||
10 | tcg/mips/tcg-target.h | 3 ++- | ||
11 | tcg/ppc/tcg-target.h | 3 ++- | ||
12 | tcg/riscv/tcg-target.h | 3 ++- | ||
13 | tcg/s390x/tcg-target.h | 10 ++-------- | ||
14 | tcg/sparc64/tcg-target.h | 3 ++- | ||
15 | tcg/tci/tcg-target.h | 3 ++- | ||
16 | accel/tcg/cpu-exec.c | 11 ++++++++--- | ||
17 | tcg/aarch64/tcg-target.c.inc | 5 +++-- | ||
18 | tcg/i386/tcg-target.c.inc | 9 +++++++++ | ||
19 | tcg/loongarch64/tcg-target.c.inc | 5 +++-- | ||
20 | tcg/ppc/tcg-target.c.inc | 7 ++++--- | ||
21 | tcg/s390x/tcg-target.c.inc | 10 ++++++++++ | ||
22 | tcg/sparc64/tcg-target.c.inc | 7 ++++--- | ||
23 | 17 files changed, 61 insertions(+), 36 deletions(-) | ||
24 | 9 | ||
25 | diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h | ||
26 | index XXXXXXX..XXXXXXX 100644 | ||
27 | --- a/tcg/aarch64/tcg-target.h | ||
28 | +++ b/tcg/aarch64/tcg-target.h | ||
29 | @@ -XXX,XX +XXX,XX @@ typedef enum { | ||
30 | #define TCG_TARGET_DEFAULT_MO (0) | ||
31 | #define TCG_TARGET_HAS_MEMORY_BSWAP 0 | ||
32 | |||
33 | -void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t); | ||
34 | +void tb_target_set_jmp_target(const TranslationBlock *, int, | ||
35 | + uintptr_t, uintptr_t); | ||
36 | |||
37 | #define TCG_TARGET_NEED_LDST_LABELS | ||
38 | #define TCG_TARGET_NEED_POOL_LABELS | ||
39 | diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h | ||
40 | index XXXXXXX..XXXXXXX 100644 | ||
41 | --- a/tcg/arm/tcg-target.h | ||
42 | +++ b/tcg/arm/tcg-target.h | ||
43 | @@ -XXX,XX +XXX,XX @@ extern bool use_neon_instructions; | ||
44 | #define TCG_TARGET_HAS_MEMORY_BSWAP 0 | ||
45 | |||
46 | /* not defined -- call should be eliminated at compile time */ | ||
47 | -void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t); | ||
48 | +void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | ||
49 | + uintptr_t, uintptr_t); | ||
50 | |||
51 | #define TCG_TARGET_NEED_LDST_LABELS | ||
52 | #define TCG_TARGET_NEED_POOL_LABELS | ||
53 | diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h | ||
54 | index XXXXXXX..XXXXXXX 100644 | ||
55 | --- a/tcg/i386/tcg-target.h | ||
56 | +++ b/tcg/i386/tcg-target.h | ||
57 | @@ -XXX,XX +XXX,XX @@ extern bool have_movbe; | ||
58 | #define TCG_TARGET_extract_i64_valid(ofs, len) \ | ||
59 | (((ofs) == 8 && (len) == 8) || ((ofs) + (len)) == 32) | ||
60 | |||
61 | -static inline void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx, | ||
62 | - uintptr_t jmp_rw, uintptr_t addr) | ||
63 | -{ | ||
64 | - /* patch the branch destination */ | ||
65 | - qatomic_set((int32_t *)jmp_rw, addr - (jmp_rx + 4)); | ||
66 | - /* no need to flush icache explicitly */ | ||
67 | -} | ||
68 | +void tb_target_set_jmp_target(const TranslationBlock *, int, | ||
69 | + uintptr_t, uintptr_t); | ||
70 | |||
71 | /* This defines the natural memory order supported by this | ||
72 | * architecture before guarantees made by various barrier | ||
73 | diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h | ||
74 | index XXXXXXX..XXXXXXX 100644 | ||
75 | --- a/tcg/loongarch64/tcg-target.h | ||
76 | +++ b/tcg/loongarch64/tcg-target.h | ||
77 | @@ -XXX,XX +XXX,XX @@ typedef enum { | ||
78 | #define TCG_TARGET_HAS_muluh_i64 1 | ||
79 | #define TCG_TARGET_HAS_mulsh_i64 1 | ||
80 | |||
81 | -void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t); | ||
82 | +void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | ||
83 | + uintptr_t, uintptr_t); | ||
84 | |||
85 | #define TCG_TARGET_DEFAULT_MO (0) | ||
86 | |||
87 | diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h | 10 | diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h |
88 | index XXXXXXX..XXXXXXX 100644 | 11 | index XXXXXXX..XXXXXXX 100644 |
89 | --- a/tcg/mips/tcg-target.h | 12 | --- a/tcg/mips/tcg-target.h |
90 | +++ b/tcg/mips/tcg-target.h | 13 | +++ b/tcg/mips/tcg-target.h |
91 | @@ -XXX,XX +XXX,XX @@ extern bool use_mips32r2_instructions; | 14 | @@ -XXX,XX +XXX,XX @@ extern bool use_mips32r2_instructions; |
92 | #define TCG_TARGET_HAS_MEMORY_BSWAP 1 | 15 | |
93 | 16 | #define TCG_TARGET_DEFAULT_MO 0 | |
94 | /* not defined -- call should be eliminated at compile time */ | ||
95 | -void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t) | ||
96 | +void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | ||
97 | + uintptr_t, uintptr_t) | ||
98 | QEMU_ERROR("code path is reachable"); | ||
99 | |||
100 | #define TCG_TARGET_NEED_LDST_LABELS | 17 | #define TCG_TARGET_NEED_LDST_LABELS |
101 | diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h | 18 | +#define TCG_TARGET_NEED_POOL_LABELS |
19 | |||
20 | #endif | ||
21 | diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc | ||
102 | index XXXXXXX..XXXXXXX 100644 | 22 | index XXXXXXX..XXXXXXX 100644 |
103 | --- a/tcg/ppc/tcg-target.h | 23 | --- a/tcg/mips/tcg-target.c.inc |
104 | +++ b/tcg/ppc/tcg-target.h | 24 | +++ b/tcg/mips/tcg-target.c.inc |
105 | @@ -XXX,XX +XXX,XX @@ extern bool have_vsx; | 25 | @@ -XXX,XX +XXX,XX @@ |
106 | #define TCG_TARGET_HAS_bitsel_vec have_vsx | 26 | */ |
107 | #define TCG_TARGET_HAS_cmpsel_vec 0 | 27 | |
108 | 28 | #include "../tcg-ldst.c.inc" | |
109 | -void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t); | 29 | +#include "../tcg-pool.c.inc" |
110 | +void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | 30 | |
111 | + uintptr_t, uintptr_t); | 31 | #if HOST_BIG_ENDIAN |
112 | 32 | # define MIPS_BE 1 | |
113 | #define TCG_TARGET_DEFAULT_MO (0) | 33 | @@ -XXX,XX +XXX,XX @@ static bool reloc_pc16(tcg_insn_unit *src_rw, const tcg_insn_unit *target) |
114 | #define TCG_TARGET_HAS_MEMORY_BSWAP 1 | 34 | static bool patch_reloc(tcg_insn_unit *code_ptr, int type, |
115 | diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h | 35 | intptr_t value, intptr_t addend) |
116 | index XXXXXXX..XXXXXXX 100644 | ||
117 | --- a/tcg/riscv/tcg-target.h | ||
118 | +++ b/tcg/riscv/tcg-target.h | ||
119 | @@ -XXX,XX +XXX,XX @@ typedef enum { | ||
120 | #endif | ||
121 | |||
122 | /* not defined -- call should be eliminated at compile time */ | ||
123 | -void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t); | ||
124 | +void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | ||
125 | + uintptr_t, uintptr_t); | ||
126 | |||
127 | #define TCG_TARGET_DEFAULT_MO (0) | ||
128 | |||
129 | diff --git a/tcg/s390x/tcg-target.h b/tcg/s390x/tcg-target.h | ||
130 | index XXXXXXX..XXXXXXX 100644 | ||
131 | --- a/tcg/s390x/tcg-target.h | ||
132 | +++ b/tcg/s390x/tcg-target.h | ||
133 | @@ -XXX,XX +XXX,XX @@ extern uint64_t s390_facilities[3]; | ||
134 | |||
135 | #define TCG_TARGET_DEFAULT_MO (TCG_MO_ALL & ~TCG_MO_ST_LD) | ||
136 | |||
137 | -static inline void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx, | ||
138 | - uintptr_t jmp_rw, uintptr_t addr) | ||
139 | -{ | ||
140 | - /* patch the branch destination */ | ||
141 | - intptr_t disp = addr - (jmp_rx - 2); | ||
142 | - qatomic_set((int32_t *)jmp_rw, disp / 2); | ||
143 | - /* no need to flush icache explicitly */ | ||
144 | -} | ||
145 | +void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | ||
146 | + uintptr_t jmp_rx, uintptr_t jmp_rw); | ||
147 | |||
148 | #define TCG_TARGET_NEED_LDST_LABELS | ||
149 | #define TCG_TARGET_NEED_POOL_LABELS | ||
150 | diff --git a/tcg/sparc64/tcg-target.h b/tcg/sparc64/tcg-target.h | ||
151 | index XXXXXXX..XXXXXXX 100644 | ||
152 | --- a/tcg/sparc64/tcg-target.h | ||
153 | +++ b/tcg/sparc64/tcg-target.h | ||
154 | @@ -XXX,XX +XXX,XX @@ extern bool use_vis3_instructions; | ||
155 | #define TCG_TARGET_DEFAULT_MO (0) | ||
156 | #define TCG_TARGET_HAS_MEMORY_BSWAP 1 | ||
157 | |||
158 | -void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t); | ||
159 | +void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | ||
160 | + uintptr_t, uintptr_t); | ||
161 | |||
162 | #define TCG_TARGET_NEED_POOL_LABELS | ||
163 | |||
164 | diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h | ||
165 | index XXXXXXX..XXXXXXX 100644 | ||
166 | --- a/tcg/tci/tcg-target.h | ||
167 | +++ b/tcg/tci/tcg-target.h | ||
168 | @@ -XXX,XX +XXX,XX @@ typedef enum { | ||
169 | #define TCG_TARGET_HAS_MEMORY_BSWAP 1 | ||
170 | |||
171 | /* not defined -- call should be eliminated at compile time */ | ||
172 | -void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t); | ||
173 | +void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | ||
174 | + uintptr_t, uintptr_t); | ||
175 | |||
176 | #endif /* TCG_TARGET_H */ | ||
177 | diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c | ||
178 | index XXXXXXX..XXXXXXX 100644 | ||
179 | --- a/accel/tcg/cpu-exec.c | ||
180 | +++ b/accel/tcg/cpu-exec.c | ||
181 | @@ -XXX,XX +XXX,XX @@ void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr) | ||
182 | { | 36 | { |
183 | tb->jmp_target_addr[n] = addr; | 37 | - tcg_debug_assert(type == R_MIPS_PC16); |
184 | if (TCG_TARGET_HAS_direct_jump) { | 38 | - tcg_debug_assert(addend == 0); |
185 | + /* | 39 | - return reloc_pc16(code_ptr, (const tcg_insn_unit *)value); |
186 | + * Get the rx view of the structure, from which we find the | 40 | + value += addend; |
187 | + * executable code address, and tb_target_set_jmp_target can | 41 | + switch (type) { |
188 | + * produce a pc-relative displacement to jmp_target_addr[n]. | 42 | + case R_MIPS_PC16: |
189 | + */ | 43 | + return reloc_pc16(code_ptr, (const tcg_insn_unit *)value); |
190 | + const TranslationBlock *c_tb = tcg_splitwx_to_rx(tb); | 44 | + case R_MIPS_16: |
191 | uintptr_t offset = tb->jmp_insn_offset[n]; | 45 | + if (value != (int16_t)value) { |
192 | - uintptr_t tc_ptr = (uintptr_t)tb->tc.ptr; | 46 | + return false; |
193 | - uintptr_t jmp_rx = tc_ptr + offset; | 47 | + } |
194 | + uintptr_t jmp_rx = (uintptr_t)tb->tc.ptr + offset; | 48 | + *code_ptr = deposit32(*code_ptr, 0, 16, value); |
195 | uintptr_t jmp_rw = jmp_rx - tcg_splitwx_diff; | 49 | + return true; |
196 | - tb_target_set_jmp_target(tc_ptr, jmp_rx, jmp_rw, addr); | 50 | + } |
197 | + tb_target_set_jmp_target(c_tb, n, jmp_rx, jmp_rw); | 51 | + g_assert_not_reached(); |
198 | } | ||
199 | } | 52 | } |
200 | 53 | ||
201 | diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc | 54 | #define TCG_CT_CONST_ZERO 0x100 |
202 | index XXXXXXX..XXXXXXX 100644 | 55 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_nop(TCGContext *s) |
203 | --- a/tcg/aarch64/tcg-target.c.inc | 56 | tcg_out32(s, 0); |
204 | +++ b/tcg/aarch64/tcg-target.c.inc | ||
205 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_call(TCGContext *s, const tcg_insn_unit *target, | ||
206 | tcg_out_call_int(s, target); | ||
207 | } | 57 | } |
208 | 58 | ||
209 | -void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx, | 59 | +static void tcg_out_nop_fill(tcg_insn_unit *p, int count) |
210 | - uintptr_t jmp_rw, uintptr_t addr) | ||
211 | +void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | ||
212 | + uintptr_t jmp_rx, uintptr_t jmp_rw) | ||
213 | { | ||
214 | + uintptr_t addr = tb->jmp_target_addr[n]; | ||
215 | tcg_insn_unit i1, i2; | ||
216 | TCGType rt = TCG_TYPE_I64; | ||
217 | TCGReg rd = TCG_REG_TMP; | ||
218 | diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc | ||
219 | index XXXXXXX..XXXXXXX 100644 | ||
220 | --- a/tcg/i386/tcg-target.c.inc | ||
221 | +++ b/tcg/i386/tcg-target.c.inc | ||
222 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_goto_tb(TCGContext *s, int which) | ||
223 | set_jmp_reset_offset(s, which); | ||
224 | } | ||
225 | |||
226 | +void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | ||
227 | + uintptr_t jmp_rx, uintptr_t jmp_rw) | ||
228 | +{ | 60 | +{ |
229 | + /* patch the branch destination */ | 61 | + memset(p, 0, count * sizeof(tcg_insn_unit)); |
230 | + uintptr_t addr = tb->jmp_target_addr[n]; | ||
231 | + qatomic_set((int32_t *)jmp_rw, addr - (jmp_rx + 4)); | ||
232 | + /* no need to flush icache explicitly */ | ||
233 | +} | 62 | +} |
234 | + | 63 | + |
235 | static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, | 64 | static void tcg_out_dsll(TCGContext *s, TCGReg rd, TCGReg rt, TCGArg sa) |
236 | const TCGArg args[TCG_MAX_OP_ARGS], | 65 | { |
237 | const int const_args[TCG_MAX_OP_ARGS]) | 66 | tcg_out_opc_sa64(s, OPC_DSLL, OPC_DSLL32, rd, rt, sa); |
238 | diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc | 67 | @@ -XXX,XX +XXX,XX @@ static bool tcg_out_movi_two(TCGContext *s, TCGReg ret, tcg_target_long arg) |
239 | index XXXXXXX..XXXXXXX 100644 | 68 | return false; |
240 | --- a/tcg/loongarch64/tcg-target.c.inc | ||
241 | +++ b/tcg/loongarch64/tcg-target.c.inc | ||
242 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_nop(TCGContext *s) | ||
243 | tcg_out32(s, NOP); | ||
244 | } | 69 | } |
245 | 70 | ||
246 | -void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx, | 71 | -static void tcg_out_movi(TCGContext *s, TCGType type, |
247 | - uintptr_t jmp_rw, uintptr_t addr) | 72 | - TCGReg ret, tcg_target_long arg) |
248 | +void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | 73 | +static void tcg_out_movi_pool(TCGContext *s, TCGReg ret, |
249 | + uintptr_t jmp_rx, uintptr_t jmp_rw) | 74 | + tcg_target_long arg, TCGReg tbreg) |
250 | { | ||
251 | tcg_insn_unit i1, i2; | ||
252 | ptrdiff_t upper, lower; | ||
253 | + uintptr_t addr = tb->jmp_target_addr[n]; | ||
254 | ptrdiff_t offset = (ptrdiff_t)(addr - jmp_rx) >> 2; | ||
255 | |||
256 | if (offset == sextreg(offset, 0, 26)) { | ||
257 | diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc | ||
258 | index XXXXXXX..XXXXXXX 100644 | ||
259 | --- a/tcg/ppc/tcg-target.c.inc | ||
260 | +++ b/tcg/ppc/tcg-target.c.inc | ||
261 | @@ -XXX,XX +XXX,XX @@ static inline void ppc64_replace4(uintptr_t rx, uintptr_t rw, | ||
262 | flush_idcache_range(rx, rw, 16); | ||
263 | } | ||
264 | |||
265 | -void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx, | ||
266 | - uintptr_t jmp_rw, uintptr_t addr) | ||
267 | +void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | ||
268 | + uintptr_t jmp_rx, uintptr_t jmp_rw) | ||
269 | { | ||
270 | tcg_insn_unit i0, i1, i2, i3; | ||
271 | - intptr_t tb_diff = addr - tc_ptr; | ||
272 | + uintptr_t addr = tb->jmp_target_addr[n]; | ||
273 | + intptr_t tb_diff = addr - (uintptr_t)tb->tc.ptr; | ||
274 | intptr_t br_diff = addr - (jmp_rx + 4); | ||
275 | intptr_t lo, hi; | ||
276 | |||
277 | diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc | ||
278 | index XXXXXXX..XXXXXXX 100644 | ||
279 | --- a/tcg/s390x/tcg-target.c.inc | ||
280 | +++ b/tcg/s390x/tcg-target.c.inc | ||
281 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_goto_tb(TCGContext *s, int which) | ||
282 | set_jmp_reset_offset(s, which); | ||
283 | } | ||
284 | |||
285 | +void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | ||
286 | + uintptr_t jmp_rx, uintptr_t jmp_rw) | ||
287 | +{ | 75 | +{ |
288 | + /* patch the branch destination */ | 76 | + new_pool_label(s, arg, R_MIPS_16, s->code_ptr, tcg_tbrel_diff(s, NULL)); |
289 | + uintptr_t addr = tb->jmp_target_addr[n]; | 77 | + tcg_out_opc_imm(s, OPC_LD, ret, tbreg, 0); |
290 | + intptr_t disp = addr - (jmp_rx - 2); | ||
291 | + qatomic_set((int32_t *)jmp_rw, disp / 2); | ||
292 | + /* no need to flush icache explicitly */ | ||
293 | +} | 78 | +} |
294 | + | 79 | + |
295 | # define OP_32_64(x) \ | 80 | +static void tcg_out_movi_int(TCGContext *s, TCGType type, TCGReg ret, |
296 | case glue(glue(INDEX_op_,x),_i32): \ | 81 | + tcg_target_long arg, TCGReg tbreg) |
297 | case glue(glue(INDEX_op_,x),_i64) | 82 | { |
298 | diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc | 83 | if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) { |
299 | index XXXXXXX..XXXXXXX 100644 | 84 | arg = (int32_t)arg; |
300 | --- a/tcg/sparc64/tcg-target.c.inc | 85 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_movi(TCGContext *s, TCGType type, |
301 | +++ b/tcg/sparc64/tcg-target.c.inc | 86 | if (tcg_out_movi_two(s, ret, arg)) { |
302 | @@ -XXX,XX +XXX,XX @@ void tcg_register_jit(const void *buf, size_t buf_size) | 87 | return; |
303 | tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame)); | 88 | } |
89 | + assert(TCG_TARGET_REG_BITS == 64); | ||
90 | |||
91 | - tcg_out_movi(s, TCG_TYPE_I32, ret, arg >> 31 >> 1); | ||
92 | - if (arg & 0xffff0000ull) { | ||
93 | - tcg_out_dsll(s, ret, ret, 16); | ||
94 | - tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg >> 16); | ||
95 | - tcg_out_dsll(s, ret, ret, 16); | ||
96 | - } else { | ||
97 | - tcg_out_dsll(s, ret, ret, 32); | ||
98 | - } | ||
99 | - if (arg & 0xffff) { | ||
100 | - tcg_out_opc_imm(s, OPC_ORI, ret, ret, arg & 0xffff); | ||
101 | - } | ||
102 | + /* Otherwise, put 64-bit constants into the constant pool. */ | ||
103 | + tcg_out_movi_pool(s, ret, arg, tbreg); | ||
104 | +} | ||
105 | + | ||
106 | +static void tcg_out_movi(TCGContext *s, TCGType type, | ||
107 | + TCGReg ret, tcg_target_long arg) | ||
108 | +{ | ||
109 | + TCGReg tbreg = TCG_TARGET_REG_BITS == 64 ? TCG_REG_TB : 0; | ||
110 | + tcg_out_movi_int(s, type, ret, arg, tbreg); | ||
304 | } | 111 | } |
305 | 112 | ||
306 | -void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx, | 113 | static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rs) |
307 | - uintptr_t jmp_rw, uintptr_t addr) | 114 | @@ -XXX,XX +XXX,XX @@ static void tcg_target_qemu_prologue(TCGContext *s) |
308 | +void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | 115 | |
309 | + uintptr_t jmp_rx, uintptr_t jmp_rw) | 116 | #ifndef CONFIG_SOFTMMU |
310 | { | 117 | if (guest_base != (int16_t)guest_base) { |
311 | - intptr_t tb_disp = addr - tc_ptr; | 118 | - tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base); |
312 | + uintptr_t addr = tb->jmp_target_addr[n]; | 119 | + /* |
313 | + intptr_t tb_disp = addr - (uintptr_t)tb->tc.ptr; | 120 | + * The function call abi for n32 and n64 will have loaded $25 (t9) |
314 | intptr_t br_disp = addr - jmp_rx; | 121 | + * with the address of the prologue, so we can use that instead |
315 | tcg_insn_unit i1, i2; | 122 | + * of TCG_REG_TB. |
316 | 123 | + */ | |
124 | +#if TCG_TARGET_REG_BITS == 64 && !defined(__mips_abicalls) | ||
125 | +# error "Unknown mips abi" | ||
126 | +#endif | ||
127 | + tcg_out_movi_int(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base, | ||
128 | + TCG_TARGET_REG_BITS == 64 ? TCG_REG_T9 : 0); | ||
129 | tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG); | ||
130 | } | ||
131 | #endif | ||
132 | + | ||
133 | if (TCG_TARGET_REG_BITS == 64) { | ||
134 | tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_TB, tcg_target_call_iarg_regs[1]); | ||
135 | } | ||
317 | -- | 136 | -- |
318 | 2.34.1 | 137 | 2.34.1 |
319 | |||
320 | diff view generated by jsdifflib |
1 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | 1 | Repeated calls to a single helper are common -- especially |
---|---|---|---|
2 | the ones for softmmu memory access. Prefer the constant pool | ||
3 | to longer sequences to increase sharing. | ||
4 | |||
2 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 5 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
3 | --- | 6 | --- |
4 | tcg/ppc/tcg-target.c.inc | 32 +++++++++++++------------------- | 7 | tcg/mips/tcg-target.c.inc | 16 +++++++++++++--- |
5 | 1 file changed, 13 insertions(+), 19 deletions(-) | 8 | 1 file changed, 13 insertions(+), 3 deletions(-) |
6 | 9 | ||
7 | diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc | 10 | diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc |
8 | index XXXXXXX..XXXXXXX 100644 | 11 | index XXXXXXX..XXXXXXX 100644 |
9 | --- a/tcg/ppc/tcg-target.c.inc | 12 | --- a/tcg/mips/tcg-target.c.inc |
10 | +++ b/tcg/ppc/tcg-target.c.inc | 13 | +++ b/tcg/mips/tcg-target.c.inc |
11 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 14 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret, |
12 | 15 | ||
13 | switch (opc) { | 16 | static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail) |
14 | case INDEX_op_goto_tb: | 17 | { |
15 | - if (s->tb_jmp_insn_offset) { | 18 | - /* Note that the ABI requires the called function's address to be |
16 | - /* Direct jump. */ | 19 | - loaded into T9, even if a direct branch is in range. */ |
17 | - if (TCG_TARGET_REG_BITS == 64) { | 20 | - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T9, (uintptr_t)arg); |
18 | - /* Ensure the next insns are 8 or 16-byte aligned. */ | 21 | + /* |
19 | - while ((uintptr_t)s->code_ptr & (have_isa_2_07 ? 15 : 7)) { | 22 | + * Note that __mips_abicalls requires the called function's address |
20 | - tcg_out32(s, NOP); | 23 | + * to be loaded into $25 (t9), even if a direct branch is in range. |
21 | - } | 24 | + * |
22 | - s->tb_jmp_insn_offset[args[0]] = tcg_current_code_size(s); | 25 | + * For n64, always drop the pointer into the constant pool. |
23 | - tcg_out32(s, ADDIS | TAI(TCG_REG_TB, TCG_REG_TB, 0)); | 26 | + * We can re-use helper addresses often and do not want any |
24 | - tcg_out32(s, ADDI | TAI(TCG_REG_TB, TCG_REG_TB, 0)); | 27 | + * of the longer sequences tcg_out_movi may try. |
25 | - } else { | 28 | + */ |
26 | - s->tb_jmp_insn_offset[args[0]] = tcg_current_code_size(s); | 29 | + if (sizeof(uintptr_t) == 8) { |
27 | - tcg_out32(s, B); | 30 | + tcg_out_movi_pool(s, TCG_REG_T9, (uintptr_t)arg, TCG_REG_TB); |
28 | - s->tb_jmp_reset_offset[args[0]] = tcg_current_code_size(s); | 31 | + } else { |
29 | - break; | 32 | + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T9, (uintptr_t)arg); |
30 | + qemu_build_assert(TCG_TARGET_HAS_direct_jump); | 33 | + } |
31 | + /* Direct jump. */ | 34 | |
32 | + if (TCG_TARGET_REG_BITS == 64) { | 35 | /* But do try a direct branch, allowing the cpu better insn prefetch. */ |
33 | + /* Ensure the next insns are 8 or 16-byte aligned. */ | 36 | if (tail) { |
34 | + while ((uintptr_t)s->code_ptr & (have_isa_2_07 ? 15 : 7)) { | ||
35 | + tcg_out32(s, NOP); | ||
36 | } | ||
37 | + s->tb_jmp_insn_offset[args[0]] = tcg_current_code_size(s); | ||
38 | + tcg_out32(s, ADDIS | TAI(TCG_REG_TB, TCG_REG_TB, 0)); | ||
39 | + tcg_out32(s, ADDI | TAI(TCG_REG_TB, TCG_REG_TB, 0)); | ||
40 | } else { | ||
41 | - /* Indirect jump. */ | ||
42 | - tcg_debug_assert(s->tb_jmp_insn_offset == NULL); | ||
43 | - tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TB, 0, | ||
44 | - (intptr_t)(s->tb_jmp_insn_offset + args[0])); | ||
45 | + s->tb_jmp_insn_offset[args[0]] = tcg_current_code_size(s); | ||
46 | + tcg_out32(s, B); | ||
47 | + s->tb_jmp_reset_offset[args[0]] = tcg_current_code_size(s); | ||
48 | + break; | ||
49 | } | ||
50 | tcg_out32(s, MTSPR | RS(TCG_REG_TB) | CTR); | ||
51 | tcg_out32(s, BCCTR | BO_ALWAYS); | ||
52 | -- | 37 | -- |
53 | 2.34.1 | 38 | 2.34.1 |
54 | |||
55 | diff view generated by jsdifflib |
1 | The old sparc64 implementation may replace two insns, which leaves | 1 | These addresses are often loaded by the qemu_ld/st slow path, |
---|---|---|---|
2 | a race condition in which a thread could be stopped at a PC in the | 2 | for loading the retaddr value. |
3 | middle of the sequence, and when restarted does not see the complete | ||
4 | address computation and branches to nowhere. | ||
5 | 3 | ||
6 | The new implemetation replaces only one insn, swapping between a | ||
7 | direct branch and a direct call. The TCG_REG_TB register is loaded | ||
8 | from tb->jmp_target_addr[] in the delay slot. | ||
9 | |||
10 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
11 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 4 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
12 | --- | 5 | --- |
13 | tcg/sparc64/tcg-target.c.inc | 87 +++++++++++++++--------------------- | 6 | tcg/mips/tcg-target.c.inc | 13 +++++++++++++ |
14 | 1 file changed, 37 insertions(+), 50 deletions(-) | 7 | 1 file changed, 13 insertions(+) |
15 | 8 | ||
16 | diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc | 9 | diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc |
17 | index XXXXXXX..XXXXXXX 100644 | 10 | index XXXXXXX..XXXXXXX 100644 |
18 | --- a/tcg/sparc64/tcg-target.c.inc | 11 | --- a/tcg/mips/tcg-target.c.inc |
19 | +++ b/tcg/sparc64/tcg-target.c.inc | 12 | +++ b/tcg/mips/tcg-target.c.inc |
20 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) | 13 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_movi_pool(TCGContext *s, TCGReg ret, |
21 | 14 | static void tcg_out_movi_int(TCGContext *s, TCGType type, TCGReg ret, | |
22 | static void tcg_out_goto_tb(TCGContext *s, int which) | 15 | tcg_target_long arg, TCGReg tbreg) |
23 | { | 16 | { |
24 | - int c; | 17 | + tcg_target_long tmp; |
25 | + ptrdiff_t off = tcg_tbrel_diff(s, (void *)get_jmp_target_addr(s, which)); | 18 | + |
26 | 19 | if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) { | |
27 | - /* Direct jump. */ | 20 | arg = (int32_t)arg; |
28 | - /* make sure the patch is 8-byte aligned. */ | ||
29 | - if ((intptr_t)s->code_ptr & 4) { | ||
30 | - tcg_out_nop(s); | ||
31 | - } | ||
32 | + /* Direct branch will be patched by tb_target_set_jmp_target. */ | ||
33 | set_jmp_insn_offset(s, which); | ||
34 | - tcg_out_sethi(s, TCG_REG_T1, 0); | ||
35 | - tcg_out_arithi(s, TCG_REG_T1, TCG_REG_T1, 0, ARITH_OR); | ||
36 | - tcg_out_arith(s, TCG_REG_G0, TCG_REG_TB, TCG_REG_T1, JMPL); | ||
37 | - tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD); | ||
38 | + tcg_out32(s, CALL); | ||
39 | + /* delay slot */ | ||
40 | + tcg_debug_assert(check_fit_ptr(off, 13)); | ||
41 | + tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TB, TCG_REG_TB, off); | ||
42 | set_jmp_reset_offset(s, which); | ||
43 | |||
44 | /* | ||
45 | * For the unlinked path of goto_tb, we need to reset TCG_REG_TB | ||
46 | * to the beginning of this TB. | ||
47 | */ | ||
48 | - c = -tcg_current_code_size(s); | ||
49 | - if (check_fit_i32(c, 13)) { | ||
50 | - tcg_out_arithi(s, TCG_REG_TB, TCG_REG_TB, c, ARITH_ADD); | ||
51 | + off = -tcg_current_code_size(s); | ||
52 | + if (check_fit_i32(off, 13)) { | ||
53 | + tcg_out_arithi(s, TCG_REG_TB, TCG_REG_TB, off, ARITH_ADD); | ||
54 | } else { | ||
55 | - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, c); | ||
56 | + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, off); | ||
57 | tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD); | ||
58 | } | 21 | } |
59 | } | 22 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_movi_int(TCGContext *s, TCGType type, TCGReg ret, |
60 | 23 | } | |
61 | +void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | 24 | assert(TCG_TARGET_REG_BITS == 64); |
62 | + uintptr_t jmp_rx, uintptr_t jmp_rw) | 25 | |
63 | +{ | 26 | + /* Load addresses within 2GB of TB with 1 or 3 insns. */ |
64 | + uintptr_t addr = tb->jmp_target_addr[n]; | 27 | + tmp = tcg_tbrel_diff(s, (void *)arg); |
65 | + intptr_t br_disp = (intptr_t)(addr - jmp_rx) >> 2; | 28 | + if (tmp == (int16_t)tmp) { |
66 | + tcg_insn_unit insn; | 29 | + tcg_out_opc_imm(s, OPC_DADDIU, ret, tbreg, tmp); |
67 | + | 30 | + return; |
68 | + br_disp >>= 2; | 31 | + } |
69 | + if (check_fit_ptr(br_disp, 19)) { | 32 | + if (tcg_out_movi_two(s, ret, tmp)) { |
70 | + /* ba,pt %icc, addr */ | 33 | + tcg_out_opc_reg(s, OPC_DADDU, ret, ret, tbreg); |
71 | + insn = deposit32(INSN_OP(0) | INSN_OP2(1) | INSN_COND(COND_A) | 34 | + return; |
72 | + | BPCC_ICC | BPCC_PT, 0, 19, br_disp); | ||
73 | + } else if (check_fit_ptr(br_disp, 22)) { | ||
74 | + /* ba addr */ | ||
75 | + insn = deposit32(INSN_OP(0) | INSN_OP2(2) | INSN_COND(COND_A), | ||
76 | + 0, 22, br_disp); | ||
77 | + } else { | ||
78 | + /* The code_gen_buffer can't be larger than 2GB. */ | ||
79 | + tcg_debug_assert(check_fit_ptr(br_disp, 30)); | ||
80 | + /* call addr */ | ||
81 | + insn = deposit32(CALL, 0, 30, br_disp); | ||
82 | + } | 35 | + } |
83 | + | 36 | + |
84 | + qatomic_set((uint32_t *)jmp_rw, insn); | 37 | /* Otherwise, put 64-bit constants into the constant pool. */ |
85 | + flush_idcache_range(jmp_rx, jmp_rw, 4); | 38 | tcg_out_movi_pool(s, ret, arg, tbreg); |
86 | +} | ||
87 | + | ||
88 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
89 | const TCGArg args[TCG_MAX_OP_ARGS], | ||
90 | const int const_args[TCG_MAX_OP_ARGS]) | ||
91 | @@ -XXX,XX +XXX,XX @@ void tcg_register_jit(const void *buf, size_t buf_size) | ||
92 | { | ||
93 | tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame)); | ||
94 | } | 39 | } |
95 | - | ||
96 | -void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | ||
97 | - uintptr_t jmp_rx, uintptr_t jmp_rw) | ||
98 | -{ | ||
99 | - uintptr_t addr = tb->jmp_target_addr[n]; | ||
100 | - intptr_t tb_disp = addr - (uintptr_t)tb->tc.ptr; | ||
101 | - intptr_t br_disp = addr - jmp_rx; | ||
102 | - tcg_insn_unit i1, i2; | ||
103 | - | ||
104 | - /* We can reach the entire address space for ILP32. | ||
105 | - For LP64, the code_gen_buffer can't be larger than 2GB. */ | ||
106 | - tcg_debug_assert(tb_disp == (int32_t)tb_disp); | ||
107 | - tcg_debug_assert(br_disp == (int32_t)br_disp); | ||
108 | - | ||
109 | - /* This does not exercise the range of the branch, but we do | ||
110 | - still need to be able to load the new value of TCG_REG_TB. | ||
111 | - But this does still happen quite often. */ | ||
112 | - if (check_fit_ptr(tb_disp, 13)) { | ||
113 | - /* ba,pt %icc, addr */ | ||
114 | - i1 = (INSN_OP(0) | INSN_OP2(1) | INSN_COND(COND_A) | ||
115 | - | BPCC_ICC | BPCC_PT | INSN_OFF19(br_disp)); | ||
116 | - i2 = (ARITH_ADD | INSN_RD(TCG_REG_TB) | INSN_RS1(TCG_REG_TB) | ||
117 | - | INSN_IMM13(tb_disp)); | ||
118 | - } else if (tb_disp >= 0) { | ||
119 | - i1 = SETHI | INSN_RD(TCG_REG_T1) | ((tb_disp & 0xfffffc00) >> 10); | ||
120 | - i2 = (ARITH_OR | INSN_RD(TCG_REG_T1) | INSN_RS1(TCG_REG_T1) | ||
121 | - | INSN_IMM13(tb_disp & 0x3ff)); | ||
122 | - } else { | ||
123 | - i1 = SETHI | INSN_RD(TCG_REG_T1) | ((~tb_disp & 0xfffffc00) >> 10); | ||
124 | - i2 = (ARITH_XOR | INSN_RD(TCG_REG_T1) | INSN_RS1(TCG_REG_T1) | ||
125 | - | INSN_IMM13((tb_disp & 0x3ff) | -0x400)); | ||
126 | - } | ||
127 | - | ||
128 | - qatomic_set((uint64_t *)jmp_rw, deposit64(i2, 32, 32, i1)); | ||
129 | - flush_idcache_range(jmp_rx, jmp_rw, 8); | ||
130 | -} | ||
131 | -- | 40 | -- |
132 | 2.34.1 | 41 | 2.34.1 |
133 | |||
134 | diff view generated by jsdifflib |
1 | The INDEX_op_exit_tb opcode needs no register allocation. | 1 | These sequences are inexpensive to test. Maxing out at three insns |
---|---|---|---|
2 | Split out a dedicated helper function for it. | 2 | results in the same space as a load plus the constant pool entry. |
3 | 3 | ||
4 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
5 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> | ||
6 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 4 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
7 | --- | 5 | --- |
8 | tcg/tcg.c | 4 ++++ | 6 | tcg/mips/tcg-target.c.inc | 44 +++++++++++++++++++++++++++++++++++++++ |
9 | tcg/aarch64/tcg-target.c.inc | 22 ++++++++++-------- | 7 | 1 file changed, 44 insertions(+) |
10 | tcg/arm/tcg-target.c.inc | 11 +++++---- | ||
11 | tcg/i386/tcg-target.c.inc | 21 +++++++++-------- | ||
12 | tcg/loongarch64/tcg-target.c.inc | 22 ++++++++++-------- | ||
13 | tcg/mips/tcg-target.c.inc | 33 +++++++++++++-------------- | ||
14 | tcg/ppc/tcg-target.c.inc | 11 +++++---- | ||
15 | tcg/riscv/tcg-target.c.inc | 22 ++++++++++-------- | ||
16 | tcg/s390x/tcg-target.c.inc | 23 ++++++++++--------- | ||
17 | tcg/sparc64/tcg-target.c.inc | 39 +++++++++++++++++--------------- | ||
18 | tcg/tci/tcg-target.c.inc | 10 ++++---- | ||
19 | 11 files changed, 121 insertions(+), 97 deletions(-) | ||
20 | 8 | ||
21 | diff --git a/tcg/tcg.c b/tcg/tcg.c | ||
22 | index XXXXXXX..XXXXXXX 100644 | ||
23 | --- a/tcg/tcg.c | ||
24 | +++ b/tcg/tcg.c | ||
25 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1, | ||
26 | static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg); | ||
27 | static void tcg_out_movi(TCGContext *s, TCGType type, | ||
28 | TCGReg ret, tcg_target_long arg); | ||
29 | +static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg); | ||
30 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
31 | const TCGArg args[TCG_MAX_OP_ARGS], | ||
32 | const int const_args[TCG_MAX_OP_ARGS]); | ||
33 | @@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, target_ulong pc_start) | ||
34 | case INDEX_op_call: | ||
35 | tcg_reg_alloc_call(s, op); | ||
36 | break; | ||
37 | + case INDEX_op_exit_tb: | ||
38 | + tcg_out_exit_tb(s, op->args[0]); | ||
39 | + break; | ||
40 | case INDEX_op_dup2_vec: | ||
41 | if (tcg_reg_alloc_dup2(s, op)) { | ||
42 | break; | ||
43 | diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc | ||
44 | index XXXXXXX..XXXXXXX 100644 | ||
45 | --- a/tcg/aarch64/tcg-target.c.inc | ||
46 | +++ b/tcg/aarch64/tcg-target.c.inc | ||
47 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, | ||
48 | |||
49 | static const tcg_insn_unit *tb_ret_addr; | ||
50 | |||
51 | +static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) | ||
52 | +{ | ||
53 | + /* Reuse the zeroing that exists for goto_ptr. */ | ||
54 | + if (a0 == 0) { | ||
55 | + tcg_out_goto_long(s, tcg_code_gen_epilogue); | ||
56 | + } else { | ||
57 | + tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_X0, a0); | ||
58 | + tcg_out_goto_long(s, tb_ret_addr); | ||
59 | + } | ||
60 | +} | ||
61 | + | ||
62 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
63 | const TCGArg args[TCG_MAX_OP_ARGS], | ||
64 | const int const_args[TCG_MAX_OP_ARGS]) | ||
65 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
66 | #define REG0(I) (const_args[I] ? TCG_REG_XZR : (TCGReg)args[I]) | ||
67 | |||
68 | switch (opc) { | ||
69 | - case INDEX_op_exit_tb: | ||
70 | - /* Reuse the zeroing that exists for goto_ptr. */ | ||
71 | - if (a0 == 0) { | ||
72 | - tcg_out_goto_long(s, tcg_code_gen_epilogue); | ||
73 | - } else { | ||
74 | - tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_X0, a0); | ||
75 | - tcg_out_goto_long(s, tb_ret_addr); | ||
76 | - } | ||
77 | - break; | ||
78 | - | ||
79 | case INDEX_op_goto_tb: | ||
80 | tcg_debug_assert(s->tb_jmp_insn_offset != NULL); | ||
81 | /* | ||
82 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
83 | case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ | ||
84 | case INDEX_op_mov_i64: | ||
85 | case INDEX_op_call: /* Always emitted via tcg_out_call. */ | ||
86 | + case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ | ||
87 | default: | ||
88 | g_assert_not_reached(); | ||
89 | } | ||
90 | diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc | ||
91 | index XXXXXXX..XXXXXXX 100644 | ||
92 | --- a/tcg/arm/tcg-target.c.inc | ||
93 | +++ b/tcg/arm/tcg-target.c.inc | ||
94 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64) | ||
95 | |||
96 | static void tcg_out_epilogue(TCGContext *s); | ||
97 | |||
98 | +static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg) | ||
99 | +{ | ||
100 | + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R0, arg); | ||
101 | + tcg_out_epilogue(s); | ||
102 | +} | ||
103 | + | ||
104 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
105 | const TCGArg args[TCG_MAX_OP_ARGS], | ||
106 | const int const_args[TCG_MAX_OP_ARGS]) | ||
107 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
108 | int c; | ||
109 | |||
110 | switch (opc) { | ||
111 | - case INDEX_op_exit_tb: | ||
112 | - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R0, args[0]); | ||
113 | - tcg_out_epilogue(s); | ||
114 | - break; | ||
115 | case INDEX_op_goto_tb: | ||
116 | { | ||
117 | /* Indirect jump method */ | ||
118 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
119 | |||
120 | case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ | ||
121 | case INDEX_op_call: /* Always emitted via tcg_out_call. */ | ||
122 | + case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ | ||
123 | default: | ||
124 | tcg_abort(); | ||
125 | } | ||
126 | diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc | ||
127 | index XXXXXXX..XXXXXXX 100644 | ||
128 | --- a/tcg/i386/tcg-target.c.inc | ||
129 | +++ b/tcg/i386/tcg-target.c.inc | ||
130 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is64) | ||
131 | #endif | ||
132 | } | ||
133 | |||
134 | +static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) | ||
135 | +{ | ||
136 | + /* Reuse the zeroing that exists for goto_ptr. */ | ||
137 | + if (a0 == 0) { | ||
138 | + tcg_out_jmp(s, tcg_code_gen_epilogue); | ||
139 | + } else { | ||
140 | + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_EAX, a0); | ||
141 | + tcg_out_jmp(s, tb_ret_addr); | ||
142 | + } | ||
143 | +} | ||
144 | + | ||
145 | static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
146 | const TCGArg args[TCG_MAX_OP_ARGS], | ||
147 | const int const_args[TCG_MAX_OP_ARGS]) | ||
148 | @@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
149 | const_a2 = const_args[2]; | ||
150 | |||
151 | switch (opc) { | ||
152 | - case INDEX_op_exit_tb: | ||
153 | - /* Reuse the zeroing that exists for goto_ptr. */ | ||
154 | - if (a0 == 0) { | ||
155 | - tcg_out_jmp(s, tcg_code_gen_epilogue); | ||
156 | - } else { | ||
157 | - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_EAX, a0); | ||
158 | - tcg_out_jmp(s, tb_ret_addr); | ||
159 | - } | ||
160 | - break; | ||
161 | case INDEX_op_goto_tb: | ||
162 | if (s->tb_jmp_insn_offset) { | ||
163 | /* direct jump method */ | ||
164 | @@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
165 | case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ | ||
166 | case INDEX_op_mov_i64: | ||
167 | case INDEX_op_call: /* Always emitted via tcg_out_call. */ | ||
168 | + case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ | ||
169 | default: | ||
170 | tcg_abort(); | ||
171 | } | ||
172 | diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc | ||
173 | index XXXXXXX..XXXXXXX 100644 | ||
174 | --- a/tcg/loongarch64/tcg-target.c.inc | ||
175 | +++ b/tcg/loongarch64/tcg-target.c.inc | ||
176 | @@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx, | ||
177 | |||
178 | static const tcg_insn_unit *tb_ret_addr; | ||
179 | |||
180 | +static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) | ||
181 | +{ | ||
182 | + /* Reuse the zeroing that exists for goto_ptr. */ | ||
183 | + if (a0 == 0) { | ||
184 | + tcg_out_call_int(s, tcg_code_gen_epilogue, true); | ||
185 | + } else { | ||
186 | + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0); | ||
187 | + tcg_out_call_int(s, tb_ret_addr, true); | ||
188 | + } | ||
189 | +} | ||
190 | + | ||
191 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
192 | const TCGArg args[TCG_MAX_OP_ARGS], | ||
193 | const int const_args[TCG_MAX_OP_ARGS]) | ||
194 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
195 | int c2 = const_args[2]; | ||
196 | |||
197 | switch (opc) { | ||
198 | - case INDEX_op_exit_tb: | ||
199 | - /* Reuse the zeroing that exists for goto_ptr. */ | ||
200 | - if (a0 == 0) { | ||
201 | - tcg_out_call_int(s, tcg_code_gen_epilogue, true); | ||
202 | - } else { | ||
203 | - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0); | ||
204 | - tcg_out_call_int(s, tb_ret_addr, true); | ||
205 | - } | ||
206 | - break; | ||
207 | - | ||
208 | case INDEX_op_goto_tb: | ||
209 | tcg_debug_assert(s->tb_jmp_insn_offset != NULL); | ||
210 | /* | ||
211 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
212 | case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ | ||
213 | case INDEX_op_mov_i64: | ||
214 | case INDEX_op_call: /* Always emitted via tcg_out_call. */ | ||
215 | + case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ | ||
216 | default: | ||
217 | g_assert_not_reached(); | ||
218 | } | ||
219 | diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc | 9 | diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc |
220 | index XXXXXXX..XXXXXXX 100644 | 10 | index XXXXXXX..XXXXXXX 100644 |
221 | --- a/tcg/mips/tcg-target.c.inc | 11 | --- a/tcg/mips/tcg-target.c.inc |
222 | +++ b/tcg/mips/tcg-target.c.inc | 12 | +++ b/tcg/mips/tcg-target.c.inc |
223 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_clz(TCGContext *s, MIPSInsn opcv2, MIPSInsn opcv6, | 13 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_movi_int(TCGContext *s, TCGType type, TCGReg ret, |
14 | tcg_target_long arg, TCGReg tbreg) | ||
15 | { | ||
16 | tcg_target_long tmp; | ||
17 | + int sh, lo; | ||
18 | |||
19 | if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) { | ||
20 | arg = (int32_t)arg; | ||
21 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_movi_int(TCGContext *s, TCGType type, TCGReg ret, | ||
22 | return; | ||
224 | } | 23 | } |
225 | } | 24 | |
226 | 25 | + /* | |
227 | +static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) | 26 | + * Load bitmasks with a right-shift. This is good for things |
228 | +{ | 27 | + * like 0x0fff_ffff_ffff_fff0: ADDUI r,0,0xff00 + DSRL r,r,4. |
229 | + TCGReg b0 = TCG_REG_ZERO; | 28 | + * or similarly using LUI. For this to work, bit 31 must be set. |
230 | + | 29 | + */ |
231 | + if (a0 & ~0xffff) { | 30 | + if (arg > 0 && (int32_t)arg < 0) { |
232 | + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, a0 & ~0xffff); | 31 | + sh = clz64(arg); |
233 | + b0 = TCG_REG_V0; | 32 | + if (tcg_out_movi_one(s, ret, arg << sh)) { |
234 | + } | 33 | + tcg_out_dsrl(s, ret, ret, sh); |
235 | + if (!tcg_out_opc_jmp(s, OPC_J, tb_ret_addr)) { | ||
236 | + tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, (uintptr_t)tb_ret_addr); | ||
237 | + tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0); | ||
238 | + } | ||
239 | + tcg_out_opc_imm(s, OPC_ORI, TCG_REG_V0, b0, a0 & 0xffff); | ||
240 | +} | ||
241 | + | ||
242 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
243 | const TCGArg args[TCG_MAX_OP_ARGS], | ||
244 | const int const_args[TCG_MAX_OP_ARGS]) | ||
245 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
246 | c2 = const_args[2]; | ||
247 | |||
248 | switch (opc) { | ||
249 | - case INDEX_op_exit_tb: | ||
250 | - { | ||
251 | - TCGReg b0 = TCG_REG_ZERO; | ||
252 | - | ||
253 | - a0 = (intptr_t)a0; | ||
254 | - if (a0 & ~0xffff) { | ||
255 | - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_V0, a0 & ~0xffff); | ||
256 | - b0 = TCG_REG_V0; | ||
257 | - } | ||
258 | - if (!tcg_out_opc_jmp(s, OPC_J, tb_ret_addr)) { | ||
259 | - tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, | ||
260 | - (uintptr_t)tb_ret_addr); | ||
261 | - tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0); | ||
262 | - } | ||
263 | - tcg_out_opc_imm(s, OPC_ORI, TCG_REG_V0, b0, a0 & 0xffff); | ||
264 | - } | ||
265 | - break; | ||
266 | case INDEX_op_goto_tb: | ||
267 | /* indirect jump method */ | ||
268 | tcg_debug_assert(s->tb_jmp_insn_offset == 0); | ||
269 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
270 | case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ | ||
271 | case INDEX_op_mov_i64: | ||
272 | case INDEX_op_call: /* Always emitted via tcg_out_call. */ | ||
273 | + case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ | ||
274 | default: | ||
275 | tcg_abort(); | ||
276 | } | ||
277 | diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc | ||
278 | index XXXXXXX..XXXXXXX 100644 | ||
279 | --- a/tcg/ppc/tcg-target.c.inc | ||
280 | +++ b/tcg/ppc/tcg-target.c.inc | ||
281 | @@ -XXX,XX +XXX,XX @@ static void tcg_target_qemu_prologue(TCGContext *s) | ||
282 | tcg_out32(s, BCLR | BO_ALWAYS); | ||
283 | } | ||
284 | |||
285 | +static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg) | ||
286 | +{ | ||
287 | + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R3, arg); | ||
288 | + tcg_out_b(s, 0, tcg_code_gen_epilogue); | ||
289 | +} | ||
290 | + | ||
291 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
292 | const TCGArg args[TCG_MAX_OP_ARGS], | ||
293 | const int const_args[TCG_MAX_OP_ARGS]) | ||
294 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
295 | TCGArg a0, a1, a2; | ||
296 | |||
297 | switch (opc) { | ||
298 | - case INDEX_op_exit_tb: | ||
299 | - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R3, args[0]); | ||
300 | - tcg_out_b(s, 0, tcg_code_gen_epilogue); | ||
301 | - break; | ||
302 | case INDEX_op_goto_tb: | ||
303 | if (s->tb_jmp_insn_offset) { | ||
304 | /* Direct jump. */ | ||
305 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
306 | case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ | ||
307 | case INDEX_op_mov_i64: | ||
308 | case INDEX_op_call: /* Always emitted via tcg_out_call. */ | ||
309 | + case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ | ||
310 | default: | ||
311 | tcg_abort(); | ||
312 | } | ||
313 | diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc | ||
314 | index XXXXXXX..XXXXXXX 100644 | ||
315 | --- a/tcg/riscv/tcg-target.c.inc | ||
316 | +++ b/tcg/riscv/tcg-target.c.inc | ||
317 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64) | ||
318 | |||
319 | static const tcg_insn_unit *tb_ret_addr; | ||
320 | |||
321 | +static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) | ||
322 | +{ | ||
323 | + /* Reuse the zeroing that exists for goto_ptr. */ | ||
324 | + if (a0 == 0) { | ||
325 | + tcg_out_call_int(s, tcg_code_gen_epilogue, true); | ||
326 | + } else { | ||
327 | + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0); | ||
328 | + tcg_out_call_int(s, tb_ret_addr, true); | ||
329 | + } | ||
330 | +} | ||
331 | + | ||
332 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
333 | const TCGArg args[TCG_MAX_OP_ARGS], | ||
334 | const int const_args[TCG_MAX_OP_ARGS]) | ||
335 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
336 | int c2 = const_args[2]; | ||
337 | |||
338 | switch (opc) { | ||
339 | - case INDEX_op_exit_tb: | ||
340 | - /* Reuse the zeroing that exists for goto_ptr. */ | ||
341 | - if (a0 == 0) { | ||
342 | - tcg_out_call_int(s, tcg_code_gen_epilogue, true); | ||
343 | - } else { | ||
344 | - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0); | ||
345 | - tcg_out_call_int(s, tb_ret_addr, true); | ||
346 | - } | ||
347 | - break; | ||
348 | - | ||
349 | case INDEX_op_goto_tb: | ||
350 | assert(s->tb_jmp_insn_offset == 0); | ||
351 | /* indirect jump method */ | ||
352 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
353 | case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ | ||
354 | case INDEX_op_mov_i64: | ||
355 | case INDEX_op_call: /* Always emitted via tcg_out_call. */ | ||
356 | + case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ | ||
357 | default: | ||
358 | g_assert_not_reached(); | ||
359 | } | ||
360 | diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc | ||
361 | index XXXXXXX..XXXXXXX 100644 | ||
362 | --- a/tcg/s390x/tcg-target.c.inc | ||
363 | +++ b/tcg/s390x/tcg-target.c.inc | ||
364 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st(TCGContext* s, TCGReg data_reg, TCGReg addr_reg, | ||
365 | #endif | ||
366 | } | ||
367 | |||
368 | +static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) | ||
369 | +{ | ||
370 | + /* Reuse the zeroing that exists for goto_ptr. */ | ||
371 | + if (a0 == 0) { | ||
372 | + tgen_gotoi(s, S390_CC_ALWAYS, tcg_code_gen_epilogue); | ||
373 | + } else { | ||
374 | + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, a0); | ||
375 | + tgen_gotoi(s, S390_CC_ALWAYS, tb_ret_addr); | ||
376 | + } | ||
377 | +} | ||
378 | + | ||
379 | # define OP_32_64(x) \ | ||
380 | case glue(glue(INDEX_op_,x),_i32): \ | ||
381 | case glue(glue(INDEX_op_,x),_i64) | ||
382 | @@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
383 | TCGArg a0, a1, a2; | ||
384 | |||
385 | switch (opc) { | ||
386 | - case INDEX_op_exit_tb: | ||
387 | - /* Reuse the zeroing that exists for goto_ptr. */ | ||
388 | - a0 = args[0]; | ||
389 | - if (a0 == 0) { | ||
390 | - tgen_gotoi(s, S390_CC_ALWAYS, tcg_code_gen_epilogue); | ||
391 | - } else { | ||
392 | - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R2, a0); | ||
393 | - tgen_gotoi(s, S390_CC_ALWAYS, tb_ret_addr); | ||
394 | - } | ||
395 | - break; | ||
396 | - | ||
397 | case INDEX_op_goto_tb: | ||
398 | a0 = args[0]; | ||
399 | /* | ||
400 | @@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
401 | case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ | ||
402 | case INDEX_op_mov_i64: | ||
403 | case INDEX_op_call: /* Always emitted via tcg_out_call. */ | ||
404 | + case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ | ||
405 | default: | ||
406 | tcg_abort(); | ||
407 | } | ||
408 | diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc | ||
409 | index XXXXXXX..XXXXXXX 100644 | ||
410 | --- a/tcg/sparc64/tcg-target.c.inc | ||
411 | +++ b/tcg/sparc64/tcg-target.c.inc | ||
412 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st(TCGContext *s, TCGReg data, TCGReg addr, | ||
413 | #endif /* CONFIG_SOFTMMU */ | ||
414 | } | ||
415 | |||
416 | +static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) | ||
417 | +{ | ||
418 | + if (check_fit_ptr(a0, 13)) { | ||
419 | + tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN); | ||
420 | + tcg_out_movi_imm13(s, TCG_REG_O0, a0); | ||
421 | + return; | ||
422 | + } else if (USE_REG_TB) { | ||
423 | + intptr_t tb_diff = tcg_tbrel_diff(s, (void *)a0); | ||
424 | + if (check_fit_ptr(tb_diff, 13)) { | ||
425 | + tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN); | ||
426 | + /* Note that TCG_REG_TB has been unwound to O1. */ | ||
427 | + tcg_out_arithi(s, TCG_REG_O0, TCG_REG_O1, tb_diff, ARITH_ADD); | ||
428 | + return; | 34 | + return; |
429 | + } | 35 | + } |
430 | + } | 36 | + } |
431 | + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I0, a0 & ~0x3ff); | ||
432 | + tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN); | ||
433 | + tcg_out_arithi(s, TCG_REG_O0, TCG_REG_O0, a0 & 0x3ff, ARITH_OR); | ||
434 | +} | ||
435 | + | 37 | + |
436 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 38 | + /* |
437 | const TCGArg args[TCG_MAX_OP_ARGS], | 39 | + * Load slightly larger constants using left-shift. |
438 | const int const_args[TCG_MAX_OP_ARGS]) | 40 | + * Limit this sequence to 3 insns to avoid too much expansion. |
439 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 41 | + */ |
440 | c2 = const_args[2]; | 42 | + sh = ctz64(arg); |
441 | 43 | + if (sh && tcg_out_movi_two(s, ret, arg >> sh)) { | |
442 | switch (opc) { | 44 | + tcg_out_dsll(s, ret, ret, sh); |
443 | - case INDEX_op_exit_tb: | 45 | + return; |
444 | - if (check_fit_ptr(a0, 13)) { | 46 | + } |
445 | - tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN); | ||
446 | - tcg_out_movi_imm13(s, TCG_REG_O0, a0); | ||
447 | - break; | ||
448 | - } else if (USE_REG_TB) { | ||
449 | - intptr_t tb_diff = tcg_tbrel_diff(s, (void *)a0); | ||
450 | - if (check_fit_ptr(tb_diff, 13)) { | ||
451 | - tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN); | ||
452 | - /* Note that TCG_REG_TB has been unwound to O1. */ | ||
453 | - tcg_out_arithi(s, TCG_REG_O0, TCG_REG_O1, tb_diff, ARITH_ADD); | ||
454 | - break; | ||
455 | - } | ||
456 | - } | ||
457 | - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I0, a0 & ~0x3ff); | ||
458 | - tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN); | ||
459 | - tcg_out_arithi(s, TCG_REG_O0, TCG_REG_O0, a0 & 0x3ff, ARITH_OR); | ||
460 | - break; | ||
461 | case INDEX_op_goto_tb: | ||
462 | if (s->tb_jmp_insn_offset) { | ||
463 | /* direct jump method */ | ||
464 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
465 | case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ | ||
466 | case INDEX_op_mov_i64: | ||
467 | case INDEX_op_call: /* Always emitted via tcg_out_call. */ | ||
468 | + case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ | ||
469 | default: | ||
470 | tcg_abort(); | ||
471 | } | ||
472 | diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc | ||
473 | index XXXXXXX..XXXXXXX 100644 | ||
474 | --- a/tcg/tci/tcg-target.c.inc | ||
475 | +++ b/tcg/tci/tcg-target.c.inc | ||
476 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_call(TCGContext *s, const tcg_insn_unit *func, | ||
477 | # define CASE_64(x) | ||
478 | #endif | ||
479 | |||
480 | +static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg) | ||
481 | +{ | ||
482 | + tcg_out_op_p(s, INDEX_op_exit_tb, (void *)arg); | ||
483 | +} | ||
484 | + | 47 | + |
485 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 48 | + /* |
486 | const TCGArg args[TCG_MAX_OP_ARGS], | 49 | + * Load slightly larger constants using left-shift and add/or. |
487 | const int const_args[TCG_MAX_OP_ARGS]) | 50 | + * Prefer addi with a negative immediate when that would produce |
488 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 51 | + * a larger shift. For this to work, bits 15 and 16 must be set. |
489 | TCGOpcode exts; | 52 | + */ |
490 | 53 | + lo = arg & 0xffff; | |
491 | switch (opc) { | 54 | + if (lo) { |
492 | - case INDEX_op_exit_tb: | 55 | + if ((arg & 0x18000) == 0x18000) { |
493 | - tcg_out_op_p(s, opc, (void *)args[0]); | 56 | + lo = (int16_t)arg; |
494 | - break; | 57 | + } |
495 | - | 58 | + tmp = arg - lo; |
496 | case INDEX_op_goto_tb: | 59 | + sh = ctz64(tmp); |
497 | tcg_debug_assert(s->tb_jmp_insn_offset == 0); | 60 | + tmp >>= sh; |
498 | /* indirect jump method. */ | 61 | + if (tcg_out_movi_one(s, ret, tmp)) { |
499 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 62 | + tcg_out_dsll(s, ret, ret, sh); |
500 | case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */ | 63 | + tcg_out_opc_imm(s, lo < 0 ? OPC_DADDIU : OPC_ORI, ret, ret, lo); |
501 | case INDEX_op_mov_i64: | 64 | + return; |
502 | case INDEX_op_call: /* Always emitted via tcg_out_call. */ | 65 | + } |
503 | + case INDEX_op_exit_tb: /* Always emitted via tcg_out_exit_tb. */ | 66 | + } |
504 | default: | 67 | + |
505 | tcg_abort(); | 68 | /* Otherwise, put 64-bit constants into the constant pool. */ |
506 | } | 69 | tcg_out_movi_pool(s, ret, arg, tbreg); |
70 | } | ||
507 | -- | 71 | -- |
508 | 2.34.1 | 72 | 2.34.1 |
509 | |||
510 | diff view generated by jsdifflib |
1 | This will shortly be used for more than reset. | 1 | The new(ish) macro produces a compile-time error instead |
---|---|---|---|
2 | of a link-time error. | ||
2 | 3 | ||
3 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
4 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> | ||
5 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 4 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
6 | --- | 5 | --- |
7 | include/exec/exec-all.h | 2 +- | 6 | tcg/mips/tcg-target.c.inc | 8 +++----- |
8 | accel/tcg/translate-all.c | 8 ++++---- | 7 | 1 file changed, 3 insertions(+), 5 deletions(-) |
9 | tcg/tcg.c | 4 ++-- | ||
10 | 3 files changed, 7 insertions(+), 7 deletions(-) | ||
11 | 8 | ||
12 | diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h | 9 | diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc |
13 | index XXXXXXX..XXXXXXX 100644 | 10 | index XXXXXXX..XXXXXXX 100644 |
14 | --- a/include/exec/exec-all.h | 11 | --- a/tcg/mips/tcg-target.c.inc |
15 | +++ b/include/exec/exec-all.h | 12 | +++ b/tcg/mips/tcg-target.c.inc |
16 | @@ -XXX,XX +XXX,XX @@ struct TranslationBlock { | 13 | @@ -XXX,XX +XXX,XX @@ |
17 | * setting one of the jump targets (or patching the jump instruction). Only | 14 | # define LO_OFF (MIPS_BE * 4) |
18 | * two of such jumps are supported. | 15 | # define HI_OFF (4 - LO_OFF) |
19 | */ | 16 | #else |
20 | +#define TB_JMP_OFFSET_INVALID 0xffff /* indicates no jump generated */ | 17 | -/* To assert at compile-time that these values are never used |
21 | uint16_t jmp_reset_offset[2]; /* offset of original jump target */ | 18 | - for TCG_TARGET_REG_BITS == 64. */ |
22 | -#define TB_JMP_RESET_OFFSET_INVALID 0xffff /* indicates no jump generated */ | 19 | -int link_error(void); |
23 | uintptr_t jmp_target_arg[2]; /* target address or offset */ | 20 | -# define LO_OFF link_error() |
24 | 21 | -# define HI_OFF link_error() | |
25 | /* | 22 | +/* Assert at compile-time that these values are never used for 64-bit. */ |
26 | diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c | 23 | +# define LO_OFF ({ qemu_build_not_reached(); 0; }) |
27 | index XXXXXXX..XXXXXXX 100644 | 24 | +# define HI_OFF ({ qemu_build_not_reached(); 0; }) |
28 | --- a/accel/tcg/translate-all.c | ||
29 | +++ b/accel/tcg/translate-all.c | ||
30 | @@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu, | ||
31 | tb->jmp_dest[1] = (uintptr_t)NULL; | ||
32 | |||
33 | /* init original jump addresses which have been set during tcg_gen_code() */ | ||
34 | - if (tb->jmp_reset_offset[0] != TB_JMP_RESET_OFFSET_INVALID) { | ||
35 | + if (tb->jmp_reset_offset[0] != TB_JMP_OFFSET_INVALID) { | ||
36 | tb_reset_jump(tb, 0); | ||
37 | } | ||
38 | - if (tb->jmp_reset_offset[1] != TB_JMP_RESET_OFFSET_INVALID) { | ||
39 | + if (tb->jmp_reset_offset[1] != TB_JMP_OFFSET_INVALID) { | ||
40 | tb_reset_jump(tb, 1); | ||
41 | } | ||
42 | |||
43 | @@ -XXX,XX +XXX,XX @@ static gboolean tb_tree_stats_iter(gpointer key, gpointer value, gpointer data) | ||
44 | if (tb_page_addr1(tb) != -1) { | ||
45 | tst->cross_page++; | ||
46 | } | ||
47 | - if (tb->jmp_reset_offset[0] != TB_JMP_RESET_OFFSET_INVALID) { | ||
48 | + if (tb->jmp_reset_offset[0] != TB_JMP_OFFSET_INVALID) { | ||
49 | tst->direct_jmp_count++; | ||
50 | - if (tb->jmp_reset_offset[1] != TB_JMP_RESET_OFFSET_INVALID) { | ||
51 | + if (tb->jmp_reset_offset[1] != TB_JMP_OFFSET_INVALID) { | ||
52 | tst->direct_jmp2_count++; | ||
53 | } | ||
54 | } | ||
55 | diff --git a/tcg/tcg.c b/tcg/tcg.c | ||
56 | index XXXXXXX..XXXXXXX 100644 | ||
57 | --- a/tcg/tcg.c | ||
58 | +++ b/tcg/tcg.c | ||
59 | @@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb, target_ulong pc_start) | ||
60 | #endif | 25 | #endif |
61 | 26 | ||
62 | /* Initialize goto_tb jump offsets. */ | 27 | #ifdef CONFIG_DEBUG_TCG |
63 | - tb->jmp_reset_offset[0] = TB_JMP_RESET_OFFSET_INVALID; | ||
64 | - tb->jmp_reset_offset[1] = TB_JMP_RESET_OFFSET_INVALID; | ||
65 | + tb->jmp_reset_offset[0] = TB_JMP_OFFSET_INVALID; | ||
66 | + tb->jmp_reset_offset[1] = TB_JMP_OFFSET_INVALID; | ||
67 | tcg_ctx->tb_jmp_reset_offset = tb->jmp_reset_offset; | ||
68 | if (TCG_TARGET_HAS_direct_jump) { | ||
69 | tcg_ctx->tb_jmp_insn_offset = tb->jmp_target_arg; | ||
70 | -- | 28 | -- |
71 | 2.34.1 | 29 | 2.34.1 |
72 | |||
73 | diff view generated by jsdifflib |
1 | Similar to the existing set_jmp_reset_offset. Include the | 1 | Since e03b56863d2b, which replaced HOST_WORDS_BIGENDIAN |
---|---|---|---|
2 | rw->rx address space conversion done by arm and s390x, and | 2 | with HOST_BIG_ENDIAN, there is no need to define a second |
3 | forgotten by mips and riscv. | 3 | symbol which is [0,1]. |
4 | 4 | ||
5 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
6 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> | 5 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> |
7 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 6 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
8 | --- | 7 | --- |
9 | tcg/tcg.c | 9 +++++++++ | 8 | tcg/mips/tcg-target.c.inc | 46 +++++++++++++++++---------------------- |
10 | tcg/arm/tcg-target.c.inc | 2 +- | 9 | 1 file changed, 20 insertions(+), 26 deletions(-) |
11 | tcg/mips/tcg-target.c.inc | 2 +- | ||
12 | tcg/riscv/tcg-target.c.inc | 2 +- | ||
13 | tcg/tci/tcg-target.c.inc | 2 +- | ||
14 | 5 files changed, 13 insertions(+), 4 deletions(-) | ||
15 | 10 | ||
16 | diff --git a/tcg/tcg.c b/tcg/tcg.c | ||
17 | index XXXXXXX..XXXXXXX 100644 | ||
18 | --- a/tcg/tcg.c | ||
19 | +++ b/tcg/tcg.c | ||
20 | @@ -XXX,XX +XXX,XX @@ static void G_GNUC_UNUSED set_jmp_insn_offset(TCGContext *s, int which) | ||
21 | s->tb_jmp_insn_offset[which] = tcg_current_code_size(s); | ||
22 | } | ||
23 | |||
24 | +static uintptr_t G_GNUC_UNUSED get_jmp_target_addr(TCGContext *s, int which) | ||
25 | +{ | ||
26 | + /* | ||
27 | + * Return the read-execute version of the pointer, for the benefit | ||
28 | + * of any pc-relative addressing mode. | ||
29 | + */ | ||
30 | + return (uintptr_t)tcg_splitwx_to_rx(&s->tb_jmp_target_addr[which]); | ||
31 | +} | ||
32 | + | ||
33 | /* Signal overflow, starting over with fewer guest insns. */ | ||
34 | static G_NORETURN | ||
35 | void tcg_raise_tb_overflow(TCGContext *s) | ||
36 | diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc | ||
37 | index XXXXXXX..XXXXXXX 100644 | ||
38 | --- a/tcg/arm/tcg-target.c.inc | ||
39 | +++ b/tcg/arm/tcg-target.c.inc | ||
40 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
41 | TCGReg base = TCG_REG_PC; | ||
42 | |||
43 | qemu_build_assert(!TCG_TARGET_HAS_direct_jump); | ||
44 | - ptr = (intptr_t)tcg_splitwx_to_rx(s->tb_jmp_target_addr + args[0]); | ||
45 | + ptr = get_jmp_target_addr(s, args[0]); | ||
46 | dif = tcg_pcrel_diff(s, (void *)ptr) - 8; | ||
47 | dil = sextract32(dif, 0, 12); | ||
48 | if (dif != dil) { | ||
49 | diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc | 11 | diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc |
50 | index XXXXXXX..XXXXXXX 100644 | 12 | index XXXXXXX..XXXXXXX 100644 |
51 | --- a/tcg/mips/tcg-target.c.inc | 13 | --- a/tcg/mips/tcg-target.c.inc |
52 | +++ b/tcg/mips/tcg-target.c.inc | 14 | +++ b/tcg/mips/tcg-target.c.inc |
53 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 15 | @@ -XXX,XX +XXX,XX @@ |
54 | /* indirect jump method */ | 16 | #include "../tcg-ldst.c.inc" |
55 | qemu_build_assert(!TCG_TARGET_HAS_direct_jump); | 17 | #include "../tcg-pool.c.inc" |
56 | tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_REG_ZERO, | 18 | |
57 | - (uintptr_t)(s->tb_jmp_target_addr + a0)); | 19 | -#if HOST_BIG_ENDIAN |
58 | + get_jmp_target_addr(s, a0)); | 20 | -# define MIPS_BE 1 |
59 | tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0); | 21 | -#else |
60 | tcg_out_nop(s); | 22 | -# define MIPS_BE 0 |
61 | set_jmp_reset_offset(s, a0); | 23 | -#endif |
62 | diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc | 24 | - |
63 | index XXXXXXX..XXXXXXX 100644 | 25 | #if TCG_TARGET_REG_BITS == 32 |
64 | --- a/tcg/riscv/tcg-target.c.inc | 26 | -# define LO_OFF (MIPS_BE * 4) |
65 | +++ b/tcg/riscv/tcg-target.c.inc | 27 | +# define LO_OFF (HOST_BIG_ENDIAN * 4) |
66 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 28 | # define HI_OFF (4 - LO_OFF) |
67 | qemu_build_assert(!TCG_TARGET_HAS_direct_jump); | 29 | #else |
68 | /* indirect jump method */ | 30 | /* Assert at compile-time that these values are never used for 64-bit. */ |
69 | tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO, | 31 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi, |
70 | - (uintptr_t)(s->tb_jmp_target_addr + a0)); | 32 | /* Prefer to load from offset 0 first, but allow for overlap. */ |
71 | + get_jmp_target_addr(s, a0)); | 33 | if (TCG_TARGET_REG_BITS == 64) { |
72 | tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_TMP0, 0); | 34 | tcg_out_opc_imm(s, OPC_LD, lo, base, 0); |
73 | set_jmp_reset_offset(s, a0); | 35 | - } else if (MIPS_BE ? hi != base : lo == base) { |
36 | + } else if (HOST_BIG_ENDIAN ? hi != base : lo == base) { | ||
37 | tcg_out_opc_imm(s, OPC_LW, hi, base, HI_OFF); | ||
38 | tcg_out_opc_imm(s, OPC_LW, lo, base, LO_OFF); | ||
39 | } else { | ||
40 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi, | ||
41 | static void tcg_out_qemu_ld_unalign(TCGContext *s, TCGReg lo, TCGReg hi, | ||
42 | TCGReg base, MemOp opc, TCGType type) | ||
43 | { | ||
44 | - const MIPSInsn lw1 = MIPS_BE ? OPC_LWL : OPC_LWR; | ||
45 | - const MIPSInsn lw2 = MIPS_BE ? OPC_LWR : OPC_LWL; | ||
46 | - const MIPSInsn ld1 = MIPS_BE ? OPC_LDL : OPC_LDR; | ||
47 | - const MIPSInsn ld2 = MIPS_BE ? OPC_LDR : OPC_LDL; | ||
48 | + const MIPSInsn lw1 = HOST_BIG_ENDIAN ? OPC_LWL : OPC_LWR; | ||
49 | + const MIPSInsn lw2 = HOST_BIG_ENDIAN ? OPC_LWR : OPC_LWL; | ||
50 | + const MIPSInsn ld1 = HOST_BIG_ENDIAN ? OPC_LDL : OPC_LDR; | ||
51 | + const MIPSInsn ld2 = HOST_BIG_ENDIAN ? OPC_LDR : OPC_LDL; | ||
52 | bool sgn = opc & MO_SIGN; | ||
53 | |||
54 | switch (opc & MO_SIZE) { | ||
55 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_ld_unalign(TCGContext *s, TCGReg lo, TCGReg hi, | ||
56 | tcg_out_opc_imm(s, ld1, lo, base, 0); | ||
57 | tcg_out_opc_imm(s, ld2, lo, base, 7); | ||
58 | } else { | ||
59 | - tcg_out_opc_imm(s, lw1, MIPS_BE ? hi : lo, base, 0 + 0); | ||
60 | - tcg_out_opc_imm(s, lw2, MIPS_BE ? hi : lo, base, 0 + 3); | ||
61 | - tcg_out_opc_imm(s, lw1, MIPS_BE ? lo : hi, base, 4 + 0); | ||
62 | - tcg_out_opc_imm(s, lw2, MIPS_BE ? lo : hi, base, 4 + 3); | ||
63 | + tcg_out_opc_imm(s, lw1, HOST_BIG_ENDIAN ? hi : lo, base, 0 + 0); | ||
64 | + tcg_out_opc_imm(s, lw2, HOST_BIG_ENDIAN ? hi : lo, base, 0 + 3); | ||
65 | + tcg_out_opc_imm(s, lw1, HOST_BIG_ENDIAN ? lo : hi, base, 4 + 0); | ||
66 | + tcg_out_opc_imm(s, lw2, HOST_BIG_ENDIAN ? lo : hi, base, 4 + 3); | ||
67 | } | ||
74 | break; | 68 | break; |
75 | diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc | 69 | |
76 | index XXXXXXX..XXXXXXX 100644 | 70 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg lo, TCGReg hi, |
77 | --- a/tcg/tci/tcg-target.c.inc | 71 | if (TCG_TARGET_REG_BITS == 64) { |
78 | +++ b/tcg/tci/tcg-target.c.inc | 72 | tcg_out_opc_imm(s, OPC_SD, lo, base, 0); |
79 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 73 | } else { |
80 | case INDEX_op_goto_tb: | 74 | - tcg_out_opc_imm(s, OPC_SW, MIPS_BE ? hi : lo, base, 0); |
81 | qemu_build_assert(!TCG_TARGET_HAS_direct_jump); | 75 | - tcg_out_opc_imm(s, OPC_SW, MIPS_BE ? lo : hi, base, 4); |
82 | /* indirect jump method. */ | 76 | + tcg_out_opc_imm(s, OPC_SW, HOST_BIG_ENDIAN ? hi : lo, base, 0); |
83 | - tcg_out_op_p(s, opc, s->tb_jmp_target_addr + args[0]); | 77 | + tcg_out_opc_imm(s, OPC_SW, HOST_BIG_ENDIAN ? lo : hi, base, 4); |
84 | + tcg_out_op_p(s, opc, (void *)get_jmp_target_addr(s, args[0])); | 78 | } |
85 | set_jmp_reset_offset(s, args[0]); | ||
86 | break; | 79 | break; |
80 | default: | ||
81 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg lo, TCGReg hi, | ||
82 | static void tcg_out_qemu_st_unalign(TCGContext *s, TCGReg lo, TCGReg hi, | ||
83 | TCGReg base, MemOp opc) | ||
84 | { | ||
85 | - const MIPSInsn sw1 = MIPS_BE ? OPC_SWL : OPC_SWR; | ||
86 | - const MIPSInsn sw2 = MIPS_BE ? OPC_SWR : OPC_SWL; | ||
87 | - const MIPSInsn sd1 = MIPS_BE ? OPC_SDL : OPC_SDR; | ||
88 | - const MIPSInsn sd2 = MIPS_BE ? OPC_SDR : OPC_SDL; | ||
89 | + const MIPSInsn sw1 = HOST_BIG_ENDIAN ? OPC_SWL : OPC_SWR; | ||
90 | + const MIPSInsn sw2 = HOST_BIG_ENDIAN ? OPC_SWR : OPC_SWL; | ||
91 | + const MIPSInsn sd1 = HOST_BIG_ENDIAN ? OPC_SDL : OPC_SDR; | ||
92 | + const MIPSInsn sd2 = HOST_BIG_ENDIAN ? OPC_SDR : OPC_SDL; | ||
93 | |||
94 | switch (opc & MO_SIZE) { | ||
95 | case MO_16: | ||
96 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st_unalign(TCGContext *s, TCGReg lo, TCGReg hi, | ||
97 | tcg_out_opc_imm(s, sd1, lo, base, 0); | ||
98 | tcg_out_opc_imm(s, sd2, lo, base, 7); | ||
99 | } else { | ||
100 | - tcg_out_opc_imm(s, sw1, MIPS_BE ? hi : lo, base, 0 + 0); | ||
101 | - tcg_out_opc_imm(s, sw2, MIPS_BE ? hi : lo, base, 0 + 3); | ||
102 | - tcg_out_opc_imm(s, sw1, MIPS_BE ? lo : hi, base, 4 + 0); | ||
103 | - tcg_out_opc_imm(s, sw2, MIPS_BE ? lo : hi, base, 4 + 3); | ||
104 | + tcg_out_opc_imm(s, sw1, HOST_BIG_ENDIAN ? hi : lo, base, 0 + 0); | ||
105 | + tcg_out_opc_imm(s, sw2, HOST_BIG_ENDIAN ? hi : lo, base, 0 + 3); | ||
106 | + tcg_out_opc_imm(s, sw1, HOST_BIG_ENDIAN ? lo : hi, base, 4 + 0); | ||
107 | + tcg_out_opc_imm(s, sw2, HOST_BIG_ENDIAN ? lo : hi, base, 4 + 3); | ||
108 | } | ||
109 | break; | ||
87 | 110 | ||
88 | -- | 111 | -- |
89 | 2.34.1 | 112 | 2.34.1 |
90 | 113 | ||
91 | 114 | diff view generated by jsdifflib |
1 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | 1 | Acked-by: Alistair Francis <alistair.francis@wdc.com> |
---|---|---|---|
2 | Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> | ||
2 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 3 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
3 | --- | 4 | --- |
4 | tcg/i386/tcg-target.c.inc | 14 +++++--------- | 5 | disas/riscv.c | 6 ++++++ |
5 | 1 file changed, 5 insertions(+), 9 deletions(-) | 6 | 1 file changed, 6 insertions(+) |
6 | 7 | ||
7 | diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc | 8 | diff --git a/disas/riscv.c b/disas/riscv.c |
8 | index XXXXXXX..XXXXXXX 100644 | 9 | index XXXXXXX..XXXXXXX 100644 |
9 | --- a/tcg/i386/tcg-target.c.inc | 10 | --- a/disas/riscv.c |
10 | +++ b/tcg/i386/tcg-target.c.inc | 11 | +++ b/disas/riscv.c |
11 | @@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, | 12 | @@ -XXX,XX +XXX,XX @@ typedef enum { |
12 | 13 | rv_op_cm_mvsa01 = 786, | |
13 | switch (opc) { | 14 | rv_op_cm_jt = 787, |
14 | case INDEX_op_goto_tb: | 15 | rv_op_cm_jalt = 788, |
15 | - if (s->tb_jmp_insn_offset) { | 16 | + rv_op_czero_eqz = 789, |
16 | - /* direct jump method */ | 17 | + rv_op_czero_nez = 790, |
17 | - int gap; | 18 | } rv_op; |
18 | - /* jump displacement must be aligned for atomic patching; | 19 | |
19 | + qemu_build_assert(TCG_TARGET_HAS_direct_jump); | 20 | /* structures */ |
20 | + { | 21 | @@ -XXX,XX +XXX,XX @@ const rv_opcode_data opcode_data[] = { |
21 | + /* | 22 | { "cm.mvsa01", rv_codec_zcmp_cm_mv, rv_fmt_rd_rs2, NULL, 0, 0, 0 }, |
22 | + * Jump displacement must be aligned for atomic patching; | 23 | { "cm.jt", rv_codec_zcmt_jt, rv_fmt_zcmt_index, NULL, 0 }, |
23 | * see if we need to add extra nops before jump | 24 | { "cm.jalt", rv_codec_zcmt_jt, rv_fmt_zcmt_index, NULL, 0 }, |
24 | */ | 25 | + { "czero.eqz", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, |
25 | - gap = QEMU_ALIGN_PTR_UP(s->code_ptr + 1, 4) - s->code_ptr; | 26 | + { "czero.nez", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, |
26 | + int gap = QEMU_ALIGN_PTR_UP(s->code_ptr + 1, 4) - s->code_ptr; | 27 | }; |
27 | if (gap != 1) { | 28 | |
28 | tcg_out_nopn(s, gap - 1); | 29 | /* CSR names */ |
29 | } | 30 | @@ -XXX,XX +XXX,XX @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) |
30 | tcg_out8(s, OPC_JMP_long); /* jmp im */ | 31 | case 45: op = rv_op_minu; break; |
31 | s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s); | 32 | case 46: op = rv_op_max; break; |
32 | tcg_out32(s, 0); | 33 | case 47: op = rv_op_maxu; break; |
33 | - } else { | 34 | + case 075: op = rv_op_czero_eqz; break; |
34 | - /* indirect jump method */ | 35 | + case 077: op = rv_op_czero_nez; break; |
35 | - tcg_out_modrm_offset(s, OPC_GRP5, EXT5_JMPN_Ev, -1, | 36 | case 130: op = rv_op_sh1add; break; |
36 | - (intptr_t)(s->tb_jmp_target_addr + a0)); | 37 | case 132: op = rv_op_sh2add; break; |
37 | } | 38 | case 134: op = rv_op_sh3add; break; |
38 | set_jmp_reset_offset(s, a0); | ||
39 | break; | ||
40 | -- | 39 | -- |
41 | 2.34.1 | 40 | 2.34.1 |
42 | |||
43 | diff view generated by jsdifflib |
1 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | 1 | Define a useful subset of the extensions. Probe for them |
---|---|---|---|
2 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> | 2 | via compiler pre-processor feature macros and SIGILL. |
3 | |||
4 | Acked-by: Alistair Francis <alistair.francis@wdc.com> | ||
5 | Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> | ||
3 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 6 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
4 | --- | 7 | --- |
5 | tcg/riscv/tcg-target.c.inc | 3 ++- | 8 | tcg/riscv/tcg-target.h | 6 +++ |
6 | 1 file changed, 2 insertions(+), 1 deletion(-) | 9 | tcg/riscv/tcg-target.c.inc | 96 ++++++++++++++++++++++++++++++++++++++ |
10 | 2 files changed, 102 insertions(+) | ||
7 | 11 | ||
12 | diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h | ||
13 | index XXXXXXX..XXXXXXX 100644 | ||
14 | --- a/tcg/riscv/tcg-target.h | ||
15 | +++ b/tcg/riscv/tcg-target.h | ||
16 | @@ -XXX,XX +XXX,XX @@ typedef enum { | ||
17 | #define TCG_TARGET_CALL_ARG_I128 TCG_CALL_ARG_NORMAL | ||
18 | #define TCG_TARGET_CALL_RET_I128 TCG_CALL_RET_NORMAL | ||
19 | |||
20 | +#if defined(__riscv_arch_test) && defined(__riscv_zbb) | ||
21 | +# define have_zbb true | ||
22 | +#else | ||
23 | +extern bool have_zbb; | ||
24 | +#endif | ||
25 | + | ||
26 | /* optional instructions */ | ||
27 | #define TCG_TARGET_HAS_movcond_i32 0 | ||
28 | #define TCG_TARGET_HAS_div_i32 1 | ||
8 | diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc | 29 | diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc |
9 | index XXXXXXX..XXXXXXX 100644 | 30 | index XXXXXXX..XXXXXXX 100644 |
10 | --- a/tcg/riscv/tcg-target.c.inc | 31 | --- a/tcg/riscv/tcg-target.c.inc |
11 | +++ b/tcg/riscv/tcg-target.c.inc | 32 | +++ b/tcg/riscv/tcg-target.c.inc |
33 | @@ -XXX,XX +XXX,XX @@ static const int tcg_target_call_iarg_regs[] = { | ||
34 | TCG_REG_A7, | ||
35 | }; | ||
36 | |||
37 | +#ifndef have_zbb | ||
38 | +bool have_zbb; | ||
39 | +#endif | ||
40 | +#if defined(__riscv_arch_test) && defined(__riscv_zba) | ||
41 | +# define have_zba true | ||
42 | +#else | ||
43 | +static bool have_zba; | ||
44 | +#endif | ||
45 | +#if defined(__riscv_arch_test) && defined(__riscv_zicond) | ||
46 | +# define have_zicond true | ||
47 | +#else | ||
48 | +static bool have_zicond; | ||
49 | +#endif | ||
50 | + | ||
51 | static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot) | ||
52 | { | ||
53 | tcg_debug_assert(kind == TCG_CALL_RET_NORMAL); | ||
12 | @@ -XXX,XX +XXX,XX @@ typedef enum { | 54 | @@ -XXX,XX +XXX,XX @@ typedef enum { |
13 | #endif | ||
14 | 55 | ||
15 | OPC_FENCE = 0x0000000f, | 56 | OPC_FENCE = 0x0000000f, |
16 | + OPC_NOP = OPC_ADDI, /* nop = addi r0,r0,0 */ | 57 | OPC_NOP = OPC_ADDI, /* nop = addi r0,r0,0 */ |
58 | + | ||
59 | + /* Zba: Bit manipulation extension, address generation */ | ||
60 | + OPC_ADD_UW = 0x0800003b, | ||
61 | + | ||
62 | + /* Zbb: Bit manipulation extension, basic bit manipulaton */ | ||
63 | + OPC_ANDN = 0x40007033, | ||
64 | + OPC_CLZ = 0x60001013, | ||
65 | + OPC_CLZW = 0x6000101b, | ||
66 | + OPC_CPOP = 0x60201013, | ||
67 | + OPC_CPOPW = 0x6020101b, | ||
68 | + OPC_CTZ = 0x60101013, | ||
69 | + OPC_CTZW = 0x6010101b, | ||
70 | + OPC_ORN = 0x40006033, | ||
71 | + OPC_REV8 = 0x6b805013, | ||
72 | + OPC_ROL = 0x60001033, | ||
73 | + OPC_ROLW = 0x6000103b, | ||
74 | + OPC_ROR = 0x60005033, | ||
75 | + OPC_RORW = 0x6000503b, | ||
76 | + OPC_RORI = 0x60005013, | ||
77 | + OPC_RORIW = 0x6000501b, | ||
78 | + OPC_SEXT_B = 0x60401013, | ||
79 | + OPC_SEXT_H = 0x60501013, | ||
80 | + OPC_XNOR = 0x40004033, | ||
81 | + OPC_ZEXT_H = 0x0800403b, | ||
82 | + | ||
83 | + /* Zicond: integer conditional operations */ | ||
84 | + OPC_CZERO_EQZ = 0x0e005033, | ||
85 | + OPC_CZERO_NEZ = 0x0e007033, | ||
17 | } RISCVInsn; | 86 | } RISCVInsn; |
18 | 87 | ||
19 | /* | 88 | /* |
20 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_nop_fill(tcg_insn_unit *p, int count) | 89 | @@ -XXX,XX +XXX,XX @@ static void tcg_target_qemu_prologue(TCGContext *s) |
90 | tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_RA, 0); | ||
91 | } | ||
92 | |||
93 | +static volatile sig_atomic_t got_sigill; | ||
94 | + | ||
95 | +static void sigill_handler(int signo, siginfo_t *si, void *data) | ||
96 | +{ | ||
97 | + /* Skip the faulty instruction */ | ||
98 | + ucontext_t *uc = (ucontext_t *)data; | ||
99 | + uc->uc_mcontext.__gregs[REG_PC] += 4; | ||
100 | + | ||
101 | + got_sigill = 1; | ||
102 | +} | ||
103 | + | ||
104 | +static void tcg_target_detect_isa(void) | ||
105 | +{ | ||
106 | +#if !defined(have_zba) || !defined(have_zbb) || !defined(have_zicond) | ||
107 | + /* | ||
108 | + * TODO: It is expected that this will be determinable via | ||
109 | + * linux riscv_hwprobe syscall, not yet merged. | ||
110 | + * In the meantime, test via sigill. | ||
111 | + */ | ||
112 | + | ||
113 | + struct sigaction sa_old, sa_new; | ||
114 | + | ||
115 | + memset(&sa_new, 0, sizeof(sa_new)); | ||
116 | + sa_new.sa_flags = SA_SIGINFO; | ||
117 | + sa_new.sa_sigaction = sigill_handler; | ||
118 | + sigaction(SIGILL, &sa_new, &sa_old); | ||
119 | + | ||
120 | +#ifndef have_zba | ||
121 | + /* Probe for Zba: add.uw zero,zero,zero. */ | ||
122 | + got_sigill = 0; | ||
123 | + asm volatile(".insn r 0x3b, 0, 0x04, zero, zero, zero" : : : "memory"); | ||
124 | + have_zba = !got_sigill; | ||
125 | +#endif | ||
126 | + | ||
127 | +#ifndef have_zbb | ||
128 | + /* Probe for Zba: andn zero,zero,zero. */ | ||
129 | + got_sigill = 0; | ||
130 | + asm volatile(".insn r 0x33, 7, 0x20, zero, zero, zero" : : : "memory"); | ||
131 | + have_zbb = !got_sigill; | ||
132 | +#endif | ||
133 | + | ||
134 | +#ifndef have_zicond | ||
135 | + /* Probe for Zicond: czero.eqz zero,zero,zero. */ | ||
136 | + got_sigill = 0; | ||
137 | + asm volatile(".insn r 0x33, 5, 0x07, zero, zero, zero" : : : "memory"); | ||
138 | + have_zicond = !got_sigill; | ||
139 | +#endif | ||
140 | + | ||
141 | + sigaction(SIGILL, &sa_old, NULL); | ||
142 | +#endif | ||
143 | +} | ||
144 | + | ||
145 | static void tcg_target_init(TCGContext *s) | ||
21 | { | 146 | { |
22 | int i; | 147 | + tcg_target_detect_isa(); |
23 | for (i = 0; i < count; ++i) { | 148 | + |
24 | - p[i] = encode_i(OPC_ADDI, TCG_REG_ZERO, TCG_REG_ZERO, 0); | 149 | tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff; |
25 | + p[i] = OPC_NOP; | 150 | tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff; |
26 | } | ||
27 | } | ||
28 | 151 | ||
29 | -- | 152 | -- |
30 | 2.34.1 | 153 | 2.34.1 |
31 | |||
32 | diff view generated by jsdifflib |
1 | The old implementation replaces two insns, swapping between | 1 | Acked-by: Alistair Francis <alistair.francis@wdc.com> |
---|---|---|---|
2 | 2 | Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> | |
3 | b <dest> | ||
4 | nop | ||
5 | br x30 | ||
6 | and | ||
7 | adrp x30, <dest> | ||
8 | addi x30, x30, lo12:<dest> | ||
9 | br x30 | ||
10 | |||
11 | There is a race condition in which a thread could be stopped at | ||
12 | the PC of the second insn, and when restarted does not see the | ||
13 | complete address computation and branches to nowhere. | ||
14 | |||
15 | The new implemetation replaces only one insn, swapping between | ||
16 | |||
17 | b <dest> | ||
18 | br tmp | ||
19 | and | ||
20 | ldr tmp, <jmp_addr> | ||
21 | br tmp | ||
22 | |||
23 | Reported-by: hev <r@hev.cc> | ||
24 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
25 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 3 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
26 | --- | 4 | --- |
27 | tcg/aarch64/tcg-target.h | 2 +- | 5 | tcg/riscv/tcg-target-con-set.h | 1 + |
28 | tcg/aarch64/tcg-target.c.inc | 66 +++++++++++++++--------------------- | 6 | tcg/riscv/tcg-target-con-str.h | 1 + |
29 | 2 files changed, 29 insertions(+), 39 deletions(-) | 7 | tcg/riscv/tcg-target.h | 12 +++++----- |
8 | tcg/riscv/tcg-target.c.inc | 41 ++++++++++++++++++++++++++++++++++ | ||
9 | 4 files changed, 49 insertions(+), 6 deletions(-) | ||
30 | 10 | ||
31 | diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h | 11 | diff --git a/tcg/riscv/tcg-target-con-set.h b/tcg/riscv/tcg-target-con-set.h |
32 | index XXXXXXX..XXXXXXX 100644 | 12 | index XXXXXXX..XXXXXXX 100644 |
33 | --- a/tcg/aarch64/tcg-target.h | 13 | --- a/tcg/riscv/tcg-target-con-set.h |
34 | +++ b/tcg/aarch64/tcg-target.h | 14 | +++ b/tcg/riscv/tcg-target-con-set.h |
35 | @@ -XXX,XX +XXX,XX @@ | 15 | @@ -XXX,XX +XXX,XX @@ C_O0_I2(rZ, rZ) |
36 | 16 | C_O1_I1(r, r) | |
37 | #define TCG_TARGET_INSN_UNIT_SIZE 4 | 17 | C_O1_I2(r, r, ri) |
38 | #define TCG_TARGET_TLB_DISPLACEMENT_BITS 24 | 18 | C_O1_I2(r, r, rI) |
39 | -#define MAX_CODE_GEN_BUFFER_SIZE (2 * GiB) | 19 | +C_O1_I2(r, r, rJ) |
40 | +#define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1) | 20 | C_O1_I2(r, rZ, rN) |
41 | 21 | C_O1_I2(r, rZ, rZ) | |
42 | typedef enum { | 22 | C_O2_I4(r, r, rZ, rZ, rM, rM) |
43 | TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3, | 23 | diff --git a/tcg/riscv/tcg-target-con-str.h b/tcg/riscv/tcg-target-con-str.h |
44 | diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc | ||
45 | index XXXXXXX..XXXXXXX 100644 | 24 | index XXXXXXX..XXXXXXX 100644 |
46 | --- a/tcg/aarch64/tcg-target.c.inc | 25 | --- a/tcg/riscv/tcg-target-con-str.h |
47 | +++ b/tcg/aarch64/tcg-target.c.inc | 26 | +++ b/tcg/riscv/tcg-target-con-str.h |
48 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_call(TCGContext *s, const tcg_insn_unit *target, | 27 | @@ -XXX,XX +XXX,XX @@ REGS('r', ALL_GENERAL_REGS) |
49 | tcg_out_call_int(s, target); | 28 | * CONST(letter, TCG_CT_CONST_* bit set) |
29 | */ | ||
30 | CONST('I', TCG_CT_CONST_S12) | ||
31 | +CONST('J', TCG_CT_CONST_J12) | ||
32 | CONST('N', TCG_CT_CONST_N12) | ||
33 | CONST('M', TCG_CT_CONST_M12) | ||
34 | CONST('Z', TCG_CT_CONST_ZERO) | ||
35 | diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h | ||
36 | index XXXXXXX..XXXXXXX 100644 | ||
37 | --- a/tcg/riscv/tcg-target.h | ||
38 | +++ b/tcg/riscv/tcg-target.h | ||
39 | @@ -XXX,XX +XXX,XX @@ extern bool have_zbb; | ||
40 | #define TCG_TARGET_HAS_bswap32_i32 0 | ||
41 | #define TCG_TARGET_HAS_not_i32 1 | ||
42 | #define TCG_TARGET_HAS_neg_i32 1 | ||
43 | -#define TCG_TARGET_HAS_andc_i32 0 | ||
44 | -#define TCG_TARGET_HAS_orc_i32 0 | ||
45 | -#define TCG_TARGET_HAS_eqv_i32 0 | ||
46 | +#define TCG_TARGET_HAS_andc_i32 have_zbb | ||
47 | +#define TCG_TARGET_HAS_orc_i32 have_zbb | ||
48 | +#define TCG_TARGET_HAS_eqv_i32 have_zbb | ||
49 | #define TCG_TARGET_HAS_nand_i32 0 | ||
50 | #define TCG_TARGET_HAS_nor_i32 0 | ||
51 | #define TCG_TARGET_HAS_clz_i32 0 | ||
52 | @@ -XXX,XX +XXX,XX @@ extern bool have_zbb; | ||
53 | #define TCG_TARGET_HAS_bswap64_i64 0 | ||
54 | #define TCG_TARGET_HAS_not_i64 1 | ||
55 | #define TCG_TARGET_HAS_neg_i64 1 | ||
56 | -#define TCG_TARGET_HAS_andc_i64 0 | ||
57 | -#define TCG_TARGET_HAS_orc_i64 0 | ||
58 | -#define TCG_TARGET_HAS_eqv_i64 0 | ||
59 | +#define TCG_TARGET_HAS_andc_i64 have_zbb | ||
60 | +#define TCG_TARGET_HAS_orc_i64 have_zbb | ||
61 | +#define TCG_TARGET_HAS_eqv_i64 have_zbb | ||
62 | #define TCG_TARGET_HAS_nand_i64 0 | ||
63 | #define TCG_TARGET_HAS_nor_i64 0 | ||
64 | #define TCG_TARGET_HAS_clz_i64 0 | ||
65 | diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc | ||
66 | index XXXXXXX..XXXXXXX 100644 | ||
67 | --- a/tcg/riscv/tcg-target.c.inc | ||
68 | +++ b/tcg/riscv/tcg-target.c.inc | ||
69 | @@ -XXX,XX +XXX,XX @@ static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot) | ||
70 | #define TCG_CT_CONST_S12 0x200 | ||
71 | #define TCG_CT_CONST_N12 0x400 | ||
72 | #define TCG_CT_CONST_M12 0x800 | ||
73 | +#define TCG_CT_CONST_J12 0x1000 | ||
74 | |||
75 | #define ALL_GENERAL_REGS MAKE_64BIT_MASK(0, 32) | ||
76 | |||
77 | @@ -XXX,XX +XXX,XX @@ static bool tcg_target_const_match(int64_t val, TCGType type, int ct) | ||
78 | if ((ct & TCG_CT_CONST_M12) && val >= -0x7ff && val <= 0x7ff) { | ||
79 | return 1; | ||
80 | } | ||
81 | + /* | ||
82 | + * Inverse of sign extended from 12 bits: ~[-0x800, 0x7ff]. | ||
83 | + * Used to map ANDN back to ANDI, etc. | ||
84 | + */ | ||
85 | + if ((ct & TCG_CT_CONST_J12) && ~val >= -0x800 && ~val <= 0x7ff) { | ||
86 | + return 1; | ||
87 | + } | ||
88 | return 0; | ||
50 | } | 89 | } |
51 | 90 | ||
52 | -void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | 91 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, |
53 | - uintptr_t jmp_rx, uintptr_t jmp_rw) | 92 | } |
54 | -{ | 93 | break; |
55 | - uintptr_t addr = tb->jmp_target_addr[n]; | 94 | |
56 | - tcg_insn_unit i1, i2; | 95 | + case INDEX_op_andc_i32: |
57 | - TCGType rt = TCG_TYPE_I64; | 96 | + case INDEX_op_andc_i64: |
58 | - TCGReg rd = TCG_REG_TMP; | 97 | + if (c2) { |
59 | - uint64_t pair; | 98 | + tcg_out_opc_imm(s, OPC_ANDI, a0, a1, ~a2); |
60 | - | 99 | + } else { |
61 | - ptrdiff_t offset = addr - jmp_rx; | 100 | + tcg_out_opc_reg(s, OPC_ANDN, a0, a1, a2); |
62 | - | 101 | + } |
63 | - if (offset == sextract64(offset, 0, 26)) { | 102 | + break; |
64 | - i1 = I3206_B | ((offset >> 2) & 0x3ffffff); | 103 | + case INDEX_op_orc_i32: |
65 | - i2 = NOP; | 104 | + case INDEX_op_orc_i64: |
66 | - } else { | 105 | + if (c2) { |
67 | - offset = (addr >> 12) - (jmp_rx >> 12); | 106 | + tcg_out_opc_imm(s, OPC_ORI, a0, a1, ~a2); |
68 | - | 107 | + } else { |
69 | - /* patch ADRP */ | 108 | + tcg_out_opc_reg(s, OPC_ORN, a0, a1, a2); |
70 | - i1 = I3406_ADRP | (offset & 3) << 29 | (offset & 0x1ffffc) << (5 - 2) | rd; | 109 | + } |
71 | - /* patch ADDI */ | 110 | + break; |
72 | - i2 = I3401_ADDI | rt << 31 | (addr & 0xfff) << 10 | rd << 5 | rd; | 111 | + case INDEX_op_eqv_i32: |
73 | - } | 112 | + case INDEX_op_eqv_i64: |
74 | - pair = (uint64_t)i2 << 32 | i1; | 113 | + if (c2) { |
75 | - qatomic_set((uint64_t *)jmp_rw, pair); | 114 | + tcg_out_opc_imm(s, OPC_XORI, a0, a1, ~a2); |
76 | - flush_idcache_range(jmp_rx, jmp_rw, 8); | 115 | + } else { |
77 | -} | 116 | + tcg_out_opc_reg(s, OPC_XNOR, a0, a1, a2); |
78 | - | 117 | + } |
79 | static inline void tcg_out_goto_label(TCGContext *s, TCGLabel *l) | 118 | + break; |
80 | { | ||
81 | if (!l->has_value) { | ||
82 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) | ||
83 | static void tcg_out_goto_tb(TCGContext *s, int which) | ||
84 | { | ||
85 | /* | ||
86 | - * Ensure that ADRP+ADD are 8-byte aligned so that an atomic | ||
87 | - * write can be used to patch the target address. | ||
88 | + * Direct branch, or indirect address load, will be patched | ||
89 | + * by tb_target_set_jmp_target. Assert indirect load offset | ||
90 | + * in range early, regardless of direct branch distance. | ||
91 | */ | ||
92 | - if ((uintptr_t)s->code_ptr & 7) { | ||
93 | - tcg_out32(s, NOP); | ||
94 | - } | ||
95 | + intptr_t i_off = tcg_pcrel_diff(s, (void *)get_jmp_target_addr(s, which)); | ||
96 | + tcg_debug_assert(i_off == sextract64(i_off, 0, 21)); | ||
97 | + | 119 | + |
98 | set_jmp_insn_offset(s, which); | 120 | case INDEX_op_not_i32: |
99 | - /* | 121 | case INDEX_op_not_i64: |
100 | - * actual branch destination will be patched by | 122 | tcg_out_opc_imm(s, OPC_XORI, a0, a1, -1); |
101 | - * tb_target_set_jmp_target later | 123 | @@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) |
102 | - */ | 124 | case INDEX_op_xor_i64: |
103 | - tcg_out_insn(s, 3406, ADRP, TCG_REG_TMP, 0); | 125 | return C_O1_I2(r, r, rI); |
104 | - tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64, TCG_REG_TMP, TCG_REG_TMP, 0); | 126 | |
105 | + tcg_out32(s, I3206_B); | 127 | + case INDEX_op_andc_i32: |
106 | tcg_out_insn(s, 3207, BR, TCG_REG_TMP); | 128 | + case INDEX_op_andc_i64: |
107 | set_jmp_reset_offset(s, which); | 129 | + case INDEX_op_orc_i32: |
108 | } | 130 | + case INDEX_op_orc_i64: |
109 | 131 | + case INDEX_op_eqv_i32: | |
110 | +void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | 132 | + case INDEX_op_eqv_i64: |
111 | + uintptr_t jmp_rx, uintptr_t jmp_rw) | 133 | + return C_O1_I2(r, r, rJ); |
112 | +{ | ||
113 | + uintptr_t d_addr = tb->jmp_target_addr[n]; | ||
114 | + ptrdiff_t d_offset = d_addr - jmp_rx; | ||
115 | + tcg_insn_unit insn; | ||
116 | + | 134 | + |
117 | + /* Either directly branch, or indirect branch load. */ | 135 | case INDEX_op_sub_i32: |
118 | + if (d_offset == sextract64(d_offset, 0, 28)) { | 136 | case INDEX_op_sub_i64: |
119 | + insn = deposit32(I3206_B, 0, 26, d_offset >> 2); | 137 | return C_O1_I2(r, rZ, rN); |
120 | + } else { | ||
121 | + uintptr_t i_addr = (uintptr_t)&tb->jmp_target_addr[n]; | ||
122 | + ptrdiff_t i_offset = i_addr - jmp_rx; | ||
123 | + | ||
124 | + /* Note that we asserted this in range in tcg_out_goto_tb. */ | ||
125 | + insn = deposit32(I3305_LDR | TCG_REG_TMP, 0, 5, i_offset >> 2); | ||
126 | + } | ||
127 | + qatomic_set((uint32_t *)jmp_rw, insn); | ||
128 | + flush_idcache_range(jmp_rx, jmp_rw, 4); | ||
129 | +} | ||
130 | + | ||
131 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
132 | const TCGArg args[TCG_MAX_OP_ARGS], | ||
133 | const int const_args[TCG_MAX_OP_ARGS]) | ||
134 | -- | 138 | -- |
135 | 2.34.1 | 139 | 2.34.1 |
136 | |||
137 | diff view generated by jsdifflib |
1 | Now that tcg can handle direct and indirect goto_tb | 1 | Acked-by: Alistair Francis <alistair.francis@wdc.com> |
---|---|---|---|
2 | simultaneously, we can optimistically leave space for | 2 | Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> |
3 | a direct branch and fall back to loading the pointer | ||
4 | from the TB for an indirect branch. | ||
5 | |||
6 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
7 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 3 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
8 | --- | 4 | --- |
9 | tcg/arm/tcg-target.c.inc | 52 ++++++++++++++++++++++++++++------------ | 5 | tcg/riscv/tcg-target.c.inc | 32 ++++++++++++++++++++++++-------- |
10 | 1 file changed, 37 insertions(+), 15 deletions(-) | 6 | 1 file changed, 24 insertions(+), 8 deletions(-) |
11 | 7 | ||
12 | diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc | 8 | diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc |
13 | index XXXXXXX..XXXXXXX 100644 | 9 | index XXXXXXX..XXXXXXX 100644 |
14 | --- a/tcg/arm/tcg-target.c.inc | 10 | --- a/tcg/riscv/tcg-target.c.inc |
15 | +++ b/tcg/arm/tcg-target.c.inc | 11 | +++ b/tcg/riscv/tcg-target.c.inc |
16 | @@ -XXX,XX +XXX,XX @@ typedef enum { | 12 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg) |
17 | ARITH_BIC = 0xe << 21, | 13 | |
18 | ARITH_MVN = 0xf << 21, | 14 | static void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg) |
19 | |||
20 | + INSN_B = 0x0a000000, | ||
21 | + | ||
22 | INSN_CLZ = 0x016f0f10, | ||
23 | INSN_RBIT = 0x06ff0f30, | ||
24 | |||
25 | @@ -XXX,XX +XXX,XX @@ static bool tcg_target_const_match(int64_t val, TCGType type, int ct) | ||
26 | |||
27 | static void tcg_out_b_imm(TCGContext *s, ARMCond cond, int32_t offset) | ||
28 | { | 15 | { |
29 | - tcg_out32(s, (cond << 28) | 0x0a000000 | | 16 | - tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16); |
30 | + tcg_out32(s, (cond << 28) | INSN_B | | 17 | - tcg_out_opc_imm(s, OPC_SRLIW, ret, ret, 16); |
31 | (((offset - 8) >> 2) & 0x00ffffff)); | 18 | + if (have_zbb) { |
19 | + tcg_out_opc_reg(s, OPC_ZEXT_H, ret, arg, TCG_REG_ZERO); | ||
20 | + } else { | ||
21 | + tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16); | ||
22 | + tcg_out_opc_imm(s, OPC_SRLIW, ret, ret, 16); | ||
23 | + } | ||
32 | } | 24 | } |
33 | 25 | ||
34 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg) | 26 | static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg) |
35 | |||
36 | static void tcg_out_goto_tb(TCGContext *s, int which) | ||
37 | { | 27 | { |
38 | - /* Indirect jump method */ | 28 | - tcg_out_opc_imm(s, OPC_SLLI, ret, arg, 32); |
39 | - intptr_t ptr, dif, dil; | 29 | - tcg_out_opc_imm(s, OPC_SRLI, ret, ret, 32); |
40 | - TCGReg base = TCG_REG_PC; | 30 | + if (have_zba) { |
41 | + uintptr_t i_addr; | 31 | + tcg_out_opc_reg(s, OPC_ADD_UW, ret, arg, TCG_REG_ZERO); |
42 | + intptr_t i_disp; | ||
43 | |||
44 | - ptr = get_jmp_target_addr(s, which); | ||
45 | - dif = tcg_pcrel_diff(s, (void *)ptr) - 8; | ||
46 | - dil = sextract32(dif, 0, 12); | ||
47 | - if (dif != dil) { | ||
48 | + /* Direct branch will be patched by tb_target_set_jmp_target. */ | ||
49 | + set_jmp_insn_offset(s, which); | ||
50 | + tcg_out32(s, INSN_NOP); | ||
51 | + | ||
52 | + /* When branch is out of range, fall through to indirect. */ | ||
53 | + i_addr = get_jmp_target_addr(s, which); | ||
54 | + i_disp = tcg_pcrel_diff(s, (void *)i_addr) - 8; | ||
55 | + tcg_debug_assert(i_disp < 0); | ||
56 | + if (i_disp >= -0xfff) { | ||
57 | + tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, i_disp); | ||
58 | + } else { | 32 | + } else { |
59 | /* | 33 | + tcg_out_opc_imm(s, OPC_SLLI, ret, arg, 32); |
60 | * The TB is close, but outside the 12 bits addressable by | 34 | + tcg_out_opc_imm(s, OPC_SRLI, ret, ret, 32); |
61 | * the load. We can extend this to 20 bits with a sub of a | 35 | + } |
62 | - * shifted immediate from pc. In the vastly unlikely event | ||
63 | - * the code requires more than 1MB, we'll use 2 insns and | ||
64 | - * be no worse off. | ||
65 | + * shifted immediate from pc. | ||
66 | */ | ||
67 | - base = TCG_REG_R0; | ||
68 | - tcg_out_movi32(s, COND_AL, base, ptr - dil); | ||
69 | + int h = -i_disp; | ||
70 | + int l = h & 0xfff; | ||
71 | + | ||
72 | + h = encode_imm_nofail(h - l); | ||
73 | + tcg_out_dat_imm(s, COND_AL, ARITH_SUB, TCG_REG_R0, TCG_REG_PC, h); | ||
74 | + tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_R0, l); | ||
75 | } | ||
76 | - tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, base, dil); | ||
77 | set_jmp_reset_offset(s, which); | ||
78 | } | 36 | } |
79 | 37 | ||
80 | void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | 38 | static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) |
81 | uintptr_t jmp_rx, uintptr_t jmp_rw) | ||
82 | { | 39 | { |
83 | - /* Always indirect, nothing to do */ | 40 | - tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 24); |
84 | + uintptr_t addr = tb->jmp_target_addr[n]; | 41 | - tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 24); |
85 | + ptrdiff_t offset = addr - (jmp_rx + 8); | 42 | + if (have_zbb) { |
86 | + tcg_insn_unit insn; | 43 | + tcg_out_opc_imm(s, OPC_SEXT_B, ret, arg, 0); |
87 | + | ||
88 | + /* Either directly branch, or fall through to indirect branch. */ | ||
89 | + if (offset == sextract64(offset, 0, 26)) { | ||
90 | + /* B <addr> */ | ||
91 | + insn = deposit32((COND_AL << 28) | INSN_B, 0, 24, offset >> 2); | ||
92 | + } else { | 44 | + } else { |
93 | + insn = INSN_NOP; | 45 | + tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 24); |
46 | + tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 24); | ||
94 | + } | 47 | + } |
95 | + | ||
96 | + qatomic_set((uint32_t *)jmp_rw, insn); | ||
97 | + flush_idcache_range(jmp_rx, jmp_rw, 4); | ||
98 | } | 48 | } |
99 | 49 | ||
100 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 50 | static void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg) |
51 | { | ||
52 | - tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16); | ||
53 | - tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 16); | ||
54 | + if (have_zbb) { | ||
55 | + tcg_out_opc_imm(s, OPC_SEXT_H, ret, arg, 0); | ||
56 | + } else { | ||
57 | + tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16); | ||
58 | + tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 16); | ||
59 | + } | ||
60 | } | ||
61 | |||
62 | static void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg) | ||
101 | -- | 63 | -- |
102 | 2.34.1 | 64 | 2.34.1 |
103 | |||
104 | diff view generated by jsdifflib |
1 | Now that tcg can handle direct and indirect goto_tb simultaneously, | 1 | The instruction is a combined zero-extend and add. |
---|---|---|---|
2 | we can optimistically leave space for a direct branch and fall back | 2 | Use it for exactly that. |
3 | to loading the pointer from the TB for an indirect branch. | ||
4 | 3 | ||
5 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | 4 | Acked-by: Alistair Francis <alistair.francis@wdc.com> |
5 | Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> | ||
6 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 6 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
7 | --- | 7 | --- |
8 | tcg/riscv/tcg-target.c.inc | 19 +++++++++++++++++-- | 8 | tcg/riscv/tcg-target.c.inc | 33 ++++++++++++++++++++++----------- |
9 | 1 file changed, 17 insertions(+), 2 deletions(-) | 9 | 1 file changed, 22 insertions(+), 11 deletions(-) |
10 | 10 | ||
11 | diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc | 11 | diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc |
12 | index XXXXXXX..XXXXXXX 100644 | 12 | index XXXXXXX..XXXXXXX 100644 |
13 | --- a/tcg/riscv/tcg-target.c.inc | 13 | --- a/tcg/riscv/tcg-target.c.inc |
14 | +++ b/tcg/riscv/tcg-target.c.inc | 14 | +++ b/tcg/riscv/tcg-target.c.inc |
15 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) | 15 | @@ -XXX,XX +XXX,XX @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase, |
16 | 16 | tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP0, TCG_REG_TMP1, 0); | |
17 | static void tcg_out_goto_tb(TCGContext *s, int which) | 17 | |
18 | { | 18 | /* TLB Hit - translate address using addend. */ |
19 | - /* indirect jump method */ | 19 | - addr_adj = addr_reg; |
20 | + /* Direct branch will be patched by tb_target_set_jmp_target. */ | 20 | - if (TARGET_LONG_BITS == 32) { |
21 | + set_jmp_insn_offset(s, which); | 21 | - addr_adj = TCG_REG_TMP0; |
22 | + tcg_out32(s, OPC_JAL); | 22 | - tcg_out_ext32u(s, addr_adj, addr_reg); |
23 | + if (TARGET_LONG_BITS == 64) { | ||
24 | + tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2); | ||
25 | + } else if (have_zba) { | ||
26 | + tcg_out_opc_reg(s, OPC_ADD_UW, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2); | ||
27 | + } else { | ||
28 | + tcg_out_ext32u(s, TCG_REG_TMP0, addr_reg); | ||
29 | + tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_REG_TMP0, TCG_REG_TMP2); | ||
30 | } | ||
31 | - tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_REG_TMP2, addr_adj); | ||
32 | *pbase = TCG_REG_TMP0; | ||
33 | #else | ||
34 | + TCGReg base; | ||
23 | + | 35 | + |
24 | + /* When branch is out of range, fall through to indirect. */ | 36 | if (a_mask) { |
25 | tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO, | 37 | ldst = new_ldst_label(s); |
26 | get_jmp_target_addr(s, which)); | 38 | ldst->is_ld = is_ld; |
27 | tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_TMP0, 0); | 39 | @@ -XXX,XX +XXX,XX @@ static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase, |
28 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_goto_tb(TCGContext *s, int which) | 40 | tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP1, TCG_REG_ZERO, 0); |
29 | void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | 41 | } |
30 | uintptr_t jmp_rx, uintptr_t jmp_rw) | 42 | |
31 | { | 43 | - TCGReg base = addr_reg; |
32 | - /* Always indirect, nothing to do */ | 44 | - if (TARGET_LONG_BITS == 32) { |
33 | + uintptr_t addr = tb->jmp_target_addr[n]; | 45 | - tcg_out_ext32u(s, TCG_REG_TMP0, base); |
34 | + ptrdiff_t offset = addr - jmp_rx; | 46 | - base = TCG_REG_TMP0; |
35 | + tcg_insn_unit insn; | 47 | - } |
36 | + | 48 | if (guest_base != 0) { |
37 | + /* Either directly branch, or fall through to indirect branch. */ | 49 | - tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_GUEST_BASE_REG, base); |
38 | + if (offset == sextreg(offset, 0, 20)) { | 50 | base = TCG_REG_TMP0; |
39 | + insn = encode_uj(OPC_JAL, TCG_REG_ZERO, offset); | 51 | + if (TARGET_LONG_BITS == 64) { |
52 | + tcg_out_opc_reg(s, OPC_ADD, base, addr_reg, TCG_GUEST_BASE_REG); | ||
53 | + } else if (have_zba) { | ||
54 | + tcg_out_opc_reg(s, OPC_ADD_UW, base, addr_reg, TCG_GUEST_BASE_REG); | ||
55 | + } else { | ||
56 | + tcg_out_ext32u(s, base, addr_reg); | ||
57 | + tcg_out_opc_reg(s, OPC_ADD, base, base, TCG_GUEST_BASE_REG); | ||
58 | + } | ||
59 | + } else if (TARGET_LONG_BITS == 64) { | ||
60 | + base = addr_reg; | ||
40 | + } else { | 61 | + } else { |
41 | + insn = OPC_NOP; | 62 | + base = TCG_REG_TMP0; |
42 | + } | 63 | + tcg_out_ext32u(s, base, addr_reg); |
43 | + qatomic_set((uint32_t *)jmp_rw, insn); | 64 | } |
44 | + flush_idcache_range(jmp_rx, jmp_rw, 4); | 65 | *pbase = base; |
45 | } | 66 | #endif |
46 | |||
47 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
48 | -- | 67 | -- |
49 | 2.34.1 | 68 | 2.34.1 |
50 | |||
51 | diff view generated by jsdifflib |
1 | Test TCG_TARGET_HAS_direct_jump instead of testing an | 1 | Acked-by: Alistair Francis <alistair.francis@wdc.com> |
---|---|---|---|
2 | implementation pointer. | 2 | Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> |
3 | |||
4 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
5 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> | ||
6 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 3 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
7 | --- | 4 | --- |
8 | tcg/aarch64/tcg-target.c.inc | 2 +- | 5 | tcg/riscv/tcg-target.h | 4 ++-- |
9 | tcg/arm/tcg-target.c.inc | 2 +- | 6 | tcg/riscv/tcg-target.c.inc | 34 ++++++++++++++++++++++++++++++++++ |
10 | tcg/loongarch64/tcg-target.c.inc | 2 +- | 7 | 2 files changed, 36 insertions(+), 2 deletions(-) |
11 | tcg/mips/tcg-target.c.inc | 2 +- | ||
12 | tcg/riscv/tcg-target.c.inc | 2 +- | ||
13 | tcg/tci/tcg-target.c.inc | 2 +- | ||
14 | 6 files changed, 6 insertions(+), 6 deletions(-) | ||
15 | 8 | ||
16 | diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc | 9 | diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h |
17 | index XXXXXXX..XXXXXXX 100644 | 10 | index XXXXXXX..XXXXXXX 100644 |
18 | --- a/tcg/aarch64/tcg-target.c.inc | 11 | --- a/tcg/riscv/tcg-target.h |
19 | +++ b/tcg/aarch64/tcg-target.c.inc | 12 | +++ b/tcg/riscv/tcg-target.h |
20 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 13 | @@ -XXX,XX +XXX,XX @@ extern bool have_zbb; |
21 | 14 | #define TCG_TARGET_HAS_div_i32 1 | |
22 | switch (opc) { | 15 | #define TCG_TARGET_HAS_rem_i32 1 |
23 | case INDEX_op_goto_tb: | 16 | #define TCG_TARGET_HAS_div2_i32 0 |
24 | - tcg_debug_assert(s->tb_jmp_insn_offset != NULL); | 17 | -#define TCG_TARGET_HAS_rot_i32 0 |
25 | + qemu_build_assert(TCG_TARGET_HAS_direct_jump); | 18 | +#define TCG_TARGET_HAS_rot_i32 have_zbb |
26 | /* | 19 | #define TCG_TARGET_HAS_deposit_i32 0 |
27 | * Ensure that ADRP+ADD are 8-byte aligned so that an atomic | 20 | #define TCG_TARGET_HAS_extract_i32 0 |
28 | * write can be used to patch the target address. | 21 | #define TCG_TARGET_HAS_sextract_i32 0 |
29 | diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc | 22 | @@ -XXX,XX +XXX,XX @@ extern bool have_zbb; |
30 | index XXXXXXX..XXXXXXX 100644 | 23 | #define TCG_TARGET_HAS_div_i64 1 |
31 | --- a/tcg/arm/tcg-target.c.inc | 24 | #define TCG_TARGET_HAS_rem_i64 1 |
32 | +++ b/tcg/arm/tcg-target.c.inc | 25 | #define TCG_TARGET_HAS_div2_i64 0 |
33 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 26 | -#define TCG_TARGET_HAS_rot_i64 0 |
34 | intptr_t ptr, dif, dil; | 27 | +#define TCG_TARGET_HAS_rot_i64 have_zbb |
35 | TCGReg base = TCG_REG_PC; | 28 | #define TCG_TARGET_HAS_deposit_i64 0 |
36 | 29 | #define TCG_TARGET_HAS_extract_i64 0 | |
37 | - tcg_debug_assert(s->tb_jmp_insn_offset == 0); | 30 | #define TCG_TARGET_HAS_sextract_i64 0 |
38 | + qemu_build_assert(!TCG_TARGET_HAS_direct_jump); | ||
39 | ptr = (intptr_t)tcg_splitwx_to_rx(s->tb_jmp_target_addr + args[0]); | ||
40 | dif = tcg_pcrel_diff(s, (void *)ptr) - 8; | ||
41 | dil = sextract32(dif, 0, 12); | ||
42 | diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc | ||
43 | index XXXXXXX..XXXXXXX 100644 | ||
44 | --- a/tcg/loongarch64/tcg-target.c.inc | ||
45 | +++ b/tcg/loongarch64/tcg-target.c.inc | ||
46 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
47 | |||
48 | switch (opc) { | ||
49 | case INDEX_op_goto_tb: | ||
50 | - tcg_debug_assert(s->tb_jmp_insn_offset != NULL); | ||
51 | + qemu_build_assert(TCG_TARGET_HAS_direct_jump); | ||
52 | /* | ||
53 | * Ensure that patch area is 8-byte aligned so that an | ||
54 | * atomic write can be used to patch the target address. | ||
55 | diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc | ||
56 | index XXXXXXX..XXXXXXX 100644 | ||
57 | --- a/tcg/mips/tcg-target.c.inc | ||
58 | +++ b/tcg/mips/tcg-target.c.inc | ||
59 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
60 | switch (opc) { | ||
61 | case INDEX_op_goto_tb: | ||
62 | /* indirect jump method */ | ||
63 | - tcg_debug_assert(s->tb_jmp_insn_offset == 0); | ||
64 | + qemu_build_assert(!TCG_TARGET_HAS_direct_jump); | ||
65 | tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_REG_ZERO, | ||
66 | (uintptr_t)(s->tb_jmp_target_addr + a0)); | ||
67 | tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0); | ||
68 | diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc | 31 | diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc |
69 | index XXXXXXX..XXXXXXX 100644 | 32 | index XXXXXXX..XXXXXXX 100644 |
70 | --- a/tcg/riscv/tcg-target.c.inc | 33 | --- a/tcg/riscv/tcg-target.c.inc |
71 | +++ b/tcg/riscv/tcg-target.c.inc | 34 | +++ b/tcg/riscv/tcg-target.c.inc |
72 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 35 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, |
73 | 36 | } | |
74 | switch (opc) { | 37 | break; |
75 | case INDEX_op_goto_tb: | 38 | |
76 | - assert(s->tb_jmp_insn_offset == 0); | 39 | + case INDEX_op_rotl_i32: |
77 | + qemu_build_assert(!TCG_TARGET_HAS_direct_jump); | 40 | + if (c2) { |
78 | /* indirect jump method */ | 41 | + tcg_out_opc_imm(s, OPC_RORIW, a0, a1, -a2 & 0x1f); |
79 | tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO, | 42 | + } else { |
80 | (uintptr_t)(s->tb_jmp_target_addr + a0)); | 43 | + tcg_out_opc_reg(s, OPC_ROLW, a0, a1, a2); |
81 | diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc | 44 | + } |
82 | index XXXXXXX..XXXXXXX 100644 | 45 | + break; |
83 | --- a/tcg/tci/tcg-target.c.inc | 46 | + case INDEX_op_rotl_i64: |
84 | +++ b/tcg/tci/tcg-target.c.inc | 47 | + if (c2) { |
85 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 48 | + tcg_out_opc_imm(s, OPC_RORI, a0, a1, -a2 & 0x3f); |
86 | 49 | + } else { | |
87 | switch (opc) { | 50 | + tcg_out_opc_reg(s, OPC_ROL, a0, a1, a2); |
88 | case INDEX_op_goto_tb: | 51 | + } |
89 | - tcg_debug_assert(s->tb_jmp_insn_offset == 0); | 52 | + break; |
90 | + qemu_build_assert(!TCG_TARGET_HAS_direct_jump); | 53 | + |
91 | /* indirect jump method. */ | 54 | + case INDEX_op_rotr_i32: |
92 | tcg_out_op_p(s, opc, s->tb_jmp_target_addr + args[0]); | 55 | + if (c2) { |
93 | set_jmp_reset_offset(s, args[0]); | 56 | + tcg_out_opc_imm(s, OPC_RORIW, a0, a1, a2 & 0x1f); |
57 | + } else { | ||
58 | + tcg_out_opc_reg(s, OPC_RORW, a0, a1, a2); | ||
59 | + } | ||
60 | + break; | ||
61 | + case INDEX_op_rotr_i64: | ||
62 | + if (c2) { | ||
63 | + tcg_out_opc_imm(s, OPC_RORI, a0, a1, a2 & 0x3f); | ||
64 | + } else { | ||
65 | + tcg_out_opc_reg(s, OPC_ROR, a0, a1, a2); | ||
66 | + } | ||
67 | + break; | ||
68 | + | ||
69 | case INDEX_op_add2_i32: | ||
70 | tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5], | ||
71 | const_args[4], const_args[5], false, true); | ||
72 | @@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) | ||
73 | case INDEX_op_shl_i32: | ||
74 | case INDEX_op_shr_i32: | ||
75 | case INDEX_op_sar_i32: | ||
76 | + case INDEX_op_rotl_i32: | ||
77 | + case INDEX_op_rotr_i32: | ||
78 | case INDEX_op_shl_i64: | ||
79 | case INDEX_op_shr_i64: | ||
80 | case INDEX_op_sar_i64: | ||
81 | + case INDEX_op_rotl_i64: | ||
82 | + case INDEX_op_rotr_i64: | ||
83 | return C_O1_I2(r, r, ri); | ||
84 | |||
85 | case INDEX_op_brcond_i32: | ||
94 | -- | 86 | -- |
95 | 2.34.1 | 87 | 2.34.1 |
96 | |||
97 | diff view generated by jsdifflib |
1 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | 1 | Acked-by: Alistair Francis <alistair.francis@wdc.com> |
---|---|---|---|
2 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> | 2 | Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> |
3 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 3 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
4 | --- | 4 | --- |
5 | include/tcg/tcg.h | 3 +++ | 5 | tcg/riscv/tcg-target.h | 10 +++++----- |
6 | tcg/aarch64/tcg-target.h | 4 ---- | 6 | tcg/riscv/tcg-target.c.inc | 29 +++++++++++++++++++++++++++++ |
7 | tcg/arm/tcg-target.h | 5 ----- | 7 | 2 files changed, 34 insertions(+), 5 deletions(-) |
8 | tcg/i386/tcg-target.h | 3 --- | ||
9 | tcg/loongarch64/tcg-target.h | 3 --- | ||
10 | tcg/mips/tcg-target.h | 5 ----- | ||
11 | tcg/ppc/tcg-target.h | 4 ---- | ||
12 | tcg/riscv/tcg-target.h | 4 ---- | ||
13 | tcg/s390x/tcg-target.h | 4 ---- | ||
14 | tcg/sparc64/tcg-target.h | 4 ---- | ||
15 | tcg/tci/tcg-target.h | 4 ---- | ||
16 | 11 files changed, 3 insertions(+), 40 deletions(-) | ||
17 | 8 | ||
18 | diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h | ||
19 | index XXXXXXX..XXXXXXX 100644 | ||
20 | --- a/include/tcg/tcg.h | ||
21 | +++ b/include/tcg/tcg.h | ||
22 | @@ -XXX,XX +XXX,XX @@ void tcg_func_start(TCGContext *s); | ||
23 | |||
24 | int tcg_gen_code(TCGContext *s, TranslationBlock *tb, target_ulong pc_start); | ||
25 | |||
26 | +void tb_target_set_jmp_target(const TranslationBlock *, int, | ||
27 | + uintptr_t, uintptr_t); | ||
28 | + | ||
29 | void tcg_set_frame(TCGContext *s, TCGReg reg, intptr_t start, intptr_t size); | ||
30 | |||
31 | TCGTemp *tcg_global_mem_new_internal(TCGType, TCGv_ptr, | ||
32 | diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h | ||
33 | index XXXXXXX..XXXXXXX 100644 | ||
34 | --- a/tcg/aarch64/tcg-target.h | ||
35 | +++ b/tcg/aarch64/tcg-target.h | ||
36 | @@ -XXX,XX +XXX,XX @@ typedef enum { | ||
37 | |||
38 | #define TCG_TARGET_DEFAULT_MO (0) | ||
39 | #define TCG_TARGET_HAS_MEMORY_BSWAP 0 | ||
40 | - | ||
41 | -void tb_target_set_jmp_target(const TranslationBlock *, int, | ||
42 | - uintptr_t, uintptr_t); | ||
43 | - | ||
44 | #define TCG_TARGET_NEED_LDST_LABELS | ||
45 | #define TCG_TARGET_NEED_POOL_LABELS | ||
46 | |||
47 | diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h | ||
48 | index XXXXXXX..XXXXXXX 100644 | ||
49 | --- a/tcg/arm/tcg-target.h | ||
50 | +++ b/tcg/arm/tcg-target.h | ||
51 | @@ -XXX,XX +XXX,XX @@ extern bool use_neon_instructions; | ||
52 | |||
53 | #define TCG_TARGET_DEFAULT_MO (0) | ||
54 | #define TCG_TARGET_HAS_MEMORY_BSWAP 0 | ||
55 | - | ||
56 | -/* not defined -- call should be eliminated at compile time */ | ||
57 | -void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | ||
58 | - uintptr_t, uintptr_t); | ||
59 | - | ||
60 | #define TCG_TARGET_NEED_LDST_LABELS | ||
61 | #define TCG_TARGET_NEED_POOL_LABELS | ||
62 | |||
63 | diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h | ||
64 | index XXXXXXX..XXXXXXX 100644 | ||
65 | --- a/tcg/i386/tcg-target.h | ||
66 | +++ b/tcg/i386/tcg-target.h | ||
67 | @@ -XXX,XX +XXX,XX @@ extern bool have_movbe; | ||
68 | #define TCG_TARGET_extract_i64_valid(ofs, len) \ | ||
69 | (((ofs) == 8 && (len) == 8) || ((ofs) + (len)) == 32) | ||
70 | |||
71 | -void tb_target_set_jmp_target(const TranslationBlock *, int, | ||
72 | - uintptr_t, uintptr_t); | ||
73 | - | ||
74 | /* This defines the natural memory order supported by this | ||
75 | * architecture before guarantees made by various barrier | ||
76 | * instructions. | ||
77 | diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h | ||
78 | index XXXXXXX..XXXXXXX 100644 | ||
79 | --- a/tcg/loongarch64/tcg-target.h | ||
80 | +++ b/tcg/loongarch64/tcg-target.h | ||
81 | @@ -XXX,XX +XXX,XX @@ typedef enum { | ||
82 | #define TCG_TARGET_HAS_muluh_i64 1 | ||
83 | #define TCG_TARGET_HAS_mulsh_i64 1 | ||
84 | |||
85 | -void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | ||
86 | - uintptr_t, uintptr_t); | ||
87 | - | ||
88 | #define TCG_TARGET_DEFAULT_MO (0) | ||
89 | |||
90 | #define TCG_TARGET_NEED_LDST_LABELS | ||
91 | diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h | ||
92 | index XXXXXXX..XXXXXXX 100644 | ||
93 | --- a/tcg/mips/tcg-target.h | ||
94 | +++ b/tcg/mips/tcg-target.h | ||
95 | @@ -XXX,XX +XXX,XX @@ extern bool use_mips32r2_instructions; | ||
96 | #define TCG_TARGET_DEFAULT_MO (0) | ||
97 | #define TCG_TARGET_HAS_MEMORY_BSWAP 1 | ||
98 | |||
99 | -/* not defined -- call should be eliminated at compile time */ | ||
100 | -void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | ||
101 | - uintptr_t, uintptr_t) | ||
102 | - QEMU_ERROR("code path is reachable"); | ||
103 | - | ||
104 | #define TCG_TARGET_NEED_LDST_LABELS | ||
105 | |||
106 | #endif | ||
107 | diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h | ||
108 | index XXXXXXX..XXXXXXX 100644 | ||
109 | --- a/tcg/ppc/tcg-target.h | ||
110 | +++ b/tcg/ppc/tcg-target.h | ||
111 | @@ -XXX,XX +XXX,XX @@ extern bool have_vsx; | ||
112 | #define TCG_TARGET_HAS_bitsel_vec have_vsx | ||
113 | #define TCG_TARGET_HAS_cmpsel_vec 0 | ||
114 | |||
115 | -void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | ||
116 | - uintptr_t, uintptr_t); | ||
117 | - | ||
118 | #define TCG_TARGET_DEFAULT_MO (0) | ||
119 | #define TCG_TARGET_HAS_MEMORY_BSWAP 1 | ||
120 | - | ||
121 | #define TCG_TARGET_NEED_LDST_LABELS | ||
122 | #define TCG_TARGET_NEED_POOL_LABELS | ||
123 | |||
124 | diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h | 9 | diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h |
125 | index XXXXXXX..XXXXXXX 100644 | 10 | index XXXXXXX..XXXXXXX 100644 |
126 | --- a/tcg/riscv/tcg-target.h | 11 | --- a/tcg/riscv/tcg-target.h |
127 | +++ b/tcg/riscv/tcg-target.h | 12 | +++ b/tcg/riscv/tcg-target.h |
128 | @@ -XXX,XX +XXX,XX @@ typedef enum { | 13 | @@ -XXX,XX +XXX,XX @@ extern bool have_zbb; |
129 | #define TCG_TARGET_HAS_mulsh_i64 1 | 14 | #define TCG_TARGET_HAS_ext16s_i32 1 |
130 | #endif | 15 | #define TCG_TARGET_HAS_ext8u_i32 1 |
131 | 16 | #define TCG_TARGET_HAS_ext16u_i32 1 | |
132 | -/* not defined -- call should be eliminated at compile time */ | 17 | -#define TCG_TARGET_HAS_bswap16_i32 0 |
133 | -void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | 18 | -#define TCG_TARGET_HAS_bswap32_i32 0 |
134 | - uintptr_t, uintptr_t); | 19 | +#define TCG_TARGET_HAS_bswap16_i32 have_zbb |
135 | - | 20 | +#define TCG_TARGET_HAS_bswap32_i32 have_zbb |
136 | #define TCG_TARGET_DEFAULT_MO (0) | 21 | #define TCG_TARGET_HAS_not_i32 1 |
137 | 22 | #define TCG_TARGET_HAS_neg_i32 1 | |
138 | #define TCG_TARGET_NEED_LDST_LABELS | 23 | #define TCG_TARGET_HAS_andc_i32 have_zbb |
139 | diff --git a/tcg/s390x/tcg-target.h b/tcg/s390x/tcg-target.h | 24 | @@ -XXX,XX +XXX,XX @@ extern bool have_zbb; |
25 | #define TCG_TARGET_HAS_ext8u_i64 1 | ||
26 | #define TCG_TARGET_HAS_ext16u_i64 1 | ||
27 | #define TCG_TARGET_HAS_ext32u_i64 1 | ||
28 | -#define TCG_TARGET_HAS_bswap16_i64 0 | ||
29 | -#define TCG_TARGET_HAS_bswap32_i64 0 | ||
30 | -#define TCG_TARGET_HAS_bswap64_i64 0 | ||
31 | +#define TCG_TARGET_HAS_bswap16_i64 have_zbb | ||
32 | +#define TCG_TARGET_HAS_bswap32_i64 have_zbb | ||
33 | +#define TCG_TARGET_HAS_bswap64_i64 have_zbb | ||
34 | #define TCG_TARGET_HAS_not_i64 1 | ||
35 | #define TCG_TARGET_HAS_neg_i64 1 | ||
36 | #define TCG_TARGET_HAS_andc_i64 have_zbb | ||
37 | diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc | ||
140 | index XXXXXXX..XXXXXXX 100644 | 38 | index XXXXXXX..XXXXXXX 100644 |
141 | --- a/tcg/s390x/tcg-target.h | 39 | --- a/tcg/riscv/tcg-target.c.inc |
142 | +++ b/tcg/s390x/tcg-target.h | 40 | +++ b/tcg/riscv/tcg-target.c.inc |
143 | @@ -XXX,XX +XXX,XX @@ extern uint64_t s390_facilities[3]; | 41 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, |
144 | #define TCG_TARGET_HAS_MEMORY_BSWAP 1 | 42 | } |
145 | 43 | break; | |
146 | #define TCG_TARGET_DEFAULT_MO (TCG_MO_ALL & ~TCG_MO_ST_LD) | 44 | |
147 | - | 45 | + case INDEX_op_bswap64_i64: |
148 | -void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | 46 | + tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0); |
149 | - uintptr_t jmp_rx, uintptr_t jmp_rw); | 47 | + break; |
150 | - | 48 | + case INDEX_op_bswap32_i32: |
151 | #define TCG_TARGET_NEED_LDST_LABELS | 49 | + a2 = 0; |
152 | #define TCG_TARGET_NEED_POOL_LABELS | 50 | + /* fall through */ |
153 | 51 | + case INDEX_op_bswap32_i64: | |
154 | diff --git a/tcg/sparc64/tcg-target.h b/tcg/sparc64/tcg-target.h | 52 | + tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0); |
155 | index XXXXXXX..XXXXXXX 100644 | 53 | + if (a2 & TCG_BSWAP_OZ) { |
156 | --- a/tcg/sparc64/tcg-target.h | 54 | + tcg_out_opc_imm(s, OPC_SRLI, a0, a0, 32); |
157 | +++ b/tcg/sparc64/tcg-target.h | 55 | + } else { |
158 | @@ -XXX,XX +XXX,XX @@ extern bool use_vis3_instructions; | 56 | + tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 32); |
159 | 57 | + } | |
160 | #define TCG_TARGET_DEFAULT_MO (0) | 58 | + break; |
161 | #define TCG_TARGET_HAS_MEMORY_BSWAP 1 | 59 | + case INDEX_op_bswap16_i64: |
162 | - | 60 | + case INDEX_op_bswap16_i32: |
163 | -void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | 61 | + tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0); |
164 | - uintptr_t, uintptr_t); | 62 | + if (a2 & TCG_BSWAP_OZ) { |
165 | - | 63 | + tcg_out_opc_imm(s, OPC_SRLI, a0, a0, 48); |
166 | #define TCG_TARGET_NEED_POOL_LABELS | 64 | + } else { |
167 | 65 | + tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 48); | |
168 | #endif | 66 | + } |
169 | diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h | 67 | + break; |
170 | index XXXXXXX..XXXXXXX 100644 | 68 | + |
171 | --- a/tcg/tci/tcg-target.h | 69 | case INDEX_op_add2_i32: |
172 | +++ b/tcg/tci/tcg-target.h | 70 | tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5], |
173 | @@ -XXX,XX +XXX,XX @@ typedef enum { | 71 | const_args[4], const_args[5], false, true); |
174 | 72 | @@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) | |
175 | #define TCG_TARGET_HAS_MEMORY_BSWAP 1 | 73 | case INDEX_op_extrl_i64_i32: |
176 | 74 | case INDEX_op_extrh_i64_i32: | |
177 | -/* not defined -- call should be eliminated at compile time */ | 75 | case INDEX_op_ext_i32_i64: |
178 | -void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | 76 | + case INDEX_op_bswap16_i32: |
179 | - uintptr_t, uintptr_t); | 77 | + case INDEX_op_bswap32_i32: |
180 | - | 78 | + case INDEX_op_bswap16_i64: |
181 | #endif /* TCG_TARGET_H */ | 79 | + case INDEX_op_bswap32_i64: |
80 | + case INDEX_op_bswap64_i64: | ||
81 | return C_O1_I1(r, r); | ||
82 | |||
83 | case INDEX_op_st8_i32: | ||
182 | -- | 84 | -- |
183 | 2.34.1 | 85 | 2.34.1 |
184 | |||
185 | diff view generated by jsdifflib |
1 | We now have the option to generate direct or indirect | 1 | Acked-by: Alistair Francis <alistair.francis@wdc.com> |
---|---|---|---|
2 | goto_tb depending on the dynamic displacement, thus | 2 | Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> |
3 | the define is no longer necessary or completely accurate. | ||
4 | |||
5 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
6 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 3 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
7 | --- | 4 | --- |
8 | tcg/aarch64/tcg-target.h | 1 - | 5 | tcg/riscv/tcg-target.h | 4 ++-- |
9 | tcg/arm/tcg-target.h | 1 - | 6 | tcg/riscv/tcg-target.c.inc | 9 +++++++++ |
10 | tcg/i386/tcg-target.h | 1 - | 7 | 2 files changed, 11 insertions(+), 2 deletions(-) |
11 | tcg/loongarch64/tcg-target.h | 1 - | ||
12 | tcg/mips/tcg-target.h | 1 - | ||
13 | tcg/ppc/tcg-target.h | 1 - | ||
14 | tcg/riscv/tcg-target.h | 1 - | ||
15 | tcg/s390x/tcg-target.h | 1 - | ||
16 | tcg/sparc64/tcg-target.h | 1 - | ||
17 | tcg/tci/tcg-target.h | 1 - | ||
18 | accel/tcg/cpu-exec.c | 23 +++++++++++------------ | ||
19 | tcg/tcg.c | 1 - | ||
20 | tcg/arm/tcg-target.c.inc | 1 - | ||
21 | tcg/mips/tcg-target.c.inc | 1 - | ||
22 | tcg/riscv/tcg-target.c.inc | 1 - | ||
23 | tcg/s390x/tcg-target.c.inc | 3 +++ | ||
24 | tcg/tci/tcg-target.c.inc | 1 - | ||
25 | 17 files changed, 14 insertions(+), 27 deletions(-) | ||
26 | 8 | ||
27 | diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h | ||
28 | index XXXXXXX..XXXXXXX 100644 | ||
29 | --- a/tcg/aarch64/tcg-target.h | ||
30 | +++ b/tcg/aarch64/tcg-target.h | ||
31 | @@ -XXX,XX +XXX,XX @@ typedef enum { | ||
32 | #define TCG_TARGET_HAS_muls2_i64 0 | ||
33 | #define TCG_TARGET_HAS_muluh_i64 1 | ||
34 | #define TCG_TARGET_HAS_mulsh_i64 1 | ||
35 | -#define TCG_TARGET_HAS_direct_jump 1 | ||
36 | |||
37 | #define TCG_TARGET_HAS_v64 1 | ||
38 | #define TCG_TARGET_HAS_v128 1 | ||
39 | diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h | ||
40 | index XXXXXXX..XXXXXXX 100644 | ||
41 | --- a/tcg/arm/tcg-target.h | ||
42 | +++ b/tcg/arm/tcg-target.h | ||
43 | @@ -XXX,XX +XXX,XX @@ extern bool use_neon_instructions; | ||
44 | #define TCG_TARGET_HAS_mulsh_i32 0 | ||
45 | #define TCG_TARGET_HAS_div_i32 use_idiv_instructions | ||
46 | #define TCG_TARGET_HAS_rem_i32 0 | ||
47 | -#define TCG_TARGET_HAS_direct_jump 0 | ||
48 | #define TCG_TARGET_HAS_qemu_st8_i32 0 | ||
49 | |||
50 | #define TCG_TARGET_HAS_v64 use_neon_instructions | ||
51 | diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h | ||
52 | index XXXXXXX..XXXXXXX 100644 | ||
53 | --- a/tcg/i386/tcg-target.h | ||
54 | +++ b/tcg/i386/tcg-target.h | ||
55 | @@ -XXX,XX +XXX,XX @@ extern bool have_movbe; | ||
56 | #define TCG_TARGET_HAS_muls2_i32 1 | ||
57 | #define TCG_TARGET_HAS_muluh_i32 0 | ||
58 | #define TCG_TARGET_HAS_mulsh_i32 0 | ||
59 | -#define TCG_TARGET_HAS_direct_jump 1 | ||
60 | |||
61 | #if TCG_TARGET_REG_BITS == 64 | ||
62 | /* Keep target addresses zero-extended in a register. */ | ||
63 | diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h | ||
64 | index XXXXXXX..XXXXXXX 100644 | ||
65 | --- a/tcg/loongarch64/tcg-target.h | ||
66 | +++ b/tcg/loongarch64/tcg-target.h | ||
67 | @@ -XXX,XX +XXX,XX @@ typedef enum { | ||
68 | #define TCG_TARGET_HAS_clz_i32 1 | ||
69 | #define TCG_TARGET_HAS_ctz_i32 1 | ||
70 | #define TCG_TARGET_HAS_ctpop_i32 0 | ||
71 | -#define TCG_TARGET_HAS_direct_jump 1 | ||
72 | #define TCG_TARGET_HAS_brcond2 0 | ||
73 | #define TCG_TARGET_HAS_setcond2 0 | ||
74 | #define TCG_TARGET_HAS_qemu_st8_i32 0 | ||
75 | diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h | ||
76 | index XXXXXXX..XXXXXXX 100644 | ||
77 | --- a/tcg/mips/tcg-target.h | ||
78 | +++ b/tcg/mips/tcg-target.h | ||
79 | @@ -XXX,XX +XXX,XX @@ extern bool use_mips32r2_instructions; | ||
80 | #define TCG_TARGET_HAS_muluh_i32 1 | ||
81 | #define TCG_TARGET_HAS_mulsh_i32 1 | ||
82 | #define TCG_TARGET_HAS_bswap32_i32 1 | ||
83 | -#define TCG_TARGET_HAS_direct_jump 0 | ||
84 | |||
85 | #if TCG_TARGET_REG_BITS == 64 | ||
86 | #define TCG_TARGET_HAS_add2_i32 0 | ||
87 | diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h | ||
88 | index XXXXXXX..XXXXXXX 100644 | ||
89 | --- a/tcg/ppc/tcg-target.h | ||
90 | +++ b/tcg/ppc/tcg-target.h | ||
91 | @@ -XXX,XX +XXX,XX @@ extern bool have_vsx; | ||
92 | #define TCG_TARGET_HAS_muls2_i32 0 | ||
93 | #define TCG_TARGET_HAS_muluh_i32 1 | ||
94 | #define TCG_TARGET_HAS_mulsh_i32 1 | ||
95 | -#define TCG_TARGET_HAS_direct_jump 1 | ||
96 | #define TCG_TARGET_HAS_qemu_st8_i32 0 | ||
97 | |||
98 | #if TCG_TARGET_REG_BITS == 64 | ||
99 | diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h | 9 | diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h |
100 | index XXXXXXX..XXXXXXX 100644 | 10 | index XXXXXXX..XXXXXXX 100644 |
101 | --- a/tcg/riscv/tcg-target.h | 11 | --- a/tcg/riscv/tcg-target.h |
102 | +++ b/tcg/riscv/tcg-target.h | 12 | +++ b/tcg/riscv/tcg-target.h |
103 | @@ -XXX,XX +XXX,XX @@ typedef enum { | 13 | @@ -XXX,XX +XXX,XX @@ extern bool have_zbb; |
14 | #define TCG_TARGET_HAS_nor_i32 0 | ||
104 | #define TCG_TARGET_HAS_clz_i32 0 | 15 | #define TCG_TARGET_HAS_clz_i32 0 |
105 | #define TCG_TARGET_HAS_ctz_i32 0 | 16 | #define TCG_TARGET_HAS_ctz_i32 0 |
106 | #define TCG_TARGET_HAS_ctpop_i32 0 | 17 | -#define TCG_TARGET_HAS_ctpop_i32 0 |
107 | -#define TCG_TARGET_HAS_direct_jump 0 | 18 | +#define TCG_TARGET_HAS_ctpop_i32 have_zbb |
108 | #define TCG_TARGET_HAS_brcond2 1 | 19 | #define TCG_TARGET_HAS_brcond2 1 |
109 | #define TCG_TARGET_HAS_setcond2 1 | 20 | #define TCG_TARGET_HAS_setcond2 1 |
110 | #define TCG_TARGET_HAS_qemu_st8_i32 0 | 21 | #define TCG_TARGET_HAS_qemu_st8_i32 0 |
111 | diff --git a/tcg/s390x/tcg-target.h b/tcg/s390x/tcg-target.h | 22 | @@ -XXX,XX +XXX,XX @@ extern bool have_zbb; |
112 | index XXXXXXX..XXXXXXX 100644 | 23 | #define TCG_TARGET_HAS_nor_i64 0 |
113 | --- a/tcg/s390x/tcg-target.h | 24 | #define TCG_TARGET_HAS_clz_i64 0 |
114 | +++ b/tcg/s390x/tcg-target.h | 25 | #define TCG_TARGET_HAS_ctz_i64 0 |
115 | @@ -XXX,XX +XXX,XX @@ extern uint64_t s390_facilities[3]; | 26 | -#define TCG_TARGET_HAS_ctpop_i64 0 |
116 | #define TCG_TARGET_HAS_mulsh_i32 0 | 27 | +#define TCG_TARGET_HAS_ctpop_i64 have_zbb |
117 | #define TCG_TARGET_HAS_extrl_i64_i32 0 | 28 | #define TCG_TARGET_HAS_add2_i64 1 |
118 | #define TCG_TARGET_HAS_extrh_i64_i32 0 | 29 | #define TCG_TARGET_HAS_sub2_i64 1 |
119 | -#define TCG_TARGET_HAS_direct_jump 1 | 30 | #define TCG_TARGET_HAS_mulu2_i64 0 |
120 | #define TCG_TARGET_HAS_qemu_st8_i32 0 | ||
121 | |||
122 | #define TCG_TARGET_HAS_div2_i64 1 | ||
123 | diff --git a/tcg/sparc64/tcg-target.h b/tcg/sparc64/tcg-target.h | ||
124 | index XXXXXXX..XXXXXXX 100644 | ||
125 | --- a/tcg/sparc64/tcg-target.h | ||
126 | +++ b/tcg/sparc64/tcg-target.h | ||
127 | @@ -XXX,XX +XXX,XX @@ extern bool use_vis3_instructions; | ||
128 | #define TCG_TARGET_HAS_muls2_i32 1 | ||
129 | #define TCG_TARGET_HAS_muluh_i32 0 | ||
130 | #define TCG_TARGET_HAS_mulsh_i32 0 | ||
131 | -#define TCG_TARGET_HAS_direct_jump 1 | ||
132 | #define TCG_TARGET_HAS_qemu_st8_i32 0 | ||
133 | |||
134 | #define TCG_TARGET_HAS_extrl_i64_i32 1 | ||
135 | diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h | ||
136 | index XXXXXXX..XXXXXXX 100644 | ||
137 | --- a/tcg/tci/tcg-target.h | ||
138 | +++ b/tcg/tci/tcg-target.h | ||
139 | @@ -XXX,XX +XXX,XX @@ | ||
140 | #define TCG_TARGET_HAS_muls2_i32 1 | ||
141 | #define TCG_TARGET_HAS_muluh_i32 0 | ||
142 | #define TCG_TARGET_HAS_mulsh_i32 0 | ||
143 | -#define TCG_TARGET_HAS_direct_jump 0 | ||
144 | #define TCG_TARGET_HAS_qemu_st8_i32 0 | ||
145 | |||
146 | #if TCG_TARGET_REG_BITS == 64 | ||
147 | diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c | ||
148 | index XXXXXXX..XXXXXXX 100644 | ||
149 | --- a/accel/tcg/cpu-exec.c | ||
150 | +++ b/accel/tcg/cpu-exec.c | ||
151 | @@ -XXX,XX +XXX,XX @@ void cpu_exec_step_atomic(CPUState *cpu) | ||
152 | |||
153 | void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr) | ||
154 | { | ||
155 | + /* | ||
156 | + * Get the rx view of the structure, from which we find the | ||
157 | + * executable code address, and tb_target_set_jmp_target can | ||
158 | + * produce a pc-relative displacement to jmp_target_addr[n]. | ||
159 | + */ | ||
160 | + const TranslationBlock *c_tb = tcg_splitwx_to_rx(tb); | ||
161 | + uintptr_t offset = tb->jmp_insn_offset[n]; | ||
162 | + uintptr_t jmp_rx = (uintptr_t)tb->tc.ptr + offset; | ||
163 | + uintptr_t jmp_rw = jmp_rx - tcg_splitwx_diff; | ||
164 | + | ||
165 | tb->jmp_target_addr[n] = addr; | ||
166 | - if (TCG_TARGET_HAS_direct_jump) { | ||
167 | - /* | ||
168 | - * Get the rx view of the structure, from which we find the | ||
169 | - * executable code address, and tb_target_set_jmp_target can | ||
170 | - * produce a pc-relative displacement to jmp_target_addr[n]. | ||
171 | - */ | ||
172 | - const TranslationBlock *c_tb = tcg_splitwx_to_rx(tb); | ||
173 | - uintptr_t offset = tb->jmp_insn_offset[n]; | ||
174 | - uintptr_t jmp_rx = (uintptr_t)tb->tc.ptr + offset; | ||
175 | - uintptr_t jmp_rw = jmp_rx - tcg_splitwx_diff; | ||
176 | - tb_target_set_jmp_target(c_tb, n, jmp_rx, jmp_rw); | ||
177 | - } | ||
178 | + tb_target_set_jmp_target(c_tb, n, jmp_rx, jmp_rw); | ||
179 | } | ||
180 | |||
181 | static inline void tb_add_jump(TranslationBlock *tb, int n, | ||
182 | diff --git a/tcg/tcg.c b/tcg/tcg.c | ||
183 | index XXXXXXX..XXXXXXX 100644 | ||
184 | --- a/tcg/tcg.c | ||
185 | +++ b/tcg/tcg.c | ||
186 | @@ -XXX,XX +XXX,XX @@ static void G_GNUC_UNUSED set_jmp_insn_offset(TCGContext *s, int which) | ||
187 | * We will check for overflow at the end of the opcode loop in | ||
188 | * tcg_gen_code, where we bound tcg_current_code_size to UINT16_MAX. | ||
189 | */ | ||
190 | - tcg_debug_assert(TCG_TARGET_HAS_direct_jump); | ||
191 | s->gen_tb->jmp_insn_offset[which] = tcg_current_code_size(s); | ||
192 | } | ||
193 | |||
194 | diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc | ||
195 | index XXXXXXX..XXXXXXX 100644 | ||
196 | --- a/tcg/arm/tcg-target.c.inc | ||
197 | +++ b/tcg/arm/tcg-target.c.inc | ||
198 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_goto_tb(TCGContext *s, int which) | ||
199 | intptr_t ptr, dif, dil; | ||
200 | TCGReg base = TCG_REG_PC; | ||
201 | |||
202 | - qemu_build_assert(!TCG_TARGET_HAS_direct_jump); | ||
203 | ptr = get_jmp_target_addr(s, which); | ||
204 | dif = tcg_pcrel_diff(s, (void *)ptr) - 8; | ||
205 | dil = sextract32(dif, 0, 12); | ||
206 | diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc | ||
207 | index XXXXXXX..XXXXXXX 100644 | ||
208 | --- a/tcg/mips/tcg-target.c.inc | ||
209 | +++ b/tcg/mips/tcg-target.c.inc | ||
210 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) | ||
211 | static void tcg_out_goto_tb(TCGContext *s, int which) | ||
212 | { | ||
213 | /* indirect jump method */ | ||
214 | - qemu_build_assert(!TCG_TARGET_HAS_direct_jump); | ||
215 | tcg_out_ld(s, TCG_TYPE_PTR, TCG_TMP0, TCG_REG_ZERO, | ||
216 | get_jmp_target_addr(s, which)); | ||
217 | tcg_out_opc_reg(s, OPC_JR, 0, TCG_TMP0, 0); | ||
218 | diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc | 31 | diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc |
219 | index XXXXXXX..XXXXXXX 100644 | 32 | index XXXXXXX..XXXXXXX 100644 |
220 | --- a/tcg/riscv/tcg-target.c.inc | 33 | --- a/tcg/riscv/tcg-target.c.inc |
221 | +++ b/tcg/riscv/tcg-target.c.inc | 34 | +++ b/tcg/riscv/tcg-target.c.inc |
222 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) | 35 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, |
223 | 36 | } | |
224 | static void tcg_out_goto_tb(TCGContext *s, int which) | 37 | break; |
225 | { | 38 | |
226 | - qemu_build_assert(!TCG_TARGET_HAS_direct_jump); | 39 | + case INDEX_op_ctpop_i32: |
227 | /* indirect jump method */ | 40 | + tcg_out_opc_imm(s, OPC_CPOPW, a0, a1, 0); |
228 | tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO, | 41 | + break; |
229 | get_jmp_target_addr(s, which)); | 42 | + case INDEX_op_ctpop_i64: |
230 | diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc | 43 | + tcg_out_opc_imm(s, OPC_CPOP, a0, a1, 0); |
231 | index XXXXXXX..XXXXXXX 100644 | 44 | + break; |
232 | --- a/tcg/s390x/tcg-target.c.inc | 45 | + |
233 | +++ b/tcg/s390x/tcg-target.c.inc | 46 | case INDEX_op_add2_i32: |
234 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_goto_tb(TCGContext *s, int which) | 47 | tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5], |
235 | void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | 48 | const_args[4], const_args[5], false, true); |
236 | uintptr_t jmp_rx, uintptr_t jmp_rw) | 49 | @@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) |
237 | { | 50 | case INDEX_op_bswap16_i64: |
238 | + if (!HAVE_FACILITY(GEN_INST_EXT)) { | 51 | case INDEX_op_bswap32_i64: |
239 | + return; | 52 | case INDEX_op_bswap64_i64: |
240 | + } | 53 | + case INDEX_op_ctpop_i32: |
241 | /* patch the branch destination */ | 54 | + case INDEX_op_ctpop_i64: |
242 | uintptr_t addr = tb->jmp_target_addr[n]; | 55 | return C_O1_I1(r, r); |
243 | intptr_t disp = addr - (jmp_rx - 2); | 56 | |
244 | diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc | 57 | case INDEX_op_st8_i32: |
245 | index XXXXXXX..XXXXXXX 100644 | ||
246 | --- a/tcg/tci/tcg-target.c.inc | ||
247 | +++ b/tcg/tci/tcg-target.c.inc | ||
248 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg) | ||
249 | |||
250 | static void tcg_out_goto_tb(TCGContext *s, int which) | ||
251 | { | ||
252 | - qemu_build_assert(!TCG_TARGET_HAS_direct_jump); | ||
253 | /* indirect jump method. */ | ||
254 | tcg_out_op_p(s, INDEX_op_goto_tb, (void *)get_jmp_target_addr(s, which)); | ||
255 | set_jmp_reset_offset(s, which); | ||
256 | -- | 58 | -- |
257 | 2.34.1 | 59 | 2.34.1 |
258 | |||
259 | diff view generated by jsdifflib |
1 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | 1 | Split out a helper function, tcg_out_setcond_int, which does not |
---|---|---|---|
2 | always produce the complete boolean result, but returns a set of | ||
3 | flags to do so. | ||
4 | |||
5 | Based on 21af16198425, the same improvement for loongarch64. | ||
6 | |||
7 | Acked-by: Alistair Francis <alistair.francis@wdc.com> | ||
8 | Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> | ||
2 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 9 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
3 | --- | 10 | --- |
4 | tcg/sparc64/tcg-target.c.inc | 41 +++++++++++------------------------- | 11 | tcg/riscv/tcg-target.c.inc | 164 +++++++++++++++++++++++++++---------- |
5 | 1 file changed, 12 insertions(+), 29 deletions(-) | 12 | 1 file changed, 121 insertions(+), 43 deletions(-) |
6 | 13 | ||
7 | diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc | 14 | diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc |
8 | index XXXXXXX..XXXXXXX 100644 | 15 | index XXXXXXX..XXXXXXX 100644 |
9 | --- a/tcg/sparc64/tcg-target.c.inc | 16 | --- a/tcg/riscv/tcg-target.c.inc |
10 | +++ b/tcg/sparc64/tcg-target.c.inc | 17 | +++ b/tcg/riscv/tcg-target.c.inc |
11 | @@ -XXX,XX +XXX,XX @@ static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, | 18 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1, |
12 | return false; | 19 | tcg_out_opc_branch(s, op, arg1, arg2, 0); |
13 | } | 20 | } |
14 | 21 | ||
15 | -static void tcg_out_ld_ptr(TCGContext *s, TCGReg ret, const void *arg) | 22 | -static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret, |
16 | -{ | 23 | - TCGReg arg1, TCGReg arg2) |
17 | - intptr_t diff = tcg_tbrel_diff(s, arg); | 24 | +#define SETCOND_INV TCG_TARGET_NB_REGS |
18 | - if (USE_REG_TB && check_fit_ptr(diff, 13)) { | 25 | +#define SETCOND_NEZ (SETCOND_INV << 1) |
19 | - tcg_out_ld(s, TCG_TYPE_PTR, ret, TCG_REG_TB, diff); | 26 | +#define SETCOND_FLAGS (SETCOND_INV | SETCOND_NEZ) |
20 | - return; | 27 | + |
21 | - } | 28 | +static int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret, |
22 | - tcg_out_movi(s, TCG_TYPE_PTR, ret, (uintptr_t)arg & ~0x3ff); | 29 | + TCGReg arg1, tcg_target_long arg2, bool c2) |
23 | - tcg_out_ld(s, TCG_TYPE_PTR, ret, ret, (uintptr_t)arg & 0x3ff); | ||
24 | -} | ||
25 | - | ||
26 | static void tcg_out_sety(TCGContext *s, TCGReg rs) | ||
27 | { | 30 | { |
28 | tcg_out32(s, WRY | INSN_RS1(TCG_REG_G0) | INSN_RS2(rs)); | 31 | + int flags = 0; |
32 | + | ||
33 | switch (cond) { | ||
34 | - case TCG_COND_EQ: | ||
35 | - tcg_out_opc_reg(s, OPC_SUB, ret, arg1, arg2); | ||
36 | - tcg_out_opc_imm(s, OPC_SLTIU, ret, ret, 1); | ||
37 | - break; | ||
38 | - case TCG_COND_NE: | ||
39 | - tcg_out_opc_reg(s, OPC_SUB, ret, arg1, arg2); | ||
40 | - tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, ret); | ||
41 | - break; | ||
42 | - case TCG_COND_LT: | ||
43 | - tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2); | ||
44 | - break; | ||
45 | - case TCG_COND_GE: | ||
46 | - tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2); | ||
47 | - tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1); | ||
48 | - break; | ||
49 | - case TCG_COND_LE: | ||
50 | - tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1); | ||
51 | - tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1); | ||
52 | - break; | ||
53 | - case TCG_COND_GT: | ||
54 | - tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1); | ||
55 | - break; | ||
56 | - case TCG_COND_LTU: | ||
57 | - tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2); | ||
58 | - break; | ||
59 | - case TCG_COND_GEU: | ||
60 | - tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2); | ||
61 | - tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1); | ||
62 | - break; | ||
63 | - case TCG_COND_LEU: | ||
64 | - tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1); | ||
65 | - tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1); | ||
66 | - break; | ||
67 | - case TCG_COND_GTU: | ||
68 | - tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1); | ||
69 | + case TCG_COND_EQ: /* -> NE */ | ||
70 | + case TCG_COND_GE: /* -> LT */ | ||
71 | + case TCG_COND_GEU: /* -> LTU */ | ||
72 | + case TCG_COND_GT: /* -> LE */ | ||
73 | + case TCG_COND_GTU: /* -> LEU */ | ||
74 | + cond = tcg_invert_cond(cond); | ||
75 | + flags ^= SETCOND_INV; | ||
76 | break; | ||
77 | default: | ||
78 | - g_assert_not_reached(); | ||
79 | - break; | ||
80 | - } | ||
81 | + break; | ||
82 | + } | ||
83 | + | ||
84 | + switch (cond) { | ||
85 | + case TCG_COND_LE: | ||
86 | + case TCG_COND_LEU: | ||
87 | + /* | ||
88 | + * If we have a constant input, the most efficient way to implement | ||
89 | + * LE is by adding 1 and using LT. Watch out for wrap around for LEU. | ||
90 | + * We don't need to care for this for LE because the constant input | ||
91 | + * is constrained to signed 12-bit, and 0x800 is representable in the | ||
92 | + * temporary register. | ||
93 | + */ | ||
94 | + if (c2) { | ||
95 | + if (cond == TCG_COND_LEU) { | ||
96 | + /* unsigned <= -1 is true */ | ||
97 | + if (arg2 == -1) { | ||
98 | + tcg_out_movi(s, TCG_TYPE_REG, ret, !(flags & SETCOND_INV)); | ||
99 | + return ret; | ||
100 | + } | ||
101 | + cond = TCG_COND_LTU; | ||
102 | + } else { | ||
103 | + cond = TCG_COND_LT; | ||
104 | + } | ||
105 | + tcg_debug_assert(arg2 <= 0x7ff); | ||
106 | + if (++arg2 == 0x800) { | ||
107 | + tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP0, arg2); | ||
108 | + arg2 = TCG_REG_TMP0; | ||
109 | + c2 = false; | ||
110 | + } | ||
111 | + } else { | ||
112 | + TCGReg tmp = arg2; | ||
113 | + arg2 = arg1; | ||
114 | + arg1 = tmp; | ||
115 | + cond = tcg_swap_cond(cond); /* LE -> GE */ | ||
116 | + cond = tcg_invert_cond(cond); /* GE -> LT */ | ||
117 | + flags ^= SETCOND_INV; | ||
118 | + } | ||
119 | + break; | ||
120 | + default: | ||
121 | + break; | ||
122 | + } | ||
123 | + | ||
124 | + switch (cond) { | ||
125 | + case TCG_COND_NE: | ||
126 | + flags |= SETCOND_NEZ; | ||
127 | + if (!c2) { | ||
128 | + tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2); | ||
129 | + } else if (arg2 == 0) { | ||
130 | + ret = arg1; | ||
131 | + } else { | ||
132 | + tcg_out_opc_imm(s, OPC_XORI, ret, arg1, arg2); | ||
133 | + } | ||
134 | + break; | ||
135 | + | ||
136 | + case TCG_COND_LT: | ||
137 | + if (c2) { | ||
138 | + tcg_out_opc_imm(s, OPC_SLTI, ret, arg1, arg2); | ||
139 | + } else { | ||
140 | + tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2); | ||
141 | + } | ||
142 | + break; | ||
143 | + | ||
144 | + case TCG_COND_LTU: | ||
145 | + if (c2) { | ||
146 | + tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, arg2); | ||
147 | + } else { | ||
148 | + tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2); | ||
149 | + } | ||
150 | + break; | ||
151 | + | ||
152 | + default: | ||
153 | + g_assert_not_reached(); | ||
154 | + } | ||
155 | + | ||
156 | + return ret | flags; | ||
157 | +} | ||
158 | + | ||
159 | +static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret, | ||
160 | + TCGReg arg1, tcg_target_long arg2, bool c2) | ||
161 | +{ | ||
162 | + int tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2); | ||
163 | + | ||
164 | + if (tmpflags != ret) { | ||
165 | + TCGReg tmp = tmpflags & ~SETCOND_FLAGS; | ||
166 | + | ||
167 | + switch (tmpflags & SETCOND_FLAGS) { | ||
168 | + case SETCOND_INV: | ||
169 | + /* Intermediate result is boolean: simply invert. */ | ||
170 | + tcg_out_opc_imm(s, OPC_XORI, ret, tmp, 1); | ||
171 | + break; | ||
172 | + case SETCOND_NEZ: | ||
173 | + /* Intermediate result is zero/non-zero: test != 0. */ | ||
174 | + tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp); | ||
175 | + break; | ||
176 | + case SETCOND_NEZ | SETCOND_INV: | ||
177 | + /* Intermediate result is zero/non-zero: test == 0. */ | ||
178 | + tcg_out_opc_imm(s, OPC_SLTIU, ret, tmp, 1); | ||
179 | + break; | ||
180 | + default: | ||
181 | + g_assert_not_reached(); | ||
182 | + } | ||
183 | + } | ||
184 | } | ||
185 | |||
186 | static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail) | ||
29 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 187 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, |
30 | 188 | ||
31 | switch (opc) { | 189 | case INDEX_op_setcond_i32: |
32 | case INDEX_op_goto_tb: | 190 | case INDEX_op_setcond_i64: |
33 | - if (s->tb_jmp_insn_offset) { | 191 | - tcg_out_setcond(s, args[3], a0, a1, a2); |
34 | - /* direct jump method */ | 192 | + tcg_out_setcond(s, args[3], a0, a1, a2, c2); |
35 | - if (USE_REG_TB) { | 193 | break; |
36 | - /* make sure the patch is 8-byte aligned. */ | 194 | |
37 | - if ((intptr_t)s->code_ptr & 4) { | 195 | case INDEX_op_qemu_ld_a32_i32: |
38 | - tcg_out_nop(s); | 196 | @@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) |
39 | - } | 197 | case INDEX_op_and_i64: |
40 | - s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s); | 198 | case INDEX_op_or_i64: |
41 | - tcg_out_sethi(s, TCG_REG_T1, 0); | 199 | case INDEX_op_xor_i64: |
42 | - tcg_out_arithi(s, TCG_REG_T1, TCG_REG_T1, 0, ARITH_OR); | 200 | + case INDEX_op_setcond_i32: |
43 | - tcg_out_arith(s, TCG_REG_G0, TCG_REG_TB, TCG_REG_T1, JMPL); | 201 | + case INDEX_op_setcond_i64: |
44 | - tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD); | 202 | return C_O1_I2(r, r, rI); |
45 | - } else { | 203 | |
46 | - s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s); | 204 | case INDEX_op_andc_i32: |
47 | - tcg_out32(s, CALL); | 205 | @@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) |
48 | + qemu_build_assert(TCG_TARGET_HAS_direct_jump); | 206 | case INDEX_op_divu_i32: |
49 | + /* Direct jump. */ | 207 | case INDEX_op_rem_i32: |
50 | + if (USE_REG_TB) { | 208 | case INDEX_op_remu_i32: |
51 | + /* make sure the patch is 8-byte aligned. */ | 209 | - case INDEX_op_setcond_i32: |
52 | + if ((intptr_t)s->code_ptr & 4) { | 210 | case INDEX_op_mul_i64: |
53 | tcg_out_nop(s); | 211 | case INDEX_op_mulsh_i64: |
54 | } | 212 | case INDEX_op_muluh_i64: |
55 | + s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s); | 213 | @@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) |
56 | + tcg_out_sethi(s, TCG_REG_T1, 0); | 214 | case INDEX_op_divu_i64: |
57 | + tcg_out_arithi(s, TCG_REG_T1, TCG_REG_T1, 0, ARITH_OR); | 215 | case INDEX_op_rem_i64: |
58 | + tcg_out_arith(s, TCG_REG_G0, TCG_REG_TB, TCG_REG_T1, JMPL); | 216 | case INDEX_op_remu_i64: |
59 | + tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD); | 217 | - case INDEX_op_setcond_i64: |
60 | } else { | 218 | return C_O1_I2(r, rZ, rZ); |
61 | - /* indirect jump method */ | 219 | |
62 | - tcg_out_ld_ptr(s, TCG_REG_TB, s->tb_jmp_target_addr + a0); | 220 | case INDEX_op_shl_i32: |
63 | - tcg_out_arithi(s, TCG_REG_G0, TCG_REG_TB, 0, JMPL); | ||
64 | + s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s); | ||
65 | + tcg_out32(s, CALL); | ||
66 | tcg_out_nop(s); | ||
67 | } | ||
68 | set_jmp_reset_offset(s, a0); | ||
69 | -- | 221 | -- |
70 | 2.34.1 | 222 | 2.34.1 |
71 | |||
72 | diff view generated by jsdifflib |
1 | This is always true for sparc64, so this is dead since 3a5f6805c7ca. | 1 | Implement with and without Zicond. Without Zicond, we were letting |
---|---|---|---|
2 | the middle-end expand to a 5 insn sequence; better to use a branch | ||
3 | over a single insn. | ||
2 | 4 | ||
3 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | 5 | Acked-by: Alistair Francis <alistair.francis@wdc.com> |
4 | Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> | 6 | Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> |
5 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 7 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
6 | --- | 8 | --- |
7 | tcg/sparc64/tcg-target.c.inc | 62 ++++++++++++------------------------ | 9 | tcg/riscv/tcg-target-con-set.h | 1 + |
8 | 1 file changed, 21 insertions(+), 41 deletions(-) | 10 | tcg/riscv/tcg-target.h | 4 +- |
11 | tcg/riscv/tcg-target.c.inc | 139 ++++++++++++++++++++++++++++++++- | ||
12 | 3 files changed, 141 insertions(+), 3 deletions(-) | ||
9 | 13 | ||
10 | diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc | 14 | diff --git a/tcg/riscv/tcg-target-con-set.h b/tcg/riscv/tcg-target-con-set.h |
11 | index XXXXXXX..XXXXXXX 100644 | 15 | index XXXXXXX..XXXXXXX 100644 |
12 | --- a/tcg/sparc64/tcg-target.c.inc | 16 | --- a/tcg/riscv/tcg-target-con-set.h |
13 | +++ b/tcg/sparc64/tcg-target.c.inc | 17 | +++ b/tcg/riscv/tcg-target-con-set.h |
14 | @@ -XXX,XX +XXX,XX @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = { | 18 | @@ -XXX,XX +XXX,XX @@ C_O1_I2(r, r, rI) |
19 | C_O1_I2(r, r, rJ) | ||
20 | C_O1_I2(r, rZ, rN) | ||
21 | C_O1_I2(r, rZ, rZ) | ||
22 | +C_O1_I4(r, r, rI, rM, rM) | ||
23 | C_O2_I4(r, r, rZ, rZ, rM, rM) | ||
24 | diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h | ||
25 | index XXXXXXX..XXXXXXX 100644 | ||
26 | --- a/tcg/riscv/tcg-target.h | ||
27 | +++ b/tcg/riscv/tcg-target.h | ||
28 | @@ -XXX,XX +XXX,XX @@ extern bool have_zbb; | ||
15 | #endif | 29 | #endif |
16 | 30 | ||
17 | #define TCG_REG_TB TCG_REG_I1 | 31 | /* optional instructions */ |
18 | -#define USE_REG_TB (sizeof(void *) > 4) | 32 | -#define TCG_TARGET_HAS_movcond_i32 0 |
19 | 33 | +#define TCG_TARGET_HAS_movcond_i32 1 | |
20 | static const int tcg_target_reg_alloc_order[] = { | 34 | #define TCG_TARGET_HAS_div_i32 1 |
21 | TCG_REG_L0, | 35 | #define TCG_TARGET_HAS_rem_i32 1 |
22 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_movi_int(TCGContext *s, TCGType type, TCGReg ret, | 36 | #define TCG_TARGET_HAS_div2_i32 0 |
37 | @@ -XXX,XX +XXX,XX @@ extern bool have_zbb; | ||
38 | #define TCG_TARGET_HAS_setcond2 1 | ||
39 | #define TCG_TARGET_HAS_qemu_st8_i32 0 | ||
40 | |||
41 | -#define TCG_TARGET_HAS_movcond_i64 0 | ||
42 | +#define TCG_TARGET_HAS_movcond_i64 1 | ||
43 | #define TCG_TARGET_HAS_div_i64 1 | ||
44 | #define TCG_TARGET_HAS_rem_i64 1 | ||
45 | #define TCG_TARGET_HAS_div2_i64 0 | ||
46 | diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc | ||
47 | index XXXXXXX..XXXXXXX 100644 | ||
48 | --- a/tcg/riscv/tcg-target.c.inc | ||
49 | +++ b/tcg/riscv/tcg-target.c.inc | ||
50 | @@ -XXX,XX +XXX,XX @@ static bool tcg_target_const_match(int64_t val, TCGType type, int ct) | ||
23 | } | 51 | } |
24 | |||
25 | /* A 13-bit constant relative to the TB. */ | ||
26 | - if (!in_prologue && USE_REG_TB) { | ||
27 | + if (!in_prologue) { | ||
28 | test = tcg_tbrel_diff(s, (void *)arg); | ||
29 | if (check_fit_ptr(test, 13)) { | ||
30 | tcg_out_arithi(s, ret, TCG_REG_TB, test, ARITH_ADD); | ||
31 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_movi_int(TCGContext *s, TCGType type, TCGReg ret, | ||
32 | } | ||
33 | |||
34 | /* Use the constant pool, if possible. */ | ||
35 | - if (!in_prologue && USE_REG_TB) { | ||
36 | + if (!in_prologue) { | ||
37 | new_pool_label(s, arg, R_SPARC_13, s->code_ptr, | ||
38 | tcg_tbrel_diff(s, NULL)); | ||
39 | tcg_out32(s, LDX | INSN_RD(ret) | INSN_RS1(TCG_REG_TB)); | ||
40 | @@ -XXX,XX +XXX,XX @@ static void tcg_target_qemu_prologue(TCGContext *s) | ||
41 | #endif | ||
42 | |||
43 | /* We choose TCG_REG_TB such that no move is required. */ | ||
44 | - if (USE_REG_TB) { | ||
45 | - QEMU_BUILD_BUG_ON(TCG_REG_TB != TCG_REG_I1); | ||
46 | - tcg_regset_set_reg(s->reserved_regs, TCG_REG_TB); | ||
47 | - } | ||
48 | + QEMU_BUILD_BUG_ON(TCG_REG_TB != TCG_REG_I1); | ||
49 | + tcg_regset_set_reg(s->reserved_regs, TCG_REG_TB); | ||
50 | |||
51 | tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I1, 0, JMPL); | ||
52 | /* delay slot */ | ||
53 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) | ||
54 | tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN); | ||
55 | tcg_out_movi_imm13(s, TCG_REG_O0, a0); | ||
56 | return; | ||
57 | - } else if (USE_REG_TB) { | ||
58 | + } else { | ||
59 | intptr_t tb_diff = tcg_tbrel_diff(s, (void *)a0); | ||
60 | if (check_fit_ptr(tb_diff, 13)) { | ||
61 | tcg_out_arithi(s, TCG_REG_G0, TCG_REG_I7, 8, RETURN); | ||
62 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0) | ||
63 | |||
64 | static void tcg_out_goto_tb(TCGContext *s, int which) | ||
65 | { | ||
66 | + int c; | ||
67 | + | ||
68 | /* Direct jump. */ | ||
69 | - if (USE_REG_TB) { | ||
70 | - /* make sure the patch is 8-byte aligned. */ | ||
71 | - if ((intptr_t)s->code_ptr & 4) { | ||
72 | - tcg_out_nop(s); | ||
73 | - } | ||
74 | - set_jmp_insn_offset(s, which); | ||
75 | - tcg_out_sethi(s, TCG_REG_T1, 0); | ||
76 | - tcg_out_arithi(s, TCG_REG_T1, TCG_REG_T1, 0, ARITH_OR); | ||
77 | - tcg_out_arith(s, TCG_REG_G0, TCG_REG_TB, TCG_REG_T1, JMPL); | ||
78 | - tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD); | ||
79 | - } else { | ||
80 | - set_jmp_insn_offset(s, which); | ||
81 | - tcg_out32(s, CALL); | ||
82 | + /* make sure the patch is 8-byte aligned. */ | ||
83 | + if ((intptr_t)s->code_ptr & 4) { | ||
84 | tcg_out_nop(s); | ||
85 | } | ||
86 | + set_jmp_insn_offset(s, which); | ||
87 | + tcg_out_sethi(s, TCG_REG_T1, 0); | ||
88 | + tcg_out_arithi(s, TCG_REG_T1, TCG_REG_T1, 0, ARITH_OR); | ||
89 | + tcg_out_arith(s, TCG_REG_G0, TCG_REG_TB, TCG_REG_T1, JMPL); | ||
90 | + tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD); | ||
91 | set_jmp_reset_offset(s, which); | ||
92 | |||
93 | /* | 52 | /* |
94 | * For the unlinked path of goto_tb, we need to reset TCG_REG_TB | 53 | * Sign extended from 12 bits, +/- matching: [-0x7ff, 0x7ff]. |
95 | * to the beginning of this TB. | 54 | - * Used by addsub2, which may need the negative operation, |
55 | + * Used by addsub2 and movcond, which may need the negative value, | ||
56 | * and requires the modified constant to be representable. | ||
96 | */ | 57 | */ |
97 | - if (USE_REG_TB) { | 58 | if ((ct & TCG_CT_CONST_M12) && val >= -0x7ff && val <= 0x7ff) { |
98 | - int c = -tcg_current_code_size(s); | 59 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret, |
99 | - if (check_fit_i32(c, 13)) { | ||
100 | - tcg_out_arithi(s, TCG_REG_TB, TCG_REG_TB, c, ARITH_ADD); | ||
101 | - } else { | ||
102 | - tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, c); | ||
103 | - tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD); | ||
104 | - } | ||
105 | + c = -tcg_current_code_size(s); | ||
106 | + if (check_fit_i32(c, 13)) { | ||
107 | + tcg_out_arithi(s, TCG_REG_TB, TCG_REG_TB, c, ARITH_ADD); | ||
108 | + } else { | ||
109 | + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_T1, c); | ||
110 | + tcg_out_arith(s, TCG_REG_TB, TCG_REG_TB, TCG_REG_T1, ARITH_ADD); | ||
111 | } | 60 | } |
112 | } | 61 | } |
113 | 62 | ||
63 | +static void tcg_out_movcond_zicond(TCGContext *s, TCGReg ret, TCGReg test_ne, | ||
64 | + int val1, bool c_val1, | ||
65 | + int val2, bool c_val2) | ||
66 | +{ | ||
67 | + if (val1 == 0) { | ||
68 | + if (c_val2) { | ||
69 | + tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val2); | ||
70 | + val2 = TCG_REG_TMP1; | ||
71 | + } | ||
72 | + tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, val2, test_ne); | ||
73 | + return; | ||
74 | + } | ||
75 | + | ||
76 | + if (val2 == 0) { | ||
77 | + if (c_val1) { | ||
78 | + tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1); | ||
79 | + val1 = TCG_REG_TMP1; | ||
80 | + } | ||
81 | + tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, val1, test_ne); | ||
82 | + return; | ||
83 | + } | ||
84 | + | ||
85 | + if (c_val2) { | ||
86 | + if (c_val1) { | ||
87 | + tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1 - val2); | ||
88 | + } else { | ||
89 | + tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val1, -val2); | ||
90 | + } | ||
91 | + tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, TCG_REG_TMP1, test_ne); | ||
92 | + tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val2); | ||
93 | + return; | ||
94 | + } | ||
95 | + | ||
96 | + if (c_val1) { | ||
97 | + tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val2, -val1); | ||
98 | + tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, TCG_REG_TMP1, test_ne); | ||
99 | + tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val1); | ||
100 | + return; | ||
101 | + } | ||
102 | + | ||
103 | + tcg_out_opc_reg(s, OPC_CZERO_NEZ, TCG_REG_TMP1, val2, test_ne); | ||
104 | + tcg_out_opc_reg(s, OPC_CZERO_EQZ, TCG_REG_TMP0, val1, test_ne); | ||
105 | + tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_TMP0, TCG_REG_TMP1); | ||
106 | +} | ||
107 | + | ||
108 | +static void tcg_out_movcond_br1(TCGContext *s, TCGCond cond, TCGReg ret, | ||
109 | + TCGReg cmp1, TCGReg cmp2, | ||
110 | + int val, bool c_val) | ||
111 | +{ | ||
112 | + RISCVInsn op; | ||
113 | + int disp = 8; | ||
114 | + | ||
115 | + tcg_debug_assert((unsigned)cond < ARRAY_SIZE(tcg_brcond_to_riscv)); | ||
116 | + op = tcg_brcond_to_riscv[cond].op; | ||
117 | + tcg_debug_assert(op != 0); | ||
118 | + | ||
119 | + if (tcg_brcond_to_riscv[cond].swap) { | ||
120 | + tcg_out_opc_branch(s, op, cmp2, cmp1, disp); | ||
121 | + } else { | ||
122 | + tcg_out_opc_branch(s, op, cmp1, cmp2, disp); | ||
123 | + } | ||
124 | + if (c_val) { | ||
125 | + tcg_out_opc_imm(s, OPC_ADDI, ret, TCG_REG_ZERO, val); | ||
126 | + } else { | ||
127 | + tcg_out_opc_imm(s, OPC_ADDI, ret, val, 0); | ||
128 | + } | ||
129 | +} | ||
130 | + | ||
131 | +static void tcg_out_movcond_br2(TCGContext *s, TCGCond cond, TCGReg ret, | ||
132 | + TCGReg cmp1, TCGReg cmp2, | ||
133 | + int val1, bool c_val1, | ||
134 | + int val2, bool c_val2) | ||
135 | +{ | ||
136 | + TCGReg tmp; | ||
137 | + | ||
138 | + /* TCG optimizer reorders to prefer ret matching val2. */ | ||
139 | + if (!c_val2 && ret == val2) { | ||
140 | + cond = tcg_invert_cond(cond); | ||
141 | + tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val1, c_val1); | ||
142 | + return; | ||
143 | + } | ||
144 | + | ||
145 | + if (!c_val1 && ret == val1) { | ||
146 | + tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val2, c_val2); | ||
147 | + return; | ||
148 | + } | ||
149 | + | ||
150 | + tmp = (ret == cmp1 || ret == cmp2 ? TCG_REG_TMP1 : ret); | ||
151 | + if (c_val1) { | ||
152 | + tcg_out_movi(s, TCG_TYPE_REG, tmp, val1); | ||
153 | + } else { | ||
154 | + tcg_out_mov(s, TCG_TYPE_REG, tmp, val1); | ||
155 | + } | ||
156 | + tcg_out_movcond_br1(s, cond, tmp, cmp1, cmp2, val2, c_val2); | ||
157 | + tcg_out_mov(s, TCG_TYPE_REG, ret, tmp); | ||
158 | +} | ||
159 | + | ||
160 | +static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret, | ||
161 | + TCGReg cmp1, int cmp2, bool c_cmp2, | ||
162 | + TCGReg val1, bool c_val1, | ||
163 | + TCGReg val2, bool c_val2) | ||
164 | +{ | ||
165 | + int tmpflags; | ||
166 | + TCGReg t; | ||
167 | + | ||
168 | + if (!have_zicond && (!c_cmp2 || cmp2 == 0)) { | ||
169 | + tcg_out_movcond_br2(s, cond, ret, cmp1, cmp2, | ||
170 | + val1, c_val1, val2, c_val2); | ||
171 | + return; | ||
172 | + } | ||
173 | + | ||
174 | + tmpflags = tcg_out_setcond_int(s, cond, TCG_REG_TMP0, cmp1, cmp2, c_cmp2); | ||
175 | + t = tmpflags & ~SETCOND_FLAGS; | ||
176 | + | ||
177 | + if (have_zicond) { | ||
178 | + if (tmpflags & SETCOND_INV) { | ||
179 | + tcg_out_movcond_zicond(s, ret, t, val2, c_val2, val1, c_val1); | ||
180 | + } else { | ||
181 | + tcg_out_movcond_zicond(s, ret, t, val1, c_val1, val2, c_val2); | ||
182 | + } | ||
183 | + } else { | ||
184 | + cond = tmpflags & SETCOND_INV ? TCG_COND_EQ : TCG_COND_NE; | ||
185 | + tcg_out_movcond_br2(s, cond, ret, t, TCG_REG_ZERO, | ||
186 | + val1, c_val1, val2, c_val2); | ||
187 | + } | ||
188 | +} | ||
189 | + | ||
190 | static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail) | ||
191 | { | ||
192 | TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA; | ||
114 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 193 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, |
115 | switch (opc) { | 194 | tcg_out_setcond(s, args[3], a0, a1, a2, c2); |
116 | case INDEX_op_goto_ptr: | ||
117 | tcg_out_arithi(s, TCG_REG_G0, a0, 0, JMPL); | ||
118 | - if (USE_REG_TB) { | ||
119 | - tcg_out_mov_delay(s, TCG_REG_TB, a0); | ||
120 | - } else { | ||
121 | - tcg_out_nop(s); | ||
122 | - } | ||
123 | + tcg_out_mov_delay(s, TCG_REG_TB, a0); | ||
124 | break; | 195 | break; |
125 | case INDEX_op_br: | 196 | |
126 | tcg_out_bpcc(s, COND_A, BPCC_PT, arg_label(a0)); | 197 | + case INDEX_op_movcond_i32: |
127 | @@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | 198 | + case INDEX_op_movcond_i64: |
128 | tcg_debug_assert(tb_disp == (int32_t)tb_disp); | 199 | + tcg_out_movcond(s, args[5], a0, a1, a2, c2, |
129 | tcg_debug_assert(br_disp == (int32_t)br_disp); | 200 | + args[3], const_args[3], args[4], const_args[4]); |
130 | 201 | + break; | |
131 | - if (!USE_REG_TB) { | 202 | + |
132 | - qatomic_set((uint32_t *)jmp_rw, | 203 | case INDEX_op_qemu_ld_a32_i32: |
133 | - deposit32(CALL, 0, 30, br_disp >> 2)); | 204 | case INDEX_op_qemu_ld_a64_i32: |
134 | - flush_idcache_range(jmp_rx, jmp_rw, 4); | 205 | tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I32); |
135 | - return; | 206 | @@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) |
136 | - } | 207 | case INDEX_op_brcond_i64: |
137 | - | 208 | return C_O0_I2(rZ, rZ); |
138 | /* This does not exercise the range of the branch, but we do | 209 | |
139 | still need to be able to load the new value of TCG_REG_TB. | 210 | + case INDEX_op_movcond_i32: |
140 | But this does still happen quite often. */ | 211 | + case INDEX_op_movcond_i64: |
212 | + return C_O1_I4(r, r, rI, rM, rM); | ||
213 | + | ||
214 | case INDEX_op_add2_i32: | ||
215 | case INDEX_op_add2_i64: | ||
216 | case INDEX_op_sub2_i32: | ||
141 | -- | 217 | -- |
142 | 2.34.1 | 218 | 2.34.1 |
143 | |||
144 | diff view generated by jsdifflib |
1 | The old ppc64 implementation replaces 2 or 4 insns, which leaves a race | 1 | Acked-by: Alistair Francis <alistair.francis@wdc.com> |
---|---|---|---|
2 | condition in which a thread could be stopped at a PC in the middle of | 2 | Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> |
3 | the sequence, and when restarted does not see the complete address | ||
4 | computation and branches to nowhere. | ||
5 | |||
6 | The new implemetation replaces only one insn, swapping between | ||
7 | |||
8 | b <dest> | ||
9 | and | ||
10 | mtctr r31 | ||
11 | |||
12 | falling through to a general-case indirect branch. | ||
13 | |||
14 | Reviewed-by: Alex Bennée <alex.bennee@linaro.org> | ||
15 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> | 3 | Signed-off-by: Richard Henderson <richard.henderson@linaro.org> |
16 | --- | 4 | --- |
17 | tcg/ppc/tcg-target.h | 3 +- | 5 | tcg/riscv/tcg-target-con-set.h | 1 + |
18 | tcg/ppc/tcg-target.c.inc | 158 +++++++++++---------------------------- | 6 | tcg/riscv/tcg-target.h | 8 ++++---- |
19 | 2 files changed, 44 insertions(+), 117 deletions(-) | 7 | tcg/riscv/tcg-target.c.inc | 35 ++++++++++++++++++++++++++++++++++ |
8 | 3 files changed, 40 insertions(+), 4 deletions(-) | ||
20 | 9 | ||
21 | diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h | 10 | diff --git a/tcg/riscv/tcg-target-con-set.h b/tcg/riscv/tcg-target-con-set.h |
22 | index XXXXXXX..XXXXXXX 100644 | 11 | index XXXXXXX..XXXXXXX 100644 |
23 | --- a/tcg/ppc/tcg-target.h | 12 | --- a/tcg/riscv/tcg-target-con-set.h |
24 | +++ b/tcg/ppc/tcg-target.h | 13 | +++ b/tcg/riscv/tcg-target-con-set.h |
25 | @@ -XXX,XX +XXX,XX @@ | 14 | @@ -XXX,XX +XXX,XX @@ C_O1_I2(r, r, rI) |
26 | 15 | C_O1_I2(r, r, rJ) | |
27 | #ifdef _ARCH_PPC64 | 16 | C_O1_I2(r, rZ, rN) |
28 | # define TCG_TARGET_REG_BITS 64 | 17 | C_O1_I2(r, rZ, rZ) |
29 | -# define MAX_CODE_GEN_BUFFER_SIZE (2 * GiB) | 18 | +C_N1_I2(r, r, rM) |
30 | #else | 19 | C_O1_I4(r, r, rI, rM, rM) |
31 | # define TCG_TARGET_REG_BITS 32 | 20 | C_O2_I4(r, r, rZ, rZ, rM, rM) |
32 | -# define MAX_CODE_GEN_BUFFER_SIZE (32 * MiB) | 21 | diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h |
33 | #endif | ||
34 | +#define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1) | ||
35 | |||
36 | #define TCG_TARGET_NB_REGS 64 | ||
37 | #define TCG_TARGET_INSN_UNIT_SIZE 4 | ||
38 | diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc | ||
39 | index XXXXXXX..XXXXXXX 100644 | 22 | index XXXXXXX..XXXXXXX 100644 |
40 | --- a/tcg/ppc/tcg-target.c.inc | 23 | --- a/tcg/riscv/tcg-target.h |
41 | +++ b/tcg/ppc/tcg-target.c.inc | 24 | +++ b/tcg/riscv/tcg-target.h |
42 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_mb(TCGContext *s, TCGArg a0) | 25 | @@ -XXX,XX +XXX,XX @@ extern bool have_zbb; |
43 | tcg_out32(s, insn); | 26 | #define TCG_TARGET_HAS_eqv_i32 have_zbb |
44 | } | 27 | #define TCG_TARGET_HAS_nand_i32 0 |
45 | 28 | #define TCG_TARGET_HAS_nor_i32 0 | |
46 | -static inline uint64_t make_pair(tcg_insn_unit i1, tcg_insn_unit i2) | 29 | -#define TCG_TARGET_HAS_clz_i32 0 |
47 | -{ | 30 | -#define TCG_TARGET_HAS_ctz_i32 0 |
48 | - if (HOST_BIG_ENDIAN) { | 31 | +#define TCG_TARGET_HAS_clz_i32 have_zbb |
49 | - return (uint64_t)i1 << 32 | i2; | 32 | +#define TCG_TARGET_HAS_ctz_i32 have_zbb |
50 | - } | 33 | #define TCG_TARGET_HAS_ctpop_i32 have_zbb |
51 | - return (uint64_t)i2 << 32 | i1; | 34 | #define TCG_TARGET_HAS_brcond2 1 |
52 | -} | 35 | #define TCG_TARGET_HAS_setcond2 1 |
53 | - | 36 | @@ -XXX,XX +XXX,XX @@ extern bool have_zbb; |
54 | -static inline void ppc64_replace2(uintptr_t rx, uintptr_t rw, | 37 | #define TCG_TARGET_HAS_eqv_i64 have_zbb |
55 | - tcg_insn_unit i0, tcg_insn_unit i1) | 38 | #define TCG_TARGET_HAS_nand_i64 0 |
56 | -{ | 39 | #define TCG_TARGET_HAS_nor_i64 0 |
57 | -#if TCG_TARGET_REG_BITS == 64 | 40 | -#define TCG_TARGET_HAS_clz_i64 0 |
58 | - qatomic_set((uint64_t *)rw, make_pair(i0, i1)); | 41 | -#define TCG_TARGET_HAS_ctz_i64 0 |
59 | - flush_idcache_range(rx, rw, 8); | 42 | +#define TCG_TARGET_HAS_clz_i64 have_zbb |
60 | -#else | 43 | +#define TCG_TARGET_HAS_ctz_i64 have_zbb |
61 | - qemu_build_not_reached(); | 44 | #define TCG_TARGET_HAS_ctpop_i64 have_zbb |
62 | -#endif | 45 | #define TCG_TARGET_HAS_add2_i64 1 |
63 | -} | 46 | #define TCG_TARGET_HAS_sub2_i64 1 |
64 | - | 47 | diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc |
65 | -static inline void ppc64_replace4(uintptr_t rx, uintptr_t rw, | 48 | index XXXXXXX..XXXXXXX 100644 |
66 | - tcg_insn_unit i0, tcg_insn_unit i1, | 49 | --- a/tcg/riscv/tcg-target.c.inc |
67 | - tcg_insn_unit i2, tcg_insn_unit i3) | 50 | +++ b/tcg/riscv/tcg-target.c.inc |
68 | -{ | 51 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret, |
69 | - uint64_t p[2]; | ||
70 | - | ||
71 | - p[!HOST_BIG_ENDIAN] = make_pair(i0, i1); | ||
72 | - p[HOST_BIG_ENDIAN] = make_pair(i2, i3); | ||
73 | - | ||
74 | - /* | ||
75 | - * There's no convenient way to get the compiler to allocate a pair | ||
76 | - * of registers at an even index, so copy into r6/r7 and clobber. | ||
77 | - */ | ||
78 | - asm("mr %%r6, %1\n\t" | ||
79 | - "mr %%r7, %2\n\t" | ||
80 | - "stq %%r6, %0" | ||
81 | - : "=Q"(*(__int128 *)rw) : "r"(p[0]), "r"(p[1]) : "r6", "r7"); | ||
82 | - flush_idcache_range(rx, rw, 16); | ||
83 | -} | ||
84 | - | ||
85 | -void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | ||
86 | - uintptr_t jmp_rx, uintptr_t jmp_rw) | ||
87 | -{ | ||
88 | - tcg_insn_unit i0, i1, i2, i3; | ||
89 | - uintptr_t addr = tb->jmp_target_addr[n]; | ||
90 | - intptr_t tb_diff = addr - (uintptr_t)tb->tc.ptr; | ||
91 | - intptr_t br_diff = addr - (jmp_rx + 4); | ||
92 | - intptr_t lo, hi; | ||
93 | - | ||
94 | - if (TCG_TARGET_REG_BITS == 32) { | ||
95 | - intptr_t diff = addr - jmp_rx; | ||
96 | - tcg_debug_assert(in_range_b(diff)); | ||
97 | - qatomic_set((uint32_t *)jmp_rw, B | (diff & 0x3fffffc)); | ||
98 | - flush_idcache_range(jmp_rx, jmp_rw, 4); | ||
99 | - return; | ||
100 | - } | ||
101 | - | ||
102 | - /* | ||
103 | - * For 16-bit displacements, we can use a single add + branch. | ||
104 | - * This happens quite often. | ||
105 | - */ | ||
106 | - if (tb_diff == (int16_t)tb_diff) { | ||
107 | - i0 = ADDI | TAI(TCG_REG_TB, TCG_REG_TB, tb_diff); | ||
108 | - i1 = B | (br_diff & 0x3fffffc); | ||
109 | - ppc64_replace2(jmp_rx, jmp_rw, i0, i1); | ||
110 | - return; | ||
111 | - } | ||
112 | - | ||
113 | - lo = (int16_t)tb_diff; | ||
114 | - hi = (int32_t)(tb_diff - lo); | ||
115 | - assert(tb_diff == hi + lo); | ||
116 | - i0 = ADDIS | TAI(TCG_REG_TB, TCG_REG_TB, hi >> 16); | ||
117 | - i1 = ADDI | TAI(TCG_REG_TB, TCG_REG_TB, lo); | ||
118 | - | ||
119 | - /* | ||
120 | - * Without stq from 2.07, we can only update two insns, | ||
121 | - * and those must be the ones that load the target address. | ||
122 | - */ | ||
123 | - if (!have_isa_2_07) { | ||
124 | - ppc64_replace2(jmp_rx, jmp_rw, i0, i1); | ||
125 | - return; | ||
126 | - } | ||
127 | - | ||
128 | - /* | ||
129 | - * For 26-bit displacements, we can use a direct branch. | ||
130 | - * Otherwise we still need the indirect branch, which we | ||
131 | - * must restore after a potential direct branch write. | ||
132 | - */ | ||
133 | - br_diff -= 4; | ||
134 | - if (in_range_b(br_diff)) { | ||
135 | - i2 = B | (br_diff & 0x3fffffc); | ||
136 | - i3 = NOP; | ||
137 | - } else { | ||
138 | - i2 = MTSPR | RS(TCG_REG_TB) | CTR; | ||
139 | - i3 = BCCTR | BO_ALWAYS; | ||
140 | - } | ||
141 | - ppc64_replace4(jmp_rx, jmp_rw, i0, i1, i2, i3); | ||
142 | -} | ||
143 | - | ||
144 | static void tcg_out_call_int(TCGContext *s, int lk, | ||
145 | const tcg_insn_unit *target) | ||
146 | { | ||
147 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t arg) | ||
148 | |||
149 | static void tcg_out_goto_tb(TCGContext *s, int which) | ||
150 | { | ||
151 | - /* Direct jump. */ | ||
152 | - if (TCG_TARGET_REG_BITS == 64) { | ||
153 | - /* Ensure the next insns are 8 or 16-byte aligned. */ | ||
154 | - while ((uintptr_t)s->code_ptr & (have_isa_2_07 ? 15 : 7)) { | ||
155 | - tcg_out32(s, NOP); | ||
156 | - } | ||
157 | + uintptr_t ptr = get_jmp_target_addr(s, which); | ||
158 | + | ||
159 | + if (USE_REG_TB) { | ||
160 | + ptrdiff_t offset = tcg_tbrel_diff(s, (void *)ptr); | ||
161 | + tcg_out_mem_long(s, LD, LDX, TCG_REG_TB, TCG_REG_TB, offset); | ||
162 | + | ||
163 | + /* Direct branch will be patched by tb_target_set_jmp_target. */ | ||
164 | set_jmp_insn_offset(s, which); | ||
165 | - tcg_out32(s, ADDIS | TAI(TCG_REG_TB, TCG_REG_TB, 0)); | ||
166 | - tcg_out32(s, ADDI | TAI(TCG_REG_TB, TCG_REG_TB, 0)); | ||
167 | tcg_out32(s, MTSPR | RS(TCG_REG_TB) | CTR); | ||
168 | + | ||
169 | + /* When branch is out of range, fall through to indirect. */ | ||
170 | + tcg_out32(s, BCCTR | BO_ALWAYS); | ||
171 | + | ||
172 | + /* For the unlinked case, need to reset TCG_REG_TB. */ | ||
173 | + set_jmp_reset_offset(s, which); | ||
174 | + tcg_out_mem_long(s, ADDI, ADD, TCG_REG_TB, TCG_REG_TB, | ||
175 | + -tcg_current_code_size(s)); | ||
176 | + } else { | ||
177 | + /* Direct branch will be patched by tb_target_set_jmp_target. */ | ||
178 | + set_jmp_insn_offset(s, which); | ||
179 | + tcg_out32(s, NOP); | ||
180 | + | ||
181 | + /* When branch is out of range, fall through to indirect. */ | ||
182 | + tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP1, ptr - (int16_t)ptr); | ||
183 | + tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_REG_TMP1, (int16_t)ptr); | ||
184 | + tcg_out32(s, MTSPR | RS(TCG_REG_TMP1) | CTR); | ||
185 | tcg_out32(s, BCCTR | BO_ALWAYS); | ||
186 | set_jmp_reset_offset(s, which); | ||
187 | - if (USE_REG_TB) { | ||
188 | - /* For the unlinked case, need to reset TCG_REG_TB. */ | ||
189 | - tcg_out_mem_long(s, ADDI, ADD, TCG_REG_TB, TCG_REG_TB, | ||
190 | - -tcg_current_code_size(s)); | ||
191 | - } | ||
192 | - } else { | ||
193 | - set_jmp_insn_offset(s, which); | ||
194 | - tcg_out32(s, B); | ||
195 | - set_jmp_reset_offset(s, which); | ||
196 | } | 52 | } |
197 | } | 53 | } |
198 | 54 | ||
199 | +void tb_target_set_jmp_target(const TranslationBlock *tb, int n, | 55 | +static void tcg_out_cltz(TCGContext *s, TCGType type, RISCVInsn insn, |
200 | + uintptr_t jmp_rx, uintptr_t jmp_rw) | 56 | + TCGReg ret, TCGReg src1, int src2, bool c_src2) |
201 | +{ | 57 | +{ |
202 | + uintptr_t addr = tb->jmp_target_addr[n]; | 58 | + tcg_out_opc_imm(s, insn, ret, src1, 0); |
203 | + intptr_t diff = addr - jmp_rx; | ||
204 | + tcg_insn_unit insn; | ||
205 | + | 59 | + |
206 | + if (in_range_b(diff)) { | 60 | + if (!c_src2 || src2 != (type == TCG_TYPE_I32 ? 32 : 64)) { |
207 | + insn = B | (diff & 0x3fffffc); | 61 | + /* |
208 | + } else if (USE_REG_TB) { | 62 | + * The requested zero result does not match the insn, so adjust. |
209 | + insn = MTSPR | RS(TCG_REG_TB) | CTR; | 63 | + * Note that constraints put 'ret' in a new register, so the |
210 | + } else { | 64 | + * computation above did not clobber either 'src1' or 'src2'. |
211 | + insn = NOP; | 65 | + */ |
66 | + tcg_out_movcond(s, TCG_COND_EQ, ret, src1, 0, true, | ||
67 | + src2, c_src2, ret, false); | ||
212 | + } | 68 | + } |
213 | + | ||
214 | + qatomic_set((uint32_t *)jmp_rw, insn); | ||
215 | + flush_idcache_range(jmp_rx, jmp_rw, 4); | ||
216 | +} | 69 | +} |
217 | + | 70 | + |
218 | static void tcg_out_op(TCGContext *s, TCGOpcode opc, | 71 | static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail) |
219 | const TCGArg args[TCG_MAX_OP_ARGS], | 72 | { |
220 | const int const_args[TCG_MAX_OP_ARGS]) | 73 | TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA; |
74 | @@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, | ||
75 | tcg_out_opc_imm(s, OPC_CPOP, a0, a1, 0); | ||
76 | break; | ||
77 | |||
78 | + case INDEX_op_clz_i32: | ||
79 | + tcg_out_cltz(s, TCG_TYPE_I32, OPC_CLZW, a0, a1, a2, c2); | ||
80 | + break; | ||
81 | + case INDEX_op_clz_i64: | ||
82 | + tcg_out_cltz(s, TCG_TYPE_I64, OPC_CLZ, a0, a1, a2, c2); | ||
83 | + break; | ||
84 | + case INDEX_op_ctz_i32: | ||
85 | + tcg_out_cltz(s, TCG_TYPE_I32, OPC_CTZW, a0, a1, a2, c2); | ||
86 | + break; | ||
87 | + case INDEX_op_ctz_i64: | ||
88 | + tcg_out_cltz(s, TCG_TYPE_I64, OPC_CTZ, a0, a1, a2, c2); | ||
89 | + break; | ||
90 | + | ||
91 | case INDEX_op_add2_i32: | ||
92 | tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5], | ||
93 | const_args[4], const_args[5], false, true); | ||
94 | @@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op) | ||
95 | case INDEX_op_rotr_i64: | ||
96 | return C_O1_I2(r, r, ri); | ||
97 | |||
98 | + case INDEX_op_clz_i32: | ||
99 | + case INDEX_op_clz_i64: | ||
100 | + case INDEX_op_ctz_i32: | ||
101 | + case INDEX_op_ctz_i64: | ||
102 | + return C_N1_I2(r, r, rM); | ||
103 | + | ||
104 | case INDEX_op_brcond_i32: | ||
105 | case INDEX_op_brcond_i64: | ||
106 | return C_O0_I2(rZ, rZ); | ||
221 | -- | 107 | -- |
222 | 2.34.1 | 108 | 2.34.1 |
223 | |||
224 | diff view generated by jsdifflib |