1
The following changes since commit 77f3804ab7ed94b471a14acb260e5aeacf26193f:
1
Changes since v1:
2
* Added QEMU_ERROR to wrap __attribute__((error)) -- patch 12.
2
3
3
Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging (2021-02-02 16:47:51 +0000)
4
5
r~
6
7
8
The following changes since commit 77f7c747193662edfadeeb3118d63eed0eac51a6:
9
10
Merge remote-tracking branch 'remotes/huth-gitlab/tags/pull-request-2018-10-17' into staging (2018-10-18 13:40:19 +0100)
4
11
5
are available in the Git repository at:
12
are available in the Git repository at:
6
13
7
https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20210202
14
https://github.com/rth7680/qemu.git tags/pull-tcg-20181018
8
15
9
for you to fetch changes up to 0c823e596877a30fd6c17a1ae9f98218a53055ea:
16
for you to fetch changes up to 403f290c0603f35f2d09c982bf5549b6d0803ec1:
10
17
11
tcg: Remove TCG_TARGET_CON_SET_H (2021-02-02 12:12:43 -1000)
18
cputlb: read CPUTLBEntry.addr_write atomically (2018-10-18 19:46:53 -0700)
12
19
13
----------------------------------------------------------------
20
----------------------------------------------------------------
14
TCG backend constraints cleanup
21
Queued tcg patches.
15
22
16
----------------------------------------------------------------
23
----------------------------------------------------------------
17
Richard Henderson (24):
24
Emilio G. Cota (10):
18
tcg/tci: Drop L and S constraints
25
tcg: access cpu->icount_decr.u16.high with atomics
19
tcg/tci: Remove TCG_TARGET_HAS_* ifdefs
26
tcg: fix use of uninitialized variable under CONFIG_PROFILER
20
tcg/i386: Move constraint type check to tcg_target_const_match
27
tcg: plug holes in struct TCGProfile
21
tcg/i386: Tidy register constraint definitions
28
tcg: distribute tcg_time into TCG contexts
22
tcg/i386: Split out target constraints to tcg-target-con-str.h
29
target/alpha: remove tlb_flush from alpha_cpu_initfn
23
tcg/arm: Split out target constraints to tcg-target-con-str.h
30
target/unicore32: remove tlb_flush from uc32_init_fn
24
tcg/aarch64: Split out target constraints to tcg-target-con-str.h
31
exec: introduce tlb_init
25
tcg/ppc: Split out target constraints to tcg-target-con-str.h
32
cputlb: fix assert_cpu_is_self macro
26
tcg/tci: Split out target constraints to tcg-target-con-str.h
33
cputlb: serialize tlb updates with env->tlb_lock
27
tcg/mips: Split out target constraints to tcg-target-con-str.h
34
cputlb: read CPUTLBEntry.addr_write atomically
28
tcg/riscv: Split out target constraints to tcg-target-con-str.h
29
tcg/s390: Split out target constraints to tcg-target-con-str.h
30
tcg/sparc: Split out target constraints to tcg-target-con-str.h
31
tcg: Remove TCG_TARGET_CON_STR_H
32
tcg/i386: Split out constraint sets to tcg-target-con-set.h
33
tcg/aarch64: Split out constraint sets to tcg-target-con-set.h
34
tcg/arm: Split out constraint sets to tcg-target-con-set.h
35
tcg/mips: Split out constraint sets to tcg-target-con-set.h
36
tcg/ppc: Split out constraint sets to tcg-target-con-set.h
37
tcg/riscv: Split out constraint sets to tcg-target-con-set.h
38
tcg/s390: Split out constraint sets to tcg-target-con-set.h
39
tcg/sparc: Split out constraint sets to tcg-target-con-set.h
40
tcg/tci: Split out constraint sets to tcg-target-con-set.h
41
tcg: Remove TCG_TARGET_CON_SET_H
42
35
43
tcg/aarch64/tcg-target-con-set.h | 36 ++++
36
Richard Henderson (11):
44
tcg/aarch64/tcg-target-con-str.h | 24 +++
37
tcg: Implement CPU_LOG_TB_NOCHAIN during expansion
45
tcg/arm/tcg-target-con-set.h | 35 ++++
38
tcg: Add tlb_index and tlb_entry helpers
46
tcg/arm/tcg-target-con-str.h | 22 +++
39
tcg: Split CONFIG_ATOMIC128
47
tcg/i386/tcg-target-con-set.h | 55 ++++++
40
target/i386: Convert to HAVE_CMPXCHG128
48
tcg/i386/tcg-target-con-str.h | 33 ++++
41
target/arm: Convert to HAVE_CMPXCHG128
49
tcg/mips/tcg-target-con-set.h | 36 ++++
42
target/arm: Check HAVE_CMPXCHG128 at translate time
50
tcg/mips/tcg-target-con-str.h | 24 +++
43
target/ppc: Convert to HAVE_CMPXCHG128 and HAVE_ATOMIC128
51
tcg/ppc/tcg-target-con-set.h | 42 +++++
44
target/s390x: Convert to HAVE_CMPXCHG128 and HAVE_ATOMIC128
52
tcg/ppc/tcg-target-con-str.h | 30 ++++
45
target/s390x: Split do_cdsg, do_lpq, do_stpq
53
tcg/riscv/tcg-target-con-set.h | 30 ++++
46
target/s390x: Skip wout, cout helpers if op helper does not return
54
tcg/riscv/tcg-target-con-str.h | 21 +++
47
target/s390x: Check HAVE_ATOMIC128 and HAVE_CMPXCHG128 at translate
55
tcg/s390/tcg-target-con-set.h | 29 ++++
56
tcg/s390/tcg-target-con-str.h | 28 +++
57
tcg/sparc/tcg-target-con-set.h | 32 ++++
58
tcg/sparc/tcg-target-con-str.h | 23 +++
59
tcg/sparc/tcg-target.h | 4 -
60
tcg/tci/tcg-target-con-set.h | 25 +++
61
tcg/tci/tcg-target-con-str.h | 11 ++
62
tcg/tcg.c | 136 +++++++++++++--
63
tcg/aarch64/tcg-target.c.inc | 137 ++++-----------
64
tcg/arm/tcg-target.c.inc | 168 ++++++------------
65
tcg/i386/tcg-target.c.inc | 317 +++++++++++-----------------------
66
tcg/mips/tcg-target.c.inc | 173 ++++++-------------
67
tcg/ppc/tcg-target.c.inc | 209 ++++++++---------------
68
tcg/riscv/tcg-target.c.inc | 135 ++++-----------
69
tcg/s390/tcg-target.c.inc | 174 +++++++------------
70
tcg/sparc/tcg-target.c.inc | 156 ++++++-----------
71
tcg/tci/tcg-target.c.inc | 359 ++++++++++++++-------------------------
72
29 files changed, 1244 insertions(+), 1260 deletions(-)
73
create mode 100644 tcg/aarch64/tcg-target-con-set.h
74
create mode 100644 tcg/aarch64/tcg-target-con-str.h
75
create mode 100644 tcg/arm/tcg-target-con-set.h
76
create mode 100644 tcg/arm/tcg-target-con-str.h
77
create mode 100644 tcg/i386/tcg-target-con-set.h
78
create mode 100644 tcg/i386/tcg-target-con-str.h
79
create mode 100644 tcg/mips/tcg-target-con-set.h
80
create mode 100644 tcg/mips/tcg-target-con-str.h
81
create mode 100644 tcg/ppc/tcg-target-con-set.h
82
create mode 100644 tcg/ppc/tcg-target-con-str.h
83
create mode 100644 tcg/riscv/tcg-target-con-set.h
84
create mode 100644 tcg/riscv/tcg-target-con-str.h
85
create mode 100644 tcg/s390/tcg-target-con-set.h
86
create mode 100644 tcg/s390/tcg-target-con-str.h
87
create mode 100644 tcg/sparc/tcg-target-con-set.h
88
create mode 100644 tcg/sparc/tcg-target-con-str.h
89
create mode 100644 tcg/tci/tcg-target-con-set.h
90
create mode 100644 tcg/tci/tcg-target-con-str.h
91
48
49
accel/tcg/atomic_template.h | 20 +++-
50
accel/tcg/softmmu_template.h | 64 +++++-----
51
include/exec/cpu-defs.h | 3 +
52
include/exec/cpu_ldst.h | 30 ++++-
53
include/exec/cpu_ldst_template.h | 25 ++--
54
include/exec/exec-all.h | 8 ++
55
include/qemu/atomic128.h | 153 ++++++++++++++++++++++++
56
include/qemu/compiler.h | 11 ++
57
include/qemu/timer.h | 1 -
58
target/ppc/helper.h | 2 +-
59
tcg/tcg.h | 20 ++--
60
accel/tcg/cpu-exec.c | 2 +-
61
accel/tcg/cputlb.c | 235 +++++++++++++++++++-----------------
62
accel/tcg/tcg-all.c | 2 +-
63
accel/tcg/translate-all.c | 2 +-
64
accel/tcg/user-exec.c | 5 +-
65
cpus.c | 3 +-
66
exec.c | 1 +
67
monitor.c | 13 +-
68
qom/cpu.c | 2 +-
69
target/alpha/cpu.c | 1 -
70
target/arm/helper-a64.c | 251 +++++++++++++++++++--------------------
71
target/arm/translate-a64.c | 38 +++---
72
target/i386/mem_helper.c | 9 +-
73
target/ppc/mem_helper.c | 33 ++++-
74
target/ppc/translate.c | 115 +++++++++---------
75
target/s390x/mem_helper.c | 202 +++++++++++++++----------------
76
target/s390x/translate.c | 45 +++++--
77
target/unicore32/cpu.c | 2 -
78
tcg/tcg-op.c | 9 +-
79
tcg/tcg.c | 25 +++-
80
configure | 19 +++
81
32 files changed, 839 insertions(+), 512 deletions(-)
82
create mode 100644 include/qemu/atomic128.h
83
diff view generated by jsdifflib
Deleted patch
1
These are identical to the 'r' constraint.
2
1
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
---
6
tcg/tci/tcg-target.c.inc | 10 ++++------
7
1 file changed, 4 insertions(+), 6 deletions(-)
8
9
diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
10
index XXXXXXX..XXXXXXX 100644
11
--- a/tcg/tci/tcg-target.c.inc
12
+++ b/tcg/tci/tcg-target.c.inc
13
@@ -XXX,XX +XXX,XX @@
14
# define R64 "r"
15
#endif
16
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
17
-# define L "L", "L"
18
-# define S "S", "S"
19
+# define L "r", "r"
20
+# define S "r", "r"
21
#else
22
-# define L "L"
23
-# define S "S"
24
+# define L "r"
25
+# define S "r"
26
#endif
27
28
/* TODO: documentation. */
29
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
30
{
31
switch (*ct_str++) {
32
case 'r':
33
- case 'L': /* qemu_ld constraint */
34
- case 'S': /* qemu_st constraint */
35
ct->regs = BIT(TCG_TARGET_NB_REGS) - 1;
36
break;
37
default:
38
--
39
2.25.1
40
41
diff view generated by jsdifflib
Deleted patch
1
The opcodes always exist, regardless of whether or not they
2
are enabled. Remove the unnecessary ifdefs.
3
1
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
---
6
tcg/tci/tcg-target.c.inc | 82 ----------------------------------------
7
1 file changed, 82 deletions(-)
8
9
diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
10
index XXXXXXX..XXXXXXX 100644
11
--- a/tcg/tci/tcg-target.c.inc
12
+++ b/tcg/tci/tcg-target.c.inc
13
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef tcg_target_op_defs[] = {
14
{ INDEX_op_add_i32, { R, RI, RI } },
15
{ INDEX_op_sub_i32, { R, RI, RI } },
16
{ INDEX_op_mul_i32, { R, RI, RI } },
17
-#if TCG_TARGET_HAS_div_i32
18
{ INDEX_op_div_i32, { R, R, R } },
19
{ INDEX_op_divu_i32, { R, R, R } },
20
{ INDEX_op_rem_i32, { R, R, R } },
21
{ INDEX_op_remu_i32, { R, R, R } },
22
-#elif TCG_TARGET_HAS_div2_i32
23
- { INDEX_op_div2_i32, { R, R, "0", "1", R } },
24
- { INDEX_op_divu2_i32, { R, R, "0", "1", R } },
25
-#endif
26
/* TODO: Does R, RI, RI result in faster code than R, R, RI?
27
If both operands are constants, we can optimize. */
28
{ INDEX_op_and_i32, { R, RI, RI } },
29
-#if TCG_TARGET_HAS_andc_i32
30
{ INDEX_op_andc_i32, { R, RI, RI } },
31
-#endif
32
-#if TCG_TARGET_HAS_eqv_i32
33
{ INDEX_op_eqv_i32, { R, RI, RI } },
34
-#endif
35
-#if TCG_TARGET_HAS_nand_i32
36
{ INDEX_op_nand_i32, { R, RI, RI } },
37
-#endif
38
-#if TCG_TARGET_HAS_nor_i32
39
{ INDEX_op_nor_i32, { R, RI, RI } },
40
-#endif
41
{ INDEX_op_or_i32, { R, RI, RI } },
42
-#if TCG_TARGET_HAS_orc_i32
43
{ INDEX_op_orc_i32, { R, RI, RI } },
44
-#endif
45
{ INDEX_op_xor_i32, { R, RI, RI } },
46
{ INDEX_op_shl_i32, { R, RI, RI } },
47
{ INDEX_op_shr_i32, { R, RI, RI } },
48
{ INDEX_op_sar_i32, { R, RI, RI } },
49
-#if TCG_TARGET_HAS_rot_i32
50
{ INDEX_op_rotl_i32, { R, RI, RI } },
51
{ INDEX_op_rotr_i32, { R, RI, RI } },
52
-#endif
53
-#if TCG_TARGET_HAS_deposit_i32
54
{ INDEX_op_deposit_i32, { R, "0", R } },
55
-#endif
56
57
{ INDEX_op_brcond_i32, { R, RI } },
58
59
{ INDEX_op_setcond_i32, { R, R, RI } },
60
-#if TCG_TARGET_REG_BITS == 64
61
{ INDEX_op_setcond_i64, { R, R, RI } },
62
-#endif /* TCG_TARGET_REG_BITS == 64 */
63
64
-#if TCG_TARGET_REG_BITS == 32
65
/* TODO: Support R, R, R, R, RI, RI? Will it be faster? */
66
{ INDEX_op_add2_i32, { R, R, R, R, R, R } },
67
{ INDEX_op_sub2_i32, { R, R, R, R, R, R } },
68
{ INDEX_op_brcond2_i32, { R, R, RI, RI } },
69
{ INDEX_op_mulu2_i32, { R, R, R, R } },
70
{ INDEX_op_setcond2_i32, { R, R, R, RI, RI } },
71
-#endif
72
73
-#if TCG_TARGET_HAS_not_i32
74
{ INDEX_op_not_i32, { R, R } },
75
-#endif
76
-#if TCG_TARGET_HAS_neg_i32
77
{ INDEX_op_neg_i32, { R, R } },
78
-#endif
79
80
-#if TCG_TARGET_REG_BITS == 64
81
{ INDEX_op_ld8u_i64, { R, R } },
82
{ INDEX_op_ld8s_i64, { R, R } },
83
{ INDEX_op_ld16u_i64, { R, R } },
84
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef tcg_target_op_defs[] = {
85
{ INDEX_op_add_i64, { R, RI, RI } },
86
{ INDEX_op_sub_i64, { R, RI, RI } },
87
{ INDEX_op_mul_i64, { R, RI, RI } },
88
-#if TCG_TARGET_HAS_div_i64
89
{ INDEX_op_div_i64, { R, R, R } },
90
{ INDEX_op_divu_i64, { R, R, R } },
91
{ INDEX_op_rem_i64, { R, R, R } },
92
{ INDEX_op_remu_i64, { R, R, R } },
93
-#elif TCG_TARGET_HAS_div2_i64
94
- { INDEX_op_div2_i64, { R, R, "0", "1", R } },
95
- { INDEX_op_divu2_i64, { R, R, "0", "1", R } },
96
-#endif
97
{ INDEX_op_and_i64, { R, RI, RI } },
98
-#if TCG_TARGET_HAS_andc_i64
99
{ INDEX_op_andc_i64, { R, RI, RI } },
100
-#endif
101
-#if TCG_TARGET_HAS_eqv_i64
102
{ INDEX_op_eqv_i64, { R, RI, RI } },
103
-#endif
104
-#if TCG_TARGET_HAS_nand_i64
105
{ INDEX_op_nand_i64, { R, RI, RI } },
106
-#endif
107
-#if TCG_TARGET_HAS_nor_i64
108
{ INDEX_op_nor_i64, { R, RI, RI } },
109
-#endif
110
{ INDEX_op_or_i64, { R, RI, RI } },
111
-#if TCG_TARGET_HAS_orc_i64
112
{ INDEX_op_orc_i64, { R, RI, RI } },
113
-#endif
114
{ INDEX_op_xor_i64, { R, RI, RI } },
115
{ INDEX_op_shl_i64, { R, RI, RI } },
116
{ INDEX_op_shr_i64, { R, RI, RI } },
117
{ INDEX_op_sar_i64, { R, RI, RI } },
118
-#if TCG_TARGET_HAS_rot_i64
119
{ INDEX_op_rotl_i64, { R, RI, RI } },
120
{ INDEX_op_rotr_i64, { R, RI, RI } },
121
-#endif
122
-#if TCG_TARGET_HAS_deposit_i64
123
{ INDEX_op_deposit_i64, { R, "0", R } },
124
-#endif
125
{ INDEX_op_brcond_i64, { R, RI } },
126
127
-#if TCG_TARGET_HAS_ext8s_i64
128
{ INDEX_op_ext8s_i64, { R, R } },
129
-#endif
130
-#if TCG_TARGET_HAS_ext16s_i64
131
{ INDEX_op_ext16s_i64, { R, R } },
132
-#endif
133
-#if TCG_TARGET_HAS_ext32s_i64
134
{ INDEX_op_ext32s_i64, { R, R } },
135
-#endif
136
-#if TCG_TARGET_HAS_ext8u_i64
137
{ INDEX_op_ext8u_i64, { R, R } },
138
-#endif
139
-#if TCG_TARGET_HAS_ext16u_i64
140
{ INDEX_op_ext16u_i64, { R, R } },
141
-#endif
142
-#if TCG_TARGET_HAS_ext32u_i64
143
{ INDEX_op_ext32u_i64, { R, R } },
144
-#endif
145
{ INDEX_op_ext_i32_i64, { R, R } },
146
{ INDEX_op_extu_i32_i64, { R, R } },
147
-#if TCG_TARGET_HAS_bswap16_i64
148
{ INDEX_op_bswap16_i64, { R, R } },
149
-#endif
150
-#if TCG_TARGET_HAS_bswap32_i64
151
{ INDEX_op_bswap32_i64, { R, R } },
152
-#endif
153
-#if TCG_TARGET_HAS_bswap64_i64
154
{ INDEX_op_bswap64_i64, { R, R } },
155
-#endif
156
-#if TCG_TARGET_HAS_not_i64
157
{ INDEX_op_not_i64, { R, R } },
158
-#endif
159
-#if TCG_TARGET_HAS_neg_i64
160
{ INDEX_op_neg_i64, { R, R } },
161
-#endif
162
-#endif /* TCG_TARGET_REG_BITS == 64 */
163
164
{ INDEX_op_qemu_ld_i32, { R, L } },
165
{ INDEX_op_qemu_ld_i64, { R64, L } },
166
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef tcg_target_op_defs[] = {
167
{ INDEX_op_qemu_st_i32, { R, S } },
168
{ INDEX_op_qemu_st_i64, { R64, S } },
169
170
-#if TCG_TARGET_HAS_ext8s_i32
171
{ INDEX_op_ext8s_i32, { R, R } },
172
-#endif
173
-#if TCG_TARGET_HAS_ext16s_i32
174
{ INDEX_op_ext16s_i32, { R, R } },
175
-#endif
176
-#if TCG_TARGET_HAS_ext8u_i32
177
{ INDEX_op_ext8u_i32, { R, R } },
178
-#endif
179
-#if TCG_TARGET_HAS_ext16u_i32
180
{ INDEX_op_ext16u_i32, { R, R } },
181
-#endif
182
183
-#if TCG_TARGET_HAS_bswap16_i32
184
{ INDEX_op_bswap16_i32, { R, R } },
185
-#endif
186
-#if TCG_TARGET_HAS_bswap32_i32
187
{ INDEX_op_bswap32_i32, { R, R } },
188
-#endif
189
190
{ INDEX_op_mb, { } },
191
{ -1 },
192
--
193
2.25.1
194
195
diff view generated by jsdifflib
1
All backends have now been converted to tcg-target-con-set.h,
1
Rather than test NOCHAIN before linking, do not emit the
2
so we can remove the fallback code.
2
goto_tb opcode at all. We already do this for goto_ptr.
3
3
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
5
---
8
tcg/aarch64/tcg-target.h | 1 -
6
accel/tcg/cpu-exec.c | 2 +-
9
tcg/arm/tcg-target.h | 1 -
7
tcg/tcg-op.c | 9 ++++++++-
10
tcg/i386/tcg-target.h | 1 -
8
2 files changed, 9 insertions(+), 2 deletions(-)
11
tcg/mips/tcg-target.h | 1 -
12
tcg/ppc/tcg-target.h | 1 -
13
tcg/riscv/tcg-target.h | 1 -
14
tcg/s390/tcg-target.h | 1 -
15
tcg/sparc/tcg-target.h | 1 -
16
tcg/tci/tcg-target.h | 2 --
17
tcg/tcg.c | 12 ------------
18
10 files changed, 22 deletions(-)
19
9
20
diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h
10
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
21
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
22
--- a/tcg/aarch64/tcg-target.h
12
--- a/accel/tcg/cpu-exec.c
23
+++ b/tcg/aarch64/tcg-target.h
13
+++ b/accel/tcg/cpu-exec.c
24
@@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
14
@@ -XXX,XX +XXX,XX @@ static inline TranslationBlock *tb_find(CPUState *cpu,
25
#define TCG_TARGET_NEED_LDST_LABELS
15
}
26
#endif
16
#endif
27
#define TCG_TARGET_NEED_POOL_LABELS
17
/* See if we can patch the calling TB. */
28
-#define TCG_TARGET_CON_SET_H
18
- if (last_tb && !qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
29
19
+ if (last_tb) {
30
#endif /* AARCH64_TCG_TARGET_H */
20
tb_add_jump(last_tb, tb_exit, tb);
31
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
21
}
22
return tb;
23
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
32
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
33
--- a/tcg/arm/tcg-target.h
25
--- a/tcg/tcg-op.c
34
+++ b/tcg/arm/tcg-target.h
26
+++ b/tcg/tcg-op.c
35
@@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
27
@@ -XXX,XX +XXX,XX @@ void tcg_gen_exit_tb(TranslationBlock *tb, unsigned idx)
36
#define TCG_TARGET_NEED_LDST_LABELS
28
seen this numbered exit before, via tcg_gen_goto_tb. */
29
tcg_debug_assert(tcg_ctx->goto_tb_issue_mask & (1 << idx));
37
#endif
30
#endif
38
#define TCG_TARGET_NEED_POOL_LABELS
31
+ /* When not chaining, exit without indicating a link. */
39
-#define TCG_TARGET_CON_SET_H
32
+ if (qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
40
33
+ val = 0;
34
+ }
35
} else {
36
/* This is an exit via the exitreq label. */
37
tcg_debug_assert(idx == TB_EXIT_REQUESTED);
38
@@ -XXX,XX +XXX,XX @@ void tcg_gen_goto_tb(unsigned idx)
39
tcg_debug_assert((tcg_ctx->goto_tb_issue_mask & (1 << idx)) == 0);
40
tcg_ctx->goto_tb_issue_mask |= 1 << idx;
41
#endif
41
#endif
42
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
42
- tcg_gen_op1i(INDEX_op_goto_tb, idx);
43
index XXXXXXX..XXXXXXX 100644
43
+ /* When not chaining, we simply fall through to the "fallback" exit. */
44
--- a/tcg/i386/tcg-target.h
44
+ if (!qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
45
+++ b/tcg/i386/tcg-target.h
45
+ tcg_gen_op1i(INDEX_op_goto_tb, idx);
46
@@ -XXX,XX +XXX,XX @@ static inline void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
46
+ }
47
#define TCG_TARGET_NEED_LDST_LABELS
48
#endif
49
#define TCG_TARGET_NEED_POOL_LABELS
50
-#define TCG_TARGET_CON_SET_H
51
52
#endif
53
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
54
index XXXXXXX..XXXXXXX 100644
55
--- a/tcg/mips/tcg-target.h
56
+++ b/tcg/mips/tcg-target.h
57
@@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
58
#ifdef CONFIG_SOFTMMU
59
#define TCG_TARGET_NEED_LDST_LABELS
60
#endif
61
-#define TCG_TARGET_CON_SET_H
62
63
#endif
64
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
65
index XXXXXXX..XXXXXXX 100644
66
--- a/tcg/ppc/tcg-target.h
67
+++ b/tcg/ppc/tcg-target.h
68
@@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
69
#define TCG_TARGET_NEED_LDST_LABELS
70
#endif
71
#define TCG_TARGET_NEED_POOL_LABELS
72
-#define TCG_TARGET_CON_SET_H
73
74
#endif
75
diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
76
index XXXXXXX..XXXXXXX 100644
77
--- a/tcg/riscv/tcg-target.h
78
+++ b/tcg/riscv/tcg-target.h
79
@@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
80
#define TCG_TARGET_NEED_POOL_LABELS
81
82
#define TCG_TARGET_HAS_MEMORY_BSWAP 0
83
-#define TCG_TARGET_CON_SET_H
84
85
#endif
86
diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h
87
index XXXXXXX..XXXXXXX 100644
88
--- a/tcg/s390/tcg-target.h
89
+++ b/tcg/s390/tcg-target.h
90
@@ -XXX,XX +XXX,XX @@ static inline void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
91
#define TCG_TARGET_NEED_LDST_LABELS
92
#endif
93
#define TCG_TARGET_NEED_POOL_LABELS
94
-#define TCG_TARGET_CON_SET_H
95
96
#endif
97
diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
98
index XXXXXXX..XXXXXXX 100644
99
--- a/tcg/sparc/tcg-target.h
100
+++ b/tcg/sparc/tcg-target.h
101
@@ -XXX,XX +XXX,XX @@ extern bool use_vis3_instructions;
102
void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
103
104
#define TCG_TARGET_NEED_POOL_LABELS
105
-#define TCG_TARGET_CON_SET_H
106
107
#endif
108
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
109
index XXXXXXX..XXXXXXX 100644
110
--- a/tcg/tci/tcg-target.h
111
+++ b/tcg/tci/tcg-target.h
112
@@ -XXX,XX +XXX,XX @@ static inline void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
113
/* no need to flush icache explicitly */
114
}
47
}
115
48
116
-#define TCG_TARGET_CON_SET_H
49
void tcg_gen_lookup_and_goto_ptr(void)
117
-
118
#endif /* TCG_TARGET_H */
119
diff --git a/tcg/tcg.c b/tcg/tcg.c
120
index XXXXXXX..XXXXXXX 100644
121
--- a/tcg/tcg.c
122
+++ b/tcg/tcg.c
123
@@ -XXX,XX +XXX,XX @@
124
/* Forward declarations for functions declared in tcg-target.c.inc and
125
used here. */
126
static void tcg_target_init(TCGContext *s);
127
-#ifndef TCG_TARGET_CON_SET_H
128
-static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode);
129
-#endif
130
static void tcg_target_qemu_prologue(TCGContext *s);
131
static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
132
intptr_t value, intptr_t addend);
133
@@ -XXX,XX +XXX,XX @@ static void set_jmp_reset_offset(TCGContext *s, int which)
134
s->tb_jmp_reset_offset[which] = tcg_current_code_size(s);
135
}
136
137
-#ifdef TCG_TARGET_CON_SET_H
138
#define C_PFX1(P, A) P##A
139
#define C_PFX2(P, A, B) P##A##_##B
140
#define C_PFX3(P, A, B, C) P##A##_##B##_##C
141
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef constraint_sets[] = {
142
#define C_O2_I3(O1, O2, I1, I2, I3) C_PFX5(c_o2_i3_, O1, O2, I1, I2, I3)
143
#define C_O2_I4(O1, O2, I1, I2, I3, I4) C_PFX6(c_o2_i4_, O1, O2, I1, I2, I3, I4)
144
145
-#endif /* TCG_TARGET_CON_SET_H */
146
-
147
#include "tcg-target.c.inc"
148
149
/* compare a pointer @ptr and a tb_tc @s */
150
@@ -XXX,XX +XXX,XX @@ static void process_op_defs(TCGContext *s)
151
continue;
152
}
153
154
-#ifdef TCG_TARGET_CON_SET_H
155
/*
156
* Macro magic should make it impossible, but double-check that
157
* the array index is in range. Since the signness of an enum
158
@@ -XXX,XX +XXX,XX @@ static void process_op_defs(TCGContext *s)
159
unsigned con_set = tcg_target_op_def(op);
160
tcg_debug_assert(con_set < ARRAY_SIZE(constraint_sets));
161
tdefs = &constraint_sets[con_set];
162
-#else
163
- tdefs = tcg_target_op_def(op);
164
- /* Missing TCGTargetOpDef entry. */
165
- tcg_debug_assert(tdefs != NULL);
166
-#endif
167
168
for (i = 0; i < nb_args; i++) {
169
const char *ct_str = tdefs->args_ct_str[i];
170
--
50
--
171
2.25.1
51
2.17.2
172
52
173
53
diff view generated by jsdifflib
1
This requires finishing the conversion to tcg_target_op_def.
1
From: "Emilio G. Cota" <cota@braap.org>
2
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Consistently access u16.high with atomics to avoid
4
undefined behaviour in MTTCG.
5
6
Note that icount_decr.u16.low is only used in icount mode,
7
so regular accesses to it are OK.
8
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Emilio G. Cota <cota@braap.org>
11
Message-Id: <20181010144853.13005-2-cota@braap.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
---
13
---
6
tcg/tci/tcg-target-con-set.h | 25 ++++
14
accel/tcg/tcg-all.c | 2 +-
7
tcg/tci/tcg-target.h | 2 +
15
accel/tcg/translate-all.c | 2 +-
8
tcg/tci/tcg-target.c.inc | 279 +++++++++++++++++------------------
16
qom/cpu.c | 2 +-
9
3 files changed, 161 insertions(+), 145 deletions(-)
17
3 files changed, 3 insertions(+), 3 deletions(-)
10
create mode 100644 tcg/tci/tcg-target-con-set.h
11
18
12
diff --git a/tcg/tci/tcg-target-con-set.h b/tcg/tci/tcg-target-con-set.h
19
diff --git a/accel/tcg/tcg-all.c b/accel/tcg/tcg-all.c
13
new file mode 100644
14
index XXXXXXX..XXXXXXX
15
--- /dev/null
16
+++ b/tcg/tci/tcg-target-con-set.h
17
@@ -XXX,XX +XXX,XX @@
18
+/* SPDX-License-Identifier: MIT */
19
+/*
20
+ * TCI target-specific constraint sets.
21
+ * Copyright (c) 2021 Linaro
22
+ */
23
+
24
+/*
25
+ * C_On_Im(...) defines a constraint set with <n> outputs and <m> inputs.
26
+ * Each operand should be a sequence of constraint letters as defined by
27
+ * tcg-target-con-str.h; the constraint combination is inclusive or.
28
+ */
29
+C_O0_I2(r, r)
30
+C_O0_I2(r, ri)
31
+C_O0_I3(r, r, r)
32
+C_O0_I4(r, r, ri, ri)
33
+C_O0_I4(r, r, r, r)
34
+C_O1_I1(r, r)
35
+C_O1_I2(r, 0, r)
36
+C_O1_I2(r, ri, ri)
37
+C_O1_I2(r, r, r)
38
+C_O1_I2(r, r, ri)
39
+C_O1_I4(r, r, r, ri, ri)
40
+C_O2_I1(r, r, r)
41
+C_O2_I2(r, r, r, r)
42
+C_O2_I4(r, r, r, r, r, r)
43
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
44
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
45
--- a/tcg/tci/tcg-target.h
21
--- a/accel/tcg/tcg-all.c
46
+++ b/tcg/tci/tcg-target.h
22
+++ b/accel/tcg/tcg-all.c
47
@@ -XXX,XX +XXX,XX @@ static inline void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
23
@@ -XXX,XX +XXX,XX @@ static void tcg_handle_interrupt(CPUState *cpu, int mask)
48
/* no need to flush icache explicitly */
24
if (!qemu_cpu_is_self(cpu)) {
25
qemu_cpu_kick(cpu);
26
} else {
27
- cpu->icount_decr.u16.high = -1;
28
+ atomic_set(&cpu->icount_decr.u16.high, -1);
29
if (use_icount &&
30
!cpu->can_do_io
31
&& (mask & ~old_mask) != 0) {
32
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/accel/tcg/translate-all.c
35
+++ b/accel/tcg/translate-all.c
36
@@ -XXX,XX +XXX,XX @@ void cpu_interrupt(CPUState *cpu, int mask)
37
{
38
g_assert(qemu_mutex_iothread_locked());
39
cpu->interrupt_request |= mask;
40
- cpu->icount_decr.u16.high = -1;
41
+ atomic_set(&cpu->icount_decr.u16.high, -1);
49
}
42
}
50
43
51
+#define TCG_TARGET_CON_SET_H
44
/*
52
+
45
diff --git a/qom/cpu.c b/qom/cpu.c
53
#endif /* TCG_TARGET_H */
54
diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
55
index XXXXXXX..XXXXXXX 100644
46
index XXXXXXX..XXXXXXX 100644
56
--- a/tcg/tci/tcg-target.c.inc
47
--- a/qom/cpu.c
57
+++ b/tcg/tci/tcg-target.c.inc
48
+++ b/qom/cpu.c
58
@@ -XXX,XX +XXX,XX @@
49
@@ -XXX,XX +XXX,XX @@ static void cpu_common_reset(CPUState *cpu)
59
/* Bitfield n...m (in 32 bit value). */
50
cpu->mem_io_pc = 0;
60
#define BITS(n, m) (((0xffffffffU << (31 - n)) >> (31 - n + m)) << m)
51
cpu->mem_io_vaddr = 0;
61
52
cpu->icount_extra = 0;
62
-/* Macros used in tcg_target_op_defs. */
53
- cpu->icount_decr.u32 = 0;
63
-#define R "r"
54
+ atomic_set(&cpu->icount_decr.u32, 0);
64
-#define RI "ri"
55
cpu->can_do_io = 1;
65
-#if TCG_TARGET_REG_BITS == 32
56
cpu->exception_index = -1;
66
-# define R64 "r", "r"
57
cpu->crash_occurred = false;
67
-#else
68
-# define R64 "r"
69
-#endif
70
-#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
71
-# define L "r", "r"
72
-# define S "r", "r"
73
-#else
74
-# define L "r"
75
-# define S "r"
76
-#endif
77
-
78
-/* TODO: documentation. */
79
-static const TCGTargetOpDef tcg_target_op_defs[] = {
80
- { INDEX_op_exit_tb, { NULL } },
81
- { INDEX_op_goto_tb, { NULL } },
82
- { INDEX_op_br, { NULL } },
83
-
84
- { INDEX_op_ld8u_i32, { R, R } },
85
- { INDEX_op_ld8s_i32, { R, R } },
86
- { INDEX_op_ld16u_i32, { R, R } },
87
- { INDEX_op_ld16s_i32, { R, R } },
88
- { INDEX_op_ld_i32, { R, R } },
89
- { INDEX_op_st8_i32, { R, R } },
90
- { INDEX_op_st16_i32, { R, R } },
91
- { INDEX_op_st_i32, { R, R } },
92
-
93
- { INDEX_op_add_i32, { R, RI, RI } },
94
- { INDEX_op_sub_i32, { R, RI, RI } },
95
- { INDEX_op_mul_i32, { R, RI, RI } },
96
- { INDEX_op_div_i32, { R, R, R } },
97
- { INDEX_op_divu_i32, { R, R, R } },
98
- { INDEX_op_rem_i32, { R, R, R } },
99
- { INDEX_op_remu_i32, { R, R, R } },
100
- /* TODO: Does R, RI, RI result in faster code than R, R, RI?
101
- If both operands are constants, we can optimize. */
102
- { INDEX_op_and_i32, { R, RI, RI } },
103
- { INDEX_op_andc_i32, { R, RI, RI } },
104
- { INDEX_op_eqv_i32, { R, RI, RI } },
105
- { INDEX_op_nand_i32, { R, RI, RI } },
106
- { INDEX_op_nor_i32, { R, RI, RI } },
107
- { INDEX_op_or_i32, { R, RI, RI } },
108
- { INDEX_op_orc_i32, { R, RI, RI } },
109
- { INDEX_op_xor_i32, { R, RI, RI } },
110
- { INDEX_op_shl_i32, { R, RI, RI } },
111
- { INDEX_op_shr_i32, { R, RI, RI } },
112
- { INDEX_op_sar_i32, { R, RI, RI } },
113
- { INDEX_op_rotl_i32, { R, RI, RI } },
114
- { INDEX_op_rotr_i32, { R, RI, RI } },
115
- { INDEX_op_deposit_i32, { R, "0", R } },
116
-
117
- { INDEX_op_brcond_i32, { R, RI } },
118
-
119
- { INDEX_op_setcond_i32, { R, R, RI } },
120
- { INDEX_op_setcond_i64, { R, R, RI } },
121
-
122
- /* TODO: Support R, R, R, R, RI, RI? Will it be faster? */
123
- { INDEX_op_add2_i32, { R, R, R, R, R, R } },
124
- { INDEX_op_sub2_i32, { R, R, R, R, R, R } },
125
- { INDEX_op_brcond2_i32, { R, R, RI, RI } },
126
- { INDEX_op_mulu2_i32, { R, R, R, R } },
127
- { INDEX_op_setcond2_i32, { R, R, R, RI, RI } },
128
-
129
- { INDEX_op_not_i32, { R, R } },
130
- { INDEX_op_neg_i32, { R, R } },
131
-
132
- { INDEX_op_ld8u_i64, { R, R } },
133
- { INDEX_op_ld8s_i64, { R, R } },
134
- { INDEX_op_ld16u_i64, { R, R } },
135
- { INDEX_op_ld16s_i64, { R, R } },
136
- { INDEX_op_ld32u_i64, { R, R } },
137
- { INDEX_op_ld32s_i64, { R, R } },
138
- { INDEX_op_ld_i64, { R, R } },
139
-
140
- { INDEX_op_st8_i64, { R, R } },
141
- { INDEX_op_st16_i64, { R, R } },
142
- { INDEX_op_st32_i64, { R, R } },
143
- { INDEX_op_st_i64, { R, R } },
144
-
145
- { INDEX_op_add_i64, { R, RI, RI } },
146
- { INDEX_op_sub_i64, { R, RI, RI } },
147
- { INDEX_op_mul_i64, { R, RI, RI } },
148
- { INDEX_op_div_i64, { R, R, R } },
149
- { INDEX_op_divu_i64, { R, R, R } },
150
- { INDEX_op_rem_i64, { R, R, R } },
151
- { INDEX_op_remu_i64, { R, R, R } },
152
- { INDEX_op_and_i64, { R, RI, RI } },
153
- { INDEX_op_andc_i64, { R, RI, RI } },
154
- { INDEX_op_eqv_i64, { R, RI, RI } },
155
- { INDEX_op_nand_i64, { R, RI, RI } },
156
- { INDEX_op_nor_i64, { R, RI, RI } },
157
- { INDEX_op_or_i64, { R, RI, RI } },
158
- { INDEX_op_orc_i64, { R, RI, RI } },
159
- { INDEX_op_xor_i64, { R, RI, RI } },
160
- { INDEX_op_shl_i64, { R, RI, RI } },
161
- { INDEX_op_shr_i64, { R, RI, RI } },
162
- { INDEX_op_sar_i64, { R, RI, RI } },
163
- { INDEX_op_rotl_i64, { R, RI, RI } },
164
- { INDEX_op_rotr_i64, { R, RI, RI } },
165
- { INDEX_op_deposit_i64, { R, "0", R } },
166
- { INDEX_op_brcond_i64, { R, RI } },
167
-
168
- { INDEX_op_ext8s_i64, { R, R } },
169
- { INDEX_op_ext16s_i64, { R, R } },
170
- { INDEX_op_ext32s_i64, { R, R } },
171
- { INDEX_op_ext8u_i64, { R, R } },
172
- { INDEX_op_ext16u_i64, { R, R } },
173
- { INDEX_op_ext32u_i64, { R, R } },
174
- { INDEX_op_ext_i32_i64, { R, R } },
175
- { INDEX_op_extu_i32_i64, { R, R } },
176
- { INDEX_op_bswap16_i64, { R, R } },
177
- { INDEX_op_bswap32_i64, { R, R } },
178
- { INDEX_op_bswap64_i64, { R, R } },
179
- { INDEX_op_not_i64, { R, R } },
180
- { INDEX_op_neg_i64, { R, R } },
181
-
182
- { INDEX_op_qemu_ld_i32, { R, L } },
183
- { INDEX_op_qemu_ld_i64, { R64, L } },
184
-
185
- { INDEX_op_qemu_st_i32, { R, S } },
186
- { INDEX_op_qemu_st_i64, { R64, S } },
187
-
188
- { INDEX_op_ext8s_i32, { R, R } },
189
- { INDEX_op_ext16s_i32, { R, R } },
190
- { INDEX_op_ext8u_i32, { R, R } },
191
- { INDEX_op_ext16u_i32, { R, R } },
192
-
193
- { INDEX_op_bswap16_i32, { R, R } },
194
- { INDEX_op_bswap32_i32, { R, R } },
195
-
196
- { INDEX_op_mb, { } },
197
- { -1 },
198
-};
199
-
200
-static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
201
+static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
202
{
203
- int i, n = ARRAY_SIZE(tcg_target_op_defs);
204
+ switch (op) {
205
+ case INDEX_op_ld8u_i32:
206
+ case INDEX_op_ld8s_i32:
207
+ case INDEX_op_ld16u_i32:
208
+ case INDEX_op_ld16s_i32:
209
+ case INDEX_op_ld_i32:
210
+ case INDEX_op_ld8u_i64:
211
+ case INDEX_op_ld8s_i64:
212
+ case INDEX_op_ld16u_i64:
213
+ case INDEX_op_ld16s_i64:
214
+ case INDEX_op_ld32u_i64:
215
+ case INDEX_op_ld32s_i64:
216
+ case INDEX_op_ld_i64:
217
+ case INDEX_op_not_i32:
218
+ case INDEX_op_not_i64:
219
+ case INDEX_op_neg_i32:
220
+ case INDEX_op_neg_i64:
221
+ case INDEX_op_ext8s_i32:
222
+ case INDEX_op_ext8s_i64:
223
+ case INDEX_op_ext16s_i32:
224
+ case INDEX_op_ext16s_i64:
225
+ case INDEX_op_ext8u_i32:
226
+ case INDEX_op_ext8u_i64:
227
+ case INDEX_op_ext16u_i32:
228
+ case INDEX_op_ext16u_i64:
229
+ case INDEX_op_ext32s_i64:
230
+ case INDEX_op_ext32u_i64:
231
+ case INDEX_op_ext_i32_i64:
232
+ case INDEX_op_extu_i32_i64:
233
+ case INDEX_op_bswap16_i32:
234
+ case INDEX_op_bswap16_i64:
235
+ case INDEX_op_bswap32_i32:
236
+ case INDEX_op_bswap32_i64:
237
+ case INDEX_op_bswap64_i64:
238
+ return C_O1_I1(r, r);
239
240
- for (i = 0; i < n; ++i) {
241
- if (tcg_target_op_defs[i].op == op) {
242
- return &tcg_target_op_defs[i];
243
- }
244
+ case INDEX_op_st8_i32:
245
+ case INDEX_op_st16_i32:
246
+ case INDEX_op_st_i32:
247
+ case INDEX_op_st8_i64:
248
+ case INDEX_op_st16_i64:
249
+ case INDEX_op_st32_i64:
250
+ case INDEX_op_st_i64:
251
+ return C_O0_I2(r, r);
252
+
253
+ case INDEX_op_div_i32:
254
+ case INDEX_op_div_i64:
255
+ case INDEX_op_divu_i32:
256
+ case INDEX_op_divu_i64:
257
+ case INDEX_op_rem_i32:
258
+ case INDEX_op_rem_i64:
259
+ case INDEX_op_remu_i32:
260
+ case INDEX_op_remu_i64:
261
+ return C_O1_I2(r, r, r);
262
+
263
+ case INDEX_op_add_i32:
264
+ case INDEX_op_add_i64:
265
+ case INDEX_op_sub_i32:
266
+ case INDEX_op_sub_i64:
267
+ case INDEX_op_mul_i32:
268
+ case INDEX_op_mul_i64:
269
+ case INDEX_op_and_i32:
270
+ case INDEX_op_and_i64:
271
+ case INDEX_op_andc_i32:
272
+ case INDEX_op_andc_i64:
273
+ case INDEX_op_eqv_i32:
274
+ case INDEX_op_eqv_i64:
275
+ case INDEX_op_nand_i32:
276
+ case INDEX_op_nand_i64:
277
+ case INDEX_op_nor_i32:
278
+ case INDEX_op_nor_i64:
279
+ case INDEX_op_or_i32:
280
+ case INDEX_op_or_i64:
281
+ case INDEX_op_orc_i32:
282
+ case INDEX_op_orc_i64:
283
+ case INDEX_op_xor_i32:
284
+ case INDEX_op_xor_i64:
285
+ case INDEX_op_shl_i32:
286
+ case INDEX_op_shl_i64:
287
+ case INDEX_op_shr_i32:
288
+ case INDEX_op_shr_i64:
289
+ case INDEX_op_sar_i32:
290
+ case INDEX_op_sar_i64:
291
+ case INDEX_op_rotl_i32:
292
+ case INDEX_op_rotl_i64:
293
+ case INDEX_op_rotr_i32:
294
+ case INDEX_op_rotr_i64:
295
+ /* TODO: Does R, RI, RI result in faster code than R, R, RI? */
296
+ return C_O1_I2(r, ri, ri);
297
+
298
+ case INDEX_op_deposit_i32:
299
+ case INDEX_op_deposit_i64:
300
+ return C_O1_I2(r, 0, r);
301
+
302
+ case INDEX_op_brcond_i32:
303
+ case INDEX_op_brcond_i64:
304
+ return C_O0_I2(r, ri);
305
+
306
+ case INDEX_op_setcond_i32:
307
+ case INDEX_op_setcond_i64:
308
+ return C_O1_I2(r, r, ri);
309
+
310
+#if TCG_TARGET_REG_BITS == 32
311
+ /* TODO: Support R, R, R, R, RI, RI? Will it be faster? */
312
+ case INDEX_op_add2_i32:
313
+ case INDEX_op_sub2_i32:
314
+ return C_O2_I4(r, r, r, r, r, r);
315
+ case INDEX_op_brcond2_i32:
316
+ return C_O0_I4(r, r, ri, ri);
317
+ case INDEX_op_mulu2_i32:
318
+ return C_O2_I2(r, r, r, r);
319
+ case INDEX_op_setcond2_i32:
320
+ return C_O1_I4(r, r, r, ri, ri);
321
+#endif
322
+
323
+ case INDEX_op_qemu_ld_i32:
324
+ return (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
325
+ ? C_O1_I1(r, r)
326
+ : C_O1_I2(r, r, r));
327
+ case INDEX_op_qemu_ld_i64:
328
+ return (TCG_TARGET_REG_BITS == 64 ? C_O1_I1(r, r)
329
+ : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? C_O2_I1(r, r, r)
330
+ : C_O2_I2(r, r, r, r));
331
+ case INDEX_op_qemu_st_i32:
332
+ return (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
333
+ ? C_O0_I2(r, r)
334
+ : C_O0_I3(r, r, r));
335
+ case INDEX_op_qemu_st_i64:
336
+ return (TCG_TARGET_REG_BITS == 64 ? C_O0_I2(r, r)
337
+ : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? C_O0_I3(r, r, r)
338
+ : C_O0_I4(r, r, r, r));
339
+
340
+ default:
341
+ g_assert_not_reached();
342
}
343
- return NULL;
344
}
345
346
static const int tcg_target_reg_alloc_order[] = {
347
--
58
--
348
2.25.1
59
2.17.2
349
60
350
61
diff view generated by jsdifflib
1
All backends have now been converted to tcg-target-con-str.h,
1
From: "Emilio G. Cota" <cota@braap.org>
2
so we can remove the fallback code.
3
2
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
We forgot to initialize n in commit 15fa08f845 ("tcg: Dynamically
5
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
4
allocate TCGOps", 2017-12-29).
5
6
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Signed-off-by: Emilio G. Cota <cota@braap.org>
8
Message-Id: <20181010144853.13005-3-cota@braap.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
10
---
8
tcg/aarch64/tcg-target.h | 1 -
11
tcg/tcg.c | 2 +-
9
tcg/arm/tcg-target.h | 1 -
12
1 file changed, 1 insertion(+), 1 deletion(-)
10
tcg/i386/tcg-target.h | 1 -
11
tcg/mips/tcg-target.h | 1 -
12
tcg/ppc/tcg-target.h | 1 -
13
tcg/riscv/tcg-target.h | 1 -
14
tcg/s390/tcg-target.h | 1 -
15
tcg/sparc/tcg-target.h | 1 -
16
tcg/tci/tcg-target.h | 2 --
17
tcg/tcg.c | 16 ----------------
18
10 files changed, 26 deletions(-)
19
13
20
diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/tcg/aarch64/tcg-target.h
23
+++ b/tcg/aarch64/tcg-target.h
24
@@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
25
#define TCG_TARGET_NEED_LDST_LABELS
26
#endif
27
#define TCG_TARGET_NEED_POOL_LABELS
28
-#define TCG_TARGET_CON_STR_H
29
30
#endif /* AARCH64_TCG_TARGET_H */
31
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/tcg/arm/tcg-target.h
34
+++ b/tcg/arm/tcg-target.h
35
@@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
36
#define TCG_TARGET_NEED_LDST_LABELS
37
#endif
38
#define TCG_TARGET_NEED_POOL_LABELS
39
-#define TCG_TARGET_CON_STR_H
40
41
#endif
42
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
43
index XXXXXXX..XXXXXXX 100644
44
--- a/tcg/i386/tcg-target.h
45
+++ b/tcg/i386/tcg-target.h
46
@@ -XXX,XX +XXX,XX @@ static inline void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
47
#define TCG_TARGET_NEED_LDST_LABELS
48
#endif
49
#define TCG_TARGET_NEED_POOL_LABELS
50
-#define TCG_TARGET_CON_STR_H
51
52
#endif
53
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
54
index XXXXXXX..XXXXXXX 100644
55
--- a/tcg/mips/tcg-target.h
56
+++ b/tcg/mips/tcg-target.h
57
@@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
58
#ifdef CONFIG_SOFTMMU
59
#define TCG_TARGET_NEED_LDST_LABELS
60
#endif
61
-#define TCG_TARGET_CON_STR_H
62
63
#endif
64
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
65
index XXXXXXX..XXXXXXX 100644
66
--- a/tcg/ppc/tcg-target.h
67
+++ b/tcg/ppc/tcg-target.h
68
@@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
69
#define TCG_TARGET_NEED_LDST_LABELS
70
#endif
71
#define TCG_TARGET_NEED_POOL_LABELS
72
-#define TCG_TARGET_CON_STR_H
73
74
#endif
75
diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
76
index XXXXXXX..XXXXXXX 100644
77
--- a/tcg/riscv/tcg-target.h
78
+++ b/tcg/riscv/tcg-target.h
79
@@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
80
#define TCG_TARGET_NEED_POOL_LABELS
81
82
#define TCG_TARGET_HAS_MEMORY_BSWAP 0
83
-#define TCG_TARGET_CON_STR_H
84
85
#endif
86
diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h
87
index XXXXXXX..XXXXXXX 100644
88
--- a/tcg/s390/tcg-target.h
89
+++ b/tcg/s390/tcg-target.h
90
@@ -XXX,XX +XXX,XX @@ static inline void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
91
#define TCG_TARGET_NEED_LDST_LABELS
92
#endif
93
#define TCG_TARGET_NEED_POOL_LABELS
94
-#define TCG_TARGET_CON_STR_H
95
96
#endif
97
diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
98
index XXXXXXX..XXXXXXX 100644
99
--- a/tcg/sparc/tcg-target.h
100
+++ b/tcg/sparc/tcg-target.h
101
@@ -XXX,XX +XXX,XX @@ extern bool use_vis3_instructions;
102
void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
103
104
#define TCG_TARGET_NEED_POOL_LABELS
105
-#define TCG_TARGET_CON_STR_H
106
107
#endif
108
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
109
index XXXXXXX..XXXXXXX 100644
110
--- a/tcg/tci/tcg-target.h
111
+++ b/tcg/tci/tcg-target.h
112
@@ -XXX,XX +XXX,XX @@ static inline void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
113
/* no need to flush icache explicitly */
114
}
115
116
-#define TCG_TARGET_CON_STR_H
117
-
118
#endif /* TCG_TARGET_H */
119
diff --git a/tcg/tcg.c b/tcg/tcg.c
14
diff --git a/tcg/tcg.c b/tcg/tcg.c
120
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
121
--- a/tcg/tcg.c
16
--- a/tcg/tcg.c
122
+++ b/tcg/tcg.c
17
+++ b/tcg/tcg.c
123
@@ -XXX,XX +XXX,XX @@ static void tcg_register_jit_int(const void *buf, size_t size,
18
@@ -XXX,XX +XXX,XX @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
124
__attribute__((unused));
19
125
20
#ifdef CONFIG_PROFILER
126
/* Forward declarations for functions declared and used in tcg-target.c.inc. */
21
{
127
-#ifndef TCG_TARGET_CON_STR_H
22
- int n;
128
-static const char *target_parse_constraint(TCGArgConstraint *ct,
23
+ int n = 0;
129
- const char *ct_str, TCGType type);
24
130
-#endif
25
QTAILQ_FOREACH(op, &s->ops, link) {
131
static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
26
n++;
132
intptr_t arg2);
133
static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg);
134
@@ -XXX,XX +XXX,XX @@ static void process_op_defs(TCGContext *s)
135
ct_str++;
136
break;
137
138
-#ifdef TCG_TARGET_CON_STR_H
139
/* Include all of the target-specific constraints. */
140
141
#undef CONST
142
@@ -XXX,XX +XXX,XX @@ static void process_op_defs(TCGContext *s)
143
default:
144
/* Typo in TCGTargetOpDef constraint. */
145
g_assert_not_reached();
146
-#else
147
- default:
148
- {
149
- TCGType type = (def->flags & TCG_OPF_64BIT
150
- ? TCG_TYPE_I64 : TCG_TYPE_I32);
151
- ct_str = target_parse_constraint(&def->args_ct[i],
152
- ct_str, type);
153
- /* Typo in TCGTargetOpDef constraint. */
154
- tcg_debug_assert(ct_str != NULL);
155
- }
156
-#endif
157
}
158
}
159
}
160
--
27
--
161
2.25.1
28
2.17.2
162
29
163
30
diff view generated by jsdifflib
1
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
1
From: "Emilio G. Cota" <cota@braap.org>
2
3
This plugs two 4-byte holes in 64-bit.
4
5
Signed-off-by: Emilio G. Cota <cota@braap.org>
6
Message-Id: <20181010144853.13005-4-cota@braap.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
8
---
4
tcg/sparc/tcg-target-con-set.h | 32 +++++++++++++++
9
tcg/tcg.h | 2 +-
5
tcg/sparc/tcg-target.h | 1 +
10
1 file changed, 1 insertion(+), 1 deletion(-)
6
tcg/sparc/tcg-target.c.inc | 75 +++++++++++-----------------------
7
3 files changed, 56 insertions(+), 52 deletions(-)
8
create mode 100644 tcg/sparc/tcg-target-con-set.h
9
11
10
diff --git a/tcg/sparc/tcg-target-con-set.h b/tcg/sparc/tcg-target-con-set.h
12
diff --git a/tcg/tcg.h b/tcg/tcg.h
11
new file mode 100644
12
index XXXXXXX..XXXXXXX
13
--- /dev/null
14
+++ b/tcg/sparc/tcg-target-con-set.h
15
@@ -XXX,XX +XXX,XX @@
16
+/* SPDX-License-Identifier: MIT */
17
+/*
18
+ * Define Sparc target-specific constraint sets.
19
+ * Copyright (c) 2021 Linaro
20
+ */
21
+
22
+/*
23
+ * C_On_Im(...) defines a constraint set with <n> outputs and <m> inputs.
24
+ * Each operand should be a sequence of constraint letters as defined by
25
+ * tcg-target-con-str.h; the constraint combination is inclusive or.
26
+ */
27
+C_O0_I1(r)
28
+C_O0_I2(rZ, r)
29
+C_O0_I2(RZ, r)
30
+C_O0_I2(rZ, rJ)
31
+C_O0_I2(RZ, RJ)
32
+C_O0_I2(sZ, A)
33
+C_O0_I2(SZ, A)
34
+C_O1_I1(r, A)
35
+C_O1_I1(R, A)
36
+C_O1_I1(r, r)
37
+C_O1_I1(r, R)
38
+C_O1_I1(R, r)
39
+C_O1_I1(R, R)
40
+C_O1_I2(R, R, R)
41
+C_O1_I2(r, rZ, rJ)
42
+C_O1_I2(R, RZ, RJ)
43
+C_O1_I4(r, rZ, rJ, rI, 0)
44
+C_O1_I4(R, RZ, RJ, RI, 0)
45
+C_O2_I2(r, r, rZ, rJ)
46
+C_O2_I4(R, R, RZ, RZ, RJ, RI)
47
+C_O2_I4(r, r, rZ, rZ, rJ, rJ)
48
diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
49
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
50
--- a/tcg/sparc/tcg-target.h
14
--- a/tcg/tcg.h
51
+++ b/tcg/sparc/tcg-target.h
15
+++ b/tcg/tcg.h
52
@@ -XXX,XX +XXX,XX @@ extern bool use_vis3_instructions;
16
@@ -XXX,XX +XXX,XX @@ typedef struct TCGProfile {
53
void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
17
int64_t tb_count;
54
18
int64_t op_count; /* total insn count */
55
#define TCG_TARGET_NEED_POOL_LABELS
19
int op_count_max; /* max insn per TB */
56
+#define TCG_TARGET_CON_SET_H
20
- int64_t temp_count;
57
21
int temp_count_max;
58
#endif
22
+ int64_t temp_count;
59
diff --git a/tcg/sparc/tcg-target.c.inc b/tcg/sparc/tcg-target.c.inc
23
int64_t del_op_count;
60
index XXXXXXX..XXXXXXX 100644
24
int64_t code_in_len;
61
--- a/tcg/sparc/tcg-target.c.inc
25
int64_t code_out_len;
62
+++ b/tcg/sparc/tcg-target.c.inc
63
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
64
}
65
}
66
67
-static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
68
+static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
69
{
70
- static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
71
- static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
72
- static const TCGTargetOpDef R_r = { .args_ct_str = { "R", "r" } };
73
- static const TCGTargetOpDef r_R = { .args_ct_str = { "r", "R" } };
74
- static const TCGTargetOpDef R_R = { .args_ct_str = { "R", "R" } };
75
- static const TCGTargetOpDef r_A = { .args_ct_str = { "r", "A" } };
76
- static const TCGTargetOpDef R_A = { .args_ct_str = { "R", "A" } };
77
- static const TCGTargetOpDef rZ_r = { .args_ct_str = { "rZ", "r" } };
78
- static const TCGTargetOpDef RZ_r = { .args_ct_str = { "RZ", "r" } };
79
- static const TCGTargetOpDef sZ_A = { .args_ct_str = { "sZ", "A" } };
80
- static const TCGTargetOpDef SZ_A = { .args_ct_str = { "SZ", "A" } };
81
- static const TCGTargetOpDef rZ_rJ = { .args_ct_str = { "rZ", "rJ" } };
82
- static const TCGTargetOpDef RZ_RJ = { .args_ct_str = { "RZ", "RJ" } };
83
- static const TCGTargetOpDef R_R_R = { .args_ct_str = { "R", "R", "R" } };
84
- static const TCGTargetOpDef r_rZ_rJ
85
- = { .args_ct_str = { "r", "rZ", "rJ" } };
86
- static const TCGTargetOpDef R_RZ_RJ
87
- = { .args_ct_str = { "R", "RZ", "RJ" } };
88
- static const TCGTargetOpDef r_r_rZ_rJ
89
- = { .args_ct_str = { "r", "r", "rZ", "rJ" } };
90
- static const TCGTargetOpDef movc_32
91
- = { .args_ct_str = { "r", "rZ", "rJ", "rI", "0" } };
92
- static const TCGTargetOpDef movc_64
93
- = { .args_ct_str = { "R", "RZ", "RJ", "RI", "0" } };
94
- static const TCGTargetOpDef add2_32
95
- = { .args_ct_str = { "r", "r", "rZ", "rZ", "rJ", "rJ" } };
96
- static const TCGTargetOpDef add2_64
97
- = { .args_ct_str = { "R", "R", "RZ", "RZ", "RJ", "RI" } };
98
-
99
switch (op) {
100
case INDEX_op_goto_ptr:
101
- return &r;
102
+ return C_O0_I1(r);
103
104
case INDEX_op_ld8u_i32:
105
case INDEX_op_ld8s_i32:
106
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
107
case INDEX_op_ld_i32:
108
case INDEX_op_neg_i32:
109
case INDEX_op_not_i32:
110
- return &r_r;
111
+ return C_O1_I1(r, r);
112
113
case INDEX_op_st8_i32:
114
case INDEX_op_st16_i32:
115
case INDEX_op_st_i32:
116
- return &rZ_r;
117
+ return C_O0_I2(rZ, r);
118
119
case INDEX_op_add_i32:
120
case INDEX_op_mul_i32:
121
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
122
case INDEX_op_shr_i32:
123
case INDEX_op_sar_i32:
124
case INDEX_op_setcond_i32:
125
- return &r_rZ_rJ;
126
+ return C_O1_I2(r, rZ, rJ);
127
128
case INDEX_op_brcond_i32:
129
- return &rZ_rJ;
130
+ return C_O0_I2(rZ, rJ);
131
case INDEX_op_movcond_i32:
132
- return &movc_32;
133
+ return C_O1_I4(r, rZ, rJ, rI, 0);
134
case INDEX_op_add2_i32:
135
case INDEX_op_sub2_i32:
136
- return &add2_32;
137
+ return C_O2_I4(r, r, rZ, rZ, rJ, rJ);
138
case INDEX_op_mulu2_i32:
139
case INDEX_op_muls2_i32:
140
- return &r_r_rZ_rJ;
141
+ return C_O2_I2(r, r, rZ, rJ);
142
143
case INDEX_op_ld8u_i64:
144
case INDEX_op_ld8s_i64:
145
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
146
case INDEX_op_ld_i64:
147
case INDEX_op_ext_i32_i64:
148
case INDEX_op_extu_i32_i64:
149
- return &R_r;
150
+ return C_O1_I1(R, r);
151
152
case INDEX_op_st8_i64:
153
case INDEX_op_st16_i64:
154
case INDEX_op_st32_i64:
155
case INDEX_op_st_i64:
156
- return &RZ_r;
157
+ return C_O0_I2(RZ, r);
158
159
case INDEX_op_add_i64:
160
case INDEX_op_mul_i64:
161
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
162
case INDEX_op_shr_i64:
163
case INDEX_op_sar_i64:
164
case INDEX_op_setcond_i64:
165
- return &R_RZ_RJ;
166
+ return C_O1_I2(R, RZ, RJ);
167
168
case INDEX_op_neg_i64:
169
case INDEX_op_not_i64:
170
case INDEX_op_ext32s_i64:
171
case INDEX_op_ext32u_i64:
172
- return &R_R;
173
+ return C_O1_I1(R, R);
174
175
case INDEX_op_extrl_i64_i32:
176
case INDEX_op_extrh_i64_i32:
177
- return &r_R;
178
+ return C_O1_I1(r, R);
179
180
case INDEX_op_brcond_i64:
181
- return &RZ_RJ;
182
+ return C_O0_I2(RZ, RJ);
183
case INDEX_op_movcond_i64:
184
- return &movc_64;
185
+ return C_O1_I4(R, RZ, RJ, RI, 0);
186
case INDEX_op_add2_i64:
187
case INDEX_op_sub2_i64:
188
- return &add2_64;
189
+ return C_O2_I4(R, R, RZ, RZ, RJ, RI);
190
case INDEX_op_muluh_i64:
191
- return &R_R_R;
192
+ return C_O1_I2(R, R, R);
193
194
case INDEX_op_qemu_ld_i32:
195
- return &r_A;
196
+ return C_O1_I1(r, A);
197
case INDEX_op_qemu_ld_i64:
198
- return &R_A;
199
+ return C_O1_I1(R, A);
200
case INDEX_op_qemu_st_i32:
201
- return &sZ_A;
202
+ return C_O0_I2(sZ, A);
203
case INDEX_op_qemu_st_i64:
204
- return &SZ_A;
205
+ return C_O0_I2(SZ, A);
206
207
default:
208
- return NULL;
209
+ g_assert_not_reached();
210
}
211
}
212
213
--
26
--
214
2.25.1
27
2.17.2
215
28
216
29
diff view generated by jsdifflib
1
This exports the constraint sets from tcg_target_op_def to
1
From: "Emilio G. Cota" <cota@braap.org>
2
a place we will be able to manipulate more in future.
3
2
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
When we implemented per-vCPU TCG contexts, we forgot to also
4
distribute the tcg_time counter, which has remained as a global
5
accessed without any serialization, leading to potentially missed
6
counts.
7
8
Fix it by distributing the field over the TCG contexts, embedding
9
it into TCGProfile with a field called "cpu_exec_time", which is more
10
descriptive than "tcg_time". Add a function to query this value
11
directly, and for completeness, fill in the field in
12
tcg_profile_snapshot, even though its callers do not use it.
13
14
Signed-off-by: Emilio G. Cota <cota@braap.org>
15
Message-Id: <20181010144853.13005-5-cota@braap.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
16
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
17
---
7
tcg/i386/tcg-target-con-set.h | 55 ++++++++++
18
include/qemu/timer.h | 1 -
8
tcg/i386/tcg-target.h | 1 +
19
tcg/tcg.h | 2 ++
9
tcg/tcg.c | 119 +++++++++++++++++++++
20
cpus.c | 3 ++-
10
tcg/i386/tcg-target.c.inc | 194 ++++++++++++----------------------
21
monitor.c | 13 ++++++++++---
11
4 files changed, 242 insertions(+), 127 deletions(-)
22
tcg/tcg.c | 23 +++++++++++++++++++++++
12
create mode 100644 tcg/i386/tcg-target-con-set.h
23
5 files changed, 37 insertions(+), 5 deletions(-)
13
24
14
diff --git a/tcg/i386/tcg-target-con-set.h b/tcg/i386/tcg-target-con-set.h
25
diff --git a/include/qemu/timer.h b/include/qemu/timer.h
15
new file mode 100644
26
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX
27
--- a/include/qemu/timer.h
17
--- /dev/null
28
+++ b/include/qemu/timer.h
18
+++ b/tcg/i386/tcg-target-con-set.h
29
@@ -XXX,XX +XXX,XX @@ static inline int64_t profile_getclock(void)
30
return get_clock();
31
}
32
33
-extern int64_t tcg_time;
34
extern int64_t dev_time;
35
#endif
36
37
diff --git a/tcg/tcg.h b/tcg/tcg.h
38
index XXXXXXX..XXXXXXX 100644
39
--- a/tcg/tcg.h
40
+++ b/tcg/tcg.h
41
@@ -XXX,XX +XXX,XX @@ typedef struct TCGOp {
42
QEMU_BUILD_BUG_ON(NB_OPS > (1 << 8));
43
44
typedef struct TCGProfile {
45
+ int64_t cpu_exec_time;
46
int64_t tb_count1;
47
int64_t tb_count;
48
int64_t op_count; /* total insn count */
49
@@ -XXX,XX +XXX,XX @@ int tcg_check_temp_count(void);
50
#define tcg_check_temp_count() 0
51
#endif
52
53
+int64_t tcg_cpu_exec_time(void);
54
void tcg_dump_info(FILE *f, fprintf_function cpu_fprintf);
55
void tcg_dump_op_count(FILE *f, fprintf_function cpu_fprintf);
56
57
diff --git a/cpus.c b/cpus.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/cpus.c
60
+++ b/cpus.c
61
@@ -XXX,XX +XXX,XX @@ static int tcg_cpu_exec(CPUState *cpu)
62
ret = cpu_exec(cpu);
63
cpu_exec_end(cpu);
64
#ifdef CONFIG_PROFILER
65
- tcg_time += profile_getclock() - ti;
66
+ atomic_set(&tcg_ctx->prof.cpu_exec_time,
67
+ tcg_ctx->prof.cpu_exec_time + profile_getclock() - ti);
68
#endif
69
return ret;
70
}
71
diff --git a/monitor.c b/monitor.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/monitor.c
74
+++ b/monitor.c
19
@@ -XXX,XX +XXX,XX @@
75
@@ -XXX,XX +XXX,XX @@
20
+/* SPDX-License-Identifier: MIT */
76
#include "sysemu/cpus.h"
21
+/*
77
#include "sysemu/iothread.h"
22
+ * Define i386 target-specific constraint sets.
78
#include "qemu/cutils.h"
23
+ * Copyright (c) 2021 Linaro
79
+#include "tcg/tcg.h"
24
+ */
80
81
#if defined(TARGET_S390X)
82
#include "hw/s390x/storage-keys.h"
83
@@ -XXX,XX +XXX,XX @@ static void hmp_info_numa(Monitor *mon, const QDict *qdict)
84
85
#ifdef CONFIG_PROFILER
86
87
-int64_t tcg_time;
88
int64_t dev_time;
89
90
static void hmp_info_profile(Monitor *mon, const QDict *qdict)
91
{
92
+ static int64_t last_cpu_exec_time;
93
+ int64_t cpu_exec_time;
94
+ int64_t delta;
25
+
95
+
26
+/*
96
+ cpu_exec_time = tcg_cpu_exec_time();
27
+ * C_On_Im(...) defines a constraint set with <n> outputs and <m> inputs.
97
+ delta = cpu_exec_time - last_cpu_exec_time;
28
+ * Each operand should be a sequence of constraint letters as defined by
98
+
29
+ * tcg-target-con-str.h; the constraint combination is inclusive or.
99
monitor_printf(mon, "async time %" PRId64 " (%0.3f)\n",
30
+ *
100
dev_time, dev_time / (double)NANOSECONDS_PER_SECOND);
31
+ * C_N1_Im(...) defines a constraint set with 1 output and <m> inputs,
101
monitor_printf(mon, "qemu time %" PRId64 " (%0.3f)\n",
32
+ * except that the output must use a new register.
102
- tcg_time, tcg_time / (double)NANOSECONDS_PER_SECOND);
33
+ */
103
- tcg_time = 0;
34
+C_O0_I1(r)
104
+ delta, delta / (double)NANOSECONDS_PER_SECOND);
35
+C_O0_I2(L, L)
105
+ last_cpu_exec_time = cpu_exec_time;
36
+C_O0_I2(qi, r)
106
dev_time = 0;
37
+C_O0_I2(re, r)
107
}
38
+C_O0_I2(ri, r)
108
#else
39
+C_O0_I2(r, re)
40
+C_O0_I2(s, L)
41
+C_O0_I2(x, r)
42
+C_O0_I3(L, L, L)
43
+C_O0_I3(s, L, L)
44
+C_O0_I4(L, L, L, L)
45
+C_O0_I4(r, r, ri, ri)
46
+C_O1_I1(r, 0)
47
+C_O1_I1(r, L)
48
+C_O1_I1(r, q)
49
+C_O1_I1(r, r)
50
+C_O1_I1(x, r)
51
+C_O1_I1(x, x)
52
+C_O1_I2(Q, 0, Q)
53
+C_O1_I2(q, r, re)
54
+C_O1_I2(r, 0, ci)
55
+C_O1_I2(r, 0, r)
56
+C_O1_I2(r, 0, re)
57
+C_O1_I2(r, 0, reZ)
58
+C_O1_I2(r, 0, ri)
59
+C_O1_I2(r, 0, rI)
60
+C_O1_I2(r, L, L)
61
+C_O1_I2(r, r, re)
62
+C_O1_I2(r, r, ri)
63
+C_O1_I2(r, r, rI)
64
+C_O1_I2(x, x, x)
65
+C_N1_I2(r, r, r)
66
+C_N1_I2(r, r, rW)
67
+C_O1_I3(x, x, x, x)
68
+C_O1_I4(r, r, re, r, 0)
69
+C_O1_I4(r, r, r, ri, ri)
70
+C_O2_I1(r, r, L)
71
+C_O2_I2(a, d, a, r)
72
+C_O2_I2(r, r, L, L)
73
+C_O2_I3(a, d, 0, 1, r)
74
+C_O2_I4(r, r, 0, 1, re, re)
75
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
76
index XXXXXXX..XXXXXXX 100644
77
--- a/tcg/i386/tcg-target.h
78
+++ b/tcg/i386/tcg-target.h
79
@@ -XXX,XX +XXX,XX @@ static inline void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
80
#define TCG_TARGET_NEED_LDST_LABELS
81
#endif
82
#define TCG_TARGET_NEED_POOL_LABELS
83
+#define TCG_TARGET_CON_SET_H
84
85
#endif
86
diff --git a/tcg/tcg.c b/tcg/tcg.c
109
diff --git a/tcg/tcg.c b/tcg/tcg.c
87
index XXXXXXX..XXXXXXX 100644
110
index XXXXXXX..XXXXXXX 100644
88
--- a/tcg/tcg.c
111
--- a/tcg/tcg.c
89
+++ b/tcg/tcg.c
112
+++ b/tcg/tcg.c
90
@@ -XXX,XX +XXX,XX @@
113
@@ -XXX,XX +XXX,XX @@
91
/* Forward declarations for functions declared in tcg-target.c.inc and
114
/* Define to jump the ELF file used to communicate with GDB. */
92
used here. */
115
#undef DEBUG_JIT
93
static void tcg_target_init(TCGContext *s);
116
94
+#ifndef TCG_TARGET_CON_SET_H
117
+#include "qemu/error-report.h"
95
static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode);
118
#include "qemu/cutils.h"
96
+#endif
119
#include "qemu/host-utils.h"
97
static void tcg_target_qemu_prologue(TCGContext *s);
120
#include "qemu/timer.h"
98
static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
121
@@ -XXX,XX +XXX,XX @@ void tcg_profile_snapshot(TCGProfile *prof, bool counters, bool table)
99
intptr_t value, intptr_t addend);
122
const TCGProfile *orig = &s->prof;
100
@@ -XXX,XX +XXX,XX @@ static void set_jmp_reset_offset(TCGContext *s, int which)
123
101
s->tb_jmp_reset_offset[which] = tcg_current_code_size(s);
124
if (counters) {
102
}
125
+ PROF_ADD(prof, orig, cpu_exec_time);
103
126
PROF_ADD(prof, orig, tb_count1);
104
+#ifdef TCG_TARGET_CON_SET_H
127
PROF_ADD(prof, orig, tb_count);
105
+#define C_PFX1(P, A) P##A
128
PROF_ADD(prof, orig, op_count);
106
+#define C_PFX2(P, A, B) P##A##_##B
129
@@ -XXX,XX +XXX,XX @@ void tcg_dump_op_count(FILE *f, fprintf_function cpu_fprintf)
107
+#define C_PFX3(P, A, B, C) P##A##_##B##_##C
130
prof.table_op_count[i]);
108
+#define C_PFX4(P, A, B, C, D) P##A##_##B##_##C##_##D
109
+#define C_PFX5(P, A, B, C, D, E) P##A##_##B##_##C##_##D##_##E
110
+#define C_PFX6(P, A, B, C, D, E, F) P##A##_##B##_##C##_##D##_##E##_##F
111
+
112
+/* Define an enumeration for the various combinations. */
113
+
114
+#define C_O0_I1(I1) C_PFX1(c_o0_i1_, I1),
115
+#define C_O0_I2(I1, I2) C_PFX2(c_o0_i2_, I1, I2),
116
+#define C_O0_I3(I1, I2, I3) C_PFX3(c_o0_i3_, I1, I2, I3),
117
+#define C_O0_I4(I1, I2, I3, I4) C_PFX4(c_o0_i4_, I1, I2, I3, I4),
118
+
119
+#define C_O1_I1(O1, I1) C_PFX2(c_o1_i1_, O1, I1),
120
+#define C_O1_I2(O1, I1, I2) C_PFX3(c_o1_i2_, O1, I1, I2),
121
+#define C_O1_I3(O1, I1, I2, I3) C_PFX4(c_o1_i3_, O1, I1, I2, I3),
122
+#define C_O1_I4(O1, I1, I2, I3, I4) C_PFX5(c_o1_i4_, O1, I1, I2, I3, I4),
123
+
124
+#define C_N1_I2(O1, I1, I2) C_PFX3(c_n1_i2_, O1, I1, I2),
125
+
126
+#define C_O2_I1(O1, O2, I1) C_PFX3(c_o2_i1_, O1, O2, I1),
127
+#define C_O2_I2(O1, O2, I1, I2) C_PFX4(c_o2_i2_, O1, O2, I1, I2),
128
+#define C_O2_I3(O1, O2, I1, I2, I3) C_PFX5(c_o2_i3_, O1, O2, I1, I2, I3),
129
+#define C_O2_I4(O1, O2, I1, I2, I3, I4) C_PFX6(c_o2_i4_, O1, O2, I1, I2, I3, I4),
130
+
131
+typedef enum {
132
+#include "tcg-target-con-set.h"
133
+} TCGConstraintSetIndex;
134
+
135
+static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode);
136
+
137
+#undef C_O0_I1
138
+#undef C_O0_I2
139
+#undef C_O0_I3
140
+#undef C_O0_I4
141
+#undef C_O1_I1
142
+#undef C_O1_I2
143
+#undef C_O1_I3
144
+#undef C_O1_I4
145
+#undef C_N1_I2
146
+#undef C_O2_I1
147
+#undef C_O2_I2
148
+#undef C_O2_I3
149
+#undef C_O2_I4
150
+
151
+/* Put all of the constraint sets into an array, indexed by the enum. */
152
+
153
+#define C_O0_I1(I1) { .args_ct_str = { #I1 } },
154
+#define C_O0_I2(I1, I2) { .args_ct_str = { #I1, #I2 } },
155
+#define C_O0_I3(I1, I2, I3) { .args_ct_str = { #I1, #I2, #I3 } },
156
+#define C_O0_I4(I1, I2, I3, I4) { .args_ct_str = { #I1, #I2, #I3, #I4 } },
157
+
158
+#define C_O1_I1(O1, I1) { .args_ct_str = { #O1, #I1 } },
159
+#define C_O1_I2(O1, I1, I2) { .args_ct_str = { #O1, #I1, #I2 } },
160
+#define C_O1_I3(O1, I1, I2, I3) { .args_ct_str = { #O1, #I1, #I2, #I3 } },
161
+#define C_O1_I4(O1, I1, I2, I3, I4) { .args_ct_str = { #O1, #I1, #I2, #I3, #I4 } },
162
+
163
+#define C_N1_I2(O1, I1, I2) { .args_ct_str = { "&" #O1, #I1, #I2 } },
164
+
165
+#define C_O2_I1(O1, O2, I1) { .args_ct_str = { #O1, #O2, #I1 } },
166
+#define C_O2_I2(O1, O2, I1, I2) { .args_ct_str = { #O1, #O2, #I1, #I2 } },
167
+#define C_O2_I3(O1, O2, I1, I2, I3) { .args_ct_str = { #O1, #O2, #I1, #I2, #I3 } },
168
+#define C_O2_I4(O1, O2, I1, I2, I3, I4) { .args_ct_str = { #O1, #O2, #I1, #I2, #I3, #I4 } },
169
+
170
+static const TCGTargetOpDef constraint_sets[] = {
171
+#include "tcg-target-con-set.h"
172
+};
173
+
174
+
175
+#undef C_O0_I1
176
+#undef C_O0_I2
177
+#undef C_O0_I3
178
+#undef C_O0_I4
179
+#undef C_O1_I1
180
+#undef C_O1_I2
181
+#undef C_O1_I3
182
+#undef C_O1_I4
183
+#undef C_N1_I2
184
+#undef C_O2_I1
185
+#undef C_O2_I2
186
+#undef C_O2_I3
187
+#undef C_O2_I4
188
+
189
+/* Expand the enumerator to be returned from tcg_target_op_def(). */
190
+
191
+#define C_O0_I1(I1) C_PFX1(c_o0_i1_, I1)
192
+#define C_O0_I2(I1, I2) C_PFX2(c_o0_i2_, I1, I2)
193
+#define C_O0_I3(I1, I2, I3) C_PFX3(c_o0_i3_, I1, I2, I3)
194
+#define C_O0_I4(I1, I2, I3, I4) C_PFX4(c_o0_i4_, I1, I2, I3, I4)
195
+
196
+#define C_O1_I1(O1, I1) C_PFX2(c_o1_i1_, O1, I1)
197
+#define C_O1_I2(O1, I1, I2) C_PFX3(c_o1_i2_, O1, I1, I2)
198
+#define C_O1_I3(O1, I1, I2, I3) C_PFX4(c_o1_i3_, O1, I1, I2, I3)
199
+#define C_O1_I4(O1, I1, I2, I3, I4) C_PFX5(c_o1_i4_, O1, I1, I2, I3, I4)
200
+
201
+#define C_N1_I2(O1, I1, I2) C_PFX3(c_n1_i2_, O1, I1, I2)
202
+
203
+#define C_O2_I1(O1, O2, I1) C_PFX3(c_o2_i1_, O1, O2, I1)
204
+#define C_O2_I2(O1, O2, I1, I2) C_PFX4(c_o2_i2_, O1, O2, I1, I2)
205
+#define C_O2_I3(O1, O2, I1, I2, I3) C_PFX5(c_o2_i3_, O1, O2, I1, I2, I3)
206
+#define C_O2_I4(O1, O2, I1, I2, I3, I4) C_PFX6(c_o2_i4_, O1, O2, I1, I2, I3, I4)
207
+
208
+#endif /* TCG_TARGET_CON_SET_H */
209
+
210
#include "tcg-target.c.inc"
211
212
/* compare a pointer @ptr and a tb_tc @s */
213
@@ -XXX,XX +XXX,XX @@ static void process_op_defs(TCGContext *s)
214
continue;
215
}
216
217
+#ifdef TCG_TARGET_CON_SET_H
218
+ /*
219
+ * Macro magic should make it impossible, but double-check that
220
+ * the array index is in range. Since the signness of an enum
221
+ * is implementation defined, force the result to unsigned.
222
+ */
223
+ unsigned con_set = tcg_target_op_def(op);
224
+ tcg_debug_assert(con_set < ARRAY_SIZE(constraint_sets));
225
+ tdefs = &constraint_sets[con_set];
226
+#else
227
tdefs = tcg_target_op_def(op);
228
/* Missing TCGTargetOpDef entry. */
229
tcg_debug_assert(tdefs != NULL);
230
+#endif
231
232
for (i = 0; i < nb_args; i++) {
233
const char *ct_str = tdefs->args_ct_str[i];
234
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
235
index XXXXXXX..XXXXXXX 100644
236
--- a/tcg/i386/tcg-target.c.inc
237
+++ b/tcg/i386/tcg-target.c.inc
238
@@ -XXX,XX +XXX,XX @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
239
}
131
}
240
}
132
}
241
133
+
242
-static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
134
+int64_t tcg_cpu_exec_time(void)
243
+static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
135
+{
136
+ unsigned int n_ctxs = atomic_read(&n_tcg_ctxs);
137
+ unsigned int i;
138
+ int64_t ret = 0;
139
+
140
+ for (i = 0; i < n_ctxs; i++) {
141
+ const TCGContext *s = atomic_read(&tcg_ctxs[i]);
142
+ const TCGProfile *prof = &s->prof;
143
+
144
+ ret += atomic_read(&prof->cpu_exec_time);
145
+ }
146
+ return ret;
147
+}
148
#else
149
void tcg_dump_op_count(FILE *f, fprintf_function cpu_fprintf)
244
{
150
{
245
- static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
151
cpu_fprintf(f, "[TCG profiler not compiled]\n");
246
- static const TCGTargetOpDef ri_r = { .args_ct_str = { "ri", "r" } };
152
}
247
- static const TCGTargetOpDef re_r = { .args_ct_str = { "re", "r" } };
248
- static const TCGTargetOpDef qi_r = { .args_ct_str = { "qi", "r" } };
249
- static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
250
- static const TCGTargetOpDef r_q = { .args_ct_str = { "r", "q" } };
251
- static const TCGTargetOpDef r_re = { .args_ct_str = { "r", "re" } };
252
- static const TCGTargetOpDef r_0 = { .args_ct_str = { "r", "0" } };
253
- static const TCGTargetOpDef r_r_ri = { .args_ct_str = { "r", "r", "ri" } };
254
- static const TCGTargetOpDef r_r_re = { .args_ct_str = { "r", "r", "re" } };
255
- static const TCGTargetOpDef r_0_r = { .args_ct_str = { "r", "0", "r" } };
256
- static const TCGTargetOpDef r_0_re = { .args_ct_str = { "r", "0", "re" } };
257
- static const TCGTargetOpDef r_0_ci = { .args_ct_str = { "r", "0", "ci" } };
258
- static const TCGTargetOpDef r_L = { .args_ct_str = { "r", "L" } };
259
- static const TCGTargetOpDef L_L = { .args_ct_str = { "L", "L" } };
260
- static const TCGTargetOpDef s_L = { .args_ct_str = { "s", "L" } };
261
- static const TCGTargetOpDef r_L_L = { .args_ct_str = { "r", "L", "L" } };
262
- static const TCGTargetOpDef r_r_L = { .args_ct_str = { "r", "r", "L" } };
263
- static const TCGTargetOpDef L_L_L = { .args_ct_str = { "L", "L", "L" } };
264
- static const TCGTargetOpDef s_L_L = { .args_ct_str = { "s", "L", "L" } };
265
- static const TCGTargetOpDef r_r_L_L
266
- = { .args_ct_str = { "r", "r", "L", "L" } };
267
- static const TCGTargetOpDef L_L_L_L
268
- = { .args_ct_str = { "L", "L", "L", "L" } };
269
- static const TCGTargetOpDef x_x = { .args_ct_str = { "x", "x" } };
270
- static const TCGTargetOpDef x_x_x = { .args_ct_str = { "x", "x", "x" } };
271
- static const TCGTargetOpDef x_x_x_x
272
- = { .args_ct_str = { "x", "x", "x", "x" } };
273
- static const TCGTargetOpDef x_r = { .args_ct_str = { "x", "r" } };
274
-
275
switch (op) {
276
case INDEX_op_goto_ptr:
277
- return &r;
278
+ return C_O0_I1(r);
279
280
case INDEX_op_ld8u_i32:
281
case INDEX_op_ld8u_i64:
282
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
283
case INDEX_op_ld32u_i64:
284
case INDEX_op_ld32s_i64:
285
case INDEX_op_ld_i64:
286
- return &r_r;
287
+ return C_O1_I1(r, r);
288
289
case INDEX_op_st8_i32:
290
case INDEX_op_st8_i64:
291
- return &qi_r;
292
+ return C_O0_I2(qi, r);
293
+
153
+
294
case INDEX_op_st16_i32:
154
+int64_t tcg_cpu_exec_time(void)
295
case INDEX_op_st16_i64:
155
+{
296
case INDEX_op_st_i32:
156
+ error_report("%s: TCG profiler not compiled", __func__);
297
case INDEX_op_st32_i64:
157
+ exit(EXIT_FAILURE);
298
- return &ri_r;
158
+}
299
+ return C_O0_I2(ri, r);
300
+
301
case INDEX_op_st_i64:
302
- return &re_r;
303
+ return C_O0_I2(re, r);
304
305
case INDEX_op_add_i32:
306
case INDEX_op_add_i64:
307
- return &r_r_re;
308
+ return C_O1_I2(r, r, re);
309
+
310
case INDEX_op_sub_i32:
311
case INDEX_op_sub_i64:
312
case INDEX_op_mul_i32:
313
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
314
case INDEX_op_or_i64:
315
case INDEX_op_xor_i32:
316
case INDEX_op_xor_i64:
317
- return &r_0_re;
318
+ return C_O1_I2(r, 0, re);
319
320
case INDEX_op_and_i32:
321
case INDEX_op_and_i64:
322
- {
323
- static const TCGTargetOpDef and
324
- = { .args_ct_str = { "r", "0", "reZ" } };
325
- return &and;
326
- }
327
- break;
328
+ return C_O1_I2(r, 0, reZ);
329
+
330
case INDEX_op_andc_i32:
331
case INDEX_op_andc_i64:
332
- {
333
- static const TCGTargetOpDef andc
334
- = { .args_ct_str = { "r", "r", "rI" } };
335
- return &andc;
336
- }
337
- break;
338
+ return C_O1_I2(r, r, rI);
339
340
case INDEX_op_shl_i32:
341
case INDEX_op_shl_i64:
342
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
343
case INDEX_op_shr_i64:
344
case INDEX_op_sar_i32:
345
case INDEX_op_sar_i64:
346
- return have_bmi2 ? &r_r_ri : &r_0_ci;
347
+ return have_bmi2 ? C_O1_I2(r, r, ri) : C_O1_I2(r, 0, ci);
348
+
349
case INDEX_op_rotl_i32:
350
case INDEX_op_rotl_i64:
351
case INDEX_op_rotr_i32:
352
case INDEX_op_rotr_i64:
353
- return &r_0_ci;
354
+ return C_O1_I2(r, 0, ci);
355
356
case INDEX_op_brcond_i32:
357
case INDEX_op_brcond_i64:
358
- return &r_re;
359
+ return C_O0_I2(r, re);
360
361
case INDEX_op_bswap16_i32:
362
case INDEX_op_bswap16_i64:
363
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
364
case INDEX_op_not_i32:
365
case INDEX_op_not_i64:
366
case INDEX_op_extrh_i64_i32:
367
- return &r_0;
368
+ return C_O1_I1(r, 0);
369
370
case INDEX_op_ext8s_i32:
371
case INDEX_op_ext8s_i64:
372
case INDEX_op_ext8u_i32:
373
case INDEX_op_ext8u_i64:
374
- return &r_q;
375
+ return C_O1_I1(r, q);
376
+
377
case INDEX_op_ext16s_i32:
378
case INDEX_op_ext16s_i64:
379
case INDEX_op_ext16u_i32:
380
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
381
case INDEX_op_sextract_i32:
382
case INDEX_op_ctpop_i32:
383
case INDEX_op_ctpop_i64:
384
- return &r_r;
385
+ return C_O1_I1(r, r);
386
+
387
case INDEX_op_extract2_i32:
388
case INDEX_op_extract2_i64:
389
- return &r_0_r;
390
+ return C_O1_I2(r, 0, r);
391
392
case INDEX_op_deposit_i32:
393
case INDEX_op_deposit_i64:
394
- {
395
- static const TCGTargetOpDef dep
396
- = { .args_ct_str = { "Q", "0", "Q" } };
397
- return &dep;
398
- }
399
+ return C_O1_I2(Q, 0, Q);
400
+
401
case INDEX_op_setcond_i32:
402
case INDEX_op_setcond_i64:
403
- {
404
- static const TCGTargetOpDef setc
405
- = { .args_ct_str = { "q", "r", "re" } };
406
- return &setc;
407
- }
408
+ return C_O1_I2(q, r, re);
409
+
410
case INDEX_op_movcond_i32:
411
case INDEX_op_movcond_i64:
412
- {
413
- static const TCGTargetOpDef movc
414
- = { .args_ct_str = { "r", "r", "re", "r", "0" } };
415
- return &movc;
416
- }
417
+ return C_O1_I4(r, r, re, r, 0);
418
+
419
case INDEX_op_div2_i32:
420
case INDEX_op_div2_i64:
421
case INDEX_op_divu2_i32:
422
case INDEX_op_divu2_i64:
423
- {
424
- static const TCGTargetOpDef div2
425
- = { .args_ct_str = { "a", "d", "0", "1", "r" } };
426
- return &div2;
427
- }
428
+ return C_O2_I3(a, d, 0, 1, r);
429
+
430
case INDEX_op_mulu2_i32:
431
case INDEX_op_mulu2_i64:
432
case INDEX_op_muls2_i32:
433
case INDEX_op_muls2_i64:
434
- {
435
- static const TCGTargetOpDef mul2
436
- = { .args_ct_str = { "a", "d", "a", "r" } };
437
- return &mul2;
438
- }
439
+ return C_O2_I2(a, d, a, r);
440
+
441
case INDEX_op_add2_i32:
442
case INDEX_op_add2_i64:
443
case INDEX_op_sub2_i32:
444
case INDEX_op_sub2_i64:
445
- {
446
- static const TCGTargetOpDef arith2
447
- = { .args_ct_str = { "r", "r", "0", "1", "re", "re" } };
448
- return &arith2;
449
- }
450
+ return C_O2_I4(r, r, 0, 1, re, re);
451
+
452
case INDEX_op_ctz_i32:
453
case INDEX_op_ctz_i64:
454
- {
455
- static const TCGTargetOpDef ctz[2] = {
456
- { .args_ct_str = { "&r", "r", "r" } },
457
- { .args_ct_str = { "&r", "r", "rW" } },
458
- };
459
- return &ctz[have_bmi1];
460
- }
461
+ return have_bmi1 ? C_N1_I2(r, r, rW) : C_N1_I2(r, r, r);
462
+
463
case INDEX_op_clz_i32:
464
case INDEX_op_clz_i64:
465
- {
466
- static const TCGTargetOpDef clz[2] = {
467
- { .args_ct_str = { "&r", "r", "r" } },
468
- { .args_ct_str = { "&r", "r", "rW" } },
469
- };
470
- return &clz[have_lzcnt];
471
- }
472
+ return have_lzcnt ? C_N1_I2(r, r, rW) : C_N1_I2(r, r, r);
473
474
case INDEX_op_qemu_ld_i32:
475
- return TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? &r_L : &r_L_L;
476
+ return (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
477
+ ? C_O1_I1(r, L) : C_O1_I2(r, L, L));
478
+
479
case INDEX_op_qemu_st_i32:
480
- return TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? &L_L : &L_L_L;
481
+ return (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
482
+ ? C_O0_I2(L, L) : C_O0_I3(L, L, L));
483
case INDEX_op_qemu_st8_i32:
484
- return TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? &s_L : &s_L_L;
485
+ return (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
486
+ ? C_O0_I2(s, L) : C_O0_I3(s, L, L));
487
+
488
case INDEX_op_qemu_ld_i64:
489
- return (TCG_TARGET_REG_BITS == 64 ? &r_L
490
- : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? &r_r_L
491
- : &r_r_L_L);
492
+ return (TCG_TARGET_REG_BITS == 64 ? C_O1_I1(r, L)
493
+ : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? C_O2_I1(r, r, L)
494
+ : C_O2_I2(r, r, L, L));
495
+
496
case INDEX_op_qemu_st_i64:
497
- return (TCG_TARGET_REG_BITS == 64 ? &L_L
498
- : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? &L_L_L
499
- : &L_L_L_L);
500
+ return (TCG_TARGET_REG_BITS == 64 ? C_O0_I2(L, L)
501
+ : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? C_O0_I3(L, L, L)
502
+ : C_O0_I4(L, L, L, L));
503
504
case INDEX_op_brcond2_i32:
505
- {
506
- static const TCGTargetOpDef b2
507
- = { .args_ct_str = { "r", "r", "ri", "ri" } };
508
- return &b2;
509
- }
510
+ return C_O0_I4(r, r, ri, ri);
511
+
512
case INDEX_op_setcond2_i32:
513
- {
514
- static const TCGTargetOpDef s2
515
- = { .args_ct_str = { "r", "r", "r", "ri", "ri" } };
516
- return &s2;
517
- }
518
+ return C_O1_I4(r, r, r, ri, ri);
519
520
case INDEX_op_ld_vec:
521
- case INDEX_op_st_vec:
522
case INDEX_op_dupm_vec:
523
- return &x_r;
524
+ return C_O1_I1(x, r);
525
+
526
+ case INDEX_op_st_vec:
527
+ return C_O0_I2(x, r);
528
529
case INDEX_op_add_vec:
530
case INDEX_op_sub_vec:
531
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
532
#if TCG_TARGET_REG_BITS == 32
533
case INDEX_op_dup2_vec:
534
#endif
159
#endif
535
- return &x_x_x;
160
536
+ return C_O1_I2(x, x, x);
161
537
+
538
case INDEX_op_abs_vec:
539
case INDEX_op_dup_vec:
540
case INDEX_op_shli_vec:
541
case INDEX_op_shri_vec:
542
case INDEX_op_sari_vec:
543
case INDEX_op_x86_psrldq_vec:
544
- return &x_x;
545
+ return C_O1_I1(x, x);
546
+
547
case INDEX_op_x86_vpblendvb_vec:
548
- return &x_x_x_x;
549
+ return C_O1_I3(x, x, x, x);
550
551
default:
552
- break;
553
+ g_assert_not_reached();
554
}
555
- return NULL;
556
}
557
558
int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
559
--
162
--
560
2.25.1
163
2.17.2
561
164
562
165
diff view generated by jsdifflib
1
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
1
From: "Emilio G. Cota" <cota@braap.org>
2
3
As far as I can tell tlb_flush does not need to be called
4
this early. tlb_flush is eventually called after the CPU
5
has been realized.
6
7
This change paves the way to the introduction of tlb_init,
8
which will be called from cpu_exec_realizefn.
9
10
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Signed-off-by: Emilio G. Cota <cota@braap.org>
13
Message-Id: <20181009174557.16125-2-cota@braap.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
15
---
4
tcg/s390/tcg-target-con-set.h | 29 ++++++++
16
target/alpha/cpu.c | 1 -
5
tcg/s390/tcg-target.h | 1 +
17
1 file changed, 1 deletion(-)
6
tcg/s390/tcg-target.c.inc | 121 ++++++++++++++--------------------
7
3 files changed, 81 insertions(+), 70 deletions(-)
8
create mode 100644 tcg/s390/tcg-target-con-set.h
9
18
10
diff --git a/tcg/s390/tcg-target-con-set.h b/tcg/s390/tcg-target-con-set.h
19
diff --git a/target/alpha/cpu.c b/target/alpha/cpu.c
11
new file mode 100644
12
index XXXXXXX..XXXXXXX
13
--- /dev/null
14
+++ b/tcg/s390/tcg-target-con-set.h
15
@@ -XXX,XX +XXX,XX @@
16
+/* SPDX-License-Identifier: MIT */
17
+/*
18
+ * Define S390 target-specific constraint sets.
19
+ * Copyright (c) 2021 Linaro
20
+ */
21
+
22
+/*
23
+ * C_On_Im(...) defines a constraint set with <n> outputs and <m> inputs.
24
+ * Each operand should be a sequence of constraint letters as defined by
25
+ * tcg-target-con-str.h; the constraint combination is inclusive or.
26
+ */
27
+C_O0_I1(r)
28
+C_O0_I2(L, L)
29
+C_O0_I2(r, r)
30
+C_O0_I2(r, ri)
31
+C_O1_I1(r, L)
32
+C_O1_I1(r, r)
33
+C_O1_I2(r, 0, ri)
34
+C_O1_I2(r, 0, rI)
35
+C_O1_I2(r, 0, rJ)
36
+C_O1_I2(r, r, ri)
37
+C_O1_I2(r, rZ, r)
38
+C_O1_I4(r, r, ri, r, 0)
39
+C_O1_I4(r, r, ri, rI, 0)
40
+C_O2_I2(b, a, 0, r)
41
+C_O2_I3(b, a, 0, 1, r)
42
+C_O2_I4(r, r, 0, 1, rA, r)
43
+C_O2_I4(r, r, 0, 1, ri, r)
44
+C_O2_I4(r, r, 0, 1, r, r)
45
diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h
46
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
47
--- a/tcg/s390/tcg-target.h
21
--- a/target/alpha/cpu.c
48
+++ b/tcg/s390/tcg-target.h
22
+++ b/target/alpha/cpu.c
49
@@ -XXX,XX +XXX,XX @@ static inline void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
23
@@ -XXX,XX +XXX,XX @@ static void alpha_cpu_initfn(Object *obj)
50
#define TCG_TARGET_NEED_LDST_LABELS
24
CPUAlphaState *env = &cpu->env;
51
#endif
25
52
#define TCG_TARGET_NEED_POOL_LABELS
26
cs->env_ptr = env;
53
+#define TCG_TARGET_CON_SET_H
27
- tlb_flush(cs);
54
28
55
#endif
29
env->lock_addr = -1;
56
diff --git a/tcg/s390/tcg-target.c.inc b/tcg/s390/tcg-target.c.inc
30
#if defined(CONFIG_USER_ONLY)
57
index XXXXXXX..XXXXXXX 100644
58
--- a/tcg/s390/tcg-target.c.inc
59
+++ b/tcg/s390/tcg-target.c.inc
60
@@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
61
}
62
}
63
64
-static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
65
+static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
66
{
67
- static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
68
- static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
69
- static const TCGTargetOpDef r_L = { .args_ct_str = { "r", "L" } };
70
- static const TCGTargetOpDef L_L = { .args_ct_str = { "L", "L" } };
71
- static const TCGTargetOpDef r_ri = { .args_ct_str = { "r", "ri" } };
72
- static const TCGTargetOpDef r_r_ri = { .args_ct_str = { "r", "r", "ri" } };
73
- static const TCGTargetOpDef r_0_ri = { .args_ct_str = { "r", "0", "ri" } };
74
- static const TCGTargetOpDef r_0_rI = { .args_ct_str = { "r", "0", "rI" } };
75
- static const TCGTargetOpDef r_0_rJ = { .args_ct_str = { "r", "0", "rJ" } };
76
- static const TCGTargetOpDef a2_r
77
- = { .args_ct_str = { "r", "r", "0", "1", "r", "r" } };
78
- static const TCGTargetOpDef a2_ri
79
- = { .args_ct_str = { "r", "r", "0", "1", "ri", "r" } };
80
- static const TCGTargetOpDef a2_rA
81
- = { .args_ct_str = { "r", "r", "0", "1", "rA", "r" } };
82
-
83
switch (op) {
84
case INDEX_op_goto_ptr:
85
- return &r;
86
+ return C_O0_I1(r);
87
88
case INDEX_op_ld8u_i32:
89
case INDEX_op_ld8u_i64:
90
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
91
case INDEX_op_ld32u_i64:
92
case INDEX_op_ld32s_i64:
93
case INDEX_op_ld_i64:
94
+ return C_O1_I1(r, r);
95
+
96
case INDEX_op_st8_i32:
97
case INDEX_op_st8_i64:
98
case INDEX_op_st16_i32:
99
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
100
case INDEX_op_st_i32:
101
case INDEX_op_st32_i64:
102
case INDEX_op_st_i64:
103
- return &r_r;
104
+ return C_O0_I2(r, r);
105
106
case INDEX_op_add_i32:
107
case INDEX_op_add_i64:
108
- return &r_r_ri;
109
+ case INDEX_op_shl_i64:
110
+ case INDEX_op_shr_i64:
111
+ case INDEX_op_sar_i64:
112
+ case INDEX_op_rotl_i32:
113
+ case INDEX_op_rotl_i64:
114
+ case INDEX_op_rotr_i32:
115
+ case INDEX_op_rotr_i64:
116
+ case INDEX_op_clz_i64:
117
+ case INDEX_op_setcond_i32:
118
+ case INDEX_op_setcond_i64:
119
+ return C_O1_I2(r, r, ri);
120
+
121
case INDEX_op_sub_i32:
122
case INDEX_op_sub_i64:
123
case INDEX_op_and_i32:
124
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
125
case INDEX_op_or_i64:
126
case INDEX_op_xor_i32:
127
case INDEX_op_xor_i64:
128
- return (s390_facilities & FACILITY_DISTINCT_OPS ? &r_r_ri : &r_0_ri);
129
+ return (s390_facilities & FACILITY_DISTINCT_OPS
130
+ ? C_O1_I2(r, r, ri)
131
+ : C_O1_I2(r, 0, ri));
132
133
case INDEX_op_mul_i32:
134
/* If we have the general-instruction-extensions, then we have
135
MULTIPLY SINGLE IMMEDIATE with a signed 32-bit, otherwise we
136
have only MULTIPLY HALFWORD IMMEDIATE, with a signed 16-bit. */
137
- return (s390_facilities & FACILITY_GEN_INST_EXT ? &r_0_ri : &r_0_rI);
138
+ return (s390_facilities & FACILITY_GEN_INST_EXT
139
+ ? C_O1_I2(r, 0, ri)
140
+ : C_O1_I2(r, 0, rI));
141
+
142
case INDEX_op_mul_i64:
143
- return (s390_facilities & FACILITY_GEN_INST_EXT ? &r_0_rJ : &r_0_rI);
144
+ return (s390_facilities & FACILITY_GEN_INST_EXT
145
+ ? C_O1_I2(r, 0, rJ)
146
+ : C_O1_I2(r, 0, rI));
147
148
case INDEX_op_shl_i32:
149
case INDEX_op_shr_i32:
150
case INDEX_op_sar_i32:
151
- return (s390_facilities & FACILITY_DISTINCT_OPS ? &r_r_ri : &r_0_ri);
152
-
153
- case INDEX_op_shl_i64:
154
- case INDEX_op_shr_i64:
155
- case INDEX_op_sar_i64:
156
- return &r_r_ri;
157
-
158
- case INDEX_op_rotl_i32:
159
- case INDEX_op_rotl_i64:
160
- case INDEX_op_rotr_i32:
161
- case INDEX_op_rotr_i64:
162
- return &r_r_ri;
163
+ return (s390_facilities & FACILITY_DISTINCT_OPS
164
+ ? C_O1_I2(r, r, ri)
165
+ : C_O1_I2(r, 0, ri));
166
167
case INDEX_op_brcond_i32:
168
case INDEX_op_brcond_i64:
169
- return &r_ri;
170
+ return C_O0_I2(r, ri);
171
172
case INDEX_op_bswap16_i32:
173
case INDEX_op_bswap16_i64:
174
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
175
case INDEX_op_extu_i32_i64:
176
case INDEX_op_extract_i32:
177
case INDEX_op_extract_i64:
178
- return &r_r;
179
-
180
- case INDEX_op_clz_i64:
181
- case INDEX_op_setcond_i32:
182
- case INDEX_op_setcond_i64:
183
- return &r_r_ri;
184
+ return C_O1_I1(r, r);
185
186
case INDEX_op_qemu_ld_i32:
187
case INDEX_op_qemu_ld_i64:
188
- return &r_L;
189
+ return C_O1_I1(r, L);
190
case INDEX_op_qemu_st_i64:
191
case INDEX_op_qemu_st_i32:
192
- return &L_L;
193
+ return C_O0_I2(L, L);
194
195
case INDEX_op_deposit_i32:
196
case INDEX_op_deposit_i64:
197
- {
198
- static const TCGTargetOpDef dep
199
- = { .args_ct_str = { "r", "rZ", "r" } };
200
- return &dep;
201
- }
202
+ return C_O1_I2(r, rZ, r);
203
+
204
case INDEX_op_movcond_i32:
205
case INDEX_op_movcond_i64:
206
- {
207
- static const TCGTargetOpDef movc
208
- = { .args_ct_str = { "r", "r", "ri", "r", "0" } };
209
- static const TCGTargetOpDef movc_l
210
- = { .args_ct_str = { "r", "r", "ri", "rI", "0" } };
211
- return (s390_facilities & FACILITY_LOAD_ON_COND2 ? &movc_l : &movc);
212
- }
213
+ return (s390_facilities & FACILITY_LOAD_ON_COND2
214
+ ? C_O1_I4(r, r, ri, rI, 0)
215
+ : C_O1_I4(r, r, ri, r, 0));
216
+
217
case INDEX_op_div2_i32:
218
case INDEX_op_div2_i64:
219
case INDEX_op_divu2_i32:
220
case INDEX_op_divu2_i64:
221
- {
222
- static const TCGTargetOpDef div2
223
- = { .args_ct_str = { "b", "a", "0", "1", "r" } };
224
- return &div2;
225
- }
226
+ return C_O2_I3(b, a, 0, 1, r);
227
+
228
case INDEX_op_mulu2_i64:
229
- {
230
- static const TCGTargetOpDef mul2
231
- = { .args_ct_str = { "b", "a", "0", "r" } };
232
- return &mul2;
233
- }
234
+ return C_O2_I2(b, a, 0, r);
235
236
case INDEX_op_add2_i32:
237
case INDEX_op_sub2_i32:
238
- return (s390_facilities & FACILITY_EXT_IMM ? &a2_ri : &a2_r);
239
+ return (s390_facilities & FACILITY_EXT_IMM
240
+ ? C_O2_I4(r, r, 0, 1, ri, r)
241
+ : C_O2_I4(r, r, 0, 1, r, r));
242
+
243
case INDEX_op_add2_i64:
244
case INDEX_op_sub2_i64:
245
- return (s390_facilities & FACILITY_EXT_IMM ? &a2_rA : &a2_r);
246
+ return (s390_facilities & FACILITY_EXT_IMM
247
+ ? C_O2_I4(r, r, 0, 1, rA, r)
248
+ : C_O2_I4(r, r, 0, 1, r, r));
249
250
default:
251
- break;
252
+ g_assert_not_reached();
253
}
254
- return NULL;
255
}
256
257
static void query_s390_facilities(void)
258
--
31
--
259
2.25.1
32
2.17.2
260
33
261
34
diff view generated by jsdifflib
1
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
1
From: "Emilio G. Cota" <cota@braap.org>
2
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
2
3
As far as I can tell tlb_flush does not need to be called
4
this early. tlb_flush is eventually called after the CPU
5
has been realized.
6
7
This change paves the way to the introduction of tlb_init,
8
which will be called from cpu_exec_realizefn.
9
10
Cc: Guan Xuetao <gxt@mprc.pku.edu.cn>
11
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Signed-off-by: Emilio G. Cota <cota@braap.org>
14
Message-Id: <20181009174557.16125-3-cota@braap.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
---
16
---
5
tcg/riscv/tcg-target-con-set.h | 30 ++++++++++++
17
target/unicore32/cpu.c | 2 --
6
tcg/riscv/tcg-target.h | 1 +
18
1 file changed, 2 deletions(-)
7
tcg/riscv/tcg-target.c.inc | 83 ++++++++++------------------------
8
3 files changed, 54 insertions(+), 60 deletions(-)
9
create mode 100644 tcg/riscv/tcg-target-con-set.h
10
19
11
diff --git a/tcg/riscv/tcg-target-con-set.h b/tcg/riscv/tcg-target-con-set.h
20
diff --git a/target/unicore32/cpu.c b/target/unicore32/cpu.c
12
new file mode 100644
13
index XXXXXXX..XXXXXXX
14
--- /dev/null
15
+++ b/tcg/riscv/tcg-target-con-set.h
16
@@ -XXX,XX +XXX,XX @@
17
+/* SPDX-License-Identifier: MIT */
18
+/*
19
+ * Define RISC-V target-specific constraint sets.
20
+ * Copyright (c) 2021 Linaro
21
+ */
22
+
23
+/*
24
+ * C_On_Im(...) defines a constraint set with <n> outputs and <m> inputs.
25
+ * Each operand should be a sequence of constraint letters as defined by
26
+ * tcg-target-con-str.h; the constraint combination is inclusive or.
27
+ */
28
+C_O0_I1(r)
29
+C_O0_I2(LZ, L)
30
+C_O0_I2(rZ, r)
31
+C_O0_I2(rZ, rZ)
32
+C_O0_I3(LZ, L, L)
33
+C_O0_I3(LZ, LZ, L)
34
+C_O0_I4(LZ, LZ, L, L)
35
+C_O0_I4(rZ, rZ, rZ, rZ)
36
+C_O1_I1(r, L)
37
+C_O1_I1(r, r)
38
+C_O1_I2(r, L, L)
39
+C_O1_I2(r, r, ri)
40
+C_O1_I2(r, r, rI)
41
+C_O1_I2(r, rZ, rN)
42
+C_O1_I2(r, rZ, rZ)
43
+C_O1_I4(r, rZ, rZ, rZ, rZ)
44
+C_O2_I1(r, r, L)
45
+C_O2_I2(r, r, L, L)
46
+C_O2_I4(r, r, rZ, rZ, rM, rM)
47
diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
48
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
49
--- a/tcg/riscv/tcg-target.h
22
--- a/target/unicore32/cpu.c
50
+++ b/tcg/riscv/tcg-target.h
23
+++ b/target/unicore32/cpu.c
51
@@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
24
@@ -XXX,XX +XXX,XX @@ static void uc32_cpu_initfn(Object *obj)
52
#define TCG_TARGET_NEED_POOL_LABELS
25
env->uncached_asr = ASR_MODE_PRIV;
53
26
env->regs[31] = 0x03000000;
54
#define TCG_TARGET_HAS_MEMORY_BSWAP 0
55
+#define TCG_TARGET_CON_SET_H
56
57
#endif
27
#endif
58
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
28
-
59
index XXXXXXX..XXXXXXX 100644
29
- tlb_flush(cs);
60
--- a/tcg/riscv/tcg-target.c.inc
61
+++ b/tcg/riscv/tcg-target.c.inc
62
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
63
}
64
}
30
}
65
31
66
-static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
32
static const VMStateDescription vmstate_uc32_cpu = {
67
+static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
68
{
69
- static const TCGTargetOpDef r
70
- = { .args_ct_str = { "r" } };
71
- static const TCGTargetOpDef r_r
72
- = { .args_ct_str = { "r", "r" } };
73
- static const TCGTargetOpDef rZ_r
74
- = { .args_ct_str = { "rZ", "r" } };
75
- static const TCGTargetOpDef rZ_rZ
76
- = { .args_ct_str = { "rZ", "rZ" } };
77
- static const TCGTargetOpDef rZ_rZ_rZ_rZ
78
- = { .args_ct_str = { "rZ", "rZ", "rZ", "rZ" } };
79
- static const TCGTargetOpDef r_r_ri
80
- = { .args_ct_str = { "r", "r", "ri" } };
81
- static const TCGTargetOpDef r_r_rI
82
- = { .args_ct_str = { "r", "r", "rI" } };
83
- static const TCGTargetOpDef r_rZ_rN
84
- = { .args_ct_str = { "r", "rZ", "rN" } };
85
- static const TCGTargetOpDef r_rZ_rZ
86
- = { .args_ct_str = { "r", "rZ", "rZ" } };
87
- static const TCGTargetOpDef r_rZ_rZ_rZ_rZ
88
- = { .args_ct_str = { "r", "rZ", "rZ", "rZ", "rZ" } };
89
- static const TCGTargetOpDef r_L
90
- = { .args_ct_str = { "r", "L" } };
91
- static const TCGTargetOpDef r_r_L
92
- = { .args_ct_str = { "r", "r", "L" } };
93
- static const TCGTargetOpDef r_L_L
94
- = { .args_ct_str = { "r", "L", "L" } };
95
- static const TCGTargetOpDef r_r_L_L
96
- = { .args_ct_str = { "r", "r", "L", "L" } };
97
- static const TCGTargetOpDef LZ_L
98
- = { .args_ct_str = { "LZ", "L" } };
99
- static const TCGTargetOpDef LZ_L_L
100
- = { .args_ct_str = { "LZ", "L", "L" } };
101
- static const TCGTargetOpDef LZ_LZ_L
102
- = { .args_ct_str = { "LZ", "LZ", "L" } };
103
- static const TCGTargetOpDef LZ_LZ_L_L
104
- = { .args_ct_str = { "LZ", "LZ", "L", "L" } };
105
- static const TCGTargetOpDef r_r_rZ_rZ_rM_rM
106
- = { .args_ct_str = { "r", "r", "rZ", "rZ", "rM", "rM" } };
107
-
108
switch (op) {
109
case INDEX_op_goto_ptr:
110
- return &r;
111
+ return C_O0_I1(r);
112
113
case INDEX_op_ld8u_i32:
114
case INDEX_op_ld8s_i32:
115
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
116
case INDEX_op_extrl_i64_i32:
117
case INDEX_op_extrh_i64_i32:
118
case INDEX_op_ext_i32_i64:
119
- return &r_r;
120
+ return C_O1_I1(r, r);
121
122
case INDEX_op_st8_i32:
123
case INDEX_op_st16_i32:
124
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
125
case INDEX_op_st16_i64:
126
case INDEX_op_st32_i64:
127
case INDEX_op_st_i64:
128
- return &rZ_r;
129
+ return C_O0_I2(rZ, r);
130
131
case INDEX_op_add_i32:
132
case INDEX_op_and_i32:
133
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
134
case INDEX_op_and_i64:
135
case INDEX_op_or_i64:
136
case INDEX_op_xor_i64:
137
- return &r_r_rI;
138
+ return C_O1_I2(r, r, rI);
139
140
case INDEX_op_sub_i32:
141
case INDEX_op_sub_i64:
142
- return &r_rZ_rN;
143
+ return C_O1_I2(r, rZ, rN);
144
145
case INDEX_op_mul_i32:
146
case INDEX_op_mulsh_i32:
147
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
148
case INDEX_op_rem_i64:
149
case INDEX_op_remu_i64:
150
case INDEX_op_setcond_i64:
151
- return &r_rZ_rZ;
152
+ return C_O1_I2(r, rZ, rZ);
153
154
case INDEX_op_shl_i32:
155
case INDEX_op_shr_i32:
156
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
157
case INDEX_op_shl_i64:
158
case INDEX_op_shr_i64:
159
case INDEX_op_sar_i64:
160
- return &r_r_ri;
161
+ return C_O1_I2(r, r, ri);
162
163
case INDEX_op_brcond_i32:
164
case INDEX_op_brcond_i64:
165
- return &rZ_rZ;
166
+ return C_O0_I2(rZ, rZ);
167
168
case INDEX_op_add2_i32:
169
case INDEX_op_add2_i64:
170
case INDEX_op_sub2_i32:
171
case INDEX_op_sub2_i64:
172
- return &r_r_rZ_rZ_rM_rM;
173
+ return C_O2_I4(r, r, rZ, rZ, rM, rM);
174
175
case INDEX_op_brcond2_i32:
176
- return &rZ_rZ_rZ_rZ;
177
+ return C_O0_I4(rZ, rZ, rZ, rZ);
178
179
case INDEX_op_setcond2_i32:
180
- return &r_rZ_rZ_rZ_rZ;
181
+ return C_O1_I4(r, rZ, rZ, rZ, rZ);
182
183
case INDEX_op_qemu_ld_i32:
184
- return TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? &r_L : &r_L_L;
185
+ return (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
186
+ ? C_O1_I1(r, L) : C_O1_I2(r, L, L));
187
case INDEX_op_qemu_st_i32:
188
- return TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? &LZ_L : &LZ_L_L;
189
+ return (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
190
+ ? C_O0_I2(LZ, L) : C_O0_I3(LZ, L, L));
191
case INDEX_op_qemu_ld_i64:
192
- return TCG_TARGET_REG_BITS == 64 ? &r_L
193
- : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? &r_r_L
194
- : &r_r_L_L;
195
+ return (TCG_TARGET_REG_BITS == 64 ? C_O1_I1(r, L)
196
+ : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? C_O2_I1(r, r, L)
197
+ : C_O2_I2(r, r, L, L));
198
case INDEX_op_qemu_st_i64:
199
- return TCG_TARGET_REG_BITS == 64 ? &LZ_L
200
- : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? &LZ_LZ_L
201
- : &LZ_LZ_L_L;
202
+ return (TCG_TARGET_REG_BITS == 64 ? C_O0_I2(LZ, L)
203
+ : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? C_O0_I3(LZ, LZ, L)
204
+ : C_O0_I4(LZ, LZ, L, L));
205
206
default:
207
- return NULL;
208
+ g_assert_not_reached();
209
}
210
}
211
212
--
33
--
213
2.25.1
34
2.17.2
214
35
215
36
diff view generated by jsdifflib
1
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
1
From: "Emilio G. Cota" <cota@braap.org>
2
3
Paves the way for the addition of a per-TLB lock.
4
5
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Emilio G. Cota <cota@braap.org>
8
Message-Id: <20181009174557.16125-4-cota@braap.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
10
---
4
tcg/ppc/tcg-target-con-set.h | 42 +++++++++++
11
include/exec/exec-all.h | 8 ++++++++
5
tcg/ppc/tcg-target.h | 1 +
12
accel/tcg/cputlb.c | 4 ++++
6
tcg/ppc/tcg-target.c.inc | 136 +++++++++++++++--------------------
13
exec.c | 1 +
7
3 files changed, 99 insertions(+), 80 deletions(-)
14
3 files changed, 13 insertions(+)
8
create mode 100644 tcg/ppc/tcg-target-con-set.h
9
15
10
diff --git a/tcg/ppc/tcg-target-con-set.h b/tcg/ppc/tcg-target-con-set.h
16
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
11
new file mode 100644
17
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX
18
--- a/include/exec/exec-all.h
13
--- /dev/null
19
+++ b/include/exec/exec-all.h
14
+++ b/tcg/ppc/tcg-target-con-set.h
20
@@ -XXX,XX +XXX,XX @@ void cpu_address_space_init(CPUState *cpu, int asidx,
15
@@ -XXX,XX +XXX,XX @@
21
16
+/* SPDX-License-Identifier: MIT */
22
#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG)
17
+/*
23
/* cputlb.c */
18
+ * Define PowerPC target-specific constraint sets.
24
+/**
19
+ * Copyright (c) 2021 Linaro
25
+ * tlb_init - initialize a CPU's TLB
26
+ * @cpu: CPU whose TLB should be initialized
20
+ */
27
+ */
28
+void tlb_init(CPUState *cpu);
29
/**
30
* tlb_flush_page:
31
* @cpu: CPU whose TLB should be flushed
32
@@ -XXX,XX +XXX,XX @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
33
void probe_write(CPUArchState *env, target_ulong addr, int size, int mmu_idx,
34
uintptr_t retaddr);
35
#else
36
+static inline void tlb_init(CPUState *cpu)
37
+{
38
+}
39
static inline void tlb_flush_page(CPUState *cpu, target_ulong addr)
40
{
41
}
42
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/accel/tcg/cputlb.c
45
+++ b/accel/tcg/cputlb.c
46
@@ -XXX,XX +XXX,XX @@ QEMU_BUILD_BUG_ON(sizeof(target_ulong) > sizeof(run_on_cpu_data));
47
QEMU_BUILD_BUG_ON(NB_MMU_MODES > 16);
48
#define ALL_MMUIDX_BITS ((1 << NB_MMU_MODES) - 1)
49
50
+void tlb_init(CPUState *cpu)
51
+{
52
+}
21
+
53
+
22
+/*
54
/* flush_all_helper: run fn across all cpus
23
+ * C_On_Im(...) defines a constraint set with <n> outputs and <m> inputs.
55
*
24
+ * Each operand should be a sequence of constraint letters as defined by
56
* If the wait flag is set then the src cpu's helper will be queued as
25
+ * tcg-target-con-str.h; the constraint combination is inclusive or.
57
diff --git a/exec.c b/exec.c
26
+ */
27
+C_O0_I1(r)
28
+C_O0_I2(r, r)
29
+C_O0_I2(r, ri)
30
+C_O0_I2(S, S)
31
+C_O0_I2(v, r)
32
+C_O0_I3(S, S, S)
33
+C_O0_I4(r, r, ri, ri)
34
+C_O0_I4(S, S, S, S)
35
+C_O1_I1(r, L)
36
+C_O1_I1(r, r)
37
+C_O1_I1(v, r)
38
+C_O1_I1(v, v)
39
+C_O1_I1(v, vr)
40
+C_O1_I2(r, 0, rZ)
41
+C_O1_I2(r, L, L)
42
+C_O1_I2(r, rI, ri)
43
+C_O1_I2(r, rI, rT)
44
+C_O1_I2(r, r, r)
45
+C_O1_I2(r, r, ri)
46
+C_O1_I2(r, r, rI)
47
+C_O1_I2(r, r, rT)
48
+C_O1_I2(r, r, rU)
49
+C_O1_I2(r, r, rZW)
50
+C_O1_I2(v, v, v)
51
+C_O1_I3(v, v, v, v)
52
+C_O1_I4(r, r, ri, rZ, rZ)
53
+C_O1_I4(r, r, r, ri, ri)
54
+C_O2_I1(L, L, L)
55
+C_O2_I2(L, L, L, L)
56
+C_O2_I4(r, r, rI, rZM, r, r)
57
+C_O2_I4(r, r, r, r, rI, rZM)
58
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
59
index XXXXXXX..XXXXXXX 100644
58
index XXXXXXX..XXXXXXX 100644
60
--- a/tcg/ppc/tcg-target.h
59
--- a/exec.c
61
+++ b/tcg/ppc/tcg-target.h
60
+++ b/exec.c
62
@@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
61
@@ -XXX,XX +XXX,XX @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp)
63
#define TCG_TARGET_NEED_LDST_LABELS
62
tcg_target_initialized = true;
64
#endif
63
cc->tcg_initialize();
65
#define TCG_TARGET_NEED_POOL_LABELS
66
+#define TCG_TARGET_CON_SET_H
67
68
#endif
69
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
70
index XXXXXXX..XXXXXXX 100644
71
--- a/tcg/ppc/tcg-target.c.inc
72
+++ b/tcg/ppc/tcg-target.c.inc
73
@@ -XXX,XX +XXX,XX @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece,
74
va_end(va);
75
}
76
77
-static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
78
+static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
79
{
80
- static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
81
- static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
82
- static const TCGTargetOpDef r_L = { .args_ct_str = { "r", "L" } };
83
- static const TCGTargetOpDef S_S = { .args_ct_str = { "S", "S" } };
84
- static const TCGTargetOpDef r_ri = { .args_ct_str = { "r", "ri" } };
85
- static const TCGTargetOpDef r_r_r = { .args_ct_str = { "r", "r", "r" } };
86
- static const TCGTargetOpDef r_L_L = { .args_ct_str = { "r", "L", "L" } };
87
- static const TCGTargetOpDef L_L_L = { .args_ct_str = { "L", "L", "L" } };
88
- static const TCGTargetOpDef S_S_S = { .args_ct_str = { "S", "S", "S" } };
89
- static const TCGTargetOpDef r_r_ri = { .args_ct_str = { "r", "r", "ri" } };
90
- static const TCGTargetOpDef r_r_rI = { .args_ct_str = { "r", "r", "rI" } };
91
- static const TCGTargetOpDef r_r_rT = { .args_ct_str = { "r", "r", "rT" } };
92
- static const TCGTargetOpDef r_r_rU = { .args_ct_str = { "r", "r", "rU" } };
93
- static const TCGTargetOpDef r_rI_ri
94
- = { .args_ct_str = { "r", "rI", "ri" } };
95
- static const TCGTargetOpDef r_rI_rT
96
- = { .args_ct_str = { "r", "rI", "rT" } };
97
- static const TCGTargetOpDef r_r_rZW
98
- = { .args_ct_str = { "r", "r", "rZW" } };
99
- static const TCGTargetOpDef L_L_L_L
100
- = { .args_ct_str = { "L", "L", "L", "L" } };
101
- static const TCGTargetOpDef S_S_S_S
102
- = { .args_ct_str = { "S", "S", "S", "S" } };
103
- static const TCGTargetOpDef movc
104
- = { .args_ct_str = { "r", "r", "ri", "rZ", "rZ" } };
105
- static const TCGTargetOpDef dep
106
- = { .args_ct_str = { "r", "0", "rZ" } };
107
- static const TCGTargetOpDef br2
108
- = { .args_ct_str = { "r", "r", "ri", "ri" } };
109
- static const TCGTargetOpDef setc2
110
- = { .args_ct_str = { "r", "r", "r", "ri", "ri" } };
111
- static const TCGTargetOpDef add2
112
- = { .args_ct_str = { "r", "r", "r", "r", "rI", "rZM" } };
113
- static const TCGTargetOpDef sub2
114
- = { .args_ct_str = { "r", "r", "rI", "rZM", "r", "r" } };
115
- static const TCGTargetOpDef v_r = { .args_ct_str = { "v", "r" } };
116
- static const TCGTargetOpDef v_vr = { .args_ct_str = { "v", "vr" } };
117
- static const TCGTargetOpDef v_v = { .args_ct_str = { "v", "v" } };
118
- static const TCGTargetOpDef v_v_v = { .args_ct_str = { "v", "v", "v" } };
119
- static const TCGTargetOpDef v_v_v_v
120
- = { .args_ct_str = { "v", "v", "v", "v" } };
121
-
122
switch (op) {
123
case INDEX_op_goto_ptr:
124
- return &r;
125
+ return C_O0_I1(r);
126
127
case INDEX_op_ld8u_i32:
128
case INDEX_op_ld8s_i32:
129
case INDEX_op_ld16u_i32:
130
case INDEX_op_ld16s_i32:
131
case INDEX_op_ld_i32:
132
- case INDEX_op_st8_i32:
133
- case INDEX_op_st16_i32:
134
- case INDEX_op_st_i32:
135
case INDEX_op_ctpop_i32:
136
case INDEX_op_neg_i32:
137
case INDEX_op_not_i32:
138
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
139
case INDEX_op_ld32u_i64:
140
case INDEX_op_ld32s_i64:
141
case INDEX_op_ld_i64:
142
- case INDEX_op_st8_i64:
143
- case INDEX_op_st16_i64:
144
- case INDEX_op_st32_i64:
145
- case INDEX_op_st_i64:
146
case INDEX_op_ctpop_i64:
147
case INDEX_op_neg_i64:
148
case INDEX_op_not_i64:
149
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
150
case INDEX_op_bswap32_i64:
151
case INDEX_op_bswap64_i64:
152
case INDEX_op_extract_i64:
153
- return &r_r;
154
+ return C_O1_I1(r, r);
155
+
156
+ case INDEX_op_st8_i32:
157
+ case INDEX_op_st16_i32:
158
+ case INDEX_op_st_i32:
159
+ case INDEX_op_st8_i64:
160
+ case INDEX_op_st16_i64:
161
+ case INDEX_op_st32_i64:
162
+ case INDEX_op_st_i64:
163
+ return C_O0_I2(r, r);
164
165
case INDEX_op_add_i32:
166
case INDEX_op_and_i32:
167
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
168
case INDEX_op_rotl_i64:
169
case INDEX_op_rotr_i64:
170
case INDEX_op_setcond_i64:
171
- return &r_r_ri;
172
+ return C_O1_I2(r, r, ri);
173
+
174
case INDEX_op_mul_i32:
175
case INDEX_op_mul_i64:
176
- return &r_r_rI;
177
+ return C_O1_I2(r, r, rI);
178
+
179
case INDEX_op_div_i32:
180
case INDEX_op_divu_i32:
181
case INDEX_op_nand_i32:
182
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
183
case INDEX_op_divu_i64:
184
case INDEX_op_mulsh_i64:
185
case INDEX_op_muluh_i64:
186
- return &r_r_r;
187
+ return C_O1_I2(r, r, r);
188
+
189
case INDEX_op_sub_i32:
190
- return &r_rI_ri;
191
+ return C_O1_I2(r, rI, ri);
192
case INDEX_op_add_i64:
193
- return &r_r_rT;
194
+ return C_O1_I2(r, r, rT);
195
case INDEX_op_or_i64:
196
case INDEX_op_xor_i64:
197
- return &r_r_rU;
198
+ return C_O1_I2(r, r, rU);
199
case INDEX_op_sub_i64:
200
- return &r_rI_rT;
201
+ return C_O1_I2(r, rI, rT);
202
case INDEX_op_clz_i32:
203
case INDEX_op_ctz_i32:
204
case INDEX_op_clz_i64:
205
case INDEX_op_ctz_i64:
206
- return &r_r_rZW;
207
+ return C_O1_I2(r, r, rZW);
208
209
case INDEX_op_brcond_i32:
210
case INDEX_op_brcond_i64:
211
- return &r_ri;
212
+ return C_O0_I2(r, ri);
213
214
case INDEX_op_movcond_i32:
215
case INDEX_op_movcond_i64:
216
- return &movc;
217
+ return C_O1_I4(r, r, ri, rZ, rZ);
218
case INDEX_op_deposit_i32:
219
case INDEX_op_deposit_i64:
220
- return &dep;
221
+ return C_O1_I2(r, 0, rZ);
222
case INDEX_op_brcond2_i32:
223
- return &br2;
224
+ return C_O0_I4(r, r, ri, ri);
225
case INDEX_op_setcond2_i32:
226
- return &setc2;
227
+ return C_O1_I4(r, r, r, ri, ri);
228
case INDEX_op_add2_i64:
229
case INDEX_op_add2_i32:
230
- return &add2;
231
+ return C_O2_I4(r, r, r, r, rI, rZM);
232
case INDEX_op_sub2_i64:
233
case INDEX_op_sub2_i32:
234
- return &sub2;
235
+ return C_O2_I4(r, r, rI, rZM, r, r);
236
237
case INDEX_op_qemu_ld_i32:
238
return (TCG_TARGET_REG_BITS == 64 || TARGET_LONG_BITS == 32
239
- ? &r_L : &r_L_L);
240
+ ? C_O1_I1(r, L)
241
+ : C_O1_I2(r, L, L));
242
+
243
case INDEX_op_qemu_st_i32:
244
return (TCG_TARGET_REG_BITS == 64 || TARGET_LONG_BITS == 32
245
- ? &S_S : &S_S_S);
246
+ ? C_O0_I2(S, S)
247
+ : C_O0_I3(S, S, S));
248
+
249
case INDEX_op_qemu_ld_i64:
250
- return (TCG_TARGET_REG_BITS == 64 ? &r_L
251
- : TARGET_LONG_BITS == 32 ? &L_L_L : &L_L_L_L);
252
+ return (TCG_TARGET_REG_BITS == 64 ? C_O1_I1(r, L)
253
+ : TARGET_LONG_BITS == 32 ? C_O2_I1(L, L, L)
254
+ : C_O2_I2(L, L, L, L));
255
+
256
case INDEX_op_qemu_st_i64:
257
- return (TCG_TARGET_REG_BITS == 64 ? &S_S
258
- : TARGET_LONG_BITS == 32 ? &S_S_S : &S_S_S_S);
259
+ return (TCG_TARGET_REG_BITS == 64 ? C_O0_I2(S, S)
260
+ : TARGET_LONG_BITS == 32 ? C_O0_I3(S, S, S)
261
+ : C_O0_I4(S, S, S, S));
262
263
case INDEX_op_add_vec:
264
case INDEX_op_sub_vec:
265
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
266
case INDEX_op_ppc_mulou_vec:
267
case INDEX_op_ppc_pkum_vec:
268
case INDEX_op_dup2_vec:
269
- return &v_v_v;
270
+ return C_O1_I2(v, v, v);
271
+
272
case INDEX_op_not_vec:
273
case INDEX_op_neg_vec:
274
- return &v_v;
275
+ return C_O1_I1(v, v);
276
+
277
case INDEX_op_dup_vec:
278
- return have_isa_3_00 ? &v_vr : &v_v;
279
+ return have_isa_3_00 ? C_O1_I1(v, vr) : C_O1_I1(v, v);
280
+
281
case INDEX_op_ld_vec:
282
- case INDEX_op_st_vec:
283
case INDEX_op_dupm_vec:
284
- return &v_r;
285
+ return C_O1_I1(v, r);
286
+
287
+ case INDEX_op_st_vec:
288
+ return C_O0_I2(v, r);
289
+
290
case INDEX_op_bitsel_vec:
291
case INDEX_op_ppc_msum_vec:
292
- return &v_v_v_v;
293
+ return C_O1_I3(v, v, v, v);
294
295
default:
296
- return NULL;
297
+ g_assert_not_reached();
298
}
64
}
299
}
65
+ tlb_init(cpu);
300
66
67
#ifndef CONFIG_USER_ONLY
68
if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
301
--
69
--
302
2.25.1
70
2.17.2
303
71
304
72
diff view generated by jsdifflib
1
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
1
From: "Emilio G. Cota" <cota@braap.org>
2
3
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
5
Signed-off-by: Emilio G. Cota <cota@braap.org>
6
Message-Id: <20181009174557.16125-5-cota@braap.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
8
---
4
tcg/mips/tcg-target-con-set.h | 36 +++++++++++++
9
accel/tcg/cputlb.c | 4 ++--
5
tcg/mips/tcg-target.h | 1 +
10
1 file changed, 2 insertions(+), 2 deletions(-)
6
tcg/mips/tcg-target.c.inc | 96 +++++++++++------------------------
7
3 files changed, 66 insertions(+), 67 deletions(-)
8
create mode 100644 tcg/mips/tcg-target-con-set.h
9
11
10
diff --git a/tcg/mips/tcg-target-con-set.h b/tcg/mips/tcg-target-con-set.h
12
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
11
new file mode 100644
13
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX
14
--- a/accel/tcg/cputlb.c
13
--- /dev/null
15
+++ b/accel/tcg/cputlb.c
14
+++ b/tcg/mips/tcg-target-con-set.h
15
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@
16
+/* SPDX-License-Identifier: MIT */
17
} \
17
+/*
18
} while (0)
18
+ * Define MIPS target-specific constraint sets.
19
19
+ * Copyright (c) 2021 Linaro
20
-#define assert_cpu_is_self(this_cpu) do { \
20
+ */
21
+#define assert_cpu_is_self(cpu) do { \
21
+
22
if (DEBUG_TLB_GATE) { \
22
+/*
23
- g_assert(!cpu->created || qemu_cpu_is_self(cpu)); \
23
+ * C_On_Im(...) defines a constraint set with <n> outputs and <m> inputs.
24
+ g_assert(!(cpu)->created || qemu_cpu_is_self(cpu)); \
24
+ * Each operand should be a sequence of constraint letters as defined by
25
} \
25
+ * tcg-target-con-str.h; the constraint combination is inclusive or.
26
} while (0)
26
+ */
27
+C_O0_I1(r)
28
+C_O0_I2(rZ, r)
29
+C_O0_I2(rZ, rZ)
30
+C_O0_I2(SZ, S)
31
+C_O0_I3(SZ, S, S)
32
+C_O0_I3(SZ, SZ, S)
33
+C_O0_I4(rZ, rZ, rZ, rZ)
34
+C_O0_I4(SZ, SZ, S, S)
35
+C_O1_I1(r, L)
36
+C_O1_I1(r, r)
37
+C_O1_I2(r, 0, rZ)
38
+C_O1_I2(r, L, L)
39
+C_O1_I2(r, r, ri)
40
+C_O1_I2(r, r, rI)
41
+C_O1_I2(r, r, rIK)
42
+C_O1_I2(r, r, rJ)
43
+C_O1_I2(r, r, rWZ)
44
+C_O1_I2(r, rZ, rN)
45
+C_O1_I2(r, rZ, rZ)
46
+C_O1_I4(r, rZ, rZ, rZ, 0)
47
+C_O1_I4(r, rZ, rZ, rZ, rZ)
48
+C_O2_I1(r, r, L)
49
+C_O2_I2(r, r, L, L)
50
+C_O2_I2(r, r, r, r)
51
+C_O2_I4(r, r, rZ, rZ, rN, rN)
52
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
53
index XXXXXXX..XXXXXXX 100644
54
--- a/tcg/mips/tcg-target.h
55
+++ b/tcg/mips/tcg-target.h
56
@@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
57
#ifdef CONFIG_SOFTMMU
58
#define TCG_TARGET_NEED_LDST_LABELS
59
#endif
60
+#define TCG_TARGET_CON_SET_H
61
62
#endif
63
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
64
index XXXXXXX..XXXXXXX 100644
65
--- a/tcg/mips/tcg-target.c.inc
66
+++ b/tcg/mips/tcg-target.c.inc
67
@@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
68
}
69
}
70
71
-static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
72
+static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
73
{
74
- static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
75
- static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
76
- static const TCGTargetOpDef r_L = { .args_ct_str = { "r", "L" } };
77
- static const TCGTargetOpDef rZ_r = { .args_ct_str = { "rZ", "r" } };
78
- static const TCGTargetOpDef SZ_S = { .args_ct_str = { "SZ", "S" } };
79
- static const TCGTargetOpDef rZ_rZ = { .args_ct_str = { "rZ", "rZ" } };
80
- static const TCGTargetOpDef r_r_L = { .args_ct_str = { "r", "r", "L" } };
81
- static const TCGTargetOpDef r_L_L = { .args_ct_str = { "r", "L", "L" } };
82
- static const TCGTargetOpDef r_r_ri = { .args_ct_str = { "r", "r", "ri" } };
83
- static const TCGTargetOpDef r_r_rI = { .args_ct_str = { "r", "r", "rI" } };
84
- static const TCGTargetOpDef r_r_rJ = { .args_ct_str = { "r", "r", "rJ" } };
85
- static const TCGTargetOpDef SZ_S_S = { .args_ct_str = { "SZ", "S", "S" } };
86
- static const TCGTargetOpDef SZ_SZ_S
87
- = { .args_ct_str = { "SZ", "SZ", "S" } };
88
- static const TCGTargetOpDef SZ_SZ_S_S
89
- = { .args_ct_str = { "SZ", "SZ", "S", "S" } };
90
- static const TCGTargetOpDef r_rZ_rN
91
- = { .args_ct_str = { "r", "rZ", "rN" } };
92
- static const TCGTargetOpDef r_rZ_rZ
93
- = { .args_ct_str = { "r", "rZ", "rZ" } };
94
- static const TCGTargetOpDef r_r_rIK
95
- = { .args_ct_str = { "r", "r", "rIK" } };
96
- static const TCGTargetOpDef r_r_rWZ
97
- = { .args_ct_str = { "r", "r", "rWZ" } };
98
- static const TCGTargetOpDef r_r_r_r
99
- = { .args_ct_str = { "r", "r", "r", "r" } };
100
- static const TCGTargetOpDef r_r_L_L
101
- = { .args_ct_str = { "r", "r", "L", "L" } };
102
- static const TCGTargetOpDef dep
103
- = { .args_ct_str = { "r", "0", "rZ" } };
104
- static const TCGTargetOpDef movc
105
- = { .args_ct_str = { "r", "rZ", "rZ", "rZ", "0" } };
106
- static const TCGTargetOpDef movc_r6
107
- = { .args_ct_str = { "r", "rZ", "rZ", "rZ", "rZ" } };
108
- static const TCGTargetOpDef add2
109
- = { .args_ct_str = { "r", "r", "rZ", "rZ", "rN", "rN" } };
110
- static const TCGTargetOpDef br2
111
- = { .args_ct_str = { "rZ", "rZ", "rZ", "rZ" } };
112
- static const TCGTargetOpDef setc2
113
- = { .args_ct_str = { "r", "rZ", "rZ", "rZ", "rZ" } };
114
-
115
switch (op) {
116
case INDEX_op_goto_ptr:
117
- return &r;
118
+ return C_O0_I1(r);
119
120
case INDEX_op_ld8u_i32:
121
case INDEX_op_ld8s_i32:
122
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
123
case INDEX_op_extrl_i64_i32:
124
case INDEX_op_extrh_i64_i32:
125
case INDEX_op_extract_i64:
126
- return &r_r;
127
+ return C_O1_I1(r, r);
128
129
case INDEX_op_st8_i32:
130
case INDEX_op_st16_i32:
131
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
132
case INDEX_op_st16_i64:
133
case INDEX_op_st32_i64:
134
case INDEX_op_st_i64:
135
- return &rZ_r;
136
+ return C_O0_I2(rZ, r);
137
138
case INDEX_op_add_i32:
139
case INDEX_op_add_i64:
140
- return &r_r_rJ;
141
+ return C_O1_I2(r, r, rJ);
142
case INDEX_op_sub_i32:
143
case INDEX_op_sub_i64:
144
- return &r_rZ_rN;
145
+ return C_O1_I2(r, rZ, rN);
146
case INDEX_op_mul_i32:
147
case INDEX_op_mulsh_i32:
148
case INDEX_op_muluh_i32:
149
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
150
case INDEX_op_remu_i64:
151
case INDEX_op_nor_i64:
152
case INDEX_op_setcond_i64:
153
- return &r_rZ_rZ;
154
+ return C_O1_I2(r, rZ, rZ);
155
case INDEX_op_muls2_i32:
156
case INDEX_op_mulu2_i32:
157
case INDEX_op_muls2_i64:
158
case INDEX_op_mulu2_i64:
159
- return &r_r_r_r;
160
+ return C_O2_I2(r, r, r, r);
161
case INDEX_op_and_i32:
162
case INDEX_op_and_i64:
163
- return &r_r_rIK;
164
+ return C_O1_I2(r, r, rIK);
165
case INDEX_op_or_i32:
166
case INDEX_op_xor_i32:
167
case INDEX_op_or_i64:
168
case INDEX_op_xor_i64:
169
- return &r_r_rI;
170
+ return C_O1_I2(r, r, rI);
171
case INDEX_op_shl_i32:
172
case INDEX_op_shr_i32:
173
case INDEX_op_sar_i32:
174
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
175
case INDEX_op_sar_i64:
176
case INDEX_op_rotr_i64:
177
case INDEX_op_rotl_i64:
178
- return &r_r_ri;
179
+ return C_O1_I2(r, r, ri);
180
case INDEX_op_clz_i32:
181
case INDEX_op_clz_i64:
182
- return &r_r_rWZ;
183
+ return C_O1_I2(r, r, rWZ);
184
185
case INDEX_op_deposit_i32:
186
case INDEX_op_deposit_i64:
187
- return &dep;
188
+ return C_O1_I2(r, 0, rZ);
189
case INDEX_op_brcond_i32:
190
case INDEX_op_brcond_i64:
191
- return &rZ_rZ;
192
+ return C_O0_I2(rZ, rZ);
193
case INDEX_op_movcond_i32:
194
case INDEX_op_movcond_i64:
195
- return use_mips32r6_instructions ? &movc_r6 : &movc;
196
-
197
+ return (use_mips32r6_instructions
198
+ ? C_O1_I4(r, rZ, rZ, rZ, rZ)
199
+ : C_O1_I4(r, rZ, rZ, rZ, 0));
200
case INDEX_op_add2_i32:
201
case INDEX_op_sub2_i32:
202
- return &add2;
203
+ return C_O2_I4(r, r, rZ, rZ, rN, rN);
204
case INDEX_op_setcond2_i32:
205
- return &setc2;
206
+ return C_O1_I4(r, rZ, rZ, rZ, rZ);
207
case INDEX_op_brcond2_i32:
208
- return &br2;
209
+ return C_O0_I4(rZ, rZ, rZ, rZ);
210
211
case INDEX_op_qemu_ld_i32:
212
return (TCG_TARGET_REG_BITS == 64 || TARGET_LONG_BITS == 32
213
- ? &r_L : &r_L_L);
214
+ ? C_O1_I1(r, L) : C_O1_I2(r, L, L));
215
case INDEX_op_qemu_st_i32:
216
return (TCG_TARGET_REG_BITS == 64 || TARGET_LONG_BITS == 32
217
- ? &SZ_S : &SZ_S_S);
218
+ ? C_O0_I2(SZ, S) : C_O0_I3(SZ, S, S));
219
case INDEX_op_qemu_ld_i64:
220
- return (TCG_TARGET_REG_BITS == 64 ? &r_L
221
- : TARGET_LONG_BITS == 32 ? &r_r_L : &r_r_L_L);
222
+ return (TCG_TARGET_REG_BITS == 64 ? C_O1_I1(r, L)
223
+ : TARGET_LONG_BITS == 32 ? C_O2_I1(r, r, L)
224
+ : C_O2_I2(r, r, L, L));
225
case INDEX_op_qemu_st_i64:
226
- return (TCG_TARGET_REG_BITS == 64 ? &SZ_S
227
- : TARGET_LONG_BITS == 32 ? &SZ_SZ_S : &SZ_SZ_S_S);
228
+ return (TCG_TARGET_REG_BITS == 64 ? C_O0_I2(SZ, S)
229
+ : TARGET_LONG_BITS == 32 ? C_O0_I3(SZ, SZ, S)
230
+ : C_O0_I4(SZ, SZ, S, S));
231
232
default:
233
- return NULL;
234
+ g_assert_not_reached();
235
}
236
}
237
27
238
--
28
--
239
2.25.1
29
2.17.2
240
30
241
31
diff view generated by jsdifflib
1
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
1
From: "Emilio G. Cota" <cota@braap.org>
2
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
3
Currently we rely on atomic operations for cross-CPU invalidations.
4
There are two cases that these atomics miss: cross-CPU invalidations
5
can race with either (1) vCPU threads flushing their TLB, which
6
happens via memset, or (2) vCPUs calling tlb_reset_dirty on their TLB,
7
which updates .addr_write with a regular store. This results in
8
undefined behaviour, since we're mixing regular and atomic ops
9
on concurrent accesses.
10
11
Fix it by using tlb_lock, a per-vCPU lock. All updaters of tlb_table
12
and the corresponding victim cache now hold the lock.
13
The readers that do not hold tlb_lock must use atomic reads when
14
reading .addr_write, since this field can be updated by other threads;
15
the conversion to atomic reads is done in the next patch.
16
17
Note that an alternative fix would be to expand the use of atomic ops.
18
However, in the case of TLB flushes this would have a huge performance
19
impact, since (1) TLB flushes can happen very frequently and (2) we
20
currently use a full memory barrier to flush each TLB entry, and a TLB
21
has many entries. Instead, acquiring the lock is barely slower than a
22
full memory barrier since it is uncontended, and with a single lock
23
acquisition we can flush the entire TLB.
24
25
Tested-by: Alex Bennée <alex.bennee@linaro.org>
26
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
27
Signed-off-by: Emilio G. Cota <cota@braap.org>
28
Message-Id: <20181009174557.16125-6-cota@braap.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
29
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
---
30
---
5
tcg/mips/tcg-target-con-str.h | 24 +++++++++++
31
include/exec/cpu-defs.h | 3 +
6
tcg/mips/tcg-target.h | 1 +
32
accel/tcg/cputlb.c | 155 ++++++++++++++++++++++------------------
7
tcg/mips/tcg-target.c.inc | 77 ++++++++++-------------------------
33
2 files changed, 87 insertions(+), 71 deletions(-)
8
3 files changed, 46 insertions(+), 56 deletions(-)
34
9
create mode 100644 tcg/mips/tcg-target-con-str.h
35
diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h
10
36
index XXXXXXX..XXXXXXX 100644
11
diff --git a/tcg/mips/tcg-target-con-str.h b/tcg/mips/tcg-target-con-str.h
37
--- a/include/exec/cpu-defs.h
12
new file mode 100644
38
+++ b/include/exec/cpu-defs.h
13
index XXXXXXX..XXXXXXX
14
--- /dev/null
15
+++ b/tcg/mips/tcg-target-con-str.h
16
@@ -XXX,XX +XXX,XX @@
39
@@ -XXX,XX +XXX,XX @@
17
+/* SPDX-License-Identifier: MIT */
40
#endif
41
42
#include "qemu/host-utils.h"
43
+#include "qemu/thread.h"
44
#include "qemu/queue.h"
45
#ifdef CONFIG_TCG
46
#include "tcg-target.h"
47
@@ -XXX,XX +XXX,XX @@ typedef struct CPUIOTLBEntry {
48
49
#define CPU_COMMON_TLB \
50
/* The meaning of the MMU modes is defined in the target code. */ \
51
+ /* tlb_lock serializes updates to tlb_table and tlb_v_table */ \
52
+ QemuSpin tlb_lock; \
53
CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \
54
CPUTLBEntry tlb_v_table[NB_MMU_MODES][CPU_VTLB_SIZE]; \
55
CPUIOTLBEntry iotlb[NB_MMU_MODES][CPU_TLB_SIZE]; \
56
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/accel/tcg/cputlb.c
59
+++ b/accel/tcg/cputlb.c
60
@@ -XXX,XX +XXX,XX @@ QEMU_BUILD_BUG_ON(NB_MMU_MODES > 16);
61
62
void tlb_init(CPUState *cpu)
63
{
64
+ CPUArchState *env = cpu->env_ptr;
65
+
66
+ qemu_spin_init(&env->tlb_lock);
67
}
68
69
/* flush_all_helper: run fn across all cpus
70
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_nocheck(CPUState *cpu)
71
atomic_set(&env->tlb_flush_count, env->tlb_flush_count + 1);
72
tlb_debug("(count: %zu)\n", tlb_flush_count());
73
74
+ /*
75
+ * tlb_table/tlb_v_table updates from any thread must hold tlb_lock.
76
+ * However, updates from the owner thread (as is the case here; see the
77
+ * above assert_cpu_is_self) do not need atomic_set because all reads
78
+ * that do not hold the lock are performed by the same owner thread.
79
+ */
80
+ qemu_spin_lock(&env->tlb_lock);
81
memset(env->tlb_table, -1, sizeof(env->tlb_table));
82
memset(env->tlb_v_table, -1, sizeof(env->tlb_v_table));
83
+ qemu_spin_unlock(&env->tlb_lock);
84
+
85
cpu_tb_jmp_cache_clear(cpu);
86
87
env->vtlb_index = 0;
88
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data)
89
90
tlb_debug("start: mmu_idx:0x%04lx\n", mmu_idx_bitmask);
91
92
+ qemu_spin_lock(&env->tlb_lock);
93
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
94
95
if (test_bit(mmu_idx, &mmu_idx_bitmask)) {
96
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_by_mmuidx_async_work(CPUState *cpu, run_on_cpu_data data)
97
memset(env->tlb_v_table[mmu_idx], -1, sizeof(env->tlb_v_table[0]));
98
}
99
}
100
+ qemu_spin_unlock(&env->tlb_lock);
101
102
cpu_tb_jmp_cache_clear(cpu);
103
104
@@ -XXX,XX +XXX,XX @@ static inline bool tlb_hit_page_anyprot(CPUTLBEntry *tlb_entry,
105
tlb_hit_page(tlb_entry->addr_code, page);
106
}
107
108
-static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong page)
109
+/* Called with tlb_lock held */
110
+static inline void tlb_flush_entry_locked(CPUTLBEntry *tlb_entry,
111
+ target_ulong page)
112
{
113
if (tlb_hit_page_anyprot(tlb_entry, page)) {
114
memset(tlb_entry, -1, sizeof(*tlb_entry));
115
}
116
}
117
118
-static inline void tlb_flush_vtlb_page(CPUArchState *env, int mmu_idx,
119
- target_ulong page)
120
+/* Called with tlb_lock held */
121
+static inline void tlb_flush_vtlb_page_locked(CPUArchState *env, int mmu_idx,
122
+ target_ulong page)
123
{
124
int k;
125
+
126
+ assert_cpu_is_self(ENV_GET_CPU(env));
127
for (k = 0; k < CPU_VTLB_SIZE; k++) {
128
- tlb_flush_entry(&env->tlb_v_table[mmu_idx][k], page);
129
+ tlb_flush_entry_locked(&env->tlb_v_table[mmu_idx][k], page);
130
}
131
}
132
133
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_page_async_work(CPUState *cpu, run_on_cpu_data data)
134
135
addr &= TARGET_PAGE_MASK;
136
i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
137
+ qemu_spin_lock(&env->tlb_lock);
138
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
139
- tlb_flush_entry(&env->tlb_table[mmu_idx][i], addr);
140
- tlb_flush_vtlb_page(env, mmu_idx, addr);
141
+ tlb_flush_entry_locked(&env->tlb_table[mmu_idx][i], addr);
142
+ tlb_flush_vtlb_page_locked(env, mmu_idx, addr);
143
}
144
+ qemu_spin_unlock(&env->tlb_lock);
145
146
tb_flush_jmp_cache(cpu, addr);
147
}
148
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_page_by_mmuidx_async_work(CPUState *cpu,
149
tlb_debug("page:%d addr:"TARGET_FMT_lx" mmu_idx:0x%lx\n",
150
page, addr, mmu_idx_bitmap);
151
152
+ qemu_spin_lock(&env->tlb_lock);
153
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
154
if (test_bit(mmu_idx, &mmu_idx_bitmap)) {
155
- tlb_flush_entry(&env->tlb_table[mmu_idx][page], addr);
156
- tlb_flush_vtlb_page(env, mmu_idx, addr);
157
+ tlb_flush_entry_locked(&env->tlb_table[mmu_idx][page], addr);
158
+ tlb_flush_vtlb_page_locked(env, mmu_idx, addr);
159
}
160
}
161
+ qemu_spin_unlock(&env->tlb_lock);
162
163
tb_flush_jmp_cache(cpu, addr);
164
}
165
@@ -XXX,XX +XXX,XX @@ void tlb_unprotect_code(ram_addr_t ram_addr)
166
* most usual is detecting writes to code regions which may invalidate
167
* generated code.
168
*
169
- * Because we want other vCPUs to respond to changes straight away we
170
- * update the te->addr_write field atomically. If the TLB entry has
171
- * been changed by the vCPU in the mean time we skip the update.
172
+ * Other vCPUs might be reading their TLBs during guest execution, so we update
173
+ * te->addr_write with atomic_set. We don't need to worry about this for
174
+ * oversized guests as MTTCG is disabled for them.
175
*
176
- * As this function uses atomic accesses we also need to ensure
177
- * updates to tlb_entries follow the same access rules. We don't need
178
- * to worry about this for oversized guests as MTTCG is disabled for
179
- * them.
180
+ * Called with tlb_lock held.
181
*/
182
-
183
-static void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry, uintptr_t start,
184
- uintptr_t length)
185
+static void tlb_reset_dirty_range_locked(CPUTLBEntry *tlb_entry,
186
+ uintptr_t start, uintptr_t length)
187
{
188
-#if TCG_OVERSIZED_GUEST
189
uintptr_t addr = tlb_entry->addr_write;
190
191
if ((addr & (TLB_INVALID_MASK | TLB_MMIO | TLB_NOTDIRTY)) == 0) {
192
addr &= TARGET_PAGE_MASK;
193
addr += tlb_entry->addend;
194
if ((addr - start) < length) {
195
+#if TCG_OVERSIZED_GUEST
196
tlb_entry->addr_write |= TLB_NOTDIRTY;
197
- }
198
- }
199
#else
200
- /* paired with atomic_mb_set in tlb_set_page_with_attrs */
201
- uintptr_t orig_addr = atomic_mb_read(&tlb_entry->addr_write);
202
- uintptr_t addr = orig_addr;
203
-
204
- if ((addr & (TLB_INVALID_MASK | TLB_MMIO | TLB_NOTDIRTY)) == 0) {
205
- addr &= TARGET_PAGE_MASK;
206
- addr += atomic_read(&tlb_entry->addend);
207
- if ((addr - start) < length) {
208
- uintptr_t notdirty_addr = orig_addr | TLB_NOTDIRTY;
209
- atomic_cmpxchg(&tlb_entry->addr_write, orig_addr, notdirty_addr);
210
+ atomic_set(&tlb_entry->addr_write,
211
+ tlb_entry->addr_write | TLB_NOTDIRTY);
212
+#endif
213
}
214
}
215
-#endif
216
}
217
218
-/* For atomic correctness when running MTTCG we need to use the right
219
- * primitives when copying entries */
220
-static inline void copy_tlb_helper(CPUTLBEntry *d, CPUTLBEntry *s,
221
- bool atomic_set)
18
+/*
222
+/*
19
+ * Define MIPS target-specific operand constraints.
223
+ * Called with tlb_lock held.
20
+ * Copyright (c) 2021 Linaro
224
+ * Called only from the vCPU context, i.e. the TLB's owner thread.
21
+ */
225
+ */
22
+
226
+static inline void copy_tlb_helper_locked(CPUTLBEntry *d, const CPUTLBEntry *s)
23
+/*
227
{
24
+ * Define constraint letters for register sets:
228
-#if TCG_OVERSIZED_GUEST
25
+ * REGS(letter, register_mask)
229
*d = *s;
26
+ */
230
-#else
27
+REGS('r', ALL_GENERAL_REGS)
231
- if (atomic_set) {
28
+REGS('L', ALL_QLOAD_REGS)
232
- d->addr_read = s->addr_read;
29
+REGS('S', ALL_QSTORE_REGS)
233
- d->addr_code = s->addr_code;
30
+
234
- atomic_set(&d->addend, atomic_read(&s->addend));
31
+/*
235
- /* Pairs with flag setting in tlb_reset_dirty_range */
32
+ * Define constraint letters for constants:
236
- atomic_mb_set(&d->addr_write, atomic_read(&s->addr_write));
33
+ * CONST(letter, TCG_CT_CONST_* bit set)
237
- } else {
34
+ */
238
- d->addr_read = s->addr_read;
35
+CONST('I', TCG_CT_CONST_U16)
239
- d->addr_write = atomic_read(&s->addr_write);
36
+CONST('J', TCG_CT_CONST_S16)
240
- d->addr_code = s->addr_code;
37
+CONST('K', TCG_CT_CONST_P2M1)
241
- d->addend = atomic_read(&s->addend);
38
+CONST('N', TCG_CT_CONST_N16)
242
- }
39
+CONST('W', TCG_CT_CONST_WSZ)
40
+CONST('Z', TCG_CT_CONST_ZERO)
41
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
42
index XXXXXXX..XXXXXXX 100644
43
--- a/tcg/mips/tcg-target.h
44
+++ b/tcg/mips/tcg-target.h
45
@@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
46
#ifdef CONFIG_SOFTMMU
47
#define TCG_TARGET_NEED_LDST_LABELS
48
#endif
49
+#define TCG_TARGET_CON_STR_H
50
51
#endif
52
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
53
index XXXXXXX..XXXXXXX 100644
54
--- a/tcg/mips/tcg-target.c.inc
55
+++ b/tcg/mips/tcg-target.c.inc
56
@@ -XXX,XX +XXX,XX @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
57
#define TCG_CT_CONST_N16 0x1000 /* "Negatable" 16-bit: -32767 - 32767 */
58
#define TCG_CT_CONST_WSZ 0x2000 /* word size */
59
60
+#define ALL_GENERAL_REGS 0xffffffffu
61
+#define NOA0_REGS (ALL_GENERAL_REGS & ~(1 << TCG_REG_A0))
62
+
63
+#ifdef CONFIG_SOFTMMU
64
+#define ALL_QLOAD_REGS \
65
+ (NOA0_REGS & ~((TCG_TARGET_REG_BITS < TARGET_LONG_BITS) << TCG_REG_A2))
66
+#define ALL_QSTORE_REGS \
67
+ (NOA0_REGS & ~(TCG_TARGET_REG_BITS < TARGET_LONG_BITS \
68
+ ? (1 << TCG_REG_A2) | (1 << TCG_REG_A3) \
69
+ : (1 << TCG_REG_A1)))
70
+#else
71
+#define ALL_QLOAD_REGS NOA0_REGS
72
+#define ALL_QSTORE_REGS NOA0_REGS
73
+#endif
74
+
75
+
76
static inline bool is_p2m1(tcg_target_long val)
77
{
78
return val && ((val + 1) & val) == 0;
79
}
80
81
-/* parse target specific constraints */
82
-static const char *target_parse_constraint(TCGArgConstraint *ct,
83
- const char *ct_str, TCGType type)
84
-{
85
- switch(*ct_str++) {
86
- case 'r':
87
- ct->regs = 0xffffffff;
88
- break;
89
- case 'L': /* qemu_ld input arg constraint */
90
- ct->regs = 0xffffffff;
91
- tcg_regset_reset_reg(ct->regs, TCG_REG_A0);
92
-#if defined(CONFIG_SOFTMMU)
93
- if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
94
- tcg_regset_reset_reg(ct->regs, TCG_REG_A2);
95
- }
96
-#endif
243
-#endif
97
- break;
244
}
98
- case 'S': /* qemu_st constraint */
245
99
- ct->regs = 0xffffffff;
246
/* This is a cross vCPU call (i.e. another vCPU resetting the flags of
100
- tcg_regset_reset_reg(ct->regs, TCG_REG_A0);
247
- * the target vCPU). As such care needs to be taken that we don't
101
-#if defined(CONFIG_SOFTMMU)
248
- * dangerously race with another vCPU update. The only thing actually
102
- if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
249
- * updated is the target TLB entry ->addr_write flags.
103
- tcg_regset_reset_reg(ct->regs, TCG_REG_A2);
250
+ * the target vCPU).
104
- tcg_regset_reset_reg(ct->regs, TCG_REG_A3);
251
+ * We must take tlb_lock to avoid racing with another vCPU update. The only
105
- } else {
252
+ * thing actually updated is the target TLB entry ->addr_write flags.
106
- tcg_regset_reset_reg(ct->regs, TCG_REG_A1);
253
*/
107
- }
254
void tlb_reset_dirty(CPUState *cpu, ram_addr_t start1, ram_addr_t length)
108
-#endif
255
{
109
- break;
256
@@ -XXX,XX +XXX,XX @@ void tlb_reset_dirty(CPUState *cpu, ram_addr_t start1, ram_addr_t length)
110
- case 'I':
257
int mmu_idx;
111
- ct->ct |= TCG_CT_CONST_U16;
258
112
- break;
259
env = cpu->env_ptr;
113
- case 'J':
260
+ qemu_spin_lock(&env->tlb_lock);
114
- ct->ct |= TCG_CT_CONST_S16;
261
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
115
- break;
262
unsigned int i;
116
- case 'K':
263
117
- ct->ct |= TCG_CT_CONST_P2M1;
264
for (i = 0; i < CPU_TLB_SIZE; i++) {
118
- break;
265
- tlb_reset_dirty_range(&env->tlb_table[mmu_idx][i],
119
- case 'N':
266
- start1, length);
120
- ct->ct |= TCG_CT_CONST_N16;
267
+ tlb_reset_dirty_range_locked(&env->tlb_table[mmu_idx][i], start1,
121
- break;
268
+ length);
122
- case 'W':
269
}
123
- ct->ct |= TCG_CT_CONST_WSZ;
270
124
- break;
271
for (i = 0; i < CPU_VTLB_SIZE; i++) {
125
- case 'Z':
272
- tlb_reset_dirty_range(&env->tlb_v_table[mmu_idx][i],
126
- /* We are cheating a bit here, using the fact that the register
273
- start1, length);
127
- ZERO is also the register number 0. Hence there is no need
274
+ tlb_reset_dirty_range_locked(&env->tlb_v_table[mmu_idx][i], start1,
128
- to check for const_args in each instruction. */
275
+ length);
129
- ct->ct |= TCG_CT_CONST_ZERO;
276
}
130
- break;
277
}
131
- default:
278
+ qemu_spin_unlock(&env->tlb_lock);
132
- return NULL;
279
}
133
- }
280
134
- return ct_str;
281
-static inline void tlb_set_dirty1(CPUTLBEntry *tlb_entry, target_ulong vaddr)
135
-}
282
+/* Called with tlb_lock held */
283
+static inline void tlb_set_dirty1_locked(CPUTLBEntry *tlb_entry,
284
+ target_ulong vaddr)
285
{
286
if (tlb_entry->addr_write == (vaddr | TLB_NOTDIRTY)) {
287
tlb_entry->addr_write = vaddr;
288
@@ -XXX,XX +XXX,XX @@ void tlb_set_dirty(CPUState *cpu, target_ulong vaddr)
289
290
vaddr &= TARGET_PAGE_MASK;
291
i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
292
+ qemu_spin_lock(&env->tlb_lock);
293
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
294
- tlb_set_dirty1(&env->tlb_table[mmu_idx][i], vaddr);
295
+ tlb_set_dirty1_locked(&env->tlb_table[mmu_idx][i], vaddr);
296
}
297
298
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
299
int k;
300
for (k = 0; k < CPU_VTLB_SIZE; k++) {
301
- tlb_set_dirty1(&env->tlb_v_table[mmu_idx][k], vaddr);
302
+ tlb_set_dirty1_locked(&env->tlb_v_table[mmu_idx][k], vaddr);
303
}
304
}
305
+ qemu_spin_unlock(&env->tlb_lock);
306
}
307
308
/* Our TLB does not support large pages, so remember the area covered by
309
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
310
addend = (uintptr_t)memory_region_get_ram_ptr(section->mr) + xlat;
311
}
312
313
- /* Make sure there's no cached translation for the new page. */
314
- tlb_flush_vtlb_page(env, mmu_idx, vaddr_page);
136
-
315
-
137
/* test if a constant matches the constraint */
316
code_address = address;
138
static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
317
iotlb = memory_region_section_get_iotlb(cpu, section, vaddr_page,
139
const TCGArgConstraint *arg_ct)
318
paddr_page, xlat, prot, &address);
140
@@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
319
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
141
TCGArg a0, a1, a2;
320
index = (vaddr_page >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
142
int c2;
321
te = &env->tlb_table[mmu_idx][index];
143
322
144
+ /*
323
+ /*
145
+ * Note that many operands use the constraint set "rZ".
324
+ * Hold the TLB lock for the rest of the function. We could acquire/release
146
+ * We make use of the fact that 0 is the ZERO register,
325
+ * the lock several times in the function, but it is faster to amortize the
147
+ * and hence such cases need not check for const_args.
326
+ * acquisition cost by acquiring it just once. Note that this leads to
327
+ * a longer critical section, but this is not a concern since the TLB lock
328
+ * is unlikely to be contended.
148
+ */
329
+ */
149
a0 = args[0];
330
+ qemu_spin_lock(&env->tlb_lock);
150
a1 = args[1];
331
+
151
a2 = args[2];
332
+ /* Make sure there's no cached translation for the new page. */
333
+ tlb_flush_vtlb_page_locked(env, mmu_idx, vaddr_page);
334
+
335
/*
336
* Only evict the old entry to the victim tlb if it's for a
337
* different page; otherwise just overwrite the stale data.
338
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
339
CPUTLBEntry *tv = &env->tlb_v_table[mmu_idx][vidx];
340
341
/* Evict the old entry into the victim tlb. */
342
- copy_tlb_helper(tv, te, true);
343
+ copy_tlb_helper_locked(tv, te);
344
env->iotlb_v[mmu_idx][vidx] = env->iotlb[mmu_idx][index];
345
}
346
347
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
348
}
349
}
350
351
- /* Pairs with flag setting in tlb_reset_dirty_range */
352
- copy_tlb_helper(te, &tn, true);
353
- /* atomic_mb_set(&te->addr_write, write_address); */
354
+ copy_tlb_helper_locked(te, &tn);
355
+ qemu_spin_unlock(&env->tlb_lock);
356
}
357
358
/* Add a new TLB entry, but without specifying the memory
359
@@ -XXX,XX +XXX,XX @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
360
size_t elt_ofs, target_ulong page)
361
{
362
size_t vidx;
363
+
364
+ assert_cpu_is_self(ENV_GET_CPU(env));
365
for (vidx = 0; vidx < CPU_VTLB_SIZE; ++vidx) {
366
CPUTLBEntry *vtlb = &env->tlb_v_table[mmu_idx][vidx];
367
target_ulong cmp = *(target_ulong *)((uintptr_t)vtlb + elt_ofs);
368
@@ -XXX,XX +XXX,XX @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
369
/* Found entry in victim tlb, swap tlb and iotlb. */
370
CPUTLBEntry tmptlb, *tlb = &env->tlb_table[mmu_idx][index];
371
372
- copy_tlb_helper(&tmptlb, tlb, false);
373
- copy_tlb_helper(tlb, vtlb, true);
374
- copy_tlb_helper(vtlb, &tmptlb, true);
375
+ qemu_spin_lock(&env->tlb_lock);
376
+ copy_tlb_helper_locked(&tmptlb, tlb);
377
+ copy_tlb_helper_locked(tlb, vtlb);
378
+ copy_tlb_helper_locked(vtlb, &tmptlb);
379
+ qemu_spin_unlock(&env->tlb_lock);
380
381
CPUIOTLBEntry tmpio, *io = &env->iotlb[mmu_idx][index];
382
CPUIOTLBEntry *vio = &env->iotlb_v[mmu_idx][vidx];
152
--
383
--
153
2.25.1
384
2.17.2
154
385
155
386
diff view generated by jsdifflib
1
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Isolate the computation of an index from an address into a
2
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
2
helper before we change that function.
3
4
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
[ cota: convert tlb_vaddr_to_host; use atomic_read on addr_write ]
7
Signed-off-by: Emilio G. Cota <cota@braap.org>
8
Message-Id: <20181009175129.17888-2-cota@braap.org>
4
---
9
---
5
tcg/sparc/tcg-target-con-str.h | 23 ++++++++++
10
accel/tcg/softmmu_template.h | 64 +++++++++++++++++---------------
6
tcg/sparc/tcg-target.h | 5 +--
11
include/exec/cpu_ldst.h | 19 ++++++++--
7
tcg/sparc/tcg-target.c.inc | 81 +++++++++++++---------------------
12
include/exec/cpu_ldst_template.h | 25 +++++++------
8
3 files changed, 55 insertions(+), 54 deletions(-)
13
accel/tcg/cputlb.c | 60 ++++++++++++++----------------
9
create mode 100644 tcg/sparc/tcg-target-con-str.h
14
4 files changed, 90 insertions(+), 78 deletions(-)
10
15
11
diff --git a/tcg/sparc/tcg-target-con-str.h b/tcg/sparc/tcg-target-con-str.h
16
diff --git a/accel/tcg/softmmu_template.h b/accel/tcg/softmmu_template.h
12
new file mode 100644
17
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX
18
--- a/accel/tcg/softmmu_template.h
14
--- /dev/null
19
+++ b/accel/tcg/softmmu_template.h
15
+++ b/tcg/sparc/tcg-target-con-str.h
20
@@ -XXX,XX +XXX,XX @@ static inline DATA_TYPE glue(io_read, SUFFIX)(CPUArchState *env,
16
@@ -XXX,XX +XXX,XX @@
21
WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr,
17
+/* SPDX-License-Identifier: MIT */
22
TCGMemOpIdx oi, uintptr_t retaddr)
18
+/*
23
{
19
+ * Define Sparc target-specific operand constraints.
24
- unsigned mmu_idx = get_mmuidx(oi);
20
+ * Copyright (c) 2021 Linaro
25
- int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
21
+ */
26
- target_ulong tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
27
+ uintptr_t mmu_idx = get_mmuidx(oi);
28
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
29
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
30
+ target_ulong tlb_addr = entry->ADDR_READ;
31
unsigned a_bits = get_alignment_bits(get_memop(oi));
32
uintptr_t haddr;
33
DATA_TYPE res;
34
@@ -XXX,XX +XXX,XX @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr,
35
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, READ_ACCESS_TYPE,
36
mmu_idx, retaddr);
37
}
38
- tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
39
+ tlb_addr = entry->ADDR_READ;
40
}
41
42
/* Handle an IO access. */
43
@@ -XXX,XX +XXX,XX @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr,
44
return res;
45
}
46
47
- haddr = addr + env->tlb_table[mmu_idx][index].addend;
48
+ haddr = addr + entry->addend;
49
#if DATA_SIZE == 1
50
res = glue(glue(ld, LSUFFIX), _p)((uint8_t *)haddr);
51
#else
52
@@ -XXX,XX +XXX,XX @@ WORD_TYPE helper_le_ld_name(CPUArchState *env, target_ulong addr,
53
WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr,
54
TCGMemOpIdx oi, uintptr_t retaddr)
55
{
56
- unsigned mmu_idx = get_mmuidx(oi);
57
- int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
58
- target_ulong tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
59
+ uintptr_t mmu_idx = get_mmuidx(oi);
60
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
61
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
62
+ target_ulong tlb_addr = entry->ADDR_READ;
63
unsigned a_bits = get_alignment_bits(get_memop(oi));
64
uintptr_t haddr;
65
DATA_TYPE res;
66
@@ -XXX,XX +XXX,XX @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr,
67
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, READ_ACCESS_TYPE,
68
mmu_idx, retaddr);
69
}
70
- tlb_addr = env->tlb_table[mmu_idx][index].ADDR_READ;
71
+ tlb_addr = entry->ADDR_READ;
72
}
73
74
/* Handle an IO access. */
75
@@ -XXX,XX +XXX,XX @@ WORD_TYPE helper_be_ld_name(CPUArchState *env, target_ulong addr,
76
return res;
77
}
78
79
- haddr = addr + env->tlb_table[mmu_idx][index].addend;
80
+ haddr = addr + entry->addend;
81
res = glue(glue(ld, LSUFFIX), _be_p)((uint8_t *)haddr);
82
return res;
83
}
84
@@ -XXX,XX +XXX,XX @@ static inline void glue(io_write, SUFFIX)(CPUArchState *env,
85
void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
86
TCGMemOpIdx oi, uintptr_t retaddr)
87
{
88
- unsigned mmu_idx = get_mmuidx(oi);
89
- int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
90
- target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
91
+ uintptr_t mmu_idx = get_mmuidx(oi);
92
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
93
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
94
+ target_ulong tlb_addr = entry->addr_write;
95
unsigned a_bits = get_alignment_bits(get_memop(oi));
96
uintptr_t haddr;
97
98
@@ -XXX,XX +XXX,XX @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
99
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, MMU_DATA_STORE,
100
mmu_idx, retaddr);
101
}
102
- tlb_addr = env->tlb_table[mmu_idx][index].addr_write & ~TLB_INVALID_MASK;
103
+ tlb_addr = entry->addr_write & ~TLB_INVALID_MASK;
104
}
105
106
/* Handle an IO access. */
107
@@ -XXX,XX +XXX,XX @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
108
if (DATA_SIZE > 1
109
&& unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
110
>= TARGET_PAGE_SIZE)) {
111
- int i, index2;
112
- target_ulong page2, tlb_addr2;
113
+ int i;
114
+ target_ulong page2;
115
+ CPUTLBEntry *entry2;
116
do_unaligned_access:
117
/* Ensure the second page is in the TLB. Note that the first page
118
is already guaranteed to be filled, and that the second page
119
cannot evict the first. */
120
page2 = (addr + DATA_SIZE) & TARGET_PAGE_MASK;
121
- index2 = (page2 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
122
- tlb_addr2 = env->tlb_table[mmu_idx][index2].addr_write;
123
- if (!tlb_hit_page(tlb_addr2, page2)
124
+ entry2 = tlb_entry(env, mmu_idx, page2);
125
+ if (!tlb_hit_page(entry2->addr_write, page2)
126
&& !VICTIM_TLB_HIT(addr_write, page2)) {
127
tlb_fill(ENV_GET_CPU(env), page2, DATA_SIZE, MMU_DATA_STORE,
128
mmu_idx, retaddr);
129
@@ -XXX,XX +XXX,XX @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
130
return;
131
}
132
133
- haddr = addr + env->tlb_table[mmu_idx][index].addend;
134
+ haddr = addr + entry->addend;
135
#if DATA_SIZE == 1
136
glue(glue(st, SUFFIX), _p)((uint8_t *)haddr, val);
137
#else
138
@@ -XXX,XX +XXX,XX @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
139
void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
140
TCGMemOpIdx oi, uintptr_t retaddr)
141
{
142
- unsigned mmu_idx = get_mmuidx(oi);
143
- int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
144
- target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
145
+ uintptr_t mmu_idx = get_mmuidx(oi);
146
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
147
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
148
+ target_ulong tlb_addr = entry->addr_write;
149
unsigned a_bits = get_alignment_bits(get_memop(oi));
150
uintptr_t haddr;
151
152
@@ -XXX,XX +XXX,XX @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
153
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, MMU_DATA_STORE,
154
mmu_idx, retaddr);
155
}
156
- tlb_addr = env->tlb_table[mmu_idx][index].addr_write & ~TLB_INVALID_MASK;
157
+ tlb_addr = entry->addr_write & ~TLB_INVALID_MASK;
158
}
159
160
/* Handle an IO access. */
161
@@ -XXX,XX +XXX,XX @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
162
if (DATA_SIZE > 1
163
&& unlikely((addr & ~TARGET_PAGE_MASK) + DATA_SIZE - 1
164
>= TARGET_PAGE_SIZE)) {
165
- int i, index2;
166
- target_ulong page2, tlb_addr2;
167
+ int i;
168
+ target_ulong page2;
169
+ CPUTLBEntry *entry2;
170
do_unaligned_access:
171
/* Ensure the second page is in the TLB. Note that the first page
172
is already guaranteed to be filled, and that the second page
173
cannot evict the first. */
174
page2 = (addr + DATA_SIZE) & TARGET_PAGE_MASK;
175
- index2 = (page2 >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
176
- tlb_addr2 = env->tlb_table[mmu_idx][index2].addr_write;
177
- if (!tlb_hit_page(tlb_addr2, page2)
178
+ entry2 = tlb_entry(env, mmu_idx, page2);
179
+ if (!tlb_hit_page(entry2->addr_write, page2)
180
&& !VICTIM_TLB_HIT(addr_write, page2)) {
181
tlb_fill(ENV_GET_CPU(env), page2, DATA_SIZE, MMU_DATA_STORE,
182
mmu_idx, retaddr);
183
@@ -XXX,XX +XXX,XX @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
184
return;
185
}
186
187
- haddr = addr + env->tlb_table[mmu_idx][index].addend;
188
+ haddr = addr + entry->addend;
189
glue(glue(st, SUFFIX), _be_p)((uint8_t *)haddr, val);
190
}
191
#endif /* DATA_SIZE > 1 */
192
diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
193
index XXXXXXX..XXXXXXX 100644
194
--- a/include/exec/cpu_ldst.h
195
+++ b/include/exec/cpu_ldst.h
196
@@ -XXX,XX +XXX,XX @@ extern __thread uintptr_t helper_retaddr;
197
/* The memory helpers for tcg-generated code need tcg_target_long etc. */
198
#include "tcg.h"
199
200
+/* Find the TLB index corresponding to the mmu_idx + address pair. */
201
+static inline uintptr_t tlb_index(CPUArchState *env, uintptr_t mmu_idx,
202
+ target_ulong addr)
203
+{
204
+ return (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
205
+}
22
+
206
+
23
+/*
207
+/* Find the TLB entry corresponding to the mmu_idx + address pair. */
24
+ * Define constraint letters for register sets:
208
+static inline CPUTLBEntry *tlb_entry(CPUArchState *env, uintptr_t mmu_idx,
25
+ * REGS(letter, register_mask)
209
+ target_ulong addr)
26
+ */
210
+{
27
+REGS('r', ALL_GENERAL_REGS)
211
+ return &env->tlb_table[mmu_idx][tlb_index(env, mmu_idx, addr)];
28
+REGS('R', ALL_GENERAL_REGS64)
212
+}
29
+REGS('s', ALL_QLDST_REGS)
30
+REGS('S', ALL_QLDST_REGS64)
31
+REGS('A', TARGET_LONG_BITS == 64 ? ALL_QLDST_REGS64 : ALL_QLDST_REGS)
32
+
213
+
33
+/*
214
#ifdef MMU_MODE0_SUFFIX
34
+ * Define constraint letters for constants:
215
#define CPU_MMU_INDEX 0
35
+ * CONST(letter, TCG_CT_CONST_* bit set)
216
#define MEMSUFFIX MMU_MODE0_SUFFIX
36
+ */
217
@@ -XXX,XX +XXX,XX @@ static inline void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
37
+CONST('I', TCG_CT_CONST_S11)
218
#if defined(CONFIG_USER_ONLY)
38
+CONST('J', TCG_CT_CONST_S13)
219
return g2h(addr);
39
+CONST('Z', TCG_CT_CONST_ZERO)
220
#else
40
diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
221
- int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
222
- CPUTLBEntry *tlbentry = &env->tlb_table[mmu_idx][index];
223
+ CPUTLBEntry *tlbentry = tlb_entry(env, mmu_idx, addr);
224
abi_ptr tlb_addr;
225
uintptr_t haddr;
226
227
@@ -XXX,XX +XXX,XX @@ static inline void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
228
return NULL;
229
}
230
231
- haddr = addr + env->tlb_table[mmu_idx][index].addend;
232
+ haddr = addr + tlbentry->addend;
233
return (void *)haddr;
234
#endif /* defined(CONFIG_USER_ONLY) */
235
}
236
diff --git a/include/exec/cpu_ldst_template.h b/include/exec/cpu_ldst_template.h
41
index XXXXXXX..XXXXXXX 100644
237
index XXXXXXX..XXXXXXX 100644
42
--- a/tcg/sparc/tcg-target.h
238
--- a/include/exec/cpu_ldst_template.h
43
+++ b/tcg/sparc/tcg-target.h
239
+++ b/include/exec/cpu_ldst_template.h
44
@@ -XXX,XX +XXX,XX @@ typedef enum {
240
@@ -XXX,XX +XXX,XX @@ glue(glue(glue(cpu_ld, USUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
45
TCG_REG_I7,
241
target_ulong ptr,
46
} TCGReg;
242
uintptr_t retaddr)
47
243
{
48
-#define TCG_CT_CONST_S11 0x100
244
- int page_index;
49
-#define TCG_CT_CONST_S13 0x200
245
+ CPUTLBEntry *entry;
50
-#define TCG_CT_CONST_ZERO 0x400
246
RES_TYPE res;
51
-
247
target_ulong addr;
52
/* used for function call generation */
248
int mmu_idx;
53
#define TCG_REG_CALL_STACK TCG_REG_O6
249
@@ -XXX,XX +XXX,XX @@ glue(glue(glue(cpu_ld, USUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
54
55
@@ -XXX,XX +XXX,XX @@ extern bool use_vis3_instructions;
56
void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
57
58
#define TCG_TARGET_NEED_POOL_LABELS
59
+#define TCG_TARGET_CON_STR_H
60
61
#endif
250
#endif
62
diff --git a/tcg/sparc/tcg-target.c.inc b/tcg/sparc/tcg-target.c.inc
251
252
addr = ptr;
253
- page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
254
mmu_idx = CPU_MMU_INDEX;
255
- if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
256
+ entry = tlb_entry(env, mmu_idx, addr);
257
+ if (unlikely(entry->ADDR_READ !=
258
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
259
oi = make_memop_idx(SHIFT, mmu_idx);
260
res = glue(glue(helper_ret_ld, URETSUFFIX), MMUSUFFIX)(env, addr,
261
oi, retaddr);
262
} else {
263
- uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
264
+ uintptr_t hostaddr = addr + entry->addend;
265
res = glue(glue(ld, USUFFIX), _p)((uint8_t *)hostaddr);
266
}
267
return res;
268
@@ -XXX,XX +XXX,XX @@ glue(glue(glue(cpu_lds, SUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
269
target_ulong ptr,
270
uintptr_t retaddr)
271
{
272
- int res, page_index;
273
+ CPUTLBEntry *entry;
274
+ int res;
275
target_ulong addr;
276
int mmu_idx;
277
TCGMemOpIdx oi;
278
@@ -XXX,XX +XXX,XX @@ glue(glue(glue(cpu_lds, SUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
279
#endif
280
281
addr = ptr;
282
- page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
283
mmu_idx = CPU_MMU_INDEX;
284
- if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
285
+ entry = tlb_entry(env, mmu_idx, addr);
286
+ if (unlikely(entry->ADDR_READ !=
287
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
288
oi = make_memop_idx(SHIFT, mmu_idx);
289
res = (DATA_STYPE)glue(glue(helper_ret_ld, SRETSUFFIX),
290
MMUSUFFIX)(env, addr, oi, retaddr);
291
} else {
292
- uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
293
+ uintptr_t hostaddr = addr + entry->addend;
294
res = glue(glue(lds, SUFFIX), _p)((uint8_t *)hostaddr);
295
}
296
return res;
297
@@ -XXX,XX +XXX,XX @@ glue(glue(glue(cpu_st, SUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
298
target_ulong ptr,
299
RES_TYPE v, uintptr_t retaddr)
300
{
301
- int page_index;
302
+ CPUTLBEntry *entry;
303
target_ulong addr;
304
int mmu_idx;
305
TCGMemOpIdx oi;
306
@@ -XXX,XX +XXX,XX @@ glue(glue(glue(cpu_st, SUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
307
#endif
308
309
addr = ptr;
310
- page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
311
mmu_idx = CPU_MMU_INDEX;
312
- if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write !=
313
+ entry = tlb_entry(env, mmu_idx, addr);
314
+ if (unlikely(entry->addr_write !=
315
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
316
oi = make_memop_idx(SHIFT, mmu_idx);
317
glue(glue(helper_ret_st, SUFFIX), MMUSUFFIX)(env, addr, v, oi,
318
retaddr);
319
} else {
320
- uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
321
+ uintptr_t hostaddr = addr + entry->addend;
322
glue(glue(st, SUFFIX), _p)((uint8_t *)hostaddr, v);
323
}
324
}
325
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
63
index XXXXXXX..XXXXXXX 100644
326
index XXXXXXX..XXXXXXX 100644
64
--- a/tcg/sparc/tcg-target.c.inc
327
--- a/accel/tcg/cputlb.c
65
+++ b/tcg/sparc/tcg-target.c.inc
328
+++ b/accel/tcg/cputlb.c
66
@@ -XXX,XX +XXX,XX @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
329
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_page_async_work(CPUState *cpu, run_on_cpu_data data)
67
# define SPARC64 0
330
{
68
#endif
331
CPUArchState *env = cpu->env_ptr;
69
332
target_ulong addr = (target_ulong) data.target_ptr;
70
-/* Note that sparcv8plus can only hold 64 bit quantities in %g and %o
333
- int i;
71
- registers. These are saved manually by the kernel in full 64-bit
334
int mmu_idx;
72
- slots. The %i and %l registers are saved by the register window
335
73
- mechanism, which only allocates space for 32 bits. Given that this
336
assert_cpu_is_self(cpu);
74
- window spill/fill can happen on any signal, we must consider the
337
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_page_async_work(CPUState *cpu, run_on_cpu_data data)
75
- high bits of the %i and %l registers garbage at all times. */
338
}
76
-#if SPARC64
339
77
-# define ALL_64 0xffffffffu
340
addr &= TARGET_PAGE_MASK;
78
+#define TCG_CT_CONST_S11 0x100
341
- i = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
79
+#define TCG_CT_CONST_S13 0x200
342
qemu_spin_lock(&env->tlb_lock);
80
+#define TCG_CT_CONST_ZERO 0x400
343
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
81
+
344
- tlb_flush_entry_locked(&env->tlb_table[mmu_idx][i], addr);
82
+/*
345
+ tlb_flush_entry_locked(tlb_entry(env, mmu_idx, addr), addr);
83
+ * For softmmu, we need to avoid conflicts with the first 3
346
tlb_flush_vtlb_page_locked(env, mmu_idx, addr);
84
+ * argument registers to perform the tlb lookup, and to call
347
}
85
+ * the helper function.
348
qemu_spin_unlock(&env->tlb_lock);
86
+ */
349
@@ -XXX,XX +XXX,XX @@ static void tlb_flush_page_by_mmuidx_async_work(CPUState *cpu,
87
+#ifdef CONFIG_SOFTMMU
350
target_ulong addr_and_mmuidx = (target_ulong) data.target_ptr;
88
+#define SOFTMMU_RESERVE_REGS MAKE_64BIT_MASK(TCG_REG_O0, 3)
351
target_ulong addr = addr_and_mmuidx & TARGET_PAGE_MASK;
89
#else
352
unsigned long mmu_idx_bitmap = addr_and_mmuidx & ALL_MMUIDX_BITS;
90
-# define ALL_64 0xffffu
353
- int page = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
91
+#define SOFTMMU_RESERVE_REGS 0
354
int mmu_idx;
92
#endif
355
93
356
assert_cpu_is_self(cpu);
94
+/*
357
95
+ * Note that sparcv8plus can only hold 64 bit quantities in %g and %o
358
- tlb_debug("page:%d addr:"TARGET_FMT_lx" mmu_idx:0x%lx\n",
96
+ * registers. These are saved manually by the kernel in full 64-bit
359
- page, addr, mmu_idx_bitmap);
97
+ * slots. The %i and %l registers are saved by the register window
360
+ tlb_debug("flush page addr:"TARGET_FMT_lx" mmu_idx:0x%lx\n",
98
+ * mechanism, which only allocates space for 32 bits. Given that this
361
+ addr, mmu_idx_bitmap);
99
+ * window spill/fill can happen on any signal, we must consider the
362
100
+ * high bits of the %i and %l registers garbage at all times.
363
qemu_spin_lock(&env->tlb_lock);
101
+ */
364
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
102
+#define ALL_GENERAL_REGS MAKE_64BIT_MASK(0, 32)
365
if (test_bit(mmu_idx, &mmu_idx_bitmap)) {
103
+#if SPARC64
366
- tlb_flush_entry_locked(&env->tlb_table[mmu_idx][page], addr);
104
+# define ALL_GENERAL_REGS64 ALL_GENERAL_REGS
367
+ tlb_flush_entry_locked(tlb_entry(env, mmu_idx, addr), addr);
105
+#else
368
tlb_flush_vtlb_page_locked(env, mmu_idx, addr);
106
+# define ALL_GENERAL_REGS64 MAKE_64BIT_MASK(0, 16)
369
}
107
+#endif
370
}
108
+#define ALL_QLDST_REGS (ALL_GENERAL_REGS & ~SOFTMMU_RESERVE_REGS)
371
@@ -XXX,XX +XXX,XX @@ static inline void tlb_set_dirty1_locked(CPUTLBEntry *tlb_entry,
109
+#define ALL_QLDST_REGS64 (ALL_GENERAL_REGS64 & ~SOFTMMU_RESERVE_REGS)
372
void tlb_set_dirty(CPUState *cpu, target_ulong vaddr)
110
+
373
{
111
/* Define some temporary registers. T2 is used for constant generation. */
374
CPUArchState *env = cpu->env_ptr;
112
#define TCG_REG_T1 TCG_REG_G1
375
- int i;
113
#define TCG_REG_T2 TCG_REG_O7
376
int mmu_idx;
114
@@ -XXX,XX +XXX,XX @@ static bool patch_reloc(tcg_insn_unit *src_rw, int type,
377
115
return true;
378
assert_cpu_is_self(cpu);
379
380
vaddr &= TARGET_PAGE_MASK;
381
- i = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
382
qemu_spin_lock(&env->tlb_lock);
383
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
384
- tlb_set_dirty1_locked(&env->tlb_table[mmu_idx][i], vaddr);
385
+ tlb_set_dirty1_locked(tlb_entry(env, mmu_idx, vaddr), vaddr);
386
}
387
388
for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
389
@@ -XXX,XX +XXX,XX @@ void tlb_set_page_with_attrs(CPUState *cpu, target_ulong vaddr,
390
iotlb = memory_region_section_get_iotlb(cpu, section, vaddr_page,
391
paddr_page, xlat, prot, &address);
392
393
- index = (vaddr_page >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
394
- te = &env->tlb_table[mmu_idx][index];
395
+ index = tlb_index(env, mmu_idx, vaddr_page);
396
+ te = tlb_entry(env, mmu_idx, vaddr_page);
397
398
/*
399
* Hold the TLB lock for the rest of the function. We could acquire/release
400
@@ -XXX,XX +XXX,XX @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
401
* repeat the MMU check here. This tlb_fill() call might
402
* longjump out if this access should cause a guest exception.
403
*/
404
- int index;
405
+ CPUTLBEntry *entry;
406
target_ulong tlb_addr;
407
408
tlb_fill(cpu, addr, size, MMU_DATA_LOAD, mmu_idx, retaddr);
409
410
- index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
411
- tlb_addr = env->tlb_table[mmu_idx][index].addr_read;
412
+ entry = tlb_entry(env, mmu_idx, addr);
413
+ tlb_addr = entry->addr_read;
414
if (!(tlb_addr & ~(TARGET_PAGE_MASK | TLB_RECHECK))) {
415
/* RAM access */
416
- uintptr_t haddr = addr + env->tlb_table[mmu_idx][index].addend;
417
+ uintptr_t haddr = addr + entry->addend;
418
419
return ldn_p((void *)haddr, size);
420
}
421
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
422
* repeat the MMU check here. This tlb_fill() call might
423
* longjump out if this access should cause a guest exception.
424
*/
425
- int index;
426
+ CPUTLBEntry *entry;
427
target_ulong tlb_addr;
428
429
tlb_fill(cpu, addr, size, MMU_DATA_STORE, mmu_idx, retaddr);
430
431
- index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
432
- tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
433
+ entry = tlb_entry(env, mmu_idx, addr);
434
+ tlb_addr = entry->addr_write;
435
if (!(tlb_addr & ~(TARGET_PAGE_MASK | TLB_RECHECK))) {
436
/* RAM access */
437
- uintptr_t haddr = addr + env->tlb_table[mmu_idx][index].addend;
438
+ uintptr_t haddr = addr + entry->addend;
439
440
stn_p((void *)haddr, size, val);
441
return;
442
@@ -XXX,XX +XXX,XX @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
443
*/
444
tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
445
{
446
- int mmu_idx, index;
447
+ uintptr_t mmu_idx = cpu_mmu_index(env, true);
448
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
449
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
450
void *p;
451
452
- index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
453
- mmu_idx = cpu_mmu_index(env, true);
454
- if (unlikely(!tlb_hit(env->tlb_table[mmu_idx][index].addr_code, addr))) {
455
+ if (unlikely(!tlb_hit(entry->addr_code, addr))) {
456
if (!VICTIM_TLB_HIT(addr_code, addr)) {
457
tlb_fill(ENV_GET_CPU(env), addr, 0, MMU_INST_FETCH, mmu_idx, 0);
458
}
459
- assert(tlb_hit(env->tlb_table[mmu_idx][index].addr_code, addr));
460
+ assert(tlb_hit(entry->addr_code, addr));
461
}
462
463
- if (unlikely(env->tlb_table[mmu_idx][index].addr_code &
464
- (TLB_RECHECK | TLB_MMIO))) {
465
+ if (unlikely(entry->addr_code & (TLB_RECHECK | TLB_MMIO))) {
466
/*
467
* Return -1 if we can't translate and execute from an entire
468
* page of RAM here, which will cause us to execute by loading
469
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
470
return -1;
471
}
472
473
- p = (void *)((uintptr_t)addr + env->tlb_table[mmu_idx][index].addend);
474
+ p = (void *)((uintptr_t)addr + entry->addend);
475
return qemu_ram_addr_from_host_nofail(p);
116
}
476
}
117
477
118
-/* parse target specific constraints */
478
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
119
-static const char *target_parse_constraint(TCGArgConstraint *ct,
479
void probe_write(CPUArchState *env, target_ulong addr, int size, int mmu_idx,
120
- const char *ct_str, TCGType type)
480
uintptr_t retaddr)
121
-{
481
{
122
- switch (*ct_str++) {
482
- int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
123
- case 'r':
483
- target_ulong tlb_addr = env->tlb_table[mmu_idx][index].addr_write;
124
- ct->regs = 0xffffffff;
484
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
125
- break;
485
+ CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
126
- case 'R':
486
127
- ct->regs = ALL_64;
487
- if (!tlb_hit(tlb_addr, addr)) {
128
- break;
488
+ if (!tlb_hit(entry->addr_write, addr)) {
129
- case 'A': /* qemu_ld/st address constraint */
489
/* TLB entry is for a different page */
130
- ct->regs = TARGET_LONG_BITS == 64 ? ALL_64 : 0xffffffff;
490
if (!VICTIM_TLB_HIT(addr_write, addr)) {
131
- reserve_helpers:
491
tlb_fill(ENV_GET_CPU(env), addr, size, MMU_DATA_STORE,
132
- tcg_regset_reset_reg(ct->regs, TCG_REG_O0);
492
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
133
- tcg_regset_reset_reg(ct->regs, TCG_REG_O1);
493
NotDirtyInfo *ndi)
134
- tcg_regset_reset_reg(ct->regs, TCG_REG_O2);
494
{
135
- break;
495
size_t mmu_idx = get_mmuidx(oi);
136
- case 's': /* qemu_st data 32-bit constraint */
496
- size_t index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
137
- ct->regs = 0xffffffff;
497
- CPUTLBEntry *tlbe = &env->tlb_table[mmu_idx][index];
138
- goto reserve_helpers;
498
+ uintptr_t index = tlb_index(env, mmu_idx, addr);
139
- case 'S': /* qemu_st data 64-bit constraint */
499
+ CPUTLBEntry *tlbe = tlb_entry(env, mmu_idx, addr);
140
- ct->regs = ALL_64;
500
target_ulong tlb_addr = tlbe->addr_write;
141
- goto reserve_helpers;
501
TCGMemOp mop = get_memop(oi);
142
- case 'I':
502
int a_bits = get_alignment_bits(mop);
143
- ct->ct |= TCG_CT_CONST_S11;
144
- break;
145
- case 'J':
146
- ct->ct |= TCG_CT_CONST_S13;
147
- break;
148
- case 'Z':
149
- ct->ct |= TCG_CT_CONST_ZERO;
150
- break;
151
- default:
152
- return NULL;
153
- }
154
- return ct_str;
155
-}
156
-
157
/* test if a constant matches the constraint */
158
static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
159
const TCGArgConstraint *arg_ct)
160
@@ -XXX,XX +XXX,XX @@ static void tcg_target_init(TCGContext *s)
161
}
162
#endif
163
164
- tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff;
165
- tcg_target_available_regs[TCG_TYPE_I64] = ALL_64;
166
+ tcg_target_available_regs[TCG_TYPE_I32] = ALL_GENERAL_REGS;
167
+ tcg_target_available_regs[TCG_TYPE_I64] = ALL_GENERAL_REGS64;
168
169
tcg_target_call_clobber_regs = 0;
170
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_G1);
171
--
503
--
172
2.25.1
504
2.17.2
173
505
174
506
diff view generated by jsdifflib
1
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
1
GCC7+ will no longer advertise support for 16-byte __atomic operations
2
if only cmpxchg is supported, as for x86_64. Fortunately, x86_64 still
3
has support for __sync_compare_and_swap_16 and we can make use of that.
4
AArch64 does not have, nor ever has had such support, so open-code it.
5
6
Reviewed-by: Emilio G. Cota <cota@braap.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
8
---
4
tcg/s390/tcg-target-con-str.h | 28 ++++++++++++++++++
9
accel/tcg/atomic_template.h | 20 ++++-
5
tcg/s390/tcg-target.h | 1 +
10
include/qemu/atomic128.h | 153 ++++++++++++++++++++++++++++++++++++
6
tcg/s390/tcg-target.c.inc | 53 +++++++++--------------------------
11
include/qemu/compiler.h | 11 +++
7
3 files changed, 42 insertions(+), 40 deletions(-)
12
tcg/tcg.h | 16 ++--
8
create mode 100644 tcg/s390/tcg-target-con-str.h
13
accel/tcg/cputlb.c | 3 +-
14
accel/tcg/user-exec.c | 5 +-
15
configure | 19 +++++
16
7 files changed, 213 insertions(+), 14 deletions(-)
17
create mode 100644 include/qemu/atomic128.h
9
18
10
diff --git a/tcg/s390/tcg-target-con-str.h b/tcg/s390/tcg-target-con-str.h
19
diff --git a/accel/tcg/atomic_template.h b/accel/tcg/atomic_template.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/accel/tcg/atomic_template.h
22
+++ b/accel/tcg/atomic_template.h
23
@@ -XXX,XX +XXX,XX @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
24
DATA_TYPE ret;
25
26
ATOMIC_TRACE_RMW;
27
+#if DATA_SIZE == 16
28
+ ret = atomic16_cmpxchg(haddr, cmpv, newv);
29
+#else
30
ret = atomic_cmpxchg__nocheck(haddr, cmpv, newv);
31
+#endif
32
ATOMIC_MMU_CLEANUP;
33
return ret;
34
}
35
36
#if DATA_SIZE >= 16
37
+#if HAVE_ATOMIC128
38
ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr EXTRA_ARGS)
39
{
40
ATOMIC_MMU_DECLS;
41
DATA_TYPE val, *haddr = ATOMIC_MMU_LOOKUP;
42
43
ATOMIC_TRACE_LD;
44
- __atomic_load(haddr, &val, __ATOMIC_RELAXED);
45
+ val = atomic16_read(haddr);
46
ATOMIC_MMU_CLEANUP;
47
return val;
48
}
49
@@ -XXX,XX +XXX,XX @@ void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr,
50
DATA_TYPE *haddr = ATOMIC_MMU_LOOKUP;
51
52
ATOMIC_TRACE_ST;
53
- __atomic_store(haddr, &val, __ATOMIC_RELAXED);
54
+ atomic16_set(haddr, val);
55
ATOMIC_MMU_CLEANUP;
56
}
57
+#endif
58
#else
59
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr,
60
ABI_TYPE val EXTRA_ARGS)
61
@@ -XXX,XX +XXX,XX @@ ABI_TYPE ATOMIC_NAME(cmpxchg)(CPUArchState *env, target_ulong addr,
62
DATA_TYPE ret;
63
64
ATOMIC_TRACE_RMW;
65
+#if DATA_SIZE == 16
66
+ ret = atomic16_cmpxchg(haddr, BSWAP(cmpv), BSWAP(newv));
67
+#else
68
ret = atomic_cmpxchg__nocheck(haddr, BSWAP(cmpv), BSWAP(newv));
69
+#endif
70
ATOMIC_MMU_CLEANUP;
71
return BSWAP(ret);
72
}
73
74
#if DATA_SIZE >= 16
75
+#if HAVE_ATOMIC128
76
ABI_TYPE ATOMIC_NAME(ld)(CPUArchState *env, target_ulong addr EXTRA_ARGS)
77
{
78
ATOMIC_MMU_DECLS;
79
DATA_TYPE val, *haddr = ATOMIC_MMU_LOOKUP;
80
81
ATOMIC_TRACE_LD;
82
- __atomic_load(haddr, &val, __ATOMIC_RELAXED);
83
+ val = atomic16_read(haddr);
84
ATOMIC_MMU_CLEANUP;
85
return BSWAP(val);
86
}
87
@@ -XXX,XX +XXX,XX @@ void ATOMIC_NAME(st)(CPUArchState *env, target_ulong addr,
88
89
ATOMIC_TRACE_ST;
90
val = BSWAP(val);
91
- __atomic_store(haddr, &val, __ATOMIC_RELAXED);
92
+ atomic16_set(haddr, val);
93
ATOMIC_MMU_CLEANUP;
94
}
95
+#endif
96
#else
97
ABI_TYPE ATOMIC_NAME(xchg)(CPUArchState *env, target_ulong addr,
98
ABI_TYPE val EXTRA_ARGS)
99
diff --git a/include/qemu/atomic128.h b/include/qemu/atomic128.h
11
new file mode 100644
100
new file mode 100644
12
index XXXXXXX..XXXXXXX
101
index XXXXXXX..XXXXXXX
13
--- /dev/null
102
--- /dev/null
14
+++ b/tcg/s390/tcg-target-con-str.h
103
+++ b/include/qemu/atomic128.h
15
@@ -XXX,XX +XXX,XX @@
104
@@ -XXX,XX +XXX,XX @@
16
+/* SPDX-License-Identifier: MIT */
17
+/*
105
+/*
18
+ * Define S390 target-specific operand constraints.
106
+ * Simple interface for 128-bit atomic operations.
19
+ * Copyright (c) 2021 Linaro
107
+ *
108
+ * Copyright (C) 2018 Linaro, Ltd.
109
+ *
110
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
111
+ * See the COPYING file in the top-level directory.
112
+ *
113
+ * See docs/devel/atomics.txt for discussion about the guarantees each
114
+ * atomic primitive is meant to provide.
20
+ */
115
+ */
21
+
116
+
117
+#ifndef QEMU_ATOMIC128_H
118
+#define QEMU_ATOMIC128_H
119
+
22
+/*
120
+/*
23
+ * Define constraint letters for register sets:
121
+ * GCC is a house divided about supporting large atomic operations.
24
+ * REGS(letter, register_mask)
122
+ *
123
+ * For hosts that only have large compare-and-swap, a legalistic reading
124
+ * of the C++ standard means that one cannot implement __atomic_read on
125
+ * read-only memory, and thus all atomic operations must synchronize
126
+ * through libatomic.
127
+ *
128
+ * See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80878
129
+ *
130
+ * This interpretation is not especially helpful for QEMU.
131
+ * For softmmu, all RAM is always read/write from the hypervisor.
132
+ * For user-only, if the guest doesn't implement such an __atomic_read
133
+ * then the host need not worry about it either.
134
+ *
135
+ * Moreover, using libatomic is not an option, because its interface is
136
+ * built for std::atomic<T>, and requires that *all* accesses to such an
137
+ * object go through the library. In our case we do not have an object
138
+ * in the C/C++ sense, but a view of memory as seen by the guest.
139
+ * The guest may issue a large atomic operation and then access those
140
+ * pieces using word-sized accesses. From the hypervisor, we have no
141
+ * way to connect those two actions.
142
+ *
143
+ * Therefore, special case each platform.
25
+ */
144
+ */
26
+REGS('r', ALL_GENERAL_REGS)
145
+
27
+REGS('L', ALL_GENERAL_REGS & ~SOFTMMU_RESERVE_REGS)
146
+#if defined(CONFIG_ATOMIC128)
147
+static inline Int128 atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
148
+{
149
+ return atomic_cmpxchg__nocheck(ptr, cmp, new);
150
+}
151
+# define HAVE_CMPXCHG128 1
152
+#elif defined(CONFIG_CMPXCHG128)
153
+static inline Int128 atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
154
+{
155
+ return __sync_val_compare_and_swap_16(ptr, cmp, new);
156
+}
157
+# define HAVE_CMPXCHG128 1
158
+#elif defined(__aarch64__)
159
+/* Through gcc 8, aarch64 has no support for 128-bit at all. */
160
+static inline Int128 atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new)
161
+{
162
+ uint64_t cmpl = int128_getlo(cmp), cmph = int128_gethi(cmp);
163
+ uint64_t newl = int128_getlo(new), newh = int128_gethi(new);
164
+ uint64_t oldl, oldh;
165
+ uint32_t tmp;
166
+
167
+ asm("0: ldaxp %[oldl], %[oldh], %[mem]\n\t"
168
+ "cmp %[oldl], %[cmpl]\n\t"
169
+ "ccmp %[oldh], %[cmph], #0, eq\n\t"
170
+ "b.ne 1f\n\t"
171
+ "stlxp %w[tmp], %[newl], %[newh], %[mem]\n\t"
172
+ "cbnz %w[tmp], 0b\n"
173
+ "1:"
174
+ : [mem] "+m"(*ptr), [tmp] "=&r"(tmp),
175
+ [oldl] "=&r"(oldl), [oldh] "=r"(oldh)
176
+ : [cmpl] "r"(cmpl), [cmph] "r"(cmph),
177
+ [newl] "r"(newl), [newh] "r"(newh)
178
+ : "memory", "cc");
179
+
180
+ return int128_make128(oldl, oldh);
181
+}
182
+# define HAVE_CMPXCHG128 1
183
+#else
184
+/* Fallback definition that must be optimized away, or error. */
185
+Int128 QEMU_ERROR("unsupported atomic")
186
+ atomic16_cmpxchg(Int128 *ptr, Int128 cmp, Int128 new);
187
+# define HAVE_CMPXCHG128 0
188
+#endif /* Some definition for HAVE_CMPXCHG128 */
189
+
190
+
191
+#if defined(CONFIG_ATOMIC128)
192
+static inline Int128 atomic16_read(Int128 *ptr)
193
+{
194
+ return atomic_read__nocheck(ptr);
195
+}
196
+
197
+static inline void atomic16_set(Int128 *ptr, Int128 val)
198
+{
199
+ atomic_set__nocheck(ptr, val);
200
+}
201
+
202
+# define HAVE_ATOMIC128 1
203
+#elif !defined(CONFIG_USER_ONLY) && defined(__aarch64__)
204
+/* We can do better than cmpxchg for AArch64. */
205
+static inline Int128 atomic16_read(Int128 *ptr)
206
+{
207
+ uint64_t l, h;
208
+ uint32_t tmp;
209
+
210
+ /* The load must be paired with the store to guarantee not tearing. */
211
+ asm("0: ldxp %[l], %[h], %[mem]\n\t"
212
+ "stxp %w[tmp], %[l], %[h], %[mem]\n\t"
213
+ "cbnz %w[tmp], 0b"
214
+ : [mem] "+m"(*ptr), [tmp] "=r"(tmp), [l] "=r"(l), [h] "=r"(h));
215
+
216
+ return int128_make128(l, h);
217
+}
218
+
219
+static inline void atomic16_set(Int128 *ptr, Int128 val)
220
+{
221
+ uint64_t l = int128_getlo(val), h = int128_gethi(val);
222
+ uint64_t t1, t2;
223
+
224
+ /* Load into temporaries to acquire the exclusive access lock. */
225
+ asm("0: ldxp %[t1], %[t2], %[mem]\n\t"
226
+ "stxp %w[t1], %[l], %[h], %[mem]\n\t"
227
+ "cbnz %w[t1], 0b"
228
+ : [mem] "+m"(*ptr), [t1] "=&r"(t1), [t2] "=&r"(t2)
229
+ : [l] "r"(l), [h] "r"(h));
230
+}
231
+
232
+# define HAVE_ATOMIC128 1
233
+#elif !defined(CONFIG_USER_ONLY) && HAVE_CMPXCHG128
234
+static inline Int128 atomic16_read(Int128 *ptr)
235
+{
236
+ /* Maybe replace 0 with 0, returning the old value. */
237
+ return atomic16_cmpxchg(ptr, 0, 0);
238
+}
239
+
240
+static inline void atomic16_set(Int128 *ptr, Int128 val)
241
+{
242
+ Int128 old = *ptr, cmp;
243
+ do {
244
+ cmp = old;
245
+ old = atomic16_cmpxchg(ptr, cmp, val);
246
+ } while (old != cmp);
247
+}
248
+
249
+# define HAVE_ATOMIC128 1
250
+#else
251
+/* Fallback definitions that must be optimized away, or error. */
252
+Int128 QEMU_ERROR("unsupported atomic") atomic16_read(Int128 *ptr);
253
+void QEMU_ERROR("unsupported atomic") atomic16_set(Int128 *ptr, Int128 val);
254
+# define HAVE_ATOMIC128 0
255
+#endif /* Some definition for HAVE_ATOMIC128 */
256
+
257
+#endif /* QEMU_ATOMIC128_H */
258
diff --git a/include/qemu/compiler.h b/include/qemu/compiler.h
259
index XXXXXXX..XXXXXXX 100644
260
--- a/include/qemu/compiler.h
261
+++ b/include/qemu/compiler.h
262
@@ -XXX,XX +XXX,XX @@
263
# define QEMU_FLATTEN
264
#endif
265
28
+/*
266
+/*
29
+ * A (single) even/odd pair for division.
267
+ * If __attribute__((error)) is present, use it to produce an error at
30
+ * TODO: Add something to the register allocator to allow
268
+ * compile time. Otherwise, one must wait for the linker to diagnose
31
+ * this kind of regno+1 pairing to be done more generally.
269
+ * the missing symbol.
32
+ */
270
+ */
33
+REGS('a', 1u << TCG_REG_R2)
271
+#if __has_attribute(error)
34
+REGS('b', 1u << TCG_REG_R3)
272
+# define QEMU_ERROR(X) __attribute__((error(X)))
35
+
273
+#else
274
+# define QEMU_ERROR(X)
275
+#endif
276
+
277
/* Implement C11 _Generic via GCC builtins. Example:
278
*
279
* QEMU_GENERIC(x, (float, sinf), (long double, sinl), sin) (x)
280
diff --git a/tcg/tcg.h b/tcg/tcg.h
281
index XXXXXXX..XXXXXXX 100644
282
--- a/tcg/tcg.h
283
+++ b/tcg/tcg.h
284
@@ -XXX,XX +XXX,XX @@
285
#include "qemu/queue.h"
286
#include "tcg-mo.h"
287
#include "tcg-target.h"
288
+#include "qemu/int128.h"
289
290
/* XXX: make safe guess about sizes */
291
#define MAX_OP_PER_INSTR 266
292
@@ -XXX,XX +XXX,XX @@ GEN_ATOMIC_HELPER_ALL(xchg)
293
#undef GEN_ATOMIC_HELPER
294
#endif /* CONFIG_SOFTMMU */
295
296
-#ifdef CONFIG_ATOMIC128
297
-#include "qemu/int128.h"
298
-
299
-/* These aren't really a "proper" helpers because TCG cannot manage Int128.
300
- However, use the same format as the others, for use by the backends. */
36
+/*
301
+/*
37
+ * Define constraint letters for constants:
302
+ * These aren't really a "proper" helpers because TCG cannot manage Int128.
38
+ * CONST(letter, TCG_CT_CONST_* bit set)
303
+ * However, use the same format as the others, for use by the backends.
304
+ *
305
+ * The cmpxchg functions are only defined if HAVE_CMPXCHG128;
306
+ * the ld/st functions are only defined if HAVE_ATOMIC128,
307
+ * as defined by <qemu/atomic128.h>.
39
+ */
308
+ */
40
+CONST('A', TCG_CT_CONST_S33)
309
Int128 helper_atomic_cmpxchgo_le_mmu(CPUArchState *env, target_ulong addr,
41
+CONST('I', TCG_CT_CONST_S16)
310
Int128 cmpv, Int128 newv,
42
+CONST('J', TCG_CT_CONST_S32)
311
TCGMemOpIdx oi, uintptr_t retaddr);
43
+CONST('Z', TCG_CT_CONST_ZERO)
312
@@ -XXX,XX +XXX,XX @@ void helper_atomic_sto_le_mmu(CPUArchState *env, target_ulong addr, Int128 val,
44
diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h
313
void helper_atomic_sto_be_mmu(CPUArchState *env, target_ulong addr, Int128 val,
314
TCGMemOpIdx oi, uintptr_t retaddr);
315
316
-#endif /* CONFIG_ATOMIC128 */
317
-
318
#endif /* TCG_H */
319
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
45
index XXXXXXX..XXXXXXX 100644
320
index XXXXXXX..XXXXXXX 100644
46
--- a/tcg/s390/tcg-target.h
321
--- a/accel/tcg/cputlb.c
47
+++ b/tcg/s390/tcg-target.h
322
+++ b/accel/tcg/cputlb.c
48
@@ -XXX,XX +XXX,XX @@ static inline void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
323
@@ -XXX,XX +XXX,XX @@
49
#define TCG_TARGET_NEED_LDST_LABELS
324
#include "exec/log.h"
325
#include "exec/helper-proto.h"
326
#include "qemu/atomic.h"
327
+#include "qemu/atomic128.h"
328
329
/* DEBUG defines, enable DEBUG_TLB_LOG to log to the CPU_LOG_MMU target */
330
/* #define DEBUG_TLB */
331
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
332
#include "atomic_template.h"
50
#endif
333
#endif
51
#define TCG_TARGET_NEED_POOL_LABELS
334
52
+#define TCG_TARGET_CON_STR_H
335
-#ifdef CONFIG_ATOMIC128
53
336
+#if HAVE_CMPXCHG128 || HAVE_ATOMIC128
337
#define DATA_SIZE 16
338
#include "atomic_template.h"
54
#endif
339
#endif
55
diff --git a/tcg/s390/tcg-target.c.inc b/tcg/s390/tcg-target.c.inc
340
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
56
index XXXXXXX..XXXXXXX 100644
341
index XXXXXXX..XXXXXXX 100644
57
--- a/tcg/s390/tcg-target.c.inc
342
--- a/accel/tcg/user-exec.c
58
+++ b/tcg/s390/tcg-target.c.inc
343
+++ b/accel/tcg/user-exec.c
59
@@ -XXX,XX +XXX,XX @@
344
@@ -XXX,XX +XXX,XX @@
60
#define TCG_CT_CONST_S33 0x400
345
#include "exec/cpu_ldst.h"
61
#define TCG_CT_CONST_ZERO 0x800
346
#include "translate-all.h"
62
347
#include "exec/helper-proto.h"
63
+#define ALL_GENERAL_REGS MAKE_64BIT_MASK(0, 16)
348
+#include "qemu/atomic128.h"
64
+/*
349
65
+ * For softmmu, we need to avoid conflicts with the first 3
350
#undef EAX
66
+ * argument registers to perform the tlb lookup, and to call
351
#undef ECX
67
+ * the helper function.
352
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
68
+ */
353
/* The following is only callable from other helpers, and matches up
69
+#ifdef CONFIG_SOFTMMU
354
with the softmmu version. */
70
+#define SOFTMMU_RESERVE_REGS MAKE_64BIT_MASK(TCG_REG_R2, 3)
355
71
+#else
356
-#ifdef CONFIG_ATOMIC128
72
+#define SOFTMMU_RESERVE_REGS 0
357
+#if HAVE_ATOMIC128 || HAVE_CMPXCHG128
73
+#endif
358
74
+
359
#undef EXTRA_ARGS
75
+
360
#undef ATOMIC_NAME
76
/* Several places within the instruction set 0 means "no register"
361
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
77
rather than TCG_REG_R0. */
362
78
#define TCG_REG_NONE 0
363
#define DATA_SIZE 16
79
@@ -XXX,XX +XXX,XX @@ static bool patch_reloc(tcg_insn_unit *src_rw, int type,
364
#include "atomic_template.h"
80
return false;
365
-#endif /* CONFIG_ATOMIC128 */
81
}
366
+#endif
82
367
diff --git a/configure b/configure
83
-/* parse target specific constraints */
368
index XXXXXXX..XXXXXXX 100755
84
-static const char *target_parse_constraint(TCGArgConstraint *ct,
369
--- a/configure
85
- const char *ct_str, TCGType type)
370
+++ b/configure
86
-{
371
@@ -XXX,XX +XXX,XX @@ EOF
87
- switch (*ct_str++) {
372
fi
88
- case 'r': /* all registers */
373
fi
89
- ct->regs = 0xffff;
374
90
- break;
375
+cmpxchg128=no
91
- case 'L': /* qemu_ld/st constraint */
376
+if test "$int128" = yes -a "$atomic128" = no; then
92
- ct->regs = 0xffff;
377
+ cat > $TMPC << EOF
93
- tcg_regset_reset_reg(ct->regs, TCG_REG_R2);
378
+int main(void)
94
- tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
379
+{
95
- tcg_regset_reset_reg(ct->regs, TCG_REG_R4);
380
+ unsigned __int128 x = 0, y = 0;
96
- break;
381
+ __sync_val_compare_and_swap_16(&x, y, x);
97
- case 'a': /* force R2 for division */
382
+ return 0;
98
- ct->regs = 0;
383
+}
99
- tcg_regset_set_reg(ct->regs, TCG_REG_R2);
384
+EOF
100
- break;
385
+ if compile_prog "" "" ; then
101
- case 'b': /* force R3 for division */
386
+ cmpxchg128=yes
102
- ct->regs = 0;
387
+ fi
103
- tcg_regset_set_reg(ct->regs, TCG_REG_R3);
388
+fi
104
- break;
389
+
105
- case 'A':
390
#########################################
106
- ct->ct |= TCG_CT_CONST_S33;
391
# See if 64-bit atomic operations are supported.
107
- break;
392
# Note that without __atomic builtins, we can only
108
- case 'I':
393
@@ -XXX,XX +XXX,XX @@ if test "$atomic128" = "yes" ; then
109
- ct->ct |= TCG_CT_CONST_S16;
394
echo "CONFIG_ATOMIC128=y" >> $config_host_mak
110
- break;
395
fi
111
- case 'J':
396
112
- ct->ct |= TCG_CT_CONST_S32;
397
+if test "$cmpxchg128" = "yes" ; then
113
- break;
398
+ echo "CONFIG_CMPXCHG128=y" >> $config_host_mak
114
- case 'Z':
399
+fi
115
- ct->ct |= TCG_CT_CONST_ZERO;
400
+
116
- break;
401
if test "$atomic64" = "yes" ; then
117
- default:
402
echo "CONFIG_ATOMIC64=y" >> $config_host_mak
118
- return NULL;
403
fi
119
- }
120
- return ct_str;
121
-}
122
-
123
/* Test if a constant matches the constraint. */
124
static int tcg_target_const_match(tcg_target_long val, TCGType type,
125
const TCGArgConstraint *arg_ct)
126
--
404
--
127
2.25.1
405
2.17.2
128
406
129
407
diff view generated by jsdifflib
1
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
1
Reviewed-by: Emilio G. Cota <cota@braap.org>
2
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.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/arm/tcg-target-con-set.h | 35 ++++++++++++++
5
target/i386/mem_helper.c | 9 ++++-----
5
tcg/arm/tcg-target.h | 1 +
6
1 file changed, 4 insertions(+), 5 deletions(-)
6
tcg/arm/tcg-target.c.inc | 94 ++++++++++++------------------------
7
3 files changed, 68 insertions(+), 62 deletions(-)
8
create mode 100644 tcg/arm/tcg-target-con-set.h
9
7
10
diff --git a/tcg/arm/tcg-target-con-set.h b/tcg/arm/tcg-target-con-set.h
8
diff --git a/target/i386/mem_helper.c b/target/i386/mem_helper.c
11
new file mode 100644
9
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX
10
--- a/target/i386/mem_helper.c
13
--- /dev/null
11
+++ b/target/i386/mem_helper.c
14
+++ b/tcg/arm/tcg-target-con-set.h
15
@@ -XXX,XX +XXX,XX @@
12
@@ -XXX,XX +XXX,XX @@
16
+/* SPDX-License-Identifier: MIT */
13
#include "exec/exec-all.h"
17
+/*
14
#include "exec/cpu_ldst.h"
18
+ * Define Arm target-specific constraint sets.
15
#include "qemu/int128.h"
19
+ * Copyright (c) 2021 Linaro
16
+#include "qemu/atomic128.h"
20
+ */
17
#include "tcg.h"
21
+
18
22
+/*
19
void helper_cmpxchg8b_unlocked(CPUX86State *env, target_ulong a0)
23
+ * C_On_Im(...) defines a constraint set with <n> outputs and <m> inputs.
20
@@ -XXX,XX +XXX,XX @@ void helper_cmpxchg16b(CPUX86State *env, target_ulong a0)
24
+ * Each operand should be a sequence of constraint letters as defined by
21
25
+ * tcg-target-con-str.h; the constraint combination is inclusive or.
22
if ((a0 & 0xf) != 0) {
26
+ */
23
raise_exception_ra(env, EXCP0D_GPF, ra);
27
+C_O0_I1(r)
24
- } else {
28
+C_O0_I2(r, r)
25
-#ifndef CONFIG_ATOMIC128
29
+C_O0_I2(r, rIN)
26
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
30
+C_O0_I2(s, s)
27
-#else
31
+C_O0_I3(s, s, s)
28
+ } else if (HAVE_CMPXCHG128) {
32
+C_O0_I4(r, r, rI, rI)
29
int eflags = cpu_cc_compute_all(env, CC_OP);
33
+C_O0_I4(s, s, s, s)
30
34
+C_O1_I1(r, l)
31
Int128 cmpv = int128_make128(env->regs[R_EAX], env->regs[R_EDX]);
35
+C_O1_I1(r, r)
32
@@ -XXX,XX +XXX,XX @@ void helper_cmpxchg16b(CPUX86State *env, target_ulong a0)
36
+C_O1_I2(r, 0, rZ)
33
eflags &= ~CC_Z;
37
+C_O1_I2(r, l, l)
34
}
38
+C_O1_I2(r, r, r)
35
CC_SRC = eflags;
39
+C_O1_I2(r, r, rI)
36
-#endif
40
+C_O1_I2(r, r, rIK)
37
+ } else {
41
+C_O1_I2(r, r, rIN)
38
+ cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
42
+C_O1_I2(r, r, ri)
43
+C_O1_I2(r, rZ, rZ)
44
+C_O1_I4(r, r, r, rI, rI)
45
+C_O1_I4(r, r, rIN, rIK, 0)
46
+C_O2_I1(r, r, l)
47
+C_O2_I2(r, r, l, l)
48
+C_O2_I2(r, r, r, r)
49
+C_O2_I4(r, r, r, r, rIN, rIK)
50
+C_O2_I4(r, r, rI, rI, rIN, rIK)
51
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
52
index XXXXXXX..XXXXXXX 100644
53
--- a/tcg/arm/tcg-target.h
54
+++ b/tcg/arm/tcg-target.h
55
@@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
56
#define TCG_TARGET_NEED_LDST_LABELS
57
#endif
58
#define TCG_TARGET_NEED_POOL_LABELS
59
+#define TCG_TARGET_CON_SET_H
60
61
#endif
62
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
63
index XXXXXXX..XXXXXXX 100644
64
--- a/tcg/arm/tcg-target.c.inc
65
+++ b/tcg/arm/tcg-target.c.inc
66
@@ -XXX,XX +XXX,XX @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
67
}
39
}
68
}
40
}
69
41
#endif
70
-static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
71
+static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
72
{
73
- static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
74
- static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
75
- static const TCGTargetOpDef s_s = { .args_ct_str = { "s", "s" } };
76
- static const TCGTargetOpDef r_l = { .args_ct_str = { "r", "l" } };
77
- static const TCGTargetOpDef r_r_r = { .args_ct_str = { "r", "r", "r" } };
78
- static const TCGTargetOpDef r_r_l = { .args_ct_str = { "r", "r", "l" } };
79
- static const TCGTargetOpDef r_l_l = { .args_ct_str = { "r", "l", "l" } };
80
- static const TCGTargetOpDef s_s_s = { .args_ct_str = { "s", "s", "s" } };
81
- static const TCGTargetOpDef r_r_ri = { .args_ct_str = { "r", "r", "ri" } };
82
- static const TCGTargetOpDef r_r_rI = { .args_ct_str = { "r", "r", "rI" } };
83
- static const TCGTargetOpDef r_r_rIN
84
- = { .args_ct_str = { "r", "r", "rIN" } };
85
- static const TCGTargetOpDef r_r_rIK
86
- = { .args_ct_str = { "r", "r", "rIK" } };
87
- static const TCGTargetOpDef r_r_r_r
88
- = { .args_ct_str = { "r", "r", "r", "r" } };
89
- static const TCGTargetOpDef r_r_l_l
90
- = { .args_ct_str = { "r", "r", "l", "l" } };
91
- static const TCGTargetOpDef s_s_s_s
92
- = { .args_ct_str = { "s", "s", "s", "s" } };
93
- static const TCGTargetOpDef br
94
- = { .args_ct_str = { "r", "rIN" } };
95
- static const TCGTargetOpDef ext2
96
- = { .args_ct_str = { "r", "rZ", "rZ" } };
97
- static const TCGTargetOpDef dep
98
- = { .args_ct_str = { "r", "0", "rZ" } };
99
- static const TCGTargetOpDef movc
100
- = { .args_ct_str = { "r", "r", "rIN", "rIK", "0" } };
101
- static const TCGTargetOpDef add2
102
- = { .args_ct_str = { "r", "r", "r", "r", "rIN", "rIK" } };
103
- static const TCGTargetOpDef sub2
104
- = { .args_ct_str = { "r", "r", "rI", "rI", "rIN", "rIK" } };
105
- static const TCGTargetOpDef br2
106
- = { .args_ct_str = { "r", "r", "rI", "rI" } };
107
- static const TCGTargetOpDef setc2
108
- = { .args_ct_str = { "r", "r", "r", "rI", "rI" } };
109
-
110
switch (op) {
111
case INDEX_op_goto_ptr:
112
- return &r;
113
+ return C_O0_I1(r);
114
115
case INDEX_op_ld8u_i32:
116
case INDEX_op_ld8s_i32:
117
case INDEX_op_ld16u_i32:
118
case INDEX_op_ld16s_i32:
119
case INDEX_op_ld_i32:
120
- case INDEX_op_st8_i32:
121
- case INDEX_op_st16_i32:
122
- case INDEX_op_st_i32:
123
case INDEX_op_neg_i32:
124
case INDEX_op_not_i32:
125
case INDEX_op_bswap16_i32:
126
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
127
case INDEX_op_ext16u_i32:
128
case INDEX_op_extract_i32:
129
case INDEX_op_sextract_i32:
130
- return &r_r;
131
+ return C_O1_I1(r, r);
132
+
133
+ case INDEX_op_st8_i32:
134
+ case INDEX_op_st16_i32:
135
+ case INDEX_op_st_i32:
136
+ return C_O0_I2(r, r);
137
138
case INDEX_op_add_i32:
139
case INDEX_op_sub_i32:
140
case INDEX_op_setcond_i32:
141
- return &r_r_rIN;
142
+ return C_O1_I2(r, r, rIN);
143
+
144
case INDEX_op_and_i32:
145
case INDEX_op_andc_i32:
146
case INDEX_op_clz_i32:
147
case INDEX_op_ctz_i32:
148
- return &r_r_rIK;
149
+ return C_O1_I2(r, r, rIK);
150
+
151
case INDEX_op_mul_i32:
152
case INDEX_op_div_i32:
153
case INDEX_op_divu_i32:
154
- return &r_r_r;
155
+ return C_O1_I2(r, r, r);
156
+
157
case INDEX_op_mulu2_i32:
158
case INDEX_op_muls2_i32:
159
- return &r_r_r_r;
160
+ return C_O2_I2(r, r, r, r);
161
+
162
case INDEX_op_or_i32:
163
case INDEX_op_xor_i32:
164
- return &r_r_rI;
165
+ return C_O1_I2(r, r, rI);
166
+
167
case INDEX_op_shl_i32:
168
case INDEX_op_shr_i32:
169
case INDEX_op_sar_i32:
170
case INDEX_op_rotl_i32:
171
case INDEX_op_rotr_i32:
172
- return &r_r_ri;
173
+ return C_O1_I2(r, r, ri);
174
175
case INDEX_op_brcond_i32:
176
- return &br;
177
+ return C_O0_I2(r, rIN);
178
case INDEX_op_deposit_i32:
179
- return &dep;
180
+ return C_O1_I2(r, 0, rZ);
181
case INDEX_op_extract2_i32:
182
- return &ext2;
183
+ return C_O1_I2(r, rZ, rZ);
184
case INDEX_op_movcond_i32:
185
- return &movc;
186
+ return C_O1_I4(r, r, rIN, rIK, 0);
187
case INDEX_op_add2_i32:
188
- return &add2;
189
+ return C_O2_I4(r, r, r, r, rIN, rIK);
190
case INDEX_op_sub2_i32:
191
- return &sub2;
192
+ return C_O2_I4(r, r, rI, rI, rIN, rIK);
193
case INDEX_op_brcond2_i32:
194
- return &br2;
195
+ return C_O0_I4(r, r, rI, rI);
196
case INDEX_op_setcond2_i32:
197
- return &setc2;
198
+ return C_O1_I4(r, r, r, rI, rI);
199
200
case INDEX_op_qemu_ld_i32:
201
- return TARGET_LONG_BITS == 32 ? &r_l : &r_l_l;
202
+ return TARGET_LONG_BITS == 32 ? C_O1_I1(r, l) : C_O1_I2(r, l, l);
203
case INDEX_op_qemu_ld_i64:
204
- return TARGET_LONG_BITS == 32 ? &r_r_l : &r_r_l_l;
205
+ return TARGET_LONG_BITS == 32 ? C_O2_I1(r, r, l) : C_O2_I2(r, r, l, l);
206
case INDEX_op_qemu_st_i32:
207
- return TARGET_LONG_BITS == 32 ? &s_s : &s_s_s;
208
+ return TARGET_LONG_BITS == 32 ? C_O0_I2(s, s) : C_O0_I3(s, s, s);
209
case INDEX_op_qemu_st_i64:
210
- return TARGET_LONG_BITS == 32 ? &s_s_s : &s_s_s_s;
211
+ return TARGET_LONG_BITS == 32 ? C_O0_I3(s, s, s) : C_O0_I4(s, s, s, s);
212
213
default:
214
- return NULL;
215
+ g_assert_not_reached();
216
}
217
}
218
219
--
42
--
220
2.25.1
43
2.17.2
221
44
222
45
diff view generated by jsdifflib
1
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
1
Reviewed-by: Emilio G. Cota <cota@braap.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
3
---
4
tcg/ppc/tcg-target-con-str.h | 30 +++++++++++++++
4
target/arm/helper-a64.c | 259 +++++++++++++++++++++-------------------
5
tcg/ppc/tcg-target.h | 1 +
5
1 file changed, 133 insertions(+), 126 deletions(-)
6
tcg/ppc/tcg-target.c.inc | 73 ++++++++----------------------------
7
3 files changed, 46 insertions(+), 58 deletions(-)
8
create mode 100644 tcg/ppc/tcg-target-con-str.h
9
6
10
diff --git a/tcg/ppc/tcg-target-con-str.h b/tcg/ppc/tcg-target-con-str.h
7
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
11
new file mode 100644
8
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX
9
--- a/target/arm/helper-a64.c
13
--- /dev/null
10
+++ b/target/arm/helper-a64.c
14
+++ b/tcg/ppc/tcg-target-con-str.h
15
@@ -XXX,XX +XXX,XX @@
11
@@ -XXX,XX +XXX,XX @@
16
+/* SPDX-License-Identifier: MIT */
12
#include "exec/exec-all.h"
17
+/*
13
#include "exec/cpu_ldst.h"
18
+ * Define PowerPC target-specific operand constraints.
14
#include "qemu/int128.h"
19
+ * Copyright (c) 2021 Linaro
15
+#include "qemu/atomic128.h"
20
+ */
16
#include "tcg.h"
21
+
17
#include "fpu/softfloat.h"
22
+/*
18
#include <zlib.h> /* For crc32 */
23
+ * Define constraint letters for register sets:
19
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(crc32c_64)(uint64_t acc, uint64_t val, uint32_t bytes)
24
+ * REGS(letter, register_mask)
20
return crc32c(acc, buf, bytes) ^ 0xffffffff;
25
+ */
21
}
26
+REGS('r', ALL_GENERAL_REGS)
22
27
+REGS('v', ALL_VECTOR_REGS)
23
-/* Returns 0 on success; 1 otherwise. */
28
+REGS('A', 1u << TCG_REG_R3)
24
-static uint64_t do_paired_cmpxchg64_le(CPUARMState *env, uint64_t addr,
29
+REGS('B', 1u << TCG_REG_R4)
25
- uint64_t new_lo, uint64_t new_hi,
30
+REGS('C', 1u << TCG_REG_R5)
26
- bool parallel, uintptr_t ra)
31
+REGS('D', 1u << TCG_REG_R6)
27
+uint64_t HELPER(paired_cmpxchg64_le)(CPUARMState *env, uint64_t addr,
32
+REGS('L', ALL_QLOAD_REGS)
28
+ uint64_t new_lo, uint64_t new_hi)
33
+REGS('S', ALL_QSTORE_REGS)
29
{
34
+
30
- Int128 oldv, cmpv, newv;
35
+/*
31
+ Int128 cmpv = int128_make128(env->exclusive_val, env->exclusive_high);
36
+ * Define constraint letters for constants:
32
+ Int128 newv = int128_make128(new_lo, new_hi);
37
+ * CONST(letter, TCG_CT_CONST_* bit set)
33
+ Int128 oldv;
38
+ */
34
+ uintptr_t ra = GETPC();
39
+CONST('I', TCG_CT_CONST_S16)
35
+ uint64_t o0, o1;
40
+CONST('J', TCG_CT_CONST_U16)
36
bool success;
41
+CONST('M', TCG_CT_CONST_MONE)
37
42
+CONST('T', TCG_CT_CONST_S32)
38
- cmpv = int128_make128(env->exclusive_val, env->exclusive_high);
43
+CONST('U', TCG_CT_CONST_U32)
39
- newv = int128_make128(new_lo, new_hi);
44
+CONST('W', TCG_CT_CONST_WSZ)
40
-
45
+CONST('Z', TCG_CT_CONST_ZERO)
41
- if (parallel) {
46
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
42
-#ifndef CONFIG_ATOMIC128
47
index XXXXXXX..XXXXXXX 100644
43
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
48
--- a/tcg/ppc/tcg-target.h
44
-#else
49
+++ b/tcg/ppc/tcg-target.h
45
- int mem_idx = cpu_mmu_index(env, false);
50
@@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
46
- TCGMemOpIdx oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
51
#define TCG_TARGET_NEED_LDST_LABELS
47
- oldv = helper_atomic_cmpxchgo_le_mmu(env, addr, cmpv, newv, oi, ra);
52
#endif
48
- success = int128_eq(oldv, cmpv);
53
#define TCG_TARGET_NEED_POOL_LABELS
49
-#endif
54
+#define TCG_TARGET_CON_STR_H
50
- } else {
55
51
- uint64_t o0, o1;
56
#endif
52
-
57
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
53
#ifdef CONFIG_USER_ONLY
58
index XXXXXXX..XXXXXXX 100644
54
- /* ??? Enforce alignment. */
59
--- a/tcg/ppc/tcg-target.c.inc
55
- uint64_t *haddr = g2h(addr);
60
+++ b/tcg/ppc/tcg-target.c.inc
56
+ /* ??? Enforce alignment. */
61
@@ -XXX,XX +XXX,XX @@
57
+ uint64_t *haddr = g2h(addr);
62
#define TCG_CT_CONST_MONE 0x2000
58
63
#define TCG_CT_CONST_WSZ 0x4000
59
- helper_retaddr = ra;
64
60
- o0 = ldq_le_p(haddr + 0);
65
+#define ALL_GENERAL_REGS 0xffffffffu
61
- o1 = ldq_le_p(haddr + 1);
66
+#define ALL_VECTOR_REGS 0xffffffff00000000ull
62
- oldv = int128_make128(o0, o1);
67
+
63
+ helper_retaddr = ra;
68
+#ifdef CONFIG_SOFTMMU
64
+ o0 = ldq_le_p(haddr + 0);
69
+#define ALL_QLOAD_REGS \
65
+ o1 = ldq_le_p(haddr + 1);
70
+ (ALL_GENERAL_REGS & \
66
+ oldv = int128_make128(o0, o1);
71
+ ~((1 << TCG_REG_R3) | (1 << TCG_REG_R4) | (1 << TCG_REG_R5)))
67
72
+#define ALL_QSTORE_REGS \
68
- success = int128_eq(oldv, cmpv);
73
+ (ALL_GENERAL_REGS & ~((1 << TCG_REG_R3) | (1 << TCG_REG_R4) | \
69
- if (success) {
74
+ (1 << TCG_REG_R5) | (1 << TCG_REG_R6)))
70
- stq_le_p(haddr + 0, int128_getlo(newv));
71
- stq_le_p(haddr + 1, int128_gethi(newv));
72
- }
73
- helper_retaddr = 0;
74
-#else
75
- int mem_idx = cpu_mmu_index(env, false);
76
- TCGMemOpIdx oi0 = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
77
- TCGMemOpIdx oi1 = make_memop_idx(MO_LEQ, mem_idx);
78
-
79
- o0 = helper_le_ldq_mmu(env, addr + 0, oi0, ra);
80
- o1 = helper_le_ldq_mmu(env, addr + 8, oi1, ra);
81
- oldv = int128_make128(o0, o1);
82
-
83
- success = int128_eq(oldv, cmpv);
84
- if (success) {
85
- helper_le_stq_mmu(env, addr + 0, int128_getlo(newv), oi1, ra);
86
- helper_le_stq_mmu(env, addr + 8, int128_gethi(newv), oi1, ra);
87
- }
88
-#endif
89
+ success = int128_eq(oldv, cmpv);
90
+ if (success) {
91
+ stq_le_p(haddr + 0, int128_getlo(newv));
92
+ stq_le_p(haddr + 1, int128_gethi(newv));
93
}
94
+ helper_retaddr = 0;
75
+#else
95
+#else
76
+#define ALL_QLOAD_REGS (ALL_GENERAL_REGS & ~(1 << TCG_REG_R3))
96
+ int mem_idx = cpu_mmu_index(env, false);
77
+#define ALL_QSTORE_REGS ALL_QLOAD_REGS
97
+ TCGMemOpIdx oi0 = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
98
+ TCGMemOpIdx oi1 = make_memop_idx(MO_LEQ, mem_idx);
99
+
100
+ o0 = helper_le_ldq_mmu(env, addr + 0, oi0, ra);
101
+ o1 = helper_le_ldq_mmu(env, addr + 8, oi1, ra);
102
+ oldv = int128_make128(o0, o1);
103
+
104
+ success = int128_eq(oldv, cmpv);
105
+ if (success) {
106
+ helper_le_stq_mmu(env, addr + 0, int128_getlo(newv), oi1, ra);
107
+ helper_le_stq_mmu(env, addr + 8, int128_gethi(newv), oi1, ra);
108
+ }
78
+#endif
109
+#endif
79
+
110
80
TCGPowerISA have_isa;
111
return !success;
81
static bool have_isel;
112
}
82
bool have_altivec;
113
83
@@ -XXX,XX +XXX,XX @@ static bool reloc_pc14(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
114
-uint64_t HELPER(paired_cmpxchg64_le)(CPUARMState *env, uint64_t addr,
84
return false;
115
- uint64_t new_lo, uint64_t new_hi)
85
}
86
87
-/* parse target specific constraints */
88
-static const char *target_parse_constraint(TCGArgConstraint *ct,
89
- const char *ct_str, TCGType type)
90
-{
116
-{
91
- switch (*ct_str++) {
117
- return do_paired_cmpxchg64_le(env, addr, new_lo, new_hi, false, GETPC());
92
- case 'A': case 'B': case 'C': case 'D':
93
- tcg_regset_set_reg(ct->regs, 3 + ct_str[0] - 'A');
94
- break;
95
- case 'r':
96
- ct->regs = 0xffffffff;
97
- break;
98
- case 'v':
99
- ct->regs = 0xffffffff00000000ull;
100
- break;
101
- case 'L': /* qemu_ld constraint */
102
- ct->regs = 0xffffffff;
103
- tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
104
-#ifdef CONFIG_SOFTMMU
105
- tcg_regset_reset_reg(ct->regs, TCG_REG_R4);
106
- tcg_regset_reset_reg(ct->regs, TCG_REG_R5);
107
-#endif
108
- break;
109
- case 'S': /* qemu_st constraint */
110
- ct->regs = 0xffffffff;
111
- tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
112
-#ifdef CONFIG_SOFTMMU
113
- tcg_regset_reset_reg(ct->regs, TCG_REG_R4);
114
- tcg_regset_reset_reg(ct->regs, TCG_REG_R5);
115
- tcg_regset_reset_reg(ct->regs, TCG_REG_R6);
116
-#endif
117
- break;
118
- case 'I':
119
- ct->ct |= TCG_CT_CONST_S16;
120
- break;
121
- case 'J':
122
- ct->ct |= TCG_CT_CONST_U16;
123
- break;
124
- case 'M':
125
- ct->ct |= TCG_CT_CONST_MONE;
126
- break;
127
- case 'T':
128
- ct->ct |= TCG_CT_CONST_S32;
129
- break;
130
- case 'U':
131
- ct->ct |= TCG_CT_CONST_U32;
132
- break;
133
- case 'W':
134
- ct->ct |= TCG_CT_CONST_WSZ;
135
- break;
136
- case 'Z':
137
- ct->ct |= TCG_CT_CONST_ZERO;
138
- break;
139
- default:
140
- return NULL;
141
- }
142
- return ct_str;
143
-}
118
-}
144
-
119
-
145
/* test if a constant matches the constraint */
120
uint64_t HELPER(paired_cmpxchg64_le_parallel)(CPUARMState *env, uint64_t addr,
146
static int tcg_target_const_match(tcg_target_long val, TCGType type,
121
uint64_t new_lo, uint64_t new_hi)
147
const TCGArgConstraint *arg_ct)
122
-{
123
- return do_paired_cmpxchg64_le(env, addr, new_lo, new_hi, true, GETPC());
124
-}
125
-
126
-static uint64_t do_paired_cmpxchg64_be(CPUARMState *env, uint64_t addr,
127
- uint64_t new_lo, uint64_t new_hi,
128
- bool parallel, uintptr_t ra)
129
{
130
Int128 oldv, cmpv, newv;
131
+ uintptr_t ra = GETPC();
132
bool success;
133
+ int mem_idx;
134
+ TCGMemOpIdx oi;
135
136
- /* high and low need to be switched here because this is not actually a
137
- * 128bit store but two doublewords stored consecutively
138
- */
139
- cmpv = int128_make128(env->exclusive_high, env->exclusive_val);
140
- newv = int128_make128(new_hi, new_lo);
141
-
142
- if (parallel) {
143
-#ifndef CONFIG_ATOMIC128
144
+ if (!HAVE_CMPXCHG128) {
145
cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
146
-#else
147
- int mem_idx = cpu_mmu_index(env, false);
148
- TCGMemOpIdx oi = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx);
149
- oldv = helper_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, oi, ra);
150
- success = int128_eq(oldv, cmpv);
151
-#endif
152
- } else {
153
- uint64_t o0, o1;
154
-
155
-#ifdef CONFIG_USER_ONLY
156
- /* ??? Enforce alignment. */
157
- uint64_t *haddr = g2h(addr);
158
-
159
- helper_retaddr = ra;
160
- o1 = ldq_be_p(haddr + 0);
161
- o0 = ldq_be_p(haddr + 1);
162
- oldv = int128_make128(o0, o1);
163
-
164
- success = int128_eq(oldv, cmpv);
165
- if (success) {
166
- stq_be_p(haddr + 0, int128_gethi(newv));
167
- stq_be_p(haddr + 1, int128_getlo(newv));
168
- }
169
- helper_retaddr = 0;
170
-#else
171
- int mem_idx = cpu_mmu_index(env, false);
172
- TCGMemOpIdx oi0 = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx);
173
- TCGMemOpIdx oi1 = make_memop_idx(MO_BEQ, mem_idx);
174
-
175
- o1 = helper_be_ldq_mmu(env, addr + 0, oi0, ra);
176
- o0 = helper_be_ldq_mmu(env, addr + 8, oi1, ra);
177
- oldv = int128_make128(o0, o1);
178
-
179
- success = int128_eq(oldv, cmpv);
180
- if (success) {
181
- helper_be_stq_mmu(env, addr + 0, int128_gethi(newv), oi1, ra);
182
- helper_be_stq_mmu(env, addr + 8, int128_getlo(newv), oi1, ra);
183
- }
184
-#endif
185
}
186
187
+ mem_idx = cpu_mmu_index(env, false);
188
+ oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
189
+
190
+ cmpv = int128_make128(env->exclusive_val, env->exclusive_high);
191
+ newv = int128_make128(new_lo, new_hi);
192
+ oldv = helper_atomic_cmpxchgo_le_mmu(env, addr, cmpv, newv, oi, ra);
193
+
194
+ success = int128_eq(oldv, cmpv);
195
return !success;
196
}
197
198
uint64_t HELPER(paired_cmpxchg64_be)(CPUARMState *env, uint64_t addr,
199
uint64_t new_lo, uint64_t new_hi)
200
{
201
- return do_paired_cmpxchg64_be(env, addr, new_lo, new_hi, false, GETPC());
202
+ /*
203
+ * High and low need to be switched here because this is not actually a
204
+ * 128bit store but two doublewords stored consecutively
205
+ */
206
+ Int128 cmpv = int128_make128(env->exclusive_val, env->exclusive_high);
207
+ Int128 newv = int128_make128(new_lo, new_hi);
208
+ Int128 oldv;
209
+ uintptr_t ra = GETPC();
210
+ uint64_t o0, o1;
211
+ bool success;
212
+
213
+#ifdef CONFIG_USER_ONLY
214
+ /* ??? Enforce alignment. */
215
+ uint64_t *haddr = g2h(addr);
216
+
217
+ helper_retaddr = ra;
218
+ o1 = ldq_be_p(haddr + 0);
219
+ o0 = ldq_be_p(haddr + 1);
220
+ oldv = int128_make128(o0, o1);
221
+
222
+ success = int128_eq(oldv, cmpv);
223
+ if (success) {
224
+ stq_be_p(haddr + 0, int128_gethi(newv));
225
+ stq_be_p(haddr + 1, int128_getlo(newv));
226
+ }
227
+ helper_retaddr = 0;
228
+#else
229
+ int mem_idx = cpu_mmu_index(env, false);
230
+ TCGMemOpIdx oi0 = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx);
231
+ TCGMemOpIdx oi1 = make_memop_idx(MO_BEQ, mem_idx);
232
+
233
+ o1 = helper_be_ldq_mmu(env, addr + 0, oi0, ra);
234
+ o0 = helper_be_ldq_mmu(env, addr + 8, oi1, ra);
235
+ oldv = int128_make128(o0, o1);
236
+
237
+ success = int128_eq(oldv, cmpv);
238
+ if (success) {
239
+ helper_be_stq_mmu(env, addr + 0, int128_gethi(newv), oi1, ra);
240
+ helper_be_stq_mmu(env, addr + 8, int128_getlo(newv), oi1, ra);
241
+ }
242
+#endif
243
+
244
+ return !success;
245
}
246
247
uint64_t HELPER(paired_cmpxchg64_be_parallel)(CPUARMState *env, uint64_t addr,
248
- uint64_t new_lo, uint64_t new_hi)
249
+ uint64_t new_lo, uint64_t new_hi)
250
{
251
- return do_paired_cmpxchg64_be(env, addr, new_lo, new_hi, true, GETPC());
252
+ Int128 oldv, cmpv, newv;
253
+ uintptr_t ra = GETPC();
254
+ bool success;
255
+ int mem_idx;
256
+ TCGMemOpIdx oi;
257
+
258
+ if (!HAVE_CMPXCHG128) {
259
+ cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
260
+ }
261
+
262
+ mem_idx = cpu_mmu_index(env, false);
263
+ oi = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx);
264
+
265
+ /*
266
+ * High and low need to be switched here because this is not actually a
267
+ * 128bit store but two doublewords stored consecutively
268
+ */
269
+ cmpv = int128_make128(env->exclusive_high, env->exclusive_val);
270
+ newv = int128_make128(new_hi, new_lo);
271
+ oldv = helper_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, oi, ra);
272
+
273
+ success = int128_eq(oldv, cmpv);
274
+ return !success;
275
}
276
277
/* Writes back the old data into Rs. */
278
void HELPER(casp_le_parallel)(CPUARMState *env, uint32_t rs, uint64_t addr,
279
uint64_t new_lo, uint64_t new_hi)
280
{
281
- uintptr_t ra = GETPC();
282
-#ifndef CONFIG_ATOMIC128
283
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
284
-#else
285
Int128 oldv, cmpv, newv;
286
+ uintptr_t ra = GETPC();
287
+ int mem_idx;
288
+ TCGMemOpIdx oi;
289
+
290
+ if (!HAVE_CMPXCHG128) {
291
+ cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
292
+ }
293
+
294
+ mem_idx = cpu_mmu_index(env, false);
295
+ oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
296
297
cmpv = int128_make128(env->xregs[rs], env->xregs[rs + 1]);
298
newv = int128_make128(new_lo, new_hi);
299
-
300
- int mem_idx = cpu_mmu_index(env, false);
301
- TCGMemOpIdx oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
302
oldv = helper_atomic_cmpxchgo_le_mmu(env, addr, cmpv, newv, oi, ra);
303
304
env->xregs[rs] = int128_getlo(oldv);
305
env->xregs[rs + 1] = int128_gethi(oldv);
306
-#endif
307
}
308
309
void HELPER(casp_be_parallel)(CPUARMState *env, uint32_t rs, uint64_t addr,
310
uint64_t new_hi, uint64_t new_lo)
311
{
312
- uintptr_t ra = GETPC();
313
-#ifndef CONFIG_ATOMIC128
314
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
315
-#else
316
Int128 oldv, cmpv, newv;
317
+ uintptr_t ra = GETPC();
318
+ int mem_idx;
319
+ TCGMemOpIdx oi;
320
+
321
+ if (!HAVE_CMPXCHG128) {
322
+ cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
323
+ }
324
+
325
+ mem_idx = cpu_mmu_index(env, false);
326
+ oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
327
328
cmpv = int128_make128(env->xregs[rs + 1], env->xregs[rs]);
329
newv = int128_make128(new_lo, new_hi);
330
-
331
- int mem_idx = cpu_mmu_index(env, false);
332
- TCGMemOpIdx oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
333
oldv = helper_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, oi, ra);
334
335
env->xregs[rs + 1] = int128_getlo(oldv);
336
env->xregs[rs] = int128_gethi(oldv);
337
-#endif
338
}
339
340
/*
148
--
341
--
149
2.25.1
342
2.17.2
150
343
151
344
diff view generated by jsdifflib
1
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
1
Reviewed-by: Emilio G. Cota <cota@braap.org>
2
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.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/aarch64/tcg-target-con-str.h | 24 +++++++++++++++
5
target/arm/helper-a64.c | 16 ++++------------
5
tcg/aarch64/tcg-target.h | 1 +
6
target/arm/translate-a64.c | 38 ++++++++++++++++++++++----------------
6
tcg/aarch64/tcg-target.c.inc | 51 +++++---------------------------
7
2 files changed, 26 insertions(+), 28 deletions(-)
7
3 files changed, 33 insertions(+), 43 deletions(-)
8
create mode 100644 tcg/aarch64/tcg-target-con-str.h
9
8
10
diff --git a/tcg/aarch64/tcg-target-con-str.h b/tcg/aarch64/tcg-target-con-str.h
9
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
11
new file mode 100644
10
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX
11
--- a/target/arm/helper-a64.c
13
--- /dev/null
12
+++ b/target/arm/helper-a64.c
14
+++ b/tcg/aarch64/tcg-target-con-str.h
13
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(paired_cmpxchg64_le_parallel)(CPUARMState *env, uint64_t addr,
14
int mem_idx;
15
TCGMemOpIdx oi;
16
17
- if (!HAVE_CMPXCHG128) {
18
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
19
- }
20
+ assert(HAVE_CMPXCHG128);
21
22
mem_idx = cpu_mmu_index(env, false);
23
oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
24
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(paired_cmpxchg64_be_parallel)(CPUARMState *env, uint64_t addr,
25
int mem_idx;
26
TCGMemOpIdx oi;
27
28
- if (!HAVE_CMPXCHG128) {
29
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
30
- }
31
+ assert(HAVE_CMPXCHG128);
32
33
mem_idx = cpu_mmu_index(env, false);
34
oi = make_memop_idx(MO_BEQ | MO_ALIGN_16, mem_idx);
35
@@ -XXX,XX +XXX,XX @@ void HELPER(casp_le_parallel)(CPUARMState *env, uint32_t rs, uint64_t addr,
36
int mem_idx;
37
TCGMemOpIdx oi;
38
39
- if (!HAVE_CMPXCHG128) {
40
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
41
- }
42
+ assert(HAVE_CMPXCHG128);
43
44
mem_idx = cpu_mmu_index(env, false);
45
oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
46
@@ -XXX,XX +XXX,XX @@ void HELPER(casp_be_parallel)(CPUARMState *env, uint32_t rs, uint64_t addr,
47
int mem_idx;
48
TCGMemOpIdx oi;
49
50
- if (!HAVE_CMPXCHG128) {
51
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
52
- }
53
+ assert(HAVE_CMPXCHG128);
54
55
mem_idx = cpu_mmu_index(env, false);
56
oi = make_memop_idx(MO_LEQ | MO_ALIGN_16, mem_idx);
57
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/target/arm/translate-a64.c
60
+++ b/target/arm/translate-a64.c
15
@@ -XXX,XX +XXX,XX @@
61
@@ -XXX,XX +XXX,XX @@
16
+/* SPDX-License-Identifier: GPL-2.0-or-later */
62
17
+/*
63
#include "trace-tcg.h"
18
+ * Define AArch64 target-specific operand constraints.
64
#include "translate-a64.h"
19
+ * Copyright (c) 2021 Linaro
65
+#include "qemu/atomic128.h"
20
+ */
66
21
+
67
static TCGv_i64 cpu_X[32];
22
+/*
68
static TCGv_i64 cpu_pc;
23
+ * Define constraint letters for register sets:
69
@@ -XXX,XX +XXX,XX @@ static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
24
+ * REGS(letter, register_mask)
70
get_mem_index(s),
25
+ */
71
MO_64 | MO_ALIGN | s->be_data);
26
+REGS('r', ALL_GENERAL_REGS)
72
tcg_gen_setcond_i64(TCG_COND_NE, tmp, tmp, cpu_exclusive_val);
27
+REGS('l', ALL_QLDST_REGS)
73
- } else if (s->be_data == MO_LE) {
28
+REGS('w', ALL_VECTOR_REGS)
74
- if (tb_cflags(s->base.tb) & CF_PARALLEL) {
29
+
75
+ } else if (tb_cflags(s->base.tb) & CF_PARALLEL) {
30
+/*
76
+ if (!HAVE_CMPXCHG128) {
31
+ * Define constraint letters for constants:
77
+ gen_helper_exit_atomic(cpu_env);
32
+ * CONST(letter, TCG_CT_CONST_* bit set)
78
+ s->base.is_jmp = DISAS_NORETURN;
33
+ */
79
+ } else if (s->be_data == MO_LE) {
34
+CONST('A', TCG_CT_CONST_AIMM)
80
gen_helper_paired_cmpxchg64_le_parallel(tmp, cpu_env,
35
+CONST('L', TCG_CT_CONST_LIMM)
81
cpu_exclusive_addr,
36
+CONST('M', TCG_CT_CONST_MONE)
82
cpu_reg(s, rt),
37
+CONST('O', TCG_CT_CONST_ORRI)
83
cpu_reg(s, rt2));
38
+CONST('N', TCG_CT_CONST_ANDI)
84
} else {
39
+CONST('Z', TCG_CT_CONST_ZERO)
85
- gen_helper_paired_cmpxchg64_le(tmp, cpu_env, cpu_exclusive_addr,
40
diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h
86
- cpu_reg(s, rt), cpu_reg(s, rt2));
41
index XXXXXXX..XXXXXXX 100644
87
- }
42
--- a/tcg/aarch64/tcg-target.h
88
- } else {
43
+++ b/tcg/aarch64/tcg-target.h
89
- if (tb_cflags(s->base.tb) & CF_PARALLEL) {
44
@@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
90
gen_helper_paired_cmpxchg64_be_parallel(tmp, cpu_env,
45
#define TCG_TARGET_NEED_LDST_LABELS
91
cpu_exclusive_addr,
46
#endif
92
cpu_reg(s, rt),
47
#define TCG_TARGET_NEED_POOL_LABELS
93
cpu_reg(s, rt2));
48
+#define TCG_TARGET_CON_STR_H
94
- } else {
49
95
- gen_helper_paired_cmpxchg64_be(tmp, cpu_env, cpu_exclusive_addr,
50
#endif /* AARCH64_TCG_TARGET_H */
96
- cpu_reg(s, rt), cpu_reg(s, rt2));
51
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
97
}
52
index XXXXXXX..XXXXXXX 100644
98
+ } else if (s->be_data == MO_LE) {
53
--- a/tcg/aarch64/tcg-target.c.inc
99
+ gen_helper_paired_cmpxchg64_le(tmp, cpu_env, cpu_exclusive_addr,
54
+++ b/tcg/aarch64/tcg-target.c.inc
100
+ cpu_reg(s, rt), cpu_reg(s, rt2));
55
@@ -XXX,XX +XXX,XX @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
101
+ } else {
56
#define TCG_CT_CONST_ORRI 0x1000
102
+ gen_helper_paired_cmpxchg64_be(tmp, cpu_env, cpu_exclusive_addr,
57
#define TCG_CT_CONST_ANDI 0x2000
103
+ cpu_reg(s, rt), cpu_reg(s, rt2));
58
104
}
59
-/* parse target specific constraints */
105
} else {
60
-static const char *target_parse_constraint(TCGArgConstraint *ct,
106
tcg_gen_atomic_cmpxchg_i64(tmp, cpu_exclusive_addr, cpu_exclusive_val,
61
- const char *ct_str, TCGType type)
107
@@ -XXX,XX +XXX,XX @@ static void gen_compare_and_swap_pair(DisasContext *s, int rs, int rt,
62
-{
108
}
63
- switch (*ct_str++) {
109
tcg_temp_free_i64(cmp);
64
- case 'r': /* general registers */
110
} else if (tb_cflags(s->base.tb) & CF_PARALLEL) {
65
- ct->regs |= 0xffffffffu;
111
- TCGv_i32 tcg_rs = tcg_const_i32(rs);
66
- break;
112
-
67
- case 'w': /* advsimd registers */
113
- if (s->be_data == MO_LE) {
68
- ct->regs |= 0xffffffff00000000ull;
114
- gen_helper_casp_le_parallel(cpu_env, tcg_rs, addr, t1, t2);
69
- break;
115
+ if (HAVE_CMPXCHG128) {
70
- case 'l': /* qemu_ld / qemu_st address, data_reg */
116
+ TCGv_i32 tcg_rs = tcg_const_i32(rs);
71
- ct->regs = 0xffffffffu;
117
+ if (s->be_data == MO_LE) {
72
+#define ALL_GENERAL_REGS 0xffffffffu
118
+ gen_helper_casp_le_parallel(cpu_env, tcg_rs, addr, t1, t2);
73
+#define ALL_VECTOR_REGS 0xffffffff00000000ull
119
+ } else {
74
+
120
+ gen_helper_casp_be_parallel(cpu_env, tcg_rs, addr, t1, t2);
75
#ifdef CONFIG_SOFTMMU
121
+ }
76
- /* x0 and x1 will be overwritten when reading the tlb entry,
122
+ tcg_temp_free_i32(tcg_rs);
77
- and x2, and x3 for helper args, better to avoid using them. */
123
} else {
78
- tcg_regset_reset_reg(ct->regs, TCG_REG_X0);
124
- gen_helper_casp_be_parallel(cpu_env, tcg_rs, addr, t1, t2);
79
- tcg_regset_reset_reg(ct->regs, TCG_REG_X1);
125
+ gen_helper_exit_atomic(cpu_env);
80
- tcg_regset_reset_reg(ct->regs, TCG_REG_X2);
126
+ s->base.is_jmp = DISAS_NORETURN;
81
- tcg_regset_reset_reg(ct->regs, TCG_REG_X3);
127
}
82
+#define ALL_QLDST_REGS \
128
- tcg_temp_free_i32(tcg_rs);
83
+ (ALL_GENERAL_REGS & ~((1 << TCG_REG_X0) | (1 << TCG_REG_X1) | \
129
} else {
84
+ (1 << TCG_REG_X2) | (1 << TCG_REG_X3)))
130
TCGv_i64 d1 = tcg_temp_new_i64();
85
+#else
131
TCGv_i64 d2 = tcg_temp_new_i64();
86
+#define ALL_QLDST_REGS ALL_GENERAL_REGS
87
#endif
88
- break;
89
- case 'A': /* Valid for arithmetic immediate (positive or negative). */
90
- ct->ct |= TCG_CT_CONST_AIMM;
91
- break;
92
- case 'L': /* Valid for logical immediate. */
93
- ct->ct |= TCG_CT_CONST_LIMM;
94
- break;
95
- case 'M': /* minus one */
96
- ct->ct |= TCG_CT_CONST_MONE;
97
- break;
98
- case 'O': /* vector orr/bic immediate */
99
- ct->ct |= TCG_CT_CONST_ORRI;
100
- break;
101
- case 'N': /* vector orr/bic immediate, inverted */
102
- ct->ct |= TCG_CT_CONST_ANDI;
103
- break;
104
- case 'Z': /* zero */
105
- ct->ct |= TCG_CT_CONST_ZERO;
106
- break;
107
- default:
108
- return NULL;
109
- }
110
- return ct_str;
111
-}
112
113
/* Match a constant valid for addition (12-bit, optionally shifted). */
114
static inline bool is_aimm(uint64_t val)
115
--
132
--
116
2.25.1
133
2.17.2
117
134
118
135
diff view generated by jsdifflib
1
This eliminates the target-specific function target_parse_constraint
1
Reviewed-by: Emilio G. Cota <cota@braap.org>
2
and folds it into the single caller, process_op_defs. Since this is
3
done directly into the switch statement, duplicates are compilation
4
errors rather than silently ignored at runtime.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
3
---
9
tcg/i386/tcg-target-con-str.h | 33 +++++++++++++++++
4
target/ppc/helper.h | 2 +-
10
tcg/i386/tcg-target.h | 1 +
5
target/ppc/mem_helper.c | 33 ++++++++++--
11
tcg/tcg.c | 33 ++++++++++++++---
6
target/ppc/translate.c | 115 +++++++++++++++++++++-------------------
12
tcg/i386/tcg-target.c.inc | 69 -----------------------------------
7
3 files changed, 88 insertions(+), 62 deletions(-)
13
4 files changed, 62 insertions(+), 74 deletions(-)
14
create mode 100644 tcg/i386/tcg-target-con-str.h
15
8
16
diff --git a/tcg/i386/tcg-target-con-str.h b/tcg/i386/tcg-target-con-str.h
9
diff --git a/target/ppc/helper.h b/target/ppc/helper.h
17
new file mode 100644
10
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX
11
--- a/target/ppc/helper.h
19
--- /dev/null
12
+++ b/target/ppc/helper.h
20
+++ b/tcg/i386/tcg-target-con-str.h
13
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_4(dscliq, void, env, fprp, fprp, i32)
14
DEF_HELPER_1(tbegin, void, env)
15
DEF_HELPER_FLAGS_1(fixup_thrm, TCG_CALL_NO_RWG, void, env)
16
17
-#if defined(TARGET_PPC64) && defined(CONFIG_ATOMIC128)
18
+#ifdef TARGET_PPC64
19
DEF_HELPER_FLAGS_3(lq_le_parallel, TCG_CALL_NO_WG, i64, env, tl, i32)
20
DEF_HELPER_FLAGS_3(lq_be_parallel, TCG_CALL_NO_WG, i64, env, tl, i32)
21
DEF_HELPER_FLAGS_5(stq_le_parallel, TCG_CALL_NO_WG,
22
diff --git a/target/ppc/mem_helper.c b/target/ppc/mem_helper.c
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/ppc/mem_helper.c
25
+++ b/target/ppc/mem_helper.c
21
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@
22
+/* SPDX-License-Identifier: MIT */
27
#include "exec/cpu_ldst.h"
23
+/*
28
#include "tcg.h"
24
+ * Define i386 target-specific operand constraints.
29
#include "internal.h"
25
+ * Copyright (c) 2021 Linaro
30
+#include "qemu/atomic128.h"
26
+ *
31
27
+ */
32
//#define DEBUG_OP
28
+
33
29
+/*
34
@@ -XXX,XX +XXX,XX @@ target_ulong helper_lscbx(CPUPPCState *env, target_ulong addr, uint32_t reg,
30
+ * Define constraint letters for register sets:
35
return i;
31
+ * REGS(letter, register_mask)
36
}
32
+ */
37
33
+REGS('a', 1u << TCG_REG_EAX)
38
-#if defined(TARGET_PPC64) && defined(CONFIG_ATOMIC128)
34
+REGS('b', 1u << TCG_REG_EBX)
39
+#ifdef TARGET_PPC64
35
+REGS('c', 1u << TCG_REG_ECX)
40
uint64_t helper_lq_le_parallel(CPUPPCState *env, target_ulong addr,
36
+REGS('d', 1u << TCG_REG_EDX)
41
uint32_t opidx)
37
+REGS('S', 1u << TCG_REG_ESI)
42
{
38
+REGS('D', 1u << TCG_REG_EDI)
43
- Int128 ret = helper_atomic_ldo_le_mmu(env, addr, opidx, GETPC());
39
+
44
+ Int128 ret;
40
+REGS('r', ALL_GENERAL_REGS)
45
+
41
+REGS('x', ALL_VECTOR_REGS)
46
+ /* We will have raised EXCP_ATOMIC from the translator. */
42
+REGS('q', ALL_BYTEL_REGS) /* regs that can be used as a byte operand */
47
+ assert(HAVE_ATOMIC128);
43
+REGS('Q', ALL_BYTEH_REGS) /* regs with a second byte (e.g. %ah) */
48
+ ret = helper_atomic_ldo_le_mmu(env, addr, opidx, GETPC());
44
+REGS('L', ALL_GENERAL_REGS & ~SOFTMMU_RESERVE_REGS) /* qemu_ld/st */
49
env->retxh = int128_gethi(ret);
45
+REGS('s', ALL_BYTEL_REGS & ~SOFTMMU_RESERVE_REGS) /* qemu_st8_i32 data */
50
return int128_getlo(ret);
46
+
51
}
47
+/*
52
@@ -XXX,XX +XXX,XX @@ uint64_t helper_lq_le_parallel(CPUPPCState *env, target_ulong addr,
48
+ * Define constraint letters for constants:
53
uint64_t helper_lq_be_parallel(CPUPPCState *env, target_ulong addr,
49
+ * CONST(letter, TCG_CT_CONST_* bit set)
54
uint32_t opidx)
50
+ */
55
{
51
+CONST('e', TCG_CT_CONST_S32)
56
- Int128 ret = helper_atomic_ldo_be_mmu(env, addr, opidx, GETPC());
52
+CONST('I', TCG_CT_CONST_I32)
57
+ Int128 ret;
53
+CONST('W', TCG_CT_CONST_WSZ)
58
+
54
+CONST('Z', TCG_CT_CONST_U32)
59
+ /* We will have raised EXCP_ATOMIC from the translator. */
55
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
60
+ assert(HAVE_ATOMIC128);
61
+ ret = helper_atomic_ldo_be_mmu(env, addr, opidx, GETPC());
62
env->retxh = int128_gethi(ret);
63
return int128_getlo(ret);
64
}
65
@@ -XXX,XX +XXX,XX @@ uint64_t helper_lq_be_parallel(CPUPPCState *env, target_ulong addr,
66
void helper_stq_le_parallel(CPUPPCState *env, target_ulong addr,
67
uint64_t lo, uint64_t hi, uint32_t opidx)
68
{
69
- Int128 val = int128_make128(lo, hi);
70
+ Int128 val;
71
+
72
+ /* We will have raised EXCP_ATOMIC from the translator. */
73
+ assert(HAVE_ATOMIC128);
74
+ val = int128_make128(lo, hi);
75
helper_atomic_sto_le_mmu(env, addr, val, opidx, GETPC());
76
}
77
78
void helper_stq_be_parallel(CPUPPCState *env, target_ulong addr,
79
uint64_t lo, uint64_t hi, uint32_t opidx)
80
{
81
- Int128 val = int128_make128(lo, hi);
82
+ Int128 val;
83
+
84
+ /* We will have raised EXCP_ATOMIC from the translator. */
85
+ assert(HAVE_ATOMIC128);
86
+ val = int128_make128(lo, hi);
87
helper_atomic_sto_be_mmu(env, addr, val, opidx, GETPC());
88
}
89
90
@@ -XXX,XX +XXX,XX @@ uint32_t helper_stqcx_le_parallel(CPUPPCState *env, target_ulong addr,
91
{
92
bool success = false;
93
94
+ /* We will have raised EXCP_ATOMIC from the translator. */
95
+ assert(HAVE_CMPXCHG128);
96
+
97
if (likely(addr == env->reserve_addr)) {
98
Int128 oldv, cmpv, newv;
99
100
@@ -XXX,XX +XXX,XX @@ uint32_t helper_stqcx_be_parallel(CPUPPCState *env, target_ulong addr,
101
{
102
bool success = false;
103
104
+ /* We will have raised EXCP_ATOMIC from the translator. */
105
+ assert(HAVE_CMPXCHG128);
106
+
107
if (likely(addr == env->reserve_addr)) {
108
Int128 oldv, cmpv, newv;
109
110
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
56
index XXXXXXX..XXXXXXX 100644
111
index XXXXXXX..XXXXXXX 100644
57
--- a/tcg/i386/tcg-target.h
112
--- a/target/ppc/translate.c
58
+++ b/tcg/i386/tcg-target.h
113
+++ b/target/ppc/translate.c
59
@@ -XXX,XX +XXX,XX @@ static inline void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
114
@@ -XXX,XX +XXX,XX @@
60
#define TCG_TARGET_NEED_LDST_LABELS
115
#include "trace-tcg.h"
61
#endif
116
#include "exec/translator.h"
62
#define TCG_TARGET_NEED_POOL_LABELS
117
#include "exec/log.h"
63
+#define TCG_TARGET_CON_STR_H
118
+#include "qemu/atomic128.h"
64
119
65
#endif
120
66
diff --git a/tcg/tcg.c b/tcg/tcg.c
121
#define CPU_SINGLE_STEP 0x1
67
index XXXXXXX..XXXXXXX 100644
122
@@ -XXX,XX +XXX,XX @@ static void gen_lq(DisasContext *ctx)
68
--- a/tcg/tcg.c
123
hi = cpu_gpr[rd];
69
+++ b/tcg/tcg.c
124
70
@@ -XXX,XX +XXX,XX @@ static void tcg_register_jit_int(const void *buf, size_t size,
125
if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
71
__attribute__((unused));
126
-#ifdef CONFIG_ATOMIC128
72
127
- TCGv_i32 oi = tcg_temp_new_i32();
73
/* Forward declarations for functions declared and used in tcg-target.c.inc. */
128
- if (ctx->le_mode) {
74
+#ifndef TCG_TARGET_CON_STR_H
129
- tcg_gen_movi_i32(oi, make_memop_idx(MO_LEQ, ctx->mem_idx));
75
static const char *target_parse_constraint(TCGArgConstraint *ct,
130
- gen_helper_lq_le_parallel(lo, cpu_env, EA, oi);
76
const char *ct_str, TCGType type);
131
+ if (HAVE_ATOMIC128) {
77
+#endif
132
+ TCGv_i32 oi = tcg_temp_new_i32();
78
static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
133
+ if (ctx->le_mode) {
79
intptr_t arg2);
134
+ tcg_gen_movi_i32(oi, make_memop_idx(MO_LEQ, ctx->mem_idx));
80
static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg);
135
+ gen_helper_lq_le_parallel(lo, cpu_env, EA, oi);
81
@@ -XXX,XX +XXX,XX @@ static void process_op_defs(TCGContext *s)
136
+ } else {
82
for (op = 0; op < NB_OPS; op++) {
137
+ tcg_gen_movi_i32(oi, make_memop_idx(MO_BEQ, ctx->mem_idx));
83
TCGOpDef *def = &tcg_op_defs[op];
138
+ gen_helper_lq_be_parallel(lo, cpu_env, EA, oi);
84
const TCGTargetOpDef *tdefs;
139
+ }
85
- TCGType type;
140
+ tcg_temp_free_i32(oi);
86
int i, nb_args;
141
+ tcg_gen_ld_i64(hi, cpu_env, offsetof(CPUPPCState, retxh));
87
142
} else {
88
if (def->flags & TCG_OPF_NOT_PRESENT) {
143
- tcg_gen_movi_i32(oi, make_memop_idx(MO_BEQ, ctx->mem_idx));
89
@@ -XXX,XX +XXX,XX @@ static void process_op_defs(TCGContext *s)
144
- gen_helper_lq_be_parallel(lo, cpu_env, EA, oi);
90
/* Missing TCGTargetOpDef entry. */
145
+ /* Restart with exclusive lock. */
91
tcg_debug_assert(tdefs != NULL);
146
+ gen_helper_exit_atomic(cpu_env);
92
147
+ ctx->base.is_jmp = DISAS_NORETURN;
93
- type = (def->flags & TCG_OPF_64BIT ? TCG_TYPE_I64 : TCG_TYPE_I32);
148
}
94
for (i = 0; i < nb_args; i++) {
149
- tcg_temp_free_i32(oi);
95
const char *ct_str = tdefs->args_ct_str[i];
150
- tcg_gen_ld_i64(hi, cpu_env, offsetof(CPUPPCState, retxh));
96
/* Incomplete TCGTargetOpDef entry. */
151
-#else
97
@@ -XXX,XX +XXX,XX @@ static void process_op_defs(TCGContext *s)
152
- /* Restart with exclusive lock. */
98
def->args_ct[i].ct |= TCG_CT_CONST;
153
- gen_helper_exit_atomic(cpu_env);
99
ct_str++;
154
- ctx->base.is_jmp = DISAS_NORETURN;
100
break;
155
-#endif
101
+
156
} else if (ctx->le_mode) {
102
+#ifdef TCG_TARGET_CON_STR_H
157
tcg_gen_qemu_ld_i64(lo, EA, ctx->mem_idx, MO_LEQ);
103
+ /* Include all of the target-specific constraints. */
158
gen_addr_add(ctx, EA, EA, 8);
104
+
159
@@ -XXX,XX +XXX,XX @@ static void gen_std(DisasContext *ctx)
105
+#undef CONST
160
hi = cpu_gpr[rs];
106
+#define CONST(CASE, MASK) \
161
107
+ case CASE: def->args_ct[i].ct |= MASK; ct_str++; break;
162
if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
108
+#define REGS(CASE, MASK) \
163
-#ifdef CONFIG_ATOMIC128
109
+ case CASE: def->args_ct[i].regs |= MASK; ct_str++; break;
164
- TCGv_i32 oi = tcg_temp_new_i32();
110
+
165
- if (ctx->le_mode) {
111
+#include "tcg-target-con-str.h"
166
- tcg_gen_movi_i32(oi, make_memop_idx(MO_LEQ, ctx->mem_idx));
112
+
167
- gen_helper_stq_le_parallel(cpu_env, EA, lo, hi, oi);
113
+#undef REGS
168
+ if (HAVE_ATOMIC128) {
114
+#undef CONST
169
+ TCGv_i32 oi = tcg_temp_new_i32();
115
default:
170
+ if (ctx->le_mode) {
116
- ct_str = target_parse_constraint(&def->args_ct[i],
171
+ tcg_gen_movi_i32(oi, make_memop_idx(MO_LEQ, ctx->mem_idx));
117
- ct_str, type);
172
+ gen_helper_stq_le_parallel(cpu_env, EA, lo, hi, oi);
118
/* Typo in TCGTargetOpDef constraint. */
173
+ } else {
119
- tcg_debug_assert(ct_str != NULL);
174
+ tcg_gen_movi_i32(oi, make_memop_idx(MO_BEQ, ctx->mem_idx));
120
+ g_assert_not_reached();
175
+ gen_helper_stq_be_parallel(cpu_env, EA, lo, hi, oi);
121
+#else
176
+ }
122
+ default:
177
+ tcg_temp_free_i32(oi);
123
+ {
178
} else {
124
+ TCGType type = (def->flags & TCG_OPF_64BIT
179
- tcg_gen_movi_i32(oi, make_memop_idx(MO_BEQ, ctx->mem_idx));
125
+ ? TCG_TYPE_I64 : TCG_TYPE_I32);
180
- gen_helper_stq_be_parallel(cpu_env, EA, lo, hi, oi);
126
+ ct_str = target_parse_constraint(&def->args_ct[i],
181
+ /* Restart with exclusive lock. */
127
+ ct_str, type);
182
+ gen_helper_exit_atomic(cpu_env);
128
+ /* Typo in TCGTargetOpDef constraint. */
183
+ ctx->base.is_jmp = DISAS_NORETURN;
129
+ tcg_debug_assert(ct_str != NULL);
130
+ }
131
+#endif
132
}
133
}
184
}
185
- tcg_temp_free_i32(oi);
186
-#else
187
- /* Restart with exclusive lock. */
188
- gen_helper_exit_atomic(cpu_env);
189
- ctx->base.is_jmp = DISAS_NORETURN;
190
-#endif
191
} else if (ctx->le_mode) {
192
tcg_gen_qemu_st_i64(lo, EA, ctx->mem_idx, MO_LEQ);
193
gen_addr_add(ctx, EA, EA, 8);
194
@@ -XXX,XX +XXX,XX @@ static void gen_lqarx(DisasContext *ctx)
195
hi = cpu_gpr[rd];
196
197
if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
198
-#ifdef CONFIG_ATOMIC128
199
- TCGv_i32 oi = tcg_temp_new_i32();
200
- if (ctx->le_mode) {
201
- tcg_gen_movi_i32(oi, make_memop_idx(MO_LEQ | MO_ALIGN_16,
202
- ctx->mem_idx));
203
- gen_helper_lq_le_parallel(lo, cpu_env, EA, oi);
204
+ if (HAVE_ATOMIC128) {
205
+ TCGv_i32 oi = tcg_temp_new_i32();
206
+ if (ctx->le_mode) {
207
+ tcg_gen_movi_i32(oi, make_memop_idx(MO_LEQ | MO_ALIGN_16,
208
+ ctx->mem_idx));
209
+ gen_helper_lq_le_parallel(lo, cpu_env, EA, oi);
210
+ } else {
211
+ tcg_gen_movi_i32(oi, make_memop_idx(MO_BEQ | MO_ALIGN_16,
212
+ ctx->mem_idx));
213
+ gen_helper_lq_be_parallel(lo, cpu_env, EA, oi);
214
+ }
215
+ tcg_temp_free_i32(oi);
216
+ tcg_gen_ld_i64(hi, cpu_env, offsetof(CPUPPCState, retxh));
217
} else {
218
- tcg_gen_movi_i32(oi, make_memop_idx(MO_BEQ | MO_ALIGN_16,
219
- ctx->mem_idx));
220
- gen_helper_lq_be_parallel(lo, cpu_env, EA, oi);
221
+ /* Restart with exclusive lock. */
222
+ gen_helper_exit_atomic(cpu_env);
223
+ ctx->base.is_jmp = DISAS_NORETURN;
224
+ tcg_temp_free(EA);
225
+ return;
134
}
226
}
135
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
227
- tcg_temp_free_i32(oi);
136
index XXXXXXX..XXXXXXX 100644
228
- tcg_gen_ld_i64(hi, cpu_env, offsetof(CPUPPCState, retxh));
137
--- a/tcg/i386/tcg-target.c.inc
229
-#else
138
+++ b/tcg/i386/tcg-target.c.inc
230
- /* Restart with exclusive lock. */
139
@@ -XXX,XX +XXX,XX @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
231
- gen_helper_exit_atomic(cpu_env);
140
return true;
232
- ctx->base.is_jmp = DISAS_NORETURN;
141
}
233
- tcg_temp_free(EA);
142
234
- return;
143
-/* parse target specific constraints */
235
-#endif
144
-static const char *target_parse_constraint(TCGArgConstraint *ct,
236
} else if (ctx->le_mode) {
145
- const char *ct_str, TCGType type)
237
tcg_gen_qemu_ld_i64(lo, EA, ctx->mem_idx, MO_LEQ | MO_ALIGN_16);
146
-{
238
tcg_gen_mov_tl(cpu_reserve, EA);
147
- switch(*ct_str++) {
239
@@ -XXX,XX +XXX,XX @@ static void gen_stqcx_(DisasContext *ctx)
148
- case 'a':
240
hi = cpu_gpr[rs];
149
- tcg_regset_set_reg(ct->regs, TCG_REG_EAX);
241
150
- break;
242
if (tb_cflags(ctx->base.tb) & CF_PARALLEL) {
151
- case 'b':
243
- TCGv_i32 oi = tcg_const_i32(DEF_MEMOP(MO_Q) | MO_ALIGN_16);
152
- tcg_regset_set_reg(ct->regs, TCG_REG_EBX);
244
-#ifdef CONFIG_ATOMIC128
153
- break;
245
- if (ctx->le_mode) {
154
- case 'c':
246
- gen_helper_stqcx_le_parallel(cpu_crf[0], cpu_env, EA, lo, hi, oi);
155
- tcg_regset_set_reg(ct->regs, TCG_REG_ECX);
247
+ if (HAVE_CMPXCHG128) {
156
- break;
248
+ TCGv_i32 oi = tcg_const_i32(DEF_MEMOP(MO_Q) | MO_ALIGN_16);
157
- case 'd':
249
+ if (ctx->le_mode) {
158
- tcg_regset_set_reg(ct->regs, TCG_REG_EDX);
250
+ gen_helper_stqcx_le_parallel(cpu_crf[0], cpu_env,
159
- break;
251
+ EA, lo, hi, oi);
160
- case 'S':
252
+ } else {
161
- tcg_regset_set_reg(ct->regs, TCG_REG_ESI);
253
+ gen_helper_stqcx_be_parallel(cpu_crf[0], cpu_env,
162
- break;
254
+ EA, lo, hi, oi);
163
- case 'D':
255
+ }
164
- tcg_regset_set_reg(ct->regs, TCG_REG_EDI);
256
+ tcg_temp_free_i32(oi);
165
- break;
257
} else {
166
- case 'q':
258
- gen_helper_stqcx_le_parallel(cpu_crf[0], cpu_env, EA, lo, hi, oi);
167
- /* A register that can be used as a byte operand. */
259
+ /* Restart with exclusive lock. */
168
- ct->regs |= ALL_BYTEL_REGS;
260
+ gen_helper_exit_atomic(cpu_env);
169
- break;
261
+ ctx->base.is_jmp = DISAS_NORETURN;
170
- case 'Q':
262
}
171
- /* A register with an addressable second byte (e.g. %ah). */
263
-#else
172
- ct->regs |= ALL_BYTEH_REGS;
264
- /* Restart with exclusive lock. */
173
- break;
265
- gen_helper_exit_atomic(cpu_env);
174
- case 'r':
266
- ctx->base.is_jmp = DISAS_NORETURN;
175
- /* A general register. */
267
-#endif
176
- ct->regs |= ALL_GENERAL_REGS;
268
tcg_temp_free(EA);
177
- break;
269
- tcg_temp_free_i32(oi);
178
- case 'W':
270
} else {
179
- /* With TZCNT/LZCNT, we can have operand-size as an input. */
271
TCGLabel *lab_fail = gen_new_label();
180
- ct->ct |= TCG_CT_CONST_WSZ;
272
TCGLabel *lab_over = gen_new_label();
181
- break;
182
- case 'x':
183
- /* A vector register. */
184
- ct->regs |= ALL_VECTOR_REGS;
185
- break;
186
-
187
- case 'L':
188
- /* qemu_ld/st data+address constraint */
189
- ct->regs |= ALL_GENERAL_REGS & ~SOFTMMU_RESERVE_REGS;
190
- break;
191
- case 's':
192
- /* qemu_st8_i32 data constraint */
193
- ct->regs |= ALL_BYTEL_REGS & ~SOFTMMU_RESERVE_REGS;
194
- break;
195
-
196
- case 'e':
197
- ct->ct |= TCG_CT_CONST_S32;
198
- break;
199
- case 'Z':
200
- ct->ct |= TCG_CT_CONST_U32;
201
- break;
202
- case 'I':
203
- ct->ct |= TCG_CT_CONST_I32;
204
- break;
205
-
206
- default:
207
- return NULL;
208
- }
209
- return ct_str;
210
-}
211
-
212
/* test if a constant matches the constraint */
213
static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
214
const TCGArgConstraint *arg_ct)
215
--
273
--
216
2.25.1
274
2.17.2
217
275
218
276
diff view generated by jsdifflib
1
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
1
Reviewed-by: David Hildenbrand <david@redhat.com>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
3
---
4
tcg/aarch64/tcg-target-con-set.h | 36 +++++++++++++
4
target/s390x/mem_helper.c | 92 +++++++++++++++++----------------------
5
tcg/aarch64/tcg-target.h | 1 +
5
1 file changed, 41 insertions(+), 51 deletions(-)
6
tcg/aarch64/tcg-target.c.inc | 86 +++++++++++---------------------
7
3 files changed, 65 insertions(+), 58 deletions(-)
8
create mode 100644 tcg/aarch64/tcg-target-con-set.h
9
6
10
diff --git a/tcg/aarch64/tcg-target-con-set.h b/tcg/aarch64/tcg-target-con-set.h
7
diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
11
new file mode 100644
8
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX
9
--- a/target/s390x/mem_helper.c
13
--- /dev/null
10
+++ b/target/s390x/mem_helper.c
14
+++ b/tcg/aarch64/tcg-target-con-set.h
15
@@ -XXX,XX +XXX,XX @@
11
@@ -XXX,XX +XXX,XX @@
16
+/* SPDX-License-Identifier: GPL-2.0-or-later */
12
#include "exec/exec-all.h"
17
+/*
13
#include "exec/cpu_ldst.h"
18
+ * Define AArch64 target-specific constraint sets.
14
#include "qemu/int128.h"
19
+ * Copyright (c) 2021 Linaro
15
+#include "qemu/atomic128.h"
20
+ */
16
21
+
17
#if !defined(CONFIG_USER_ONLY)
22
+/*
18
#include "hw/s390x/storage-keys.h"
23
+ * C_On_Im(...) defines a constraint set with <n> outputs and <m> inputs.
19
@@ -XXX,XX +XXX,XX @@ static void do_cdsg(CPUS390XState *env, uint64_t addr,
24
+ * Each operand should be a sequence of constraint letters as defined by
20
bool fail;
25
+ * tcg-target-con-str.h; the constraint combination is inclusive or.
21
26
+ */
22
if (parallel) {
27
+C_O0_I1(r)
23
-#ifndef CONFIG_ATOMIC128
28
+C_O0_I2(lZ, l)
24
+#if !HAVE_CMPXCHG128
29
+C_O0_I2(r, rA)
25
cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
30
+C_O0_I2(rZ, r)
26
#else
31
+C_O0_I2(w, r)
27
int mem_idx = cpu_mmu_index(env, false);
32
+C_O1_I1(r, l)
28
@@ -XXX,XX +XXX,XX @@ void HELPER(cdsg_parallel)(CPUS390XState *env, uint64_t addr,
33
+C_O1_I1(r, r)
29
static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
34
+C_O1_I1(w, r)
30
uint64_t a2, bool parallel)
35
+C_O1_I1(w, w)
31
{
36
+C_O1_I1(w, wr)
32
-#if !defined(CONFIG_USER_ONLY) || defined(CONFIG_ATOMIC128)
37
+C_O1_I2(r, 0, rZ)
33
uint32_t mem_idx = cpu_mmu_index(env, false);
38
+C_O1_I2(r, r, r)
34
-#endif
39
+C_O1_I2(r, r, rA)
35
uintptr_t ra = GETPC();
40
+C_O1_I2(r, r, rAL)
36
uint32_t fc = extract32(env->regs[0], 0, 8);
41
+C_O1_I2(r, r, ri)
37
uint32_t sc = extract32(env->regs[0], 8, 8);
42
+C_O1_I2(r, r, rL)
38
@@ -XXX,XX +XXX,XX @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
43
+C_O1_I2(r, rZ, rZ)
39
probe_write(env, a2, 0, mem_idx, ra);
44
+C_O1_I2(w, 0, w)
45
+C_O1_I2(w, w, w)
46
+C_O1_I2(w, w, wN)
47
+C_O1_I2(w, w, wO)
48
+C_O1_I2(w, w, wZ)
49
+C_O1_I3(w, w, w, w)
50
+C_O1_I4(r, r, rA, rZ, rZ)
51
+C_O2_I4(r, r, rZ, rZ, rA, rMZ)
52
diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h
53
index XXXXXXX..XXXXXXX 100644
54
--- a/tcg/aarch64/tcg-target.h
55
+++ b/tcg/aarch64/tcg-target.h
56
@@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
57
#define TCG_TARGET_NEED_LDST_LABELS
58
#endif
40
#endif
59
#define TCG_TARGET_NEED_POOL_LABELS
41
60
+#define TCG_TARGET_CON_SET_H
42
- /* Note that the compare-and-swap is atomic, and the store is atomic, but
61
43
- the complete operation is not. Therefore we do not need to assert serial
62
#endif /* AARCH64_TCG_TARGET_H */
44
- context in order to implement this. That said, restart early if we can't
63
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
45
- support either operation that is supposed to be atomic. */
64
index XXXXXXX..XXXXXXX 100644
46
+ /*
65
--- a/tcg/aarch64/tcg-target.c.inc
47
+ * Note that the compare-and-swap is atomic, and the store is atomic,
66
+++ b/tcg/aarch64/tcg-target.c.inc
48
+ * but the complete operation is not. Therefore we do not need to
67
@@ -XXX,XX +XXX,XX @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece,
49
+ * assert serial context in order to implement this. That said,
68
va_end(va);
50
+ * restart early if we can't support either operation that is supposed
69
}
51
+ * to be atomic.
70
52
+ */
71
-static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
53
if (parallel) {
72
+static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
54
- int mask = 0;
55
-#if !defined(CONFIG_ATOMIC64)
56
- mask = -8;
57
-#elif !defined(CONFIG_ATOMIC128)
58
- mask = -16;
59
+ uint32_t max = 2;
60
+#ifdef CONFIG_ATOMIC64
61
+ max = 3;
62
#endif
63
- if (((4 << fc) | (1 << sc)) & mask) {
64
+ if ((HAVE_CMPXCHG128 ? 0 : fc + 2 > max) ||
65
+ (HAVE_ATOMIC128 ? 0 : sc > max)) {
66
cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
67
}
68
}
69
@@ -XXX,XX +XXX,XX @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
70
Int128 cv = int128_make128(env->regs[r3 + 1], env->regs[r3]);
71
Int128 ov;
72
73
- if (parallel) {
74
-#ifdef CONFIG_ATOMIC128
75
- TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
76
- ov = helper_atomic_cmpxchgo_be_mmu(env, a1, cv, nv, oi, ra);
77
- cc = !int128_eq(ov, cv);
78
-#else
79
- /* Note that we asserted !parallel above. */
80
- g_assert_not_reached();
81
-#endif
82
- } else {
83
+ if (!parallel) {
84
uint64_t oh = cpu_ldq_data_ra(env, a1 + 0, ra);
85
uint64_t ol = cpu_ldq_data_ra(env, a1 + 8, ra);
86
87
@@ -XXX,XX +XXX,XX @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
88
89
cpu_stq_data_ra(env, a1 + 0, int128_gethi(nv), ra);
90
cpu_stq_data_ra(env, a1 + 8, int128_getlo(nv), ra);
91
+ } else if (HAVE_CMPXCHG128) {
92
+ TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
93
+ ov = helper_atomic_cmpxchgo_be_mmu(env, a1, cv, nv, oi, ra);
94
+ cc = !int128_eq(ov, cv);
95
+ } else {
96
+ /* Note that we asserted !parallel above. */
97
+ g_assert_not_reached();
98
}
99
100
env->regs[r3 + 0] = int128_gethi(ov);
101
@@ -XXX,XX +XXX,XX @@ static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
102
cpu_stq_data_ra(env, a2, svh, ra);
103
break;
104
case 4:
105
- if (parallel) {
106
-#ifdef CONFIG_ATOMIC128
107
+ if (!parallel) {
108
+ cpu_stq_data_ra(env, a2 + 0, svh, ra);
109
+ cpu_stq_data_ra(env, a2 + 8, svl, ra);
110
+ } else if (HAVE_ATOMIC128) {
111
TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
112
Int128 sv = int128_make128(svl, svh);
113
helper_atomic_sto_be_mmu(env, a2, sv, oi, ra);
114
-#else
115
+ } else {
116
/* Note that we asserted !parallel above. */
117
g_assert_not_reached();
118
-#endif
119
- } else {
120
- cpu_stq_data_ra(env, a2 + 0, svh, ra);
121
- cpu_stq_data_ra(env, a2 + 8, svl, ra);
122
}
123
break;
124
default:
125
@@ -XXX,XX +XXX,XX @@ static uint64_t do_lpq(CPUS390XState *env, uint64_t addr, bool parallel)
126
uintptr_t ra = GETPC();
127
uint64_t hi, lo;
128
129
- if (parallel) {
130
-#ifndef CONFIG_ATOMIC128
131
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
132
-#else
133
+ if (!parallel) {
134
+ check_alignment(env, addr, 16, ra);
135
+ hi = cpu_ldq_data_ra(env, addr + 0, ra);
136
+ lo = cpu_ldq_data_ra(env, addr + 8, ra);
137
+ } else if (HAVE_ATOMIC128) {
138
int mem_idx = cpu_mmu_index(env, false);
139
TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
140
Int128 v = helper_atomic_ldo_be_mmu(env, addr, oi, ra);
141
hi = int128_gethi(v);
142
lo = int128_getlo(v);
143
-#endif
144
} else {
145
- check_alignment(env, addr, 16, ra);
146
-
147
- hi = cpu_ldq_data_ra(env, addr + 0, ra);
148
- lo = cpu_ldq_data_ra(env, addr + 8, ra);
149
+ cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
150
}
151
152
env->retxl = lo;
153
@@ -XXX,XX +XXX,XX @@ static void do_stpq(CPUS390XState *env, uint64_t addr,
73
{
154
{
74
- static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
155
uintptr_t ra = GETPC();
75
- static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
156
76
- static const TCGTargetOpDef w_w = { .args_ct_str = { "w", "w" } };
157
- if (parallel) {
77
- static const TCGTargetOpDef w_r = { .args_ct_str = { "w", "r" } };
158
-#ifndef CONFIG_ATOMIC128
78
- static const TCGTargetOpDef w_wr = { .args_ct_str = { "w", "wr" } };
159
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
79
- static const TCGTargetOpDef r_l = { .args_ct_str = { "r", "l" } };
160
-#else
80
- static const TCGTargetOpDef r_rA = { .args_ct_str = { "r", "rA" } };
161
- int mem_idx = cpu_mmu_index(env, false);
81
- static const TCGTargetOpDef rZ_r = { .args_ct_str = { "rZ", "r" } };
162
- TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
82
- static const TCGTargetOpDef lZ_l = { .args_ct_str = { "lZ", "l" } };
83
- static const TCGTargetOpDef r_r_r = { .args_ct_str = { "r", "r", "r" } };
84
- static const TCGTargetOpDef w_w_w = { .args_ct_str = { "w", "w", "w" } };
85
- static const TCGTargetOpDef w_0_w = { .args_ct_str = { "w", "0", "w" } };
86
- static const TCGTargetOpDef w_w_wO = { .args_ct_str = { "w", "w", "wO" } };
87
- static const TCGTargetOpDef w_w_wN = { .args_ct_str = { "w", "w", "wN" } };
88
- static const TCGTargetOpDef w_w_wZ = { .args_ct_str = { "w", "w", "wZ" } };
89
- static const TCGTargetOpDef r_r_ri = { .args_ct_str = { "r", "r", "ri" } };
90
- static const TCGTargetOpDef r_r_rA = { .args_ct_str = { "r", "r", "rA" } };
91
- static const TCGTargetOpDef r_r_rL = { .args_ct_str = { "r", "r", "rL" } };
92
- static const TCGTargetOpDef r_r_rAL
93
- = { .args_ct_str = { "r", "r", "rAL" } };
94
- static const TCGTargetOpDef dep
95
- = { .args_ct_str = { "r", "0", "rZ" } };
96
- static const TCGTargetOpDef ext2
97
- = { .args_ct_str = { "r", "rZ", "rZ" } };
98
- static const TCGTargetOpDef movc
99
- = { .args_ct_str = { "r", "r", "rA", "rZ", "rZ" } };
100
- static const TCGTargetOpDef add2
101
- = { .args_ct_str = { "r", "r", "rZ", "rZ", "rA", "rMZ" } };
102
- static const TCGTargetOpDef w_w_w_w
103
- = { .args_ct_str = { "w", "w", "w", "w" } };
104
-
163
-
105
switch (op) {
164
- Int128 v = int128_make128(low, high);
106
case INDEX_op_goto_ptr:
165
- helper_atomic_sto_be_mmu(env, addr, v, oi, ra);
107
- return &r;
166
-#endif
108
+ return C_O0_I1(r);
167
- } else {
109
168
+ if (!parallel) {
110
case INDEX_op_ld8u_i32:
169
check_alignment(env, addr, 16, ra);
111
case INDEX_op_ld8s_i32:
170
-
112
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
171
cpu_stq_data_ra(env, addr + 0, high, ra);
113
case INDEX_op_extract_i64:
172
cpu_stq_data_ra(env, addr + 8, low, ra);
114
case INDEX_op_sextract_i32:
173
+ } else if (HAVE_ATOMIC128) {
115
case INDEX_op_sextract_i64:
174
+ int mem_idx = cpu_mmu_index(env, false);
116
- return &r_r;
175
+ TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
117
+ return C_O1_I1(r, r);
176
+ Int128 v = int128_make128(low, high);
118
177
+ helper_atomic_sto_be_mmu(env, addr, v, oi, ra);
119
case INDEX_op_st8_i32:
178
+ } else {
120
case INDEX_op_st16_i32:
179
+ cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
121
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
122
case INDEX_op_st16_i64:
123
case INDEX_op_st32_i64:
124
case INDEX_op_st_i64:
125
- return &rZ_r;
126
+ return C_O0_I2(rZ, r);
127
128
case INDEX_op_add_i32:
129
case INDEX_op_add_i64:
130
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
131
case INDEX_op_sub_i64:
132
case INDEX_op_setcond_i32:
133
case INDEX_op_setcond_i64:
134
- return &r_r_rA;
135
+ return C_O1_I2(r, r, rA);
136
137
case INDEX_op_mul_i32:
138
case INDEX_op_mul_i64:
139
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
140
case INDEX_op_remu_i64:
141
case INDEX_op_muluh_i64:
142
case INDEX_op_mulsh_i64:
143
- return &r_r_r;
144
+ return C_O1_I2(r, r, r);
145
146
case INDEX_op_and_i32:
147
case INDEX_op_and_i64:
148
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
149
case INDEX_op_orc_i64:
150
case INDEX_op_eqv_i32:
151
case INDEX_op_eqv_i64:
152
- return &r_r_rL;
153
+ return C_O1_I2(r, r, rL);
154
155
case INDEX_op_shl_i32:
156
case INDEX_op_shr_i32:
157
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
158
case INDEX_op_sar_i64:
159
case INDEX_op_rotl_i64:
160
case INDEX_op_rotr_i64:
161
- return &r_r_ri;
162
+ return C_O1_I2(r, r, ri);
163
164
case INDEX_op_clz_i32:
165
case INDEX_op_ctz_i32:
166
case INDEX_op_clz_i64:
167
case INDEX_op_ctz_i64:
168
- return &r_r_rAL;
169
+ return C_O1_I2(r, r, rAL);
170
171
case INDEX_op_brcond_i32:
172
case INDEX_op_brcond_i64:
173
- return &r_rA;
174
+ return C_O0_I2(r, rA);
175
176
case INDEX_op_movcond_i32:
177
case INDEX_op_movcond_i64:
178
- return &movc;
179
+ return C_O1_I4(r, r, rA, rZ, rZ);
180
181
case INDEX_op_qemu_ld_i32:
182
case INDEX_op_qemu_ld_i64:
183
- return &r_l;
184
+ return C_O1_I1(r, l);
185
case INDEX_op_qemu_st_i32:
186
case INDEX_op_qemu_st_i64:
187
- return &lZ_l;
188
+ return C_O0_I2(lZ, l);
189
190
case INDEX_op_deposit_i32:
191
case INDEX_op_deposit_i64:
192
- return &dep;
193
+ return C_O1_I2(r, 0, rZ);
194
195
case INDEX_op_extract2_i32:
196
case INDEX_op_extract2_i64:
197
- return &ext2;
198
+ return C_O1_I2(r, rZ, rZ);
199
200
case INDEX_op_add2_i32:
201
case INDEX_op_add2_i64:
202
case INDEX_op_sub2_i32:
203
case INDEX_op_sub2_i64:
204
- return &add2;
205
+ return C_O2_I4(r, r, rZ, rZ, rA, rMZ);
206
207
case INDEX_op_add_vec:
208
case INDEX_op_sub_vec:
209
@@ -XXX,XX +XXX,XX @@ static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
210
case INDEX_op_shrv_vec:
211
case INDEX_op_sarv_vec:
212
case INDEX_op_aa64_sshl_vec:
213
- return &w_w_w;
214
+ return C_O1_I2(w, w, w);
215
case INDEX_op_not_vec:
216
case INDEX_op_neg_vec:
217
case INDEX_op_abs_vec:
218
case INDEX_op_shli_vec:
219
case INDEX_op_shri_vec:
220
case INDEX_op_sari_vec:
221
- return &w_w;
222
+ return C_O1_I1(w, w);
223
case INDEX_op_ld_vec:
224
- case INDEX_op_st_vec:
225
case INDEX_op_dupm_vec:
226
- return &w_r;
227
+ return C_O1_I1(w, r);
228
+ case INDEX_op_st_vec:
229
+ return C_O0_I2(w, r);
230
case INDEX_op_dup_vec:
231
- return &w_wr;
232
+ return C_O1_I1(w, wr);
233
case INDEX_op_or_vec:
234
case INDEX_op_andc_vec:
235
- return &w_w_wO;
236
+ return C_O1_I2(w, w, wO);
237
case INDEX_op_and_vec:
238
case INDEX_op_orc_vec:
239
- return &w_w_wN;
240
+ return C_O1_I2(w, w, wN);
241
case INDEX_op_cmp_vec:
242
- return &w_w_wZ;
243
+ return C_O1_I2(w, w, wZ);
244
case INDEX_op_bitsel_vec:
245
- return &w_w_w_w;
246
+ return C_O1_I3(w, w, w, w);
247
case INDEX_op_aa64_sli_vec:
248
- return &w_0_w;
249
+ return C_O1_I2(w, 0, w);
250
251
default:
252
- return NULL;
253
+ g_assert_not_reached();
254
}
180
}
255
}
181
}
256
182
257
--
183
--
258
2.25.1
184
2.17.2
259
185
260
186
diff view generated by jsdifflib
1
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
1
Reviewed-by: David Hildenbrand <david@redhat.com>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
3
---
4
tcg/riscv/tcg-target-con-str.h | 21 ++++++++++++++
4
target/s390x/mem_helper.c | 128 ++++++++++++++++++--------------------
5
tcg/riscv/tcg-target.h | 1 +
5
1 file changed, 61 insertions(+), 67 deletions(-)
6
tcg/riscv/tcg-target.c.inc | 52 +++++++++-------------------------
7
3 files changed, 35 insertions(+), 39 deletions(-)
8
create mode 100644 tcg/riscv/tcg-target-con-str.h
9
6
10
diff --git a/tcg/riscv/tcg-target-con-str.h b/tcg/riscv/tcg-target-con-str.h
7
diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
11
new file mode 100644
8
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX
9
--- a/target/s390x/mem_helper.c
13
--- /dev/null
10
+++ b/target/s390x/mem_helper.c
14
+++ b/tcg/riscv/tcg-target-con-str.h
11
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(trXX)(CPUS390XState *env, uint32_t r1, uint32_t r2,
15
@@ -XXX,XX +XXX,XX @@
12
return cc;
16
+/* SPDX-License-Identifier: MIT */
13
}
17
+/*
14
18
+ * Define RISC-V target-specific operand constraints.
15
-static void do_cdsg(CPUS390XState *env, uint64_t addr,
19
+ * Copyright (c) 2021 Linaro
16
- uint32_t r1, uint32_t r3, bool parallel)
20
+ */
17
+void HELPER(cdsg)(CPUS390XState *env, uint64_t addr,
18
+ uint32_t r1, uint32_t r3)
19
{
20
uintptr_t ra = GETPC();
21
Int128 cmpv = int128_make128(env->regs[r1 + 1], env->regs[r1]);
22
Int128 newv = int128_make128(env->regs[r3 + 1], env->regs[r3]);
23
Int128 oldv;
24
+ uint64_t oldh, oldl;
25
bool fail;
26
27
- if (parallel) {
28
-#if !HAVE_CMPXCHG128
29
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
30
-#else
31
- int mem_idx = cpu_mmu_index(env, false);
32
- TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
33
- oldv = helper_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, oi, ra);
34
- fail = !int128_eq(oldv, cmpv);
35
-#endif
36
- } else {
37
- uint64_t oldh, oldl;
38
+ check_alignment(env, addr, 16, ra);
39
40
- check_alignment(env, addr, 16, ra);
41
+ oldh = cpu_ldq_data_ra(env, addr + 0, ra);
42
+ oldl = cpu_ldq_data_ra(env, addr + 8, ra);
43
44
- oldh = cpu_ldq_data_ra(env, addr + 0, ra);
45
- oldl = cpu_ldq_data_ra(env, addr + 8, ra);
46
-
47
- oldv = int128_make128(oldl, oldh);
48
- fail = !int128_eq(oldv, cmpv);
49
- if (fail) {
50
- newv = oldv;
51
- }
52
-
53
- cpu_stq_data_ra(env, addr + 0, int128_gethi(newv), ra);
54
- cpu_stq_data_ra(env, addr + 8, int128_getlo(newv), ra);
55
+ oldv = int128_make128(oldl, oldh);
56
+ fail = !int128_eq(oldv, cmpv);
57
+ if (fail) {
58
+ newv = oldv;
59
}
60
61
+ cpu_stq_data_ra(env, addr + 0, int128_gethi(newv), ra);
62
+ cpu_stq_data_ra(env, addr + 8, int128_getlo(newv), ra);
21
+
63
+
22
+/*
64
env->cc_op = fail;
23
+ * Define constraint letters for register sets:
65
env->regs[r1] = int128_gethi(oldv);
24
+ * REGS(letter, register_mask)
66
env->regs[r1 + 1] = int128_getlo(oldv);
25
+ */
67
}
26
+REGS('r', ALL_GENERAL_REGS)
68
27
+REGS('L', ALL_GENERAL_REGS & ~SOFTMMU_RESERVE_REGS)
69
-void HELPER(cdsg)(CPUS390XState *env, uint64_t addr,
70
- uint32_t r1, uint32_t r3)
71
-{
72
- do_cdsg(env, addr, r1, r3, false);
73
-}
74
-
75
void HELPER(cdsg_parallel)(CPUS390XState *env, uint64_t addr,
76
uint32_t r1, uint32_t r3)
77
{
78
- do_cdsg(env, addr, r1, r3, true);
79
+ uintptr_t ra = GETPC();
80
+ Int128 cmpv = int128_make128(env->regs[r1 + 1], env->regs[r1]);
81
+ Int128 newv = int128_make128(env->regs[r3 + 1], env->regs[r3]);
82
+ int mem_idx;
83
+ TCGMemOpIdx oi;
84
+ Int128 oldv;
85
+ bool fail;
28
+
86
+
29
+/*
87
+ if (!HAVE_CMPXCHG128) {
30
+ * Define constraint letters for constants:
88
+ cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
31
+ * CONST(letter, TCG_CT_CONST_* bit set)
89
+ }
32
+ */
90
+
33
+CONST('I', TCG_CT_CONST_S12)
91
+ mem_idx = cpu_mmu_index(env, false);
34
+CONST('N', TCG_CT_CONST_N12)
92
+ oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
35
+CONST('M', TCG_CT_CONST_M12)
93
+ oldv = helper_atomic_cmpxchgo_be_mmu(env, addr, cmpv, newv, oi, ra);
36
+CONST('Z', TCG_CT_CONST_ZERO)
94
+ fail = !int128_eq(oldv, cmpv);
37
diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
95
+
38
index XXXXXXX..XXXXXXX 100644
96
+ env->cc_op = fail;
39
--- a/tcg/riscv/tcg-target.h
97
+ env->regs[r1] = int128_gethi(oldv);
40
+++ b/tcg/riscv/tcg-target.h
98
+ env->regs[r1 + 1] = int128_getlo(oldv);
41
@@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
99
}
42
#define TCG_TARGET_NEED_POOL_LABELS
100
43
101
static uint32_t do_csst(CPUS390XState *env, uint32_t r3, uint64_t a1,
44
#define TCG_TARGET_HAS_MEMORY_BSWAP 0
102
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(lra)(CPUS390XState *env, uint64_t addr)
45
+#define TCG_TARGET_CON_STR_H
46
47
#endif
103
#endif
48
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
104
49
index XXXXXXX..XXXXXXX 100644
105
/* load pair from quadword */
50
--- a/tcg/riscv/tcg-target.c.inc
106
-static uint64_t do_lpq(CPUS390XState *env, uint64_t addr, bool parallel)
51
+++ b/tcg/riscv/tcg-target.c.inc
107
+uint64_t HELPER(lpq)(CPUS390XState *env, uint64_t addr)
52
@@ -XXX,XX +XXX,XX @@ static const int tcg_target_call_oarg_regs[] = {
108
{
53
#define TCG_CT_CONST_N12 0x400
109
uintptr_t ra = GETPC();
54
#define TCG_CT_CONST_M12 0x800
110
uint64_t hi, lo;
55
111
56
+#define ALL_GENERAL_REGS MAKE_64BIT_MASK(0, 32)
112
- if (!parallel) {
57
+/*
113
- check_alignment(env, addr, 16, ra);
58
+ * For softmmu, we need to avoid conflicts with the first 5
114
- hi = cpu_ldq_data_ra(env, addr + 0, ra);
59
+ * argument registers to call the helper. Some of these are
115
- lo = cpu_ldq_data_ra(env, addr + 8, ra);
60
+ * also used for the tlb lookup.
116
- } else if (HAVE_ATOMIC128) {
61
+ */
117
+ check_alignment(env, addr, 16, ra);
62
+#ifdef CONFIG_SOFTMMU
118
+ hi = cpu_ldq_data_ra(env, addr + 0, ra);
63
+#define SOFTMMU_RESERVE_REGS MAKE_64BIT_MASK(TCG_REG_A0, 5)
119
+ lo = cpu_ldq_data_ra(env, addr + 8, ra);
64
+#else
65
+#define SOFTMMU_RESERVE_REGS 0
66
+#endif
67
+
120
+
121
+ env->retxl = lo;
122
+ return hi;
123
+}
68
+
124
+
69
static inline tcg_target_long sextreg(tcg_target_long val, int pos, int len)
125
+uint64_t HELPER(lpq_parallel)(CPUS390XState *env, uint64_t addr)
126
+{
127
+ uintptr_t ra = GETPC();
128
+ uint64_t hi, lo;
129
+
130
+ if (HAVE_ATOMIC128) {
131
int mem_idx = cpu_mmu_index(env, false);
132
TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
133
Int128 v = helper_atomic_ldo_be_mmu(env, addr, oi, ra);
134
@@ -XXX,XX +XXX,XX @@ static uint64_t do_lpq(CPUS390XState *env, uint64_t addr, bool parallel)
135
return hi;
136
}
137
138
-uint64_t HELPER(lpq)(CPUS390XState *env, uint64_t addr)
139
-{
140
- return do_lpq(env, addr, false);
141
-}
142
-
143
-uint64_t HELPER(lpq_parallel)(CPUS390XState *env, uint64_t addr)
144
-{
145
- return do_lpq(env, addr, true);
146
-}
147
-
148
/* store pair to quadword */
149
-static void do_stpq(CPUS390XState *env, uint64_t addr,
150
- uint64_t low, uint64_t high, bool parallel)
151
+void HELPER(stpq)(CPUS390XState *env, uint64_t addr,
152
+ uint64_t low, uint64_t high)
70
{
153
{
71
if (TCG_TARGET_REG_BITS == 32) {
154
uintptr_t ra = GETPC();
72
@@ -XXX,XX +XXX,XX @@ static inline tcg_target_long sextreg(tcg_target_long val, int pos, int len)
155
156
- if (!parallel) {
157
- check_alignment(env, addr, 16, ra);
158
- cpu_stq_data_ra(env, addr + 0, high, ra);
159
- cpu_stq_data_ra(env, addr + 8, low, ra);
160
- } else if (HAVE_ATOMIC128) {
161
+ check_alignment(env, addr, 16, ra);
162
+ cpu_stq_data_ra(env, addr + 0, high, ra);
163
+ cpu_stq_data_ra(env, addr + 8, low, ra);
164
+}
165
+
166
+void HELPER(stpq_parallel)(CPUS390XState *env, uint64_t addr,
167
+ uint64_t low, uint64_t high)
168
+{
169
+ uintptr_t ra = GETPC();
170
+
171
+ if (HAVE_ATOMIC128) {
172
int mem_idx = cpu_mmu_index(env, false);
173
TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
174
Int128 v = int128_make128(low, high);
175
@@ -XXX,XX +XXX,XX @@ static void do_stpq(CPUS390XState *env, uint64_t addr,
73
}
176
}
74
}
177
}
75
178
76
-/* parse target specific constraints */
179
-void HELPER(stpq)(CPUS390XState *env, uint64_t addr,
77
-static const char *target_parse_constraint(TCGArgConstraint *ct,
180
- uint64_t low, uint64_t high)
78
- const char *ct_str, TCGType type)
79
-{
181
-{
80
- switch (*ct_str++) {
182
- do_stpq(env, addr, low, high, false);
81
- case 'r':
82
- ct->regs = 0xffffffff;
83
- break;
84
- case 'L':
85
- /* qemu_ld/qemu_st constraint */
86
- ct->regs = 0xffffffff;
87
- /* qemu_ld/qemu_st uses TCG_REG_TMP0 */
88
-#if defined(CONFIG_SOFTMMU)
89
- tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[0]);
90
- tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[1]);
91
- tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[2]);
92
- tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[3]);
93
- tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[4]);
94
-#endif
95
- break;
96
- case 'I':
97
- ct->ct |= TCG_CT_CONST_S12;
98
- break;
99
- case 'N':
100
- ct->ct |= TCG_CT_CONST_N12;
101
- break;
102
- case 'M':
103
- ct->ct |= TCG_CT_CONST_M12;
104
- break;
105
- case 'Z':
106
- /* we can use a zero immediate as a zero register argument. */
107
- ct->ct |= TCG_CT_CONST_ZERO;
108
- break;
109
- default:
110
- return NULL;
111
- }
112
- return ct_str;
113
-}
183
-}
114
-
184
-
115
/* test if a constant matches the constraint */
185
-void HELPER(stpq_parallel)(CPUS390XState *env, uint64_t addr,
116
static int tcg_target_const_match(tcg_target_long val, TCGType type,
186
- uint64_t low, uint64_t high)
117
const TCGArgConstraint *arg_ct)
187
-{
188
- do_stpq(env, addr, low, high, true);
189
-}
190
-
191
/* Execute instruction. This instruction executes an insn modified with
192
the contents of r1. It does not change the executed instruction in memory;
193
it does not change the program counter.
118
--
194
--
119
2.25.1
195
2.17.2
120
196
121
197
diff view generated by jsdifflib
1
Rather than check the type when filling in the constraint,
1
When op raises an exception, it may not have initialized the output
2
check it when matching the constant. This removes the only
2
temps that would be written back by wout or cout.
3
use of the type argument to target_parse_constraint.
4
3
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: David Hildenbrand <david@redhat.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
6
---
8
tcg/i386/tcg-target.c.inc | 28 +++++++++++++++++-----------
7
target/s390x/translate.c | 20 +++++++++++++++-----
9
1 file changed, 17 insertions(+), 11 deletions(-)
8
1 file changed, 15 insertions(+), 5 deletions(-)
10
9
11
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
10
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
12
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
13
--- a/tcg/i386/tcg-target.c.inc
12
--- a/target/s390x/translate.c
14
+++ b/tcg/i386/tcg-target.c.inc
13
+++ b/target/s390x/translate.c
15
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
14
@@ -XXX,XX +XXX,XX @@ struct DisasInsn {
16
break;
15
17
16
const char *name;
18
case 'e':
17
19
- ct->ct |= (type == TCG_TYPE_I32 ? TCG_CT_CONST : TCG_CT_CONST_S32);
18
+ /* Pre-process arguments before HELP_OP. */
20
+ ct->ct |= TCG_CT_CONST_S32;
19
void (*help_in1)(DisasContext *, DisasFields *, DisasOps *);
21
break;
20
void (*help_in2)(DisasContext *, DisasFields *, DisasOps *);
22
case 'Z':
21
void (*help_prep)(DisasContext *, DisasFields *, DisasOps *);
23
- ct->ct |= (type == TCG_TYPE_I32 ? TCG_CT_CONST : TCG_CT_CONST_U32);
22
+
24
+ ct->ct |= TCG_CT_CONST_U32;
23
+ /*
25
break;
24
+ * Post-process output after HELP_OP.
26
case 'I':
25
+ * Note that these are not called if HELP_OP returns DISAS_NORETURN.
27
- ct->ct |= (type == TCG_TYPE_I32 ? TCG_CT_CONST : TCG_CT_CONST_I32);
26
+ */
28
+ ct->ct |= TCG_CT_CONST_I32;
27
void (*help_wout)(DisasContext *, DisasFields *, DisasOps *);
29
break;
28
void (*help_cout)(DisasContext *, DisasOps *);
30
29
+
31
default:
30
+ /* Implement the operation itself. */
32
@@ -XXX,XX +XXX,XX @@ static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
31
DisasJumpType (*help_op)(DisasContext *, DisasOps *);
33
if (ct & TCG_CT_CONST) {
32
34
return 1;
33
uint64_t data;
34
@@ -XXX,XX +XXX,XX @@ static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s)
35
if (insn->help_op) {
36
ret = insn->help_op(s, &o);
35
}
37
}
36
- if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) {
38
- if (insn->help_wout) {
37
- return 1;
39
- insn->help_wout(s, &f, &o);
38
- }
40
- }
39
- if ((ct & TCG_CT_CONST_U32) && val == (uint32_t)val) {
41
- if (insn->help_cout) {
40
- return 1;
42
- insn->help_cout(s, &o);
41
- }
43
+ if (ret != DISAS_NORETURN) {
42
- if ((ct & TCG_CT_CONST_I32) && ~val == (int32_t)~val) {
44
+ if (insn->help_wout) {
43
- return 1;
45
+ insn->help_wout(s, &f, &o);
44
+ if (type == TCG_TYPE_I32) {
45
+ if (ct & (TCG_CT_CONST_S32 | TCG_CT_CONST_U32 | TCG_CT_CONST_I32)) {
46
+ return 1;
47
+ }
46
+ }
48
+ } else {
47
+ if (insn->help_cout) {
49
+ if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) {
48
+ insn->help_cout(s, &o);
50
+ return 1;
51
+ }
52
+ if ((ct & TCG_CT_CONST_U32) && val == (uint32_t)val) {
53
+ return 1;
54
+ }
55
+ if ((ct & TCG_CT_CONST_I32) && ~val == (int32_t)~val) {
56
+ return 1;
57
+ }
49
+ }
58
}
50
}
59
if ((ct & TCG_CT_CONST_WSZ) && val == (type == TCG_TYPE_I32 ? 32 : 64)) {
51
60
return 1;
52
/* Free any temporaries created by the helpers. */
61
--
53
--
62
2.25.1
54
2.17.2
63
55
64
56
diff view generated by jsdifflib
1
Create symbolic constants for all low-byte-addressable
1
Reviewed-by: David Hildenbrand <david@redhat.com>
2
and second-byte-addressable registers. Create a symbol
3
for the registers that need reserving for softmmu.
4
5
There is no functional change for 's', as this letter is
6
only used for i386. The BYTEL name is correct for the
7
action we wish from the constraint.
8
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
---
3
---
12
tcg/i386/tcg-target.c.inc | 40 +++++++++++++++++++--------------------
4
target/s390x/mem_helper.c | 40 +++++++++++++++++++--------------------
13
1 file changed, 20 insertions(+), 20 deletions(-)
5
target/s390x/translate.c | 25 +++++++++++++++++-------
6
2 files changed, 38 insertions(+), 27 deletions(-)
14
7
15
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
8
diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c
16
index XXXXXXX..XXXXXXX 100644
9
index XXXXXXX..XXXXXXX 100644
17
--- a/tcg/i386/tcg-target.c.inc
10
--- a/target/s390x/mem_helper.c
18
+++ b/tcg/i386/tcg-target.c.inc
11
+++ b/target/s390x/mem_helper.c
19
@@ -XXX,XX +XXX,XX @@ static const int tcg_target_call_oarg_regs[] = {
12
@@ -XXX,XX +XXX,XX @@ void HELPER(cdsg_parallel)(CPUS390XState *env, uint64_t addr,
20
# define TCG_REG_L1 TCG_REG_EDX
13
Int128 oldv;
21
#endif
14
bool fail;
22
15
23
+#define ALL_BYTEH_REGS 0x0000000fu
16
- if (!HAVE_CMPXCHG128) {
24
+#if TCG_TARGET_REG_BITS == 64
17
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
25
+# define ALL_GENERAL_REGS 0x0000ffffu
18
- }
26
+# define ALL_VECTOR_REGS 0xffff0000u
19
+ assert(HAVE_CMPXCHG128);
27
+# define ALL_BYTEL_REGS ALL_GENERAL_REGS
20
28
+#else
21
mem_idx = cpu_mmu_index(env, false);
29
+# define ALL_GENERAL_REGS 0x000000ffu
22
oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
30
+# define ALL_VECTOR_REGS 0x00ff0000u
23
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(lpq_parallel)(CPUS390XState *env, uint64_t addr)
31
+# define ALL_BYTEL_REGS ALL_BYTEH_REGS
24
{
32
+#endif
25
uintptr_t ra = GETPC();
33
+#ifdef CONFIG_SOFTMMU
26
uint64_t hi, lo;
34
+# define SOFTMMU_RESERVE_REGS ((1 << TCG_REG_L0) | (1 << TCG_REG_L1))
27
+ int mem_idx;
35
+#else
28
+ TCGMemOpIdx oi;
36
+# define SOFTMMU_RESERVE_REGS 0
29
+ Int128 v;
37
+#endif
30
31
- if (HAVE_ATOMIC128) {
32
- int mem_idx = cpu_mmu_index(env, false);
33
- TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
34
- Int128 v = helper_atomic_ldo_be_mmu(env, addr, oi, ra);
35
- hi = int128_gethi(v);
36
- lo = int128_getlo(v);
37
- } else {
38
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
39
- }
40
+ assert(HAVE_ATOMIC128);
38
+
41
+
39
/* The host compiler should supply <cpuid.h> to enable runtime features
42
+ mem_idx = cpu_mmu_index(env, false);
40
detection, as we're not going to go so far as our own inline assembly.
43
+ oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
41
If not available, default values will be assumed. */
44
+ v = helper_atomic_ldo_be_mmu(env, addr, oi, ra);
42
@@ -XXX,XX +XXX,XX @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
45
+ hi = int128_gethi(v);
43
return true;
46
+ lo = int128_getlo(v);
47
48
env->retxl = lo;
49
return hi;
50
@@ -XXX,XX +XXX,XX @@ void HELPER(stpq_parallel)(CPUS390XState *env, uint64_t addr,
51
uint64_t low, uint64_t high)
52
{
53
uintptr_t ra = GETPC();
54
+ int mem_idx;
55
+ TCGMemOpIdx oi;
56
+ Int128 v;
57
58
- if (HAVE_ATOMIC128) {
59
- int mem_idx = cpu_mmu_index(env, false);
60
- TCGMemOpIdx oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
61
- Int128 v = int128_make128(low, high);
62
- helper_atomic_sto_be_mmu(env, addr, v, oi, ra);
63
- } else {
64
- cpu_loop_exit_atomic(ENV_GET_CPU(env), ra);
65
- }
66
+ assert(HAVE_ATOMIC128);
67
+
68
+ mem_idx = cpu_mmu_index(env, false);
69
+ oi = make_memop_idx(MO_TEQ | MO_ALIGN_16, mem_idx);
70
+ v = int128_make128(low, high);
71
+ helper_atomic_sto_be_mmu(env, addr, v, oi, ra);
44
}
72
}
45
73
46
-#if TCG_TARGET_REG_BITS == 64
74
/* Execute instruction. This instruction executes an insn modified with
47
-#define ALL_GENERAL_REGS 0x0000ffffu
75
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
48
-#define ALL_VECTOR_REGS 0xffff0000u
76
index XXXXXXX..XXXXXXX 100644
49
-#else
77
--- a/target/s390x/translate.c
50
-#define ALL_GENERAL_REGS 0x000000ffu
78
+++ b/target/s390x/translate.c
51
-#define ALL_VECTOR_REGS 0x00ff0000u
79
@@ -XXX,XX +XXX,XX @@
52
-#endif
80
#include "trace-tcg.h"
53
-
81
#include "exec/translator.h"
54
/* parse target specific constraints */
82
#include "exec/log.h"
55
static const char *target_parse_constraint(TCGArgConstraint *ct,
83
+#include "qemu/atomic128.h"
56
const char *ct_str, TCGType type)
84
57
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
85
58
break;
86
/* Information that (most) every instruction needs to manipulate. */
59
case 'q':
87
@@ -XXX,XX +XXX,XX @@ static DisasJumpType op_cdsg(DisasContext *s, DisasOps *o)
60
/* A register that can be used as a byte operand. */
88
int r3 = get_field(s->fields, r3);
61
- ct->regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xf;
89
int d2 = get_field(s->fields, d2);
62
+ ct->regs |= ALL_BYTEL_REGS;
90
int b2 = get_field(s->fields, b2);
63
break;
91
+ DisasJumpType ret = DISAS_NEXT;
64
case 'Q':
92
TCGv_i64 addr;
65
/* A register with an addressable second byte (e.g. %ah). */
93
TCGv_i32 t_r1, t_r3;
66
- ct->regs = 0xf;
94
67
+ ct->regs |= ALL_BYTEH_REGS;
95
@@ -XXX,XX +XXX,XX @@ static DisasJumpType op_cdsg(DisasContext *s, DisasOps *o)
68
break;
96
addr = get_address(s, 0, b2, d2);
69
case 'r':
97
t_r1 = tcg_const_i32(r1);
70
/* A general register. */
98
t_r3 = tcg_const_i32(r3);
71
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
99
- if (tb_cflags(s->base.tb) & CF_PARALLEL) {
72
100
+ if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
73
case 'L':
101
+ gen_helper_cdsg(cpu_env, addr, t_r1, t_r3);
74
/* qemu_ld/st data+address constraint */
102
+ } else if (HAVE_CMPXCHG128) {
75
- ct->regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xff;
103
gen_helper_cdsg_parallel(cpu_env, addr, t_r1, t_r3);
76
-#ifdef CONFIG_SOFTMMU
104
} else {
77
- tcg_regset_reset_reg(ct->regs, TCG_REG_L0);
105
- gen_helper_cdsg(cpu_env, addr, t_r1, t_r3);
78
- tcg_regset_reset_reg(ct->regs, TCG_REG_L1);
106
+ gen_helper_exit_atomic(cpu_env);
79
-#endif
107
+ ret = DISAS_NORETURN;
80
+ ct->regs |= ALL_GENERAL_REGS & ~SOFTMMU_RESERVE_REGS;
108
}
81
break;
109
tcg_temp_free_i64(addr);
82
case 's':
110
tcg_temp_free_i32(t_r1);
83
/* qemu_st8_i32 data constraint */
111
tcg_temp_free_i32(t_r3);
84
- ct->regs = 0xf;
112
85
-#ifdef CONFIG_SOFTMMU
113
set_cc_static(s);
86
- tcg_regset_reset_reg(ct->regs, TCG_REG_L0);
114
- return DISAS_NEXT;
87
- tcg_regset_reset_reg(ct->regs, TCG_REG_L1);
115
+ return ret;
88
-#endif
116
}
89
+ ct->regs |= ALL_BYTEL_REGS & ~SOFTMMU_RESERVE_REGS;
117
90
break;
118
static DisasJumpType op_csst(DisasContext *s, DisasOps *o)
91
119
@@ -XXX,XX +XXX,XX @@ static DisasJumpType op_lpd(DisasContext *s, DisasOps *o)
92
case 'e':
120
121
static DisasJumpType op_lpq(DisasContext *s, DisasOps *o)
122
{
123
- if (tb_cflags(s->base.tb) & CF_PARALLEL) {
124
+ if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
125
+ gen_helper_lpq(o->out, cpu_env, o->in2);
126
+ } else if (HAVE_ATOMIC128) {
127
gen_helper_lpq_parallel(o->out, cpu_env, o->in2);
128
} else {
129
- gen_helper_lpq(o->out, cpu_env, o->in2);
130
+ gen_helper_exit_atomic(cpu_env);
131
+ return DISAS_NORETURN;
132
}
133
return_low128(o->out2);
134
return DISAS_NEXT;
135
@@ -XXX,XX +XXX,XX @@ static DisasJumpType op_stmh(DisasContext *s, DisasOps *o)
136
137
static DisasJumpType op_stpq(DisasContext *s, DisasOps *o)
138
{
139
- if (tb_cflags(s->base.tb) & CF_PARALLEL) {
140
+ if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
141
+ gen_helper_stpq(cpu_env, o->in2, o->out2, o->out);
142
+ } else if (HAVE_ATOMIC128) {
143
gen_helper_stpq_parallel(cpu_env, o->in2, o->out2, o->out);
144
} else {
145
- gen_helper_stpq(cpu_env, o->in2, o->out2, o->out);
146
+ gen_helper_exit_atomic(cpu_env);
147
+ return DISAS_NORETURN;
148
}
149
return DISAS_NEXT;
150
}
93
--
151
--
94
2.25.1
152
2.17.2
95
153
96
154
diff view generated by jsdifflib
Deleted patch
1
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
4
tcg/arm/tcg-target-con-str.h | 22 +++++++++++
5
tcg/arm/tcg-target.h | 1 +
6
tcg/arm/tcg-target.c.inc | 74 +++++++++---------------------------
7
3 files changed, 41 insertions(+), 56 deletions(-)
8
create mode 100644 tcg/arm/tcg-target-con-str.h
9
1
10
diff --git a/tcg/arm/tcg-target-con-str.h b/tcg/arm/tcg-target-con-str.h
11
new file mode 100644
12
index XXXXXXX..XXXXXXX
13
--- /dev/null
14
+++ b/tcg/arm/tcg-target-con-str.h
15
@@ -XXX,XX +XXX,XX @@
16
+/* SPDX-License-Identifier: MIT */
17
+/*
18
+ * Define Arm target-specific operand constraints.
19
+ * Copyright (c) 2021 Linaro
20
+ */
21
+
22
+/*
23
+ * Define constraint letters for register sets:
24
+ * REGS(letter, register_mask)
25
+ */
26
+REGS('r', ALL_GENERAL_REGS)
27
+REGS('l', ALL_QLOAD_REGS)
28
+REGS('s', ALL_QSTORE_REGS)
29
+
30
+/*
31
+ * Define constraint letters for constants:
32
+ * CONST(letter, TCG_CT_CONST_* bit set)
33
+ */
34
+CONST('I', TCG_CT_CONST_ARM)
35
+CONST('K', TCG_CT_CONST_INV)
36
+CONST('N', TCG_CT_CONST_NEG)
37
+CONST('Z', TCG_CT_CONST_ZERO)
38
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/tcg/arm/tcg-target.h
41
+++ b/tcg/arm/tcg-target.h
42
@@ -XXX,XX +XXX,XX @@ void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
43
#define TCG_TARGET_NEED_LDST_LABELS
44
#endif
45
#define TCG_TARGET_NEED_POOL_LABELS
46
+#define TCG_TARGET_CON_STR_H
47
48
#endif
49
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
50
index XXXXXXX..XXXXXXX 100644
51
--- a/tcg/arm/tcg-target.c.inc
52
+++ b/tcg/arm/tcg-target.c.inc
53
@@ -XXX,XX +XXX,XX @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
54
#define TCG_CT_CONST_NEG 0x400
55
#define TCG_CT_CONST_ZERO 0x800
56
57
-/* parse target specific constraints */
58
-static const char *target_parse_constraint(TCGArgConstraint *ct,
59
- const char *ct_str, TCGType type)
60
-{
61
- switch (*ct_str++) {
62
- case 'I':
63
- ct->ct |= TCG_CT_CONST_ARM;
64
- break;
65
- case 'K':
66
- ct->ct |= TCG_CT_CONST_INV;
67
- break;
68
- case 'N': /* The gcc constraint letter is L, already used here. */
69
- ct->ct |= TCG_CT_CONST_NEG;
70
- break;
71
- case 'Z':
72
- ct->ct |= TCG_CT_CONST_ZERO;
73
- break;
74
+#define ALL_GENERAL_REGS 0xffffu
75
76
- case 'r':
77
- ct->regs = 0xffff;
78
- break;
79
-
80
- /* qemu_ld address */
81
- case 'l':
82
- ct->regs = 0xffff;
83
+/*
84
+ * r0-r2 will be overwritten when reading the tlb entry (softmmu only)
85
+ * and r0-r1 doing the byte swapping, so don't use these.
86
+ * r3 is removed for softmmu to avoid clashes with helper arguments.
87
+ */
88
#ifdef CONFIG_SOFTMMU
89
- /* r0-r2,lr will be overwritten when reading the tlb entry,
90
- so don't use these. */
91
- tcg_regset_reset_reg(ct->regs, TCG_REG_R0);
92
- tcg_regset_reset_reg(ct->regs, TCG_REG_R1);
93
- tcg_regset_reset_reg(ct->regs, TCG_REG_R2);
94
- tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
95
- tcg_regset_reset_reg(ct->regs, TCG_REG_R14);
96
+#define ALL_QLOAD_REGS \
97
+ (ALL_GENERAL_REGS & ~((1 << TCG_REG_R0) | (1 << TCG_REG_R1) | \
98
+ (1 << TCG_REG_R2) | (1 << TCG_REG_R3) | \
99
+ (1 << TCG_REG_R14)))
100
+#define ALL_QSTORE_REGS \
101
+ (ALL_GENERAL_REGS & ~((1 << TCG_REG_R0) | (1 << TCG_REG_R1) | \
102
+ (1 << TCG_REG_R2) | (1 << TCG_REG_R14) | \
103
+ ((TARGET_LONG_BITS == 64) << TCG_REG_R3)))
104
+#else
105
+#define ALL_QLOAD_REGS ALL_GENERAL_REGS
106
+#define ALL_QSTORE_REGS \
107
+ (ALL_GENERAL_REGS & ~((1 << TCG_REG_R0) | (1 << TCG_REG_R1)))
108
#endif
109
- break;
110
-
111
- /* qemu_st address & data */
112
- case 's':
113
- ct->regs = 0xffff;
114
- /* r0-r2 will be overwritten when reading the tlb entry (softmmu only)
115
- and r0-r1 doing the byte swapping, so don't use these. */
116
- tcg_regset_reset_reg(ct->regs, TCG_REG_R0);
117
- tcg_regset_reset_reg(ct->regs, TCG_REG_R1);
118
-#if defined(CONFIG_SOFTMMU)
119
- /* Avoid clashes with registers being used for helper args */
120
- tcg_regset_reset_reg(ct->regs, TCG_REG_R2);
121
-#if TARGET_LONG_BITS == 64
122
- /* Avoid clashes with registers being used for helper args */
123
- tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
124
-#endif
125
- tcg_regset_reset_reg(ct->regs, TCG_REG_R14);
126
-#endif
127
- break;
128
-
129
- default:
130
- return NULL;
131
- }
132
- return ct_str;
133
-}
134
135
static inline uint32_t rotl(uint32_t val, int n)
136
{
137
--
138
2.25.1
139
140
diff view generated by jsdifflib
1
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
1
From: "Emilio G. Cota" <cota@braap.org>
2
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
3
Updates can come from other threads, so readers that do not
4
take tlb_lock must use atomic_read to avoid undefined
5
behaviour (UB).
6
7
This completes the conversion to tlb_lock. This conversion results
8
on average in no performance loss, as the following experiments
9
(run on an Intel i7-6700K CPU @ 4.00GHz) show.
10
11
1. aarch64 bootup+shutdown test:
12
13
- Before:
14
Performance counter stats for 'taskset -c 0 ../img/aarch64/die.sh' (10 runs):
15
16
7487.087786 task-clock (msec) # 0.998 CPUs utilized ( +- 0.12% )
17
31,574,905,303 cycles # 4.217 GHz ( +- 0.12% )
18
57,097,908,812 instructions # 1.81 insns per cycle ( +- 0.08% )
19
10,255,415,367 branches # 1369.747 M/sec ( +- 0.08% )
20
173,278,962 branch-misses # 1.69% of all branches ( +- 0.18% )
21
22
7.504481349 seconds time elapsed ( +- 0.14% )
23
24
- After:
25
Performance counter stats for 'taskset -c 0 ../img/aarch64/die.sh' (10 runs):
26
27
7462.441328 task-clock (msec) # 0.998 CPUs utilized ( +- 0.07% )
28
31,478,476,520 cycles # 4.218 GHz ( +- 0.07% )
29
57,017,330,084 instructions # 1.81 insns per cycle ( +- 0.05% )
30
10,251,929,667 branches # 1373.804 M/sec ( +- 0.05% )
31
173,023,787 branch-misses # 1.69% of all branches ( +- 0.11% )
32
33
7.474970463 seconds time elapsed ( +- 0.07% )
34
35
2. SPEC06int:
36
SPEC06int (test set)
37
[Y axis: Speedup over master]
38
1.15 +-+----+------+------+------+------+------+-------+------+------+------+------+------+------+----+-+
39
| |
40
1.1 +-+.................................+++.............................+ tlb-lock-v2 (m+++x) +-+
41
| +++ | +++ tlb-lock-v3 (spinl|ck) |
42
| +++ | | +++ +++ | | |
43
1.05 +-+....+++...........####.........|####.+++.|......|.....###....+++...........+++....###.........+-+
44
| ### ++#| # |# |# ***### +++### +++#+# | +++ | #|# ### |
45
1 +-+++***+#++++####+++#++#++++++++++#++#+*+*++#++++#+#+****+#++++###++++###++++###++++#+#++++#+#+++-+
46
| *+* # #++# *** # #### *** # * *++# ****+# *| * # ****|# |# # #|# #+# # # |
47
0.95 +-+..*.*.#....#..#.*|*..#...#..#.*|*..#.*.*..#.*|.*.#.*++*.#.*++*+#.****.#....#+#....#.#..++#.#..+-+
48
| * * # # # *|* # # # *|* # * * # *++* # * * # * * # * |* # ++# # # # *** # |
49
| * * # ++# # *+* # # # *|* # * * # * * # * * # * * # *++* # **** # ++# # * * # |
50
0.9 +-+..*.*.#...|#..#.*.*..#.++#..#.*|*..#.*.*..#.*..*.#.*..*.#.*..*.#.*..*.#.*.|*.#...|#.#..*.*.#..+-+
51
| * * # *** # * * # |# # *+* # * * # * * # * * # * * # * * # *++* # |# # * * # |
52
0.85 +-+..*.*.#..*|*..#.*.*..#.***..#.*.*..#.*.*..#.*..*.#.*..*.#.*..*.#.*..*.#.*..*.#.****.#..*.*.#..+-+
53
| * * # *+* # * * # *|* # * * # * * # * * # * * # * * # * * # * * # * |* # * * # |
54
| * * # * * # * * # *+* # * * # * * # * * # * * # * * # * * # * * # * |* # * * # |
55
0.8 +-+..*.*.#..*.*..#.*.*..#.*.*..#.*.*..#.*.*..#.*..*.#.*..*.#.*..*.#.*..*.#.*..*.#.*++*.#..*.*.#..+-+
56
| * * # * * # * * # * * # * * # * * # * * # * * # * * # * * # * * # * * # * * # |
57
0.75 +-+--***##--***###-***###-***###-***###-***###-****##-****##-****##-****##-****##-****##--***##--+-+
58
400.perlben401.bzip2403.gcc429.m445.gob456.hmme45462.libqua464.h26471.omnet473483.xalancbmkgeomean
59
60
png: https://imgur.com/a/BHzpPTW
61
62
Notes:
63
- tlb-lock-v2 corresponds to an implementation with a mutex.
64
- tlb-lock-v3 corresponds to the current implementation, i.e.
65
a spinlock and a single lock acquisition in tlb_set_page_with_attrs.
66
67
Signed-off-by: Emilio G. Cota <cota@braap.org>
68
Message-Id: <20181016153840.25877-1-cota@braap.org>
3
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
69
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
---
70
---
5
tcg/tci/tcg-target-con-str.h | 11 +++++++++++
71
accel/tcg/softmmu_template.h | 12 ++++++------
6
tcg/tci/tcg-target.h | 2 ++
72
include/exec/cpu_ldst.h | 11 ++++++++++-
7
tcg/tci/tcg-target.c.inc | 14 --------------
73
include/exec/cpu_ldst_template.h | 2 +-
8
3 files changed, 13 insertions(+), 14 deletions(-)
74
accel/tcg/cputlb.c | 19 +++++++++++++------
9
create mode 100644 tcg/tci/tcg-target-con-str.h
75
4 files changed, 30 insertions(+), 14 deletions(-)
10
76
11
diff --git a/tcg/tci/tcg-target-con-str.h b/tcg/tci/tcg-target-con-str.h
77
diff --git a/accel/tcg/softmmu_template.h b/accel/tcg/softmmu_template.h
12
new file mode 100644
78
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX
79
--- a/accel/tcg/softmmu_template.h
14
--- /dev/null
80
+++ b/accel/tcg/softmmu_template.h
15
+++ b/tcg/tci/tcg-target-con-str.h
81
@@ -XXX,XX +XXX,XX @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
16
@@ -XXX,XX +XXX,XX @@
82
uintptr_t mmu_idx = get_mmuidx(oi);
17
+/* SPDX-License-Identifier: MIT */
83
uintptr_t index = tlb_index(env, mmu_idx, addr);
18
+/*
84
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
19
+ * Define TCI target-specific operand constraints.
85
- target_ulong tlb_addr = entry->addr_write;
20
+ * Copyright (c) 2021 Linaro
86
+ target_ulong tlb_addr = tlb_addr_write(entry);
21
+ */
87
unsigned a_bits = get_alignment_bits(get_memop(oi));
88
uintptr_t haddr;
89
90
@@ -XXX,XX +XXX,XX @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
91
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, MMU_DATA_STORE,
92
mmu_idx, retaddr);
93
}
94
- tlb_addr = entry->addr_write & ~TLB_INVALID_MASK;
95
+ tlb_addr = tlb_addr_write(entry) & ~TLB_INVALID_MASK;
96
}
97
98
/* Handle an IO access. */
99
@@ -XXX,XX +XXX,XX @@ void helper_le_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
100
cannot evict the first. */
101
page2 = (addr + DATA_SIZE) & TARGET_PAGE_MASK;
102
entry2 = tlb_entry(env, mmu_idx, page2);
103
- if (!tlb_hit_page(entry2->addr_write, page2)
104
+ if (!tlb_hit_page(tlb_addr_write(entry2), page2)
105
&& !VICTIM_TLB_HIT(addr_write, page2)) {
106
tlb_fill(ENV_GET_CPU(env), page2, DATA_SIZE, MMU_DATA_STORE,
107
mmu_idx, retaddr);
108
@@ -XXX,XX +XXX,XX @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
109
uintptr_t mmu_idx = get_mmuidx(oi);
110
uintptr_t index = tlb_index(env, mmu_idx, addr);
111
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
112
- target_ulong tlb_addr = entry->addr_write;
113
+ target_ulong tlb_addr = tlb_addr_write(entry);
114
unsigned a_bits = get_alignment_bits(get_memop(oi));
115
uintptr_t haddr;
116
117
@@ -XXX,XX +XXX,XX @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
118
tlb_fill(ENV_GET_CPU(env), addr, DATA_SIZE, MMU_DATA_STORE,
119
mmu_idx, retaddr);
120
}
121
- tlb_addr = entry->addr_write & ~TLB_INVALID_MASK;
122
+ tlb_addr = tlb_addr_write(entry) & ~TLB_INVALID_MASK;
123
}
124
125
/* Handle an IO access. */
126
@@ -XXX,XX +XXX,XX @@ void helper_be_st_name(CPUArchState *env, target_ulong addr, DATA_TYPE val,
127
cannot evict the first. */
128
page2 = (addr + DATA_SIZE) & TARGET_PAGE_MASK;
129
entry2 = tlb_entry(env, mmu_idx, page2);
130
- if (!tlb_hit_page(entry2->addr_write, page2)
131
+ if (!tlb_hit_page(tlb_addr_write(entry2), page2)
132
&& !VICTIM_TLB_HIT(addr_write, page2)) {
133
tlb_fill(ENV_GET_CPU(env), page2, DATA_SIZE, MMU_DATA_STORE,
134
mmu_idx, retaddr);
135
diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h
136
index XXXXXXX..XXXXXXX 100644
137
--- a/include/exec/cpu_ldst.h
138
+++ b/include/exec/cpu_ldst.h
139
@@ -XXX,XX +XXX,XX @@ extern __thread uintptr_t helper_retaddr;
140
/* The memory helpers for tcg-generated code need tcg_target_long etc. */
141
#include "tcg.h"
142
143
+static inline target_ulong tlb_addr_write(const CPUTLBEntry *entry)
144
+{
145
+#if TCG_OVERSIZED_GUEST
146
+ return entry->addr_write;
147
+#else
148
+ return atomic_read(&entry->addr_write);
149
+#endif
150
+}
22
+
151
+
23
+/*
152
/* Find the TLB index corresponding to the mmu_idx + address pair. */
24
+ * Define constraint letters for register sets:
153
static inline uintptr_t tlb_index(CPUArchState *env, uintptr_t mmu_idx,
25
+ * REGS(letter, register_mask)
154
target_ulong addr)
26
+ */
155
@@ -XXX,XX +XXX,XX @@ static inline void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
27
+REGS('r', MAKE_64BIT_MASK(0, TCG_TARGET_NB_REGS))
156
tlb_addr = tlbentry->addr_read;
28
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
157
break;
29
index XXXXXXX..XXXXXXX 100644
158
case 1:
30
--- a/tcg/tci/tcg-target.h
159
- tlb_addr = tlbentry->addr_write;
31
+++ b/tcg/tci/tcg-target.h
160
+ tlb_addr = tlb_addr_write(tlbentry);
32
@@ -XXX,XX +XXX,XX @@ static inline void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
161
break;
33
/* no need to flush icache explicitly */
162
case 2:
163
tlb_addr = tlbentry->addr_code;
164
diff --git a/include/exec/cpu_ldst_template.h b/include/exec/cpu_ldst_template.h
165
index XXXXXXX..XXXXXXX 100644
166
--- a/include/exec/cpu_ldst_template.h
167
+++ b/include/exec/cpu_ldst_template.h
168
@@ -XXX,XX +XXX,XX @@ glue(glue(glue(cpu_st, SUFFIX), MEMSUFFIX), _ra)(CPUArchState *env,
169
addr = ptr;
170
mmu_idx = CPU_MMU_INDEX;
171
entry = tlb_entry(env, mmu_idx, addr);
172
- if (unlikely(entry->addr_write !=
173
+ if (unlikely(tlb_addr_write(entry) !=
174
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
175
oi = make_memop_idx(SHIFT, mmu_idx);
176
glue(glue(helper_ret_st, SUFFIX), MMUSUFFIX)(env, addr, v, oi,
177
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
178
index XXXXXXX..XXXXXXX 100644
179
--- a/accel/tcg/cputlb.c
180
+++ b/accel/tcg/cputlb.c
181
@@ -XXX,XX +XXX,XX @@ static inline bool tlb_hit_page_anyprot(CPUTLBEntry *tlb_entry,
182
target_ulong page)
183
{
184
return tlb_hit_page(tlb_entry->addr_read, page) ||
185
- tlb_hit_page(tlb_entry->addr_write, page) ||
186
+ tlb_hit_page(tlb_addr_write(tlb_entry), page) ||
187
tlb_hit_page(tlb_entry->addr_code, page);
34
}
188
}
35
189
36
+#define TCG_TARGET_CON_STR_H
190
@@ -XXX,XX +XXX,XX @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
191
tlb_fill(cpu, addr, size, MMU_DATA_STORE, mmu_idx, retaddr);
192
193
entry = tlb_entry(env, mmu_idx, addr);
194
- tlb_addr = entry->addr_write;
195
+ tlb_addr = tlb_addr_write(entry);
196
if (!(tlb_addr & ~(TARGET_PAGE_MASK | TLB_RECHECK))) {
197
/* RAM access */
198
uintptr_t haddr = addr + entry->addend;
199
@@ -XXX,XX +XXX,XX @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
200
assert_cpu_is_self(ENV_GET_CPU(env));
201
for (vidx = 0; vidx < CPU_VTLB_SIZE; ++vidx) {
202
CPUTLBEntry *vtlb = &env->tlb_v_table[mmu_idx][vidx];
203
- target_ulong cmp = *(target_ulong *)((uintptr_t)vtlb + elt_ofs);
204
+ target_ulong cmp;
37
+
205
+
38
#endif /* TCG_TARGET_H */
206
+ /* elt_ofs might correspond to .addr_write, so use atomic_read */
39
diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
207
+#if TCG_OVERSIZED_GUEST
40
index XXXXXXX..XXXXXXX 100644
208
+ cmp = *(target_ulong *)((uintptr_t)vtlb + elt_ofs);
41
--- a/tcg/tci/tcg-target.c.inc
209
+#else
42
+++ b/tcg/tci/tcg-target.c.inc
210
+ cmp = atomic_read((target_ulong *)((uintptr_t)vtlb + elt_ofs));
43
@@ -XXX,XX +XXX,XX @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
211
+#endif
44
return true;
212
45
}
213
if (cmp == page) {
46
214
/* Found entry in victim tlb, swap tlb and iotlb. */
47
-/* Parse target specific constraints. */
215
@@ -XXX,XX +XXX,XX @@ void probe_write(CPUArchState *env, target_ulong addr, int size, int mmu_idx,
48
-static const char *target_parse_constraint(TCGArgConstraint *ct,
216
uintptr_t index = tlb_index(env, mmu_idx, addr);
49
- const char *ct_str, TCGType type)
217
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
50
-{
218
51
- switch (*ct_str++) {
219
- if (!tlb_hit(entry->addr_write, addr)) {
52
- case 'r':
220
+ if (!tlb_hit(tlb_addr_write(entry), addr)) {
53
- ct->regs = BIT(TCG_TARGET_NB_REGS) - 1;
221
/* TLB entry is for a different page */
54
- break;
222
if (!VICTIM_TLB_HIT(addr_write, addr)) {
55
- default:
223
tlb_fill(ENV_GET_CPU(env), addr, size, MMU_DATA_STORE,
56
- return NULL;
224
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
57
- }
225
size_t mmu_idx = get_mmuidx(oi);
58
- return ct_str;
226
uintptr_t index = tlb_index(env, mmu_idx, addr);
59
-}
227
CPUTLBEntry *tlbe = tlb_entry(env, mmu_idx, addr);
60
-
228
- target_ulong tlb_addr = tlbe->addr_write;
61
#if defined(CONFIG_DEBUG_TCG_INTERPRETER)
229
+ target_ulong tlb_addr = tlb_addr_write(tlbe);
62
/* Show current bytecode. Used by tcg interpreter. */
230
TCGMemOp mop = get_memop(oi);
63
void tci_disas(uint8_t opc)
231
int a_bits = get_alignment_bits(mop);
232
int s_bits = mop & MO_SIZE;
233
@@ -XXX,XX +XXX,XX @@ static void *atomic_mmu_lookup(CPUArchState *env, target_ulong addr,
234
tlb_fill(ENV_GET_CPU(env), addr, 1 << s_bits, MMU_DATA_STORE,
235
mmu_idx, retaddr);
236
}
237
- tlb_addr = tlbe->addr_write & ~TLB_INVALID_MASK;
238
+ tlb_addr = tlb_addr_write(tlbe) & ~TLB_INVALID_MASK;
239
}
240
241
/* Notice an IO access or a needs-MMU-lookup access */
64
--
242
--
65
2.25.1
243
2.17.2
66
244
67
245
diff view generated by jsdifflib