1
Mostly my decodetree stuff, but also some patches for various
1
The following changes since commit ec397e90d21269037280633b6058d1f280e27667:
2
smaller bugs/features from others.
3
2
4
thanks
3
Merge remote-tracking branch 'remotes/alistair/tags/pull-riscv-to-apply-20210901-2' into staging (2021-09-01 08:33:02 +0100)
5
-- PMM
6
7
The following changes since commit 53550e81e2cafe7c03a39526b95cd21b5194d9b1:
8
9
Merge remote-tracking branch 'remotes/berrange/tags/qcrypto-next-pull-request' into staging (2020-06-15 16:36:34 +0100)
10
4
11
are available in the Git repository at:
5
are available in the Git repository at:
12
6
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200616
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210901
14
8
15
for you to fetch changes up to 64b397417a26509bcdff44ab94356a35c7901c79:
9
for you to fetch changes up to 683754c7b61f9e2ff098720ec80c9ab86c54663d:
16
10
17
hw: arm: Set vendor property for IMX SDHCI emulations (2020-06-16 10:32:29 +0100)
11
arm: Remove system_clock_scale global (2021-09-01 11:08:21 +0100)
18
12
19
----------------------------------------------------------------
13
----------------------------------------------------------------
20
* hw: arm: Set vendor property for IMX SDHCI emulations
14
* Refactor M-profile systick to use Clocks instead of system_clock_scale global
21
* sd: sdhci: Implement basic vendor specific register support
15
* clock: Provide builtin multiplier/divider
22
* hw/net/imx_fec: Convert debug fprintf() to trace events
16
* Add A64FX processor model
23
* target/arm/cpu: adjust virtual time for all KVM arm cpus
17
* Enable MVE emulation in Cortex-M55
24
* Implement configurable descriptor size in ftgmac100
18
* hw: Add compat machines for 6.2
25
* hw/misc/imx6ul_ccm: Implement non writable bits in CCM registers
19
* hw/intc/arm_gicv3: Replace mis-used MEMTX_* constants by booleans
26
* target/arm: More Neon decodetree conversion work
20
* hw/arm/raspi: Remove deprecated raspi2/raspi3 aliases
27
21
28
----------------------------------------------------------------
22
----------------------------------------------------------------
29
Erik Smit (1):
23
Peter Maydell (43):
30
Implement configurable descriptor size in ftgmac100
24
target/arm: Implement MVE VADD (floating-point)
25
target/arm: Implement MVE VSUB, VMUL, VABD, VMAXNM, VMINNM
26
target/arm: Implement MVE VCADD
27
target/arm: Implement MVE VFMA and VFMS
28
target/arm: Implement MVE VCMUL and VCMLA
29
target/arm: Implement MVE VMAXNMA and VMINNMA
30
target/arm: Implement MVE scalar fp insns
31
target/arm: Implement MVE fp-with-scalar VFMA, VFMAS
32
softfloat: Remove assertion preventing silencing of NaN in default-NaN mode
33
target/arm: Implement MVE FP max/min across vector
34
target/arm: Implement MVE fp vector comparisons
35
target/arm: Implement MVE fp scalar comparisons
36
target/arm: Implement MVE VCVT between floating and fixed point
37
target/arm: Implement MVE VCVT between fp and integer
38
target/arm: Implement MVE VCVT with specified rounding mode
39
target/arm: Implement MVE VCVT between single and half precision
40
target/arm: Implement MVE VRINT insns
41
target/arm: Enable MVE in Cortex-M55
42
arm: Move M-profile RAS register block into its own device
43
arm: Move systick device creation from NVIC to ARMv7M object
44
arm: Move system PPB container handling to armv7m
45
hw/timer/armv7m_systick: Add usual QEMU interface comment
46
hw/timer/armv7m_systick: Add input clocks
47
hw/arm/armv7m: Create input clocks
48
armsse: Wire up systick cpuclk clock
49
hw/arm/mps2.c: Connect up armv7m clocks
50
clock: Provide builtin multiplier/divider
51
hw/arm: Don't allocate separate MemoryRegions in stm32 SoC realize
52
hw/arm/stm32f100: Wire up sysclk and refclk
53
hw/arm/stm32f205: Wire up sysclk and refclk
54
hw/arm/stm32f405: Wire up sysclk and refclk
55
hw/arm/stm32vldiscovery: Delete trailing blank line
56
hw/arm/nrf51: Wire up sysclk
57
hw/arm/stellaris: split stellaris_sys_init()
58
hw/arm/stellaris: Wire sysclk up to armv7m
59
hw/arm/msf2_soc: Don't allocate separate MemoryRegions
60
hw/arm/msf2: Use Clock input to MSF2_SOC instead of m3clk property
61
hw/arm/msf2-soc: Wire up refclk
62
hw/timer/armv7m_systick: Use clock inputs instead of system_clock_scale
63
hw/arm/stellaris: Fix code style issues in GPTM code
64
hw/arm/stellaris: Split stellaris-gptm into its own file
65
hw/timer/stellaris-gptm: Use Clock input instead of system_clock_scale
66
arm: Remove system_clock_scale global
31
67
32
Guenter Roeck (2):
68
Philippe Mathieu-Daudé (4):
33
sd: sdhci: Implement basic vendor specific register support
69
tests: Remove uses of deprecated raspi2/raspi3 machine names
34
hw: arm: Set vendor property for IMX SDHCI emulations
70
hw/arm/raspi: Remove deprecated raspi2/raspi3 aliases
71
hw/intc/arm_gicv3_dist: Rename 64-bit accessors with 'q' suffix
72
hw/intc/arm_gicv3: Replace mis-used MEMTX_* constants by booleans
35
73
36
Jean-Christophe Dubois (2):
74
Shuuichirou Ishii (3):
37
hw/misc/imx6ul_ccm: Implement non writable bits in CCM registers
75
target-arm: Add support for Fujitsu A64FX
38
hw/net/imx_fec: Convert debug fprintf() to trace events
76
hw/arm/virt: target-arm: Add A64FX processor support to virt machine
77
tests/arm-cpu-features: Add A64FX processor related tests
39
78
40
Peter Maydell (17):
79
Yanan Wang (1):
41
target/arm: Fix missing temp frees in do_vshll_2sh
80
hw: Add compat machines for 6.2
42
target/arm: Convert Neon 3-reg-diff prewidening ops to decodetree
43
target/arm: Convert Neon 3-reg-diff narrowing ops to decodetree
44
target/arm: Convert Neon 3-reg-diff VABAL, VABDL to decodetree
45
target/arm: Convert Neon 3-reg-diff long multiplies
46
target/arm: Convert Neon 3-reg-diff saturating doubling multiplies
47
target/arm: Convert Neon 3-reg-diff polynomial VMULL
48
target/arm: Add 'static' and 'const' annotations to VSHLL function arrays
49
target/arm: Add missing TCG temp free in do_2shift_env_64()
50
target/arm: Convert Neon 2-reg-scalar integer multiplies to decodetree
51
target/arm: Convert Neon 2-reg-scalar float multiplies to decodetree
52
target/arm: Convert Neon 2-reg-scalar VQDMULH, VQRDMULH to decodetree
53
target/arm: Convert Neon 2-reg-scalar VQRDMLAH, VQRDMLSH to decodetree
54
target/arm: Convert Neon 2-reg-scalar long multiplies to decodetree
55
target/arm: Convert Neon VEXT to decodetree
56
target/arm: Convert Neon VTBL, VTBX to decodetree
57
target/arm: Convert Neon VDUP (scalar) to decodetree
58
81
59
fangying (1):
82
docs/about/deprecated.rst | 7 -
60
target/arm/cpu: adjust virtual time for all KVM arm cpus
83
docs/about/removed-features.rst | 7 +
84
docs/devel/clocks.rst | 23 ++
85
docs/devel/qgraph.rst | 38 +-
86
docs/system/arm/virt.rst | 1 +
87
include/hw/arm/armv7m.h | 24 ++
88
include/hw/arm/msf2-soc.h | 8 +-
89
include/hw/arm/nrf51_soc.h | 2 +
90
include/hw/arm/stm32f100_soc.h | 8 +
91
include/hw/arm/stm32f205_soc.h | 8 +
92
include/hw/arm/stm32f405_soc.h | 3 +
93
include/hw/boards.h | 3 +
94
include/hw/clock.h | 29 ++
95
include/hw/i386/pc.h | 3 +
96
include/hw/intc/armv7m_nvic.h | 8 -
97
include/hw/misc/armv7m_ras.h | 37 ++
98
include/hw/timer/armv7m_systick.h | 36 +-
99
include/hw/timer/stellaris-gptm.h | 51 +++
100
target/arm/helper-mve.h | 142 +++++++
101
target/arm/translate.h | 6 +
102
tests/qtest/libqos/qgraph.h | 6 +-
103
tests/qtest/libqos/qgraph_internal.h | 2 +-
104
target/arm/mve.decode | 297 +++++++++++++--
105
hw/arm/armsse.c | 20 +-
106
hw/arm/armv7m.c | 260 ++++++++++++-
107
hw/arm/mps2.c | 17 +-
108
hw/arm/msf2-soc.c | 68 ++--
109
hw/arm/msf2-som.c | 7 +-
110
hw/arm/netduino2.c | 12 +-
111
hw/arm/netduinoplus2.c | 12 +-
112
hw/arm/nrf51_soc.c | 20 +-
113
hw/arm/raspi.c | 2 -
114
hw/arm/stellaris.c | 396 +++----------------
115
hw/arm/stm32f100_soc.c | 47 ++-
116
hw/arm/stm32f205_soc.c | 47 ++-
117
hw/arm/stm32f405_soc.c | 30 ++
118
hw/arm/stm32vldiscovery.c | 13 +-
119
hw/arm/virt.c | 12 +-
120
hw/core/clock-vmstate.c | 40 +-
121
hw/core/clock.c | 31 +-
122
hw/core/machine.c | 3 +
123
hw/i386/pc.c | 3 +
124
hw/i386/pc_piix.c | 14 +-
125
hw/i386/pc_q35.c | 13 +-
126
hw/intc/arm_gicv3_dist.c | 205 +++++-----
127
hw/intc/armv7m_nvic.c | 274 +-------------
128
hw/misc/armv7m_ras.c | 93 +++++
129
hw/ppc/spapr.c | 17 +-
130
hw/s390x/s390-virtio-ccw.c | 14 +-
131
hw/timer/armv7m_systick.c | 118 ++++--
132
hw/timer/stellaris-gptm.c | 332 ++++++++++++++++
133
target/arm/cpu64.c | 48 +++
134
target/arm/cpu_tcg.c | 7 +-
135
target/arm/mve_helper.c | 650 ++++++++++++++++++++++++++++++++
136
target/arm/translate-mve.c | 277 +++++++++++++-
137
target/arm/translate-neon.c | 6 -
138
tests/qtest/arm-cpu-features.c | 13 +
139
tests/qtest/boot-serial-test.c | 2 +-
140
tests/qtest/libqos/arm-raspi2-machine.c | 8 +-
141
tests/unit/test-qgraph.c | 2 +-
142
fpu/softfloat-specialize.c.inc | 1 -
143
MAINTAINERS | 2 +
144
hw/arm/Kconfig | 1 +
145
hw/core/trace-events | 1 +
146
hw/misc/meson.build | 2 +
147
hw/timer/Kconfig | 3 +
148
hw/timer/meson.build | 1 +
149
tests/acceptance/boot_linux_console.py | 6 +-
150
68 files changed, 2928 insertions(+), 971 deletions(-)
151
create mode 100644 include/hw/misc/armv7m_ras.h
152
create mode 100644 include/hw/timer/stellaris-gptm.h
153
create mode 100644 hw/misc/armv7m_ras.c
154
create mode 100644 hw/timer/stellaris-gptm.c
61
155
62
hw/sd/sdhci-internal.h | 5 +
63
include/hw/sd/sdhci.h | 5 +
64
target/arm/translate.h | 1 +
65
target/arm/neon-dp.decode | 130 +++++
66
hw/arm/fsl-imx25.c | 6 +
67
hw/arm/fsl-imx6.c | 6 +
68
hw/arm/fsl-imx6ul.c | 2 +
69
hw/arm/fsl-imx7.c | 2 +
70
hw/misc/imx6ul_ccm.c | 76 ++-
71
hw/net/ftgmac100.c | 26 +-
72
hw/net/imx_fec.c | 106 ++--
73
hw/sd/sdhci.c | 18 +-
74
target/arm/cpu.c | 6 +-
75
target/arm/cpu64.c | 1 -
76
target/arm/kvm.c | 21 +-
77
target/arm/translate-neon.inc.c | 1148 ++++++++++++++++++++++++++++++++++++++-
78
target/arm/translate.c | 684 +----------------------
79
hw/net/trace-events | 18 +
80
18 files changed, 1495 insertions(+), 766 deletions(-)
81
diff view generated by jsdifflib
New patch
1
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
3
Commit 155e1c82ed0 deprecated the raspi2/raspi3 machine names.
4
Use the recommended new names: raspi2b and raspi3b.
5
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Thomas Huth <thuth@redhat.com>
8
Reviewed-by: Willian Rampazzo <willianr@redhat.com>
9
Message-id: 20210827060815.2384760-2-f4bug@amsat.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
docs/devel/qgraph.rst | 38 ++++++++++++-------------
13
tests/qtest/libqos/qgraph.h | 6 ++--
14
tests/qtest/libqos/qgraph_internal.h | 2 +-
15
tests/qtest/boot-serial-test.c | 2 +-
16
tests/qtest/libqos/arm-raspi2-machine.c | 8 +++---
17
tests/unit/test-qgraph.c | 2 +-
18
tests/acceptance/boot_linux_console.py | 6 ++--
19
7 files changed, 32 insertions(+), 32 deletions(-)
20
21
diff --git a/docs/devel/qgraph.rst b/docs/devel/qgraph.rst
22
index XXXXXXX..XXXXXXX 100644
23
--- a/docs/devel/qgraph.rst
24
+++ b/docs/devel/qgraph.rst
25
@@ -XXX,XX +XXX,XX @@ Nodes
26
27
A node can be of four types:
28
29
-- **QNODE_MACHINE**: for example ``arm/raspi2``
30
+- **QNODE_MACHINE**: for example ``arm/raspi2b``
31
- **QNODE_DRIVER**: for example ``generic-sdhci``
32
- **QNODE_INTERFACE**: for example ``sdhci`` (interface for all ``-sdhci``
33
drivers).
34
@@ -XXX,XX +XXX,XX @@ It is possible to troubleshoot unavailable tests by running::
35
# |-> dest='i440FX-pcihost' type=0 (node=0x5591421117f0)
36
# src=''
37
# |-> dest='x86_64/pc' type=0 (node=0x559142111600)
38
- # |-> dest='arm/raspi2' type=0 (node=0x559142110740)
39
+ # |-> dest='arm/raspi2b' type=0 (node=0x559142110740)
40
...
41
# }
42
# ALL QGRAPH NODES: {
43
# name='virtio-net-tests/announce-self' type=3 cmd_line='(null)' [available]
44
- # name='arm/raspi2' type=0 cmd_line='-M raspi2 ' [UNAVAILABLE]
45
+ # name='arm/raspi2b' type=0 cmd_line='-M raspi2b ' [UNAVAILABLE]
46
...
47
# }
48
49
@@ -XXX,XX +XXX,XX @@ qgraph path in the "ALL QGRAPH EDGES" output as follows: '' -> 'x86_64/pc' ->
50
'virtio-net'. The root of the qgraph is '' and the depth first search begins
51
there.
52
53
-The ``arm/raspi`` machine node is listed as "UNAVAILABLE". Although it is
54
-reachable from the root via '' -> 'arm/raspi2' the node is unavailable because
55
+The ``arm/raspi2b`` machine node is listed as "UNAVAILABLE". Although it is
56
+reachable from the root via '' -> 'arm/raspi2b' the node is unavailable because
57
the QEMU binary did not list it when queried by the framework. This is expected
58
because we used the ``qemu-system-x86_64`` binary which does not support ARM
59
machine types.
60
@@ -XXX,XX +XXX,XX @@ Here we continue the ``sdhci`` use case, with the following scenario:
61
- ``sdhci-test`` aims to test the ``read[q,w], writeq`` functions
62
offered by the ``sdhci`` drivers.
63
- The current ``sdhci`` device is supported by both ``x86_64/pc`` and ``ARM``
64
- (in this example we focus on the ``arm-raspi2``) machines.
65
+ (in this example we focus on the ``arm-raspi2b``) machines.
66
- QEMU offers 2 types of drivers: ``QSDHCI_MemoryMapped`` for ``ARM`` and
67
``QSDHCI_PCI`` for ``x86_64/pc``. Both implement the
68
``read[q,w], writeq`` functions.
69
@@ -XXX,XX +XXX,XX @@ In order to implement such scenario in qgraph, the test developer needs to:
70
all the pci drivers available)
71
72
``sdhci-pci --consumes--> pci-bus``
73
-- Create an ``arm/raspi2`` machine node. This machine ``contains``
74
+- Create an ``arm/raspi2b`` machine node. This machine ``contains``
75
a ``generic-sdhci`` memory mapped ``sdhci`` driver node, representing
76
``QSDHCI_MemoryMapped``.
77
78
- ``arm/raspi2 --contains--> generic-sdhci``
79
+ ``arm/raspi2b --contains--> generic-sdhci``
80
- Create the ``sdhci`` interface node. This interface offers the
81
functions that are shared by all ``sdhci`` devices.
82
The interface is produced by ``sdhci-pci`` and ``generic-sdhci``,
83
@@ -XXX,XX +XXX,XX @@ In order to implement such scenario in qgraph, the test developer needs to:
84
85
``sdhci-test --consumes--> sdhci``
86
87
-``arm-raspi2`` machine, simplified from
88
+``arm-raspi2b`` machine, simplified from
89
``tests/qtest/libqos/arm-raspi2-machine.c``::
90
91
#include "qgraph.h"
92
@@ -XXX,XX +XXX,XX @@ In order to implement such scenario in qgraph, the test developer needs to:
93
return &machine->alloc;
94
}
95
96
- fprintf(stderr, "%s not present in arm/raspi2\n", interface);
97
+ fprintf(stderr, "%s not present in arm/raspi2b\n", interface);
98
g_assert_not_reached();
99
}
100
101
@@ -XXX,XX +XXX,XX @@ In order to implement such scenario in qgraph, the test developer needs to:
102
return &machine->sdhci.obj;
103
}
104
105
- fprintf(stderr, "%s not present in arm/raspi2\n", device);
106
+ fprintf(stderr, "%s not present in arm/raspi2b\n", device);
107
g_assert_not_reached();
108
}
109
110
@@ -XXX,XX +XXX,XX @@ In order to implement such scenario in qgraph, the test developer needs to:
111
112
static void raspi2_register_nodes(void)
113
{
114
- /* arm/raspi2 --contains--> generic-sdhci */
115
- qos_node_create_machine("arm/raspi2",
116
+ /* arm/raspi2b --contains--> generic-sdhci */
117
+ qos_node_create_machine("arm/raspi2b",
118
qos_create_machine_arm_raspi2);
119
- qos_node_contains("arm/raspi2", "generic-sdhci", NULL);
120
+ qos_node_contains("arm/raspi2b", "generic-sdhci", NULL);
121
}
122
123
libqos_init(raspi2_register_nodes);
124
@@ -XXX,XX +XXX,XX @@ In the above example, all possible types of relations are created::
125
|
126
+--produces-- +
127
|
128
- arm/raspi2 --contains--> generic-sdhci
129
+ arm/raspi2b --contains--> generic-sdhci
130
131
or inverting the consumes edge in consumed_by::
132
133
@@ -XXX,XX +XXX,XX @@ or inverting the consumes edge in consumed_by::
134
|
135
+--produces-- +
136
|
137
- arm/raspi2 --contains--> generic-sdhci
138
+ arm/raspi2b --contains--> generic-sdhci
139
140
Adding a new test
141
"""""""""""""""""
142
@@ -XXX,XX +XXX,XX @@ Final graph will be like this::
143
|
144
+--produces-- +
145
|
146
- arm/raspi2 --contains--> generic-sdhci
147
+ arm/raspi2b --contains--> generic-sdhci
148
149
or inverting the consumes edge in consumed_by::
150
151
@@ -XXX,XX +XXX,XX @@ or inverting the consumes edge in consumed_by::
152
|
153
+--produces-- +
154
|
155
- arm/raspi2 --contains--> generic-sdhci
156
+ arm/raspi2b --contains--> generic-sdhci
157
158
Assuming there the binary is
159
``QTEST_QEMU_BINARY=./qemu-system-x86_64``
160
@@ -XXX,XX +XXX,XX @@ a valid test path will be:
161
162
and for the binary ``QTEST_QEMU_BINARY=./qemu-system-arm``:
163
164
-``/arm/raspi2/generic-sdhci/sdhci/sdhci-test``
165
+``/arm/raspi2b/generic-sdhci/sdhci/sdhci-test``
166
167
Additional examples are also in ``test-qgraph.c``
168
169
diff --git a/tests/qtest/libqos/qgraph.h b/tests/qtest/libqos/qgraph.h
170
index XXXXXXX..XXXXXXX 100644
171
--- a/tests/qtest/libqos/qgraph.h
172
+++ b/tests/qtest/libqos/qgraph.h
173
@@ -XXX,XX +XXX,XX @@ void qos_node_create_driver_named(const char *name, const char *qemu_name,
174
* This function can be useful when there are multiple devices
175
* with the same node name contained in a machine/other node
176
*
177
- * For example, if ``arm/raspi2`` contains 2 ``generic-sdhci``
178
+ * For example, if ``arm/raspi2b`` contains 2 ``generic-sdhci``
179
* devices, the right commands will be:
180
*
181
* .. code::
182
*
183
- * qos_node_create_machine("arm/raspi2");
184
+ * qos_node_create_machine("arm/raspi2b");
185
* qos_node_create_driver("generic-sdhci", constructor);
186
* // assume rest of the fields are set NULL
187
* QOSGraphEdgeOptions op1 = { .edge_name = "emmc" };
188
* QOSGraphEdgeOptions op2 = { .edge_name = "sdcard" };
189
- * qos_node_contains("arm/raspi2", "generic-sdhci", &op1, &op2, NULL);
190
+ * qos_node_contains("arm/raspi2b", "generic-sdhci", &op1, &op2, NULL);
191
*
192
* Of course this also requires that the @container's get_device function
193
* should implement a case for "emmc" and "sdcard".
194
diff --git a/tests/qtest/libqos/qgraph_internal.h b/tests/qtest/libqos/qgraph_internal.h
195
index XXXXXXX..XXXXXXX 100644
196
--- a/tests/qtest/libqos/qgraph_internal.h
197
+++ b/tests/qtest/libqos/qgraph_internal.h
198
@@ -XXX,XX +XXX,XX @@ void qos_graph_foreach_test_path(QOSTestCallback fn);
199
/**
200
* qos_get_machine_type(): return QEMU machine type for a machine node.
201
* This function requires every machine @name to be in the form
202
- * <arch>/<machine_name>, like "arm/raspi2" or "x86_64/pc".
203
+ * <arch>/<machine_name>, like "arm/raspi2b" or "x86_64/pc".
204
*
205
* The function will validate the format and return a pointer to
206
* @machine to <machine_name>. For example, when passed "x86_64/pc"
207
diff --git a/tests/qtest/boot-serial-test.c b/tests/qtest/boot-serial-test.c
208
index XXXXXXX..XXXXXXX 100644
209
--- a/tests/qtest/boot-serial-test.c
210
+++ b/tests/qtest/boot-serial-test.c
211
@@ -XXX,XX +XXX,XX @@ static testdef_t tests[] = {
212
sizeof(kernel_pls3adsp1800), kernel_pls3adsp1800 },
213
{ "microblazeel", "petalogix-ml605", "", "TT",
214
sizeof(kernel_plml605), kernel_plml605 },
215
- { "arm", "raspi2", "", "TT", sizeof(bios_raspi2), 0, bios_raspi2 },
216
+ { "arm", "raspi2b", "", "TT", sizeof(bios_raspi2), 0, bios_raspi2 },
217
/* For hppa, force bios to output to serial by disabling graphics. */
218
{ "hppa", "hppa", "-vga none", "SeaBIOS wants SYSTEM HALT" },
219
{ "aarch64", "virt", "-cpu max", "TT", sizeof(kernel_aarch64),
220
diff --git a/tests/qtest/libqos/arm-raspi2-machine.c b/tests/qtest/libqos/arm-raspi2-machine.c
221
index XXXXXXX..XXXXXXX 100644
222
--- a/tests/qtest/libqos/arm-raspi2-machine.c
223
+++ b/tests/qtest/libqos/arm-raspi2-machine.c
224
@@ -XXX,XX +XXX,XX @@ static void *raspi2_get_driver(void *object, const char *interface)
225
return &machine->alloc;
226
}
227
228
- fprintf(stderr, "%s not present in arm/raspi2\n", interface);
229
+ fprintf(stderr, "%s not present in arm/raspi2b\n", interface);
230
g_assert_not_reached();
231
}
232
233
@@ -XXX,XX +XXX,XX @@ static QOSGraphObject *raspi2_get_device(void *obj, const char *device)
234
return &machine->sdhci.obj;
235
}
236
237
- fprintf(stderr, "%s not present in arm/raspi2\n", device);
238
+ fprintf(stderr, "%s not present in arm/raspi2b\n", device);
239
g_assert_not_reached();
240
}
241
242
@@ -XXX,XX +XXX,XX @@ static void *qos_create_machine_arm_raspi2(QTestState *qts)
243
244
static void raspi2_register_nodes(void)
245
{
246
- qos_node_create_machine("arm/raspi2", qos_create_machine_arm_raspi2);
247
- qos_node_contains("arm/raspi2", "generic-sdhci", NULL);
248
+ qos_node_create_machine("arm/raspi2b", qos_create_machine_arm_raspi2);
249
+ qos_node_contains("arm/raspi2b", "generic-sdhci", NULL);
250
}
251
252
libqos_init(raspi2_register_nodes);
253
diff --git a/tests/unit/test-qgraph.c b/tests/unit/test-qgraph.c
254
index XXXXXXX..XXXXXXX 100644
255
--- a/tests/unit/test-qgraph.c
256
+++ b/tests/unit/test-qgraph.c
257
@@ -XXX,XX +XXX,XX @@
258
#include "../qtest/libqos/qgraph_internal.h"
259
260
#define MACHINE_PC "x86_64/pc"
261
-#define MACHINE_RASPI2 "arm/raspi2"
262
+#define MACHINE_RASPI2 "arm/raspi2b"
263
#define I440FX "i440FX-pcihost"
264
#define PCIBUS_PC "pcibus-pc"
265
#define SDHCI "sdhci"
266
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
267
index XXXXXXX..XXXXXXX 100644
268
--- a/tests/acceptance/boot_linux_console.py
269
+++ b/tests/acceptance/boot_linux_console.py
270
@@ -XXX,XX +XXX,XX @@ def do_test_arm_raspi2(self, uart_id):
271
def test_arm_raspi2_uart0(self):
272
"""
273
:avocado: tags=arch:arm
274
- :avocado: tags=machine:raspi2
275
+ :avocado: tags=machine:raspi2b
276
:avocado: tags=device:pl011
277
:avocado: tags=accel:tcg
278
"""
279
@@ -XXX,XX +XXX,XX @@ def test_arm_raspi2_uart0(self):
280
def test_arm_raspi2_initrd(self):
281
"""
282
:avocado: tags=arch:arm
283
- :avocado: tags=machine:raspi2
284
+ :avocado: tags=machine:raspi2b
285
"""
286
deb_url = ('http://archive.raspberrypi.org/debian/'
287
'pool/main/r/raspberrypi-firmware/'
288
@@ -XXX,XX +XXX,XX @@ def test_arm_orangepi_uboot_netbsd9(self):
289
def test_aarch64_raspi3_atf(self):
290
"""
291
:avocado: tags=arch:aarch64
292
- :avocado: tags=machine:raspi3
293
+ :avocado: tags=machine:raspi3b
294
:avocado: tags=cpu:cortex-a53
295
:avocado: tags=device:pl011
296
:avocado: tags=atf
297
--
298
2.20.1
299
300
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
2
3
Remove the raspi2/raspi3 machine aliases,
4
deprecated since commit 155e1c82ed0.
5
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20210827060815.2384760-3-f4bug@amsat.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
docs/about/deprecated.rst | 7 -------
12
docs/about/removed-features.rst | 7 +++++++
13
hw/arm/raspi.c | 2 --
14
3 files changed, 7 insertions(+), 9 deletions(-)
15
16
diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
17
index XXXXXXX..XXXXXXX 100644
18
--- a/docs/about/deprecated.rst
19
+++ b/docs/about/deprecated.rst
20
@@ -XXX,XX +XXX,XX @@ this CPU is also deprecated.
21
System emulator machines
22
------------------------
23
24
-Raspberry Pi ``raspi2`` and ``raspi3`` machines (since 5.2)
25
-'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
26
-
27
-The Raspberry Pi machines come in various models (A, A+, B, B+). To be able
28
-to distinguish which model QEMU is implementing, the ``raspi2`` and ``raspi3``
29
-machines have been renamed ``raspi2b`` and ``raspi3b``.
30
-
31
Aspeed ``swift-bmc`` machine (since 6.1)
32
''''''''''''''''''''''''''''''''''''''''
33
34
diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst
35
index XXXXXXX..XXXXXXX 100644
36
--- a/docs/about/removed-features.rst
37
+++ b/docs/about/removed-features.rst
38
@@ -XXX,XX +XXX,XX @@ This machine has been renamed ``fuloong2e``.
39
These machine types were very old and likely could not be used for live
40
migration from old QEMU versions anymore. Use a newer machine type instead.
41
42
+Raspberry Pi ``raspi2`` and ``raspi3`` machines (removed in 6.2)
43
+''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
44
+
45
+The Raspberry Pi machines come in various models (A, A+, B, B+). To be able
46
+to distinguish which model QEMU is implementing, the ``raspi2`` and ``raspi3``
47
+machines have been renamed ``raspi2b`` and ``raspi3b``.
48
+
49
50
linux-user mode CPUs
51
--------------------
52
diff --git a/hw/arm/raspi.c b/hw/arm/raspi.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/hw/arm/raspi.c
55
+++ b/hw/arm/raspi.c
56
@@ -XXX,XX +XXX,XX @@ static void raspi2b_machine_class_init(ObjectClass *oc, void *data)
57
MachineClass *mc = MACHINE_CLASS(oc);
58
RaspiMachineClass *rmc = RASPI_MACHINE_CLASS(oc);
59
60
- mc->alias = "raspi2";
61
rmc->board_rev = 0xa21041;
62
raspi_machine_class_common_init(mc, rmc->board_rev);
63
};
64
@@ -XXX,XX +XXX,XX @@ static void raspi3b_machine_class_init(ObjectClass *oc, void *data)
65
MachineClass *mc = MACHINE_CLASS(oc);
66
RaspiMachineClass *rmc = RASPI_MACHINE_CLASS(oc);
67
68
- mc->alias = "raspi3";
69
rmc->board_rev = 0xa02082;
70
raspi_machine_class_common_init(mc, rmc->board_rev);
71
};
72
--
73
2.20.1
74
75
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
2
3
QEMU load/store API (docs/devel/loads-stores.rst) uses the 'q'
4
suffix for 64-bit accesses. Rename the current 'll' suffix to
5
have the GIC dist accessors better match the rest of the codebase.
6
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
8
Message-id: 20210826180704.2131949-2-philmd@redhat.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
hw/intc/arm_gicv3_dist.c | 12 ++++++------
12
1 file changed, 6 insertions(+), 6 deletions(-)
13
14
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/intc/arm_gicv3_dist.c
17
+++ b/hw/intc/arm_gicv3_dist.c
18
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_writel(GICv3State *s, hwaddr offset,
19
}
20
}
21
22
-static MemTxResult gicd_writell(GICv3State *s, hwaddr offset,
23
- uint64_t value, MemTxAttrs attrs)
24
+static MemTxResult gicd_writeq(GICv3State *s, hwaddr offset,
25
+ uint64_t value, MemTxAttrs attrs)
26
{
27
/* Our only 64-bit registers are GICD_IROUTER<n> */
28
int irq;
29
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_writell(GICv3State *s, hwaddr offset,
30
}
31
}
32
33
-static MemTxResult gicd_readll(GICv3State *s, hwaddr offset,
34
- uint64_t *data, MemTxAttrs attrs)
35
+static MemTxResult gicd_readq(GICv3State *s, hwaddr offset,
36
+ uint64_t *data, MemTxAttrs attrs)
37
{
38
/* Our only 64-bit registers are GICD_IROUTER<n> */
39
int irq;
40
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_dist_read(void *opaque, hwaddr offset, uint64_t *data,
41
r = gicd_readl(s, offset, data, attrs);
42
break;
43
case 8:
44
- r = gicd_readll(s, offset, data, attrs);
45
+ r = gicd_readq(s, offset, data, attrs);
46
break;
47
default:
48
r = MEMTX_ERROR;
49
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_dist_write(void *opaque, hwaddr offset, uint64_t data,
50
r = gicd_writel(s, offset, data, attrs);
51
break;
52
case 8:
53
- r = gicd_writell(s, offset, data, attrs);
54
+ r = gicd_writeq(s, offset, data, attrs);
55
break;
56
default:
57
r = MEMTX_ERROR;
58
--
59
2.20.1
60
61
diff view generated by jsdifflib
New patch
1
From: Philippe Mathieu-Daudé <philmd@redhat.com>
1
2
3
Quoting Peter Maydell:
4
5
These MEMTX_* aren't from the memory transaction API functions;
6
they're just being used by gicd_readl() and friends as a way to
7
indicate a success/failure so that the actual MemoryRegionOps
8
read/write fns like gicv3_dist_read() can log a guest error.
9
Arguably this is a bit of a misuse of the MEMTX_* constants and
10
perhaps we should have gicd_readl etc return a bool instead.
11
12
Follow his suggestion and replace the MEMTX_* constants by
13
boolean values, simplifying a bit the gicv3_dist_read() /
14
gicv3_dist_write() handlers.
15
16
Suggested-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Philippe Mathieu-Daudé <philmd@redhat.com>
18
Message-id: 20210826180704.2131949-3-philmd@redhat.com
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
---
21
hw/intc/arm_gicv3_dist.c | 201 +++++++++++++++++++++------------------
22
1 file changed, 106 insertions(+), 95 deletions(-)
23
24
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
25
index XXXXXXX..XXXXXXX 100644
26
--- a/hw/intc/arm_gicv3_dist.c
27
+++ b/hw/intc/arm_gicv3_dist.c
28
@@ -XXX,XX +XXX,XX @@ static void gicd_write_irouter(GICv3State *s, MemTxAttrs attrs, int irq,
29
gicv3_update(s, irq, 1);
30
}
31
32
-static MemTxResult gicd_readb(GICv3State *s, hwaddr offset,
33
- uint64_t *data, MemTxAttrs attrs)
34
+/**
35
+ * gicd_readb
36
+ * gicd_readw
37
+ * gicd_readl
38
+ * gicd_readq
39
+ * gicd_writeb
40
+ * gicd_writew
41
+ * gicd_writel
42
+ * gicd_writeq
43
+ *
44
+ * Return %true if the operation succeeded, %false otherwise.
45
+ */
46
+
47
+static bool gicd_readb(GICv3State *s, hwaddr offset,
48
+ uint64_t *data, MemTxAttrs attrs)
49
{
50
/* Most GICv3 distributor registers do not support byte accesses. */
51
switch (offset) {
52
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_readb(GICv3State *s, hwaddr offset,
53
/* This GIC implementation always has affinity routing enabled,
54
* so these registers are all RAZ/WI.
55
*/
56
- return MEMTX_OK;
57
+ return true;
58
case GICD_IPRIORITYR ... GICD_IPRIORITYR + 0x3ff:
59
*data = gicd_read_ipriorityr(s, attrs, offset - GICD_IPRIORITYR);
60
- return MEMTX_OK;
61
+ return true;
62
default:
63
- return MEMTX_ERROR;
64
+ return false;
65
}
66
}
67
68
-static MemTxResult gicd_writeb(GICv3State *s, hwaddr offset,
69
- uint64_t value, MemTxAttrs attrs)
70
+static bool gicd_writeb(GICv3State *s, hwaddr offset,
71
+ uint64_t value, MemTxAttrs attrs)
72
{
73
/* Most GICv3 distributor registers do not support byte accesses. */
74
switch (offset) {
75
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_writeb(GICv3State *s, hwaddr offset,
76
/* This GIC implementation always has affinity routing enabled,
77
* so these registers are all RAZ/WI.
78
*/
79
- return MEMTX_OK;
80
+ return true;
81
case GICD_IPRIORITYR ... GICD_IPRIORITYR + 0x3ff:
82
{
83
int irq = offset - GICD_IPRIORITYR;
84
85
if (irq < GIC_INTERNAL || irq >= s->num_irq) {
86
- return MEMTX_OK;
87
+ return true;
88
}
89
gicd_write_ipriorityr(s, attrs, irq, value);
90
gicv3_update(s, irq, 1);
91
- return MEMTX_OK;
92
+ return true;
93
}
94
default:
95
- return MEMTX_ERROR;
96
+ return false;
97
}
98
}
99
100
-static MemTxResult gicd_readw(GICv3State *s, hwaddr offset,
101
- uint64_t *data, MemTxAttrs attrs)
102
+static bool gicd_readw(GICv3State *s, hwaddr offset,
103
+ uint64_t *data, MemTxAttrs attrs)
104
{
105
/* Only GICD_SETSPI_NSR, GICD_CLRSPI_NSR, GICD_SETSPI_SR and GICD_SETSPI_NSR
106
* support 16 bit accesses, and those registers are all part of the
107
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_readw(GICv3State *s, hwaddr offset,
108
* implement (ie for us GICD_TYPER.MBIS == 0), so for us they are
109
* reserved.
110
*/
111
- return MEMTX_ERROR;
112
+ return false;
113
}
114
115
-static MemTxResult gicd_writew(GICv3State *s, hwaddr offset,
116
- uint64_t value, MemTxAttrs attrs)
117
+static bool gicd_writew(GICv3State *s, hwaddr offset,
118
+ uint64_t value, MemTxAttrs attrs)
119
{
120
/* Only GICD_SETSPI_NSR, GICD_CLRSPI_NSR, GICD_SETSPI_SR and GICD_SETSPI_NSR
121
* support 16 bit accesses, and those registers are all part of the
122
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_writew(GICv3State *s, hwaddr offset,
123
* implement (ie for us GICD_TYPER.MBIS == 0), so for us they are
124
* reserved.
125
*/
126
- return MEMTX_ERROR;
127
+ return false;
128
}
129
130
-static MemTxResult gicd_readl(GICv3State *s, hwaddr offset,
131
- uint64_t *data, MemTxAttrs attrs)
132
+static bool gicd_readl(GICv3State *s, hwaddr offset,
133
+ uint64_t *data, MemTxAttrs attrs)
134
{
135
/* Almost all GICv3 distributor registers are 32-bit.
136
* Note that WO registers must return an UNKNOWN value on reads,
137
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset,
138
} else {
139
*data = s->gicd_ctlr;
140
}
141
- return MEMTX_OK;
142
+ return true;
143
case GICD_TYPER:
144
{
145
/* For this implementation:
146
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset,
147
148
*data = (1 << 25) | (1 << 24) | (sec_extn << 10) |
149
(0xf << 19) | itlinesnumber;
150
- return MEMTX_OK;
151
+ return true;
152
}
153
case GICD_IIDR:
154
/* We claim to be an ARM r0p0 with a zero ProductID.
155
* This is the same as an r0p0 GIC-500.
156
*/
157
*data = gicv3_iidr();
158
- return MEMTX_OK;
159
+ return true;
160
case GICD_STATUSR:
161
/* RAZ/WI for us (this is an optional register and our implementation
162
* does not track RO/WO/reserved violations to report them to the guest)
163
*/
164
*data = 0;
165
- return MEMTX_OK;
166
+ return true;
167
case GICD_IGROUPR ... GICD_IGROUPR + 0x7f:
168
{
169
int irq;
170
171
if (!attrs.secure && !(s->gicd_ctlr & GICD_CTLR_DS)) {
172
*data = 0;
173
- return MEMTX_OK;
174
+ return true;
175
}
176
/* RAZ/WI for SGIs, PPIs, unimplemented irqs */
177
irq = (offset - GICD_IGROUPR) * 8;
178
if (irq < GIC_INTERNAL || irq >= s->num_irq) {
179
*data = 0;
180
- return MEMTX_OK;
181
+ return true;
182
}
183
*data = *gic_bmp_ptr32(s->group, irq);
184
- return MEMTX_OK;
185
+ return true;
186
}
187
case GICD_ISENABLER ... GICD_ISENABLER + 0x7f:
188
*data = gicd_read_bitmap_reg(s, attrs, s->enabled, NULL,
189
offset - GICD_ISENABLER);
190
- return MEMTX_OK;
191
+ return true;
192
case GICD_ICENABLER ... GICD_ICENABLER + 0x7f:
193
*data = gicd_read_bitmap_reg(s, attrs, s->enabled, NULL,
194
offset - GICD_ICENABLER);
195
- return MEMTX_OK;
196
+ return true;
197
case GICD_ISPENDR ... GICD_ISPENDR + 0x7f:
198
*data = gicd_read_bitmap_reg(s, attrs, s->pending, mask_nsacr_ge1,
199
offset - GICD_ISPENDR);
200
- return MEMTX_OK;
201
+ return true;
202
case GICD_ICPENDR ... GICD_ICPENDR + 0x7f:
203
*data = gicd_read_bitmap_reg(s, attrs, s->pending, mask_nsacr_ge2,
204
offset - GICD_ICPENDR);
205
- return MEMTX_OK;
206
+ return true;
207
case GICD_ISACTIVER ... GICD_ISACTIVER + 0x7f:
208
*data = gicd_read_bitmap_reg(s, attrs, s->active, mask_nsacr_ge2,
209
offset - GICD_ISACTIVER);
210
- return MEMTX_OK;
211
+ return true;
212
case GICD_ICACTIVER ... GICD_ICACTIVER + 0x7f:
213
*data = gicd_read_bitmap_reg(s, attrs, s->active, mask_nsacr_ge2,
214
offset - GICD_ICACTIVER);
215
- return MEMTX_OK;
216
+ return true;
217
case GICD_IPRIORITYR ... GICD_IPRIORITYR + 0x3ff:
218
{
219
int i, irq = offset - GICD_IPRIORITYR;
220
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset,
221
value |= gicd_read_ipriorityr(s, attrs, i);
222
}
223
*data = value;
224
- return MEMTX_OK;
225
+ return true;
226
}
227
case GICD_ITARGETSR ... GICD_ITARGETSR + 0x3ff:
228
/* RAZ/WI since affinity routing is always enabled */
229
*data = 0;
230
- return MEMTX_OK;
231
+ return true;
232
case GICD_ICFGR ... GICD_ICFGR + 0xff:
233
{
234
/* Here only the even bits are used; odd bits are RES0 */
235
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset,
236
237
if (irq < GIC_INTERNAL || irq >= s->num_irq) {
238
*data = 0;
239
- return MEMTX_OK;
240
+ return true;
241
}
242
243
/* Since our edge_trigger bitmap is one bit per irq, we only need
244
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset,
245
value = extract32(value, (irq & 0x1f) ? 16 : 0, 16);
246
value = half_shuffle32(value) << 1;
247
*data = value;
248
- return MEMTX_OK;
249
+ return true;
250
}
251
case GICD_IGRPMODR ... GICD_IGRPMODR + 0xff:
252
{
253
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset,
254
* security enabled and this is an NS access
255
*/
256
*data = 0;
257
- return MEMTX_OK;
258
+ return true;
259
}
260
/* RAZ/WI for SGIs, PPIs, unimplemented irqs */
261
irq = (offset - GICD_IGRPMODR) * 8;
262
if (irq < GIC_INTERNAL || irq >= s->num_irq) {
263
*data = 0;
264
- return MEMTX_OK;
265
+ return true;
266
}
267
*data = *gic_bmp_ptr32(s->grpmod, irq);
268
- return MEMTX_OK;
269
+ return true;
270
}
271
case GICD_NSACR ... GICD_NSACR + 0xff:
272
{
273
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset,
274
275
if (irq < GIC_INTERNAL || irq >= s->num_irq) {
276
*data = 0;
277
- return MEMTX_OK;
278
+ return true;
279
}
280
281
if ((s->gicd_ctlr & GICD_CTLR_DS) || !attrs.secure) {
282
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset,
283
* security enabled and this is an NS access
284
*/
285
*data = 0;
286
- return MEMTX_OK;
287
+ return true;
288
}
289
290
*data = s->gicd_nsacr[irq / 16];
291
- return MEMTX_OK;
292
+ return true;
293
}
294
case GICD_CPENDSGIR ... GICD_CPENDSGIR + 0xf:
295
case GICD_SPENDSGIR ... GICD_SPENDSGIR + 0xf:
296
/* RAZ/WI since affinity routing is always enabled */
297
*data = 0;
298
- return MEMTX_OK;
299
+ return true;
300
case GICD_IROUTER ... GICD_IROUTER + 0x1fdf:
301
{
302
uint64_t r;
303
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_readl(GICv3State *s, hwaddr offset,
304
} else {
305
*data = (uint32_t)r;
306
}
307
- return MEMTX_OK;
308
+ return true;
309
}
310
case GICD_IDREGS ... GICD_IDREGS + 0x2f:
311
/* ID registers */
312
*data = gicv3_idreg(offset - GICD_IDREGS);
313
- return MEMTX_OK;
314
+ return true;
315
case GICD_SGIR:
316
/* WO registers, return unknown value */
317
qemu_log_mask(LOG_GUEST_ERROR,
318
"%s: invalid guest read from WO register at offset "
319
TARGET_FMT_plx "\n", __func__, offset);
320
*data = 0;
321
- return MEMTX_OK;
322
+ return true;
323
default:
324
- return MEMTX_ERROR;
325
+ return false;
326
}
327
}
328
329
-static MemTxResult gicd_writel(GICv3State *s, hwaddr offset,
330
- uint64_t value, MemTxAttrs attrs)
331
+static bool gicd_writel(GICv3State *s, hwaddr offset,
332
+ uint64_t value, MemTxAttrs attrs)
333
{
334
/* Almost all GICv3 distributor registers are 32-bit. Note that
335
* RO registers must ignore writes, not abort.
336
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_writel(GICv3State *s, hwaddr offset,
337
s->gicd_ctlr &= ~(GICD_CTLR_EN_GRP1S | GICD_CTLR_ARE_NS);
338
}
339
gicv3_full_update(s);
340
- return MEMTX_OK;
341
+ return true;
342
}
343
case GICD_STATUSR:
344
/* RAZ/WI for our implementation */
345
- return MEMTX_OK;
346
+ return true;
347
case GICD_IGROUPR ... GICD_IGROUPR + 0x7f:
348
{
349
int irq;
350
351
if (!attrs.secure && !(s->gicd_ctlr & GICD_CTLR_DS)) {
352
- return MEMTX_OK;
353
+ return true;
354
}
355
/* RAZ/WI for SGIs, PPIs, unimplemented irqs */
356
irq = (offset - GICD_IGROUPR) * 8;
357
if (irq < GIC_INTERNAL || irq >= s->num_irq) {
358
- return MEMTX_OK;
359
+ return true;
360
}
361
*gic_bmp_ptr32(s->group, irq) = value;
362
gicv3_update(s, irq, 32);
363
- return MEMTX_OK;
364
+ return true;
365
}
366
case GICD_ISENABLER ... GICD_ISENABLER + 0x7f:
367
gicd_write_set_bitmap_reg(s, attrs, s->enabled, NULL,
368
offset - GICD_ISENABLER, value);
369
- return MEMTX_OK;
370
+ return true;
371
case GICD_ICENABLER ... GICD_ICENABLER + 0x7f:
372
gicd_write_clear_bitmap_reg(s, attrs, s->enabled, NULL,
373
offset - GICD_ICENABLER, value);
374
- return MEMTX_OK;
375
+ return true;
376
case GICD_ISPENDR ... GICD_ISPENDR + 0x7f:
377
gicd_write_set_bitmap_reg(s, attrs, s->pending, mask_nsacr_ge1,
378
offset - GICD_ISPENDR, value);
379
- return MEMTX_OK;
380
+ return true;
381
case GICD_ICPENDR ... GICD_ICPENDR + 0x7f:
382
gicd_write_clear_bitmap_reg(s, attrs, s->pending, mask_nsacr_ge2,
383
offset - GICD_ICPENDR, value);
384
- return MEMTX_OK;
385
+ return true;
386
case GICD_ISACTIVER ... GICD_ISACTIVER + 0x7f:
387
gicd_write_set_bitmap_reg(s, attrs, s->active, NULL,
388
offset - GICD_ISACTIVER, value);
389
- return MEMTX_OK;
390
+ return true;
391
case GICD_ICACTIVER ... GICD_ICACTIVER + 0x7f:
392
gicd_write_clear_bitmap_reg(s, attrs, s->active, NULL,
393
offset - GICD_ICACTIVER, value);
394
- return MEMTX_OK;
395
+ return true;
396
case GICD_IPRIORITYR ... GICD_IPRIORITYR + 0x3ff:
397
{
398
int i, irq = offset - GICD_IPRIORITYR;
399
400
if (irq < GIC_INTERNAL || irq + 3 >= s->num_irq) {
401
- return MEMTX_OK;
402
+ return true;
403
}
404
405
for (i = irq; i < irq + 4; i++, value >>= 8) {
406
gicd_write_ipriorityr(s, attrs, i, value);
407
}
408
gicv3_update(s, irq, 4);
409
- return MEMTX_OK;
410
+ return true;
411
}
412
case GICD_ITARGETSR ... GICD_ITARGETSR + 0x3ff:
413
/* RAZ/WI since affinity routing is always enabled */
414
- return MEMTX_OK;
415
+ return true;
416
case GICD_ICFGR ... GICD_ICFGR + 0xff:
417
{
418
/* Here only the odd bits are used; even bits are RES0 */
419
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_writel(GICv3State *s, hwaddr offset,
420
uint32_t mask, oldval;
421
422
if (irq < GIC_INTERNAL || irq >= s->num_irq) {
423
- return MEMTX_OK;
424
+ return true;
425
}
426
427
/* Since our edge_trigger bitmap is one bit per irq, our input
428
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_writel(GICv3State *s, hwaddr offset,
429
oldval = *gic_bmp_ptr32(s->edge_trigger, (irq & ~0x1f));
430
value = (oldval & ~mask) | (value & mask);
431
*gic_bmp_ptr32(s->edge_trigger, irq & ~0x1f) = value;
432
- return MEMTX_OK;
433
+ return true;
434
}
435
case GICD_IGRPMODR ... GICD_IGRPMODR + 0xff:
436
{
437
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_writel(GICv3State *s, hwaddr offset,
438
/* RAZ/WI if security disabled, or if
439
* security enabled and this is an NS access
440
*/
441
- return MEMTX_OK;
442
+ return true;
443
}
444
/* RAZ/WI for SGIs, PPIs, unimplemented irqs */
445
irq = (offset - GICD_IGRPMODR) * 8;
446
if (irq < GIC_INTERNAL || irq >= s->num_irq) {
447
- return MEMTX_OK;
448
+ return true;
449
}
450
*gic_bmp_ptr32(s->grpmod, irq) = value;
451
gicv3_update(s, irq, 32);
452
- return MEMTX_OK;
453
+ return true;
454
}
455
case GICD_NSACR ... GICD_NSACR + 0xff:
456
{
457
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_writel(GICv3State *s, hwaddr offset,
458
int irq = (offset - GICD_NSACR) * 4;
459
460
if (irq < GIC_INTERNAL || irq >= s->num_irq) {
461
- return MEMTX_OK;
462
+ return true;
463
}
464
465
if ((s->gicd_ctlr & GICD_CTLR_DS) || !attrs.secure) {
466
/* RAZ/WI if security disabled, or if
467
* security enabled and this is an NS access
468
*/
469
- return MEMTX_OK;
470
+ return true;
471
}
472
473
s->gicd_nsacr[irq / 16] = value;
474
/* No update required as this only affects access permission checks */
475
- return MEMTX_OK;
476
+ return true;
477
}
478
case GICD_SGIR:
479
/* RES0 if affinity routing is enabled */
480
- return MEMTX_OK;
481
+ return true;
482
case GICD_CPENDSGIR ... GICD_CPENDSGIR + 0xf:
483
case GICD_SPENDSGIR ... GICD_SPENDSGIR + 0xf:
484
/* RAZ/WI since affinity routing is always enabled */
485
- return MEMTX_OK;
486
+ return true;
487
case GICD_IROUTER ... GICD_IROUTER + 0x1fdf:
488
{
489
uint64_t r;
490
int irq = (offset - GICD_IROUTER) / 8;
491
492
if (irq < GIC_INTERNAL || irq >= s->num_irq) {
493
- return MEMTX_OK;
494
+ return true;
495
}
496
497
/* Write half of the 64-bit register */
498
r = gicd_read_irouter(s, attrs, irq);
499
r = deposit64(r, (offset & 7) ? 32 : 0, 32, value);
500
gicd_write_irouter(s, attrs, irq, r);
501
- return MEMTX_OK;
502
+ return true;
503
}
504
case GICD_IDREGS ... GICD_IDREGS + 0x2f:
505
case GICD_TYPER:
506
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_writel(GICv3State *s, hwaddr offset,
507
qemu_log_mask(LOG_GUEST_ERROR,
508
"%s: invalid guest write to RO register at offset "
509
TARGET_FMT_plx "\n", __func__, offset);
510
- return MEMTX_OK;
511
+ return true;
512
default:
513
- return MEMTX_ERROR;
514
+ return false;
515
}
516
}
517
518
-static MemTxResult gicd_writeq(GICv3State *s, hwaddr offset,
519
- uint64_t value, MemTxAttrs attrs)
520
+static bool gicd_writeq(GICv3State *s, hwaddr offset,
521
+ uint64_t value, MemTxAttrs attrs)
522
{
523
/* Our only 64-bit registers are GICD_IROUTER<n> */
524
int irq;
525
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_writeq(GICv3State *s, hwaddr offset,
526
case GICD_IROUTER ... GICD_IROUTER + 0x1fdf:
527
irq = (offset - GICD_IROUTER) / 8;
528
gicd_write_irouter(s, attrs, irq, value);
529
- return MEMTX_OK;
530
+ return true;
531
default:
532
- return MEMTX_ERROR;
533
+ return false;
534
}
535
}
536
537
-static MemTxResult gicd_readq(GICv3State *s, hwaddr offset,
538
- uint64_t *data, MemTxAttrs attrs)
539
+static bool gicd_readq(GICv3State *s, hwaddr offset,
540
+ uint64_t *data, MemTxAttrs attrs)
541
{
542
/* Our only 64-bit registers are GICD_IROUTER<n> */
543
int irq;
544
@@ -XXX,XX +XXX,XX @@ static MemTxResult gicd_readq(GICv3State *s, hwaddr offset,
545
case GICD_IROUTER ... GICD_IROUTER + 0x1fdf:
546
irq = (offset - GICD_IROUTER) / 8;
547
*data = gicd_read_irouter(s, attrs, irq);
548
- return MEMTX_OK;
549
+ return true;
550
default:
551
- return MEMTX_ERROR;
552
+ return false;
553
}
554
}
555
556
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_dist_read(void *opaque, hwaddr offset, uint64_t *data,
557
unsigned size, MemTxAttrs attrs)
558
{
559
GICv3State *s = (GICv3State *)opaque;
560
- MemTxResult r;
561
+ bool r;
562
563
switch (size) {
564
case 1:
565
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_dist_read(void *opaque, hwaddr offset, uint64_t *data,
566
r = gicd_readq(s, offset, data, attrs);
567
break;
568
default:
569
- r = MEMTX_ERROR;
570
+ r = false;
571
break;
572
}
573
574
- if (r == MEMTX_ERROR) {
575
+ if (!r) {
576
qemu_log_mask(LOG_GUEST_ERROR,
577
"%s: invalid guest read at offset " TARGET_FMT_plx
578
"size %u\n", __func__, offset, size);
579
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_dist_read(void *opaque, hwaddr offset, uint64_t *data,
580
* trigger the guest-error logging but don't return it to
581
* the caller, or we'll cause a spurious guest data abort.
582
*/
583
- r = MEMTX_OK;
584
*data = 0;
585
} else {
586
trace_gicv3_dist_read(offset, *data, size, attrs.secure);
587
}
588
- return r;
589
+ return MEMTX_OK;
590
}
591
592
MemTxResult gicv3_dist_write(void *opaque, hwaddr offset, uint64_t data,
593
unsigned size, MemTxAttrs attrs)
594
{
595
GICv3State *s = (GICv3State *)opaque;
596
- MemTxResult r;
597
+ bool r;
598
599
switch (size) {
600
case 1:
601
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_dist_write(void *opaque, hwaddr offset, uint64_t data,
602
r = gicd_writeq(s, offset, data, attrs);
603
break;
604
default:
605
- r = MEMTX_ERROR;
606
+ r = false;
607
break;
608
}
609
610
- if (r == MEMTX_ERROR) {
611
+ if (!r) {
612
qemu_log_mask(LOG_GUEST_ERROR,
613
"%s: invalid guest write at offset " TARGET_FMT_plx
614
"size %u\n", __func__, offset, size);
615
@@ -XXX,XX +XXX,XX @@ MemTxResult gicv3_dist_write(void *opaque, hwaddr offset, uint64_t data,
616
* trigger the guest-error logging but don't return it to
617
* the caller, or we'll cause a spurious guest data abort.
618
*/
619
- r = MEMTX_OK;
620
} else {
621
trace_gicv3_dist_write(offset, data, size, attrs.secure);
622
}
623
- return r;
624
+ return MEMTX_OK;
625
}
626
627
void gicv3_dist_set_irq(GICv3State *s, int irq, int level)
628
--
629
2.20.1
630
631
diff view generated by jsdifflib
New patch
1
1
From: Yanan Wang <wangyanan55@huawei.com>
2
3
Add 6.2 machine types for arm/i440fx/q35/s390x/spapr.
4
5
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
6
Acked-by: David Gibson <david@gibson.dropbear.id.au>
7
Reviewed-by: Andrew Jones <drjones@redhat.com>
8
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
9
Reviewed-by: Pankaj Gupta <pankaj.gupta@ionos.com>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/boards.h | 3 +++
13
include/hw/i386/pc.h | 3 +++
14
hw/arm/virt.c | 11 +++++++++--
15
hw/core/machine.c | 3 +++
16
hw/i386/pc.c | 3 +++
17
hw/i386/pc_piix.c | 14 +++++++++++++-
18
hw/i386/pc_q35.c | 13 ++++++++++++-
19
hw/ppc/spapr.c | 17 ++++++++++++++---
20
hw/s390x/s390-virtio-ccw.c | 14 +++++++++++++-
21
9 files changed, 73 insertions(+), 8 deletions(-)
22
23
diff --git a/include/hw/boards.h b/include/hw/boards.h
24
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/boards.h
26
+++ b/include/hw/boards.h
27
@@ -XXX,XX +XXX,XX @@ struct MachineState {
28
} \
29
type_init(machine_initfn##_register_types)
30
31
+extern GlobalProperty hw_compat_6_1[];
32
+extern const size_t hw_compat_6_1_len;
33
+
34
extern GlobalProperty hw_compat_6_0[];
35
extern const size_t hw_compat_6_0_len;
36
37
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
38
index XXXXXXX..XXXXXXX 100644
39
--- a/include/hw/i386/pc.h
40
+++ b/include/hw/i386/pc.h
41
@@ -XXX,XX +XXX,XX @@ void pc_system_parse_ovmf_flash(uint8_t *flash_ptr, size_t flash_size);
42
void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
43
const CPUArchIdList *apic_ids, GArray *entry);
44
45
+extern GlobalProperty pc_compat_6_1[];
46
+extern const size_t pc_compat_6_1_len;
47
+
48
extern GlobalProperty pc_compat_6_0[];
49
extern const size_t pc_compat_6_0_len;
50
51
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/hw/arm/virt.c
54
+++ b/hw/arm/virt.c
55
@@ -XXX,XX +XXX,XX @@ static void machvirt_machine_init(void)
56
}
57
type_init(machvirt_machine_init);
58
59
-static void virt_machine_6_1_options(MachineClass *mc)
60
+static void virt_machine_6_2_options(MachineClass *mc)
61
{
62
}
63
-DEFINE_VIRT_MACHINE_AS_LATEST(6, 1)
64
+DEFINE_VIRT_MACHINE_AS_LATEST(6, 2)
65
+
66
+static void virt_machine_6_1_options(MachineClass *mc)
67
+{
68
+ virt_machine_6_2_options(mc);
69
+ compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
70
+}
71
+DEFINE_VIRT_MACHINE(6, 1)
72
73
static void virt_machine_6_0_options(MachineClass *mc)
74
{
75
diff --git a/hw/core/machine.c b/hw/core/machine.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/hw/core/machine.c
78
+++ b/hw/core/machine.c
79
@@ -XXX,XX +XXX,XX @@
80
#include "hw/virtio/virtio.h"
81
#include "hw/virtio/virtio-pci.h"
82
83
+GlobalProperty hw_compat_6_1[] = {};
84
+const size_t hw_compat_6_1_len = G_N_ELEMENTS(hw_compat_6_1);
85
+
86
GlobalProperty hw_compat_6_0[] = {
87
{ "gpex-pcihost", "allow-unmapped-accesses", "false" },
88
{ "i8042", "extended-state", "false"},
89
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
90
index XXXXXXX..XXXXXXX 100644
91
--- a/hw/i386/pc.c
92
+++ b/hw/i386/pc.c
93
@@ -XXX,XX +XXX,XX @@
94
#include "trace.h"
95
#include CONFIG_DEVICES
96
97
+GlobalProperty pc_compat_6_1[] = {};
98
+const size_t pc_compat_6_1_len = G_N_ELEMENTS(pc_compat_6_1);
99
+
100
GlobalProperty pc_compat_6_0[] = {
101
{ "qemu64" "-" TYPE_X86_CPU, "family", "6" },
102
{ "qemu64" "-" TYPE_X86_CPU, "model", "6" },
103
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
104
index XXXXXXX..XXXXXXX 100644
105
--- a/hw/i386/pc_piix.c
106
+++ b/hw/i386/pc_piix.c
107
@@ -XXX,XX +XXX,XX @@ static void pc_i440fx_machine_options(MachineClass *m)
108
machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE);
109
}
110
111
-static void pc_i440fx_6_1_machine_options(MachineClass *m)
112
+static void pc_i440fx_6_2_machine_options(MachineClass *m)
113
{
114
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
115
pc_i440fx_machine_options(m);
116
@@ -XXX,XX +XXX,XX @@ static void pc_i440fx_6_1_machine_options(MachineClass *m)
117
pcmc->default_cpu_version = 1;
118
}
119
120
+DEFINE_I440FX_MACHINE(v6_2, "pc-i440fx-6.2", NULL,
121
+ pc_i440fx_6_2_machine_options);
122
+
123
+static void pc_i440fx_6_1_machine_options(MachineClass *m)
124
+{
125
+ pc_i440fx_6_2_machine_options(m);
126
+ m->alias = NULL;
127
+ m->is_default = false;
128
+ compat_props_add(m->compat_props, hw_compat_6_1, hw_compat_6_1_len);
129
+ compat_props_add(m->compat_props, pc_compat_6_1, pc_compat_6_1_len);
130
+}
131
+
132
DEFINE_I440FX_MACHINE(v6_1, "pc-i440fx-6.1", NULL,
133
pc_i440fx_6_1_machine_options);
134
135
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
136
index XXXXXXX..XXXXXXX 100644
137
--- a/hw/i386/pc_q35.c
138
+++ b/hw/i386/pc_q35.c
139
@@ -XXX,XX +XXX,XX @@ static void pc_q35_machine_options(MachineClass *m)
140
m->max_cpus = 288;
141
}
142
143
-static void pc_q35_6_1_machine_options(MachineClass *m)
144
+static void pc_q35_6_2_machine_options(MachineClass *m)
145
{
146
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
147
pc_q35_machine_options(m);
148
@@ -XXX,XX +XXX,XX @@ static void pc_q35_6_1_machine_options(MachineClass *m)
149
pcmc->default_cpu_version = 1;
150
}
151
152
+DEFINE_Q35_MACHINE(v6_2, "pc-q35-6.2", NULL,
153
+ pc_q35_6_2_machine_options);
154
+
155
+static void pc_q35_6_1_machine_options(MachineClass *m)
156
+{
157
+ pc_q35_6_2_machine_options(m);
158
+ m->alias = NULL;
159
+ compat_props_add(m->compat_props, hw_compat_6_1, hw_compat_6_1_len);
160
+ compat_props_add(m->compat_props, pc_compat_6_1, pc_compat_6_1_len);
161
+}
162
+
163
DEFINE_Q35_MACHINE(v6_1, "pc-q35-6.1", NULL,
164
pc_q35_6_1_machine_options);
165
166
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
167
index XXXXXXX..XXXXXXX 100644
168
--- a/hw/ppc/spapr.c
169
+++ b/hw/ppc/spapr.c
170
@@ -XXX,XX +XXX,XX @@ static void spapr_machine_latest_class_options(MachineClass *mc)
171
type_init(spapr_machine_register_##suffix)
172
173
/*
174
- * pseries-6.1
175
+ * pseries-6.2
176
*/
177
-static void spapr_machine_6_1_class_options(MachineClass *mc)
178
+static void spapr_machine_6_2_class_options(MachineClass *mc)
179
{
180
/* Defaults for the latest behaviour inherited from the base class */
181
}
182
183
-DEFINE_SPAPR_MACHINE(6_1, "6.1", true);
184
+DEFINE_SPAPR_MACHINE(6_2, "6.2", true);
185
+
186
+/*
187
+ * pseries-6.1
188
+ */
189
+static void spapr_machine_6_1_class_options(MachineClass *mc)
190
+{
191
+ spapr_machine_6_2_class_options(mc);
192
+ compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
193
+}
194
+
195
+DEFINE_SPAPR_MACHINE(6_1, "6.1", false);
196
197
/*
198
* pseries-6.0
199
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/hw/s390x/s390-virtio-ccw.c
202
+++ b/hw/s390x/s390-virtio-ccw.c
203
@@ -XXX,XX +XXX,XX @@ bool css_migration_enabled(void)
204
} \
205
type_init(ccw_machine_register_##suffix)
206
207
+static void ccw_machine_6_2_instance_options(MachineState *machine)
208
+{
209
+}
210
+
211
+static void ccw_machine_6_2_class_options(MachineClass *mc)
212
+{
213
+}
214
+DEFINE_CCW_MACHINE(6_2, "6.2", true);
215
+
216
static void ccw_machine_6_1_instance_options(MachineState *machine)
217
{
218
+ ccw_machine_6_2_instance_options(machine);
219
}
220
221
static void ccw_machine_6_1_class_options(MachineClass *mc)
222
{
223
+ ccw_machine_6_2_class_options(mc);
224
+ compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
225
}
226
-DEFINE_CCW_MACHINE(6_1, "6.1", true);
227
+DEFINE_CCW_MACHINE(6_1, "6.1", false);
228
229
static void ccw_machine_6_0_instance_options(MachineState *machine)
230
{
231
--
232
2.20.1
233
234
diff view generated by jsdifflib
1
Convert the Neon 3-reg-diff insns VABAL and VABDL to decodetree.
1
Implement the MVE VADD (floating-point) insn. Handling of this is
2
Like almost all the remaining insns in this group, these are
2
similar to the 2-operand integer insns, except that we must take care
3
a combination of a two-input operation which returns a double width
3
to only update the floating point exception status if the least
4
result and then a possible accumulation of that double width
4
significant bit of the predicate mask for each element is active.
5
result into the destination.
6
5
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
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>
9
---
8
---
10
target/arm/translate.h | 1 +
9
target/arm/helper-mve.h | 3 +++
11
target/arm/neon-dp.decode | 6 ++
10
target/arm/translate.h | 6 ++++++
12
target/arm/translate-neon.inc.c | 132 ++++++++++++++++++++++++++++++++
11
target/arm/mve.decode | 10 ++++++++++
13
target/arm/translate.c | 31 +-------
12
target/arm/mve_helper.c | 40 +++++++++++++++++++++++++++++++++++++
14
4 files changed, 142 insertions(+), 28 deletions(-)
13
target/arm/translate-mve.c | 17 ++++++++++++++++
14
target/arm/translate-neon.c | 6 ------
15
6 files changed, 76 insertions(+), 6 deletions(-)
15
16
17
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper-mve.h
20
+++ b/target/arm/helper-mve.h
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vhcadd270b, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
DEF_HELPER_FLAGS_4(mve_vhcadd270h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
DEF_HELPER_FLAGS_4(mve_vhcadd270w, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
25
+DEF_HELPER_FLAGS_4(mve_vfaddh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
+DEF_HELPER_FLAGS_4(mve_vfadds, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+
28
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
29
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
30
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
16
diff --git a/target/arm/translate.h b/target/arm/translate.h
31
diff --git a/target/arm/translate.h b/target/arm/translate.h
17
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate.h
33
--- a/target/arm/translate.h
19
+++ b/target/arm/translate.h
34
+++ b/target/arm/translate.h
20
@@ -XXX,XX +XXX,XX @@ typedef void NeonGenTwo64OpEnvFn(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64);
35
@@ -XXX,XX +XXX,XX @@ static inline int rsub_8(DisasContext *s, int x)
21
typedef void NeonGenNarrowFn(TCGv_i32, TCGv_i64);
36
return 8 - x;
22
typedef void NeonGenNarrowEnvFn(TCGv_i32, TCGv_ptr, TCGv_i64);
37
}
23
typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32);
38
24
+typedef void NeonGenTwoOpWidenFn(TCGv_i64, TCGv_i32, TCGv_i32);
39
+static inline int neon_3same_fp_size(DisasContext *s, int x)
25
typedef void NeonGenTwoSingleOPFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
40
+{
26
typedef void NeonGenTwoDoubleOPFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr);
41
+ /* Convert 0==fp32, 1==fp16 into a MO_* value */
27
typedef void NeonGenOneOpFn(TCGv_i64, TCGv_i64);
42
+ return MO_32 - x;
28
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
43
+}
44
+
45
static inline int arm_dc_feature(DisasContext *dc, int feature)
46
{
47
return (dc->features & (1ULL << feature)) != 0;
48
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
29
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/neon-dp.decode
50
--- a/target/arm/mve.decode
31
+++ b/target/arm/neon-dp.decode
51
+++ b/target/arm/mve.decode
32
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
52
@@ -XXX,XX +XXX,XX @@
33
VADDHN_3d 1111 001 0 1 . .. .... .... 0100 . 0 . 0 .... @3diff
53
# VQDMULL has size in bit 28: 0 for 16 bit, 1 for 32 bit
34
VRADDHN_3d 1111 001 1 1 . .. .... .... 0100 . 0 . 0 .... @3diff
54
%size_28 28:1 !function=plus_1
35
55
36
+ VABAL_S_3d 1111 001 0 1 . .. .... .... 0101 . 0 . 0 .... @3diff
56
+# 2 operand fp insns have size in bit 20: 1 for 16 bit, 0 for 32 bit,
37
+ VABAL_U_3d 1111 001 1 1 . .. .... .... 0101 . 0 . 0 .... @3diff
57
+# like Neon FP insns.
58
+%2op_fp_size 20:1 !function=neon_3same_fp_size
38
+
59
+
39
VSUBHN_3d 1111 001 0 1 . .. .... .... 0110 . 0 . 0 .... @3diff
60
# 1imm format immediate
40
VRSUBHN_3d 1111 001 1 1 . .. .... .... 0110 . 0 . 0 .... @3diff
61
%imm_28_16_0 28:1 16:3 0:4
62
63
@@ -XXX,XX +XXX,XX @@
64
65
@vmaxv .... .... .... size:2 .. rda:4 .... .... .... &vmaxv qm=%qm
66
67
+@2op_fp .... .... .... .... .... .... .... .... &2op \
68
+ qd=%qd qn=%qn qm=%qm size=%2op_fp_size
41
+
69
+
42
+ VABDL_S_3d 1111 001 0 1 . .. .... .... 0111 . 0 . 0 .... @3diff
70
# Vector loads and stores
43
+ VABDL_U_3d 1111 001 1 1 . .. .... .... 0111 . 0 . 0 .... @3diff
71
44
]
72
# Widening loads and narrowing stores:
45
}
73
@@ -XXX,XX +XXX,XX @@ VCMPGE_scalar 1111 1110 0 . .. ... 1 ... 1 1111 0 1 0 0 .... @vcmp_scalar
46
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
74
VCMPLT_scalar 1111 1110 0 . .. ... 1 ... 1 1111 1 1 0 0 .... @vcmp_scalar
75
VCMPGT_scalar 1111 1110 0 . .. ... 1 ... 1 1111 0 1 1 0 .... @vcmp_scalar
76
VCMPLE_scalar 1111 1110 0 . .. ... 1 ... 1 1111 1 1 1 0 .... @vcmp_scalar
77
+
78
+# 2-operand FP
79
+VADD_fp 1110 1111 0 . 0 . ... 0 ... 0 1101 . 1 . 0 ... 0 @2op_fp
80
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
47
index XXXXXXX..XXXXXXX 100644
81
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/translate-neon.inc.c
82
--- a/target/arm/mve_helper.c
49
+++ b/target/arm/translate-neon.inc.c
83
+++ b/target/arm/mve_helper.c
50
@@ -XXX,XX +XXX,XX @@ DO_NARROW_3D(VADDHN, add, narrow, tcg_gen_extrh_i64_i32)
84
@@ -XXX,XX +XXX,XX @@
51
DO_NARROW_3D(VSUBHN, sub, narrow, tcg_gen_extrh_i64_i32)
85
#include "exec/cpu_ldst.h"
52
DO_NARROW_3D(VRADDHN, add, narrow_round, gen_narrow_round_high_u32)
86
#include "exec/exec-all.h"
53
DO_NARROW_3D(VRSUBHN, sub, narrow_round, gen_narrow_round_high_u32)
87
#include "tcg/tcg.h"
88
+#include "fpu/softfloat.h"
89
90
static uint16_t mve_eci_mask(CPUARMState *env)
91
{
92
@@ -XXX,XX +XXX,XX @@ DO_VMAXMINA(vmaxaw, 4, int32_t, uint32_t, DO_MAX)
93
DO_VMAXMINA(vminab, 1, int8_t, uint8_t, DO_MIN)
94
DO_VMAXMINA(vminah, 2, int16_t, uint16_t, DO_MIN)
95
DO_VMAXMINA(vminaw, 4, int32_t, uint32_t, DO_MIN)
54
+
96
+
55
+static bool do_long_3d(DisasContext *s, arg_3diff *a,
97
+/*
56
+ NeonGenTwoOpWidenFn *opfn,
98
+ * 2-operand floating point. Note that if an element is partially
57
+ NeonGenTwo64OpFn *accfn)
99
+ * predicated we must do the FP operation to update the non-predicated
58
+{
100
+ * bytes, but we must be careful to avoid updating the FP exception
59
+ /*
101
+ * state unless byte 0 of the element was unpredicated.
60
+ * 3-regs different lengths, long operations.
102
+ */
61
+ * These perform an operation on two inputs that returns a double-width
103
+#define DO_2OP_FP(OP, ESIZE, TYPE, FN) \
62
+ * result, and then possibly perform an accumulation operation of
104
+ void HELPER(glue(mve_, OP))(CPUARMState *env, \
63
+ * that result into the double-width destination.
105
+ void *vd, void *vn, void *vm) \
64
+ */
106
+ { \
65
+ TCGv_i64 rd0, rd1, tmp;
107
+ TYPE *d = vd, *n = vn, *m = vm; \
66
+ TCGv_i32 rn, rm;
108
+ TYPE r; \
67
+
109
+ uint16_t mask = mve_element_mask(env); \
68
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
110
+ unsigned e; \
69
+ return false;
111
+ float_status *fpst; \
112
+ float_status scratch_fpst; \
113
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
114
+ if ((mask & MAKE_64BIT_MASK(0, ESIZE)) == 0) { \
115
+ continue; \
116
+ } \
117
+ fpst = (ESIZE == 2) ? &env->vfp.standard_fp_status_f16 : \
118
+ &env->vfp.standard_fp_status; \
119
+ if (!(mask & 1)) { \
120
+ /* We need the result but without updating flags */ \
121
+ scratch_fpst = *fpst; \
122
+ fpst = &scratch_fpst; \
123
+ } \
124
+ r = FN(n[H##ESIZE(e)], m[H##ESIZE(e)], fpst); \
125
+ mergemask(&d[H##ESIZE(e)], r, mask); \
126
+ } \
127
+ mve_advance_vpt(env); \
70
+ }
128
+ }
71
+
129
+
72
+ /* UNDEF accesses to D16-D31 if they don't exist. */
130
+#define DO_2OP_FP_ALL(OP, FN) \
73
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
131
+ DO_2OP_FP(OP##h, 2, float16, float16_##FN) \
74
+ ((a->vd | a->vn | a->vm) & 0x10)) {
132
+ DO_2OP_FP(OP##s, 4, float32, float32_##FN)
75
+ return false;
133
+
134
+DO_2OP_FP_ALL(vfadd, add)
135
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
136
index XXXXXXX..XXXXXXX 100644
137
--- a/target/arm/translate-mve.c
138
+++ b/target/arm/translate-mve.c
139
@@ -XXX,XX +XXX,XX @@ static bool trans_VSBCI(DisasContext *s, arg_2op *a)
140
return do_2op(s, a, gen_helper_mve_vsbci);
141
}
142
143
+#define DO_2OP_FP(INSN, FN) \
144
+ static bool trans_##INSN(DisasContext *s, arg_2op *a) \
145
+ { \
146
+ static MVEGenTwoOpFn * const fns[] = { \
147
+ NULL, \
148
+ gen_helper_mve_##FN##h, \
149
+ gen_helper_mve_##FN##s, \
150
+ NULL, \
151
+ }; \
152
+ if (!dc_isar_feature(aa32_mve_fp, s)) { \
153
+ return false; \
154
+ } \
155
+ return do_2op(s, a, fns[a->size]); \
76
+ }
156
+ }
77
+
157
+
78
+ if (!opfn) {
158
+DO_2OP_FP(VADD_fp, vfadd)
79
+ /* size == 3 case, which is an entirely different insn group */
80
+ return false;
81
+ }
82
+
159
+
83
+ if (a->vd & 1) {
160
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
84
+ return false;
161
MVEGenTwoOpScalarFn fn)
85
+ }
162
{
86
+
163
diff --git a/target/arm/translate-neon.c b/target/arm/translate-neon.c
87
+ if (!vfp_access_check(s)) {
88
+ return true;
89
+ }
90
+
91
+ rd0 = tcg_temp_new_i64();
92
+ rd1 = tcg_temp_new_i64();
93
+
94
+ rn = neon_load_reg(a->vn, 0);
95
+ rm = neon_load_reg(a->vm, 0);
96
+ opfn(rd0, rn, rm);
97
+ tcg_temp_free_i32(rn);
98
+ tcg_temp_free_i32(rm);
99
+
100
+ rn = neon_load_reg(a->vn, 1);
101
+ rm = neon_load_reg(a->vm, 1);
102
+ opfn(rd1, rn, rm);
103
+ tcg_temp_free_i32(rn);
104
+ tcg_temp_free_i32(rm);
105
+
106
+ /* Don't store results until after all loads: they might overlap */
107
+ if (accfn) {
108
+ tmp = tcg_temp_new_i64();
109
+ neon_load_reg64(tmp, a->vd);
110
+ accfn(tmp, tmp, rd0);
111
+ neon_store_reg64(tmp, a->vd);
112
+ neon_load_reg64(tmp, a->vd + 1);
113
+ accfn(tmp, tmp, rd1);
114
+ neon_store_reg64(tmp, a->vd + 1);
115
+ tcg_temp_free_i64(tmp);
116
+ } else {
117
+ neon_store_reg64(rd0, a->vd);
118
+ neon_store_reg64(rd1, a->vd + 1);
119
+ }
120
+
121
+ tcg_temp_free_i64(rd0);
122
+ tcg_temp_free_i64(rd1);
123
+
124
+ return true;
125
+}
126
+
127
+static bool trans_VABDL_S_3d(DisasContext *s, arg_3diff *a)
128
+{
129
+ static NeonGenTwoOpWidenFn * const opfn[] = {
130
+ gen_helper_neon_abdl_s16,
131
+ gen_helper_neon_abdl_s32,
132
+ gen_helper_neon_abdl_s64,
133
+ NULL,
134
+ };
135
+
136
+ return do_long_3d(s, a, opfn[a->size], NULL);
137
+}
138
+
139
+static bool trans_VABDL_U_3d(DisasContext *s, arg_3diff *a)
140
+{
141
+ static NeonGenTwoOpWidenFn * const opfn[] = {
142
+ gen_helper_neon_abdl_u16,
143
+ gen_helper_neon_abdl_u32,
144
+ gen_helper_neon_abdl_u64,
145
+ NULL,
146
+ };
147
+
148
+ return do_long_3d(s, a, opfn[a->size], NULL);
149
+}
150
+
151
+static bool trans_VABAL_S_3d(DisasContext *s, arg_3diff *a)
152
+{
153
+ static NeonGenTwoOpWidenFn * const opfn[] = {
154
+ gen_helper_neon_abdl_s16,
155
+ gen_helper_neon_abdl_s32,
156
+ gen_helper_neon_abdl_s64,
157
+ NULL,
158
+ };
159
+ static NeonGenTwo64OpFn * const addfn[] = {
160
+ gen_helper_neon_addl_u16,
161
+ gen_helper_neon_addl_u32,
162
+ tcg_gen_add_i64,
163
+ NULL,
164
+ };
165
+
166
+ return do_long_3d(s, a, opfn[a->size], addfn[a->size]);
167
+}
168
+
169
+static bool trans_VABAL_U_3d(DisasContext *s, arg_3diff *a)
170
+{
171
+ static NeonGenTwoOpWidenFn * const opfn[] = {
172
+ gen_helper_neon_abdl_u16,
173
+ gen_helper_neon_abdl_u32,
174
+ gen_helper_neon_abdl_u64,
175
+ NULL,
176
+ };
177
+ static NeonGenTwo64OpFn * const addfn[] = {
178
+ gen_helper_neon_addl_u16,
179
+ gen_helper_neon_addl_u32,
180
+ tcg_gen_add_i64,
181
+ NULL,
182
+ };
183
+
184
+ return do_long_3d(s, a, opfn[a->size], addfn[a->size]);
185
+}
186
diff --git a/target/arm/translate.c b/target/arm/translate.c
187
index XXXXXXX..XXXXXXX 100644
164
index XXXXXXX..XXXXXXX 100644
188
--- a/target/arm/translate.c
165
--- a/target/arm/translate-neon.c
189
+++ b/target/arm/translate.c
166
+++ b/target/arm/translate-neon.c
190
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
167
@@ -XXX,XX +XXX,XX @@
191
{0, 0, 0, 7}, /* VSUBL: handled by decodetree */
168
#include "translate.h"
192
{0, 0, 0, 7}, /* VSUBW: handled by decodetree */
169
#include "translate-a32.h"
193
{0, 0, 0, 7}, /* VADDHN: handled by decodetree */
170
194
- {0, 0, 0, 0}, /* VABAL */
171
-static inline int neon_3same_fp_size(DisasContext *s, int x)
195
+ {0, 0, 0, 7}, /* VABAL */
172
-{
196
{0, 0, 0, 7}, /* VSUBHN: handled by decodetree */
173
- /* Convert 0==fp32, 1==fp16 into a MO_* value */
197
- {0, 0, 0, 0}, /* VABDL */
174
- return MO_32 - x;
198
+ {0, 0, 0, 7}, /* VABDL */
175
-}
199
{0, 0, 0, 0}, /* VMLAL */
176
-
200
{0, 0, 0, 9}, /* VQDMLAL */
177
/* Include the generated Neon decoder */
201
{0, 0, 0, 0}, /* VMLSL */
178
#include "decode-neon-dp.c.inc"
202
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
179
#include "decode-neon-ls.c.inc"
203
tmp2 = neon_load_reg(rm, pass);
204
}
205
switch (op) {
206
- case 5: case 7: /* VABAL, VABDL */
207
- switch ((size << 1) | u) {
208
- case 0:
209
- gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
210
- break;
211
- case 1:
212
- gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
213
- break;
214
- case 2:
215
- gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
216
- break;
217
- case 3:
218
- gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
219
- break;
220
- case 4:
221
- gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
222
- break;
223
- case 5:
224
- gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
225
- break;
226
- default: abort();
227
- }
228
- tcg_temp_free_i32(tmp2);
229
- tcg_temp_free_i32(tmp);
230
- break;
231
case 8: case 9: case 10: case 11: case 12: case 13:
232
/* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
233
gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
234
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
235
case 10: /* VMLSL */
236
gen_neon_negl(cpu_V0, size);
237
/* Fall through */
238
- case 5: case 8: /* VABAL, VMLAL */
239
+ case 8: /* VABAL, VMLAL */
240
gen_neon_addl(size);
241
break;
242
case 9: case 11: /* VQDMLAL, VQDMLSL */
243
--
180
--
244
2.20.1
181
2.20.1
245
182
246
183
diff view generated by jsdifflib
New patch
1
Implement more simple 2-operand floating point MVE insns.
1
2
3
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
---
6
target/arm/helper-mve.h | 15 +++++++++++++++
7
target/arm/mve.decode | 6 ++++++
8
target/arm/mve_helper.c | 16 ++++++++++++++++
9
target/arm/translate-mve.c | 5 +++++
10
4 files changed, 42 insertions(+)
11
12
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/helper-mve.h
15
+++ b/target/arm/helper-mve.h
16
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vhcadd270w, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
17
DEF_HELPER_FLAGS_4(mve_vfaddh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
18
DEF_HELPER_FLAGS_4(mve_vfadds, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
20
+DEF_HELPER_FLAGS_4(mve_vfsubh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
+DEF_HELPER_FLAGS_4(mve_vfsubs, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
+
23
+DEF_HELPER_FLAGS_4(mve_vfmulh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+DEF_HELPER_FLAGS_4(mve_vfmuls, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+
26
+DEF_HELPER_FLAGS_4(mve_vfabdh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_vfabds, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+
29
+DEF_HELPER_FLAGS_4(mve_vmaxnmh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
+DEF_HELPER_FLAGS_4(mve_vmaxnms, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
+
32
+DEF_HELPER_FLAGS_4(mve_vminnmh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
+DEF_HELPER_FLAGS_4(mve_vminnms, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
+
35
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
36
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
37
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
38
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/mve.decode
41
+++ b/target/arm/mve.decode
42
@@ -XXX,XX +XXX,XX @@ VCMPLE_scalar 1111 1110 0 . .. ... 1 ... 1 1111 1 1 1 0 .... @vcmp_scalar
43
44
# 2-operand FP
45
VADD_fp 1110 1111 0 . 0 . ... 0 ... 0 1101 . 1 . 0 ... 0 @2op_fp
46
+VSUB_fp 1110 1111 0 . 1 . ... 0 ... 0 1101 . 1 . 0 ... 0 @2op_fp
47
+VMUL_fp 1111 1111 0 . 0 . ... 0 ... 0 1101 . 1 . 1 ... 0 @2op_fp
48
+VABD_fp 1111 1111 0 . 1 . ... 0 ... 0 1101 . 1 . 0 ... 0 @2op_fp
49
+
50
+VMAXNM 1111 1111 0 . 0 . ... 0 ... 0 1111 . 1 . 1 ... 0 @2op_fp
51
+VMINNM 1111 1111 0 . 1 . ... 0 ... 0 1111 . 1 . 1 ... 0 @2op_fp
52
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/mve_helper.c
55
+++ b/target/arm/mve_helper.c
56
@@ -XXX,XX +XXX,XX @@ DO_VMAXMINA(vminaw, 4, int32_t, uint32_t, DO_MIN)
57
DO_2OP_FP(OP##s, 4, float32, float32_##FN)
58
59
DO_2OP_FP_ALL(vfadd, add)
60
+DO_2OP_FP_ALL(vfsub, sub)
61
+DO_2OP_FP_ALL(vfmul, mul)
62
+
63
+static inline float16 float16_abd(float16 a, float16 b, float_status *s)
64
+{
65
+ return float16_abs(float16_sub(a, b, s));
66
+}
67
+
68
+static inline float32 float32_abd(float32 a, float32 b, float_status *s)
69
+{
70
+ return float32_abs(float32_sub(a, b, s));
71
+}
72
+
73
+DO_2OP_FP_ALL(vfabd, abd)
74
+DO_2OP_FP_ALL(vmaxnm, maxnum)
75
+DO_2OP_FP_ALL(vminnm, minnum)
76
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
77
index XXXXXXX..XXXXXXX 100644
78
--- a/target/arm/translate-mve.c
79
+++ b/target/arm/translate-mve.c
80
@@ -XXX,XX +XXX,XX @@ static bool trans_VSBCI(DisasContext *s, arg_2op *a)
81
}
82
83
DO_2OP_FP(VADD_fp, vfadd)
84
+DO_2OP_FP(VSUB_fp, vfsub)
85
+DO_2OP_FP(VMUL_fp, vfmul)
86
+DO_2OP_FP(VABD_fp, vfabd)
87
+DO_2OP_FP(VMAXNM, vmaxnm)
88
+DO_2OP_FP(VMINNM, vminnm)
89
90
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
91
MVEGenTwoOpScalarFn fn)
92
--
93
2.20.1
94
95
diff view generated by jsdifflib
New patch
1
Implement the MVE VCADD insn. Note that here the size bit is the
2
opposite sense to the other 2-operand fp insns.
1
3
4
We don't check for the sz == 1 && Qd == Qm UNPREDICTABLE case,
5
because that would mean we can't use the DO_2OP_FP macro in
6
translate-mve.c.
7
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/helper-mve.h | 6 ++++++
12
target/arm/mve.decode | 8 ++++++++
13
target/arm/mve_helper.c | 40 ++++++++++++++++++++++++++++++++++++++
14
target/arm/translate-mve.c | 4 +++-
15
4 files changed, 57 insertions(+), 1 deletion(-)
16
17
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper-mve.h
20
+++ b/target/arm/helper-mve.h
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmaxnms, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
DEF_HELPER_FLAGS_4(mve_vminnmh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
DEF_HELPER_FLAGS_4(mve_vminnms, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
25
+DEF_HELPER_FLAGS_4(mve_vfcadd90h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
+DEF_HELPER_FLAGS_4(mve_vfcadd90s, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+
28
+DEF_HELPER_FLAGS_4(mve_vfcadd270h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
+DEF_HELPER_FLAGS_4(mve_vfcadd270s, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
+
31
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
32
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
33
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
34
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/mve.decode
37
+++ b/target/arm/mve.decode
38
@@ -XXX,XX +XXX,XX @@
39
# 2 operand fp insns have size in bit 20: 1 for 16 bit, 0 for 32 bit,
40
# like Neon FP insns.
41
%2op_fp_size 20:1 !function=neon_3same_fp_size
42
+# VCADD is an exception, where bit 20 is 0 for 16 bit and 1 for 32 bit
43
+%2op_fp_size_rev 20:1 !function=plus_1
44
45
# 1imm format immediate
46
%imm_28_16_0 28:1 16:3 0:4
47
@@ -XXX,XX +XXX,XX @@
48
@2op_fp .... .... .... .... .... .... .... .... &2op \
49
qd=%qd qn=%qn qm=%qm size=%2op_fp_size
50
51
+@2op_fp_size_rev .... .... .... .... .... .... .... .... &2op \
52
+ qd=%qd qn=%qn qm=%qm size=%2op_fp_size_rev
53
+
54
# Vector loads and stores
55
56
# Widening loads and narrowing stores:
57
@@ -XXX,XX +XXX,XX @@ VABD_fp 1111 1111 0 . 1 . ... 0 ... 0 1101 . 1 . 0 ... 0 @2op_fp
58
59
VMAXNM 1111 1111 0 . 0 . ... 0 ... 0 1111 . 1 . 1 ... 0 @2op_fp
60
VMINNM 1111 1111 0 . 1 . ... 0 ... 0 1111 . 1 . 1 ... 0 @2op_fp
61
+
62
+VCADD90_fp 1111 1100 1 . 0 . ... 0 ... 0 1000 . 1 . 0 ... 0 @2op_fp_size_rev
63
+VCADD270_fp 1111 1101 1 . 0 . ... 0 ... 0 1000 . 1 . 0 ... 0 @2op_fp_size_rev
64
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/mve_helper.c
67
+++ b/target/arm/mve_helper.c
68
@@ -XXX,XX +XXX,XX @@ static inline float32 float32_abd(float32 a, float32 b, float_status *s)
69
DO_2OP_FP_ALL(vfabd, abd)
70
DO_2OP_FP_ALL(vmaxnm, maxnum)
71
DO_2OP_FP_ALL(vminnm, minnum)
72
+
73
+#define DO_VCADD_FP(OP, ESIZE, TYPE, FN0, FN1) \
74
+ void HELPER(glue(mve_, OP))(CPUARMState *env, \
75
+ void *vd, void *vn, void *vm) \
76
+ { \
77
+ TYPE *d = vd, *n = vn, *m = vm; \
78
+ TYPE r[16 / ESIZE]; \
79
+ uint16_t tm, mask = mve_element_mask(env); \
80
+ unsigned e; \
81
+ float_status *fpst; \
82
+ float_status scratch_fpst; \
83
+ /* Calculate all results first to avoid overwriting inputs */ \
84
+ for (e = 0, tm = mask; e < 16 / ESIZE; e++, tm >>= ESIZE) { \
85
+ if ((tm & MAKE_64BIT_MASK(0, ESIZE)) == 0) { \
86
+ r[e] = 0; \
87
+ continue; \
88
+ } \
89
+ fpst = (ESIZE == 2) ? &env->vfp.standard_fp_status_f16 : \
90
+ &env->vfp.standard_fp_status; \
91
+ if (!(tm & 1)) { \
92
+ /* We need the result but without updating flags */ \
93
+ scratch_fpst = *fpst; \
94
+ fpst = &scratch_fpst; \
95
+ } \
96
+ if (!(e & 1)) { \
97
+ r[e] = FN0(n[H##ESIZE(e)], m[H##ESIZE(e + 1)], fpst); \
98
+ } else { \
99
+ r[e] = FN1(n[H##ESIZE(e)], m[H##ESIZE(e - 1)], fpst); \
100
+ } \
101
+ } \
102
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
103
+ mergemask(&d[H##ESIZE(e)], r[e], mask); \
104
+ } \
105
+ mve_advance_vpt(env); \
106
+ }
107
+
108
+DO_VCADD_FP(vfcadd90h, 2, float16, float16_sub, float16_add)
109
+DO_VCADD_FP(vfcadd90s, 4, float32, float32_sub, float32_add)
110
+DO_VCADD_FP(vfcadd270h, 2, float16, float16_add, float16_sub)
111
+DO_VCADD_FP(vfcadd270s, 4, float32, float32_add, float32_sub)
112
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
113
index XXXXXXX..XXXXXXX 100644
114
--- a/target/arm/translate-mve.c
115
+++ b/target/arm/translate-mve.c
116
@@ -XXX,XX +XXX,XX @@ DO_2OP_FP(VMUL_fp, vfmul)
117
DO_2OP_FP(VABD_fp, vfabd)
118
DO_2OP_FP(VMAXNM, vmaxnm)
119
DO_2OP_FP(VMINNM, vminnm)
120
+DO_2OP_FP(VCADD90_fp, vfcadd90)
121
+DO_2OP_FP(VCADD270_fp, vfcadd270)
122
123
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
124
MVEGenTwoOpScalarFn fn)
125
@@ -XXX,XX +XXX,XX @@ static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
126
return true;
127
}
128
129
-#define DO_2OP_SCALAR(INSN, FN) \
130
+#define DO_2OP_SCALAR(INSN, FN) \
131
static bool trans_##INSN(DisasContext *s, arg_2scalar *a) \
132
{ \
133
static MVEGenTwoOpScalarFn * const fns[] = { \
134
--
135
2.20.1
136
137
diff view generated by jsdifflib
New patch
1
Implement the MVE VFMA and VFMS insns.
1
2
3
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
---
6
target/arm/helper-mve.h | 6 ++++++
7
target/arm/mve.decode | 3 +++
8
target/arm/mve_helper.c | 37 +++++++++++++++++++++++++++++++++++++
9
target/arm/translate-mve.c | 2 ++
10
4 files changed, 48 insertions(+)
11
12
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/helper-mve.h
15
+++ b/target/arm/helper-mve.h
16
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vfcadd90s, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
17
DEF_HELPER_FLAGS_4(mve_vfcadd270h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
18
DEF_HELPER_FLAGS_4(mve_vfcadd270s, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
20
+DEF_HELPER_FLAGS_4(mve_vfmah, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
+DEF_HELPER_FLAGS_4(mve_vfmas, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
+
23
+DEF_HELPER_FLAGS_4(mve_vfmsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+DEF_HELPER_FLAGS_4(mve_vfmss, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+
26
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
27
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
28
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
29
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/mve.decode
32
+++ b/target/arm/mve.decode
33
@@ -XXX,XX +XXX,XX @@ VMINNM 1111 1111 0 . 1 . ... 0 ... 0 1111 . 1 . 1 ... 0 @2op_fp
34
35
VCADD90_fp 1111 1100 1 . 0 . ... 0 ... 0 1000 . 1 . 0 ... 0 @2op_fp_size_rev
36
VCADD270_fp 1111 1101 1 . 0 . ... 0 ... 0 1000 . 1 . 0 ... 0 @2op_fp_size_rev
37
+
38
+VFMA 1110 1111 0 . 0 . ... 0 ... 0 1100 . 1 . 1 ... 0 @2op_fp
39
+VFMS 1110 1111 0 . 1 . ... 0 ... 0 1100 . 1 . 1 ... 0 @2op_fp
40
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/mve_helper.c
43
+++ b/target/arm/mve_helper.c
44
@@ -XXX,XX +XXX,XX @@ DO_VCADD_FP(vfcadd90h, 2, float16, float16_sub, float16_add)
45
DO_VCADD_FP(vfcadd90s, 4, float32, float32_sub, float32_add)
46
DO_VCADD_FP(vfcadd270h, 2, float16, float16_add, float16_sub)
47
DO_VCADD_FP(vfcadd270s, 4, float32, float32_add, float32_sub)
48
+
49
+#define DO_VFMA(OP, ESIZE, TYPE, CHS) \
50
+ void HELPER(glue(mve_, OP))(CPUARMState *env, \
51
+ void *vd, void *vn, void *vm) \
52
+ { \
53
+ TYPE *d = vd, *n = vn, *m = vm; \
54
+ TYPE r; \
55
+ uint16_t mask = mve_element_mask(env); \
56
+ unsigned e; \
57
+ float_status *fpst; \
58
+ float_status scratch_fpst; \
59
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
60
+ if ((mask & MAKE_64BIT_MASK(0, ESIZE)) == 0) { \
61
+ continue; \
62
+ } \
63
+ fpst = (ESIZE == 2) ? &env->vfp.standard_fp_status_f16 : \
64
+ &env->vfp.standard_fp_status; \
65
+ if (!(mask & 1)) { \
66
+ /* We need the result but without updating flags */ \
67
+ scratch_fpst = *fpst; \
68
+ fpst = &scratch_fpst; \
69
+ } \
70
+ r = n[H##ESIZE(e)]; \
71
+ if (CHS) { \
72
+ r = TYPE##_chs(r); \
73
+ } \
74
+ r = TYPE##_muladd(r, m[H##ESIZE(e)], d[H##ESIZE(e)], \
75
+ 0, fpst); \
76
+ mergemask(&d[H##ESIZE(e)], r, mask); \
77
+ } \
78
+ mve_advance_vpt(env); \
79
+ }
80
+
81
+DO_VFMA(vfmah, 2, float16, false)
82
+DO_VFMA(vfmas, 4, float32, false)
83
+DO_VFMA(vfmsh, 2, float16, true)
84
+DO_VFMA(vfmss, 4, float32, true)
85
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/target/arm/translate-mve.c
88
+++ b/target/arm/translate-mve.c
89
@@ -XXX,XX +XXX,XX @@ DO_2OP_FP(VMAXNM, vmaxnm)
90
DO_2OP_FP(VMINNM, vminnm)
91
DO_2OP_FP(VCADD90_fp, vfcadd90)
92
DO_2OP_FP(VCADD270_fp, vfcadd270)
93
+DO_2OP_FP(VFMA, vfma)
94
+DO_2OP_FP(VFMS, vfms)
95
96
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
97
MVEGenTwoOpScalarFn fn)
98
--
99
2.20.1
100
101
diff view generated by jsdifflib
New patch
1
1
Implement the MVE VCMUL and VCMLA insns.
2
3
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
---
6
target/arm/helper-mve.h | 18 ++++++++
7
target/arm/mve.decode | 35 ++++++++++++----
8
target/arm/mve_helper.c | 86 ++++++++++++++++++++++++++++++++++++++
9
target/arm/translate-mve.c | 8 ++++
10
4 files changed, 139 insertions(+), 8 deletions(-)
11
12
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/helper-mve.h
15
+++ b/target/arm/helper-mve.h
16
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vfmas, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
17
DEF_HELPER_FLAGS_4(mve_vfmsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
18
DEF_HELPER_FLAGS_4(mve_vfmss, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
20
+DEF_HELPER_FLAGS_4(mve_vcmul0h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
+DEF_HELPER_FLAGS_4(mve_vcmul0s, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
+DEF_HELPER_FLAGS_4(mve_vcmul90h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
+DEF_HELPER_FLAGS_4(mve_vcmul90s, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+DEF_HELPER_FLAGS_4(mve_vcmul180h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+DEF_HELPER_FLAGS_4(mve_vcmul180s, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
+DEF_HELPER_FLAGS_4(mve_vcmul270h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_vcmul270s, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+
29
+DEF_HELPER_FLAGS_4(mve_vcmla0h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
+DEF_HELPER_FLAGS_4(mve_vcmla0s, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
+DEF_HELPER_FLAGS_4(mve_vcmla90h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
+DEF_HELPER_FLAGS_4(mve_vcmla90s, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
+DEF_HELPER_FLAGS_4(mve_vcmla180h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
+DEF_HELPER_FLAGS_4(mve_vcmla180s, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
35
+DEF_HELPER_FLAGS_4(mve_vcmla270h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
+DEF_HELPER_FLAGS_4(mve_vcmla270s, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
37
+
38
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
39
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
40
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
41
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
42
index XXXXXXX..XXXXXXX 100644
43
--- a/target/arm/mve.decode
44
+++ b/target/arm/mve.decode
45
@@ -XXX,XX +XXX,XX @@ VQSHL_U 111 1 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
46
VQRSHL_S 111 0 1111 0 . .. ... 0 ... 0 0101 . 1 . 1 ... 0 @2op_rev
47
VQRSHL_U 111 1 1111 0 . .. ... 0 ... 0 0101 . 1 . 1 ... 0 @2op_rev
48
49
-VQDMLADH 1110 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 0 @2op
50
-VQDMLADHX 1110 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 0 @2op
51
-VQRDMLADH 1110 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 1 @2op
52
-VQRDMLADHX 1110 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 1 @2op
53
+{
54
+ VCMUL0 111 . 1110 0 . 11 ... 0 ... 0 1110 . 0 . 0 ... 0 @2op_sz28
55
+ VQDMLADH 1110 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 0 @2op
56
+ VQDMLSDH 1111 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 0 @2op
57
+}
58
59
-VQDMLSDH 1111 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 0 @2op
60
-VQDMLSDHX 1111 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 0 @2op
61
-VQRDMLSDH 1111 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 1 @2op
62
-VQRDMLSDHX 1111 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 1 @2op
63
+{
64
+ VCMUL180 111 . 1110 0 . 11 ... 0 ... 1 1110 . 0 . 0 ... 0 @2op_sz28
65
+ VQDMLADHX 111 0 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 0 @2op
66
+ VQDMLSDHX 111 1 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 0 @2op
67
+}
68
+
69
+{
70
+ VCMUL90 111 . 1110 0 . 11 ... 0 ... 0 1110 . 0 . 0 ... 1 @2op_sz28
71
+ VQRDMLADH 111 0 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 1 @2op
72
+ VQRDMLSDH 111 1 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 1 @2op
73
+}
74
+
75
+{
76
+ VCMUL270 111 . 1110 0 . 11 ... 0 ... 1 1110 . 0 . 0 ... 1 @2op_sz28
77
+ VQRDMLADHX 111 0 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 1 @2op
78
+ VQRDMLSDHX 111 1 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 1 @2op
79
+}
80
81
VQDMULLB 111 . 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 1 @2op_sz28
82
VQDMULLT 111 . 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 1 @2op_sz28
83
@@ -XXX,XX +XXX,XX @@ VCADD270_fp 1111 1101 1 . 0 . ... 0 ... 0 1000 . 1 . 0 ... 0 @2op_fp_size_
84
85
VFMA 1110 1111 0 . 0 . ... 0 ... 0 1100 . 1 . 1 ... 0 @2op_fp
86
VFMS 1110 1111 0 . 1 . ... 0 ... 0 1100 . 1 . 1 ... 0 @2op_fp
87
+
88
+VCMLA0 1111 110 00 . 1 . ... 0 ... 0 1000 . 1 . 0 ... 0 @2op_fp_size_rev
89
+VCMLA90 1111 110 01 . 1 . ... 0 ... 0 1000 . 1 . 0 ... 0 @2op_fp_size_rev
90
+VCMLA180 1111 110 10 . 1 . ... 0 ... 0 1000 . 1 . 0 ... 0 @2op_fp_size_rev
91
+VCMLA270 1111 110 11 . 1 . ... 0 ... 0 1000 . 1 . 0 ... 0 @2op_fp_size_rev
92
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
93
index XXXXXXX..XXXXXXX 100644
94
--- a/target/arm/mve_helper.c
95
+++ b/target/arm/mve_helper.c
96
@@ -XXX,XX +XXX,XX @@ DO_VFMA(vfmah, 2, float16, false)
97
DO_VFMA(vfmas, 4, float32, false)
98
DO_VFMA(vfmsh, 2, float16, true)
99
DO_VFMA(vfmss, 4, float32, true)
100
+
101
+#define DO_VCMLA(OP, ESIZE, TYPE, ROT, FN) \
102
+ void HELPER(glue(mve_, OP))(CPUARMState *env, \
103
+ void *vd, void *vn, void *vm) \
104
+ { \
105
+ TYPE *d = vd, *n = vn, *m = vm; \
106
+ TYPE r0, r1, e1, e2, e3, e4; \
107
+ uint16_t mask = mve_element_mask(env); \
108
+ unsigned e; \
109
+ float_status *fpst0, *fpst1; \
110
+ float_status scratch_fpst; \
111
+ /* We loop through pairs of elements at a time */ \
112
+ for (e = 0; e < 16 / ESIZE; e += 2, mask >>= ESIZE * 2) { \
113
+ if ((mask & MAKE_64BIT_MASK(0, ESIZE * 2)) == 0) { \
114
+ continue; \
115
+ } \
116
+ fpst0 = (ESIZE == 2) ? &env->vfp.standard_fp_status_f16 : \
117
+ &env->vfp.standard_fp_status; \
118
+ fpst1 = fpst0; \
119
+ if (!(mask & 1)) { \
120
+ scratch_fpst = *fpst0; \
121
+ fpst0 = &scratch_fpst; \
122
+ } \
123
+ if (!(mask & (1 << ESIZE))) { \
124
+ scratch_fpst = *fpst1; \
125
+ fpst1 = &scratch_fpst; \
126
+ } \
127
+ switch (ROT) { \
128
+ case 0: \
129
+ e1 = m[H##ESIZE(e)]; \
130
+ e2 = n[H##ESIZE(e)]; \
131
+ e3 = m[H##ESIZE(e + 1)]; \
132
+ e4 = n[H##ESIZE(e)]; \
133
+ break; \
134
+ case 1: \
135
+ e1 = TYPE##_chs(m[H##ESIZE(e + 1)]); \
136
+ e2 = n[H##ESIZE(e + 1)]; \
137
+ e3 = m[H##ESIZE(e)]; \
138
+ e4 = n[H##ESIZE(e + 1)]; \
139
+ break; \
140
+ case 2: \
141
+ e1 = TYPE##_chs(m[H##ESIZE(e)]); \
142
+ e2 = n[H##ESIZE(e)]; \
143
+ e3 = TYPE##_chs(m[H##ESIZE(e + 1)]); \
144
+ e4 = n[H##ESIZE(e)]; \
145
+ break; \
146
+ case 3: \
147
+ e1 = m[H##ESIZE(e + 1)]; \
148
+ e2 = n[H##ESIZE(e + 1)]; \
149
+ e3 = TYPE##_chs(m[H##ESIZE(e)]); \
150
+ e4 = n[H##ESIZE(e + 1)]; \
151
+ break; \
152
+ default: \
153
+ g_assert_not_reached(); \
154
+ } \
155
+ r0 = FN(e2, e1, d[H##ESIZE(e)], fpst0); \
156
+ r1 = FN(e4, e3, d[H##ESIZE(e + 1)], fpst1); \
157
+ mergemask(&d[H##ESIZE(e)], r0, mask); \
158
+ mergemask(&d[H##ESIZE(e + 1)], r1, mask >> ESIZE); \
159
+ } \
160
+ mve_advance_vpt(env); \
161
+ }
162
+
163
+#define DO_VCMULH(N, M, D, S) float16_mul(N, M, S)
164
+#define DO_VCMULS(N, M, D, S) float32_mul(N, M, S)
165
+
166
+#define DO_VCMLAH(N, M, D, S) float16_muladd(N, M, D, 0, S)
167
+#define DO_VCMLAS(N, M, D, S) float32_muladd(N, M, D, 0, S)
168
+
169
+DO_VCMLA(vcmul0h, 2, float16, 0, DO_VCMULH)
170
+DO_VCMLA(vcmul0s, 4, float32, 0, DO_VCMULS)
171
+DO_VCMLA(vcmul90h, 2, float16, 1, DO_VCMULH)
172
+DO_VCMLA(vcmul90s, 4, float32, 1, DO_VCMULS)
173
+DO_VCMLA(vcmul180h, 2, float16, 2, DO_VCMULH)
174
+DO_VCMLA(vcmul180s, 4, float32, 2, DO_VCMULS)
175
+DO_VCMLA(vcmul270h, 2, float16, 3, DO_VCMULH)
176
+DO_VCMLA(vcmul270s, 4, float32, 3, DO_VCMULS)
177
+
178
+DO_VCMLA(vcmla0h, 2, float16, 0, DO_VCMLAH)
179
+DO_VCMLA(vcmla0s, 4, float32, 0, DO_VCMLAS)
180
+DO_VCMLA(vcmla90h, 2, float16, 1, DO_VCMLAH)
181
+DO_VCMLA(vcmla90s, 4, float32, 1, DO_VCMLAS)
182
+DO_VCMLA(vcmla180h, 2, float16, 2, DO_VCMLAH)
183
+DO_VCMLA(vcmla180s, 4, float32, 2, DO_VCMLAS)
184
+DO_VCMLA(vcmla270h, 2, float16, 3, DO_VCMLAH)
185
+DO_VCMLA(vcmla270s, 4, float32, 3, DO_VCMLAS)
186
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
187
index XXXXXXX..XXXXXXX 100644
188
--- a/target/arm/translate-mve.c
189
+++ b/target/arm/translate-mve.c
190
@@ -XXX,XX +XXX,XX @@ DO_2OP_FP(VCADD90_fp, vfcadd90)
191
DO_2OP_FP(VCADD270_fp, vfcadd270)
192
DO_2OP_FP(VFMA, vfma)
193
DO_2OP_FP(VFMS, vfms)
194
+DO_2OP_FP(VCMUL0, vcmul0)
195
+DO_2OP_FP(VCMUL90, vcmul90)
196
+DO_2OP_FP(VCMUL180, vcmul180)
197
+DO_2OP_FP(VCMUL270, vcmul270)
198
+DO_2OP_FP(VCMLA0, vcmla0)
199
+DO_2OP_FP(VCMLA90, vcmla90)
200
+DO_2OP_FP(VCMLA180, vcmla180)
201
+DO_2OP_FP(VCMLA270, vcmla270)
202
203
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
204
MVEGenTwoOpScalarFn fn)
205
--
206
2.20.1
207
208
diff view generated by jsdifflib
1
From: Jean-Christophe Dubois <jcd@tribudubois.net>
1
Implement the MVE VMAXNMA and VMINNMA insns; these are 2-operand, but
2
the destination register must be the same as one of the source
3
registers.
2
4
3
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
5
We defer the decode of the size in bit 28 to the individual insn
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
patterns rather than doing it in the format, because otherwise we
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
would have a single insn pattern that overlapped with two groups (eg
6
[PMD: Fixed 32-bit format string using PRIx32/PRIx64]
8
VMAXNMA with the VMULH_S and VMULH_U groups). Having two insn
7
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
patterns per insn seems clearer than a complex multilevel nesting
10
of overlapping and non-overlapping groups.
11
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
14
---
10
hw/net/imx_fec.c | 106 +++++++++++++++++++-------------------------
15
target/arm/helper-mve.h | 6 ++++++
11
hw/net/trace-events | 18 ++++++++
16
target/arm/mve.decode | 11 +++++++++++
12
2 files changed, 63 insertions(+), 61 deletions(-)
17
target/arm/mve_helper.c | 23 +++++++++++++++++++++++
18
target/arm/translate-mve.c | 2 ++
19
4 files changed, 42 insertions(+)
13
20
14
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
21
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
15
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/net/imx_fec.c
23
--- a/target/arm/helper-mve.h
17
+++ b/hw/net/imx_fec.c
24
+++ b/target/arm/helper-mve.h
25
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmaxnms, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
DEF_HELPER_FLAGS_4(mve_vminnmh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
DEF_HELPER_FLAGS_4(mve_vminnms, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
29
+DEF_HELPER_FLAGS_4(mve_vmaxnmah, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
+DEF_HELPER_FLAGS_4(mve_vmaxnmas, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
+
32
+DEF_HELPER_FLAGS_4(mve_vminnmah, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
+DEF_HELPER_FLAGS_4(mve_vminnmas, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
+
35
DEF_HELPER_FLAGS_4(mve_vfcadd90h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
DEF_HELPER_FLAGS_4(mve_vfcadd90s, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
37
38
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/mve.decode
41
+++ b/target/arm/mve.decode
18
@@ -XXX,XX +XXX,XX @@
42
@@ -XXX,XX +XXX,XX @@
19
#include "qemu/module.h"
43
@2op_fp_size_rev .... .... .... .... .... .... .... .... &2op \
20
#include "net/checksum.h"
44
qd=%qd qn=%qn qm=%qm size=%2op_fp_size_rev
21
#include "net/eth.h"
45
22
+#include "trace.h"
46
+# 2-operand, but Qd and Qn share a field. Size is in bit 28, but we
23
47
+# don't decode it in this format
24
/* For crc32 */
48
+@vmaxnma .... .... .... .... .... .... .... .... &2op \
25
#include <zlib.h>
49
+ qd=%qd qn=%qd qm=%qm
26
50
+
27
-#ifndef DEBUG_IMX_FEC
51
# Vector loads and stores
28
-#define DEBUG_IMX_FEC 0
52
29
-#endif
53
# Widening loads and narrowing stores:
30
-
54
@@ -XXX,XX +XXX,XX @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
31
-#define FEC_PRINTF(fmt, args...) \
55
# The VSHLL T2 encoding is not a @2op pattern, but is here because it
32
- do { \
56
# overlaps what would be size=0b11 VMULH/VRMULH
33
- if (DEBUG_IMX_FEC) { \
34
- fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_FEC, \
35
- __func__, ##args); \
36
- } \
37
- } while (0)
38
-
39
-#ifndef DEBUG_IMX_PHY
40
-#define DEBUG_IMX_PHY 0
41
-#endif
42
-
43
-#define PHY_PRINTF(fmt, args...) \
44
- do { \
45
- if (DEBUG_IMX_PHY) { \
46
- fprintf(stderr, "[%s.phy]%s: " fmt , TYPE_IMX_FEC, \
47
- __func__, ##args); \
48
- } \
49
- } while (0)
50
-
51
#define IMX_MAX_DESC 1024
52
53
static const char *imx_default_reg_name(IMXFECState *s, uint32_t index)
54
@@ -XXX,XX +XXX,XX @@ static void imx_eth_update(IMXFECState *s);
55
* For now we don't handle any GPIO/interrupt line, so the OS will
56
* have to poll for the PHY status.
57
*/
58
-static void phy_update_irq(IMXFECState *s)
59
+static void imx_phy_update_irq(IMXFECState *s)
60
{
57
{
61
imx_eth_update(s);
58
+ VMAXNMA 111 0 1110 0 . 11 1111 ... 0 1110 1 0 . 0 ... 1 @vmaxnma size=2
59
+
60
VSHLL_BS 111 0 1110 0 . 11 .. 01 ... 0 1110 0 0 . 0 ... 1 @2_shll_esize_b
61
VSHLL_BS 111 0 1110 0 . 11 .. 01 ... 0 1110 0 0 . 0 ... 1 @2_shll_esize_h
62
63
@@ -XXX,XX +XXX,XX @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
62
}
64
}
63
65
64
-static void phy_update_link(IMXFECState *s)
65
+static void imx_phy_update_link(IMXFECState *s)
66
{
66
{
67
/* Autonegotiation status mirrors link status. */
67
+ VMAXNMA 111 1 1110 0 . 11 1111 ... 0 1110 1 0 . 0 ... 1 @vmaxnma size=1
68
if (qemu_get_queue(s->nic)->link_down) {
68
+
69
- PHY_PRINTF("link is down\n");
69
VSHLL_BU 111 1 1110 0 . 11 .. 01 ... 0 1110 0 0 . 0 ... 1 @2_shll_esize_b
70
+ trace_imx_phy_update_link("down");
70
VSHLL_BU 111 1 1110 0 . 11 .. 01 ... 0 1110 0 0 . 0 ... 1 @2_shll_esize_h
71
s->phy_status &= ~0x0024;
71
72
s->phy_int |= PHY_INT_DOWN;
72
@@ -XXX,XX +XXX,XX @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
73
} else {
74
- PHY_PRINTF("link is up\n");
75
+ trace_imx_phy_update_link("up");
76
s->phy_status |= 0x0024;
77
s->phy_int |= PHY_INT_ENERGYON;
78
s->phy_int |= PHY_INT_AUTONEG_COMPLETE;
79
}
80
- phy_update_irq(s);
81
+ imx_phy_update_irq(s);
82
}
73
}
83
74
84
static void imx_eth_set_link(NetClientState *nc)
85
{
75
{
86
- phy_update_link(IMX_FEC(qemu_get_nic_opaque(nc)));
76
+ VMINNMA 111 0 1110 0 . 11 1111 ... 1 1110 1 0 . 0 ... 1 @vmaxnma size=2
87
+ imx_phy_update_link(IMX_FEC(qemu_get_nic_opaque(nc)));
77
VSHLL_TS 111 0 1110 0 . 11 .. 01 ... 1 1110 0 0 . 0 ... 1 @2_shll_esize_b
78
VSHLL_TS 111 0 1110 0 . 11 .. 01 ... 1 1110 0 0 . 0 ... 1 @2_shll_esize_h
79
80
@@ -XXX,XX +XXX,XX @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
88
}
81
}
89
82
90
-static void phy_reset(IMXFECState *s)
91
+static void imx_phy_reset(IMXFECState *s)
92
{
83
{
93
+ trace_imx_phy_reset();
84
+ VMINNMA 111 1 1110 0 . 11 1111 ... 1 1110 1 0 . 0 ... 1 @vmaxnma size=1
85
VSHLL_TU 111 1 1110 0 . 11 .. 01 ... 1 1110 0 0 . 0 ... 1 @2_shll_esize_b
86
VSHLL_TU 111 1 1110 0 . 11 .. 01 ... 1 1110 0 0 . 0 ... 1 @2_shll_esize_h
87
88
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/target/arm/mve_helper.c
91
+++ b/target/arm/mve_helper.c
92
@@ -XXX,XX +XXX,XX @@ DO_2OP_FP_ALL(vfabd, abd)
93
DO_2OP_FP_ALL(vmaxnm, maxnum)
94
DO_2OP_FP_ALL(vminnm, minnum)
95
96
+static inline float16 float16_maxnuma(float16 a, float16 b, float_status *s)
97
+{
98
+ return float16_maxnum(float16_abs(a), float16_abs(b), s);
99
+}
94
+
100
+
95
s->phy_status = 0x7809;
101
+static inline float32 float32_maxnuma(float32 a, float32 b, float_status *s)
96
s->phy_control = 0x3000;
102
+{
97
s->phy_advertise = 0x01e1;
103
+ return float32_maxnum(float32_abs(a), float32_abs(b), s);
98
s->phy_int_mask = 0;
104
+}
99
s->phy_int = 0;
100
- phy_update_link(s);
101
+ imx_phy_update_link(s);
102
}
103
104
-static uint32_t do_phy_read(IMXFECState *s, int reg)
105
+static uint32_t imx_phy_read(IMXFECState *s, int reg)
106
{
107
uint32_t val;
108
109
@@ -XXX,XX +XXX,XX @@ static uint32_t do_phy_read(IMXFECState *s, int reg)
110
case 29: /* Interrupt source. */
111
val = s->phy_int;
112
s->phy_int = 0;
113
- phy_update_irq(s);
114
+ imx_phy_update_irq(s);
115
break;
116
case 30: /* Interrupt mask */
117
val = s->phy_int_mask;
118
@@ -XXX,XX +XXX,XX @@ static uint32_t do_phy_read(IMXFECState *s, int reg)
119
break;
120
}
121
122
- PHY_PRINTF("read 0x%04x @ %d\n", val, reg);
123
+ trace_imx_phy_read(val, reg);
124
125
return val;
126
}
127
128
-static void do_phy_write(IMXFECState *s, int reg, uint32_t val)
129
+static void imx_phy_write(IMXFECState *s, int reg, uint32_t val)
130
{
131
- PHY_PRINTF("write 0x%04x @ %d\n", val, reg);
132
+ trace_imx_phy_write(val, reg);
133
134
if (reg > 31) {
135
/* we only advertise one phy */
136
@@ -XXX,XX +XXX,XX @@ static void do_phy_write(IMXFECState *s, int reg, uint32_t val)
137
switch (reg) {
138
case 0: /* Basic Control */
139
if (val & 0x8000) {
140
- phy_reset(s);
141
+ imx_phy_reset(s);
142
} else {
143
s->phy_control = val & 0x7980;
144
/* Complete autonegotiation immediately. */
145
@@ -XXX,XX +XXX,XX @@ static void do_phy_write(IMXFECState *s, int reg, uint32_t val)
146
break;
147
case 30: /* Interrupt mask */
148
s->phy_int_mask = val & 0xff;
149
- phy_update_irq(s);
150
+ imx_phy_update_irq(s);
151
break;
152
case 17:
153
case 18:
154
@@ -XXX,XX +XXX,XX @@ static void do_phy_write(IMXFECState *s, int reg, uint32_t val)
155
static void imx_fec_read_bd(IMXFECBufDesc *bd, dma_addr_t addr)
156
{
157
dma_memory_read(&address_space_memory, addr, bd, sizeof(*bd));
158
+
105
+
159
+ trace_imx_fec_read_bd(addr, bd->flags, bd->length, bd->data);
106
+static inline float16 float16_minnuma(float16 a, float16 b, float_status *s)
160
}
107
+{
161
108
+ return float16_minnum(float16_abs(a), float16_abs(b), s);
162
static void imx_fec_write_bd(IMXFECBufDesc *bd, dma_addr_t addr)
109
+}
163
@@ -XXX,XX +XXX,XX @@ static void imx_fec_write_bd(IMXFECBufDesc *bd, dma_addr_t addr)
164
static void imx_enet_read_bd(IMXENETBufDesc *bd, dma_addr_t addr)
165
{
166
dma_memory_read(&address_space_memory, addr, bd, sizeof(*bd));
167
+
110
+
168
+ trace_imx_enet_read_bd(addr, bd->flags, bd->length, bd->data,
111
+static inline float32 float32_minnuma(float32 a, float32 b, float_status *s)
169
+ bd->option, bd->status);
112
+{
170
}
113
+ return float32_minnum(float32_abs(a), float32_abs(b), s);
171
114
+}
172
static void imx_enet_write_bd(IMXENETBufDesc *bd, dma_addr_t addr)
173
@@ -XXX,XX +XXX,XX @@ static void imx_fec_do_tx(IMXFECState *s)
174
int len;
175
176
imx_fec_read_bd(&bd, addr);
177
- FEC_PRINTF("tx_bd %x flags %04x len %d data %08x\n",
178
- addr, bd.flags, bd.length, bd.data);
179
if ((bd.flags & ENET_BD_R) == 0) {
180
+
115
+
181
/* Run out of descriptors to transmit. */
116
+DO_2OP_FP_ALL(vmaxnma, maxnuma)
182
- FEC_PRINTF("tx_bd ran out of descriptors to transmit\n");
117
+DO_2OP_FP_ALL(vminnma, minnuma)
183
+ trace_imx_eth_tx_bd_busy();
184
+
118
+
185
break;
119
#define DO_VCADD_FP(OP, ESIZE, TYPE, FN0, FN1) \
186
}
120
void HELPER(glue(mve_, OP))(CPUARMState *env, \
187
len = bd.length;
121
void *vd, void *vn, void *vm) \
188
@@ -XXX,XX +XXX,XX @@ static void imx_enet_do_tx(IMXFECState *s, uint32_t index)
122
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
189
int len;
190
191
imx_enet_read_bd(&bd, addr);
192
- FEC_PRINTF("tx_bd %x flags %04x len %d data %08x option %04x "
193
- "status %04x\n", addr, bd.flags, bd.length, bd.data,
194
- bd.option, bd.status);
195
if ((bd.flags & ENET_BD_R) == 0) {
196
/* Run out of descriptors to transmit. */
197
+
198
+ trace_imx_eth_tx_bd_busy();
199
+
200
break;
201
}
202
len = bd.length;
203
@@ -XXX,XX +XXX,XX @@ static void imx_eth_enable_rx(IMXFECState *s, bool flush)
204
s->regs[ENET_RDAR] = (bd.flags & ENET_BD_E) ? ENET_RDAR_RDAR : 0;
205
206
if (!s->regs[ENET_RDAR]) {
207
- FEC_PRINTF("RX buffer full\n");
208
+ trace_imx_eth_rx_bd_full();
209
} else if (flush) {
210
qemu_flush_queued_packets(qemu_get_queue(s->nic));
211
}
212
@@ -XXX,XX +XXX,XX @@ static void imx_eth_reset(DeviceState *d)
213
memset(s->tx_descriptor, 0, sizeof(s->tx_descriptor));
214
215
/* We also reset the PHY */
216
- phy_reset(s);
217
+ imx_phy_reset(s);
218
}
219
220
static uint32_t imx_default_read(IMXFECState *s, uint32_t index)
221
@@ -XXX,XX +XXX,XX @@ static uint64_t imx_eth_read(void *opaque, hwaddr offset, unsigned size)
222
break;
223
}
224
225
- FEC_PRINTF("reg[%s] => 0x%" PRIx32 "\n", imx_eth_reg_name(s, index),
226
- value);
227
+ trace_imx_eth_read(index, imx_eth_reg_name(s, index), value);
228
229
return value;
230
}
231
@@ -XXX,XX +XXX,XX @@ static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value,
232
const bool single_tx_ring = !imx_eth_is_multi_tx_ring(s);
233
uint32_t index = offset >> 2;
234
235
- FEC_PRINTF("reg[%s] <= 0x%" PRIx32 "\n", imx_eth_reg_name(s, index),
236
- (uint32_t)value);
237
+ trace_imx_eth_write(index, imx_eth_reg_name(s, index), value);
238
239
switch (index) {
240
case ENET_EIR:
241
@@ -XXX,XX +XXX,XX @@ static void imx_eth_write(void *opaque, hwaddr offset, uint64_t value,
242
if (extract32(value, 29, 1)) {
243
/* This is a read operation */
244
s->regs[ENET_MMFR] = deposit32(s->regs[ENET_MMFR], 0, 16,
245
- do_phy_read(s,
246
+ imx_phy_read(s,
247
extract32(value,
248
18, 10)));
249
} else {
250
/* This a write operation */
251
- do_phy_write(s, extract32(value, 18, 10), extract32(value, 0, 16));
252
+ imx_phy_write(s, extract32(value, 18, 10), extract32(value, 0, 16));
253
}
254
/* raise the interrupt as the PHY operation is done */
255
s->regs[ENET_EIR] |= ENET_INT_MII;
256
@@ -XXX,XX +XXX,XX @@ static bool imx_eth_can_receive(NetClientState *nc)
257
{
258
IMXFECState *s = IMX_FEC(qemu_get_nic_opaque(nc));
259
260
- FEC_PRINTF("\n");
261
-
262
return !!s->regs[ENET_RDAR];
263
}
264
265
@@ -XXX,XX +XXX,XX @@ static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf,
266
unsigned int buf_len;
267
size_t size = len;
268
269
- FEC_PRINTF("len %d\n", (int)size);
270
+ trace_imx_fec_receive(size);
271
272
if (!s->regs[ENET_RDAR]) {
273
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Unexpected packet\n",
274
@@ -XXX,XX +XXX,XX @@ static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf,
275
bd.length = buf_len;
276
size -= buf_len;
277
278
- FEC_PRINTF("rx_bd 0x%x length %d\n", addr, bd.length);
279
+ trace_imx_fec_receive_len(addr, bd.length);
280
281
/* The last 4 bytes are the CRC. */
282
if (size < 4) {
283
@@ -XXX,XX +XXX,XX @@ static ssize_t imx_fec_receive(NetClientState *nc, const uint8_t *buf,
284
if (size == 0) {
285
/* Last buffer in frame. */
286
bd.flags |= flags | ENET_BD_L;
287
- FEC_PRINTF("rx frame flags %04x\n", bd.flags);
288
+
289
+ trace_imx_fec_receive_last(bd.flags);
290
+
291
s->regs[ENET_EIR] |= ENET_INT_RXF;
292
} else {
293
s->regs[ENET_EIR] |= ENET_INT_RXB;
294
@@ -XXX,XX +XXX,XX @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf,
295
size_t size = len;
296
bool shift16 = s->regs[ENET_RACC] & ENET_RACC_SHIFT16;
297
298
- FEC_PRINTF("len %d\n", (int)size);
299
+ trace_imx_enet_receive(size);
300
301
if (!s->regs[ENET_RDAR]) {
302
qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Unexpected packet\n",
303
@@ -XXX,XX +XXX,XX @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf,
304
bd.length = buf_len;
305
size -= buf_len;
306
307
- FEC_PRINTF("rx_bd 0x%x length %d\n", addr, bd.length);
308
+ trace_imx_enet_receive_len(addr, bd.length);
309
310
/* The last 4 bytes are the CRC. */
311
if (size < 4) {
312
@@ -XXX,XX +XXX,XX @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf,
313
if (size == 0) {
314
/* Last buffer in frame. */
315
bd.flags |= flags | ENET_BD_L;
316
- FEC_PRINTF("rx frame flags %04x\n", bd.flags);
317
+
318
+ trace_imx_enet_receive_last(bd.flags);
319
+
320
/* Indicate that we've updated the last buffer descriptor. */
321
bd.last_buffer = ENET_BD_BDU;
322
if (bd.option & ENET_BD_RX_INT) {
323
diff --git a/hw/net/trace-events b/hw/net/trace-events
324
index XXXXXXX..XXXXXXX 100644
123
index XXXXXXX..XXXXXXX 100644
325
--- a/hw/net/trace-events
124
--- a/target/arm/translate-mve.c
326
+++ b/hw/net/trace-events
125
+++ b/target/arm/translate-mve.c
327
@@ -XXX,XX +XXX,XX @@ i82596_receive_packet(size_t sz) "len=%zu"
126
@@ -XXX,XX +XXX,XX @@ DO_2OP_FP(VCMLA0, vcmla0)
328
i82596_new_mac(const char *id_with_mac) "New MAC for: %s"
127
DO_2OP_FP(VCMLA90, vcmla90)
329
i82596_set_multicast(uint16_t count) "Added %d multicast entries"
128
DO_2OP_FP(VCMLA180, vcmla180)
330
i82596_channel_attention(void *s) "%p: Received CHANNEL ATTENTION"
129
DO_2OP_FP(VCMLA270, vcmla270)
331
+
130
+DO_2OP_FP(VMAXNMA, vmaxnma)
332
+# imx_fec.c
131
+DO_2OP_FP(VMINNMA, vminnma)
333
+imx_phy_read(uint32_t val, int reg) "0x%04"PRIx32" <= reg[%d]"
132
334
+imx_phy_write(uint32_t val, int reg) "0x%04"PRIx32" => reg[%d]"
133
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
335
+imx_phy_update_link(const char *s) "%s"
134
MVEGenTwoOpScalarFn fn)
336
+imx_phy_reset(void) ""
337
+imx_fec_read_bd(uint64_t addr, int flags, int len, int data) "tx_bd 0x%"PRIx64" flags 0x%04x len %d data 0x%08x"
338
+imx_enet_read_bd(uint64_t addr, int flags, int len, int data, int options, int status) "tx_bd 0x%"PRIx64" flags 0x%04x len %d data 0x%08x option 0x%04x status 0x%04x"
339
+imx_eth_tx_bd_busy(void) "tx_bd ran out of descriptors to transmit"
340
+imx_eth_rx_bd_full(void) "RX buffer is full"
341
+imx_eth_read(int reg, const char *reg_name, uint32_t value) "reg[%d:%s] => 0x%08"PRIx32
342
+imx_eth_write(int reg, const char *reg_name, uint64_t value) "reg[%d:%s] <= 0x%08"PRIx64
343
+imx_fec_receive(size_t size) "len %zu"
344
+imx_fec_receive_len(uint64_t addr, int len) "rx_bd 0x%"PRIx64" length %d"
345
+imx_fec_receive_last(int last) "rx frame flags 0x%04x"
346
+imx_enet_receive(size_t size) "len %zu"
347
+imx_enet_receive_len(uint64_t addr, int len) "rx_bd 0x%"PRIx64" length %d"
348
+imx_enet_receive_last(int last) "rx frame flags 0x%04x"
349
--
135
--
350
2.20.1
136
2.20.1
351
137
352
138
diff view generated by jsdifflib
1
Convert the Neon VEXT insn to decodetree. Rather than keeping the
1
Implement the MVE scalar floating point insns VADD, VSUB and VMUL.
2
old implementation which used fixed temporaries cpu_V0 and cpu_V1
3
and did the extraction with by-hand shift and logic ops, we use
4
the TCG extract2 insn.
5
6
We don't need to special case 0 or 8 immediates any more as the
7
optimizer is smart enough to throw away the dead code.
8
2
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
---
5
---
12
target/arm/neon-dp.decode | 8 +++-
6
target/arm/helper-mve.h | 9 +++++++++
13
target/arm/translate-neon.inc.c | 76 +++++++++++++++++++++++++++++++++
7
target/arm/mve.decode | 27 +++++++++++++++++++++------
14
target/arm/translate.c | 58 +------------------------
8
target/arm/mve_helper.c | 35 +++++++++++++++++++++++++++++++++++
15
3 files changed, 85 insertions(+), 57 deletions(-)
9
target/arm/translate-mve.c | 20 ++++++++++++++++++++
10
4 files changed, 85 insertions(+), 6 deletions(-)
16
11
17
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
12
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
18
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/neon-dp.decode
14
--- a/target/arm/helper-mve.h
20
+++ b/target/arm/neon-dp.decode
15
+++ b/target/arm/helper-mve.h
21
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
16
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vcmpgt_scalarw, TCG_CALL_NO_WG, void, env, ptr, i32)
22
# return false for size==3.
17
DEF_HELPER_FLAGS_3(mve_vcmple_scalarb, TCG_CALL_NO_WG, void, env, ptr, i32)
23
######################################################################
18
DEF_HELPER_FLAGS_3(mve_vcmple_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
19
DEF_HELPER_FLAGS_3(mve_vcmple_scalarw, TCG_CALL_NO_WG, void, env, ptr, i32)
20
+
21
+DEF_HELPER_FLAGS_4(mve_vfadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
22
+DEF_HELPER_FLAGS_4(mve_vfadd_scalars, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
23
+
24
+DEF_HELPER_FLAGS_4(mve_vfsub_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
+DEF_HELPER_FLAGS_4(mve_vfsub_scalars, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
26
+
27
+DEF_HELPER_FLAGS_4(mve_vfmul_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
28
+DEF_HELPER_FLAGS_4(mve_vfmul_scalars, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
29
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/mve.decode
32
+++ b/target/arm/mve.decode
33
@@ -XXX,XX +XXX,XX @@
34
%2op_fp_size 20:1 !function=neon_3same_fp_size
35
# VCADD is an exception, where bit 20 is 0 for 16 bit and 1 for 32 bit
36
%2op_fp_size_rev 20:1 !function=plus_1
37
+# FP scalars have size in bit 28, 1 for 16 bit, 0 for 32 bit
38
+%2op_fp_scalar_size 28:1 !function=neon_3same_fp_size
39
40
# 1imm format immediate
41
%imm_28_16_0 28:1 16:3 0:4
42
@@ -XXX,XX +XXX,XX @@
43
@vmaxnma .... .... .... .... .... .... .... .... &2op \
44
qd=%qd qn=%qd qm=%qm
45
46
+@2op_fp_scalar .... .... .... .... .... .... .... rm:4 &2scalar \
47
+ qd=%qd qn=%qn size=%2op_fp_scalar_size
48
+
49
# Vector loads and stores
50
51
# Widening loads and narrowing stores:
52
@@ -XXX,XX +XXX,XX @@ VSUB_scalar 1110 1110 0 . .. ... 1 ... 1 1111 . 100 .... @2scalar
53
VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
54
}
55
56
-VHADD_S_scalar 1110 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
57
-VHADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
58
-VHSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
59
-VHSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
60
+{
61
+ VADD_fp_scalar 111 . 1110 0 . 11 ... 0 ... 0 1111 . 100 .... @2op_fp_scalar
62
+ VHADD_S_scalar 1110 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
63
+ VHADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
64
+}
65
+
66
+{
67
+ VSUB_fp_scalar 111 . 1110 0 . 11 ... 0 ... 1 1111 . 100 .... @2op_fp_scalar
68
+ VHSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
69
+ VHSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
70
+}
71
24
{
72
{
25
- # 0b11 subgroup will go here
73
VQADD_S_scalar 1110 1110 0 . .. ... 0 ... 0 1111 . 110 .... @2scalar
26
+ [
74
@@ -XXX,XX +XXX,XX @@ VHSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
27
+ ##################################################################
75
size=%size_28
28
+ # Miscellaneous size=0b11 insns
76
}
29
+ ##################################################################
77
30
+ VEXT 1111 001 0 1 . 11 .... .... imm:4 . q:1 . 0 .... \
78
-VQDMULH_scalar 1110 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
31
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
79
-VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
32
+ ]
80
+{
33
81
+ VMUL_fp_scalar 111 . 1110 0 . 11 ... 1 ... 0 1110 . 110 .... @2op_fp_scalar
34
# Subgroup for size != 0b11
82
+ VQDMULH_scalar 1110 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
35
[
83
+ VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
36
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
84
+}
85
86
# The U bit (28) is don't-care because it does not affect the result
87
VMLA 111- 1110 0 . .. ... 1 ... 0 1110 . 100 .... @2scalar
88
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
37
index XXXXXXX..XXXXXXX 100644
89
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/translate-neon.inc.c
90
--- a/target/arm/mve_helper.c
39
+++ b/target/arm/translate-neon.inc.c
91
+++ b/target/arm/mve_helper.c
40
@@ -XXX,XX +XXX,XX @@ static bool trans_VQDMLSL_2sc(DisasContext *s, arg_2scalar *a)
92
@@ -XXX,XX +XXX,XX @@ DO_VCMLA(vcmla180h, 2, float16, 2, DO_VCMLAH)
41
93
DO_VCMLA(vcmla180s, 4, float32, 2, DO_VCMLAS)
42
return do_2scalar_long(s, a, opfn[a->size], accfn[a->size]);
94
DO_VCMLA(vcmla270h, 2, float16, 3, DO_VCMLAH)
43
}
95
DO_VCMLA(vcmla270s, 4, float32, 3, DO_VCMLAS)
44
+
96
+
45
+static bool trans_VEXT(DisasContext *s, arg_VEXT *a)
97
+#define DO_2OP_FP_SCALAR(OP, ESIZE, TYPE, FN) \
46
+{
98
+ void HELPER(glue(mve_, OP))(CPUARMState *env, \
47
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
99
+ void *vd, void *vn, uint32_t rm) \
48
+ return false;
100
+ { \
101
+ TYPE *d = vd, *n = vn; \
102
+ TYPE r, m = rm; \
103
+ uint16_t mask = mve_element_mask(env); \
104
+ unsigned e; \
105
+ float_status *fpst; \
106
+ float_status scratch_fpst; \
107
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
108
+ if ((mask & MAKE_64BIT_MASK(0, ESIZE)) == 0) { \
109
+ continue; \
110
+ } \
111
+ fpst = (ESIZE == 2) ? &env->vfp.standard_fp_status_f16 : \
112
+ &env->vfp.standard_fp_status; \
113
+ if (!(mask & 1)) { \
114
+ /* We need the result but without updating flags */ \
115
+ scratch_fpst = *fpst; \
116
+ fpst = &scratch_fpst; \
117
+ } \
118
+ r = FN(n[H##ESIZE(e)], m, fpst); \
119
+ mergemask(&d[H##ESIZE(e)], r, mask); \
120
+ } \
121
+ mve_advance_vpt(env); \
49
+ }
122
+ }
50
+
123
+
51
+ /* UNDEF accesses to D16-D31 if they don't exist. */
124
+#define DO_2OP_FP_SCALAR_ALL(OP, FN) \
52
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
125
+ DO_2OP_FP_SCALAR(OP##h, 2, float16, float16_##FN) \
53
+ ((a->vd | a->vn | a->vm) & 0x10)) {
126
+ DO_2OP_FP_SCALAR(OP##s, 4, float32, float32_##FN)
54
+ return false;
127
+
128
+DO_2OP_FP_SCALAR_ALL(vfadd_scalar, add)
129
+DO_2OP_FP_SCALAR_ALL(vfsub_scalar, sub)
130
+DO_2OP_FP_SCALAR_ALL(vfmul_scalar, mul)
131
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
132
index XXXXXXX..XXXXXXX 100644
133
--- a/target/arm/translate-mve.c
134
+++ b/target/arm/translate-mve.c
135
@@ -XXX,XX +XXX,XX @@ static bool trans_VQDMULLT_scalar(DisasContext *s, arg_2scalar *a)
136
return do_2op_scalar(s, a, fns[a->size]);
137
}
138
139
+
140
+#define DO_2OP_FP_SCALAR(INSN, FN) \
141
+ static bool trans_##INSN(DisasContext *s, arg_2scalar *a) \
142
+ { \
143
+ static MVEGenTwoOpScalarFn * const fns[] = { \
144
+ NULL, \
145
+ gen_helper_mve_##FN##h, \
146
+ gen_helper_mve_##FN##s, \
147
+ NULL, \
148
+ }; \
149
+ if (!dc_isar_feature(aa32_mve_fp, s)) { \
150
+ return false; \
151
+ } \
152
+ return do_2op_scalar(s, a, fns[a->size]); \
55
+ }
153
+ }
56
+
154
+
57
+ if ((a->vn | a->vm | a->vd) & a->q) {
155
+DO_2OP_FP_SCALAR(VADD_fp_scalar, vfadd_scalar)
58
+ return false;
156
+DO_2OP_FP_SCALAR(VSUB_fp_scalar, vfsub_scalar)
59
+ }
157
+DO_2OP_FP_SCALAR(VMUL_fp_scalar, vfmul_scalar)
60
+
158
+
61
+ if (a->imm > 7 && !a->q) {
159
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
62
+ return false;
160
MVEGenLongDualAccOpFn *fn)
63
+ }
161
{
64
+
65
+ if (!vfp_access_check(s)) {
66
+ return true;
67
+ }
68
+
69
+ if (!a->q) {
70
+ /* Extract 64 bits from <Vm:Vn> */
71
+ TCGv_i64 left, right, dest;
72
+
73
+ left = tcg_temp_new_i64();
74
+ right = tcg_temp_new_i64();
75
+ dest = tcg_temp_new_i64();
76
+
77
+ neon_load_reg64(right, a->vn);
78
+ neon_load_reg64(left, a->vm);
79
+ tcg_gen_extract2_i64(dest, right, left, a->imm * 8);
80
+ neon_store_reg64(dest, a->vd);
81
+
82
+ tcg_temp_free_i64(left);
83
+ tcg_temp_free_i64(right);
84
+ tcg_temp_free_i64(dest);
85
+ } else {
86
+ /* Extract 128 bits from <Vm+1:Vm:Vn+1:Vn> */
87
+ TCGv_i64 left, middle, right, destleft, destright;
88
+
89
+ left = tcg_temp_new_i64();
90
+ middle = tcg_temp_new_i64();
91
+ right = tcg_temp_new_i64();
92
+ destleft = tcg_temp_new_i64();
93
+ destright = tcg_temp_new_i64();
94
+
95
+ if (a->imm < 8) {
96
+ neon_load_reg64(right, a->vn);
97
+ neon_load_reg64(middle, a->vn + 1);
98
+ tcg_gen_extract2_i64(destright, right, middle, a->imm * 8);
99
+ neon_load_reg64(left, a->vm);
100
+ tcg_gen_extract2_i64(destleft, middle, left, a->imm * 8);
101
+ } else {
102
+ neon_load_reg64(right, a->vn + 1);
103
+ neon_load_reg64(middle, a->vm);
104
+ tcg_gen_extract2_i64(destright, right, middle, (a->imm - 8) * 8);
105
+ neon_load_reg64(left, a->vm + 1);
106
+ tcg_gen_extract2_i64(destleft, middle, left, (a->imm - 8) * 8);
107
+ }
108
+
109
+ neon_store_reg64(destright, a->vd);
110
+ neon_store_reg64(destleft, a->vd + 1);
111
+
112
+ tcg_temp_free_i64(destright);
113
+ tcg_temp_free_i64(destleft);
114
+ tcg_temp_free_i64(right);
115
+ tcg_temp_free_i64(middle);
116
+ tcg_temp_free_i64(left);
117
+ }
118
+ return true;
119
+}
120
diff --git a/target/arm/translate.c b/target/arm/translate.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/target/arm/translate.c
123
+++ b/target/arm/translate.c
124
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
125
int pass;
126
int u;
127
int vec_size;
128
- uint32_t imm;
129
TCGv_i32 tmp, tmp2, tmp3, tmp5;
130
TCGv_ptr ptr1;
131
- TCGv_i64 tmp64;
132
133
if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
134
return 1;
135
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
136
return 1;
137
} else { /* size == 3 */
138
if (!u) {
139
- /* Extract. */
140
- imm = (insn >> 8) & 0xf;
141
-
142
- if (imm > 7 && !q)
143
- return 1;
144
-
145
- if (q && ((rd | rn | rm) & 1)) {
146
- return 1;
147
- }
148
-
149
- if (imm == 0) {
150
- neon_load_reg64(cpu_V0, rn);
151
- if (q) {
152
- neon_load_reg64(cpu_V1, rn + 1);
153
- }
154
- } else if (imm == 8) {
155
- neon_load_reg64(cpu_V0, rn + 1);
156
- if (q) {
157
- neon_load_reg64(cpu_V1, rm);
158
- }
159
- } else if (q) {
160
- tmp64 = tcg_temp_new_i64();
161
- if (imm < 8) {
162
- neon_load_reg64(cpu_V0, rn);
163
- neon_load_reg64(tmp64, rn + 1);
164
- } else {
165
- neon_load_reg64(cpu_V0, rn + 1);
166
- neon_load_reg64(tmp64, rm);
167
- }
168
- tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
169
- tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
170
- tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
171
- if (imm < 8) {
172
- neon_load_reg64(cpu_V1, rm);
173
- } else {
174
- neon_load_reg64(cpu_V1, rm + 1);
175
- imm -= 8;
176
- }
177
- tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
178
- tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
179
- tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
180
- tcg_temp_free_i64(tmp64);
181
- } else {
182
- /* BUGFIX */
183
- neon_load_reg64(cpu_V0, rn);
184
- tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
185
- neon_load_reg64(cpu_V1, rm);
186
- tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
187
- tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
188
- }
189
- neon_store_reg64(cpu_V0, rd);
190
- if (q) {
191
- neon_store_reg64(cpu_V1, rd + 1);
192
- }
193
+ /* Extract: handled by decodetree */
194
+ return 1;
195
} else if ((insn & (1 << 11)) == 0) {
196
/* Two register misc. */
197
op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
198
--
162
--
199
2.20.1
163
2.20.1
200
164
201
165
diff view generated by jsdifflib
1
Convert the VMLA, VMLS and VMUL insns in the Neon "2 registers and a
1
Implement the MVE fp-with-scalar VFMA and VFMAS insns.
2
scalar" group to decodetree. These are 32x32->32 operations where
3
one of the inputs is the scalar, followed by a possible accumulate
4
operation of the 32-bit result.
5
6
The refactoring removes some of the oddities of the old decoder:
7
* operands to the operation and accumulation were often
8
reversed (taking advantage of the fact that most of these ops
9
are commutative); the new code follows the pseudocode order
10
* the Q bit in the insn was in a local variable 'u'; in the
11
new code it is decoded into a->q
12
2
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
---
5
---
16
target/arm/neon-dp.decode | 15 ++++
6
target/arm/helper-mve.h | 6 ++++++
17
target/arm/translate-neon.inc.c | 133 ++++++++++++++++++++++++++++++++
7
target/arm/mve.decode | 14 +++++++++++---
18
target/arm/translate.c | 77 ++----------------
8
target/arm/mve_helper.c | 37 +++++++++++++++++++++++++++++++++++++
19
3 files changed, 154 insertions(+), 71 deletions(-)
9
target/arm/translate-mve.c | 2 ++
10
4 files changed, 56 insertions(+), 3 deletions(-)
20
11
21
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
12
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
22
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/neon-dp.decode
14
--- a/target/arm/helper-mve.h
24
+++ b/target/arm/neon-dp.decode
15
+++ b/target/arm/helper-mve.h
25
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
16
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vfsub_scalars, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
26
VQDMULL_3d 1111 001 0 1 . .. .... .... 1101 . 0 . 0 .... @3diff
17
27
18
DEF_HELPER_FLAGS_4(mve_vfmul_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
28
VMULL_P_3d 1111 001 0 1 . .. .... .... 1110 . 0 . 0 .... @3diff
19
DEF_HELPER_FLAGS_4(mve_vfmul_scalars, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
29
+
20
+
30
+ ##################################################################
21
+DEF_HELPER_FLAGS_4(mve_vfma_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
+ # 2-regs-plus-scalar grouping:
22
+DEF_HELPER_FLAGS_4(mve_vfma_scalars, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
32
+ # 1111 001 Q 1 D sz!=11 Vn:4 Vd:4 opc:4 N 1 M 0 Vm:4
33
+ ##################################################################
34
+ &2scalar vm vn vd size q
35
+
23
+
36
+ @2scalar .... ... q:1 . . size:2 .... .... .... . . . . .... \
24
+DEF_HELPER_FLAGS_4(mve_vfmas_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
37
+ &2scalar vm=%vm_dp vn=%vn_dp vd=%vd_dp
25
+DEF_HELPER_FLAGS_4(mve_vfmas_scalars, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
38
+
26
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
39
+ VMLA_2sc 1111 001 . 1 . .. .... .... 0000 . 1 . 0 .... @2scalar
27
index XXXXXXX..XXXXXXX 100644
40
+
28
--- a/target/arm/mve.decode
41
+ VMLS_2sc 1111 001 . 1 . .. .... .... 0100 . 1 . 0 .... @2scalar
29
+++ b/target/arm/mve.decode
42
+
30
@@ -XXX,XX +XXX,XX @@ VSUB_scalar 1110 1110 0 . .. ... 1 ... 1 1111 . 100 .... @2scalar
43
+ VMUL_2sc 1111 001 . 1 . .. .... .... 1000 . 1 . 0 .... @2scalar
31
VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
44
]
45
}
32
}
46
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
33
47
index XXXXXXX..XXXXXXX 100644
34
-# The U bit (28) is don't-care because it does not affect the result
48
--- a/target/arm/translate-neon.inc.c
35
-VMLA 111- 1110 0 . .. ... 1 ... 0 1110 . 100 .... @2scalar
49
+++ b/target/arm/translate-neon.inc.c
36
-VMLAS 111- 1110 0 . .. ... 1 ... 1 1110 . 100 .... @2scalar
50
@@ -XXX,XX +XXX,XX @@ static bool trans_VMULL_P_3d(DisasContext *s, arg_3diff *a)
51
16, 16, 0, fn_gvec);
52
return true;
53
}
54
+
55
+static void gen_neon_dup_low16(TCGv_i32 var)
56
+{
37
+{
57
+ TCGv_i32 tmp = tcg_temp_new_i32();
38
+ VFMA_scalar 111 . 1110 0 . 11 ... 1 ... 0 1110 . 100 .... @2op_fp_scalar
58
+ tcg_gen_ext16u_i32(var, var);
39
+ # The U bit (28) is don't-care because it does not affect the result
59
+ tcg_gen_shli_i32(tmp, var, 16);
40
+ VMLA 111 - 1110 0 . .. ... 1 ... 0 1110 . 100 .... @2scalar
60
+ tcg_gen_or_i32(var, var, tmp);
61
+ tcg_temp_free_i32(tmp);
62
+}
41
+}
63
+
42
+
64
+static void gen_neon_dup_high16(TCGv_i32 var)
65
+{
43
+{
66
+ TCGv_i32 tmp = tcg_temp_new_i32();
44
+ VFMAS_scalar 111 . 1110 0 . 11 ... 1 ... 1 1110 . 100 .... @2op_fp_scalar
67
+ tcg_gen_andi_i32(var, var, 0xffff0000);
45
+ # The U bit (28) is don't-care because it does not affect the result
68
+ tcg_gen_shri_i32(tmp, var, 16);
46
+ VMLAS 111 - 1110 0 . .. ... 1 ... 1 1110 . 100 .... @2scalar
69
+ tcg_gen_or_i32(var, var, tmp);
70
+ tcg_temp_free_i32(tmp);
71
+}
47
+}
48
49
VQRDMLAH 1110 1110 0 . .. ... 0 ... 0 1110 . 100 .... @2scalar
50
VQRDMLASH 1110 1110 0 . .. ... 0 ... 1 1110 . 100 .... @2scalar
51
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/mve_helper.c
54
+++ b/target/arm/mve_helper.c
55
@@ -XXX,XX +XXX,XX @@ DO_VCMLA(vcmla270s, 4, float32, 3, DO_VCMLAS)
56
DO_2OP_FP_SCALAR_ALL(vfadd_scalar, add)
57
DO_2OP_FP_SCALAR_ALL(vfsub_scalar, sub)
58
DO_2OP_FP_SCALAR_ALL(vfmul_scalar, mul)
72
+
59
+
73
+static inline TCGv_i32 neon_get_scalar(int size, int reg)
60
+#define DO_2OP_FP_ACC_SCALAR(OP, ESIZE, TYPE, FN) \
74
+{
61
+ void HELPER(glue(mve_, OP))(CPUARMState *env, \
75
+ TCGv_i32 tmp;
62
+ void *vd, void *vn, uint32_t rm) \
76
+ if (size == 1) {
63
+ { \
77
+ tmp = neon_load_reg(reg & 7, reg >> 4);
64
+ TYPE *d = vd, *n = vn; \
78
+ if (reg & 8) {
65
+ TYPE r, m = rm; \
79
+ gen_neon_dup_high16(tmp);
66
+ uint16_t mask = mve_element_mask(env); \
80
+ } else {
67
+ unsigned e; \
81
+ gen_neon_dup_low16(tmp);
68
+ float_status *fpst; \
82
+ }
69
+ float_status scratch_fpst; \
83
+ } else {
70
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
84
+ tmp = neon_load_reg(reg & 15, reg >> 4);
71
+ if ((mask & MAKE_64BIT_MASK(0, ESIZE)) == 0) { \
85
+ }
72
+ continue; \
86
+ return tmp;
73
+ } \
87
+}
74
+ fpst = (ESIZE == 2) ? &env->vfp.standard_fp_status_f16 : \
88
+
75
+ &env->vfp.standard_fp_status; \
89
+static bool do_2scalar(DisasContext *s, arg_2scalar *a,
76
+ if (!(mask & 1)) { \
90
+ NeonGenTwoOpFn *opfn, NeonGenTwoOpFn *accfn)
77
+ /* We need the result but without updating flags */ \
91
+{
78
+ scratch_fpst = *fpst; \
92
+ /*
79
+ fpst = &scratch_fpst; \
93
+ * Two registers and a scalar: perform an operation between
80
+ } \
94
+ * the input elements and the scalar, and then possibly
81
+ r = FN(n[H##ESIZE(e)], m, d[H##ESIZE(e)], 0, fpst); \
95
+ * perform an accumulation operation of that result into the
82
+ mergemask(&d[H##ESIZE(e)], r, mask); \
96
+ * destination.
83
+ } \
97
+ */
84
+ mve_advance_vpt(env); \
98
+ TCGv_i32 scalar;
99
+ int pass;
100
+
101
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
102
+ return false;
103
+ }
85
+ }
104
+
86
+
105
+ /* UNDEF accesses to D16-D31 if they don't exist. */
87
+/* VFMAS is vector * vector + scalar, so swap op2 and op3 */
106
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
88
+#define DO_VFMAS_SCALARH(N, M, D, F, S) float16_muladd(N, D, M, F, S)
107
+ ((a->vd | a->vn | a->vm) & 0x10)) {
89
+#define DO_VFMAS_SCALARS(N, M, D, F, S) float32_muladd(N, D, M, F, S)
108
+ return false;
109
+ }
110
+
90
+
111
+ if (!opfn) {
91
+/* VFMA is vector * scalar + vector */
112
+ /* Bad size (including size == 3, which is a different insn group) */
92
+DO_2OP_FP_ACC_SCALAR(vfma_scalarh, 2, float16, float16_muladd)
113
+ return false;
93
+DO_2OP_FP_ACC_SCALAR(vfma_scalars, 4, float32, float32_muladd)
114
+ }
94
+DO_2OP_FP_ACC_SCALAR(vfmas_scalarh, 2, float16, DO_VFMAS_SCALARH)
115
+
95
+DO_2OP_FP_ACC_SCALAR(vfmas_scalars, 4, float32, DO_VFMAS_SCALARS)
116
+ if (a->q && ((a->vd | a->vn) & 1)) {
96
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
117
+ return false;
118
+ }
119
+
120
+ if (!vfp_access_check(s)) {
121
+ return true;
122
+ }
123
+
124
+ scalar = neon_get_scalar(a->size, a->vm);
125
+
126
+ for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
127
+ TCGv_i32 tmp = neon_load_reg(a->vn, pass);
128
+ opfn(tmp, tmp, scalar);
129
+ if (accfn) {
130
+ TCGv_i32 rd = neon_load_reg(a->vd, pass);
131
+ accfn(tmp, rd, tmp);
132
+ tcg_temp_free_i32(rd);
133
+ }
134
+ neon_store_reg(a->vd, pass, tmp);
135
+ }
136
+ tcg_temp_free_i32(scalar);
137
+ return true;
138
+}
139
+
140
+static bool trans_VMUL_2sc(DisasContext *s, arg_2scalar *a)
141
+{
142
+ static NeonGenTwoOpFn * const opfn[] = {
143
+ NULL,
144
+ gen_helper_neon_mul_u16,
145
+ tcg_gen_mul_i32,
146
+ NULL,
147
+ };
148
+
149
+ return do_2scalar(s, a, opfn[a->size], NULL);
150
+}
151
+
152
+static bool trans_VMLA_2sc(DisasContext *s, arg_2scalar *a)
153
+{
154
+ static NeonGenTwoOpFn * const opfn[] = {
155
+ NULL,
156
+ gen_helper_neon_mul_u16,
157
+ tcg_gen_mul_i32,
158
+ NULL,
159
+ };
160
+ static NeonGenTwoOpFn * const accfn[] = {
161
+ NULL,
162
+ gen_helper_neon_add_u16,
163
+ tcg_gen_add_i32,
164
+ NULL,
165
+ };
166
+
167
+ return do_2scalar(s, a, opfn[a->size], accfn[a->size]);
168
+}
169
+
170
+static bool trans_VMLS_2sc(DisasContext *s, arg_2scalar *a)
171
+{
172
+ static NeonGenTwoOpFn * const opfn[] = {
173
+ NULL,
174
+ gen_helper_neon_mul_u16,
175
+ tcg_gen_mul_i32,
176
+ NULL,
177
+ };
178
+ static NeonGenTwoOpFn * const accfn[] = {
179
+ NULL,
180
+ gen_helper_neon_sub_u16,
181
+ tcg_gen_sub_i32,
182
+ NULL,
183
+ };
184
+
185
+ return do_2scalar(s, a, opfn[a->size], accfn[a->size]);
186
+}
187
diff --git a/target/arm/translate.c b/target/arm/translate.c
188
index XXXXXXX..XXXXXXX 100644
97
index XXXXXXX..XXXXXXX 100644
189
--- a/target/arm/translate.c
98
--- a/target/arm/translate-mve.c
190
+++ b/target/arm/translate.c
99
+++ b/target/arm/translate-mve.c
191
@@ -XXX,XX +XXX,XX @@ static int disas_dsp_insn(DisasContext *s, uint32_t insn)
100
@@ -XXX,XX +XXX,XX @@ static bool trans_VQDMULLT_scalar(DisasContext *s, arg_2scalar *a)
192
#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
101
DO_2OP_FP_SCALAR(VADD_fp_scalar, vfadd_scalar)
193
#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
102
DO_2OP_FP_SCALAR(VSUB_fp_scalar, vfsub_scalar)
194
103
DO_2OP_FP_SCALAR(VMUL_fp_scalar, vfmul_scalar)
195
-static void gen_neon_dup_low16(TCGv_i32 var)
104
+DO_2OP_FP_SCALAR(VFMA_scalar, vfma_scalar)
196
-{
105
+DO_2OP_FP_SCALAR(VFMAS_scalar, vfmas_scalar)
197
- TCGv_i32 tmp = tcg_temp_new_i32();
106
198
- tcg_gen_ext16u_i32(var, var);
107
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
199
- tcg_gen_shli_i32(tmp, var, 16);
108
MVEGenLongDualAccOpFn *fn)
200
- tcg_gen_or_i32(var, var, tmp);
201
- tcg_temp_free_i32(tmp);
202
-}
203
-
204
-static void gen_neon_dup_high16(TCGv_i32 var)
205
-{
206
- TCGv_i32 tmp = tcg_temp_new_i32();
207
- tcg_gen_andi_i32(var, var, 0xffff0000);
208
- tcg_gen_shri_i32(tmp, var, 16);
209
- tcg_gen_or_i32(var, var, tmp);
210
- tcg_temp_free_i32(tmp);
211
-}
212
-
213
static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
214
{
215
#ifndef CONFIG_USER_ONLY
216
@@ -XXX,XX +XXX,XX @@ static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
217
218
#define CPU_V001 cpu_V0, cpu_V0, cpu_V1
219
220
-static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1)
221
-{
222
- switch (size) {
223
- case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
224
- case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
225
- case 2: tcg_gen_add_i32(t0, t0, t1); break;
226
- default: abort();
227
- }
228
-}
229
-
230
-static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
231
-{
232
- switch (size) {
233
- case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
234
- case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
235
- case 2: tcg_gen_sub_i32(t0, t1, t0); break;
236
- default: return;
237
- }
238
-}
239
-
240
static TCGv_i32 neon_load_scratch(int scratch)
241
{
242
TCGv_i32 tmp = tcg_temp_new_i32();
243
@@ -XXX,XX +XXX,XX @@ static void neon_store_scratch(int scratch, TCGv_i32 var)
244
tcg_temp_free_i32(var);
245
}
246
247
-static inline TCGv_i32 neon_get_scalar(int size, int reg)
248
-{
249
- TCGv_i32 tmp;
250
- if (size == 1) {
251
- tmp = neon_load_reg(reg & 7, reg >> 4);
252
- if (reg & 8) {
253
- gen_neon_dup_high16(tmp);
254
- } else {
255
- gen_neon_dup_low16(tmp);
256
- }
257
- } else {
258
- tmp = neon_load_reg(reg & 15, reg >> 4);
259
- }
260
- return tmp;
261
-}
262
-
263
static int gen_neon_unzip(int rd, int rm, int size, int q)
264
{
265
TCGv_ptr pd, pm;
266
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
267
return 1;
268
}
269
switch (op) {
270
+ case 0: /* Integer VMLA scalar */
271
+ case 4: /* Integer VMLS scalar */
272
+ case 8: /* Integer VMUL scalar */
273
+ return 1; /* handled by decodetree */
274
+
275
case 1: /* Float VMLA scalar */
276
case 5: /* Floating point VMLS scalar */
277
case 9: /* Floating point VMUL scalar */
278
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
279
return 1;
280
}
281
/* fall through */
282
- case 0: /* Integer VMLA scalar */
283
- case 4: /* Integer VMLS scalar */
284
- case 8: /* Integer VMUL scalar */
285
case 12: /* VQDMULH scalar */
286
case 13: /* VQRDMULH scalar */
287
if (u && ((rd | rn) & 1)) {
288
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
289
} else {
290
gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
291
}
292
- } else if (op & 1) {
293
+ } else {
294
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
295
gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
296
tcg_temp_free_ptr(fpstatus);
297
- } else {
298
- switch (size) {
299
- case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
300
- case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
301
- case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
302
- default: abort();
303
- }
304
}
305
tcg_temp_free_i32(tmp2);
306
if (op < 8) {
307
/* Accumulate. */
308
tmp2 = neon_load_reg(rd, pass);
309
switch (op) {
310
- case 0:
311
- gen_neon_add(size, tmp, tmp2);
312
- break;
313
case 1:
314
{
315
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
316
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
317
tcg_temp_free_ptr(fpstatus);
318
break;
319
}
320
- case 4:
321
- gen_neon_rsb(size, tmp, tmp2);
322
- break;
323
case 5:
324
{
325
TCGv_ptr fpstatus = get_fpstatus_ptr(1);
326
--
109
--
327
2.20.1
110
2.20.1
328
111
329
112
diff view generated by jsdifflib
1
Mark the arrays of function pointers in trans_VSHLL_S_2sh() and
1
In commit a777d6033447a we added an assertion to parts_silence_nan() that
2
trans_VSHLL_U_2sh() as both 'static' and 'const'.
2
prohibits calling float*_silence_nan() when in default-NaN mode.
3
This ties together a property of the output ("do we generate a default
4
NaN when the result is a NaN?") with an operation on an input ("silence
5
this input NaN").
6
7
It's true that most of the time when in default-NaN mode you won't
8
need to silence an input NaN, because you can just produce the
9
default NaN as the result instead. But some functions like
10
float*_maxnum() are defined to be able to work with quiet NaNs, so
11
silencing an input SNaN is still reasonable. In particular, the
12
upcoming implementation of MVE VMAXNMV would fall over this assertion
13
if we didn't delete it.
14
15
Delete the assertion.
3
16
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
---
19
---
7
target/arm/translate-neon.inc.c | 4 ++--
20
fpu/softfloat-specialize.c.inc | 1 -
8
1 file changed, 2 insertions(+), 2 deletions(-)
21
1 file changed, 1 deletion(-)
9
22
10
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
23
diff --git a/fpu/softfloat-specialize.c.inc b/fpu/softfloat-specialize.c.inc
11
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
12
--- a/target/arm/translate-neon.inc.c
25
--- a/fpu/softfloat-specialize.c.inc
13
+++ b/target/arm/translate-neon.inc.c
26
+++ b/fpu/softfloat-specialize.c.inc
14
@@ -XXX,XX +XXX,XX @@ static bool do_vshll_2sh(DisasContext *s, arg_2reg_shift *a,
27
@@ -XXX,XX +XXX,XX @@ static void parts128_default_nan(FloatParts128 *p, float_status *status)
15
28
static uint64_t parts_silence_nan_frac(uint64_t frac, float_status *status)
16
static bool trans_VSHLL_S_2sh(DisasContext *s, arg_2reg_shift *a)
17
{
29
{
18
- NeonGenWidenFn *widenfn[] = {
30
g_assert(!no_signaling_nans(status));
19
+ static NeonGenWidenFn * const widenfn[] = {
31
- g_assert(!status->default_nan_mode);
20
gen_helper_neon_widen_s8,
32
21
gen_helper_neon_widen_s16,
33
/* The only snan_bit_is_one target without default_nan_mode is HPPA. */
22
tcg_gen_ext_i32_i64,
34
if (snan_bit_is_one(status)) {
23
@@ -XXX,XX +XXX,XX @@ static bool trans_VSHLL_S_2sh(DisasContext *s, arg_2reg_shift *a)
24
25
static bool trans_VSHLL_U_2sh(DisasContext *s, arg_2reg_shift *a)
26
{
27
- NeonGenWidenFn *widenfn[] = {
28
+ static NeonGenWidenFn * const widenfn[] = {
29
gen_helper_neon_widen_u8,
30
gen_helper_neon_widen_u16,
31
tcg_gen_extu_i32_i64,
32
--
35
--
33
2.20.1
36
2.20.1
34
37
35
38
diff view generated by jsdifflib
1
Convert the Neon VTBL, VTBX instructions to decodetree. The actual
1
Implement the MVE VMAXNMV, VMINNMV, VMAXNMAV, VMINNMAV insns. These
2
implementation of the insn is copied across to the new trans function
2
calculate the maximum or minimum of floating point elements across a
3
unchanged except for renaming 'tmp5' to 'tmp4'.
3
vector, starting with a value in a general purpose register and
4
returning the result there.
5
6
The pseudocode silences a possible SNaN in the accumulating result
7
on every iteration (by calling FPConvertNaN), but we do it only
8
on the input ra, because if none of the inputs to float*_maxnum
9
or float*_minnum are SNaNs then the result can't be an SNaN.
10
11
Note that we can't use the float*_maxnuma() etc functions we defined
12
earlier for VMAXNMA and VMINNMA, because we mustn't take the absolute
13
value of the starting general-purpose register value, which could be
14
negative.
4
15
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
---
18
---
8
target/arm/neon-dp.decode | 3 ++
19
target/arm/helper-mve.h | 12 +++++++++++
9
target/arm/translate-neon.inc.c | 56 +++++++++++++++++++++++++++++++++
20
target/arm/mve.decode | 32 +++++++++++++++++++++------
10
target/arm/translate.c | 41 +++---------------------
21
target/arm/mve_helper.c | 44 ++++++++++++++++++++++++++++++++++++++
11
3 files changed, 63 insertions(+), 37 deletions(-)
22
target/arm/translate-mve.c | 20 +++++++++++++++++
23
4 files changed, 102 insertions(+), 6 deletions(-)
12
24
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
25
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
27
--- a/target/arm/helper-mve.h
16
+++ b/target/arm/neon-dp.decode
28
+++ b/target/arm/helper-mve.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 @@ DEF_HELPER_FLAGS_3(mve_vminavb, TCG_CALL_NO_WG, i32, env, ptr, i32)
18
##################################################################
30
DEF_HELPER_FLAGS_3(mve_vminavh, TCG_CALL_NO_WG, i32, env, ptr, i32)
19
VEXT 1111 001 0 1 . 11 .... .... imm:4 . q:1 . 0 .... \
31
DEF_HELPER_FLAGS_3(mve_vminavw, TCG_CALL_NO_WG, i32, env, ptr, i32)
20
vm=%vm_dp vn=%vn_dp vd=%vd_dp
32
33
+DEF_HELPER_FLAGS_3(mve_vmaxnmvh, TCG_CALL_NO_WG, i32, env, ptr, i32)
34
+DEF_HELPER_FLAGS_3(mve_vmaxnmvs, TCG_CALL_NO_WG, i32, env, ptr, i32)
21
+
35
+
22
+ VTBL 1111 001 1 1 . 11 .... .... 10 len:2 . op:1 . 0 .... \
36
+DEF_HELPER_FLAGS_3(mve_vminnmvh, TCG_CALL_NO_WG, i32, env, ptr, i32)
23
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
37
+DEF_HELPER_FLAGS_3(mve_vminnmvs, TCG_CALL_NO_WG, i32, env, ptr, i32)
24
]
38
+
25
39
+DEF_HELPER_FLAGS_3(mve_vmaxnmavh, TCG_CALL_NO_WG, i32, env, ptr, i32)
26
# Subgroup for size != 0b11
40
+DEF_HELPER_FLAGS_3(mve_vmaxnmavs, TCG_CALL_NO_WG, i32, env, ptr, i32)
27
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
41
+
42
+DEF_HELPER_FLAGS_3(mve_vminnmavh, TCG_CALL_NO_WG, i32, env, ptr, i32)
43
+DEF_HELPER_FLAGS_3(mve_vminnmavs, TCG_CALL_NO_WG, i32, env, ptr, i32)
44
+
45
DEF_HELPER_FLAGS_3(mve_vaddlv_s, TCG_CALL_NO_WG, i64, env, ptr, i64)
46
DEF_HELPER_FLAGS_3(mve_vaddlv_u, TCG_CALL_NO_WG, i64, env, ptr, i64)
47
48
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
28
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/translate-neon.inc.c
50
--- a/target/arm/mve.decode
30
+++ b/target/arm/translate-neon.inc.c
51
+++ b/target/arm/mve.decode
31
@@ -XXX,XX +XXX,XX @@ static bool trans_VEXT(DisasContext *s, arg_VEXT *a)
52
@@ -XXX,XX +XXX,XX @@
32
}
53
@vmaxnma .... .... .... .... .... .... .... .... &2op \
33
return true;
54
qd=%qd qn=%qd qm=%qm
55
56
+# Here also we don't decode the bit 28 size in the format to avoid
57
+# awkward nested overlap groups
58
+@vmaxnmv .... .... .... .... rda:4 .... .... .... &vmaxv qm=%qm
59
+
60
@2op_fp_scalar .... .... .... .... .... .... .... rm:4 &2scalar \
61
qd=%qd qn=%qn size=%2op_fp_scalar_size
62
63
@@ -XXX,XX +XXX,XX @@ VMLADAV_S 1110 1110 1111 ... 0 ... . 1111 . 0 . 0 ... 1 @vmladav_nosz
64
VMLADAV_U 1111 1110 1111 ... 0 ... . 1111 . 0 . 0 ... 1 @vmladav_nosz
65
66
{
67
- VMAXV_S 1110 1110 1110 .. 10 .... 1111 0 0 . 0 ... 0 @vmaxv
68
- VMINV_S 1110 1110 1110 .. 10 .... 1111 1 0 . 0 ... 0 @vmaxv
69
- VMAXAV 1110 1110 1110 .. 00 .... 1111 0 0 . 0 ... 0 @vmaxv
70
- VMINAV 1110 1110 1110 .. 00 .... 1111 1 0 . 0 ... 0 @vmaxv
71
+ [
72
+ VMAXNMAV 1110 1110 1110 11 00 .... 1111 0 0 . 0 ... 0 @vmaxnmv size=2
73
+ VMINNMAV 1110 1110 1110 11 00 .... 1111 1 0 . 0 ... 0 @vmaxnmv size=2
74
+ VMAXNMV 1110 1110 1110 11 10 .... 1111 0 0 . 0 ... 0 @vmaxnmv size=2
75
+ VMINNMV 1110 1110 1110 11 10 .... 1111 1 0 . 0 ... 0 @vmaxnmv size=2
76
+ ]
77
+ [
78
+ VMAXV_S 1110 1110 1110 .. 10 .... 1111 0 0 . 0 ... 0 @vmaxv
79
+ VMINV_S 1110 1110 1110 .. 10 .... 1111 1 0 . 0 ... 0 @vmaxv
80
+ VMAXAV 1110 1110 1110 .. 00 .... 1111 0 0 . 0 ... 0 @vmaxv
81
+ VMINAV 1110 1110 1110 .. 00 .... 1111 1 0 . 0 ... 0 @vmaxv
82
+ ]
83
VMLADAV_S 1110 1110 1111 ... 0 ... . 1111 . 0 . 0 ... 0 @vmladav_nosz
84
VRMLALDAVH_S 1110 1110 1 ... ... 0 ... . 1111 . 0 . 0 ... 0 @vmlaldav_nosz
34
}
85
}
86
87
{
88
- VMAXV_U 1111 1110 1110 .. 10 .... 1111 0 0 . 0 ... 0 @vmaxv
89
- VMINV_U 1111 1110 1110 .. 10 .... 1111 1 0 . 0 ... 0 @vmaxv
90
+ [
91
+ VMAXNMAV 1111 1110 1110 11 00 .... 1111 0 0 . 0 ... 0 @vmaxnmv size=1
92
+ VMINNMAV 1111 1110 1110 11 00 .... 1111 1 0 . 0 ... 0 @vmaxnmv size=1
93
+ VMAXNMV 1111 1110 1110 11 10 .... 1111 0 0 . 0 ... 0 @vmaxnmv size=1
94
+ VMINNMV 1111 1110 1110 11 10 .... 1111 1 0 . 0 ... 0 @vmaxnmv size=1
95
+ ]
96
+ [
97
+ VMAXV_U 1111 1110 1110 .. 10 .... 1111 0 0 . 0 ... 0 @vmaxv
98
+ VMINV_U 1111 1110 1110 .. 10 .... 1111 1 0 . 0 ... 0 @vmaxv
99
+ ]
100
VMLADAV_U 1111 1110 1111 ... 0 ... . 1111 . 0 . 0 ... 0 @vmladav_nosz
101
VRMLALDAVH_U 1111 1110 1 ... ... 0 ... . 1111 . 0 . 0 ... 0 @vmlaldav_nosz
102
}
103
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
104
index XXXXXXX..XXXXXXX 100644
105
--- a/target/arm/mve_helper.c
106
+++ b/target/arm/mve_helper.c
107
@@ -XXX,XX +XXX,XX @@ DO_2OP_FP_ACC_SCALAR(vfma_scalarh, 2, float16, float16_muladd)
108
DO_2OP_FP_ACC_SCALAR(vfma_scalars, 4, float32, float32_muladd)
109
DO_2OP_FP_ACC_SCALAR(vfmas_scalarh, 2, float16, DO_VFMAS_SCALARH)
110
DO_2OP_FP_ACC_SCALAR(vfmas_scalars, 4, float32, DO_VFMAS_SCALARS)
35
+
111
+
36
+static bool trans_VTBL(DisasContext *s, arg_VTBL *a)
112
+/* Floating point max/min across vector. */
37
+{
113
+#define DO_FP_VMAXMINV(OP, ESIZE, TYPE, ABS, FN) \
38
+ int n;
114
+ uint32_t HELPER(glue(mve_, OP))(CPUARMState *env, void *vm, \
39
+ TCGv_i32 tmp, tmp2, tmp3, tmp4;
115
+ uint32_t ra_in) \
40
+ TCGv_ptr ptr1;
116
+ { \
117
+ uint16_t mask = mve_element_mask(env); \
118
+ unsigned e; \
119
+ TYPE *m = vm; \
120
+ TYPE ra = (TYPE)ra_in; \
121
+ float_status *fpst = (ESIZE == 2) ? \
122
+ &env->vfp.standard_fp_status_f16 : \
123
+ &env->vfp.standard_fp_status; \
124
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
125
+ if (mask & 1) { \
126
+ TYPE v = m[H##ESIZE(e)]; \
127
+ if (TYPE##_is_signaling_nan(ra, fpst)) { \
128
+ ra = TYPE##_silence_nan(ra, fpst); \
129
+ float_raise(float_flag_invalid, fpst); \
130
+ } \
131
+ if (TYPE##_is_signaling_nan(v, fpst)) { \
132
+ v = TYPE##_silence_nan(v, fpst); \
133
+ float_raise(float_flag_invalid, fpst); \
134
+ } \
135
+ if (ABS) { \
136
+ v = TYPE##_abs(v); \
137
+ } \
138
+ ra = FN(ra, v, fpst); \
139
+ } \
140
+ } \
141
+ mve_advance_vpt(env); \
142
+ return ra; \
143
+ } \
41
+
144
+
42
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
145
+#define NOP(X) (X)
43
+ return false;
146
+
147
+DO_FP_VMAXMINV(vmaxnmvh, 2, float16, false, float16_maxnum)
148
+DO_FP_VMAXMINV(vmaxnmvs, 4, float32, false, float32_maxnum)
149
+DO_FP_VMAXMINV(vminnmvh, 2, float16, false, float16_minnum)
150
+DO_FP_VMAXMINV(vminnmvs, 4, float32, false, float32_minnum)
151
+DO_FP_VMAXMINV(vmaxnmavh, 2, float16, true, float16_maxnum)
152
+DO_FP_VMAXMINV(vmaxnmavs, 4, float32, true, float32_maxnum)
153
+DO_FP_VMAXMINV(vminnmavh, 2, float16, true, float16_minnum)
154
+DO_FP_VMAXMINV(vminnmavs, 4, float32, true, float32_minnum)
155
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
156
index XXXXXXX..XXXXXXX 100644
157
--- a/target/arm/translate-mve.c
158
+++ b/target/arm/translate-mve.c
159
@@ -XXX,XX +XXX,XX @@ DO_VMAXV(VMINV_S, vminvs)
160
DO_VMAXV(VMINV_U, vminvu)
161
DO_VMAXV(VMINAV, vminav)
162
163
+#define DO_VMAXV_FP(INSN, FN) \
164
+ static bool trans_##INSN(DisasContext *s, arg_vmaxv *a) \
165
+ { \
166
+ static MVEGenVADDVFn * const fns[] = { \
167
+ NULL, \
168
+ gen_helper_mve_##FN##h, \
169
+ gen_helper_mve_##FN##s, \
170
+ NULL, \
171
+ }; \
172
+ if (!dc_isar_feature(aa32_mve_fp, s)) { \
173
+ return false; \
174
+ } \
175
+ return do_vmaxv(s, a, fns[a->size]); \
44
+ }
176
+ }
45
+
177
+
46
+ /* UNDEF accesses to D16-D31 if they don't exist. */
178
+DO_VMAXV_FP(VMAXNMV, vmaxnmv)
47
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
179
+DO_VMAXV_FP(VMINNMV, vminnmv)
48
+ ((a->vd | a->vn | a->vm) & 0x10)) {
180
+DO_VMAXV_FP(VMAXNMAV, vmaxnmav)
49
+ return false;
181
+DO_VMAXV_FP(VMINNMAV, vminnmav)
50
+ }
51
+
182
+
52
+ if (!vfp_access_check(s)) {
183
static bool do_vabav(DisasContext *s, arg_vabav *a, MVEGenVABAVFn *fn)
53
+ return true;
54
+ }
55
+
56
+ n = a->len + 1;
57
+ if ((a->vn + n) > 32) {
58
+ /*
59
+ * This is UNPREDICTABLE; we choose to UNDEF to avoid the
60
+ * helper function running off the end of the register file.
61
+ */
62
+ return false;
63
+ }
64
+ n <<= 3;
65
+ if (a->op) {
66
+ tmp = neon_load_reg(a->vd, 0);
67
+ } else {
68
+ tmp = tcg_temp_new_i32();
69
+ tcg_gen_movi_i32(tmp, 0);
70
+ }
71
+ tmp2 = neon_load_reg(a->vm, 0);
72
+ ptr1 = vfp_reg_ptr(true, a->vn);
73
+ tmp4 = tcg_const_i32(n);
74
+ gen_helper_neon_tbl(tmp2, tmp2, tmp, ptr1, tmp4);
75
+ tcg_temp_free_i32(tmp);
76
+ if (a->op) {
77
+ tmp = neon_load_reg(a->vd, 1);
78
+ } else {
79
+ tmp = tcg_temp_new_i32();
80
+ tcg_gen_movi_i32(tmp, 0);
81
+ }
82
+ tmp3 = neon_load_reg(a->vm, 1);
83
+ gen_helper_neon_tbl(tmp3, tmp3, tmp, ptr1, tmp4);
84
+ tcg_temp_free_i32(tmp4);
85
+ tcg_temp_free_ptr(ptr1);
86
+ neon_store_reg(a->vd, 0, tmp2);
87
+ neon_store_reg(a->vd, 1, tmp3);
88
+ tcg_temp_free_i32(tmp);
89
+ return true;
90
+}
91
diff --git a/target/arm/translate.c b/target/arm/translate.c
92
index XXXXXXX..XXXXXXX 100644
93
--- a/target/arm/translate.c
94
+++ b/target/arm/translate.c
95
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
96
{
184
{
97
int op;
185
/* Absolute difference accumulated across vector */
98
int q;
99
- int rd, rn, rm, rd_ofs, rm_ofs;
100
+ int rd, rm, rd_ofs, rm_ofs;
101
int size;
102
int pass;
103
int u;
104
int vec_size;
105
- TCGv_i32 tmp, tmp2, tmp3, tmp5;
106
- TCGv_ptr ptr1;
107
+ TCGv_i32 tmp, tmp2, tmp3;
108
109
if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
110
return 1;
111
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
112
q = (insn & (1 << 6)) != 0;
113
u = (insn >> 24) & 1;
114
VFP_DREG_D(rd, insn);
115
- VFP_DREG_N(rn, insn);
116
VFP_DREG_M(rm, insn);
117
size = (insn >> 20) & 3;
118
vec_size = q ? 16 : 8;
119
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
120
break;
121
}
122
} else if ((insn & (1 << 10)) == 0) {
123
- /* VTBL, VTBX. */
124
- int n = ((insn >> 8) & 3) + 1;
125
- if ((rn + n) > 32) {
126
- /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
127
- * helper function running off the end of the register file.
128
- */
129
- return 1;
130
- }
131
- n <<= 3;
132
- if (insn & (1 << 6)) {
133
- tmp = neon_load_reg(rd, 0);
134
- } else {
135
- tmp = tcg_temp_new_i32();
136
- tcg_gen_movi_i32(tmp, 0);
137
- }
138
- tmp2 = neon_load_reg(rm, 0);
139
- ptr1 = vfp_reg_ptr(true, rn);
140
- tmp5 = tcg_const_i32(n);
141
- gen_helper_neon_tbl(tmp2, tmp2, tmp, ptr1, tmp5);
142
- tcg_temp_free_i32(tmp);
143
- if (insn & (1 << 6)) {
144
- tmp = neon_load_reg(rd, 1);
145
- } else {
146
- tmp = tcg_temp_new_i32();
147
- tcg_gen_movi_i32(tmp, 0);
148
- }
149
- tmp3 = neon_load_reg(rm, 1);
150
- gen_helper_neon_tbl(tmp3, tmp3, tmp, ptr1, tmp5);
151
- tcg_temp_free_i32(tmp5);
152
- tcg_temp_free_ptr(ptr1);
153
- neon_store_reg(rd, 0, tmp2);
154
- neon_store_reg(rd, 1, tmp3);
155
- tcg_temp_free_i32(tmp);
156
+ /* VTBL, VTBX: handled by decodetree */
157
+ return 1;
158
} else if ((insn & 0x380) == 0) {
159
/* VDUP */
160
int element;
161
--
186
--
162
2.20.1
187
2.20.1
163
188
164
189
diff view generated by jsdifflib
1
Convert the narrow-to-high-half insns VADDHN, VSUBHN, VRADDHN,
1
Implement the MVE fp vector comparisons VCMP and VPT.
2
VRSUBHN in the Neon 3-registers-different-lengths group to
3
decodetree.
4
2
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
---
5
---
8
target/arm/neon-dp.decode | 6 +++
6
target/arm/helper-mve.h | 18 +++++++++++
9
target/arm/translate-neon.inc.c | 87 +++++++++++++++++++++++++++++++
7
target/arm/mve.decode | 39 +++++++++++++++++++----
10
target/arm/translate.c | 91 ++++-----------------------------
8
target/arm/mve_helper.c | 64 ++++++++++++++++++++++++++++++++++++++
11
3 files changed, 104 insertions(+), 80 deletions(-)
9
target/arm/translate-mve.c | 22 +++++++++++++
12
10
4 files changed, 137 insertions(+), 6 deletions(-)
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
11
14
index XXXXXXX..XXXXXXX 100644
12
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
15
--- a/target/arm/neon-dp.decode
13
index XXXXXXX..XXXXXXX 100644
16
+++ b/target/arm/neon-dp.decode
14
--- a/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
15
+++ b/target/arm/helper-mve.h
18
16
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vcmple_scalarb, TCG_CALL_NO_WG, void, env, ptr, i32)
19
VSUBW_S_3d 1111 001 0 1 . .. .... .... 0011 . 0 . 0 .... @3diff
17
DEF_HELPER_FLAGS_3(mve_vcmple_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
20
VSUBW_U_3d 1111 001 1 1 . .. .... .... 0011 . 0 . 0 .... @3diff
18
DEF_HELPER_FLAGS_3(mve_vcmple_scalarw, TCG_CALL_NO_WG, void, env, ptr, i32)
21
+
19
22
+ VADDHN_3d 1111 001 0 1 . .. .... .... 0100 . 0 . 0 .... @3diff
20
+DEF_HELPER_FLAGS_3(mve_vfcmpeqh, TCG_CALL_NO_WG, void, env, ptr, ptr)
23
+ VRADDHN_3d 1111 001 1 1 . .. .... .... 0100 . 0 . 0 .... @3diff
21
+DEF_HELPER_FLAGS_3(mve_vfcmpeqs, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
+
22
+
25
+ VSUBHN_3d 1111 001 0 1 . .. .... .... 0110 . 0 . 0 .... @3diff
23
+DEF_HELPER_FLAGS_3(mve_vfcmpneh, TCG_CALL_NO_WG, void, env, ptr, ptr)
26
+ VRSUBHN_3d 1111 001 1 1 . .. .... .... 0110 . 0 . 0 .... @3diff
24
+DEF_HELPER_FLAGS_3(mve_vfcmpnes, TCG_CALL_NO_WG, void, env, ptr, ptr)
27
]
25
+
26
+DEF_HELPER_FLAGS_3(mve_vfcmpgeh, TCG_CALL_NO_WG, void, env, ptr, ptr)
27
+DEF_HELPER_FLAGS_3(mve_vfcmpges, TCG_CALL_NO_WG, void, env, ptr, ptr)
28
+
29
+DEF_HELPER_FLAGS_3(mve_vfcmplth, TCG_CALL_NO_WG, void, env, ptr, ptr)
30
+DEF_HELPER_FLAGS_3(mve_vfcmplts, TCG_CALL_NO_WG, void, env, ptr, ptr)
31
+
32
+DEF_HELPER_FLAGS_3(mve_vfcmpgth, TCG_CALL_NO_WG, void, env, ptr, ptr)
33
+DEF_HELPER_FLAGS_3(mve_vfcmpgts, TCG_CALL_NO_WG, void, env, ptr, ptr)
34
+
35
+DEF_HELPER_FLAGS_3(mve_vfcmpleh, TCG_CALL_NO_WG, void, env, ptr, ptr)
36
+DEF_HELPER_FLAGS_3(mve_vfcmples, TCG_CALL_NO_WG, void, env, ptr, ptr)
37
+
38
DEF_HELPER_FLAGS_4(mve_vfadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
39
DEF_HELPER_FLAGS_4(mve_vfadd_scalars, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
40
41
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
42
index XXXXXXX..XXXXXXX 100644
43
--- a/target/arm/mve.decode
44
+++ b/target/arm/mve.decode
45
@@ -XXX,XX +XXX,XX @@
46
@vcmp_scalar .... .... .. size:2 qn:3 . .... .... .... rm:4 &vcmp_scalar \
47
mask=%mask_22_13
48
49
+@vcmp_fp .... .... .... qn:3 . .... .... .... .... &vcmp \
50
+ qm=%qm size=%2op_fp_scalar_size mask=%mask_22_13
51
+
52
@vmaxv .... .... .... size:2 .. rda:4 .... .... .... &vmaxv qm=%qm
53
54
@2op_fp .... .... .... .... .... .... .... .... &2op \
55
@@ -XXX,XX +XXX,XX @@ VSHLC 111 0 1110 1 . 1 imm:5 ... 0 1111 1100 rdm:4 qd=%qd
56
# Comparisons. We expand out the conditions which are split across
57
# encodings T1, T2, T3 and the fc bits. These include VPT, which is
58
# effectively "VCMP then VPST". A plain "VCMP" has a mask field of zero.
59
-VCMPEQ 1111 1110 0 . .. ... 1 ... 0 1111 0 0 . 0 ... 0 @vcmp
60
-VCMPNE 1111 1110 0 . .. ... 1 ... 0 1111 1 0 . 0 ... 0 @vcmp
61
+{
62
+ VCMPEQ_fp 111 . 1110 0 . 11 ... 1 ... 0 1111 0 0 . 0 ... 0 @vcmp_fp
63
+ VCMPEQ 111 1 1110 0 . .. ... 1 ... 0 1111 0 0 . 0 ... 0 @vcmp
64
+}
65
+
66
+{
67
+ VCMPNE_fp 111 . 1110 0 . 11 ... 1 ... 0 1111 1 0 . 0 ... 0 @vcmp_fp
68
+ VCMPNE 111 1 1110 0 . .. ... 1 ... 0 1111 1 0 . 0 ... 0 @vcmp
69
+}
70
+
71
+{
72
+ VCMPGE_fp 111 . 1110 0 . 11 ... 1 ... 1 1111 0 0 . 0 ... 0 @vcmp_fp
73
+ VCMPGE 111 1 1110 0 . .. ... 1 ... 1 1111 0 0 . 0 ... 0 @vcmp
74
+}
75
+
76
+{
77
+ VCMPLT_fp 111 . 1110 0 . 11 ... 1 ... 1 1111 1 0 . 0 ... 0 @vcmp_fp
78
+ VCMPLT 111 1 1110 0 . .. ... 1 ... 1 1111 1 0 . 0 ... 0 @vcmp
79
+}
80
+
81
+{
82
+ VCMPGT_fp 111 . 1110 0 . 11 ... 1 ... 1 1111 0 0 . 0 ... 1 @vcmp_fp
83
+ VCMPGT 111 1 1110 0 . .. ... 1 ... 1 1111 0 0 . 0 ... 1 @vcmp
84
+}
85
+
86
+{
87
+ VCMPLE_fp 111 . 1110 0 . 11 ... 1 ... 1 1111 1 0 . 0 ... 1 @vcmp_fp
88
+ VCMPLE 1111 1110 0 . .. ... 1 ... 1 1111 1 0 . 0 ... 1 @vcmp
89
+}
90
+
91
{
92
VPSEL 1111 1110 0 . 11 ... 1 ... 0 1111 . 0 . 0 ... 1 @2op_nosz
93
VCMPCS 1111 1110 0 . .. ... 1 ... 0 1111 0 0 . 0 ... 1 @vcmp
94
VCMPHI 1111 1110 0 . .. ... 1 ... 0 1111 1 0 . 0 ... 1 @vcmp
28
}
95
}
29
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
96
-VCMPGE 1111 1110 0 . .. ... 1 ... 1 1111 0 0 . 0 ... 0 @vcmp
30
index XXXXXXX..XXXXXXX 100644
97
-VCMPLT 1111 1110 0 . .. ... 1 ... 1 1111 1 0 . 0 ... 0 @vcmp
31
--- a/target/arm/translate-neon.inc.c
98
-VCMPGT 1111 1110 0 . .. ... 1 ... 1 1111 0 0 . 0 ... 1 @vcmp
32
+++ b/target/arm/translate-neon.inc.c
99
-VCMPLE 1111 1110 0 . .. ... 1 ... 1 1111 1 0 . 0 ... 1 @vcmp
33
@@ -XXX,XX +XXX,XX @@ DO_PREWIDEN(VADDW_S, s, ext, add, true)
100
34
DO_PREWIDEN(VADDW_U, u, extu, add, true)
101
{
35
DO_PREWIDEN(VSUBW_S, s, ext, sub, true)
102
VPNOT 1111 1110 0 0 11 000 1 000 0 1111 0100 1101
36
DO_PREWIDEN(VSUBW_U, u, extu, sub, true)
103
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
37
+
104
index XXXXXXX..XXXXXXX 100644
38
+static bool do_narrow_3d(DisasContext *s, arg_3diff *a,
105
--- a/target/arm/mve_helper.c
39
+ NeonGenTwo64OpFn *opfn, NeonGenNarrowFn *narrowfn)
106
+++ b/target/arm/mve_helper.c
40
+{
107
@@ -XXX,XX +XXX,XX @@ DO_FP_VMAXMINV(vmaxnmavh, 2, float16, true, float16_maxnum)
41
+ /* 3-regs different lengths, narrowing (VADDHN/VSUBHN/VRADDHN/VRSUBHN) */
108
DO_FP_VMAXMINV(vmaxnmavs, 4, float32, true, float32_maxnum)
42
+ TCGv_i64 rn_64, rm_64;
109
DO_FP_VMAXMINV(vminnmavh, 2, float16, true, float16_minnum)
43
+ TCGv_i32 rd0, rd1;
110
DO_FP_VMAXMINV(vminnmavs, 4, float32, true, float32_minnum)
44
+
111
+
45
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
112
+/* FP compares; note that all comparisons signal InvalidOp for QNaNs */
46
+ return false;
113
+#define DO_VCMP_FP(OP, ESIZE, TYPE, FN) \
114
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vn, void *vm) \
115
+ { \
116
+ TYPE *n = vn, *m = vm; \
117
+ uint16_t mask = mve_element_mask(env); \
118
+ uint16_t eci_mask = mve_eci_mask(env); \
119
+ uint16_t beatpred = 0; \
120
+ uint16_t emask = MAKE_64BIT_MASK(0, ESIZE); \
121
+ unsigned e; \
122
+ float_status *fpst; \
123
+ float_status scratch_fpst; \
124
+ bool r; \
125
+ for (e = 0; e < 16 / ESIZE; e++, emask <<= ESIZE) { \
126
+ if ((mask & emask) == 0) { \
127
+ continue; \
128
+ } \
129
+ fpst = (ESIZE == 2) ? &env->vfp.standard_fp_status_f16 : \
130
+ &env->vfp.standard_fp_status; \
131
+ if (!(mask & (1 << (e * ESIZE)))) { \
132
+ /* We need the result but without updating flags */ \
133
+ scratch_fpst = *fpst; \
134
+ fpst = &scratch_fpst; \
135
+ } \
136
+ r = FN(n[H##ESIZE(e)], m[H##ESIZE(e)], fpst); \
137
+ /* Comparison sets 0/1 bits for each byte in the element */ \
138
+ beatpred |= r * emask; \
139
+ } \
140
+ beatpred &= mask; \
141
+ env->v7m.vpr = (env->v7m.vpr & ~(uint32_t)eci_mask) | \
142
+ (beatpred & eci_mask); \
143
+ mve_advance_vpt(env); \
47
+ }
144
+ }
48
+
145
+
49
+ /* UNDEF accesses to D16-D31 if they don't exist. */
146
+/*
50
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
147
+ * Some care is needed here to get the correct result for the unordered case.
51
+ ((a->vd | a->vn | a->vm) & 0x10)) {
148
+ * Architecturally EQ, GE and GT are defined to be false for unordered, but
52
+ return false;
149
+ * the NE, LT and LE comparisons are defined as simple logical inverses of
150
+ * EQ, GE and GT and so they must return true for unordered. The softfloat
151
+ * comparison functions float*_{eq,le,lt} all return false for unordered.
152
+ */
153
+#define DO_GE16(X, Y, S) float16_le(Y, X, S)
154
+#define DO_GE32(X, Y, S) float32_le(Y, X, S)
155
+#define DO_GT16(X, Y, S) float16_lt(Y, X, S)
156
+#define DO_GT32(X, Y, S) float32_lt(Y, X, S)
157
+
158
+DO_VCMP_FP(vfcmpeqh, 2, float16, float16_eq)
159
+DO_VCMP_FP(vfcmpeqs, 4, float32, float32_eq)
160
+
161
+DO_VCMP_FP(vfcmpneh, 2, float16, !float16_eq)
162
+DO_VCMP_FP(vfcmpnes, 4, float32, !float32_eq)
163
+
164
+DO_VCMP_FP(vfcmpgeh, 2, float16, DO_GE16)
165
+DO_VCMP_FP(vfcmpges, 4, float32, DO_GE32)
166
+
167
+DO_VCMP_FP(vfcmplth, 2, float16, !DO_GE16)
168
+DO_VCMP_FP(vfcmplts, 4, float32, !DO_GE32)
169
+
170
+DO_VCMP_FP(vfcmpgth, 2, float16, DO_GT16)
171
+DO_VCMP_FP(vfcmpgts, 4, float32, DO_GT32)
172
+
173
+DO_VCMP_FP(vfcmpleh, 2, float16, !DO_GT16)
174
+DO_VCMP_FP(vfcmples, 4, float32, !DO_GT32)
175
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
176
index XXXXXXX..XXXXXXX 100644
177
--- a/target/arm/translate-mve.c
178
+++ b/target/arm/translate-mve.c
179
@@ -XXX,XX +XXX,XX @@ DO_VCMP(VCMPLT, vcmplt)
180
DO_VCMP(VCMPGT, vcmpgt)
181
DO_VCMP(VCMPLE, vcmple)
182
183
+#define DO_VCMP_FP(INSN, FN) \
184
+ static bool trans_##INSN(DisasContext *s, arg_vcmp *a) \
185
+ { \
186
+ static MVEGenCmpFn * const fns[] = { \
187
+ NULL, \
188
+ gen_helper_mve_##FN##h, \
189
+ gen_helper_mve_##FN##s, \
190
+ NULL, \
191
+ }; \
192
+ if (!dc_isar_feature(aa32_mve_fp, s)) { \
193
+ return false; \
194
+ } \
195
+ return do_vcmp(s, a, fns[a->size]); \
53
+ }
196
+ }
54
+
197
+
55
+ if (!opfn || !narrowfn) {
198
+DO_VCMP_FP(VCMPEQ_fp, vfcmpeq)
56
+ /* size == 3 case, which is an entirely different insn group */
199
+DO_VCMP_FP(VCMPNE_fp, vfcmpne)
57
+ return false;
200
+DO_VCMP_FP(VCMPGE_fp, vfcmpge)
58
+ }
201
+DO_VCMP_FP(VCMPLT_fp, vfcmplt)
59
+
202
+DO_VCMP_FP(VCMPGT_fp, vfcmpgt)
60
+ if ((a->vn | a->vm) & 1) {
203
+DO_VCMP_FP(VCMPLE_fp, vfcmple)
61
+ return false;
204
+
62
+ }
205
static bool do_vmaxv(DisasContext *s, arg_vmaxv *a, MVEGenVADDVFn fn)
63
+
64
+ if (!vfp_access_check(s)) {
65
+ return true;
66
+ }
67
+
68
+ rn_64 = tcg_temp_new_i64();
69
+ rm_64 = tcg_temp_new_i64();
70
+ rd0 = tcg_temp_new_i32();
71
+ rd1 = tcg_temp_new_i32();
72
+
73
+ neon_load_reg64(rn_64, a->vn);
74
+ neon_load_reg64(rm_64, a->vm);
75
+
76
+ opfn(rn_64, rn_64, rm_64);
77
+
78
+ narrowfn(rd0, rn_64);
79
+
80
+ neon_load_reg64(rn_64, a->vn + 1);
81
+ neon_load_reg64(rm_64, a->vm + 1);
82
+
83
+ opfn(rn_64, rn_64, rm_64);
84
+
85
+ narrowfn(rd1, rn_64);
86
+
87
+ neon_store_reg(a->vd, 0, rd0);
88
+ neon_store_reg(a->vd, 1, rd1);
89
+
90
+ tcg_temp_free_i64(rn_64);
91
+ tcg_temp_free_i64(rm_64);
92
+
93
+ return true;
94
+}
95
+
96
+#define DO_NARROW_3D(INSN, OP, NARROWTYPE, EXTOP) \
97
+ static bool trans_##INSN##_3d(DisasContext *s, arg_3diff *a) \
98
+ { \
99
+ static NeonGenTwo64OpFn * const addfn[] = { \
100
+ gen_helper_neon_##OP##l_u16, \
101
+ gen_helper_neon_##OP##l_u32, \
102
+ tcg_gen_##OP##_i64, \
103
+ NULL, \
104
+ }; \
105
+ static NeonGenNarrowFn * const narrowfn[] = { \
106
+ gen_helper_neon_##NARROWTYPE##_high_u8, \
107
+ gen_helper_neon_##NARROWTYPE##_high_u16, \
108
+ EXTOP, \
109
+ NULL, \
110
+ }; \
111
+ return do_narrow_3d(s, a, addfn[a->size], narrowfn[a->size]); \
112
+ }
113
+
114
+static void gen_narrow_round_high_u32(TCGv_i32 rd, TCGv_i64 rn)
115
+{
116
+ tcg_gen_addi_i64(rn, rn, 1u << 31);
117
+ tcg_gen_extrh_i64_i32(rd, rn);
118
+}
119
+
120
+DO_NARROW_3D(VADDHN, add, narrow, tcg_gen_extrh_i64_i32)
121
+DO_NARROW_3D(VSUBHN, sub, narrow, tcg_gen_extrh_i64_i32)
122
+DO_NARROW_3D(VRADDHN, add, narrow_round, gen_narrow_round_high_u32)
123
+DO_NARROW_3D(VRSUBHN, sub, narrow_round, gen_narrow_round_high_u32)
124
diff --git a/target/arm/translate.c b/target/arm/translate.c
125
index XXXXXXX..XXXXXXX 100644
126
--- a/target/arm/translate.c
127
+++ b/target/arm/translate.c
128
@@ -XXX,XX +XXX,XX @@ static inline void gen_neon_addl(int size)
129
}
130
}
131
132
-static inline void gen_neon_subl(int size)
133
-{
134
- switch (size) {
135
- case 0: gen_helper_neon_subl_u16(CPU_V001); break;
136
- case 1: gen_helper_neon_subl_u32(CPU_V001); break;
137
- case 2: tcg_gen_sub_i64(CPU_V001); break;
138
- default: abort();
139
- }
140
-}
141
-
142
static inline void gen_neon_negl(TCGv_i64 var, int size)
143
{
206
{
144
switch (size) {
207
/*
145
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
146
op = (insn >> 8) & 0xf;
147
if ((insn & (1 << 6)) == 0) {
148
/* Three registers of different lengths. */
149
- int src1_wide;
150
- int src2_wide;
151
/* undefreq: bit 0 : UNDEF if size == 0
152
* bit 1 : UNDEF if size == 1
153
* bit 2 : UNDEF if size == 2
154
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
155
{0, 0, 0, 7}, /* VADDW: handled by decodetree */
156
{0, 0, 0, 7}, /* VSUBL: handled by decodetree */
157
{0, 0, 0, 7}, /* VSUBW: handled by decodetree */
158
- {0, 1, 1, 0}, /* VADDHN */
159
+ {0, 0, 0, 7}, /* VADDHN: handled by decodetree */
160
{0, 0, 0, 0}, /* VABAL */
161
- {0, 1, 1, 0}, /* VSUBHN */
162
+ {0, 0, 0, 7}, /* VSUBHN: handled by decodetree */
163
{0, 0, 0, 0}, /* VABDL */
164
{0, 0, 0, 0}, /* VMLAL */
165
{0, 0, 0, 9}, /* VQDMLAL */
166
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
167
{0, 0, 0, 7}, /* Reserved: always UNDEF */
168
};
169
170
- src1_wide = neon_3reg_wide[op][1];
171
- src2_wide = neon_3reg_wide[op][2];
172
undefreq = neon_3reg_wide[op][3];
173
174
if ((undefreq & (1 << size)) ||
175
((undefreq & 8) && u)) {
176
return 1;
177
}
178
- if ((src1_wide && (rn & 1)) ||
179
- (src2_wide && (rm & 1)) ||
180
- (!src2_wide && (rd & 1))) {
181
+ if (rd & 1) {
182
return 1;
183
}
184
185
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
186
/* Avoid overlapping operands. Wide source operands are
187
always aligned so will never overlap with wide
188
destinations in problematic ways. */
189
- if (rd == rm && !src2_wide) {
190
+ if (rd == rm) {
191
tmp = neon_load_reg(rm, 1);
192
neon_store_scratch(2, tmp);
193
- } else if (rd == rn && !src1_wide) {
194
+ } else if (rd == rn) {
195
tmp = neon_load_reg(rn, 1);
196
neon_store_scratch(2, tmp);
197
}
198
tmp3 = NULL;
199
for (pass = 0; pass < 2; pass++) {
200
- if (src1_wide) {
201
- neon_load_reg64(cpu_V0, rn + pass);
202
- tmp = NULL;
203
+ if (pass == 1 && rd == rn) {
204
+ tmp = neon_load_scratch(2);
205
} else {
206
- if (pass == 1 && rd == rn) {
207
- tmp = neon_load_scratch(2);
208
- } else {
209
- tmp = neon_load_reg(rn, pass);
210
- }
211
+ tmp = neon_load_reg(rn, pass);
212
}
213
- if (src2_wide) {
214
- neon_load_reg64(cpu_V1, rm + pass);
215
- tmp2 = NULL;
216
+ if (pass == 1 && rd == rm) {
217
+ tmp2 = neon_load_scratch(2);
218
} else {
219
- if (pass == 1 && rd == rm) {
220
- tmp2 = neon_load_scratch(2);
221
- } else {
222
- tmp2 = neon_load_reg(rm, pass);
223
- }
224
+ tmp2 = neon_load_reg(rm, pass);
225
}
226
switch (op) {
227
- case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
228
- gen_neon_addl(size);
229
- break;
230
- case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
231
- gen_neon_subl(size);
232
- break;
233
case 5: case 7: /* VABAL, VABDL */
234
switch ((size << 1) | u) {
235
case 0:
236
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
237
abort();
238
}
239
neon_store_reg64(cpu_V0, rd + pass);
240
- } else if (op == 4 || op == 6) {
241
- /* Narrowing operation. */
242
- tmp = tcg_temp_new_i32();
243
- if (!u) {
244
- switch (size) {
245
- case 0:
246
- gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
247
- break;
248
- case 1:
249
- gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
250
- break;
251
- case 2:
252
- tcg_gen_extrh_i64_i32(tmp, cpu_V0);
253
- break;
254
- default: abort();
255
- }
256
- } else {
257
- switch (size) {
258
- case 0:
259
- gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
260
- break;
261
- case 1:
262
- gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
263
- break;
264
- case 2:
265
- tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
266
- tcg_gen_extrh_i64_i32(tmp, cpu_V0);
267
- break;
268
- default: abort();
269
- }
270
- }
271
- if (pass == 0) {
272
- tmp3 = tmp;
273
- } else {
274
- neon_store_reg(rd, 0, tmp3);
275
- neon_store_reg(rd, 1, tmp);
276
- }
277
} else {
278
/* Write back the result. */
279
neon_store_reg64(cpu_V0, rd + pass);
280
--
208
--
281
2.20.1
209
2.20.1
282
210
283
211
diff view generated by jsdifflib
1
Convert the "pre-widening" insns VADDL, VSUBL, VADDW and VSUBW
1
Implement the MVE fp scalar comparisons VCMP and VPT.
2
in the Neon 3-registers-different-lengths group to decodetree.
3
These insns work by widening one or both inputs to double their
4
size, performing an add or subtract at the doubled size and
5
then storing the double-size result.
6
7
As usual, rather than copying the loop of the original decoder
8
(which needs awkward code to avoid problems when source and
9
destination registers overlap) we just unroll the two passes.
10
2
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
---
5
---
14
target/arm/neon-dp.decode | 43 +++++++++++++
6
target/arm/helper-mve.h | 18 +++++++++++
15
target/arm/translate-neon.inc.c | 104 ++++++++++++++++++++++++++++++++
7
target/arm/mve.decode | 61 +++++++++++++++++++++++++++++--------
16
target/arm/translate.c | 16 ++---
8
target/arm/mve_helper.c | 62 ++++++++++++++++++++++++++++++--------
17
3 files changed, 151 insertions(+), 12 deletions(-)
9
target/arm/translate-mve.c | 14 +++++++++
18
10
4 files changed, 131 insertions(+), 24 deletions(-)
19
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
11
20
index XXXXXXX..XXXXXXX 100644
12
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
21
--- a/target/arm/neon-dp.decode
13
index XXXXXXX..XXXXXXX 100644
22
+++ b/target/arm/neon-dp.decode
14
--- a/target/arm/helper-mve.h
23
@@ -XXX,XX +XXX,XX @@ VCVT_FU_2sh 1111 001 1 1 . ...... .... 1111 0 . . 1 .... @2reg_vcvt
15
+++ b/target/arm/helper-mve.h
24
# So we have a single decode line and check the cmode/op in the
16
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vfcmpgts, TCG_CALL_NO_WG, void, env, ptr, ptr)
25
# trans function.
17
DEF_HELPER_FLAGS_3(mve_vfcmpleh, TCG_CALL_NO_WG, void, env, ptr, ptr)
26
Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
18
DEF_HELPER_FLAGS_3(mve_vfcmples, TCG_CALL_NO_WG, void, env, ptr, ptr)
27
+
19
28
+######################################################################
20
+DEF_HELPER_FLAGS_3(mve_vfcmpeq_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
29
+# Within the "two registers, or three registers of different lengths"
21
+DEF_HELPER_FLAGS_3(mve_vfcmpeq_scalars, TCG_CALL_NO_WG, void, env, ptr, i32)
30
+# grouping ([23,4]=0b10), bits [21:20] are either part of the opcode
22
+
31
+# decode: 0b11 for VEXT, two-reg-misc, VTBL, and duplicate-scalar;
23
+DEF_HELPER_FLAGS_3(mve_vfcmpne_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
32
+# or they are a size field for the three-reg-different-lengths and
24
+DEF_HELPER_FLAGS_3(mve_vfcmpne_scalars, TCG_CALL_NO_WG, void, env, ptr, i32)
33
+# two-reg-and-scalar insn groups (where size cannot be 0b11). This
25
+
34
+# is slightly awkward for decodetree: we handle it with this
26
+DEF_HELPER_FLAGS_3(mve_vfcmpge_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
35
+# non-exclusive group which contains within it two exclusive groups:
27
+DEF_HELPER_FLAGS_3(mve_vfcmpge_scalars, TCG_CALL_NO_WG, void, env, ptr, i32)
36
+# one for the size=0b11 patterns, and one for the size-not-0b11
28
+
37
+# patterns. This allows us to check that none of the insns within
29
+DEF_HELPER_FLAGS_3(mve_vfcmplt_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
38
+# each subgroup accidentally overlap each other. Note that all the
30
+DEF_HELPER_FLAGS_3(mve_vfcmplt_scalars, TCG_CALL_NO_WG, void, env, ptr, i32)
39
+# trans functions for the size-not-0b11 patterns must check and
31
+
40
+# return false for size==3.
32
+DEF_HELPER_FLAGS_3(mve_vfcmpgt_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
41
+######################################################################
33
+DEF_HELPER_FLAGS_3(mve_vfcmpgt_scalars, TCG_CALL_NO_WG, void, env, ptr, i32)
42
+{
34
+
43
+ # 0b11 subgroup will go here
35
+DEF_HELPER_FLAGS_3(mve_vfcmple_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
44
+
36
+DEF_HELPER_FLAGS_3(mve_vfcmple_scalars, TCG_CALL_NO_WG, void, env, ptr, i32)
45
+ # Subgroup for size != 0b11
37
+
46
+ [
38
DEF_HELPER_FLAGS_4(mve_vfadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
47
+ ##################################################################
39
DEF_HELPER_FLAGS_4(mve_vfadd_scalars, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
48
+ # 3-reg-different-length grouping:
40
49
+ # 1111 001 U 1 D sz!=11 Vn:4 Vd:4 opc:4 N 0 M 0 Vm:4
41
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
50
+ ##################################################################
42
index XXXXXXX..XXXXXXX 100644
51
+
43
--- a/target/arm/mve.decode
52
+ &3diff vm vn vd size
44
+++ b/target/arm/mve.decode
53
+
45
@@ -XXX,XX +XXX,XX @@
54
+ @3diff .... ... . . . size:2 .... .... .... . . . . .... \
46
@vcmp_fp .... .... .... qn:3 . .... .... .... .... &vcmp \
55
+ &3diff vm=%vm_dp vn=%vn_dp vd=%vd_dp
47
qm=%qm size=%2op_fp_scalar_size mask=%mask_22_13
56
+
48
57
+ VADDL_S_3d 1111 001 0 1 . .. .... .... 0000 . 0 . 0 .... @3diff
49
+# Bit 28 is a 2op_fp_scalar_size bit, but we do not decode it in this
58
+ VADDL_U_3d 1111 001 1 1 . .. .... .... 0000 . 0 . 0 .... @3diff
50
+# format to avoid complicated overlapping-instruction-groups
59
+
51
+@vcmp_fp_scalar .... .... .... qn:3 . .... .... .... rm:4 &vcmp_scalar \
60
+ VADDW_S_3d 1111 001 0 1 . .. .... .... 0001 . 0 . 0 .... @3diff
52
+ mask=%mask_22_13
61
+ VADDW_U_3d 1111 001 1 1 . .. .... .... 0001 . 0 . 0 .... @3diff
53
+
62
+
54
@vmaxv .... .... .... size:2 .. rda:4 .... .... .... &vmaxv qm=%qm
63
+ VSUBL_S_3d 1111 001 0 1 . .. .... .... 0010 . 0 . 0 .... @3diff
55
64
+ VSUBL_U_3d 1111 001 1 1 . .. .... .... 0010 . 0 . 0 .... @3diff
56
@2op_fp .... .... .... .... .... .... .... .... &2op \
65
+
57
@@ -XXX,XX +XXX,XX @@ VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=2
66
+ VSUBW_S_3d 1111 001 0 1 . .. .... .... 0011 . 0 . 0 .... @3diff
58
VIWDUP 1110 1110 0 . .. ... 1 ... 0 1111 . 110 ... . @viwdup
67
+ VSUBW_U_3d 1111 001 1 1 . .. .... .... 0011 . 0 . 0 .... @3diff
59
}
68
+ ]
60
{
69
+}
61
- VDDUP 1110 1110 0 . .. ... 1 ... 1 1111 . 110 111 . @vidup
70
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
62
- VDWDUP 1110 1110 0 . .. ... 1 ... 1 1111 . 110 ... . @viwdup
71
index XXXXXXX..XXXXXXX 100644
63
+ VCMPGT_fp_scalar 1110 1110 0 . 11 ... 1 ... 1 1111 0110 .... @vcmp_fp_scalar size=2
72
--- a/target/arm/translate-neon.inc.c
64
+ VCMPLE_fp_scalar 1110 1110 0 . 11 ... 1 ... 1 1111 1110 .... @vcmp_fp_scalar size=2
73
+++ b/target/arm/translate-neon.inc.c
65
+ VDDUP 1110 1110 0 . .. ... 1 ... 1 1111 . 110 111 . @vidup
74
@@ -XXX,XX +XXX,XX @@ static bool trans_Vimm_1r(DisasContext *s, arg_1reg_imm *a)
66
+ VDWDUP 1110 1110 0 . .. ... 1 ... 1 1111 . 110 ... . @viwdup
67
}
68
69
# multiply-add long dual accumulate
70
@@ -XXX,XX +XXX,XX @@ VMLADAV_U 1111 1110 1111 ... 0 ... . 1111 . 0 . 0 ... 1 @vmladav_nosz
71
72
# Scalar operations
73
74
-VADD_scalar 1110 1110 0 . .. ... 1 ... 0 1111 . 100 .... @2scalar
75
-VSUB_scalar 1110 1110 0 . .. ... 1 ... 1 1111 . 100 .... @2scalar
76
+{
77
+ VCMPEQ_fp_scalar 1110 1110 0 . 11 ... 1 ... 0 1111 0100 .... @vcmp_fp_scalar size=2
78
+ VCMPNE_fp_scalar 1110 1110 0 . 11 ... 1 ... 0 1111 1100 .... @vcmp_fp_scalar size=2
79
+ VADD_scalar 1110 1110 0 . .. ... 1 ... 0 1111 . 100 .... @2scalar
80
+}
81
+
82
+{
83
+ VCMPLT_fp_scalar 1110 1110 0 . 11 ... 1 ... 1 1111 1100 .... @vcmp_fp_scalar size=2
84
+ VCMPGE_fp_scalar 1110 1110 0 . 11 ... 1 ... 1 1111 0100 .... @vcmp_fp_scalar size=2
85
+ VSUB_scalar 1110 1110 0 . .. ... 1 ... 1 1111 . 100 .... @2scalar
86
+}
87
88
{
89
VSHL_S_scalar 1110 1110 0 . 11 .. 01 ... 1 1110 0110 .... @shl_scalar
90
@@ -XXX,XX +XXX,XX @@ VSHLC 111 0 1110 1 . 1 imm:5 ... 0 1111 1100 rdm:4 qd=%qd
91
}
92
93
{
94
- VPNOT 1111 1110 0 0 11 000 1 000 0 1111 0100 1101
95
- VPST 1111 1110 0 . 11 000 1 ... 0 1111 0100 1101 mask=%mask_22_13
96
- VCMPEQ_scalar 1111 1110 0 . .. ... 1 ... 0 1111 0 1 0 0 .... @vcmp_scalar
97
+ VPNOT 1111 1110 0 0 11 000 1 000 0 1111 0100 1101
98
+ VPST 1111 1110 0 . 11 000 1 ... 0 1111 0100 1101 mask=%mask_22_13
99
+ VCMPEQ_fp_scalar 1111 1110 0 . 11 ... 1 ... 0 1111 0100 .... @vcmp_fp_scalar size=1
100
+ VCMPEQ_scalar 1111 1110 0 . .. ... 1 ... 0 1111 0100 .... @vcmp_scalar
101
}
102
-VCMPNE_scalar 1111 1110 0 . .. ... 1 ... 0 1111 1 1 0 0 .... @vcmp_scalar
103
+
104
+{
105
+ VCMPNE_fp_scalar 1111 1110 0 . 11 ... 1 ... 0 1111 1100 .... @vcmp_fp_scalar size=1
106
+ VCMPNE_scalar 1111 1110 0 . .. ... 1 ... 0 1111 1100 .... @vcmp_scalar
107
+}
108
+
109
+{
110
+ VCMPGT_fp_scalar 1111 1110 0 . 11 ... 1 ... 1 1111 0110 .... @vcmp_fp_scalar size=1
111
+ VCMPGT_scalar 1111 1110 0 . .. ... 1 ... 1 1111 0110 .... @vcmp_scalar
112
+}
113
+
114
+{
115
+ VCMPLE_fp_scalar 1111 1110 0 . 11 ... 1 ... 1 1111 1110 .... @vcmp_fp_scalar size=1
116
+ VCMPLE_scalar 1111 1110 0 . .. ... 1 ... 1 1111 1110 .... @vcmp_scalar
117
+}
118
+
119
+{
120
+ VCMPGE_fp_scalar 1111 1110 0 . 11 ... 1 ... 1 1111 0100 .... @vcmp_fp_scalar size=1
121
+ VCMPGE_scalar 1111 1110 0 . .. ... 1 ... 1 1111 0100 .... @vcmp_scalar
122
+}
123
+{
124
+ VCMPLT_fp_scalar 1111 1110 0 . 11 ... 1 ... 1 1111 1100 .... @vcmp_fp_scalar size=1
125
+ VCMPLT_scalar 1111 1110 0 . .. ... 1 ... 1 1111 1100 .... @vcmp_scalar
126
+}
127
+
128
VCMPCS_scalar 1111 1110 0 . .. ... 1 ... 0 1111 0 1 1 0 .... @vcmp_scalar
129
VCMPHI_scalar 1111 1110 0 . .. ... 1 ... 0 1111 1 1 1 0 .... @vcmp_scalar
130
-VCMPGE_scalar 1111 1110 0 . .. ... 1 ... 1 1111 0 1 0 0 .... @vcmp_scalar
131
-VCMPLT_scalar 1111 1110 0 . .. ... 1 ... 1 1111 1 1 0 0 .... @vcmp_scalar
132
-VCMPGT_scalar 1111 1110 0 . .. ... 1 ... 1 1111 0 1 1 0 .... @vcmp_scalar
133
-VCMPLE_scalar 1111 1110 0 . .. ... 1 ... 1 1111 1 1 1 0 .... @vcmp_scalar
134
135
# 2-operand FP
136
VADD_fp 1110 1111 0 . 0 . ... 0 ... 0 1101 . 1 . 0 ... 0 @2op_fp
137
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
138
index XXXXXXX..XXXXXXX 100644
139
--- a/target/arm/mve_helper.c
140
+++ b/target/arm/mve_helper.c
141
@@ -XXX,XX +XXX,XX @@ DO_FP_VMAXMINV(vminnmavs, 4, float32, true, float32_minnum)
142
mve_advance_vpt(env); \
75
}
143
}
76
return do_1reg_imm(s, a, fn);
144
77
}
145
+#define DO_VCMP_FP_SCALAR(OP, ESIZE, TYPE, FN) \
78
+
146
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vn, \
79
+static bool do_prewiden_3d(DisasContext *s, arg_3diff *a,
147
+ uint32_t rm) \
80
+ NeonGenWidenFn *widenfn,
148
+ { \
81
+ NeonGenTwo64OpFn *opfn,
149
+ TYPE *n = vn; \
82
+ bool src1_wide)
150
+ uint16_t mask = mve_element_mask(env); \
83
+{
151
+ uint16_t eci_mask = mve_eci_mask(env); \
84
+ /* 3-regs different lengths, prewidening case (VADDL/VSUBL/VAADW/VSUBW) */
152
+ uint16_t beatpred = 0; \
85
+ TCGv_i64 rn0_64, rn1_64, rm_64;
153
+ uint16_t emask = MAKE_64BIT_MASK(0, ESIZE); \
86
+ TCGv_i32 rm;
154
+ unsigned e; \
87
+
155
+ float_status *fpst; \
88
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
156
+ float_status scratch_fpst; \
89
+ return false;
157
+ bool r; \
158
+ for (e = 0; e < 16 / ESIZE; e++, emask <<= ESIZE) { \
159
+ if ((mask & emask) == 0) { \
160
+ continue; \
161
+ } \
162
+ fpst = (ESIZE == 2) ? &env->vfp.standard_fp_status_f16 : \
163
+ &env->vfp.standard_fp_status; \
164
+ if (!(mask & (1 << (e * ESIZE)))) { \
165
+ /* We need the result but without updating flags */ \
166
+ scratch_fpst = *fpst; \
167
+ fpst = &scratch_fpst; \
168
+ } \
169
+ r = FN(n[H##ESIZE(e)], (TYPE)rm, fpst); \
170
+ /* Comparison sets 0/1 bits for each byte in the element */ \
171
+ beatpred |= r * emask; \
172
+ } \
173
+ beatpred &= mask; \
174
+ env->v7m.vpr = (env->v7m.vpr & ~(uint32_t)eci_mask) | \
175
+ (beatpred & eci_mask); \
176
+ mve_advance_vpt(env); \
90
+ }
177
+ }
91
+
178
+
92
+ /* UNDEF accesses to D16-D31 if they don't exist. */
179
+#define DO_VCMP_FP_BOTH(VOP, SOP, ESIZE, TYPE, FN) \
93
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
180
+ DO_VCMP_FP(VOP, ESIZE, TYPE, FN) \
94
+ ((a->vd | a->vn | a->vm) & 0x10)) {
181
+ DO_VCMP_FP_SCALAR(SOP, ESIZE, TYPE, FN)
95
+ return false;
182
+
96
+ }
183
/*
97
+
184
* Some care is needed here to get the correct result for the unordered case.
98
+ if (!widenfn || !opfn) {
185
* Architecturally EQ, GE and GT are defined to be false for unordered, but
99
+ /* size == 3 case, which is an entirely different insn group */
186
@@ -XXX,XX +XXX,XX @@ DO_FP_VMAXMINV(vminnmavs, 4, float32, true, float32_minnum)
100
+ return false;
187
#define DO_GT16(X, Y, S) float16_lt(Y, X, S)
101
+ }
188
#define DO_GT32(X, Y, S) float32_lt(Y, X, S)
102
+
189
103
+ if ((a->vd & 1) || (src1_wide && (a->vn & 1))) {
190
-DO_VCMP_FP(vfcmpeqh, 2, float16, float16_eq)
104
+ return false;
191
-DO_VCMP_FP(vfcmpeqs, 4, float32, float32_eq)
105
+ }
192
+DO_VCMP_FP_BOTH(vfcmpeqh, vfcmpeq_scalarh, 2, float16, float16_eq)
106
+
193
+DO_VCMP_FP_BOTH(vfcmpeqs, vfcmpeq_scalars, 4, float32, float32_eq)
107
+ if (!vfp_access_check(s)) {
194
108
+ return true;
195
-DO_VCMP_FP(vfcmpneh, 2, float16, !float16_eq)
109
+ }
196
-DO_VCMP_FP(vfcmpnes, 4, float32, !float32_eq)
110
+
197
+DO_VCMP_FP_BOTH(vfcmpneh, vfcmpne_scalarh, 2, float16, !float16_eq)
111
+ rn0_64 = tcg_temp_new_i64();
198
+DO_VCMP_FP_BOTH(vfcmpnes, vfcmpne_scalars, 4, float32, !float32_eq)
112
+ rn1_64 = tcg_temp_new_i64();
199
113
+ rm_64 = tcg_temp_new_i64();
200
-DO_VCMP_FP(vfcmpgeh, 2, float16, DO_GE16)
114
+
201
-DO_VCMP_FP(vfcmpges, 4, float32, DO_GE32)
115
+ if (src1_wide) {
202
+DO_VCMP_FP_BOTH(vfcmpgeh, vfcmpge_scalarh, 2, float16, DO_GE16)
116
+ neon_load_reg64(rn0_64, a->vn);
203
+DO_VCMP_FP_BOTH(vfcmpges, vfcmpge_scalars, 4, float32, DO_GE32)
117
+ } else {
204
118
+ TCGv_i32 tmp = neon_load_reg(a->vn, 0);
205
-DO_VCMP_FP(vfcmplth, 2, float16, !DO_GE16)
119
+ widenfn(rn0_64, tmp);
206
-DO_VCMP_FP(vfcmplts, 4, float32, !DO_GE32)
120
+ tcg_temp_free_i32(tmp);
207
+DO_VCMP_FP_BOTH(vfcmplth, vfcmplt_scalarh, 2, float16, !DO_GE16)
121
+ }
208
+DO_VCMP_FP_BOTH(vfcmplts, vfcmplt_scalars, 4, float32, !DO_GE32)
122
+ rm = neon_load_reg(a->vm, 0);
209
123
+
210
-DO_VCMP_FP(vfcmpgth, 2, float16, DO_GT16)
124
+ widenfn(rm_64, rm);
211
-DO_VCMP_FP(vfcmpgts, 4, float32, DO_GT32)
125
+ tcg_temp_free_i32(rm);
212
+DO_VCMP_FP_BOTH(vfcmpgth, vfcmpgt_scalarh, 2, float16, DO_GT16)
126
+ opfn(rn0_64, rn0_64, rm_64);
213
+DO_VCMP_FP_BOTH(vfcmpgts, vfcmpgt_scalars, 4, float32, DO_GT32)
127
+
214
128
+ /*
215
-DO_VCMP_FP(vfcmpleh, 2, float16, !DO_GT16)
129
+ * Load second pass inputs before storing the first pass result, to
216
-DO_VCMP_FP(vfcmples, 4, float32, !DO_GT32)
130
+ * avoid incorrect results if a narrow input overlaps with the result.
217
+DO_VCMP_FP_BOTH(vfcmpleh, vfcmple_scalarh, 2, float16, !DO_GT16)
131
+ */
218
+DO_VCMP_FP_BOTH(vfcmples, vfcmple_scalars, 4, float32, !DO_GT32)
132
+ if (src1_wide) {
219
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
133
+ neon_load_reg64(rn1_64, a->vn + 1);
220
index XXXXXXX..XXXXXXX 100644
134
+ } else {
221
--- a/target/arm/translate-mve.c
135
+ TCGv_i32 tmp = neon_load_reg(a->vn, 1);
222
+++ b/target/arm/translate-mve.c
136
+ widenfn(rn1_64, tmp);
223
@@ -XXX,XX +XXX,XX @@ DO_VCMP(VCMPLE, vcmple)
137
+ tcg_temp_free_i32(tmp);
224
return false; \
138
+ }
225
} \
139
+ rm = neon_load_reg(a->vm, 1);
226
return do_vcmp(s, a, fns[a->size]); \
140
+
227
+ } \
141
+ neon_store_reg64(rn0_64, a->vd);
228
+ static bool trans_##INSN##_scalar(DisasContext *s, \
142
+
229
+ arg_vcmp_scalar *a) \
143
+ widenfn(rm_64, rm);
230
+ { \
144
+ tcg_temp_free_i32(rm);
231
+ static MVEGenScalarCmpFn * const fns[] = { \
145
+ opfn(rn1_64, rn1_64, rm_64);
232
+ NULL, \
146
+ neon_store_reg64(rn1_64, a->vd + 1);
233
+ gen_helper_mve_##FN##_scalarh, \
147
+
234
+ gen_helper_mve_##FN##_scalars, \
148
+ tcg_temp_free_i64(rn0_64);
235
+ NULL, \
149
+ tcg_temp_free_i64(rn1_64);
236
+ }; \
150
+ tcg_temp_free_i64(rm_64);
237
+ if (!dc_isar_feature(aa32_mve_fp, s)) { \
151
+
238
+ return false; \
152
+ return true;
239
+ } \
153
+}
240
+ return do_vcmp_scalar(s, a, fns[a->size]); \
154
+
241
}
155
+#define DO_PREWIDEN(INSN, S, EXT, OP, SRC1WIDE) \
242
156
+ static bool trans_##INSN##_3d(DisasContext *s, arg_3diff *a) \
243
DO_VCMP_FP(VCMPEQ_fp, vfcmpeq)
157
+ { \
158
+ static NeonGenWidenFn * const widenfn[] = { \
159
+ gen_helper_neon_widen_##S##8, \
160
+ gen_helper_neon_widen_##S##16, \
161
+ tcg_gen_##EXT##_i32_i64, \
162
+ NULL, \
163
+ }; \
164
+ static NeonGenTwo64OpFn * const addfn[] = { \
165
+ gen_helper_neon_##OP##l_u16, \
166
+ gen_helper_neon_##OP##l_u32, \
167
+ tcg_gen_##OP##_i64, \
168
+ NULL, \
169
+ }; \
170
+ return do_prewiden_3d(s, a, widenfn[a->size], \
171
+ addfn[a->size], SRC1WIDE); \
172
+ }
173
+
174
+DO_PREWIDEN(VADDL_S, s, ext, add, false)
175
+DO_PREWIDEN(VADDL_U, u, extu, add, false)
176
+DO_PREWIDEN(VSUBL_S, s, ext, sub, false)
177
+DO_PREWIDEN(VSUBL_U, u, extu, sub, false)
178
+DO_PREWIDEN(VADDW_S, s, ext, add, true)
179
+DO_PREWIDEN(VADDW_U, u, extu, add, true)
180
+DO_PREWIDEN(VSUBW_S, s, ext, sub, true)
181
+DO_PREWIDEN(VSUBW_U, u, extu, sub, true)
182
diff --git a/target/arm/translate.c b/target/arm/translate.c
183
index XXXXXXX..XXXXXXX 100644
184
--- a/target/arm/translate.c
185
+++ b/target/arm/translate.c
186
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
187
/* Three registers of different lengths. */
188
int src1_wide;
189
int src2_wide;
190
- int prewiden;
191
/* undefreq: bit 0 : UNDEF if size == 0
192
* bit 1 : UNDEF if size == 1
193
* bit 2 : UNDEF if size == 2
194
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
195
int undefreq;
196
/* prewiden, src1_wide, src2_wide, undefreq */
197
static const int neon_3reg_wide[16][4] = {
198
- {1, 0, 0, 0}, /* VADDL */
199
- {1, 1, 0, 0}, /* VADDW */
200
- {1, 0, 0, 0}, /* VSUBL */
201
- {1, 1, 0, 0}, /* VSUBW */
202
+ {0, 0, 0, 7}, /* VADDL: handled by decodetree */
203
+ {0, 0, 0, 7}, /* VADDW: handled by decodetree */
204
+ {0, 0, 0, 7}, /* VSUBL: handled by decodetree */
205
+ {0, 0, 0, 7}, /* VSUBW: handled by decodetree */
206
{0, 1, 1, 0}, /* VADDHN */
207
{0, 0, 0, 0}, /* VABAL */
208
{0, 1, 1, 0}, /* VSUBHN */
209
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
210
{0, 0, 0, 7}, /* Reserved: always UNDEF */
211
};
212
213
- prewiden = neon_3reg_wide[op][0];
214
src1_wide = neon_3reg_wide[op][1];
215
src2_wide = neon_3reg_wide[op][2];
216
undefreq = neon_3reg_wide[op][3];
217
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
218
} else {
219
tmp = neon_load_reg(rn, pass);
220
}
221
- if (prewiden) {
222
- gen_neon_widen(cpu_V0, tmp, size, u);
223
- }
224
}
225
if (src2_wide) {
226
neon_load_reg64(cpu_V1, rm + pass);
227
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
228
} else {
229
tmp2 = neon_load_reg(rm, pass);
230
}
231
- if (prewiden) {
232
- gen_neon_widen(cpu_V1, tmp2, size, u);
233
- }
234
}
235
switch (op) {
236
case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
237
--
244
--
238
2.20.1
245
2.20.1
239
246
240
247
diff view generated by jsdifflib
1
Convert the Neon VDUP (scalar) insn to decodetree. (Note that we
1
Implement the MVE VCVT insns which convert between floating and fixed
2
can't call this just "VDUP" as we used that already in vfp.decode for
2
point. As with the Neon equivalents, these use essentially the same
3
the "VDUP (general purpose register" insn.)
3
constant encoding as right-shift-by-immediate.
4
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
---
7
---
8
target/arm/neon-dp.decode | 7 +++++++
8
target/arm/helper-mve.h | 9 +++++++++
9
target/arm/translate-neon.inc.c | 26 ++++++++++++++++++++++++++
9
target/arm/mve.decode | 19 +++++++++++++++++++
10
target/arm/translate.c | 25 +------------------------
10
target/arm/mve_helper.c | 36 ++++++++++++++++++++++++++++++++++++
11
3 files changed, 34 insertions(+), 24 deletions(-)
11
target/arm/translate-mve.c | 18 ++++++++++++++++++
12
4 files changed, 82 insertions(+)
12
13
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
16
--- a/target/arm/helper-mve.h
16
+++ b/target/arm/neon-dp.decode
17
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vfma_scalars, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
18
19
19
VTBL 1111 001 1 1 . 11 .... .... 10 len:2 . op:1 . 0 .... \
20
DEF_HELPER_FLAGS_4(mve_vfmas_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
20
vm=%vm_dp vn=%vn_dp vd=%vd_dp
21
DEF_HELPER_FLAGS_4(mve_vfmas_scalars, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
21
+
22
+
22
+ VDUP_scalar 1111 001 1 1 . 11 index:3 1 .... 11 000 q:1 . 0 .... \
23
+DEF_HELPER_FLAGS_4(mve_vcvt_sh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
23
+ vm=%vm_dp vd=%vd_dp size=0
24
+DEF_HELPER_FLAGS_4(mve_vcvt_uh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
+ VDUP_scalar 1111 001 1 1 . 11 index:2 10 .... 11 000 q:1 . 0 .... \
25
+DEF_HELPER_FLAGS_4(mve_vcvt_hs, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
+ vm=%vm_dp vd=%vd_dp size=1
26
+DEF_HELPER_FLAGS_4(mve_vcvt_hu, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
26
+ VDUP_scalar 1111 001 1 1 . 11 index:1 100 .... 11 000 q:1 . 0 .... \
27
+DEF_HELPER_FLAGS_4(mve_vcvt_sf, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
27
+ vm=%vm_dp vd=%vd_dp size=2
28
+DEF_HELPER_FLAGS_4(mve_vcvt_uf, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
28
]
29
+DEF_HELPER_FLAGS_4(mve_vcvt_fs, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
29
30
+DEF_HELPER_FLAGS_4(mve_vcvt_fu, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
30
# Subgroup for size != 0b11
31
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
31
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
32
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/translate-neon.inc.c
33
--- a/target/arm/mve.decode
34
+++ b/target/arm/translate-neon.inc.c
34
+++ b/target/arm/mve.decode
35
@@ -XXX,XX +XXX,XX @@ static bool trans_VTBL(DisasContext *s, arg_VTBL *a)
35
@@ -XXX,XX +XXX,XX @@ VCMLA0 1111 110 00 . 1 . ... 0 ... 0 1000 . 1 . 0 ... 0 @2op_fp_size_
36
tcg_temp_free_i32(tmp);
36
VCMLA90 1111 110 01 . 1 . ... 0 ... 0 1000 . 1 . 0 ... 0 @2op_fp_size_rev
37
return true;
37
VCMLA180 1111 110 10 . 1 . ... 0 ... 0 1000 . 1 . 0 ... 0 @2op_fp_size_rev
38
}
38
VCMLA270 1111 110 11 . 1 . ... 0 ... 0 1000 . 1 . 0 ... 0 @2op_fp_size_rev
39
+
39
+
40
+static bool trans_VDUP_scalar(DisasContext *s, arg_VDUP_scalar *a)
40
+# floating-point <-> fixed-point conversions. Naming convention:
41
+{
41
+# VCVT_<from><to>, S = signed int, U = unsigned int, H = halfprec, F = singleprec
42
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
42
+@vcvt .... .... .. 1 ..... .... .. 1 . .... .... &2shift \
43
+ return false;
43
+ qd=%qd qm=%qm shift=%rshift_i5 size=2
44
+@vcvt_f16 .... .... .. 11 .... .... .. 0 . .... .... &2shift \
45
+ qd=%qd qm=%qm shift=%rshift_i4 size=1
46
+
47
+VCVT_SH_fixed 1110 1111 1 . ...... ... 0 11 . 0 01 . 1 ... 0 @vcvt_f16
48
+VCVT_UH_fixed 1111 1111 1 . ...... ... 0 11 . 0 01 . 1 ... 0 @vcvt_f16
49
+
50
+VCVT_HS_fixed 1110 1111 1 . ...... ... 0 11 . 1 01 . 1 ... 0 @vcvt_f16
51
+VCVT_HU_fixed 1111 1111 1 . ...... ... 0 11 . 1 01 . 1 ... 0 @vcvt_f16
52
+
53
+VCVT_SF_fixed 1110 1111 1 . ...... ... 0 11 . 0 01 . 1 ... 0 @vcvt
54
+VCVT_UF_fixed 1111 1111 1 . ...... ... 0 11 . 0 01 . 1 ... 0 @vcvt
55
+
56
+VCVT_FS_fixed 1110 1111 1 . ...... ... 0 11 . 1 01 . 1 ... 0 @vcvt
57
+VCVT_FU_fixed 1111 1111 1 . ...... ... 0 11 . 1 01 . 1 ... 0 @vcvt
58
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/mve_helper.c
61
+++ b/target/arm/mve_helper.c
62
@@ -XXX,XX +XXX,XX @@ DO_VCMP_FP_BOTH(vfcmpgts, vfcmpgt_scalars, 4, float32, DO_GT32)
63
64
DO_VCMP_FP_BOTH(vfcmpleh, vfcmple_scalarh, 2, float16, !DO_GT16)
65
DO_VCMP_FP_BOTH(vfcmples, vfcmple_scalars, 4, float32, !DO_GT32)
66
+
67
+#define DO_VCVT_FIXED(OP, ESIZE, TYPE, FN) \
68
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vm, \
69
+ uint32_t shift) \
70
+ { \
71
+ TYPE *d = vd, *m = vm; \
72
+ TYPE r; \
73
+ uint16_t mask = mve_element_mask(env); \
74
+ unsigned e; \
75
+ float_status *fpst; \
76
+ float_status scratch_fpst; \
77
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
78
+ if ((mask & MAKE_64BIT_MASK(0, ESIZE)) == 0) { \
79
+ continue; \
80
+ } \
81
+ fpst = (ESIZE == 2) ? &env->vfp.standard_fp_status_f16 : \
82
+ &env->vfp.standard_fp_status; \
83
+ if (!(mask & 1)) { \
84
+ /* We need the result but without updating flags */ \
85
+ scratch_fpst = *fpst; \
86
+ fpst = &scratch_fpst; \
87
+ } \
88
+ r = FN(m[H##ESIZE(e)], shift, fpst); \
89
+ mergemask(&d[H##ESIZE(e)], r, mask); \
90
+ } \
91
+ mve_advance_vpt(env); \
44
+ }
92
+ }
45
+
93
+
46
+ /* UNDEF accesses to D16-D31 if they don't exist. */
94
+DO_VCVT_FIXED(vcvt_sh, 2, int16_t, helper_vfp_shtoh)
47
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
95
+DO_VCVT_FIXED(vcvt_uh, 2, uint16_t, helper_vfp_uhtoh)
48
+ ((a->vd | a->vm) & 0x10)) {
96
+DO_VCVT_FIXED(vcvt_hs, 2, int16_t, helper_vfp_toshh_round_to_zero)
49
+ return false;
97
+DO_VCVT_FIXED(vcvt_hu, 2, uint16_t, helper_vfp_touhh_round_to_zero)
98
+DO_VCVT_FIXED(vcvt_sf, 4, int32_t, helper_vfp_sltos)
99
+DO_VCVT_FIXED(vcvt_uf, 4, uint32_t, helper_vfp_ultos)
100
+DO_VCVT_FIXED(vcvt_fs, 4, int32_t, helper_vfp_tosls_round_to_zero)
101
+DO_VCVT_FIXED(vcvt_fu, 4, uint32_t, helper_vfp_touls_round_to_zero)
102
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
103
index XXXXXXX..XXXXXXX 100644
104
--- a/target/arm/translate-mve.c
105
+++ b/target/arm/translate-mve.c
106
@@ -XXX,XX +XXX,XX @@ DO_2SHIFT(VRSHRI_U, vrshli_u, true)
107
DO_2SHIFT(VSRI, vsri, false)
108
DO_2SHIFT(VSLI, vsli, false)
109
110
+#define DO_2SHIFT_FP(INSN, FN) \
111
+ static bool trans_##INSN(DisasContext *s, arg_2shift *a) \
112
+ { \
113
+ if (!dc_isar_feature(aa32_mve_fp, s)) { \
114
+ return false; \
115
+ } \
116
+ return do_2shift(s, a, gen_helper_mve_##FN, false); \
50
+ }
117
+ }
51
+
118
+
52
+ if (a->vd & a->q) {
119
+DO_2SHIFT_FP(VCVT_SH_fixed, vcvt_sh)
53
+ return false;
120
+DO_2SHIFT_FP(VCVT_UH_fixed, vcvt_uh)
54
+ }
121
+DO_2SHIFT_FP(VCVT_HS_fixed, vcvt_hs)
122
+DO_2SHIFT_FP(VCVT_HU_fixed, vcvt_hu)
123
+DO_2SHIFT_FP(VCVT_SF_fixed, vcvt_sf)
124
+DO_2SHIFT_FP(VCVT_UF_fixed, vcvt_uf)
125
+DO_2SHIFT_FP(VCVT_FS_fixed, vcvt_fs)
126
+DO_2SHIFT_FP(VCVT_FU_fixed, vcvt_fu)
55
+
127
+
56
+ if (!vfp_access_check(s)) {
128
static bool do_2shift_scalar(DisasContext *s, arg_shl_scalar *a,
57
+ return true;
129
MVEGenTwoOpShiftFn *fn)
58
+ }
130
{
59
+
60
+ tcg_gen_gvec_dup_mem(a->size, neon_reg_offset(a->vd, 0),
61
+ neon_element_offset(a->vm, a->index, a->size),
62
+ a->q ? 16 : 8, a->q ? 16 : 8);
63
+ return true;
64
+}
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 int disas_neon_data_insn(DisasContext *s, uint32_t insn)
70
}
71
break;
72
}
73
- } else if ((insn & (1 << 10)) == 0) {
74
- /* VTBL, VTBX: handled by decodetree */
75
- return 1;
76
- } else if ((insn & 0x380) == 0) {
77
- /* VDUP */
78
- int element;
79
- MemOp size;
80
-
81
- if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
82
- return 1;
83
- }
84
- if (insn & (1 << 16)) {
85
- size = MO_8;
86
- element = (insn >> 17) & 7;
87
- } else if (insn & (1 << 17)) {
88
- size = MO_16;
89
- element = (insn >> 18) & 3;
90
- } else {
91
- size = MO_32;
92
- element = (insn >> 19) & 1;
93
- }
94
- tcg_gen_gvec_dup_mem(size, neon_reg_offset(rd, 0),
95
- neon_element_offset(rm, element, size),
96
- q ? 16 : 8, q ? 16 : 8);
97
} else {
98
+ /* VTBL, VTBX, VDUP: handled by decodetree */
99
return 1;
100
}
101
}
102
--
131
--
103
2.20.1
132
2.20.1
104
133
105
134
diff view generated by jsdifflib
1
Convert the Neon 3-reg-diff insns VMULL, VMLAL and VMLSL; these perform
1
Implement the MVE "VCVT (between floating-point and integer)" insn.
2
a 32x32->64 multiply with possible accumulate.
3
4
Note that for VMLSL we do the accumulate directly with a subtraction
5
rather than doing a negate-then-add as the old code did.
6
2
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
---
5
---
10
target/arm/neon-dp.decode | 9 +++++
6
target/arm/mve.decode | 7 +++++++
11
target/arm/translate-neon.inc.c | 71 +++++++++++++++++++++++++++++++++
7
target/arm/translate-mve.c | 32 ++++++++++++++++++++++++++++++++
12
target/arm/translate.c | 21 +++-------
8
2 files changed, 39 insertions(+)
13
3 files changed, 86 insertions(+), 15 deletions(-)
14
9
15
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
10
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
16
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/neon-dp.decode
12
--- a/target/arm/mve.decode
18
+++ b/target/arm/neon-dp.decode
13
+++ b/target/arm/mve.decode
19
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
14
@@ -XXX,XX +XXX,XX @@ VCVT_UF_fixed 1111 1111 1 . ...... ... 0 11 . 0 01 . 1 ... 0 @vcvt
20
15
21
VABDL_S_3d 1111 001 0 1 . .. .... .... 0111 . 0 . 0 .... @3diff
16
VCVT_FS_fixed 1110 1111 1 . ...... ... 0 11 . 1 01 . 1 ... 0 @vcvt
22
VABDL_U_3d 1111 001 1 1 . .. .... .... 0111 . 0 . 0 .... @3diff
17
VCVT_FU_fixed 1111 1111 1 . ...... ... 0 11 . 1 01 . 1 ... 0 @vcvt
23
+
18
+
24
+ VMLAL_S_3d 1111 001 0 1 . .. .... .... 1000 . 0 . 0 .... @3diff
19
+# VCVT between floating point and integer (halfprec and single);
25
+ VMLAL_U_3d 1111 001 1 1 . .. .... .... 1000 . 0 . 0 .... @3diff
20
+# VCVT_<from><to>, S = signed int, U = unsigned int, F = float
26
+
21
+VCVT_SF 1111 1111 1 . 11 .. 11 ... 0 011 00 1 . 0 ... 0 @1op
27
+ VMLSL_S_3d 1111 001 0 1 . .. .... .... 1010 . 0 . 0 .... @3diff
22
+VCVT_UF 1111 1111 1 . 11 .. 11 ... 0 011 01 1 . 0 ... 0 @1op
28
+ VMLSL_U_3d 1111 001 1 1 . .. .... .... 1010 . 0 . 0 .... @3diff
23
+VCVT_FS 1111 1111 1 . 11 .. 11 ... 0 011 10 1 . 0 ... 0 @1op
29
+
24
+VCVT_FU 1111 1111 1 . 11 .. 11 ... 0 011 11 1 . 0 ... 0 @1op
30
+ VMULL_S_3d 1111 001 0 1 . .. .... .... 1100 . 0 . 0 .... @3diff
25
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
31
+ VMULL_U_3d 1111 001 1 1 . .. .... .... 1100 . 0 . 0 .... @3diff
32
]
33
}
34
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
35
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/translate-neon.inc.c
27
--- a/target/arm/translate-mve.c
37
+++ b/target/arm/translate-neon.inc.c
28
+++ b/target/arm/translate-mve.c
38
@@ -XXX,XX +XXX,XX @@ static bool trans_VABAL_U_3d(DisasContext *s, arg_3diff *a)
29
@@ -XXX,XX +XXX,XX @@ DO_1OP(VQNEG, vqneg)
39
30
DO_1OP(VMAXA, vmaxa)
40
return do_long_3d(s, a, opfn[a->size], addfn[a->size]);
31
DO_1OP(VMINA, vmina)
41
}
32
42
+
33
+/*
43
+static void gen_mull_s32(TCGv_i64 rd, TCGv_i32 rn, TCGv_i32 rm)
34
+ * For simple float/int conversions we use the fixed-point
44
+{
35
+ * conversion helpers with a zero shift count
45
+ TCGv_i32 lo = tcg_temp_new_i32();
36
+ */
46
+ TCGv_i32 hi = tcg_temp_new_i32();
37
+#define DO_VCVT(INSN, HFN, SFN) \
47
+
38
+ static void gen_##INSN##h(TCGv_ptr env, TCGv_ptr qd, TCGv_ptr qm) \
48
+ tcg_gen_muls2_i32(lo, hi, rn, rm);
49
+ tcg_gen_concat_i32_i64(rd, lo, hi);
50
+
51
+ tcg_temp_free_i32(lo);
52
+ tcg_temp_free_i32(hi);
53
+}
54
+
55
+static void gen_mull_u32(TCGv_i64 rd, TCGv_i32 rn, TCGv_i32 rm)
56
+{
57
+ TCGv_i32 lo = tcg_temp_new_i32();
58
+ TCGv_i32 hi = tcg_temp_new_i32();
59
+
60
+ tcg_gen_mulu2_i32(lo, hi, rn, rm);
61
+ tcg_gen_concat_i32_i64(rd, lo, hi);
62
+
63
+ tcg_temp_free_i32(lo);
64
+ tcg_temp_free_i32(hi);
65
+}
66
+
67
+static bool trans_VMULL_S_3d(DisasContext *s, arg_3diff *a)
68
+{
69
+ static NeonGenTwoOpWidenFn * const opfn[] = {
70
+ gen_helper_neon_mull_s8,
71
+ gen_helper_neon_mull_s16,
72
+ gen_mull_s32,
73
+ NULL,
74
+ };
75
+
76
+ return do_long_3d(s, a, opfn[a->size], NULL);
77
+}
78
+
79
+static bool trans_VMULL_U_3d(DisasContext *s, arg_3diff *a)
80
+{
81
+ static NeonGenTwoOpWidenFn * const opfn[] = {
82
+ gen_helper_neon_mull_u8,
83
+ gen_helper_neon_mull_u16,
84
+ gen_mull_u32,
85
+ NULL,
86
+ };
87
+
88
+ return do_long_3d(s, a, opfn[a->size], NULL);
89
+}
90
+
91
+#define DO_VMLAL(INSN,MULL,ACC) \
92
+ static bool trans_##INSN##_3d(DisasContext *s, arg_3diff *a) \
93
+ { \
39
+ { \
94
+ static NeonGenTwoOpWidenFn * const opfn[] = { \
40
+ gen_helper_mve_##HFN(env, qd, qm, tcg_constant_i32(0)); \
95
+ gen_helper_neon_##MULL##8, \
41
+ } \
96
+ gen_helper_neon_##MULL##16, \
42
+ static void gen_##INSN##s(TCGv_ptr env, TCGv_ptr qd, TCGv_ptr qm) \
97
+ gen_##MULL##32, \
43
+ { \
44
+ gen_helper_mve_##SFN(env, qd, qm, tcg_constant_i32(0)); \
45
+ } \
46
+ static bool trans_##INSN(DisasContext *s, arg_1op *a) \
47
+ { \
48
+ static MVEGenOneOpFn * const fns[] = { \
49
+ NULL, \
50
+ gen_##INSN##h, \
51
+ gen_##INSN##s, \
98
+ NULL, \
52
+ NULL, \
99
+ }; \
53
+ }; \
100
+ static NeonGenTwo64OpFn * const accfn[] = { \
54
+ if (!dc_isar_feature(aa32_mve_fp, s)) { \
101
+ gen_helper_neon_##ACC##l_u16, \
55
+ return false; \
102
+ gen_helper_neon_##ACC##l_u32, \
56
+ } \
103
+ tcg_gen_##ACC##_i64, \
57
+ return do_1op(s, a, fns[a->size]); \
104
+ NULL, \
105
+ }; \
106
+ return do_long_3d(s, a, opfn[a->size], accfn[a->size]); \
107
+ }
58
+ }
108
+
59
+
109
+DO_VMLAL(VMLAL_S,mull_s,add)
60
+DO_VCVT(VCVT_SF, vcvt_sh, vcvt_sf)
110
+DO_VMLAL(VMLAL_U,mull_u,add)
61
+DO_VCVT(VCVT_UF, vcvt_uh, vcvt_uf)
111
+DO_VMLAL(VMLSL_S,mull_s,sub)
62
+DO_VCVT(VCVT_FS, vcvt_hs, vcvt_fs)
112
+DO_VMLAL(VMLSL_U,mull_u,sub)
63
+DO_VCVT(VCVT_FU, vcvt_hu, vcvt_fu)
113
diff --git a/target/arm/translate.c b/target/arm/translate.c
64
+
114
index XXXXXXX..XXXXXXX 100644
65
/* Narrowing moves: only size 0 and 1 are valid */
115
--- a/target/arm/translate.c
66
#define DO_VMOVN(INSN, FN) \
116
+++ b/target/arm/translate.c
67
static bool trans_##INSN(DisasContext *s, arg_1op *a) \
117
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
118
{0, 0, 0, 7}, /* VABAL */
119
{0, 0, 0, 7}, /* VSUBHN: handled by decodetree */
120
{0, 0, 0, 7}, /* VABDL */
121
- {0, 0, 0, 0}, /* VMLAL */
122
+ {0, 0, 0, 7}, /* VMLAL */
123
{0, 0, 0, 9}, /* VQDMLAL */
124
- {0, 0, 0, 0}, /* VMLSL */
125
+ {0, 0, 0, 7}, /* VMLSL */
126
{0, 0, 0, 9}, /* VQDMLSL */
127
- {0, 0, 0, 0}, /* Integer VMULL */
128
+ {0, 0, 0, 7}, /* Integer VMULL */
129
{0, 0, 0, 9}, /* VQDMULL */
130
{0, 0, 0, 0xa}, /* Polynomial VMULL */
131
{0, 0, 0, 7}, /* Reserved: always UNDEF */
132
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
133
tmp2 = neon_load_reg(rm, pass);
134
}
135
switch (op) {
136
- case 8: case 9: case 10: case 11: case 12: case 13:
137
- /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
138
+ case 9: case 11: case 13:
139
+ /* VQDMLAL, VQDMLSL, VQDMULL */
140
gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
141
break;
142
default: /* 15 is RESERVED: caught earlier */
143
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
144
/* VQDMULL */
145
gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
146
neon_store_reg64(cpu_V0, rd + pass);
147
- } else if (op == 5 || (op >= 8 && op <= 11)) {
148
+ } else {
149
/* Accumulate. */
150
neon_load_reg64(cpu_V1, rd + pass);
151
switch (op) {
152
- case 10: /* VMLSL */
153
- gen_neon_negl(cpu_V0, size);
154
- /* Fall through */
155
- case 8: /* VABAL, VMLAL */
156
- gen_neon_addl(size);
157
- break;
158
case 9: case 11: /* VQDMLAL, VQDMLSL */
159
gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
160
if (op == 11) {
161
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
162
abort();
163
}
164
neon_store_reg64(cpu_V0, rd + pass);
165
- } else {
166
- /* Write back the result. */
167
- neon_store_reg64(cpu_V0, rd + pass);
168
}
169
}
170
} else {
171
--
68
--
172
2.20.1
69
2.20.1
173
70
174
71
diff view generated by jsdifflib
1
Convert the VQRDMLAH and VQRDMLSH insns in the 2-reg-scalar
1
Implement the MVE VCVT which converts from floating-point to integer
2
group to decodetree.
2
using a rounding mode specified by the instruction. We implement
3
this similarly to the Neon equivalents, by passing the required
4
rounding mode as an extra integer parameter to the helper functions.
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
---
8
---
7
target/arm/neon-dp.decode | 3 ++
9
target/arm/helper-mve.h | 5 ++++
8
target/arm/translate-neon.inc.c | 74 +++++++++++++++++++++++++++++++++
10
target/arm/mve.decode | 10 ++++++++
9
target/arm/translate.c | 38 +----------------
11
target/arm/mve_helper.c | 38 ++++++++++++++++++++++++++++
10
3 files changed, 79 insertions(+), 36 deletions(-)
12
target/arm/translate-mve.c | 52 ++++++++++++++++++++++++++++++++++++++
13
4 files changed, 105 insertions(+)
11
14
12
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
15
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
13
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/neon-dp.decode
17
--- a/target/arm/helper-mve.h
15
+++ b/target/arm/neon-dp.decode
18
+++ b/target/arm/helper-mve.h
16
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vminab, TCG_CALL_NO_WG, void, env, ptr, ptr)
17
20
DEF_HELPER_FLAGS_3(mve_vminah, TCG_CALL_NO_WG, void, env, ptr, ptr)
18
VQDMULH_2sc 1111 001 . 1 . .. .... .... 1100 . 1 . 0 .... @2scalar
21
DEF_HELPER_FLAGS_3(mve_vminaw, TCG_CALL_NO_WG, void, env, ptr, ptr)
19
VQRDMULH_2sc 1111 001 . 1 . .. .... .... 1101 . 1 . 0 .... @2scalar
22
23
+DEF_HELPER_FLAGS_4(mve_vcvt_rm_sh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
+DEF_HELPER_FLAGS_4(mve_vcvt_rm_uh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
+DEF_HELPER_FLAGS_4(mve_vcvt_rm_ss, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
26
+DEF_HELPER_FLAGS_4(mve_vcvt_rm_us, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
20
+
27
+
21
+ VQRDMLAH_2sc 1111 001 . 1 . .. .... .... 1110 . 1 . 0 .... @2scalar
28
DEF_HELPER_FLAGS_3(mve_vmovnbb, TCG_CALL_NO_WG, void, env, ptr, ptr)
22
+ VQRDMLSH_2sc 1111 001 . 1 . .. .... .... 1111 . 1 . 0 .... @2scalar
29
DEF_HELPER_FLAGS_3(mve_vmovnbh, TCG_CALL_NO_WG, void, env, ptr, ptr)
23
]
30
DEF_HELPER_FLAGS_3(mve_vmovntb, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
}
31
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
25
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
26
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/translate-neon.inc.c
33
--- a/target/arm/mve.decode
28
+++ b/target/arm/translate-neon.inc.c
34
+++ b/target/arm/mve.decode
29
@@ -XXX,XX +XXX,XX @@ static bool trans_VQRDMULH_2sc(DisasContext *s, arg_2scalar *a)
35
@@ -XXX,XX +XXX,XX @@ VCVT_SF 1111 1111 1 . 11 .. 11 ... 0 011 00 1 . 0 ... 0 @1op
30
36
VCVT_UF 1111 1111 1 . 11 .. 11 ... 0 011 01 1 . 0 ... 0 @1op
31
return do_2scalar(s, a, opfn[a->size], NULL);
37
VCVT_FS 1111 1111 1 . 11 .. 11 ... 0 011 10 1 . 0 ... 0 @1op
32
}
38
VCVT_FU 1111 1111 1 . 11 .. 11 ... 0 011 11 1 . 0 ... 0 @1op
33
+
39
+
34
+static bool do_vqrdmlah_2sc(DisasContext *s, arg_2scalar *a,
40
+# VCVT from floating point to integer with specified rounding mode
35
+ NeonGenThreeOpEnvFn *opfn)
41
+VCVTAS 1111 1111 1 . 11 .. 11 ... 000 00 0 1 . 0 ... 0 @1op
42
+VCVTAU 1111 1111 1 . 11 .. 11 ... 000 00 1 1 . 0 ... 0 @1op
43
+VCVTNS 1111 1111 1 . 11 .. 11 ... 000 01 0 1 . 0 ... 0 @1op
44
+VCVTNU 1111 1111 1 . 11 .. 11 ... 000 01 1 1 . 0 ... 0 @1op
45
+VCVTPS 1111 1111 1 . 11 .. 11 ... 000 10 0 1 . 0 ... 0 @1op
46
+VCVTPU 1111 1111 1 . 11 .. 11 ... 000 10 1 1 . 0 ... 0 @1op
47
+VCVTMS 1111 1111 1 . 11 .. 11 ... 000 11 0 1 . 0 ... 0 @1op
48
+VCVTMU 1111 1111 1 . 11 .. 11 ... 000 11 1 1 . 0 ... 0 @1op
49
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/mve_helper.c
52
+++ b/target/arm/mve_helper.c
53
@@ -XXX,XX +XXX,XX @@ DO_VCVT_FIXED(vcvt_sf, 4, int32_t, helper_vfp_sltos)
54
DO_VCVT_FIXED(vcvt_uf, 4, uint32_t, helper_vfp_ultos)
55
DO_VCVT_FIXED(vcvt_fs, 4, int32_t, helper_vfp_tosls_round_to_zero)
56
DO_VCVT_FIXED(vcvt_fu, 4, uint32_t, helper_vfp_touls_round_to_zero)
57
+
58
+/* VCVT with specified rmode */
59
+#define DO_VCVT_RMODE(OP, ESIZE, TYPE, FN) \
60
+ void HELPER(glue(mve_, OP))(CPUARMState *env, \
61
+ void *vd, void *vm, uint32_t rmode) \
62
+ { \
63
+ TYPE *d = vd, *m = vm; \
64
+ TYPE r; \
65
+ uint16_t mask = mve_element_mask(env); \
66
+ unsigned e; \
67
+ float_status *fpst; \
68
+ float_status scratch_fpst; \
69
+ float_status *base_fpst = (ESIZE == 2) ? \
70
+ &env->vfp.standard_fp_status_f16 : \
71
+ &env->vfp.standard_fp_status; \
72
+ uint32_t prev_rmode = get_float_rounding_mode(base_fpst); \
73
+ set_float_rounding_mode(rmode, base_fpst); \
74
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
75
+ if ((mask & MAKE_64BIT_MASK(0, ESIZE)) == 0) { \
76
+ continue; \
77
+ } \
78
+ fpst = base_fpst; \
79
+ if (!(mask & 1)) { \
80
+ /* We need the result but without updating flags */ \
81
+ scratch_fpst = *fpst; \
82
+ fpst = &scratch_fpst; \
83
+ } \
84
+ r = FN(m[H##ESIZE(e)], 0, fpst); \
85
+ mergemask(&d[H##ESIZE(e)], r, mask); \
86
+ } \
87
+ set_float_rounding_mode(prev_rmode, base_fpst); \
88
+ mve_advance_vpt(env); \
89
+ }
90
+
91
+DO_VCVT_RMODE(vcvt_rm_sh, 2, uint16_t, helper_vfp_toshh)
92
+DO_VCVT_RMODE(vcvt_rm_uh, 2, uint16_t, helper_vfp_touhh)
93
+DO_VCVT_RMODE(vcvt_rm_ss, 4, uint32_t, helper_vfp_tosls)
94
+DO_VCVT_RMODE(vcvt_rm_us, 4, uint32_t, helper_vfp_touls)
95
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
96
index XXXXXXX..XXXXXXX 100644
97
--- a/target/arm/translate-mve.c
98
+++ b/target/arm/translate-mve.c
99
@@ -XXX,XX +XXX,XX @@ typedef void MVEGenCmpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
100
typedef void MVEGenScalarCmpFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
101
typedef void MVEGenVABAVFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
102
typedef void MVEGenDualAccOpFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
103
+typedef void MVEGenVCVTRmodeFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
104
105
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
106
static inline long mve_qreg_offset(unsigned reg)
107
@@ -XXX,XX +XXX,XX @@ DO_VCVT(VCVT_UF, vcvt_uh, vcvt_uf)
108
DO_VCVT(VCVT_FS, vcvt_hs, vcvt_fs)
109
DO_VCVT(VCVT_FU, vcvt_hu, vcvt_fu)
110
111
+static bool do_vcvt_rmode(DisasContext *s, arg_1op *a,
112
+ enum arm_fprounding rmode, bool u)
36
+{
113
+{
37
+ /*
114
+ /*
38
+ * VQRDMLAH/VQRDMLSH: this is like do_2scalar, but the opfn
115
+ * Handle VCVT fp to int with specified rounding mode.
39
+ * performs a kind of fused op-then-accumulate using a helper
116
+ * This is a 1op fn but we must pass the rounding mode as
40
+ * function that takes all of rd, rn and the scalar at once.
117
+ * an immediate to the helper.
41
+ */
118
+ */
42
+ TCGv_i32 scalar;
119
+ TCGv_ptr qd, qm;
43
+ int pass;
120
+ static MVEGenVCVTRmodeFn * const fns[4][2] = {
121
+ { NULL, NULL },
122
+ { gen_helper_mve_vcvt_rm_sh, gen_helper_mve_vcvt_rm_uh },
123
+ { gen_helper_mve_vcvt_rm_ss, gen_helper_mve_vcvt_rm_us },
124
+ { NULL, NULL },
125
+ };
126
+ MVEGenVCVTRmodeFn *fn = fns[a->size][u];
44
+
127
+
45
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
128
+ if (!dc_isar_feature(aa32_mve_fp, s) ||
129
+ !mve_check_qreg_bank(s, a->qd | a->qm) ||
130
+ !fn) {
46
+ return false;
131
+ return false;
47
+ }
132
+ }
48
+
133
+
49
+ if (!dc_isar_feature(aa32_rdm, s)) {
134
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
50
+ return false;
51
+ }
52
+
53
+ /* UNDEF accesses to D16-D31 if they don't exist. */
54
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
55
+ ((a->vd | a->vn | a->vm) & 0x10)) {
56
+ return false;
57
+ }
58
+
59
+ if (!opfn) {
60
+ /* Bad size (including size == 3, which is a different insn group) */
61
+ return false;
62
+ }
63
+
64
+ if (a->q && ((a->vd | a->vn) & 1)) {
65
+ return false;
66
+ }
67
+
68
+ if (!vfp_access_check(s)) {
69
+ return true;
135
+ return true;
70
+ }
136
+ }
71
+
137
+
72
+ scalar = neon_get_scalar(a->size, a->vm);
138
+ qd = mve_qreg_ptr(a->qd);
73
+
139
+ qm = mve_qreg_ptr(a->qm);
74
+ for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
140
+ fn(cpu_env, qd, qm, tcg_constant_i32(arm_rmode_to_sf(rmode)));
75
+ TCGv_i32 rn = neon_load_reg(a->vn, pass);
141
+ tcg_temp_free_ptr(qd);
76
+ TCGv_i32 rd = neon_load_reg(a->vd, pass);
142
+ tcg_temp_free_ptr(qm);
77
+ opfn(rd, cpu_env, rn, scalar, rd);
143
+ mve_update_eci(s);
78
+ tcg_temp_free_i32(rn);
79
+ neon_store_reg(a->vd, pass, rd);
80
+ }
81
+ tcg_temp_free_i32(scalar);
82
+
83
+ return true;
144
+ return true;
84
+}
145
+}
85
+
146
+
86
+static bool trans_VQRDMLAH_2sc(DisasContext *s, arg_2scalar *a)
147
+#define DO_VCVT_RMODE(INSN, RMODE, U) \
87
+{
148
+ static bool trans_##INSN(DisasContext *s, arg_1op *a) \
88
+ static NeonGenThreeOpEnvFn *opfn[] = {
149
+ { \
89
+ NULL,
150
+ return do_vcvt_rmode(s, a, RMODE, U); \
90
+ gen_helper_neon_qrdmlah_s16,
151
+ } \
91
+ gen_helper_neon_qrdmlah_s32,
92
+ NULL,
93
+ };
94
+ return do_vqrdmlah_2sc(s, a, opfn[a->size]);
95
+}
96
+
152
+
97
+static bool trans_VQRDMLSH_2sc(DisasContext *s, arg_2scalar *a)
153
+DO_VCVT_RMODE(VCVTAS, FPROUNDING_TIEAWAY, false)
98
+{
154
+DO_VCVT_RMODE(VCVTAU, FPROUNDING_TIEAWAY, true)
99
+ static NeonGenThreeOpEnvFn *opfn[] = {
155
+DO_VCVT_RMODE(VCVTNS, FPROUNDING_TIEEVEN, false)
100
+ NULL,
156
+DO_VCVT_RMODE(VCVTNU, FPROUNDING_TIEEVEN, true)
101
+ gen_helper_neon_qrdmlsh_s16,
157
+DO_VCVT_RMODE(VCVTPS, FPROUNDING_POSINF, false)
102
+ gen_helper_neon_qrdmlsh_s32,
158
+DO_VCVT_RMODE(VCVTPU, FPROUNDING_POSINF, true)
103
+ NULL,
159
+DO_VCVT_RMODE(VCVTMS, FPROUNDING_NEGINF, false)
104
+ };
160
+DO_VCVT_RMODE(VCVTMU, FPROUNDING_NEGINF, true)
105
+ return do_vqrdmlah_2sc(s, a, opfn[a->size]);
161
+
106
+}
162
/* Narrowing moves: only size 0 and 1 are valid */
107
diff --git a/target/arm/translate.c b/target/arm/translate.c
163
#define DO_VMOVN(INSN, FN) \
108
index XXXXXXX..XXXXXXX 100644
164
static bool trans_##INSN(DisasContext *s, arg_1op *a) \
109
--- a/target/arm/translate.c
110
+++ b/target/arm/translate.c
111
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
112
case 9: /* Floating point VMUL scalar */
113
case 12: /* VQDMULH scalar */
114
case 13: /* VQRDMULH scalar */
115
+ case 14: /* VQRDMLAH scalar */
116
+ case 15: /* VQRDMLSH scalar */
117
return 1; /* handled by decodetree */
118
119
case 3: /* VQDMLAL scalar */
120
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
121
neon_store_reg64(cpu_V0, rd + pass);
122
}
123
break;
124
- case 14: /* VQRDMLAH scalar */
125
- case 15: /* VQRDMLSH scalar */
126
- {
127
- NeonGenThreeOpEnvFn *fn;
128
-
129
- if (!dc_isar_feature(aa32_rdm, s)) {
130
- return 1;
131
- }
132
- if (u && ((rd | rn) & 1)) {
133
- return 1;
134
- }
135
- if (op == 14) {
136
- if (size == 1) {
137
- fn = gen_helper_neon_qrdmlah_s16;
138
- } else {
139
- fn = gen_helper_neon_qrdmlah_s32;
140
- }
141
- } else {
142
- if (size == 1) {
143
- fn = gen_helper_neon_qrdmlsh_s16;
144
- } else {
145
- fn = gen_helper_neon_qrdmlsh_s32;
146
- }
147
- }
148
-
149
- tmp2 = neon_get_scalar(size, rm);
150
- for (pass = 0; pass < (u ? 4 : 2); pass++) {
151
- tmp = neon_load_reg(rn, pass);
152
- tmp3 = neon_load_reg(rd, pass);
153
- fn(tmp, cpu_env, tmp, tmp2, tmp3);
154
- tcg_temp_free_i32(tmp3);
155
- neon_store_reg(rd, pass, tmp);
156
- }
157
- tcg_temp_free_i32(tmp2);
158
- }
159
- break;
160
default:
161
g_assert_not_reached();
162
}
163
--
165
--
164
2.20.1
166
2.20.1
165
167
166
168
diff view generated by jsdifflib
1
Convert the float versions of VMLA, VMLS and VMUL in the Neon
1
Implement the MVE VCVT instruction which converts between single
2
2-reg-scalar group to decodetree.
2
and half precision floating point.
3
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
---
6
As noted in the comment on the WRAP_FP_FN macro, we could have
7
had a do_2scalar_fp() function, but for 3 insns it seemed
8
simpler to just do the wrapping to get hold of the fpstatus ptr.
9
(These are the only fp insns in the group.)
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
---
6
---
12
target/arm/neon-dp.decode | 3 ++
7
target/arm/helper-mve.h | 5 +++
13
target/arm/translate-neon.inc.c | 65 +++++++++++++++++++++++++++++++++
8
target/arm/mve.decode | 8 ++++
14
target/arm/translate.c | 37 ++-----------------
9
target/arm/mve_helper.c | 81 ++++++++++++++++++++++++++++++++++++++
15
3 files changed, 71 insertions(+), 34 deletions(-)
10
target/arm/translate-mve.c | 14 +++++++
11
4 files changed, 108 insertions(+)
16
12
17
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/neon-dp.decode
15
--- a/target/arm/helper-mve.h
20
+++ b/target/arm/neon-dp.decode
16
+++ b/target/arm/helper-mve.h
21
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vcvt_rm_uh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
22
&2scalar vm=%vm_dp vn=%vn_dp vd=%vd_dp
18
DEF_HELPER_FLAGS_4(mve_vcvt_rm_ss, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
23
19
DEF_HELPER_FLAGS_4(mve_vcvt_rm_us, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
VMLA_2sc 1111 001 . 1 . .. .... .... 0000 . 1 . 0 .... @2scalar
20
25
+ VMLA_F_2sc 1111 001 . 1 . .. .... .... 0001 . 1 . 0 .... @2scalar
21
+DEF_HELPER_FLAGS_3(mve_vcvtb_sh, TCG_CALL_NO_WG, void, env, ptr, ptr)
26
22
+DEF_HELPER_FLAGS_3(mve_vcvtt_sh, TCG_CALL_NO_WG, void, env, ptr, ptr)
27
VMLS_2sc 1111 001 . 1 . .. .... .... 0100 . 1 . 0 .... @2scalar
23
+DEF_HELPER_FLAGS_3(mve_vcvtb_hs, TCG_CALL_NO_WG, void, env, ptr, ptr)
28
+ VMLS_F_2sc 1111 001 . 1 . .. .... .... 0101 . 1 . 0 .... @2scalar
24
+DEF_HELPER_FLAGS_3(mve_vcvtt_hs, TCG_CALL_NO_WG, void, env, ptr, ptr)
29
25
+
30
VMUL_2sc 1111 001 . 1 . .. .... .... 1000 . 1 . 0 .... @2scalar
26
DEF_HELPER_FLAGS_3(mve_vmovnbb, TCG_CALL_NO_WG, void, env, ptr, ptr)
31
+ VMUL_F_2sc 1111 001 . 1 . .. .... .... 1001 . 1 . 0 .... @2scalar
27
DEF_HELPER_FLAGS_3(mve_vmovnbh, TCG_CALL_NO_WG, void, env, ptr, ptr)
32
]
28
DEF_HELPER_FLAGS_3(mve_vmovntb, TCG_CALL_NO_WG, void, env, ptr, ptr)
29
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/mve.decode
32
+++ b/target/arm/mve.decode
33
@@ -XXX,XX +XXX,XX @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
34
# The VSHLL T2 encoding is not a @2op pattern, but is here because it
35
# overlaps what would be size=0b11 VMULH/VRMULH
36
{
37
+ VCVTB_SH 111 0 1110 0 . 11 1111 ... 0 1110 0 0 . 0 ... 1 @1op_nosz
38
+
39
VMAXNMA 111 0 1110 0 . 11 1111 ... 0 1110 1 0 . 0 ... 1 @vmaxnma size=2
40
41
VSHLL_BS 111 0 1110 0 . 11 .. 01 ... 0 1110 0 0 . 0 ... 1 @2_shll_esize_b
42
@@ -XXX,XX +XXX,XX @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
33
}
43
}
34
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
44
45
{
46
+ VCVTB_HS 111 1 1110 0 . 11 1111 ... 0 1110 0 0 . 0 ... 1 @1op_nosz
47
+
48
VMAXNMA 111 1 1110 0 . 11 1111 ... 0 1110 1 0 . 0 ... 1 @vmaxnma size=1
49
50
VSHLL_BU 111 1 1110 0 . 11 .. 01 ... 0 1110 0 0 . 0 ... 1 @2_shll_esize_b
51
@@ -XXX,XX +XXX,XX @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
52
}
53
54
{
55
+ VCVTT_SH 111 0 1110 0 . 11 1111 ... 1 1110 0 0 . 0 ... 1 @1op_nosz
56
+
57
VMINNMA 111 0 1110 0 . 11 1111 ... 1 1110 1 0 . 0 ... 1 @vmaxnma size=2
58
VSHLL_TS 111 0 1110 0 . 11 .. 01 ... 1 1110 0 0 . 0 ... 1 @2_shll_esize_b
59
VSHLL_TS 111 0 1110 0 . 11 .. 01 ... 1 1110 0 0 . 0 ... 1 @2_shll_esize_h
60
@@ -XXX,XX +XXX,XX @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
61
}
62
63
{
64
+ VCVTT_HS 111 1 1110 0 . 11 1111 ... 1 1110 0 0 . 0 ... 1 @1op_nosz
65
+
66
VMINNMA 111 1 1110 0 . 11 1111 ... 1 1110 1 0 . 0 ... 1 @vmaxnma size=1
67
VSHLL_TU 111 1 1110 0 . 11 .. 01 ... 1 1110 0 0 . 0 ... 1 @2_shll_esize_b
68
VSHLL_TU 111 1 1110 0 . 11 .. 01 ... 1 1110 0 0 . 0 ... 1 @2_shll_esize_h
69
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
35
index XXXXXXX..XXXXXXX 100644
70
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/translate-neon.inc.c
71
--- a/target/arm/mve_helper.c
37
+++ b/target/arm/translate-neon.inc.c
72
+++ b/target/arm/mve_helper.c
38
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLS_2sc(DisasContext *s, arg_2scalar *a)
73
@@ -XXX,XX +XXX,XX @@ DO_VCVT_RMODE(vcvt_rm_sh, 2, uint16_t, helper_vfp_toshh)
39
74
DO_VCVT_RMODE(vcvt_rm_uh, 2, uint16_t, helper_vfp_touhh)
40
return do_2scalar(s, a, opfn[a->size], accfn[a->size]);
75
DO_VCVT_RMODE(vcvt_rm_ss, 4, uint32_t, helper_vfp_tosls)
41
}
76
DO_VCVT_RMODE(vcvt_rm_us, 4, uint32_t, helper_vfp_touls)
42
+
77
+
43
+/*
78
+/*
44
+ * Rather than have a float-specific version of do_2scalar just for
79
+ * VCVT between halfprec and singleprec. As usual for halfprec
45
+ * three insns, we wrap a NeonGenTwoSingleOpFn to turn it into
80
+ * conversions, FZ16 is ignored and AHP is observed.
46
+ * a NeonGenTwoOpFn.
47
+ */
81
+ */
48
+#define WRAP_FP_FN(WRAPNAME, FUNC) \
82
+static void do_vcvt_sh(CPUARMState *env, void *vd, void *vm, int top)
49
+ static void WRAPNAME(TCGv_i32 rd, TCGv_i32 rn, TCGv_i32 rm) \
83
+{
50
+ { \
84
+ uint16_t *d = vd;
51
+ TCGv_ptr fpstatus = get_fpstatus_ptr(1); \
85
+ uint32_t *m = vm;
52
+ FUNC(rd, rn, rm, fpstatus); \
86
+ uint16_t r;
53
+ tcg_temp_free_ptr(fpstatus); \
87
+ uint16_t mask = mve_element_mask(env);
88
+ bool ieee = !(env->vfp.xregs[ARM_VFP_FPSCR] & FPCR_AHP);
89
+ unsigned e;
90
+ float_status *fpst;
91
+ float_status scratch_fpst;
92
+ float_status *base_fpst = &env->vfp.standard_fp_status;
93
+ bool old_fz = get_flush_to_zero(base_fpst);
94
+ set_flush_to_zero(false, base_fpst);
95
+ for (e = 0; e < 16 / 4; e++, mask >>= 4) {
96
+ if ((mask & MAKE_64BIT_MASK(0, 4)) == 0) {
97
+ continue;
98
+ }
99
+ fpst = base_fpst;
100
+ if (!(mask & 1)) {
101
+ /* We need the result but without updating flags */
102
+ scratch_fpst = *fpst;
103
+ fpst = &scratch_fpst;
104
+ }
105
+ r = float32_to_float16(m[H4(e)], ieee, fpst);
106
+ mergemask(&d[H2(e * 2 + top)], r, mask >> (top * 2));
54
+ }
107
+ }
55
+
108
+ set_flush_to_zero(old_fz, base_fpst);
56
+WRAP_FP_FN(gen_VMUL_F_mul, gen_helper_vfp_muls)
109
+ mve_advance_vpt(env);
57
+WRAP_FP_FN(gen_VMUL_F_add, gen_helper_vfp_adds)
58
+WRAP_FP_FN(gen_VMUL_F_sub, gen_helper_vfp_subs)
59
+
60
+static bool trans_VMUL_F_2sc(DisasContext *s, arg_2scalar *a)
61
+{
62
+ static NeonGenTwoOpFn * const opfn[] = {
63
+ NULL,
64
+ NULL, /* TODO: fp16 support */
65
+ gen_VMUL_F_mul,
66
+ NULL,
67
+ };
68
+
69
+ return do_2scalar(s, a, opfn[a->size], NULL);
70
+}
110
+}
71
+
111
+
72
+static bool trans_VMLA_F_2sc(DisasContext *s, arg_2scalar *a)
112
+static void do_vcvt_hs(CPUARMState *env, void *vd, void *vm, int top)
73
+{
113
+{
74
+ static NeonGenTwoOpFn * const opfn[] = {
114
+ uint32_t *d = vd;
75
+ NULL,
115
+ uint16_t *m = vm;
76
+ NULL, /* TODO: fp16 support */
116
+ uint32_t r;
77
+ gen_VMUL_F_mul,
117
+ uint16_t mask = mve_element_mask(env);
78
+ NULL,
118
+ bool ieee = !(env->vfp.xregs[ARM_VFP_FPSCR] & FPCR_AHP);
79
+ };
119
+ unsigned e;
80
+ static NeonGenTwoOpFn * const accfn[] = {
120
+ float_status *fpst;
81
+ NULL,
121
+ float_status scratch_fpst;
82
+ NULL, /* TODO: fp16 support */
122
+ float_status *base_fpst = &env->vfp.standard_fp_status;
83
+ gen_VMUL_F_add,
123
+ bool old_fiz = get_flush_inputs_to_zero(base_fpst);
84
+ NULL,
124
+ set_flush_inputs_to_zero(false, base_fpst);
85
+ };
125
+ for (e = 0; e < 16 / 4; e++, mask >>= 4) {
86
+
126
+ if ((mask & MAKE_64BIT_MASK(0, 4)) == 0) {
87
+ return do_2scalar(s, a, opfn[a->size], accfn[a->size]);
127
+ continue;
128
+ }
129
+ fpst = base_fpst;
130
+ if (!(mask & (1 << (top * 2)))) {
131
+ /* We need the result but without updating flags */
132
+ scratch_fpst = *fpst;
133
+ fpst = &scratch_fpst;
134
+ }
135
+ r = float16_to_float32(m[H2(e * 2 + top)], ieee, fpst);
136
+ mergemask(&d[H4(e)], r, mask);
137
+ }
138
+ set_flush_inputs_to_zero(old_fiz, base_fpst);
139
+ mve_advance_vpt(env);
88
+}
140
+}
89
+
141
+
90
+static bool trans_VMLS_F_2sc(DisasContext *s, arg_2scalar *a)
142
+void HELPER(mve_vcvtb_sh)(CPUARMState *env, void *vd, void *vm)
91
+{
143
+{
92
+ static NeonGenTwoOpFn * const opfn[] = {
144
+ do_vcvt_sh(env, vd, vm, 0);
93
+ NULL,
145
+}
94
+ NULL, /* TODO: fp16 support */
146
+void HELPER(mve_vcvtt_sh)(CPUARMState *env, void *vd, void *vm)
95
+ gen_VMUL_F_mul,
147
+{
96
+ NULL,
148
+ do_vcvt_sh(env, vd, vm, 1);
97
+ };
149
+}
98
+ static NeonGenTwoOpFn * const accfn[] = {
150
+void HELPER(mve_vcvtb_hs)(CPUARMState *env, void *vd, void *vm)
99
+ NULL,
151
+{
100
+ NULL, /* TODO: fp16 support */
152
+ do_vcvt_hs(env, vd, vm, 0);
101
+ gen_VMUL_F_sub,
153
+}
102
+ NULL,
154
+void HELPER(mve_vcvtt_hs)(CPUARMState *env, void *vd, void *vm)
103
+ };
155
+{
156
+ do_vcvt_hs(env, vd, vm, 1);
157
+}
158
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
159
index XXXXXXX..XXXXXXX 100644
160
--- a/target/arm/translate-mve.c
161
+++ b/target/arm/translate-mve.c
162
@@ -XXX,XX +XXX,XX @@ DO_VCVT_RMODE(VCVTPU, FPROUNDING_POSINF, true)
163
DO_VCVT_RMODE(VCVTMS, FPROUNDING_NEGINF, false)
164
DO_VCVT_RMODE(VCVTMU, FPROUNDING_NEGINF, true)
165
166
+#define DO_VCVT_SH(INSN, FN) \
167
+ static bool trans_##INSN(DisasContext *s, arg_1op *a) \
168
+ { \
169
+ if (!dc_isar_feature(aa32_mve_fp, s)) { \
170
+ return false; \
171
+ } \
172
+ return do_1op(s, a, gen_helper_mve_##FN); \
173
+ } \
104
+
174
+
105
+ return do_2scalar(s, a, opfn[a->size], accfn[a->size]);
175
+DO_VCVT_SH(VCVTB_SH, vcvtb_sh)
106
+}
176
+DO_VCVT_SH(VCVTT_SH, vcvtt_sh)
107
diff --git a/target/arm/translate.c b/target/arm/translate.c
177
+DO_VCVT_SH(VCVTB_HS, vcvtb_hs)
108
index XXXXXXX..XXXXXXX 100644
178
+DO_VCVT_SH(VCVTT_HS, vcvtt_hs)
109
--- a/target/arm/translate.c
110
+++ b/target/arm/translate.c
111
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
112
case 0: /* Integer VMLA scalar */
113
case 4: /* Integer VMLS scalar */
114
case 8: /* Integer VMUL scalar */
115
- return 1; /* handled by decodetree */
116
-
117
case 1: /* Float VMLA scalar */
118
case 5: /* Floating point VMLS scalar */
119
case 9: /* Floating point VMUL scalar */
120
- if (size == 1) {
121
- return 1;
122
- }
123
- /* fall through */
124
+ return 1; /* handled by decodetree */
125
+
179
+
126
case 12: /* VQDMULH scalar */
180
/* Narrowing moves: only size 0 and 1 are valid */
127
case 13: /* VQRDMULH scalar */
181
#define DO_VMOVN(INSN, FN) \
128
if (u && ((rd | rn) & 1)) {
182
static bool trans_##INSN(DisasContext *s, arg_1op *a) \
129
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
130
} else {
131
gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
132
}
133
- } else if (op == 13) {
134
+ } else {
135
if (size == 1) {
136
gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
137
} else {
138
gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
139
}
140
- } else {
141
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
142
- gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
143
- tcg_temp_free_ptr(fpstatus);
144
}
145
tcg_temp_free_i32(tmp2);
146
- if (op < 8) {
147
- /* Accumulate. */
148
- tmp2 = neon_load_reg(rd, pass);
149
- switch (op) {
150
- case 1:
151
- {
152
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
153
- gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
154
- tcg_temp_free_ptr(fpstatus);
155
- break;
156
- }
157
- case 5:
158
- {
159
- TCGv_ptr fpstatus = get_fpstatus_ptr(1);
160
- gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
161
- tcg_temp_free_ptr(fpstatus);
162
- break;
163
- }
164
- default:
165
- abort();
166
- }
167
- tcg_temp_free_i32(tmp2);
168
- }
169
neon_store_reg(rd, pass, tmp);
170
}
171
break;
172
--
183
--
173
2.20.1
184
2.20.1
174
185
175
186
diff view generated by jsdifflib
1
Convert the VQDMULH and VQRDMULH insns in the 2-reg-scalar group
1
Implement the MVE VRINT insns, which round floating point inputs
2
to decodetree.
2
to integer values, leaving them in floating point format.
3
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
---
6
---
7
target/arm/neon-dp.decode | 3 +++
7
target/arm/helper-mve.h | 6 +++++
8
target/arm/translate-neon.inc.c | 29 +++++++++++++++++++++++
8
target/arm/mve.decode | 7 ++++++
9
target/arm/translate.c | 42 ++-------------------------------
9
target/arm/mve_helper.c | 35 +++++++++++++++++++++++++++++
10
3 files changed, 34 insertions(+), 40 deletions(-)
10
target/arm/translate-mve.c | 45 ++++++++++++++++++++++++++++++++++++++
11
4 files changed, 93 insertions(+)
11
12
12
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
13
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/neon-dp.decode
15
--- a/target/arm/helper-mve.h
15
+++ b/target/arm/neon-dp.decode
16
+++ b/target/arm/helper-mve.h
16
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vcvt_sf, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
17
18
DEF_HELPER_FLAGS_4(mve_vcvt_uf, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
18
VMUL_2sc 1111 001 . 1 . .. .... .... 1000 . 1 . 0 .... @2scalar
19
DEF_HELPER_FLAGS_4(mve_vcvt_fs, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
19
VMUL_F_2sc 1111 001 . 1 . .. .... .... 1001 . 1 . 0 .... @2scalar
20
DEF_HELPER_FLAGS_4(mve_vcvt_fu, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
20
+
21
+
21
+ VQDMULH_2sc 1111 001 . 1 . .. .... .... 1100 . 1 . 0 .... @2scalar
22
+DEF_HELPER_FLAGS_4(mve_vrint_rm_h, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
22
+ VQRDMULH_2sc 1111 001 . 1 . .. .... .... 1101 . 1 . 0 .... @2scalar
23
+DEF_HELPER_FLAGS_4(mve_vrint_rm_s, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
23
]
24
+
24
}
25
+DEF_HELPER_FLAGS_3(mve_vrintx_h, TCG_CALL_NO_WG, void, env, ptr, ptr)
25
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
26
+DEF_HELPER_FLAGS_3(mve_vrintx_s, TCG_CALL_NO_WG, void, env, ptr, ptr)
27
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
26
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/translate-neon.inc.c
29
--- a/target/arm/mve.decode
28
+++ b/target/arm/translate-neon.inc.c
30
+++ b/target/arm/mve.decode
29
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLS_F_2sc(DisasContext *s, arg_2scalar *a)
31
@@ -XXX,XX +XXX,XX @@ VCVTPS 1111 1111 1 . 11 .. 11 ... 000 10 0 1 . 0 ... 0 @1op
30
32
VCVTPU 1111 1111 1 . 11 .. 11 ... 000 10 1 1 . 0 ... 0 @1op
31
return do_2scalar(s, a, opfn[a->size], accfn[a->size]);
33
VCVTMS 1111 1111 1 . 11 .. 11 ... 000 11 0 1 . 0 ... 0 @1op
34
VCVTMU 1111 1111 1 . 11 .. 11 ... 000 11 1 1 . 0 ... 0 @1op
35
+
36
+VRINTN 1111 1111 1 . 11 .. 10 ... 001 000 1 . 0 ... 0 @1op
37
+VRINTX 1111 1111 1 . 11 .. 10 ... 001 001 1 . 0 ... 0 @1op
38
+VRINTA 1111 1111 1 . 11 .. 10 ... 001 010 1 . 0 ... 0 @1op
39
+VRINTZ 1111 1111 1 . 11 .. 10 ... 001 011 1 . 0 ... 0 @1op
40
+VRINTM 1111 1111 1 . 11 .. 10 ... 001 101 1 . 0 ... 0 @1op
41
+VRINTP 1111 1111 1 . 11 .. 10 ... 001 111 1 . 0 ... 0 @1op
42
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/mve_helper.c
45
+++ b/target/arm/mve_helper.c
46
@@ -XXX,XX +XXX,XX @@ DO_VCVT_RMODE(vcvt_rm_uh, 2, uint16_t, helper_vfp_touhh)
47
DO_VCVT_RMODE(vcvt_rm_ss, 4, uint32_t, helper_vfp_tosls)
48
DO_VCVT_RMODE(vcvt_rm_us, 4, uint32_t, helper_vfp_touls)
49
50
+#define DO_VRINT_RM_H(M, F, S) helper_rinth(M, S)
51
+#define DO_VRINT_RM_S(M, F, S) helper_rints(M, S)
52
+
53
+DO_VCVT_RMODE(vrint_rm_h, 2, uint16_t, DO_VRINT_RM_H)
54
+DO_VCVT_RMODE(vrint_rm_s, 4, uint32_t, DO_VRINT_RM_S)
55
+
56
/*
57
* VCVT between halfprec and singleprec. As usual for halfprec
58
* conversions, FZ16 is ignored and AHP is observed.
59
@@ -XXX,XX +XXX,XX @@ void HELPER(mve_vcvtt_hs)(CPUARMState *env, void *vd, void *vm)
60
{
61
do_vcvt_hs(env, vd, vm, 1);
32
}
62
}
33
+
63
+
34
+WRAP_ENV_FN(gen_VQDMULH_16, gen_helper_neon_qdmulh_s16)
64
+#define DO_1OP_FP(OP, ESIZE, TYPE, FN) \
35
+WRAP_ENV_FN(gen_VQDMULH_32, gen_helper_neon_qdmulh_s32)
65
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vm) \
36
+WRAP_ENV_FN(gen_VQRDMULH_16, gen_helper_neon_qrdmulh_s16)
66
+ { \
37
+WRAP_ENV_FN(gen_VQRDMULH_32, gen_helper_neon_qrdmulh_s32)
67
+ TYPE *d = vd, *m = vm; \
68
+ TYPE r; \
69
+ uint16_t mask = mve_element_mask(env); \
70
+ unsigned e; \
71
+ float_status *fpst; \
72
+ float_status scratch_fpst; \
73
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
74
+ if ((mask & MAKE_64BIT_MASK(0, ESIZE)) == 0) { \
75
+ continue; \
76
+ } \
77
+ fpst = (ESIZE == 2) ? &env->vfp.standard_fp_status_f16 : \
78
+ &env->vfp.standard_fp_status; \
79
+ if (!(mask & 1)) { \
80
+ /* We need the result but without updating flags */ \
81
+ scratch_fpst = *fpst; \
82
+ fpst = &scratch_fpst; \
83
+ } \
84
+ r = FN(m[H##ESIZE(e)], fpst); \
85
+ mergemask(&d[H##ESIZE(e)], r, mask); \
86
+ } \
87
+ mve_advance_vpt(env); \
88
+ }
38
+
89
+
39
+static bool trans_VQDMULH_2sc(DisasContext *s, arg_2scalar *a)
90
+DO_1OP_FP(vrintx_h, 2, float16, float16_round_to_int)
91
+DO_1OP_FP(vrintx_s, 4, float32, float32_round_to_int)
92
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
93
index XXXXXXX..XXXXXXX 100644
94
--- a/target/arm/translate-mve.c
95
+++ b/target/arm/translate-mve.c
96
@@ -XXX,XX +XXX,XX @@ DO_VCVT_SH(VCVTT_SH, vcvtt_sh)
97
DO_VCVT_SH(VCVTB_HS, vcvtb_hs)
98
DO_VCVT_SH(VCVTT_HS, vcvtt_hs)
99
100
+#define DO_VRINT(INSN, RMODE) \
101
+ static void gen_##INSN##h(TCGv_ptr env, TCGv_ptr qd, TCGv_ptr qm) \
102
+ { \
103
+ gen_helper_mve_vrint_rm_h(env, qd, qm, \
104
+ tcg_constant_i32(arm_rmode_to_sf(RMODE))); \
105
+ } \
106
+ static void gen_##INSN##s(TCGv_ptr env, TCGv_ptr qd, TCGv_ptr qm) \
107
+ { \
108
+ gen_helper_mve_vrint_rm_s(env, qd, qm, \
109
+ tcg_constant_i32(arm_rmode_to_sf(RMODE))); \
110
+ } \
111
+ static bool trans_##INSN(DisasContext *s, arg_1op *a) \
112
+ { \
113
+ static MVEGenOneOpFn * const fns[] = { \
114
+ NULL, \
115
+ gen_##INSN##h, \
116
+ gen_##INSN##s, \
117
+ NULL, \
118
+ }; \
119
+ if (!dc_isar_feature(aa32_mve_fp, s)) { \
120
+ return false; \
121
+ } \
122
+ return do_1op(s, a, fns[a->size]); \
123
+ }
124
+
125
+DO_VRINT(VRINTN, FPROUNDING_TIEEVEN)
126
+DO_VRINT(VRINTA, FPROUNDING_TIEAWAY)
127
+DO_VRINT(VRINTZ, FPROUNDING_ZERO)
128
+DO_VRINT(VRINTM, FPROUNDING_NEGINF)
129
+DO_VRINT(VRINTP, FPROUNDING_POSINF)
130
+
131
+static bool trans_VRINTX(DisasContext *s, arg_1op *a)
40
+{
132
+{
41
+ static NeonGenTwoOpFn * const opfn[] = {
133
+ static MVEGenOneOpFn * const fns[] = {
42
+ NULL,
134
+ NULL,
43
+ gen_VQDMULH_16,
135
+ gen_helper_mve_vrintx_h,
44
+ gen_VQDMULH_32,
136
+ gen_helper_mve_vrintx_s,
45
+ NULL,
137
+ NULL,
46
+ };
138
+ };
47
+
139
+ if (!dc_isar_feature(aa32_mve_fp, s)) {
48
+ return do_2scalar(s, a, opfn[a->size], NULL);
140
+ return false;
141
+ }
142
+ return do_1op(s, a, fns[a->size]);
49
+}
143
+}
50
+
144
+
51
+static bool trans_VQRDMULH_2sc(DisasContext *s, arg_2scalar *a)
145
/* Narrowing moves: only size 0 and 1 are valid */
52
+{
146
#define DO_VMOVN(INSN, FN) \
53
+ static NeonGenTwoOpFn * const opfn[] = {
147
static bool trans_##INSN(DisasContext *s, arg_1op *a) \
54
+ NULL,
55
+ gen_VQRDMULH_16,
56
+ gen_VQRDMULH_32,
57
+ NULL,
58
+ };
59
+
60
+ return do_2scalar(s, a, opfn[a->size], NULL);
61
+}
62
diff --git a/target/arm/translate.c b/target/arm/translate.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/target/arm/translate.c
65
+++ b/target/arm/translate.c
66
@@ -XXX,XX +XXX,XX @@ static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
67
68
#define CPU_V001 cpu_V0, cpu_V0, cpu_V1
69
70
-static TCGv_i32 neon_load_scratch(int scratch)
71
-{
72
- TCGv_i32 tmp = tcg_temp_new_i32();
73
- tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
74
- return tmp;
75
-}
76
-
77
-static void neon_store_scratch(int scratch, TCGv_i32 var)
78
-{
79
- tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
80
- tcg_temp_free_i32(var);
81
-}
82
-
83
static int gen_neon_unzip(int rd, int rm, int size, int q)
84
{
85
TCGv_ptr pd, pm;
86
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
87
case 1: /* Float VMLA scalar */
88
case 5: /* Floating point VMLS scalar */
89
case 9: /* Floating point VMUL scalar */
90
- return 1; /* handled by decodetree */
91
-
92
case 12: /* VQDMULH scalar */
93
case 13: /* VQRDMULH scalar */
94
- if (u && ((rd | rn) & 1)) {
95
- return 1;
96
- }
97
- tmp = neon_get_scalar(size, rm);
98
- neon_store_scratch(0, tmp);
99
- for (pass = 0; pass < (u ? 4 : 2); pass++) {
100
- tmp = neon_load_scratch(0);
101
- tmp2 = neon_load_reg(rn, pass);
102
- if (op == 12) {
103
- if (size == 1) {
104
- gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
105
- } else {
106
- gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
107
- }
108
- } else {
109
- if (size == 1) {
110
- gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
111
- } else {
112
- gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
113
- }
114
- }
115
- tcg_temp_free_i32(tmp2);
116
- neon_store_reg(rd, pass, tmp);
117
- }
118
- break;
119
+ return 1; /* handled by decodetree */
120
+
121
case 3: /* VQDMLAL scalar */
122
case 7: /* VQDMLSL scalar */
123
case 11: /* VQDMULL scalar */
124
--
148
--
125
2.20.1
149
2.20.1
126
150
127
151
diff view generated by jsdifflib
1
In commit 37bfce81b10450071 we accidentally introduced a leak of a TCG
1
We now have a complete MVE emulation, so we can enable it in our
2
temporary in do_2shift_env_64(); free it.
2
Cortex-M55 model by setting the ID registers to match those of a
3
Cortex-M55 with full MVE support.
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
---
7
---
7
target/arm/translate-neon.inc.c | 1 +
8
target/arm/cpu_tcg.c | 7 ++-----
8
1 file changed, 1 insertion(+)
9
1 file changed, 2 insertions(+), 5 deletions(-)
9
10
10
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
11
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
11
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
12
--- a/target/arm/translate-neon.inc.c
13
--- a/target/arm/cpu_tcg.c
13
+++ b/target/arm/translate-neon.inc.c
14
+++ b/target/arm/cpu_tcg.c
14
@@ -XXX,XX +XXX,XX @@ static bool do_2shift_env_64(DisasContext *s, arg_2reg_shift *a,
15
@@ -XXX,XX +XXX,XX @@ static void cortex_m55_initfn(Object *obj)
15
neon_load_reg64(tmp, a->vm + pass);
16
cpu->revidr = 0;
16
fn(tmp, cpu_env, tmp, constimm);
17
cpu->pmsav7_dregion = 16;
17
neon_store_reg64(tmp, a->vd + pass);
18
cpu->sau_sregion = 8;
18
+ tcg_temp_free_i64(tmp);
19
- /*
19
}
20
- * These are the MVFR* values for the FPU, no MVE configuration;
20
tcg_temp_free_i64(constimm);
21
- * we will update them later when we implement MVE
21
return true;
22
- */
23
+ /* These are the MVFR* values for the FPU + full MVE configuration */
24
cpu->isar.mvfr0 = 0x10110221;
25
- cpu->isar.mvfr1 = 0x12100011;
26
+ cpu->isar.mvfr1 = 0x12100211;
27
cpu->isar.mvfr2 = 0x00000040;
28
cpu->isar.id_pfr0 = 0x20000030;
29
cpu->isar.id_pfr1 = 0x00000230;
22
--
30
--
23
2.20.1
31
2.20.1
24
32
25
33
diff view generated by jsdifflib
1
From: fangying <fangying1@huawei.com>
1
From: Shuuichirou Ishii <ishii.shuuichir@fujitsu.com>
2
2
3
Virtual time adjustment was implemented for virt-5.0 machine type,
3
Add a definition for the Fujitsu A64FX processor.
4
but the cpu property was enabled only for host-passthrough and max
5
cpu model. Let's add it for any KVM arm cpu which has the generic
6
timer feature enabled.
7
4
8
Signed-off-by: Ying Fang <fangying1@huawei.com>
5
The A64FX processor does not implement the AArch32 Execution state,
6
so there are no associated AArch32 Identification registers.
7
8
For SVE, the A64FX processor supports only 128,256 and 512bit vector
9
lengths.
10
11
The Identification register values are defined based on the FX700,
12
and have been tested and confirmed.
13
14
Signed-off-by: Shuuichirou Ishii <ishii.shuuichir@fujitsu.com>
9
Reviewed-by: Andrew Jones <drjones@redhat.com>
15
Reviewed-by: Andrew Jones <drjones@redhat.com>
10
Message-id: 20200608121243.2076-1-fangying1@huawei.com
11
[PMM: minor commit message tweak, removed inaccurate
12
suggested-by tag]
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
17
---
15
target/arm/cpu.c | 6 ++++--
18
target/arm/cpu64.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++
16
target/arm/cpu64.c | 1 -
19
1 file changed, 48 insertions(+)
17
target/arm/kvm.c | 21 +++++++++++----------
18
3 files changed, 15 insertions(+), 13 deletions(-)
19
20
20
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.c
23
+++ b/target/arm/cpu.c
24
@@ -XXX,XX +XXX,XX @@ void arm_cpu_post_init(Object *obj)
25
if (arm_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER)) {
26
qdev_property_add_static(DEVICE(cpu), &arm_cpu_gt_cntfrq_property);
27
}
28
+
29
+ if (kvm_enabled()) {
30
+ kvm_arm_add_vcpu_properties(obj);
31
+ }
32
}
33
34
static void arm_cpu_finalizefn(Object *obj)
35
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
36
37
if (kvm_enabled()) {
38
kvm_arm_set_cpu_features_from_host(cpu);
39
- kvm_arm_add_vcpu_properties(obj);
40
} else {
41
cortex_a15_initfn(obj);
42
43
@@ -XXX,XX +XXX,XX @@ static void arm_host_initfn(Object *obj)
44
if (arm_feature(&cpu->env, ARM_FEATURE_AARCH64)) {
45
aarch64_add_sve_properties(obj);
46
}
47
- kvm_arm_add_vcpu_properties(obj);
48
arm_cpu_post_init(obj);
49
}
50
51
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
21
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
52
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/cpu64.c
23
--- a/target/arm/cpu64.c
54
+++ b/target/arm/cpu64.c
24
+++ b/target/arm/cpu64.c
55
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
25
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
56
26
cpu_max_set_sve_max_vq, NULL, NULL);
57
if (kvm_enabled()) {
27
}
58
kvm_arm_set_cpu_features_from_host(cpu);
28
59
- kvm_arm_add_vcpu_properties(obj);
29
+static void aarch64_a64fx_initfn(Object *obj)
60
} else {
30
+{
61
uint64_t t;
62
uint32_t u;
63
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/kvm.c
66
+++ b/target/arm/kvm.c
67
@@ -XXX,XX +XXX,XX @@ static void kvm_no_adjvtime_set(Object *obj, bool value, Error **errp)
68
/* KVM VCPU properties should be prefixed with "kvm-". */
69
void kvm_arm_add_vcpu_properties(Object *obj)
70
{
71
- if (!kvm_enabled()) {
72
- return;
73
- }
74
+ ARMCPU *cpu = ARM_CPU(obj);
31
+ ARMCPU *cpu = ARM_CPU(obj);
75
+ CPUARMState *env = &cpu->env;
32
+
76
33
+ cpu->dtb_compatible = "arm,a64fx";
77
- ARM_CPU(obj)->kvm_adjvtime = true;
34
+ set_feature(&cpu->env, ARM_FEATURE_V8);
78
- object_property_add_bool(obj, "kvm-no-adjvtime", kvm_no_adjvtime_get,
35
+ set_feature(&cpu->env, ARM_FEATURE_NEON);
79
- kvm_no_adjvtime_set);
36
+ set_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER);
80
- object_property_set_description(obj, "kvm-no-adjvtime",
37
+ set_feature(&cpu->env, ARM_FEATURE_AARCH64);
81
- "Set on to disable the adjustment of "
38
+ set_feature(&cpu->env, ARM_FEATURE_EL2);
82
- "the virtual counter. VM stopped time "
39
+ set_feature(&cpu->env, ARM_FEATURE_EL3);
83
- "will be counted.");
40
+ set_feature(&cpu->env, ARM_FEATURE_PMU);
84
+ if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
41
+ cpu->midr = 0x461f0010;
85
+ cpu->kvm_adjvtime = true;
42
+ cpu->revidr = 0x00000000;
86
+ object_property_add_bool(obj, "kvm-no-adjvtime", kvm_no_adjvtime_get,
43
+ cpu->ctr = 0x86668006;
87
+ kvm_no_adjvtime_set);
44
+ cpu->reset_sctlr = 0x30000180;
88
+ object_property_set_description(obj, "kvm-no-adjvtime",
45
+ cpu->isar.id_aa64pfr0 = 0x0000000101111111; /* No RAS Extensions */
89
+ "Set on to disable the adjustment of "
46
+ cpu->isar.id_aa64pfr1 = 0x0000000000000000;
90
+ "the virtual counter. VM stopped time "
47
+ cpu->isar.id_aa64dfr0 = 0x0000000010305408;
91
+ "will be counted.");
48
+ cpu->isar.id_aa64dfr1 = 0x0000000000000000;
92
+ }
49
+ cpu->id_aa64afr0 = 0x0000000000000000;
93
}
50
+ cpu->id_aa64afr1 = 0x0000000000000000;
94
51
+ cpu->isar.id_aa64mmfr0 = 0x0000000000001122;
95
bool kvm_arm_pmu_supported(CPUState *cpu)
52
+ cpu->isar.id_aa64mmfr1 = 0x0000000011212100;
53
+ cpu->isar.id_aa64mmfr2 = 0x0000000000001011;
54
+ cpu->isar.id_aa64isar0 = 0x0000000010211120;
55
+ cpu->isar.id_aa64isar1 = 0x0000000000010001;
56
+ cpu->isar.id_aa64zfr0 = 0x0000000000000000;
57
+ cpu->clidr = 0x0000000080000023;
58
+ cpu->ccsidr[0] = 0x7007e01c; /* 64KB L1 dcache */
59
+ cpu->ccsidr[1] = 0x2007e01c; /* 64KB L1 icache */
60
+ cpu->ccsidr[2] = 0x70ffe07c; /* 8MB L2 cache */
61
+ cpu->dcz_blocksize = 6; /* 256 bytes */
62
+ cpu->gic_num_lrs = 4;
63
+ cpu->gic_vpribits = 5;
64
+ cpu->gic_vprebits = 5;
65
+
66
+ /* Suppport of A64FX's vector length are 128,256 and 512bit only */
67
+ aarch64_add_sve_properties(obj);
68
+ bitmap_zero(cpu->sve_vq_supported, ARM_MAX_VQ);
69
+ set_bit(0, cpu->sve_vq_supported); /* 128bit */
70
+ set_bit(1, cpu->sve_vq_supported); /* 256bit */
71
+ set_bit(3, cpu->sve_vq_supported); /* 512bit */
72
+
73
+ /* TODO: Add A64FX specific HPC extension registers */
74
+}
75
+
76
static const ARMCPUInfo aarch64_cpus[] = {
77
{ .name = "cortex-a57", .initfn = aarch64_a57_initfn },
78
{ .name = "cortex-a53", .initfn = aarch64_a53_initfn },
79
{ .name = "cortex-a72", .initfn = aarch64_a72_initfn },
80
+ { .name = "a64fx", .initfn = aarch64_a64fx_initfn },
81
{ .name = "max", .initfn = aarch64_max_initfn },
82
};
83
96
--
84
--
97
2.20.1
85
2.20.1
98
86
99
87
diff view generated by jsdifflib
1
From: Guenter Roeck <linux@roeck-us.net>
1
From: Shuuichirou Ishii <ishii.shuuichir@fujitsu.com>
2
2
3
The Linux kernel's IMX code now uses vendor specific commands.
3
Add -cpu a64fx to use A64FX processor when -machine virt option is
4
This results in endless warnings when booting the Linux kernel.
4
specified. In addition, add a64fx to the Supported guest CPU types
5
in the virt.rst document.
5
6
6
sdhci-esdhc-imx 2194000.usdhc: esdhc_wait_for_card_clock_gate_off:
7
Signed-off-by: Shuuichirou Ishii <ishii.shuuichir@fujitsu.com>
7
    card clock still not gate off in 100us!.
8
Reviewed-by: Andrew Jones <drjones@redhat.com>
8
9
Implement support for the vendor specific command implemented in IMX hardware
10
to be able to avoid this warning.
11
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
15
Message-id: 20200603145258.195920-2-linux@roeck-us.net
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
10
---
18
hw/sd/sdhci-internal.h | 5 +++++
11
docs/system/arm/virt.rst | 1 +
19
include/hw/sd/sdhci.h | 5 +++++
12
hw/arm/virt.c | 1 +
20
hw/sd/sdhci.c | 18 +++++++++++++++++-
13
2 files changed, 2 insertions(+)
21
3 files changed, 27 insertions(+), 1 deletion(-)
22
14
23
diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
15
diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
24
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/sd/sdhci-internal.h
17
--- a/docs/system/arm/virt.rst
26
+++ b/hw/sd/sdhci-internal.h
18
+++ b/docs/system/arm/virt.rst
27
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ Supported guest CPU types:
28
#define SDHC_CMD_INHIBIT 0x00000001
20
- ``cortex-a53`` (64-bit)
29
#define SDHC_DATA_INHIBIT 0x00000002
21
- ``cortex-a57`` (64-bit)
30
#define SDHC_DAT_LINE_ACTIVE 0x00000004
22
- ``cortex-a72`` (64-bit)
31
+#define SDHC_IMX_CLOCK_GATE_OFF 0x00000080
23
+- ``a64fx`` (64-bit)
32
#define SDHC_DOING_WRITE 0x00000100
24
- ``host`` (with KVM only)
33
#define SDHC_DOING_READ 0x00000200
25
- ``max`` (same as ``host`` for KVM; best possible emulation with TCG)
34
#define SDHC_SPACE_AVAILABLE 0x00000400
26
35
@@ -XXX,XX +XXX,XX @@ extern const VMStateDescription sdhci_vmstate;
27
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
36
37
38
#define ESDHC_MIX_CTRL 0x48
39
+
40
#define ESDHC_VENDOR_SPEC 0xc0
41
+#define ESDHC_IMX_FRC_SDCLK_ON (1 << 8)
42
+
43
#define ESDHC_DLL_CTRL 0x60
44
45
#define ESDHC_TUNING_CTRL 0xcc
46
@@ -XXX,XX +XXX,XX @@ extern const VMStateDescription sdhci_vmstate;
47
#define DEFINE_SDHCI_COMMON_PROPERTIES(_state) \
48
DEFINE_PROP_UINT8("sd-spec-version", _state, sd_spec_version, 2), \
49
DEFINE_PROP_UINT8("uhs", _state, uhs_mode, UHS_NOT_SUPPORTED), \
50
+ DEFINE_PROP_UINT8("vendor", _state, vendor, SDHCI_VENDOR_NONE), \
51
\
52
/* Capabilities registers provide information on supported
53
* features of this specific host controller implementation */ \
54
diff --git a/include/hw/sd/sdhci.h b/include/hw/sd/sdhci.h
55
index XXXXXXX..XXXXXXX 100644
28
index XXXXXXX..XXXXXXX 100644
56
--- a/include/hw/sd/sdhci.h
29
--- a/hw/arm/virt.c
57
+++ b/include/hw/sd/sdhci.h
30
+++ b/hw/arm/virt.c
58
@@ -XXX,XX +XXX,XX @@ typedef struct SDHCIState {
31
@@ -XXX,XX +XXX,XX @@ static const char *valid_cpus[] = {
59
uint16_t acmd12errsts; /* Auto CMD12 error status register */
32
ARM_CPU_TYPE_NAME("cortex-a53"),
60
uint16_t hostctl2; /* Host Control 2 */
33
ARM_CPU_TYPE_NAME("cortex-a57"),
61
uint64_t admasysaddr; /* ADMA System Address Register */
34
ARM_CPU_TYPE_NAME("cortex-a72"),
62
+ uint16_t vendor_spec; /* Vendor specific register */
35
+ ARM_CPU_TYPE_NAME("a64fx"),
63
36
ARM_CPU_TYPE_NAME("host"),
64
/* Read-only registers */
37
ARM_CPU_TYPE_NAME("max"),
65
uint64_t capareg; /* Capabilities Register */
38
};
66
@@ -XXX,XX +XXX,XX @@ typedef struct SDHCIState {
67
uint32_t quirks;
68
uint8_t sd_spec_version;
69
uint8_t uhs_mode;
70
+ uint8_t vendor; /* For vendor specific functionality */
71
} SDHCIState;
72
73
+#define SDHCI_VENDOR_NONE 0
74
+#define SDHCI_VENDOR_IMX 1
75
+
76
/*
77
* Controller does not provide transfer-complete interrupt when not
78
* busy.
79
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/hw/sd/sdhci.c
82
+++ b/hw/sd/sdhci.c
83
@@ -XXX,XX +XXX,XX @@ static uint64_t usdhc_read(void *opaque, hwaddr offset, unsigned size)
84
}
85
break;
86
87
+ case ESDHC_VENDOR_SPEC:
88
+ ret = s->vendor_spec;
89
+ break;
90
case ESDHC_DLL_CTRL:
91
case ESDHC_TUNE_CTRL_STATUS:
92
case ESDHC_UNDOCUMENTED_REG27:
93
case ESDHC_TUNING_CTRL:
94
- case ESDHC_VENDOR_SPEC:
95
case ESDHC_MIX_CTRL:
96
case ESDHC_WTMK_LVL:
97
ret = 0;
98
@@ -XXX,XX +XXX,XX @@ usdhc_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
99
case ESDHC_UNDOCUMENTED_REG27:
100
case ESDHC_TUNING_CTRL:
101
case ESDHC_WTMK_LVL:
102
+ break;
103
+
104
case ESDHC_VENDOR_SPEC:
105
+ s->vendor_spec = value;
106
+ switch (s->vendor) {
107
+ case SDHCI_VENDOR_IMX:
108
+ if (value & ESDHC_IMX_FRC_SDCLK_ON) {
109
+ s->prnsts &= ~SDHC_IMX_CLOCK_GATE_OFF;
110
+ } else {
111
+ s->prnsts |= SDHC_IMX_CLOCK_GATE_OFF;
112
+ }
113
+ break;
114
+ default:
115
+ break;
116
+ }
117
break;
118
119
case SDHC_HOSTCTL:
120
--
39
--
121
2.20.1
40
2.20.1
122
41
123
42
diff view generated by jsdifflib
1
From: Guenter Roeck <linux@roeck-us.net>
1
From: Shuuichirou Ishii <ishii.shuuichir@fujitsu.com>
2
2
3
Set vendor property to IMX to enable IMX specific functionality
3
Add tests that the A64FX CPU model exposes the expected features.
4
in sdhci code.
5
4
6
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Signed-off-by: Shuuichirou Ishii <ishii.shuuichir@fujitsu.com>
7
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
6
Reviewed-by: Andrew Jones <drjones@redhat.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
[PMM: added commit message body]
9
Message-id: 20200603145258.195920-3-linux@roeck-us.net
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
9
---
12
hw/arm/fsl-imx25.c | 6 ++++++
10
tests/qtest/arm-cpu-features.c | 13 +++++++++++++
13
hw/arm/fsl-imx6.c | 6 ++++++
11
1 file changed, 13 insertions(+)
14
hw/arm/fsl-imx6ul.c | 2 ++
15
hw/arm/fsl-imx7.c | 2 ++
16
4 files changed, 16 insertions(+)
17
12
18
diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c
13
diff --git a/tests/qtest/arm-cpu-features.c b/tests/qtest/arm-cpu-features.c
19
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/fsl-imx25.c
15
--- a/tests/qtest/arm-cpu-features.c
21
+++ b/hw/arm/fsl-imx25.c
16
+++ b/tests/qtest/arm-cpu-features.c
22
@@ -XXX,XX +XXX,XX @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
17
@@ -XXX,XX +XXX,XX @@ static void test_query_cpu_model_expansion(const void *data)
23
&err);
18
assert_has_feature_enabled(qts, "cortex-a57", "pmu");
24
object_property_set_uint(OBJECT(&s->esdhc[i]), IMX25_ESDHC_CAPABILITIES,
19
assert_has_feature_enabled(qts, "cortex-a57", "aarch64");
25
"capareg", &err);
20
26
+ object_property_set_uint(OBJECT(&s->esdhc[i]), SDHCI_VENDOR_IMX,
21
+ assert_has_feature_enabled(qts, "a64fx", "pmu");
27
+ "vendor", &err);
22
+ assert_has_feature_enabled(qts, "a64fx", "aarch64");
28
+ if (err) {
23
+ /*
29
+ error_propagate(errp, err);
24
+ * A64FX does not support any other vector lengths besides those
30
+ return;
25
+ * that are enabled by default(128bit, 256bits, 512bit).
31
+ }
26
+ */
32
object_property_set_bool(OBJECT(&s->esdhc[i]), true, "realized", &err);
27
+ assert_has_feature_enabled(qts, "a64fx", "sve");
33
if (err) {
28
+ assert_sve_vls(qts, "a64fx", 0xb, NULL);
34
error_propagate(errp, err);
29
+ assert_error(qts, "a64fx", "cannot enable sve384",
35
diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
30
+ "{ 'sve384': true }");
36
index XXXXXXX..XXXXXXX 100644
31
+ assert_error(qts, "a64fx", "cannot enable sve640",
37
--- a/hw/arm/fsl-imx6.c
32
+ "{ 'sve640': true }");
38
+++ b/hw/arm/fsl-imx6.c
33
+
39
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
34
sve_tests_default(qts, "max");
40
&err);
35
pauth_tests_default(qts, "max");
41
object_property_set_uint(OBJECT(&s->esdhc[i]), IMX6_ESDHC_CAPABILITIES,
42
"capareg", &err);
43
+ object_property_set_uint(OBJECT(&s->esdhc[i]), SDHCI_VENDOR_IMX,
44
+ "vendor", &err);
45
+ if (err) {
46
+ error_propagate(errp, err);
47
+ return;
48
+ }
49
object_property_set_bool(OBJECT(&s->esdhc[i]), true, "realized", &err);
50
if (err) {
51
error_propagate(errp, err);
52
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/hw/arm/fsl-imx6ul.c
55
+++ b/hw/arm/fsl-imx6ul.c
56
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
57
FSL_IMX6UL_USDHC2_IRQ,
58
};
59
60
+ object_property_set_uint(OBJECT(&s->usdhc[i]), SDHCI_VENDOR_IMX,
61
+ "vendor", &error_abort);
62
object_property_set_bool(OBJECT(&s->usdhc[i]), true, "realized",
63
&error_abort);
64
65
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/hw/arm/fsl-imx7.c
68
+++ b/hw/arm/fsl-imx7.c
69
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
70
FSL_IMX7_USDHC3_IRQ,
71
};
72
73
+ object_property_set_uint(OBJECT(&s->usdhc[i]), SDHCI_VENDOR_IMX,
74
+ "vendor", &error_abort);
75
object_property_set_bool(OBJECT(&s->usdhc[i]), true, "realized",
76
&error_abort);
77
36
78
--
37
--
79
2.20.1
38
2.20.1
80
39
81
40
diff view generated by jsdifflib
1
From: Jean-Christophe Dubois <jcd@tribudubois.net>
1
Currently we implement the RAS register block within the NVIC device.
2
It isn't really very tightly coupled with the NVIC proper, so instead
3
move it out into a sysbus device of its own and have the top level
4
ARMv7M container create it and map it into memory at the right
5
address.
2
6
3
Some bits of the CCM registers are non writable.
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Alexandre Iooss <erdnaxe@crans.org>
9
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
10
Reviewed-by: Luc Michel <luc@lmichel.fr>
11
Reviewed-by: Damien Hedde <damien.hedde@greensocs.com>
12
Message-id: 20210812093356.1946-2-peter.maydell@linaro.org
13
---
14
include/hw/arm/armv7m.h | 2 +
15
include/hw/intc/armv7m_nvic.h | 1 -
16
include/hw/misc/armv7m_ras.h | 37 ++++++++++++++
17
hw/arm/armv7m.c | 12 +++++
18
hw/intc/armv7m_nvic.c | 56 ---------------------
19
hw/misc/armv7m_ras.c | 93 +++++++++++++++++++++++++++++++++++
20
MAINTAINERS | 2 +
21
hw/misc/meson.build | 2 +
22
8 files changed, 148 insertions(+), 57 deletions(-)
23
create mode 100644 include/hw/misc/armv7m_ras.h
24
create mode 100644 hw/misc/armv7m_ras.c
4
25
5
This was left undone in the initial commit (all bits of registers were
26
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
6
writable).
27
index XXXXXXX..XXXXXXX 100644
7
28
--- a/include/hw/arm/armv7m.h
8
This patch adds the required code to protect the non writable bits.
29
+++ b/include/hw/arm/armv7m.h
9
10
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
11
Message-id: 20200608133508.550046-1-jcd@tribudubois.net
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
hw/misc/imx6ul_ccm.c | 76 ++++++++++++++++++++++++++++++++++++--------
16
1 file changed, 63 insertions(+), 13 deletions(-)
17
18
diff --git a/hw/misc/imx6ul_ccm.c b/hw/misc/imx6ul_ccm.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/misc/imx6ul_ccm.c
21
+++ b/hw/misc/imx6ul_ccm.c
22
@@ -XXX,XX +XXX,XX @@
30
@@ -XXX,XX +XXX,XX @@
23
31
24
#include "trace.h"
32
#include "hw/sysbus.h"
25
33
#include "hw/intc/armv7m_nvic.h"
26
+static const uint32_t ccm_mask[CCM_MAX] = {
34
+#include "hw/misc/armv7m_ras.h"
27
+ [CCM_CCR] = 0xf01fef80,
35
#include "target/arm/idau.h"
28
+ [CCM_CCDR] = 0xfffeffff,
36
#include "qom/object.h"
29
+ [CCM_CSR] = 0xffffffff,
37
30
+ [CCM_CCSR] = 0xfffffef2,
38
@@ -XXX,XX +XXX,XX @@ struct ARMv7MState {
31
+ [CCM_CACRR] = 0xfffffff8,
39
NVICState nvic;
32
+ [CCM_CBCDR] = 0xc1f8e000,
40
BitBandState bitband[ARMV7M_NUM_BITBANDS];
33
+ [CCM_CBCMR] = 0xfc03cfff,
41
ARMCPU *cpu;
34
+ [CCM_CSCMR1] = 0x80700000,
42
+ ARMv7MRAS ras;
35
+ [CCM_CSCMR2] = 0xe01ff003,
43
36
+ [CCM_CSCDR1] = 0xfe00c780,
44
/* MemoryRegion we pass to the CPU, with our devices layered on
37
+ [CCM_CS1CDR] = 0xfe00fe00,
45
* top of the ones the board provides in board_memory.
38
+ [CCM_CS2CDR] = 0xf8007000,
46
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
39
+ [CCM_CDCDR] = 0xf00fffff,
47
index XXXXXXX..XXXXXXX 100644
40
+ [CCM_CHSCCDR] = 0xfffc01ff,
48
--- a/include/hw/intc/armv7m_nvic.h
41
+ [CCM_CSCDR2] = 0xfe0001ff,
49
+++ b/include/hw/intc/armv7m_nvic.h
42
+ [CCM_CSCDR3] = 0xffffc1ff,
50
@@ -XXX,XX +XXX,XX @@ struct NVICState {
43
+ [CCM_CDHIPR] = 0xffffffff,
51
MemoryRegion sysreg_ns_mem;
44
+ [CCM_CTOR] = 0x00000000,
52
MemoryRegion systickmem;
45
+ [CCM_CLPCR] = 0xf39ff01c,
53
MemoryRegion systick_ns_mem;
46
+ [CCM_CISR] = 0xfb85ffbe,
54
- MemoryRegion ras_mem;
47
+ [CCM_CIMR] = 0xfb85ffbf,
55
MemoryRegion container;
48
+ [CCM_CCOSR] = 0xfe00fe00,
56
MemoryRegion defaultmem;
49
+ [CCM_CGPR] = 0xfffc3fea,
57
50
+ [CCM_CCGR0] = 0x00000000,
58
diff --git a/include/hw/misc/armv7m_ras.h b/include/hw/misc/armv7m_ras.h
51
+ [CCM_CCGR1] = 0x00000000,
59
new file mode 100644
52
+ [CCM_CCGR2] = 0x00000000,
60
index XXXXXXX..XXXXXXX
53
+ [CCM_CCGR3] = 0x00000000,
61
--- /dev/null
54
+ [CCM_CCGR4] = 0x00000000,
62
+++ b/include/hw/misc/armv7m_ras.h
55
+ [CCM_CCGR5] = 0x00000000,
63
@@ -XXX,XX +XXX,XX @@
56
+ [CCM_CCGR6] = 0x00000000,
64
+/*
57
+ [CCM_CMEOR] = 0xafffff1f,
65
+ * Arm M-profile RAS (Reliability, Availability and Serviceability) block
66
+ *
67
+ * Copyright (c) 2021 Linaro Limited
68
+ *
69
+ * This program is free software; you can redistribute it and/or modify
70
+ * it under the terms of the GNU General Public License version 2 or
71
+ * (at your option) any later version.
72
+ */
73
+
74
+/*
75
+ * This is a model of the RAS register block of an M-profile CPU
76
+ * (the registers starting at 0xE0005000 with ERRFRn).
77
+ *
78
+ * QEMU interface:
79
+ * + sysbus MMIO region 0: the register bank
80
+ *
81
+ * The QEMU implementation currently provides "minimal RAS" only.
82
+ */
83
+
84
+#ifndef HW_MISC_ARMV7M_RAS_H
85
+#define HW_MISC_ARMV7M_RAS_H
86
+
87
+#include "hw/sysbus.h"
88
+
89
+#define TYPE_ARMV7M_RAS "armv7m-ras"
90
+OBJECT_DECLARE_SIMPLE_TYPE(ARMv7MRAS, ARMV7M_RAS)
91
+
92
+struct ARMv7MRAS {
93
+ /*< private >*/
94
+ SysBusDevice parent_obj;
95
+
96
+ /*< public >*/
97
+ MemoryRegion iomem;
58
+};
98
+};
59
+
99
+
60
+static const uint32_t analog_mask[CCM_ANALOG_MAX] = {
100
+#endif
61
+ [CCM_ANALOG_PLL_ARM] = 0xfff60f80,
101
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
62
+ [CCM_ANALOG_PLL_USB1] = 0xfffe0fbc,
102
index XXXXXXX..XXXXXXX 100644
63
+ [CCM_ANALOG_PLL_USB2] = 0xfffe0fbc,
103
--- a/hw/arm/armv7m.c
64
+ [CCM_ANALOG_PLL_SYS] = 0xfffa0ffe,
104
+++ b/hw/arm/armv7m.c
65
+ [CCM_ANALOG_PLL_SYS_SS] = 0x00000000,
105
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
66
+ [CCM_ANALOG_PLL_SYS_NUM] = 0xc0000000,
106
memory_region_add_subregion(&s->container, 0xe0000000,
67
+ [CCM_ANALOG_PLL_SYS_DENOM] = 0xc0000000,
107
sysbus_mmio_get_region(sbd, 0));
68
+ [CCM_ANALOG_PLL_AUDIO] = 0xffe20f80,
108
69
+ [CCM_ANALOG_PLL_AUDIO_NUM] = 0xc0000000,
109
+ /* If the CPU has RAS support, create the RAS register block */
70
+ [CCM_ANALOG_PLL_AUDIO_DENOM] = 0xc0000000,
110
+ if (cpu_isar_feature(aa32_ras, s->cpu)) {
71
+ [CCM_ANALOG_PLL_VIDEO] = 0xffe20f80,
111
+ object_initialize_child(OBJECT(dev), "armv7m-ras",
72
+ [CCM_ANALOG_PLL_VIDEO_NUM] = 0xc0000000,
112
+ &s->ras, TYPE_ARMV7M_RAS);
73
+ [CCM_ANALOG_PLL_VIDEO_DENOM] = 0xc0000000,
113
+ sbd = SYS_BUS_DEVICE(&s->ras);
74
+ [CCM_ANALOG_PLL_ENET] = 0xffc20ff0,
114
+ if (!sysbus_realize(sbd, errp)) {
75
+ [CCM_ANALOG_PFD_480] = 0x40404040,
115
+ return;
76
+ [CCM_ANALOG_PFD_528] = 0x40404040,
116
+ }
77
+ [PMU_MISC0] = 0x01fe8306,
117
+ memory_region_add_subregion_overlap(&s->container, 0xe0005000,
78
+ [PMU_MISC1] = 0x07fcede0,
118
+ sysbus_mmio_get_region(sbd, 0), 1);
79
+ [PMU_MISC2] = 0x005f5f5f,
119
+ }
120
+
121
for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
122
if (s->enable_bitband) {
123
Object *obj = OBJECT(&s->bitband[i]);
124
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
125
index XXXXXXX..XXXXXXX 100644
126
--- a/hw/intc/armv7m_nvic.c
127
+++ b/hw/intc/armv7m_nvic.c
128
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_systick_ops = {
129
.endianness = DEVICE_NATIVE_ENDIAN,
130
};
131
132
-
133
-static MemTxResult ras_read(void *opaque, hwaddr addr,
134
- uint64_t *data, unsigned size,
135
- MemTxAttrs attrs)
136
-{
137
- if (attrs.user) {
138
- return MEMTX_ERROR;
139
- }
140
-
141
- switch (addr) {
142
- case 0xe10: /* ERRIIDR */
143
- /* architect field = Arm; product/variant/revision 0 */
144
- *data = 0x43b;
145
- break;
146
- case 0xfc8: /* ERRDEVID */
147
- /* Minimal RAS: we implement 0 error record indexes */
148
- *data = 0;
149
- break;
150
- default:
151
- qemu_log_mask(LOG_UNIMP, "Read RAS register offset 0x%x\n",
152
- (uint32_t)addr);
153
- *data = 0;
154
- break;
155
- }
156
- return MEMTX_OK;
157
-}
158
-
159
-static MemTxResult ras_write(void *opaque, hwaddr addr,
160
- uint64_t value, unsigned size,
161
- MemTxAttrs attrs)
162
-{
163
- if (attrs.user) {
164
- return MEMTX_ERROR;
165
- }
166
-
167
- switch (addr) {
168
- default:
169
- qemu_log_mask(LOG_UNIMP, "Write to RAS register offset 0x%x\n",
170
- (uint32_t)addr);
171
- break;
172
- }
173
- return MEMTX_OK;
174
-}
175
-
176
-static const MemoryRegionOps ras_ops = {
177
- .read_with_attrs = ras_read,
178
- .write_with_attrs = ras_write,
179
- .endianness = DEVICE_NATIVE_ENDIAN,
180
-};
181
-
182
/*
183
* Unassigned portions of the PPB space are RAZ/WI for privileged
184
* accesses, and fault for non-privileged accesses.
185
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
186
&s->systick_ns_mem, 1);
187
}
188
189
- if (cpu_isar_feature(aa32_ras, s->cpu)) {
190
- memory_region_init_io(&s->ras_mem, OBJECT(s),
191
- &ras_ops, s, "nvic_ras", 0x1000);
192
- memory_region_add_subregion(&s->container, 0x5000, &s->ras_mem);
193
- }
194
-
195
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->container);
196
}
197
198
diff --git a/hw/misc/armv7m_ras.c b/hw/misc/armv7m_ras.c
199
new file mode 100644
200
index XXXXXXX..XXXXXXX
201
--- /dev/null
202
+++ b/hw/misc/armv7m_ras.c
203
@@ -XXX,XX +XXX,XX @@
204
+/*
205
+ * Arm M-profile RAS (Reliability, Availability and Serviceability) block
206
+ *
207
+ * Copyright (c) 2021 Linaro Limited
208
+ *
209
+ * This program is free software; you can redistribute it and/or modify
210
+ * it under the terms of the GNU General Public License version 2 or
211
+ * (at your option) any later version.
212
+ */
213
+
214
+#include "qemu/osdep.h"
215
+#include "hw/misc/armv7m_ras.h"
216
+#include "qemu/log.h"
217
+
218
+static MemTxResult ras_read(void *opaque, hwaddr addr,
219
+ uint64_t *data, unsigned size,
220
+ MemTxAttrs attrs)
221
+{
222
+ if (attrs.user) {
223
+ return MEMTX_ERROR;
224
+ }
225
+
226
+ switch (addr) {
227
+ case 0xe10: /* ERRIIDR */
228
+ /* architect field = Arm; product/variant/revision 0 */
229
+ *data = 0x43b;
230
+ break;
231
+ case 0xfc8: /* ERRDEVID */
232
+ /* Minimal RAS: we implement 0 error record indexes */
233
+ *data = 0;
234
+ break;
235
+ default:
236
+ qemu_log_mask(LOG_UNIMP, "Read RAS register offset 0x%x\n",
237
+ (uint32_t)addr);
238
+ *data = 0;
239
+ break;
240
+ }
241
+ return MEMTX_OK;
242
+}
243
+
244
+static MemTxResult ras_write(void *opaque, hwaddr addr,
245
+ uint64_t value, unsigned size,
246
+ MemTxAttrs attrs)
247
+{
248
+ if (attrs.user) {
249
+ return MEMTX_ERROR;
250
+ }
251
+
252
+ switch (addr) {
253
+ default:
254
+ qemu_log_mask(LOG_UNIMP, "Write to RAS register offset 0x%x\n",
255
+ (uint32_t)addr);
256
+ break;
257
+ }
258
+ return MEMTX_OK;
259
+}
260
+
261
+static const MemoryRegionOps ras_ops = {
262
+ .read_with_attrs = ras_read,
263
+ .write_with_attrs = ras_write,
264
+ .endianness = DEVICE_NATIVE_ENDIAN,
80
+};
265
+};
81
+
266
+
82
static const char *imx6ul_ccm_reg_name(uint32_t reg)
267
+
83
{
268
+static void armv7m_ras_init(Object *obj)
84
static char unknown[20];
269
+{
85
@@ -XXX,XX +XXX,XX @@ static void imx6ul_ccm_write(void *opaque, hwaddr offset, uint64_t value,
270
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
86
271
+ ARMv7MRAS *s = ARMV7M_RAS(obj);
87
trace_ccm_write_reg(imx6ul_ccm_reg_name(index), (uint32_t)value);
272
+
88
273
+ memory_region_init_io(&s->iomem, obj, &ras_ops,
89
- /*
274
+ s, "armv7m-ras", 0x1000);
90
- * We will do a better implementation later. In particular some bits
275
+ sysbus_init_mmio(sbd, &s->iomem);
91
- * cannot be written to.
276
+}
92
- */
277
+
93
- s->ccm[index] = (uint32_t)value;
278
+static void armv7m_ras_class_init(ObjectClass *klass, void *data)
94
+ s->ccm[index] = (s->ccm[index] & ccm_mask[index]) |
279
+{
95
+ ((uint32_t)value & ~ccm_mask[index]);
280
+ /* This device has no state: no need for vmstate or reset */
96
}
281
+}
97
282
+
98
static uint64_t imx6ul_analog_read(void *opaque, hwaddr offset, unsigned size)
283
+static const TypeInfo armv7m_ras_info = {
99
@@ -XXX,XX +XXX,XX @@ static void imx6ul_analog_write(void *opaque, hwaddr offset, uint64_t value,
284
+ .name = TYPE_ARMV7M_RAS,
100
* the REG_NAME register. So we change the value of the
285
+ .parent = TYPE_SYS_BUS_DEVICE,
101
* REG_NAME register, setting bits passed in the value.
286
+ .instance_size = sizeof(ARMv7MRAS),
102
*/
287
+ .instance_init = armv7m_ras_init,
103
- s->analog[index - 1] |= value;
288
+ .class_init = armv7m_ras_class_init,
104
+ s->analog[index - 1] |= (value & ~analog_mask[index - 1]);
289
+};
105
break;
290
+
106
case CCM_ANALOG_PLL_ARM_CLR:
291
+static void armv7m_ras_register_types(void)
107
case CCM_ANALOG_PLL_USB1_CLR:
292
+{
108
@@ -XXX,XX +XXX,XX @@ static void imx6ul_analog_write(void *opaque, hwaddr offset, uint64_t value,
293
+ type_register_static(&armv7m_ras_info);
109
* the REG_NAME register. So we change the value of the
294
+}
110
* REG_NAME register, unsetting bits passed in the value.
295
+
111
*/
296
+type_init(armv7m_ras_register_types);
112
- s->analog[index - 2] &= ~value;
297
diff --git a/MAINTAINERS b/MAINTAINERS
113
+ s->analog[index - 2] &= ~(value & ~analog_mask[index - 2]);
298
index XXXXXXX..XXXXXXX 100644
114
break;
299
--- a/MAINTAINERS
115
case CCM_ANALOG_PLL_ARM_TOG:
300
+++ b/MAINTAINERS
116
case CCM_ANALOG_PLL_USB1_TOG:
301
@@ -XXX,XX +XXX,XX @@ F: hw/intc/gic_internal.h
117
@@ -XXX,XX +XXX,XX @@ static void imx6ul_analog_write(void *opaque, hwaddr offset, uint64_t value,
302
F: hw/misc/a9scu.c
118
* the REG_NAME register. So we change the value of the
303
F: hw/misc/arm11scu.c
119
* REG_NAME register, toggling bits passed in the value.
304
F: hw/misc/arm_l2x0.c
120
*/
305
+F: hw/misc/armv7m_ras.c
121
- s->analog[index - 3] ^= value;
306
F: hw/timer/a9gtimer*
122
+ s->analog[index - 3] ^= (value & ~analog_mask[index - 3]);
307
F: hw/timer/arm*
123
break;
308
F: include/hw/arm/arm*.h
124
default:
309
@@ -XXX,XX +XXX,XX @@ F: include/hw/misc/arm11scu.h
125
- /*
310
F: include/hw/timer/a9gtimer.h
126
- * We will do a better implementation later. In particular some bits
311
F: include/hw/timer/arm_mptimer.h
127
- * cannot be written to.
312
F: include/hw/timer/armv7m_systick.h
128
- */
313
+F: include/hw/misc/armv7m_ras.h
129
- s->analog[index] = value;
314
F: tests/qtest/test-arm-mptimer.c
130
+ s->analog[index] = (s->analog[index] & analog_mask[index]) |
315
131
+ (value & ~analog_mask[index]);
316
Exynos
132
break;
317
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
133
}
318
index XXXXXXX..XXXXXXX 100644
134
}
319
--- a/hw/misc/meson.build
320
+++ b/hw/misc/meson.build
321
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_INTEGRATOR_DEBUG', if_true: files('arm_integrator_d
322
softmmu_ss.add(when: 'CONFIG_A9SCU', if_true: files('a9scu.c'))
323
softmmu_ss.add(when: 'CONFIG_ARM11SCU', if_true: files('arm11scu.c'))
324
325
+softmmu_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('armv7m_ras.c'))
326
+
327
# Mac devices
328
softmmu_ss.add(when: 'CONFIG_MOS6522', if_true: files('mos6522.c'))
329
135
--
330
--
136
2.20.1
331
2.20.1
137
332
138
333
diff view generated by jsdifflib
1
Convert the Neon 3-reg-diff insns VQDMULL, VQDMLAL and VQDMLSL:
1
There's no particular reason why the NVIC should be owning the
2
these are all saturating doubling long multiplies with a possible
2
SysTick device objects; move them into the ARMv7M container object
3
accumulate step.
3
instead, as part of consolidating the "create the devices which are
4
4
built into an M-profile CPU and map them into their architected
5
These are the last insns in the group which use the pass-over-each
5
locations in the address space" work into one place.
6
elements loop, so we can delete that code.
6
7
This involves temporarily creating a duplicate copy of the
8
nvic_sysreg_ns_ops struct and its read/write functions (renamed as
9
v7m_sysreg_ns_*), but we will delete the NVIC's copy of this code in
10
a subsequent patch.
7
11
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Acked-by: Alistair Francis <alistair.francis@wdc.com>
14
Reviewed-by: Luc Michel <luc@lmichel.fr>
15
Message-id: 20210812093356.1946-3-peter.maydell@linaro.org
10
---
16
---
11
target/arm/neon-dp.decode | 6 +++
17
include/hw/arm/armv7m.h | 12 ++++
12
target/arm/translate-neon.inc.c | 82 +++++++++++++++++++++++++++++++++
18
include/hw/intc/armv7m_nvic.h | 4 --
13
target/arm/translate.c | 59 ++----------------------
19
hw/arm/armv7m.c | 125 ++++++++++++++++++++++++++++++++++
14
3 files changed, 92 insertions(+), 55 deletions(-)
20
hw/intc/armv7m_nvic.c | 73 --------------------
15
21
4 files changed, 137 insertions(+), 77 deletions(-)
16
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
22
23
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
17
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/neon-dp.decode
25
--- a/include/hw/arm/armv7m.h
19
+++ b/target/arm/neon-dp.decode
26
+++ b/include/hw/arm/armv7m.h
20
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
27
@@ -XXX,XX +XXX,XX @@ struct ARMv7MState {
21
VMLAL_S_3d 1111 001 0 1 . .. .... .... 1000 . 0 . 0 .... @3diff
28
BitBandState bitband[ARMV7M_NUM_BITBANDS];
22
VMLAL_U_3d 1111 001 1 1 . .. .... .... 1000 . 0 . 0 .... @3diff
29
ARMCPU *cpu;
23
30
ARMv7MRAS ras;
24
+ VQDMLAL_3d 1111 001 0 1 . .. .... .... 1001 . 0 . 0 .... @3diff
31
+ SysTickState systick[M_REG_NUM_BANKS];
25
+
32
26
VMLSL_S_3d 1111 001 0 1 . .. .... .... 1010 . 0 . 0 .... @3diff
33
/* MemoryRegion we pass to the CPU, with our devices layered on
27
VMLSL_U_3d 1111 001 1 1 . .. .... .... 1010 . 0 . 0 .... @3diff
34
* top of the ones the board provides in board_memory.
28
35
*/
29
+ VQDMLSL_3d 1111 001 0 1 . .. .... .... 1011 . 0 . 0 .... @3diff
36
MemoryRegion container;
30
+
37
+ /*
31
VMULL_S_3d 1111 001 0 1 . .. .... .... 1100 . 0 . 0 .... @3diff
38
+ * MemoryRegion which passes the transaction to either the S or the
32
VMULL_U_3d 1111 001 1 1 . .. .... .... 1100 . 0 . 0 .... @3diff
39
+ * NS systick device depending on the transaction attributes
33
+
40
+ */
34
+ VQDMULL_3d 1111 001 0 1 . .. .... .... 1101 . 0 . 0 .... @3diff
41
+ MemoryRegion systickmem;
35
]
42
+ /*
36
}
43
+ * MemoryRegion which enforces the S/NS handling of the systick
37
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
44
+ * device NS alias region and passes the transaction to the
45
+ * NS systick device if appropriate.
46
+ */
47
+ MemoryRegion systick_ns_mem;
48
49
/* Properties */
50
char *cpu_type;
51
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
38
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/translate-neon.inc.c
53
--- a/include/hw/intc/armv7m_nvic.h
40
+++ b/target/arm/translate-neon.inc.c
54
+++ b/include/hw/intc/armv7m_nvic.h
41
@@ -XXX,XX +XXX,XX @@ DO_VMLAL(VMLAL_S,mull_s,add)
55
@@ -XXX,XX +XXX,XX @@ struct NVICState {
42
DO_VMLAL(VMLAL_U,mull_u,add)
56
43
DO_VMLAL(VMLSL_S,mull_s,sub)
57
MemoryRegion sysregmem;
44
DO_VMLAL(VMLSL_U,mull_u,sub)
58
MemoryRegion sysreg_ns_mem;
45
+
59
- MemoryRegion systickmem;
46
+static void gen_VQDMULL_16(TCGv_i64 rd, TCGv_i32 rn, TCGv_i32 rm)
60
- MemoryRegion systick_ns_mem;
61
MemoryRegion container;
62
MemoryRegion defaultmem;
63
64
uint32_t num_irq;
65
qemu_irq excpout;
66
qemu_irq sysresetreq;
67
-
68
- SysTickState systick[M_REG_NUM_BANKS];
69
};
70
71
#endif
72
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/hw/arm/armv7m.c
75
+++ b/hw/arm/armv7m.c
76
@@ -XXX,XX +XXX,XX @@ static const hwaddr bitband_output_addr[ARMV7M_NUM_BITBANDS] = {
77
0x22000000, 0x42000000
78
};
79
80
+static MemTxResult v7m_sysreg_ns_write(void *opaque, hwaddr addr,
81
+ uint64_t value, unsigned size,
82
+ MemTxAttrs attrs)
47
+{
83
+{
48
+ gen_helper_neon_mull_s16(rd, rn, rm);
84
+ MemoryRegion *mr = opaque;
49
+ gen_helper_neon_addl_saturate_s32(rd, cpu_env, rd, rd);
85
+
86
+ if (attrs.secure) {
87
+ /* S accesses to the alias act like NS accesses to the real region */
88
+ attrs.secure = 0;
89
+ return memory_region_dispatch_write(mr, addr, value,
90
+ size_memop(size) | MO_TE, attrs);
91
+ } else {
92
+ /* NS attrs are RAZ/WI for privileged, and BusFault for user */
93
+ if (attrs.user) {
94
+ return MEMTX_ERROR;
95
+ }
96
+ return MEMTX_OK;
97
+ }
50
+}
98
+}
51
+
99
+
52
+static void gen_VQDMULL_32(TCGv_i64 rd, TCGv_i32 rn, TCGv_i32 rm)
100
+static MemTxResult v7m_sysreg_ns_read(void *opaque, hwaddr addr,
101
+ uint64_t *data, unsigned size,
102
+ MemTxAttrs attrs)
53
+{
103
+{
54
+ gen_mull_s32(rd, rn, rm);
104
+ MemoryRegion *mr = opaque;
55
+ gen_helper_neon_addl_saturate_s64(rd, cpu_env, rd, rd);
105
+
106
+ if (attrs.secure) {
107
+ /* S accesses to the alias act like NS accesses to the real region */
108
+ attrs.secure = 0;
109
+ return memory_region_dispatch_read(mr, addr, data,
110
+ size_memop(size) | MO_TE, attrs);
111
+ } else {
112
+ /* NS attrs are RAZ/WI for privileged, and BusFault for user */
113
+ if (attrs.user) {
114
+ return MEMTX_ERROR;
115
+ }
116
+ *data = 0;
117
+ return MEMTX_OK;
118
+ }
56
+}
119
+}
57
+
120
+
58
+static bool trans_VQDMULL_3d(DisasContext *s, arg_3diff *a)
121
+static const MemoryRegionOps v7m_sysreg_ns_ops = {
122
+ .read_with_attrs = v7m_sysreg_ns_read,
123
+ .write_with_attrs = v7m_sysreg_ns_write,
124
+ .endianness = DEVICE_NATIVE_ENDIAN,
125
+};
126
+
127
+static MemTxResult v7m_systick_write(void *opaque, hwaddr addr,
128
+ uint64_t value, unsigned size,
129
+ MemTxAttrs attrs)
59
+{
130
+{
60
+ static NeonGenTwoOpWidenFn * const opfn[] = {
131
+ ARMv7MState *s = opaque;
61
+ NULL,
132
+ MemoryRegion *mr;
62
+ gen_VQDMULL_16,
133
+
63
+ gen_VQDMULL_32,
134
+ /* Direct the access to the correct systick */
64
+ NULL,
135
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->systick[attrs.secure]), 0);
65
+ };
136
+ return memory_region_dispatch_write(mr, addr, value,
66
+
137
+ size_memop(size) | MO_TE, attrs);
67
+ return do_long_3d(s, a, opfn[a->size], NULL);
68
+}
138
+}
69
+
139
+
70
+static void gen_VQDMLAL_acc_16(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
140
+static MemTxResult v7m_systick_read(void *opaque, hwaddr addr,
141
+ uint64_t *data, unsigned size,
142
+ MemTxAttrs attrs)
71
+{
143
+{
72
+ gen_helper_neon_addl_saturate_s32(rd, cpu_env, rn, rm);
144
+ ARMv7MState *s = opaque;
145
+ MemoryRegion *mr;
146
+
147
+ /* Direct the access to the correct systick */
148
+ mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->systick[attrs.secure]), 0);
149
+ return memory_region_dispatch_read(mr, addr, data, size_memop(size) | MO_TE,
150
+ attrs);
73
+}
151
+}
74
+
152
+
75
+static void gen_VQDMLAL_acc_32(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
153
+static const MemoryRegionOps v7m_systick_ops = {
76
+{
154
+ .read_with_attrs = v7m_systick_read,
77
+ gen_helper_neon_addl_saturate_s64(rd, cpu_env, rn, rm);
155
+ .write_with_attrs = v7m_systick_write,
78
+}
156
+ .endianness = DEVICE_NATIVE_ENDIAN,
79
+
157
+};
80
+static bool trans_VQDMLAL_3d(DisasContext *s, arg_3diff *a)
158
+
81
+{
159
static void armv7m_instance_init(Object *obj)
82
+ static NeonGenTwoOpWidenFn * const opfn[] = {
160
{
83
+ NULL,
161
ARMv7MState *s = ARMV7M(obj);
84
+ gen_VQDMULL_16,
162
@@ -XXX,XX +XXX,XX @@ static void armv7m_instance_init(Object *obj)
85
+ gen_VQDMULL_32,
163
object_property_add_alias(obj, "num-irq",
86
+ NULL,
164
OBJECT(&s->nvic), "num-irq");
87
+ };
165
88
+ static NeonGenTwo64OpFn * const accfn[] = {
166
+ object_initialize_child(obj, "systick-reg-ns", &s->systick[M_REG_NS],
89
+ NULL,
167
+ TYPE_SYSTICK);
90
+ gen_VQDMLAL_acc_16,
168
+ /*
91
+ gen_VQDMLAL_acc_32,
169
+ * We can't initialize the secure systick here, as we don't know
92
+ NULL,
170
+ * yet if we need it.
93
+ };
171
+ */
94
+
172
+
95
+ return do_long_3d(s, a, opfn[a->size], accfn[a->size]);
173
for (i = 0; i < ARRAY_SIZE(s->bitband); i++) {
96
+}
174
object_initialize_child(obj, "bitband[*]", &s->bitband[i],
97
+
175
TYPE_BITBAND);
98
+static void gen_VQDMLSL_acc_16(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
176
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
99
+{
177
memory_region_add_subregion(&s->container, 0xe0000000,
100
+ gen_helper_neon_negl_u32(rm, rm);
178
sysbus_mmio_get_region(sbd, 0));
101
+ gen_helper_neon_addl_saturate_s32(rd, cpu_env, rn, rm);
179
102
+}
180
+ /* Create and map the systick devices */
103
+
181
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->systick[M_REG_NS]), errp)) {
104
+static void gen_VQDMLSL_acc_32(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
182
+ return;
105
+{
183
+ }
106
+ tcg_gen_neg_i64(rm, rm);
184
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systick[M_REG_NS]), 0,
107
+ gen_helper_neon_addl_saturate_s64(rd, cpu_env, rn, rm);
185
+ qdev_get_gpio_in_named(DEVICE(&s->nvic),
108
+}
186
+ "systick-trigger", M_REG_NS));
109
+
187
+
110
+static bool trans_VQDMLSL_3d(DisasContext *s, arg_3diff *a)
188
+ if (arm_feature(&s->cpu->env, ARM_FEATURE_M_SECURITY)) {
111
+{
189
+ /*
112
+ static NeonGenTwoOpWidenFn * const opfn[] = {
190
+ * We couldn't init the secure systick device in instance_init
113
+ NULL,
191
+ * as we didn't know then if the CPU had the security extensions;
114
+ gen_VQDMULL_16,
192
+ * so we have to do it here.
115
+ gen_VQDMULL_32,
193
+ */
116
+ NULL,
194
+ object_initialize_child(OBJECT(dev), "systick-reg-s",
117
+ };
195
+ &s->systick[M_REG_S], TYPE_SYSTICK);
118
+ static NeonGenTwo64OpFn * const accfn[] = {
196
+
119
+ NULL,
197
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->systick[M_REG_S]), errp)) {
120
+ gen_VQDMLSL_acc_16,
198
+ return;
121
+ gen_VQDMLSL_acc_32,
199
+ }
122
+ NULL,
200
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->systick[M_REG_S]), 0,
123
+ };
201
+ qdev_get_gpio_in_named(DEVICE(&s->nvic),
124
+
202
+ "systick-trigger", M_REG_S));
125
+ return do_long_3d(s, a, opfn[a->size], accfn[a->size]);
203
+ }
126
+}
204
+
127
diff --git a/target/arm/translate.c b/target/arm/translate.c
205
+ memory_region_init_io(&s->systickmem, OBJECT(s),
206
+ &v7m_systick_ops, s,
207
+ "v7m_systick", 0xe0);
208
+
209
+ memory_region_add_subregion_overlap(&s->container, 0xe000e010,
210
+ &s->systickmem, 1);
211
+ if (arm_feature(&s->cpu->env, ARM_FEATURE_V8)) {
212
+ memory_region_init_io(&s->systick_ns_mem, OBJECT(s),
213
+ &v7m_sysreg_ns_ops, &s->systickmem,
214
+ "v7m_systick_ns", 0xe0);
215
+ memory_region_add_subregion_overlap(&s->container, 0xe002e010,
216
+ &s->systick_ns_mem, 1);
217
+ }
218
+
219
/* If the CPU has RAS support, create the RAS register block */
220
if (cpu_isar_feature(aa32_ras, s->cpu)) {
221
object_initialize_child(OBJECT(dev), "armv7m-ras",
222
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
128
index XXXXXXX..XXXXXXX 100644
223
index XXXXXXX..XXXXXXX 100644
129
--- a/target/arm/translate.c
224
--- a/hw/intc/armv7m_nvic.c
130
+++ b/target/arm/translate.c
225
+++ b/hw/intc/armv7m_nvic.c
131
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
226
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_sysreg_ns_ops = {
132
{0, 0, 0, 7}, /* VSUBHN: handled by decodetree */
227
.endianness = DEVICE_NATIVE_ENDIAN,
133
{0, 0, 0, 7}, /* VABDL */
228
};
134
{0, 0, 0, 7}, /* VMLAL */
229
135
- {0, 0, 0, 9}, /* VQDMLAL */
230
-static MemTxResult nvic_systick_write(void *opaque, hwaddr addr,
136
+ {0, 0, 0, 7}, /* VQDMLAL */
231
- uint64_t value, unsigned size,
137
{0, 0, 0, 7}, /* VMLSL */
232
- MemTxAttrs attrs)
138
- {0, 0, 0, 9}, /* VQDMLSL */
233
-{
139
+ {0, 0, 0, 7}, /* VQDMLSL */
234
- NVICState *s = opaque;
140
{0, 0, 0, 7}, /* Integer VMULL */
235
- MemoryRegion *mr;
141
- {0, 0, 0, 9}, /* VQDMULL */
236
-
142
+ {0, 0, 0, 7}, /* VQDMULL */
237
- /* Direct the access to the correct systick */
143
{0, 0, 0, 0xa}, /* Polynomial VMULL */
238
- mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->systick[attrs.secure]), 0);
144
{0, 0, 0, 7}, /* Reserved: always UNDEF */
239
- return memory_region_dispatch_write(mr, addr, value,
145
};
240
- size_memop(size) | MO_TE, attrs);
146
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
241
-}
147
}
242
-
148
return 0;
243
-static MemTxResult nvic_systick_read(void *opaque, hwaddr addr,
149
}
244
- uint64_t *data, unsigned size,
150
-
245
- MemTxAttrs attrs)
151
- /* Avoid overlapping operands. Wide source operands are
246
-{
152
- always aligned so will never overlap with wide
247
- NVICState *s = opaque;
153
- destinations in problematic ways. */
248
- MemoryRegion *mr;
154
- if (rd == rm) {
249
-
155
- tmp = neon_load_reg(rm, 1);
250
- /* Direct the access to the correct systick */
156
- neon_store_scratch(2, tmp);
251
- mr = sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->systick[attrs.secure]), 0);
157
- } else if (rd == rn) {
252
- return memory_region_dispatch_read(mr, addr, data, size_memop(size) | MO_TE,
158
- tmp = neon_load_reg(rn, 1);
253
- attrs);
159
- neon_store_scratch(2, tmp);
254
-}
160
- }
255
-
161
- tmp3 = NULL;
256
-static const MemoryRegionOps nvic_systick_ops = {
162
- for (pass = 0; pass < 2; pass++) {
257
- .read_with_attrs = nvic_systick_read,
163
- if (pass == 1 && rd == rn) {
258
- .write_with_attrs = nvic_systick_write,
164
- tmp = neon_load_scratch(2);
259
- .endianness = DEVICE_NATIVE_ENDIAN,
165
- } else {
260
-};
166
- tmp = neon_load_reg(rn, pass);
261
-
167
- }
262
/*
168
- if (pass == 1 && rd == rm) {
263
* Unassigned portions of the PPB space are RAZ/WI for privileged
169
- tmp2 = neon_load_scratch(2);
264
* accesses, and fault for non-privileged accesses.
170
- } else {
265
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
171
- tmp2 = neon_load_reg(rm, pass);
266
172
- }
267
s->num_prio_bits = arm_feature(&s->cpu->env, ARM_FEATURE_V7) ? 8 : 2;
173
- switch (op) {
268
174
- case 9: case 11: case 13:
269
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->systick[M_REG_NS]), errp)) {
175
- /* VQDMLAL, VQDMLSL, VQDMULL */
270
- return;
176
- gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
271
- }
177
- break;
272
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->systick[M_REG_NS]), 0,
178
- default: /* 15 is RESERVED: caught earlier */
273
- qdev_get_gpio_in_named(dev, "systick-trigger",
179
- abort();
274
- M_REG_NS));
180
- }
275
-
181
- if (op == 13) {
276
- if (arm_feature(&s->cpu->env, ARM_FEATURE_M_SECURITY)) {
182
- /* VQDMULL */
277
- /* We couldn't init the secure systick device in instance_init
183
- gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
278
- * as we didn't know then if the CPU had the security extensions;
184
- neon_store_reg64(cpu_V0, rd + pass);
279
- * so we have to do it here.
185
- } else {
280
- */
186
- /* Accumulate. */
281
- object_initialize_child(OBJECT(dev), "systick-reg-s",
187
- neon_load_reg64(cpu_V1, rd + pass);
282
- &s->systick[M_REG_S], TYPE_SYSTICK);
188
- switch (op) {
283
-
189
- case 9: case 11: /* VQDMLAL, VQDMLSL */
284
- if (!sysbus_realize(SYS_BUS_DEVICE(&s->systick[M_REG_S]), errp)) {
190
- gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
285
- return;
191
- if (op == 11) {
286
- }
192
- gen_neon_negl(cpu_V0, size);
287
- sysbus_connect_irq(SYS_BUS_DEVICE(&s->systick[M_REG_S]), 0,
193
- }
288
- qdev_get_gpio_in_named(dev, "systick-trigger",
194
- gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
289
- M_REG_S));
195
- break;
290
- }
196
- default:
291
-
197
- abort();
292
/*
198
- }
293
* This device provides a single sysbus memory region which
199
- neon_store_reg64(cpu_V0, rd + pass);
294
* represents the whole of the "System PPB" space. This is the
200
- }
295
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
201
- }
296
"nvic_sysregs", 0x1000);
202
+ abort(); /* all others handled by decodetree */
297
memory_region_add_subregion(&s->container, 0xe000, &s->sysregmem);
203
} else {
298
204
/* Two registers and a scalar. NB that for ops of this form
299
- memory_region_init_io(&s->systickmem, OBJECT(s),
205
* the ARM ARM labels bit 24 as Q, but it is in our variable
300
- &nvic_systick_ops, s,
301
- "nvic_systick", 0xe0);
302
-
303
- memory_region_add_subregion_overlap(&s->container, 0xe010,
304
- &s->systickmem, 1);
305
-
306
if (arm_feature(&s->cpu->env, ARM_FEATURE_V8)) {
307
memory_region_init_io(&s->sysreg_ns_mem, OBJECT(s),
308
&nvic_sysreg_ns_ops, &s->sysregmem,
309
"nvic_sysregs_ns", 0x1000);
310
memory_region_add_subregion(&s->container, 0x2e000, &s->sysreg_ns_mem);
311
- memory_region_init_io(&s->systick_ns_mem, OBJECT(s),
312
- &nvic_sysreg_ns_ops, &s->systickmem,
313
- "nvic_systick_ns", 0xe0);
314
- memory_region_add_subregion_overlap(&s->container, 0x2e010,
315
- &s->systick_ns_mem, 1);
316
}
317
318
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->container);
319
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_instance_init(Object *obj)
320
NVICState *nvic = NVIC(obj);
321
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
322
323
- object_initialize_child(obj, "systick-reg-ns", &nvic->systick[M_REG_NS],
324
- TYPE_SYSTICK);
325
- /* We can't initialize the secure systick here, as we don't know
326
- * yet if we need it.
327
- */
328
-
329
sysbus_init_irq(sbd, &nvic->excpout);
330
qdev_init_gpio_out_named(dev, &nvic->sysresetreq, "SYSRESETREQ", 1);
331
qdev_init_gpio_in_named(dev, nvic_systick_trigger, "systick-trigger",
206
--
332
--
207
2.20.1
333
2.20.1
208
334
209
335
diff view generated by jsdifflib
New patch
1
Instead of having the NVIC device provide a single sysbus memory
2
region covering the whole of the "System PPB" space, which implements
3
the default behaviour for unimplemented ranges and provides the NS
4
alias window to the sysregs as well as the main sysreg MR, move this
5
handling to the container armv7m device. The NVIC now provides a
6
single memory region which just implements the system registers.
7
This consolidates all the handling of "map various devices in the
8
PPB" into the armv7m container where it belongs.
1
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Alexandre Iooss <erdnaxe@crans.org>
12
Reviewed-by: Luc Michel <luc@lmichel.fr>
13
Message-id: 20210812093356.1946-4-peter.maydell@linaro.org
14
---
15
include/hw/arm/armv7m.h | 4 +
16
include/hw/intc/armv7m_nvic.h | 3 -
17
hw/arm/armv7m.c | 100 ++++++++++++++++++++++-
18
hw/intc/armv7m_nvic.c | 145 +---------------------------------
19
4 files changed, 107 insertions(+), 145 deletions(-)
20
21
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/arm/armv7m.h
24
+++ b/include/hw/arm/armv7m.h
25
@@ -XXX,XX +XXX,XX @@ struct ARMv7MState {
26
* NS systick device if appropriate.
27
*/
28
MemoryRegion systick_ns_mem;
29
+ /* Ditto, for the sysregs region provided by the NVIC */
30
+ MemoryRegion sysreg_ns_mem;
31
+ /* MR providing default PPB behaviour */
32
+ MemoryRegion defaultmem;
33
34
/* Properties */
35
char *cpu_type;
36
diff --git a/include/hw/intc/armv7m_nvic.h b/include/hw/intc/armv7m_nvic.h
37
index XXXXXXX..XXXXXXX 100644
38
--- a/include/hw/intc/armv7m_nvic.h
39
+++ b/include/hw/intc/armv7m_nvic.h
40
@@ -XXX,XX +XXX,XX @@ struct NVICState {
41
int vectpending_prio; /* group prio of the exeception in vectpending */
42
43
MemoryRegion sysregmem;
44
- MemoryRegion sysreg_ns_mem;
45
- MemoryRegion container;
46
- MemoryRegion defaultmem;
47
48
uint32_t num_irq;
49
qemu_irq excpout;
50
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/hw/arm/armv7m.c
53
+++ b/hw/arm/armv7m.c
54
@@ -XXX,XX +XXX,XX @@
55
#include "sysemu/reset.h"
56
#include "qemu/error-report.h"
57
#include "qemu/module.h"
58
+#include "qemu/log.h"
59
#include "target/arm/idau.h"
60
61
/* Bitbanded IO. Each word corresponds to a single bit. */
62
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps v7m_systick_ops = {
63
.endianness = DEVICE_NATIVE_ENDIAN,
64
};
65
66
+/*
67
+ * Unassigned portions of the PPB space are RAZ/WI for privileged
68
+ * accesses, and fault for non-privileged accesses.
69
+ */
70
+static MemTxResult ppb_default_read(void *opaque, hwaddr addr,
71
+ uint64_t *data, unsigned size,
72
+ MemTxAttrs attrs)
73
+{
74
+ qemu_log_mask(LOG_UNIMP, "Read of unassigned area of PPB: offset 0x%x\n",
75
+ (uint32_t)addr);
76
+ if (attrs.user) {
77
+ return MEMTX_ERROR;
78
+ }
79
+ *data = 0;
80
+ return MEMTX_OK;
81
+}
82
+
83
+static MemTxResult ppb_default_write(void *opaque, hwaddr addr,
84
+ uint64_t value, unsigned size,
85
+ MemTxAttrs attrs)
86
+{
87
+ qemu_log_mask(LOG_UNIMP, "Write of unassigned area of PPB: offset 0x%x\n",
88
+ (uint32_t)addr);
89
+ if (attrs.user) {
90
+ return MEMTX_ERROR;
91
+ }
92
+ return MEMTX_OK;
93
+}
94
+
95
+static const MemoryRegionOps ppb_default_ops = {
96
+ .read_with_attrs = ppb_default_read,
97
+ .write_with_attrs = ppb_default_write,
98
+ .endianness = DEVICE_NATIVE_ENDIAN,
99
+ .valid.min_access_size = 1,
100
+ .valid.max_access_size = 8,
101
+};
102
+
103
static void armv7m_instance_init(Object *obj)
104
{
105
ARMv7MState *s = ARMV7M(obj);
106
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
107
qdev_pass_gpios(DEVICE(&s->nvic), dev, "SYSRESETREQ");
108
qdev_pass_gpios(DEVICE(&s->nvic), dev, "NMI");
109
110
+ /*
111
+ * We map various devices into the container MR at their architected
112
+ * addresses. In particular, we map everything corresponding to the
113
+ * "System PPB" space. This is the range from 0xe0000000 to 0xe00fffff
114
+ * and includes the NVIC, the System Control Space (system registers),
115
+ * the systick timer, and for CPUs with the Security extension an NS
116
+ * banked version of all of these.
117
+ *
118
+ * The default behaviour for unimplemented registers/ranges
119
+ * (for instance the Data Watchpoint and Trace unit at 0xe0001000)
120
+ * is to RAZ/WI for privileged access and BusFault for non-privileged
121
+ * access.
122
+ *
123
+ * The NVIC and System Control Space (SCS) starts at 0xe000e000
124
+ * and looks like this:
125
+ * 0x004 - ICTR
126
+ * 0x010 - 0xff - systick
127
+ * 0x100..0x7ec - NVIC
128
+ * 0x7f0..0xcff - Reserved
129
+ * 0xd00..0xd3c - SCS registers
130
+ * 0xd40..0xeff - Reserved or Not implemented
131
+ * 0xf00 - STIR
132
+ *
133
+ * Some registers within this space are banked between security states.
134
+ * In v8M there is a second range 0xe002e000..0xe002efff which is the
135
+ * NonSecure alias SCS; secure accesses to this behave like NS accesses
136
+ * to the main SCS range, and non-secure accesses (including when
137
+ * the security extension is not implemented) are RAZ/WI.
138
+ * Note that both the main SCS range and the alias range are defined
139
+ * to be exempt from memory attribution (R_BLJT) and so the memory
140
+ * transaction attribute always matches the current CPU security
141
+ * state (attrs.secure == env->v7m.secure). In the v7m_sysreg_ns_ops
142
+ * wrappers we change attrs.secure to indicate the NS access; so
143
+ * generally code determining which banked register to use should
144
+ * use attrs.secure; code determining actual behaviour of the system
145
+ * should use env->v7m.secure.
146
+ *
147
+ * Within the PPB space, some MRs overlap, and the priority
148
+ * of overlapping regions is:
149
+ * - default region (for RAZ/WI and BusFault) : -1
150
+ * - system register regions (provided by the NVIC) : 0
151
+ * - systick : 1
152
+ * This is because the systick device is a small block of registers
153
+ * in the middle of the other system control registers.
154
+ */
155
+
156
+ memory_region_init_io(&s->defaultmem, OBJECT(s), &ppb_default_ops, s,
157
+ "nvic-default", 0x100000);
158
+ memory_region_add_subregion_overlap(&s->container, 0xe0000000,
159
+ &s->defaultmem, -1);
160
+
161
/* Wire the NVIC up to the CPU */
162
sbd = SYS_BUS_DEVICE(&s->nvic);
163
sysbus_connect_irq(sbd, 0,
164
qdev_get_gpio_in(DEVICE(s->cpu), ARM_CPU_IRQ));
165
166
- memory_region_add_subregion(&s->container, 0xe0000000,
167
+ memory_region_add_subregion(&s->container, 0xe000e000,
168
sysbus_mmio_get_region(sbd, 0));
169
+ if (arm_feature(&s->cpu->env, ARM_FEATURE_V8)) {
170
+ /* Create the NS alias region for the NVIC sysregs */
171
+ memory_region_init_io(&s->sysreg_ns_mem, OBJECT(s),
172
+ &v7m_sysreg_ns_ops,
173
+ sysbus_mmio_get_region(sbd, 0),
174
+ "nvic_sysregs_ns", 0x1000);
175
+ memory_region_add_subregion(&s->container, 0xe002e000,
176
+ &s->sysreg_ns_mem);
177
+ }
178
179
/* Create and map the systick devices */
180
if (!sysbus_realize(SYS_BUS_DEVICE(&s->systick[M_REG_NS]), errp)) {
181
diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c
182
index XXXXXXX..XXXXXXX 100644
183
--- a/hw/intc/armv7m_nvic.c
184
+++ b/hw/intc/armv7m_nvic.c
185
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps nvic_sysreg_ops = {
186
.endianness = DEVICE_NATIVE_ENDIAN,
187
};
188
189
-static MemTxResult nvic_sysreg_ns_write(void *opaque, hwaddr addr,
190
- uint64_t value, unsigned size,
191
- MemTxAttrs attrs)
192
-{
193
- MemoryRegion *mr = opaque;
194
-
195
- if (attrs.secure) {
196
- /* S accesses to the alias act like NS accesses to the real region */
197
- attrs.secure = 0;
198
- return memory_region_dispatch_write(mr, addr, value,
199
- size_memop(size) | MO_TE, attrs);
200
- } else {
201
- /* NS attrs are RAZ/WI for privileged, and BusFault for user */
202
- if (attrs.user) {
203
- return MEMTX_ERROR;
204
- }
205
- return MEMTX_OK;
206
- }
207
-}
208
-
209
-static MemTxResult nvic_sysreg_ns_read(void *opaque, hwaddr addr,
210
- uint64_t *data, unsigned size,
211
- MemTxAttrs attrs)
212
-{
213
- MemoryRegion *mr = opaque;
214
-
215
- if (attrs.secure) {
216
- /* S accesses to the alias act like NS accesses to the real region */
217
- attrs.secure = 0;
218
- return memory_region_dispatch_read(mr, addr, data,
219
- size_memop(size) | MO_TE, attrs);
220
- } else {
221
- /* NS attrs are RAZ/WI for privileged, and BusFault for user */
222
- if (attrs.user) {
223
- return MEMTX_ERROR;
224
- }
225
- *data = 0;
226
- return MEMTX_OK;
227
- }
228
-}
229
-
230
-static const MemoryRegionOps nvic_sysreg_ns_ops = {
231
- .read_with_attrs = nvic_sysreg_ns_read,
232
- .write_with_attrs = nvic_sysreg_ns_write,
233
- .endianness = DEVICE_NATIVE_ENDIAN,
234
-};
235
-
236
-/*
237
- * Unassigned portions of the PPB space are RAZ/WI for privileged
238
- * accesses, and fault for non-privileged accesses.
239
- */
240
-static MemTxResult ppb_default_read(void *opaque, hwaddr addr,
241
- uint64_t *data, unsigned size,
242
- MemTxAttrs attrs)
243
-{
244
- qemu_log_mask(LOG_UNIMP, "Read of unassigned area of PPB: offset 0x%x\n",
245
- (uint32_t)addr);
246
- if (attrs.user) {
247
- return MEMTX_ERROR;
248
- }
249
- *data = 0;
250
- return MEMTX_OK;
251
-}
252
-
253
-static MemTxResult ppb_default_write(void *opaque, hwaddr addr,
254
- uint64_t value, unsigned size,
255
- MemTxAttrs attrs)
256
-{
257
- qemu_log_mask(LOG_UNIMP, "Write of unassigned area of PPB: offset 0x%x\n",
258
- (uint32_t)addr);
259
- if (attrs.user) {
260
- return MEMTX_ERROR;
261
- }
262
- return MEMTX_OK;
263
-}
264
-
265
-static const MemoryRegionOps ppb_default_ops = {
266
- .read_with_attrs = ppb_default_read,
267
- .write_with_attrs = ppb_default_write,
268
- .endianness = DEVICE_NATIVE_ENDIAN,
269
- .valid.min_access_size = 1,
270
- .valid.max_access_size = 8,
271
-};
272
-
273
static int nvic_post_load(void *opaque, int version_id)
274
{
275
NVICState *s = opaque;
276
@@ -XXX,XX +XXX,XX @@ static void armv7m_nvic_realize(DeviceState *dev, Error **errp)
277
s->num_prio_bits = arm_feature(&s->cpu->env, ARM_FEATURE_V7) ? 8 : 2;
278
279
/*
280
- * This device provides a single sysbus memory region which
281
- * represents the whole of the "System PPB" space. This is the
282
- * range from 0xe0000000 to 0xe00fffff and includes the NVIC,
283
- * the System Control Space (system registers), the systick timer,
284
- * and for CPUs with the Security extension an NS banked version
285
- * of all of these.
286
- *
287
- * The default behaviour for unimplemented registers/ranges
288
- * (for instance the Data Watchpoint and Trace unit at 0xe0001000)
289
- * is to RAZ/WI for privileged access and BusFault for non-privileged
290
- * access.
291
- *
292
- * The NVIC and System Control Space (SCS) starts at 0xe000e000
293
- * and looks like this:
294
- * 0x004 - ICTR
295
- * 0x010 - 0xff - systick
296
- * 0x100..0x7ec - NVIC
297
- * 0x7f0..0xcff - Reserved
298
- * 0xd00..0xd3c - SCS registers
299
- * 0xd40..0xeff - Reserved or Not implemented
300
- * 0xf00 - STIR
301
- *
302
- * Some registers within this space are banked between security states.
303
- * In v8M there is a second range 0xe002e000..0xe002efff which is the
304
- * NonSecure alias SCS; secure accesses to this behave like NS accesses
305
- * to the main SCS range, and non-secure accesses (including when
306
- * the security extension is not implemented) are RAZ/WI.
307
- * Note that both the main SCS range and the alias range are defined
308
- * to be exempt from memory attribution (R_BLJT) and so the memory
309
- * transaction attribute always matches the current CPU security
310
- * state (attrs.secure == env->v7m.secure). In the nvic_sysreg_ns_ops
311
- * wrappers we change attrs.secure to indicate the NS access; so
312
- * generally code determining which banked register to use should
313
- * use attrs.secure; code determining actual behaviour of the system
314
- * should use env->v7m.secure.
315
- *
316
- * The container covers the whole PPB space. Within it the priority
317
- * of overlapping regions is:
318
- * - default region (for RAZ/WI and BusFault) : -1
319
- * - system register regions : 0
320
- * - systick : 1
321
- * This is because the systick device is a small block of registers
322
- * in the middle of the other system control registers.
323
+ * This device provides a single memory region which covers the
324
+ * sysreg/NVIC registers from 0xE000E000 .. 0xE000EFFF, with the
325
+ * exception of the systick timer registers 0xE000E010 .. 0xE000E0FF.
326
*/
327
- memory_region_init(&s->container, OBJECT(s), "nvic", 0x100000);
328
- memory_region_init_io(&s->defaultmem, OBJECT(s), &ppb_default_ops, s,
329
- "nvic-default", 0x100000);
330
- memory_region_add_subregion_overlap(&s->container, 0, &s->defaultmem, -1);
331
memory_region_init_io(&s->sysregmem, OBJECT(s), &nvic_sysreg_ops, s,
332
"nvic_sysregs", 0x1000);
333
- memory_region_add_subregion(&s->container, 0xe000, &s->sysregmem);
334
-
335
- if (arm_feature(&s->cpu->env, ARM_FEATURE_V8)) {
336
- memory_region_init_io(&s->sysreg_ns_mem, OBJECT(s),
337
- &nvic_sysreg_ns_ops, &s->sysregmem,
338
- "nvic_sysregs_ns", 0x1000);
339
- memory_region_add_subregion(&s->container, 0x2e000, &s->sysreg_ns_mem);
340
- }
341
-
342
- sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->container);
343
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->sysregmem);
344
}
345
346
static void armv7m_nvic_instance_init(Object *obj)
347
--
348
2.20.1
349
350
diff view generated by jsdifflib
New patch
1
Add the usual-style QEMU interface comment documenting what
2
properties, etc, this device exposes.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
Reviewed-by: Luc Michel <luc@lmichel.fr>
7
Message-id: 20210812093356.1946-5-peter.maydell@linaro.org
8
---
9
include/hw/timer/armv7m_systick.h | 7 +++++++
10
1 file changed, 7 insertions(+)
11
12
diff --git a/include/hw/timer/armv7m_systick.h b/include/hw/timer/armv7m_systick.h
13
index XXXXXXX..XXXXXXX 100644
14
--- a/include/hw/timer/armv7m_systick.h
15
+++ b/include/hw/timer/armv7m_systick.h
16
@@ -XXX,XX +XXX,XX @@
17
18
OBJECT_DECLARE_SIMPLE_TYPE(SysTickState, SYSTICK)
19
20
+/*
21
+ * QEMU interface:
22
+ * + sysbus MMIO region 0 is the register interface (covering
23
+ * the registers which are mapped at address 0xE000E010)
24
+ * + sysbus IRQ 0 is the interrupt line to the NVIC
25
+ */
26
+
27
struct SysTickState {
28
/*< private >*/
29
SysBusDevice parent_obj;
30
--
31
2.20.1
32
33
diff view generated by jsdifflib
New patch
1
The v7M systick timer can be programmed to run from either of
2
two clocks:
3
* an "external reference clock" (when SYST_CSR.CLKSOURCE == 0)
4
* the main CPU clock (when SYST_CSR.CLKSOURCE == 1)
1
5
6
Our implementation currently hardwires the external reference clock
7
to be 1MHz, and allows boards to set the main CPU clock frequency via
8
the global 'system_clock_scale'. (Most boards set that to a constant
9
value; the Stellaris boards allow the guest to reprogram it via the
10
board-specific RCC registers).
11
12
As the first step in converting this to use the Clock infrastructure,
13
add input clocks to the systick device for the reference clock and
14
the CPU clock. The device implementation ignores them; once we have
15
made all the users of the device correctly wire up the new Clocks we
16
will switch the implementation to use them and ignore the old
17
system_clock_scale.
18
19
This is a migration compat break for all M-profile boards, because of
20
the addition of the new clock objects to the vmstate struct.
21
22
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
23
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
24
Reviewed-by: Luc Michel <luc@lmichel.fr>
25
Message-id: 20210812093356.1946-6-peter.maydell@linaro.org
26
---
27
include/hw/timer/armv7m_systick.h | 7 +++++++
28
hw/timer/armv7m_systick.c | 10 ++++++++--
29
2 files changed, 15 insertions(+), 2 deletions(-)
30
31
diff --git a/include/hw/timer/armv7m_systick.h b/include/hw/timer/armv7m_systick.h
32
index XXXXXXX..XXXXXXX 100644
33
--- a/include/hw/timer/armv7m_systick.h
34
+++ b/include/hw/timer/armv7m_systick.h
35
@@ -XXX,XX +XXX,XX @@
36
#include "hw/sysbus.h"
37
#include "qom/object.h"
38
#include "hw/ptimer.h"
39
+#include "hw/clock.h"
40
41
#define TYPE_SYSTICK "armv7m_systick"
42
43
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(SysTickState, SYSTICK)
44
* + sysbus MMIO region 0 is the register interface (covering
45
* the registers which are mapped at address 0xE000E010)
46
* + sysbus IRQ 0 is the interrupt line to the NVIC
47
+ * + Clock input "refclk" is the external reference clock
48
+ * (used when SYST_CSR.CLKSOURCE == 0)
49
+ * + Clock input "cpuclk" is the main CPU clock
50
+ * (used when SYST_CSR.CLKSOURCE == 1)
51
*/
52
53
struct SysTickState {
54
@@ -XXX,XX +XXX,XX @@ struct SysTickState {
55
ptimer_state *ptimer;
56
MemoryRegion iomem;
57
qemu_irq irq;
58
+ Clock *refclk;
59
+ Clock *cpuclk;
60
};
61
62
/*
63
diff --git a/hw/timer/armv7m_systick.c b/hw/timer/armv7m_systick.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/hw/timer/armv7m_systick.c
66
+++ b/hw/timer/armv7m_systick.c
67
@@ -XXX,XX +XXX,XX @@
68
#include "migration/vmstate.h"
69
#include "hw/irq.h"
70
#include "hw/sysbus.h"
71
+#include "hw/qdev-clock.h"
72
#include "qemu/timer.h"
73
#include "qemu/log.h"
74
#include "qemu/module.h"
75
@@ -XXX,XX +XXX,XX @@ static void systick_instance_init(Object *obj)
76
memory_region_init_io(&s->iomem, obj, &systick_ops, s, "systick", 0xe0);
77
sysbus_init_mmio(sbd, &s->iomem);
78
sysbus_init_irq(sbd, &s->irq);
79
+
80
+ s->refclk = qdev_init_clock_in(DEVICE(obj), "refclk", NULL, NULL, 0);
81
+ s->cpuclk = qdev_init_clock_in(DEVICE(obj), "cpuclk", NULL, NULL, 0);
82
}
83
84
static void systick_realize(DeviceState *dev, Error **errp)
85
@@ -XXX,XX +XXX,XX @@ static void systick_realize(DeviceState *dev, Error **errp)
86
87
static const VMStateDescription vmstate_systick = {
88
.name = "armv7m_systick",
89
- .version_id = 2,
90
- .minimum_version_id = 2,
91
+ .version_id = 3,
92
+ .minimum_version_id = 3,
93
.fields = (VMStateField[]) {
94
+ VMSTATE_CLOCK(refclk, SysTickState),
95
+ VMSTATE_CLOCK(cpuclk, SysTickState),
96
VMSTATE_UINT32(control, SysTickState),
97
VMSTATE_INT64(tick, SysTickState),
98
VMSTATE_PTIMER(ptimer, SysTickState),
99
--
100
2.20.1
101
102
diff view generated by jsdifflib
New patch
1
Create input clocks on the armv7m container object which pass through
2
to the systick timers, so that users of the armv7m object can specify
3
the clocks being used.
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
8
Message-id: 20210812093356.1946-7-peter.maydell@linaro.org
9
---
10
include/hw/arm/armv7m.h | 6 ++++++
11
hw/arm/armv7m.c | 23 +++++++++++++++++++++++
12
2 files changed, 29 insertions(+)
13
14
diff --git a/include/hw/arm/armv7m.h b/include/hw/arm/armv7m.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/arm/armv7m.h
17
+++ b/include/hw/arm/armv7m.h
18
@@ -XXX,XX +XXX,XX @@
19
#include "hw/misc/armv7m_ras.h"
20
#include "target/arm/idau.h"
21
#include "qom/object.h"
22
+#include "hw/clock.h"
23
24
#define TYPE_BITBAND "ARM-bitband-memory"
25
OBJECT_DECLARE_SIMPLE_TYPE(BitBandState, BITBAND)
26
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(ARMv7MState, ARMV7M)
27
* + Property "vfp": enable VFP (forwarded to CPU object)
28
* + Property "dsp": enable DSP (forwarded to CPU object)
29
* + Property "enable-bitband": expose bitbanded IO
30
+ * + Clock input "refclk" is the external reference clock for the systick timers
31
+ * + Clock input "cpuclk" is the main CPU clock
32
*/
33
struct ARMv7MState {
34
/*< private >*/
35
@@ -XXX,XX +XXX,XX @@ struct ARMv7MState {
36
/* MR providing default PPB behaviour */
37
MemoryRegion defaultmem;
38
39
+ Clock *refclk;
40
+ Clock *cpuclk;
41
+
42
/* Properties */
43
char *cpu_type;
44
/* MemoryRegion the board provides to us (with its devices, RAM, etc) */
45
diff --git a/hw/arm/armv7m.c b/hw/arm/armv7m.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/hw/arm/armv7m.c
48
+++ b/hw/arm/armv7m.c
49
@@ -XXX,XX +XXX,XX @@
50
#include "hw/arm/boot.h"
51
#include "hw/loader.h"
52
#include "hw/qdev-properties.h"
53
+#include "hw/qdev-clock.h"
54
#include "elf.h"
55
#include "sysemu/reset.h"
56
#include "qemu/error-report.h"
57
#include "qemu/module.h"
58
#include "qemu/log.h"
59
#include "target/arm/idau.h"
60
+#include "migration/vmstate.h"
61
62
/* Bitbanded IO. Each word corresponds to a single bit. */
63
64
@@ -XXX,XX +XXX,XX @@ static void armv7m_instance_init(Object *obj)
65
object_initialize_child(obj, "bitband[*]", &s->bitband[i],
66
TYPE_BITBAND);
67
}
68
+
69
+ s->refclk = qdev_init_clock_in(DEVICE(obj), "refclk", NULL, NULL, 0);
70
+ s->cpuclk = qdev_init_clock_in(DEVICE(obj), "cpuclk", NULL, NULL, 0);
71
}
72
73
static void armv7m_realize(DeviceState *dev, Error **errp)
74
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
75
}
76
77
/* Create and map the systick devices */
78
+ qdev_connect_clock_in(DEVICE(&s->systick[M_REG_NS]), "refclk", s->refclk);
79
+ qdev_connect_clock_in(DEVICE(&s->systick[M_REG_NS]), "cpuclk", s->cpuclk);
80
if (!sysbus_realize(SYS_BUS_DEVICE(&s->systick[M_REG_NS]), errp)) {
81
return;
82
}
83
@@ -XXX,XX +XXX,XX @@ static void armv7m_realize(DeviceState *dev, Error **errp)
84
*/
85
object_initialize_child(OBJECT(dev), "systick-reg-s",
86
&s->systick[M_REG_S], TYPE_SYSTICK);
87
+ qdev_connect_clock_in(DEVICE(&s->systick[M_REG_S]), "refclk",
88
+ s->refclk);
89
+ qdev_connect_clock_in(DEVICE(&s->systick[M_REG_S]), "cpuclk",
90
+ s->cpuclk);
91
92
if (!sysbus_realize(SYS_BUS_DEVICE(&s->systick[M_REG_S]), errp)) {
93
return;
94
@@ -XXX,XX +XXX,XX @@ static Property armv7m_properties[] = {
95
DEFINE_PROP_END_OF_LIST(),
96
};
97
98
+static const VMStateDescription vmstate_armv7m = {
99
+ .name = "armv7m",
100
+ .version_id = 1,
101
+ .minimum_version_id = 1,
102
+ .fields = (VMStateField[]) {
103
+ VMSTATE_CLOCK(refclk, SysTickState),
104
+ VMSTATE_CLOCK(cpuclk, SysTickState),
105
+ VMSTATE_END_OF_LIST()
106
+ }
107
+};
108
+
109
static void armv7m_class_init(ObjectClass *klass, void *data)
110
{
111
DeviceClass *dc = DEVICE_CLASS(klass);
112
113
dc->realize = armv7m_realize;
114
+ dc->vmsd = &vmstate_armv7m;
115
device_class_set_props(dc, armv7m_properties);
116
}
117
118
--
119
2.20.1
120
121
diff view generated by jsdifflib
New patch
1
Wire up the cpuclk for the systick devices to the SSE object's
2
existing mainclk clock.
1
3
4
We do not wire up the refclk because the SSE subsystems do not
5
provide a refclk. (This is documented in the IoTKit and SSE-200
6
TRMs; the SSE-300 TRM doesn't mention it but we assume it follows the
7
same approach.) When we update the systick device later to honour "no
8
refclk connected" this will fix a minor emulation inaccuracy for the
9
SSE-based boards.
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Acked-by: Alistair Francis <alistair.francis@wdc.com>
13
Reviewed-by: Luc Michel <luc@lmichel.fr>
14
Message-id: 20210812093356.1946-8-peter.maydell@linaro.org
15
---
16
hw/arm/armsse.c | 3 +++
17
1 file changed, 3 insertions(+)
18
19
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/arm/armsse.c
22
+++ b/hw/arm/armsse.c
23
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
24
int j;
25
char *gpioname;
26
27
+ qdev_connect_clock_in(cpudev, "cpuclk", s->mainclk);
28
+ /* The SSE subsystems do not wire up a systick refclk */
29
+
30
qdev_prop_set_uint32(cpudev, "num-irq", s->exp_numirq + NUM_SSE_IRQS);
31
/*
32
* In real hardware the initial Secure VTOR is set from the INITSVTOR*
33
--
34
2.20.1
35
36
diff view generated by jsdifflib
New patch
1
Connect up the armv7m clocks on the mps2-an385/386/500/511.
1
2
3
Connect up the armv7m object's clocks on the MPS boards defined in
4
mps2.c. The documentation for these FPGA images doesn't specify what
5
systick reference clock is used (if any), so for the moment we
6
provide a 1MHz refclock, which will result in no behavioural change
7
from the current hardwired 1MHz clock implemented in
8
armv7m_systick.c:systick_scale().
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Luc Michel <luc@lmichel.fr>
12
Message-id: 20210812093356.1946-9-peter.maydell@linaro.org
13
---
14
hw/arm/mps2.c | 15 +++++++++++++++
15
1 file changed, 15 insertions(+)
16
17
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/mps2.c
20
+++ b/hw/arm/mps2.c
21
@@ -XXX,XX +XXX,XX @@ struct MPS2MachineState {
22
CMSDKAPBWatchdog watchdog;
23
CMSDKAPBTimer timer[2];
24
Clock *sysclk;
25
+ Clock *refclk;
26
};
27
28
#define TYPE_MPS2_MACHINE "mps2"
29
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(MPS2MachineState, MPS2MachineClass, MPS2_MACHINE)
30
/* Main SYSCLK frequency in Hz */
31
#define SYSCLK_FRQ 25000000
32
33
+/*
34
+ * The Application Notes don't say anything about how the
35
+ * systick reference clock is configured. (Quite possibly
36
+ * they don't have one at all.) This 1MHz clock matches the
37
+ * pre-existing behaviour that used to be hardcoded in the
38
+ * armv7m_systick implementation.
39
+ */
40
+#define REFCLK_FRQ (1 * 1000 * 1000)
41
+
42
/* Initialize the auxiliary RAM region @mr and map it into
43
* the memory map at @base.
44
*/
45
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
46
mms->sysclk = clock_new(OBJECT(machine), "SYSCLK");
47
clock_set_hz(mms->sysclk, SYSCLK_FRQ);
48
49
+ mms->refclk = clock_new(OBJECT(machine), "REFCLK");
50
+ clock_set_hz(mms->refclk, REFCLK_FRQ);
51
+
52
/* The FPGA images have an odd combination of different RAMs,
53
* because in hardware they are different implementations and
54
* connected to different buses, giving varying performance/size
55
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
56
default:
57
g_assert_not_reached();
58
}
59
+ qdev_connect_clock_in(armv7m, "cpuclk", mms->sysclk);
60
+ qdev_connect_clock_in(armv7m, "refclk", mms->refclk);
61
qdev_prop_set_string(armv7m, "cpu-type", machine->cpu_type);
62
qdev_prop_set_bit(armv7m, "enable-bitband", true);
63
object_property_set_link(OBJECT(&mms->armv7m), "memory",
64
--
65
2.20.1
66
67
diff view generated by jsdifflib
1
Convert the Neon 2-reg-scalar long multiplies to decodetree.
1
It is quite common for a clock tree to involve possibly programmable
2
These are the last instructions in the group.
2
clock multipliers or dividers, where the frequency of a clock is for
3
instance divided by 8 to produce a slower clock to feed to a
4
particular device.
5
6
Currently we provide no convenient mechanism for modelling this. You
7
can implement it by having an input Clock and an output Clock, and
8
manually setting the period of the output clock in the period-changed
9
callback of the input clock, but that's quite clunky.
10
11
This patch adds support in the Clock objects themselves for setting a
12
multiplier or divider. The effect of setting this on a clock is that
13
when the clock's period is changed, all the children of the clock are
14
set to period * multiplier / divider, rather than being set to the
15
same period as the parent clock.
3
16
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Reviewed-by: Alexandre Iooss <erdnaxe@crans.org>
19
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
20
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
21
Reviewed-by: Luc Michel <luc@lmichel.fr>
22
Reviewed-by: Damien Hedde <damien.hedde@greensocs.com>
23
Message-id: 20210812093356.1946-10-peter.maydell@linaro.org
6
---
24
---
7
target/arm/neon-dp.decode | 18 ++++
25
docs/devel/clocks.rst | 23 +++++++++++++++++++++++
8
target/arm/translate-neon.inc.c | 163 ++++++++++++++++++++++++++++
26
include/hw/clock.h | 29 +++++++++++++++++++++++++++++
9
target/arm/translate.c | 182 ++------------------------------
27
hw/core/clock-vmstate.c | 40 +++++++++++++++++++++++++++++++++++++++-
10
3 files changed, 187 insertions(+), 176 deletions(-)
28
hw/core/clock.c | 31 +++++++++++++++++++++++++++----
11
29
hw/core/trace-events | 1 +
12
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
30
5 files changed, 119 insertions(+), 5 deletions(-)
13
index XXXXXXX..XXXXXXX 100644
31
14
--- a/target/arm/neon-dp.decode
32
diff --git a/docs/devel/clocks.rst b/docs/devel/clocks.rst
15
+++ b/target/arm/neon-dp.decode
33
index XXXXXXX..XXXXXXX 100644
16
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
34
--- a/docs/devel/clocks.rst
17
35
+++ b/docs/devel/clocks.rst
18
@2scalar .... ... q:1 . . size:2 .... .... .... . . . . .... \
36
@@ -XXX,XX +XXX,XX @@ clocks get the new clock period value: *Clock 2*, *Clock 3* and *Clock 4*.
19
&2scalar vm=%vm_dp vn=%vn_dp vd=%vd_dp
37
It is not possible to disconnect a clock or to change the clock connection
20
+ # For the 'long' ops the Q bit is part of insn decode
38
after it is connected.
21
+ @2scalar_q0 .... ... . . . size:2 .... .... .... . . . . .... \
39
22
+ &2scalar vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0
40
+Clock multiplier and divider settings
23
41
+-------------------------------------
24
VMLA_2sc 1111 001 . 1 . .. .... .... 0000 . 1 . 0 .... @2scalar
42
+
25
VMLA_F_2sc 1111 001 . 1 . .. .... .... 0001 . 1 . 0 .... @2scalar
43
+By default, when clocks are connected together, the child
26
44
+clocks run with the same period as their source (parent) clock.
27
+ VMLAL_S_2sc 1111 001 0 1 . .. .... .... 0010 . 1 . 0 .... @2scalar_q0
45
+The Clock API supports a built-in period multiplier/divider
28
+ VMLAL_U_2sc 1111 001 1 1 . .. .... .... 0010 . 1 . 0 .... @2scalar_q0
46
+mechanism so you can configure a clock to make its children
29
+
47
+run at a different period from its own. If you call the
30
+ VQDMLAL_2sc 1111 001 0 1 . .. .... .... 0011 . 1 . 0 .... @2scalar_q0
48
+``clock_set_mul_div()`` function you can specify the clock's
31
+
49
+multiplier and divider values. The children of that clock
32
VMLS_2sc 1111 001 . 1 . .. .... .... 0100 . 1 . 0 .... @2scalar
50
+will all run with a period of ``parent_period * multiplier / divider``.
33
VMLS_F_2sc 1111 001 . 1 . .. .... .... 0101 . 1 . 0 .... @2scalar
51
+For instance, if the clock has a frequency of 8MHz and you set its
34
52
+multiplier to 2 and its divider to 3, the child clocks will run
35
+ VMLSL_S_2sc 1111 001 0 1 . .. .... .... 0110 . 1 . 0 .... @2scalar_q0
53
+at 12MHz.
36
+ VMLSL_U_2sc 1111 001 1 1 . .. .... .... 0110 . 1 . 0 .... @2scalar_q0
54
+
37
+
55
+You can change the multiplier and divider of a clock at runtime,
38
+ VQDMLSL_2sc 1111 001 0 1 . .. .... .... 0111 . 1 . 0 .... @2scalar_q0
56
+so you can use this to model clock controller devices which
39
+
57
+have guest-programmable frequency multipliers or dividers.
40
VMUL_2sc 1111 001 . 1 . .. .... .... 1000 . 1 . 0 .... @2scalar
58
+
41
VMUL_F_2sc 1111 001 . 1 . .. .... .... 1001 . 1 . 0 .... @2scalar
59
+Note that ``clock_set_mul_div()`` does not automatically call
42
60
+``clock_propagate()``. If you make a runtime change to the
43
+ VMULL_S_2sc 1111 001 0 1 . .. .... .... 1010 . 1 . 0 .... @2scalar_q0
61
+multiplier or divider you must call clock_propagate() yourself.
44
+ VMULL_U_2sc 1111 001 1 1 . .. .... .... 1010 . 1 . 0 .... @2scalar_q0
62
+
45
+
63
Unconnected input clocks
46
+ VQDMULL_2sc 1111 001 0 1 . .. .... .... 1011 . 1 . 0 .... @2scalar_q0
64
------------------------
47
+
65
48
VQDMULH_2sc 1111 001 . 1 . .. .... .... 1100 . 1 . 0 .... @2scalar
66
diff --git a/include/hw/clock.h b/include/hw/clock.h
49
VQRDMULH_2sc 1111 001 . 1 . .. .... .... 1101 . 1 . 0 .... @2scalar
67
index XXXXXXX..XXXXXXX 100644
50
68
--- a/include/hw/clock.h
51
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
69
+++ b/include/hw/clock.h
52
index XXXXXXX..XXXXXXX 100644
70
@@ -XXX,XX +XXX,XX @@ struct Clock {
53
--- a/target/arm/translate-neon.inc.c
71
void *callback_opaque;
54
+++ b/target/arm/translate-neon.inc.c
72
unsigned int callback_events;
55
@@ -XXX,XX +XXX,XX @@ static bool trans_VQRDMLSH_2sc(DisasContext *s, arg_2scalar *a)
73
56
};
74
+ /* Ratio of the parent clock to run the child clocks at */
57
return do_vqrdmlah_2sc(s, a, opfn[a->size]);
75
+ uint32_t multiplier;
76
+ uint32_t divider;
77
+
78
/* Clocks are organized in a clock tree */
79
Clock *source;
80
QLIST_HEAD(, Clock) children;
81
@@ -XXX,XX +XXX,XX @@ static inline bool clock_is_enabled(const Clock *clk)
82
*/
83
char *clock_display_freq(Clock *clk);
84
85
+/**
86
+ * clock_set_mul_div: set multiplier/divider for child clocks
87
+ * @clk: clock
88
+ * @multiplier: multiplier value
89
+ * @divider: divider value
90
+ *
91
+ * By default, a Clock's children will all run with the same period
92
+ * as their parent. This function allows you to adjust the multiplier
93
+ * and divider used to derive the child clock frequency.
94
+ * For example, setting a multiplier of 2 and a divider of 3
95
+ * will run child clocks with a period 2/3 of the parent clock,
96
+ * so if the parent clock is an 8MHz clock the children will
97
+ * be 12MHz.
98
+ *
99
+ * Setting the multiplier to 0 will stop the child clocks.
100
+ * Setting the divider to 0 is a programming error (diagnosed with
101
+ * an assertion failure).
102
+ * Setting a multiplier value that results in the child period
103
+ * overflowing is not diagnosed.
104
+ *
105
+ * Note that this function does not call clock_propagate(); the
106
+ * caller should do that if necessary.
107
+ */
108
+void clock_set_mul_div(Clock *clk, uint32_t multiplier, uint32_t divider);
109
+
110
#endif /* QEMU_HW_CLOCK_H */
111
diff --git a/hw/core/clock-vmstate.c b/hw/core/clock-vmstate.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/hw/core/clock-vmstate.c
114
+++ b/hw/core/clock-vmstate.c
115
@@ -XXX,XX +XXX,XX @@
116
#include "migration/vmstate.h"
117
#include "hw/clock.h"
118
119
+static bool muldiv_needed(void *opaque)
120
+{
121
+ Clock *clk = opaque;
122
+
123
+ return clk->multiplier != 1 || clk->divider != 1;
124
+}
125
+
126
+static int clock_pre_load(void *opaque)
127
+{
128
+ Clock *clk = opaque;
129
+ /*
130
+ * The initial out-of-reset settings of the Clock might have been
131
+ * configured by the device to be different from what we set
132
+ * in clock_initfn(), so we must here set the default values to
133
+ * be used if they are not in the inbound migration state.
134
+ */
135
+ clk->multiplier = 1;
136
+ clk->divider = 1;
137
+
138
+ return 0;
139
+}
140
+
141
+const VMStateDescription vmstate_muldiv = {
142
+ .name = "clock/muldiv",
143
+ .version_id = 1,
144
+ .minimum_version_id = 1,
145
+ .needed = muldiv_needed,
146
+ .fields = (VMStateField[]) {
147
+ VMSTATE_UINT32(multiplier, Clock),
148
+ VMSTATE_UINT32(divider, Clock),
149
+ },
150
+};
151
+
152
const VMStateDescription vmstate_clock = {
153
.name = "clock",
154
.version_id = 0,
155
.minimum_version_id = 0,
156
+ .pre_load = clock_pre_load,
157
.fields = (VMStateField[]) {
158
VMSTATE_UINT64(period, Clock),
159
VMSTATE_END_OF_LIST()
160
- }
161
+ },
162
+ .subsections = (const VMStateDescription*[]) {
163
+ &vmstate_muldiv,
164
+ NULL
165
+ },
166
};
167
diff --git a/hw/core/clock.c b/hw/core/clock.c
168
index XXXXXXX..XXXXXXX 100644
169
--- a/hw/core/clock.c
170
+++ b/hw/core/clock.c
171
@@ -XXX,XX +XXX,XX @@ bool clock_set(Clock *clk, uint64_t period)
172
return true;
58
}
173
}
59
+
174
60
+static bool do_2scalar_long(DisasContext *s, arg_2scalar *a,
175
+static uint64_t clock_get_child_period(Clock *clk)
61
+ NeonGenTwoOpWidenFn *opfn,
62
+ NeonGenTwo64OpFn *accfn)
63
+{
176
+{
64
+ /*
177
+ /*
65
+ * Two registers and a scalar, long operations: perform an
178
+ * Return the period to be used for child clocks, which is the parent
66
+ * operation on the input elements and the scalar which produces
179
+ * clock period adjusted for for multiplier and divider effects.
67
+ * a double-width result, and then possibly perform an accumulation
68
+ * operation of that result into the destination.
69
+ */
180
+ */
70
+ TCGv_i32 scalar, rn;
181
+ return muldiv64(clk->period, clk->multiplier, clk->divider);
71
+ TCGv_i64 rn0_64, rn1_64;
182
+}
72
+
183
+
73
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
184
static void clock_call_callback(Clock *clk, ClockEvent event)
74
+ return false;
185
{
75
+ }
186
/*
76
+
187
@@ -XXX,XX +XXX,XX @@ static void clock_call_callback(Clock *clk, ClockEvent event)
77
+ /* UNDEF accesses to D16-D31 if they don't exist. */
188
static void clock_propagate_period(Clock *clk, bool call_callbacks)
78
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
189
{
79
+ ((a->vd | a->vn | a->vm) & 0x10)) {
190
Clock *child;
80
+ return false;
191
+ uint64_t child_period = clock_get_child_period(clk);
81
+ }
192
82
+
193
QLIST_FOREACH(child, &clk->children, sibling) {
83
+ if (!opfn) {
194
- if (child->period != clk->period) {
84
+ /* Bad size (including size == 3, which is a different insn group) */
195
+ if (child->period != child_period) {
85
+ return false;
196
if (call_callbacks) {
86
+ }
197
clock_call_callback(child, ClockPreUpdate);
87
+
198
}
88
+ if (a->vd & 1) {
199
- child->period = clk->period;
89
+ return false;
200
+ child->period = child_period;
90
+ }
201
trace_clock_update(CLOCK_PATH(child), CLOCK_PATH(clk),
91
+
202
- CLOCK_PERIOD_TO_HZ(clk->period),
92
+ if (!vfp_access_check(s)) {
203
+ CLOCK_PERIOD_TO_HZ(child->period),
93
+ return true;
204
call_callbacks);
94
+ }
205
if (call_callbacks) {
95
+
206
clock_call_callback(child, ClockUpdate);
96
+ scalar = neon_get_scalar(a->size, a->vm);
207
@@ -XXX,XX +XXX,XX @@ void clock_set_source(Clock *clk, Clock *src)
97
+
208
98
+ /* Load all inputs before writing any outputs, in case of overlap */
209
trace_clock_set_source(CLOCK_PATH(clk), CLOCK_PATH(src));
99
+ rn = neon_load_reg(a->vn, 0);
210
100
+ rn0_64 = tcg_temp_new_i64();
211
- clk->period = src->period;
101
+ opfn(rn0_64, rn, scalar);
212
+ clk->period = clock_get_child_period(src);
102
+ tcg_temp_free_i32(rn);
213
QLIST_INSERT_HEAD(&src->children, clk, sibling);
103
+
214
clk->source = src;
104
+ rn = neon_load_reg(a->vn, 1);
215
clock_propagate_period(clk, false);
105
+ rn1_64 = tcg_temp_new_i64();
216
@@ -XXX,XX +XXX,XX @@ char *clock_display_freq(Clock *clk)
106
+ opfn(rn1_64, rn, scalar);
217
return freq_to_str(clock_get_hz(clk));
107
+ tcg_temp_free_i32(rn);
108
+ tcg_temp_free_i32(scalar);
109
+
110
+ if (accfn) {
111
+ TCGv_i64 t64 = tcg_temp_new_i64();
112
+ neon_load_reg64(t64, a->vd);
113
+ accfn(t64, t64, rn0_64);
114
+ neon_store_reg64(t64, a->vd);
115
+ neon_load_reg64(t64, a->vd + 1);
116
+ accfn(t64, t64, rn1_64);
117
+ neon_store_reg64(t64, a->vd + 1);
118
+ tcg_temp_free_i64(t64);
119
+ } else {
120
+ neon_store_reg64(rn0_64, a->vd);
121
+ neon_store_reg64(rn1_64, a->vd + 1);
122
+ }
123
+ tcg_temp_free_i64(rn0_64);
124
+ tcg_temp_free_i64(rn1_64);
125
+ return true;
126
+}
127
+
128
+static bool trans_VMULL_S_2sc(DisasContext *s, arg_2scalar *a)
129
+{
130
+ static NeonGenTwoOpWidenFn * const opfn[] = {
131
+ NULL,
132
+ gen_helper_neon_mull_s16,
133
+ gen_mull_s32,
134
+ NULL,
135
+ };
136
+
137
+ return do_2scalar_long(s, a, opfn[a->size], NULL);
138
+}
139
+
140
+static bool trans_VMULL_U_2sc(DisasContext *s, arg_2scalar *a)
141
+{
142
+ static NeonGenTwoOpWidenFn * const opfn[] = {
143
+ NULL,
144
+ gen_helper_neon_mull_u16,
145
+ gen_mull_u32,
146
+ NULL,
147
+ };
148
+
149
+ return do_2scalar_long(s, a, opfn[a->size], NULL);
150
+}
151
+
152
+#define DO_VMLAL_2SC(INSN, MULL, ACC) \
153
+ static bool trans_##INSN##_2sc(DisasContext *s, arg_2scalar *a) \
154
+ { \
155
+ static NeonGenTwoOpWidenFn * const opfn[] = { \
156
+ NULL, \
157
+ gen_helper_neon_##MULL##16, \
158
+ gen_##MULL##32, \
159
+ NULL, \
160
+ }; \
161
+ static NeonGenTwo64OpFn * const accfn[] = { \
162
+ NULL, \
163
+ gen_helper_neon_##ACC##l_u32, \
164
+ tcg_gen_##ACC##_i64, \
165
+ NULL, \
166
+ }; \
167
+ return do_2scalar_long(s, a, opfn[a->size], accfn[a->size]); \
168
+ }
169
+
170
+DO_VMLAL_2SC(VMLAL_S, mull_s, add)
171
+DO_VMLAL_2SC(VMLAL_U, mull_u, add)
172
+DO_VMLAL_2SC(VMLSL_S, mull_s, sub)
173
+DO_VMLAL_2SC(VMLSL_U, mull_u, sub)
174
+
175
+static bool trans_VQDMULL_2sc(DisasContext *s, arg_2scalar *a)
176
+{
177
+ static NeonGenTwoOpWidenFn * const opfn[] = {
178
+ NULL,
179
+ gen_VQDMULL_16,
180
+ gen_VQDMULL_32,
181
+ NULL,
182
+ };
183
+
184
+ return do_2scalar_long(s, a, opfn[a->size], NULL);
185
+}
186
+
187
+static bool trans_VQDMLAL_2sc(DisasContext *s, arg_2scalar *a)
188
+{
189
+ static NeonGenTwoOpWidenFn * const opfn[] = {
190
+ NULL,
191
+ gen_VQDMULL_16,
192
+ gen_VQDMULL_32,
193
+ NULL,
194
+ };
195
+ static NeonGenTwo64OpFn * const accfn[] = {
196
+ NULL,
197
+ gen_VQDMLAL_acc_16,
198
+ gen_VQDMLAL_acc_32,
199
+ NULL,
200
+ };
201
+
202
+ return do_2scalar_long(s, a, opfn[a->size], accfn[a->size]);
203
+}
204
+
205
+static bool trans_VQDMLSL_2sc(DisasContext *s, arg_2scalar *a)
206
+{
207
+ static NeonGenTwoOpWidenFn * const opfn[] = {
208
+ NULL,
209
+ gen_VQDMULL_16,
210
+ gen_VQDMULL_32,
211
+ NULL,
212
+ };
213
+ static NeonGenTwo64OpFn * const accfn[] = {
214
+ NULL,
215
+ gen_VQDMLSL_acc_16,
216
+ gen_VQDMLSL_acc_32,
217
+ NULL,
218
+ };
219
+
220
+ return do_2scalar_long(s, a, opfn[a->size], accfn[a->size]);
221
+}
222
diff --git a/target/arm/translate.c b/target/arm/translate.c
223
index XXXXXXX..XXXXXXX 100644
224
--- a/target/arm/translate.c
225
+++ b/target/arm/translate.c
226
@@ -XXX,XX +XXX,XX @@ static void gen_revsh(TCGv_i32 dest, TCGv_i32 var)
227
tcg_gen_ext16s_i32(dest, var);
228
}
218
}
229
219
230
-/* 32x32->64 multiply. Marks inputs as dead. */
220
+void clock_set_mul_div(Clock *clk, uint32_t multiplier, uint32_t divider)
231
-static TCGv_i64 gen_mulu_i64_i32(TCGv_i32 a, TCGv_i32 b)
221
+{
232
-{
222
+ assert(divider != 0);
233
- TCGv_i32 lo = tcg_temp_new_i32();
223
+
234
- TCGv_i32 hi = tcg_temp_new_i32();
224
+ trace_clock_set_mul_div(CLOCK_PATH(clk), clk->multiplier, multiplier,
235
- TCGv_i64 ret;
225
+ clk->divider, divider);
236
-
226
+ clk->multiplier = multiplier;
237
- tcg_gen_mulu2_i32(lo, hi, a, b);
227
+ clk->divider = divider;
238
- tcg_temp_free_i32(a);
228
+}
239
- tcg_temp_free_i32(b);
229
+
240
-
230
static void clock_initfn(Object *obj)
241
- ret = tcg_temp_new_i64();
242
- tcg_gen_concat_i32_i64(ret, lo, hi);
243
- tcg_temp_free_i32(lo);
244
- tcg_temp_free_i32(hi);
245
-
246
- return ret;
247
-}
248
-
249
-static TCGv_i64 gen_muls_i64_i32(TCGv_i32 a, TCGv_i32 b)
250
-{
251
- TCGv_i32 lo = tcg_temp_new_i32();
252
- TCGv_i32 hi = tcg_temp_new_i32();
253
- TCGv_i64 ret;
254
-
255
- tcg_gen_muls2_i32(lo, hi, a, b);
256
- tcg_temp_free_i32(a);
257
- tcg_temp_free_i32(b);
258
-
259
- ret = tcg_temp_new_i64();
260
- tcg_gen_concat_i32_i64(ret, lo, hi);
261
- tcg_temp_free_i32(lo);
262
- tcg_temp_free_i32(hi);
263
-
264
- return ret;
265
-}
266
-
267
/* Swap low and high halfwords. */
268
static void gen_swap_half(TCGv_i32 var)
269
{
231
{
270
@@ -XXX,XX +XXX,XX @@ static inline void gen_neon_addl(int size)
232
Clock *clk = CLOCK(obj);
271
}
233
234
+ clk->multiplier = 1;
235
+ clk->divider = 1;
236
+
237
QLIST_INIT(&clk->children);
272
}
238
}
273
239
274
-static inline void gen_neon_negl(TCGv_i64 var, int size)
240
diff --git a/hw/core/trace-events b/hw/core/trace-events
275
-{
241
index XXXXXXX..XXXXXXX 100644
276
- switch (size) {
242
--- a/hw/core/trace-events
277
- case 0: gen_helper_neon_negl_u16(var, var); break;
243
+++ b/hw/core/trace-events
278
- case 1: gen_helper_neon_negl_u32(var, var); break;
244
@@ -XXX,XX +XXX,XX @@ clock_disconnect(const char *clk) "'%s'"
279
- case 2:
245
clock_set(const char *clk, uint64_t old, uint64_t new) "'%s', %"PRIu64"Hz->%"PRIu64"Hz"
280
- tcg_gen_neg_i64(var, var);
246
clock_propagate(const char *clk) "'%s'"
281
- break;
247
clock_update(const char *clk, const char *src, uint64_t hz, int cb) "'%s', src='%s', val=%"PRIu64"Hz cb=%d"
282
- default: abort();
248
+clock_set_mul_div(const char *clk, uint32_t oldmul, uint32_t mul, uint32_t olddiv, uint32_t div) "'%s', mul: %u -> %u, div: %u -> %u"
283
- }
284
-}
285
-
286
-static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
287
-{
288
- switch (size) {
289
- case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
290
- case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
291
- default: abort();
292
- }
293
-}
294
-
295
-static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
296
- int size, int u)
297
-{
298
- TCGv_i64 tmp;
299
-
300
- switch ((size << 1) | u) {
301
- case 0: gen_helper_neon_mull_s8(dest, a, b); break;
302
- case 1: gen_helper_neon_mull_u8(dest, a, b); break;
303
- case 2: gen_helper_neon_mull_s16(dest, a, b); break;
304
- case 3: gen_helper_neon_mull_u16(dest, a, b); break;
305
- case 4:
306
- tmp = gen_muls_i64_i32(a, b);
307
- tcg_gen_mov_i64(dest, tmp);
308
- tcg_temp_free_i64(tmp);
309
- break;
310
- case 5:
311
- tmp = gen_mulu_i64_i32(a, b);
312
- tcg_gen_mov_i64(dest, tmp);
313
- tcg_temp_free_i64(tmp);
314
- break;
315
- default: abort();
316
- }
317
-
318
- /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
319
- Don't forget to clean them now. */
320
- if (size < 2) {
321
- tcg_temp_free_i32(a);
322
- tcg_temp_free_i32(b);
323
- }
324
-}
325
-
326
static void gen_neon_narrow_op(int op, int u, int size,
327
TCGv_i32 dest, TCGv_i64 src)
328
{
329
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
330
int u;
331
int vec_size;
332
uint32_t imm;
333
- TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
334
+ TCGv_i32 tmp, tmp2, tmp3, tmp5;
335
TCGv_ptr ptr1;
336
TCGv_i64 tmp64;
337
338
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
339
return 1;
340
} else { /* (insn & 0x00800010 == 0x00800000) */
341
if (size != 3) {
342
- op = (insn >> 8) & 0xf;
343
- if ((insn & (1 << 6)) == 0) {
344
- /* Three registers of different lengths: handled by decodetree */
345
- return 1;
346
- } else {
347
- /* Two registers and a scalar. NB that for ops of this form
348
- * the ARM ARM labels bit 24 as Q, but it is in our variable
349
- * 'u', not 'q'.
350
- */
351
- if (size == 0) {
352
- return 1;
353
- }
354
- switch (op) {
355
- case 0: /* Integer VMLA scalar */
356
- case 4: /* Integer VMLS scalar */
357
- case 8: /* Integer VMUL scalar */
358
- case 1: /* Float VMLA scalar */
359
- case 5: /* Floating point VMLS scalar */
360
- case 9: /* Floating point VMUL scalar */
361
- case 12: /* VQDMULH scalar */
362
- case 13: /* VQRDMULH scalar */
363
- case 14: /* VQRDMLAH scalar */
364
- case 15: /* VQRDMLSH scalar */
365
- return 1; /* handled by decodetree */
366
-
367
- case 3: /* VQDMLAL scalar */
368
- case 7: /* VQDMLSL scalar */
369
- case 11: /* VQDMULL scalar */
370
- if (u == 1) {
371
- return 1;
372
- }
373
- /* fall through */
374
- case 2: /* VMLAL sclar */
375
- case 6: /* VMLSL scalar */
376
- case 10: /* VMULL scalar */
377
- if (rd & 1) {
378
- return 1;
379
- }
380
- tmp2 = neon_get_scalar(size, rm);
381
- /* We need a copy of tmp2 because gen_neon_mull
382
- * deletes it during pass 0. */
383
- tmp4 = tcg_temp_new_i32();
384
- tcg_gen_mov_i32(tmp4, tmp2);
385
- tmp3 = neon_load_reg(rn, 1);
386
-
387
- for (pass = 0; pass < 2; pass++) {
388
- if (pass == 0) {
389
- tmp = neon_load_reg(rn, 0);
390
- } else {
391
- tmp = tmp3;
392
- tmp2 = tmp4;
393
- }
394
- gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
395
- if (op != 11) {
396
- neon_load_reg64(cpu_V1, rd + pass);
397
- }
398
- switch (op) {
399
- case 6:
400
- gen_neon_negl(cpu_V0, size);
401
- /* Fall through */
402
- case 2:
403
- gen_neon_addl(size);
404
- break;
405
- case 3: case 7:
406
- gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
407
- if (op == 7) {
408
- gen_neon_negl(cpu_V0, size);
409
- }
410
- gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
411
- break;
412
- case 10:
413
- /* no-op */
414
- break;
415
- case 11:
416
- gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
417
- break;
418
- default:
419
- abort();
420
- }
421
- neon_store_reg64(cpu_V0, rd + pass);
422
- }
423
- break;
424
- default:
425
- g_assert_not_reached();
426
- }
427
- }
428
+ /*
429
+ * Three registers of different lengths, or two registers and
430
+ * a scalar: handled by decodetree
431
+ */
432
+ return 1;
433
} else { /* size == 3 */
434
if (!u) {
435
/* Extract. */
436
--
249
--
437
2.20.1
250
2.20.1
438
251
439
252
diff view generated by jsdifflib
New patch
1
In the realize methods of the stm32f100 and stm32f205 SoC objects, we
2
call g_new() to create new MemoryRegion objects for the sram, flash,
3
and flash_alias. This is unnecessary (and leaves open the
4
possibility of leaking the allocations if we exit from realize with
5
an error). Make these MemoryRegions member fields of the device
6
state struct instead, as stm32f405 already does.
1
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Alexandre Iooss <erdnaxe@crans.org>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Reviewed-by: Luc Michel <luc@lmichel.fr>
12
Message-id: 20210812093356.1946-11-peter.maydell@linaro.org
13
---
14
include/hw/arm/stm32f100_soc.h | 4 ++++
15
include/hw/arm/stm32f205_soc.h | 4 ++++
16
hw/arm/stm32f100_soc.c | 17 +++++++----------
17
hw/arm/stm32f205_soc.c | 17 +++++++----------
18
4 files changed, 22 insertions(+), 20 deletions(-)
19
20
diff --git a/include/hw/arm/stm32f100_soc.h b/include/hw/arm/stm32f100_soc.h
21
index XXXXXXX..XXXXXXX 100644
22
--- a/include/hw/arm/stm32f100_soc.h
23
+++ b/include/hw/arm/stm32f100_soc.h
24
@@ -XXX,XX +XXX,XX @@ struct STM32F100State {
25
26
STM32F2XXUsartState usart[STM_NUM_USARTS];
27
STM32F2XXSPIState spi[STM_NUM_SPIS];
28
+
29
+ MemoryRegion sram;
30
+ MemoryRegion flash;
31
+ MemoryRegion flash_alias;
32
};
33
34
#endif
35
diff --git a/include/hw/arm/stm32f205_soc.h b/include/hw/arm/stm32f205_soc.h
36
index XXXXXXX..XXXXXXX 100644
37
--- a/include/hw/arm/stm32f205_soc.h
38
+++ b/include/hw/arm/stm32f205_soc.h
39
@@ -XXX,XX +XXX,XX @@ struct STM32F205State {
40
STM32F2XXSPIState spi[STM_NUM_SPIS];
41
42
qemu_or_irq *adc_irqs;
43
+
44
+ MemoryRegion sram;
45
+ MemoryRegion flash;
46
+ MemoryRegion flash_alias;
47
};
48
49
#endif
50
diff --git a/hw/arm/stm32f100_soc.c b/hw/arm/stm32f100_soc.c
51
index XXXXXXX..XXXXXXX 100644
52
--- a/hw/arm/stm32f100_soc.c
53
+++ b/hw/arm/stm32f100_soc.c
54
@@ -XXX,XX +XXX,XX @@ static void stm32f100_soc_realize(DeviceState *dev_soc, Error **errp)
55
int i;
56
57
MemoryRegion *system_memory = get_system_memory();
58
- MemoryRegion *sram = g_new(MemoryRegion, 1);
59
- MemoryRegion *flash = g_new(MemoryRegion, 1);
60
- MemoryRegion *flash_alias = g_new(MemoryRegion, 1);
61
62
/*
63
* Init flash region
64
* Flash starts at 0x08000000 and then is aliased to boot memory at 0x0
65
*/
66
- memory_region_init_rom(flash, OBJECT(dev_soc), "STM32F100.flash",
67
+ memory_region_init_rom(&s->flash, OBJECT(dev_soc), "STM32F100.flash",
68
FLASH_SIZE, &error_fatal);
69
- memory_region_init_alias(flash_alias, OBJECT(dev_soc),
70
- "STM32F100.flash.alias", flash, 0, FLASH_SIZE);
71
- memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
72
- memory_region_add_subregion(system_memory, 0, flash_alias);
73
+ memory_region_init_alias(&s->flash_alias, OBJECT(dev_soc),
74
+ "STM32F100.flash.alias", &s->flash, 0, FLASH_SIZE);
75
+ memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, &s->flash);
76
+ memory_region_add_subregion(system_memory, 0, &s->flash_alias);
77
78
/* Init SRAM region */
79
- memory_region_init_ram(sram, NULL, "STM32F100.sram", SRAM_SIZE,
80
+ memory_region_init_ram(&s->sram, NULL, "STM32F100.sram", SRAM_SIZE,
81
&error_fatal);
82
- memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
83
+ memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, &s->sram);
84
85
/* Init ARMv7m */
86
armv7m = DEVICE(&s->armv7m);
87
diff --git a/hw/arm/stm32f205_soc.c b/hw/arm/stm32f205_soc.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/hw/arm/stm32f205_soc.c
90
+++ b/hw/arm/stm32f205_soc.c
91
@@ -XXX,XX +XXX,XX @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
92
int i;
93
94
MemoryRegion *system_memory = get_system_memory();
95
- MemoryRegion *sram = g_new(MemoryRegion, 1);
96
- MemoryRegion *flash = g_new(MemoryRegion, 1);
97
- MemoryRegion *flash_alias = g_new(MemoryRegion, 1);
98
99
- memory_region_init_rom(flash, OBJECT(dev_soc), "STM32F205.flash",
100
+ memory_region_init_rom(&s->flash, OBJECT(dev_soc), "STM32F205.flash",
101
FLASH_SIZE, &error_fatal);
102
- memory_region_init_alias(flash_alias, OBJECT(dev_soc),
103
- "STM32F205.flash.alias", flash, 0, FLASH_SIZE);
104
+ memory_region_init_alias(&s->flash_alias, OBJECT(dev_soc),
105
+ "STM32F205.flash.alias", &s->flash, 0, FLASH_SIZE);
106
107
- memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, flash);
108
- memory_region_add_subregion(system_memory, 0, flash_alias);
109
+ memory_region_add_subregion(system_memory, FLASH_BASE_ADDRESS, &s->flash);
110
+ memory_region_add_subregion(system_memory, 0, &s->flash_alias);
111
112
- memory_region_init_ram(sram, NULL, "STM32F205.sram", SRAM_SIZE,
113
+ memory_region_init_ram(&s->sram, NULL, "STM32F205.sram", SRAM_SIZE,
114
&error_fatal);
115
- memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
116
+ memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, &s->sram);
117
118
armv7m = DEVICE(&s->armv7m);
119
qdev_prop_set_uint32(armv7m, "num-irq", 96);
120
--
121
2.20.1
122
123
diff view generated by jsdifflib
New patch
1
Wire up the sysclk and refclk for the stm32f100 SoC. This SoC always
2
runs the systick refclk at 1/8 the frequency of the main CPU clock,
3
so the board code only needs to provide a single sysclk clock.
1
4
5
Because there is only one board using this SoC, we convert the SoC
6
and the board together, rather than splitting it into "add clock to
7
SoC; connect clock in board; add error check in SoC code that clock
8
is wired up".
9
10
When the systick device starts honouring its clock inputs, this will
11
fix an emulation inaccuracy in the stm32vldiscovery board where the
12
systick reference clock was running at 1MHz rather than 3MHz.
13
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
16
Reviewed-by: Alexandre Iooss <erdnaxe@crans.org>
17
Reviewed-by: Luc Michel <luc@lmichel.fr>
18
Message-id: 20210812093356.1946-12-peter.maydell@linaro.org
19
---
20
include/hw/arm/stm32f100_soc.h | 4 ++++
21
hw/arm/stm32f100_soc.c | 30 ++++++++++++++++++++++++++++++
22
hw/arm/stm32vldiscovery.c | 12 +++++++-----
23
3 files changed, 41 insertions(+), 5 deletions(-)
24
25
diff --git a/include/hw/arm/stm32f100_soc.h b/include/hw/arm/stm32f100_soc.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/include/hw/arm/stm32f100_soc.h
28
+++ b/include/hw/arm/stm32f100_soc.h
29
@@ -XXX,XX +XXX,XX @@
30
#include "hw/ssi/stm32f2xx_spi.h"
31
#include "hw/arm/armv7m.h"
32
#include "qom/object.h"
33
+#include "hw/clock.h"
34
35
#define TYPE_STM32F100_SOC "stm32f100-soc"
36
OBJECT_DECLARE_SIMPLE_TYPE(STM32F100State, STM32F100_SOC)
37
@@ -XXX,XX +XXX,XX @@ struct STM32F100State {
38
MemoryRegion sram;
39
MemoryRegion flash;
40
MemoryRegion flash_alias;
41
+
42
+ Clock *sysclk;
43
+ Clock *refclk;
44
};
45
46
#endif
47
diff --git a/hw/arm/stm32f100_soc.c b/hw/arm/stm32f100_soc.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/arm/stm32f100_soc.c
50
+++ b/hw/arm/stm32f100_soc.c
51
@@ -XXX,XX +XXX,XX @@
52
#include "exec/address-spaces.h"
53
#include "hw/arm/stm32f100_soc.h"
54
#include "hw/qdev-properties.h"
55
+#include "hw/qdev-clock.h"
56
#include "hw/misc/unimp.h"
57
#include "sysemu/sysemu.h"
58
59
@@ -XXX,XX +XXX,XX @@ static void stm32f100_soc_initfn(Object *obj)
60
for (i = 0; i < STM_NUM_SPIS; i++) {
61
object_initialize_child(obj, "spi[*]", &s->spi[i], TYPE_STM32F2XX_SPI);
62
}
63
+
64
+ s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
65
+ s->refclk = qdev_init_clock_in(DEVICE(s), "refclk", NULL, NULL, 0);
66
}
67
68
static void stm32f100_soc_realize(DeviceState *dev_soc, Error **errp)
69
@@ -XXX,XX +XXX,XX @@ static void stm32f100_soc_realize(DeviceState *dev_soc, Error **errp)
70
71
MemoryRegion *system_memory = get_system_memory();
72
73
+ /*
74
+ * We use s->refclk internally and only define it with qdev_init_clock_in()
75
+ * so it is correctly parented and not leaked on an init/deinit; it is not
76
+ * intended as an externally exposed clock.
77
+ */
78
+ if (clock_has_source(s->refclk)) {
79
+ error_setg(errp, "refclk clock must not be wired up by the board code");
80
+ return;
81
+ }
82
+
83
+ if (!clock_has_source(s->sysclk)) {
84
+ error_setg(errp, "sysclk clock must be wired up by the board code");
85
+ return;
86
+ }
87
+
88
+ /*
89
+ * TODO: ideally we should model the SoC RCC and its ability to
90
+ * change the sysclk frequency and define different sysclk sources.
91
+ */
92
+
93
+ /* The refclk always runs at frequency HCLK / 8 */
94
+ clock_set_mul_div(s->refclk, 8, 1);
95
+ clock_set_source(s->refclk, s->sysclk);
96
+
97
/*
98
* Init flash region
99
* Flash starts at 0x08000000 and then is aliased to boot memory at 0x0
100
@@ -XXX,XX +XXX,XX @@ static void stm32f100_soc_realize(DeviceState *dev_soc, Error **errp)
101
qdev_prop_set_uint32(armv7m, "num-irq", 61);
102
qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
103
qdev_prop_set_bit(armv7m, "enable-bitband", true);
104
+ qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
105
+ qdev_connect_clock_in(armv7m, "refclk", s->refclk);
106
object_property_set_link(OBJECT(&s->armv7m), "memory",
107
OBJECT(get_system_memory()), &error_abort);
108
if (!sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), errp)) {
109
diff --git a/hw/arm/stm32vldiscovery.c b/hw/arm/stm32vldiscovery.c
110
index XXXXXXX..XXXXXXX 100644
111
--- a/hw/arm/stm32vldiscovery.c
112
+++ b/hw/arm/stm32vldiscovery.c
113
@@ -XXX,XX +XXX,XX @@
114
#include "qapi/error.h"
115
#include "hw/boards.h"
116
#include "hw/qdev-properties.h"
117
+#include "hw/qdev-clock.h"
118
#include "qemu/error-report.h"
119
#include "hw/arm/stm32f100_soc.h"
120
#include "hw/arm/boot.h"
121
@@ -XXX,XX +XXX,XX @@
122
static void stm32vldiscovery_init(MachineState *machine)
123
{
124
DeviceState *dev;
125
+ Clock *sysclk;
126
127
- /*
128
- * TODO: ideally we would model the SoC RCC and let it handle
129
- * system_clock_scale, including its ability to define different
130
- * possible SYSCLK sources.
131
- */
132
system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
133
134
+ /* This clock doesn't need migration because it is fixed-frequency */
135
+ sysclk = clock_new(OBJECT(machine), "SYSCLK");
136
+ clock_set_hz(sysclk, SYSCLK_FRQ);
137
+
138
dev = qdev_new(TYPE_STM32F100_SOC);
139
qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m3"));
140
+ qdev_connect_clock_in(dev, "sysclk", sysclk);
141
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
142
143
armv7m_load_kernel(ARM_CPU(first_cpu),
144
--
145
2.20.1
146
147
diff view generated by jsdifflib
New patch
1
Wire up the sysclk and refclk for the stm32f205 SoC. This SoC always
2
runs the systick refclk at 1/8 the frequency of the main CPU clock,
3
so the board code only needs to provide a single sysclk clock.
1
4
5
Because there is only one board using this SoC, we convert the SoC
6
and the board together, rather than splitting it into "add clock to
7
SoC; connect clock in board; add error check in SoC code that clock
8
is wired up".
9
10
When the systick device starts honouring its clock inputs, this will
11
fix an emulation inaccuracy in the netduino2 board where the systick
12
reference clock was running at 1MHz rather than 15MHz.
13
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
16
Reviewed-by: Alexandre Iooss <erdnaxe@crans.org>
17
Reviewed-by: Luc Michel <luc@lmichel.fr>
18
Message-id: 20210812093356.1946-13-peter.maydell@linaro.org
19
---
20
include/hw/arm/stm32f205_soc.h | 4 ++++
21
hw/arm/netduino2.c | 12 +++++++-----
22
hw/arm/stm32f205_soc.c | 30 ++++++++++++++++++++++++++++++
23
3 files changed, 41 insertions(+), 5 deletions(-)
24
25
diff --git a/include/hw/arm/stm32f205_soc.h b/include/hw/arm/stm32f205_soc.h
26
index XXXXXXX..XXXXXXX 100644
27
--- a/include/hw/arm/stm32f205_soc.h
28
+++ b/include/hw/arm/stm32f205_soc.h
29
@@ -XXX,XX +XXX,XX @@
30
#include "hw/or-irq.h"
31
#include "hw/ssi/stm32f2xx_spi.h"
32
#include "hw/arm/armv7m.h"
33
+#include "hw/clock.h"
34
#include "qom/object.h"
35
36
#define TYPE_STM32F205_SOC "stm32f205-soc"
37
@@ -XXX,XX +XXX,XX @@ struct STM32F205State {
38
MemoryRegion sram;
39
MemoryRegion flash;
40
MemoryRegion flash_alias;
41
+
42
+ Clock *sysclk;
43
+ Clock *refclk;
44
};
45
46
#endif
47
diff --git a/hw/arm/netduino2.c b/hw/arm/netduino2.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/arm/netduino2.c
50
+++ b/hw/arm/netduino2.c
51
@@ -XXX,XX +XXX,XX @@
52
#include "qapi/error.h"
53
#include "hw/boards.h"
54
#include "hw/qdev-properties.h"
55
+#include "hw/qdev-clock.h"
56
#include "qemu/error-report.h"
57
#include "hw/arm/stm32f205_soc.h"
58
#include "hw/arm/boot.h"
59
@@ -XXX,XX +XXX,XX @@
60
static void netduino2_init(MachineState *machine)
61
{
62
DeviceState *dev;
63
+ Clock *sysclk;
64
65
- /*
66
- * TODO: ideally we would model the SoC RCC and let it handle
67
- * system_clock_scale, including its ability to define different
68
- * possible SYSCLK sources.
69
- */
70
system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
71
72
+ /* This clock doesn't need migration because it is fixed-frequency */
73
+ sysclk = clock_new(OBJECT(machine), "SYSCLK");
74
+ clock_set_hz(sysclk, SYSCLK_FRQ);
75
+
76
dev = qdev_new(TYPE_STM32F205_SOC);
77
qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m3"));
78
+ qdev_connect_clock_in(dev, "sysclk", sysclk);
79
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
80
81
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
82
diff --git a/hw/arm/stm32f205_soc.c b/hw/arm/stm32f205_soc.c
83
index XXXXXXX..XXXXXXX 100644
84
--- a/hw/arm/stm32f205_soc.c
85
+++ b/hw/arm/stm32f205_soc.c
86
@@ -XXX,XX +XXX,XX @@
87
#include "exec/address-spaces.h"
88
#include "hw/arm/stm32f205_soc.h"
89
#include "hw/qdev-properties.h"
90
+#include "hw/qdev-clock.h"
91
#include "sysemu/sysemu.h"
92
93
/* At the moment only Timer 2 to 5 are modelled */
94
@@ -XXX,XX +XXX,XX @@ static void stm32f205_soc_initfn(Object *obj)
95
for (i = 0; i < STM_NUM_SPIS; i++) {
96
object_initialize_child(obj, "spi[*]", &s->spi[i], TYPE_STM32F2XX_SPI);
97
}
98
+
99
+ s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
100
+ s->refclk = qdev_init_clock_in(DEVICE(s), "refclk", NULL, NULL, 0);
101
}
102
103
static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
104
@@ -XXX,XX +XXX,XX @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
105
106
MemoryRegion *system_memory = get_system_memory();
107
108
+ /*
109
+ * We use s->refclk internally and only define it with qdev_init_clock_in()
110
+ * so it is correctly parented and not leaked on an init/deinit; it is not
111
+ * intended as an externally exposed clock.
112
+ */
113
+ if (clock_has_source(s->refclk)) {
114
+ error_setg(errp, "refclk clock must not be wired up by the board code");
115
+ return;
116
+ }
117
+
118
+ if (!clock_has_source(s->sysclk)) {
119
+ error_setg(errp, "sysclk clock must be wired up by the board code");
120
+ return;
121
+ }
122
+
123
+ /*
124
+ * TODO: ideally we should model the SoC RCC and its ability to
125
+ * change the sysclk frequency and define different sysclk sources.
126
+ */
127
+
128
+ /* The refclk always runs at frequency HCLK / 8 */
129
+ clock_set_mul_div(s->refclk, 8, 1);
130
+ clock_set_source(s->refclk, s->sysclk);
131
+
132
memory_region_init_rom(&s->flash, OBJECT(dev_soc), "STM32F205.flash",
133
FLASH_SIZE, &error_fatal);
134
memory_region_init_alias(&s->flash_alias, OBJECT(dev_soc),
135
@@ -XXX,XX +XXX,XX @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
136
qdev_prop_set_uint32(armv7m, "num-irq", 96);
137
qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
138
qdev_prop_set_bit(armv7m, "enable-bitband", true);
139
+ qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
140
+ qdev_connect_clock_in(armv7m, "refclk", s->refclk);
141
object_property_set_link(OBJECT(&s->armv7m), "memory",
142
OBJECT(get_system_memory()), &error_abort);
143
if (!sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), errp)) {
144
--
145
2.20.1
146
147
diff view generated by jsdifflib
1
Convert the Neon 3-reg-diff insn polynomial VMULL. This is the last
1
Wire up the sysclk and refclk for the stm32f405 SoC. This SoC always
2
insn in this group to be converted.
2
runs the systick refclk at 1/8 the frequency of the main CPU clock,
3
so the board code only needs to provide a single sysclk clock.
4
5
Because there is only one board using this SoC, we convert the SoC
6
and the board together, rather than splitting it into "add clock to
7
SoC; connect clock in board; add error check in SoC code that clock
8
is wired up".
9
10
When the systick device starts honouring its clock inputs, this will
11
fix an emulation inaccuracy in the netduinoplus2 board where the
12
systick reference clock was running at 1MHz rather than 21MHz.
3
13
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
16
Reviewed-by: Alexandre Iooss <erdnaxe@crans.org>
17
Reviewed-by: Luc Michel <luc@lmichel.fr>
18
Message-id: 20210812093356.1946-14-peter.maydell@linaro.org
6
---
19
---
7
target/arm/neon-dp.decode | 2 ++
20
include/hw/arm/stm32f405_soc.h | 3 +++
8
target/arm/translate-neon.inc.c | 43 +++++++++++++++++++++++
21
hw/arm/netduinoplus2.c | 12 +++++++-----
9
target/arm/translate.c | 60 ++-------------------------------
22
hw/arm/stm32f405_soc.c | 30 ++++++++++++++++++++++++++++++
10
3 files changed, 48 insertions(+), 57 deletions(-)
23
3 files changed, 40 insertions(+), 5 deletions(-)
11
24
12
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
25
diff --git a/include/hw/arm/stm32f405_soc.h b/include/hw/arm/stm32f405_soc.h
13
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/neon-dp.decode
27
--- a/include/hw/arm/stm32f405_soc.h
15
+++ b/target/arm/neon-dp.decode
28
+++ b/include/hw/arm/stm32f405_soc.h
16
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
29
@@ -XXX,XX +XXX,XX @@ struct STM32F405State {
17
VMULL_U_3d 1111 001 1 1 . .. .... .... 1100 . 0 . 0 .... @3diff
30
MemoryRegion sram;
18
31
MemoryRegion flash;
19
VQDMULL_3d 1111 001 0 1 . .. .... .... 1101 . 0 . 0 .... @3diff
32
MemoryRegion flash_alias;
20
+
33
+
21
+ VMULL_P_3d 1111 001 0 1 . .. .... .... 1110 . 0 . 0 .... @3diff
34
+ Clock *sysclk;
22
]
35
+ Clock *refclk;
36
};
37
38
#endif
39
diff --git a/hw/arm/netduinoplus2.c b/hw/arm/netduinoplus2.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/hw/arm/netduinoplus2.c
42
+++ b/hw/arm/netduinoplus2.c
43
@@ -XXX,XX +XXX,XX @@
44
#include "qapi/error.h"
45
#include "hw/boards.h"
46
#include "hw/qdev-properties.h"
47
+#include "hw/qdev-clock.h"
48
#include "qemu/error-report.h"
49
#include "hw/arm/stm32f405_soc.h"
50
#include "hw/arm/boot.h"
51
@@ -XXX,XX +XXX,XX @@
52
static void netduinoplus2_init(MachineState *machine)
53
{
54
DeviceState *dev;
55
+ Clock *sysclk;
56
57
- /*
58
- * TODO: ideally we would model the SoC RCC and let it handle
59
- * system_clock_scale, including its ability to define different
60
- * possible SYSCLK sources.
61
- */
62
system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
63
64
+ /* This clock doesn't need migration because it is fixed-frequency */
65
+ sysclk = clock_new(OBJECT(machine), "SYSCLK");
66
+ clock_set_hz(sysclk, SYSCLK_FRQ);
67
+
68
dev = qdev_new(TYPE_STM32F405_SOC);
69
qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4"));
70
+ qdev_connect_clock_in(dev, "sysclk", sysclk);
71
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
72
73
armv7m_load_kernel(ARM_CPU(first_cpu),
74
diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/hw/arm/stm32f405_soc.c
77
+++ b/hw/arm/stm32f405_soc.c
78
@@ -XXX,XX +XXX,XX @@
79
#include "exec/address-spaces.h"
80
#include "sysemu/sysemu.h"
81
#include "hw/arm/stm32f405_soc.h"
82
+#include "hw/qdev-clock.h"
83
#include "hw/misc/unimp.h"
84
85
#define SYSCFG_ADD 0x40013800
86
@@ -XXX,XX +XXX,XX @@ static void stm32f405_soc_initfn(Object *obj)
87
}
88
89
object_initialize_child(obj, "exti", &s->exti, TYPE_STM32F4XX_EXTI);
90
+
91
+ s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
92
+ s->refclk = qdev_init_clock_in(DEVICE(s), "refclk", NULL, NULL, 0);
23
}
93
}
24
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
94
25
index XXXXXXX..XXXXXXX 100644
95
static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
26
--- a/target/arm/translate-neon.inc.c
96
@@ -XXX,XX +XXX,XX @@ static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
27
+++ b/target/arm/translate-neon.inc.c
97
Error *err = NULL;
28
@@ -XXX,XX +XXX,XX @@ static bool trans_VQDMLSL_3d(DisasContext *s, arg_3diff *a)
98
int i;
29
99
30
return do_long_3d(s, a, opfn[a->size], accfn[a->size]);
100
+ /*
31
}
101
+ * We use s->refclk internally and only define it with qdev_init_clock_in()
32
+
102
+ * so it is correctly parented and not leaked on an init/deinit; it is not
33
+static bool trans_VMULL_P_3d(DisasContext *s, arg_3diff *a)
103
+ * intended as an externally exposed clock.
34
+{
104
+ */
35
+ gen_helper_gvec_3 *fn_gvec;
105
+ if (clock_has_source(s->refclk)) {
36
+
106
+ error_setg(errp, "refclk clock must not be wired up by the board code");
37
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
107
+ return;
38
+ return false;
39
+ }
108
+ }
40
+
109
+
41
+ /* UNDEF accesses to D16-D31 if they don't exist. */
110
+ if (!clock_has_source(s->sysclk)) {
42
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
111
+ error_setg(errp, "sysclk clock must be wired up by the board code");
43
+ ((a->vd | a->vn | a->vm) & 0x10)) {
112
+ return;
44
+ return false;
45
+ }
113
+ }
46
+
114
+
47
+ if (a->vd & 1) {
115
+ /*
48
+ return false;
116
+ * TODO: ideally we should model the SoC RCC and its ability to
49
+ }
117
+ * change the sysclk frequency and define different sysclk sources.
118
+ */
50
+
119
+
51
+ switch (a->size) {
120
+ /* The refclk always runs at frequency HCLK / 8 */
52
+ case 0:
121
+ clock_set_mul_div(s->refclk, 8, 1);
53
+ fn_gvec = gen_helper_neon_pmull_h;
122
+ clock_set_source(s->refclk, s->sysclk);
54
+ break;
55
+ case 2:
56
+ if (!dc_isar_feature(aa32_pmull, s)) {
57
+ return false;
58
+ }
59
+ fn_gvec = gen_helper_gvec_pmull_q;
60
+ break;
61
+ default:
62
+ return false;
63
+ }
64
+
123
+
65
+ if (!vfp_access_check(s)) {
124
memory_region_init_rom(&s->flash, OBJECT(dev_soc), "STM32F405.flash",
66
+ return true;
125
FLASH_SIZE, &err);
67
+ }
126
if (err != NULL) {
68
+
127
@@ -XXX,XX +XXX,XX @@ static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
69
+ tcg_gen_gvec_3_ool(neon_reg_offset(a->vd, 0),
128
qdev_prop_set_uint32(armv7m, "num-irq", 96);
70
+ neon_reg_offset(a->vn, 0),
129
qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
71
+ neon_reg_offset(a->vm, 0),
130
qdev_prop_set_bit(armv7m, "enable-bitband", true);
72
+ 16, 16, 0, fn_gvec);
131
+ qdev_connect_clock_in(armv7m, "cpuclk", s->sysclk);
73
+ return true;
132
+ qdev_connect_clock_in(armv7m, "refclk", s->refclk);
74
+}
133
object_property_set_link(OBJECT(&s->armv7m), "memory",
75
diff --git a/target/arm/translate.c b/target/arm/translate.c
134
OBJECT(system_memory), &error_abort);
76
index XXXXXXX..XXXXXXX 100644
135
if (!sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), errp)) {
77
--- a/target/arm/translate.c
78
+++ b/target/arm/translate.c
79
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
80
{
81
int op;
82
int q;
83
- int rd, rn, rm, rd_ofs, rn_ofs, rm_ofs;
84
+ int rd, rn, rm, rd_ofs, rm_ofs;
85
int size;
86
int pass;
87
int u;
88
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
89
size = (insn >> 20) & 3;
90
vec_size = q ? 16 : 8;
91
rd_ofs = neon_reg_offset(rd, 0);
92
- rn_ofs = neon_reg_offset(rn, 0);
93
rm_ofs = neon_reg_offset(rm, 0);
94
95
if ((insn & (1 << 23)) == 0) {
96
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
97
if (size != 3) {
98
op = (insn >> 8) & 0xf;
99
if ((insn & (1 << 6)) == 0) {
100
- /* Three registers of different lengths. */
101
- /* undefreq: bit 0 : UNDEF if size == 0
102
- * bit 1 : UNDEF if size == 1
103
- * bit 2 : UNDEF if size == 2
104
- * bit 3 : UNDEF if U == 1
105
- * Note that [2:0] set implies 'always UNDEF'
106
- */
107
- int undefreq;
108
- /* prewiden, src1_wide, src2_wide, undefreq */
109
- static const int neon_3reg_wide[16][4] = {
110
- {0, 0, 0, 7}, /* VADDL: handled by decodetree */
111
- {0, 0, 0, 7}, /* VADDW: handled by decodetree */
112
- {0, 0, 0, 7}, /* VSUBL: handled by decodetree */
113
- {0, 0, 0, 7}, /* VSUBW: handled by decodetree */
114
- {0, 0, 0, 7}, /* VADDHN: handled by decodetree */
115
- {0, 0, 0, 7}, /* VABAL */
116
- {0, 0, 0, 7}, /* VSUBHN: handled by decodetree */
117
- {0, 0, 0, 7}, /* VABDL */
118
- {0, 0, 0, 7}, /* VMLAL */
119
- {0, 0, 0, 7}, /* VQDMLAL */
120
- {0, 0, 0, 7}, /* VMLSL */
121
- {0, 0, 0, 7}, /* VQDMLSL */
122
- {0, 0, 0, 7}, /* Integer VMULL */
123
- {0, 0, 0, 7}, /* VQDMULL */
124
- {0, 0, 0, 0xa}, /* Polynomial VMULL */
125
- {0, 0, 0, 7}, /* Reserved: always UNDEF */
126
- };
127
-
128
- undefreq = neon_3reg_wide[op][3];
129
-
130
- if ((undefreq & (1 << size)) ||
131
- ((undefreq & 8) && u)) {
132
- return 1;
133
- }
134
- if (rd & 1) {
135
- return 1;
136
- }
137
-
138
- /* Handle polynomial VMULL in a single pass. */
139
- if (op == 14) {
140
- if (size == 0) {
141
- /* VMULL.P8 */
142
- tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, 16, 16,
143
- 0, gen_helper_neon_pmull_h);
144
- } else {
145
- /* VMULL.P64 */
146
- if (!dc_isar_feature(aa32_pmull, s)) {
147
- return 1;
148
- }
149
- tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, 16, 16,
150
- 0, gen_helper_gvec_pmull_q);
151
- }
152
- return 0;
153
- }
154
- abort(); /* all others handled by decodetree */
155
+ /* Three registers of different lengths: handled by decodetree */
156
+ return 1;
157
} else {
158
/* Two registers and a scalar. NB that for ops of this form
159
* the ARM ARM labels bit 24 as Q, but it is in our variable
160
--
136
--
161
2.20.1
137
2.20.1
162
138
163
139
diff view generated by jsdifflib
New patch
1
Delete the trailing blank line at the end of the source file.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Alexandre Iooss <erdnaxe@crans.org>
5
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
6
Reviewed-by: Luc Michel <luc@lmichel.fr>
7
Message-id: 20210812093356.1946-15-peter.maydell@linaro.org
8
---
9
hw/arm/stm32vldiscovery.c | 1 -
10
1 file changed, 1 deletion(-)
11
12
diff --git a/hw/arm/stm32vldiscovery.c b/hw/arm/stm32vldiscovery.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/stm32vldiscovery.c
15
+++ b/hw/arm/stm32vldiscovery.c
16
@@ -XXX,XX +XXX,XX @@ static void stm32vldiscovery_machine_init(MachineClass *mc)
17
}
18
19
DEFINE_MACHINE("stm32vldiscovery", stm32vldiscovery_machine_init)
20
-
21
--
22
2.20.1
23
24
diff view generated by jsdifflib
New patch
1
Wire up the sysclk input to the armv7m object.
1
2
3
Strictly this SoC should not have a systick device at all, but our
4
armv7m container object doesn't currently support disabling the
5
systick device. For the moment, add a TODO comment, but note that
6
this is why we aren't wiring up a refclk (no need for one).
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Alexandre Iooss <erdnaxe@crans.org>
10
Message-id: 20210812093356.1946-16-peter.maydell@linaro.org
11
---
12
include/hw/arm/nrf51_soc.h | 2 ++
13
hw/arm/nrf51_soc.c | 20 ++++++++++++++++++++
14
2 files changed, 22 insertions(+)
15
16
diff --git a/include/hw/arm/nrf51_soc.h b/include/hw/arm/nrf51_soc.h
17
index XXXXXXX..XXXXXXX 100644
18
--- a/include/hw/arm/nrf51_soc.h
19
+++ b/include/hw/arm/nrf51_soc.h
20
@@ -XXX,XX +XXX,XX @@
21
#include "hw/gpio/nrf51_gpio.h"
22
#include "hw/nvram/nrf51_nvm.h"
23
#include "hw/timer/nrf51_timer.h"
24
+#include "hw/clock.h"
25
#include "qom/object.h"
26
27
#define TYPE_NRF51_SOC "nrf51-soc"
28
@@ -XXX,XX +XXX,XX @@ struct NRF51State {
29
30
MemoryRegion container;
31
32
+ Clock *sysclk;
33
};
34
35
#endif
36
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/arm/nrf51_soc.c
39
+++ b/hw/arm/nrf51_soc.c
40
@@ -XXX,XX +XXX,XX @@
41
#include "qapi/error.h"
42
#include "hw/arm/boot.h"
43
#include "hw/sysbus.h"
44
+#include "hw/qdev-clock.h"
45
#include "hw/misc/unimp.h"
46
#include "qemu/log.h"
47
48
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
49
return;
50
}
51
52
+ /*
53
+ * HCLK on this SoC is fixed, so we set up sysclk ourselves and
54
+ * the board shouldn't connect it.
55
+ */
56
+ if (clock_has_source(s->sysclk)) {
57
+ error_setg(errp, "sysclk clock must not be wired up by the board code");
58
+ return;
59
+ }
60
+ /* This clock doesn't need migration because it is fixed-frequency */
61
+ clock_set_hz(s->sysclk, HCLK_FRQ);
62
+ qdev_connect_clock_in(DEVICE(&s->cpu), "cpuclk", s->sysclk);
63
+ /*
64
+ * This SoC has no systick device, so don't connect refclk.
65
+ * TODO: model the lack of systick (currently the armv7m object
66
+ * will always provide one).
67
+ */
68
+
69
system_clock_scale = NANOSECONDS_PER_SECOND / HCLK_FRQ;
70
71
object_property_set_link(OBJECT(&s->cpu), "memory", OBJECT(&s->container),
72
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_init(Object *obj)
73
TYPE_NRF51_TIMER);
74
75
}
76
+
77
+ s->sysclk = qdev_init_clock_in(DEVICE(s), "sysclk", NULL, NULL, 0);
78
}
79
80
static Property nrf51_soc_properties[] = {
81
--
82
2.20.1
83
84
diff view generated by jsdifflib
1
From: Erik Smit <erik.lucas.smit@gmail.com>
1
Currently the stellaris_sys_init() function creates the
2
TYPE_STELLARIS_SYS object, sets its properties, realizes it, maps its
3
MMIO region and connects its IRQ. In order to support wiring the
4
sysclk up to the armv7m object, we need to split this function apart,
5
because to connect the clock output of the STELLARIS_SYS object to
6
the armv7m object we need to create the STELLARIS_SYS object before
7
the armv7m object, but we can't wire up the IRQ until after we've
8
created the armv7m object.
2
9
3
The hardware supports configurable descriptor sizes, configured in the DBLAC
10
Remove the stellaris_sys_init() function, and instead put the
4
register.
11
create/configure/realize parts before we create the armv7m object and
12
the mmio/irq connection parts afterwards.
5
13
6
Most drivers use the default 4 word descriptor, which is currently hardcoded,
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
but Aspeed SDK configures 8 words to store extra data.
15
Reviewed-by: Alexandre Iooss <erdnaxe@crans.org>
16
Message-id: 20210812093356.1946-17-peter.maydell@linaro.org
17
---
18
hw/arm/stellaris.c | 56 +++++++++++++++++++++-------------------------
19
1 file changed, 25 insertions(+), 31 deletions(-)
8
20
9
Signed-off-by: Erik Smit <erik.lucas.smit@gmail.com>
21
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
10
Reviewed-by: Cédric Le Goater <clg@kaod.org>
11
[PMM: removed unnecessary parens]
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
hw/net/ftgmac100.c | 26 ++++++++++++++++++++++++--
15
1 file changed, 24 insertions(+), 2 deletions(-)
16
17
diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c
18
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/net/ftgmac100.c
23
--- a/hw/arm/stellaris.c
20
+++ b/hw/net/ftgmac100.c
24
+++ b/hw/arm/stellaris.c
21
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@ static void stellaris_sys_instance_init(Object *obj)
22
#define FTGMAC100_APTC_TXPOLL_CNT(x) (((x) >> 8) & 0xf)
26
s->sysclk = qdev_init_clock_out(DEVICE(s), "SYSCLK");
23
#define FTGMAC100_APTC_TXPOLL_TIME_SEL (1 << 12)
27
}
24
28
25
+/*
29
-static DeviceState *stellaris_sys_init(uint32_t base, qemu_irq irq,
26
+ * DMA burst length and arbitration control register
30
- stellaris_board_info *board,
27
+ */
31
- uint8_t *macaddr)
28
+#define FTGMAC100_DBLAC_RXBURST_SIZE(x) (((x) >> 8) & 0x3)
32
-{
29
+#define FTGMAC100_DBLAC_TXBURST_SIZE(x) (((x) >> 10) & 0x3)
33
- DeviceState *dev = qdev_new(TYPE_STELLARIS_SYS);
30
+#define FTGMAC100_DBLAC_RXDES_SIZE(x) ((((x) >> 12) & 0xf) * 8)
34
- SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
31
+#define FTGMAC100_DBLAC_TXDES_SIZE(x) ((((x) >> 16) & 0xf) * 8)
35
-
32
+#define FTGMAC100_DBLAC_IFG_CNT(x) (((x) >> 20) & 0x7)
36
- /* Most devices come preprogrammed with a MAC address in the user data. */
33
+#define FTGMAC100_DBLAC_IFG_INC (1 << 23)
37
- qdev_prop_set_uint32(dev, "user0",
38
- macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16));
39
- qdev_prop_set_uint32(dev, "user1",
40
- macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16));
41
- qdev_prop_set_uint32(dev, "did0", board->did0);
42
- qdev_prop_set_uint32(dev, "did1", board->did1);
43
- qdev_prop_set_uint32(dev, "dc0", board->dc0);
44
- qdev_prop_set_uint32(dev, "dc1", board->dc1);
45
- qdev_prop_set_uint32(dev, "dc2", board->dc2);
46
- qdev_prop_set_uint32(dev, "dc3", board->dc3);
47
- qdev_prop_set_uint32(dev, "dc4", board->dc4);
48
-
49
- sysbus_realize_and_unref(sbd, &error_fatal);
50
- sysbus_mmio_map(sbd, 0, base);
51
- sysbus_connect_irq(sbd, 0, irq);
52
-
53
- return dev;
54
-}
55
-
56
/* I2C controller. */
57
58
#define TYPE_STELLARIS_I2C "stellaris-i2c"
59
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
60
DeviceState *ssys_dev;
61
int i;
62
int j;
63
+ uint8_t *macaddr;
64
65
MemoryRegion *sram = g_new(MemoryRegion, 1);
66
MemoryRegion *flash = g_new(MemoryRegion, 1);
67
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
68
&error_fatal);
69
memory_region_add_subregion(system_memory, 0x20000000, sram);
70
71
+ /*
72
+ * Create the system-registers object early, because we will
73
+ * need its sysclk output.
74
+ */
75
+ ssys_dev = qdev_new(TYPE_STELLARIS_SYS);
76
+ /* Most devices come preprogrammed with a MAC address in the user data. */
77
+ macaddr = nd_table[0].macaddr.a;
78
+ qdev_prop_set_uint32(ssys_dev, "user0",
79
+ macaddr[0] | (macaddr[1] << 8) | (macaddr[2] << 16));
80
+ qdev_prop_set_uint32(ssys_dev, "user1",
81
+ macaddr[3] | (macaddr[4] << 8) | (macaddr[5] << 16));
82
+ qdev_prop_set_uint32(ssys_dev, "did0", board->did0);
83
+ qdev_prop_set_uint32(ssys_dev, "did1", board->did1);
84
+ qdev_prop_set_uint32(ssys_dev, "dc0", board->dc0);
85
+ qdev_prop_set_uint32(ssys_dev, "dc1", board->dc1);
86
+ qdev_prop_set_uint32(ssys_dev, "dc2", board->dc2);
87
+ qdev_prop_set_uint32(ssys_dev, "dc3", board->dc3);
88
+ qdev_prop_set_uint32(ssys_dev, "dc4", board->dc4);
89
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(ssys_dev), &error_fatal);
34
+
90
+
35
/*
91
nvic = qdev_new(TYPE_ARMV7M);
36
* PHY control register
92
qdev_prop_set_uint32(nvic, "num-irq", NUM_IRQ_LINES);
37
*/
93
qdev_prop_set_string(nvic, "cpu-type", ms->cpu_type);
38
@@ -XXX,XX +XXX,XX @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring,
94
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
39
if (bd.des0 & s->txdes0_edotr) {
95
/* This will exit with an error if the user passed us a bad cpu_type */
40
addr = tx_ring;
96
sysbus_realize_and_unref(SYS_BUS_DEVICE(nvic), &error_fatal);
41
} else {
97
42
- addr += sizeof(FTGMAC100Desc);
98
+ /* Now we can wire up the IRQ and MMIO of the system registers */
43
+ addr += FTGMAC100_DBLAC_TXDES_SIZE(s->dblac);
99
+ sysbus_mmio_map(SYS_BUS_DEVICE(ssys_dev), 0, 0x400fe000);
100
+ sysbus_connect_irq(SYS_BUS_DEVICE(ssys_dev), 0, qdev_get_gpio_in(nvic, 28));
101
+
102
if (board->dc1 & (1 << 16)) {
103
dev = sysbus_create_varargs(TYPE_STELLARIS_ADC, 0x40038000,
104
qdev_get_gpio_in(nvic, 14),
105
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
44
}
106
}
45
}
107
}
46
108
47
@@ -XXX,XX +XXX,XX @@ static void ftgmac100_write(void *opaque, hwaddr addr,
109
- ssys_dev = stellaris_sys_init(0x400fe000, qdev_get_gpio_in(nvic, 28),
48
s->phydata = value & 0xffff;
110
- board, nd_table[0].macaddr.a);
49
break;
111
-
50
case FTGMAC100_DBLAC: /* DMA Burst Length and Arbitration Control */
112
-
51
+ if (FTGMAC100_DBLAC_TXDES_SIZE(s->dblac) < sizeof(FTGMAC100Desc)) {
113
if (board->dc1 & (1 << 3)) { /* watchdog present */
52
+ qemu_log_mask(LOG_GUEST_ERROR,
114
dev = qdev_new(TYPE_LUMINARY_WATCHDOG);
53
+ "%s: transmit descriptor too small : %d bytes\n",
115
54
+ __func__, FTGMAC100_DBLAC_TXDES_SIZE(s->dblac));
55
+ break;
56
+ }
57
+ if (FTGMAC100_DBLAC_RXDES_SIZE(s->dblac) < sizeof(FTGMAC100Desc)) {
58
+ qemu_log_mask(LOG_GUEST_ERROR,
59
+ "%s: receive descriptor too small : %d bytes\n",
60
+ __func__, FTGMAC100_DBLAC_RXDES_SIZE(s->dblac));
61
+ break;
62
+ }
63
s->dblac = value;
64
break;
65
case FTGMAC100_REVR: /* Feature Register */
66
@@ -XXX,XX +XXX,XX @@ static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf,
67
if (bd.des0 & s->rxdes0_edorr) {
68
addr = s->rx_ring;
69
} else {
70
- addr += sizeof(FTGMAC100Desc);
71
+ addr += FTGMAC100_DBLAC_RXDES_SIZE(s->dblac);
72
}
73
}
74
s->rx_descriptor = addr;
75
--
116
--
76
2.20.1
117
2.20.1
77
118
78
119
diff view generated by jsdifflib
New patch
1
Connect the sysclk to the armv7m object. This board's SoC does not
2
connect up the systick reference clock, so we don't need to connect a
3
refclk.
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Alexandre Iooss <erdnaxe@crans.org>
7
Message-id: 20210812093356.1946-18-peter.maydell@linaro.org
8
---
9
hw/arm/stellaris.c | 5 ++++-
10
1 file changed, 4 insertions(+), 1 deletion(-)
11
12
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/stellaris.c
15
+++ b/hw/arm/stellaris.c
16
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
17
DeviceState *ssys_dev;
18
int i;
19
int j;
20
- uint8_t *macaddr;
21
+ const uint8_t *macaddr;
22
23
MemoryRegion *sram = g_new(MemoryRegion, 1);
24
MemoryRegion *flash = g_new(MemoryRegion, 1);
25
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
26
qdev_prop_set_uint32(nvic, "num-irq", NUM_IRQ_LINES);
27
qdev_prop_set_string(nvic, "cpu-type", ms->cpu_type);
28
qdev_prop_set_bit(nvic, "enable-bitband", true);
29
+ qdev_connect_clock_in(nvic, "cpuclk",
30
+ qdev_get_clock_out(ssys_dev, "SYSCLK"));
31
+ /* This SoC does not connect the systick reference clock */
32
object_property_set_link(OBJECT(nvic), "memory",
33
OBJECT(get_system_memory()), &error_abort);
34
/* This will exit with an error if the user passed us a bad cpu_type */
35
--
36
2.20.1
37
38
diff view generated by jsdifflib
New patch
1
In the realize method of the msf2-soc SoC object, we call g_new() to
2
create new MemoryRegion objects for the nvm, nvm_alias, and sram.
3
This is unnecessary; make these MemoryRegions member fields of the
4
device state struct instead.
1
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Alexandre Iooss <erdnaxe@crans.org>
8
Message-id: 20210812093356.1946-19-peter.maydell@linaro.org
9
---
10
include/hw/arm/msf2-soc.h | 4 ++++
11
hw/arm/msf2-soc.c | 17 +++++++----------
12
2 files changed, 11 insertions(+), 10 deletions(-)
13
14
diff --git a/include/hw/arm/msf2-soc.h b/include/hw/arm/msf2-soc.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/arm/msf2-soc.h
17
+++ b/include/hw/arm/msf2-soc.h
18
@@ -XXX,XX +XXX,XX @@ struct MSF2State {
19
MSSTimerState timer;
20
MSSSpiState spi[MSF2_NUM_SPIS];
21
MSF2EmacState emac;
22
+
23
+ MemoryRegion nvm;
24
+ MemoryRegion nvm_alias;
25
+ MemoryRegion sram;
26
};
27
28
#endif
29
diff --git a/hw/arm/msf2-soc.c b/hw/arm/msf2-soc.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/msf2-soc.c
32
+++ b/hw/arm/msf2-soc.c
33
@@ -XXX,XX +XXX,XX @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp)
34
int i;
35
36
MemoryRegion *system_memory = get_system_memory();
37
- MemoryRegion *nvm = g_new(MemoryRegion, 1);
38
- MemoryRegion *nvm_alias = g_new(MemoryRegion, 1);
39
- MemoryRegion *sram = g_new(MemoryRegion, 1);
40
41
- memory_region_init_rom(nvm, OBJECT(dev_soc), "MSF2.eNVM", s->envm_size,
42
+ memory_region_init_rom(&s->nvm, OBJECT(dev_soc), "MSF2.eNVM", s->envm_size,
43
&error_fatal);
44
/*
45
* On power-on, the eNVM region 0x60000000 is automatically
46
@@ -XXX,XX +XXX,XX @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp)
47
* start address (0x0). We do not support remapping other eNVM,
48
* eSRAM and DDR regions by guest(via Sysreg) currently.
49
*/
50
- memory_region_init_alias(nvm_alias, OBJECT(dev_soc), "MSF2.eNVM", nvm, 0,
51
- s->envm_size);
52
+ memory_region_init_alias(&s->nvm_alias, OBJECT(dev_soc), "MSF2.eNVM",
53
+ &s->nvm, 0, s->envm_size);
54
55
- memory_region_add_subregion(system_memory, ENVM_BASE_ADDRESS, nvm);
56
- memory_region_add_subregion(system_memory, 0, nvm_alias);
57
+ memory_region_add_subregion(system_memory, ENVM_BASE_ADDRESS, &s->nvm);
58
+ memory_region_add_subregion(system_memory, 0, &s->nvm_alias);
59
60
- memory_region_init_ram(sram, NULL, "MSF2.eSRAM", s->esram_size,
61
+ memory_region_init_ram(&s->sram, NULL, "MSF2.eSRAM", s->esram_size,
62
&error_fatal);
63
- memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, sram);
64
+ memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, &s->sram);
65
66
armv7m = DEVICE(&s->armv7m);
67
qdev_prop_set_uint32(armv7m, "num-irq", 81);
68
--
69
2.20.1
70
71
diff view generated by jsdifflib
New patch
1
Instead of passing the MSF2 SoC an integer property specifying the
2
CPU clock rate, pass it a Clock instead. This lets us wire that
3
clock up to the armv7m object.
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Alexandre Iooss <erdnaxe@crans.org>
7
Message-id: 20210812093356.1946-20-peter.maydell@linaro.org
8
---
9
include/hw/arm/msf2-soc.h | 3 ++-
10
hw/arm/msf2-soc.c | 28 +++++++++++++++++-----------
11
hw/arm/msf2-som.c | 7 ++++++-
12
3 files changed, 25 insertions(+), 13 deletions(-)
13
14
diff --git a/include/hw/arm/msf2-soc.h b/include/hw/arm/msf2-soc.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/arm/msf2-soc.h
17
+++ b/include/hw/arm/msf2-soc.h
18
@@ -XXX,XX +XXX,XX @@
19
#include "hw/misc/msf2-sysreg.h"
20
#include "hw/ssi/mss-spi.h"
21
#include "hw/net/msf2-emac.h"
22
+#include "hw/clock.h"
23
#include "qom/object.h"
24
25
#define TYPE_MSF2_SOC "msf2-soc"
26
@@ -XXX,XX +XXX,XX @@ struct MSF2State {
27
uint64_t envm_size;
28
uint64_t esram_size;
29
30
- uint32_t m3clk;
31
+ Clock *m3clk;
32
uint8_t apb0div;
33
uint8_t apb1div;
34
35
diff --git a/hw/arm/msf2-soc.c b/hw/arm/msf2-soc.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/arm/msf2-soc.c
38
+++ b/hw/arm/msf2-soc.c
39
@@ -XXX,XX +XXX,XX @@
40
#include "hw/char/serial.h"
41
#include "hw/arm/msf2-soc.h"
42
#include "hw/misc/unimp.h"
43
+#include "hw/qdev-clock.h"
44
#include "sysemu/sysemu.h"
45
46
#define MSF2_TIMER_BASE 0x40004000
47
@@ -XXX,XX +XXX,XX @@ static void m2sxxx_soc_initfn(Object *obj)
48
}
49
50
object_initialize_child(obj, "emac", &s->emac, TYPE_MSS_EMAC);
51
+
52
+ s->m3clk = qdev_init_clock_in(DEVICE(obj), "m3clk", NULL, NULL, 0);
53
}
54
55
static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp)
56
@@ -XXX,XX +XXX,XX @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp)
57
58
MemoryRegion *system_memory = get_system_memory();
59
60
+ if (!clock_has_source(s->m3clk)) {
61
+ error_setg(errp, "m3clk must be wired up by the board code");
62
+ return;
63
+ }
64
+
65
memory_region_init_rom(&s->nvm, OBJECT(dev_soc), "MSF2.eNVM", s->envm_size,
66
&error_fatal);
67
/*
68
@@ -XXX,XX +XXX,XX @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp)
69
qdev_prop_set_uint32(armv7m, "num-irq", 81);
70
qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
71
qdev_prop_set_bit(armv7m, "enable-bitband", true);
72
+ qdev_connect_clock_in(armv7m, "cpuclk", s->m3clk);
73
object_property_set_link(OBJECT(&s->armv7m), "memory",
74
OBJECT(get_system_memory()), &error_abort);
75
if (!sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), errp)) {
76
return;
77
}
78
79
- if (!s->m3clk) {
80
- error_setg(errp, "Invalid m3clk value");
81
- error_append_hint(errp, "m3clk can not be zero\n");
82
- return;
83
- }
84
-
85
- system_clock_scale = NANOSECONDS_PER_SECOND / s->m3clk;
86
+ system_clock_scale = clock_ticks_to_ns(s->m3clk, 1);
87
88
for (i = 0; i < MSF2_NUM_UARTS; i++) {
89
if (serial_hd(i)) {
90
@@ -XXX,XX +XXX,XX @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp)
91
}
92
93
dev = DEVICE(&s->timer);
94
- /* APB0 clock is the timer input clock */
95
- qdev_prop_set_uint32(dev, "clock-frequency", s->m3clk / s->apb0div);
96
+ /*
97
+ * APB0 clock is the timer input clock.
98
+ * TODO: ideally the MSF2 timer device should use a Clock rather than a
99
+ * clock-frequency integer property.
100
+ */
101
+ qdev_prop_set_uint32(dev, "clock-frequency",
102
+ clock_get_hz(s->m3clk) / s->apb0div);
103
if (!sysbus_realize(SYS_BUS_DEVICE(&s->timer), errp)) {
104
return;
105
}
106
@@ -XXX,XX +XXX,XX @@ static Property m2sxxx_soc_properties[] = {
107
DEFINE_PROP_UINT64("eNVM-size", MSF2State, envm_size, MSF2_ENVM_MAX_SIZE),
108
DEFINE_PROP_UINT64("eSRAM-size", MSF2State, esram_size,
109
MSF2_ESRAM_MAX_SIZE),
110
- /* Libero GUI shows 100Mhz as default for clocks */
111
- DEFINE_PROP_UINT32("m3clk", MSF2State, m3clk, 100 * 1000000),
112
/* default divisors in Libero GUI */
113
DEFINE_PROP_UINT8("apb0div", MSF2State, apb0div, 2),
114
DEFINE_PROP_UINT8("apb1div", MSF2State, apb1div, 2),
115
diff --git a/hw/arm/msf2-som.c b/hw/arm/msf2-som.c
116
index XXXXXXX..XXXXXXX 100644
117
--- a/hw/arm/msf2-som.c
118
+++ b/hw/arm/msf2-som.c
119
@@ -XXX,XX +XXX,XX @@
120
#include "hw/boards.h"
121
#include "hw/qdev-properties.h"
122
#include "hw/arm/boot.h"
123
+#include "hw/qdev-clock.h"
124
#include "exec/address-spaces.h"
125
#include "hw/arm/msf2-soc.h"
126
127
@@ -XXX,XX +XXX,XX @@ static void emcraft_sf2_s2s010_init(MachineState *machine)
128
BusState *spi_bus;
129
MemoryRegion *sysmem = get_system_memory();
130
MemoryRegion *ddr = g_new(MemoryRegion, 1);
131
+ Clock *m3clk;
132
133
if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
134
error_report("This board can only be used with CPU %s",
135
@@ -XXX,XX +XXX,XX @@ static void emcraft_sf2_s2s010_init(MachineState *machine)
136
* in Libero. CPU clock is divided by APB0 and APB1 divisors for
137
* peripherals. Emcraft's SoM kit comes with these settings by default.
138
*/
139
- qdev_prop_set_uint32(dev, "m3clk", 142 * 1000000);
140
+ /* This clock doesn't need migration because it is fixed-frequency */
141
+ m3clk = clock_new(OBJECT(machine), "m3clk");
142
+ clock_set_hz(m3clk, 142 * 1000000);
143
+ qdev_connect_clock_in(dev, "m3clk", m3clk);
144
qdev_prop_set_uint32(dev, "apb0div", 2);
145
qdev_prop_set_uint32(dev, "apb1div", 2);
146
147
--
148
2.20.1
149
150
diff view generated by jsdifflib
New patch
1
Wire up the refclk for the msf2 SoC. This SoC runs the refclk at a
2
frequency which is programmably either /4, /8, /16 or /32 of the main
3
CPU clock. We don't currently model the register which allows the
4
guest to set the divisor, so implement the refclk as a fixed /32 of
5
the CPU clock (which is the value of the divisor at reset).
1
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Damien Hedde <damien.hedde@greensocs.com>
9
Message-id: 20210812093356.1946-21-peter.maydell@linaro.org
10
---
11
include/hw/arm/msf2-soc.h | 1 +
12
hw/arm/msf2-soc.c | 23 +++++++++++++++++++++++
13
2 files changed, 24 insertions(+)
14
15
diff --git a/include/hw/arm/msf2-soc.h b/include/hw/arm/msf2-soc.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/arm/msf2-soc.h
18
+++ b/include/hw/arm/msf2-soc.h
19
@@ -XXX,XX +XXX,XX @@ struct MSF2State {
20
uint64_t esram_size;
21
22
Clock *m3clk;
23
+ Clock *refclk;
24
uint8_t apb0div;
25
uint8_t apb1div;
26
27
diff --git a/hw/arm/msf2-soc.c b/hw/arm/msf2-soc.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/hw/arm/msf2-soc.c
30
+++ b/hw/arm/msf2-soc.c
31
@@ -XXX,XX +XXX,XX @@ static void m2sxxx_soc_initfn(Object *obj)
32
object_initialize_child(obj, "emac", &s->emac, TYPE_MSS_EMAC);
33
34
s->m3clk = qdev_init_clock_in(DEVICE(obj), "m3clk", NULL, NULL, 0);
35
+ s->refclk = qdev_init_clock_in(DEVICE(obj), "refclk", NULL, NULL, 0);
36
}
37
38
static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp)
39
@@ -XXX,XX +XXX,XX @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp)
40
return;
41
}
42
43
+ /*
44
+ * We use s->refclk internally and only define it with qdev_init_clock_in()
45
+ * so it is correctly parented and not leaked on an init/deinit; it is not
46
+ * intended as an externally exposed clock.
47
+ */
48
+ if (clock_has_source(s->refclk)) {
49
+ error_setg(errp, "refclk must not be wired up by the board code");
50
+ return;
51
+ }
52
+
53
+ /*
54
+ * TODO: ideally we should model the SoC SYSTICK_CR register at 0xe0042038,
55
+ * which allows the guest to program the divisor between the m3clk and
56
+ * the systick refclk to either /4, /8, /16 or /32, as well as setting
57
+ * the value the guest can read in the STCALIB register. Currently we
58
+ * implement the divisor as a fixed /32, which matches the reset value
59
+ * of SYSTICK_CR.
60
+ */
61
+ clock_set_mul_div(s->refclk, 32, 1);
62
+ clock_set_source(s->refclk, s->m3clk);
63
+
64
memory_region_init_rom(&s->nvm, OBJECT(dev_soc), "MSF2.eNVM", s->envm_size,
65
&error_fatal);
66
/*
67
@@ -XXX,XX +XXX,XX @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp)
68
qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
69
qdev_prop_set_bit(armv7m, "enable-bitband", true);
70
qdev_connect_clock_in(armv7m, "cpuclk", s->m3clk);
71
+ qdev_connect_clock_in(armv7m, "refclk", s->refclk);
72
object_property_set_link(OBJECT(&s->armv7m), "memory",
73
OBJECT(get_system_memory()), &error_abort);
74
if (!sysbus_realize(SYS_BUS_DEVICE(&s->armv7m), errp)) {
75
--
76
2.20.1
77
78
diff view generated by jsdifflib
New patch
1
1
Now that all users of the systick devices wire up the clock inputs,
2
use those instead of the system_clock_scale and the hardwired 1MHz
3
value for the reference clock.
4
5
This will fix various board models where we were incorrectly
6
providing a 1MHz reference clock instead of some other value or
7
instead of providing no reference clock at all.
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Damien Hedde <damien.hedde@greensocs.com>
11
Message-id: 20210812093356.1946-22-peter.maydell@linaro.org
12
---
13
hw/timer/armv7m_systick.c | 112 ++++++++++++++++++++++++++++----------
14
1 file changed, 84 insertions(+), 28 deletions(-)
15
16
diff --git a/hw/timer/armv7m_systick.c b/hw/timer/armv7m_systick.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/timer/armv7m_systick.c
19
+++ b/hw/timer/armv7m_systick.c
20
@@ -XXX,XX +XXX,XX @@
21
#include "qemu/timer.h"
22
#include "qemu/log.h"
23
#include "qemu/module.h"
24
+#include "qapi/error.h"
25
#include "trace.h"
26
27
-/* qemu timers run at 1GHz. We want something closer to 1MHz. */
28
-#define SYSTICK_SCALE 1000ULL
29
-
30
#define SYSTICK_ENABLE (1 << 0)
31
#define SYSTICK_TICKINT (1 << 1)
32
#define SYSTICK_CLKSOURCE (1 << 2)
33
#define SYSTICK_COUNTFLAG (1 << 16)
34
35
+#define SYSCALIB_NOREF (1U << 31)
36
+#define SYSCALIB_SKEW (1U << 30)
37
+#define SYSCALIB_TENMS ((1U << 24) - 1)
38
+
39
int system_clock_scale;
40
41
-/* Conversion factor from qemu timer to SysTick frequencies. */
42
-static inline int64_t systick_scale(SysTickState *s)
43
+static void systick_set_period_from_clock(SysTickState *s)
44
{
45
+ /*
46
+ * Set the ptimer period from whichever clock is selected.
47
+ * Must be called from within a ptimer transaction block.
48
+ */
49
if (s->control & SYSTICK_CLKSOURCE) {
50
- return system_clock_scale;
51
+ ptimer_set_period_from_clock(s->ptimer, s->cpuclk, 1);
52
} else {
53
- return 1000;
54
+ ptimer_set_period_from_clock(s->ptimer, s->refclk, 1);
55
}
56
}
57
58
@@ -XXX,XX +XXX,XX @@ static MemTxResult systick_read(void *opaque, hwaddr addr, uint64_t *data,
59
val = ptimer_get_count(s->ptimer);
60
break;
61
case 0xc: /* SysTick Calibration Value. */
62
- val = 10000;
63
+ /*
64
+ * In real hardware it is possible to make this register report
65
+ * a different value from what the reference clock is actually
66
+ * running at. We don't model that (which usually happens due
67
+ * to integration errors in the real hardware) and instead always
68
+ * report the theoretical correct value as described in the
69
+ * knowledgebase article at
70
+ * https://developer.arm.com/documentation/ka001325/latest
71
+ * If necessary, we could implement an extra QOM property on this
72
+ * device to force the STCALIB value to something different from
73
+ * the "correct" value.
74
+ */
75
+ if (!clock_has_source(s->refclk)) {
76
+ val = SYSCALIB_NOREF;
77
+ break;
78
+ }
79
+ val = clock_ns_to_ticks(s->refclk, 10 * SCALE_MS) - 1;
80
+ val &= SYSCALIB_TENMS;
81
+ if (clock_ticks_to_ns(s->refclk, val + 1) != 10 * SCALE_MS) {
82
+ /* report that tick count does not yield exactly 10ms */
83
+ val |= SYSCALIB_SKEW;
84
+ }
85
break;
86
default:
87
val = 0;
88
@@ -XXX,XX +XXX,XX @@ static MemTxResult systick_write(void *opaque, hwaddr addr,
89
{
90
uint32_t oldval;
91
92
+ if (!clock_has_source(s->refclk)) {
93
+ /* This bit is always 1 if there is no external refclk */
94
+ value |= SYSTICK_CLKSOURCE;
95
+ }
96
+
97
ptimer_transaction_begin(s->ptimer);
98
oldval = s->control;
99
s->control &= 0xfffffff8;
100
@@ -XXX,XX +XXX,XX @@ static MemTxResult systick_write(void *opaque, hwaddr addr,
101
102
if ((oldval ^ value) & SYSTICK_ENABLE) {
103
if (value & SYSTICK_ENABLE) {
104
- /*
105
- * Always reload the period in case board code has
106
- * changed system_clock_scale. If we ever replace that
107
- * global with a more sensible API then we might be able
108
- * to set the period only when it actually changes.
109
- */
110
- ptimer_set_period(s->ptimer, systick_scale(s));
111
ptimer_run(s->ptimer, 0);
112
} else {
113
ptimer_stop(s->ptimer);
114
}
115
- } else if ((oldval ^ value) & SYSTICK_CLKSOURCE) {
116
- ptimer_set_period(s->ptimer, systick_scale(s));
117
+ }
118
+
119
+ if ((oldval ^ value) & SYSTICK_CLKSOURCE) {
120
+ systick_set_period_from_clock(s);
121
}
122
ptimer_transaction_commit(s->ptimer);
123
break;
124
@@ -XXX,XX +XXX,XX @@ static void systick_reset(DeviceState *dev)
125
{
126
SysTickState *s = SYSTICK(dev);
127
128
- /*
129
- * Forgetting to set system_clock_scale is always a board code
130
- * bug. We can't check this earlier because for some boards
131
- * (like stellaris) it is not yet configured at the point where
132
- * the systick device is realized.
133
- */
134
- assert(system_clock_scale != 0);
135
-
136
ptimer_transaction_begin(s->ptimer);
137
s->control = 0;
138
+ if (!clock_has_source(s->refclk)) {
139
+ /* This bit is always 1 if there is no external refclk */
140
+ s->control |= SYSTICK_CLKSOURCE;
141
+ }
142
ptimer_stop(s->ptimer);
143
ptimer_set_count(s->ptimer, 0);
144
ptimer_set_limit(s->ptimer, 0, 0);
145
- ptimer_set_period(s->ptimer, systick_scale(s));
146
+ systick_set_period_from_clock(s);
147
+ ptimer_transaction_commit(s->ptimer);
148
+}
149
+
150
+static void systick_cpuclk_update(void *opaque, ClockEvent event)
151
+{
152
+ SysTickState *s = SYSTICK(opaque);
153
+
154
+ if (!(s->control & SYSTICK_CLKSOURCE)) {
155
+ /* currently using refclk, we can ignore cpuclk changes */
156
+ }
157
+
158
+ ptimer_transaction_begin(s->ptimer);
159
+ ptimer_set_period_from_clock(s->ptimer, s->cpuclk, 1);
160
+ ptimer_transaction_commit(s->ptimer);
161
+}
162
+
163
+static void systick_refclk_update(void *opaque, ClockEvent event)
164
+{
165
+ SysTickState *s = SYSTICK(opaque);
166
+
167
+ if (s->control & SYSTICK_CLKSOURCE) {
168
+ /* currently using cpuclk, we can ignore refclk changes */
169
+ }
170
+
171
+ ptimer_transaction_begin(s->ptimer);
172
+ ptimer_set_period_from_clock(s->ptimer, s->refclk, 1);
173
ptimer_transaction_commit(s->ptimer);
174
}
175
176
@@ -XXX,XX +XXX,XX @@ static void systick_instance_init(Object *obj)
177
sysbus_init_mmio(sbd, &s->iomem);
178
sysbus_init_irq(sbd, &s->irq);
179
180
- s->refclk = qdev_init_clock_in(DEVICE(obj), "refclk", NULL, NULL, 0);
181
- s->cpuclk = qdev_init_clock_in(DEVICE(obj), "cpuclk", NULL, NULL, 0);
182
+ s->refclk = qdev_init_clock_in(DEVICE(obj), "refclk",
183
+ systick_refclk_update, s, ClockUpdate);
184
+ s->cpuclk = qdev_init_clock_in(DEVICE(obj), "cpuclk",
185
+ systick_cpuclk_update, s, ClockUpdate);
186
}
187
188
static void systick_realize(DeviceState *dev, Error **errp)
189
@@ -XXX,XX +XXX,XX @@ static void systick_realize(DeviceState *dev, Error **errp)
190
PTIMER_POLICY_NO_COUNTER_ROUND_DOWN |
191
PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
192
PTIMER_POLICY_TRIGGER_ONLY_ON_DECREMENT);
193
+
194
+ if (!clock_has_source(s->cpuclk)) {
195
+ error_setg(errp, "systick: cpuclk must be connected");
196
+ return;
197
+ }
198
+ /* It's OK not to connect the refclk */
199
}
200
201
static const VMStateDescription vmstate_systick = {
202
--
203
2.20.1
204
205
diff view generated by jsdifflib
New patch
1
Fix the code style issues in the Stellaris general purpose timer
2
module code, so that when we move it to a different file in a
3
following patch checkpatch doesn't complain.
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Alexandre Iooss <erdnaxe@crans.org>
7
Message-id: 20210812093356.1946-23-peter.maydell@linaro.org
8
---
9
hw/arm/stellaris.c | 13 ++++++++-----
10
1 file changed, 8 insertions(+), 5 deletions(-)
11
12
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/stellaris.c
15
+++ b/hw/arm/stellaris.c
16
@@ -XXX,XX +XXX,XX @@ static void gptm_stop(gptm_state *s, int n)
17
static void gptm_reload(gptm_state *s, int n, int reset)
18
{
19
int64_t tick;
20
- if (reset)
21
+ if (reset) {
22
tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
23
- else
24
+ } else {
25
tick = s->tick[n];
26
+ }
27
28
if (s->config == 0) {
29
/* 32-bit CountDown. */
30
@@ -XXX,XX +XXX,XX @@ static void gptm_write(void *opaque, hwaddr offset,
31
gptm_state *s = (gptm_state *)opaque;
32
uint32_t oldval;
33
34
- /* The timers should be disabled before changing the configuration.
35
- We take advantage of this and defer everything until the timer
36
- is enabled. */
37
+ /*
38
+ * The timers should be disabled before changing the configuration.
39
+ * We take advantage of this and defer everything until the timer
40
+ * is enabled.
41
+ */
42
switch (offset) {
43
case 0x00: /* CFG */
44
s->config = value;
45
--
46
2.20.1
47
48
diff view generated by jsdifflib
New patch
1
The implementation of the Stellaris general purpose timer module
2
device stellaris-gptm is currently in the same source file as the
3
board model. Split it out into its own source file in hw/timer.
1
4
5
Apart from the new file comment headers and the Kconfig and
6
meson.build changes, this is just code movement.
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Damien Hedde <damien.hedde@greensocs.com>
10
Message-id: 20210812093356.1946-24-peter.maydell@linaro.org
11
---
12
include/hw/timer/stellaris-gptm.h | 48 +++++
13
hw/arm/stellaris.c | 321 +-----------------------------
14
hw/timer/stellaris-gptm.c | 314 +++++++++++++++++++++++++++++
15
hw/arm/Kconfig | 1 +
16
hw/timer/Kconfig | 3 +
17
hw/timer/meson.build | 1 +
18
6 files changed, 368 insertions(+), 320 deletions(-)
19
create mode 100644 include/hw/timer/stellaris-gptm.h
20
create mode 100644 hw/timer/stellaris-gptm.c
21
22
diff --git a/include/hw/timer/stellaris-gptm.h b/include/hw/timer/stellaris-gptm.h
23
new file mode 100644
24
index XXXXXXX..XXXXXXX
25
--- /dev/null
26
+++ b/include/hw/timer/stellaris-gptm.h
27
@@ -XXX,XX +XXX,XX @@
28
+/*
29
+ * Luminary Micro Stellaris General Purpose Timer Module
30
+ *
31
+ * Copyright (c) 2006 CodeSourcery.
32
+ * Written by Paul Brook
33
+ *
34
+ * This code is licensed under the GPL.
35
+ */
36
+
37
+#ifndef HW_TIMER_STELLARIS_GPTM_H
38
+#define HW_TIMER_STELLARIS_GPTM_H
39
+
40
+#include "qom/object.h"
41
+#include "hw/sysbus.h"
42
+#include "hw/irq.h"
43
+
44
+#define TYPE_STELLARIS_GPTM "stellaris-gptm"
45
+OBJECT_DECLARE_SIMPLE_TYPE(gptm_state, STELLARIS_GPTM)
46
+
47
+/*
48
+ * QEMU interface:
49
+ * + sysbus MMIO region 0: register bank
50
+ * + sysbus IRQ 0: timer interrupt
51
+ * + unnamed GPIO output 0: trigger output for the ADC
52
+ */
53
+struct gptm_state {
54
+ SysBusDevice parent_obj;
55
+
56
+ MemoryRegion iomem;
57
+ uint32_t config;
58
+ uint32_t mode[2];
59
+ uint32_t control;
60
+ uint32_t state;
61
+ uint32_t mask;
62
+ uint32_t load[2];
63
+ uint32_t match[2];
64
+ uint32_t prescale[2];
65
+ uint32_t match_prescale[2];
66
+ uint32_t rtc;
67
+ int64_t tick[2];
68
+ struct gptm_state *opaque[2];
69
+ QEMUTimer *timer[2];
70
+ /* The timers have an alternate output used to trigger the ADC. */
71
+ qemu_irq trigger;
72
+ qemu_irq irq;
73
+};
74
+
75
+#endif
76
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
77
index XXXXXXX..XXXXXXX 100644
78
--- a/hw/arm/stellaris.c
79
+++ b/hw/arm/stellaris.c
80
@@ -XXX,XX +XXX,XX @@
81
#include "hw/watchdog/cmsdk-apb-watchdog.h"
82
#include "migration/vmstate.h"
83
#include "hw/misc/unimp.h"
84
+#include "hw/timer/stellaris-gptm.h"
85
#include "hw/qdev-clock.h"
86
#include "qom/object.h"
87
88
@@ -XXX,XX +XXX,XX @@ typedef const struct {
89
uint32_t peripherals;
90
} stellaris_board_info;
91
92
-/* General purpose timer module. */
93
-
94
-#define TYPE_STELLARIS_GPTM "stellaris-gptm"
95
-OBJECT_DECLARE_SIMPLE_TYPE(gptm_state, STELLARIS_GPTM)
96
-
97
-struct gptm_state {
98
- SysBusDevice parent_obj;
99
-
100
- MemoryRegion iomem;
101
- uint32_t config;
102
- uint32_t mode[2];
103
- uint32_t control;
104
- uint32_t state;
105
- uint32_t mask;
106
- uint32_t load[2];
107
- uint32_t match[2];
108
- uint32_t prescale[2];
109
- uint32_t match_prescale[2];
110
- uint32_t rtc;
111
- int64_t tick[2];
112
- struct gptm_state *opaque[2];
113
- QEMUTimer *timer[2];
114
- /* The timers have an alternate output used to trigger the ADC. */
115
- qemu_irq trigger;
116
- qemu_irq irq;
117
-};
118
-
119
-static void gptm_update_irq(gptm_state *s)
120
-{
121
- int level;
122
- level = (s->state & s->mask) != 0;
123
- qemu_set_irq(s->irq, level);
124
-}
125
-
126
-static void gptm_stop(gptm_state *s, int n)
127
-{
128
- timer_del(s->timer[n]);
129
-}
130
-
131
-static void gptm_reload(gptm_state *s, int n, int reset)
132
-{
133
- int64_t tick;
134
- if (reset) {
135
- tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
136
- } else {
137
- tick = s->tick[n];
138
- }
139
-
140
- if (s->config == 0) {
141
- /* 32-bit CountDown. */
142
- uint32_t count;
143
- count = s->load[0] | (s->load[1] << 16);
144
- tick += (int64_t)count * system_clock_scale;
145
- } else if (s->config == 1) {
146
- /* 32-bit RTC. 1Hz tick. */
147
- tick += NANOSECONDS_PER_SECOND;
148
- } else if (s->mode[n] == 0xa) {
149
- /* PWM mode. Not implemented. */
150
- } else {
151
- qemu_log_mask(LOG_UNIMP,
152
- "GPTM: 16-bit timer mode unimplemented: 0x%x\n",
153
- s->mode[n]);
154
- return;
155
- }
156
- s->tick[n] = tick;
157
- timer_mod(s->timer[n], tick);
158
-}
159
-
160
-static void gptm_tick(void *opaque)
161
-{
162
- gptm_state **p = (gptm_state **)opaque;
163
- gptm_state *s;
164
- int n;
165
-
166
- s = *p;
167
- n = p - s->opaque;
168
- if (s->config == 0) {
169
- s->state |= 1;
170
- if ((s->control & 0x20)) {
171
- /* Output trigger. */
172
- qemu_irq_pulse(s->trigger);
173
- }
174
- if (s->mode[0] & 1) {
175
- /* One-shot. */
176
- s->control &= ~1;
177
- } else {
178
- /* Periodic. */
179
- gptm_reload(s, 0, 0);
180
- }
181
- } else if (s->config == 1) {
182
- /* RTC. */
183
- uint32_t match;
184
- s->rtc++;
185
- match = s->match[0] | (s->match[1] << 16);
186
- if (s->rtc > match)
187
- s->rtc = 0;
188
- if (s->rtc == 0) {
189
- s->state |= 8;
190
- }
191
- gptm_reload(s, 0, 0);
192
- } else if (s->mode[n] == 0xa) {
193
- /* PWM mode. Not implemented. */
194
- } else {
195
- qemu_log_mask(LOG_UNIMP,
196
- "GPTM: 16-bit timer mode unimplemented: 0x%x\n",
197
- s->mode[n]);
198
- }
199
- gptm_update_irq(s);
200
-}
201
-
202
-static uint64_t gptm_read(void *opaque, hwaddr offset,
203
- unsigned size)
204
-{
205
- gptm_state *s = (gptm_state *)opaque;
206
-
207
- switch (offset) {
208
- case 0x00: /* CFG */
209
- return s->config;
210
- case 0x04: /* TAMR */
211
- return s->mode[0];
212
- case 0x08: /* TBMR */
213
- return s->mode[1];
214
- case 0x0c: /* CTL */
215
- return s->control;
216
- case 0x18: /* IMR */
217
- return s->mask;
218
- case 0x1c: /* RIS */
219
- return s->state;
220
- case 0x20: /* MIS */
221
- return s->state & s->mask;
222
- case 0x24: /* CR */
223
- return 0;
224
- case 0x28: /* TAILR */
225
- return s->load[0] | ((s->config < 4) ? (s->load[1] << 16) : 0);
226
- case 0x2c: /* TBILR */
227
- return s->load[1];
228
- case 0x30: /* TAMARCHR */
229
- return s->match[0] | ((s->config < 4) ? (s->match[1] << 16) : 0);
230
- case 0x34: /* TBMATCHR */
231
- return s->match[1];
232
- case 0x38: /* TAPR */
233
- return s->prescale[0];
234
- case 0x3c: /* TBPR */
235
- return s->prescale[1];
236
- case 0x40: /* TAPMR */
237
- return s->match_prescale[0];
238
- case 0x44: /* TBPMR */
239
- return s->match_prescale[1];
240
- case 0x48: /* TAR */
241
- if (s->config == 1) {
242
- return s->rtc;
243
- }
244
- qemu_log_mask(LOG_UNIMP,
245
- "GPTM: read of TAR but timer read not supported\n");
246
- return 0;
247
- case 0x4c: /* TBR */
248
- qemu_log_mask(LOG_UNIMP,
249
- "GPTM: read of TBR but timer read not supported\n");
250
- return 0;
251
- default:
252
- qemu_log_mask(LOG_GUEST_ERROR,
253
- "GPTM: read at bad offset 0x02%" HWADDR_PRIx "\n",
254
- offset);
255
- return 0;
256
- }
257
-}
258
-
259
-static void gptm_write(void *opaque, hwaddr offset,
260
- uint64_t value, unsigned size)
261
-{
262
- gptm_state *s = (gptm_state *)opaque;
263
- uint32_t oldval;
264
-
265
- /*
266
- * The timers should be disabled before changing the configuration.
267
- * We take advantage of this and defer everything until the timer
268
- * is enabled.
269
- */
270
- switch (offset) {
271
- case 0x00: /* CFG */
272
- s->config = value;
273
- break;
274
- case 0x04: /* TAMR */
275
- s->mode[0] = value;
276
- break;
277
- case 0x08: /* TBMR */
278
- s->mode[1] = value;
279
- break;
280
- case 0x0c: /* CTL */
281
- oldval = s->control;
282
- s->control = value;
283
- /* TODO: Implement pause. */
284
- if ((oldval ^ value) & 1) {
285
- if (value & 1) {
286
- gptm_reload(s, 0, 1);
287
- } else {
288
- gptm_stop(s, 0);
289
- }
290
- }
291
- if (((oldval ^ value) & 0x100) && s->config >= 4) {
292
- if (value & 0x100) {
293
- gptm_reload(s, 1, 1);
294
- } else {
295
- gptm_stop(s, 1);
296
- }
297
- }
298
- break;
299
- case 0x18: /* IMR */
300
- s->mask = value & 0x77;
301
- gptm_update_irq(s);
302
- break;
303
- case 0x24: /* CR */
304
- s->state &= ~value;
305
- break;
306
- case 0x28: /* TAILR */
307
- s->load[0] = value & 0xffff;
308
- if (s->config < 4) {
309
- s->load[1] = value >> 16;
310
- }
311
- break;
312
- case 0x2c: /* TBILR */
313
- s->load[1] = value & 0xffff;
314
- break;
315
- case 0x30: /* TAMARCHR */
316
- s->match[0] = value & 0xffff;
317
- if (s->config < 4) {
318
- s->match[1] = value >> 16;
319
- }
320
- break;
321
- case 0x34: /* TBMATCHR */
322
- s->match[1] = value >> 16;
323
- break;
324
- case 0x38: /* TAPR */
325
- s->prescale[0] = value;
326
- break;
327
- case 0x3c: /* TBPR */
328
- s->prescale[1] = value;
329
- break;
330
- case 0x40: /* TAPMR */
331
- s->match_prescale[0] = value;
332
- break;
333
- case 0x44: /* TBPMR */
334
- s->match_prescale[0] = value;
335
- break;
336
- default:
337
- qemu_log_mask(LOG_GUEST_ERROR,
338
- "GPTM: write at bad offset 0x02%" HWADDR_PRIx "\n",
339
- offset);
340
- }
341
- gptm_update_irq(s);
342
-}
343
-
344
-static const MemoryRegionOps gptm_ops = {
345
- .read = gptm_read,
346
- .write = gptm_write,
347
- .endianness = DEVICE_NATIVE_ENDIAN,
348
-};
349
-
350
-static const VMStateDescription vmstate_stellaris_gptm = {
351
- .name = "stellaris_gptm",
352
- .version_id = 1,
353
- .minimum_version_id = 1,
354
- .fields = (VMStateField[]) {
355
- VMSTATE_UINT32(config, gptm_state),
356
- VMSTATE_UINT32_ARRAY(mode, gptm_state, 2),
357
- VMSTATE_UINT32(control, gptm_state),
358
- VMSTATE_UINT32(state, gptm_state),
359
- VMSTATE_UINT32(mask, gptm_state),
360
- VMSTATE_UNUSED(8),
361
- VMSTATE_UINT32_ARRAY(load, gptm_state, 2),
362
- VMSTATE_UINT32_ARRAY(match, gptm_state, 2),
363
- VMSTATE_UINT32_ARRAY(prescale, gptm_state, 2),
364
- VMSTATE_UINT32_ARRAY(match_prescale, gptm_state, 2),
365
- VMSTATE_UINT32(rtc, gptm_state),
366
- VMSTATE_INT64_ARRAY(tick, gptm_state, 2),
367
- VMSTATE_TIMER_PTR_ARRAY(timer, gptm_state, 2),
368
- VMSTATE_END_OF_LIST()
369
- }
370
-};
371
-
372
-static void stellaris_gptm_init(Object *obj)
373
-{
374
- DeviceState *dev = DEVICE(obj);
375
- gptm_state *s = STELLARIS_GPTM(obj);
376
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
377
-
378
- sysbus_init_irq(sbd, &s->irq);
379
- qdev_init_gpio_out(dev, &s->trigger, 1);
380
-
381
- memory_region_init_io(&s->iomem, obj, &gptm_ops, s,
382
- "gptm", 0x1000);
383
- sysbus_init_mmio(sbd, &s->iomem);
384
-
385
- s->opaque[0] = s->opaque[1] = s;
386
-}
387
-
388
-static void stellaris_gptm_realize(DeviceState *dev, Error **errp)
389
-{
390
- gptm_state *s = STELLARIS_GPTM(dev);
391
- s->timer[0] = timer_new_ns(QEMU_CLOCK_VIRTUAL, gptm_tick, &s->opaque[0]);
392
- s->timer[1] = timer_new_ns(QEMU_CLOCK_VIRTUAL, gptm_tick, &s->opaque[1]);
393
-}
394
-
395
/* System controller. */
396
397
#define TYPE_STELLARIS_SYS "stellaris-sys"
398
@@ -XXX,XX +XXX,XX @@ static const TypeInfo stellaris_i2c_info = {
399
.class_init = stellaris_i2c_class_init,
400
};
401
402
-static void stellaris_gptm_class_init(ObjectClass *klass, void *data)
403
-{
404
- DeviceClass *dc = DEVICE_CLASS(klass);
405
-
406
- dc->vmsd = &vmstate_stellaris_gptm;
407
- dc->realize = stellaris_gptm_realize;
408
-}
409
-
410
-static const TypeInfo stellaris_gptm_info = {
411
- .name = TYPE_STELLARIS_GPTM,
412
- .parent = TYPE_SYS_BUS_DEVICE,
413
- .instance_size = sizeof(gptm_state),
414
- .instance_init = stellaris_gptm_init,
415
- .class_init = stellaris_gptm_class_init,
416
-};
417
-
418
static void stellaris_adc_class_init(ObjectClass *klass, void *data)
419
{
420
DeviceClass *dc = DEVICE_CLASS(klass);
421
@@ -XXX,XX +XXX,XX @@ static const TypeInfo stellaris_sys_info = {
422
static void stellaris_register_types(void)
423
{
424
type_register_static(&stellaris_i2c_info);
425
- type_register_static(&stellaris_gptm_info);
426
type_register_static(&stellaris_adc_info);
427
type_register_static(&stellaris_sys_info);
428
}
429
diff --git a/hw/timer/stellaris-gptm.c b/hw/timer/stellaris-gptm.c
430
new file mode 100644
431
index XXXXXXX..XXXXXXX
432
--- /dev/null
433
+++ b/hw/timer/stellaris-gptm.c
434
@@ -XXX,XX +XXX,XX @@
435
+/*
436
+ * Luminary Micro Stellaris General Purpose Timer Module
437
+ *
438
+ * Copyright (c) 2006 CodeSourcery.
439
+ * Written by Paul Brook
440
+ *
441
+ * This code is licensed under the GPL.
442
+ */
443
+
444
+#include "qemu/osdep.h"
445
+#include "qemu/log.h"
446
+#include "qemu/timer.h"
447
+#include "migration/vmstate.h"
448
+#include "hw/timer/stellaris-gptm.h"
449
+#include "hw/timer/armv7m_systick.h" /* Needed only for system_clock_scale */
450
+
451
+static void gptm_update_irq(gptm_state *s)
452
+{
453
+ int level;
454
+ level = (s->state & s->mask) != 0;
455
+ qemu_set_irq(s->irq, level);
456
+}
457
+
458
+static void gptm_stop(gptm_state *s, int n)
459
+{
460
+ timer_del(s->timer[n]);
461
+}
462
+
463
+static void gptm_reload(gptm_state *s, int n, int reset)
464
+{
465
+ int64_t tick;
466
+ if (reset) {
467
+ tick = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
468
+ } else {
469
+ tick = s->tick[n];
470
+ }
471
+
472
+ if (s->config == 0) {
473
+ /* 32-bit CountDown. */
474
+ uint32_t count;
475
+ count = s->load[0] | (s->load[1] << 16);
476
+ tick += (int64_t)count * system_clock_scale;
477
+ } else if (s->config == 1) {
478
+ /* 32-bit RTC. 1Hz tick. */
479
+ tick += NANOSECONDS_PER_SECOND;
480
+ } else if (s->mode[n] == 0xa) {
481
+ /* PWM mode. Not implemented. */
482
+ } else {
483
+ qemu_log_mask(LOG_UNIMP,
484
+ "GPTM: 16-bit timer mode unimplemented: 0x%x\n",
485
+ s->mode[n]);
486
+ return;
487
+ }
488
+ s->tick[n] = tick;
489
+ timer_mod(s->timer[n], tick);
490
+}
491
+
492
+static void gptm_tick(void *opaque)
493
+{
494
+ gptm_state **p = (gptm_state **)opaque;
495
+ gptm_state *s;
496
+ int n;
497
+
498
+ s = *p;
499
+ n = p - s->opaque;
500
+ if (s->config == 0) {
501
+ s->state |= 1;
502
+ if ((s->control & 0x20)) {
503
+ /* Output trigger. */
504
+ qemu_irq_pulse(s->trigger);
505
+ }
506
+ if (s->mode[0] & 1) {
507
+ /* One-shot. */
508
+ s->control &= ~1;
509
+ } else {
510
+ /* Periodic. */
511
+ gptm_reload(s, 0, 0);
512
+ }
513
+ } else if (s->config == 1) {
514
+ /* RTC. */
515
+ uint32_t match;
516
+ s->rtc++;
517
+ match = s->match[0] | (s->match[1] << 16);
518
+ if (s->rtc > match)
519
+ s->rtc = 0;
520
+ if (s->rtc == 0) {
521
+ s->state |= 8;
522
+ }
523
+ gptm_reload(s, 0, 0);
524
+ } else if (s->mode[n] == 0xa) {
525
+ /* PWM mode. Not implemented. */
526
+ } else {
527
+ qemu_log_mask(LOG_UNIMP,
528
+ "GPTM: 16-bit timer mode unimplemented: 0x%x\n",
529
+ s->mode[n]);
530
+ }
531
+ gptm_update_irq(s);
532
+}
533
+
534
+static uint64_t gptm_read(void *opaque, hwaddr offset,
535
+ unsigned size)
536
+{
537
+ gptm_state *s = (gptm_state *)opaque;
538
+
539
+ switch (offset) {
540
+ case 0x00: /* CFG */
541
+ return s->config;
542
+ case 0x04: /* TAMR */
543
+ return s->mode[0];
544
+ case 0x08: /* TBMR */
545
+ return s->mode[1];
546
+ case 0x0c: /* CTL */
547
+ return s->control;
548
+ case 0x18: /* IMR */
549
+ return s->mask;
550
+ case 0x1c: /* RIS */
551
+ return s->state;
552
+ case 0x20: /* MIS */
553
+ return s->state & s->mask;
554
+ case 0x24: /* CR */
555
+ return 0;
556
+ case 0x28: /* TAILR */
557
+ return s->load[0] | ((s->config < 4) ? (s->load[1] << 16) : 0);
558
+ case 0x2c: /* TBILR */
559
+ return s->load[1];
560
+ case 0x30: /* TAMARCHR */
561
+ return s->match[0] | ((s->config < 4) ? (s->match[1] << 16) : 0);
562
+ case 0x34: /* TBMATCHR */
563
+ return s->match[1];
564
+ case 0x38: /* TAPR */
565
+ return s->prescale[0];
566
+ case 0x3c: /* TBPR */
567
+ return s->prescale[1];
568
+ case 0x40: /* TAPMR */
569
+ return s->match_prescale[0];
570
+ case 0x44: /* TBPMR */
571
+ return s->match_prescale[1];
572
+ case 0x48: /* TAR */
573
+ if (s->config == 1) {
574
+ return s->rtc;
575
+ }
576
+ qemu_log_mask(LOG_UNIMP,
577
+ "GPTM: read of TAR but timer read not supported\n");
578
+ return 0;
579
+ case 0x4c: /* TBR */
580
+ qemu_log_mask(LOG_UNIMP,
581
+ "GPTM: read of TBR but timer read not supported\n");
582
+ return 0;
583
+ default:
584
+ qemu_log_mask(LOG_GUEST_ERROR,
585
+ "GPTM: read at bad offset 0x02%" HWADDR_PRIx "\n",
586
+ offset);
587
+ return 0;
588
+ }
589
+}
590
+
591
+static void gptm_write(void *opaque, hwaddr offset,
592
+ uint64_t value, unsigned size)
593
+{
594
+ gptm_state *s = (gptm_state *)opaque;
595
+ uint32_t oldval;
596
+
597
+ /*
598
+ * The timers should be disabled before changing the configuration.
599
+ * We take advantage of this and defer everything until the timer
600
+ * is enabled.
601
+ */
602
+ switch (offset) {
603
+ case 0x00: /* CFG */
604
+ s->config = value;
605
+ break;
606
+ case 0x04: /* TAMR */
607
+ s->mode[0] = value;
608
+ break;
609
+ case 0x08: /* TBMR */
610
+ s->mode[1] = value;
611
+ break;
612
+ case 0x0c: /* CTL */
613
+ oldval = s->control;
614
+ s->control = value;
615
+ /* TODO: Implement pause. */
616
+ if ((oldval ^ value) & 1) {
617
+ if (value & 1) {
618
+ gptm_reload(s, 0, 1);
619
+ } else {
620
+ gptm_stop(s, 0);
621
+ }
622
+ }
623
+ if (((oldval ^ value) & 0x100) && s->config >= 4) {
624
+ if (value & 0x100) {
625
+ gptm_reload(s, 1, 1);
626
+ } else {
627
+ gptm_stop(s, 1);
628
+ }
629
+ }
630
+ break;
631
+ case 0x18: /* IMR */
632
+ s->mask = value & 0x77;
633
+ gptm_update_irq(s);
634
+ break;
635
+ case 0x24: /* CR */
636
+ s->state &= ~value;
637
+ break;
638
+ case 0x28: /* TAILR */
639
+ s->load[0] = value & 0xffff;
640
+ if (s->config < 4) {
641
+ s->load[1] = value >> 16;
642
+ }
643
+ break;
644
+ case 0x2c: /* TBILR */
645
+ s->load[1] = value & 0xffff;
646
+ break;
647
+ case 0x30: /* TAMARCHR */
648
+ s->match[0] = value & 0xffff;
649
+ if (s->config < 4) {
650
+ s->match[1] = value >> 16;
651
+ }
652
+ break;
653
+ case 0x34: /* TBMATCHR */
654
+ s->match[1] = value >> 16;
655
+ break;
656
+ case 0x38: /* TAPR */
657
+ s->prescale[0] = value;
658
+ break;
659
+ case 0x3c: /* TBPR */
660
+ s->prescale[1] = value;
661
+ break;
662
+ case 0x40: /* TAPMR */
663
+ s->match_prescale[0] = value;
664
+ break;
665
+ case 0x44: /* TBPMR */
666
+ s->match_prescale[0] = value;
667
+ break;
668
+ default:
669
+ qemu_log_mask(LOG_GUEST_ERROR,
670
+ "GPTM: write at bad offset 0x02%" HWADDR_PRIx "\n",
671
+ offset);
672
+ }
673
+ gptm_update_irq(s);
674
+}
675
+
676
+static const MemoryRegionOps gptm_ops = {
677
+ .read = gptm_read,
678
+ .write = gptm_write,
679
+ .endianness = DEVICE_NATIVE_ENDIAN,
680
+};
681
+
682
+static const VMStateDescription vmstate_stellaris_gptm = {
683
+ .name = "stellaris_gptm",
684
+ .version_id = 1,
685
+ .minimum_version_id = 1,
686
+ .fields = (VMStateField[]) {
687
+ VMSTATE_UINT32(config, gptm_state),
688
+ VMSTATE_UINT32_ARRAY(mode, gptm_state, 2),
689
+ VMSTATE_UINT32(control, gptm_state),
690
+ VMSTATE_UINT32(state, gptm_state),
691
+ VMSTATE_UINT32(mask, gptm_state),
692
+ VMSTATE_UNUSED(8),
693
+ VMSTATE_UINT32_ARRAY(load, gptm_state, 2),
694
+ VMSTATE_UINT32_ARRAY(match, gptm_state, 2),
695
+ VMSTATE_UINT32_ARRAY(prescale, gptm_state, 2),
696
+ VMSTATE_UINT32_ARRAY(match_prescale, gptm_state, 2),
697
+ VMSTATE_UINT32(rtc, gptm_state),
698
+ VMSTATE_INT64_ARRAY(tick, gptm_state, 2),
699
+ VMSTATE_TIMER_PTR_ARRAY(timer, gptm_state, 2),
700
+ VMSTATE_END_OF_LIST()
701
+ }
702
+};
703
+
704
+static void stellaris_gptm_init(Object *obj)
705
+{
706
+ DeviceState *dev = DEVICE(obj);
707
+ gptm_state *s = STELLARIS_GPTM(obj);
708
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
709
+
710
+ sysbus_init_irq(sbd, &s->irq);
711
+ qdev_init_gpio_out(dev, &s->trigger, 1);
712
+
713
+ memory_region_init_io(&s->iomem, obj, &gptm_ops, s,
714
+ "gptm", 0x1000);
715
+ sysbus_init_mmio(sbd, &s->iomem);
716
+
717
+ s->opaque[0] = s->opaque[1] = s;
718
+}
719
+
720
+static void stellaris_gptm_realize(DeviceState *dev, Error **errp)
721
+{
722
+ gptm_state *s = STELLARIS_GPTM(dev);
723
+ s->timer[0] = timer_new_ns(QEMU_CLOCK_VIRTUAL, gptm_tick, &s->opaque[0]);
724
+ s->timer[1] = timer_new_ns(QEMU_CLOCK_VIRTUAL, gptm_tick, &s->opaque[1]);
725
+}
726
+
727
+static void stellaris_gptm_class_init(ObjectClass *klass, void *data)
728
+{
729
+ DeviceClass *dc = DEVICE_CLASS(klass);
730
+
731
+ dc->vmsd = &vmstate_stellaris_gptm;
732
+ dc->realize = stellaris_gptm_realize;
733
+}
734
+
735
+static const TypeInfo stellaris_gptm_info = {
736
+ .name = TYPE_STELLARIS_GPTM,
737
+ .parent = TYPE_SYS_BUS_DEVICE,
738
+ .instance_size = sizeof(gptm_state),
739
+ .instance_init = stellaris_gptm_init,
740
+ .class_init = stellaris_gptm_class_init,
741
+};
742
+
743
+static void stellaris_gptm_register_types(void)
744
+{
745
+ type_register_static(&stellaris_gptm_info);
746
+}
747
+
748
+type_init(stellaris_gptm_register_types)
749
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
750
index XXXXXXX..XXXXXXX 100644
751
--- a/hw/arm/Kconfig
752
+++ b/hw/arm/Kconfig
753
@@ -XXX,XX +XXX,XX @@ config STELLARIS
754
select SSI_SD
755
select STELLARIS_INPUT
756
select STELLARIS_ENET # ethernet
757
+ select STELLARIS_GPTM # general purpose timer module
758
select UNIMP
759
760
config STM32VLDISCOVERY
761
diff --git a/hw/timer/Kconfig b/hw/timer/Kconfig
762
index XXXXXXX..XXXXXXX 100644
763
--- a/hw/timer/Kconfig
764
+++ b/hw/timer/Kconfig
765
@@ -XXX,XX +XXX,XX @@ config SSE_COUNTER
766
config SSE_TIMER
767
bool
768
769
+config STELLARIS_GPTM
770
+ bool
771
+
772
config AVR_TIMER16
773
bool
774
diff --git a/hw/timer/meson.build b/hw/timer/meson.build
775
index XXXXXXX..XXXXXXX 100644
776
--- a/hw/timer/meson.build
777
+++ b/hw/timer/meson.build
778
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_SH_TIMER', if_true: files('sh_timer.c'))
779
softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_timer.c'))
780
softmmu_ss.add(when: 'CONFIG_SSE_COUNTER', if_true: files('sse-counter.c'))
781
softmmu_ss.add(when: 'CONFIG_SSE_TIMER', if_true: files('sse-timer.c'))
782
+softmmu_ss.add(when: 'CONFIG_STELLARIS_GPTM', if_true: files('stellaris-gptm.c'))
783
softmmu_ss.add(when: 'CONFIG_STM32F2XX_TIMER', if_true: files('stm32f2xx_timer.c'))
784
softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_timer.c'))
785
specific_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_timer.c'))
786
--
787
2.20.1
788
789
diff view generated by jsdifflib
New patch
1
The stellaris-gptm timer currently uses system_clock_scale for one of
2
its timer modes where the timer runs at the CPU clock rate. Make it
3
use a Clock input instead.
1
4
5
We don't try to make the timer handle changes in the clock frequency
6
while the downcounter is running. This is not a change in behaviour
7
from the previous system_clock_scale implementation -- we will pick
8
up the new frequency only when the downcounter hits zero. Handling
9
dynamic clock changes when the counter is running would require state
10
that the current gptm implementation doesn't have.
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Damien Hedde <damien.hedde@greensocs.com>
14
Message-id: 20210812093356.1946-25-peter.maydell@linaro.org
15
---
16
include/hw/timer/stellaris-gptm.h | 3 +++
17
hw/arm/stellaris.c | 12 +++++++++---
18
hw/timer/stellaris-gptm.c | 26 ++++++++++++++++++++++----
19
3 files changed, 34 insertions(+), 7 deletions(-)
20
21
diff --git a/include/hw/timer/stellaris-gptm.h b/include/hw/timer/stellaris-gptm.h
22
index XXXXXXX..XXXXXXX 100644
23
--- a/include/hw/timer/stellaris-gptm.h
24
+++ b/include/hw/timer/stellaris-gptm.h
25
@@ -XXX,XX +XXX,XX @@
26
#include "qom/object.h"
27
#include "hw/sysbus.h"
28
#include "hw/irq.h"
29
+#include "hw/clock.h"
30
31
#define TYPE_STELLARIS_GPTM "stellaris-gptm"
32
OBJECT_DECLARE_SIMPLE_TYPE(gptm_state, STELLARIS_GPTM)
33
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(gptm_state, STELLARIS_GPTM)
34
* + sysbus MMIO region 0: register bank
35
* + sysbus IRQ 0: timer interrupt
36
* + unnamed GPIO output 0: trigger output for the ADC
37
+ * + Clock input "clk": the 32-bit countdown timer runs at this speed
38
*/
39
struct gptm_state {
40
SysBusDevice parent_obj;
41
@@ -XXX,XX +XXX,XX @@ struct gptm_state {
42
/* The timers have an alternate output used to trigger the ADC. */
43
qemu_irq trigger;
44
qemu_irq irq;
45
+ Clock *clk;
46
};
47
48
#endif
49
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/arm/stellaris.c
52
+++ b/hw/arm/stellaris.c
53
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
54
}
55
for (i = 0; i < 4; i++) {
56
if (board->dc2 & (0x10000 << i)) {
57
- dev = sysbus_create_simple(TYPE_STELLARIS_GPTM,
58
- 0x40030000 + i * 0x1000,
59
- qdev_get_gpio_in(nvic, timer_irq[i]));
60
+ SysBusDevice *sbd;
61
+
62
+ dev = qdev_new(TYPE_STELLARIS_GPTM);
63
+ sbd = SYS_BUS_DEVICE(dev);
64
+ qdev_connect_clock_in(dev, "clk",
65
+ qdev_get_clock_out(ssys_dev, "SYSCLK"));
66
+ sysbus_realize_and_unref(sbd, &error_fatal);
67
+ sysbus_mmio_map(sbd, 0, 0x40030000 + i * 0x1000);
68
+ sysbus_connect_irq(sbd, 0, qdev_get_gpio_in(nvic, timer_irq[i]));
69
/* TODO: This is incorrect, but we get away with it because
70
the ADC output is only ever pulsed. */
71
qdev_connect_gpio_out(dev, 0, adc);
72
diff --git a/hw/timer/stellaris-gptm.c b/hw/timer/stellaris-gptm.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/hw/timer/stellaris-gptm.c
75
+++ b/hw/timer/stellaris-gptm.c
76
@@ -XXX,XX +XXX,XX @@
77
#include "qemu/osdep.h"
78
#include "qemu/log.h"
79
#include "qemu/timer.h"
80
+#include "qapi/error.h"
81
#include "migration/vmstate.h"
82
+#include "hw/qdev-clock.h"
83
#include "hw/timer/stellaris-gptm.h"
84
-#include "hw/timer/armv7m_systick.h" /* Needed only for system_clock_scale */
85
86
static void gptm_update_irq(gptm_state *s)
87
{
88
@@ -XXX,XX +XXX,XX @@ static void gptm_reload(gptm_state *s, int n, int reset)
89
/* 32-bit CountDown. */
90
uint32_t count;
91
count = s->load[0] | (s->load[1] << 16);
92
- tick += (int64_t)count * system_clock_scale;
93
+ tick += clock_ticks_to_ns(s->clk, count);
94
} else if (s->config == 1) {
95
/* 32-bit RTC. 1Hz tick. */
96
tick += NANOSECONDS_PER_SECOND;
97
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps gptm_ops = {
98
99
static const VMStateDescription vmstate_stellaris_gptm = {
100
.name = "stellaris_gptm",
101
- .version_id = 1,
102
- .minimum_version_id = 1,
103
+ .version_id = 2,
104
+ .minimum_version_id = 2,
105
.fields = (VMStateField[]) {
106
VMSTATE_UINT32(config, gptm_state),
107
VMSTATE_UINT32_ARRAY(mode, gptm_state, 2),
108
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_stellaris_gptm = {
109
VMSTATE_UINT32(rtc, gptm_state),
110
VMSTATE_INT64_ARRAY(tick, gptm_state, 2),
111
VMSTATE_TIMER_PTR_ARRAY(timer, gptm_state, 2),
112
+ VMSTATE_CLOCK(clk, gptm_state),
113
VMSTATE_END_OF_LIST()
114
}
115
};
116
@@ -XXX,XX +XXX,XX @@ static void stellaris_gptm_init(Object *obj)
117
sysbus_init_mmio(sbd, &s->iomem);
118
119
s->opaque[0] = s->opaque[1] = s;
120
+
121
+ /*
122
+ * TODO: in an ideal world we would model the effects of changing
123
+ * the input clock frequency while the countdown timer is active.
124
+ * The best way to do this would be to convert the device to use
125
+ * ptimer instead of hand-rolling its own timer. This would also
126
+ * make it easy to implement reading the current count from the
127
+ * TAR and TBR registers.
128
+ */
129
+ s->clk = qdev_init_clock_in(dev, "clk", NULL, NULL, 0);
130
}
131
132
static void stellaris_gptm_realize(DeviceState *dev, Error **errp)
133
{
134
gptm_state *s = STELLARIS_GPTM(dev);
135
+
136
+ if (!clock_has_source(s->clk)) {
137
+ error_setg(errp, "stellaris-gptm: clk must be connected");
138
+ return;
139
+ }
140
+
141
s->timer[0] = timer_new_ns(QEMU_CLOCK_VIRTUAL, gptm_tick, &s->opaque[0]);
142
s->timer[1] = timer_new_ns(QEMU_CLOCK_VIRTUAL, gptm_tick, &s->opaque[1]);
143
}
144
--
145
2.20.1
146
147
diff view generated by jsdifflib
1
The widenfn() in do_vshll_2sh() does not free the input 32-bit
1
All the devices that used to use system_clock_scale have now been
2
TCGv, so we need to do this in the calling code.
2
converted to use Clock inputs instead, so the global is no longer
3
needed; remove it and all the code that sets it.
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: Alistair Francis <alistair.francis@wdc.com>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20210812093356.1946-26-peter.maydell@linaro.org
7
---
8
---
8
target/arm/translate-neon.inc.c | 2 ++
9
include/hw/timer/armv7m_systick.h | 22 ----------------------
9
1 file changed, 2 insertions(+)
10
hw/arm/armsse.c | 17 +----------------
10
11
hw/arm/mps2.c | 2 --
11
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
12
hw/arm/msf2-soc.c | 2 --
12
index XXXXXXX..XXXXXXX 100644
13
hw/arm/netduino2.c | 2 --
13
--- a/target/arm/translate-neon.inc.c
14
hw/arm/netduinoplus2.c | 2 --
14
+++ b/target/arm/translate-neon.inc.c
15
hw/arm/nrf51_soc.c | 2 --
15
@@ -XXX,XX +XXX,XX @@ static bool do_vshll_2sh(DisasContext *s, arg_2reg_shift *a,
16
hw/arm/stellaris.c | 7 ++++---
16
tmp = tcg_temp_new_i64();
17
hw/arm/stm32vldiscovery.c | 2 --
17
18
hw/timer/armv7m_systick.c | 2 --
18
widenfn(tmp, rm0);
19
10 files changed, 5 insertions(+), 55 deletions(-)
19
+ tcg_temp_free_i32(rm0);
20
20
if (a->shift != 0) {
21
diff --git a/include/hw/timer/armv7m_systick.h b/include/hw/timer/armv7m_systick.h
21
tcg_gen_shli_i64(tmp, tmp, a->shift);
22
index XXXXXXX..XXXXXXX 100644
22
tcg_gen_andi_i64(tmp, tmp, ~widen_mask);
23
--- a/include/hw/timer/armv7m_systick.h
23
@@ -XXX,XX +XXX,XX @@ static bool do_vshll_2sh(DisasContext *s, arg_2reg_shift *a,
24
+++ b/include/hw/timer/armv7m_systick.h
24
neon_store_reg64(tmp, a->vd);
25
@@ -XXX,XX +XXX,XX @@ struct SysTickState {
25
26
Clock *cpuclk;
26
widenfn(tmp, rm1);
27
};
27
+ tcg_temp_free_i32(rm1);
28
28
if (a->shift != 0) {
29
-/*
29
tcg_gen_shli_i64(tmp, tmp, a->shift);
30
- * Multiplication factor to convert from system clock ticks to qemu timer
30
tcg_gen_andi_i64(tmp, tmp, ~widen_mask);
31
- * ticks. This should be set (by board code, usually) to a value
32
- * equal to NANOSECONDS_PER_SECOND / frq, where frq is the clock frequency
33
- * in Hz of the CPU.
34
- *
35
- * This value is used by the systick device when it is running in
36
- * its "use the CPU clock" mode (ie when SYST_CSR.CLKSOURCE == 1) to
37
- * set how fast the timer should tick.
38
- *
39
- * TODO: we should refactor this so that rather than using a global
40
- * we use a device property or something similar. This is complicated
41
- * because (a) the property would need to be plumbed through from the
42
- * board code down through various layers to the systick device
43
- * and (b) the property needs to be modifiable after realize, because
44
- * the stellaris board uses this to implement the behaviour where the
45
- * guest can reprogram the PLL registers to downclock the CPU, and the
46
- * systick device needs to react accordingly. Possibly this should
47
- * be deferred until we have a good API for modelling clock trees.
48
- */
49
-extern int system_clock_scale;
50
-
51
#endif
52
diff --git a/hw/arm/armsse.c b/hw/arm/armsse.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/hw/arm/armsse.c
55
+++ b/hw/arm/armsse.c
56
@@ -XXX,XX +XXX,XX @@ static void armsse_forward_sec_resp_cfg(ARMSSE *s)
57
qdev_connect_gpio_out(dev_splitter, 2, s->sec_resp_cfg_in);
58
}
59
60
-static void armsse_mainclk_update(void *opaque, ClockEvent event)
61
-{
62
- ARMSSE *s = ARM_SSE(opaque);
63
-
64
- /*
65
- * Set system_clock_scale from our Clock input; this is what
66
- * controls the tick rate of the CPU SysTick timer.
67
- */
68
- system_clock_scale = clock_ticks_to_ns(s->mainclk, 1);
69
-}
70
-
71
static void armsse_init(Object *obj)
72
{
73
ARMSSE *s = ARM_SSE(obj);
74
@@ -XXX,XX +XXX,XX @@ static void armsse_init(Object *obj)
75
assert(info->sram_banks <= MAX_SRAM_BANKS);
76
assert(info->num_cpus <= SSE_MAX_CPUS);
77
78
- s->mainclk = qdev_init_clock_in(DEVICE(s), "MAINCLK",
79
- armsse_mainclk_update, s, ClockUpdate);
80
+ s->mainclk = qdev_init_clock_in(DEVICE(s), "MAINCLK", NULL, NULL, 0);
81
s->s32kclk = qdev_init_clock_in(DEVICE(s), "S32KCLK", NULL, NULL, 0);
82
83
memory_region_init(&s->container, obj, "armsse-container", UINT64_MAX);
84
@@ -XXX,XX +XXX,XX @@ static void armsse_realize(DeviceState *dev, Error **errp)
85
* devices in the ARMSSE.
86
*/
87
sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->container);
88
-
89
- /* Set initial system_clock_scale from MAINCLK */
90
- armsse_mainclk_update(s, ClockUpdate);
91
}
92
93
static void armsse_idau_check(IDAUInterface *ii, uint32_t address,
94
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
95
index XXXXXXX..XXXXXXX 100644
96
--- a/hw/arm/mps2.c
97
+++ b/hw/arm/mps2.c
98
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
99
qdev_get_gpio_in(armv7m,
100
mmc->fpga_type == FPGA_AN511 ? 47 : 13));
101
102
- system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
103
-
104
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
105
0x400000);
106
}
107
diff --git a/hw/arm/msf2-soc.c b/hw/arm/msf2-soc.c
108
index XXXXXXX..XXXXXXX 100644
109
--- a/hw/arm/msf2-soc.c
110
+++ b/hw/arm/msf2-soc.c
111
@@ -XXX,XX +XXX,XX @@ static void m2sxxx_soc_realize(DeviceState *dev_soc, Error **errp)
112
return;
113
}
114
115
- system_clock_scale = clock_ticks_to_ns(s->m3clk, 1);
116
-
117
for (i = 0; i < MSF2_NUM_UARTS; i++) {
118
if (serial_hd(i)) {
119
serial_mm_init(get_system_memory(), uart_addr[i], 2,
120
diff --git a/hw/arm/netduino2.c b/hw/arm/netduino2.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/hw/arm/netduino2.c
123
+++ b/hw/arm/netduino2.c
124
@@ -XXX,XX +XXX,XX @@ static void netduino2_init(MachineState *machine)
125
DeviceState *dev;
126
Clock *sysclk;
127
128
- system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
129
-
130
/* This clock doesn't need migration because it is fixed-frequency */
131
sysclk = clock_new(OBJECT(machine), "SYSCLK");
132
clock_set_hz(sysclk, SYSCLK_FRQ);
133
diff --git a/hw/arm/netduinoplus2.c b/hw/arm/netduinoplus2.c
134
index XXXXXXX..XXXXXXX 100644
135
--- a/hw/arm/netduinoplus2.c
136
+++ b/hw/arm/netduinoplus2.c
137
@@ -XXX,XX +XXX,XX @@ static void netduinoplus2_init(MachineState *machine)
138
DeviceState *dev;
139
Clock *sysclk;
140
141
- system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
142
-
143
/* This clock doesn't need migration because it is fixed-frequency */
144
sysclk = clock_new(OBJECT(machine), "SYSCLK");
145
clock_set_hz(sysclk, SYSCLK_FRQ);
146
diff --git a/hw/arm/nrf51_soc.c b/hw/arm/nrf51_soc.c
147
index XXXXXXX..XXXXXXX 100644
148
--- a/hw/arm/nrf51_soc.c
149
+++ b/hw/arm/nrf51_soc.c
150
@@ -XXX,XX +XXX,XX @@ static void nrf51_soc_realize(DeviceState *dev_soc, Error **errp)
151
* will always provide one).
152
*/
153
154
- system_clock_scale = NANOSECONDS_PER_SECOND / HCLK_FRQ;
155
-
156
object_property_set_link(OBJECT(&s->cpu), "memory", OBJECT(&s->container),
157
&error_abort);
158
if (!sysbus_realize(SYS_BUS_DEVICE(&s->cpu), errp)) {
159
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
160
index XXXXXXX..XXXXXXX 100644
161
--- a/hw/arm/stellaris.c
162
+++ b/hw/arm/stellaris.c
163
@@ -XXX,XX +XXX,XX @@ static bool ssys_use_rcc2(ssys_state *s)
164
*/
165
static void ssys_calculate_system_clock(ssys_state *s, bool propagate_clock)
166
{
167
+ int period_ns;
168
/*
169
* SYSDIV field specifies divisor: 0 == /1, 1 == /2, etc. Input
170
* clock is 200MHz, which is a period of 5 ns. Dividing the clock
171
* frequency by X is the same as multiplying the period by X.
172
*/
173
if (ssys_use_rcc2(s)) {
174
- system_clock_scale = 5 * (((s->rcc2 >> 23) & 0x3f) + 1);
175
+ period_ns = 5 * (((s->rcc2 >> 23) & 0x3f) + 1);
176
} else {
177
- system_clock_scale = 5 * (((s->rcc >> 23) & 0xf) + 1);
178
+ period_ns = 5 * (((s->rcc >> 23) & 0xf) + 1);
179
}
180
- clock_set_ns(s->sysclk, system_clock_scale);
181
+ clock_set_ns(s->sysclk, period_ns);
182
if (propagate_clock) {
183
clock_propagate(s->sysclk);
184
}
185
diff --git a/hw/arm/stm32vldiscovery.c b/hw/arm/stm32vldiscovery.c
186
index XXXXXXX..XXXXXXX 100644
187
--- a/hw/arm/stm32vldiscovery.c
188
+++ b/hw/arm/stm32vldiscovery.c
189
@@ -XXX,XX +XXX,XX @@ static void stm32vldiscovery_init(MachineState *machine)
190
DeviceState *dev;
191
Clock *sysclk;
192
193
- system_clock_scale = NANOSECONDS_PER_SECOND / SYSCLK_FRQ;
194
-
195
/* This clock doesn't need migration because it is fixed-frequency */
196
sysclk = clock_new(OBJECT(machine), "SYSCLK");
197
clock_set_hz(sysclk, SYSCLK_FRQ);
198
diff --git a/hw/timer/armv7m_systick.c b/hw/timer/armv7m_systick.c
199
index XXXXXXX..XXXXXXX 100644
200
--- a/hw/timer/armv7m_systick.c
201
+++ b/hw/timer/armv7m_systick.c
202
@@ -XXX,XX +XXX,XX @@
203
#define SYSCALIB_SKEW (1U << 30)
204
#define SYSCALIB_TENMS ((1U << 24) - 1)
205
206
-int system_clock_scale;
207
-
208
static void systick_set_period_from_clock(SysTickState *s)
209
{
210
/*
31
--
211
--
32
2.20.1
212
2.20.1
33
213
34
214
diff view generated by jsdifflib