1
The following changes since commit 61fee7f45955cd0bf9b79be9fa9c7ebabb5e6a85:
1
First pullreq for 6.0: mostly my v8.1M work, plus some other
2
bits and pieces. (I still have a lot of stuff in my to-review
3
folder, which I may or may not get to before the Christmas break...)
2
4
3
Merge remote-tracking branch 'remotes/philmd-gitlab/tags/acceptance-testing-20200622' into staging (2020-06-22 20:50:10 +0100)
5
thanks
6
-- PMM
7
8
The following changes since commit 5e7b204dbfae9a562fc73684986f936b97f63877:
9
10
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging (2020-12-09 20:08:54 +0000)
4
11
5
are available in the Git repository at:
12
are available in the Git repository at:
6
13
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200623
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20201210
8
15
9
for you to fetch changes up to 539533b85fbd269f777bed931de8ccae1dd837e9:
16
for you to fetch changes up to 71f916be1c7e9ede0e37d9cabc781b5a9e8638ff:
10
17
11
arm/virt: Add memory hot remove support (2020-06-23 11:39:48 +0100)
18
hw/arm/armv7m: Correct typo in QOM object name (2020-12-10 11:44:56 +0000)
12
19
13
----------------------------------------------------------------
20
----------------------------------------------------------------
14
target-arm queue:
21
target-arm queue:
15
* util/oslib-posix : qemu_init_exec_dir implementation for Mac
22
* hw/arm/smmuv3: Fix up L1STD_SPAN decoding
16
* target/arm: Last parts of neon decodetree conversion
23
* xlnx-zynqmp: Support Xilinx ZynqMP CAN controllers
17
* hw/arm/virt: Add 5.0 HW compat props
24
* sbsa-ref: allow to use Cortex-A53/57/72 cpus
18
* hw/watchdog/cmsdk-apb-watchdog: Add trace event for lock status
25
* Various minor code cleanups
19
* mps2: Add CMSDK APB watchdog, FPGAIO block, S2I devices and I2C devices
26
* hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault
20
* mps2: Add some unimplemented-device stubs for audio and GPIO
27
* Implement more pieces of ARMv8.1M support
21
* mps2-tz: Use the ARM SBCon two-wire serial bus interface
22
* target/arm: Check supported KVM features globally (not per vCPU)
23
* tests/qtest/arm-cpu-features: Add feature setting tests
24
* arm/virt: Add memory hot remove support
25
28
26
----------------------------------------------------------------
29
----------------------------------------------------------------
27
Andrew Jones (2):
30
Alex Chen (4):
28
hw/arm/virt: Add 5.0 HW compat props
31
i.MX25: Fix bad printf format specifiers
29
tests/qtest/arm-cpu-features: Add feature setting tests
32
i.MX31: Fix bad printf format specifiers
33
i.MX6: Fix bad printf format specifiers
34
i.MX6ul: Fix bad printf format specifiers
30
35
31
David CARLIER (1):
36
Havard Skinnemoen (1):
32
util/oslib-posix : qemu_init_exec_dir implementation for Mac
37
tests/qtest/npcm7xx_rng-test: dump random data on failure
33
38
34
Peter Maydell (23):
39
Kunkun Jiang (1):
35
target/arm: Convert Neon 2-reg-misc VREV64 to decodetree
40
hw/arm/smmuv3: Fix up L1STD_SPAN decoding
36
target/arm: Convert Neon 2-reg-misc pairwise ops to decodetree
37
target/arm: Convert VZIP, VUZP to decodetree
38
target/arm: Convert Neon narrowing moves to decodetree
39
target/arm: Convert Neon 2-reg-misc VSHLL to decodetree
40
target/arm: Convert Neon VCVT f16/f32 insns to decodetree
41
target/arm: Convert vectorised 2-reg-misc Neon ops to decodetree
42
target/arm: Convert Neon 2-reg-misc crypto operations to decodetree
43
target/arm: Rename NeonGenOneOpFn to NeonGenOne64OpFn
44
target/arm: Fix capitalization in NeonGenTwo{Single, Double}OPFn typedefs
45
target/arm: Make gen_swap_half() take separate src and dest
46
target/arm: Convert Neon 2-reg-misc VREV32 and VREV16 to decodetree
47
target/arm: Convert remaining simple 2-reg-misc Neon ops
48
target/arm: Convert Neon VQABS, VQNEG to decodetree
49
target/arm: Convert simple fp Neon 2-reg-misc insns
50
target/arm: Convert Neon 2-reg-misc fp-compare-with-zero insns to decodetree
51
target/arm: Convert Neon 2-reg-misc VRINT insns to decodetree
52
target/arm: Convert Neon 2-reg-misc VCVT insns to decodetree
53
target/arm: Convert Neon VSWP to decodetree
54
target/arm: Convert Neon VTRN to decodetree
55
target/arm: Move some functions used only in translate-neon.inc.c to that file
56
target/arm: Remove unnecessary gen_io_end() calls
57
target/arm: Remove dead code relating to SABA and UABA
58
41
59
Philippe Mathieu-Daudé (15):
42
Marcin Juszkiewicz (1):
60
hw/watchdog/cmsdk-apb-watchdog: Add trace event for lock status
43
sbsa-ref: allow to use Cortex-A53/57/72 cpus
61
hw/i2c/versatile_i2c: Add definitions for register addresses
62
hw/i2c/versatile_i2c: Add SCL/SDA definitions
63
hw/i2c: Add header for ARM SBCon two-wire serial bus interface
64
hw/arm: Use TYPE_VERSATILE_I2C instead of hardcoded string
65
hw/arm/mps2: Document CMSDK/FPGA APB subsystem sections
66
hw/arm/mps2: Rename CMSDK AHB peripheral region
67
hw/arm/mps2: Add CMSDK APB watchdog device
68
hw/arm/mps2: Add CMSDK AHB GPIO peripherals as unimplemented devices
69
hw/arm/mps2: Map the FPGA I/O block
70
hw/arm/mps2: Add SPI devices
71
hw/arm/mps2: Add I2C devices
72
hw/arm/mps2: Add audio I2S interface as unimplemented device
73
hw/arm/mps2-tz: Use the ARM SBCon two-wire serial bus interface
74
target/arm: Check supported KVM features globally (not per vCPU)
75
44
76
Shameer Kolothum (1):
45
Peter Maydell (25):
77
arm/virt: Add memory hot remove support
46
hw/intc/armv7m_nvic: Make all of system PPB range be RAZWI/BusFault
47
target/arm: Implement v8.1M PXN extension
48
target/arm: Don't clobber ID_PFR1.Security on M-profile cores
49
target/arm: Implement VSCCLRM insn
50
target/arm: Implement CLRM instruction
51
target/arm: Enforce M-profile VMRS/VMSR register restrictions
52
target/arm: Refactor M-profile VMSR/VMRS handling
53
target/arm: Move general-use constant expanders up in translate.c
54
target/arm: Implement VLDR/VSTR system register
55
target/arm: Implement M-profile FPSCR_nzcvqc
56
target/arm: Use new FPCR_NZCV_MASK constant
57
target/arm: Factor out preserve-fp-state from full_vfp_access_check()
58
target/arm: Implement FPCXT_S fp system register
59
hw/intc/armv7m_nvic: Update FPDSCR masking for v8.1M
60
target/arm: For v8.1M, always clear R0-R3, R12, APSR, EPSR on exception entry
61
target/arm: In v8.1M, don't set HFSR.FORCED on vector table fetch failures
62
target/arm: Implement v8.1M REVIDR register
63
target/arm: Implement new v8.1M NOCP check for exception return
64
target/arm: Implement new v8.1M VLLDM and VLSTM encodings
65
hw/intc/armv7m_nvic: Support v8.1M CCR.TRD bit
66
target/arm: Implement CCR_S.TRD behaviour for SG insns
67
hw/intc/armv7m_nvic: Fix "return from inactive handler" check
68
target/arm: Implement M-profile "minimal RAS implementation"
69
hw/intc/armv7m_nvic: Implement read/write for RAS register block
70
hw/arm/armv7m: Correct typo in QOM object name
78
71
79
include/hw/i2c/arm_sbcon_i2c.h | 35 ++
72
Vikram Garhwal (4):
80
target/arm/cpu.h | 2 +-
73
hw/net/can: Introduce Xilinx ZynqMP CAN controller
81
target/arm/kvm_arm.h | 21 +-
74
xlnx-zynqmp: Connect Xilinx ZynqMP CAN controllers
82
target/arm/translate.h | 8 +-
75
tests/qtest: Introduce tests for Xilinx ZynqMP CAN controller
83
target/arm/neon-dp.decode | 106 ++++
76
MAINTAINERS: Add maintainer entry for Xilinx ZynqMP CAN controller
84
hw/acpi/generic_event_device.c | 29 +
85
hw/arm/mps2-tz.c | 23 +-
86
hw/arm/mps2.c | 65 ++-
87
hw/arm/realview.c | 3 +-
88
hw/arm/versatilepb.c | 3 +-
89
hw/arm/vexpress.c | 3 +-
90
hw/arm/virt.c | 63 +-
91
hw/i2c/versatile_i2c.c | 38 +-
92
hw/watchdog/cmsdk-apb-watchdog.c | 1 +
93
target/arm/cpu.c | 2 +-
94
target/arm/cpu64.c | 10 +-
95
target/arm/kvm.c | 4 +-
96
target/arm/kvm64.c | 14 +-
97
target/arm/translate-a64.c | 20 +-
98
target/arm/translate-neon.inc.c | 1191 +++++++++++++++++++++++++++++++++++++-
99
target/arm/translate-vfp.inc.c | 7 +-
100
target/arm/translate.c | 1064 +---------------------------------
101
tests/qtest/arm-cpu-features.c | 38 +-
102
util/oslib-posix.c | 15 +
103
MAINTAINERS | 1 +
104
hw/arm/Kconfig | 8 +-
105
hw/watchdog/trace-events | 1 +
106
27 files changed, 1624 insertions(+), 1151 deletions(-)
107
create mode 100644 include/hw/i2c/arm_sbcon_i2c.h
108
77
78
meson.build | 1 +
79
hw/arm/smmuv3-internal.h | 2 +-
80
hw/net/can/trace.h | 1 +
81
include/hw/arm/xlnx-zynqmp.h | 8 +
82
include/hw/intc/armv7m_nvic.h | 2 +
83
include/hw/net/xlnx-zynqmp-can.h | 78 +++
84
target/arm/cpu.h | 46 ++
85
target/arm/m-nocp.decode | 10 +-
86
target/arm/t32.decode | 10 +-
87
target/arm/vfp.decode | 14 +
88
hw/arm/armv7m.c | 4 +-
89
hw/arm/sbsa-ref.c | 23 +-
90
hw/arm/xlnx-zcu102.c | 20 +
91
hw/arm/xlnx-zynqmp.c | 34 ++
92
hw/intc/armv7m_nvic.c | 246 ++++++--
93
hw/misc/imx25_ccm.c | 12 +-
94
hw/misc/imx31_ccm.c | 14 +-
95
hw/misc/imx6_ccm.c | 20 +-
96
hw/misc/imx6_src.c | 2 +-
97
hw/misc/imx6ul_ccm.c | 4 +-
98
hw/misc/imx_ccm.c | 4 +-
99
hw/net/can/xlnx-zynqmp-can.c | 1161 ++++++++++++++++++++++++++++++++++++++
100
target/arm/cpu.c | 5 +-
101
target/arm/helper.c | 7 +-
102
target/arm/m_helper.c | 130 ++++-
103
target/arm/translate.c | 105 +++-
104
tests/qtest/npcm7xx_rng-test.c | 12 +
105
tests/qtest/xlnx-can-test.c | 360 ++++++++++++
106
MAINTAINERS | 8 +
107
hw/Kconfig | 1 +
108
hw/net/can/meson.build | 1 +
109
hw/net/can/trace-events | 9 +
110
target/arm/translate-vfp.c.inc | 511 ++++++++++++++++-
111
tests/qtest/meson.build | 1 +
112
34 files changed, 2713 insertions(+), 153 deletions(-)
113
create mode 100644 hw/net/can/trace.h
114
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
115
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
116
create mode 100644 tests/qtest/xlnx-can-test.c
117
create mode 100644 hw/net/can/trace-events
118
diff view generated by jsdifflib
Deleted patch
1
From: Andrew Jones <drjones@redhat.com>
2
1
3
Cc: Cornelia Huck <cohuck@redhat.com>
4
Signed-off-by: Andrew Jones <drjones@redhat.com>
5
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
6
Message-id: 20200616140803.25515-1-drjones@redhat.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
hw/arm/virt.c | 1 +
10
1 file changed, 1 insertion(+)
11
12
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/virt.c
15
+++ b/hw/arm/virt.c
16
@@ -XXX,XX +XXX,XX @@ DEFINE_VIRT_MACHINE_AS_LATEST(5, 1)
17
static void virt_machine_5_0_options(MachineClass *mc)
18
{
19
virt_machine_5_1_options(mc);
20
+ compat_props_add(mc->compat_props, hw_compat_5_0, hw_compat_5_0_len);
21
}
22
DEFINE_VIRT_MACHINE(5, 0)
23
24
--
25
2.20.1
26
27
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Kunkun Jiang <jiangkunkun@huawei.com>
2
2
3
From 'Application Note AN521', chapter 4.7:
3
Accroding to the SMMUv3 spec, the SPAN field of Level1 Stream Table
4
Descriptor is 5 bits([4:0]).
4
5
5
The SMM implements four SBCon serial modules:
6
Fixes: 9bde7f0674f(hw/arm/smmuv3: Implement translate callback)
6
7
Signed-off-by: Kunkun Jiang <jiangkunkun@huawei.com>
7
One SBCon module for use by the Color LCD touch interface.
8
Message-id: 20201124023711.1184-1-jiangkunkun@huawei.com
8
One SBCon module to configure the audio controller.
9
Two general purpose SBCon modules, that connect to the
10
Expansion headers J7 and J8, are intended for use with the
11
V2C-Shield1 which provide an I2C interface on the headers.
12
13
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Message-id: 20200617072539.32686-15-f4bug@amsat.org
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Acked-by: Eric Auger <eric.auger@redhat.com>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
12
---
18
hw/arm/mps2-tz.c | 23 ++++++++++++++++++-----
13
hw/arm/smmuv3-internal.h | 2 +-
19
1 file changed, 18 insertions(+), 5 deletions(-)
14
1 file changed, 1 insertion(+), 1 deletion(-)
20
15
21
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
16
diff --git a/hw/arm/smmuv3-internal.h b/hw/arm/smmuv3-internal.h
22
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/mps2-tz.c
18
--- a/hw/arm/smmuv3-internal.h
24
+++ b/hw/arm/mps2-tz.c
19
+++ b/hw/arm/smmuv3-internal.h
25
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static inline uint64_t l1std_l2ptr(STEDesc *desc)
26
#include "hw/arm/armsse.h"
21
return hi << 32 | lo;
27
#include "hw/dma/pl080.h"
28
#include "hw/ssi/pl022.h"
29
+#include "hw/i2c/arm_sbcon_i2c.h"
30
#include "hw/net/lan9118.h"
31
#include "net/net.h"
32
#include "hw/core/split-irq.h"
33
@@ -XXX,XX +XXX,XX @@ typedef struct {
34
TZPPC ppc[5];
35
TZMPC ssram_mpc[3];
36
PL022State spi[5];
37
- UnimplementedDeviceState i2c[4];
38
+ ArmSbconI2CState i2c[4];
39
UnimplementedDeviceState i2s_audio;
40
UnimplementedDeviceState gpio[4];
41
UnimplementedDeviceState gfx;
42
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
43
return sysbus_mmio_get_region(s, 0);
44
}
22
}
45
23
46
+static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
24
-#define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 4))
47
+ const char *name, hwaddr size)
25
+#define L1STD_SPAN(stm) (extract32((stm)->word[0], 0, 5))
48
+{
26
49
+ ArmSbconI2CState *i2c = opaque;
27
#endif
50
+ SysBusDevice *s;
51
+
52
+ object_initialize_child(OBJECT(mms), name, i2c, TYPE_ARM_SBCON_I2C);
53
+ s = SYS_BUS_DEVICE(i2c);
54
+ sysbus_realize(s, &error_fatal);
55
+ return sysbus_mmio_get_region(s, 0);
56
+}
57
+
58
static void mps2tz_common_init(MachineState *machine)
59
{
60
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
61
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
62
{ "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000 },
63
{ "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000 },
64
{ "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000 },
65
- { "i2c0", make_unimp_dev, &mms->i2c[0], 0x40207000, 0x1000 },
66
- { "i2c1", make_unimp_dev, &mms->i2c[1], 0x40208000, 0x1000 },
67
- { "i2c2", make_unimp_dev, &mms->i2c[2], 0x4020c000, 0x1000 },
68
- { "i2c3", make_unimp_dev, &mms->i2c[3], 0x4020d000, 0x1000 },
69
+ { "i2c0", make_i2c, &mms->i2c[0], 0x40207000, 0x1000 },
70
+ { "i2c1", make_i2c, &mms->i2c[1], 0x40208000, 0x1000 },
71
+ { "i2c2", make_i2c, &mms->i2c[2], 0x4020c000, 0x1000 },
72
+ { "i2c3", make_i2c, &mms->i2c[3], 0x4020d000, 0x1000 },
73
},
74
}, {
75
.name = "apb_ppcexp2",
76
--
28
--
77
2.20.1
29
2.20.1
78
30
79
31
diff view generated by jsdifflib
1
From: David CARLIER <devnexen@gmail.com>
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
2
3
From 3025a0ce3fdf7d3559fc35a52c659f635f5c750c Mon Sep 17 00:00:00 2001
3
The Xilinx ZynqMP CAN controller is developed based on SocketCAN, QEMU CAN bus
4
From: David Carlier <devnexen@gmail.com>
4
implementation. Bus connection and socketCAN connection for each CAN module
5
Date: Tue, 26 May 2020 21:35:27 +0100
5
can be set through command lines.
6
Subject: [PATCH] util/oslib-posix : qemu_init_exec_dir implementation for Mac
7
6
8
Using dyld API to get the full path of the current process.
7
Example for using single CAN:
8
-object can-bus,id=canbus0 \
9
-machine xlnx-zcu102.canbus0=canbus0 \
10
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0
9
11
10
Signed-off-by: David Carlier <devnexen@gmail.com>
12
Example for connecting both CAN to same virtual CAN on host machine:
11
Message-id: CA+XhMqxwC10XHVs4Z-JfE0-WLAU3ztDuU9QKVi31mjr59HWCxg@mail.gmail.com
13
-object can-bus,id=canbus0 -object can-bus,id=canbus1 \
14
-machine xlnx-zcu102.canbus0=canbus0 \
15
-machine xlnx-zcu102.canbus1=canbus1 \
16
-object can-host-socketcan,id=socketcan0,if=vcan0,canbus=canbus0 \
17
-object can-host-socketcan,id=socketcan1,if=vcan0,canbus=canbus1
18
19
To create virtual CAN on the host machine, please check the QEMU CAN docs:
20
https://github.com/qemu/qemu/blob/master/docs/can.txt
21
22
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
23
Message-id: 1605728926-352690-2-git-send-email-fnu.vikram@xilinx.com
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
26
---
15
util/oslib-posix.c | 15 +++++++++++++++
27
meson.build | 1 +
16
1 file changed, 15 insertions(+)
28
hw/net/can/trace.h | 1 +
29
include/hw/net/xlnx-zynqmp-can.h | 78 ++
30
hw/net/can/xlnx-zynqmp-can.c | 1161 ++++++++++++++++++++++++++++++
31
hw/Kconfig | 1 +
32
hw/net/can/meson.build | 1 +
33
hw/net/can/trace-events | 9 +
34
7 files changed, 1252 insertions(+)
35
create mode 100644 hw/net/can/trace.h
36
create mode 100644 include/hw/net/xlnx-zynqmp-can.h
37
create mode 100644 hw/net/can/xlnx-zynqmp-can.c
38
create mode 100644 hw/net/can/trace-events
17
39
18
diff --git a/util/oslib-posix.c b/util/oslib-posix.c
40
diff --git a/meson.build b/meson.build
19
index XXXXXXX..XXXXXXX 100644
41
index XXXXXXX..XXXXXXX 100644
20
--- a/util/oslib-posix.c
42
--- a/meson.build
21
+++ b/util/oslib-posix.c
43
+++ b/meson.build
44
@@ -XXX,XX +XXX,XX @@ if have_system
45
'hw/misc',
46
'hw/misc/macio',
47
'hw/net',
48
+ 'hw/net/can',
49
'hw/nvram',
50
'hw/pci',
51
'hw/pci-host',
52
diff --git a/hw/net/can/trace.h b/hw/net/can/trace.h
53
new file mode 100644
54
index XXXXXXX..XXXXXXX
55
--- /dev/null
56
+++ b/hw/net/can/trace.h
57
@@ -0,0 +1 @@
58
+#include "trace/trace-hw_net_can.h"
59
diff --git a/include/hw/net/xlnx-zynqmp-can.h b/include/hw/net/xlnx-zynqmp-can.h
60
new file mode 100644
61
index XXXXXXX..XXXXXXX
62
--- /dev/null
63
+++ b/include/hw/net/xlnx-zynqmp-can.h
22
@@ -XXX,XX +XXX,XX @@
64
@@ -XXX,XX +XXX,XX @@
23
#include <lwp.h>
65
+/*
24
#endif
66
+ * QEMU model of the Xilinx ZynqMP CAN controller.
25
67
+ *
26
+#ifdef __APPLE__
68
+ * Copyright (c) 2020 Xilinx Inc.
27
+#include <mach-o/dyld.h>
69
+ *
70
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
71
+ *
72
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
73
+ * Pavel Pisa.
74
+ *
75
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
76
+ * of this software and associated documentation files (the "Software"), to deal
77
+ * in the Software without restriction, including without limitation the rights
78
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
79
+ * copies of the Software, and to permit persons to whom the Software is
80
+ * furnished to do so, subject to the following conditions:
81
+ *
82
+ * The above copyright notice and this permission notice shall be included in
83
+ * all copies or substantial portions of the Software.
84
+ *
85
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
86
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
87
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
88
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
89
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
90
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
91
+ * THE SOFTWARE.
92
+ */
93
+
94
+#ifndef XLNX_ZYNQMP_CAN_H
95
+#define XLNX_ZYNQMP_CAN_H
96
+
97
+#include "hw/register.h"
98
+#include "net/can_emu.h"
99
+#include "net/can_host.h"
100
+#include "qemu/fifo32.h"
101
+#include "hw/ptimer.h"
102
+#include "hw/qdev-clock.h"
103
+
104
+#define TYPE_XLNX_ZYNQMP_CAN "xlnx.zynqmp-can"
105
+
106
+#define XLNX_ZYNQMP_CAN(obj) \
107
+ OBJECT_CHECK(XlnxZynqMPCANState, (obj), TYPE_XLNX_ZYNQMP_CAN)
108
+
109
+#define MAX_CAN_CTRLS 2
110
+#define XLNX_ZYNQMP_CAN_R_MAX (0x84 / 4)
111
+#define MAILBOX_CAPACITY 64
112
+#define CAN_TIMER_MAX 0XFFFFUL
113
+#define CAN_DEFAULT_CLOCK (24 * 1000 * 1000)
114
+
115
+/* Each CAN_FRAME will have 4 * 32bit size. */
116
+#define CAN_FRAME_SIZE 4
117
+#define RXFIFO_SIZE (MAILBOX_CAPACITY * CAN_FRAME_SIZE)
118
+
119
+typedef struct XlnxZynqMPCANState {
120
+ SysBusDevice parent_obj;
121
+ MemoryRegion iomem;
122
+
123
+ qemu_irq irq;
124
+
125
+ CanBusClientState bus_client;
126
+ CanBusState *canbus;
127
+
128
+ struct {
129
+ uint32_t ext_clk_freq;
130
+ } cfg;
131
+
132
+ RegisterInfo reg_info[XLNX_ZYNQMP_CAN_R_MAX];
133
+ uint32_t regs[XLNX_ZYNQMP_CAN_R_MAX];
134
+
135
+ Fifo32 rx_fifo;
136
+ Fifo32 tx_fifo;
137
+ Fifo32 txhpb_fifo;
138
+
139
+ ptimer_state *can_timer;
140
+} XlnxZynqMPCANState;
141
+
28
+#endif
142
+#endif
29
+
143
diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
30
#include "qemu/mmap-alloc.h"
144
new file mode 100644
31
145
index XXXXXXX..XXXXXXX
32
#ifdef CONFIG_DEBUG_STACK_USAGE
146
--- /dev/null
33
@@ -XXX,XX +XXX,XX @@ void qemu_init_exec_dir(const char *argv0)
147
+++ b/hw/net/can/xlnx-zynqmp-can.c
34
p = buf;
148
@@ -XXX,XX +XXX,XX @@
35
}
149
+/*
36
}
150
+ * QEMU model of the Xilinx ZynqMP CAN controller.
37
+#elif defined(__APPLE__)
151
+ * This implementation is based on the following datasheet:
38
+ {
152
+ * https://www.xilinx.com/support/documentation/user_guides/ug1085-zynq-ultrascale-trm.pdf
39
+ char fpath[PATH_MAX];
153
+ *
40
+ uint32_t len = sizeof(fpath);
154
+ * Copyright (c) 2020 Xilinx Inc.
41
+ if (_NSGetExecutablePath(fpath, &len) == 0) {
155
+ *
42
+ p = realpath(fpath, buf);
156
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
43
+ if (!p) {
157
+ *
44
+ return;
158
+ * Based on QEMU CAN Device emulation implemented by Jin Yang, Deniz Eren and
159
+ * Pavel Pisa
160
+ *
161
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
162
+ * of this software and associated documentation files (the "Software"), to deal
163
+ * in the Software without restriction, including without limitation the rights
164
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
165
+ * copies of the Software, and to permit persons to whom the Software is
166
+ * furnished to do so, subject to the following conditions:
167
+ *
168
+ * The above copyright notice and this permission notice shall be included in
169
+ * all copies or substantial portions of the Software.
170
+ *
171
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
172
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
173
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
174
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
175
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
176
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
177
+ * THE SOFTWARE.
178
+ */
179
+
180
+#include "qemu/osdep.h"
181
+#include "hw/sysbus.h"
182
+#include "hw/register.h"
183
+#include "hw/irq.h"
184
+#include "qapi/error.h"
185
+#include "qemu/bitops.h"
186
+#include "qemu/log.h"
187
+#include "qemu/cutils.h"
188
+#include "sysemu/sysemu.h"
189
+#include "migration/vmstate.h"
190
+#include "hw/qdev-properties.h"
191
+#include "net/can_emu.h"
192
+#include "net/can_host.h"
193
+#include "qemu/event_notifier.h"
194
+#include "qom/object_interfaces.h"
195
+#include "hw/net/xlnx-zynqmp-can.h"
196
+#include "trace.h"
197
+
198
+#ifndef XLNX_ZYNQMP_CAN_ERR_DEBUG
199
+#define XLNX_ZYNQMP_CAN_ERR_DEBUG 0
200
+#endif
201
+
202
+#define MAX_DLC 8
203
+#undef ERROR
204
+
205
+REG32(SOFTWARE_RESET_REGISTER, 0x0)
206
+ FIELD(SOFTWARE_RESET_REGISTER, CEN, 1, 1)
207
+ FIELD(SOFTWARE_RESET_REGISTER, SRST, 0, 1)
208
+REG32(MODE_SELECT_REGISTER, 0x4)
209
+ FIELD(MODE_SELECT_REGISTER, SNOOP, 2, 1)
210
+ FIELD(MODE_SELECT_REGISTER, LBACK, 1, 1)
211
+ FIELD(MODE_SELECT_REGISTER, SLEEP, 0, 1)
212
+REG32(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, 0x8)
213
+ FIELD(ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER, BRP, 0, 8)
214
+REG32(ARBITRATION_PHASE_BIT_TIMING_REGISTER, 0xc)
215
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, SJW, 7, 2)
216
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS2, 4, 3)
217
+ FIELD(ARBITRATION_PHASE_BIT_TIMING_REGISTER, TS1, 0, 4)
218
+REG32(ERROR_COUNTER_REGISTER, 0x10)
219
+ FIELD(ERROR_COUNTER_REGISTER, REC, 8, 8)
220
+ FIELD(ERROR_COUNTER_REGISTER, TEC, 0, 8)
221
+REG32(ERROR_STATUS_REGISTER, 0x14)
222
+ FIELD(ERROR_STATUS_REGISTER, ACKER, 4, 1)
223
+ FIELD(ERROR_STATUS_REGISTER, BERR, 3, 1)
224
+ FIELD(ERROR_STATUS_REGISTER, STER, 2, 1)
225
+ FIELD(ERROR_STATUS_REGISTER, FMER, 1, 1)
226
+ FIELD(ERROR_STATUS_REGISTER, CRCER, 0, 1)
227
+REG32(STATUS_REGISTER, 0x18)
228
+ FIELD(STATUS_REGISTER, SNOOP, 12, 1)
229
+ FIELD(STATUS_REGISTER, ACFBSY, 11, 1)
230
+ FIELD(STATUS_REGISTER, TXFLL, 10, 1)
231
+ FIELD(STATUS_REGISTER, TXBFLL, 9, 1)
232
+ FIELD(STATUS_REGISTER, ESTAT, 7, 2)
233
+ FIELD(STATUS_REGISTER, ERRWRN, 6, 1)
234
+ FIELD(STATUS_REGISTER, BBSY, 5, 1)
235
+ FIELD(STATUS_REGISTER, BIDLE, 4, 1)
236
+ FIELD(STATUS_REGISTER, NORMAL, 3, 1)
237
+ FIELD(STATUS_REGISTER, SLEEP, 2, 1)
238
+ FIELD(STATUS_REGISTER, LBACK, 1, 1)
239
+ FIELD(STATUS_REGISTER, CONFIG, 0, 1)
240
+REG32(INTERRUPT_STATUS_REGISTER, 0x1c)
241
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFEMP, 14, 1)
242
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFWMEMP, 13, 1)
243
+ FIELD(INTERRUPT_STATUS_REGISTER, RXFWMFLL, 12, 1)
244
+ FIELD(INTERRUPT_STATUS_REGISTER, WKUP, 11, 1)
245
+ FIELD(INTERRUPT_STATUS_REGISTER, SLP, 10, 1)
246
+ FIELD(INTERRUPT_STATUS_REGISTER, BSOFF, 9, 1)
247
+ FIELD(INTERRUPT_STATUS_REGISTER, ERROR, 8, 1)
248
+ FIELD(INTERRUPT_STATUS_REGISTER, RXNEMP, 7, 1)
249
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOFLW, 6, 1)
250
+ FIELD(INTERRUPT_STATUS_REGISTER, RXUFLW, 5, 1)
251
+ FIELD(INTERRUPT_STATUS_REGISTER, RXOK, 4, 1)
252
+ FIELD(INTERRUPT_STATUS_REGISTER, TXBFLL, 3, 1)
253
+ FIELD(INTERRUPT_STATUS_REGISTER, TXFLL, 2, 1)
254
+ FIELD(INTERRUPT_STATUS_REGISTER, TXOK, 1, 1)
255
+ FIELD(INTERRUPT_STATUS_REGISTER, ARBLST, 0, 1)
256
+REG32(INTERRUPT_ENABLE_REGISTER, 0x20)
257
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFEMP, 14, 1)
258
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFWMEMP, 13, 1)
259
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXFWMFLL, 12, 1)
260
+ FIELD(INTERRUPT_ENABLE_REGISTER, EWKUP, 11, 1)
261
+ FIELD(INTERRUPT_ENABLE_REGISTER, ESLP, 10, 1)
262
+ FIELD(INTERRUPT_ENABLE_REGISTER, EBSOFF, 9, 1)
263
+ FIELD(INTERRUPT_ENABLE_REGISTER, EERROR, 8, 1)
264
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXNEMP, 7, 1)
265
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOFLW, 6, 1)
266
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXUFLW, 5, 1)
267
+ FIELD(INTERRUPT_ENABLE_REGISTER, ERXOK, 4, 1)
268
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXBFLL, 3, 1)
269
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXFLL, 2, 1)
270
+ FIELD(INTERRUPT_ENABLE_REGISTER, ETXOK, 1, 1)
271
+ FIELD(INTERRUPT_ENABLE_REGISTER, EARBLST, 0, 1)
272
+REG32(INTERRUPT_CLEAR_REGISTER, 0x24)
273
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFEMP, 14, 1)
274
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFWMEMP, 13, 1)
275
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXFWMFLL, 12, 1)
276
+ FIELD(INTERRUPT_CLEAR_REGISTER, CWKUP, 11, 1)
277
+ FIELD(INTERRUPT_CLEAR_REGISTER, CSLP, 10, 1)
278
+ FIELD(INTERRUPT_CLEAR_REGISTER, CBSOFF, 9, 1)
279
+ FIELD(INTERRUPT_CLEAR_REGISTER, CERROR, 8, 1)
280
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXNEMP, 7, 1)
281
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOFLW, 6, 1)
282
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXUFLW, 5, 1)
283
+ FIELD(INTERRUPT_CLEAR_REGISTER, CRXOK, 4, 1)
284
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXBFLL, 3, 1)
285
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXFLL, 2, 1)
286
+ FIELD(INTERRUPT_CLEAR_REGISTER, CTXOK, 1, 1)
287
+ FIELD(INTERRUPT_CLEAR_REGISTER, CARBLST, 0, 1)
288
+REG32(TIMESTAMP_REGISTER, 0x28)
289
+ FIELD(TIMESTAMP_REGISTER, CTS, 0, 1)
290
+REG32(WIR, 0x2c)
291
+ FIELD(WIR, EW, 8, 8)
292
+ FIELD(WIR, FW, 0, 8)
293
+REG32(TXFIFO_ID, 0x30)
294
+ FIELD(TXFIFO_ID, IDH, 21, 11)
295
+ FIELD(TXFIFO_ID, SRRRTR, 20, 1)
296
+ FIELD(TXFIFO_ID, IDE, 19, 1)
297
+ FIELD(TXFIFO_ID, IDL, 1, 18)
298
+ FIELD(TXFIFO_ID, RTR, 0, 1)
299
+REG32(TXFIFO_DLC, 0x34)
300
+ FIELD(TXFIFO_DLC, DLC, 28, 4)
301
+REG32(TXFIFO_DATA1, 0x38)
302
+ FIELD(TXFIFO_DATA1, DB0, 24, 8)
303
+ FIELD(TXFIFO_DATA1, DB1, 16, 8)
304
+ FIELD(TXFIFO_DATA1, DB2, 8, 8)
305
+ FIELD(TXFIFO_DATA1, DB3, 0, 8)
306
+REG32(TXFIFO_DATA2, 0x3c)
307
+ FIELD(TXFIFO_DATA2, DB4, 24, 8)
308
+ FIELD(TXFIFO_DATA2, DB5, 16, 8)
309
+ FIELD(TXFIFO_DATA2, DB6, 8, 8)
310
+ FIELD(TXFIFO_DATA2, DB7, 0, 8)
311
+REG32(TXHPB_ID, 0x40)
312
+ FIELD(TXHPB_ID, IDH, 21, 11)
313
+ FIELD(TXHPB_ID, SRRRTR, 20, 1)
314
+ FIELD(TXHPB_ID, IDE, 19, 1)
315
+ FIELD(TXHPB_ID, IDL, 1, 18)
316
+ FIELD(TXHPB_ID, RTR, 0, 1)
317
+REG32(TXHPB_DLC, 0x44)
318
+ FIELD(TXHPB_DLC, DLC, 28, 4)
319
+REG32(TXHPB_DATA1, 0x48)
320
+ FIELD(TXHPB_DATA1, DB0, 24, 8)
321
+ FIELD(TXHPB_DATA1, DB1, 16, 8)
322
+ FIELD(TXHPB_DATA1, DB2, 8, 8)
323
+ FIELD(TXHPB_DATA1, DB3, 0, 8)
324
+REG32(TXHPB_DATA2, 0x4c)
325
+ FIELD(TXHPB_DATA2, DB4, 24, 8)
326
+ FIELD(TXHPB_DATA2, DB5, 16, 8)
327
+ FIELD(TXHPB_DATA2, DB6, 8, 8)
328
+ FIELD(TXHPB_DATA2, DB7, 0, 8)
329
+REG32(RXFIFO_ID, 0x50)
330
+ FIELD(RXFIFO_ID, IDH, 21, 11)
331
+ FIELD(RXFIFO_ID, SRRRTR, 20, 1)
332
+ FIELD(RXFIFO_ID, IDE, 19, 1)
333
+ FIELD(RXFIFO_ID, IDL, 1, 18)
334
+ FIELD(RXFIFO_ID, RTR, 0, 1)
335
+REG32(RXFIFO_DLC, 0x54)
336
+ FIELD(RXFIFO_DLC, DLC, 28, 4)
337
+ FIELD(RXFIFO_DLC, RXT, 0, 16)
338
+REG32(RXFIFO_DATA1, 0x58)
339
+ FIELD(RXFIFO_DATA1, DB0, 24, 8)
340
+ FIELD(RXFIFO_DATA1, DB1, 16, 8)
341
+ FIELD(RXFIFO_DATA1, DB2, 8, 8)
342
+ FIELD(RXFIFO_DATA1, DB3, 0, 8)
343
+REG32(RXFIFO_DATA2, 0x5c)
344
+ FIELD(RXFIFO_DATA2, DB4, 24, 8)
345
+ FIELD(RXFIFO_DATA2, DB5, 16, 8)
346
+ FIELD(RXFIFO_DATA2, DB6, 8, 8)
347
+ FIELD(RXFIFO_DATA2, DB7, 0, 8)
348
+REG32(AFR, 0x60)
349
+ FIELD(AFR, UAF4, 3, 1)
350
+ FIELD(AFR, UAF3, 2, 1)
351
+ FIELD(AFR, UAF2, 1, 1)
352
+ FIELD(AFR, UAF1, 0, 1)
353
+REG32(AFMR1, 0x64)
354
+ FIELD(AFMR1, AMIDH, 21, 11)
355
+ FIELD(AFMR1, AMSRR, 20, 1)
356
+ FIELD(AFMR1, AMIDE, 19, 1)
357
+ FIELD(AFMR1, AMIDL, 1, 18)
358
+ FIELD(AFMR1, AMRTR, 0, 1)
359
+REG32(AFIR1, 0x68)
360
+ FIELD(AFIR1, AIIDH, 21, 11)
361
+ FIELD(AFIR1, AISRR, 20, 1)
362
+ FIELD(AFIR1, AIIDE, 19, 1)
363
+ FIELD(AFIR1, AIIDL, 1, 18)
364
+ FIELD(AFIR1, AIRTR, 0, 1)
365
+REG32(AFMR2, 0x6c)
366
+ FIELD(AFMR2, AMIDH, 21, 11)
367
+ FIELD(AFMR2, AMSRR, 20, 1)
368
+ FIELD(AFMR2, AMIDE, 19, 1)
369
+ FIELD(AFMR2, AMIDL, 1, 18)
370
+ FIELD(AFMR2, AMRTR, 0, 1)
371
+REG32(AFIR2, 0x70)
372
+ FIELD(AFIR2, AIIDH, 21, 11)
373
+ FIELD(AFIR2, AISRR, 20, 1)
374
+ FIELD(AFIR2, AIIDE, 19, 1)
375
+ FIELD(AFIR2, AIIDL, 1, 18)
376
+ FIELD(AFIR2, AIRTR, 0, 1)
377
+REG32(AFMR3, 0x74)
378
+ FIELD(AFMR3, AMIDH, 21, 11)
379
+ FIELD(AFMR3, AMSRR, 20, 1)
380
+ FIELD(AFMR3, AMIDE, 19, 1)
381
+ FIELD(AFMR3, AMIDL, 1, 18)
382
+ FIELD(AFMR3, AMRTR, 0, 1)
383
+REG32(AFIR3, 0x78)
384
+ FIELD(AFIR3, AIIDH, 21, 11)
385
+ FIELD(AFIR3, AISRR, 20, 1)
386
+ FIELD(AFIR3, AIIDE, 19, 1)
387
+ FIELD(AFIR3, AIIDL, 1, 18)
388
+ FIELD(AFIR3, AIRTR, 0, 1)
389
+REG32(AFMR4, 0x7c)
390
+ FIELD(AFMR4, AMIDH, 21, 11)
391
+ FIELD(AFMR4, AMSRR, 20, 1)
392
+ FIELD(AFMR4, AMIDE, 19, 1)
393
+ FIELD(AFMR4, AMIDL, 1, 18)
394
+ FIELD(AFMR4, AMRTR, 0, 1)
395
+REG32(AFIR4, 0x80)
396
+ FIELD(AFIR4, AIIDH, 21, 11)
397
+ FIELD(AFIR4, AISRR, 20, 1)
398
+ FIELD(AFIR4, AIIDE, 19, 1)
399
+ FIELD(AFIR4, AIIDL, 1, 18)
400
+ FIELD(AFIR4, AIRTR, 0, 1)
401
+
402
+static void can_update_irq(XlnxZynqMPCANState *s)
403
+{
404
+ uint32_t irq;
405
+
406
+ /* Watermark register interrupts. */
407
+ if ((fifo32_num_free(&s->tx_fifo) / CAN_FRAME_SIZE) >
408
+ ARRAY_FIELD_EX32(s->regs, WIR, EW)) {
409
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFWMEMP, 1);
410
+ }
411
+
412
+ if ((fifo32_num_used(&s->rx_fifo) / CAN_FRAME_SIZE) >
413
+ ARRAY_FIELD_EX32(s->regs, WIR, FW)) {
414
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXFWMFLL, 1);
415
+ }
416
+
417
+ /* RX Interrupts. */
418
+ if (fifo32_num_used(&s->rx_fifo) >= CAN_FRAME_SIZE) {
419
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXNEMP, 1);
420
+ }
421
+
422
+ /* TX interrupts. */
423
+ if (fifo32_is_empty(&s->tx_fifo)) {
424
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFEMP, 1);
425
+ }
426
+
427
+ if (fifo32_is_full(&s->tx_fifo)) {
428
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXFLL, 1);
429
+ }
430
+
431
+ if (fifo32_is_full(&s->txhpb_fifo)) {
432
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXBFLL, 1);
433
+ }
434
+
435
+ irq = s->regs[R_INTERRUPT_STATUS_REGISTER];
436
+ irq &= s->regs[R_INTERRUPT_ENABLE_REGISTER];
437
+
438
+ trace_xlnx_can_update_irq(s->regs[R_INTERRUPT_STATUS_REGISTER],
439
+ s->regs[R_INTERRUPT_ENABLE_REGISTER], irq);
440
+ qemu_set_irq(s->irq, irq);
441
+}
442
+
443
+static void can_ier_post_write(RegisterInfo *reg, uint64_t val)
444
+{
445
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
446
+
447
+ can_update_irq(s);
448
+}
449
+
450
+static uint64_t can_icr_pre_write(RegisterInfo *reg, uint64_t val)
451
+{
452
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
453
+
454
+ s->regs[R_INTERRUPT_STATUS_REGISTER] &= ~val;
455
+ can_update_irq(s);
456
+
457
+ return 0;
458
+}
459
+
460
+static void can_config_reset(XlnxZynqMPCANState *s)
461
+{
462
+ /* Reset all the configuration registers. */
463
+ register_reset(&s->reg_info[R_SOFTWARE_RESET_REGISTER]);
464
+ register_reset(&s->reg_info[R_MODE_SELECT_REGISTER]);
465
+ register_reset(
466
+ &s->reg_info[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER]);
467
+ register_reset(&s->reg_info[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER]);
468
+ register_reset(&s->reg_info[R_STATUS_REGISTER]);
469
+ register_reset(&s->reg_info[R_INTERRUPT_STATUS_REGISTER]);
470
+ register_reset(&s->reg_info[R_INTERRUPT_ENABLE_REGISTER]);
471
+ register_reset(&s->reg_info[R_INTERRUPT_CLEAR_REGISTER]);
472
+ register_reset(&s->reg_info[R_WIR]);
473
+}
474
+
475
+static void can_config_mode(XlnxZynqMPCANState *s)
476
+{
477
+ register_reset(&s->reg_info[R_ERROR_COUNTER_REGISTER]);
478
+ register_reset(&s->reg_info[R_ERROR_STATUS_REGISTER]);
479
+
480
+ /* Put XlnxZynqMPCAN in configuration mode. */
481
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 1);
482
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP, 0);
483
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP, 0);
484
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, BSOFF, 0);
485
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ERROR, 0);
486
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 0);
487
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 0);
488
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 0);
489
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, ARBLST, 0);
490
+
491
+ can_update_irq(s);
492
+}
493
+
494
+static void update_status_register_mode_bits(XlnxZynqMPCANState *s)
495
+{
496
+ bool sleep_status = ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP);
497
+ bool sleep_mode = ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP);
498
+ /* Wake up interrupt bit. */
499
+ bool wakeup_irq_val = sleep_status && (sleep_mode == 0);
500
+ /* Sleep interrupt bit. */
501
+ bool sleep_irq_val = sleep_mode && (sleep_status == 0);
502
+
503
+ /* Clear previous core mode status bits. */
504
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 0);
505
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 0);
506
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 0);
507
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 0);
508
+
509
+ /* set current mode bit and generate irqs accordingly. */
510
+ if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, LBACK)) {
511
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, LBACK, 1);
512
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SLEEP)) {
513
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SLEEP, 1);
514
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, SLP,
515
+ sleep_irq_val);
516
+ } else if (ARRAY_FIELD_EX32(s->regs, MODE_SELECT_REGISTER, SNOOP)) {
517
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, SNOOP, 1);
518
+ } else {
519
+ /*
520
+ * If all bits are zero then XlnxZynqMPCAN is set in normal mode.
521
+ */
522
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, NORMAL, 1);
523
+ /* Set wakeup interrupt bit. */
524
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, WKUP,
525
+ wakeup_irq_val);
526
+ }
527
+
528
+ can_update_irq(s);
529
+}
530
+
531
+static void can_exit_sleep_mode(XlnxZynqMPCANState *s)
532
+{
533
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, 0);
534
+ update_status_register_mode_bits(s);
535
+}
536
+
537
+static void generate_frame(qemu_can_frame *frame, uint32_t *data)
538
+{
539
+ frame->can_id = data[0];
540
+ frame->can_dlc = FIELD_EX32(data[1], TXFIFO_DLC, DLC);
541
+
542
+ frame->data[0] = FIELD_EX32(data[2], TXFIFO_DATA1, DB3);
543
+ frame->data[1] = FIELD_EX32(data[2], TXFIFO_DATA1, DB2);
544
+ frame->data[2] = FIELD_EX32(data[2], TXFIFO_DATA1, DB1);
545
+ frame->data[3] = FIELD_EX32(data[2], TXFIFO_DATA1, DB0);
546
+
547
+ frame->data[4] = FIELD_EX32(data[3], TXFIFO_DATA2, DB7);
548
+ frame->data[5] = FIELD_EX32(data[3], TXFIFO_DATA2, DB6);
549
+ frame->data[6] = FIELD_EX32(data[3], TXFIFO_DATA2, DB5);
550
+ frame->data[7] = FIELD_EX32(data[3], TXFIFO_DATA2, DB4);
551
+}
552
+
553
+static bool tx_ready_check(XlnxZynqMPCANState *s)
554
+{
555
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
556
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
557
+
558
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer data while"
559
+ " data while controller is in reset mode.\n",
560
+ path);
561
+ return false;
562
+ }
563
+
564
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
565
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
566
+
567
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
568
+ " data while controller is in configuration mode. Reset"
569
+ " the core so operations can start fresh.\n",
570
+ path);
571
+ return false;
572
+ }
573
+
574
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
575
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
576
+
577
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to transfer"
578
+ " data while controller is in SNOOP MODE.\n",
579
+ path);
580
+ return false;
581
+ }
582
+
583
+ return true;
584
+}
585
+
586
+static void transfer_fifo(XlnxZynqMPCANState *s, Fifo32 *fifo)
587
+{
588
+ qemu_can_frame frame;
589
+ uint32_t data[CAN_FRAME_SIZE];
590
+ int i;
591
+ bool can_tx = tx_ready_check(s);
592
+
593
+ if (!can_tx) {
594
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
595
+
596
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is not enabled for data"
597
+ " transfer.\n", path);
598
+ can_update_irq(s);
599
+ return;
600
+ }
601
+
602
+ while (!fifo32_is_empty(fifo)) {
603
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
604
+ data[i] = fifo32_pop(fifo);
605
+ }
606
+
607
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, LBACK)) {
608
+ /*
609
+ * Controller is in loopback. In Loopback mode, the CAN core
610
+ * transmits a recessive bitstream on to the XlnxZynqMPCAN Bus.
611
+ * Any message transmitted is looped back to the RX line and
612
+ * acknowledged. The XlnxZynqMPCAN core receives any message
613
+ * that it transmits.
614
+ */
615
+ if (fifo32_is_full(&s->rx_fifo)) {
616
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
617
+ } else {
618
+ for (i = 0; i < CAN_FRAME_SIZE; i++) {
619
+ fifo32_push(&s->rx_fifo, data[i]);
620
+ }
621
+
622
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
45
+ }
623
+ }
624
+ } else {
625
+ /* Normal mode Tx. */
626
+ generate_frame(&frame, data);
627
+
628
+ trace_xlnx_can_tx_data(frame.can_id, frame.can_dlc,
629
+ frame.data[0], frame.data[1],
630
+ frame.data[2], frame.data[3],
631
+ frame.data[4], frame.data[5],
632
+ frame.data[6], frame.data[7]);
633
+ can_bus_client_send(&s->bus_client, &frame, 1);
46
+ }
634
+ }
47
+ }
635
+ }
48
#endif
636
+
49
/* If we don't have any way of figuring out the actual executable
637
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, TXOK, 1);
50
location then try argv[0]. */
638
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, TXBFLL, 0);
639
+
640
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) {
641
+ can_exit_sleep_mode(s);
642
+ }
643
+
644
+ can_update_irq(s);
645
+}
646
+
647
+static uint64_t can_srr_pre_write(RegisterInfo *reg, uint64_t val)
648
+{
649
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
650
+
651
+ ARRAY_FIELD_DP32(s->regs, SOFTWARE_RESET_REGISTER, CEN,
652
+ FIELD_EX32(val, SOFTWARE_RESET_REGISTER, CEN));
653
+
654
+ if (FIELD_EX32(val, SOFTWARE_RESET_REGISTER, SRST)) {
655
+ trace_xlnx_can_reset(val);
656
+
657
+ /* First, core will do software reset then will enter in config mode. */
658
+ can_config_reset(s);
659
+ }
660
+
661
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
662
+ can_config_mode(s);
663
+ } else {
664
+ /*
665
+ * Leave config mode. Now XlnxZynqMPCAN core will enter normal,
666
+ * sleep, snoop or loopback mode depending upon LBACK, SLEEP, SNOOP
667
+ * register states.
668
+ */
669
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, CONFIG, 0);
670
+
671
+ ptimer_transaction_begin(s->can_timer);
672
+ ptimer_set_count(s->can_timer, 0);
673
+ ptimer_transaction_commit(s->can_timer);
674
+
675
+ /* XlnxZynqMPCAN is out of config mode. It will send pending data. */
676
+ transfer_fifo(s, &s->txhpb_fifo);
677
+ transfer_fifo(s, &s->tx_fifo);
678
+ }
679
+
680
+ update_status_register_mode_bits(s);
681
+
682
+ return s->regs[R_SOFTWARE_RESET_REGISTER];
683
+}
684
+
685
+static uint64_t can_msr_pre_write(RegisterInfo *reg, uint64_t val)
686
+{
687
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
688
+ uint8_t multi_mode;
689
+
690
+ /*
691
+ * Multiple mode set check. This is done to make sure user doesn't set
692
+ * multiple modes.
693
+ */
694
+ multi_mode = FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK) +
695
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP) +
696
+ FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP);
697
+
698
+ if (multi_mode > 1) {
699
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
700
+
701
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to config"
702
+ " several modes simultaneously. One mode will be selected"
703
+ " according to their priority: LBACK > SLEEP > SNOOP.\n",
704
+ path);
705
+ }
706
+
707
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN) == 0) {
708
+ /* We are in configuration mode, any mode can be selected. */
709
+ s->regs[R_MODE_SELECT_REGISTER] = val;
710
+ } else {
711
+ bool sleep_mode_bit = FIELD_EX32(val, MODE_SELECT_REGISTER, SLEEP);
712
+
713
+ ARRAY_FIELD_DP32(s->regs, MODE_SELECT_REGISTER, SLEEP, sleep_mode_bit);
714
+
715
+ if (FIELD_EX32(val, MODE_SELECT_REGISTER, LBACK)) {
716
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
717
+
718
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
719
+ " LBACK mode without setting CEN bit as 0.\n",
720
+ path);
721
+ } else if (FIELD_EX32(val, MODE_SELECT_REGISTER, SNOOP)) {
722
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
723
+
724
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Attempting to set"
725
+ " SNOOP mode without setting CEN bit as 0.\n",
726
+ path);
727
+ }
728
+
729
+ update_status_register_mode_bits(s);
730
+ }
731
+
732
+ return s->regs[R_MODE_SELECT_REGISTER];
733
+}
734
+
735
+static uint64_t can_brpr_pre_write(RegisterInfo *reg, uint64_t val)
736
+{
737
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
738
+
739
+ /* Only allow writes when in config mode. */
740
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
741
+ return s->regs[R_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER];
742
+ }
743
+
744
+ return val;
745
+}
746
+
747
+static uint64_t can_btr_pre_write(RegisterInfo *reg, uint64_t val)
748
+{
749
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
750
+
751
+ /* Only allow writes when in config mode. */
752
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
753
+ return s->regs[R_ARBITRATION_PHASE_BIT_TIMING_REGISTER];
754
+ }
755
+
756
+ return val;
757
+}
758
+
759
+static uint64_t can_tcr_pre_write(RegisterInfo *reg, uint64_t val)
760
+{
761
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
762
+
763
+ if (FIELD_EX32(val, TIMESTAMP_REGISTER, CTS)) {
764
+ ptimer_transaction_begin(s->can_timer);
765
+ ptimer_set_count(s->can_timer, 0);
766
+ ptimer_transaction_commit(s->can_timer);
767
+ }
768
+
769
+ return 0;
770
+}
771
+
772
+static void update_rx_fifo(XlnxZynqMPCANState *s, const qemu_can_frame *frame)
773
+{
774
+ bool filter_pass = false;
775
+ uint16_t timestamp = 0;
776
+
777
+ /* If no filter is enabled. Message will be stored in FIFO. */
778
+ if (!((ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) |
779
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) |
780
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) |
781
+ (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)))) {
782
+ filter_pass = true;
783
+ }
784
+
785
+ /*
786
+ * Messages that pass any of the acceptance filters will be stored in
787
+ * the RX FIFO.
788
+ */
789
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1)) {
790
+ uint32_t id_masked = s->regs[R_AFMR1] & frame->can_id;
791
+ uint32_t filter_id_masked = s->regs[R_AFMR1] & s->regs[R_AFIR1];
792
+
793
+ if (filter_id_masked == id_masked) {
794
+ filter_pass = true;
795
+ }
796
+ }
797
+
798
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF2)) {
799
+ uint32_t id_masked = s->regs[R_AFMR2] & frame->can_id;
800
+ uint32_t filter_id_masked = s->regs[R_AFMR2] & s->regs[R_AFIR2];
801
+
802
+ if (filter_id_masked == id_masked) {
803
+ filter_pass = true;
804
+ }
805
+ }
806
+
807
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF3)) {
808
+ uint32_t id_masked = s->regs[R_AFMR3] & frame->can_id;
809
+ uint32_t filter_id_masked = s->regs[R_AFMR3] & s->regs[R_AFIR3];
810
+
811
+ if (filter_id_masked == id_masked) {
812
+ filter_pass = true;
813
+ }
814
+ }
815
+
816
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
817
+ uint32_t id_masked = s->regs[R_AFMR4] & frame->can_id;
818
+ uint32_t filter_id_masked = s->regs[R_AFMR4] & s->regs[R_AFIR4];
819
+
820
+ if (filter_id_masked == id_masked) {
821
+ filter_pass = true;
822
+ }
823
+ }
824
+
825
+ if (!filter_pass) {
826
+ trace_xlnx_can_rx_fifo_filter_reject(frame->can_id, frame->can_dlc);
827
+ return;
828
+ }
829
+
830
+ /* Store the message in fifo if it passed through any of the filters. */
831
+ if (filter_pass && frame->can_dlc <= MAX_DLC) {
832
+
833
+ if (fifo32_is_full(&s->rx_fifo)) {
834
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOFLW, 1);
835
+ } else {
836
+ timestamp = CAN_TIMER_MAX - ptimer_get_count(s->can_timer);
837
+
838
+ fifo32_push(&s->rx_fifo, frame->can_id);
839
+
840
+ fifo32_push(&s->rx_fifo, deposit32(0, R_RXFIFO_DLC_DLC_SHIFT,
841
+ R_RXFIFO_DLC_DLC_LENGTH,
842
+ frame->can_dlc) |
843
+ deposit32(0, R_RXFIFO_DLC_RXT_SHIFT,
844
+ R_RXFIFO_DLC_RXT_LENGTH,
845
+ timestamp));
846
+
847
+ /* First 32 bit of the data. */
848
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA1_DB3_SHIFT,
849
+ R_TXFIFO_DATA1_DB3_LENGTH,
850
+ frame->data[0]) |
851
+ deposit32(0, R_TXFIFO_DATA1_DB2_SHIFT,
852
+ R_TXFIFO_DATA1_DB2_LENGTH,
853
+ frame->data[1]) |
854
+ deposit32(0, R_TXFIFO_DATA1_DB1_SHIFT,
855
+ R_TXFIFO_DATA1_DB1_LENGTH,
856
+ frame->data[2]) |
857
+ deposit32(0, R_TXFIFO_DATA1_DB0_SHIFT,
858
+ R_TXFIFO_DATA1_DB0_LENGTH,
859
+ frame->data[3]));
860
+ /* Last 32 bit of the data. */
861
+ fifo32_push(&s->rx_fifo, deposit32(0, R_TXFIFO_DATA2_DB7_SHIFT,
862
+ R_TXFIFO_DATA2_DB7_LENGTH,
863
+ frame->data[4]) |
864
+ deposit32(0, R_TXFIFO_DATA2_DB6_SHIFT,
865
+ R_TXFIFO_DATA2_DB6_LENGTH,
866
+ frame->data[5]) |
867
+ deposit32(0, R_TXFIFO_DATA2_DB5_SHIFT,
868
+ R_TXFIFO_DATA2_DB5_LENGTH,
869
+ frame->data[6]) |
870
+ deposit32(0, R_TXFIFO_DATA2_DB4_SHIFT,
871
+ R_TXFIFO_DATA2_DB4_LENGTH,
872
+ frame->data[7]));
873
+
874
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXOK, 1);
875
+ trace_xlnx_can_rx_data(frame->can_id, frame->can_dlc,
876
+ frame->data[0], frame->data[1],
877
+ frame->data[2], frame->data[3],
878
+ frame->data[4], frame->data[5],
879
+ frame->data[6], frame->data[7]);
880
+ }
881
+
882
+ can_update_irq(s);
883
+ }
884
+}
885
+
886
+static uint64_t can_rxfifo_pre_read(RegisterInfo *reg, uint64_t val)
887
+{
888
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
889
+
890
+ if (!fifo32_is_empty(&s->rx_fifo)) {
891
+ val = fifo32_pop(&s->rx_fifo);
892
+ } else {
893
+ ARRAY_FIELD_DP32(s->regs, INTERRUPT_STATUS_REGISTER, RXUFLW, 1);
894
+ }
895
+
896
+ can_update_irq(s);
897
+ return val;
898
+}
899
+
900
+static void can_filter_enable_post_write(RegisterInfo *reg, uint64_t val)
901
+{
902
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
903
+
904
+ if (ARRAY_FIELD_EX32(s->regs, AFR, UAF1) &&
905
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF2) &&
906
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF3) &&
907
+ ARRAY_FIELD_EX32(s->regs, AFR, UAF4)) {
908
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 1);
909
+ } else {
910
+ ARRAY_FIELD_DP32(s->regs, STATUS_REGISTER, ACFBSY, 0);
911
+ }
912
+}
913
+
914
+static uint64_t can_filter_mask_pre_write(RegisterInfo *reg, uint64_t val)
915
+{
916
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
917
+ uint32_t reg_idx = (reg->access->addr) / 4;
918
+ uint32_t filter_number = (reg_idx - R_AFMR1) / 2;
919
+
920
+ /* modify an acceptance filter, the corresponding UAF bit should be '0'. */
921
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
922
+ s->regs[reg_idx] = val;
923
+
924
+ trace_xlnx_can_filter_mask_pre_write(filter_number, s->regs[reg_idx]);
925
+ } else {
926
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
927
+
928
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
929
+ " mask is not set as corresponding UAF bit is not 0.\n",
930
+ path, filter_number + 1);
931
+ }
932
+
933
+ return s->regs[reg_idx];
934
+}
935
+
936
+static uint64_t can_filter_id_pre_write(RegisterInfo *reg, uint64_t val)
937
+{
938
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
939
+ uint32_t reg_idx = (reg->access->addr) / 4;
940
+ uint32_t filter_number = (reg_idx - R_AFIR1) / 2;
941
+
942
+ if (!(s->regs[R_AFR] & (1 << filter_number))) {
943
+ s->regs[reg_idx] = val;
944
+
945
+ trace_xlnx_can_filter_id_pre_write(filter_number, s->regs[reg_idx]);
946
+ } else {
947
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
948
+
949
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Acceptance filter %d"
950
+ " id is not set as corresponding UAF bit is not 0.\n",
951
+ path, filter_number + 1);
952
+ }
953
+
954
+ return s->regs[reg_idx];
955
+}
956
+
957
+static void can_tx_post_write(RegisterInfo *reg, uint64_t val)
958
+{
959
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(reg->opaque);
960
+
961
+ bool is_txhpb = reg->access->addr > A_TXFIFO_DATA2;
962
+
963
+ bool initiate_transfer = (reg->access->addr == A_TXFIFO_DATA2) ||
964
+ (reg->access->addr == A_TXHPB_DATA2);
965
+
966
+ Fifo32 *f = is_txhpb ? &s->txhpb_fifo : &s->tx_fifo;
967
+
968
+ if (!fifo32_is_full(f)) {
969
+ fifo32_push(f, val);
970
+ } else {
971
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
972
+
973
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: TX FIFO is full.\n", path);
974
+ }
975
+
976
+ /* Initiate the message send if TX register is written. */
977
+ if (initiate_transfer &&
978
+ ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) {
979
+ transfer_fifo(s, f);
980
+ }
981
+
982
+ can_update_irq(s);
983
+}
984
+
985
+static const RegisterAccessInfo can_regs_info[] = {
986
+ { .name = "SOFTWARE_RESET_REGISTER",
987
+ .addr = A_SOFTWARE_RESET_REGISTER,
988
+ .rsvd = 0xfffffffc,
989
+ .pre_write = can_srr_pre_write,
990
+ },{ .name = "MODE_SELECT_REGISTER",
991
+ .addr = A_MODE_SELECT_REGISTER,
992
+ .rsvd = 0xfffffff8,
993
+ .pre_write = can_msr_pre_write,
994
+ },{ .name = "ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER",
995
+ .addr = A_ARBITRATION_PHASE_BAUD_RATE_PRESCALER_REGISTER,
996
+ .rsvd = 0xffffff00,
997
+ .pre_write = can_brpr_pre_write,
998
+ },{ .name = "ARBITRATION_PHASE_BIT_TIMING_REGISTER",
999
+ .addr = A_ARBITRATION_PHASE_BIT_TIMING_REGISTER,
1000
+ .rsvd = 0xfffffe00,
1001
+ .pre_write = can_btr_pre_write,
1002
+ },{ .name = "ERROR_COUNTER_REGISTER",
1003
+ .addr = A_ERROR_COUNTER_REGISTER,
1004
+ .rsvd = 0xffff0000,
1005
+ .ro = 0xffffffff,
1006
+ },{ .name = "ERROR_STATUS_REGISTER",
1007
+ .addr = A_ERROR_STATUS_REGISTER,
1008
+ .rsvd = 0xffffffe0,
1009
+ .w1c = 0x1f,
1010
+ },{ .name = "STATUS_REGISTER", .addr = A_STATUS_REGISTER,
1011
+ .reset = 0x1,
1012
+ .rsvd = 0xffffe000,
1013
+ .ro = 0x1fff,
1014
+ },{ .name = "INTERRUPT_STATUS_REGISTER",
1015
+ .addr = A_INTERRUPT_STATUS_REGISTER,
1016
+ .reset = 0x6000,
1017
+ .rsvd = 0xffff8000,
1018
+ .ro = 0x7fff,
1019
+ },{ .name = "INTERRUPT_ENABLE_REGISTER",
1020
+ .addr = A_INTERRUPT_ENABLE_REGISTER,
1021
+ .rsvd = 0xffff8000,
1022
+ .post_write = can_ier_post_write,
1023
+ },{ .name = "INTERRUPT_CLEAR_REGISTER",
1024
+ .addr = A_INTERRUPT_CLEAR_REGISTER,
1025
+ .rsvd = 0xffff8000,
1026
+ .pre_write = can_icr_pre_write,
1027
+ },{ .name = "TIMESTAMP_REGISTER",
1028
+ .addr = A_TIMESTAMP_REGISTER,
1029
+ .rsvd = 0xfffffffe,
1030
+ .pre_write = can_tcr_pre_write,
1031
+ },{ .name = "WIR", .addr = A_WIR,
1032
+ .reset = 0x3f3f,
1033
+ .rsvd = 0xffff0000,
1034
+ },{ .name = "TXFIFO_ID", .addr = A_TXFIFO_ID,
1035
+ .post_write = can_tx_post_write,
1036
+ },{ .name = "TXFIFO_DLC", .addr = A_TXFIFO_DLC,
1037
+ .rsvd = 0xfffffff,
1038
+ .post_write = can_tx_post_write,
1039
+ },{ .name = "TXFIFO_DATA1", .addr = A_TXFIFO_DATA1,
1040
+ .post_write = can_tx_post_write,
1041
+ },{ .name = "TXFIFO_DATA2", .addr = A_TXFIFO_DATA2,
1042
+ .post_write = can_tx_post_write,
1043
+ },{ .name = "TXHPB_ID", .addr = A_TXHPB_ID,
1044
+ .post_write = can_tx_post_write,
1045
+ },{ .name = "TXHPB_DLC", .addr = A_TXHPB_DLC,
1046
+ .rsvd = 0xfffffff,
1047
+ .post_write = can_tx_post_write,
1048
+ },{ .name = "TXHPB_DATA1", .addr = A_TXHPB_DATA1,
1049
+ .post_write = can_tx_post_write,
1050
+ },{ .name = "TXHPB_DATA2", .addr = A_TXHPB_DATA2,
1051
+ .post_write = can_tx_post_write,
1052
+ },{ .name = "RXFIFO_ID", .addr = A_RXFIFO_ID,
1053
+ .ro = 0xffffffff,
1054
+ .post_read = can_rxfifo_pre_read,
1055
+ },{ .name = "RXFIFO_DLC", .addr = A_RXFIFO_DLC,
1056
+ .rsvd = 0xfff0000,
1057
+ .post_read = can_rxfifo_pre_read,
1058
+ },{ .name = "RXFIFO_DATA1", .addr = A_RXFIFO_DATA1,
1059
+ .post_read = can_rxfifo_pre_read,
1060
+ },{ .name = "RXFIFO_DATA2", .addr = A_RXFIFO_DATA2,
1061
+ .post_read = can_rxfifo_pre_read,
1062
+ },{ .name = "AFR", .addr = A_AFR,
1063
+ .rsvd = 0xfffffff0,
1064
+ .post_write = can_filter_enable_post_write,
1065
+ },{ .name = "AFMR1", .addr = A_AFMR1,
1066
+ .pre_write = can_filter_mask_pre_write,
1067
+ },{ .name = "AFIR1", .addr = A_AFIR1,
1068
+ .pre_write = can_filter_id_pre_write,
1069
+ },{ .name = "AFMR2", .addr = A_AFMR2,
1070
+ .pre_write = can_filter_mask_pre_write,
1071
+ },{ .name = "AFIR2", .addr = A_AFIR2,
1072
+ .pre_write = can_filter_id_pre_write,
1073
+ },{ .name = "AFMR3", .addr = A_AFMR3,
1074
+ .pre_write = can_filter_mask_pre_write,
1075
+ },{ .name = "AFIR3", .addr = A_AFIR3,
1076
+ .pre_write = can_filter_id_pre_write,
1077
+ },{ .name = "AFMR4", .addr = A_AFMR4,
1078
+ .pre_write = can_filter_mask_pre_write,
1079
+ },{ .name = "AFIR4", .addr = A_AFIR4,
1080
+ .pre_write = can_filter_id_pre_write,
1081
+ }
1082
+};
1083
+
1084
+static void xlnx_zynqmp_can_ptimer_cb(void *opaque)
1085
+{
1086
+ /* No action required on the timer rollover. */
1087
+}
1088
+
1089
+static const MemoryRegionOps can_ops = {
1090
+ .read = register_read_memory,
1091
+ .write = register_write_memory,
1092
+ .endianness = DEVICE_LITTLE_ENDIAN,
1093
+ .valid = {
1094
+ .min_access_size = 4,
1095
+ .max_access_size = 4,
1096
+ },
1097
+};
1098
+
1099
+static void xlnx_zynqmp_can_reset_init(Object *obj, ResetType type)
1100
+{
1101
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1102
+ unsigned int i;
1103
+
1104
+ for (i = R_RXFIFO_ID; i < ARRAY_SIZE(s->reg_info); ++i) {
1105
+ register_reset(&s->reg_info[i]);
1106
+ }
1107
+
1108
+ ptimer_transaction_begin(s->can_timer);
1109
+ ptimer_set_count(s->can_timer, 0);
1110
+ ptimer_transaction_commit(s->can_timer);
1111
+}
1112
+
1113
+static void xlnx_zynqmp_can_reset_hold(Object *obj)
1114
+{
1115
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1116
+ unsigned int i;
1117
+
1118
+ for (i = 0; i < R_RXFIFO_ID; ++i) {
1119
+ register_reset(&s->reg_info[i]);
1120
+ }
1121
+
1122
+ /*
1123
+ * Reset FIFOs when CAN model is reset. This will clear the fifo writes
1124
+ * done by post_write which gets called from register_reset function,
1125
+ * post_write handle will not be able to trigger tx because CAN will be
1126
+ * disabled when software_reset_register is cleared first.
1127
+ */
1128
+ fifo32_reset(&s->rx_fifo);
1129
+ fifo32_reset(&s->tx_fifo);
1130
+ fifo32_reset(&s->txhpb_fifo);
1131
+}
1132
+
1133
+static bool xlnx_zynqmp_can_can_receive(CanBusClientState *client)
1134
+{
1135
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
1136
+ bus_client);
1137
+
1138
+ if (ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, SRST)) {
1139
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1140
+
1141
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is in reset state.\n",
1142
+ path);
1143
+ return false;
1144
+ }
1145
+
1146
+ if ((ARRAY_FIELD_EX32(s->regs, SOFTWARE_RESET_REGISTER, CEN)) == 0) {
1147
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1148
+
1149
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Controller is disabled. Incoming"
1150
+ " messages will be discarded.\n", path);
1151
+ return false;
1152
+ }
1153
+
1154
+ return true;
1155
+}
1156
+
1157
+static ssize_t xlnx_zynqmp_can_receive(CanBusClientState *client,
1158
+ const qemu_can_frame *buf, size_t buf_size) {
1159
+ XlnxZynqMPCANState *s = container_of(client, XlnxZynqMPCANState,
1160
+ bus_client);
1161
+ const qemu_can_frame *frame = buf;
1162
+
1163
+ if (buf_size <= 0) {
1164
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1165
+
1166
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Error in the data received.\n",
1167
+ path);
1168
+ return 0;
1169
+ }
1170
+
1171
+ if (ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SNOOP)) {
1172
+ /* Snoop Mode: Just keep the data. no response back. */
1173
+ update_rx_fifo(s, frame);
1174
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP))) {
1175
+ /*
1176
+ * XlnxZynqMPCAN is in sleep mode. Any data on bus will bring it to wake
1177
+ * up state.
1178
+ */
1179
+ can_exit_sleep_mode(s);
1180
+ update_rx_fifo(s, frame);
1181
+ } else if ((ARRAY_FIELD_EX32(s->regs, STATUS_REGISTER, SLEEP)) == 0) {
1182
+ update_rx_fifo(s, frame);
1183
+ } else {
1184
+ /*
1185
+ * XlnxZynqMPCAN will not participate in normal bus communication
1186
+ * and will not receive any messages transmitted by other CAN nodes.
1187
+ */
1188
+ trace_xlnx_can_rx_discard(s->regs[R_STATUS_REGISTER]);
1189
+ }
1190
+
1191
+ return 1;
1192
+}
1193
+
1194
+static CanBusClientInfo can_xilinx_bus_client_info = {
1195
+ .can_receive = xlnx_zynqmp_can_can_receive,
1196
+ .receive = xlnx_zynqmp_can_receive,
1197
+};
1198
+
1199
+static int xlnx_zynqmp_can_connect_to_bus(XlnxZynqMPCANState *s,
1200
+ CanBusState *bus)
1201
+{
1202
+ s->bus_client.info = &can_xilinx_bus_client_info;
1203
+
1204
+ if (can_bus_insert_client(bus, &s->bus_client) < 0) {
1205
+ return -1;
1206
+ }
1207
+ return 0;
1208
+}
1209
+
1210
+static void xlnx_zynqmp_can_realize(DeviceState *dev, Error **errp)
1211
+{
1212
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(dev);
1213
+
1214
+ if (s->canbus) {
1215
+ if (xlnx_zynqmp_can_connect_to_bus(s, s->canbus) < 0) {
1216
+ g_autofree char *path = object_get_canonical_path(OBJECT(s));
1217
+
1218
+ error_setg(errp, "%s: xlnx_zynqmp_can_connect_to_bus"
1219
+ " failed.", path);
1220
+ return;
1221
+ }
1222
+ }
1223
+
1224
+ /* Create RX FIFO, TXFIFO, TXHPB storage. */
1225
+ fifo32_create(&s->rx_fifo, RXFIFO_SIZE);
1226
+ fifo32_create(&s->tx_fifo, RXFIFO_SIZE);
1227
+ fifo32_create(&s->txhpb_fifo, CAN_FRAME_SIZE);
1228
+
1229
+ /* Allocate a new timer. */
1230
+ s->can_timer = ptimer_init(xlnx_zynqmp_can_ptimer_cb, s,
1231
+ PTIMER_POLICY_DEFAULT);
1232
+
1233
+ ptimer_transaction_begin(s->can_timer);
1234
+
1235
+ ptimer_set_freq(s->can_timer, s->cfg.ext_clk_freq);
1236
+ ptimer_set_limit(s->can_timer, CAN_TIMER_MAX, 1);
1237
+ ptimer_run(s->can_timer, 0);
1238
+ ptimer_transaction_commit(s->can_timer);
1239
+}
1240
+
1241
+static void xlnx_zynqmp_can_init(Object *obj)
1242
+{
1243
+ XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
1244
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1245
+
1246
+ RegisterInfoArray *reg_array;
1247
+
1248
+ memory_region_init(&s->iomem, obj, TYPE_XLNX_ZYNQMP_CAN,
1249
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
1250
+ reg_array = register_init_block32(DEVICE(obj), can_regs_info,
1251
+ ARRAY_SIZE(can_regs_info),
1252
+ s->reg_info, s->regs,
1253
+ &can_ops,
1254
+ XLNX_ZYNQMP_CAN_ERR_DEBUG,
1255
+ XLNX_ZYNQMP_CAN_R_MAX * 4);
1256
+
1257
+ memory_region_add_subregion(&s->iomem, 0x00, &reg_array->mem);
1258
+ sysbus_init_mmio(sbd, &s->iomem);
1259
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
1260
+}
1261
+
1262
+static const VMStateDescription vmstate_can = {
1263
+ .name = TYPE_XLNX_ZYNQMP_CAN,
1264
+ .version_id = 1,
1265
+ .minimum_version_id = 1,
1266
+ .fields = (VMStateField[]) {
1267
+ VMSTATE_FIFO32(rx_fifo, XlnxZynqMPCANState),
1268
+ VMSTATE_FIFO32(tx_fifo, XlnxZynqMPCANState),
1269
+ VMSTATE_FIFO32(txhpb_fifo, XlnxZynqMPCANState),
1270
+ VMSTATE_UINT32_ARRAY(regs, XlnxZynqMPCANState, XLNX_ZYNQMP_CAN_R_MAX),
1271
+ VMSTATE_PTIMER(can_timer, XlnxZynqMPCANState),
1272
+ VMSTATE_END_OF_LIST(),
1273
+ }
1274
+};
1275
+
1276
+static Property xlnx_zynqmp_can_properties[] = {
1277
+ DEFINE_PROP_UINT32("ext_clk_freq", XlnxZynqMPCANState, cfg.ext_clk_freq,
1278
+ CAN_DEFAULT_CLOCK),
1279
+ DEFINE_PROP_LINK("canbus", XlnxZynqMPCANState, canbus, TYPE_CAN_BUS,
1280
+ CanBusState *),
1281
+ DEFINE_PROP_END_OF_LIST(),
1282
+};
1283
+
1284
+static void xlnx_zynqmp_can_class_init(ObjectClass *klass, void *data)
1285
+{
1286
+ DeviceClass *dc = DEVICE_CLASS(klass);
1287
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
1288
+
1289
+ rc->phases.enter = xlnx_zynqmp_can_reset_init;
1290
+ rc->phases.hold = xlnx_zynqmp_can_reset_hold;
1291
+ dc->realize = xlnx_zynqmp_can_realize;
1292
+ device_class_set_props(dc, xlnx_zynqmp_can_properties);
1293
+ dc->vmsd = &vmstate_can;
1294
+}
1295
+
1296
+static const TypeInfo can_info = {
1297
+ .name = TYPE_XLNX_ZYNQMP_CAN,
1298
+ .parent = TYPE_SYS_BUS_DEVICE,
1299
+ .instance_size = sizeof(XlnxZynqMPCANState),
1300
+ .class_init = xlnx_zynqmp_can_class_init,
1301
+ .instance_init = xlnx_zynqmp_can_init,
1302
+};
1303
+
1304
+static void can_register_types(void)
1305
+{
1306
+ type_register_static(&can_info);
1307
+}
1308
+
1309
+type_init(can_register_types)
1310
diff --git a/hw/Kconfig b/hw/Kconfig
1311
index XXXXXXX..XXXXXXX 100644
1312
--- a/hw/Kconfig
1313
+++ b/hw/Kconfig
1314
@@ -XXX,XX +XXX,XX @@ config XILINX_AXI
1315
config XLNX_ZYNQMP
1316
bool
1317
select REGISTER
1318
+ select CAN_BUS
1319
diff --git a/hw/net/can/meson.build b/hw/net/can/meson.build
1320
index XXXXXXX..XXXXXXX 100644
1321
--- a/hw/net/can/meson.build
1322
+++ b/hw/net/can/meson.build
1323
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_pcm3680_pci.c'))
1324
softmmu_ss.add(when: 'CONFIG_CAN_PCI', if_true: files('can_mioe3680_pci.c'))
1325
softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD', if_true: files('ctucan_core.c'))
1326
softmmu_ss.add(when: 'CONFIG_CAN_CTUCANFD_PCI', if_true: files('ctucan_pci.c'))
1327
+softmmu_ss.add(when: 'CONFIG_XLNX_ZYNQMP', if_true: files('xlnx-zynqmp-can.c'))
1328
diff --git a/hw/net/can/trace-events b/hw/net/can/trace-events
1329
new file mode 100644
1330
index XXXXXXX..XXXXXXX
1331
--- /dev/null
1332
+++ b/hw/net/can/trace-events
1333
@@ -XXX,XX +XXX,XX @@
1334
+# xlnx-zynqmp-can.c
1335
+xlnx_can_update_irq(uint32_t isr, uint32_t ier, uint32_t irq) "ISR: 0x%08x IER: 0x%08x IRQ: 0x%08x"
1336
+xlnx_can_reset(uint32_t val) "Resetting controller with value = 0x%08x"
1337
+xlnx_can_rx_fifo_filter_reject(uint32_t id, uint8_t dlc) "Frame: ID: 0x%08x DLC: 0x%02x"
1338
+xlnx_can_filter_id_pre_write(uint8_t filter_num, uint32_t value) "Filter%d ID: 0x%08x"
1339
+xlnx_can_filter_mask_pre_write(uint8_t filter_num, uint32_t value) "Filter%d MASK: 0x%08x"
1340
+xlnx_can_tx_data(uint32_t id, uint8_t dlc, uint8_t db0, uint8_t db1, uint8_t db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x"
1341
+xlnx_can_rx_data(uint32_t id, uint32_t dlc, uint8_t db0, uint8_t db1, uint8_t db2, uint8_t db3, uint8_t db4, uint8_t db5, uint8_t db6, uint8_t db7) "Frame: ID: 0x%08x DLC: 0x%02x DATA: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x"
1342
+xlnx_can_rx_discard(uint32_t status) "Controller is not enabled for bus communication. Status Register: 0x%08x"
51
--
1343
--
52
2.20.1
1344
2.20.1
53
1345
54
1346
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
2
3
By using the TYPE_* definitions for devices, we can:
3
Connect CAN0 and CAN1 on the ZynqMP.
4
- quickly find where devices are used with 'git-grep'
5
- easily rename a device (one-line change).
6
4
7
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
8
Message-id: 20200617072539.32686-6-f4bug@amsat.org
6
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
8
Message-id: 1605728926-352690-3-git-send-email-fnu.vikram@xilinx.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
10
---
12
hw/arm/realview.c | 3 ++-
11
include/hw/arm/xlnx-zynqmp.h | 8 ++++++++
13
hw/arm/versatilepb.c | 3 ++-
12
hw/arm/xlnx-zcu102.c | 20 ++++++++++++++++++++
14
hw/arm/vexpress.c | 3 ++-
13
hw/arm/xlnx-zynqmp.c | 34 ++++++++++++++++++++++++++++++++++
15
3 files changed, 6 insertions(+), 3 deletions(-)
14
3 files changed, 62 insertions(+)
16
15
17
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/realview.c
18
--- a/include/hw/arm/xlnx-zynqmp.h
20
+++ b/hw/arm/realview.c
19
+++ b/include/hw/arm/xlnx-zynqmp.h
21
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@
22
#include "hw/cpu/a9mpcore.h"
21
#include "hw/intc/arm_gic.h"
23
#include "hw/intc/realview_gic.h"
22
#include "hw/net/cadence_gem.h"
24
#include "hw/irq.h"
23
#include "hw/char/cadence_uart.h"
25
+#include "hw/i2c/arm_sbcon_i2c.h"
24
+#include "hw/net/xlnx-zynqmp-can.h"
26
25
#include "hw/ide/ahci.h"
27
#define SMP_BOOT_ADDR 0xe0000000
26
#include "hw/sd/sdhci.h"
28
#define SMP_BOOTREG_ADDR 0x10000030
27
#include "hw/ssi/xilinx_spips.h"
29
@@ -XXX,XX +XXX,XX @@ static void realview_init(MachineState *machine,
28
@@ -XXX,XX +XXX,XX @@
30
}
29
#include "hw/cpu/cluster.h"
30
#include "target/arm/cpu.h"
31
#include "qom/object.h"
32
+#include "net/can_emu.h"
33
34
#define TYPE_XLNX_ZYNQMP "xlnx,zynqmp"
35
OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
36
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
37
#define XLNX_ZYNQMP_NUM_RPU_CPUS 2
38
#define XLNX_ZYNQMP_NUM_GEMS 4
39
#define XLNX_ZYNQMP_NUM_UARTS 2
40
+#define XLNX_ZYNQMP_NUM_CAN 2
41
+#define XLNX_ZYNQMP_CAN_REF_CLK (24 * 1000 * 1000)
42
#define XLNX_ZYNQMP_NUM_SDHCI 2
43
#define XLNX_ZYNQMP_NUM_SPIS 2
44
#define XLNX_ZYNQMP_NUM_GDMA_CH 8
45
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
46
47
CadenceGEMState gem[XLNX_ZYNQMP_NUM_GEMS];
48
CadenceUARTState uart[XLNX_ZYNQMP_NUM_UARTS];
49
+ XlnxZynqMPCANState can[XLNX_ZYNQMP_NUM_CAN];
50
SysbusAHCIState sata;
51
SDHCIState sdhci[XLNX_ZYNQMP_NUM_SDHCI];
52
XilinxSPIPS spi[XLNX_ZYNQMP_NUM_SPIS];
53
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
54
bool virt;
55
/* Has the RPU subsystem? */
56
bool has_rpu;
57
+
58
+ /* CAN bus. */
59
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
60
};
61
62
#endif
63
diff --git a/hw/arm/xlnx-zcu102.c b/hw/arm/xlnx-zcu102.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/arm/xlnx-zcu102.c
66
+++ b/hw/arm/xlnx-zcu102.c
67
@@ -XXX,XX +XXX,XX @@
68
#include "sysemu/qtest.h"
69
#include "sysemu/device_tree.h"
70
#include "qom/object.h"
71
+#include "net/can_emu.h"
72
73
struct XlnxZCU102 {
74
MachineState parent_obj;
75
@@ -XXX,XX +XXX,XX @@ struct XlnxZCU102 {
76
bool secure;
77
bool virt;
78
79
+ CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
80
+
81
struct arm_boot_info binfo;
82
};
83
84
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_init(MachineState *machine)
85
object_property_set_bool(OBJECT(&s->soc), "virtualization", s->virt,
86
&error_fatal);
87
88
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
89
+ gchar *bus_name = g_strdup_printf("canbus%d", i);
90
+
91
+ object_property_set_link(OBJECT(&s->soc), bus_name,
92
+ OBJECT(s->canbus[i]), &error_fatal);
93
+ g_free(bus_name);
94
+ }
95
+
96
qdev_realize(DEVICE(&s->soc), NULL, &error_fatal);
97
98
/* Create and plug in the SD cards */
99
@@ -XXX,XX +XXX,XX @@ static void xlnx_zcu102_machine_instance_init(Object *obj)
100
s->secure = false;
101
/* Default to virt (EL2) being disabled */
102
s->virt = false;
103
+ object_property_add_link(obj, "xlnx-zcu102.canbus0", TYPE_CAN_BUS,
104
+ (Object **)&s->canbus[0],
105
+ object_property_allow_set_link,
106
+ 0);
107
+
108
+ object_property_add_link(obj, "xlnx-zcu102.canbus1", TYPE_CAN_BUS,
109
+ (Object **)&s->canbus[1],
110
+ object_property_allow_set_link,
111
+ 0);
112
}
113
114
static void xlnx_zcu102_machine_class_init(ObjectClass *oc, void *data)
115
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
116
index XXXXXXX..XXXXXXX 100644
117
--- a/hw/arm/xlnx-zynqmp.c
118
+++ b/hw/arm/xlnx-zynqmp.c
119
@@ -XXX,XX +XXX,XX @@ static const int uart_intr[XLNX_ZYNQMP_NUM_UARTS] = {
120
21, 22,
121
};
122
123
+static const uint64_t can_addr[XLNX_ZYNQMP_NUM_CAN] = {
124
+ 0xFF060000, 0xFF070000,
125
+};
126
+
127
+static const int can_intr[XLNX_ZYNQMP_NUM_CAN] = {
128
+ 23, 24,
129
+};
130
+
131
static const uint64_t sdhci_addr[XLNX_ZYNQMP_NUM_SDHCI] = {
132
0xFF160000, 0xFF170000,
133
};
134
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_init(Object *obj)
135
TYPE_CADENCE_UART);
31
}
136
}
32
137
33
- dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL);
138
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
34
+ dev = sysbus_create_simple(TYPE_VERSATILE_I2C, 0x10002000, NULL);
139
+ object_initialize_child(obj, "can[*]", &s->can[i],
35
i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c");
140
+ TYPE_XLNX_ZYNQMP_CAN);
36
i2c_create_slave(i2c, "ds1338", 0x68);
141
+ }
37
142
+
38
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
143
object_initialize_child(obj, "sata", &s->sata, TYPE_SYSBUS_AHCI);
39
index XXXXXXX..XXXXXXX 100644
144
40
--- a/hw/arm/versatilepb.c
145
for (i = 0; i < XLNX_ZYNQMP_NUM_SDHCI; i++) {
41
+++ b/hw/arm/versatilepb.c
146
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
42
@@ -XXX,XX +XXX,XX @@
147
gic_spi[uart_intr[i]]);
43
#include "sysemu/sysemu.h"
148
}
44
#include "hw/pci/pci.h"
149
45
#include "hw/i2c/i2c.h"
150
+ for (i = 0; i < XLNX_ZYNQMP_NUM_CAN; i++) {
46
+#include "hw/i2c/arm_sbcon_i2c.h"
151
+ object_property_set_int(OBJECT(&s->can[i]), "ext_clk_freq",
47
#include "hw/irq.h"
152
+ XLNX_ZYNQMP_CAN_REF_CLK, &error_abort);
48
#include "hw/boards.h"
153
+
49
#include "exec/address-spaces.h"
154
+ object_property_set_link(OBJECT(&s->can[i]), "canbus",
50
@@ -XXX,XX +XXX,XX @@ static void versatile_init(MachineState *machine, int board_id)
155
+ OBJECT(s->canbus[i]), &error_fatal);
51
/* Add PL031 Real Time Clock. */
156
+
52
sysbus_create_simple("pl031", 0x101e8000, pic[10]);
157
+ sysbus_realize(SYS_BUS_DEVICE(&s->can[i]), &err);
53
158
+ if (err) {
54
- dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL);
159
+ error_propagate(errp, err);
55
+ dev = sysbus_create_simple(TYPE_VERSATILE_I2C, 0x10002000, NULL);
160
+ return;
56
i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c");
161
+ }
57
i2c_create_slave(i2c, "ds1338", 0x68);
162
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->can[i]), 0, can_addr[i]);
58
163
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->can[i]), 0,
59
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
164
+ gic_spi[can_intr[i]]);
60
index XXXXXXX..XXXXXXX 100644
165
+ }
61
--- a/hw/arm/vexpress.c
166
+
62
+++ b/hw/arm/vexpress.c
167
object_property_set_int(OBJECT(&s->sata), "num-ports", SATA_NUM_PORTS,
63
@@ -XXX,XX +XXX,XX @@
168
&error_abort);
64
#include "hw/char/pl011.h"
169
if (!sysbus_realize(SYS_BUS_DEVICE(&s->sata), errp)) {
65
#include "hw/cpu/a9mpcore.h"
170
@@ -XXX,XX +XXX,XX @@ static Property xlnx_zynqmp_props[] = {
66
#include "hw/cpu/a15mpcore.h"
171
DEFINE_PROP_BOOL("has_rpu", XlnxZynqMPState, has_rpu, false),
67
+#include "hw/i2c/arm_sbcon_i2c.h"
172
DEFINE_PROP_LINK("ddr-ram", XlnxZynqMPState, ddr_ram, TYPE_MEMORY_REGION,
68
173
MemoryRegion *),
69
#define VEXPRESS_BOARD_ID 0x8e0
174
+ DEFINE_PROP_LINK("canbus0", XlnxZynqMPState, canbus[0], TYPE_CAN_BUS,
70
#define VEXPRESS_FLASH_SIZE (64 * 1024 * 1024)
175
+ CanBusState *),
71
@@ -XXX,XX +XXX,XX @@ static void vexpress_common_init(MachineState *machine)
176
+ DEFINE_PROP_LINK("canbus1", XlnxZynqMPState, canbus[1], TYPE_CAN_BUS,
72
sysbus_create_simple("sp804", map[VE_TIMER01], pic[2]);
177
+ CanBusState *),
73
sysbus_create_simple("sp804", map[VE_TIMER23], pic[3]);
178
DEFINE_PROP_END_OF_LIST()
74
179
};
75
- dev = sysbus_create_simple("versatile_i2c", map[VE_SERIALDVI], NULL);
76
+ dev = sysbus_create_simple(TYPE_VERSATILE_I2C, map[VE_SERIALDVI], NULL);
77
i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c");
78
i2c_create_slave(i2c, "sii9022", 0x39);
79
180
80
--
181
--
81
2.20.1
182
2.20.1
82
183
83
184
diff view generated by jsdifflib
1
From: Andrew Jones <drjones@redhat.com>
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
2
3
Some cpu features may be enabled and disabled for all configurations
3
The QTests perform five tests on the Xilinx ZynqMP CAN controller:
4
that support the feature. Let's test that.
4
Tests the CAN controller in loopback, sleep and snoop mode.
5
5
Tests filtering of incoming CAN messages.
6
A recent regression[*] inspired adding these tests.
6
7
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
[*] '-cpu host,pmu=on' caused a segfault
8
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
9
9
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
10
Signed-off-by: Andrew Jones <drjones@redhat.com>
10
Message-id: 1605728926-352690-4-git-send-email-fnu.vikram@xilinx.com
11
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
12
Message-id: 20200623090622.30365-2-philmd@redhat.com
13
Message-Id: <20200623082310.17577-1-drjones@redhat.com>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
12
---
17
tests/qtest/arm-cpu-features.c | 38 ++++++++++++++++++++++++++++++----
13
tests/qtest/xlnx-can-test.c | 360 ++++++++++++++++++++++++++++++++++++
18
1 file changed, 34 insertions(+), 4 deletions(-)
14
tests/qtest/meson.build | 1 +
19
15
2 files changed, 361 insertions(+)
20
diff --git a/tests/qtest/arm-cpu-features.c b/tests/qtest/arm-cpu-features.c
16
create mode 100644 tests/qtest/xlnx-can-test.c
17
18
diff --git a/tests/qtest/xlnx-can-test.c b/tests/qtest/xlnx-can-test.c
19
new file mode 100644
20
index XXXXXXX..XXXXXXX
21
--- /dev/null
22
+++ b/tests/qtest/xlnx-can-test.c
23
@@ -XXX,XX +XXX,XX @@
24
+/*
25
+ * QTests for the Xilinx ZynqMP CAN controller.
26
+ *
27
+ * Copyright (c) 2020 Xilinx Inc.
28
+ *
29
+ * Written-by: Vikram Garhwal<fnu.vikram@xilinx.com>
30
+ *
31
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
32
+ * of this software and associated documentation files (the "Software"), to deal
33
+ * in the Software without restriction, including without limitation the rights
34
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
35
+ * copies of the Software, and to permit persons to whom the Software is
36
+ * furnished to do so, subject to the following conditions:
37
+ *
38
+ * The above copyright notice and this permission notice shall be included in
39
+ * all copies or substantial portions of the Software.
40
+ *
41
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
42
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
43
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
44
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
45
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
46
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
47
+ * THE SOFTWARE.
48
+ */
49
+
50
+#include "qemu/osdep.h"
51
+#include "libqos/libqtest.h"
52
+
53
+/* Base address. */
54
+#define CAN0_BASE_ADDR 0xFF060000
55
+#define CAN1_BASE_ADDR 0xFF070000
56
+
57
+/* Register addresses. */
58
+#define R_SRR_OFFSET 0x00
59
+#define R_MSR_OFFSET 0x04
60
+#define R_SR_OFFSET 0x18
61
+#define R_ISR_OFFSET 0x1C
62
+#define R_ICR_OFFSET 0x24
63
+#define R_TXID_OFFSET 0x30
64
+#define R_TXDLC_OFFSET 0x34
65
+#define R_TXDATA1_OFFSET 0x38
66
+#define R_TXDATA2_OFFSET 0x3C
67
+#define R_RXID_OFFSET 0x50
68
+#define R_RXDLC_OFFSET 0x54
69
+#define R_RXDATA1_OFFSET 0x58
70
+#define R_RXDATA2_OFFSET 0x5C
71
+#define R_AFR 0x60
72
+#define R_AFMR1 0x64
73
+#define R_AFIR1 0x68
74
+#define R_AFMR2 0x6C
75
+#define R_AFIR2 0x70
76
+#define R_AFMR3 0x74
77
+#define R_AFIR3 0x78
78
+#define R_AFMR4 0x7C
79
+#define R_AFIR4 0x80
80
+
81
+/* CAN modes. */
82
+#define CONFIG_MODE 0x00
83
+#define NORMAL_MODE 0x00
84
+#define LOOPBACK_MODE 0x02
85
+#define SNOOP_MODE 0x04
86
+#define SLEEP_MODE 0x01
87
+#define ENABLE_CAN (1 << 1)
88
+#define STATUS_NORMAL_MODE (1 << 3)
89
+#define STATUS_LOOPBACK_MODE (1 << 1)
90
+#define STATUS_SNOOP_MODE (1 << 12)
91
+#define STATUS_SLEEP_MODE (1 << 2)
92
+#define ISR_TXOK (1 << 1)
93
+#define ISR_RXOK (1 << 4)
94
+
95
+static void match_rx_tx_data(const uint32_t *buf_tx, const uint32_t *buf_rx,
96
+ uint8_t can_timestamp)
97
+{
98
+ uint16_t size = 0;
99
+ uint8_t len = 4;
100
+
101
+ while (size < len) {
102
+ if (R_RXID_OFFSET + 4 * size == R_RXDLC_OFFSET) {
103
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size] + can_timestamp);
104
+ } else {
105
+ g_assert_cmpint(buf_rx[size], ==, buf_tx[size]);
106
+ }
107
+
108
+ size++;
109
+ }
110
+}
111
+
112
+static void read_data(QTestState *qts, uint64_t can_base_addr, uint32_t *buf_rx)
113
+{
114
+ uint32_t int_status;
115
+
116
+ /* Read the interrupt on CAN rx. */
117
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_RXOK;
118
+
119
+ g_assert_cmpint(int_status, ==, ISR_RXOK);
120
+
121
+ /* Read the RX register data for CAN. */
122
+ buf_rx[0] = qtest_readl(qts, can_base_addr + R_RXID_OFFSET);
123
+ buf_rx[1] = qtest_readl(qts, can_base_addr + R_RXDLC_OFFSET);
124
+ buf_rx[2] = qtest_readl(qts, can_base_addr + R_RXDATA1_OFFSET);
125
+ buf_rx[3] = qtest_readl(qts, can_base_addr + R_RXDATA2_OFFSET);
126
+
127
+ /* Clear the RX interrupt. */
128
+ qtest_writel(qts, CAN1_BASE_ADDR + R_ICR_OFFSET, ISR_RXOK);
129
+}
130
+
131
+static void send_data(QTestState *qts, uint64_t can_base_addr,
132
+ const uint32_t *buf_tx)
133
+{
134
+ uint32_t int_status;
135
+
136
+ /* Write the TX register data for CAN. */
137
+ qtest_writel(qts, can_base_addr + R_TXID_OFFSET, buf_tx[0]);
138
+ qtest_writel(qts, can_base_addr + R_TXDLC_OFFSET, buf_tx[1]);
139
+ qtest_writel(qts, can_base_addr + R_TXDATA1_OFFSET, buf_tx[2]);
140
+ qtest_writel(qts, can_base_addr + R_TXDATA2_OFFSET, buf_tx[3]);
141
+
142
+ /* Read the interrupt on CAN for tx. */
143
+ int_status = qtest_readl(qts, can_base_addr + R_ISR_OFFSET) & ISR_TXOK;
144
+
145
+ g_assert_cmpint(int_status, ==, ISR_TXOK);
146
+
147
+ /* Clear the interrupt for tx. */
148
+ qtest_writel(qts, CAN0_BASE_ADDR + R_ICR_OFFSET, ISR_TXOK);
149
+}
150
+
151
+/*
152
+ * This test will be transferring data from CAN0 and CAN1 through canbus. CAN0
153
+ * initiate the data transfer to can-bus, CAN1 receives the data. Test compares
154
+ * the data sent from CAN0 with received on CAN1.
155
+ */
156
+static void test_can_bus(void)
157
+{
158
+ const uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
159
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
160
+ uint32_t status = 0;
161
+ uint8_t can_timestamp = 1;
162
+
163
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
164
+ " -object can-bus,id=canbus0"
165
+ " -machine xlnx-zcu102.canbus0=canbus0"
166
+ " -machine xlnx-zcu102.canbus1=canbus0"
167
+ );
168
+
169
+ /* Configure the CAN0 and CAN1. */
170
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
171
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
172
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
173
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
174
+
175
+ /* Check here if CAN0 and CAN1 are in normal mode. */
176
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
177
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
178
+
179
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
180
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
181
+
182
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
183
+
184
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
185
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
186
+
187
+ qtest_quit(qts);
188
+}
189
+
190
+/*
191
+ * This test is performing loopback mode on CAN0 and CAN1. Data sent from TX of
192
+ * each CAN0 and CAN1 are compared with RX register data for respective CAN.
193
+ */
194
+static void test_can_loopback(void)
195
+{
196
+ uint32_t buf_tx[4] = { 0xFF, 0x80000000, 0x12345678, 0x87654321 };
197
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
198
+ uint32_t status = 0;
199
+
200
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
201
+ " -object can-bus,id=canbus0"
202
+ " -machine xlnx-zcu102.canbus0=canbus0"
203
+ " -machine xlnx-zcu102.canbus1=canbus0"
204
+ );
205
+
206
+ /* Configure the CAN0 in loopback mode. */
207
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
208
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
209
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
210
+
211
+ /* Check here if CAN0 is set in loopback mode. */
212
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
213
+
214
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
215
+
216
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
217
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
218
+ match_rx_tx_data(buf_tx, buf_rx, 0);
219
+
220
+ /* Configure the CAN1 in loopback mode. */
221
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
222
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, LOOPBACK_MODE);
223
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
224
+
225
+ /* Check here if CAN1 is set in loopback mode. */
226
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
227
+
228
+ g_assert_cmpint(status, ==, STATUS_LOOPBACK_MODE);
229
+
230
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
231
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
232
+ match_rx_tx_data(buf_tx, buf_rx, 0);
233
+
234
+ qtest_quit(qts);
235
+}
236
+
237
+/*
238
+ * Enable filters for CAN1. This will filter incoming messages with ID. In this
239
+ * test message will pass through filter 2.
240
+ */
241
+static void test_can_filter(void)
242
+{
243
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
244
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
245
+ uint32_t status = 0;
246
+ uint8_t can_timestamp = 1;
247
+
248
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
249
+ " -object can-bus,id=canbus0"
250
+ " -machine xlnx-zcu102.canbus0=canbus0"
251
+ " -machine xlnx-zcu102.canbus1=canbus0"
252
+ );
253
+
254
+ /* Configure the CAN0 and CAN1. */
255
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
256
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
257
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
258
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
259
+
260
+ /* Check here if CAN0 and CAN1 are in normal mode. */
261
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
262
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
263
+
264
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
265
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
266
+
267
+ /* Set filter for CAN1 for incoming messages. */
268
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0x0);
269
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR1, 0xF7);
270
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR1, 0x121F);
271
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR2, 0x5431);
272
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR2, 0x14);
273
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR3, 0x1234);
274
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR3, 0x5431);
275
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFMR4, 0xFFF);
276
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFIR4, 0x1234);
277
+
278
+ qtest_writel(qts, CAN1_BASE_ADDR + R_AFR, 0xF);
279
+
280
+ send_data(qts, CAN0_BASE_ADDR, buf_tx);
281
+
282
+ read_data(qts, CAN1_BASE_ADDR, buf_rx);
283
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
284
+
285
+ qtest_quit(qts);
286
+}
287
+
288
+/* Testing sleep mode on CAN0 while CAN1 is in normal mode. */
289
+static void test_can_sleepmode(void)
290
+{
291
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
292
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
293
+ uint32_t status = 0;
294
+ uint8_t can_timestamp = 1;
295
+
296
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
297
+ " -object can-bus,id=canbus0"
298
+ " -machine xlnx-zcu102.canbus0=canbus0"
299
+ " -machine xlnx-zcu102.canbus1=canbus0"
300
+ );
301
+
302
+ /* Configure the CAN0. */
303
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
304
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SLEEP_MODE);
305
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
306
+
307
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
308
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
309
+
310
+ /* Check here if CAN0 is in SLEEP mode and CAN1 in normal mode. */
311
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
312
+ g_assert_cmpint(status, ==, STATUS_SLEEP_MODE);
313
+
314
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
315
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
316
+
317
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
318
+
319
+ /*
320
+ * Once CAN1 sends data on can-bus. CAN0 should exit sleep mode.
321
+ * Check the CAN0 status now. It should exit the sleep mode and receive the
322
+ * incoming data.
323
+ */
324
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
325
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
326
+
327
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
328
+
329
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
330
+
331
+ qtest_quit(qts);
332
+}
333
+
334
+/* Testing Snoop mode on CAN0 while CAN1 is in normal mode. */
335
+static void test_can_snoopmode(void)
336
+{
337
+ uint32_t buf_tx[4] = { 0x14, 0x80000000, 0x12345678, 0x87654321 };
338
+ uint32_t buf_rx[4] = { 0x00, 0x00, 0x00, 0x00 };
339
+ uint32_t status = 0;
340
+ uint8_t can_timestamp = 1;
341
+
342
+ QTestState *qts = qtest_init("-machine xlnx-zcu102"
343
+ " -object can-bus,id=canbus0"
344
+ " -machine xlnx-zcu102.canbus0=canbus0"
345
+ " -machine xlnx-zcu102.canbus1=canbus0"
346
+ );
347
+
348
+ /* Configure the CAN0. */
349
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, CONFIG_MODE);
350
+ qtest_writel(qts, CAN0_BASE_ADDR + R_MSR_OFFSET, SNOOP_MODE);
351
+ qtest_writel(qts, CAN0_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
352
+
353
+ qtest_writel(qts, CAN1_BASE_ADDR + R_SRR_OFFSET, ENABLE_CAN);
354
+ qtest_writel(qts, CAN1_BASE_ADDR + R_MSR_OFFSET, NORMAL_MODE);
355
+
356
+ /* Check here if CAN0 is in SNOOP mode and CAN1 in normal mode. */
357
+ status = qtest_readl(qts, CAN0_BASE_ADDR + R_SR_OFFSET);
358
+ g_assert_cmpint(status, ==, STATUS_SNOOP_MODE);
359
+
360
+ status = qtest_readl(qts, CAN1_BASE_ADDR + R_SR_OFFSET);
361
+ g_assert_cmpint(status, ==, STATUS_NORMAL_MODE);
362
+
363
+ send_data(qts, CAN1_BASE_ADDR, buf_tx);
364
+
365
+ read_data(qts, CAN0_BASE_ADDR, buf_rx);
366
+
367
+ match_rx_tx_data(buf_tx, buf_rx, can_timestamp);
368
+
369
+ qtest_quit(qts);
370
+}
371
+
372
+int main(int argc, char **argv)
373
+{
374
+ g_test_init(&argc, &argv, NULL);
375
+
376
+ qtest_add_func("/net/can/can_bus", test_can_bus);
377
+ qtest_add_func("/net/can/can_loopback", test_can_loopback);
378
+ qtest_add_func("/net/can/can_filter", test_can_filter);
379
+ qtest_add_func("/net/can/can_test_snoopmode", test_can_snoopmode);
380
+ qtest_add_func("/net/can/can_test_sleepmode", test_can_sleepmode);
381
+
382
+ return g_test_run();
383
+}
384
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
21
index XXXXXXX..XXXXXXX 100644
385
index XXXXXXX..XXXXXXX 100644
22
--- a/tests/qtest/arm-cpu-features.c
386
--- a/tests/qtest/meson.build
23
+++ b/tests/qtest/arm-cpu-features.c
387
+++ b/tests/qtest/meson.build
24
@@ -XXX,XX +XXX,XX @@ static bool resp_get_feature(QDict *resp, const char *feature)
388
@@ -XXX,XX +XXX,XX @@ qtests_aarch64 = \
25
qobject_unref(_resp); \
389
['arm-cpu-features',
26
})
390
'numa-test',
27
391
'boot-serial-test',
28
-#define assert_feature(qts, cpu_type, feature, expected_value) \
392
+ 'xlnx-can-test',
29
+#define resp_assert_feature(resp, feature, expected_value) \
393
'migration-test']
30
({ \
394
31
- QDict *_resp, *_props; \
395
qtests_s390x = \
32
+ QDict *_props; \
33
\
34
- _resp = do_query_no_props(qts, cpu_type); \
35
g_assert(_resp); \
36
g_assert(resp_has_props(_resp)); \
37
_props = resp_get_props(_resp); \
38
g_assert(qdict_get(_props, feature)); \
39
g_assert(qdict_get_bool(_props, feature) == (expected_value)); \
40
+})
41
+
42
+#define assert_feature(qts, cpu_type, feature, expected_value) \
43
+({ \
44
+ QDict *_resp; \
45
+ \
46
+ _resp = do_query_no_props(qts, cpu_type); \
47
+ g_assert(_resp); \
48
+ resp_assert_feature(_resp, feature, expected_value); \
49
+ qobject_unref(_resp); \
50
+})
51
+
52
+#define assert_set_feature(qts, cpu_type, feature, value) \
53
+({ \
54
+ const char *_fmt = (value) ? "{ %s: true }" : "{ %s: false }"; \
55
+ QDict *_resp; \
56
+ \
57
+ _resp = do_query(qts, cpu_type, _fmt, feature); \
58
+ g_assert(_resp); \
59
+ resp_assert_feature(_resp, feature, value); \
60
qobject_unref(_resp); \
61
})
62
63
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion(const void *data)
64
assert_error(qts, "host", "The CPU type 'host' requires KVM", NULL);
65
66
/* Test expected feature presence/absence for some cpu types */
67
- assert_has_feature_enabled(qts, "max", "pmu");
68
assert_has_feature_enabled(qts, "cortex-a15", "pmu");
69
assert_has_not_feature(qts, "cortex-a15", "aarch64");
70
71
+ /* Enabling and disabling pmu should always work. */
72
+ assert_has_feature_enabled(qts, "max", "pmu");
73
+ assert_set_feature(qts, "max", "pmu", false);
74
+ assert_set_feature(qts, "max", "pmu", true);
75
+
76
assert_has_not_feature(qts, "max", "kvm-no-adjvtime");
77
78
if (g_str_equal(qtest_get_arch(), "aarch64")) {
79
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion_kvm(const void *data)
80
return;
81
}
82
83
+ /* Enabling and disabling kvm-no-adjvtime should always work. */
84
assert_has_feature_disabled(qts, "host", "kvm-no-adjvtime");
85
+ assert_set_feature(qts, "host", "kvm-no-adjvtime", true);
86
+ assert_set_feature(qts, "host", "kvm-no-adjvtime", false);
87
88
if (g_str_equal(qtest_get_arch(), "aarch64")) {
89
bool kvm_supports_sve;
90
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion_kvm(const void *data)
91
char *error;
92
93
assert_has_feature_enabled(qts, "host", "aarch64");
94
+
95
+ /* Enabling and disabling pmu should always work. */
96
assert_has_feature_enabled(qts, "host", "pmu");
97
+ assert_set_feature(qts, "host", "pmu", false);
98
+ assert_set_feature(qts, "host", "pmu", true);
99
100
assert_error(qts, "cortex-a15",
101
"We cannot guarantee the CPU type 'cortex-a15' works "
102
--
396
--
103
2.20.1
397
2.20.1
104
398
105
399
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Vikram Garhwal <fnu.vikram@xilinx.com>
2
2
3
'ARM SBCon two-wire serial bus interface' is the official
3
Reviewed-by: Francisco Iglesias <francisco.iglesias@xilinx.com>
4
name describing the pair of registers used to bitbanging
4
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
5
I2C in the Versatile boards.
5
Signed-off-by: Vikram Garhwal <fnu.vikram@xilinx.com>
6
6
Message-id: 1605728926-352690-5-git-send-email-fnu.vikram@xilinx.com
7
Make the private VersatileI2CState structure as public
8
ArmSbconI2CState.
9
Add the TYPE_ARM_SBCON_I2C, alias to our current
10
TYPE_VERSATILE_I2C model.
11
Rename the memory region description as 'arm_sbcon_i2c'.
12
13
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Message-id: 20200617072539.32686-5-f4bug@amsat.org
15
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
8
---
18
include/hw/i2c/arm_sbcon_i2c.h | 35 ++++++++++++++++++++++++++++++++++
9
MAINTAINERS | 8 ++++++++
19
hw/i2c/versatile_i2c.c | 17 +++++------------
10
1 file changed, 8 insertions(+)
20
MAINTAINERS | 1 +
21
3 files changed, 41 insertions(+), 12 deletions(-)
22
create mode 100644 include/hw/i2c/arm_sbcon_i2c.h
23
11
24
diff --git a/include/hw/i2c/arm_sbcon_i2c.h b/include/hw/i2c/arm_sbcon_i2c.h
25
new file mode 100644
26
index XXXXXXX..XXXXXXX
27
--- /dev/null
28
+++ b/include/hw/i2c/arm_sbcon_i2c.h
29
@@ -XXX,XX +XXX,XX @@
30
+/*
31
+ * ARM SBCon two-wire serial bus interface (I2C bitbang)
32
+ * a.k.a.
33
+ * ARM Versatile I2C controller
34
+ *
35
+ * Copyright (c) 2006-2007 CodeSourcery.
36
+ * Copyright (c) 2012 Oskar Andero <oskar.andero@gmail.com>
37
+ * Copyright (C) 2020 Philippe Mathieu-Daudé <f4bug@amsat.org>
38
+ *
39
+ * SPDX-License-Identifier: GPL-2.0-or-later
40
+ */
41
+#ifndef HW_I2C_ARM_SBCON_H
42
+#define HW_I2C_ARM_SBCON_H
43
+
44
+#include "hw/sysbus.h"
45
+#include "hw/i2c/bitbang_i2c.h"
46
+
47
+#define TYPE_VERSATILE_I2C "versatile_i2c"
48
+#define TYPE_ARM_SBCON_I2C TYPE_VERSATILE_I2C
49
+
50
+#define ARM_SBCON_I2C(obj) \
51
+ OBJECT_CHECK(ArmSbconI2CState, (obj), TYPE_ARM_SBCON_I2C)
52
+
53
+typedef struct ArmSbconI2CState {
54
+ /*< private >*/
55
+ SysBusDevice parent_obj;
56
+ /*< public >*/
57
+
58
+ MemoryRegion iomem;
59
+ bitbang_i2c_interface bitbang;
60
+ int out;
61
+ int in;
62
+} ArmSbconI2CState;
63
+
64
+#endif /* HW_I2C_ARM_SBCON_H */
65
diff --git a/hw/i2c/versatile_i2c.c b/hw/i2c/versatile_i2c.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/hw/i2c/versatile_i2c.c
68
+++ b/hw/i2c/versatile_i2c.c
69
@@ -XXX,XX +XXX,XX @@
70
/*
71
- * ARM Versatile I2C controller
72
+ * ARM SBCon two-wire serial bus interface (I2C bitbang)
73
+ * a.k.a. ARM Versatile I2C controller
74
*
75
* Copyright (c) 2006-2007 CodeSourcery.
76
* Copyright (c) 2012 Oskar Andero <oskar.andero@gmail.com>
77
@@ -XXX,XX +XXX,XX @@
78
*/
79
80
#include "qemu/osdep.h"
81
-#include "hw/sysbus.h"
82
-#include "hw/i2c/bitbang_i2c.h"
83
+#include "hw/i2c/arm_sbcon_i2c.h"
84
#include "hw/registerfields.h"
85
#include "qemu/log.h"
86
#include "qemu/module.h"
87
88
-#define TYPE_VERSATILE_I2C "versatile_i2c"
89
#define VERSATILE_I2C(obj) \
90
OBJECT_CHECK(VersatileI2CState, (obj), TYPE_VERSATILE_I2C)
91
92
-typedef struct VersatileI2CState {
93
- SysBusDevice parent_obj;
94
+typedef ArmSbconI2CState VersatileI2CState;
95
96
- MemoryRegion iomem;
97
- bitbang_i2c_interface bitbang;
98
- int out;
99
- int in;
100
-} VersatileI2CState;
101
102
REG32(CONTROL_GET, 0)
103
REG32(CONTROL_SET, 0)
104
@@ -XXX,XX +XXX,XX @@ static void versatile_i2c_init(Object *obj)
105
bus = i2c_init_bus(dev, "i2c");
106
bitbang_i2c_init(&s->bitbang, bus);
107
memory_region_init_io(&s->iomem, obj, &versatile_i2c_ops, s,
108
- "versatile_i2c", 0x1000);
109
+ "arm_sbcon_i2c", 0x1000);
110
sysbus_init_mmio(sbd, &s->iomem);
111
}
112
113
diff --git a/MAINTAINERS b/MAINTAINERS
12
diff --git a/MAINTAINERS b/MAINTAINERS
114
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
115
--- a/MAINTAINERS
14
--- a/MAINTAINERS
116
+++ b/MAINTAINERS
15
+++ b/MAINTAINERS
117
@@ -XXX,XX +XXX,XX @@ M: Peter Maydell <peter.maydell@linaro.org>
16
@@ -XXX,XX +XXX,XX @@ F: hw/net/opencores_eth.c
118
L: qemu-arm@nongnu.org
17
18
Devices
19
-------
20
+Xilinx CAN
21
+M: Vikram Garhwal <fnu.vikram@xilinx.com>
22
+M: Francisco Iglesias <francisco.iglesias@xilinx.com>
23
+S: Maintained
24
+F: hw/net/can/xlnx-*
25
+F: include/hw/net/xlnx-*
26
+F: tests/qtest/xlnx-can-test*
27
+
28
EDU
29
M: Jiri Slaby <jslaby@suse.cz>
119
S: Maintained
30
S: Maintained
120
F: hw/*/versatile*
121
+F: include/hw/i2c/arm_sbcon_i2c.h
122
F: hw/misc/arm_sysctl.c
123
F: docs/system/arm/versatile.rst
124
125
--
31
--
126
2.20.1
32
2.20.1
127
33
128
34
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
2
2
3
From 'Application Note AN385', chapter 3.9, SPI:
3
Trusted Firmware now supports A72 on sbsa-ref by default [1] so enable
4
it for QEMU as well. A53 was already enabled there.
4
5
5
The SMM implements five PL022 SPI modules.
6
1. https://review.trustedfirmware.org/c/TF-A/trusted-firmware-a/+/7117
6
7
7
Two pairs of modules share the same OR-gated IRQ.
8
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
8
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20201120141705.246690-1-marcin.juszkiewicz@linaro.org
10
Message-id: 20200617072539.32686-12-f4bug@amsat.org
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
13
---
14
hw/arm/mps2.c | 24 ++++++++++++++++++++++++
14
hw/arm/sbsa-ref.c | 23 ++++++++++++++++++++---
15
hw/arm/Kconfig | 6 +++---
15
1 file changed, 20 insertions(+), 3 deletions(-)
16
2 files changed, 27 insertions(+), 3 deletions(-)
17
16
18
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
17
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
19
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/mps2.c
19
--- a/hw/arm/sbsa-ref.c
21
+++ b/hw/arm/mps2.c
20
+++ b/hw/arm/sbsa-ref.c
22
@@ -XXX,XX +XXX,XX @@
21
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
23
#include "hw/timer/cmsdk-apb-dualtimer.h"
22
[SBSA_GWDT] = 16,
24
#include "hw/misc/mps2-scc.h"
23
};
25
#include "hw/misc/mps2-fpgaio.h"
24
26
+#include "hw/ssi/pl022.h"
25
+static const char * const valid_cpus[] = {
27
#include "hw/net/lan9118.h"
26
+ ARM_CPU_TYPE_NAME("cortex-a53"),
28
#include "net/net.h"
27
+ ARM_CPU_TYPE_NAME("cortex-a57"),
29
#include "hw/watchdog/cmsdk-apb-watchdog.h"
28
+ ARM_CPU_TYPE_NAME("cortex-a72"),
30
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
29
+};
31
qdev_prop_set_uint32(DEVICE(&mms->fpgaio), "prescale-clk", 25000000);
32
sysbus_realize(SYS_BUS_DEVICE(&mms->fpgaio), &error_fatal);
33
sysbus_mmio_map(SYS_BUS_DEVICE(&mms->fpgaio), 0, 0x40028000);
34
+ sysbus_create_simple(TYPE_PL022, 0x40025000, /* External ADC */
35
+ qdev_get_gpio_in(armv7m, 22));
36
+ for (i = 0; i < 2; i++) {
37
+ static const int spi_irqno[] = {11, 24};
38
+ static const hwaddr spibase[] = {0x40020000, /* APB */
39
+ 0x40021000, /* LCD */
40
+ 0x40026000, /* Shield0 */
41
+ 0x40027000}; /* Shield1 */
42
+ DeviceState *orgate_dev;
43
+ Object *orgate;
44
+ int j;
45
+
30
+
46
+ orgate = object_new(TYPE_OR_IRQ);
31
+static bool cpu_type_valid(const char *cpu)
47
+ object_property_set_int(orgate, 2, "num-lines", &error_fatal);
32
+{
48
+ orgate_dev = DEVICE(orgate);
33
+ int i;
49
+ qdev_realize(orgate_dev, NULL, &error_fatal);
34
+
50
+ qdev_connect_gpio_out(orgate_dev, 0,
35
+ for (i = 0; i < ARRAY_SIZE(valid_cpus); i++) {
51
+ qdev_get_gpio_in(armv7m, spi_irqno[i]));
36
+ if (strcmp(cpu, valid_cpus[i]) == 0) {
52
+ for (j = 0; j < 2; j++) {
37
+ return true;
53
+ sysbus_create_simple(TYPE_PL022, spibase[2 * i + j],
54
+ qdev_get_gpio_in(orgate_dev, j));
55
+ }
38
+ }
56
+ }
39
+ }
57
40
+ return false;
58
/* In hardware this is a LAN9220; the LAN9118 is software compatible
41
+}
59
* except that it doesn't support the checksum-offload feature.
42
+
60
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
43
static uint64_t sbsa_ref_cpu_mp_affinity(SBSAMachineState *sms, int idx)
61
index XXXXXXX..XXXXXXX 100644
44
{
62
--- a/hw/arm/Kconfig
45
uint8_t clustersz = ARM_DEFAULT_CPUS_PER_CLUSTER;
63
+++ b/hw/arm/Kconfig
46
@@ -XXX,XX +XXX,XX @@ static void sbsa_ref_init(MachineState *machine)
64
@@ -XXX,XX +XXX,XX @@ config HIGHBANK
47
const CPUArchIdList *possible_cpus;
65
select ARM_TIMER # sp804
48
int n, sbsa_max_cpus;
66
select ARM_V7M
49
67
select PL011 # UART
50
- if (strcmp(machine->cpu_type, ARM_CPU_TYPE_NAME("cortex-a57"))) {
68
- select PL022 # Serial port
51
- error_report("sbsa-ref: CPU type other than the built-in "
69
+ select PL022 # SPI
52
- "cortex-a57 not supported");
70
select PL031 # RTC
53
+ if (!cpu_type_valid(machine->cpu_type)) {
71
select PL061 # GPIO
54
+ error_report("mach-virt: CPU type %s not supported", machine->cpu_type);
72
select PL310 # cache controller
55
exit(1);
73
@@ -XXX,XX +XXX,XX @@ config STELLARIS
56
}
74
select CMSDK_APB_WATCHDOG
57
75
select I2C
76
select PL011 # UART
77
- select PL022 # Serial port
78
+ select PL022 # SPI
79
select PL061 # GPIO
80
select SSD0303 # OLED display
81
select SSD0323 # OLED display
82
@@ -XXX,XX +XXX,XX @@ config MPS2
83
select MPS2_FPGAIO
84
select MPS2_SCC
85
select OR_IRQ
86
- select PL022 # Serial port
87
+ select PL022 # SPI
88
select PL080 # DMA controller
89
select SPLIT_IRQ
90
select UNIMP
91
--
58
--
92
2.20.1
59
2.20.1
93
60
94
61
diff view generated by jsdifflib
1
From: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
1
From: Havard Skinnemoen <hskinnemoen@google.com>
2
2
3
This adds support for memory(pc-dimm) hot remove on arm/virt that
3
Dump the collected random data after a randomness test failure.
4
uses acpi ged device.
5
4
6
NVDIMM hot removal is not yet supported.
5
Note that this relies on the test having called
6
g_test_set_nonfatal_assertions() so we don't abort immediately on the
7
assertion failure.
7
8
8
Signed-off-by: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
9
Signed-off-by: Havard Skinnemoen <hskinnemoen@google.com>
9
Message-id: 20200622124157.20360-1-shameerali.kolothum.thodi@huawei.com
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Eric Auger <eric.auger@redhat.com>
11
[PMM: minor commit message tweak]
11
Tested-by: Eric Auger <eric.auger@redhat.com>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
13
---
14
hw/acpi/generic_event_device.c | 29 ++++++++++++++++
14
tests/qtest/npcm7xx_rng-test.c | 12 ++++++++++++
15
hw/arm/virt.c | 62 ++++++++++++++++++++++++++++++++--
15
1 file changed, 12 insertions(+)
16
2 files changed, 89 insertions(+), 2 deletions(-)
17
16
18
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
17
diff --git a/tests/qtest/npcm7xx_rng-test.c b/tests/qtest/npcm7xx_rng-test.c
19
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/acpi/generic_event_device.c
19
--- a/tests/qtest/npcm7xx_rng-test.c
21
+++ b/hw/acpi/generic_event_device.c
20
+++ b/tests/qtest/npcm7xx_rng-test.c
22
@@ -XXX,XX +XXX,XX @@ static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev,
21
@@ -XXX,XX +XXX,XX @@
23
}
22
24
}
23
#include "libqtest-single.h"
25
24
#include "qemu/bitops.h"
26
+static void acpi_ged_unplug_request_cb(HotplugHandler *hotplug_dev,
25
+#include "qemu-common.h"
27
+ DeviceState *dev, Error **errp)
26
27
#define RNG_BASE_ADDR 0xf000b000
28
29
@@ -XXX,XX +XXX,XX @@
30
/* Number of bits to collect for randomness tests. */
31
#define TEST_INPUT_BITS (128)
32
33
+static void dump_buf_if_failed(const uint8_t *buf, size_t size)
28
+{
34
+{
29
+ AcpiGedState *s = ACPI_GED(hotplug_dev);
35
+ if (g_test_failed()) {
30
+
36
+ qemu_hexdump(stderr, "", buf, size);
31
+ if ((object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) &&
32
+ !(object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)))) {
33
+ acpi_memory_unplug_request_cb(hotplug_dev, &s->memhp_state, dev, errp);
34
+ } else {
35
+ error_setg(errp, "acpi: device unplug request for unsupported device"
36
+ " type: %s", object_get_typename(OBJECT(dev)));
37
+ }
37
+ }
38
+}
38
+}
39
+
39
+
40
+static void acpi_ged_unplug_cb(HotplugHandler *hotplug_dev,
40
static void rng_writeb(unsigned int offset, uint8_t value)
41
+ DeviceState *dev, Error **errp)
42
+{
43
+ AcpiGedState *s = ACPI_GED(hotplug_dev);
44
+
45
+ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
46
+ acpi_memory_unplug_cb(&s->memhp_state, dev, errp);
47
+ } else {
48
+ error_setg(errp, "acpi: device unplug for unsupported device"
49
+ " type: %s", object_get_typename(OBJECT(dev)));
50
+ }
51
+}
52
+
53
static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
54
{
41
{
55
AcpiGedState *s = ACPI_GED(adev);
42
writeb(RNG_BASE_ADDR + offset, value);
56
@@ -XXX,XX +XXX,XX @@ static void acpi_ged_class_init(ObjectClass *class, void *data)
43
@@ -XXX,XX +XXX,XX @@ static void test_continuous_monobit(void)
57
dc->vmsd = &vmstate_acpi_ged;
44
}
58
45
59
hc->plug = acpi_ged_device_plug_cb;
46
g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
60
+ hc->unplug_request = acpi_ged_unplug_request_cb;
47
+ dump_buf_if_failed(buf, sizeof(buf));
61
+ hc->unplug = acpi_ged_unplug_cb;
62
63
adevc->send_event = acpi_ged_send_event;
64
}
48
}
65
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
49
66
index XXXXXXX..XXXXXXX 100644
50
/*
67
--- a/hw/arm/virt.c
51
@@ -XXX,XX +XXX,XX @@ static void test_continuous_runs(void)
68
+++ b/hw/arm/virt.c
69
@@ -XXX,XX +XXX,XX @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev,
70
}
52
}
53
54
g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01);
55
+ dump_buf_if_failed(buf.c, sizeof(buf));
71
}
56
}
72
57
73
+static void virt_dimm_unplug_request(HotplugHandler *hotplug_dev,
58
/*
74
+ DeviceState *dev, Error **errp)
59
@@ -XXX,XX +XXX,XX @@ static void test_first_byte_monobit(void)
75
+{
60
}
76
+ VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
61
77
+ Error *local_err = NULL;
62
g_assert_cmpfloat(calc_monobit_p(buf, sizeof(buf)), >, 0.01);
78
+
63
+ dump_buf_if_failed(buf, sizeof(buf));
79
+ if (!vms->acpi_dev) {
80
+ error_setg(&local_err,
81
+ "memory hotplug is not enabled: missing acpi-ged device");
82
+ goto out;
83
+ }
84
+
85
+ if (object_dynamic_cast(OBJECT(dev), TYPE_NVDIMM)) {
86
+ error_setg(&local_err,
87
+ "nvdimm device hot unplug is not supported yet.");
88
+ goto out;
89
+ }
90
+
91
+ hotplug_handler_unplug_request(HOTPLUG_HANDLER(vms->acpi_dev), dev,
92
+ &local_err);
93
+out:
94
+ error_propagate(errp, local_err);
95
+}
96
+
97
+static void virt_dimm_unplug(HotplugHandler *hotplug_dev,
98
+ DeviceState *dev, Error **errp)
99
+{
100
+ VirtMachineState *vms = VIRT_MACHINE(hotplug_dev);
101
+ Error *local_err = NULL;
102
+
103
+ hotplug_handler_unplug(HOTPLUG_HANDLER(vms->acpi_dev), dev, &local_err);
104
+ if (local_err) {
105
+ goto out;
106
+ }
107
+
108
+ pc_dimm_unplug(PC_DIMM(dev), MACHINE(vms));
109
+ qdev_unrealize(dev);
110
+
111
+out:
112
+ error_propagate(errp, local_err);
113
+}
114
+
115
static void virt_machine_device_unplug_request_cb(HotplugHandler *hotplug_dev,
116
DeviceState *dev, Error **errp)
117
{
118
- error_setg(errp, "device unplug request for unsupported device"
119
- " type: %s", object_get_typename(OBJECT(dev)));
120
+ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
121
+ virt_dimm_unplug_request(hotplug_dev, dev, errp);
122
+ } else {
123
+ error_setg(errp, "device unplug request for unsupported device"
124
+ " type: %s", object_get_typename(OBJECT(dev)));
125
+ }
126
+}
127
+
128
+static void virt_machine_device_unplug_cb(HotplugHandler *hotplug_dev,
129
+ DeviceState *dev, Error **errp)
130
+{
131
+ if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
132
+ virt_dimm_unplug(hotplug_dev, dev, errp);
133
+ } else {
134
+ error_setg(errp, "virt: device unplug for unsupported device"
135
+ " type: %s", object_get_typename(OBJECT(dev)));
136
+ }
137
}
64
}
138
65
139
static HotplugHandler *virt_machine_get_hotplug_handler(MachineState *machine,
66
/*
140
@@ -XXX,XX +XXX,XX @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
67
@@ -XXX,XX +XXX,XX @@ static void test_first_byte_runs(void)
141
hc->pre_plug = virt_machine_device_pre_plug_cb;
68
}
142
hc->plug = virt_machine_device_plug_cb;
69
143
hc->unplug_request = virt_machine_device_unplug_request_cb;
70
g_assert_cmpfloat(calc_runs_p(buf.l, sizeof(buf) * BITS_PER_BYTE), >, 0.01);
144
+ hc->unplug = virt_machine_device_unplug_cb;
71
+ dump_buf_if_failed(buf.c, sizeof(buf));
145
mc->numa_mem_supported = true;
72
}
146
mc->nvdimm_supported = true;
73
147
mc->auto_enable_numa_with_memhp = true;
74
int main(int argc, char **argv)
148
--
75
--
149
2.20.1
76
2.20.1
150
77
151
78
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Alex Chen <alex.chen@huawei.com>
2
2
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
3
We should use printf format specifier "%u" instead of "%d" for
4
Message-id: 20200617072539.32686-14-f4bug@amsat.org
4
argument of type "unsigned int".
5
6
Reported-by: Euler Robot <euler.robot@huawei.com>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
8
Message-id: 20201126111109.112238-2-alex.chen@huawei.com
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@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
hw/arm/mps2.c | 1 +
12
hw/misc/imx25_ccm.c | 12 ++++++------
9
1 file changed, 1 insertion(+)
13
1 file changed, 6 insertions(+), 6 deletions(-)
10
14
11
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
15
diff --git a/hw/misc/imx25_ccm.c b/hw/misc/imx25_ccm.c
12
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/mps2.c
17
--- a/hw/misc/imx25_ccm.c
14
+++ b/hw/arm/mps2.c
18
+++ b/hw/misc/imx25_ccm.c
15
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
19
@@ -XXX,XX +XXX,XX @@ static const char *imx25_ccm_reg_name(uint32_t reg)
16
0x4002a000}; /* Shield1 */
20
case IMX25_CCM_LPIMR1_REG:
17
sysbus_create_simple(TYPE_ARM_SBCON_I2C, i2cbase[i], NULL);
21
return "lpimr1";
22
default:
23
- sprintf(unknown, "[%d ?]", reg);
24
+ sprintf(unknown, "[%u ?]", reg);
25
return unknown;
18
}
26
}
19
+ create_unimplemented_device("i2s", 0x40024000, 0x400);
27
}
20
28
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_mpll_clk(IMXCCMState *dev)
21
/* In hardware this is a LAN9220; the LAN9118 is software compatible
29
freq = imx_ccm_calc_pll(s->reg[IMX25_CCM_MPCTL_REG], CKIH_FREQ);
22
* except that it doesn't support the checksum-offload feature.
30
}
31
32
- DPRINTF("freq = %d\n", freq);
33
+ DPRINTF("freq = %u\n", freq);
34
35
return freq;
36
}
37
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_mcu_clk(IMXCCMState *dev)
38
39
freq = freq / (1 + EXTRACT(s->reg[IMX25_CCM_CCTL_REG], ARM_CLK_DIV));
40
41
- DPRINTF("freq = %d\n", freq);
42
+ DPRINTF("freq = %u\n", freq);
43
44
return freq;
45
}
46
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_ahb_clk(IMXCCMState *dev)
47
freq = imx25_ccm_get_mcu_clk(dev)
48
/ (1 + EXTRACT(s->reg[IMX25_CCM_CCTL_REG], AHB_CLK_DIV));
49
50
- DPRINTF("freq = %d\n", freq);
51
+ DPRINTF("freq = %u\n", freq);
52
53
return freq;
54
}
55
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_ipg_clk(IMXCCMState *dev)
56
57
freq = imx25_ccm_get_ahb_clk(dev) / 2;
58
59
- DPRINTF("freq = %d\n", freq);
60
+ DPRINTF("freq = %u\n", freq);
61
62
return freq;
63
}
64
@@ -XXX,XX +XXX,XX @@ static uint32_t imx25_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
65
break;
66
}
67
68
- DPRINTF("Clock = %d) = %d\n", clock, freq);
69
+ DPRINTF("Clock = %d) = %u\n", clock, freq);
70
71
return freq;
72
}
23
--
73
--
24
2.20.1
74
2.20.1
25
75
26
76
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Alex Chen <alex.chen@huawei.com>
2
2
3
From 'Application Note AN385', chapter 3.14:
3
We should use printf format specifier "%u" instead of "%d" for
4
argument of type "unsigned int".
4
5
5
The SMM implements a simple SBCon interface based on I2C.
6
Reported-by: Euler Robot <euler.robot@huawei.com>
6
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
7
There are 4 SBCon interfaces on the FPGA APB subsystem.
8
Message-id: 20201126111109.112238-3-alex.chen@huawei.com
8
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20200617072539.32686-13-f4bug@amsat.org
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
11
---
14
hw/arm/mps2.c | 8 ++++++++
12
hw/misc/imx31_ccm.c | 14 +++++++-------
15
hw/arm/Kconfig | 1 +
13
hw/misc/imx_ccm.c | 4 ++--
16
2 files changed, 9 insertions(+)
14
2 files changed, 9 insertions(+), 9 deletions(-)
17
15
18
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
16
diff --git a/hw/misc/imx31_ccm.c b/hw/misc/imx31_ccm.c
19
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/mps2.c
18
--- a/hw/misc/imx31_ccm.c
21
+++ b/hw/arm/mps2.c
19
+++ b/hw/misc/imx31_ccm.c
22
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static const char *imx31_ccm_reg_name(uint32_t reg)
23
#include "hw/misc/mps2-scc.h"
21
case IMX31_CCM_PDR2_REG:
24
#include "hw/misc/mps2-fpgaio.h"
22
return "PDR2";
25
#include "hw/ssi/pl022.h"
23
default:
26
+#include "hw/i2c/arm_sbcon_i2c.h"
24
- sprintf(unknown, "[%d ?]", reg);
27
#include "hw/net/lan9118.h"
25
+ sprintf(unknown, "[%u ?]", reg);
28
#include "net/net.h"
26
return unknown;
29
#include "hw/watchdog/cmsdk-apb-watchdog.h"
30
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
31
qdev_get_gpio_in(orgate_dev, j));
32
}
33
}
27
}
34
+ for (i = 0; i < 4; i++) {
28
}
35
+ static const hwaddr i2cbase[] = {0x40022000, /* Touch */
29
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_pll_ref_clk(IMXCCMState *dev)
36
+ 0x40023000, /* Audio */
30
freq = CKIH_FREQ;
37
+ 0x40029000, /* Shield0 */
31
}
38
+ 0x4002a000}; /* Shield1 */
32
39
+ sysbus_create_simple(TYPE_ARM_SBCON_I2C, i2cbase[i], NULL);
33
- DPRINTF("freq = %d\n", freq);
40
+ }
34
+ DPRINTF("freq = %u\n", freq);
41
35
42
/* In hardware this is a LAN9220; the LAN9118 is software compatible
36
return freq;
43
* except that it doesn't support the checksum-offload feature.
37
}
44
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
38
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_mpll_clk(IMXCCMState *dev)
39
freq = imx_ccm_calc_pll(s->reg[IMX31_CCM_MPCTL_REG],
40
imx31_ccm_get_pll_ref_clk(dev));
41
42
- DPRINTF("freq = %d\n", freq);
43
+ DPRINTF("freq = %u\n", freq);
44
45
return freq;
46
}
47
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_mcu_main_clk(IMXCCMState *dev)
48
freq = imx31_ccm_get_mpll_clk(dev);
49
}
50
51
- DPRINTF("freq = %d\n", freq);
52
+ DPRINTF("freq = %u\n", freq);
53
54
return freq;
55
}
56
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_hclk_clk(IMXCCMState *dev)
57
freq = imx31_ccm_get_mcu_main_clk(dev)
58
/ (1 + EXTRACT(s->reg[IMX31_CCM_PDR0_REG], MAX));
59
60
- DPRINTF("freq = %d\n", freq);
61
+ DPRINTF("freq = %u\n", freq);
62
63
return freq;
64
}
65
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_ipg_clk(IMXCCMState *dev)
66
freq = imx31_ccm_get_hclk_clk(dev)
67
/ (1 + EXTRACT(s->reg[IMX31_CCM_PDR0_REG], IPG));
68
69
- DPRINTF("freq = %d\n", freq);
70
+ DPRINTF("freq = %u\n", freq);
71
72
return freq;
73
}
74
@@ -XXX,XX +XXX,XX @@ static uint32_t imx31_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
75
break;
76
}
77
78
- DPRINTF("Clock = %d) = %d\n", clock, freq);
79
+ DPRINTF("Clock = %d) = %u\n", clock, freq);
80
81
return freq;
82
}
83
diff --git a/hw/misc/imx_ccm.c b/hw/misc/imx_ccm.c
45
index XXXXXXX..XXXXXXX 100644
84
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/arm/Kconfig
85
--- a/hw/misc/imx_ccm.c
47
+++ b/hw/arm/Kconfig
86
+++ b/hw/misc/imx_ccm.c
48
@@ -XXX,XX +XXX,XX @@ config MPS2
87
@@ -XXX,XX +XXX,XX @@ uint32_t imx_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
49
select SPLIT_IRQ
88
freq = klass->get_clock_frequency(dev, clock);
50
select UNIMP
89
}
51
select CMSDK_APB_WATCHDOG
90
52
+ select VERSATILE_I2C
91
- DPRINTF("(clock = %d) = %d\n", clock, freq);
53
92
+ DPRINTF("(clock = %d) = %u\n", clock, freq);
54
config FSL_IMX7
93
55
bool
94
return freq;
95
}
96
@@ -XXX,XX +XXX,XX @@ uint32_t imx_ccm_calc_pll(uint32_t pllreg, uint32_t base_freq)
97
freq = ((2 * (base_freq >> 10) * (mfi * mfd + mfn)) /
98
(mfd * pd)) << 10;
99
100
- DPRINTF("(pllreg = 0x%08x, base_freq = %d) = %d\n", pllreg, base_freq,
101
+ DPRINTF("(pllreg = 0x%08x, base_freq = %u) = %d\n", pllreg, base_freq,
102
freq);
103
104
return freq;
56
--
105
--
57
2.20.1
106
2.20.1
58
107
59
108
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Alex Chen <alex.chen@huawei.com>
2
2
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
3
We should use printf format specifier "%u" instead of "%d" for
4
Message-id: 20200617072539.32686-11-f4bug@amsat.org
4
argument of type "unsigned int".
5
6
Reported-by: Euler Robot <euler.robot@huawei.com>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
8
Message-id: 20201126111109.112238-4-alex.chen@huawei.com
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@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
hw/arm/mps2.c | 9 +++++++++
12
hw/misc/imx6_ccm.c | 20 ++++++++++----------
9
1 file changed, 9 insertions(+)
13
hw/misc/imx6_src.c | 2 +-
14
2 files changed, 11 insertions(+), 11 deletions(-)
10
15
11
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
16
diff --git a/hw/misc/imx6_ccm.c b/hw/misc/imx6_ccm.c
12
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/mps2.c
18
--- a/hw/misc/imx6_ccm.c
14
+++ b/hw/arm/mps2.c
19
+++ b/hw/misc/imx6_ccm.c
15
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@ static const char *imx6_ccm_reg_name(uint32_t reg)
16
#include "hw/timer/cmsdk-apb-timer.h"
21
case CCM_CMEOR:
17
#include "hw/timer/cmsdk-apb-dualtimer.h"
22
return "CMEOR";
18
#include "hw/misc/mps2-scc.h"
23
default:
19
+#include "hw/misc/mps2-fpgaio.h"
24
- sprintf(unknown, "%d ?", reg);
20
#include "hw/net/lan9118.h"
25
+ sprintf(unknown, "%u ?", reg);
21
#include "net/net.h"
26
return unknown;
22
+#include "hw/watchdog/cmsdk-apb-watchdog.h"
27
}
23
28
}
24
typedef enum MPS2FPGAType {
29
@@ -XXX,XX +XXX,XX @@ static const char *imx6_analog_reg_name(uint32_t reg)
25
FPGA_AN385,
30
case USB_ANALOG_DIGPROG:
26
@@ -XXX,XX +XXX,XX @@ typedef struct {
31
return "USB_ANALOG_DIGPROG";
27
MemoryRegion sram;
32
default:
28
/* FPGA APB subsystem */
33
- sprintf(unknown, "%d ?", reg);
29
MPS2SCC scc;
34
+ sprintf(unknown, "%u ?", reg);
30
+ MPS2FPGAIO fpgaio;
35
return unknown;
31
/* CMSDK APB subsystem */
36
}
32
CMSDKAPBDualTimer dualtimer;
37
}
33
+ CMSDKAPBWatchdog watchdog;
38
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_clk(IMX6CCMState *dev)
34
} MPS2MachineState;
39
freq *= 20;
35
40
}
36
#define TYPE_MPS2_MACHINE "mps2"
41
37
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
42
- DPRINTF("freq = %d\n", (uint32_t)freq);
38
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
43
+ DPRINTF("freq = %u\n", (uint32_t)freq);
39
sysbus_realize(SYS_BUS_DEVICE(&mms->scc), &error_fatal);
44
40
sysbus_mmio_map(SYS_BUS_DEVICE(sccdev), 0, 0x4002f000);
45
return freq;
41
+ object_initialize_child(OBJECT(mms), "fpgaio",
46
}
42
+ &mms->fpgaio, TYPE_MPS2_FPGAIO);
47
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_pfd0_clk(IMX6CCMState *dev)
43
+ qdev_prop_set_uint32(DEVICE(&mms->fpgaio), "prescale-clk", 25000000);
48
freq = imx6_analog_get_pll2_clk(dev) * 18
44
+ sysbus_realize(SYS_BUS_DEVICE(&mms->fpgaio), &error_fatal);
49
/ EXTRACT(dev->analog[CCM_ANALOG_PFD_528], PFD0_FRAC);
45
+ sysbus_mmio_map(SYS_BUS_DEVICE(&mms->fpgaio), 0, 0x40028000);
50
46
51
- DPRINTF("freq = %d\n", (uint32_t)freq);
47
/* In hardware this is a LAN9220; the LAN9118 is software compatible
52
+ DPRINTF("freq = %u\n", (uint32_t)freq);
48
* except that it doesn't support the checksum-offload feature.
53
54
return freq;
55
}
56
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_pll2_pfd2_clk(IMX6CCMState *dev)
57
freq = imx6_analog_get_pll2_clk(dev) * 18
58
/ EXTRACT(dev->analog[CCM_ANALOG_PFD_528], PFD2_FRAC);
59
60
- DPRINTF("freq = %d\n", (uint32_t)freq);
61
+ DPRINTF("freq = %u\n", (uint32_t)freq);
62
63
return freq;
64
}
65
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_analog_get_periph_clk(IMX6CCMState *dev)
66
break;
67
}
68
69
- DPRINTF("freq = %d\n", (uint32_t)freq);
70
+ DPRINTF("freq = %u\n", (uint32_t)freq);
71
72
return freq;
73
}
74
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_ccm_get_ahb_clk(IMX6CCMState *dev)
75
freq = imx6_analog_get_periph_clk(dev)
76
/ (1 + EXTRACT(dev->ccm[CCM_CBCDR], AHB_PODF));
77
78
- DPRINTF("freq = %d\n", (uint32_t)freq);
79
+ DPRINTF("freq = %u\n", (uint32_t)freq);
80
81
return freq;
82
}
83
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_ccm_get_ipg_clk(IMX6CCMState *dev)
84
freq = imx6_ccm_get_ahb_clk(dev)
85
/ (1 + EXTRACT(dev->ccm[CCM_CBCDR], IPG_PODF));
86
87
- DPRINTF("freq = %d\n", (uint32_t)freq);
88
+ DPRINTF("freq = %u\n", (uint32_t)freq);
89
90
return freq;
91
}
92
@@ -XXX,XX +XXX,XX @@ static uint64_t imx6_ccm_get_per_clk(IMX6CCMState *dev)
93
freq = imx6_ccm_get_ipg_clk(dev)
94
/ (1 + EXTRACT(dev->ccm[CCM_CSCMR1], PERCLK_PODF));
95
96
- DPRINTF("freq = %d\n", (uint32_t)freq);
97
+ DPRINTF("freq = %u\n", (uint32_t)freq);
98
99
return freq;
100
}
101
@@ -XXX,XX +XXX,XX @@ static uint32_t imx6_ccm_get_clock_frequency(IMXCCMState *dev, IMXClk clock)
102
break;
103
}
104
105
- DPRINTF("Clock = %d) = %d\n", clock, freq);
106
+ DPRINTF("Clock = %d) = %u\n", clock, freq);
107
108
return freq;
109
}
110
diff --git a/hw/misc/imx6_src.c b/hw/misc/imx6_src.c
111
index XXXXXXX..XXXXXXX 100644
112
--- a/hw/misc/imx6_src.c
113
+++ b/hw/misc/imx6_src.c
114
@@ -XXX,XX +XXX,XX @@ static const char *imx6_src_reg_name(uint32_t reg)
115
case SRC_GPR10:
116
return "SRC_GPR10";
117
default:
118
- sprintf(unknown, "%d ?", reg);
119
+ sprintf(unknown, "%u ?", reg);
120
return unknown;
121
}
122
}
49
--
123
--
50
2.20.1
124
2.20.1
51
125
52
126
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Alex Chen <alex.chen@huawei.com>
2
2
3
We already model the CMSDK APB watchdog device, let's use it!
3
We should use printf format specifier "%u" instead of "%d" for
4
argument of type "unsigned int".
4
5
5
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
6
Reported-by: Euler Robot <euler.robot@huawei.com>
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Signed-off-by: Alex Chen <alex.chen@huawei.com>
7
Message-id: 20200617072539.32686-9-f4bug@amsat.org
8
Message-id: 20201126111109.112238-5-alex.chen@huawei.com
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@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
hw/arm/mps2.c | 7 +++++++
12
hw/misc/imx6ul_ccm.c | 4 ++--
12
hw/arm/Kconfig | 1 +
13
1 file changed, 2 insertions(+), 2 deletions(-)
13
2 files changed, 8 insertions(+)
14
14
15
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
15
diff --git a/hw/misc/imx6ul_ccm.c b/hw/misc/imx6ul_ccm.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/mps2.c
17
--- a/hw/misc/imx6ul_ccm.c
18
+++ b/hw/arm/mps2.c
18
+++ b/hw/misc/imx6ul_ccm.c
19
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
19
@@ -XXX,XX +XXX,XX @@ static const char *imx6ul_ccm_reg_name(uint32_t reg)
20
sysbus_connect_irq(SYS_BUS_DEVICE(&mms->dualtimer), 0,
20
case CCM_CMEOR:
21
qdev_get_gpio_in(armv7m, 10));
21
return "CMEOR";
22
sysbus_mmio_map(SYS_BUS_DEVICE(&mms->dualtimer), 0, 0x40002000);
22
default:
23
+ object_initialize_child(OBJECT(mms), "watchdog", &mms->watchdog,
23
- sprintf(unknown, "%d ?", reg);
24
+ TYPE_CMSDK_APB_WATCHDOG);
24
+ sprintf(unknown, "%u ?", reg);
25
+ qdev_prop_set_uint32(DEVICE(&mms->watchdog), "wdogclk-frq", SYSCLK_FRQ);
25
return unknown;
26
+ sysbus_realize(SYS_BUS_DEVICE(&mms->watchdog), &error_fatal);
26
}
27
+ sysbus_connect_irq(SYS_BUS_DEVICE(&mms->watchdog), 0,
27
}
28
+ qdev_get_gpio_in_named(armv7m, "NMI", 0));
28
@@ -XXX,XX +XXX,XX @@ static const char *imx6ul_analog_reg_name(uint32_t reg)
29
+ sysbus_mmio_map(SYS_BUS_DEVICE(&mms->watchdog), 0, 0x40008000);
29
case USB_ANALOG_DIGPROG:
30
30
return "USB_ANALOG_DIGPROG";
31
/* FPGA APB subsystem */
31
default:
32
object_initialize_child(OBJECT(mms), "scc", &mms->scc, TYPE_MPS2_SCC);
32
- sprintf(unknown, "%d ?", reg);
33
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
33
+ sprintf(unknown, "%u ?", reg);
34
index XXXXXXX..XXXXXXX 100644
34
return unknown;
35
--- a/hw/arm/Kconfig
35
}
36
+++ b/hw/arm/Kconfig
36
}
37
@@ -XXX,XX +XXX,XX @@ config MPS2
38
select PL080 # DMA controller
39
select SPLIT_IRQ
40
select UNIMP
41
+ select CMSDK_APB_WATCHDOG
42
43
config FSL_IMX7
44
bool
45
--
37
--
46
2.20.1
38
2.20.1
47
39
48
40
diff view generated by jsdifflib
1
Convert the VREV32 and VREV16 insns in the Neon 2-reg-misc group
1
For M-profile CPUs, the range from 0xe0000000 to 0xe00fffff is the
2
to decodetree.
2
Private Peripheral Bus range, which includes all of the memory mapped
3
devices and registers that are part of the CPU itself, including the
4
NVIC, systick timer, and debug and trace components like the Data
5
Watchpoint and Trace unit (DWT). Within this large region, the range
6
0xe000e000 to 0xe000efff is the System Control Space (NVIC, system
7
registers, systick) and 0xe002e000 to 0exe002efff is its Non-secure
8
alias.
9
10
The architecture is clear that within the SCS unimplemented registers
11
should be RES0 for privileged accesses and generate BusFault for
12
unprivileged accesses, and we currently implement this.
13
14
It is less clear about how to handle accesses to unimplemented
15
regions of the wider PPB. Unprivileged accesses should definitely
16
cause BusFaults (R_DQQS), but the behaviour of privileged accesses is
17
not given as a general rule. However, the register definitions of
18
individual registers for components like the DWT all state that they
19
are RES0 if the relevant component is not implemented, so the
20
simplest way to provide that is to provide RAZ/WI for the whole range
21
for privileged accesses. (The v7M Arm ARM does say that reserved
22
registers should be UNK/SBZP.)
23
24
Expand the container MemoryRegion that the NVIC exposes so that
25
it covers the whole PPB space. This means:
26
* moving the address that the ARMV7M device maps it to down by
27
0xe000 bytes
28
* moving the off and the offsets within the container of all the
29
subregions forward by 0xe000 bytes
30
* adding a new default MemoryRegion that covers the whole container
31
at a lower priority than anything else and which provides the
32
RAZWI/BusFault behaviour
3
33
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
34
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
35
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200616170844.13318-13-peter.maydell@linaro.org
36
Message-id: 20201119215617.29887-2-peter.maydell@linaro.org
7
---
37
---
8
target/arm/translate.h | 1 +
38
include/hw/intc/armv7m_nvic.h | 1 +
9
target/arm/neon-dp.decode | 2 ++
39
hw/arm/armv7m.c | 2 +-
10
target/arm/translate-neon.inc.c | 55 +++++++++++++++++++++++++++++++++
40
hw/intc/armv7m_nvic.c | 78 ++++++++++++++++++++++++++++++-----
11
target/arm/translate.c | 12 ++-----
41
3 files changed, 69 insertions(+), 12 deletions(-)
12
4 files changed, 60 insertions(+), 10 deletions(-)
13
42
14
diff --git a/target/arm/translate.h b/target/arm/translate.h
43
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
15
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate.h
45
--- a/include/hw/intc/armv7m_nvic.h
17
+++ b/target/arm/translate.h
46
+++ b/include/hw/intc/armv7m_nvic.h
18
@@ -XXX,XX +XXX,XX @@ typedef void GVecGen4Fn(unsigned, uint32_t, uint32_t, uint32_t,
47
@@ -XXX,XX +XXX,XX @@ struct NVICState {
19
uint32_t, uint32_t, uint32_t);
48
MemoryRegion systickmem;
20
49
MemoryRegion systick_ns_mem;
21
/* Function prototype for gen_ functions for calling Neon helpers */
50
MemoryRegion container;
22
+typedef void NeonGenOneOpFn(TCGv_i32, TCGv_i32);
51
+ MemoryRegion defaultmem;
23
typedef void NeonGenOneOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32);
52
24
typedef void NeonGenTwoOpFn(TCGv_i32, TCGv_i32, TCGv_i32);
53
uint32_t num_irq;
25
typedef void NeonGenTwoOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32);
54
qemu_irq excpout;
26
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
55
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
27
index XXXXXXX..XXXXXXX 100644
56
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/neon-dp.decode
57
--- a/hw/arm/armv7m.c
29
+++ b/target/arm/neon-dp.decode
58
+++ b/hw/arm/armv7m.c
30
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
59
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
31
&2misc vm=%vm_dp vd=%vd_dp q=1
60
sysbus_connect_irq(sbd, 0,
32
61
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
33
VREV64 1111 001 11 . 11 .. 00 .... 0 0000 . . 0 .... @2misc
62
34
+ VREV32 1111 001 11 . 11 .. 00 .... 0 0001 . . 0 .... @2misc
63
- memory_region_add_subregion(&s->container, 0xe000e000,
35
+ VREV16 1111 001 11 . 11 .. 00 .... 0 0010 . . 0 .... @2misc
64
+ memory_region_add_subregion(&s->container, 0xe0000000,
36
65
sysbus_mmio_get_region(sbd, 0));
37
VPADDL_S 1111 001 11 . 11 .. 00 .... 0 0100 . . 0 .... @2misc
66
38
VPADDL_U 1111 001 11 . 11 .. 00 .... 0 0101 . . 0 .... @2misc
67
for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
39
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
68
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
40
index XXXXXXX..XXXXXXX 100644
69
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/translate-neon.inc.c
70
--- a/hw/intc/armv7m_nvic.c
42
+++ b/target/arm/translate-neon.inc.c
71
+++ b/hw/intc/armv7m_nvic.c
43
@@ -XXX,XX +XXX,XX @@ DO_2M_CRYPTO(AESIMC, aa32_aes, 0)
72
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_systick_ops = {
44
DO_2M_CRYPTO(SHA1H, aa32_sha1, 2)
73
.endianness = DEVICE_NATIVE_ENDIAN,
45
DO_2M_CRYPTO(SHA1SU1, aa32_sha1, 2)
74
};
46
DO_2M_CRYPTO(SHA256SU0, aa32_sha2, 2)
75
47
+
76
+/*
48
+static bool do_2misc(DisasContext *s, arg_2misc *a, NeonGenOneOpFn *fn)
77
+ * Unassigned portions of the PPB space are RAZ/WI for privileged
78
+ * accesses, and fault for non-privileged accesses.
79
+ */
80
+static MemTxResult ppb_default_read(void *opaque, hwaddr addr,
81
+ uint64_t *data, unsigned size,
82
+ MemTxAttrs attrs)
49
+{
83
+{
50
+ int pass;
84
+ qemu_log_mask(LOG_UNIMP, "Read of unassigned area of PPB: offset 0x%x\n",
51
+
85
+ (uint32_t)addr);
52
+ /* Handle a 2-reg-misc operation by iterating 32 bits at a time */
86
+ if (attrs.user) {
53
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
87
+ return MEMTX_ERROR;
54
+ return false;
55
+ }
88
+ }
56
+
89
+ *data = 0;
57
+ /* UNDEF accesses to D16-D31 if they don't exist. */
90
+ return MEMTX_OK;
58
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
59
+ ((a->vd | a->vm) & 0x10)) {
60
+ return false;
61
+ }
62
+
63
+ if (!fn) {
64
+ return false;
65
+ }
66
+
67
+ if ((a->vd | a->vm) & a->q) {
68
+ return false;
69
+ }
70
+
71
+ if (!vfp_access_check(s)) {
72
+ return true;
73
+ }
74
+
75
+ for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
76
+ TCGv_i32 tmp = neon_load_reg(a->vm, pass);
77
+ fn(tmp, tmp);
78
+ neon_store_reg(a->vd, pass, tmp);
79
+ }
80
+
81
+ return true;
82
+}
91
+}
83
+
92
+
84
+static bool trans_VREV32(DisasContext *s, arg_2misc *a)
93
+static MemTxResult ppb_default_write(void *opaque, hwaddr addr,
94
+ uint64_t value, unsigned size,
95
+ MemTxAttrs attrs)
85
+{
96
+{
86
+ static NeonGenOneOpFn * const fn[] = {
97
+ qemu_log_mask(LOG_UNIMP, "Write of unassigned area of PPB: offset 0x%x\n",
87
+ tcg_gen_bswap32_i32,
98
+ (uint32_t)addr);
88
+ gen_swap_half,
99
+ if (attrs.user) {
89
+ NULL,
100
+ return MEMTX_ERROR;
90
+ NULL,
101
+ }
91
+ };
102
+ return MEMTX_OK;
92
+ return do_2misc(s, a, fn[a->size]);
93
+}
103
+}
94
+
104
+
95
+static bool trans_VREV16(DisasContext *s, arg_2misc *a)
105
+static const MemoryRegionOps ppb_default_ops = {
96
+{
106
+ .read_with_attrs = ppb_default_read,
97
+ if (a->size != 0) {
107
+ .write_with_attrs = ppb_default_write,
98
+ return false;
108
+ .endianness = DEVICE_NATIVE_ENDIAN,
99
+ }
109
+ .valid.min_access_size = 1,
100
+ return do_2misc(s, a, gen_rev16);
110
+ .valid.max_access_size = 8,
101
+}
111
+};
102
diff --git a/target/arm/translate.c b/target/arm/translate.c
112
+
103
index XXXXXXX..XXXXXXX 100644
113
static int nvic_post_load(void *opaque, int version_id)
104
--- a/target/arm/translate.c
114
{
105
+++ b/target/arm/translate.c
115
NVICState *s = opaque;
106
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
116
@@ -XXX,XX +XXX,XX @@ static void nvic_systick_trigger(void *opaque, int n, int level)
107
case NEON_2RM_AESE: case NEON_2RM_AESMC:
117
static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
108
case NEON_2RM_SHA1H:
118
{
109
case NEON_2RM_SHA1SU1:
119
NVICState *s = NVIC(dev);
110
+ case NEON_2RM_VREV32:
120
- int regionlen;
111
+ case NEON_2RM_VREV16:
121
112
/* handled by decodetree */
122
/* The armv7m container object will have set our CPU pointer */
113
return 1;
123
if (!s->cpu || !arm_feature(&s->cpu->env, ARM_FEATURE_M)) {
114
case NEON_2RM_VTRN:
124
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
115
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
125
M_REG_S));
116
for (pass = 0; pass < (q ? 4 : 2); pass++) {
126
}
117
tmp = neon_load_reg(rm, pass);
127
118
switch (op) {
128
- /* The NVIC and System Control Space (SCS) starts at 0xe000e000
119
- case NEON_2RM_VREV32:
129
+ /*
120
- switch (size) {
130
+ * This device provides a single sysbus memory region which
121
- case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
131
+ * represents the whole of the "System PPB" space. This is the
122
- case 1: gen_swap_half(tmp, tmp); break;
132
+ * range from 0xe0000000 to 0xe00fffff and includes the NVIC,
123
- default: abort();
133
+ * the System Control Space (system registers), the systick timer,
124
- }
134
+ * and for CPUs with the Security extension an NS banked version
125
- break;
135
+ * of all of these.
126
- case NEON_2RM_VREV16:
136
+ *
127
- gen_rev16(tmp, tmp);
137
+ * The default behaviour for unimplemented registers/ranges
128
- break;
138
+ * (for instance the Data Watchpoint and Trace unit at 0xe0001000)
129
case NEON_2RM_VCLS:
139
+ * is to RAZ/WI for privileged access and BusFault for non-privileged
130
switch (size) {
140
+ * access.
131
case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
141
+ *
142
+ * The NVIC and System Control Space (SCS) starts at 0xe000e000
143
* and looks like this:
144
* 0x004 - ICTR
145
* 0x010 - 0xff - systick
146
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
147
* generally code determining which banked register to use should
148
* use attrs.secure; code determining actual behaviour of the system
149
* should use env->v7m.secure.
150
+ *
151
+ * The container covers the whole PPB space. Within it the priority
152
+ * of overlapping regions is:
153
+ * - default region (for RAZ/WI and BusFault) : -1
154
+ * - system register regions : 0
155
+ * - systick : 1
156
+ * This is because the systick device is a small block of registers
157
+ * in the middle of the other system control registers.
158
*/
159
- regionlen = arm_feature(&s->cpu->env, ARM_FEATURE_V8) ? 0x21000 : 0x1000;
160
- memory_region_init(&s->container, OBJECT(s), "nvic", regionlen);
161
- /* The system register region goes at the bottom of the priority
162
- * stack as it covers the whole page.
163
- */
164
+ memory_region_init(&s->container, OBJECT(s), "nvic", 0x100000);
165
+ memory_region_init_io(&s->defaultmem, OBJECT(s), &ppb_default_ops, s,
166
+ "nvic-default", 0x100000);
167
+ memory_region_add_subregion_overlap(&s->container, 0, &s->defaultmem, -1);
168
memory_region_init_io(&s->sysregmem, OBJECT(s), &nvic_sysreg_ops, s,
169
"nvic_sysregs", 0x1000);
170
- memory_region_add_subregion(&s->container, 0, &s->sysregmem);
171
+ memory_region_add_subregion(&s->container, 0xe000, &s->sysregmem);
172
173
memory_region_init_io(&s->systickmem, OBJECT(s),
174
&nvic_systick_ops, s,
175
"nvic_systick", 0xe0);
176
177
- memory_region_add_subregion_overlap(&s->container, 0x10,
178
+ memory_region_add_subregion_overlap(&s->container, 0xe010,
179
&s->systickmem, 1);
180
181
if (arm_feature(&s->cpu->env, ARM_FEATURE_V8)) {
182
memory_region_init_io(&s->sysreg_ns_mem, OBJECT(s),
183
&nvic_sysreg_ns_ops, &s->sysregmem,
184
"nvic_sysregs_ns", 0x1000);
185
- memory_region_add_subregion(&s->container, 0x20000, &s->sysreg_ns_mem);
186
+ memory_region_add_subregion(&s->container, 0x2e000, &s->sysreg_ns_mem);
187
memory_region_init_io(&s->systick_ns_mem, OBJECT(s),
188
&nvic_sysreg_ns_ops, &s->systickmem,
189
"nvic_systick_ns", 0xe0);
190
- memory_region_add_subregion_overlap(&s->container, 0x20010,
191
+ memory_region_add_subregion_overlap(&s->container, 0x2e010,
192
&s->systick_ns_mem, 1);
193
}
194
132
--
195
--
133
2.20.1
196
2.20.1
134
197
135
198
diff view generated by jsdifflib
1
The NeonGenOneOpFn typedef breaks with the pattern of the other
1
In v8.1M the PXN architecture extension adds a new PXN bit to the
2
NeonGen*Fn typedefs, because it is a TCGv_i64 -> TCGv_i64 operation
2
MPU_RLAR registers, which forbids execution of code in the region
3
but it does not have '64' in its name. Rename it to NeonGenOne64OpFn,
3
from a privileged mode.
4
so that the old name is available for a TCGv_i32 -> TCGv_i32 operation
4
5
(which we will need in a subsequent commit).
5
This is another feature which is just in the generic "in v8.1M" set
6
and has no ID register field indicating its presence.
6
7
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200616170844.13318-10-peter.maydell@linaro.org
10
Message-id: 20201119215617.29887-3-peter.maydell@linaro.org
10
---
11
---
11
target/arm/translate.h | 2 +-
12
target/arm/helper.c | 7 ++++++-
12
target/arm/translate-a64.c | 4 ++--
13
1 file changed, 6 insertions(+), 1 deletion(-)
13
2 files changed, 3 insertions(+), 3 deletions(-)
14
14
15
diff --git a/target/arm/translate.h b/target/arm/translate.h
15
diff --git a/target/arm/helper.c b/target/arm/helper.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate.h
17
--- a/target/arm/helper.c
18
+++ b/target/arm/translate.h
18
+++ b/target/arm/helper.c
19
@@ -XXX,XX +XXX,XX @@ typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32);
19
@@ -XXX,XX +XXX,XX @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
20
typedef void NeonGenTwoOpWidenFn(TCGv_i64, TCGv_i32, TCGv_i32);
21
typedef void NeonGenTwoSingleOPFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
22
typedef void NeonGenTwoDoubleOPFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr);
23
-typedef void NeonGenOneOpFn(TCGv_i64, TCGv_i64);
24
+typedef void NeonGenOne64OpFn(TCGv_i64, TCGv_i64);
25
typedef void CryptoTwoOpFn(TCGv_ptr, TCGv_ptr);
26
typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
27
typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
28
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/translate-a64.c
31
+++ b/target/arm/translate-a64.c
32
@@ -XXX,XX +XXX,XX @@ static void handle_2misc_pairwise(DisasContext *s, int opcode, bool u,
33
} else {
20
} else {
34
for (pass = 0; pass < maxpass; pass++) {
21
uint32_t ap = extract32(env->pmsav8.rbar[secure][matchregion], 1, 2);
35
TCGv_i64 tcg_op = tcg_temp_new_i64();
22
uint32_t xn = extract32(env->pmsav8.rbar[secure][matchregion], 0, 1);
36
- NeonGenOneOpFn *genfn;
23
+ bool pxn = false;
37
- static NeonGenOneOpFn * const fns[2][2] = {
24
+
38
+ NeonGenOne64OpFn *genfn;
25
+ if (arm_feature(env, ARM_FEATURE_V8_1M)) {
39
+ static NeonGenOne64OpFn * const fns[2][2] = {
26
+ pxn = extract32(env->pmsav8.rlar[secure][matchregion], 4, 1);
40
{ gen_helper_neon_addlp_s8, gen_helper_neon_addlp_u8 },
27
+ }
41
{ gen_helper_neon_addlp_s16, gen_helper_neon_addlp_u16 },
28
42
};
29
if (m_is_system_region(env, address)) {
30
/* System space is always execute never */
31
@@ -XXX,XX +XXX,XX @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
32
}
33
34
*prot = simple_ap_to_rw_prot(env, mmu_idx, ap);
35
- if (*prot && !xn) {
36
+ if (*prot && !xn && !(pxn && !is_user)) {
37
*prot |= PAGE_EXEC;
38
}
39
/* We don't need to look the attribute up in the MAIR0/MAIR1
43
--
40
--
44
2.20.1
41
2.20.1
45
42
46
43
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
In arm_cpu_realizefn() we check whether the board code disabled EL3
2
via the has_el3 CPU object property, which we create if the CPU
3
starts with the ARM_FEATURE_EL3 feature bit. If it is disabled, then
4
we turn off ARM_FEATURE_EL3 and also zero out the relevant fields in
5
the ID_PFR1 and ID_AA64PFR0 registers.
2
6
3
Since commit d70c996df23f, when enabling the PMU we get:
7
This codepath was incorrectly being taken for M-profile CPUs, which
8
do not have an EL3 and don't set ARM_FEATURE_EL3, but which may have
9
the M-profile Security extension and so should have non-zero values
10
in the ID_PFR1.Security field.
4
11
5
$ qemu-system-aarch64 -cpu host,pmu=on -M virt,accel=kvm,gic-version=3
12
Restrict the handling of the feature flag to A/R-profile cores.
6
Segmentation fault (core dumped)
7
13
8
Thread 1 "qemu-system-aar" received signal SIGSEGV, Segmentation fault.
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
0x0000aaaaaae356d0 in kvm_ioctl (s=0x0, type=44547) at accel/kvm/kvm-all.c:2588
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
2588 ret = ioctl(s->fd, type, arg);
16
Message-id: 20201119215617.29887-4-peter.maydell@linaro.org
11
(gdb) bt
17
---
12
#0 0x0000aaaaaae356d0 in kvm_ioctl (s=0x0, type=44547) at accel/kvm/kvm-all.c:2588
18
target/arm/cpu.c | 2 +-
13
#1 0x0000aaaaaae31568 in kvm_check_extension (s=0x0, extension=126) at accel/kvm/kvm-all.c:916
19
1 file changed, 1 insertion(+), 1 deletion(-)
14
#2 0x0000aaaaaafce254 in kvm_arm_pmu_supported (cpu=0xaaaaac214ab0) at target/arm/kvm.c:213
15
#3 0x0000aaaaaafc0f94 in arm_set_pmu (obj=0xaaaaac214ab0, value=true, errp=0xffffffffe438) at target/arm/cpu.c:1111
16
#4 0x0000aaaaab5533ac in property_set_bool (obj=0xaaaaac214ab0, v=0xaaaaac223a80, name=0xaaaaac11a970 "pmu", opaque=0xaaaaac222730, errp=0xffffffffe438) at qom/object.c:2170
17
#5 0x0000aaaaab5512f0 in object_property_set (obj=0xaaaaac214ab0, v=0xaaaaac223a80, name=0xaaaaac11a970 "pmu", errp=0xffffffffe438) at qom/object.c:1328
18
#6 0x0000aaaaab551e10 in object_property_parse (obj=0xaaaaac214ab0, string=0xaaaaac11b4c0 "on", name=0xaaaaac11a970 "pmu", errp=0xffffffffe438) at qom/object.c:1561
19
#7 0x0000aaaaab54ee8c in object_apply_global_props (obj=0xaaaaac214ab0, props=0xaaaaac018e20, errp=0xaaaaabd6fd88 <error_fatal>) at qom/object.c:407
20
#8 0x0000aaaaab1dd5a4 in qdev_prop_set_globals (dev=0xaaaaac214ab0) at hw/core/qdev-properties.c:1218
21
#9 0x0000aaaaab1d9fac in device_post_init (obj=0xaaaaac214ab0) at hw/core/qdev.c:1050
22
...
23
#15 0x0000aaaaab54f310 in object_initialize_with_type (obj=0xaaaaac214ab0, size=52208, type=0xaaaaabe237f0) at qom/object.c:512
24
#16 0x0000aaaaab54fa24 in object_new_with_type (type=0xaaaaabe237f0) at qom/object.c:687
25
#17 0x0000aaaaab54fa80 in object_new (typename=0xaaaaabe23970 "host-arm-cpu") at qom/object.c:702
26
#18 0x0000aaaaaaf04a74 in machvirt_init (machine=0xaaaaac0a8550) at hw/arm/virt.c:1770
27
#19 0x0000aaaaab1e8720 in machine_run_board_init (machine=0xaaaaac0a8550) at hw/core/machine.c:1138
28
#20 0x0000aaaaaaf95394 in qemu_init (argc=5, argv=0xffffffffea58, envp=0xffffffffea88) at softmmu/vl.c:4348
29
#21 0x0000aaaaaada3f74 in main (argc=<optimized out>, argv=<optimized out>, envp=<optimized out>) at softmmu/main.c:48
30
20
31
This is because in frame #2, cpu->kvm_state is still NULL
32
(the vCPU is not yet realized).
33
34
KVM has a hard requirement of all cores supporting the same
35
feature set. We only need to check if the accelerator supports
36
a feature, not each vCPU individually.
37
38
Fix by removing the 'CPUState *cpu' argument from the
39
kvm_arm_<FEATURE>_supported() functions.
40
41
Fixes: d70c996df23f ('Use CPUState::kvm_state in kvm_arm_pmu_supported')
42
Reported-by: Haibo Xu <haibo.xu@linaro.org>
43
Reviewed-by: Andrew Jones <drjones@redhat.com>
44
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
45
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
46
Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
47
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
48
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
49
---
50
target/arm/kvm_arm.h | 21 +++++++++------------
51
target/arm/cpu.c | 2 +-
52
target/arm/cpu64.c | 10 +++++-----
53
target/arm/kvm.c | 4 ++--
54
target/arm/kvm64.c | 14 +++++---------
55
5 files changed, 22 insertions(+), 29 deletions(-)
56
57
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
58
index XXXXXXX..XXXXXXX 100644
59
--- a/target/arm/kvm_arm.h
60
+++ b/target/arm/kvm_arm.h
61
@@ -XXX,XX +XXX,XX @@ void kvm_arm_add_vcpu_properties(Object *obj);
62
63
/**
64
* kvm_arm_aarch32_supported:
65
- * @cs: CPUState
66
*
67
- * Returns: true if the KVM VCPU can enable AArch32 mode
68
+ * Returns: true if KVM can enable AArch32 mode
69
* and false otherwise.
70
*/
71
-bool kvm_arm_aarch32_supported(CPUState *cs);
72
+bool kvm_arm_aarch32_supported(void);
73
74
/**
75
* kvm_arm_pmu_supported:
76
- * @cs: CPUState
77
*
78
- * Returns: true if the KVM VCPU can enable its PMU
79
+ * Returns: true if KVM can enable the PMU
80
* and false otherwise.
81
*/
82
-bool kvm_arm_pmu_supported(CPUState *cs);
83
+bool kvm_arm_pmu_supported(void);
84
85
/**
86
* kvm_arm_sve_supported:
87
- * @cs: CPUState
88
*
89
- * Returns true if the KVM VCPU can enable SVE and false otherwise.
90
+ * Returns true if KVM can enable SVE and false otherwise.
91
*/
92
-bool kvm_arm_sve_supported(CPUState *cs);
93
+bool kvm_arm_sve_supported(void);
94
95
/**
96
* kvm_arm_get_max_vm_ipa_size:
97
@@ -XXX,XX +XXX,XX @@ static inline void kvm_arm_set_cpu_features_from_host(ARMCPU *cpu)
98
99
static inline void kvm_arm_add_vcpu_properties(Object *obj) {}
100
101
-static inline bool kvm_arm_aarch32_supported(CPUState *cs)
102
+static inline bool kvm_arm_aarch32_supported(void)
103
{
104
return false;
105
}
106
107
-static inline bool kvm_arm_pmu_supported(CPUState *cs)
108
+static inline bool kvm_arm_pmu_supported(void)
109
{
110
return false;
111
}
112
113
-static inline bool kvm_arm_sve_supported(CPUState *cs)
114
+static inline bool kvm_arm_sve_supported(void)
115
{
116
return false;
117
}
118
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
21
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
119
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
120
--- a/target/arm/cpu.c
23
--- a/target/arm/cpu.c
121
+++ b/target/arm/cpu.c
24
+++ b/target/arm/cpu.c
122
@@ -XXX,XX +XXX,XX @@ static void arm_set_pmu(Object *obj, bool value, Error **errp)
25
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
123
ARMCPU *cpu = ARM_CPU(obj);
124
125
if (value) {
126
- if (kvm_enabled() && !kvm_arm_pmu_supported(CPU(cpu))) {
127
+ if (kvm_enabled() && !kvm_arm_pmu_supported()) {
128
error_setg(errp, "'pmu' feature not supported by KVM on this host");
129
return;
130
}
26
}
131
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
132
index XXXXXXX..XXXXXXX 100644
133
--- a/target/arm/cpu64.c
134
+++ b/target/arm/cpu64.c
135
@@ -XXX,XX +XXX,XX @@ void arm_cpu_sve_finalize(ARMCPU *cpu, Error **errp)
136
137
/* Collect the set of vector lengths supported by KVM. */
138
bitmap_zero(kvm_supported, ARM_MAX_VQ);
139
- if (kvm_enabled() && kvm_arm_sve_supported(CPU(cpu))) {
140
+ if (kvm_enabled() && kvm_arm_sve_supported()) {
141
kvm_arm_sve_get_vls(CPU(cpu), kvm_supported);
142
} else if (kvm_enabled()) {
143
assert(!cpu_isar_feature(aa64_sve, cpu));
144
@@ -XXX,XX +XXX,XX @@ static void cpu_max_set_sve_max_vq(Object *obj, Visitor *v, const char *name,
145
return;
146
}
27
}
147
28
148
- if (kvm_enabled() && !kvm_arm_sve_supported(CPU(cpu))) {
29
- if (!cpu->has_el3) {
149
+ if (kvm_enabled() && !kvm_arm_sve_supported()) {
30
+ if (!arm_feature(env, ARM_FEATURE_M) && !cpu->has_el3) {
150
error_setg(errp, "cannot set sve-max-vq");
31
/* If the has_el3 CPU property is disabled then we need to disable the
151
error_append_hint(errp, "SVE not supported by KVM on this host\n");
32
* feature.
152
return;
33
*/
153
@@ -XXX,XX +XXX,XX @@ static void cpu_arm_set_sve_vq(Object *obj, Visitor *v, const char *name,
154
return;
155
}
156
157
- if (value && kvm_enabled() && !kvm_arm_sve_supported(CPU(cpu))) {
158
+ if (value && kvm_enabled() && !kvm_arm_sve_supported()) {
159
error_setg(errp, "cannot enable %s", name);
160
error_append_hint(errp, "SVE not supported by KVM on this host\n");
161
return;
162
@@ -XXX,XX +XXX,XX @@ static void cpu_arm_set_sve(Object *obj, Visitor *v, const char *name,
163
return;
164
}
165
166
- if (value && kvm_enabled() && !kvm_arm_sve_supported(CPU(cpu))) {
167
+ if (value && kvm_enabled() && !kvm_arm_sve_supported()) {
168
error_setg(errp, "'sve' feature not supported by KVM on this host");
169
return;
170
}
171
@@ -XXX,XX +XXX,XX @@ static void aarch64_cpu_set_aarch64(Object *obj, bool value, Error **errp)
172
* uniform execution state like do_interrupt.
173
*/
174
if (value == false) {
175
- if (!kvm_enabled() || !kvm_arm_aarch32_supported(CPU(cpu))) {
176
+ if (!kvm_enabled() || !kvm_arm_aarch32_supported()) {
177
error_setg(errp, "'aarch64' feature cannot be disabled "
178
"unless KVM is enabled and 32-bit EL1 "
179
"is supported");
180
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
181
index XXXXXXX..XXXXXXX 100644
182
--- a/target/arm/kvm.c
183
+++ b/target/arm/kvm.c
184
@@ -XXX,XX +XXX,XX @@ void kvm_arm_add_vcpu_properties(Object *obj)
185
}
186
}
187
188
-bool kvm_arm_pmu_supported(CPUState *cpu)
189
+bool kvm_arm_pmu_supported(void)
190
{
191
- return kvm_check_extension(cpu->kvm_state, KVM_CAP_ARM_PMU_V3);
192
+ return kvm_check_extension(kvm_state, KVM_CAP_ARM_PMU_V3);
193
}
194
195
int kvm_arm_get_max_vm_ipa_size(MachineState *ms)
196
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
197
index XXXXXXX..XXXXXXX 100644
198
--- a/target/arm/kvm64.c
199
+++ b/target/arm/kvm64.c
200
@@ -XXX,XX +XXX,XX @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
201
return true;
202
}
203
204
-bool kvm_arm_aarch32_supported(CPUState *cpu)
205
+bool kvm_arm_aarch32_supported(void)
206
{
207
- KVMState *s = KVM_STATE(current_accel());
208
-
209
- return kvm_check_extension(s, KVM_CAP_ARM_EL1_32BIT);
210
+ return kvm_check_extension(kvm_state, KVM_CAP_ARM_EL1_32BIT);
211
}
212
213
-bool kvm_arm_sve_supported(CPUState *cpu)
214
+bool kvm_arm_sve_supported(void)
215
{
216
- KVMState *s = KVM_STATE(current_accel());
217
-
218
- return kvm_check_extension(s, KVM_CAP_ARM_SVE);
219
+ return kvm_check_extension(kvm_state, KVM_CAP_ARM_SVE);
220
}
221
222
QEMU_BUILD_BUG_ON(KVM_ARM64_SVE_VQ_MIN != 1);
223
@@ -XXX,XX +XXX,XX @@ int kvm_arch_init_vcpu(CPUState *cs)
224
env->features &= ~(1ULL << ARM_FEATURE_PMU);
225
}
226
if (cpu_isar_feature(aa64_sve, cpu)) {
227
- assert(kvm_arm_sve_supported(cs));
228
+ assert(kvm_arm_sve_supported());
229
cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_SVE;
230
}
231
232
--
34
--
233
2.20.1
35
2.20.1
234
36
235
37
diff view generated by jsdifflib
1
Convert the Neon insns in the 2-reg-misc group which are
1
Implement the v8.1M VSCCLRM insn, which zeros floating point
2
VCVT between f32 and f16 to decodetree.
2
registers if there is an active floating point context.
3
This requires support in write_neon_element32() for the MO_32
4
element size, so add it.
5
6
Because we want to use arm_gen_condlabel(), we need to move
7
the definition of that function up in translate.c so it is
8
before the #include of translate-vfp.c.inc.
3
9
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200616170844.13318-7-peter.maydell@linaro.org
12
Message-id: 20201119215617.29887-5-peter.maydell@linaro.org
7
---
13
---
8
target/arm/neon-dp.decode | 3 ++
14
target/arm/cpu.h | 9 ++++
9
target/arm/translate-neon.inc.c | 96 +++++++++++++++++++++++++++++++++
15
target/arm/m-nocp.decode | 8 +++-
10
target/arm/translate.c | 65 ++--------------------
16
target/arm/translate.c | 21 +++++----
11
3 files changed, 102 insertions(+), 62 deletions(-)
17
target/arm/translate-vfp.c.inc | 84 ++++++++++++++++++++++++++++++++++
12
18
4 files changed, 111 insertions(+), 11 deletions(-)
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
19
14
index XXXXXXX..XXXXXXX 100644
20
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
--- a/target/arm/neon-dp.decode
21
index XXXXXXX..XXXXXXX 100644
16
+++ b/target/arm/neon-dp.decode
22
--- a/target/arm/cpu.h
17
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
23
+++ b/target/arm/cpu.h
18
VQMOVN_U 1111 001 11 . 11 .. 10 .... 0 0101 1 . 0 .... @2misc_q0
24
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id)
19
25
return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0;
20
VSHLL 1111 001 11 . 11 .. 10 .... 0 0110 0 . 0 .... @2misc_q0
26
}
21
+
27
22
+ VCVT_F16_F32 1111 001 11 . 11 .. 10 .... 0 1100 0 . 0 .... @2misc_q0
28
+static inline bool isar_feature_aa32_m_sec_state(const ARMISARegisters *id)
23
+ VCVT_F32_F16 1111 001 11 . 11 .. 10 .... 0 1110 0 . 0 .... @2misc_q0
29
+{
24
]
30
+ /*
25
31
+ * Return true if M-profile state handling insns
26
# Subgroup for size != 0b11
32
+ * (VSCCLRM, CLRM, FPCTX access insns) are implemented
27
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
33
+ */
28
index XXXXXXX..XXXXXXX 100644
34
+ return FIELD_EX32(id->id_pfr1, ID_PFR1, SECURITY) >= 3;
29
--- a/target/arm/translate-neon.inc.c
35
+}
30
+++ b/target/arm/translate-neon.inc.c
36
+
31
@@ -XXX,XX +XXX,XX @@ static bool trans_VSHLL(DisasContext *s, arg_2misc *a)
37
static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
32
tcg_temp_free_i32(rm1);
38
{
39
/* Sadly this is encoded differently for A-profile and M-profile */
40
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/m-nocp.decode
43
+++ b/target/arm/m-nocp.decode
44
@@ -XXX,XX +XXX,XX @@
45
# If the coprocessor is not present or disabled then we will generate
46
# the NOCP exception; otherwise we let the insn through to the main decode.
47
48
+%vd_dp 22:1 12:4
49
+%vd_sp 12:4 22:1
50
+
51
&nocp cp
52
53
{
54
# Special cases which do not take an early NOCP: VLLDM and VLSTM
55
VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
56
- # TODO: VSCCLRM (new in v8.1M) is similar:
57
- #VSCCLRM 1110 1100 1-01 1111 ---- 1011 ---- ---0
58
+ # VSCCLRM (new in v8.1M) is similar:
59
+ VSCCLRM 1110 1100 1.01 1111 .... 1011 imm:7 0 vd=%vd_dp size=3
60
+ VSCCLRM 1110 1100 1.01 1111 .... 1010 imm:8 vd=%vd_sp size=2
61
62
NOCP 111- 1110 ---- ---- ---- cp:4 ---- ---- &nocp
63
NOCP 111- 110- ---- ---- ---- cp:4 ---- ---- &nocp
64
diff --git a/target/arm/translate.c b/target/arm/translate.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/translate.c
67
+++ b/target/arm/translate.c
68
@@ -XXX,XX +XXX,XX @@ void arm_translate_init(void)
69
a64_translate_init();
70
}
71
72
+/* Generate a label used for skipping this instruction */
73
+static void arm_gen_condlabel(DisasContext *s)
74
+{
75
+ if (!s->condjmp) {
76
+ s->condlabel = gen_new_label();
77
+ s->condjmp = 1;
78
+ }
79
+}
80
+
81
/* Flags for the disas_set_da_iss info argument:
82
* lower bits hold the Rt register number, higher bits are flags.
83
*/
84
@@ -XXX,XX +XXX,XX @@ static void write_neon_element64(TCGv_i64 src, int reg, int ele, MemOp memop)
85
long off = neon_element_offset(reg, ele, memop);
86
87
switch (memop) {
88
+ case MO_32:
89
+ tcg_gen_st32_i64(src, cpu_env, off);
90
+ break;
91
case MO_64:
92
tcg_gen_st_i64(src, cpu_env, off);
93
break;
94
@@ -XXX,XX +XXX,XX @@ static void gen_srs(DisasContext *s,
95
s->base.is_jmp = DISAS_UPDATE_EXIT;
96
}
97
98
-/* Generate a label used for skipping this instruction */
99
-static void arm_gen_condlabel(DisasContext *s)
100
-{
101
- if (!s->condjmp) {
102
- s->condlabel = gen_new_label();
103
- s->condjmp = 1;
104
- }
105
-}
106
-
107
/* Skip this instruction if the ARM condition is false */
108
static void arm_skip_unless(DisasContext *s, uint32_t cond)
109
{
110
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
111
index XXXXXXX..XXXXXXX 100644
112
--- a/target/arm/translate-vfp.c.inc
113
+++ b/target/arm/translate-vfp.c.inc
114
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
33
return true;
115
return true;
34
}
116
}
35
+
117
36
+static bool trans_VCVT_F16_F32(DisasContext *s, arg_2misc *a)
118
+static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
37
+{
119
+{
38
+ TCGv_ptr fpst;
120
+ int btmreg, topreg;
39
+ TCGv_i32 ahp, tmp, tmp2, tmp3;
121
+ TCGv_i64 zero;
40
+
122
+ TCGv_i32 aspen, sfpa;
41
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
123
+
42
+ !dc_isar_feature(aa32_fp16_spconv, s)) {
124
+ if (!dc_isar_feature(aa32_m_sec_state, s)) {
125
+ /* Before v8.1M, fall through in decode to NOCP check */
43
+ return false;
126
+ return false;
44
+ }
127
+ }
45
+
128
+
46
+ /* UNDEF accesses to D16-D31 if they don't exist. */
129
+ /* Explicitly UNDEF because this takes precedence over NOCP */
47
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
130
+ if (!arm_dc_feature(s, ARM_FEATURE_M_MAIN) || !s->v8m_secure) {
48
+ ((a->vd | a->vm) & 0x10)) {
131
+ unallocated_encoding(s);
49
+ return false;
132
+ return true;
50
+ }
133
+ }
51
+
134
+
52
+ if ((a->vm & 1) || (a->size != 1)) {
135
+ if (!dc_isar_feature(aa32_vfp_simd, s)) {
53
+ return false;
136
+ /* NOP if we have neither FP nor MVE */
137
+ return true;
138
+ }
139
+
140
+ /*
141
+ * If FPCCR.ASPEN != 0 && CONTROL_S.SFPA == 0 then there is no
142
+ * active floating point context so we must NOP (without doing
143
+ * any lazy state preservation or the NOCP check).
144
+ */
145
+ aspen = load_cpu_field(v7m.fpccr[M_REG_S]);
146
+ sfpa = load_cpu_field(v7m.control[M_REG_S]);
147
+ tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
148
+ tcg_gen_xori_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
149
+ tcg_gen_andi_i32(sfpa, sfpa, R_V7M_CONTROL_SFPA_MASK);
150
+ tcg_gen_or_i32(sfpa, sfpa, aspen);
151
+ arm_gen_condlabel(s);
152
+ tcg_gen_brcondi_i32(TCG_COND_EQ, sfpa, 0, s->condlabel);
153
+
154
+ if (s->fp_excp_el != 0) {
155
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
156
+ syn_uncategorized(), s->fp_excp_el);
157
+ return true;
158
+ }
159
+
160
+ topreg = a->vd + a->imm - 1;
161
+ btmreg = a->vd;
162
+
163
+ /* Convert to Sreg numbers if the insn specified in Dregs */
164
+ if (a->size == 3) {
165
+ topreg = topreg * 2 + 1;
166
+ btmreg *= 2;
167
+ }
168
+
169
+ if (topreg > 63 || (topreg > 31 && !(topreg & 1))) {
170
+ /* UNPREDICTABLE: we choose to undef */
171
+ unallocated_encoding(s);
172
+ return true;
173
+ }
174
+
175
+ /* Silently ignore requests to clear D16-D31 if they don't exist */
176
+ if (topreg > 31 && !dc_isar_feature(aa32_simd_r32, s)) {
177
+ topreg = 31;
54
+ }
178
+ }
55
+
179
+
56
+ if (!vfp_access_check(s)) {
180
+ if (!vfp_access_check(s)) {
57
+ return true;
181
+ return true;
58
+ }
182
+ }
59
+
183
+
60
+ fpst = get_fpstatus_ptr(true);
184
+ /* Zero the Sregs from btmreg to topreg inclusive. */
61
+ ahp = get_ahp_flag();
185
+ zero = tcg_const_i64(0);
62
+ tmp = neon_load_reg(a->vm, 0);
186
+ if (btmreg & 1) {
63
+ gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp);
187
+ write_neon_element64(zero, btmreg >> 1, 1, MO_32);
64
+ tmp2 = neon_load_reg(a->vm, 1);
188
+ btmreg++;
65
+ gen_helper_vfp_fcvt_f32_to_f16(tmp2, tmp2, fpst, ahp);
189
+ }
66
+ tcg_gen_shli_i32(tmp2, tmp2, 16);
190
+ for (; btmreg + 1 <= topreg; btmreg += 2) {
67
+ tcg_gen_or_i32(tmp2, tmp2, tmp);
191
+ write_neon_element64(zero, btmreg >> 1, 0, MO_64);
68
+ tcg_temp_free_i32(tmp);
192
+ }
69
+ tmp = neon_load_reg(a->vm, 2);
193
+ if (btmreg == topreg) {
70
+ gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp);
194
+ write_neon_element64(zero, btmreg >> 1, 0, MO_32);
71
+ tmp3 = neon_load_reg(a->vm, 3);
195
+ btmreg++;
72
+ neon_store_reg(a->vd, 0, tmp2);
196
+ }
73
+ gen_helper_vfp_fcvt_f32_to_f16(tmp3, tmp3, fpst, ahp);
197
+ assert(btmreg == topreg + 1);
74
+ tcg_gen_shli_i32(tmp3, tmp3, 16);
198
+ /* TODO: when MVE is implemented, zero VPR here */
75
+ tcg_gen_or_i32(tmp3, tmp3, tmp);
76
+ neon_store_reg(a->vd, 1, tmp3);
77
+ tcg_temp_free_i32(tmp);
78
+ tcg_temp_free_i32(ahp);
79
+ tcg_temp_free_ptr(fpst);
80
+
81
+ return true;
199
+ return true;
82
+}
200
+}
83
+
201
+
84
+static bool trans_VCVT_F32_F16(DisasContext *s, arg_2misc *a)
202
static bool trans_NOCP(DisasContext *s, arg_nocp *a)
85
+{
203
{
86
+ TCGv_ptr fpst;
204
/*
87
+ TCGv_i32 ahp, tmp, tmp2, tmp3;
88
+
89
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
90
+ !dc_isar_feature(aa32_fp16_spconv, s)) {
91
+ return false;
92
+ }
93
+
94
+ /* UNDEF accesses to D16-D31 if they don't exist. */
95
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
96
+ ((a->vd | a->vm) & 0x10)) {
97
+ return false;
98
+ }
99
+
100
+ if ((a->vd & 1) || (a->size != 1)) {
101
+ return false;
102
+ }
103
+
104
+ if (!vfp_access_check(s)) {
105
+ return true;
106
+ }
107
+
108
+ fpst = get_fpstatus_ptr(true);
109
+ ahp = get_ahp_flag();
110
+ tmp3 = tcg_temp_new_i32();
111
+ tmp = neon_load_reg(a->vm, 0);
112
+ tmp2 = neon_load_reg(a->vm, 1);
113
+ tcg_gen_ext16u_i32(tmp3, tmp);
114
+ gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp);
115
+ neon_store_reg(a->vd, 0, tmp3);
116
+ tcg_gen_shri_i32(tmp, tmp, 16);
117
+ gen_helper_vfp_fcvt_f16_to_f32(tmp, tmp, fpst, ahp);
118
+ neon_store_reg(a->vd, 1, tmp);
119
+ tmp3 = tcg_temp_new_i32();
120
+ tcg_gen_ext16u_i32(tmp3, tmp2);
121
+ gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp);
122
+ neon_store_reg(a->vd, 2, tmp3);
123
+ tcg_gen_shri_i32(tmp2, tmp2, 16);
124
+ gen_helper_vfp_fcvt_f16_to_f32(tmp2, tmp2, fpst, ahp);
125
+ neon_store_reg(a->vd, 3, tmp2);
126
+ tcg_temp_free_i32(ahp);
127
+ tcg_temp_free_ptr(fpst);
128
+
129
+ return true;
130
+}
131
diff --git a/target/arm/translate.c b/target/arm/translate.c
132
index XXXXXXX..XXXXXXX 100644
133
--- a/target/arm/translate.c
134
+++ b/target/arm/translate.c
135
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
136
int pass;
137
int u;
138
int vec_size;
139
- TCGv_i32 tmp, tmp2, tmp3;
140
+ TCGv_i32 tmp, tmp2;
141
142
if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
143
return 1;
144
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
145
case NEON_2RM_VZIP:
146
case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
147
case NEON_2RM_VSHLL:
148
+ case NEON_2RM_VCVT_F16_F32:
149
+ case NEON_2RM_VCVT_F32_F16:
150
/* handled by decodetree */
151
return 1;
152
case NEON_2RM_VTRN:
153
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
154
goto elementwise;
155
}
156
break;
157
- case NEON_2RM_VCVT_F16_F32:
158
- {
159
- TCGv_ptr fpst;
160
- TCGv_i32 ahp;
161
-
162
- if (!dc_isar_feature(aa32_fp16_spconv, s) ||
163
- q || (rm & 1)) {
164
- return 1;
165
- }
166
- fpst = get_fpstatus_ptr(true);
167
- ahp = get_ahp_flag();
168
- tmp = neon_load_reg(rm, 0);
169
- gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp);
170
- tmp2 = neon_load_reg(rm, 1);
171
- gen_helper_vfp_fcvt_f32_to_f16(tmp2, tmp2, fpst, ahp);
172
- tcg_gen_shli_i32(tmp2, tmp2, 16);
173
- tcg_gen_or_i32(tmp2, tmp2, tmp);
174
- tcg_temp_free_i32(tmp);
175
- tmp = neon_load_reg(rm, 2);
176
- gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp);
177
- tmp3 = neon_load_reg(rm, 3);
178
- neon_store_reg(rd, 0, tmp2);
179
- gen_helper_vfp_fcvt_f32_to_f16(tmp3, tmp3, fpst, ahp);
180
- tcg_gen_shli_i32(tmp3, tmp3, 16);
181
- tcg_gen_or_i32(tmp3, tmp3, tmp);
182
- neon_store_reg(rd, 1, tmp3);
183
- tcg_temp_free_i32(tmp);
184
- tcg_temp_free_i32(ahp);
185
- tcg_temp_free_ptr(fpst);
186
- break;
187
- }
188
- case NEON_2RM_VCVT_F32_F16:
189
- {
190
- TCGv_ptr fpst;
191
- TCGv_i32 ahp;
192
- if (!dc_isar_feature(aa32_fp16_spconv, s) ||
193
- q || (rd & 1)) {
194
- return 1;
195
- }
196
- fpst = get_fpstatus_ptr(true);
197
- ahp = get_ahp_flag();
198
- tmp3 = tcg_temp_new_i32();
199
- tmp = neon_load_reg(rm, 0);
200
- tmp2 = neon_load_reg(rm, 1);
201
- tcg_gen_ext16u_i32(tmp3, tmp);
202
- gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp);
203
- neon_store_reg(rd, 0, tmp3);
204
- tcg_gen_shri_i32(tmp, tmp, 16);
205
- gen_helper_vfp_fcvt_f16_to_f32(tmp, tmp, fpst, ahp);
206
- neon_store_reg(rd, 1, tmp);
207
- tmp3 = tcg_temp_new_i32();
208
- tcg_gen_ext16u_i32(tmp3, tmp2);
209
- gen_helper_vfp_fcvt_f16_to_f32(tmp3, tmp3, fpst, ahp);
210
- neon_store_reg(rd, 2, tmp3);
211
- tcg_gen_shri_i32(tmp2, tmp2, 16);
212
- gen_helper_vfp_fcvt_f16_to_f32(tmp2, tmp2, fpst, ahp);
213
- neon_store_reg(rd, 3, tmp2);
214
- tcg_temp_free_i32(ahp);
215
- tcg_temp_free_ptr(fpst);
216
- break;
217
- }
218
case NEON_2RM_AESE: case NEON_2RM_AESMC:
219
if (!dc_isar_feature(aa32_aes, s) || ((rm | rd) & 1)) {
220
return 1;
221
--
205
--
222
2.20.1
206
2.20.1
223
207
224
208
diff view generated by jsdifflib
1
Make gen_swap_half() take a source and destination TCGv_i32 rather
1
In v8.1M the new CLRM instruction allows zeroing an arbitrary set of
2
than modifying the input TCGv_i32; we're going to want to be able to
2
the general-purpose registers and APSR. Implement this.
3
use it with the more flexible function signature, and this also
3
4
brings it into line with other functions like gen_rev16() and
4
The encoding is a subset of the LDMIA T2 encoding, using what would
5
gen_revsh().
5
be Rn=0b1111 (which UNDEFs for LDMIA).
6
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200616170844.13318-12-peter.maydell@linaro.org
9
Message-id: 20201119215617.29887-6-peter.maydell@linaro.org
10
---
10
---
11
target/arm/translate-neon.inc.c | 2 +-
11
target/arm/t32.decode | 6 +++++-
12
target/arm/translate.c | 10 +++++-----
12
target/arm/translate.c | 38 ++++++++++++++++++++++++++++++++++++++
13
2 files changed, 6 insertions(+), 6 deletions(-)
13
2 files changed, 43 insertions(+), 1 deletion(-)
14
14
15
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
15
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-neon.inc.c
17
--- a/target/arm/t32.decode
18
+++ b/target/arm/translate-neon.inc.c
18
+++ b/target/arm/t32.decode
19
@@ -XXX,XX +XXX,XX @@ static bool trans_VREV64(DisasContext *s, arg_VREV64 *a)
19
@@ -XXX,XX +XXX,XX @@ UXTAB 1111 1010 0101 .... 1111 .... 10.. .... @rrr_rot
20
tcg_gen_bswap32_i32(tmp[half], tmp[half]);
20
21
break;
21
STM_t32 1110 1000 10.0 .... ................ @ldstm i=1 b=0
22
case 1:
22
STM_t32 1110 1001 00.0 .... ................ @ldstm i=0 b=1
23
- gen_swap_half(tmp[half]);
23
-LDM_t32 1110 1000 10.1 .... ................ @ldstm i=1 b=0
24
+ gen_swap_half(tmp[half], tmp[half]);
24
+{
25
break;
25
+ # Rn=15 UNDEFs for LDM; M-profile CLRM uses that encoding
26
case 2:
26
+ CLRM 1110 1000 1001 1111 list:16
27
break;
27
+ LDM_t32 1110 1000 10.1 .... ................ @ldstm i=1 b=0
28
+}
29
LDM_t32 1110 1001 00.1 .... ................ @ldstm i=0 b=1
30
31
&rfe !extern rn w pu
28
diff --git a/target/arm/translate.c b/target/arm/translate.c
32
diff --git a/target/arm/translate.c b/target/arm/translate.c
29
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/translate.c
34
--- a/target/arm/translate.c
31
+++ b/target/arm/translate.c
35
+++ b/target/arm/translate.c
32
@@ -XXX,XX +XXX,XX @@ static void gen_revsh(TCGv_i32 dest, TCGv_i32 var)
36
@@ -XXX,XX +XXX,XX @@ static bool trans_LDM_t16(DisasContext *s, arg_ldst_block *a)
37
return do_ldm(s, a, 1);
33
}
38
}
34
39
35
/* Swap low and high halfwords. */
40
+static bool trans_CLRM(DisasContext *s, arg_CLRM *a)
36
-static void gen_swap_half(TCGv_i32 var)
41
+{
37
+static void gen_swap_half(TCGv_i32 dest, TCGv_i32 var)
42
+ int i;
38
{
43
+ TCGv_i32 zero;
39
- tcg_gen_rotri_i32(var, var, 16);
44
+
40
+ tcg_gen_rotri_i32(dest, var, 16);
45
+ if (!dc_isar_feature(aa32_m_sec_state, s)) {
41
}
46
+ return false;
42
47
+ }
43
/* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
48
+
44
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
49
+ if (extract32(a->list, 13, 1)) {
45
case NEON_2RM_VREV32:
50
+ return false;
46
switch (size) {
51
+ }
47
case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
52
+
48
- case 1: gen_swap_half(tmp); break;
53
+ if (!a->list) {
49
+ case 1: gen_swap_half(tmp, tmp); break;
54
+ /* UNPREDICTABLE; we choose to UNDEF */
50
default: abort();
55
+ return false;
51
}
56
+ }
52
break;
57
+
53
@@ -XXX,XX +XXX,XX @@ static bool op_smlad(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
58
+ zero = tcg_const_i32(0);
54
t1 = load_reg(s, a->rn);
59
+ for (i = 0; i < 15; i++) {
55
t2 = load_reg(s, a->rm);
60
+ if (extract32(a->list, i, 1)) {
56
if (m_swap) {
61
+ /* Clear R[i] */
57
- gen_swap_half(t2);
62
+ tcg_gen_mov_i32(cpu_R[i], zero);
58
+ gen_swap_half(t2, t2);
63
+ }
59
}
64
+ }
60
gen_smul_dual(t1, t2);
65
+ if (extract32(a->list, 15, 1)) {
61
66
+ /*
62
@@ -XXX,XX +XXX,XX @@ static bool op_smlald(DisasContext *s, arg_rrrr *a, bool m_swap, bool sub)
67
+ * Clear APSR (by calling the MSR helper with the same argument
63
t1 = load_reg(s, a->rn);
68
+ * as for "MSR APSR_nzcvqg, Rn": mask = 0b1100, SYSM=0)
64
t2 = load_reg(s, a->rm);
69
+ */
65
if (m_swap) {
70
+ TCGv_i32 maskreg = tcg_const_i32(0xc << 8);
66
- gen_swap_half(t2);
71
+ gen_helper_v7m_msr(cpu_env, maskreg, zero);
67
+ gen_swap_half(t2, t2);
72
+ tcg_temp_free_i32(maskreg);
68
}
73
+ }
69
gen_smul_dual(t1, t2);
74
+ tcg_temp_free_i32(zero);
70
75
+ return true;
76
+}
77
+
78
/*
79
* Branch, branch with link
80
*/
71
--
81
--
72
2.20.1
82
2.20.1
73
83
74
84
diff view generated by jsdifflib
1
Convert the Neon VSWP insn to decodetree. Since the new implementation
1
For M-profile before v8.1M, the only valid register for VMSR/VMRS is
2
doesn't have to share a pass-loop with the other 2-reg-misc operations
2
the FPSCR. We have a comment that states this, but the actual logic
3
we can implement the swap with 64-bit accesses rather than 32-bits
3
to forbid accesses for any other register value is missing, so we
4
(which brings us into line with the pseudocode and is more efficient).
4
would end up with A-profile style behaviour. Add the missing check.
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: 20200616170844.13318-20-peter.maydell@linaro.org
8
Message-id: 20201119215617.29887-7-peter.maydell@linaro.org
9
---
9
---
10
target/arm/neon-dp.decode | 2 ++
10
target/arm/translate-vfp.c.inc | 5 ++++-
11
target/arm/translate-neon.inc.c | 41 +++++++++++++++++++++++++++++++++
11
1 file changed, 4 insertions(+), 1 deletion(-)
12
target/arm/translate.c | 5 +---
13
3 files changed, 44 insertions(+), 4 deletions(-)
14
12
15
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/neon-dp.decode
15
--- a/target/arm/translate-vfp.c.inc
18
+++ b/target/arm/neon-dp.decode
16
+++ b/target/arm/translate-vfp.c.inc
19
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
17
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
20
VABS_F 1111 001 11 . 11 .. 01 .... 0 1110 . . 0 .... @2misc
18
* Accesses to R15 are UNPREDICTABLE; we choose to undef.
21
VNEG_F 1111 001 11 . 11 .. 01 .... 0 1111 . . 0 .... @2misc
19
* (FPSCR -> r15 is a special case which writes to the PSR flags.)
22
20
*/
23
+ VSWP 1111 001 11 . 11 .. 10 .... 0 0000 . . 0 .... @2misc
21
- if (a->rt == 15 && (!a->l || a->reg != ARM_VFP_FPSCR)) {
24
+
22
+ if (a->reg != ARM_VFP_FPSCR) {
25
VUZP 1111 001 11 . 11 .. 10 .... 0 0010 . . 0 .... @2misc
23
+ return false;
26
VZIP 1111 001 11 . 11 .. 10 .... 0 0011 . . 0 .... @2misc
24
+ }
27
25
+ if (a->rt == 15 && !a->l) {
28
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
26
return false;
29
index XXXXXXX..XXXXXXX 100644
27
}
30
--- a/target/arm/translate-neon.inc.c
28
}
31
+++ b/target/arm/translate-neon.inc.c
32
@@ -XXX,XX +XXX,XX @@ DO_VCVT(VCVTPU, FPROUNDING_POSINF, false)
33
DO_VCVT(VCVTPS, FPROUNDING_POSINF, true)
34
DO_VCVT(VCVTMU, FPROUNDING_NEGINF, false)
35
DO_VCVT(VCVTMS, FPROUNDING_NEGINF, true)
36
+
37
+static bool trans_VSWP(DisasContext *s, arg_2misc *a)
38
+{
39
+ TCGv_i64 rm, rd;
40
+ int pass;
41
+
42
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
43
+ return false;
44
+ }
45
+
46
+ /* UNDEF accesses to D16-D31 if they don't exist. */
47
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
48
+ ((a->vd | a->vm) & 0x10)) {
49
+ return false;
50
+ }
51
+
52
+ if (a->size != 0) {
53
+ return false;
54
+ }
55
+
56
+ if ((a->vd | a->vm) & a->q) {
57
+ return false;
58
+ }
59
+
60
+ if (!vfp_access_check(s)) {
61
+ return true;
62
+ }
63
+
64
+ rm = tcg_temp_new_i64();
65
+ rd = tcg_temp_new_i64();
66
+ for (pass = 0; pass < (a->q ? 2 : 1); pass++) {
67
+ neon_load_reg64(rm, a->vm + pass);
68
+ neon_load_reg64(rd, a->vd + pass);
69
+ neon_store_reg64(rm, a->vd + pass);
70
+ neon_store_reg64(rd, a->vm + pass);
71
+ }
72
+ tcg_temp_free_i64(rm);
73
+ tcg_temp_free_i64(rd);
74
+
75
+ return true;
76
+}
77
diff --git a/target/arm/translate.c b/target/arm/translate.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/target/arm/translate.c
80
+++ b/target/arm/translate.c
81
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
82
case NEON_2RM_VCVTPS:
83
case NEON_2RM_VCVTMU:
84
case NEON_2RM_VCVTMS:
85
+ case NEON_2RM_VSWP:
86
/* handled by decodetree */
87
return 1;
88
case NEON_2RM_VTRN:
89
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
90
for (pass = 0; pass < (q ? 4 : 2); pass++) {
91
tmp = neon_load_reg(rm, pass);
92
switch (op) {
93
- case NEON_2RM_VSWP:
94
- tmp2 = neon_load_reg(rd, pass);
95
- neon_store_reg(rm, pass, tmp2);
96
- break;
97
case NEON_2RM_VTRN:
98
tmp2 = neon_load_reg(rd, pass);
99
switch (size) {
100
--
29
--
101
2.20.1
30
2.20.1
102
31
103
32
diff view generated by jsdifflib
1
The functions neon_element_offset(), neon_load_element(),
1
Currently M-profile borrows the A-profile code for VMSR and VMRS
2
neon_load_element64(), neon_store_element() and
2
(access to the FP system registers), because all it needs to support
3
neon_store_element64() are used only in the translate-neon.inc.c
3
is the FPSCR. In v8.1M things become significantly more complicated
4
file, so move their definitions there.
4
in two ways:
5
5
6
Since the .inc.c file is #included in translate.c this doesn't make
6
* there are several new FP system registers; some have side effects
7
much difference currently, but it's a more logical place to put the
7
on read, and one (FPCXT_NS) needs to avoid the usual
8
functions and it might be helpful if we ever decide to try to make
8
vfp_access_check() and the "only if FPU implemented" check
9
the .inc.c files genuinely separate compilation units.
9
10
* all sysregs are now accessible both by VMRS/VMSR (which
11
reads/writes a general purpose register) and also by VLDR/VSTR
12
(which reads/writes them directly to memory)
13
14
Refactor the structure of how we handle VMSR/VMRS to cope with this:
15
16
* keep the M-profile code entirely separate from the A-profile code
17
18
* abstract out the "read or write the general purpose register" part
19
of the code into a loadfn or storefn function pointer, so we can
20
reuse it for VLDR/VSTR.
10
21
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20200616170844.13318-22-peter.maydell@linaro.org
24
Message-id: 20201119215617.29887-8-peter.maydell@linaro.org
14
---
25
---
15
target/arm/translate-neon.inc.c | 101 ++++++++++++++++++++++++++++++++
26
target/arm/cpu.h | 3 +
16
target/arm/translate.c | 101 --------------------------------
27
target/arm/translate-vfp.c.inc | 182 ++++++++++++++++++++++++++++++---
17
2 files changed, 101 insertions(+), 101 deletions(-)
28
2 files changed, 171 insertions(+), 14 deletions(-)
18
29
19
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
30
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
index XXXXXXX..XXXXXXX 100644
31
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/translate-neon.inc.c
32
--- a/target/arm/cpu.h
22
+++ b/target/arm/translate-neon.inc.c
33
+++ b/target/arm/cpu.h
23
@@ -XXX,XX +XXX,XX @@ static inline int rsub_8(DisasContext *s, int x)
34
@@ -XXX,XX +XXX,XX @@ enum arm_cpu_mode {
24
#include "decode-neon-ls.inc.c"
35
#define ARM_VFP_FPINST 9
25
#include "decode-neon-shared.inc.c"
36
#define ARM_VFP_FPINST2 10
26
37
27
+/* Return the offset of a 2**SIZE piece of a NEON register, at index ELE,
38
+/* QEMU-internal value meaning "FPSCR, but we care only about NZCV" */
28
+ * where 0 is the least significant end of the register.
39
+#define QEMU_VFP_FPSCR_NZCV 0xffff
40
+
41
/* iwMMXt coprocessor control registers. */
42
#define ARM_IWMMXT_wCID 0
43
#define ARM_IWMMXT_wCon 1
44
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/arm/translate-vfp.c.inc
47
+++ b/target/arm/translate-vfp.c.inc
48
@@ -XXX,XX +XXX,XX @@ static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
49
return true;
50
}
51
52
+/*
53
+ * M-profile provides two different sets of instructions that can
54
+ * access floating point system registers: VMSR/VMRS (which move
55
+ * to/from a general purpose register) and VLDR/VSTR sysreg (which
56
+ * move directly to/from memory). In some cases there are also side
57
+ * effects which must happen after any write to memory (which could
58
+ * cause an exception). So we implement the common logic for the
59
+ * sysreg access in gen_M_fp_sysreg_write() and gen_M_fp_sysreg_read(),
60
+ * which take pointers to callback functions which will perform the
61
+ * actual "read/write general purpose register" and "read/write
62
+ * memory" operations.
29
+ */
63
+ */
30
+static inline long
64
+
31
+neon_element_offset(int reg, int element, MemOp size)
65
+/*
32
+{
66
+ * Emit code to store the sysreg to its final destination; frees the
33
+ int element_size = 1 << size;
67
+ * TCG temp 'value' it is passed.
34
+ int ofs = element * element_size;
68
+ */
35
+#ifdef HOST_WORDS_BIGENDIAN
69
+typedef void fp_sysreg_storefn(DisasContext *s, void *opaque, TCGv_i32 value);
36
+ /* Calculate the offset assuming fully little-endian,
70
+/*
37
+ * then XOR to account for the order of the 8-byte units.
71
+ * Emit code to load the value to be copied to the sysreg; returns
38
+ */
72
+ * a new TCG temporary
39
+ if (element_size < 8) {
73
+ */
40
+ ofs ^= 8 - element_size;
74
+typedef TCGv_i32 fp_sysreg_loadfn(DisasContext *s, void *opaque);
41
+ }
75
+
42
+#endif
76
+/* Common decode/access checks for fp sysreg read/write */
43
+ return neon_reg_offset(reg, 0) + ofs;
77
+typedef enum FPSysRegCheckResult {
44
+}
78
+ FPSysRegCheckFailed, /* caller should return false */
45
+
79
+ FPSysRegCheckDone, /* caller should return true */
46
+static void neon_load_element(TCGv_i32 var, int reg, int ele, MemOp mop)
80
+ FPSysRegCheckContinue, /* caller should continue generating code */
47
+{
81
+} FPSysRegCheckResult;
48
+ long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
82
+
49
+
83
+static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
50
+ switch (mop) {
84
+{
51
+ case MO_UB:
85
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
52
+ tcg_gen_ld8u_i32(var, cpu_env, offset);
86
+ return FPSysRegCheckFailed;
53
+ break;
87
+ }
54
+ case MO_UW:
88
+
55
+ tcg_gen_ld16u_i32(var, cpu_env, offset);
89
+ switch (regno) {
56
+ break;
90
+ case ARM_VFP_FPSCR:
57
+ case MO_UL:
91
+ case QEMU_VFP_FPSCR_NZCV:
58
+ tcg_gen_ld_i32(var, cpu_env, offset);
92
+ break;
93
+ default:
94
+ return FPSysRegCheckFailed;
95
+ }
96
+
97
+ if (!vfp_access_check(s)) {
98
+ return FPSysRegCheckDone;
99
+ }
100
+
101
+ return FPSysRegCheckContinue;
102
+}
103
+
104
+static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
105
+
106
+ fp_sysreg_loadfn *loadfn,
107
+ void *opaque)
108
+{
109
+ /* Do a write to an M-profile floating point system register */
110
+ TCGv_i32 tmp;
111
+
112
+ switch (fp_sysreg_checks(s, regno)) {
113
+ case FPSysRegCheckFailed:
114
+ return false;
115
+ case FPSysRegCheckDone:
116
+ return true;
117
+ case FPSysRegCheckContinue:
118
+ break;
119
+ }
120
+
121
+ switch (regno) {
122
+ case ARM_VFP_FPSCR:
123
+ tmp = loadfn(s, opaque);
124
+ gen_helper_vfp_set_fpscr(cpu_env, tmp);
125
+ tcg_temp_free_i32(tmp);
126
+ gen_lookup_tb(s);
59
+ break;
127
+ break;
60
+ default:
128
+ default:
61
+ g_assert_not_reached();
129
+ g_assert_not_reached();
62
+ }
130
+ }
63
+}
131
+ return true;
64
+
132
+}
65
+static void neon_load_element64(TCGv_i64 var, int reg, int ele, MemOp mop)
133
+
66
+{
134
+static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
67
+ long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
135
+ fp_sysreg_storefn *storefn,
68
+
136
+ void *opaque)
69
+ switch (mop) {
137
+{
70
+ case MO_UB:
138
+ /* Do a read from an M-profile floating point system register */
71
+ tcg_gen_ld8u_i64(var, cpu_env, offset);
139
+ TCGv_i32 tmp;
72
+ break;
140
+
73
+ case MO_UW:
141
+ switch (fp_sysreg_checks(s, regno)) {
74
+ tcg_gen_ld16u_i64(var, cpu_env, offset);
142
+ case FPSysRegCheckFailed:
75
+ break;
143
+ return false;
76
+ case MO_UL:
144
+ case FPSysRegCheckDone:
77
+ tcg_gen_ld32u_i64(var, cpu_env, offset);
145
+ return true;
78
+ break;
146
+ case FPSysRegCheckContinue:
79
+ case MO_Q:
147
+ break;
80
+ tcg_gen_ld_i64(var, cpu_env, offset);
148
+ }
149
+
150
+ switch (regno) {
151
+ case ARM_VFP_FPSCR:
152
+ tmp = tcg_temp_new_i32();
153
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
154
+ storefn(s, opaque, tmp);
155
+ break;
156
+ case QEMU_VFP_FPSCR_NZCV:
157
+ /*
158
+ * Read just NZCV; this is a special case to avoid the
159
+ * helper call for the "VMRS to CPSR.NZCV" insn.
160
+ */
161
+ tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
162
+ tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
163
+ storefn(s, opaque, tmp);
81
+ break;
164
+ break;
82
+ default:
165
+ default:
83
+ g_assert_not_reached();
166
+ g_assert_not_reached();
84
+ }
167
+ }
85
+}
168
+ return true;
86
+
169
+}
87
+static void neon_store_element(int reg, int ele, MemOp size, TCGv_i32 var)
170
+
88
+{
171
+static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value)
89
+ long offset = neon_element_offset(reg, ele, size);
172
+{
90
+
173
+ arg_VMSR_VMRS *a = opaque;
91
+ switch (size) {
174
+
92
+ case MO_8:
175
+ if (a->rt == 15) {
93
+ tcg_gen_st8_i32(var, cpu_env, offset);
176
+ /* Set the 4 flag bits in the CPSR */
94
+ break;
177
+ gen_set_nzcv(value);
95
+ case MO_16:
178
+ tcg_temp_free_i32(value);
96
+ tcg_gen_st16_i32(var, cpu_env, offset);
179
+ } else {
97
+ break;
180
+ store_reg(s, a->rt, value);
98
+ case MO_32:
181
+ }
99
+ tcg_gen_st_i32(var, cpu_env, offset);
182
+}
100
+ break;
183
+
101
+ default:
184
+static TCGv_i32 gpr_to_fp_sysreg(DisasContext *s, void *opaque)
102
+ g_assert_not_reached();
185
+{
103
+ }
186
+ arg_VMSR_VMRS *a = opaque;
104
+}
187
+
105
+
188
+ return load_reg(s, a->rt);
106
+static void neon_store_element64(int reg, int ele, MemOp size, TCGv_i64 var)
189
+}
107
+{
190
+
108
+ long offset = neon_element_offset(reg, ele, size);
191
+static bool gen_M_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
109
+
192
+{
110
+ switch (size) {
193
+ /*
111
+ case MO_8:
194
+ * Accesses to R15 are UNPREDICTABLE; we choose to undef.
112
+ tcg_gen_st8_i64(var, cpu_env, offset);
195
+ * FPSCR -> r15 is a special case which writes to the PSR flags;
113
+ break;
196
+ * set a->reg to a special value to tell gen_M_fp_sysreg_read()
114
+ case MO_16:
197
+ * we only care about the top 4 bits of FPSCR there.
115
+ tcg_gen_st16_i64(var, cpu_env, offset);
198
+ */
116
+ break;
199
+ if (a->rt == 15) {
117
+ case MO_32:
200
+ if (a->l && a->reg == ARM_VFP_FPSCR) {
118
+ tcg_gen_st32_i64(var, cpu_env, offset);
201
+ a->reg = QEMU_VFP_FPSCR_NZCV;
119
+ break;
202
+ } else {
120
+ case MO_64:
203
+ return false;
121
+ tcg_gen_st_i64(var, cpu_env, offset);
204
+ }
122
+ break;
205
+ }
123
+ default:
206
+
124
+ g_assert_not_reached();
207
+ if (a->l) {
125
+ }
208
+ /* VMRS, move FP system register to gp register */
126
+}
209
+ return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_gpr, a);
127
+
210
+ } else {
128
static bool trans_VCMLA(DisasContext *s, arg_VCMLA *a)
211
+ /* VMSR, move gp register to FP system register */
212
+ return gen_M_fp_sysreg_write(s, a->reg, gpr_to_fp_sysreg, a);
213
+ }
214
+}
215
+
216
static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
129
{
217
{
130
int opr_sz;
218
TCGv_i32 tmp;
131
diff --git a/target/arm/translate.c b/target/arm/translate.c
219
bool ignore_vfp_enabled = false;
132
index XXXXXXX..XXXXXXX 100644
220
133
--- a/target/arm/translate.c
221
- if (!dc_isar_feature(aa32_fpsp_v2, s)) {
134
+++ b/target/arm/translate.c
222
- return false;
135
@@ -XXX,XX +XXX,XX @@ neon_reg_offset (int reg, int n)
223
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
136
return vfp_reg_offset(0, sreg);
224
+ return gen_M_VMSR_VMRS(s, a);
137
}
225
}
138
226
139
-/* Return the offset of a 2**SIZE piece of a NEON register, at index ELE,
227
- if (arm_dc_feature(s, ARM_FEATURE_M)) {
140
- * where 0 is the least significant end of the register.
228
- /*
141
- */
229
- * The only M-profile VFP vmrs/vmsr sysreg is FPSCR.
142
-static inline long
230
- * Accesses to R15 are UNPREDICTABLE; we choose to undef.
143
-neon_element_offset(int reg, int element, MemOp size)
231
- * (FPSCR -> r15 is a special case which writes to the PSR flags.)
144
-{
232
- */
145
- int element_size = 1 << size;
233
- if (a->reg != ARM_VFP_FPSCR) {
146
- int ofs = element * element_size;
234
- return false;
147
-#ifdef HOST_WORDS_BIGENDIAN
235
- }
148
- /* Calculate the offset assuming fully little-endian,
236
- if (a->rt == 15 && !a->l) {
149
- * then XOR to account for the order of the 8-byte units.
237
- return false;
150
- */
238
- }
151
- if (element_size < 8) {
239
+ if (!dc_isar_feature(aa32_fpsp_v2, s)) {
152
- ofs ^= 8 - element_size;
240
+ return false;
153
- }
241
}
154
-#endif
242
155
- return neon_reg_offset(reg, 0) + ofs;
243
switch (a->reg) {
156
-}
157
-
158
static TCGv_i32 neon_load_reg(int reg, int pass)
159
{
160
TCGv_i32 tmp = tcg_temp_new_i32();
161
@@ -XXX,XX +XXX,XX @@ static TCGv_i32 neon_load_reg(int reg, int pass)
162
return tmp;
163
}
164
165
-static void neon_load_element(TCGv_i32 var, int reg, int ele, MemOp mop)
166
-{
167
- long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
168
-
169
- switch (mop) {
170
- case MO_UB:
171
- tcg_gen_ld8u_i32(var, cpu_env, offset);
172
- break;
173
- case MO_UW:
174
- tcg_gen_ld16u_i32(var, cpu_env, offset);
175
- break;
176
- case MO_UL:
177
- tcg_gen_ld_i32(var, cpu_env, offset);
178
- break;
179
- default:
180
- g_assert_not_reached();
181
- }
182
-}
183
-
184
-static void neon_load_element64(TCGv_i64 var, int reg, int ele, MemOp mop)
185
-{
186
- long offset = neon_element_offset(reg, ele, mop & MO_SIZE);
187
-
188
- switch (mop) {
189
- case MO_UB:
190
- tcg_gen_ld8u_i64(var, cpu_env, offset);
191
- break;
192
- case MO_UW:
193
- tcg_gen_ld16u_i64(var, cpu_env, offset);
194
- break;
195
- case MO_UL:
196
- tcg_gen_ld32u_i64(var, cpu_env, offset);
197
- break;
198
- case MO_Q:
199
- tcg_gen_ld_i64(var, cpu_env, offset);
200
- break;
201
- default:
202
- g_assert_not_reached();
203
- }
204
-}
205
-
206
static void neon_store_reg(int reg, int pass, TCGv_i32 var)
207
{
208
tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
209
tcg_temp_free_i32(var);
210
}
211
212
-static void neon_store_element(int reg, int ele, MemOp size, TCGv_i32 var)
213
-{
214
- long offset = neon_element_offset(reg, ele, size);
215
-
216
- switch (size) {
217
- case MO_8:
218
- tcg_gen_st8_i32(var, cpu_env, offset);
219
- break;
220
- case MO_16:
221
- tcg_gen_st16_i32(var, cpu_env, offset);
222
- break;
223
- case MO_32:
224
- tcg_gen_st_i32(var, cpu_env, offset);
225
- break;
226
- default:
227
- g_assert_not_reached();
228
- }
229
-}
230
-
231
-static void neon_store_element64(int reg, int ele, MemOp size, TCGv_i64 var)
232
-{
233
- long offset = neon_element_offset(reg, ele, size);
234
-
235
- switch (size) {
236
- case MO_8:
237
- tcg_gen_st8_i64(var, cpu_env, offset);
238
- break;
239
- case MO_16:
240
- tcg_gen_st16_i64(var, cpu_env, offset);
241
- break;
242
- case MO_32:
243
- tcg_gen_st32_i64(var, cpu_env, offset);
244
- break;
245
- case MO_64:
246
- tcg_gen_st_i64(var, cpu_env, offset);
247
- break;
248
- default:
249
- g_assert_not_reached();
250
- }
251
-}
252
-
253
static inline void neon_load_reg64(TCGv_i64 var, int reg)
254
{
255
tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
256
--
244
--
257
2.20.1
245
2.20.1
258
246
259
247
diff view generated by jsdifflib
1
Convert the Neon narrowing moves VMQNV, VQMOVN, VQMOVUN in the 2-reg-misc
1
The constant-expander functions like negate, plus_2, etc, are
2
group to decodetree.
2
generally useful; move them up in translate.c so we can use them in
3
the VFP/Neon decoders as well as in the A32/T32/T16 decoders.
3
4
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200616170844.13318-5-peter.maydell@linaro.org
7
Message-id: 20201119215617.29887-9-peter.maydell@linaro.org
7
---
8
---
8
target/arm/neon-dp.decode | 9 ++++
9
target/arm/translate.c | 46 +++++++++++++++++++++++-------------------
9
target/arm/translate-neon.inc.c | 59 ++++++++++++++++++++++++
10
1 file changed, 25 insertions(+), 21 deletions(-)
10
target/arm/translate.c | 81 +--------------------------------
11
3 files changed, 70 insertions(+), 79 deletions(-)
12
11
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 @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
18
19
@2misc .... ... .. . .. size:2 .. .... . .... q:1 . . .... \
20
&2misc vm=%vm_dp vd=%vd_dp
21
+ @2misc_q0 .... ... .. . .. size:2 .. .... . .... . . . .... \
22
+ &2misc vm=%vm_dp vd=%vd_dp q=0
23
24
VREV64 1111 001 11 . 11 .. 00 .... 0 0000 . . 0 .... @2misc
25
26
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
27
28
VUZP 1111 001 11 . 11 .. 10 .... 0 0010 . . 0 .... @2misc
29
VZIP 1111 001 11 . 11 .. 10 .... 0 0011 . . 0 .... @2misc
30
+
31
+ VMOVN 1111 001 11 . 11 .. 10 .... 0 0100 0 . 0 .... @2misc_q0
32
+ # VQMOVUN: unsigned result (source is always signed)
33
+ VQMOVUN 1111 001 11 . 11 .. 10 .... 0 0100 1 . 0 .... @2misc_q0
34
+ # VQMOVN: signed result, source may be signed (_S) or unsigned (_U)
35
+ VQMOVN_S 1111 001 11 . 11 .. 10 .... 0 0101 0 . 0 .... @2misc_q0
36
+ VQMOVN_U 1111 001 11 . 11 .. 10 .... 0 0101 1 . 0 .... @2misc_q0
37
]
38
39
# Subgroup for size != 0b11
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 @@ static bool trans_VZIP(DisasContext *s, arg_2misc *a)
45
};
46
return do_zip_uzp(s, a, fn[a->q][a->size]);
47
}
48
+
49
+static bool do_vmovn(DisasContext *s, arg_2misc *a,
50
+ NeonGenNarrowEnvFn *narrowfn)
51
+{
52
+ TCGv_i64 rm;
53
+ TCGv_i32 rd0, rd1;
54
+
55
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
56
+ return false;
57
+ }
58
+
59
+ /* UNDEF accesses to D16-D31 if they don't exist. */
60
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
61
+ ((a->vd | a->vm) & 0x10)) {
62
+ return false;
63
+ }
64
+
65
+ if (a->vm & 1) {
66
+ return false;
67
+ }
68
+
69
+ if (!narrowfn) {
70
+ return false;
71
+ }
72
+
73
+ if (!vfp_access_check(s)) {
74
+ return true;
75
+ }
76
+
77
+ rm = tcg_temp_new_i64();
78
+ rd0 = tcg_temp_new_i32();
79
+ rd1 = tcg_temp_new_i32();
80
+
81
+ neon_load_reg64(rm, a->vm);
82
+ narrowfn(rd0, cpu_env, rm);
83
+ neon_load_reg64(rm, a->vm + 1);
84
+ narrowfn(rd1, cpu_env, rm);
85
+ neon_store_reg(a->vd, 0, rd0);
86
+ neon_store_reg(a->vd, 1, rd1);
87
+ tcg_temp_free_i64(rm);
88
+ return true;
89
+}
90
+
91
+#define DO_VMOVN(INSN, FUNC) \
92
+ static bool trans_##INSN(DisasContext *s, arg_2misc *a) \
93
+ { \
94
+ static NeonGenNarrowEnvFn * const narrowfn[] = { \
95
+ FUNC##8, \
96
+ FUNC##16, \
97
+ FUNC##32, \
98
+ NULL, \
99
+ }; \
100
+ return do_vmovn(s, a, narrowfn[a->size]); \
101
+ }
102
+
103
+DO_VMOVN(VMOVN, gen_neon_narrow_u)
104
+DO_VMOVN(VQMOVUN, gen_helper_neon_unarrow_sat)
105
+DO_VMOVN(VQMOVN_S, gen_helper_neon_narrow_sat_s)
106
+DO_VMOVN(VQMOVN_U, gen_helper_neon_narrow_sat_u)
107
diff --git a/target/arm/translate.c b/target/arm/translate.c
12
diff --git a/target/arm/translate.c b/target/arm/translate.c
108
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
109
--- a/target/arm/translate.c
14
--- a/target/arm/translate.c
110
+++ b/target/arm/translate.c
15
+++ b/target/arm/translate.c
111
@@ -XXX,XX +XXX,XX @@ static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
16
@@ -XXX,XX +XXX,XX @@ static void arm_gen_condlabel(DisasContext *s)
112
tcg_temp_free_i32(rd);
17
}
113
}
18
}
114
19
115
-static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
20
+/*
21
+ * Constant expanders for the decoders.
22
+ */
23
+
24
+static int negate(DisasContext *s, int x)
25
+{
26
+ return -x;
27
+}
28
+
29
+static int plus_2(DisasContext *s, int x)
30
+{
31
+ return x + 2;
32
+}
33
+
34
+static int times_2(DisasContext *s, int x)
35
+{
36
+ return x * 2;
37
+}
38
+
39
+static int times_4(DisasContext *s, int x)
40
+{
41
+ return x * 4;
42
+}
43
+
44
/* Flags for the disas_set_da_iss info argument:
45
* lower bits hold the Rt register number, higher bits are flags.
46
*/
47
@@ -XXX,XX +XXX,XX @@ static void arm_skip_unless(DisasContext *s, uint32_t cond)
48
49
50
/*
51
- * Constant expanders for the decoders.
52
+ * Constant expanders used by T16/T32 decode
53
*/
54
55
-static int negate(DisasContext *s, int x)
116
-{
56
-{
117
- switch (size) {
57
- return -x;
118
- case 0: gen_helper_neon_narrow_u8(dest, src); break;
119
- case 1: gen_helper_neon_narrow_u16(dest, src); break;
120
- case 2: tcg_gen_extrl_i64_i32(dest, src); break;
121
- default: abort();
122
- }
123
-}
58
-}
124
-
59
-
125
-static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
60
-static int plus_2(DisasContext *s, int x)
126
-{
61
-{
127
- switch (size) {
62
- return x + 2;
128
- case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
129
- case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
130
- case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
131
- default: abort();
132
- }
133
-}
63
-}
134
-
64
-
135
-static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
65
-static int times_2(DisasContext *s, int x)
136
-{
66
-{
137
- switch (size) {
67
- return x * 2;
138
- case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
139
- case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
140
- case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
141
- default: abort();
142
- }
143
-}
68
-}
144
-
69
-
145
-static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
70
-static int times_4(DisasContext *s, int x)
146
-{
71
-{
147
- switch (size) {
72
- return x * 4;
148
- case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
149
- case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
150
- case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
151
- default: abort();
152
- }
153
-}
73
-}
154
-
74
-
155
static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
75
/* Return only the rotation part of T32ExpandImm. */
76
static int t32_expandimm_rot(DisasContext *s, int x)
156
{
77
{
157
if (u) {
158
@@ -XXX,XX +XXX,XX @@ static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
159
tcg_temp_free_i32(src);
160
}
161
162
-static void gen_neon_narrow_op(int op, int u, int size,
163
- TCGv_i32 dest, TCGv_i64 src)
164
-{
165
- if (op) {
166
- if (u) {
167
- gen_neon_unarrow_sats(size, dest, src);
168
- } else {
169
- gen_neon_narrow(size, dest, src);
170
- }
171
- } else {
172
- if (u) {
173
- gen_neon_narrow_satu(size, dest, src);
174
- } else {
175
- gen_neon_narrow_sats(size, dest, src);
176
- }
177
- }
178
-}
179
-
180
/* Symbolic constants for op fields for Neon 2-register miscellaneous.
181
* The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
182
* table A7-13.
183
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
184
!arm_dc_feature(s, ARM_FEATURE_V8)) {
185
return 1;
186
}
187
- if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
188
- q && ((rm | rd) & 1)) {
189
+ if (q && ((rm | rd) & 1)) {
190
return 1;
191
}
192
switch (op) {
193
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
194
case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
195
case NEON_2RM_VUZP:
196
case NEON_2RM_VZIP:
197
+ case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
198
/* handled by decodetree */
199
return 1;
200
case NEON_2RM_VTRN:
201
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
202
goto elementwise;
203
}
204
break;
205
- case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
206
- /* also VQMOVUN; op field and mnemonics don't line up */
207
- if (rm & 1) {
208
- return 1;
209
- }
210
- tmp2 = NULL;
211
- for (pass = 0; pass < 2; pass++) {
212
- neon_load_reg64(cpu_V0, rm + pass);
213
- tmp = tcg_temp_new_i32();
214
- gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
215
- tmp, cpu_V0);
216
- if (pass == 0) {
217
- tmp2 = tmp;
218
- } else {
219
- neon_store_reg(rd, 0, tmp2);
220
- neon_store_reg(rd, 1, tmp);
221
- }
222
- }
223
- break;
224
case NEON_2RM_VSHLL:
225
if (q || (rd & 1)) {
226
return 1;
227
--
78
--
228
2.20.1
79
2.20.1
229
80
230
81
diff view generated by jsdifflib
1
Convert the pairwise ops VPADDL and VPADAL in the 2-reg-misc grouping
1
Implement the new-in-v8.1M VLDR/VSTR variants which directly
2
to decodetree.
2
read or write FP system registers to memory.
3
4
At this point we can get rid of the weird CPU_V001 #define that was
5
used to avoid having to explicitly list all the arguments being
6
passed to some TCG gen/helper functions.
7
3
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20200616170844.13318-3-peter.maydell@linaro.org
6
Message-id: 20201119215617.29887-10-peter.maydell@linaro.org
11
---
7
---
12
target/arm/neon-dp.decode | 6 ++
8
target/arm/vfp.decode | 14 ++++++
13
target/arm/translate-neon.inc.c | 149 ++++++++++++++++++++++++++++++++
9
target/arm/translate-vfp.c.inc | 91 ++++++++++++++++++++++++++++++++++
14
target/arm/translate.c | 35 +-------
10
2 files changed, 105 insertions(+)
15
3 files changed, 157 insertions(+), 33 deletions(-)
16
11
17
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
12
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
18
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/neon-dp.decode
14
--- a/target/arm/vfp.decode
20
+++ b/target/arm/neon-dp.decode
15
+++ b/target/arm/vfp.decode
21
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
16
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR_hp ---- 1101 u:1 .0 l:1 rn:4 .... 1001 imm:8 vd=%vd_sp
22
&2misc vm=%vm_dp vd=%vd_dp
17
VLDR_VSTR_sp ---- 1101 u:1 .0 l:1 rn:4 .... 1010 imm:8 vd=%vd_sp
23
18
VLDR_VSTR_dp ---- 1101 u:1 .0 l:1 rn:4 .... 1011 imm:8 vd=%vd_dp
24
VREV64 1111 001 11 . 11 .. 00 .... 0 0000 . . 0 .... @2misc
19
20
+# M-profile VLDR/VSTR to sysreg
21
+%vldr_sysreg 22:1 13:3
22
+%imm7_0x4 0:7 !function=times_4
25
+
23
+
26
+ VPADDL_S 1111 001 11 . 11 .. 00 .... 0 0100 . . 0 .... @2misc
24
+&vldr_sysreg rn reg imm a w p
27
+ VPADDL_U 1111 001 11 . 11 .. 00 .... 0 0101 . . 0 .... @2misc
25
+@vldr_sysreg .... ... . a:1 . . . rn:4 ... . ... .. ....... \
26
+ reg=%vldr_sysreg imm=%imm7_0x4 &vldr_sysreg
28
+
27
+
29
+ VPADAL_S 1111 001 11 . 11 .. 00 .... 0 1100 . . 0 .... @2misc
28
+# P=0 W=0 is SEE "Related encodings", so split into two patterns
30
+ VPADAL_U 1111 001 11 . 11 .. 00 .... 0 1101 . . 0 .... @2misc
29
+VLDR_sysreg ---- 110 1 . . w:1 1 .... ... 0 111 11 ....... @vldr_sysreg p=1
31
]
30
+VLDR_sysreg ---- 110 0 . . 1 1 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
32
31
+VSTR_sysreg ---- 110 1 . . w:1 0 .... ... 0 111 11 ....... @vldr_sysreg p=1
33
# Subgroup for size != 0b11
32
+VSTR_sysreg ---- 110 0 . . 1 0 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
34
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
33
+
34
# We split the load/store multiple up into two patterns to avoid
35
# overlap with other insns in the "Advanced SIMD load/store and 64-bit move"
36
# grouping:
37
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
35
index XXXXXXX..XXXXXXX 100644
38
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/translate-neon.inc.c
39
--- a/target/arm/translate-vfp.c.inc
37
+++ b/target/arm/translate-neon.inc.c
40
+++ b/target/arm/translate-vfp.c.inc
38
@@ -XXX,XX +XXX,XX @@ static bool trans_VREV64(DisasContext *s, arg_VREV64 *a)
41
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
39
}
40
return true;
42
return true;
41
}
43
}
44
45
+static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
46
+{
47
+ arg_vldr_sysreg *a = opaque;
48
+ uint32_t offset = a->imm;
49
+ TCGv_i32 addr;
42
+
50
+
43
+static bool do_2misc_pairwise(DisasContext *s, arg_2misc *a,
51
+ if (!a->a) {
44
+ NeonGenWidenFn *widenfn,
52
+ offset = - offset;
45
+ NeonGenTwo64OpFn *opfn,
53
+ }
46
+ NeonGenTwo64OpFn *accfn)
54
+
55
+ addr = load_reg(s, a->rn);
56
+ if (a->p) {
57
+ tcg_gen_addi_i32(addr, addr, offset);
58
+ }
59
+
60
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
61
+ gen_helper_v8m_stackcheck(cpu_env, addr);
62
+ }
63
+
64
+ gen_aa32_st_i32(s, value, addr, get_mem_index(s),
65
+ MO_UL | MO_ALIGN | s->be_data);
66
+ tcg_temp_free_i32(value);
67
+
68
+ if (a->w) {
69
+ /* writeback */
70
+ if (!a->p) {
71
+ tcg_gen_addi_i32(addr, addr, offset);
72
+ }
73
+ store_reg(s, a->rn, addr);
74
+ } else {
75
+ tcg_temp_free_i32(addr);
76
+ }
77
+}
78
+
79
+static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
47
+{
80
+{
48
+ /*
81
+ arg_vldr_sysreg *a = opaque;
49
+ * Pairwise long operations: widen both halves of the pair,
82
+ uint32_t offset = a->imm;
50
+ * combine the pairs with the opfn, and then possibly accumulate
83
+ TCGv_i32 addr;
51
+ * into the destination with the accfn.
84
+ TCGv_i32 value = tcg_temp_new_i32();
52
+ */
53
+ int pass;
54
+
85
+
55
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
86
+ if (!a->a) {
87
+ offset = - offset;
88
+ }
89
+
90
+ addr = load_reg(s, a->rn);
91
+ if (a->p) {
92
+ tcg_gen_addi_i32(addr, addr, offset);
93
+ }
94
+
95
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
96
+ gen_helper_v8m_stackcheck(cpu_env, addr);
97
+ }
98
+
99
+ gen_aa32_ld_i32(s, value, addr, get_mem_index(s),
100
+ MO_UL | MO_ALIGN | s->be_data);
101
+
102
+ if (a->w) {
103
+ /* writeback */
104
+ if (!a->p) {
105
+ tcg_gen_addi_i32(addr, addr, offset);
106
+ }
107
+ store_reg(s, a->rn, addr);
108
+ } else {
109
+ tcg_temp_free_i32(addr);
110
+ }
111
+ return value;
112
+}
113
+
114
+static bool trans_VLDR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
115
+{
116
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
56
+ return false;
117
+ return false;
57
+ }
118
+ }
58
+
119
+ if (a->rn == 15) {
59
+ /* UNDEF accesses to D16-D31 if they don't exist. */
60
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
61
+ ((a->vd | a->vm) & 0x10)) {
62
+ return false;
120
+ return false;
63
+ }
121
+ }
122
+ return gen_M_fp_sysreg_write(s, a->reg, memory_to_fp_sysreg, a);
123
+}
64
+
124
+
65
+ if ((a->vd | a->vm) & a->q) {
125
+static bool trans_VSTR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
126
+{
127
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
66
+ return false;
128
+ return false;
67
+ }
129
+ }
68
+
130
+ if (a->rn == 15) {
69
+ if (!widenfn) {
70
+ return false;
131
+ return false;
71
+ }
132
+ }
72
+
133
+ return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_memory, a);
73
+ if (!vfp_access_check(s)) {
74
+ return true;
75
+ }
76
+
77
+ for (pass = 0; pass < a->q + 1; pass++) {
78
+ TCGv_i32 tmp;
79
+ TCGv_i64 rm0_64, rm1_64, rd_64;
80
+
81
+ rm0_64 = tcg_temp_new_i64();
82
+ rm1_64 = tcg_temp_new_i64();
83
+ rd_64 = tcg_temp_new_i64();
84
+ tmp = neon_load_reg(a->vm, pass * 2);
85
+ widenfn(rm0_64, tmp);
86
+ tcg_temp_free_i32(tmp);
87
+ tmp = neon_load_reg(a->vm, pass * 2 + 1);
88
+ widenfn(rm1_64, tmp);
89
+ tcg_temp_free_i32(tmp);
90
+ opfn(rd_64, rm0_64, rm1_64);
91
+ tcg_temp_free_i64(rm0_64);
92
+ tcg_temp_free_i64(rm1_64);
93
+
94
+ if (accfn) {
95
+ TCGv_i64 tmp64 = tcg_temp_new_i64();
96
+ neon_load_reg64(tmp64, a->vd + pass);
97
+ accfn(rd_64, tmp64, rd_64);
98
+ tcg_temp_free_i64(tmp64);
99
+ }
100
+ neon_store_reg64(rd_64, a->vd + pass);
101
+ tcg_temp_free_i64(rd_64);
102
+ }
103
+ return true;
104
+}
134
+}
105
+
135
+
106
+static bool trans_VPADDL_S(DisasContext *s, arg_2misc *a)
136
static bool trans_VMOV_half(DisasContext *s, arg_VMOV_single *a)
107
+{
108
+ static NeonGenWidenFn * const widenfn[] = {
109
+ gen_helper_neon_widen_s8,
110
+ gen_helper_neon_widen_s16,
111
+ tcg_gen_ext_i32_i64,
112
+ NULL,
113
+ };
114
+ static NeonGenTwo64OpFn * const opfn[] = {
115
+ gen_helper_neon_paddl_u16,
116
+ gen_helper_neon_paddl_u32,
117
+ tcg_gen_add_i64,
118
+ NULL,
119
+ };
120
+
121
+ return do_2misc_pairwise(s, a, widenfn[a->size], opfn[a->size], NULL);
122
+}
123
+
124
+static bool trans_VPADDL_U(DisasContext *s, arg_2misc *a)
125
+{
126
+ static NeonGenWidenFn * const widenfn[] = {
127
+ gen_helper_neon_widen_u8,
128
+ gen_helper_neon_widen_u16,
129
+ tcg_gen_extu_i32_i64,
130
+ NULL,
131
+ };
132
+ static NeonGenTwo64OpFn * const opfn[] = {
133
+ gen_helper_neon_paddl_u16,
134
+ gen_helper_neon_paddl_u32,
135
+ tcg_gen_add_i64,
136
+ NULL,
137
+ };
138
+
139
+ return do_2misc_pairwise(s, a, widenfn[a->size], opfn[a->size], NULL);
140
+}
141
+
142
+static bool trans_VPADAL_S(DisasContext *s, arg_2misc *a)
143
+{
144
+ static NeonGenWidenFn * const widenfn[] = {
145
+ gen_helper_neon_widen_s8,
146
+ gen_helper_neon_widen_s16,
147
+ tcg_gen_ext_i32_i64,
148
+ NULL,
149
+ };
150
+ static NeonGenTwo64OpFn * const opfn[] = {
151
+ gen_helper_neon_paddl_u16,
152
+ gen_helper_neon_paddl_u32,
153
+ tcg_gen_add_i64,
154
+ NULL,
155
+ };
156
+ static NeonGenTwo64OpFn * const accfn[] = {
157
+ gen_helper_neon_addl_u16,
158
+ gen_helper_neon_addl_u32,
159
+ tcg_gen_add_i64,
160
+ NULL,
161
+ };
162
+
163
+ return do_2misc_pairwise(s, a, widenfn[a->size], opfn[a->size],
164
+ accfn[a->size]);
165
+}
166
+
167
+static bool trans_VPADAL_U(DisasContext *s, arg_2misc *a)
168
+{
169
+ static NeonGenWidenFn * const widenfn[] = {
170
+ gen_helper_neon_widen_u8,
171
+ gen_helper_neon_widen_u16,
172
+ tcg_gen_extu_i32_i64,
173
+ NULL,
174
+ };
175
+ static NeonGenTwo64OpFn * const opfn[] = {
176
+ gen_helper_neon_paddl_u16,
177
+ gen_helper_neon_paddl_u32,
178
+ tcg_gen_add_i64,
179
+ NULL,
180
+ };
181
+ static NeonGenTwo64OpFn * const accfn[] = {
182
+ gen_helper_neon_addl_u16,
183
+ gen_helper_neon_addl_u32,
184
+ tcg_gen_add_i64,
185
+ NULL,
186
+ };
187
+
188
+ return do_2misc_pairwise(s, a, widenfn[a->size], opfn[a->size],
189
+ accfn[a->size]);
190
+}
191
diff --git a/target/arm/translate.c b/target/arm/translate.c
192
index XXXXXXX..XXXXXXX 100644
193
--- a/target/arm/translate.c
194
+++ b/target/arm/translate.c
195
@@ -XXX,XX +XXX,XX @@ static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
196
gen_rfe(s, pc, load_cpu_field(spsr));
197
}
198
199
-#define CPU_V001 cpu_V0, cpu_V0, cpu_V1
200
-
201
static int gen_neon_unzip(int rd, int rm, int size, int q)
202
{
137
{
203
TCGv_ptr pd, pm;
138
TCGv_i32 tmp;
204
@@ -XXX,XX +XXX,XX @@ static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
205
tcg_temp_free_i32(src);
206
}
207
208
-static inline void gen_neon_addl(int size)
209
-{
210
- switch (size) {
211
- case 0: gen_helper_neon_addl_u16(CPU_V001); break;
212
- case 1: gen_helper_neon_addl_u32(CPU_V001); break;
213
- case 2: tcg_gen_add_i64(CPU_V001); break;
214
- default: abort();
215
- }
216
-}
217
-
218
static void gen_neon_narrow_op(int op, int u, int size,
219
TCGv_i32 dest, TCGv_i64 src)
220
{
221
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
222
}
223
switch (op) {
224
case NEON_2RM_VREV64:
225
- /* handled by decodetree */
226
- return 1;
227
case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
228
case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
229
- for (pass = 0; pass < q + 1; pass++) {
230
- tmp = neon_load_reg(rm, pass * 2);
231
- gen_neon_widen(cpu_V0, tmp, size, op & 1);
232
- tmp = neon_load_reg(rm, pass * 2 + 1);
233
- gen_neon_widen(cpu_V1, tmp, size, op & 1);
234
- switch (size) {
235
- case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
236
- case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
237
- case 2: tcg_gen_add_i64(CPU_V001); break;
238
- default: abort();
239
- }
240
- if (op >= NEON_2RM_VPADAL) {
241
- /* Accumulate. */
242
- neon_load_reg64(cpu_V1, rd + pass);
243
- gen_neon_addl(size);
244
- }
245
- neon_store_reg64(cpu_V0, rd + pass);
246
- }
247
- break;
248
+ /* handled by decodetree */
249
+ return 1;
250
case NEON_2RM_VTRN:
251
if (size == 2) {
252
int n;
253
--
139
--
254
2.20.1
140
2.20.1
255
141
256
142
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
v8.1M defines a new FP system register FPSCR_nzcvqc; this behaves
2
like the existing FPSCR, except that it reads and writes only bits
3
[31:27] of the FPSCR (the N, Z, C, V and QC flag bits). (Unlike the
4
FPSCR, the special case for Rt=15 of writing the CPSR.NZCV is not
5
permitted.)
2
6
3
Register the GPIO peripherals as unimplemented to better
7
Implement the register. Since we don't yet implement MVE, we handle
4
follow their accesses, for example booting Zephyr:
8
the QC bit as RES0, with todo comments for where we will need to add
9
support later.
5
10
6
----------------
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
IN: arm_mps2_pinmux_init
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
0x00001160: f64f 0231 movw r2, #0xf831
13
Message-id: 20201119215617.29887-11-peter.maydell@linaro.org
9
0x00001164: 4b06 ldr r3, [pc, #0x18]
14
---
10
0x00001166: 2000 movs r0, #0
15
target/arm/cpu.h | 13 +++++++++++++
11
0x00001168: 619a str r2, [r3, #0x18]
16
target/arm/translate-vfp.c.inc | 27 +++++++++++++++++++++++++++
12
0x0000116a: f24c 426f movw r2, #0xc46f
17
2 files changed, 40 insertions(+)
13
0x0000116e: f503 5380 add.w r3, r3, #0x1000
14
0x00001172: 619a str r2, [r3, #0x18]
15
0x00001174: f44f 529e mov.w r2, #0x13c0
16
0x00001178: f503 5380 add.w r3, r3, #0x1000
17
0x0000117c: 619a str r2, [r3, #0x18]
18
0x0000117e: 4770 bx lr
19
cmsdk-ahb-gpio: unimplemented device write (size 4, value 0xf831, offset 0x18)
20
cmsdk-ahb-gpio: unimplemented device write (size 4, value 0xc46f, offset 0x18)
21
cmsdk-ahb-gpio: unimplemented device write (size 4, value 0x13c0, offset 0x18)
22
18
23
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
24
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
25
Message-id: 20200617072539.32686-10-f4bug@amsat.org
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
---
28
hw/arm/mps2.c | 8 ++++++--
29
1 file changed, 6 insertions(+), 2 deletions(-)
30
31
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
32
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
33
--- a/hw/arm/mps2.c
21
--- a/target/arm/cpu.h
34
+++ b/hw/arm/mps2.c
22
+++ b/target/arm/cpu.h
35
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
23
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
36
MemoryRegion *system_memory = get_system_memory();
24
#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
37
MachineClass *mc = MACHINE_GET_CLASS(machine);
25
#define FPCR_DN (1 << 25) /* Default NaN enable bit */
38
DeviceState *armv7m, *sccdev;
26
#define FPCR_QC (1 << 27) /* Cumulative saturation bit */
39
+ int i;
27
+#define FPCR_V (1 << 28) /* FP overflow flag */
40
28
+#define FPCR_C (1 << 29) /* FP carry flag */
41
if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
29
+#define FPCR_Z (1 << 30) /* FP zero flag */
42
error_report("This board can only be used with CPU %s",
30
+#define FPCR_N (1 << 31) /* FP negative flag */
43
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
31
+
44
*/
32
+#define FPCR_NZCV_MASK (FPCR_N | FPCR_Z | FPCR_C | FPCR_V)
45
Object *orgate;
33
+#define FPCR_NZCVQC_MASK (FPCR_NZCV_MASK | FPCR_QC)
46
DeviceState *orgate_dev;
34
47
- int i;
35
static inline uint32_t vfp_get_fpsr(CPUARMState *env)
48
36
{
49
orgate = object_new(TYPE_OR_IRQ);
37
@@ -XXX,XX +XXX,XX @@ enum arm_cpu_mode {
50
object_property_set_int(orgate, 6, "num-lines", &error_fatal);
38
#define ARM_VFP_FPEXC 8
51
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
39
#define ARM_VFP_FPINST 9
52
*/
40
#define ARM_VFP_FPINST2 10
53
Object *orgate;
41
+/* These ones are M-profile only */
54
DeviceState *orgate_dev;
42
+#define ARM_VFP_FPSCR_NZCVQC 2
55
- int i;
43
+#define ARM_VFP_VPR 12
56
44
+#define ARM_VFP_P0 13
57
orgate = object_new(TYPE_OR_IRQ);
45
+#define ARM_VFP_FPCXT_NS 14
58
object_property_set_int(orgate, 10, "num-lines", &error_fatal);
46
+#define ARM_VFP_FPCXT_S 15
59
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
47
48
/* QEMU-internal value meaning "FPSCR, but we care only about NZCV" */
49
#define QEMU_VFP_FPSCR_NZCV 0xffff
50
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/translate-vfp.c.inc
53
+++ b/target/arm/translate-vfp.c.inc
54
@@ -XXX,XX +XXX,XX @@ static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
55
case ARM_VFP_FPSCR:
56
case QEMU_VFP_FPSCR_NZCV:
57
break;
58
+ case ARM_VFP_FPSCR_NZCVQC:
59
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
60
+ return false;
61
+ }
62
+ break;
63
default:
64
return FPSysRegCheckFailed;
65
}
66
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
67
tcg_temp_free_i32(tmp);
68
gen_lookup_tb(s);
69
break;
70
+ case ARM_VFP_FPSCR_NZCVQC:
71
+ {
72
+ TCGv_i32 fpscr;
73
+ tmp = loadfn(s, opaque);
74
+ /*
75
+ * TODO: when we implement MVE, write the QC bit.
76
+ * For non-MVE, QC is RES0.
77
+ */
78
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
79
+ fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
80
+ tcg_gen_andi_i32(fpscr, fpscr, ~FPCR_NZCV_MASK);
81
+ tcg_gen_or_i32(fpscr, fpscr, tmp);
82
+ store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
83
+ tcg_temp_free_i32(tmp);
84
+ break;
85
+ }
60
default:
86
default:
61
g_assert_not_reached();
87
g_assert_not_reached();
62
}
88
}
63
+ for (i = 0; i < 4; i++) {
89
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
64
+ static const hwaddr gpiobase[] = {0x40010000, 0x40011000,
90
gen_helper_vfp_get_fpscr(tmp, cpu_env);
65
+ 0x40012000, 0x40013000};
91
storefn(s, opaque, tmp);
66
+ create_unimplemented_device("cmsdk-ahb-gpio", gpiobase[i], 0x1000);
92
break;
67
+ }
93
+ case ARM_VFP_FPSCR_NZCVQC:
68
94
+ /*
69
/* CMSDK APB subsystem */
95
+ * TODO: MVE has a QC bit, which we probably won't store
70
cmsdk_apb_timer_create(0x40000000, qdev_get_gpio_in(armv7m, 8), SYSCLK_FRQ);
96
+ * in the xregs[] field. For non-MVE, where QC is RES0,
97
+ * we can just fall through to the FPSCR_NZCV case.
98
+ */
99
case QEMU_VFP_FPSCR_NZCV:
100
/*
101
* Read just NZCV; this is a special case to avoid the
71
--
102
--
72
2.20.1
103
2.20.1
73
104
74
105
diff view generated by jsdifflib
1
Convert the VCVT instructions in the 2-reg-misc grouping to
1
We defined a constant name for the mask of NZCV bits in the FPCR/FPSCR
2
decodetree.
2
in the previous commit; use it in a couple of places in existing code,
3
where we're masking out everything except NZCV for the "load to Rt=15
4
sets CPSR.NZCV" special case.
3
5
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200616170844.13318-19-peter.maydell@linaro.org
8
Message-id: 20201119215617.29887-12-peter.maydell@linaro.org
7
---
9
---
8
target/arm/neon-dp.decode | 9 +++++
10
target/arm/translate-vfp.c.inc | 4 ++--
9
target/arm/translate-neon.inc.c | 70 +++++++++++++++++++++++++++++++++
11
1 file changed, 2 insertions(+), 2 deletions(-)
10
target/arm/translate.c | 70 ++++-----------------------------
11
3 files changed, 87 insertions(+), 62 deletions(-)
12
12
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
15
--- a/target/arm/translate-vfp.c.inc
16
+++ b/target/arm/neon-dp.decode
16
+++ b/target/arm/translate-vfp.c.inc
17
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
17
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
18
18
* helper call for the "VMRS to CPSR.NZCV" insn.
19
VRINTP 1111 001 11 . 11 .. 10 .... 0 1111 . . 0 .... @2misc
19
*/
20
20
tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
21
+ VCVTAS 1111 001 11 . 11 .. 11 .... 0 0000 . . 0 .... @2misc
21
- tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
22
+ VCVTAU 1111 001 11 . 11 .. 11 .... 0 0001 . . 0 .... @2misc
22
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
23
+ VCVTNS 1111 001 11 . 11 .. 11 .... 0 0010 . . 0 .... @2misc
23
storefn(s, opaque, tmp);
24
+ VCVTNU 1111 001 11 . 11 .. 11 .... 0 0011 . . 0 .... @2misc
24
break;
25
+ VCVTPS 1111 001 11 . 11 .. 11 .... 0 0100 . . 0 .... @2misc
25
default:
26
+ VCVTPU 1111 001 11 . 11 .. 11 .... 0 0101 . . 0 .... @2misc
26
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
27
+ VCVTMS 1111 001 11 . 11 .. 11 .... 0 0110 . . 0 .... @2misc
27
case ARM_VFP_FPSCR:
28
+ VCVTMU 1111 001 11 . 11 .. 11 .... 0 0111 . . 0 .... @2misc
28
if (a->rt == 15) {
29
+
29
tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
30
VRECPE 1111 001 11 . 11 .. 11 .... 0 1000 . . 0 .... @2misc
30
- tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
31
VRSQRTE 1111 001 11 . 11 .. 11 .... 0 1001 . . 0 .... @2misc
31
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
32
VRECPE_F 1111 001 11 . 11 .. 11 .... 0 1010 . . 0 .... @2misc
32
} else {
33
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
33
tmp = tcg_temp_new_i32();
34
index XXXXXXX..XXXXXXX 100644
34
gen_helper_vfp_get_fpscr(tmp, cpu_env);
35
--- a/target/arm/translate-neon.inc.c
36
+++ b/target/arm/translate-neon.inc.c
37
@@ -XXX,XX +XXX,XX @@ DO_VRINT(VRINTA, FPROUNDING_TIEAWAY)
38
DO_VRINT(VRINTZ, FPROUNDING_ZERO)
39
DO_VRINT(VRINTM, FPROUNDING_NEGINF)
40
DO_VRINT(VRINTP, FPROUNDING_POSINF)
41
+
42
+static bool do_vcvt(DisasContext *s, arg_2misc *a, int rmode, bool is_signed)
43
+{
44
+ /*
45
+ * Handle a VCVT* operation by iterating 32 bits at a time,
46
+ * with a specified rounding mode in operation.
47
+ */
48
+ int pass;
49
+ TCGv_ptr fpst;
50
+ TCGv_i32 tcg_rmode, tcg_shift;
51
+
52
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
53
+ !arm_dc_feature(s, ARM_FEATURE_V8)) {
54
+ return false;
55
+ }
56
+
57
+ /* UNDEF accesses to D16-D31 if they don't exist. */
58
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
59
+ ((a->vd | a->vm) & 0x10)) {
60
+ return false;
61
+ }
62
+
63
+ if (a->size != 2) {
64
+ /* TODO: FP16 will be the size == 1 case */
65
+ return false;
66
+ }
67
+
68
+ if ((a->vd | a->vm) & a->q) {
69
+ return false;
70
+ }
71
+
72
+ if (!vfp_access_check(s)) {
73
+ return true;
74
+ }
75
+
76
+ fpst = get_fpstatus_ptr(1);
77
+ tcg_shift = tcg_const_i32(0);
78
+ tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
79
+ gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode, cpu_env);
80
+ for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
81
+ TCGv_i32 tmp = neon_load_reg(a->vm, pass);
82
+ if (is_signed) {
83
+ gen_helper_vfp_tosls(tmp, tmp, tcg_shift, fpst);
84
+ } else {
85
+ gen_helper_vfp_touls(tmp, tmp, tcg_shift, fpst);
86
+ }
87
+ neon_store_reg(a->vd, pass, tmp);
88
+ }
89
+ gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode, cpu_env);
90
+ tcg_temp_free_i32(tcg_rmode);
91
+ tcg_temp_free_i32(tcg_shift);
92
+ tcg_temp_free_ptr(fpst);
93
+
94
+ return true;
95
+}
96
+
97
+#define DO_VCVT(INSN, RMODE, SIGNED) \
98
+ static bool trans_##INSN(DisasContext *s, arg_2misc *a) \
99
+ { \
100
+ return do_vcvt(s, a, RMODE, SIGNED); \
101
+ }
102
+
103
+DO_VCVT(VCVTAU, FPROUNDING_TIEAWAY, false)
104
+DO_VCVT(VCVTAS, FPROUNDING_TIEAWAY, true)
105
+DO_VCVT(VCVTNU, FPROUNDING_TIEEVEN, false)
106
+DO_VCVT(VCVTNS, FPROUNDING_TIEEVEN, true)
107
+DO_VCVT(VCVTPU, FPROUNDING_POSINF, false)
108
+DO_VCVT(VCVTPS, FPROUNDING_POSINF, true)
109
+DO_VCVT(VCVTMU, FPROUNDING_NEGINF, false)
110
+DO_VCVT(VCVTMS, FPROUNDING_NEGINF, true)
111
diff --git a/target/arm/translate.c b/target/arm/translate.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/target/arm/translate.c
114
+++ b/target/arm/translate.c
115
@@ -XXX,XX +XXX,XX @@ static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
116
#define NEON_2RM_VCVT_SF 62
117
#define NEON_2RM_VCVT_UF 63
118
119
-static bool neon_2rm_is_v8_op(int op)
120
-{
121
- /* Return true if this neon 2reg-misc op is ARMv8 and up */
122
- switch (op) {
123
- case NEON_2RM_VRINTN:
124
- case NEON_2RM_VRINTA:
125
- case NEON_2RM_VRINTM:
126
- case NEON_2RM_VRINTP:
127
- case NEON_2RM_VRINTZ:
128
- case NEON_2RM_VRINTX:
129
- case NEON_2RM_VCVTAU:
130
- case NEON_2RM_VCVTAS:
131
- case NEON_2RM_VCVTNU:
132
- case NEON_2RM_VCVTNS:
133
- case NEON_2RM_VCVTPU:
134
- case NEON_2RM_VCVTPS:
135
- case NEON_2RM_VCVTMU:
136
- case NEON_2RM_VCVTMS:
137
- return true;
138
- default:
139
- return false;
140
- }
141
-}
142
-
143
/* Each entry in this array has bit n set if the insn allows
144
* size value n (otherwise it will UNDEF). Since unallocated
145
* op values will have no bits set they always UNDEF.
146
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
147
if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
148
return 1;
149
}
150
- if (neon_2rm_is_v8_op(op) &&
151
- !arm_dc_feature(s, ARM_FEATURE_V8)) {
152
- return 1;
153
- }
154
if (q && ((rm | rd) & 1)) {
155
return 1;
156
}
157
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
158
case NEON_2RM_VRINTM:
159
case NEON_2RM_VRINTP:
160
case NEON_2RM_VRINTZ:
161
+ case NEON_2RM_VCVTAU:
162
+ case NEON_2RM_VCVTAS:
163
+ case NEON_2RM_VCVTNU:
164
+ case NEON_2RM_VCVTNS:
165
+ case NEON_2RM_VCVTPU:
166
+ case NEON_2RM_VCVTPS:
167
+ case NEON_2RM_VCVTMU:
168
+ case NEON_2RM_VCVTMS:
169
/* handled by decodetree */
170
return 1;
171
case NEON_2RM_VTRN:
172
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
173
}
174
neon_store_reg(rm, pass, tmp2);
175
break;
176
- case NEON_2RM_VCVTAU:
177
- case NEON_2RM_VCVTAS:
178
- case NEON_2RM_VCVTNU:
179
- case NEON_2RM_VCVTNS:
180
- case NEON_2RM_VCVTPU:
181
- case NEON_2RM_VCVTPS:
182
- case NEON_2RM_VCVTMU:
183
- case NEON_2RM_VCVTMS:
184
- {
185
- bool is_signed = !extract32(insn, 7, 1);
186
- TCGv_ptr fpst = get_fpstatus_ptr(1);
187
- TCGv_i32 tcg_rmode, tcg_shift;
188
- int rmode = fp_decode_rm[extract32(insn, 8, 2)];
189
-
190
- tcg_shift = tcg_const_i32(0);
191
- tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
192
- gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
193
- cpu_env);
194
-
195
- if (is_signed) {
196
- gen_helper_vfp_tosls(tmp, tmp,
197
- tcg_shift, fpst);
198
- } else {
199
- gen_helper_vfp_touls(tmp, tmp,
200
- tcg_shift, fpst);
201
- }
202
-
203
- gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
204
- cpu_env);
205
- tcg_temp_free_i32(tcg_rmode);
206
- tcg_temp_free_i32(tcg_shift);
207
- tcg_temp_free_ptr(fpst);
208
- break;
209
- }
210
default:
211
/* Reserved op values were caught by the
212
* neon_2rm_sizes[] check earlier.
213
--
35
--
214
2.20.1
36
2.20.1
215
37
216
38
diff view generated by jsdifflib
1
Convert the Neon 2-reg-misc VRINT insns to decodetree.
1
Factor out the code which handles M-profile lazy FP state preservation
2
Giving these insns their own do_vrint() function allows us
2
from full_vfp_access_check(); accesses to the FPCXT_NS register are
3
to change the rounding mode just once at the start and end
3
a special case which need to do just this part (corresponding in the
4
rather than doing it for every element in the vector.
4
pseudocode to the PreserveFPState() function), and not the full
5
set of actions matching the pseudocode ExecuteFPCheck() which
6
normal FP instructions need to do.
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: 20200616170844.13318-18-peter.maydell@linaro.org
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20201119215617.29887-13-peter.maydell@linaro.org
9
---
12
---
10
target/arm/neon-dp.decode | 8 +++++
13
target/arm/translate-vfp.c.inc | 45 ++++++++++++++++++++--------------
11
target/arm/translate-neon.inc.c | 61 +++++++++++++++++++++++++++++++++
14
1 file changed, 27 insertions(+), 18 deletions(-)
12
target/arm/translate.c | 31 +++--------------
13
3 files changed, 74 insertions(+), 26 deletions(-)
14
15
15
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
16
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/neon-dp.decode
18
--- a/target/arm/translate-vfp.c.inc
18
+++ b/target/arm/neon-dp.decode
19
+++ b/target/arm/translate-vfp.c.inc
19
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
20
@@ -XXX,XX +XXX,XX @@ static inline long vfp_f16_offset(unsigned reg, bool top)
20
SHA1SU1 1111 001 11 . 11 .. 10 .... 0 0111 0 . 0 .... @2misc_q1
21
return offs;
21
SHA256SU0 1111 001 11 . 11 .. 10 .... 0 0111 1 . 0 .... @2misc_q1
22
}
22
23
23
+ VRINTN 1111 001 11 . 11 .. 10 .... 0 1000 . . 0 .... @2misc
24
+/*
24
VRINTX 1111 001 11 . 11 .. 10 .... 0 1001 . . 0 .... @2misc
25
+ * Generate code for M-profile lazy FP state preservation if needed;
25
+ VRINTA 1111 001 11 . 11 .. 10 .... 0 1010 . . 0 .... @2misc
26
+ * this corresponds to the pseudocode PreserveFPState() function.
26
+ VRINTZ 1111 001 11 . 11 .. 10 .... 0 1011 . . 0 .... @2misc
27
+ */
27
28
+static void gen_preserve_fp_state(DisasContext *s)
28
VCVT_F16_F32 1111 001 11 . 11 .. 10 .... 0 1100 0 . 0 .... @2misc_q0
29
+
30
+ VRINTM 1111 001 11 . 11 .. 10 .... 0 1101 . . 0 .... @2misc
31
+
32
VCVT_F32_F16 1111 001 11 . 11 .. 10 .... 0 1110 0 . 0 .... @2misc_q0
33
34
+ VRINTP 1111 001 11 . 11 .. 10 .... 0 1111 . . 0 .... @2misc
35
+
36
VRECPE 1111 001 11 . 11 .. 11 .... 0 1000 . . 0 .... @2misc
37
VRSQRTE 1111 001 11 . 11 .. 11 .... 0 1001 . . 0 .... @2misc
38
VRECPE_F 1111 001 11 . 11 .. 11 .... 0 1010 . . 0 .... @2misc
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_FP_CMP0(VCGE0_F, gen_helper_neon_cge_f32, FWD)
44
DO_FP_CMP0(VCEQ0_F, gen_helper_neon_ceq_f32, FWD)
45
DO_FP_CMP0(VCLE0_F, gen_helper_neon_cge_f32, REV)
46
DO_FP_CMP0(VCLT0_F, gen_helper_neon_cgt_f32, REV)
47
+
48
+static bool do_vrint(DisasContext *s, arg_2misc *a, int rmode)
49
+{
29
+{
50
+ /*
30
+ if (s->v7m_lspact) {
51
+ * Handle a VRINT* operation by iterating 32 bits at a time,
31
+ /*
52
+ * with a specified rounding mode in operation.
32
+ * Lazy state saving affects external memory and also the NVIC,
53
+ */
33
+ * so we must mark it as an IO operation for icount (and cause
54
+ int pass;
34
+ * this to be the last insn in the TB).
55
+ TCGv_ptr fpst;
35
+ */
56
+ TCGv_i32 tcg_rmode;
36
+ if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
57
+
37
+ s->base.is_jmp = DISAS_UPDATE_EXIT;
58
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
38
+ gen_io_start();
59
+ !arm_dc_feature(s, ARM_FEATURE_V8)) {
39
+ }
60
+ return false;
40
+ gen_helper_v7m_preserve_fp_state(cpu_env);
41
+ /*
42
+ * If the preserve_fp_state helper doesn't throw an exception
43
+ * then it will clear LSPACT; we don't need to repeat this for
44
+ * any further FP insns in this TB.
45
+ */
46
+ s->v7m_lspact = false;
61
+ }
47
+ }
62
+
63
+ /* UNDEF accesses to D16-D31 if they don't exist. */
64
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
65
+ ((a->vd | a->vm) & 0x10)) {
66
+ return false;
67
+ }
68
+
69
+ if (a->size != 2) {
70
+ /* TODO: FP16 will be the size == 1 case */
71
+ return false;
72
+ }
73
+
74
+ if ((a->vd | a->vm) & a->q) {
75
+ return false;
76
+ }
77
+
78
+ if (!vfp_access_check(s)) {
79
+ return true;
80
+ }
81
+
82
+ fpst = get_fpstatus_ptr(1);
83
+ tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
84
+ gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode, cpu_env);
85
+ for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
86
+ TCGv_i32 tmp = neon_load_reg(a->vm, pass);
87
+ gen_helper_rints(tmp, tmp, fpst);
88
+ neon_store_reg(a->vd, pass, tmp);
89
+ }
90
+ gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode, cpu_env);
91
+ tcg_temp_free_i32(tcg_rmode);
92
+ tcg_temp_free_ptr(fpst);
93
+
94
+ return true;
95
+}
48
+}
96
+
49
+
97
+#define DO_VRINT(INSN, RMODE) \
50
/*
98
+ static bool trans_##INSN(DisasContext *s, arg_2misc *a) \
51
* Check that VFP access is enabled. If it is, do the necessary
99
+ { \
52
* M-profile lazy-FP handling and then return true.
100
+ return do_vrint(s, a, RMODE); \
53
@@ -XXX,XX +XXX,XX @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
101
+ }
54
/* Handle M-profile lazy FP state mechanics */
102
+
55
103
+DO_VRINT(VRINTN, FPROUNDING_TIEEVEN)
56
/* Trigger lazy-state preservation if necessary */
104
+DO_VRINT(VRINTA, FPROUNDING_TIEAWAY)
57
- if (s->v7m_lspact) {
105
+DO_VRINT(VRINTZ, FPROUNDING_ZERO)
58
- /*
106
+DO_VRINT(VRINTM, FPROUNDING_NEGINF)
59
- * Lazy state saving affects external memory and also the NVIC,
107
+DO_VRINT(VRINTP, FPROUNDING_POSINF)
60
- * so we must mark it as an IO operation for icount (and cause
108
diff --git a/target/arm/translate.c b/target/arm/translate.c
61
- * this to be the last insn in the TB).
109
index XXXXXXX..XXXXXXX 100644
62
- */
110
--- a/target/arm/translate.c
63
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
111
+++ b/target/arm/translate.c
64
- s->base.is_jmp = DISAS_UPDATE_EXIT;
112
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
65
- gen_io_start();
113
case NEON_2RM_VCEQ0_F:
66
- }
114
case NEON_2RM_VCLE0_F:
67
- gen_helper_v7m_preserve_fp_state(cpu_env);
115
case NEON_2RM_VCLT0_F:
68
- /*
116
+ case NEON_2RM_VRINTN:
69
- * If the preserve_fp_state helper doesn't throw an exception
117
+ case NEON_2RM_VRINTA:
70
- * then it will clear LSPACT; we don't need to repeat this for
118
+ case NEON_2RM_VRINTM:
71
- * any further FP insns in this TB.
119
+ case NEON_2RM_VRINTP:
72
- */
120
+ case NEON_2RM_VRINTZ:
73
- s->v7m_lspact = false;
121
/* handled by decodetree */
74
- }
122
return 1;
75
+ gen_preserve_fp_state(s);
123
case NEON_2RM_VTRN:
76
124
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
77
/* Update ownership of FP context: set FPCCR.S to match current state */
125
}
78
if (s->v8m_fpccr_s_wrong) {
126
neon_store_reg(rm, pass, tmp2);
127
break;
128
- case NEON_2RM_VRINTN:
129
- case NEON_2RM_VRINTA:
130
- case NEON_2RM_VRINTM:
131
- case NEON_2RM_VRINTP:
132
- case NEON_2RM_VRINTZ:
133
- {
134
- TCGv_i32 tcg_rmode;
135
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
136
- int rmode;
137
-
138
- if (op == NEON_2RM_VRINTZ) {
139
- rmode = FPROUNDING_ZERO;
140
- } else {
141
- rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1];
142
- }
143
-
144
- tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
145
- gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
146
- cpu_env);
147
- gen_helper_rints(tmp, tmp, fpstatus);
148
- gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
149
- cpu_env);
150
- tcg_temp_free_ptr(fpstatus);
151
- tcg_temp_free_i32(tcg_rmode);
152
- break;
153
- }
154
case NEON_2RM_VCVTAU:
155
case NEON_2RM_VCVTAS:
156
case NEON_2RM_VCVTNU:
157
--
79
--
158
2.20.1
80
2.20.1
159
81
160
82
diff view generated by jsdifflib
1
Convert the fp-compare-with-zero insns in the Neon 2-reg-misc group to
1
Implement the new-in-v8.1M FPCXT_S floating point system register.
2
decodetree.
2
This is for saving and restoring the secure floating point context,
3
and it reads and writes bits [27:0] from the FPSCR and the
4
CONTROL.SFPA bit in bit [31].
3
5
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200616170844.13318-17-peter.maydell@linaro.org
8
Message-id: 20201119215617.29887-14-peter.maydell@linaro.org
7
---
9
---
8
target/arm/neon-dp.decode | 6 ++++
10
target/arm/translate-vfp.c.inc | 58 ++++++++++++++++++++++++++++++++++
9
target/arm/translate-neon.inc.c | 28 ++++++++++++++++++
11
1 file changed, 58 insertions(+)
10
target/arm/translate.c | 50 ++++-----------------------------
11
3 files changed, 39 insertions(+), 45 deletions(-)
12
12
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
13
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
15
--- a/target/arm/translate-vfp.c.inc
16
+++ b/target/arm/neon-dp.decode
16
+++ b/target/arm/translate-vfp.c.inc
17
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
17
@@ -XXX,XX +XXX,XX @@ static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
18
VABS 1111 001 11 . 11 .. 01 .... 0 0110 . . 0 .... @2misc
18
return false;
19
VNEG 1111 001 11 . 11 .. 01 .... 0 0111 . . 0 .... @2misc
19
}
20
20
break;
21
+ VCGT0_F 1111 001 11 . 11 .. 01 .... 0 1000 . . 0 .... @2misc
21
+ case ARM_VFP_FPCXT_S:
22
+ VCGE0_F 1111 001 11 . 11 .. 01 .... 0 1001 . . 0 .... @2misc
22
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
23
+ VCEQ0_F 1111 001 11 . 11 .. 01 .... 0 1010 . . 0 .... @2misc
23
+ return false;
24
+ VCLE0_F 1111 001 11 . 11 .. 01 .... 0 1011 . . 0 .... @2misc
24
+ }
25
+ VCLT0_F 1111 001 11 . 11 .. 01 .... 0 1100 . . 0 .... @2misc
25
+ if (!s->v8m_secure) {
26
+
26
+ return false;
27
VABS_F 1111 001 11 . 11 .. 01 .... 0 1110 . . 0 .... @2misc
27
+ }
28
VNEG_F 1111 001 11 . 11 .. 01 .... 0 1111 . . 0 .... @2misc
28
+ break;
29
29
default:
30
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
30
return FPSysRegCheckFailed;
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/translate-neon.inc.c
33
+++ b/target/arm/translate-neon.inc.c
34
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTX(DisasContext *s, arg_2misc *a)
35
}
31
}
36
return do_2misc_fp(s, a, gen_helper_rints_exact);
32
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
37
}
33
tcg_temp_free_i32(tmp);
38
+
34
break;
39
+#define WRAP_FP_CMP0_FWD(WRAPNAME, FUNC) \
35
}
40
+ static void WRAPNAME(TCGv_i32 d, TCGv_i32 m, TCGv_ptr fpst) \
36
+ case ARM_VFP_FPCXT_S:
41
+ { \
37
+ {
42
+ TCGv_i32 zero = tcg_const_i32(0); \
38
+ TCGv_i32 sfpa, control, fpscr;
43
+ FUNC(d, m, zero, fpst); \
39
+ /* Set FPSCR[27:0] and CONTROL.SFPA from value */
44
+ tcg_temp_free_i32(zero); \
40
+ tmp = loadfn(s, opaque);
41
+ sfpa = tcg_temp_new_i32();
42
+ tcg_gen_shri_i32(sfpa, tmp, 31);
43
+ control = load_cpu_field(v7m.control[M_REG_S]);
44
+ tcg_gen_deposit_i32(control, control, sfpa,
45
+ R_V7M_CONTROL_SFPA_SHIFT, 1);
46
+ store_cpu_field(control, v7m.control[M_REG_S]);
47
+ fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
48
+ tcg_gen_andi_i32(fpscr, fpscr, FPCR_NZCV_MASK);
49
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
50
+ tcg_gen_or_i32(fpscr, fpscr, tmp);
51
+ store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
52
+ tcg_temp_free_i32(tmp);
53
+ tcg_temp_free_i32(sfpa);
54
+ break;
45
+ }
55
+ }
46
+#define WRAP_FP_CMP0_REV(WRAPNAME, FUNC) \
56
default:
47
+ static void WRAPNAME(TCGv_i32 d, TCGv_i32 m, TCGv_ptr fpst) \
57
g_assert_not_reached();
48
+ { \
58
}
49
+ TCGv_i32 zero = tcg_const_i32(0); \
59
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
50
+ FUNC(d, zero, m, fpst); \
60
tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
51
+ tcg_temp_free_i32(zero); \
61
storefn(s, opaque, tmp);
62
break;
63
+ case ARM_VFP_FPCXT_S:
64
+ {
65
+ TCGv_i32 control, sfpa, fpscr;
66
+ /* Bits [27:0] from FPSCR, bit [31] from CONTROL.SFPA */
67
+ tmp = tcg_temp_new_i32();
68
+ sfpa = tcg_temp_new_i32();
69
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
70
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
71
+ control = load_cpu_field(v7m.control[M_REG_S]);
72
+ tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
73
+ tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
74
+ tcg_gen_or_i32(tmp, tmp, sfpa);
75
+ tcg_temp_free_i32(sfpa);
76
+ /*
77
+ * Store result before updating FPSCR etc, in case
78
+ * it is a memory write which causes an exception.
79
+ */
80
+ storefn(s, opaque, tmp);
81
+ /*
82
+ * Now we must reset FPSCR from FPDSCR_NS, and clear
83
+ * CONTROL.SFPA; so we'll end the TB here.
84
+ */
85
+ tcg_gen_andi_i32(control, control, ~R_V7M_CONTROL_SFPA_MASK);
86
+ store_cpu_field(control, v7m.control[M_REG_S]);
87
+ fpscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
88
+ gen_helper_vfp_set_fpscr(cpu_env, fpscr);
89
+ tcg_temp_free_i32(fpscr);
90
+ gen_lookup_tb(s);
91
+ break;
52
+ }
92
+ }
53
+
93
default:
54
+#define DO_FP_CMP0(INSN, FUNC, REV) \
94
g_assert_not_reached();
55
+ WRAP_FP_CMP0_##REV(gen_##INSN, FUNC) \
95
}
56
+ static bool trans_##INSN(DisasContext *s, arg_2misc *a) \
57
+ { \
58
+ return do_2misc_fp(s, a, gen_##INSN); \
59
+ }
60
+
61
+DO_FP_CMP0(VCGT0_F, gen_helper_neon_cgt_f32, FWD)
62
+DO_FP_CMP0(VCGE0_F, gen_helper_neon_cge_f32, FWD)
63
+DO_FP_CMP0(VCEQ0_F, gen_helper_neon_ceq_f32, FWD)
64
+DO_FP_CMP0(VCLE0_F, gen_helper_neon_cge_f32, REV)
65
+DO_FP_CMP0(VCLT0_F, gen_helper_neon_cgt_f32, REV)
66
diff --git a/target/arm/translate.c b/target/arm/translate.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/translate.c
69
+++ b/target/arm/translate.c
70
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
71
case NEON_2RM_VCVT_SF:
72
case NEON_2RM_VCVT_UF:
73
case NEON_2RM_VRINTX:
74
+ case NEON_2RM_VCGT0_F:
75
+ case NEON_2RM_VCGE0_F:
76
+ case NEON_2RM_VCEQ0_F:
77
+ case NEON_2RM_VCLE0_F:
78
+ case NEON_2RM_VCLT0_F:
79
/* handled by decodetree */
80
return 1;
81
case NEON_2RM_VTRN:
82
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
83
for (pass = 0; pass < (q ? 4 : 2); pass++) {
84
tmp = neon_load_reg(rm, pass);
85
switch (op) {
86
- case NEON_2RM_VCGT0_F:
87
- {
88
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
89
- tmp2 = tcg_const_i32(0);
90
- gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
91
- tcg_temp_free_i32(tmp2);
92
- tcg_temp_free_ptr(fpstatus);
93
- break;
94
- }
95
- case NEON_2RM_VCGE0_F:
96
- {
97
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
98
- tmp2 = tcg_const_i32(0);
99
- gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
100
- tcg_temp_free_i32(tmp2);
101
- tcg_temp_free_ptr(fpstatus);
102
- break;
103
- }
104
- case NEON_2RM_VCEQ0_F:
105
- {
106
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
107
- tmp2 = tcg_const_i32(0);
108
- gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
109
- tcg_temp_free_i32(tmp2);
110
- tcg_temp_free_ptr(fpstatus);
111
- break;
112
- }
113
- case NEON_2RM_VCLE0_F:
114
- {
115
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
116
- tmp2 = tcg_const_i32(0);
117
- gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
118
- tcg_temp_free_i32(tmp2);
119
- tcg_temp_free_ptr(fpstatus);
120
- break;
121
- }
122
- case NEON_2RM_VCLT0_F:
123
- {
124
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
125
- tmp2 = tcg_const_i32(0);
126
- gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
127
- tcg_temp_free_i32(tmp2);
128
- tcg_temp_free_ptr(fpstatus);
129
- break;
130
- }
131
case NEON_2RM_VSWP:
132
tmp2 = neon_load_reg(rd, pass);
133
neon_store_reg(rm, pass, tmp2);
134
--
96
--
135
2.20.1
97
2.20.1
136
98
137
99
diff view generated by jsdifflib
1
Convert the Neon 2-reg-misc insns which are implemented with
1
The FPDSCR register has a similar layout to the FPSCR. In v8.1M it
2
simple calls to functions that take the input, output and
2
gains new fields FZ16 (if half-precision floating point is supported)
3
fpstatus pointer.
3
and LTPSIZE (always reads as 4). Update the reset value and the code
4
that handles writes to this register accordingly.
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: 20200616170844.13318-16-peter.maydell@linaro.org
8
Message-id: 20201119215617.29887-16-peter.maydell@linaro.org
8
---
9
---
9
target/arm/translate.h | 1 +
10
target/arm/cpu.h | 5 +++++
10
target/arm/neon-dp.decode | 8 +++++
11
hw/intc/armv7m_nvic.c | 9 ++++++++-
11
target/arm/translate-neon.inc.c | 62 +++++++++++++++++++++++++++++++++
12
target/arm/cpu.c | 3 +++
12
target/arm/translate.c | 56 ++++-------------------------
13
3 files changed, 16 insertions(+), 1 deletion(-)
13
4 files changed, 78 insertions(+), 49 deletions(-)
14
14
15
diff --git a/target/arm/translate.h b/target/arm/translate.h
15
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate.h
17
--- a/target/arm/cpu.h
18
+++ b/target/arm/translate.h
18
+++ b/target/arm/cpu.h
19
@@ -XXX,XX +XXX,XX @@ typedef void NeonGenNarrowFn(TCGv_i32, TCGv_i64);
19
@@ -XXX,XX +XXX,XX @@ void vfp_set_fpscr(CPUARMState *env, uint32_t val);
20
typedef void NeonGenNarrowEnvFn(TCGv_i32, TCGv_ptr, TCGv_i64);
20
#define FPCR_IXE (1 << 12) /* Inexact exception trap enable */
21
typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32);
21
#define FPCR_IDE (1 << 15) /* Input Denormal exception trap enable */
22
typedef void NeonGenTwoOpWidenFn(TCGv_i64, TCGv_i32, TCGv_i32);
22
#define FPCR_FZ16 (1 << 19) /* ARMv8.2+, FP16 flush-to-zero */
23
+typedef void NeonGenOneSingleOpFn(TCGv_i32, TCGv_i32, TCGv_ptr);
23
+#define FPCR_RMODE_MASK (3 << 22) /* Rounding mode */
24
typedef void NeonGenTwoSingleOpFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
24
#define FPCR_FZ (1 << 24) /* Flush-to-zero enable bit */
25
typedef void NeonGenTwoDoubleOpFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr);
25
#define FPCR_DN (1 << 25) /* Default NaN enable bit */
26
typedef void NeonGenOne64OpFn(TCGv_i64, TCGv_i64);
26
+#define FPCR_AHP (1 << 26) /* Alternative half-precision */
27
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
27
#define FPCR_QC (1 << 27) /* Cumulative saturation bit */
28
#define FPCR_V (1 << 28) /* FP overflow flag */
29
#define FPCR_C (1 << 29) /* FP carry flag */
30
#define FPCR_Z (1 << 30) /* FP zero flag */
31
#define FPCR_N (1 << 31) /* FP negative flag */
32
33
+#define FPCR_LTPSIZE_SHIFT 16 /* LTPSIZE, M-profile only */
34
+#define FPCR_LTPSIZE_MASK (7 << FPCR_LTPSIZE_SHIFT)
35
+
36
#define FPCR_NZCV_MASK (FPCR_N | FPCR_Z | FPCR_C | FPCR_V)
37
#define FPCR_NZCVQC_MASK (FPCR_NZCV_MASK | FPCR_QC)
38
39
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
28
index XXXXXXX..XXXXXXX 100644
40
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/neon-dp.decode
41
--- a/hw/intc/armv7m_nvic.c
30
+++ b/target/arm/neon-dp.decode
42
+++ b/hw/intc/armv7m_nvic.c
31
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
43
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
32
SHA1SU1 1111 001 11 . 11 .. 10 .... 0 0111 0 . 0 .... @2misc_q1
44
break;
33
SHA256SU0 1111 001 11 . 11 .. 10 .... 0 0111 1 . 0 .... @2misc_q1
45
case 0xf3c: /* FPDSCR */
34
46
if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
35
+ VRINTX 1111 001 11 . 11 .. 10 .... 0 1001 . . 0 .... @2misc
47
- value &= 0x07c00000;
36
+
48
+ uint32_t mask = FPCR_AHP | FPCR_DN | FPCR_FZ | FPCR_RMODE_MASK;
37
VCVT_F16_F32 1111 001 11 . 11 .. 10 .... 0 1100 0 . 0 .... @2misc_q0
49
+ if (cpu_isar_feature(any_fp16, cpu)) {
38
VCVT_F32_F16 1111 001 11 . 11 .. 10 .... 0 1110 0 . 0 .... @2misc_q0
50
+ mask |= FPCR_FZ16;
39
51
+ }
40
VRECPE 1111 001 11 . 11 .. 11 .... 0 1000 . . 0 .... @2misc
52
+ value &= mask;
41
VRSQRTE 1111 001 11 . 11 .. 11 .... 0 1001 . . 0 .... @2misc
53
+ if (cpu_isar_feature(aa32_lob, cpu)) {
42
+ VRECPE_F 1111 001 11 . 11 .. 11 .... 0 1010 . . 0 .... @2misc
54
+ value |= 4 << FPCR_LTPSIZE_SHIFT;
43
+ VRSQRTE_F 1111 001 11 . 11 .. 11 .... 0 1011 . . 0 .... @2misc
55
+ }
44
+ VCVT_FS 1111 001 11 . 11 .. 11 .... 0 1100 . . 0 .... @2misc
56
cpu->env.v7m.fpdscr[attrs.secure] = value;
45
+ VCVT_FU 1111 001 11 . 11 .. 11 .... 0 1101 . . 0 .... @2misc
57
}
46
+ VCVT_SF 1111 001 11 . 11 .. 11 .... 0 1110 . . 0 .... @2misc
58
break;
47
+ VCVT_UF 1111 001 11 . 11 .. 11 .... 0 1111 . . 0 .... @2misc
59
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
48
]
49
50
# Subgroup for size != 0b11
51
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
52
index XXXXXXX..XXXXXXX 100644
60
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/translate-neon.inc.c
61
--- a/target/arm/cpu.c
54
+++ b/target/arm/translate-neon.inc.c
62
+++ b/target/arm/cpu.c
55
@@ -XXX,XX +XXX,XX @@ static bool trans_VQNEG(DisasContext *s, arg_2misc *a)
63
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_reset(DeviceState *dev)
56
};
64
* always reset to 4.
57
return do_2misc(s, a, fn[a->size]);
65
*/
58
}
66
env->v7m.ltpsize = 4;
59
+
67
+ /* The LTPSIZE field in FPDSCR is constant and reads as 4. */
60
+static bool do_2misc_fp(DisasContext *s, arg_2misc *a,
68
+ env->v7m.fpdscr[M_REG_NS] = 4 << FPCR_LTPSIZE_SHIFT;
61
+ NeonGenOneSingleOpFn *fn)
69
+ env->v7m.fpdscr[M_REG_S] = 4 << FPCR_LTPSIZE_SHIFT;
62
+{
70
}
63
+ int pass;
71
64
+ TCGv_ptr fpst;
72
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
65
+
66
+ /* Handle a 2-reg-misc operation by iterating 32 bits at a time */
67
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
68
+ return false;
69
+ }
70
+
71
+ /* UNDEF accesses to D16-D31 if they don't exist. */
72
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
73
+ ((a->vd | a->vm) & 0x10)) {
74
+ return false;
75
+ }
76
+
77
+ if (a->size != 2) {
78
+ /* TODO: FP16 will be the size == 1 case */
79
+ return false;
80
+ }
81
+
82
+ if ((a->vd | a->vm) & a->q) {
83
+ return false;
84
+ }
85
+
86
+ if (!vfp_access_check(s)) {
87
+ return true;
88
+ }
89
+
90
+ fpst = get_fpstatus_ptr(1);
91
+ for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
92
+ TCGv_i32 tmp = neon_load_reg(a->vm, pass);
93
+ fn(tmp, tmp, fpst);
94
+ neon_store_reg(a->vd, pass, tmp);
95
+ }
96
+ tcg_temp_free_ptr(fpst);
97
+
98
+ return true;
99
+}
100
+
101
+#define DO_2MISC_FP(INSN, FUNC) \
102
+ static bool trans_##INSN(DisasContext *s, arg_2misc *a) \
103
+ { \
104
+ return do_2misc_fp(s, a, FUNC); \
105
+ }
106
+
107
+DO_2MISC_FP(VRECPE_F, gen_helper_recpe_f32)
108
+DO_2MISC_FP(VRSQRTE_F, gen_helper_rsqrte_f32)
109
+DO_2MISC_FP(VCVT_FS, gen_helper_vfp_sitos)
110
+DO_2MISC_FP(VCVT_FU, gen_helper_vfp_uitos)
111
+DO_2MISC_FP(VCVT_SF, gen_helper_vfp_tosizs)
112
+DO_2MISC_FP(VCVT_UF, gen_helper_vfp_touizs)
113
+
114
+static bool trans_VRINTX(DisasContext *s, arg_2misc *a)
115
+{
116
+ if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
117
+ return false;
118
+ }
119
+ return do_2misc_fp(s, a, gen_helper_rints_exact);
120
+}
121
diff --git a/target/arm/translate.c b/target/arm/translate.c
122
index XXXXXXX..XXXXXXX 100644
123
--- a/target/arm/translate.c
124
+++ b/target/arm/translate.c
125
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
126
case NEON_2RM_VRSQRTE:
127
case NEON_2RM_VQABS:
128
case NEON_2RM_VQNEG:
129
+ case NEON_2RM_VRECPE_F:
130
+ case NEON_2RM_VRSQRTE_F:
131
+ case NEON_2RM_VCVT_FS:
132
+ case NEON_2RM_VCVT_FU:
133
+ case NEON_2RM_VCVT_SF:
134
+ case NEON_2RM_VCVT_UF:
135
+ case NEON_2RM_VRINTX:
136
/* handled by decodetree */
137
return 1;
138
case NEON_2RM_VTRN:
139
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
140
tcg_temp_free_i32(tcg_rmode);
141
break;
142
}
143
- case NEON_2RM_VRINTX:
144
- {
145
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
146
- gen_helper_rints_exact(tmp, tmp, fpstatus);
147
- tcg_temp_free_ptr(fpstatus);
148
- break;
149
- }
150
case NEON_2RM_VCVTAU:
151
case NEON_2RM_VCVTAS:
152
case NEON_2RM_VCVTNU:
153
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
154
tcg_temp_free_ptr(fpst);
155
break;
156
}
157
- case NEON_2RM_VRECPE_F:
158
- {
159
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
160
- gen_helper_recpe_f32(tmp, tmp, fpstatus);
161
- tcg_temp_free_ptr(fpstatus);
162
- break;
163
- }
164
- case NEON_2RM_VRSQRTE_F:
165
- {
166
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
167
- gen_helper_rsqrte_f32(tmp, tmp, fpstatus);
168
- tcg_temp_free_ptr(fpstatus);
169
- break;
170
- }
171
- case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
172
- {
173
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
174
- gen_helper_vfp_sitos(tmp, tmp, fpstatus);
175
- tcg_temp_free_ptr(fpstatus);
176
- break;
177
- }
178
- case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
179
- {
180
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
181
- gen_helper_vfp_uitos(tmp, tmp, fpstatus);
182
- tcg_temp_free_ptr(fpstatus);
183
- break;
184
- }
185
- case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
186
- {
187
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
188
- gen_helper_vfp_tosizs(tmp, tmp, fpstatus);
189
- tcg_temp_free_ptr(fpstatus);
190
- break;
191
- }
192
- case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
193
- {
194
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
195
- gen_helper_vfp_touizs(tmp, tmp, fpstatus);
196
- tcg_temp_free_ptr(fpstatus);
197
- break;
198
- }
199
default:
200
/* Reserved op values were caught by the
201
* neon_2rm_sizes[] check earlier.
202
--
73
--
203
2.20.1
74
2.20.1
204
75
205
76
diff view generated by jsdifflib
1
Convert the Neon VQABS and VQNEG insns to decodetree.
1
In v8.0M, on exception entry the registers R0-R3, R12, APSR and EPSR
2
Since these are the only ones which need cpu_env passing to
2
are zeroed for an exception taken to Non-secure state; for an
3
the helper, we wrap the helper rather than creating a whole
3
exception taken to Secure state they become UNKNOWN, and we chose to
4
new do_2misc_env() function.
4
leave them at their previous values.
5
6
In v8.1M the behaviour is specified more tightly and these registers
7
are always zeroed regardless of the security state that the exception
8
targets (see rule R_KPZV). Implement this.
5
9
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200616170844.13318-15-peter.maydell@linaro.org
12
Message-id: 20201119215617.29887-17-peter.maydell@linaro.org
9
---
13
---
10
target/arm/neon-dp.decode | 3 +++
14
target/arm/m_helper.c | 16 ++++++++++++----
11
target/arm/translate-neon.inc.c | 35 +++++++++++++++++++++++++++++++++
15
1 file changed, 12 insertions(+), 4 deletions(-)
12
target/arm/translate.c | 30 ++--------------------------
13
3 files changed, 40 insertions(+), 28 deletions(-)
14
16
15
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
17
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/neon-dp.decode
19
--- a/target/arm/m_helper.c
18
+++ b/target/arm/neon-dp.decode
20
+++ b/target/arm/m_helper.c
19
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
21
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
20
VPADAL_S 1111 001 11 . 11 .. 00 .... 0 1100 . . 0 .... @2misc
22
* Clear registers if necessary to prevent non-secure exception
21
VPADAL_U 1111 001 11 . 11 .. 00 .... 0 1101 . . 0 .... @2misc
23
* code being able to see register values from secure code.
22
24
* Where register values become architecturally UNKNOWN we leave
23
+ VQABS 1111 001 11 . 11 .. 00 .... 0 1110 . . 0 .... @2misc
25
- * them with their previous values.
24
+ VQNEG 1111 001 11 . 11 .. 00 .... 0 1111 . . 0 .... @2misc
26
+ * them with their previous values. v8.1M is tighter than v8.0M
25
+
27
+ * here and always zeroes the caller-saved registers regardless
26
VCGT0 1111 001 11 . 11 .. 01 .... 0 0000 . . 0 .... @2misc
28
+ * of the security state the exception is targeting.
27
VCGE0 1111 001 11 . 11 .. 01 .... 0 0001 . . 0 .... @2misc
29
*/
28
VCEQ0 1111 001 11 . 11 .. 01 .... 0 0010 . . 0 .... @2misc
30
if (arm_feature(env, ARM_FEATURE_M_SECURITY)) {
29
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
31
- if (!targets_secure) {
30
index XXXXXXX..XXXXXXX 100644
32
+ if (!targets_secure || arm_feature(env, ARM_FEATURE_V8_1M)) {
31
--- a/target/arm/translate-neon.inc.c
33
/*
32
+++ b/target/arm/translate-neon.inc.c
34
* Always clear the caller-saved registers (they have been
33
@@ -XXX,XX +XXX,XX @@ static bool trans_VRSQRTE(DisasContext *s, arg_2misc *a)
35
* pushed to the stack earlier in v7m_push_stack()).
34
}
36
@@ -XXX,XX +XXX,XX @@ static void v7m_exception_taken(ARMCPU *cpu, uint32_t lr, bool dotailchain,
35
return do_2misc(s, a, gen_helper_rsqrte_u32);
37
* v7m_push_callee_stack()).
36
}
38
*/
37
+
39
int i;
38
+#define WRAP_1OP_ENV_FN(WRAPNAME, FUNC) \
40
+ /*
39
+ static void WRAPNAME(TCGv_i32 d, TCGv_i32 m) \
41
+ * r4..r11 are callee-saves, zero only if background
40
+ { \
42
+ * state was Secure (EXCRET.S == 1) and exception
41
+ FUNC(d, cpu_env, m); \
43
+ * targets Non-secure state
42
+ }
44
+ */
43
+
45
+ bool zero_callee_saves = !targets_secure &&
44
+WRAP_1OP_ENV_FN(gen_VQABS_s8, gen_helper_neon_qabs_s8)
46
+ (lr & R_V7M_EXCRET_S_MASK);
45
+WRAP_1OP_ENV_FN(gen_VQABS_s16, gen_helper_neon_qabs_s16)
47
46
+WRAP_1OP_ENV_FN(gen_VQABS_s32, gen_helper_neon_qabs_s32)
48
for (i = 0; i < 13; i++) {
47
+WRAP_1OP_ENV_FN(gen_VQNEG_s8, gen_helper_neon_qneg_s8)
49
- /* r4..r11 are callee-saves, zero only if EXCRET.S == 1 */
48
+WRAP_1OP_ENV_FN(gen_VQNEG_s16, gen_helper_neon_qneg_s16)
50
- if (i < 4 || i > 11 || (lr & R_V7M_EXCRET_S_MASK)) {
49
+WRAP_1OP_ENV_FN(gen_VQNEG_s32, gen_helper_neon_qneg_s32)
51
+ if (i < 4 || i > 11 || zero_callee_saves) {
50
+
52
env->regs[i] = 0;
51
+static bool trans_VQABS(DisasContext *s, arg_2misc *a)
53
}
52
+{
54
}
53
+ static NeonGenOneOpFn * const fn[] = {
54
+ gen_VQABS_s8,
55
+ gen_VQABS_s16,
56
+ gen_VQABS_s32,
57
+ NULL,
58
+ };
59
+ return do_2misc(s, a, fn[a->size]);
60
+}
61
+
62
+static bool trans_VQNEG(DisasContext *s, arg_2misc *a)
63
+{
64
+ static NeonGenOneOpFn * const fn[] = {
65
+ gen_VQNEG_s8,
66
+ gen_VQNEG_s16,
67
+ gen_VQNEG_s32,
68
+ NULL,
69
+ };
70
+ return do_2misc(s, a, fn[a->size]);
71
+}
72
diff --git a/target/arm/translate.c b/target/arm/translate.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/target/arm/translate.c
75
+++ b/target/arm/translate.c
76
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
77
case NEON_2RM_VNEG_F:
78
case NEON_2RM_VRECPE:
79
case NEON_2RM_VRSQRTE:
80
+ case NEON_2RM_VQABS:
81
+ case NEON_2RM_VQNEG:
82
/* handled by decodetree */
83
return 1;
84
case NEON_2RM_VTRN:
85
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
86
for (pass = 0; pass < (q ? 4 : 2); pass++) {
87
tmp = neon_load_reg(rm, pass);
88
switch (op) {
89
- case NEON_2RM_VQABS:
90
- switch (size) {
91
- case 0:
92
- gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
93
- break;
94
- case 1:
95
- gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
96
- break;
97
- case 2:
98
- gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
99
- break;
100
- default: abort();
101
- }
102
- break;
103
- case NEON_2RM_VQNEG:
104
- switch (size) {
105
- case 0:
106
- gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
107
- break;
108
- case 1:
109
- gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
110
- break;
111
- case 2:
112
- gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
113
- break;
114
- default: abort();
115
- }
116
- break;
117
case NEON_2RM_VCGT0_F:
118
{
119
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
120
--
55
--
121
2.20.1
56
2.20.1
122
57
123
58
diff view generated by jsdifflib
1
Convert the remaining ops in the Neon 2-reg-misc group which
1
In v8.1M, vector table fetch failures don't set HFSR.FORCED (see rule
2
can be implemented simply with our do_2misc() helper.
2
R_LLRP). (In previous versions of the architecture this was either
3
required or IMPDEF.)
3
4
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200616170844.13318-14-peter.maydell@linaro.org
7
Message-id: 20201119215617.29887-18-peter.maydell@linaro.org
7
---
8
---
8
target/arm/neon-dp.decode | 10 +++++
9
target/arm/m_helper.c | 6 +++++-
9
target/arm/translate-neon.inc.c | 69 +++++++++++++++++++++++++++++++++
10
1 file changed, 5 insertions(+), 1 deletion(-)
10
target/arm/translate.c | 38 ++++--------------
11
3 files changed, 86 insertions(+), 31 deletions(-)
12
11
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
12
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
14
--- a/target/arm/m_helper.c
16
+++ b/target/arm/neon-dp.decode
15
+++ b/target/arm/m_helper.c
17
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
16
@@ -XXX,XX +XXX,XX @@ load_fail:
18
AESMC 1111 001 11 . 11 .. 00 .... 0 0111 0 . 0 .... @2misc_q1
17
* The HardFault is Secure if BFHFNMINS is 0 (meaning that all HFs are
19
AESIMC 1111 001 11 . 11 .. 00 .... 0 0111 1 . 0 .... @2misc_q1
18
* secure); otherwise it targets the same security state as the
20
19
* underlying exception.
21
+ VCLS 1111 001 11 . 11 .. 00 .... 0 1000 . . 0 .... @2misc
20
+ * In v8.1M HardFaults from vector table fetch fails don't set FORCED.
22
+ VCLZ 1111 001 11 . 11 .. 00 .... 0 1001 . . 0 .... @2misc
21
*/
23
+ VCNT 1111 001 11 . 11 .. 00 .... 0 1010 . . 0 .... @2misc
22
if (!(cpu->env.v7m.aircr & R_V7M_AIRCR_BFHFNMINS_MASK)) {
24
+
23
exc_secure = true;
25
VMVN 1111 001 11 . 11 .. 00 .... 0 1011 . . 0 .... @2misc
26
27
VPADAL_S 1111 001 11 . 11 .. 00 .... 0 1100 . . 0 .... @2misc
28
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
29
VABS 1111 001 11 . 11 .. 01 .... 0 0110 . . 0 .... @2misc
30
VNEG 1111 001 11 . 11 .. 01 .... 0 0111 . . 0 .... @2misc
31
32
+ VABS_F 1111 001 11 . 11 .. 01 .... 0 1110 . . 0 .... @2misc
33
+ VNEG_F 1111 001 11 . 11 .. 01 .... 0 1111 . . 0 .... @2misc
34
+
35
VUZP 1111 001 11 . 11 .. 10 .... 0 0010 . . 0 .... @2misc
36
VZIP 1111 001 11 . 11 .. 10 .... 0 0011 . . 0 .... @2misc
37
38
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
39
40
VCVT_F16_F32 1111 001 11 . 11 .. 10 .... 0 1100 0 . 0 .... @2misc_q0
41
VCVT_F32_F16 1111 001 11 . 11 .. 10 .... 0 1110 0 . 0 .... @2misc_q0
42
+
43
+ VRECPE 1111 001 11 . 11 .. 11 .... 0 1000 . . 0 .... @2misc
44
+ VRSQRTE 1111 001 11 . 11 .. 11 .... 0 1001 . . 0 .... @2misc
45
]
46
47
# Subgroup for size != 0b11
48
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/translate-neon.inc.c
51
+++ b/target/arm/translate-neon.inc.c
52
@@ -XXX,XX +XXX,XX @@ static bool trans_VREV16(DisasContext *s, arg_2misc *a)
53
}
24
}
54
return do_2misc(s, a, gen_rev16);
25
- env->v7m.hfsr |= R_V7M_HFSR_VECTTBL_MASK | R_V7M_HFSR_FORCED_MASK;
26
+ env->v7m.hfsr |= R_V7M_HFSR_VECTTBL_MASK;
27
+ if (!arm_feature(env, ARM_FEATURE_V8_1M)) {
28
+ env->v7m.hfsr |= R_V7M_HFSR_FORCED_MASK;
29
+ }
30
armv7m_nvic_set_pending_derived(env->nvic, ARMV7M_EXCP_HARD, exc_secure);
31
return false;
55
}
32
}
56
+
57
+static bool trans_VCLS(DisasContext *s, arg_2misc *a)
58
+{
59
+ static NeonGenOneOpFn * const fn[] = {
60
+ gen_helper_neon_cls_s8,
61
+ gen_helper_neon_cls_s16,
62
+ gen_helper_neon_cls_s32,
63
+ NULL,
64
+ };
65
+ return do_2misc(s, a, fn[a->size]);
66
+}
67
+
68
+static void do_VCLZ_32(TCGv_i32 rd, TCGv_i32 rm)
69
+{
70
+ tcg_gen_clzi_i32(rd, rm, 32);
71
+}
72
+
73
+static bool trans_VCLZ(DisasContext *s, arg_2misc *a)
74
+{
75
+ static NeonGenOneOpFn * const fn[] = {
76
+ gen_helper_neon_clz_u8,
77
+ gen_helper_neon_clz_u16,
78
+ do_VCLZ_32,
79
+ NULL,
80
+ };
81
+ return do_2misc(s, a, fn[a->size]);
82
+}
83
+
84
+static bool trans_VCNT(DisasContext *s, arg_2misc *a)
85
+{
86
+ if (a->size != 0) {
87
+ return false;
88
+ }
89
+ return do_2misc(s, a, gen_helper_neon_cnt_u8);
90
+}
91
+
92
+static bool trans_VABS_F(DisasContext *s, arg_2misc *a)
93
+{
94
+ if (a->size != 2) {
95
+ return false;
96
+ }
97
+ /* TODO: FP16 : size == 1 */
98
+ return do_2misc(s, a, gen_helper_vfp_abss);
99
+}
100
+
101
+static bool trans_VNEG_F(DisasContext *s, arg_2misc *a)
102
+{
103
+ if (a->size != 2) {
104
+ return false;
105
+ }
106
+ /* TODO: FP16 : size == 1 */
107
+ return do_2misc(s, a, gen_helper_vfp_negs);
108
+}
109
+
110
+static bool trans_VRECPE(DisasContext *s, arg_2misc *a)
111
+{
112
+ if (a->size != 2) {
113
+ return false;
114
+ }
115
+ return do_2misc(s, a, gen_helper_recpe_u32);
116
+}
117
+
118
+static bool trans_VRSQRTE(DisasContext *s, arg_2misc *a)
119
+{
120
+ if (a->size != 2) {
121
+ return false;
122
+ }
123
+ return do_2misc(s, a, gen_helper_rsqrte_u32);
124
+}
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 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
130
case NEON_2RM_SHA1SU1:
131
case NEON_2RM_VREV32:
132
case NEON_2RM_VREV16:
133
+ case NEON_2RM_VCLS:
134
+ case NEON_2RM_VCLZ:
135
+ case NEON_2RM_VCNT:
136
+ case NEON_2RM_VABS_F:
137
+ case NEON_2RM_VNEG_F:
138
+ case NEON_2RM_VRECPE:
139
+ case NEON_2RM_VRSQRTE:
140
/* handled by decodetree */
141
return 1;
142
case NEON_2RM_VTRN:
143
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
144
for (pass = 0; pass < (q ? 4 : 2); pass++) {
145
tmp = neon_load_reg(rm, pass);
146
switch (op) {
147
- case NEON_2RM_VCLS:
148
- switch (size) {
149
- case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
150
- case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
151
- case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
152
- default: abort();
153
- }
154
- break;
155
- case NEON_2RM_VCLZ:
156
- switch (size) {
157
- case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
158
- case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
159
- case 2: tcg_gen_clzi_i32(tmp, tmp, 32); break;
160
- default: abort();
161
- }
162
- break;
163
- case NEON_2RM_VCNT:
164
- gen_helper_neon_cnt_u8(tmp, tmp);
165
- break;
166
case NEON_2RM_VQABS:
167
switch (size) {
168
case 0:
169
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
170
tcg_temp_free_ptr(fpstatus);
171
break;
172
}
173
- case NEON_2RM_VABS_F:
174
- gen_helper_vfp_abss(tmp, tmp);
175
- break;
176
- case NEON_2RM_VNEG_F:
177
- gen_helper_vfp_negs(tmp, tmp);
178
- break;
179
case NEON_2RM_VSWP:
180
tmp2 = neon_load_reg(rd, pass);
181
neon_store_reg(rm, pass, tmp2);
182
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
183
tcg_temp_free_ptr(fpst);
184
break;
185
}
186
- case NEON_2RM_VRECPE:
187
- gen_helper_recpe_u32(tmp, tmp);
188
- break;
189
- case NEON_2RM_VRSQRTE:
190
- gen_helper_rsqrte_u32(tmp, tmp);
191
- break;
192
case NEON_2RM_VRECPE_F:
193
{
194
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
195
--
33
--
196
2.20.1
34
2.20.1
197
35
198
36
diff view generated by jsdifflib
1
Convert the Neon VREV64 insn from the 2-reg-misc grouping to decodetree.
1
In v8.1M a REVIDR register is defined, which is at address 0xe00ecfc
2
and is a read-only IMPDEF register providing implementation specific
3
minor revision information, like the v8A REVIDR_EL1. Implement this.
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: 20200616170844.13318-2-peter.maydell@linaro.org
7
Message-id: 20201119215617.29887-19-peter.maydell@linaro.org
6
---
8
---
7
target/arm/neon-dp.decode | 12 ++++++++
9
hw/intc/armv7m_nvic.c | 5 +++++
8
target/arm/translate-neon.inc.c | 50 +++++++++++++++++++++++++++++++++
10
1 file changed, 5 insertions(+)
9
target/arm/translate.c | 24 ++--------------
10
3 files changed, 64 insertions(+), 22 deletions(-)
11
11
12
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
12
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
13
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/neon-dp.decode
14
--- a/hw/intc/armv7m_nvic.c
15
+++ b/target/arm/neon-dp.decode
15
+++ b/hw/intc/armv7m_nvic.c
16
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
16
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
17
vm=%vm_dp vd=%vd_dp size=1
17
}
18
VDUP_scalar 1111 001 1 1 . 11 index:1 100 .... 11 000 q:1 . 0 .... \
18
return val;
19
vm=%vm_dp vd=%vd_dp size=2
19
}
20
+
20
+ case 0xcfc:
21
+ ##################################################################
21
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V8_1M)) {
22
+ # 2-reg-misc grouping:
22
+ goto bad_offset;
23
+ # 1111 001 11 D 11 size:2 opc1:2 Vd:4 0 opc2:4 q:1 M 0 Vm:4
24
+ ##################################################################
25
+
26
+ &2misc vd vm q size
27
+
28
+ @2misc .... ... .. . .. size:2 .. .... . .... q:1 . . .... \
29
+ &2misc vm=%vm_dp vd=%vd_dp
30
+
31
+ VREV64 1111 001 11 . 11 .. 00 .... 0 0000 . . 0 .... @2misc
32
]
33
34
# Subgroup for size != 0b11
35
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/translate-neon.inc.c
38
+++ b/target/arm/translate-neon.inc.c
39
@@ -XXX,XX +XXX,XX @@ static bool trans_VDUP_scalar(DisasContext *s, arg_VDUP_scalar *a)
40
a->q ? 16 : 8, a->q ? 16 : 8);
41
return true;
42
}
43
+
44
+static bool trans_VREV64(DisasContext *s, arg_VREV64 *a)
45
+{
46
+ int pass, half;
47
+
48
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
49
+ return false;
50
+ }
51
+
52
+ /* UNDEF accesses to D16-D31 if they don't exist. */
53
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
54
+ ((a->vd | a->vm) & 0x10)) {
55
+ return false;
56
+ }
57
+
58
+ if ((a->vd | a->vm) & a->q) {
59
+ return false;
60
+ }
61
+
62
+ if (a->size == 3) {
63
+ return false;
64
+ }
65
+
66
+ if (!vfp_access_check(s)) {
67
+ return true;
68
+ }
69
+
70
+ for (pass = 0; pass < (a->q ? 2 : 1); pass++) {
71
+ TCGv_i32 tmp[2];
72
+
73
+ for (half = 0; half < 2; half++) {
74
+ tmp[half] = neon_load_reg(a->vm, pass * 2 + half);
75
+ switch (a->size) {
76
+ case 0:
77
+ tcg_gen_bswap32_i32(tmp[half], tmp[half]);
78
+ break;
79
+ case 1:
80
+ gen_swap_half(tmp[half]);
81
+ break;
82
+ case 2:
83
+ break;
84
+ default:
85
+ g_assert_not_reached();
86
+ }
87
+ }
23
+ }
88
+ neon_store_reg(a->vd, pass * 2, tmp[1]);
24
+ return cpu->revidr;
89
+ neon_store_reg(a->vd, pass * 2 + 1, tmp[0]);
25
case 0xd00: /* CPUID Base. */
90
+ }
26
return cpu->midr;
91
+ return true;
27
case 0xd04: /* Interrupt Control State (ICSR) */
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 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
98
}
99
switch (op) {
100
case NEON_2RM_VREV64:
101
- for (pass = 0; pass < (q ? 2 : 1); pass++) {
102
- tmp = neon_load_reg(rm, pass * 2);
103
- tmp2 = neon_load_reg(rm, pass * 2 + 1);
104
- switch (size) {
105
- case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
106
- case 1: gen_swap_half(tmp); break;
107
- case 2: /* no-op */ break;
108
- default: abort();
109
- }
110
- neon_store_reg(rd, pass * 2 + 1, tmp);
111
- if (size == 2) {
112
- neon_store_reg(rd, pass * 2, tmp2);
113
- } else {
114
- switch (size) {
115
- case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
116
- case 1: gen_swap_half(tmp2); break;
117
- default: abort();
118
- }
119
- neon_store_reg(rd, pass * 2, tmp2);
120
- }
121
- }
122
- break;
123
+ /* handled by decodetree */
124
+ return 1;
125
case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
126
case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
127
for (pass = 0; pass < q + 1; pass++) {
128
--
28
--
129
2.20.1
29
2.20.1
130
30
131
31
diff view generated by jsdifflib
1
All the other typedefs like these spell "Op" with a lowercase 'p';
1
In v8.1M a new exception return check is added which may cause a NOCP
2
remane the NeonGenTwoSingleOPFn and NeonGenTwoDoubleOPFn typedefs to
2
UsageFault (see rule R_XLTP): before we clear s0..s15 and the FPSCR
3
match.
3
we must check whether access to CP10 from the Security state of the
4
returning exception is disabled; if it is then we must take a fault.
5
6
(Note that for our implementation CPPWR is always RAZ/WI and so can
7
never cause CP10 accesses to fail.)
8
9
The other v8.1M change to this register-clearing code is that if MVE
10
is implemented VPR must also be cleared, so add a TODO comment to
11
that effect.
4
12
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200616170844.13318-11-peter.maydell@linaro.org
15
Message-id: 20201119215617.29887-20-peter.maydell@linaro.org
8
---
16
---
9
target/arm/translate.h | 4 ++--
17
target/arm/m_helper.c | 22 +++++++++++++++++++++-
10
target/arm/translate-a64.c | 4 ++--
18
1 file changed, 21 insertions(+), 1 deletion(-)
11
target/arm/translate-neon.inc.c | 2 +-
12
3 files changed, 5 insertions(+), 5 deletions(-)
13
19
14
diff --git a/target/arm/translate.h b/target/arm/translate.h
20
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
15
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/translate.h
22
--- a/target/arm/m_helper.c
17
+++ b/target/arm/translate.h
23
+++ b/target/arm/m_helper.c
18
@@ -XXX,XX +XXX,XX @@ typedef void NeonGenNarrowFn(TCGv_i32, TCGv_i64);
24
@@ -XXX,XX +XXX,XX @@ static void do_v7m_exception_exit(ARMCPU *cpu)
19
typedef void NeonGenNarrowEnvFn(TCGv_i32, TCGv_ptr, TCGv_i64);
25
v7m_exception_taken(cpu, excret, true, false);
20
typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32);
26
return;
21
typedef void NeonGenTwoOpWidenFn(TCGv_i64, TCGv_i32, TCGv_i32);
27
} else {
22
-typedef void NeonGenTwoSingleOPFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
28
- /* Clear s0..s15 and FPSCR */
23
-typedef void NeonGenTwoDoubleOPFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr);
29
+ if (arm_feature(env, ARM_FEATURE_V8_1M)) {
24
+typedef void NeonGenTwoSingleOpFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
30
+ /* v8.1M adds this NOCP check */
25
+typedef void NeonGenTwoDoubleOpFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr);
31
+ bool nsacr_pass = exc_secure ||
26
typedef void NeonGenOne64OpFn(TCGv_i64, TCGv_i64);
32
+ extract32(env->v7m.nsacr, 10, 1);
27
typedef void CryptoTwoOpFn(TCGv_ptr, TCGv_ptr);
33
+ bool cpacr_pass = v7m_cpacr_pass(env, exc_secure, true);
28
typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
34
+ if (!nsacr_pass) {
29
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
35
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, true);
30
index XXXXXXX..XXXXXXX 100644
36
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_NOCP_MASK;
31
--- a/target/arm/translate-a64.c
37
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
32
+++ b/target/arm/translate-a64.c
38
+ "stackframe: NSACR prevents clearing FPU registers\n");
33
@@ -XXX,XX +XXX,XX @@ static void handle_2misc_fcmp_zero(DisasContext *s, int opcode,
39
+ v7m_exception_taken(cpu, excret, true, false);
34
TCGv_i64 tcg_op = tcg_temp_new_i64();
40
+ } else if (!cpacr_pass) {
35
TCGv_i64 tcg_zero = tcg_const_i64(0);
41
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE,
36
TCGv_i64 tcg_res = tcg_temp_new_i64();
42
+ exc_secure);
37
- NeonGenTwoDoubleOPFn *genfn;
43
+ env->v7m.cfsr[exc_secure] |= R_V7M_CFSR_NOCP_MASK;
38
+ NeonGenTwoDoubleOpFn *genfn;
44
+ qemu_log_mask(CPU_LOG_INT, "...taking UsageFault on existing "
39
bool swap = false;
45
+ "stackframe: CPACR prevents clearing FPU registers\n");
40
int pass;
46
+ v7m_exception_taken(cpu, excret, true, false);
41
47
+ }
42
@@ -XXX,XX +XXX,XX @@ static void handle_2misc_fcmp_zero(DisasContext *s, int opcode,
48
+ }
43
TCGv_i32 tcg_op = tcg_temp_new_i32();
49
+ /* Clear s0..s15 and FPSCR; TODO also VPR when MVE is implemented */
44
TCGv_i32 tcg_zero = tcg_const_i32(0);
50
int i;
45
TCGv_i32 tcg_res = tcg_temp_new_i32();
51
46
- NeonGenTwoSingleOPFn *genfn;
52
for (i = 0; i < 16; i += 2) {
47
+ NeonGenTwoSingleOpFn *genfn;
48
bool swap = false;
49
int pass, maxpasses;
50
51
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/translate-neon.inc.c
54
+++ b/target/arm/translate-neon.inc.c
55
@@ -XXX,XX +XXX,XX @@ static bool trans_VSHLL_U_2sh(DisasContext *s, arg_2reg_shift *a)
56
}
57
58
static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
59
- NeonGenTwoSingleOPFn *fn)
60
+ NeonGenTwoSingleOpFn *fn)
61
{
62
/* FP operations in 2-reg-and-shift group */
63
TCGv_i32 tmp, shiftv;
64
--
53
--
65
2.20.1
54
2.20.1
66
55
67
56
diff view generated by jsdifflib
1
Convert the Neon-2-reg misc crypto ops (AESE, AESMC, SHA1H, SHA1SU1)
1
v8.1M adds new encodings of VLLDM and VLSTM (where bit 7 is set).
2
to decodetree.
2
The only difference is that:
3
* the old T1 encodings UNDEF if the implementation implements 32
4
Dregs (this is currently architecturally impossible for M-profile)
5
* the new T2 encodings have the implementation-defined option to
6
read from memory (discarding the data) or write UNKNOWN values to
7
memory for the stack slots that would be D16-D31
8
9
We choose not to make those accesses, so for us the two
10
instructions behave identically assuming they don't UNDEF.
3
11
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>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200616170844.13318-9-peter.maydell@linaro.org
14
Message-id: 20201119215617.29887-21-peter.maydell@linaro.org
7
---
15
---
8
target/arm/neon-dp.decode | 12 ++++++++
16
target/arm/m-nocp.decode | 2 +-
9
target/arm/translate-neon.inc.c | 42 ++++++++++++++++++++++++++
17
target/arm/translate-vfp.c.inc | 25 +++++++++++++++++++++++++
10
target/arm/translate.c | 52 +++------------------------------
18
2 files changed, 26 insertions(+), 1 deletion(-)
11
3 files changed, 58 insertions(+), 48 deletions(-)
12
19
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
20
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
14
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
22
--- a/target/arm/m-nocp.decode
16
+++ b/target/arm/neon-dp.decode
23
+++ b/target/arm/m-nocp.decode
17
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
24
@@ -XXX,XX +XXX,XX @@
18
&2misc vm=%vm_dp vd=%vd_dp
25
19
@2misc_q0 .... ... .. . .. size:2 .. .... . .... . . . .... \
26
{
20
&2misc vm=%vm_dp vd=%vd_dp q=0
27
# Special cases which do not take an early NOCP: VLLDM and VLSTM
21
+ @2misc_q1 .... ... .. . .. size:2 .. .... . .... . . . .... \
28
- VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 0000 0000
22
+ &2misc vm=%vm_dp vd=%vd_dp q=1
29
+ VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 op:1 000 0000
23
30
# VSCCLRM (new in v8.1M) is similar:
24
VREV64 1111 001 11 . 11 .. 00 .... 0 0000 . . 0 .... @2misc
31
VSCCLRM 1110 1100 1.01 1111 .... 1011 imm:7 0 vd=%vd_dp size=3
25
32
VSCCLRM 1110 1100 1.01 1111 .... 1010 imm:8 vd=%vd_sp size=2
26
VPADDL_S 1111 001 11 . 11 .. 00 .... 0 0100 . . 0 .... @2misc
33
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc
27
VPADDL_U 1111 001 11 . 11 .. 00 .... 0 0101 . . 0 .... @2misc
34
index XXXXXXX..XXXXXXX 100644
28
35
--- a/target/arm/translate-vfp.c.inc
29
+ AESE 1111 001 11 . 11 .. 00 .... 0 0110 0 . 0 .... @2misc_q1
36
+++ b/target/arm/translate-vfp.c.inc
30
+ AESD 1111 001 11 . 11 .. 00 .... 0 0110 1 . 0 .... @2misc_q1
37
@@ -XXX,XX +XXX,XX @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
31
+ AESMC 1111 001 11 . 11 .. 00 .... 0 0111 0 . 0 .... @2misc_q1
38
!arm_dc_feature(s, ARM_FEATURE_V8)) {
32
+ AESIMC 1111 001 11 . 11 .. 00 .... 0 0111 1 . 0 .... @2misc_q1
39
return false;
40
}
33
+
41
+
34
VMVN 1111 001 11 . 11 .. 00 .... 0 1011 . . 0 .... @2misc
42
+ if (a->op) {
35
43
+ /*
36
VPADAL_S 1111 001 11 . 11 .. 00 .... 0 1100 . . 0 .... @2misc
44
+ * T2 encoding ({D0-D31} reglist): v8.1M and up. We choose not
37
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
45
+ * to take the IMPDEF option to make memory accesses to the stack
38
VCLE0 1111 001 11 . 11 .. 01 .... 0 0011 . . 0 .... @2misc
46
+ * slots that correspond to the D16-D31 registers (discarding
39
VCLT0 1111 001 11 . 11 .. 01 .... 0 0100 . . 0 .... @2misc
47
+ * read data and writing UNKNOWN values), so for us the T2
40
48
+ * encoding behaves identically to the T1 encoding.
41
+ SHA1H 1111 001 11 . 11 .. 01 .... 0 0101 1 . 0 .... @2misc_q1
49
+ */
42
+
50
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
43
VABS 1111 001 11 . 11 .. 01 .... 0 0110 . . 0 .... @2misc
51
+ return false;
44
VNEG 1111 001 11 . 11 .. 01 .... 0 0111 . . 0 .... @2misc
52
+ }
45
53
+ } else {
46
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
54
+ /*
47
55
+ * T1 encoding ({D0-D15} reglist); undef if we have 32 Dregs.
48
VSHLL 1111 001 11 . 11 .. 10 .... 0 0110 0 . 0 .... @2misc_q0
56
+ * This is currently architecturally impossible, but we add the
49
57
+ * check to stay in line with the pseudocode. Note that we must
50
+ SHA1SU1 1111 001 11 . 11 .. 10 .... 0 0111 0 . 0 .... @2misc_q1
58
+ * emit code for the UNDEF so it takes precedence over the NOCP.
51
+ SHA256SU0 1111 001 11 . 11 .. 10 .... 0 0111 1 . 0 .... @2misc_q1
59
+ */
52
+
60
+ if (dc_isar_feature(aa32_simd_r32, s)) {
53
VCVT_F16_F32 1111 001 11 . 11 .. 10 .... 0 1100 0 . 0 .... @2misc_q0
61
+ unallocated_encoding(s);
54
VCVT_F32_F16 1111 001 11 . 11 .. 10 .... 0 1110 0 . 0 .... @2misc_q0
62
+ return true;
55
]
63
+ }
56
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/translate-neon.inc.c
59
+++ b/target/arm/translate-neon.inc.c
60
@@ -XXX,XX +XXX,XX @@ static bool trans_VMVN(DisasContext *s, arg_2misc *a)
61
}
62
return do_2misc_vec(s, a, tcg_gen_gvec_not);
63
}
64
+
65
+#define WRAP_2M_3_OOL_FN(WRAPNAME, FUNC, DATA) \
66
+ static void WRAPNAME(unsigned vece, uint32_t rd_ofs, \
67
+ uint32_t rm_ofs, uint32_t oprsz, \
68
+ uint32_t maxsz) \
69
+ { \
70
+ tcg_gen_gvec_3_ool(rd_ofs, rd_ofs, rm_ofs, oprsz, maxsz, \
71
+ DATA, FUNC); \
72
+ }
64
+ }
73
+
65
+
74
+#define WRAP_2M_2_OOL_FN(WRAPNAME, FUNC, DATA) \
66
/*
75
+ static void WRAPNAME(unsigned vece, uint32_t rd_ofs, \
67
* If not secure, UNDEF. We must emit code for this
76
+ uint32_t rm_ofs, uint32_t oprsz, \
68
* rather than returning false so that this takes
77
+ uint32_t maxsz) \
78
+ { \
79
+ tcg_gen_gvec_2_ool(rd_ofs, rm_ofs, oprsz, maxsz, DATA, FUNC); \
80
+ }
81
+
82
+WRAP_2M_3_OOL_FN(gen_AESE, gen_helper_crypto_aese, 0)
83
+WRAP_2M_3_OOL_FN(gen_AESD, gen_helper_crypto_aese, 1)
84
+WRAP_2M_2_OOL_FN(gen_AESMC, gen_helper_crypto_aesmc, 0)
85
+WRAP_2M_2_OOL_FN(gen_AESIMC, gen_helper_crypto_aesmc, 1)
86
+WRAP_2M_2_OOL_FN(gen_SHA1H, gen_helper_crypto_sha1h, 0)
87
+WRAP_2M_2_OOL_FN(gen_SHA1SU1, gen_helper_crypto_sha1su1, 0)
88
+WRAP_2M_2_OOL_FN(gen_SHA256SU0, gen_helper_crypto_sha256su0, 0)
89
+
90
+#define DO_2M_CRYPTO(INSN, FEATURE, SIZE) \
91
+ static bool trans_##INSN(DisasContext *s, arg_2misc *a) \
92
+ { \
93
+ if (!dc_isar_feature(FEATURE, s) || a->size != SIZE) { \
94
+ return false; \
95
+ } \
96
+ return do_2misc_vec(s, a, gen_##INSN); \
97
+ }
98
+
99
+DO_2M_CRYPTO(AESE, aa32_aes, 0)
100
+DO_2M_CRYPTO(AESD, aa32_aes, 0)
101
+DO_2M_CRYPTO(AESMC, aa32_aes, 0)
102
+DO_2M_CRYPTO(AESIMC, aa32_aes, 0)
103
+DO_2M_CRYPTO(SHA1H, aa32_sha1, 2)
104
+DO_2M_CRYPTO(SHA1SU1, aa32_sha1, 2)
105
+DO_2M_CRYPTO(SHA256SU0, aa32_sha2, 2)
106
diff --git a/target/arm/translate.c b/target/arm/translate.c
107
index XXXXXXX..XXXXXXX 100644
108
--- a/target/arm/translate.c
109
+++ b/target/arm/translate.c
110
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
111
{
112
int op;
113
int q;
114
- int rd, rm, rd_ofs, rm_ofs;
115
+ int rd, rm;
116
int size;
117
int pass;
118
int u;
119
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
120
VFP_DREG_D(rd, insn);
121
VFP_DREG_M(rm, insn);
122
size = (insn >> 20) & 3;
123
- rd_ofs = neon_reg_offset(rd, 0);
124
- rm_ofs = neon_reg_offset(rm, 0);
125
126
if ((insn & (1 << 23)) == 0) {
127
/* Three register same length: handled by decodetree */
128
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
129
case NEON_2RM_VCLE0:
130
case NEON_2RM_VCGE0:
131
case NEON_2RM_VCLT0:
132
+ case NEON_2RM_AESE: case NEON_2RM_AESMC:
133
+ case NEON_2RM_SHA1H:
134
+ case NEON_2RM_SHA1SU1:
135
/* handled by decodetree */
136
return 1;
137
case NEON_2RM_VTRN:
138
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
139
goto elementwise;
140
}
141
break;
142
- case NEON_2RM_AESE: case NEON_2RM_AESMC:
143
- if (!dc_isar_feature(aa32_aes, s) || ((rm | rd) & 1)) {
144
- return 1;
145
- }
146
- /*
147
- * Bit 6 is the lowest opcode bit; it distinguishes
148
- * between encryption (AESE/AESMC) and decryption
149
- * (AESD/AESIMC).
150
- */
151
- if (op == NEON_2RM_AESE) {
152
- tcg_gen_gvec_3_ool(vfp_reg_offset(true, rd),
153
- vfp_reg_offset(true, rd),
154
- vfp_reg_offset(true, rm),
155
- 16, 16, extract32(insn, 6, 1),
156
- gen_helper_crypto_aese);
157
- } else {
158
- tcg_gen_gvec_2_ool(vfp_reg_offset(true, rd),
159
- vfp_reg_offset(true, rm),
160
- 16, 16, extract32(insn, 6, 1),
161
- gen_helper_crypto_aesmc);
162
- }
163
- break;
164
- case NEON_2RM_SHA1H:
165
- if (!dc_isar_feature(aa32_sha1, s) || ((rm | rd) & 1)) {
166
- return 1;
167
- }
168
- tcg_gen_gvec_2_ool(rd_ofs, rm_ofs, 16, 16, 0,
169
- gen_helper_crypto_sha1h);
170
- break;
171
- case NEON_2RM_SHA1SU1:
172
- if ((rm | rd) & 1) {
173
- return 1;
174
- }
175
- /* bit 6 (q): set -> SHA256SU0, cleared -> SHA1SU1 */
176
- if (q) {
177
- if (!dc_isar_feature(aa32_sha2, s)) {
178
- return 1;
179
- }
180
- } else if (!dc_isar_feature(aa32_sha1, s)) {
181
- return 1;
182
- }
183
- tcg_gen_gvec_2_ool(rd_ofs, rm_ofs, 16, 16, 0,
184
- q ? gen_helper_crypto_sha256su0
185
- : gen_helper_crypto_sha1su1);
186
- break;
187
188
default:
189
elementwise:
190
--
69
--
191
2.20.1
70
2.20.1
192
71
193
72
diff view generated by jsdifflib
1
Since commit ba3e7926691ed3 it has been unnecessary for target code
1
v8.1M introduces a new TRD flag in the CCR register, which enables
2
to call gen_io_end() after an IO instruction in icount mode; it is
2
checking for stack frame integrity signatures on SG instructions.
3
sufficient to call gen_io_start() before it and to force the end of
3
This bit is not banked, and is always RAZ/WI to Non-secure code.
4
the TB.
4
Adjust the code for handling CCR reads and writes to handle this.
5
6
Many now-unnecessary calls to gen_io_end() were removed in commit
7
9e9b10c6491153b, but some were missed or accidentally added later.
8
Remove unneeded calls from the arm target:
9
10
* the call in the handling of exception-return-via-LDM is
11
unnecessary, and the code is already forcing end-of-TB
12
* the call in the VFP access check code is more complicated:
13
we weren't ending the TB, so we need to add the code to
14
force that by setting DISAS_UPDATE
15
* the doc comment for ARM_CP_IO doesn't need to mention
16
gen_io_end() any more
17
5
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Reviewed-by: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>
8
Message-id: 20201119215617.29887-23-peter.maydell@linaro.org
22
Message-id: 20200619170324.12093-1-peter.maydell@linaro.org
23
---
9
---
24
target/arm/cpu.h | 2 +-
10
target/arm/cpu.h | 2 ++
25
target/arm/translate-vfp.inc.c | 7 +++----
11
hw/intc/armv7m_nvic.c | 26 ++++++++++++++++++--------
26
target/arm/translate.c | 3 ---
12
2 files changed, 20 insertions(+), 8 deletions(-)
27
3 files changed, 4 insertions(+), 8 deletions(-)
28
13
29
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
30
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/cpu.h
16
--- a/target/arm/cpu.h
32
+++ b/target/arm/cpu.h
17
+++ b/target/arm/cpu.h
33
@@ -XXX,XX +XXX,XX @@ static inline uint64_t cpreg_to_kvm_id(uint32_t cpregid)
18
@@ -XXX,XX +XXX,XX @@ FIELD(V7M_CCR, STKOFHFNMIGN, 10, 1)
34
* migration or KVM state synchronization. (Typically this is for "registers"
19
FIELD(V7M_CCR, DC, 16, 1)
35
* which are actually used as instructions for cache maintenance and so on.)
20
FIELD(V7M_CCR, IC, 17, 1)
36
* IO indicates that this register does I/O and therefore its accesses
21
FIELD(V7M_CCR, BP, 18, 1)
37
- * need to be surrounded by gen_io_start()/gen_io_end(). In particular,
22
+FIELD(V7M_CCR, LOB, 19, 1)
38
+ * need to be marked with gen_io_start() and also end the TB. In particular,
23
+FIELD(V7M_CCR, TRD, 20, 1)
39
* registers which implement clocks or timers require this.
24
40
* RAISES_EXC is for when the read or write hook might raise an exception;
25
/* V7M SCR bits */
41
* the generated code will synchronize the CPU state before calling the hook
26
FIELD(V7M_SCR, SLEEPONEXIT, 1, 1)
42
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
27
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
43
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/translate-vfp.inc.c
29
--- a/hw/intc/armv7m_nvic.c
45
+++ b/target/arm/translate-vfp.inc.c
30
+++ b/hw/intc/armv7m_nvic.c
46
@@ -XXX,XX +XXX,XX @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
31
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
47
if (s->v7m_lspact) {
48
/*
49
* Lazy state saving affects external memory and also the NVIC,
50
- * so we must mark it as an IO operation for icount.
51
+ * so we must mark it as an IO operation for icount (and cause
52
+ * this to be the last insn in the TB).
53
*/
54
if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
55
+ s->base.is_jmp = DISAS_UPDATE;
56
gen_io_start();
57
}
58
gen_helper_v7m_preserve_fp_state(cpu_env);
59
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
60
- gen_io_end();
61
- }
62
/*
63
* If the preserve_fp_state helper doesn't throw an exception
64
* then it will clear LSPACT; we don't need to repeat this for
65
diff --git a/target/arm/translate.c b/target/arm/translate.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/target/arm/translate.c
68
+++ b/target/arm/translate.c
69
@@ -XXX,XX +XXX,XX @@ static bool do_ldm(DisasContext *s, arg_ldst_block *a, int min_n)
70
gen_io_start();
71
}
32
}
72
gen_helper_cpsr_write_eret(cpu_env, tmp);
33
return cpu->env.v7m.scr[attrs.secure];
73
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
34
case 0xd14: /* Configuration Control. */
74
- gen_io_end();
35
- /* The BFHFNMIGN bit is the only non-banked bit; we
75
- }
36
- * keep it in the non-secure copy of the register.
76
tcg_temp_free_i32(tmp);
37
+ /*
77
/* Must exit loop to check un-masked IRQs */
38
+ * Non-banked bits: BFHFNMIGN (stored in the NS copy of the register)
78
s->base.is_jmp = DISAS_EXIT;
39
+ * and TRD (stored in the S copy of the register)
40
*/
41
val = cpu->env.v7m.ccr[attrs.secure];
42
val |= cpu->env.v7m.ccr[M_REG_NS] & R_V7M_CCR_BFHFNMIGN_MASK;
43
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
44
cpu->env.v7m.scr[attrs.secure] = value;
45
break;
46
case 0xd14: /* Configuration Control. */
47
+ {
48
+ uint32_t mask;
49
+
50
if (!arm_feature(&cpu->env, ARM_FEATURE_M_MAIN)) {
51
goto bad_offset;
52
}
53
54
/* Enforce RAZ/WI on reserved and must-RAZ/WI bits */
55
- value &= (R_V7M_CCR_STKALIGN_MASK |
56
- R_V7M_CCR_BFHFNMIGN_MASK |
57
- R_V7M_CCR_DIV_0_TRP_MASK |
58
- R_V7M_CCR_UNALIGN_TRP_MASK |
59
- R_V7M_CCR_USERSETMPEND_MASK |
60
- R_V7M_CCR_NONBASETHRDENA_MASK);
61
+ mask = R_V7M_CCR_STKALIGN_MASK |
62
+ R_V7M_CCR_BFHFNMIGN_MASK |
63
+ R_V7M_CCR_DIV_0_TRP_MASK |
64
+ R_V7M_CCR_UNALIGN_TRP_MASK |
65
+ R_V7M_CCR_USERSETMPEND_MASK |
66
+ R_V7M_CCR_NONBASETHRDENA_MASK;
67
+ if (arm_feature(&cpu->env, ARM_FEATURE_V8_1M) && attrs.secure) {
68
+ /* TRD is always RAZ/WI from NS */
69
+ mask |= R_V7M_CCR_TRD_MASK;
70
+ }
71
+ value &= mask;
72
73
if (arm_feature(&cpu->env, ARM_FEATURE_V8)) {
74
/* v8M makes NONBASETHRDENA and STKALIGN be RES1 */
75
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
76
77
cpu->env.v7m.ccr[attrs.secure] = value;
78
break;
79
+ }
80
case 0xd24: /* System Handler Control and State (SHCSR) */
81
if (!arm_feature(&cpu->env, ARM_FEATURE_V7)) {
82
goto bad_offset;
79
--
83
--
80
2.20.1
84
2.20.1
81
85
82
86
diff view generated by jsdifflib
1
Convert to decodetree the insns in the Neon 2-reg-misc grouping which
1
v8.1M introduces a new TRD flag in the CCR register, which enables
2
we implement using gvec.
2
checking for stack frame integrity signatures on SG instructions.
3
Add the code in the SG insn implementation for the new behaviour.
3
4
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200616170844.13318-8-peter.maydell@linaro.org
7
Message-id: 20201119215617.29887-24-peter.maydell@linaro.org
7
---
8
---
8
target/arm/neon-dp.decode | 11 +++++++
9
target/arm/m_helper.c | 86 +++++++++++++++++++++++++++++++++++++++++++
9
target/arm/translate-neon.inc.c | 55 +++++++++++++++++++++++++++++++++
10
1 file changed, 86 insertions(+)
10
target/arm/translate.c | 35 +++++----------------
11
3 files changed, 74 insertions(+), 27 deletions(-)
12
11
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
12
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
14
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
14
--- a/target/arm/m_helper.c
16
+++ b/target/arm/neon-dp.decode
15
+++ b/target/arm/m_helper.c
17
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
16
@@ -XXX,XX +XXX,XX @@ static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx,
18
VPADDL_S 1111 001 11 . 11 .. 00 .... 0 0100 . . 0 .... @2misc
19
VPADDL_U 1111 001 11 . 11 .. 00 .... 0 0101 . . 0 .... @2misc
20
21
+ VMVN 1111 001 11 . 11 .. 00 .... 0 1011 . . 0 .... @2misc
22
+
23
VPADAL_S 1111 001 11 . 11 .. 00 .... 0 1100 . . 0 .... @2misc
24
VPADAL_U 1111 001 11 . 11 .. 00 .... 0 1101 . . 0 .... @2misc
25
26
+ VCGT0 1111 001 11 . 11 .. 01 .... 0 0000 . . 0 .... @2misc
27
+ VCGE0 1111 001 11 . 11 .. 01 .... 0 0001 . . 0 .... @2misc
28
+ VCEQ0 1111 001 11 . 11 .. 01 .... 0 0010 . . 0 .... @2misc
29
+ VCLE0 1111 001 11 . 11 .. 01 .... 0 0011 . . 0 .... @2misc
30
+ VCLT0 1111 001 11 . 11 .. 01 .... 0 0100 . . 0 .... @2misc
31
+
32
+ VABS 1111 001 11 . 11 .. 01 .... 0 0110 . . 0 .... @2misc
33
+ VNEG 1111 001 11 . 11 .. 01 .... 0 0111 . . 0 .... @2misc
34
+
35
VUZP 1111 001 11 . 11 .. 10 .... 0 0010 . . 0 .... @2misc
36
VZIP 1111 001 11 . 11 .. 10 .... 0 0011 . . 0 .... @2misc
37
38
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/translate-neon.inc.c
41
+++ b/target/arm/translate-neon.inc.c
42
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_F32_F16(DisasContext *s, arg_2misc *a)
43
44
return true;
17
return true;
45
}
18
}
19
20
+static bool v7m_read_sg_stack_word(ARMCPU *cpu, ARMMMUIdx mmu_idx,
21
+ uint32_t addr, uint32_t *spdata)
22
+{
23
+ /*
24
+ * Read a word of data from the stack for the SG instruction,
25
+ * writing the value into *spdata. If the load succeeds, return
26
+ * true; otherwise pend an appropriate exception and return false.
27
+ * (We can't use data load helpers here that throw an exception
28
+ * because of the context we're called in, which is halfway through
29
+ * arm_v7m_cpu_do_interrupt().)
30
+ */
31
+ CPUState *cs = CPU(cpu);
32
+ CPUARMState *env = &cpu->env;
33
+ MemTxAttrs attrs = {};
34
+ MemTxResult txres;
35
+ target_ulong page_size;
36
+ hwaddr physaddr;
37
+ int prot;
38
+ ARMMMUFaultInfo fi = {};
39
+ ARMCacheAttrs cacheattrs = {};
40
+ uint32_t value;
46
+
41
+
47
+static bool do_2misc_vec(DisasContext *s, arg_2misc *a, GVecGen2Fn *fn)
42
+ if (get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &physaddr,
48
+{
43
+ &attrs, &prot, &page_size, &fi, &cacheattrs)) {
49
+ int vec_size = a->q ? 16 : 8;
44
+ /* MPU/SAU lookup failed */
50
+ int rd_ofs = neon_reg_offset(a->vd, 0);
45
+ if (fi.type == ARMFault_QEMU_SFault) {
51
+ int rm_ofs = neon_reg_offset(a->vm, 0);
46
+ qemu_log_mask(CPU_LOG_INT,
52
+
47
+ "...SecureFault during stack word read\n");
53
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
48
+ env->v7m.sfsr |= R_V7M_SFSR_AUVIOL_MASK | R_V7M_SFSR_SFARVALID_MASK;
49
+ env->v7m.sfar = addr;
50
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SECURE, false);
51
+ } else {
52
+ qemu_log_mask(CPU_LOG_INT,
53
+ "...MemManageFault during stack word read\n");
54
+ env->v7m.cfsr[M_REG_S] |= R_V7M_CFSR_DACCVIOL_MASK |
55
+ R_V7M_CFSR_MMARVALID_MASK;
56
+ env->v7m.mmfar[M_REG_S] = addr;
57
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM, false);
58
+ }
59
+ return false;
60
+ }
61
+ value = address_space_ldl(arm_addressspace(cs, attrs), physaddr,
62
+ attrs, &txres);
63
+ if (txres != MEMTX_OK) {
64
+ /* BusFault trying to read the data */
65
+ qemu_log_mask(CPU_LOG_INT,
66
+ "...BusFault during stack word read\n");
67
+ env->v7m.cfsr[M_REG_NS] |=
68
+ (R_V7M_CFSR_PRECISERR_MASK | R_V7M_CFSR_BFARVALID_MASK);
69
+ env->v7m.bfar = addr;
70
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_BUS, false);
54
+ return false;
71
+ return false;
55
+ }
72
+ }
56
+
73
+
57
+ /* UNDEF accesses to D16-D31 if they don't exist. */
74
+ *spdata = value;
58
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
59
+ ((a->vd | a->vm) & 0x10)) {
60
+ return false;
61
+ }
62
+
63
+ if (a->size == 3) {
64
+ return false;
65
+ }
66
+
67
+ if ((a->vd | a->vm) & a->q) {
68
+ return false;
69
+ }
70
+
71
+ if (!vfp_access_check(s)) {
72
+ return true;
73
+ }
74
+
75
+ fn(a->size, rd_ofs, rm_ofs, vec_size, vec_size);
76
+
77
+ return true;
75
+ return true;
78
+}
76
+}
79
+
77
+
80
+#define DO_2MISC_VEC(INSN, FN) \
78
static bool v7m_handle_execute_nsc(ARMCPU *cpu)
81
+ static bool trans_##INSN(DisasContext *s, arg_2misc *a) \
79
{
82
+ { \
80
/*
83
+ return do_2misc_vec(s, a, FN); \
81
@@ -XXX,XX +XXX,XX @@ static bool v7m_handle_execute_nsc(ARMCPU *cpu)
82
*/
83
qemu_log_mask(CPU_LOG_INT, "...really an SG instruction at 0x%08" PRIx32
84
", executing it\n", env->regs[15]);
85
+
86
+ if (cpu_isar_feature(aa32_m_sec_state, cpu) &&
87
+ !arm_v7m_is_handler_mode(env)) {
88
+ /*
89
+ * v8.1M exception stack frame integrity check. Note that we
90
+ * must perform the memory access even if CCR_S.TRD is zero
91
+ * and we aren't going to check what the data loaded is.
92
+ */
93
+ uint32_t spdata, sp;
94
+
95
+ /*
96
+ * We know we are currently NS, so the S stack pointers must be
97
+ * in other_ss_{psp,msp}, not in regs[13]/other_sp.
98
+ */
99
+ sp = v7m_using_psp(env) ? env->v7m.other_ss_psp : env->v7m.other_ss_msp;
100
+ if (!v7m_read_sg_stack_word(cpu, mmu_idx, sp, &spdata)) {
101
+ /* Stack access failed and an exception has been pended */
102
+ return false;
103
+ }
104
+
105
+ if (env->v7m.ccr[M_REG_S] & R_V7M_CCR_TRD_MASK) {
106
+ if (((spdata & ~1) == 0xfefa125a) ||
107
+ !(env->v7m.control[M_REG_S] & 1)) {
108
+ goto gen_invep;
109
+ }
110
+ }
84
+ }
111
+ }
85
+
112
+
86
+DO_2MISC_VEC(VNEG, tcg_gen_gvec_neg)
113
env->regs[14] &= ~1;
87
+DO_2MISC_VEC(VABS, tcg_gen_gvec_abs)
114
env->v7m.control[M_REG_S] &= ~R_V7M_CONTROL_SFPA_MASK;
88
+DO_2MISC_VEC(VCEQ0, gen_gvec_ceq0)
115
switch_v7m_security_state(env, true);
89
+DO_2MISC_VEC(VCGT0, gen_gvec_cgt0)
90
+DO_2MISC_VEC(VCLE0, gen_gvec_cle0)
91
+DO_2MISC_VEC(VCGE0, gen_gvec_cge0)
92
+DO_2MISC_VEC(VCLT0, gen_gvec_clt0)
93
+
94
+static bool trans_VMVN(DisasContext *s, arg_2misc *a)
95
+{
96
+ if (a->size != 0) {
97
+ return false;
98
+ }
99
+ return do_2misc_vec(s, a, tcg_gen_gvec_not);
100
+}
101
diff --git a/target/arm/translate.c b/target/arm/translate.c
102
index XXXXXXX..XXXXXXX 100644
103
--- a/target/arm/translate.c
104
+++ b/target/arm/translate.c
105
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
106
int size;
107
int pass;
108
int u;
109
- int vec_size;
110
TCGv_i32 tmp, tmp2;
111
112
if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
113
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
114
VFP_DREG_D(rd, insn);
115
VFP_DREG_M(rm, insn);
116
size = (insn >> 20) & 3;
117
- vec_size = q ? 16 : 8;
118
rd_ofs = neon_reg_offset(rd, 0);
119
rm_ofs = neon_reg_offset(rm, 0);
120
121
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
122
case NEON_2RM_VSHLL:
123
case NEON_2RM_VCVT_F16_F32:
124
case NEON_2RM_VCVT_F32_F16:
125
+ case NEON_2RM_VMVN:
126
+ case NEON_2RM_VNEG:
127
+ case NEON_2RM_VABS:
128
+ case NEON_2RM_VCEQ0:
129
+ case NEON_2RM_VCGT0:
130
+ case NEON_2RM_VCLE0:
131
+ case NEON_2RM_VCGE0:
132
+ case NEON_2RM_VCLT0:
133
/* handled by decodetree */
134
return 1;
135
case NEON_2RM_VTRN:
136
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
137
q ? gen_helper_crypto_sha256su0
138
: gen_helper_crypto_sha1su1);
139
break;
140
- case NEON_2RM_VMVN:
141
- tcg_gen_gvec_not(0, rd_ofs, rm_ofs, vec_size, vec_size);
142
- break;
143
- case NEON_2RM_VNEG:
144
- tcg_gen_gvec_neg(size, rd_ofs, rm_ofs, vec_size, vec_size);
145
- break;
146
- case NEON_2RM_VABS:
147
- tcg_gen_gvec_abs(size, rd_ofs, rm_ofs, vec_size, vec_size);
148
- break;
149
-
150
- case NEON_2RM_VCEQ0:
151
- gen_gvec_ceq0(size, rd_ofs, rm_ofs, vec_size, vec_size);
152
- break;
153
- case NEON_2RM_VCGT0:
154
- gen_gvec_cgt0(size, rd_ofs, rm_ofs, vec_size, vec_size);
155
- break;
156
- case NEON_2RM_VCLE0:
157
- gen_gvec_cle0(size, rd_ofs, rm_ofs, vec_size, vec_size);
158
- break;
159
- case NEON_2RM_VCGE0:
160
- gen_gvec_cge0(size, rd_ofs, rm_ofs, vec_size, vec_size);
161
- break;
162
- case NEON_2RM_VCLT0:
163
- gen_gvec_clt0(size, rd_ofs, rm_ofs, vec_size, vec_size);
164
- break;
165
166
default:
167
elementwise:
168
--
116
--
169
2.20.1
117
2.20.1
170
118
171
119
diff view generated by jsdifflib
1
Convert the Neon VTRN insn to decodetree. This is the last insn in the
1
In commit 077d7449100d824a4 we added code to handle the v8M
2
Neon data-processing group, so we can remove all the now-unused old
2
requirement that returns from NMI or HardFault forcibly deactivate
3
decoder framework.
3
those exceptions regardless of what interrupt the guest is trying to
4
deactivate. Unfortunately this broke the handling of the "illegal
5
exception return because the returning exception number is not
6
active" check for those cases. In the pseudocode this test is done
7
on the exception the guest asks to return from, but because our
8
implementation was doing this in armv7m_nvic_complete_irq() after the
9
new "deactivate NMI/HardFault regardless" code we ended up doing the
10
test on the VecInfo for that exception instead, which usually meant
11
failing to raise the illegal exception return fault.
4
12
5
It's possible that there's a more efficient implementation of
13
In the case for "configurable exception targeting the opposite
6
VTRN, but for this conversion we just copy the existing approach.
14
security state" we detected the illegal-return case but went ahead
15
and deactivated the VecInfo anyway, which is wrong because that is
16
the VecInfo for the other security state.
17
18
Rearrange the code so that we first identify the illegal return
19
cases, then see if we really need to deactivate NMI or HardFault
20
instead, and finally do the deactivation.
7
21
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20200616170844.13318-21-peter.maydell@linaro.org
24
Message-id: 20201119215617.29887-25-peter.maydell@linaro.org
11
---
25
---
12
target/arm/neon-dp.decode | 2 +-
26
hw/intc/armv7m_nvic.c | 59 +++++++++++++++++++++++--------------------
13
target/arm/translate-neon.inc.c | 90 ++++++++
27
1 file changed, 32 insertions(+), 27 deletions(-)
14
target/arm/translate.c | 363 +-------------------------------
15
3 files changed, 93 insertions(+), 362 deletions(-)
16
28
17
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
29
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
18
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/neon-dp.decode
31
--- a/hw/intc/armv7m_nvic.c
20
+++ b/target/arm/neon-dp.decode
32
+++ b/hw/intc/armv7m_nvic.c
21
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
33
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
22
VNEG_F 1111 001 11 . 11 .. 01 .... 0 1111 . . 0 .... @2misc
34
{
23
35
NVICState *s = (NVICState *)opaque;
24
VSWP 1111 001 11 . 11 .. 10 .... 0 0000 . . 0 .... @2misc
36
VecInfo *vec = NULL;
25
-
37
- int ret;
26
+ VTRN 1111 001 11 . 11 .. 10 .... 0 0001 . . 0 .... @2misc
38
+ int ret = 0;
27
VUZP 1111 001 11 . 11 .. 10 .... 0 0010 . . 0 .... @2misc
39
28
VZIP 1111 001 11 . 11 .. 10 .... 0 0011 . . 0 .... @2misc
40
assert(irq > ARMV7M_EXCP_RESET && irq < s->num_irq);
29
41
30
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
42
+ trace_nvic_complete_irq(irq, secure);
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/translate-neon.inc.c
33
+++ b/target/arm/translate-neon.inc.c
34
@@ -XXX,XX +XXX,XX @@ static bool trans_VSWP(DisasContext *s, arg_2misc *a)
35
36
return true;
37
}
38
+static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
39
+{
40
+ TCGv_i32 rd, tmp;
41
+
43
+
42
+ rd = tcg_temp_new_i32();
44
+ if (secure && exc_is_banked(irq)) {
43
+ tmp = tcg_temp_new_i32();
45
+ vec = &s->sec_vectors[irq];
44
+
46
+ } else {
45
+ tcg_gen_shli_i32(rd, t0, 8);
47
+ vec = &s->vectors[irq];
46
+ tcg_gen_andi_i32(rd, rd, 0xff00ff00);
47
+ tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
48
+ tcg_gen_or_i32(rd, rd, tmp);
49
+
50
+ tcg_gen_shri_i32(t1, t1, 8);
51
+ tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
52
+ tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
53
+ tcg_gen_or_i32(t1, t1, tmp);
54
+ tcg_gen_mov_i32(t0, rd);
55
+
56
+ tcg_temp_free_i32(tmp);
57
+ tcg_temp_free_i32(rd);
58
+}
59
+
60
+static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
61
+{
62
+ TCGv_i32 rd, tmp;
63
+
64
+ rd = tcg_temp_new_i32();
65
+ tmp = tcg_temp_new_i32();
66
+
67
+ tcg_gen_shli_i32(rd, t0, 16);
68
+ tcg_gen_andi_i32(tmp, t1, 0xffff);
69
+ tcg_gen_or_i32(rd, rd, tmp);
70
+ tcg_gen_shri_i32(t1, t1, 16);
71
+ tcg_gen_andi_i32(tmp, t0, 0xffff0000);
72
+ tcg_gen_or_i32(t1, t1, tmp);
73
+ tcg_gen_mov_i32(t0, rd);
74
+
75
+ tcg_temp_free_i32(tmp);
76
+ tcg_temp_free_i32(rd);
77
+}
78
+
79
+static bool trans_VTRN(DisasContext *s, arg_2misc *a)
80
+{
81
+ TCGv_i32 tmp, tmp2;
82
+ int pass;
83
+
84
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
85
+ return false;
86
+ }
48
+ }
87
+
49
+
88
+ /* UNDEF accesses to D16-D31 if they don't exist. */
50
+ /*
89
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
51
+ * Identify illegal exception return cases. We can't immediately
90
+ ((a->vd | a->vm) & 0x10)) {
52
+ * return at this point because we still need to deactivate
91
+ return false;
53
+ * (either this exception or NMI/HardFault) first.
54
+ */
55
+ if (!exc_is_banked(irq) && exc_targets_secure(s, irq) != secure) {
56
+ /*
57
+ * Return from a configurable exception targeting the opposite
58
+ * security state from the one we're trying to complete it for.
59
+ * Clear vec because it's not really the VecInfo for this
60
+ * (irq, secstate) so we mustn't deactivate it.
61
+ */
62
+ ret = -1;
63
+ vec = NULL;
64
+ } else if (!vec->active) {
65
+ /* Return from an inactive interrupt */
66
+ ret = -1;
67
+ } else {
68
+ /* Legal return, we will return the RETTOBASE bit value to the caller */
69
+ ret = nvic_rettobase(s);
92
+ }
70
+ }
93
+
71
+
94
+ if ((a->vd | a->vm) & a->q) {
72
/*
95
+ return false;
73
* For negative priorities, v8M will forcibly deactivate the appropriate
96
+ }
74
* NMI or HardFault regardless of what interrupt we're being asked to
97
+
75
@@ -XXX,XX +XXX,XX @@ int armv7m_nvic_complete_irq(void *opaque, int irq, bool secure)
98
+ if (a->size == 3) {
76
}
99
+ return false;
77
100
+ }
78
if (!vec) {
101
+
79
- if (secure && exc_is_banked(irq)) {
102
+ if (!vfp_access_check(s)) {
80
- vec = &s->sec_vectors[irq];
103
+ return true;
81
- } else {
104
+ }
82
- vec = &s->vectors[irq];
105
+
83
- }
106
+ if (a->size == 2) {
107
+ for (pass = 0; pass < (a->q ? 4 : 2); pass += 2) {
108
+ tmp = neon_load_reg(a->vm, pass);
109
+ tmp2 = neon_load_reg(a->vd, pass + 1);
110
+ neon_store_reg(a->vm, pass, tmp2);
111
+ neon_store_reg(a->vd, pass + 1, tmp);
112
+ }
113
+ } else {
114
+ for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
115
+ tmp = neon_load_reg(a->vm, pass);
116
+ tmp2 = neon_load_reg(a->vd, pass);
117
+ if (a->size == 0) {
118
+ gen_neon_trn_u8(tmp, tmp2);
119
+ } else {
120
+ gen_neon_trn_u16(tmp, tmp2);
121
+ }
122
+ neon_store_reg(a->vm, pass, tmp2);
123
+ neon_store_reg(a->vd, pass, tmp);
124
+ }
125
+ }
126
+ return true;
127
+}
128
diff --git a/target/arm/translate.c b/target/arm/translate.c
129
index XXXXXXX..XXXXXXX 100644
130
--- a/target/arm/translate.c
131
+++ b/target/arm/translate.c
132
@@ -XXX,XX +XXX,XX @@ static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
133
gen_rfe(s, pc, load_cpu_field(spsr));
134
}
135
136
-static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
137
-{
138
- TCGv_i32 rd, tmp;
139
-
140
- rd = tcg_temp_new_i32();
141
- tmp = tcg_temp_new_i32();
142
-
143
- tcg_gen_shli_i32(rd, t0, 8);
144
- tcg_gen_andi_i32(rd, rd, 0xff00ff00);
145
- tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
146
- tcg_gen_or_i32(rd, rd, tmp);
147
-
148
- tcg_gen_shri_i32(t1, t1, 8);
149
- tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
150
- tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
151
- tcg_gen_or_i32(t1, t1, tmp);
152
- tcg_gen_mov_i32(t0, rd);
153
-
154
- tcg_temp_free_i32(tmp);
155
- tcg_temp_free_i32(rd);
156
-}
157
-
158
-static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
159
-{
160
- TCGv_i32 rd, tmp;
161
-
162
- rd = tcg_temp_new_i32();
163
- tmp = tcg_temp_new_i32();
164
-
165
- tcg_gen_shli_i32(rd, t0, 16);
166
- tcg_gen_andi_i32(tmp, t1, 0xffff);
167
- tcg_gen_or_i32(rd, rd, tmp);
168
- tcg_gen_shri_i32(t1, t1, 16);
169
- tcg_gen_andi_i32(tmp, t0, 0xffff0000);
170
- tcg_gen_or_i32(t1, t1, tmp);
171
- tcg_gen_mov_i32(t0, rd);
172
-
173
- tcg_temp_free_i32(tmp);
174
- tcg_temp_free_i32(rd);
175
-}
176
-
177
-/* Symbolic constants for op fields for Neon 2-register miscellaneous.
178
- * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
179
- * table A7-13.
180
- */
181
-#define NEON_2RM_VREV64 0
182
-#define NEON_2RM_VREV32 1
183
-#define NEON_2RM_VREV16 2
184
-#define NEON_2RM_VPADDL 4
185
-#define NEON_2RM_VPADDL_U 5
186
-#define NEON_2RM_AESE 6 /* Includes AESD */
187
-#define NEON_2RM_AESMC 7 /* Includes AESIMC */
188
-#define NEON_2RM_VCLS 8
189
-#define NEON_2RM_VCLZ 9
190
-#define NEON_2RM_VCNT 10
191
-#define NEON_2RM_VMVN 11
192
-#define NEON_2RM_VPADAL 12
193
-#define NEON_2RM_VPADAL_U 13
194
-#define NEON_2RM_VQABS 14
195
-#define NEON_2RM_VQNEG 15
196
-#define NEON_2RM_VCGT0 16
197
-#define NEON_2RM_VCGE0 17
198
-#define NEON_2RM_VCEQ0 18
199
-#define NEON_2RM_VCLE0 19
200
-#define NEON_2RM_VCLT0 20
201
-#define NEON_2RM_SHA1H 21
202
-#define NEON_2RM_VABS 22
203
-#define NEON_2RM_VNEG 23
204
-#define NEON_2RM_VCGT0_F 24
205
-#define NEON_2RM_VCGE0_F 25
206
-#define NEON_2RM_VCEQ0_F 26
207
-#define NEON_2RM_VCLE0_F 27
208
-#define NEON_2RM_VCLT0_F 28
209
-#define NEON_2RM_VABS_F 30
210
-#define NEON_2RM_VNEG_F 31
211
-#define NEON_2RM_VSWP 32
212
-#define NEON_2RM_VTRN 33
213
-#define NEON_2RM_VUZP 34
214
-#define NEON_2RM_VZIP 35
215
-#define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
216
-#define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
217
-#define NEON_2RM_VSHLL 38
218
-#define NEON_2RM_SHA1SU1 39 /* Includes SHA256SU0 */
219
-#define NEON_2RM_VRINTN 40
220
-#define NEON_2RM_VRINTX 41
221
-#define NEON_2RM_VRINTA 42
222
-#define NEON_2RM_VRINTZ 43
223
-#define NEON_2RM_VCVT_F16_F32 44
224
-#define NEON_2RM_VRINTM 45
225
-#define NEON_2RM_VCVT_F32_F16 46
226
-#define NEON_2RM_VRINTP 47
227
-#define NEON_2RM_VCVTAU 48
228
-#define NEON_2RM_VCVTAS 49
229
-#define NEON_2RM_VCVTNU 50
230
-#define NEON_2RM_VCVTNS 51
231
-#define NEON_2RM_VCVTPU 52
232
-#define NEON_2RM_VCVTPS 53
233
-#define NEON_2RM_VCVTMU 54
234
-#define NEON_2RM_VCVTMS 55
235
-#define NEON_2RM_VRECPE 56
236
-#define NEON_2RM_VRSQRTE 57
237
-#define NEON_2RM_VRECPE_F 58
238
-#define NEON_2RM_VRSQRTE_F 59
239
-#define NEON_2RM_VCVT_FS 60
240
-#define NEON_2RM_VCVT_FU 61
241
-#define NEON_2RM_VCVT_SF 62
242
-#define NEON_2RM_VCVT_UF 63
243
-
244
-/* Each entry in this array has bit n set if the insn allows
245
- * size value n (otherwise it will UNDEF). Since unallocated
246
- * op values will have no bits set they always UNDEF.
247
- */
248
-static const uint8_t neon_2rm_sizes[] = {
249
- [NEON_2RM_VREV64] = 0x7,
250
- [NEON_2RM_VREV32] = 0x3,
251
- [NEON_2RM_VREV16] = 0x1,
252
- [NEON_2RM_VPADDL] = 0x7,
253
- [NEON_2RM_VPADDL_U] = 0x7,
254
- [NEON_2RM_AESE] = 0x1,
255
- [NEON_2RM_AESMC] = 0x1,
256
- [NEON_2RM_VCLS] = 0x7,
257
- [NEON_2RM_VCLZ] = 0x7,
258
- [NEON_2RM_VCNT] = 0x1,
259
- [NEON_2RM_VMVN] = 0x1,
260
- [NEON_2RM_VPADAL] = 0x7,
261
- [NEON_2RM_VPADAL_U] = 0x7,
262
- [NEON_2RM_VQABS] = 0x7,
263
- [NEON_2RM_VQNEG] = 0x7,
264
- [NEON_2RM_VCGT0] = 0x7,
265
- [NEON_2RM_VCGE0] = 0x7,
266
- [NEON_2RM_VCEQ0] = 0x7,
267
- [NEON_2RM_VCLE0] = 0x7,
268
- [NEON_2RM_VCLT0] = 0x7,
269
- [NEON_2RM_SHA1H] = 0x4,
270
- [NEON_2RM_VABS] = 0x7,
271
- [NEON_2RM_VNEG] = 0x7,
272
- [NEON_2RM_VCGT0_F] = 0x4,
273
- [NEON_2RM_VCGE0_F] = 0x4,
274
- [NEON_2RM_VCEQ0_F] = 0x4,
275
- [NEON_2RM_VCLE0_F] = 0x4,
276
- [NEON_2RM_VCLT0_F] = 0x4,
277
- [NEON_2RM_VABS_F] = 0x4,
278
- [NEON_2RM_VNEG_F] = 0x4,
279
- [NEON_2RM_VSWP] = 0x1,
280
- [NEON_2RM_VTRN] = 0x7,
281
- [NEON_2RM_VUZP] = 0x7,
282
- [NEON_2RM_VZIP] = 0x7,
283
- [NEON_2RM_VMOVN] = 0x7,
284
- [NEON_2RM_VQMOVN] = 0x7,
285
- [NEON_2RM_VSHLL] = 0x7,
286
- [NEON_2RM_SHA1SU1] = 0x4,
287
- [NEON_2RM_VRINTN] = 0x4,
288
- [NEON_2RM_VRINTX] = 0x4,
289
- [NEON_2RM_VRINTA] = 0x4,
290
- [NEON_2RM_VRINTZ] = 0x4,
291
- [NEON_2RM_VCVT_F16_F32] = 0x2,
292
- [NEON_2RM_VRINTM] = 0x4,
293
- [NEON_2RM_VCVT_F32_F16] = 0x2,
294
- [NEON_2RM_VRINTP] = 0x4,
295
- [NEON_2RM_VCVTAU] = 0x4,
296
- [NEON_2RM_VCVTAS] = 0x4,
297
- [NEON_2RM_VCVTNU] = 0x4,
298
- [NEON_2RM_VCVTNS] = 0x4,
299
- [NEON_2RM_VCVTPU] = 0x4,
300
- [NEON_2RM_VCVTPS] = 0x4,
301
- [NEON_2RM_VCVTMU] = 0x4,
302
- [NEON_2RM_VCVTMS] = 0x4,
303
- [NEON_2RM_VRECPE] = 0x4,
304
- [NEON_2RM_VRSQRTE] = 0x4,
305
- [NEON_2RM_VRECPE_F] = 0x4,
306
- [NEON_2RM_VRSQRTE_F] = 0x4,
307
- [NEON_2RM_VCVT_FS] = 0x4,
308
- [NEON_2RM_VCVT_FU] = 0x4,
309
- [NEON_2RM_VCVT_SF] = 0x4,
310
- [NEON_2RM_VCVT_UF] = 0x4,
311
-};
312
-
313
static void gen_gvec_fn3_qc(uint32_t rd_ofs, uint32_t rn_ofs, uint32_t rm_ofs,
314
uint32_t opr_sz, uint32_t max_sz,
315
gen_helper_gvec_3_ptr *fn)
316
@@ -XXX,XX +XXX,XX @@ void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
317
tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &ops[vece]);
318
}
319
320
-/* Translate a NEON data processing instruction. Return nonzero if the
321
- instruction is invalid.
322
- We process data in a mixture of 32-bit and 64-bit chunks.
323
- Mostly we use 32-bit chunks so we can use normal scalar instructions. */
324
-
325
-static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
326
-{
327
- int op;
328
- int q;
329
- int rd, rm;
330
- int size;
331
- int pass;
332
- int u;
333
- TCGv_i32 tmp, tmp2;
334
-
335
- if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
336
- return 1;
337
- }
84
- }
338
-
85
-
339
- /* FIXME: this access check should not take precedence over UNDEF
86
- trace_nvic_complete_irq(irq, secure);
340
- * for invalid encodings; we will generate incorrect syndrome information
87
-
341
- * for attempts to execute invalid vfp/neon encodings with FP disabled.
88
- if (!vec->active) {
342
- */
89
- /* Tell the caller this was an illegal exception return */
343
- if (s->fp_excp_el) {
90
- return -1;
344
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
345
- syn_simd_access_trap(1, 0xe, false), s->fp_excp_el);
346
- return 0;
347
- }
91
- }
348
-
92
-
349
- if (!s->vfp_enabled)
93
- /*
350
- return 1;
94
- * If this is a configurable exception and it is currently
351
- q = (insn & (1 << 6)) != 0;
95
- * targeting the opposite security state from the one we're trying
352
- u = (insn >> 24) & 1;
96
- * to complete it for, this counts as an illegal exception return.
353
- VFP_DREG_D(rd, insn);
97
- * We still need to deactivate whatever vector the logic above has
354
- VFP_DREG_M(rm, insn);
98
- * selected, though, as it might not be the same as the one for the
355
- size = (insn >> 20) & 3;
99
- * requested exception number.
356
-
100
- */
357
- if ((insn & (1 << 23)) == 0) {
101
- if (!exc_is_banked(irq) && exc_targets_secure(s, irq) != secure) {
358
- /* Three register same length: handled by decodetree */
102
- ret = -1;
359
- return 1;
103
- } else {
360
- } else if (insn & (1 << 4)) {
104
- ret = nvic_rettobase(s);
361
- /* Two registers and shift or reg and imm: handled by decodetree */
105
+ return ret;
362
- return 1;
106
}
363
- } else { /* (insn & 0x00800010 == 0x00800000) */
107
364
- if (size != 3) {
108
vec->active = 0;
365
- /*
366
- * Three registers of different lengths, or two registers and
367
- * a scalar: handled by decodetree
368
- */
369
- return 1;
370
- } else { /* size == 3 */
371
- if (!u) {
372
- /* Extract: handled by decodetree */
373
- return 1;
374
- } else if ((insn & (1 << 11)) == 0) {
375
- /* Two register misc. */
376
- op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
377
- size = (insn >> 18) & 3;
378
- /* UNDEF for unknown op values and bad op-size combinations */
379
- if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
380
- return 1;
381
- }
382
- if (q && ((rm | rd) & 1)) {
383
- return 1;
384
- }
385
- switch (op) {
386
- case NEON_2RM_VREV64:
387
- case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
388
- case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
389
- case NEON_2RM_VUZP:
390
- case NEON_2RM_VZIP:
391
- case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
392
- case NEON_2RM_VSHLL:
393
- case NEON_2RM_VCVT_F16_F32:
394
- case NEON_2RM_VCVT_F32_F16:
395
- case NEON_2RM_VMVN:
396
- case NEON_2RM_VNEG:
397
- case NEON_2RM_VABS:
398
- case NEON_2RM_VCEQ0:
399
- case NEON_2RM_VCGT0:
400
- case NEON_2RM_VCLE0:
401
- case NEON_2RM_VCGE0:
402
- case NEON_2RM_VCLT0:
403
- case NEON_2RM_AESE: case NEON_2RM_AESMC:
404
- case NEON_2RM_SHA1H:
405
- case NEON_2RM_SHA1SU1:
406
- case NEON_2RM_VREV32:
407
- case NEON_2RM_VREV16:
408
- case NEON_2RM_VCLS:
409
- case NEON_2RM_VCLZ:
410
- case NEON_2RM_VCNT:
411
- case NEON_2RM_VABS_F:
412
- case NEON_2RM_VNEG_F:
413
- case NEON_2RM_VRECPE:
414
- case NEON_2RM_VRSQRTE:
415
- case NEON_2RM_VQABS:
416
- case NEON_2RM_VQNEG:
417
- case NEON_2RM_VRECPE_F:
418
- case NEON_2RM_VRSQRTE_F:
419
- case NEON_2RM_VCVT_FS:
420
- case NEON_2RM_VCVT_FU:
421
- case NEON_2RM_VCVT_SF:
422
- case NEON_2RM_VCVT_UF:
423
- case NEON_2RM_VRINTX:
424
- case NEON_2RM_VCGT0_F:
425
- case NEON_2RM_VCGE0_F:
426
- case NEON_2RM_VCEQ0_F:
427
- case NEON_2RM_VCLE0_F:
428
- case NEON_2RM_VCLT0_F:
429
- case NEON_2RM_VRINTN:
430
- case NEON_2RM_VRINTA:
431
- case NEON_2RM_VRINTM:
432
- case NEON_2RM_VRINTP:
433
- case NEON_2RM_VRINTZ:
434
- case NEON_2RM_VCVTAU:
435
- case NEON_2RM_VCVTAS:
436
- case NEON_2RM_VCVTNU:
437
- case NEON_2RM_VCVTNS:
438
- case NEON_2RM_VCVTPU:
439
- case NEON_2RM_VCVTPS:
440
- case NEON_2RM_VCVTMU:
441
- case NEON_2RM_VCVTMS:
442
- case NEON_2RM_VSWP:
443
- /* handled by decodetree */
444
- return 1;
445
- case NEON_2RM_VTRN:
446
- if (size == 2) {
447
- int n;
448
- for (n = 0; n < (q ? 4 : 2); n += 2) {
449
- tmp = neon_load_reg(rm, n);
450
- tmp2 = neon_load_reg(rd, n + 1);
451
- neon_store_reg(rm, n, tmp2);
452
- neon_store_reg(rd, n + 1, tmp);
453
- }
454
- } else {
455
- goto elementwise;
456
- }
457
- break;
458
-
459
- default:
460
- elementwise:
461
- for (pass = 0; pass < (q ? 4 : 2); pass++) {
462
- tmp = neon_load_reg(rm, pass);
463
- switch (op) {
464
- case NEON_2RM_VTRN:
465
- tmp2 = neon_load_reg(rd, pass);
466
- switch (size) {
467
- case 0: gen_neon_trn_u8(tmp, tmp2); break;
468
- case 1: gen_neon_trn_u16(tmp, tmp2); break;
469
- default: abort();
470
- }
471
- neon_store_reg(rm, pass, tmp2);
472
- break;
473
- default:
474
- /* Reserved op values were caught by the
475
- * neon_2rm_sizes[] check earlier.
476
- */
477
- abort();
478
- }
479
- neon_store_reg(rd, pass, tmp);
480
- }
481
- break;
482
- }
483
- } else {
484
- /* VTBL, VTBX, VDUP: handled by decodetree */
485
- return 1;
486
- }
487
- }
488
- }
489
- return 0;
490
-}
491
-
492
static int disas_coproc_insn(DisasContext *s, uint32_t insn)
493
{
494
int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
495
@@ -XXX,XX +XXX,XX @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
496
}
497
/* fall back to legacy decoder */
498
499
- if (((insn >> 25) & 7) == 1) {
500
- /* NEON Data processing. */
501
- if (disas_neon_data_insn(s, insn)) {
502
- goto illegal_op;
503
- }
504
- return;
505
- }
506
if ((insn & 0x0e000f00) == 0x0c000100) {
507
if (arm_dc_feature(s, ARM_FEATURE_IWMMXT)) {
508
/* iWMMXt register transfer. */
509
@@ -XXX,XX +XXX,XX @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
510
break;
511
}
512
if (((insn >> 24) & 3) == 3) {
513
- /* Translate into the equivalent ARM encoding. */
514
- insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
515
- if (disas_neon_data_insn(s, insn)) {
516
- goto illegal_op;
517
- }
518
+ /* Neon DP, but failed disas_neon_dp() */
519
+ goto illegal_op;
520
} else if (((insn >> 8) & 0xe) == 10) {
521
/* VFP, but failed disas_vfp. */
522
goto illegal_op;
523
--
109
--
524
2.20.1
110
2.20.1
525
111
526
112
diff view generated by jsdifflib
1
Convert the Neon VZIP and VUZP insns in the 2-reg-misc group to
1
For v8.1M the architecture mandates that CPUs must provide at
2
decodetree.
2
least the "minimal RAS implementation" from the Reliability,
3
Availability and Serviceability extension. This consists of:
4
* an ESB instruction which is a NOP
5
-- since it is in the HINT space we need only add a comment
6
* an RFSR register which will RAZ/WI
7
* a RAZ/WI AIRCR.IESB bit
8
-- the code which handles writes to AIRCR does not allow setting
9
of RES0 bits, so we already treat this as RAZ/WI; add a comment
10
noting that this is deliberate
11
* minimal implementation of the RAS register block at 0xe0005000
12
-- this will be in a subsequent commit
13
* setting the ID_PFR0.RAS field to 0b0010
14
-- we will do this when we add the Cortex-M55 CPU model
3
15
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200616170844.13318-4-peter.maydell@linaro.org
18
Message-id: 20201119215617.29887-26-peter.maydell@linaro.org
7
---
19
---
8
target/arm/neon-dp.decode | 3 ++
20
target/arm/cpu.h | 14 ++++++++++++++
9
target/arm/translate-neon.inc.c | 74 ++++++++++++++++++++++++++
21
target/arm/t32.decode | 4 ++++
10
target/arm/translate.c | 92 +--------------------------------
22
hw/intc/armv7m_nvic.c | 13 +++++++++++++
11
3 files changed, 79 insertions(+), 90 deletions(-)
23
3 files changed, 31 insertions(+)
12
24
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
25
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
14
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
27
--- a/target/arm/cpu.h
16
+++ b/target/arm/neon-dp.decode
28
+++ b/target/arm/cpu.h
17
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
29
@@ -XXX,XX +XXX,XX @@ FIELD(ID_MMFR4, LSM, 20, 4)
18
30
FIELD(ID_MMFR4, CCIDX, 24, 4)
19
VPADAL_S 1111 001 11 . 11 .. 00 .... 0 1100 . . 0 .... @2misc
31
FIELD(ID_MMFR4, EVT, 28, 4)
20
VPADAL_U 1111 001 11 . 11 .. 00 .... 0 1101 . . 0 .... @2misc
32
33
+FIELD(ID_PFR0, STATE0, 0, 4)
34
+FIELD(ID_PFR0, STATE1, 4, 4)
35
+FIELD(ID_PFR0, STATE2, 8, 4)
36
+FIELD(ID_PFR0, STATE3, 12, 4)
37
+FIELD(ID_PFR0, CSV2, 16, 4)
38
+FIELD(ID_PFR0, AMU, 20, 4)
39
+FIELD(ID_PFR0, DIT, 24, 4)
40
+FIELD(ID_PFR0, RAS, 28, 4)
21
+
41
+
22
+ VUZP 1111 001 11 . 11 .. 10 .... 0 0010 . . 0 .... @2misc
42
FIELD(ID_PFR1, PROGMOD, 0, 4)
23
+ VZIP 1111 001 11 . 11 .. 10 .... 0 0011 . . 0 .... @2misc
43
FIELD(ID_PFR1, SECURITY, 4, 4)
24
]
44
FIELD(ID_PFR1, MPROGMOD, 8, 4)
25
45
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_predinv(const ARMISARegisters *id)
26
# Subgroup for size != 0b11
46
return FIELD_EX32(id->id_isar6, ID_ISAR6, SPECRES) != 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 trans_VPADAL_U(DisasContext *s, arg_2misc *a)
32
return do_2misc_pairwise(s, a, widenfn[a->size], opfn[a->size],
33
accfn[a->size]);
34
}
47
}
35
+
48
36
+typedef void ZipFn(TCGv_ptr, TCGv_ptr);
49
+static inline bool isar_feature_aa32_ras(const ARMISARegisters *id)
37
+
38
+static bool do_zip_uzp(DisasContext *s, arg_2misc *a,
39
+ ZipFn *fn)
40
+{
50
+{
41
+ TCGv_ptr pd, pm;
51
+ return FIELD_EX32(id->id_pfr0, ID_PFR0, RAS) != 0;
42
+
43
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
44
+ return false;
45
+ }
46
+
47
+ /* UNDEF accesses to D16-D31 if they don't exist. */
48
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
49
+ ((a->vd | a->vm) & 0x10)) {
50
+ return false;
51
+ }
52
+
53
+ if ((a->vd | a->vm) & a->q) {
54
+ return false;
55
+ }
56
+
57
+ if (!fn) {
58
+ /* Bad size or size/q combination */
59
+ return false;
60
+ }
61
+
62
+ if (!vfp_access_check(s)) {
63
+ return true;
64
+ }
65
+
66
+ pd = vfp_reg_ptr(true, a->vd);
67
+ pm = vfp_reg_ptr(true, a->vm);
68
+ fn(pd, pm);
69
+ tcg_temp_free_ptr(pd);
70
+ tcg_temp_free_ptr(pm);
71
+ return true;
72
+}
52
+}
73
+
53
+
74
+static bool trans_VUZP(DisasContext *s, arg_2misc *a)
54
static inline bool isar_feature_aa32_mprofile(const ARMISARegisters *id)
75
+{
55
{
76
+ static ZipFn * const fn[2][4] = {
56
return FIELD_EX32(id->id_pfr1, ID_PFR1, MPROGMOD) != 0;
77
+ {
57
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
78
+ gen_helper_neon_unzip8,
58
index XXXXXXX..XXXXXXX 100644
79
+ gen_helper_neon_unzip16,
59
--- a/target/arm/t32.decode
80
+ NULL,
60
+++ b/target/arm/t32.decode
81
+ NULL,
61
@@ -XXX,XX +XXX,XX @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
82
+ }, {
62
# SEV 1111 0011 1010 1111 1000 0000 0000 0100
83
+ gen_helper_neon_qunzip8,
63
# SEVL 1111 0011 1010 1111 1000 0000 0000 0101
84
+ gen_helper_neon_qunzip16,
64
85
+ gen_helper_neon_qunzip32,
65
+ # For M-profile minimal-RAS ESB can be a NOP, which is the
86
+ NULL,
66
+ # default behaviour since it is in the hint space.
67
+ # ESB 1111 0011 1010 1111 1000 0000 0001 0000
68
+
69
# The canonical nop ends in 0000 0000, but the whole rest
70
# of the space is "reserved hint, behaves as nop".
71
NOP 1111 0011 1010 1111 1000 0000 ---- ----
72
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/hw/intc/armv7m_nvic.c
75
+++ b/hw/intc/armv7m_nvic.c
76
@@ -XXX,XX +XXX,XX @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset, MemTxAttrs attrs)
77
return 0;
78
}
79
return cpu->env.v7m.sfar;
80
+ case 0xf04: /* RFSR */
81
+ if (!cpu_isar_feature(aa32_ras, cpu)) {
82
+ goto bad_offset;
87
+ }
83
+ }
88
+ };
84
+ /* We provide minimal-RAS only: RFSR is RAZ/WI */
89
+ return do_zip_uzp(s, a, fn[a->q][a->size]);
85
+ return 0;
90
+}
86
case 0xf34: /* FPCCR */
91
+
87
if (!cpu_isar_feature(aa32_vfp_simd, cpu)) {
92
+static bool trans_VZIP(DisasContext *s, arg_2misc *a)
88
return 0;
93
+{
89
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
94
+ static ZipFn * const fn[2][4] = {
90
R_V7M_AIRCR_PRIGROUP_SHIFT,
95
+ {
91
R_V7M_AIRCR_PRIGROUP_LENGTH);
96
+ gen_helper_neon_zip8,
92
}
97
+ gen_helper_neon_zip16,
93
+ /* AIRCR.IESB is RAZ/WI because we implement only minimal RAS */
98
+ NULL,
94
if (attrs.secure) {
99
+ NULL,
95
/* These bits are only writable by secure */
100
+ }, {
96
cpu->env.v7m.aircr = value &
101
+ gen_helper_neon_qzip8,
97
@@ -XXX,XX +XXX,XX @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value,
102
+ gen_helper_neon_qzip16,
98
}
103
+ gen_helper_neon_qzip32,
99
break;
104
+ NULL,
100
}
101
+ case 0xf04: /* RFSR */
102
+ if (!cpu_isar_feature(aa32_ras, cpu)) {
103
+ goto bad_offset;
105
+ }
104
+ }
106
+ };
105
+ /* We provide minimal-RAS only: RFSR is RAZ/WI */
107
+ return do_zip_uzp(s, a, fn[a->q][a->size]);
106
+ break;
108
+}
107
case 0xf34: /* FPCCR */
109
diff --git a/target/arm/translate.c b/target/arm/translate.c
108
if (cpu_isar_feature(aa32_vfp_simd, cpu)) {
110
index XXXXXXX..XXXXXXX 100644
109
/* Not all bits here are banked. */
111
--- a/target/arm/translate.c
112
+++ b/target/arm/translate.c
113
@@ -XXX,XX +XXX,XX @@ static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
114
gen_rfe(s, pc, load_cpu_field(spsr));
115
}
116
117
-static int gen_neon_unzip(int rd, int rm, int size, int q)
118
-{
119
- TCGv_ptr pd, pm;
120
-
121
- if (!q && size == 2) {
122
- return 1;
123
- }
124
- pd = vfp_reg_ptr(true, rd);
125
- pm = vfp_reg_ptr(true, rm);
126
- if (q) {
127
- switch (size) {
128
- case 0:
129
- gen_helper_neon_qunzip8(pd, pm);
130
- break;
131
- case 1:
132
- gen_helper_neon_qunzip16(pd, pm);
133
- break;
134
- case 2:
135
- gen_helper_neon_qunzip32(pd, pm);
136
- break;
137
- default:
138
- abort();
139
- }
140
- } else {
141
- switch (size) {
142
- case 0:
143
- gen_helper_neon_unzip8(pd, pm);
144
- break;
145
- case 1:
146
- gen_helper_neon_unzip16(pd, pm);
147
- break;
148
- default:
149
- abort();
150
- }
151
- }
152
- tcg_temp_free_ptr(pd);
153
- tcg_temp_free_ptr(pm);
154
- return 0;
155
-}
156
-
157
-static int gen_neon_zip(int rd, int rm, int size, int q)
158
-{
159
- TCGv_ptr pd, pm;
160
-
161
- if (!q && size == 2) {
162
- return 1;
163
- }
164
- pd = vfp_reg_ptr(true, rd);
165
- pm = vfp_reg_ptr(true, rm);
166
- if (q) {
167
- switch (size) {
168
- case 0:
169
- gen_helper_neon_qzip8(pd, pm);
170
- break;
171
- case 1:
172
- gen_helper_neon_qzip16(pd, pm);
173
- break;
174
- case 2:
175
- gen_helper_neon_qzip32(pd, pm);
176
- break;
177
- default:
178
- abort();
179
- }
180
- } else {
181
- switch (size) {
182
- case 0:
183
- gen_helper_neon_zip8(pd, pm);
184
- break;
185
- case 1:
186
- gen_helper_neon_zip16(pd, pm);
187
- break;
188
- default:
189
- abort();
190
- }
191
- }
192
- tcg_temp_free_ptr(pd);
193
- tcg_temp_free_ptr(pm);
194
- return 0;
195
-}
196
-
197
static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
198
{
199
TCGv_i32 rd, tmp;
200
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
201
case NEON_2RM_VREV64:
202
case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
203
case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
204
+ case NEON_2RM_VUZP:
205
+ case NEON_2RM_VZIP:
206
/* handled by decodetree */
207
return 1;
208
case NEON_2RM_VTRN:
209
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
210
goto elementwise;
211
}
212
break;
213
- case NEON_2RM_VUZP:
214
- if (gen_neon_unzip(rd, rm, size, q)) {
215
- return 1;
216
- }
217
- break;
218
- case NEON_2RM_VZIP:
219
- if (gen_neon_zip(rd, rm, size, q)) {
220
- return 1;
221
- }
222
- break;
223
case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
224
/* also VQMOVUN; op field and mnemonics don't line up */
225
if (rm & 1) {
226
--
110
--
227
2.20.1
111
2.20.1
228
112
229
113
diff view generated by jsdifflib
1
Convert the VSHLL insn in the 2-reg-misc Neon group to decodetree.
1
The RAS feature has a block of memory-mapped registers at offset
2
0x5000 within the PPB. For a "minimal RAS" implementation we provide
3
no error records and so the only registers that exist in the block
4
are ERRIIDR and ERRDEVID.
5
6
The "RAZ/WI for privileged, BusFault for nonprivileged" behaviour
7
of the "nvic-default" region is actually valid for minimal-RAS,
8
so the main benefit of providing an explicit implementation of
9
the register block is more accurate LOG_UNIMP messages, and a
10
framework for where we could add a real RAS implementation later
11
if necessary.
2
12
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20200616170844.13318-6-peter.maydell@linaro.org
15
Message-id: 20201119215617.29887-27-peter.maydell@linaro.org
6
---
16
---
7
target/arm/neon-dp.decode | 2 ++
17
include/hw/intc/armv7m_nvic.h | 1 +
8
target/arm/translate-neon.inc.c | 52 +++++++++++++++++++++++++++++++++
18
hw/intc/armv7m_nvic.c | 56 +++++++++++++++++++++++++++++++++++
9
target/arm/translate.c | 35 +---------------------
19
2 files changed, 57 insertions(+)
10
3 files changed, 55 insertions(+), 34 deletions(-)
11
20
12
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
21
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
13
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/neon-dp.decode
23
--- a/include/hw/intc/armv7m_nvic.h
15
+++ b/target/arm/neon-dp.decode
24
+++ b/include/hw/intc/armv7m_nvic.h
16
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
25
@@ -XXX,XX +XXX,XX @@ struct NVICState {
17
# VQMOVN: signed result, source may be signed (_S) or unsigned (_U)
26
MemoryRegion sysreg_ns_mem;
18
VQMOVN_S 1111 001 11 . 11 .. 10 .... 0 0101 0 . 0 .... @2misc_q0
27
MemoryRegion systickmem;
19
VQMOVN_U 1111 001 11 . 11 .. 10 .... 0 0101 1 . 0 .... @2misc_q0
28
MemoryRegion systick_ns_mem;
29
+ MemoryRegion ras_mem;
30
MemoryRegion container;
31
MemoryRegion defaultmem;
32
33
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/intc/armv7m_nvic.c
36
+++ b/hw/intc/armv7m_nvic.c
37
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_systick_ops = {
38
.endianness = DEVICE_NATIVE_ENDIAN,
39
};
40
20
+
41
+
21
+ VSHLL 1111 001 11 . 11 .. 10 .... 0 0110 0 . 0 .... @2misc_q0
42
+static MemTxResult ras_read(void *opaque, hwaddr addr,
22
]
43
+ uint64_t *data, unsigned size,
23
44
+ MemTxAttrs attrs)
24
# Subgroup for size != 0b11
25
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
26
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/translate-neon.inc.c
28
+++ b/target/arm/translate-neon.inc.c
29
@@ -XXX,XX +XXX,XX @@ DO_VMOVN(VMOVN, gen_neon_narrow_u)
30
DO_VMOVN(VQMOVUN, gen_helper_neon_unarrow_sat)
31
DO_VMOVN(VQMOVN_S, gen_helper_neon_narrow_sat_s)
32
DO_VMOVN(VQMOVN_U, gen_helper_neon_narrow_sat_u)
33
+
34
+static bool trans_VSHLL(DisasContext *s, arg_2misc *a)
35
+{
45
+{
36
+ TCGv_i32 rm0, rm1;
46
+ if (attrs.user) {
37
+ TCGv_i64 rd;
47
+ return MEMTX_ERROR;
38
+ static NeonGenWidenFn * const widenfns[] = {
39
+ gen_helper_neon_widen_u8,
40
+ gen_helper_neon_widen_u16,
41
+ tcg_gen_extu_i32_i64,
42
+ NULL,
43
+ };
44
+ NeonGenWidenFn *widenfn = widenfns[a->size];
45
+
46
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
47
+ return false;
48
+ }
48
+ }
49
+
49
+
50
+ /* UNDEF accesses to D16-D31 if they don't exist. */
50
+ switch (addr) {
51
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
51
+ case 0xe10: /* ERRIIDR */
52
+ ((a->vd | a->vm) & 0x10)) {
52
+ /* architect field = Arm; product/variant/revision 0 */
53
+ return false;
53
+ *data = 0x43b;
54
+ break;
55
+ case 0xfc8: /* ERRDEVID */
56
+ /* Minimal RAS: we implement 0 error record indexes */
57
+ *data = 0;
58
+ break;
59
+ default:
60
+ qemu_log_mask(LOG_UNIMP, "Read RAS register offset 0x%x\n",
61
+ (uint32_t)addr);
62
+ *data = 0;
63
+ break;
64
+ }
65
+ return MEMTX_OK;
66
+}
67
+
68
+static MemTxResult ras_write(void *opaque, hwaddr addr,
69
+ uint64_t value, unsigned size,
70
+ MemTxAttrs attrs)
71
+{
72
+ if (attrs.user) {
73
+ return MEMTX_ERROR;
54
+ }
74
+ }
55
+
75
+
56
+ if (a->vd & 1) {
76
+ switch (addr) {
57
+ return false;
77
+ default:
78
+ qemu_log_mask(LOG_UNIMP, "Write to RAS register offset 0x%x\n",
79
+ (uint32_t)addr);
80
+ break;
81
+ }
82
+ return MEMTX_OK;
83
+}
84
+
85
+static const MemoryRegionOps ras_ops = {
86
+ .read_with_attrs = ras_read,
87
+ .write_with_attrs = ras_write,
88
+ .endianness = DEVICE_NATIVE_ENDIAN,
89
+};
90
+
91
/*
92
* Unassigned portions of the PPB space are RAZ/WI for privileged
93
* accesses, and fault for non-privileged accesses.
94
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
95
&s->systick_ns_mem, 1);
96
}
97
98
+ if (cpu_isar_feature(aa32_ras, s->cpu)) {
99
+ memory_region_init_io(&s->ras_mem, OBJECT(s),
100
+ &ras_ops, s, "nvic_ras", 0x1000);
101
+ memory_region_add_subregion(&s->container, 0x5000, &s->ras_mem);
58
+ }
102
+ }
59
+
103
+
60
+ if (!widenfn) {
104
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->container);
61
+ return false;
62
+ }
63
+
64
+ if (!vfp_access_check(s)) {
65
+ return true;
66
+ }
67
+
68
+ rd = tcg_temp_new_i64();
69
+
70
+ rm0 = neon_load_reg(a->vm, 0);
71
+ rm1 = neon_load_reg(a->vm, 1);
72
+
73
+ widenfn(rd, rm0);
74
+ tcg_gen_shli_i64(rd, rd, 8 << a->size);
75
+ neon_store_reg64(rd, a->vd);
76
+ widenfn(rd, rm1);
77
+ tcg_gen_shli_i64(rd, rd, 8 << a->size);
78
+ neon_store_reg64(rd, a->vd + 1);
79
+
80
+ tcg_temp_free_i64(rd);
81
+ tcg_temp_free_i32(rm0);
82
+ tcg_temp_free_i32(rm1);
83
+ return true;
84
+}
85
diff --git a/target/arm/translate.c b/target/arm/translate.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/target/arm/translate.c
88
+++ b/target/arm/translate.c
89
@@ -XXX,XX +XXX,XX @@ static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
90
tcg_temp_free_i32(rd);
91
}
105
}
92
106
93
-static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
94
-{
95
- if (u) {
96
- switch (size) {
97
- case 0: gen_helper_neon_widen_u8(dest, src); break;
98
- case 1: gen_helper_neon_widen_u16(dest, src); break;
99
- case 2: tcg_gen_extu_i32_i64(dest, src); break;
100
- default: abort();
101
- }
102
- } else {
103
- switch (size) {
104
- case 0: gen_helper_neon_widen_s8(dest, src); break;
105
- case 1: gen_helper_neon_widen_s16(dest, src); break;
106
- case 2: tcg_gen_ext_i32_i64(dest, src); break;
107
- default: abort();
108
- }
109
- }
110
- tcg_temp_free_i32(src);
111
-}
112
-
113
/* Symbolic constants for op fields for Neon 2-register miscellaneous.
114
* The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
115
* table A7-13.
116
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
117
case NEON_2RM_VUZP:
118
case NEON_2RM_VZIP:
119
case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
120
+ case NEON_2RM_VSHLL:
121
/* handled by decodetree */
122
return 1;
123
case NEON_2RM_VTRN:
124
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
125
goto elementwise;
126
}
127
break;
128
- case NEON_2RM_VSHLL:
129
- if (q || (rd & 1)) {
130
- return 1;
131
- }
132
- tmp = neon_load_reg(rm, 0);
133
- tmp2 = neon_load_reg(rm, 1);
134
- for (pass = 0; pass < 2; pass++) {
135
- if (pass == 1)
136
- tmp = tmp2;
137
- gen_neon_widen(cpu_V0, tmp, size, 1);
138
- tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
139
- neon_store_reg64(cpu_V0, rd + pass);
140
- }
141
- break;
142
case NEON_2RM_VCVT_F16_F32:
143
{
144
TCGv_ptr fpst;
145
--
107
--
146
2.20.1
108
2.20.1
147
109
148
110
diff view generated by jsdifflib
1
In commit cfdb2c0c95ae9205b0 ("target/arm: Vectorize SABA/UABA") we
1
Correct a typo in the name we give the NVIC object.
2
replaced the old handling of SABA/UABA with a vectorized implementation
3
which returns early rather than falling into the loop-ever-elements
4
code. We forgot to delete the part of the old looping code that
5
did the accumulate step, and Coverity correctly warns (CID 1428955)
6
that this code is now dead. Delete it.
7
2
8
Fixes: cfdb2c0c95ae9205b0
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20200619171547.29780-1-peter.maydell@linaro.org
6
Message-id: 20201119215617.29887-28-peter.maydell@linaro.org
13
---
7
---
14
target/arm/translate-a64.c | 12 ------------
8
hw/arm/armv7m.c | 2 +-
15
1 file changed, 12 deletions(-)
9
1 file changed, 1 insertion(+), 1 deletion(-)
16
10
17
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
11
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
18
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/translate-a64.c
13
--- a/hw/arm/armv7m.c
20
+++ b/target/arm/translate-a64.c
14
+++ b/hw/arm/armv7m.c
21
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
15
@@ -XXX,XX +XXX,XX @@ static void armv7m_instance_init(Object *obj)
22
genfn(tcg_res, tcg_op1, tcg_op2);
16
23
}
17
memory_region_init(&s->container, obj, "armv7m-container", UINT64_MAX);
24
18
25
- if (opcode == 0xf) {
19
- object_initialize_child(obj, "nvnic", &s->nvic, TYPE_NVIC);
26
- /* SABA, UABA: accumulating ops */
20
+ object_initialize_child(obj, "nvic", &s->nvic, TYPE_NVIC);
27
- static NeonGenTwoOpFn * const fns[3] = {
21
object_property_add_alias(obj, "num-irq",
28
- gen_helper_neon_add_u8,
22
OBJECT(&s->nvic), "num-irq");
29
- gen_helper_neon_add_u16,
23
30
- tcg_gen_add_i32,
31
- };
32
-
33
- read_vec_element_i32(s, tcg_op1, rd, pass, MO_32);
34
- fns[size](tcg_res, tcg_op1, tcg_res);
35
- }
36
-
37
write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
38
39
tcg_temp_free_i32(tcg_res);
40
--
24
--
41
2.20.1
25
2.20.1
42
26
43
27
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
Add a trace event to see when a guest disable/enable the watchdog.
4
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20200617072539.32686-2-f4bug@amsat.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
hw/watchdog/cmsdk-apb-watchdog.c | 1 +
11
hw/watchdog/trace-events | 1 +
12
2 files changed, 2 insertions(+)
13
14
diff --git a/hw/watchdog/cmsdk-apb-watchdog.c b/hw/watchdog/cmsdk-apb-watchdog.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/watchdog/cmsdk-apb-watchdog.c
17
+++ b/hw/watchdog/cmsdk-apb-watchdog.c
18
@@ -XXX,XX +XXX,XX @@ static void cmsdk_apb_watchdog_write(void *opaque, hwaddr offset,
19
break;
20
case A_WDOGLOCK:
21
s->lock = (value != WDOG_UNLOCK_VALUE);
22
+ trace_cmsdk_apb_watchdog_lock(s->lock);
23
break;
24
case A_WDOGITCR:
25
if (s->is_luminary) {
26
diff --git a/hw/watchdog/trace-events b/hw/watchdog/trace-events
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/watchdog/trace-events
29
+++ b/hw/watchdog/trace-events
30
@@ -XXX,XX +XXX,XX @@
31
cmsdk_apb_watchdog_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB watchdog read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
32
cmsdk_apb_watchdog_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB watchdog write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
33
cmsdk_apb_watchdog_reset(void) "CMSDK APB watchdog: reset"
34
+cmsdk_apb_watchdog_lock(uint32_t lock) "CMSDK APB watchdog: lock %" PRIu32
35
--
36
2.20.1
37
38
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
Use self-explicit definitions instead of magic values.
4
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20200617072539.32686-3-f4bug@amsat.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
hw/i2c/versatile_i2c.c | 14 ++++++++++----
11
1 file changed, 10 insertions(+), 4 deletions(-)
12
13
diff --git a/hw/i2c/versatile_i2c.c b/hw/i2c/versatile_i2c.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/i2c/versatile_i2c.c
16
+++ b/hw/i2c/versatile_i2c.c
17
@@ -XXX,XX +XXX,XX @@
18
#include "qemu/osdep.h"
19
#include "hw/sysbus.h"
20
#include "hw/i2c/bitbang_i2c.h"
21
+#include "hw/registerfields.h"
22
#include "qemu/log.h"
23
#include "qemu/module.h"
24
25
@@ -XXX,XX +XXX,XX @@ typedef struct VersatileI2CState {
26
int in;
27
} VersatileI2CState;
28
29
+REG32(CONTROL_GET, 0)
30
+REG32(CONTROL_SET, 0)
31
+REG32(CONTROL_CLR, 4)
32
+
33
static uint64_t versatile_i2c_read(void *opaque, hwaddr offset,
34
unsigned size)
35
{
36
VersatileI2CState *s = (VersatileI2CState *)opaque;
37
38
- if (offset == 0) {
39
+ switch (offset) {
40
+ case A_CONTROL_SET:
41
return (s->out & 1) | (s->in << 1);
42
- } else {
43
+ default:
44
qemu_log_mask(LOG_GUEST_ERROR,
45
"%s: Bad offset 0x%x\n", __func__, (int)offset);
46
return -1;
47
@@ -XXX,XX +XXX,XX @@ static void versatile_i2c_write(void *opaque, hwaddr offset,
48
VersatileI2CState *s = (VersatileI2CState *)opaque;
49
50
switch (offset) {
51
- case 0:
52
+ case A_CONTROL_SET:
53
s->out |= value & 3;
54
break;
55
- case 4:
56
+ case A_CONTROL_CLR:
57
s->out &= ~value;
58
break;
59
default:
60
--
61
2.20.1
62
63
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
Use self-explicit definitions instead of magic values.
4
5
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20200617072539.32686-4-f4bug@amsat.org
7
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
hw/i2c/versatile_i2c.c | 7 +++++--
11
1 file changed, 5 insertions(+), 2 deletions(-)
12
13
diff --git a/hw/i2c/versatile_i2c.c b/hw/i2c/versatile_i2c.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/i2c/versatile_i2c.c
16
+++ b/hw/i2c/versatile_i2c.c
17
@@ -XXX,XX +XXX,XX @@ REG32(CONTROL_GET, 0)
18
REG32(CONTROL_SET, 0)
19
REG32(CONTROL_CLR, 4)
20
21
+#define SCL BIT(0)
22
+#define SDA BIT(1)
23
+
24
static uint64_t versatile_i2c_read(void *opaque, hwaddr offset,
25
unsigned size)
26
{
27
@@ -XXX,XX +XXX,XX @@ static void versatile_i2c_write(void *opaque, hwaddr offset,
28
qemu_log_mask(LOG_GUEST_ERROR,
29
"%s: Bad offset 0x%x\n", __func__, (int)offset);
30
}
31
- bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SCL, (s->out & 1) != 0);
32
- s->in = bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SDA, (s->out & 2) != 0);
33
+ bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SCL, (s->out & SCL) != 0);
34
+ s->in = bitbang_i2c_set(&s->bitbang, BITBANG_I2C_SDA, (s->out & SDA) != 0);
35
}
36
37
static const MemoryRegionOps versatile_i2c_ops = {
38
--
39
2.20.1
40
41
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
Message-id: 20200617072539.32686-7-f4bug@amsat.org
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
hw/arm/mps2.c | 5 ++++-
9
1 file changed, 4 insertions(+), 1 deletion(-)
10
11
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/mps2.c
14
+++ b/hw/arm/mps2.c
15
@@ -XXX,XX +XXX,XX @@ typedef struct {
16
MemoryRegion blockram_m2;
17
MemoryRegion blockram_m3;
18
MemoryRegion sram;
19
+ /* FPGA APB subsystem */
20
MPS2SCC scc;
21
+ /* CMSDK APB subsystem */
22
CMSDKAPBDualTimer dualtimer;
23
} MPS2MachineState;
24
25
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
26
g_assert_not_reached();
27
}
28
29
+ /* CMSDK APB subsystem */
30
cmsdk_apb_timer_create(0x40000000, qdev_get_gpio_in(armv7m, 8), SYSCLK_FRQ);
31
cmsdk_apb_timer_create(0x40001000, qdev_get_gpio_in(armv7m, 9), SYSCLK_FRQ);
32
-
33
object_initialize_child(OBJECT(mms), "dualtimer", &mms->dualtimer,
34
TYPE_CMSDK_APB_DUALTIMER);
35
qdev_prop_set_uint32(DEVICE(&mms->dualtimer), "pclk-frq", SYSCLK_FRQ);
36
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
37
qdev_get_gpio_in(armv7m, 10));
38
sysbus_mmio_map(SYS_BUS_DEVICE(&mms->dualtimer), 0, 0x40002000);
39
40
+ /* FPGA APB subsystem */
41
object_initialize_child(OBJECT(mms), "scc", &mms->scc, TYPE_MPS2_SCC);
42
sccdev = DEVICE(&mms->scc);
43
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
44
--
45
2.20.1
46
47
diff view generated by jsdifflib
Deleted patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
1
3
To differenciate with the CMSDK APB peripheral region,
4
rename this region 'CMSDK AHB peripheral region'.
5
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20200617072539.32686-8-f4bug@amsat.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/arm/mps2.c | 3 ++-
12
1 file changed, 2 insertions(+), 1 deletion(-)
13
14
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/mps2.c
17
+++ b/hw/arm/mps2.c
18
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
19
*/
20
create_unimplemented_device("CMSDK APB peripheral region @0x40000000",
21
0x40000000, 0x00010000);
22
- create_unimplemented_device("CMSDK peripheral region @0x40010000",
23
+ create_unimplemented_device("CMSDK AHB peripheral region @0x40010000",
24
0x40010000, 0x00010000);
25
create_unimplemented_device("Extra peripheral region @0x40020000",
26
0x40020000, 0x00010000);
27
+
28
create_unimplemented_device("RESERVED 4", 0x40030000, 0x001D0000);
29
create_unimplemented_device("VGA", 0x41000000, 0x0200000);
30
31
--
32
2.20.1
33
34
diff view generated by jsdifflib