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