1
Mostly my decodetree stuff, but also some patches for various
1
First arm pullreq for 7.1. The bulk of this is the qemu_split_irq
2
smaller bugs/features from others.
2
removal.
3
4
I have enough stuff in my to-review queue that I expect to do another
5
pullreq early next week, but 31 patches is enough to not hang on to.
3
6
4
thanks
7
thanks
5
-- PMM
8
-- PMM
6
9
7
The following changes since commit 53550e81e2cafe7c03a39526b95cd21b5194d9b1:
10
The following changes since commit 9c125d17e9402c232c46610802e5931b3639d77b:
8
11
9
Merge remote-tracking branch 'remotes/berrange/tags/qcrypto-next-pull-request' into staging (2020-06-15 16:36:34 +0100)
12
Merge tag 'pull-tcg-20220420' of https://gitlab.com/rth7680/qemu into staging (2022-04-20 16:43:11 -0700)
10
13
11
are available in the Git repository at:
14
are available in the Git repository at:
12
15
13
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200616
16
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220421
14
17
15
for you to fetch changes up to 64b397417a26509bcdff44ab94356a35c7901c79:
18
for you to fetch changes up to 5b415dd61bdbf61fb4be0e9f1a7172b8bce682c6:
16
19
17
hw: arm: Set vendor property for IMX SDHCI emulations (2020-06-16 10:32:29 +0100)
20
hw/arm: Use bit fields for NPCM7XX PWRON STRAPs (2022-04-21 11:37:05 +0100)
18
21
19
----------------------------------------------------------------
22
----------------------------------------------------------------
20
* hw: arm: Set vendor property for IMX SDHCI emulations
23
target-arm queue:
21
* sd: sdhci: Implement basic vendor specific register support
24
* hw/arm/virt: Check for attempt to use TrustZone with KVM or HVF
22
* hw/net/imx_fec: Convert debug fprintf() to trace events
25
* versal: Add the Cortex-R5s in the Real-Time Processing Unit (RPU) subsystem
23
* target/arm/cpu: adjust virtual time for all KVM arm cpus
26
* versal: model enough of the Clock/Reset Low-power domain (CRL) to allow control of the Cortex-R5s
24
* Implement configurable descriptor size in ftgmac100
27
* xlnx-zynqmp: Connect 4 TTC timers
25
* hw/misc/imx6ul_ccm: Implement non writable bits in CCM registers
28
* exynos4210: Refactor GIC/combiner code to stop using qemu_split_irq
26
* target/arm: More Neon decodetree conversion work
29
* realview: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
30
* stellaris: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
31
* hw/core/irq: remove unused 'qemu_irq_split' function
32
* npcm7xx: use symbolic constants for PWRON STRAP bit fields
33
* virt: document impact of gic-version on max CPUs
27
34
28
----------------------------------------------------------------
35
----------------------------------------------------------------
29
Erik Smit (1):
36
Edgar E. Iglesias (6):
30
Implement configurable descriptor size in ftgmac100
37
timer: cadence_ttc: Break out header file to allow embedding
38
hw/arm/xlnx-zynqmp: Connect 4 TTC timers
39
hw/arm: versal: Create an APU CPU Cluster
40
hw/arm: versal: Add the Cortex-R5Fs
41
hw/misc: Add a model of the Xilinx Versal CRL
42
hw/arm: versal: Connect the CRL
31
43
32
Guenter Roeck (2):
44
Hao Wu (2):
33
sd: sdhci: Implement basic vendor specific register support
45
hw/misc: Add PWRON STRAP bit fields in GCR module
34
hw: arm: Set vendor property for IMX SDHCI emulations
46
hw/arm: Use bit fields for NPCM7XX PWRON STRAPs
35
47
36
Jean-Christophe Dubois (2):
48
Heinrich Schuchardt (1):
37
hw/misc/imx6ul_ccm: Implement non writable bits in CCM registers
49
hw/arm/virt: impact of gic-version on max CPUs
38
hw/net/imx_fec: Convert debug fprintf() to trace events
39
50
40
Peter Maydell (17):
51
Peter Maydell (19):
41
target/arm: Fix missing temp frees in do_vshll_2sh
52
hw/arm/virt: Check for attempt to use TrustZone with KVM or HVF
42
target/arm: Convert Neon 3-reg-diff prewidening ops to decodetree
53
hw/arm/exynos4210: Use TYPE_OR_IRQ instead of custom OR-gate device
43
target/arm: Convert Neon 3-reg-diff narrowing ops to decodetree
54
hw/intc/exynos4210_gic: Remove unused TYPE_EXYNOS4210_IRQ_GATE
44
target/arm: Convert Neon 3-reg-diff VABAL, VABDL to decodetree
55
hw/arm/exynos4210: Put a9mpcore device into state struct
45
target/arm: Convert Neon 3-reg-diff long multiplies
56
hw/arm/exynos4210: Drop int_gic_irq[] from Exynos4210Irq struct
46
target/arm: Convert Neon 3-reg-diff saturating doubling multiplies
57
hw/arm/exynos4210: Coalesce board_irqs and irq_table
47
target/arm: Convert Neon 3-reg-diff polynomial VMULL
58
hw/arm/exynos4210: Fix code style nit in combiner_grp_to_gic_id[]
48
target/arm: Add 'static' and 'const' annotations to VSHLL function arrays
59
hw/arm/exynos4210: Move exynos4210_init_board_irqs() into exynos4210.c
49
target/arm: Add missing TCG temp free in do_2shift_env_64()
60
hw/arm/exynos4210: Put external GIC into state struct
50
target/arm: Convert Neon 2-reg-scalar integer multiplies to decodetree
61
hw/arm/exynos4210: Drop ext_gic_irq[] from Exynos4210Irq struct
51
target/arm: Convert Neon 2-reg-scalar float multiplies to decodetree
62
hw/arm/exynos4210: Move exynos4210_combiner_get_gpioin() into exynos4210.c
52
target/arm: Convert Neon 2-reg-scalar VQDMULH, VQRDMULH to decodetree
63
hw/arm/exynos4210: Delete unused macro definitions
53
target/arm: Convert Neon 2-reg-scalar VQRDMLAH, VQRDMLSH to decodetree
64
hw/arm/exynos4210: Use TYPE_SPLIT_IRQ in exynos4210_init_board_irqs()
54
target/arm: Convert Neon 2-reg-scalar long multiplies to decodetree
65
hw/arm/exynos4210: Fill in irq_table[] for internal-combiner-only IRQ lines
55
target/arm: Convert Neon VEXT to decodetree
66
hw/arm/exynos4210: Connect MCT_G0 and MCT_G1 to both combiners
56
target/arm: Convert Neon VTBL, VTBX to decodetree
67
hw/arm/exynos4210: Don't connect multiple lines to external GIC inputs
57
target/arm: Convert Neon VDUP (scalar) to decodetree
68
hw/arm/exynos4210: Fold combiner splits into exynos4210_init_board_irqs()
69
hw/arm/exynos4210: Put combiners into state struct
70
hw/arm/exynos4210: Drop Exynos4210Irq struct
58
71
59
fangying (1):
72
Zongyuan Li (3):
60
target/arm/cpu: adjust virtual time for all KVM arm cpus
73
hw/arm/realview: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
74
hw/arm/stellaris: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
75
hw/core/irq: remove unused 'qemu_irq_split' function
61
76
62
hw/sd/sdhci-internal.h | 5 +
77
docs/system/arm/virt.rst | 4 +-
63
include/hw/sd/sdhci.h | 5 +
78
include/hw/arm/exynos4210.h | 50 ++--
64
target/arm/translate.h | 1 +
79
include/hw/arm/xlnx-versal.h | 16 ++
65
target/arm/neon-dp.decode | 130 +++++
80
include/hw/arm/xlnx-zynqmp.h | 4 +
66
hw/arm/fsl-imx25.c | 6 +
81
include/hw/intc/exynos4210_combiner.h | 57 +++++
67
hw/arm/fsl-imx6.c | 6 +
82
include/hw/intc/exynos4210_gic.h | 43 ++++
68
hw/arm/fsl-imx6ul.c | 2 +
83
include/hw/irq.h | 5 -
69
hw/arm/fsl-imx7.c | 2 +
84
include/hw/misc/npcm7xx_gcr.h | 30 +++
70
hw/misc/imx6ul_ccm.c | 76 ++-
85
include/hw/misc/xlnx-versal-crl.h | 235 +++++++++++++++++++
71
hw/net/ftgmac100.c | 26 +-
86
include/hw/timer/cadence_ttc.h | 54 +++++
72
hw/net/imx_fec.c | 106 ++--
87
hw/arm/exynos4210.c | 430 ++++++++++++++++++++++++++++++----
73
hw/sd/sdhci.c | 18 +-
88
hw/arm/npcm7xx_boards.c | 24 +-
74
target/arm/cpu.c | 6 +-
89
hw/arm/realview.c | 33 ++-
75
target/arm/cpu64.c | 1 -
90
hw/arm/stellaris.c | 15 +-
76
target/arm/kvm.c | 21 +-
91
hw/arm/virt.c | 7 +
77
target/arm/translate-neon.inc.c | 1148 ++++++++++++++++++++++++++++++++++++++-
92
hw/arm/xlnx-versal-virt.c | 6 +-
78
target/arm/translate.c | 684 +----------------------
93
hw/arm/xlnx-versal.c | 99 +++++++-
79
hw/net/trace-events | 18 +
94
hw/arm/xlnx-zynqmp.c | 22 ++
80
18 files changed, 1495 insertions(+), 766 deletions(-)
95
hw/core/irq.c | 15 --
81
96
hw/intc/exynos4210_combiner.c | 108 +--------
97
hw/intc/exynos4210_gic.c | 344 +--------------------------
98
hw/misc/xlnx-versal-crl.c | 421 +++++++++++++++++++++++++++++++++
99
hw/timer/cadence_ttc.c | 32 +--
100
MAINTAINERS | 2 +-
101
hw/misc/meson.build | 1 +
102
25 files changed, 1457 insertions(+), 600 deletions(-)
103
create mode 100644 include/hw/intc/exynos4210_combiner.h
104
create mode 100644 include/hw/intc/exynos4210_gic.h
105
create mode 100644 include/hw/misc/xlnx-versal-crl.h
106
create mode 100644 include/hw/timer/cadence_ttc.h
107
create mode 100644 hw/misc/xlnx-versal-crl.c
diff view generated by jsdifflib
New patch
1
It's not possible to provide the guest with the Security extensions
2
(TrustZone) when using KVM or HVF, because the hardware
3
virtualization extensions don't permit running EL3 guest code.
4
However, we weren't checking for this combination, with the result
5
that QEMU would assert if you tried it:
1
6
7
$ qemu-system-aarch64 -enable-kvm -machine virt,secure=on -cpu host -display none
8
Unexpected error in object_property_find_err() at ../../qom/object.c:1304:
9
qemu-system-aarch64: Property 'host-arm-cpu.secure-memory' not found
10
Aborted
11
12
Check for this combination of options and report an error, in the
13
same way we already do for attempts to give a KVM or HVF guest the
14
Virtualization or MTE extensions. Now we will report:
15
16
qemu-system-aarch64: mach-virt: KVM does not support providing Security extensions (TrustZone) to the guest CPU
17
18
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/961
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20220404155301.566542-1-peter.maydell@linaro.org
22
---
23
hw/arm/virt.c | 7 +++++++
24
1 file changed, 7 insertions(+)
25
26
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/arm/virt.c
29
+++ b/hw/arm/virt.c
30
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
31
exit(1);
32
}
33
34
+ if (vms->secure && (kvm_enabled() || hvf_enabled())) {
35
+ error_report("mach-virt: %s does not support providing "
36
+ "Security extensions (TrustZone) to the guest CPU",
37
+ kvm_enabled() ? "KVM" : "HVF");
38
+ exit(1);
39
+ }
40
+
41
if (vms->virt && (kvm_enabled() || hvf_enabled())) {
42
error_report("mach-virt: %s does not support providing "
43
"Virtualization extensions to the guest CPU",
44
--
45
2.25.1
diff view generated by jsdifflib
New patch
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
1
2
3
Break out header file to allow embedding of the the TTC.
4
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
8
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
9
Message-id: 20220331222017.2914409-2-edgar.iglesias@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/timer/cadence_ttc.h | 54 ++++++++++++++++++++++++++++++++++
13
hw/timer/cadence_ttc.c | 32 ++------------------
14
2 files changed, 56 insertions(+), 30 deletions(-)
15
create mode 100644 include/hw/timer/cadence_ttc.h
16
17
diff --git a/include/hw/timer/cadence_ttc.h b/include/hw/timer/cadence_ttc.h
18
new file mode 100644
19
index XXXXXXX..XXXXXXX
20
--- /dev/null
21
+++ b/include/hw/timer/cadence_ttc.h
22
@@ -XXX,XX +XXX,XX @@
23
+/*
24
+ * Xilinx Zynq cadence TTC model
25
+ *
26
+ * Copyright (c) 2011 Xilinx Inc.
27
+ * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite@petalogix.com)
28
+ * Copyright (c) 2012 PetaLogix Pty Ltd.
29
+ * Written By Haibing Ma
30
+ * M. Habib
31
+ *
32
+ * This program is free software; you can redistribute it and/or
33
+ * modify it under the terms of the GNU General Public License
34
+ * as published by the Free Software Foundation; either version
35
+ * 2 of the License, or (at your option) any later version.
36
+ *
37
+ * You should have received a copy of the GNU General Public License along
38
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
39
+ */
40
+#ifndef HW_TIMER_CADENCE_TTC_H
41
+#define HW_TIMER_CADENCE_TTC_H
42
+
43
+#include "hw/sysbus.h"
44
+#include "qemu/timer.h"
45
+
46
+typedef struct {
47
+ QEMUTimer *timer;
48
+ int freq;
49
+
50
+ uint32_t reg_clock;
51
+ uint32_t reg_count;
52
+ uint32_t reg_value;
53
+ uint16_t reg_interval;
54
+ uint16_t reg_match[3];
55
+ uint32_t reg_intr;
56
+ uint32_t reg_intr_en;
57
+ uint32_t reg_event_ctrl;
58
+ uint32_t reg_event;
59
+
60
+ uint64_t cpu_time;
61
+ unsigned int cpu_time_valid;
62
+
63
+ qemu_irq irq;
64
+} CadenceTimerState;
65
+
66
+#define TYPE_CADENCE_TTC "cadence_ttc"
67
+OBJECT_DECLARE_SIMPLE_TYPE(CadenceTTCState, CADENCE_TTC)
68
+
69
+struct CadenceTTCState {
70
+ SysBusDevice parent_obj;
71
+
72
+ MemoryRegion iomem;
73
+ CadenceTimerState timer[3];
74
+};
75
+
76
+#endif
77
diff --git a/hw/timer/cadence_ttc.c b/hw/timer/cadence_ttc.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/hw/timer/cadence_ttc.c
80
+++ b/hw/timer/cadence_ttc.c
81
@@ -XXX,XX +XXX,XX @@
82
#include "qemu/timer.h"
83
#include "qom/object.h"
84
85
+#include "hw/timer/cadence_ttc.h"
86
+
87
#ifdef CADENCE_TTC_ERR_DEBUG
88
#define DB_PRINT(...) do { \
89
fprintf(stderr, ": %s: ", __func__); \
90
@@ -XXX,XX +XXX,XX @@
91
#define CLOCK_CTRL_PS_EN 0x00000001
92
#define CLOCK_CTRL_PS_V 0x0000001e
93
94
-typedef struct {
95
- QEMUTimer *timer;
96
- int freq;
97
-
98
- uint32_t reg_clock;
99
- uint32_t reg_count;
100
- uint32_t reg_value;
101
- uint16_t reg_interval;
102
- uint16_t reg_match[3];
103
- uint32_t reg_intr;
104
- uint32_t reg_intr_en;
105
- uint32_t reg_event_ctrl;
106
- uint32_t reg_event;
107
-
108
- uint64_t cpu_time;
109
- unsigned int cpu_time_valid;
110
-
111
- qemu_irq irq;
112
-} CadenceTimerState;
113
-
114
-#define TYPE_CADENCE_TTC "cadence_ttc"
115
-OBJECT_DECLARE_SIMPLE_TYPE(CadenceTTCState, CADENCE_TTC)
116
-
117
-struct CadenceTTCState {
118
- SysBusDevice parent_obj;
119
-
120
- MemoryRegion iomem;
121
- CadenceTimerState timer[3];
122
-};
123
-
124
static void cadence_timer_update(CadenceTimerState *s)
125
{
126
qemu_set_irq(s->irq, !!(s->reg_intr & s->reg_intr_en));
127
--
128
2.25.1
diff view generated by jsdifflib
1
From: Guenter Roeck <linux@roeck-us.net>
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
2
3
The Linux kernel's IMX code now uses vendor specific commands.
3
Connect the 4 TTC timers on the ZynqMP.
4
This results in endless warnings when booting the Linux kernel.
5
4
6
sdhci-esdhc-imx 2194000.usdhc: esdhc_wait_for_card_clock_gate_off:
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
7
    card clock still not gate off in 100us!.
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
8
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
9
Implement support for the vendor specific command implemented in IMX hardware
8
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
10
to be able to avoid this warning.
9
Message-id: 20220331222017.2914409-3-edgar.iglesias@gmail.com
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>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
11
---
18
hw/sd/sdhci-internal.h | 5 +++++
12
include/hw/arm/xlnx-zynqmp.h | 4 ++++
19
include/hw/sd/sdhci.h | 5 +++++
13
hw/arm/xlnx-zynqmp.c | 22 ++++++++++++++++++++++
20
hw/sd/sdhci.c | 18 +++++++++++++++++-
14
2 files changed, 26 insertions(+)
21
3 files changed, 27 insertions(+), 1 deletion(-)
22
15
23
diff --git a/hw/sd/sdhci-internal.h b/hw/sd/sdhci-internal.h
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
24
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
25
--- a/hw/sd/sdhci-internal.h
18
--- a/include/hw/arm/xlnx-zynqmp.h
26
+++ b/hw/sd/sdhci-internal.h
19
+++ b/include/hw/arm/xlnx-zynqmp.h
27
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@
28
#define SDHC_CMD_INHIBIT 0x00000001
21
#include "hw/or-irq.h"
29
#define SDHC_DATA_INHIBIT 0x00000002
22
#include "hw/misc/xlnx-zynqmp-apu-ctrl.h"
30
#define SDHC_DAT_LINE_ACTIVE 0x00000004
23
#include "hw/misc/xlnx-zynqmp-crf.h"
31
+#define SDHC_IMX_CLOCK_GATE_OFF 0x00000080
24
+#include "hw/timer/cadence_ttc.h"
32
#define SDHC_DOING_WRITE 0x00000100
25
33
#define SDHC_DOING_READ 0x00000200
26
#define TYPE_XLNX_ZYNQMP "xlnx-zynqmp"
34
#define SDHC_SPACE_AVAILABLE 0x00000400
27
OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
35
@@ -XXX,XX +XXX,XX @@ extern const VMStateDescription sdhci_vmstate;
28
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
36
29
#define XLNX_ZYNQMP_MAX_RAM_SIZE (XLNX_ZYNQMP_MAX_LOW_RAM_SIZE + \
37
30
XLNX_ZYNQMP_MAX_HIGH_RAM_SIZE)
38
#define ESDHC_MIX_CTRL 0x48
31
39
+
32
+#define XLNX_ZYNQMP_NUM_TTC 4
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
56
--- a/include/hw/sd/sdhci.h
57
+++ b/include/hw/sd/sdhci.h
58
@@ -XXX,XX +XXX,XX @@ typedef struct SDHCIState {
59
uint16_t acmd12errsts; /* Auto CMD12 error status register */
60
uint16_t hostctl2; /* Host Control 2 */
61
uint64_t admasysaddr; /* ADMA System Address Register */
62
+ uint16_t vendor_spec; /* Vendor specific register */
63
64
/* Read-only registers */
65
uint64_t capareg; /* Capabilities Register */
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
+
33
+
76
/*
34
/*
77
* Controller does not provide transfer-complete interrupt when not
35
* Unimplemented mmio regions needed to boot some images.
78
* busy.
36
*/
79
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
37
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
38
qemu_or_irq qspi_irq_orgate;
39
XlnxZynqMPAPUCtrl apu_ctrl;
40
XlnxZynqMPCRF crf;
41
+ CadenceTTCState ttc[XLNX_ZYNQMP_NUM_TTC];
42
43
char *boot_cpu;
44
ARMCPU *boot_cpu_ptr;
45
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
80
index XXXXXXX..XXXXXXX 100644
46
index XXXXXXX..XXXXXXX 100644
81
--- a/hw/sd/sdhci.c
47
--- a/hw/arm/xlnx-zynqmp.c
82
+++ b/hw/sd/sdhci.c
48
+++ b/hw/arm/xlnx-zynqmp.c
83
@@ -XXX,XX +XXX,XX @@ static uint64_t usdhc_read(void *opaque, hwaddr offset, unsigned size)
49
@@ -XXX,XX +XXX,XX @@
84
}
50
#define APU_ADDR 0xfd5c0000
85
break;
51
#define APU_IRQ 153
86
52
87
+ case ESDHC_VENDOR_SPEC:
53
+#define TTC0_ADDR 0xFF110000
88
+ ret = s->vendor_spec;
54
+#define TTC0_IRQ 36
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
+
55
+
104
case ESDHC_VENDOR_SPEC:
56
#define IPI_ADDR 0xFF300000
105
+ s->vendor_spec = value;
57
#define IPI_IRQ 64
106
+ switch (s->vendor) {
58
107
+ case SDHCI_VENDOR_IMX:
59
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_create_crf(XlnxZynqMPState *s, qemu_irq *gic)
108
+ if (value & ESDHC_IMX_FRC_SDCLK_ON) {
60
sysbus_connect_irq(sbd, 0, gic[CRF_IRQ]);
109
+ s->prnsts &= ~SDHC_IMX_CLOCK_GATE_OFF;
61
}
110
+ } else {
62
111
+ s->prnsts |= SDHC_IMX_CLOCK_GATE_OFF;
63
+static void xlnx_zynqmp_create_ttc(XlnxZynqMPState *s, qemu_irq *gic)
112
+ }
64
+{
113
+ break;
65
+ SysBusDevice *sbd;
114
+ default:
66
+ int i, irq;
115
+ break;
67
+
68
+ for (i = 0; i < XLNX_ZYNQMP_NUM_TTC; i++) {
69
+ object_initialize_child(OBJECT(s), "ttc[*]", &s->ttc[i],
70
+ TYPE_CADENCE_TTC);
71
+ sbd = SYS_BUS_DEVICE(&s->ttc[i]);
72
+
73
+ sysbus_realize(sbd, &error_fatal);
74
+ sysbus_mmio_map(sbd, 0, TTC0_ADDR + i * 0x10000);
75
+ for (irq = 0; irq < 3; irq++) {
76
+ sysbus_connect_irq(sbd, irq, gic[TTC0_IRQ + i * 3 + irq]);
116
+ }
77
+ }
117
break;
78
+ }
118
79
+}
119
case SDHC_HOSTCTL:
80
+
81
static void xlnx_zynqmp_create_unimp_mmio(XlnxZynqMPState *s)
82
{
83
static const struct UnimpInfo {
84
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
85
xlnx_zynqmp_create_efuse(s, gic_spi);
86
xlnx_zynqmp_create_apu_ctrl(s, gic_spi);
87
xlnx_zynqmp_create_crf(s, gic_spi);
88
+ xlnx_zynqmp_create_ttc(s, gic_spi);
89
xlnx_zynqmp_create_unimp_mmio(s);
90
91
for (i = 0; i < XLNX_ZYNQMP_NUM_GDMA_CH; i++) {
120
--
92
--
121
2.20.1
93
2.25.1
122
123
diff view generated by jsdifflib
New patch
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
1
2
3
Create an APU CPU Cluster. This is in preparation to add the RPU.
4
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
6
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
7
Message-id: 20220406174303.2022038-2-edgar.iglesias@xilinx.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
include/hw/arm/xlnx-versal.h | 2 ++
11
hw/arm/xlnx-versal.c | 9 ++++++++-
12
2 files changed, 10 insertions(+), 1 deletion(-)
13
14
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/arm/xlnx-versal.h
17
+++ b/include/hw/arm/xlnx-versal.h
18
@@ -XXX,XX +XXX,XX @@
19
20
#include "hw/sysbus.h"
21
#include "hw/arm/boot.h"
22
+#include "hw/cpu/cluster.h"
23
#include "hw/or-irq.h"
24
#include "hw/sd/sdhci.h"
25
#include "hw/intc/arm_gicv3.h"
26
@@ -XXX,XX +XXX,XX @@ struct Versal {
27
struct {
28
struct {
29
MemoryRegion mr;
30
+ CPUClusterState cluster;
31
ARMCPU cpu[XLNX_VERSAL_NR_ACPUS];
32
GICv3State gic;
33
} apu;
34
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/arm/xlnx-versal.c
37
+++ b/hw/arm/xlnx-versal.c
38
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_cpus(Versal *s)
39
{
40
int i;
41
42
+ object_initialize_child(OBJECT(s), "apu-cluster", &s->fpd.apu.cluster,
43
+ TYPE_CPU_CLUSTER);
44
+ qdev_prop_set_uint32(DEVICE(&s->fpd.apu.cluster), "cluster-id", 0);
45
+
46
for (i = 0; i < ARRAY_SIZE(s->fpd.apu.cpu); i++) {
47
Object *obj;
48
49
- object_initialize_child(OBJECT(s), "apu-cpu[*]", &s->fpd.apu.cpu[i],
50
+ object_initialize_child(OBJECT(&s->fpd.apu.cluster),
51
+ "apu-cpu[*]", &s->fpd.apu.cpu[i],
52
XLNX_VERSAL_ACPU_TYPE);
53
obj = OBJECT(&s->fpd.apu.cpu[i]);
54
if (i) {
55
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_cpus(Versal *s)
56
&error_abort);
57
qdev_realize(DEVICE(obj), NULL, &error_fatal);
58
}
59
+
60
+ qdev_realize(DEVICE(&s->fpd.apu.cluster), NULL, &error_fatal);
61
}
62
63
static void versal_create_apu_gic(Versal *s, qemu_irq *pic)
64
--
65
2.25.1
diff view generated by jsdifflib
1
From: Jean-Christophe Dubois <jcd@tribudubois.net>
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
2
3
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
3
Add the Cortex-R5Fs of the Versal RPU (Real-time Processing Unit)
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
subsystem.
5
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
6
[PMD: Fixed 32-bit format string using PRIx32/PRIx64]
6
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
7
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
8
Message-id: 20220406174303.2022038-3-edgar.iglesias@xilinx.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
---
10
hw/net/imx_fec.c | 106 +++++++++++++++++++-------------------------
11
include/hw/arm/xlnx-versal.h | 10 ++++++++++
11
hw/net/trace-events | 18 ++++++++
12
hw/arm/xlnx-versal-virt.c | 6 +++---
12
2 files changed, 63 insertions(+), 61 deletions(-)
13
hw/arm/xlnx-versal.c | 36 ++++++++++++++++++++++++++++++++++++
14
3 files changed, 49 insertions(+), 3 deletions(-)
13
15
14
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
16
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
15
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/net/imx_fec.c
18
--- a/include/hw/arm/xlnx-versal.h
17
+++ b/hw/net/imx_fec.c
19
+++ b/include/hw/arm/xlnx-versal.h
18
@@ -XXX,XX +XXX,XX @@
20
@@ -XXX,XX +XXX,XX @@
19
#include "qemu/module.h"
21
OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
20
#include "net/checksum.h"
22
21
#include "net/eth.h"
23
#define XLNX_VERSAL_NR_ACPUS 2
22
+#include "trace.h"
24
+#define XLNX_VERSAL_NR_RCPUS 2
23
25
#define XLNX_VERSAL_NR_UARTS 2
24
/* For crc32 */
26
#define XLNX_VERSAL_NR_GEMS 2
25
#include <zlib.h>
27
#define XLNX_VERSAL_NR_ADMAS 8
26
28
@@ -XXX,XX +XXX,XX @@ struct Versal {
27
-#ifndef DEBUG_IMX_FEC
29
VersalUsb2 usb;
28
-#define DEBUG_IMX_FEC 0
30
} iou;
29
-#endif
31
30
-
32
+ /* Real-time Processing Unit. */
31
-#define FEC_PRINTF(fmt, args...) \
33
+ struct {
32
- do { \
34
+ MemoryRegion mr;
33
- if (DEBUG_IMX_FEC) { \
35
+ MemoryRegion mr_ps_alias;
34
- fprintf(stderr, "[%s]%s: " fmt , TYPE_IMX_FEC, \
36
+
35
- __func__, ##args); \
37
+ CPUClusterState cluster;
36
- } \
38
+ ARMCPU cpu[XLNX_VERSAL_NR_RCPUS];
37
- } while (0)
39
+ } rpu;
38
-
40
+
39
-#ifndef DEBUG_IMX_PHY
41
struct {
40
-#define DEBUG_IMX_PHY 0
42
qemu_or_irq irq_orgate;
41
-#endif
43
XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM];
42
-
44
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
43
-#define PHY_PRINTF(fmt, args...) \
45
index XXXXXXX..XXXXXXX 100644
44
- do { \
46
--- a/hw/arm/xlnx-versal-virt.c
45
- if (DEBUG_IMX_PHY) { \
47
+++ b/hw/arm/xlnx-versal-virt.c
46
- fprintf(stderr, "[%s.phy]%s: " fmt , TYPE_IMX_FEC, \
48
@@ -XXX,XX +XXX,XX @@ static void versal_virt_machine_class_init(ObjectClass *oc, void *data)
47
- __func__, ##args); \
49
48
- } \
50
mc->desc = "Xilinx Versal Virtual development board";
49
- } while (0)
51
mc->init = versal_virt_init;
50
-
52
- mc->min_cpus = XLNX_VERSAL_NR_ACPUS;
51
#define IMX_MAX_DESC 1024
53
- mc->max_cpus = XLNX_VERSAL_NR_ACPUS;
52
54
- mc->default_cpus = XLNX_VERSAL_NR_ACPUS;
53
static const char *imx_default_reg_name(IMXFECState *s, uint32_t index)
55
+ mc->min_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
54
@@ -XXX,XX +XXX,XX @@ static void imx_eth_update(IMXFECState *s);
56
+ mc->max_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
55
* For now we don't handle any GPIO/interrupt line, so the OS will
57
+ mc->default_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
56
* have to poll for the PHY status.
58
mc->no_cdrom = true;
57
*/
59
mc->default_ram_id = "ddr";
58
-static void phy_update_irq(IMXFECState *s)
60
}
59
+static void imx_phy_update_irq(IMXFECState *s)
61
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/hw/arm/xlnx-versal.c
64
+++ b/hw/arm/xlnx-versal.c
65
@@ -XXX,XX +XXX,XX @@
66
#include "hw/sysbus.h"
67
68
#define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
69
+#define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
70
#define GEM_REVISION 0x40070106
71
72
#define VERSAL_NUM_PMC_APB_IRQS 3
73
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_gic(Versal *s, qemu_irq *pic)
74
}
75
}
76
77
+static void versal_create_rpu_cpus(Versal *s)
78
+{
79
+ int i;
80
+
81
+ object_initialize_child(OBJECT(s), "rpu-cluster", &s->lpd.rpu.cluster,
82
+ TYPE_CPU_CLUSTER);
83
+ qdev_prop_set_uint32(DEVICE(&s->lpd.rpu.cluster), "cluster-id", 1);
84
+
85
+ for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) {
86
+ Object *obj;
87
+
88
+ object_initialize_child(OBJECT(&s->lpd.rpu.cluster),
89
+ "rpu-cpu[*]", &s->lpd.rpu.cpu[i],
90
+ XLNX_VERSAL_RCPU_TYPE);
91
+ obj = OBJECT(&s->lpd.rpu.cpu[i]);
92
+ object_property_set_bool(obj, "start-powered-off", true,
93
+ &error_abort);
94
+
95
+ object_property_set_int(obj, "mp-affinity", 0x100 | i, &error_abort);
96
+ object_property_set_int(obj, "core-count", ARRAY_SIZE(s->lpd.rpu.cpu),
97
+ &error_abort);
98
+ object_property_set_link(obj, "memory", OBJECT(&s->lpd.rpu.mr),
99
+ &error_abort);
100
+ qdev_realize(DEVICE(obj), NULL, &error_fatal);
101
+ }
102
+
103
+ qdev_realize(DEVICE(&s->lpd.rpu.cluster), NULL, &error_fatal);
104
+}
105
+
106
static void versal_create_uarts(Versal *s, qemu_irq *pic)
60
{
107
{
61
imx_eth_update(s);
108
int i;
109
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
110
111
versal_create_apu_cpus(s);
112
versal_create_apu_gic(s, pic);
113
+ versal_create_rpu_cpus(s);
114
versal_create_uarts(s, pic);
115
versal_create_usbs(s, pic);
116
versal_create_gems(s, pic);
117
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
118
119
memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0);
120
memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0);
121
+ memory_region_add_subregion_overlap(&s->lpd.rpu.mr, 0,
122
+ &s->lpd.rpu.mr_ps_alias, 0);
62
}
123
}
63
124
64
-static void phy_update_link(IMXFECState *s)
125
static void versal_init(Object *obj)
65
+static void imx_phy_update_link(IMXFECState *s)
126
@@ -XXX,XX +XXX,XX @@ static void versal_init(Object *obj)
66
{
127
Versal *s = XLNX_VERSAL(obj);
67
/* Autonegotiation status mirrors link status. */
128
68
if (qemu_get_queue(s->nic)->link_down) {
129
memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX);
69
- PHY_PRINTF("link is down\n");
130
+ memory_region_init(&s->lpd.rpu.mr, obj, "mr-rpu", UINT64_MAX);
70
+ trace_imx_phy_update_link("down");
131
memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
71
s->phy_status &= ~0x0024;
132
+ memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s),
72
s->phy_int |= PHY_INT_DOWN;
133
+ "mr-rpu-ps-alias", &s->mr_ps, 0, UINT64_MAX);
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
}
134
}
83
135
84
static void imx_eth_set_link(NetClientState *nc)
136
static Property versal_properties[] = {
85
{
86
- phy_update_link(IMX_FEC(qemu_get_nic_opaque(nc)));
87
+ imx_phy_update_link(IMX_FEC(qemu_get_nic_opaque(nc)));
88
}
89
90
-static void phy_reset(IMXFECState *s)
91
+static void imx_phy_reset(IMXFECState *s)
92
{
93
+ trace_imx_phy_reset();
94
+
95
s->phy_status = 0x7809;
96
s->phy_control = 0x3000;
97
s->phy_advertise = 0x01e1;
98
s->phy_int_mask = 0;
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
+
159
+ trace_imx_fec_read_bd(addr, bd->flags, bd->length, bd->data);
160
}
161
162
static void imx_fec_write_bd(IMXFECBufDesc *bd, dma_addr_t addr)
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
+
168
+ trace_imx_enet_read_bd(addr, bd->flags, bd->length, bd->data,
169
+ bd->option, bd->status);
170
}
171
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
+
181
/* Run out of descriptors to transmit. */
182
- FEC_PRINTF("tx_bd ran out of descriptors to transmit\n");
183
+ trace_imx_eth_tx_bd_busy();
184
+
185
break;
186
}
187
len = bd.length;
188
@@ -XXX,XX +XXX,XX @@ static void imx_enet_do_tx(IMXFECState *s, uint32_t index)
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
325
--- a/hw/net/trace-events
326
+++ b/hw/net/trace-events
327
@@ -XXX,XX +XXX,XX @@ i82596_receive_packet(size_t sz) "len=%zu"
328
i82596_new_mac(const char *id_with_mac) "New MAC for: %s"
329
i82596_set_multicast(uint16_t count) "Added %d multicast entries"
330
i82596_channel_attention(void *s) "%p: Received CHANNEL ATTENTION"
331
+
332
+# imx_fec.c
333
+imx_phy_read(uint32_t val, int reg) "0x%04"PRIx32" <= reg[%d]"
334
+imx_phy_write(uint32_t val, int reg) "0x%04"PRIx32" => reg[%d]"
335
+imx_phy_update_link(const char *s) "%s"
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
--
137
--
350
2.20.1
138
2.25.1
351
352
diff view generated by jsdifflib
New patch
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
1
2
3
Add a model of the Xilinx Versal CRL.
4
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
6
Reviewed-by: Frederic Konrad <fkonrad@amd.com>
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
8
Message-id: 20220406174303.2022038-4-edgar.iglesias@xilinx.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
include/hw/misc/xlnx-versal-crl.h | 235 +++++++++++++++++
12
hw/misc/xlnx-versal-crl.c | 421 ++++++++++++++++++++++++++++++
13
hw/misc/meson.build | 1 +
14
3 files changed, 657 insertions(+)
15
create mode 100644 include/hw/misc/xlnx-versal-crl.h
16
create mode 100644 hw/misc/xlnx-versal-crl.c
17
18
diff --git a/include/hw/misc/xlnx-versal-crl.h b/include/hw/misc/xlnx-versal-crl.h
19
new file mode 100644
20
index XXXXXXX..XXXXXXX
21
--- /dev/null
22
+++ b/include/hw/misc/xlnx-versal-crl.h
23
@@ -XXX,XX +XXX,XX @@
24
+/*
25
+ * QEMU model of the Clock-Reset-LPD (CRL).
26
+ *
27
+ * Copyright (c) 2022 Xilinx Inc.
28
+ * SPDX-License-Identifier: GPL-2.0-or-later
29
+ *
30
+ * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
31
+ */
32
+#ifndef HW_MISC_XLNX_VERSAL_CRL_H
33
+#define HW_MISC_XLNX_VERSAL_CRL_H
34
+
35
+#include "hw/sysbus.h"
36
+#include "hw/register.h"
37
+#include "target/arm/cpu.h"
38
+
39
+#define TYPE_XLNX_VERSAL_CRL "xlnx,versal-crl"
40
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCRL, XLNX_VERSAL_CRL)
41
+
42
+REG32(ERR_CTRL, 0x0)
43
+ FIELD(ERR_CTRL, SLVERR_ENABLE, 0, 1)
44
+REG32(IR_STATUS, 0x4)
45
+ FIELD(IR_STATUS, ADDR_DECODE_ERR, 0, 1)
46
+REG32(IR_MASK, 0x8)
47
+ FIELD(IR_MASK, ADDR_DECODE_ERR, 0, 1)
48
+REG32(IR_ENABLE, 0xc)
49
+ FIELD(IR_ENABLE, ADDR_DECODE_ERR, 0, 1)
50
+REG32(IR_DISABLE, 0x10)
51
+ FIELD(IR_DISABLE, ADDR_DECODE_ERR, 0, 1)
52
+REG32(WPROT, 0x1c)
53
+ FIELD(WPROT, ACTIVE, 0, 1)
54
+REG32(PLL_CLK_OTHER_DMN, 0x20)
55
+ FIELD(PLL_CLK_OTHER_DMN, APLL_BYPASS, 0, 1)
56
+REG32(RPLL_CTRL, 0x40)
57
+ FIELD(RPLL_CTRL, POST_SRC, 24, 3)
58
+ FIELD(RPLL_CTRL, PRE_SRC, 20, 3)
59
+ FIELD(RPLL_CTRL, CLKOUTDIV, 16, 2)
60
+ FIELD(RPLL_CTRL, FBDIV, 8, 8)
61
+ FIELD(RPLL_CTRL, BYPASS, 3, 1)
62
+ FIELD(RPLL_CTRL, RESET, 0, 1)
63
+REG32(RPLL_CFG, 0x44)
64
+ FIELD(RPLL_CFG, LOCK_DLY, 25, 7)
65
+ FIELD(RPLL_CFG, LOCK_CNT, 13, 10)
66
+ FIELD(RPLL_CFG, LFHF, 10, 2)
67
+ FIELD(RPLL_CFG, CP, 5, 4)
68
+ FIELD(RPLL_CFG, RES, 0, 4)
69
+REG32(RPLL_FRAC_CFG, 0x48)
70
+ FIELD(RPLL_FRAC_CFG, ENABLED, 31, 1)
71
+ FIELD(RPLL_FRAC_CFG, SEED, 22, 3)
72
+ FIELD(RPLL_FRAC_CFG, ALGRTHM, 19, 1)
73
+ FIELD(RPLL_FRAC_CFG, ORDER, 18, 1)
74
+ FIELD(RPLL_FRAC_CFG, DATA, 0, 16)
75
+REG32(PLL_STATUS, 0x50)
76
+ FIELD(PLL_STATUS, RPLL_STABLE, 2, 1)
77
+ FIELD(PLL_STATUS, RPLL_LOCK, 0, 1)
78
+REG32(RPLL_TO_XPD_CTRL, 0x100)
79
+ FIELD(RPLL_TO_XPD_CTRL, CLKACT, 25, 1)
80
+ FIELD(RPLL_TO_XPD_CTRL, DIVISOR0, 8, 10)
81
+REG32(LPD_TOP_SWITCH_CTRL, 0x104)
82
+ FIELD(LPD_TOP_SWITCH_CTRL, CLKACT_ADMA, 26, 1)
83
+ FIELD(LPD_TOP_SWITCH_CTRL, CLKACT, 25, 1)
84
+ FIELD(LPD_TOP_SWITCH_CTRL, DIVISOR0, 8, 10)
85
+ FIELD(LPD_TOP_SWITCH_CTRL, SRCSEL, 0, 3)
86
+REG32(LPD_LSBUS_CTRL, 0x108)
87
+ FIELD(LPD_LSBUS_CTRL, CLKACT, 25, 1)
88
+ FIELD(LPD_LSBUS_CTRL, DIVISOR0, 8, 10)
89
+ FIELD(LPD_LSBUS_CTRL, SRCSEL, 0, 3)
90
+REG32(CPU_R5_CTRL, 0x10c)
91
+ FIELD(CPU_R5_CTRL, CLKACT_OCM2, 28, 1)
92
+ FIELD(CPU_R5_CTRL, CLKACT_OCM, 27, 1)
93
+ FIELD(CPU_R5_CTRL, CLKACT_CORE, 26, 1)
94
+ FIELD(CPU_R5_CTRL, CLKACT, 25, 1)
95
+ FIELD(CPU_R5_CTRL, DIVISOR0, 8, 10)
96
+ FIELD(CPU_R5_CTRL, SRCSEL, 0, 3)
97
+REG32(IOU_SWITCH_CTRL, 0x114)
98
+ FIELD(IOU_SWITCH_CTRL, CLKACT, 25, 1)
99
+ FIELD(IOU_SWITCH_CTRL, DIVISOR0, 8, 10)
100
+ FIELD(IOU_SWITCH_CTRL, SRCSEL, 0, 3)
101
+REG32(GEM0_REF_CTRL, 0x118)
102
+ FIELD(GEM0_REF_CTRL, CLKACT_RX, 27, 1)
103
+ FIELD(GEM0_REF_CTRL, CLKACT_TX, 26, 1)
104
+ FIELD(GEM0_REF_CTRL, CLKACT, 25, 1)
105
+ FIELD(GEM0_REF_CTRL, DIVISOR0, 8, 10)
106
+ FIELD(GEM0_REF_CTRL, SRCSEL, 0, 3)
107
+REG32(GEM1_REF_CTRL, 0x11c)
108
+ FIELD(GEM1_REF_CTRL, CLKACT_RX, 27, 1)
109
+ FIELD(GEM1_REF_CTRL, CLKACT_TX, 26, 1)
110
+ FIELD(GEM1_REF_CTRL, CLKACT, 25, 1)
111
+ FIELD(GEM1_REF_CTRL, DIVISOR0, 8, 10)
112
+ FIELD(GEM1_REF_CTRL, SRCSEL, 0, 3)
113
+REG32(GEM_TSU_REF_CTRL, 0x120)
114
+ FIELD(GEM_TSU_REF_CTRL, CLKACT, 25, 1)
115
+ FIELD(GEM_TSU_REF_CTRL, DIVISOR0, 8, 10)
116
+ FIELD(GEM_TSU_REF_CTRL, SRCSEL, 0, 3)
117
+REG32(USB0_BUS_REF_CTRL, 0x124)
118
+ FIELD(USB0_BUS_REF_CTRL, CLKACT, 25, 1)
119
+ FIELD(USB0_BUS_REF_CTRL, DIVISOR0, 8, 10)
120
+ FIELD(USB0_BUS_REF_CTRL, SRCSEL, 0, 3)
121
+REG32(UART0_REF_CTRL, 0x128)
122
+ FIELD(UART0_REF_CTRL, CLKACT, 25, 1)
123
+ FIELD(UART0_REF_CTRL, DIVISOR0, 8, 10)
124
+ FIELD(UART0_REF_CTRL, SRCSEL, 0, 3)
125
+REG32(UART1_REF_CTRL, 0x12c)
126
+ FIELD(UART1_REF_CTRL, CLKACT, 25, 1)
127
+ FIELD(UART1_REF_CTRL, DIVISOR0, 8, 10)
128
+ FIELD(UART1_REF_CTRL, SRCSEL, 0, 3)
129
+REG32(SPI0_REF_CTRL, 0x130)
130
+ FIELD(SPI0_REF_CTRL, CLKACT, 25, 1)
131
+ FIELD(SPI0_REF_CTRL, DIVISOR0, 8, 10)
132
+ FIELD(SPI0_REF_CTRL, SRCSEL, 0, 3)
133
+REG32(SPI1_REF_CTRL, 0x134)
134
+ FIELD(SPI1_REF_CTRL, CLKACT, 25, 1)
135
+ FIELD(SPI1_REF_CTRL, DIVISOR0, 8, 10)
136
+ FIELD(SPI1_REF_CTRL, SRCSEL, 0, 3)
137
+REG32(CAN0_REF_CTRL, 0x138)
138
+ FIELD(CAN0_REF_CTRL, CLKACT, 25, 1)
139
+ FIELD(CAN0_REF_CTRL, DIVISOR0, 8, 10)
140
+ FIELD(CAN0_REF_CTRL, SRCSEL, 0, 3)
141
+REG32(CAN1_REF_CTRL, 0x13c)
142
+ FIELD(CAN1_REF_CTRL, CLKACT, 25, 1)
143
+ FIELD(CAN1_REF_CTRL, DIVISOR0, 8, 10)
144
+ FIELD(CAN1_REF_CTRL, SRCSEL, 0, 3)
145
+REG32(I2C0_REF_CTRL, 0x140)
146
+ FIELD(I2C0_REF_CTRL, CLKACT, 25, 1)
147
+ FIELD(I2C0_REF_CTRL, DIVISOR0, 8, 10)
148
+ FIELD(I2C0_REF_CTRL, SRCSEL, 0, 3)
149
+REG32(I2C1_REF_CTRL, 0x144)
150
+ FIELD(I2C1_REF_CTRL, CLKACT, 25, 1)
151
+ FIELD(I2C1_REF_CTRL, DIVISOR0, 8, 10)
152
+ FIELD(I2C1_REF_CTRL, SRCSEL, 0, 3)
153
+REG32(DBG_LPD_CTRL, 0x148)
154
+ FIELD(DBG_LPD_CTRL, CLKACT, 25, 1)
155
+ FIELD(DBG_LPD_CTRL, DIVISOR0, 8, 10)
156
+ FIELD(DBG_LPD_CTRL, SRCSEL, 0, 3)
157
+REG32(TIMESTAMP_REF_CTRL, 0x14c)
158
+ FIELD(TIMESTAMP_REF_CTRL, CLKACT, 25, 1)
159
+ FIELD(TIMESTAMP_REF_CTRL, DIVISOR0, 8, 10)
160
+ FIELD(TIMESTAMP_REF_CTRL, SRCSEL, 0, 3)
161
+REG32(CRL_SAFETY_CHK, 0x150)
162
+REG32(PSM_REF_CTRL, 0x154)
163
+ FIELD(PSM_REF_CTRL, DIVISOR0, 8, 10)
164
+ FIELD(PSM_REF_CTRL, SRCSEL, 0, 3)
165
+REG32(DBG_TSTMP_CTRL, 0x158)
166
+ FIELD(DBG_TSTMP_CTRL, CLKACT, 25, 1)
167
+ FIELD(DBG_TSTMP_CTRL, DIVISOR0, 8, 10)
168
+ FIELD(DBG_TSTMP_CTRL, SRCSEL, 0, 3)
169
+REG32(CPM_TOPSW_REF_CTRL, 0x15c)
170
+ FIELD(CPM_TOPSW_REF_CTRL, CLKACT, 25, 1)
171
+ FIELD(CPM_TOPSW_REF_CTRL, DIVISOR0, 8, 10)
172
+ FIELD(CPM_TOPSW_REF_CTRL, SRCSEL, 0, 3)
173
+REG32(USB3_DUAL_REF_CTRL, 0x160)
174
+ FIELD(USB3_DUAL_REF_CTRL, CLKACT, 25, 1)
175
+ FIELD(USB3_DUAL_REF_CTRL, DIVISOR0, 8, 10)
176
+ FIELD(USB3_DUAL_REF_CTRL, SRCSEL, 0, 3)
177
+REG32(RST_CPU_R5, 0x300)
178
+ FIELD(RST_CPU_R5, RESET_PGE, 4, 1)
179
+ FIELD(RST_CPU_R5, RESET_AMBA, 2, 1)
180
+ FIELD(RST_CPU_R5, RESET_CPU1, 1, 1)
181
+ FIELD(RST_CPU_R5, RESET_CPU0, 0, 1)
182
+REG32(RST_ADMA, 0x304)
183
+ FIELD(RST_ADMA, RESET, 0, 1)
184
+REG32(RST_GEM0, 0x308)
185
+ FIELD(RST_GEM0, RESET, 0, 1)
186
+REG32(RST_GEM1, 0x30c)
187
+ FIELD(RST_GEM1, RESET, 0, 1)
188
+REG32(RST_SPARE, 0x310)
189
+ FIELD(RST_SPARE, RESET, 0, 1)
190
+REG32(RST_USB0, 0x314)
191
+ FIELD(RST_USB0, RESET, 0, 1)
192
+REG32(RST_UART0, 0x318)
193
+ FIELD(RST_UART0, RESET, 0, 1)
194
+REG32(RST_UART1, 0x31c)
195
+ FIELD(RST_UART1, RESET, 0, 1)
196
+REG32(RST_SPI0, 0x320)
197
+ FIELD(RST_SPI0, RESET, 0, 1)
198
+REG32(RST_SPI1, 0x324)
199
+ FIELD(RST_SPI1, RESET, 0, 1)
200
+REG32(RST_CAN0, 0x328)
201
+ FIELD(RST_CAN0, RESET, 0, 1)
202
+REG32(RST_CAN1, 0x32c)
203
+ FIELD(RST_CAN1, RESET, 0, 1)
204
+REG32(RST_I2C0, 0x330)
205
+ FIELD(RST_I2C0, RESET, 0, 1)
206
+REG32(RST_I2C1, 0x334)
207
+ FIELD(RST_I2C1, RESET, 0, 1)
208
+REG32(RST_DBG_LPD, 0x338)
209
+ FIELD(RST_DBG_LPD, RPU_DBG1_RESET, 5, 1)
210
+ FIELD(RST_DBG_LPD, RPU_DBG0_RESET, 4, 1)
211
+ FIELD(RST_DBG_LPD, RESET_HSDP, 1, 1)
212
+ FIELD(RST_DBG_LPD, RESET, 0, 1)
213
+REG32(RST_GPIO, 0x33c)
214
+ FIELD(RST_GPIO, RESET, 0, 1)
215
+REG32(RST_TTC, 0x344)
216
+ FIELD(RST_TTC, TTC3_RESET, 3, 1)
217
+ FIELD(RST_TTC, TTC2_RESET, 2, 1)
218
+ FIELD(RST_TTC, TTC1_RESET, 1, 1)
219
+ FIELD(RST_TTC, TTC0_RESET, 0, 1)
220
+REG32(RST_TIMESTAMP, 0x348)
221
+ FIELD(RST_TIMESTAMP, RESET, 0, 1)
222
+REG32(RST_SWDT, 0x34c)
223
+ FIELD(RST_SWDT, RESET, 0, 1)
224
+REG32(RST_OCM, 0x350)
225
+ FIELD(RST_OCM, RESET, 0, 1)
226
+REG32(RST_IPI, 0x354)
227
+ FIELD(RST_IPI, RESET, 0, 1)
228
+REG32(RST_SYSMON, 0x358)
229
+ FIELD(RST_SYSMON, SEQ_RST, 1, 1)
230
+ FIELD(RST_SYSMON, CFG_RST, 0, 1)
231
+REG32(RST_FPD, 0x360)
232
+ FIELD(RST_FPD, SRST, 1, 1)
233
+ FIELD(RST_FPD, POR, 0, 1)
234
+REG32(PSM_RST_MODE, 0x370)
235
+ FIELD(PSM_RST_MODE, WAKEUP, 2, 1)
236
+ FIELD(PSM_RST_MODE, RST_MODE, 0, 2)
237
+
238
+#define CRL_R_MAX (R_PSM_RST_MODE + 1)
239
+
240
+#define RPU_MAX_CPU 2
241
+
242
+struct XlnxVersalCRL {
243
+ SysBusDevice parent_obj;
244
+ qemu_irq irq;
245
+
246
+ struct {
247
+ ARMCPU *cpu_r5[RPU_MAX_CPU];
248
+ DeviceState *adma[8];
249
+ DeviceState *uart[2];
250
+ DeviceState *gem[2];
251
+ DeviceState *usb;
252
+ } cfg;
253
+
254
+ RegisterInfoArray *reg_array;
255
+ uint32_t regs[CRL_R_MAX];
256
+ RegisterInfo regs_info[CRL_R_MAX];
257
+};
258
+#endif
259
diff --git a/hw/misc/xlnx-versal-crl.c b/hw/misc/xlnx-versal-crl.c
260
new file mode 100644
261
index XXXXXXX..XXXXXXX
262
--- /dev/null
263
+++ b/hw/misc/xlnx-versal-crl.c
264
@@ -XXX,XX +XXX,XX @@
265
+/*
266
+ * QEMU model of the Clock-Reset-LPD (CRL).
267
+ *
268
+ * Copyright (c) 2022 Advanced Micro Devices, Inc.
269
+ * SPDX-License-Identifier: GPL-2.0-or-later
270
+ *
271
+ * Written by Edgar E. Iglesias <edgar.iglesias@amd.com>
272
+ */
273
+
274
+#include "qemu/osdep.h"
275
+#include "qapi/error.h"
276
+#include "qemu/log.h"
277
+#include "qemu/bitops.h"
278
+#include "migration/vmstate.h"
279
+#include "hw/qdev-properties.h"
280
+#include "hw/sysbus.h"
281
+#include "hw/irq.h"
282
+#include "hw/register.h"
283
+#include "hw/resettable.h"
284
+
285
+#include "target/arm/arm-powerctl.h"
286
+#include "hw/misc/xlnx-versal-crl.h"
287
+
288
+#ifndef XLNX_VERSAL_CRL_ERR_DEBUG
289
+#define XLNX_VERSAL_CRL_ERR_DEBUG 0
290
+#endif
291
+
292
+static void crl_update_irq(XlnxVersalCRL *s)
293
+{
294
+ bool pending = s->regs[R_IR_STATUS] & ~s->regs[R_IR_MASK];
295
+ qemu_set_irq(s->irq, pending);
296
+}
297
+
298
+static void crl_status_postw(RegisterInfo *reg, uint64_t val64)
299
+{
300
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
301
+ crl_update_irq(s);
302
+}
303
+
304
+static uint64_t crl_enable_prew(RegisterInfo *reg, uint64_t val64)
305
+{
306
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
307
+ uint32_t val = val64;
308
+
309
+ s->regs[R_IR_MASK] &= ~val;
310
+ crl_update_irq(s);
311
+ return 0;
312
+}
313
+
314
+static uint64_t crl_disable_prew(RegisterInfo *reg, uint64_t val64)
315
+{
316
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
317
+ uint32_t val = val64;
318
+
319
+ s->regs[R_IR_MASK] |= val;
320
+ crl_update_irq(s);
321
+ return 0;
322
+}
323
+
324
+static void crl_reset_dev(XlnxVersalCRL *s, DeviceState *dev,
325
+ bool rst_old, bool rst_new)
326
+{
327
+ device_cold_reset(dev);
328
+}
329
+
330
+static void crl_reset_cpu(XlnxVersalCRL *s, ARMCPU *armcpu,
331
+ bool rst_old, bool rst_new)
332
+{
333
+ if (rst_new) {
334
+ arm_set_cpu_off(armcpu->mp_affinity);
335
+ } else {
336
+ arm_set_cpu_on_and_reset(armcpu->mp_affinity);
337
+ }
338
+}
339
+
340
+#define REGFIELD_RESET(type, s, reg, f, new_val, dev) { \
341
+ bool old_f = ARRAY_FIELD_EX32((s)->regs, reg, f); \
342
+ bool new_f = FIELD_EX32(new_val, reg, f); \
343
+ \
344
+ /* Detect edges. */ \
345
+ if (dev && old_f != new_f) { \
346
+ crl_reset_ ## type(s, dev, old_f, new_f); \
347
+ } \
348
+}
349
+
350
+static uint64_t crl_rst_r5_prew(RegisterInfo *reg, uint64_t val64)
351
+{
352
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
353
+
354
+ REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU0, val64, s->cfg.cpu_r5[0]);
355
+ REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU1, val64, s->cfg.cpu_r5[1]);
356
+ return val64;
357
+}
358
+
359
+static uint64_t crl_rst_adma_prew(RegisterInfo *reg, uint64_t val64)
360
+{
361
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
362
+ int i;
363
+
364
+ /* A single register fans out to all ADMA reset inputs. */
365
+ for (i = 0; i < ARRAY_SIZE(s->cfg.adma); i++) {
366
+ REGFIELD_RESET(dev, s, RST_ADMA, RESET, val64, s->cfg.adma[i]);
367
+ }
368
+ return val64;
369
+}
370
+
371
+static uint64_t crl_rst_uart0_prew(RegisterInfo *reg, uint64_t val64)
372
+{
373
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
374
+
375
+ REGFIELD_RESET(dev, s, RST_UART0, RESET, val64, s->cfg.uart[0]);
376
+ return val64;
377
+}
378
+
379
+static uint64_t crl_rst_uart1_prew(RegisterInfo *reg, uint64_t val64)
380
+{
381
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
382
+
383
+ REGFIELD_RESET(dev, s, RST_UART1, RESET, val64, s->cfg.uart[1]);
384
+ return val64;
385
+}
386
+
387
+static uint64_t crl_rst_gem0_prew(RegisterInfo *reg, uint64_t val64)
388
+{
389
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
390
+
391
+ REGFIELD_RESET(dev, s, RST_GEM0, RESET, val64, s->cfg.gem[0]);
392
+ return val64;
393
+}
394
+
395
+static uint64_t crl_rst_gem1_prew(RegisterInfo *reg, uint64_t val64)
396
+{
397
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
398
+
399
+ REGFIELD_RESET(dev, s, RST_GEM1, RESET, val64, s->cfg.gem[1]);
400
+ return val64;
401
+}
402
+
403
+static uint64_t crl_rst_usb_prew(RegisterInfo *reg, uint64_t val64)
404
+{
405
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
406
+
407
+ REGFIELD_RESET(dev, s, RST_USB0, RESET, val64, s->cfg.usb);
408
+ return val64;
409
+}
410
+
411
+static const RegisterAccessInfo crl_regs_info[] = {
412
+ { .name = "ERR_CTRL", .addr = A_ERR_CTRL,
413
+ },{ .name = "IR_STATUS", .addr = A_IR_STATUS,
414
+ .w1c = 0x1,
415
+ .post_write = crl_status_postw,
416
+ },{ .name = "IR_MASK", .addr = A_IR_MASK,
417
+ .reset = 0x1,
418
+ .ro = 0x1,
419
+ },{ .name = "IR_ENABLE", .addr = A_IR_ENABLE,
420
+ .pre_write = crl_enable_prew,
421
+ },{ .name = "IR_DISABLE", .addr = A_IR_DISABLE,
422
+ .pre_write = crl_disable_prew,
423
+ },{ .name = "WPROT", .addr = A_WPROT,
424
+ },{ .name = "PLL_CLK_OTHER_DMN", .addr = A_PLL_CLK_OTHER_DMN,
425
+ .reset = 0x1,
426
+ .rsvd = 0xe,
427
+ },{ .name = "RPLL_CTRL", .addr = A_RPLL_CTRL,
428
+ .reset = 0x24809,
429
+ .rsvd = 0xf88c00f6,
430
+ },{ .name = "RPLL_CFG", .addr = A_RPLL_CFG,
431
+ .reset = 0x2000000,
432
+ .rsvd = 0x1801210,
433
+ },{ .name = "RPLL_FRAC_CFG", .addr = A_RPLL_FRAC_CFG,
434
+ .rsvd = 0x7e330000,
435
+ },{ .name = "PLL_STATUS", .addr = A_PLL_STATUS,
436
+ .reset = R_PLL_STATUS_RPLL_STABLE_MASK |
437
+ R_PLL_STATUS_RPLL_LOCK_MASK,
438
+ .rsvd = 0xfa,
439
+ .ro = 0x5,
440
+ },{ .name = "RPLL_TO_XPD_CTRL", .addr = A_RPLL_TO_XPD_CTRL,
441
+ .reset = 0x2000100,
442
+ .rsvd = 0xfdfc00ff,
443
+ },{ .name = "LPD_TOP_SWITCH_CTRL", .addr = A_LPD_TOP_SWITCH_CTRL,
444
+ .reset = 0x6000300,
445
+ .rsvd = 0xf9fc00f8,
446
+ },{ .name = "LPD_LSBUS_CTRL", .addr = A_LPD_LSBUS_CTRL,
447
+ .reset = 0x2000800,
448
+ .rsvd = 0xfdfc00f8,
449
+ },{ .name = "CPU_R5_CTRL", .addr = A_CPU_R5_CTRL,
450
+ .reset = 0xe000300,
451
+ .rsvd = 0xe1fc00f8,
452
+ },{ .name = "IOU_SWITCH_CTRL", .addr = A_IOU_SWITCH_CTRL,
453
+ .reset = 0x2000500,
454
+ .rsvd = 0xfdfc00f8,
455
+ },{ .name = "GEM0_REF_CTRL", .addr = A_GEM0_REF_CTRL,
456
+ .reset = 0xe000a00,
457
+ .rsvd = 0xf1fc00f8,
458
+ },{ .name = "GEM1_REF_CTRL", .addr = A_GEM1_REF_CTRL,
459
+ .reset = 0xe000a00,
460
+ .rsvd = 0xf1fc00f8,
461
+ },{ .name = "GEM_TSU_REF_CTRL", .addr = A_GEM_TSU_REF_CTRL,
462
+ .reset = 0x300,
463
+ .rsvd = 0xfdfc00f8,
464
+ },{ .name = "USB0_BUS_REF_CTRL", .addr = A_USB0_BUS_REF_CTRL,
465
+ .reset = 0x2001900,
466
+ .rsvd = 0xfdfc00f8,
467
+ },{ .name = "UART0_REF_CTRL", .addr = A_UART0_REF_CTRL,
468
+ .reset = 0xc00,
469
+ .rsvd = 0xfdfc00f8,
470
+ },{ .name = "UART1_REF_CTRL", .addr = A_UART1_REF_CTRL,
471
+ .reset = 0xc00,
472
+ .rsvd = 0xfdfc00f8,
473
+ },{ .name = "SPI0_REF_CTRL", .addr = A_SPI0_REF_CTRL,
474
+ .reset = 0x600,
475
+ .rsvd = 0xfdfc00f8,
476
+ },{ .name = "SPI1_REF_CTRL", .addr = A_SPI1_REF_CTRL,
477
+ .reset = 0x600,
478
+ .rsvd = 0xfdfc00f8,
479
+ },{ .name = "CAN0_REF_CTRL", .addr = A_CAN0_REF_CTRL,
480
+ .reset = 0xc00,
481
+ .rsvd = 0xfdfc00f8,
482
+ },{ .name = "CAN1_REF_CTRL", .addr = A_CAN1_REF_CTRL,
483
+ .reset = 0xc00,
484
+ .rsvd = 0xfdfc00f8,
485
+ },{ .name = "I2C0_REF_CTRL", .addr = A_I2C0_REF_CTRL,
486
+ .reset = 0xc00,
487
+ .rsvd = 0xfdfc00f8,
488
+ },{ .name = "I2C1_REF_CTRL", .addr = A_I2C1_REF_CTRL,
489
+ .reset = 0xc00,
490
+ .rsvd = 0xfdfc00f8,
491
+ },{ .name = "DBG_LPD_CTRL", .addr = A_DBG_LPD_CTRL,
492
+ .reset = 0x300,
493
+ .rsvd = 0xfdfc00f8,
494
+ },{ .name = "TIMESTAMP_REF_CTRL", .addr = A_TIMESTAMP_REF_CTRL,
495
+ .reset = 0x2000c00,
496
+ .rsvd = 0xfdfc00f8,
497
+ },{ .name = "CRL_SAFETY_CHK", .addr = A_CRL_SAFETY_CHK,
498
+ },{ .name = "PSM_REF_CTRL", .addr = A_PSM_REF_CTRL,
499
+ .reset = 0xf04,
500
+ .rsvd = 0xfffc00f8,
501
+ },{ .name = "DBG_TSTMP_CTRL", .addr = A_DBG_TSTMP_CTRL,
502
+ .reset = 0x300,
503
+ .rsvd = 0xfdfc00f8,
504
+ },{ .name = "CPM_TOPSW_REF_CTRL", .addr = A_CPM_TOPSW_REF_CTRL,
505
+ .reset = 0x300,
506
+ .rsvd = 0xfdfc00f8,
507
+ },{ .name = "USB3_DUAL_REF_CTRL", .addr = A_USB3_DUAL_REF_CTRL,
508
+ .reset = 0x3c00,
509
+ .rsvd = 0xfdfc00f8,
510
+ },{ .name = "RST_CPU_R5", .addr = A_RST_CPU_R5,
511
+ .reset = 0x17,
512
+ .rsvd = 0x8,
513
+ .pre_write = crl_rst_r5_prew,
514
+ },{ .name = "RST_ADMA", .addr = A_RST_ADMA,
515
+ .reset = 0x1,
516
+ .pre_write = crl_rst_adma_prew,
517
+ },{ .name = "RST_GEM0", .addr = A_RST_GEM0,
518
+ .reset = 0x1,
519
+ .pre_write = crl_rst_gem0_prew,
520
+ },{ .name = "RST_GEM1", .addr = A_RST_GEM1,
521
+ .reset = 0x1,
522
+ .pre_write = crl_rst_gem1_prew,
523
+ },{ .name = "RST_SPARE", .addr = A_RST_SPARE,
524
+ .reset = 0x1,
525
+ },{ .name = "RST_USB0", .addr = A_RST_USB0,
526
+ .reset = 0x1,
527
+ .pre_write = crl_rst_usb_prew,
528
+ },{ .name = "RST_UART0", .addr = A_RST_UART0,
529
+ .reset = 0x1,
530
+ .pre_write = crl_rst_uart0_prew,
531
+ },{ .name = "RST_UART1", .addr = A_RST_UART1,
532
+ .reset = 0x1,
533
+ .pre_write = crl_rst_uart1_prew,
534
+ },{ .name = "RST_SPI0", .addr = A_RST_SPI0,
535
+ .reset = 0x1,
536
+ },{ .name = "RST_SPI1", .addr = A_RST_SPI1,
537
+ .reset = 0x1,
538
+ },{ .name = "RST_CAN0", .addr = A_RST_CAN0,
539
+ .reset = 0x1,
540
+ },{ .name = "RST_CAN1", .addr = A_RST_CAN1,
541
+ .reset = 0x1,
542
+ },{ .name = "RST_I2C0", .addr = A_RST_I2C0,
543
+ .reset = 0x1,
544
+ },{ .name = "RST_I2C1", .addr = A_RST_I2C1,
545
+ .reset = 0x1,
546
+ },{ .name = "RST_DBG_LPD", .addr = A_RST_DBG_LPD,
547
+ .reset = 0x33,
548
+ .rsvd = 0xcc,
549
+ },{ .name = "RST_GPIO", .addr = A_RST_GPIO,
550
+ .reset = 0x1,
551
+ },{ .name = "RST_TTC", .addr = A_RST_TTC,
552
+ .reset = 0xf,
553
+ },{ .name = "RST_TIMESTAMP", .addr = A_RST_TIMESTAMP,
554
+ .reset = 0x1,
555
+ },{ .name = "RST_SWDT", .addr = A_RST_SWDT,
556
+ .reset = 0x1,
557
+ },{ .name = "RST_OCM", .addr = A_RST_OCM,
558
+ },{ .name = "RST_IPI", .addr = A_RST_IPI,
559
+ },{ .name = "RST_FPD", .addr = A_RST_FPD,
560
+ .reset = 0x3,
561
+ },{ .name = "PSM_RST_MODE", .addr = A_PSM_RST_MODE,
562
+ .reset = 0x1,
563
+ .rsvd = 0xf8,
564
+ }
565
+};
566
+
567
+static void crl_reset_enter(Object *obj, ResetType type)
568
+{
569
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
570
+ unsigned int i;
571
+
572
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
573
+ register_reset(&s->regs_info[i]);
574
+ }
575
+}
576
+
577
+static void crl_reset_hold(Object *obj)
578
+{
579
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
580
+
581
+ crl_update_irq(s);
582
+}
583
+
584
+static const MemoryRegionOps crl_ops = {
585
+ .read = register_read_memory,
586
+ .write = register_write_memory,
587
+ .endianness = DEVICE_LITTLE_ENDIAN,
588
+ .valid = {
589
+ .min_access_size = 4,
590
+ .max_access_size = 4,
591
+ },
592
+};
593
+
594
+static void crl_init(Object *obj)
595
+{
596
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
597
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
598
+ int i;
599
+
600
+ s->reg_array =
601
+ register_init_block32(DEVICE(obj), crl_regs_info,
602
+ ARRAY_SIZE(crl_regs_info),
603
+ s->regs_info, s->regs,
604
+ &crl_ops,
605
+ XLNX_VERSAL_CRL_ERR_DEBUG,
606
+ CRL_R_MAX * 4);
607
+ sysbus_init_mmio(sbd, &s->reg_array->mem);
608
+ sysbus_init_irq(sbd, &s->irq);
609
+
610
+ for (i = 0; i < ARRAY_SIZE(s->cfg.cpu_r5); ++i) {
611
+ object_property_add_link(obj, "cpu_r5[*]", TYPE_ARM_CPU,
612
+ (Object **)&s->cfg.cpu_r5[i],
613
+ qdev_prop_allow_set_link_before_realize,
614
+ OBJ_PROP_LINK_STRONG);
615
+ }
616
+
617
+ for (i = 0; i < ARRAY_SIZE(s->cfg.adma); ++i) {
618
+ object_property_add_link(obj, "adma[*]", TYPE_DEVICE,
619
+ (Object **)&s->cfg.adma[i],
620
+ qdev_prop_allow_set_link_before_realize,
621
+ OBJ_PROP_LINK_STRONG);
622
+ }
623
+
624
+ for (i = 0; i < ARRAY_SIZE(s->cfg.uart); ++i) {
625
+ object_property_add_link(obj, "uart[*]", TYPE_DEVICE,
626
+ (Object **)&s->cfg.uart[i],
627
+ qdev_prop_allow_set_link_before_realize,
628
+ OBJ_PROP_LINK_STRONG);
629
+ }
630
+
631
+ for (i = 0; i < ARRAY_SIZE(s->cfg.gem); ++i) {
632
+ object_property_add_link(obj, "gem[*]", TYPE_DEVICE,
633
+ (Object **)&s->cfg.gem[i],
634
+ qdev_prop_allow_set_link_before_realize,
635
+ OBJ_PROP_LINK_STRONG);
636
+ }
637
+
638
+ object_property_add_link(obj, "usb", TYPE_DEVICE,
639
+ (Object **)&s->cfg.gem[i],
640
+ qdev_prop_allow_set_link_before_realize,
641
+ OBJ_PROP_LINK_STRONG);
642
+}
643
+
644
+static void crl_finalize(Object *obj)
645
+{
646
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
647
+ register_finalize_block(s->reg_array);
648
+}
649
+
650
+static const VMStateDescription vmstate_crl = {
651
+ .name = TYPE_XLNX_VERSAL_CRL,
652
+ .version_id = 1,
653
+ .minimum_version_id = 1,
654
+ .fields = (VMStateField[]) {
655
+ VMSTATE_UINT32_ARRAY(regs, XlnxVersalCRL, CRL_R_MAX),
656
+ VMSTATE_END_OF_LIST(),
657
+ }
658
+};
659
+
660
+static void crl_class_init(ObjectClass *klass, void *data)
661
+{
662
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
663
+ DeviceClass *dc = DEVICE_CLASS(klass);
664
+
665
+ dc->vmsd = &vmstate_crl;
666
+
667
+ rc->phases.enter = crl_reset_enter;
668
+ rc->phases.hold = crl_reset_hold;
669
+}
670
+
671
+static const TypeInfo crl_info = {
672
+ .name = TYPE_XLNX_VERSAL_CRL,
673
+ .parent = TYPE_SYS_BUS_DEVICE,
674
+ .instance_size = sizeof(XlnxVersalCRL),
675
+ .class_init = crl_class_init,
676
+ .instance_init = crl_init,
677
+ .instance_finalize = crl_finalize,
678
+};
679
+
680
+static void crl_register_types(void)
681
+{
682
+ type_register_static(&crl_info);
683
+}
684
+
685
+type_init(crl_register_types)
686
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
687
index XXXXXXX..XXXXXXX 100644
688
--- a/hw/misc/meson.build
689
+++ b/hw/misc/meson.build
690
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c'))
691
softmmu_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c'))
692
specific_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp-crf.c'))
693
specific_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp-apu-ctrl.c'))
694
+specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-crl.c'))
695
softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
696
'xlnx-versal-xramc.c',
697
'xlnx-versal-pmc-iou-slcr.c',
698
--
699
2.25.1
diff view generated by jsdifflib
1
Convert the VQRDMLAH and VQRDMLSH insns in the 2-reg-scalar
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
group to decodetree.
3
2
3
Connect the CRL (Clock Reset LPD) to the Versal SoC.
4
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
6
Reviewed-by: Frederic Konrad <fkonrad@amd.com>
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
8
Message-id: 20220406174303.2022038-5-edgar.iglesias@xilinx.com
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
---
10
---
7
target/arm/neon-dp.decode | 3 ++
11
include/hw/arm/xlnx-versal.h | 4 +++
8
target/arm/translate-neon.inc.c | 74 +++++++++++++++++++++++++++++++++
12
hw/arm/xlnx-versal.c | 54 ++++++++++++++++++++++++++++++++++--
9
target/arm/translate.c | 38 +----------------
13
2 files changed, 56 insertions(+), 2 deletions(-)
10
3 files changed, 79 insertions(+), 36 deletions(-)
11
14
12
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
15
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
13
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/neon-dp.decode
17
--- a/include/hw/arm/xlnx-versal.h
15
+++ b/target/arm/neon-dp.decode
18
+++ b/include/hw/arm/xlnx-versal.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 @@
17
20
#include "hw/nvram/xlnx-versal-efuse.h"
18
VQDMULH_2sc 1111 001 . 1 . .. .... .... 1100 . 1 . 0 .... @2scalar
21
#include "hw/ssi/xlnx-versal-ospi.h"
19
VQRDMULH_2sc 1111 001 . 1 . .. .... .... 1101 . 1 . 0 .... @2scalar
22
#include "hw/dma/xlnx_csu_dma.h"
23
+#include "hw/misc/xlnx-versal-crl.h"
24
#include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
25
26
#define TYPE_XLNX_VERSAL "xlnx-versal"
27
@@ -XXX,XX +XXX,XX @@ struct Versal {
28
qemu_or_irq irq_orgate;
29
XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM];
30
} xram;
20
+
31
+
21
+ VQRDMLAH_2sc 1111 001 . 1 . .. .... .... 1110 . 1 . 0 .... @2scalar
32
+ XlnxVersalCRL crl;
22
+ VQRDMLSH_2sc 1111 001 . 1 . .. .... .... 1111 . 1 . 0 .... @2scalar
33
} lpd;
23
]
34
35
/* The Platform Management Controller subsystem. */
36
@@ -XXX,XX +XXX,XX @@ struct Versal {
37
#define VERSAL_TIMER_NS_EL1_IRQ 14
38
#define VERSAL_TIMER_NS_EL2_IRQ 10
39
40
+#define VERSAL_CRL_IRQ 10
41
#define VERSAL_UART0_IRQ_0 18
42
#define VERSAL_UART1_IRQ_0 19
43
#define VERSAL_USB0_IRQ_0 22
44
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/arm/xlnx-versal.c
47
+++ b/hw/arm/xlnx-versal.c
48
@@ -XXX,XX +XXX,XX @@ static void versal_create_ospi(Versal *s, qemu_irq *pic)
49
qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]);
24
}
50
}
25
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
51
26
index XXXXXXX..XXXXXXX 100644
52
+static void versal_create_crl(Versal *s, qemu_irq *pic)
27
--- a/target/arm/translate-neon.inc.c
53
+{
28
+++ b/target/arm/translate-neon.inc.c
54
+ SysBusDevice *sbd;
29
@@ -XXX,XX +XXX,XX @@ static bool trans_VQRDMULH_2sc(DisasContext *s, arg_2scalar *a)
55
+ int i;
30
31
return do_2scalar(s, a, opfn[a->size], NULL);
32
}
33
+
56
+
34
+static bool do_vqrdmlah_2sc(DisasContext *s, arg_2scalar *a,
57
+ object_initialize_child(OBJECT(s), "crl", &s->lpd.crl,
35
+ NeonGenThreeOpEnvFn *opfn)
58
+ TYPE_XLNX_VERSAL_CRL);
36
+{
59
+ sbd = SYS_BUS_DEVICE(&s->lpd.crl);
37
+ /*
38
+ * VQRDMLAH/VQRDMLSH: this is like do_2scalar, but the opfn
39
+ * performs a kind of fused op-then-accumulate using a helper
40
+ * function that takes all of rd, rn and the scalar at once.
41
+ */
42
+ TCGv_i32 scalar;
43
+ int pass;
44
+
60
+
45
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
61
+ for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) {
46
+ return false;
62
+ g_autofree gchar *name = g_strdup_printf("cpu_r5[%d]", i);
63
+
64
+ object_property_set_link(OBJECT(&s->lpd.crl),
65
+ name, OBJECT(&s->lpd.rpu.cpu[i]),
66
+ &error_abort);
47
+ }
67
+ }
48
+
68
+
49
+ if (!dc_isar_feature(aa32_rdm, s)) {
69
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.gem); i++) {
50
+ return false;
70
+ g_autofree gchar *name = g_strdup_printf("gem[%d]", i);
71
+
72
+ object_property_set_link(OBJECT(&s->lpd.crl),
73
+ name, OBJECT(&s->lpd.iou.gem[i]),
74
+ &error_abort);
51
+ }
75
+ }
52
+
76
+
53
+ /* UNDEF accesses to D16-D31 if they don't exist. */
77
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.adma); i++) {
54
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
78
+ g_autofree gchar *name = g_strdup_printf("adma[%d]", i);
55
+ ((a->vd | a->vn | a->vm) & 0x10)) {
79
+
56
+ return false;
80
+ object_property_set_link(OBJECT(&s->lpd.crl),
81
+ name, OBJECT(&s->lpd.iou.adma[i]),
82
+ &error_abort);
57
+ }
83
+ }
58
+
84
+
59
+ if (!opfn) {
85
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.uart); i++) {
60
+ /* Bad size (including size == 3, which is a different insn group) */
86
+ g_autofree gchar *name = g_strdup_printf("uart[%d]", i);
61
+ return false;
87
+
88
+ object_property_set_link(OBJECT(&s->lpd.crl),
89
+ name, OBJECT(&s->lpd.iou.uart[i]),
90
+ &error_abort);
62
+ }
91
+ }
63
+
92
+
64
+ if (a->q && ((a->vd | a->vn) & 1)) {
93
+ object_property_set_link(OBJECT(&s->lpd.crl),
65
+ return false;
94
+ "usb", OBJECT(&s->lpd.iou.usb),
66
+ }
95
+ &error_abort);
67
+
96
+
68
+ if (!vfp_access_check(s)) {
97
+ sysbus_realize(sbd, &error_fatal);
69
+ return true;
98
+ memory_region_add_subregion(&s->mr_ps, MM_CRL,
70
+ }
99
+ sysbus_mmio_get_region(sbd, 0));
71
+
100
+ sysbus_connect_irq(sbd, 0, pic[VERSAL_CRL_IRQ]);
72
+ scalar = neon_get_scalar(a->size, a->vm);
73
+
74
+ for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
75
+ TCGv_i32 rn = neon_load_reg(a->vn, pass);
76
+ TCGv_i32 rd = neon_load_reg(a->vd, pass);
77
+ opfn(rd, cpu_env, rn, scalar, rd);
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;
84
+}
101
+}
85
+
102
+
86
+static bool trans_VQRDMLAH_2sc(DisasContext *s, arg_2scalar *a)
103
/* This takes the board allocated linear DDR memory and creates aliases
87
+{
104
* for each split DDR range/aperture on the Versal address map.
88
+ static NeonGenThreeOpEnvFn *opfn[] = {
105
*/
89
+ NULL,
106
@@ -XXX,XX +XXX,XX @@ static void versal_unimp(Versal *s)
90
+ gen_helper_neon_qrdmlah_s16,
107
91
+ gen_helper_neon_qrdmlah_s32,
108
versal_unimp_area(s, "psm", &s->mr_ps,
92
+ NULL,
109
MM_PSM_START, MM_PSM_END - MM_PSM_START);
93
+ };
110
- versal_unimp_area(s, "crl", &s->mr_ps,
94
+ return do_vqrdmlah_2sc(s, a, opfn[a->size]);
111
- MM_CRL, MM_CRL_SIZE);
95
+}
112
versal_unimp_area(s, "crf", &s->mr_ps,
96
+
113
MM_FPD_CRF, MM_FPD_CRF_SIZE);
97
+static bool trans_VQRDMLSH_2sc(DisasContext *s, arg_2scalar *a)
114
versal_unimp_area(s, "apu", &s->mr_ps,
98
+{
115
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
99
+ static NeonGenThreeOpEnvFn *opfn[] = {
116
versal_create_efuse(s, pic);
100
+ NULL,
117
versal_create_pmc_iou_slcr(s, pic);
101
+ gen_helper_neon_qrdmlsh_s16,
118
versal_create_ospi(s, pic);
102
+ gen_helper_neon_qrdmlsh_s32,
119
+ versal_create_crl(s, pic);
103
+ NULL,
120
versal_map_ddr(s);
104
+ };
121
versal_unimp(s);
105
+ return do_vqrdmlah_2sc(s, a, opfn[a->size]);
122
106
+}
107
diff --git a/target/arm/translate.c b/target/arm/translate.c
108
index XXXXXXX..XXXXXXX 100644
109
--- a/target/arm/translate.c
110
+++ b/target/arm/translate.c
111
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
112
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
--
123
--
164
2.20.1
124
2.25.1
165
166
diff view generated by jsdifflib
1
From: fangying <fangying1@huawei.com>
1
The Exynos4210 SoC device currently uses a custom device
2
"exynos4210.irq_gate" to model the OR gate that feeds each CPU's IRQ
3
line. We have a standard TYPE_OR_IRQ device for this now, so use
4
that instead.
2
5
3
Virtual time adjustment was implemented for virt-5.0 machine type,
6
(This is a migration compatibility break, but that is OK for this
4
but the cpu property was enabled only for host-passthrough and max
7
machine type.)
5
cpu model. Let's add it for any KVM arm cpu which has the generic
6
timer feature enabled.
7
8
8
Signed-off-by: Ying Fang <fangying1@huawei.com>
9
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>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-2-peter.maydell@linaro.org
14
---
12
---
15
target/arm/cpu.c | 6 ++++--
13
include/hw/arm/exynos4210.h | 1 +
16
target/arm/cpu64.c | 1 -
14
hw/arm/exynos4210.c | 31 ++++++++++++++++---------------
17
target/arm/kvm.c | 21 +++++++++++----------
15
2 files changed, 17 insertions(+), 15 deletions(-)
18
3 files changed, 15 insertions(+), 13 deletions(-)
19
16
20
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
21
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/cpu.c
19
--- a/include/hw/arm/exynos4210.h
23
+++ b/target/arm/cpu.c
20
+++ b/include/hw/arm/exynos4210.h
24
@@ -XXX,XX +XXX,XX @@ void arm_cpu_post_init(Object *obj)
21
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
25
if (arm_feature(&cpu->env, ARM_FEATURE_GENERIC_TIMER)) {
22
MemoryRegion bootreg_mem;
26
qdev_property_add_static(DEVICE(cpu), &arm_cpu_gt_cntfrq_property);
23
I2CBus *i2c_if[EXYNOS4210_I2C_NUMBER];
24
qemu_or_irq pl330_irq_orgate[EXYNOS4210_NUM_DMA];
25
+ qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
26
};
27
28
#define TYPE_EXYNOS4210_SOC "exynos4210"
29
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/exynos4210.c
32
+++ b/hw/arm/exynos4210.c
33
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
34
{
35
Exynos4210State *s = EXYNOS4210_SOC(socdev);
36
MemoryRegion *system_mem = get_system_memory();
37
- qemu_irq gate_irq[EXYNOS4210_NCPUS][EXYNOS4210_IRQ_GATE_NINPUTS];
38
SysBusDevice *busdev;
39
DeviceState *dev, *uart[4], *pl330[3];
40
int i, n;
41
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
42
43
/* IRQ Gate */
44
for (i = 0; i < EXYNOS4210_NCPUS; i++) {
45
- dev = qdev_new("exynos4210.irq_gate");
46
- qdev_prop_set_uint32(dev, "n_in", EXYNOS4210_IRQ_GATE_NINPUTS);
47
- sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
48
- /* Get IRQ Gate input in gate_irq */
49
- for (n = 0; n < EXYNOS4210_IRQ_GATE_NINPUTS; n++) {
50
- gate_irq[i][n] = qdev_get_gpio_in(dev, n);
51
- }
52
- busdev = SYS_BUS_DEVICE(dev);
53
-
54
- /* Connect IRQ Gate output to CPU's IRQ line */
55
- sysbus_connect_irq(busdev, 0,
56
- qdev_get_gpio_in(DEVICE(s->cpu[i]), ARM_CPU_IRQ));
57
+ DeviceState *orgate = DEVICE(&s->cpu_irq_orgate[i]);
58
+ object_property_set_int(OBJECT(orgate), "num-lines",
59
+ EXYNOS4210_IRQ_GATE_NINPUTS,
60
+ &error_abort);
61
+ qdev_realize(orgate, NULL, &error_abort);
62
+ qdev_connect_gpio_out(orgate, 0,
63
+ qdev_get_gpio_in(DEVICE(s->cpu[i]), ARM_CPU_IRQ));
64
}
65
66
/* Private memory region and Internal GIC */
67
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
68
sysbus_realize_and_unref(busdev, &error_fatal);
69
sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
70
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
71
- sysbus_connect_irq(busdev, n, gate_irq[n][0]);
72
+ sysbus_connect_irq(busdev, n,
73
+ qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 0));
74
}
75
for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
76
s->irqs.int_gic_irq[n] = qdev_get_gpio_in(dev, n);
77
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
78
/* Map Distributer interface */
79
sysbus_mmio_map(busdev, 1, EXYNOS4210_EXT_GIC_DIST_BASE_ADDR);
80
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
81
- sysbus_connect_irq(busdev, n, gate_irq[n][1]);
82
+ sysbus_connect_irq(busdev, n,
83
+ qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 1));
84
}
85
for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
86
s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(dev, n);
87
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
88
object_initialize_child(obj, name, orgate, TYPE_OR_IRQ);
89
g_free(name);
27
}
90
}
28
+
91
+
29
+ if (kvm_enabled()) {
92
+ for (i = 0; i < ARRAY_SIZE(s->cpu_irq_orgate); i++) {
30
+ kvm_arm_add_vcpu_properties(obj);
93
+ g_autofree char *name = g_strdup_printf("cpu-irq-orgate%d", i);
94
+ object_initialize_child(obj, name, &s->cpu_irq_orgate[i], TYPE_OR_IRQ);
31
+ }
95
+ }
32
}
96
}
33
97
34
static void arm_cpu_finalizefn(Object *obj)
98
static void exynos4210_class_init(ObjectClass *klass, void *data)
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
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/cpu64.c
54
+++ b/target/arm/cpu64.c
55
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
56
57
if (kvm_enabled()) {
58
kvm_arm_set_cpu_features_from_host(cpu);
59
- kvm_arm_add_vcpu_properties(obj);
60
} else {
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);
75
+ CPUARMState *env = &cpu->env;
76
77
- ARM_CPU(obj)->kvm_adjvtime = true;
78
- object_property_add_bool(obj, "kvm-no-adjvtime", kvm_no_adjvtime_get,
79
- kvm_no_adjvtime_set);
80
- object_property_set_description(obj, "kvm-no-adjvtime",
81
- "Set on to disable the adjustment of "
82
- "the virtual counter. VM stopped time "
83
- "will be counted.");
84
+ if (arm_feature(env, ARM_FEATURE_GENERIC_TIMER)) {
85
+ cpu->kvm_adjvtime = true;
86
+ object_property_add_bool(obj, "kvm-no-adjvtime", kvm_no_adjvtime_get,
87
+ kvm_no_adjvtime_set);
88
+ object_property_set_description(obj, "kvm-no-adjvtime",
89
+ "Set on to disable the adjustment of "
90
+ "the virtual counter. VM stopped time "
91
+ "will be counted.");
92
+ }
93
}
94
95
bool kvm_arm_pmu_supported(CPUState *cpu)
96
--
99
--
97
2.20.1
100
2.25.1
98
99
diff view generated by jsdifflib
1
Convert the Neon 2-reg-scalar long multiplies to decodetree.
1
Now we have removed the only use of TYPE_EXYNOS4210_IRQ_GATE we can
2
These are the last instructions in the group.
2
delete the device entirely.
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: Francisco Iglesias <frasse.iglesias@gmail.com>
6
Message-id: 20220404154658.565020-3-peter.maydell@linaro.org
6
---
7
---
7
target/arm/neon-dp.decode | 18 ++++
8
hw/intc/exynos4210_gic.c | 107 ---------------------------------------
8
target/arm/translate-neon.inc.c | 163 ++++++++++++++++++++++++++++
9
1 file changed, 107 deletions(-)
9
target/arm/translate.c | 182 ++------------------------------
10
3 files changed, 187 insertions(+), 176 deletions(-)
11
10
12
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
11
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
13
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/neon-dp.decode
13
--- a/hw/intc/exynos4210_gic.c
15
+++ b/target/arm/neon-dp.decode
14
+++ b/hw/intc/exynos4210_gic.c
16
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
15
@@ -XXX,XX +XXX,XX @@ static void exynos4210_gic_register_types(void)
17
18
@2scalar .... ... q:1 . . size:2 .... .... .... . . . . .... \
19
&2scalar vm=%vm_dp vn=%vn_dp vd=%vd_dp
20
+ # For the 'long' ops the Q bit is part of insn decode
21
+ @2scalar_q0 .... ... . . . size:2 .... .... .... . . . . .... \
22
+ &2scalar vm=%vm_dp vn=%vn_dp vd=%vd_dp q=0
23
24
VMLA_2sc 1111 001 . 1 . .. .... .... 0000 . 1 . 0 .... @2scalar
25
VMLA_F_2sc 1111 001 . 1 . .. .... .... 0001 . 1 . 0 .... @2scalar
26
27
+ VMLAL_S_2sc 1111 001 0 1 . .. .... .... 0010 . 1 . 0 .... @2scalar_q0
28
+ VMLAL_U_2sc 1111 001 1 1 . .. .... .... 0010 . 1 . 0 .... @2scalar_q0
29
+
30
+ VQDMLAL_2sc 1111 001 0 1 . .. .... .... 0011 . 1 . 0 .... @2scalar_q0
31
+
32
VMLS_2sc 1111 001 . 1 . .. .... .... 0100 . 1 . 0 .... @2scalar
33
VMLS_F_2sc 1111 001 . 1 . .. .... .... 0101 . 1 . 0 .... @2scalar
34
35
+ VMLSL_S_2sc 1111 001 0 1 . .. .... .... 0110 . 1 . 0 .... @2scalar_q0
36
+ VMLSL_U_2sc 1111 001 1 1 . .. .... .... 0110 . 1 . 0 .... @2scalar_q0
37
+
38
+ VQDMLSL_2sc 1111 001 0 1 . .. .... .... 0111 . 1 . 0 .... @2scalar_q0
39
+
40
VMUL_2sc 1111 001 . 1 . .. .... .... 1000 . 1 . 0 .... @2scalar
41
VMUL_F_2sc 1111 001 . 1 . .. .... .... 1001 . 1 . 0 .... @2scalar
42
43
+ VMULL_S_2sc 1111 001 0 1 . .. .... .... 1010 . 1 . 0 .... @2scalar_q0
44
+ VMULL_U_2sc 1111 001 1 1 . .. .... .... 1010 . 1 . 0 .... @2scalar_q0
45
+
46
+ VQDMULL_2sc 1111 001 0 1 . .. .... .... 1011 . 1 . 0 .... @2scalar_q0
47
+
48
VQDMULH_2sc 1111 001 . 1 . .. .... .... 1100 . 1 . 0 .... @2scalar
49
VQRDMULH_2sc 1111 001 . 1 . .. .... .... 1101 . 1 . 0 .... @2scalar
50
51
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/translate-neon.inc.c
54
+++ b/target/arm/translate-neon.inc.c
55
@@ -XXX,XX +XXX,XX @@ static bool trans_VQRDMLSH_2sc(DisasContext *s, arg_2scalar *a)
56
};
57
return do_vqrdmlah_2sc(s, a, opfn[a->size]);
58
}
16
}
59
+
17
60
+static bool do_2scalar_long(DisasContext *s, arg_2scalar *a,
18
type_init(exynos4210_gic_register_types)
61
+ NeonGenTwoOpWidenFn *opfn,
19
-
62
+ NeonGenTwo64OpFn *accfn)
20
-/* IRQ OR Gate struct.
63
+{
21
- *
64
+ /*
22
- * This device models an OR gate. There are n_in input qdev gpio lines and one
65
+ * Two registers and a scalar, long operations: perform an
23
- * output sysbus IRQ line. The output IRQ level is formed as OR between all
66
+ * operation on the input elements and the scalar which produces
24
- * gpio inputs.
67
+ * a double-width result, and then possibly perform an accumulation
25
- */
68
+ * operation of that result into the destination.
26
-
69
+ */
27
-#define TYPE_EXYNOS4210_IRQ_GATE "exynos4210.irq_gate"
70
+ TCGv_i32 scalar, rn;
28
-OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210IRQGateState, EXYNOS4210_IRQ_GATE)
71
+ TCGv_i64 rn0_64, rn1_64;
29
-
72
+
30
-struct Exynos4210IRQGateState {
73
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
31
- SysBusDevice parent_obj;
74
+ return false;
32
-
75
+ }
33
- uint32_t n_in; /* inputs amount */
76
+
34
- uint32_t *level; /* input levels */
77
+ /* UNDEF accesses to D16-D31 if they don't exist. */
35
- qemu_irq out; /* output IRQ */
78
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
36
-};
79
+ ((a->vd | a->vn | a->vm) & 0x10)) {
37
-
80
+ return false;
38
-static Property exynos4210_irq_gate_properties[] = {
81
+ }
39
- DEFINE_PROP_UINT32("n_in", Exynos4210IRQGateState, n_in, 1),
82
+
40
- DEFINE_PROP_END_OF_LIST(),
83
+ if (!opfn) {
41
-};
84
+ /* Bad size (including size == 3, which is a different insn group) */
42
-
85
+ return false;
43
-static const VMStateDescription vmstate_exynos4210_irq_gate = {
86
+ }
44
- .name = "exynos4210.irq_gate",
87
+
45
- .version_id = 2,
88
+ if (a->vd & 1) {
46
- .minimum_version_id = 2,
89
+ return false;
47
- .fields = (VMStateField[]) {
90
+ }
48
- VMSTATE_VBUFFER_UINT32(level, Exynos4210IRQGateState, 1, NULL, n_in),
91
+
49
- VMSTATE_END_OF_LIST()
92
+ if (!vfp_access_check(s)) {
50
- }
93
+ return true;
51
-};
94
+ }
52
-
95
+
53
-/* Process a change in IRQ input. */
96
+ scalar = neon_get_scalar(a->size, a->vm);
54
-static void exynos4210_irq_gate_handler(void *opaque, int irq, int level)
97
+
98
+ /* Load all inputs before writing any outputs, in case of overlap */
99
+ rn = neon_load_reg(a->vn, 0);
100
+ rn0_64 = tcg_temp_new_i64();
101
+ opfn(rn0_64, rn, scalar);
102
+ tcg_temp_free_i32(rn);
103
+
104
+ rn = neon_load_reg(a->vn, 1);
105
+ rn1_64 = tcg_temp_new_i64();
106
+ opfn(rn1_64, rn, scalar);
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
}
229
230
-/* 32x32->64 multiply. Marks inputs as dead. */
231
-static TCGv_i64 gen_mulu_i64_i32(TCGv_i32 a, TCGv_i32 b)
232
-{
55
-{
233
- TCGv_i32 lo = tcg_temp_new_i32();
56
- Exynos4210IRQGateState *s = (Exynos4210IRQGateState *)opaque;
234
- TCGv_i32 hi = tcg_temp_new_i32();
57
- uint32_t i;
235
- TCGv_i64 ret;
236
-
58
-
237
- tcg_gen_mulu2_i32(lo, hi, a, b);
59
- assert(irq < s->n_in);
238
- tcg_temp_free_i32(a);
239
- tcg_temp_free_i32(b);
240
-
60
-
241
- ret = tcg_temp_new_i64();
61
- s->level[irq] = level;
242
- tcg_gen_concat_i32_i64(ret, lo, hi);
243
- tcg_temp_free_i32(lo);
244
- tcg_temp_free_i32(hi);
245
-
62
-
246
- return ret;
63
- for (i = 0; i < s->n_in; i++) {
64
- if (s->level[i] >= 1) {
65
- qemu_irq_raise(s->out);
66
- return;
67
- }
68
- }
69
-
70
- qemu_irq_lower(s->out);
247
-}
71
-}
248
-
72
-
249
-static TCGv_i64 gen_muls_i64_i32(TCGv_i32 a, TCGv_i32 b)
73
-static void exynos4210_irq_gate_reset(DeviceState *d)
250
-{
74
-{
251
- TCGv_i32 lo = tcg_temp_new_i32();
75
- Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(d);
252
- TCGv_i32 hi = tcg_temp_new_i32();
253
- TCGv_i64 ret;
254
-
76
-
255
- tcg_gen_muls2_i32(lo, hi, a, b);
77
- memset(s->level, 0, s->n_in * sizeof(*s->level));
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
-}
78
-}
266
-
79
-
267
/* Swap low and high halfwords. */
80
-/*
268
static void gen_swap_half(TCGv_i32 var)
81
- * IRQ Gate initialization.
269
{
82
- */
270
@@ -XXX,XX +XXX,XX @@ static inline void gen_neon_addl(int size)
83
-static void exynos4210_irq_gate_init(Object *obj)
271
}
272
}
273
274
-static inline void gen_neon_negl(TCGv_i64 var, int size)
275
-{
84
-{
276
- switch (size) {
85
- Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(obj);
277
- case 0: gen_helper_neon_negl_u16(var, var); break;
86
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
278
- case 1: gen_helper_neon_negl_u32(var, var); break;
87
-
279
- case 2:
88
- sysbus_init_irq(sbd, &s->out);
280
- tcg_gen_neg_i64(var, var);
281
- break;
282
- default: abort();
283
- }
284
-}
89
-}
285
-
90
-
286
-static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
91
-static void exynos4210_irq_gate_realize(DeviceState *dev, Error **errp)
287
-{
92
-{
288
- switch (size) {
93
- Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(dev);
289
- case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
94
-
290
- case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
95
- /* Allocate general purpose input signals and connect a handler to each of
291
- default: abort();
96
- * them */
292
- }
97
- qdev_init_gpio_in(dev, exynos4210_irq_gate_handler, s->n_in);
98
-
99
- s->level = g_malloc0(s->n_in * sizeof(*s->level));
293
-}
100
-}
294
-
101
-
295
-static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
102
-static void exynos4210_irq_gate_class_init(ObjectClass *klass, void *data)
296
- int size, int u)
297
-{
103
-{
298
- TCGv_i64 tmp;
104
- DeviceClass *dc = DEVICE_CLASS(klass);
299
-
105
-
300
- switch ((size << 1) | u) {
106
- dc->reset = exynos4210_irq_gate_reset;
301
- case 0: gen_helper_neon_mull_s8(dest, a, b); break;
107
- dc->vmsd = &vmstate_exynos4210_irq_gate;
302
- case 1: gen_helper_neon_mull_u8(dest, a, b); break;
108
- device_class_set_props(dc, exynos4210_irq_gate_properties);
303
- case 2: gen_helper_neon_mull_s16(dest, a, b); break;
109
- dc->realize = exynos4210_irq_gate_realize;
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
-}
110
-}
325
-
111
-
326
static void gen_neon_narrow_op(int op, int u, int size,
112
-static const TypeInfo exynos4210_irq_gate_info = {
327
TCGv_i32 dest, TCGv_i64 src)
113
- .name = TYPE_EXYNOS4210_IRQ_GATE,
328
{
114
- .parent = TYPE_SYS_BUS_DEVICE,
329
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
115
- .instance_size = sizeof(Exynos4210IRQGateState),
330
int u;
116
- .instance_init = exynos4210_irq_gate_init,
331
int vec_size;
117
- .class_init = exynos4210_irq_gate_class_init,
332
uint32_t imm;
118
-};
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
-
119
-
367
- case 3: /* VQDMLAL scalar */
120
-static void exynos4210_irq_gate_register_types(void)
368
- case 7: /* VQDMLSL scalar */
121
-{
369
- case 11: /* VQDMULL scalar */
122
- type_register_static(&exynos4210_irq_gate_info);
370
- if (u == 1) {
123
-}
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
-
124
-
387
- for (pass = 0; pass < 2; pass++) {
125
-type_init(exynos4210_irq_gate_register_types)
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
--
126
--
437
2.20.1
127
2.25.1
438
439
diff view generated by jsdifflib
New patch
1
The exynos4210 SoC mostly creates its child devices as if it were
2
board code. This includes the a9mpcore object. Switch that to a
3
new-style "embedded in the state struct" creation, because in the
4
next commit we're going to want to refer to the object again further
5
down in the exynos4210_realize() function.
1
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220404154658.565020-4-peter.maydell@linaro.org
10
---
11
include/hw/arm/exynos4210.h | 2 ++
12
hw/arm/exynos4210.c | 11 ++++++-----
13
2 files changed, 8 insertions(+), 5 deletions(-)
14
15
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/arm/exynos4210.h
18
+++ b/include/hw/arm/exynos4210.h
19
@@ -XXX,XX +XXX,XX @@
20
21
#include "hw/or-irq.h"
22
#include "hw/sysbus.h"
23
+#include "hw/cpu/a9mpcore.h"
24
#include "target/arm/cpu-qom.h"
25
#include "qom/object.h"
26
27
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
28
I2CBus *i2c_if[EXYNOS4210_I2C_NUMBER];
29
qemu_or_irq pl330_irq_orgate[EXYNOS4210_NUM_DMA];
30
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
31
+ A9MPPrivState a9mpcore;
32
};
33
34
#define TYPE_EXYNOS4210_SOC "exynos4210"
35
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/arm/exynos4210.c
38
+++ b/hw/arm/exynos4210.c
39
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
40
}
41
42
/* Private memory region and Internal GIC */
43
- dev = qdev_new(TYPE_A9MPCORE_PRIV);
44
- qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
45
- busdev = SYS_BUS_DEVICE(dev);
46
- sysbus_realize_and_unref(busdev, &error_fatal);
47
+ qdev_prop_set_uint32(DEVICE(&s->a9mpcore), "num-cpu", EXYNOS4210_NCPUS);
48
+ busdev = SYS_BUS_DEVICE(&s->a9mpcore);
49
+ sysbus_realize(busdev, &error_fatal);
50
sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
51
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
52
sysbus_connect_irq(busdev, n,
53
qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 0));
54
}
55
for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
56
- s->irqs.int_gic_irq[n] = qdev_get_gpio_in(dev, n);
57
+ s->irqs.int_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
58
}
59
60
/* Cache controller */
61
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
62
g_autofree char *name = g_strdup_printf("cpu-irq-orgate%d", i);
63
object_initialize_child(obj, name, &s->cpu_irq_orgate[i], TYPE_OR_IRQ);
64
}
65
+
66
+ object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
67
}
68
69
static void exynos4210_class_init(ObjectClass *klass, void *data)
70
--
71
2.25.1
diff view generated by jsdifflib
1
Convert the Neon VEXT insn to decodetree. Rather than keeping the
1
The only time we use the int_gic_irq[] array in the Exynos4210Irq
2
old implementation which used fixed temporaries cpu_V0 and cpu_V1
2
struct is in the exynos4210_realize() function: we initialize it with
3
and did the extraction with by-hand shift and logic ops, we use
3
the GPIO inputs of the a9mpcore device, and then a bit later on we
4
the TCG extract2 insn.
4
connect those to the outputs of the internal combiner. Now that the
5
5
a9mpcore object is easily accessible as s->a9mpcore we can make the
6
We don't need to special case 0 or 8 immediates any more as the
6
connection directly from one device to the other without going via
7
optimizer is smart enough to throw away the dead code.
7
this array.
8
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-5-peter.maydell@linaro.org
11
---
12
---
12
target/arm/neon-dp.decode | 8 +++-
13
include/hw/arm/exynos4210.h | 1 -
13
target/arm/translate-neon.inc.c | 76 +++++++++++++++++++++++++++++++++
14
hw/arm/exynos4210.c | 6 ++----
14
target/arm/translate.c | 58 +------------------------
15
2 files changed, 2 insertions(+), 5 deletions(-)
15
3 files changed, 85 insertions(+), 57 deletions(-)
16
16
17
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
18
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/neon-dp.decode
19
--- a/include/hw/arm/exynos4210.h
20
+++ b/target/arm/neon-dp.decode
20
+++ b/include/hw/arm/exynos4210.h
21
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
21
@@ -XXX,XX +XXX,XX @@
22
# return false for size==3.
22
typedef struct Exynos4210Irq {
23
######################################################################
23
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
24
{
24
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
25
- # 0b11 subgroup will go here
25
- qemu_irq int_gic_irq[EXYNOS4210_INT_GIC_NIRQ];
26
+ [
26
qemu_irq ext_gic_irq[EXYNOS4210_EXT_GIC_NIRQ];
27
+ ##################################################################
27
qemu_irq board_irqs[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
28
+ # Miscellaneous size=0b11 insns
28
} Exynos4210Irq;
29
+ ##################################################################
29
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
30
+ VEXT 1111 001 0 1 . 11 .... .... imm:4 . q:1 . 0 .... \
31
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
32
+ ]
33
34
# Subgroup for size != 0b11
35
[
36
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
37
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/translate-neon.inc.c
31
--- a/hw/arm/exynos4210.c
39
+++ b/target/arm/translate-neon.inc.c
32
+++ b/hw/arm/exynos4210.c
40
@@ -XXX,XX +XXX,XX @@ static bool trans_VQDMLSL_2sc(DisasContext *s, arg_2scalar *a)
33
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
41
34
sysbus_connect_irq(busdev, n,
42
return do_2scalar_long(s, a, opfn[a->size], accfn[a->size]);
35
qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 0));
43
}
36
}
44
+
37
- for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
45
+static bool trans_VEXT(DisasContext *s, arg_VEXT *a)
38
- s->irqs.int_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
46
+{
39
- }
47
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
40
48
+ return false;
41
/* Cache controller */
49
+ }
42
sysbus_create_simple("l2x0", EXYNOS4210_L2X0_BASE_ADDR, NULL);
50
+
43
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
51
+ /* UNDEF accesses to D16-D31 if they don't exist. */
44
busdev = SYS_BUS_DEVICE(dev);
52
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
45
sysbus_realize_and_unref(busdev, &error_fatal);
53
+ ((a->vd | a->vn | a->vm) & 0x10)) {
46
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
54
+ return false;
47
- sysbus_connect_irq(busdev, n, s->irqs.int_gic_irq[n]);
55
+ }
48
+ sysbus_connect_irq(busdev, n,
56
+
49
+ qdev_get_gpio_in(DEVICE(&s->a9mpcore), n));
57
+ if ((a->vn | a->vm | a->vd) & a->q) {
50
}
58
+ return false;
51
exynos4210_combiner_get_gpioin(&s->irqs, dev, 0);
59
+ }
52
sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
60
+
61
+ if (a->imm > 7 && !a->q) {
62
+ return false;
63
+ }
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
--
53
--
199
2.20.1
54
2.25.1
200
201
diff view generated by jsdifflib
1
Convert the VQDMULH and VQRDMULH insns in the 2-reg-scalar group
1
The exynos4210 code currently has two very similar arrays of IRQs:
2
to decodetree.
2
3
* board_irqs is a field of the Exynos4210Irq struct which is filled
4
in by exynos4210_init_board_irqs() with the appropriate qemu_irqs
5
for each IRQ the board/SoC can assert
6
* irq_table is a set of qemu_irqs pointed to from the
7
Exynos4210State struct. It's allocated in exynos4210_init_irq,
8
and the only behaviour these irqs have is that they pass on the
9
level to the equivalent board_irqs[] irq
10
11
The extra indirection through irq_table is unnecessary, so coalesce
12
these into a single irq_table[] array as a direct field in
13
Exynos4210State which exynos4210_init_board_irqs() fills in.
3
14
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20220404154658.565020-6-peter.maydell@linaro.org
6
---
18
---
7
target/arm/neon-dp.decode | 3 +++
19
include/hw/arm/exynos4210.h | 8 ++------
8
target/arm/translate-neon.inc.c | 29 +++++++++++++++++++++++
20
hw/arm/exynos4210.c | 6 +-----
9
target/arm/translate.c | 42 ++-------------------------------
21
hw/intc/exynos4210_gic.c | 32 ++++++++------------------------
10
3 files changed, 34 insertions(+), 40 deletions(-)
22
3 files changed, 11 insertions(+), 35 deletions(-)
11
23
12
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
24
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
13
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/neon-dp.decode
26
--- a/include/hw/arm/exynos4210.h
15
+++ b/target/arm/neon-dp.decode
27
+++ b/include/hw/arm/exynos4210.h
16
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
28
@@ -XXX,XX +XXX,XX @@ typedef struct Exynos4210Irq {
17
29
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
18
VMUL_2sc 1111 001 . 1 . .. .... .... 1000 . 1 . 0 .... @2scalar
30
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
19
VMUL_F_2sc 1111 001 . 1 . .. .... .... 1001 . 1 . 0 .... @2scalar
31
qemu_irq ext_gic_irq[EXYNOS4210_EXT_GIC_NIRQ];
20
+
32
- qemu_irq board_irqs[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
21
+ VQDMULH_2sc 1111 001 . 1 . .. .... .... 1100 . 1 . 0 .... @2scalar
33
} Exynos4210Irq;
22
+ VQRDMULH_2sc 1111 001 . 1 . .. .... .... 1101 . 1 . 0 .... @2scalar
34
23
]
35
struct Exynos4210State {
24
}
36
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
25
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
37
/*< public >*/
38
ARMCPU *cpu[EXYNOS4210_NCPUS];
39
Exynos4210Irq irqs;
40
- qemu_irq *irq_table;
41
+ qemu_irq irq_table[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
42
43
MemoryRegion chipid_mem;
44
MemoryRegion iram_mem;
45
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210State, EXYNOS4210_SOC)
46
void exynos4210_write_secondary(ARMCPU *cpu,
47
const struct arm_boot_info *info);
48
49
-/* Initialize exynos4210 IRQ subsystem stub */
50
-qemu_irq *exynos4210_init_irq(Exynos4210Irq *env);
51
-
52
/* Initialize board IRQs.
53
* These IRQs contain splitted Int/External Combiner and External Gic IRQs */
54
-void exynos4210_init_board_irqs(Exynos4210Irq *s);
55
+void exynos4210_init_board_irqs(Exynos4210State *s);
56
57
/* Get IRQ number from exynos4210 IRQ subsystem stub.
58
* To identify IRQ source use internal combiner group and bit number
59
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
26
index XXXXXXX..XXXXXXX 100644
60
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/translate-neon.inc.c
61
--- a/hw/arm/exynos4210.c
28
+++ b/target/arm/translate-neon.inc.c
62
+++ b/hw/arm/exynos4210.c
29
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLS_F_2sc(DisasContext *s, arg_2scalar *a)
63
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
30
64
qdev_realize(DEVICE(cpuobj), NULL, &error_fatal);
31
return do_2scalar(s, a, opfn[a->size], accfn[a->size]);
65
}
32
}
66
33
+
67
- /*** IRQs ***/
34
+WRAP_ENV_FN(gen_VQDMULH_16, gen_helper_neon_qdmulh_s16)
68
-
35
+WRAP_ENV_FN(gen_VQDMULH_32, gen_helper_neon_qdmulh_s32)
69
- s->irq_table = exynos4210_init_irq(&s->irqs);
36
+WRAP_ENV_FN(gen_VQRDMULH_16, gen_helper_neon_qrdmulh_s16)
70
-
37
+WRAP_ENV_FN(gen_VQRDMULH_32, gen_helper_neon_qrdmulh_s32)
71
/* IRQ Gate */
38
+
72
for (i = 0; i < EXYNOS4210_NCPUS; i++) {
39
+static bool trans_VQDMULH_2sc(DisasContext *s, arg_2scalar *a)
73
DeviceState *orgate = DEVICE(&s->cpu_irq_orgate[i]);
40
+{
74
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
41
+ static NeonGenTwoOpFn * const opfn[] = {
75
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
42
+ NULL,
76
43
+ gen_VQDMULH_16,
77
/* Initialize board IRQs. */
44
+ gen_VQDMULH_32,
78
- exynos4210_init_board_irqs(&s->irqs);
45
+ NULL,
79
+ exynos4210_init_board_irqs(s);
46
+ };
80
47
+
81
/*** Memory ***/
48
+ return do_2scalar(s, a, opfn[a->size], NULL);
82
49
+}
83
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
50
+
51
+static bool trans_VQRDMULH_2sc(DisasContext *s, arg_2scalar *a)
52
+{
53
+ static NeonGenTwoOpFn * const opfn[] = {
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
84
index XXXXXXX..XXXXXXX 100644
64
--- a/target/arm/translate.c
85
--- a/hw/intc/exynos4210_gic.c
65
+++ b/target/arm/translate.c
86
+++ b/hw/intc/exynos4210_gic.c
66
@@ -XXX,XX +XXX,XX @@ static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
87
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64-EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
67
88
#define EXYNOS4210_GIC_CPU_REGION_SIZE 0x100
68
#define CPU_V001 cpu_V0, cpu_V0, cpu_V1
89
#define EXYNOS4210_GIC_DIST_REGION_SIZE 0x1000
69
90
70
-static TCGv_i32 neon_load_scratch(int scratch)
91
-static void exynos4210_irq_handler(void *opaque, int irq, int level)
71
-{
92
-{
72
- TCGv_i32 tmp = tcg_temp_new_i32();
93
- Exynos4210Irq *s = (Exynos4210Irq *)opaque;
73
- tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
94
-
74
- return tmp;
95
- /* Bypass */
96
- qemu_set_irq(s->board_irqs[irq], level);
75
-}
97
-}
76
-
98
-
77
-static void neon_store_scratch(int scratch, TCGv_i32 var)
99
-/*
100
- * Initialize exynos4210 IRQ subsystem stub.
101
- */
102
-qemu_irq *exynos4210_init_irq(Exynos4210Irq *s)
78
-{
103
-{
79
- tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
104
- return qemu_allocate_irqs(exynos4210_irq_handler, s,
80
- tcg_temp_free_i32(var);
105
- EXYNOS4210_MAX_INT_COMBINER_IN_IRQ);
81
-}
106
-}
82
-
107
-
83
static int gen_neon_unzip(int rd, int rm, int size, int q)
108
/*
109
* Initialize board IRQs.
110
* These IRQs contain splitted Int/External Combiner and External Gic IRQs.
111
*/
112
-void exynos4210_init_board_irqs(Exynos4210Irq *s)
113
+void exynos4210_init_board_irqs(Exynos4210State *s)
84
{
114
{
85
TCGv_ptr pd, pm;
115
uint32_t grp, bit, irq_id, n;
86
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
116
+ Exynos4210Irq *is = &s->irqs;
87
case 1: /* Float VMLA scalar */
117
88
case 5: /* Floating point VMLS scalar */
118
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
89
case 9: /* Floating point VMUL scalar */
119
irq_id = 0;
90
- return 1; /* handled by decodetree */
120
@@ -XXX,XX +XXX,XX @@ void exynos4210_init_board_irqs(Exynos4210Irq *s)
91
-
121
irq_id = EXT_GIC_ID_MCT_G1;
92
case 12: /* VQDMULH scalar */
122
}
93
case 13: /* VQRDMULH scalar */
123
if (irq_id) {
94
- if (u && ((rd | rn) & 1)) {
124
- s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
95
- return 1;
125
- s->ext_gic_irq[irq_id-32]);
96
- }
126
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
97
- tmp = neon_get_scalar(size, rm);
127
+ is->ext_gic_irq[irq_id - 32]);
98
- neon_store_scratch(0, tmp);
128
} else {
99
- for (pass = 0; pass < (u ? 4 : 2); pass++) {
129
- s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
100
- tmp = neon_load_scratch(0);
130
- s->ext_combiner_irq[n]);
101
- tmp2 = neon_load_reg(rn, pass);
131
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
102
- if (op == 12) {
132
+ is->ext_combiner_irq[n]);
103
- if (size == 1) {
133
}
104
- gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
134
}
105
- } else {
135
for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
106
- gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
136
@@ -XXX,XX +XXX,XX @@ void exynos4210_init_board_irqs(Exynos4210Irq *s)
107
- }
137
EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
108
- } else {
138
109
- if (size == 1) {
139
if (irq_id) {
110
- gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
140
- s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
111
- } else {
141
- s->ext_gic_irq[irq_id-32]);
112
- gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
142
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
113
- }
143
+ is->ext_gic_irq[irq_id - 32]);
114
- }
144
}
115
- tcg_temp_free_i32(tmp2);
145
}
116
- neon_store_reg(rd, pass, tmp);
146
}
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
--
147
--
125
2.20.1
148
2.25.1
126
127
diff view generated by jsdifflib
1
In commit 37bfce81b10450071 we accidentally introduced a leak of a TCG
1
Fix a missing set of spaces around '-' in the definition of
2
temporary in do_2shift_env_64(); free it.
2
combiner_grp_to_gic_id[]. We're about to move this code, so
3
fix the style issue first to keep checkpatch happy with the
4
code-motion patch.
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>
8
Message-id: 20220404154658.565020-7-peter.maydell@linaro.org
6
---
9
---
7
target/arm/translate-neon.inc.c | 1 +
10
hw/intc/exynos4210_gic.c | 2 +-
8
1 file changed, 1 insertion(+)
11
1 file changed, 1 insertion(+), 1 deletion(-)
9
12
10
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
13
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
11
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
12
--- a/target/arm/translate-neon.inc.c
15
--- a/hw/intc/exynos4210_gic.c
13
+++ b/target/arm/translate-neon.inc.c
16
+++ b/hw/intc/exynos4210_gic.c
14
@@ -XXX,XX +XXX,XX @@ static bool do_2shift_env_64(DisasContext *s, arg_2reg_shift *a,
17
@@ -XXX,XX +XXX,XX @@ enum ExtInt {
15
neon_load_reg64(tmp, a->vm + pass);
18
*/
16
fn(tmp, cpu_env, tmp, constimm);
19
17
neon_store_reg64(tmp, a->vd + pass);
20
static const uint32_t
18
+ tcg_temp_free_i64(tmp);
21
-combiner_grp_to_gic_id[64-EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
19
}
22
+combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
20
tcg_temp_free_i64(constimm);
23
/* int combiner groups 16-19 */
21
return true;
24
{ }, { }, { }, { },
25
/* int combiner group 20 */
22
--
26
--
23
2.20.1
27
2.25.1
24
25
diff view generated by jsdifflib
1
Convert the VMLA, VMLS and VMUL insns in the Neon "2 registers and a
1
The function exynos4210_init_board_irqs() currently lives in
2
scalar" group to decodetree. These are 32x32->32 operations where
2
exynos4210_gic.c, but it isn't really part of the exynos4210.gic
3
one of the inputs is the scalar, followed by a possible accumulate
3
device -- it is a function that implements (some of) the wiring up of
4
operation of the 32-bit result.
4
interrupts between the SoC's GIC and combiner components. This means
5
5
it fits better in exynos4210.c, which is the SoC-level code. Move it
6
The refactoring removes some of the oddities of the old decoder:
6
there. Similarly, exynos4210_git_irq() is used almost only in the
7
* operands to the operation and accumulation were often
7
SoC-level code, so move it too.
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
8
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-8-peter.maydell@linaro.org
15
---
12
---
16
target/arm/neon-dp.decode | 15 ++++
13
include/hw/arm/exynos4210.h | 4 -
17
target/arm/translate-neon.inc.c | 133 ++++++++++++++++++++++++++++++++
14
hw/arm/exynos4210.c | 202 +++++++++++++++++++++++++++++++++++
18
target/arm/translate.c | 77 ++----------------
15
hw/intc/exynos4210_gic.c | 204 ------------------------------------
19
3 files changed, 154 insertions(+), 71 deletions(-)
16
3 files changed, 202 insertions(+), 208 deletions(-)
20
17
21
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
18
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
22
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
23
--- a/target/arm/neon-dp.decode
20
--- a/include/hw/arm/exynos4210.h
24
+++ b/target/arm/neon-dp.decode
21
+++ b/include/hw/arm/exynos4210.h
25
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
22
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210State, EXYNOS4210_SOC)
26
VQDMULL_3d 1111 001 0 1 . .. .... .... 1101 . 0 . 0 .... @3diff
23
void exynos4210_write_secondary(ARMCPU *cpu,
27
24
const struct arm_boot_info *info);
28
VMULL_P_3d 1111 001 0 1 . .. .... .... 1110 . 0 . 0 .... @3diff
25
29
+
26
-/* Initialize board IRQs.
30
+ ##################################################################
27
- * These IRQs contain splitted Int/External Combiner and External Gic IRQs */
31
+ # 2-regs-plus-scalar grouping:
28
-void exynos4210_init_board_irqs(Exynos4210State *s);
32
+ # 1111 001 Q 1 D sz!=11 Vn:4 Vd:4 opc:4 N 1 M 0 Vm:4
29
-
33
+ ##################################################################
30
/* Get IRQ number from exynos4210 IRQ subsystem stub.
34
+ &2scalar vm vn vd size q
31
* To identify IRQ source use internal combiner group and bit number
35
+
32
* grp - group number
36
+ @2scalar .... ... q:1 . . size:2 .... .... .... . . . . .... \
33
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
37
+ &2scalar vm=%vm_dp vn=%vn_dp vd=%vd_dp
38
+
39
+ VMLA_2sc 1111 001 . 1 . .. .... .... 0000 . 1 . 0 .... @2scalar
40
+
41
+ VMLS_2sc 1111 001 . 1 . .. .... .... 0100 . 1 . 0 .... @2scalar
42
+
43
+ VMUL_2sc 1111 001 . 1 . .. .... .... 1000 . 1 . 0 .... @2scalar
44
]
45
}
46
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
47
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/translate-neon.inc.c
35
--- a/hw/arm/exynos4210.c
49
+++ b/target/arm/translate-neon.inc.c
36
+++ b/hw/arm/exynos4210.c
50
@@ -XXX,XX +XXX,XX @@ static bool trans_VMULL_P_3d(DisasContext *s, arg_3diff *a)
37
@@ -XXX,XX +XXX,XX @@
51
16, 16, 0, fn_gvec);
38
#define EXYNOS4210_PL330_BASE1_ADDR 0x12690000
52
return true;
39
#define EXYNOS4210_PL330_BASE2_ADDR 0x12850000
53
}
40
54
+
41
+enum ExtGicId {
55
+static void gen_neon_dup_low16(TCGv_i32 var)
42
+ EXT_GIC_ID_MDMA_LCD0 = 66,
43
+ EXT_GIC_ID_PDMA0,
44
+ EXT_GIC_ID_PDMA1,
45
+ EXT_GIC_ID_TIMER0,
46
+ EXT_GIC_ID_TIMER1,
47
+ EXT_GIC_ID_TIMER2,
48
+ EXT_GIC_ID_TIMER3,
49
+ EXT_GIC_ID_TIMER4,
50
+ EXT_GIC_ID_MCT_L0,
51
+ EXT_GIC_ID_WDT,
52
+ EXT_GIC_ID_RTC_ALARM,
53
+ EXT_GIC_ID_RTC_TIC,
54
+ EXT_GIC_ID_GPIO_XB,
55
+ EXT_GIC_ID_GPIO_XA,
56
+ EXT_GIC_ID_MCT_L1,
57
+ EXT_GIC_ID_IEM_APC,
58
+ EXT_GIC_ID_IEM_IEC,
59
+ EXT_GIC_ID_NFC,
60
+ EXT_GIC_ID_UART0,
61
+ EXT_GIC_ID_UART1,
62
+ EXT_GIC_ID_UART2,
63
+ EXT_GIC_ID_UART3,
64
+ EXT_GIC_ID_UART4,
65
+ EXT_GIC_ID_MCT_G0,
66
+ EXT_GIC_ID_I2C0,
67
+ EXT_GIC_ID_I2C1,
68
+ EXT_GIC_ID_I2C2,
69
+ EXT_GIC_ID_I2C3,
70
+ EXT_GIC_ID_I2C4,
71
+ EXT_GIC_ID_I2C5,
72
+ EXT_GIC_ID_I2C6,
73
+ EXT_GIC_ID_I2C7,
74
+ EXT_GIC_ID_SPI0,
75
+ EXT_GIC_ID_SPI1,
76
+ EXT_GIC_ID_SPI2,
77
+ EXT_GIC_ID_MCT_G1,
78
+ EXT_GIC_ID_USB_HOST,
79
+ EXT_GIC_ID_USB_DEVICE,
80
+ EXT_GIC_ID_MODEMIF,
81
+ EXT_GIC_ID_HSMMC0,
82
+ EXT_GIC_ID_HSMMC1,
83
+ EXT_GIC_ID_HSMMC2,
84
+ EXT_GIC_ID_HSMMC3,
85
+ EXT_GIC_ID_SDMMC,
86
+ EXT_GIC_ID_MIPI_CSI_4LANE,
87
+ EXT_GIC_ID_MIPI_DSI_4LANE,
88
+ EXT_GIC_ID_MIPI_CSI_2LANE,
89
+ EXT_GIC_ID_MIPI_DSI_2LANE,
90
+ EXT_GIC_ID_ONENAND_AUDI,
91
+ EXT_GIC_ID_ROTATOR,
92
+ EXT_GIC_ID_FIMC0,
93
+ EXT_GIC_ID_FIMC1,
94
+ EXT_GIC_ID_FIMC2,
95
+ EXT_GIC_ID_FIMC3,
96
+ EXT_GIC_ID_JPEG,
97
+ EXT_GIC_ID_2D,
98
+ EXT_GIC_ID_PCIe,
99
+ EXT_GIC_ID_MIXER,
100
+ EXT_GIC_ID_HDMI,
101
+ EXT_GIC_ID_HDMI_I2C,
102
+ EXT_GIC_ID_MFC,
103
+ EXT_GIC_ID_TVENC,
104
+};
105
+
106
+enum ExtInt {
107
+ EXT_GIC_ID_EXTINT0 = 48,
108
+ EXT_GIC_ID_EXTINT1,
109
+ EXT_GIC_ID_EXTINT2,
110
+ EXT_GIC_ID_EXTINT3,
111
+ EXT_GIC_ID_EXTINT4,
112
+ EXT_GIC_ID_EXTINT5,
113
+ EXT_GIC_ID_EXTINT6,
114
+ EXT_GIC_ID_EXTINT7,
115
+ EXT_GIC_ID_EXTINT8,
116
+ EXT_GIC_ID_EXTINT9,
117
+ EXT_GIC_ID_EXTINT10,
118
+ EXT_GIC_ID_EXTINT11,
119
+ EXT_GIC_ID_EXTINT12,
120
+ EXT_GIC_ID_EXTINT13,
121
+ EXT_GIC_ID_EXTINT14,
122
+ EXT_GIC_ID_EXTINT15
123
+};
124
+
125
+/*
126
+ * External GIC sources which are not from External Interrupt Combiner or
127
+ * External Interrupts are starting from EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ,
128
+ * which is INTG16 in Internal Interrupt Combiner.
129
+ */
130
+
131
+static const uint32_t
132
+combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
133
+ /* int combiner groups 16-19 */
134
+ { }, { }, { }, { },
135
+ /* int combiner group 20 */
136
+ { 0, EXT_GIC_ID_MDMA_LCD0 },
137
+ /* int combiner group 21 */
138
+ { EXT_GIC_ID_PDMA0, EXT_GIC_ID_PDMA1 },
139
+ /* int combiner group 22 */
140
+ { EXT_GIC_ID_TIMER0, EXT_GIC_ID_TIMER1, EXT_GIC_ID_TIMER2,
141
+ EXT_GIC_ID_TIMER3, EXT_GIC_ID_TIMER4 },
142
+ /* int combiner group 23 */
143
+ { EXT_GIC_ID_RTC_ALARM, EXT_GIC_ID_RTC_TIC },
144
+ /* int combiner group 24 */
145
+ { EXT_GIC_ID_GPIO_XB, EXT_GIC_ID_GPIO_XA },
146
+ /* int combiner group 25 */
147
+ { EXT_GIC_ID_IEM_APC, EXT_GIC_ID_IEM_IEC },
148
+ /* int combiner group 26 */
149
+ { EXT_GIC_ID_UART0, EXT_GIC_ID_UART1, EXT_GIC_ID_UART2, EXT_GIC_ID_UART3,
150
+ EXT_GIC_ID_UART4 },
151
+ /* int combiner group 27 */
152
+ { EXT_GIC_ID_I2C0, EXT_GIC_ID_I2C1, EXT_GIC_ID_I2C2, EXT_GIC_ID_I2C3,
153
+ EXT_GIC_ID_I2C4, EXT_GIC_ID_I2C5, EXT_GIC_ID_I2C6,
154
+ EXT_GIC_ID_I2C7 },
155
+ /* int combiner group 28 */
156
+ { EXT_GIC_ID_SPI0, EXT_GIC_ID_SPI1, EXT_GIC_ID_SPI2 , EXT_GIC_ID_USB_HOST},
157
+ /* int combiner group 29 */
158
+ { EXT_GIC_ID_HSMMC0, EXT_GIC_ID_HSMMC1, EXT_GIC_ID_HSMMC2,
159
+ EXT_GIC_ID_HSMMC3, EXT_GIC_ID_SDMMC },
160
+ /* int combiner group 30 */
161
+ { EXT_GIC_ID_MIPI_CSI_4LANE, EXT_GIC_ID_MIPI_CSI_2LANE },
162
+ /* int combiner group 31 */
163
+ { EXT_GIC_ID_MIPI_DSI_4LANE, EXT_GIC_ID_MIPI_DSI_2LANE },
164
+ /* int combiner group 32 */
165
+ { EXT_GIC_ID_FIMC0, EXT_GIC_ID_FIMC1 },
166
+ /* int combiner group 33 */
167
+ { EXT_GIC_ID_FIMC2, EXT_GIC_ID_FIMC3 },
168
+ /* int combiner group 34 */
169
+ { EXT_GIC_ID_ONENAND_AUDI, EXT_GIC_ID_NFC },
170
+ /* int combiner group 35 */
171
+ { 0, 0, 0, EXT_GIC_ID_MCT_L1, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
172
+ /* int combiner group 36 */
173
+ { EXT_GIC_ID_MIXER },
174
+ /* int combiner group 37 */
175
+ { EXT_GIC_ID_EXTINT4, EXT_GIC_ID_EXTINT5, EXT_GIC_ID_EXTINT6,
176
+ EXT_GIC_ID_EXTINT7 },
177
+ /* groups 38-50 */
178
+ { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { },
179
+ /* int combiner group 51 */
180
+ { EXT_GIC_ID_MCT_L0, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
181
+ /* group 52 */
182
+ { },
183
+ /* int combiner group 53 */
184
+ { EXT_GIC_ID_WDT, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
185
+ /* groups 54-63 */
186
+ { }, { }, { }, { }, { }, { }, { }, { }, { }, { }
187
+};
188
+
189
+/*
190
+ * Initialize board IRQs.
191
+ * These IRQs contain splitted Int/External Combiner and External Gic IRQs.
192
+ */
193
+static void exynos4210_init_board_irqs(Exynos4210State *s)
56
+{
194
+{
57
+ TCGv_i32 tmp = tcg_temp_new_i32();
195
+ uint32_t grp, bit, irq_id, n;
58
+ tcg_gen_ext16u_i32(var, var);
196
+ Exynos4210Irq *is = &s->irqs;
59
+ tcg_gen_shli_i32(tmp, var, 16);
197
+
60
+ tcg_gen_or_i32(var, var, tmp);
198
+ for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
61
+ tcg_temp_free_i32(tmp);
199
+ irq_id = 0;
200
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4) ||
201
+ n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4)) {
202
+ /* MCT_G0 is passed to External GIC */
203
+ irq_id = EXT_GIC_ID_MCT_G0;
204
+ }
205
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) ||
206
+ n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) {
207
+ /* MCT_G1 is passed to External and GIC */
208
+ irq_id = EXT_GIC_ID_MCT_G1;
209
+ }
210
+ if (irq_id) {
211
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
212
+ is->ext_gic_irq[irq_id - 32]);
213
+ } else {
214
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
215
+ is->ext_combiner_irq[n]);
216
+ }
217
+ }
218
+ for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
219
+ /* these IDs are passed to Internal Combiner and External GIC */
220
+ grp = EXYNOS4210_COMBINER_GET_GRP_NUM(n);
221
+ bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
222
+ irq_id = combiner_grp_to_gic_id[grp -
223
+ EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
224
+
225
+ if (irq_id) {
226
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
227
+ is->ext_gic_irq[irq_id - 32]);
228
+ }
229
+ }
62
+}
230
+}
63
+
231
+
64
+static void gen_neon_dup_high16(TCGv_i32 var)
232
+/*
233
+ * Get IRQ number from exynos4210 IRQ subsystem stub.
234
+ * To identify IRQ source use internal combiner group and bit number
235
+ * grp - group number
236
+ * bit - bit number inside group
237
+ */
238
+uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
65
+{
239
+{
66
+ TCGv_i32 tmp = tcg_temp_new_i32();
240
+ return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
67
+ tcg_gen_andi_i32(var, var, 0xffff0000);
68
+ tcg_gen_shri_i32(tmp, var, 16);
69
+ tcg_gen_or_i32(var, var, tmp);
70
+ tcg_temp_free_i32(tmp);
71
+}
241
+}
72
+
242
+
73
+static inline TCGv_i32 neon_get_scalar(int size, int reg)
243
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
74
+{
244
0x09, 0x00, 0x00, 0x00 };
75
+ TCGv_i32 tmp;
245
76
+ if (size == 1) {
246
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
77
+ tmp = neon_load_reg(reg & 7, reg >> 4);
78
+ if (reg & 8) {
79
+ gen_neon_dup_high16(tmp);
80
+ } else {
81
+ gen_neon_dup_low16(tmp);
82
+ }
83
+ } else {
84
+ tmp = neon_load_reg(reg & 15, reg >> 4);
85
+ }
86
+ return tmp;
87
+}
88
+
89
+static bool do_2scalar(DisasContext *s, arg_2scalar *a,
90
+ NeonGenTwoOpFn *opfn, NeonGenTwoOpFn *accfn)
91
+{
92
+ /*
93
+ * Two registers and a scalar: perform an operation between
94
+ * the input elements and the scalar, and then possibly
95
+ * perform an accumulation operation of that result into the
96
+ * destination.
97
+ */
98
+ TCGv_i32 scalar;
99
+ int pass;
100
+
101
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
102
+ return false;
103
+ }
104
+
105
+ /* UNDEF accesses to D16-D31 if they don't exist. */
106
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
107
+ ((a->vd | a->vn | a->vm) & 0x10)) {
108
+ return false;
109
+ }
110
+
111
+ if (!opfn) {
112
+ /* Bad size (including size == 3, which is a different insn group) */
113
+ return false;
114
+ }
115
+
116
+ if (a->q && ((a->vd | a->vn) & 1)) {
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
247
index XXXXXXX..XXXXXXX 100644
189
--- a/target/arm/translate.c
248
--- a/hw/intc/exynos4210_gic.c
190
+++ b/target/arm/translate.c
249
+++ b/hw/intc/exynos4210_gic.c
191
@@ -XXX,XX +XXX,XX @@ static int disas_dsp_insn(DisasContext *s, uint32_t insn)
250
@@ -XXX,XX +XXX,XX @@
192
#define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
251
#include "hw/arm/exynos4210.h"
193
#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
252
#include "qom/object.h"
194
253
195
-static void gen_neon_dup_low16(TCGv_i32 var)
254
-enum ExtGicId {
255
- EXT_GIC_ID_MDMA_LCD0 = 66,
256
- EXT_GIC_ID_PDMA0,
257
- EXT_GIC_ID_PDMA1,
258
- EXT_GIC_ID_TIMER0,
259
- EXT_GIC_ID_TIMER1,
260
- EXT_GIC_ID_TIMER2,
261
- EXT_GIC_ID_TIMER3,
262
- EXT_GIC_ID_TIMER4,
263
- EXT_GIC_ID_MCT_L0,
264
- EXT_GIC_ID_WDT,
265
- EXT_GIC_ID_RTC_ALARM,
266
- EXT_GIC_ID_RTC_TIC,
267
- EXT_GIC_ID_GPIO_XB,
268
- EXT_GIC_ID_GPIO_XA,
269
- EXT_GIC_ID_MCT_L1,
270
- EXT_GIC_ID_IEM_APC,
271
- EXT_GIC_ID_IEM_IEC,
272
- EXT_GIC_ID_NFC,
273
- EXT_GIC_ID_UART0,
274
- EXT_GIC_ID_UART1,
275
- EXT_GIC_ID_UART2,
276
- EXT_GIC_ID_UART3,
277
- EXT_GIC_ID_UART4,
278
- EXT_GIC_ID_MCT_G0,
279
- EXT_GIC_ID_I2C0,
280
- EXT_GIC_ID_I2C1,
281
- EXT_GIC_ID_I2C2,
282
- EXT_GIC_ID_I2C3,
283
- EXT_GIC_ID_I2C4,
284
- EXT_GIC_ID_I2C5,
285
- EXT_GIC_ID_I2C6,
286
- EXT_GIC_ID_I2C7,
287
- EXT_GIC_ID_SPI0,
288
- EXT_GIC_ID_SPI1,
289
- EXT_GIC_ID_SPI2,
290
- EXT_GIC_ID_MCT_G1,
291
- EXT_GIC_ID_USB_HOST,
292
- EXT_GIC_ID_USB_DEVICE,
293
- EXT_GIC_ID_MODEMIF,
294
- EXT_GIC_ID_HSMMC0,
295
- EXT_GIC_ID_HSMMC1,
296
- EXT_GIC_ID_HSMMC2,
297
- EXT_GIC_ID_HSMMC3,
298
- EXT_GIC_ID_SDMMC,
299
- EXT_GIC_ID_MIPI_CSI_4LANE,
300
- EXT_GIC_ID_MIPI_DSI_4LANE,
301
- EXT_GIC_ID_MIPI_CSI_2LANE,
302
- EXT_GIC_ID_MIPI_DSI_2LANE,
303
- EXT_GIC_ID_ONENAND_AUDI,
304
- EXT_GIC_ID_ROTATOR,
305
- EXT_GIC_ID_FIMC0,
306
- EXT_GIC_ID_FIMC1,
307
- EXT_GIC_ID_FIMC2,
308
- EXT_GIC_ID_FIMC3,
309
- EXT_GIC_ID_JPEG,
310
- EXT_GIC_ID_2D,
311
- EXT_GIC_ID_PCIe,
312
- EXT_GIC_ID_MIXER,
313
- EXT_GIC_ID_HDMI,
314
- EXT_GIC_ID_HDMI_I2C,
315
- EXT_GIC_ID_MFC,
316
- EXT_GIC_ID_TVENC,
317
-};
318
-
319
-enum ExtInt {
320
- EXT_GIC_ID_EXTINT0 = 48,
321
- EXT_GIC_ID_EXTINT1,
322
- EXT_GIC_ID_EXTINT2,
323
- EXT_GIC_ID_EXTINT3,
324
- EXT_GIC_ID_EXTINT4,
325
- EXT_GIC_ID_EXTINT5,
326
- EXT_GIC_ID_EXTINT6,
327
- EXT_GIC_ID_EXTINT7,
328
- EXT_GIC_ID_EXTINT8,
329
- EXT_GIC_ID_EXTINT9,
330
- EXT_GIC_ID_EXTINT10,
331
- EXT_GIC_ID_EXTINT11,
332
- EXT_GIC_ID_EXTINT12,
333
- EXT_GIC_ID_EXTINT13,
334
- EXT_GIC_ID_EXTINT14,
335
- EXT_GIC_ID_EXTINT15
336
-};
337
-
338
-/*
339
- * External GIC sources which are not from External Interrupt Combiner or
340
- * External Interrupts are starting from EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ,
341
- * which is INTG16 in Internal Interrupt Combiner.
342
- */
343
-
344
-static const uint32_t
345
-combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
346
- /* int combiner groups 16-19 */
347
- { }, { }, { }, { },
348
- /* int combiner group 20 */
349
- { 0, EXT_GIC_ID_MDMA_LCD0 },
350
- /* int combiner group 21 */
351
- { EXT_GIC_ID_PDMA0, EXT_GIC_ID_PDMA1 },
352
- /* int combiner group 22 */
353
- { EXT_GIC_ID_TIMER0, EXT_GIC_ID_TIMER1, EXT_GIC_ID_TIMER2,
354
- EXT_GIC_ID_TIMER3, EXT_GIC_ID_TIMER4 },
355
- /* int combiner group 23 */
356
- { EXT_GIC_ID_RTC_ALARM, EXT_GIC_ID_RTC_TIC },
357
- /* int combiner group 24 */
358
- { EXT_GIC_ID_GPIO_XB, EXT_GIC_ID_GPIO_XA },
359
- /* int combiner group 25 */
360
- { EXT_GIC_ID_IEM_APC, EXT_GIC_ID_IEM_IEC },
361
- /* int combiner group 26 */
362
- { EXT_GIC_ID_UART0, EXT_GIC_ID_UART1, EXT_GIC_ID_UART2, EXT_GIC_ID_UART3,
363
- EXT_GIC_ID_UART4 },
364
- /* int combiner group 27 */
365
- { EXT_GIC_ID_I2C0, EXT_GIC_ID_I2C1, EXT_GIC_ID_I2C2, EXT_GIC_ID_I2C3,
366
- EXT_GIC_ID_I2C4, EXT_GIC_ID_I2C5, EXT_GIC_ID_I2C6,
367
- EXT_GIC_ID_I2C7 },
368
- /* int combiner group 28 */
369
- { EXT_GIC_ID_SPI0, EXT_GIC_ID_SPI1, EXT_GIC_ID_SPI2 , EXT_GIC_ID_USB_HOST},
370
- /* int combiner group 29 */
371
- { EXT_GIC_ID_HSMMC0, EXT_GIC_ID_HSMMC1, EXT_GIC_ID_HSMMC2,
372
- EXT_GIC_ID_HSMMC3, EXT_GIC_ID_SDMMC },
373
- /* int combiner group 30 */
374
- { EXT_GIC_ID_MIPI_CSI_4LANE, EXT_GIC_ID_MIPI_CSI_2LANE },
375
- /* int combiner group 31 */
376
- { EXT_GIC_ID_MIPI_DSI_4LANE, EXT_GIC_ID_MIPI_DSI_2LANE },
377
- /* int combiner group 32 */
378
- { EXT_GIC_ID_FIMC0, EXT_GIC_ID_FIMC1 },
379
- /* int combiner group 33 */
380
- { EXT_GIC_ID_FIMC2, EXT_GIC_ID_FIMC3 },
381
- /* int combiner group 34 */
382
- { EXT_GIC_ID_ONENAND_AUDI, EXT_GIC_ID_NFC },
383
- /* int combiner group 35 */
384
- { 0, 0, 0, EXT_GIC_ID_MCT_L1, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
385
- /* int combiner group 36 */
386
- { EXT_GIC_ID_MIXER },
387
- /* int combiner group 37 */
388
- { EXT_GIC_ID_EXTINT4, EXT_GIC_ID_EXTINT5, EXT_GIC_ID_EXTINT6,
389
- EXT_GIC_ID_EXTINT7 },
390
- /* groups 38-50 */
391
- { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { },
392
- /* int combiner group 51 */
393
- { EXT_GIC_ID_MCT_L0, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
394
- /* group 52 */
395
- { },
396
- /* int combiner group 53 */
397
- { EXT_GIC_ID_WDT, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
398
- /* groups 54-63 */
399
- { }, { }, { }, { }, { }, { }, { }, { }, { }, { }
400
-};
401
-
402
#define EXYNOS4210_GIC_NIRQ 160
403
404
#define EXYNOS4210_EXT_GIC_CPU_REGION_SIZE 0x10000
405
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
406
#define EXYNOS4210_GIC_CPU_REGION_SIZE 0x100
407
#define EXYNOS4210_GIC_DIST_REGION_SIZE 0x1000
408
409
-/*
410
- * Initialize board IRQs.
411
- * These IRQs contain splitted Int/External Combiner and External Gic IRQs.
412
- */
413
-void exynos4210_init_board_irqs(Exynos4210State *s)
196
-{
414
-{
197
- TCGv_i32 tmp = tcg_temp_new_i32();
415
- uint32_t grp, bit, irq_id, n;
198
- tcg_gen_ext16u_i32(var, var);
416
- Exynos4210Irq *is = &s->irqs;
199
- tcg_gen_shli_i32(tmp, var, 16);
417
-
200
- tcg_gen_or_i32(var, var, tmp);
418
- for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
201
- tcg_temp_free_i32(tmp);
419
- irq_id = 0;
202
-}
420
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4) ||
203
-
421
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4)) {
204
-static void gen_neon_dup_high16(TCGv_i32 var)
422
- /* MCT_G0 is passed to External GIC */
205
-{
423
- irq_id = EXT_GIC_ID_MCT_G0;
206
- TCGv_i32 tmp = tcg_temp_new_i32();
424
- }
207
- tcg_gen_andi_i32(var, var, 0xffff0000);
425
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) ||
208
- tcg_gen_shri_i32(tmp, var, 16);
426
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) {
209
- tcg_gen_or_i32(var, var, tmp);
427
- /* MCT_G1 is passed to External and GIC */
210
- tcg_temp_free_i32(tmp);
428
- irq_id = EXT_GIC_ID_MCT_G1;
211
-}
429
- }
212
-
430
- if (irq_id) {
213
static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
431
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
214
{
432
- is->ext_gic_irq[irq_id - 32]);
215
#ifndef CONFIG_USER_ONLY
433
- } else {
216
@@ -XXX,XX +XXX,XX @@ static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
434
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
217
435
- is->ext_combiner_irq[n]);
218
#define CPU_V001 cpu_V0, cpu_V0, cpu_V1
436
- }
219
437
- }
220
-static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1)
438
- for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
221
-{
439
- /* these IDs are passed to Internal Combiner and External GIC */
222
- switch (size) {
440
- grp = EXYNOS4210_COMBINER_GET_GRP_NUM(n);
223
- case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
441
- bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
224
- case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
442
- irq_id = combiner_grp_to_gic_id[grp -
225
- case 2: tcg_gen_add_i32(t0, t0, t1); break;
443
- EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
226
- default: abort();
444
-
445
- if (irq_id) {
446
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
447
- is->ext_gic_irq[irq_id - 32]);
448
- }
227
- }
449
- }
228
-}
450
-}
229
-
451
-
230
-static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
452
-/*
453
- * Get IRQ number from exynos4210 IRQ subsystem stub.
454
- * To identify IRQ source use internal combiner group and bit number
455
- * grp - group number
456
- * bit - bit number inside group
457
- */
458
-uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
231
-{
459
-{
232
- switch (size) {
460
- return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
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
-}
461
-}
239
-
462
-
240
static TCGv_i32 neon_load_scratch(int scratch)
463
-/********* GIC part *********/
241
{
464
-
242
TCGv_i32 tmp = tcg_temp_new_i32();
465
#define TYPE_EXYNOS4210_GIC "exynos4210.gic"
243
@@ -XXX,XX +XXX,XX @@ static void neon_store_scratch(int scratch, TCGv_i32 var)
466
OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210GicState, EXYNOS4210_GIC)
244
tcg_temp_free_i32(var);
467
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
--
468
--
327
2.20.1
469
2.25.1
328
329
diff view generated by jsdifflib
1
Mark the arrays of function pointers in trans_VSHLL_S_2sh() and
1
Switch the creation of the external GIC to the new-style "embedded in
2
trans_VSHLL_U_2sh() as both 'static' and 'const'.
2
state struct" approach, so we can easily refer to the object
3
elsewhere during realize.
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>
7
Message-id: 20220404154658.565020-9-peter.maydell@linaro.org
6
---
8
---
7
target/arm/translate-neon.inc.c | 4 ++--
9
include/hw/arm/exynos4210.h | 2 ++
8
1 file changed, 2 insertions(+), 2 deletions(-)
10
include/hw/intc/exynos4210_gic.h | 43 ++++++++++++++++++++++++++++++++
11
hw/arm/exynos4210.c | 10 ++++----
12
hw/intc/exynos4210_gic.c | 17 ++-----------
13
MAINTAINERS | 2 +-
14
5 files changed, 53 insertions(+), 21 deletions(-)
15
create mode 100644 include/hw/intc/exynos4210_gic.h
9
16
10
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
11
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
12
--- a/target/arm/translate-neon.inc.c
19
--- a/include/hw/arm/exynos4210.h
13
+++ b/target/arm/translate-neon.inc.c
20
+++ b/include/hw/arm/exynos4210.h
14
@@ -XXX,XX +XXX,XX @@ static bool do_vshll_2sh(DisasContext *s, arg_2reg_shift *a,
21
@@ -XXX,XX +XXX,XX @@
15
22
#include "hw/or-irq.h"
16
static bool trans_VSHLL_S_2sh(DisasContext *s, arg_2reg_shift *a)
23
#include "hw/sysbus.h"
24
#include "hw/cpu/a9mpcore.h"
25
+#include "hw/intc/exynos4210_gic.h"
26
#include "target/arm/cpu-qom.h"
27
#include "qom/object.h"
28
29
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
30
qemu_or_irq pl330_irq_orgate[EXYNOS4210_NUM_DMA];
31
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
32
A9MPPrivState a9mpcore;
33
+ Exynos4210GicState ext_gic;
34
};
35
36
#define TYPE_EXYNOS4210_SOC "exynos4210"
37
diff --git a/include/hw/intc/exynos4210_gic.h b/include/hw/intc/exynos4210_gic.h
38
new file mode 100644
39
index XXXXXXX..XXXXXXX
40
--- /dev/null
41
+++ b/include/hw/intc/exynos4210_gic.h
42
@@ -XXX,XX +XXX,XX @@
43
+/*
44
+ * Samsung exynos4210 GIC implementation. Based on hw/arm_gic.c
45
+ *
46
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
47
+ * All rights reserved.
48
+ *
49
+ * Evgeny Voevodin <e.voevodin@samsung.com>
50
+ *
51
+ * This program is free software; you can redistribute it and/or modify it
52
+ * under the terms of the GNU General Public License as published by the
53
+ * Free Software Foundation; either version 2 of the License, or (at your
54
+ * option) any later version.
55
+ *
56
+ * This program is distributed in the hope that it will be useful,
57
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
58
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
59
+ * See the GNU General Public License for more details.
60
+ *
61
+ * You should have received a copy of the GNU General Public License along
62
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
63
+ */
64
+#ifndef HW_INTC_EXYNOS4210_GIC_H
65
+#define HW_INTC_EXYNOS4210_GIC_H
66
+
67
+#include "hw/sysbus.h"
68
+
69
+#define TYPE_EXYNOS4210_GIC "exynos4210.gic"
70
+OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210GicState, EXYNOS4210_GIC)
71
+
72
+#define EXYNOS4210_GIC_NCPUS 2
73
+
74
+struct Exynos4210GicState {
75
+ SysBusDevice parent_obj;
76
+
77
+ MemoryRegion cpu_container;
78
+ MemoryRegion dist_container;
79
+ MemoryRegion cpu_alias[EXYNOS4210_GIC_NCPUS];
80
+ MemoryRegion dist_alias[EXYNOS4210_GIC_NCPUS];
81
+ uint32_t num_cpu;
82
+ DeviceState *gic;
83
+};
84
+
85
+#endif
86
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/hw/arm/exynos4210.c
89
+++ b/hw/arm/exynos4210.c
90
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
91
sysbus_create_simple("l2x0", EXYNOS4210_L2X0_BASE_ADDR, NULL);
92
93
/* External GIC */
94
- dev = qdev_new("exynos4210.gic");
95
- qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
96
- busdev = SYS_BUS_DEVICE(dev);
97
- sysbus_realize_and_unref(busdev, &error_fatal);
98
+ qdev_prop_set_uint32(DEVICE(&s->ext_gic), "num-cpu", EXYNOS4210_NCPUS);
99
+ busdev = SYS_BUS_DEVICE(&s->ext_gic);
100
+ sysbus_realize(busdev, &error_fatal);
101
/* Map CPU interface */
102
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_GIC_CPU_BASE_ADDR);
103
/* Map Distributer interface */
104
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
105
qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 1));
106
}
107
for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
108
- s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(dev, n);
109
+ s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->ext_gic), n);
110
}
111
112
/* Internal Interrupt Combiner */
113
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
114
}
115
116
object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
117
+ object_initialize_child(obj, "ext-gic", &s->ext_gic, TYPE_EXYNOS4210_GIC);
118
}
119
120
static void exynos4210_class_init(ObjectClass *klass, void *data)
121
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
122
index XXXXXXX..XXXXXXX 100644
123
--- a/hw/intc/exynos4210_gic.c
124
+++ b/hw/intc/exynos4210_gic.c
125
@@ -XXX,XX +XXX,XX @@
126
#include "qemu/module.h"
127
#include "hw/irq.h"
128
#include "hw/qdev-properties.h"
129
+#include "hw/intc/exynos4210_gic.h"
130
#include "hw/arm/exynos4210.h"
131
#include "qom/object.h"
132
133
@@ -XXX,XX +XXX,XX @@
134
#define EXYNOS4210_GIC_CPU_REGION_SIZE 0x100
135
#define EXYNOS4210_GIC_DIST_REGION_SIZE 0x1000
136
137
-#define TYPE_EXYNOS4210_GIC "exynos4210.gic"
138
-OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210GicState, EXYNOS4210_GIC)
139
-
140
-struct Exynos4210GicState {
141
- SysBusDevice parent_obj;
142
-
143
- MemoryRegion cpu_container;
144
- MemoryRegion dist_container;
145
- MemoryRegion cpu_alias[EXYNOS4210_NCPUS];
146
- MemoryRegion dist_alias[EXYNOS4210_NCPUS];
147
- uint32_t num_cpu;
148
- DeviceState *gic;
149
-};
150
-
151
static void exynos4210_gic_set_irq(void *opaque, int irq, int level)
17
{
152
{
18
- NeonGenWidenFn *widenfn[] = {
153
Exynos4210GicState *s = (Exynos4210GicState *)opaque;
19
+ static NeonGenWidenFn * const widenfn[] = {
154
@@ -XXX,XX +XXX,XX @@ static void exynos4210_gic_realize(DeviceState *dev, Error **errp)
20
gen_helper_neon_widen_s8,
155
* enough room for the cpu numbers. gcc 9.2.1 on 32-bit x86
21
gen_helper_neon_widen_s16,
156
* doesn't figure this out, otherwise and gives spurious warnings.
22
tcg_gen_ext_i32_i64,
157
*/
23
@@ -XXX,XX +XXX,XX @@ static bool trans_VSHLL_S_2sh(DisasContext *s, arg_2reg_shift *a)
158
- assert(n <= EXYNOS4210_NCPUS);
24
159
+ assert(n <= EXYNOS4210_GIC_NCPUS);
25
static bool trans_VSHLL_U_2sh(DisasContext *s, arg_2reg_shift *a)
160
for (i = 0; i < n; i++) {
26
{
161
/* Map CPU interface per SMP Core */
27
- NeonGenWidenFn *widenfn[] = {
162
sprintf(cpu_alias_name, "%s%x", cpu_prefix, i);
28
+ static NeonGenWidenFn * const widenfn[] = {
163
diff --git a/MAINTAINERS b/MAINTAINERS
29
gen_helper_neon_widen_u8,
164
index XXXXXXX..XXXXXXX 100644
30
gen_helper_neon_widen_u16,
165
--- a/MAINTAINERS
31
tcg_gen_extu_i32_i64,
166
+++ b/MAINTAINERS
167
@@ -XXX,XX +XXX,XX @@ M: Peter Maydell <peter.maydell@linaro.org>
168
L: qemu-arm@nongnu.org
169
S: Odd Fixes
170
F: hw/*/exynos*
171
-F: include/hw/arm/exynos4210.h
172
+F: include/hw/*/exynos*
173
174
Calxeda Highbank
175
M: Rob Herring <robh@kernel.org>
32
--
176
--
33
2.20.1
177
2.25.1
34
35
diff view generated by jsdifflib
1
Convert the Neon 3-reg-diff insn polynomial VMULL. This is the last
1
The only time we use the ext_gic_irq[] array in the Exynos4210Irq
2
insn in this group to be converted.
2
struct is during realize of the SoC -- we initialize it with the
3
input IRQs of the external GIC device, and then connect those to
4
outputs of other devices further on in realize (including in the
5
exynos4210_init_board_irqs() function). Now that the ext_gic object
6
is easily accessible as s->ext_gic we can make the connections
7
directly from one device to the other without going via this array.
3
8
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-10-peter.maydell@linaro.org
6
---
12
---
7
target/arm/neon-dp.decode | 2 ++
13
include/hw/arm/exynos4210.h | 1 -
8
target/arm/translate-neon.inc.c | 43 +++++++++++++++++++++++
14
hw/arm/exynos4210.c | 12 ++++++------
9
target/arm/translate.c | 60 ++-------------------------------
15
2 files changed, 6 insertions(+), 7 deletions(-)
10
3 files changed, 48 insertions(+), 57 deletions(-)
11
16
12
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
13
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/neon-dp.decode
19
--- a/include/hw/arm/exynos4210.h
15
+++ b/target/arm/neon-dp.decode
20
+++ b/include/hw/arm/exynos4210.h
16
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
21
@@ -XXX,XX +XXX,XX @@
17
VMULL_U_3d 1111 001 1 1 . .. .... .... 1100 . 0 . 0 .... @3diff
22
typedef struct Exynos4210Irq {
18
23
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
19
VQDMULL_3d 1111 001 0 1 . .. .... .... 1101 . 0 . 0 .... @3diff
24
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
20
+
25
- qemu_irq ext_gic_irq[EXYNOS4210_EXT_GIC_NIRQ];
21
+ VMULL_P_3d 1111 001 0 1 . .. .... .... 1110 . 0 . 0 .... @3diff
26
} Exynos4210Irq;
22
]
27
28
struct Exynos4210State {
29
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/exynos4210.c
32
+++ b/hw/arm/exynos4210.c
33
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
34
{
35
uint32_t grp, bit, irq_id, n;
36
Exynos4210Irq *is = &s->irqs;
37
+ DeviceState *extgicdev = DEVICE(&s->ext_gic);
38
39
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
40
irq_id = 0;
41
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
42
}
43
if (irq_id) {
44
s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
45
- is->ext_gic_irq[irq_id - 32]);
46
+ qdev_get_gpio_in(extgicdev,
47
+ irq_id - 32));
48
} else {
49
s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
50
is->ext_combiner_irq[n]);
51
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
52
53
if (irq_id) {
54
s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
55
- is->ext_gic_irq[irq_id - 32]);
56
+ qdev_get_gpio_in(extgicdev,
57
+ irq_id - 32));
58
}
59
}
23
}
60
}
24
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
61
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
25
index XXXXXXX..XXXXXXX 100644
62
sysbus_connect_irq(busdev, n,
26
--- a/target/arm/translate-neon.inc.c
63
qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 1));
27
+++ b/target/arm/translate-neon.inc.c
64
}
28
@@ -XXX,XX +XXX,XX @@ static bool trans_VQDMLSL_3d(DisasContext *s, arg_3diff *a)
65
- for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
29
66
- s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->ext_gic), n);
30
return do_long_3d(s, a, opfn[a->size], accfn[a->size]);
67
- }
31
}
68
32
+
69
/* Internal Interrupt Combiner */
33
+static bool trans_VMULL_P_3d(DisasContext *s, arg_3diff *a)
70
dev = qdev_new("exynos4210.combiner");
34
+{
71
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
35
+ gen_helper_gvec_3 *fn_gvec;
72
busdev = SYS_BUS_DEVICE(dev);
36
+
73
sysbus_realize_and_unref(busdev, &error_fatal);
37
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
74
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
38
+ return false;
75
- sysbus_connect_irq(busdev, n, s->irqs.ext_gic_irq[n]);
39
+ }
76
+ sysbus_connect_irq(busdev, n, qdev_get_gpio_in(DEVICE(&s->ext_gic), n));
40
+
77
}
41
+ /* UNDEF accesses to D16-D31 if they don't exist. */
78
exynos4210_combiner_get_gpioin(&s->irqs, dev, 1);
42
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
79
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
43
+ ((a->vd | a->vn | a->vm) & 0x10)) {
44
+ return false;
45
+ }
46
+
47
+ if (a->vd & 1) {
48
+ return false;
49
+ }
50
+
51
+ switch (a->size) {
52
+ case 0:
53
+ fn_gvec = gen_helper_neon_pmull_h;
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
+
65
+ if (!vfp_access_check(s)) {
66
+ return true;
67
+ }
68
+
69
+ tcg_gen_gvec_3_ool(neon_reg_offset(a->vd, 0),
70
+ neon_reg_offset(a->vn, 0),
71
+ neon_reg_offset(a->vm, 0),
72
+ 16, 16, 0, fn_gvec);
73
+ return true;
74
+}
75
diff --git a/target/arm/translate.c b/target/arm/translate.c
76
index XXXXXXX..XXXXXXX 100644
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
--
80
--
161
2.20.1
81
2.25.1
162
163
diff view generated by jsdifflib
1
Convert the Neon VTBL, VTBX instructions to decodetree. The actual
1
The function exynos4210_combiner_get_gpioin() currently lives in
2
implementation of the insn is copied across to the new trans function
2
exynos4210_combiner.c, but it isn't really part of the combiner
3
unchanged except for renaming 'tmp5' to 'tmp4'.
3
device itself -- it is a function that implements the wiring up of
4
some interrupt sources to multiple combiner inputs. Move it to live
5
with the other SoC-level code in exynos4210.c, along with a few
6
macros previously defined in exynos4210.h which are now used only
7
in exynos4210.c.
4
8
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-11-peter.maydell@linaro.org
7
---
12
---
8
target/arm/neon-dp.decode | 3 ++
13
include/hw/arm/exynos4210.h | 11 -----
9
target/arm/translate-neon.inc.c | 56 +++++++++++++++++++++++++++++++++
14
hw/arm/exynos4210.c | 82 +++++++++++++++++++++++++++++++++++
10
target/arm/translate.c | 41 +++---------------------
15
hw/intc/exynos4210_combiner.c | 77 --------------------------------
11
3 files changed, 63 insertions(+), 37 deletions(-)
16
3 files changed, 82 insertions(+), 88 deletions(-)
12
17
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
18
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
14
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
20
--- a/include/hw/arm/exynos4210.h
16
+++ b/target/arm/neon-dp.decode
21
+++ b/include/hw/arm/exynos4210.h
17
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
22
@@ -XXX,XX +XXX,XX @@
18
##################################################################
23
#define EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ \
19
VEXT 1111 001 0 1 . 11 .... .... imm:4 . q:1 . 0 .... \
24
(EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ * 8)
20
vm=%vm_dp vn=%vn_dp vd=%vd_dp
25
21
+
26
-#define EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit) ((grp)*8 + (bit))
22
+ VTBL 1111 001 1 1 . 11 .... .... 10 len:2 . op:1 . 0 .... \
27
-#define EXYNOS4210_COMBINER_GET_GRP_NUM(irq) ((irq) / 8)
23
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
28
-#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
24
]
29
- ((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
25
30
-
26
# Subgroup for size != 0b11
31
/* IRQs number for external and internal GIC */
27
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
32
#define EXYNOS4210_EXT_GIC_NIRQ (160-32)
33
#define EXYNOS4210_INT_GIC_NIRQ 64
34
@@ -XXX,XX +XXX,XX @@ void exynos4210_write_secondary(ARMCPU *cpu,
35
* bit - bit number inside group */
36
uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit);
37
38
-/*
39
- * Get Combiner input GPIO into irqs structure
40
- */
41
-void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs, DeviceState *dev,
42
- int ext);
43
-
44
/*
45
* exynos4210 UART
46
*/
47
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
28
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/translate-neon.inc.c
49
--- a/hw/arm/exynos4210.c
30
+++ b/target/arm/translate-neon.inc.c
50
+++ b/hw/arm/exynos4210.c
31
@@ -XXX,XX +XXX,XX @@ static bool trans_VEXT(DisasContext *s, arg_VEXT *a)
51
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
32
}
52
{ }, { }, { }, { }, { }, { }, { }, { }, { }, { }
33
return true;
53
};
54
55
+#define EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit) ((grp) * 8 + (bit))
56
+#define EXYNOS4210_COMBINER_GET_GRP_NUM(irq) ((irq) / 8)
57
+#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
58
+ ((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
59
+
60
/*
61
* Initialize board IRQs.
62
* These IRQs contain splitted Int/External Combiner and External Gic IRQs.
63
@@ -XXX,XX +XXX,XX @@ uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
64
return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
34
}
65
}
35
+
66
36
+static bool trans_VTBL(DisasContext *s, arg_VTBL *a)
67
+/*
68
+ * Get Combiner input GPIO into irqs structure
69
+ */
70
+static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
71
+ DeviceState *dev, int ext)
37
+{
72
+{
38
+ int n;
73
+ int n;
39
+ TCGv_i32 tmp, tmp2, tmp3, tmp4;
74
+ int bit;
40
+ TCGv_ptr ptr1;
75
+ int max;
41
+
76
+ qemu_irq *irq;
42
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
77
+
43
+ return false;
78
+ max = ext ? EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ :
79
+ EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
80
+ irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
81
+
82
+ /*
83
+ * Some IRQs of Int/External Combiner are going to two Combiners groups,
84
+ * so let split them.
85
+ */
86
+ for (n = 0; n < max; n++) {
87
+
88
+ bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
89
+
90
+ switch (n) {
91
+ /* MDNIE_LCD1 INTG1 */
92
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 0) ...
93
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 3):
94
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
95
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(0, bit + 4)]);
96
+ continue;
97
+
98
+ /* TMU INTG3 */
99
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(3, 4):
100
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
101
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(2, bit)]);
102
+ continue;
103
+
104
+ /* LCD1 INTG12 */
105
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 0) ...
106
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 3):
107
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
108
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(11, bit + 4)]);
109
+ continue;
110
+
111
+ /* Multi-Core Timer INTG12 */
112
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4) ...
113
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 8):
114
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
115
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
116
+ continue;
117
+
118
+ /* Multi-Core Timer INTG35 */
119
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 4) ...
120
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 8):
121
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
122
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
123
+ continue;
124
+
125
+ /* Multi-Core Timer INTG51 */
126
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 4) ...
127
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 8):
128
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
129
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
130
+ continue;
131
+
132
+ /* Multi-Core Timer INTG53 */
133
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 4) ...
134
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 8):
135
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
136
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
137
+ continue;
138
+ }
139
+
140
+ irq[n] = qdev_get_gpio_in(dev, n);
44
+ }
141
+ }
45
+
46
+ /* UNDEF accesses to D16-D31 if they don't exist. */
47
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
48
+ ((a->vd | a->vn | a->vm) & 0x10)) {
49
+ return false;
50
+ }
51
+
52
+ if (!vfp_access_check(s)) {
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
+}
142
+}
91
diff --git a/target/arm/translate.c b/target/arm/translate.c
143
+
144
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
145
0x09, 0x00, 0x00, 0x00 };
146
147
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
92
index XXXXXXX..XXXXXXX 100644
148
index XXXXXXX..XXXXXXX 100644
93
--- a/target/arm/translate.c
149
--- a/hw/intc/exynos4210_combiner.c
94
+++ b/target/arm/translate.c
150
+++ b/hw/intc/exynos4210_combiner.c
95
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
151
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_exynos4210_combiner = {
152
}
153
};
154
155
-/*
156
- * Get Combiner input GPIO into irqs structure
157
- */
158
-void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs, DeviceState *dev,
159
- int ext)
160
-{
161
- int n;
162
- int bit;
163
- int max;
164
- qemu_irq *irq;
165
-
166
- max = ext ? EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ :
167
- EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
168
- irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
169
-
170
- /*
171
- * Some IRQs of Int/External Combiner are going to two Combiners groups,
172
- * so let split them.
173
- */
174
- for (n = 0; n < max; n++) {
175
-
176
- bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
177
-
178
- switch (n) {
179
- /* MDNIE_LCD1 INTG1 */
180
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 0) ...
181
- EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 3):
182
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
183
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(0, bit + 4)]);
184
- continue;
185
-
186
- /* TMU INTG3 */
187
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(3, 4):
188
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
189
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(2, bit)]);
190
- continue;
191
-
192
- /* LCD1 INTG12 */
193
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 0) ...
194
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 3):
195
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
196
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(11, bit + 4)]);
197
- continue;
198
-
199
- /* Multi-Core Timer INTG12 */
200
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4) ...
201
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 8):
202
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
203
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
204
- continue;
205
-
206
- /* Multi-Core Timer INTG35 */
207
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 4) ...
208
- EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 8):
209
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
210
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
211
- continue;
212
-
213
- /* Multi-Core Timer INTG51 */
214
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 4) ...
215
- EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 8):
216
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
217
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
218
- continue;
219
-
220
- /* Multi-Core Timer INTG53 */
221
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 4) ...
222
- EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 8):
223
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
224
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
225
- continue;
226
- }
227
-
228
- irq[n] = qdev_get_gpio_in(dev, n);
229
- }
230
-}
231
-
232
static uint64_t
233
exynos4210_combiner_read(void *opaque, hwaddr offset, unsigned size)
96
{
234
{
97
int op;
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
--
235
--
162
2.20.1
236
2.25.1
163
164
diff view generated by jsdifflib
1
Convert the Neon 3-reg-diff insns VQDMULL, VQDMLAL and VQDMLSL:
1
Delete a couple of #defines which are never used.
2
these are all saturating doubling long multiplies with a possible
3
accumulate step.
4
5
These are the last insns in the group which use the pass-over-each
6
elements loop, so we can delete that code.
7
2
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20220404154658.565020-12-peter.maydell@linaro.org
10
---
6
---
11
target/arm/neon-dp.decode | 6 +++
7
include/hw/arm/exynos4210.h | 4 ----
12
target/arm/translate-neon.inc.c | 82 +++++++++++++++++++++++++++++++++
8
1 file changed, 4 deletions(-)
13
target/arm/translate.c | 59 ++----------------------
14
3 files changed, 92 insertions(+), 55 deletions(-)
15
9
16
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
10
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
17
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/neon-dp.decode
12
--- a/include/hw/arm/exynos4210.h
19
+++ b/target/arm/neon-dp.decode
13
+++ b/include/hw/arm/exynos4210.h
20
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
14
@@ -XXX,XX +XXX,XX @@
21
VMLAL_S_3d 1111 001 0 1 . .. .... .... 1000 . 0 . 0 .... @3diff
15
#define EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ \
22
VMLAL_U_3d 1111 001 1 1 . .. .... .... 1000 . 0 . 0 .... @3diff
16
(EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ * 8)
23
17
24
+ VQDMLAL_3d 1111 001 0 1 . .. .... .... 1001 . 0 . 0 .... @3diff
18
-/* IRQs number for external and internal GIC */
25
+
19
-#define EXYNOS4210_EXT_GIC_NIRQ (160-32)
26
VMLSL_S_3d 1111 001 0 1 . .. .... .... 1010 . 0 . 0 .... @3diff
20
-#define EXYNOS4210_INT_GIC_NIRQ 64
27
VMLSL_U_3d 1111 001 1 1 . .. .... .... 1010 . 0 . 0 .... @3diff
28
29
+ VQDMLSL_3d 1111 001 0 1 . .. .... .... 1011 . 0 . 0 .... @3diff
30
+
31
VMULL_S_3d 1111 001 0 1 . .. .... .... 1100 . 0 . 0 .... @3diff
32
VMULL_U_3d 1111 001 1 1 . .. .... .... 1100 . 0 . 0 .... @3diff
33
+
34
+ VQDMULL_3d 1111 001 0 1 . .. .... .... 1101 . 0 . 0 .... @3diff
35
]
36
}
37
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/translate-neon.inc.c
40
+++ b/target/arm/translate-neon.inc.c
41
@@ -XXX,XX +XXX,XX @@ DO_VMLAL(VMLAL_S,mull_s,add)
42
DO_VMLAL(VMLAL_U,mull_u,add)
43
DO_VMLAL(VMLSL_S,mull_s,sub)
44
DO_VMLAL(VMLSL_U,mull_u,sub)
45
+
46
+static void gen_VQDMULL_16(TCGv_i64 rd, TCGv_i32 rn, TCGv_i32 rm)
47
+{
48
+ gen_helper_neon_mull_s16(rd, rn, rm);
49
+ gen_helper_neon_addl_saturate_s32(rd, cpu_env, rd, rd);
50
+}
51
+
52
+static void gen_VQDMULL_32(TCGv_i64 rd, TCGv_i32 rn, TCGv_i32 rm)
53
+{
54
+ gen_mull_s32(rd, rn, rm);
55
+ gen_helper_neon_addl_saturate_s64(rd, cpu_env, rd, rd);
56
+}
57
+
58
+static bool trans_VQDMULL_3d(DisasContext *s, arg_3diff *a)
59
+{
60
+ static NeonGenTwoOpWidenFn * const opfn[] = {
61
+ NULL,
62
+ gen_VQDMULL_16,
63
+ gen_VQDMULL_32,
64
+ NULL,
65
+ };
66
+
67
+ return do_long_3d(s, a, opfn[a->size], NULL);
68
+}
69
+
70
+static void gen_VQDMLAL_acc_16(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
71
+{
72
+ gen_helper_neon_addl_saturate_s32(rd, cpu_env, rn, rm);
73
+}
74
+
75
+static void gen_VQDMLAL_acc_32(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
76
+{
77
+ gen_helper_neon_addl_saturate_s64(rd, cpu_env, rn, rm);
78
+}
79
+
80
+static bool trans_VQDMLAL_3d(DisasContext *s, arg_3diff *a)
81
+{
82
+ static NeonGenTwoOpWidenFn * const opfn[] = {
83
+ NULL,
84
+ gen_VQDMULL_16,
85
+ gen_VQDMULL_32,
86
+ NULL,
87
+ };
88
+ static NeonGenTwo64OpFn * const accfn[] = {
89
+ NULL,
90
+ gen_VQDMLAL_acc_16,
91
+ gen_VQDMLAL_acc_32,
92
+ NULL,
93
+ };
94
+
95
+ return do_long_3d(s, a, opfn[a->size], accfn[a->size]);
96
+}
97
+
98
+static void gen_VQDMLSL_acc_16(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
99
+{
100
+ gen_helper_neon_negl_u32(rm, rm);
101
+ gen_helper_neon_addl_saturate_s32(rd, cpu_env, rn, rm);
102
+}
103
+
104
+static void gen_VQDMLSL_acc_32(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
105
+{
106
+ tcg_gen_neg_i64(rm, rm);
107
+ gen_helper_neon_addl_saturate_s64(rd, cpu_env, rn, rm);
108
+}
109
+
110
+static bool trans_VQDMLSL_3d(DisasContext *s, arg_3diff *a)
111
+{
112
+ static NeonGenTwoOpWidenFn * const opfn[] = {
113
+ NULL,
114
+ gen_VQDMULL_16,
115
+ gen_VQDMULL_32,
116
+ NULL,
117
+ };
118
+ static NeonGenTwo64OpFn * const accfn[] = {
119
+ NULL,
120
+ gen_VQDMLSL_acc_16,
121
+ gen_VQDMLSL_acc_32,
122
+ NULL,
123
+ };
124
+
125
+ return do_long_3d(s, a, opfn[a->size], accfn[a->size]);
126
+}
127
diff --git a/target/arm/translate.c b/target/arm/translate.c
128
index XXXXXXX..XXXXXXX 100644
129
--- a/target/arm/translate.c
130
+++ b/target/arm/translate.c
131
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
132
{0, 0, 0, 7}, /* VSUBHN: handled by decodetree */
133
{0, 0, 0, 7}, /* VABDL */
134
{0, 0, 0, 7}, /* VMLAL */
135
- {0, 0, 0, 9}, /* VQDMLAL */
136
+ {0, 0, 0, 7}, /* VQDMLAL */
137
{0, 0, 0, 7}, /* VMLSL */
138
- {0, 0, 0, 9}, /* VQDMLSL */
139
+ {0, 0, 0, 7}, /* VQDMLSL */
140
{0, 0, 0, 7}, /* Integer VMULL */
141
- {0, 0, 0, 9}, /* VQDMULL */
142
+ {0, 0, 0, 7}, /* VQDMULL */
143
{0, 0, 0, 0xa}, /* Polynomial VMULL */
144
{0, 0, 0, 7}, /* Reserved: always UNDEF */
145
};
146
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
147
}
148
return 0;
149
}
150
-
21
-
151
- /* Avoid overlapping operands. Wide source operands are
22
#define EXYNOS4210_I2C_NUMBER 9
152
- always aligned so will never overlap with wide
23
153
- destinations in problematic ways. */
24
#define EXYNOS4210_NUM_DMA 3
154
- if (rd == rm) {
155
- tmp = neon_load_reg(rm, 1);
156
- neon_store_scratch(2, tmp);
157
- } else if (rd == rn) {
158
- tmp = neon_load_reg(rn, 1);
159
- neon_store_scratch(2, tmp);
160
- }
161
- tmp3 = NULL;
162
- for (pass = 0; pass < 2; pass++) {
163
- if (pass == 1 && rd == rn) {
164
- tmp = neon_load_scratch(2);
165
- } else {
166
- tmp = neon_load_reg(rn, pass);
167
- }
168
- if (pass == 1 && rd == rm) {
169
- tmp2 = neon_load_scratch(2);
170
- } else {
171
- tmp2 = neon_load_reg(rm, pass);
172
- }
173
- switch (op) {
174
- case 9: case 11: case 13:
175
- /* VQDMLAL, VQDMLSL, VQDMULL */
176
- gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
177
- break;
178
- default: /* 15 is RESERVED: caught earlier */
179
- abort();
180
- }
181
- if (op == 13) {
182
- /* VQDMULL */
183
- gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
184
- neon_store_reg64(cpu_V0, rd + pass);
185
- } else {
186
- /* Accumulate. */
187
- neon_load_reg64(cpu_V1, rd + pass);
188
- switch (op) {
189
- case 9: case 11: /* VQDMLAL, VQDMLSL */
190
- gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
191
- if (op == 11) {
192
- gen_neon_negl(cpu_V0, size);
193
- }
194
- gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
195
- break;
196
- default:
197
- abort();
198
- }
199
- neon_store_reg64(cpu_V0, rd + pass);
200
- }
201
- }
202
+ abort(); /* all others handled by decodetree */
203
} else {
204
/* Two registers and a scalar. NB that for ops of this form
205
* the ARM ARM labels bit 24 as Q, but it is in our variable
206
--
25
--
207
2.20.1
26
2.25.1
208
209
diff view generated by jsdifflib
1
Convert the Neon 3-reg-diff insns VMULL, VMLAL and VMLSL; these perform
1
In exynos4210_init_board_irqs(), use the TYPE_SPLIT_IRQ device
2
a 32x32->64 multiply with possible accumulate.
2
instead of qemu_irq_split().
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
3
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20220404154658.565020-13-peter.maydell@linaro.org
9
---
7
---
10
target/arm/neon-dp.decode | 9 +++++
8
include/hw/arm/exynos4210.h | 9 ++++++++
11
target/arm/translate-neon.inc.c | 71 +++++++++++++++++++++++++++++++++
9
hw/arm/exynos4210.c | 41 +++++++++++++++++++++++++++++--------
12
target/arm/translate.c | 21 +++-------
10
2 files changed, 42 insertions(+), 8 deletions(-)
13
3 files changed, 86 insertions(+), 15 deletions(-)
14
11
15
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
12
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
16
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/neon-dp.decode
14
--- a/include/hw/arm/exynos4210.h
18
+++ b/target/arm/neon-dp.decode
15
+++ b/include/hw/arm/exynos4210.h
19
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
16
@@ -XXX,XX +XXX,XX @@
20
17
#include "hw/sysbus.h"
21
VABDL_S_3d 1111 001 0 1 . .. .... .... 0111 . 0 . 0 .... @3diff
18
#include "hw/cpu/a9mpcore.h"
22
VABDL_U_3d 1111 001 1 1 . .. .... .... 0111 . 0 . 0 .... @3diff
19
#include "hw/intc/exynos4210_gic.h"
20
+#include "hw/core/split-irq.h"
21
#include "target/arm/cpu-qom.h"
22
#include "qom/object.h"
23
24
@@ -XXX,XX +XXX,XX @@
25
26
#define EXYNOS4210_NUM_DMA 3
27
28
+/*
29
+ * We need one splitter for every external combiner input, plus
30
+ * one for every non-zero entry in combiner_grp_to_gic_id[].
31
+ * We'll assert in exynos4210_init_board_irqs() if this is wrong.
32
+ */
33
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 60)
23
+
34
+
24
+ VMLAL_S_3d 1111 001 0 1 . .. .... .... 1000 . 0 . 0 .... @3diff
35
typedef struct Exynos4210Irq {
25
+ VMLAL_U_3d 1111 001 1 1 . .. .... .... 1000 . 0 . 0 .... @3diff
36
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
37
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
38
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
39
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
40
A9MPPrivState a9mpcore;
41
Exynos4210GicState ext_gic;
42
+ SplitIRQ splitter[EXYNOS4210_NUM_SPLITTERS];
43
};
44
45
#define TYPE_EXYNOS4210_SOC "exynos4210"
46
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/arm/exynos4210.c
49
+++ b/hw/arm/exynos4210.c
50
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
51
uint32_t grp, bit, irq_id, n;
52
Exynos4210Irq *is = &s->irqs;
53
DeviceState *extgicdev = DEVICE(&s->ext_gic);
54
+ int splitcount = 0;
55
+ DeviceState *splitter;
56
57
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
58
irq_id = 0;
59
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
60
/* MCT_G1 is passed to External and GIC */
61
irq_id = EXT_GIC_ID_MCT_G1;
62
}
26
+
63
+
27
+ VMLSL_S_3d 1111 001 0 1 . .. .... .... 1010 . 0 . 0 .... @3diff
64
+ assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
28
+ VMLSL_U_3d 1111 001 1 1 . .. .... .... 1010 . 0 . 0 .... @3diff
65
+ splitter = DEVICE(&s->splitter[splitcount]);
29
+
66
+ qdev_prop_set_uint16(splitter, "num-lines", 2);
30
+ VMULL_S_3d 1111 001 0 1 . .. .... .... 1100 . 0 . 0 .... @3diff
67
+ qdev_realize(splitter, NULL, &error_abort);
31
+ VMULL_U_3d 1111 001 1 1 . .. .... .... 1100 . 0 . 0 .... @3diff
68
+ splitcount++;
32
]
69
+ s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
70
+ qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
71
if (irq_id) {
72
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
73
- qdev_get_gpio_in(extgicdev,
74
- irq_id - 32));
75
+ qdev_connect_gpio_out(splitter, 1,
76
+ qdev_get_gpio_in(extgicdev, irq_id - 32));
77
} else {
78
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
79
- is->ext_combiner_irq[n]);
80
+ qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
81
}
82
}
83
for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
84
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
85
EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
86
87
if (irq_id) {
88
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
89
- qdev_get_gpio_in(extgicdev,
90
- irq_id - 32));
91
+ assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
92
+ splitter = DEVICE(&s->splitter[splitcount]);
93
+ qdev_prop_set_uint16(splitter, "num-lines", 2);
94
+ qdev_realize(splitter, NULL, &error_abort);
95
+ splitcount++;
96
+ s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
97
+ qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
98
+ qdev_connect_gpio_out(splitter, 1,
99
+ qdev_get_gpio_in(extgicdev, irq_id - 32));
100
}
101
}
102
+ /*
103
+ * We check this here to avoid a more obscure assert later when
104
+ * qdev_assert_realized_properly() checks that we realized every
105
+ * child object we initialized.
106
+ */
107
+ assert(splitcount == EXYNOS4210_NUM_SPLITTERS);
33
}
108
}
34
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
109
35
index XXXXXXX..XXXXXXX 100644
110
/*
36
--- a/target/arm/translate-neon.inc.c
111
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
37
+++ b/target/arm/translate-neon.inc.c
112
object_initialize_child(obj, name, &s->cpu_irq_orgate[i], TYPE_OR_IRQ);
38
@@ -XXX,XX +XXX,XX @@ static bool trans_VABAL_U_3d(DisasContext *s, arg_3diff *a)
113
}
39
114
40
return do_long_3d(s, a, opfn[a->size], addfn[a->size]);
115
+ for (i = 0; i < ARRAY_SIZE(s->splitter); i++) {
41
}
116
+ g_autofree char *name = g_strdup_printf("irq-splitter%d", i);
42
+
117
+ object_initialize_child(obj, name, &s->splitter[i], TYPE_SPLIT_IRQ);
43
+static void gen_mull_s32(TCGv_i64 rd, TCGv_i32 rn, TCGv_i32 rm)
44
+{
45
+ TCGv_i32 lo = tcg_temp_new_i32();
46
+ TCGv_i32 hi = tcg_temp_new_i32();
47
+
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
+ { \
94
+ static NeonGenTwoOpWidenFn * const opfn[] = { \
95
+ gen_helper_neon_##MULL##8, \
96
+ gen_helper_neon_##MULL##16, \
97
+ gen_##MULL##32, \
98
+ NULL, \
99
+ }; \
100
+ static NeonGenTwo64OpFn * const accfn[] = { \
101
+ gen_helper_neon_##ACC##l_u16, \
102
+ gen_helper_neon_##ACC##l_u32, \
103
+ tcg_gen_##ACC##_i64, \
104
+ NULL, \
105
+ }; \
106
+ return do_long_3d(s, a, opfn[a->size], accfn[a->size]); \
107
+ }
118
+ }
108
+
119
+
109
+DO_VMLAL(VMLAL_S,mull_s,add)
120
object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
110
+DO_VMLAL(VMLAL_U,mull_u,add)
121
object_initialize_child(obj, "ext-gic", &s->ext_gic, TYPE_EXYNOS4210_GIC);
111
+DO_VMLAL(VMLSL_S,mull_s,sub)
122
}
112
+DO_VMLAL(VMLSL_U,mull_u,sub)
113
diff --git a/target/arm/translate.c b/target/arm/translate.c
114
index XXXXXXX..XXXXXXX 100644
115
--- a/target/arm/translate.c
116
+++ b/target/arm/translate.c
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
--
123
--
172
2.20.1
124
2.25.1
173
174
diff view generated by jsdifflib
1
The widenfn() in do_vshll_2sh() does not free the input 32-bit
1
In exynos4210_init_board_irqs(), the loop that handles IRQ lines that
2
TCGv, so we need to do this in the calling code.
2
are in a range that applies to the internal combiner only creates a
3
splitter for those interrupts which go to both the internal combiner
4
and to the external GIC, but it does nothing at all for the
5
interrupts which don't go to the external GIC, leaving the
6
irq_table[] array element empty for those. (This will result in
7
those interrupts simply being lost, not in a QEMU crash.)
8
9
I don't have a reliable datasheet for this SoC, but since we do wire
10
up one interrupt line in this category (the HDMI I2C device on
11
interrupt 16,1), this seems like it must be a bug in the existing
12
QEMU code. Fill in the irq_table[] entries where we're not splitting
13
the IRQ to both the internal combiner and the external GIC with the
14
IRQ line of the internal combiner. (That is, these IRQ lines go to
15
just one device, not multiple.)
16
17
This bug didn't have any visible guest effects because the only
18
implemented device that was affected was the HDMI I2C controller,
19
and we never connect any I2C devices to that bus.
3
20
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
23
Message-id: 20220404154658.565020-14-peter.maydell@linaro.org
7
---
24
---
8
target/arm/translate-neon.inc.c | 2 ++
25
hw/arm/exynos4210.c | 2 ++
9
1 file changed, 2 insertions(+)
26
1 file changed, 2 insertions(+)
10
27
11
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
28
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
12
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-neon.inc.c
30
--- a/hw/arm/exynos4210.c
14
+++ b/target/arm/translate-neon.inc.c
31
+++ b/hw/arm/exynos4210.c
15
@@ -XXX,XX +XXX,XX @@ static bool do_vshll_2sh(DisasContext *s, arg_2reg_shift *a,
32
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
16
tmp = tcg_temp_new_i64();
33
qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
17
34
qdev_connect_gpio_out(splitter, 1,
18
widenfn(tmp, rm0);
35
qdev_get_gpio_in(extgicdev, irq_id - 32));
19
+ tcg_temp_free_i32(rm0);
36
+ } else {
20
if (a->shift != 0) {
37
+ s->irq_table[n] = is->int_combiner_irq[n];
21
tcg_gen_shli_i64(tmp, tmp, a->shift);
38
}
22
tcg_gen_andi_i64(tmp, tmp, ~widen_mask);
39
}
23
@@ -XXX,XX +XXX,XX @@ static bool do_vshll_2sh(DisasContext *s, arg_2reg_shift *a,
40
/*
24
neon_store_reg64(tmp, a->vd);
25
26
widenfn(tmp, rm1);
27
+ tcg_temp_free_i32(rm1);
28
if (a->shift != 0) {
29
tcg_gen_shli_i64(tmp, tmp, a->shift);
30
tcg_gen_andi_i64(tmp, tmp, ~widen_mask);
31
--
41
--
32
2.20.1
42
2.25.1
33
34
diff view generated by jsdifflib
1
Convert the Neon 3-reg-diff insns VABAL and VABDL to decodetree.
1
Currently for the interrupts MCT_G0 and MCT_G1 which are
2
Like almost all the remaining insns in this group, these are
2
the only ones in the input range of the external combiner
3
a combination of a two-input operation which returns a double width
3
and which are also wired to the external GIC, we connect
4
result and then a possible accumulation of that double width
4
them only to the internal combiner and the external GIC.
5
result into the destination.
5
This seems likely to be a bug, as all other interrupts
6
which are in the input range of both combiners are
7
connected to both combiners. (The fact that the code in
8
exynos4210_combiner_get_gpioin() is also trying to wire
9
up these inputs on both combiners also suggests this.)
10
11
Wire these interrupts up to both combiners, like the rest.
6
12
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20220404154658.565020-15-peter.maydell@linaro.org
9
---
16
---
10
target/arm/translate.h | 1 +
17
hw/arm/exynos4210.c | 7 +++----
11
target/arm/neon-dp.decode | 6 ++
18
1 file changed, 3 insertions(+), 4 deletions(-)
12
target/arm/translate-neon.inc.c | 132 ++++++++++++++++++++++++++++++++
13
target/arm/translate.c | 31 +-------
14
4 files changed, 142 insertions(+), 28 deletions(-)
15
19
16
diff --git a/target/arm/translate.h b/target/arm/translate.h
20
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
17
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate.h
22
--- a/hw/arm/exynos4210.c
19
+++ b/target/arm/translate.h
23
+++ b/hw/arm/exynos4210.c
20
@@ -XXX,XX +XXX,XX @@ typedef void NeonGenTwo64OpEnvFn(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64);
24
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
21
typedef void NeonGenNarrowFn(TCGv_i32, TCGv_i64);
25
22
typedef void NeonGenNarrowEnvFn(TCGv_i32, TCGv_ptr, TCGv_i64);
26
assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
23
typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32);
27
splitter = DEVICE(&s->splitter[splitcount]);
24
+typedef void NeonGenTwoOpWidenFn(TCGv_i64, TCGv_i32, TCGv_i32);
28
- qdev_prop_set_uint16(splitter, "num-lines", 2);
25
typedef void NeonGenTwoSingleOPFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
29
+ qdev_prop_set_uint16(splitter, "num-lines", irq_id ? 3 : 2);
26
typedef void NeonGenTwoDoubleOPFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr);
30
qdev_realize(splitter, NULL, &error_abort);
27
typedef void NeonGenOneOpFn(TCGv_i64, TCGv_i64);
31
splitcount++;
28
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
32
s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
29
index XXXXXXX..XXXXXXX 100644
33
qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
30
--- a/target/arm/neon-dp.decode
34
+ qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
31
+++ b/target/arm/neon-dp.decode
35
if (irq_id) {
32
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
36
- qdev_connect_gpio_out(splitter, 1,
33
VADDHN_3d 1111 001 0 1 . .. .... .... 0100 . 0 . 0 .... @3diff
37
+ qdev_connect_gpio_out(splitter, 2,
34
VRADDHN_3d 1111 001 1 1 . .. .... .... 0100 . 0 . 0 .... @3diff
38
qdev_get_gpio_in(extgicdev, irq_id - 32));
35
39
- } else {
36
+ VABAL_S_3d 1111 001 0 1 . .. .... .... 0101 . 0 . 0 .... @3diff
40
- qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
37
+ VABAL_U_3d 1111 001 1 1 . .. .... .... 0101 . 0 . 0 .... @3diff
41
}
38
+
42
}
39
VSUBHN_3d 1111 001 0 1 . .. .... .... 0110 . 0 . 0 .... @3diff
43
for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
40
VRSUBHN_3d 1111 001 1 1 . .. .... .... 0110 . 0 . 0 .... @3diff
41
+
42
+ VABDL_S_3d 1111 001 0 1 . .. .... .... 0111 . 0 . 0 .... @3diff
43
+ VABDL_U_3d 1111 001 1 1 . .. .... .... 0111 . 0 . 0 .... @3diff
44
]
45
}
46
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/translate-neon.inc.c
49
+++ b/target/arm/translate-neon.inc.c
50
@@ -XXX,XX +XXX,XX @@ DO_NARROW_3D(VADDHN, add, narrow, tcg_gen_extrh_i64_i32)
51
DO_NARROW_3D(VSUBHN, sub, narrow, tcg_gen_extrh_i64_i32)
52
DO_NARROW_3D(VRADDHN, add, narrow_round, gen_narrow_round_high_u32)
53
DO_NARROW_3D(VRSUBHN, sub, narrow_round, gen_narrow_round_high_u32)
54
+
55
+static bool do_long_3d(DisasContext *s, arg_3diff *a,
56
+ NeonGenTwoOpWidenFn *opfn,
57
+ NeonGenTwo64OpFn *accfn)
58
+{
59
+ /*
60
+ * 3-regs different lengths, long operations.
61
+ * These perform an operation on two inputs that returns a double-width
62
+ * result, and then possibly perform an accumulation operation of
63
+ * that result into the double-width destination.
64
+ */
65
+ TCGv_i64 rd0, rd1, tmp;
66
+ TCGv_i32 rn, rm;
67
+
68
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
69
+ return false;
70
+ }
71
+
72
+ /* UNDEF accesses to D16-D31 if they don't exist. */
73
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
74
+ ((a->vd | a->vn | a->vm) & 0x10)) {
75
+ return false;
76
+ }
77
+
78
+ if (!opfn) {
79
+ /* size == 3 case, which is an entirely different insn group */
80
+ return false;
81
+ }
82
+
83
+ if (a->vd & 1) {
84
+ return false;
85
+ }
86
+
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
188
--- a/target/arm/translate.c
189
+++ b/target/arm/translate.c
190
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
191
{0, 0, 0, 7}, /* VSUBL: handled by decodetree */
192
{0, 0, 0, 7}, /* VSUBW: handled by decodetree */
193
{0, 0, 0, 7}, /* VADDHN: handled by decodetree */
194
- {0, 0, 0, 0}, /* VABAL */
195
+ {0, 0, 0, 7}, /* VABAL */
196
{0, 0, 0, 7}, /* VSUBHN: handled by decodetree */
197
- {0, 0, 0, 0}, /* VABDL */
198
+ {0, 0, 0, 7}, /* VABDL */
199
{0, 0, 0, 0}, /* VMLAL */
200
{0, 0, 0, 9}, /* VQDMLAL */
201
{0, 0, 0, 0}, /* VMLSL */
202
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
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
--
44
--
244
2.20.1
45
2.25.1
245
246
diff view generated by jsdifflib
1
Convert the Neon VDUP (scalar) insn to decodetree. (Note that we
1
The combiner_grp_to_gic_id[] array includes the EXT_GIC_ID_MCT_G0
2
can't call this just "VDUP" as we used that already in vfp.decode for
2
and EXT_GIC_ID_MCT_G1 multiple times. This means that we will
3
the "VDUP (general purpose register" insn.)
3
connect multiple IRQs up to the same external GIC input, which
4
is not permitted. We do the same thing in the code in
5
exynos4210_init_board_irqs() because the conditionals selecting
6
an irq_id in the first loop match multiple interrupt IDs.
7
8
Overall we do this for interrupt IDs
9
(1, 4), (12, 4), (35, 4), (51, 4), (53, 4) for EXT_GIC_ID_MCT_G0
10
and
11
(1, 5), (12, 5), (35, 5), (51, 5), (53, 5) for EXT_GIC_ID_MCT_G1
12
13
These correspond to the cases for the multi-core timer that we are
14
wiring up to multiple inputs on the combiner in
15
exynos4210_combiner_get_gpioin(). That code already deals with all
16
these interrupt IDs being the same input source, so we don't need to
17
connect the external GIC interrupt for any of them except the first
18
(1, 4) and (1, 5). Remove the array entries and conditionals which
19
were incorrectly causing us to wire up extra lines.
20
21
This bug didn't cause any visible effects, because we only connect
22
up a device to the "primary" ID values (1, 4) and (1, 5), so the
23
extra lines would never be set to a level.
4
24
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Message-id: 20220404154658.565020-16-peter.maydell@linaro.org
7
---
28
---
8
target/arm/neon-dp.decode | 7 +++++++
29
include/hw/arm/exynos4210.h | 2 +-
9
target/arm/translate-neon.inc.c | 26 ++++++++++++++++++++++++++
30
hw/arm/exynos4210.c | 12 +++++-------
10
target/arm/translate.c | 25 +------------------------
31
2 files changed, 6 insertions(+), 8 deletions(-)
11
3 files changed, 34 insertions(+), 24 deletions(-)
12
32
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
33
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
14
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
35
--- a/include/hw/arm/exynos4210.h
16
+++ b/target/arm/neon-dp.decode
36
+++ b/include/hw/arm/exynos4210.h
17
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
37
@@ -XXX,XX +XXX,XX @@
18
38
* one for every non-zero entry in combiner_grp_to_gic_id[].
19
VTBL 1111 001 1 1 . 11 .... .... 10 len:2 . op:1 . 0 .... \
39
* We'll assert in exynos4210_init_board_irqs() if this is wrong.
20
vm=%vm_dp vn=%vn_dp vd=%vd_dp
40
*/
21
+
41
-#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 60)
22
+ VDUP_scalar 1111 001 1 1 . 11 index:3 1 .... 11 000 q:1 . 0 .... \
42
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 54)
23
+ vm=%vm_dp vd=%vd_dp size=0
43
24
+ VDUP_scalar 1111 001 1 1 . 11 index:2 10 .... 11 000 q:1 . 0 .... \
44
typedef struct Exynos4210Irq {
25
+ vm=%vm_dp vd=%vd_dp size=1
45
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
26
+ VDUP_scalar 1111 001 1 1 . 11 index:1 100 .... 11 000 q:1 . 0 .... \
46
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
27
+ vm=%vm_dp vd=%vd_dp size=2
28
]
29
30
# Subgroup for size != 0b11
31
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
32
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/translate-neon.inc.c
48
--- a/hw/arm/exynos4210.c
34
+++ b/target/arm/translate-neon.inc.c
49
+++ b/hw/arm/exynos4210.c
35
@@ -XXX,XX +XXX,XX @@ static bool trans_VTBL(DisasContext *s, arg_VTBL *a)
50
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
36
tcg_temp_free_i32(tmp);
51
/* int combiner group 34 */
37
return true;
52
{ EXT_GIC_ID_ONENAND_AUDI, EXT_GIC_ID_NFC },
38
}
53
/* int combiner group 35 */
39
+
54
- { 0, 0, 0, EXT_GIC_ID_MCT_L1, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
40
+static bool trans_VDUP_scalar(DisasContext *s, arg_VDUP_scalar *a)
55
+ { 0, 0, 0, EXT_GIC_ID_MCT_L1 },
41
+{
56
/* int combiner group 36 */
42
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
57
{ EXT_GIC_ID_MIXER },
43
+ return false;
58
/* int combiner group 37 */
44
+ }
59
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
45
+
60
/* groups 38-50 */
46
+ /* UNDEF accesses to D16-D31 if they don't exist. */
61
{ }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { },
47
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
62
/* int combiner group 51 */
48
+ ((a->vd | a->vm) & 0x10)) {
63
- { EXT_GIC_ID_MCT_L0, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
49
+ return false;
64
+ { EXT_GIC_ID_MCT_L0 },
50
+ }
65
/* group 52 */
51
+
66
{ },
52
+ if (a->vd & a->q) {
67
/* int combiner group 53 */
53
+ return false;
68
- { EXT_GIC_ID_WDT, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
54
+ }
69
+ { EXT_GIC_ID_WDT },
55
+
70
/* groups 54-63 */
56
+ if (!vfp_access_check(s)) {
71
{ }, { }, { }, { }, { }, { }, { }, { }, { }, { }
57
+ return true;
72
};
58
+ }
73
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
59
+
74
60
+ tcg_gen_gvec_dup_mem(a->size, neon_reg_offset(a->vd, 0),
75
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
61
+ neon_element_offset(a->vm, a->index, a->size),
76
irq_id = 0;
62
+ a->q ? 16 : 8, a->q ? 16 : 8);
77
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4) ||
63
+ return true;
78
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4)) {
64
+}
79
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4)) {
65
diff --git a/target/arm/translate.c b/target/arm/translate.c
80
/* MCT_G0 is passed to External GIC */
66
index XXXXXXX..XXXXXXX 100644
81
irq_id = EXT_GIC_ID_MCT_G0;
67
--- a/target/arm/translate.c
82
}
68
+++ b/target/arm/translate.c
83
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) ||
69
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
84
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) {
70
}
85
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5)) {
71
break;
86
/* MCT_G1 is passed to External and GIC */
72
}
87
irq_id = EXT_GIC_ID_MCT_G1;
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
}
88
}
102
--
89
--
103
2.20.1
90
2.25.1
104
105
diff view generated by jsdifflib
1
From: Jean-Christophe Dubois <jcd@tribudubois.net>
1
At this point, the function exynos4210_init_board_irqs() splits input
2
2
IRQ lines to connect them to the input combiner, output combiner and
3
Some bits of the CCM registers are non writable.
3
external GIC. The function exynos4210_combiner_get_gpioin() splits
4
4
some of the combiner input lines further to connect them to multiple
5
This was left undone in the initial commit (all bits of registers were
5
different inputs on the combiner.
6
writable).
6
7
7
Because (unlike qemu_irq_split()) the TYPE_SPLIT_IRQ device has a
8
This patch adds the required code to protect the non writable bits.
8
configurable number of outputs, we can do all this in one place, by
9
9
making exynos4210_init_board_irqs() add extra outputs to the splitter
10
Signed-off-by: Jean-Christophe Dubois <jcd@tribudubois.net>
10
device when it must be connected to more than one input on each
11
Message-id: 20200608133508.550046-1-jcd@tribudubois.net
11
combiner.
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
13
We do this with a new data structure, the combinermap, which is an
14
array each of whose elements is a list of the interrupt IDs on the
15
combiner which must be tied together. As we loop through each
16
interrupt ID, if we find that it is the first one in one of these
17
lists, we configure the splitter device with eonugh extra outputs and
18
wire them up to the other interrupt IDs in the list.
19
20
Conveniently, for all the cases where this is necessary, the
21
lowest-numbered interrupt ID in each group is in the range of the
22
external combiner, so we only need to code for this in the first of
23
the two loops in exynos4210_init_board_irqs().
24
25
The old code in exynos4210_combiner_get_gpioin() which is being
26
deleted here had several problems which don't exist in the new code
27
in its handling of the multi-core timer interrupts:
28
(1) the case labels specified bits 4 ... 8, but bit '8' doesn't
29
exist; these should have been 4 ... 7
30
(2) it used the input irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]
31
multiple times as the input of several different splitters,
32
which isn't allowed
33
(3) in an apparent cut-and-paste error, the cases for all the
34
multi-core timer inputs used "bit + 4" even though the
35
bit range for the case was (intended to be) 4 ... 7, which
36
meant it was looking at non-existent bits 8 ... 11.
37
None of these exist in the new code.
38
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
39
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
40
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
41
Message-id: 20220404154658.565020-17-peter.maydell@linaro.org
14
---
42
---
15
hw/misc/imx6ul_ccm.c | 76 ++++++++++++++++++++++++++++++++++++--------
43
include/hw/arm/exynos4210.h | 6 +-
16
1 file changed, 63 insertions(+), 13 deletions(-)
44
hw/arm/exynos4210.c | 178 +++++++++++++++++++++++-------------
17
45
2 files changed, 119 insertions(+), 65 deletions(-)
18
diff --git a/hw/misc/imx6ul_ccm.c b/hw/misc/imx6ul_ccm.c
46
47
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
19
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/misc/imx6ul_ccm.c
49
--- a/include/hw/arm/exynos4210.h
21
+++ b/hw/misc/imx6ul_ccm.c
50
+++ b/include/hw/arm/exynos4210.h
22
@@ -XXX,XX +XXX,XX @@
51
@@ -XXX,XX +XXX,XX @@
23
52
24
#include "trace.h"
53
/*
25
54
* We need one splitter for every external combiner input, plus
26
+static const uint32_t ccm_mask[CCM_MAX] = {
55
- * one for every non-zero entry in combiner_grp_to_gic_id[].
27
+ [CCM_CCR] = 0xf01fef80,
56
+ * one for every non-zero entry in combiner_grp_to_gic_id[],
28
+ [CCM_CCDR] = 0xfffeffff,
57
+ * minus one for every external combiner ID in second or later
29
+ [CCM_CSR] = 0xffffffff,
58
+ * places in a combinermap[] line.
30
+ [CCM_CCSR] = 0xfffffef2,
59
* We'll assert in exynos4210_init_board_irqs() if this is wrong.
31
+ [CCM_CACRR] = 0xfffffff8,
60
*/
32
+ [CCM_CBCDR] = 0xc1f8e000,
61
-#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 54)
33
+ [CCM_CBCMR] = 0xfc03cfff,
62
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 38)
34
+ [CCM_CSCMR1] = 0x80700000,
63
35
+ [CCM_CSCMR2] = 0xe01ff003,
64
typedef struct Exynos4210Irq {
36
+ [CCM_CSCDR1] = 0xfe00c780,
65
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
37
+ [CCM_CS1CDR] = 0xfe00fe00,
66
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
38
+ [CCM_CS2CDR] = 0xf8007000,
67
index XXXXXXX..XXXXXXX 100644
39
+ [CCM_CDCDR] = 0xf00fffff,
68
--- a/hw/arm/exynos4210.c
40
+ [CCM_CHSCCDR] = 0xfffc01ff,
69
+++ b/hw/arm/exynos4210.c
41
+ [CCM_CSCDR2] = 0xfe0001ff,
70
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
42
+ [CCM_CSCDR3] = 0xffffc1ff,
71
#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
43
+ [CCM_CDHIPR] = 0xffffffff,
72
((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
44
+ [CCM_CTOR] = 0x00000000,
73
45
+ [CCM_CLPCR] = 0xf39ff01c,
74
+/*
46
+ [CCM_CISR] = 0xfb85ffbe,
75
+ * Some interrupt lines go to multiple combiner inputs.
47
+ [CCM_CIMR] = 0xfb85ffbf,
76
+ * This data structure defines those: each array element is
48
+ [CCM_CCOSR] = 0xfe00fe00,
77
+ * a list of combiner inputs which are connected together;
49
+ [CCM_CGPR] = 0xfffc3fea,
78
+ * the one with the smallest interrupt ID value must be first.
50
+ [CCM_CCGR0] = 0x00000000,
79
+ * As with combiner_grp_to_gic_id[], we rely on (0, 0) not being
51
+ [CCM_CCGR1] = 0x00000000,
80
+ * wired to anything so we can use 0 as a terminator.
52
+ [CCM_CCGR2] = 0x00000000,
81
+ */
53
+ [CCM_CCGR3] = 0x00000000,
82
+#define IRQNO(G, B) EXYNOS4210_COMBINER_GET_IRQ_NUM(G, B)
54
+ [CCM_CCGR4] = 0x00000000,
83
+#define IRQNONE 0
55
+ [CCM_CCGR5] = 0x00000000,
84
+
56
+ [CCM_CCGR6] = 0x00000000,
85
+#define COMBINERMAP_SIZE 16
57
+ [CCM_CMEOR] = 0xafffff1f,
86
+
87
+static const int combinermap[COMBINERMAP_SIZE][6] = {
88
+ /* MDNIE_LCD1 */
89
+ { IRQNO(0, 4), IRQNO(1, 0), IRQNONE },
90
+ { IRQNO(0, 5), IRQNO(1, 1), IRQNONE },
91
+ { IRQNO(0, 6), IRQNO(1, 2), IRQNONE },
92
+ { IRQNO(0, 7), IRQNO(1, 3), IRQNONE },
93
+ /* TMU */
94
+ { IRQNO(2, 4), IRQNO(3, 4), IRQNONE },
95
+ { IRQNO(2, 5), IRQNO(3, 5), IRQNONE },
96
+ { IRQNO(2, 6), IRQNO(3, 6), IRQNONE },
97
+ { IRQNO(2, 7), IRQNO(3, 7), IRQNONE },
98
+ /* LCD1 */
99
+ { IRQNO(11, 4), IRQNO(12, 0), IRQNONE },
100
+ { IRQNO(11, 5), IRQNO(12, 1), IRQNONE },
101
+ { IRQNO(11, 6), IRQNO(12, 2), IRQNONE },
102
+ { IRQNO(11, 7), IRQNO(12, 3), IRQNONE },
103
+ /* Multi-core timer */
104
+ { IRQNO(1, 4), IRQNO(12, 4), IRQNO(35, 4), IRQNO(51, 4), IRQNO(53, 4), IRQNONE },
105
+ { IRQNO(1, 5), IRQNO(12, 5), IRQNO(35, 5), IRQNO(51, 5), IRQNO(53, 5), IRQNONE },
106
+ { IRQNO(1, 6), IRQNO(12, 6), IRQNO(35, 6), IRQNO(51, 6), IRQNO(53, 6), IRQNONE },
107
+ { IRQNO(1, 7), IRQNO(12, 7), IRQNO(35, 7), IRQNO(51, 7), IRQNO(53, 7), IRQNONE },
58
+};
108
+};
59
+
109
+
60
+static const uint32_t analog_mask[CCM_ANALOG_MAX] = {
110
+#undef IRQNO
61
+ [CCM_ANALOG_PLL_ARM] = 0xfff60f80,
111
+
62
+ [CCM_ANALOG_PLL_USB1] = 0xfffe0fbc,
112
+static const int *combinermap_entry(int irq)
63
+ [CCM_ANALOG_PLL_USB2] = 0xfffe0fbc,
113
+{
64
+ [CCM_ANALOG_PLL_SYS] = 0xfffa0ffe,
114
+ /*
65
+ [CCM_ANALOG_PLL_SYS_SS] = 0x00000000,
115
+ * If the interrupt number passed in is the first entry in some
66
+ [CCM_ANALOG_PLL_SYS_NUM] = 0xc0000000,
116
+ * line of the combinermap, return a pointer to that line;
67
+ [CCM_ANALOG_PLL_SYS_DENOM] = 0xc0000000,
117
+ * otherwise return NULL.
68
+ [CCM_ANALOG_PLL_AUDIO] = 0xffe20f80,
118
+ */
69
+ [CCM_ANALOG_PLL_AUDIO_NUM] = 0xc0000000,
119
+ int i;
70
+ [CCM_ANALOG_PLL_AUDIO_DENOM] = 0xc0000000,
120
+ for (i = 0; i < COMBINERMAP_SIZE; i++) {
71
+ [CCM_ANALOG_PLL_VIDEO] = 0xffe20f80,
121
+ if (combinermap[i][0] == irq) {
72
+ [CCM_ANALOG_PLL_VIDEO_NUM] = 0xc0000000,
122
+ return combinermap[i];
73
+ [CCM_ANALOG_PLL_VIDEO_DENOM] = 0xc0000000,
123
+ }
74
+ [CCM_ANALOG_PLL_ENET] = 0xffc20ff0,
124
+ }
75
+ [CCM_ANALOG_PFD_480] = 0x40404040,
125
+ return NULL;
76
+ [CCM_ANALOG_PFD_528] = 0x40404040,
126
+}
77
+ [PMU_MISC0] = 0x01fe8306,
127
+
78
+ [PMU_MISC1] = 0x07fcede0,
128
+static int mapline_size(const int *mapline)
79
+ [PMU_MISC2] = 0x005f5f5f,
129
+{
80
+};
130
+ /* Return number of entries in this mapline in total */
81
+
131
+ int i = 0;
82
static const char *imx6ul_ccm_reg_name(uint32_t reg)
132
+
133
+ if (!mapline) {
134
+ /* Not in the map? IRQ goes to exactly one combiner input */
135
+ return 1;
136
+ }
137
+ while (*mapline != IRQNONE) {
138
+ mapline++;
139
+ i++;
140
+ }
141
+ return i;
142
+}
143
+
144
/*
145
* Initialize board IRQs.
146
* These IRQs contain splitted Int/External Combiner and External Gic IRQs.
147
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
148
DeviceState *extgicdev = DEVICE(&s->ext_gic);
149
int splitcount = 0;
150
DeviceState *splitter;
151
+ const int *mapline;
152
+ int numlines, splitin, in;
153
154
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
155
irq_id = 0;
156
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
157
irq_id = EXT_GIC_ID_MCT_G1;
158
}
159
160
+ if (s->irq_table[n]) {
161
+ /*
162
+ * This must be some non-first entry in a combinermap line,
163
+ * and we've already filled it in.
164
+ */
165
+ continue;
166
+ }
167
+ mapline = combinermap_entry(n);
168
+ /*
169
+ * We need to connect the IRQ to multiple inputs on both combiners
170
+ * and possibly also to the external GIC.
171
+ */
172
+ numlines = 2 * mapline_size(mapline);
173
+ if (irq_id) {
174
+ numlines++;
175
+ }
176
assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
177
splitter = DEVICE(&s->splitter[splitcount]);
178
- qdev_prop_set_uint16(splitter, "num-lines", irq_id ? 3 : 2);
179
+ qdev_prop_set_uint16(splitter, "num-lines", numlines);
180
qdev_realize(splitter, NULL, &error_abort);
181
splitcount++;
182
- s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
183
- qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
184
- qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
185
+
186
+ in = n;
187
+ splitin = 0;
188
+ for (;;) {
189
+ s->irq_table[in] = qdev_get_gpio_in(splitter, 0);
190
+ qdev_connect_gpio_out(splitter, splitin, is->int_combiner_irq[in]);
191
+ qdev_connect_gpio_out(splitter, splitin + 1, is->ext_combiner_irq[in]);
192
+ splitin += 2;
193
+ if (!mapline) {
194
+ break;
195
+ }
196
+ mapline++;
197
+ in = *mapline;
198
+ if (in == IRQNONE) {
199
+ break;
200
+ }
201
+ }
202
if (irq_id) {
203
- qdev_connect_gpio_out(splitter, 2,
204
+ qdev_connect_gpio_out(splitter, splitin,
205
qdev_get_gpio_in(extgicdev, irq_id - 32));
206
}
207
}
208
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
209
irq_id = combiner_grp_to_gic_id[grp -
210
EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
211
212
+ if (s->irq_table[n]) {
213
+ /*
214
+ * This must be some non-first entry in a combinermap line,
215
+ * and we've already filled it in.
216
+ */
217
+ continue;
218
+ }
219
+
220
if (irq_id) {
221
assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
222
splitter = DEVICE(&s->splitter[splitcount]);
223
@@ -XXX,XX +XXX,XX @@ static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
224
DeviceState *dev, int ext)
83
{
225
{
84
static char unknown[20];
226
int n;
85
@@ -XXX,XX +XXX,XX @@ static void imx6ul_ccm_write(void *opaque, hwaddr offset, uint64_t value,
227
- int bit;
86
228
int max;
87
trace_ccm_write_reg(imx6ul_ccm_reg_name(index), (uint32_t)value);
229
qemu_irq *irq;
230
231
@@ -XXX,XX +XXX,XX @@ static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
232
EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
233
irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
88
234
89
- /*
235
- /*
90
- * We will do a better implementation later. In particular some bits
236
- * Some IRQs of Int/External Combiner are going to two Combiners groups,
91
- * cannot be written to.
237
- * so let split them.
92
- */
238
- */
93
- s->ccm[index] = (uint32_t)value;
239
for (n = 0; n < max; n++) {
94
+ s->ccm[index] = (s->ccm[index] & ccm_mask[index]) |
240
-
95
+ ((uint32_t)value & ~ccm_mask[index]);
241
- bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
96
}
242
-
97
243
- switch (n) {
98
static uint64_t imx6ul_analog_read(void *opaque, hwaddr offset, unsigned size)
244
- /* MDNIE_LCD1 INTG1 */
99
@@ -XXX,XX +XXX,XX @@ static void imx6ul_analog_write(void *opaque, hwaddr offset, uint64_t value,
245
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 0) ...
100
* the REG_NAME register. So we change the value of the
246
- EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 3):
101
* REG_NAME register, setting bits passed in the value.
247
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
102
*/
248
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(0, bit + 4)]);
103
- s->analog[index - 1] |= value;
249
- continue;
104
+ s->analog[index - 1] |= (value & ~analog_mask[index - 1]);
250
-
105
break;
251
- /* TMU INTG3 */
106
case CCM_ANALOG_PLL_ARM_CLR:
252
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(3, 4):
107
case CCM_ANALOG_PLL_USB1_CLR:
253
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
108
@@ -XXX,XX +XXX,XX @@ static void imx6ul_analog_write(void *opaque, hwaddr offset, uint64_t value,
254
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(2, bit)]);
109
* the REG_NAME register. So we change the value of the
255
- continue;
110
* REG_NAME register, unsetting bits passed in the value.
256
-
111
*/
257
- /* LCD1 INTG12 */
112
- s->analog[index - 2] &= ~value;
258
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 0) ...
113
+ s->analog[index - 2] &= ~(value & ~analog_mask[index - 2]);
259
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 3):
114
break;
260
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
115
case CCM_ANALOG_PLL_ARM_TOG:
261
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(11, bit + 4)]);
116
case CCM_ANALOG_PLL_USB1_TOG:
262
- continue;
117
@@ -XXX,XX +XXX,XX @@ static void imx6ul_analog_write(void *opaque, hwaddr offset, uint64_t value,
263
-
118
* the REG_NAME register. So we change the value of the
264
- /* Multi-Core Timer INTG12 */
119
* REG_NAME register, toggling bits passed in the value.
265
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4) ...
120
*/
266
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 8):
121
- s->analog[index - 3] ^= value;
267
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
122
+ s->analog[index - 3] ^= (value & ~analog_mask[index - 3]);
268
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
123
break;
269
- continue;
124
default:
270
-
125
- /*
271
- /* Multi-Core Timer INTG35 */
126
- * We will do a better implementation later. In particular some bits
272
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 4) ...
127
- * cannot be written to.
273
- EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 8):
128
- */
274
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
129
- s->analog[index] = value;
275
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
130
+ s->analog[index] = (s->analog[index] & analog_mask[index]) |
276
- continue;
131
+ (value & ~analog_mask[index]);
277
-
132
break;
278
- /* Multi-Core Timer INTG51 */
279
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 4) ...
280
- EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 8):
281
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
282
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
283
- continue;
284
-
285
- /* Multi-Core Timer INTG53 */
286
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 4) ...
287
- EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 8):
288
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
289
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
290
- continue;
291
- }
292
-
293
irq[n] = qdev_get_gpio_in(dev, n);
133
}
294
}
134
}
295
}
135
--
296
--
136
2.20.1
297
2.25.1
137
138
diff view generated by jsdifflib
1
Convert the "pre-widening" insns VADDL, VSUBL, VADDW and VSUBW
1
Switch the creation of the combiner devices to the new-style
2
in the Neon 3-registers-different-lengths group to decodetree.
2
"embedded in state struct" approach, so we can easily refer
3
These insns work by widening one or both inputs to double their
3
to the object elsewhere during realize.
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
4
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220404154658.565020-18-peter.maydell@linaro.org
13
---
8
---
14
target/arm/neon-dp.decode | 43 +++++++++++++
9
include/hw/arm/exynos4210.h | 3 ++
15
target/arm/translate-neon.inc.c | 104 ++++++++++++++++++++++++++++++++
10
include/hw/intc/exynos4210_combiner.h | 57 +++++++++++++++++++++++++++
16
target/arm/translate.c | 16 ++---
11
hw/arm/exynos4210.c | 20 +++++-----
17
3 files changed, 151 insertions(+), 12 deletions(-)
12
hw/intc/exynos4210_combiner.c | 31 +--------------
13
4 files changed, 72 insertions(+), 39 deletions(-)
14
create mode 100644 include/hw/intc/exynos4210_combiner.h
18
15
19
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
16
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
20
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/neon-dp.decode
18
--- a/include/hw/arm/exynos4210.h
22
+++ b/target/arm/neon-dp.decode
19
+++ b/include/hw/arm/exynos4210.h
23
@@ -XXX,XX +XXX,XX @@ VCVT_FU_2sh 1111 001 1 1 . ...... .... 1111 0 . . 1 .... @2reg_vcvt
20
@@ -XXX,XX +XXX,XX @@
24
# So we have a single decode line and check the cmode/op in the
21
#include "hw/sysbus.h"
25
# trans function.
22
#include "hw/cpu/a9mpcore.h"
26
Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
23
#include "hw/intc/exynos4210_gic.h"
24
+#include "hw/intc/exynos4210_combiner.h"
25
#include "hw/core/split-irq.h"
26
#include "target/arm/cpu-qom.h"
27
#include "qom/object.h"
28
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
29
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
30
A9MPPrivState a9mpcore;
31
Exynos4210GicState ext_gic;
32
+ Exynos4210CombinerState int_combiner;
33
+ Exynos4210CombinerState ext_combiner;
34
SplitIRQ splitter[EXYNOS4210_NUM_SPLITTERS];
35
};
36
37
diff --git a/include/hw/intc/exynos4210_combiner.h b/include/hw/intc/exynos4210_combiner.h
38
new file mode 100644
39
index XXXXXXX..XXXXXXX
40
--- /dev/null
41
+++ b/include/hw/intc/exynos4210_combiner.h
42
@@ -XXX,XX +XXX,XX @@
43
+/*
44
+ * Samsung exynos4210 Interrupt Combiner
45
+ *
46
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
47
+ * All rights reserved.
48
+ *
49
+ * Evgeny Voevodin <e.voevodin@samsung.com>
50
+ *
51
+ * This program is free software; you can redistribute it and/or modify it
52
+ * under the terms of the GNU General Public License as published by the
53
+ * Free Software Foundation; either version 2 of the License, or (at your
54
+ * option) any later version.
55
+ *
56
+ * This program is distributed in the hope that it will be useful,
57
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
58
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
59
+ * See the GNU General Public License for more details.
60
+ *
61
+ * You should have received a copy of the GNU General Public License along
62
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
63
+ */
27
+
64
+
28
+######################################################################
65
+#ifndef HW_INTC_EXYNOS4210_COMBINER
29
+# Within the "two registers, or three registers of different lengths"
66
+#define HW_INTC_EXYNOS4210_COMBINER
30
+# grouping ([23,4]=0b10), bits [21:20] are either part of the opcode
31
+# decode: 0b11 for VEXT, two-reg-misc, VTBL, and duplicate-scalar;
32
+# or they are a size field for the three-reg-different-lengths and
33
+# two-reg-and-scalar insn groups (where size cannot be 0b11). This
34
+# is slightly awkward for decodetree: we handle it with this
35
+# non-exclusive group which contains within it two exclusive groups:
36
+# one for the size=0b11 patterns, and one for the size-not-0b11
37
+# patterns. This allows us to check that none of the insns within
38
+# each subgroup accidentally overlap each other. Note that all the
39
+# trans functions for the size-not-0b11 patterns must check and
40
+# return false for size==3.
41
+######################################################################
42
+{
43
+ # 0b11 subgroup will go here
44
+
67
+
45
+ # Subgroup for size != 0b11
68
+#include "hw/sysbus.h"
46
+ [
47
+ ##################################################################
48
+ # 3-reg-different-length grouping:
49
+ # 1111 001 U 1 D sz!=11 Vn:4 Vd:4 opc:4 N 0 M 0 Vm:4
50
+ ##################################################################
51
+
69
+
52
+ &3diff vm vn vd size
70
+/*
71
+ * State for each output signal of internal combiner
72
+ */
73
+typedef struct CombinerGroupState {
74
+ uint8_t src_mask; /* 1 - source enabled, 0 - disabled */
75
+ uint8_t src_pending; /* Pending source interrupts before masking */
76
+} CombinerGroupState;
53
+
77
+
54
+ @3diff .... ... . . . size:2 .... .... .... . . . . .... \
78
+#define TYPE_EXYNOS4210_COMBINER "exynos4210.combiner"
55
+ &3diff vm=%vm_dp vn=%vn_dp vd=%vd_dp
79
+OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210CombinerState, EXYNOS4210_COMBINER)
56
+
80
+
57
+ VADDL_S_3d 1111 001 0 1 . .. .... .... 0000 . 0 . 0 .... @3diff
81
+/* Number of groups and total number of interrupts for the internal combiner */
58
+ VADDL_U_3d 1111 001 1 1 . .. .... .... 0000 . 0 . 0 .... @3diff
82
+#define IIC_NGRP 64
83
+#define IIC_NIRQ (IIC_NGRP * 8)
84
+#define IIC_REGSET_SIZE 0x41
59
+
85
+
60
+ VADDW_S_3d 1111 001 0 1 . .. .... .... 0001 . 0 . 0 .... @3diff
86
+struct Exynos4210CombinerState {
61
+ VADDW_U_3d 1111 001 1 1 . .. .... .... 0001 . 0 . 0 .... @3diff
87
+ SysBusDevice parent_obj;
62
+
88
+
63
+ VSUBL_S_3d 1111 001 0 1 . .. .... .... 0010 . 0 . 0 .... @3diff
89
+ MemoryRegion iomem;
64
+ VSUBL_U_3d 1111 001 1 1 . .. .... .... 0010 . 0 . 0 .... @3diff
65
+
90
+
66
+ VSUBW_S_3d 1111 001 0 1 . .. .... .... 0011 . 0 . 0 .... @3diff
91
+ struct CombinerGroupState group[IIC_NGRP];
67
+ VSUBW_U_3d 1111 001 1 1 . .. .... .... 0011 . 0 . 0 .... @3diff
92
+ uint32_t reg_set[IIC_REGSET_SIZE];
68
+ ]
93
+ uint32_t icipsr[2];
69
+}
94
+ uint32_t external; /* 1 means that this combiner is external */
70
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
95
+
96
+ qemu_irq output_irq[IIC_NGRP];
97
+};
98
+
99
+#endif
100
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
71
index XXXXXXX..XXXXXXX 100644
101
index XXXXXXX..XXXXXXX 100644
72
--- a/target/arm/translate-neon.inc.c
102
--- a/hw/arm/exynos4210.c
73
+++ b/target/arm/translate-neon.inc.c
103
+++ b/hw/arm/exynos4210.c
74
@@ -XXX,XX +XXX,XX @@ static bool trans_Vimm_1r(DisasContext *s, arg_1reg_imm *a)
104
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
75
}
105
}
76
return do_1reg_imm(s, a, fn);
106
107
/* Internal Interrupt Combiner */
108
- dev = qdev_new("exynos4210.combiner");
109
- busdev = SYS_BUS_DEVICE(dev);
110
- sysbus_realize_and_unref(busdev, &error_fatal);
111
+ busdev = SYS_BUS_DEVICE(&s->int_combiner);
112
+ sysbus_realize(busdev, &error_fatal);
113
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
114
sysbus_connect_irq(busdev, n,
115
qdev_get_gpio_in(DEVICE(&s->a9mpcore), n));
116
}
117
- exynos4210_combiner_get_gpioin(&s->irqs, dev, 0);
118
+ exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->int_combiner), 0);
119
sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
120
121
/* External Interrupt Combiner */
122
- dev = qdev_new("exynos4210.combiner");
123
- qdev_prop_set_uint32(dev, "external", 1);
124
- busdev = SYS_BUS_DEVICE(dev);
125
- sysbus_realize_and_unref(busdev, &error_fatal);
126
+ qdev_prop_set_uint32(DEVICE(&s->ext_combiner), "external", 1);
127
+ busdev = SYS_BUS_DEVICE(&s->ext_combiner);
128
+ sysbus_realize(busdev, &error_fatal);
129
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
130
sysbus_connect_irq(busdev, n, qdev_get_gpio_in(DEVICE(&s->ext_gic), n));
131
}
132
- exynos4210_combiner_get_gpioin(&s->irqs, dev, 1);
133
+ exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->ext_combiner), 1);
134
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
135
136
/* Initialize board IRQs. */
137
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
138
139
object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
140
object_initialize_child(obj, "ext-gic", &s->ext_gic, TYPE_EXYNOS4210_GIC);
141
+ object_initialize_child(obj, "int-combiner", &s->int_combiner,
142
+ TYPE_EXYNOS4210_COMBINER);
143
+ object_initialize_child(obj, "ext-combiner", &s->ext_combiner,
144
+ TYPE_EXYNOS4210_COMBINER);
77
}
145
}
78
+
146
79
+static bool do_prewiden_3d(DisasContext *s, arg_3diff *a,
147
static void exynos4210_class_init(ObjectClass *klass, void *data)
80
+ NeonGenWidenFn *widenfn,
148
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
81
+ NeonGenTwo64OpFn *opfn,
82
+ bool src1_wide)
83
+{
84
+ /* 3-regs different lengths, prewidening case (VADDL/VSUBL/VAADW/VSUBW) */
85
+ TCGv_i64 rn0_64, rn1_64, rm_64;
86
+ TCGv_i32 rm;
87
+
88
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
89
+ return false;
90
+ }
91
+
92
+ /* UNDEF accesses to D16-D31 if they don't exist. */
93
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
94
+ ((a->vd | a->vn | a->vm) & 0x10)) {
95
+ return false;
96
+ }
97
+
98
+ if (!widenfn || !opfn) {
99
+ /* size == 3 case, which is an entirely different insn group */
100
+ return false;
101
+ }
102
+
103
+ if ((a->vd & 1) || (src1_wide && (a->vn & 1))) {
104
+ return false;
105
+ }
106
+
107
+ if (!vfp_access_check(s)) {
108
+ return true;
109
+ }
110
+
111
+ rn0_64 = tcg_temp_new_i64();
112
+ rn1_64 = tcg_temp_new_i64();
113
+ rm_64 = tcg_temp_new_i64();
114
+
115
+ if (src1_wide) {
116
+ neon_load_reg64(rn0_64, a->vn);
117
+ } else {
118
+ TCGv_i32 tmp = neon_load_reg(a->vn, 0);
119
+ widenfn(rn0_64, tmp);
120
+ tcg_temp_free_i32(tmp);
121
+ }
122
+ rm = neon_load_reg(a->vm, 0);
123
+
124
+ widenfn(rm_64, rm);
125
+ tcg_temp_free_i32(rm);
126
+ opfn(rn0_64, rn0_64, rm_64);
127
+
128
+ /*
129
+ * Load second pass inputs before storing the first pass result, to
130
+ * avoid incorrect results if a narrow input overlaps with the result.
131
+ */
132
+ if (src1_wide) {
133
+ neon_load_reg64(rn1_64, a->vn + 1);
134
+ } else {
135
+ TCGv_i32 tmp = neon_load_reg(a->vn, 1);
136
+ widenfn(rn1_64, tmp);
137
+ tcg_temp_free_i32(tmp);
138
+ }
139
+ rm = neon_load_reg(a->vm, 1);
140
+
141
+ neon_store_reg64(rn0_64, a->vd);
142
+
143
+ widenfn(rm_64, rm);
144
+ tcg_temp_free_i32(rm);
145
+ opfn(rn1_64, rn1_64, rm_64);
146
+ neon_store_reg64(rn1_64, a->vd + 1);
147
+
148
+ tcg_temp_free_i64(rn0_64);
149
+ tcg_temp_free_i64(rn1_64);
150
+ tcg_temp_free_i64(rm_64);
151
+
152
+ return true;
153
+}
154
+
155
+#define DO_PREWIDEN(INSN, S, EXT, OP, SRC1WIDE) \
156
+ static bool trans_##INSN##_3d(DisasContext *s, arg_3diff *a) \
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
149
index XXXXXXX..XXXXXXX 100644
184
--- a/target/arm/translate.c
150
--- a/hw/intc/exynos4210_combiner.c
185
+++ b/target/arm/translate.c
151
+++ b/hw/intc/exynos4210_combiner.c
186
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
152
@@ -XXX,XX +XXX,XX @@
187
/* Three registers of different lengths. */
153
#include "hw/sysbus.h"
188
int src1_wide;
154
#include "migration/vmstate.h"
189
int src2_wide;
155
#include "qemu/module.h"
190
- int prewiden;
156
-
191
/* undefreq: bit 0 : UNDEF if size == 0
157
+#include "hw/intc/exynos4210_combiner.h"
192
* bit 1 : UNDEF if size == 1
158
#include "hw/arm/exynos4210.h"
193
* bit 2 : UNDEF if size == 2
159
#include "hw/hw.h"
194
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
160
#include "hw/irq.h"
195
int undefreq;
161
@@ -XXX,XX +XXX,XX @@
196
/* prewiden, src1_wide, src2_wide, undefreq */
162
#define DPRINTF(fmt, ...) do {} while (0)
197
static const int neon_3reg_wide[16][4] = {
163
#endif
198
- {1, 0, 0, 0}, /* VADDL */
164
199
- {1, 1, 0, 0}, /* VADDW */
165
-#define IIC_NGRP 64 /* Internal Interrupt Combiner
200
- {1, 0, 0, 0}, /* VSUBL */
166
- Groups number */
201
- {1, 1, 0, 0}, /* VSUBW */
167
-#define IIC_NIRQ (IIC_NGRP * 8)/* Internal Interrupt Combiner
202
+ {0, 0, 0, 7}, /* VADDL: handled by decodetree */
168
- Interrupts number */
203
+ {0, 0, 0, 7}, /* VADDW: handled by decodetree */
169
#define IIC_REGION_SIZE 0x108 /* Size of memory mapped region */
204
+ {0, 0, 0, 7}, /* VSUBL: handled by decodetree */
170
-#define IIC_REGSET_SIZE 0x41
205
+ {0, 0, 0, 7}, /* VSUBW: handled by decodetree */
171
-
206
{0, 1, 1, 0}, /* VADDHN */
172
-/*
207
{0, 0, 0, 0}, /* VABAL */
173
- * State for each output signal of internal combiner
208
{0, 1, 1, 0}, /* VSUBHN */
174
- */
209
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
175
-typedef struct CombinerGroupState {
210
{0, 0, 0, 7}, /* Reserved: always UNDEF */
176
- uint8_t src_mask; /* 1 - source enabled, 0 - disabled */
211
};
177
- uint8_t src_pending; /* Pending source interrupts before masking */
212
178
-} CombinerGroupState;
213
- prewiden = neon_3reg_wide[op][0];
179
-
214
src1_wide = neon_3reg_wide[op][1];
180
-#define TYPE_EXYNOS4210_COMBINER "exynos4210.combiner"
215
src2_wide = neon_3reg_wide[op][2];
181
-OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210CombinerState, EXYNOS4210_COMBINER)
216
undefreq = neon_3reg_wide[op][3];
182
-
217
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
183
-struct Exynos4210CombinerState {
218
} else {
184
- SysBusDevice parent_obj;
219
tmp = neon_load_reg(rn, pass);
185
-
220
}
186
- MemoryRegion iomem;
221
- if (prewiden) {
187
-
222
- gen_neon_widen(cpu_V0, tmp, size, u);
188
- struct CombinerGroupState group[IIC_NGRP];
223
- }
189
- uint32_t reg_set[IIC_REGSET_SIZE];
224
}
190
- uint32_t icipsr[2];
225
if (src2_wide) {
191
- uint32_t external; /* 1 means that this combiner is external */
226
neon_load_reg64(cpu_V1, rm + pass);
192
-
227
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
193
- qemu_irq output_irq[IIC_NGRP];
228
} else {
194
-};
229
tmp2 = neon_load_reg(rm, pass);
195
230
}
196
static const VMStateDescription vmstate_exynos4210_combiner_group_state = {
231
- if (prewiden) {
197
.name = "exynos4210.combiner.groupstate",
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
--
198
--
238
2.20.1
199
2.25.1
239
240
diff view generated by jsdifflib
1
Convert the narrow-to-high-half insns VADDHN, VSUBHN, VRADDHN,
1
The only time we use the int_combiner_irq[] and ext_combiner_irq[]
2
VRSUBHN in the Neon 3-registers-different-lengths group to
2
arrays in the Exynos4210Irq struct is during realize of the SoC -- we
3
decodetree.
3
initialize them with the input IRQs of the combiner devices, and then
4
connect those to outputs of other devices in
5
exynos4210_init_board_irqs(). Now that the combiner objects are
6
easily accessible as s->int_combiner and s->ext_combiner we can make
7
the connections directly from one device to the other without going
8
via these arrays.
9
10
Since these are the only two remaining elements of Exynos4210Irq,
11
we can remove that struct entirely.
4
12
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20220404154658.565020-19-peter.maydell@linaro.org
7
---
16
---
8
target/arm/neon-dp.decode | 6 +++
17
include/hw/arm/exynos4210.h | 6 ------
9
target/arm/translate-neon.inc.c | 87 +++++++++++++++++++++++++++++++
18
hw/arm/exynos4210.c | 34 ++++++++--------------------------
10
target/arm/translate.c | 91 ++++-----------------------------
19
2 files changed, 8 insertions(+), 32 deletions(-)
11
3 files changed, 104 insertions(+), 80 deletions(-)
12
20
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
21
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
14
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
23
--- a/include/hw/arm/exynos4210.h
16
+++ b/target/arm/neon-dp.decode
24
+++ b/include/hw/arm/exynos4210.h
17
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
25
@@ -XXX,XX +XXX,XX @@
18
26
*/
19
VSUBW_S_3d 1111 001 0 1 . .. .... .... 0011 . 0 . 0 .... @3diff
27
#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 38)
20
VSUBW_U_3d 1111 001 1 1 . .. .... .... 0011 . 0 . 0 .... @3diff
28
21
+
29
-typedef struct Exynos4210Irq {
22
+ VADDHN_3d 1111 001 0 1 . .. .... .... 0100 . 0 . 0 .... @3diff
30
- qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
23
+ VRADDHN_3d 1111 001 1 1 . .. .... .... 0100 . 0 . 0 .... @3diff
31
- qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
24
+
32
-} Exynos4210Irq;
25
+ VSUBHN_3d 1111 001 0 1 . .. .... .... 0110 . 0 . 0 .... @3diff
33
-
26
+ VRSUBHN_3d 1111 001 1 1 . .. .... .... 0110 . 0 . 0 .... @3diff
34
struct Exynos4210State {
27
]
35
/*< private >*/
36
SysBusDevice parent_obj;
37
/*< public >*/
38
ARMCPU *cpu[EXYNOS4210_NCPUS];
39
- Exynos4210Irq irqs;
40
qemu_irq irq_table[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
41
42
MemoryRegion chipid_mem;
43
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/arm/exynos4210.c
46
+++ b/hw/arm/exynos4210.c
47
@@ -XXX,XX +XXX,XX @@ static int mapline_size(const int *mapline)
48
static void exynos4210_init_board_irqs(Exynos4210State *s)
49
{
50
uint32_t grp, bit, irq_id, n;
51
- Exynos4210Irq *is = &s->irqs;
52
DeviceState *extgicdev = DEVICE(&s->ext_gic);
53
+ DeviceState *intcdev = DEVICE(&s->int_combiner);
54
+ DeviceState *extcdev = DEVICE(&s->ext_combiner);
55
int splitcount = 0;
56
DeviceState *splitter;
57
const int *mapline;
58
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
59
splitin = 0;
60
for (;;) {
61
s->irq_table[in] = qdev_get_gpio_in(splitter, 0);
62
- qdev_connect_gpio_out(splitter, splitin, is->int_combiner_irq[in]);
63
- qdev_connect_gpio_out(splitter, splitin + 1, is->ext_combiner_irq[in]);
64
+ qdev_connect_gpio_out(splitter, splitin,
65
+ qdev_get_gpio_in(intcdev, in));
66
+ qdev_connect_gpio_out(splitter, splitin + 1,
67
+ qdev_get_gpio_in(extcdev, in));
68
splitin += 2;
69
if (!mapline) {
70
break;
71
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
72
qdev_realize(splitter, NULL, &error_abort);
73
splitcount++;
74
s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
75
- qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
76
+ qdev_connect_gpio_out(splitter, 0, qdev_get_gpio_in(intcdev, n));
77
qdev_connect_gpio_out(splitter, 1,
78
qdev_get_gpio_in(extgicdev, irq_id - 32));
79
} else {
80
- s->irq_table[n] = is->int_combiner_irq[n];
81
+ s->irq_table[n] = qdev_get_gpio_in(intcdev, n);
82
}
83
}
84
/*
85
@@ -XXX,XX +XXX,XX @@ uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
86
return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
28
}
87
}
29
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
88
30
index XXXXXXX..XXXXXXX 100644
89
-/*
31
--- a/target/arm/translate-neon.inc.c
90
- * Get Combiner input GPIO into irqs structure
32
+++ b/target/arm/translate-neon.inc.c
91
- */
33
@@ -XXX,XX +XXX,XX @@ DO_PREWIDEN(VADDW_S, s, ext, add, true)
92
-static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
34
DO_PREWIDEN(VADDW_U, u, extu, add, true)
93
- DeviceState *dev, int ext)
35
DO_PREWIDEN(VSUBW_S, s, ext, sub, true)
36
DO_PREWIDEN(VSUBW_U, u, extu, sub, true)
37
+
38
+static bool do_narrow_3d(DisasContext *s, arg_3diff *a,
39
+ NeonGenTwo64OpFn *opfn, NeonGenNarrowFn *narrowfn)
40
+{
41
+ /* 3-regs different lengths, narrowing (VADDHN/VSUBHN/VRADDHN/VRSUBHN) */
42
+ TCGv_i64 rn_64, rm_64;
43
+ TCGv_i32 rd0, rd1;
44
+
45
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
46
+ return false;
47
+ }
48
+
49
+ /* UNDEF accesses to D16-D31 if they don't exist. */
50
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
51
+ ((a->vd | a->vn | a->vm) & 0x10)) {
52
+ return false;
53
+ }
54
+
55
+ if (!opfn || !narrowfn) {
56
+ /* size == 3 case, which is an entirely different insn group */
57
+ return false;
58
+ }
59
+
60
+ if ((a->vn | a->vm) & 1) {
61
+ return false;
62
+ }
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
-{
94
-{
134
- switch (size) {
95
- int n;
135
- case 0: gen_helper_neon_subl_u16(CPU_V001); break;
96
- int max;
136
- case 1: gen_helper_neon_subl_u32(CPU_V001); break;
97
- qemu_irq *irq;
137
- case 2: tcg_gen_sub_i64(CPU_V001); break;
98
-
138
- default: abort();
99
- max = ext ? EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ :
100
- EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
101
- irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
102
-
103
- for (n = 0; n < max; n++) {
104
- irq[n] = qdev_get_gpio_in(dev, n);
139
- }
105
- }
140
-}
106
-}
141
-
107
-
142
static inline void gen_neon_negl(TCGv_i64 var, int size)
108
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
143
{
109
0x09, 0x00, 0x00, 0x00 };
144
switch (size) {
110
145
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
111
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
146
op = (insn >> 8) & 0xf;
112
sysbus_connect_irq(busdev, n,
147
if ((insn & (1 << 6)) == 0) {
113
qdev_get_gpio_in(DEVICE(&s->a9mpcore), n));
148
/* Three registers of different lengths. */
114
}
149
- int src1_wide;
115
- exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->int_combiner), 0);
150
- int src2_wide;
116
sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
151
/* undefreq: bit 0 : UNDEF if size == 0
117
152
* bit 1 : UNDEF if size == 1
118
/* External Interrupt Combiner */
153
* bit 2 : UNDEF if size == 2
119
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
154
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
120
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
155
{0, 0, 0, 7}, /* VADDW: handled by decodetree */
121
sysbus_connect_irq(busdev, n, qdev_get_gpio_in(DEVICE(&s->ext_gic), n));
156
{0, 0, 0, 7}, /* VSUBL: handled by decodetree */
122
}
157
{0, 0, 0, 7}, /* VSUBW: handled by decodetree */
123
- exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->ext_combiner), 1);
158
- {0, 1, 1, 0}, /* VADDHN */
124
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
159
+ {0, 0, 0, 7}, /* VADDHN: handled by decodetree */
125
160
{0, 0, 0, 0}, /* VABAL */
126
/* Initialize board IRQs. */
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
--
127
--
281
2.20.1
128
2.25.1
282
283
diff view generated by jsdifflib
1
Convert the float versions of VMLA, VMLS and VMUL in the Neon
1
From: Zongyuan Li <zongyuan.li@smartx.com>
2
2-reg-scalar group to decodetree.
3
2
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20220324181557.203805-2-zongyuan.li@smartx.com
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
---
7
---
6
As noted in the comment on the WRAP_FP_FN macro, we could have
8
hw/arm/realview.c | 33 ++++++++++++++++++++++++---------
7
had a do_2scalar_fp() function, but for 3 insns it seemed
9
1 file changed, 24 insertions(+), 9 deletions(-)
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>
11
---
12
target/arm/neon-dp.decode | 3 ++
13
target/arm/translate-neon.inc.c | 65 +++++++++++++++++++++++++++++++++
14
target/arm/translate.c | 37 ++-----------------
15
3 files changed, 71 insertions(+), 34 deletions(-)
16
10
17
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
11
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
18
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/neon-dp.decode
13
--- a/hw/arm/realview.c
20
+++ b/target/arm/neon-dp.decode
14
+++ b/hw/arm/realview.c
21
@@ -XXX,XX +XXX,XX @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
15
@@ -XXX,XX +XXX,XX @@
22
&2scalar vm=%vm_dp vn=%vn_dp vd=%vd_dp
16
#include "hw/sysbus.h"
23
17
#include "hw/arm/boot.h"
24
VMLA_2sc 1111 001 . 1 . .. .... .... 0000 . 1 . 0 .... @2scalar
18
#include "hw/arm/primecell.h"
25
+ VMLA_F_2sc 1111 001 . 1 . .. .... .... 0001 . 1 . 0 .... @2scalar
19
+#include "hw/core/split-irq.h"
26
20
#include "hw/net/lan9118.h"
27
VMLS_2sc 1111 001 . 1 . .. .... .... 0100 . 1 . 0 .... @2scalar
21
#include "hw/net/smc91c111.h"
28
+ VMLS_F_2sc 1111 001 . 1 . .. .... .... 0101 . 1 . 0 .... @2scalar
22
#include "hw/pci/pci.h"
29
23
+#include "hw/qdev-core.h"
30
VMUL_2sc 1111 001 . 1 . .. .... .... 1000 . 1 . 0 .... @2scalar
24
#include "net/net.h"
31
+ VMUL_F_2sc 1111 001 . 1 . .. .... .... 1001 . 1 . 0 .... @2scalar
25
#include "sysemu/sysemu.h"
32
]
26
#include "hw/boards.h"
33
}
27
@@ -XXX,XX +XXX,XX @@ static const int realview_board_id[] = {
34
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
28
0x76d
35
index XXXXXXX..XXXXXXX 100644
29
};
36
--- a/target/arm/translate-neon.inc.c
30
37
+++ b/target/arm/translate-neon.inc.c
31
+static void split_irq_from_named(DeviceState *src, const char* outname,
38
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLS_2sc(DisasContext *s, arg_2scalar *a)
32
+ qemu_irq out1, qemu_irq out2) {
39
33
+ DeviceState *splitter = qdev_new(TYPE_SPLIT_IRQ);
40
return do_2scalar(s, a, opfn[a->size], accfn[a->size]);
41
}
42
+
34
+
43
+/*
35
+ qdev_prop_set_uint32(splitter, "num-lines", 2);
44
+ * Rather than have a float-specific version of do_2scalar just for
45
+ * three insns, we wrap a NeonGenTwoSingleOpFn to turn it into
46
+ * a NeonGenTwoOpFn.
47
+ */
48
+#define WRAP_FP_FN(WRAPNAME, FUNC) \
49
+ static void WRAPNAME(TCGv_i32 rd, TCGv_i32 rn, TCGv_i32 rm) \
50
+ { \
51
+ TCGv_ptr fpstatus = get_fpstatus_ptr(1); \
52
+ FUNC(rd, rn, rm, fpstatus); \
53
+ tcg_temp_free_ptr(fpstatus); \
54
+ }
55
+
36
+
56
+WRAP_FP_FN(gen_VMUL_F_mul, gen_helper_vfp_muls)
37
+ qdev_realize_and_unref(splitter, NULL, &error_fatal);
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
+
38
+
60
+static bool trans_VMUL_F_2sc(DisasContext *s, arg_2scalar *a)
39
+ qdev_connect_gpio_out(splitter, 0, out1);
61
+{
40
+ qdev_connect_gpio_out(splitter, 1, out2);
62
+ static NeonGenTwoOpFn * const opfn[] = {
41
+ qdev_connect_gpio_out_named(src, outname, 0,
63
+ NULL,
42
+ qdev_get_gpio_in(splitter, 0));
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
+}
43
+}
71
+
44
+
72
+static bool trans_VMLA_F_2sc(DisasContext *s, arg_2scalar *a)
45
static void realview_init(MachineState *machine,
73
+{
46
enum realview_board_type board_type)
74
+ static NeonGenTwoOpFn * const opfn[] = {
47
{
75
+ NULL,
48
@@ -XXX,XX +XXX,XX @@ static void realview_init(MachineState *machine,
76
+ NULL, /* TODO: fp16 support */
49
DeviceState *dev, *sysctl, *gpio2, *pl041;
77
+ gen_VMUL_F_mul,
50
SysBusDevice *busdev;
78
+ NULL,
51
qemu_irq pic[64];
79
+ };
52
- qemu_irq mmc_irq[2];
80
+ static NeonGenTwoOpFn * const accfn[] = {
53
PCIBus *pci_bus = NULL;
81
+ NULL,
54
NICInfo *nd;
82
+ NULL, /* TODO: fp16 support */
55
DriveInfo *dinfo;
83
+ gen_VMUL_F_add,
56
@@ -XXX,XX +XXX,XX @@ static void realview_init(MachineState *machine,
84
+ NULL,
57
* and the PL061 has them the other way about. Also the card
85
+ };
58
* detect line is inverted.
59
*/
60
- mmc_irq[0] = qemu_irq_split(
61
- qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT),
62
- qdev_get_gpio_in(gpio2, 1));
63
- mmc_irq[1] = qemu_irq_split(
64
- qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN),
65
- qemu_irq_invert(qdev_get_gpio_in(gpio2, 0)));
66
- qdev_connect_gpio_out_named(dev, "card-read-only", 0, mmc_irq[0]);
67
- qdev_connect_gpio_out_named(dev, "card-inserted", 0, mmc_irq[1]);
68
+ split_irq_from_named(dev, "card-read-only",
69
+ qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT),
70
+ qdev_get_gpio_in(gpio2, 1));
86
+
71
+
87
+ return do_2scalar(s, a, opfn[a->size], accfn[a->size]);
72
+ split_irq_from_named(dev, "card-inserted",
88
+}
73
+ qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN),
74
+ qemu_irq_invert(qdev_get_gpio_in(gpio2, 0)));
89
+
75
+
90
+static bool trans_VMLS_F_2sc(DisasContext *s, arg_2scalar *a)
76
dinfo = drive_get(IF_SD, 0, 0);
91
+{
77
if (dinfo) {
92
+ static NeonGenTwoOpFn * const opfn[] = {
78
DeviceState *card;
93
+ NULL,
94
+ NULL, /* TODO: fp16 support */
95
+ gen_VMUL_F_mul,
96
+ NULL,
97
+ };
98
+ static NeonGenTwoOpFn * const accfn[] = {
99
+ NULL,
100
+ NULL, /* TODO: fp16 support */
101
+ gen_VMUL_F_sub,
102
+ NULL,
103
+ };
104
+
105
+ return do_2scalar(s, a, opfn[a->size], accfn[a->size]);
106
+}
107
diff --git a/target/arm/translate.c b/target/arm/translate.c
108
index XXXXXXX..XXXXXXX 100644
109
--- a/target/arm/translate.c
110
+++ b/target/arm/translate.c
111
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
112
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
+
126
case 12: /* VQDMULH scalar */
127
case 13: /* VQRDMULH scalar */
128
if (u && ((rd | rn) & 1)) {
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
--
79
--
173
2.20.1
80
2.25.1
174
175
diff view generated by jsdifflib
New patch
1
From: Zongyuan Li <zongyuan.li@smartx.com>
1
2
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20220324181557.203805-3-zongyuan.li@smartx.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
8
hw/arm/stellaris.c | 15 +++++++++++++--
9
1 file changed, 13 insertions(+), 2 deletions(-)
10
11
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/stellaris.c
14
+++ b/hw/arm/stellaris.c
15
@@ -XXX,XX +XXX,XX @@
16
17
#include "qemu/osdep.h"
18
#include "qapi/error.h"
19
+#include "hw/core/split-irq.h"
20
#include "hw/sysbus.h"
21
#include "hw/sd/sd.h"
22
#include "hw/ssi/ssi.h"
23
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
24
DeviceState *ssddev;
25
DriveInfo *dinfo;
26
DeviceState *carddev;
27
+ DeviceState *gpio_d_splitter;
28
BlockBackend *blk;
29
30
/*
31
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
32
&error_fatal);
33
34
ssddev = ssi_create_peripheral(bus, "ssd0323");
35
- gpio_out[GPIO_D][0] = qemu_irq_split(
36
- qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0),
37
+
38
+ gpio_d_splitter = qdev_new(TYPE_SPLIT_IRQ);
39
+ qdev_prop_set_uint32(gpio_d_splitter, "num-lines", 2);
40
+ qdev_realize_and_unref(gpio_d_splitter, NULL, &error_fatal);
41
+ qdev_connect_gpio_out(
42
+ gpio_d_splitter, 0,
43
+ qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0));
44
+ qdev_connect_gpio_out(
45
+ gpio_d_splitter, 1,
46
qdev_get_gpio_in_named(ssddev, SSI_GPIO_CS, 0));
47
+ gpio_out[GPIO_D][0] = qdev_get_gpio_in(gpio_d_splitter, 0);
48
+
49
gpio_out[GPIO_C][7] = qdev_get_gpio_in(ssddev, 0);
50
51
/* Make sure the select pin is high. */
52
--
53
2.25.1
diff view generated by jsdifflib
New patch
1
From: Zongyuan Li <zongyuan.li@smartx.com>
1
2
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
5
Message-id: 20220324181557.203805-5-zongyuan.li@smartx.com
6
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/811
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
include/hw/irq.h | 5 -----
10
hw/core/irq.c | 15 ---------------
11
2 files changed, 20 deletions(-)
12
13
diff --git a/include/hw/irq.h b/include/hw/irq.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/include/hw/irq.h
16
+++ b/include/hw/irq.h
17
@@ -XXX,XX +XXX,XX @@ void qemu_free_irq(qemu_irq irq);
18
/* Returns a new IRQ with opposite polarity. */
19
qemu_irq qemu_irq_invert(qemu_irq irq);
20
21
-/* Returns a new IRQ which feeds into both the passed IRQs.
22
- * It's probably better to use the TYPE_SPLIT_IRQ device instead.
23
- */
24
-qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2);
25
-
26
/* For internal use in qtest. Similar to qemu_irq_split, but operating
27
on an existing vector of qemu_irq. */
28
void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n);
29
diff --git a/hw/core/irq.c b/hw/core/irq.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/core/irq.c
32
+++ b/hw/core/irq.c
33
@@ -XXX,XX +XXX,XX @@ qemu_irq qemu_irq_invert(qemu_irq irq)
34
return qemu_allocate_irq(qemu_notirq, irq, 0);
35
}
36
37
-static void qemu_splitirq(void *opaque, int line, int level)
38
-{
39
- struct IRQState **irq = opaque;
40
- irq[0]->handler(irq[0]->opaque, irq[0]->n, level);
41
- irq[1]->handler(irq[1]->opaque, irq[1]->n, level);
42
-}
43
-
44
-qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2)
45
-{
46
- qemu_irq *s = g_new0(qemu_irq, 2);
47
- s[0] = irq1;
48
- s[1] = irq2;
49
- return qemu_allocate_irq(qemu_splitirq, s, 0);
50
-}
51
-
52
void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n)
53
{
54
int i;
55
--
56
2.25.1
diff view generated by jsdifflib
New patch
1
From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
1
2
3
Describe that the gic-version influences the maximum number of CPUs.
4
5
Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
6
Message-id: 20220413231456.35811-1-heinrich.schuchardt@canonical.com
7
[PMM: minor punctuation tweaks]
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
docs/system/arm/virt.rst | 4 ++--
12
1 file changed, 2 insertions(+), 2 deletions(-)
13
14
diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
15
index XXXXXXX..XXXXXXX 100644
16
--- a/docs/system/arm/virt.rst
17
+++ b/docs/system/arm/virt.rst
18
@@ -XXX,XX +XXX,XX @@ gic-version
19
Valid values are:
20
21
``2``
22
- GICv2
23
+ GICv2. Note that this limits the number of CPUs to 8.
24
``3``
25
- GICv3
26
+ GICv3. This allows up to 512 CPUs.
27
``host``
28
Use the same GIC version the host provides, when using KVM
29
``max``
30
--
31
2.25.1
diff view generated by jsdifflib
1
From: Erik Smit <erik.lucas.smit@gmail.com>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
The hardware supports configurable descriptor sizes, configured in the DBLAC
3
Similar to the Aspeed code in include/misc/aspeed_scu.h, we define
4
register.
4
the PWRON STRAP fields in their corresponding module for NPCM7XX.
5
5
6
Most drivers use the default 4 word descriptor, which is currently hardcoded,
6
Signed-off-by: Hao Wu <wuhaotsh@google.com>
7
but Aspeed SDK configures 8 words to store extra data.
7
Reviewed-by: Patrick Venture <venture@google.com>
8
8
Message-id: 20220411165842.3912945-2-wuhaotsh@google.com
9
Signed-off-by: Erik Smit <erik.lucas.smit@gmail.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
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>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
11
---
14
hw/net/ftgmac100.c | 26 ++++++++++++++++++++++++--
12
include/hw/misc/npcm7xx_gcr.h | 30 ++++++++++++++++++++++++++++++
15
1 file changed, 24 insertions(+), 2 deletions(-)
13
1 file changed, 30 insertions(+)
16
14
17
diff --git a/hw/net/ftgmac100.c b/hw/net/ftgmac100.c
15
diff --git a/include/hw/misc/npcm7xx_gcr.h b/include/hw/misc/npcm7xx_gcr.h
18
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/net/ftgmac100.c
17
--- a/include/hw/misc/npcm7xx_gcr.h
20
+++ b/hw/net/ftgmac100.c
18
+++ b/include/hw/misc/npcm7xx_gcr.h
21
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
22
#define FTGMAC100_APTC_TXPOLL_CNT(x) (((x) >> 8) & 0xf)
20
#include "exec/memory.h"
23
#define FTGMAC100_APTC_TXPOLL_TIME_SEL (1 << 12)
21
#include "hw/sysbus.h"
24
22
25
+/*
23
+/*
26
+ * DMA burst length and arbitration control register
24
+ * NPCM7XX PWRON STRAP bit fields
25
+ * 12: SPI0 powered by VSBV3 at 1.8V
26
+ * 11: System flash attached to BMC
27
+ * 10: BSP alternative pins.
28
+ * 9:8: Flash UART command route enabled.
29
+ * 7: Security enabled.
30
+ * 6: HI-Z state control.
31
+ * 5: ECC disabled.
32
+ * 4: Reserved
33
+ * 3: JTAG2 enabled.
34
+ * 2:0: CPU and DRAM clock frequency.
27
+ */
35
+ */
28
+#define FTGMAC100_DBLAC_RXBURST_SIZE(x) (((x) >> 8) & 0x3)
36
+#define NPCM7XX_PWRON_STRAP_SPI0F18 BIT(12)
29
+#define FTGMAC100_DBLAC_TXBURST_SIZE(x) (((x) >> 10) & 0x3)
37
+#define NPCM7XX_PWRON_STRAP_SFAB BIT(11)
30
+#define FTGMAC100_DBLAC_RXDES_SIZE(x) ((((x) >> 12) & 0xf) * 8)
38
+#define NPCM7XX_PWRON_STRAP_BSPA BIT(10)
31
+#define FTGMAC100_DBLAC_TXDES_SIZE(x) ((((x) >> 16) & 0xf) * 8)
39
+#define NPCM7XX_PWRON_STRAP_FUP(x) ((x) << 8)
32
+#define FTGMAC100_DBLAC_IFG_CNT(x) (((x) >> 20) & 0x7)
40
+#define FUP_NORM_UART2 3
33
+#define FTGMAC100_DBLAC_IFG_INC (1 << 23)
41
+#define FUP_PROG_UART3 2
42
+#define FUP_PROG_UART2 1
43
+#define FUP_NORM_UART3 0
44
+#define NPCM7XX_PWRON_STRAP_SECEN BIT(7)
45
+#define NPCM7XX_PWRON_STRAP_HIZ BIT(6)
46
+#define NPCM7XX_PWRON_STRAP_ECC BIT(5)
47
+#define NPCM7XX_PWRON_STRAP_RESERVE1 BIT(4)
48
+#define NPCM7XX_PWRON_STRAP_J2EN BIT(3)
49
+#define NPCM7XX_PWRON_STRAP_CKFRQ(x) (x)
50
+#define CKFRQ_SKIPINIT 0x000
51
+#define CKFRQ_DEFAULT 0x111
34
+
52
+
35
/*
53
/*
36
* PHY control register
54
* Number of registers in our device state structure. Don't change this without
37
*/
55
* incrementing the version_id in the vmstate.
38
@@ -XXX,XX +XXX,XX @@ static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring,
39
if (bd.des0 & s->txdes0_edotr) {
40
addr = tx_ring;
41
} else {
42
- addr += sizeof(FTGMAC100Desc);
43
+ addr += FTGMAC100_DBLAC_TXDES_SIZE(s->dblac);
44
}
45
}
46
47
@@ -XXX,XX +XXX,XX @@ static void ftgmac100_write(void *opaque, hwaddr addr,
48
s->phydata = value & 0xffff;
49
break;
50
case FTGMAC100_DBLAC: /* DMA Burst Length and Arbitration Control */
51
+ if (FTGMAC100_DBLAC_TXDES_SIZE(s->dblac) < sizeof(FTGMAC100Desc)) {
52
+ qemu_log_mask(LOG_GUEST_ERROR,
53
+ "%s: transmit descriptor too small : %d bytes\n",
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
--
56
--
76
2.20.1
57
2.25.1
77
78
diff view generated by jsdifflib
1
From: Guenter Roeck <linux@roeck-us.net>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
Set vendor property to IMX to enable IMX specific functionality
3
This patch uses the defined fields to describe PWRON STRAPs for
4
in sdhci code.
4
better readability.
5
5
6
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Signed-off-by: Hao Wu <wuhaotsh@google.com>
7
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
7
Reviewed-by: Patrick Venture <venture@google.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20220411165842.3912945-3-wuhaotsh@google.com
9
Message-id: 20200603145258.195920-3-linux@roeck-us.net
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
11
---
12
hw/arm/fsl-imx25.c | 6 ++++++
12
hw/arm/npcm7xx_boards.c | 24 +++++++++++++++++++-----
13
hw/arm/fsl-imx6.c | 6 ++++++
13
1 file changed, 19 insertions(+), 5 deletions(-)
14
hw/arm/fsl-imx6ul.c | 2 ++
15
hw/arm/fsl-imx7.c | 2 ++
16
4 files changed, 16 insertions(+)
17
14
18
diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c
15
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
19
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/fsl-imx25.c
17
--- a/hw/arm/npcm7xx_boards.c
21
+++ b/hw/arm/fsl-imx25.c
18
+++ b/hw/arm/npcm7xx_boards.c
22
@@ -XXX,XX +XXX,XX @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
19
@@ -XXX,XX +XXX,XX @@
23
&err);
20
#include "sysemu/sysemu.h"
24
object_property_set_uint(OBJECT(&s->esdhc[i]), IMX25_ESDHC_CAPABILITIES,
21
#include "sysemu/block-backend.h"
25
"capareg", &err);
22
26
+ object_property_set_uint(OBJECT(&s->esdhc[i]), SDHCI_VENDOR_IMX,
23
-#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
27
+ "vendor", &err);
24
-#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
28
+ if (err) {
25
-#define QUANTA_GBS_POWER_ON_STRAPS 0x000017ff
29
+ error_propagate(errp, err);
26
-#define KUDO_BMC_POWER_ON_STRAPS 0x00001fff
30
+ return;
27
-#define MORI_BMC_POWER_ON_STRAPS 0x00001fff
31
+ }
28
+#define NPCM7XX_POWER_ON_STRAPS_DEFAULT ( \
32
object_property_set_bool(OBJECT(&s->esdhc[i]), true, "realized", &err);
29
+ NPCM7XX_PWRON_STRAP_SPI0F18 | \
33
if (err) {
30
+ NPCM7XX_PWRON_STRAP_SFAB | \
34
error_propagate(errp, err);
31
+ NPCM7XX_PWRON_STRAP_BSPA | \
35
diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c
32
+ NPCM7XX_PWRON_STRAP_FUP(FUP_NORM_UART2) | \
36
index XXXXXXX..XXXXXXX 100644
33
+ NPCM7XX_PWRON_STRAP_SECEN | \
37
--- a/hw/arm/fsl-imx6.c
34
+ NPCM7XX_PWRON_STRAP_HIZ | \
38
+++ b/hw/arm/fsl-imx6.c
35
+ NPCM7XX_PWRON_STRAP_ECC | \
39
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
36
+ NPCM7XX_PWRON_STRAP_RESERVE1 | \
40
&err);
37
+ NPCM7XX_PWRON_STRAP_J2EN | \
41
object_property_set_uint(OBJECT(&s->esdhc[i]), IMX6_ESDHC_CAPABILITIES,
38
+ NPCM7XX_PWRON_STRAP_CKFRQ(CKFRQ_DEFAULT))
42
"capareg", &err);
39
+
43
+ object_property_set_uint(OBJECT(&s->esdhc[i]), SDHCI_VENDOR_IMX,
40
+#define NPCM750_EVB_POWER_ON_STRAPS ( \
44
+ "vendor", &err);
41
+ NPCM7XX_POWER_ON_STRAPS_DEFAULT & ~NPCM7XX_PWRON_STRAP_J2EN)
45
+ if (err) {
42
+#define QUANTA_GSJ_POWER_ON_STRAPS NPCM7XX_POWER_ON_STRAPS_DEFAULT
46
+ error_propagate(errp, err);
43
+#define QUANTA_GBS_POWER_ON_STRAPS ( \
47
+ return;
44
+ NPCM7XX_POWER_ON_STRAPS_DEFAULT & ~NPCM7XX_PWRON_STRAP_SFAB)
48
+ }
45
+#define KUDO_BMC_POWER_ON_STRAPS NPCM7XX_POWER_ON_STRAPS_DEFAULT
49
object_property_set_bool(OBJECT(&s->esdhc[i]), true, "realized", &err);
46
+#define MORI_BMC_POWER_ON_STRAPS NPCM7XX_POWER_ON_STRAPS_DEFAULT
50
if (err) {
47
51
error_propagate(errp, err);
48
static const char npcm7xx_default_bootrom[] = "npcm7xx_bootrom.bin";
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
49
78
--
50
--
79
2.20.1
51
2.25.1
80
81
diff view generated by jsdifflib