1
First pullreq for arm of the 4.1 series, since I'm back from
1
Mostly this is patches from me and RTH cleaning up and doing
2
holiday now. This is mostly my M-profile FPU series and Philippe's
2
more decodetree conversion for AArch32 Neon. The major new feature
3
devices.h cleanup. I have a pile of other patchsets to work through
3
is Dongjiu Geng's patchset to report host memory errors to KVM guests;
4
in my to-review folder, but 42 patches is definitely quite
4
also a new aspeed board from Patrick Williams.
5
big enough to send now...
6
5
7
thanks
6
thanks
8
-- PMM
7
-- PMM
9
8
10
The following changes since commit 413a99a92c13ec408dcf2adaa87918dc81e890c8:
9
The following changes since commit 035b448b84f3557206abc44d786c5d3db2638f7d:
11
10
12
Add Nios II semihosting support. (2019-04-29 16:09:51 +0100)
11
Merge remote-tracking branch 'remotes/gkurz/tags/9p-next-2020-05-14' into staging (2020-05-14 10:58:30 +0100)
13
12
14
are available in the Git repository at:
13
are available in the Git repository at:
15
14
16
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190429
15
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200514
17
16
18
for you to fetch changes up to 437cc27ddfded3bbab6afd5ac1761e0e195edba7:
17
for you to fetch changes up to e95485f85657be21135c17a9226e297c21e73360:
19
18
20
hw/devices: Move SMSC 91C111 declaration into a new header (2019-04-29 17:57:21 +0100)
19
target/arm: Convert NEON VFMA, VFMS 3-reg-same insns to decodetree (2020-05-14 15:03:09 +0100)
21
20
22
----------------------------------------------------------------
21
----------------------------------------------------------------
23
target-arm queue:
22
target-arm queue:
24
* remove "bag of random stuff" hw/devices.h header
23
* target/arm: Use correct GDB XML for M-profile cores
25
* implement FPU for Cortex-M and enable it for Cortex-M4 and -M33
24
* target/arm: Code cleanup to use gvec APIs better
26
* hw/dma: Compile the bcm2835_dma device as common object
25
* aspeed: Add support for the sonorapass-bmc board
27
* configure: Remove --source-path option
26
* target/arm: Support reporting KVM host memory errors
28
* hw/ssi/xilinx_spips: Avoid variable length array
27
to the guest via ACPI notifications
29
* hw/arm/smmuv3: Remove SMMUNotifierNode
28
* target/arm: Finish conversion of Neon 3-reg-same insns to decodetree
30
29
31
----------------------------------------------------------------
30
----------------------------------------------------------------
32
Eric Auger (1):
31
Dongjiu Geng (10):
33
hw/arm/smmuv3: Remove SMMUNotifierNode
32
acpi: nvdimm: change NVDIMM_UUID_LE to a common macro
33
hw/arm/virt: Introduce a RAS machine option
34
docs: APEI GHES generation and CPER record description
35
ACPI: Build related register address fields via hardware error fw_cfg blob
36
ACPI: Build Hardware Error Source Table
37
ACPI: Record the Generic Error Status Block address
38
KVM: Move hwpoison page related functions into kvm-all.c
39
ACPI: Record Generic Error Status Block(GESB) table
40
target-arm: kvm64: handle SIGBUS signal from kernel or KVM
41
MAINTAINERS: Add ACPI/HEST/GHES entries
34
42
35
Peter Maydell (28):
43
Patrick Williams (1):
36
hw/ssi/xilinx_spips: Avoid variable length array
44
aspeed: Add support for the sonorapass-bmc board
37
configure: Remove --source-path option
38
target/arm: Make sure M-profile FPSCR RES0 bits are not settable
39
hw/intc/armv7m_nvic: Allow reading of M-profile MVFR* registers
40
target/arm: Implement dummy versions of M-profile FP-related registers
41
target/arm: Disable most VFP sysregs for M-profile
42
target/arm: Honour M-profile FP enable bits
43
target/arm: Decode FP instructions for M profile
44
target/arm: Clear CONTROL_S.SFPA in SG insn if FPU present
45
target/arm: Handle SFPA and FPCA bits in reads and writes of CONTROL
46
target/arm/helper: don't return early for STKOF faults during stacking
47
target/arm: Handle floating point registers in exception entry
48
target/arm: Implement v7m_update_fpccr()
49
target/arm: Clear CONTROL.SFPA in BXNS and BLXNS
50
target/arm: Clean excReturn bits when tail chaining
51
target/arm: Allow for floating point in callee stack integrity check
52
target/arm: Handle floating point registers in exception return
53
target/arm: Move NS TBFLAG from bit 19 to bit 6
54
target/arm: Overlap VECSTRIDE and XSCALE_CPAR TB flags
55
target/arm: Set FPCCR.S when executing M-profile floating point insns
56
target/arm: Activate M-profile floating point context when FPCCR.ASPEN is set
57
target/arm: New helper function arm_v7m_mmu_idx_all()
58
target/arm: New function armv7m_nvic_set_pending_lazyfp()
59
target/arm: Add lazy-FP-stacking support to v7m_stack_write()
60
target/arm: Implement M-profile lazy FP state preservation
61
target/arm: Implement VLSTM for v7M CPUs with an FPU
62
target/arm: Implement VLLDM for v7M CPUs with an FPU
63
target/arm: Enable FPU for Cortex-M4 and Cortex-M33
64
45
65
Philippe Mathieu-Daudé (13):
46
Peter Maydell (18):
66
hw/dma: Compile the bcm2835_dma device as common object
47
target/arm: Use correct GDB XML for M-profile cores
67
hw/arm/aspeed: Use TYPE_TMP105/TYPE_PCA9552 instead of hardcoded string
48
target/arm: Convert Neon 3-reg-same VQRDMLAH/VQRDMLSH to decodetree
68
hw/arm/nseries: Use TYPE_TMP105 instead of hardcoded string
49
target/arm: Convert Neon 3-reg-same SHA to decodetree
69
hw/display/tc6393xb: Remove unused functions
50
target/arm: Convert Neon 64-bit element 3-reg-same insns
70
hw/devices: Move TC6393XB declarations into a new header
51
target/arm: Convert Neon VHADD 3-reg-same insns
71
hw/devices: Move Blizzard declarations into a new header
52
target/arm: Convert Neon VABA/VABD 3-reg-same to decodetree
72
hw/devices: Move CBus declarations into a new header
53
target/arm: Convert Neon VRHADD, VHSUB 3-reg-same insns to decodetree
73
hw/devices: Move Gamepad declarations into a new header
54
target/arm: Convert Neon VQSHL, VRSHL, VQRSHL 3-reg-same insns to decodetree
74
hw/devices: Move TI touchscreen declarations into a new header
55
target/arm: Convert Neon VPMAX/VPMIN 3-reg-same insns to decodetree
75
hw/devices: Move LAN9118 declarations into a new header
56
target/arm: Convert Neon VPADD 3-reg-same insns to decodetree
76
hw/net/ne2000-isa: Add guards to the header
57
target/arm: Convert Neon VQDMULH/VQRDMULH 3-reg-same to decodetree
77
hw/net/lan9118: Export TYPE_LAN9118 and use it instead of hardcoded string
58
target/arm: Convert Neon VADD, VSUB, VABD 3-reg-same insns to decodetree
78
hw/devices: Move SMSC 91C111 declaration into a new header
59
target/arm: Convert Neon VPMIN/VPMAX/VPADD float 3-reg-same insns to decodetree
60
target/arm: Convert Neon fp VMUL, VMLA, VMLS 3-reg-same insns to decodetree
61
target/arm: Convert Neon 3-reg-same compare insns to decodetree
62
target/arm: Move 'env' argument of recps_f32 and rsqrts_f32 helpers to usual place
63
target/arm: Convert Neon fp VMAX/VMIN/VMAXNM/VMINNM/VRECPS/VRSQRTS to decodetree
64
target/arm: Convert NEON VFMA, VFMS 3-reg-same insns to decodetree
79
65
80
configure | 10 +-
66
Richard Henderson (16):
81
hw/dma/Makefile.objs | 2 +-
67
target/arm: Create gen_gvec_[us]sra
82
include/hw/arm/omap.h | 6 +-
68
target/arm: Create gen_gvec_{u,s}{rshr,rsra}
83
include/hw/arm/smmu-common.h | 8 +-
69
target/arm: Create gen_gvec_{sri,sli}
84
include/hw/devices.h | 62 ---
70
target/arm: Remove unnecessary range check for VSHL
85
include/hw/display/blizzard.h | 22 ++
71
target/arm: Tidy handle_vec_simd_shri
86
include/hw/display/tc6393xb.h | 24 ++
72
target/arm: Create gen_gvec_{ceq,clt,cle,cgt,cge}0
87
include/hw/input/gamepad.h | 19 +
73
target/arm: Create gen_gvec_{mla,mls}
88
include/hw/input/tsc2xxx.h | 36 ++
74
target/arm: Swap argument order for VSHL during decode
89
include/hw/misc/cbus.h | 32 ++
75
target/arm: Create gen_gvec_{cmtst,ushl,sshl}
90
include/hw/net/lan9118.h | 21 +
76
target/arm: Create gen_gvec_{uqadd, sqadd, uqsub, sqsub}
91
include/hw/net/ne2000-isa.h | 6 +
77
target/arm: Remove fp_status from helper_{recpe, rsqrte}_u32
92
include/hw/net/smc91c111.h | 19 +
78
target/arm: Create gen_gvec_{qrdmla,qrdmls}
93
include/qemu/typedefs.h | 1 -
79
target/arm: Pass pointer to qc to qrdmla/qrdmls
94
target/arm/cpu.h | 95 ++++-
80
target/arm: Clear tail in gvec_fmul_idx_*, gvec_fmla_idx_*
95
target/arm/helper.h | 5 +
81
target/arm: Vectorize SABD/UABD
96
target/arm/translate.h | 3 +
82
target/arm: Vectorize SABA/UABA
97
hw/arm/aspeed.c | 13 +-
98
hw/arm/exynos4_boards.c | 3 +-
99
hw/arm/gumstix.c | 2 +-
100
hw/arm/integratorcp.c | 2 +-
101
hw/arm/kzm.c | 2 +-
102
hw/arm/mainstone.c | 2 +-
103
hw/arm/mps2-tz.c | 3 +-
104
hw/arm/mps2.c | 2 +-
105
hw/arm/nseries.c | 7 +-
106
hw/arm/palm.c | 2 +-
107
hw/arm/realview.c | 3 +-
108
hw/arm/smmu-common.c | 6 +-
109
hw/arm/smmuv3.c | 28 +-
110
hw/arm/stellaris.c | 2 +-
111
hw/arm/tosa.c | 2 +-
112
hw/arm/versatilepb.c | 2 +-
113
hw/arm/vexpress.c | 2 +-
114
hw/display/blizzard.c | 2 +-
115
hw/display/tc6393xb.c | 18 +-
116
hw/input/stellaris_input.c | 2 +-
117
hw/input/tsc2005.c | 2 +-
118
hw/input/tsc210x.c | 4 +-
119
hw/intc/armv7m_nvic.c | 261 +++++++++++++
120
hw/misc/cbus.c | 2 +-
121
hw/net/lan9118.c | 3 +-
122
hw/net/smc91c111.c | 2 +-
123
hw/ssi/xilinx_spips.c | 6 +-
124
target/arm/cpu.c | 20 +
125
target/arm/helper.c | 873 +++++++++++++++++++++++++++++++++++++++---
126
target/arm/machine.c | 16 +
127
target/arm/translate.c | 150 +++++++-
128
target/arm/vfp_helper.c | 8 +
129
MAINTAINERS | 7 +
130
50 files changed, 1595 insertions(+), 235 deletions(-)
131
delete mode 100644 include/hw/devices.h
132
create mode 100644 include/hw/display/blizzard.h
133
create mode 100644 include/hw/display/tc6393xb.h
134
create mode 100644 include/hw/input/gamepad.h
135
create mode 100644 include/hw/input/tsc2xxx.h
136
create mode 100644 include/hw/misc/cbus.h
137
create mode 100644 include/hw/net/lan9118.h
138
create mode 100644 include/hw/net/smc91c111.h
139
83
84
docs/specs/acpi_hest_ghes.rst | 110 ++
85
docs/specs/index.rst | 1 +
86
configure | 4 +-
87
default-configs/arm-softmmu.mak | 1 +
88
include/hw/acpi/aml-build.h | 1 +
89
include/hw/acpi/generic_event_device.h | 2 +
90
include/hw/acpi/ghes.h | 74 +
91
include/hw/arm/virt.h | 1 +
92
include/qemu/uuid.h | 27 +
93
include/sysemu/kvm.h | 3 +-
94
include/sysemu/kvm_int.h | 12 +
95
target/arm/cpu.h | 4 +
96
target/arm/helper.h | 78 +-
97
target/arm/internals.h | 5 +-
98
target/arm/translate.h | 84 +-
99
target/i386/cpu.h | 2 +
100
target/arm/neon-dp.decode | 119 +-
101
accel/kvm/kvm-all.c | 36 +
102
hw/acpi/aml-build.c | 2 +
103
hw/acpi/generic_event_device.c | 19 +
104
hw/acpi/ghes.c | 448 ++++++
105
hw/acpi/nvdimm.c | 10 +-
106
hw/arm/aspeed.c | 78 ++
107
hw/arm/virt-acpi-build.c | 15 +
108
hw/arm/virt.c | 23 +
109
target/arm/cpu_tcg.c | 1 +
110
target/arm/gdbstub.c | 22 +-
111
target/arm/helper.c | 2 +-
112
target/arm/kvm64.c | 77 ++
113
target/arm/neon_helper.c | 17 -
114
target/arm/tlb_helper.c | 2 +-
115
target/arm/translate-a64.c | 210 +--
116
target/arm/translate-neon.inc.c | 682 +++++++++-
117
target/arm/translate.c | 2349 +++++++++++++++++---------------
118
target/arm/vec_helper.c | 240 +++-
119
target/arm/vfp_helper.c | 9 +-
120
target/i386/kvm.c | 36 -
121
MAINTAINERS | 9 +
122
gdb-xml/arm-m-profile.xml | 27 +
123
hw/acpi/Kconfig | 4 +
124
hw/acpi/Makefile.objs | 1 +
125
41 files changed, 3402 insertions(+), 1445 deletions(-)
126
create mode 100644 docs/specs/acpi_hest_ghes.rst
127
create mode 100644 include/hw/acpi/ghes.h
128
create mode 100644 hw/acpi/ghes.c
129
create mode 100644 gdb-xml/arm-m-profile.xml
130
diff view generated by jsdifflib
1
Normally configure identifies the source path by looking
1
GDB's remote protocol requires M-profile cores to use the feature
2
at the location where the configure script itself exists.
2
name 'org.gnu.gdb.arm.m-profile' instead of the 'org.gnu.gdb.arm.core'
3
We also provide a --source-path option which lets the user
3
feature used for A- and R-profile cores. We weren't doing this, which
4
manually override this.
4
meant GDB treated our M-profile cores like A-profile ones. This mostly
5
doesn't matter, but for instance means that it doesn't correctly
6
handle backtraces where an M-profile exception frame is involved.
5
7
6
There isn't really an obvious use case for the --source-path
8
Ship a copy of GDB's arm-m-profile.xml and use it on the M-profile
7
option, and in commit 927128222b0a91f56c13a in 2017 we
9
cores. The integer registers have the same offsets as the
8
accidentally added some logic that looks at $source_path
10
arm-core.xml, but register 25 is the M-profile XPSR rather than the
9
before the command line option that overrides it has been
11
A-profile CPSR, so we need to update arm_cpu_gdb_read_register() and
10
processed.
12
arm_cpu_gdb_write_register() to handle XSPR reads and writes.
11
13
12
The fact that nobody complained suggests that there isn't
14
Fixes: https://bugs.launchpad.net/qemu/+bug/1877136
13
any use of this option and we aren't testing it either;
14
remove it. This allows us to move the "make $source_path
15
absolute" logic up so that there is no window in the script
16
where $source_path is set but not yet absolute.
17
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
16
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Message-id: 20190318134019.23729-1-peter.maydell@linaro.org
17
Message-id: 20200507134755.13997-1-peter.maydell@linaro.org
21
---
18
---
22
configure | 10 ++--------
19
configure | 4 ++--
23
1 file changed, 2 insertions(+), 8 deletions(-)
20
target/arm/cpu_tcg.c | 1 +
21
target/arm/gdbstub.c | 22 ++++++++++++++++++----
22
gdb-xml/arm-m-profile.xml | 27 +++++++++++++++++++++++++++
23
4 files changed, 48 insertions(+), 6 deletions(-)
24
create mode 100644 gdb-xml/arm-m-profile.xml
24
25
25
diff --git a/configure b/configure
26
diff --git a/configure b/configure
26
index XXXXXXX..XXXXXXX 100755
27
index XXXXXXX..XXXXXXX 100755
27
--- a/configure
28
--- a/configure
28
+++ b/configure
29
+++ b/configure
29
@@ -XXX,XX +XXX,XX @@ ld_has() {
30
@@ -XXX,XX +XXX,XX @@ case "$target_name" in
30
31
TARGET_SYSTBL_ABI=common,oabi
31
# default parameters
32
bflt="yes"
32
source_path=$(dirname "$0")
33
mttcg="yes"
33
+# make source path absolute
34
- gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
34
+source_path=$(cd "$source_path"; pwd)
35
+ gdb_xml_files="arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml arm-m-profile.xml"
35
cpu=""
36
iasl="iasl"
37
interp_prefix="/usr/gnemul/qemu-%M"
38
@@ -XXX,XX +XXX,XX @@ for opt do
39
;;
36
;;
40
--cxx=*) CXX="$optarg"
37
aarch64|aarch64_be)
38
TARGET_ARCH=aarch64
39
TARGET_BASE_ARCH=arm
40
bflt="yes"
41
mttcg="yes"
42
- gdb_xml_files="aarch64-core.xml aarch64-fpu.xml arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml"
43
+ gdb_xml_files="aarch64-core.xml aarch64-fpu.xml arm-core.xml arm-vfp.xml arm-vfp3.xml arm-neon.xml arm-m-profile.xml"
41
;;
44
;;
42
- --source-path=*) source_path="$optarg"
45
cris)
43
- ;;
44
--cpu=*) cpu="$optarg"
45
;;
46
;;
46
--extra-cflags=*) QEMU_CFLAGS="$QEMU_CFLAGS $optarg"
47
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
47
@@ -XXX,XX +XXX,XX @@ if test "$debug_info" = "yes"; then
48
index XXXXXXX..XXXXXXX 100644
48
LDFLAGS="-g $LDFLAGS"
49
--- a/target/arm/cpu_tcg.c
49
fi
50
+++ b/target/arm/cpu_tcg.c
50
51
@@ -XXX,XX +XXX,XX @@ static void arm_v7m_class_init(ObjectClass *oc, void *data)
51
-# make source path absolute
52
#endif
52
-source_path=$(cd "$source_path"; pwd)
53
53
-
54
cc->cpu_exec_interrupt = arm_v7m_cpu_exec_interrupt;
54
# running configure in the source tree?
55
+ cc->gdb_core_xml_file = "arm-m-profile.xml";
55
# we know that's the case if configure is there.
56
}
56
if test -f "./configure"; then
57
57
@@ -XXX,XX +XXX,XX @@ for opt do
58
static const ARMCPUInfo arm_tcg_cpus[] = {
58
;;
59
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
59
--interp-prefix=*) interp_prefix="$optarg"
60
index XXXXXXX..XXXXXXX 100644
60
;;
61
--- a/target/arm/gdbstub.c
61
- --source-path=*)
62
+++ b/target/arm/gdbstub.c
62
- ;;
63
@@ -XXX,XX +XXX,XX @@ int arm_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
63
--cross-prefix=*)
64
}
64
;;
65
return gdb_get_reg32(mem_buf, 0);
65
--cc=*)
66
case 25:
66
@@ -XXX,XX +XXX,XX @@ $(echo Available targets: $default_target_list | \
67
- /* CPSR */
67
--target-list-exclude=LIST exclude a set of targets from the default target-list
68
- return gdb_get_reg32(mem_buf, cpsr_read(env));
68
69
+ /* CPSR, or XPSR for M-profile */
69
Advanced options (experts only):
70
+ if (arm_feature(env, ARM_FEATURE_M)) {
70
- --source-path=PATH path of source code [$source_path]
71
+ return gdb_get_reg32(mem_buf, xpsr_read(env));
71
--cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]
72
+ } else {
72
--cc=CC use C compiler CC [$cc]
73
+ return gdb_get_reg32(mem_buf, cpsr_read(env));
73
--iasl=IASL use ACPI compiler IASL [$iasl]
74
+ }
75
}
76
/* Unknown register. */
77
return 0;
78
@@ -XXX,XX +XXX,XX @@ int arm_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
79
}
80
return 4;
81
case 25:
82
- /* CPSR */
83
- cpsr_write(env, tmp, 0xffffffff, CPSRWriteByGDBStub);
84
+ /* CPSR, or XPSR for M-profile */
85
+ if (arm_feature(env, ARM_FEATURE_M)) {
86
+ /*
87
+ * Don't allow writing to XPSR.Exception as it can cause
88
+ * a transition into or out of handler mode (it's not
89
+ * writeable via the MSR insn so this is a reasonable
90
+ * restriction). Other fields are safe to update.
91
+ */
92
+ xpsr_write(env, tmp, ~XPSR_EXCP);
93
+ } else {
94
+ cpsr_write(env, tmp, 0xffffffff, CPSRWriteByGDBStub);
95
+ }
96
return 4;
97
}
98
/* Unknown register. */
99
diff --git a/gdb-xml/arm-m-profile.xml b/gdb-xml/arm-m-profile.xml
100
new file mode 100644
101
index XXXXXXX..XXXXXXX
102
--- /dev/null
103
+++ b/gdb-xml/arm-m-profile.xml
104
@@ -XXX,XX +XXX,XX @@
105
+<?xml version="1.0"?>
106
+<!-- Copyright (C) 2010-2020 Free Software Foundation, Inc.
107
+
108
+ Copying and distribution of this file, with or without modification,
109
+ are permitted in any medium without royalty provided the copyright
110
+ notice and this notice are preserved. -->
111
+
112
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
113
+<feature name="org.gnu.gdb.arm.m-profile">
114
+ <reg name="r0" bitsize="32"/>
115
+ <reg name="r1" bitsize="32"/>
116
+ <reg name="r2" bitsize="32"/>
117
+ <reg name="r3" bitsize="32"/>
118
+ <reg name="r4" bitsize="32"/>
119
+ <reg name="r5" bitsize="32"/>
120
+ <reg name="r6" bitsize="32"/>
121
+ <reg name="r7" bitsize="32"/>
122
+ <reg name="r8" bitsize="32"/>
123
+ <reg name="r9" bitsize="32"/>
124
+ <reg name="r10" bitsize="32"/>
125
+ <reg name="r11" bitsize="32"/>
126
+ <reg name="r12" bitsize="32"/>
127
+ <reg name="sp" bitsize="32" type="data_ptr"/>
128
+ <reg name="lr" bitsize="32"/>
129
+ <reg name="pc" bitsize="32" type="code_ptr"/>
130
+ <reg name="xpsr" bitsize="32" regnum="25"/>
131
+</feature>
74
--
132
--
75
2.20.1
133
2.20.1
76
134
77
135
diff view generated by jsdifflib
1
Add a new helper function which returns the MMU index to use
1
From: Richard Henderson <richard.henderson@linaro.org>
2
for v7M, where the caller specifies all of the security
2
3
state, privilege level and whether the execution priority
3
The functions eliminate duplication of the special cases for
4
is negative, and reimplement the existing
4
this operation. They match up with the GVecGen2iFn typedef.
5
arm_v7m_mmu_idx_for_secstate_and_priv() in terms of it.
5
6
6
Add out-of-line helpers. We got away with only having inline
7
We are going to need this for the lazy-FP-stacking code.
7
expanders because the neon vector size is only 16 bytes, and
8
8
we know that the inline expansion will always succeed.
9
When we reuse this for SVE, tcg-gvec-op may decide to use an
10
out-of-line helper due to longer vector lengths.
11
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20200513163245.17915-2-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20190416125744.27770-21-peter.maydell@linaro.org
12
---
16
---
13
target/arm/cpu.h | 7 +++++++
17
target/arm/helper.h | 10 +++
14
target/arm/helper.c | 14 +++++++++++---
18
target/arm/translate.h | 7 +-
15
2 files changed, 18 insertions(+), 3 deletions(-)
19
target/arm/translate-a64.c | 15 +---
16
20
target/arm/translate.c | 161 ++++++++++++++++++++++---------------
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
21
target/arm/vec_helper.c | 25 ++++++
18
index XXXXXXX..XXXXXXX 100644
22
5 files changed, 139 insertions(+), 79 deletions(-)
19
--- a/target/arm/cpu.h
23
20
+++ b/target/arm/cpu.h
24
diff --git a/target/arm/helper.h b/target/arm/helper.h
21
@@ -XXX,XX +XXX,XX @@ static inline int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
25
index XXXXXXX..XXXXXXX 100644
22
}
26
--- a/target/arm/helper.h
27
+++ b/target/arm/helper.h
28
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(gvec_pmull_q, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
29
30
DEF_HELPER_FLAGS_4(neon_pmull_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
31
32
+DEF_HELPER_FLAGS_3(gvec_ssra_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
33
+DEF_HELPER_FLAGS_3(gvec_ssra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
34
+DEF_HELPER_FLAGS_3(gvec_ssra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
35
+DEF_HELPER_FLAGS_3(gvec_ssra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
36
+
37
+DEF_HELPER_FLAGS_3(gvec_usra_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
38
+DEF_HELPER_FLAGS_3(gvec_usra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
39
+DEF_HELPER_FLAGS_3(gvec_usra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
40
+DEF_HELPER_FLAGS_3(gvec_usra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
41
+
42
#ifdef TARGET_AARCH64
43
#include "helper-a64.h"
44
#include "helper-sve.h"
45
diff --git a/target/arm/translate.h b/target/arm/translate.h
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/translate.h
48
+++ b/target/arm/translate.h
49
@@ -XXX,XX +XXX,XX @@ extern const GVecGen3 mls_op[4];
50
extern const GVecGen3 cmtst_op[4];
51
extern const GVecGen3 sshl_op[4];
52
extern const GVecGen3 ushl_op[4];
53
-extern const GVecGen2i ssra_op[4];
54
-extern const GVecGen2i usra_op[4];
55
extern const GVecGen2i sri_op[4];
56
extern const GVecGen2i sli_op[4];
57
extern const GVecGen4 uqadd_op[4];
58
@@ -XXX,XX +XXX,XX @@ void gen_sshl_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
59
void gen_ushl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
60
void gen_sshl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
61
62
+void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
63
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
64
+void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
65
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
66
+
67
/*
68
* Forward to the isar_feature_* tests given a DisasContext pointer.
69
*/
70
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/target/arm/translate-a64.c
73
+++ b/target/arm/translate-a64.c
74
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
75
76
switch (opcode) {
77
case 0x02: /* SSRA / USRA (accumulate) */
78
- if (is_u) {
79
- /* Shift count same as element size produces zero to add. */
80
- if (shift == 8 << size) {
81
- goto done;
82
- }
83
- gen_gvec_op2i(s, is_q, rd, rn, shift, &usra_op[size]);
84
- } else {
85
- /* Shift count same as element size produces all sign to add. */
86
- if (shift == 8 << size) {
87
- shift -= 1;
88
- }
89
- gen_gvec_op2i(s, is_q, rd, rn, shift, &ssra_op[size]);
90
- }
91
+ gen_gvec_fn2i(s, is_q, rd, rn, shift,
92
+ is_u ? gen_gvec_usra : gen_gvec_ssra, size);
93
return;
94
case 0x08: /* SRI */
95
/* Shift count same as element size is valid but does nothing. */
96
diff --git a/target/arm/translate.c b/target/arm/translate.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/target/arm/translate.c
99
+++ b/target/arm/translate.c
100
@@ -XXX,XX +XXX,XX @@ static void gen_ssra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
101
tcg_gen_add_vec(vece, d, d, a);
23
}
102
}
24
103
25
+/*
104
-static const TCGOpcode vecop_list_ssra[] = {
26
+ * Return the MMU index for a v7M CPU with all relevant information
105
- INDEX_op_sari_vec, INDEX_op_add_vec, 0
27
+ * manually specified.
106
-};
28
+ */
107
+void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
29
+ARMMMUIdx arm_v7m_mmu_idx_all(CPUARMState *env,
108
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
30
+ bool secstate, bool priv, bool negpri);
109
+{
31
+
110
+ static const TCGOpcode vecop_list[] = {
32
/* Return the MMU index for a v7M CPU in the specified security and
111
+ INDEX_op_sari_vec, INDEX_op_add_vec, 0
33
* privilege state.
112
+ };
34
*/
113
+ static const GVecGen2i ops[4] = {
35
diff --git a/target/arm/helper.c b/target/arm/helper.c
114
+ { .fni8 = gen_ssra8_i64,
36
index XXXXXXX..XXXXXXX 100644
115
+ .fniv = gen_ssra_vec,
37
--- a/target/arm/helper.c
116
+ .fno = gen_helper_gvec_ssra_b,
38
+++ b/target/arm/helper.c
117
+ .load_dest = true,
39
@@ -XXX,XX +XXX,XX @@ int fp_exception_el(CPUARMState *env, int cur_el)
118
+ .opt_opc = vecop_list,
40
return 0;
119
+ .vece = MO_8 },
120
+ { .fni8 = gen_ssra16_i64,
121
+ .fniv = gen_ssra_vec,
122
+ .fno = gen_helper_gvec_ssra_h,
123
+ .load_dest = true,
124
+ .opt_opc = vecop_list,
125
+ .vece = MO_16 },
126
+ { .fni4 = gen_ssra32_i32,
127
+ .fniv = gen_ssra_vec,
128
+ .fno = gen_helper_gvec_ssra_s,
129
+ .load_dest = true,
130
+ .opt_opc = vecop_list,
131
+ .vece = MO_32 },
132
+ { .fni8 = gen_ssra64_i64,
133
+ .fniv = gen_ssra_vec,
134
+ .fno = gen_helper_gvec_ssra_b,
135
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
136
+ .opt_opc = vecop_list,
137
+ .load_dest = true,
138
+ .vece = MO_64 },
139
+ };
140
141
-const GVecGen2i ssra_op[4] = {
142
- { .fni8 = gen_ssra8_i64,
143
- .fniv = gen_ssra_vec,
144
- .load_dest = true,
145
- .opt_opc = vecop_list_ssra,
146
- .vece = MO_8 },
147
- { .fni8 = gen_ssra16_i64,
148
- .fniv = gen_ssra_vec,
149
- .load_dest = true,
150
- .opt_opc = vecop_list_ssra,
151
- .vece = MO_16 },
152
- { .fni4 = gen_ssra32_i32,
153
- .fniv = gen_ssra_vec,
154
- .load_dest = true,
155
- .opt_opc = vecop_list_ssra,
156
- .vece = MO_32 },
157
- { .fni8 = gen_ssra64_i64,
158
- .fniv = gen_ssra_vec,
159
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
160
- .opt_opc = vecop_list_ssra,
161
- .load_dest = true,
162
- .vece = MO_64 },
163
-};
164
+ /* tszimm encoding produces immediates in the range [1..esize]. */
165
+ tcg_debug_assert(shift > 0);
166
+ tcg_debug_assert(shift <= (8 << vece));
167
+
168
+ /*
169
+ * Shifts larger than the element size are architecturally valid.
170
+ * Signed results in all sign bits.
171
+ */
172
+ shift = MIN(shift, (8 << vece) - 1);
173
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
174
+}
175
176
static void gen_usra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
177
{
178
@@ -XXX,XX +XXX,XX @@ static void gen_usra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
179
tcg_gen_add_vec(vece, d, d, a);
41
}
180
}
42
181
43
-ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env,
182
-static const TCGOpcode vecop_list_usra[] = {
44
- bool secstate, bool priv)
183
- INDEX_op_shri_vec, INDEX_op_add_vec, 0
45
+ARMMMUIdx arm_v7m_mmu_idx_all(CPUARMState *env,
184
-};
46
+ bool secstate, bool priv, bool negpri)
185
+void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
186
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
187
+{
188
+ static const TCGOpcode vecop_list[] = {
189
+ INDEX_op_shri_vec, INDEX_op_add_vec, 0
190
+ };
191
+ static const GVecGen2i ops[4] = {
192
+ { .fni8 = gen_usra8_i64,
193
+ .fniv = gen_usra_vec,
194
+ .fno = gen_helper_gvec_usra_b,
195
+ .load_dest = true,
196
+ .opt_opc = vecop_list,
197
+ .vece = MO_8, },
198
+ { .fni8 = gen_usra16_i64,
199
+ .fniv = gen_usra_vec,
200
+ .fno = gen_helper_gvec_usra_h,
201
+ .load_dest = true,
202
+ .opt_opc = vecop_list,
203
+ .vece = MO_16, },
204
+ { .fni4 = gen_usra32_i32,
205
+ .fniv = gen_usra_vec,
206
+ .fno = gen_helper_gvec_usra_s,
207
+ .load_dest = true,
208
+ .opt_opc = vecop_list,
209
+ .vece = MO_32, },
210
+ { .fni8 = gen_usra64_i64,
211
+ .fniv = gen_usra_vec,
212
+ .fno = gen_helper_gvec_usra_d,
213
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
214
+ .load_dest = true,
215
+ .opt_opc = vecop_list,
216
+ .vece = MO_64, },
217
+ };
218
219
-const GVecGen2i usra_op[4] = {
220
- { .fni8 = gen_usra8_i64,
221
- .fniv = gen_usra_vec,
222
- .load_dest = true,
223
- .opt_opc = vecop_list_usra,
224
- .vece = MO_8, },
225
- { .fni8 = gen_usra16_i64,
226
- .fniv = gen_usra_vec,
227
- .load_dest = true,
228
- .opt_opc = vecop_list_usra,
229
- .vece = MO_16, },
230
- { .fni4 = gen_usra32_i32,
231
- .fniv = gen_usra_vec,
232
- .load_dest = true,
233
- .opt_opc = vecop_list_usra,
234
- .vece = MO_32, },
235
- { .fni8 = gen_usra64_i64,
236
- .fniv = gen_usra_vec,
237
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
238
- .load_dest = true,
239
- .opt_opc = vecop_list_usra,
240
- .vece = MO_64, },
241
-};
242
+ /* tszimm encoding produces immediates in the range [1..esize]. */
243
+ tcg_debug_assert(shift > 0);
244
+ tcg_debug_assert(shift <= (8 << vece));
245
+
246
+ /*
247
+ * Shifts larger than the element size are architecturally valid.
248
+ * Unsigned results in all zeros as input to accumulate: nop.
249
+ */
250
+ if (shift < (8 << vece)) {
251
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
252
+ } else {
253
+ /* Nop, but we do need to clear the tail. */
254
+ tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
255
+ }
256
+}
257
258
static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
47
{
259
{
48
ARMMMUIdx mmu_idx = ARM_MMU_IDX_M;
260
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
49
261
case 1: /* VSRA */
50
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env,
262
/* Right shift comes here negative. */
51
mmu_idx |= ARM_MMU_IDX_M_PRIV;
263
shift = -shift;
52
}
264
- /* Shifts larger than the element size are architecturally
53
265
- * valid. Unsigned results in all zeros; signed results
54
- if (armv7m_nvic_neg_prio_requested(env->nvic, secstate)) {
266
- * in all sign bits.
55
+ if (negpri) {
267
- */
56
mmu_idx |= ARM_MMU_IDX_M_NEGPRI;
268
- if (!u) {
57
}
269
- tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
58
270
- MIN(shift, (8 << size) - 1),
59
@@ -XXX,XX +XXX,XX @@ ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env,
271
- &ssra_op[size]);
60
return mmu_idx;
272
- } else if (shift >= 8 << size) {
273
- /* rd += 0 */
274
+ if (u) {
275
+ gen_gvec_usra(size, rd_ofs, rm_ofs, shift,
276
+ vec_size, vec_size);
277
} else {
278
- tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
279
- shift, &usra_op[size]);
280
+ gen_gvec_ssra(size, rd_ofs, rm_ofs, shift,
281
+ vec_size, vec_size);
282
}
283
return 0;
284
285
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
286
index XXXXXXX..XXXXXXX 100644
287
--- a/target/arm/vec_helper.c
288
+++ b/target/arm/vec_helper.c
289
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_sqsub_d)(void *vd, void *vq, void *vn,
290
clear_tail(d, oprsz, simd_maxsz(desc));
61
}
291
}
62
292
63
+ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env,
293
+
64
+ bool secstate, bool priv)
294
+#define DO_SRA(NAME, TYPE) \
65
+{
295
+void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \
66
+ bool negpri = armv7m_nvic_neg_prio_requested(env->nvic, secstate);
296
+{ \
67
+
297
+ intptr_t i, oprsz = simd_oprsz(desc); \
68
+ return arm_v7m_mmu_idx_all(env, secstate, priv, negpri);
298
+ int shift = simd_data(desc); \
299
+ TYPE *d = vd, *n = vn; \
300
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
301
+ d[i] += n[i] >> shift; \
302
+ } \
303
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
69
+}
304
+}
70
+
305
+
71
/* Return the MMU index for a v7M CPU in the specified security state */
306
+DO_SRA(gvec_ssra_b, int8_t)
72
ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate)
307
+DO_SRA(gvec_ssra_h, int16_t)
73
{
308
+DO_SRA(gvec_ssra_s, int32_t)
309
+DO_SRA(gvec_ssra_d, int64_t)
310
+
311
+DO_SRA(gvec_usra_b, uint8_t)
312
+DO_SRA(gvec_usra_h, uint16_t)
313
+DO_SRA(gvec_usra_s, uint32_t)
314
+DO_SRA(gvec_usra_d, uint64_t)
315
+
316
+#undef DO_SRA
317
+
318
/*
319
* Convert float16 to float32, raising no exceptions and
320
* preserving exceptional values, including SNaN.
74
--
321
--
75
2.20.1
322
2.20.1
76
323
77
324
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Since uWireSlave is only used in this new header, there is no
3
Create vectorized versions of handle_shri_with_rndacc
4
need to expose it via "qemu/typedefs.h".
4
for shift+round and shift+round+accumulate. Add out-of-line
5
helpers in preparation for longer vector lengths from SVE.
5
6
6
Reviewed-by: Markus Armbruster <armbru@redhat.com>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20190412165416.7977-9-philmd@redhat.com
9
Message-id: 20200513163245.17915-3-richard.henderson@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
---
11
include/hw/arm/omap.h | 6 +-----
12
target/arm/helper.h | 20 ++
12
include/hw/devices.h | 15 ---------------
13
target/arm/translate.h | 9 +
13
include/hw/input/tsc2xxx.h | 36 ++++++++++++++++++++++++++++++++++++
14
target/arm/translate-a64.c | 11 +-
14
include/qemu/typedefs.h | 1 -
15
target/arm/translate.c | 463 +++++++++++++++++++++++++++++++++++--
15
hw/arm/nseries.c | 2 +-
16
target/arm/vec_helper.c | 50 ++++
16
hw/arm/palm.c | 2 +-
17
5 files changed, 527 insertions(+), 26 deletions(-)
17
hw/input/tsc2005.c | 2 +-
18
hw/input/tsc210x.c | 4 ++--
19
MAINTAINERS | 2 ++
20
9 files changed, 44 insertions(+), 26 deletions(-)
21
create mode 100644 include/hw/input/tsc2xxx.h
22
18
23
diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h
19
diff --git a/target/arm/helper.h b/target/arm/helper.h
24
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/arm/omap.h
21
--- a/target/arm/helper.h
26
+++ b/include/hw/arm/omap.h
22
+++ b/target/arm/helper.h
27
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(gvec_usra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
28
#include "exec/memory.h"
24
DEF_HELPER_FLAGS_3(gvec_usra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
29
# define hw_omap_h        "omap.h"
25
DEF_HELPER_FLAGS_3(gvec_usra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
30
#include "hw/irq.h"
26
31
+#include "hw/input/tsc2xxx.h"
27
+DEF_HELPER_FLAGS_3(gvec_srshr_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
32
#include "target/arm/cpu-qom.h"
28
+DEF_HELPER_FLAGS_3(gvec_srshr_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
33
#include "qemu/log.h"
29
+DEF_HELPER_FLAGS_3(gvec_srshr_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
34
30
+DEF_HELPER_FLAGS_3(gvec_srshr_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
35
@@ -XXX,XX +XXX,XX @@ qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s);
31
+
36
void omap_mpuio_out_set(struct omap_mpuio_s *s, int line, qemu_irq handler);
32
+DEF_HELPER_FLAGS_3(gvec_urshr_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
37
void omap_mpuio_key(struct omap_mpuio_s *s, int row, int col, int down);
33
+DEF_HELPER_FLAGS_3(gvec_urshr_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
38
34
+DEF_HELPER_FLAGS_3(gvec_urshr_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
39
-struct uWireSlave {
35
+DEF_HELPER_FLAGS_3(gvec_urshr_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
40
- uint16_t (*receive)(void *opaque);
36
+
41
- void (*send)(void *opaque, uint16_t data);
37
+DEF_HELPER_FLAGS_3(gvec_srsra_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
42
- void *opaque;
38
+DEF_HELPER_FLAGS_3(gvec_srsra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
43
-};
39
+DEF_HELPER_FLAGS_3(gvec_srsra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
44
struct omap_uwire_s;
40
+DEF_HELPER_FLAGS_3(gvec_srsra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
45
void omap_uwire_attach(struct omap_uwire_s *s,
41
+
46
uWireSlave *slave, int chipselect);
42
+DEF_HELPER_FLAGS_3(gvec_ursra_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
47
diff --git a/include/hw/devices.h b/include/hw/devices.h
43
+DEF_HELPER_FLAGS_3(gvec_ursra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
44
+DEF_HELPER_FLAGS_3(gvec_ursra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
45
+DEF_HELPER_FLAGS_3(gvec_ursra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
46
+
47
#ifdef TARGET_AARCH64
48
#include "helper-a64.h"
49
#include "helper-sve.h"
50
diff --git a/target/arm/translate.h b/target/arm/translate.h
48
index XXXXXXX..XXXXXXX 100644
51
index XXXXXXX..XXXXXXX 100644
49
--- a/include/hw/devices.h
52
--- a/target/arm/translate.h
50
+++ b/include/hw/devices.h
53
+++ b/target/arm/translate.h
51
@@ -XXX,XX +XXX,XX @@
54
@@ -XXX,XX +XXX,XX @@ void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
52
/* Devices that have nowhere better to go. */
55
void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
53
56
int64_t shift, uint32_t opr_sz, uint32_t max_sz);
54
#include "hw/hw.h"
57
55
-#include "ui/console.h"
58
+void gen_gvec_srshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
56
59
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
57
/* smc91c111.c */
60
+void gen_gvec_urshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
58
void smc91c111_init(NICInfo *, uint32_t, qemu_irq);
61
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
59
@@ -XXX,XX +XXX,XX @@ void smc91c111_init(NICInfo *, uint32_t, qemu_irq);
62
+void gen_gvec_srsra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
60
/* lan9118.c */
63
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
61
void lan9118_init(NICInfo *, uint32_t, qemu_irq);
64
+void gen_gvec_ursra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
62
65
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
63
-/* tsc210x.c */
66
+
64
-uWireSlave *tsc2102_init(qemu_irq pint);
67
/*
65
-uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav);
68
* Forward to the isar_feature_* tests given a DisasContext pointer.
66
-I2SCodec *tsc210x_codec(uWireSlave *chip);
69
*/
67
-uint32_t tsc210x_txrx(void *opaque, uint32_t value, int len);
70
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
68
-void tsc210x_set_transform(uWireSlave *chip,
71
index XXXXXXX..XXXXXXX 100644
69
- MouseTransformInfo *info);
72
--- a/target/arm/translate-a64.c
70
-void tsc210x_key_event(uWireSlave *chip, int key, int down);
73
+++ b/target/arm/translate-a64.c
74
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
75
return;
76
77
case 0x04: /* SRSHR / URSHR (rounding) */
78
- break;
79
+ gen_gvec_fn2i(s, is_q, rd, rn, shift,
80
+ is_u ? gen_gvec_urshr : gen_gvec_srshr, size);
81
+ return;
82
+
83
case 0x06: /* SRSRA / URSRA (accum + rounding) */
84
- accumulate = true;
85
- break;
86
+ gen_gvec_fn2i(s, is_q, rd, rn, shift,
87
+ is_u ? gen_gvec_ursra : gen_gvec_srsra, size);
88
+ return;
89
+
90
default:
91
g_assert_not_reached();
92
}
93
diff --git a/target/arm/translate.c b/target/arm/translate.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/target/arm/translate.c
96
+++ b/target/arm/translate.c
97
@@ -XXX,XX +XXX,XX @@ void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
98
}
99
}
100
101
+/*
102
+ * Shift one less than the requested amount, and the low bit is
103
+ * the rounding bit. For the 8 and 16-bit operations, because we
104
+ * mask the low bit, we can perform a normal integer shift instead
105
+ * of a vector shift.
106
+ */
107
+static void gen_srshr8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
108
+{
109
+ TCGv_i64 t = tcg_temp_new_i64();
110
+
111
+ tcg_gen_shri_i64(t, a, sh - 1);
112
+ tcg_gen_andi_i64(t, t, dup_const(MO_8, 1));
113
+ tcg_gen_vec_sar8i_i64(d, a, sh);
114
+ tcg_gen_vec_add8_i64(d, d, t);
115
+ tcg_temp_free_i64(t);
116
+}
117
+
118
+static void gen_srshr16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
119
+{
120
+ TCGv_i64 t = tcg_temp_new_i64();
121
+
122
+ tcg_gen_shri_i64(t, a, sh - 1);
123
+ tcg_gen_andi_i64(t, t, dup_const(MO_16, 1));
124
+ tcg_gen_vec_sar16i_i64(d, a, sh);
125
+ tcg_gen_vec_add16_i64(d, d, t);
126
+ tcg_temp_free_i64(t);
127
+}
128
+
129
+static void gen_srshr32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
130
+{
131
+ TCGv_i32 t = tcg_temp_new_i32();
132
+
133
+ tcg_gen_extract_i32(t, a, sh - 1, 1);
134
+ tcg_gen_sari_i32(d, a, sh);
135
+ tcg_gen_add_i32(d, d, t);
136
+ tcg_temp_free_i32(t);
137
+}
138
+
139
+static void gen_srshr64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
140
+{
141
+ TCGv_i64 t = tcg_temp_new_i64();
142
+
143
+ tcg_gen_extract_i64(t, a, sh - 1, 1);
144
+ tcg_gen_sari_i64(d, a, sh);
145
+ tcg_gen_add_i64(d, d, t);
146
+ tcg_temp_free_i64(t);
147
+}
148
+
149
+static void gen_srshr_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
150
+{
151
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
152
+ TCGv_vec ones = tcg_temp_new_vec_matching(d);
153
+
154
+ tcg_gen_shri_vec(vece, t, a, sh - 1);
155
+ tcg_gen_dupi_vec(vece, ones, 1);
156
+ tcg_gen_and_vec(vece, t, t, ones);
157
+ tcg_gen_sari_vec(vece, d, a, sh);
158
+ tcg_gen_add_vec(vece, d, d, t);
159
+
160
+ tcg_temp_free_vec(t);
161
+ tcg_temp_free_vec(ones);
162
+}
163
+
164
+void gen_gvec_srshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
165
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
166
+{
167
+ static const TCGOpcode vecop_list[] = {
168
+ INDEX_op_shri_vec, INDEX_op_sari_vec, INDEX_op_add_vec, 0
169
+ };
170
+ static const GVecGen2i ops[4] = {
171
+ { .fni8 = gen_srshr8_i64,
172
+ .fniv = gen_srshr_vec,
173
+ .fno = gen_helper_gvec_srshr_b,
174
+ .opt_opc = vecop_list,
175
+ .vece = MO_8 },
176
+ { .fni8 = gen_srshr16_i64,
177
+ .fniv = gen_srshr_vec,
178
+ .fno = gen_helper_gvec_srshr_h,
179
+ .opt_opc = vecop_list,
180
+ .vece = MO_16 },
181
+ { .fni4 = gen_srshr32_i32,
182
+ .fniv = gen_srshr_vec,
183
+ .fno = gen_helper_gvec_srshr_s,
184
+ .opt_opc = vecop_list,
185
+ .vece = MO_32 },
186
+ { .fni8 = gen_srshr64_i64,
187
+ .fniv = gen_srshr_vec,
188
+ .fno = gen_helper_gvec_srshr_d,
189
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
190
+ .opt_opc = vecop_list,
191
+ .vece = MO_64 },
192
+ };
193
+
194
+ /* tszimm encoding produces immediates in the range [1..esize] */
195
+ tcg_debug_assert(shift > 0);
196
+ tcg_debug_assert(shift <= (8 << vece));
197
+
198
+ if (shift == (8 << vece)) {
199
+ /*
200
+ * Shifts larger than the element size are architecturally valid.
201
+ * Signed results in all sign bits. With rounding, this produces
202
+ * (-1 + 1) >> 1 == 0, or (0 + 1) >> 1 == 0.
203
+ * I.e. always zero.
204
+ */
205
+ tcg_gen_gvec_dup_imm(vece, rd_ofs, opr_sz, max_sz, 0);
206
+ } else {
207
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
208
+ }
209
+}
210
+
211
+static void gen_srsra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
212
+{
213
+ TCGv_i64 t = tcg_temp_new_i64();
214
+
215
+ gen_srshr8_i64(t, a, sh);
216
+ tcg_gen_vec_add8_i64(d, d, t);
217
+ tcg_temp_free_i64(t);
218
+}
219
+
220
+static void gen_srsra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
221
+{
222
+ TCGv_i64 t = tcg_temp_new_i64();
223
+
224
+ gen_srshr16_i64(t, a, sh);
225
+ tcg_gen_vec_add16_i64(d, d, t);
226
+ tcg_temp_free_i64(t);
227
+}
228
+
229
+static void gen_srsra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
230
+{
231
+ TCGv_i32 t = tcg_temp_new_i32();
232
+
233
+ gen_srshr32_i32(t, a, sh);
234
+ tcg_gen_add_i32(d, d, t);
235
+ tcg_temp_free_i32(t);
236
+}
237
+
238
+static void gen_srsra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
239
+{
240
+ TCGv_i64 t = tcg_temp_new_i64();
241
+
242
+ gen_srshr64_i64(t, a, sh);
243
+ tcg_gen_add_i64(d, d, t);
244
+ tcg_temp_free_i64(t);
245
+}
246
+
247
+static void gen_srsra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
248
+{
249
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
250
+
251
+ gen_srshr_vec(vece, t, a, sh);
252
+ tcg_gen_add_vec(vece, d, d, t);
253
+ tcg_temp_free_vec(t);
254
+}
255
+
256
+void gen_gvec_srsra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
257
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
258
+{
259
+ static const TCGOpcode vecop_list[] = {
260
+ INDEX_op_shri_vec, INDEX_op_sari_vec, INDEX_op_add_vec, 0
261
+ };
262
+ static const GVecGen2i ops[4] = {
263
+ { .fni8 = gen_srsra8_i64,
264
+ .fniv = gen_srsra_vec,
265
+ .fno = gen_helper_gvec_srsra_b,
266
+ .opt_opc = vecop_list,
267
+ .load_dest = true,
268
+ .vece = MO_8 },
269
+ { .fni8 = gen_srsra16_i64,
270
+ .fniv = gen_srsra_vec,
271
+ .fno = gen_helper_gvec_srsra_h,
272
+ .opt_opc = vecop_list,
273
+ .load_dest = true,
274
+ .vece = MO_16 },
275
+ { .fni4 = gen_srsra32_i32,
276
+ .fniv = gen_srsra_vec,
277
+ .fno = gen_helper_gvec_srsra_s,
278
+ .opt_opc = vecop_list,
279
+ .load_dest = true,
280
+ .vece = MO_32 },
281
+ { .fni8 = gen_srsra64_i64,
282
+ .fniv = gen_srsra_vec,
283
+ .fno = gen_helper_gvec_srsra_d,
284
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
285
+ .opt_opc = vecop_list,
286
+ .load_dest = true,
287
+ .vece = MO_64 },
288
+ };
289
+
290
+ /* tszimm encoding produces immediates in the range [1..esize] */
291
+ tcg_debug_assert(shift > 0);
292
+ tcg_debug_assert(shift <= (8 << vece));
293
+
294
+ /*
295
+ * Shifts larger than the element size are architecturally valid.
296
+ * Signed results in all sign bits. With rounding, this produces
297
+ * (-1 + 1) >> 1 == 0, or (0 + 1) >> 1 == 0.
298
+ * I.e. always zero. With accumulation, this leaves D unchanged.
299
+ */
300
+ if (shift == (8 << vece)) {
301
+ /* Nop, but we do need to clear the tail. */
302
+ tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
303
+ } else {
304
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
305
+ }
306
+}
307
+
308
+static void gen_urshr8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
309
+{
310
+ TCGv_i64 t = tcg_temp_new_i64();
311
+
312
+ tcg_gen_shri_i64(t, a, sh - 1);
313
+ tcg_gen_andi_i64(t, t, dup_const(MO_8, 1));
314
+ tcg_gen_vec_shr8i_i64(d, a, sh);
315
+ tcg_gen_vec_add8_i64(d, d, t);
316
+ tcg_temp_free_i64(t);
317
+}
318
+
319
+static void gen_urshr16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
320
+{
321
+ TCGv_i64 t = tcg_temp_new_i64();
322
+
323
+ tcg_gen_shri_i64(t, a, sh - 1);
324
+ tcg_gen_andi_i64(t, t, dup_const(MO_16, 1));
325
+ tcg_gen_vec_shr16i_i64(d, a, sh);
326
+ tcg_gen_vec_add16_i64(d, d, t);
327
+ tcg_temp_free_i64(t);
328
+}
329
+
330
+static void gen_urshr32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
331
+{
332
+ TCGv_i32 t = tcg_temp_new_i32();
333
+
334
+ tcg_gen_extract_i32(t, a, sh - 1, 1);
335
+ tcg_gen_shri_i32(d, a, sh);
336
+ tcg_gen_add_i32(d, d, t);
337
+ tcg_temp_free_i32(t);
338
+}
339
+
340
+static void gen_urshr64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
341
+{
342
+ TCGv_i64 t = tcg_temp_new_i64();
343
+
344
+ tcg_gen_extract_i64(t, a, sh - 1, 1);
345
+ tcg_gen_shri_i64(d, a, sh);
346
+ tcg_gen_add_i64(d, d, t);
347
+ tcg_temp_free_i64(t);
348
+}
349
+
350
+static void gen_urshr_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t shift)
351
+{
352
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
353
+ TCGv_vec ones = tcg_temp_new_vec_matching(d);
354
+
355
+ tcg_gen_shri_vec(vece, t, a, shift - 1);
356
+ tcg_gen_dupi_vec(vece, ones, 1);
357
+ tcg_gen_and_vec(vece, t, t, ones);
358
+ tcg_gen_shri_vec(vece, d, a, shift);
359
+ tcg_gen_add_vec(vece, d, d, t);
360
+
361
+ tcg_temp_free_vec(t);
362
+ tcg_temp_free_vec(ones);
363
+}
364
+
365
+void gen_gvec_urshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
366
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
367
+{
368
+ static const TCGOpcode vecop_list[] = {
369
+ INDEX_op_shri_vec, INDEX_op_add_vec, 0
370
+ };
371
+ static const GVecGen2i ops[4] = {
372
+ { .fni8 = gen_urshr8_i64,
373
+ .fniv = gen_urshr_vec,
374
+ .fno = gen_helper_gvec_urshr_b,
375
+ .opt_opc = vecop_list,
376
+ .vece = MO_8 },
377
+ { .fni8 = gen_urshr16_i64,
378
+ .fniv = gen_urshr_vec,
379
+ .fno = gen_helper_gvec_urshr_h,
380
+ .opt_opc = vecop_list,
381
+ .vece = MO_16 },
382
+ { .fni4 = gen_urshr32_i32,
383
+ .fniv = gen_urshr_vec,
384
+ .fno = gen_helper_gvec_urshr_s,
385
+ .opt_opc = vecop_list,
386
+ .vece = MO_32 },
387
+ { .fni8 = gen_urshr64_i64,
388
+ .fniv = gen_urshr_vec,
389
+ .fno = gen_helper_gvec_urshr_d,
390
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
391
+ .opt_opc = vecop_list,
392
+ .vece = MO_64 },
393
+ };
394
+
395
+ /* tszimm encoding produces immediates in the range [1..esize] */
396
+ tcg_debug_assert(shift > 0);
397
+ tcg_debug_assert(shift <= (8 << vece));
398
+
399
+ if (shift == (8 << vece)) {
400
+ /*
401
+ * Shifts larger than the element size are architecturally valid.
402
+ * Unsigned results in zero. With rounding, this produces a
403
+ * copy of the most significant bit.
404
+ */
405
+ tcg_gen_gvec_shri(vece, rd_ofs, rm_ofs, shift - 1, opr_sz, max_sz);
406
+ } else {
407
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
408
+ }
409
+}
410
+
411
+static void gen_ursra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
412
+{
413
+ TCGv_i64 t = tcg_temp_new_i64();
414
+
415
+ if (sh == 8) {
416
+ tcg_gen_vec_shr8i_i64(t, a, 7);
417
+ } else {
418
+ gen_urshr8_i64(t, a, sh);
419
+ }
420
+ tcg_gen_vec_add8_i64(d, d, t);
421
+ tcg_temp_free_i64(t);
422
+}
423
+
424
+static void gen_ursra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
425
+{
426
+ TCGv_i64 t = tcg_temp_new_i64();
427
+
428
+ if (sh == 16) {
429
+ tcg_gen_vec_shr16i_i64(t, a, 15);
430
+ } else {
431
+ gen_urshr16_i64(t, a, sh);
432
+ }
433
+ tcg_gen_vec_add16_i64(d, d, t);
434
+ tcg_temp_free_i64(t);
435
+}
436
+
437
+static void gen_ursra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh)
438
+{
439
+ TCGv_i32 t = tcg_temp_new_i32();
440
+
441
+ if (sh == 32) {
442
+ tcg_gen_shri_i32(t, a, 31);
443
+ } else {
444
+ gen_urshr32_i32(t, a, sh);
445
+ }
446
+ tcg_gen_add_i32(d, d, t);
447
+ tcg_temp_free_i32(t);
448
+}
449
+
450
+static void gen_ursra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh)
451
+{
452
+ TCGv_i64 t = tcg_temp_new_i64();
453
+
454
+ if (sh == 64) {
455
+ tcg_gen_shri_i64(t, a, 63);
456
+ } else {
457
+ gen_urshr64_i64(t, a, sh);
458
+ }
459
+ tcg_gen_add_i64(d, d, t);
460
+ tcg_temp_free_i64(t);
461
+}
462
+
463
+static void gen_ursra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
464
+{
465
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
466
+
467
+ if (sh == (8 << vece)) {
468
+ tcg_gen_shri_vec(vece, t, a, sh - 1);
469
+ } else {
470
+ gen_urshr_vec(vece, t, a, sh);
471
+ }
472
+ tcg_gen_add_vec(vece, d, d, t);
473
+ tcg_temp_free_vec(t);
474
+}
475
+
476
+void gen_gvec_ursra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
477
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
478
+{
479
+ static const TCGOpcode vecop_list[] = {
480
+ INDEX_op_shri_vec, INDEX_op_add_vec, 0
481
+ };
482
+ static const GVecGen2i ops[4] = {
483
+ { .fni8 = gen_ursra8_i64,
484
+ .fniv = gen_ursra_vec,
485
+ .fno = gen_helper_gvec_ursra_b,
486
+ .opt_opc = vecop_list,
487
+ .load_dest = true,
488
+ .vece = MO_8 },
489
+ { .fni8 = gen_ursra16_i64,
490
+ .fniv = gen_ursra_vec,
491
+ .fno = gen_helper_gvec_ursra_h,
492
+ .opt_opc = vecop_list,
493
+ .load_dest = true,
494
+ .vece = MO_16 },
495
+ { .fni4 = gen_ursra32_i32,
496
+ .fniv = gen_ursra_vec,
497
+ .fno = gen_helper_gvec_ursra_s,
498
+ .opt_opc = vecop_list,
499
+ .load_dest = true,
500
+ .vece = MO_32 },
501
+ { .fni8 = gen_ursra64_i64,
502
+ .fniv = gen_ursra_vec,
503
+ .fno = gen_helper_gvec_ursra_d,
504
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
505
+ .opt_opc = vecop_list,
506
+ .load_dest = true,
507
+ .vece = MO_64 },
508
+ };
509
+
510
+ /* tszimm encoding produces immediates in the range [1..esize] */
511
+ tcg_debug_assert(shift > 0);
512
+ tcg_debug_assert(shift <= (8 << vece));
513
+
514
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
515
+}
516
+
517
static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
518
{
519
uint64_t mask = dup_const(MO_8, 0xff >> shift);
520
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
521
}
522
return 0;
523
524
+ case 2: /* VRSHR */
525
+ /* Right shift comes here negative. */
526
+ shift = -shift;
527
+ if (u) {
528
+ gen_gvec_urshr(size, rd_ofs, rm_ofs, shift,
529
+ vec_size, vec_size);
530
+ } else {
531
+ gen_gvec_srshr(size, rd_ofs, rm_ofs, shift,
532
+ vec_size, vec_size);
533
+ }
534
+ return 0;
535
+
536
+ case 3: /* VRSRA */
537
+ /* Right shift comes here negative. */
538
+ shift = -shift;
539
+ if (u) {
540
+ gen_gvec_ursra(size, rd_ofs, rm_ofs, shift,
541
+ vec_size, vec_size);
542
+ } else {
543
+ gen_gvec_srsra(size, rd_ofs, rm_ofs, shift,
544
+ vec_size, vec_size);
545
+ }
546
+ return 0;
547
+
548
case 4: /* VSRI */
549
if (!u) {
550
return 1;
551
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
552
neon_load_reg64(cpu_V0, rm + pass);
553
tcg_gen_movi_i64(cpu_V1, imm);
554
switch (op) {
555
- case 2: /* VRSHR */
556
- case 3: /* VRSRA */
557
- if (u)
558
- gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
559
- else
560
- gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
561
- break;
562
case 6: /* VQSHLU */
563
gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
564
cpu_V0, cpu_V1);
565
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
566
default:
567
g_assert_not_reached();
568
}
569
- if (op == 3) {
570
- /* Accumulate. */
571
- neon_load_reg64(cpu_V1, rd + pass);
572
- tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
573
- }
574
neon_store_reg64(cpu_V0, rd + pass);
575
} else { /* size < 3 */
576
/* Operands in T0 and T1. */
577
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
578
tmp2 = tcg_temp_new_i32();
579
tcg_gen_movi_i32(tmp2, imm);
580
switch (op) {
581
- case 2: /* VRSHR */
582
- case 3: /* VRSRA */
583
- GEN_NEON_INTEGER_OP(rshl);
584
- break;
585
case 6: /* VQSHLU */
586
switch (size) {
587
case 0:
588
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
589
g_assert_not_reached();
590
}
591
tcg_temp_free_i32(tmp2);
71
-
592
-
72
-/* tsc2005.c */
593
- if (op == 3) {
73
-void *tsc2005_init(qemu_irq pintdav);
594
- /* Accumulate. */
74
-uint32_t tsc2005_txrx(void *opaque, uint32_t value, int len);
595
- tmp2 = neon_load_reg(rd, pass);
75
-void tsc2005_set_transform(void *opaque, MouseTransformInfo *info);
596
- gen_neon_add(size, tmp, tmp2);
76
-
597
- tcg_temp_free_i32(tmp2);
77
#endif
598
- }
78
diff --git a/include/hw/input/tsc2xxx.h b/include/hw/input/tsc2xxx.h
599
neon_store_reg(rd, pass, tmp);
79
new file mode 100644
600
}
80
index XXXXXXX..XXXXXXX
601
} /* for pass */
81
--- /dev/null
602
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
82
+++ b/include/hw/input/tsc2xxx.h
83
@@ -XXX,XX +XXX,XX @@
84
+/*
85
+ * TI touchscreen controller
86
+ *
87
+ * Copyright (c) 2006 Andrzej Zaborowski
88
+ * Copyright (C) 2008 Nokia Corporation
89
+ *
90
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
91
+ * See the COPYING file in the top-level directory.
92
+ */
93
+
94
+#ifndef HW_INPUT_TSC2XXX_H
95
+#define HW_INPUT_TSC2XXX_H
96
+
97
+#include "hw/irq.h"
98
+#include "ui/console.h"
99
+
100
+typedef struct uWireSlave {
101
+ uint16_t (*receive)(void *opaque);
102
+ void (*send)(void *opaque, uint16_t data);
103
+ void *opaque;
104
+} uWireSlave;
105
+
106
+/* tsc210x.c */
107
+uWireSlave *tsc2102_init(qemu_irq pint);
108
+uWireSlave *tsc2301_init(qemu_irq penirq, qemu_irq kbirq, qemu_irq dav);
109
+I2SCodec *tsc210x_codec(uWireSlave *chip);
110
+uint32_t tsc210x_txrx(void *opaque, uint32_t value, int len);
111
+void tsc210x_set_transform(uWireSlave *chip, MouseTransformInfo *info);
112
+void tsc210x_key_event(uWireSlave *chip, int key, int down);
113
+
114
+/* tsc2005.c */
115
+void *tsc2005_init(qemu_irq pintdav);
116
+uint32_t tsc2005_txrx(void *opaque, uint32_t value, int len);
117
+void tsc2005_set_transform(void *opaque, MouseTransformInfo *info);
118
+
119
+#endif
120
diff --git a/include/qemu/typedefs.h b/include/qemu/typedefs.h
121
index XXXXXXX..XXXXXXX 100644
603
index XXXXXXX..XXXXXXX 100644
122
--- a/include/qemu/typedefs.h
604
--- a/target/arm/vec_helper.c
123
+++ b/include/qemu/typedefs.h
605
+++ b/target/arm/vec_helper.c
124
@@ -XXX,XX +XXX,XX @@ typedef struct RAMBlock RAMBlock;
606
@@ -XXX,XX +XXX,XX @@ DO_SRA(gvec_usra_d, uint64_t)
125
typedef struct Range Range;
607
126
typedef struct SHPCDevice SHPCDevice;
608
#undef DO_SRA
127
typedef struct SSIBus SSIBus;
609
128
-typedef struct uWireSlave uWireSlave;
610
+#define DO_RSHR(NAME, TYPE) \
129
typedef struct VirtIODevice VirtIODevice;
611
+void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \
130
typedef struct Visitor Visitor;
612
+{ \
131
typedef void SaveStateHandler(QEMUFile *f, void *opaque);
613
+ intptr_t i, oprsz = simd_oprsz(desc); \
132
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
614
+ int shift = simd_data(desc); \
133
index XXXXXXX..XXXXXXX 100644
615
+ TYPE *d = vd, *n = vn; \
134
--- a/hw/arm/nseries.c
616
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
135
+++ b/hw/arm/nseries.c
617
+ TYPE tmp = n[i] >> (shift - 1); \
136
@@ -XXX,XX +XXX,XX @@
618
+ d[i] = (tmp >> 1) + (tmp & 1); \
137
#include "ui/console.h"
619
+ } \
138
#include "hw/boards.h"
620
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
139
#include "hw/i2c/i2c.h"
621
+}
140
-#include "hw/devices.h"
622
+
141
#include "hw/display/blizzard.h"
623
+DO_RSHR(gvec_srshr_b, int8_t)
142
+#include "hw/input/tsc2xxx.h"
624
+DO_RSHR(gvec_srshr_h, int16_t)
143
#include "hw/misc/cbus.h"
625
+DO_RSHR(gvec_srshr_s, int32_t)
144
#include "hw/misc/tmp105.h"
626
+DO_RSHR(gvec_srshr_d, int64_t)
145
#include "hw/block/flash.h"
627
+
146
diff --git a/hw/arm/palm.c b/hw/arm/palm.c
628
+DO_RSHR(gvec_urshr_b, uint8_t)
147
index XXXXXXX..XXXXXXX 100644
629
+DO_RSHR(gvec_urshr_h, uint16_t)
148
--- a/hw/arm/palm.c
630
+DO_RSHR(gvec_urshr_s, uint32_t)
149
+++ b/hw/arm/palm.c
631
+DO_RSHR(gvec_urshr_d, uint64_t)
150
@@ -XXX,XX +XXX,XX @@
632
+
151
#include "hw/arm/omap.h"
633
+#undef DO_RSHR
152
#include "hw/boards.h"
634
+
153
#include "hw/arm/arm.h"
635
+#define DO_RSRA(NAME, TYPE) \
154
-#include "hw/devices.h"
636
+void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \
155
+#include "hw/input/tsc2xxx.h"
637
+{ \
156
#include "hw/loader.h"
638
+ intptr_t i, oprsz = simd_oprsz(desc); \
157
#include "exec/address-spaces.h"
639
+ int shift = simd_data(desc); \
158
#include "cpu.h"
640
+ TYPE *d = vd, *n = vn; \
159
diff --git a/hw/input/tsc2005.c b/hw/input/tsc2005.c
641
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
160
index XXXXXXX..XXXXXXX 100644
642
+ TYPE tmp = n[i] >> (shift - 1); \
161
--- a/hw/input/tsc2005.c
643
+ d[i] += (tmp >> 1) + (tmp & 1); \
162
+++ b/hw/input/tsc2005.c
644
+ } \
163
@@ -XXX,XX +XXX,XX @@
645
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
164
#include "hw/hw.h"
646
+}
165
#include "qemu/timer.h"
647
+
166
#include "ui/console.h"
648
+DO_RSRA(gvec_srsra_b, int8_t)
167
-#include "hw/devices.h"
649
+DO_RSRA(gvec_srsra_h, int16_t)
168
+#include "hw/input/tsc2xxx.h"
650
+DO_RSRA(gvec_srsra_s, int32_t)
169
#include "trace.h"
651
+DO_RSRA(gvec_srsra_d, int64_t)
170
652
+
171
#define TSC_CUT_RESOLUTION(value, p)    ((value) >> (16 - (p ? 12 : 10)))
653
+DO_RSRA(gvec_ursra_b, uint8_t)
172
diff --git a/hw/input/tsc210x.c b/hw/input/tsc210x.c
654
+DO_RSRA(gvec_ursra_h, uint16_t)
173
index XXXXXXX..XXXXXXX 100644
655
+DO_RSRA(gvec_ursra_s, uint32_t)
174
--- a/hw/input/tsc210x.c
656
+DO_RSRA(gvec_ursra_d, uint64_t)
175
+++ b/hw/input/tsc210x.c
657
+
176
@@ -XXX,XX +XXX,XX @@
658
+#undef DO_RSRA
177
#include "audio/audio.h"
659
+
178
#include "qemu/timer.h"
660
/*
179
#include "ui/console.h"
661
* Convert float16 to float32, raising no exceptions and
180
-#include "hw/arm/omap.h"    /* For I2SCodec and uWireSlave */
662
* preserving exceptional values, including SNaN.
181
-#include "hw/devices.h"
182
+#include "hw/arm/omap.h" /* For I2SCodec */
183
+#include "hw/input/tsc2xxx.h"
184
185
#define TSC_DATA_REGISTERS_PAGE        0x0
186
#define TSC_CONTROL_REGISTERS_PAGE    0x1
187
diff --git a/MAINTAINERS b/MAINTAINERS
188
index XXXXXXX..XXXXXXX 100644
189
--- a/MAINTAINERS
190
+++ b/MAINTAINERS
191
@@ -XXX,XX +XXX,XX @@ F: hw/input/tsc2005.c
192
F: hw/misc/cbus.c
193
F: hw/timer/twl92230.c
194
F: include/hw/display/blizzard.h
195
+F: include/hw/input/tsc2xxx.h
196
F: include/hw/misc/cbus.h
197
198
Palm
199
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
200
S: Odd Fixes
201
F: hw/arm/palm.c
202
F: hw/input/tsc210x.c
203
+F: include/hw/input/tsc2xxx.h
204
205
Raspberry Pi
206
M: Peter Maydell <peter.maydell@linaro.org>
207
--
663
--
208
2.20.1
664
2.20.1
209
665
210
666
diff view generated by jsdifflib
1
The M-profile architecture floating point system supports
1
From: Richard Henderson <richard.henderson@linaro.org>
2
lazy FP state preservation, where FP registers are not
2
3
pushed to the stack when an exception occurs but are instead
3
The functions eliminate duplication of the special cases for
4
only saved if and when the first FP instruction in the exception
4
this operation. They match up with the GVecGen2iFn typedef.
5
handler is executed. Implement this in QEMU, corresponding
5
6
to the check of LSPACT in the pseudocode ExecuteFPCheck().
6
Add out-of-line helpers. We got away with only having inline
7
7
expanders because the neon vector size is only 16 bytes, and
8
we know that the inline expansion will always succeed.
9
When we reuse this for SVE, tcg-gvec-op may decide to use an
10
out-of-line helper due to longer vector lengths.
11
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20200513163245.17915-4-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20190416125744.27770-24-peter.maydell@linaro.org
11
---
16
---
12
target/arm/cpu.h | 3 ++
17
target/arm/helper.h | 10 ++
13
target/arm/helper.h | 2 +
18
target/arm/translate.h | 7 +-
14
target/arm/translate.h | 1 +
19
target/arm/translate-a64.c | 20 +---
15
target/arm/helper.c | 112 +++++++++++++++++++++++++++++++++++++++++
20
target/arm/translate.c | 186 +++++++++++++++++++++----------------
16
target/arm/translate.c | 22 ++++++++
21
target/arm/vec_helper.c | 38 ++++++++
17
5 files changed, 140 insertions(+)
22
5 files changed, 160 insertions(+), 101 deletions(-)
18
23
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.h
22
+++ b/target/arm/cpu.h
23
@@ -XXX,XX +XXX,XX @@
24
#define EXCP_NOCP 17 /* v7M NOCP UsageFault */
25
#define EXCP_INVSTATE 18 /* v7M INVSTATE UsageFault */
26
#define EXCP_STKOF 19 /* v8M STKOF UsageFault */
27
+#define EXCP_LAZYFP 20 /* v7M fault during lazy FP stacking */
28
/* NB: add new EXCP_ defines to the array in arm_log_exception() too */
29
30
#define ARMV7M_EXCP_RESET 1
31
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, NS, 6, 1)
32
FIELD(TBFLAG_A32, VFPEN, 7, 1)
33
FIELD(TBFLAG_A32, CONDEXEC, 8, 8)
34
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
35
+/* For M profile only, set if FPCCR.LSPACT is set */
36
+FIELD(TBFLAG_A32, LSPACT, 18, 1)
37
/* For M profile only, set if we must create a new FP context */
38
FIELD(TBFLAG_A32, NEW_FP_CTXT_NEEDED, 19, 1)
39
/* For M profile only, set if FPCCR.S does not match current security state */
40
diff --git a/target/arm/helper.h b/target/arm/helper.h
24
diff --git a/target/arm/helper.h b/target/arm/helper.h
41
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/helper.h
26
--- a/target/arm/helper.h
43
+++ b/target/arm/helper.h
27
+++ b/target/arm/helper.h
44
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(v7m_blxns, void, env, i32)
28
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(gvec_ursra_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
45
29
DEF_HELPER_FLAGS_3(gvec_ursra_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
46
DEF_HELPER_3(v7m_tt, i32, env, i32, i32)
30
DEF_HELPER_FLAGS_3(gvec_ursra_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
47
31
48
+DEF_HELPER_1(v7m_preserve_fp_state, void, env)
32
+DEF_HELPER_FLAGS_3(gvec_sri_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
49
+
33
+DEF_HELPER_FLAGS_3(gvec_sri_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
50
DEF_HELPER_2(v8m_stackcheck, void, env, i32)
34
+DEF_HELPER_FLAGS_3(gvec_sri_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
51
35
+DEF_HELPER_FLAGS_3(gvec_sri_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
52
DEF_HELPER_4(access_check_cp_reg, void, env, ptr, i32, i32)
36
+
37
+DEF_HELPER_FLAGS_3(gvec_sli_b, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
38
+DEF_HELPER_FLAGS_3(gvec_sli_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
39
+DEF_HELPER_FLAGS_3(gvec_sli_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
40
+DEF_HELPER_FLAGS_3(gvec_sli_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
41
+
42
#ifdef TARGET_AARCH64
43
#include "helper-a64.h"
44
#include "helper-sve.h"
53
diff --git a/target/arm/translate.h b/target/arm/translate.h
45
diff --git a/target/arm/translate.h b/target/arm/translate.h
54
index XXXXXXX..XXXXXXX 100644
46
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/translate.h
47
--- a/target/arm/translate.h
56
+++ b/target/arm/translate.h
48
+++ b/target/arm/translate.h
57
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
49
@@ -XXX,XX +XXX,XX @@ extern const GVecGen3 mls_op[4];
58
bool v8m_stackcheck; /* true if we need to perform v8M stack limit checks */
50
extern const GVecGen3 cmtst_op[4];
59
bool v8m_fpccr_s_wrong; /* true if v8M FPCCR.S != v8m_secure */
51
extern const GVecGen3 sshl_op[4];
60
bool v7m_new_fp_ctxt_needed; /* ASPEN set but no active FP context */
52
extern const GVecGen3 ushl_op[4];
61
+ bool v7m_lspact; /* FPCCR.LSPACT set */
53
-extern const GVecGen2i sri_op[4];
62
/* Immediate value in AArch32 SVC insn; must be set if is_jmp == DISAS_SWI
54
-extern const GVecGen2i sli_op[4];
63
* so that top level loop can generate correct syndrome information.
55
extern const GVecGen4 uqadd_op[4];
64
*/
56
extern const GVecGen4 sqadd_op[4];
65
diff --git a/target/arm/helper.c b/target/arm/helper.c
57
extern const GVecGen4 uqsub_op[4];
58
@@ -XXX,XX +XXX,XX @@ void gen_gvec_srsra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
59
void gen_gvec_ursra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
60
int64_t shift, uint32_t opr_sz, uint32_t max_sz);
61
62
+void gen_gvec_sri(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
63
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
64
+void gen_gvec_sli(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
65
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz);
66
+
67
/*
68
* Forward to the isar_feature_* tests given a DisasContext pointer.
69
*/
70
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
66
index XXXXXXX..XXXXXXX 100644
71
index XXXXXXX..XXXXXXX 100644
67
--- a/target/arm/helper.c
72
--- a/target/arm/translate-a64.c
68
+++ b/target/arm/helper.c
73
+++ b/target/arm/translate-a64.c
69
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
74
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_op2(DisasContext *s, bool is_q, int rd,
70
g_assert_not_reached();
75
is_q ? 16 : 8, vec_full_reg_size(s), gvec_op);
71
}
76
}
72
77
73
+void HELPER(v7m_preserve_fp_state)(CPUARMState *env)
78
-/* Expand a 2-operand + immediate AdvSIMD vector operation using
74
+{
79
- * an op descriptor.
75
+ /* translate.c should never generate calls here in user-only mode */
80
- */
76
+ g_assert_not_reached();
81
-static void gen_gvec_op2i(DisasContext *s, bool is_q, int rd,
77
+}
82
- int rn, int64_t imm, const GVecGen2i *gvec_op)
78
+
83
-{
79
uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op)
84
- tcg_gen_gvec_2i(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
80
{
85
- is_q ? 16 : 8, vec_full_reg_size(s), imm, gvec_op);
81
/* The TT instructions can be used by unprivileged code, but in
86
-}
82
@@ -XXX,XX +XXX,XX @@ pend_fault:
87
-
83
return false;
88
/* Expand a 3-operand AdvSIMD vector operation using an op descriptor. */
89
static void gen_gvec_op3(DisasContext *s, bool is_q, int rd,
90
int rn, int rm, const GVecGen3 *gvec_op)
91
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
92
gen_gvec_fn2i(s, is_q, rd, rn, shift,
93
is_u ? gen_gvec_usra : gen_gvec_ssra, size);
94
return;
95
+
96
case 0x08: /* SRI */
97
- /* Shift count same as element size is valid but does nothing. */
98
- if (shift == 8 << size) {
99
- goto done;
100
- }
101
- gen_gvec_op2i(s, is_q, rd, rn, shift, &sri_op[size]);
102
+ gen_gvec_fn2i(s, is_q, rd, rn, shift, gen_gvec_sri, size);
103
return;
104
105
case 0x00: /* SSHR / USHR */
106
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
107
}
108
tcg_temp_free_i64(tcg_round);
109
110
- done:
111
clear_vec_high(s, is_q, rd);
84
}
112
}
85
113
86
+void HELPER(v7m_preserve_fp_state)(CPUARMState *env)
114
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shli(DisasContext *s, bool is_q, bool insert,
87
+{
88
+ /*
89
+ * Preserve FP state (because LSPACT was set and we are about
90
+ * to execute an FP instruction). This corresponds to the
91
+ * PreserveFPState() pseudocode.
92
+ * We may throw an exception if the stacking fails.
93
+ */
94
+ ARMCPU *cpu = arm_env_get_cpu(env);
95
+ bool is_secure = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK;
96
+ bool negpri = !(env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_HFRDY_MASK);
97
+ bool is_priv = !(env->v7m.fpccr[is_secure] & R_V7M_FPCCR_USER_MASK);
98
+ bool splimviol = env->v7m.fpccr[is_secure] & R_V7M_FPCCR_SPLIMVIOL_MASK;
99
+ uint32_t fpcar = env->v7m.fpcar[is_secure];
100
+ bool stacked_ok = true;
101
+ bool ts = is_secure && (env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_TS_MASK);
102
+ bool take_exception;
103
+
104
+ /* Take the iothread lock as we are going to touch the NVIC */
105
+ qemu_mutex_lock_iothread();
106
+
107
+ /* Check the background context had access to the FPU */
108
+ if (!v7m_cpacr_pass(env, is_secure, is_priv)) {
109
+ armv7m_nvic_set_pending_lazyfp(env->nvic, ARMV7M_EXCP_USAGE, is_secure);
110
+ env->v7m.cfsr[is_secure] |= R_V7M_CFSR_NOCP_MASK;
111
+ stacked_ok = false;
112
+ } else if (!is_secure && !extract32(env->v7m.nsacr, 10, 1)) {
113
+ armv7m_nvic_set_pending_lazyfp(env->nvic, ARMV7M_EXCP_USAGE, M_REG_S);
114
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_NOCP_MASK;
115
+ stacked_ok = false;
116
+ }
117
+
118
+ if (!splimviol && stacked_ok) {
119
+ /* We only stack if the stack limit wasn't violated */
120
+ int i;
121
+ ARMMMUIdx mmu_idx;
122
+
123
+ mmu_idx = arm_v7m_mmu_idx_all(env, is_secure, is_priv, negpri);
124
+ for (i = 0; i < (ts ? 32 : 16); i += 2) {
125
+ uint64_t dn = *aa32_vfp_dreg(env, i / 2);
126
+ uint32_t faddr = fpcar + 4 * i;
127
+ uint32_t slo = extract64(dn, 0, 32);
128
+ uint32_t shi = extract64(dn, 32, 32);
129
+
130
+ if (i >= 16) {
131
+ faddr += 8; /* skip the slot for the FPSCR */
132
+ }
133
+ stacked_ok = stacked_ok &&
134
+ v7m_stack_write(cpu, faddr, slo, mmu_idx, STACK_LAZYFP) &&
135
+ v7m_stack_write(cpu, faddr + 4, shi, mmu_idx, STACK_LAZYFP);
136
+ }
137
+
138
+ stacked_ok = stacked_ok &&
139
+ v7m_stack_write(cpu, fpcar + 0x40,
140
+ vfp_get_fpscr(env), mmu_idx, STACK_LAZYFP);
141
+ }
142
+
143
+ /*
144
+ * We definitely pended an exception, but it's possible that it
145
+ * might not be able to be taken now. If its priority permits us
146
+ * to take it now, then we must not update the LSPACT or FP regs,
147
+ * but instead jump out to take the exception immediately.
148
+ * If it's just pending and won't be taken until the current
149
+ * handler exits, then we do update LSPACT and the FP regs.
150
+ */
151
+ take_exception = !stacked_ok &&
152
+ armv7m_nvic_can_take_pending_exception(env->nvic);
153
+
154
+ qemu_mutex_unlock_iothread();
155
+
156
+ if (take_exception) {
157
+ raise_exception_ra(env, EXCP_LAZYFP, 0, 1, GETPC());
158
+ }
159
+
160
+ env->v7m.fpccr[is_secure] &= ~R_V7M_FPCCR_LSPACT_MASK;
161
+
162
+ if (ts) {
163
+ /* Clear s0 to s31 and the FPSCR */
164
+ int i;
165
+
166
+ for (i = 0; i < 32; i += 2) {
167
+ *aa32_vfp_dreg(env, i / 2) = 0;
168
+ }
169
+ vfp_set_fpscr(env, 0);
170
+ }
171
+ /*
172
+ * Otherwise s0 to s15 and FPSCR are UNKNOWN; we choose to leave them
173
+ * unchanged.
174
+ */
175
+}
176
+
177
/* Write to v7M CONTROL.SPSEL bit for the specified security bank.
178
* This may change the current stack pointer between Main and Process
179
* stack pointers if it is done for the CONTROL register for the current
180
@@ -XXX,XX +XXX,XX @@ static void arm_log_exception(int idx)
181
[EXCP_NOCP] = "v7M NOCP UsageFault",
182
[EXCP_INVSTATE] = "v7M INVSTATE UsageFault",
183
[EXCP_STKOF] = "v8M STKOF UsageFault",
184
+ [EXCP_LAZYFP] = "v7M exception during lazy FP stacking",
185
};
186
187
if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
188
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
189
return;
190
}
191
break;
192
+ case EXCP_LAZYFP:
193
+ /*
194
+ * We already pended the specific exception in the NVIC in the
195
+ * v7m_preserve_fp_state() helper function.
196
+ */
197
+ break;
198
default:
199
cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
200
return; /* Never happens. Keep compiler happy. */
201
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
202
flags = FIELD_DP32(flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED, 1);
203
}
115
}
204
116
205
+ if (arm_feature(env, ARM_FEATURE_M)) {
117
if (insert) {
206
+ bool is_secure = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK;
118
- gen_gvec_op2i(s, is_q, rd, rn, shift, &sli_op[size]);
207
+
119
+ gen_gvec_fn2i(s, is_q, rd, rn, shift, gen_gvec_sli, size);
208
+ if (env->v7m.fpccr[is_secure] & R_V7M_FPCCR_LSPACT_MASK) {
120
} else {
209
+ flags = FIELD_DP32(flags, TBFLAG_A32, LSPACT, 1);
121
gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_shli, size);
210
+ }
122
}
211
+ }
212
+
213
*pflags = flags;
214
*cs_base = 0;
215
}
216
diff --git a/target/arm/translate.c b/target/arm/translate.c
123
diff --git a/target/arm/translate.c b/target/arm/translate.c
217
index XXXXXXX..XXXXXXX 100644
124
index XXXXXXX..XXXXXXX 100644
218
--- a/target/arm/translate.c
125
--- a/target/arm/translate.c
219
+++ b/target/arm/translate.c
126
+++ b/target/arm/translate.c
220
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
127
@@ -XXX,XX +XXX,XX @@ static void gen_shr64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
221
if (arm_dc_feature(s, ARM_FEATURE_M)) {
128
222
/* Handle M-profile lazy FP state mechanics */
129
static void gen_shr_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
223
130
{
224
+ /* Trigger lazy-state preservation if necessary */
131
- if (sh == 0) {
225
+ if (s->v7m_lspact) {
132
- tcg_gen_mov_vec(d, a);
226
+ /*
133
- } else {
227
+ * Lazy state saving affects external memory and also the NVIC,
134
- TCGv_vec t = tcg_temp_new_vec_matching(d);
228
+ * so we must mark it as an IO operation for icount.
135
- TCGv_vec m = tcg_temp_new_vec_matching(d);
229
+ */
136
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
230
+ if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
137
+ TCGv_vec m = tcg_temp_new_vec_matching(d);
231
+ gen_io_start();
138
232
+ }
139
- tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh));
233
+ gen_helper_v7m_preserve_fp_state(cpu_env);
140
- tcg_gen_shri_vec(vece, t, a, sh);
234
+ if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
141
- tcg_gen_and_vec(vece, d, d, m);
235
+ gen_io_end();
142
- tcg_gen_or_vec(vece, d, d, t);
236
+ }
143
+ tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK((8 << vece) - sh, sh));
237
+ /*
144
+ tcg_gen_shri_vec(vece, t, a, sh);
238
+ * If the preserve_fp_state helper doesn't throw an exception
145
+ tcg_gen_and_vec(vece, d, d, m);
239
+ * then it will clear LSPACT; we don't need to repeat this for
146
+ tcg_gen_or_vec(vece, d, d, t);
240
+ * any further FP insns in this TB.
147
241
+ */
148
- tcg_temp_free_vec(t);
242
+ s->v7m_lspact = false;
149
- tcg_temp_free_vec(m);
243
+ }
150
- }
244
+
151
+ tcg_temp_free_vec(t);
245
/* Update ownership of FP context: set FPCCR.S to match current state */
152
+ tcg_temp_free_vec(m);
246
if (s->v8m_fpccr_s_wrong) {
153
}
247
TCGv_i32 tmp;
154
248
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
155
-static const TCGOpcode vecop_list_sri[] = { INDEX_op_shri_vec, 0 };
249
dc->v8m_fpccr_s_wrong = FIELD_EX32(tb_flags, TBFLAG_A32, FPCCR_S_WRONG);
156
+void gen_gvec_sri(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
250
dc->v7m_new_fp_ctxt_needed =
157
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
251
FIELD_EX32(tb_flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED);
158
+{
252
+ dc->v7m_lspact = FIELD_EX32(tb_flags, TBFLAG_A32, LSPACT);
159
+ static const TCGOpcode vecop_list[] = { INDEX_op_shri_vec, 0 };
253
dc->cp_regs = cpu->cp_regs;
160
+ const GVecGen2i ops[4] = {
254
dc->features = env->features;
161
+ { .fni8 = gen_shr8_ins_i64,
255
162
+ .fniv = gen_shr_ins_vec,
163
+ .fno = gen_helper_gvec_sri_b,
164
+ .load_dest = true,
165
+ .opt_opc = vecop_list,
166
+ .vece = MO_8 },
167
+ { .fni8 = gen_shr16_ins_i64,
168
+ .fniv = gen_shr_ins_vec,
169
+ .fno = gen_helper_gvec_sri_h,
170
+ .load_dest = true,
171
+ .opt_opc = vecop_list,
172
+ .vece = MO_16 },
173
+ { .fni4 = gen_shr32_ins_i32,
174
+ .fniv = gen_shr_ins_vec,
175
+ .fno = gen_helper_gvec_sri_s,
176
+ .load_dest = true,
177
+ .opt_opc = vecop_list,
178
+ .vece = MO_32 },
179
+ { .fni8 = gen_shr64_ins_i64,
180
+ .fniv = gen_shr_ins_vec,
181
+ .fno = gen_helper_gvec_sri_d,
182
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
183
+ .load_dest = true,
184
+ .opt_opc = vecop_list,
185
+ .vece = MO_64 },
186
+ };
187
188
-const GVecGen2i sri_op[4] = {
189
- { .fni8 = gen_shr8_ins_i64,
190
- .fniv = gen_shr_ins_vec,
191
- .load_dest = true,
192
- .opt_opc = vecop_list_sri,
193
- .vece = MO_8 },
194
- { .fni8 = gen_shr16_ins_i64,
195
- .fniv = gen_shr_ins_vec,
196
- .load_dest = true,
197
- .opt_opc = vecop_list_sri,
198
- .vece = MO_16 },
199
- { .fni4 = gen_shr32_ins_i32,
200
- .fniv = gen_shr_ins_vec,
201
- .load_dest = true,
202
- .opt_opc = vecop_list_sri,
203
- .vece = MO_32 },
204
- { .fni8 = gen_shr64_ins_i64,
205
- .fniv = gen_shr_ins_vec,
206
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
207
- .load_dest = true,
208
- .opt_opc = vecop_list_sri,
209
- .vece = MO_64 },
210
-};
211
+ /* tszimm encoding produces immediates in the range [1..esize]. */
212
+ tcg_debug_assert(shift > 0);
213
+ tcg_debug_assert(shift <= (8 << vece));
214
+
215
+ /* Shift of esize leaves destination unchanged. */
216
+ if (shift < (8 << vece)) {
217
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
218
+ } else {
219
+ /* Nop, but we do need to clear the tail. */
220
+ tcg_gen_gvec_mov(vece, rd_ofs, rd_ofs, opr_sz, max_sz);
221
+ }
222
+}
223
224
static void gen_shl8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
225
{
226
@@ -XXX,XX +XXX,XX @@ static void gen_shl64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
227
228
static void gen_shl_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
229
{
230
- if (sh == 0) {
231
- tcg_gen_mov_vec(d, a);
232
- } else {
233
- TCGv_vec t = tcg_temp_new_vec_matching(d);
234
- TCGv_vec m = tcg_temp_new_vec_matching(d);
235
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
236
+ TCGv_vec m = tcg_temp_new_vec_matching(d);
237
238
- tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh));
239
- tcg_gen_shli_vec(vece, t, a, sh);
240
- tcg_gen_and_vec(vece, d, d, m);
241
- tcg_gen_or_vec(vece, d, d, t);
242
+ tcg_gen_shli_vec(vece, t, a, sh);
243
+ tcg_gen_dupi_vec(vece, m, MAKE_64BIT_MASK(0, sh));
244
+ tcg_gen_and_vec(vece, d, d, m);
245
+ tcg_gen_or_vec(vece, d, d, t);
246
247
- tcg_temp_free_vec(t);
248
- tcg_temp_free_vec(m);
249
- }
250
+ tcg_temp_free_vec(t);
251
+ tcg_temp_free_vec(m);
252
}
253
254
-static const TCGOpcode vecop_list_sli[] = { INDEX_op_shli_vec, 0 };
255
+void gen_gvec_sli(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
256
+ int64_t shift, uint32_t opr_sz, uint32_t max_sz)
257
+{
258
+ static const TCGOpcode vecop_list[] = { INDEX_op_shli_vec, 0 };
259
+ const GVecGen2i ops[4] = {
260
+ { .fni8 = gen_shl8_ins_i64,
261
+ .fniv = gen_shl_ins_vec,
262
+ .fno = gen_helper_gvec_sli_b,
263
+ .load_dest = true,
264
+ .opt_opc = vecop_list,
265
+ .vece = MO_8 },
266
+ { .fni8 = gen_shl16_ins_i64,
267
+ .fniv = gen_shl_ins_vec,
268
+ .fno = gen_helper_gvec_sli_h,
269
+ .load_dest = true,
270
+ .opt_opc = vecop_list,
271
+ .vece = MO_16 },
272
+ { .fni4 = gen_shl32_ins_i32,
273
+ .fniv = gen_shl_ins_vec,
274
+ .fno = gen_helper_gvec_sli_s,
275
+ .load_dest = true,
276
+ .opt_opc = vecop_list,
277
+ .vece = MO_32 },
278
+ { .fni8 = gen_shl64_ins_i64,
279
+ .fniv = gen_shl_ins_vec,
280
+ .fno = gen_helper_gvec_sli_d,
281
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
282
+ .load_dest = true,
283
+ .opt_opc = vecop_list,
284
+ .vece = MO_64 },
285
+ };
286
287
-const GVecGen2i sli_op[4] = {
288
- { .fni8 = gen_shl8_ins_i64,
289
- .fniv = gen_shl_ins_vec,
290
- .load_dest = true,
291
- .opt_opc = vecop_list_sli,
292
- .vece = MO_8 },
293
- { .fni8 = gen_shl16_ins_i64,
294
- .fniv = gen_shl_ins_vec,
295
- .load_dest = true,
296
- .opt_opc = vecop_list_sli,
297
- .vece = MO_16 },
298
- { .fni4 = gen_shl32_ins_i32,
299
- .fniv = gen_shl_ins_vec,
300
- .load_dest = true,
301
- .opt_opc = vecop_list_sli,
302
- .vece = MO_32 },
303
- { .fni8 = gen_shl64_ins_i64,
304
- .fniv = gen_shl_ins_vec,
305
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
306
- .load_dest = true,
307
- .opt_opc = vecop_list_sli,
308
- .vece = MO_64 },
309
-};
310
+ /* tszimm encoding produces immediates in the range [0..esize-1]. */
311
+ tcg_debug_assert(shift >= 0);
312
+ tcg_debug_assert(shift < (8 << vece));
313
+
314
+ if (shift == 0) {
315
+ tcg_gen_gvec_mov(vece, rd_ofs, rm_ofs, opr_sz, max_sz);
316
+ } else {
317
+ tcg_gen_gvec_2i(rd_ofs, rm_ofs, opr_sz, max_sz, shift, &ops[vece]);
318
+ }
319
+}
320
321
static void gen_mla8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
322
{
323
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
324
}
325
/* Right shift comes here negative. */
326
shift = -shift;
327
- /* Shift out of range leaves destination unchanged. */
328
- if (shift < 8 << size) {
329
- tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size, vec_size,
330
- shift, &sri_op[size]);
331
- }
332
+ gen_gvec_sri(size, rd_ofs, rm_ofs, shift,
333
+ vec_size, vec_size);
334
return 0;
335
336
case 5: /* VSHL, VSLI */
337
if (u) { /* VSLI */
338
- /* Shift out of range leaves destination unchanged. */
339
- if (shift < 8 << size) {
340
- tcg_gen_gvec_2i(rd_ofs, rm_ofs, vec_size,
341
- vec_size, shift, &sli_op[size]);
342
- }
343
+ gen_gvec_sli(size, rd_ofs, rm_ofs, shift,
344
+ vec_size, vec_size);
345
} else { /* VSHL */
346
/* Shifts larger than the element size are
347
* architecturally valid and results in zero.
348
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
349
index XXXXXXX..XXXXXXX 100644
350
--- a/target/arm/vec_helper.c
351
+++ b/target/arm/vec_helper.c
352
@@ -XXX,XX +XXX,XX @@ DO_RSRA(gvec_ursra_d, uint64_t)
353
354
#undef DO_RSRA
355
356
+#define DO_SRI(NAME, TYPE) \
357
+void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \
358
+{ \
359
+ intptr_t i, oprsz = simd_oprsz(desc); \
360
+ int shift = simd_data(desc); \
361
+ TYPE *d = vd, *n = vn; \
362
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
363
+ d[i] = deposit64(d[i], 0, sizeof(TYPE) * 8 - shift, n[i] >> shift); \
364
+ } \
365
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
366
+}
367
+
368
+DO_SRI(gvec_sri_b, uint8_t)
369
+DO_SRI(gvec_sri_h, uint16_t)
370
+DO_SRI(gvec_sri_s, uint32_t)
371
+DO_SRI(gvec_sri_d, uint64_t)
372
+
373
+#undef DO_SRI
374
+
375
+#define DO_SLI(NAME, TYPE) \
376
+void HELPER(NAME)(void *vd, void *vn, uint32_t desc) \
377
+{ \
378
+ intptr_t i, oprsz = simd_oprsz(desc); \
379
+ int shift = simd_data(desc); \
380
+ TYPE *d = vd, *n = vn; \
381
+ for (i = 0; i < oprsz / sizeof(TYPE); i++) { \
382
+ d[i] = deposit64(d[i], shift, sizeof(TYPE) * 8 - shift, n[i]); \
383
+ } \
384
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
385
+}
386
+
387
+DO_SLI(gvec_sli_b, uint8_t)
388
+DO_SLI(gvec_sli_h, uint16_t)
389
+DO_SLI(gvec_sli_s, uint32_t)
390
+DO_SLI(gvec_sli_d, uint64_t)
391
+
392
+#undef DO_SLI
393
+
394
/*
395
* Convert float16 to float32, raising no exceptions and
396
* preserving exceptional values, including SNaN.
256
--
397
--
257
2.20.1
398
2.20.1
258
399
259
400
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Markus Armbruster <armbru@redhat.com>
3
In 1dc8425e551, while converting to gvec, I added an extra range check
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
4
against the shift count. This was unnecessary because the encoding of
5
Message-id: 20190412165416.7977-8-philmd@redhat.com
5
the shift count produces 0 to the element size - 1.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200513163245.17915-5-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
11
---
8
include/hw/devices.h | 3 ---
12
target/arm/translate.c | 12 ++----------
9
include/hw/input/gamepad.h | 19 +++++++++++++++++++
13
1 file changed, 2 insertions(+), 10 deletions(-)
10
hw/arm/stellaris.c | 2 +-
11
hw/input/stellaris_input.c | 2 +-
12
MAINTAINERS | 1 +
13
5 files changed, 22 insertions(+), 5 deletions(-)
14
create mode 100644 include/hw/input/gamepad.h
15
14
16
diff --git a/include/hw/devices.h b/include/hw/devices.h
15
diff --git a/target/arm/translate.c b/target/arm/translate.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/devices.h
17
--- a/target/arm/translate.c
19
+++ b/include/hw/devices.h
18
+++ b/target/arm/translate.c
20
@@ -XXX,XX +XXX,XX @@ void *tsc2005_init(qemu_irq pintdav);
19
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
21
uint32_t tsc2005_txrx(void *opaque, uint32_t value, int len);
20
gen_gvec_sli(size, rd_ofs, rm_ofs, shift,
22
void tsc2005_set_transform(void *opaque, MouseTransformInfo *info);
21
vec_size, vec_size);
23
22
} else { /* VSHL */
24
-/* stellaris_input.c */
23
- /* Shifts larger than the element size are
25
-void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode);
24
- * architecturally valid and results in zero.
26
-
25
- */
27
#endif
26
- if (shift >= 8 << size) {
28
diff --git a/include/hw/input/gamepad.h b/include/hw/input/gamepad.h
27
- tcg_gen_gvec_dup_imm(size, rd_ofs,
29
new file mode 100644
28
- vec_size, vec_size, 0);
30
index XXXXXXX..XXXXXXX
29
- } else {
31
--- /dev/null
30
- tcg_gen_gvec_shli(size, rd_ofs, rm_ofs, shift,
32
+++ b/include/hw/input/gamepad.h
31
- vec_size, vec_size);
33
@@ -XXX,XX +XXX,XX @@
32
- }
34
+/*
33
+ tcg_gen_gvec_shli(size, rd_ofs, rm_ofs, shift,
35
+ * Gamepad style buttons connected to IRQ/GPIO lines
34
+ vec_size, vec_size);
36
+ *
35
}
37
+ * Copyright (c) 2007 CodeSourcery.
36
return 0;
38
+ * Written by Paul Brook
37
}
39
+ *
40
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
41
+ * See the COPYING file in the top-level directory.
42
+ */
43
+
44
+#ifndef HW_INPUT_GAMEPAD_H
45
+#define HW_INPUT_GAMEPAD_H
46
+
47
+#include "hw/irq.h"
48
+
49
+/* stellaris_input.c */
50
+void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode);
51
+
52
+#endif
53
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/hw/arm/stellaris.c
56
+++ b/hw/arm/stellaris.c
57
@@ -XXX,XX +XXX,XX @@
58
#include "hw/sysbus.h"
59
#include "hw/ssi/ssi.h"
60
#include "hw/arm/arm.h"
61
-#include "hw/devices.h"
62
#include "qemu/timer.h"
63
#include "hw/i2c/i2c.h"
64
#include "net/net.h"
65
@@ -XXX,XX +XXX,XX @@
66
#include "sysemu/sysemu.h"
67
#include "hw/arm/armv7m.h"
68
#include "hw/char/pl011.h"
69
+#include "hw/input/gamepad.h"
70
#include "hw/watchdog/cmsdk-apb-watchdog.h"
71
#include "hw/misc/unimp.h"
72
#include "cpu.h"
73
diff --git a/hw/input/stellaris_input.c b/hw/input/stellaris_input.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/hw/input/stellaris_input.c
76
+++ b/hw/input/stellaris_input.c
77
@@ -XXX,XX +XXX,XX @@
78
*/
79
#include "qemu/osdep.h"
80
#include "hw/hw.h"
81
-#include "hw/devices.h"
82
+#include "hw/input/gamepad.h"
83
#include "ui/console.h"
84
85
typedef struct {
86
diff --git a/MAINTAINERS b/MAINTAINERS
87
index XXXXXXX..XXXXXXX 100644
88
--- a/MAINTAINERS
89
+++ b/MAINTAINERS
90
@@ -XXX,XX +XXX,XX @@ M: Peter Maydell <peter.maydell@linaro.org>
91
L: qemu-arm@nongnu.org
92
S: Maintained
93
F: hw/*/stellaris*
94
+F: include/hw/input/gamepad.h
95
96
Versatile Express
97
M: Peter Maydell <peter.maydell@linaro.org>
98
--
38
--
99
2.20.1
39
2.20.1
100
40
101
41
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Now that we've converted all cases to gvec, there is quite a bit
4
of dead code at the end of the function. Remove it.
5
6
Sink the call to gen_gvec_fn2i to the end, loading a function
7
pointer within the switch statement.
8
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20200513163245.17915-6-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
target/arm/translate-a64.c | 56 ++++++++++----------------------------
15
1 file changed, 14 insertions(+), 42 deletions(-)
16
17
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/translate-a64.c
20
+++ b/target/arm/translate-a64.c
21
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
22
int size = 32 - clz32(immh) - 1;
23
int immhb = immh << 3 | immb;
24
int shift = 2 * (8 << size) - immhb;
25
- bool accumulate = false;
26
- int dsize = is_q ? 128 : 64;
27
- int esize = 8 << size;
28
- int elements = dsize/esize;
29
- MemOp memop = size | (is_u ? 0 : MO_SIGN);
30
- TCGv_i64 tcg_rn = new_tmp_a64(s);
31
- TCGv_i64 tcg_rd = new_tmp_a64(s);
32
- TCGv_i64 tcg_round;
33
- uint64_t round_const;
34
- int i;
35
+ GVecGen2iFn *gvec_fn;
36
37
if (extract32(immh, 3, 1) && !is_q) {
38
unallocated_encoding(s);
39
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
40
41
switch (opcode) {
42
case 0x02: /* SSRA / USRA (accumulate) */
43
- gen_gvec_fn2i(s, is_q, rd, rn, shift,
44
- is_u ? gen_gvec_usra : gen_gvec_ssra, size);
45
- return;
46
+ gvec_fn = is_u ? gen_gvec_usra : gen_gvec_ssra;
47
+ break;
48
49
case 0x08: /* SRI */
50
- gen_gvec_fn2i(s, is_q, rd, rn, shift, gen_gvec_sri, size);
51
- return;
52
+ gvec_fn = gen_gvec_sri;
53
+ break;
54
55
case 0x00: /* SSHR / USHR */
56
if (is_u) {
57
@@ -XXX,XX +XXX,XX @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
58
/* Shift count the same size as element size produces zero. */
59
tcg_gen_gvec_dup_imm(size, vec_full_reg_offset(s, rd),
60
is_q ? 16 : 8, vec_full_reg_size(s), 0);
61
- } else {
62
- gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_shri, size);
63
+ return;
64
}
65
+ gvec_fn = tcg_gen_gvec_shri;
66
} else {
67
/* Shift count the same size as element size produces all sign. */
68
if (shift == 8 << size) {
69
shift -= 1;
70
}
71
- gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_sari, size);
72
+ gvec_fn = tcg_gen_gvec_sari;
73
}
74
- return;
75
+ break;
76
77
case 0x04: /* SRSHR / URSHR (rounding) */
78
- gen_gvec_fn2i(s, is_q, rd, rn, shift,
79
- is_u ? gen_gvec_urshr : gen_gvec_srshr, size);
80
- return;
81
+ gvec_fn = is_u ? gen_gvec_urshr : gen_gvec_srshr;
82
+ break;
83
84
case 0x06: /* SRSRA / URSRA (accum + rounding) */
85
- gen_gvec_fn2i(s, is_q, rd, rn, shift,
86
- is_u ? gen_gvec_ursra : gen_gvec_srsra, size);
87
- return;
88
+ gvec_fn = is_u ? gen_gvec_ursra : gen_gvec_srsra;
89
+ break;
90
91
default:
92
g_assert_not_reached();
93
}
94
95
- round_const = 1ULL << (shift - 1);
96
- tcg_round = tcg_const_i64(round_const);
97
-
98
- for (i = 0; i < elements; i++) {
99
- read_vec_element(s, tcg_rn, rn, i, memop);
100
- if (accumulate) {
101
- read_vec_element(s, tcg_rd, rd, i, memop);
102
- }
103
-
104
- handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
105
- accumulate, is_u, size, shift);
106
-
107
- write_vec_element(s, tcg_rd, rd, i, size);
108
- }
109
- tcg_temp_free_i64(tcg_round);
110
-
111
- clear_vec_high(s, is_q, rd);
112
+ gen_gvec_fn2i(s, is_q, rd, rn, shift, gvec_fn, size);
113
}
114
115
/* SHL/SLI - Vector shift left */
116
--
117
2.20.1
118
119
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Markus Armbruster <armbru@redhat.com>
3
Provide a functional interface for the vector expansion.
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
4
This fits better with the existing set of helpers that
5
Message-id: 20190412165416.7977-12-philmd@redhat.com
5
we provide for other operations.
6
7
Macro-ize the 5 nearly identical comparisons.
8
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20200513163245.17915-7-richard.henderson@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
13
---
8
include/hw/net/lan9118.h | 2 ++
14
target/arm/translate.h | 16 ++-
9
hw/arm/exynos4_boards.c | 3 ++-
15
target/arm/translate-a64.c | 22 ++--
10
hw/arm/mps2-tz.c | 3 ++-
16
target/arm/translate.c | 254 ++++++++-----------------------------
11
hw/net/lan9118.c | 1 -
17
3 files changed, 74 insertions(+), 218 deletions(-)
12
4 files changed, 6 insertions(+), 3 deletions(-)
18
13
19
diff --git a/target/arm/translate.h b/target/arm/translate.h
14
diff --git a/include/hw/net/lan9118.h b/include/hw/net/lan9118.h
15
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/net/lan9118.h
21
--- a/target/arm/translate.h
17
+++ b/include/hw/net/lan9118.h
22
+++ b/target/arm/translate.h
18
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@ static inline void gen_swstep_exception(DisasContext *s, int isv, int ex)
19
#include "hw/irq.h"
24
uint64_t vfp_expand_imm(int size, uint8_t imm8);
20
#include "net/net.h"
25
21
26
/* Vector operations shared between ARM and AArch64. */
22
+#define TYPE_LAN9118 "lan9118"
27
-extern const GVecGen2 ceq0_op[4];
28
-extern const GVecGen2 clt0_op[4];
29
-extern const GVecGen2 cgt0_op[4];
30
-extern const GVecGen2 cle0_op[4];
31
-extern const GVecGen2 cge0_op[4];
32
+void gen_gvec_ceq0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
33
+ uint32_t opr_sz, uint32_t max_sz);
34
+void gen_gvec_clt0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
35
+ uint32_t opr_sz, uint32_t max_sz);
36
+void gen_gvec_cgt0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
37
+ uint32_t opr_sz, uint32_t max_sz);
38
+void gen_gvec_cle0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
39
+ uint32_t opr_sz, uint32_t max_sz);
40
+void gen_gvec_cge0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
41
+ uint32_t opr_sz, uint32_t max_sz);
23
+
42
+
24
void lan9118_init(NICInfo *, uint32_t, qemu_irq);
43
extern const GVecGen3 mla_op[4];
25
44
extern const GVecGen3 mls_op[4];
26
#endif
45
extern const GVecGen3 cmtst_op[4];
27
diff --git a/hw/arm/exynos4_boards.c b/hw/arm/exynos4_boards.c
46
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
28
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/arm/exynos4_boards.c
48
--- a/target/arm/translate-a64.c
30
+++ b/hw/arm/exynos4_boards.c
49
+++ b/target/arm/translate-a64.c
31
@@ -XXX,XX +XXX,XX @@
50
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_fn4(DisasContext *s, bool is_q, int rd, int rn, int rm,
32
#include "hw/arm/arm.h"
51
is_q ? 16 : 8, vec_full_reg_size(s));
33
#include "exec/address-spaces.h"
52
}
34
#include "hw/arm/exynos4210.h"
53
35
+#include "hw/net/lan9118.h"
54
-/* Expand a 2-operand AdvSIMD vector operation using an op descriptor. */
36
#include "hw/boards.h"
55
-static void gen_gvec_op2(DisasContext *s, bool is_q, int rd,
37
56
- int rn, const GVecGen2 *gvec_op)
38
#undef DEBUG
57
-{
39
@@ -XXX,XX +XXX,XX @@ static void lan9215_init(uint32_t base, qemu_irq irq)
58
- tcg_gen_gvec_2(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
40
/* This should be a 9215 but the 9118 is close enough */
59
- is_q ? 16 : 8, vec_full_reg_size(s), gvec_op);
41
if (nd_table[0].used) {
60
-}
42
qemu_check_nic_model(&nd_table[0], "lan9118");
61
-
43
- dev = qdev_create(NULL, "lan9118");
62
/* Expand a 3-operand AdvSIMD vector operation using an op descriptor. */
44
+ dev = qdev_create(NULL, TYPE_LAN9118);
63
static void gen_gvec_op3(DisasContext *s, bool is_q, int rd,
45
qdev_set_nic_properties(dev, &nd_table[0]);
64
int rn, int rm, const GVecGen3 *gvec_op)
46
qdev_prop_set_uint32(dev, "mode_16bit", 1);
65
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
47
qdev_init_nofail(dev);
66
}
48
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
67
break;
68
case 0x8: /* CMGT, CMGE */
69
- gen_gvec_op2(s, is_q, rd, rn, u ? &cge0_op[size] : &cgt0_op[size]);
70
+ if (u) {
71
+ gen_gvec_fn2(s, is_q, rd, rn, gen_gvec_cge0, size);
72
+ } else {
73
+ gen_gvec_fn2(s, is_q, rd, rn, gen_gvec_cgt0, size);
74
+ }
75
return;
76
case 0x9: /* CMEQ, CMLE */
77
- gen_gvec_op2(s, is_q, rd, rn, u ? &cle0_op[size] : &ceq0_op[size]);
78
+ if (u) {
79
+ gen_gvec_fn2(s, is_q, rd, rn, gen_gvec_cle0, size);
80
+ } else {
81
+ gen_gvec_fn2(s, is_q, rd, rn, gen_gvec_ceq0, size);
82
+ }
83
return;
84
case 0xa: /* CMLT */
85
- gen_gvec_op2(s, is_q, rd, rn, &clt0_op[size]);
86
+ gen_gvec_fn2(s, is_q, rd, rn, gen_gvec_clt0, size);
87
return;
88
case 0xb:
89
if (u) { /* ABS, NEG */
90
diff --git a/target/arm/translate.c b/target/arm/translate.c
49
index XXXXXXX..XXXXXXX 100644
91
index XXXXXXX..XXXXXXX 100644
50
--- a/hw/arm/mps2-tz.c
92
--- a/target/arm/translate.c
51
+++ b/hw/arm/mps2-tz.c
93
+++ b/target/arm/translate.c
52
@@ -XXX,XX +XXX,XX @@
94
@@ -XXX,XX +XXX,XX @@ static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
53
#include "hw/arm/armsse.h"
95
return 1;
54
#include "hw/dma/pl080.h"
96
}
55
#include "hw/ssi/pl022.h"
97
56
+#include "hw/net/lan9118.h"
98
-static void gen_ceq0_i32(TCGv_i32 d, TCGv_i32 a)
57
#include "net/net.h"
99
-{
58
#include "hw/core/split-irq.h"
100
- tcg_gen_setcondi_i32(TCG_COND_EQ, d, a, 0);
59
101
- tcg_gen_neg_i32(d, d);
60
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
102
-}
61
* except that it doesn't support the checksum-offload feature.
103
-
62
*/
104
-static void gen_ceq0_i64(TCGv_i64 d, TCGv_i64 a)
63
qemu_check_nic_model(nd, "lan9118");
105
-{
64
- mms->lan9118 = qdev_create(NULL, "lan9118");
106
- tcg_gen_setcondi_i64(TCG_COND_EQ, d, a, 0);
65
+ mms->lan9118 = qdev_create(NULL, TYPE_LAN9118);
107
- tcg_gen_neg_i64(d, d);
66
qdev_set_nic_properties(mms->lan9118, nd);
108
-}
67
qdev_init_nofail(mms->lan9118);
109
-
68
110
-static void gen_ceq0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
69
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
111
-{
70
index XXXXXXX..XXXXXXX 100644
112
- TCGv_vec zero = tcg_const_zeros_vec_matching(d);
71
--- a/hw/net/lan9118.c
113
- tcg_gen_cmp_vec(TCG_COND_EQ, vece, d, a, zero);
72
+++ b/hw/net/lan9118.c
114
- tcg_temp_free_vec(zero);
73
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_lan9118_packet = {
115
-}
74
}
116
+#define GEN_CMP0(NAME, COND) \
117
+ static void gen_##NAME##0_i32(TCGv_i32 d, TCGv_i32 a) \
118
+ { \
119
+ tcg_gen_setcondi_i32(COND, d, a, 0); \
120
+ tcg_gen_neg_i32(d, d); \
121
+ } \
122
+ static void gen_##NAME##0_i64(TCGv_i64 d, TCGv_i64 a) \
123
+ { \
124
+ tcg_gen_setcondi_i64(COND, d, a, 0); \
125
+ tcg_gen_neg_i64(d, d); \
126
+ } \
127
+ static void gen_##NAME##0_vec(unsigned vece, TCGv_vec d, TCGv_vec a) \
128
+ { \
129
+ TCGv_vec zero = tcg_const_zeros_vec_matching(d); \
130
+ tcg_gen_cmp_vec(COND, vece, d, a, zero); \
131
+ tcg_temp_free_vec(zero); \
132
+ } \
133
+ void gen_gvec_##NAME##0(unsigned vece, uint32_t d, uint32_t m, \
134
+ uint32_t opr_sz, uint32_t max_sz) \
135
+ { \
136
+ const GVecGen2 op[4] = { \
137
+ { .fno = gen_helper_gvec_##NAME##0_b, \
138
+ .fniv = gen_##NAME##0_vec, \
139
+ .opt_opc = vecop_list_cmp, \
140
+ .vece = MO_8 }, \
141
+ { .fno = gen_helper_gvec_##NAME##0_h, \
142
+ .fniv = gen_##NAME##0_vec, \
143
+ .opt_opc = vecop_list_cmp, \
144
+ .vece = MO_16 }, \
145
+ { .fni4 = gen_##NAME##0_i32, \
146
+ .fniv = gen_##NAME##0_vec, \
147
+ .opt_opc = vecop_list_cmp, \
148
+ .vece = MO_32 }, \
149
+ { .fni8 = gen_##NAME##0_i64, \
150
+ .fniv = gen_##NAME##0_vec, \
151
+ .opt_opc = vecop_list_cmp, \
152
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64, \
153
+ .vece = MO_64 }, \
154
+ }; \
155
+ tcg_gen_gvec_2(d, m, opr_sz, max_sz, &op[vece]); \
156
+ }
157
158
static const TCGOpcode vecop_list_cmp[] = {
159
INDEX_op_cmp_vec, 0
75
};
160
};
76
161
77
-#define TYPE_LAN9118 "lan9118"
162
-const GVecGen2 ceq0_op[4] = {
78
#define LAN9118(obj) OBJECT_CHECK(lan9118_state, (obj), TYPE_LAN9118)
163
- { .fno = gen_helper_gvec_ceq0_b,
79
164
- .fniv = gen_ceq0_vec,
80
typedef struct {
165
- .opt_opc = vecop_list_cmp,
166
- .vece = MO_8 },
167
- { .fno = gen_helper_gvec_ceq0_h,
168
- .fniv = gen_ceq0_vec,
169
- .opt_opc = vecop_list_cmp,
170
- .vece = MO_16 },
171
- { .fni4 = gen_ceq0_i32,
172
- .fniv = gen_ceq0_vec,
173
- .opt_opc = vecop_list_cmp,
174
- .vece = MO_32 },
175
- { .fni8 = gen_ceq0_i64,
176
- .fniv = gen_ceq0_vec,
177
- .opt_opc = vecop_list_cmp,
178
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
179
- .vece = MO_64 },
180
-};
181
+GEN_CMP0(ceq, TCG_COND_EQ)
182
+GEN_CMP0(cle, TCG_COND_LE)
183
+GEN_CMP0(cge, TCG_COND_GE)
184
+GEN_CMP0(clt, TCG_COND_LT)
185
+GEN_CMP0(cgt, TCG_COND_GT)
186
187
-static void gen_cle0_i32(TCGv_i32 d, TCGv_i32 a)
188
-{
189
- tcg_gen_setcondi_i32(TCG_COND_LE, d, a, 0);
190
- tcg_gen_neg_i32(d, d);
191
-}
192
-
193
-static void gen_cle0_i64(TCGv_i64 d, TCGv_i64 a)
194
-{
195
- tcg_gen_setcondi_i64(TCG_COND_LE, d, a, 0);
196
- tcg_gen_neg_i64(d, d);
197
-}
198
-
199
-static void gen_cle0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
200
-{
201
- TCGv_vec zero = tcg_const_zeros_vec_matching(d);
202
- tcg_gen_cmp_vec(TCG_COND_LE, vece, d, a, zero);
203
- tcg_temp_free_vec(zero);
204
-}
205
-
206
-const GVecGen2 cle0_op[4] = {
207
- { .fno = gen_helper_gvec_cle0_b,
208
- .fniv = gen_cle0_vec,
209
- .opt_opc = vecop_list_cmp,
210
- .vece = MO_8 },
211
- { .fno = gen_helper_gvec_cle0_h,
212
- .fniv = gen_cle0_vec,
213
- .opt_opc = vecop_list_cmp,
214
- .vece = MO_16 },
215
- { .fni4 = gen_cle0_i32,
216
- .fniv = gen_cle0_vec,
217
- .opt_opc = vecop_list_cmp,
218
- .vece = MO_32 },
219
- { .fni8 = gen_cle0_i64,
220
- .fniv = gen_cle0_vec,
221
- .opt_opc = vecop_list_cmp,
222
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
223
- .vece = MO_64 },
224
-};
225
-
226
-static void gen_cge0_i32(TCGv_i32 d, TCGv_i32 a)
227
-{
228
- tcg_gen_setcondi_i32(TCG_COND_GE, d, a, 0);
229
- tcg_gen_neg_i32(d, d);
230
-}
231
-
232
-static void gen_cge0_i64(TCGv_i64 d, TCGv_i64 a)
233
-{
234
- tcg_gen_setcondi_i64(TCG_COND_GE, d, a, 0);
235
- tcg_gen_neg_i64(d, d);
236
-}
237
-
238
-static void gen_cge0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
239
-{
240
- TCGv_vec zero = tcg_const_zeros_vec_matching(d);
241
- tcg_gen_cmp_vec(TCG_COND_GE, vece, d, a, zero);
242
- tcg_temp_free_vec(zero);
243
-}
244
-
245
-const GVecGen2 cge0_op[4] = {
246
- { .fno = gen_helper_gvec_cge0_b,
247
- .fniv = gen_cge0_vec,
248
- .opt_opc = vecop_list_cmp,
249
- .vece = MO_8 },
250
- { .fno = gen_helper_gvec_cge0_h,
251
- .fniv = gen_cge0_vec,
252
- .opt_opc = vecop_list_cmp,
253
- .vece = MO_16 },
254
- { .fni4 = gen_cge0_i32,
255
- .fniv = gen_cge0_vec,
256
- .opt_opc = vecop_list_cmp,
257
- .vece = MO_32 },
258
- { .fni8 = gen_cge0_i64,
259
- .fniv = gen_cge0_vec,
260
- .opt_opc = vecop_list_cmp,
261
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
262
- .vece = MO_64 },
263
-};
264
-
265
-static void gen_clt0_i32(TCGv_i32 d, TCGv_i32 a)
266
-{
267
- tcg_gen_setcondi_i32(TCG_COND_LT, d, a, 0);
268
- tcg_gen_neg_i32(d, d);
269
-}
270
-
271
-static void gen_clt0_i64(TCGv_i64 d, TCGv_i64 a)
272
-{
273
- tcg_gen_setcondi_i64(TCG_COND_LT, d, a, 0);
274
- tcg_gen_neg_i64(d, d);
275
-}
276
-
277
-static void gen_clt0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
278
-{
279
- TCGv_vec zero = tcg_const_zeros_vec_matching(d);
280
- tcg_gen_cmp_vec(TCG_COND_LT, vece, d, a, zero);
281
- tcg_temp_free_vec(zero);
282
-}
283
-
284
-const GVecGen2 clt0_op[4] = {
285
- { .fno = gen_helper_gvec_clt0_b,
286
- .fniv = gen_clt0_vec,
287
- .opt_opc = vecop_list_cmp,
288
- .vece = MO_8 },
289
- { .fno = gen_helper_gvec_clt0_h,
290
- .fniv = gen_clt0_vec,
291
- .opt_opc = vecop_list_cmp,
292
- .vece = MO_16 },
293
- { .fni4 = gen_clt0_i32,
294
- .fniv = gen_clt0_vec,
295
- .opt_opc = vecop_list_cmp,
296
- .vece = MO_32 },
297
- { .fni8 = gen_clt0_i64,
298
- .fniv = gen_clt0_vec,
299
- .opt_opc = vecop_list_cmp,
300
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
301
- .vece = MO_64 },
302
-};
303
-
304
-static void gen_cgt0_i32(TCGv_i32 d, TCGv_i32 a)
305
-{
306
- tcg_gen_setcondi_i32(TCG_COND_GT, d, a, 0);
307
- tcg_gen_neg_i32(d, d);
308
-}
309
-
310
-static void gen_cgt0_i64(TCGv_i64 d, TCGv_i64 a)
311
-{
312
- tcg_gen_setcondi_i64(TCG_COND_GT, d, a, 0);
313
- tcg_gen_neg_i64(d, d);
314
-}
315
-
316
-static void gen_cgt0_vec(unsigned vece, TCGv_vec d, TCGv_vec a)
317
-{
318
- TCGv_vec zero = tcg_const_zeros_vec_matching(d);
319
- tcg_gen_cmp_vec(TCG_COND_GT, vece, d, a, zero);
320
- tcg_temp_free_vec(zero);
321
-}
322
-
323
-const GVecGen2 cgt0_op[4] = {
324
- { .fno = gen_helper_gvec_cgt0_b,
325
- .fniv = gen_cgt0_vec,
326
- .opt_opc = vecop_list_cmp,
327
- .vece = MO_8 },
328
- { .fno = gen_helper_gvec_cgt0_h,
329
- .fniv = gen_cgt0_vec,
330
- .opt_opc = vecop_list_cmp,
331
- .vece = MO_16 },
332
- { .fni4 = gen_cgt0_i32,
333
- .fniv = gen_cgt0_vec,
334
- .opt_opc = vecop_list_cmp,
335
- .vece = MO_32 },
336
- { .fni8 = gen_cgt0_i64,
337
- .fniv = gen_cgt0_vec,
338
- .opt_opc = vecop_list_cmp,
339
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
340
- .vece = MO_64 },
341
-};
342
+#undef GEN_CMP0
343
344
static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
345
{
346
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
347
break;
348
349
case NEON_2RM_VCEQ0:
350
- tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
351
- vec_size, &ceq0_op[size]);
352
+ gen_gvec_ceq0(size, rd_ofs, rm_ofs, vec_size, vec_size);
353
break;
354
case NEON_2RM_VCGT0:
355
- tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
356
- vec_size, &cgt0_op[size]);
357
+ gen_gvec_cgt0(size, rd_ofs, rm_ofs, vec_size, vec_size);
358
break;
359
case NEON_2RM_VCLE0:
360
- tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
361
- vec_size, &cle0_op[size]);
362
+ gen_gvec_cle0(size, rd_ofs, rm_ofs, vec_size, vec_size);
363
break;
364
case NEON_2RM_VCGE0:
365
- tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
366
- vec_size, &cge0_op[size]);
367
+ gen_gvec_cge0(size, rd_ofs, rm_ofs, vec_size, vec_size);
368
break;
369
case NEON_2RM_VCLT0:
370
- tcg_gen_gvec_2(rd_ofs, rm_ofs, vec_size,
371
- vec_size, &clt0_op[size]);
372
+ gen_gvec_clt0(size, rd_ofs, rm_ofs, vec_size, vec_size);
373
break;
374
375
default:
81
--
376
--
82
2.20.1
377
2.20.1
83
378
84
379
diff view generated by jsdifflib
New patch
1
1
From: Richard Henderson <richard.henderson@linaro.org>
2
3
Provide a functional interface for the vector expansion.
4
This fits better with the existing set of helpers that
5
we provide for other operations.
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200513163245.17915-8-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/translate.h | 7 +-
13
target/arm/translate-a64.c | 4 +-
14
target/arm/translate-neon.inc.c | 16 +----
15
target/arm/translate.c | 117 +++++++++++++++++---------------
16
4 files changed, 71 insertions(+), 73 deletions(-)
17
18
diff --git a/target/arm/translate.h b/target/arm/translate.h
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/translate.h
21
+++ b/target/arm/translate.h
22
@@ -XXX,XX +XXX,XX @@ void gen_gvec_cle0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
23
void gen_gvec_cge0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
24
uint32_t opr_sz, uint32_t max_sz);
25
26
-extern const GVecGen3 mla_op[4];
27
-extern const GVecGen3 mls_op[4];
28
+void gen_gvec_mla(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
29
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
30
+void gen_gvec_mls(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
31
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
32
+
33
extern const GVecGen3 cmtst_op[4];
34
extern const GVecGen3 sshl_op[4];
35
extern const GVecGen3 ushl_op[4];
36
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/translate-a64.c
39
+++ b/target/arm/translate-a64.c
40
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
41
return;
42
case 0x12: /* MLA, MLS */
43
if (u) {
44
- gen_gvec_op3(s, is_q, rd, rn, rm, &mls_op[size]);
45
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_mls, size);
46
} else {
47
- gen_gvec_op3(s, is_q, rd, rn, rm, &mla_op[size]);
48
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_mla, size);
49
}
50
return;
51
case 0x11:
52
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/translate-neon.inc.c
55
+++ b/target/arm/translate-neon.inc.c
56
@@ -XXX,XX +XXX,XX @@ DO_3SAME_NO_SZ_3(VMAX_U, tcg_gen_gvec_umax)
57
DO_3SAME_NO_SZ_3(VMIN_S, tcg_gen_gvec_smin)
58
DO_3SAME_NO_SZ_3(VMIN_U, tcg_gen_gvec_umin)
59
DO_3SAME_NO_SZ_3(VMUL, tcg_gen_gvec_mul)
60
+DO_3SAME_NO_SZ_3(VMLA, gen_gvec_mla)
61
+DO_3SAME_NO_SZ_3(VMLS, gen_gvec_mls)
62
63
#define DO_3SAME_CMP(INSN, COND) \
64
static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
65
@@ -XXX,XX +XXX,XX @@ static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a)
66
return do_3same(s, a, gen_VMUL_p_3s);
67
}
68
69
-#define DO_3SAME_GVEC3_NO_SZ_3(INSN, OPARRAY) \
70
- static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
71
- uint32_t rn_ofs, uint32_t rm_ofs, \
72
- uint32_t oprsz, uint32_t maxsz) \
73
- { \
74
- tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, \
75
- oprsz, maxsz, &OPARRAY[vece]); \
76
- } \
77
- DO_3SAME_NO_SZ_3(INSN, gen_##INSN##_3s)
78
-
79
-
80
-DO_3SAME_GVEC3_NO_SZ_3(VMLA, mla_op)
81
-DO_3SAME_GVEC3_NO_SZ_3(VMLS, mls_op)
82
-
83
#define DO_3SAME_GVEC3_SHIFT(INSN, OPARRAY) \
84
static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
85
uint32_t rn_ofs, uint32_t rm_ofs, \
86
diff --git a/target/arm/translate.c b/target/arm/translate.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/target/arm/translate.c
89
+++ b/target/arm/translate.c
90
@@ -XXX,XX +XXX,XX @@ static void gen_mls_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
91
/* Note that while NEON does not support VMLA and VMLS as 64-bit ops,
92
* these tables are shared with AArch64 which does support them.
93
*/
94
+void gen_gvec_mla(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
95
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
96
+{
97
+ static const TCGOpcode vecop_list[] = {
98
+ INDEX_op_mul_vec, INDEX_op_add_vec, 0
99
+ };
100
+ static const GVecGen3 ops[4] = {
101
+ { .fni4 = gen_mla8_i32,
102
+ .fniv = gen_mla_vec,
103
+ .load_dest = true,
104
+ .opt_opc = vecop_list,
105
+ .vece = MO_8 },
106
+ { .fni4 = gen_mla16_i32,
107
+ .fniv = gen_mla_vec,
108
+ .load_dest = true,
109
+ .opt_opc = vecop_list,
110
+ .vece = MO_16 },
111
+ { .fni4 = gen_mla32_i32,
112
+ .fniv = gen_mla_vec,
113
+ .load_dest = true,
114
+ .opt_opc = vecop_list,
115
+ .vece = MO_32 },
116
+ { .fni8 = gen_mla64_i64,
117
+ .fniv = gen_mla_vec,
118
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
119
+ .load_dest = true,
120
+ .opt_opc = vecop_list,
121
+ .vece = MO_64 },
122
+ };
123
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
124
+}
125
126
-static const TCGOpcode vecop_list_mla[] = {
127
- INDEX_op_mul_vec, INDEX_op_add_vec, 0
128
-};
129
-
130
-static const TCGOpcode vecop_list_mls[] = {
131
- INDEX_op_mul_vec, INDEX_op_sub_vec, 0
132
-};
133
-
134
-const GVecGen3 mla_op[4] = {
135
- { .fni4 = gen_mla8_i32,
136
- .fniv = gen_mla_vec,
137
- .load_dest = true,
138
- .opt_opc = vecop_list_mla,
139
- .vece = MO_8 },
140
- { .fni4 = gen_mla16_i32,
141
- .fniv = gen_mla_vec,
142
- .load_dest = true,
143
- .opt_opc = vecop_list_mla,
144
- .vece = MO_16 },
145
- { .fni4 = gen_mla32_i32,
146
- .fniv = gen_mla_vec,
147
- .load_dest = true,
148
- .opt_opc = vecop_list_mla,
149
- .vece = MO_32 },
150
- { .fni8 = gen_mla64_i64,
151
- .fniv = gen_mla_vec,
152
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
153
- .load_dest = true,
154
- .opt_opc = vecop_list_mla,
155
- .vece = MO_64 },
156
-};
157
-
158
-const GVecGen3 mls_op[4] = {
159
- { .fni4 = gen_mls8_i32,
160
- .fniv = gen_mls_vec,
161
- .load_dest = true,
162
- .opt_opc = vecop_list_mls,
163
- .vece = MO_8 },
164
- { .fni4 = gen_mls16_i32,
165
- .fniv = gen_mls_vec,
166
- .load_dest = true,
167
- .opt_opc = vecop_list_mls,
168
- .vece = MO_16 },
169
- { .fni4 = gen_mls32_i32,
170
- .fniv = gen_mls_vec,
171
- .load_dest = true,
172
- .opt_opc = vecop_list_mls,
173
- .vece = MO_32 },
174
- { .fni8 = gen_mls64_i64,
175
- .fniv = gen_mls_vec,
176
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
177
- .load_dest = true,
178
- .opt_opc = vecop_list_mls,
179
- .vece = MO_64 },
180
-};
181
+void gen_gvec_mls(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
182
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
183
+{
184
+ static const TCGOpcode vecop_list[] = {
185
+ INDEX_op_mul_vec, INDEX_op_sub_vec, 0
186
+ };
187
+ static const GVecGen3 ops[4] = {
188
+ { .fni4 = gen_mls8_i32,
189
+ .fniv = gen_mls_vec,
190
+ .load_dest = true,
191
+ .opt_opc = vecop_list,
192
+ .vece = MO_8 },
193
+ { .fni4 = gen_mls16_i32,
194
+ .fniv = gen_mls_vec,
195
+ .load_dest = true,
196
+ .opt_opc = vecop_list,
197
+ .vece = MO_16 },
198
+ { .fni4 = gen_mls32_i32,
199
+ .fniv = gen_mls_vec,
200
+ .load_dest = true,
201
+ .opt_opc = vecop_list,
202
+ .vece = MO_32 },
203
+ { .fni8 = gen_mls64_i64,
204
+ .fniv = gen_mls_vec,
205
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
206
+ .load_dest = true,
207
+ .opt_opc = vecop_list,
208
+ .vece = MO_64 },
209
+ };
210
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
211
+}
212
213
/* CMTST : test is "if (X & Y != 0)". */
214
static void gen_cmtst_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
215
--
216
2.20.1
217
218
diff view generated by jsdifflib
New patch
1
From: Richard Henderson <richard.henderson@linaro.org>
1
2
3
Rather than perform the argument swap during code generation,
4
perform it during decode. This means it doesn't have to be
5
special cased later, and we can share code with aarch64 code
6
generation. Hopefully the decode comment addresses any confusion
7
that might arise in between.
8
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20200513163245.17915-9-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
target/arm/neon-dp.decode | 17 +++++++++++++++--
15
target/arm/translate-neon.inc.c | 3 +--
16
2 files changed, 16 insertions(+), 4 deletions(-)
17
18
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/neon-dp.decode
21
+++ b/target/arm/neon-dp.decode
22
@@ -XXX,XX +XXX,XX @@ VCGT_U_3s 1111 001 1 0 . .. .... .... 0011 . . . 0 .... @3same
23
VCGE_S_3s 1111 001 0 0 . .. .... .... 0011 . . . 1 .... @3same
24
VCGE_U_3s 1111 001 1 0 . .. .... .... 0011 . . . 1 .... @3same
25
26
-VSHL_S_3s 1111 001 0 0 . .. .... .... 0100 . . . 0 .... @3same
27
-VSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 0 .... @3same
28
+# The _rev suffix indicates that Vn and Vm are reversed. This is
29
+# the case for shifts. In the Arm ARM these insns are documented
30
+# with the Vm and Vn fields in their usual places, but in the
31
+# assembly the operands are listed "backwards", ie in the order
32
+# Dd, Dm, Dn where other insns use Dd, Dn, Dm. For QEMU we choose
33
+# to consider Vm and Vn as being in different fields in the insn,
34
+# which allows us to avoid special-casing shifts in the trans_
35
+# function code. We would otherwise need to manually swap the operands
36
+# over to call Neon helper functions that are shared with AArch64,
37
+# which does not have this odd reversed-operand situation.
38
+@3same_rev .... ... . . . size:2 .... .... .... . q:1 . . .... \
39
+ &3same vn=%vm_dp vm=%vn_dp vd=%vd_dp
40
+
41
+VSHL_S_3s 1111 001 0 0 . .. .... .... 0100 . . . 0 .... @3same_rev
42
+VSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 0 .... @3same_rev
43
44
VMAX_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 0 .... @3same
45
VMAX_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 0 .... @3same
46
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/translate-neon.inc.c
49
+++ b/target/arm/translate-neon.inc.c
50
@@ -XXX,XX +XXX,XX @@ static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a)
51
uint32_t rn_ofs, uint32_t rm_ofs, \
52
uint32_t oprsz, uint32_t maxsz) \
53
{ \
54
- /* Note the operation is vshl vd,vm,vn */ \
55
- tcg_gen_gvec_3(rd_ofs, rm_ofs, rn_ofs, \
56
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, \
57
oprsz, maxsz, &OPARRAY[vece]); \
58
} \
59
DO_3SAME(INSN, gen_##INSN##_3s)
60
--
61
2.20.1
62
63
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Thomas Huth <thuth@redhat.com>
3
Provide a functional interface for the vector expansion.
4
Reviewed-by: Markus Armbruster <armbru@redhat.com>
4
This fits better with the existing set of helpers that
5
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
we provide for other operations.
6
Message-id: 20190412165416.7977-11-philmd@redhat.com
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200513163245.17915-10-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
11
---
9
include/hw/net/ne2000-isa.h | 6 ++++++
12
target/arm/translate.h | 10 ++-
10
1 file changed, 6 insertions(+)
13
target/arm/translate-a64.c | 18 ++--
11
14
target/arm/translate-neon.inc.c | 23 +----
12
diff --git a/include/hw/net/ne2000-isa.h b/include/hw/net/ne2000-isa.h
15
target/arm/translate.c | 146 +++++++++++++++++---------------
16
4 files changed, 95 insertions(+), 102 deletions(-)
17
18
diff --git a/target/arm/translate.h b/target/arm/translate.h
13
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/net/ne2000-isa.h
20
--- a/target/arm/translate.h
15
+++ b/include/hw/net/ne2000-isa.h
21
+++ b/target/arm/translate.h
16
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@ void gen_gvec_mla(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
17
* This work is licensed under the terms of the GNU GPL, version 2 or later.
23
void gen_gvec_mls(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
18
* See the COPYING file in the top-level directory.
24
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
19
*/
25
26
-extern const GVecGen3 cmtst_op[4];
27
-extern const GVecGen3 sshl_op[4];
28
-extern const GVecGen3 ushl_op[4];
29
+void gen_gvec_cmtst(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
30
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
31
+void gen_gvec_sshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
32
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
33
+void gen_gvec_ushl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
34
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
20
+
35
+
21
+#ifndef HW_NET_NE2K_ISA_H
36
extern const GVecGen4 uqadd_op[4];
22
+#define HW_NET_NE2K_ISA_H
37
extern const GVecGen4 sqadd_op[4];
23
+
38
extern const GVecGen4 uqsub_op[4];
24
#include "hw/hw.h"
39
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
25
#include "hw/qdev.h"
40
index XXXXXXX..XXXXXXX 100644
26
#include "hw/isa/isa.h"
41
--- a/target/arm/translate-a64.c
27
@@ -XXX,XX +XXX,XX @@ static inline ISADevice *isa_ne2000_init(ISABus *bus, int base, int irq,
42
+++ b/target/arm/translate-a64.c
43
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_fn4(DisasContext *s, bool is_q, int rd, int rn, int rm,
44
is_q ? 16 : 8, vec_full_reg_size(s));
45
}
46
47
-/* Expand a 3-operand AdvSIMD vector operation using an op descriptor. */
48
-static void gen_gvec_op3(DisasContext *s, bool is_q, int rd,
49
- int rn, int rm, const GVecGen3 *gvec_op)
50
-{
51
- tcg_gen_gvec_3(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
52
- vec_full_reg_offset(s, rm), is_q ? 16 : 8,
53
- vec_full_reg_size(s), gvec_op);
54
-}
55
-
56
/* Expand a 3-operand operation using an out-of-line helper. */
57
static void gen_gvec_op3_ool(DisasContext *s, bool is_q, int rd,
58
int rn, int rm, int data, gen_helper_gvec_3 *fn)
59
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
60
(u ? uqsub_op : sqsub_op) + size);
61
return;
62
case 0x08: /* SSHL, USHL */
63
- gen_gvec_op3(s, is_q, rd, rn, rm,
64
- u ? &ushl_op[size] : &sshl_op[size]);
65
+ if (u) {
66
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_ushl, size);
67
+ } else {
68
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sshl, size);
69
+ }
70
return;
71
case 0x0c: /* SMAX, UMAX */
72
if (u) {
73
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
74
return;
75
case 0x11:
76
if (!u) { /* CMTST */
77
- gen_gvec_op3(s, is_q, rd, rn, rm, &cmtst_op[size]);
78
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_cmtst, size);
79
return;
80
}
81
/* else CMEQ */
82
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
83
index XXXXXXX..XXXXXXX 100644
84
--- a/target/arm/translate-neon.inc.c
85
+++ b/target/arm/translate-neon.inc.c
86
@@ -XXX,XX +XXX,XX @@ DO_3SAME(VBIC, tcg_gen_gvec_andc)
87
DO_3SAME(VORR, tcg_gen_gvec_or)
88
DO_3SAME(VORN, tcg_gen_gvec_orc)
89
DO_3SAME(VEOR, tcg_gen_gvec_xor)
90
+DO_3SAME(VSHL_S, gen_gvec_sshl)
91
+DO_3SAME(VSHL_U, gen_gvec_ushl)
92
93
/* These insns are all gvec_bitsel but with the inputs in various orders. */
94
#define DO_3SAME_BITSEL(INSN, O1, O2, O3) \
95
@@ -XXX,XX +XXX,XX @@ DO_3SAME_NO_SZ_3(VMIN_U, tcg_gen_gvec_umin)
96
DO_3SAME_NO_SZ_3(VMUL, tcg_gen_gvec_mul)
97
DO_3SAME_NO_SZ_3(VMLA, gen_gvec_mla)
98
DO_3SAME_NO_SZ_3(VMLS, gen_gvec_mls)
99
+DO_3SAME_NO_SZ_3(VTST, gen_gvec_cmtst)
100
101
#define DO_3SAME_CMP(INSN, COND) \
102
static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
103
@@ -XXX,XX +XXX,XX @@ DO_3SAME_CMP(VCGE_S, TCG_COND_GE)
104
DO_3SAME_CMP(VCGE_U, TCG_COND_GEU)
105
DO_3SAME_CMP(VCEQ, TCG_COND_EQ)
106
107
-static void gen_VTST_3s(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
108
- uint32_t rm_ofs, uint32_t oprsz, uint32_t maxsz)
109
-{
110
- tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &cmtst_op[vece]);
111
-}
112
-DO_3SAME_NO_SZ_3(VTST, gen_VTST_3s)
113
-
114
#define DO_3SAME_GVEC4(INSN, OPARRAY) \
115
static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
116
uint32_t rn_ofs, uint32_t rm_ofs, \
117
@@ -XXX,XX +XXX,XX @@ static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a)
28
}
118
}
29
return d;
119
return do_3same(s, a, gen_VMUL_p_3s);
30
}
120
}
31
+
121
-
32
+#endif
122
-#define DO_3SAME_GVEC3_SHIFT(INSN, OPARRAY) \
123
- static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
124
- uint32_t rn_ofs, uint32_t rm_ofs, \
125
- uint32_t oprsz, uint32_t maxsz) \
126
- { \
127
- tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, \
128
- oprsz, maxsz, &OPARRAY[vece]); \
129
- } \
130
- DO_3SAME(INSN, gen_##INSN##_3s)
131
-
132
-DO_3SAME_GVEC3_SHIFT(VSHL_S, sshl_op)
133
-DO_3SAME_GVEC3_SHIFT(VSHL_U, ushl_op)
134
diff --git a/target/arm/translate.c b/target/arm/translate.c
135
index XXXXXXX..XXXXXXX 100644
136
--- a/target/arm/translate.c
137
+++ b/target/arm/translate.c
138
@@ -XXX,XX +XXX,XX @@ static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
139
tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a);
140
}
141
142
-static const TCGOpcode vecop_list_cmtst[] = { INDEX_op_cmp_vec, 0 };
143
-
144
-const GVecGen3 cmtst_op[4] = {
145
- { .fni4 = gen_helper_neon_tst_u8,
146
- .fniv = gen_cmtst_vec,
147
- .opt_opc = vecop_list_cmtst,
148
- .vece = MO_8 },
149
- { .fni4 = gen_helper_neon_tst_u16,
150
- .fniv = gen_cmtst_vec,
151
- .opt_opc = vecop_list_cmtst,
152
- .vece = MO_16 },
153
- { .fni4 = gen_cmtst_i32,
154
- .fniv = gen_cmtst_vec,
155
- .opt_opc = vecop_list_cmtst,
156
- .vece = MO_32 },
157
- { .fni8 = gen_cmtst_i64,
158
- .fniv = gen_cmtst_vec,
159
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
160
- .opt_opc = vecop_list_cmtst,
161
- .vece = MO_64 },
162
-};
163
+void gen_gvec_cmtst(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
164
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
165
+{
166
+ static const TCGOpcode vecop_list[] = { INDEX_op_cmp_vec, 0 };
167
+ static const GVecGen3 ops[4] = {
168
+ { .fni4 = gen_helper_neon_tst_u8,
169
+ .fniv = gen_cmtst_vec,
170
+ .opt_opc = vecop_list,
171
+ .vece = MO_8 },
172
+ { .fni4 = gen_helper_neon_tst_u16,
173
+ .fniv = gen_cmtst_vec,
174
+ .opt_opc = vecop_list,
175
+ .vece = MO_16 },
176
+ { .fni4 = gen_cmtst_i32,
177
+ .fniv = gen_cmtst_vec,
178
+ .opt_opc = vecop_list,
179
+ .vece = MO_32 },
180
+ { .fni8 = gen_cmtst_i64,
181
+ .fniv = gen_cmtst_vec,
182
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
183
+ .opt_opc = vecop_list,
184
+ .vece = MO_64 },
185
+ };
186
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
187
+}
188
189
void gen_ushl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift)
190
{
191
@@ -XXX,XX +XXX,XX @@ static void gen_ushl_vec(unsigned vece, TCGv_vec dst,
192
tcg_temp_free_vec(rsh);
193
}
194
195
-static const TCGOpcode ushl_list[] = {
196
- INDEX_op_neg_vec, INDEX_op_shlv_vec,
197
- INDEX_op_shrv_vec, INDEX_op_cmp_vec, 0
198
-};
199
-
200
-const GVecGen3 ushl_op[4] = {
201
- { .fniv = gen_ushl_vec,
202
- .fno = gen_helper_gvec_ushl_b,
203
- .opt_opc = ushl_list,
204
- .vece = MO_8 },
205
- { .fniv = gen_ushl_vec,
206
- .fno = gen_helper_gvec_ushl_h,
207
- .opt_opc = ushl_list,
208
- .vece = MO_16 },
209
- { .fni4 = gen_ushl_i32,
210
- .fniv = gen_ushl_vec,
211
- .opt_opc = ushl_list,
212
- .vece = MO_32 },
213
- { .fni8 = gen_ushl_i64,
214
- .fniv = gen_ushl_vec,
215
- .opt_opc = ushl_list,
216
- .vece = MO_64 },
217
-};
218
+void gen_gvec_ushl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
219
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
220
+{
221
+ static const TCGOpcode vecop_list[] = {
222
+ INDEX_op_neg_vec, INDEX_op_shlv_vec,
223
+ INDEX_op_shrv_vec, INDEX_op_cmp_vec, 0
224
+ };
225
+ static const GVecGen3 ops[4] = {
226
+ { .fniv = gen_ushl_vec,
227
+ .fno = gen_helper_gvec_ushl_b,
228
+ .opt_opc = vecop_list,
229
+ .vece = MO_8 },
230
+ { .fniv = gen_ushl_vec,
231
+ .fno = gen_helper_gvec_ushl_h,
232
+ .opt_opc = vecop_list,
233
+ .vece = MO_16 },
234
+ { .fni4 = gen_ushl_i32,
235
+ .fniv = gen_ushl_vec,
236
+ .opt_opc = vecop_list,
237
+ .vece = MO_32 },
238
+ { .fni8 = gen_ushl_i64,
239
+ .fniv = gen_ushl_vec,
240
+ .opt_opc = vecop_list,
241
+ .vece = MO_64 },
242
+ };
243
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
244
+}
245
246
void gen_sshl_i32(TCGv_i32 dst, TCGv_i32 src, TCGv_i32 shift)
247
{
248
@@ -XXX,XX +XXX,XX @@ static void gen_sshl_vec(unsigned vece, TCGv_vec dst,
249
tcg_temp_free_vec(tmp);
250
}
251
252
-static const TCGOpcode sshl_list[] = {
253
- INDEX_op_neg_vec, INDEX_op_umin_vec, INDEX_op_shlv_vec,
254
- INDEX_op_sarv_vec, INDEX_op_cmp_vec, INDEX_op_cmpsel_vec, 0
255
-};
256
-
257
-const GVecGen3 sshl_op[4] = {
258
- { .fniv = gen_sshl_vec,
259
- .fno = gen_helper_gvec_sshl_b,
260
- .opt_opc = sshl_list,
261
- .vece = MO_8 },
262
- { .fniv = gen_sshl_vec,
263
- .fno = gen_helper_gvec_sshl_h,
264
- .opt_opc = sshl_list,
265
- .vece = MO_16 },
266
- { .fni4 = gen_sshl_i32,
267
- .fniv = gen_sshl_vec,
268
- .opt_opc = sshl_list,
269
- .vece = MO_32 },
270
- { .fni8 = gen_sshl_i64,
271
- .fniv = gen_sshl_vec,
272
- .opt_opc = sshl_list,
273
- .vece = MO_64 },
274
-};
275
+void gen_gvec_sshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
276
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
277
+{
278
+ static const TCGOpcode vecop_list[] = {
279
+ INDEX_op_neg_vec, INDEX_op_umin_vec, INDEX_op_shlv_vec,
280
+ INDEX_op_sarv_vec, INDEX_op_cmp_vec, INDEX_op_cmpsel_vec, 0
281
+ };
282
+ static const GVecGen3 ops[4] = {
283
+ { .fniv = gen_sshl_vec,
284
+ .fno = gen_helper_gvec_sshl_b,
285
+ .opt_opc = vecop_list,
286
+ .vece = MO_8 },
287
+ { .fniv = gen_sshl_vec,
288
+ .fno = gen_helper_gvec_sshl_h,
289
+ .opt_opc = vecop_list,
290
+ .vece = MO_16 },
291
+ { .fni4 = gen_sshl_i32,
292
+ .fniv = gen_sshl_vec,
293
+ .opt_opc = vecop_list,
294
+ .vece = MO_32 },
295
+ { .fni8 = gen_sshl_i64,
296
+ .fniv = gen_sshl_vec,
297
+ .opt_opc = vecop_list,
298
+ .vece = MO_64 },
299
+ };
300
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
301
+}
302
303
static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
304
TCGv_vec a, TCGv_vec b)
33
--
305
--
34
2.20.1
306
2.20.1
35
307
36
308
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Reviewed-by: Thomas Huth <thuth@redhat.com>
3
Provide a functional interface for the vector expansion.
4
Reviewed-by: Markus Armbruster <armbru@redhat.com>
4
This fits better with the existing set of helpers that
5
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
we provide for other operations.
6
Message-id: 20190412165416.7977-7-philmd@redhat.com
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200513163245.17915-11-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
11
---
9
include/hw/devices.h | 14 --------------
12
target/arm/translate.h | 13 +-
10
include/hw/misc/cbus.h | 32 ++++++++++++++++++++++++++++++++
13
target/arm/translate-a64.c | 22 ++-
11
hw/arm/nseries.c | 1 +
14
target/arm/translate-neon.inc.c | 19 +--
12
hw/misc/cbus.c | 2 +-
15
target/arm/translate.c | 228 +++++++++++++++++---------------
13
MAINTAINERS | 1 +
16
4 files changed, 147 insertions(+), 135 deletions(-)
14
5 files changed, 35 insertions(+), 15 deletions(-)
17
15
create mode 100644 include/hw/misc/cbus.h
18
diff --git a/target/arm/translate.h b/target/arm/translate.h
16
17
diff --git a/include/hw/devices.h b/include/hw/devices.h
18
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/devices.h
20
--- a/target/arm/translate.h
20
+++ b/include/hw/devices.h
21
+++ b/target/arm/translate.h
21
@@ -XXX,XX +XXX,XX @@ void tsc2005_set_transform(void *opaque, MouseTransformInfo *info);
22
@@ -XXX,XX +XXX,XX @@ void gen_gvec_sshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
22
/* stellaris_input.c */
23
void gen_gvec_ushl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
23
void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode);
24
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
24
25
25
-/* cbus.c */
26
-extern const GVecGen4 uqadd_op[4];
26
-typedef struct {
27
-extern const GVecGen4 sqadd_op[4];
27
- qemu_irq clk;
28
-extern const GVecGen4 uqsub_op[4];
28
- qemu_irq dat;
29
-extern const GVecGen4 sqsub_op[4];
29
- qemu_irq sel;
30
void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
30
-} CBus;
31
void gen_ushl_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
31
-CBus *cbus_init(qemu_irq dat_out);
32
void gen_sshl_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
32
-void cbus_attach(CBus *bus, void *slave_opaque);
33
void gen_ushl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
33
-
34
void gen_sshl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
34
-void *retu_init(qemu_irq irq, int vilma);
35
35
-void *tahvo_init(qemu_irq irq, int betty);
36
+void gen_gvec_uqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
36
-
37
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
37
-void retu_key_event(void *retu, int state);
38
+void gen_gvec_sqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
38
-
39
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
39
#endif
40
+void gen_gvec_uqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
40
diff --git a/include/hw/misc/cbus.h b/include/hw/misc/cbus.h
41
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
41
new file mode 100644
42
+void gen_gvec_sqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
42
index XXXXXXX..XXXXXXX
43
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
43
--- /dev/null
44
+++ b/include/hw/misc/cbus.h
45
@@ -XXX,XX +XXX,XX @@
46
+/*
47
+ * CBUS three-pin bus and the Retu / Betty / Tahvo / Vilma / Avilma /
48
+ * Hinku / Vinku / Ahne / Pihi chips used in various Nokia platforms.
49
+ * Based on reverse-engineering of a linux driver.
50
+ *
51
+ * Copyright (C) 2008 Nokia Corporation
52
+ * Written by Andrzej Zaborowski
53
+ *
54
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
55
+ * See the COPYING file in the top-level directory.
56
+ */
57
+
44
+
58
+#ifndef HW_MISC_CBUS_H
45
void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
59
+#define HW_MISC_CBUS_H
46
int64_t shift, uint32_t opr_sz, uint32_t max_sz);
60
+
47
void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
61
+#include "hw/irq.h"
48
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
62
+
63
+typedef struct {
64
+ qemu_irq clk;
65
+ qemu_irq dat;
66
+ qemu_irq sel;
67
+} CBus;
68
+
69
+CBus *cbus_init(qemu_irq dat_out);
70
+void cbus_attach(CBus *bus, void *slave_opaque);
71
+
72
+void *retu_init(qemu_irq irq, int vilma);
73
+void *tahvo_init(qemu_irq irq, int betty);
74
+
75
+void retu_key_event(void *retu, int state);
76
+
77
+#endif
78
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
79
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
80
--- a/hw/arm/nseries.c
50
--- a/target/arm/translate-a64.c
81
+++ b/hw/arm/nseries.c
51
+++ b/target/arm/translate-a64.c
82
@@ -XXX,XX +XXX,XX @@
52
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
83
#include "hw/i2c/i2c.h"
53
84
#include "hw/devices.h"
54
switch (opcode) {
85
#include "hw/display/blizzard.h"
55
case 0x01: /* SQADD, UQADD */
86
+#include "hw/misc/cbus.h"
56
- tcg_gen_gvec_4(vec_full_reg_offset(s, rd),
87
#include "hw/misc/tmp105.h"
57
- offsetof(CPUARMState, vfp.qc),
88
#include "hw/block/flash.h"
58
- vec_full_reg_offset(s, rn),
89
#include "hw/hw.h"
59
- vec_full_reg_offset(s, rm),
90
diff --git a/hw/misc/cbus.c b/hw/misc/cbus.c
60
- is_q ? 16 : 8, vec_full_reg_size(s),
61
- (u ? uqadd_op : sqadd_op) + size);
62
+ if (u) {
63
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_uqadd_qc, size);
64
+ } else {
65
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sqadd_qc, size);
66
+ }
67
return;
68
case 0x05: /* SQSUB, UQSUB */
69
- tcg_gen_gvec_4(vec_full_reg_offset(s, rd),
70
- offsetof(CPUARMState, vfp.qc),
71
- vec_full_reg_offset(s, rn),
72
- vec_full_reg_offset(s, rm),
73
- is_q ? 16 : 8, vec_full_reg_size(s),
74
- (u ? uqsub_op : sqsub_op) + size);
75
+ if (u) {
76
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_uqsub_qc, size);
77
+ } else {
78
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sqsub_qc, size);
79
+ }
80
return;
81
case 0x08: /* SSHL, USHL */
82
if (u) {
83
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
91
index XXXXXXX..XXXXXXX 100644
84
index XXXXXXX..XXXXXXX 100644
92
--- a/hw/misc/cbus.c
85
--- a/target/arm/translate-neon.inc.c
93
+++ b/hw/misc/cbus.c
86
+++ b/target/arm/translate-neon.inc.c
94
@@ -XXX,XX +XXX,XX @@
87
@@ -XXX,XX +XXX,XX @@ DO_3SAME(VORN, tcg_gen_gvec_orc)
95
#include "qemu/osdep.h"
88
DO_3SAME(VEOR, tcg_gen_gvec_xor)
96
#include "hw/hw.h"
89
DO_3SAME(VSHL_S, gen_gvec_sshl)
97
#include "hw/irq.h"
90
DO_3SAME(VSHL_U, gen_gvec_ushl)
98
-#include "hw/devices.h"
91
+DO_3SAME(VQADD_S, gen_gvec_sqadd_qc)
99
+#include "hw/misc/cbus.h"
92
+DO_3SAME(VQADD_U, gen_gvec_uqadd_qc)
100
#include "sysemu/sysemu.h"
93
+DO_3SAME(VQSUB_S, gen_gvec_sqsub_qc)
101
94
+DO_3SAME(VQSUB_U, gen_gvec_uqsub_qc)
102
//#define DEBUG
95
103
diff --git a/MAINTAINERS b/MAINTAINERS
96
/* These insns are all gvec_bitsel but with the inputs in various orders. */
97
#define DO_3SAME_BITSEL(INSN, O1, O2, O3) \
98
@@ -XXX,XX +XXX,XX @@ DO_3SAME_CMP(VCGE_S, TCG_COND_GE)
99
DO_3SAME_CMP(VCGE_U, TCG_COND_GEU)
100
DO_3SAME_CMP(VCEQ, TCG_COND_EQ)
101
102
-#define DO_3SAME_GVEC4(INSN, OPARRAY) \
103
- static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
104
- uint32_t rn_ofs, uint32_t rm_ofs, \
105
- uint32_t oprsz, uint32_t maxsz) \
106
- { \
107
- tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc), \
108
- rn_ofs, rm_ofs, oprsz, maxsz, &OPARRAY[vece]); \
109
- } \
110
- DO_3SAME(INSN, gen_##INSN##_3s)
111
-
112
-DO_3SAME_GVEC4(VQADD_S, sqadd_op)
113
-DO_3SAME_GVEC4(VQADD_U, uqadd_op)
114
-DO_3SAME_GVEC4(VQSUB_S, sqsub_op)
115
-DO_3SAME_GVEC4(VQSUB_U, uqsub_op)
116
-
117
static void gen_VMUL_p_3s(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
118
uint32_t rm_ofs, uint32_t oprsz, uint32_t maxsz)
119
{
120
diff --git a/target/arm/translate.c b/target/arm/translate.c
104
index XXXXXXX..XXXXXXX 100644
121
index XXXXXXX..XXXXXXX 100644
105
--- a/MAINTAINERS
122
--- a/target/arm/translate.c
106
+++ b/MAINTAINERS
123
+++ b/target/arm/translate.c
107
@@ -XXX,XX +XXX,XX @@ F: hw/input/tsc2005.c
124
@@ -XXX,XX +XXX,XX @@ static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
108
F: hw/misc/cbus.c
125
tcg_temp_free_vec(x);
109
F: hw/timer/twl92230.c
126
}
110
F: include/hw/display/blizzard.h
127
111
+F: include/hw/misc/cbus.h
128
-static const TCGOpcode vecop_list_uqadd[] = {
112
129
- INDEX_op_usadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
113
Palm
130
-};
114
M: Andrzej Zaborowski <balrogg@gmail.com>
131
-
132
-const GVecGen4 uqadd_op[4] = {
133
- { .fniv = gen_uqadd_vec,
134
- .fno = gen_helper_gvec_uqadd_b,
135
- .write_aofs = true,
136
- .opt_opc = vecop_list_uqadd,
137
- .vece = MO_8 },
138
- { .fniv = gen_uqadd_vec,
139
- .fno = gen_helper_gvec_uqadd_h,
140
- .write_aofs = true,
141
- .opt_opc = vecop_list_uqadd,
142
- .vece = MO_16 },
143
- { .fniv = gen_uqadd_vec,
144
- .fno = gen_helper_gvec_uqadd_s,
145
- .write_aofs = true,
146
- .opt_opc = vecop_list_uqadd,
147
- .vece = MO_32 },
148
- { .fniv = gen_uqadd_vec,
149
- .fno = gen_helper_gvec_uqadd_d,
150
- .write_aofs = true,
151
- .opt_opc = vecop_list_uqadd,
152
- .vece = MO_64 },
153
-};
154
+void gen_gvec_uqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
155
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
156
+{
157
+ static const TCGOpcode vecop_list[] = {
158
+ INDEX_op_usadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
159
+ };
160
+ static const GVecGen4 ops[4] = {
161
+ { .fniv = gen_uqadd_vec,
162
+ .fno = gen_helper_gvec_uqadd_b,
163
+ .write_aofs = true,
164
+ .opt_opc = vecop_list,
165
+ .vece = MO_8 },
166
+ { .fniv = gen_uqadd_vec,
167
+ .fno = gen_helper_gvec_uqadd_h,
168
+ .write_aofs = true,
169
+ .opt_opc = vecop_list,
170
+ .vece = MO_16 },
171
+ { .fniv = gen_uqadd_vec,
172
+ .fno = gen_helper_gvec_uqadd_s,
173
+ .write_aofs = true,
174
+ .opt_opc = vecop_list,
175
+ .vece = MO_32 },
176
+ { .fniv = gen_uqadd_vec,
177
+ .fno = gen_helper_gvec_uqadd_d,
178
+ .write_aofs = true,
179
+ .opt_opc = vecop_list,
180
+ .vece = MO_64 },
181
+ };
182
+ tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
183
+ rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
184
+}
185
186
static void gen_sqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
187
TCGv_vec a, TCGv_vec b)
188
@@ -XXX,XX +XXX,XX @@ static void gen_sqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
189
tcg_temp_free_vec(x);
190
}
191
192
-static const TCGOpcode vecop_list_sqadd[] = {
193
- INDEX_op_ssadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
194
-};
195
-
196
-const GVecGen4 sqadd_op[4] = {
197
- { .fniv = gen_sqadd_vec,
198
- .fno = gen_helper_gvec_sqadd_b,
199
- .opt_opc = vecop_list_sqadd,
200
- .write_aofs = true,
201
- .vece = MO_8 },
202
- { .fniv = gen_sqadd_vec,
203
- .fno = gen_helper_gvec_sqadd_h,
204
- .opt_opc = vecop_list_sqadd,
205
- .write_aofs = true,
206
- .vece = MO_16 },
207
- { .fniv = gen_sqadd_vec,
208
- .fno = gen_helper_gvec_sqadd_s,
209
- .opt_opc = vecop_list_sqadd,
210
- .write_aofs = true,
211
- .vece = MO_32 },
212
- { .fniv = gen_sqadd_vec,
213
- .fno = gen_helper_gvec_sqadd_d,
214
- .opt_opc = vecop_list_sqadd,
215
- .write_aofs = true,
216
- .vece = MO_64 },
217
-};
218
+void gen_gvec_sqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
219
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
220
+{
221
+ static const TCGOpcode vecop_list[] = {
222
+ INDEX_op_ssadd_vec, INDEX_op_cmp_vec, INDEX_op_add_vec, 0
223
+ };
224
+ static const GVecGen4 ops[4] = {
225
+ { .fniv = gen_sqadd_vec,
226
+ .fno = gen_helper_gvec_sqadd_b,
227
+ .opt_opc = vecop_list,
228
+ .write_aofs = true,
229
+ .vece = MO_8 },
230
+ { .fniv = gen_sqadd_vec,
231
+ .fno = gen_helper_gvec_sqadd_h,
232
+ .opt_opc = vecop_list,
233
+ .write_aofs = true,
234
+ .vece = MO_16 },
235
+ { .fniv = gen_sqadd_vec,
236
+ .fno = gen_helper_gvec_sqadd_s,
237
+ .opt_opc = vecop_list,
238
+ .write_aofs = true,
239
+ .vece = MO_32 },
240
+ { .fniv = gen_sqadd_vec,
241
+ .fno = gen_helper_gvec_sqadd_d,
242
+ .opt_opc = vecop_list,
243
+ .write_aofs = true,
244
+ .vece = MO_64 },
245
+ };
246
+ tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
247
+ rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
248
+}
249
250
static void gen_uqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
251
TCGv_vec a, TCGv_vec b)
252
@@ -XXX,XX +XXX,XX @@ static void gen_uqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
253
tcg_temp_free_vec(x);
254
}
255
256
-static const TCGOpcode vecop_list_uqsub[] = {
257
- INDEX_op_ussub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
258
-};
259
-
260
-const GVecGen4 uqsub_op[4] = {
261
- { .fniv = gen_uqsub_vec,
262
- .fno = gen_helper_gvec_uqsub_b,
263
- .opt_opc = vecop_list_uqsub,
264
- .write_aofs = true,
265
- .vece = MO_8 },
266
- { .fniv = gen_uqsub_vec,
267
- .fno = gen_helper_gvec_uqsub_h,
268
- .opt_opc = vecop_list_uqsub,
269
- .write_aofs = true,
270
- .vece = MO_16 },
271
- { .fniv = gen_uqsub_vec,
272
- .fno = gen_helper_gvec_uqsub_s,
273
- .opt_opc = vecop_list_uqsub,
274
- .write_aofs = true,
275
- .vece = MO_32 },
276
- { .fniv = gen_uqsub_vec,
277
- .fno = gen_helper_gvec_uqsub_d,
278
- .opt_opc = vecop_list_uqsub,
279
- .write_aofs = true,
280
- .vece = MO_64 },
281
-};
282
+void gen_gvec_uqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
283
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
284
+{
285
+ static const TCGOpcode vecop_list[] = {
286
+ INDEX_op_ussub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
287
+ };
288
+ static const GVecGen4 ops[4] = {
289
+ { .fniv = gen_uqsub_vec,
290
+ .fno = gen_helper_gvec_uqsub_b,
291
+ .opt_opc = vecop_list,
292
+ .write_aofs = true,
293
+ .vece = MO_8 },
294
+ { .fniv = gen_uqsub_vec,
295
+ .fno = gen_helper_gvec_uqsub_h,
296
+ .opt_opc = vecop_list,
297
+ .write_aofs = true,
298
+ .vece = MO_16 },
299
+ { .fniv = gen_uqsub_vec,
300
+ .fno = gen_helper_gvec_uqsub_s,
301
+ .opt_opc = vecop_list,
302
+ .write_aofs = true,
303
+ .vece = MO_32 },
304
+ { .fniv = gen_uqsub_vec,
305
+ .fno = gen_helper_gvec_uqsub_d,
306
+ .opt_opc = vecop_list,
307
+ .write_aofs = true,
308
+ .vece = MO_64 },
309
+ };
310
+ tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
311
+ rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
312
+}
313
314
static void gen_sqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
315
TCGv_vec a, TCGv_vec b)
316
@@ -XXX,XX +XXX,XX @@ static void gen_sqsub_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
317
tcg_temp_free_vec(x);
318
}
319
320
-static const TCGOpcode vecop_list_sqsub[] = {
321
- INDEX_op_sssub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
322
-};
323
-
324
-const GVecGen4 sqsub_op[4] = {
325
- { .fniv = gen_sqsub_vec,
326
- .fno = gen_helper_gvec_sqsub_b,
327
- .opt_opc = vecop_list_sqsub,
328
- .write_aofs = true,
329
- .vece = MO_8 },
330
- { .fniv = gen_sqsub_vec,
331
- .fno = gen_helper_gvec_sqsub_h,
332
- .opt_opc = vecop_list_sqsub,
333
- .write_aofs = true,
334
- .vece = MO_16 },
335
- { .fniv = gen_sqsub_vec,
336
- .fno = gen_helper_gvec_sqsub_s,
337
- .opt_opc = vecop_list_sqsub,
338
- .write_aofs = true,
339
- .vece = MO_32 },
340
- { .fniv = gen_sqsub_vec,
341
- .fno = gen_helper_gvec_sqsub_d,
342
- .opt_opc = vecop_list_sqsub,
343
- .write_aofs = true,
344
- .vece = MO_64 },
345
-};
346
+void gen_gvec_sqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
347
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
348
+{
349
+ static const TCGOpcode vecop_list[] = {
350
+ INDEX_op_sssub_vec, INDEX_op_cmp_vec, INDEX_op_sub_vec, 0
351
+ };
352
+ static const GVecGen4 ops[4] = {
353
+ { .fniv = gen_sqsub_vec,
354
+ .fno = gen_helper_gvec_sqsub_b,
355
+ .opt_opc = vecop_list,
356
+ .write_aofs = true,
357
+ .vece = MO_8 },
358
+ { .fniv = gen_sqsub_vec,
359
+ .fno = gen_helper_gvec_sqsub_h,
360
+ .opt_opc = vecop_list,
361
+ .write_aofs = true,
362
+ .vece = MO_16 },
363
+ { .fniv = gen_sqsub_vec,
364
+ .fno = gen_helper_gvec_sqsub_s,
365
+ .opt_opc = vecop_list,
366
+ .write_aofs = true,
367
+ .vece = MO_32 },
368
+ { .fniv = gen_sqsub_vec,
369
+ .fno = gen_helper_gvec_sqsub_d,
370
+ .opt_opc = vecop_list,
371
+ .write_aofs = true,
372
+ .vece = MO_64 },
373
+ };
374
+ tcg_gen_gvec_4(rd_ofs, offsetof(CPUARMState, vfp.qc),
375
+ rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
376
+}
377
378
/* Translate a NEON data processing instruction. Return nonzero if the
379
instruction is invalid.
115
--
380
--
116
2.20.1
381
2.20.1
117
382
118
383
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
No code used the tc6393xb_gpio_in_get() and tc6393xb_gpio_out_set()
3
These operations do not touch fp_status.
4
functions since their introduction in commit 88d2c950b002. Time to
5
remove them.
6
4
7
Suggested-by: Markus Armbruster <armbru@redhat.com>
8
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Message-id: 20190412165416.7977-4-philmd@redhat.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200513163245.17915-12-richard.henderson@linaro.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
9
---
13
include/hw/devices.h | 3 ---
10
target/arm/helper.h | 4 ++--
14
hw/display/tc6393xb.c | 16 ----------------
11
target/arm/translate-a64.c | 5 ++---
15
2 files changed, 19 deletions(-)
12
target/arm/translate.c | 12 ++----------
13
target/arm/vfp_helper.c | 5 ++---
14
4 files changed, 8 insertions(+), 18 deletions(-)
16
15
17
diff --git a/include/hw/devices.h b/include/hw/devices.h
16
diff --git a/target/arm/helper.h b/target/arm/helper.h
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/include/hw/devices.h
18
--- a/target/arm/helper.h
20
+++ b/include/hw/devices.h
19
+++ b/target/arm/helper.h
21
@@ -XXX,XX +XXX,XX @@ void retu_key_event(void *retu, int state);
20
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(recpe_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
22
typedef struct TC6393xbState TC6393xbState;
21
DEF_HELPER_FLAGS_2(rsqrte_f16, TCG_CALL_NO_RWG, f16, f16, ptr)
23
TC6393xbState *tc6393xb_init(struct MemoryRegion *sysmem,
22
DEF_HELPER_FLAGS_2(rsqrte_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
24
uint32_t base, qemu_irq irq);
23
DEF_HELPER_FLAGS_2(rsqrte_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
25
-void tc6393xb_gpio_out_set(TC6393xbState *s, int line,
24
-DEF_HELPER_2(recpe_u32, i32, i32, ptr)
26
- qemu_irq handler);
25
-DEF_HELPER_FLAGS_2(rsqrte_u32, TCG_CALL_NO_RWG, i32, i32, ptr)
27
-qemu_irq *tc6393xb_gpio_in_get(TC6393xbState *s);
26
+DEF_HELPER_FLAGS_1(recpe_u32, TCG_CALL_NO_RWG, i32, i32)
28
qemu_irq tc6393xb_l3v_get(TC6393xbState *s);
27
+DEF_HELPER_FLAGS_1(rsqrte_u32, TCG_CALL_NO_RWG, i32, i32)
29
28
DEF_HELPER_FLAGS_4(neon_tbl, TCG_CALL_NO_RWG, i32, i32, i32, ptr, i32)
30
#endif
29
31
diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
30
DEF_HELPER_3(shl_cc, i32, env, i32, i32)
31
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
32
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
33
--- a/hw/display/tc6393xb.c
33
--- a/target/arm/translate-a64.c
34
+++ b/hw/display/tc6393xb.c
34
+++ b/target/arm/translate-a64.c
35
@@ -XXX,XX +XXX,XX @@ struct TC6393xbState {
35
@@ -XXX,XX +XXX,XX @@ static void handle_2misc_reciprocal(DisasContext *s, int opcode,
36
blanked : 1;
36
37
};
37
switch (opcode) {
38
38
case 0x3c: /* URECPE */
39
-qemu_irq *tc6393xb_gpio_in_get(TC6393xbState *s)
39
- gen_helper_recpe_u32(tcg_res, tcg_op, fpst);
40
-{
40
+ gen_helper_recpe_u32(tcg_res, tcg_op);
41
- return s->gpio_in;
41
break;
42
-}
42
case 0x3d: /* FRECPE */
43
-
43
gen_helper_recpe_f32(tcg_res, tcg_op, fpst);
44
static void tc6393xb_gpio_set(void *opaque, int line, int level)
44
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
45
unallocated_encoding(s);
46
return;
47
}
48
- need_fpstatus = true;
49
break;
50
case 0x1e: /* FRINT32Z */
51
case 0x1f: /* FRINT64Z */
52
@@ -XXX,XX +XXX,XX @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
53
gen_helper_rints_exact(tcg_res, tcg_op, tcg_fpstatus);
54
break;
55
case 0x7c: /* URSQRTE */
56
- gen_helper_rsqrte_u32(tcg_res, tcg_op, tcg_fpstatus);
57
+ gen_helper_rsqrte_u32(tcg_res, tcg_op);
58
break;
59
case 0x1e: /* FRINT32Z */
60
case 0x5e: /* FRINT32X */
61
diff --git a/target/arm/translate.c b/target/arm/translate.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/target/arm/translate.c
64
+++ b/target/arm/translate.c
65
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
66
break;
67
}
68
case NEON_2RM_VRECPE:
69
- {
70
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
71
- gen_helper_recpe_u32(tmp, tmp, fpstatus);
72
- tcg_temp_free_ptr(fpstatus);
73
+ gen_helper_recpe_u32(tmp, tmp);
74
break;
75
- }
76
case NEON_2RM_VRSQRTE:
77
- {
78
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
79
- gen_helper_rsqrte_u32(tmp, tmp, fpstatus);
80
- tcg_temp_free_ptr(fpstatus);
81
+ gen_helper_rsqrte_u32(tmp, tmp);
82
break;
83
- }
84
case NEON_2RM_VRECPE_F:
85
{
86
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
87
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/target/arm/vfp_helper.c
90
+++ b/target/arm/vfp_helper.c
91
@@ -XXX,XX +XXX,XX @@ float64 HELPER(rsqrte_f64)(float64 input, void *fpstp)
92
return make_float64(val);
93
}
94
95
-uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp)
96
+uint32_t HELPER(recpe_u32)(uint32_t a)
45
{
97
{
46
// TC6393xbState *s = opaque;
98
- /* float_status *s = fpstp; */
47
@@ -XXX,XX +XXX,XX @@ static void tc6393xb_gpio_set(void *opaque, int line, int level)
99
int input, estimate;
48
// FIXME: how does the chip reflect the GPIO input level change?
100
101
if ((a & 0x80000000) == 0) {
102
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(recpe_u32)(uint32_t a, void *fpstp)
103
return deposit32(0, (32 - 9), 9, estimate);
49
}
104
}
50
105
51
-void tc6393xb_gpio_out_set(TC6393xbState *s, int line,
106
-uint32_t HELPER(rsqrte_u32)(uint32_t a, void *fpstp)
52
- qemu_irq handler)
107
+uint32_t HELPER(rsqrte_u32)(uint32_t a)
53
-{
54
- if (line >= TC6393XB_GPIOS) {
55
- fprintf(stderr, "TC6393xb: no GPIO pin %d\n", line);
56
- return;
57
- }
58
-
59
- s->handler[line] = handler;
60
-}
61
-
62
static void tc6393xb_gpio_handler_update(TC6393xbState *s)
63
{
108
{
64
uint32_t level, diff;
109
int estimate;
110
65
--
111
--
66
2.20.1
112
2.20.1
67
113
68
114
diff view generated by jsdifflib
1
The M-profile FPCCR.ASPEN bit indicates that automatic floating-point
1
From: Richard Henderson <richard.henderson@linaro.org>
2
context preservation is enabled. Before executing any floating-point
3
instruction, if FPCCR.ASPEN is set and the CONTROL FPCA/SFPA bits
4
indicate that there is no active floating point context then we
5
must create a new context (by initializing FPSCR and setting
6
FPCA/SFPA to indicate that the context is now active). In the
7
pseudocode this is handled by ExecuteFPCheck().
8
2
9
Implement this with a new TB flag which tracks whether we
3
Provide a functional interface for the vector expansion.
10
need to create a new FP context.
4
This fits better with the existing set of helpers that
5
we provide for other operations.
11
6
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200513163245.17915-13-richard.henderson@linaro.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20190416125744.27770-20-peter.maydell@linaro.org
15
---
11
---
16
target/arm/cpu.h | 2 ++
12
target/arm/translate.h | 5 ++++
17
target/arm/translate.h | 1 +
13
target/arm/translate-a64.c | 34 ++----------------------
18
target/arm/helper.c | 13 +++++++++++++
14
target/arm/translate.c | 54 +++++++++++++++++++-------------------
19
target/arm/translate.c | 29 +++++++++++++++++++++++++++++
15
3 files changed, 34 insertions(+), 59 deletions(-)
20
4 files changed, 45 insertions(+)
21
16
22
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
23
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/cpu.h
25
+++ b/target/arm/cpu.h
26
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, NS, 6, 1)
27
FIELD(TBFLAG_A32, VFPEN, 7, 1)
28
FIELD(TBFLAG_A32, CONDEXEC, 8, 8)
29
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
30
+/* For M profile only, set if we must create a new FP context */
31
+FIELD(TBFLAG_A32, NEW_FP_CTXT_NEEDED, 19, 1)
32
/* For M profile only, set if FPCCR.S does not match current security state */
33
FIELD(TBFLAG_A32, FPCCR_S_WRONG, 20, 1)
34
/* For M profile only, Handler (ie not Thread) mode */
35
diff --git a/target/arm/translate.h b/target/arm/translate.h
17
diff --git a/target/arm/translate.h b/target/arm/translate.h
36
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/translate.h
19
--- a/target/arm/translate.h
38
+++ b/target/arm/translate.h
20
+++ b/target/arm/translate.h
39
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
21
@@ -XXX,XX +XXX,XX @@ void gen_gvec_sri(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
40
bool v8m_secure; /* true if v8M and we're in Secure mode */
22
void gen_gvec_sli(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
41
bool v8m_stackcheck; /* true if we need to perform v8M stack limit checks */
23
int64_t shift, uint32_t opr_sz, uint32_t max_sz);
42
bool v8m_fpccr_s_wrong; /* true if v8M FPCCR.S != v8m_secure */
24
43
+ bool v7m_new_fp_ctxt_needed; /* ASPEN set but no active FP context */
25
+void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
44
/* Immediate value in AArch32 SVC insn; must be set if is_jmp == DISAS_SWI
26
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
45
* so that top level loop can generate correct syndrome information.
27
+void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
46
*/
28
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
47
diff --git a/target/arm/helper.c b/target/arm/helper.c
29
+
30
/*
31
* Forward to the isar_feature_* tests given a DisasContext pointer.
32
*/
33
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
48
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/helper.c
35
--- a/target/arm/translate-a64.c
50
+++ b/target/arm/helper.c
36
+++ b/target/arm/translate-a64.c
51
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
37
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_op3_ool(DisasContext *s, bool is_q, int rd,
52
flags = FIELD_DP32(flags, TBFLAG_A32, FPCCR_S_WRONG, 1);
38
is_q ? 16 : 8, vec_full_reg_size(s), data, fn);
53
}
54
55
+ if (arm_feature(env, ARM_FEATURE_M) &&
56
+ (env->v7m.fpccr[env->v7m.secure] & R_V7M_FPCCR_ASPEN_MASK) &&
57
+ (!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) ||
58
+ (env->v7m.secure &&
59
+ !(env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)))) {
60
+ /*
61
+ * ASPEN is set, but FPCA/SFPA indicate that there is no active
62
+ * FP context; we must create a new FP context before executing
63
+ * any FP insn.
64
+ */
65
+ flags = FIELD_DP32(flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED, 1);
66
+ }
67
+
68
*pflags = flags;
69
*cs_base = 0;
70
}
39
}
40
41
-/* Expand a 3-operand + env pointer operation using
42
- * an out-of-line helper.
43
- */
44
-static void gen_gvec_op3_env(DisasContext *s, bool is_q, int rd,
45
- int rn, int rm, gen_helper_gvec_3_ptr *fn)
46
-{
47
- tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
48
- vec_full_reg_offset(s, rn),
49
- vec_full_reg_offset(s, rm), cpu_env,
50
- is_q ? 16 : 8, vec_full_reg_size(s), 0, fn);
51
-}
52
-
53
/* Expand a 3-operand + fpstatus pointer + simd data value operation using
54
* an out-of-line helper.
55
*/
56
@@ -XXX,XX +XXX,XX @@ static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
57
58
switch (opcode) {
59
case 0x0: /* SQRDMLAH (vector) */
60
- switch (size) {
61
- case 1:
62
- gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s16);
63
- break;
64
- case 2:
65
- gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s32);
66
- break;
67
- default:
68
- g_assert_not_reached();
69
- }
70
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sqrdmlah_qc, size);
71
return;
72
73
case 0x1: /* SQRDMLSH (vector) */
74
- switch (size) {
75
- case 1:
76
- gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s16);
77
- break;
78
- case 2:
79
- gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s32);
80
- break;
81
- default:
82
- g_assert_not_reached();
83
- }
84
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sqrdmlsh_qc, size);
85
return;
86
87
case 0x2: /* SDOT / UDOT */
71
diff --git a/target/arm/translate.c b/target/arm/translate.c
88
diff --git a/target/arm/translate.c b/target/arm/translate.c
72
index XXXXXXX..XXXXXXX 100644
89
index XXXXXXX..XXXXXXX 100644
73
--- a/target/arm/translate.c
90
--- a/target/arm/translate.c
74
+++ b/target/arm/translate.c
91
+++ b/target/arm/translate.c
75
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
92
@@ -XXX,XX +XXX,XX @@ static const uint8_t neon_2rm_sizes[] = {
76
/* Don't need to do this for any further FP insns in this TB */
93
[NEON_2RM_VCVT_UF] = 0x4,
77
s->v8m_fpccr_s_wrong = false;
94
};
78
}
95
96
-
97
-/* Expand v8.1 simd helper. */
98
-static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
99
- int q, int rd, int rn, int rm)
100
+void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
101
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
102
{
103
- if (dc_isar_feature(aa32_rdm, s)) {
104
- int opr_sz = (1 + q) * 8;
105
- tcg_gen_gvec_3_ptr(vfp_reg_offset(1, rd),
106
- vfp_reg_offset(1, rn),
107
- vfp_reg_offset(1, rm), cpu_env,
108
- opr_sz, opr_sz, 0, fn);
109
- return 0;
110
- }
111
- return 1;
112
+ static gen_helper_gvec_3_ptr * const fns[2] = {
113
+ gen_helper_gvec_qrdmlah_s16, gen_helper_gvec_qrdmlah_s32
114
+ };
115
+ tcg_debug_assert(vece >= 1 && vece <= 2);
116
+ tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, cpu_env,
117
+ opr_sz, max_sz, 0, fns[vece - 1]);
118
+}
79
+
119
+
80
+ if (s->v7m_new_fp_ctxt_needed) {
120
+void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
81
+ /*
121
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
82
+ * Create new FP context by updating CONTROL.FPCA, CONTROL.SFPA
122
+{
83
+ * and the FPSCR.
123
+ static gen_helper_gvec_3_ptr * const fns[2] = {
84
+ */
124
+ gen_helper_gvec_qrdmlsh_s16, gen_helper_gvec_qrdmlsh_s32
85
+ TCGv_i32 control, fpscr;
125
+ };
86
+ uint32_t bits = R_V7M_CONTROL_FPCA_MASK;
126
+ tcg_debug_assert(vece >= 1 && vece <= 2);
87
+
127
+ tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, cpu_env,
88
+ fpscr = load_cpu_field(v7m.fpdscr[s->v8m_secure]);
128
+ opr_sz, max_sz, 0, fns[vece - 1]);
89
+ gen_helper_vfp_set_fpscr(cpu_env, fpscr);
129
}
90
+ tcg_temp_free_i32(fpscr);
130
91
+ /*
131
#define GEN_CMP0(NAME, COND) \
92
+ * We don't need to arrange to end the TB, because the only
132
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
93
+ * parts of FPSCR which we cache in the TB flags are the VECLEN
133
break; /* VPADD */
94
+ * and VECSTRIDE, and those don't exist for M-profile.
134
}
95
+ */
135
/* VQRDMLAH */
96
+
136
- switch (size) {
97
+ if (s->v8m_secure) {
137
- case 1:
98
+ bits |= R_V7M_CONTROL_SFPA_MASK;
138
- return do_v81_helper(s, gen_helper_gvec_qrdmlah_s16,
99
+ }
139
- q, rd, rn, rm);
100
+ control = load_cpu_field(v7m.control[M_REG_S]);
140
- case 2:
101
+ tcg_gen_ori_i32(control, control, bits);
141
- return do_v81_helper(s, gen_helper_gvec_qrdmlah_s32,
102
+ store_cpu_field(control, v7m.control[M_REG_S]);
142
- q, rd, rn, rm);
103
+ /* Don't need to do this for any further FP insns in this TB */
143
+ if (dc_isar_feature(aa32_rdm, s) && (size == 1 || size == 2)) {
104
+ s->v7m_new_fp_ctxt_needed = false;
144
+ gen_gvec_sqrdmlah_qc(size, rd_ofs, rn_ofs, rm_ofs,
105
+ }
145
+ vec_size, vec_size);
106
}
146
+ return 0;
107
147
}
108
if (extract32(insn, 28, 4) == 0xf) {
148
return 1;
109
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
149
110
regime_is_secure(env, dc->mmu_idx);
150
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
111
dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_A32, STACKCHECK);
151
break;
112
dc->v8m_fpccr_s_wrong = FIELD_EX32(tb_flags, TBFLAG_A32, FPCCR_S_WRONG);
152
}
113
+ dc->v7m_new_fp_ctxt_needed =
153
/* VQRDMLSH */
114
+ FIELD_EX32(tb_flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED);
154
- switch (size) {
115
dc->cp_regs = cpu->cp_regs;
155
- case 1:
116
dc->features = env->features;
156
- return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s16,
157
- q, rd, rn, rm);
158
- case 2:
159
- return do_v81_helper(s, gen_helper_gvec_qrdmlsh_s32,
160
- q, rd, rn, rm);
161
+ if (dc_isar_feature(aa32_rdm, s) && (size == 1 || size == 2)) {
162
+ gen_gvec_sqrdmlsh_qc(size, rd_ofs, rn_ofs, rm_ofs,
163
+ vec_size, vec_size);
164
+ return 0;
165
}
166
return 1;
117
167
118
--
168
--
119
2.20.1
169
2.20.1
120
170
121
171
diff view generated by jsdifflib
1
Currently the code in v7m_push_stack() which detects a violation
1
From: Richard Henderson <richard.henderson@linaro.org>
2
of the v8M stack limit simply returns early if it does so. This
2
3
is OK for the current integer-only code, but won't work for the
3
Pass a pointer directly to env->vfp.qc[0], rather than env.
4
floating point handling we're about to add. We need to continue
4
This will allow SVE2, which does not modify QC, to pass a
5
executing the rest of the function so that we check for other
5
pointer to dummy storage.
6
exceptions like not having permission to use the FPU and so
6
7
that we correctly set the FPCCR state if we are doing lazy
7
Change the return type of inl_qrdml.h_s16 to match the
8
stacking. Refactor to avoid the early return.
8
sense of the operation: signed.
9
9
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20200513163245.17915-14-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20190416125744.27770-10-peter.maydell@linaro.org
13
---
14
---
14
target/arm/helper.c | 23 ++++++++++++++++++-----
15
target/arm/translate.c | 18 ++++++++---
15
1 file changed, 18 insertions(+), 5 deletions(-)
16
target/arm/vec_helper.c | 70 +++++++++++++++++++++++------------------
16
17
2 files changed, 54 insertions(+), 34 deletions(-)
17
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
19
diff --git a/target/arm/translate.c b/target/arm/translate.c
18
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.c
21
--- a/target/arm/translate.c
20
+++ b/target/arm/helper.c
22
+++ b/target/arm/translate.c
21
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
23
@@ -XXX,XX +XXX,XX @@ static const uint8_t neon_2rm_sizes[] = {
22
* should ignore further stack faults trying to process
24
[NEON_2RM_VCVT_UF] = 0x4,
23
* that derived exception.)
25
};
24
*/
26
25
- bool stacked_ok;
27
+static void gen_gvec_fn3_qc(uint32_t rd_ofs, uint32_t rn_ofs, uint32_t rm_ofs,
26
+ bool stacked_ok = true, limitviol = false;
28
+ uint32_t opr_sz, uint32_t max_sz,
27
CPUARMState *env = &cpu->env;
29
+ gen_helper_gvec_3_ptr *fn)
28
uint32_t xpsr = xpsr_read(env);
30
+{
29
uint32_t frameptr = env->regs[13];
31
+ TCGv_ptr qc_ptr = tcg_temp_new_ptr();
30
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
32
+
31
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
33
+ tcg_gen_addi_ptr(qc_ptr, cpu_env, offsetof(CPUARMState, vfp.qc));
32
env->v7m.secure);
34
+ tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, qc_ptr,
33
env->regs[13] = limit;
35
+ opr_sz, max_sz, 0, fn);
34
- return true;
36
+ tcg_temp_free_ptr(qc_ptr);
35
+ /*
37
+}
36
+ * We won't try to perform any further memory accesses but
38
+
37
+ * we must continue through the following code to check for
39
void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
38
+ * permission faults during FPU state preservation, and we
40
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
39
+ * must update FPCCR if lazy stacking is enabled.
41
{
40
+ */
42
@@ -XXX,XX +XXX,XX @@ void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
41
+ limitviol = true;
43
gen_helper_gvec_qrdmlah_s16, gen_helper_gvec_qrdmlah_s32
42
+ stacked_ok = false;
44
};
43
}
45
tcg_debug_assert(vece >= 1 && vece <= 2);
44
}
46
- tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, cpu_env,
45
47
- opr_sz, max_sz, 0, fns[vece - 1]);
46
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
48
+ gen_gvec_fn3_qc(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, fns[vece - 1]);
47
* (which may be taken in preference to the one we started with
49
}
48
* if it has higher priority).
50
49
*/
51
void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
50
- stacked_ok =
52
@@ -XXX,XX +XXX,XX @@ void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
51
+ stacked_ok = stacked_ok &&
53
gen_helper_gvec_qrdmlsh_s16, gen_helper_gvec_qrdmlsh_s32
52
v7m_stack_write(cpu, frameptr, env->regs[0], mmu_idx, false) &&
54
};
53
v7m_stack_write(cpu, frameptr + 4, env->regs[1], mmu_idx, false) &&
55
tcg_debug_assert(vece >= 1 && vece <= 2);
54
v7m_stack_write(cpu, frameptr + 8, env->regs[2], mmu_idx, false) &&
56
- tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, cpu_env,
55
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
57
- opr_sz, max_sz, 0, fns[vece - 1]);
56
v7m_stack_write(cpu, frameptr + 24, env->regs[15], mmu_idx, false) &&
58
+ gen_gvec_fn3_qc(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, fns[vece - 1]);
57
v7m_stack_write(cpu, frameptr + 28, xpsr, mmu_idx, false);
59
}
58
60
59
- /* Update SP regardless of whether any of the stack accesses failed. */
61
#define GEN_CMP0(NAME, COND) \
60
- env->regs[13] = frameptr;
62
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
61
+ /*
63
index XXXXXXX..XXXXXXX 100644
62
+ * If we broke a stack limit then SP was already updated earlier;
64
--- a/target/arm/vec_helper.c
63
+ * otherwise we update SP regardless of whether any of the stack
65
+++ b/target/arm/vec_helper.c
64
+ * accesses failed or we took some other kind of fault.
66
@@ -XXX,XX +XXX,XX @@
65
+ */
67
#define H4(x) (x)
66
+ if (!limitviol) {
68
#endif
67
+ env->regs[13] = frameptr;
69
68
+ }
70
-#define SET_QC() env->vfp.qc[0] = 1
69
71
-
70
return !stacked_ok;
72
static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
73
{
74
uint64_t *d = vd + opr_sz;
75
@@ -XXX,XX +XXX,XX @@ static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
76
}
77
78
/* Signed saturating rounding doubling multiply-accumulate high half, 16-bit */
79
-static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1,
80
- int16_t src2, int16_t src3)
81
+static int16_t inl_qrdmlah_s16(int16_t src1, int16_t src2,
82
+ int16_t src3, uint32_t *sat)
83
{
84
/* Simplify:
85
* = ((a3 << 16) + ((e1 * e2) << 1) + (1 << 15)) >> 16
86
@@ -XXX,XX +XXX,XX @@ static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1,
87
ret = ((int32_t)src3 << 15) + ret + (1 << 14);
88
ret >>= 15;
89
if (ret != (int16_t)ret) {
90
- SET_QC();
91
+ *sat = 1;
92
ret = (ret < 0 ? -0x8000 : 0x7fff);
93
}
94
return ret;
95
@@ -XXX,XX +XXX,XX @@ static uint16_t inl_qrdmlah_s16(CPUARMState *env, int16_t src1,
96
uint32_t HELPER(neon_qrdmlah_s16)(CPUARMState *env, uint32_t src1,
97
uint32_t src2, uint32_t src3)
98
{
99
- uint16_t e1 = inl_qrdmlah_s16(env, src1, src2, src3);
100
- uint16_t e2 = inl_qrdmlah_s16(env, src1 >> 16, src2 >> 16, src3 >> 16);
101
+ uint32_t *sat = &env->vfp.qc[0];
102
+ uint16_t e1 = inl_qrdmlah_s16(src1, src2, src3, sat);
103
+ uint16_t e2 = inl_qrdmlah_s16(src1 >> 16, src2 >> 16, src3 >> 16, sat);
104
return deposit32(e1, 16, 16, e2);
105
}
106
107
void HELPER(gvec_qrdmlah_s16)(void *vd, void *vn, void *vm,
108
- void *ve, uint32_t desc)
109
+ void *vq, uint32_t desc)
110
{
111
uintptr_t opr_sz = simd_oprsz(desc);
112
int16_t *d = vd;
113
int16_t *n = vn;
114
int16_t *m = vm;
115
- CPUARMState *env = ve;
116
uintptr_t i;
117
118
for (i = 0; i < opr_sz / 2; ++i) {
119
- d[i] = inl_qrdmlah_s16(env, n[i], m[i], d[i]);
120
+ d[i] = inl_qrdmlah_s16(n[i], m[i], d[i], vq);
121
}
122
clear_tail(d, opr_sz, simd_maxsz(desc));
123
}
124
125
/* Signed saturating rounding doubling multiply-subtract high half, 16-bit */
126
-static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1,
127
- int16_t src2, int16_t src3)
128
+static int16_t inl_qrdmlsh_s16(int16_t src1, int16_t src2,
129
+ int16_t src3, uint32_t *sat)
130
{
131
/* Similarly, using subtraction:
132
* = ((a3 << 16) - ((e1 * e2) << 1) + (1 << 15)) >> 16
133
@@ -XXX,XX +XXX,XX @@ static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1,
134
ret = ((int32_t)src3 << 15) - ret + (1 << 14);
135
ret >>= 15;
136
if (ret != (int16_t)ret) {
137
- SET_QC();
138
+ *sat = 1;
139
ret = (ret < 0 ? -0x8000 : 0x7fff);
140
}
141
return ret;
142
@@ -XXX,XX +XXX,XX @@ static uint16_t inl_qrdmlsh_s16(CPUARMState *env, int16_t src1,
143
uint32_t HELPER(neon_qrdmlsh_s16)(CPUARMState *env, uint32_t src1,
144
uint32_t src2, uint32_t src3)
145
{
146
- uint16_t e1 = inl_qrdmlsh_s16(env, src1, src2, src3);
147
- uint16_t e2 = inl_qrdmlsh_s16(env, src1 >> 16, src2 >> 16, src3 >> 16);
148
+ uint32_t *sat = &env->vfp.qc[0];
149
+ uint16_t e1 = inl_qrdmlsh_s16(src1, src2, src3, sat);
150
+ uint16_t e2 = inl_qrdmlsh_s16(src1 >> 16, src2 >> 16, src3 >> 16, sat);
151
return deposit32(e1, 16, 16, e2);
152
}
153
154
void HELPER(gvec_qrdmlsh_s16)(void *vd, void *vn, void *vm,
155
- void *ve, uint32_t desc)
156
+ void *vq, uint32_t desc)
157
{
158
uintptr_t opr_sz = simd_oprsz(desc);
159
int16_t *d = vd;
160
int16_t *n = vn;
161
int16_t *m = vm;
162
- CPUARMState *env = ve;
163
uintptr_t i;
164
165
for (i = 0; i < opr_sz / 2; ++i) {
166
- d[i] = inl_qrdmlsh_s16(env, n[i], m[i], d[i]);
167
+ d[i] = inl_qrdmlsh_s16(n[i], m[i], d[i], vq);
168
}
169
clear_tail(d, opr_sz, simd_maxsz(desc));
170
}
171
172
/* Signed saturating rounding doubling multiply-accumulate high half, 32-bit */
173
-uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
174
- int32_t src2, int32_t src3)
175
+static int32_t inl_qrdmlah_s32(int32_t src1, int32_t src2,
176
+ int32_t src3, uint32_t *sat)
177
{
178
/* Simplify similarly to int_qrdmlah_s16 above. */
179
int64_t ret = (int64_t)src1 * src2;
180
ret = ((int64_t)src3 << 31) + ret + (1 << 30);
181
ret >>= 31;
182
if (ret != (int32_t)ret) {
183
- SET_QC();
184
+ *sat = 1;
185
ret = (ret < 0 ? INT32_MIN : INT32_MAX);
186
}
187
return ret;
188
}
189
190
+uint32_t HELPER(neon_qrdmlah_s32)(CPUARMState *env, int32_t src1,
191
+ int32_t src2, int32_t src3)
192
+{
193
+ uint32_t *sat = &env->vfp.qc[0];
194
+ return inl_qrdmlah_s32(src1, src2, src3, sat);
195
+}
196
+
197
void HELPER(gvec_qrdmlah_s32)(void *vd, void *vn, void *vm,
198
- void *ve, uint32_t desc)
199
+ void *vq, uint32_t desc)
200
{
201
uintptr_t opr_sz = simd_oprsz(desc);
202
int32_t *d = vd;
203
int32_t *n = vn;
204
int32_t *m = vm;
205
- CPUARMState *env = ve;
206
uintptr_t i;
207
208
for (i = 0; i < opr_sz / 4; ++i) {
209
- d[i] = helper_neon_qrdmlah_s32(env, n[i], m[i], d[i]);
210
+ d[i] = inl_qrdmlah_s32(n[i], m[i], d[i], vq);
211
}
212
clear_tail(d, opr_sz, simd_maxsz(desc));
213
}
214
215
/* Signed saturating rounding doubling multiply-subtract high half, 32-bit */
216
-uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
217
- int32_t src2, int32_t src3)
218
+static int32_t inl_qrdmlsh_s32(int32_t src1, int32_t src2,
219
+ int32_t src3, uint32_t *sat)
220
{
221
/* Simplify similarly to int_qrdmlsh_s16 above. */
222
int64_t ret = (int64_t)src1 * src2;
223
ret = ((int64_t)src3 << 31) - ret + (1 << 30);
224
ret >>= 31;
225
if (ret != (int32_t)ret) {
226
- SET_QC();
227
+ *sat = 1;
228
ret = (ret < 0 ? INT32_MIN : INT32_MAX);
229
}
230
return ret;
231
}
232
233
+uint32_t HELPER(neon_qrdmlsh_s32)(CPUARMState *env, int32_t src1,
234
+ int32_t src2, int32_t src3)
235
+{
236
+ uint32_t *sat = &env->vfp.qc[0];
237
+ return inl_qrdmlsh_s32(src1, src2, src3, sat);
238
+}
239
+
240
void HELPER(gvec_qrdmlsh_s32)(void *vd, void *vn, void *vm,
241
- void *ve, uint32_t desc)
242
+ void *vq, uint32_t desc)
243
{
244
uintptr_t opr_sz = simd_oprsz(desc);
245
int32_t *d = vd;
246
int32_t *n = vn;
247
int32_t *m = vm;
248
- CPUARMState *env = ve;
249
uintptr_t i;
250
251
for (i = 0; i < opr_sz / 4; ++i) {
252
- d[i] = helper_neon_qrdmlsh_s32(env, n[i], m[i], d[i]);
253
+ d[i] = inl_qrdmlsh_s32(n[i], m[i], d[i], vq);
254
}
255
clear_tail(d, opr_sz, simd_maxsz(desc));
71
}
256
}
72
--
257
--
73
2.20.1
258
2.20.1
74
259
75
260
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Richard Henderson <richard.henderson@linaro.org>
2
2
3
Suggested-by: Markus Armbruster <armbru@redhat.com>
3
Must clear the tail for AdvSIMD when SVE is enabled.
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
4
5
Message-id: 20190412165416.7977-3-philmd@redhat.com
5
Fixes: ca40a6e6e39
6
Cc: qemu-stable@nongnu.org
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200513163245.17915-15-richard.henderson@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
11
---
9
hw/arm/nseries.c | 3 ++-
12
target/arm/vec_helper.c | 2 ++
10
1 file changed, 2 insertions(+), 1 deletion(-)
13
1 file changed, 2 insertions(+)
11
14
12
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
15
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
13
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/nseries.c
17
--- a/target/arm/vec_helper.c
15
+++ b/hw/arm/nseries.c
18
+++ b/target/arm/vec_helper.c
16
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \
17
#include "hw/boards.h"
20
d[i + j] = TYPE##_mul(n[i + j], mm, stat); \
18
#include "hw/i2c/i2c.h"
21
} \
19
#include "hw/devices.h"
22
} \
20
+#include "hw/misc/tmp105.h"
23
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
21
#include "hw/block/flash.h"
22
#include "hw/hw.h"
23
#include "hw/bt.h"
24
@@ -XXX,XX +XXX,XX @@ static void n8x0_i2c_setup(struct n800_s *s)
25
qemu_register_powerdown_notifier(&n8x0_system_powerdown_notifier);
26
27
/* Attach a TMP105 PM chip (A0 wired to ground) */
28
- dev = i2c_create_slave(i2c, "tmp105", N8X0_TMP105_ADDR);
29
+ dev = i2c_create_slave(i2c, TYPE_TMP105, N8X0_TMP105_ADDR);
30
qdev_connect_gpio_out(dev, 0, tmp_irq);
31
}
24
}
32
25
26
DO_MUL_IDX(gvec_fmul_idx_h, float16, H2)
27
@@ -XXX,XX +XXX,XX @@ void HELPER(NAME)(void *vd, void *vn, void *vm, void *va, \
28
mm, a[i + j], 0, stat); \
29
} \
30
} \
31
+ clear_tail(d, oprsz, simd_maxsz(desc)); \
32
}
33
34
DO_FMLA_IDX(gvec_fmla_idx_h, float16, H2)
33
--
35
--
34
2.20.1
36
2.20.1
35
37
36
38
diff view generated by jsdifflib
1
The M-profile FPCCR.S bit indicates the security status of
1
From: Richard Henderson <richard.henderson@linaro.org>
2
the floating point context. In the pseudocode ExecuteFPCheck()
2
3
function it is unconditionally set to match the current
3
Include 64-bit element size in preparation for SVE2.
4
security state whenever a floating point instruction is
4
5
executed.
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Implement this by adding a new TB flag which tracks whether
7
Message-id: 20200513163245.17915-16-richard.henderson@linaro.org
8
FPCCR.S is different from the current security state, so
9
that we only need to emit the code to update it in the
10
less-common case when it is not already set correctly.
11
12
Note that we will add the handling for the other work done
13
by ExecuteFPCheck() in later commits.
14
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20190416125744.27770-19-peter.maydell@linaro.org
18
---
9
---
19
target/arm/cpu.h | 2 ++
10
target/arm/helper.h | 10 +++
20
target/arm/translate.h | 1 +
11
target/arm/translate.h | 5 ++
21
target/arm/helper.c | 5 +++++
12
target/arm/translate-a64.c | 8 ++-
22
target/arm/translate.c | 20 ++++++++++++++++++++
13
target/arm/translate.c | 133 ++++++++++++++++++++++++++++++++++++-
23
4 files changed, 28 insertions(+)
14
target/arm/vec_helper.c | 24 +++++++
24
15
5 files changed, 176 insertions(+), 4 deletions(-)
25
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
26
index XXXXXXX..XXXXXXX 100644
17
diff --git a/target/arm/helper.h b/target/arm/helper.h
27
--- a/target/arm/cpu.h
18
index XXXXXXX..XXXXXXX 100644
28
+++ b/target/arm/cpu.h
19
--- a/target/arm/helper.h
29
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, NS, 6, 1)
20
+++ b/target/arm/helper.h
30
FIELD(TBFLAG_A32, VFPEN, 7, 1)
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(gvec_sli_h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
31
FIELD(TBFLAG_A32, CONDEXEC, 8, 8)
22
DEF_HELPER_FLAGS_3(gvec_sli_s, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
32
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
23
DEF_HELPER_FLAGS_3(gvec_sli_d, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
33
+/* For M profile only, set if FPCCR.S does not match current security state */
24
34
+FIELD(TBFLAG_A32, FPCCR_S_WRONG, 20, 1)
25
+DEF_HELPER_FLAGS_4(gvec_sabd_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
35
/* For M profile only, Handler (ie not Thread) mode */
26
+DEF_HELPER_FLAGS_4(gvec_sabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
36
FIELD(TBFLAG_A32, HANDLER, 21, 1)
27
+DEF_HELPER_FLAGS_4(gvec_sabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
37
/* For M profile only, whether we should generate stack-limit checks */
28
+DEF_HELPER_FLAGS_4(gvec_sabd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
29
+
30
+DEF_HELPER_FLAGS_4(gvec_uabd_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
31
+DEF_HELPER_FLAGS_4(gvec_uabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
32
+DEF_HELPER_FLAGS_4(gvec_uabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
33
+DEF_HELPER_FLAGS_4(gvec_uabd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
34
+
35
#ifdef TARGET_AARCH64
36
#include "helper-a64.h"
37
#include "helper-sve.h"
38
diff --git a/target/arm/translate.h b/target/arm/translate.h
38
diff --git a/target/arm/translate.h b/target/arm/translate.h
39
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/translate.h
40
--- a/target/arm/translate.h
41
+++ b/target/arm/translate.h
41
+++ b/target/arm/translate.h
42
@@ -XXX,XX +XXX,XX @@ typedef struct DisasContext {
42
@@ -XXX,XX +XXX,XX @@ void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
43
bool v7m_handler_mode;
43
void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
44
bool v8m_secure; /* true if v8M and we're in Secure mode */
44
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
45
bool v8m_stackcheck; /* true if we need to perform v8M stack limit checks */
45
46
+ bool v8m_fpccr_s_wrong; /* true if v8M FPCCR.S != v8m_secure */
46
+void gen_gvec_sabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
47
/* Immediate value in AArch32 SVC insn; must be set if is_jmp == DISAS_SWI
47
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
48
* so that top level loop can generate correct syndrome information.
48
+void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
49
*/
49
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
50
diff --git a/target/arm/helper.c b/target/arm/helper.c
50
+
51
index XXXXXXX..XXXXXXX 100644
51
/*
52
--- a/target/arm/helper.c
52
* Forward to the isar_feature_* tests given a DisasContext pointer.
53
+++ b/target/arm/helper.c
53
*/
54
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
54
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
55
flags = FIELD_DP32(flags, TBFLAG_A32, STACKCHECK, 1);
55
index XXXXXXX..XXXXXXX 100644
56
}
56
--- a/target/arm/translate-a64.c
57
57
+++ b/target/arm/translate-a64.c
58
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
58
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
59
+ FIELD_EX32(env->v7m.fpccr[M_REG_S], V7M_FPCCR, S) != env->v7m.secure) {
59
gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_smin, size);
60
+ flags = FIELD_DP32(flags, TBFLAG_A32, FPCCR_S_WRONG, 1);
60
}
61
+ }
61
return;
62
+
62
+ case 0xe: /* SABD, UABD */
63
*pflags = flags;
63
+ if (u) {
64
*cs_base = 0;
64
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_uabd, size);
65
}
65
+ } else {
66
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sabd, size);
67
+ }
68
+ return;
69
case 0x10: /* ADD, SUB */
70
if (u) {
71
gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_sub, size);
72
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
73
genenvfn = fns[size][u];
74
break;
75
}
76
- case 0xe: /* SABD, UABD */
77
case 0xf: /* SABA, UABA */
78
{
79
static NeonGenTwoOpFn * const fns[3][2] = {
66
diff --git a/target/arm/translate.c b/target/arm/translate.c
80
diff --git a/target/arm/translate.c b/target/arm/translate.c
67
index XXXXXXX..XXXXXXX 100644
81
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/translate.c
82
--- a/target/arm/translate.c
69
+++ b/target/arm/translate.c
83
+++ b/target/arm/translate.c
70
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
84
@@ -XXX,XX +XXX,XX @@ void gen_gvec_sqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
71
}
85
rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
72
}
86
}
73
87
74
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
88
+static void gen_sabd_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
75
+ /* Handle M-profile lazy FP state mechanics */
89
+{
76
+
90
+ TCGv_i32 t = tcg_temp_new_i32();
77
+ /* Update ownership of FP context: set FPCCR.S to match current state */
91
+
78
+ if (s->v8m_fpccr_s_wrong) {
92
+ tcg_gen_sub_i32(t, a, b);
79
+ TCGv_i32 tmp;
93
+ tcg_gen_sub_i32(d, b, a);
80
+
94
+ tcg_gen_movcond_i32(TCG_COND_LT, d, a, b, d, t);
81
+ tmp = load_cpu_field(v7m.fpccr[M_REG_S]);
95
+ tcg_temp_free_i32(t);
82
+ if (s->v8m_secure) {
96
+}
83
+ tcg_gen_ori_i32(tmp, tmp, R_V7M_FPCCR_S_MASK);
97
+
98
+static void gen_sabd_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
99
+{
100
+ TCGv_i64 t = tcg_temp_new_i64();
101
+
102
+ tcg_gen_sub_i64(t, a, b);
103
+ tcg_gen_sub_i64(d, b, a);
104
+ tcg_gen_movcond_i64(TCG_COND_LT, d, a, b, d, t);
105
+ tcg_temp_free_i64(t);
106
+}
107
+
108
+static void gen_sabd_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
109
+{
110
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
111
+
112
+ tcg_gen_smin_vec(vece, t, a, b);
113
+ tcg_gen_smax_vec(vece, d, a, b);
114
+ tcg_gen_sub_vec(vece, d, d, t);
115
+ tcg_temp_free_vec(t);
116
+}
117
+
118
+void gen_gvec_sabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
119
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
120
+{
121
+ static const TCGOpcode vecop_list[] = {
122
+ INDEX_op_sub_vec, INDEX_op_smin_vec, INDEX_op_smax_vec, 0
123
+ };
124
+ static const GVecGen3 ops[4] = {
125
+ { .fniv = gen_sabd_vec,
126
+ .fno = gen_helper_gvec_sabd_b,
127
+ .opt_opc = vecop_list,
128
+ .vece = MO_8 },
129
+ { .fniv = gen_sabd_vec,
130
+ .fno = gen_helper_gvec_sabd_h,
131
+ .opt_opc = vecop_list,
132
+ .vece = MO_16 },
133
+ { .fni4 = gen_sabd_i32,
134
+ .fniv = gen_sabd_vec,
135
+ .fno = gen_helper_gvec_sabd_s,
136
+ .opt_opc = vecop_list,
137
+ .vece = MO_32 },
138
+ { .fni8 = gen_sabd_i64,
139
+ .fniv = gen_sabd_vec,
140
+ .fno = gen_helper_gvec_sabd_d,
141
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
142
+ .opt_opc = vecop_list,
143
+ .vece = MO_64 },
144
+ };
145
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
146
+}
147
+
148
+static void gen_uabd_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
149
+{
150
+ TCGv_i32 t = tcg_temp_new_i32();
151
+
152
+ tcg_gen_sub_i32(t, a, b);
153
+ tcg_gen_sub_i32(d, b, a);
154
+ tcg_gen_movcond_i32(TCG_COND_LTU, d, a, b, d, t);
155
+ tcg_temp_free_i32(t);
156
+}
157
+
158
+static void gen_uabd_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
159
+{
160
+ TCGv_i64 t = tcg_temp_new_i64();
161
+
162
+ tcg_gen_sub_i64(t, a, b);
163
+ tcg_gen_sub_i64(d, b, a);
164
+ tcg_gen_movcond_i64(TCG_COND_LTU, d, a, b, d, t);
165
+ tcg_temp_free_i64(t);
166
+}
167
+
168
+static void gen_uabd_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
169
+{
170
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
171
+
172
+ tcg_gen_umin_vec(vece, t, a, b);
173
+ tcg_gen_umax_vec(vece, d, a, b);
174
+ tcg_gen_sub_vec(vece, d, d, t);
175
+ tcg_temp_free_vec(t);
176
+}
177
+
178
+void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
179
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
180
+{
181
+ static const TCGOpcode vecop_list[] = {
182
+ INDEX_op_sub_vec, INDEX_op_umin_vec, INDEX_op_umax_vec, 0
183
+ };
184
+ static const GVecGen3 ops[4] = {
185
+ { .fniv = gen_uabd_vec,
186
+ .fno = gen_helper_gvec_uabd_b,
187
+ .opt_opc = vecop_list,
188
+ .vece = MO_8 },
189
+ { .fniv = gen_uabd_vec,
190
+ .fno = gen_helper_gvec_uabd_h,
191
+ .opt_opc = vecop_list,
192
+ .vece = MO_16 },
193
+ { .fni4 = gen_uabd_i32,
194
+ .fniv = gen_uabd_vec,
195
+ .fno = gen_helper_gvec_uabd_s,
196
+ .opt_opc = vecop_list,
197
+ .vece = MO_32 },
198
+ { .fni8 = gen_uabd_i64,
199
+ .fniv = gen_uabd_vec,
200
+ .fno = gen_helper_gvec_uabd_d,
201
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
202
+ .opt_opc = vecop_list,
203
+ .vece = MO_64 },
204
+ };
205
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
206
+}
207
+
208
/* Translate a NEON data processing instruction. Return nonzero if the
209
instruction is invalid.
210
We process data in a mixture of 32-bit and 64-bit chunks.
211
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
212
}
213
return 1;
214
215
+ case NEON_3R_VABD:
216
+ if (u) {
217
+ gen_gvec_uabd(size, rd_ofs, rn_ofs, rm_ofs,
218
+ vec_size, vec_size);
84
+ } else {
219
+ } else {
85
+ tcg_gen_andi_i32(tmp, tmp, ~R_V7M_FPCCR_S_MASK);
220
+ gen_gvec_sabd(size, rd_ofs, rn_ofs, rm_ofs,
221
+ vec_size, vec_size);
86
+ }
222
+ }
87
+ store_cpu_field(tmp, v7m.fpccr[M_REG_S]);
223
+ return 0;
88
+ /* Don't need to do this for any further FP insns in this TB */
224
+
89
+ s->v8m_fpccr_s_wrong = false;
225
case NEON_3R_VADD_VSUB:
90
+ }
226
case NEON_3R_LOGIC:
91
+ }
227
case NEON_3R_VMAX:
92
+
228
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
93
if (extract32(insn, 28, 4) == 0xf) {
229
case NEON_3R_VQRSHL:
94
/*
230
GEN_NEON_INTEGER_OP_ENV(qrshl);
95
* Encodings with T=1 (Thumb) or unconditional (ARM):
231
break;
96
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
232
- case NEON_3R_VABD:
97
dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
233
- GEN_NEON_INTEGER_OP(abd);
98
regime_is_secure(env, dc->mmu_idx);
234
- break;
99
dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_A32, STACKCHECK);
235
case NEON_3R_VABA:
100
+ dc->v8m_fpccr_s_wrong = FIELD_EX32(tb_flags, TBFLAG_A32, FPCCR_S_WRONG);
236
GEN_NEON_INTEGER_OP(abd);
101
dc->cp_regs = cpu->cp_regs;
237
tcg_temp_free_i32(tmp2);
102
dc->features = env->features;
238
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
103
239
index XXXXXXX..XXXXXXX 100644
240
--- a/target/arm/vec_helper.c
241
+++ b/target/arm/vec_helper.c
242
@@ -XXX,XX +XXX,XX @@ DO_CMP0(gvec_cgt0_h, int16_t, >)
243
DO_CMP0(gvec_cge0_h, int16_t, >=)
244
245
#undef DO_CMP0
246
+
247
+#define DO_ABD(NAME, TYPE) \
248
+void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \
249
+{ \
250
+ intptr_t i, opr_sz = simd_oprsz(desc); \
251
+ TYPE *d = vd, *n = vn, *m = vm; \
252
+ \
253
+ for (i = 0; i < opr_sz / sizeof(TYPE); ++i) { \
254
+ d[i] = n[i] < m[i] ? m[i] - n[i] : n[i] - m[i]; \
255
+ } \
256
+ clear_tail(d, opr_sz, simd_maxsz(desc)); \
257
+}
258
+
259
+DO_ABD(gvec_sabd_b, int8_t)
260
+DO_ABD(gvec_sabd_h, int16_t)
261
+DO_ABD(gvec_sabd_s, int32_t)
262
+DO_ABD(gvec_sabd_d, int64_t)
263
+
264
+DO_ABD(gvec_uabd_b, uint8_t)
265
+DO_ABD(gvec_uabd_h, uint16_t)
266
+DO_ABD(gvec_uabd_s, uint32_t)
267
+DO_ABD(gvec_uabd_d, uint64_t)
268
+
269
+#undef DO_ABD
104
--
270
--
105
2.20.1
271
2.20.1
106
272
107
273
diff view generated by jsdifflib
1
In the stripe8() function we use a variable length array; however
1
From: Richard Henderson <richard.henderson@linaro.org>
2
we know that the maximum length required is MAX_NUM_BUSSES. Use
2
3
a fixed-length array and an assert instead.
3
Include 64-bit element size in preparation for SVE2.
4
4
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200513163245.17915-17-richard.henderson@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
8
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
10
Message-id: 20190328152635.2794-1-peter.maydell@linaro.org
11
---
9
---
12
hw/ssi/xilinx_spips.c | 6 ++++--
10
target/arm/helper.h | 17 +++--
13
1 file changed, 4 insertions(+), 2 deletions(-)
11
target/arm/translate.h | 5 ++
14
12
target/arm/neon_helper.c | 10 ---
15
diff --git a/hw/ssi/xilinx_spips.c b/hw/ssi/xilinx_spips.c
13
target/arm/translate-a64.c | 17 ++---
16
index XXXXXXX..XXXXXXX 100644
14
target/arm/translate.c | 134 +++++++++++++++++++++++++++++++++++--
17
--- a/hw/ssi/xilinx_spips.c
15
target/arm/vec_helper.c | 24 +++++++
18
+++ b/hw/ssi/xilinx_spips.c
16
6 files changed, 174 insertions(+), 33 deletions(-)
19
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_qspips_reset(DeviceState *d)
17
20
18
diff --git a/target/arm/helper.h b/target/arm/helper.h
21
static inline void stripe8(uint8_t *x, int num, bool dir)
19
index XXXXXXX..XXXXXXX 100644
22
{
20
--- a/target/arm/helper.h
23
- uint8_t r[num];
21
+++ b/target/arm/helper.h
24
- memset(r, 0, sizeof(uint8_t) * num);
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(neon_pmax_s8, i32, i32, i32)
25
+ uint8_t r[MAX_NUM_BUSSES];
23
DEF_HELPER_2(neon_pmax_u16, i32, i32, i32)
26
int idx[2] = {0, 0};
24
DEF_HELPER_2(neon_pmax_s16, i32, i32, i32)
27
int bit[2] = {0, 7};
25
28
int d = dir;
26
-DEF_HELPER_2(neon_abd_u8, i32, i32, i32)
29
27
-DEF_HELPER_2(neon_abd_s8, i32, i32, i32)
30
+ assert(num <= MAX_NUM_BUSSES);
28
-DEF_HELPER_2(neon_abd_u16, i32, i32, i32)
31
+ memset(r, 0, sizeof(uint8_t) * num);
29
-DEF_HELPER_2(neon_abd_s16, i32, i32, i32)
32
+
30
-DEF_HELPER_2(neon_abd_u32, i32, i32, i32)
33
for (idx[0] = 0; idx[0] < num; ++idx[0]) {
31
-DEF_HELPER_2(neon_abd_s32, i32, i32, i32)
34
for (bit[0] = 7; bit[0] >= 0; bit[0]--) {
32
-
35
r[idx[!d]] |= x[idx[d]] & 1 << bit[d] ? 1 << bit[!d] : 0;
33
DEF_HELPER_2(neon_shl_u16, i32, i32, i32)
34
DEF_HELPER_2(neon_shl_s16, i32, i32, i32)
35
DEF_HELPER_2(neon_rshl_u8, i32, i32, i32)
36
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(gvec_uabd_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
37
DEF_HELPER_FLAGS_4(gvec_uabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
38
DEF_HELPER_FLAGS_4(gvec_uabd_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
39
40
+DEF_HELPER_FLAGS_4(gvec_saba_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
41
+DEF_HELPER_FLAGS_4(gvec_saba_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
42
+DEF_HELPER_FLAGS_4(gvec_saba_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
43
+DEF_HELPER_FLAGS_4(gvec_saba_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
44
+
45
+DEF_HELPER_FLAGS_4(gvec_uaba_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
46
+DEF_HELPER_FLAGS_4(gvec_uaba_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
47
+DEF_HELPER_FLAGS_4(gvec_uaba_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
48
+DEF_HELPER_FLAGS_4(gvec_uaba_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
49
+
50
#ifdef TARGET_AARCH64
51
#include "helper-a64.h"
52
#include "helper-sve.h"
53
diff --git a/target/arm/translate.h b/target/arm/translate.h
54
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/translate.h
56
+++ b/target/arm/translate.h
57
@@ -XXX,XX +XXX,XX @@ void gen_gvec_sabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
58
void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
59
uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
60
61
+void gen_gvec_saba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
62
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
63
+void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
64
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
65
+
66
/*
67
* Forward to the isar_feature_* tests given a DisasContext pointer.
68
*/
69
diff --git a/target/arm/neon_helper.c b/target/arm/neon_helper.c
70
index XXXXXXX..XXXXXXX 100644
71
--- a/target/arm/neon_helper.c
72
+++ b/target/arm/neon_helper.c
73
@@ -XXX,XX +XXX,XX @@ NEON_POP(pmax_s16, neon_s16, 2)
74
NEON_POP(pmax_u16, neon_u16, 2)
75
#undef NEON_FN
76
77
-#define NEON_FN(dest, src1, src2) \
78
- dest = (src1 > src2) ? (src1 - src2) : (src2 - src1)
79
-NEON_VOP(abd_s8, neon_s8, 4)
80
-NEON_VOP(abd_u8, neon_u8, 4)
81
-NEON_VOP(abd_s16, neon_s16, 2)
82
-NEON_VOP(abd_u16, neon_u16, 2)
83
-NEON_VOP(abd_s32, neon_s32, 1)
84
-NEON_VOP(abd_u32, neon_u32, 1)
85
-#undef NEON_FN
86
-
87
#define NEON_FN(dest, src1, src2) do { \
88
int8_t tmp; \
89
tmp = (int8_t)src2; \
90
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
91
index XXXXXXX..XXXXXXX 100644
92
--- a/target/arm/translate-a64.c
93
+++ b/target/arm/translate-a64.c
94
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
95
gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_sabd, size);
96
}
97
return;
98
+ case 0xf: /* SABA, UABA */
99
+ if (u) {
100
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_uaba, size);
101
+ } else {
102
+ gen_gvec_fn3(s, is_q, rd, rn, rm, gen_gvec_saba, size);
103
+ }
104
+ return;
105
case 0x10: /* ADD, SUB */
106
if (u) {
107
gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_sub, size);
108
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
109
genenvfn = fns[size][u];
110
break;
111
}
112
- case 0xf: /* SABA, UABA */
113
- {
114
- static NeonGenTwoOpFn * const fns[3][2] = {
115
- { gen_helper_neon_abd_s8, gen_helper_neon_abd_u8 },
116
- { gen_helper_neon_abd_s16, gen_helper_neon_abd_u16 },
117
- { gen_helper_neon_abd_s32, gen_helper_neon_abd_u32 },
118
- };
119
- genfn = fns[size][u];
120
- break;
121
- }
122
case 0x16: /* SQDMULH, SQRDMULH */
123
{
124
static NeonGenTwoOpEnvFn * const fns[2][2] = {
125
diff --git a/target/arm/translate.c b/target/arm/translate.c
126
index XXXXXXX..XXXXXXX 100644
127
--- a/target/arm/translate.c
128
+++ b/target/arm/translate.c
129
@@ -XXX,XX +XXX,XX @@ void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
130
tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
131
}
132
133
+static void gen_saba_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
134
+{
135
+ TCGv_i32 t = tcg_temp_new_i32();
136
+ gen_sabd_i32(t, a, b);
137
+ tcg_gen_add_i32(d, d, t);
138
+ tcg_temp_free_i32(t);
139
+}
140
+
141
+static void gen_saba_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
142
+{
143
+ TCGv_i64 t = tcg_temp_new_i64();
144
+ gen_sabd_i64(t, a, b);
145
+ tcg_gen_add_i64(d, d, t);
146
+ tcg_temp_free_i64(t);
147
+}
148
+
149
+static void gen_saba_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
150
+{
151
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
152
+ gen_sabd_vec(vece, t, a, b);
153
+ tcg_gen_add_vec(vece, d, d, t);
154
+ tcg_temp_free_vec(t);
155
+}
156
+
157
+void gen_gvec_saba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
158
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
159
+{
160
+ static const TCGOpcode vecop_list[] = {
161
+ INDEX_op_sub_vec, INDEX_op_add_vec,
162
+ INDEX_op_smin_vec, INDEX_op_smax_vec, 0
163
+ };
164
+ static const GVecGen3 ops[4] = {
165
+ { .fniv = gen_saba_vec,
166
+ .fno = gen_helper_gvec_saba_b,
167
+ .opt_opc = vecop_list,
168
+ .load_dest = true,
169
+ .vece = MO_8 },
170
+ { .fniv = gen_saba_vec,
171
+ .fno = gen_helper_gvec_saba_h,
172
+ .opt_opc = vecop_list,
173
+ .load_dest = true,
174
+ .vece = MO_16 },
175
+ { .fni4 = gen_saba_i32,
176
+ .fniv = gen_saba_vec,
177
+ .fno = gen_helper_gvec_saba_s,
178
+ .opt_opc = vecop_list,
179
+ .load_dest = true,
180
+ .vece = MO_32 },
181
+ { .fni8 = gen_saba_i64,
182
+ .fniv = gen_saba_vec,
183
+ .fno = gen_helper_gvec_saba_d,
184
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
185
+ .opt_opc = vecop_list,
186
+ .load_dest = true,
187
+ .vece = MO_64 },
188
+ };
189
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
190
+}
191
+
192
+static void gen_uaba_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
193
+{
194
+ TCGv_i32 t = tcg_temp_new_i32();
195
+ gen_uabd_i32(t, a, b);
196
+ tcg_gen_add_i32(d, d, t);
197
+ tcg_temp_free_i32(t);
198
+}
199
+
200
+static void gen_uaba_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
201
+{
202
+ TCGv_i64 t = tcg_temp_new_i64();
203
+ gen_uabd_i64(t, a, b);
204
+ tcg_gen_add_i64(d, d, t);
205
+ tcg_temp_free_i64(t);
206
+}
207
+
208
+static void gen_uaba_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
209
+{
210
+ TCGv_vec t = tcg_temp_new_vec_matching(d);
211
+ gen_uabd_vec(vece, t, a, b);
212
+ tcg_gen_add_vec(vece, d, d, t);
213
+ tcg_temp_free_vec(t);
214
+}
215
+
216
+void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
217
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
218
+{
219
+ static const TCGOpcode vecop_list[] = {
220
+ INDEX_op_sub_vec, INDEX_op_add_vec,
221
+ INDEX_op_umin_vec, INDEX_op_umax_vec, 0
222
+ };
223
+ static const GVecGen3 ops[4] = {
224
+ { .fniv = gen_uaba_vec,
225
+ .fno = gen_helper_gvec_uaba_b,
226
+ .opt_opc = vecop_list,
227
+ .load_dest = true,
228
+ .vece = MO_8 },
229
+ { .fniv = gen_uaba_vec,
230
+ .fno = gen_helper_gvec_uaba_h,
231
+ .opt_opc = vecop_list,
232
+ .load_dest = true,
233
+ .vece = MO_16 },
234
+ { .fni4 = gen_uaba_i32,
235
+ .fniv = gen_uaba_vec,
236
+ .fno = gen_helper_gvec_uaba_s,
237
+ .opt_opc = vecop_list,
238
+ .load_dest = true,
239
+ .vece = MO_32 },
240
+ { .fni8 = gen_uaba_i64,
241
+ .fniv = gen_uaba_vec,
242
+ .fno = gen_helper_gvec_uaba_d,
243
+ .prefer_i64 = TCG_TARGET_REG_BITS == 64,
244
+ .opt_opc = vecop_list,
245
+ .load_dest = true,
246
+ .vece = MO_64 },
247
+ };
248
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
249
+}
250
+
251
/* Translate a NEON data processing instruction. Return nonzero if the
252
instruction is invalid.
253
We process data in a mixture of 32-bit and 64-bit chunks.
254
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
255
}
256
return 0;
257
258
+ case NEON_3R_VABA:
259
+ if (u) {
260
+ gen_gvec_uaba(size, rd_ofs, rn_ofs, rm_ofs,
261
+ vec_size, vec_size);
262
+ } else {
263
+ gen_gvec_saba(size, rd_ofs, rn_ofs, rm_ofs,
264
+ vec_size, vec_size);
265
+ }
266
+ return 0;
267
+
268
case NEON_3R_VADD_VSUB:
269
case NEON_3R_LOGIC:
270
case NEON_3R_VMAX:
271
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
272
case NEON_3R_VQRSHL:
273
GEN_NEON_INTEGER_OP_ENV(qrshl);
274
break;
275
- case NEON_3R_VABA:
276
- GEN_NEON_INTEGER_OP(abd);
277
- tcg_temp_free_i32(tmp2);
278
- tmp2 = neon_load_reg(rd, pass);
279
- gen_neon_add(size, tmp, tmp2);
280
- break;
281
case NEON_3R_VPMAX:
282
GEN_NEON_INTEGER_OP(pmax);
283
break;
284
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
285
index XXXXXXX..XXXXXXX 100644
286
--- a/target/arm/vec_helper.c
287
+++ b/target/arm/vec_helper.c
288
@@ -XXX,XX +XXX,XX @@ DO_ABD(gvec_uabd_s, uint32_t)
289
DO_ABD(gvec_uabd_d, uint64_t)
290
291
#undef DO_ABD
292
+
293
+#define DO_ABA(NAME, TYPE) \
294
+void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \
295
+{ \
296
+ intptr_t i, opr_sz = simd_oprsz(desc); \
297
+ TYPE *d = vd, *n = vn, *m = vm; \
298
+ \
299
+ for (i = 0; i < opr_sz / sizeof(TYPE); ++i) { \
300
+ d[i] += n[i] < m[i] ? m[i] - n[i] : n[i] - m[i]; \
301
+ } \
302
+ clear_tail(d, opr_sz, simd_maxsz(desc)); \
303
+}
304
+
305
+DO_ABA(gvec_saba_b, int8_t)
306
+DO_ABA(gvec_saba_h, int16_t)
307
+DO_ABA(gvec_saba_s, int32_t)
308
+DO_ABA(gvec_saba_d, int64_t)
309
+
310
+DO_ABA(gvec_uaba_b, uint8_t)
311
+DO_ABA(gvec_uaba_h, uint16_t)
312
+DO_ABA(gvec_uaba_s, uint32_t)
313
+DO_ABA(gvec_uaba_d, uint64_t)
314
+
315
+#undef DO_ABA
36
--
316
--
37
2.20.1
317
2.20.1
38
318
39
319
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Patrick Williams <patrick@stwcx.xyz>
2
2
3
Reviewed-by: Thomas Huth <thuth@redhat.com>
3
Sonora Pass is a 2 socket x86 motherboard designed by Facebook
4
and supported by OpenBMC. Strapping configuration was obtained
5
from hardware and i2c configuration is based on dts found at:
6
7
https://github.com/facebook/openbmc-linux/blob/1633c87b8ba7c162095787c988979b748ba65dc8/arch/arm/boot/dts/aspeed-bmc-facebook-sonorapass.dts
8
9
Booted a test image of http://github.com/facebook/openbmc to login
10
prompt.
11
12
Signed-off-by: Patrick Williams <patrick@stwcx.xyz>
13
Reviewed-by: Amithash Prasad <amithash@fb.com>
4
Reviewed-by: Cédric Le Goater <clg@kaod.org>
14
Reviewed-by: Cédric Le Goater <clg@kaod.org>
5
Reviewed-by: Markus Armbruster <armbru@redhat.com>
15
[PMM: fixed block comment style nit]
6
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Message-id: 20190412165416.7977-2-philmd@redhat.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
17
---
10
hw/arm/aspeed.c | 13 +++++++++----
18
hw/arm/aspeed.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++
11
1 file changed, 9 insertions(+), 4 deletions(-)
19
1 file changed, 78 insertions(+)
12
20
13
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
21
diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c
14
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/aspeed.c
23
--- a/hw/arm/aspeed.c
16
+++ b/hw/arm/aspeed.c
24
+++ b/hw/arm/aspeed.c
17
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ struct AspeedBoardState {
18
#include "hw/arm/aspeed_soc.h"
26
SCU_AST2500_HW_STRAP_ACPI_ENABLE | \
19
#include "hw/boards.h"
27
SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER))
20
#include "hw/i2c/smbus_eeprom.h"
28
21
+#include "hw/misc/pca9552.h"
29
+/* Sonorapass hardware value: 0xF100D216 */
22
+#include "hw/misc/tmp105.h"
30
+#define SONORAPASS_BMC_HW_STRAP1 ( \
23
#include "qemu/log.h"
31
+ SCU_AST2500_HW_STRAP_SPI_AUTOFETCH_ENABLE | \
24
#include "sysemu/block-backend.h"
32
+ SCU_AST2500_HW_STRAP_GPIO_STRAP_ENABLE | \
25
#include "hw/loader.h"
33
+ SCU_AST2500_HW_STRAP_UART_DEBUG | \
26
@@ -XXX,XX +XXX,XX @@ static void ast2500_evb_i2c_init(AspeedBoardState *bmc)
34
+ SCU_AST2500_HW_STRAP_RESERVED28 | \
27
eeprom_buf);
35
+ SCU_AST2500_HW_STRAP_DDR4_ENABLE | \
28
36
+ SCU_HW_STRAP_VGA_CLASS_CODE | \
29
/* The AST2500 EVB expects a LM75 but a TMP105 is compatible */
37
+ SCU_HW_STRAP_LPC_RESET_PIN | \
30
- i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 7), "tmp105", 0x4d);
38
+ SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER) | \
31
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 7),
39
+ SCU_AST2500_HW_STRAP_SET_AXI_AHB_RATIO(AXI_AHB_RATIO_2_1) | \
32
+ TYPE_TMP105, 0x4d);
40
+ SCU_HW_STRAP_VGA_BIOS_ROM | \
33
41
+ SCU_HW_STRAP_VGA_SIZE_SET(VGA_16M_DRAM) | \
34
/* The AST2500 EVB does not have an RTC. Let's pretend that one is
42
+ SCU_AST2500_HW_STRAP_RESERVED1)
35
* plugged on the I2C bus header */
43
+
36
@@ -XXX,XX +XXX,XX @@ static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
44
/* Swift hardware value: 0xF11AD206 */
45
#define SWIFT_BMC_HW_STRAP1 ( \
46
AST2500_HW_STRAP1_DEFAULTS | \
47
@@ -XXX,XX +XXX,XX @@ static void swift_bmc_i2c_init(AspeedBoardState *bmc)
48
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 12), "tmp105", 0x4a);
49
}
50
51
+static void sonorapass_bmc_i2c_init(AspeedBoardState *bmc)
52
+{
53
+ AspeedSoCState *soc = &bmc->soc;
54
+
55
+ /* bus 2 : */
56
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 2), "tmp105", 0x48);
57
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 2), "tmp105", 0x49);
58
+ /* bus 2 : pca9546 @ 0x73 */
59
+
60
+ /* bus 3 : pca9548 @ 0x70 */
61
+
62
+ /* bus 4 : */
63
+ uint8_t *eeprom4_54 = g_malloc0(8 * 1024);
64
+ smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), 0x54,
65
+ eeprom4_54);
66
+ /* PCA9539 @ 0x76, but PCA9552 is compatible */
67
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), "pca9552", 0x76);
68
+ /* PCA9539 @ 0x77, but PCA9552 is compatible */
69
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), "pca9552", 0x77);
70
+
71
+ /* bus 6 : */
72
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 6), "tmp105", 0x48);
73
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 6), "tmp105", 0x49);
74
+ /* bus 6 : pca9546 @ 0x73 */
75
+
76
+ /* bus 8 : */
77
+ uint8_t *eeprom8_56 = g_malloc0(8 * 1024);
78
+ smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), 0x56,
79
+ eeprom8_56);
80
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), "pca9552", 0x60);
81
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 8), "pca9552", 0x61);
82
+ /* bus 8 : adc128d818 @ 0x1d */
83
+ /* bus 8 : adc128d818 @ 0x1f */
84
+
85
+ /*
86
+ * bus 13 : pca9548 @ 0x71
87
+ * - channel 3:
88
+ * - tmm421 @ 0x4c
89
+ * - tmp421 @ 0x4e
90
+ * - tmp421 @ 0x4f
91
+ */
92
+
93
+}
94
+
95
static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
96
{
37
AspeedSoCState *soc = &bmc->soc;
97
AspeedSoCState *soc = &bmc->soc;
38
uint8_t *eeprom_buf = g_malloc0(8 * 1024);
98
@@ -XXX,XX +XXX,XX @@ static void aspeed_machine_romulus_class_init(ObjectClass *oc, void *data)
39
99
mc->default_ram_size = 512 * MiB;
40
- i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 3), "pca9552", 0x60);
100
};
41
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 3), TYPE_PCA9552,
101
42
+ 0x60);
102
+static void aspeed_machine_sonorapass_class_init(ObjectClass *oc, void *data)
43
103
+{
44
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 4), "tmp423", 0x4c);
104
+ MachineClass *mc = MACHINE_CLASS(oc);
45
i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 5), "tmp423", 0x4c);
105
+ AspeedMachineClass *amc = ASPEED_MACHINE_CLASS(oc);
46
106
+
47
/* The Witherspoon expects a TMP275 but a TMP105 is compatible */
107
+ mc->desc = "OCP SonoraPass BMC (ARM1176)";
48
- i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 9), "tmp105", 0x4a);
108
+ amc->soc_name = "ast2500-a1";
49
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 9), TYPE_TMP105,
109
+ amc->hw_strap1 = SONORAPASS_BMC_HW_STRAP1;
50
+ 0x4a);
110
+ amc->fmc_model = "mx66l1g45g";
51
111
+ amc->spi_model = "mx66l1g45g";
52
/* The witherspoon board expects Epson RX8900 I2C RTC but a ds1338 is
112
+ amc->num_cs = 2;
53
* good enough */
113
+ amc->i2c_init = sonorapass_bmc_i2c_init;
54
@@ -XXX,XX +XXX,XX @@ static void witherspoon_bmc_i2c_init(AspeedBoardState *bmc)
114
+ mc->default_ram_size = 512 * MiB;
55
115
+};
56
smbus_eeprom_init_one(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), 0x51,
116
+
57
eeprom_buf);
117
static void aspeed_machine_swift_class_init(ObjectClass *oc, void *data)
58
- i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), "pca9552",
118
{
59
+ i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 11), TYPE_PCA9552,
119
MachineClass *mc = MACHINE_CLASS(oc);
60
0x60);
120
@@ -XXX,XX +XXX,XX @@ static const TypeInfo aspeed_machine_types[] = {
61
}
121
.name = MACHINE_TYPE_NAME("swift-bmc"),
62
122
.parent = TYPE_ASPEED_MACHINE,
123
.class_init = aspeed_machine_swift_class_init,
124
+ }, {
125
+ .name = MACHINE_TYPE_NAME("sonorapass-bmc"),
126
+ .parent = TYPE_ASPEED_MACHINE,
127
+ .class_init = aspeed_machine_sonorapass_class_init,
128
}, {
129
.name = MACHINE_TYPE_NAME("witherspoon-bmc"),
130
.parent = TYPE_ASPEED_MACHINE,
63
--
131
--
64
2.20.1
132
2.20.1
65
133
66
134
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
2
2
3
This device is used by both ARM (BCM2836, for raspi2) and AArch64
3
The little end UUID is used in many places, so make
4
(BCM2837, for raspi3) targets, and is not CPU-specific.
4
NVDIMM_UUID_LE to a common macro to convert the UUID
5
Move it to common object, so we build it once for all targets.
5
to a little end array.
6
6
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Xiang Zheng <zhengxiang9@huawei.com>
8
Message-id: 20190427133028.12874-1-philmd@redhat.com
8
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
9
Message-id: 20200512030609.19593-2-gengdongjiu@huawei.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
hw/dma/Makefile.objs | 2 +-
13
include/qemu/uuid.h | 27 +++++++++++++++++++++++++++
13
1 file changed, 1 insertion(+), 1 deletion(-)
14
hw/acpi/nvdimm.c | 10 +++-------
15
2 files changed, 30 insertions(+), 7 deletions(-)
14
16
15
diff --git a/hw/dma/Makefile.objs b/hw/dma/Makefile.objs
17
diff --git a/include/qemu/uuid.h b/include/qemu/uuid.h
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/dma/Makefile.objs
19
--- a/include/qemu/uuid.h
18
+++ b/hw/dma/Makefile.objs
20
+++ b/include/qemu/uuid.h
19
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_XLNX_ZYNQMP_ARM) += xlnx-zdma.o
21
@@ -XXX,XX +XXX,XX @@ typedef struct {
20
22
};
21
obj-$(CONFIG_OMAP) += omap_dma.o soc_dma.o
23
} QemuUUID;
22
obj-$(CONFIG_PXA2XX) += pxa2xx_dma.o
24
23
-obj-$(CONFIG_RASPI) += bcm2835_dma.o
25
+/**
24
+common-obj-$(CONFIG_RASPI) += bcm2835_dma.o
26
+ * UUID_LE - converts the fields of UUID to little-endian array,
27
+ * each of parameters is the filed of UUID.
28
+ *
29
+ * @time_low: The low field of the timestamp
30
+ * @time_mid: The middle field of the timestamp
31
+ * @time_hi_and_version: The high field of the timestamp
32
+ * multiplexed with the version number
33
+ * @clock_seq_hi_and_reserved: The high field of the clock
34
+ * sequence multiplexed with the variant
35
+ * @clock_seq_low: The low field of the clock sequence
36
+ * @node0: The spatially unique node0 identifier
37
+ * @node1: The spatially unique node1 identifier
38
+ * @node2: The spatially unique node2 identifier
39
+ * @node3: The spatially unique node3 identifier
40
+ * @node4: The spatially unique node4 identifier
41
+ * @node5: The spatially unique node5 identifier
42
+ */
43
+#define UUID_LE(time_low, time_mid, time_hi_and_version, \
44
+ clock_seq_hi_and_reserved, clock_seq_low, node0, node1, node2, \
45
+ node3, node4, node5) \
46
+ { (time_low) & 0xff, ((time_low) >> 8) & 0xff, ((time_low) >> 16) & 0xff, \
47
+ ((time_low) >> 24) & 0xff, (time_mid) & 0xff, ((time_mid) >> 8) & 0xff, \
48
+ (time_hi_and_version) & 0xff, ((time_hi_and_version) >> 8) & 0xff, \
49
+ (clock_seq_hi_and_reserved), (clock_seq_low), (node0), (node1), (node2),\
50
+ (node3), (node4), (node5) }
51
+
52
#define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-" \
53
"%02hhx%02hhx-%02hhx%02hhx-" \
54
"%02hhx%02hhx-" \
55
diff --git a/hw/acpi/nvdimm.c b/hw/acpi/nvdimm.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/hw/acpi/nvdimm.c
58
+++ b/hw/acpi/nvdimm.c
59
@@ -XXX,XX +XXX,XX @@
60
*/
61
62
#include "qemu/osdep.h"
63
+#include "qemu/uuid.h"
64
#include "hw/acpi/acpi.h"
65
#include "hw/acpi/aml-build.h"
66
#include "hw/acpi/bios-linker-loader.h"
67
@@ -XXX,XX +XXX,XX @@
68
#include "hw/mem/nvdimm.h"
69
#include "qemu/nvdimm-utils.h"
70
71
-#define NVDIMM_UUID_LE(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \
72
- { (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
73
- (b) & 0xff, ((b) >> 8) & 0xff, (c) & 0xff, ((c) >> 8) & 0xff, \
74
- (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }
75
-
76
/*
77
* define Byte Addressable Persistent Memory (PM) Region according to
78
* ACPI 6.0: 5.2.25.1 System Physical Address Range Structure.
79
*/
80
static const uint8_t nvdimm_nfit_spa_uuid[] =
81
- NVDIMM_UUID_LE(0x66f0d379, 0xb4f3, 0x4074, 0xac, 0x43, 0x0d, 0x33,
82
- 0x18, 0xb7, 0x8c, 0xdb);
83
+ UUID_LE(0x66f0d379, 0xb4f3, 0x4074, 0xac, 0x43, 0x0d, 0x33,
84
+ 0x18, 0xb7, 0x8c, 0xdb);
85
86
/*
87
* NVDIMM Firmware Interface Table
25
--
88
--
26
2.20.1
89
2.20.1
27
90
28
91
diff view generated by jsdifflib
1
The magic value pushed onto the callee stack as an integrity
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
2
check is different if floating point is present.
3
2
3
RAS Virtualization feature is not supported now, so
4
add a RAS machine option and disable it by default.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
8
Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
9
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
10
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
11
Message-id: 20200512030609.19593-3-gengdongjiu@huawei.com
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20190416125744.27770-15-peter.maydell@linaro.org
7
---
13
---
8
target/arm/helper.c | 22 +++++++++++++++++++---
14
include/hw/arm/virt.h | 1 +
9
1 file changed, 19 insertions(+), 3 deletions(-)
15
hw/arm/virt.c | 23 +++++++++++++++++++++++
16
2 files changed, 24 insertions(+)
10
17
11
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h
12
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/helper.c
20
--- a/include/hw/arm/virt.h
14
+++ b/target/arm/helper.c
21
+++ b/include/hw/arm/virt.h
15
@@ -XXX,XX +XXX,XX @@ load_fail:
22
@@ -XXX,XX +XXX,XX @@ typedef struct {
16
return false;
23
bool highmem_ecam;
24
bool its;
25
bool virt;
26
+ bool ras;
27
OnOffAuto acpi;
28
VirtGICType gic_version;
29
VirtIOMMUType iommu;
30
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/arm/virt.c
33
+++ b/hw/arm/virt.c
34
@@ -XXX,XX +XXX,XX @@ static void virt_set_acpi(Object *obj, Visitor *v, const char *name,
35
visit_type_OnOffAuto(v, name, &vms->acpi, errp);
17
}
36
}
18
37
19
+static uint32_t v7m_integrity_sig(CPUARMState *env, uint32_t lr)
38
+static bool virt_get_ras(Object *obj, Error **errp)
20
+{
39
+{
21
+ /*
40
+ VirtMachineState *vms = VIRT_MACHINE(obj);
22
+ * Return the integrity signature value for the callee-saves
23
+ * stack frame section. @lr is the exception return payload/LR value
24
+ * whose FType bit forms bit 0 of the signature if FP is present.
25
+ */
26
+ uint32_t sig = 0xfefa125a;
27
+
41
+
28
+ if (!arm_feature(env, ARM_FEATURE_VFP) || (lr & R_V7M_EXCRET_FTYPE_MASK)) {
42
+ return vms->ras;
29
+ sig |= 1;
30
+ }
31
+ return sig;
32
+}
43
+}
33
+
44
+
34
static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
45
+static void virt_set_ras(Object *obj, bool value, Error **errp)
35
bool ignore_faults)
46
+{
47
+ VirtMachineState *vms = VIRT_MACHINE(obj);
48
+
49
+ vms->ras = value;
50
+}
51
+
52
static char *virt_get_gic_version(Object *obj, Error **errp)
36
{
53
{
37
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
54
VirtMachineState *vms = VIRT_MACHINE(obj);
38
bool stacked_ok;
55
@@ -XXX,XX +XXX,XX @@ static void virt_instance_init(Object *obj)
39
uint32_t limit;
56
"Valid values are none and smmuv3",
40
bool want_psp;
57
NULL);
41
+ uint32_t sig;
58
42
59
+ /* Default disallows RAS instantiation */
43
if (dotailchain) {
60
+ vms->ras = false;
44
bool mode = lr & R_V7M_EXCRET_MODE_MASK;
61
+ object_property_add_bool(obj, "ras", virt_get_ras,
45
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
62
+ virt_set_ras, NULL);
46
/* Write as much of the stack frame as we can. A write failure may
63
+ object_property_set_description(obj, "ras",
47
* cause us to pend a derived exception.
64
+ "Set on/off to enable/disable reporting host memory errors "
48
*/
65
+ "to a KVM guest using ACPI and guest external abort exceptions",
49
+ sig = v7m_integrity_sig(env, lr);
66
+ NULL);
50
stacked_ok =
67
+
51
- v7m_stack_write(cpu, frameptr, 0xfefa125b, mmu_idx, ignore_faults) &&
68
vms->irqmap = a15irqmap;
52
+ v7m_stack_write(cpu, frameptr, sig, mmu_idx, ignore_faults) &&
69
53
v7m_stack_write(cpu, frameptr + 0x8, env->regs[4], mmu_idx,
70
virt_flash_create(vms);
54
ignore_faults) &&
55
v7m_stack_write(cpu, frameptr + 0xc, env->regs[5], mmu_idx,
56
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
57
if (return_to_secure &&
58
((excret & R_V7M_EXCRET_ES_MASK) == 0 ||
59
(excret & R_V7M_EXCRET_DCRS_MASK) == 0)) {
60
- uint32_t expected_sig = 0xfefa125b;
61
uint32_t actual_sig;
62
63
pop_ok = v7m_stack_read(cpu, &actual_sig, frameptr, mmu_idx);
64
65
- if (pop_ok && expected_sig != actual_sig) {
66
+ if (pop_ok && v7m_integrity_sig(env, excret) != actual_sig) {
67
/* Take a SecureFault on the current stack */
68
env->v7m.sfsr |= R_V7M_SFSR_INVIS_MASK;
69
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
70
--
71
--
71
2.20.1
72
2.20.1
72
73
73
74
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
2
2
3
Add an entries the Blizzard device in MAINTAINERS.
3
Add APEI/GHES detailed design document
4
4
5
Reviewed-by: Thomas Huth <thuth@redhat.com>
5
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
6
Reviewed-by: Markus Armbruster <armbru@redhat.com>
6
Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
7
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
8
Message-id: 20190412165416.7977-6-philmd@redhat.com
8
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
9
Message-id: 20200512030609.19593-4-gengdongjiu@huawei.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
---
11
include/hw/devices.h | 7 -------
12
docs/specs/acpi_hest_ghes.rst | 110 ++++++++++++++++++++++++++++++++++
12
include/hw/display/blizzard.h | 22 ++++++++++++++++++++++
13
docs/specs/index.rst | 1 +
13
hw/arm/nseries.c | 1 +
14
2 files changed, 111 insertions(+)
14
hw/display/blizzard.c | 2 +-
15
create mode 100644 docs/specs/acpi_hest_ghes.rst
15
MAINTAINERS | 2 ++
16
5 files changed, 26 insertions(+), 8 deletions(-)
17
create mode 100644 include/hw/display/blizzard.h
18
16
19
diff --git a/include/hw/devices.h b/include/hw/devices.h
17
diff --git a/docs/specs/acpi_hest_ghes.rst b/docs/specs/acpi_hest_ghes.rst
20
index XXXXXXX..XXXXXXX 100644
21
--- a/include/hw/devices.h
22
+++ b/include/hw/devices.h
23
@@ -XXX,XX +XXX,XX @@ void tsc2005_set_transform(void *opaque, MouseTransformInfo *info);
24
/* stellaris_input.c */
25
void stellaris_gamepad_init(int n, qemu_irq *irq, const int *keycode);
26
27
-/* blizzard.c */
28
-void *s1d13745_init(qemu_irq gpio_int);
29
-void s1d13745_write(void *opaque, int dc, uint16_t value);
30
-void s1d13745_write_block(void *opaque, int dc,
31
- void *buf, size_t len, int pitch);
32
-uint16_t s1d13745_read(void *opaque, int dc);
33
-
34
/* cbus.c */
35
typedef struct {
36
qemu_irq clk;
37
diff --git a/include/hw/display/blizzard.h b/include/hw/display/blizzard.h
38
new file mode 100644
18
new file mode 100644
39
index XXXXXXX..XXXXXXX
19
index XXXXXXX..XXXXXXX
40
--- /dev/null
20
--- /dev/null
41
+++ b/include/hw/display/blizzard.h
21
+++ b/docs/specs/acpi_hest_ghes.rst
42
@@ -XXX,XX +XXX,XX @@
22
@@ -XXX,XX +XXX,XX @@
43
+/*
23
+APEI tables generating and CPER record
44
+ * Epson S1D13744/S1D13745 (Blizzard/Hailstorm/Tornado) LCD/TV controller.
24
+======================================
45
+ *
46
+ * Copyright (C) 2008 Nokia Corporation
47
+ * Written by Andrzej Zaborowski
48
+ *
49
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
50
+ * See the COPYING file in the top-level directory.
51
+ */
52
+
25
+
53
+#ifndef HW_DISPLAY_BLIZZARD_H
26
+..
54
+#define HW_DISPLAY_BLIZZARD_H
27
+ Copyright (c) 2020 HUAWEI TECHNOLOGIES CO., LTD.
55
+
28
+
56
+#include "hw/irq.h"
29
+ This work is licensed under the terms of the GNU GPL, version 2 or later.
30
+ See the COPYING file in the top-level directory.
57
+
31
+
58
+void *s1d13745_init(qemu_irq gpio_int);
32
+Design Details
59
+void s1d13745_write(void *opaque, int dc, uint16_t value);
33
+--------------
60
+void s1d13745_write_block(void *opaque, int dc,
61
+ void *buf, size_t len, int pitch);
62
+uint16_t s1d13745_read(void *opaque, int dc);
63
+
34
+
64
+#endif
35
+::
65
diff --git a/hw/arm/nseries.c b/hw/arm/nseries.c
36
+
37
+ etc/acpi/tables etc/hardware_errors
38
+ ==================== ===============================
39
+ + +--------------------------+ +----------------------------+
40
+ | | HEST | +--------->| error_block_address1 |------+
41
+ | +--------------------------+ | +----------------------------+ |
42
+ | | GHES1 | | +------->| error_block_address2 |------+-+
43
+ | +--------------------------+ | | +----------------------------+ | |
44
+ | | ................. | | | | .............. | | |
45
+ | | error_status_address-----+-+ | -----------------------------+ | |
46
+ | | ................. | | +--->| error_block_addressN |------+-+---+
47
+ | | read_ack_register--------+-+ | | +----------------------------+ | | |
48
+ | | read_ack_preserve | +-+---+--->| read_ack_register1 | | | |
49
+ | | read_ack_write | | | +----------------------------+ | | |
50
+ + +--------------------------+ | +-+--->| read_ack_register2 | | | |
51
+ | | GHES2 | | | | +----------------------------+ | | |
52
+ + +--------------------------+ | | | | ............. | | | |
53
+ | | ................. | | | | +----------------------------+ | | |
54
+ | | error_status_address-----+---+ | | +->| read_ack_registerN | | | |
55
+ | | ................. | | | | +----------------------------+ | | |
56
+ | | read_ack_register--------+-----+ | | |Generic Error Status Block 1|<-----+ | |
57
+ | | read_ack_preserve | | | |-+------------------------+-+ | |
58
+ | | read_ack_write | | | | | CPER | | | |
59
+ + +--------------------------| | | | | CPER | | | |
60
+ | | ............... | | | | | .... | | | |
61
+ + +--------------------------+ | | | | CPER | | | |
62
+ | | GHESN | | | |-+------------------------+-| | |
63
+ + +--------------------------+ | | |Generic Error Status Block 2|<-------+ |
64
+ | | ................. | | | |-+------------------------+-+ |
65
+ | | error_status_address-----+-------+ | | | CPER | | |
66
+ | | ................. | | | | CPER | | |
67
+ | | read_ack_register--------+---------+ | | .... | | |
68
+ | | read_ack_preserve | | | CPER | | |
69
+ | | read_ack_write | +-+------------------------+-+ |
70
+ + +--------------------------+ | .......... | |
71
+ |----------------------------+ |
72
+ |Generic Error Status Block N |<----------+
73
+ |-+-------------------------+-+
74
+ | | CPER | |
75
+ | | CPER | |
76
+ | | .... | |
77
+ | | CPER | |
78
+ +-+-------------------------+-+
79
+
80
+
81
+(1) QEMU generates the ACPI HEST table. This table goes in the current
82
+ "etc/acpi/tables" fw_cfg blob. Each error source has different
83
+ notification types.
84
+
85
+(2) A new fw_cfg blob called "etc/hardware_errors" is introduced. QEMU
86
+ also needs to populate this blob. The "etc/hardware_errors" fw_cfg blob
87
+ contains an address registers table and an Error Status Data Block table.
88
+
89
+(3) The address registers table contains N Error Block Address entries
90
+ and N Read Ack Register entries. The size for each entry is 8-byte.
91
+ The Error Status Data Block table contains N Error Status Data Block
92
+ entries. The size for each entry is 4096(0x1000) bytes. The total size
93
+ for the "etc/hardware_errors" fw_cfg blob is (N * 8 * 2 + N * 4096) bytes.
94
+ N is the number of the kinds of hardware error sources.
95
+
96
+(4) QEMU generates the ACPI linker/loader script for the firmware. The
97
+ firmware pre-allocates memory for "etc/acpi/tables", "etc/hardware_errors"
98
+ and copies blob contents there.
99
+
100
+(5) QEMU generates N ADD_POINTER commands, which patch addresses in the
101
+ "error_status_address" fields of the HEST table with a pointer to the
102
+ corresponding "address registers" in the "etc/hardware_errors" blob.
103
+
104
+(6) QEMU generates N ADD_POINTER commands, which patch addresses in the
105
+ "read_ack_register" fields of the HEST table with a pointer to the
106
+ corresponding "read_ack_register" within the "etc/hardware_errors" blob.
107
+
108
+(7) QEMU generates N ADD_POINTER commands for the firmware, which patch
109
+ addresses in the "error_block_address" fields with a pointer to the
110
+ respective "Error Status Data Block" in the "etc/hardware_errors" blob.
111
+
112
+(8) QEMU defines a third and write-only fw_cfg blob which is called
113
+ "etc/hardware_errors_addr". Through that blob, the firmware can send back
114
+ the guest-side allocation addresses to QEMU. The "etc/hardware_errors_addr"
115
+ blob contains a 8-byte entry. QEMU generates a single WRITE_POINTER command
116
+ for the firmware. The firmware will write back the start address of
117
+ "etc/hardware_errors" blob to the fw_cfg file "etc/hardware_errors_addr".
118
+
119
+(9) When QEMU gets a SIGBUS from the kernel, QEMU writes CPER into corresponding
120
+ "Error Status Data Block", guest memory, and then injects platform specific
121
+ interrupt (in case of arm/virt machine it's Synchronous External Abort) as a
122
+ notification which is necessary for notifying the guest.
123
+
124
+(10) This notification (in virtual hardware) will be handled by the guest
125
+ kernel, on receiving notification, guest APEI driver could read the CPER error
126
+ and take appropriate action.
127
+
128
+(11) kvm_arch_on_sigbus_vcpu() uses source_id as index in "etc/hardware_errors" to
129
+ find out "Error Status Data Block" entry corresponding to error source. So supported
130
+ source_id values should be assigned here and not be changed afterwards to make sure
131
+ that guest will write error into expected "Error Status Data Block" even if guest was
132
+ migrated to a newer QEMU.
133
diff --git a/docs/specs/index.rst b/docs/specs/index.rst
66
index XXXXXXX..XXXXXXX 100644
134
index XXXXXXX..XXXXXXX 100644
67
--- a/hw/arm/nseries.c
135
--- a/docs/specs/index.rst
68
+++ b/hw/arm/nseries.c
136
+++ b/docs/specs/index.rst
69
@@ -XXX,XX +XXX,XX @@
137
@@ -XXX,XX +XXX,XX @@ Contents:
70
#include "hw/boards.h"
138
ppc-spapr-xive
71
#include "hw/i2c/i2c.h"
139
acpi_hw_reduced_hotplug
72
#include "hw/devices.h"
140
tpm
73
+#include "hw/display/blizzard.h"
141
+ acpi_hest_ghes
74
#include "hw/misc/tmp105.h"
75
#include "hw/block/flash.h"
76
#include "hw/hw.h"
77
diff --git a/hw/display/blizzard.c b/hw/display/blizzard.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/hw/display/blizzard.c
80
+++ b/hw/display/blizzard.c
81
@@ -XXX,XX +XXX,XX @@
82
#include "qemu/osdep.h"
83
#include "qemu-common.h"
84
#include "ui/console.h"
85
-#include "hw/devices.h"
86
+#include "hw/display/blizzard.h"
87
#include "ui/pixel_ops.h"
88
89
typedef void (*blizzard_fn_t)(uint8_t *, const uint8_t *, unsigned int);
90
diff --git a/MAINTAINERS b/MAINTAINERS
91
index XXXXXXX..XXXXXXX 100644
92
--- a/MAINTAINERS
93
+++ b/MAINTAINERS
94
@@ -XXX,XX +XXX,XX @@ M: Peter Maydell <peter.maydell@linaro.org>
95
L: qemu-arm@nongnu.org
96
S: Odd Fixes
97
F: hw/arm/nseries.c
98
+F: hw/display/blizzard.c
99
F: hw/input/lm832x.c
100
F: hw/input/tsc2005.c
101
F: hw/misc/cbus.c
102
F: hw/timer/twl92230.c
103
+F: include/hw/display/blizzard.h
104
105
Palm
106
M: Andrzej Zaborowski <balrogg@gmail.com>
107
--
142
--
108
2.20.1
143
2.20.1
109
144
110
145
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
2
2
3
This commit finally deletes "hw/devices.h".
3
This patch builds error_block_address and read_ack_register fields
4
4
in hardware errors table , the error_block_address points to Generic
5
Reviewed-by: Markus Armbruster <armbru@redhat.com>
5
Error Status Block(GESB) via bios_linker. The max size for one GESB
6
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
6
is 1kb, For more detailed information, please refer to
7
Message-id: 20190412165416.7977-13-philmd@redhat.com
7
document: docs/specs/acpi_hest_ghes.rst
8
9
Now we only support one Error source, if necessary, we can extend to
10
support more.
11
12
Suggested-by: Laszlo Ersek <lersek@redhat.com>
13
Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
14
Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
15
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
16
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
17
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
18
Message-id: 20200512030609.19593-5-gengdongjiu@huawei.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
20
---
10
include/hw/devices.h | 11 -----------
21
default-configs/arm-softmmu.mak | 1 +
11
include/hw/net/smc91c111.h | 19 +++++++++++++++++++
22
include/hw/acpi/aml-build.h | 1 +
12
hw/arm/gumstix.c | 2 +-
23
include/hw/acpi/ghes.h | 28 +++++++++++
13
hw/arm/integratorcp.c | 2 +-
24
hw/acpi/aml-build.c | 2 +
14
hw/arm/mainstone.c | 2 +-
25
hw/acpi/ghes.c | 89 +++++++++++++++++++++++++++++++++
15
hw/arm/realview.c | 2 +-
26
hw/arm/virt-acpi-build.c | 5 ++
16
hw/arm/versatilepb.c | 2 +-
27
hw/acpi/Kconfig | 4 ++
17
hw/net/smc91c111.c | 2 +-
28
hw/acpi/Makefile.objs | 1 +
18
8 files changed, 25 insertions(+), 17 deletions(-)
29
8 files changed, 131 insertions(+)
19
delete mode 100644 include/hw/devices.h
30
create mode 100644 include/hw/acpi/ghes.h
20
create mode 100644 include/hw/net/smc91c111.h
31
create mode 100644 hw/acpi/ghes.c
21
32
22
diff --git a/include/hw/devices.h b/include/hw/devices.h
33
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak
23
deleted file mode 100644
34
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX
35
--- a/default-configs/arm-softmmu.mak
25
--- a/include/hw/devices.h
36
+++ b/default-configs/arm-softmmu.mak
26
+++ /dev/null
37
@@ -XXX,XX +XXX,XX @@ CONFIG_FSL_IMX7=y
27
@@ -XXX,XX +XXX,XX @@
38
CONFIG_FSL_IMX6UL=y
28
-#ifndef QEMU_DEVICES_H
39
CONFIG_SEMIHOSTING=y
29
-#define QEMU_DEVICES_H
40
CONFIG_ALLWINNER_H3=y
30
-
41
+CONFIG_ACPI_APEI=y
31
-/* Devices that have nowhere better to go. */
42
diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h
32
-
43
index XXXXXXX..XXXXXXX 100644
33
-#include "hw/hw.h"
44
--- a/include/hw/acpi/aml-build.h
34
-
45
+++ b/include/hw/acpi/aml-build.h
35
-/* smc91c111.c */
46
@@ -XXX,XX +XXX,XX @@ struct AcpiBuildTables {
36
-void smc91c111_init(NICInfo *, uint32_t, qemu_irq);
47
GArray *rsdp;
37
-
48
GArray *tcpalog;
38
-#endif
49
GArray *vmgenid;
39
diff --git a/include/hw/net/smc91c111.h b/include/hw/net/smc91c111.h
50
+ GArray *hardware_errors;
51
BIOSLinker *linker;
52
} AcpiBuildTables;
53
54
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
40
new file mode 100644
55
new file mode 100644
41
index XXXXXXX..XXXXXXX
56
index XXXXXXX..XXXXXXX
42
--- /dev/null
57
--- /dev/null
43
+++ b/include/hw/net/smc91c111.h
58
+++ b/include/hw/acpi/ghes.h
44
@@ -XXX,XX +XXX,XX @@
59
@@ -XXX,XX +XXX,XX @@
45
+/*
60
+/*
46
+ * SMSC 91C111 Ethernet interface emulation
61
+ * Support for generating APEI tables and recording CPER for Guests
47
+ *
62
+ *
48
+ * Copyright (c) 2005 CodeSourcery, LLC.
63
+ * Copyright (c) 2020 HUAWEI TECHNOLOGIES CO., LTD.
49
+ * Written by Paul Brook
64
+ *
50
+ *
65
+ * Author: Dongjiu Geng <gengdongjiu@huawei.com>
51
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
66
+ *
52
+ * See the COPYING file in the top-level directory.
67
+ * This program is free software; you can redistribute it and/or modify
68
+ * it under the terms of the GNU General Public License as published by
69
+ * the Free Software Foundation; either version 2 of the License, or
70
+ * (at your option) any later version.
71
+
72
+ * This program is distributed in the hope that it will be useful,
73
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
74
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
75
+ * GNU General Public License for more details.
76
+
77
+ * You should have received a copy of the GNU General Public License along
78
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
53
+ */
79
+ */
54
+
80
+
55
+#ifndef HW_NET_SMC91C111_H
81
+#ifndef ACPI_GHES_H
56
+#define HW_NET_SMC91C111_H
82
+#define ACPI_GHES_H
57
+
83
+
58
+#include "hw/irq.h"
84
+#include "hw/acpi/bios-linker-loader.h"
59
+#include "net/net.h"
85
+
60
+
86
+void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker);
61
+void smc91c111_init(NICInfo *, uint32_t, qemu_irq);
62
+
63
+#endif
87
+#endif
64
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
88
diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
65
index XXXXXXX..XXXXXXX 100644
89
index XXXXXXX..XXXXXXX 100644
66
--- a/hw/arm/gumstix.c
90
--- a/hw/acpi/aml-build.c
67
+++ b/hw/arm/gumstix.c
91
+++ b/hw/acpi/aml-build.c
92
@@ -XXX,XX +XXX,XX @@ void acpi_build_tables_init(AcpiBuildTables *tables)
93
tables->table_data = g_array_new(false, true /* clear */, 1);
94
tables->tcpalog = g_array_new(false, true /* clear */, 1);
95
tables->vmgenid = g_array_new(false, true /* clear */, 1);
96
+ tables->hardware_errors = g_array_new(false, true /* clear */, 1);
97
tables->linker = bios_linker_loader_init();
98
}
99
100
@@ -XXX,XX +XXX,XX @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
101
g_array_free(tables->table_data, true);
102
g_array_free(tables->tcpalog, mfre);
103
g_array_free(tables->vmgenid, mfre);
104
+ g_array_free(tables->hardware_errors, mfre);
105
}
106
107
/*
108
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
109
new file mode 100644
110
index XXXXXXX..XXXXXXX
111
--- /dev/null
112
+++ b/hw/acpi/ghes.c
68
@@ -XXX,XX +XXX,XX @@
113
@@ -XXX,XX +XXX,XX @@
69
#include "hw/arm/pxa.h"
114
+/*
70
#include "net/net.h"
115
+ * Support for generating APEI tables and recording CPER for Guests
71
#include "hw/block/flash.h"
116
+ *
72
-#include "hw/devices.h"
117
+ * Copyright (c) 2020 HUAWEI TECHNOLOGIES CO., LTD.
73
+#include "hw/net/smc91c111.h"
118
+ *
74
#include "hw/boards.h"
119
+ * Author: Dongjiu Geng <gengdongjiu@huawei.com>
75
#include "exec/address-spaces.h"
120
+ *
76
#include "sysemu/qtest.h"
121
+ * This program is free software; you can redistribute it and/or modify
77
diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
122
+ * it under the terms of the GNU General Public License as published by
78
index XXXXXXX..XXXXXXX 100644
123
+ * the Free Software Foundation; either version 2 of the License, or
79
--- a/hw/arm/integratorcp.c
124
+ * (at your option) any later version.
80
+++ b/hw/arm/integratorcp.c
125
+
126
+ * This program is distributed in the hope that it will be useful,
127
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
128
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
129
+ * GNU General Public License for more details.
130
+
131
+ * You should have received a copy of the GNU General Public License along
132
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
133
+ */
134
+
135
+#include "qemu/osdep.h"
136
+#include "qemu/units.h"
137
+#include "hw/acpi/ghes.h"
138
+#include "hw/acpi/aml-build.h"
139
+
140
+#define ACPI_GHES_ERRORS_FW_CFG_FILE "etc/hardware_errors"
141
+#define ACPI_GHES_DATA_ADDR_FW_CFG_FILE "etc/hardware_errors_addr"
142
+
143
+/* The max size in bytes for one error block */
144
+#define ACPI_GHES_MAX_RAW_DATA_LENGTH (1 * KiB)
145
+
146
+/* Now only support ARMv8 SEA notification type error source */
147
+#define ACPI_GHES_ERROR_SOURCE_COUNT 1
148
+
149
+/*
150
+ * Build table for the hardware error fw_cfg blob.
151
+ * Initialize "etc/hardware_errors" and "etc/hardware_errors_addr" fw_cfg blobs.
152
+ * See docs/specs/acpi_hest_ghes.rst for blobs format.
153
+ */
154
+void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker)
155
+{
156
+ int i, error_status_block_offset;
157
+
158
+ /* Build error_block_address */
159
+ for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) {
160
+ build_append_int_noprefix(hardware_errors, 0, sizeof(uint64_t));
161
+ }
162
+
163
+ /* Build read_ack_register */
164
+ for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) {
165
+ /*
166
+ * Initialize the value of read_ack_register to 1, so GHES can be
167
+ * writeable after (re)boot.
168
+ * ACPI 6.2: 18.3.2.8 Generic Hardware Error Source version 2
169
+ * (GHESv2 - Type 10)
170
+ */
171
+ build_append_int_noprefix(hardware_errors, 1, sizeof(uint64_t));
172
+ }
173
+
174
+ /* Generic Error Status Block offset in the hardware error fw_cfg blob */
175
+ error_status_block_offset = hardware_errors->len;
176
+
177
+ /* Reserve space for Error Status Data Block */
178
+ acpi_data_push(hardware_errors,
179
+ ACPI_GHES_MAX_RAW_DATA_LENGTH * ACPI_GHES_ERROR_SOURCE_COUNT);
180
+
181
+ /* Tell guest firmware to place hardware_errors blob into RAM */
182
+ bios_linker_loader_alloc(linker, ACPI_GHES_ERRORS_FW_CFG_FILE,
183
+ hardware_errors, sizeof(uint64_t), false);
184
+
185
+ for (i = 0; i < ACPI_GHES_ERROR_SOURCE_COUNT; i++) {
186
+ /*
187
+ * Tell firmware to patch error_block_address entries to point to
188
+ * corresponding "Generic Error Status Block"
189
+ */
190
+ bios_linker_loader_add_pointer(linker,
191
+ ACPI_GHES_ERRORS_FW_CFG_FILE, sizeof(uint64_t) * i,
192
+ sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE,
193
+ error_status_block_offset + i * ACPI_GHES_MAX_RAW_DATA_LENGTH);
194
+ }
195
+
196
+ /*
197
+ * tell firmware to write hardware_errors GPA into
198
+ * hardware_errors_addr fw_cfg, once the former has been initialized.
199
+ */
200
+ bios_linker_loader_write_pointer(linker, ACPI_GHES_DATA_ADDR_FW_CFG_FILE,
201
+ 0, sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE, 0);
202
+}
203
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
204
index XXXXXXX..XXXXXXX 100644
205
--- a/hw/arm/virt-acpi-build.c
206
+++ b/hw/arm/virt-acpi-build.c
81
@@ -XXX,XX +XXX,XX @@
207
@@ -XXX,XX +XXX,XX @@
82
#include "qemu-common.h"
208
#include "sysemu/reset.h"
83
#include "cpu.h"
209
#include "kvm_arm.h"
84
#include "hw/sysbus.h"
210
#include "migration/vmstate.h"
85
-#include "hw/devices.h"
211
+#include "hw/acpi/ghes.h"
86
#include "hw/boards.h"
212
87
#include "hw/arm/arm.h"
213
#define ARM_SPI_BASE 32
88
#include "hw/misc/arm_integrator_debug.h"
214
89
+#include "hw/net/smc91c111.h"
215
@@ -XXX,XX +XXX,XX @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
90
#include "net/net.h"
216
acpi_add_table(table_offsets, tables_blob);
91
#include "exec/address-spaces.h"
217
build_spcr(tables_blob, tables->linker, vms);
92
#include "sysemu/sysemu.h"
218
93
diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
219
+ if (vms->ras) {
94
index XXXXXXX..XXXXXXX 100644
220
+ build_ghes_error_table(tables->hardware_errors, tables->linker);
95
--- a/hw/arm/mainstone.c
221
+ }
96
+++ b/hw/arm/mainstone.c
222
+
97
@@ -XXX,XX +XXX,XX @@
223
if (ms->numa_state->num_nodes > 0) {
98
#include "hw/arm/pxa.h"
224
acpi_add_table(table_offsets, tables_blob);
99
#include "hw/arm/arm.h"
225
build_srat(tables_blob, tables->linker, vms);
100
#include "net/net.h"
226
diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig
101
-#include "hw/devices.h"
227
index XXXXXXX..XXXXXXX 100644
102
+#include "hw/net/smc91c111.h"
228
--- a/hw/acpi/Kconfig
103
#include "hw/boards.h"
229
+++ b/hw/acpi/Kconfig
104
#include "hw/block/flash.h"
230
@@ -XXX,XX +XXX,XX @@ config ACPI_HMAT
105
#include "hw/sysbus.h"
231
bool
106
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
232
depends on ACPI
107
index XXXXXXX..XXXXXXX 100644
233
108
--- a/hw/arm/realview.c
234
+config ACPI_APEI
109
+++ b/hw/arm/realview.c
235
+ bool
110
@@ -XXX,XX +XXX,XX @@
236
+ depends on ACPI
111
#include "hw/sysbus.h"
237
+
112
#include "hw/arm/arm.h"
238
config ACPI_PCI
113
#include "hw/arm/primecell.h"
239
bool
114
-#include "hw/devices.h"
240
depends on ACPI && PCI
115
#include "hw/net/lan9118.h"
241
diff --git a/hw/acpi/Makefile.objs b/hw/acpi/Makefile.objs
116
+#include "hw/net/smc91c111.h"
242
index XXXXXXX..XXXXXXX 100644
117
#include "hw/pci/pci.h"
243
--- a/hw/acpi/Makefile.objs
118
#include "net/net.h"
244
+++ b/hw/acpi/Makefile.objs
119
#include "sysemu/sysemu.h"
245
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
120
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
246
common-obj-$(CONFIG_ACPI_VMGENID) += vmgenid.o
121
index XXXXXXX..XXXXXXX 100644
247
common-obj-$(CONFIG_ACPI_HW_REDUCED) += generic_event_device.o
122
--- a/hw/arm/versatilepb.c
248
common-obj-$(CONFIG_ACPI_HMAT) += hmat.o
123
+++ b/hw/arm/versatilepb.c
249
+common-obj-$(CONFIG_ACPI_APEI) += ghes.o
124
@@ -XXX,XX +XXX,XX @@
250
common-obj-$(call lnot,$(CONFIG_ACPI_X86)) += acpi-stub.o
125
#include "cpu.h"
251
common-obj-$(call lnot,$(CONFIG_PC)) += acpi-x86-stub.o
126
#include "hw/sysbus.h"
252
127
#include "hw/arm/arm.h"
128
-#include "hw/devices.h"
129
+#include "hw/net/smc91c111.h"
130
#include "net/net.h"
131
#include "sysemu/sysemu.h"
132
#include "hw/pci/pci.h"
133
diff --git a/hw/net/smc91c111.c b/hw/net/smc91c111.c
134
index XXXXXXX..XXXXXXX 100644
135
--- a/hw/net/smc91c111.c
136
+++ b/hw/net/smc91c111.c
137
@@ -XXX,XX +XXX,XX @@
138
#include "qemu/osdep.h"
139
#include "hw/sysbus.h"
140
#include "net/net.h"
141
-#include "hw/devices.h"
142
+#include "hw/net/smc91c111.h"
143
#include "qemu/log.h"
144
/* For crc32 */
145
#include <zlib.h>
146
--
253
--
147
2.20.1
254
2.20.1
148
255
149
256
diff view generated by jsdifflib
1
The M-profile CONTROL register has two bits -- SFPA and FPCA --
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
2
which relate to floating-point support, and should be RES0 otherwise.
2
3
Handle them correctly in the MSR/MRS register access code.
3
This patch builds Hardware Error Source Table(HEST) via fw_cfg blobs.
4
Neither is banked between security states, so they are stored
4
Now it only supports ARMv8 SEA, a type of Generic Hardware Error
5
in v7m.control[M_REG_S] regardless of current security state.
5
Source version 2(GHESv2) error source. Afterwards, we can extend
6
6
the supported types if needed. For the CPER section, currently it
7
is memory section because kernel mainly wants userspace to handle
8
the memory errors.
9
10
This patch follows the spec ACPI 6.2 to build the Hardware Error
11
Source table. For more detailed information, please refer to
12
document: docs/specs/acpi_hest_ghes.rst
13
14
build_ghes_hw_error_notification() helper will help to add Hardware
15
Error Notification to ACPI tables without using packed C structures
16
and avoid endianness issues as API doesn't need explicit conversion.
17
18
Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
19
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
20
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
21
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
22
Message-id: 20200512030609.19593-6-gengdongjiu@huawei.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20190416125744.27770-9-peter.maydell@linaro.org
10
---
24
---
11
target/arm/helper.c | 57 ++++++++++++++++++++++++++++++++++++++-------
25
include/hw/acpi/ghes.h | 39 ++++++++++++
12
1 file changed, 49 insertions(+), 8 deletions(-)
26
hw/acpi/ghes.c | 126 +++++++++++++++++++++++++++++++++++++++
13
27
hw/arm/virt-acpi-build.c | 2 +
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
28
3 files changed, 167 insertions(+)
29
30
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
15
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
32
--- a/include/hw/acpi/ghes.h
17
+++ b/target/arm/helper.c
33
+++ b/include/hw/acpi/ghes.h
18
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
34
@@ -XXX,XX +XXX,XX @@
19
return xpsr_read(env) & mask;
35
20
break;
36
#include "hw/acpi/bios-linker-loader.h"
21
case 20: /* CONTROL */
37
22
- return env->v7m.control[env->v7m.secure];
38
+/*
23
+ {
39
+ * Values for Hardware Error Notification Type field
24
+ uint32_t value = env->v7m.control[env->v7m.secure];
40
+ */
25
+ if (!env->v7m.secure) {
41
+enum AcpiGhesNotifyType {
26
+ /* SFPA is RAZ/WI from NS; FPCA is stored in the M_REG_S bank */
42
+ /* Polled */
27
+ value |= env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK;
43
+ ACPI_GHES_NOTIFY_POLLED = 0,
28
+ }
44
+ /* External Interrupt */
29
+ return value;
45
+ ACPI_GHES_NOTIFY_EXTERNAL = 1,
46
+ /* Local Interrupt */
47
+ ACPI_GHES_NOTIFY_LOCAL = 2,
48
+ /* SCI */
49
+ ACPI_GHES_NOTIFY_SCI = 3,
50
+ /* NMI */
51
+ ACPI_GHES_NOTIFY_NMI = 4,
52
+ /* CMCI, ACPI 5.0: 18.3.2.7, Table 18-290 */
53
+ ACPI_GHES_NOTIFY_CMCI = 5,
54
+ /* MCE, ACPI 5.0: 18.3.2.7, Table 18-290 */
55
+ ACPI_GHES_NOTIFY_MCE = 6,
56
+ /* GPIO-Signal, ACPI 6.0: 18.3.2.7, Table 18-332 */
57
+ ACPI_GHES_NOTIFY_GPIO = 7,
58
+ /* ARMv8 SEA, ACPI 6.1: 18.3.2.9, Table 18-345 */
59
+ ACPI_GHES_NOTIFY_SEA = 8,
60
+ /* ARMv8 SEI, ACPI 6.1: 18.3.2.9, Table 18-345 */
61
+ ACPI_GHES_NOTIFY_SEI = 9,
62
+ /* External Interrupt - GSIV, ACPI 6.1: 18.3.2.9, Table 18-345 */
63
+ ACPI_GHES_NOTIFY_GSIV = 10,
64
+ /* Software Delegated Exception, ACPI 6.2: 18.3.2.9, Table 18-383 */
65
+ ACPI_GHES_NOTIFY_SDEI = 11,
66
+ /* 12 and greater are reserved */
67
+ ACPI_GHES_NOTIFY_RESERVED = 12
68
+};
69
+
70
+enum {
71
+ ACPI_HEST_SRC_ID_SEA = 0,
72
+ /* future ids go here */
73
+ ACPI_HEST_SRC_ID_RESERVED,
74
+};
75
+
76
void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker);
77
+void acpi_build_hest(GArray *table_data, BIOSLinker *linker);
78
#endif
79
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/hw/acpi/ghes.c
82
+++ b/hw/acpi/ghes.c
83
@@ -XXX,XX +XXX,XX @@
84
#include "qemu/units.h"
85
#include "hw/acpi/ghes.h"
86
#include "hw/acpi/aml-build.h"
87
+#include "qemu/error-report.h"
88
89
#define ACPI_GHES_ERRORS_FW_CFG_FILE "etc/hardware_errors"
90
#define ACPI_GHES_DATA_ADDR_FW_CFG_FILE "etc/hardware_errors_addr"
91
@@ -XXX,XX +XXX,XX @@
92
/* Now only support ARMv8 SEA notification type error source */
93
#define ACPI_GHES_ERROR_SOURCE_COUNT 1
94
95
+/* Generic Hardware Error Source version 2 */
96
+#define ACPI_GHES_SOURCE_GENERIC_ERROR_V2 10
97
+
98
+/* Address offset in Generic Address Structure(GAS) */
99
+#define GAS_ADDR_OFFSET 4
100
+
101
+/*
102
+ * Hardware Error Notification
103
+ * ACPI 4.0: 17.3.2.7 Hardware Error Notification
104
+ * Composes dummy Hardware Error Notification descriptor of specified type
105
+ */
106
+static void build_ghes_hw_error_notification(GArray *table, const uint8_t type)
107
+{
108
+ /* Type */
109
+ build_append_int_noprefix(table, type, 1);
110
+ /*
111
+ * Length:
112
+ * Total length of the structure in bytes
113
+ */
114
+ build_append_int_noprefix(table, 28, 1);
115
+ /* Configuration Write Enable */
116
+ build_append_int_noprefix(table, 0, 2);
117
+ /* Poll Interval */
118
+ build_append_int_noprefix(table, 0, 4);
119
+ /* Vector */
120
+ build_append_int_noprefix(table, 0, 4);
121
+ /* Switch To Polling Threshold Value */
122
+ build_append_int_noprefix(table, 0, 4);
123
+ /* Switch To Polling Threshold Window */
124
+ build_append_int_noprefix(table, 0, 4);
125
+ /* Error Threshold Value */
126
+ build_append_int_noprefix(table, 0, 4);
127
+ /* Error Threshold Window */
128
+ build_append_int_noprefix(table, 0, 4);
129
+}
130
+
131
/*
132
* Build table for the hardware error fw_cfg blob.
133
* Initialize "etc/hardware_errors" and "etc/hardware_errors_addr" fw_cfg blobs.
134
@@ -XXX,XX +XXX,XX @@ void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker)
135
bios_linker_loader_write_pointer(linker, ACPI_GHES_DATA_ADDR_FW_CFG_FILE,
136
0, sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE, 0);
137
}
138
+
139
+/* Build Generic Hardware Error Source version 2 (GHESv2) */
140
+static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker)
141
+{
142
+ uint64_t address_offset;
143
+ /*
144
+ * Type:
145
+ * Generic Hardware Error Source version 2(GHESv2 - Type 10)
146
+ */
147
+ build_append_int_noprefix(table_data, ACPI_GHES_SOURCE_GENERIC_ERROR_V2, 2);
148
+ /* Source Id */
149
+ build_append_int_noprefix(table_data, source_id, 2);
150
+ /* Related Source Id */
151
+ build_append_int_noprefix(table_data, 0xffff, 2);
152
+ /* Flags */
153
+ build_append_int_noprefix(table_data, 0, 1);
154
+ /* Enabled */
155
+ build_append_int_noprefix(table_data, 1, 1);
156
+
157
+ /* Number of Records To Pre-allocate */
158
+ build_append_int_noprefix(table_data, 1, 4);
159
+ /* Max Sections Per Record */
160
+ build_append_int_noprefix(table_data, 1, 4);
161
+ /* Max Raw Data Length */
162
+ build_append_int_noprefix(table_data, ACPI_GHES_MAX_RAW_DATA_LENGTH, 4);
163
+
164
+ address_offset = table_data->len;
165
+ /* Error Status Address */
166
+ build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 0x40, 0,
167
+ 4 /* QWord access */, 0);
168
+ bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
169
+ address_offset + GAS_ADDR_OFFSET, sizeof(uint64_t),
170
+ ACPI_GHES_ERRORS_FW_CFG_FILE, source_id * sizeof(uint64_t));
171
+
172
+ switch (source_id) {
173
+ case ACPI_HEST_SRC_ID_SEA:
174
+ /*
175
+ * Notification Structure
176
+ * Now only enable ARMv8 SEA notification type
177
+ */
178
+ build_ghes_hw_error_notification(table_data, ACPI_GHES_NOTIFY_SEA);
179
+ break;
180
+ default:
181
+ error_report("Not support this error source");
182
+ abort();
30
+ }
183
+ }
31
case 0x94: /* CONTROL_NS */
184
+
32
/* We have to handle this here because unprivileged Secure code
185
+ /* Error Status Block Length */
33
* can read the NS CONTROL register.
186
+ build_append_int_noprefix(table_data, ACPI_GHES_MAX_RAW_DATA_LENGTH, 4);
34
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(v7m_mrs)(CPUARMState *env, uint32_t reg)
187
+
35
if (!env->v7m.secure) {
188
+ /*
36
return 0;
189
+ * Read Ack Register
37
}
190
+ * ACPI 6.1: 18.3.2.8 Generic Hardware Error Source
38
- return env->v7m.control[M_REG_NS];
191
+ * version 2 (GHESv2 - Type 10)
39
+ return env->v7m.control[M_REG_NS] |
192
+ */
40
+ (env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK);
193
+ address_offset = table_data->len;
194
+ build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 0x40, 0,
195
+ 4 /* QWord access */, 0);
196
+ bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
197
+ address_offset + GAS_ADDR_OFFSET,
198
+ sizeof(uint64_t), ACPI_GHES_ERRORS_FW_CFG_FILE,
199
+ (ACPI_GHES_ERROR_SOURCE_COUNT + source_id) * sizeof(uint64_t));
200
+
201
+ /*
202
+ * Read Ack Preserve field
203
+ * We only provide the first bit in Read Ack Register to OSPM to write
204
+ * while the other bits are preserved.
205
+ */
206
+ build_append_int_noprefix(table_data, ~0x1ULL, 8);
207
+ /* Read Ack Write */
208
+ build_append_int_noprefix(table_data, 0x1, 8);
209
+}
210
+
211
+/* Build Hardware Error Source Table */
212
+void acpi_build_hest(GArray *table_data, BIOSLinker *linker)
213
+{
214
+ uint64_t hest_start = table_data->len;
215
+
216
+ /* Hardware Error Source Table header*/
217
+ acpi_data_push(table_data, sizeof(AcpiTableHeader));
218
+
219
+ /* Error Source Count */
220
+ build_append_int_noprefix(table_data, ACPI_GHES_ERROR_SOURCE_COUNT, 4);
221
+
222
+ build_ghes_v2(table_data, ACPI_HEST_SRC_ID_SEA, linker);
223
+
224
+ build_header(linker, table_data, (void *)(table_data->data + hest_start),
225
+ "HEST", table_data->len - hest_start, 1, NULL, NULL);
226
+}
227
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
228
index XXXXXXX..XXXXXXX 100644
229
--- a/hw/arm/virt-acpi-build.c
230
+++ b/hw/arm/virt-acpi-build.c
231
@@ -XXX,XX +XXX,XX @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
232
233
if (vms->ras) {
234
build_ghes_error_table(tables->hardware_errors, tables->linker);
235
+ acpi_add_table(table_offsets, tables_blob);
236
+ acpi_build_hest(tables_blob, tables->linker);
41
}
237
}
42
238
43
if (el == 0) {
239
if (ms->numa_state->num_nodes > 0) {
44
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
45
*/
46
uint32_t mask = extract32(maskreg, 8, 4);
47
uint32_t reg = extract32(maskreg, 0, 8);
48
+ int cur_el = arm_current_el(env);
49
50
- if (arm_current_el(env) == 0 && reg > 7) {
51
- /* only xPSR sub-fields may be written by unprivileged */
52
+ if (cur_el == 0 && reg > 7 && reg != 20) {
53
+ /*
54
+ * only xPSR sub-fields and CONTROL.SFPA may be written by
55
+ * unprivileged code
56
+ */
57
return;
58
}
59
60
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
61
env->v7m.control[M_REG_NS] &= ~R_V7M_CONTROL_NPRIV_MASK;
62
env->v7m.control[M_REG_NS] |= val & R_V7M_CONTROL_NPRIV_MASK;
63
}
64
+ /*
65
+ * SFPA is RAZ/WI from NS. FPCA is RO if NSACR.CP10 == 0,
66
+ * RES0 if the FPU is not present, and is stored in the S bank
67
+ */
68
+ if (arm_feature(env, ARM_FEATURE_VFP) &&
69
+ extract32(env->v7m.nsacr, 10, 1)) {
70
+ env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_FPCA_MASK;
71
+ env->v7m.control[M_REG_S] |= val & R_V7M_CONTROL_FPCA_MASK;
72
+ }
73
return;
74
case 0x98: /* SP_NS */
75
{
76
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_msr)(CPUARMState *env, uint32_t maskreg, uint32_t val)
77
env->v7m.faultmask[env->v7m.secure] = val & 1;
78
break;
79
case 20: /* CONTROL */
80
- /* Writing to the SPSEL bit only has an effect if we are in
81
+ /*
82
+ * Writing to the SPSEL bit only has an effect if we are in
83
* thread mode; other bits can be updated by any privileged code.
84
* write_v7m_control_spsel() deals with updating the SPSEL bit in
85
* env->v7m.control, so we only need update the others.
86
* For v7M, we must just ignore explicit writes to SPSEL in handler
87
* mode; for v8M the write is permitted but will have no effect.
88
+ * All these bits are writes-ignored from non-privileged code,
89
+ * except for SFPA.
90
*/
91
- if (arm_feature(env, ARM_FEATURE_V8) ||
92
- !arm_v7m_is_handler_mode(env)) {
93
+ if (cur_el > 0 && (arm_feature(env, ARM_FEATURE_V8) ||
94
+ !arm_v7m_is_handler_mode(env))) {
95
write_v7m_control_spsel(env, (val & R_V7M_CONTROL_SPSEL_MASK) != 0);
96
}
97
- if (arm_feature(env, ARM_FEATURE_M_MAIN)) {
98
+ if (cur_el > 0 && arm_feature(env, ARM_FEATURE_M_MAIN)) {
99
env->v7m.control[env->v7m.secure] &= ~R_V7M_CONTROL_NPRIV_MASK;
100
env->v7m.control[env->v7m.secure] |= val & R_V7M_CONTROL_NPRIV_MASK;
101
}
102
+ if (arm_feature(env, ARM_FEATURE_VFP)) {
103
+ /*
104
+ * SFPA is RAZ/WI from NS or if no FPU.
105
+ * FPCA is RO if NSACR.CP10 == 0, RES0 if the FPU is not present.
106
+ * Both are stored in the S bank.
107
+ */
108
+ if (env->v7m.secure) {
109
+ env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
110
+ env->v7m.control[M_REG_S] |= val & R_V7M_CONTROL_SFPA_MASK;
111
+ }
112
+ if (cur_el > 0 &&
113
+ (env->v7m.secure || !arm_feature(env, ARM_FEATURE_M_SECURITY) ||
114
+ extract32(env->v7m.nsacr, 10, 1))) {
115
+ env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_FPCA_MASK;
116
+ env->v7m.control[M_REG_S] |= val & R_V7M_CONTROL_FPCA_MASK;
117
+ }
118
+ }
119
break;
120
default:
121
bad_reg:
122
--
240
--
123
2.20.1
241
2.20.1
124
242
125
243
diff view generated by jsdifflib
1
The M-profile floating point support has three associated config
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
2
registers: FPCAR, FPCCR and FPDSCR. It also makes the registers
3
CPACR and NSACR have behaviour other than reads-as-zero.
4
Add support for all of these as simple reads-as-written registers.
5
We will hook up actual functionality later.
6
2
7
The main complexity here is handling the FPCCR register, which
3
Record the GHEB address via fw_cfg file, when recording
8
has a mix of banked and unbanked bits.
4
a error to CPER, it will use this address to find out
5
Generic Error Data Entries and write the error.
9
6
10
Note that we don't share storage with the A-profile
7
In order to avoid migration failure, make hardware
11
cpu->cp15.nsacr and cpu->cp15.cpacr_el1, though the behaviour
8
error table address to a part of GED device instead
12
is quite similar, for two reasons:
9
of global variable, then this address will be migrated
13
* the M profile CPACR is banked between security states
10
to target QEMU.
14
* it preserves the invariant that M profile uses no state
15
inside the cp15 substruct
16
11
12
Acked-by: Xiang Zheng <zhengxiang9@huawei.com>
13
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
14
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
15
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
16
Message-id: 20200512030609.19593-7-gengdongjiu@huawei.com
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Message-id: 20190416125744.27770-4-peter.maydell@linaro.org
20
---
18
---
21
target/arm/cpu.h | 34 ++++++++++++
19
include/hw/acpi/generic_event_device.h | 2 ++
22
hw/intc/armv7m_nvic.c | 125 ++++++++++++++++++++++++++++++++++++++++++
20
include/hw/acpi/ghes.h | 6 ++++++
23
target/arm/cpu.c | 5 ++
21
hw/acpi/generic_event_device.c | 19 +++++++++++++++++++
24
target/arm/machine.c | 16 ++++++
22
hw/acpi/ghes.c | 14 ++++++++++++++
25
4 files changed, 180 insertions(+)
23
hw/arm/virt-acpi-build.c | 8 ++++++++
24
5 files changed, 49 insertions(+)
26
25
27
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
26
diff --git a/include/hw/acpi/generic_event_device.h b/include/hw/acpi/generic_event_device.h
28
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/cpu.h
28
--- a/include/hw/acpi/generic_event_device.h
30
+++ b/target/arm/cpu.h
29
+++ b/include/hw/acpi/generic_event_device.h
31
@@ -XXX,XX +XXX,XX @@ typedef struct CPUARMState {
30
@@ -XXX,XX +XXX,XX @@
32
uint32_t scr[M_REG_NUM_BANKS];
31
33
uint32_t msplim[M_REG_NUM_BANKS];
32
#include "hw/sysbus.h"
34
uint32_t psplim[M_REG_NUM_BANKS];
33
#include "hw/acpi/memory_hotplug.h"
35
+ uint32_t fpcar[M_REG_NUM_BANKS];
34
+#include "hw/acpi/ghes.h"
36
+ uint32_t fpccr[M_REG_NUM_BANKS];
35
37
+ uint32_t fpdscr[M_REG_NUM_BANKS];
36
#define ACPI_POWER_BUTTON_DEVICE "PWRB"
38
+ uint32_t cpacr[M_REG_NUM_BANKS];
37
39
+ uint32_t nsacr;
38
@@ -XXX,XX +XXX,XX @@ typedef struct AcpiGedState {
40
} v7m;
39
GEDState ged_state;
41
40
uint32_t ged_event_bitmap;
42
/* Information associated with an exception about to be taken:
41
qemu_irq irq;
43
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_CSSELR, LEVEL, 1, 3)
42
+ AcpiGhesState ghes_state;
44
*/
43
} AcpiGedState;
45
FIELD(V7M_CSSELR, INDEX, 0, 4)
44
46
45
void build_ged_aml(Aml *table, const char* name, HotplugHandler *hotplug_dev,
47
+/* v7M FPCCR bits */
46
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
48
+FIELD(V7M_FPCCR, LSPACT, 0, 1)
47
index XXXXXXX..XXXXXXX 100644
49
+FIELD(V7M_FPCCR, USER, 1, 1)
48
--- a/include/hw/acpi/ghes.h
50
+FIELD(V7M_FPCCR, S, 2, 1)
49
+++ b/include/hw/acpi/ghes.h
51
+FIELD(V7M_FPCCR, THREAD, 3, 1)
50
@@ -XXX,XX +XXX,XX @@ enum {
52
+FIELD(V7M_FPCCR, HFRDY, 4, 1)
51
ACPI_HEST_SRC_ID_RESERVED,
53
+FIELD(V7M_FPCCR, MMRDY, 5, 1)
52
};
54
+FIELD(V7M_FPCCR, BFRDY, 6, 1)
53
55
+FIELD(V7M_FPCCR, SFRDY, 7, 1)
54
+typedef struct AcpiGhesState {
56
+FIELD(V7M_FPCCR, MONRDY, 8, 1)
55
+ uint64_t ghes_addr_le;
57
+FIELD(V7M_FPCCR, SPLIMVIOL, 9, 1)
56
+} AcpiGhesState;
58
+FIELD(V7M_FPCCR, UFRDY, 10, 1)
59
+FIELD(V7M_FPCCR, RES0, 11, 15)
60
+FIELD(V7M_FPCCR, TS, 26, 1)
61
+FIELD(V7M_FPCCR, CLRONRETS, 27, 1)
62
+FIELD(V7M_FPCCR, CLRONRET, 28, 1)
63
+FIELD(V7M_FPCCR, LSPENS, 29, 1)
64
+FIELD(V7M_FPCCR, LSPEN, 30, 1)
65
+FIELD(V7M_FPCCR, ASPEN, 31, 1)
66
+/* These bits are banked. Others are non-banked and live in the M_REG_S bank */
67
+#define R_V7M_FPCCR_BANKED_MASK \
68
+ (R_V7M_FPCCR_LSPACT_MASK | \
69
+ R_V7M_FPCCR_USER_MASK | \
70
+ R_V7M_FPCCR_THREAD_MASK | \
71
+ R_V7M_FPCCR_MMRDY_MASK | \
72
+ R_V7M_FPCCR_SPLIMVIOL_MASK | \
73
+ R_V7M_FPCCR_UFRDY_MASK | \
74
+ R_V7M_FPCCR_ASPEN_MASK)
75
+
57
+
76
/*
58
void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker);
77
* System register ID fields.
59
void acpi_build_hest(GArray *table_data, BIOSLinker *linker);
78
*/
60
+void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s,
79
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
61
+ GArray *hardware_errors);
62
#endif
63
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
80
index XXXXXXX..XXXXXXX 100644
64
index XXXXXXX..XXXXXXX 100644
81
--- a/hw/intc/armv7m_nvic.c
65
--- a/hw/acpi/generic_event_device.c
82
+++ b/hw/intc/armv7m_nvic.c
66
+++ b/hw/acpi/generic_event_device.c
83
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
67
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_ged_state = {
84
}
85
case 0xd84: /* CSSELR */
86
return cpu->env.v7m.csselr[attrs.secure];
87
+ case 0xd88: /* CPACR */
88
+ if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
89
+ return 0;
90
+ }
91
+ return cpu->env.v7m.cpacr[attrs.secure];
92
+ case 0xd8c: /* NSACR */
93
+ if (!attrs.secure || !arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
94
+ return 0;
95
+ }
96
+ return cpu->env.v7m.nsacr;
97
/* TODO: Implement debug registers. */
98
case 0xd90: /* MPU_TYPE */
99
/* Unified MPU; if the MPU is not present this value is zero */
100
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
101
return 0;
102
}
103
return cpu->env.v7m.sfar;
104
+ case 0xf34: /* FPCCR */
105
+ if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
106
+ return 0;
107
+ }
108
+ if (attrs.secure) {
109
+ return cpu->env.v7m.fpccr[M_REG_S];
110
+ } else {
111
+ /*
112
+ * NS can read LSPEN, CLRONRET and MONRDY. It can read
113
+ * BFRDY and HFRDY if AIRCR.BFHFNMINS != 0;
114
+ * other non-banked bits RAZ.
115
+ * TODO: MONRDY should RAZ/WI if DEMCR.SDME is set.
116
+ */
117
+ uint32_t value = cpu->env.v7m.fpccr[M_REG_S];
118
+ uint32_t mask = R_V7M_FPCCR_LSPEN_MASK |
119
+ R_V7M_FPCCR_CLRONRET_MASK |
120
+ R_V7M_FPCCR_MONRDY_MASK;
121
+
122
+ if (s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK) {
123
+ mask |= R_V7M_FPCCR_BFRDY_MASK | R_V7M_FPCCR_HFRDY_MASK;
124
+ }
125
+
126
+ value &= mask;
127
+
128
+ value |= cpu->env.v7m.fpccr[M_REG_NS];
129
+ return value;
130
+ }
131
+ case 0xf38: /* FPCAR */
132
+ if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
133
+ return 0;
134
+ }
135
+ return cpu->env.v7m.fpcar[attrs.secure];
136
+ case 0xf3c: /* FPDSCR */
137
+ if (!arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
138
+ return 0;
139
+ }
140
+ return cpu->env.v7m.fpdscr[attrs.secure];
141
case 0xf40: /* MVFR0 */
142
return cpu->isar.mvfr0;
143
case 0xf44: /* MVFR1 */
144
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
145
cpu->env.v7m.csselr[attrs.secure] = value & R_V7M_CSSELR_INDEX_MASK;
146
}
147
break;
148
+ case 0xd88: /* CPACR */
149
+ if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
150
+ /* We implement only the Floating Point extension's CP10/CP11 */
151
+ cpu->env.v7m.cpacr[attrs.secure] = value & (0xf << 20);
152
+ }
153
+ break;
154
+ case 0xd8c: /* NSACR */
155
+ if (attrs.secure && arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
156
+ /* We implement only the Floating Point extension's CP10/CP11 */
157
+ cpu->env.v7m.nsacr = value & (3 << 10);
158
+ }
159
+ break;
160
case 0xd90: /* MPU_TYPE */
161
return; /* RO */
162
case 0xd94: /* MPU_CTRL */
163
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
164
}
165
break;
166
}
167
+ case 0xf34: /* FPCCR */
168
+ if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
169
+ /* Not all bits here are banked. */
170
+ uint32_t fpccr_s;
171
+
172
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8)) {
173
+ /* Don't allow setting of bits not present in v7M */
174
+ value &= (R_V7M_FPCCR_LSPACT_MASK |
175
+ R_V7M_FPCCR_USER_MASK |
176
+ R_V7M_FPCCR_THREAD_MASK |
177
+ R_V7M_FPCCR_HFRDY_MASK |
178
+ R_V7M_FPCCR_MMRDY_MASK |
179
+ R_V7M_FPCCR_BFRDY_MASK |
180
+ R_V7M_FPCCR_MONRDY_MASK |
181
+ R_V7M_FPCCR_LSPEN_MASK |
182
+ R_V7M_FPCCR_ASPEN_MASK);
183
+ }
184
+ value &= ~R_V7M_FPCCR_RES0_MASK;
185
+
186
+ if (!attrs.secure) {
187
+ /* Some non-banked bits are configurably writable by NS */
188
+ fpccr_s = cpu->env.v7m.fpccr[M_REG_S];
189
+ if (!(fpccr_s & R_V7M_FPCCR_LSPENS_MASK)) {
190
+ uint32_t lspen = FIELD_EX32(value, V7M_FPCCR, LSPEN);
191
+ fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, LSPEN, lspen);
192
+ }
193
+ if (!(fpccr_s & R_V7M_FPCCR_CLRONRETS_MASK)) {
194
+ uint32_t cor = FIELD_EX32(value, V7M_FPCCR, CLRONRET);
195
+ fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, CLRONRET, cor);
196
+ }
197
+ if ((s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
198
+ uint32_t hfrdy = FIELD_EX32(value, V7M_FPCCR, HFRDY);
199
+ uint32_t bfrdy = FIELD_EX32(value, V7M_FPCCR, BFRDY);
200
+ fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, HFRDY, hfrdy);
201
+ fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, BFRDY, bfrdy);
202
+ }
203
+ /* TODO MONRDY should RAZ/WI if DEMCR.SDME is set */
204
+ {
205
+ uint32_t monrdy = FIELD_EX32(value, V7M_FPCCR, MONRDY);
206
+ fpccr_s = FIELD_DP32(fpccr_s, V7M_FPCCR, MONRDY, monrdy);
207
+ }
208
+
209
+ /*
210
+ * All other non-banked bits are RAZ/WI from NS; write
211
+ * just the banked bits to fpccr[M_REG_NS].
212
+ */
213
+ value &= R_V7M_FPCCR_BANKED_MASK;
214
+ cpu->env.v7m.fpccr[M_REG_NS] = value;
215
+ } else {
216
+ fpccr_s = value;
217
+ }
218
+ cpu->env.v7m.fpccr[M_REG_S] = fpccr_s;
219
+ }
220
+ break;
221
+ case 0xf38: /* FPCAR */
222
+ if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
223
+ value &= ~7;
224
+ cpu->env.v7m.fpcar[attrs.secure] = value;
225
+ }
226
+ break;
227
+ case 0xf3c: /* FPDSCR */
228
+ if (arm_feature(&cpu->env, ARM_FEATURE_VFP)) {
229
+ value &= 0x07c00000;
230
+ cpu->env.v7m.fpdscr[attrs.secure] = value;
231
+ }
232
+ break;
233
case 0xf50: /* ICIALLU */
234
case 0xf58: /* ICIMVAU */
235
case 0xf5c: /* DCIMVAC */
236
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
237
index XXXXXXX..XXXXXXX 100644
238
--- a/target/arm/cpu.c
239
+++ b/target/arm/cpu.c
240
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(CPUState *s)
241
env->v7m.ccr[M_REG_S] |= R_V7M_CCR_UNALIGN_TRP_MASK;
242
}
243
244
+ if (arm_feature(env, ARM_FEATURE_VFP)) {
245
+ env->v7m.fpccr[M_REG_NS] = R_V7M_FPCCR_ASPEN_MASK;
246
+ env->v7m.fpccr[M_REG_S] = R_V7M_FPCCR_ASPEN_MASK |
247
+ R_V7M_FPCCR_LSPEN_MASK | R_V7M_FPCCR_S_MASK;
248
+ }
249
/* Unlike A/R profile, M profile defines the reset LR value */
250
env->regs[14] = 0xffffffff;
251
252
diff --git a/target/arm/machine.c b/target/arm/machine.c
253
index XXXXXXX..XXXXXXX 100644
254
--- a/target/arm/machine.c
255
+++ b/target/arm/machine.c
256
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m_v8m = {
257
}
68
}
258
};
69
};
259
70
260
+static const VMStateDescription vmstate_m_fp = {
71
+static bool ghes_needed(void *opaque)
261
+ .name = "cpu/m/fp",
72
+{
73
+ AcpiGedState *s = opaque;
74
+ return s->ghes_state.ghes_addr_le;
75
+}
76
+
77
+static const VMStateDescription vmstate_ghes_state = {
78
+ .name = "acpi-ged/ghes",
262
+ .version_id = 1,
79
+ .version_id = 1,
263
+ .minimum_version_id = 1,
80
+ .minimum_version_id = 1,
264
+ .needed = vfp_needed,
81
+ .needed = ghes_needed,
265
+ .fields = (VMStateField[]) {
82
+ .fields = (VMStateField[]) {
266
+ VMSTATE_UINT32_ARRAY(env.v7m.fpcar, ARMCPU, M_REG_NUM_BANKS),
83
+ VMSTATE_STRUCT(ghes_state, AcpiGedState, 1,
267
+ VMSTATE_UINT32_ARRAY(env.v7m.fpccr, ARMCPU, M_REG_NUM_BANKS),
84
+ vmstate_ghes_state, AcpiGhesState),
268
+ VMSTATE_UINT32_ARRAY(env.v7m.fpdscr, ARMCPU, M_REG_NUM_BANKS),
269
+ VMSTATE_UINT32_ARRAY(env.v7m.cpacr, ARMCPU, M_REG_NUM_BANKS),
270
+ VMSTATE_UINT32(env.v7m.nsacr, ARMCPU),
271
+ VMSTATE_END_OF_LIST()
85
+ VMSTATE_END_OF_LIST()
272
+ }
86
+ }
273
+};
87
+};
274
+
88
+
275
static const VMStateDescription vmstate_m = {
89
static const VMStateDescription vmstate_acpi_ged = {
276
.name = "cpu/m",
90
.name = "acpi-ged",
277
.version_id = 4,
91
.version_id = 1,
278
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_m = {
92
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_acpi_ged = {
279
&vmstate_m_scr,
93
},
280
&vmstate_m_other_sp,
94
.subsections = (const VMStateDescription * []) {
281
&vmstate_m_v8m,
95
&vmstate_memhp_state,
282
+ &vmstate_m_fp,
96
+ &vmstate_ghes_state,
283
NULL
97
NULL
284
}
98
}
285
};
99
};
100
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
101
index XXXXXXX..XXXXXXX 100644
102
--- a/hw/acpi/ghes.c
103
+++ b/hw/acpi/ghes.c
104
@@ -XXX,XX +XXX,XX @@
105
#include "hw/acpi/ghes.h"
106
#include "hw/acpi/aml-build.h"
107
#include "qemu/error-report.h"
108
+#include "hw/acpi/generic_event_device.h"
109
+#include "hw/nvram/fw_cfg.h"
110
111
#define ACPI_GHES_ERRORS_FW_CFG_FILE "etc/hardware_errors"
112
#define ACPI_GHES_DATA_ADDR_FW_CFG_FILE "etc/hardware_errors_addr"
113
@@ -XXX,XX +XXX,XX @@ void acpi_build_hest(GArray *table_data, BIOSLinker *linker)
114
build_header(linker, table_data, (void *)(table_data->data + hest_start),
115
"HEST", table_data->len - hest_start, 1, NULL, NULL);
116
}
117
+
118
+void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s,
119
+ GArray *hardware_error)
120
+{
121
+ /* Create a read-only fw_cfg file for GHES */
122
+ fw_cfg_add_file(s, ACPI_GHES_ERRORS_FW_CFG_FILE, hardware_error->data,
123
+ hardware_error->len);
124
+
125
+ /* Create a read-write fw_cfg file for Address */
126
+ fw_cfg_add_file_callback(s, ACPI_GHES_DATA_ADDR_FW_CFG_FILE, NULL, NULL,
127
+ NULL, &(ags->ghes_addr_le), sizeof(ags->ghes_addr_le), false);
128
+}
129
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/hw/arm/virt-acpi-build.c
132
+++ b/hw/arm/virt-acpi-build.c
133
@@ -XXX,XX +XXX,XX @@ void virt_acpi_setup(VirtMachineState *vms)
134
{
135
AcpiBuildTables tables;
136
AcpiBuildState *build_state;
137
+ AcpiGedState *acpi_ged_state;
138
139
if (!vms->fw_cfg) {
140
trace_virt_acpi_setup();
141
@@ -XXX,XX +XXX,XX @@ void virt_acpi_setup(VirtMachineState *vms)
142
fw_cfg_add_file(vms->fw_cfg, ACPI_BUILD_TPMLOG_FILE, tables.tcpalog->data,
143
acpi_data_len(tables.tcpalog));
144
145
+ if (vms->ras) {
146
+ assert(vms->acpi_dev);
147
+ acpi_ged_state = ACPI_GED(vms->acpi_dev);
148
+ acpi_ghes_add_fw_cfg(&acpi_ged_state->ghes_state,
149
+ vms->fw_cfg, tables.hardware_errors);
150
+ }
151
+
152
build_state->rsdp_mr = acpi_add_rom_blob(virt_acpi_build_update,
153
build_state, tables.rsdp,
154
ACPI_BUILD_RSDP_FILE, 0);
286
--
155
--
287
2.20.1
156
2.20.1
288
157
289
158
diff view generated by jsdifflib
1
From: Eric Auger <eric.auger@redhat.com>
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
2
2
3
The SMMUNotifierNode struct is not necessary and brings extra
3
kvm_hwpoison_page_add() and kvm_unpoison_all() will both
4
complexity so let's remove it. We now directly track the SMMUDevices
4
be used by X86 and ARM platforms, so moving them into
5
which have registered IOMMU MR notifiers.
5
"accel/kvm/kvm-all.c" to avoid duplicate code.
6
6
7
This is inspired from the same transformation on intel-iommu
7
For architectures that don't use the poison-list functionality
8
done in commit b4a4ba0d68f50f218ee3957b6638dbee32a5eeef
8
the reset handler will harmlessly do nothing, so let's register
9
("intel-iommu: remove IntelIOMMUNotifierNode")
9
the kvm_unpoison_all() function in the generic kvm_init() function.
10
10
11
Signed-off-by: Eric Auger <eric.auger@redhat.com>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Peter Xu <peterx@redhat.com>
12
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
13
Message-id: 20190409160219.19026-1-eric.auger@redhat.com
13
Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
14
Acked-by: Xiang Zheng <zhengxiang9@huawei.com>
15
Message-id: 20200512030609.19593-8-gengdongjiu@huawei.com
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
17
---
16
include/hw/arm/smmu-common.h | 8 ++------
18
include/sysemu/kvm_int.h | 12 ++++++++++++
17
hw/arm/smmu-common.c | 6 +++---
19
accel/kvm/kvm-all.c | 36 ++++++++++++++++++++++++++++++++++++
18
hw/arm/smmuv3.c | 28 +++++++---------------------
20
target/i386/kvm.c | 36 ------------------------------------
19
3 files changed, 12 insertions(+), 30 deletions(-)
21
3 files changed, 48 insertions(+), 36 deletions(-)
20
22
21
diff --git a/include/hw/arm/smmu-common.h b/include/hw/arm/smmu-common.h
23
diff --git a/include/sysemu/kvm_int.h b/include/sysemu/kvm_int.h
22
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/arm/smmu-common.h
25
--- a/include/sysemu/kvm_int.h
24
+++ b/include/hw/arm/smmu-common.h
26
+++ b/include/sysemu/kvm_int.h
25
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUDevice {
27
@@ -XXX,XX +XXX,XX @@ void kvm_memory_listener_register(KVMState *s, KVMMemoryListener *kml,
26
AddressSpace as;
28
AddressSpace *as, int as_id);
27
uint32_t cfg_cache_hits;
29
28
uint32_t cfg_cache_misses;
30
void kvm_set_max_memslot_size(hwaddr max_slot_size);
29
+ QLIST_ENTRY(SMMUDevice) next;
31
+
30
} SMMUDevice;
32
+/**
31
33
+ * kvm_hwpoison_page_add:
32
-typedef struct SMMUNotifierNode {
34
+ *
33
- SMMUDevice *sdev;
35
+ * Parameters:
34
- QLIST_ENTRY(SMMUNotifierNode) next;
36
+ * @ram_addr: the address in the RAM for the poisoned page
35
-} SMMUNotifierNode;
37
+ *
36
-
38
+ * Add a poisoned page to the list
37
typedef struct SMMUPciBus {
39
+ *
38
PCIBus *bus;
40
+ * Return: None.
39
SMMUDevice *pbdev[0]; /* Parent array is sparse, so dynamically alloc */
41
+ */
40
@@ -XXX,XX +XXX,XX @@ typedef struct SMMUState {
42
+void kvm_hwpoison_page_add(ram_addr_t ram_addr);
41
GHashTable *iotlb;
43
#endif
42
SMMUPciBus *smmu_pcibus_by_bus_num[SMMU_PCI_BUS_MAX];
44
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
43
PCIBus *pci_bus;
44
- QLIST_HEAD(, SMMUNotifierNode) notifiers_list;
45
+ QLIST_HEAD(, SMMUDevice) devices_with_notifiers;
46
uint8_t bus_num;
47
PCIBus *primary_bus;
48
} SMMUState;
49
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
50
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/arm/smmu-common.c
46
--- a/accel/kvm/kvm-all.c
52
+++ b/hw/arm/smmu-common.c
47
+++ b/accel/kvm/kvm-all.c
53
@@ -XXX,XX +XXX,XX @@ inline void smmu_inv_notifiers_mr(IOMMUMemoryRegion *mr)
48
@@ -XXX,XX +XXX,XX @@
54
/* Unmap all notifiers of all mr's */
49
#include "qapi/visitor.h"
55
void smmu_inv_notifiers_all(SMMUState *s)
50
#include "qapi/qapi-types-common.h"
51
#include "qapi/qapi-visit-common.h"
52
+#include "sysemu/reset.h"
53
54
#include "hw/boards.h"
55
56
@@ -XXX,XX +XXX,XX @@ int kvm_vm_check_extension(KVMState *s, unsigned int extension)
57
return ret;
58
}
59
60
+typedef struct HWPoisonPage {
61
+ ram_addr_t ram_addr;
62
+ QLIST_ENTRY(HWPoisonPage) list;
63
+} HWPoisonPage;
64
+
65
+static QLIST_HEAD(, HWPoisonPage) hwpoison_page_list =
66
+ QLIST_HEAD_INITIALIZER(hwpoison_page_list);
67
+
68
+static void kvm_unpoison_all(void *param)
69
+{
70
+ HWPoisonPage *page, *next_page;
71
+
72
+ QLIST_FOREACH_SAFE(page, &hwpoison_page_list, list, next_page) {
73
+ QLIST_REMOVE(page, list);
74
+ qemu_ram_remap(page->ram_addr, TARGET_PAGE_SIZE);
75
+ g_free(page);
76
+ }
77
+}
78
+
79
+void kvm_hwpoison_page_add(ram_addr_t ram_addr)
80
+{
81
+ HWPoisonPage *page;
82
+
83
+ QLIST_FOREACH(page, &hwpoison_page_list, list) {
84
+ if (page->ram_addr == ram_addr) {
85
+ return;
86
+ }
87
+ }
88
+ page = g_new(HWPoisonPage, 1);
89
+ page->ram_addr = ram_addr;
90
+ QLIST_INSERT_HEAD(&hwpoison_page_list, page, list);
91
+}
92
+
93
static uint32_t adjust_ioeventfd_endianness(uint32_t val, uint32_t size)
56
{
94
{
57
- SMMUNotifierNode *node;
95
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
58
+ SMMUDevice *sdev;
96
@@ -XXX,XX +XXX,XX @@ static int kvm_init(MachineState *ms)
59
97
s->kernel_irqchip_split = mc->default_kernel_irqchip_split ? ON_OFF_AUTO_ON : ON_OFF_AUTO_OFF;
60
- QLIST_FOREACH(node, &s->notifiers_list, next) {
98
}
61
- smmu_inv_notifiers_mr(&node->sdev->iommu);
99
62
+ QLIST_FOREACH(sdev, &s->devices_with_notifiers, next) {
100
+ qemu_register_reset(kvm_unpoison_all, NULL);
63
+ smmu_inv_notifiers_mr(&sdev->iommu);
101
+
102
if (s->kernel_irqchip_allowed) {
103
kvm_irqchip_create(s);
104
}
105
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/target/i386/kvm.c
108
+++ b/target/i386/kvm.c
109
@@ -XXX,XX +XXX,XX @@
110
#include "sysemu/sysemu.h"
111
#include "sysemu/hw_accel.h"
112
#include "sysemu/kvm_int.h"
113
-#include "sysemu/reset.h"
114
#include "sysemu/runstate.h"
115
#include "kvm_i386.h"
116
#include "hyperv.h"
117
@@ -XXX,XX +XXX,XX @@ uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index)
64
}
118
}
65
}
119
}
66
120
67
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
121
-
68
index XXXXXXX..XXXXXXX 100644
122
-typedef struct HWPoisonPage {
69
--- a/hw/arm/smmuv3.c
123
- ram_addr_t ram_addr;
70
+++ b/hw/arm/smmuv3.c
124
- QLIST_ENTRY(HWPoisonPage) list;
71
@@ -XXX,XX +XXX,XX @@ static void smmuv3_notify_iova(IOMMUMemoryRegion *mr,
125
-} HWPoisonPage;
72
/* invalidate an asid/iova tuple in all mr's */
126
-
73
static void smmuv3_inv_notifiers_iova(SMMUState *s, int asid, dma_addr_t iova)
127
-static QLIST_HEAD(, HWPoisonPage) hwpoison_page_list =
74
{
128
- QLIST_HEAD_INITIALIZER(hwpoison_page_list);
75
- SMMUNotifierNode *node;
129
-
76
+ SMMUDevice *sdev;
130
-static void kvm_unpoison_all(void *param)
77
131
-{
78
- QLIST_FOREACH(node, &s->notifiers_list, next) {
132
- HWPoisonPage *page, *next_page;
79
- IOMMUMemoryRegion *mr = &node->sdev->iommu;
133
-
80
+ QLIST_FOREACH(sdev, &s->devices_with_notifiers, next) {
134
- QLIST_FOREACH_SAFE(page, &hwpoison_page_list, list, next_page) {
81
+ IOMMUMemoryRegion *mr = &sdev->iommu;
135
- QLIST_REMOVE(page, list);
82
IOMMUNotifier *n;
136
- qemu_ram_remap(page->ram_addr, TARGET_PAGE_SIZE);
83
137
- g_free(page);
84
trace_smmuv3_inv_notifiers_iova(mr->parent_obj.name, asid, iova);
85
@@ -XXX,XX +XXX,XX @@ static void smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu,
86
SMMUDevice *sdev = container_of(iommu, SMMUDevice, iommu);
87
SMMUv3State *s3 = sdev->smmu;
88
SMMUState *s = &(s3->smmu_state);
89
- SMMUNotifierNode *node = NULL;
90
- SMMUNotifierNode *next_node = NULL;
91
92
if (new & IOMMU_NOTIFIER_MAP) {
93
int bus_num = pci_bus_num(sdev->bus);
94
@@ -XXX,XX +XXX,XX @@ static void smmuv3_notify_flag_changed(IOMMUMemoryRegion *iommu,
95
96
if (old == IOMMU_NOTIFIER_NONE) {
97
trace_smmuv3_notify_flag_add(iommu->parent_obj.name);
98
- node = g_malloc0(sizeof(*node));
99
- node->sdev = sdev;
100
- QLIST_INSERT_HEAD(&s->notifiers_list, node, next);
101
- return;
102
- }
138
- }
139
-}
103
-
140
-
104
- /* update notifier node with new flags */
141
-static void kvm_hwpoison_page_add(ram_addr_t ram_addr)
105
- QLIST_FOREACH_SAFE(node, &s->notifiers_list, next, next_node) {
142
-{
106
- if (node->sdev == sdev) {
143
- HWPoisonPage *page;
107
- if (new == IOMMU_NOTIFIER_NONE) {
144
-
108
- trace_smmuv3_notify_flag_del(iommu->parent_obj.name);
145
- QLIST_FOREACH(page, &hwpoison_page_list, list) {
109
- QLIST_REMOVE(node, next);
146
- if (page->ram_addr == ram_addr) {
110
- g_free(node);
111
- }
112
- return;
147
- return;
113
- }
148
- }
114
+ QLIST_INSERT_HEAD(&s->devices_with_notifiers, sdev, next);
149
- }
115
+ } else if (new == IOMMU_NOTIFIER_NONE) {
150
- page = g_new(HWPoisonPage, 1);
116
+ trace_smmuv3_notify_flag_del(iommu->parent_obj.name);
151
- page->ram_addr = ram_addr;
117
+ QLIST_REMOVE(sdev, next);
152
- QLIST_INSERT_HEAD(&hwpoison_page_list, page, list);
153
-}
154
-
155
static int kvm_get_mce_cap_supported(KVMState *s, uint64_t *mce_cap,
156
int *max_banks)
157
{
158
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init(MachineState *ms, KVMState *s)
159
fprintf(stderr, "e820_add_entry() table is full\n");
160
return ret;
118
}
161
}
119
}
162
- qemu_register_reset(kvm_unpoison_all, NULL);
120
163
164
shadow_mem = object_property_get_int(OBJECT(s), "kvm-shadow-mem", &error_abort);
165
if (shadow_mem != -1) {
121
--
166
--
122
2.20.1
167
2.20.1
123
168
124
169
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
2
2
3
Reviewed-by: Markus Armbruster <armbru@redhat.com>
3
kvm_arch_on_sigbus_vcpu() error injection uses source_id as
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
4
index in etc/hardware_errors to find out Error Status Data
5
Message-id: 20190412165416.7977-10-philmd@redhat.com
5
Block entry corresponding to error source. So supported source_id
6
values should be assigned here and not be changed afterwards to
7
make sure that guest will write error into expected Error Status
8
Data Block.
9
10
Before QEMU writes a new error to ACPI table, it will check whether
11
previous error has been acknowledged. If not acknowledged, the new
12
errors will be ignored and not be recorded. For the errors section
13
type, QEMU simulate it to memory section error.
14
15
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
16
Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
17
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
18
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
19
Message-id: 20200512030609.19593-9-gengdongjiu@huawei.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
21
---
8
include/hw/devices.h | 3 ---
22
include/hw/acpi/ghes.h | 1 +
9
include/hw/net/lan9118.h | 19 +++++++++++++++++++
23
hw/acpi/ghes.c | 219 +++++++++++++++++++++++++++++++++++++++++
10
hw/arm/kzm.c | 2 +-
24
2 files changed, 220 insertions(+)
11
hw/arm/mps2.c | 2 +-
25
12
hw/arm/realview.c | 1 +
26
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
13
hw/arm/vexpress.c | 2 +-
14
hw/net/lan9118.c | 2 +-
15
7 files changed, 24 insertions(+), 7 deletions(-)
16
create mode 100644 include/hw/net/lan9118.h
17
18
diff --git a/include/hw/devices.h b/include/hw/devices.h
19
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/devices.h
28
--- a/include/hw/acpi/ghes.h
21
+++ b/include/hw/devices.h
29
+++ b/include/hw/acpi/ghes.h
22
@@ -XXX,XX +XXX,XX @@
30
@@ -XXX,XX +XXX,XX @@ void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker);
23
/* smc91c111.c */
31
void acpi_build_hest(GArray *table_data, BIOSLinker *linker);
24
void smc91c111_init(NICInfo *, uint32_t, qemu_irq);
32
void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s,
25
33
GArray *hardware_errors);
26
-/* lan9118.c */
34
+int acpi_ghes_record_errors(uint8_t notify, uint64_t error_physical_addr);
27
-void lan9118_init(NICInfo *, uint32_t, qemu_irq);
28
-
29
#endif
35
#endif
30
diff --git a/include/hw/net/lan9118.h b/include/hw/net/lan9118.h
36
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
31
new file mode 100644
32
index XXXXXXX..XXXXXXX
33
--- /dev/null
34
+++ b/include/hw/net/lan9118.h
35
@@ -XXX,XX +XXX,XX @@
36
+/*
37
+ * SMSC LAN9118 Ethernet interface emulation
38
+ *
39
+ * Copyright (c) 2009 CodeSourcery, LLC.
40
+ * Written by Paul Brook
41
+ *
42
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
43
+ * See the COPYING file in the top-level directory.
44
+ */
45
+
46
+#ifndef HW_NET_LAN9118_H
47
+#define HW_NET_LAN9118_H
48
+
49
+#include "hw/irq.h"
50
+#include "net/net.h"
51
+
52
+void lan9118_init(NICInfo *, uint32_t, qemu_irq);
53
+
54
+#endif
55
diff --git a/hw/arm/kzm.c b/hw/arm/kzm.c
56
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
57
--- a/hw/arm/kzm.c
38
--- a/hw/acpi/ghes.c
58
+++ b/hw/arm/kzm.c
39
+++ b/hw/acpi/ghes.c
59
@@ -XXX,XX +XXX,XX @@
40
@@ -XXX,XX +XXX,XX @@
60
#include "qemu/error-report.h"
41
#include "qemu/error-report.h"
61
#include "exec/address-spaces.h"
42
#include "hw/acpi/generic_event_device.h"
62
#include "net/net.h"
43
#include "hw/nvram/fw_cfg.h"
63
-#include "hw/devices.h"
44
+#include "qemu/uuid.h"
64
+#include "hw/net/lan9118.h"
45
65
#include "hw/char/serial.h"
46
#define ACPI_GHES_ERRORS_FW_CFG_FILE "etc/hardware_errors"
66
#include "sysemu/qtest.h"
47
#define ACPI_GHES_DATA_ADDR_FW_CFG_FILE "etc/hardware_errors_addr"
67
68
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/hw/arm/mps2.c
71
+++ b/hw/arm/mps2.c
72
@@ -XXX,XX +XXX,XX @@
48
@@ -XXX,XX +XXX,XX @@
73
#include "hw/timer/cmsdk-apb-timer.h"
49
/* Address offset in Generic Address Structure(GAS) */
74
#include "hw/timer/cmsdk-apb-dualtimer.h"
50
#define GAS_ADDR_OFFSET 4
75
#include "hw/misc/mps2-scc.h"
51
76
-#include "hw/devices.h"
52
+/*
77
+#include "hw/net/lan9118.h"
53
+ * The total size of Generic Error Data Entry
78
#include "net/net.h"
54
+ * ACPI 6.1/6.2: 18.3.2.7.1 Generic Error Data,
79
55
+ * Table 18-343 Generic Error Data Entry
80
typedef enum MPS2FPGAType {
56
+ */
81
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
57
+#define ACPI_GHES_DATA_LENGTH 72
82
index XXXXXXX..XXXXXXX 100644
58
+
83
--- a/hw/arm/realview.c
59
+/* The memory section CPER size, UEFI 2.6: N.2.5 Memory Error Section */
84
+++ b/hw/arm/realview.c
60
+#define ACPI_GHES_MEM_CPER_LENGTH 80
85
@@ -XXX,XX +XXX,XX @@
61
+
86
#include "hw/arm/arm.h"
62
+/* Masks for block_status flags */
87
#include "hw/arm/primecell.h"
63
+#define ACPI_GEBS_UNCORRECTABLE 1
88
#include "hw/devices.h"
64
+
89
+#include "hw/net/lan9118.h"
65
+/*
90
#include "hw/pci/pci.h"
66
+ * Total size for Generic Error Status Block except Generic Error Data Entries
91
#include "net/net.h"
67
+ * ACPI 6.2: 18.3.2.7.1 Generic Error Data,
92
#include "sysemu/sysemu.h"
68
+ * Table 18-380 Generic Error Status Block
93
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
69
+ */
94
index XXXXXXX..XXXXXXX 100644
70
+#define ACPI_GHES_GESB_SIZE 20
95
--- a/hw/arm/vexpress.c
71
+
96
+++ b/hw/arm/vexpress.c
72
+/*
97
@@ -XXX,XX +XXX,XX @@
73
+ * Values for error_severity field
98
#include "hw/sysbus.h"
74
+ */
99
#include "hw/arm/arm.h"
75
+enum AcpiGenericErrorSeverity {
100
#include "hw/arm/primecell.h"
76
+ ACPI_CPER_SEV_RECOVERABLE = 0,
101
-#include "hw/devices.h"
77
+ ACPI_CPER_SEV_FATAL = 1,
102
+#include "hw/net/lan9118.h"
78
+ ACPI_CPER_SEV_CORRECTED = 2,
103
#include "hw/i2c/i2c.h"
79
+ ACPI_CPER_SEV_NONE = 3,
104
#include "net/net.h"
80
+};
105
#include "sysemu/sysemu.h"
81
+
106
diff --git a/hw/net/lan9118.c b/hw/net/lan9118.c
82
/*
107
index XXXXXXX..XXXXXXX 100644
83
* Hardware Error Notification
108
--- a/hw/net/lan9118.c
84
* ACPI 4.0: 17.3.2.7 Hardware Error Notification
109
+++ b/hw/net/lan9118.c
85
@@ -XXX,XX +XXX,XX @@ static void build_ghes_hw_error_notification(GArray *table, const uint8_t type)
110
@@ -XXX,XX +XXX,XX @@
86
build_append_int_noprefix(table, 0, 4);
111
#include "hw/sysbus.h"
87
}
112
#include "net/net.h"
88
113
#include "net/eth.h"
89
+/*
114
-#include "hw/devices.h"
90
+ * Generic Error Data Entry
115
+#include "hw/net/lan9118.h"
91
+ * ACPI 6.1: 18.3.2.7.1 Generic Error Data
116
#include "sysemu/sysemu.h"
92
+ */
117
#include "hw/ptimer.h"
93
+static void acpi_ghes_generic_error_data(GArray *table,
118
#include "qemu/log.h"
94
+ const uint8_t *section_type, uint32_t error_severity,
95
+ uint8_t validation_bits, uint8_t flags,
96
+ uint32_t error_data_length, QemuUUID fru_id,
97
+ uint64_t time_stamp)
98
+{
99
+ const uint8_t fru_text[20] = {0};
100
+
101
+ /* Section Type */
102
+ g_array_append_vals(table, section_type, 16);
103
+
104
+ /* Error Severity */
105
+ build_append_int_noprefix(table, error_severity, 4);
106
+ /* Revision */
107
+ build_append_int_noprefix(table, 0x300, 2);
108
+ /* Validation Bits */
109
+ build_append_int_noprefix(table, validation_bits, 1);
110
+ /* Flags */
111
+ build_append_int_noprefix(table, flags, 1);
112
+ /* Error Data Length */
113
+ build_append_int_noprefix(table, error_data_length, 4);
114
+
115
+ /* FRU Id */
116
+ g_array_append_vals(table, fru_id.data, ARRAY_SIZE(fru_id.data));
117
+
118
+ /* FRU Text */
119
+ g_array_append_vals(table, fru_text, sizeof(fru_text));
120
+
121
+ /* Timestamp */
122
+ build_append_int_noprefix(table, time_stamp, 8);
123
+}
124
+
125
+/*
126
+ * Generic Error Status Block
127
+ * ACPI 6.1: 18.3.2.7.1 Generic Error Data
128
+ */
129
+static void acpi_ghes_generic_error_status(GArray *table, uint32_t block_status,
130
+ uint32_t raw_data_offset, uint32_t raw_data_length,
131
+ uint32_t data_length, uint32_t error_severity)
132
+{
133
+ /* Block Status */
134
+ build_append_int_noprefix(table, block_status, 4);
135
+ /* Raw Data Offset */
136
+ build_append_int_noprefix(table, raw_data_offset, 4);
137
+ /* Raw Data Length */
138
+ build_append_int_noprefix(table, raw_data_length, 4);
139
+ /* Data Length */
140
+ build_append_int_noprefix(table, data_length, 4);
141
+ /* Error Severity */
142
+ build_append_int_noprefix(table, error_severity, 4);
143
+}
144
+
145
+/* UEFI 2.6: N.2.5 Memory Error Section */
146
+static void acpi_ghes_build_append_mem_cper(GArray *table,
147
+ uint64_t error_physical_addr)
148
+{
149
+ /*
150
+ * Memory Error Record
151
+ */
152
+
153
+ /* Validation Bits */
154
+ build_append_int_noprefix(table,
155
+ (1ULL << 14) | /* Type Valid */
156
+ (1ULL << 1) /* Physical Address Valid */,
157
+ 8);
158
+ /* Error Status */
159
+ build_append_int_noprefix(table, 0, 8);
160
+ /* Physical Address */
161
+ build_append_int_noprefix(table, error_physical_addr, 8);
162
+ /* Skip all the detailed information normally found in such a record */
163
+ build_append_int_noprefix(table, 0, 48);
164
+ /* Memory Error Type */
165
+ build_append_int_noprefix(table, 0 /* Unknown error */, 1);
166
+ /* Skip all the detailed information normally found in such a record */
167
+ build_append_int_noprefix(table, 0, 7);
168
+}
169
+
170
+static int acpi_ghes_record_mem_error(uint64_t error_block_address,
171
+ uint64_t error_physical_addr)
172
+{
173
+ GArray *block;
174
+
175
+ /* Memory Error Section Type */
176
+ const uint8_t uefi_cper_mem_sec[] =
177
+ UUID_LE(0xA5BC1114, 0x6F64, 0x4EDE, 0xB8, 0x63, 0x3E, 0x83, \
178
+ 0xED, 0x7C, 0x83, 0xB1);
179
+
180
+ /* invalid fru id: ACPI 4.0: 17.3.2.6.1 Generic Error Data,
181
+ * Table 17-13 Generic Error Data Entry
182
+ */
183
+ QemuUUID fru_id = {};
184
+ uint32_t data_length;
185
+
186
+ block = g_array_new(false, true /* clear */, 1);
187
+
188
+ /* This is the length if adding a new generic error data entry*/
189
+ data_length = ACPI_GHES_DATA_LENGTH + ACPI_GHES_MEM_CPER_LENGTH;
190
+
191
+ /*
192
+ * Check whether it will run out of the preallocated memory if adding a new
193
+ * generic error data entry
194
+ */
195
+ if ((data_length + ACPI_GHES_GESB_SIZE) > ACPI_GHES_MAX_RAW_DATA_LENGTH) {
196
+ error_report("Not enough memory to record new CPER!!!");
197
+ g_array_free(block, true);
198
+ return -1;
199
+ }
200
+
201
+ /* Build the new generic error status block header */
202
+ acpi_ghes_generic_error_status(block, ACPI_GEBS_UNCORRECTABLE,
203
+ 0, 0, data_length, ACPI_CPER_SEV_RECOVERABLE);
204
+
205
+ /* Build this new generic error data entry header */
206
+ acpi_ghes_generic_error_data(block, uefi_cper_mem_sec,
207
+ ACPI_CPER_SEV_RECOVERABLE, 0, 0,
208
+ ACPI_GHES_MEM_CPER_LENGTH, fru_id, 0);
209
+
210
+ /* Build the memory section CPER for above new generic error data entry */
211
+ acpi_ghes_build_append_mem_cper(block, error_physical_addr);
212
+
213
+ /* Write the generic error data entry into guest memory */
214
+ cpu_physical_memory_write(error_block_address, block->data, block->len);
215
+
216
+ g_array_free(block, true);
217
+
218
+ return 0;
219
+}
220
+
221
/*
222
* Build table for the hardware error fw_cfg blob.
223
* Initialize "etc/hardware_errors" and "etc/hardware_errors_addr" fw_cfg blobs.
224
@@ -XXX,XX +XXX,XX @@ void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s,
225
fw_cfg_add_file_callback(s, ACPI_GHES_DATA_ADDR_FW_CFG_FILE, NULL, NULL,
226
NULL, &(ags->ghes_addr_le), sizeof(ags->ghes_addr_le), false);
227
}
228
+
229
+int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address)
230
+{
231
+ uint64_t error_block_addr, read_ack_register_addr, read_ack_register = 0;
232
+ uint64_t start_addr;
233
+ bool ret = -1;
234
+ AcpiGedState *acpi_ged_state;
235
+ AcpiGhesState *ags;
236
+
237
+ assert(source_id < ACPI_HEST_SRC_ID_RESERVED);
238
+
239
+ acpi_ged_state = ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED,
240
+ NULL));
241
+ g_assert(acpi_ged_state);
242
+ ags = &acpi_ged_state->ghes_state;
243
+
244
+ start_addr = le64_to_cpu(ags->ghes_addr_le);
245
+
246
+ if (physical_address) {
247
+
248
+ if (source_id < ACPI_HEST_SRC_ID_RESERVED) {
249
+ start_addr += source_id * sizeof(uint64_t);
250
+ }
251
+
252
+ cpu_physical_memory_read(start_addr, &error_block_addr,
253
+ sizeof(error_block_addr));
254
+
255
+ error_block_addr = le64_to_cpu(error_block_addr);
256
+
257
+ read_ack_register_addr = start_addr +
258
+ ACPI_GHES_ERROR_SOURCE_COUNT * sizeof(uint64_t);
259
+
260
+ cpu_physical_memory_read(read_ack_register_addr,
261
+ &read_ack_register, sizeof(read_ack_register));
262
+
263
+ /* zero means OSPM does not acknowledge the error */
264
+ if (!read_ack_register) {
265
+ error_report("OSPM does not acknowledge previous error,"
266
+ " so can not record CPER for current error anymore");
267
+ } else if (error_block_addr) {
268
+ read_ack_register = cpu_to_le64(0);
269
+ /*
270
+ * Clear the Read Ack Register, OSPM will write it to 1 when
271
+ * it acknowledges this error.
272
+ */
273
+ cpu_physical_memory_write(read_ack_register_addr,
274
+ &read_ack_register, sizeof(uint64_t));
275
+
276
+ ret = acpi_ghes_record_mem_error(error_block_addr,
277
+ physical_address);
278
+ } else
279
+ error_report("can not find Generic Error Status Block");
280
+ }
281
+
282
+ return ret;
283
+}
119
--
284
--
120
2.20.1
285
2.20.1
121
286
122
287
diff view generated by jsdifflib
1
Implement the code which updates the FPCCR register on an
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
2
exception entry where we are going to use lazy FP stacking.
2
3
We have to defer to the NVIC to determine whether the
3
Add a SIGBUS signal handler. In this handler, it checks the SIGBUS type,
4
various exceptions are currently ready or not.
4
translates the host VA delivered by host to guest PA, then fills this PA
5
5
to guest APEI GHES memory, then notifies guest according to the SIGBUS
6
type.
7
8
When guest accesses the poisoned memory, it will generate a Synchronous
9
External Abort(SEA). Then host kernel gets an APEI notification and calls
10
memory_failure() to unmapped the affected page in stage 2, finally
11
returns to guest.
12
13
Guest continues to access the PG_hwpoison page, it will trap to KVM as
14
stage2 fault, then a SIGBUS_MCEERR_AR synchronous signal is delivered to
15
Qemu, Qemu records this error address into guest APEI GHES memory and
16
notifes guest using Synchronous-External-Abort(SEA).
17
18
In order to inject a vSEA, we introduce the kvm_inject_arm_sea() function
19
in which we can setup the type of exception and the syndrome information.
20
When switching to guest, the target vcpu will jump to the synchronous
21
external abort vector table entry.
22
23
The ESR_ELx.DFSC is set to synchronous external abort(0x10), and the
24
ESR_ELx.FnV is set to not valid(0x1), which will tell guest that FAR is
25
not valid and hold an UNKNOWN value. These values will be set to KVM
26
register structures through KVM_SET_ONE_REG IOCTL.
27
28
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
29
Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
30
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
31
Acked-by: Xiang Zheng <zhengxiang9@huawei.com>
32
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
33
Reviewed-by: Igor Mammedov <imammedo@redhat.com>
34
Message-id: 20200512030609.19593-10-gengdongjiu@huawei.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
35
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20190416125744.27770-12-peter.maydell@linaro.org
8
---
36
---
9
target/arm/cpu.h | 14 +++++++++
37
include/sysemu/kvm.h | 3 +-
10
hw/intc/armv7m_nvic.c | 34 ++++++++++++++++++++++
38
target/arm/cpu.h | 4 +++
11
target/arm/helper.c | 67 ++++++++++++++++++++++++++++++++++++++++++-
39
target/arm/internals.h | 5 +--
12
3 files changed, 114 insertions(+), 1 deletion(-)
40
target/i386/cpu.h | 2 ++
13
41
target/arm/helper.c | 2 +-
42
target/arm/kvm64.c | 77 +++++++++++++++++++++++++++++++++++++++++
43
target/arm/tlb_helper.c | 2 +-
44
7 files changed, 89 insertions(+), 6 deletions(-)
45
46
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
47
index XXXXXXX..XXXXXXX 100644
48
--- a/include/sysemu/kvm.h
49
+++ b/include/sysemu/kvm.h
50
@@ -XXX,XX +XXX,XX @@ bool kvm_vcpu_id_is_valid(int vcpu_id);
51
/* Returns VCPU ID to be used on KVM_CREATE_VCPU ioctl() */
52
unsigned long kvm_arch_vcpu_id(CPUState *cpu);
53
54
-#ifdef TARGET_I386
55
-#define KVM_HAVE_MCE_INJECTION 1
56
+#ifdef KVM_HAVE_MCE_INJECTION
57
void kvm_arch_on_sigbus_vcpu(CPUState *cpu, int code, void *addr);
58
#endif
59
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
60
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.h
62
--- a/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
63
+++ b/target/arm/cpu.h
18
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_acknowledge_irq(void *opaque);
64
@@ -XXX,XX +XXX,XX @@
19
* (Ignoring -1, this is the same as the RETTOBASE value before completion.)
65
/* ARM processors have a weak memory model */
20
*/
66
#define TCG_GUEST_DEFAULT_MO (0)
21
int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure);
67
22
+/**
68
+#ifdef TARGET_AARCH64
23
+ * armv7m_nvic_get_ready_status(void *opaque, int irq, bool secure)
69
+#define KVM_HAVE_MCE_INJECTION 1
24
+ * @opaque: the NVIC
70
+#endif
25
+ * @irq: the exception number to mark pending
71
+
26
+ * @secure: false for non-banked exceptions or for the nonsecure
72
#define EXCP_UDEF 1 /* undefined instruction */
27
+ * version of a banked exception, true for the secure version of a banked
73
#define EXCP_SWI 2 /* software interrupt */
28
+ * exception.
74
#define EXCP_PREFETCH_ABORT 3
29
+ *
75
diff --git a/target/arm/internals.h b/target/arm/internals.h
30
+ * Return whether an exception is "ready", i.e. whether the exception is
76
index XXXXXXX..XXXXXXX 100644
31
+ * enabled and is configured at a priority which would allow it to
77
--- a/target/arm/internals.h
32
+ * interrupt the current execution priority. This controls whether the
78
+++ b/target/arm/internals.h
33
+ * RDY bit for it in the FPCCR is set.
79
@@ -XXX,XX +XXX,XX @@ static inline uint32_t syn_insn_abort(int same_el, int ea, int s1ptw, int fsc)
34
+ */
80
| ARM_EL_IL | (ea << 9) | (s1ptw << 7) | fsc;
35
+bool armv7m_nvic_get_ready_status(void *opaque, int irq, bool secure);
81
}
36
/**
82
37
* armv7m_nvic_raw_execution_priority: return the raw execution priority
83
-static inline uint32_t syn_data_abort_no_iss(int same_el,
38
* @opaque: the NVIC
84
+static inline uint32_t syn_data_abort_no_iss(int same_el, int fnv,
39
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
85
int ea, int cm, int s1ptw,
40
index XXXXXXX..XXXXXXX 100644
86
int wnr, int fsc)
41
--- a/hw/intc/armv7m_nvic.c
42
+++ b/hw/intc/armv7m_nvic.c
43
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
44
return ret;
45
}
46
47
+bool armv7m_nvic_get_ready_status(void *opaque, int irq, bool secure)
48
+{
49
+ /*
50
+ * Return whether an exception is "ready", i.e. it is enabled and is
51
+ * configured at a priority which would allow it to interrupt the
52
+ * current execution priority.
53
+ *
54
+ * irq and secure have the same semantics as for armv7m_nvic_set_pending():
55
+ * for non-banked exceptions secure is always false; for banked exceptions
56
+ * it indicates which of the exceptions is required.
57
+ */
58
+ NVICState *s = (NVICState *)opaque;
59
+ bool banked = exc_is_banked(irq);
60
+ VecInfo *vec;
61
+ int running = nvic_exec_prio(s);
62
+
63
+ assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
64
+ assert(!secure || banked);
65
+
66
+ /*
67
+ * HardFault is an odd special case: we always check against -1,
68
+ * even if we're secure and HardFault has priority -3; we never
69
+ * need to check for enabled state.
70
+ */
71
+ if (irq == ARMV7M_EXCP_HARD) {
72
+ return running > -1;
73
+ }
74
+
75
+ vec = (banked && secure) ? &s->sec_vectors[irq] : &s->vectors[irq];
76
+
77
+ return vec->enabled &&
78
+ exc_group_prio(s, vec->prio, secure) < running;
79
+}
80
+
81
/* callback when external interrupt line is changed */
82
static void set_irq_level(void *opaque, int n, int level)
83
{
87
{
88
return (EC_DATAABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
89
| ARM_EL_IL
90
- | (ea << 9) | (cm << 8) | (s1ptw << 7) | (wnr << 6) | fsc;
91
+ | (fnv << 10) | (ea << 9) | (cm << 8) | (s1ptw << 7)
92
+ | (wnr << 6) | fsc;
93
}
94
95
static inline uint32_t syn_data_abort_with_iss(int same_el,
96
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
97
index XXXXXXX..XXXXXXX 100644
98
--- a/target/i386/cpu.h
99
+++ b/target/i386/cpu.h
100
@@ -XXX,XX +XXX,XX @@
101
/* The x86 has a strong memory model with some store-after-load re-ordering */
102
#define TCG_GUEST_DEFAULT_MO (TCG_MO_ALL & ~TCG_MO_ST_LD)
103
104
+#define KVM_HAVE_MCE_INJECTION 1
105
+
106
/* Maximum instruction code size */
107
#define TARGET_MAX_INSN_SIZE 16
108
84
diff --git a/target/arm/helper.c b/target/arm/helper.c
109
diff --git a/target/arm/helper.c b/target/arm/helper.c
85
index XXXXXXX..XXXXXXX 100644
110
index XXXXXXX..XXXXXXX 100644
86
--- a/target/arm/helper.c
111
--- a/target/arm/helper.c
87
+++ b/target/arm/helper.c
112
+++ b/target/arm/helper.c
88
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
113
@@ -XXX,XX +XXX,XX @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
89
env->thumb = addr & 1;
114
* Report exception with ESR indicating a fault due to a
90
}
115
* translation table walk for a cache maintenance instruction.
91
116
*/
92
+static void v7m_update_fpccr(CPUARMState *env, uint32_t frameptr,
117
- syn = syn_data_abort_no_iss(current_el == target_el,
93
+ bool apply_splim)
118
+ syn = syn_data_abort_no_iss(current_el == target_el, 0,
119
fi.ea, 1, fi.s1ptw, 1, fsc);
120
env->exception.vaddress = value;
121
env->exception.fsr = fsr;
122
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
123
index XXXXXXX..XXXXXXX 100644
124
--- a/target/arm/kvm64.c
125
+++ b/target/arm/kvm64.c
126
@@ -XXX,XX +XXX,XX @@
127
#include "sysemu/kvm_int.h"
128
#include "kvm_arm.h"
129
#include "internals.h"
130
+#include "hw/acpi/acpi.h"
131
+#include "hw/acpi/ghes.h"
132
+#include "hw/arm/virt.h"
133
134
static bool have_guest_debug;
135
136
@@ -XXX,XX +XXX,XX @@ int kvm_arm_cpreg_level(uint64_t regidx)
137
return KVM_PUT_RUNTIME_STATE;
138
}
139
140
+/* Callers must hold the iothread mutex lock */
141
+static void kvm_inject_arm_sea(CPUState *c)
94
+{
142
+{
143
+ ARMCPU *cpu = ARM_CPU(c);
144
+ CPUARMState *env = &cpu->env;
145
+ CPUClass *cc = CPU_GET_CLASS(c);
146
+ uint32_t esr;
147
+ bool same_el;
148
+
149
+ c->exception_index = EXCP_DATA_ABORT;
150
+ env->exception.target_el = 1;
151
+
95
+ /*
152
+ /*
96
+ * Like the pseudocode UpdateFPCCR: save state in FPCAR and FPCCR
153
+ * Set the DFSC to synchronous external abort and set FnV to not valid,
97
+ * that we will need later in order to do lazy FP reg stacking.
154
+ * this will tell guest the FAR_ELx is UNKNOWN for this abort.
98
+ */
155
+ */
99
+ bool is_secure = env->v7m.secure;
156
+ same_el = arm_current_el(env) == env->exception.target_el;
100
+ void *nvic = env->nvic;
157
+ esr = syn_data_abort_no_iss(same_el, 1, 0, 0, 0, 0, 0x10);
101
+ /*
158
+
102
+ * Some bits are unbanked and live always in fpccr[M_REG_S]; some bits
159
+ env->exception.syndrome = esr;
103
+ * are banked and we want to update the bit in the bank for the
160
+
104
+ * current security state; and in one case we want to specifically
161
+ cc->do_interrupt(c);
105
+ * update the NS banked version of a bit even if we are secure.
162
+}
106
+ */
163
+
107
+ uint32_t *fpccr_s = &env->v7m.fpccr[M_REG_S];
164
#define AARCH64_CORE_REG(x) (KVM_REG_ARM64 | KVM_REG_SIZE_U64 | \
108
+ uint32_t *fpccr_ns = &env->v7m.fpccr[M_REG_NS];
165
KVM_REG_ARM_CORE | KVM_REG_ARM_CORE_REG(x))
109
+ uint32_t *fpccr = &env->v7m.fpccr[is_secure];
166
110
+ bool hfrdy, bfrdy, mmrdy, ns_ufrdy, s_ufrdy, sfrdy, monrdy;
167
@@ -XXX,XX +XXX,XX @@ int kvm_arch_get_registers(CPUState *cs)
111
+
168
return ret;
112
+ env->v7m.fpcar[is_secure] = frameptr & ~0x7;
169
}
113
+
170
114
+ if (apply_splim && arm_feature(env, ARM_FEATURE_V8)) {
171
+void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
115
+ bool splimviol;
172
+{
116
+ uint32_t splim = v7m_sp_limit(env);
173
+ ram_addr_t ram_addr;
117
+ bool ign = armv7m_nvic_neg_prio_requested(nvic, is_secure) &&
174
+ hwaddr paddr;
118
+ (env->v7m.ccr[is_secure] & R_V7M_CCR_STKOFHFNMIGN_MASK);
175
+ Object *obj = qdev_get_machine();
119
+
176
+ VirtMachineState *vms = VIRT_MACHINE(obj);
120
+ splimviol = !ign && frameptr < splim;
177
+ bool acpi_enabled = virt_is_acpi_enabled(vms);
121
+ *fpccr = FIELD_DP32(*fpccr, V7M_FPCCR, SPLIMVIOL, splimviol);
178
+
179
+ assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
180
+
181
+ if (acpi_enabled && addr &&
182
+ object_property_get_bool(obj, "ras", NULL)) {
183
+ ram_addr = qemu_ram_addr_from_host(addr);
184
+ if (ram_addr != RAM_ADDR_INVALID &&
185
+ kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
186
+ kvm_hwpoison_page_add(ram_addr);
187
+ /*
188
+ * If this is a BUS_MCEERR_AR, we know we have been called
189
+ * synchronously from the vCPU thread, so we can easily
190
+ * synchronize the state and inject an error.
191
+ *
192
+ * TODO: we currently don't tell the guest at all about
193
+ * BUS_MCEERR_AO. In that case we might either be being
194
+ * called synchronously from the vCPU thread, or a bit
195
+ * later from the main thread, so doing the injection of
196
+ * the error would be more complicated.
197
+ */
198
+ if (code == BUS_MCEERR_AR) {
199
+ kvm_cpu_synchronize_state(c);
200
+ if (!acpi_ghes_record_errors(ACPI_HEST_SRC_ID_SEA, paddr)) {
201
+ kvm_inject_arm_sea(c);
202
+ } else {
203
+ error_report("failed to record the error");
204
+ abort();
205
+ }
206
+ }
207
+ return;
208
+ }
209
+ if (code == BUS_MCEERR_AO) {
210
+ error_report("Hardware memory error at addr %p for memory used by "
211
+ "QEMU itself instead of guest system!", addr);
212
+ }
122
+ }
213
+ }
123
+
214
+
124
+ *fpccr = FIELD_DP32(*fpccr, V7M_FPCCR, LSPACT, 1);
215
+ if (code == BUS_MCEERR_AR) {
125
+
216
+ error_report("Hardware memory error!");
126
+ *fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, S, is_secure);
217
+ exit(1);
127
+
128
+ *fpccr = FIELD_DP32(*fpccr, V7M_FPCCR, USER, arm_current_el(env) == 0);
129
+
130
+ *fpccr = FIELD_DP32(*fpccr, V7M_FPCCR, THREAD,
131
+ !arm_v7m_is_handler_mode(env));
132
+
133
+ hfrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_HARD, false);
134
+ *fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, HFRDY, hfrdy);
135
+
136
+ bfrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_BUS, false);
137
+ *fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, BFRDY, bfrdy);
138
+
139
+ mmrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_MEM, is_secure);
140
+ *fpccr = FIELD_DP32(*fpccr, V7M_FPCCR, MMRDY, mmrdy);
141
+
142
+ ns_ufrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_USAGE, false);
143
+ *fpccr_ns = FIELD_DP32(*fpccr_ns, V7M_FPCCR, UFRDY, ns_ufrdy);
144
+
145
+ monrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_DEBUG, false);
146
+ *fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, MONRDY, monrdy);
147
+
148
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
149
+ s_ufrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_USAGE, true);
150
+ *fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, UFRDY, s_ufrdy);
151
+
152
+ sfrdy = armv7m_nvic_get_ready_status(nvic, ARMV7M_EXCP_SECURE, false);
153
+ *fpccr_s = FIELD_DP32(*fpccr_s, V7M_FPCCR, SFRDY, sfrdy);
154
+ }
218
+ }
155
+}
219
+}
156
+
220
+
157
static bool v7m_push_stack(ARMCPU *cpu)
221
/* C6.6.29 BRK instruction */
158
{
222
static const uint32_t brk_insn = 0xd4200000;
159
/* Do the "set up stack frame" part of exception entry,
223
160
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
224
diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
161
}
225
index XXXXXXX..XXXXXXX 100644
162
} else {
226
--- a/target/arm/tlb_helper.c
163
/* Lazy stacking enabled, save necessary info to stack later */
227
+++ b/target/arm/tlb_helper.c
164
- /* TODO : equivalent of UpdateFPCCR() pseudocode */
228
@@ -XXX,XX +XXX,XX @@ static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
165
+ v7m_update_fpccr(env, frameptr + 0x20, true);
229
* ISV field.
166
}
230
*/
167
}
231
if (!(template_syn & ARM_EL_ISV) || target_el != 2 || s1ptw) {
168
}
232
- syn = syn_data_abort_no_iss(same_el,
233
+ syn = syn_data_abort_no_iss(same_el, 0,
234
ea, 0, s1ptw, is_write, fsc);
235
} else {
236
/*
169
--
237
--
170
2.20.1
238
2.20.1
171
239
172
240
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
From: Dongjiu Geng <gengdongjiu@huawei.com>
2
2
3
Reviewed-by: Markus Armbruster <armbru@redhat.com>
3
I and Xiang are willing to review the APEI-related patches and
4
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
4
volunteer as the reviewers for the HEST/GHES part.
5
Message-id: 20190412165416.7977-5-philmd@redhat.com
5
6
Signed-off-by: Dongjiu Geng <gengdongjiu@huawei.com>
7
Signed-off-by: Xiang Zheng <zhengxiang9@huawei.com>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
9
Acked-by: Michael S. Tsirkin <mst@redhat.com>
10
Message-id: 20200512030609.19593-11-gengdongjiu@huawei.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
12
---
8
include/hw/devices.h | 6 ------
13
MAINTAINERS | 9 +++++++++
9
include/hw/display/tc6393xb.h | 24 ++++++++++++++++++++++++
14
1 file changed, 9 insertions(+)
10
hw/arm/tosa.c | 2 +-
11
hw/display/tc6393xb.c | 2 +-
12
MAINTAINERS | 1 +
13
5 files changed, 27 insertions(+), 8 deletions(-)
14
create mode 100644 include/hw/display/tc6393xb.h
15
15
16
diff --git a/include/hw/devices.h b/include/hw/devices.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/devices.h
19
+++ b/include/hw/devices.h
20
@@ -XXX,XX +XXX,XX @@ void *tahvo_init(qemu_irq irq, int betty);
21
22
void retu_key_event(void *retu, int state);
23
24
-/* tc6393xb.c */
25
-typedef struct TC6393xbState TC6393xbState;
26
-TC6393xbState *tc6393xb_init(struct MemoryRegion *sysmem,
27
- uint32_t base, qemu_irq irq);
28
-qemu_irq tc6393xb_l3v_get(TC6393xbState *s);
29
-
30
#endif
31
diff --git a/include/hw/display/tc6393xb.h b/include/hw/display/tc6393xb.h
32
new file mode 100644
33
index XXXXXXX..XXXXXXX
34
--- /dev/null
35
+++ b/include/hw/display/tc6393xb.h
36
@@ -XXX,XX +XXX,XX @@
37
+/*
38
+ * Toshiba TC6393XB I/O Controller.
39
+ * Found in Sharp Zaurus SL-6000 (tosa) or some
40
+ * Toshiba e-Series PDAs.
41
+ *
42
+ * Copyright (c) 2007 Hervé Poussineau
43
+ *
44
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
45
+ * See the COPYING file in the top-level directory.
46
+ */
47
+
48
+#ifndef HW_DISPLAY_TC6393XB_H
49
+#define HW_DISPLAY_TC6393XB_H
50
+
51
+#include "exec/memory.h"
52
+#include "hw/irq.h"
53
+
54
+typedef struct TC6393xbState TC6393xbState;
55
+
56
+TC6393xbState *tc6393xb_init(struct MemoryRegion *sysmem,
57
+ uint32_t base, qemu_irq irq);
58
+qemu_irq tc6393xb_l3v_get(TC6393xbState *s);
59
+
60
+#endif
61
diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/hw/arm/tosa.c
64
+++ b/hw/arm/tosa.c
65
@@ -XXX,XX +XXX,XX @@
66
#include "hw/hw.h"
67
#include "hw/arm/pxa.h"
68
#include "hw/arm/arm.h"
69
-#include "hw/devices.h"
70
#include "hw/arm/sharpsl.h"
71
#include "hw/pcmcia.h"
72
#include "hw/boards.h"
73
+#include "hw/display/tc6393xb.h"
74
#include "hw/i2c/i2c.h"
75
#include "hw/ssi/ssi.h"
76
#include "hw/sysbus.h"
77
diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/hw/display/tc6393xb.c
80
+++ b/hw/display/tc6393xb.c
81
@@ -XXX,XX +XXX,XX @@
82
#include "qapi/error.h"
83
#include "qemu/host-utils.h"
84
#include "hw/hw.h"
85
-#include "hw/devices.h"
86
+#include "hw/display/tc6393xb.h"
87
#include "hw/block/flash.h"
88
#include "ui/console.h"
89
#include "ui/pixel_ops.h"
90
diff --git a/MAINTAINERS b/MAINTAINERS
16
diff --git a/MAINTAINERS b/MAINTAINERS
91
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
92
--- a/MAINTAINERS
18
--- a/MAINTAINERS
93
+++ b/MAINTAINERS
19
+++ b/MAINTAINERS
94
@@ -XXX,XX +XXX,XX @@ F: hw/misc/mst_fpga.c
20
@@ -XXX,XX +XXX,XX @@ F: tests/qtest/bios-tables-test.c
95
F: hw/misc/max111x.c
21
F: tests/qtest/acpi-utils.[hc]
96
F: include/hw/arm/pxa.h
22
F: tests/data/acpi/
97
F: include/hw/arm/sharpsl.h
23
98
+F: include/hw/display/tc6393xb.h
24
+ACPI/HEST/GHES
99
25
+R: Dongjiu Geng <gengdongjiu@huawei.com>
100
SABRELITE / i.MX6
26
+R: Xiang Zheng <zhengxiang9@huawei.com>
101
M: Peter Maydell <peter.maydell@linaro.org>
27
+L: qemu-arm@nongnu.org
28
+S: Maintained
29
+F: hw/acpi/ghes.c
30
+F: include/hw/acpi/ghes.h
31
+F: docs/specs/acpi_hest_ghes.rst
32
+
33
ppc4xx
34
M: David Gibson <david@gibson.dropbear.id.au>
35
L: qemu-ppc@nongnu.org
102
--
36
--
103
2.20.1
37
2.20.1
104
38
105
39
diff view generated by jsdifflib
1
Correct the decode of the M-profile "coprocessor and
1
Convert the Neon VQRDMLAH and VQRDMLSH insns in the 3-reg-same group
2
floating-point instructions" space:
2
to decodetree. These don't use do_3same() because they want to
3
* op0 == 0b11 is always unallocated
3
operate on VFP double registers, whose offsets are different from the
4
* if the CPU has an FPU then all insns with op1 == 0b101
4
neon_reg_offset() calculations do_3same does.
5
are floating point and go to disas_vfp_insn()
6
7
For the moment we leave VLLDM and VLSTM as NOPs; in
8
a later commit we will fill in the proper implementation
9
for the case where an FPU is present.
10
5
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20190416125744.27770-7-peter.maydell@linaro.org
8
Message-id: 20200512163904.10918-2-peter.maydell@linaro.org
14
---
9
---
15
target/arm/translate.c | 26 ++++++++++++++++++++++----
10
target/arm/neon-dp.decode | 3 +++
16
1 file changed, 22 insertions(+), 4 deletions(-)
11
target/arm/translate-neon.inc.c | 15 +++++++++++++++
12
target/arm/translate.c | 14 ++------------
13
3 files changed, 20 insertions(+), 12 deletions(-)
17
14
15
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/neon-dp.decode
18
+++ b/target/arm/neon-dp.decode
19
@@ -XXX,XX +XXX,XX @@ VMLS_3s 1111 001 1 0 . .. .... .... 1001 . . . 0 .... @3same
20
21
VMUL_3s 1111 001 0 0 . .. .... .... 1001 . . . 1 .... @3same
22
VMUL_p_3s 1111 001 1 0 . .. .... .... 1001 . . . 1 .... @3same
23
+
24
+VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same
25
+VQRDMLSH_3s 1111 001 1 0 . .. .... .... 1100 ... 1 .... @3same
26
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/translate-neon.inc.c
29
+++ b/target/arm/translate-neon.inc.c
30
@@ -XXX,XX +XXX,XX @@ static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a)
31
}
32
return do_3same(s, a, gen_VMUL_p_3s);
33
}
34
+
35
+#define DO_VQRDMLAH(INSN, FUNC) \
36
+ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \
37
+ { \
38
+ if (!dc_isar_feature(aa32_rdm, s)) { \
39
+ return false; \
40
+ } \
41
+ if (a->size != 1 && a->size != 2) { \
42
+ return false; \
43
+ } \
44
+ return do_3same(s, a, FUNC); \
45
+ }
46
+
47
+DO_VQRDMLAH(VQRDMLAH, gen_gvec_sqrdmlah_qc)
48
+DO_VQRDMLAH(VQRDMLSH, gen_gvec_sqrdmlsh_qc)
18
diff --git a/target/arm/translate.c b/target/arm/translate.c
49
diff --git a/target/arm/translate.c b/target/arm/translate.c
19
index XXXXXXX..XXXXXXX 100644
50
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/translate.c
51
--- a/target/arm/translate.c
21
+++ b/target/arm/translate.c
52
+++ b/target/arm/translate.c
22
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
53
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
23
case 6: case 7: case 14: case 15:
54
if (!u) {
24
/* Coprocessor. */
55
break; /* VPADD */
25
if (arm_dc_feature(s, ARM_FEATURE_M)) {
56
}
26
- /* We don't currently implement M profile FP support,
57
- /* VQRDMLAH */
27
- * so this entire space should give a NOCP fault, with
58
- if (dc_isar_feature(aa32_rdm, s) && (size == 1 || size == 2)) {
28
- * the exception of the v8M VLLDM and VLSTM insns, which
59
- gen_gvec_sqrdmlah_qc(size, rd_ofs, rn_ofs, rm_ofs,
29
- * must be NOPs in Secure state and UNDEF in Nonsecure state.
60
- vec_size, vec_size);
30
+ /* 0b111x_11xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx */
61
- return 0;
31
+ if (extract32(insn, 24, 2) == 3) {
62
- }
32
+ goto illegal_op; /* op0 = 0b11 : unallocated */
63
+ /* VQRDMLAH : handled by decodetree */
33
+ }
64
return 1;
34
+
65
35
+ /*
66
case NEON_3R_VFM_VQRDMLSH:
36
+ * Decode VLLDM and VLSTM first: these are nonstandard because:
67
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
37
+ * * if there is no FPU then these insns must NOP in
68
}
38
+ * Secure state and UNDEF in Nonsecure state
39
+ * * if there is an FPU then these insns do not have
40
+ * the usual behaviour that disas_vfp_insn() provides of
41
+ * being controlled by CPACR/NSACR enable bits or the
42
+ * lazy-stacking logic.
43
*/
44
if (arm_dc_feature(s, ARM_FEATURE_V8) &&
45
(insn & 0xffa00f00) == 0xec200a00) {
46
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
47
/* Just NOP since FP support is not implemented */
48
break;
69
break;
49
}
70
}
50
+ if (arm_dc_feature(s, ARM_FEATURE_VFP) &&
71
- /* VQRDMLSH */
51
+ ((insn >> 8) & 0xe) == 10) {
72
- if (dc_isar_feature(aa32_rdm, s) && (size == 1 || size == 2)) {
52
+ /* FP, and the CPU supports it */
73
- gen_gvec_sqrdmlsh_qc(size, rd_ofs, rn_ofs, rm_ofs,
53
+ if (disas_vfp_insn(s, insn)) {
74
- vec_size, vec_size);
54
+ goto illegal_op;
75
- return 0;
55
+ }
76
- }
56
+ break;
77
+ /* VQRDMLSH : handled by decodetree */
57
+ }
78
return 1;
58
+
79
59
/* All other insns: NOCP */
80
case NEON_3R_VABD:
60
gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
61
default_exception_el(s));
62
--
81
--
63
2.20.1
82
2.20.1
64
83
65
84
diff view generated by jsdifflib
1
The only "system register" that M-profile floating point exposes
1
Convert the Neon SHA instructions in the 3-reg-same group
2
via the VMRS/VMRS instructions is FPSCR, and it does not have
2
to decodetree.
3
the odd special case for rd==15. Add a check to ensure we only
4
expose FPSCR.
5
3
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20190416125744.27770-5-peter.maydell@linaro.org
6
Message-id: 20200512163904.10918-3-peter.maydell@linaro.org
9
---
7
---
10
target/arm/translate.c | 19 +++++++++++++++++--
8
target/arm/neon-dp.decode | 10 +++
11
1 file changed, 17 insertions(+), 2 deletions(-)
9
target/arm/translate-neon.inc.c | 139 ++++++++++++++++++++++++++++++++
12
10
target/arm/translate.c | 46 +----------
11
3 files changed, 151 insertions(+), 44 deletions(-)
12
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
16
+++ b/target/arm/neon-dp.decode
17
@@ -XXX,XX +XXX,XX @@ VMUL_3s 1111 001 0 0 . .. .... .... 1001 . . . 1 .... @3same
18
VMUL_p_3s 1111 001 1 0 . .. .... .... 1001 . . . 1 .... @3same
19
20
VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same
21
+
22
+SHA1_3s 1111 001 0 0 . optype:2 .... .... 1100 . 1 . 0 .... \
23
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
24
+SHA256H_3s 1111 001 1 0 . 00 .... .... 1100 . 1 . 0 .... \
25
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
26
+SHA256H2_3s 1111 001 1 0 . 01 .... .... 1100 . 1 . 0 .... \
27
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
28
+SHA256SU1_3s 1111 001 1 0 . 10 .... .... 1100 . 1 . 0 .... \
29
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
30
+
31
VQRDMLSH_3s 1111 001 1 0 . .. .... .... 1100 ... 1 .... @3same
32
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/translate-neon.inc.c
35
+++ b/target/arm/translate-neon.inc.c
36
@@ -XXX,XX +XXX,XX @@ static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a)
37
38
DO_VQRDMLAH(VQRDMLAH, gen_gvec_sqrdmlah_qc)
39
DO_VQRDMLAH(VQRDMLSH, gen_gvec_sqrdmlsh_qc)
40
+
41
+static bool trans_SHA1_3s(DisasContext *s, arg_SHA1_3s *a)
42
+{
43
+ TCGv_ptr ptr1, ptr2, ptr3;
44
+ TCGv_i32 tmp;
45
+
46
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
47
+ !dc_isar_feature(aa32_sha1, s)) {
48
+ return false;
49
+ }
50
+
51
+ /* UNDEF accesses to D16-D31 if they don't exist. */
52
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
53
+ ((a->vd | a->vn | a->vm) & 0x10)) {
54
+ return false;
55
+ }
56
+
57
+ if ((a->vn | a->vm | a->vd) & 1) {
58
+ return false;
59
+ }
60
+
61
+ if (!vfp_access_check(s)) {
62
+ return true;
63
+ }
64
+
65
+ ptr1 = vfp_reg_ptr(true, a->vd);
66
+ ptr2 = vfp_reg_ptr(true, a->vn);
67
+ ptr3 = vfp_reg_ptr(true, a->vm);
68
+ tmp = tcg_const_i32(a->optype);
69
+ gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp);
70
+ tcg_temp_free_i32(tmp);
71
+ tcg_temp_free_ptr(ptr1);
72
+ tcg_temp_free_ptr(ptr2);
73
+ tcg_temp_free_ptr(ptr3);
74
+
75
+ return true;
76
+}
77
+
78
+static bool trans_SHA256H_3s(DisasContext *s, arg_SHA256H_3s *a)
79
+{
80
+ TCGv_ptr ptr1, ptr2, ptr3;
81
+
82
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
83
+ !dc_isar_feature(aa32_sha2, s)) {
84
+ return false;
85
+ }
86
+
87
+ /* UNDEF accesses to D16-D31 if they don't exist. */
88
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
89
+ ((a->vd | a->vn | a->vm) & 0x10)) {
90
+ return false;
91
+ }
92
+
93
+ if ((a->vn | a->vm | a->vd) & 1) {
94
+ return false;
95
+ }
96
+
97
+ if (!vfp_access_check(s)) {
98
+ return true;
99
+ }
100
+
101
+ ptr1 = vfp_reg_ptr(true, a->vd);
102
+ ptr2 = vfp_reg_ptr(true, a->vn);
103
+ ptr3 = vfp_reg_ptr(true, a->vm);
104
+ gen_helper_crypto_sha256h(ptr1, ptr2, ptr3);
105
+ tcg_temp_free_ptr(ptr1);
106
+ tcg_temp_free_ptr(ptr2);
107
+ tcg_temp_free_ptr(ptr3);
108
+
109
+ return true;
110
+}
111
+
112
+static bool trans_SHA256H2_3s(DisasContext *s, arg_SHA256H2_3s *a)
113
+{
114
+ TCGv_ptr ptr1, ptr2, ptr3;
115
+
116
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
117
+ !dc_isar_feature(aa32_sha2, s)) {
118
+ return false;
119
+ }
120
+
121
+ /* UNDEF accesses to D16-D31 if they don't exist. */
122
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
123
+ ((a->vd | a->vn | a->vm) & 0x10)) {
124
+ return false;
125
+ }
126
+
127
+ if ((a->vn | a->vm | a->vd) & 1) {
128
+ return false;
129
+ }
130
+
131
+ if (!vfp_access_check(s)) {
132
+ return true;
133
+ }
134
+
135
+ ptr1 = vfp_reg_ptr(true, a->vd);
136
+ ptr2 = vfp_reg_ptr(true, a->vn);
137
+ ptr3 = vfp_reg_ptr(true, a->vm);
138
+ gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3);
139
+ tcg_temp_free_ptr(ptr1);
140
+ tcg_temp_free_ptr(ptr2);
141
+ tcg_temp_free_ptr(ptr3);
142
+
143
+ return true;
144
+}
145
+
146
+static bool trans_SHA256SU1_3s(DisasContext *s, arg_SHA256SU1_3s *a)
147
+{
148
+ TCGv_ptr ptr1, ptr2, ptr3;
149
+
150
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
151
+ !dc_isar_feature(aa32_sha2, s)) {
152
+ return false;
153
+ }
154
+
155
+ /* UNDEF accesses to D16-D31 if they don't exist. */
156
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
157
+ ((a->vd | a->vn | a->vm) & 0x10)) {
158
+ return false;
159
+ }
160
+
161
+ if ((a->vn | a->vm | a->vd) & 1) {
162
+ return false;
163
+ }
164
+
165
+ if (!vfp_access_check(s)) {
166
+ return true;
167
+ }
168
+
169
+ ptr1 = vfp_reg_ptr(true, a->vd);
170
+ ptr2 = vfp_reg_ptr(true, a->vn);
171
+ ptr3 = vfp_reg_ptr(true, a->vm);
172
+ gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3);
173
+ tcg_temp_free_ptr(ptr1);
174
+ tcg_temp_free_ptr(ptr2);
175
+ tcg_temp_free_ptr(ptr3);
176
+
177
+ return true;
178
+}
13
diff --git a/target/arm/translate.c b/target/arm/translate.c
179
diff --git a/target/arm/translate.c b/target/arm/translate.c
14
index XXXXXXX..XXXXXXX 100644
180
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate.c
181
--- a/target/arm/translate.c
16
+++ b/target/arm/translate.c
182
+++ b/target/arm/translate.c
17
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
183
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
18
}
184
int vec_size;
19
}
185
uint32_t imm;
20
} else { /* !dp */
186
TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
21
+ bool is_sysreg;
187
- TCGv_ptr ptr1, ptr2, ptr3;
22
+
188
+ TCGv_ptr ptr1, ptr2;
23
if ((insn & 0x6f) != 0x00)
189
TCGv_i64 tmp64;
24
return 1;
190
25
rn = VFP_SREG_N(insn);
191
if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
26
+
192
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
27
+ is_sysreg = extract32(insn, 21, 1);
193
return 1;
28
+
194
}
29
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
195
switch (op) {
30
+ /*
196
- case NEON_3R_SHA:
31
+ * The only M-profile VFP vmrs/vmsr sysreg is FPSCR.
197
- /* The SHA-1/SHA-256 3-register instructions require special
32
+ * Writes to R15 are UNPREDICTABLE; we choose to undef.
198
- * treatment here, as their size field is overloaded as an
33
+ */
199
- * op type selector, and they all consume their input in a
34
+ if (is_sysreg && (rd == 15 || (rn >> 1) != ARM_VFP_FPSCR)) {
200
- * single pass.
35
+ return 1;
201
- */
36
+ }
202
- if (!q) {
37
+ }
203
- return 1;
38
+
204
- }
39
if (insn & ARM_CP_RW_BIT) {
205
- if (!u) { /* SHA-1 */
40
/* vfp->arm */
206
- if (!dc_isar_feature(aa32_sha1, s)) {
41
- if (insn & (1 << 21)) {
207
- return 1;
42
+ if (is_sysreg) {
208
- }
43
/* system register */
209
- ptr1 = vfp_reg_ptr(true, rd);
44
rn >>= 1;
210
- ptr2 = vfp_reg_ptr(true, rn);
45
211
- ptr3 = vfp_reg_ptr(true, rm);
46
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
212
- tmp4 = tcg_const_i32(size);
47
}
213
- gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp4);
48
} else {
214
- tcg_temp_free_i32(tmp4);
49
/* arm->vfp */
215
- } else { /* SHA-256 */
50
- if (insn & (1 << 21)) {
216
- if (!dc_isar_feature(aa32_sha2, s) || size == 3) {
51
+ if (is_sysreg) {
217
- return 1;
52
rn >>= 1;
218
- }
53
/* system register */
219
- ptr1 = vfp_reg_ptr(true, rd);
54
switch (rn) {
220
- ptr2 = vfp_reg_ptr(true, rn);
221
- ptr3 = vfp_reg_ptr(true, rm);
222
- switch (size) {
223
- case 0:
224
- gen_helper_crypto_sha256h(ptr1, ptr2, ptr3);
225
- break;
226
- case 1:
227
- gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3);
228
- break;
229
- case 2:
230
- gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3);
231
- break;
232
- }
233
- }
234
- tcg_temp_free_ptr(ptr1);
235
- tcg_temp_free_ptr(ptr2);
236
- tcg_temp_free_ptr(ptr3);
237
- return 0;
238
-
239
case NEON_3R_VPADD_VQRDMLAH:
240
if (!u) {
241
break; /* VPADD */
242
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
243
case NEON_3R_VMUL:
244
case NEON_3R_VML:
245
case NEON_3R_VSHL:
246
+ case NEON_3R_SHA:
247
/* Already handled by decodetree */
248
return 1;
249
}
55
--
250
--
56
2.20.1
251
2.20.1
57
252
58
253
diff view generated by jsdifflib
1
Enable the FPU by default for the Cortex-M4 and Cortex-M33.
1
Convert the 64-bit element insns in the 3-reg-same group
2
to decodetree. This covers VQSHL, VRSHL and VQRSHL where
3
size==0b11.
2
4
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20190416125744.27770-27-peter.maydell@linaro.org
7
Message-id: 20200512163904.10918-4-peter.maydell@linaro.org
6
---
8
---
7
target/arm/cpu.c | 8 ++++++++
9
target/arm/neon-dp.decode | 13 +++++++++++
8
1 file changed, 8 insertions(+)
10
target/arm/translate-neon.inc.c | 24 +++++++++++++++++++++
11
target/arm/translate.c | 38 ++-------------------------------
12
3 files changed, 39 insertions(+), 36 deletions(-)
9
13
10
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
11
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
12
--- a/target/arm/cpu.c
16
--- a/target/arm/neon-dp.decode
13
+++ b/target/arm/cpu.c
17
+++ b/target/arm/neon-dp.decode
14
@@ -XXX,XX +XXX,XX @@ static void cortex_m4_initfn(Object *obj)
18
@@ -XXX,XX +XXX,XX @@ VCGE_U_3s 1111 001 1 0 . .. .... .... 0011 . . . 1 .... @3same
15
set_feature(&cpu->env, ARM_FEATURE_M);
19
VSHL_S_3s 1111 001 0 0 . .. .... .... 0100 . . . 0 .... @3same_rev
16
set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
20
VSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 0 .... @3same_rev
17
set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
21
18
+ set_feature(&cpu->env, ARM_FEATURE_VFP4);
22
+# Insns operating on 64-bit elements (size!=0b11 handled elsewhere)
19
cpu->midr = 0x410fc240; /* r0p0 */
23
+# The _rev suffix indicates that Vn and Vm are reversed (as explained
20
cpu->pmsav7_dregion = 8;
24
+# by the comment for the @3same_rev format).
21
+ cpu->isar.mvfr0 = 0x10110021;
25
+@3same_64_rev .... ... . . . 11 .... .... .... . q:1 . . .... \
22
+ cpu->isar.mvfr1 = 0x11000011;
26
+ &3same vm=%vn_dp vn=%vm_dp vd=%vd_dp size=3
23
+ cpu->isar.mvfr2 = 0x00000000;
27
+
24
cpu->id_pfr0 = 0x00000030;
28
+VQSHL_S64_3s 1111 001 0 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev
25
cpu->id_pfr1 = 0x00000200;
29
+VQSHL_U64_3s 1111 001 1 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev
26
cpu->id_dfr0 = 0x00100000;
30
+VRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev
27
@@ -XXX,XX +XXX,XX @@ static void cortex_m33_initfn(Object *obj)
31
+VRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev
28
set_feature(&cpu->env, ARM_FEATURE_M_MAIN);
32
+VQRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev
29
set_feature(&cpu->env, ARM_FEATURE_M_SECURITY);
33
+VQRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev
30
set_feature(&cpu->env, ARM_FEATURE_THUMB_DSP);
34
+
31
+ set_feature(&cpu->env, ARM_FEATURE_VFP4);
35
VMAX_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 0 .... @3same
32
cpu->midr = 0x410fd213; /* r0p3 */
36
VMAX_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 0 .... @3same
33
cpu->pmsav7_dregion = 16;
37
VMIN_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 1 .... @3same
34
cpu->sau_sregion = 8;
38
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
35
+ cpu->isar.mvfr0 = 0x10110021;
39
index XXXXXXX..XXXXXXX 100644
36
+ cpu->isar.mvfr1 = 0x11000011;
40
--- a/target/arm/translate-neon.inc.c
37
+ cpu->isar.mvfr2 = 0x00000040;
41
+++ b/target/arm/translate-neon.inc.c
38
cpu->id_pfr0 = 0x00000030;
42
@@ -XXX,XX +XXX,XX @@ static bool trans_SHA256SU1_3s(DisasContext *s, arg_SHA256SU1_3s *a)
39
cpu->id_pfr1 = 0x00000210;
43
40
cpu->id_dfr0 = 0x00200000;
44
return true;
45
}
46
+
47
+#define DO_3SAME_64(INSN, FUNC) \
48
+ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
49
+ uint32_t rn_ofs, uint32_t rm_ofs, \
50
+ uint32_t oprsz, uint32_t maxsz) \
51
+ { \
52
+ static const GVecGen3 op = { .fni8 = FUNC }; \
53
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &op); \
54
+ } \
55
+ DO_3SAME(INSN, gen_##INSN##_3s)
56
+
57
+#define DO_3SAME_64_ENV(INSN, FUNC) \
58
+ static void gen_##INSN##_elt(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m) \
59
+ { \
60
+ FUNC(d, cpu_env, n, m); \
61
+ } \
62
+ DO_3SAME_64(INSN, gen_##INSN##_elt)
63
+
64
+DO_3SAME_64(VRSHL_S64, gen_helper_neon_rshl_s64)
65
+DO_3SAME_64(VRSHL_U64, gen_helper_neon_rshl_u64)
66
+DO_3SAME_64_ENV(VQSHL_S64, gen_helper_neon_qshl_s64)
67
+DO_3SAME_64_ENV(VQSHL_U64, gen_helper_neon_qshl_u64)
68
+DO_3SAME_64_ENV(VQRSHL_S64, gen_helper_neon_qrshl_s64)
69
+DO_3SAME_64_ENV(VQRSHL_U64, gen_helper_neon_qrshl_u64)
70
diff --git a/target/arm/translate.c b/target/arm/translate.c
71
index XXXXXXX..XXXXXXX 100644
72
--- a/target/arm/translate.c
73
+++ b/target/arm/translate.c
74
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
75
}
76
77
if (size == 3) {
78
- /* 64-bit element instructions. */
79
- for (pass = 0; pass < (q ? 2 : 1); pass++) {
80
- neon_load_reg64(cpu_V0, rn + pass);
81
- neon_load_reg64(cpu_V1, rm + pass);
82
- switch (op) {
83
- case NEON_3R_VQSHL:
84
- if (u) {
85
- gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
86
- cpu_V1, cpu_V0);
87
- } else {
88
- gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
89
- cpu_V1, cpu_V0);
90
- }
91
- break;
92
- case NEON_3R_VRSHL:
93
- if (u) {
94
- gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
95
- } else {
96
- gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
97
- }
98
- break;
99
- case NEON_3R_VQRSHL:
100
- if (u) {
101
- gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
102
- cpu_V1, cpu_V0);
103
- } else {
104
- gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
105
- cpu_V1, cpu_V0);
106
- }
107
- break;
108
- default:
109
- abort();
110
- }
111
- neon_store_reg64(cpu_V0, rd + pass);
112
- }
113
- return 0;
114
+ /* 64-bit element instructions: handled by decodetree */
115
+ return 1;
116
}
117
pairwise = 0;
118
switch (op) {
41
--
119
--
42
2.20.1
120
2.20.1
43
121
44
122
diff view generated by jsdifflib
1
Handle floating point registers in exception return.
1
Convert the Neon VHADD insns in the 3-reg-same group to decodetree.
2
This corresponds to pseudocode functions ValidateExceptionReturn(),
3
ExceptionReturn(), PopStack() and ConsumeExcStackFrame().
4
2
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20190416125744.27770-16-peter.maydell@linaro.org
5
Message-id: 20200512163904.10918-5-peter.maydell@linaro.org
8
---
6
---
9
target/arm/helper.c | 142 +++++++++++++++++++++++++++++++++++++++++++-
7
target/arm/neon-dp.decode | 2 ++
10
1 file changed, 141 insertions(+), 1 deletion(-)
8
target/arm/translate-neon.inc.c | 24 ++++++++++++++++++++++++
9
target/arm/translate.c | 4 +---
10
3 files changed, 27 insertions(+), 3 deletions(-)
11
11
12
diff --git a/target/arm/helper.c b/target/arm/helper.c
12
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
13
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/helper.c
14
--- a/target/arm/neon-dp.decode
15
+++ b/target/arm/helper.c
15
+++ b/target/arm/neon-dp.decode
16
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
16
@@ -XXX,XX +XXX,XX @@
17
bool rettobase = false;
17
@3same .... ... . . . size:2 .... .... .... . q:1 . . .... \
18
bool exc_secure = false;
18
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp
19
bool return_to_secure;
19
20
+ bool ftype;
20
+VHADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 0 .... @3same
21
+ bool restore_s16_s31;
21
+VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same
22
22
VQADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 1 .... @3same
23
/* If we're not in Handler mode then jumps to magic exception-exit
23
VQADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 1 .... @3same
24
* addresses don't have magic behaviour. However for the v8M
24
25
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
25
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
26
excret);
26
index XXXXXXX..XXXXXXX 100644
27
}
27
--- a/target/arm/translate-neon.inc.c
28
28
+++ b/target/arm/translate-neon.inc.c
29
+ ftype = excret & R_V7M_EXCRET_FTYPE_MASK;
29
@@ -XXX,XX +XXX,XX @@ DO_3SAME_64_ENV(VQSHL_S64, gen_helper_neon_qshl_s64)
30
DO_3SAME_64_ENV(VQSHL_U64, gen_helper_neon_qshl_u64)
31
DO_3SAME_64_ENV(VQRSHL_S64, gen_helper_neon_qrshl_s64)
32
DO_3SAME_64_ENV(VQRSHL_U64, gen_helper_neon_qrshl_u64)
30
+
33
+
31
+ if (!arm_feature(env, ARM_FEATURE_VFP) && !ftype) {
34
+#define DO_3SAME_32(INSN, FUNC) \
32
+ qemu_log_mask(LOG_GUEST_ERROR, "M profile: zero FTYPE in exception "
35
+ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
33
+ "exit PC value 0x%" PRIx32 " is UNPREDICTABLE "
36
+ uint32_t rn_ofs, uint32_t rm_ofs, \
34
+ "if FPU not present\n",
37
+ uint32_t oprsz, uint32_t maxsz) \
35
+ excret);
38
+ { \
36
+ ftype = true;
39
+ static const GVecGen3 ops[4] = { \
40
+ { .fni4 = gen_helper_neon_##FUNC##8 }, \
41
+ { .fni4 = gen_helper_neon_##FUNC##16 }, \
42
+ { .fni4 = gen_helper_neon_##FUNC##32 }, \
43
+ { 0 }, \
44
+ }; \
45
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops[vece]); \
46
+ } \
47
+ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \
48
+ { \
49
+ if (a->size > 2) { \
50
+ return false; \
51
+ } \
52
+ return do_3same(s, a, gen_##INSN##_3s); \
37
+ }
53
+ }
38
+
54
+
39
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
55
+DO_3SAME_32(VHADD_S, hadd_s)
40
/* EXC_RETURN.ES validation check (R_SMFL). We must do this before
56
+DO_3SAME_32(VHADD_U, hadd_u)
41
* we pick which FAULTMASK to clear.
57
diff --git a/target/arm/translate.c b/target/arm/translate.c
42
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
58
index XXXXXXX..XXXXXXX 100644
43
*/
59
--- a/target/arm/translate.c
44
write_v7m_control_spsel_for_secstate(env, return_to_sp_process, exc_secure);
60
+++ b/target/arm/translate.c
45
61
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
46
+ /*
62
case NEON_3R_VML:
47
+ * Clear scratch FP values left in caller saved registers; this
63
case NEON_3R_VSHL:
48
+ * must happen before any kind of tail chaining.
64
case NEON_3R_SHA:
49
+ */
65
+ case NEON_3R_VHADD:
50
+ if ((env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_CLRONRET_MASK) &&
66
/* Already handled by decodetree */
51
+ (env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK)) {
67
return 1;
52
+ if (env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_LSPACT_MASK) {
53
+ env->v7m.sfsr |= R_V7M_SFSR_LSERR_MASK;
54
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
55
+ qemu_log_mask(CPU_LOG_INT, "...taking SecureFault on existing "
56
+ "stackframe: error during lazy state deactivation\n");
57
+ v7m_exception_taken(cpu, excret, true, false);
58
+ return;
59
+ } else {
60
+ /* Clear s0..s15 and FPSCR */
61
+ int i;
62
+
63
+ for (i = 0; i < 16; i += 2) {
64
+ *aa32_vfp_dreg(env, i / 2) = 0;
65
+ }
66
+ vfp_set_fpscr(env, 0);
67
+ }
68
+ }
69
+
70
if (sfault) {
71
env->v7m.sfsr |= R_V7M_SFSR_INVER_MASK;
72
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
73
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
74
}
75
}
68
}
76
69
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
77
+ if (!ftype) {
70
tmp2 = neon_load_reg(rm, pass);
78
+ /* FP present and we need to handle it */
71
}
79
+ if (!return_to_secure &&
72
switch (op) {
80
+ (env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_LSPACT_MASK)) {
73
- case NEON_3R_VHADD:
81
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
74
- GEN_NEON_INTEGER_OP(hadd);
82
+ env->v7m.sfsr |= R_V7M_SFSR_LSERR_MASK;
75
- break;
83
+ qemu_log_mask(CPU_LOG_INT,
76
case NEON_3R_VRHADD:
84
+ "...taking SecureFault on existing stackframe: "
77
GEN_NEON_INTEGER_OP(rhadd);
85
+ "Secure LSPACT set but exception return is "
78
break;
86
+ "not to secure state\n");
87
+ v7m_exception_taken(cpu, excret, true, false);
88
+ return;
89
+ }
90
+
91
+ restore_s16_s31 = return_to_secure &&
92
+ (env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_TS_MASK);
93
+
94
+ if (env->v7m.fpccr[return_to_secure] & R_V7M_FPCCR_LSPACT_MASK) {
95
+ /* State in FPU is still valid, just clear LSPACT */
96
+ env->v7m.fpccr[return_to_secure] &= ~R_V7M_FPCCR_LSPACT_MASK;
97
+ } else {
98
+ int i;
99
+ uint32_t fpscr;
100
+ bool cpacr_pass, nsacr_pass;
101
+
102
+ cpacr_pass = v7m_cpacr_pass(env, return_to_secure,
103
+ return_to_priv);
104
+ nsacr_pass = return_to_secure ||
105
+ extract32(env->v7m.nsacr, 10, 1);
106
+
107
+ if (!cpacr_pass) {
108
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
109
+ return_to_secure);
110
+ env->v7m.cfsr[return_to_secure] |= R_V7M_CFSR_NOCP_MASK;
111
+ qemu_log_mask(CPU_LOG_INT,
112
+ "...taking UsageFault on existing "
113
+ "stackframe: CPACR.CP10 prevents unstacking "
114
+ "FP regs\n");
115
+ v7m_exception_taken(cpu, excret, true, false);
116
+ return;
117
+ } else if (!nsacr_pass) {
118
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, true);
119
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_INVPC_MASK;
120
+ qemu_log_mask(CPU_LOG_INT,
121
+ "...taking Secure UsageFault on existing "
122
+ "stackframe: NSACR.CP10 prevents unstacking "
123
+ "FP regs\n");
124
+ v7m_exception_taken(cpu, excret, true, false);
125
+ return;
126
+ }
127
+
128
+ for (i = 0; i < (restore_s16_s31 ? 32 : 16); i += 2) {
129
+ uint32_t slo, shi;
130
+ uint64_t dn;
131
+ uint32_t faddr = frameptr + 0x20 + 4 * i;
132
+
133
+ if (i >= 16) {
134
+ faddr += 8; /* Skip the slot for the FPSCR */
135
+ }
136
+
137
+ pop_ok = pop_ok &&
138
+ v7m_stack_read(cpu, &slo, faddr, mmu_idx) &&
139
+ v7m_stack_read(cpu, &shi, faddr + 4, mmu_idx);
140
+
141
+ if (!pop_ok) {
142
+ break;
143
+ }
144
+
145
+ dn = (uint64_t)shi << 32 | slo;
146
+ *aa32_vfp_dreg(env, i / 2) = dn;
147
+ }
148
+ pop_ok = pop_ok &&
149
+ v7m_stack_read(cpu, &fpscr, frameptr + 0x60, mmu_idx);
150
+ if (pop_ok) {
151
+ vfp_set_fpscr(env, fpscr);
152
+ }
153
+ if (!pop_ok) {
154
+ /*
155
+ * These regs are 0 if security extension present;
156
+ * otherwise merely UNKNOWN. We zero always.
157
+ */
158
+ for (i = 0; i < (restore_s16_s31 ? 32 : 16); i += 2) {
159
+ *aa32_vfp_dreg(env, i / 2) = 0;
160
+ }
161
+ vfp_set_fpscr(env, 0);
162
+ }
163
+ }
164
+ }
165
+ env->v7m.control[M_REG_S] = FIELD_DP32(env->v7m.control[M_REG_S],
166
+ V7M_CONTROL, FPCA, !ftype);
167
+
168
/* Commit to consuming the stack frame */
169
frameptr += 0x20;
170
+ if (!ftype) {
171
+ frameptr += 0x48;
172
+ if (restore_s16_s31) {
173
+ frameptr += 0x40;
174
+ }
175
+ }
176
/* Undo stack alignment (the SPREALIGN bit indicates that the original
177
* pre-exception SP was not 8-aligned and we added a padding word to
178
* align it, so we undo this by ORing in the bit that increases it
179
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
180
*frame_sp_p = frameptr;
181
}
182
/* This xpsr_write() will invalidate frame_sp_p as it may switch stack */
183
- xpsr_write(env, xpsr, ~XPSR_SPREALIGN);
184
+ xpsr_write(env, xpsr, ~(XPSR_SPREALIGN | XPSR_SFPA));
185
+
186
+ if (env->v7m.secure) {
187
+ bool sfpa = xpsr & XPSR_SFPA;
188
+
189
+ env->v7m.control[M_REG_S] = FIELD_DP32(env->v7m.control[M_REG_S],
190
+ V7M_CONTROL, SFPA, sfpa);
191
+ }
192
193
/* The restored xPSR exception field will be zero if we're
194
* resuming in Thread mode. If that doesn't match what the
195
--
79
--
196
2.20.1
80
2.20.1
197
81
198
82
diff view generated by jsdifflib
1
Move the NS TBFLAG down from bit 19 to bit 6, which has not
1
Convert the Neon VABA and VABD insns in the 3-reg-same group to
2
been used since commit c1e3781090b9d36c60 in 2015, when we
2
decodetree.
3
started passing the entire MMU index in the TB flags rather
4
than just a 'privilege level' bit.
5
6
This rearrangement is not strictly necessary, but means that
7
we can put M-profile-only bits next to each other rather
8
than scattered across the flag word.
9
3
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20190416125744.27770-17-peter.maydell@linaro.org
6
Message-id: 20200512163904.10918-6-peter.maydell@linaro.org
13
---
7
---
14
target/arm/cpu.h | 11 ++++++-----
8
target/arm/neon-dp.decode | 6 ++++++
15
1 file changed, 6 insertions(+), 5 deletions(-)
9
target/arm/translate-neon.inc.c | 4 ++++
10
target/arm/translate.c | 22 ++--------------------
11
3 files changed, 12 insertions(+), 20 deletions(-)
16
12
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
15
--- a/target/arm/neon-dp.decode
20
+++ b/target/arm/cpu.h
16
+++ b/target/arm/neon-dp.decode
21
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_ANY, BE_DATA, 23, 1)
17
@@ -XXX,XX +XXX,XX @@ VMAX_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 0 .... @3same
22
FIELD(TBFLAG_A32, THUMB, 0, 1)
18
VMIN_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 1 .... @3same
23
FIELD(TBFLAG_A32, VECLEN, 1, 3)
19
VMIN_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 1 .... @3same
24
FIELD(TBFLAG_A32, VECSTRIDE, 4, 2)
20
25
+/*
21
+VABD_S_3s 1111 001 0 0 . .. .... .... 0111 . . . 0 .... @3same
26
+ * Indicates whether cp register reads and writes by guest code should access
22
+VABD_U_3s 1111 001 1 0 . .. .... .... 0111 . . . 0 .... @3same
27
+ * the secure or nonsecure bank of banked registers; note that this is not
23
+
28
+ * the same thing as the current security state of the processor!
24
+VABA_S_3s 1111 001 0 0 . .. .... .... 0111 . . . 1 .... @3same
29
+ */
25
+VABA_U_3s 1111 001 1 0 . .. .... .... 0111 . . . 1 .... @3same
30
+FIELD(TBFLAG_A32, NS, 6, 1)
26
+
31
FIELD(TBFLAG_A32, VFPEN, 7, 1)
27
VADD_3s 1111 001 0 0 . .. .... .... 1000 . . . 0 .... @3same
32
FIELD(TBFLAG_A32, CONDEXEC, 8, 8)
28
VSUB_3s 1111 001 1 0 . .. .... .... 1000 . . . 0 .... @3same
33
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
29
34
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
30
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
35
* checks on the other bits at runtime
31
index XXXXXXX..XXXXXXX 100644
36
*/
32
--- a/target/arm/translate-neon.inc.c
37
FIELD(TBFLAG_A32, XSCALE_CPAR, 17, 2)
33
+++ b/target/arm/translate-neon.inc.c
38
-/* Indicates whether cp register reads and writes by guest code should access
34
@@ -XXX,XX +XXX,XX @@ DO_3SAME_NO_SZ_3(VMUL, tcg_gen_gvec_mul)
39
- * the secure or nonsecure bank of banked registers; note that this is not
35
DO_3SAME_NO_SZ_3(VMLA, gen_gvec_mla)
40
- * the same thing as the current security state of the processor!
36
DO_3SAME_NO_SZ_3(VMLS, gen_gvec_mls)
41
- */
37
DO_3SAME_NO_SZ_3(VTST, gen_gvec_cmtst)
42
-FIELD(TBFLAG_A32, NS, 19, 1)
38
+DO_3SAME_NO_SZ_3(VABD_S, gen_gvec_sabd)
43
/* For M profile only, Handler (ie not Thread) mode */
39
+DO_3SAME_NO_SZ_3(VABA_S, gen_gvec_saba)
44
FIELD(TBFLAG_A32, HANDLER, 21, 1)
40
+DO_3SAME_NO_SZ_3(VABD_U, gen_gvec_uabd)
45
/* For M profile only, whether we should generate stack-limit checks */
41
+DO_3SAME_NO_SZ_3(VABA_U, gen_gvec_uaba)
42
43
#define DO_3SAME_CMP(INSN, COND) \
44
static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
45
diff --git a/target/arm/translate.c b/target/arm/translate.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/translate.c
48
+++ b/target/arm/translate.c
49
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
50
/* VQRDMLSH : handled by decodetree */
51
return 1;
52
53
- case NEON_3R_VABD:
54
- if (u) {
55
- gen_gvec_uabd(size, rd_ofs, rn_ofs, rm_ofs,
56
- vec_size, vec_size);
57
- } else {
58
- gen_gvec_sabd(size, rd_ofs, rn_ofs, rm_ofs,
59
- vec_size, vec_size);
60
- }
61
- return 0;
62
-
63
- case NEON_3R_VABA:
64
- if (u) {
65
- gen_gvec_uaba(size, rd_ofs, rn_ofs, rm_ofs,
66
- vec_size, vec_size);
67
- } else {
68
- gen_gvec_saba(size, rd_ofs, rn_ofs, rm_ofs,
69
- vec_size, vec_size);
70
- }
71
- return 0;
72
-
73
case NEON_3R_VADD_VSUB:
74
case NEON_3R_LOGIC:
75
case NEON_3R_VMAX:
76
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
77
case NEON_3R_VSHL:
78
case NEON_3R_SHA:
79
case NEON_3R_VHADD:
80
+ case NEON_3R_VABD:
81
+ case NEON_3R_VABA:
82
/* Already handled by decodetree */
83
return 1;
84
}
46
--
85
--
47
2.20.1
86
2.20.1
48
87
49
88
diff view generated by jsdifflib
1
For v8M floating point support, transitions from Secure
1
Convert the Neon VRHADD and VHSUB 3-reg-same insns to decodetree.
2
to Non-secure state via BLNS and BLXNS must clear the
2
(These are all the other insns in 3-reg-same which were using
3
CONTROL.SFPA bit. (This corresponds to the pseudocode
3
GEN_NEON_INTEGER_OP() and which are not pairwise or
4
BranchToNS() function.)
4
reversed-operands.)
5
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20190416125744.27770-13-peter.maydell@linaro.org
8
Message-id: 20200512163904.10918-7-peter.maydell@linaro.org
9
---
9
---
10
target/arm/helper.c | 4 ++++
10
target/arm/neon-dp.decode | 6 ++++++
11
1 file changed, 4 insertions(+)
11
target/arm/translate-neon.inc.c | 4 ++++
12
target/arm/translate.c | 8 ++------
13
3 files changed, 12 insertions(+), 6 deletions(-)
12
14
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
15
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
17
--- a/target/arm/neon-dp.decode
16
+++ b/target/arm/helper.c
18
+++ b/target/arm/neon-dp.decode
17
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_bxns)(CPUARMState *env, uint32_t dest)
19
@@ -XXX,XX +XXX,XX @@ VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same
18
/* translate.c should have made BXNS UNDEF unless we're secure */
20
VQADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 1 .... @3same
19
assert(env->v7m.secure);
21
VQADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 1 .... @3same
20
22
21
+ if (!(dest & 1)) {
23
+VRHADD_S_3s 1111 001 0 0 . .. .... .... 0001 . . . 0 .... @3same
22
+ env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
24
+VRHADD_U_3s 1111 001 1 0 . .. .... .... 0001 . . . 0 .... @3same
23
+ }
25
+
24
switch_v7m_security_state(env, dest & 1);
26
@3same_logic .... ... . . . .. .... .... .... . q:1 .. .... \
25
env->thumb = 1;
27
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp size=0
26
env->regs[15] = dest & ~1;
28
27
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_blxns)(CPUARMState *env, uint32_t dest)
29
@@ -XXX,XX +XXX,XX @@ VBSL_3s 1111 001 1 0 . 01 .... .... 0001 ... 1 .... @3same_logic
28
*/
30
VBIT_3s 1111 001 1 0 . 10 .... .... 0001 ... 1 .... @3same_logic
29
write_v7m_exception(env, 1);
31
VBIF_3s 1111 001 1 0 . 11 .... .... 0001 ... 1 .... @3same_logic
30
}
32
31
+ env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
33
+VHSUB_S_3s 1111 001 0 0 . .. .... .... 0010 . . . 0 .... @3same
32
switch_v7m_security_state(env, 0);
34
+VHSUB_U_3s 1111 001 1 0 . .. .... .... 0010 . . . 0 .... @3same
33
env->thumb = 1;
35
+
34
env->regs[15] = dest;
36
VQSUB_S_3s 1111 001 0 0 . .. .... .... 0010 . . . 1 .... @3same
37
VQSUB_U_3s 1111 001 1 0 . .. .... .... 0010 . . . 1 .... @3same
38
39
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/translate-neon.inc.c
42
+++ b/target/arm/translate-neon.inc.c
43
@@ -XXX,XX +XXX,XX @@ DO_3SAME_64_ENV(VQRSHL_U64, gen_helper_neon_qrshl_u64)
44
45
DO_3SAME_32(VHADD_S, hadd_s)
46
DO_3SAME_32(VHADD_U, hadd_u)
47
+DO_3SAME_32(VHSUB_S, hsub_s)
48
+DO_3SAME_32(VHSUB_U, hsub_u)
49
+DO_3SAME_32(VRHADD_S, rhadd_s)
50
+DO_3SAME_32(VRHADD_U, rhadd_u)
51
diff --git a/target/arm/translate.c b/target/arm/translate.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/translate.c
54
+++ b/target/arm/translate.c
55
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
56
case NEON_3R_VSHL:
57
case NEON_3R_SHA:
58
case NEON_3R_VHADD:
59
+ case NEON_3R_VRHADD:
60
+ case NEON_3R_VHSUB:
61
case NEON_3R_VABD:
62
case NEON_3R_VABA:
63
/* Already handled by decodetree */
64
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
65
tmp2 = neon_load_reg(rm, pass);
66
}
67
switch (op) {
68
- case NEON_3R_VRHADD:
69
- GEN_NEON_INTEGER_OP(rhadd);
70
- break;
71
- case NEON_3R_VHSUB:
72
- GEN_NEON_INTEGER_OP(hsub);
73
- break;
74
case NEON_3R_VQSHL:
75
GEN_NEON_INTEGER_OP_ENV(qshl);
76
break;
35
--
77
--
36
2.20.1
78
2.20.1
37
79
38
80
diff view generated by jsdifflib
1
Handle floating point registers in exception entry.
1
Convert the VQSHL, VRSHL and VQRSHL insns in the 3-reg-same
2
This corresponds to the FP-specific parts of the pseudocode
2
group to decodetree. We have already implemented the size==0b11
3
functions ActivateException() and PushStack().
3
case of these insns; this commit handles the remaining sizes.
4
5
We defer the code corresponding to UpdateFPCCR() to a later patch.
6
4
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20190416125744.27770-11-peter.maydell@linaro.org
7
Message-id: 20200512163904.10918-8-peter.maydell@linaro.org
10
---
8
---
11
target/arm/helper.c | 98 +++++++++++++++++++++++++++++++++++++++++++--
9
target/arm/neon-dp.decode | 30 ++++++++++++++++++-----
12
1 file changed, 95 insertions(+), 3 deletions(-)
10
target/arm/translate-neon.inc.c | 43 +++++++++++++++++++++++++++++++++
11
target/arm/translate.c | 22 +++--------------
12
3 files changed, 70 insertions(+), 25 deletions(-)
13
13
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
16
--- a/target/arm/neon-dp.decode
17
+++ b/target/arm/helper.c
17
+++ b/target/arm/neon-dp.decode
18
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
18
@@ -XXX,XX +XXX,XX @@ VSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 0 .... @3same_rev
19
switch_v7m_security_state(env, targets_secure);
19
@3same_64_rev .... ... . . . 11 .... .... .... . q:1 . . .... \
20
write_v7m_control_spsel(env, 0);
20
&3same vm=%vn_dp vn=%vm_dp vd=%vd_dp size=3
21
arm_clear_exclusive(env);
21
22
+ /* Clear SFPA and FPCA (has no effect if no FPU) */
22
-VQSHL_S64_3s 1111 001 0 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev
23
+ env->v7m.control[M_REG_S] &=
23
-VQSHL_U64_3s 1111 001 1 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev
24
+ ~(R_V7M_CONTROL_FPCA_MASK | R_V7M_CONTROL_SFPA_MASK);
24
-VRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev
25
/* Clear IT bits */
25
-VRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev
26
env->condexec_bits = 0;
26
-VQRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev
27
env->regs[14] = lr;
27
-VQRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev
28
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
28
+{
29
uint32_t xpsr = xpsr_read(env);
29
+ VQSHL_S64_3s 1111 001 0 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev
30
uint32_t frameptr = env->regs[13];
30
+ VQSHL_S_3s 1111 001 0 0 . .. .... .... 0100 . . . 1 .... @3same_rev
31
ARMMMUIdx mmu_idx = arm_mmu_idx(env);
31
+}
32
+ uint32_t framesize;
32
+{
33
+ bool nsacr_cp10 = extract32(env->v7m.nsacr, 10, 1);
33
+ VQSHL_U64_3s 1111 001 1 0 . .. .... .... 0100 . . . 1 .... @3same_64_rev
34
+
34
+ VQSHL_U_3s 1111 001 1 0 . .. .... .... 0100 . . . 1 .... @3same_rev
35
+ if ((env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) &&
35
+}
36
+ (env->v7m.secure || nsacr_cp10)) {
36
+{
37
+ if (env->v7m.secure &&
37
+ VRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev
38
+ env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_TS_MASK) {
38
+ VRSHL_S_3s 1111 001 0 0 . .. .... .... 0101 . . . 0 .... @3same_rev
39
+ framesize = 0xa8;
39
+}
40
+ } else {
40
+{
41
+ framesize = 0x68;
41
+ VRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 0 .... @3same_64_rev
42
+ }
42
+ VRSHL_U_3s 1111 001 1 0 . .. .... .... 0101 . . . 0 .... @3same_rev
43
+ } else {
43
+}
44
+ framesize = 0x20;
44
+{
45
+ }
45
+ VQRSHL_S64_3s 1111 001 0 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev
46
46
+ VQRSHL_S_3s 1111 001 0 0 . .. .... .... 0101 . . . 1 .... @3same_rev
47
/* Align stack pointer if the guest wants that */
47
+}
48
if ((frameptr & 4) &&
48
+{
49
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
49
+ VQRSHL_U64_3s 1111 001 1 0 . .. .... .... 0101 . . . 1 .... @3same_64_rev
50
xpsr |= XPSR_SPREALIGN;
50
+ VQRSHL_U_3s 1111 001 1 0 . .. .... .... 0101 . . . 1 .... @3same_rev
51
+}
52
53
VMAX_S_3s 1111 001 0 0 . .. .... .... 0110 . . . 0 .... @3same
54
VMAX_U_3s 1111 001 1 0 . .. .... .... 0110 . . . 0 .... @3same
55
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/translate-neon.inc.c
58
+++ b/target/arm/translate-neon.inc.c
59
@@ -XXX,XX +XXX,XX @@ DO_3SAME_64_ENV(VQRSHL_U64, gen_helper_neon_qrshl_u64)
60
return do_3same(s, a, gen_##INSN##_3s); \
51
}
61
}
52
62
53
- frameptr -= 0x20;
63
+/*
54
+ xpsr &= ~XPSR_SFPA;
64
+ * Some helper functions need to be passed the cpu_env. In order
55
+ if (env->v7m.secure &&
65
+ * to use those with the gvec APIs like tcg_gen_gvec_3() we need
56
+ (env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)) {
66
+ * to create wrapper functions whose prototype is a NeonGenTwoOpFn()
57
+ xpsr |= XPSR_SFPA;
67
+ * and which call a NeonGenTwoOpEnvFn().
68
+ */
69
+#define WRAP_ENV_FN(WRAPNAME, FUNC) \
70
+ static void WRAPNAME(TCGv_i32 d, TCGv_i32 n, TCGv_i32 m) \
71
+ { \
72
+ FUNC(d, cpu_env, n, m); \
58
+ }
73
+ }
59
+
74
+
60
+ frameptr -= framesize;
75
+#define DO_3SAME_32_ENV(INSN, FUNC) \
61
76
+ WRAP_ENV_FN(gen_##INSN##_tramp8, gen_helper_neon_##FUNC##8); \
62
if (arm_feature(env, ARM_FEATURE_V8)) {
77
+ WRAP_ENV_FN(gen_##INSN##_tramp16, gen_helper_neon_##FUNC##16); \
63
uint32_t limit = v7m_sp_limit(env);
78
+ WRAP_ENV_FN(gen_##INSN##_tramp32, gen_helper_neon_##FUNC##32); \
64
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
79
+ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
65
v7m_stack_write(cpu, frameptr + 24, env->regs[15], mmu_idx, false) &&
80
+ uint32_t rn_ofs, uint32_t rm_ofs, \
66
v7m_stack_write(cpu, frameptr + 28, xpsr, mmu_idx, false);
81
+ uint32_t oprsz, uint32_t maxsz) \
67
82
+ { \
68
+ if (env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) {
83
+ static const GVecGen3 ops[4] = { \
69
+ /* FPU is active, try to save its registers */
84
+ { .fni4 = gen_##INSN##_tramp8 }, \
70
+ bool fpccr_s = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK;
85
+ { .fni4 = gen_##INSN##_tramp16 }, \
71
+ bool lspact = env->v7m.fpccr[fpccr_s] & R_V7M_FPCCR_LSPACT_MASK;
86
+ { .fni4 = gen_##INSN##_tramp32 }, \
72
+
87
+ { 0 }, \
73
+ if (lspact && arm_feature(env, ARM_FEATURE_M_SECURITY)) {
88
+ }; \
74
+ qemu_log_mask(CPU_LOG_INT,
89
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops[vece]); \
75
+ "...SecureFault because LSPACT and FPCA both set\n");
90
+ } \
76
+ env->v7m.sfsr |= R_V7M_SFSR_LSERR_MASK;
91
+ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \
77
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
92
+ { \
78
+ } else if (!env->v7m.secure && !nsacr_cp10) {
93
+ if (a->size > 2) { \
79
+ qemu_log_mask(CPU_LOG_INT,
94
+ return false; \
80
+ "...Secure UsageFault with CFSR.NOCP because "
95
+ } \
81
+ "NSACR.CP10 prevents stacking FP regs\n");
96
+ return do_3same(s, a, gen_##INSN##_3s); \
82
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, M_REG_S);
83
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_NOCP_MASK;
84
+ } else {
85
+ if (!(env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_LSPEN_MASK)) {
86
+ /* Lazy stacking disabled, save registers now */
87
+ int i;
88
+ bool cpacr_pass = v7m_cpacr_pass(env, env->v7m.secure,
89
+ arm_current_el(env) != 0);
90
+
91
+ if (stacked_ok && !cpacr_pass) {
92
+ /*
93
+ * Take UsageFault if CPACR forbids access. The pseudocode
94
+ * here does a full CheckCPEnabled() but we know the NSACR
95
+ * check can never fail as we have already handled that.
96
+ */
97
+ qemu_log_mask(CPU_LOG_INT,
98
+ "...UsageFault with CFSR.NOCP because "
99
+ "CPACR.CP10 prevents stacking FP regs\n");
100
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
101
+ env->v7m.secure);
102
+ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_NOCP_MASK;
103
+ stacked_ok = false;
104
+ }
105
+
106
+ for (i = 0; i < ((framesize == 0xa8) ? 32 : 16); i += 2) {
107
+ uint64_t dn = *aa32_vfp_dreg(env, i / 2);
108
+ uint32_t faddr = frameptr + 0x20 + 4 * i;
109
+ uint32_t slo = extract64(dn, 0, 32);
110
+ uint32_t shi = extract64(dn, 32, 32);
111
+
112
+ if (i >= 16) {
113
+ faddr += 8; /* skip the slot for the FPSCR */
114
+ }
115
+ stacked_ok = stacked_ok &&
116
+ v7m_stack_write(cpu, faddr, slo, mmu_idx, false) &&
117
+ v7m_stack_write(cpu, faddr + 4, shi, mmu_idx, false);
118
+ }
119
+ stacked_ok = stacked_ok &&
120
+ v7m_stack_write(cpu, frameptr + 0x60,
121
+ vfp_get_fpscr(env), mmu_idx, false);
122
+ if (cpacr_pass) {
123
+ for (i = 0; i < ((framesize == 0xa8) ? 32 : 16); i += 2) {
124
+ *aa32_vfp_dreg(env, i / 2) = 0;
125
+ }
126
+ vfp_set_fpscr(env, 0);
127
+ }
128
+ } else {
129
+ /* Lazy stacking enabled, save necessary info to stack later */
130
+ /* TODO : equivalent of UpdateFPCCR() pseudocode */
131
+ }
132
+ }
133
+ }
97
+ }
134
+
98
+
135
/*
99
DO_3SAME_32(VHADD_S, hadd_s)
136
* If we broke a stack limit then SP was already updated earlier;
100
DO_3SAME_32(VHADD_U, hadd_u)
137
* otherwise we update SP regardless of whether any of the stack
101
DO_3SAME_32(VHSUB_S, hsub_s)
138
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
102
DO_3SAME_32(VHSUB_U, hsub_u)
139
103
DO_3SAME_32(VRHADD_S, rhadd_s)
140
if (arm_feature(env, ARM_FEATURE_V8)) {
104
DO_3SAME_32(VRHADD_U, rhadd_u)
141
lr = R_V7M_EXCRET_RES1_MASK |
105
+DO_3SAME_32(VRSHL_S, rshl_s)
142
- R_V7M_EXCRET_DCRS_MASK |
106
+DO_3SAME_32(VRSHL_U, rshl_u)
143
- R_V7M_EXCRET_FTYPE_MASK;
107
+
144
+ R_V7M_EXCRET_DCRS_MASK;
108
+DO_3SAME_32_ENV(VQSHL_S, qshl_s)
145
/* The S bit indicates whether we should return to Secure
109
+DO_3SAME_32_ENV(VQSHL_U, qshl_u)
146
* or NonSecure (ie our current state).
110
+DO_3SAME_32_ENV(VQRSHL_S, qrshl_s)
147
* The ES bit indicates whether we're taking this exception
111
+DO_3SAME_32_ENV(VQRSHL_U, qrshl_u)
148
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
112
diff --git a/target/arm/translate.c b/target/arm/translate.c
149
if (env->v7m.secure) {
113
index XXXXXXX..XXXXXXX 100644
150
lr |= R_V7M_EXCRET_S_MASK;
114
--- a/target/arm/translate.c
115
+++ b/target/arm/translate.c
116
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
117
case NEON_3R_VHSUB:
118
case NEON_3R_VABD:
119
case NEON_3R_VABA:
120
+ case NEON_3R_VQSHL:
121
+ case NEON_3R_VRSHL:
122
+ case NEON_3R_VQRSHL:
123
/* Already handled by decodetree */
124
return 1;
151
}
125
}
152
+ if (!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK)) {
126
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
153
+ lr |= R_V7M_EXCRET_FTYPE_MASK;
127
}
154
+ }
128
pairwise = 0;
155
} else {
129
switch (op) {
156
lr = R_V7M_EXCRET_RES1_MASK |
130
- case NEON_3R_VQSHL:
157
R_V7M_EXCRET_S_MASK |
131
- case NEON_3R_VRSHL:
132
- case NEON_3R_VQRSHL:
133
- {
134
- int rtmp;
135
- /* Shift instruction operands are reversed. */
136
- rtmp = rn;
137
- rn = rm;
138
- rm = rtmp;
139
- }
140
- break;
141
case NEON_3R_VPADD_VQRDMLAH:
142
case NEON_3R_VPMAX:
143
case NEON_3R_VPMIN:
144
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
145
tmp2 = neon_load_reg(rm, pass);
146
}
147
switch (op) {
148
- case NEON_3R_VQSHL:
149
- GEN_NEON_INTEGER_OP_ENV(qshl);
150
- break;
151
- case NEON_3R_VRSHL:
152
- GEN_NEON_INTEGER_OP(rshl);
153
- break;
154
- case NEON_3R_VQRSHL:
155
- GEN_NEON_INTEGER_OP_ENV(qrshl);
156
break;
157
case NEON_3R_VPMAX:
158
GEN_NEON_INTEGER_OP(pmax);
158
--
159
--
159
2.20.1
160
2.20.1
160
161
161
162
diff view generated by jsdifflib
1
Like AArch64, M-profile floating point has no FPEXC enable
1
Convert the Neon integer VPMAX and VPMIN 3-reg-same insns to
2
bit to gate floating point; so always set the VFPEN TB flag.
2
decodetree. These are 'pairwise' operations.
3
4
M-profile also has CPACR and NSACR similar to A-profile;
5
they behave slightly differently:
6
* the CPACR is banked between Secure and Non-Secure
7
* if the NSACR forces a trap then this is taken to
8
the Secure state, not the Non-Secure state
9
10
Honour the CPACR and NSACR settings. The NSACR handling
11
requires us to borrow the exception.target_el field
12
(usually meaningless for M profile) to distinguish the
13
NOCP UsageFault taken to Secure state from the more
14
usual fault taken to the current security state.
15
3
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 20190416125744.27770-6-peter.maydell@linaro.org
6
Message-id: 20200512163904.10918-9-peter.maydell@linaro.org
19
---
7
---
20
target/arm/helper.c | 55 +++++++++++++++++++++++++++++++++++++++---
8
target/arm/neon-dp.decode | 9 +++++
21
target/arm/translate.c | 10 ++++++--
9
target/arm/translate-neon.inc.c | 71 +++++++++++++++++++++++++++++++++
22
2 files changed, 60 insertions(+), 5 deletions(-)
10
target/arm/translate.c | 17 +-------
11
3 files changed, 82 insertions(+), 15 deletions(-)
23
12
24
diff --git a/target/arm/helper.c b/target/arm/helper.c
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
25
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/helper.c
15
--- a/target/arm/neon-dp.decode
27
+++ b/target/arm/helper.c
16
+++ b/target/arm/neon-dp.decode
28
@@ -XXX,XX +XXX,XX @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx,
17
@@ -XXX,XX +XXX,XX @@
29
return target_el;
18
@3same .... ... . . . size:2 .... .... .... . q:1 . . .... \
30
}
19
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp
31
20
32
+/*
21
+@3same_q0 .... ... . . . size:2 .... .... .... . 0 . . .... \
33
+ * Return true if the v7M CPACR permits access to the FPU for the specified
22
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0
34
+ * security state and privilege level.
23
+
35
+ */
24
VHADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 0 .... @3same
36
+static bool v7m_cpacr_pass(CPUARMState *env, bool is_secure, bool is_priv)
25
VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same
26
VQADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 1 .... @3same
27
@@ -XXX,XX +XXX,XX @@ VMLS_3s 1111 001 1 0 . .. .... .... 1001 . . . 0 .... @3same
28
VMUL_3s 1111 001 0 0 . .. .... .... 1001 . . . 1 .... @3same
29
VMUL_p_3s 1111 001 1 0 . .. .... .... 1001 . . . 1 .... @3same
30
31
+VPMAX_S_3s 1111 001 0 0 . .. .... .... 1010 . . . 0 .... @3same_q0
32
+VPMAX_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 0 .... @3same_q0
33
+
34
+VPMIN_S_3s 1111 001 0 0 . .. .... .... 1010 . . . 1 .... @3same_q0
35
+VPMIN_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 1 .... @3same_q0
36
+
37
VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same
38
39
SHA1_3s 1111 001 0 0 . optype:2 .... .... 1100 . 1 . 0 .... \
40
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/translate-neon.inc.c
43
+++ b/target/arm/translate-neon.inc.c
44
@@ -XXX,XX +XXX,XX @@ DO_3SAME_32_ENV(VQSHL_S, qshl_s)
45
DO_3SAME_32_ENV(VQSHL_U, qshl_u)
46
DO_3SAME_32_ENV(VQRSHL_S, qrshl_s)
47
DO_3SAME_32_ENV(VQRSHL_U, qrshl_u)
48
+
49
+static bool do_3same_pair(DisasContext *s, arg_3same *a, NeonGenTwoOpFn *fn)
37
+{
50
+{
38
+ switch (extract32(env->v7m.cpacr[is_secure], 20, 2)) {
51
+ /* Operations handled pairwise 32 bits at a time */
39
+ case 0:
52
+ TCGv_i32 tmp, tmp2, tmp3;
40
+ case 2: /* UNPREDICTABLE: we treat like 0 */
53
+
54
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
41
+ return false;
55
+ return false;
42
+ case 1:
56
+ }
43
+ return is_priv;
57
+
44
+ case 3:
58
+ /* UNDEF accesses to D16-D31 if they don't exist. */
59
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
60
+ ((a->vd | a->vn | a->vm) & 0x10)) {
61
+ return false;
62
+ }
63
+
64
+ if (a->size == 3) {
65
+ return false;
66
+ }
67
+
68
+ if (!vfp_access_check(s)) {
45
+ return true;
69
+ return true;
46
+ default:
47
+ g_assert_not_reached();
48
+ }
70
+ }
71
+
72
+ assert(a->q == 0); /* enforced by decode patterns */
73
+
74
+ /*
75
+ * Note that we have to be careful not to clobber the source operands
76
+ * in the "vm == vd" case by storing the result of the first pass too
77
+ * early. Since Q is 0 there are always just two passes, so instead
78
+ * of a complicated loop over each pass we just unroll.
79
+ */
80
+ tmp = neon_load_reg(a->vn, 0);
81
+ tmp2 = neon_load_reg(a->vn, 1);
82
+ fn(tmp, tmp, tmp2);
83
+ tcg_temp_free_i32(tmp2);
84
+
85
+ tmp3 = neon_load_reg(a->vm, 0);
86
+ tmp2 = neon_load_reg(a->vm, 1);
87
+ fn(tmp3, tmp3, tmp2);
88
+ tcg_temp_free_i32(tmp2);
89
+
90
+ neon_store_reg(a->vd, 0, tmp);
91
+ neon_store_reg(a->vd, 1, tmp3);
92
+ return true;
49
+}
93
+}
50
+
94
+
51
static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value,
95
+#define DO_3SAME_PAIR(INSN, func) \
52
ARMMMUIdx mmu_idx, bool ignfault)
96
+ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \
53
{
97
+ { \
54
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
98
+ static NeonGenTwoOpFn * const fns[] = { \
55
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_UNDEFINSTR_MASK;
99
+ gen_helper_neon_##func##8, \
56
break;
100
+ gen_helper_neon_##func##16, \
57
case EXCP_NOCP:
101
+ gen_helper_neon_##func##32, \
58
- armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
102
+ }; \
59
- env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_NOCP_MASK;
103
+ if (a->size > 2) { \
60
+ {
104
+ return false; \
61
+ /*
105
+ } \
62
+ * NOCP might be directed to something other than the current
106
+ return do_3same_pair(s, a, fns[a->size]); \
63
+ * security state if this fault is because of NSACR; we indicate
64
+ * the target security state using exception.target_el.
65
+ */
66
+ int target_secstate;
67
+
68
+ if (env->exception.target_el == 3) {
69
+ target_secstate = M_REG_S;
70
+ } else {
71
+ target_secstate = env->v7m.secure;
72
+ }
73
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, target_secstate);
74
+ env->v7m.cfsr[target_secstate] |= R_V7M_CFSR_NOCP_MASK;
75
break;
76
+ }
77
case EXCP_INVSTATE:
78
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
79
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_INVSTATE_MASK;
80
@@ -XXX,XX +XXX,XX @@ int fp_exception_el(CPUARMState *env, int cur_el)
81
return 0;
82
}
83
84
+ if (arm_feature(env, ARM_FEATURE_M)) {
85
+ /* CPACR can cause a NOCP UsageFault taken to current security state */
86
+ if (!v7m_cpacr_pass(env, env->v7m.secure, cur_el != 0)) {
87
+ return 1;
88
+ }
89
+
90
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY) && !env->v7m.secure) {
91
+ if (!extract32(env->v7m.nsacr, 10, 1)) {
92
+ /* FP insns cause a NOCP UsageFault taken to Secure */
93
+ return 3;
94
+ }
95
+ }
96
+
97
+ return 0;
98
+ }
107
+ }
99
+
108
+
100
/* The CPACR controls traps to EL1, or PL1 if we're 32 bit:
109
+/* 32-bit pairwise ops end up the same as the elementwise versions. */
101
* 0, 2 : trap EL0 and EL1/PL1 accesses
110
+#define gen_helper_neon_pmax_s32 tcg_gen_smax_i32
102
* 1 : trap only EL0 accesses
111
+#define gen_helper_neon_pmax_u32 tcg_gen_umax_i32
103
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
112
+#define gen_helper_neon_pmin_s32 tcg_gen_smin_i32
104
flags = FIELD_DP32(flags, TBFLAG_A32, SCTLR_B, arm_sctlr_b(env));
113
+#define gen_helper_neon_pmin_u32 tcg_gen_umin_i32
105
flags = FIELD_DP32(flags, TBFLAG_A32, NS, !access_secure_reg(env));
114
+
106
if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)
115
+DO_3SAME_PAIR(VPMAX_S, pmax_s)
107
- || arm_el_is_aa64(env, 1)) {
116
+DO_3SAME_PAIR(VPMIN_S, pmin_s)
108
+ || arm_el_is_aa64(env, 1) || arm_feature(env, ARM_FEATURE_M)) {
117
+DO_3SAME_PAIR(VPMAX_U, pmax_u)
109
flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
118
+DO_3SAME_PAIR(VPMIN_U, pmin_u)
110
}
111
flags = FIELD_DP32(flags, TBFLAG_A32, XSCALE_CPAR, env->cp15.c15_cpar);
112
diff --git a/target/arm/translate.c b/target/arm/translate.c
119
diff --git a/target/arm/translate.c b/target/arm/translate.c
113
index XXXXXXX..XXXXXXX 100644
120
index XXXXXXX..XXXXXXX 100644
114
--- a/target/arm/translate.c
121
--- a/target/arm/translate.c
115
+++ b/target/arm/translate.c
122
+++ b/target/arm/translate.c
116
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
123
@@ -XXX,XX +XXX,XX @@ static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
117
* for attempts to execute invalid vfp/neon encodings with FP disabled.
118
*/
119
if (s->fp_excp_el) {
120
- gen_exception_insn(s, 4, EXCP_UDEF,
121
- syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
122
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
123
+ gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
124
+ s->fp_excp_el);
125
+ } else {
126
+ gen_exception_insn(s, 4, EXCP_UDEF,
127
+ syn_fp_access_trap(1, 0xe, false),
128
+ s->fp_excp_el);
129
+ }
130
return 0;
131
}
124
}
132
125
}
126
127
-/* 32-bit pairwise ops end up the same as the elementwise versions. */
128
-#define gen_helper_neon_pmax_s32 tcg_gen_smax_i32
129
-#define gen_helper_neon_pmax_u32 tcg_gen_umax_i32
130
-#define gen_helper_neon_pmin_s32 tcg_gen_smin_i32
131
-#define gen_helper_neon_pmin_u32 tcg_gen_umin_i32
132
-
133
#define GEN_NEON_INTEGER_OP_ENV(name) do { \
134
switch ((size << 1) | u) { \
135
case 0: \
136
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
137
case NEON_3R_VQSHL:
138
case NEON_3R_VRSHL:
139
case NEON_3R_VQRSHL:
140
+ case NEON_3R_VPMAX:
141
+ case NEON_3R_VPMIN:
142
/* Already handled by decodetree */
143
return 1;
144
}
145
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
146
pairwise = 0;
147
switch (op) {
148
case NEON_3R_VPADD_VQRDMLAH:
149
- case NEON_3R_VPMAX:
150
- case NEON_3R_VPMIN:
151
pairwise = 1;
152
break;
153
case NEON_3R_FLOAT_ARITH:
154
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
155
tmp2 = neon_load_reg(rm, pass);
156
}
157
switch (op) {
158
- break;
159
- case NEON_3R_VPMAX:
160
- GEN_NEON_INTEGER_OP(pmax);
161
- break;
162
- case NEON_3R_VPMIN:
163
- GEN_NEON_INTEGER_OP(pmin);
164
- break;
165
case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
166
if (!u) { /* VQDMULH */
167
switch (size) {
133
--
168
--
134
2.20.1
169
2.20.1
135
170
136
171
diff view generated by jsdifflib
1
If the floating point extension is present, then the SG instruction
1
Convert the Neon integer VPADD 3-reg-same insns to decodetree. These
2
must clear the CONTROL_S.SFPA bit. Implement this.
2
are 'pairwise' operations. (Note that VQRDMLAH, which shares the
3
3
same primary opcode but has U=1, has already been converted.)
4
(On a no-FPU system the bit will always be zero, so we don't need
5
to make the clearing of the bit conditional on ARM_FEATURE_VFP.)
6
4
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20190416125744.27770-8-peter.maydell@linaro.org
7
Message-id: 20200512163904.10918-10-peter.maydell@linaro.org
10
---
8
---
11
target/arm/helper.c | 1 +
9
target/arm/neon-dp.decode | 2 ++
12
1 file changed, 1 insertion(+)
10
target/arm/translate-neon.inc.c | 2 ++
11
target/arm/translate.c | 19 +------------------
12
3 files changed, 5 insertions(+), 18 deletions(-)
13
13
14
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper.c
16
--- a/target/arm/neon-dp.decode
17
+++ b/target/arm/helper.c
17
+++ b/target/arm/neon-dp.decode
18
@@ -XXX,XX +XXX,XX @@ static bool v7m_handle_execute_nsc(ARMCPU *cpu)
18
@@ -XXX,XX +XXX,XX @@ VPMAX_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 0 .... @3same_q0
19
qemu_log_mask(CPU_LOG_INT, "...really an SG instruction at 0x%08" PRIx32
19
VPMIN_S_3s 1111 001 0 0 . .. .... .... 1010 . . . 1 .... @3same_q0
20
", executing it\n", env->regs[15]);
20
VPMIN_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 1 .... @3same_q0
21
env->regs[14] &= ~1;
21
22
+ env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
22
+VPADD_3s 1111 001 0 0 . .. .... .... 1011 . . . 1 .... @3same_q0
23
switch_v7m_security_state(env, true);
23
+
24
xpsr_write(env, 0, XPSR_IT);
24
VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same
25
env->regs[15] += 4;
25
26
SHA1_3s 1111 001 0 0 . optype:2 .... .... 1100 . 1 . 0 .... \
27
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/translate-neon.inc.c
30
+++ b/target/arm/translate-neon.inc.c
31
@@ -XXX,XX +XXX,XX @@ static bool do_3same_pair(DisasContext *s, arg_3same *a, NeonGenTwoOpFn *fn)
32
#define gen_helper_neon_pmax_u32 tcg_gen_umax_i32
33
#define gen_helper_neon_pmin_s32 tcg_gen_smin_i32
34
#define gen_helper_neon_pmin_u32 tcg_gen_umin_i32
35
+#define gen_helper_neon_padd_u32 tcg_gen_add_i32
36
37
DO_3SAME_PAIR(VPMAX_S, pmax_s)
38
DO_3SAME_PAIR(VPMIN_S, pmin_s)
39
DO_3SAME_PAIR(VPMAX_U, pmax_u)
40
DO_3SAME_PAIR(VPMIN_U, pmin_u)
41
+DO_3SAME_PAIR(VPADD, padd_u)
42
diff --git a/target/arm/translate.c b/target/arm/translate.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/translate.c
45
+++ b/target/arm/translate.c
46
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
47
return 1;
48
}
49
switch (op) {
50
- case NEON_3R_VPADD_VQRDMLAH:
51
- if (!u) {
52
- break; /* VPADD */
53
- }
54
- /* VQRDMLAH : handled by decodetree */
55
- return 1;
56
-
57
case NEON_3R_VFM_VQRDMLSH:
58
if (!u) {
59
/* VFM, VFMS */
60
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
61
case NEON_3R_VQRSHL:
62
case NEON_3R_VPMAX:
63
case NEON_3R_VPMIN:
64
+ case NEON_3R_VPADD_VQRDMLAH:
65
/* Already handled by decodetree */
66
return 1;
67
}
68
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
69
}
70
pairwise = 0;
71
switch (op) {
72
- case NEON_3R_VPADD_VQRDMLAH:
73
- pairwise = 1;
74
- break;
75
case NEON_3R_FLOAT_ARITH:
76
pairwise = (u && size < 2); /* if VPADD (float) */
77
break;
78
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
79
}
80
}
81
break;
82
- case NEON_3R_VPADD_VQRDMLAH:
83
- switch (size) {
84
- case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
85
- case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
86
- case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
87
- default: abort();
88
- }
89
- break;
90
case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
91
{
92
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
26
--
93
--
27
2.20.1
94
2.20.1
28
95
29
96
diff view generated by jsdifflib
1
The TailChain() pseudocode specifies that a tail chaining
1
Convert the Neon VQDMULH and VQRDMULH 3-reg-same insns to
2
exception should sanitize the excReturn all-ones bits and
2
decodetree. These are the last integer operations in the
3
(if there is no FPU) the excReturn FType bits; we weren't
3
3-reg-same group.
4
doing this.
5
4
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20190416125744.27770-14-peter.maydell@linaro.org
7
Message-id: 20200512163904.10918-11-peter.maydell@linaro.org
9
---
8
---
10
target/arm/helper.c | 8 ++++++++
9
target/arm/neon-dp.decode | 3 +++
11
1 file changed, 8 insertions(+)
10
target/arm/translate-neon.inc.c | 24 ++++++++++++++++++++++++
11
target/arm/translate.c | 24 +-----------------------
12
3 files changed, 28 insertions(+), 23 deletions(-)
12
13
13
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper.c
16
--- a/target/arm/neon-dp.decode
16
+++ b/target/arm/helper.c
17
+++ b/target/arm/neon-dp.decode
17
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
18
@@ -XXX,XX +XXX,XX @@ VPMAX_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 0 .... @3same_q0
18
qemu_log_mask(CPU_LOG_INT, "...taking pending %s exception %d\n",
19
VPMIN_S_3s 1111 001 0 0 . .. .... .... 1010 . . . 1 .... @3same_q0
19
targets_secure ? "secure" : "nonsecure", exc);
20
VPMIN_U_3s 1111 001 1 0 . .. .... .... 1010 . . . 1 .... @3same_q0
20
21
21
+ if (dotailchain) {
22
+VQDMULH_3s 1111 001 0 0 . .. .... .... 1011 . . . 0 .... @3same
22
+ /* Sanitize LR FType and PREFIX bits */
23
+VQRDMULH_3s 1111 001 1 0 . .. .... .... 1011 . . . 0 .... @3same
23
+ if (!arm_feature(env, ARM_FEATURE_VFP)) {
24
+
24
+ lr |= R_V7M_EXCRET_FTYPE_MASK;
25
VPADD_3s 1111 001 0 0 . .. .... .... 1011 . . . 1 .... @3same_q0
25
+ }
26
26
+ lr = deposit32(lr, 24, 8, 0xff);
27
VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same
28
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/translate-neon.inc.c
31
+++ b/target/arm/translate-neon.inc.c
32
@@ -XXX,XX +XXX,XX @@ DO_3SAME_PAIR(VPMIN_S, pmin_s)
33
DO_3SAME_PAIR(VPMAX_U, pmax_u)
34
DO_3SAME_PAIR(VPMIN_U, pmin_u)
35
DO_3SAME_PAIR(VPADD, padd_u)
36
+
37
+#define DO_3SAME_VQDMULH(INSN, FUNC) \
38
+ WRAP_ENV_FN(gen_##INSN##_tramp16, gen_helper_neon_##FUNC##_s16); \
39
+ WRAP_ENV_FN(gen_##INSN##_tramp32, gen_helper_neon_##FUNC##_s32); \
40
+ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
41
+ uint32_t rn_ofs, uint32_t rm_ofs, \
42
+ uint32_t oprsz, uint32_t maxsz) \
43
+ { \
44
+ static const GVecGen3 ops[2] = { \
45
+ { .fni4 = gen_##INSN##_tramp16 }, \
46
+ { .fni4 = gen_##INSN##_tramp32 }, \
47
+ }; \
48
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops[vece - 1]); \
49
+ } \
50
+ static bool trans_##INSN##_3s(DisasContext *s, arg_3same *a) \
51
+ { \
52
+ if (a->size != 1 && a->size != 2) { \
53
+ return false; \
54
+ } \
55
+ return do_3same(s, a, gen_##INSN##_3s); \
27
+ }
56
+ }
28
+
57
+
29
if (arm_feature(env, ARM_FEATURE_V8)) {
58
+DO_3SAME_VQDMULH(VQDMULH, qdmulh)
30
if (arm_feature(env, ARM_FEATURE_M_SECURITY) &&
59
+DO_3SAME_VQDMULH(VQRDMULH, qrdmulh)
31
(lr & R_V7M_EXCRET_S_MASK)) {
60
diff --git a/target/arm/translate.c b/target/arm/translate.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/translate.c
63
+++ b/target/arm/translate.c
64
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
65
case NEON_3R_VPMAX:
66
case NEON_3R_VPMIN:
67
case NEON_3R_VPADD_VQRDMLAH:
68
+ case NEON_3R_VQDMULH_VQRDMULH:
69
/* Already handled by decodetree */
70
return 1;
71
}
72
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
73
tmp2 = neon_load_reg(rm, pass);
74
}
75
switch (op) {
76
- case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
77
- if (!u) { /* VQDMULH */
78
- switch (size) {
79
- case 1:
80
- gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
81
- break;
82
- case 2:
83
- gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
84
- break;
85
- default: abort();
86
- }
87
- } else { /* VQRDMULH */
88
- switch (size) {
89
- case 1:
90
- gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
91
- break;
92
- case 2:
93
- gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
94
- break;
95
- default: abort();
96
- }
97
- }
98
- break;
99
case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
100
{
101
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
32
--
102
--
33
2.20.1
103
2.20.1
34
104
35
105
diff view generated by jsdifflib
1
Implement the VLLDM instruction for v7M for the FPU present cas.
1
Convert the Neon VADD, VSUB, VABD 3-reg-same insns to decodetree.
2
We already have gvec helpers for addition and subtraction, but must
3
add one for fabd.
2
4
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20190416125744.27770-26-peter.maydell@linaro.org
7
Message-id: 20200512163904.10918-12-peter.maydell@linaro.org
6
---
8
---
7
target/arm/helper.h | 1 +
9
target/arm/helper.h | 3 ++-
8
target/arm/helper.c | 54 ++++++++++++++++++++++++++++++++++++++++++
10
target/arm/neon-dp.decode | 8 ++++++++
9
target/arm/translate.c | 2 +-
11
target/arm/neon_helper.c | 7 -------
10
3 files changed, 56 insertions(+), 1 deletion(-)
12
target/arm/translate-neon.inc.c | 28 ++++++++++++++++++++++++++++
13
target/arm/translate.c | 10 +++-------
14
target/arm/vec_helper.c | 7 +++++++
15
6 files changed, 48 insertions(+), 15 deletions(-)
11
16
12
diff --git a/target/arm/helper.h b/target/arm/helper.h
17
diff --git a/target/arm/helper.h b/target/arm/helper.h
13
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/helper.h
19
--- a/target/arm/helper.h
15
+++ b/target/arm/helper.h
20
+++ b/target/arm/helper.h
16
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(v7m_tt, i32, env, i32, i32)
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(neon_qneg_s16, TCG_CALL_NO_RWG, i32, env, i32)
17
DEF_HELPER_1(v7m_preserve_fp_state, void, env)
22
DEF_HELPER_FLAGS_2(neon_qneg_s32, TCG_CALL_NO_RWG, i32, env, i32)
18
23
DEF_HELPER_FLAGS_2(neon_qneg_s64, TCG_CALL_NO_RWG, i64, env, i64)
19
DEF_HELPER_2(v7m_vlstm, void, env, i32)
24
20
+DEF_HELPER_2(v7m_vlldm, void, env, i32)
25
-DEF_HELPER_3(neon_abd_f32, i32, i32, i32, ptr)
21
26
DEF_HELPER_3(neon_ceq_f32, i32, i32, i32, ptr)
22
DEF_HELPER_2(v8m_stackcheck, void, env, i32)
27
DEF_HELPER_3(neon_cge_f32, i32, i32, i32, ptr)
23
28
DEF_HELPER_3(neon_cgt_f32, i32, i32, i32, ptr)
24
diff --git a/target/arm/helper.c b/target/arm/helper.c
29
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(gvec_fmul_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
30
DEF_HELPER_FLAGS_5(gvec_fmul_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
31
DEF_HELPER_FLAGS_5(gvec_fmul_d, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
32
33
+DEF_HELPER_FLAGS_5(gvec_fabd_s, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, ptr, i32)
34
+
35
DEF_HELPER_FLAGS_5(gvec_ftsmul_h, TCG_CALL_NO_RWG,
36
void, ptr, ptr, ptr, ptr, i32)
37
DEF_HELPER_FLAGS_5(gvec_ftsmul_s, TCG_CALL_NO_RWG,
38
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
25
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/helper.c
40
--- a/target/arm/neon-dp.decode
27
+++ b/target/arm/helper.c
41
+++ b/target/arm/neon-dp.decode
28
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_vlstm)(CPUARMState *env, uint32_t fptr)
42
@@ -XXX,XX +XXX,XX @@
29
g_assert_not_reached();
43
@3same_q0 .... ... . . . size:2 .... .... .... . 0 . . .... \
44
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0
45
46
+# For FP insns the high bit of 'size' is used as part of opcode decode
47
+@3same_fp .... ... . . . . size:1 .... .... .... . q:1 . . .... \
48
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp
49
+
50
VHADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 0 .... @3same
51
VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same
52
VQADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 1 .... @3same
53
@@ -XXX,XX +XXX,XX @@ SHA256SU1_3s 1111 001 1 0 . 10 .... .... 1100 . 1 . 0 .... \
54
vm=%vm_dp vn=%vn_dp vd=%vd_dp
55
56
VQRDMLSH_3s 1111 001 1 0 . .. .... .... 1100 ... 1 .... @3same
57
+
58
+VADD_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 0 .... @3same_fp
59
+VSUB_fp_3s 1111 001 0 0 . 1 . .... .... 1101 ... 0 .... @3same_fp
60
+VABD_fp_3s 1111 001 1 0 . 1 . .... .... 1101 ... 0 .... @3same_fp
61
diff --git a/target/arm/neon_helper.c b/target/arm/neon_helper.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/target/arm/neon_helper.c
64
+++ b/target/arm/neon_helper.c
65
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(neon_qneg_s64)(CPUARMState *env, uint64_t x)
30
}
66
}
31
67
32
+void HELPER(v7m_vlldm)(CPUARMState *env, uint32_t fptr)
68
/* NEON Float helpers. */
33
+{
69
-uint32_t HELPER(neon_abd_f32)(uint32_t a, uint32_t b, void *fpstp)
34
+ /* translate.c should never generate calls here in user-only mode */
70
-{
35
+ g_assert_not_reached();
71
- float_status *fpst = fpstp;
36
+}
72
- float32 f0 = make_float32(a);
73
- float32 f1 = make_float32(b);
74
- return float32_val(float32_abs(float32_sub(f0, f1, fpst)));
75
-}
76
77
/* Floating point comparisons produce an integer result.
78
* Note that EQ doesn't signal InvalidOp for QNaNs but GE and GT do.
79
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/target/arm/translate-neon.inc.c
82
+++ b/target/arm/translate-neon.inc.c
83
@@ -XXX,XX +XXX,XX @@ DO_3SAME_PAIR(VPADD, padd_u)
84
85
DO_3SAME_VQDMULH(VQDMULH, qdmulh)
86
DO_3SAME_VQDMULH(VQRDMULH, qrdmulh)
37
+
87
+
38
uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op)
88
+/*
39
{
89
+ * For all the functions using this macro, size == 1 means fp16,
40
/* The TT instructions can be used by unprivileged code, but in
90
+ * which is an architecture extension we don't implement yet.
41
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_vlstm)(CPUARMState *env, uint32_t fptr)
91
+ */
42
env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_FPCA_MASK;
92
+#define DO_3S_FP_GVEC(INSN,FUNC) \
43
}
93
+ static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
44
94
+ uint32_t rn_ofs, uint32_t rm_ofs, \
45
+void HELPER(v7m_vlldm)(CPUARMState *env, uint32_t fptr)
95
+ uint32_t oprsz, uint32_t maxsz) \
46
+{
96
+ { \
47
+ /* fptr is the value of Rn, the frame pointer we load the FP regs from */
97
+ TCGv_ptr fpst = get_fpstatus_ptr(1); \
48
+ assert(env->v7m.secure);
98
+ tcg_gen_gvec_3_ptr(rd_ofs, rn_ofs, rm_ofs, fpst, \
49
+
99
+ oprsz, maxsz, 0, FUNC); \
50
+ if (!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)) {
100
+ tcg_temp_free_ptr(fpst); \
51
+ return;
101
+ } \
102
+ static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
103
+ { \
104
+ if (a->size != 0) { \
105
+ /* TODO fp16 support */ \
106
+ return false; \
107
+ } \
108
+ return do_3same(s, a, gen_##INSN##_3s); \
52
+ }
109
+ }
53
+
110
+
54
+ /* Check access to the coprocessor is permitted */
55
+ if (!v7m_cpacr_pass(env, true, arm_current_el(env) != 0)) {
56
+ raise_exception_ra(env, EXCP_NOCP, 0, 1, GETPC());
57
+ }
58
+
111
+
59
+ if (env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_LSPACT_MASK) {
112
+DO_3S_FP_GVEC(VADD, gen_helper_gvec_fadd_s)
60
+ /* State in FP is still valid */
113
+DO_3S_FP_GVEC(VSUB, gen_helper_gvec_fsub_s)
61
+ env->v7m.fpccr[M_REG_S] &= ~R_V7M_FPCCR_LSPACT_MASK;
114
+DO_3S_FP_GVEC(VABD, gen_helper_gvec_fabd_s)
62
+ } else {
63
+ bool ts = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_TS_MASK;
64
+ int i;
65
+ uint32_t fpscr;
66
+
67
+ if (fptr & 7) {
68
+ raise_exception_ra(env, EXCP_UNALIGNED, 0, 1, GETPC());
69
+ }
70
+
71
+ for (i = 0; i < (ts ? 32 : 16); i += 2) {
72
+ uint32_t slo, shi;
73
+ uint64_t dn;
74
+ uint32_t faddr = fptr + 4 * i;
75
+
76
+ if (i >= 16) {
77
+ faddr += 8; /* skip the slot for the FPSCR */
78
+ }
79
+
80
+ slo = cpu_ldl_data(env, faddr);
81
+ shi = cpu_ldl_data(env, faddr + 4);
82
+
83
+ dn = (uint64_t) shi << 32 | slo;
84
+ *aa32_vfp_dreg(env, i / 2) = dn;
85
+ }
86
+ fpscr = cpu_ldl_data(env, fptr + 0x40);
87
+ vfp_set_fpscr(env, fpscr);
88
+ }
89
+
90
+ env->v7m.control[M_REG_S] |= R_V7M_CONTROL_FPCA_MASK;
91
+}
92
+
93
static bool v7m_push_stack(ARMCPU *cpu)
94
{
95
/* Do the "set up stack frame" part of exception entry,
96
diff --git a/target/arm/translate.c b/target/arm/translate.c
115
diff --git a/target/arm/translate.c b/target/arm/translate.c
97
index XXXXXXX..XXXXXXX 100644
116
index XXXXXXX..XXXXXXX 100644
98
--- a/target/arm/translate.c
117
--- a/target/arm/translate.c
99
+++ b/target/arm/translate.c
118
+++ b/target/arm/translate.c
100
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
119
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
101
TCGv_i32 fptr = load_reg(s, rn);
120
switch (op) {
102
121
case NEON_3R_FLOAT_ARITH:
103
if (extract32(insn, 20, 1)) {
122
pairwise = (u && size < 2); /* if VPADD (float) */
104
- /* VLLDM */
123
+ if (!pairwise) {
105
+ gen_helper_v7m_vlldm(cpu_env, fptr);
124
+ return 1; /* handled by decodetree */
106
} else {
125
+ }
107
gen_helper_v7m_vlstm(cpu_env, fptr);
126
break;
108
}
127
case NEON_3R_FLOAT_MINMAX:
128
pairwise = u; /* if VPMIN/VPMAX (float) */
129
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
130
{
131
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
132
switch ((u << 2) | size) {
133
- case 0: /* VADD */
134
case 4: /* VPADD */
135
gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
136
break;
137
- case 2: /* VSUB */
138
- gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
139
- break;
140
- case 6: /* VABD */
141
- gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
142
- break;
143
default:
144
abort();
145
}
146
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/target/arm/vec_helper.c
149
+++ b/target/arm/vec_helper.c
150
@@ -XXX,XX +XXX,XX @@ static float64 float64_ftsmul(float64 op1, uint64_t op2, float_status *stat)
151
return result;
152
}
153
154
+static float32 float32_abd(float32 op1, float32 op2, float_status *stat)
155
+{
156
+ return float32_abs(float32_sub(op1, op2, stat));
157
+}
158
+
159
#define DO_3OP(NAME, FUNC, TYPE) \
160
void HELPER(NAME)(void *vd, void *vn, void *vm, void *stat, uint32_t desc) \
161
{ \
162
@@ -XXX,XX +XXX,XX @@ DO_3OP(gvec_ftsmul_h, float16_ftsmul, float16)
163
DO_3OP(gvec_ftsmul_s, float32_ftsmul, float32)
164
DO_3OP(gvec_ftsmul_d, float64_ftsmul, float64)
165
166
+DO_3OP(gvec_fabd_s, float32_abd, float32)
167
+
168
#ifdef TARGET_AARCH64
169
170
DO_3OP(gvec_recps_h, helper_recpsf_f16, float16)
109
--
171
--
110
2.20.1
172
2.20.1
111
173
112
174
diff view generated by jsdifflib
1
For M-profile the MVFR* ID registers are memory mapped, in the
1
Convert the Neon float VPMIN, VPMAX and VPADD 3-reg-same insns to
2
range we implement via the NVIC. Allow them to be read.
2
decodetree. These are the only remaining 'pairwise' operations,
3
(If the CPU has no FPU, these registers are defined to be RAZ.)
3
so we can delete the pairwise-specific bits of the old decoder's
4
for-each-element loop now.
4
5
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20190416125744.27770-3-peter.maydell@linaro.org
8
Message-id: 20200512163904.10918-13-peter.maydell@linaro.org
8
---
9
---
9
hw/intc/armv7m_nvic.c | 6 ++++++
10
target/arm/neon-dp.decode | 5 +++
10
1 file changed, 6 insertions(+)
11
target/arm/translate-neon.inc.c | 63 +++++++++++++++++++++++++++++++++
11
12
target/arm/translate.c | 63 +++++----------------------------
12
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
13
3 files changed, 76 insertions(+), 55 deletions(-)
14
15
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
13
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/intc/armv7m_nvic.c
17
--- a/target/arm/neon-dp.decode
15
+++ b/hw/intc/armv7m_nvic.c
18
+++ b/target/arm/neon-dp.decode
16
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
19
@@ -XXX,XX +XXX,XX @@
17
return 0;
20
# For FP insns the high bit of 'size' is used as part of opcode decode
18
}
21
@3same_fp .... ... . . . . size:1 .... .... .... . q:1 . . .... \
19
return cpu->env.v7m.sfar;
22
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp
20
+ case 0xf40: /* MVFR0 */
23
+@3same_fp_q0 .... ... . . . . size:1 .... .... .... . 0 . . .... \
21
+ return cpu->isar.mvfr0;
24
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0
22
+ case 0xf44: /* MVFR1 */
25
23
+ return cpu->isar.mvfr1;
26
VHADD_S_3s 1111 001 0 0 . .. .... .... 0000 . . . 0 .... @3same
24
+ case 0xf48: /* MVFR2 */
27
VHADD_U_3s 1111 001 1 0 . .. .... .... 0000 . . . 0 .... @3same
25
+ return cpu->isar.mvfr2;
28
@@ -XXX,XX +XXX,XX @@ VQRDMLSH_3s 1111 001 1 0 . .. .... .... 1100 ... 1 .... @3same
26
default:
29
27
bad_offset:
30
VADD_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 0 .... @3same_fp
28
qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad read offset 0x%x\n", offset);
31
VSUB_fp_3s 1111 001 0 0 . 1 . .... .... 1101 ... 0 .... @3same_fp
32
+VPADD_fp_3s 1111 001 1 0 . 0 . .... .... 1101 ... 0 .... @3same_fp_q0
33
VABD_fp_3s 1111 001 1 0 . 1 . .... .... 1101 ... 0 .... @3same_fp
34
+VPMAX_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 0 .... @3same_fp_q0
35
+VPMIN_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 0 .... @3same_fp_q0
36
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/translate-neon.inc.c
39
+++ b/target/arm/translate-neon.inc.c
40
@@ -XXX,XX +XXX,XX @@ DO_3SAME_VQDMULH(VQRDMULH, qrdmulh)
41
DO_3S_FP_GVEC(VADD, gen_helper_gvec_fadd_s)
42
DO_3S_FP_GVEC(VSUB, gen_helper_gvec_fsub_s)
43
DO_3S_FP_GVEC(VABD, gen_helper_gvec_fabd_s)
44
+
45
+static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn)
46
+{
47
+ /* FP operations handled pairwise 32 bits at a time */
48
+ TCGv_i32 tmp, tmp2, tmp3;
49
+ TCGv_ptr fpstatus;
50
+
51
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
52
+ return false;
53
+ }
54
+
55
+ /* UNDEF accesses to D16-D31 if they don't exist. */
56
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
57
+ ((a->vd | a->vn | a->vm) & 0x10)) {
58
+ return false;
59
+ }
60
+
61
+ if (!vfp_access_check(s)) {
62
+ return true;
63
+ }
64
+
65
+ assert(a->q == 0); /* enforced by decode patterns */
66
+
67
+ /*
68
+ * Note that we have to be careful not to clobber the source operands
69
+ * in the "vm == vd" case by storing the result of the first pass too
70
+ * early. Since Q is 0 there are always just two passes, so instead
71
+ * of a complicated loop over each pass we just unroll.
72
+ */
73
+ fpstatus = get_fpstatus_ptr(1);
74
+ tmp = neon_load_reg(a->vn, 0);
75
+ tmp2 = neon_load_reg(a->vn, 1);
76
+ fn(tmp, tmp, tmp2, fpstatus);
77
+ tcg_temp_free_i32(tmp2);
78
+
79
+ tmp3 = neon_load_reg(a->vm, 0);
80
+ tmp2 = neon_load_reg(a->vm, 1);
81
+ fn(tmp3, tmp3, tmp2, fpstatus);
82
+ tcg_temp_free_i32(tmp2);
83
+ tcg_temp_free_ptr(fpstatus);
84
+
85
+ neon_store_reg(a->vd, 0, tmp);
86
+ neon_store_reg(a->vd, 1, tmp3);
87
+ return true;
88
+}
89
+
90
+/*
91
+ * For all the functions using this macro, size == 1 means fp16,
92
+ * which is an architecture extension we don't implement yet.
93
+ */
94
+#define DO_3S_FP_PAIR(INSN,FUNC) \
95
+ static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
96
+ { \
97
+ if (a->size != 0) { \
98
+ /* TODO fp16 support */ \
99
+ return false; \
100
+ } \
101
+ return do_3same_fp_pair(s, a, FUNC); \
102
+ }
103
+
104
+DO_3S_FP_PAIR(VPADD, gen_helper_vfp_adds)
105
+DO_3S_FP_PAIR(VPMAX, gen_helper_vfp_maxs)
106
+DO_3S_FP_PAIR(VPMIN, gen_helper_vfp_mins)
107
diff --git a/target/arm/translate.c b/target/arm/translate.c
108
index XXXXXXX..XXXXXXX 100644
109
--- a/target/arm/translate.c
110
+++ b/target/arm/translate.c
111
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
112
int shift;
113
int pass;
114
int count;
115
- int pairwise;
116
int u;
117
int vec_size;
118
uint32_t imm;
119
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
120
case NEON_3R_VPMIN:
121
case NEON_3R_VPADD_VQRDMLAH:
122
case NEON_3R_VQDMULH_VQRDMULH:
123
+ case NEON_3R_FLOAT_ARITH:
124
/* Already handled by decodetree */
125
return 1;
126
}
127
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
128
/* 64-bit element instructions: handled by decodetree */
129
return 1;
130
}
131
- pairwise = 0;
132
switch (op) {
133
- case NEON_3R_FLOAT_ARITH:
134
- pairwise = (u && size < 2); /* if VPADD (float) */
135
- if (!pairwise) {
136
- return 1; /* handled by decodetree */
137
- }
138
- break;
139
case NEON_3R_FLOAT_MINMAX:
140
- pairwise = u; /* if VPMIN/VPMAX (float) */
141
+ if (u) {
142
+ return 1; /* VPMIN/VPMAX handled by decodetree */
143
+ }
144
break;
145
case NEON_3R_FLOAT_CMP:
146
if (!u && size) {
147
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
148
break;
149
}
150
151
- if (pairwise && q) {
152
- /* All the pairwise insns UNDEF if Q is set */
153
- return 1;
154
- }
155
-
156
for (pass = 0; pass < (q ? 4 : 2); pass++) {
157
158
- if (pairwise) {
159
- /* Pairwise. */
160
- if (pass < 1) {
161
- tmp = neon_load_reg(rn, 0);
162
- tmp2 = neon_load_reg(rn, 1);
163
- } else {
164
- tmp = neon_load_reg(rm, 0);
165
- tmp2 = neon_load_reg(rm, 1);
166
- }
167
- } else {
168
- /* Elementwise. */
169
- tmp = neon_load_reg(rn, pass);
170
- tmp2 = neon_load_reg(rm, pass);
171
- }
172
+ /* Elementwise. */
173
+ tmp = neon_load_reg(rn, pass);
174
+ tmp2 = neon_load_reg(rm, pass);
175
switch (op) {
176
- case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
177
- {
178
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
179
- switch ((u << 2) | size) {
180
- case 4: /* VPADD */
181
- gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
182
- break;
183
- default:
184
- abort();
185
- }
186
- tcg_temp_free_ptr(fpstatus);
187
- break;
188
- }
189
case NEON_3R_FLOAT_MULTIPLY:
190
{
191
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
192
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
193
}
194
tcg_temp_free_i32(tmp2);
195
196
- /* Save the result. For elementwise operations we can put it
197
- straight into the destination register. For pairwise operations
198
- we have to be careful to avoid clobbering the source operands. */
199
- if (pairwise && rd == rm) {
200
- neon_store_scratch(pass, tmp);
201
- } else {
202
- neon_store_reg(rd, pass, tmp);
203
- }
204
+ neon_store_reg(rd, pass, tmp);
205
206
} /* for pass */
207
- if (pairwise && rd == rm) {
208
- for (pass = 0; pass < (q ? 4 : 2); pass++) {
209
- tmp = neon_load_scratch(pass);
210
- neon_store_reg(rd, pass, tmp);
211
- }
212
- }
213
/* End of 3 register same size operations. */
214
} else if (insn & (1 << 4)) {
215
if ((insn & 0x00380080) != 0) {
29
--
216
--
30
2.20.1
217
2.20.1
31
218
32
219
diff view generated by jsdifflib
1
In the v7M architecture, if an exception is generated in the process
1
Convert the Neon integer VMUL, VMLA, and VMLS 3-reg-same inssn to
2
of doing the lazy stacking of FP registers, the handling of
2
decodetree.
3
possible escalation to HardFault is treated differently to the normal
4
approach: it works based on the saved information about exception
5
readiness that was stored in the FPCCR when the stack frame was
6
created. Provide a new function armv7m_nvic_set_pending_lazyfp()
7
which pends exceptions during lazy stacking, and implements
8
this logic.
9
3
10
This corresponds to the pseudocode TakePreserveFPException().
4
We don't have a gvec helper for multiply-accumulate, so VMLA and VMLS
5
need a loop function do_3same_fp(). This takes a reads_vd parameter
6
to do_3same_fp() which tells it to load the old value into vd before
7
calling the callback function, in the same way that the do_vfp_3op_sp()
8
and do_vfp_3op_dp() functions in translate-vfp.inc.c work. (The
9
only uses in this patch pass reads_vd == true, but later commits
10
will use reads_vd == false.)
11
12
This conversion fixes in passing an underdecoding for VMUL
13
(originally reported by Fredrik Strupe <fredrik@strupe.net>): bit 1
14
of the 'size' field must be 0. The old decoder didn't enforce this,
15
but the decodetree pattern does.
16
17
The gen_VMLA_fp_reg() function performs the addition operation
18
with the operands in the opposite order to the old decoder:
19
since Neon sets 'default NaN mode' float32_add operations are
20
commutative so there is no behaviour difference, but putting
21
them this way around matches the Arm ARM pseudocode and the
22
required operation order for the subtraction in gen_VMLS_fp_reg().
11
23
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20190416125744.27770-22-peter.maydell@linaro.org
26
Message-id: 20200512163904.10918-14-peter.maydell@linaro.org
15
---
27
---
16
target/arm/cpu.h | 12 ++++++
28
target/arm/neon-dp.decode | 3 ++
17
hw/intc/armv7m_nvic.c | 96 +++++++++++++++++++++++++++++++++++++++++++
29
target/arm/translate-neon.inc.c | 81 +++++++++++++++++++++++++++++++++
18
2 files changed, 108 insertions(+)
30
target/arm/translate.c | 17 +------
31
3 files changed, 85 insertions(+), 16 deletions(-)
19
32
20
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
33
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
21
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.h
35
--- a/target/arm/neon-dp.decode
23
+++ b/target/arm/cpu.h
36
+++ b/target/arm/neon-dp.decode
24
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending(void *opaque, int irq, bool secure);
37
@@ -XXX,XX +XXX,XX @@ VADD_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 0 .... @3same_fp
25
* a different exception).
38
VSUB_fp_3s 1111 001 0 0 . 1 . .... .... 1101 ... 0 .... @3same_fp
26
*/
39
VPADD_fp_3s 1111 001 1 0 . 0 . .... .... 1101 ... 0 .... @3same_fp_q0
27
void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure);
40
VABD_fp_3s 1111 001 1 0 . 1 . .... .... 1101 ... 0 .... @3same_fp
28
+/**
41
+VMLA_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 1 .... @3same_fp
29
+ * armv7m_nvic_set_pending_lazyfp: mark this lazy FP exception as pending
42
+VMLS_fp_3s 1111 001 0 0 . 1 . .... .... 1101 ... 1 .... @3same_fp
30
+ * @opaque: the NVIC
43
+VMUL_fp_3s 1111 001 1 0 . 0 . .... .... 1101 ... 1 .... @3same_fp
31
+ * @irq: the exception number to mark pending
44
VPMAX_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 0 .... @3same_fp_q0
32
+ * @secure: false for non-banked exceptions or for the nonsecure
45
VPMIN_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 0 .... @3same_fp_q0
33
+ * version of a banked exception, true for the secure version of a banked
46
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
34
+ * exception.
35
+ *
36
+ * Similar to armv7m_nvic_set_pending(), but specifically for exceptions
37
+ * generated in the course of lazy stacking of FP registers.
38
+ */
39
+void armv7m_nvic_set_pending_lazyfp(void *opaque, int irq, bool secure);
40
/**
41
* armv7m_nvic_get_pending_irq_info: return highest priority pending
42
* exception, and whether it targets Secure state
43
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
44
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/intc/armv7m_nvic.c
48
--- a/target/arm/translate-neon.inc.c
46
+++ b/hw/intc/armv7m_nvic.c
49
+++ b/target/arm/translate-neon.inc.c
47
@@ -XXX,XX +XXX,XX @@ void armv7m_nvic_set_pending_derived(void *opaque, int irq, bool secure)
50
@@ -XXX,XX +XXX,XX @@ DO_3SAME_PAIR(VPADD, padd_u)
48
do_armv7m_nvic_set_pending(opaque, irq, secure, true);
51
DO_3SAME_VQDMULH(VQDMULH, qdmulh)
49
}
52
DO_3SAME_VQDMULH(VQRDMULH, qrdmulh)
50
53
51
+void armv7m_nvic_set_pending_lazyfp(void *opaque, int irq, bool secure)
54
+static bool do_3same_fp(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn,
55
+ bool reads_vd)
52
+{
56
+{
53
+ /*
57
+ /*
54
+ * Pend an exception during lazy FP stacking. This differs
58
+ * FP operations handled elementwise 32 bits at a time.
55
+ * from the usual exception pending because the logic for
59
+ * If reads_vd is true then the old value of Vd will be
56
+ * whether we should escalate depends on the saved context
60
+ * loaded before calling the callback function. This is
57
+ * in the FPCCR register, not on the current state of the CPU/NVIC.
61
+ * used for multiply-accumulate type operations.
58
+ */
62
+ */
59
+ NVICState *s = (NVICState *)opaque;
63
+ TCGv_i32 tmp, tmp2;
60
+ bool banked = exc_is_banked(irq);
64
+ int pass;
61
+ VecInfo *vec;
62
+ bool targets_secure;
63
+ bool escalate = false;
64
+ /*
65
+ * We will only look at bits in fpccr if this is a banked exception
66
+ * (in which case 'secure' tells us whether it is the S or NS version).
67
+ * All the bits for the non-banked exceptions are in fpccr_s.
68
+ */
69
+ uint32_t fpccr_s = s->cpu->env.v7m.fpccr[M_REG_S];
70
+ uint32_t fpccr = s->cpu->env.v7m.fpccr[secure];
71
+
65
+
72
+ assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
66
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
73
+ assert(!secure || banked);
67
+ return false;
74
+
75
+ vec = (banked && secure) ? &s->sec_vectors[irq] : &s->vectors[irq];
76
+
77
+ targets_secure = banked ? secure : exc_targets_secure(s, irq);
78
+
79
+ switch (irq) {
80
+ case ARMV7M_EXCP_DEBUG:
81
+ if (!(fpccr_s & R_V7M_FPCCR_MONRDY_MASK)) {
82
+ /* Ignore DebugMonitor exception */
83
+ return;
84
+ }
85
+ break;
86
+ case ARMV7M_EXCP_MEM:
87
+ escalate = !(fpccr & R_V7M_FPCCR_MMRDY_MASK);
88
+ break;
89
+ case ARMV7M_EXCP_USAGE:
90
+ escalate = !(fpccr & R_V7M_FPCCR_UFRDY_MASK);
91
+ break;
92
+ case ARMV7M_EXCP_BUS:
93
+ escalate = !(fpccr_s & R_V7M_FPCCR_BFRDY_MASK);
94
+ break;
95
+ case ARMV7M_EXCP_SECURE:
96
+ escalate = !(fpccr_s & R_V7M_FPCCR_SFRDY_MASK);
97
+ break;
98
+ default:
99
+ g_assert_not_reached();
100
+ }
68
+ }
101
+
69
+
102
+ if (escalate) {
70
+ /* UNDEF accesses to D16-D31 if they don't exist. */
103
+ /*
71
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
104
+ * Escalate to HardFault: faults that initially targeted Secure
72
+ ((a->vd | a->vn | a->vm) & 0x10)) {
105
+ * continue to do so, even if HF normally targets NonSecure.
73
+ return false;
106
+ */
107
+ irq = ARMV7M_EXCP_HARD;
108
+ if (arm_feature(&s->cpu->env, ARM_FEATURE_M_SECURITY) &&
109
+ (targets_secure ||
110
+ !(s->cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK))) {
111
+ vec = &s->sec_vectors[irq];
112
+ } else {
113
+ vec = &s->vectors[irq];
114
+ }
115
+ }
74
+ }
116
+
75
+
117
+ if (!vec->enabled ||
76
+ if ((a->vn | a->vm | a->vd) & a->q) {
118
+ nvic_exec_prio(s) <= exc_group_prio(s, vec->prio, secure)) {
77
+ return false;
119
+ if (!(fpccr_s & R_V7M_FPCCR_HFRDY_MASK)) {
120
+ /*
121
+ * We want to escalate to HardFault but the context the
122
+ * FP state belongs to prevents the exception pre-empting.
123
+ */
124
+ cpu_abort(&s->cpu->parent_obj,
125
+ "Lockup: can't escalate to HardFault during "
126
+ "lazy FP register stacking\n");
127
+ }
128
+ }
78
+ }
129
+
79
+
130
+ if (escalate) {
80
+ if (!vfp_access_check(s)) {
131
+ s->cpu->env.v7m.hfsr |= R_V7M_HFSR_FORCED_MASK;
81
+ return true;
132
+ }
82
+ }
133
+ if (!vec->pending) {
83
+
134
+ vec->pending = 1;
84
+ TCGv_ptr fpstatus = get_fpstatus_ptr(1);
135
+ /*
85
+ for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
136
+ * We do not call nvic_irq_update(), because we know our caller
86
+ tmp = neon_load_reg(a->vn, pass);
137
+ * is going to handle causing us to take the exception by
87
+ tmp2 = neon_load_reg(a->vm, pass);
138
+ * raising EXCP_LAZYFP, so raising the IRQ line would be
88
+ if (reads_vd) {
139
+ * pointless extra work. We just need to recompute the
89
+ TCGv_i32 tmp_rd = neon_load_reg(a->vd, pass);
140
+ * priorities so that armv7m_nvic_can_take_pending_exception()
90
+ fn(tmp_rd, tmp, tmp2, fpstatus);
141
+ * returns the right answer.
91
+ neon_store_reg(a->vd, pass, tmp_rd);
142
+ */
92
+ tcg_temp_free_i32(tmp);
143
+ nvic_recompute_state(s);
93
+ } else {
94
+ fn(tmp, tmp, tmp2, fpstatus);
95
+ neon_store_reg(a->vd, pass, tmp);
96
+ }
97
+ tcg_temp_free_i32(tmp2);
144
+ }
98
+ }
99
+ tcg_temp_free_ptr(fpstatus);
100
+ return true;
145
+}
101
+}
146
+
102
+
147
/* Make pending IRQ active. */
103
/*
148
void armv7m_nvic_acknowledge_irq(void *opaque)
104
* For all the functions using this macro, size == 1 means fp16,
105
* which is an architecture extension we don't implement yet.
106
@@ -XXX,XX +XXX,XX @@ DO_3SAME_VQDMULH(VQRDMULH, qrdmulh)
107
DO_3S_FP_GVEC(VADD, gen_helper_gvec_fadd_s)
108
DO_3S_FP_GVEC(VSUB, gen_helper_gvec_fsub_s)
109
DO_3S_FP_GVEC(VABD, gen_helper_gvec_fabd_s)
110
+DO_3S_FP_GVEC(VMUL, gen_helper_gvec_fmul_s)
111
+
112
+/*
113
+ * For all the functions using this macro, size == 1 means fp16,
114
+ * which is an architecture extension we don't implement yet.
115
+ */
116
+#define DO_3S_FP(INSN,FUNC,READS_VD) \
117
+ static bool trans_##INSN##_fp_3s(DisasContext *s, arg_3same *a) \
118
+ { \
119
+ if (a->size != 0) { \
120
+ /* TODO fp16 support */ \
121
+ return false; \
122
+ } \
123
+ return do_3same_fp(s, a, FUNC, READS_VD); \
124
+ }
125
+
126
+static void gen_VMLA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
127
+ TCGv_ptr fpstatus)
128
+{
129
+ gen_helper_vfp_muls(vn, vn, vm, fpstatus);
130
+ gen_helper_vfp_adds(vd, vd, vn, fpstatus);
131
+}
132
+
133
+static void gen_VMLS_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
134
+ TCGv_ptr fpstatus)
135
+{
136
+ gen_helper_vfp_muls(vn, vn, vm, fpstatus);
137
+ gen_helper_vfp_subs(vd, vd, vn, fpstatus);
138
+}
139
+
140
+DO_3S_FP(VMLA, gen_VMLA_fp_3s, true)
141
+DO_3S_FP(VMLS, gen_VMLS_fp_3s, true)
142
143
static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn)
149
{
144
{
145
diff --git a/target/arm/translate.c b/target/arm/translate.c
146
index XXXXXXX..XXXXXXX 100644
147
--- a/target/arm/translate.c
148
+++ b/target/arm/translate.c
149
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
150
case NEON_3R_VPADD_VQRDMLAH:
151
case NEON_3R_VQDMULH_VQRDMULH:
152
case NEON_3R_FLOAT_ARITH:
153
+ case NEON_3R_FLOAT_MULTIPLY:
154
/* Already handled by decodetree */
155
return 1;
156
}
157
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
158
tmp = neon_load_reg(rn, pass);
159
tmp2 = neon_load_reg(rm, pass);
160
switch (op) {
161
- case NEON_3R_FLOAT_MULTIPLY:
162
- {
163
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
164
- gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
165
- if (!u) {
166
- tcg_temp_free_i32(tmp2);
167
- tmp2 = neon_load_reg(rd, pass);
168
- if (size == 0) {
169
- gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
170
- } else {
171
- gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
172
- }
173
- }
174
- tcg_temp_free_ptr(fpstatus);
175
- break;
176
- }
177
case NEON_3R_FLOAT_CMP:
178
{
179
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
150
--
180
--
151
2.20.1
181
2.20.1
152
182
153
183
diff view generated by jsdifflib
1
We are close to running out of TB flags for AArch32; we could
1
Convert the Neon integer 3-reg-same compare insns VCGE, VCGT,
2
start using the cs_base word, but before we do that we can
2
VCEQ, VACGE and VACGT to decodetree.
3
economise on our usage by sharing the same bits for the VFP
4
VECSTRIDE field and the XScale XSCALE_CPAR field. This
5
works because no XScale CPU ever had VFP.
6
3
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20190416125744.27770-18-peter.maydell@linaro.org
6
Message-id: 20200512163904.10918-15-peter.maydell@linaro.org
10
---
7
---
11
target/arm/cpu.h | 10 ++++++----
8
target/arm/neon-dp.decode | 5 +++++
12
target/arm/cpu.c | 7 +++++++
9
target/arm/translate-neon.inc.c | 6 +++++
13
target/arm/helper.c | 6 +++++-
10
target/arm/translate.c | 39 ++-------------------------------
14
target/arm/translate.c | 9 +++++++--
11
3 files changed, 13 insertions(+), 37 deletions(-)
15
4 files changed, 25 insertions(+), 7 deletions(-)
16
12
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.h
15
--- a/target/arm/neon-dp.decode
20
+++ b/target/arm/cpu.h
16
+++ b/target/arm/neon-dp.decode
21
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_ANY, BE_DATA, 23, 1)
17
@@ -XXX,XX +XXX,XX @@ VABD_fp_3s 1111 001 1 0 . 1 . .... .... 1101 ... 0 .... @3same_fp
22
FIELD(TBFLAG_A32, THUMB, 0, 1)
18
VMLA_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 1 .... @3same_fp
23
FIELD(TBFLAG_A32, VECLEN, 1, 3)
19
VMLS_fp_3s 1111 001 0 0 . 1 . .... .... 1101 ... 1 .... @3same_fp
24
FIELD(TBFLAG_A32, VECSTRIDE, 4, 2)
20
VMUL_fp_3s 1111 001 1 0 . 0 . .... .... 1101 ... 1 .... @3same_fp
25
+/*
21
+VCEQ_fp_3s 1111 001 0 0 . 0 . .... .... 1110 ... 0 .... @3same_fp
26
+ * We store the bottom two bits of the CPAR as TB flags and handle
22
+VCGE_fp_3s 1111 001 1 0 . 0 . .... .... 1110 ... 0 .... @3same_fp
27
+ * checks on the other bits at runtime. This shares the same bits as
23
+VACGE_fp_3s 1111 001 1 0 . 0 . .... .... 1110 ... 1 .... @3same_fp
28
+ * VECSTRIDE, which is OK as no XScale CPU has VFP.
24
+VCGT_fp_3s 1111 001 1 0 . 1 . .... .... 1110 ... 0 .... @3same_fp
29
+ */
25
+VACGT_fp_3s 1111 001 1 0 . 1 . .... .... 1110 ... 1 .... @3same_fp
30
+FIELD(TBFLAG_A32, XSCALE_CPAR, 4, 2)
26
VPMAX_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 0 .... @3same_fp_q0
31
/*
27
VPMIN_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 0 .... @3same_fp_q0
32
* Indicates whether cp register reads and writes by guest code should access
28
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
33
* the secure or nonsecure bank of banked registers; note that this is not
34
@@ -XXX,XX +XXX,XX @@ FIELD(TBFLAG_A32, NS, 6, 1)
35
FIELD(TBFLAG_A32, VFPEN, 7, 1)
36
FIELD(TBFLAG_A32, CONDEXEC, 8, 8)
37
FIELD(TBFLAG_A32, SCTLR_B, 16, 1)
38
-/* We store the bottom two bits of the CPAR as TB flags and handle
39
- * checks on the other bits at runtime
40
- */
41
-FIELD(TBFLAG_A32, XSCALE_CPAR, 17, 2)
42
/* For M profile only, Handler (ie not Thread) mode */
43
FIELD(TBFLAG_A32, HANDLER, 21, 1)
44
/* For M profile only, whether we should generate stack-limit checks */
45
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
46
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/cpu.c
30
--- a/target/arm/translate-neon.inc.c
48
+++ b/target/arm/cpu.c
31
+++ b/target/arm/translate-neon.inc.c
49
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
32
@@ -XXX,XX +XXX,XX @@ DO_3S_FP_GVEC(VMUL, gen_helper_gvec_fmul_s)
50
set_feature(env, ARM_FEATURE_THUMB_DSP);
33
return do_3same_fp(s, a, FUNC, READS_VD); \
51
}
34
}
52
35
53
+ /*
36
+DO_3S_FP(VCEQ, gen_helper_neon_ceq_f32, false)
54
+ * We rely on no XScale CPU having VFP so we can use the same bits in the
37
+DO_3S_FP(VCGE, gen_helper_neon_cge_f32, false)
55
+ * TB flags field for VECSTRIDE and XSCALE_CPAR.
38
+DO_3S_FP(VCGT, gen_helper_neon_cgt_f32, false)
56
+ */
39
+DO_3S_FP(VACGE, gen_helper_neon_acge_f32, false)
57
+ assert(!(arm_feature(env, ARM_FEATURE_VFP) &&
40
+DO_3S_FP(VACGT, gen_helper_neon_acgt_f32, false)
58
+ arm_feature(env, ARM_FEATURE_XSCALE)));
59
+
41
+
60
if (arm_feature(env, ARM_FEATURE_V7) &&
42
static void gen_VMLA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
61
!arm_feature(env, ARM_FEATURE_M) &&
43
TCGv_ptr fpstatus)
62
!arm_feature(env, ARM_FEATURE_PMSA)) {
44
{
63
diff --git a/target/arm/helper.c b/target/arm/helper.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/helper.c
66
+++ b/target/arm/helper.c
67
@@ -XXX,XX +XXX,XX @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
68
|| arm_el_is_aa64(env, 1) || arm_feature(env, ARM_FEATURE_M)) {
69
flags = FIELD_DP32(flags, TBFLAG_A32, VFPEN, 1);
70
}
71
- flags = FIELD_DP32(flags, TBFLAG_A32, XSCALE_CPAR, env->cp15.c15_cpar);
72
+ /* Note that XSCALE_CPAR shares bits with VECSTRIDE */
73
+ if (arm_feature(env, ARM_FEATURE_XSCALE)) {
74
+ flags = FIELD_DP32(flags, TBFLAG_A32,
75
+ XSCALE_CPAR, env->cp15.c15_cpar);
76
+ }
77
}
78
79
flags = FIELD_DP32(flags, TBFLAG_ANY, MMUIDX, arm_to_core_mmu_idx(mmu_idx));
80
diff --git a/target/arm/translate.c b/target/arm/translate.c
45
diff --git a/target/arm/translate.c b/target/arm/translate.c
81
index XXXXXXX..XXXXXXX 100644
46
index XXXXXXX..XXXXXXX 100644
82
--- a/target/arm/translate.c
47
--- a/target/arm/translate.c
83
+++ b/target/arm/translate.c
48
+++ b/target/arm/translate.c
84
@@ -XXX,XX +XXX,XX @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
49
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
85
dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
50
case NEON_3R_VQDMULH_VQRDMULH:
86
dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
51
case NEON_3R_FLOAT_ARITH:
87
dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
52
case NEON_3R_FLOAT_MULTIPLY:
88
- dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
53
+ case NEON_3R_FLOAT_CMP:
89
- dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
54
+ case NEON_3R_FLOAT_ACMP:
90
+ if (arm_feature(env, ARM_FEATURE_XSCALE)) {
55
/* Already handled by decodetree */
91
+ dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
56
return 1;
92
+ dc->vec_stride = 0;
57
}
93
+ } else {
58
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
94
+ dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
59
return 1; /* VPMIN/VPMAX handled by decodetree */
95
+ dc->c15_cpar = 0;
60
}
96
+ }
61
break;
97
dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_A32, HANDLER);
62
- case NEON_3R_FLOAT_CMP:
98
dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
63
- if (!u && size) {
99
regime_is_secure(env, dc->mmu_idx);
64
- /* no encoding for U=0 C=1x */
65
- return 1;
66
- }
67
- break;
68
- case NEON_3R_FLOAT_ACMP:
69
- if (!u) {
70
- return 1;
71
- }
72
- break;
73
case NEON_3R_FLOAT_MISC:
74
/* VMAXNM/VMINNM in ARMv8 */
75
if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) {
76
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
77
tmp = neon_load_reg(rn, pass);
78
tmp2 = neon_load_reg(rm, pass);
79
switch (op) {
80
- case NEON_3R_FLOAT_CMP:
81
- {
82
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
83
- if (!u) {
84
- gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
85
- } else {
86
- if (size == 0) {
87
- gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
88
- } else {
89
- gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
90
- }
91
- }
92
- tcg_temp_free_ptr(fpstatus);
93
- break;
94
- }
95
- case NEON_3R_FLOAT_ACMP:
96
- {
97
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
98
- if (size == 0) {
99
- gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
100
- } else {
101
- gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
102
- }
103
- tcg_temp_free_ptr(fpstatus);
104
- break;
105
- }
106
case NEON_3R_FLOAT_MINMAX:
107
{
108
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
100
--
109
--
101
2.20.1
110
2.20.1
102
111
103
112
diff view generated by jsdifflib
1
Enforce that for M-profile various FPSCR bits which are RES0 there
1
The usual location for the env argument in the argument list of a TCG helper
2
but have defined meanings on A-profile are never settable. This
2
is immediately after the return-value argument. recps_f32 and rsqrts_f32
3
ensures that M-profile code can't enable the A-profile behaviour
3
differ in that they put it at the end.
4
(notably vector length/stride handling) by accident.
4
5
Move the env argument to its usual place; this will allow us to
6
more easily use these helper functions with the gvec APIs.
5
7
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20190416125744.27770-2-peter.maydell@linaro.org
10
Message-id: 20200512163904.10918-16-peter.maydell@linaro.org
9
---
11
---
10
target/arm/vfp_helper.c | 8 ++++++++
12
target/arm/helper.h | 4 ++--
11
1 file changed, 8 insertions(+)
13
target/arm/translate.c | 4 ++--
14
target/arm/vfp_helper.c | 4 ++--
15
3 files changed, 6 insertions(+), 6 deletions(-)
12
16
17
diff --git a/target/arm/helper.h b/target/arm/helper.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.h
20
+++ b/target/arm/helper.h
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(vfp_fcvt_f64_to_f16, TCG_CALL_NO_RWG, f16, f64, ptr, i32)
22
DEF_HELPER_4(vfp_muladdd, f64, f64, f64, f64, ptr)
23
DEF_HELPER_4(vfp_muladds, f32, f32, f32, f32, ptr)
24
25
-DEF_HELPER_3(recps_f32, f32, f32, f32, env)
26
-DEF_HELPER_3(rsqrts_f32, f32, f32, f32, env)
27
+DEF_HELPER_3(recps_f32, f32, env, f32, f32)
28
+DEF_HELPER_3(rsqrts_f32, f32, env, f32, f32)
29
DEF_HELPER_FLAGS_2(recpe_f16, TCG_CALL_NO_RWG, f16, f16, ptr)
30
DEF_HELPER_FLAGS_2(recpe_f32, TCG_CALL_NO_RWG, f32, f32, ptr)
31
DEF_HELPER_FLAGS_2(recpe_f64, TCG_CALL_NO_RWG, f64, f64, ptr)
32
diff --git a/target/arm/translate.c b/target/arm/translate.c
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/translate.c
35
+++ b/target/arm/translate.c
36
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
37
tcg_temp_free_ptr(fpstatus);
38
} else {
39
if (size == 0) {
40
- gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
41
+ gen_helper_recps_f32(tmp, cpu_env, tmp, tmp2);
42
} else {
43
- gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
44
+ gen_helper_rsqrts_f32(tmp, cpu_env, tmp, tmp2);
45
}
46
}
47
break;
13
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
48
diff --git a/target/arm/vfp_helper.c b/target/arm/vfp_helper.c
14
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/vfp_helper.c
50
--- a/target/arm/vfp_helper.c
16
+++ b/target/arm/vfp_helper.c
51
+++ b/target/arm/vfp_helper.c
17
@@ -XXX,XX +XXX,XX @@ void HELPER(vfp_set_fpscr)(CPUARMState *env, uint32_t val)
52
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(vfp_fcvt_f64_to_f16)(float64 a, void *fpstp, uint32_t ahp_mode)
18
val &= ~FPCR_FZ16;
53
#define float32_three make_float32(0x40400000)
19
}
54
#define float32_one_point_five make_float32(0x3fc00000)
20
55
21
+ if (arm_feature(env, ARM_FEATURE_M)) {
56
-float32 HELPER(recps_f32)(float32 a, float32 b, CPUARMState *env)
22
+ /*
57
+float32 HELPER(recps_f32)(CPUARMState *env, float32 a, float32 b)
23
+ * M profile FPSCR is RES0 for the QC, STRIDE, FZ16, LEN bits
58
{
24
+ * and also for the trapped-exception-handling bits IxE.
59
float_status *s = &env->vfp.standard_fp_status;
25
+ */
60
if ((float32_is_infinity(a) && float32_is_zero_or_denormal(b)) ||
26
+ val &= 0xf7c0009f;
61
@@ -XXX,XX +XXX,XX @@ float32 HELPER(recps_f32)(float32 a, float32 b, CPUARMState *env)
27
+ }
62
return float32_sub(float32_two, float32_mul(a, b, s), s);
28
+
63
}
29
/*
64
30
* We don't implement trapped exception handling, so the
65
-float32 HELPER(rsqrts_f32)(float32 a, float32 b, CPUARMState *env)
31
* trap enable bits, IDE|IXE|UFE|OFE|DZE|IOE are all RAZ/WI (not RES0!)
66
+float32 HELPER(rsqrts_f32)(CPUARMState *env, float32 a, float32 b)
67
{
68
float_status *s = &env->vfp.standard_fp_status;
69
float32 product;
32
--
70
--
33
2.20.1
71
2.20.1
34
72
35
73
diff view generated by jsdifflib
1
Implement the VLSTM instruction for v7M for the FPU present case.
1
Convert the Neon fp VMAX/VMIN/VMAXNM/VMINNM/VRECPS/VRSQRTS 3-reg-same
2
insns to decodetree. (These are all the remaining non-accumulation
3
instructions in this group.)
2
4
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20190416125744.27770-25-peter.maydell@linaro.org
7
Message-id: 20200512163904.10918-17-peter.maydell@linaro.org
6
---
8
---
7
target/arm/cpu.h | 2 +
9
target/arm/neon-dp.decode | 6 +++
8
target/arm/helper.h | 2 +
10
target/arm/translate-neon.inc.c | 70 +++++++++++++++++++++++++++++++++
9
target/arm/helper.c | 84 ++++++++++++++++++++++++++++++++++++++++++
11
target/arm/translate.c | 42 +-------------------
10
target/arm/translate.c | 15 +++++++-
12
3 files changed, 78 insertions(+), 40 deletions(-)
11
4 files changed, 102 insertions(+), 1 deletion(-)
12
13
13
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu.h
16
--- a/target/arm/neon-dp.decode
16
+++ b/target/arm/cpu.h
17
+++ b/target/arm/neon-dp.decode
17
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ VCGE_fp_3s 1111 001 1 0 . 0 . .... .... 1110 ... 0 .... @3same_fp
18
#define EXCP_INVSTATE 18 /* v7M INVSTATE UsageFault */
19
VACGE_fp_3s 1111 001 1 0 . 0 . .... .... 1110 ... 1 .... @3same_fp
19
#define EXCP_STKOF 19 /* v8M STKOF UsageFault */
20
VCGT_fp_3s 1111 001 1 0 . 1 . .... .... 1110 ... 0 .... @3same_fp
20
#define EXCP_LAZYFP 20 /* v7M fault during lazy FP stacking */
21
VACGT_fp_3s 1111 001 1 0 . 1 . .... .... 1110 ... 1 .... @3same_fp
21
+#define EXCP_LSERR 21 /* v8M LSERR SecureFault */
22
+VMAX_fp_3s 1111 001 0 0 . 0 . .... .... 1111 ... 0 .... @3same_fp
22
+#define EXCP_UNALIGNED 22 /* v7M UNALIGNED UsageFault */
23
+VMIN_fp_3s 1111 001 0 0 . 1 . .... .... 1111 ... 0 .... @3same_fp
23
/* NB: add new EXCP_ defines to the array in arm_log_exception() too */
24
VPMAX_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 0 .... @3same_fp_q0
24
25
VPMIN_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 0 .... @3same_fp_q0
25
#define ARMV7M_EXCP_RESET 1
26
+VRECPS_fp_3s 1111 001 0 0 . 0 . .... .... 1111 ... 1 .... @3same_fp
26
diff --git a/target/arm/helper.h b/target/arm/helper.h
27
+VRSQRTS_fp_3s 1111 001 0 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
28
+VMAXNM_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 1 .... @3same_fp
29
+VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
30
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
27
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/helper.h
32
--- a/target/arm/translate-neon.inc.c
29
+++ b/target/arm/helper.h
33
+++ b/target/arm/translate-neon.inc.c
30
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(v7m_tt, i32, env, i32, i32)
34
@@ -XXX,XX +XXX,XX @@ DO_3S_FP(VCGE, gen_helper_neon_cge_f32, false)
31
35
DO_3S_FP(VCGT, gen_helper_neon_cgt_f32, false)
32
DEF_HELPER_1(v7m_preserve_fp_state, void, env)
36
DO_3S_FP(VACGE, gen_helper_neon_acge_f32, false)
33
37
DO_3S_FP(VACGT, gen_helper_neon_acgt_f32, false)
34
+DEF_HELPER_2(v7m_vlstm, void, env, i32)
38
+DO_3S_FP(VMAX, gen_helper_vfp_maxs, false)
39
+DO_3S_FP(VMIN, gen_helper_vfp_mins, false)
40
41
static void gen_VMLA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
42
TCGv_ptr fpstatus)
43
@@ -XXX,XX +XXX,XX @@ static void gen_VMLS_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
44
DO_3S_FP(VMLA, gen_VMLA_fp_3s, true)
45
DO_3S_FP(VMLS, gen_VMLS_fp_3s, true)
46
47
+static bool trans_VMAXNM_fp_3s(DisasContext *s, arg_3same *a)
48
+{
49
+ if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
50
+ return false;
51
+ }
35
+
52
+
36
DEF_HELPER_2(v8m_stackcheck, void, env, i32)
53
+ if (a->size != 0) {
37
54
+ /* TODO fp16 support */
38
DEF_HELPER_4(access_check_cp_reg, void, env, ptr, i32, i32)
55
+ return false;
39
diff --git a/target/arm/helper.c b/target/arm/helper.c
56
+ }
40
index XXXXXXX..XXXXXXX 100644
57
+
41
--- a/target/arm/helper.c
58
+ return do_3same_fp(s, a, gen_helper_vfp_maxnums, false);
42
+++ b/target/arm/helper.c
43
@@ -XXX,XX +XXX,XX @@ void HELPER(v7m_preserve_fp_state)(CPUARMState *env)
44
g_assert_not_reached();
45
}
46
47
+void HELPER(v7m_vlstm)(CPUARMState *env, uint32_t fptr)
48
+{
49
+ /* translate.c should never generate calls here in user-only mode */
50
+ g_assert_not_reached();
51
+}
59
+}
52
+
60
+
53
uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op)
61
+static bool trans_VMINNM_fp_3s(DisasContext *s, arg_3same *a)
54
{
55
/* The TT instructions can be used by unprivileged code, but in
56
@@ -XXX,XX +XXX,XX @@ static void v7m_update_fpccr(CPUARMState *env, uint32_t frameptr,
57
}
58
}
59
60
+void HELPER(v7m_vlstm)(CPUARMState *env, uint32_t fptr)
61
+{
62
+{
62
+ /* fptr is the value of Rn, the frame pointer we store the FP regs to */
63
+ if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
63
+ bool s = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_S_MASK;
64
+ return false;
64
+ bool lspact = env->v7m.fpccr[s] & R_V7M_FPCCR_LSPACT_MASK;
65
+
66
+ assert(env->v7m.secure);
67
+
68
+ if (!(env->v7m.control[M_REG_S] & R_V7M_CONTROL_SFPA_MASK)) {
69
+ return;
70
+ }
65
+ }
71
+
66
+
72
+ /* Check access to the coprocessor is permitted */
67
+ if (a->size != 0) {
73
+ if (!v7m_cpacr_pass(env, true, arm_current_el(env) != 0)) {
68
+ /* TODO fp16 support */
74
+ raise_exception_ra(env, EXCP_NOCP, 0, 1, GETPC());
69
+ return false;
75
+ }
70
+ }
76
+
71
+
77
+ if (lspact) {
72
+ return do_3same_fp(s, a, gen_helper_vfp_minnums, false);
78
+ /* LSPACT should not be active when there is active FP state */
73
+}
79
+ raise_exception_ra(env, EXCP_LSERR, 0, 1, GETPC());
74
+
75
+WRAP_ENV_FN(gen_VRECPS_tramp, gen_helper_recps_f32)
76
+
77
+static void gen_VRECPS_fp_3s(unsigned vece, uint32_t rd_ofs,
78
+ uint32_t rn_ofs, uint32_t rm_ofs,
79
+ uint32_t oprsz, uint32_t maxsz)
80
+{
81
+ static const GVecGen3 ops = { .fni4 = gen_VRECPS_tramp };
82
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops);
83
+}
84
+
85
+static bool trans_VRECPS_fp_3s(DisasContext *s, arg_3same *a)
86
+{
87
+ if (a->size != 0) {
88
+ /* TODO fp16 support */
89
+ return false;
80
+ }
90
+ }
81
+
91
+
82
+ if (fptr & 7) {
92
+ return do_3same(s, a, gen_VRECPS_fp_3s);
83
+ raise_exception_ra(env, EXCP_UNALIGNED, 0, 1, GETPC());
93
+}
94
+
95
+WRAP_ENV_FN(gen_VRSQRTS_tramp, gen_helper_rsqrts_f32)
96
+
97
+static void gen_VRSQRTS_fp_3s(unsigned vece, uint32_t rd_ofs,
98
+ uint32_t rn_ofs, uint32_t rm_ofs,
99
+ uint32_t oprsz, uint32_t maxsz)
100
+{
101
+ static const GVecGen3 ops = { .fni4 = gen_VRSQRTS_tramp };
102
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, &ops);
103
+}
104
+
105
+static bool trans_VRSQRTS_fp_3s(DisasContext *s, arg_3same *a)
106
+{
107
+ if (a->size != 0) {
108
+ /* TODO fp16 support */
109
+ return false;
84
+ }
110
+ }
85
+
111
+
86
+ /*
112
+ return do_3same(s, a, gen_VRSQRTS_fp_3s);
87
+ * Note that we do not use v7m_stack_write() here, because the
88
+ * accesses should not set the FSR bits for stacking errors if they
89
+ * fail. (In pseudocode terms, they are AccType_NORMAL, not AccType_STACK
90
+ * or AccType_LAZYFP). Faults in cpu_stl_data() will throw exceptions
91
+ * and longjmp out.
92
+ */
93
+ if (!(env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_LSPEN_MASK)) {
94
+ bool ts = env->v7m.fpccr[M_REG_S] & R_V7M_FPCCR_TS_MASK;
95
+ int i;
96
+
97
+ for (i = 0; i < (ts ? 32 : 16); i += 2) {
98
+ uint64_t dn = *aa32_vfp_dreg(env, i / 2);
99
+ uint32_t faddr = fptr + 4 * i;
100
+ uint32_t slo = extract64(dn, 0, 32);
101
+ uint32_t shi = extract64(dn, 32, 32);
102
+
103
+ if (i >= 16) {
104
+ faddr += 8; /* skip the slot for the FPSCR */
105
+ }
106
+ cpu_stl_data(env, faddr, slo);
107
+ cpu_stl_data(env, faddr + 4, shi);
108
+ }
109
+ cpu_stl_data(env, fptr + 0x40, vfp_get_fpscr(env));
110
+
111
+ /*
112
+ * If TS is 0 then s0 to s15 and FPSCR are UNKNOWN; we choose to
113
+ * leave them unchanged, matching our choice in v7m_preserve_fp_state.
114
+ */
115
+ if (ts) {
116
+ for (i = 0; i < 32; i += 2) {
117
+ *aa32_vfp_dreg(env, i / 2) = 0;
118
+ }
119
+ vfp_set_fpscr(env, 0);
120
+ }
121
+ } else {
122
+ v7m_update_fpccr(env, fptr, false);
123
+ }
124
+
125
+ env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_FPCA_MASK;
126
+}
113
+}
127
+
114
+
128
static bool v7m_push_stack(ARMCPU *cpu)
115
static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn)
129
{
116
{
130
/* Do the "set up stack frame" part of exception entry,
117
/* FP operations handled pairwise 32 bits at a time */
131
@@ -XXX,XX +XXX,XX @@ static void arm_log_exception(int idx)
132
[EXCP_INVSTATE] = "v7M INVSTATE UsageFault",
133
[EXCP_STKOF] = "v8M STKOF UsageFault",
134
[EXCP_LAZYFP] = "v7M exception during lazy FP stacking",
135
+ [EXCP_LSERR] = "v8M LSERR UsageFault",
136
+ [EXCP_UNALIGNED] = "v7M UNALIGNED UsageFault",
137
};
138
139
if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
140
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
141
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
142
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_STKOF_MASK;
143
break;
144
+ case EXCP_LSERR:
145
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
146
+ env->v7m.sfsr |= R_V7M_SFSR_LSERR_MASK;
147
+ break;
148
+ case EXCP_UNALIGNED:
149
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
150
+ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_UNALIGNED_MASK;
151
+ break;
152
case EXCP_SWI:
153
/* The PC already points to the next instruction. */
154
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC, env->v7m.secure);
155
diff --git a/target/arm/translate.c b/target/arm/translate.c
118
diff --git a/target/arm/translate.c b/target/arm/translate.c
156
index XXXXXXX..XXXXXXX 100644
119
index XXXXXXX..XXXXXXX 100644
157
--- a/target/arm/translate.c
120
--- a/target/arm/translate.c
158
+++ b/target/arm/translate.c
121
+++ b/target/arm/translate.c
159
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
122
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
160
if (!s->v8m_secure || (insn & 0x0040f0ff)) {
123
case NEON_3R_FLOAT_MULTIPLY:
161
goto illegal_op;
124
case NEON_3R_FLOAT_CMP:
162
}
125
case NEON_3R_FLOAT_ACMP:
163
- /* Just NOP since FP support is not implemented */
126
+ case NEON_3R_FLOAT_MINMAX:
164
+
127
+ case NEON_3R_FLOAT_MISC:
165
+ if (arm_dc_feature(s, ARM_FEATURE_VFP)) {
128
/* Already handled by decodetree */
166
+ TCGv_i32 fptr = load_reg(s, rn);
129
return 1;
167
+
130
}
168
+ if (extract32(insn, 20, 1)) {
131
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
169
+ /* VLLDM */
132
return 1;
170
+ } else {
133
}
171
+ gen_helper_v7m_vlstm(cpu_env, fptr);
134
switch (op) {
172
+ }
135
- case NEON_3R_FLOAT_MINMAX:
173
+ tcg_temp_free_i32(fptr);
136
- if (u) {
174
+
137
- return 1; /* VPMIN/VPMAX handled by decodetree */
175
+ /* End the TB, because we have updated FP control bits */
138
- }
176
+ s->base.is_jmp = DISAS_UPDATE;
139
- break;
177
+ }
140
- case NEON_3R_FLOAT_MISC:
178
break;
141
- /* VMAXNM/VMINNM in ARMv8 */
179
}
142
- if (u && !arm_dc_feature(s, ARM_FEATURE_V8)) {
180
if (arm_dc_feature(s, ARM_FEATURE_VFP) &&
143
- return 1;
144
- }
145
- break;
146
case NEON_3R_VFM_VQRDMLSH:
147
if (!dc_isar_feature(aa32_simdfmac, s)) {
148
return 1;
149
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
150
tmp = neon_load_reg(rn, pass);
151
tmp2 = neon_load_reg(rm, pass);
152
switch (op) {
153
- case NEON_3R_FLOAT_MINMAX:
154
- {
155
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
156
- if (size == 0) {
157
- gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
158
- } else {
159
- gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
160
- }
161
- tcg_temp_free_ptr(fpstatus);
162
- break;
163
- }
164
- case NEON_3R_FLOAT_MISC:
165
- if (u) {
166
- /* VMAXNM/VMINNM */
167
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
168
- if (size == 0) {
169
- gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
170
- } else {
171
- gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
172
- }
173
- tcg_temp_free_ptr(fpstatus);
174
- } else {
175
- if (size == 0) {
176
- gen_helper_recps_f32(tmp, cpu_env, tmp, tmp2);
177
- } else {
178
- gen_helper_rsqrts_f32(tmp, cpu_env, tmp, tmp2);
179
- }
180
- }
181
- break;
182
case NEON_3R_VFM_VQRDMLSH:
183
{
184
/* VFMA, VFMS: fused multiply-add */
181
--
185
--
182
2.20.1
186
2.20.1
183
187
184
188
diff view generated by jsdifflib
1
Pushing registers to the stack for v7M needs to handle three cases:
1
Convert the Neon floating point VFMA and VFMS insn to decodetree.
2
* the "normal" case where we pend exceptions
2
These are the last insns in the 3-reg-same group so we can
3
* an "ignore faults" case where we set FSR bits but
3
remove all the support/loop code from the old decoder.
4
do not pend exceptions (this is used when we are
5
handling some kinds of derived exception on exception entry)
6
* a "lazy FP stacking" case, where different FSR bits
7
are set and the exception is pended differently
8
9
Implement this by changing the existing flag argument that
10
tells us whether to ignore faults or not into an enum that
11
specifies which of the 3 modes we should handle.
12
4
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20190416125744.27770-23-peter.maydell@linaro.org
7
Message-id: 20200512163904.10918-18-peter.maydell@linaro.org
16
---
8
---
17
target/arm/helper.c | 118 +++++++++++++++++++++++++++++---------------
9
target/arm/neon-dp.decode | 3 +
18
1 file changed, 79 insertions(+), 39 deletions(-)
10
target/arm/translate-neon.inc.c | 41 ++++++++
19
11
target/arm/translate.c | 176 +-------------------------------
20
diff --git a/target/arm/helper.c b/target/arm/helper.c
12
3 files changed, 46 insertions(+), 174 deletions(-)
13
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
21
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/helper.c
16
--- a/target/arm/neon-dp.decode
23
+++ b/target/arm/helper.c
17
+++ b/target/arm/neon-dp.decode
24
@@ -XXX,XX +XXX,XX @@ static bool v7m_cpacr_pass(CPUARMState *env, bool is_secure, bool is_priv)
18
@@ -XXX,XX +XXX,XX @@ SHA256H2_3s 1111 001 1 0 . 01 .... .... 1100 . 1 . 0 .... \
19
SHA256SU1_3s 1111 001 1 0 . 10 .... .... 1100 . 1 . 0 .... \
20
vm=%vm_dp vn=%vn_dp vd=%vd_dp
21
22
+VFMA_fp_3s 1111 001 0 0 . 0 . .... .... 1100 ... 1 .... @3same_fp
23
+VFMS_fp_3s 1111 001 0 0 . 1 . .... .... 1100 ... 1 .... @3same_fp
24
+
25
VQRDMLSH_3s 1111 001 1 0 . .. .... .... 1100 ... 1 .... @3same
26
27
VADD_fp_3s 1111 001 0 0 . 0 . .... .... 1101 ... 0 .... @3same_fp
28
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/translate-neon.inc.c
31
+++ b/target/arm/translate-neon.inc.c
32
@@ -XXX,XX +XXX,XX @@ static bool trans_VRSQRTS_fp_3s(DisasContext *s, arg_3same *a)
33
return do_3same(s, a, gen_VRSQRTS_fp_3s);
34
}
35
36
+static void gen_VFMA_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
37
+ TCGv_ptr fpstatus)
38
+{
39
+ gen_helper_vfp_muladds(vd, vn, vm, vd, fpstatus);
40
+}
41
+
42
+static bool trans_VFMA_fp_3s(DisasContext *s, arg_3same *a)
43
+{
44
+ if (!dc_isar_feature(aa32_simdfmac, s)) {
45
+ return false;
46
+ }
47
+
48
+ if (a->size != 0) {
49
+ /* TODO fp16 support */
50
+ return false;
51
+ }
52
+
53
+ return do_3same_fp(s, a, gen_VFMA_fp_3s, true);
54
+}
55
+
56
+static void gen_VFMS_fp_3s(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm,
57
+ TCGv_ptr fpstatus)
58
+{
59
+ gen_helper_vfp_negs(vn, vn);
60
+ gen_helper_vfp_muladds(vd, vn, vm, vd, fpstatus);
61
+}
62
+
63
+static bool trans_VFMS_fp_3s(DisasContext *s, arg_3same *a)
64
+{
65
+ if (!dc_isar_feature(aa32_simdfmac, s)) {
66
+ return false;
67
+ }
68
+
69
+ if (a->size != 0) {
70
+ /* TODO fp16 support */
71
+ return false;
72
+ }
73
+
74
+ return do_3same_fp(s, a, gen_VFMS_fp_3s, true);
75
+}
76
+
77
static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn)
78
{
79
/* FP operations handled pairwise 32 bits at a time */
80
diff --git a/target/arm/translate.c b/target/arm/translate.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/target/arm/translate.c
83
+++ b/target/arm/translate.c
84
@@ -XXX,XX +XXX,XX @@ static void gen_neon_narrow_op(int op, int u, int size,
25
}
85
}
26
}
86
}
27
87
28
+/*
88
-/* Symbolic constants for op fields for Neon 3-register same-length.
29
+ * What kind of stack write are we doing? This affects how exceptions
89
- * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
30
+ * generated during the stacking are treated.
90
- * table A7-9.
31
+ */
91
- */
32
+typedef enum StackingMode {
92
-#define NEON_3R_VHADD 0
33
+ STACK_NORMAL,
93
-#define NEON_3R_VQADD 1
34
+ STACK_IGNFAULTS,
94
-#define NEON_3R_VRHADD 2
35
+ STACK_LAZYFP,
95
-#define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
36
+} StackingMode;
96
-#define NEON_3R_VHSUB 4
37
+
97
-#define NEON_3R_VQSUB 5
38
static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value,
98
-#define NEON_3R_VCGT 6
39
- ARMMMUIdx mmu_idx, bool ignfault)
99
-#define NEON_3R_VCGE 7
40
+ ARMMMUIdx mmu_idx, StackingMode mode)
100
-#define NEON_3R_VSHL 8
41
{
101
-#define NEON_3R_VQSHL 9
42
CPUState *cs = CPU(cpu);
102
-#define NEON_3R_VRSHL 10
43
CPUARMState *env = &cpu->env;
103
-#define NEON_3R_VQRSHL 11
44
@@ -XXX,XX +XXX,XX @@ static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value,
104
-#define NEON_3R_VMAX 12
45
&attrs, &prot, &page_size, &fi, NULL)) {
105
-#define NEON_3R_VMIN 13
46
/* MPU/SAU lookup failed */
106
-#define NEON_3R_VABD 14
47
if (fi.type == ARMFault_QEMU_SFault) {
107
-#define NEON_3R_VABA 15
48
- qemu_log_mask(CPU_LOG_INT,
108
-#define NEON_3R_VADD_VSUB 16
49
- "...SecureFault with SFSR.AUVIOL during stacking\n");
109
-#define NEON_3R_VTST_VCEQ 17
50
- env->v7m.sfsr |= R_V7M_SFSR_AUVIOL_MASK | R_V7M_SFSR_SFARVALID_MASK;
110
-#define NEON_3R_VML 18 /* VMLA, VMLS */
51
+ if (mode == STACK_LAZYFP) {
111
-#define NEON_3R_VMUL 19
52
+ qemu_log_mask(CPU_LOG_INT,
112
-#define NEON_3R_VPMAX 20
53
+ "...SecureFault with SFSR.LSPERR "
113
-#define NEON_3R_VPMIN 21
54
+ "during lazy stacking\n");
114
-#define NEON_3R_VQDMULH_VQRDMULH 22
55
+ env->v7m.sfsr |= R_V7M_SFSR_LSPERR_MASK;
115
-#define NEON_3R_VPADD_VQRDMLAH 23
56
+ } else {
116
-#define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
57
+ qemu_log_mask(CPU_LOG_INT,
117
-#define NEON_3R_VFM_VQRDMLSH 25 /* VFMA, VFMS, VQRDMLSH */
58
+ "...SecureFault with SFSR.AUVIOL "
118
-#define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
59
+ "during stacking\n");
119
-#define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
60
+ env->v7m.sfsr |= R_V7M_SFSR_AUVIOL_MASK;
120
-#define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
61
+ }
121
-#define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
62
+ env->v7m.sfsr |= R_V7M_SFSR_SFARVALID_MASK;
122
-#define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
63
env->v7m.sfar = addr;
123
-#define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
64
exc = ARMV7M_EXCP_SECURE;
124
-
65
exc_secure = false;
125
-static const uint8_t neon_3r_sizes[] = {
66
} else {
126
- [NEON_3R_VHADD] = 0x7,
67
- qemu_log_mask(CPU_LOG_INT, "...MemManageFault with CFSR.MSTKERR\n");
127
- [NEON_3R_VQADD] = 0xf,
68
- env->v7m.cfsr[secure] |= R_V7M_CFSR_MSTKERR_MASK;
128
- [NEON_3R_VRHADD] = 0x7,
69
+ if (mode == STACK_LAZYFP) {
129
- [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
70
+ qemu_log_mask(CPU_LOG_INT,
130
- [NEON_3R_VHSUB] = 0x7,
71
+ "...MemManageFault with CFSR.MLSPERR\n");
131
- [NEON_3R_VQSUB] = 0xf,
72
+ env->v7m.cfsr[secure] |= R_V7M_CFSR_MLSPERR_MASK;
132
- [NEON_3R_VCGT] = 0x7,
73
+ } else {
133
- [NEON_3R_VCGE] = 0x7,
74
+ qemu_log_mask(CPU_LOG_INT,
134
- [NEON_3R_VSHL] = 0xf,
75
+ "...MemManageFault with CFSR.MSTKERR\n");
135
- [NEON_3R_VQSHL] = 0xf,
76
+ env->v7m.cfsr[secure] |= R_V7M_CFSR_MSTKERR_MASK;
136
- [NEON_3R_VRSHL] = 0xf,
77
+ }
137
- [NEON_3R_VQRSHL] = 0xf,
78
exc = ARMV7M_EXCP_MEM;
138
- [NEON_3R_VMAX] = 0x7,
79
exc_secure = secure;
139
- [NEON_3R_VMIN] = 0x7,
80
}
140
- [NEON_3R_VABD] = 0x7,
81
@@ -XXX,XX +XXX,XX @@ static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value,
141
- [NEON_3R_VABA] = 0x7,
82
attrs, &txres);
142
- [NEON_3R_VADD_VSUB] = 0xf,
83
if (txres != MEMTX_OK) {
143
- [NEON_3R_VTST_VCEQ] = 0x7,
84
/* BusFault trying to write the data */
144
- [NEON_3R_VML] = 0x7,
85
- qemu_log_mask(CPU_LOG_INT, "...BusFault with BFSR.STKERR\n");
145
- [NEON_3R_VMUL] = 0x7,
86
- env->v7m.cfsr[M_REG_NS] |= R_V7M_CFSR_STKERR_MASK;
146
- [NEON_3R_VPMAX] = 0x7,
87
+ if (mode == STACK_LAZYFP) {
147
- [NEON_3R_VPMIN] = 0x7,
88
+ qemu_log_mask(CPU_LOG_INT, "...BusFault with BFSR.LSPERR\n");
148
- [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
89
+ env->v7m.cfsr[M_REG_NS] |= R_V7M_CFSR_LSPERR_MASK;
149
- [NEON_3R_VPADD_VQRDMLAH] = 0x7,
90
+ } else {
150
- [NEON_3R_SHA] = 0xf, /* size field encodes op type */
91
+ qemu_log_mask(CPU_LOG_INT, "...BusFault with BFSR.STKERR\n");
151
- [NEON_3R_VFM_VQRDMLSH] = 0x7, /* For VFM, size bit 1 encodes op */
92
+ env->v7m.cfsr[M_REG_NS] |= R_V7M_CFSR_STKERR_MASK;
152
- [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
93
+ }
153
- [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
94
exc = ARMV7M_EXCP_BUS;
154
- [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
95
exc_secure = false;
155
- [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
96
goto pend_fault;
156
- [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
97
@@ -XXX,XX +XXX,XX @@ pend_fault:
157
- [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
98
* later if we have two derived exceptions.
158
-};
99
* The only case when we must not pend the exception but instead
159
-
100
* throw it away is if we are doing the push of the callee registers
160
/* Symbolic constants for op fields for Neon 2-register miscellaneous.
101
- * and we've already generated a derived exception. Even in this
161
* The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
102
- * case we will still update the fault status registers.
162
* table A7-13.
103
+ * and we've already generated a derived exception (this is indicated
163
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
104
+ * by the caller passing STACK_IGNFAULTS). Even in this case we will
164
rm_ofs = neon_reg_offset(rm, 0);
105
+ * still update the fault status registers.
165
106
*/
166
if ((insn & (1 << 23)) == 0) {
107
- if (!ignfault) {
167
- /* Three register same length. */
108
+ switch (mode) {
168
- op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
109
+ case STACK_NORMAL:
169
- /* Catch invalid op and bad size combinations: UNDEF */
110
armv7m_nvic_set_pending_derived(env->nvic, exc, exc_secure);
170
- if ((neon_3r_sizes[op] & (1 << size)) == 0) {
111
+ break;
171
- return 1;
112
+ case STACK_LAZYFP:
172
- }
113
+ armv7m_nvic_set_pending_lazyfp(env->nvic, exc, exc_secure);
173
- /* All insns of this form UNDEF for either this condition or the
114
+ break;
174
- * superset of cases "Q==1"; we catch the latter later.
115
+ case STACK_IGNFAULTS:
175
- */
116
+ break;
176
- if (q && ((rd | rn | rm) & 1)) {
117
}
177
- return 1;
118
return false;
178
- }
119
}
179
- switch (op) {
120
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
180
- case NEON_3R_VFM_VQRDMLSH:
121
uint32_t limit;
181
- if (!u) {
122
bool want_psp;
182
- /* VFM, VFMS */
123
uint32_t sig;
183
- if (size == 1) {
124
+ StackingMode smode = ignore_faults ? STACK_IGNFAULTS : STACK_NORMAL;
184
- return 1;
125
185
- }
126
if (dotailchain) {
186
- break;
127
bool mode = lr & R_V7M_EXCRET_MODE_MASK;
187
- }
128
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_callee_stack(ARMCPU *cpu, uint32_t lr, bool dotailchain,
188
- /* VQRDMLSH : handled by decodetree */
129
*/
189
- return 1;
130
sig = v7m_integrity_sig(env, lr);
190
-
131
stacked_ok =
191
- case NEON_3R_VADD_VSUB:
132
- v7m_stack_write(cpu, frameptr, sig, mmu_idx, ignore_faults) &&
192
- case NEON_3R_LOGIC:
133
- v7m_stack_write(cpu, frameptr + 0x8, env->regs[4], mmu_idx,
193
- case NEON_3R_VMAX:
134
- ignore_faults) &&
194
- case NEON_3R_VMIN:
135
- v7m_stack_write(cpu, frameptr + 0xc, env->regs[5], mmu_idx,
195
- case NEON_3R_VTST_VCEQ:
136
- ignore_faults) &&
196
- case NEON_3R_VCGT:
137
- v7m_stack_write(cpu, frameptr + 0x10, env->regs[6], mmu_idx,
197
- case NEON_3R_VCGE:
138
- ignore_faults) &&
198
- case NEON_3R_VQADD:
139
- v7m_stack_write(cpu, frameptr + 0x14, env->regs[7], mmu_idx,
199
- case NEON_3R_VQSUB:
140
- ignore_faults) &&
200
- case NEON_3R_VMUL:
141
- v7m_stack_write(cpu, frameptr + 0x18, env->regs[8], mmu_idx,
201
- case NEON_3R_VML:
142
- ignore_faults) &&
202
- case NEON_3R_VSHL:
143
- v7m_stack_write(cpu, frameptr + 0x1c, env->regs[9], mmu_idx,
203
- case NEON_3R_SHA:
144
- ignore_faults) &&
204
- case NEON_3R_VHADD:
145
- v7m_stack_write(cpu, frameptr + 0x20, env->regs[10], mmu_idx,
205
- case NEON_3R_VRHADD:
146
- ignore_faults) &&
206
- case NEON_3R_VHSUB:
147
- v7m_stack_write(cpu, frameptr + 0x24, env->regs[11], mmu_idx,
207
- case NEON_3R_VABD:
148
- ignore_faults);
208
- case NEON_3R_VABA:
149
+ v7m_stack_write(cpu, frameptr, sig, mmu_idx, smode) &&
209
- case NEON_3R_VQSHL:
150
+ v7m_stack_write(cpu, frameptr + 0x8, env->regs[4], mmu_idx, smode) &&
210
- case NEON_3R_VRSHL:
151
+ v7m_stack_write(cpu, frameptr + 0xc, env->regs[5], mmu_idx, smode) &&
211
- case NEON_3R_VQRSHL:
152
+ v7m_stack_write(cpu, frameptr + 0x10, env->regs[6], mmu_idx, smode) &&
212
- case NEON_3R_VPMAX:
153
+ v7m_stack_write(cpu, frameptr + 0x14, env->regs[7], mmu_idx, smode) &&
213
- case NEON_3R_VPMIN:
154
+ v7m_stack_write(cpu, frameptr + 0x18, env->regs[8], mmu_idx, smode) &&
214
- case NEON_3R_VPADD_VQRDMLAH:
155
+ v7m_stack_write(cpu, frameptr + 0x1c, env->regs[9], mmu_idx, smode) &&
215
- case NEON_3R_VQDMULH_VQRDMULH:
156
+ v7m_stack_write(cpu, frameptr + 0x20, env->regs[10], mmu_idx, smode) &&
216
- case NEON_3R_FLOAT_ARITH:
157
+ v7m_stack_write(cpu, frameptr + 0x24, env->regs[11], mmu_idx, smode);
217
- case NEON_3R_FLOAT_MULTIPLY:
158
218
- case NEON_3R_FLOAT_CMP:
159
/* Update SP regardless of whether any of the stack accesses failed. */
219
- case NEON_3R_FLOAT_ACMP:
160
*frame_sp_p = frameptr;
220
- case NEON_3R_FLOAT_MINMAX:
161
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
221
- case NEON_3R_FLOAT_MISC:
162
* if it has higher priority).
222
- /* Already handled by decodetree */
163
*/
223
- return 1;
164
stacked_ok = stacked_ok &&
224
- }
165
- v7m_stack_write(cpu, frameptr, env->regs[0], mmu_idx, false) &&
225
-
166
- v7m_stack_write(cpu, frameptr + 4, env->regs[1], mmu_idx, false) &&
226
- if (size == 3) {
167
- v7m_stack_write(cpu, frameptr + 8, env->regs[2], mmu_idx, false) &&
227
- /* 64-bit element instructions: handled by decodetree */
168
- v7m_stack_write(cpu, frameptr + 12, env->regs[3], mmu_idx, false) &&
228
- return 1;
169
- v7m_stack_write(cpu, frameptr + 16, env->regs[12], mmu_idx, false) &&
229
- }
170
- v7m_stack_write(cpu, frameptr + 20, env->regs[14], mmu_idx, false) &&
230
- switch (op) {
171
- v7m_stack_write(cpu, frameptr + 24, env->regs[15], mmu_idx, false) &&
231
- case NEON_3R_VFM_VQRDMLSH:
172
- v7m_stack_write(cpu, frameptr + 28, xpsr, mmu_idx, false);
232
- if (!dc_isar_feature(aa32_simdfmac, s)) {
173
+ v7m_stack_write(cpu, frameptr, env->regs[0], mmu_idx, STACK_NORMAL) &&
233
- return 1;
174
+ v7m_stack_write(cpu, frameptr + 4, env->regs[1],
234
- }
175
+ mmu_idx, STACK_NORMAL) &&
235
- break;
176
+ v7m_stack_write(cpu, frameptr + 8, env->regs[2],
236
- default:
177
+ mmu_idx, STACK_NORMAL) &&
237
- break;
178
+ v7m_stack_write(cpu, frameptr + 12, env->regs[3],
238
- }
179
+ mmu_idx, STACK_NORMAL) &&
239
-
180
+ v7m_stack_write(cpu, frameptr + 16, env->regs[12],
240
- for (pass = 0; pass < (q ? 4 : 2); pass++) {
181
+ mmu_idx, STACK_NORMAL) &&
241
-
182
+ v7m_stack_write(cpu, frameptr + 20, env->regs[14],
242
- /* Elementwise. */
183
+ mmu_idx, STACK_NORMAL) &&
243
- tmp = neon_load_reg(rn, pass);
184
+ v7m_stack_write(cpu, frameptr + 24, env->regs[15],
244
- tmp2 = neon_load_reg(rm, pass);
185
+ mmu_idx, STACK_NORMAL) &&
245
- switch (op) {
186
+ v7m_stack_write(cpu, frameptr + 28, xpsr, mmu_idx, STACK_NORMAL);
246
- case NEON_3R_VFM_VQRDMLSH:
187
247
- {
188
if (env->v7m.control[M_REG_S] & R_V7M_CONTROL_FPCA_MASK) {
248
- /* VFMA, VFMS: fused multiply-add */
189
/* FPU is active, try to save its registers */
249
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
190
@@ -XXX,XX +XXX,XX @@ static bool v7m_push_stack(ARMCPU *cpu)
250
- TCGv_i32 tmp3 = neon_load_reg(rd, pass);
191
faddr += 8; /* skip the slot for the FPSCR */
251
- if (size) {
192
}
252
- /* VFMS */
193
stacked_ok = stacked_ok &&
253
- gen_helper_vfp_negs(tmp, tmp);
194
- v7m_stack_write(cpu, faddr, slo, mmu_idx, false) &&
254
- }
195
- v7m_stack_write(cpu, faddr + 4, shi, mmu_idx, false);
255
- gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
196
+ v7m_stack_write(cpu, faddr, slo,
256
- tcg_temp_free_i32(tmp3);
197
+ mmu_idx, STACK_NORMAL) &&
257
- tcg_temp_free_ptr(fpstatus);
198
+ v7m_stack_write(cpu, faddr + 4, shi,
258
- break;
199
+ mmu_idx, STACK_NORMAL);
259
- }
200
}
260
- default:
201
stacked_ok = stacked_ok &&
261
- abort();
202
v7m_stack_write(cpu, frameptr + 0x60,
262
- }
203
- vfp_get_fpscr(env), mmu_idx, false);
263
- tcg_temp_free_i32(tmp2);
204
+ vfp_get_fpscr(env), mmu_idx, STACK_NORMAL);
264
-
205
if (cpacr_pass) {
265
- neon_store_reg(rd, pass, tmp);
206
for (i = 0; i < ((framesize == 0xa8) ? 32 : 16); i += 2) {
266
-
207
*aa32_vfp_dreg(env, i / 2) = 0;
267
- } /* for pass */
268
- /* End of 3 register same size operations. */
269
+ /* Three register same length: handled by decodetree */
270
+ return 1;
271
} else if (insn & (1 << 4)) {
272
if ((insn & 0x00380080) != 0) {
273
/* Two registers and shift. */
208
--
274
--
209
2.20.1
275
2.20.1
210
276
211
277
diff view generated by jsdifflib