1
The following changes since commit 6eeea6725a70e6fcb5abba0764496bdab07ddfb3:
1
Second try's the charm today, right?
2
2
3
Merge remote-tracking branch 'remotes/huth-gitlab/tags/pull-request-2020-10-06' into staging (2020-10-06 21:13:34 +0100)
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://github.com/rth7680/qemu.git tags/pull-tcg-20201008
13
https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20230123
8
14
9
for you to fetch changes up to 62475e9d007d83db4d0a6ccebcda8914f392e9c9:
15
for you to fetch changes up to 709bcd7da3f6b4655d910634a0d520fa1439df38:
10
16
11
accel/tcg: Fix computing of is_write for MIPS (2020-10-08 05:57:32 -0500)
17
tcg/loongarch64: Reorg goto_tb implementation (2023-01-23 16:00:13 -1000)
12
18
13
----------------------------------------------------------------
19
----------------------------------------------------------------
14
Extend maximum gvec vector size
20
common-user: Re-enable ppc32 host
15
Fix i386 avx2 dupi
21
tcg: Avoid recursion in tcg_gen_mulu2_i32
16
Fix mips host user-only write detection
22
tcg: Mark tcg helpers noinline to avoid an issue with LTO
17
Misc cleanups.
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
Kele Huang (1):
33
Richard Henderson (14):
21
accel/tcg: Fix computing of is_write for MIPS
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 (10):
49
Rui Wang (1):
24
tcg: Adjust simd_desc size encoding
50
tcg/loongarch64: Optimize immediate loading
25
tcg: Drop union from TCGArgConstraint
26
tcg: Move sorted_args into TCGArgConstraint.sort_index
27
tcg: Remove TCG_CT_REG
28
tcg: Move some TCG_CT_* bits to TCGArgConstraint bitfields
29
tcg: Remove TCGOpDef.used
30
tcg/i386: Fix dupi for avx2 32-bit hosts
31
tcg: Fix generation of dupi_vec for 32-bit host
32
tcg/optimize: Fold dup2_vec
33
tcg: Remove TCG_TARGET_HAS_cmp_vec
34
51
35
include/tcg/tcg-gvec-desc.h | 38 ++++++++++++------
52
include/exec/helper-proto.h | 32 ++-
36
include/tcg/tcg.h | 22 ++++------
53
include/tcg/tcg.h | 7 -
37
tcg/aarch64/tcg-target.h | 1 -
54
linux-user/include/host/ppc/host-signal.h | 39 +++
38
tcg/i386/tcg-target.h | 1 -
55
tcg/arm/tcg-target-con-set.h | 7 +-
39
tcg/ppc/tcg-target.h | 1 -
56
tcg/arm/tcg-target-con-str.h | 2 +
40
accel/tcg/user-exec.c | 43 ++++++++++++++++++--
57
tcg/loongarch64/tcg-target-con-set.h | 5 +-
41
tcg/optimize.c | 15 +++++++
58
tcg/loongarch64/tcg-target-con-str.h | 2 +-
42
tcg/tcg-op-gvec.c | 35 ++++++++++++----
59
tcg/loongarch64/tcg-target.h | 11 +-
43
tcg/tcg-op-vec.c | 12 ++++--
60
target/loongarch/insns.decode | 3 +-
44
tcg/tcg.c | 96 +++++++++++++++++++-------------------------
61
disas.c | 2 +
45
tcg/aarch64/tcg-target.c.inc | 17 ++++----
62
target/loongarch/disas.c | 39 ++-
46
tcg/arm/tcg-target.c.inc | 29 ++++++-------
63
tcg/tcg-op.c | 4 +-
47
tcg/i386/tcg-target.c.inc | 39 +++++++-----------
64
target/loongarch/insn_trans/trans_branch.c.inc | 2 +-
48
tcg/mips/tcg-target.c.inc | 21 +++++-----
65
tcg/arm/tcg-target.c.inc | 28 +-
49
tcg/ppc/tcg-target.c.inc | 29 ++++++-------
66
tcg/loongarch64/tcg-insn-defs.c.inc | 10 +-
50
tcg/riscv/tcg-target.c.inc | 16 ++++----
67
tcg/loongarch64/tcg-target.c.inc | 364 ++++++++++++++++---------
51
tcg/s390/tcg-target.c.inc | 22 +++++-----
68
common-user/host/ppc/safe-syscall.inc.S | 107 ++++++++
52
tcg/sparc/tcg-target.c.inc | 21 ++++------
69
target/loongarch/meson.build | 3 +-
53
tcg/tci/tcg-target.c.inc | 3 +-
70
18 files changed, 497 insertions(+), 170 deletions(-)
54
19 files changed, 244 insertions(+), 217 deletions(-)
71
create mode 100644 linux-user/include/host/ppc/host-signal.h
55
72
create mode 100644 common-user/host/ppc/safe-syscall.inc.S
diff view generated by jsdifflib
1
The last user of this field disappeared in f69d277ece4.
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.
2
5
3
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
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
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
---
11
---
6
include/tcg/tcg.h | 3 ---
12
include/tcg/tcg.h | 7 -------
7
1 file changed, 3 deletions(-)
13
tcg/tcg-op.c | 4 +++-
14
2 files changed, 3 insertions(+), 8 deletions(-)
8
15
9
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
16
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
10
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
11
--- a/include/tcg/tcg.h
18
--- a/include/tcg/tcg.h
12
+++ b/include/tcg/tcg.h
19
+++ b/include/tcg/tcg.h
13
@@ -XXX,XX +XXX,XX @@ typedef struct TCGOpDef {
20
@@ -XXX,XX +XXX,XX @@ typedef uint64_t TCGRegSet;
14
uint8_t nb_oargs, nb_iargs, nb_cargs, nb_args;
21
#define TCG_TARGET_HAS_rem_i64 0
15
uint8_t flags;
22
#endif
16
TCGArgConstraint *args_ct;
23
17
-#if defined(CONFIG_DEBUG_TCG)
24
-/* For 32-bit targets, some sort of unsigned widening multiply is required. */
18
- int used;
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"
19
-#endif
29
-#endif
20
} TCGOpDef;
30
-
21
31
#if !defined(TCG_TARGET_HAS_v64) \
22
extern TCGOpDef tcg_op_defs[];
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
23
--
56
--
24
2.25.1
57
2.34.1
25
26
diff view generated by jsdifflib
1
This wasn't actually used for anything, really. All variable
1
Although we still can't use ldrd and strd for all operations,
2
operands must accept registers, and which are indicated by the
2
increase the chances by getting the register allocation correct.
3
set in TCGArgConstraint.regs.
4
3
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
5
---
7
include/tcg/tcg.h | 1 -
6
tcg/arm/tcg-target-con-set.h | 7 ++++---
8
tcg/tcg.c | 15 ++++-----------
7
tcg/arm/tcg-target-con-str.h | 2 ++
9
tcg/aarch64/tcg-target.c.inc | 3 ---
8
tcg/arm/tcg-target.c.inc | 28 ++++++++++++++++++----------
10
tcg/arm/tcg-target.c.inc | 3 ---
9
3 files changed, 24 insertions(+), 13 deletions(-)
11
tcg/i386/tcg-target.c.inc | 11 -----------
12
tcg/mips/tcg-target.c.inc | 3 ---
13
tcg/ppc/tcg-target.c.inc | 5 -----
14
tcg/riscv/tcg-target.c.inc | 2 --
15
tcg/s390/tcg-target.c.inc | 4 ----
16
tcg/sparc/tcg-target.c.inc | 5 -----
17
tcg/tci/tcg-target.c.inc | 1 -
18
11 files changed, 4 insertions(+), 49 deletions(-)
19
10
20
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
11
diff --git a/tcg/arm/tcg-target-con-set.h b/tcg/arm/tcg-target-con-set.h
21
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
22
--- a/include/tcg/tcg.h
13
--- a/tcg/arm/tcg-target-con-set.h
23
+++ b/include/tcg/tcg.h
14
+++ b/tcg/arm/tcg-target-con-set.h
24
@@ -XXX,XX +XXX,XX @@ void tcg_dump_op_count(void);
15
@@ -XXX,XX +XXX,XX @@ C_O0_I2(r, rIN)
25
#define TCG_CT_ALIAS 0x80
16
C_O0_I2(s, s)
26
#define TCG_CT_IALIAS 0x40
17
C_O0_I2(w, r)
27
#define TCG_CT_NEWREG 0x20 /* output requires a new register */
18
C_O0_I3(s, s, s)
28
-#define TCG_CT_REG 0x01
19
+C_O0_I3(S, p, s)
29
#define TCG_CT_CONST 0x02 /* any constant of register size */
20
C_O0_I4(r, r, rI, rI)
30
21
-C_O0_I4(s, s, s, s)
31
typedef struct TCGArgConstraint {
22
+C_O0_I4(S, p, s, s)
32
diff --git a/tcg/tcg.c b/tcg/tcg.c
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
33
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX 100644
34
--- a/tcg/tcg.c
39
--- a/tcg/arm/tcg-target-con-str.h
35
+++ b/tcg/tcg.c
40
+++ b/tcg/arm/tcg-target-con-str.h
36
@@ -XXX,XX +XXX,XX @@ static void tcg_dump_ops(TCGContext *s, bool have_prefs)
41
@@ -XXX,XX +XXX,XX @@
37
/* we give more priority to constraints with less registers */
42
* Define constraint letters for register sets:
38
static int get_constraint_priority(const TCGOpDef *def, int k)
43
* REGS(letter, register_mask)
39
{
44
*/
40
- const TCGArgConstraint *arg_ct;
45
+REGS('e', ALL_GENERAL_REGS & 0x5555) /* even regs */
41
+ const TCGArgConstraint *arg_ct = &def->args_ct[k];
46
REGS('r', ALL_GENERAL_REGS)
42
+ int n;
47
REGS('l', ALL_QLOAD_REGS)
43
48
REGS('s', ALL_QSTORE_REGS)
44
- int i, n;
49
+REGS('S', ALL_QSTORE_REGS & 0x5555) /* even qstore */
45
- arg_ct = &def->args_ct[k];
50
REGS('w', ALL_VECTOR_REGS)
46
if (arg_ct->ct & TCG_CT_ALIAS) {
51
47
/* an alias is equivalent to a single register */
52
/*
48
n = 1;
49
} else {
50
- if (!(arg_ct->ct & TCG_CT_REG))
51
- return 0;
52
- n = 0;
53
- for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
54
- if (tcg_regset_test_reg(arg_ct->regs, i))
55
- n++;
56
- }
57
+ n = ctpop64(arg_ct->regs);
58
}
59
return TCG_TARGET_NB_REGS - n + 1;
60
}
61
@@ -XXX,XX +XXX,XX @@ static void process_op_defs(TCGContext *s)
62
int oarg = *ct_str - '0';
63
tcg_debug_assert(ct_str == tdefs->args_ct_str[i]);
64
tcg_debug_assert(oarg < def->nb_oargs);
65
- tcg_debug_assert(def->args_ct[oarg].ct & TCG_CT_REG);
66
+ tcg_debug_assert(def->args_ct[oarg].regs != 0);
67
/* TCG_CT_ALIAS is for the output arguments.
68
The input is tagged with TCG_CT_IALIAS. */
69
def->args_ct[i] = def->args_ct[oarg];
70
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
71
index XXXXXXX..XXXXXXX 100644
72
--- a/tcg/aarch64/tcg-target.c.inc
73
+++ b/tcg/aarch64/tcg-target.c.inc
74
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
75
{
76
switch (*ct_str++) {
77
case 'r': /* general registers */
78
- ct->ct |= TCG_CT_REG;
79
ct->regs |= 0xffffffffu;
80
break;
81
case 'w': /* advsimd registers */
82
- ct->ct |= TCG_CT_REG;
83
ct->regs |= 0xffffffff00000000ull;
84
break;
85
case 'l': /* qemu_ld / qemu_st address, data_reg */
86
- ct->ct |= TCG_CT_REG;
87
ct->regs = 0xffffffffu;
88
#ifdef CONFIG_SOFTMMU
89
/* x0 and x1 will be overwritten when reading the tlb entry,
90
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
53
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
91
index XXXXXXX..XXXXXXX 100644
54
index XXXXXXX..XXXXXXX 100644
92
--- a/tcg/arm/tcg-target.c.inc
55
--- a/tcg/arm/tcg-target.c.inc
93
+++ b/tcg/arm/tcg-target.c.inc
56
+++ b/tcg/arm/tcg-target.c.inc
94
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
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);
95
break;
59
break;
96
60
case MO_UQ:
97
case 'r':
61
+ /* We used pair allocation for datalo, so already should be aligned. */
98
- ct->ct |= TCG_CT_REG;
62
+ tcg_debug_assert((datalo & 1) == 0);
99
ct->regs = 0xffff;
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);
100
break;
73
break;
101
74
case MO_UQ:
102
/* qemu_ld address */
75
+ /* We used pair allocation for datalo, so already should be aligned. */
103
case 'l':
76
+ tcg_debug_assert((datalo & 1) == 0);
104
- ct->ct |= TCG_CT_REG;
77
+ tcg_debug_assert(datahi == datalo + 1);
105
ct->regs = 0xffff;
78
/* LDRD requires alignment; double-check that. */
106
#ifdef CONFIG_SOFTMMU
79
- if (get_alignment_bits(opc) >= MO_64
107
/* r0-r2,lr will be overwritten when reading the tlb entry,
80
- && (datalo & 1) == 0 && datahi == datalo + 1) {
108
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
81
+ if (get_alignment_bits(opc) >= MO_64) {
109
82
tcg_out_ldrd_8(s, COND_AL, datalo, addrlo, 0);
110
/* qemu_st address & data */
83
} else if (datalo == addrlo) {
111
case 's':
84
tcg_out_ld32_12(s, COND_AL, datahi, addrlo, 4);
112
- ct->ct |= TCG_CT_REG;
85
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st_index(TCGContext *s, ARMCond cond, MemOp opc,
113
ct->regs = 0xffff;
86
tcg_out_st32_r(s, cond, datalo, addrlo, addend);
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
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
117
index XXXXXXX..XXXXXXX 100644
118
--- a/tcg/i386/tcg-target.c.inc
119
+++ b/tcg/i386/tcg-target.c.inc
120
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
121
{
122
switch(*ct_str++) {
123
case 'a':
124
- ct->ct |= TCG_CT_REG;
125
tcg_regset_set_reg(ct->regs, TCG_REG_EAX);
126
break;
87
break;
127
case 'b':
88
case MO_64:
128
- ct->ct |= TCG_CT_REG;
89
+ /* We used pair allocation for datalo, so already should be aligned. */
129
tcg_regset_set_reg(ct->regs, TCG_REG_EBX);
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);
130
break;
101
break;
131
case 'c':
102
case MO_64:
132
- ct->ct |= TCG_CT_REG;
103
+ /* We used pair allocation for datalo, so already should be aligned. */
133
tcg_regset_set_reg(ct->regs, TCG_REG_ECX);
104
+ tcg_debug_assert((datalo & 1) == 0);
134
break;
105
+ tcg_debug_assert(datahi == datalo + 1);
135
case 'd':
106
/* STRD requires alignment; double-check that. */
136
- ct->ct |= TCG_CT_REG;
107
- if (get_alignment_bits(opc) >= MO_64
137
tcg_regset_set_reg(ct->regs, TCG_REG_EDX);
108
- && (datalo & 1) == 0 && datahi == datalo + 1) {
138
break;
109
+ if (get_alignment_bits(opc) >= MO_64) {
139
case 'S':
110
tcg_out_strd_8(s, COND_AL, datalo, addrlo, 0);
140
- ct->ct |= TCG_CT_REG;
111
} else {
141
tcg_regset_set_reg(ct->regs, TCG_REG_ESI);
112
tcg_out_st32_12(s, COND_AL, datalo, addrlo, 0);
142
break;
113
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
143
case 'D':
114
case INDEX_op_qemu_ld_i32:
144
- ct->ct |= TCG_CT_REG;
115
return TARGET_LONG_BITS == 32 ? C_O1_I1(r, l) : C_O1_I2(r, l, l);
145
tcg_regset_set_reg(ct->regs, TCG_REG_EDI);
116
case INDEX_op_qemu_ld_i64:
146
break;
117
- return TARGET_LONG_BITS == 32 ? C_O2_I1(r, r, l) : C_O2_I2(r, r, l, l);
147
case 'q':
118
+ return TARGET_LONG_BITS == 32 ? C_O2_I1(e, p, l) : C_O2_I2(e, p, l, l);
148
/* A register that can be used as a byte operand. */
119
case INDEX_op_qemu_st_i32:
149
- ct->ct |= TCG_CT_REG;
120
return TARGET_LONG_BITS == 32 ? C_O0_I2(s, s) : C_O0_I3(s, s, s);
150
ct->regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xf;
121
case INDEX_op_qemu_st_i64:
151
break;
122
- return TARGET_LONG_BITS == 32 ? C_O0_I3(s, s, s) : C_O0_I4(s, s, s, s);
152
case 'Q':
123
+ return TARGET_LONG_BITS == 32 ? C_O0_I3(S, p, s) : C_O0_I4(S, p, s, s);
153
/* A register with an addressable second byte (e.g. %ah). */
124
154
- ct->ct |= TCG_CT_REG;
125
case INDEX_op_st_vec:
155
ct->regs = 0xf;
126
return C_O0_I2(w, r);
156
break;
157
case 'r':
158
/* A general register. */
159
- ct->ct |= TCG_CT_REG;
160
ct->regs |= ALL_GENERAL_REGS;
161
break;
162
case 'W':
163
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
164
break;
165
case 'x':
166
/* A vector register. */
167
- ct->ct |= TCG_CT_REG;
168
ct->regs |= ALL_VECTOR_REGS;
169
break;
170
171
/* qemu_ld/st address constraint */
172
case 'L':
173
- ct->ct |= TCG_CT_REG;
174
ct->regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xff;
175
tcg_regset_reset_reg(ct->regs, TCG_REG_L0);
176
tcg_regset_reset_reg(ct->regs, TCG_REG_L1);
177
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
178
index XXXXXXX..XXXXXXX 100644
179
--- a/tcg/mips/tcg-target.c.inc
180
+++ b/tcg/mips/tcg-target.c.inc
181
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
182
{
183
switch(*ct_str++) {
184
case 'r':
185
- ct->ct |= TCG_CT_REG;
186
ct->regs = 0xffffffff;
187
break;
188
case 'L': /* qemu_ld input arg constraint */
189
- ct->ct |= TCG_CT_REG;
190
ct->regs = 0xffffffff;
191
tcg_regset_reset_reg(ct->regs, TCG_REG_A0);
192
#if defined(CONFIG_SOFTMMU)
193
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
194
#endif
195
break;
196
case 'S': /* qemu_st constraint */
197
- ct->ct |= TCG_CT_REG;
198
ct->regs = 0xffffffff;
199
tcg_regset_reset_reg(ct->regs, TCG_REG_A0);
200
#if defined(CONFIG_SOFTMMU)
201
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
202
index XXXXXXX..XXXXXXX 100644
203
--- a/tcg/ppc/tcg-target.c.inc
204
+++ b/tcg/ppc/tcg-target.c.inc
205
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
206
{
207
switch (*ct_str++) {
208
case 'A': case 'B': case 'C': case 'D':
209
- ct->ct |= TCG_CT_REG;
210
tcg_regset_set_reg(ct->regs, 3 + ct_str[0] - 'A');
211
break;
212
case 'r':
213
- ct->ct |= TCG_CT_REG;
214
ct->regs = 0xffffffff;
215
break;
216
case 'v':
217
- ct->ct |= TCG_CT_REG;
218
ct->regs = 0xffffffff00000000ull;
219
break;
220
case 'L': /* qemu_ld constraint */
221
- ct->ct |= TCG_CT_REG;
222
ct->regs = 0xffffffff;
223
tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
224
#ifdef CONFIG_SOFTMMU
225
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
226
#endif
227
break;
228
case 'S': /* qemu_st constraint */
229
- ct->ct |= TCG_CT_REG;
230
ct->regs = 0xffffffff;
231
tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
232
#ifdef CONFIG_SOFTMMU
233
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
234
index XXXXXXX..XXXXXXX 100644
235
--- a/tcg/riscv/tcg-target.c.inc
236
+++ b/tcg/riscv/tcg-target.c.inc
237
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
238
{
239
switch (*ct_str++) {
240
case 'r':
241
- ct->ct |= TCG_CT_REG;
242
ct->regs = 0xffffffff;
243
break;
244
case 'L':
245
/* qemu_ld/qemu_st constraint */
246
- ct->ct |= TCG_CT_REG;
247
ct->regs = 0xffffffff;
248
/* qemu_ld/qemu_st uses TCG_REG_TMP0 */
249
#if defined(CONFIG_SOFTMMU)
250
diff --git a/tcg/s390/tcg-target.c.inc b/tcg/s390/tcg-target.c.inc
251
index XXXXXXX..XXXXXXX 100644
252
--- a/tcg/s390/tcg-target.c.inc
253
+++ b/tcg/s390/tcg-target.c.inc
254
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
255
{
256
switch (*ct_str++) {
257
case 'r': /* all registers */
258
- ct->ct |= TCG_CT_REG;
259
ct->regs = 0xffff;
260
break;
261
case 'L': /* qemu_ld/st constraint */
262
- ct->ct |= TCG_CT_REG;
263
ct->regs = 0xffff;
264
tcg_regset_reset_reg(ct->regs, TCG_REG_R2);
265
tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
266
tcg_regset_reset_reg(ct->regs, TCG_REG_R4);
267
break;
268
case 'a': /* force R2 for division */
269
- ct->ct |= TCG_CT_REG;
270
ct->regs = 0;
271
tcg_regset_set_reg(ct->regs, TCG_REG_R2);
272
break;
273
case 'b': /* force R3 for division */
274
- ct->ct |= TCG_CT_REG;
275
ct->regs = 0;
276
tcg_regset_set_reg(ct->regs, TCG_REG_R3);
277
break;
278
diff --git a/tcg/sparc/tcg-target.c.inc b/tcg/sparc/tcg-target.c.inc
279
index XXXXXXX..XXXXXXX 100644
280
--- a/tcg/sparc/tcg-target.c.inc
281
+++ b/tcg/sparc/tcg-target.c.inc
282
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
283
{
284
switch (*ct_str++) {
285
case 'r':
286
- ct->ct |= TCG_CT_REG;
287
ct->regs = 0xffffffff;
288
break;
289
case 'R':
290
- ct->ct |= TCG_CT_REG;
291
ct->regs = ALL_64;
292
break;
293
case 'A': /* qemu_ld/st address constraint */
294
- ct->ct |= TCG_CT_REG;
295
ct->regs = TARGET_LONG_BITS == 64 ? ALL_64 : 0xffffffff;
296
reserve_helpers:
297
tcg_regset_reset_reg(ct->regs, TCG_REG_O0);
298
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
299
tcg_regset_reset_reg(ct->regs, TCG_REG_O2);
300
break;
301
case 's': /* qemu_st data 32-bit constraint */
302
- ct->ct |= TCG_CT_REG;
303
ct->regs = 0xffffffff;
304
goto reserve_helpers;
305
case 'S': /* qemu_st data 64-bit constraint */
306
- ct->ct |= TCG_CT_REG;
307
ct->regs = ALL_64;
308
goto reserve_helpers;
309
case 'I':
310
diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
311
index XXXXXXX..XXXXXXX 100644
312
--- a/tcg/tci/tcg-target.c.inc
313
+++ b/tcg/tci/tcg-target.c.inc
314
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
315
case 'r':
316
case 'L': /* qemu_ld constraint */
317
case 'S': /* qemu_st constraint */
318
- ct->ct |= TCG_CT_REG;
319
ct->regs = BIT(TCG_TARGET_NB_REGS) - 1;
320
break;
321
default:
322
--
127
--
323
2.25.1
128
2.34.1
324
325
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
From: Kele Huang <kele.hwang@gmail.com>
1
Marking helpers __attribute__((noinline)) prevents an issue
2
with GCC's ipa-split pass under --enable-lto.
2
3
3
Detect all MIPS store instructions in cpu_signal_handler for all available
4
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1454
4
MIPS versions, and set is_write if encountering such store instructions.
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
5
6
Tested-by: Idan Horowitz <idan.horowitz@gmail.com>
6
This fixed the error while dealing with self-modified code for MIPS.
7
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Kele Huang <kele.hwang@gmail.com>
10
Signed-off-by: Xu Zou <iwatchnima@gmail.com>
11
Message-Id: <20201002081420.10814-1-kele.hwang@gmail.com>
12
[rth: Use uintptr_t for pc to fix n32 build error.]
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
---
8
---
15
accel/tcg/user-exec.c | 43 +++++++++++++++++++++++++++++++++++++++----
9
include/exec/helper-proto.h | 32 ++++++++++++++++++++++++--------
16
1 file changed, 39 insertions(+), 4 deletions(-)
10
1 file changed, 24 insertions(+), 8 deletions(-)
17
11
18
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
12
diff --git a/include/exec/helper-proto.h b/include/exec/helper-proto.h
19
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
20
--- a/accel/tcg/user-exec.c
14
--- a/include/exec/helper-proto.h
21
+++ b/accel/tcg/user-exec.c
15
+++ b/include/exec/helper-proto.h
22
@@ -XXX,XX +XXX,XX @@ int cpu_signal_handler(int host_signum, void *pinfo,
16
@@ -XXX,XX +XXX,XX @@
23
17
24
#elif defined(__mips__)
18
#include "exec/helper-head.h"
25
19
26
+#if defined(__misp16) || defined(__mips_micromips)
20
+/*
27
+#error "Unsupported encoding"
21
+ * Work around an issue with --enable-lto, in which GCC's ipa-split pass
28
+#endif
22
+ * decides to split out the noreturn code paths that raise an exception,
23
+ * taking the __builtin_return_address() along into the new function,
24
+ * where it no longer computes a value that returns to TCG generated code.
25
+ * Despite the name, the noinline attribute affects splitter, so this
26
+ * prevents the optimization in question. Given that helpers should not
27
+ * otherwise be called directly, this should have any other visible effect.
28
+ *
29
+ * See https://gitlab.com/qemu-project/qemu/-/issues/1454
30
+ */
31
+#define DEF_HELPER_ATTR __attribute__((noinline))
29
+
32
+
30
int cpu_signal_handler(int host_signum, void *pinfo,
33
#define DEF_HELPER_FLAGS_0(name, flags, ret) \
31
void *puc)
34
-dh_ctype(ret) HELPER(name) (void);
32
{
35
+dh_ctype(ret) HELPER(name) (void) DEF_HELPER_ATTR;
33
siginfo_t *info = pinfo;
36
34
ucontext_t *uc = puc;
37
#define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
35
- greg_t pc = uc->uc_mcontext.pc;
38
-dh_ctype(ret) HELPER(name) (dh_ctype(t1));
36
- int is_write;
39
+dh_ctype(ret) HELPER(name) (dh_ctype(t1)) DEF_HELPER_ATTR;
37
+ uintptr_t pc = uc->uc_mcontext.pc;
40
38
+ uint32_t insn = *(uint32_t *)pc;
41
#define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \
39
+ int is_write = 0;
42
-dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2));
40
+
43
+dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2)) DEF_HELPER_ATTR;
41
+ /* Detect all store instructions at program counter. */
44
42
+ switch((insn >> 26) & 077) {
45
#define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \
43
+ case 050: /* SB */
46
-dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3));
44
+ case 051: /* SH */
47
+dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), \
45
+ case 052: /* SWL */
48
+ dh_ctype(t3)) DEF_HELPER_ATTR;
46
+ case 053: /* SW */
49
47
+ case 054: /* SDL */
50
#define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \
48
+ case 055: /* SDR */
51
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
49
+ case 056: /* SWR */
52
- dh_ctype(t4));
50
+ case 070: /* SC */
53
+ dh_ctype(t4)) DEF_HELPER_ATTR;
51
+ case 071: /* SWC1 */
54
52
+ case 074: /* SCD */
55
#define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
53
+ case 075: /* SDC1 */
56
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
54
+ case 077: /* SD */
57
- dh_ctype(t4), dh_ctype(t5));
55
+#if !defined(__mips_isa_rev) || __mips_isa_rev < 6
58
+ dh_ctype(t4), dh_ctype(t5)) DEF_HELPER_ATTR;
56
+ case 072: /* SWC2 */
59
57
+ case 076: /* SDC2 */
60
#define DEF_HELPER_FLAGS_6(name, flags, ret, t1, t2, t3, t4, t5, t6) \
58
+#endif
61
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
59
+ is_write = 1;
62
- dh_ctype(t4), dh_ctype(t5), dh_ctype(t6));
60
+ break;
63
+ dh_ctype(t4), dh_ctype(t5), \
61
+ case 023: /* COP1X */
64
+ dh_ctype(t6)) DEF_HELPER_ATTR;
62
+ /* Required in all versions of MIPS64 since
65
63
+ MIPS64r1 and subsequent versions of MIPS32r2. */
66
#define DEF_HELPER_FLAGS_7(name, flags, ret, t1, t2, t3, t4, t5, t6, t7) \
64
+ switch (insn & 077) {
67
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
65
+ case 010: /* SWXC1 */
68
dh_ctype(t4), dh_ctype(t5), dh_ctype(t6), \
66
+ case 011: /* SDXC1 */
69
- dh_ctype(t7));
67
+ case 015: /* SUXC1 */
70
+ dh_ctype(t7)) DEF_HELPER_ATTR;
68
+ is_write = 1;
71
69
+ }
72
#define IN_HELPER_PROTO
70
+ break;
73
71
+ }
74
@@ -XXX,XX +XXX,XX @@ dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
72
75
#undef DEF_HELPER_FLAGS_5
73
- /* XXX: compute is_write */
76
#undef DEF_HELPER_FLAGS_6
74
- is_write = 0;
77
#undef DEF_HELPER_FLAGS_7
75
return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
78
+#undef DEF_HELPER_ATTR
76
}
79
77
80
#endif /* HELPER_PROTO_H */
78
--
81
--
79
2.25.1
82
2.34.1
80
83
81
84
diff view generated by jsdifflib
1
The cmp_vec opcode is mandatory; this symbol is unused.
1
Reuse the decodetree based disassembler from
2
target/loongarch/ for tcg/loongarch64/.
2
3
3
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
The generation of decode-insns.c.inc into ./libcommon.fa.p/ could
5
eventually result in conflict, if any other host requires the same
6
trick, but this is good enough for now.
7
8
Reviewed-by: WANG Xuerui <git@xen0n.name>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
---
11
---
6
tcg/aarch64/tcg-target.h | 1 -
12
disas.c | 2 ++
7
tcg/i386/tcg-target.h | 1 -
13
target/loongarch/meson.build | 3 ++-
8
tcg/ppc/tcg-target.h | 1 -
14
2 files changed, 4 insertions(+), 1 deletion(-)
9
3 files changed, 3 deletions(-)
10
15
11
diff --git a/tcg/aarch64/tcg-target.h b/tcg/aarch64/tcg-target.h
16
diff --git a/disas.c b/disas.c
12
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
13
--- a/tcg/aarch64/tcg-target.h
18
--- a/disas.c
14
+++ b/tcg/aarch64/tcg-target.h
19
+++ b/disas.c
15
@@ -XXX,XX +XXX,XX @@ typedef enum {
20
@@ -XXX,XX +XXX,XX @@ static void initialize_debug_host(CPUDebug *s)
16
#define TCG_TARGET_HAS_shi_vec 1
21
s->info.cap_insn_split = 6;
17
#define TCG_TARGET_HAS_shs_vec 0
22
#elif defined(__hppa__)
18
#define TCG_TARGET_HAS_shv_vec 1
23
s->info.print_insn = print_insn_hppa;
19
-#define TCG_TARGET_HAS_cmp_vec 1
24
+#elif defined(__loongarch__)
20
#define TCG_TARGET_HAS_mul_vec 1
25
+ s->info.print_insn = print_insn_loongarch;
21
#define TCG_TARGET_HAS_sat_vec 1
26
#endif
22
#define TCG_TARGET_HAS_minmax_vec 1
27
}
23
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
28
29
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
24
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
25
--- a/tcg/i386/tcg-target.h
31
--- a/target/loongarch/meson.build
26
+++ b/tcg/i386/tcg-target.h
32
+++ b/target/loongarch/meson.build
27
@@ -XXX,XX +XXX,XX @@ extern bool have_avx2;
33
@@ -XXX,XX +XXX,XX @@ gen = decodetree.process('insns.decode')
28
#define TCG_TARGET_HAS_shi_vec 1
34
loongarch_ss = ss.source_set()
29
#define TCG_TARGET_HAS_shs_vec 1
35
loongarch_ss.add(files(
30
#define TCG_TARGET_HAS_shv_vec have_avx2
36
'cpu.c',
31
-#define TCG_TARGET_HAS_cmp_vec 1
37
- 'disas.c',
32
#define TCG_TARGET_HAS_mul_vec 1
38
))
33
#define TCG_TARGET_HAS_sat_vec 1
39
loongarch_tcg_ss = ss.source_set()
34
#define TCG_TARGET_HAS_minmax_vec 1
40
loongarch_tcg_ss.add(gen)
35
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
41
@@ -XXX,XX +XXX,XX @@ loongarch_softmmu_ss.add(files(
36
index XXXXXXX..XXXXXXX 100644
42
'iocsr_helper.c',
37
--- a/tcg/ppc/tcg-target.h
43
))
38
+++ b/tcg/ppc/tcg-target.h
44
39
@@ -XXX,XX +XXX,XX @@ extern bool have_vsx;
45
+common_ss.add(when: 'CONFIG_LOONGARCH_DIS', if_true: [files('disas.c'), gen])
40
#define TCG_TARGET_HAS_shi_vec 0
46
+
41
#define TCG_TARGET_HAS_shs_vec 0
47
loongarch_ss.add_all(when: 'CONFIG_TCG', if_true: [loongarch_tcg_ss])
42
#define TCG_TARGET_HAS_shv_vec 1
48
43
-#define TCG_TARGET_HAS_cmp_vec 1
49
target_arch += {'loongarch': loongarch_ss}
44
#define TCG_TARGET_HAS_mul_vec 1
45
#define TCG_TARGET_HAS_sat_vec 1
46
#define TCG_TARGET_HAS_minmax_vec 1
47
--
50
--
48
2.25.1
51
2.34.1
49
52
50
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
1
This uses an existing hole in the TCGArgConstraint structure
1
From: Rui Wang <wangrui@loongson.cn>
2
and will be convenient for keeping the data in one place.
3
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>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
---
15
---
6
include/tcg/tcg.h | 2 +-
16
tcg/loongarch64/tcg-target.c.inc | 35 +++++++++++---------------------
7
tcg/tcg.c | 35 +++++++++++++++++------------------
17
1 file changed, 12 insertions(+), 23 deletions(-)
8
2 files changed, 18 insertions(+), 19 deletions(-)
9
18
10
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
19
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
11
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
12
--- a/include/tcg/tcg.h
21
--- a/tcg/loongarch64/tcg-target.c.inc
13
+++ b/include/tcg/tcg.h
22
+++ b/tcg/loongarch64/tcg-target.c.inc
14
@@ -XXX,XX +XXX,XX @@ void tcg_dump_op_count(void);
23
@@ -XXX,XX +XXX,XX @@ static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
15
typedef struct TCGArgConstraint {
24
return true;
16
uint16_t ct;
25
}
17
uint8_t alias_index;
26
18
+ uint8_t sort_index;
27
-static bool imm_part_needs_loading(bool high_bits_are_ones,
19
TCGRegSet regs;
28
- tcg_target_long part)
20
} TCGArgConstraint;
29
-{
21
30
- if (high_bits_are_ones) {
22
@@ -XXX,XX +XXX,XX @@ typedef struct TCGOpDef {
31
- return part != -1;
23
uint8_t nb_oargs, nb_iargs, nb_cargs, nb_args;
32
- } else {
24
uint8_t flags;
33
- return part != 0;
25
TCGArgConstraint *args_ct;
34
- }
26
- int *sorted_args;
35
-}
27
#if defined(CONFIG_DEBUG_TCG)
36
-
28
int used;
37
/* Loads a 32-bit immediate into rd, sign-extended. */
29
#endif
38
static void tcg_out_movi_i32(TCGContext *s, TCGReg rd, int32_t val)
30
diff --git a/tcg/tcg.c b/tcg/tcg.c
39
{
31
index XXXXXXX..XXXXXXX 100644
40
@@ -XXX,XX +XXX,XX @@ static void tcg_out_movi_i32(TCGContext *s, TCGReg rd, int32_t val)
32
--- a/tcg/tcg.c
41
tcg_target_long hi12 = sextreg(val, 12, 20);
33
+++ b/tcg/tcg.c
42
34
@@ -XXX,XX +XXX,XX @@ void tcg_context_init(TCGContext *s)
43
/* Single-instruction cases. */
35
int op, total_args, n, i;
44
- if (lo == val) {
36
TCGOpDef *def;
45
- /* val fits in simm12: addi.w rd, zero, val */
37
TCGArgConstraint *args_ct;
46
- tcg_out_opc_addi_w(s, rd, TCG_REG_ZERO, val);
38
- int *sorted_args;
47
- return;
39
TCGTemp *ts;
48
- }
40
49
- if (0x800 <= val && val <= 0xfff) {
41
memset(s, 0, sizeof(*s));
50
+ if (hi12 == 0) {
42
@@ -XXX,XX +XXX,XX @@ void tcg_context_init(TCGContext *s)
51
/* val fits in uimm12: ori rd, zero, val */
52
tcg_out_opc_ori(s, rd, TCG_REG_ZERO, val);
53
return;
43
}
54
}
44
55
+ if (hi12 == sextreg(lo, 12, 20)) {
45
args_ct = g_malloc(sizeof(TCGArgConstraint) * total_args);
56
+ /* val fits in simm12: addi.w rd, zero, val */
46
- sorted_args = g_malloc(sizeof(int) * total_args);
57
+ tcg_out_opc_addi_w(s, rd, TCG_REG_ZERO, val);
47
58
+ return;
48
for(op = 0; op < NB_OPS; op++) {
59
+ }
49
def = &tcg_op_defs[op];
60
50
def->args_ct = args_ct;
61
/* High bits must be set; load with lu12i.w + optional ori. */
51
- def->sorted_args = sorted_args;
62
tcg_out_opc_lu12i_w(s, rd, hi12);
52
n = def->nb_iargs + def->nb_oargs;
63
@@ -XXX,XX +XXX,XX @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
53
- sorted_args += n;
64
54
args_ct += n;
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;
55
}
75
}
56
76
57
@@ -XXX,XX +XXX,XX @@ static int get_constraint_priority(const TCGOpDef *def, int k)
77
+ hi12 = sextreg(val, 12, 20);
58
/* sort from highest priority to lowest */
78
hi32 = sextreg(val, 32, 20);
59
static void sort_constraints(TCGOpDef *def, int start, int n)
79
hi52 = sextreg(val, 52, 12);
60
{
80
61
- int i, j, p1, p2, tmp;
81
/* Single cu52i.d case. */
62
+ int i, j;
82
- if (ctz64(val) >= 52) {
63
+ TCGArgConstraint *a = def->args_ct;
83
+ if ((hi52 != 0) && (ctz64(val) >= 52)) {
64
84
tcg_out_opc_cu52i_d(s, rd, TCG_REG_ZERO, hi52);
65
- for(i = 0; i < n; i++)
66
- def->sorted_args[start + i] = start + i;
67
- if (n <= 1)
68
+ for (i = 0; i < n; i++) {
69
+ a[start + i].sort_index = start + i;
70
+ }
71
+ if (n <= 1) {
72
return;
85
return;
73
- for(i = 0; i < n - 1; i++) {
74
- for(j = i + 1; j < n; j++) {
75
- p1 = get_constraint_priority(def, def->sorted_args[start + i]);
76
- p2 = get_constraint_priority(def, def->sorted_args[start + j]);
77
+ }
78
+ for (i = 0; i < n - 1; i++) {
79
+ for (j = i + 1; j < n; j++) {
80
+ int p1 = get_constraint_priority(def, a[start + i].sort_index);
81
+ int p2 = get_constraint_priority(def, a[start + j].sort_index);
82
if (p1 < p2) {
83
- tmp = def->sorted_args[start + i];
84
- def->sorted_args[start + i] = def->sorted_args[start + j];
85
- def->sorted_args[start + j] = tmp;
86
+ int tmp = a[start + i].sort_index;
87
+ a[start + i].sort_index = a[start + j].sort_index;
88
+ a[start + j].sort_index = tmp;
89
}
90
}
91
}
86
}
92
@@ -XXX,XX +XXX,XX @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
87
93
for (k = 0; k < nb_iargs; k++) {
88
/* Slow path. Initialize the low 32 bits, then concat high bits. */
94
TCGRegSet i_preferred_regs, o_preferred_regs;
89
tcg_out_movi_i32(s, rd, val);
95
90
- rd_high_bits_are_ones = (int32_t)val < 0;
96
- i = def->sorted_args[nb_oargs + k];
91
97
+ i = def->args_ct[nb_oargs + k].sort_index;
92
- if (imm_part_needs_loading(rd_high_bits_are_ones, hi32)) {
98
arg = op->args[i];
93
+ /* Load hi32 and hi52 explicitly when they are unexpected values. */
99
arg_ct = &def->args_ct[i];
94
+ if (hi32 != sextreg(hi12, 20, 20)) {
100
ts = arg_temp(arg);
95
tcg_out_opc_cu32i_d(s, rd, hi32);
101
@@ -XXX,XX +XXX,XX @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
96
- rd_high_bits_are_ones = hi32 < 0;
102
int k2, i2;
97
}
103
reg = ts->reg;
98
104
for (k2 = 0 ; k2 < k ; k2++) {
99
- if (imm_part_needs_loading(rd_high_bits_are_ones, hi52)) {
105
- i2 = def->sorted_args[nb_oargs + k2];
100
+ if (hi52 != sextreg(hi32, 20, 12)) {
106
+ i2 = def->args_ct[nb_oargs + k2].sort_index;
101
tcg_out_opc_cu52i_d(s, rd, rd, hi52);
107
if ((def->args_ct[i2].ct & TCG_CT_IALIAS) &&
102
}
108
reg == new_args[i2]) {
103
}
109
goto allocate_in_reg;
110
@@ -XXX,XX +XXX,XX @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
111
112
/* satisfy the output constraints */
113
for(k = 0; k < nb_oargs; k++) {
114
- i = def->sorted_args[k];
115
+ i = def->args_ct[k].sort_index;
116
arg = op->args[i];
117
arg_ct = &def->args_ct[i];
118
ts = arg_temp(arg);
119
--
104
--
120
2.25.1
105
2.34.1
121
122
diff view generated by jsdifflib
1
When the two arguments are identical, this can be reduced to
1
Regenerate with ADDU16I included:
2
dup_vec or to mov_vec from a tcg_constant_vec.
3
2
3
$ cd loongarch-opcodes/scripts/go
4
$ go run ./genqemutcgdefs > $QEMU/tcg/loongarch64/tcg-insn-defs.c.inc
5
6
Reviewed-by: WANG Xuerui <git@xen0n.name>
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
---
9
---
6
tcg/optimize.c | 15 +++++++++++++++
10
tcg/loongarch64/tcg-insn-defs.c.inc | 10 +++++++++-
7
1 file changed, 15 insertions(+)
11
1 file changed, 9 insertions(+), 1 deletion(-)
8
12
9
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
10
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
11
--- a/tcg/optimize.c
15
--- a/tcg/loongarch64/tcg-insn-defs.c.inc
12
+++ b/tcg/optimize.c
16
+++ b/tcg/loongarch64/tcg-insn-defs.c.inc
13
@@ -XXX,XX +XXX,XX @@ void tcg_optimize(TCGContext *s)
17
@@ -XXX,XX +XXX,XX @@
14
}
18
*
15
goto do_default;
19
* This file is auto-generated by genqemutcgdefs from
16
20
* https://github.com/loongson-community/loongarch-opcodes,
17
+ case INDEX_op_dup2_vec:
21
- * from commit 961f0c60f5b63e574d785995600c71ad5413fdc4.
18
+ assert(TCG_TARGET_REG_BITS == 32);
22
+ * from commit 25ca7effe9d88101c1cf96c4005423643386d81f.
19
+ if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) {
23
* DO NOT EDIT.
20
+ tmp = arg_info(op->args[1])->val;
24
*/
21
+ if (tmp == arg_info(op->args[2])->val) {
25
22
+ tcg_opt_gen_movi(s, op, op->args[0], tmp);
26
@@ -XXX,XX +XXX,XX @@ typedef enum {
23
+ break;
27
OPC_ANDI = 0x03400000,
24
+ }
28
OPC_ORI = 0x03800000,
25
+ } else if (args_are_copies(op->args[1], op->args[2])) {
29
OPC_XORI = 0x03c00000,
26
+ op->opc = INDEX_op_dup_vec;
30
+ OPC_ADDU16I_D = 0x10000000,
27
+ TCGOP_VECE(op) = MO_32;
31
OPC_LU12I_W = 0x14000000,
28
+ nb_iargs = 1;
32
OPC_CU32I_D = 0x16000000,
29
+ }
33
OPC_PCADDU2I = 0x18000000,
30
+ goto do_default;
34
@@ -XXX,XX +XXX,XX @@ tcg_out_opc_xori(TCGContext *s, TCGReg d, TCGReg j, uint32_t uk12)
35
tcg_out32(s, encode_djuk12_insn(OPC_XORI, d, j, uk12));
36
}
37
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)
41
+{
42
+ tcg_out32(s, encode_djsk16_insn(OPC_ADDU16I_D, d, j, sk16));
43
+}
31
+
44
+
32
CASE_OP_32_64(not):
45
/* Emits the `lu12i.w d, sj20` instruction. */
33
CASE_OP_32_64(neg):
46
static void __attribute__((unused))
34
CASE_OP_32_64(ext8s):
47
tcg_out_opc_lu12i_w(TCGContext *s, TCGReg d, int32_t sj20)
35
--
48
--
36
2.25.1
49
2.34.1
37
50
38
51
diff view generated by jsdifflib
1
These are easier to set and test when they have their own fields.
1
Adjust the constraints to allow any int32_t for immediate
2
Reduce the size of alias_index and sort_index to 4 bits, which is
2
addition. Split immediate adds into addu16i + addi, which
3
sufficient for TCG_MAX_OP_ARGS. This leaves only the bits indicating
3
covers quite a lot of the immediate space. For the hole in
4
constants within the ct field.
4
the middle, load the constant into TMP0 instead.
5
5
6
Move all initialization to allocation time, rather than init
6
Reviewed-by: WANG Xuerui <git@xen0n.name>
7
individual fields in process_op_defs.
8
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
---
8
---
11
include/tcg/tcg.h | 14 +++++++-------
9
tcg/loongarch64/tcg-target-con-set.h | 4 +-
12
tcg/tcg.c | 28 ++++++++++++----------------
10
tcg/loongarch64/tcg-target-con-str.h | 2 +-
13
2 files changed, 19 insertions(+), 23 deletions(-)
11
tcg/loongarch64/tcg-target.c.inc | 57 ++++++++++++++++++++++++----
12
3 files changed, 53 insertions(+), 10 deletions(-)
14
13
15
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
14
diff --git a/tcg/loongarch64/tcg-target-con-set.h b/tcg/loongarch64/tcg-target-con-set.h
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/include/tcg/tcg.h
16
--- a/tcg/loongarch64/tcg-target-con-set.h
18
+++ b/include/tcg/tcg.h
17
+++ b/tcg/loongarch64/tcg-target-con-set.h
19
@@ -XXX,XX +XXX,XX @@ int64_t tcg_cpu_exec_time(void);
18
@@ -XXX,XX +XXX,XX @@ C_O1_I1(r, L)
20
void tcg_dump_info(void);
19
C_O1_I2(r, r, rC)
21
void tcg_dump_op_count(void);
20
C_O1_I2(r, r, ri)
22
21
C_O1_I2(r, r, rI)
23
-#define TCG_CT_ALIAS 0x80
22
+C_O1_I2(r, r, rJ)
24
-#define TCG_CT_IALIAS 0x40
23
C_O1_I2(r, r, rU)
25
-#define TCG_CT_NEWREG 0x20 /* output requires a new register */
24
C_O1_I2(r, r, rW)
26
-#define TCG_CT_CONST 0x02 /* any constant of register size */
25
C_O1_I2(r, r, rZ)
27
+#define TCG_CT_CONST 1 /* any constant of register size */
26
C_O1_I2(r, 0, rZ)
28
27
-C_O1_I2(r, rZ, rN)
29
typedef struct TCGArgConstraint {
28
+C_O1_I2(r, rZ, ri)
30
- uint16_t ct;
29
+C_O1_I2(r, rZ, rJ)
31
- uint8_t alias_index;
30
C_O1_I2(r, rZ, rZ)
32
- uint8_t sort_index;
31
diff --git a/tcg/loongarch64/tcg-target-con-str.h b/tcg/loongarch64/tcg-target-con-str.h
33
+ unsigned ct : 16;
34
+ unsigned alias_index : 4;
35
+ unsigned sort_index : 4;
36
+ bool oalias : 1;
37
+ bool ialias : 1;
38
+ bool newreg : 1;
39
TCGRegSet regs;
40
} TCGArgConstraint;
41
42
diff --git a/tcg/tcg.c b/tcg/tcg.c
43
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
44
--- a/tcg/tcg.c
33
--- a/tcg/loongarch64/tcg-target-con-str.h
45
+++ b/tcg/tcg.c
34
+++ b/tcg/loongarch64/tcg-target-con-str.h
46
@@ -XXX,XX +XXX,XX @@ void tcg_context_init(TCGContext *s)
35
@@ -XXX,XX +XXX,XX @@ REGS('L', ALL_GENERAL_REGS & ~SOFTMMU_RESERVE_REGS)
47
total_args += n;
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;
48
}
60
}
49
61
- if ((ct & TCG_CT_CONST_N12) && -val == sextreg(-val, 0, 12)) {
50
- args_ct = g_malloc(sizeof(TCGArgConstraint) * total_args);
62
+ if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) {
51
+ args_ct = g_new0(TCGArgConstraint, total_args);
63
return true;
52
64
}
53
for(op = 0; op < NB_OPS; op++) {
65
if ((ct & TCG_CT_CONST_U12) && val >= 0 && val <= 0xfff) {
54
def = &tcg_op_defs[op];
66
@@ -XXX,XX +XXX,XX @@ static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
55
@@ -XXX,XX +XXX,XX @@ static int get_constraint_priority(const TCGOpDef *def, int k)
67
}
56
const TCGArgConstraint *arg_ct = &def->args_ct[k];
68
}
57
int n;
69
58
70
+static void tcg_out_addi(TCGContext *s, TCGType type, TCGReg rd,
59
- if (arg_ct->ct & TCG_CT_ALIAS) {
71
+ TCGReg rs, tcg_target_long imm)
60
+ if (arg_ct->oalias) {
72
+{
61
/* an alias is equivalent to a single register */
73
+ tcg_target_long lo12 = sextreg(imm, 0, 12);
62
n = 1;
74
+ tcg_target_long hi16 = sextreg(imm - lo12, 16, 16);
63
} else {
75
+
64
@@ -XXX,XX +XXX,XX @@ static void process_op_defs(TCGContext *s)
76
+ /*
65
/* Incomplete TCGTargetOpDef entry. */
77
+ * Note that there's a hole in between hi16 and lo12:
66
tcg_debug_assert(ct_str != NULL);
78
+ *
67
79
+ * 3 2 1 0
68
- def->args_ct[i].regs = 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
69
- def->args_ct[i].ct = 0;
81
+ * ...+-------------------------------+-------+-----------------------+
70
while (*ct_str != '\0') {
82
+ * | hi16 | | lo12 |
71
switch(*ct_str) {
83
+ * ...+-------------------------------+-------+-----------------------+
72
case '0' ... '9':
84
+ *
73
@@ -XXX,XX +XXX,XX @@ static void process_op_defs(TCGContext *s)
85
+ * For bits within that hole, it's more efficient to use LU12I and ADD.
74
tcg_debug_assert(ct_str == tdefs->args_ct_str[i]);
86
+ */
75
tcg_debug_assert(oarg < def->nb_oargs);
87
+ if (imm == (hi16 << 16) + lo12) {
76
tcg_debug_assert(def->args_ct[oarg].regs != 0);
88
+ if (hi16) {
77
- /* TCG_CT_ALIAS is for the output arguments.
89
+ tcg_out_opc_addu16i_d(s, rd, rs, hi16);
78
- The input is tagged with TCG_CT_IALIAS. */
90
+ rs = rd;
79
def->args_ct[i] = def->args_ct[oarg];
91
+ }
80
- def->args_ct[oarg].ct |= TCG_CT_ALIAS;
92
+ if (type == TCG_TYPE_I32) {
81
+ /* The output sets oalias. */
93
+ tcg_out_opc_addi_w(s, rd, rs, lo12);
82
+ def->args_ct[oarg].oalias = true;
94
+ } else if (lo12) {
83
def->args_ct[oarg].alias_index = i;
95
+ tcg_out_opc_addi_d(s, rd, rs, lo12);
84
- def->args_ct[i].ct |= TCG_CT_IALIAS;
96
+ } else {
85
+ /* The input sets ialias. */
97
+ tcg_out_mov(s, type, rd, rs);
86
+ def->args_ct[i].ialias = true;
98
+ }
87
def->args_ct[i].alias_index = oarg;
99
+ } else {
88
}
100
+ tcg_out_movi(s, type, TCG_REG_TMP0, imm);
89
ct_str++;
101
+ if (type == TCG_TYPE_I32) {
90
break;
102
+ tcg_out_opc_add_w(s, rd, rs, TCG_REG_TMP0);
91
case '&':
103
+ } else {
92
- def->args_ct[i].ct |= TCG_CT_NEWREG;
104
+ tcg_out_opc_add_d(s, rd, rs, TCG_REG_TMP0);
93
+ def->args_ct[i].newreg = true;
105
+ }
94
ct_str++;
106
+ }
95
break;
107
+}
96
case 'i':
108
+
97
@@ -XXX,XX +XXX,XX @@ static void liveness_pass_1(TCGContext *s)
109
static void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg)
98
set = *pset;
110
{
99
111
tcg_out_opc_andi(s, ret, arg, 0xff);
100
set &= ct->regs;
112
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
101
- if (ct->ct & TCG_CT_IALIAS) {
113
102
+ if (ct->ialias) {
114
case INDEX_op_add_i32:
103
set &= op->output_pref[ct->alias_index];
115
if (c2) {
104
}
116
- tcg_out_opc_addi_w(s, a0, a1, a2);
105
/* If the combination is not possible, restart. */
117
+ tcg_out_addi(s, TCG_TYPE_I32, a0, a1, a2);
106
@@ -XXX,XX +XXX,XX @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
118
} else {
119
tcg_out_opc_add_w(s, a0, a1, a2);
107
}
120
}
108
121
break;
109
i_preferred_regs = o_preferred_regs = 0;
122
case INDEX_op_add_i64:
110
- if (arg_ct->ct & TCG_CT_IALIAS) {
123
if (c2) {
111
+ if (arg_ct->ialias) {
124
- tcg_out_opc_addi_d(s, a0, a1, a2);
112
o_preferred_regs = op->output_pref[arg_ct->alias_index];
125
+ tcg_out_addi(s, TCG_TYPE_I64, a0, a1, a2);
113
if (ts->fixed_reg) {
126
} else {
114
/* if fixed register, we must allocate a new register
127
tcg_out_opc_add_d(s, a0, a1, a2);
115
@@ -XXX,XX +XXX,XX @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
128
}
116
reg = ts->reg;
129
@@ -XXX,XX +XXX,XX @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc,
117
for (k2 = 0 ; k2 < k ; k2++) {
130
118
i2 = def->args_ct[nb_oargs + k2].sort_index;
131
case INDEX_op_sub_i32:
119
- if ((def->args_ct[i2].ct & TCG_CT_IALIAS) &&
132
if (c2) {
120
- reg == new_args[i2]) {
133
- tcg_out_opc_addi_w(s, a0, a1, -a2);
121
+ if (def->args_ct[i2].ialias && reg == new_args[i2]) {
134
+ tcg_out_addi(s, TCG_TYPE_I32, a0, a1, -a2);
122
goto allocate_in_reg;
135
} else {
123
}
136
tcg_out_opc_sub_w(s, a0, a1, a2);
124
}
137
}
125
@@ -XXX,XX +XXX,XX @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
138
break;
126
/* ENV should not be modified. */
139
case INDEX_op_sub_i64:
127
tcg_debug_assert(!ts->fixed_reg);
140
if (c2) {
128
141
- tcg_out_opc_addi_d(s, a0, a1, -a2);
129
- if ((arg_ct->ct & TCG_CT_ALIAS)
142
+ tcg_out_addi(s, TCG_TYPE_I64, a0, a1, -a2);
130
- && !const_args[arg_ct->alias_index]) {
143
} else {
131
+ if (arg_ct->oalias && !const_args[arg_ct->alias_index]) {
144
tcg_out_opc_sub_d(s, a0, a1, a2);
132
reg = new_args[arg_ct->alias_index];
145
}
133
- } else if (arg_ct->ct & TCG_CT_NEWREG) {
146
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
134
+ } else if (arg_ct->newreg) {
147
return C_O1_I2(r, r, ri);
135
reg = tcg_reg_alloc(s, arg_ct->regs,
148
136
i_allocated_regs | o_allocated_regs,
149
case INDEX_op_add_i32:
137
op->output_pref[k], ts->indirect_base);
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:
138
--
168
--
139
2.25.1
169
2.34.1
140
141
diff view generated by jsdifflib
1
The definition of INDEX_op_dupi_vec is that it operates on
1
Split out a helper function, tcg_out_setcond_int, which
2
units of tcg_target_ulong -- in this case 32 bits. It does
2
does not always produce the complete boolean result, but
3
not work to use this for a uint64_t value that happens to be
3
returns a set of flags to do so.
4
small enough to fit in tcg_target_ulong.
5
4
6
Fixes: d2fd745fe8b
5
Accept all int32_t as constant input, so that LE/GT can
7
Fixes: db432672dc5
6
adjust the constant to LT.
8
Cc: qemu-stable@nongnu.org
7
8
Reviewed-by: WANG Xuerui <git@xen0n.name>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
---
10
---
11
tcg/tcg-op-vec.c | 12 ++++++++----
11
tcg/loongarch64/tcg-target.c.inc | 165 +++++++++++++++++++++----------
12
1 file changed, 8 insertions(+), 4 deletions(-)
12
1 file changed, 115 insertions(+), 50 deletions(-)
13
13
14
diff --git a/tcg/tcg-op-vec.c b/tcg/tcg-op-vec.c
14
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tcg/tcg-op-vec.c
16
--- a/tcg/loongarch64/tcg-target.c.inc
17
+++ b/tcg/tcg-op-vec.c
17
+++ b/tcg/loongarch64/tcg-target.c.inc
18
@@ -XXX,XX +XXX,XX @@ TCGv_vec tcg_const_ones_vec_matching(TCGv_vec m)
18
@@ -XXX,XX +XXX,XX @@ static void tcg_out_clzctz(TCGContext *s, LoongArchInsn opc,
19
19
tcg_out_opc_or(s, a0, TCG_REG_TMP0, a0);
20
void tcg_gen_dup64i_vec(TCGv_vec r, uint64_t a)
20
}
21
{
21
22
- if (TCG_TARGET_REG_BITS == 32 && a == deposit64(a, 32, 32, a)) {
22
-static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
23
- do_dupi_vec(r, MO_32, a);
23
- TCGReg arg1, TCGReg arg2, bool c2)
24
- } else if (TCG_TARGET_REG_BITS == 64 || a == (uint64_t)(int32_t)a) {
24
-{
25
+ if (TCG_TARGET_REG_BITS == 64) {
25
- TCGReg tmp;
26
do_dupi_vec(r, MO_64, a);
26
+#define SETCOND_INV TCG_TARGET_NB_REGS
27
+ } else if (a == dup_const(MO_32, a)) {
27
+#define SETCOND_NEZ (SETCOND_INV << 1)
28
+ do_dupi_vec(r, MO_32, a);
28
+#define SETCOND_FLAGS (SETCOND_INV | SETCOND_NEZ)
29
} else {
29
30
TCGv_i64 c = tcg_const_i64(a);
30
- if (c2) {
31
tcg_gen_dup_i64_vec(MO_64, r, c);
31
- tcg_debug_assert(arg2 == 0);
32
@@ -XXX,XX +XXX,XX @@ void tcg_gen_dup8i_vec(TCGv_vec r, uint32_t a)
32
+static int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret,
33
33
+ TCGReg arg1, tcg_target_long arg2, bool c2)
34
void tcg_gen_dupi_vec(unsigned vece, TCGv_vec r, uint64_t a)
34
+{
35
{
35
+ int flags = 0;
36
- do_dupi_vec(r, MO_REG, dup_const(vece, a));
36
+
37
+ if (vece == MO_64) {
37
+ switch (cond) {
38
+ tcg_gen_dup64i_vec(r, a);
38
+ case TCG_COND_EQ: /* -> NE */
39
+ } else {
39
+ case TCG_COND_GE: /* -> LT */
40
+ do_dupi_vec(r, MO_REG, dup_const(vece, a));
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
+ }
41
+ }
192
+ }
42
}
193
}
43
194
44
void tcg_gen_dup_i64_vec(unsigned vece, TCGv_vec r, TCGv_i64 a)
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:
45
--
217
--
46
2.25.1
218
2.34.1
47
48
diff view generated by jsdifflib
1
The union is unused; let "regs" appear in the main structure
1
Reviewed-by: WANG Xuerui <git@xen0n.name>
2
without the "u.regs" wrapping.
3
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
3
---
7
include/tcg/tcg.h | 4 +---
4
tcg/loongarch64/tcg-target-con-set.h | 1 +
8
tcg/tcg.c | 22 +++++++++++-----------
5
tcg/loongarch64/tcg-target.h | 4 ++--
9
tcg/aarch64/tcg-target.c.inc | 14 +++++++-------
6
tcg/loongarch64/tcg-target.c.inc | 33 ++++++++++++++++++++++++++++
10
tcg/arm/tcg-target.c.inc | 26 +++++++++++++-------------
7
3 files changed, 36 insertions(+), 2 deletions(-)
11
tcg/i386/tcg-target.c.inc | 26 +++++++++++++-------------
12
tcg/mips/tcg-target.c.inc | 18 +++++++++---------
13
tcg/ppc/tcg-target.c.inc | 24 ++++++++++++------------
14
tcg/riscv/tcg-target.c.inc | 14 +++++++-------
15
tcg/s390/tcg-target.c.inc | 18 +++++++++---------
16
tcg/sparc/tcg-target.c.inc | 16 ++++++++--------
17
tcg/tci/tcg-target.c.inc | 2 +-
18
11 files changed, 91 insertions(+), 93 deletions(-)
19
8
20
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
9
diff --git a/tcg/loongarch64/tcg-target-con-set.h b/tcg/loongarch64/tcg-target-con-set.h
21
index XXXXXXX..XXXXXXX 100644
10
index XXXXXXX..XXXXXXX 100644
22
--- a/include/tcg/tcg.h
11
--- a/tcg/loongarch64/tcg-target-con-set.h
23
+++ b/include/tcg/tcg.h
12
+++ b/tcg/loongarch64/tcg-target-con-set.h
24
@@ -XXX,XX +XXX,XX @@ void tcg_dump_op_count(void);
13
@@ -XXX,XX +XXX,XX @@ C_O1_I2(r, 0, rZ)
25
typedef struct TCGArgConstraint {
14
C_O1_I2(r, rZ, ri)
26
uint16_t ct;
15
C_O1_I2(r, rZ, rJ)
27
uint8_t alias_index;
16
C_O1_I2(r, rZ, rZ)
28
- union {
17
+C_O1_I4(r, rZ, rJ, rZ, rZ)
29
- TCGRegSet regs;
18
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
30
- } u;
31
+ TCGRegSet regs;
32
} TCGArgConstraint;
33
34
#define TCG_MAX_OP_ARGS 16
35
diff --git a/tcg/tcg.c b/tcg/tcg.c
36
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
37
--- a/tcg/tcg.c
20
--- a/tcg/loongarch64/tcg-target.h
38
+++ b/tcg/tcg.c
21
+++ b/tcg/loongarch64/tcg-target.h
39
@@ -XXX,XX +XXX,XX @@ static int get_constraint_priority(const TCGOpDef *def, int k)
22
@@ -XXX,XX +XXX,XX @@ typedef enum {
40
return 0;
23
#define TCG_TARGET_CALL_ARG_I64 TCG_CALL_ARG_NORMAL
41
n = 0;
24
42
for(i = 0; i < TCG_TARGET_NB_REGS; i++) {
25
/* optional instructions */
43
- if (tcg_regset_test_reg(arg_ct->u.regs, i))
26
-#define TCG_TARGET_HAS_movcond_i32 0
44
+ if (tcg_regset_test_reg(arg_ct->regs, i))
27
+#define TCG_TARGET_HAS_movcond_i32 1
45
n++;
28
#define TCG_TARGET_HAS_div_i32 1
46
}
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,
47
}
45
}
48
@@ -XXX,XX +XXX,XX @@ static void process_op_defs(TCGContext *s)
46
}
49
/* Incomplete TCGTargetOpDef entry. */
47
50
tcg_debug_assert(ct_str != NULL);
48
+static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
51
49
+ TCGReg c1, tcg_target_long c2, bool const2,
52
- def->args_ct[i].u.regs = 0;
50
+ TCGReg v1, TCGReg v2)
53
+ def->args_ct[i].regs = 0;
51
+{
54
def->args_ct[i].ct = 0;
52
+ int tmpflags = tcg_out_setcond_int(s, cond, TCG_REG_TMP0, c1, c2, const2);
55
while (*ct_str != '\0') {
53
+ TCGReg t;
56
switch(*ct_str) {
54
+
57
@@ -XXX,XX +XXX,XX @@ static void liveness_pass_1(TCGContext *s)
55
+ /* Standardize the test below to t != 0. */
58
pset = la_temp_pref(ts);
56
+ if (tmpflags & SETCOND_INV) {
59
set = *pset;
57
+ t = v1, v1 = v2, v2 = t;
60
58
+ }
61
- set &= ct->u.regs;
59
+
62
+ set &= ct->regs;
60
+ t = tmpflags & ~SETCOND_FLAGS;
63
if (ct->ct & TCG_CT_IALIAS) {
61
+ if (v1 == TCG_REG_ZERO) {
64
set &= op->output_pref[ct->alias_index];
62
+ tcg_out_opc_masknez(s, ret, v2, t);
65
}
63
+ } else if (v2 == TCG_REG_ZERO) {
66
/* If the combination is not possible, restart. */
64
+ tcg_out_opc_maskeqz(s, ret, v1, t);
67
if (set == 0) {
65
+ } else {
68
- set = ct->u.regs;
66
+ tcg_out_opc_masknez(s, TCG_REG_TMP2, v2, t); /* t ? 0 : v2 */
69
+ set = ct->regs;
67
+ tcg_out_opc_maskeqz(s, TCG_REG_TMP1, v1, t); /* t ? v1 : 0 */
70
}
68
+ tcg_out_opc_or(s, ret, TCG_REG_TMP1, TCG_REG_TMP2);
71
*pset = set;
69
+ }
72
}
70
+}
73
@@ -XXX,XX +XXX,XX @@ static void tcg_reg_alloc_dup(TCGContext *s, const TCGOp *op)
71
+
74
return;
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();
75
}
97
}
76
77
- dup_out_regs = tcg_op_defs[INDEX_op_dup_vec].args_ct[0].u.regs;
78
- dup_in_regs = tcg_op_defs[INDEX_op_dup_vec].args_ct[1].u.regs;
79
+ dup_out_regs = tcg_op_defs[INDEX_op_dup_vec].args_ct[0].regs;
80
+ dup_in_regs = tcg_op_defs[INDEX_op_dup_vec].args_ct[1].regs;
81
82
/* Allocate the output register now. */
83
if (ots->val_type != TEMP_VAL_REG) {
84
@@ -XXX,XX +XXX,XX @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
85
}
86
}
87
88
- temp_load(s, ts, arg_ct->u.regs, i_allocated_regs, i_preferred_regs);
89
+ temp_load(s, ts, arg_ct->regs, i_allocated_regs, i_preferred_regs);
90
reg = ts->reg;
91
92
- if (tcg_regset_test_reg(arg_ct->u.regs, reg)) {
93
+ if (tcg_regset_test_reg(arg_ct->regs, reg)) {
94
/* nothing to do : the constraint is satisfied */
95
} else {
96
allocate_in_reg:
97
@@ -XXX,XX +XXX,XX @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
98
and move the temporary register into it */
99
temp_load(s, ts, tcg_target_available_regs[ts->type],
100
i_allocated_regs, 0);
101
- reg = tcg_reg_alloc(s, arg_ct->u.regs, i_allocated_regs,
102
+ reg = tcg_reg_alloc(s, arg_ct->regs, i_allocated_regs,
103
o_preferred_regs, ts->indirect_base);
104
if (!tcg_out_mov(s, ts->type, reg, ts->reg)) {
105
/*
106
@@ -XXX,XX +XXX,XX @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
107
&& !const_args[arg_ct->alias_index]) {
108
reg = new_args[arg_ct->alias_index];
109
} else if (arg_ct->ct & TCG_CT_NEWREG) {
110
- reg = tcg_reg_alloc(s, arg_ct->u.regs,
111
+ reg = tcg_reg_alloc(s, arg_ct->regs,
112
i_allocated_regs | o_allocated_regs,
113
op->output_pref[k], ts->indirect_base);
114
} else {
115
- reg = tcg_reg_alloc(s, arg_ct->u.regs, o_allocated_regs,
116
+ reg = tcg_reg_alloc(s, arg_ct->regs, o_allocated_regs,
117
op->output_pref[k], ts->indirect_base);
118
}
119
tcg_regset_set_reg(o_allocated_regs, reg);
120
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
121
index XXXXXXX..XXXXXXX 100644
122
--- a/tcg/aarch64/tcg-target.c.inc
123
+++ b/tcg/aarch64/tcg-target.c.inc
124
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
125
switch (*ct_str++) {
126
case 'r': /* general registers */
127
ct->ct |= TCG_CT_REG;
128
- ct->u.regs |= 0xffffffffu;
129
+ ct->regs |= 0xffffffffu;
130
break;
131
case 'w': /* advsimd registers */
132
ct->ct |= TCG_CT_REG;
133
- ct->u.regs |= 0xffffffff00000000ull;
134
+ ct->regs |= 0xffffffff00000000ull;
135
break;
136
case 'l': /* qemu_ld / qemu_st address, data_reg */
137
ct->ct |= TCG_CT_REG;
138
- ct->u.regs = 0xffffffffu;
139
+ ct->regs = 0xffffffffu;
140
#ifdef CONFIG_SOFTMMU
141
/* x0 and x1 will be overwritten when reading the tlb entry,
142
and x2, and x3 for helper args, better to avoid using them. */
143
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_X0);
144
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_X1);
145
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_X2);
146
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_X3);
147
+ tcg_regset_reset_reg(ct->regs, TCG_REG_X0);
148
+ tcg_regset_reset_reg(ct->regs, TCG_REG_X1);
149
+ tcg_regset_reset_reg(ct->regs, TCG_REG_X2);
150
+ tcg_regset_reset_reg(ct->regs, TCG_REG_X3);
151
#endif
152
break;
153
case 'A': /* Valid for arithmetic immediate (positive or negative). */
154
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
155
index XXXXXXX..XXXXXXX 100644
156
--- a/tcg/arm/tcg-target.c.inc
157
+++ b/tcg/arm/tcg-target.c.inc
158
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
159
160
case 'r':
161
ct->ct |= TCG_CT_REG;
162
- ct->u.regs = 0xffff;
163
+ ct->regs = 0xffff;
164
break;
165
166
/* qemu_ld address */
167
case 'l':
168
ct->ct |= TCG_CT_REG;
169
- ct->u.regs = 0xffff;
170
+ ct->regs = 0xffff;
171
#ifdef CONFIG_SOFTMMU
172
/* r0-r2,lr will be overwritten when reading the tlb entry,
173
so don't use these. */
174
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
175
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
176
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
177
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
178
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R14);
179
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R0);
180
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R1);
181
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R2);
182
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
183
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R14);
184
#endif
185
break;
186
187
/* qemu_st address & data */
188
case 's':
189
ct->ct |= TCG_CT_REG;
190
- ct->u.regs = 0xffff;
191
+ ct->regs = 0xffff;
192
/* r0-r2 will be overwritten when reading the tlb entry (softmmu only)
193
and r0-r1 doing the byte swapping, so don't use these. */
194
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R0);
195
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R1);
196
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R0);
197
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R1);
198
#if defined(CONFIG_SOFTMMU)
199
/* Avoid clashes with registers being used for helper args */
200
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
201
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R2);
202
#if TARGET_LONG_BITS == 64
203
/* Avoid clashes with registers being used for helper args */
204
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
205
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
206
#endif
207
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R14);
208
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R14);
209
#endif
210
break;
211
212
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
213
index XXXXXXX..XXXXXXX 100644
214
--- a/tcg/i386/tcg-target.c.inc
215
+++ b/tcg/i386/tcg-target.c.inc
216
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
217
switch(*ct_str++) {
218
case 'a':
219
ct->ct |= TCG_CT_REG;
220
- tcg_regset_set_reg(ct->u.regs, TCG_REG_EAX);
221
+ tcg_regset_set_reg(ct->regs, TCG_REG_EAX);
222
break;
223
case 'b':
224
ct->ct |= TCG_CT_REG;
225
- tcg_regset_set_reg(ct->u.regs, TCG_REG_EBX);
226
+ tcg_regset_set_reg(ct->regs, TCG_REG_EBX);
227
break;
228
case 'c':
229
ct->ct |= TCG_CT_REG;
230
- tcg_regset_set_reg(ct->u.regs, TCG_REG_ECX);
231
+ tcg_regset_set_reg(ct->regs, TCG_REG_ECX);
232
break;
233
case 'd':
234
ct->ct |= TCG_CT_REG;
235
- tcg_regset_set_reg(ct->u.regs, TCG_REG_EDX);
236
+ tcg_regset_set_reg(ct->regs, TCG_REG_EDX);
237
break;
238
case 'S':
239
ct->ct |= TCG_CT_REG;
240
- tcg_regset_set_reg(ct->u.regs, TCG_REG_ESI);
241
+ tcg_regset_set_reg(ct->regs, TCG_REG_ESI);
242
break;
243
case 'D':
244
ct->ct |= TCG_CT_REG;
245
- tcg_regset_set_reg(ct->u.regs, TCG_REG_EDI);
246
+ tcg_regset_set_reg(ct->regs, TCG_REG_EDI);
247
break;
248
case 'q':
249
/* A register that can be used as a byte operand. */
250
ct->ct |= TCG_CT_REG;
251
- ct->u.regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xf;
252
+ ct->regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xf;
253
break;
254
case 'Q':
255
/* A register with an addressable second byte (e.g. %ah). */
256
ct->ct |= TCG_CT_REG;
257
- ct->u.regs = 0xf;
258
+ ct->regs = 0xf;
259
break;
260
case 'r':
261
/* A general register. */
262
ct->ct |= TCG_CT_REG;
263
- ct->u.regs |= ALL_GENERAL_REGS;
264
+ ct->regs |= ALL_GENERAL_REGS;
265
break;
266
case 'W':
267
/* With TZCNT/LZCNT, we can have operand-size as an input. */
268
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
269
case 'x':
270
/* A vector register. */
271
ct->ct |= TCG_CT_REG;
272
- ct->u.regs |= ALL_VECTOR_REGS;
273
+ ct->regs |= ALL_VECTOR_REGS;
274
break;
275
276
/* qemu_ld/st address constraint */
277
case 'L':
278
ct->ct |= TCG_CT_REG;
279
- ct->u.regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xff;
280
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_L0);
281
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_L1);
282
+ ct->regs = TCG_TARGET_REG_BITS == 64 ? 0xffff : 0xff;
283
+ tcg_regset_reset_reg(ct->regs, TCG_REG_L0);
284
+ tcg_regset_reset_reg(ct->regs, TCG_REG_L1);
285
break;
286
287
case 'e':
288
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
289
index XXXXXXX..XXXXXXX 100644
290
--- a/tcg/mips/tcg-target.c.inc
291
+++ b/tcg/mips/tcg-target.c.inc
292
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
293
switch(*ct_str++) {
294
case 'r':
295
ct->ct |= TCG_CT_REG;
296
- ct->u.regs = 0xffffffff;
297
+ ct->regs = 0xffffffff;
298
break;
299
case 'L': /* qemu_ld input arg constraint */
300
ct->ct |= TCG_CT_REG;
301
- ct->u.regs = 0xffffffff;
302
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
303
+ ct->regs = 0xffffffff;
304
+ tcg_regset_reset_reg(ct->regs, TCG_REG_A0);
305
#if defined(CONFIG_SOFTMMU)
306
if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
307
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
308
+ tcg_regset_reset_reg(ct->regs, TCG_REG_A2);
309
}
310
#endif
311
break;
312
case 'S': /* qemu_st constraint */
313
ct->ct |= TCG_CT_REG;
314
- ct->u.regs = 0xffffffff;
315
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_A0);
316
+ ct->regs = 0xffffffff;
317
+ tcg_regset_reset_reg(ct->regs, TCG_REG_A0);
318
#if defined(CONFIG_SOFTMMU)
319
if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
320
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_A2);
321
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_A3);
322
+ tcg_regset_reset_reg(ct->regs, TCG_REG_A2);
323
+ tcg_regset_reset_reg(ct->regs, TCG_REG_A3);
324
} else {
325
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_A1);
326
+ tcg_regset_reset_reg(ct->regs, TCG_REG_A1);
327
}
328
#endif
329
break;
330
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
331
index XXXXXXX..XXXXXXX 100644
332
--- a/tcg/ppc/tcg-target.c.inc
333
+++ b/tcg/ppc/tcg-target.c.inc
334
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
335
switch (*ct_str++) {
336
case 'A': case 'B': case 'C': case 'D':
337
ct->ct |= TCG_CT_REG;
338
- tcg_regset_set_reg(ct->u.regs, 3 + ct_str[0] - 'A');
339
+ tcg_regset_set_reg(ct->regs, 3 + ct_str[0] - 'A');
340
break;
341
case 'r':
342
ct->ct |= TCG_CT_REG;
343
- ct->u.regs = 0xffffffff;
344
+ ct->regs = 0xffffffff;
345
break;
346
case 'v':
347
ct->ct |= TCG_CT_REG;
348
- ct->u.regs = 0xffffffff00000000ull;
349
+ ct->regs = 0xffffffff00000000ull;
350
break;
351
case 'L': /* qemu_ld constraint */
352
ct->ct |= TCG_CT_REG;
353
- ct->u.regs = 0xffffffff;
354
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
355
+ ct->regs = 0xffffffff;
356
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
357
#ifdef CONFIG_SOFTMMU
358
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
359
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
360
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R4);
361
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R5);
362
#endif
363
break;
364
case 'S': /* qemu_st constraint */
365
ct->ct |= TCG_CT_REG;
366
- ct->u.regs = 0xffffffff;
367
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
368
+ ct->regs = 0xffffffff;
369
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
370
#ifdef CONFIG_SOFTMMU
371
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
372
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R5);
373
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R6);
374
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R4);
375
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R5);
376
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R6);
377
#endif
378
break;
379
case 'I':
380
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
381
index XXXXXXX..XXXXXXX 100644
382
--- a/tcg/riscv/tcg-target.c.inc
383
+++ b/tcg/riscv/tcg-target.c.inc
384
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
385
switch (*ct_str++) {
386
case 'r':
387
ct->ct |= TCG_CT_REG;
388
- ct->u.regs = 0xffffffff;
389
+ ct->regs = 0xffffffff;
390
break;
391
case 'L':
392
/* qemu_ld/qemu_st constraint */
393
ct->ct |= TCG_CT_REG;
394
- ct->u.regs = 0xffffffff;
395
+ ct->regs = 0xffffffff;
396
/* qemu_ld/qemu_st uses TCG_REG_TMP0 */
397
#if defined(CONFIG_SOFTMMU)
398
- tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[0]);
399
- tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[1]);
400
- tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[2]);
401
- tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[3]);
402
- tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[4]);
403
+ tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[0]);
404
+ tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[1]);
405
+ tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[2]);
406
+ tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[3]);
407
+ tcg_regset_reset_reg(ct->regs, tcg_target_call_iarg_regs[4]);
408
#endif
409
break;
410
case 'I':
411
diff --git a/tcg/s390/tcg-target.c.inc b/tcg/s390/tcg-target.c.inc
412
index XXXXXXX..XXXXXXX 100644
413
--- a/tcg/s390/tcg-target.c.inc
414
+++ b/tcg/s390/tcg-target.c.inc
415
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
416
switch (*ct_str++) {
417
case 'r': /* all registers */
418
ct->ct |= TCG_CT_REG;
419
- ct->u.regs = 0xffff;
420
+ ct->regs = 0xffff;
421
break;
422
case 'L': /* qemu_ld/st constraint */
423
ct->ct |= TCG_CT_REG;
424
- ct->u.regs = 0xffff;
425
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R2);
426
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R3);
427
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_R4);
428
+ ct->regs = 0xffff;
429
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R2);
430
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R3);
431
+ tcg_regset_reset_reg(ct->regs, TCG_REG_R4);
432
break;
433
case 'a': /* force R2 for division */
434
ct->ct |= TCG_CT_REG;
435
- ct->u.regs = 0;
436
- tcg_regset_set_reg(ct->u.regs, TCG_REG_R2);
437
+ ct->regs = 0;
438
+ tcg_regset_set_reg(ct->regs, TCG_REG_R2);
439
break;
440
case 'b': /* force R3 for division */
441
ct->ct |= TCG_CT_REG;
442
- ct->u.regs = 0;
443
- tcg_regset_set_reg(ct->u.regs, TCG_REG_R3);
444
+ ct->regs = 0;
445
+ tcg_regset_set_reg(ct->regs, TCG_REG_R3);
446
break;
447
case 'A':
448
ct->ct |= TCG_CT_CONST_S33;
449
diff --git a/tcg/sparc/tcg-target.c.inc b/tcg/sparc/tcg-target.c.inc
450
index XXXXXXX..XXXXXXX 100644
451
--- a/tcg/sparc/tcg-target.c.inc
452
+++ b/tcg/sparc/tcg-target.c.inc
453
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
454
switch (*ct_str++) {
455
case 'r':
456
ct->ct |= TCG_CT_REG;
457
- ct->u.regs = 0xffffffff;
458
+ ct->regs = 0xffffffff;
459
break;
460
case 'R':
461
ct->ct |= TCG_CT_REG;
462
- ct->u.regs = ALL_64;
463
+ ct->regs = ALL_64;
464
break;
465
case 'A': /* qemu_ld/st address constraint */
466
ct->ct |= TCG_CT_REG;
467
- ct->u.regs = TARGET_LONG_BITS == 64 ? ALL_64 : 0xffffffff;
468
+ ct->regs = TARGET_LONG_BITS == 64 ? ALL_64 : 0xffffffff;
469
reserve_helpers:
470
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_O0);
471
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_O1);
472
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_O2);
473
+ tcg_regset_reset_reg(ct->regs, TCG_REG_O0);
474
+ tcg_regset_reset_reg(ct->regs, TCG_REG_O1);
475
+ tcg_regset_reset_reg(ct->regs, TCG_REG_O2);
476
break;
477
case 's': /* qemu_st data 32-bit constraint */
478
ct->ct |= TCG_CT_REG;
479
- ct->u.regs = 0xffffffff;
480
+ ct->regs = 0xffffffff;
481
goto reserve_helpers;
482
case 'S': /* qemu_st data 64-bit constraint */
483
ct->ct |= TCG_CT_REG;
484
- ct->u.regs = ALL_64;
485
+ ct->regs = ALL_64;
486
goto reserve_helpers;
487
case 'I':
488
ct->ct |= TCG_CT_CONST_S11;
489
diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
490
index XXXXXXX..XXXXXXX 100644
491
--- a/tcg/tci/tcg-target.c.inc
492
+++ b/tcg/tci/tcg-target.c.inc
493
@@ -XXX,XX +XXX,XX @@ static const char *target_parse_constraint(TCGArgConstraint *ct,
494
case 'L': /* qemu_ld constraint */
495
case 'S': /* qemu_st constraint */
496
ct->ct |= TCG_CT_REG;
497
- ct->u.regs = BIT(TCG_TARGET_NB_REGS) - 1;
498
+ ct->regs = BIT(TCG_TARGET_NB_REGS) - 1;
499
break;
500
default:
501
return NULL;
502
--
98
--
503
2.25.1
99
2.34.1
504
505
diff view generated by jsdifflib
1
The previous change wrongly stated that 32-bit avx2 should have
1
Take the w^x split into account when computing the
2
used VPBROADCASTW. But that's a 16-bit broadcast and we want a
2
pc-relative distance to an absolute pointer.
3
32-bit broadcast.
4
3
5
Fixes: 7b60ef3264e
4
Reviewed-by: WANG Xuerui <git@xen0n.name>
6
Cc: qemu-stable@nongnu.org
5
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
7
---
9
tcg/i386/tcg-target.c.inc | 2 +-
8
tcg/loongarch64/tcg-target.c.inc | 2 +-
10
1 file changed, 1 insertion(+), 1 deletion(-)
9
1 file changed, 1 insertion(+), 1 deletion(-)
11
10
12
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
11
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
13
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
14
--- a/tcg/i386/tcg-target.c.inc
13
--- a/tcg/loongarch64/tcg-target.c.inc
15
+++ b/tcg/i386/tcg-target.c.inc
14
+++ b/tcg/loongarch64/tcg-target.c.inc
16
@@ -XXX,XX +XXX,XX @@ static void tcg_out_dupi_vec(TCGContext *s, TCGType type,
15
@@ -XXX,XX +XXX,XX @@ static void tcg_out_ldst(TCGContext *s, LoongArchInsn opc, TCGReg data,
17
new_pool_label(s, arg, R_386_PC32, s->code_ptr - 4, -4);
16
intptr_t imm12 = sextreg(offset, 0, 12);
18
} else {
17
19
if (have_avx2) {
18
if (offset != imm12) {
20
- tcg_out_vex_modrm_pool(s, OPC_VPBROADCASTW + vex_l, ret);
19
- intptr_t diff = offset - (uintptr_t)s->code_ptr;
21
+ tcg_out_vex_modrm_pool(s, OPC_VPBROADCASTD + vex_l, ret);
20
+ intptr_t diff = tcg_pcrel_diff(s, (void *)offset);
22
} else {
21
23
tcg_out_vex_modrm_pool(s, OPC_VBROADCASTSS, ret);
22
if (addr == TCG_REG_ZERO && diff == (int32_t)diff) {
24
}
23
imm12 = sextreg(diff, 0, 12);
25
--
24
--
26
2.25.1
25
2.34.1
27
26
28
27
diff view generated by jsdifflib
1
With larger vector sizes, it turns out oprsz == maxsz, and we only
1
The old implementation replaces two insns, swapping between
2
need to represent mismatch for oprsz <= 32. We do, however, need
3
to represent larger oprsz and do so without reducing SIMD_DATA_BITS.
4
2
5
Reduce the size of the oprsz field and increase the maxsz field.
3
b <dest>
6
Steal the oprsz value of 24 to indicate equality with maxsz.
4
nop
5
and
6
pcaddu18i tmp, <dest>
7
jirl zero, tmp, <dest> & 0xffff
7
8
8
Tested-by: Frank Chang <frank.chang@sifive.com>
9
There is a race condition in which a thread could be stopped at
9
Reviewed-by: Frank Chang <frank.chang@sifive.com>
10
the jirl, i.e. with the top of the address loaded, and when
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
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>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
27
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
---
28
---
13
include/tcg/tcg-gvec-desc.h | 38 ++++++++++++++++++++++++-------------
29
tcg/loongarch64/tcg-target.h | 7 +---
14
tcg/tcg-op-gvec.c | 35 ++++++++++++++++++++++++++--------
30
tcg/loongarch64/tcg-target.c.inc | 72 ++++++++++++++------------------
15
2 files changed, 52 insertions(+), 21 deletions(-)
31
2 files changed, 33 insertions(+), 46 deletions(-)
16
32
17
diff --git a/include/tcg/tcg-gvec-desc.h b/include/tcg/tcg-gvec-desc.h
33
diff --git a/tcg/loongarch64/tcg-target.h b/tcg/loongarch64/tcg-target.h
18
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
19
--- a/include/tcg/tcg-gvec-desc.h
35
--- a/tcg/loongarch64/tcg-target.h
20
+++ b/include/tcg/tcg-gvec-desc.h
36
+++ b/tcg/loongarch64/tcg-target.h
21
@@ -XXX,XX +XXX,XX @@
37
@@ -XXX,XX +XXX,XX @@
22
#ifndef TCG_TCG_GVEC_DESC_H
38
23
#define TCG_TCG_GVEC_DESC_H
39
#define TCG_TARGET_INSN_UNIT_SIZE 4
24
40
#define TCG_TARGET_NB_REGS 32
25
-/* ??? These bit widths are set for ARM SVE, maxing out at 256 byte vectors. */
41
-/*
26
-#define SIMD_OPRSZ_SHIFT 0
42
- * PCADDU18I + JIRL sequence can give 20 + 16 + 2 = 38 bits
27
-#define SIMD_OPRSZ_BITS 5
43
- * signed offset, which is +/- 128 GiB.
28
+/*
44
- */
29
+ * This configuration allows MAXSZ to represent 2048 bytes, and
45
-#define MAX_CODE_GEN_BUFFER_SIZE (128 * GiB)
30
+ * OPRSZ to match MAXSZ, or represent the smaller values 8, 16, or 32.
46
+
31
+ *
47
+#define MAX_CODE_GEN_BUFFER_SIZE ((size_t)-1)
32
+ * Encode this with:
48
33
+ * 0, 1, 3 -> 8, 16, 32
49
typedef enum {
34
+ * 2 -> maxsz
50
TCG_REG_ZERO,
35
+ *
51
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
36
+ * This steals the input that would otherwise map to 24 to match maxsz.
52
index XXXXXXX..XXXXXXX 100644
37
+ */
53
--- a/tcg/loongarch64/tcg-target.c.inc
38
+#define SIMD_MAXSZ_SHIFT 0
54
+++ b/tcg/loongarch64/tcg-target.c.inc
39
+#define SIMD_MAXSZ_BITS 8
55
@@ -XXX,XX +XXX,XX @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args)
40
56
#endif
41
-#define SIMD_MAXSZ_SHIFT (SIMD_OPRSZ_SHIFT + SIMD_OPRSZ_BITS)
57
}
42
-#define SIMD_MAXSZ_BITS 5
58
43
+#define SIMD_OPRSZ_SHIFT (SIMD_MAXSZ_SHIFT + SIMD_MAXSZ_BITS)
59
-/* LoongArch uses `andi zero, zero, 0` as NOP. */
44
+#define SIMD_OPRSZ_BITS 2
60
-#define NOP OPC_ANDI
45
61
-static void tcg_out_nop(TCGContext *s)
46
-#define SIMD_DATA_SHIFT (SIMD_MAXSZ_SHIFT + SIMD_MAXSZ_BITS)
47
+#define SIMD_DATA_SHIFT (SIMD_OPRSZ_SHIFT + SIMD_OPRSZ_BITS)
48
#define SIMD_DATA_BITS (32 - SIMD_DATA_SHIFT)
49
50
/* Create a descriptor from components. */
51
uint32_t simd_desc(uint32_t oprsz, uint32_t maxsz, int32_t data);
52
53
-/* Extract the operation size from a descriptor. */
54
-static inline intptr_t simd_oprsz(uint32_t desc)
55
-{
62
-{
56
- return (extract32(desc, SIMD_OPRSZ_SHIFT, SIMD_OPRSZ_BITS) + 1) * 8;
63
- tcg_out32(s, NOP);
57
-}
64
-}
58
-
65
-
59
/* Extract the max vector size from a descriptor. */
66
-void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
60
static inline intptr_t simd_maxsz(uint32_t desc)
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)
61
{
95
{
62
- return (extract32(desc, SIMD_MAXSZ_SHIFT, SIMD_MAXSZ_BITS) + 1) * 8;
96
/*
63
+ return extract32(desc, SIMD_MAXSZ_SHIFT, SIMD_MAXSZ_BITS) * 8 + 8;
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);
64
+}
142
+}
65
+
143
+
66
+/* Extract the operation size from a descriptor. */
144
static void tcg_out_op(TCGContext *s, TCGOpcode opc,
67
+static inline intptr_t simd_oprsz(uint32_t desc)
145
const TCGArg args[TCG_MAX_OP_ARGS],
68
+{
146
const int const_args[TCG_MAX_OP_ARGS])
69
+ uint32_t f = extract32(desc, SIMD_OPRSZ_SHIFT, SIMD_OPRSZ_BITS);
70
+ intptr_t o = f * 8 + 8;
71
+ intptr_t m = simd_maxsz(desc);
72
+ return f == 2 ? m : o;
73
}
74
75
/* Extract the operation-specific data from a descriptor. */
76
diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c
77
index XXXXXXX..XXXXXXX 100644
78
--- a/tcg/tcg-op-gvec.c
79
+++ b/tcg/tcg-op-gvec.c
80
@@ -XXX,XX +XXX,XX @@ static const TCGOpcode vecop_list_empty[1] = { 0 };
81
of the operand offsets so that we can check them all at once. */
82
static void check_size_align(uint32_t oprsz, uint32_t maxsz, uint32_t ofs)
83
{
84
- uint32_t opr_align = oprsz >= 16 ? 15 : 7;
85
- uint32_t max_align = maxsz >= 16 || oprsz >= 16 ? 15 : 7;
86
- tcg_debug_assert(oprsz > 0);
87
- tcg_debug_assert(oprsz <= maxsz);
88
- tcg_debug_assert((oprsz & opr_align) == 0);
89
+ uint32_t max_align;
90
+
91
+ switch (oprsz) {
92
+ case 8:
93
+ case 16:
94
+ case 32:
95
+ tcg_debug_assert(oprsz <= maxsz);
96
+ break;
97
+ default:
98
+ tcg_debug_assert(oprsz == maxsz);
99
+ break;
100
+ }
101
+ tcg_debug_assert(maxsz <= (8 << SIMD_MAXSZ_BITS));
102
+
103
+ max_align = maxsz >= 16 ? 15 : 7;
104
tcg_debug_assert((maxsz & max_align) == 0);
105
tcg_debug_assert((ofs & max_align) == 0);
106
}
107
@@ -XXX,XX +XXX,XX @@ uint32_t simd_desc(uint32_t oprsz, uint32_t maxsz, int32_t data)
108
{
109
uint32_t desc = 0;
110
111
- assert(oprsz % 8 == 0 && oprsz <= (8 << SIMD_OPRSZ_BITS));
112
- assert(maxsz % 8 == 0 && maxsz <= (8 << SIMD_MAXSZ_BITS));
113
- assert(data == sextract32(data, 0, SIMD_DATA_BITS));
114
+ check_size_align(oprsz, maxsz, 0);
115
+ tcg_debug_assert(data == sextract32(data, 0, SIMD_DATA_BITS));
116
117
oprsz = (oprsz / 8) - 1;
118
maxsz = (maxsz / 8) - 1;
119
+
120
+ /*
121
+ * We have just asserted in check_size_align that either
122
+ * oprsz is {8,16,32} or matches maxsz. Encode the final
123
+ * case with '2', as that would otherwise map to 24.
124
+ */
125
+ if (oprsz == maxsz) {
126
+ oprsz = 2;
127
+ }
128
+
129
desc = deposit32(desc, SIMD_OPRSZ_SHIFT, SIMD_OPRSZ_BITS, oprsz);
130
desc = deposit32(desc, SIMD_MAXSZ_SHIFT, SIMD_MAXSZ_BITS, maxsz);
131
desc = deposit32(desc, SIMD_DATA_SHIFT, SIMD_DATA_BITS, data);
132
--
147
--
133
2.25.1
148
2.34.1
134
135
diff view generated by jsdifflib