1
The following changes since commit 67e41fe0cfb62e6cdfa659f0155417d17e5274ea:
1
Second try's the charm today, right?
2
2
3
Merge tag 'pull-ppc-20220104' of https://github.com/legoater/qemu into staging (2022-01-04 07:23:27 -0800)
3
4
r~
5
6
7
The following changes since commit 00b1faea41d283e931256aa78aa975a369ec3ae6:
8
9
Merge tag 'pull-target-arm-20230123' of https://git.linaro.org/people/pmaydell/qemu-arm into staging (2023-01-23 13:40:28 +0000)
4
10
5
are available in the Git repository at:
11
are available in the Git repository at:
6
12
7
https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20220104
13
https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20230123
8
14
9
for you to fetch changes up to d7478d4229f0a2b2817a55487e6b17081099fae4:
15
for you to fetch changes up to 709bcd7da3f6b4655d910634a0d520fa1439df38:
10
16
11
common-user: Fix tail calls to safe_syscall_set_errno_tail (2022-01-04 15:41:03 -0800)
17
tcg/loongarch64: Reorg goto_tb implementation (2023-01-23 16:00:13 -1000)
12
18
13
----------------------------------------------------------------
19
----------------------------------------------------------------
14
Fix for safe_syscall_base.
20
common-user: Re-enable ppc32 host
15
Fix for folding of vector add/sub.
21
tcg: Avoid recursion in tcg_gen_mulu2_i32
16
Fix build on loongarch64 with gcc 8.
22
tcg: Mark tcg helpers noinline to avoid an issue with LTO
17
Remove decl for qemu_run_machine_init_done_notifiers.
23
tcg/arm: Use register pair allocation for qemu_{ld,st}_i64
24
disas: Enable loongarch disassembler, and fixes
25
tcg/loongarch64: Improve move immediate
26
tcg/loongarch64: Improve add immediate
27
tcg/loongarch64: Improve setcond
28
tcg/loongarch64: Implement movcond
29
tcg/loongarch64: Use tcg_pcrel_diff in tcg_out_ldst
30
tcg/loongarch64: Reorg goto_tb implementation
18
31
19
----------------------------------------------------------------
32
----------------------------------------------------------------
20
Philippe Mathieu-Daudé (1):
33
Richard Henderson (14):
21
linux-user: Fix trivial build error on loongarch64 hosts
34
tcg: Avoid recursion in tcg_gen_mulu2_i32
35
tcg/arm: Use register pair allocation for qemu_{ld,st}_i64
36
common-user/host/ppc: Implement safe-syscall.inc.S
37
linux-user: Implment host/ppc/host-signal.h
38
tcg: Mark tcg helpers noinline to avoid an issue with LTO
39
target/loongarch: Enable the disassembler for host tcg
40
target/loongarch: Disassemble jirl properly
41
target/loongarch: Disassemble pcadd* addresses
42
tcg/loongarch64: Update tcg-insn-defs.c.inc
43
tcg/loongarch64: Introduce tcg_out_addi
44
tcg/loongarch64: Improve setcond expansion
45
tcg/loongarch64: Implement movcond
46
tcg/loongarch64: Use tcg_pcrel_diff in tcg_out_ldst
47
tcg/loongarch64: Reorg goto_tb implementation
22
48
23
Richard Henderson (2):
49
Rui Wang (1):
24
tcg/optimize: Fix folding of vector ops
50
tcg/loongarch64: Optimize immediate loading
25
common-user: Fix tail calls to safe_syscall_set_errno_tail
26
51
27
Xiaoyao Li (1):
52
include/exec/helper-proto.h | 32 ++-
28
sysemu: Cleanup qemu_run_machine_init_done_notifiers()
53
include/tcg/tcg.h | 7 -
29
54
linux-user/include/host/ppc/host-signal.h | 39 +++
30
include/sysemu/sysemu.h | 1 -
55
tcg/arm/tcg-target-con-set.h | 7 +-
31
linux-user/host/loongarch64/host-signal.h | 4 +--
56
tcg/arm/tcg-target-con-str.h | 2 +
32
tcg/optimize.c | 49 +++++++++++++++++++++++-------
57
tcg/loongarch64/tcg-target-con-set.h | 5 +-
33
common-user/host/i386/safe-syscall.inc.S | 1 +
58
tcg/loongarch64/tcg-target-con-str.h | 2 +-
34
common-user/host/mips/safe-syscall.inc.S | 1 +
59
tcg/loongarch64/tcg-target.h | 11 +-
35
common-user/host/x86_64/safe-syscall.inc.S | 1 +
60
target/loongarch/insns.decode | 3 +-
36
6 files changed, 42 insertions(+), 15 deletions(-)
61
disas.c | 2 +
37
62
target/loongarch/disas.c | 39 ++-
63
tcg/tcg-op.c | 4 +-
64
target/loongarch/insn_trans/trans_branch.c.inc | 2 +-
65
tcg/arm/tcg-target.c.inc | 28 +-
66
tcg/loongarch64/tcg-insn-defs.c.inc | 10 +-
67
tcg/loongarch64/tcg-target.c.inc | 364 ++++++++++++++++---------
68
common-user/host/ppc/safe-syscall.inc.S | 107 ++++++++
69
target/loongarch/meson.build | 3 +-
70
18 files changed, 497 insertions(+), 170 deletions(-)
71
create mode 100644 linux-user/include/host/ppc/host-signal.h
72
create mode 100644 common-user/host/ppc/safe-syscall.inc.S
diff view generated by jsdifflib
New patch
1
We have a test for one of TCG_TARGET_HAS_mulu2_i32 or
2
TCG_TARGET_HAS_muluh_i32 being defined, but the test
3
became non-functional when we changed to always define
4
all of these macros.
1
5
6
Replace this with a build-time test in tcg_gen_mulu2_i32.
7
8
Fixes: 25c4d9cc845 ("tcg: Always define all of the TCGOpcode enum members.")
9
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1435
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
---
12
include/tcg/tcg.h | 7 -------
13
tcg/tcg-op.c | 4 +++-
14
2 files changed, 3 insertions(+), 8 deletions(-)
15
16
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/tcg/tcg.h
19
+++ b/include/tcg/tcg.h
20
@@ -XXX,XX +XXX,XX @@ typedef uint64_t TCGRegSet;
21
#define TCG_TARGET_HAS_rem_i64 0
22
#endif
23
24
-/* For 32-bit targets, some sort of unsigned widening multiply is required. */
25
-#if TCG_TARGET_REG_BITS == 32 \
26
- && !(defined(TCG_TARGET_HAS_mulu2_i32) \
27
- || defined(TCG_TARGET_HAS_muluh_i32))
28
-# error "Missing unsigned widening multiply"
29
-#endif
30
-
31
#if !defined(TCG_TARGET_HAS_v64) \
32
&& !defined(TCG_TARGET_HAS_v128) \
33
&& !defined(TCG_TARGET_HAS_v256)
34
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/tcg/tcg-op.c
37
+++ b/tcg/tcg-op.c
38
@@ -XXX,XX +XXX,XX @@ void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
39
tcg_gen_op3_i32(INDEX_op_muluh_i32, rh, arg1, arg2);
40
tcg_gen_mov_i32(rl, t);
41
tcg_temp_free_i32(t);
42
- } else {
43
+ } else if (TCG_TARGET_REG_BITS == 64) {
44
TCGv_i64 t0 = tcg_temp_new_i64();
45
TCGv_i64 t1 = tcg_temp_new_i64();
46
tcg_gen_extu_i32_i64(t0, arg1);
47
@@ -XXX,XX +XXX,XX @@ void tcg_gen_mulu2_i32(TCGv_i32 rl, TCGv_i32 rh, TCGv_i32 arg1, TCGv_i32 arg2)
48
tcg_gen_extr_i64_i32(rl, rh, t0);
49
tcg_temp_free_i64(t0);
50
tcg_temp_free_i64(t1);
51
+ } else {
52
+ qemu_build_not_reached();
53
}
54
}
55
56
--
57
2.34.1
diff view generated by jsdifflib
New patch
1
Although we still can't use ldrd and strd for all operations,
2
increase the chances by getting the register allocation correct.
1
3
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
---
6
tcg/arm/tcg-target-con-set.h | 7 ++++---
7
tcg/arm/tcg-target-con-str.h | 2 ++
8
tcg/arm/tcg-target.c.inc | 28 ++++++++++++++++++----------
9
3 files changed, 24 insertions(+), 13 deletions(-)
10
11
diff --git a/tcg/arm/tcg-target-con-set.h b/tcg/arm/tcg-target-con-set.h
12
index XXXXXXX..XXXXXXX 100644
13
--- a/tcg/arm/tcg-target-con-set.h
14
+++ b/tcg/arm/tcg-target-con-set.h
15
@@ -XXX,XX +XXX,XX @@ C_O0_I2(r, rIN)
16
C_O0_I2(s, s)
17
C_O0_I2(w, r)
18
C_O0_I3(s, s, s)
19
+C_O0_I3(S, p, s)
20
C_O0_I4(r, r, rI, rI)
21
-C_O0_I4(s, s, s, s)
22
+C_O0_I4(S, p, s, s)
23
C_O1_I1(r, l)
24
C_O1_I1(r, r)
25
C_O1_I1(w, r)
26
@@ -XXX,XX +XXX,XX @@ C_O1_I2(w, w, wZ)
27
C_O1_I3(w, w, w, w)
28
C_O1_I4(r, r, r, rI, rI)
29
C_O1_I4(r, r, rIN, rIK, 0)
30
-C_O2_I1(r, r, l)
31
-C_O2_I2(r, r, l, l)
32
+C_O2_I1(e, p, l)
33
+C_O2_I2(e, p, l, l)
34
C_O2_I2(r, r, r, r)
35
C_O2_I4(r, r, r, r, rIN, rIK)
36
C_O2_I4(r, r, rI, rI, rIN, rIK)
37
diff --git a/tcg/arm/tcg-target-con-str.h b/tcg/arm/tcg-target-con-str.h
38
index XXXXXXX..XXXXXXX 100644
39
--- a/tcg/arm/tcg-target-con-str.h
40
+++ b/tcg/arm/tcg-target-con-str.h
41
@@ -XXX,XX +XXX,XX @@
42
* Define constraint letters for register sets:
43
* REGS(letter, register_mask)
44
*/
45
+REGS('e', ALL_GENERAL_REGS & 0x5555) /* even regs */
46
REGS('r', ALL_GENERAL_REGS)
47
REGS('l', ALL_QLOAD_REGS)
48
REGS('s', ALL_QSTORE_REGS)
49
+REGS('S', ALL_QSTORE_REGS & 0x5555) /* even qstore */
50
REGS('w', ALL_VECTOR_REGS)
51
52
/*
53
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
54
index XXXXXXX..XXXXXXX 100644
55
--- a/tcg/arm/tcg-target.c.inc
56
+++ b/tcg/arm/tcg-target.c.inc
57
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_ld_index(TCGContext *s, MemOp opc,
58
tcg_out_ld32_r(s, COND_AL, datalo, addrlo, addend);
59
break;
60
case MO_UQ:
61
+ /* We used pair allocation for datalo, so already should be aligned. */
62
+ tcg_debug_assert((datalo & 1) == 0);
63
+ tcg_debug_assert(datahi == datalo + 1);
64
/* LDRD requires alignment; double-check that. */
65
- if (get_alignment_bits(opc) >= MO_64
66
- && (datalo & 1) == 0 && datahi == datalo + 1) {
67
+ if (get_alignment_bits(opc) >= MO_64) {
68
/*
69
* Rm (the second address op) must not overlap Rt or Rt + 1.
70
* Since datalo is aligned, we can simplify the test via alignment.
71
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp opc, TCGReg datalo,
72
tcg_out_ld32_12(s, COND_AL, datalo, addrlo, 0);
73
break;
74
case MO_UQ:
75
+ /* We used pair allocation for datalo, so already should be aligned. */
76
+ tcg_debug_assert((datalo & 1) == 0);
77
+ tcg_debug_assert(datahi == datalo + 1);
78
/* LDRD requires alignment; double-check that. */
79
- if (get_alignment_bits(opc) >= MO_64
80
- && (datalo & 1) == 0 && datahi == datalo + 1) {
81
+ if (get_alignment_bits(opc) >= MO_64) {
82
tcg_out_ldrd_8(s, COND_AL, datalo, addrlo, 0);
83
} else if (datalo == addrlo) {
84
tcg_out_ld32_12(s, COND_AL, datahi, addrlo, 4);
85
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st_index(TCGContext *s, ARMCond cond, MemOp opc,
86
tcg_out_st32_r(s, cond, datalo, addrlo, addend);
87
break;
88
case MO_64:
89
+ /* We used pair allocation for datalo, so already should be aligned. */
90
+ tcg_debug_assert((datalo & 1) == 0);
91
+ tcg_debug_assert(datahi == datalo + 1);
92
/* STRD requires alignment; double-check that. */
93
- if (get_alignment_bits(opc) >= MO_64
94
- && (datalo & 1) == 0 && datahi == datalo + 1) {
95
+ if (get_alignment_bits(opc) >= MO_64) {
96
tcg_out_strd_r(s, cond, datalo, addrlo, addend);
97
} else if (scratch_addend) {
98
tcg_out_st32_rwb(s, cond, datalo, addend, addrlo);
99
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st_direct(TCGContext *s, MemOp opc, TCGReg datalo,
100
tcg_out_st32_12(s, COND_AL, datalo, addrlo, 0);
101
break;
102
case MO_64:
103
+ /* We used pair allocation for datalo, so already should be aligned. */
104
+ tcg_debug_assert((datalo & 1) == 0);
105
+ tcg_debug_assert(datahi == datalo + 1);
106
/* STRD requires alignment; double-check that. */
107
- if (get_alignment_bits(opc) >= MO_64
108
- && (datalo & 1) == 0 && datahi == datalo + 1) {
109
+ if (get_alignment_bits(opc) >= MO_64) {
110
tcg_out_strd_8(s, COND_AL, datalo, addrlo, 0);
111
} else {
112
tcg_out_st32_12(s, COND_AL, datalo, addrlo, 0);
113
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
114
case INDEX_op_qemu_ld_i32:
115
return TARGET_LONG_BITS == 32 ? C_O1_I1(r, l) : C_O1_I2(r, l, l);
116
case INDEX_op_qemu_ld_i64:
117
- return TARGET_LONG_BITS == 32 ? C_O2_I1(r, r, l) : C_O2_I2(r, r, l, l);
118
+ return TARGET_LONG_BITS == 32 ? C_O2_I1(e, p, l) : C_O2_I2(e, p, l, l);
119
case INDEX_op_qemu_st_i32:
120
return TARGET_LONG_BITS == 32 ? C_O0_I2(s, s) : C_O0_I3(s, s, s);
121
case INDEX_op_qemu_st_i64:
122
- return TARGET_LONG_BITS == 32 ? C_O0_I3(s, s, s) : C_O0_I4(s, s, s, s);
123
+ return TARGET_LONG_BITS == 32 ? C_O0_I3(S, p, s) : C_O0_I4(S, p, s, s);
124
125
case INDEX_op_st_vec:
126
return C_O0_I2(w, r);
127
--
128
2.34.1
diff view generated by jsdifflib
New patch
1
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
2
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
3
Message-Id: <20220729172141.1789105-2-richard.henderson@linaro.org>
4
---
5
common-user/host/ppc/safe-syscall.inc.S | 107 ++++++++++++++++++++++++
6
1 file changed, 107 insertions(+)
7
create mode 100644 common-user/host/ppc/safe-syscall.inc.S
1
8
9
diff --git a/common-user/host/ppc/safe-syscall.inc.S b/common-user/host/ppc/safe-syscall.inc.S
10
new file mode 100644
11
index XXXXXXX..XXXXXXX
12
--- /dev/null
13
+++ b/common-user/host/ppc/safe-syscall.inc.S
14
@@ -XXX,XX +XXX,XX @@
15
+/*
16
+ * safe-syscall.inc.S : host-specific assembly fragment
17
+ * to handle signals occurring at the same time as system calls.
18
+ * This is intended to be included by common-user/safe-syscall.S
19
+ *
20
+ * Copyright (C) 2022 Linaro, Ltd.
21
+ *
22
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
23
+ * See the COPYING file in the top-level directory.
24
+ */
25
+
26
+/*
27
+ * Standardize on the _CALL_FOO symbols used by GCC:
28
+ * Apple XCode does not define _CALL_DARWIN.
29
+ * Clang defines _CALL_ELF (64-bit) but not _CALL_SYSV (32-bit).
30
+ */
31
+#if !defined(_CALL_SYSV) && \
32
+ !defined(_CALL_DARWIN) && \
33
+ !defined(_CALL_AIX) && \
34
+ !defined(_CALL_ELF)
35
+# if defined(__APPLE__)
36
+# define _CALL_DARWIN
37
+# elif defined(__ELF__) && TCG_TARGET_REG_BITS == 32
38
+# define _CALL_SYSV
39
+# else
40
+# error "Unknown ABI"
41
+# endif
42
+#endif
43
+
44
+#ifndef _CALL_SYSV
45
+# error "Unsupported ABI"
46
+#endif
47
+
48
+
49
+ .global safe_syscall_base
50
+ .global safe_syscall_start
51
+ .global safe_syscall_end
52
+ .type safe_syscall_base, @function
53
+
54
+ .text
55
+
56
+ /*
57
+ * This is the entry point for making a system call. The calling
58
+ * convention here is that of a C varargs function with the
59
+ * first argument an 'int *' to the signal_pending flag, the
60
+ * second one the system call number (as a 'long'), and all further
61
+ * arguments being syscall arguments (also 'long').
62
+ */
63
+safe_syscall_base:
64
+ .cfi_startproc
65
+ stwu 1, -8(1)
66
+ .cfi_def_cfa_offset 8
67
+ stw 30, 4(1)
68
+ .cfi_offset 30, -4
69
+
70
+ /*
71
+ * We enter with r3 == &signal_pending
72
+ * r4 == syscall number
73
+ * r5 ... r10 == syscall arguments
74
+ * and return the result in r3
75
+ * and the syscall instruction needs
76
+ * r0 == syscall number
77
+ * r3 ... r8 == syscall arguments
78
+ * and returns the result in r3
79
+ * Shuffle everything around appropriately.
80
+ */
81
+ mr 30, 3 /* signal_pending */
82
+ mr 0, 4 /* syscall number */
83
+ mr 3, 5 /* syscall arguments */
84
+ mr 4, 6
85
+ mr 5, 7
86
+ mr 6, 8
87
+ mr 7, 9
88
+ mr 8, 10
89
+
90
+ /*
91
+ * This next sequence of code works in conjunction with the
92
+ * rewind_if_safe_syscall_function(). If a signal is taken
93
+ * and the interrupted PC is anywhere between 'safe_syscall_start'
94
+ * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'.
95
+ * The code sequence must therefore be able to cope with this, and
96
+ * the syscall instruction must be the final one in the sequence.
97
+ */
98
+safe_syscall_start:
99
+ /* if signal_pending is non-zero, don't do the call */
100
+ lwz 12, 0(30)
101
+ cmpwi 0, 12, 0
102
+ bne- 2f
103
+ sc
104
+safe_syscall_end:
105
+ /* code path when we did execute the syscall */
106
+ lwz 30, 4(1) /* restore r30 */
107
+ addi 1, 1, 8 /* restore stack */
108
+ .cfi_restore 30
109
+ .cfi_def_cfa_offset 0
110
+ bnslr+ /* return on success */
111
+ b safe_syscall_set_errno_tail
112
+
113
+ /* code path when we didn't execute the syscall */
114
+2: lwz 30, 4(1)
115
+ addi 1, 1, 8
116
+ addi 3, 0, QEMU_ERESTARTSYS
117
+ b safe_syscall_set_errno_tail
118
+
119
+ .cfi_endproc
120
+
121
+ .size safe_syscall_base, .-safe_syscall_base
122
--
123
2.34.1
diff view generated by jsdifflib
New patch
1
This commit re-enables ppc32 as a linux-user host,
2
as existance of the directory is noted by configure.
1
3
4
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1097
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
7
Message-Id: <20220729172141.1789105-3-richard.henderson@linaro.org>
8
---
9
linux-user/include/host/ppc/host-signal.h | 39 +++++++++++++++++++++++
10
1 file changed, 39 insertions(+)
11
create mode 100644 linux-user/include/host/ppc/host-signal.h
12
13
diff --git a/linux-user/include/host/ppc/host-signal.h b/linux-user/include/host/ppc/host-signal.h
14
new file mode 100644
15
index XXXXXXX..XXXXXXX
16
--- /dev/null
17
+++ b/linux-user/include/host/ppc/host-signal.h
18
@@ -XXX,XX +XXX,XX @@
19
+/*
20
+ * host-signal.h: signal info dependent on the host architecture
21
+ *
22
+ * Copyright (c) 2022 Linaro Ltd.
23
+ *
24
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
25
+ * See the COPYING file in the top-level directory.
26
+ */
27
+
28
+#ifndef PPC_HOST_SIGNAL_H
29
+#define PPC_HOST_SIGNAL_H
30
+
31
+#include <asm/ptrace.h>
32
+
33
+/* The third argument to a SA_SIGINFO handler is ucontext_t. */
34
+typedef ucontext_t host_sigcontext;
35
+
36
+static inline uintptr_t host_signal_pc(host_sigcontext *uc)
37
+{
38
+ return uc->uc_mcontext.regs->nip;
39
+}
40
+
41
+static inline void host_signal_set_pc(host_sigcontext *uc, uintptr_t pc)
42
+{
43
+ uc->uc_mcontext.regs->nip = pc;
44
+}
45
+
46
+static inline void *host_signal_mask(host_sigcontext *uc)
47
+{
48
+ return &uc->uc_sigmask;
49
+}
50
+
51
+static inline bool host_signal_write(siginfo_t *info, host_sigcontext *uc)
52
+{
53
+ return uc->uc_mcontext.regs->trap != 0x400
54
+ && (uc->uc_mcontext.regs->dsisr & 0x02000000);
55
+}
56
+
57
+#endif
58
--
59
2.34.1
diff view generated by jsdifflib
1
For the ABIs in which the syscall return register is not
1
Marking helpers __attribute__((noinline)) prevents an issue
2
also the first function argument register, move the errno
2
with GCC's ipa-split pass under --enable-lto.
3
value into the correct place.
4
3
5
Fixes: a3310c0397e2 ("linux-user: Move syscall error detection into safe_syscall_base")
4
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1454
6
Reported-by: Laurent Vivier <laurent@vivier.eu>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Tested-by: Laurent Vivier <laurent@vivier.eu>
6
Tested-by: Idan Horowitz <idan.horowitz@gmail.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-Id: <20220104190454.542225-1-richard.henderson@linaro.org>
11
---
8
---
12
common-user/host/i386/safe-syscall.inc.S | 1 +
9
include/exec/helper-proto.h | 32 ++++++++++++++++++++++++--------
13
common-user/host/mips/safe-syscall.inc.S | 1 +
10
1 file changed, 24 insertions(+), 8 deletions(-)
14
common-user/host/x86_64/safe-syscall.inc.S | 1 +
15
3 files changed, 3 insertions(+)
16
11
17
diff --git a/common-user/host/i386/safe-syscall.inc.S b/common-user/host/i386/safe-syscall.inc.S
12
diff --git a/include/exec/helper-proto.h b/include/exec/helper-proto.h
18
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
19
--- a/common-user/host/i386/safe-syscall.inc.S
14
--- a/include/exec/helper-proto.h
20
+++ b/common-user/host/i386/safe-syscall.inc.S
15
+++ b/include/exec/helper-proto.h
21
@@ -XXX,XX +XXX,XX @@ safe_syscall_end:
16
@@ -XXX,XX +XXX,XX @@
22
pop %ebp
17
23
.cfi_adjust_cfa_offset -4
18
#include "exec/helper-head.h"
24
.cfi_restore ebp
19
25
+ mov %eax, (%esp)
20
+/*
26
jmp safe_syscall_set_errno_tail
21
+ * Work around an issue with --enable-lto, in which GCC's ipa-split pass
27
22
+ * decides to split out the noreturn code paths that raise an exception,
28
.cfi_endproc
23
+ * taking the __builtin_return_address() along into the new function,
29
diff --git a/common-user/host/mips/safe-syscall.inc.S b/common-user/host/mips/safe-syscall.inc.S
24
+ * where it no longer computes a value that returns to TCG generated code.
30
index XXXXXXX..XXXXXXX 100644
25
+ * Despite the name, the noinline attribute affects splitter, so this
31
--- a/common-user/host/mips/safe-syscall.inc.S
26
+ * prevents the optimization in question. Given that helpers should not
32
+++ b/common-user/host/mips/safe-syscall.inc.S
27
+ * otherwise be called directly, this should have any other visible effect.
33
@@ -XXX,XX +XXX,XX @@ safe_syscall_end:
28
+ *
34
1: USE_ALT_CP(t0)
29
+ * See https://gitlab.com/qemu-project/qemu/-/issues/1454
35
SETUP_GPX(t1)
30
+ */
36
SETUP_GPX64(t0, t1)
31
+#define DEF_HELPER_ATTR __attribute__((noinline))
37
+ move a0, v0
32
+
38
PTR_LA t9, safe_syscall_set_errno_tail
33
#define DEF_HELPER_FLAGS_0(name, flags, ret) \
39
jr t9
34
-dh_ctype(ret) HELPER(name) (void);
40
35
+dh_ctype(ret) HELPER(name) (void) DEF_HELPER_ATTR;
41
diff --git a/common-user/host/x86_64/safe-syscall.inc.S b/common-user/host/x86_64/safe-syscall.inc.S
36
42
index XXXXXXX..XXXXXXX 100644
37
#define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
43
--- a/common-user/host/x86_64/safe-syscall.inc.S
38
-dh_ctype(ret) HELPER(name) (dh_ctype(t1));
44
+++ b/common-user/host/x86_64/safe-syscall.inc.S
39
+dh_ctype(ret) HELPER(name) (dh_ctype(t1)) DEF_HELPER_ATTR;
45
@@ -XXX,XX +XXX,XX @@ safe_syscall_end:
40
46
1: pop %rbp
41
#define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \
47
.cfi_def_cfa_offset 8
42
-dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2));
48
.cfi_restore rbp
43
+dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2)) DEF_HELPER_ATTR;
49
+ mov %eax, %edi
44
50
jmp safe_syscall_set_errno_tail
45
#define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \
51
.cfi_endproc
46
-dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3));
52
47
+dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), \
48
+ dh_ctype(t3)) DEF_HELPER_ATTR;
49
50
#define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \
51
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
52
- dh_ctype(t4));
53
+ dh_ctype(t4)) DEF_HELPER_ATTR;
54
55
#define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
56
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
57
- dh_ctype(t4), dh_ctype(t5));
58
+ dh_ctype(t4), dh_ctype(t5)) DEF_HELPER_ATTR;
59
60
#define DEF_HELPER_FLAGS_6(name, flags, ret, t1, t2, t3, t4, t5, t6) \
61
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
62
- dh_ctype(t4), dh_ctype(t5), dh_ctype(t6));
63
+ dh_ctype(t4), dh_ctype(t5), \
64
+ dh_ctype(t6)) DEF_HELPER_ATTR;
65
66
#define DEF_HELPER_FLAGS_7(name, flags, ret, t1, t2, t3, t4, t5, t6, t7) \
67
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
68
dh_ctype(t4), dh_ctype(t5), dh_ctype(t6), \
69
- dh_ctype(t7));
70
+ dh_ctype(t7)) DEF_HELPER_ATTR;
71
72
#define IN_HELPER_PROTO
73
74
@@ -XXX,XX +XXX,XX @@ dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
75
#undef DEF_HELPER_FLAGS_5
76
#undef DEF_HELPER_FLAGS_6
77
#undef DEF_HELPER_FLAGS_7
78
+#undef DEF_HELPER_ATTR
79
80
#endif /* HELPER_PROTO_H */
53
--
81
--
54
2.25.1
82
2.34.1
55
83
56
84
diff view generated by jsdifflib
1
From: Xiaoyao Li <xiaoyao.li@intel.com>
1
Reuse the decodetree based disassembler from
2
target/loongarch/ for tcg/loongarch64/.
2
3
3
Remove qemu_run_machine_init_done_notifiers() since no implementation
4
The generation of decode-insns.c.inc into ./libcommon.fa.p/ could
4
and user.
5
eventually result in conflict, if any other host requires the same
6
trick, but this is good enough for now.
5
7
6
Fixes: f66dc8737c9 ("vl: move all generic initialization out of vl.c")
8
Reviewed-by: WANG Xuerui <git@xen0n.name>
7
Signed-off-by: Xiaoyao Li <xiaoyao.li@intel.com>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-Id: <20220104024136.1433545-1-xiaoyao.li@intel.com>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
---
11
---
12
include/sysemu/sysemu.h | 1 -
12
disas.c | 2 ++
13
1 file changed, 1 deletion(-)
13
target/loongarch/meson.build | 3 ++-
14
2 files changed, 4 insertions(+), 1 deletion(-)
14
15
15
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
16
diff --git a/disas.c b/disas.c
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/include/sysemu/sysemu.h
18
--- a/disas.c
18
+++ b/include/sysemu/sysemu.h
19
+++ b/disas.c
19
@@ -XXX,XX +XXX,XX @@ extern bool qemu_uuid_set;
20
@@ -XXX,XX +XXX,XX @@ static void initialize_debug_host(CPUDebug *s)
20
void qemu_add_exit_notifier(Notifier *notify);
21
s->info.cap_insn_split = 6;
21
void qemu_remove_exit_notifier(Notifier *notify);
22
#elif defined(__hppa__)
22
23
s->info.print_insn = print_insn_hppa;
23
-void qemu_run_machine_init_done_notifiers(void);
24
+#elif defined(__loongarch__)
24
void qemu_add_machine_init_done_notifier(Notifier *notify);
25
+ s->info.print_insn = print_insn_loongarch;
25
void qemu_remove_machine_init_done_notifier(Notifier *notify);
26
#endif
26
27
}
28
29
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/loongarch/meson.build
32
+++ b/target/loongarch/meson.build
33
@@ -XXX,XX +XXX,XX @@ gen = decodetree.process('insns.decode')
34
loongarch_ss = ss.source_set()
35
loongarch_ss.add(files(
36
'cpu.c',
37
- 'disas.c',
38
))
39
loongarch_tcg_ss = ss.source_set()
40
loongarch_tcg_ss.add(gen)
41
@@ -XXX,XX +XXX,XX @@ loongarch_softmmu_ss.add(files(
42
'iocsr_helper.c',
43
))
44
45
+common_ss.add(when: 'CONFIG_LOONGARCH_DIS', if_true: [files('disas.c'), gen])
46
+
47
loongarch_ss.add_all(when: 'CONFIG_TCG', if_true: [loongarch_tcg_ss])
48
49
target_arch += {'loongarch': loongarch_ss}
27
--
50
--
28
2.25.1
51
2.34.1
29
52
30
53
diff view generated by jsdifflib
New patch
1
While jirl shares the same instruction format as bne etc,
2
it is not assembled the same. In particular, rd is printed
3
first not second and the immediate is not pc-relative.
1
4
5
Decode into the arg_rr_i structure, which prints correctly.
6
This changes the "offs" member to "imm", to update translate.
7
8
Reviewed-by: WANG Xuerui <git@xen0n.name>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
---
11
target/loongarch/insns.decode | 3 ++-
12
target/loongarch/disas.c | 2 +-
13
target/loongarch/insn_trans/trans_branch.c.inc | 2 +-
14
3 files changed, 4 insertions(+), 3 deletions(-)
15
16
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/loongarch/insns.decode
19
+++ b/target/loongarch/insns.decode
20
@@ -XXX,XX +XXX,XX @@
21
@rr_ui12 .... ...... imm:12 rj:5 rd:5 &rr_i
22
@rr_i14s2 .... .... .............. rj:5 rd:5 &rr_i imm=%i14s2
23
@rr_i16 .... .. imm:s16 rj:5 rd:5 &rr_i
24
+@rr_i16s2 .... .. ................ rj:5 rd:5 &rr_i imm=%offs16
25
@hint_r_i12 .... ...... imm:s12 rj:5 hint:5 &hint_r_i
26
@rrr_sa2p1 .... ........ ... .. rk:5 rj:5 rd:5 &rrr_sa sa=%sa2p1
27
@rrr_sa2 .... ........ ... sa:2 rk:5 rj:5 rd:5 &rrr_sa
28
@@ -XXX,XX +XXX,XX @@ beqz 0100 00 ................ ..... ..... @r_offs21
29
bnez 0100 01 ................ ..... ..... @r_offs21
30
bceqz 0100 10 ................ 00 ... ..... @c_offs21
31
bcnez 0100 10 ................ 01 ... ..... @c_offs21
32
-jirl 0100 11 ................ ..... ..... @rr_offs16
33
+jirl 0100 11 ................ ..... ..... @rr_i16s2
34
b 0101 00 .......................... @offs26
35
bl 0101 01 .......................... @offs26
36
beq 0101 10 ................ ..... ..... @rr_offs16
37
diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/loongarch/disas.c
40
+++ b/target/loongarch/disas.c
41
@@ -XXX,XX +XXX,XX @@ INSN(beqz, r_offs)
42
INSN(bnez, r_offs)
43
INSN(bceqz, c_offs)
44
INSN(bcnez, c_offs)
45
-INSN(jirl, rr_offs)
46
+INSN(jirl, rr_i)
47
INSN(b, offs)
48
INSN(bl, offs)
49
INSN(beq, rr_offs)
50
diff --git a/target/loongarch/insn_trans/trans_branch.c.inc b/target/loongarch/insn_trans/trans_branch.c.inc
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/loongarch/insn_trans/trans_branch.c.inc
53
+++ b/target/loongarch/insn_trans/trans_branch.c.inc
54
@@ -XXX,XX +XXX,XX @@ static bool trans_jirl(DisasContext *ctx, arg_jirl *a)
55
TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
56
TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
57
58
- tcg_gen_addi_tl(cpu_pc, src1, a->offs);
59
+ tcg_gen_addi_tl(cpu_pc, src1, a->imm);
60
tcg_gen_movi_tl(dest, ctx->base.pc_next + 4);
61
gen_set_gpr(a->rd, dest, EXT_NONE);
62
tcg_gen_lookup_and_goto_ptr();
63
--
64
2.34.1
diff view generated by jsdifflib
New patch
1
Print both the raw field and the resolved pc-relative
2
address, as we do for branches.
1
3
4
Reviewed-by: WANG Xuerui <git@xen0n.name>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
7
target/loongarch/disas.c | 37 +++++++++++++++++++++++++++++++++----
8
1 file changed, 33 insertions(+), 4 deletions(-)
9
10
diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/loongarch/disas.c
13
+++ b/target/loongarch/disas.c
14
@@ -XXX,XX +XXX,XX @@ INSN(fsel, fffc)
15
INSN(addu16i_d, rr_i)
16
INSN(lu12i_w, r_i)
17
INSN(lu32i_d, r_i)
18
-INSN(pcaddi, r_i)
19
-INSN(pcalau12i, r_i)
20
-INSN(pcaddu12i, r_i)
21
-INSN(pcaddu18i, r_i)
22
INSN(ll_w, rr_i)
23
INSN(sc_w, rr_i)
24
INSN(ll_d, rr_i)
25
@@ -XXX,XX +XXX,XX @@ static bool trans_fcmp_cond_##suffix(DisasContext *ctx, \
26
27
FCMP_INSN(s)
28
FCMP_INSN(d)
29
+
30
+#define PCADD_INSN(name) \
31
+static bool trans_##name(DisasContext *ctx, arg_##name *a) \
32
+{ \
33
+ output(ctx, #name, "r%d, %d # 0x%" PRIx64, \
34
+ a->rd, a->imm, gen_##name(ctx->pc, a->imm)); \
35
+ return true; \
36
+}
37
+
38
+static uint64_t gen_pcaddi(uint64_t pc, int imm)
39
+{
40
+ return pc + (imm << 2);
41
+}
42
+
43
+static uint64_t gen_pcalau12i(uint64_t pc, int imm)
44
+{
45
+ return (pc + (imm << 12)) & ~0xfff;
46
+}
47
+
48
+static uint64_t gen_pcaddu12i(uint64_t pc, int imm)
49
+{
50
+ return pc + (imm << 12);
51
+}
52
+
53
+static uint64_t gen_pcaddu18i(uint64_t pc, int imm)
54
+{
55
+ return pc + ((uint64_t)(imm) << 18);
56
+}
57
+
58
+PCADD_INSN(pcaddi)
59
+PCADD_INSN(pcalau12i)
60
+PCADD_INSN(pcaddu12i)
61
+PCADD_INSN(pcaddu18i)
62
--
63
2.34.1
diff view generated by jsdifflib
New patch
1
From: Rui Wang <wangrui@loongson.cn>
1
2
3
diff:
4
Imm Before After
5
0000000000000000 addi.w rd, zero, 0 addi.w rd, zero, 0
6
lu52i.d rd, zero, 0
7
00000000fffff800 lu12i.w rd, -1 addi.w rd, zero, -2048
8
ori rd, rd, 2048 lu32i.d rd, 0
9
lu32i.d rd, 0
10
11
Reviewed-by: WANG Xuerui <git@xen0n.name>
12
Signed-off-by: Rui Wang <wangrui@loongson.cn>
13
Message-Id: <20221107144713.845550-1-wangrui@loongson.cn>
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
15
---
16
tcg/loongarch64/tcg-target.c.inc | 35 +++++++++++---------------------
17
1 file changed, 12 insertions(+), 23 deletions(-)
18
19
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
20
index XXXXXXX..XXXXXXX 100644
21
--- a/tcg/loongarch64/tcg-target.c.inc
22
+++ b/tcg/loongarch64/tcg-target.c.inc
23
@@ -XXX,XX +XXX,XX @@ static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
24
return true;
25
}
26
27
-static bool imm_part_needs_loading(bool high_bits_are_ones,
28
- tcg_target_long part)
29
-{
30
- if (high_bits_are_ones) {
31
- return part != -1;
32
- } else {
33
- return part != 0;
34
- }
35
-}
36
-
37
/* Loads a 32-bit immediate into rd, sign-extended. */
38
static void tcg_out_movi_i32(TCGContext *s, TCGReg rd, int32_t val)
39
{
40
@@ -XXX,XX +XXX,XX @@ static void tcg_out_movi_i32(TCGContext *s, TCGReg rd, int32_t val)
41
tcg_target_long hi12 = sextreg(val, 12, 20);
42
43
/* Single-instruction cases. */
44
- if (lo == val) {
45
- /* val fits in simm12: addi.w rd, zero, val */
46
- tcg_out_opc_addi_w(s, rd, TCG_REG_ZERO, val);
47
- return;
48
- }
49
- if (0x800 <= val && val <= 0xfff) {
50
+ if (hi12 == 0) {
51
/* val fits in uimm12: ori rd, zero, val */
52
tcg_out_opc_ori(s, rd, TCG_REG_ZERO, val);
53
return;
54
}
55
+ if (hi12 == sextreg(lo, 12, 20)) {
56
+ /* val fits in simm12: addi.w rd, zero, val */
57
+ tcg_out_opc_addi_w(s, rd, TCG_REG_ZERO, val);
58
+ return;
59
+ }
60
61
/* High bits must be set; load with lu12i.w + optional ori. */
62
tcg_out_opc_lu12i_w(s, rd, hi12);
63
@@ -XXX,XX +XXX,XX @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
64
65
intptr_t pc_offset;
66
tcg_target_long val_lo, val_hi, pc_hi, offset_hi;
67
- tcg_target_long hi32, hi52;
68
- bool rd_high_bits_are_ones;
69
+ tcg_target_long hi12, hi32, hi52;
70
71
/* Value fits in signed i32. */
72
if (type == TCG_TYPE_I32 || val == (int32_t)val) {
73
@@ -XXX,XX +XXX,XX @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
74
return;
75
}
76
77
+ hi12 = sextreg(val, 12, 20);
78
hi32 = sextreg(val, 32, 20);
79
hi52 = sextreg(val, 52, 12);
80
81
/* Single cu52i.d case. */
82
- if (ctz64(val) >= 52) {
83
+ if ((hi52 != 0) && (ctz64(val) >= 52)) {
84
tcg_out_opc_cu52i_d(s, rd, TCG_REG_ZERO, hi52);
85
return;
86
}
87
88
/* Slow path. Initialize the low 32 bits, then concat high bits. */
89
tcg_out_movi_i32(s, rd, val);
90
- rd_high_bits_are_ones = (int32_t)val < 0;
91
92
- if (imm_part_needs_loading(rd_high_bits_are_ones, hi32)) {
93
+ /* Load hi32 and hi52 explicitly when they are unexpected values. */
94
+ if (hi32 != sextreg(hi12, 20, 20)) {
95
tcg_out_opc_cu32i_d(s, rd, hi32);
96
- rd_high_bits_are_ones = hi32 < 0;
97
}
98
99
- if (imm_part_needs_loading(rd_high_bits_are_ones, hi52)) {
100
+ if (hi52 != sextreg(hi32, 20, 12)) {
101
tcg_out_opc_cu52i_d(s, rd, rd, hi52);
102
}
103
}
104
--
105
2.34.1
diff view generated by jsdifflib
1
Bitwise operations are easy to fold, because the operation is
1
Regenerate with ADDU16I included:
2
identical regardless of element size. But add and sub need
3
extra element size info that is not currently propagated.
4
2
5
Fixes: 2f9f08ba43d
3
$ cd loongarch-opcodes/scripts/go
6
Cc: qemu-stable@nongnu.org
4
$ go run ./genqemutcgdefs > $QEMU/tcg/loongarch64/tcg-insn-defs.c.inc
7
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/799
5
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: WANG Xuerui <git@xen0n.name>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
---
9
---
11
tcg/optimize.c | 49 ++++++++++++++++++++++++++++++++++++++-----------
10
tcg/loongarch64/tcg-insn-defs.c.inc | 10 +++++++++-
12
1 file changed, 38 insertions(+), 11 deletions(-)
11
1 file changed, 9 insertions(+), 1 deletion(-)
13
12
14
diff --git a/tcg/optimize.c b/tcg/optimize.c
13
diff --git a/tcg/loongarch64/tcg-insn-defs.c.inc b/tcg/loongarch64/tcg-insn-defs.c.inc
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/tcg/optimize.c
15
--- a/tcg/loongarch64/tcg-insn-defs.c.inc
17
+++ b/tcg/optimize.c
16
+++ b/tcg/loongarch64/tcg-insn-defs.c.inc
18
@@ -XXX,XX +XXX,XX @@ static uint64_t do_constant_folding_2(TCGOpcode op, uint64_t x, uint64_t y)
17
@@ -XXX,XX +XXX,XX @@
19
CASE_OP_32_64(mul):
18
*
20
return x * y;
19
* This file is auto-generated by genqemutcgdefs from
21
20
* https://github.com/loongson-community/loongarch-opcodes,
22
- CASE_OP_32_64(and):
21
- * from commit 961f0c60f5b63e574d785995600c71ad5413fdc4.
23
+ CASE_OP_32_64_VEC(and):
22
+ * from commit 25ca7effe9d88101c1cf96c4005423643386d81f.
24
return x & y;
23
* DO NOT EDIT.
25
24
*/
26
- CASE_OP_32_64(or):
25
27
+ CASE_OP_32_64_VEC(or):
26
@@ -XXX,XX +XXX,XX @@ typedef enum {
28
return x | y;
27
OPC_ANDI = 0x03400000,
29
28
OPC_ORI = 0x03800000,
30
- CASE_OP_32_64(xor):
29
OPC_XORI = 0x03c00000,
31
+ CASE_OP_32_64_VEC(xor):
30
+ OPC_ADDU16I_D = 0x10000000,
32
return x ^ y;
31
OPC_LU12I_W = 0x14000000,
33
32
OPC_CU32I_D = 0x16000000,
34
case INDEX_op_shl_i32:
33
OPC_PCADDU2I = 0x18000000,
35
@@ -XXX,XX +XXX,XX @@ static uint64_t do_constant_folding_2(TCGOpcode op, uint64_t x, uint64_t y)
34
@@ -XXX,XX +XXX,XX @@ tcg_out_opc_xori(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk12)
36
case INDEX_op_rotl_i64:
35
tcg_out32(s, encode_djuk12_insn(OPC_XORI, d, j, uk12));
37
return rol64(x, y & 63);
38
39
- CASE_OP_32_64(not):
40
+ CASE_OP_32_64_VEC(not):
41
return ~x;
42
43
CASE_OP_32_64(neg):
44
return -x;
45
46
- CASE_OP_32_64(andc):
47
+ CASE_OP_32_64_VEC(andc):
48
return x & ~y;
49
50
- CASE_OP_32_64(orc):
51
+ CASE_OP_32_64_VEC(orc):
52
return x | ~y;
53
54
CASE_OP_32_64(eqv):
55
@@ -XXX,XX +XXX,XX @@ static bool fold_const2(OptContext *ctx, TCGOp *op)
56
return false;
57
}
36
}
58
37
59
+static bool fold_commutative(OptContext *ctx, TCGOp *op)
38
+/* Emits the `addu16i.d d, j, sk16` instruction. */
39
+static void __attribute__((unused))
40
+tcg_out_opc_addu16i_d(TCGContext *s, TCGReg d, TCGReg j, int32_t sk16)
60
+{
41
+{
61
+ swap_commutative(op->args[0], &op->args[1], &op->args[2]);
42
+ tcg_out32(s, encode_djsk16_insn(OPC_ADDU16I_D, d, j, sk16));
62
+ return false;
63
+}
43
+}
64
+
44
+
65
static bool fold_const2_commutative(OptContext *ctx, TCGOp *op)
45
/* Emits the `lu12i.w d, sj20` instruction. */
66
{
46
static void __attribute__((unused))
67
swap_commutative(op->args[0], &op->args[1], &op->args[2]);
47
tcg_out_opc_lu12i_w(TCGContext *s, TCGReg d, int32_t sj20)
68
@@ -XXX,XX +XXX,XX @@ static bool fold_add(OptContext *ctx, TCGOp *op)
69
return false;
70
}
71
72
+/* We cannot as yet do_constant_folding with vectors. */
73
+static bool fold_add_vec(OptContext *ctx, TCGOp *op)
74
+{
75
+ if (fold_commutative(ctx, op) ||
76
+ fold_xi_to_x(ctx, op, 0)) {
77
+ return true;
78
+ }
79
+ return false;
80
+}
81
+
82
static bool fold_addsub2(OptContext *ctx, TCGOp *op, bool add)
83
{
84
if (arg_is_const(op->args[2]) && arg_is_const(op->args[3]) &&
85
@@ -XXX,XX +XXX,XX @@ static bool fold_sub_to_neg(OptContext *ctx, TCGOp *op)
86
return false;
87
}
88
89
-static bool fold_sub(OptContext *ctx, TCGOp *op)
90
+/* We cannot as yet do_constant_folding with vectors. */
91
+static bool fold_sub_vec(OptContext *ctx, TCGOp *op)
92
{
93
- if (fold_const2(ctx, op) ||
94
- fold_xx_to_i(ctx, op, 0) ||
95
+ if (fold_xx_to_i(ctx, op, 0) ||
96
fold_xi_to_x(ctx, op, 0) ||
97
fold_sub_to_neg(ctx, op)) {
98
return true;
99
@@ -XXX,XX +XXX,XX @@ static bool fold_sub(OptContext *ctx, TCGOp *op)
100
return false;
101
}
102
103
+static bool fold_sub(OptContext *ctx, TCGOp *op)
104
+{
105
+ return fold_const2(ctx, op) || fold_sub_vec(ctx, op);
106
+}
107
+
108
static bool fold_sub2(OptContext *ctx, TCGOp *op)
109
{
110
return fold_addsub2(ctx, op, false);
111
@@ -XXX,XX +XXX,XX @@ void tcg_optimize(TCGContext *s)
112
* Sorted alphabetically by opcode as much as possible.
113
*/
114
switch (opc) {
115
- CASE_OP_32_64_VEC(add):
116
+ CASE_OP_32_64(add):
117
done = fold_add(&ctx, op);
118
break;
119
+ case INDEX_op_add_vec:
120
+ done = fold_add_vec(&ctx, op);
121
+ break;
122
CASE_OP_32_64(add2):
123
done = fold_add2(&ctx, op);
124
break;
125
@@ -XXX,XX +XXX,XX @@ void tcg_optimize(TCGContext *s)
126
CASE_OP_32_64(sextract):
127
done = fold_sextract(&ctx, op);
128
break;
129
- CASE_OP_32_64_VEC(sub):
130
+ CASE_OP_32_64(sub):
131
done = fold_sub(&ctx, op);
132
break;
133
+ case INDEX_op_sub_vec:
134
+ done = fold_sub_vec(&ctx, op);
135
+ break;
136
CASE_OP_32_64(sub2):
137
done = fold_sub2(&ctx, op);
138
break;
139
--
48
--
140
2.25.1
49
2.34.1
141
50
142
51
diff view generated by jsdifflib
New patch
1
Adjust the constraints to allow any int32_t for immediate
2
addition. Split immediate adds into addu16i + addi, which
3
covers quite a lot of the immediate space. For the hole in
4
the middle, load the constant into TMP0 instead.
1
5
6
Reviewed-by: WANG Xuerui <git@xen0n.name>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
9
tcg/loongarch64/tcg-target-con-set.h | 4 +-
10
tcg/loongarch64/tcg-target-con-str.h | 2 +-
11
tcg/loongarch64/tcg-target.c.inc | 57 ++++++++++++++++++++++++----
12
3 files changed, 53 insertions(+), 10 deletions(-)
13
14
diff --git a/tcg/loongarch64/tcg-target-con-set.h b/tcg/loongarch64/tcg-target-con-set.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tcg/loongarch64/tcg-target-con-set.h
17
+++ b/tcg/loongarch64/tcg-target-con-set.h
18
@@ -XXX,XX +XXX,XX @@ C_O1_I1(r, L)
19
C_O1_I2(r, r, rC)
20
C_O1_I2(r, r, ri)
21
C_O1_I2(r, r, rI)
22
+C_O1_I2(r, r, rJ)
23
C_O1_I2(r, r, rU)
24
C_O1_I2(r, r, rW)
25
C_O1_I2(r, r, rZ)
26
C_O1_I2(r, 0, rZ)
27
-C_O1_I2(r, rZ, rN)
28
+C_O1_I2(r, rZ, ri)
29
+C_O1_I2(r, rZ, rJ)
30
C_O1_I2(r, rZ, rZ)
31
diff --git a/tcg/loongarch64/tcg-target-con-str.h b/tcg/loongarch64/tcg-target-con-str.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/tcg/loongarch64/tcg-target-con-str.h
34
+++ b/tcg/loongarch64/tcg-target-con-str.h
35
@@ -XXX,XX +XXX,XX @@ REGS('L', ALL_GENERAL_REGS & ~SOFTMMU_RESERVE_REGS)
36
* CONST(letter, TCG_CT_CONST_* bit set)
37
*/
38
CONST('I', TCG_CT_CONST_S12)
39
-CONST('N', TCG_CT_CONST_N12)
40
+CONST('J', TCG_CT_CONST_S32)
41
CONST('U', TCG_CT_CONST_U12)
42
CONST('Z', TCG_CT_CONST_ZERO)
43
CONST('C', TCG_CT_CONST_C12)
44
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
45
index XXXXXXX..XXXXXXX 100644
46
--- a/tcg/loongarch64/tcg-target.c.inc
47
+++ b/tcg/loongarch64/tcg-target.c.inc
48
@@ -XXX,XX +XXX,XX @@ static const int tcg_target_call_oarg_regs[] = {
49
50
#define TCG_CT_CONST_ZERO 0x100
51
#define TCG_CT_CONST_S12 0x200
52
-#define TCG_CT_CONST_N12 0x400
53
+#define TCG_CT_CONST_S32 0x400
54
#define TCG_CT_CONST_U12 0x800
55
#define TCG_CT_CONST_C12 0x1000
56
#define TCG_CT_CONST_WSZ 0x2000
57
@@ -XXX,XX +XXX,XX @@ static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
58
if ((ct & TCG_CT_CONST_S12) && val == sextreg(val, 0, 12)) {
59
return true;
60
}
61
- if ((ct & TCG_CT_CONST_N12) && -val == sextreg(-val, 0, 12)) {
62
+ if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) {
63
return true;
64
}
65
if ((ct & TCG_CT_CONST_U12) && val >= 0 && val <= 0xfff) {
66
@@ -XXX,XX +XXX,XX @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
67
}
68
}
69
70
+static void tcg_out_addi(TCGContext *s, TCGType type, TCGReg rd,
71
+ TCGReg rs, tcg_target_long imm)
72
+{
73
+ tcg_target_long lo12 = sextreg(imm, 0, 12);
74
+ tcg_target_long hi16 = sextreg(imm - lo12, 16, 16);
75
+
76
+ /*
77
+ * Note that there's a hole in between hi16 and lo12:
78
+ *
79
+ * 3 2 1 0
80
+ * 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
81
+ * ...+-------------------------------+-------+-----------------------+
82
+ * | hi16 | | lo12 |
83
+ * ...+-------------------------------+-------+-----------------------+
84
+ *
85
+ * For bits within that hole, it's more efficient to use LU12I and ADD.
86
+ */
87
+ if (imm == (hi16 << 16) + lo12) {
88
+ if (hi16) {
89
+ tcg_out_opc_addu16i_d(s, rd, rs, hi16);
90
+ rs = rd;
91
+ }
92
+ if (type == TCG_TYPE_I32) {
93
+ tcg_out_opc_addi_w(s, rd, rs, lo12);
94
+ } else if (lo12) {
95
+ tcg_out_opc_addi_d(s, rd, rs, lo12);
96
+ } else {
97
+ tcg_out_mov(s, type, rd, rs);
98
+ }
99
+ } else {
100
+ tcg_out_movi(s, type, TCG_REG_TMP0, imm);
101
+ if (type == TCG_TYPE_I32) {
102
+ tcg_out_opc_add_w(s, rd, rs, TCG_REG_TMP0);
103
+ } else {
104
+ tcg_out_opc_add_d(s, rd, rs, TCG_REG_TMP0);
105
+ }
106
+ }
107
+}
108
+
109
static void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg)
110
{
111
tcg_out_opc_andi(s, ret, arg, 0xff);
112
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
113
114
case INDEX_op_add_i32:
115
if (c2) {
116
- tcg_out_opc_addi_w(s, a0, a1, a2);
117
+ tcg_out_addi(s, TCG_TYPE_I32, a0, a1, a2);
118
} else {
119
tcg_out_opc_add_w(s, a0, a1, a2);
120
}
121
break;
122
case INDEX_op_add_i64:
123
if (c2) {
124
- tcg_out_opc_addi_d(s, a0, a1, a2);
125
+ tcg_out_addi(s, TCG_TYPE_I64, a0, a1, a2);
126
} else {
127
tcg_out_opc_add_d(s, a0, a1, a2);
128
}
129
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
130
131
case INDEX_op_sub_i32:
132
if (c2) {
133
- tcg_out_opc_addi_w(s, a0, a1, -a2);
134
+ tcg_out_addi(s, TCG_TYPE_I32, a0, a1, -a2);
135
} else {
136
tcg_out_opc_sub_w(s, a0, a1, a2);
137
}
138
break;
139
case INDEX_op_sub_i64:
140
if (c2) {
141
- tcg_out_opc_addi_d(s, a0, a1, -a2);
142
+ tcg_out_addi(s, TCG_TYPE_I64, a0, a1, -a2);
143
} else {
144
tcg_out_opc_sub_d(s, a0, a1, a2);
145
}
146
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
147
return C_O1_I2(r, r, ri);
148
149
case INDEX_op_add_i32:
150
+ return C_O1_I2(r, r, ri);
151
case INDEX_op_add_i64:
152
- return C_O1_I2(r, r, rI);
153
+ return C_O1_I2(r, r, rJ);
154
155
case INDEX_op_and_i32:
156
case INDEX_op_and_i64:
157
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
158
return C_O1_I2(r, 0, rZ);
159
160
case INDEX_op_sub_i32:
161
+ return C_O1_I2(r, rZ, ri);
162
case INDEX_op_sub_i64:
163
- return C_O1_I2(r, rZ, rN);
164
+ return C_O1_I2(r, rZ, rJ);
165
166
case INDEX_op_mul_i32:
167
case INDEX_op_mul_i64:
168
--
169
2.34.1
diff view generated by jsdifflib
New patch
1
Split out a helper function, tcg_out_setcond_int, which
2
does not always produce the complete boolean result, but
3
returns a set of flags to do so.
1
4
5
Accept all int32_t as constant input, so that LE/GT can
6
adjust the constant to LT.
7
8
Reviewed-by: WANG Xuerui <git@xen0n.name>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
---
11
tcg/loongarch64/tcg-target.c.inc | 165 +++++++++++++++++++++----------
12
1 file changed, 115 insertions(+), 50 deletions(-)
13
14
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tcg/loongarch64/tcg-target.c.inc
17
+++ b/tcg/loongarch64/tcg-target.c.inc
18
@@ -XXX,XX +XXX,XX @@ static void tcg_out_clzctz(TCGContext *s, LoongArchInsn opc,
19
tcg_out_opc_or(s, a0, TCG_REG_TMP0, a0);
20
}
21
22
-static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
23
- TCGReg arg1, TCGReg arg2, bool c2)
24
-{
25
- TCGReg tmp;
26
+#define SETCOND_INV TCG_TARGET_NB_REGS
27
+#define SETCOND_NEZ (SETCOND_INV << 1)
28
+#define SETCOND_FLAGS (SETCOND_INV | SETCOND_NEZ)
29
30
- if (c2) {
31
- tcg_debug_assert(arg2 == 0);
32
+static int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret,
33
+ TCGReg arg1, tcg_target_long arg2, bool c2)
34
+{
35
+ int flags = 0;
36
+
37
+ switch (cond) {
38
+ case TCG_COND_EQ: /* -> NE */
39
+ case TCG_COND_GE: /* -> LT */
40
+ case TCG_COND_GEU: /* -> LTU */
41
+ case TCG_COND_GT: /* -> LE */
42
+ case TCG_COND_GTU: /* -> LEU */
43
+ cond = tcg_invert_cond(cond);
44
+ flags ^= SETCOND_INV;
45
+ break;
46
+ default:
47
+ break;
48
}
49
50
switch (cond) {
51
- case TCG_COND_EQ:
52
- if (c2) {
53
- tmp = arg1;
54
- } else {
55
- tcg_out_opc_sub_d(s, ret, arg1, arg2);
56
- tmp = ret;
57
- }
58
- tcg_out_opc_sltui(s, ret, tmp, 1);
59
- break;
60
- case TCG_COND_NE:
61
- if (c2) {
62
- tmp = arg1;
63
- } else {
64
- tcg_out_opc_sub_d(s, ret, arg1, arg2);
65
- tmp = ret;
66
- }
67
- tcg_out_opc_sltu(s, ret, TCG_REG_ZERO, tmp);
68
- break;
69
- case TCG_COND_LT:
70
- tcg_out_opc_slt(s, ret, arg1, arg2);
71
- break;
72
- case TCG_COND_GE:
73
- tcg_out_opc_slt(s, ret, arg1, arg2);
74
- tcg_out_opc_xori(s, ret, ret, 1);
75
- break;
76
case TCG_COND_LE:
77
- tcg_out_setcond(s, TCG_COND_GE, ret, arg2, arg1, false);
78
- break;
79
- case TCG_COND_GT:
80
- tcg_out_setcond(s, TCG_COND_LT, ret, arg2, arg1, false);
81
- break;
82
- case TCG_COND_LTU:
83
- tcg_out_opc_sltu(s, ret, arg1, arg2);
84
- break;
85
- case TCG_COND_GEU:
86
- tcg_out_opc_sltu(s, ret, arg1, arg2);
87
- tcg_out_opc_xori(s, ret, ret, 1);
88
- break;
89
case TCG_COND_LEU:
90
- tcg_out_setcond(s, TCG_COND_GEU, ret, arg2, arg1, false);
91
+ /*
92
+ * If we have a constant input, the most efficient way to implement
93
+ * LE is by adding 1 and using LT. Watch out for wrap around for LEU.
94
+ * We don't need to care for this for LE because the constant input
95
+ * is still constrained to int32_t, and INT32_MAX+1 is representable
96
+ * in the 64-bit temporary register.
97
+ */
98
+ if (c2) {
99
+ if (cond == TCG_COND_LEU) {
100
+ /* unsigned <= -1 is true */
101
+ if (arg2 == -1) {
102
+ tcg_out_movi(s, TCG_TYPE_REG, ret, !(flags & SETCOND_INV));
103
+ return ret;
104
+ }
105
+ cond = TCG_COND_LTU;
106
+ } else {
107
+ cond = TCG_COND_LT;
108
+ }
109
+ arg2 += 1;
110
+ } else {
111
+ TCGReg tmp = arg2;
112
+ arg2 = arg1;
113
+ arg1 = tmp;
114
+ cond = tcg_swap_cond(cond); /* LE -> GE */
115
+ cond = tcg_invert_cond(cond); /* GE -> LT */
116
+ flags ^= SETCOND_INV;
117
+ }
118
break;
119
- case TCG_COND_GTU:
120
- tcg_out_setcond(s, TCG_COND_LTU, ret, arg2, arg1, false);
121
+ default:
122
break;
123
+ }
124
+
125
+ switch (cond) {
126
+ case TCG_COND_NE:
127
+ flags |= SETCOND_NEZ;
128
+ if (!c2) {
129
+ tcg_out_opc_xor(s, ret, arg1, arg2);
130
+ } else if (arg2 == 0) {
131
+ ret = arg1;
132
+ } else if (arg2 >= 0 && arg2 <= 0xfff) {
133
+ tcg_out_opc_xori(s, ret, arg1, arg2);
134
+ } else {
135
+ tcg_out_addi(s, TCG_TYPE_REG, ret, arg1, -arg2);
136
+ }
137
+ break;
138
+
139
+ case TCG_COND_LT:
140
+ case TCG_COND_LTU:
141
+ if (c2) {
142
+ if (arg2 >= -0x800 && arg2 <= 0x7ff) {
143
+ if (cond == TCG_COND_LT) {
144
+ tcg_out_opc_slti(s, ret, arg1, arg2);
145
+ } else {
146
+ tcg_out_opc_sltui(s, ret, arg1, arg2);
147
+ }
148
+ break;
149
+ }
150
+ tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP0, arg2);
151
+ arg2 = TCG_REG_TMP0;
152
+ }
153
+ if (cond == TCG_COND_LT) {
154
+ tcg_out_opc_slt(s, ret, arg1, arg2);
155
+ } else {
156
+ tcg_out_opc_sltu(s, ret, arg1, arg2);
157
+ }
158
+ break;
159
+
160
default:
161
g_assert_not_reached();
162
break;
163
}
164
+
165
+ return ret | flags;
166
+}
167
+
168
+static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
169
+ TCGReg arg1, tcg_target_long arg2, bool c2)
170
+{
171
+ int tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2);
172
+
173
+ if (tmpflags != ret) {
174
+ TCGReg tmp = tmpflags & ~SETCOND_FLAGS;
175
+
176
+ switch (tmpflags & SETCOND_FLAGS) {
177
+ case SETCOND_INV:
178
+ /* Intermediate result is boolean: simply invert. */
179
+ tcg_out_opc_xori(s, ret, tmp, 1);
180
+ break;
181
+ case SETCOND_NEZ:
182
+ /* Intermediate result is zero/non-zero: test != 0. */
183
+ tcg_out_opc_sltu(s, ret, TCG_REG_ZERO, tmp);
184
+ break;
185
+ case SETCOND_NEZ | SETCOND_INV:
186
+ /* Intermediate result is zero/non-zero: test == 0. */
187
+ tcg_out_opc_sltui(s, ret, tmp, 1);
188
+ break;
189
+ default:
190
+ g_assert_not_reached();
191
+ }
192
+ }
193
}
194
195
/*
196
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
197
case INDEX_op_ctz_i64:
198
return C_O1_I2(r, r, rW);
199
200
- case INDEX_op_setcond_i32:
201
- case INDEX_op_setcond_i64:
202
- return C_O1_I2(r, r, rZ);
203
-
204
case INDEX_op_deposit_i32:
205
case INDEX_op_deposit_i64:
206
/* Must deposit into the same register as input */
207
return C_O1_I2(r, 0, rZ);
208
209
case INDEX_op_sub_i32:
210
+ case INDEX_op_setcond_i32:
211
return C_O1_I2(r, rZ, ri);
212
case INDEX_op_sub_i64:
213
+ case INDEX_op_setcond_i64:
214
return C_O1_I2(r, rZ, rJ);
215
216
case INDEX_op_mul_i32:
217
--
218
2.34.1
diff view generated by jsdifflib
New patch
1
Reviewed-by: WANG Xuerui <git@xen0n.name>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
4
tcg/loongarch64/tcg-target-con-set.h | 1 +
5
tcg/loongarch64/tcg-target.h | 4 ++--
6
tcg/loongarch64/tcg-target.c.inc | 33 ++++++++++++++++++++++++++++
7
3 files changed, 36 insertions(+), 2 deletions(-)
1
8
9
diff --git a/tcg/loongarch64/tcg-target-con-set.h b/tcg/loongarch64/tcg-target-con-set.h
10
index XXXXXXX..XXXXXXX 100644
11
--- a/tcg/loongarch64/tcg-target-con-set.h
12
+++ b/tcg/loongarch64/tcg-target-con-set.h
13
@@ -XXX,XX +XXX,XX @@ C_O1_I2(r, 0, rZ)
14
C_O1_I2(r, rZ, ri)
15
C_O1_I2(r, rZ, rJ)
16
C_O1_I2(r, rZ, rZ)
17
+C_O1_I4(r, rZ, rJ, rZ, rZ)
18
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/tcg/loongarch64/tcg-target.h
21
+++ b/tcg/loongarch64/tcg-target.h
22
@@ -XXX,XX +XXX,XX @@ typedef enum {
23
#define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL
24
25
/* optional instructions */
26
-#define TCG_TARGET_HAS_movcond_i32 0
27
+#define TCG_TARGET_HAS_movcond_i32 1
28
#define TCG_TARGET_HAS_div_i32 1
29
#define TCG_TARGET_HAS_rem_i32 1
30
#define TCG_TARGET_HAS_div2_i32 0
31
@@ -XXX,XX +XXX,XX @@ typedef enum {
32
#define TCG_TARGET_HAS_qemu_st8_i32 0
33
34
/* 64-bit operations */
35
-#define TCG_TARGET_HAS_movcond_i64 0
36
+#define TCG_TARGET_HAS_movcond_i64 1
37
#define TCG_TARGET_HAS_div_i64 1
38
#define TCG_TARGET_HAS_rem_i64 1
39
#define TCG_TARGET_HAS_div2_i64 0
40
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
41
index XXXXXXX..XXXXXXX 100644
42
--- a/tcg/loongarch64/tcg-target.c.inc
43
+++ b/tcg/loongarch64/tcg-target.c.inc
44
@@ -XXX,XX +XXX,XX @@ static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
45
}
46
}
47
48
+static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
49
+ TCGReg c1, tcg_target_long c2, bool const2,
50
+ TCGReg v1, TCGReg v2)
51
+{
52
+ int tmpflags = tcg_out_setcond_int(s, cond, TCG_REG_TMP0, c1, c2, const2);
53
+ TCGReg t;
54
+
55
+ /* Standardize the test below to t != 0. */
56
+ if (tmpflags & SETCOND_INV) {
57
+ t = v1, v1 = v2, v2 = t;
58
+ }
59
+
60
+ t = tmpflags & ~SETCOND_FLAGS;
61
+ if (v1 == TCG_REG_ZERO) {
62
+ tcg_out_opc_masknez(s, ret, v2, t);
63
+ } else if (v2 == TCG_REG_ZERO) {
64
+ tcg_out_opc_maskeqz(s, ret, v1, t);
65
+ } else {
66
+ tcg_out_opc_masknez(s, TCG_REG_TMP2, v2, t); /* t ? 0 : v2 */
67
+ tcg_out_opc_maskeqz(s, TCG_REG_TMP1, v1, t); /* t ? v1 : 0 */
68
+ tcg_out_opc_or(s, ret, TCG_REG_TMP1, TCG_REG_TMP2);
69
+ }
70
+}
71
+
72
/*
73
* Branch helpers
74
*/
75
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
76
tcg_out_setcond(s, args[3], a0, a1, a2, c2);
77
break;
78
79
+ case INDEX_op_movcond_i32:
80
+ case INDEX_op_movcond_i64:
81
+ tcg_out_movcond(s, args[5], a0, a1, a2, c2, args[3], args[4]);
82
+ break;
83
+
84
case INDEX_op_ld8s_i32:
85
case INDEX_op_ld8s_i64:
86
tcg_out_ldst(s, OPC_LD_B, a0, a1, a2);
87
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
88
case INDEX_op_remu_i64:
89
return C_O1_I2(r, rZ, rZ);
90
91
+ case INDEX_op_movcond_i32:
92
+ case INDEX_op_movcond_i64:
93
+ return C_O1_I4(r, rZ, rJ, rZ, rZ);
94
+
95
default:
96
g_assert_not_reached();
97
}
98
--
99
2.34.1
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Take the w^x split into account when computing the
2
pc-relative distance to an absolute pointer.
2
3
3
When building using GCC 8.3.0 on loongarch64 (Loongnix) we get:
4
5
In file included from ../linux-user/signal.c:33:
6
../linux-user/host/loongarch64/host-signal.h: In function ‘host_signal_write’:
7
../linux-user/host/loongarch64/host-signal.h:57:9: error: a label can only be part of a statement and a declaration is not a statement
8
uint32_t sel = (insn >> 15) & 0b11111111111;
9
^~~~~~~~
10
11
We don't use the 'sel' variable more than once, so drop it.
12
13
Meson output for the record:
14
15
Host machine cpu family: loongarch64
16
Host machine cpu: loongarch64
17
C compiler for the host machine: cc (gcc 8.3.0 "cc (Loongnix 8.3.0-6.lnd.vec.27) 8.3.0")
18
C linker for the host machine: cc ld.bfd 2.31.1-system
19
20
Fixes: ad812c3bd65 ("linux-user: Implement CPU-specific signal handler for loongarch64 hosts")
21
Reported-by: Song Gao <gaosong@loongson.cn>
22
Suggested-by: Song Gao <gaosong@loongson.cn>
23
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
24
Reviewed-by: WANG Xuerui <git@xen0n.name>
4
Reviewed-by: WANG Xuerui <git@xen0n.name>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
26
Message-Id: <20220104215027.2180972-1-f4bug@amsat.org>
27
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
28
---
7
---
29
linux-user/host/loongarch64/host-signal.h | 4 +---
8
tcg/loongarch64/tcg-target.c.inc | 2 +-
30
1 file changed, 1 insertion(+), 3 deletions(-)
9
1 file changed, 1 insertion(+), 1 deletion(-)
31
10
32
diff --git a/linux-user/host/loongarch64/host-signal.h b/linux-user/host/loongarch64/host-signal.h
11
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
33
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
34
--- a/linux-user/host/loongarch64/host-signal.h
13
--- a/tcg/loongarch64/tcg-target.c.inc
35
+++ b/linux-user/host/loongarch64/host-signal.h
14
+++ b/tcg/loongarch64/tcg-target.c.inc
36
@@ -XXX,XX +XXX,XX @@ static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
15
@@ -XXX,XX +XXX,XX @@ static void tcg_out_ldst(TCGContext *s, LoongArchInsn opc, TCGReg data,
37
}
16
intptr_t imm12 = sextreg(offset, 0, 12);
38
break;
17
39
case 0b001110: /* indexed, atomic, bounds-checking memory operations */
18
if (offset != imm12) {
40
- uint32_t sel = (insn >> 15) & 0b11111111111;
19
- intptr_t diff = offset - (uintptr_t)s->code_ptr;
41
-
20
+ intptr_t diff = tcg_pcrel_diff(s, (void *)offset);
42
- switch (sel) {
21
43
+ switch ((insn >> 15) & 0b11111111111) {
22
if (addr == TCG_REG_ZERO && diff == (int32_t)diff) {
44
case 0b00000100000: /* stx.b */
23
imm12 = sextreg(diff, 0, 12);
45
case 0b00000101000: /* stx.h */
46
case 0b00000110000: /* stx.w */
47
--
24
--
48
2.25.1
25
2.34.1
49
26
50
27
diff view generated by jsdifflib
New patch
1
The old implementation replaces two insns, swapping between
1
2
3
b <dest>
4
nop
5
and
6
pcaddu18i tmp, <dest>
7
jirl zero, tmp, <dest> & 0xffff
8
9
There is a race condition in which a thread could be stopped at
10
the jirl, i.e. with the top of the address loaded, and when
11
restarted we have re-linked to a different TB, so that the top
12
half no longer matches the bottom half.
13
14
Note that while we never directly re-link to a different TB, we
15
can link, unlink, and link again all while the stopped thread
16
remains stopped.
17
18
The new implementation replaces only one insn, swapping between
19
20
b <dest>
21
and
22
pcadd tmp, <jmp_addr>
23
24
falling through to load the address from tmp, and branch.
25
26
Reviewed-by: WANG Xuerui <git@xen0n.name>
27
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
28
---
29
tcg/loongarch64/tcg-target.h | 7 +---
30
tcg/loongarch64/tcg-target.c.inc | 72 ++++++++++++++------------------
31
2 files changed, 33 insertions(+), 46 deletions(-)
32
33
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
34
index XXXXXXX..XXXXXXX 100644
35
--- a/tcg/loongarch64/tcg-target.h
36
+++ b/tcg/loongarch64/tcg-target.h
37
@@ -XXX,XX +XXX,XX @@
38
39
#define TCG_TARGET_INSN_UNIT_SIZE 4
40
#define TCG_TARGET_NB_REGS 32
41
-/*
42
- * PCADDU18I + JIRL sequence can give 20 + 16 + 2 = 38 bits
43
- * signed offset, which is +/- 128 GiB.
44
- */
45
-#define MAX_CODE_GEN_BUFFER_SIZE (128 * GiB)
46
+
47
+#define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1)
48
49
typedef enum {
50
TCG_REG_ZERO,
51
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
52
index XXXXXXX..XXXXXXX 100644
53
--- a/tcg/loongarch64/tcg-target.c.inc
54
+++ b/tcg/loongarch64/tcg-target.c.inc
55
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args)
56
#endif
57
}
58
59
-/* LoongArch uses `andi zero, zero, 0` as NOP. */
60
-#define NOP OPC_ANDI
61
-static void tcg_out_nop(TCGContext *s)
62
-{
63
- tcg_out32(s, NOP);
64
-}
65
-
66
-void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
67
- uintptr_t jmp_rx, uintptr_t jmp_rw)
68
-{
69
- tcg_insn_unit i1, i2;
70
- ptrdiff_t upper, lower;
71
- uintptr_t addr = tb->jmp_target_addr[n];
72
- ptrdiff_t offset = (ptrdiff_t)(addr - jmp_rx) >> 2;
73
-
74
- if (offset == sextreg(offset, 0, 26)) {
75
- i1 = encode_sd10k16_insn(OPC_B, offset);
76
- i2 = NOP;
77
- } else {
78
- tcg_debug_assert(offset == sextreg(offset, 0, 36));
79
- lower = (int16_t)offset;
80
- upper = (offset - lower) >> 16;
81
-
82
- i1 = encode_dsj20_insn(OPC_PCADDU18I, TCG_REG_TMP0, upper);
83
- i2 = encode_djsk16_insn(OPC_JIRL, TCG_REG_ZERO, TCG_REG_TMP0, lower);
84
- }
85
- uint64_t pair = ((uint64_t)i2 << 32) | i1;
86
- qatomic_set((uint64_t *)jmp_rw, pair);
87
- flush_idcache_range(jmp_rx, jmp_rw, 8);
88
-}
89
-
90
/*
91
* Entry-points
92
*/
93
@@ -XXX,XX +XXX,XX @@ static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
94
static void tcg_out_goto_tb(TCGContext *s, int which)
95
{
96
/*
97
- * Ensure that patch area is 8-byte aligned so that an
98
- * atomic write can be used to patch the target address.
99
+ * Direct branch, or load indirect address, to be patched
100
+ * by tb_target_set_jmp_target. Check indirect load offset
101
+ * in range early, regardless of direct branch distance,
102
+ * via assert within tcg_out_opc_pcaddu2i.
103
*/
104
- if ((uintptr_t)s->code_ptr & 7) {
105
- tcg_out_nop(s);
106
- }
107
+ uintptr_t i_addr = get_jmp_target_addr(s, which);
108
+ intptr_t i_disp = tcg_pcrel_diff(s, (void *)i_addr);
109
+
110
set_jmp_insn_offset(s, which);
111
- /*
112
- * actual branch destination will be patched by
113
- * tb_target_set_jmp_target later
114
- */
115
- tcg_out_opc_pcaddu18i(s, TCG_REG_TMP0, 0);
116
+ tcg_out_opc_pcaddu2i(s, TCG_REG_TMP0, i_disp >> 2);
117
+
118
+ /* Finish the load and indirect branch. */
119
+ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_TMP0, 0);
120
tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_TMP0, 0);
121
set_jmp_reset_offset(s, which);
122
}
123
124
+void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
125
+ uintptr_t jmp_rx, uintptr_t jmp_rw)
126
+{
127
+ uintptr_t d_addr = tb->jmp_target_addr[n];
128
+ ptrdiff_t d_disp = (ptrdiff_t)(d_addr - jmp_rx) >> 2;
129
+ tcg_insn_unit insn;
130
+
131
+ /* Either directly branch, or load slot address for indirect branch. */
132
+ if (d_disp == sextreg(d_disp, 0, 26)) {
133
+ insn = encode_sd10k16_insn(OPC_B, d_disp);
134
+ } else {
135
+ uintptr_t i_addr = (uintptr_t)&tb->jmp_target_addr[n];
136
+ intptr_t i_disp = i_addr - jmp_rx;
137
+ insn = encode_dsj20_insn(OPC_PCADDU2I, TCG_REG_TMP0, i_disp >> 2);
138
+ }
139
+
140
+ qatomic_set((tcg_insn_unit *)jmp_rw, insn);
141
+ flush_idcache_range(jmp_rx, jmp_rw, 4);
142
+}
143
+
144
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
145
const TCGArg args[TCG_MAX_OP_ARGS],
146
const int const_args[TCG_MAX_OP_ARGS])
147
--
148
2.34.1
diff view generated by jsdifflib