1
The following changes since commit 1cbd2d914939ee6028e9688d4ba859a528c28405:
1
The following changes since commit e93ded1bf6c94ab95015b33e188bc8b0b0c32670:
2
2
3
Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging (2021-06-04 13:38:49 +0100)
3
Merge tag 'testing-pull-request-2022-08-30' of https://gitlab.com/thuth/qemu into staging (2022-08-31 18:19:03 -0400)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20210604
7
https://gitlab.com/rth7680/qemu.git tags/pull-tcg-20220901
8
8
9
for you to fetch changes up to 0006039e29b9e6118beab300146f7c4931f7a217:
9
for you to fetch changes up to 20011be2e30b8aa8ef1fc258485f00c688703deb:
10
10
11
tcg/arm: Implement TCG_TARGET_HAS_rotv_vec (2021-06-04 11:50:11 -0700)
11
target/riscv: Make translator stop before the end of a page (2022-09-01 07:43:08 +0100)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
Host vector support for arm neon.
14
Respect PROT_EXEC in user-only mode.
15
Fix s390x, i386 and riscv for translations crossing a page.
15
16
16
----------------------------------------------------------------
17
----------------------------------------------------------------
17
Richard Henderson (15):
18
Ilya Leoshkevich (4):
18
tcg: Change parameters for tcg_target_const_match
19
linux-user: Clear translations on mprotect()
19
tcg/arm: Add host vector framework
20
accel/tcg: Introduce is_same_page()
20
tcg/arm: Implement tcg_out_ld/st for vector types
21
target/s390x: Make translator stop before the end of a page
21
tcg/arm: Implement tcg_out_mov for vector types
22
target/i386: Make translator stop before the end of a page
22
tcg/arm: Implement tcg_out_dup*_vec
23
tcg/arm: Implement minimal vector operations
24
tcg/arm: Implement andc, orc, abs, neg, not vector operations
25
tcg/arm: Implement TCG_TARGET_HAS_shi_vec
26
tcg/arm: Implement TCG_TARGET_HAS_mul_vec
27
tcg/arm: Implement TCG_TARGET_HAS_sat_vec
28
tcg/arm: Implement TCG_TARGET_HAS_minmax_vec
29
tcg/arm: Implement TCG_TARGET_HAS_bitsel_vec
30
tcg/arm: Implement TCG_TARGET_HAS_shv_vec
31
tcg/arm: Implement TCG_TARGET_HAS_roti_vec
32
tcg/arm: Implement TCG_TARGET_HAS_rotv_vec
33
23
34
tcg/arm/tcg-target-con-set.h | 10 +
24
Richard Henderson (16):
35
tcg/arm/tcg-target-con-str.h | 3 +
25
linux-user/arm: Mark the commpage executable
36
tcg/arm/tcg-target.h | 52 ++-
26
linux-user/hppa: Allocate page zero as a commpage
37
tcg/arm/tcg-target.opc.h | 16 +
27
linux-user/x86_64: Allocate vsyscall page as a commpage
38
tcg/tcg.c | 5 +-
28
linux-user: Honor PT_GNU_STACK
39
tcg/aarch64/tcg-target.c.inc | 5 +-
29
tests/tcg/i386: Move smc_code2 to an executable section
40
tcg/arm/tcg-target.c.inc | 956 +++++++++++++++++++++++++++++++++++++++++--
30
accel/tcg: Properly implement get_page_addr_code for user-only
41
tcg/i386/tcg-target.c.inc | 4 +-
31
accel/tcg: Unlock mmap_lock after longjmp
42
tcg/mips/tcg-target.c.inc | 5 +-
32
accel/tcg: Make tb_htable_lookup static
43
tcg/ppc/tcg-target.c.inc | 4 +-
33
accel/tcg: Move qemu_ram_addr_from_host_nofail to physmem.c
44
tcg/riscv/tcg-target.c.inc | 4 +-
34
accel/tcg: Use probe_access_internal for softmmu get_page_addr_code_hostp
45
tcg/s390/tcg-target.c.inc | 5 +-
35
accel/tcg: Document the faulting lookup in tb_lookup_cmp
46
tcg/sparc/tcg-target.c.inc | 5 +-
36
accel/tcg: Remove translator_ldsw
47
tcg/tci/tcg-target.c.inc | 6 +-
37
accel/tcg: Add pc and host_pc params to gen_intermediate_code
48
14 files changed, 1001 insertions(+), 79 deletions(-)
38
accel/tcg: Add fast path for translator_ld*
49
create mode 100644 tcg/arm/tcg-target.opc.h
39
target/riscv: Add MAX_INSN_LEN and insn_len
40
target/riscv: Make translator stop before the end of a page
50
41
42
include/elf.h | 1 +
43
include/exec/cpu-common.h | 1 +
44
include/exec/exec-all.h | 89 ++++++++----------------
45
include/exec/translator.h | 96 ++++++++++++++++---------
46
linux-user/arm/target_cpu.h | 4 +-
47
linux-user/qemu.h | 1 +
48
accel/tcg/cpu-exec.c | 143 ++++++++++++++++++++------------------
49
accel/tcg/cputlb.c | 93 +++++++------------------
50
accel/tcg/translate-all.c | 29 ++++----
51
accel/tcg/translator.c | 135 ++++++++++++++++++++++++++---------
52
accel/tcg/user-exec.c | 17 ++++-
53
linux-user/elfload.c | 82 ++++++++++++++++++++--
54
linux-user/mmap.c | 6 +-
55
softmmu/physmem.c | 12 ++++
56
target/alpha/translate.c | 5 +-
57
target/arm/translate.c | 5 +-
58
target/avr/translate.c | 5 +-
59
target/cris/translate.c | 5 +-
60
target/hexagon/translate.c | 6 +-
61
target/hppa/translate.c | 5 +-
62
target/i386/tcg/translate.c | 71 +++++++++++--------
63
target/loongarch/translate.c | 6 +-
64
target/m68k/translate.c | 5 +-
65
target/microblaze/translate.c | 5 +-
66
target/mips/tcg/translate.c | 5 +-
67
target/nios2/translate.c | 5 +-
68
target/openrisc/translate.c | 6 +-
69
target/ppc/translate.c | 5 +-
70
target/riscv/translate.c | 32 +++++++--
71
target/rx/translate.c | 5 +-
72
target/s390x/tcg/translate.c | 20 ++++--
73
target/sh4/translate.c | 5 +-
74
target/sparc/translate.c | 5 +-
75
target/tricore/translate.c | 6 +-
76
target/xtensa/translate.c | 6 +-
77
tests/tcg/i386/test-i386.c | 2 +-
78
tests/tcg/riscv64/noexec.c | 79 +++++++++++++++++++++
79
tests/tcg/s390x/noexec.c | 106 ++++++++++++++++++++++++++++
80
tests/tcg/x86_64/noexec.c | 75 ++++++++++++++++++++
81
tests/tcg/multiarch/noexec.c.inc | 139 ++++++++++++++++++++++++++++++++++++
82
tests/tcg/riscv64/Makefile.target | 1 +
83
tests/tcg/s390x/Makefile.target | 1 +
84
tests/tcg/x86_64/Makefile.target | 3 +-
85
43 files changed, 966 insertions(+), 367 deletions(-)
86
create mode 100644 tests/tcg/riscv64/noexec.c
87
create mode 100644 tests/tcg/s390x/noexec.c
88
create mode 100644 tests/tcg/x86_64/noexec.c
89
create mode 100644 tests/tcg/multiarch/noexec.c.inc
diff view generated by jsdifflib
New patch
1
We're about to start validating PAGE_EXEC, which means
2
that we've got to mark the commpage executable. We had
3
been placing the commpage outside of reserved_va, which
4
was incorrect and lead to an abort.
1
5
6
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
7
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
10
linux-user/arm/target_cpu.h | 4 ++--
11
linux-user/elfload.c | 6 +++++-
12
2 files changed, 7 insertions(+), 3 deletions(-)
13
14
diff --git a/linux-user/arm/target_cpu.h b/linux-user/arm/target_cpu.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/arm/target_cpu.h
17
+++ b/linux-user/arm/target_cpu.h
18
@@ -XXX,XX +XXX,XX @@ static inline unsigned long arm_max_reserved_va(CPUState *cs)
19
} else {
20
/*
21
* We need to be able to map the commpage.
22
- * See validate_guest_space in linux-user/elfload.c.
23
+ * See init_guest_commpage in linux-user/elfload.c.
24
*/
25
- return 0xffff0000ul;
26
+ return 0xfffffffful;
27
}
28
}
29
#define MAX_RESERVED_VA arm_max_reserved_va
30
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/linux-user/elfload.c
33
+++ b/linux-user/elfload.c
34
@@ -XXX,XX +XXX,XX @@ enum {
35
36
static bool init_guest_commpage(void)
37
{
38
- void *want = g2h_untagged(HI_COMMPAGE & -qemu_host_page_size);
39
+ abi_ptr commpage = HI_COMMPAGE & -qemu_host_page_size;
40
+ void *want = g2h_untagged(commpage);
41
void *addr = mmap(want, qemu_host_page_size, PROT_READ | PROT_WRITE,
42
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
43
44
@@ -XXX,XX +XXX,XX @@ static bool init_guest_commpage(void)
45
perror("Protecting guest commpage");
46
exit(EXIT_FAILURE);
47
}
48
+
49
+ page_set_flags(commpage, commpage + qemu_host_page_size,
50
+ PAGE_READ | PAGE_EXEC | PAGE_VALID);
51
return true;
52
}
53
54
--
55
2.34.1
diff view generated by jsdifflib
1
This is saturating add and subtract, signed and unsigned.
1
While there are no target-specific nonfaulting probes,
2
generic code may grow some uses at some point.
2
3
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Note that the attrs argument was incorrect -- it should have
5
been MEMTXATTRS_UNSPECIFIED. Just use the simpler interface.
6
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.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/arm/tcg-target.h | 2 +-
10
target/avr/helper.c | 46 ++++++++++++++++++++++++++++-----------------
7
tcg/arm/tcg-target.c.inc | 24 ++++++++++++++++++++++++
11
1 file changed, 29 insertions(+), 17 deletions(-)
8
2 files changed, 25 insertions(+), 1 deletion(-)
9
12
10
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
13
diff --git a/target/avr/helper.c b/target/avr/helper.c
11
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
12
--- a/tcg/arm/tcg-target.h
15
--- a/target/avr/helper.c
13
+++ b/tcg/arm/tcg-target.h
16
+++ b/target/avr/helper.c
14
@@ -XXX,XX +XXX,XX @@ extern bool use_neon_instructions;
17
@@ -XXX,XX +XXX,XX @@ bool avr_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
15
#define TCG_TARGET_HAS_shs_vec 0
18
MMUAccessType access_type, int mmu_idx,
16
#define TCG_TARGET_HAS_shv_vec 0
19
bool probe, uintptr_t retaddr)
17
#define TCG_TARGET_HAS_mul_vec 1
20
{
18
-#define TCG_TARGET_HAS_sat_vec 0
21
- int prot = 0;
19
+#define TCG_TARGET_HAS_sat_vec 1
22
- MemTxAttrs attrs = {};
20
#define TCG_TARGET_HAS_minmax_vec 0
23
+ int prot, page_size = TARGET_PAGE_SIZE;
21
#define TCG_TARGET_HAS_bitsel_vec 0
24
uint32_t paddr;
22
#define TCG_TARGET_HAS_cmpsel_vec 0
25
23
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
26
address &= TARGET_PAGE_MASK;
24
index XXXXXXX..XXXXXXX 100644
27
25
--- a/tcg/arm/tcg-target.c.inc
28
if (mmu_idx == MMU_CODE_IDX) {
26
+++ b/tcg/arm/tcg-target.c.inc
29
- /* access to code in flash */
27
@@ -XXX,XX +XXX,XX @@ typedef enum {
30
+ /* Access to code in flash. */
28
INSN_VORR = 0xf2200110,
31
paddr = OFFSET_CODE + address;
29
INSN_VSUB = 0xf3000800,
32
prot = PAGE_READ | PAGE_EXEC;
30
INSN_VMUL = 0xf2000910,
33
- if (paddr + TARGET_PAGE_SIZE > OFFSET_DATA) {
31
+ INSN_VQADD = 0xf2000010,
34
+ if (paddr >= OFFSET_DATA) {
32
+ INSN_VQADD_U = 0xf3000010,
35
+ /*
33
+ INSN_VQSUB = 0xf2000210,
36
+ * This should not be possible via any architectural operations.
34
+ INSN_VQSUB_U = 0xf3000210,
37
+ * There is certainly not an exception that we can deliver.
35
38
+ * Accept probing that might come from generic code.
36
INSN_VABS = 0xf3b10300,
39
+ */
37
INSN_VMVN = 0xf3b00580,
40
+ if (probe) {
38
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
41
+ return false;
39
case INDEX_op_dup2_vec:
42
+ }
40
case INDEX_op_add_vec:
43
error_report("execution left flash memory");
41
case INDEX_op_mul_vec:
44
abort();
42
+ case INDEX_op_ssadd_vec:
45
}
43
+ case INDEX_op_sssub_vec:
46
- } else if (address < NUMBER_OF_CPU_REGISTERS + NUMBER_OF_IO_REGISTERS) {
44
case INDEX_op_sub_vec:
47
- /*
45
+ case INDEX_op_usadd_vec:
48
- * access to CPU registers, exit and rebuilt this TB to use full access
46
+ case INDEX_op_ussub_vec:
49
- * incase it touches specially handled registers like SREG or SP
47
case INDEX_op_xor_vec:
50
- */
48
return C_O1_I2(w, w, w);
51
- AVRCPU *cpu = AVR_CPU(cs);
49
case INDEX_op_or_vec:
52
- CPUAVRState *env = &cpu->env;
50
@@ -XXX,XX +XXX,XX @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
53
- env->fullacc = 1;
51
case INDEX_op_sub_vec:
54
- cpu_loop_exit_restore(cs, retaddr);
52
tcg_out_vreg3(s, INSN_VSUB, q, vece, a0, a1, a2);
55
} else {
53
return;
56
- /* access to memory. nothing special */
54
+ case INDEX_op_ssadd_vec:
57
+ /* Access to memory. */
55
+ tcg_out_vreg3(s, INSN_VQADD, q, vece, a0, a1, a2);
58
paddr = OFFSET_DATA + address;
56
+ return;
59
prot = PAGE_READ | PAGE_WRITE;
57
+ case INDEX_op_sssub_vec:
60
+ if (address < NUMBER_OF_CPU_REGISTERS + NUMBER_OF_IO_REGISTERS) {
58
+ tcg_out_vreg3(s, INSN_VQSUB, q, vece, a0, a1, a2);
61
+ /*
59
+ return;
62
+ * Access to CPU registers, exit and rebuilt this TB to use
60
+ case INDEX_op_usadd_vec:
63
+ * full access in case it touches specially handled registers
61
+ tcg_out_vreg3(s, INSN_VQADD_U, q, vece, a0, a1, a2);
64
+ * like SREG or SP. For probing, set page_size = 1, in order
62
+ return;
65
+ * to force tlb_fill to be called for the next access.
63
+ case INDEX_op_ussub_vec:
66
+ */
64
+ tcg_out_vreg3(s, INSN_VQSUB_U, q, vece, a0, a1, a2);
67
+ if (probe) {
65
+ return;
68
+ page_size = 1;
66
case INDEX_op_xor_vec:
69
+ } else {
67
tcg_out_vreg3(s, INSN_VEOR, q, 0, a0, a1, a2);
70
+ AVRCPU *cpu = AVR_CPU(cs);
68
return;
71
+ CPUAVRState *env = &cpu->env;
69
@@ -XXX,XX +XXX,XX @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
72
+ env->fullacc = 1;
70
case INDEX_op_shli_vec:
73
+ cpu_loop_exit_restore(cs, retaddr);
71
case INDEX_op_shri_vec:
74
+ }
72
case INDEX_op_sari_vec:
75
+ }
73
+ case INDEX_op_ssadd_vec:
76
}
74
+ case INDEX_op_sssub_vec:
77
75
+ case INDEX_op_usadd_vec:
78
- tlb_set_page_with_attrs(cs, address, paddr, attrs, prot,
76
+ case INDEX_op_ussub_vec:
79
- mmu_idx, TARGET_PAGE_SIZE);
77
return 1;
80
-
78
case INDEX_op_abs_vec:
81
+ tlb_set_page(cs, address, paddr, prot, mmu_idx, page_size);
79
case INDEX_op_cmp_vec:
82
return true;
83
}
84
80
--
85
--
81
2.25.1
86
2.34.1
82
87
83
88
diff view generated by jsdifflib
1
Implement via expansion, so don't actually set TCG_TARGET_HAS_rotv_vec.
1
There is no need to go through cc->tcg_ops when
2
we know what value that must have.
2
3
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Michael Rolnik <mrolnik@gmail.com>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
---
7
---
6
tcg/arm/tcg-target.c.inc | 35 ++++++++++++++++++++++++++++++++++-
8
target/avr/helper.c | 5 ++---
7
1 file changed, 34 insertions(+), 1 deletion(-)
9
1 file changed, 2 insertions(+), 3 deletions(-)
8
10
9
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
11
diff --git a/target/avr/helper.c b/target/avr/helper.c
10
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
11
--- a/tcg/arm/tcg-target.c.inc
13
--- a/target/avr/helper.c
12
+++ b/tcg/arm/tcg-target.c.inc
14
+++ b/target/avr/helper.c
13
@@ -XXX,XX +XXX,XX @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
15
@@ -XXX,XX +XXX,XX @@
14
case INDEX_op_shrv_vec:
16
bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
15
case INDEX_op_sarv_vec:
16
case INDEX_op_rotli_vec:
17
+ case INDEX_op_rotlv_vec:
18
+ case INDEX_op_rotrv_vec:
19
return -1;
20
default:
21
return 0;
22
@@ -XXX,XX +XXX,XX @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece,
23
TCGArg a0, ...)
24
{
17
{
25
va_list va;
18
bool ret = false;
26
- TCGv_vec v0, v1, v2, t1;
19
- CPUClass *cc = CPU_GET_CLASS(cs);
27
+ TCGv_vec v0, v1, v2, t1, t2, c1;
20
AVRCPU *cpu = AVR_CPU(cs);
28
TCGArg a2;
21
CPUAVRState *env = &cpu->env;
29
22
30
va_start(va, a0);
23
if (interrupt_request & CPU_INTERRUPT_RESET) {
31
@@ -XXX,XX +XXX,XX @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece,
24
if (cpu_interrupts_enabled(env)) {
32
tcg_temp_free_vec(t1);
25
cs->exception_index = EXCP_RESET;
33
break;
26
- cc->tcg_ops->do_interrupt(cs);
34
27
+ avr_cpu_do_interrupt(cs);
35
+ case INDEX_op_rotlv_vec:
28
36
+ v2 = temp_tcgv_vec(arg_temp(a2));
29
cs->interrupt_request &= ~CPU_INTERRUPT_RESET;
37
+ t1 = tcg_temp_new_vec(type);
30
38
+ c1 = tcg_constant_vec(type, vece, 8 << vece);
31
@@ -XXX,XX +XXX,XX @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
39
+ tcg_gen_sub_vec(vece, t1, v2, c1);
32
if (cpu_interrupts_enabled(env) && env->intsrc != 0) {
40
+ /* Right shifts are negative left shifts for NEON. */
33
int index = ctz32(env->intsrc);
41
+ vec_gen_3(INDEX_op_arm_ushl_vec, type, vece, tcgv_vec_arg(t1),
34
cs->exception_index = EXCP_INT(index);
42
+ tcgv_vec_arg(v1), tcgv_vec_arg(t1));
35
- cc->tcg_ops->do_interrupt(cs);
43
+ vec_gen_3(INDEX_op_arm_ushl_vec, type, vece, tcgv_vec_arg(v0),
36
+ avr_cpu_do_interrupt(cs);
44
+ tcgv_vec_arg(v1), tcgv_vec_arg(v2));
37
45
+ tcg_gen_or_vec(vece, v0, v0, t1);
38
env->intsrc &= env->intsrc - 1; /* clear the interrupt */
46
+ tcg_temp_free_vec(t1);
39
if (!env->intsrc) {
47
+ break;
48
+
49
+ case INDEX_op_rotrv_vec:
50
+ v2 = temp_tcgv_vec(arg_temp(a2));
51
+ t1 = tcg_temp_new_vec(type);
52
+ t2 = tcg_temp_new_vec(type);
53
+ c1 = tcg_constant_vec(type, vece, 8 << vece);
54
+ tcg_gen_neg_vec(vece, t1, v2);
55
+ tcg_gen_sub_vec(vece, t2, c1, v2);
56
+ /* Right shifts are negative left shifts for NEON. */
57
+ vec_gen_3(INDEX_op_arm_ushl_vec, type, vece, tcgv_vec_arg(t1),
58
+ tcgv_vec_arg(v1), tcgv_vec_arg(t1));
59
+ vec_gen_3(INDEX_op_arm_ushl_vec, type, vece, tcgv_vec_arg(t2),
60
+ tcgv_vec_arg(v1), tcgv_vec_arg(t2));
61
+ tcg_gen_or_vec(vece, v0, t1, t2);
62
+ tcg_temp_free_vec(t1);
63
+ tcg_temp_free_vec(t2);
64
+ break;
65
+
66
default:
67
g_assert_not_reached();
68
}
69
--
40
--
70
2.25.1
41
2.34.1
71
42
72
43
diff view generated by jsdifflib
1
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
1
We're about to start validating PAGE_EXEC, which means that we've
2
got to mark page zero executable. We had been special casing this
3
entirely within translate.
4
5
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
6
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
8
---
4
tcg/arm/tcg-target.c.inc | 52 +++++++++++++++++++++++++++++++++++-----
9
linux-user/elfload.c | 34 +++++++++++++++++++++++++++++++---
5
1 file changed, 46 insertions(+), 6 deletions(-)
10
1 file changed, 31 insertions(+), 3 deletions(-)
6
11
7
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
12
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
8
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
9
--- a/tcg/arm/tcg-target.c.inc
14
--- a/linux-user/elfload.c
10
+++ b/tcg/arm/tcg-target.c.inc
15
+++ b/linux-user/elfload.c
11
@@ -XXX,XX +XXX,XX @@ typedef enum {
16
@@ -XXX,XX +XXX,XX @@ static inline void init_thread(struct target_pt_regs *regs,
12
/* Otherwise the assembler uses mov r0,r0 */
17
regs->gr[31] = infop->entry;
13
INSN_NOP_v4 = (COND_AL << 28) | ARITH_MOV,
18
}
14
19
15
+ INSN_VORR = 0xf2200110,
20
+#define LO_COMMPAGE 0
16
+
21
+
17
INSN_VLD1 = 0xf4200000, /* VLD1 (multiple single elements) */
22
+static bool init_guest_commpage(void)
18
INSN_VST1 = 0xf4000000, /* VST1 (multiple single elements) */
19
} ARMInsn;
20
@@ -XXX,XX +XXX,XX @@ static uint32_t encode_vd(TCGReg rd)
21
return (extract32(rd, 3, 1) << 22) | (extract32(rd, 0, 3) << 13);
22
}
23
24
+static uint32_t encode_vn(TCGReg rn)
25
+{
23
+{
26
+ tcg_debug_assert(rn >= TCG_REG_Q0);
24
+ void *want = g2h_untagged(LO_COMMPAGE);
27
+ return (extract32(rn, 3, 1) << 7) | (extract32(rn, 0, 3) << 17);
25
+ void *addr = mmap(want, qemu_host_page_size, PROT_NONE,
26
+ MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0);
27
+
28
+ if (addr == MAP_FAILED) {
29
+ perror("Allocating guest commpage");
30
+ exit(EXIT_FAILURE);
31
+ }
32
+ if (addr != want) {
33
+ return false;
34
+ }
35
+
36
+ /*
37
+ * On Linux, page zero is normally marked execute only + gateway.
38
+ * Normal read or write is supposed to fail (thus PROT_NONE above),
39
+ * but specific offsets have kernel code mapped to raise permissions
40
+ * and implement syscalls. Here, simply mark the page executable.
41
+ * Special case the entry points during translation (see do_page_zero).
42
+ */
43
+ page_set_flags(LO_COMMPAGE, LO_COMMPAGE + TARGET_PAGE_SIZE,
44
+ PAGE_EXEC | PAGE_VALID);
45
+ return true;
28
+}
46
+}
29
+
47
+
30
+static uint32_t encode_vm(TCGReg rm)
48
#endif /* TARGET_HPPA */
31
+{
49
32
+ tcg_debug_assert(rm >= TCG_REG_Q0);
50
#ifdef TARGET_XTENSA
33
+ return (extract32(rm, 3, 1) << 5) | (extract32(rm, 0, 3) << 1);
51
@@ -XXX,XX +XXX,XX @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
34
+}
35
+
36
+static void tcg_out_vreg3(TCGContext *s, ARMInsn insn, int q, int vece,
37
+ TCGReg d, TCGReg n, TCGReg m)
38
+{
39
+ tcg_out32(s, insn | (vece << 20) | (q << 6) |
40
+ encode_vd(d) | encode_vn(n) | encode_vm(m));
41
+}
42
+
43
static void tcg_out_vldst(TCGContext *s, ARMInsn insn,
44
TCGReg rd, TCGReg rn, int offset)
45
{
46
@@ -XXX,XX +XXX,XX @@ static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
47
return false;
48
}
52
}
49
53
50
-static inline bool tcg_out_mov(TCGContext *s, TCGType type,
54
#if defined(HI_COMMPAGE)
51
- TCGReg ret, TCGReg arg)
55
-#define LO_COMMPAGE 0
52
+static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
56
+#define LO_COMMPAGE -1
53
{
57
#elif defined(LO_COMMPAGE)
54
- tcg_out_mov_reg(s, COND_AL, ret, arg);
58
#define HI_COMMPAGE 0
55
- return true;
59
#else
56
+ if (ret == arg) {
60
#define HI_COMMPAGE 0
57
+ return true;
61
-#define LO_COMMPAGE 0
58
+ }
62
+#define LO_COMMPAGE -1
59
+ switch (type) {
63
#define init_guest_commpage() true
60
+ case TCG_TYPE_I32:
64
#endif
61
+ if (ret < TCG_REG_Q0 && arg < TCG_REG_Q0) {
65
62
+ tcg_out_mov_reg(s, COND_AL, ret, arg);
66
@@ -XXX,XX +XXX,XX @@ static void pgb_static(const char *image_name, abi_ulong orig_loaddr,
63
+ return true;
67
} else {
64
+ }
68
offset = -(HI_COMMPAGE & -align);
65
+ return false;
69
}
66
+
70
- } else if (LO_COMMPAGE != 0) {
67
+ case TCG_TYPE_V64:
71
+ } else if (LO_COMMPAGE != -1) {
68
+ case TCG_TYPE_V128:
72
loaddr = MIN(loaddr, LO_COMMPAGE & -align);
69
+ /* "VMOV D,N" is an alias for "VORR D,N,N". */
73
}
70
+ tcg_out_vreg3(s, INSN_VORR, type - TCG_TYPE_V64, 0, ret, arg, arg);
71
+ return true;
72
+
73
+ default:
74
+ g_assert_not_reached();
75
+ }
76
}
77
78
-static inline void tcg_out_movi(TCGContext *s, TCGType type,
79
- TCGReg ret, tcg_target_long arg)
80
+static void tcg_out_movi(TCGContext *s, TCGType type,
81
+ TCGReg ret, tcg_target_long arg)
82
{
83
+ tcg_debug_assert(type == TCG_TYPE_I32);
84
+ tcg_debug_assert(ret < TCG_REG_Q0);
85
tcg_out_movi32(s, COND_AL, ret, arg);
86
}
87
74
88
--
75
--
89
2.25.1
76
2.34.1
90
91
diff view generated by jsdifflib
New patch
1
We're about to start validating PAGE_EXEC, which means that we've
2
got to mark the vsyscall page executable. We had been special
3
casing this entirely within translate.
1
4
5
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
6
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
9
linux-user/elfload.c | 23 +++++++++++++++++++++++
10
1 file changed, 23 insertions(+)
11
12
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/linux-user/elfload.c
15
+++ b/linux-user/elfload.c
16
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *en
17
(*regs)[26] = tswapreg(env->segs[R_GS].selector & 0xffff);
18
}
19
20
+#if ULONG_MAX >= TARGET_VSYSCALL_PAGE
21
+#define INIT_GUEST_COMMPAGE
22
+static bool init_guest_commpage(void)
23
+{
24
+ /*
25
+ * The vsyscall page is at a high negative address aka kernel space,
26
+ * which means that we cannot actually allocate it with target_mmap.
27
+ * We still should be able to use page_set_flags, unless the user
28
+ * has specified -R reserved_va, which would trigger an assert().
29
+ */
30
+ if (reserved_va != 0 &&
31
+ TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE >= reserved_va) {
32
+ error_report("Cannot allocate vsyscall page");
33
+ exit(EXIT_FAILURE);
34
+ }
35
+ page_set_flags(TARGET_VSYSCALL_PAGE,
36
+ TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE,
37
+ PAGE_EXEC | PAGE_VALID);
38
+ return true;
39
+}
40
+#endif
41
#else
42
43
#define ELF_START_MMAP 0x80000000
44
@@ -XXX,XX +XXX,XX @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
45
#else
46
#define HI_COMMPAGE 0
47
#define LO_COMMPAGE -1
48
+#ifndef INIT_GUEST_COMMPAGE
49
#define init_guest_commpage() true
50
#endif
51
+#endif
52
53
static void pgb_fail_in_use(const char *image_name)
54
{
55
--
56
2.34.1
diff view generated by jsdifflib
1
NEON has 3 instructions implementing this 4 argument operation,
1
We cannot deliver two interrupts simultaneously;
2
with each insn overlapping a different logical input onto the
2
the first interrupt handler must execute first.
3
destination register.
4
3
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Michael Rolnik <mrolnik@gmail.com>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
7
---
8
tcg/arm/tcg-target-con-set.h | 1 +
8
target/avr/helper.c | 9 +++------
9
tcg/arm/tcg-target.h | 2 +-
9
1 file changed, 3 insertions(+), 6 deletions(-)
10
tcg/arm/tcg-target.c.inc | 22 ++++++++++++++++++++--
11
3 files changed, 22 insertions(+), 3 deletions(-)
12
10
13
diff --git a/tcg/arm/tcg-target-con-set.h b/tcg/arm/tcg-target-con-set.h
11
diff --git a/target/avr/helper.c b/target/avr/helper.c
14
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
15
--- a/tcg/arm/tcg-target-con-set.h
13
--- a/target/avr/helper.c
16
+++ b/tcg/arm/tcg-target-con-set.h
14
+++ b/target/avr/helper.c
17
@@ -XXX,XX +XXX,XX @@ C_O1_I2(w, w, w)
15
@@ -XXX,XX +XXX,XX @@
18
C_O1_I2(w, w, wO)
16
19
C_O1_I2(w, w, wV)
17
bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
20
C_O1_I2(w, w, wZ)
18
{
21
+C_O1_I3(w, w, w, w)
19
- bool ret = false;
22
C_O1_I4(r, r, r, rI, rI)
20
AVRCPU *cpu = AVR_CPU(cs);
23
C_O1_I4(r, r, rIN, rIK, 0)
21
CPUAVRState *env = &cpu->env;
24
C_O2_I1(r, r, l)
22
25
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
23
@@ -XXX,XX +XXX,XX @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
26
index XXXXXXX..XXXXXXX 100644
24
avr_cpu_do_interrupt(cs);
27
--- a/tcg/arm/tcg-target.h
25
28
+++ b/tcg/arm/tcg-target.h
26
cs->interrupt_request &= ~CPU_INTERRUPT_RESET;
29
@@ -XXX,XX +XXX,XX @@ extern bool use_neon_instructions;
30
#define TCG_TARGET_HAS_mul_vec 1
31
#define TCG_TARGET_HAS_sat_vec 1
32
#define TCG_TARGET_HAS_minmax_vec 1
33
-#define TCG_TARGET_HAS_bitsel_vec 0
34
+#define TCG_TARGET_HAS_bitsel_vec 1
35
#define TCG_TARGET_HAS_cmpsel_vec 0
36
37
#define TCG_TARGET_DEFAULT_MO (0)
38
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
39
index XXXXXXX..XXXXXXX 100644
40
--- a/tcg/arm/tcg-target.c.inc
41
+++ b/tcg/arm/tcg-target.c.inc
42
@@ -XXX,XX +XXX,XX @@ typedef enum {
43
INSN_VSARI = 0xf2800010, /* VSHR.S */
44
INSN_VSHRI = 0xf3800010, /* VSHR.U */
45
46
+ INSN_VBSL = 0xf3100110,
47
+ INSN_VBIT = 0xf3200110,
48
+ INSN_VBIF = 0xf3300110,
49
+
50
INSN_VTST = 0xf2000810,
51
52
INSN_VDUP_G = 0xee800b10, /* VDUP (ARM core register) */
53
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
54
return C_O1_I2(w, w, wV);
55
case INDEX_op_cmp_vec:
56
return C_O1_I2(w, w, wZ);
57
-
27
-
58
+ case INDEX_op_bitsel_vec:
28
- ret = true;
59
+ return C_O1_I3(w, w, w, w);
29
+ return true;
60
default:
30
}
61
g_assert_not_reached();
62
}
31
}
63
@@ -XXX,XX +XXX,XX @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
32
if (interrupt_request & CPU_INTERRUPT_HARD) {
64
{
33
@@ -XXX,XX +XXX,XX @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
65
TCGType type = vecl + TCG_TYPE_V64;
34
if (!env->intsrc) {
66
unsigned q = vecl;
35
cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
67
- TCGArg a0, a1, a2;
36
}
68
+ TCGArg a0, a1, a2, a3;
37
-
69
int cmode, imm8;
38
- ret = true;
70
39
+ return true;
71
a0 = args[0];
72
@@ -XXX,XX +XXX,XX @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
73
}
40
}
74
return;
41
}
75
42
- return ret;
76
+ case INDEX_op_bitsel_vec:
43
+ return false;
77
+ a3 = args[3];
44
}
78
+ if (a0 == a3) {
45
79
+ tcg_out_vreg3(s, INSN_VBIT, q, 0, a0, a2, a1);
46
void avr_cpu_do_interrupt(CPUState *cs)
80
+ } else if (a0 == a2) {
81
+ tcg_out_vreg3(s, INSN_VBIF, q, 0, a0, a3, a1);
82
+ } else {
83
+ tcg_out_mov(s, type, a0, a1);
84
+ tcg_out_vreg3(s, INSN_VBSL, q, 0, a0, a2, a3);
85
+ }
86
+ return;
87
+
88
case INDEX_op_mov_vec: /* Always emitted via tcg_out_mov. */
89
case INDEX_op_dup_vec: /* Always emitted via tcg_out_dup_vec. */
90
default:
91
@@ -XXX,XX +XXX,XX @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
92
case INDEX_op_sssub_vec:
93
case INDEX_op_usadd_vec:
94
case INDEX_op_ussub_vec:
95
+ case INDEX_op_bitsel_vec:
96
return 1;
97
case INDEX_op_abs_vec:
98
case INDEX_op_cmp_vec:
99
--
47
--
100
2.25.1
48
2.34.1
101
49
102
50
diff view generated by jsdifflib
1
This is minimum and maximum, signed and unsigned.
1
This bit is not saved across interrupts, so we must
2
delay delivering the interrupt until the skip has
3
been processed.
2
4
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1118
6
Reviewed-by: Michael Rolnik <mrolnik@gmail.com>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.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/arm/tcg-target.h | 2 +-
10
target/avr/helper.c | 9 +++++++++
7
tcg/arm/tcg-target.c.inc | 24 ++++++++++++++++++++++++
11
target/avr/translate.c | 26 ++++++++++++++++++++++----
8
2 files changed, 25 insertions(+), 1 deletion(-)
12
2 files changed, 31 insertions(+), 4 deletions(-)
9
13
10
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
14
diff --git a/target/avr/helper.c b/target/avr/helper.c
11
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
12
--- a/tcg/arm/tcg-target.h
16
--- a/target/avr/helper.c
13
+++ b/tcg/arm/tcg-target.h
17
+++ b/target/avr/helper.c
14
@@ -XXX,XX +XXX,XX @@ extern bool use_neon_instructions;
18
@@ -XXX,XX +XXX,XX @@ bool avr_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
15
#define TCG_TARGET_HAS_shv_vec 0
19
AVRCPU *cpu = AVR_CPU(cs);
16
#define TCG_TARGET_HAS_mul_vec 1
20
CPUAVRState *env = &cpu->env;
17
#define TCG_TARGET_HAS_sat_vec 1
21
18
-#define TCG_TARGET_HAS_minmax_vec 0
22
+ /*
19
+#define TCG_TARGET_HAS_minmax_vec 1
23
+ * We cannot separate a skip from the next instruction,
20
#define TCG_TARGET_HAS_bitsel_vec 0
24
+ * as the skip would not be preserved across the interrupt.
21
#define TCG_TARGET_HAS_cmpsel_vec 0
25
+ * Separating the two insn normally only happens at page boundaries.
22
26
+ */
23
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
27
+ if (env->skip) {
28
+ return false;
29
+ }
30
+
31
if (interrupt_request & CPU_INTERRUPT_RESET) {
32
if (cpu_interrupts_enabled(env)) {
33
cs->exception_index = EXCP_RESET;
34
diff --git a/target/avr/translate.c b/target/avr/translate.c
24
index XXXXXXX..XXXXXXX 100644
35
index XXXXXXX..XXXXXXX 100644
25
--- a/tcg/arm/tcg-target.c.inc
36
--- a/target/avr/translate.c
26
+++ b/tcg/arm/tcg-target.c.inc
37
+++ b/target/avr/translate.c
27
@@ -XXX,XX +XXX,XX @@ typedef enum {
38
@@ -XXX,XX +XXX,XX @@ static void avr_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
28
INSN_VQADD_U = 0xf3000010,
39
if (skip_label) {
29
INSN_VQSUB = 0xf2000210,
40
canonicalize_skip(ctx);
30
INSN_VQSUB_U = 0xf3000210,
41
gen_set_label(skip_label);
31
+ INSN_VMAX = 0xf2000600,
42
- if (ctx->base.is_jmp == DISAS_NORETURN) {
32
+ INSN_VMAX_U = 0xf3000600,
43
+
33
+ INSN_VMIN = 0xf2000610,
44
+ switch (ctx->base.is_jmp) {
34
+ INSN_VMIN_U = 0xf3000610,
45
+ case DISAS_NORETURN:
35
46
ctx->base.is_jmp = DISAS_CHAIN;
36
INSN_VABS = 0xf3b10300,
47
+ break;
37
INSN_VMVN = 0xf3b00580,
48
+ case DISAS_NEXT:
38
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
49
+ if (ctx->base.tb->flags & TB_FLAGS_SKIP) {
39
case INDEX_op_dup2_vec:
50
+ ctx->base.is_jmp = DISAS_TOO_MANY;
40
case INDEX_op_add_vec:
51
+ }
41
case INDEX_op_mul_vec:
52
+ break;
42
+ case INDEX_op_smax_vec:
53
+ default:
43
+ case INDEX_op_smin_vec:
54
+ break;
44
case INDEX_op_ssadd_vec:
55
}
45
case INDEX_op_sssub_vec:
56
}
46
case INDEX_op_sub_vec:
57
47
+ case INDEX_op_umax_vec:
58
@@ -XXX,XX +XXX,XX @@ static void avr_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
48
+ case INDEX_op_umin_vec:
59
{
49
case INDEX_op_usadd_vec:
60
DisasContext *ctx = container_of(dcbase, DisasContext, base);
50
case INDEX_op_ussub_vec:
61
bool nonconst_skip = canonicalize_skip(ctx);
51
case INDEX_op_xor_vec:
62
+ /*
52
@@ -XXX,XX +XXX,XX @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
63
+ * Because we disable interrupts while env->skip is set,
53
case INDEX_op_mul_vec:
64
+ * we must return to the main loop to re-evaluate afterward.
54
tcg_out_vreg3(s, INSN_VMUL, q, vece, a0, a1, a2);
65
+ */
55
return;
66
+ bool force_exit = ctx->base.tb->flags & TB_FLAGS_SKIP;
56
+ case INDEX_op_smax_vec:
67
57
+ tcg_out_vreg3(s, INSN_VMAX, q, vece, a0, a1, a2);
68
switch (ctx->base.is_jmp) {
58
+ return;
69
case DISAS_NORETURN:
59
+ case INDEX_op_smin_vec:
70
@@ -XXX,XX +XXX,XX @@ static void avr_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
60
+ tcg_out_vreg3(s, INSN_VMIN, q, vece, a0, a1, a2);
71
case DISAS_NEXT:
61
+ return;
72
case DISAS_TOO_MANY:
62
case INDEX_op_sub_vec:
73
case DISAS_CHAIN:
63
tcg_out_vreg3(s, INSN_VSUB, q, vece, a0, a1, a2);
74
- if (!nonconst_skip) {
64
return;
75
+ if (!nonconst_skip && !force_exit) {
65
@@ -XXX,XX +XXX,XX @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
76
/* Note gen_goto_tb checks singlestep. */
66
case INDEX_op_sssub_vec:
77
gen_goto_tb(ctx, 1, ctx->npc);
67
tcg_out_vreg3(s, INSN_VQSUB, q, vece, a0, a1, a2);
78
break;
68
return;
79
@@ -XXX,XX +XXX,XX @@ static void avr_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
69
+ case INDEX_op_umax_vec:
80
tcg_gen_movi_tl(cpu_pc, ctx->npc);
70
+ tcg_out_vreg3(s, INSN_VMAX_U, q, vece, a0, a1, a2);
81
/* fall through */
71
+ return;
82
case DISAS_LOOKUP:
72
+ case INDEX_op_umin_vec:
83
- tcg_gen_lookup_and_goto_ptr();
73
+ tcg_out_vreg3(s, INSN_VMIN_U, q, vece, a0, a1, a2);
84
- break;
74
+ return;
85
+ if (!force_exit) {
75
case INDEX_op_usadd_vec:
86
+ tcg_gen_lookup_and_goto_ptr();
76
tcg_out_vreg3(s, INSN_VQADD_U, q, vece, a0, a1, a2);
87
+ break;
77
return;
88
+ }
78
@@ -XXX,XX +XXX,XX @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
89
+ /* fall through */
79
case INDEX_op_cmp_vec:
90
case DISAS_EXIT:
80
case INDEX_op_mul_vec:
91
tcg_gen_exit_tb(NULL, 0);
81
case INDEX_op_neg_vec:
92
break;
82
+ case INDEX_op_smax_vec:
83
+ case INDEX_op_smin_vec:
84
+ case INDEX_op_umax_vec:
85
+ case INDEX_op_umin_vec:
86
return vece < MO_64;
87
default:
88
return 0;
89
--
93
--
90
2.25.1
94
2.34.1
91
95
92
96
diff view generated by jsdifflib
New patch
1
Map the stack executable if required by default or on demand.
1
2
3
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
4
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
7
include/elf.h | 1 +
8
linux-user/qemu.h | 1 +
9
linux-user/elfload.c | 19 ++++++++++++++++++-
10
3 files changed, 20 insertions(+), 1 deletion(-)
11
12
diff --git a/include/elf.h b/include/elf.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/include/elf.h
15
+++ b/include/elf.h
16
@@ -XXX,XX +XXX,XX @@ typedef int64_t Elf64_Sxword;
17
#define PT_LOPROC 0x70000000
18
#define PT_HIPROC 0x7fffffff
19
20
+#define PT_GNU_STACK (PT_LOOS + 0x474e551)
21
#define PT_GNU_PROPERTY (PT_LOOS + 0x474e553)
22
23
#define PT_MIPS_REGINFO 0x70000000
24
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
25
index XXXXXXX..XXXXXXX 100644
26
--- a/linux-user/qemu.h
27
+++ b/linux-user/qemu.h
28
@@ -XXX,XX +XXX,XX @@ struct image_info {
29
uint32_t elf_flags;
30
int personality;
31
abi_ulong alignment;
32
+ bool exec_stack;
33
34
/* Generic semihosting knows about these pointers. */
35
abi_ulong arg_strings; /* strings for argv */
36
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/linux-user/elfload.c
39
+++ b/linux-user/elfload.c
40
@@ -XXX,XX +XXX,XX @@ static bool init_guest_commpage(void)
41
#define ELF_ARCH EM_386
42
43
#define ELF_PLATFORM get_elf_platform()
44
+#define EXSTACK_DEFAULT true
45
46
static const char *get_elf_platform(void)
47
{
48
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUX86State *en
49
50
#define ELF_ARCH EM_ARM
51
#define ELF_CLASS ELFCLASS32
52
+#define EXSTACK_DEFAULT true
53
54
static inline void init_thread(struct target_pt_regs *regs,
55
struct image_info *infop)
56
@@ -XXX,XX +XXX,XX @@ static inline void init_thread(struct target_pt_regs *regs,
57
#else
58
59
#define ELF_CLASS ELFCLASS32
60
+#define EXSTACK_DEFAULT true
61
62
#endif
63
64
@@ -XXX,XX +XXX,XX @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUPPCState *en
65
66
#define ELF_CLASS ELFCLASS64
67
#define ELF_ARCH EM_LOONGARCH
68
+#define EXSTACK_DEFAULT true
69
70
#define elf_check_arch(x) ((x) == EM_LOONGARCH)
71
72
@@ -XXX,XX +XXX,XX @@ static uint32_t get_elf_hwcap(void)
73
#define ELF_CLASS ELFCLASS32
74
#endif
75
#define ELF_ARCH EM_MIPS
76
+#define EXSTACK_DEFAULT true
77
78
#ifdef TARGET_ABI_MIPSN32
79
#define elf_check_abi(x) ((x) & EF_MIPS_ABI2)
80
@@ -XXX,XX +XXX,XX @@ static inline void init_thread(struct target_pt_regs *regs,
81
#define bswaptls(ptr) bswap32s(ptr)
82
#endif
83
84
+#ifndef EXSTACK_DEFAULT
85
+#define EXSTACK_DEFAULT false
86
+#endif
87
+
88
#include "elf.h"
89
90
/* We must delay the following stanzas until after "elf.h". */
91
@@ -XXX,XX +XXX,XX @@ static abi_ulong setup_arg_pages(struct linux_binprm *bprm,
92
struct image_info *info)
93
{
94
abi_ulong size, error, guard;
95
+ int prot;
96
97
size = guest_stack_size;
98
if (size < STACK_LOWER_LIMIT) {
99
@@ -XXX,XX +XXX,XX @@ static abi_ulong setup_arg_pages(struct linux_binprm *bprm,
100
guard = qemu_real_host_page_size();
101
}
102
103
- error = target_mmap(0, size + guard, PROT_READ | PROT_WRITE,
104
+ prot = PROT_READ | PROT_WRITE;
105
+ if (info->exec_stack) {
106
+ prot |= PROT_EXEC;
107
+ }
108
+ error = target_mmap(0, size + guard, prot,
109
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
110
if (error == -1) {
111
perror("mmap stack");
112
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
113
*/
114
loaddr = -1, hiaddr = 0;
115
info->alignment = 0;
116
+ info->exec_stack = EXSTACK_DEFAULT;
117
for (i = 0; i < ehdr->e_phnum; ++i) {
118
struct elf_phdr *eppnt = phdr + i;
119
if (eppnt->p_type == PT_LOAD) {
120
@@ -XXX,XX +XXX,XX @@ static void load_elf_image(const char *image_name, int image_fd,
121
if (!parse_elf_properties(image_fd, info, eppnt, bprm_buf, &err)) {
122
goto exit_errmsg;
123
}
124
+ } else if (eppnt->p_type == PT_GNU_STACK) {
125
+ info->exec_stack = eppnt->p_flags & PF_X;
126
}
127
}
128
129
--
130
2.34.1
diff view generated by jsdifflib
New patch
1
From: Ilya Leoshkevich <iii@linux.ibm.com>
1
2
3
Currently it's possible to execute pages that do not have PAGE_EXEC
4
if there is an existing translation block. Fix by invalidating TBs
5
that touch the affected pages.
6
7
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
8
Message-Id: <20220817150506.592862-2-iii@linux.ibm.com>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
---
11
linux-user/mmap.c | 6 ++++--
12
1 file changed, 4 insertions(+), 2 deletions(-)
13
14
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/linux-user/mmap.c
17
+++ b/linux-user/mmap.c
18
@@ -XXX,XX +XXX,XX @@ int target_mprotect(abi_ulong start, abi_ulong len, int target_prot)
19
goto error;
20
}
21
}
22
+
23
page_set_flags(start, start + len, page_flags);
24
- mmap_unlock();
25
- return 0;
26
+ tb_invalidate_phys_range(start, start + len);
27
+ ret = 0;
28
+
29
error:
30
mmap_unlock();
31
return ret;
32
--
33
2.34.1
diff view generated by jsdifflib
New patch
1
We're about to start validating PAGE_EXEC, which means
2
that we've got to put this code into a section that is
3
both writable and executable.
1
4
5
Note that this test did not run on hardware beforehand either.
6
7
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
8
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
---
11
tests/tcg/i386/test-i386.c | 2 +-
12
1 file changed, 1 insertion(+), 1 deletion(-)
13
14
diff --git a/tests/tcg/i386/test-i386.c b/tests/tcg/i386/test-i386.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/tcg/i386/test-i386.c
17
+++ b/tests/tcg/i386/test-i386.c
18
@@ -XXX,XX +XXX,XX @@ uint8_t code[] = {
19
0xc3, /* ret */
20
};
21
22
-asm(".section \".data\"\n"
23
+asm(".section \".data_x\",\"awx\"\n"
24
"smc_code2:\n"
25
"movl 4(%esp), %eax\n"
26
"movl %eax, smc_patch_addr2 + 1\n"
27
--
28
2.34.1
diff view generated by jsdifflib
New patch
1
From: Ilya Leoshkevich <iii@linux.ibm.com>
1
2
3
Introduce a function that checks whether a given address is on the same
4
page as where disassembly started. Having it improves readability of
5
the following patches.
6
7
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
9
Message-Id: <20220811095534.241224-3-iii@linux.ibm.com>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
[rth: Make the DisasContextBase parameter const.]
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
---
14
include/exec/translator.h | 10 ++++++++++
15
1 file changed, 10 insertions(+)
16
17
diff --git a/include/exec/translator.h b/include/exec/translator.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/exec/translator.h
20
+++ b/include/exec/translator.h
21
@@ -XXX,XX +XXX,XX @@ FOR_EACH_TRANSLATOR_LD(GEN_TRANSLATOR_LD)
22
23
#undef GEN_TRANSLATOR_LD
24
25
+/*
26
+ * Return whether addr is on the same page as where disassembly started.
27
+ * Translators can use this to enforce the rule that only single-insn
28
+ * translation blocks are allowed to cross page boundaries.
29
+ */
30
+static inline bool is_same_page(const DisasContextBase *db, target_ulong addr)
31
+{
32
+ return ((addr ^ db->pc_first) & TARGET_PAGE_MASK) == 0;
33
+}
34
+
35
#endif /* EXEC__TRANSLATOR_H */
36
--
37
2.34.1
diff view generated by jsdifflib
New patch
1
The current implementation is a no-op, simply returning addr.
2
This is incorrect, because we ought to be checking the page
3
permissions for execution.
1
4
5
Make get_page_addr_code inline for both implementations.
6
7
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
8
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
9
Acked-by: Alistair Francis <alistair.francis@wdc.com>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
---
12
include/exec/exec-all.h | 85 ++++++++++++++---------------------------
13
accel/tcg/cputlb.c | 5 ---
14
accel/tcg/user-exec.c | 14 +++++++
15
3 files changed, 42 insertions(+), 62 deletions(-)
16
17
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/include/exec/exec-all.h
20
+++ b/include/exec/exec-all.h
21
@@ -XXX,XX +XXX,XX @@ struct MemoryRegionSection *iotlb_to_section(CPUState *cpu,
22
hwaddr index, MemTxAttrs attrs);
23
#endif
24
25
-#if defined(CONFIG_USER_ONLY)
26
-void mmap_lock(void);
27
-void mmap_unlock(void);
28
-bool have_mmap_lock(void);
29
-
30
/**
31
- * get_page_addr_code() - user-mode version
32
+ * get_page_addr_code_hostp()
33
* @env: CPUArchState
34
* @addr: guest virtual address of guest code
35
*
36
- * Returns @addr.
37
+ * See get_page_addr_code() (full-system version) for documentation on the
38
+ * return value.
39
+ *
40
+ * Sets *@hostp (when @hostp is non-NULL) as follows.
41
+ * If the return value is -1, sets *@hostp to NULL. Otherwise, sets *@hostp
42
+ * to the host address where @addr's content is kept.
43
+ *
44
+ * Note: this function can trigger an exception.
45
+ */
46
+tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
47
+ void **hostp);
48
+
49
+/**
50
+ * get_page_addr_code()
51
+ * @env: CPUArchState
52
+ * @addr: guest virtual address of guest code
53
+ *
54
+ * If we cannot translate and execute from the entire RAM page, or if
55
+ * the region is not backed by RAM, returns -1. Otherwise, returns the
56
+ * ram_addr_t corresponding to the guest code at @addr.
57
+ *
58
+ * Note: this function can trigger an exception.
59
*/
60
static inline tb_page_addr_t get_page_addr_code(CPUArchState *env,
61
target_ulong addr)
62
{
63
- return addr;
64
+ return get_page_addr_code_hostp(env, addr, NULL);
65
}
66
67
-/**
68
- * get_page_addr_code_hostp() - user-mode version
69
- * @env: CPUArchState
70
- * @addr: guest virtual address of guest code
71
- *
72
- * Returns @addr.
73
- *
74
- * If @hostp is non-NULL, sets *@hostp to the host address where @addr's content
75
- * is kept.
76
- */
77
-static inline tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env,
78
- target_ulong addr,
79
- void **hostp)
80
-{
81
- if (hostp) {
82
- *hostp = g2h_untagged(addr);
83
- }
84
- return addr;
85
-}
86
+#if defined(CONFIG_USER_ONLY)
87
+void mmap_lock(void);
88
+void mmap_unlock(void);
89
+bool have_mmap_lock(void);
90
91
/**
92
* adjust_signal_pc:
93
@@ -XXX,XX +XXX,XX @@ G_NORETURN void cpu_loop_exit_sigbus(CPUState *cpu, target_ulong addr,
94
static inline void mmap_lock(void) {}
95
static inline void mmap_unlock(void) {}
96
97
-/**
98
- * get_page_addr_code() - full-system version
99
- * @env: CPUArchState
100
- * @addr: guest virtual address of guest code
101
- *
102
- * If we cannot translate and execute from the entire RAM page, or if
103
- * the region is not backed by RAM, returns -1. Otherwise, returns the
104
- * ram_addr_t corresponding to the guest code at @addr.
105
- *
106
- * Note: this function can trigger an exception.
107
- */
108
-tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr);
109
-
110
-/**
111
- * get_page_addr_code_hostp() - full-system version
112
- * @env: CPUArchState
113
- * @addr: guest virtual address of guest code
114
- *
115
- * See get_page_addr_code() (full-system version) for documentation on the
116
- * return value.
117
- *
118
- * Sets *@hostp (when @hostp is non-NULL) as follows.
119
- * If the return value is -1, sets *@hostp to NULL. Otherwise, sets *@hostp
120
- * to the host address where @addr's content is kept.
121
- *
122
- * Note: this function can trigger an exception.
123
- */
124
-tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
125
- void **hostp);
126
-
127
void tlb_reset_dirty(CPUState *cpu, ram_addr_t start1, ram_addr_t length);
128
void tlb_set_dirty(CPUState *cpu, target_ulong vaddr);
129
130
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
131
index XXXXXXX..XXXXXXX 100644
132
--- a/accel/tcg/cputlb.c
133
+++ b/accel/tcg/cputlb.c
134
@@ -XXX,XX +XXX,XX @@ tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
135
return qemu_ram_addr_from_host_nofail(p);
136
}
137
138
-tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
139
-{
140
- return get_page_addr_code_hostp(env, addr, NULL);
141
-}
142
-
143
static void notdirty_write(CPUState *cpu, vaddr mem_vaddr, unsigned size,
144
CPUIOTLBEntry *iotlbentry, uintptr_t retaddr)
145
{
146
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/accel/tcg/user-exec.c
149
+++ b/accel/tcg/user-exec.c
150
@@ -XXX,XX +XXX,XX @@ void *probe_access(CPUArchState *env, target_ulong addr, int size,
151
return size ? g2h(env_cpu(env), addr) : NULL;
152
}
153
154
+tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
155
+ void **hostp)
156
+{
157
+ int flags;
158
+
159
+ flags = probe_access_internal(env, addr, 1, MMU_INST_FETCH, false, 0);
160
+ g_assert(flags == 0);
161
+
162
+ if (hostp) {
163
+ *hostp = g2h_untagged(addr);
164
+ }
165
+ return addr;
166
+}
167
+
168
/* The softmmu versions of these helpers are in cputlb.c. */
169
170
/*
171
--
172
2.34.1
diff view generated by jsdifflib
1
Implement via expansion, so don't actually set TCG_TARGET_HAS_roti_vec.
1
The mmap_lock is held around tb_gen_code. While the comment
2
For NEON, this is shift-right followed by shift-left-and-insert.
2
is correct that the lock is dropped when tb_gen_code runs out
3
of memory, the lock is *not* dropped when an exception is
4
raised reading code for translation.
3
5
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Acked-by: Alistair Francis <alistair.francis@wdc.com>
7
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
8
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
10
---
7
tcg/arm/tcg-target-con-set.h | 1 +
11
accel/tcg/cpu-exec.c | 12 ++++++------
8
tcg/arm/tcg-target.opc.h | 1 +
12
accel/tcg/user-exec.c | 3 ---
9
tcg/arm/tcg-target.c.inc | 15 +++++++++++++++
13
2 files changed, 6 insertions(+), 9 deletions(-)
10
3 files changed, 17 insertions(+)
11
14
12
diff --git a/tcg/arm/tcg-target-con-set.h b/tcg/arm/tcg-target-con-set.h
15
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
13
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
14
--- a/tcg/arm/tcg-target-con-set.h
17
--- a/accel/tcg/cpu-exec.c
15
+++ b/tcg/arm/tcg-target-con-set.h
18
+++ b/accel/tcg/cpu-exec.c
16
@@ -XXX,XX +XXX,XX @@ C_O1_I2(r, r, rIK)
19
@@ -XXX,XX +XXX,XX @@ void cpu_exec_step_atomic(CPUState *cpu)
17
C_O1_I2(r, r, rIN)
20
cpu_tb_exec(cpu, tb, &tb_exit);
18
C_O1_I2(r, r, ri)
21
cpu_exec_exit(cpu);
19
C_O1_I2(r, rZ, rZ)
22
} else {
20
+C_O1_I2(w, 0, w)
23
- /*
21
C_O1_I2(w, w, w)
24
- * The mmap_lock is dropped by tb_gen_code if it runs out of
22
C_O1_I2(w, w, wO)
25
- * memory.
23
C_O1_I2(w, w, wV)
26
- */
24
diff --git a/tcg/arm/tcg-target.opc.h b/tcg/arm/tcg-target.opc.h
27
#ifndef CONFIG_SOFTMMU
28
clear_helper_retaddr();
29
- tcg_debug_assert(!have_mmap_lock());
30
+ if (have_mmap_lock()) {
31
+ mmap_unlock();
32
+ }
33
#endif
34
if (qemu_mutex_iothread_locked()) {
35
qemu_mutex_unlock_iothread();
36
@@ -XXX,XX +XXX,XX @@ int cpu_exec(CPUState *cpu)
37
38
#ifndef CONFIG_SOFTMMU
39
clear_helper_retaddr();
40
- tcg_debug_assert(!have_mmap_lock());
41
+ if (have_mmap_lock()) {
42
+ mmap_unlock();
43
+ }
44
#endif
45
if (qemu_mutex_iothread_locked()) {
46
qemu_mutex_unlock_iothread();
47
diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c
25
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
26
--- a/tcg/arm/tcg-target.opc.h
49
--- a/accel/tcg/user-exec.c
27
+++ b/tcg/arm/tcg-target.opc.h
50
+++ b/accel/tcg/user-exec.c
28
@@ -XXX,XX +XXX,XX @@
51
@@ -XXX,XX +XXX,XX @@ MMUAccessType adjust_signal_pc(uintptr_t *pc, bool is_write)
29
* consider these to be UNSPEC with names.
52
* (and if the translator doesn't handle page boundaries correctly
30
*/
53
* there's little we can do about that here). Therefore, do not
31
54
* trigger the unwinder.
32
+DEF(arm_sli_vec, 1, 2, 1, IMPLVEC)
55
- *
33
DEF(arm_sshl_vec, 1, 2, 0, IMPLVEC)
56
- * Like tb_gen_code, release the memory lock before cpu_loop_exit.
34
DEF(arm_ushl_vec, 1, 2, 0, IMPLVEC)
57
*/
35
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
58
- mmap_unlock();
36
index XXXXXXX..XXXXXXX 100644
59
*pc = 0;
37
--- a/tcg/arm/tcg-target.c.inc
60
return MMU_INST_FETCH;
38
+++ b/tcg/arm/tcg-target.c.inc
39
@@ -XXX,XX +XXX,XX @@ typedef enum {
40
INSN_VSHLI = 0xf2800510, /* VSHL (immediate) */
41
INSN_VSARI = 0xf2800010, /* VSHR.S */
42
INSN_VSHRI = 0xf3800010, /* VSHR.U */
43
+ INSN_VSLI = 0xf3800510,
44
INSN_VSHL_S = 0xf2000400, /* VSHL.S (register) */
45
INSN_VSHL_U = 0xf3000400, /* VSHL.U (register) */
46
47
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
48
case INDEX_op_arm_sshl_vec:
49
case INDEX_op_arm_ushl_vec:
50
return C_O1_I2(w, w, w);
51
+ case INDEX_op_arm_sli_vec:
52
+ return C_O1_I2(w, 0, w);
53
case INDEX_op_or_vec:
54
case INDEX_op_andc_vec:
55
return C_O1_I2(w, w, wO);
56
@@ -XXX,XX +XXX,XX @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
57
case INDEX_op_sari_vec:
58
tcg_out_vshifti(s, INSN_VSARI, q, a0, a1, (16 << vece) - a2);
59
return;
60
+ case INDEX_op_arm_sli_vec:
61
+ tcg_out_vshifti(s, INSN_VSLI, q, a0, a2, args[3] + (8 << vece));
62
+ return;
63
64
case INDEX_op_andc_vec:
65
if (!const_args[2]) {
66
@@ -XXX,XX +XXX,XX @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
67
case INDEX_op_shlv_vec:
68
case INDEX_op_shrv_vec:
69
case INDEX_op_sarv_vec:
70
+ case INDEX_op_rotli_vec:
71
return -1;
72
default:
73
return 0;
74
@@ -XXX,XX +XXX,XX @@ void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece,
75
tcg_temp_free_vec(t1);
76
break;
77
78
+ case INDEX_op_rotli_vec:
79
+ t1 = tcg_temp_new_vec(type);
80
+ tcg_gen_shri_vec(vece, t1, v1, -a2 & ((8 << vece) - 1));
81
+ vec_gen_4(INDEX_op_arm_sli_vec, type, vece,
82
+ tcgv_vec_arg(v0), tcgv_vec_arg(t1), tcgv_vec_arg(v1), a2);
83
+ tcg_temp_free_vec(t1);
84
+ break;
85
+
86
default:
87
g_assert_not_reached();
88
}
61
}
89
--
62
--
90
2.25.1
63
2.34.1
91
92
diff view generated by jsdifflib
1
Most of dupi is copied from tcg/aarch64, which has the same
1
The function is not used outside of cpu-exec.c. Move it and
2
encoding for AdvSimdExpandImm.
2
its subroutines up in the file, before the first use.
3
3
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
5
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
6
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
8
---
7
tcg/arm/tcg-target.c.inc | 283 +++++++++++++++++++++++++++++++++++++--
9
include/exec/exec-all.h | 3 -
8
1 file changed, 275 insertions(+), 8 deletions(-)
10
accel/tcg/cpu-exec.c | 122 ++++++++++++++++++++--------------------
11
2 files changed, 61 insertions(+), 64 deletions(-)
9
12
10
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
13
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
11
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
12
--- a/tcg/arm/tcg-target.c.inc
15
--- a/include/exec/exec-all.h
13
+++ b/tcg/arm/tcg-target.c.inc
16
+++ b/include/exec/exec-all.h
14
@@ -XXX,XX +XXX,XX @@ typedef enum {
17
@@ -XXX,XX +XXX,XX @@ void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr, MemTxAttrs attrs);
15
18
#endif
16
INSN_VORR = 0xf2200110,
19
void tb_flush(CPUState *cpu);
17
20
void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr);
18
+ INSN_VDUP_G = 0xee800b10, /* VDUP (ARM core register) */
21
-TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc,
19
+ INSN_VDUP_S = 0xf3b00c00, /* VDUP (scalar) */
22
- target_ulong cs_base, uint32_t flags,
20
+ INSN_VLDR_D = 0xed100b00, /* VLDR.64 */
23
- uint32_t cflags);
21
INSN_VLD1 = 0xf4200000, /* VLD1 (multiple single elements) */
24
void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr);
22
+ INSN_VLD1R = 0xf4a00c00, /* VLD1 (single element to all lanes) */
25
23
INSN_VST1 = 0xf4000000, /* VST1 (multiple single elements) */
26
/* GETPC is the true target of the return instruction that we'll execute. */
24
+ INSN_VMOVI = 0xf2800010, /* VMOV (immediate) */
27
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
25
} ARMInsn;
28
index XXXXXXX..XXXXXXX 100644
26
29
--- a/accel/tcg/cpu-exec.c
27
#define INSN_NOP (use_armv7_instructions ? INSN_NOP_v6k : INSN_NOP_v4)
30
+++ b/accel/tcg/cpu-exec.c
28
@@ -XXX,XX +XXX,XX @@ static const uint8_t tcg_cond_to_arm_cond[] = {
31
@@ -XXX,XX +XXX,XX @@ uint32_t curr_cflags(CPUState *cpu)
29
[TCG_COND_GTU] = COND_HI,
32
return cflags;
30
};
33
}
31
34
32
+static int encode_imm(uint32_t imm);
35
+struct tb_desc {
36
+ target_ulong pc;
37
+ target_ulong cs_base;
38
+ CPUArchState *env;
39
+ tb_page_addr_t phys_page1;
40
+ uint32_t flags;
41
+ uint32_t cflags;
42
+ uint32_t trace_vcpu_dstate;
43
+};
33
+
44
+
34
+/* TCG private relocation type: add with pc+imm8 */
45
+static bool tb_lookup_cmp(const void *p, const void *d)
35
+#define R_ARM_PC8 11
46
+{
47
+ const TranslationBlock *tb = p;
48
+ const struct tb_desc *desc = d;
36
+
49
+
37
+/* TCG private relocation type: vldr with imm8 << 2 */
50
+ if (tb->pc == desc->pc &&
38
+#define R_ARM_PC11 12
51
+ tb->page_addr[0] == desc->phys_page1 &&
52
+ tb->cs_base == desc->cs_base &&
53
+ tb->flags == desc->flags &&
54
+ tb->trace_vcpu_dstate == desc->trace_vcpu_dstate &&
55
+ tb_cflags(tb) == desc->cflags) {
56
+ /* check next page if needed */
57
+ if (tb->page_addr[1] == -1) {
58
+ return true;
59
+ } else {
60
+ tb_page_addr_t phys_page2;
61
+ target_ulong virt_page2;
39
+
62
+
40
static bool reloc_pc24(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
63
+ virt_page2 = (desc->pc & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
41
{
64
+ phys_page2 = get_page_addr_code(desc->env, virt_page2);
42
const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
65
+ if (tb->page_addr[1] == phys_page2) {
43
@@ -XXX,XX +XXX,XX @@ static bool reloc_pc13(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
66
+ return true;
44
return false;
67
+ }
45
}
46
47
+static bool reloc_pc11(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
48
+{
49
+ const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
50
+ ptrdiff_t offset = (tcg_ptr_byte_diff(target, src_rx) - 8) / 4;
51
+
52
+ if (offset >= -0xff && offset <= 0xff) {
53
+ tcg_insn_unit insn = *src_rw;
54
+ bool u = (offset >= 0);
55
+ if (!u) {
56
+ offset = -offset;
57
+ }
68
+ }
58
+ insn = deposit32(insn, 23, 1, u);
59
+ insn = deposit32(insn, 0, 8, offset);
60
+ *src_rw = insn;
61
+ return true;
62
+ }
69
+ }
63
+ return false;
70
+ return false;
64
+}
71
+}
65
+
72
+
66
+static bool reloc_pc8(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
73
+static TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc,
74
+ target_ulong cs_base, uint32_t flags,
75
+ uint32_t cflags)
67
+{
76
+{
68
+ const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
77
+ tb_page_addr_t phys_pc;
69
+ ptrdiff_t offset = tcg_ptr_byte_diff(target, src_rx) - 8;
78
+ struct tb_desc desc;
70
+ int rot = encode_imm(offset);
79
+ uint32_t h;
71
+
80
+
72
+ if (rot >= 0) {
81
+ desc.env = cpu->env_ptr;
73
+ *src_rw = deposit32(*src_rw, 0, 12, rol32(offset, rot) | (rot << 7));
82
+ desc.cs_base = cs_base;
74
+ return true;
83
+ desc.flags = flags;
84
+ desc.cflags = cflags;
85
+ desc.trace_vcpu_dstate = *cpu->trace_dstate;
86
+ desc.pc = pc;
87
+ phys_pc = get_page_addr_code(desc.env, pc);
88
+ if (phys_pc == -1) {
89
+ return NULL;
75
+ }
90
+ }
76
+ return false;
91
+ desc.phys_page1 = phys_pc & TARGET_PAGE_MASK;
92
+ h = tb_hash_func(phys_pc, pc, flags, cflags, *cpu->trace_dstate);
93
+ return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp);
77
+}
94
+}
78
+
95
+
79
static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
96
/* Might cause an exception, so have a longjmp destination ready */
80
intptr_t value, intptr_t addend)
97
static inline TranslationBlock *tb_lookup(CPUState *cpu, target_ulong pc,
98
target_ulong cs_base,
99
@@ -XXX,XX +XXX,XX @@ void cpu_exec_step_atomic(CPUState *cpu)
100
end_exclusive();
101
}
102
103
-struct tb_desc {
104
- target_ulong pc;
105
- target_ulong cs_base;
106
- CPUArchState *env;
107
- tb_page_addr_t phys_page1;
108
- uint32_t flags;
109
- uint32_t cflags;
110
- uint32_t trace_vcpu_dstate;
111
-};
112
-
113
-static bool tb_lookup_cmp(const void *p, const void *d)
114
-{
115
- const TranslationBlock *tb = p;
116
- const struct tb_desc *desc = d;
117
-
118
- if (tb->pc == desc->pc &&
119
- tb->page_addr[0] == desc->phys_page1 &&
120
- tb->cs_base == desc->cs_base &&
121
- tb->flags == desc->flags &&
122
- tb->trace_vcpu_dstate == desc->trace_vcpu_dstate &&
123
- tb_cflags(tb) == desc->cflags) {
124
- /* check next page if needed */
125
- if (tb->page_addr[1] == -1) {
126
- return true;
127
- } else {
128
- tb_page_addr_t phys_page2;
129
- target_ulong virt_page2;
130
-
131
- virt_page2 = (desc->pc & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
132
- phys_page2 = get_page_addr_code(desc->env, virt_page2);
133
- if (tb->page_addr[1] == phys_page2) {
134
- return true;
135
- }
136
- }
137
- }
138
- return false;
139
-}
140
-
141
-TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc,
142
- target_ulong cs_base, uint32_t flags,
143
- uint32_t cflags)
144
-{
145
- tb_page_addr_t phys_pc;
146
- struct tb_desc desc;
147
- uint32_t h;
148
-
149
- desc.env = cpu->env_ptr;
150
- desc.cs_base = cs_base;
151
- desc.flags = flags;
152
- desc.cflags = cflags;
153
- desc.trace_vcpu_dstate = *cpu->trace_dstate;
154
- desc.pc = pc;
155
- phys_pc = get_page_addr_code(desc.env, pc);
156
- if (phys_pc == -1) {
157
- return NULL;
158
- }
159
- desc.phys_page1 = phys_pc & TARGET_PAGE_MASK;
160
- h = tb_hash_func(phys_pc, pc, flags, cflags, *cpu->trace_dstate);
161
- return qht_lookup_custom(&tb_ctx.htable, &desc, h, tb_lookup_cmp);
162
-}
163
-
164
void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr)
81
{
165
{
82
tcg_debug_assert(addend == 0);
166
if (TCG_TARGET_HAS_direct_jump) {
83
-
84
- if (type == R_ARM_PC24) {
85
+ switch (type) {
86
+ case R_ARM_PC24:
87
return reloc_pc24(code_ptr, (const tcg_insn_unit *)value);
88
- } else if (type == R_ARM_PC13) {
89
+ case R_ARM_PC13:
90
return reloc_pc13(code_ptr, (const tcg_insn_unit *)value);
91
- } else {
92
+ case R_ARM_PC11:
93
+ return reloc_pc11(code_ptr, (const tcg_insn_unit *)value);
94
+ case R_ARM_PC8:
95
+ return reloc_pc8(code_ptr, (const tcg_insn_unit *)value);
96
+ default:
97
g_assert_not_reached();
98
}
99
}
100
@@ -XXX,XX +XXX,XX @@ static inline uint32_t rotl(uint32_t val, int n)
101
102
/* ARM immediates for ALU instructions are made of an unsigned 8-bit
103
right-rotated by an even amount between 0 and 30. */
104
-static inline int encode_imm(uint32_t imm)
105
+static int encode_imm(uint32_t imm)
106
{
107
int shift;
108
109
@@ -XXX,XX +XXX,XX @@ static inline int check_fit_imm(uint32_t imm)
110
return encode_imm(imm) >= 0;
111
}
112
113
+/* Return true if v16 is a valid 16-bit shifted immediate. */
114
+static bool is_shimm16(uint16_t v16, int *cmode, int *imm8)
115
+{
116
+ if (v16 == (v16 & 0xff)) {
117
+ *cmode = 0x8;
118
+ *imm8 = v16 & 0xff;
119
+ return true;
120
+ } else if (v16 == (v16 & 0xff00)) {
121
+ *cmode = 0xa;
122
+ *imm8 = v16 >> 8;
123
+ return true;
124
+ }
125
+ return false;
126
+}
127
+
128
+/* Return true if v32 is a valid 32-bit shifted immediate. */
129
+static bool is_shimm32(uint32_t v32, int *cmode, int *imm8)
130
+{
131
+ if (v32 == (v32 & 0xff)) {
132
+ *cmode = 0x0;
133
+ *imm8 = v32 & 0xff;
134
+ return true;
135
+ } else if (v32 == (v32 & 0xff00)) {
136
+ *cmode = 0x2;
137
+ *imm8 = (v32 >> 8) & 0xff;
138
+ return true;
139
+ } else if (v32 == (v32 & 0xff0000)) {
140
+ *cmode = 0x4;
141
+ *imm8 = (v32 >> 16) & 0xff;
142
+ return true;
143
+ } else if (v32 == (v32 & 0xff000000)) {
144
+ *cmode = 0x6;
145
+ *imm8 = v32 >> 24;
146
+ return true;
147
+ }
148
+ return false;
149
+}
150
+
151
+/* Return true if v32 is a valid 32-bit shifting ones immediate. */
152
+static bool is_soimm32(uint32_t v32, int *cmode, int *imm8)
153
+{
154
+ if ((v32 & 0xffff00ff) == 0xff) {
155
+ *cmode = 0xc;
156
+ *imm8 = (v32 >> 8) & 0xff;
157
+ return true;
158
+ } else if ((v32 & 0xff00ffff) == 0xffff) {
159
+ *cmode = 0xd;
160
+ *imm8 = (v32 >> 16) & 0xff;
161
+ return true;
162
+ }
163
+ return false;
164
+}
165
+
166
+/*
167
+ * Return non-zero if v32 can be formed by MOVI+ORR.
168
+ * Place the parameters for MOVI in (cmode, imm8).
169
+ * Return the cmode for ORR; the imm8 can be had via extraction from v32.
170
+ */
171
+static int is_shimm32_pair(uint32_t v32, int *cmode, int *imm8)
172
+{
173
+ int i;
174
+
175
+ for (i = 6; i > 0; i -= 2) {
176
+ /* Mask out one byte we can add with ORR. */
177
+ uint32_t tmp = v32 & ~(0xffu << (i * 4));
178
+ if (is_shimm32(tmp, cmode, imm8) ||
179
+ is_soimm32(tmp, cmode, imm8)) {
180
+ break;
181
+ }
182
+ }
183
+ return i;
184
+}
185
+
186
/* Test if a constant matches the constraint.
187
* TODO: define constraints for:
188
*
189
@@ -XXX,XX +XXX,XX @@ static void tcg_out_vreg3(TCGContext *s, ARMInsn insn, int q, int vece,
190
encode_vd(d) | encode_vn(n) | encode_vm(m));
191
}
192
193
+static void tcg_out_vmovi(TCGContext *s, TCGReg rd,
194
+ int q, int op, int cmode, uint8_t imm8)
195
+{
196
+ tcg_out32(s, INSN_VMOVI | encode_vd(rd) | (q << 6) | (op << 5)
197
+ | (cmode << 8) | extract32(imm8, 0, 4)
198
+ | (extract32(imm8, 4, 3) << 16)
199
+ | (extract32(imm8, 7, 1) << 24));
200
+}
201
+
202
static void tcg_out_vldst(TCGContext *s, ARMInsn insn,
203
TCGReg rd, TCGReg rn, int offset)
204
{
205
@@ -XXX,XX +XXX,XX @@ static void tcg_out_movi(TCGContext *s, TCGType type,
206
tcg_out_movi32(s, COND_AL, ret, arg);
207
}
208
209
+/* Type is always V128, with I64 elements. */
210
+static void tcg_out_dup2_vec(TCGContext *s, TCGReg rd, TCGReg rl, TCGReg rh)
211
+{
212
+ /* Move high element into place first. */
213
+ /* VMOV Dd+1, Ds */
214
+ tcg_out_vreg3(s, INSN_VORR | (1 << 12), 0, 0, rd, rh, rh);
215
+ /* Move low element into place; tcg_out_mov will check for nop. */
216
+ tcg_out_mov(s, TCG_TYPE_V64, rd, rl);
217
+}
218
+
219
static bool tcg_out_dup_vec(TCGContext *s, TCGType type, unsigned vece,
220
TCGReg rd, TCGReg rs)
221
{
222
- g_assert_not_reached();
223
+ int q = type - TCG_TYPE_V64;
224
+
225
+ if (vece == MO_64) {
226
+ if (type == TCG_TYPE_V128) {
227
+ tcg_out_dup2_vec(s, rd, rs, rs);
228
+ } else {
229
+ tcg_out_mov(s, TCG_TYPE_V64, rd, rs);
230
+ }
231
+ } else if (rs < TCG_REG_Q0) {
232
+ int b = (vece == MO_8);
233
+ int e = (vece == MO_16);
234
+ tcg_out32(s, INSN_VDUP_G | (b << 22) | (q << 21) | (e << 5) |
235
+ encode_vn(rd) | (rs << 12));
236
+ } else {
237
+ int imm4 = 1 << vece;
238
+ tcg_out32(s, INSN_VDUP_S | (imm4 << 16) | (q << 6) |
239
+ encode_vd(rd) | encode_vm(rs));
240
+ }
241
+ return true;
242
}
243
244
static bool tcg_out_dupm_vec(TCGContext *s, TCGType type, unsigned vece,
245
TCGReg rd, TCGReg base, intptr_t offset)
246
{
247
- g_assert_not_reached();
248
+ if (vece == MO_64) {
249
+ tcg_out_ld(s, TCG_TYPE_V64, rd, base, offset);
250
+ if (type == TCG_TYPE_V128) {
251
+ tcg_out_dup2_vec(s, rd, rd, rd);
252
+ }
253
+ } else {
254
+ int q = type - TCG_TYPE_V64;
255
+ tcg_out_vldst(s, INSN_VLD1R | (vece << 6) | (q << 5),
256
+ rd, base, offset);
257
+ }
258
+ return true;
259
}
260
261
static void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece,
262
TCGReg rd, int64_t v64)
263
{
264
- g_assert_not_reached();
265
+ int q = type - TCG_TYPE_V64;
266
+ int cmode, imm8, i;
267
+
268
+ /* Test all bytes equal first. */
269
+ if (vece == MO_8) {
270
+ tcg_out_vmovi(s, rd, q, 0, 0xe, v64);
271
+ return;
272
+ }
273
+
274
+ /*
275
+ * Test all bytes 0x00 or 0xff second. This can match cases that
276
+ * might otherwise take 2 or 3 insns for MO_16 or MO_32 below.
277
+ */
278
+ for (i = imm8 = 0; i < 8; i++) {
279
+ uint8_t byte = v64 >> (i * 8);
280
+ if (byte == 0xff) {
281
+ imm8 |= 1 << i;
282
+ } else if (byte != 0) {
283
+ goto fail_bytes;
284
+ }
285
+ }
286
+ tcg_out_vmovi(s, rd, q, 1, 0xe, imm8);
287
+ return;
288
+ fail_bytes:
289
+
290
+ /*
291
+ * Tests for various replications. For each element width, if we
292
+ * cannot find an expansion there's no point checking a larger
293
+ * width because we already know by replication it cannot match.
294
+ */
295
+ if (vece == MO_16) {
296
+ uint16_t v16 = v64;
297
+
298
+ if (is_shimm16(v16, &cmode, &imm8)) {
299
+ tcg_out_vmovi(s, rd, q, 0, cmode, imm8);
300
+ return;
301
+ }
302
+ if (is_shimm16(~v16, &cmode, &imm8)) {
303
+ tcg_out_vmovi(s, rd, q, 1, cmode, imm8);
304
+ return;
305
+ }
306
+
307
+ /*
308
+ * Otherwise, all remaining constants can be loaded in two insns:
309
+ * rd = v16 & 0xff, rd |= v16 & 0xff00.
310
+ */
311
+ tcg_out_vmovi(s, rd, q, 0, 0x8, v16 & 0xff);
312
+ tcg_out_vmovi(s, rd, q, 0, 0xb, v16 >> 8); /* VORRI */
313
+ return;
314
+ }
315
+
316
+ if (vece == MO_32) {
317
+ uint32_t v32 = v64;
318
+
319
+ if (is_shimm32(v32, &cmode, &imm8) ||
320
+ is_soimm32(v32, &cmode, &imm8)) {
321
+ tcg_out_vmovi(s, rd, q, 0, cmode, imm8);
322
+ return;
323
+ }
324
+ if (is_shimm32(~v32, &cmode, &imm8) ||
325
+ is_soimm32(~v32, &cmode, &imm8)) {
326
+ tcg_out_vmovi(s, rd, q, 1, cmode, imm8);
327
+ return;
328
+ }
329
+
330
+ /*
331
+ * Restrict the set of constants to those we can load with
332
+ * two instructions. Others we load from the pool.
333
+ */
334
+ i = is_shimm32_pair(v32, &cmode, &imm8);
335
+ if (i) {
336
+ tcg_out_vmovi(s, rd, q, 0, cmode, imm8);
337
+ tcg_out_vmovi(s, rd, q, 0, i | 1, extract32(v32, i * 4, 8));
338
+ return;
339
+ }
340
+ i = is_shimm32_pair(~v32, &cmode, &imm8);
341
+ if (i) {
342
+ tcg_out_vmovi(s, rd, q, 1, cmode, imm8);
343
+ tcg_out_vmovi(s, rd, q, 1, i | 1, extract32(~v32, i * 4, 8));
344
+ return;
345
+ }
346
+ }
347
+
348
+ /*
349
+ * As a last resort, load from the constant pool.
350
+ */
351
+ if (!q || vece == MO_64) {
352
+ new_pool_l2(s, R_ARM_PC11, s->code_ptr, 0, v64, v64 >> 32);
353
+ /* VLDR Dd, [pc + offset] */
354
+ tcg_out32(s, INSN_VLDR_D | encode_vd(rd) | (0xf << 16));
355
+ if (q) {
356
+ tcg_out_dup2_vec(s, rd, rd, rd);
357
+ }
358
+ } else {
359
+ new_pool_label(s, (uint32_t)v64, R_ARM_PC8, s->code_ptr, 0);
360
+ /* add tmp, pc, offset */
361
+ tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_TMP, TCG_REG_PC, 0);
362
+ tcg_out_dupm_vec(s, type, MO_32, rd, TCG_REG_TMP, 0);
363
+ }
364
}
365
366
static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
367
--
167
--
368
2.25.1
168
2.34.1
369
370
diff view generated by jsdifflib
1
Change the return value to bool, because that's what is should
1
The base qemu_ram_addr_from_host function is already in
2
have been from the start. Pass the ct mask instead of the whole
2
softmmu/physmem.c; move the nofail version to be adjacent.
3
TCGArgConstraint, as that's the only part that's relevant.
4
3
5
Change the value argument to int64_t. We will need the extra
4
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
width for 32-bit hosts wanting to match vector constants.
5
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
7
6
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
---
8
---
11
tcg/tcg.c | 5 ++---
9
include/exec/cpu-common.h | 1 +
12
tcg/aarch64/tcg-target.c.inc | 5 +----
10
accel/tcg/cputlb.c | 12 ------------
13
tcg/arm/tcg-target.c.inc | 5 +----
11
softmmu/physmem.c | 12 ++++++++++++
14
tcg/i386/tcg-target.c.inc | 4 +---
12
3 files changed, 13 insertions(+), 12 deletions(-)
15
tcg/mips/tcg-target.c.inc | 5 +----
16
tcg/ppc/tcg-target.c.inc | 4 +---
17
tcg/riscv/tcg-target.c.inc | 4 +---
18
tcg/s390/tcg-target.c.inc | 5 +----
19
tcg/sparc/tcg-target.c.inc | 5 +----
20
tcg/tci/tcg-target.c.inc | 6 ++----
21
10 files changed, 12 insertions(+), 36 deletions(-)
22
13
23
diff --git a/tcg/tcg.c b/tcg/tcg.c
14
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
24
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
25
--- a/tcg/tcg.c
16
--- a/include/exec/cpu-common.h
26
+++ b/tcg/tcg.c
17
+++ b/include/exec/cpu-common.h
27
@@ -XXX,XX +XXX,XX @@ static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
18
@@ -XXX,XX +XXX,XX @@ typedef uintptr_t ram_addr_t;
28
static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
19
void qemu_ram_remap(ram_addr_t addr, ram_addr_t length);
29
TCGReg base, intptr_t ofs);
20
/* This should not be used by devices. */
30
static void tcg_out_call(TCGContext *s, const tcg_insn_unit *target);
21
ram_addr_t qemu_ram_addr_from_host(void *ptr);
31
-static int tcg_target_const_match(tcg_target_long val, TCGType type,
22
+ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr);
32
- const TCGArgConstraint *arg_ct);
23
RAMBlock *qemu_ram_block_by_name(const char *name);
33
+static bool tcg_target_const_match(int64_t val, TCGType type, int ct);
24
RAMBlock *qemu_ram_block_from_host(void *ptr, bool round_offset,
34
#ifdef TCG_TARGET_NEED_LDST_LABELS
25
ram_addr_t *offset);
35
static int tcg_out_ldst_finalize(TCGContext *s);
26
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
36
#endif
37
@@ -XXX,XX +XXX,XX @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op)
38
ts = arg_temp(arg);
39
40
if (ts->val_type == TEMP_VAL_CONST
41
- && tcg_target_const_match(ts->val, ts->type, arg_ct)) {
42
+ && tcg_target_const_match(ts->val, ts->type, arg_ct->ct)) {
43
/* constant is OK for instruction */
44
const_args[i] = 1;
45
new_args[i] = ts->val;
46
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
47
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
48
--- a/tcg/aarch64/tcg-target.c.inc
28
--- a/accel/tcg/cputlb.c
49
+++ b/tcg/aarch64/tcg-target.c.inc
29
+++ b/accel/tcg/cputlb.c
50
@@ -XXX,XX +XXX,XX @@ static bool is_shimm1632(uint32_t v32, int *cmode, int *imm8)
30
@@ -XXX,XX +XXX,XX @@ void tlb_set_page(CPUState *cpu, target_ulong vaddr,
51
}
31
prot, mmu_idx, size);
52
}
32
}
53
33
54
-static int tcg_target_const_match(tcg_target_long val, TCGType type,
34
-static inline ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
55
- const TCGArgConstraint *arg_ct)
35
-{
56
+static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
36
- ram_addr_t ram_addr;
57
{
58
- int ct = arg_ct->ct;
59
-
37
-
60
if (ct & TCG_CT_CONST) {
38
- ram_addr = qemu_ram_addr_from_host(ptr);
61
return 1;
39
- if (ram_addr == RAM_ADDR_INVALID) {
62
}
40
- error_report("Bad ram pointer %p", ptr);
63
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
41
- abort();
42
- }
43
- return ram_addr;
44
-}
45
-
46
/*
47
* Note: tlb_fill() can trigger a resize of the TLB. This means that all of the
48
* caller's prior references to the TLB table (e.g. CPUTLBEntry pointers) must
49
diff --git a/softmmu/physmem.c b/softmmu/physmem.c
64
index XXXXXXX..XXXXXXX 100644
50
index XXXXXXX..XXXXXXX 100644
65
--- a/tcg/arm/tcg-target.c.inc
51
--- a/softmmu/physmem.c
66
+++ b/tcg/arm/tcg-target.c.inc
52
+++ b/softmmu/physmem.c
67
@@ -XXX,XX +XXX,XX @@ static inline int check_fit_imm(uint32_t imm)
53
@@ -XXX,XX +XXX,XX @@ ram_addr_t qemu_ram_addr_from_host(void *ptr)
68
* mov operand2: values represented with x << (2 * y), x < 0x100
54
return block->offset + offset;
69
* add, sub, eor...: ditto
70
*/
71
-static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
72
- const TCGArgConstraint *arg_ct)
73
+static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
74
{
75
- int ct;
76
- ct = arg_ct->ct;
77
if (ct & TCG_CT_CONST) {
78
return 1;
79
} else if ((ct & TCG_CT_CONST_ARM) && check_fit_imm(val)) {
80
diff --git a/tcg/i386/tcg-target.c.inc b/tcg/i386/tcg-target.c.inc
81
index XXXXXXX..XXXXXXX 100644
82
--- a/tcg/i386/tcg-target.c.inc
83
+++ b/tcg/i386/tcg-target.c.inc
84
@@ -XXX,XX +XXX,XX @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
85
}
55
}
86
56
87
/* test if a constant matches the constraint */
57
+ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr)
88
-static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
58
+{
89
- const TCGArgConstraint *arg_ct)
59
+ ram_addr_t ram_addr;
90
+static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
60
+
91
{
61
+ ram_addr = qemu_ram_addr_from_host(ptr);
92
- int ct = arg_ct->ct;
62
+ if (ram_addr == RAM_ADDR_INVALID) {
93
if (ct & TCG_CT_CONST) {
63
+ error_report("Bad ram pointer %p", ptr);
94
return 1;
64
+ abort();
95
}
65
+ }
96
diff --git a/tcg/mips/tcg-target.c.inc b/tcg/mips/tcg-target.c.inc
66
+ return ram_addr;
97
index XXXXXXX..XXXXXXX 100644
67
+}
98
--- a/tcg/mips/tcg-target.c.inc
68
+
99
+++ b/tcg/mips/tcg-target.c.inc
69
static MemTxResult flatview_read(FlatView *fv, hwaddr addr,
100
@@ -XXX,XX +XXX,XX @@ static inline bool is_p2m1(tcg_target_long val)
70
MemTxAttrs attrs, void *buf, hwaddr len);
101
}
71
static MemTxResult flatview_write(FlatView *fv, hwaddr addr, MemTxAttrs attrs,
102
103
/* test if a constant matches the constraint */
104
-static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
105
- const TCGArgConstraint *arg_ct)
106
+static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
107
{
108
- int ct;
109
- ct = arg_ct->ct;
110
if (ct & TCG_CT_CONST) {
111
return 1;
112
} else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
113
diff --git a/tcg/ppc/tcg-target.c.inc b/tcg/ppc/tcg-target.c.inc
114
index XXXXXXX..XXXXXXX 100644
115
--- a/tcg/ppc/tcg-target.c.inc
116
+++ b/tcg/ppc/tcg-target.c.inc
117
@@ -XXX,XX +XXX,XX @@ static bool reloc_pc14(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
118
}
119
120
/* test if a constant matches the constraint */
121
-static int tcg_target_const_match(tcg_target_long val, TCGType type,
122
- const TCGArgConstraint *arg_ct)
123
+static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
124
{
125
- int ct = arg_ct->ct;
126
if (ct & TCG_CT_CONST) {
127
return 1;
128
}
129
diff --git a/tcg/riscv/tcg-target.c.inc b/tcg/riscv/tcg-target.c.inc
130
index XXXXXXX..XXXXXXX 100644
131
--- a/tcg/riscv/tcg-target.c.inc
132
+++ b/tcg/riscv/tcg-target.c.inc
133
@@ -XXX,XX +XXX,XX @@ static inline tcg_target_long sextreg(tcg_target_long val, int pos, int len)
134
}
135
136
/* test if a constant matches the constraint */
137
-static int tcg_target_const_match(tcg_target_long val, TCGType type,
138
- const TCGArgConstraint *arg_ct)
139
+static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
140
{
141
- int ct = arg_ct->ct;
142
if (ct & TCG_CT_CONST) {
143
return 1;
144
}
145
diff --git a/tcg/s390/tcg-target.c.inc b/tcg/s390/tcg-target.c.inc
146
index XXXXXXX..XXXXXXX 100644
147
--- a/tcg/s390/tcg-target.c.inc
148
+++ b/tcg/s390/tcg-target.c.inc
149
@@ -XXX,XX +XXX,XX @@ static bool patch_reloc(tcg_insn_unit *src_rw, int type,
150
}
151
152
/* Test if a constant matches the constraint. */
153
-static int tcg_target_const_match(tcg_target_long val, TCGType type,
154
- const TCGArgConstraint *arg_ct)
155
+static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
156
{
157
- int ct = arg_ct->ct;
158
-
159
if (ct & TCG_CT_CONST) {
160
return 1;
161
}
162
diff --git a/tcg/sparc/tcg-target.c.inc b/tcg/sparc/tcg-target.c.inc
163
index XXXXXXX..XXXXXXX 100644
164
--- a/tcg/sparc/tcg-target.c.inc
165
+++ b/tcg/sparc/tcg-target.c.inc
166
@@ -XXX,XX +XXX,XX @@ static bool patch_reloc(tcg_insn_unit *src_rw, int type,
167
}
168
169
/* test if a constant matches the constraint */
170
-static inline int tcg_target_const_match(tcg_target_long val, TCGType type,
171
- const TCGArgConstraint *arg_ct)
172
+static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
173
{
174
- int ct = arg_ct->ct;
175
-
176
if (ct & TCG_CT_CONST) {
177
return 1;
178
}
179
diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
180
index XXXXXXX..XXXXXXX 100644
181
--- a/tcg/tci/tcg-target.c.inc
182
+++ b/tcg/tci/tcg-target.c.inc
183
@@ -XXX,XX +XXX,XX @@ static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
184
}
185
186
/* Test if a constant matches the constraint. */
187
-static int tcg_target_const_match(tcg_target_long val, TCGType type,
188
- const TCGArgConstraint *arg_ct)
189
+static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
190
{
191
- /* No need to return 0 or 1, 0 or != 0 is good enough. */
192
- return arg_ct->ct & TCG_CT_CONST;
193
+ return ct & TCG_CT_CONST;
194
}
195
196
static void tcg_target_init(TCGContext *s)
197
--
72
--
198
2.25.1
73
2.34.1
199
200
diff view generated by jsdifflib
New patch
1
Simplify the implementation of get_page_addr_code_hostp
2
by reusing the existing probe_access infrastructure.
1
3
4
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
5
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
accel/tcg/cputlb.c | 76 ++++++++++++++++------------------------------
9
1 file changed, 26 insertions(+), 50 deletions(-)
10
11
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/accel/tcg/cputlb.c
14
+++ b/accel/tcg/cputlb.c
15
@@ -XXX,XX +XXX,XX @@ static bool victim_tlb_hit(CPUArchState *env, size_t mmu_idx, size_t index,
16
victim_tlb_hit(env, mmu_idx, index, offsetof(CPUTLBEntry, TY), \
17
(ADDR) & TARGET_PAGE_MASK)
18
19
-/*
20
- * Return a ram_addr_t for the virtual address for execution.
21
- *
22
- * Return -1 if we can't translate and execute from an entire page
23
- * of RAM. This will force us to execute by loading and translating
24
- * one insn at a time, without caching.
25
- *
26
- * NOTE: This function will trigger an exception if the page is
27
- * not executable.
28
- */
29
-tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
30
- void **hostp)
31
-{
32
- uintptr_t mmu_idx = cpu_mmu_index(env, true);
33
- uintptr_t index = tlb_index(env, mmu_idx, addr);
34
- CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
35
- void *p;
36
-
37
- if (unlikely(!tlb_hit(entry->addr_code, addr))) {
38
- if (!VICTIM_TLB_HIT(addr_code, addr)) {
39
- tlb_fill(env_cpu(env), addr, 0, MMU_INST_FETCH, mmu_idx, 0);
40
- index = tlb_index(env, mmu_idx, addr);
41
- entry = tlb_entry(env, mmu_idx, addr);
42
-
43
- if (unlikely(entry->addr_code & TLB_INVALID_MASK)) {
44
- /*
45
- * The MMU protection covers a smaller range than a target
46
- * page, so we must redo the MMU check for every insn.
47
- */
48
- return -1;
49
- }
50
- }
51
- assert(tlb_hit(entry->addr_code, addr));
52
- }
53
-
54
- if (unlikely(entry->addr_code & TLB_MMIO)) {
55
- /* The region is not backed by RAM. */
56
- if (hostp) {
57
- *hostp = NULL;
58
- }
59
- return -1;
60
- }
61
-
62
- p = (void *)((uintptr_t)addr + entry->addend);
63
- if (hostp) {
64
- *hostp = p;
65
- }
66
- return qemu_ram_addr_from_host_nofail(p);
67
-}
68
-
69
static void notdirty_write(CPUState *cpu, vaddr mem_vaddr, unsigned size,
70
CPUIOTLBEntry *iotlbentry, uintptr_t retaddr)
71
{
72
@@ -XXX,XX +XXX,XX @@ void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
73
return flags ? NULL : host;
74
}
75
76
+/*
77
+ * Return a ram_addr_t for the virtual address for execution.
78
+ *
79
+ * Return -1 if we can't translate and execute from an entire page
80
+ * of RAM. This will force us to execute by loading and translating
81
+ * one insn at a time, without caching.
82
+ *
83
+ * NOTE: This function will trigger an exception if the page is
84
+ * not executable.
85
+ */
86
+tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
87
+ void **hostp)
88
+{
89
+ void *p;
90
+
91
+ (void)probe_access_internal(env, addr, 1, MMU_INST_FETCH,
92
+ cpu_mmu_index(env, true), false, &p, 0);
93
+ if (p == NULL) {
94
+ return -1;
95
+ }
96
+ if (hostp) {
97
+ *hostp = p;
98
+ }
99
+ return qemu_ram_addr_from_host_nofail(p);
100
+}
101
+
102
#ifdef CONFIG_PLUGIN
103
/*
104
* Perform a TLB lookup and populate the qemu_plugin_hwaddr structure.
105
--
106
2.34.1
diff view generated by jsdifflib
New patch
1
It was non-obvious to me why we can raise an exception in
2
the middle of a comparison function, but it works.
3
While nearby, use TARGET_PAGE_ALIGN instead of open-coding.
1
4
5
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
accel/tcg/cpu-exec.c | 11 ++++++++++-
9
1 file changed, 10 insertions(+), 1 deletion(-)
10
11
diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/accel/tcg/cpu-exec.c
14
+++ b/accel/tcg/cpu-exec.c
15
@@ -XXX,XX +XXX,XX @@ static bool tb_lookup_cmp(const void *p, const void *d)
16
tb_page_addr_t phys_page2;
17
target_ulong virt_page2;
18
19
- virt_page2 = (desc->pc & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
20
+ /*
21
+ * We know that the first page matched, and an otherwise valid TB
22
+ * encountered an incomplete instruction at the end of that page,
23
+ * therefore we know that generating a new TB from the current PC
24
+ * must also require reading from the next page -- even if the
25
+ * second pages do not match, and therefore the resulting insn
26
+ * is different for the new TB. Therefore any exception raised
27
+ * here by the faulting lookup is not premature.
28
+ */
29
+ virt_page2 = TARGET_PAGE_ALIGN(desc->pc);
30
phys_page2 = get_page_addr_code(desc->env, virt_page2);
31
if (tb->page_addr[1] == phys_page2) {
32
return true;
33
--
34
2.34.1
diff view generated by jsdifflib
1
The three vector shift by vector operations are all implemented via
1
The only user can easily use translator_lduw and
2
expansion. Therefore do not actually set TCG_TARGET_HAS_shv_vec,
2
adjust the type to signed during the return.
3
as none of shlv_vec, shrv_vec, sarv_vec may actually appear in the
4
instruction stream, and therefore also do not appear in tcg_target_op_def.
5
3
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
5
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
6
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
---
8
---
9
tcg/arm/tcg-target.opc.h | 3 ++
9
include/exec/translator.h | 1 -
10
tcg/arm/tcg-target.c.inc | 61 +++++++++++++++++++++++++++++++++++++++-
10
target/i386/tcg/translate.c | 2 +-
11
2 files changed, 63 insertions(+), 1 deletion(-)
11
2 files changed, 1 insertion(+), 2 deletions(-)
12
12
13
diff --git a/tcg/arm/tcg-target.opc.h b/tcg/arm/tcg-target.opc.h
13
diff --git a/include/exec/translator.h b/include/exec/translator.h
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/tcg/arm/tcg-target.opc.h
15
--- a/include/exec/translator.h
16
+++ b/tcg/arm/tcg-target.opc.h
16
+++ b/include/exec/translator.h
17
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest);
18
* emitted by tcg_expand_vec_op. For those familiar with GCC internals,
18
19
* consider these to be UNSPEC with names.
19
#define FOR_EACH_TRANSLATOR_LD(F) \
20
*/
20
F(translator_ldub, uint8_t, cpu_ldub_code, /* no swap */) \
21
+
21
- F(translator_ldsw, int16_t, cpu_ldsw_code, bswap16) \
22
+DEF(arm_sshl_vec, 1, 2, 0, IMPLVEC)
22
F(translator_lduw, uint16_t, cpu_lduw_code, bswap16) \
23
+DEF(arm_ushl_vec, 1, 2, 0, IMPLVEC)
23
F(translator_ldl, uint32_t, cpu_ldl_code, bswap32) \
24
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
24
F(translator_ldq, uint64_t, cpu_ldq_code, bswap64)
25
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
25
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
26
--- a/tcg/arm/tcg-target.c.inc
27
--- a/target/i386/tcg/translate.c
27
+++ b/tcg/arm/tcg-target.c.inc
28
+++ b/target/i386/tcg/translate.c
28
@@ -XXX,XX +XXX,XX @@ typedef enum {
29
@@ -XXX,XX +XXX,XX @@ static inline uint8_t x86_ldub_code(CPUX86State *env, DisasContext *s)
29
INSN_VSHLI = 0xf2800510, /* VSHL (immediate) */
30
30
INSN_VSARI = 0xf2800010, /* VSHR.S */
31
static inline int16_t x86_ldsw_code(CPUX86State *env, DisasContext *s)
31
INSN_VSHRI = 0xf3800010, /* VSHR.U */
32
+ INSN_VSHL_S = 0xf2000400, /* VSHL.S (register) */
33
+ INSN_VSHL_U = 0xf3000400, /* VSHL.U (register) */
34
35
INSN_VBSL = 0xf3100110,
36
INSN_VBIT = 0xf3200110,
37
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
38
case INDEX_op_usadd_vec:
39
case INDEX_op_ussub_vec:
40
case INDEX_op_xor_vec:
41
+ case INDEX_op_arm_sshl_vec:
42
+ case INDEX_op_arm_ushl_vec:
43
return C_O1_I2(w, w, w);
44
case INDEX_op_or_vec:
45
case INDEX_op_andc_vec:
46
@@ -XXX,XX +XXX,XX @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
47
case INDEX_op_xor_vec:
48
tcg_out_vreg3(s, INSN_VEOR, q, 0, a0, a1, a2);
49
return;
50
+ case INDEX_op_arm_sshl_vec:
51
+ /*
52
+ * Note that Vm is the data and Vn is the shift count,
53
+ * therefore the arguments appear reversed.
54
+ */
55
+ tcg_out_vreg3(s, INSN_VSHL_S, q, vece, a0, a2, a1);
56
+ return;
57
+ case INDEX_op_arm_ushl_vec:
58
+ /* See above. */
59
+ tcg_out_vreg3(s, INSN_VSHL_U, q, vece, a0, a2, a1);
60
+ return;
61
case INDEX_op_shli_vec:
62
tcg_out_vshifti(s, INSN_VSHLI, q, a0, a1, a2 + (8 << vece));
63
return;
64
@@ -XXX,XX +XXX,XX @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
65
case INDEX_op_umax_vec:
66
case INDEX_op_umin_vec:
67
return vece < MO_64;
68
+ case INDEX_op_shlv_vec:
69
+ case INDEX_op_shrv_vec:
70
+ case INDEX_op_sarv_vec:
71
+ return -1;
72
default:
73
return 0;
74
}
75
@@ -XXX,XX +XXX,XX @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
76
void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece,
77
TCGArg a0, ...)
78
{
32
{
79
- g_assert_not_reached();
33
- return translator_ldsw(env, &s->base, advance_pc(env, s, 2));
80
+ va_list va;
34
+ return translator_lduw(env, &s->base, advance_pc(env, s, 2));
81
+ TCGv_vec v0, v1, v2, t1;
82
+ TCGArg a2;
83
+
84
+ va_start(va, a0);
85
+ v0 = temp_tcgv_vec(arg_temp(a0));
86
+ v1 = temp_tcgv_vec(arg_temp(va_arg(va, TCGArg)));
87
+ a2 = va_arg(va, TCGArg);
88
+ va_end(va);
89
+
90
+ switch (opc) {
91
+ case INDEX_op_shlv_vec:
92
+ /*
93
+ * Merely propagate shlv_vec to arm_ushl_vec.
94
+ * In this way we don't set TCG_TARGET_HAS_shv_vec
95
+ * because everything is done via expansion.
96
+ */
97
+ v2 = temp_tcgv_vec(arg_temp(a2));
98
+ vec_gen_3(INDEX_op_arm_ushl_vec, type, vece, tcgv_vec_arg(v0),
99
+ tcgv_vec_arg(v1), tcgv_vec_arg(v2));
100
+ break;
101
+
102
+ case INDEX_op_shrv_vec:
103
+ case INDEX_op_sarv_vec:
104
+ /* Right shifts are negative left shifts for NEON. */
105
+ v2 = temp_tcgv_vec(arg_temp(a2));
106
+ t1 = tcg_temp_new_vec(type);
107
+ tcg_gen_neg_vec(vece, t1, v2);
108
+ if (opc == INDEX_op_shrv_vec) {
109
+ opc = INDEX_op_arm_ushl_vec;
110
+ } else {
111
+ opc = INDEX_op_arm_sshl_vec;
112
+ }
113
+ vec_gen_3(opc, type, vece, tcgv_vec_arg(v0),
114
+ tcgv_vec_arg(v1), tcgv_vec_arg(t1));
115
+ tcg_temp_free_vec(t1);
116
+ break;
117
+
118
+ default:
119
+ g_assert_not_reached();
120
+ }
121
}
35
}
122
36
123
static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
37
static inline uint16_t x86_lduw_code(CPUX86State *env, DisasContext *s)
124
--
38
--
125
2.25.1
39
2.34.1
126
127
diff view generated by jsdifflib
1
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
1
Pass these along to translator_loop -- pc may be used instead
2
of tb->pc, and host_pc is currently unused. Adjust all targets
3
at one time.
4
5
Acked-by: Alistair Francis <alistair.francis@wdc.com>
6
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
7
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
9
---
4
tcg/arm/tcg-target.h | 2 +-
10
include/exec/exec-all.h | 1 -
5
tcg/arm/tcg-target.c.inc | 6 ++++++
11
include/exec/translator.h | 24 ++++++++++++++++++++----
6
2 files changed, 7 insertions(+), 1 deletion(-)
12
accel/tcg/translate-all.c | 6 ++++--
13
accel/tcg/translator.c | 9 +++++----
14
target/alpha/translate.c | 5 +++--
15
target/arm/translate.c | 5 +++--
16
target/avr/translate.c | 5 +++--
17
target/cris/translate.c | 5 +++--
18
target/hexagon/translate.c | 6 ++++--
19
target/hppa/translate.c | 5 +++--
20
target/i386/tcg/translate.c | 5 +++--
21
target/loongarch/translate.c | 6 ++++--
22
target/m68k/translate.c | 5 +++--
23
target/microblaze/translate.c | 5 +++--
24
target/mips/tcg/translate.c | 5 +++--
25
target/nios2/translate.c | 5 +++--
26
target/openrisc/translate.c | 6 ++++--
27
target/ppc/translate.c | 5 +++--
28
target/riscv/translate.c | 5 +++--
29
target/rx/translate.c | 5 +++--
30
target/s390x/tcg/translate.c | 5 +++--
31
target/sh4/translate.c | 5 +++--
32
target/sparc/translate.c | 5 +++--
33
target/tricore/translate.c | 6 ++++--
34
target/xtensa/translate.c | 6 ++++--
35
25 files changed, 97 insertions(+), 53 deletions(-)
7
36
8
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
37
diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
9
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX 100644
10
--- a/tcg/arm/tcg-target.h
39
--- a/include/exec/exec-all.h
11
+++ b/tcg/arm/tcg-target.h
40
+++ b/include/exec/exec-all.h
12
@@ -XXX,XX +XXX,XX @@ extern bool use_neon_instructions;
41
@@ -XXX,XX +XXX,XX @@ typedef ram_addr_t tb_page_addr_t;
13
#define TCG_TARGET_HAS_shi_vec 1
42
#define TB_PAGE_ADDR_FMT RAM_ADDR_FMT
14
#define TCG_TARGET_HAS_shs_vec 0
43
#endif
15
#define TCG_TARGET_HAS_shv_vec 0
44
16
-#define TCG_TARGET_HAS_mul_vec 0
45
-void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns);
17
+#define TCG_TARGET_HAS_mul_vec 1
46
void restore_state_to_opc(CPUArchState *env, TranslationBlock *tb,
18
#define TCG_TARGET_HAS_sat_vec 0
47
target_ulong *data);
19
#define TCG_TARGET_HAS_minmax_vec 0
48
20
#define TCG_TARGET_HAS_bitsel_vec 0
49
diff --git a/include/exec/translator.h b/include/exec/translator.h
21
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
50
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
51
--- a/include/exec/translator.h
23
--- a/tcg/arm/tcg-target.c.inc
52
+++ b/include/exec/translator.h
24
+++ b/tcg/arm/tcg-target.c.inc
53
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ typedef enum {
54
#include "exec/translate-all.h"
26
INSN_VORN = 0xf2300110,
55
#include "tcg/tcg.h"
27
INSN_VORR = 0xf2200110,
56
28
INSN_VSUB = 0xf3000800,
57
+/**
29
+ INSN_VMUL = 0xf2000910,
58
+ * gen_intermediate_code
30
59
+ * @cpu: cpu context
31
INSN_VABS = 0xf3b10300,
60
+ * @tb: translation block
32
INSN_VMVN = 0xf3b00580,
61
+ * @max_insns: max number of instructions to translate
33
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
62
+ * @pc: guest virtual program counter address
34
return C_O1_I1(w, w);
63
+ * @host_pc: host physical program counter address
35
case INDEX_op_dup2_vec:
64
+ *
36
case INDEX_op_add_vec:
65
+ * This function must be provided by the target, which should create
37
+ case INDEX_op_mul_vec:
66
+ * the target-specific DisasContext, and then invoke translator_loop.
38
case INDEX_op_sub_vec:
67
+ */
39
case INDEX_op_xor_vec:
68
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns,
40
return C_O1_I2(w, w, w);
69
+ target_ulong pc, void *host_pc);
41
@@ -XXX,XX +XXX,XX @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
70
42
case INDEX_op_add_vec:
71
/**
43
tcg_out_vreg3(s, INSN_VADD, q, vece, a0, a1, a2);
72
* DisasJumpType:
44
return;
73
@@ -XXX,XX +XXX,XX @@ typedef struct TranslatorOps {
45
+ case INDEX_op_mul_vec:
74
46
+ tcg_out_vreg3(s, INSN_VMUL, q, vece, a0, a1, a2);
75
/**
47
+ return;
76
* translator_loop:
48
case INDEX_op_sub_vec:
77
- * @ops: Target-specific operations.
49
tcg_out_vreg3(s, INSN_VSUB, q, vece, a0, a1, a2);
78
- * @db: Disassembly context.
50
return;
79
* @cpu: Target vCPU.
51
@@ -XXX,XX +XXX,XX @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
80
* @tb: Translation block.
52
return 1;
81
* @max_insns: Maximum number of insns to translate.
53
case INDEX_op_abs_vec:
82
+ * @pc: guest virtual program counter address
54
case INDEX_op_cmp_vec:
83
+ * @host_pc: host physical program counter address
55
+ case INDEX_op_mul_vec:
84
+ * @ops: Target-specific operations.
56
case INDEX_op_neg_vec:
85
+ * @db: Disassembly context.
57
return vece < MO_64;
86
*
58
default:
87
* Generic translator loop.
88
*
89
@@ -XXX,XX +XXX,XX @@ typedef struct TranslatorOps {
90
* - When single-stepping is enabled (system-wide or on the current vCPU).
91
* - When too many instructions have been translated.
92
*/
93
-void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
94
- CPUState *cpu, TranslationBlock *tb, int max_insns);
95
+void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns,
96
+ target_ulong pc, void *host_pc,
97
+ const TranslatorOps *ops, DisasContextBase *db);
98
99
void translator_loop_temp_check(DisasContextBase *db);
100
101
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
102
index XXXXXXX..XXXXXXX 100644
103
--- a/accel/tcg/translate-all.c
104
+++ b/accel/tcg/translate-all.c
105
@@ -XXX,XX +XXX,XX @@
106
107
#include "exec/cputlb.h"
108
#include "exec/translate-all.h"
109
+#include "exec/translator.h"
110
#include "qemu/bitmap.h"
111
#include "qemu/qemu-print.h"
112
#include "qemu/timer.h"
113
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
114
TCGProfile *prof = &tcg_ctx->prof;
115
int64_t ti;
116
#endif
117
+ void *host_pc;
118
119
assert_memory_lock();
120
qemu_thread_jit_write();
121
122
- phys_pc = get_page_addr_code(env, pc);
123
+ phys_pc = get_page_addr_code_hostp(env, pc, &host_pc);
124
125
if (phys_pc == -1) {
126
/* Generate a one-shot TB with 1 insn in it */
127
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
128
tcg_func_start(tcg_ctx);
129
130
tcg_ctx->cpu = env_cpu(env);
131
- gen_intermediate_code(cpu, tb, max_insns);
132
+ gen_intermediate_code(cpu, tb, max_insns, pc, host_pc);
133
assert(tb->size != 0);
134
tcg_ctx->cpu = NULL;
135
max_insns = tb->icount;
136
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
137
index XXXXXXX..XXXXXXX 100644
138
--- a/accel/tcg/translator.c
139
+++ b/accel/tcg/translator.c
140
@@ -XXX,XX +XXX,XX @@ static inline void translator_page_protect(DisasContextBase *dcbase,
141
#endif
142
}
143
144
-void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
145
- CPUState *cpu, TranslationBlock *tb, int max_insns)
146
+void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns,
147
+ target_ulong pc, void *host_pc,
148
+ const TranslatorOps *ops, DisasContextBase *db)
149
{
150
uint32_t cflags = tb_cflags(tb);
151
bool plugin_enabled;
152
153
/* Initialize DisasContext */
154
db->tb = tb;
155
- db->pc_first = tb->pc;
156
- db->pc_next = db->pc_first;
157
+ db->pc_first = pc;
158
+ db->pc_next = pc;
159
db->is_jmp = DISAS_NEXT;
160
db->num_insns = 0;
161
db->max_insns = max_insns;
162
diff --git a/target/alpha/translate.c b/target/alpha/translate.c
163
index XXXXXXX..XXXXXXX 100644
164
--- a/target/alpha/translate.c
165
+++ b/target/alpha/translate.c
166
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps alpha_tr_ops = {
167
.disas_log = alpha_tr_disas_log,
168
};
169
170
-void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
171
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns,
172
+ target_ulong pc, void *host_pc)
173
{
174
DisasContext dc;
175
- translator_loop(&alpha_tr_ops, &dc.base, cpu, tb, max_insns);
176
+ translator_loop(cpu, tb, max_insns, pc, host_pc, &alpha_tr_ops, &dc.base);
177
}
178
179
void restore_state_to_opc(CPUAlphaState *env, TranslationBlock *tb,
180
diff --git a/target/arm/translate.c b/target/arm/translate.c
181
index XXXXXXX..XXXXXXX 100644
182
--- a/target/arm/translate.c
183
+++ b/target/arm/translate.c
184
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps thumb_translator_ops = {
185
};
186
187
/* generate intermediate code for basic block 'tb'. */
188
-void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
189
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns,
190
+ target_ulong pc, void *host_pc)
191
{
192
DisasContext dc = { };
193
const TranslatorOps *ops = &arm_translator_ops;
194
@@ -XXX,XX +XXX,XX @@ void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
195
}
196
#endif
197
198
- translator_loop(ops, &dc.base, cpu, tb, max_insns);
199
+ translator_loop(cpu, tb, max_insns, pc, host_pc, ops, &dc.base);
200
}
201
202
void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb,
203
diff --git a/target/avr/translate.c b/target/avr/translate.c
204
index XXXXXXX..XXXXXXX 100644
205
--- a/target/avr/translate.c
206
+++ b/target/avr/translate.c
207
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps avr_tr_ops = {
208
.disas_log = avr_tr_disas_log,
209
};
210
211
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
212
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
213
+ target_ulong pc, void *host_pc)
214
{
215
DisasContext dc = { };
216
- translator_loop(&avr_tr_ops, &dc.base, cs, tb, max_insns);
217
+ translator_loop(cs, tb, max_insns, pc, host_pc, &avr_tr_ops, &dc.base);
218
}
219
220
void restore_state_to_opc(CPUAVRState *env, TranslationBlock *tb,
221
diff --git a/target/cris/translate.c b/target/cris/translate.c
222
index XXXXXXX..XXXXXXX 100644
223
--- a/target/cris/translate.c
224
+++ b/target/cris/translate.c
225
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps cris_tr_ops = {
226
.disas_log = cris_tr_disas_log,
227
};
228
229
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
230
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
231
+ target_ulong pc, void *host_pc)
232
{
233
DisasContext dc;
234
- translator_loop(&cris_tr_ops, &dc.base, cs, tb, max_insns);
235
+ translator_loop(cs, tb, max_insns, pc, host_pc, &cris_tr_ops, &dc.base);
236
}
237
238
void cris_cpu_dump_state(CPUState *cs, FILE *f, int flags)
239
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
240
index XXXXXXX..XXXXXXX 100644
241
--- a/target/hexagon/translate.c
242
+++ b/target/hexagon/translate.c
243
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps hexagon_tr_ops = {
244
.disas_log = hexagon_tr_disas_log,
245
};
246
247
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
248
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
249
+ target_ulong pc, void *host_pc)
250
{
251
DisasContext ctx;
252
253
- translator_loop(&hexagon_tr_ops, &ctx.base, cs, tb, max_insns);
254
+ translator_loop(cs, tb, max_insns, pc, host_pc,
255
+ &hexagon_tr_ops, &ctx.base);
256
}
257
258
#define NAME_LEN 64
259
diff --git a/target/hppa/translate.c b/target/hppa/translate.c
260
index XXXXXXX..XXXXXXX 100644
261
--- a/target/hppa/translate.c
262
+++ b/target/hppa/translate.c
263
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps hppa_tr_ops = {
264
.disas_log = hppa_tr_disas_log,
265
};
266
267
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
268
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
269
+ target_ulong pc, void *host_pc)
270
{
271
DisasContext ctx;
272
- translator_loop(&hppa_tr_ops, &ctx.base, cs, tb, max_insns);
273
+ translator_loop(cs, tb, max_insns, pc, host_pc, &hppa_tr_ops, &ctx.base);
274
}
275
276
void restore_state_to_opc(CPUHPPAState *env, TranslationBlock *tb,
277
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
278
index XXXXXXX..XXXXXXX 100644
279
--- a/target/i386/tcg/translate.c
280
+++ b/target/i386/tcg/translate.c
281
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps i386_tr_ops = {
282
};
283
284
/* generate intermediate code for basic block 'tb'. */
285
-void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
286
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns,
287
+ target_ulong pc, void *host_pc)
288
{
289
DisasContext dc;
290
291
- translator_loop(&i386_tr_ops, &dc.base, cpu, tb, max_insns);
292
+ translator_loop(cpu, tb, max_insns, pc, host_pc, &i386_tr_ops, &dc.base);
293
}
294
295
void restore_state_to_opc(CPUX86State *env, TranslationBlock *tb,
296
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
297
index XXXXXXX..XXXXXXX 100644
298
--- a/target/loongarch/translate.c
299
+++ b/target/loongarch/translate.c
300
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps loongarch_tr_ops = {
301
.disas_log = loongarch_tr_disas_log,
302
};
303
304
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
305
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
306
+ target_ulong pc, void *host_pc)
307
{
308
DisasContext ctx;
309
310
- translator_loop(&loongarch_tr_ops, &ctx.base, cs, tb, max_insns);
311
+ translator_loop(cs, tb, max_insns, pc, host_pc,
312
+ &loongarch_tr_ops, &ctx.base);
313
}
314
315
void loongarch_translate_init(void)
316
diff --git a/target/m68k/translate.c b/target/m68k/translate.c
317
index XXXXXXX..XXXXXXX 100644
318
--- a/target/m68k/translate.c
319
+++ b/target/m68k/translate.c
320
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps m68k_tr_ops = {
321
.disas_log = m68k_tr_disas_log,
322
};
323
324
-void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
325
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns,
326
+ target_ulong pc, void *host_pc)
327
{
328
DisasContext dc;
329
- translator_loop(&m68k_tr_ops, &dc.base, cpu, tb, max_insns);
330
+ translator_loop(cpu, tb, max_insns, pc, host_pc, &m68k_tr_ops, &dc.base);
331
}
332
333
static double floatx80_to_double(CPUM68KState *env, uint16_t high, uint64_t low)
334
diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c
335
index XXXXXXX..XXXXXXX 100644
336
--- a/target/microblaze/translate.c
337
+++ b/target/microblaze/translate.c
338
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps mb_tr_ops = {
339
.disas_log = mb_tr_disas_log,
340
};
341
342
-void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
343
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns,
344
+ target_ulong pc, void *host_pc)
345
{
346
DisasContext dc;
347
- translator_loop(&mb_tr_ops, &dc.base, cpu, tb, max_insns);
348
+ translator_loop(cpu, tb, max_insns, pc, host_pc, &mb_tr_ops, &dc.base);
349
}
350
351
void mb_cpu_dump_state(CPUState *cs, FILE *f, int flags)
352
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
353
index XXXXXXX..XXXXXXX 100644
354
--- a/target/mips/tcg/translate.c
355
+++ b/target/mips/tcg/translate.c
356
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps mips_tr_ops = {
357
.disas_log = mips_tr_disas_log,
358
};
359
360
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
361
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
362
+ target_ulong pc, void *host_pc)
363
{
364
DisasContext ctx;
365
366
- translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
367
+ translator_loop(cs, tb, max_insns, pc, host_pc, &mips_tr_ops, &ctx.base);
368
}
369
370
void mips_tcg_init(void)
371
diff --git a/target/nios2/translate.c b/target/nios2/translate.c
372
index XXXXXXX..XXXXXXX 100644
373
--- a/target/nios2/translate.c
374
+++ b/target/nios2/translate.c
375
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps nios2_tr_ops = {
376
.disas_log = nios2_tr_disas_log,
377
};
378
379
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
380
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
381
+ target_ulong pc, void *host_pc)
382
{
383
DisasContext dc;
384
- translator_loop(&nios2_tr_ops, &dc.base, cs, tb, max_insns);
385
+ translator_loop(cs, tb, max_insns, pc, host_pc, &nios2_tr_ops, &dc.base);
386
}
387
388
void nios2_cpu_dump_state(CPUState *cs, FILE *f, int flags)
389
diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c
390
index XXXXXXX..XXXXXXX 100644
391
--- a/target/openrisc/translate.c
392
+++ b/target/openrisc/translate.c
393
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps openrisc_tr_ops = {
394
.disas_log = openrisc_tr_disas_log,
395
};
396
397
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
398
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
399
+ target_ulong pc, void *host_pc)
400
{
401
DisasContext ctx;
402
403
- translator_loop(&openrisc_tr_ops, &ctx.base, cs, tb, max_insns);
404
+ translator_loop(cs, tb, max_insns, pc, host_pc,
405
+ &openrisc_tr_ops, &ctx.base);
406
}
407
408
void openrisc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
409
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
410
index XXXXXXX..XXXXXXX 100644
411
--- a/target/ppc/translate.c
412
+++ b/target/ppc/translate.c
413
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps ppc_tr_ops = {
414
.disas_log = ppc_tr_disas_log,
415
};
416
417
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
418
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
419
+ target_ulong pc, void *host_pc)
420
{
421
DisasContext ctx;
422
423
- translator_loop(&ppc_tr_ops, &ctx.base, cs, tb, max_insns);
424
+ translator_loop(cs, tb, max_insns, pc, host_pc, &ppc_tr_ops, &ctx.base);
425
}
426
427
void restore_state_to_opc(CPUPPCState *env, TranslationBlock *tb,
428
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
429
index XXXXXXX..XXXXXXX 100644
430
--- a/target/riscv/translate.c
431
+++ b/target/riscv/translate.c
432
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps riscv_tr_ops = {
433
.disas_log = riscv_tr_disas_log,
434
};
435
436
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
437
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
438
+ target_ulong pc, void *host_pc)
439
{
440
DisasContext ctx;
441
442
- translator_loop(&riscv_tr_ops, &ctx.base, cs, tb, max_insns);
443
+ translator_loop(cs, tb, max_insns, pc, host_pc, &riscv_tr_ops, &ctx.base);
444
}
445
446
void riscv_translate_init(void)
447
diff --git a/target/rx/translate.c b/target/rx/translate.c
448
index XXXXXXX..XXXXXXX 100644
449
--- a/target/rx/translate.c
450
+++ b/target/rx/translate.c
451
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps rx_tr_ops = {
452
.disas_log = rx_tr_disas_log,
453
};
454
455
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
456
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
457
+ target_ulong pc, void *host_pc)
458
{
459
DisasContext dc;
460
461
- translator_loop(&rx_tr_ops, &dc.base, cs, tb, max_insns);
462
+ translator_loop(cs, tb, max_insns, pc, host_pc, &rx_tr_ops, &dc.base);
463
}
464
465
void restore_state_to_opc(CPURXState *env, TranslationBlock *tb,
466
diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c
467
index XXXXXXX..XXXXXXX 100644
468
--- a/target/s390x/tcg/translate.c
469
+++ b/target/s390x/tcg/translate.c
470
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps s390x_tr_ops = {
471
.disas_log = s390x_tr_disas_log,
472
};
473
474
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
475
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
476
+ target_ulong pc, void *host_pc)
477
{
478
DisasContext dc;
479
480
- translator_loop(&s390x_tr_ops, &dc.base, cs, tb, max_insns);
481
+ translator_loop(cs, tb, max_insns, pc, host_pc, &s390x_tr_ops, &dc.base);
482
}
483
484
void restore_state_to_opc(CPUS390XState *env, TranslationBlock *tb,
485
diff --git a/target/sh4/translate.c b/target/sh4/translate.c
486
index XXXXXXX..XXXXXXX 100644
487
--- a/target/sh4/translate.c
488
+++ b/target/sh4/translate.c
489
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps sh4_tr_ops = {
490
.disas_log = sh4_tr_disas_log,
491
};
492
493
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
494
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
495
+ target_ulong pc, void *host_pc)
496
{
497
DisasContext ctx;
498
499
- translator_loop(&sh4_tr_ops, &ctx.base, cs, tb, max_insns);
500
+ translator_loop(cs, tb, max_insns, pc, host_pc, &sh4_tr_ops, &ctx.base);
501
}
502
503
void restore_state_to_opc(CPUSH4State *env, TranslationBlock *tb,
504
diff --git a/target/sparc/translate.c b/target/sparc/translate.c
505
index XXXXXXX..XXXXXXX 100644
506
--- a/target/sparc/translate.c
507
+++ b/target/sparc/translate.c
508
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps sparc_tr_ops = {
509
.disas_log = sparc_tr_disas_log,
510
};
511
512
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
513
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
514
+ target_ulong pc, void *host_pc)
515
{
516
DisasContext dc = {};
517
518
- translator_loop(&sparc_tr_ops, &dc.base, cs, tb, max_insns);
519
+ translator_loop(cs, tb, max_insns, pc, host_pc, &sparc_tr_ops, &dc.base);
520
}
521
522
void sparc_tcg_init(void)
523
diff --git a/target/tricore/translate.c b/target/tricore/translate.c
524
index XXXXXXX..XXXXXXX 100644
525
--- a/target/tricore/translate.c
526
+++ b/target/tricore/translate.c
527
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps tricore_tr_ops = {
528
};
529
530
531
-void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
532
+void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns,
533
+ target_ulong pc, void *host_pc)
534
{
535
DisasContext ctx;
536
- translator_loop(&tricore_tr_ops, &ctx.base, cs, tb, max_insns);
537
+ translator_loop(cs, tb, max_insns, pc, host_pc,
538
+ &tricore_tr_ops, &ctx.base);
539
}
540
541
void
542
diff --git a/target/xtensa/translate.c b/target/xtensa/translate.c
543
index XXXXXXX..XXXXXXX 100644
544
--- a/target/xtensa/translate.c
545
+++ b/target/xtensa/translate.c
546
@@ -XXX,XX +XXX,XX @@ static const TranslatorOps xtensa_translator_ops = {
547
.disas_log = xtensa_tr_disas_log,
548
};
549
550
-void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
551
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns,
552
+ target_ulong pc, void *host_pc)
553
{
554
DisasContext dc = {};
555
- translator_loop(&xtensa_translator_ops, &dc.base, cpu, tb, max_insns);
556
+ translator_loop(cpu, tb, max_insns, pc, host_pc,
557
+ &xtensa_translator_ops, &dc.base);
558
}
559
560
void xtensa_cpu_dump_state(CPUState *cs, FILE *f, int flags)
59
--
561
--
60
2.25.1
562
2.34.1
61
62
diff view generated by jsdifflib
1
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
1
Cache the translation from guest to host address, so we may
2
use direct loads when we hit on the primary translation page.
3
4
Look up the second translation page only once, during translation.
5
This obviates another lookup of the second page within tb_gen_code
6
after translation.
7
8
Fixes a bug in that plugin_insn_append should be passed the bytes
9
in the original memory order, not bswapped by pieces.
10
11
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
12
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
2
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
3
---
14
---
4
tcg/arm/tcg-target.c.inc | 70 ++++++++++++++++++++++++++++++++++++----
15
include/exec/translator.h | 63 +++++++++++--------
5
1 file changed, 64 insertions(+), 6 deletions(-)
16
accel/tcg/translate-all.c | 23 +++----
17
accel/tcg/translator.c | 126 +++++++++++++++++++++++++++++---------
18
3 files changed, 141 insertions(+), 71 deletions(-)
6
19
7
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
20
diff --git a/include/exec/translator.h b/include/exec/translator.h
8
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
9
--- a/tcg/arm/tcg-target.c.inc
22
--- a/include/exec/translator.h
10
+++ b/tcg/arm/tcg-target.c.inc
23
+++ b/include/exec/translator.h
11
@@ -XXX,XX +XXX,XX @@ typedef enum {
24
@@ -XXX,XX +XXX,XX @@ typedef enum DisasJumpType {
12
INSN_NOP_v6k = 0xe320f000,
25
* Architecture-agnostic disassembly context.
13
/* Otherwise the assembler uses mov r0,r0 */
26
*/
14
INSN_NOP_v4 = (COND_AL << 28) | ARITH_MOV,
27
typedef struct DisasContextBase {
15
+
28
- const TranslationBlock *tb;
16
+ INSN_VLD1 = 0xf4200000, /* VLD1 (multiple single elements) */
29
+ TranslationBlock *tb;
17
+ INSN_VST1 = 0xf4000000, /* VST1 (multiple single elements) */
30
target_ulong pc_first;
18
} ARMInsn;
31
target_ulong pc_next;
19
32
DisasJumpType is_jmp;
20
#define INSN_NOP (use_armv7_instructions ? INSN_NOP_v6k : INSN_NOP_v4)
33
int num_insns;
21
@@ -XXX,XX +XXX,XX @@ static TCGCond tcg_out_cmp2(TCGContext *s, const TCGArg *args,
34
int max_insns;
22
}
35
bool singlestep_enabled;
36
-#ifdef CONFIG_USER_ONLY
37
- /*
38
- * Guest address of the last byte of the last protected page.
39
- *
40
- * Pages containing the translated instructions are made non-writable in
41
- * order to achieve consistency in case another thread is modifying the
42
- * code while translate_insn() fetches the instruction bytes piecemeal.
43
- * Such writer threads are blocked on mmap_lock() in page_unprotect().
44
- */
45
- target_ulong page_protect_end;
46
-#endif
47
+ void *host_addr[2];
48
} DisasContextBase;
49
50
/**
51
@@ -XXX,XX +XXX,XX @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest);
52
* the relevant information at translation time.
53
*/
54
55
-#define GEN_TRANSLATOR_LD(fullname, type, load_fn, swap_fn) \
56
- type fullname ## _swap(CPUArchState *env, DisasContextBase *dcbase, \
57
- abi_ptr pc, bool do_swap); \
58
- static inline type fullname(CPUArchState *env, \
59
- DisasContextBase *dcbase, abi_ptr pc) \
60
- { \
61
- return fullname ## _swap(env, dcbase, pc, false); \
62
+uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, abi_ptr pc);
63
+uint16_t translator_lduw(CPUArchState *env, DisasContextBase *db, abi_ptr pc);
64
+uint32_t translator_ldl(CPUArchState *env, DisasContextBase *db, abi_ptr pc);
65
+uint64_t translator_ldq(CPUArchState *env, DisasContextBase *db, abi_ptr pc);
66
+
67
+static inline uint16_t
68
+translator_lduw_swap(CPUArchState *env, DisasContextBase *db,
69
+ abi_ptr pc, bool do_swap)
70
+{
71
+ uint16_t ret = translator_lduw(env, db, pc);
72
+ if (do_swap) {
73
+ ret = bswap16(ret);
74
}
75
+ return ret;
76
+}
77
78
-#define FOR_EACH_TRANSLATOR_LD(F) \
79
- F(translator_ldub, uint8_t, cpu_ldub_code, /* no swap */) \
80
- F(translator_lduw, uint16_t, cpu_lduw_code, bswap16) \
81
- F(translator_ldl, uint32_t, cpu_ldl_code, bswap32) \
82
- F(translator_ldq, uint64_t, cpu_ldq_code, bswap64)
83
+static inline uint32_t
84
+translator_ldl_swap(CPUArchState *env, DisasContextBase *db,
85
+ abi_ptr pc, bool do_swap)
86
+{
87
+ uint32_t ret = translator_ldl(env, db, pc);
88
+ if (do_swap) {
89
+ ret = bswap32(ret);
90
+ }
91
+ return ret;
92
+}
93
94
-FOR_EACH_TRANSLATOR_LD(GEN_TRANSLATOR_LD)
95
-
96
-#undef GEN_TRANSLATOR_LD
97
+static inline uint64_t
98
+translator_ldq_swap(CPUArchState *env, DisasContextBase *db,
99
+ abi_ptr pc, bool do_swap)
100
+{
101
+ uint64_t ret = translator_ldq_swap(env, db, pc, false);
102
+ if (do_swap) {
103
+ ret = bswap64(ret);
104
+ }
105
+ return ret;
106
+}
107
108
/*
109
* Return whether addr is on the same page as where disassembly started.
110
diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
111
index XXXXXXX..XXXXXXX 100644
112
--- a/accel/tcg/translate-all.c
113
+++ b/accel/tcg/translate-all.c
114
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
115
{
116
CPUArchState *env = cpu->env_ptr;
117
TranslationBlock *tb, *existing_tb;
118
- tb_page_addr_t phys_pc, phys_page2;
119
- target_ulong virt_page2;
120
+ tb_page_addr_t phys_pc;
121
tcg_insn_unit *gen_code_buf;
122
int gen_code_size, search_size, max_insns;
123
#ifdef CONFIG_PROFILER
124
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
125
tb->flags = flags;
126
tb->cflags = cflags;
127
tb->trace_vcpu_dstate = *cpu->trace_dstate;
128
+ tb->page_addr[0] = phys_pc;
129
+ tb->page_addr[1] = -1;
130
tcg_ctx->tb_cflags = cflags;
131
tb_overflow:
132
133
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
134
}
135
136
/*
137
- * If the TB is not associated with a physical RAM page then
138
- * it must be a temporary one-insn TB, and we have nothing to do
139
- * except fill in the page_addr[] fields. Return early before
140
- * attempting to link to other TBs or add to the lookup table.
141
+ * If the TB is not associated with a physical RAM page then it must be
142
+ * a temporary one-insn TB, and we have nothing left to do. Return early
143
+ * before attempting to link to other TBs or add to the lookup table.
144
*/
145
- if (phys_pc == -1) {
146
- tb->page_addr[0] = tb->page_addr[1] = -1;
147
+ if (tb->page_addr[0] == -1) {
148
return tb;
149
}
150
151
@@ -XXX,XX +XXX,XX @@ TranslationBlock *tb_gen_code(CPUState *cpu,
152
*/
153
tcg_tb_insert(tb);
154
155
- /* check next page if needed */
156
- virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
157
- phys_page2 = -1;
158
- if ((pc & TARGET_PAGE_MASK) != virt_page2) {
159
- phys_page2 = get_page_addr_code(env, virt_page2);
160
- }
161
/*
162
* No explicit memory barrier is required -- tb_link_page() makes the
163
* TB visible in a consistent state.
164
*/
165
- existing_tb = tb_link_page(tb, phys_pc, phys_page2);
166
+ existing_tb = tb_link_page(tb, tb->page_addr[0], tb->page_addr[1]);
167
/* if the TB already exists, discard what we just translated */
168
if (unlikely(existing_tb != tb)) {
169
uintptr_t orig_aligned = (uintptr_t)gen_code_buf;
170
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
171
index XXXXXXX..XXXXXXX 100644
172
--- a/accel/tcg/translator.c
173
+++ b/accel/tcg/translator.c
174
@@ -XXX,XX +XXX,XX @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest)
175
return ((db->pc_first ^ dest) & TARGET_PAGE_MASK) == 0;
23
}
176
}
24
177
25
+/*
178
-static inline void translator_page_protect(DisasContextBase *dcbase,
26
+ * Note that TCGReg references Q-registers.
179
- target_ulong pc)
27
+ * Q-regno = 2 * D-regno, so shift left by 1 whlie inserting.
180
-{
28
+ */
181
-#ifdef CONFIG_USER_ONLY
29
+static uint32_t encode_vd(TCGReg rd)
182
- dcbase->page_protect_end = pc | ~TARGET_PAGE_MASK;
30
+{
183
- page_protect(pc);
31
+ tcg_debug_assert(rd >= TCG_REG_Q0);
184
-#endif
32
+ return (extract32(rd, 3, 1) << 22) | (extract32(rd, 0, 3) << 13);
185
-}
33
+}
186
-
34
+
187
void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns,
35
+static void tcg_out_vldst(TCGContext *s, ARMInsn insn,
188
target_ulong pc, void *host_pc,
36
+ TCGReg rd, TCGReg rn, int offset)
189
const TranslatorOps *ops, DisasContextBase *db)
37
+{
190
@@ -XXX,XX +XXX,XX @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns,
38
+ if (offset != 0) {
191
db->num_insns = 0;
39
+ if (check_fit_imm(offset) || check_fit_imm(-offset)) {
192
db->max_insns = max_insns;
40
+ tcg_out_dat_rIN(s, COND_AL, ARITH_ADD, ARITH_SUB,
193
db->singlestep_enabled = cflags & CF_SINGLE_STEP;
41
+ TCG_REG_TMP, rn, offset, true);
194
- translator_page_protect(db, db->pc_next);
42
+ } else {
195
+ db->host_addr[0] = host_pc;
43
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP, offset);
196
+ db->host_addr[1] = NULL;
44
+ tcg_out_dat_reg(s, COND_AL, ARITH_ADD,
197
+
45
+ TCG_REG_TMP, TCG_REG_TMP, rn, 0);
198
+#ifdef CONFIG_USER_ONLY
199
+ page_protect(pc);
200
+#endif
201
202
ops->init_disas_context(db, cpu);
203
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
204
@@ -XXX,XX +XXX,XX @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns,
205
#endif
206
}
207
208
-static inline void translator_maybe_page_protect(DisasContextBase *dcbase,
209
- target_ulong pc, size_t len)
210
+static void *translator_access(CPUArchState *env, DisasContextBase *db,
211
+ target_ulong pc, size_t len)
212
{
213
-#ifdef CONFIG_USER_ONLY
214
- target_ulong end = pc + len - 1;
215
+ void *host;
216
+ target_ulong base, end;
217
+ TranslationBlock *tb;
218
219
- if (end > dcbase->page_protect_end) {
220
- translator_page_protect(dcbase, end);
221
+ tb = db->tb;
222
+
223
+ /* Use slow path if first page is MMIO. */
224
+ if (unlikely(tb->page_addr[0] == -1)) {
225
+ return NULL;
226
}
227
+
228
+ end = pc + len - 1;
229
+ if (likely(is_same_page(db, end))) {
230
+ host = db->host_addr[0];
231
+ base = db->pc_first;
232
+ } else {
233
+ host = db->host_addr[1];
234
+ base = TARGET_PAGE_ALIGN(db->pc_first);
235
+ if (host == NULL) {
236
+ tb->page_addr[1] =
237
+ get_page_addr_code_hostp(env, base, &db->host_addr[1]);
238
+#ifdef CONFIG_USER_ONLY
239
+ page_protect(end);
240
#endif
241
+ /* We cannot handle MMIO as second page. */
242
+ assert(tb->page_addr[1] != -1);
243
+ host = db->host_addr[1];
46
+ }
244
+ }
47
+ rn = TCG_REG_TMP;
245
+
48
+ }
246
+ /* Use slow path when crossing pages. */
49
+ tcg_out32(s, insn | (rn << 16) | encode_vd(rd) | 0xf);
247
+ if (is_same_page(db, pc)) {
50
+}
248
+ return NULL;
51
+
249
+ }
52
#ifdef CONFIG_SOFTMMU
250
+ }
53
#include "../tcg-ldst.c.inc"
251
+
54
252
+ tcg_debug_assert(pc >= base);
55
@@ -XXX,XX +XXX,XX @@ static void tcg_target_init(TCGContext *s)
253
+ return host + (pc - base);
56
tcg_regset_set_reg(s->reserved_regs, TCG_VEC_TMP);
57
}
254
}
58
255
59
-static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
256
-#define GEN_TRANSLATOR_LD(fullname, type, load_fn, swap_fn) \
60
- TCGReg arg1, intptr_t arg2)
257
- type fullname ## _swap(CPUArchState *env, DisasContextBase *dcbase, \
61
+static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
258
- abi_ptr pc, bool do_swap) \
62
+ TCGReg arg1, intptr_t arg2)
259
- { \
63
{
260
- translator_maybe_page_protect(dcbase, pc, sizeof(type)); \
64
- tcg_out_ld32u(s, COND_AL, arg, arg1, arg2);
261
- type ret = load_fn(env, pc); \
65
+ switch (type) {
262
- if (do_swap) { \
66
+ case TCG_TYPE_I32:
263
- ret = swap_fn(ret); \
67
+ tcg_out_ld32u(s, COND_AL, arg, arg1, arg2);
264
- } \
68
+ return;
265
- plugin_insn_append(pc, &ret, sizeof(ret)); \
69
+ case TCG_TYPE_V64:
266
- return ret; \
70
+ /* regs 1; size 8; align 8 */
267
+uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
71
+ tcg_out_vldst(s, INSN_VLD1 | 0x7d0, arg, arg1, arg2);
268
+{
72
+ return;
269
+ uint8_t ret;
73
+ case TCG_TYPE_V128:
270
+ void *p = translator_access(env, db, pc, sizeof(ret));
74
+ /* regs 2; size 8; align 16 */
271
+
75
+ tcg_out_vldst(s, INSN_VLD1 | 0xae0, arg, arg1, arg2);
272
+ if (p) {
76
+ return;
273
+ plugin_insn_append(pc, p, sizeof(ret));
77
+ default:
274
+ return ldub_p(p);
78
+ g_assert_not_reached();
275
}
79
+ }
276
+ ret = cpu_ldub_code(env, pc);
80
}
277
+ plugin_insn_append(pc, &ret, sizeof(ret));
81
278
+ return ret;
82
-static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
279
+}
83
- TCGReg arg1, intptr_t arg2)
280
84
+static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
281
-FOR_EACH_TRANSLATOR_LD(GEN_TRANSLATOR_LD)
85
+ TCGReg arg1, intptr_t arg2)
282
+uint16_t translator_lduw(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
86
{
283
+{
87
- tcg_out_st32(s, COND_AL, arg, arg1, arg2);
284
+ uint16_t ret, plug;
88
+ switch (type) {
285
+ void *p = translator_access(env, db, pc, sizeof(ret));
89
+ case TCG_TYPE_I32:
286
90
+ tcg_out_st32(s, COND_AL, arg, arg1, arg2);
287
-#undef GEN_TRANSLATOR_LD
91
+ return;
288
+ if (p) {
92
+ case TCG_TYPE_V64:
289
+ plugin_insn_append(pc, p, sizeof(ret));
93
+ /* regs 1; size 8; align 8 */
290
+ return lduw_p(p);
94
+ tcg_out_vldst(s, INSN_VST1 | 0x7d0, arg, arg1, arg2);
291
+ }
95
+ return;
292
+ ret = cpu_lduw_code(env, pc);
96
+ case TCG_TYPE_V128:
293
+ plug = tswap16(ret);
97
+ /* regs 2; size 8; align 16 */
294
+ plugin_insn_append(pc, &plug, sizeof(ret));
98
+ tcg_out_vldst(s, INSN_VST1 | 0xae0, arg, arg1, arg2);
295
+ return ret;
99
+ return;
296
+}
100
+ default:
297
+
101
+ g_assert_not_reached();
298
+uint32_t translator_ldl(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
102
+ }
299
+{
103
}
300
+ uint32_t ret, plug;
104
301
+ void *p = translator_access(env, db, pc, sizeof(ret));
105
static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
302
+
303
+ if (p) {
304
+ plugin_insn_append(pc, p, sizeof(ret));
305
+ return ldl_p(p);
306
+ }
307
+ ret = cpu_ldl_code(env, pc);
308
+ plug = tswap32(ret);
309
+ plugin_insn_append(pc, &plug, sizeof(ret));
310
+ return ret;
311
+}
312
+
313
+uint64_t translator_ldq(CPUArchState *env, DisasContextBase *db, abi_ptr pc)
314
+{
315
+ uint64_t ret, plug;
316
+ void *p = translator_access(env, db, pc, sizeof(ret));
317
+
318
+ if (p) {
319
+ plugin_insn_append(pc, p, sizeof(ret));
320
+ return ldq_p(p);
321
+ }
322
+ ret = cpu_ldq_code(env, pc);
323
+ plug = tswap64(ret);
324
+ plugin_insn_append(pc, &plug, sizeof(ret));
325
+ return ret;
326
+}
106
--
327
--
107
2.25.1
328
2.34.1
108
109
diff view generated by jsdifflib
1
These logical and arithmetic operations are optional, but are
1
From: Ilya Leoshkevich <iii@linux.ibm.com>
2
trivial to accomplish with the existing infrastructure.
3
2
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Right now translator stops right *after* the end of a page, which
4
breaks reporting of fault locations when the last instruction of a
5
multi-insn translation block crosses a page boundary.
6
7
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-Id: <20220817150506.592862-3-iii@linux.ibm.com>
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
11
---
7
tcg/arm/tcg-target-con-set.h | 1 +
12
target/s390x/tcg/translate.c | 15 +++-
8
tcg/arm/tcg-target.h | 10 +++++-----
13
tests/tcg/s390x/noexec.c | 106 +++++++++++++++++++++++
9
tcg/arm/tcg-target.c.inc | 38 ++++++++++++++++++++++++++++++++++++
14
tests/tcg/multiarch/noexec.c.inc | 139 +++++++++++++++++++++++++++++++
10
3 files changed, 44 insertions(+), 5 deletions(-)
15
tests/tcg/s390x/Makefile.target | 1 +
16
4 files changed, 257 insertions(+), 4 deletions(-)
17
create mode 100644 tests/tcg/s390x/noexec.c
18
create mode 100644 tests/tcg/multiarch/noexec.c.inc
11
19
12
diff --git a/tcg/arm/tcg-target-con-set.h b/tcg/arm/tcg-target-con-set.h
20
diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c
13
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
14
--- a/tcg/arm/tcg-target-con-set.h
22
--- a/target/s390x/tcg/translate.c
15
+++ b/tcg/arm/tcg-target-con-set.h
23
+++ b/target/s390x/tcg/translate.c
16
@@ -XXX,XX +XXX,XX @@ C_O0_I4(s, s, s, s)
24
@@ -XXX,XX +XXX,XX @@ static void s390x_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
17
C_O1_I1(r, l)
25
dc->insn_start = tcg_last_op();
18
C_O1_I1(r, r)
26
}
19
C_O1_I1(w, r)
27
20
+C_O1_I1(w, w)
28
+static target_ulong get_next_pc(CPUS390XState *env, DisasContext *s,
21
C_O1_I1(w, wr)
29
+ uint64_t pc)
22
C_O1_I2(r, 0, rZ)
30
+{
23
C_O1_I2(r, l, l)
31
+ uint64_t insn = ld_code2(env, s, pc);
24
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
32
+
33
+ return pc + get_ilen((insn >> 8) & 0xff);
34
+}
35
+
36
static void s390x_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
37
{
38
CPUS390XState *env = cs->env_ptr;
39
@@ -XXX,XX +XXX,XX @@ static void s390x_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
40
41
dc->base.is_jmp = translate_one(env, dc);
42
if (dc->base.is_jmp == DISAS_NEXT) {
43
- uint64_t page_start;
44
-
45
- page_start = dc->base.pc_first & TARGET_PAGE_MASK;
46
- if (dc->base.pc_next - page_start >= TARGET_PAGE_SIZE || dc->ex_value) {
47
+ if (!is_same_page(dcbase, dc->base.pc_next) ||
48
+ !is_same_page(dcbase, get_next_pc(env, dc, dc->base.pc_next)) ||
49
+ dc->ex_value) {
50
dc->base.is_jmp = DISAS_TOO_MANY;
51
}
52
}
53
diff --git a/tests/tcg/s390x/noexec.c b/tests/tcg/s390x/noexec.c
54
new file mode 100644
55
index XXXXXXX..XXXXXXX
56
--- /dev/null
57
+++ b/tests/tcg/s390x/noexec.c
58
@@ -XXX,XX +XXX,XX @@
59
+#include "../multiarch/noexec.c.inc"
60
+
61
+static void *arch_mcontext_pc(const mcontext_t *ctx)
62
+{
63
+ return (void *)ctx->psw.addr;
64
+}
65
+
66
+static int arch_mcontext_arg(const mcontext_t *ctx)
67
+{
68
+ return ctx->gregs[2];
69
+}
70
+
71
+static void arch_flush(void *p, int len)
72
+{
73
+}
74
+
75
+extern char noexec_1[];
76
+extern char noexec_2[];
77
+extern char noexec_end[];
78
+
79
+asm("noexec_1:\n"
80
+ " lgfi %r2,1\n" /* %r2 is 0 on entry, set 1. */
81
+ "noexec_2:\n"
82
+ " lgfi %r2,2\n" /* %r2 is 0/1; set 2. */
83
+ " br %r14\n" /* return */
84
+ "noexec_end:");
85
+
86
+extern char exrl_1[];
87
+extern char exrl_2[];
88
+extern char exrl_end[];
89
+
90
+asm("exrl_1:\n"
91
+ " exrl %r0, exrl_2\n"
92
+ " br %r14\n"
93
+ "exrl_2:\n"
94
+ " lgfi %r2,2\n"
95
+ "exrl_end:");
96
+
97
+int main(void)
98
+{
99
+ struct noexec_test noexec_tests[] = {
100
+ {
101
+ .name = "fallthrough",
102
+ .test_code = noexec_1,
103
+ .test_len = noexec_end - noexec_1,
104
+ .page_ofs = noexec_1 - noexec_2,
105
+ .entry_ofs = noexec_1 - noexec_2,
106
+ .expected_si_ofs = 0,
107
+ .expected_pc_ofs = 0,
108
+ .expected_arg = 1,
109
+ },
110
+ {
111
+ .name = "jump",
112
+ .test_code = noexec_1,
113
+ .test_len = noexec_end - noexec_1,
114
+ .page_ofs = noexec_1 - noexec_2,
115
+ .entry_ofs = 0,
116
+ .expected_si_ofs = 0,
117
+ .expected_pc_ofs = 0,
118
+ .expected_arg = 0,
119
+ },
120
+ {
121
+ .name = "exrl",
122
+ .test_code = exrl_1,
123
+ .test_len = exrl_end - exrl_1,
124
+ .page_ofs = exrl_1 - exrl_2,
125
+ .entry_ofs = exrl_1 - exrl_2,
126
+ .expected_si_ofs = 0,
127
+ .expected_pc_ofs = exrl_1 - exrl_2,
128
+ .expected_arg = 0,
129
+ },
130
+ {
131
+ .name = "fallthrough [cross]",
132
+ .test_code = noexec_1,
133
+ .test_len = noexec_end - noexec_1,
134
+ .page_ofs = noexec_1 - noexec_2 - 2,
135
+ .entry_ofs = noexec_1 - noexec_2 - 2,
136
+ .expected_si_ofs = 0,
137
+ .expected_pc_ofs = -2,
138
+ .expected_arg = 1,
139
+ },
140
+ {
141
+ .name = "jump [cross]",
142
+ .test_code = noexec_1,
143
+ .test_len = noexec_end - noexec_1,
144
+ .page_ofs = noexec_1 - noexec_2 - 2,
145
+ .entry_ofs = -2,
146
+ .expected_si_ofs = 0,
147
+ .expected_pc_ofs = -2,
148
+ .expected_arg = 0,
149
+ },
150
+ {
151
+ .name = "exrl [cross]",
152
+ .test_code = exrl_1,
153
+ .test_len = exrl_end - exrl_1,
154
+ .page_ofs = exrl_1 - exrl_2 - 2,
155
+ .entry_ofs = exrl_1 - exrl_2 - 2,
156
+ .expected_si_ofs = 0,
157
+ .expected_pc_ofs = exrl_1 - exrl_2 - 2,
158
+ .expected_arg = 0,
159
+ },
160
+ };
161
+
162
+ return test_noexec(noexec_tests,
163
+ sizeof(noexec_tests) / sizeof(noexec_tests[0]));
164
+}
165
diff --git a/tests/tcg/multiarch/noexec.c.inc b/tests/tcg/multiarch/noexec.c.inc
166
new file mode 100644
167
index XXXXXXX..XXXXXXX
168
--- /dev/null
169
+++ b/tests/tcg/multiarch/noexec.c.inc
170
@@ -XXX,XX +XXX,XX @@
171
+/*
172
+ * Common code for arch-specific MMU_INST_FETCH fault testing.
173
+ */
174
+
175
+#define _GNU_SOURCE
176
+
177
+#include <assert.h>
178
+#include <signal.h>
179
+#include <stdio.h>
180
+#include <stdlib.h>
181
+#include <string.h>
182
+#include <errno.h>
183
+#include <unistd.h>
184
+#include <sys/mman.h>
185
+#include <sys/ucontext.h>
186
+
187
+/* Forward declarations. */
188
+
189
+static void *arch_mcontext_pc(const mcontext_t *ctx);
190
+static int arch_mcontext_arg(const mcontext_t *ctx);
191
+static void arch_flush(void *p, int len);
192
+
193
+/* Testing infrastructure. */
194
+
195
+struct noexec_test {
196
+ const char *name;
197
+ const char *test_code;
198
+ int test_len;
199
+ int page_ofs;
200
+ int entry_ofs;
201
+ int expected_si_ofs;
202
+ int expected_pc_ofs;
203
+ int expected_arg;
204
+};
205
+
206
+static void *page_base;
207
+static int page_size;
208
+static const struct noexec_test *current_noexec_test;
209
+
210
+static void handle_err(const char *syscall)
211
+{
212
+ printf("[ FAILED ] %s: %s\n", syscall, strerror(errno));
213
+ exit(EXIT_FAILURE);
214
+}
215
+
216
+static void handle_segv(int sig, siginfo_t *info, void *ucontext)
217
+{
218
+ const struct noexec_test *test = current_noexec_test;
219
+ const mcontext_t *mc = &((ucontext_t *)ucontext)->uc_mcontext;
220
+ void *expected_si;
221
+ void *expected_pc;
222
+ void *pc;
223
+ int arg;
224
+
225
+ if (test == NULL) {
226
+ printf("[ FAILED ] unexpected SEGV\n");
227
+ exit(EXIT_FAILURE);
228
+ }
229
+ current_noexec_test = NULL;
230
+
231
+ expected_si = page_base + test->expected_si_ofs;
232
+ if (info->si_addr != expected_si) {
233
+ printf("[ FAILED ] wrong si_addr (%p != %p)\n",
234
+ info->si_addr, expected_si);
235
+ exit(EXIT_FAILURE);
236
+ }
237
+
238
+ pc = arch_mcontext_pc(mc);
239
+ expected_pc = page_base + test->expected_pc_ofs;
240
+ if (pc != expected_pc) {
241
+ printf("[ FAILED ] wrong pc (%p != %p)\n", pc, expected_pc);
242
+ exit(EXIT_FAILURE);
243
+ }
244
+
245
+ arg = arch_mcontext_arg(mc);
246
+ if (arg != test->expected_arg) {
247
+ printf("[ FAILED ] wrong arg (%d != %d)\n", arg, test->expected_arg);
248
+ exit(EXIT_FAILURE);
249
+ }
250
+
251
+ if (mprotect(page_base, page_size,
252
+ PROT_READ | PROT_WRITE | PROT_EXEC) < 0) {
253
+ handle_err("mprotect");
254
+ }
255
+}
256
+
257
+static void test_noexec_1(const struct noexec_test *test)
258
+{
259
+ void *start = page_base + test->page_ofs;
260
+ void (*fn)(int arg) = page_base + test->entry_ofs;
261
+
262
+ memcpy(start, test->test_code, test->test_len);
263
+ arch_flush(start, test->test_len);
264
+
265
+ /* Trigger TB creation in order to test invalidation. */
266
+ fn(0);
267
+
268
+ if (mprotect(page_base, page_size, PROT_NONE) < 0) {
269
+ handle_err("mprotect");
270
+ }
271
+
272
+ /* Trigger SEGV and check that handle_segv() ran. */
273
+ current_noexec_test = test;
274
+ fn(0);
275
+ assert(current_noexec_test == NULL);
276
+}
277
+
278
+static int test_noexec(struct noexec_test *tests, size_t n_tests)
279
+{
280
+ struct sigaction act;
281
+ size_t i;
282
+
283
+ memset(&act, 0, sizeof(act));
284
+ act.sa_sigaction = handle_segv;
285
+ act.sa_flags = SA_SIGINFO;
286
+ if (sigaction(SIGSEGV, &act, NULL) < 0) {
287
+ handle_err("sigaction");
288
+ }
289
+
290
+ page_size = getpagesize();
291
+ page_base = mmap(NULL, 2 * page_size,
292
+ PROT_READ | PROT_WRITE | PROT_EXEC,
293
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
294
+ if (page_base == MAP_FAILED) {
295
+ handle_err("mmap");
296
+ }
297
+ page_base += page_size;
298
+
299
+ for (i = 0; i < n_tests; i++) {
300
+ struct noexec_test *test = &tests[i];
301
+
302
+ printf("[ RUN ] %s\n", test->name);
303
+ test_noexec_1(test);
304
+ printf("[ OK ]\n");
305
+ }
306
+
307
+ printf("[ PASSED ]\n");
308
+ return EXIT_SUCCESS;
309
+}
310
diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target
25
index XXXXXXX..XXXXXXX 100644
311
index XXXXXXX..XXXXXXX 100644
26
--- a/tcg/arm/tcg-target.h
312
--- a/tests/tcg/s390x/Makefile.target
27
+++ b/tcg/arm/tcg-target.h
313
+++ b/tests/tcg/s390x/Makefile.target
28
@@ -XXX,XX +XXX,XX @@ extern bool use_neon_instructions;
314
@@ -XXX,XX +XXX,XX @@ TESTS+=shift
29
#define TCG_TARGET_HAS_v128 use_neon_instructions
315
TESTS+=trap
30
#define TCG_TARGET_HAS_v256 0
316
TESTS+=signals-s390x
31
317
TESTS+=branch-relative-long
32
-#define TCG_TARGET_HAS_andc_vec 0
318
+TESTS+=noexec
33
-#define TCG_TARGET_HAS_orc_vec 0
319
34
-#define TCG_TARGET_HAS_not_vec 0
320
Z14_TESTS=vfminmax
35
-#define TCG_TARGET_HAS_neg_vec 0
321
vfminmax: LDFLAGS+=-lm
36
-#define TCG_TARGET_HAS_abs_vec 0
37
+#define TCG_TARGET_HAS_andc_vec 1
38
+#define TCG_TARGET_HAS_orc_vec 1
39
+#define TCG_TARGET_HAS_not_vec 1
40
+#define TCG_TARGET_HAS_neg_vec 1
41
+#define TCG_TARGET_HAS_abs_vec 1
42
#define TCG_TARGET_HAS_roti_vec 0
43
#define TCG_TARGET_HAS_rots_vec 0
44
#define TCG_TARGET_HAS_rotv_vec 0
45
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
46
index XXXXXXX..XXXXXXX 100644
47
--- a/tcg/arm/tcg-target.c.inc
48
+++ b/tcg/arm/tcg-target.c.inc
49
@@ -XXX,XX +XXX,XX @@ typedef enum {
50
51
INSN_VADD = 0xf2000800,
52
INSN_VAND = 0xf2000110,
53
+ INSN_VBIC = 0xf2100110,
54
INSN_VEOR = 0xf3000110,
55
+ INSN_VORN = 0xf2300110,
56
INSN_VORR = 0xf2200110,
57
INSN_VSUB = 0xf3000800,
58
59
+ INSN_VABS = 0xf3b10300,
60
INSN_VMVN = 0xf3b00580,
61
+ INSN_VNEG = 0xf3b10380,
62
63
INSN_VCEQ0 = 0xf3b10100,
64
INSN_VCGT0 = 0xf3b10000,
65
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
66
return C_O1_I1(w, r);
67
case INDEX_op_dup_vec:
68
return C_O1_I1(w, wr);
69
+ case INDEX_op_abs_vec:
70
+ case INDEX_op_neg_vec:
71
+ case INDEX_op_not_vec:
72
+ return C_O1_I1(w, w);
73
case INDEX_op_dup2_vec:
74
case INDEX_op_add_vec:
75
case INDEX_op_sub_vec:
76
case INDEX_op_xor_vec:
77
return C_O1_I2(w, w, w);
78
case INDEX_op_or_vec:
79
+ case INDEX_op_andc_vec:
80
return C_O1_I2(w, w, wO);
81
case INDEX_op_and_vec:
82
+ case INDEX_op_orc_vec:
83
return C_O1_I2(w, w, wV);
84
case INDEX_op_cmp_vec:
85
return C_O1_I2(w, w, wZ);
86
@@ -XXX,XX +XXX,XX @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
87
case INDEX_op_dup2_vec:
88
tcg_out_dup2_vec(s, a0, a1, a2);
89
return;
90
+ case INDEX_op_abs_vec:
91
+ tcg_out_vreg2(s, INSN_VABS, q, vece, a0, a1);
92
+ return;
93
+ case INDEX_op_neg_vec:
94
+ tcg_out_vreg2(s, INSN_VNEG, q, vece, a0, a1);
95
+ return;
96
+ case INDEX_op_not_vec:
97
+ tcg_out_vreg2(s, INSN_VMVN, q, 0, a0, a1);
98
+ return;
99
case INDEX_op_add_vec:
100
tcg_out_vreg3(s, INSN_VADD, q, vece, a0, a1, a2);
101
return;
102
@@ -XXX,XX +XXX,XX @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
103
tcg_out_vreg3(s, INSN_VEOR, q, 0, a0, a1, a2);
104
return;
105
106
+ case INDEX_op_andc_vec:
107
+ if (!const_args[2]) {
108
+ tcg_out_vreg3(s, INSN_VBIC, q, 0, a0, a1, a2);
109
+ return;
110
+ }
111
+ a2 = ~a2;
112
+ /* fall through */
113
case INDEX_op_and_vec:
114
if (const_args[2]) {
115
is_shimm1632(~a2, &cmode, &imm8);
116
@@ -XXX,XX +XXX,XX @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
117
tcg_out_vreg3(s, INSN_VAND, q, 0, a0, a1, a2);
118
return;
119
120
+ case INDEX_op_orc_vec:
121
+ if (!const_args[2]) {
122
+ tcg_out_vreg3(s, INSN_VORN, q, 0, a0, a1, a2);
123
+ return;
124
+ }
125
+ a2 = ~a2;
126
+ /* fall through */
127
case INDEX_op_or_vec:
128
if (const_args[2]) {
129
is_shimm1632(a2, &cmode, &imm8);
130
@@ -XXX,XX +XXX,XX @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
131
case INDEX_op_add_vec:
132
case INDEX_op_sub_vec:
133
case INDEX_op_and_vec:
134
+ case INDEX_op_andc_vec:
135
case INDEX_op_or_vec:
136
+ case INDEX_op_orc_vec:
137
case INDEX_op_xor_vec:
138
+ case INDEX_op_not_vec:
139
return 1;
140
+ case INDEX_op_abs_vec:
141
case INDEX_op_cmp_vec:
142
+ case INDEX_op_neg_vec:
143
return vece < MO_64;
144
default:
145
return 0;
146
--
322
--
147
2.25.1
323
2.34.1
148
149
diff view generated by jsdifflib
1
Implementing dup2, add, sub, and, or, xor as the minimal set.
1
From: Ilya Leoshkevich <iii@linux.ibm.com>
2
This allows us to actually enable neon in the header file.
2
3
3
Right now translator stops right *after* the end of a page, which
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
breaks reporting of fault locations when the last instruction of a
5
multi-insn translation block crosses a page boundary.
6
7
An implementation, like the one arm and s390x have, would require an
8
i386 length disassembler, which is burdensome to maintain. Another
9
alternative would be to single-step at the end of a guest page, but
10
this may come with a performance impact.
11
12
Fix by snapshotting disassembly state and restoring it after we figure
13
out we crossed a page boundary. This includes rolling back cc_op
14
updates and emitted ops.
15
16
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1143
19
Message-Id: <20220817150506.592862-4-iii@linux.ibm.com>
20
[rth: Simplify end-of-insn cross-page checks.]
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
21
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
---
22
---
7
tcg/arm/tcg-target-con-set.h | 3 +
23
target/i386/tcg/translate.c | 64 ++++++++++++++++-----------
8
tcg/arm/tcg-target-con-str.h | 2 +
24
tests/tcg/x86_64/noexec.c | 75 ++++++++++++++++++++++++++++++++
9
tcg/arm/tcg-target.h | 6 +-
25
tests/tcg/x86_64/Makefile.target | 3 +-
10
tcg/arm/tcg-target.c.inc | 201 +++++++++++++++++++++++++++++++++--
26
3 files changed, 116 insertions(+), 26 deletions(-)
11
4 files changed, 204 insertions(+), 8 deletions(-)
27
create mode 100644 tests/tcg/x86_64/noexec.c
12
28
13
diff --git a/tcg/arm/tcg-target-con-set.h b/tcg/arm/tcg-target-con-set.h
29
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
14
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
15
--- a/tcg/arm/tcg-target-con-set.h
31
--- a/target/i386/tcg/translate.c
16
+++ b/tcg/arm/tcg-target-con-set.h
32
+++ b/target/i386/tcg/translate.c
17
@@ -XXX,XX +XXX,XX @@ C_O1_I2(r, r, rIN)
33
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
18
C_O1_I2(r, r, ri)
34
TCGv_i64 tmp1_i64;
19
C_O1_I2(r, rZ, rZ)
35
20
C_O1_I2(w, w, w)
36
sigjmp_buf jmpbuf;
21
+C_O1_I2(w, w, wO)
37
+ TCGOp *prev_insn_end;
22
+C_O1_I2(w, w, wV)
38
} DisasContext;
23
+C_O1_I2(w, w, wZ)
39
24
C_O1_I4(r, r, r, rI, rI)
40
/* The environment in which user-only runs is constrained. */
25
C_O1_I4(r, r, rIN, rIK, 0)
41
@@ -XXX,XX +XXX,XX @@ static uint64_t advance_pc(CPUX86State *env, DisasContext *s, int num_bytes)
26
C_O2_I1(r, r, l)
42
{
27
diff --git a/tcg/arm/tcg-target-con-str.h b/tcg/arm/tcg-target-con-str.h
43
uint64_t pc = s->pc;
28
index XXXXXXX..XXXXXXX 100644
44
29
--- a/tcg/arm/tcg-target-con-str.h
45
+ /* This is a subsequent insn that crosses a page boundary. */
30
+++ b/tcg/arm/tcg-target-con-str.h
46
+ if (s->base.num_insns > 1 &&
31
@@ -XXX,XX +XXX,XX @@ REGS('w', ALL_VECTOR_REGS)
47
+ !is_same_page(&s->base, s->pc + num_bytes - 1)) {
32
CONST('I', TCG_CT_CONST_ARM)
48
+ siglongjmp(s->jmpbuf, 2);
33
CONST('K', TCG_CT_CONST_INV)
34
CONST('N', TCG_CT_CONST_NEG)
35
+CONST('O', TCG_CT_CONST_ORRI)
36
+CONST('V', TCG_CT_CONST_ANDI)
37
CONST('Z', TCG_CT_CONST_ZERO)
38
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
39
index XXXXXXX..XXXXXXX 100644
40
--- a/tcg/arm/tcg-target.h
41
+++ b/tcg/arm/tcg-target.h
42
@@ -XXX,XX +XXX,XX @@ typedef enum {
43
#else
44
extern bool use_idiv_instructions;
45
#endif
46
-#define use_neon_instructions 0
47
+#ifdef __ARM_NEON__
48
+#define use_neon_instructions 1
49
+#else
50
+extern bool use_neon_instructions;
51
+#endif
52
53
/* used for function call generation */
54
#define TCG_TARGET_STACK_ALIGN        8
55
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
56
index XXXXXXX..XXXXXXX 100644
57
--- a/tcg/arm/tcg-target.c.inc
58
+++ b/tcg/arm/tcg-target.c.inc
59
@@ -XXX,XX +XXX,XX @@ int arm_arch = __ARM_ARCH;
60
#ifndef use_idiv_instructions
61
bool use_idiv_instructions;
62
#endif
63
+#ifndef use_neon_instructions
64
+bool use_neon_instructions;
65
+#endif
66
67
/* ??? Ought to think about changing CONFIG_SOFTMMU to always defined. */
68
#ifdef CONFIG_SOFTMMU
69
@@ -XXX,XX +XXX,XX @@ typedef enum {
70
/* Otherwise the assembler uses mov r0,r0 */
71
INSN_NOP_v4 = (COND_AL << 28) | ARITH_MOV,
72
73
+ INSN_VADD = 0xf2000800,
74
+ INSN_VAND = 0xf2000110,
75
+ INSN_VEOR = 0xf3000110,
76
INSN_VORR = 0xf2200110,
77
+ INSN_VSUB = 0xf3000800,
78
+
79
+ INSN_VMVN = 0xf3b00580,
80
+
81
+ INSN_VCEQ0 = 0xf3b10100,
82
+ INSN_VCGT0 = 0xf3b10000,
83
+ INSN_VCGE0 = 0xf3b10080,
84
+ INSN_VCLE0 = 0xf3b10180,
85
+ INSN_VCLT0 = 0xf3b10200,
86
+
87
+ INSN_VCEQ = 0xf3000810,
88
+ INSN_VCGE = 0xf2000310,
89
+ INSN_VCGT = 0xf2000300,
90
+ INSN_VCGE_U = 0xf3000310,
91
+ INSN_VCGT_U = 0xf3000300,
92
+
93
+ INSN_VTST = 0xf2000810,
94
95
INSN_VDUP_G = 0xee800b10, /* VDUP (ARM core register) */
96
INSN_VDUP_S = 0xf3b00c00, /* VDUP (scalar) */
97
@@ -XXX,XX +XXX,XX @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
98
#define TCG_CT_CONST_INV 0x200
99
#define TCG_CT_CONST_NEG 0x400
100
#define TCG_CT_CONST_ZERO 0x800
101
+#define TCG_CT_CONST_ORRI 0x1000
102
+#define TCG_CT_CONST_ANDI 0x2000
103
104
#define ALL_GENERAL_REGS 0xffffu
105
#define ALL_VECTOR_REGS 0xffff0000u
106
@@ -XXX,XX +XXX,XX @@ static int is_shimm32_pair(uint32_t v32, int *cmode, int *imm8)
107
return i;
108
}
109
110
+/* Return true if V is a valid 16-bit or 32-bit shifted immediate. */
111
+static bool is_shimm1632(uint32_t v32, int *cmode, int *imm8)
112
+{
113
+ if (v32 == deposit32(v32, 16, 16, v32)) {
114
+ return is_shimm16(v32, cmode, imm8);
115
+ } else {
116
+ return is_shimm32(v32, cmode, imm8);
117
+ }
49
+ }
118
+}
50
+
119
+
51
s->pc += num_bytes;
120
/* Test if a constant matches the constraint.
52
if (unlikely(s->pc - s->pc_start > X86_MAX_INSN_LENGTH)) {
121
* TODO: define constraints for:
53
/* If the instruction's 16th byte is on a different page than the 1st, a
122
*
54
@@ -XXX,XX +XXX,XX @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
123
@@ -XXX,XX +XXX,XX @@ static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
55
int modrm, reg, rm, mod, op, opreg, val;
124
return 1;
56
target_ulong next_eip, tval;
125
} else if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
57
target_ulong pc_start = s->base.pc_next;
126
return 1;
58
+ bool orig_cc_op_dirty = s->cc_op_dirty;
127
- } else {
59
+ CCOp orig_cc_op = s->cc_op;
128
- return 0;
60
129
}
61
s->pc_start = s->pc = pc_start;
130
+
62
s->override = -1;
131
+ switch (ct & (TCG_CT_CONST_ORRI | TCG_CT_CONST_ANDI)) {
63
@@ -XXX,XX +XXX,XX @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
64
s->rip_offset = 0; /* for relative ip address */
65
s->vex_l = 0;
66
s->vex_v = 0;
67
- if (sigsetjmp(s->jmpbuf, 0) != 0) {
68
+ switch (sigsetjmp(s->jmpbuf, 0)) {
132
+ case 0:
69
+ case 0:
133
+ break;
70
+ break;
134
+ case TCG_CT_CONST_ANDI:
71
+ case 1:
135
+ val = ~val;
72
gen_exception_gpf(s);
136
+ /* fallthru */
73
return s->pc;
137
+ case TCG_CT_CONST_ORRI:
74
+ case 2:
138
+ if (val == deposit64(val, 32, 32, val)) {
75
+ /* Restore state that may affect the next instruction. */
139
+ int cmode, imm8;
76
+ s->cc_op_dirty = orig_cc_op_dirty;
140
+ return is_shimm1632(val, &cmode, &imm8);
77
+ s->cc_op = orig_cc_op;
141
+ }
78
+ s->base.num_insns--;
142
+ break;
79
+ tcg_remove_ops_after(s->prev_insn_end);
143
+ default:
80
+ s->base.is_jmp = DISAS_TOO_MANY;
144
+ /* Both bits should not be set for the same insn. */
81
+ return pc_start;
145
+ g_assert_not_reached();
146
+ }
147
+
148
+ return 0;
149
}
150
151
static inline void tcg_out_b(TCGContext *s, int cond, int32_t offset)
152
@@ -XXX,XX +XXX,XX @@ static uint32_t encode_vm(TCGReg rm)
153
return (extract32(rm, 3, 1) << 5) | (extract32(rm, 0, 3) << 1);
154
}
155
156
+static void tcg_out_vreg2(TCGContext *s, ARMInsn insn, int q, int vece,
157
+ TCGReg d, TCGReg m)
158
+{
159
+ tcg_out32(s, insn | (vece << 18) | (q << 6) |
160
+ encode_vd(d) | encode_vm(m));
161
+}
162
+
163
static void tcg_out_vreg3(TCGContext *s, ARMInsn insn, int q, int vece,
164
TCGReg d, TCGReg n, TCGReg m)
165
{
166
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
167
case INDEX_op_add_vec:
168
case INDEX_op_sub_vec:
169
case INDEX_op_xor_vec:
170
- case INDEX_op_or_vec:
171
- case INDEX_op_and_vec:
172
- case INDEX_op_cmp_vec:
173
return C_O1_I2(w, w, w);
174
+ case INDEX_op_or_vec:
175
+ return C_O1_I2(w, w, wO);
176
+ case INDEX_op_and_vec:
177
+ return C_O1_I2(w, w, wV);
178
+ case INDEX_op_cmp_vec:
179
+ return C_O1_I2(w, w, wZ);
180
181
default:
182
g_assert_not_reached();
183
@@ -XXX,XX +XXX,XX @@ static void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece,
184
}
185
}
186
187
+static const ARMInsn vec_cmp_insn[16] = {
188
+ [TCG_COND_EQ] = INSN_VCEQ,
189
+ [TCG_COND_GT] = INSN_VCGT,
190
+ [TCG_COND_GE] = INSN_VCGE,
191
+ [TCG_COND_GTU] = INSN_VCGT_U,
192
+ [TCG_COND_GEU] = INSN_VCGE_U,
193
+};
194
+
195
+static const ARMInsn vec_cmp0_insn[16] = {
196
+ [TCG_COND_EQ] = INSN_VCEQ0,
197
+ [TCG_COND_GT] = INSN_VCGT0,
198
+ [TCG_COND_GE] = INSN_VCGE0,
199
+ [TCG_COND_LT] = INSN_VCLT0,
200
+ [TCG_COND_LE] = INSN_VCLE0,
201
+};
202
+
203
static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
204
unsigned vecl, unsigned vece,
205
const TCGArg *args, const int *const_args)
206
{
207
- g_assert_not_reached();
208
+ TCGType type = vecl + TCG_TYPE_V64;
209
+ unsigned q = vecl;
210
+ TCGArg a0, a1, a2;
211
+ int cmode, imm8;
212
+
213
+ a0 = args[0];
214
+ a1 = args[1];
215
+ a2 = args[2];
216
+
217
+ switch (opc) {
218
+ case INDEX_op_ld_vec:
219
+ tcg_out_ld(s, type, a0, a1, a2);
220
+ return;
221
+ case INDEX_op_st_vec:
222
+ tcg_out_st(s, type, a0, a1, a2);
223
+ return;
224
+ case INDEX_op_dupm_vec:
225
+ tcg_out_dupm_vec(s, type, vece, a0, a1, a2);
226
+ return;
227
+ case INDEX_op_dup2_vec:
228
+ tcg_out_dup2_vec(s, a0, a1, a2);
229
+ return;
230
+ case INDEX_op_add_vec:
231
+ tcg_out_vreg3(s, INSN_VADD, q, vece, a0, a1, a2);
232
+ return;
233
+ case INDEX_op_sub_vec:
234
+ tcg_out_vreg3(s, INSN_VSUB, q, vece, a0, a1, a2);
235
+ return;
236
+ case INDEX_op_xor_vec:
237
+ tcg_out_vreg3(s, INSN_VEOR, q, 0, a0, a1, a2);
238
+ return;
239
+
240
+ case INDEX_op_and_vec:
241
+ if (const_args[2]) {
242
+ is_shimm1632(~a2, &cmode, &imm8);
243
+ if (a0 == a1) {
244
+ tcg_out_vmovi(s, a0, q, 1, cmode | 1, imm8); /* VBICI */
245
+ return;
246
+ }
247
+ tcg_out_vmovi(s, a0, q, 1, cmode, imm8); /* VMVNI */
248
+ a2 = a0;
249
+ }
250
+ tcg_out_vreg3(s, INSN_VAND, q, 0, a0, a1, a2);
251
+ return;
252
+
253
+ case INDEX_op_or_vec:
254
+ if (const_args[2]) {
255
+ is_shimm1632(a2, &cmode, &imm8);
256
+ if (a0 == a1) {
257
+ tcg_out_vmovi(s, a0, q, 0, cmode | 1, imm8); /* VORRI */
258
+ return;
259
+ }
260
+ tcg_out_vmovi(s, a0, q, 0, cmode, imm8); /* VMOVI */
261
+ a2 = a0;
262
+ }
263
+ tcg_out_vreg3(s, INSN_VORR, q, 0, a0, a1, a2);
264
+ return;
265
+
266
+ case INDEX_op_cmp_vec:
267
+ {
268
+ TCGCond cond = args[3];
269
+
270
+ if (cond == TCG_COND_NE) {
271
+ if (const_args[2]) {
272
+ tcg_out_vreg3(s, INSN_VTST, q, vece, a0, a1, a1);
273
+ } else {
274
+ tcg_out_vreg3(s, INSN_VCEQ, q, vece, a0, a1, a2);
275
+ tcg_out_vreg2(s, INSN_VMVN, q, 0, a0, a0);
276
+ }
277
+ } else {
278
+ ARMInsn insn;
279
+
280
+ if (const_args[2]) {
281
+ insn = vec_cmp0_insn[cond];
282
+ if (insn) {
283
+ tcg_out_vreg2(s, insn, q, vece, a0, a1);
284
+ return;
285
+ }
286
+ tcg_out_dupi_vec(s, type, MO_8, TCG_VEC_TMP, 0);
287
+ a2 = TCG_VEC_TMP;
288
+ }
289
+ insn = vec_cmp_insn[cond];
290
+ if (insn == 0) {
291
+ TCGArg t;
292
+ t = a1, a1 = a2, a2 = t;
293
+ cond = tcg_swap_cond(cond);
294
+ insn = vec_cmp_insn[cond];
295
+ tcg_debug_assert(insn != 0);
296
+ }
297
+ tcg_out_vreg3(s, insn, q, vece, a0, a1, a2);
298
+ }
299
+ }
300
+ return;
301
+
302
+ case INDEX_op_mov_vec: /* Always emitted via tcg_out_mov. */
303
+ case INDEX_op_dup_vec: /* Always emitted via tcg_out_dup_vec. */
304
+ default:
82
+ default:
305
+ g_assert_not_reached();
83
+ g_assert_not_reached();
84
}
85
86
prefixes = 0;
87
@@ -XXX,XX +XXX,XX @@ static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
88
{
89
DisasContext *dc = container_of(dcbase, DisasContext, base);
90
91
+ dc->prev_insn_end = tcg_last_op();
92
tcg_gen_insn_start(dc->base.pc_next, dc->cc_op);
93
}
94
95
@@ -XXX,XX +XXX,XX @@ static void i386_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
96
#endif
97
98
pc_next = disas_insn(dc, cpu);
99
-
100
- if (dc->flags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK)) {
101
- /* if single step mode, we generate only one instruction and
102
- generate an exception */
103
- /* if irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
104
- the flag and abort the translation to give the irqs a
105
- chance to happen */
106
- dc->base.is_jmp = DISAS_TOO_MANY;
107
- } else if ((tb_cflags(dc->base.tb) & CF_USE_ICOUNT)
108
- && ((pc_next & TARGET_PAGE_MASK)
109
- != ((pc_next + TARGET_MAX_INSN_SIZE - 1)
110
- & TARGET_PAGE_MASK)
111
- || (pc_next & ~TARGET_PAGE_MASK) == 0)) {
112
- /* Do not cross the boundary of the pages in icount mode,
113
- it can cause an exception. Do it only when boundary is
114
- crossed by the first instruction in the block.
115
- If current instruction already crossed the bound - it's ok,
116
- because an exception hasn't stopped this code.
117
- */
118
- dc->base.is_jmp = DISAS_TOO_MANY;
119
- } else if ((pc_next - dc->base.pc_first) >= (TARGET_PAGE_SIZE - 32)) {
120
- dc->base.is_jmp = DISAS_TOO_MANY;
121
- }
122
-
123
dc->base.pc_next = pc_next;
124
+
125
+ if (dc->base.is_jmp == DISAS_NEXT) {
126
+ if (dc->flags & (HF_TF_MASK | HF_INHIBIT_IRQ_MASK)) {
127
+ /*
128
+ * If single step mode, we generate only one instruction and
129
+ * generate an exception.
130
+ * If irq were inhibited with HF_INHIBIT_IRQ_MASK, we clear
131
+ * the flag and abort the translation to give the irqs a
132
+ * chance to happen.
133
+ */
134
+ dc->base.is_jmp = DISAS_TOO_MANY;
135
+ } else if (!is_same_page(&dc->base, pc_next)) {
136
+ dc->base.is_jmp = DISAS_TOO_MANY;
137
+ }
306
+ }
138
+ }
307
}
139
}
308
140
309
int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
141
static void i386_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
310
{
142
diff --git a/tests/tcg/x86_64/noexec.c b/tests/tcg/x86_64/noexec.c
311
- return 0;
143
new file mode 100644
312
+ switch (opc) {
144
index XXXXXXX..XXXXXXX
313
+ case INDEX_op_add_vec:
145
--- /dev/null
314
+ case INDEX_op_sub_vec:
146
+++ b/tests/tcg/x86_64/noexec.c
315
+ case INDEX_op_and_vec:
147
@@ -XXX,XX +XXX,XX @@
316
+ case INDEX_op_or_vec:
148
+#include "../multiarch/noexec.c.inc"
317
+ case INDEX_op_xor_vec:
149
+
318
+ return 1;
150
+static void *arch_mcontext_pc(const mcontext_t *ctx)
319
+ case INDEX_op_cmp_vec:
151
+{
320
+ return vece < MO_64;
152
+ return (void *)ctx->gregs[REG_RIP];
321
+ default:
153
+}
322
+ return 0;
154
+
323
+ }
155
+int arch_mcontext_arg(const mcontext_t *ctx)
324
}
156
+{
325
157
+ return ctx->gregs[REG_RDI];
326
void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece,
158
+}
159
+
160
+static void arch_flush(void *p, int len)
161
+{
162
+}
163
+
164
+extern char noexec_1[];
165
+extern char noexec_2[];
166
+extern char noexec_end[];
167
+
168
+asm("noexec_1:\n"
169
+ " movq $1,%rdi\n" /* %rdi is 0 on entry, set 1. */
170
+ "noexec_2:\n"
171
+ " movq $2,%rdi\n" /* %rdi is 0/1; set 2. */
172
+ " ret\n"
173
+ "noexec_end:");
174
+
175
+int main(void)
176
+{
177
+ struct noexec_test noexec_tests[] = {
178
+ {
179
+ .name = "fallthrough",
180
+ .test_code = noexec_1,
181
+ .test_len = noexec_end - noexec_1,
182
+ .page_ofs = noexec_1 - noexec_2,
183
+ .entry_ofs = noexec_1 - noexec_2,
184
+ .expected_si_ofs = 0,
185
+ .expected_pc_ofs = 0,
186
+ .expected_arg = 1,
187
+ },
188
+ {
189
+ .name = "jump",
190
+ .test_code = noexec_1,
191
+ .test_len = noexec_end - noexec_1,
192
+ .page_ofs = noexec_1 - noexec_2,
193
+ .entry_ofs = 0,
194
+ .expected_si_ofs = 0,
195
+ .expected_pc_ofs = 0,
196
+ .expected_arg = 0,
197
+ },
198
+ {
199
+ .name = "fallthrough [cross]",
200
+ .test_code = noexec_1,
201
+ .test_len = noexec_end - noexec_1,
202
+ .page_ofs = noexec_1 - noexec_2 - 2,
203
+ .entry_ofs = noexec_1 - noexec_2 - 2,
204
+ .expected_si_ofs = 0,
205
+ .expected_pc_ofs = -2,
206
+ .expected_arg = 1,
207
+ },
208
+ {
209
+ .name = "jump [cross]",
210
+ .test_code = noexec_1,
211
+ .test_len = noexec_end - noexec_1,
212
+ .page_ofs = noexec_1 - noexec_2 - 2,
213
+ .entry_ofs = -2,
214
+ .expected_si_ofs = 0,
215
+ .expected_pc_ofs = -2,
216
+ .expected_arg = 0,
217
+ },
218
+ };
219
+
220
+ return test_noexec(noexec_tests,
221
+ sizeof(noexec_tests) / sizeof(noexec_tests[0]));
222
+}
223
diff --git a/tests/tcg/x86_64/Makefile.target b/tests/tcg/x86_64/Makefile.target
224
index XXXXXXX..XXXXXXX 100644
225
--- a/tests/tcg/x86_64/Makefile.target
226
+++ b/tests/tcg/x86_64/Makefile.target
227
@@ -XXX,XX +XXX,XX @@ include $(SRC_PATH)/tests/tcg/i386/Makefile.target
228
229
ifeq ($(filter %-linux-user, $(TARGET)),$(TARGET))
230
X86_64_TESTS += vsyscall
231
+X86_64_TESTS += noexec
232
TESTS=$(MULTIARCH_TESTS) $(X86_64_TESTS) test-x86_64
233
else
234
TESTS=$(MULTIARCH_TESTS)
235
@@ -XXX,XX +XXX,XX @@ test-x86_64: LDFLAGS+=-lm -lc
236
test-x86_64: test-i386.c test-i386.h test-i386-shift.h test-i386-muldiv.h
237
    $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
238
239
-vsyscall: $(SRC_PATH)/tests/tcg/x86_64/vsyscall.c
240
+%: $(SRC_PATH)/tests/tcg/x86_64/%.c
241
    $(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
327
--
242
--
328
2.25.1
243
2.34.1
329
330
diff view generated by jsdifflib
1
This consists of the three immediate shifts: shli, shri, sari.
1
These will be useful in properly ending the TB.
2
2
3
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
3
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
4
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
5
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
4
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
5
---
7
---
6
tcg/arm/tcg-target.h | 2 +-
8
target/riscv/translate.c | 10 +++++++++-
7
tcg/arm/tcg-target.c.inc | 27 +++++++++++++++++++++++++++
9
1 file changed, 9 insertions(+), 1 deletion(-)
8
2 files changed, 28 insertions(+), 1 deletion(-)
9
10
10
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
11
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
11
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
12
--- a/tcg/arm/tcg-target.h
13
--- a/target/riscv/translate.c
13
+++ b/tcg/arm/tcg-target.h
14
+++ b/target/riscv/translate.c
14
@@ -XXX,XX +XXX,XX @@ extern bool use_neon_instructions;
15
@@ -XXX,XX +XXX,XX @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
15
#define TCG_TARGET_HAS_roti_vec 0
16
/* Include decoders for factored-out extensions */
16
#define TCG_TARGET_HAS_rots_vec 0
17
#include "decode-XVentanaCondOps.c.inc"
17
#define TCG_TARGET_HAS_rotv_vec 0
18
18
-#define TCG_TARGET_HAS_shi_vec 0
19
+/* The specification allows for longer insns, but not supported by qemu. */
19
+#define TCG_TARGET_HAS_shi_vec 1
20
+#define MAX_INSN_LEN 4
20
#define TCG_TARGET_HAS_shs_vec 0
21
#define TCG_TARGET_HAS_shv_vec 0
22
#define TCG_TARGET_HAS_mul_vec 0
23
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
24
index XXXXXXX..XXXXXXX 100644
25
--- a/tcg/arm/tcg-target.c.inc
26
+++ b/tcg/arm/tcg-target.c.inc
27
@@ -XXX,XX +XXX,XX @@ typedef enum {
28
INSN_VCGE_U = 0xf3000310,
29
INSN_VCGT_U = 0xf3000300,
30
31
+ INSN_VSHLI = 0xf2800510, /* VSHL (immediate) */
32
+ INSN_VSARI = 0xf2800010, /* VSHR.S */
33
+ INSN_VSHRI = 0xf3800010, /* VSHR.U */
34
+
21
+
35
INSN_VTST = 0xf2000810,
22
+static inline int insn_len(uint16_t first_word)
36
37
INSN_VDUP_G = 0xee800b10, /* VDUP (ARM core register) */
38
@@ -XXX,XX +XXX,XX @@ static void tcg_out_vmovi(TCGContext *s, TCGReg rd,
39
| (extract32(imm8, 7, 1) << 24));
40
}
41
42
+static void tcg_out_vshifti(TCGContext *s, ARMInsn insn, int q,
43
+ TCGReg rd, TCGReg rm, int l_imm6)
44
+{
23
+{
45
+ tcg_out32(s, insn | (q << 6) | encode_vd(rd) | encode_vm(rm) |
24
+ return (first_word & 3) == 3 ? 4 : 2;
46
+ (extract32(l_imm6, 6, 1) << 7) |
47
+ (extract32(l_imm6, 0, 6) << 16));
48
+}
25
+}
49
+
26
+
50
static void tcg_out_vldst(TCGContext *s, ARMInsn insn,
27
static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
51
TCGReg rd, TCGReg rn, int offset)
52
{
28
{
53
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
29
/*
54
case INDEX_op_abs_vec:
30
@@ -XXX,XX +XXX,XX @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
55
case INDEX_op_neg_vec:
31
};
56
case INDEX_op_not_vec:
32
57
+ case INDEX_op_shli_vec:
33
/* Check for compressed insn */
58
+ case INDEX_op_shri_vec:
34
- if (extract16(opcode, 0, 2) != 3) {
59
+ case INDEX_op_sari_vec:
35
+ if (insn_len(opcode) == 2) {
60
return C_O1_I1(w, w);
36
if (!has_ext(ctx, RVC)) {
61
case INDEX_op_dup2_vec:
37
gen_exception_illegal(ctx);
62
case INDEX_op_add_vec:
38
} else {
63
@@ -XXX,XX +XXX,XX @@ static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
64
case INDEX_op_xor_vec:
65
tcg_out_vreg3(s, INSN_VEOR, q, 0, a0, a1, a2);
66
return;
67
+ case INDEX_op_shli_vec:
68
+ tcg_out_vshifti(s, INSN_VSHLI, q, a0, a1, a2 + (8 << vece));
69
+ return;
70
+ case INDEX_op_shri_vec:
71
+ tcg_out_vshifti(s, INSN_VSHRI, q, a0, a1, (16 << vece) - a2);
72
+ return;
73
+ case INDEX_op_sari_vec:
74
+ tcg_out_vshifti(s, INSN_VSARI, q, a0, a1, (16 << vece) - a2);
75
+ return;
76
77
case INDEX_op_andc_vec:
78
if (!const_args[2]) {
79
@@ -XXX,XX +XXX,XX @@ int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
80
case INDEX_op_orc_vec:
81
case INDEX_op_xor_vec:
82
case INDEX_op_not_vec:
83
+ case INDEX_op_shli_vec:
84
+ case INDEX_op_shri_vec:
85
+ case INDEX_op_sari_vec:
86
return 1;
87
case INDEX_op_abs_vec:
88
case INDEX_op_cmp_vec:
89
--
39
--
90
2.25.1
40
2.34.1
91
92
diff view generated by jsdifflib
1
Add registers and function stubs. The functionality
1
Right now the translator stops right *after* the end of a page, which
2
is disabled via use_neon_instructions defined to 0.
2
breaks reporting of fault locations when the last instruction of a
3
multi-insn translation block crosses a page boundary.
3
4
4
We must still include results for the mandatory opcodes in
5
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1155
5
tcg_target_op_def, as all opcodes are checked during tcg init.
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
7
Acked-by: Ilya Leoshkevich <iii@linux.ibm.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Tested-by: Ilya Leoshkevich <iii@linux.ibm.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
---
10
---
10
tcg/arm/tcg-target-con-set.h | 4 ++
11
target/riscv/translate.c | 17 +++++--
11
tcg/arm/tcg-target-con-str.h | 1 +
12
tests/tcg/riscv64/noexec.c | 79 +++++++++++++++++++++++++++++++
12
tcg/arm/tcg-target.h | 48 ++++++++++++--
13
tests/tcg/riscv64/Makefile.target | 1 +
13
tcg/arm/tcg-target.opc.h | 12 ++++
14
3 files changed, 93 insertions(+), 4 deletions(-)
14
tcg/arm/tcg-target.c.inc | 117 +++++++++++++++++++++++++++++------
15
create mode 100644 tests/tcg/riscv64/noexec.c
15
5 files changed, 158 insertions(+), 24 deletions(-)
16
create mode 100644 tcg/arm/tcg-target.opc.h
17
16
18
diff --git a/tcg/arm/tcg-target-con-set.h b/tcg/arm/tcg-target-con-set.h
17
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
19
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
20
--- a/tcg/arm/tcg-target-con-set.h
19
--- a/target/riscv/translate.c
21
+++ b/tcg/arm/tcg-target-con-set.h
20
+++ b/target/riscv/translate.c
22
@@ -XXX,XX +XXX,XX @@ C_O0_I1(r)
21
@@ -XXX,XX +XXX,XX @@ static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
23
C_O0_I2(r, r)
22
}
24
C_O0_I2(r, rIN)
23
ctx->nftemp = 0;
25
C_O0_I2(s, s)
24
26
+C_O0_I2(w, r)
25
+ /* Only the first insn within a TB is allowed to cross a page boundary. */
27
C_O0_I3(s, s, s)
26
if (ctx->base.is_jmp == DISAS_NEXT) {
28
C_O0_I4(r, r, rI, rI)
27
- target_ulong page_start;
29
C_O0_I4(s, s, s, s)
28
-
30
C_O1_I1(r, l)
29
- page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
31
C_O1_I1(r, r)
30
- if (ctx->base.pc_next - page_start >= TARGET_PAGE_SIZE) {
32
+C_O1_I1(w, r)
31
+ if (!is_same_page(&ctx->base, ctx->base.pc_next)) {
33
+C_O1_I1(w, wr)
32
ctx->base.is_jmp = DISAS_TOO_MANY;
34
C_O1_I2(r, 0, rZ)
33
+ } else {
35
C_O1_I2(r, l, l)
34
+ unsigned page_ofs = ctx->base.pc_next & ~TARGET_PAGE_MASK;
36
C_O1_I2(r, r, r)
37
@@ -XXX,XX +XXX,XX @@ C_O1_I2(r, r, rIK)
38
C_O1_I2(r, r, rIN)
39
C_O1_I2(r, r, ri)
40
C_O1_I2(r, rZ, rZ)
41
+C_O1_I2(w, w, w)
42
C_O1_I4(r, r, r, rI, rI)
43
C_O1_I4(r, r, rIN, rIK, 0)
44
C_O2_I1(r, r, l)
45
diff --git a/tcg/arm/tcg-target-con-str.h b/tcg/arm/tcg-target-con-str.h
46
index XXXXXXX..XXXXXXX 100644
47
--- a/tcg/arm/tcg-target-con-str.h
48
+++ b/tcg/arm/tcg-target-con-str.h
49
@@ -XXX,XX +XXX,XX @@
50
REGS('r', ALL_GENERAL_REGS)
51
REGS('l', ALL_QLOAD_REGS)
52
REGS('s', ALL_QSTORE_REGS)
53
+REGS('w', ALL_VECTOR_REGS)
54
55
/*
56
* Define constraint letters for constants:
57
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
58
index XXXXXXX..XXXXXXX 100644
59
--- a/tcg/arm/tcg-target.h
60
+++ b/tcg/arm/tcg-target.h
61
@@ -XXX,XX +XXX,XX @@ typedef enum {
62
TCG_REG_R13,
63
TCG_REG_R14,
64
TCG_REG_PC,
65
+
35
+
66
+ TCG_REG_Q0,
36
+ if (page_ofs > TARGET_PAGE_SIZE - MAX_INSN_LEN) {
67
+ TCG_REG_Q1,
37
+ uint16_t next_insn = cpu_lduw_code(env, ctx->base.pc_next);
68
+ TCG_REG_Q2,
38
+ int len = insn_len(next_insn);
69
+ TCG_REG_Q3,
70
+ TCG_REG_Q4,
71
+ TCG_REG_Q5,
72
+ TCG_REG_Q6,
73
+ TCG_REG_Q7,
74
+ TCG_REG_Q8,
75
+ TCG_REG_Q9,
76
+ TCG_REG_Q10,
77
+ TCG_REG_Q11,
78
+ TCG_REG_Q12,
79
+ TCG_REG_Q13,
80
+ TCG_REG_Q14,
81
+ TCG_REG_Q15,
82
+
39
+
83
+ TCG_AREG0 = TCG_REG_R6,
40
+ if (!is_same_page(&ctx->base, ctx->base.pc_next + len)) {
84
+ TCG_REG_CALL_STACK = TCG_REG_R13,
41
+ ctx->base.is_jmp = DISAS_TOO_MANY;
85
} TCGReg;
42
+ }
86
43
+ }
87
-#define TCG_TARGET_NB_REGS 16
44
}
88
+#define TCG_TARGET_NB_REGS 32
45
}
89
46
}
90
#ifdef __ARM_ARCH_EXT_IDIV__
47
diff --git a/tests/tcg/riscv64/noexec.c b/tests/tcg/riscv64/noexec.c
91
#define use_idiv_instructions 1
92
#else
93
extern bool use_idiv_instructions;
94
#endif
95
-
96
+#define use_neon_instructions 0
97
98
/* used for function call generation */
99
-#define TCG_REG_CALL_STACK        TCG_REG_R13
100
#define TCG_TARGET_STACK_ALIGN        8
101
#define TCG_TARGET_CALL_ALIGN_ARGS    1
102
#define TCG_TARGET_CALL_STACK_OFFSET    0
103
@@ -XXX,XX +XXX,XX @@ extern bool use_idiv_instructions;
104
#define TCG_TARGET_HAS_direct_jump 0
105
#define TCG_TARGET_HAS_qemu_st8_i32 0
106
107
-enum {
108
- TCG_AREG0 = TCG_REG_R6,
109
-};
110
+#define TCG_TARGET_HAS_v64 use_neon_instructions
111
+#define TCG_TARGET_HAS_v128 use_neon_instructions
112
+#define TCG_TARGET_HAS_v256 0
113
+
114
+#define TCG_TARGET_HAS_andc_vec 0
115
+#define TCG_TARGET_HAS_orc_vec 0
116
+#define TCG_TARGET_HAS_not_vec 0
117
+#define TCG_TARGET_HAS_neg_vec 0
118
+#define TCG_TARGET_HAS_abs_vec 0
119
+#define TCG_TARGET_HAS_roti_vec 0
120
+#define TCG_TARGET_HAS_rots_vec 0
121
+#define TCG_TARGET_HAS_rotv_vec 0
122
+#define TCG_TARGET_HAS_shi_vec 0
123
+#define TCG_TARGET_HAS_shs_vec 0
124
+#define TCG_TARGET_HAS_shv_vec 0
125
+#define TCG_TARGET_HAS_mul_vec 0
126
+#define TCG_TARGET_HAS_sat_vec 0
127
+#define TCG_TARGET_HAS_minmax_vec 0
128
+#define TCG_TARGET_HAS_bitsel_vec 0
129
+#define TCG_TARGET_HAS_cmpsel_vec 0
130
131
#define TCG_TARGET_DEFAULT_MO (0)
132
#define TCG_TARGET_HAS_MEMORY_BSWAP 1
133
diff --git a/tcg/arm/tcg-target.opc.h b/tcg/arm/tcg-target.opc.h
134
new file mode 100644
48
new file mode 100644
135
index XXXXXXX..XXXXXXX
49
index XXXXXXX..XXXXXXX
136
--- /dev/null
50
--- /dev/null
137
+++ b/tcg/arm/tcg-target.opc.h
51
+++ b/tests/tcg/riscv64/noexec.c
138
@@ -XXX,XX +XXX,XX @@
52
@@ -XXX,XX +XXX,XX @@
139
+/*
53
+#include "../multiarch/noexec.c.inc"
140
+ * Copyright (c) 2019 Linaro
141
+ *
142
+ * This work is licensed under the terms of the GNU GPL, version 2 or
143
+ * (at your option) any later version.
144
+ *
145
+ * See the COPYING file in the top-level directory for details.
146
+ *
147
+ * Target-specific opcodes for host vector expansion. These will be
148
+ * emitted by tcg_expand_vec_op. For those familiar with GCC internals,
149
+ * consider these to be UNSPEC with names.
150
+ */
151
diff --git a/tcg/arm/tcg-target.c.inc b/tcg/arm/tcg-target.c.inc
152
index XXXXXXX..XXXXXXX 100644
153
--- a/tcg/arm/tcg-target.c.inc
154
+++ b/tcg/arm/tcg-target.c.inc
155
@@ -XXX,XX +XXX,XX @@ bool use_idiv_instructions;
156
157
#ifdef CONFIG_DEBUG_TCG
158
static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
159
- "%r0",
160
- "%r1",
161
- "%r2",
162
- "%r3",
163
- "%r4",
164
- "%r5",
165
- "%r6",
166
- "%r7",
167
- "%r8",
168
- "%r9",
169
- "%r10",
170
- "%r11",
171
- "%r12",
172
- "%r13",
173
- "%r14",
174
- "%pc",
175
+ "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
176
+ "%r8", "%r9", "%r10", "%r11", "%r12", "%sp", "%r14", "%pc",
177
+ "%q0", "%q1", "%q2", "%q3", "%q4", "%q5", "%q6", "%q7",
178
+ "%q8", "%q9", "%q10", "%q11", "%q12", "%q13", "%q14", "%q15",
179
};
180
#endif
181
182
@@ -XXX,XX +XXX,XX @@ static const int tcg_target_reg_alloc_order[] = {
183
TCG_REG_R3,
184
TCG_REG_R12,
185
TCG_REG_R14,
186
+
54
+
187
+ TCG_REG_Q0,
55
+static void *arch_mcontext_pc(const mcontext_t *ctx)
188
+ TCG_REG_Q1,
189
+ TCG_REG_Q2,
190
+ TCG_REG_Q3,
191
+ /* Q4 - Q7 are call-saved, and skipped. */
192
+ TCG_REG_Q8,
193
+ TCG_REG_Q9,
194
+ TCG_REG_Q10,
195
+ TCG_REG_Q11,
196
+ TCG_REG_Q12,
197
+ TCG_REG_Q13,
198
+ TCG_REG_Q14,
199
+ TCG_REG_Q15,
200
};
201
202
static const int tcg_target_call_iarg_regs[4] = {
203
@@ -XXX,XX +XXX,XX @@ static const int tcg_target_call_oarg_regs[2] = {
204
};
205
206
#define TCG_REG_TMP TCG_REG_R12
207
+#define TCG_VEC_TMP TCG_REG_Q15
208
209
enum arm_cond_code_e {
210
COND_EQ = 0x0,
211
@@ -XXX,XX +XXX,XX @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
212
#define TCG_CT_CONST_ZERO 0x800
213
214
#define ALL_GENERAL_REGS 0xffffu
215
+#define ALL_VECTOR_REGS 0xffff0000u
216
217
/*
218
* r0-r2 will be overwritten when reading the tlb entry (softmmu only)
219
@@ -XXX,XX +XXX,XX @@ static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
220
case INDEX_op_qemu_st_i64:
221
return TARGET_LONG_BITS == 32 ? C_O0_I3(s, s, s) : C_O0_I4(s, s, s, s);
222
223
+ case INDEX_op_st_vec:
224
+ return C_O0_I2(w, r);
225
+ case INDEX_op_ld_vec:
226
+ case INDEX_op_dupm_vec:
227
+ return C_O1_I1(w, r);
228
+ case INDEX_op_dup_vec:
229
+ return C_O1_I1(w, wr);
230
+ case INDEX_op_dup2_vec:
231
+ case INDEX_op_add_vec:
232
+ case INDEX_op_sub_vec:
233
+ case INDEX_op_xor_vec:
234
+ case INDEX_op_or_vec:
235
+ case INDEX_op_and_vec:
236
+ case INDEX_op_cmp_vec:
237
+ return C_O1_I2(w, w, w);
238
+
239
default:
240
g_assert_not_reached();
241
}
242
@@ -XXX,XX +XXX,XX @@ static void tcg_target_init(TCGContext *s)
243
{
244
/* Only probe for the platform and capabilities if we havn't already
245
determined maximum values at compile time. */
246
-#ifndef use_idiv_instructions
247
+#if !defined(use_idiv_instructions) || !defined(use_neon_instructions)
248
{
249
unsigned long hwcap = qemu_getauxval(AT_HWCAP);
250
+#ifndef use_idiv_instructions
251
use_idiv_instructions = (hwcap & HWCAP_ARM_IDIVA) != 0;
252
+#endif
253
+#ifndef use_neon_instructions
254
+ use_neon_instructions = (hwcap & HWCAP_ARM_NEON) != 0;
255
+#endif
256
}
257
#endif
258
+
259
if (__ARM_ARCH < 7) {
260
const char *pl = (const char *)qemu_getauxval(AT_PLATFORM);
261
if (pl != NULL && pl[0] == 'v' && pl[1] >= '4' && pl[1] <= '9') {
262
@@ -XXX,XX +XXX,XX @@ static void tcg_target_init(TCGContext *s)
263
}
264
}
265
266
- tcg_target_available_regs[TCG_TYPE_I32] = 0xffff;
267
+ tcg_target_available_regs[TCG_TYPE_I32] = ALL_GENERAL_REGS;
268
269
tcg_target_call_clobber_regs = 0;
270
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R0);
271
@@ -XXX,XX +XXX,XX @@ static void tcg_target_init(TCGContext *s)
272
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R12);
273
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R14);
274
275
+ if (use_neon_instructions) {
276
+ tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS;
277
+ tcg_target_available_regs[TCG_TYPE_V128] = ALL_VECTOR_REGS;
278
+
279
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q0);
280
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q1);
281
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q2);
282
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q3);
283
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q8);
284
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q9);
285
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q10);
286
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q11);
287
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q12);
288
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q13);
289
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q14);
290
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_Q15);
291
+ }
292
+
293
s->reserved_regs = 0;
294
tcg_regset_set_reg(s->reserved_regs, TCG_REG_CALL_STACK);
295
tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP);
296
tcg_regset_set_reg(s->reserved_regs, TCG_REG_PC);
297
+ tcg_regset_set_reg(s->reserved_regs, TCG_VEC_TMP);
298
}
299
300
static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
301
@@ -XXX,XX +XXX,XX @@ static inline void tcg_out_movi(TCGContext *s, TCGType type,
302
tcg_out_movi32(s, COND_AL, ret, arg);
303
}
304
305
+static bool tcg_out_dup_vec(TCGContext *s, TCGType type, unsigned vece,
306
+ TCGReg rd, TCGReg rs)
307
+{
56
+{
308
+ g_assert_not_reached();
57
+ return (void *)ctx->__gregs[REG_PC];
309
+}
58
+}
310
+
59
+
311
+static bool tcg_out_dupm_vec(TCGContext *s, TCGType type, unsigned vece,
60
+static int arch_mcontext_arg(const mcontext_t *ctx)
312
+ TCGReg rd, TCGReg base, intptr_t offset)
313
+{
61
+{
314
+ g_assert_not_reached();
62
+ return ctx->__gregs[REG_A0];
315
+}
63
+}
316
+
64
+
317
+static void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece,
65
+static void arch_flush(void *p, int len)
318
+ TCGReg rd, int64_t v64)
319
+{
66
+{
320
+ g_assert_not_reached();
67
+ __builtin___clear_cache(p, p + len);
321
+}
68
+}
322
+
69
+
323
+static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
70
+extern char noexec_1[];
324
+ unsigned vecl, unsigned vece,
71
+extern char noexec_2[];
325
+ const TCGArg *args, const int *const_args)
72
+extern char noexec_end[];
73
+
74
+asm(".option push\n"
75
+ ".option norvc\n"
76
+ "noexec_1:\n"
77
+ " li a0,1\n" /* a0 is 0 on entry, set 1. */
78
+ "noexec_2:\n"
79
+ " li a0,2\n" /* a0 is 0/1; set 2. */
80
+ " ret\n"
81
+ "noexec_end:\n"
82
+ ".option pop");
83
+
84
+int main(void)
326
+{
85
+{
327
+ g_assert_not_reached();
86
+ struct noexec_test noexec_tests[] = {
87
+ {
88
+ .name = "fallthrough",
89
+ .test_code = noexec_1,
90
+ .test_len = noexec_end - noexec_1,
91
+ .page_ofs = noexec_1 - noexec_2,
92
+ .entry_ofs = noexec_1 - noexec_2,
93
+ .expected_si_ofs = 0,
94
+ .expected_pc_ofs = 0,
95
+ .expected_arg = 1,
96
+ },
97
+ {
98
+ .name = "jump",
99
+ .test_code = noexec_1,
100
+ .test_len = noexec_end - noexec_1,
101
+ .page_ofs = noexec_1 - noexec_2,
102
+ .entry_ofs = 0,
103
+ .expected_si_ofs = 0,
104
+ .expected_pc_ofs = 0,
105
+ .expected_arg = 0,
106
+ },
107
+ {
108
+ .name = "fallthrough [cross]",
109
+ .test_code = noexec_1,
110
+ .test_len = noexec_end - noexec_1,
111
+ .page_ofs = noexec_1 - noexec_2 - 2,
112
+ .entry_ofs = noexec_1 - noexec_2 - 2,
113
+ .expected_si_ofs = 0,
114
+ .expected_pc_ofs = -2,
115
+ .expected_arg = 1,
116
+ },
117
+ {
118
+ .name = "jump [cross]",
119
+ .test_code = noexec_1,
120
+ .test_len = noexec_end - noexec_1,
121
+ .page_ofs = noexec_1 - noexec_2 - 2,
122
+ .entry_ofs = -2,
123
+ .expected_si_ofs = 0,
124
+ .expected_pc_ofs = -2,
125
+ .expected_arg = 0,
126
+ },
127
+ };
128
+
129
+ return test_noexec(noexec_tests,
130
+ sizeof(noexec_tests) / sizeof(noexec_tests[0]));
328
+}
131
+}
329
+
132
diff --git a/tests/tcg/riscv64/Makefile.target b/tests/tcg/riscv64/Makefile.target
330
+int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
133
index XXXXXXX..XXXXXXX 100644
331
+{
134
--- a/tests/tcg/riscv64/Makefile.target
332
+ return 0;
135
+++ b/tests/tcg/riscv64/Makefile.target
333
+}
136
@@ -XXX,XX +XXX,XX @@
334
+
137
335
+void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece,
138
VPATH += $(SRC_PATH)/tests/tcg/riscv64
336
+ TCGArg a0, ...)
139
TESTS += test-div
337
+{
140
+TESTS += noexec
338
+ g_assert_not_reached();
339
+}
340
+
341
static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
342
{
343
int i;
344
--
141
--
345
2.25.1
142
2.34.1
346
347
diff view generated by jsdifflib