1
target-arm queue: I have a lot more still in my to-review
1
The following changes since commit 53f306f316549d20c76886903181413d20842423:
2
queue, but my rule of thumb is when I get to 50 patches or
3
so to send out what I have.
4
2
5
thanks
3
Merge remote-tracking branch 'remotes/ehabkost-gl/tags/x86-next-pull-request' into staging (2021-06-21 11:26:04 +0100)
6
-- PMM
7
8
The following changes since commit 9a7beaad3dbba982f7a461d676b55a5c3851d312:
9
10
Merge remote-tracking branch 'remotes/alistair/tags/pull-riscv-to-apply-20210304' into staging (2021-03-05 10:47:46 +0000)
11
4
12
are available in the Git repository at:
5
are available in the Git repository at:
13
6
14
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210305
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210621
15
8
16
for you to fetch changes up to 2c669ff88ec6733420a000103a2b8b9e93df4945:
9
for you to fetch changes up to a83f1d9263d281f938a3984cda7104d55affd43a:
17
10
18
hw/arm/mps2: Update old infocenter.arm.com URLs (2021-03-05 15:17:38 +0000)
11
docs/system: arm: Add nRF boards description (2021-06-21 17:24:33 +0100)
19
12
20
----------------------------------------------------------------
13
----------------------------------------------------------------
21
* sbsa-ref: remove cortex-a53 from list of supported cpus
14
target-arm queue:
22
* sbsa-ref: add 'max' to list of allowed cpus
15
* Don't require 'virt' board to be compiled in for ACPI GHES code
23
* target/arm: Add support for FEAT_SSBS, Speculative Store Bypass Safe
16
* docs: Document which architecture extensions we emulate
24
* npcm7xx: add EMC model
17
* Fix bugs in M-profile FPCXT_NS accesses
25
* xlnx-zynqmp: Remove obsolete 'has_rpu' property
18
* First slice of MVE patches
26
* target/arm: Speed up aarch64 TBL/TBX
19
* Implement MTE3
27
* virtio-mmio: improve virtio-mmio get_dev_path alog
20
* docs/system: arm: Add nRF boards description
28
* target/arm: Use TCF0 and TFSRE0 for unprivileged tag checks
29
* target/arm: Restrict v8M IDAU to TCG
30
* target/arm/cpu: Update coding style to make checkpatch.pl happy
31
* musicpal, tc6393xb, omap_lcdc, tcx: drop dead code for non-32-bit-RGB surfaces
32
* Add new board: mps3-an524
33
21
34
----------------------------------------------------------------
22
----------------------------------------------------------------
35
Doug Evans (3):
23
Alexandre Iooss (1):
36
hw/net: Add npcm7xx emc model
24
docs/system: arm: Add nRF boards description
37
hw/arm: Add npcm7xx emc model
38
tests/qtests: Add npcm7xx emc model test
39
40
Marcin Juszkiewicz (2):
41
sbsa-ref: remove cortex-a53 from list of supported cpus
42
sbsa-ref: add 'max' to list of allowed cpus
43
25
44
Peter Collingbourne (1):
26
Peter Collingbourne (1):
45
target/arm: Use TCF0 and TFSRE0 for unprivileged tag checks
27
target/arm: Implement MTE3
46
28
47
Peter Maydell (34):
29
Peter Maydell (55):
48
hw/arm/musicpal: Remove dead code for non-32-bit-RGB surfaces
30
hw/acpi: Provide stub version of acpi_ghes_record_errors()
49
hw/display/tc6393xb: Remove dead code for handling non-32bpp surfaces
31
hw/acpi: Provide function acpi_ghes_present()
50
hw/display/tc6393xb: Expand out macros in template header
32
target/arm: Use acpi_ghes_present() to see if we report ACPI memory errors
51
hw/display/tc6393xb: Inline tc6393xb_draw_graphic32() at its callsite
33
docs/system/arm: Document which architecture extensions we emulate
52
hw/display/omap_lcdc: Expand out macros in template header
34
target/arm/translate-vfp.c: Whitespace fixes
53
hw/display/omap_lcdc: Drop broken bigendian ifdef
35
target/arm: Handle FPU being disabled in FPCXT_NS accesses
54
hw/display/omap_lcdc: Fix coding style issues in template header
36
target/arm: Don't NOCP fault for FPCXT_NS accesses
55
hw/display/omap_lcdc: Inline template header into C file
37
target/arm: Handle writeback in VLDR/VSTR sysreg with no memory access
56
hw/display/omap_lcdc: Delete unnecessary macro
38
target/arm: Factor FP context update code out into helper function
57
hw/display/tcx: Drop unnecessary code for handling BGR format outputs
39
target/arm: Split vfp_access_check() into A and M versions
58
hw/arm/mps2-tz: Make SYSCLK frequency board-specific
40
target/arm: Handle FPU check for FPCXT_NS insns via vfp_access_check_m()
59
hw/misc/mps2-scc: Support configurable number of OSCCLK values
41
target/arm: Implement MVE VLDR/VSTR (non-widening forms)
60
hw/arm/mps2-tz: Correct the OSCCLK settings for mps2-an505 and mps2-an511
42
target/arm: Implement widening/narrowing MVE VLDR/VSTR insns
61
hw/arm/mps2-tz: Make the OSCCLK settings be configurable per-board
43
target/arm: Implement MVE VCLZ
62
hw/misc/mps2-fpgaio: Make number of LEDs configurable by board
44
target/arm: Implement MVE VCLS
63
hw/misc/mps2-fpgaio: Support SWITCH register
45
target/arm: Implement MVE VREV16, VREV32, VREV64
64
hw/arm/mps2-tz: Make FPGAIO switch and LED config per-board
46
target/arm: Implement MVE VMVN (register)
65
hw/arm/mps2-tz: Condition IRQ splitting on number of CPUs, not board type
47
target/arm: Implement MVE VABS
66
hw/arm/mps2-tz: Make number of IRQs board-specific
48
target/arm: Implement MVE VNEG
67
hw/misc/mps2-scc: Implement CFG_REG5 and CFG_REG6 for MPS3 AN524
49
tcg: Make gen_dup_i32/i64() public as tcg_gen_dup_i32/i64
68
hw/arm/mps2-tz: Correct wrong interrupt numbers for DMA and SPI
50
target/arm: Implement MVE VDUP
69
hw/arm/mps2-tz: Allow PPCPortInfo structures to specify device interrupts
51
target/arm: Implement MVE VAND, VBIC, VORR, VORN, VEOR
70
hw/arm/mps2-tz: Move device IRQ info to data structures
52
target/arm: Implement MVE VADD, VSUB, VMUL
71
hw/arm/mps2-tz: Size the uart-irq-orgate based on the number of UARTs
53
target/arm: Implement MVE VMULH
72
hw/arm/mps2-tz: Allow boards to have different PPCInfo data
54
target/arm: Implement MVE VRMULH
73
hw/arm/mps2-tz: Make RAM arrangement board-specific
55
target/arm: Implement MVE VMAX, VMIN
74
hw/arm/mps2-tz: Set MachineClass default_ram info from RAMInfo data
56
target/arm: Implement MVE VABD
75
hw/arm/mps2-tz: Support ROMs as well as RAMs
57
target/arm: Implement MVE VHADD, VHSUB
76
hw/arm/mps2-tz: Get armv7m_load_kernel() size argument from RAMInfo
58
target/arm: Implement MVE VMULL
77
hw/arm/mps2-tz: Add new mps3-an524 board
59
target/arm: Implement MVE VMLALDAV
78
hw/arm/mps2-tz: Stub out USB controller for mps3-an524
60
target/arm: Implement MVE VMLSLDAV
79
hw/arm/mps2-tz: Provide PL031 RTC on mps3-an524
61
target/arm: Implement MVE VRMLALDAVH, VRMLSLDAVH
80
docs/system/arm/mps2.rst: Document the new mps3-an524 board
62
target/arm: Implement MVE VADD (scalar)
81
hw/arm/mps2: Update old infocenter.arm.com URLs
63
target/arm: Implement MVE VSUB, VMUL (scalar)
64
target/arm: Implement MVE VHADD, VHSUB (scalar)
65
target/arm: Implement MVE VBRSR
66
target/arm: Implement MVE VPST
67
target/arm: Implement MVE VQADD and VQSUB
68
target/arm: Implement MVE VQDMULH and VQRDMULH (scalar)
69
target/arm: Implement MVE VQDMULL scalar
70
target/arm: Implement MVE VQDMULH, VQRDMULH (vector)
71
target/arm: Implement MVE VQADD, VQSUB (vector)
72
target/arm: Implement MVE VQSHL (vector)
73
target/arm: Implement MVE VQRSHL
74
target/arm: Implement MVE VSHL insn
75
target/arm: Implement MVE VRSHL
76
target/arm: Implement MVE VQDMLADH and VQRDMLADH
77
target/arm: Implement MVE VQDMLSDH and VQRDMLSDH
78
target/arm: Implement MVE VQDMULL (vector)
79
target/arm: Implement MVE VRHADD
80
target/arm: Implement MVE VADC, VSBC
81
target/arm: Implement MVE VCADD
82
target/arm: Implement MVE VHCADD
83
target/arm: Implement MVE VADDV
84
target/arm: Make VMOV scalar <-> gpreg beatwise for MVE
82
85
83
Philippe Mathieu-Daudé (4):
86
docs/system/arm/emulation.rst | 103 ++++
84
hw/arm/xlnx-zynqmp: Remove obsolete 'has_rpu' property
87
docs/system/arm/nrf.rst | 51 ++
85
hw/i2c/npcm7xx_smbus: Simplify npcm7xx_smbus_init()
88
docs/system/target-arm.rst | 7 +
86
target/arm: Restrict v8M IDAU to TCG
89
include/hw/acpi/ghes.h | 9 +
87
target/arm/cpu: Update coding style to make checkpatch.pl happy
90
include/tcg/tcg-op.h | 8 +
91
include/tcg/tcg.h | 1 -
92
target/arm/helper-mve.h | 357 +++++++++++++
93
target/arm/helper.h | 2 +
94
target/arm/internals.h | 11 +
95
target/arm/translate-a32.h | 3 +
96
target/arm/translate.h | 10 +
97
target/arm/m-nocp.decode | 24 +
98
target/arm/mve.decode | 240 +++++++++
99
target/arm/vfp.decode | 14 -
100
hw/acpi/ghes-stub.c | 22 +
101
hw/acpi/ghes.c | 17 +
102
target/arm/cpu64.c | 2 +-
103
target/arm/kvm64.c | 6 +-
104
target/arm/mte_helper.c | 82 +--
105
target/arm/mve_helper.c | 1160 +++++++++++++++++++++++++++++++++++++++++
106
target/arm/translate-m-nocp.c | 550 +++++++++++++++++++
107
target/arm/translate-mve.c | 759 +++++++++++++++++++++++++++
108
target/arm/translate-vfp.c | 741 +++++++-------------------
109
tcg/tcg-op-gvec.c | 20 +-
110
MAINTAINERS | 1 +
111
hw/acpi/meson.build | 6 +-
112
target/arm/meson.build | 1 +
113
27 files changed, 3578 insertions(+), 629 deletions(-)
114
create mode 100644 docs/system/arm/emulation.rst
115
create mode 100644 docs/system/arm/nrf.rst
116
create mode 100644 target/arm/helper-mve.h
117
create mode 100644 hw/acpi/ghes-stub.c
118
create mode 100644 target/arm/mve_helper.c
88
119
89
Rebecca Cran (3):
90
target/arm: Add support for FEAT_SSBS, Speculative Store Bypass Safe
91
target/arm: Enable FEAT_SSBS for "max" AARCH64 CPU
92
target/arm: Set ID_PFR2.SSBS to 1 for "max" 32-bit CPU
93
94
Richard Henderson (1):
95
target/arm: Speed up aarch64 TBL/TBX
96
97
schspa (1):
98
virtio-mmio: improve virtio-mmio get_dev_path alog
99
100
docs/system/arm/mps2.rst | 24 +-
101
docs/system/arm/nuvoton.rst | 3 +-
102
hw/display/omap_lcd_template.h | 169 --------
103
hw/display/tc6393xb_template.h | 72 ----
104
include/hw/arm/armsse.h | 4 +-
105
include/hw/arm/npcm7xx.h | 2 +
106
include/hw/arm/xlnx-zynqmp.h | 2 -
107
include/hw/misc/armsse-cpuid.h | 2 +-
108
include/hw/misc/armsse-mhu.h | 2 +-
109
include/hw/misc/iotkit-secctl.h | 2 +-
110
include/hw/misc/iotkit-sysctl.h | 2 +-
111
include/hw/misc/iotkit-sysinfo.h | 2 +-
112
include/hw/misc/mps2-fpgaio.h | 8 +-
113
include/hw/misc/mps2-scc.h | 10 +-
114
include/hw/net/npcm7xx_emc.h | 286 +++++++++++++
115
include/ui/console.h | 10 -
116
target/arm/cpu.h | 15 +-
117
target/arm/helper-a64.h | 2 +-
118
target/arm/internals.h | 6 +
119
hw/arm/mps2-tz.c | 632 +++++++++++++++++++++++-----
120
hw/arm/mps2.c | 5 +
121
hw/arm/musicpal.c | 64 ++-
122
hw/arm/npcm7xx.c | 50 ++-
123
hw/arm/sbsa-ref.c | 2 +-
124
hw/arm/xlnx-zynqmp.c | 6 -
125
hw/display/omap_lcdc.c | 129 +++++-
126
hw/display/tc6393xb.c | 48 +--
127
hw/display/tcx.c | 31 +-
128
hw/i2c/npcm7xx_smbus.c | 1 -
129
hw/misc/armsse-cpuid.c | 2 +-
130
hw/misc/armsse-mhu.c | 2 +-
131
hw/misc/iotkit-sysctl.c | 2 +-
132
hw/misc/iotkit-sysinfo.c | 2 +-
133
hw/misc/mps2-fpgaio.c | 43 +-
134
hw/misc/mps2-scc.c | 93 ++++-
135
hw/net/npcm7xx_emc.c | 857 ++++++++++++++++++++++++++++++++++++++
136
hw/virtio/virtio-mmio.c | 13 +-
137
target/arm/cpu.c | 23 +-
138
target/arm/cpu64.c | 5 +
139
target/arm/cpu_tcg.c | 8 +
140
target/arm/helper-a64.c | 32 --
141
target/arm/helper.c | 39 +-
142
target/arm/mte_helper.c | 13 +-
143
target/arm/translate-a64.c | 70 +---
144
target/arm/vec_helper.c | 48 +++
145
tests/qtest/npcm7xx_emc-test.c | 862 +++++++++++++++++++++++++++++++++++++++
146
hw/net/meson.build | 1 +
147
hw/net/trace-events | 17 +
148
tests/qtest/meson.build | 3 +-
149
49 files changed, 3098 insertions(+), 628 deletions(-)
150
delete mode 100644 hw/display/omap_lcd_template.h
151
delete mode 100644 hw/display/tc6393xb_template.h
152
create mode 100644 include/hw/net/npcm7xx_emc.h
153
create mode 100644 hw/net/npcm7xx_emc.c
154
create mode 100644 tests/qtest/npcm7xx_emc-test.c
155
diff view generated by jsdifflib
New patch
1
Generic code in target/arm wants to call acpi_ghes_record_errors();
2
provide a stub version so that we don't fail to link when
3
CONFIG_ACPI_APEI is not set. This requires us to add a new
4
ghes-stub.c file to contain it and the meson.build mechanics
5
to use it when appropriate.
1
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Dongjiu Geng <gengdongjiu1@gmail.com>
10
Message-id: 20210603171259.27962-2-peter.maydell@linaro.org
11
---
12
hw/acpi/ghes-stub.c | 17 +++++++++++++++++
13
hw/acpi/meson.build | 6 +++---
14
2 files changed, 20 insertions(+), 3 deletions(-)
15
create mode 100644 hw/acpi/ghes-stub.c
16
17
diff --git a/hw/acpi/ghes-stub.c b/hw/acpi/ghes-stub.c
18
new file mode 100644
19
index XXXXXXX..XXXXXXX
20
--- /dev/null
21
+++ b/hw/acpi/ghes-stub.c
22
@@ -XXX,XX +XXX,XX @@
23
+/*
24
+ * Support for generating APEI tables and recording CPER for Guests:
25
+ * stub functions.
26
+ *
27
+ * Copyright (c) 2021 Linaro, Ltd
28
+ *
29
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
30
+ * See the COPYING file in the top-level directory.
31
+ */
32
+
33
+#include "qemu/osdep.h"
34
+#include "hw/acpi/ghes.h"
35
+
36
+int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address)
37
+{
38
+ return -1;
39
+}
40
diff --git a/hw/acpi/meson.build b/hw/acpi/meson.build
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/acpi/meson.build
43
+++ b/hw/acpi/meson.build
44
@@ -XXX,XX +XXX,XX @@ acpi_ss.add(when: 'CONFIG_ACPI_PCI', if_true: files('pci.c'))
45
acpi_ss.add(when: 'CONFIG_ACPI_VMGENID', if_true: files('vmgenid.c'))
46
acpi_ss.add(when: 'CONFIG_ACPI_HW_REDUCED', if_true: files('generic_event_device.c'))
47
acpi_ss.add(when: 'CONFIG_ACPI_HMAT', if_true: files('hmat.c'))
48
-acpi_ss.add(when: 'CONFIG_ACPI_APEI', if_true: files('ghes.c'))
49
+acpi_ss.add(when: 'CONFIG_ACPI_APEI', if_true: files('ghes.c'), if_false: files('ghes-stub.c'))
50
acpi_ss.add(when: 'CONFIG_ACPI_X86', if_true: files('core.c', 'piix4.c', 'pcihp.c'), if_false: files('acpi-stub.c'))
51
acpi_ss.add(when: 'CONFIG_ACPI_X86_ICH', if_true: files('ich9.c', 'tco.c'))
52
acpi_ss.add(when: 'CONFIG_IPMI', if_true: files('ipmi.c'), if_false: files('ipmi-stub.c'))
53
acpi_ss.add(when: 'CONFIG_PC', if_false: files('acpi-x86-stub.c'))
54
acpi_ss.add(when: 'CONFIG_TPM', if_true: files('tpm.c'))
55
-softmmu_ss.add(when: 'CONFIG_ACPI', if_false: files('acpi-stub.c', 'aml-build-stub.c'))
56
+softmmu_ss.add(when: 'CONFIG_ACPI', if_false: files('acpi-stub.c', 'aml-build-stub.c', 'ghes-stub.c'))
57
softmmu_ss.add_all(when: 'CONFIG_ACPI', if_true: acpi_ss)
58
softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('acpi-stub.c', 'aml-build-stub.c',
59
- 'acpi-x86-stub.c', 'ipmi-stub.c'))
60
+ 'acpi-x86-stub.c', 'ipmi-stub.c', 'ghes-stub.c'))
61
--
62
2.20.1
63
64
diff view generated by jsdifflib
1
Move the specification of the IRQ information for the uart, ethernet,
1
Allow code elsewhere in the system to check whether the ACPI GHES
2
dma and spi devices to the data structures. (The other devices
2
table is present, so it can determine whether it is OK to try to
3
handled by the PPCPortInfo structures don't have any interrupt lines
3
record an error by calling acpi_ghes_record_errors().
4
we need to wire up.)
4
5
(We don't need to migrate the new 'present' field in AcpiGhesState,
6
because it is set once at system initialization and doesn't change.)
5
7
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215115138.20465-14-peter.maydell@linaro.org
10
Reviewed-by: Dongjiu Geng <gengdongjiu1@gmail.com>
11
Message-id: 20210603171259.27962-3-peter.maydell@linaro.org
9
---
12
---
10
hw/arm/mps2-tz.c | 52 +++++++++++++++++++++++-------------------------
13
include/hw/acpi/ghes.h | 9 +++++++++
11
1 file changed, 25 insertions(+), 27 deletions(-)
14
hw/acpi/ghes-stub.c | 5 +++++
15
hw/acpi/ghes.c | 17 +++++++++++++++++
16
3 files changed, 31 insertions(+)
12
17
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
18
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
14
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/mps2-tz.c
20
--- a/include/hw/acpi/ghes.h
16
+++ b/hw/arm/mps2-tz.c
21
+++ b/include/hw/acpi/ghes.h
17
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
22
@@ -XXX,XX +XXX,XX @@ enum {
18
const char *name, hwaddr size,
23
19
const int *irqs)
24
typedef struct AcpiGhesState {
25
uint64_t ghes_addr_le;
26
+ bool present; /* True if GHES is present at all on this board */
27
} AcpiGhesState;
28
29
void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker);
30
@@ -XXX,XX +XXX,XX @@ void acpi_build_hest(GArray *table_data, BIOSLinker *linker,
31
void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s,
32
GArray *hardware_errors);
33
int acpi_ghes_record_errors(uint8_t notify, uint64_t error_physical_addr);
34
+
35
+/**
36
+ * acpi_ghes_present: Report whether ACPI GHES table is present
37
+ *
38
+ * Returns: true if the system has an ACPI GHES table and it is
39
+ * safe to call acpi_ghes_record_errors() to record a memory error.
40
+ */
41
+bool acpi_ghes_present(void);
42
#endif
43
diff --git a/hw/acpi/ghes-stub.c b/hw/acpi/ghes-stub.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/acpi/ghes-stub.c
46
+++ b/hw/acpi/ghes-stub.c
47
@@ -XXX,XX +XXX,XX @@ int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address)
20
{
48
{
21
+ /* The irq[] array is tx, rx, combined, in that order */
49
return -1;
22
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
23
CMSDKAPBUART *uart = opaque;
24
int i = uart - &mms->uart[0];
25
- int rxirqno = i * 2 + 32;
26
- int txirqno = i * 2 + 33;
27
- int combirqno = i + 42;
28
SysBusDevice *s;
29
DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate);
30
31
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
32
qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", mmc->sysclk_frq);
33
sysbus_realize(SYS_BUS_DEVICE(uart), &error_fatal);
34
s = SYS_BUS_DEVICE(uart);
35
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, txirqno));
36
- sysbus_connect_irq(s, 1, get_sse_irq_in(mms, rxirqno));
37
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
38
+ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqs[1]));
39
sysbus_connect_irq(s, 2, qdev_get_gpio_in(orgate_dev, i * 2));
40
sysbus_connect_irq(s, 3, qdev_get_gpio_in(orgate_dev, i * 2 + 1));
41
- sysbus_connect_irq(s, 4, get_sse_irq_in(mms, combirqno));
42
+ sysbus_connect_irq(s, 4, get_sse_irq_in(mms, irqs[2]));
43
return sysbus_mmio_get_region(SYS_BUS_DEVICE(uart), 0);
44
}
50
}
45
51
+
46
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
52
+bool acpi_ghes_present(void)
47
53
+{
48
s = SYS_BUS_DEVICE(mms->lan9118);
54
+ return false;
49
sysbus_realize_and_unref(s, &error_fatal);
55
+}
50
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 48));
56
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
51
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
57
index XXXXXXX..XXXXXXX 100644
52
return sysbus_mmio_get_region(s, 0);
58
--- a/hw/acpi/ghes.c
59
+++ b/hw/acpi/ghes.c
60
@@ -XXX,XX +XXX,XX @@ void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s,
61
/* Create a read-write fw_cfg file for Address */
62
fw_cfg_add_file_callback(s, ACPI_GHES_DATA_ADDR_FW_CFG_FILE, NULL, NULL,
63
NULL, &(ags->ghes_addr_le), sizeof(ags->ghes_addr_le), false);
64
+
65
+ ags->present = true;
53
}
66
}
54
67
55
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
68
int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address)
56
const char *name, hwaddr size,
69
@@ -XXX,XX +XXX,XX @@ int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address)
57
const int *irqs)
70
58
{
71
return ret;
59
+ /* The irq[] array is DMACINTR, DMACINTERR, DMACINTTC, in that order */
60
PL080State *dma = opaque;
61
int i = dma - &mms->dma[0];
62
SysBusDevice *s;
63
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
64
65
s = SYS_BUS_DEVICE(dma);
66
/* Wire up DMACINTR, DMACINTERR, DMACINTTC */
67
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 58 + i * 3));
68
- sysbus_connect_irq(s, 1, get_sse_irq_in(mms, 56 + i * 3));
69
- sysbus_connect_irq(s, 2, get_sse_irq_in(mms, 57 + i * 3));
70
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
71
+ sysbus_connect_irq(s, 1, get_sse_irq_in(mms, irqs[1]));
72
+ sysbus_connect_irq(s, 2, get_sse_irq_in(mms, irqs[2]));
73
74
g_free(mscname);
75
return sysbus_mmio_get_region(s, 0);
76
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
77
* lines are set via the "MISC" register in the MPS2 FPGAIO device.
78
*/
79
PL022State *spi = opaque;
80
- int i = spi - &mms->spi[0];
81
SysBusDevice *s;
82
83
object_initialize_child(OBJECT(mms), name, spi, TYPE_PL022);
84
sysbus_realize(SYS_BUS_DEVICE(spi), &error_fatal);
85
s = SYS_BUS_DEVICE(spi);
86
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 51 + i));
87
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
88
return sysbus_mmio_get_region(s, 0);
89
}
72
}
90
73
+
91
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
74
+bool acpi_ghes_present(void)
92
}, {
75
+{
93
.name = "apb_ppcexp1",
76
+ AcpiGedState *acpi_ged_state;
94
.ports = {
77
+ AcpiGhesState *ags;
95
- { "spi0", make_spi, &mms->spi[0], 0x40205000, 0x1000 },
78
+
96
- { "spi1", make_spi, &mms->spi[1], 0x40206000, 0x1000 },
79
+ acpi_ged_state = ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED,
97
- { "spi2", make_spi, &mms->spi[2], 0x40209000, 0x1000 },
80
+ NULL));
98
- { "spi3", make_spi, &mms->spi[3], 0x4020a000, 0x1000 },
81
+
99
- { "spi4", make_spi, &mms->spi[4], 0x4020b000, 0x1000 },
82
+ if (!acpi_ged_state) {
100
- { "uart0", make_uart, &mms->uart[0], 0x40200000, 0x1000 },
83
+ return false;
101
- { "uart1", make_uart, &mms->uart[1], 0x40201000, 0x1000 },
84
+ }
102
- { "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000 },
85
+ ags = &acpi_ged_state->ghes_state;
103
- { "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000 },
86
+ return ags->present;
104
- { "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000 },
87
+}
105
+ { "spi0", make_spi, &mms->spi[0], 0x40205000, 0x1000, { 51 } },
106
+ { "spi1", make_spi, &mms->spi[1], 0x40206000, 0x1000, { 52 } },
107
+ { "spi2", make_spi, &mms->spi[2], 0x40209000, 0x1000, { 53 } },
108
+ { "spi3", make_spi, &mms->spi[3], 0x4020a000, 0x1000, { 54 } },
109
+ { "spi4", make_spi, &mms->spi[4], 0x4020b000, 0x1000, { 55 } },
110
+ { "uart0", make_uart, &mms->uart[0], 0x40200000, 0x1000, { 32, 33, 42 } },
111
+ { "uart1", make_uart, &mms->uart[1], 0x40201000, 0x1000, { 34, 35, 43 } },
112
+ { "uart2", make_uart, &mms->uart[2], 0x40202000, 0x1000, { 36, 37, 44 } },
113
+ { "uart3", make_uart, &mms->uart[3], 0x40203000, 0x1000, { 38, 39, 45 } },
114
+ { "uart4", make_uart, &mms->uart[4], 0x40204000, 0x1000, { 40, 41, 46 } },
115
{ "i2c0", make_i2c, &mms->i2c[0], 0x40207000, 0x1000 },
116
{ "i2c1", make_i2c, &mms->i2c[1], 0x40208000, 0x1000 },
117
{ "i2c2", make_i2c, &mms->i2c[2], 0x4020c000, 0x1000 },
118
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
119
{ "gpio1", make_unimp_dev, &mms->gpio[1], 0x40101000, 0x1000 },
120
{ "gpio2", make_unimp_dev, &mms->gpio[2], 0x40102000, 0x1000 },
121
{ "gpio3", make_unimp_dev, &mms->gpio[3], 0x40103000, 0x1000 },
122
- { "eth", make_eth_dev, NULL, 0x42000000, 0x100000 },
123
+ { "eth", make_eth_dev, NULL, 0x42000000, 0x100000, { 48 } },
124
},
125
}, {
126
.name = "ahb_ppcexp1",
127
.ports = {
128
- { "dma0", make_dma, &mms->dma[0], 0x40110000, 0x1000 },
129
- { "dma1", make_dma, &mms->dma[1], 0x40111000, 0x1000 },
130
- { "dma2", make_dma, &mms->dma[2], 0x40112000, 0x1000 },
131
- { "dma3", make_dma, &mms->dma[3], 0x40113000, 0x1000 },
132
+ { "dma0", make_dma, &mms->dma[0], 0x40110000, 0x1000, { 58, 56, 57 } },
133
+ { "dma1", make_dma, &mms->dma[1], 0x40111000, 0x1000, { 61, 59, 60 } },
134
+ { "dma2", make_dma, &mms->dma[2], 0x40112000, 0x1000, { 64, 62, 63 } },
135
+ { "dma3", make_dma, &mms->dma[3], 0x40113000, 0x1000, { 67, 65, 66 } },
136
},
137
},
138
};
139
--
88
--
140
2.20.1
89
2.20.1
141
90
142
91
diff view generated by jsdifflib
New patch
1
The virt_is_acpi_enabled() function is specific to the virt board, as
2
is the check for its 'ras' property. Use the new acpi_ghes_present()
3
function to check whether we should report memory errors via
4
acpi_ghes_record_errors().
1
5
6
This avoids a link error if QEMU was built without support for the
7
virt board, and provides a mechanism that can be used by any future
8
board models that want to add ACPI memory error reporting support
9
(they only need to call acpi_ghes_add_fw_cfg()).
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Dongjiu Geng <gengdongjiu1@gmail.com>
14
Message-id: 20210603171259.27962-4-peter.maydell@linaro.org
15
---
16
target/arm/kvm64.c | 6 +-----
17
1 file changed, 1 insertion(+), 5 deletions(-)
18
19
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/kvm64.c
22
+++ b/target/arm/kvm64.c
23
@@ -XXX,XX +XXX,XX @@ void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
24
{
25
ram_addr_t ram_addr;
26
hwaddr paddr;
27
- Object *obj = qdev_get_machine();
28
- VirtMachineState *vms = VIRT_MACHINE(obj);
29
- bool acpi_enabled = virt_is_acpi_enabled(vms);
30
31
assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
32
33
- if (acpi_enabled && addr &&
34
- object_property_get_bool(obj, "ras", NULL)) {
35
+ if (acpi_ghes_present() && addr) {
36
ram_addr = qemu_ram_addr_from_host(addr);
37
if (ram_addr != RAM_ADDR_INVALID &&
38
kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
39
--
40
2.20.1
41
42
diff view generated by jsdifflib
1
The AN524 has more interrupt lines than the AN505 and AN521; make
1
These days the Arm architecture has a wide range of fine-grained
2
numirq board-specific rather than a compile-time constant.
2
optional extra architectural features. We implement quite a lot
3
3
of these but by no means all of them. Document what we do implement,
4
Since the difference is small (92 on the current boards and 95 on the
4
so that users can find out without having to dig through back-issues
5
new one) we don't dynamically allocate the cpu_irq_splitter[] array
5
of our Changelog on the wiki.
6
but leave it as a fixed length array whose size is the maximum needed
7
for any of the boards.
8
6
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Message-id: 20210617140328.28622-1-peter.maydell@linaro.org
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210215115138.20465-10-peter.maydell@linaro.org
13
---
11
---
14
hw/arm/mps2-tz.c | 15 ++++++++++-----
12
docs/system/arm/emulation.rst | 102 ++++++++++++++++++++++++++++++++++
15
1 file changed, 10 insertions(+), 5 deletions(-)
13
docs/system/target-arm.rst | 6 ++
14
2 files changed, 108 insertions(+)
15
create mode 100644 docs/system/arm/emulation.rst
16
16
17
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
17
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
18
new file mode 100644
19
index XXXXXXX..XXXXXXX
20
--- /dev/null
21
+++ b/docs/system/arm/emulation.rst
22
@@ -XXX,XX +XXX,XX @@
23
+A-profile CPU architecture support
24
+==================================
25
+
26
+QEMU's TCG emulation includes support for the Armv5, Armv6, Armv7 and
27
+Armv8 versions of the A-profile architecture. It also has support for
28
+the following architecture extensions:
29
+
30
+- FEAT_AA32BF16 (AArch32 BFloat16 instructions)
31
+- FEAT_AA32HPD (AArch32 hierarchical permission disables)
32
+- FEAT_AA32I8MM (AArch32 Int8 matrix multiplication instructions)
33
+- FEAT_AES (AESD and AESE instructions)
34
+- FEAT_BF16 (AArch64 BFloat16 instructions)
35
+- FEAT_BTI (Branch Target Identification)
36
+- FEAT_DIT (Data Independent Timing instructions)
37
+- FEAT_DPB (DC CVAP instruction)
38
+- FEAT_DotProd (Advanced SIMD dot product instructions)
39
+- FEAT_FCMA (Floating-point complex number instructions)
40
+- FEAT_FHM (Floating-point half-precision multiplication instructions)
41
+- FEAT_FP16 (Half-precision floating-point data processing)
42
+- FEAT_FRINTTS (Floating-point to integer instructions)
43
+- FEAT_FlagM (Flag manipulation instructions v2)
44
+- FEAT_FlagM2 (Enhancements to flag manipulation instructions)
45
+- FEAT_HPDS (Hierarchical permission disables)
46
+- FEAT_I8MM (AArch64 Int8 matrix multiplication instructions)
47
+- FEAT_JSCVT (JavaScript conversion instructions)
48
+- FEAT_LOR (Limited ordering regions)
49
+- FEAT_LRCPC (Load-acquire RCpc instructions)
50
+- FEAT_LRCPC2 (Load-acquire RCpc instructions v2)
51
+- FEAT_LSE (Large System Extensions)
52
+- FEAT_MTE (Memory Tagging Extension)
53
+- FEAT_MTE2 (Memory Tagging Extension)
54
+- FEAT_PAN (Privileged access never)
55
+- FEAT_PAN2 (AT S1E1R and AT S1E1W instruction variants affected by PSTATE.PAN)
56
+- FEAT_PAuth (Pointer authentication)
57
+- FEAT_PMULL (PMULL, PMULL2 instructions)
58
+- FEAT_PMUv3p1 (PMU Extensions v3.1)
59
+- FEAT_PMUv3p4 (PMU Extensions v3.4)
60
+- FEAT_RDM (Advanced SIMD rounding double multiply accumulate instructions)
61
+- FEAT_RNG (Random number generator)
62
+- FEAT_SB (Speculation Barrier)
63
+- FEAT_SEL2 (Secure EL2)
64
+- FEAT_SHA1 (SHA1 instructions)
65
+- FEAT_SHA256 (SHA256 instructions)
66
+- FEAT_SHA3 (Advanced SIMD SHA3 instructions)
67
+- FEAT_SHA512 (Advanced SIMD SHA512 instructions)
68
+- FEAT_SM3 (Advanced SIMD SM3 instructions)
69
+- FEAT_SM4 (Advanced SIMD SM4 instructions)
70
+- FEAT_SPECRES (Speculation restriction instructions)
71
+- FEAT_SSBS (Speculative Store Bypass Safe)
72
+- FEAT_TLBIOS (TLB invalidate instructions in Outer Shareable domain)
73
+- FEAT_TLBIRANGE (TLB invalidate range instructions)
74
+- FEAT_TTCNP (Translation table Common not private translations)
75
+- FEAT_TTST (Small translation tables)
76
+- FEAT_UAO (Unprivileged Access Override control)
77
+- FEAT_VHE (Virtualization Host Extensions)
78
+- FEAT_VMID16 (16-bit VMID)
79
+- FEAT_XNX (Translation table stage 2 Unprivileged Execute-never)
80
+- SVE (The Scalable Vector Extension)
81
+- SVE2 (The Scalable Vector Extension v2)
82
+
83
+For information on the specifics of these extensions, please refer
84
+to the `Armv8-A Arm Architecture Reference Manual
85
+<https://developer.arm.com/documentation/ddi0487/latest>`_.
86
+
87
+When a specific named CPU is being emulated, only those features which
88
+are present in hardware for that CPU are emulated. (If a feature is
89
+not in the list above then it is not supported, even if the real
90
+hardware should have it.) The ``max`` CPU enables all features.
91
+
92
+R-profile CPU architecture support
93
+==================================
94
+
95
+QEMU's TCG emulation support for R-profile CPUs is currently limited.
96
+We emulate only the Cortex-R5 and Cortex-R5F CPUs.
97
+
98
+M-profile CPU architecture support
99
+==================================
100
+
101
+QEMU's TCG emulation includes support for Armv6-M, Armv7-M, Armv8-M, and
102
+Armv8.1-M versions of the M-profile architucture. It also has support
103
+for the following architecture extensions:
104
+
105
+- FP (Floating-point Extension)
106
+- FPCXT (FPCXT access instructions)
107
+- HP (Half-precision floating-point instructions)
108
+- LOB (Low Overhead loops and Branch future)
109
+- M (Main Extension)
110
+- MPU (Memory Protection Unit Extension)
111
+- PXN (Privileged Execute Never)
112
+- RAS (Reliability, Serviceability and Availability): "minimum RAS Extension" only
113
+- S (Security Extension)
114
+- ST (System Timer Extension)
115
+
116
+For information on the specifics of these extensions, please refer
117
+to the `Armv8-M Arm Architecture Reference Manual
118
+<https://developer.arm.com/documentation/ddi0553/latest>`_.
119
+
120
+When a specific named CPU is being emulated, only those features which
121
+are present in hardware for that CPU are emulated. (If a feature is
122
+not in the list above then it is not supported, even if the real
123
+hardware should have it.) There is no equivalent of the ``max`` CPU for
124
+M-profile.
125
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
18
index XXXXXXX..XXXXXXX 100644
126
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/mps2-tz.c
127
--- a/docs/system/target-arm.rst
20
+++ b/hw/arm/mps2-tz.c
128
+++ b/docs/system/target-arm.rst
21
@@ -XXX,XX +XXX,XX @@
129
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
22
#include "hw/qdev-clock.h"
130
arm/virt
23
#include "qom/object.h"
131
arm/xlnx-versal-virt
24
132
25
-#define MPS2TZ_NUMIRQ 92
133
+Emulated CPU architecture support
26
+#define MPS2TZ_NUMIRQ_MAX 92
134
+=================================
27
135
+
28
typedef enum MPS2TZFPGAType {
136
+.. toctree::
29
FPGA_AN505,
137
+ arm/emulation
30
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
138
+
31
const uint32_t *oscclk;
139
Arm CPU features
32
uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
140
================
33
bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
34
+ int numirq; /* Number of external interrupts */
35
const char *armsse_type;
36
};
37
38
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
39
SplitIRQ sec_resp_splitter;
40
qemu_or_irq uart_irq_orgate;
41
DeviceState *lan9118;
42
- SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ];
43
+ SplitIRQ cpu_irq_splitter[MPS2TZ_NUMIRQ_MAX];
44
Clock *sysclk;
45
Clock *s32kclk;
46
};
47
@@ -XXX,XX +XXX,XX @@ static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
48
{
49
/* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
50
MachineClass *mc = MACHINE_GET_CLASS(mms);
51
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
52
53
- assert(irqno < MPS2TZ_NUMIRQ);
54
+ assert(irqno < mmc->numirq);
55
56
if (mc->max_cpus > 1) {
57
return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
58
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
59
iotkitdev = DEVICE(&mms->iotkit);
60
object_property_set_link(OBJECT(&mms->iotkit), "memory",
61
OBJECT(system_memory), &error_abort);
62
- qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", MPS2TZ_NUMIRQ);
63
+ qdev_prop_set_uint32(iotkitdev, "EXP_NUMIRQ", mmc->numirq);
64
qdev_connect_clock_in(iotkitdev, "MAINCLK", mms->sysclk);
65
qdev_connect_clock_in(iotkitdev, "S32KCLK", mms->s32kclk);
66
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
67
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
68
* board. If there is only one CPU, we can just wire the device IRQ
69
* directly to the SSE's IRQ input.
70
*/
71
+ assert(mmc->numirq <= MPS2TZ_NUMIRQ_MAX);
72
if (mc->max_cpus > 1) {
73
- for (i = 0; i < MPS2TZ_NUMIRQ; i++) {
74
+ for (i = 0; i < mmc->numirq; i++) {
75
char *name = g_strdup_printf("mps2-irq-splitter%d", i);
76
SplitIRQ *splitter = &mms->cpu_irq_splitter[i];
77
78
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
79
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
80
mmc->fpgaio_num_leds = 2;
81
mmc->fpgaio_has_switches = false;
82
+ mmc->numirq = 92;
83
mmc->armsse_type = TYPE_IOTKIT;
84
}
85
86
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
87
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
88
mmc->fpgaio_num_leds = 2;
89
mmc->fpgaio_has_switches = false;
90
+ mmc->numirq = 92;
91
mmc->armsse_type = TYPE_SSE200;
92
}
93
141
94
--
142
--
95
2.20.1
143
2.20.1
96
144
97
145
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
In the code for handling VFP system register accesses there is some
2
stray whitespace after a unary '-' operator, and also some incorrect
3
indent in a couple of function prototypes. We're about to move this
4
code to another file, so fix the code style issues first so
5
checkpatch doesn't complain about the code-movement patch.
2
6
3
We will move this code in the next commit. Clean it up
7
Cc: qemu-stable@nongnu.org
4
first to avoid checkpatch.pl errors.
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210618141019.10671-2-peter.maydell@linaro.org
11
---
12
target/arm/translate-vfp.c | 11 +++++------
13
1 file changed, 5 insertions(+), 6 deletions(-)
5
14
6
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
7
Message-id: 20210221222617.2579610-3-f4bug@amsat.org
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/cpu.c | 12 ++++++++----
12
1 file changed, 8 insertions(+), 4 deletions(-)
13
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.c
17
--- a/target/arm/translate-vfp.c
17
+++ b/target/arm/cpu.c
18
+++ b/target/arm/translate-vfp.c
18
@@ -XXX,XX +XXX,XX @@ static void cortex_a8_initfn(Object *obj)
19
@@ -XXX,XX +XXX,XX @@ static void gen_branch_fpInactive(DisasContext *s, TCGCond cond,
19
}
20
}
20
21
21
static const ARMCPRegInfo cortexa9_cp_reginfo[] = {
22
static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
22
- /* power_control should be set to maximum latency. Again,
23
-
23
+ /*
24
fp_sysreg_loadfn *loadfn,
24
+ * power_control should be set to maximum latency. Again,
25
- void *opaque)
25
* default to 0 and set by private hook
26
+ void *opaque)
26
*/
27
{ .name = "A9_PWRCTL", .cp = 15, .crn = 15, .crm = 0, .opc1 = 0, .opc2 = 0,
28
@@ -XXX,XX +XXX,XX @@ static void cortex_a9_initfn(Object *obj)
29
set_feature(&cpu->env, ARM_FEATURE_NEON);
30
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
31
set_feature(&cpu->env, ARM_FEATURE_EL3);
32
- /* Note that A9 supports the MP extensions even for
33
+ /*
34
+ * Note that A9 supports the MP extensions even for
35
* A9UP and single-core A9MP (which are both different
36
* and valid configurations; we don't model A9UP).
37
*/
38
@@ -XXX,XX +XXX,XX @@ static uint64_t a15_l2ctlr_read(CPUARMState *env, const ARMCPRegInfo *ri)
39
{
27
{
40
MachineState *ms = MACHINE(qdev_get_machine());
28
/* Do a write to an M-profile floating point system register */
41
29
TCGv_i32 tmp;
42
- /* Linux wants the number of processors from here.
30
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
43
+ /*
31
}
44
+ * Linux wants the number of processors from here.
32
45
* Might as well set the interrupt-controller bit too.
33
static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
46
*/
34
- fp_sysreg_storefn *storefn,
47
return ((ms->smp.cpus - 1) << 24) | (1 << 23);
35
- void *opaque)
48
@@ -XXX,XX +XXX,XX @@ static void cortex_a7_initfn(Object *obj)
36
+ fp_sysreg_storefn *storefn,
49
cpu->isar.id_mmfr1 = 0x40000000;
37
+ void *opaque)
50
cpu->isar.id_mmfr2 = 0x01240000;
38
{
51
cpu->isar.id_mmfr3 = 0x02102211;
39
/* Do a read from an M-profile floating point system register */
52
- /* a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but
40
TCGv_i32 tmp;
53
+ /*
41
@@ -XXX,XX +XXX,XX @@ static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
54
+ * a7_mpcore_r0p5_trm, page 4-4 gives 0x01101110; but
42
TCGv_i32 addr;
55
* table 4-41 gives 0x02101110, which includes the arm div insns.
43
56
*/
44
if (!a->a) {
57
cpu->isar.id_isar0 = 0x02101110;
45
- offset = - offset;
46
+ offset = -offset;
47
}
48
49
addr = load_reg(s, a->rn);
50
@@ -XXX,XX +XXX,XX @@ static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
51
TCGv_i32 value = tcg_temp_new_i32();
52
53
if (!a->a) {
54
- offset = - offset;
55
+ offset = -offset;
56
}
57
58
addr = load_reg(s, a->rn);
58
--
59
--
59
2.20.1
60
2.20.1
60
61
61
62
diff view generated by jsdifflib
New patch
1
If the guest makes an FPCXT_NS access when the FPU is disabled,
2
one of two things happens:
3
* if there is no active FP context, then the insn behaves the
4
same way as if the FPU was enabled: writes ignored, reads
5
same value as FPDSCR_NS
6
* if there is an active FP context, then we take a NOCP
7
exception
1
8
9
Add code to the sysreg read/write functions which emits
10
code to take the NOCP exception in the latter case.
11
12
At the moment this will never be used, because the NOCP checks in
13
m-nocp.decode happen first, and so the trans functions are never
14
called when the FPU is disabled. The code will be needed when we
15
move the sysreg access insns to before the NOCP patterns in the
16
following commit.
17
18
Cc: qemu-stable@nongnu.org
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20210618141019.10671-3-peter.maydell@linaro.org
22
---
23
target/arm/translate-vfp.c | 32 ++++++++++++++++++++++++++++++--
24
1 file changed, 30 insertions(+), 2 deletions(-)
25
26
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/translate-vfp.c
29
+++ b/target/arm/translate-vfp.c
30
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
31
lab_end = gen_new_label();
32
/* fpInactive case: write is a NOP, so branch to end */
33
gen_branch_fpInactive(s, TCG_COND_NE, lab_end);
34
- /* !fpInactive: PreserveFPState(), and reads same as FPCXT_S */
35
+ /*
36
+ * !fpInactive: if FPU disabled, take NOCP exception;
37
+ * otherwise PreserveFPState(), and then FPCXT_NS writes
38
+ * behave the same as FPCXT_S writes.
39
+ */
40
+ if (s->fp_excp_el) {
41
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
42
+ syn_uncategorized(), s->fp_excp_el);
43
+ /*
44
+ * This was only a conditional exception, so override
45
+ * gen_exception_insn()'s default to DISAS_NORETURN
46
+ */
47
+ s->base.is_jmp = DISAS_NEXT;
48
+ break;
49
+ }
50
gen_preserve_fp_state(s);
51
/* fall through */
52
case ARM_VFP_FPCXT_S:
53
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
54
tcg_gen_br(lab_end);
55
56
gen_set_label(lab_active);
57
- /* !fpInactive: Reads the same as FPCXT_S, but side effects differ */
58
+ /*
59
+ * !fpInactive: if FPU disabled, take NOCP exception;
60
+ * otherwise PreserveFPState(), and then FPCXT_NS
61
+ * reads the same as FPCXT_S.
62
+ */
63
+ if (s->fp_excp_el) {
64
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
65
+ syn_uncategorized(), s->fp_excp_el);
66
+ /*
67
+ * This was only a conditional exception, so override
68
+ * gen_exception_insn()'s default to DISAS_NORETURN
69
+ */
70
+ s->base.is_jmp = DISAS_NEXT;
71
+ break;
72
+ }
73
gen_preserve_fp_state(s);
74
tmp = tcg_temp_new_i32();
75
sfpa = tcg_temp_new_i32();
76
--
77
2.20.1
78
79
diff view generated by jsdifflib
1
From: Doug Evans <dje@google.com>
1
The M-profile architecture requires that accesses to FPCXT_NS when
2
there is no active FP state must not take a NOCP fault even if the
3
FPU is disabled. We were not implementing this correctly, because
4
in our decode we catch the NOCP faults early in m-nocp.decode.
2
5
3
This is a 10/100 ethernet device that has several features.
6
Fix this bug by moving all the handling of M-profile FP system
4
Only the ones needed by the Linux driver have been implemented.
7
register accesses from vfp.decode into m-nocp.decode and putting
5
See npcm7xx_emc.c for a list of unimplemented features.
8
it above the NOCP blocks. This provides the correct behaviour:
9
* for accesses other than FPCXT_NS the trans functions call
10
vfp_access_check(), which will check for FPU disabled and
11
raise a NOCP exception if necessary
12
* for FPCXT_NS we have the special case code that doesn't
13
call vfp_access_check()
14
* when these trans functions want to raise an UNDEF they return
15
false, so the decoder will fall through into the NOCP blocks.
16
This means that NOCP correctly takes precedence over UNDEF
17
for these insns. (This is a difference from the other insns
18
handled by m-nocp.decode, where UNDEF takes precedence and
19
which we implement by having those trans functions call
20
unallocated_encoding() in the appropriate places.)
6
21
7
Reviewed-by: Hao Wu <wuhaotsh@google.com>
22
[Note for backport to stable: this commit has a semantic dependency
8
Reviewed-by: Avi Fishman <avi.fishman@nuvoton.com>
23
on commit 9a486856e9173af, which was not marked as cc-stable because
9
Signed-off-by: Doug Evans <dje@google.com>
24
we didn't know we'd need it for a for-stable bugfix.]
10
Message-id: 20210218212453.831406-2-dje@google.com
25
26
Cc: qemu-stable@nongnu.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
29
Message-id: 20210618141019.10671-4-peter.maydell@linaro.org
12
---
30
---
13
include/hw/net/npcm7xx_emc.h | 286 ++++++++++++
31
target/arm/translate-a32.h | 1 +
14
hw/net/npcm7xx_emc.c | 857 +++++++++++++++++++++++++++++++++++
32
target/arm/m-nocp.decode | 24 ++
15
hw/net/meson.build | 1 +
33
target/arm/vfp.decode | 14 -
16
hw/net/trace-events | 17 +
34
target/arm/translate-m-nocp.c | 514 +++++++++++++++++++++++++++++++++
17
4 files changed, 1161 insertions(+)
35
target/arm/translate-vfp.c | 517 +---------------------------------
18
create mode 100644 include/hw/net/npcm7xx_emc.h
36
5 files changed, 542 insertions(+), 528 deletions(-)
19
create mode 100644 hw/net/npcm7xx_emc.c
20
37
21
diff --git a/include/hw/net/npcm7xx_emc.h b/include/hw/net/npcm7xx_emc.h
38
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
22
new file mode 100644
39
index XXXXXXX..XXXXXXX 100644
23
index XXXXXXX..XXXXXXX
40
--- a/target/arm/translate-a32.h
24
--- /dev/null
41
+++ b/target/arm/translate-a32.h
25
+++ b/include/hw/net/npcm7xx_emc.h
42
@@ -XXX,XX +XXX,XX @@ bool disas_neon_shared(DisasContext *s, uint32_t insn);
43
void load_reg_var(DisasContext *s, TCGv_i32 var, int reg);
44
void arm_gen_condlabel(DisasContext *s);
45
bool vfp_access_check(DisasContext *s);
46
+void gen_preserve_fp_state(DisasContext *s);
47
void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop);
48
void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop);
49
void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop);
50
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.decode
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/m-nocp.decode
53
+++ b/target/arm/m-nocp.decode
26
@@ -XXX,XX +XXX,XX @@
54
@@ -XXX,XX +XXX,XX @@
55
56
&nocp cp
57
58
+# M-profile VLDR/VSTR to sysreg
59
+%vldr_sysreg 22:1 13:3
60
+%imm7_0x4 0:7 !function=times_4
61
+
62
+&vldr_sysreg rn reg imm a w p
63
+@vldr_sysreg .... ... . a:1 . . . rn:4 ... . ... .. ....... \
64
+ reg=%vldr_sysreg imm=%imm7_0x4 &vldr_sysreg
65
+
66
{
67
# Special cases which do not take an early NOCP: VLLDM and VLSTM
68
VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 op:1 000 0000
69
@@ -XXX,XX +XXX,XX @@
70
VSCCLRM 1110 1100 1.01 1111 .... 1011 imm:7 0 vd=%vd_dp size=3
71
VSCCLRM 1110 1100 1.01 1111 .... 1010 imm:8 vd=%vd_sp size=2
72
73
+ # FP system register accesses: these are a special case because accesses
74
+ # to FPCXT_NS succeed even if the FPU is disabled. We therefore need
75
+ # to handle them before the big NOCP blocks. Note that within these
76
+ # insns NOCP still has higher priority than UNDEFs; this is implemented
77
+ # by their returning 'false' for UNDEF so as to fall through into the
78
+ # NOCP check (in contrast to VLLDM etc, which call unallocated_encoding()
79
+ # for the UNDEFs there that must take precedence over NOCP.)
80
+
81
+ VMSR_VMRS ---- 1110 111 l:1 reg:4 rt:4 1010 0001 0000
82
+
83
+ # P=0 W=0 is SEE "Related encodings", so split into two patterns
84
+ VLDR_sysreg ---- 110 1 . . w:1 1 .... ... 0 111 11 ....... @vldr_sysreg p=1
85
+ VLDR_sysreg ---- 110 0 . . 1 1 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
86
+ VSTR_sysreg ---- 110 1 . . w:1 0 .... ... 0 111 11 ....... @vldr_sysreg p=1
87
+ VSTR_sysreg ---- 110 0 . . 1 0 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
88
+
89
NOCP 111- 1110 ---- ---- ---- cp:4 ---- ---- &nocp
90
NOCP 111- 110- ---- ---- ---- cp:4 ---- ---- &nocp
91
# From v8.1M onwards this range will also NOCP:
92
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
93
index XXXXXXX..XXXXXXX 100644
94
--- a/target/arm/vfp.decode
95
+++ b/target/arm/vfp.decode
96
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR_hp ---- 1101 u:1 .0 l:1 rn:4 .... 1001 imm:8 vd=%vd_sp
97
VLDR_VSTR_sp ---- 1101 u:1 .0 l:1 rn:4 .... 1010 imm:8 vd=%vd_sp
98
VLDR_VSTR_dp ---- 1101 u:1 .0 l:1 rn:4 .... 1011 imm:8 vd=%vd_dp
99
100
-# M-profile VLDR/VSTR to sysreg
101
-%vldr_sysreg 22:1 13:3
102
-%imm7_0x4 0:7 !function=times_4
103
-
104
-&vldr_sysreg rn reg imm a w p
105
-@vldr_sysreg .... ... . a:1 . . . rn:4 ... . ... .. ....... \
106
- reg=%vldr_sysreg imm=%imm7_0x4 &vldr_sysreg
107
-
108
-# P=0 W=0 is SEE "Related encodings", so split into two patterns
109
-VLDR_sysreg ---- 110 1 . . w:1 1 .... ... 0 111 11 ....... @vldr_sysreg p=1
110
-VLDR_sysreg ---- 110 0 . . 1 1 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
111
-VSTR_sysreg ---- 110 1 . . w:1 0 .... ... 0 111 11 ....... @vldr_sysreg p=1
112
-VSTR_sysreg ---- 110 0 . . 1 0 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
113
-
114
# We split the load/store multiple up into two patterns to avoid
115
# overlap with other insns in the "Advanced SIMD load/store and 64-bit move"
116
# grouping:
117
diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/target/arm/translate-m-nocp.c
120
+++ b/target/arm/translate-m-nocp.c
121
@@ -XXX,XX +XXX,XX @@
122
123
#include "qemu/osdep.h"
124
#include "tcg/tcg-op.h"
125
+#include "tcg/tcg-op-gvec.h"
126
#include "translate.h"
127
#include "translate-a32.h"
128
129
@@ -XXX,XX +XXX,XX @@ static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
130
return true;
131
}
132
27
+/*
133
+/*
28
+ * Nuvoton NPCM7xx EMC Module
134
+ * M-profile provides two different sets of instructions that can
29
+ *
135
+ * access floating point system registers: VMSR/VMRS (which move
30
+ * Copyright 2020 Google LLC
136
+ * to/from a general purpose register) and VLDR/VSTR sysreg (which
31
+ *
137
+ * move directly to/from memory). In some cases there are also side
32
+ * This program is free software; you can redistribute it and/or modify it
138
+ * effects which must happen after any write to memory (which could
33
+ * under the terms of the GNU General Public License as published by the
139
+ * cause an exception). So we implement the common logic for the
34
+ * Free Software Foundation; either version 2 of the License, or
140
+ * sysreg access in gen_M_fp_sysreg_write() and gen_M_fp_sysreg_read(),
35
+ * (at your option) any later version.
141
+ * which take pointers to callback functions which will perform the
36
+ *
142
+ * actual "read/write general purpose register" and "read/write
37
+ * This program is distributed in the hope that it will be useful, but WITHOUT
143
+ * memory" operations.
38
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
39
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
40
+ * for more details.
41
+ */
144
+ */
42
+
145
+
43
+#ifndef NPCM7XX_EMC_H
146
+/*
44
+#define NPCM7XX_EMC_H
147
+ * Emit code to store the sysreg to its final destination; frees the
45
+
148
+ * TCG temp 'value' it is passed.
46
+#include "hw/irq.h"
149
+ */
47
+#include "hw/sysbus.h"
150
+typedef void fp_sysreg_storefn(DisasContext *s, void *opaque, TCGv_i32 value);
48
+#include "net/net.h"
151
+/*
49
+
152
+ * Emit code to load the value to be copied to the sysreg; returns
50
+/* 32-bit register indices. */
153
+ * a new TCG temporary
51
+enum NPCM7xxPWMRegister {
154
+ */
52
+ /* Control registers. */
155
+typedef TCGv_i32 fp_sysreg_loadfn(DisasContext *s, void *opaque);
53
+ REG_CAMCMR,
156
+
54
+ REG_CAMEN,
157
+/* Common decode/access checks for fp sysreg read/write */
55
+
158
+typedef enum FPSysRegCheckResult {
56
+ /* There are 16 CAMn[ML] registers. */
159
+ FPSysRegCheckFailed, /* caller should return false */
57
+ REG_CAMM_BASE,
160
+ FPSysRegCheckDone, /* caller should return true */
58
+ REG_CAML_BASE,
161
+ FPSysRegCheckContinue, /* caller should continue generating code */
59
+ REG_CAMML_LAST = 0x21,
162
+} FPSysRegCheckResult;
60
+
163
+
61
+ REG_TXDLSA = 0x22,
164
+static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
62
+ REG_RXDLSA,
165
+{
63
+ REG_MCMDR,
166
+ if (!dc_isar_feature(aa32_fpsp_v2, s) && !dc_isar_feature(aa32_mve, s)) {
64
+ REG_MIID,
167
+ return FPSysRegCheckFailed;
65
+ REG_MIIDA,
168
+ }
66
+ REG_FFTCR,
169
+
67
+ REG_TSDR,
170
+ switch (regno) {
68
+ REG_RSDR,
171
+ case ARM_VFP_FPSCR:
69
+ REG_DMARFC,
172
+ case QEMU_VFP_FPSCR_NZCV:
70
+ REG_MIEN,
173
+ break;
71
+
174
+ case ARM_VFP_FPSCR_NZCVQC:
72
+ /* Status registers. */
175
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
73
+ REG_MISTA,
176
+ return FPSysRegCheckFailed;
74
+ REG_MGSTA,
177
+ }
75
+ REG_MPCNT,
178
+ break;
76
+ REG_MRPC,
179
+ case ARM_VFP_FPCXT_S:
77
+ REG_MRPCC,
180
+ case ARM_VFP_FPCXT_NS:
78
+ REG_MREPC,
181
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
79
+ REG_DMARFS,
182
+ return FPSysRegCheckFailed;
80
+ REG_CTXDSA,
183
+ }
81
+ REG_CTXBSA,
184
+ if (!s->v8m_secure) {
82
+ REG_CRXDSA,
185
+ return FPSysRegCheckFailed;
83
+ REG_CRXBSA,
186
+ }
84
+
187
+ break;
85
+ NPCM7XX_NUM_EMC_REGS,
188
+ case ARM_VFP_VPR:
86
+};
189
+ case ARM_VFP_P0:
87
+
190
+ if (!dc_isar_feature(aa32_mve, s)) {
88
+/* REG_CAMCMR fields */
191
+ return FPSysRegCheckFailed;
89
+/* Enable CAM Compare */
192
+ }
90
+#define REG_CAMCMR_ECMP (1 << 4)
193
+ break;
91
+/* Complement CAM Compare */
194
+ default:
92
+#define REG_CAMCMR_CCAM (1 << 3)
195
+ return FPSysRegCheckFailed;
93
+/* Accept Broadcast Packet */
196
+ }
94
+#define REG_CAMCMR_ABP (1 << 2)
95
+/* Accept Multicast Packet */
96
+#define REG_CAMCMR_AMP (1 << 1)
97
+/* Accept Unicast Packet */
98
+#define REG_CAMCMR_AUP (1 << 0)
99
+
100
+/* REG_MCMDR fields */
101
+/* Software Reset */
102
+#define REG_MCMDR_SWR (1 << 24)
103
+/* Internal Loopback Select */
104
+#define REG_MCMDR_LBK (1 << 21)
105
+/* Operation Mode Select */
106
+#define REG_MCMDR_OPMOD (1 << 20)
107
+/* Enable MDC Clock Generation */
108
+#define REG_MCMDR_ENMDC (1 << 19)
109
+/* Full-Duplex Mode Select */
110
+#define REG_MCMDR_FDUP (1 << 18)
111
+/* Enable SQE Checking */
112
+#define REG_MCMDR_ENSEQ (1 << 17)
113
+/* Send PAUSE Frame */
114
+#define REG_MCMDR_SDPZ (1 << 16)
115
+/* No Defer */
116
+#define REG_MCMDR_NDEF (1 << 9)
117
+/* Frame Transmission On */
118
+#define REG_MCMDR_TXON (1 << 8)
119
+/* Strip CRC Checksum */
120
+#define REG_MCMDR_SPCRC (1 << 5)
121
+/* Accept CRC Error Packet */
122
+#define REG_MCMDR_AEP (1 << 4)
123
+/* Accept Control Packet */
124
+#define REG_MCMDR_ACP (1 << 3)
125
+/* Accept Runt Packet */
126
+#define REG_MCMDR_ARP (1 << 2)
127
+/* Accept Long Packet */
128
+#define REG_MCMDR_ALP (1 << 1)
129
+/* Frame Reception On */
130
+#define REG_MCMDR_RXON (1 << 0)
131
+
132
+/* REG_MIEN fields */
133
+/* Enable Transmit Descriptor Unavailable Interrupt */
134
+#define REG_MIEN_ENTDU (1 << 23)
135
+/* Enable Transmit Completion Interrupt */
136
+#define REG_MIEN_ENTXCP (1 << 18)
137
+/* Enable Transmit Interrupt */
138
+#define REG_MIEN_ENTXINTR (1 << 16)
139
+/* Enable Receive Descriptor Unavailable Interrupt */
140
+#define REG_MIEN_ENRDU (1 << 10)
141
+/* Enable Receive Good Interrupt */
142
+#define REG_MIEN_ENRXGD (1 << 4)
143
+/* Enable Receive Interrupt */
144
+#define REG_MIEN_ENRXINTR (1 << 0)
145
+
146
+/* REG_MISTA fields */
147
+/* TODO: Add error fields and support simulated errors? */
148
+/* Transmit Bus Error Interrupt */
149
+#define REG_MISTA_TXBERR (1 << 24)
150
+/* Transmit Descriptor Unavailable Interrupt */
151
+#define REG_MISTA_TDU (1 << 23)
152
+/* Transmit Completion Interrupt */
153
+#define REG_MISTA_TXCP (1 << 18)
154
+/* Transmit Interrupt */
155
+#define REG_MISTA_TXINTR (1 << 16)
156
+/* Receive Bus Error Interrupt */
157
+#define REG_MISTA_RXBERR (1 << 11)
158
+/* Receive Descriptor Unavailable Interrupt */
159
+#define REG_MISTA_RDU (1 << 10)
160
+/* DMA Early Notification Interrupt */
161
+#define REG_MISTA_DENI (1 << 9)
162
+/* Maximum Frame Length Interrupt */
163
+#define REG_MISTA_DFOI (1 << 8)
164
+/* Receive Good Interrupt */
165
+#define REG_MISTA_RXGD (1 << 4)
166
+/* Packet Too Long Interrupt */
167
+#define REG_MISTA_PTLE (1 << 3)
168
+/* Receive Interrupt */
169
+#define REG_MISTA_RXINTR (1 << 0)
170
+
171
+/* REG_MGSTA fields */
172
+/* Transmission Halted */
173
+#define REG_MGSTA_TXHA (1 << 11)
174
+/* Receive Halted */
175
+#define REG_MGSTA_RXHA (1 << 11)
176
+
177
+/* REG_DMARFC fields */
178
+/* Maximum Receive Frame Length */
179
+#define REG_DMARFC_RXMS(word) extract32((word), 0, 16)
180
+
181
+/* REG MIIDA fields */
182
+/* Busy Bit */
183
+#define REG_MIIDA_BUSY (1 << 17)
184
+
185
+/* Transmit and receive descriptors */
186
+typedef struct NPCM7xxEMCTxDesc NPCM7xxEMCTxDesc;
187
+typedef struct NPCM7xxEMCRxDesc NPCM7xxEMCRxDesc;
188
+
189
+struct NPCM7xxEMCTxDesc {
190
+ uint32_t flags;
191
+ uint32_t txbsa;
192
+ uint32_t status_and_length;
193
+ uint32_t ntxdsa;
194
+};
195
+
196
+struct NPCM7xxEMCRxDesc {
197
+ uint32_t status_and_length;
198
+ uint32_t rxbsa;
199
+ uint32_t reserved;
200
+ uint32_t nrxdsa;
201
+};
202
+
203
+/* NPCM7xxEMCTxDesc.flags values */
204
+/* Owner: 0 = cpu, 1 = emc */
205
+#define TX_DESC_FLAG_OWNER_MASK (1 << 31)
206
+/* Transmit interrupt enable */
207
+#define TX_DESC_FLAG_INTEN (1 << 2)
208
+/* CRC append */
209
+#define TX_DESC_FLAG_CRCAPP (1 << 1)
210
+/* Padding enable */
211
+#define TX_DESC_FLAG_PADEN (1 << 0)
212
+
213
+/* NPCM7xxEMCTxDesc.status_and_length values */
214
+/* Collision count */
215
+#define TX_DESC_STATUS_CCNT_SHIFT 28
216
+#define TX_DESC_STATUS_CCNT_BITSIZE 4
217
+/* SQE error */
218
+#define TX_DESC_STATUS_SQE (1 << 26)
219
+/* Transmission paused */
220
+#define TX_DESC_STATUS_PAU (1 << 25)
221
+/* P transmission halted */
222
+#define TX_DESC_STATUS_TXHA (1 << 24)
223
+/* Late collision */
224
+#define TX_DESC_STATUS_LC (1 << 23)
225
+/* Transmission abort */
226
+#define TX_DESC_STATUS_TXABT (1 << 22)
227
+/* No carrier sense */
228
+#define TX_DESC_STATUS_NCS (1 << 21)
229
+/* Defer exceed */
230
+#define TX_DESC_STATUS_EXDEF (1 << 20)
231
+/* Transmission complete */
232
+#define TX_DESC_STATUS_TXCP (1 << 19)
233
+/* Transmission deferred */
234
+#define TX_DESC_STATUS_DEF (1 << 17)
235
+/* Transmit interrupt */
236
+#define TX_DESC_STATUS_TXINTR (1 << 16)
237
+
238
+#define TX_DESC_PKT_LEN(word) extract32((word), 0, 16)
239
+
240
+/* Transmit buffer start address */
241
+#define TX_DESC_TXBSA(word) ((uint32_t) (word) & ~3u)
242
+
243
+/* Next transmit descriptor start address */
244
+#define TX_DESC_NTXDSA(word) ((uint32_t) (word) & ~3u)
245
+
246
+/* NPCM7xxEMCRxDesc.status_and_length values */
247
+/* Owner: 0b00 = cpu, 0b01 = undefined, 0b10 = emc, 0b11 = undefined */
248
+#define RX_DESC_STATUS_OWNER_SHIFT 30
249
+#define RX_DESC_STATUS_OWNER_BITSIZE 2
250
+#define RX_DESC_STATUS_OWNER_MASK (3 << RX_DESC_STATUS_OWNER_SHIFT)
251
+/* Runt packet */
252
+#define RX_DESC_STATUS_RP (1 << 22)
253
+/* Alignment error */
254
+#define RX_DESC_STATUS_ALIE (1 << 21)
255
+/* Frame reception complete */
256
+#define RX_DESC_STATUS_RXGD (1 << 20)
257
+/* Packet too long */
258
+#define RX_DESC_STATUS_PTLE (1 << 19)
259
+/* CRC error */
260
+#define RX_DESC_STATUS_CRCE (1 << 17)
261
+/* Receive interrupt */
262
+#define RX_DESC_STATUS_RXINTR (1 << 16)
263
+
264
+#define RX_DESC_PKT_LEN(word) extract32((word), 0, 16)
265
+
266
+/* Receive buffer start address */
267
+#define RX_DESC_RXBSA(word) ((uint32_t) (word) & ~3u)
268
+
269
+/* Next receive descriptor start address */
270
+#define RX_DESC_NRXDSA(word) ((uint32_t) (word) & ~3u)
271
+
272
+/* Minimum packet length, when TX_DESC_FLAG_PADEN is set. */
273
+#define MIN_PACKET_LENGTH 64
274
+
275
+struct NPCM7xxEMCState {
276
+ /*< private >*/
277
+ SysBusDevice parent;
278
+ /*< public >*/
279
+
280
+ MemoryRegion iomem;
281
+
282
+ qemu_irq tx_irq;
283
+ qemu_irq rx_irq;
284
+
285
+ NICState *nic;
286
+ NICConf conf;
287
+
288
+ /* 0 or 1, for log messages */
289
+ uint8_t emc_num;
290
+
291
+ uint32_t regs[NPCM7XX_NUM_EMC_REGS];
292
+
197
+
293
+ /*
198
+ /*
294
+ * tx is active. Set to true by TSDR and then switches off when out of
199
+ * FPCXT_NS is a special case: it has specific handling for
295
+ * descriptors. If the TXON bit in REG_MCMDR is off then this is off.
200
+ * "current FP state is inactive", and must do the PreserveFPState()
201
+ * but not the usual full set of actions done by ExecuteFPCheck().
202
+ * So we don't call vfp_access_check() and the callers must handle this.
296
+ */
203
+ */
297
+ bool tx_active;
204
+ if (regno != ARM_VFP_FPCXT_NS && !vfp_access_check(s)) {
298
+
205
+ return FPSysRegCheckDone;
299
+ /*
206
+ }
300
+ * rx is active. Set to true by RSDR and then switches off when out of
207
+ return FPSysRegCheckContinue;
301
+ * descriptors. If the RXON bit in REG_MCMDR is off then this is off.
302
+ */
303
+ bool rx_active;
304
+};
305
+
306
+typedef struct NPCM7xxEMCState NPCM7xxEMCState;
307
+
308
+#define TYPE_NPCM7XX_EMC "npcm7xx-emc"
309
+#define NPCM7XX_EMC(obj) \
310
+ OBJECT_CHECK(NPCM7xxEMCState, (obj), TYPE_NPCM7XX_EMC)
311
+
312
+#endif /* NPCM7XX_EMC_H */
313
diff --git a/hw/net/npcm7xx_emc.c b/hw/net/npcm7xx_emc.c
314
new file mode 100644
315
index XXXXXXX..XXXXXXX
316
--- /dev/null
317
+++ b/hw/net/npcm7xx_emc.c
318
@@ -XXX,XX +XXX,XX @@
319
+/*
320
+ * Nuvoton NPCM7xx EMC Module
321
+ *
322
+ * Copyright 2020 Google LLC
323
+ *
324
+ * This program is free software; you can redistribute it and/or modify it
325
+ * under the terms of the GNU General Public License as published by the
326
+ * Free Software Foundation; either version 2 of the License, or
327
+ * (at your option) any later version.
328
+ *
329
+ * This program is distributed in the hope that it will be useful, but WITHOUT
330
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
331
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
332
+ * for more details.
333
+ *
334
+ * Unsupported/unimplemented features:
335
+ * - MCMDR.FDUP (full duplex) is ignored, half duplex is not supported
336
+ * - Only CAM0 is supported, CAM[1-15] are not
337
+ * - writes to CAMEN.[1-15] are ignored, these bits always read as zeroes
338
+ * - MII is not implemented, MIIDA.BUSY and MIID always return zero
339
+ * - MCMDR.LBK is not implemented
340
+ * - MCMDR.{OPMOD,ENSQE,AEP,ARP} are not supported
341
+ * - H/W FIFOs are not supported, MCMDR.FFTCR is ignored
342
+ * - MGSTA.SQE is not supported
343
+ * - pause and control frames are not implemented
344
+ * - MGSTA.CCNT is not supported
345
+ * - MPCNT, DMARFS are not implemented
346
+ */
347
+
348
+#include "qemu/osdep.h"
349
+
350
+/* For crc32 */
351
+#include <zlib.h>
352
+
353
+#include "qemu-common.h"
354
+#include "hw/irq.h"
355
+#include "hw/qdev-clock.h"
356
+#include "hw/qdev-properties.h"
357
+#include "hw/net/npcm7xx_emc.h"
358
+#include "net/eth.h"
359
+#include "migration/vmstate.h"
360
+#include "qemu/bitops.h"
361
+#include "qemu/error-report.h"
362
+#include "qemu/log.h"
363
+#include "qemu/module.h"
364
+#include "qemu/units.h"
365
+#include "sysemu/dma.h"
366
+#include "trace.h"
367
+
368
+#define CRC_LENGTH 4
369
+
370
+/*
371
+ * The maximum size of a (layer 2) ethernet frame as defined by 802.3.
372
+ * 1518 = 6(dest macaddr) + 6(src macaddr) + 2(proto) + 4(crc) + 1500(payload)
373
+ * This does not include an additional 4 for the vlan field (802.1q).
374
+ */
375
+#define MAX_ETH_FRAME_SIZE 1518
376
+
377
+static const char *emc_reg_name(int regno)
378
+{
379
+#define REG(name) case REG_ ## name: return #name;
380
+ switch (regno) {
381
+ REG(CAMCMR)
382
+ REG(CAMEN)
383
+ REG(TXDLSA)
384
+ REG(RXDLSA)
385
+ REG(MCMDR)
386
+ REG(MIID)
387
+ REG(MIIDA)
388
+ REG(FFTCR)
389
+ REG(TSDR)
390
+ REG(RSDR)
391
+ REG(DMARFC)
392
+ REG(MIEN)
393
+ REG(MISTA)
394
+ REG(MGSTA)
395
+ REG(MPCNT)
396
+ REG(MRPC)
397
+ REG(MRPCC)
398
+ REG(MREPC)
399
+ REG(DMARFS)
400
+ REG(CTXDSA)
401
+ REG(CTXBSA)
402
+ REG(CRXDSA)
403
+ REG(CRXBSA)
404
+ case REG_CAMM_BASE + 0: return "CAM0M";
405
+ case REG_CAML_BASE + 0: return "CAM0L";
406
+ case REG_CAMM_BASE + 2 ... REG_CAMML_LAST:
407
+ /* Only CAM0 is supported, fold the others into something simple. */
408
+ if (regno & 1) {
409
+ return "CAM<n>L";
410
+ } else {
411
+ return "CAM<n>M";
412
+ }
413
+ default: return "UNKNOWN";
414
+ }
415
+#undef REG
416
+}
208
+}
417
+
209
+
418
+static void emc_reset(NPCM7xxEMCState *emc)
210
+static void gen_branch_fpInactive(DisasContext *s, TCGCond cond,
419
+{
211
+ TCGLabel *label)
420
+ trace_npcm7xx_emc_reset(emc->emc_num);
421
+
422
+ memset(&emc->regs[0], 0, sizeof(emc->regs));
423
+
424
+ /* These regs have non-zero reset values. */
425
+ emc->regs[REG_TXDLSA] = 0xfffffffc;
426
+ emc->regs[REG_RXDLSA] = 0xfffffffc;
427
+ emc->regs[REG_MIIDA] = 0x00900000;
428
+ emc->regs[REG_FFTCR] = 0x0101;
429
+ emc->regs[REG_DMARFC] = 0x0800;
430
+ emc->regs[REG_MPCNT] = 0x7fff;
431
+
432
+ emc->tx_active = false;
433
+ emc->rx_active = false;
434
+}
435
+
436
+static void npcm7xx_emc_reset(DeviceState *dev)
437
+{
438
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(dev);
439
+ emc_reset(emc);
440
+}
441
+
442
+static void emc_soft_reset(NPCM7xxEMCState *emc)
443
+{
212
+{
444
+ /*
213
+ /*
445
+ * The docs say at least MCMDR.{LBK,OPMOD} bits are not changed during a
214
+ * FPCXT_NS is a special case: it has specific handling for
446
+ * soft reset, but does not go into further detail. For now, KISS.
215
+ * "current FP state is inactive", and must do the PreserveFPState()
216
+ * but not the usual full set of actions done by ExecuteFPCheck().
217
+ * We don't have a TB flag that matches the fpInactive check, so we
218
+ * do it at runtime as we don't expect FPCXT_NS accesses to be frequent.
219
+ *
220
+ * Emit code that checks fpInactive and does a conditional
221
+ * branch to label based on it:
222
+ * if cond is TCG_COND_NE then branch if fpInactive != 0 (ie if inactive)
223
+ * if cond is TCG_COND_EQ then branch if fpInactive == 0 (ie if active)
447
+ */
224
+ */
448
+ uint32_t mcmdr = emc->regs[REG_MCMDR];
225
+ assert(cond == TCG_COND_EQ || cond == TCG_COND_NE);
449
+ emc_reset(emc);
226
+
450
+ emc->regs[REG_MCMDR] = mcmdr & (REG_MCMDR_LBK | REG_MCMDR_OPMOD);
227
+ /* fpInactive = FPCCR_NS.ASPEN == 1 && CONTROL.FPCA == 0 */
451
+
228
+ TCGv_i32 aspen, fpca;
452
+ qemu_set_irq(emc->tx_irq, 0);
229
+ aspen = load_cpu_field(v7m.fpccr[M_REG_NS]);
453
+ qemu_set_irq(emc->rx_irq, 0);
230
+ fpca = load_cpu_field(v7m.control[M_REG_S]);
231
+ tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
232
+ tcg_gen_xori_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
233
+ tcg_gen_andi_i32(fpca, fpca, R_V7M_CONTROL_FPCA_MASK);
234
+ tcg_gen_or_i32(fpca, fpca, aspen);
235
+ tcg_gen_brcondi_i32(tcg_invert_cond(cond), fpca, 0, label);
236
+ tcg_temp_free_i32(aspen);
237
+ tcg_temp_free_i32(fpca);
454
+}
238
+}
455
+
239
+
456
+static void emc_set_link(NetClientState *nc)
240
+static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
241
+ fp_sysreg_loadfn *loadfn,
242
+ void *opaque)
457
+{
243
+{
458
+ /* Nothing to do yet. */
244
+ /* Do a write to an M-profile floating point system register */
459
+}
245
+ TCGv_i32 tmp;
460
+
246
+ TCGLabel *lab_end = NULL;
461
+/* MISTA.TXINTR is the union of the individual bits with their enables. */
247
+
462
+static void emc_update_mista_txintr(NPCM7xxEMCState *emc)
248
+ switch (fp_sysreg_checks(s, regno)) {
463
+{
249
+ case FPSysRegCheckFailed:
464
+ /* Only look at the bits we support. */
250
+ return false;
465
+ uint32_t mask = (REG_MISTA_TXBERR |
251
+ case FPSysRegCheckDone:
466
+ REG_MISTA_TDU |
252
+ return true;
467
+ REG_MISTA_TXCP);
253
+ case FPSysRegCheckContinue:
468
+ if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & mask) {
254
+ break;
469
+ emc->regs[REG_MISTA] |= REG_MISTA_TXINTR;
255
+ }
470
+ } else {
256
+
471
+ emc->regs[REG_MISTA] &= ~REG_MISTA_TXINTR;
257
+ switch (regno) {
472
+ }
258
+ case ARM_VFP_FPSCR:
473
+}
259
+ tmp = loadfn(s, opaque);
474
+
260
+ gen_helper_vfp_set_fpscr(cpu_env, tmp);
475
+/* MISTA.RXINTR is the union of the individual bits with their enables. */
261
+ tcg_temp_free_i32(tmp);
476
+static void emc_update_mista_rxintr(NPCM7xxEMCState *emc)
262
+ gen_lookup_tb(s);
477
+{
263
+ break;
478
+ /* Only look at the bits we support. */
264
+ case ARM_VFP_FPSCR_NZCVQC:
479
+ uint32_t mask = (REG_MISTA_RXBERR |
265
+ {
480
+ REG_MISTA_RDU |
266
+ TCGv_i32 fpscr;
481
+ REG_MISTA_RXGD);
267
+ tmp = loadfn(s, opaque);
482
+ if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & mask) {
268
+ if (dc_isar_feature(aa32_mve, s)) {
483
+ emc->regs[REG_MISTA] |= REG_MISTA_RXINTR;
269
+ /* QC is only present for MVE; otherwise RES0 */
484
+ } else {
270
+ TCGv_i32 qc = tcg_temp_new_i32();
485
+ emc->regs[REG_MISTA] &= ~REG_MISTA_RXINTR;
271
+ tcg_gen_andi_i32(qc, tmp, FPCR_QC);
486
+ }
272
+ /*
487
+}
273
+ * The 4 vfp.qc[] fields need only be "zero" vs "non-zero";
488
+
274
+ * here writing the same value into all elements is simplest.
489
+/* N.B. emc_update_mista_txintr must have already been called. */
275
+ */
490
+static void emc_update_tx_irq(NPCM7xxEMCState *emc)
276
+ tcg_gen_gvec_dup_i32(MO_32, offsetof(CPUARMState, vfp.qc),
491
+{
277
+ 16, 16, qc);
492
+ int level = !!(emc->regs[REG_MISTA] &
278
+ }
493
+ emc->regs[REG_MIEN] &
279
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
494
+ REG_MISTA_TXINTR);
280
+ fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
495
+ trace_npcm7xx_emc_update_tx_irq(level);
281
+ tcg_gen_andi_i32(fpscr, fpscr, ~FPCR_NZCV_MASK);
496
+ qemu_set_irq(emc->tx_irq, level);
282
+ tcg_gen_or_i32(fpscr, fpscr, tmp);
497
+}
283
+ store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
498
+
284
+ tcg_temp_free_i32(tmp);
499
+/* N.B. emc_update_mista_rxintr must have already been called. */
285
+ break;
500
+static void emc_update_rx_irq(NPCM7xxEMCState *emc)
286
+ }
501
+{
287
+ case ARM_VFP_FPCXT_NS:
502
+ int level = !!(emc->regs[REG_MISTA] &
288
+ lab_end = gen_new_label();
503
+ emc->regs[REG_MIEN] &
289
+ /* fpInactive case: write is a NOP, so branch to end */
504
+ REG_MISTA_RXINTR);
290
+ gen_branch_fpInactive(s, TCG_COND_NE, lab_end);
505
+ trace_npcm7xx_emc_update_rx_irq(level);
506
+ qemu_set_irq(emc->rx_irq, level);
507
+}
508
+
509
+/* Update IRQ states due to changes in MIEN,MISTA. */
510
+static void emc_update_irq_from_reg_change(NPCM7xxEMCState *emc)
511
+{
512
+ emc_update_mista_txintr(emc);
513
+ emc_update_tx_irq(emc);
514
+
515
+ emc_update_mista_rxintr(emc);
516
+ emc_update_rx_irq(emc);
517
+}
518
+
519
+static int emc_read_tx_desc(dma_addr_t addr, NPCM7xxEMCTxDesc *desc)
520
+{
521
+ if (dma_memory_read(&address_space_memory, addr, desc, sizeof(*desc))) {
522
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read descriptor @ 0x%"
523
+ HWADDR_PRIx "\n", __func__, addr);
524
+ return -1;
525
+ }
526
+ desc->flags = le32_to_cpu(desc->flags);
527
+ desc->txbsa = le32_to_cpu(desc->txbsa);
528
+ desc->status_and_length = le32_to_cpu(desc->status_and_length);
529
+ desc->ntxdsa = le32_to_cpu(desc->ntxdsa);
530
+ return 0;
531
+}
532
+
533
+static int emc_write_tx_desc(const NPCM7xxEMCTxDesc *desc, dma_addr_t addr)
534
+{
535
+ NPCM7xxEMCTxDesc le_desc;
536
+
537
+ le_desc.flags = cpu_to_le32(desc->flags);
538
+ le_desc.txbsa = cpu_to_le32(desc->txbsa);
539
+ le_desc.status_and_length = cpu_to_le32(desc->status_and_length);
540
+ le_desc.ntxdsa = cpu_to_le32(desc->ntxdsa);
541
+ if (dma_memory_write(&address_space_memory, addr, &le_desc,
542
+ sizeof(le_desc))) {
543
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to write descriptor @ 0x%"
544
+ HWADDR_PRIx "\n", __func__, addr);
545
+ return -1;
546
+ }
547
+ return 0;
548
+}
549
+
550
+static int emc_read_rx_desc(dma_addr_t addr, NPCM7xxEMCRxDesc *desc)
551
+{
552
+ if (dma_memory_read(&address_space_memory, addr, desc, sizeof(*desc))) {
553
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read descriptor @ 0x%"
554
+ HWADDR_PRIx "\n", __func__, addr);
555
+ return -1;
556
+ }
557
+ desc->status_and_length = le32_to_cpu(desc->status_and_length);
558
+ desc->rxbsa = le32_to_cpu(desc->rxbsa);
559
+ desc->reserved = le32_to_cpu(desc->reserved);
560
+ desc->nrxdsa = le32_to_cpu(desc->nrxdsa);
561
+ return 0;
562
+}
563
+
564
+static int emc_write_rx_desc(const NPCM7xxEMCRxDesc *desc, dma_addr_t addr)
565
+{
566
+ NPCM7xxEMCRxDesc le_desc;
567
+
568
+ le_desc.status_and_length = cpu_to_le32(desc->status_and_length);
569
+ le_desc.rxbsa = cpu_to_le32(desc->rxbsa);
570
+ le_desc.reserved = cpu_to_le32(desc->reserved);
571
+ le_desc.nrxdsa = cpu_to_le32(desc->nrxdsa);
572
+ if (dma_memory_write(&address_space_memory, addr, &le_desc,
573
+ sizeof(le_desc))) {
574
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to write descriptor @ 0x%"
575
+ HWADDR_PRIx "\n", __func__, addr);
576
+ return -1;
577
+ }
578
+ return 0;
579
+}
580
+
581
+static void emc_set_mista(NPCM7xxEMCState *emc, uint32_t flags)
582
+{
583
+ trace_npcm7xx_emc_set_mista(flags);
584
+ emc->regs[REG_MISTA] |= flags;
585
+ if (extract32(flags, 16, 16)) {
586
+ emc_update_mista_txintr(emc);
587
+ }
588
+ if (extract32(flags, 0, 16)) {
589
+ emc_update_mista_rxintr(emc);
590
+ }
591
+}
592
+
593
+static void emc_halt_tx(NPCM7xxEMCState *emc, uint32_t mista_flag)
594
+{
595
+ emc->tx_active = false;
596
+ emc_set_mista(emc, mista_flag);
597
+}
598
+
599
+static void emc_halt_rx(NPCM7xxEMCState *emc, uint32_t mista_flag)
600
+{
601
+ emc->rx_active = false;
602
+ emc_set_mista(emc, mista_flag);
603
+}
604
+
605
+static void emc_set_next_tx_descriptor(NPCM7xxEMCState *emc,
606
+ const NPCM7xxEMCTxDesc *tx_desc,
607
+ uint32_t desc_addr)
608
+{
609
+ /* Update the current descriptor, if only to reset the owner flag. */
610
+ if (emc_write_tx_desc(tx_desc, desc_addr)) {
611
+ /*
291
+ /*
612
+ * We just read it so this shouldn't generally happen.
292
+ * !fpInactive: if FPU disabled, take NOCP exception;
613
+ * Error already reported.
293
+ * otherwise PreserveFPState(), and then FPCXT_NS writes
294
+ * behave the same as FPCXT_S writes.
614
+ */
295
+ */
615
+ emc_set_mista(emc, REG_MISTA_TXBERR);
296
+ if (s->fp_excp_el) {
616
+ }
297
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
617
+ emc->regs[REG_CTXDSA] = TX_DESC_NTXDSA(tx_desc->ntxdsa);
298
+ syn_uncategorized(), s->fp_excp_el);
618
+}
299
+ /*
619
+
300
+ * This was only a conditional exception, so override
620
+static void emc_set_next_rx_descriptor(NPCM7xxEMCState *emc,
301
+ * gen_exception_insn()'s default to DISAS_NORETURN
621
+ const NPCM7xxEMCRxDesc *rx_desc,
302
+ */
622
+ uint32_t desc_addr)
303
+ s->base.is_jmp = DISAS_NEXT;
623
+{
304
+ break;
624
+ /* Update the current descriptor, if only to reset the owner flag. */
305
+ }
625
+ if (emc_write_rx_desc(rx_desc, desc_addr)) {
306
+ gen_preserve_fp_state(s);
307
+ /* fall through */
308
+ case ARM_VFP_FPCXT_S:
309
+ {
310
+ TCGv_i32 sfpa, control;
626
+ /*
311
+ /*
627
+ * We just read it so this shouldn't generally happen.
312
+ * Set FPSCR and CONTROL.SFPA from value; the new FPSCR takes
628
+ * Error already reported.
313
+ * bits [27:0] from value and zeroes bits [31:28].
629
+ */
314
+ */
630
+ emc_set_mista(emc, REG_MISTA_RXBERR);
315
+ tmp = loadfn(s, opaque);
631
+ }
316
+ sfpa = tcg_temp_new_i32();
632
+ emc->regs[REG_CRXDSA] = RX_DESC_NRXDSA(rx_desc->nrxdsa);
317
+ tcg_gen_shri_i32(sfpa, tmp, 31);
633
+}
318
+ control = load_cpu_field(v7m.control[M_REG_S]);
634
+
319
+ tcg_gen_deposit_i32(control, control, sfpa,
635
+static void emc_try_send_next_packet(NPCM7xxEMCState *emc)
320
+ R_V7M_CONTROL_SFPA_SHIFT, 1);
636
+{
321
+ store_cpu_field(control, v7m.control[M_REG_S]);
637
+ /* Working buffer for sending out packets. Most packets fit in this. */
322
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
638
+#define TX_BUFFER_SIZE 2048
323
+ gen_helper_vfp_set_fpscr(cpu_env, tmp);
639
+ uint8_t tx_send_buffer[TX_BUFFER_SIZE];
324
+ tcg_temp_free_i32(tmp);
640
+ uint32_t desc_addr = TX_DESC_NTXDSA(emc->regs[REG_CTXDSA]);
325
+ tcg_temp_free_i32(sfpa);
641
+ NPCM7xxEMCTxDesc tx_desc;
326
+ break;
642
+ uint32_t next_buf_addr, length;
327
+ }
643
+ uint8_t *buf;
328
+ case ARM_VFP_VPR:
644
+ g_autofree uint8_t *malloced_buf = NULL;
329
+ /* Behaves as NOP if not privileged */
645
+
330
+ if (IS_USER(s)) {
646
+ if (emc_read_tx_desc(desc_addr, &tx_desc)) {
331
+ break;
647
+ /* Error reading descriptor, already reported. */
648
+ emc_halt_tx(emc, REG_MISTA_TXBERR);
649
+ emc_update_tx_irq(emc);
650
+ return;
651
+ }
652
+
653
+ /* Nothing we can do if we don't own the descriptor. */
654
+ if (!(tx_desc.flags & TX_DESC_FLAG_OWNER_MASK)) {
655
+ trace_npcm7xx_emc_cpu_owned_desc(desc_addr);
656
+ emc_halt_tx(emc, REG_MISTA_TDU);
657
+ emc_update_tx_irq(emc);
658
+ return;
659
+ }
660
+
661
+ /* Give the descriptor back regardless of what happens. */
662
+ tx_desc.flags &= ~TX_DESC_FLAG_OWNER_MASK;
663
+ tx_desc.status_and_length &= 0xffff;
664
+
665
+ /*
666
+ * Despite the h/w documentation saying the tx buffer is word aligned,
667
+ * the linux driver does not word align the buffer. There is value in not
668
+ * aligning the buffer: See the description of NET_IP_ALIGN in linux
669
+ * kernel sources.
670
+ */
671
+ next_buf_addr = tx_desc.txbsa;
672
+ emc->regs[REG_CTXBSA] = next_buf_addr;
673
+ length = TX_DESC_PKT_LEN(tx_desc.status_and_length);
674
+ buf = &tx_send_buffer[0];
675
+
676
+ if (length > sizeof(tx_send_buffer)) {
677
+ malloced_buf = g_malloc(length);
678
+ buf = malloced_buf;
679
+ }
680
+
681
+ if (dma_memory_read(&address_space_memory, next_buf_addr, buf, length)) {
682
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read packet @ 0x%x\n",
683
+ __func__, next_buf_addr);
684
+ emc_set_mista(emc, REG_MISTA_TXBERR);
685
+ emc_set_next_tx_descriptor(emc, &tx_desc, desc_addr);
686
+ emc_update_tx_irq(emc);
687
+ trace_npcm7xx_emc_tx_done(emc->regs[REG_CTXDSA]);
688
+ return;
689
+ }
690
+
691
+ if ((tx_desc.flags & TX_DESC_FLAG_PADEN) && (length < MIN_PACKET_LENGTH)) {
692
+ memset(buf + length, 0, MIN_PACKET_LENGTH - length);
693
+ length = MIN_PACKET_LENGTH;
694
+ }
695
+
696
+ /* N.B. emc_receive can get called here. */
697
+ qemu_send_packet(qemu_get_queue(emc->nic), buf, length);
698
+ trace_npcm7xx_emc_sent_packet(length);
699
+
700
+ tx_desc.status_and_length |= TX_DESC_STATUS_TXCP;
701
+ if (tx_desc.flags & TX_DESC_FLAG_INTEN) {
702
+ emc_set_mista(emc, REG_MISTA_TXCP);
703
+ }
704
+ if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & REG_MISTA_TXINTR) {
705
+ tx_desc.status_and_length |= TX_DESC_STATUS_TXINTR;
706
+ }
707
+
708
+ emc_set_next_tx_descriptor(emc, &tx_desc, desc_addr);
709
+ emc_update_tx_irq(emc);
710
+ trace_npcm7xx_emc_tx_done(emc->regs[REG_CTXDSA]);
711
+}
712
+
713
+static bool emc_can_receive(NetClientState *nc)
714
+{
715
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(qemu_get_nic_opaque(nc));
716
+
717
+ bool can_receive = emc->rx_active;
718
+ trace_npcm7xx_emc_can_receive(can_receive);
719
+ return can_receive;
720
+}
721
+
722
+/* If result is false then *fail_reason contains the reason. */
723
+static bool emc_receive_filter1(NPCM7xxEMCState *emc, const uint8_t *buf,
724
+ size_t len, const char **fail_reason)
725
+{
726
+ eth_pkt_types_e pkt_type = get_eth_packet_type(PKT_GET_ETH_HDR(buf));
727
+
728
+ switch (pkt_type) {
729
+ case ETH_PKT_BCAST:
730
+ if (emc->regs[REG_CAMCMR] & REG_CAMCMR_CCAM) {
731
+ return true;
732
+ } else {
733
+ *fail_reason = "Broadcast packet disabled";
734
+ return !!(emc->regs[REG_CAMCMR] & REG_CAMCMR_ABP);
735
+ }
332
+ }
736
+ case ETH_PKT_MCAST:
333
+ tmp = loadfn(s, opaque);
737
+ if (emc->regs[REG_CAMCMR] & REG_CAMCMR_CCAM) {
334
+ store_cpu_field(tmp, v7m.vpr);
738
+ return true;
335
+ break;
739
+ } else {
336
+ case ARM_VFP_P0:
740
+ *fail_reason = "Multicast packet disabled";
337
+ {
741
+ return !!(emc->regs[REG_CAMCMR] & REG_CAMCMR_AMP);
338
+ TCGv_i32 vpr;
742
+ }
339
+ tmp = loadfn(s, opaque);
743
+ case ETH_PKT_UCAST: {
340
+ vpr = load_cpu_field(v7m.vpr);
744
+ bool matches;
341
+ tcg_gen_deposit_i32(vpr, vpr, tmp,
745
+ if (emc->regs[REG_CAMCMR] & REG_CAMCMR_AUP) {
342
+ R_V7M_VPR_P0_SHIFT, R_V7M_VPR_P0_LENGTH);
746
+ return true;
343
+ store_cpu_field(vpr, v7m.vpr);
747
+ }
344
+ tcg_temp_free_i32(tmp);
748
+ matches = ((emc->regs[REG_CAMCMR] & REG_CAMCMR_ECMP) &&
345
+ break;
749
+ /* We only support one CAM register, CAM0. */
750
+ (emc->regs[REG_CAMEN] & (1 << 0)) &&
751
+ memcmp(buf, emc->conf.macaddr.a, ETH_ALEN) == 0);
752
+ if (emc->regs[REG_CAMCMR] & REG_CAMCMR_CCAM) {
753
+ *fail_reason = "MACADDR matched, comparison complemented";
754
+ return !matches;
755
+ } else {
756
+ *fail_reason = "MACADDR didn't match";
757
+ return matches;
758
+ }
759
+ }
346
+ }
760
+ default:
347
+ default:
761
+ g_assert_not_reached();
348
+ g_assert_not_reached();
762
+ }
349
+ }
350
+ if (lab_end) {
351
+ gen_set_label(lab_end);
352
+ }
353
+ return true;
763
+}
354
+}
764
+
355
+
765
+static bool emc_receive_filter(NPCM7xxEMCState *emc, const uint8_t *buf,
356
+static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
766
+ size_t len)
357
+ fp_sysreg_storefn *storefn,
358
+ void *opaque)
767
+{
359
+{
768
+ const char *fail_reason = NULL;
360
+ /* Do a read from an M-profile floating point system register */
769
+ bool ok = emc_receive_filter1(emc, buf, len, &fail_reason);
361
+ TCGv_i32 tmp;
770
+ if (!ok) {
362
+ TCGLabel *lab_end = NULL;
771
+ trace_npcm7xx_emc_packet_filtered_out(fail_reason);
363
+ bool lookup_tb = false;
772
+ }
364
+
773
+ return ok;
365
+ switch (fp_sysreg_checks(s, regno)) {
774
+}
366
+ case FPSysRegCheckFailed:
775
+
367
+ return false;
776
+static ssize_t emc_receive(NetClientState *nc, const uint8_t *buf, size_t len1)
368
+ case FPSysRegCheckDone:
777
+{
369
+ return true;
778
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(qemu_get_nic_opaque(nc));
370
+ case FPSysRegCheckContinue:
779
+ const uint32_t len = len1;
371
+ break;
780
+ size_t max_frame_len;
372
+ }
781
+ bool long_frame;
373
+
782
+ uint32_t desc_addr;
374
+ if (regno == ARM_VFP_FPSCR_NZCVQC && !dc_isar_feature(aa32_mve, s)) {
783
+ NPCM7xxEMCRxDesc rx_desc;
375
+ /* QC is RES0 without MVE, so NZCVQC simplifies to NZCV */
784
+ uint32_t crc;
376
+ regno = QEMU_VFP_FPSCR_NZCV;
785
+ uint8_t *crc_ptr;
377
+ }
786
+ uint32_t buf_addr;
378
+
787
+
379
+ switch (regno) {
788
+ trace_npcm7xx_emc_receiving_packet(len);
380
+ case ARM_VFP_FPSCR:
789
+
381
+ tmp = tcg_temp_new_i32();
790
+ if (!emc_can_receive(nc)) {
382
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
791
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Unexpected packet\n", __func__);
383
+ storefn(s, opaque, tmp);
792
+ return -1;
384
+ break;
793
+ }
385
+ case ARM_VFP_FPSCR_NZCVQC:
794
+
386
+ tmp = tcg_temp_new_i32();
795
+ if (len < ETH_HLEN ||
387
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
796
+ /* Defensive programming: drop unsupportable large packets. */
388
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCVQC_MASK);
797
+ len > 0xffff - CRC_LENGTH) {
389
+ storefn(s, opaque, tmp);
798
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Dropped frame of %u bytes\n",
390
+ break;
799
+ __func__, len);
391
+ case QEMU_VFP_FPSCR_NZCV:
800
+ return len;
801
+ }
802
+
803
+ /*
804
+ * DENI is set if EMC received the Length/Type field of the incoming
805
+ * packet, so it will be set regardless of what happens next.
806
+ */
807
+ emc_set_mista(emc, REG_MISTA_DENI);
808
+
809
+ if (!emc_receive_filter(emc, buf, len)) {
810
+ emc_update_rx_irq(emc);
811
+ return len;
812
+ }
813
+
814
+ /* Huge frames (> DMARFC) are dropped. */
815
+ max_frame_len = REG_DMARFC_RXMS(emc->regs[REG_DMARFC]);
816
+ if (len + CRC_LENGTH > max_frame_len) {
817
+ trace_npcm7xx_emc_packet_dropped(len);
818
+ emc_set_mista(emc, REG_MISTA_DFOI);
819
+ emc_update_rx_irq(emc);
820
+ return len;
821
+ }
822
+
823
+ /*
824
+ * Long Frames (> MAX_ETH_FRAME_SIZE) are also dropped, unless MCMDR.ALP
825
+ * is set.
826
+ */
827
+ long_frame = false;
828
+ if (len + CRC_LENGTH > MAX_ETH_FRAME_SIZE) {
829
+ if (emc->regs[REG_MCMDR] & REG_MCMDR_ALP) {
830
+ long_frame = true;
831
+ } else {
832
+ trace_npcm7xx_emc_packet_dropped(len);
833
+ emc_set_mista(emc, REG_MISTA_PTLE);
834
+ emc_update_rx_irq(emc);
835
+ return len;
836
+ }
837
+ }
838
+
839
+ desc_addr = RX_DESC_NRXDSA(emc->regs[REG_CRXDSA]);
840
+ if (emc_read_rx_desc(desc_addr, &rx_desc)) {
841
+ /* Error reading descriptor, already reported. */
842
+ emc_halt_rx(emc, REG_MISTA_RXBERR);
843
+ emc_update_rx_irq(emc);
844
+ return len;
845
+ }
846
+
847
+ /* Nothing we can do if we don't own the descriptor. */
848
+ if (!(rx_desc.status_and_length & RX_DESC_STATUS_OWNER_MASK)) {
849
+ trace_npcm7xx_emc_cpu_owned_desc(desc_addr);
850
+ emc_halt_rx(emc, REG_MISTA_RDU);
851
+ emc_update_rx_irq(emc);
852
+ return len;
853
+ }
854
+
855
+ crc = 0;
856
+ crc_ptr = (uint8_t *) &crc;
857
+ if (!(emc->regs[REG_MCMDR] & REG_MCMDR_SPCRC)) {
858
+ crc = cpu_to_be32(crc32(~0, buf, len));
859
+ }
860
+
861
+ /* Give the descriptor back regardless of what happens. */
862
+ rx_desc.status_and_length &= ~RX_DESC_STATUS_OWNER_MASK;
863
+
864
+ buf_addr = rx_desc.rxbsa;
865
+ emc->regs[REG_CRXBSA] = buf_addr;
866
+ if (dma_memory_write(&address_space_memory, buf_addr, buf, len) ||
867
+ (!(emc->regs[REG_MCMDR] & REG_MCMDR_SPCRC) &&
868
+ dma_memory_write(&address_space_memory, buf_addr + len, crc_ptr,
869
+ 4))) {
870
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Bus error writing packet\n",
871
+ __func__);
872
+ emc_set_mista(emc, REG_MISTA_RXBERR);
873
+ emc_set_next_rx_descriptor(emc, &rx_desc, desc_addr);
874
+ emc_update_rx_irq(emc);
875
+ trace_npcm7xx_emc_rx_done(emc->regs[REG_CRXDSA]);
876
+ return len;
877
+ }
878
+
879
+ trace_npcm7xx_emc_received_packet(len);
880
+
881
+ /* Note: We've already verified len+4 <= 0xffff. */
882
+ rx_desc.status_and_length = len;
883
+ if (!(emc->regs[REG_MCMDR] & REG_MCMDR_SPCRC)) {
884
+ rx_desc.status_and_length += 4;
885
+ }
886
+ rx_desc.status_and_length |= RX_DESC_STATUS_RXGD;
887
+ emc_set_mista(emc, REG_MISTA_RXGD);
888
+
889
+ if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & REG_MISTA_RXINTR) {
890
+ rx_desc.status_and_length |= RX_DESC_STATUS_RXINTR;
891
+ }
892
+ if (long_frame) {
893
+ rx_desc.status_and_length |= RX_DESC_STATUS_PTLE;
894
+ }
895
+
896
+ emc_set_next_rx_descriptor(emc, &rx_desc, desc_addr);
897
+ emc_update_rx_irq(emc);
898
+ trace_npcm7xx_emc_rx_done(emc->regs[REG_CRXDSA]);
899
+ return len;
900
+}
901
+
902
+static void emc_try_receive_next_packet(NPCM7xxEMCState *emc)
903
+{
904
+ if (emc_can_receive(qemu_get_queue(emc->nic))) {
905
+ qemu_flush_queued_packets(qemu_get_queue(emc->nic));
906
+ }
907
+}
908
+
909
+static uint64_t npcm7xx_emc_read(void *opaque, hwaddr offset, unsigned size)
910
+{
911
+ NPCM7xxEMCState *emc = opaque;
912
+ uint32_t reg = offset / sizeof(uint32_t);
913
+ uint32_t result;
914
+
915
+ if (reg >= NPCM7XX_NUM_EMC_REGS) {
916
+ qemu_log_mask(LOG_GUEST_ERROR,
917
+ "%s: Invalid offset 0x%04" HWADDR_PRIx "\n",
918
+ __func__, offset);
919
+ return 0;
920
+ }
921
+
922
+ switch (reg) {
923
+ case REG_MIID:
924
+ /*
392
+ /*
925
+ * We don't implement MII. For determinism, always return zero as
393
+ * Read just NZCV; this is a special case to avoid the
926
+ * writes record the last value written for debugging purposes.
394
+ * helper call for the "VMRS to CPSR.NZCV" insn.
927
+ */
395
+ */
928
+ qemu_log_mask(LOG_UNIMP, "%s: Read of MIID, returning 0\n", __func__);
396
+ tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
929
+ result = 0;
397
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
930
+ break;
398
+ storefn(s, opaque, tmp);
931
+ case REG_TSDR:
399
+ break;
932
+ case REG_RSDR:
400
+ case ARM_VFP_FPCXT_S:
933
+ qemu_log_mask(LOG_GUEST_ERROR,
401
+ {
934
+ "%s: Read of write-only reg, %s/%d\n",
402
+ TCGv_i32 control, sfpa, fpscr;
935
+ __func__, emc_reg_name(reg), reg);
403
+ /* Bits [27:0] from FPSCR, bit [31] from CONTROL.SFPA */
936
+ return 0;
404
+ tmp = tcg_temp_new_i32();
937
+ default:
405
+ sfpa = tcg_temp_new_i32();
938
+ result = emc->regs[reg];
406
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
939
+ break;
407
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
940
+ }
408
+ control = load_cpu_field(v7m.control[M_REG_S]);
941
+
409
+ tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
942
+ trace_npcm7xx_emc_reg_read(emc->emc_num, result, emc_reg_name(reg), reg);
410
+ tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
943
+ return result;
411
+ tcg_gen_or_i32(tmp, tmp, sfpa);
944
+}
412
+ tcg_temp_free_i32(sfpa);
945
+
413
+ /*
946
+static void npcm7xx_emc_write(void *opaque, hwaddr offset,
414
+ * Store result before updating FPSCR etc, in case
947
+ uint64_t v, unsigned size)
415
+ * it is a memory write which causes an exception.
948
+{
416
+ */
949
+ NPCM7xxEMCState *emc = opaque;
417
+ storefn(s, opaque, tmp);
950
+ uint32_t reg = offset / sizeof(uint32_t);
418
+ /*
951
+ uint32_t value = v;
419
+ * Now we must reset FPSCR from FPDSCR_NS, and clear
952
+
420
+ * CONTROL.SFPA; so we'll end the TB here.
953
+ g_assert(size == sizeof(uint32_t));
421
+ */
954
+
422
+ tcg_gen_andi_i32(control, control, ~R_V7M_CONTROL_SFPA_MASK);
955
+ if (reg >= NPCM7XX_NUM_EMC_REGS) {
423
+ store_cpu_field(control, v7m.control[M_REG_S]);
956
+ qemu_log_mask(LOG_GUEST_ERROR,
424
+ fpscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
957
+ "%s: Invalid offset 0x%04" HWADDR_PRIx "\n",
425
+ gen_helper_vfp_set_fpscr(cpu_env, fpscr);
958
+ __func__, offset);
426
+ tcg_temp_free_i32(fpscr);
959
+ return;
427
+ lookup_tb = true;
960
+ }
428
+ break;
961
+
429
+ }
962
+ trace_npcm7xx_emc_reg_write(emc->emc_num, emc_reg_name(reg), reg, value);
430
+ case ARM_VFP_FPCXT_NS:
963
+
431
+ {
964
+ switch (reg) {
432
+ TCGv_i32 control, sfpa, fpscr, fpdscr, zero;
965
+ case REG_CAMCMR:
433
+ TCGLabel *lab_active = gen_new_label();
966
+ emc->regs[reg] = value;
434
+
967
+ break;
435
+ lookup_tb = true;
968
+ case REG_CAMEN:
436
+
969
+ /* Only CAM0 is supported, don't pretend otherwise. */
437
+ gen_branch_fpInactive(s, TCG_COND_EQ, lab_active);
970
+ if (value & ~1) {
438
+ /* fpInactive case: reads as FPDSCR_NS */
971
+ qemu_log_mask(LOG_GUEST_ERROR,
439
+ TCGv_i32 tmp = load_cpu_field(v7m.fpdscr[M_REG_NS]);
972
+ "%s: Only CAM0 is supported, cannot enable others"
440
+ storefn(s, opaque, tmp);
973
+ ": 0x%x\n",
441
+ lab_end = gen_new_label();
974
+ __func__, value);
442
+ tcg_gen_br(lab_end);
975
+ }
443
+
976
+ emc->regs[reg] = value & 1;
444
+ gen_set_label(lab_active);
977
+ break;
445
+ /*
978
+ case REG_CAMM_BASE + 0:
446
+ * !fpInactive: if FPU disabled, take NOCP exception;
979
+ emc->regs[reg] = value;
447
+ * otherwise PreserveFPState(), and then FPCXT_NS
980
+ emc->conf.macaddr.a[0] = value >> 24;
448
+ * reads the same as FPCXT_S.
981
+ emc->conf.macaddr.a[1] = value >> 16;
449
+ */
982
+ emc->conf.macaddr.a[2] = value >> 8;
450
+ if (s->fp_excp_el) {
983
+ emc->conf.macaddr.a[3] = value >> 0;
451
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
984
+ break;
452
+ syn_uncategorized(), s->fp_excp_el);
985
+ case REG_CAML_BASE + 0:
453
+ /*
986
+ emc->regs[reg] = value;
454
+ * This was only a conditional exception, so override
987
+ emc->conf.macaddr.a[4] = value >> 24;
455
+ * gen_exception_insn()'s default to DISAS_NORETURN
988
+ emc->conf.macaddr.a[5] = value >> 16;
456
+ */
989
+ break;
457
+ s->base.is_jmp = DISAS_NEXT;
990
+ case REG_MCMDR: {
991
+ uint32_t prev;
992
+ if (value & REG_MCMDR_SWR) {
993
+ emc_soft_reset(emc);
994
+ /* On h/w the reset happens over multiple cycles. For now KISS. */
995
+ break;
458
+ break;
996
+ }
459
+ }
997
+ prev = emc->regs[reg];
460
+ gen_preserve_fp_state(s);
998
+ emc->regs[reg] = value;
461
+ tmp = tcg_temp_new_i32();
999
+ /* Update tx state. */
462
+ sfpa = tcg_temp_new_i32();
1000
+ if (!(prev & REG_MCMDR_TXON) &&
463
+ fpscr = tcg_temp_new_i32();
1001
+ (value & REG_MCMDR_TXON)) {
464
+ gen_helper_vfp_get_fpscr(fpscr, cpu_env);
1002
+ emc->regs[REG_CTXDSA] = emc->regs[REG_TXDLSA];
465
+ tcg_gen_andi_i32(tmp, fpscr, ~FPCR_NZCV_MASK);
1003
+ /*
466
+ control = load_cpu_field(v7m.control[M_REG_S]);
1004
+ * Linux kernel turns TX on with CPU still holding descriptor,
467
+ tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
1005
+ * which suggests we should wait for a write to TSDR before trying
468
+ tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
1006
+ * to send a packet: so we don't send one here.
469
+ tcg_gen_or_i32(tmp, tmp, sfpa);
1007
+ */
470
+ tcg_temp_free_i32(control);
1008
+ } else if ((prev & REG_MCMDR_TXON) &&
471
+ /* Store result before updating FPSCR, in case it faults */
1009
+ !(value & REG_MCMDR_TXON)) {
472
+ storefn(s, opaque, tmp);
1010
+ emc->regs[REG_MGSTA] |= REG_MGSTA_TXHA;
473
+ /* If SFPA is zero then set FPSCR from FPDSCR_NS */
474
+ fpdscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
475
+ zero = tcg_const_i32(0);
476
+ tcg_gen_movcond_i32(TCG_COND_EQ, fpscr, sfpa, zero, fpdscr, fpscr);
477
+ gen_helper_vfp_set_fpscr(cpu_env, fpscr);
478
+ tcg_temp_free_i32(zero);
479
+ tcg_temp_free_i32(sfpa);
480
+ tcg_temp_free_i32(fpdscr);
481
+ tcg_temp_free_i32(fpscr);
482
+ break;
483
+ }
484
+ case ARM_VFP_VPR:
485
+ /* Behaves as NOP if not privileged */
486
+ if (IS_USER(s)) {
487
+ break;
1011
+ }
488
+ }
1012
+ if (!(value & REG_MCMDR_TXON)) {
489
+ tmp = load_cpu_field(v7m.vpr);
1013
+ emc_halt_tx(emc, 0);
490
+ storefn(s, opaque, tmp);
491
+ break;
492
+ case ARM_VFP_P0:
493
+ tmp = load_cpu_field(v7m.vpr);
494
+ tcg_gen_extract_i32(tmp, tmp, R_V7M_VPR_P0_SHIFT, R_V7M_VPR_P0_LENGTH);
495
+ storefn(s, opaque, tmp);
496
+ break;
497
+ default:
498
+ g_assert_not_reached();
499
+ }
500
+
501
+ if (lab_end) {
502
+ gen_set_label(lab_end);
503
+ }
504
+ if (lookup_tb) {
505
+ gen_lookup_tb(s);
506
+ }
507
+ return true;
508
+}
509
+
510
+static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value)
511
+{
512
+ arg_VMSR_VMRS *a = opaque;
513
+
514
+ if (a->rt == 15) {
515
+ /* Set the 4 flag bits in the CPSR */
516
+ gen_set_nzcv(value);
517
+ tcg_temp_free_i32(value);
518
+ } else {
519
+ store_reg(s, a->rt, value);
520
+ }
521
+}
522
+
523
+static TCGv_i32 gpr_to_fp_sysreg(DisasContext *s, void *opaque)
524
+{
525
+ arg_VMSR_VMRS *a = opaque;
526
+
527
+ return load_reg(s, a->rt);
528
+}
529
+
530
+static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
531
+{
532
+ /*
533
+ * Accesses to R15 are UNPREDICTABLE; we choose to undef.
534
+ * FPSCR -> r15 is a special case which writes to the PSR flags;
535
+ * set a->reg to a special value to tell gen_M_fp_sysreg_read()
536
+ * we only care about the top 4 bits of FPSCR there.
537
+ */
538
+ if (a->rt == 15) {
539
+ if (a->l && a->reg == ARM_VFP_FPSCR) {
540
+ a->reg = QEMU_VFP_FPSCR_NZCV;
541
+ } else {
542
+ return false;
1014
+ }
543
+ }
1015
+ /* Update rx state. */
544
+ }
1016
+ if (!(prev & REG_MCMDR_RXON) &&
545
+
1017
+ (value & REG_MCMDR_RXON)) {
546
+ if (a->l) {
1018
+ emc->regs[REG_CRXDSA] = emc->regs[REG_RXDLSA];
547
+ /* VMRS, move FP system register to gp register */
1019
+ } else if ((prev & REG_MCMDR_RXON) &&
548
+ return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_gpr, a);
1020
+ !(value & REG_MCMDR_RXON)) {
549
+ } else {
1021
+ emc->regs[REG_MGSTA] |= REG_MGSTA_RXHA;
550
+ /* VMSR, move gp register to FP system register */
551
+ return gen_M_fp_sysreg_write(s, a->reg, gpr_to_fp_sysreg, a);
552
+ }
553
+}
554
+
555
+static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
556
+{
557
+ arg_vldr_sysreg *a = opaque;
558
+ uint32_t offset = a->imm;
559
+ TCGv_i32 addr;
560
+
561
+ if (!a->a) {
562
+ offset = -offset;
563
+ }
564
+
565
+ addr = load_reg(s, a->rn);
566
+ if (a->p) {
567
+ tcg_gen_addi_i32(addr, addr, offset);
568
+ }
569
+
570
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
571
+ gen_helper_v8m_stackcheck(cpu_env, addr);
572
+ }
573
+
574
+ gen_aa32_st_i32(s, value, addr, get_mem_index(s),
575
+ MO_UL | MO_ALIGN | s->be_data);
576
+ tcg_temp_free_i32(value);
577
+
578
+ if (a->w) {
579
+ /* writeback */
580
+ if (!a->p) {
581
+ tcg_gen_addi_i32(addr, addr, offset);
1022
+ }
582
+ }
1023
+ if (!(value & REG_MCMDR_RXON)) {
583
+ store_reg(s, a->rn, addr);
1024
+ emc_halt_rx(emc, 0);
584
+ } else {
585
+ tcg_temp_free_i32(addr);
586
+ }
587
+}
588
+
589
+static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
590
+{
591
+ arg_vldr_sysreg *a = opaque;
592
+ uint32_t offset = a->imm;
593
+ TCGv_i32 addr;
594
+ TCGv_i32 value = tcg_temp_new_i32();
595
+
596
+ if (!a->a) {
597
+ offset = -offset;
598
+ }
599
+
600
+ addr = load_reg(s, a->rn);
601
+ if (a->p) {
602
+ tcg_gen_addi_i32(addr, addr, offset);
603
+ }
604
+
605
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
606
+ gen_helper_v8m_stackcheck(cpu_env, addr);
607
+ }
608
+
609
+ gen_aa32_ld_i32(s, value, addr, get_mem_index(s),
610
+ MO_UL | MO_ALIGN | s->be_data);
611
+
612
+ if (a->w) {
613
+ /* writeback */
614
+ if (!a->p) {
615
+ tcg_gen_addi_i32(addr, addr, offset);
1025
+ }
616
+ }
1026
+ break;
617
+ store_reg(s, a->rn, addr);
1027
+ }
618
+ } else {
1028
+ case REG_TXDLSA:
619
+ tcg_temp_free_i32(addr);
1029
+ case REG_RXDLSA:
620
+ }
1030
+ case REG_DMARFC:
621
+ return value;
1031
+ case REG_MIID:
1032
+ emc->regs[reg] = value;
1033
+ break;
1034
+ case REG_MIEN:
1035
+ emc->regs[reg] = value;
1036
+ emc_update_irq_from_reg_change(emc);
1037
+ break;
1038
+ case REG_MISTA:
1039
+ /* Clear the bits that have 1 in "value". */
1040
+ emc->regs[reg] &= ~value;
1041
+ emc_update_irq_from_reg_change(emc);
1042
+ break;
1043
+ case REG_MGSTA:
1044
+ /* Clear the bits that have 1 in "value". */
1045
+ emc->regs[reg] &= ~value;
1046
+ break;
1047
+ case REG_TSDR:
1048
+ if (emc->regs[REG_MCMDR] & REG_MCMDR_TXON) {
1049
+ emc->tx_active = true;
1050
+ /* Keep trying to send packets until we run out. */
1051
+ while (emc->tx_active) {
1052
+ emc_try_send_next_packet(emc);
1053
+ }
1054
+ }
1055
+ break;
1056
+ case REG_RSDR:
1057
+ if (emc->regs[REG_MCMDR] & REG_MCMDR_RXON) {
1058
+ emc->rx_active = true;
1059
+ emc_try_receive_next_packet(emc);
1060
+ }
1061
+ break;
1062
+ case REG_MIIDA:
1063
+ emc->regs[reg] = value & ~REG_MIIDA_BUSY;
1064
+ break;
1065
+ case REG_MRPC:
1066
+ case REG_MRPCC:
1067
+ case REG_MREPC:
1068
+ case REG_CTXDSA:
1069
+ case REG_CTXBSA:
1070
+ case REG_CRXDSA:
1071
+ case REG_CRXBSA:
1072
+ qemu_log_mask(LOG_GUEST_ERROR,
1073
+ "%s: Write to read-only reg %s/%d\n",
1074
+ __func__, emc_reg_name(reg), reg);
1075
+ break;
1076
+ default:
1077
+ qemu_log_mask(LOG_UNIMP, "%s: Write to unimplemented reg %s/%d\n",
1078
+ __func__, emc_reg_name(reg), reg);
1079
+ break;
1080
+ }
1081
+}
622
+}
1082
+
623
+
1083
+static const struct MemoryRegionOps npcm7xx_emc_ops = {
624
+static bool trans_VLDR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
1084
+ .read = npcm7xx_emc_read,
1085
+ .write = npcm7xx_emc_write,
1086
+ .endianness = DEVICE_LITTLE_ENDIAN,
1087
+ .valid = {
1088
+ .min_access_size = 4,
1089
+ .max_access_size = 4,
1090
+ .unaligned = false,
1091
+ },
1092
+};
1093
+
1094
+static void emc_cleanup(NetClientState *nc)
1095
+{
625
+{
1096
+ /* Nothing to do yet. */
626
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
627
+ return false;
628
+ }
629
+ if (a->rn == 15) {
630
+ return false;
631
+ }
632
+ return gen_M_fp_sysreg_write(s, a->reg, memory_to_fp_sysreg, a);
1097
+}
633
+}
1098
+
634
+
1099
+static NetClientInfo net_npcm7xx_emc_info = {
635
+static bool trans_VSTR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
1100
+ .type = NET_CLIENT_DRIVER_NIC,
1101
+ .size = sizeof(NICState),
1102
+ .can_receive = emc_can_receive,
1103
+ .receive = emc_receive,
1104
+ .cleanup = emc_cleanup,
1105
+ .link_status_changed = emc_set_link,
1106
+};
1107
+
1108
+static void npcm7xx_emc_realize(DeviceState *dev, Error **errp)
1109
+{
636
+{
1110
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(dev);
637
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
1111
+ SysBusDevice *sbd = SYS_BUS_DEVICE(emc);
638
+ return false;
1112
+
639
+ }
1113
+ memory_region_init_io(&emc->iomem, OBJECT(emc), &npcm7xx_emc_ops, emc,
640
+ if (a->rn == 15) {
1114
+ TYPE_NPCM7XX_EMC, 4 * KiB);
641
+ return false;
1115
+ sysbus_init_mmio(sbd, &emc->iomem);
642
+ }
1116
+ sysbus_init_irq(sbd, &emc->tx_irq);
643
+ return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_memory, a);
1117
+ sysbus_init_irq(sbd, &emc->rx_irq);
1118
+
1119
+ qemu_macaddr_default_if_unset(&emc->conf.macaddr);
1120
+ emc->nic = qemu_new_nic(&net_npcm7xx_emc_info, &emc->conf,
1121
+ object_get_typename(OBJECT(dev)), dev->id, emc);
1122
+ qemu_format_nic_info_str(qemu_get_queue(emc->nic), emc->conf.macaddr.a);
1123
+}
644
+}
1124
+
645
+
1125
+static void npcm7xx_emc_unrealize(DeviceState *dev)
646
static bool trans_NOCP(DisasContext *s, arg_nocp *a)
1126
+{
647
{
1127
+ NPCM7xxEMCState *emc = NPCM7XX_EMC(dev);
648
/*
1128
+
649
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
1129
+ qemu_del_nic(emc->nic);
1130
+}
1131
+
1132
+static const VMStateDescription vmstate_npcm7xx_emc = {
1133
+ .name = TYPE_NPCM7XX_EMC,
1134
+ .version_id = 0,
1135
+ .minimum_version_id = 0,
1136
+ .fields = (VMStateField[]) {
1137
+ VMSTATE_UINT8(emc_num, NPCM7xxEMCState),
1138
+ VMSTATE_UINT32_ARRAY(regs, NPCM7xxEMCState, NPCM7XX_NUM_EMC_REGS),
1139
+ VMSTATE_BOOL(tx_active, NPCM7xxEMCState),
1140
+ VMSTATE_BOOL(rx_active, NPCM7xxEMCState),
1141
+ VMSTATE_END_OF_LIST(),
1142
+ },
1143
+};
1144
+
1145
+static Property npcm7xx_emc_properties[] = {
1146
+ DEFINE_NIC_PROPERTIES(NPCM7xxEMCState, conf),
1147
+ DEFINE_PROP_END_OF_LIST(),
1148
+};
1149
+
1150
+static void npcm7xx_emc_class_init(ObjectClass *klass, void *data)
1151
+{
1152
+ DeviceClass *dc = DEVICE_CLASS(klass);
1153
+
1154
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
1155
+ dc->desc = "NPCM7xx EMC Controller";
1156
+ dc->realize = npcm7xx_emc_realize;
1157
+ dc->unrealize = npcm7xx_emc_unrealize;
1158
+ dc->reset = npcm7xx_emc_reset;
1159
+ dc->vmsd = &vmstate_npcm7xx_emc;
1160
+ device_class_set_props(dc, npcm7xx_emc_properties);
1161
+}
1162
+
1163
+static const TypeInfo npcm7xx_emc_info = {
1164
+ .name = TYPE_NPCM7XX_EMC,
1165
+ .parent = TYPE_SYS_BUS_DEVICE,
1166
+ .instance_size = sizeof(NPCM7xxEMCState),
1167
+ .class_init = npcm7xx_emc_class_init,
1168
+};
1169
+
1170
+static void npcm7xx_emc_register_type(void)
1171
+{
1172
+ type_register_static(&npcm7xx_emc_info);
1173
+}
1174
+
1175
+type_init(npcm7xx_emc_register_type)
1176
diff --git a/hw/net/meson.build b/hw/net/meson.build
1177
index XXXXXXX..XXXXXXX 100644
650
index XXXXXXX..XXXXXXX 100644
1178
--- a/hw/net/meson.build
651
--- a/target/arm/translate-vfp.c
1179
+++ b/hw/net/meson.build
652
+++ b/target/arm/translate-vfp.c
1180
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_I82596_COMMON', if_true: files('i82596.c'))
653
@@ -XXX,XX +XXX,XX @@ static inline long vfp_f16_offset(unsigned reg, bool top)
1181
softmmu_ss.add(when: 'CONFIG_SUNHME', if_true: files('sunhme.c'))
654
* Generate code for M-profile lazy FP state preservation if needed;
1182
softmmu_ss.add(when: 'CONFIG_FTGMAC100', if_true: files('ftgmac100.c'))
655
* this corresponds to the pseudocode PreserveFPState() function.
1183
softmmu_ss.add(when: 'CONFIG_SUNGEM', if_true: files('sungem.c'))
656
*/
1184
+softmmu_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_emc.c'))
657
-static void gen_preserve_fp_state(DisasContext *s)
1185
658
+void gen_preserve_fp_state(DisasContext *s)
1186
softmmu_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_eth.c'))
659
{
1187
softmmu_ss.add(when: 'CONFIG_COLDFIRE', if_true: files('mcf_fec.c'))
660
if (s->v7m_lspact) {
1188
diff --git a/hw/net/trace-events b/hw/net/trace-events
661
/*
1189
index XXXXXXX..XXXXXXX 100644
662
@@ -XXX,XX +XXX,XX @@ static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
1190
--- a/hw/net/trace-events
663
return true;
1191
+++ b/hw/net/trace-events
664
}
1192
@@ -XXX,XX +XXX,XX @@ imx_fec_receive_last(int last) "rx frame flags 0x%04x"
665
1193
imx_enet_receive(size_t size) "len %zu"
666
-/*
1194
imx_enet_receive_len(uint64_t addr, int len) "rx_bd 0x%"PRIx64" length %d"
667
- * M-profile provides two different sets of instructions that can
1195
imx_enet_receive_last(int last) "rx frame flags 0x%04x"
668
- * access floating point system registers: VMSR/VMRS (which move
1196
+
669
- * to/from a general purpose register) and VLDR/VSTR sysreg (which
1197
+# npcm7xx_emc.c
670
- * move directly to/from memory). In some cases there are also side
1198
+npcm7xx_emc_reset(int emc_num) "Resetting emc%d"
671
- * effects which must happen after any write to memory (which could
1199
+npcm7xx_emc_update_tx_irq(int level) "Setting tx irq to %d"
672
- * cause an exception). So we implement the common logic for the
1200
+npcm7xx_emc_update_rx_irq(int level) "Setting rx irq to %d"
673
- * sysreg access in gen_M_fp_sysreg_write() and gen_M_fp_sysreg_read(),
1201
+npcm7xx_emc_set_mista(uint32_t flags) "ORing 0x%x into MISTA"
674
- * which take pointers to callback functions which will perform the
1202
+npcm7xx_emc_cpu_owned_desc(uint32_t addr) "Can't process cpu-owned descriptor @0x%x"
675
- * actual "read/write general purpose register" and "read/write
1203
+npcm7xx_emc_sent_packet(uint32_t len) "Sent %u byte packet"
676
- * memory" operations.
1204
+npcm7xx_emc_tx_done(uint32_t ctxdsa) "TX done, CTXDSA=0x%x"
677
- */
1205
+npcm7xx_emc_can_receive(int can_receive) "Can receive: %d"
678
-
1206
+npcm7xx_emc_packet_filtered_out(const char* fail_reason) "Packet filtered out: %s"
679
-/*
1207
+npcm7xx_emc_packet_dropped(uint32_t len) "%u byte packet dropped"
680
- * Emit code to store the sysreg to its final destination; frees the
1208
+npcm7xx_emc_receiving_packet(uint32_t len) "Receiving %u byte packet"
681
- * TCG temp 'value' it is passed.
1209
+npcm7xx_emc_received_packet(uint32_t len) "Received %u byte packet"
682
- */
1210
+npcm7xx_emc_rx_done(uint32_t crxdsa) "RX done, CRXDSA=0x%x"
683
-typedef void fp_sysreg_storefn(DisasContext *s, void *opaque, TCGv_i32 value);
1211
+npcm7xx_emc_reg_read(int emc_num, uint32_t result, const char *name, int regno) "emc%d: 0x%x = reg[%s/%d]"
684
-/*
1212
+npcm7xx_emc_reg_write(int emc_num, const char *name, int regno, uint32_t value) "emc%d: reg[%s/%d] = 0x%x"
685
- * Emit code to load the value to be copied to the sysreg; returns
686
- * a new TCG temporary
687
- */
688
-typedef TCGv_i32 fp_sysreg_loadfn(DisasContext *s, void *opaque);
689
-
690
-/* Common decode/access checks for fp sysreg read/write */
691
-typedef enum FPSysRegCheckResult {
692
- FPSysRegCheckFailed, /* caller should return false */
693
- FPSysRegCheckDone, /* caller should return true */
694
- FPSysRegCheckContinue, /* caller should continue generating code */
695
-} FPSysRegCheckResult;
696
-
697
-static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
698
-{
699
- if (!dc_isar_feature(aa32_fpsp_v2, s) && !dc_isar_feature(aa32_mve, s)) {
700
- return FPSysRegCheckFailed;
701
- }
702
-
703
- switch (regno) {
704
- case ARM_VFP_FPSCR:
705
- case QEMU_VFP_FPSCR_NZCV:
706
- break;
707
- case ARM_VFP_FPSCR_NZCVQC:
708
- if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
709
- return FPSysRegCheckFailed;
710
- }
711
- break;
712
- case ARM_VFP_FPCXT_S:
713
- case ARM_VFP_FPCXT_NS:
714
- if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
715
- return FPSysRegCheckFailed;
716
- }
717
- if (!s->v8m_secure) {
718
- return FPSysRegCheckFailed;
719
- }
720
- break;
721
- case ARM_VFP_VPR:
722
- case ARM_VFP_P0:
723
- if (!dc_isar_feature(aa32_mve, s)) {
724
- return FPSysRegCheckFailed;
725
- }
726
- break;
727
- default:
728
- return FPSysRegCheckFailed;
729
- }
730
-
731
- /*
732
- * FPCXT_NS is a special case: it has specific handling for
733
- * "current FP state is inactive", and must do the PreserveFPState()
734
- * but not the usual full set of actions done by ExecuteFPCheck().
735
- * So we don't call vfp_access_check() and the callers must handle this.
736
- */
737
- if (regno != ARM_VFP_FPCXT_NS && !vfp_access_check(s)) {
738
- return FPSysRegCheckDone;
739
- }
740
- return FPSysRegCheckContinue;
741
-}
742
-
743
-static void gen_branch_fpInactive(DisasContext *s, TCGCond cond,
744
- TCGLabel *label)
745
-{
746
- /*
747
- * FPCXT_NS is a special case: it has specific handling for
748
- * "current FP state is inactive", and must do the PreserveFPState()
749
- * but not the usual full set of actions done by ExecuteFPCheck().
750
- * We don't have a TB flag that matches the fpInactive check, so we
751
- * do it at runtime as we don't expect FPCXT_NS accesses to be frequent.
752
- *
753
- * Emit code that checks fpInactive and does a conditional
754
- * branch to label based on it:
755
- * if cond is TCG_COND_NE then branch if fpInactive != 0 (ie if inactive)
756
- * if cond is TCG_COND_EQ then branch if fpInactive == 0 (ie if active)
757
- */
758
- assert(cond == TCG_COND_EQ || cond == TCG_COND_NE);
759
-
760
- /* fpInactive = FPCCR_NS.ASPEN == 1 && CONTROL.FPCA == 0 */
761
- TCGv_i32 aspen, fpca;
762
- aspen = load_cpu_field(v7m.fpccr[M_REG_NS]);
763
- fpca = load_cpu_field(v7m.control[M_REG_S]);
764
- tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
765
- tcg_gen_xori_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
766
- tcg_gen_andi_i32(fpca, fpca, R_V7M_CONTROL_FPCA_MASK);
767
- tcg_gen_or_i32(fpca, fpca, aspen);
768
- tcg_gen_brcondi_i32(tcg_invert_cond(cond), fpca, 0, label);
769
- tcg_temp_free_i32(aspen);
770
- tcg_temp_free_i32(fpca);
771
-}
772
-
773
-static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
774
- fp_sysreg_loadfn *loadfn,
775
- void *opaque)
776
-{
777
- /* Do a write to an M-profile floating point system register */
778
- TCGv_i32 tmp;
779
- TCGLabel *lab_end = NULL;
780
-
781
- switch (fp_sysreg_checks(s, regno)) {
782
- case FPSysRegCheckFailed:
783
- return false;
784
- case FPSysRegCheckDone:
785
- return true;
786
- case FPSysRegCheckContinue:
787
- break;
788
- }
789
-
790
- switch (regno) {
791
- case ARM_VFP_FPSCR:
792
- tmp = loadfn(s, opaque);
793
- gen_helper_vfp_set_fpscr(cpu_env, tmp);
794
- tcg_temp_free_i32(tmp);
795
- gen_lookup_tb(s);
796
- break;
797
- case ARM_VFP_FPSCR_NZCVQC:
798
- {
799
- TCGv_i32 fpscr;
800
- tmp = loadfn(s, opaque);
801
- if (dc_isar_feature(aa32_mve, s)) {
802
- /* QC is only present for MVE; otherwise RES0 */
803
- TCGv_i32 qc = tcg_temp_new_i32();
804
- tcg_gen_andi_i32(qc, tmp, FPCR_QC);
805
- /*
806
- * The 4 vfp.qc[] fields need only be "zero" vs "non-zero";
807
- * here writing the same value into all elements is simplest.
808
- */
809
- tcg_gen_gvec_dup_i32(MO_32, offsetof(CPUARMState, vfp.qc),
810
- 16, 16, qc);
811
- }
812
- tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
813
- fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
814
- tcg_gen_andi_i32(fpscr, fpscr, ~FPCR_NZCV_MASK);
815
- tcg_gen_or_i32(fpscr, fpscr, tmp);
816
- store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
817
- tcg_temp_free_i32(tmp);
818
- break;
819
- }
820
- case ARM_VFP_FPCXT_NS:
821
- lab_end = gen_new_label();
822
- /* fpInactive case: write is a NOP, so branch to end */
823
- gen_branch_fpInactive(s, TCG_COND_NE, lab_end);
824
- /*
825
- * !fpInactive: if FPU disabled, take NOCP exception;
826
- * otherwise PreserveFPState(), and then FPCXT_NS writes
827
- * behave the same as FPCXT_S writes.
828
- */
829
- if (s->fp_excp_el) {
830
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
831
- syn_uncategorized(), s->fp_excp_el);
832
- /*
833
- * This was only a conditional exception, so override
834
- * gen_exception_insn()'s default to DISAS_NORETURN
835
- */
836
- s->base.is_jmp = DISAS_NEXT;
837
- break;
838
- }
839
- gen_preserve_fp_state(s);
840
- /* fall through */
841
- case ARM_VFP_FPCXT_S:
842
- {
843
- TCGv_i32 sfpa, control;
844
- /*
845
- * Set FPSCR and CONTROL.SFPA from value; the new FPSCR takes
846
- * bits [27:0] from value and zeroes bits [31:28].
847
- */
848
- tmp = loadfn(s, opaque);
849
- sfpa = tcg_temp_new_i32();
850
- tcg_gen_shri_i32(sfpa, tmp, 31);
851
- control = load_cpu_field(v7m.control[M_REG_S]);
852
- tcg_gen_deposit_i32(control, control, sfpa,
853
- R_V7M_CONTROL_SFPA_SHIFT, 1);
854
- store_cpu_field(control, v7m.control[M_REG_S]);
855
- tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
856
- gen_helper_vfp_set_fpscr(cpu_env, tmp);
857
- tcg_temp_free_i32(tmp);
858
- tcg_temp_free_i32(sfpa);
859
- break;
860
- }
861
- case ARM_VFP_VPR:
862
- /* Behaves as NOP if not privileged */
863
- if (IS_USER(s)) {
864
- break;
865
- }
866
- tmp = loadfn(s, opaque);
867
- store_cpu_field(tmp, v7m.vpr);
868
- break;
869
- case ARM_VFP_P0:
870
- {
871
- TCGv_i32 vpr;
872
- tmp = loadfn(s, opaque);
873
- vpr = load_cpu_field(v7m.vpr);
874
- tcg_gen_deposit_i32(vpr, vpr, tmp,
875
- R_V7M_VPR_P0_SHIFT, R_V7M_VPR_P0_LENGTH);
876
- store_cpu_field(vpr, v7m.vpr);
877
- tcg_temp_free_i32(tmp);
878
- break;
879
- }
880
- default:
881
- g_assert_not_reached();
882
- }
883
- if (lab_end) {
884
- gen_set_label(lab_end);
885
- }
886
- return true;
887
-}
888
-
889
-static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
890
- fp_sysreg_storefn *storefn,
891
- void *opaque)
892
-{
893
- /* Do a read from an M-profile floating point system register */
894
- TCGv_i32 tmp;
895
- TCGLabel *lab_end = NULL;
896
- bool lookup_tb = false;
897
-
898
- switch (fp_sysreg_checks(s, regno)) {
899
- case FPSysRegCheckFailed:
900
- return false;
901
- case FPSysRegCheckDone:
902
- return true;
903
- case FPSysRegCheckContinue:
904
- break;
905
- }
906
-
907
- if (regno == ARM_VFP_FPSCR_NZCVQC && !dc_isar_feature(aa32_mve, s)) {
908
- /* QC is RES0 without MVE, so NZCVQC simplifies to NZCV */
909
- regno = QEMU_VFP_FPSCR_NZCV;
910
- }
911
-
912
- switch (regno) {
913
- case ARM_VFP_FPSCR:
914
- tmp = tcg_temp_new_i32();
915
- gen_helper_vfp_get_fpscr(tmp, cpu_env);
916
- storefn(s, opaque, tmp);
917
- break;
918
- case ARM_VFP_FPSCR_NZCVQC:
919
- tmp = tcg_temp_new_i32();
920
- gen_helper_vfp_get_fpscr(tmp, cpu_env);
921
- tcg_gen_andi_i32(tmp, tmp, FPCR_NZCVQC_MASK);
922
- storefn(s, opaque, tmp);
923
- break;
924
- case QEMU_VFP_FPSCR_NZCV:
925
- /*
926
- * Read just NZCV; this is a special case to avoid the
927
- * helper call for the "VMRS to CPSR.NZCV" insn.
928
- */
929
- tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
930
- tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
931
- storefn(s, opaque, tmp);
932
- break;
933
- case ARM_VFP_FPCXT_S:
934
- {
935
- TCGv_i32 control, sfpa, fpscr;
936
- /* Bits [27:0] from FPSCR, bit [31] from CONTROL.SFPA */
937
- tmp = tcg_temp_new_i32();
938
- sfpa = tcg_temp_new_i32();
939
- gen_helper_vfp_get_fpscr(tmp, cpu_env);
940
- tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
941
- control = load_cpu_field(v7m.control[M_REG_S]);
942
- tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
943
- tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
944
- tcg_gen_or_i32(tmp, tmp, sfpa);
945
- tcg_temp_free_i32(sfpa);
946
- /*
947
- * Store result before updating FPSCR etc, in case
948
- * it is a memory write which causes an exception.
949
- */
950
- storefn(s, opaque, tmp);
951
- /*
952
- * Now we must reset FPSCR from FPDSCR_NS, and clear
953
- * CONTROL.SFPA; so we'll end the TB here.
954
- */
955
- tcg_gen_andi_i32(control, control, ~R_V7M_CONTROL_SFPA_MASK);
956
- store_cpu_field(control, v7m.control[M_REG_S]);
957
- fpscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
958
- gen_helper_vfp_set_fpscr(cpu_env, fpscr);
959
- tcg_temp_free_i32(fpscr);
960
- lookup_tb = true;
961
- break;
962
- }
963
- case ARM_VFP_FPCXT_NS:
964
- {
965
- TCGv_i32 control, sfpa, fpscr, fpdscr, zero;
966
- TCGLabel *lab_active = gen_new_label();
967
-
968
- lookup_tb = true;
969
-
970
- gen_branch_fpInactive(s, TCG_COND_EQ, lab_active);
971
- /* fpInactive case: reads as FPDSCR_NS */
972
- TCGv_i32 tmp = load_cpu_field(v7m.fpdscr[M_REG_NS]);
973
- storefn(s, opaque, tmp);
974
- lab_end = gen_new_label();
975
- tcg_gen_br(lab_end);
976
-
977
- gen_set_label(lab_active);
978
- /*
979
- * !fpInactive: if FPU disabled, take NOCP exception;
980
- * otherwise PreserveFPState(), and then FPCXT_NS
981
- * reads the same as FPCXT_S.
982
- */
983
- if (s->fp_excp_el) {
984
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
985
- syn_uncategorized(), s->fp_excp_el);
986
- /*
987
- * This was only a conditional exception, so override
988
- * gen_exception_insn()'s default to DISAS_NORETURN
989
- */
990
- s->base.is_jmp = DISAS_NEXT;
991
- break;
992
- }
993
- gen_preserve_fp_state(s);
994
- tmp = tcg_temp_new_i32();
995
- sfpa = tcg_temp_new_i32();
996
- fpscr = tcg_temp_new_i32();
997
- gen_helper_vfp_get_fpscr(fpscr, cpu_env);
998
- tcg_gen_andi_i32(tmp, fpscr, ~FPCR_NZCV_MASK);
999
- control = load_cpu_field(v7m.control[M_REG_S]);
1000
- tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
1001
- tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
1002
- tcg_gen_or_i32(tmp, tmp, sfpa);
1003
- tcg_temp_free_i32(control);
1004
- /* Store result before updating FPSCR, in case it faults */
1005
- storefn(s, opaque, tmp);
1006
- /* If SFPA is zero then set FPSCR from FPDSCR_NS */
1007
- fpdscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
1008
- zero = tcg_const_i32(0);
1009
- tcg_gen_movcond_i32(TCG_COND_EQ, fpscr, sfpa, zero, fpdscr, fpscr);
1010
- gen_helper_vfp_set_fpscr(cpu_env, fpscr);
1011
- tcg_temp_free_i32(zero);
1012
- tcg_temp_free_i32(sfpa);
1013
- tcg_temp_free_i32(fpdscr);
1014
- tcg_temp_free_i32(fpscr);
1015
- break;
1016
- }
1017
- case ARM_VFP_VPR:
1018
- /* Behaves as NOP if not privileged */
1019
- if (IS_USER(s)) {
1020
- break;
1021
- }
1022
- tmp = load_cpu_field(v7m.vpr);
1023
- storefn(s, opaque, tmp);
1024
- break;
1025
- case ARM_VFP_P0:
1026
- tmp = load_cpu_field(v7m.vpr);
1027
- tcg_gen_extract_i32(tmp, tmp, R_V7M_VPR_P0_SHIFT, R_V7M_VPR_P0_LENGTH);
1028
- storefn(s, opaque, tmp);
1029
- break;
1030
- default:
1031
- g_assert_not_reached();
1032
- }
1033
-
1034
- if (lab_end) {
1035
- gen_set_label(lab_end);
1036
- }
1037
- if (lookup_tb) {
1038
- gen_lookup_tb(s);
1039
- }
1040
- return true;
1041
-}
1042
-
1043
-static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value)
1044
-{
1045
- arg_VMSR_VMRS *a = opaque;
1046
-
1047
- if (a->rt == 15) {
1048
- /* Set the 4 flag bits in the CPSR */
1049
- gen_set_nzcv(value);
1050
- tcg_temp_free_i32(value);
1051
- } else {
1052
- store_reg(s, a->rt, value);
1053
- }
1054
-}
1055
-
1056
-static TCGv_i32 gpr_to_fp_sysreg(DisasContext *s, void *opaque)
1057
-{
1058
- arg_VMSR_VMRS *a = opaque;
1059
-
1060
- return load_reg(s, a->rt);
1061
-}
1062
-
1063
-static bool gen_M_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
1064
-{
1065
- /*
1066
- * Accesses to R15 are UNPREDICTABLE; we choose to undef.
1067
- * FPSCR -> r15 is a special case which writes to the PSR flags;
1068
- * set a->reg to a special value to tell gen_M_fp_sysreg_read()
1069
- * we only care about the top 4 bits of FPSCR there.
1070
- */
1071
- if (a->rt == 15) {
1072
- if (a->l && a->reg == ARM_VFP_FPSCR) {
1073
- a->reg = QEMU_VFP_FPSCR_NZCV;
1074
- } else {
1075
- return false;
1076
- }
1077
- }
1078
-
1079
- if (a->l) {
1080
- /* VMRS, move FP system register to gp register */
1081
- return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_gpr, a);
1082
- } else {
1083
- /* VMSR, move gp register to FP system register */
1084
- return gen_M_fp_sysreg_write(s, a->reg, gpr_to_fp_sysreg, a);
1085
- }
1086
-}
1087
-
1088
static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
1089
{
1090
TCGv_i32 tmp;
1091
bool ignore_vfp_enabled = false;
1092
1093
if (arm_dc_feature(s, ARM_FEATURE_M)) {
1094
- return gen_M_VMSR_VMRS(s, a);
1095
+ /* M profile version was already handled in m-nocp.decode */
1096
+ return false;
1097
}
1098
1099
if (!dc_isar_feature(aa32_fpsp_v2, s)) {
1100
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
1101
return true;
1102
}
1103
1104
-static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
1105
-{
1106
- arg_vldr_sysreg *a = opaque;
1107
- uint32_t offset = a->imm;
1108
- TCGv_i32 addr;
1109
-
1110
- if (!a->a) {
1111
- offset = -offset;
1112
- }
1113
-
1114
- addr = load_reg(s, a->rn);
1115
- if (a->p) {
1116
- tcg_gen_addi_i32(addr, addr, offset);
1117
- }
1118
-
1119
- if (s->v8m_stackcheck && a->rn == 13 && a->w) {
1120
- gen_helper_v8m_stackcheck(cpu_env, addr);
1121
- }
1122
-
1123
- gen_aa32_st_i32(s, value, addr, get_mem_index(s),
1124
- MO_UL | MO_ALIGN | s->be_data);
1125
- tcg_temp_free_i32(value);
1126
-
1127
- if (a->w) {
1128
- /* writeback */
1129
- if (!a->p) {
1130
- tcg_gen_addi_i32(addr, addr, offset);
1131
- }
1132
- store_reg(s, a->rn, addr);
1133
- } else {
1134
- tcg_temp_free_i32(addr);
1135
- }
1136
-}
1137
-
1138
-static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
1139
-{
1140
- arg_vldr_sysreg *a = opaque;
1141
- uint32_t offset = a->imm;
1142
- TCGv_i32 addr;
1143
- TCGv_i32 value = tcg_temp_new_i32();
1144
-
1145
- if (!a->a) {
1146
- offset = -offset;
1147
- }
1148
-
1149
- addr = load_reg(s, a->rn);
1150
- if (a->p) {
1151
- tcg_gen_addi_i32(addr, addr, offset);
1152
- }
1153
-
1154
- if (s->v8m_stackcheck && a->rn == 13 && a->w) {
1155
- gen_helper_v8m_stackcheck(cpu_env, addr);
1156
- }
1157
-
1158
- gen_aa32_ld_i32(s, value, addr, get_mem_index(s),
1159
- MO_UL | MO_ALIGN | s->be_data);
1160
-
1161
- if (a->w) {
1162
- /* writeback */
1163
- if (!a->p) {
1164
- tcg_gen_addi_i32(addr, addr, offset);
1165
- }
1166
- store_reg(s, a->rn, addr);
1167
- } else {
1168
- tcg_temp_free_i32(addr);
1169
- }
1170
- return value;
1171
-}
1172
-
1173
-static bool trans_VLDR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
1174
-{
1175
- if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
1176
- return false;
1177
- }
1178
- if (a->rn == 15) {
1179
- return false;
1180
- }
1181
- return gen_M_fp_sysreg_write(s, a->reg, memory_to_fp_sysreg, a);
1182
-}
1183
-
1184
-static bool trans_VSTR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
1185
-{
1186
- if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
1187
- return false;
1188
- }
1189
- if (a->rn == 15) {
1190
- return false;
1191
- }
1192
- return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_memory, a);
1193
-}
1194
1195
static bool trans_VMOV_half(DisasContext *s, arg_VMOV_single *a)
1196
{
1213
--
1197
--
1214
2.20.1
1198
2.20.1
1215
1199
1216
1200
diff view generated by jsdifflib
New patch
1
1
A few subcases of VLDR/VSTR sysreg succeed but do not perform a
2
memory access:
3
* VSTR of VPR when unprivileged
4
* VLDR to VPR when unprivileged
5
* VLDR to FPCXT_NS when fpInactive
6
7
In these cases, even though we don't do the memory access we should
8
still update the base register and perform the stack limit check if
9
the insn's addressing mode specifies writeback. Our implementation
10
failed to do this, because we handle these side-effects inside the
11
memory_to_fp_sysreg() and fp_sysreg_to_memory() callback functions,
12
which are only called if there's something to load or store.
13
14
Fix this by adding an extra argument to the callbacks which is set to
15
true to actually perform the access and false to only do side effects
16
like writeback, and calling the callback with do_access = false
17
for the three cases listed above.
18
19
This produces slightly suboptimal code for the case of a write
20
to FPCXT_NS when the FPU is inactive and the insn didn't have
21
side effects (ie no writeback, or via VMSR), in which case we'll
22
generate a conditional branch over an unconditional branch.
23
But this doesn't seem to be important enough to merit requiring
24
the callback to report back whether it generated any code or not.
25
26
Cc: qemu-stable@nongnu.org
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
29
Message-id: 20210618141019.10671-5-peter.maydell@linaro.org
30
---
31
target/arm/translate-m-nocp.c | 102 ++++++++++++++++++++++++----------
32
1 file changed, 72 insertions(+), 30 deletions(-)
33
34
diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/translate-m-nocp.c
37
+++ b/target/arm/translate-m-nocp.c
38
@@ -XXX,XX +XXX,XX @@ static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
39
40
/*
41
* Emit code to store the sysreg to its final destination; frees the
42
- * TCG temp 'value' it is passed.
43
+ * TCG temp 'value' it is passed. do_access is true to do the store,
44
+ * and false to skip it and only perform side-effects like base
45
+ * register writeback.
46
*/
47
-typedef void fp_sysreg_storefn(DisasContext *s, void *opaque, TCGv_i32 value);
48
+typedef void fp_sysreg_storefn(DisasContext *s, void *opaque, TCGv_i32 value,
49
+ bool do_access);
50
/*
51
* Emit code to load the value to be copied to the sysreg; returns
52
- * a new TCG temporary
53
+ * a new TCG temporary. do_access is true to do the store,
54
+ * and false to skip it and only perform side-effects like base
55
+ * register writeback.
56
*/
57
-typedef TCGv_i32 fp_sysreg_loadfn(DisasContext *s, void *opaque);
58
+typedef TCGv_i32 fp_sysreg_loadfn(DisasContext *s, void *opaque,
59
+ bool do_access);
60
61
/* Common decode/access checks for fp sysreg read/write */
62
typedef enum FPSysRegCheckResult {
63
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
64
65
switch (regno) {
66
case ARM_VFP_FPSCR:
67
- tmp = loadfn(s, opaque);
68
+ tmp = loadfn(s, opaque, true);
69
gen_helper_vfp_set_fpscr(cpu_env, tmp);
70
tcg_temp_free_i32(tmp);
71
gen_lookup_tb(s);
72
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
73
case ARM_VFP_FPSCR_NZCVQC:
74
{
75
TCGv_i32 fpscr;
76
- tmp = loadfn(s, opaque);
77
+ tmp = loadfn(s, opaque, true);
78
if (dc_isar_feature(aa32_mve, s)) {
79
/* QC is only present for MVE; otherwise RES0 */
80
TCGv_i32 qc = tcg_temp_new_i32();
81
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
82
break;
83
}
84
case ARM_VFP_FPCXT_NS:
85
+ {
86
+ TCGLabel *lab_active = gen_new_label();
87
+
88
lab_end = gen_new_label();
89
- /* fpInactive case: write is a NOP, so branch to end */
90
- gen_branch_fpInactive(s, TCG_COND_NE, lab_end);
91
+ gen_branch_fpInactive(s, TCG_COND_EQ, lab_active);
92
+ /*
93
+ * fpInactive case: write is a NOP, so only do side effects
94
+ * like register writeback before we branch to end
95
+ */
96
+ loadfn(s, opaque, false);
97
+ tcg_gen_br(lab_end);
98
+
99
+ gen_set_label(lab_active);
100
/*
101
* !fpInactive: if FPU disabled, take NOCP exception;
102
* otherwise PreserveFPState(), and then FPCXT_NS writes
103
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
104
break;
105
}
106
gen_preserve_fp_state(s);
107
- /* fall through */
108
+ }
109
+ /* fall through */
110
case ARM_VFP_FPCXT_S:
111
{
112
TCGv_i32 sfpa, control;
113
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
114
* Set FPSCR and CONTROL.SFPA from value; the new FPSCR takes
115
* bits [27:0] from value and zeroes bits [31:28].
116
*/
117
- tmp = loadfn(s, opaque);
118
+ tmp = loadfn(s, opaque, true);
119
sfpa = tcg_temp_new_i32();
120
tcg_gen_shri_i32(sfpa, tmp, 31);
121
control = load_cpu_field(v7m.control[M_REG_S]);
122
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
123
case ARM_VFP_VPR:
124
/* Behaves as NOP if not privileged */
125
if (IS_USER(s)) {
126
+ loadfn(s, opaque, false);
127
break;
128
}
129
- tmp = loadfn(s, opaque);
130
+ tmp = loadfn(s, opaque, true);
131
store_cpu_field(tmp, v7m.vpr);
132
break;
133
case ARM_VFP_P0:
134
{
135
TCGv_i32 vpr;
136
- tmp = loadfn(s, opaque);
137
+ tmp = loadfn(s, opaque, true);
138
vpr = load_cpu_field(v7m.vpr);
139
tcg_gen_deposit_i32(vpr, vpr, tmp,
140
R_V7M_VPR_P0_SHIFT, R_V7M_VPR_P0_LENGTH);
141
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
142
case ARM_VFP_FPSCR:
143
tmp = tcg_temp_new_i32();
144
gen_helper_vfp_get_fpscr(tmp, cpu_env);
145
- storefn(s, opaque, tmp);
146
+ storefn(s, opaque, tmp, true);
147
break;
148
case ARM_VFP_FPSCR_NZCVQC:
149
tmp = tcg_temp_new_i32();
150
gen_helper_vfp_get_fpscr(tmp, cpu_env);
151
tcg_gen_andi_i32(tmp, tmp, FPCR_NZCVQC_MASK);
152
- storefn(s, opaque, tmp);
153
+ storefn(s, opaque, tmp, true);
154
break;
155
case QEMU_VFP_FPSCR_NZCV:
156
/*
157
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
158
*/
159
tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
160
tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
161
- storefn(s, opaque, tmp);
162
+ storefn(s, opaque, tmp, true);
163
break;
164
case ARM_VFP_FPCXT_S:
165
{
166
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
167
* Store result before updating FPSCR etc, in case
168
* it is a memory write which causes an exception.
169
*/
170
- storefn(s, opaque, tmp);
171
+ storefn(s, opaque, tmp, true);
172
/*
173
* Now we must reset FPSCR from FPDSCR_NS, and clear
174
* CONTROL.SFPA; so we'll end the TB here.
175
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
176
gen_branch_fpInactive(s, TCG_COND_EQ, lab_active);
177
/* fpInactive case: reads as FPDSCR_NS */
178
TCGv_i32 tmp = load_cpu_field(v7m.fpdscr[M_REG_NS]);
179
- storefn(s, opaque, tmp);
180
+ storefn(s, opaque, tmp, true);
181
lab_end = gen_new_label();
182
tcg_gen_br(lab_end);
183
184
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
185
tcg_gen_or_i32(tmp, tmp, sfpa);
186
tcg_temp_free_i32(control);
187
/* Store result before updating FPSCR, in case it faults */
188
- storefn(s, opaque, tmp);
189
+ storefn(s, opaque, tmp, true);
190
/* If SFPA is zero then set FPSCR from FPDSCR_NS */
191
fpdscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
192
zero = tcg_const_i32(0);
193
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
194
case ARM_VFP_VPR:
195
/* Behaves as NOP if not privileged */
196
if (IS_USER(s)) {
197
+ storefn(s, opaque, NULL, false);
198
break;
199
}
200
tmp = load_cpu_field(v7m.vpr);
201
- storefn(s, opaque, tmp);
202
+ storefn(s, opaque, tmp, true);
203
break;
204
case ARM_VFP_P0:
205
tmp = load_cpu_field(v7m.vpr);
206
tcg_gen_extract_i32(tmp, tmp, R_V7M_VPR_P0_SHIFT, R_V7M_VPR_P0_LENGTH);
207
- storefn(s, opaque, tmp);
208
+ storefn(s, opaque, tmp, true);
209
break;
210
default:
211
g_assert_not_reached();
212
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
213
return true;
214
}
215
216
-static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value)
217
+static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value,
218
+ bool do_access)
219
{
220
arg_VMSR_VMRS *a = opaque;
221
222
+ if (!do_access) {
223
+ return;
224
+ }
225
+
226
if (a->rt == 15) {
227
/* Set the 4 flag bits in the CPSR */
228
gen_set_nzcv(value);
229
@@ -XXX,XX +XXX,XX @@ static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value)
230
}
231
}
232
233
-static TCGv_i32 gpr_to_fp_sysreg(DisasContext *s, void *opaque)
234
+static TCGv_i32 gpr_to_fp_sysreg(DisasContext *s, void *opaque, bool do_access)
235
{
236
arg_VMSR_VMRS *a = opaque;
237
238
+ if (!do_access) {
239
+ return NULL;
240
+ }
241
return load_reg(s, a->rt);
242
}
243
244
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
245
}
246
}
247
248
-static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
249
+static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value,
250
+ bool do_access)
251
{
252
arg_vldr_sysreg *a = opaque;
253
uint32_t offset = a->imm;
254
@@ -XXX,XX +XXX,XX @@ static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
255
offset = -offset;
256
}
257
258
+ if (!do_access && !a->w) {
259
+ return;
260
+ }
261
+
262
addr = load_reg(s, a->rn);
263
if (a->p) {
264
tcg_gen_addi_i32(addr, addr, offset);
265
@@ -XXX,XX +XXX,XX @@ static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
266
gen_helper_v8m_stackcheck(cpu_env, addr);
267
}
268
269
- gen_aa32_st_i32(s, value, addr, get_mem_index(s),
270
- MO_UL | MO_ALIGN | s->be_data);
271
- tcg_temp_free_i32(value);
272
+ if (do_access) {
273
+ gen_aa32_st_i32(s, value, addr, get_mem_index(s),
274
+ MO_UL | MO_ALIGN | s->be_data);
275
+ tcg_temp_free_i32(value);
276
+ }
277
278
if (a->w) {
279
/* writeback */
280
@@ -XXX,XX +XXX,XX @@ static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
281
}
282
}
283
284
-static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
285
+static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque,
286
+ bool do_access)
287
{
288
arg_vldr_sysreg *a = opaque;
289
uint32_t offset = a->imm;
290
TCGv_i32 addr;
291
- TCGv_i32 value = tcg_temp_new_i32();
292
+ TCGv_i32 value = NULL;
293
294
if (!a->a) {
295
offset = -offset;
296
}
297
298
+ if (!do_access && !a->w) {
299
+ return NULL;
300
+ }
301
+
302
addr = load_reg(s, a->rn);
303
if (a->p) {
304
tcg_gen_addi_i32(addr, addr, offset);
305
@@ -XXX,XX +XXX,XX @@ static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
306
gen_helper_v8m_stackcheck(cpu_env, addr);
307
}
308
309
- gen_aa32_ld_i32(s, value, addr, get_mem_index(s),
310
- MO_UL | MO_ALIGN | s->be_data);
311
+ if (do_access) {
312
+ value = tcg_temp_new_i32();
313
+ gen_aa32_ld_i32(s, value, addr, get_mem_index(s),
314
+ MO_UL | MO_ALIGN | s->be_data);
315
+ }
316
317
if (a->w) {
318
/* writeback */
319
--
320
2.20.1
321
322
diff view generated by jsdifflib
1
The armv7m_load_kernel() function takes a mem_size argument which it
1
Factor the code in full_vfp_access_check() which updates the
2
expects to be the size of the memory region at guest address 0. (It
2
ownership of the FP context and creates a new FP context
3
uses this argument only as a limit on how large a raw image file it
3
out into its own function.
4
can load at address zero).
5
6
Instead of hardcoding this value, find the RAMInfo corresponding to
7
the 0 address and extract its size.
8
4
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210215115138.20465-20-peter.maydell@linaro.org
7
Message-id: 20210618141019.10671-6-peter.maydell@linaro.org
13
---
8
---
14
hw/arm/mps2-tz.c | 17 ++++++++++++++++-
9
target/arm/translate-vfp.c | 104 +++++++++++++++++++++----------------
15
1 file changed, 16 insertions(+), 1 deletion(-)
10
1 file changed, 58 insertions(+), 46 deletions(-)
16
11
17
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
12
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
18
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/mps2-tz.c
14
--- a/target/arm/translate-vfp.c
20
+++ b/hw/arm/mps2-tz.c
15
+++ b/target/arm/translate-vfp.c
21
@@ -XXX,XX +XXX,XX @@ static void create_non_mpc_ram(MPS2TZMachineState *mms)
16
@@ -XXX,XX +XXX,XX @@ void gen_preserve_fp_state(DisasContext *s)
22
}
17
}
23
}
18
}
24
19
25
+static uint32_t boot_ram_size(MPS2TZMachineState *mms)
20
+/*
21
+ * Generate code for M-profile FP context handling: update the
22
+ * ownership of the FP context, and create a new context if
23
+ * necessary. This corresponds to the parts of the pseudocode
24
+ * ExecuteFPCheck() after the inital PreserveFPState() call.
25
+ */
26
+static void gen_update_fp_context(DisasContext *s)
26
+{
27
+{
27
+ /* Return the size of the RAM block at guest address zero */
28
+ /* Update ownership of FP context: set FPCCR.S to match current state */
28
+ const RAMInfo *p;
29
+ if (s->v8m_fpccr_s_wrong) {
29
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
30
+ TCGv_i32 tmp;
30
+
31
+
31
+ for (p = mmc->raminfo; p->name; p++) {
32
+ tmp = load_cpu_field(v7m.fpccr[M_REG_S]);
32
+ if (p->base == 0) {
33
+ if (s->v8m_secure) {
33
+ return p->size;
34
+ tcg_gen_ori_i32(tmp, tmp, R_V7M_FPCCR_S_MASK);
35
+ } else {
36
+ tcg_gen_andi_i32(tmp, tmp, ~R_V7M_FPCCR_S_MASK);
34
+ }
37
+ }
38
+ store_cpu_field(tmp, v7m.fpccr[M_REG_S]);
39
+ /* Don't need to do this for any further FP insns in this TB */
40
+ s->v8m_fpccr_s_wrong = false;
35
+ }
41
+ }
36
+ g_assert_not_reached();
42
+
43
+ if (s->v7m_new_fp_ctxt_needed) {
44
+ /*
45
+ * Create new FP context by updating CONTROL.FPCA, CONTROL.SFPA,
46
+ * the FPSCR, and VPR.
47
+ */
48
+ TCGv_i32 control, fpscr;
49
+ uint32_t bits = R_V7M_CONTROL_FPCA_MASK;
50
+
51
+ fpscr = load_cpu_field(v7m.fpdscr[s->v8m_secure]);
52
+ gen_helper_vfp_set_fpscr(cpu_env, fpscr);
53
+ tcg_temp_free_i32(fpscr);
54
+ if (dc_isar_feature(aa32_mve, s)) {
55
+ TCGv_i32 z32 = tcg_const_i32(0);
56
+ store_cpu_field(z32, v7m.vpr);
57
+ }
58
+
59
+ /*
60
+ * We don't need to arrange to end the TB, because the only
61
+ * parts of FPSCR which we cache in the TB flags are the VECLEN
62
+ * and VECSTRIDE, and those don't exist for M-profile.
63
+ */
64
+
65
+ if (s->v8m_secure) {
66
+ bits |= R_V7M_CONTROL_SFPA_MASK;
67
+ }
68
+ control = load_cpu_field(v7m.control[M_REG_S]);
69
+ tcg_gen_ori_i32(control, control, bits);
70
+ store_cpu_field(control, v7m.control[M_REG_S]);
71
+ /* Don't need to do this for any further FP insns in this TB */
72
+ s->v7m_new_fp_ctxt_needed = false;
73
+ }
37
+}
74
+}
38
+
75
+
39
static void mps2tz_common_init(MachineState *machine)
76
/*
40
{
77
* Check that VFP access is enabled. If it is, do the necessary
41
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
78
* M-profile lazy-FP handling and then return true.
42
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
79
@@ -XXX,XX +XXX,XX @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
43
80
/* Trigger lazy-state preservation if necessary */
44
create_non_mpc_ram(mms);
81
gen_preserve_fp_state(s);
45
82
46
- armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
83
- /* Update ownership of FP context: set FPCCR.S to match current state */
47
+ armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename,
84
- if (s->v8m_fpccr_s_wrong) {
48
+ boot_ram_size(mms));
85
- TCGv_i32 tmp;
49
}
86
-
50
87
- tmp = load_cpu_field(v7m.fpccr[M_REG_S]);
51
static void mps2_tz_idau_check(IDAUInterface *ii, uint32_t address,
88
- if (s->v8m_secure) {
89
- tcg_gen_ori_i32(tmp, tmp, R_V7M_FPCCR_S_MASK);
90
- } else {
91
- tcg_gen_andi_i32(tmp, tmp, ~R_V7M_FPCCR_S_MASK);
92
- }
93
- store_cpu_field(tmp, v7m.fpccr[M_REG_S]);
94
- /* Don't need to do this for any further FP insns in this TB */
95
- s->v8m_fpccr_s_wrong = false;
96
- }
97
-
98
- if (s->v7m_new_fp_ctxt_needed) {
99
- /*
100
- * Create new FP context by updating CONTROL.FPCA, CONTROL.SFPA,
101
- * the FPSCR, and VPR.
102
- */
103
- TCGv_i32 control, fpscr;
104
- uint32_t bits = R_V7M_CONTROL_FPCA_MASK;
105
-
106
- fpscr = load_cpu_field(v7m.fpdscr[s->v8m_secure]);
107
- gen_helper_vfp_set_fpscr(cpu_env, fpscr);
108
- tcg_temp_free_i32(fpscr);
109
- if (dc_isar_feature(aa32_mve, s)) {
110
- TCGv_i32 z32 = tcg_const_i32(0);
111
- store_cpu_field(z32, v7m.vpr);
112
- }
113
-
114
- /*
115
- * We don't need to arrange to end the TB, because the only
116
- * parts of FPSCR which we cache in the TB flags are the VECLEN
117
- * and VECSTRIDE, and those don't exist for M-profile.
118
- */
119
-
120
- if (s->v8m_secure) {
121
- bits |= R_V7M_CONTROL_SFPA_MASK;
122
- }
123
- control = load_cpu_field(v7m.control[M_REG_S]);
124
- tcg_gen_ori_i32(control, control, bits);
125
- store_cpu_field(control, v7m.control[M_REG_S]);
126
- /* Don't need to do this for any further FP insns in this TB */
127
- s->v7m_new_fp_ctxt_needed = false;
128
- }
129
+ /* Update ownership of FP context and create new FP context if needed */
130
+ gen_update_fp_context(s);
131
}
132
133
return true;
52
--
134
--
53
2.20.1
135
2.20.1
54
136
55
137
diff view generated by jsdifflib
1
The mps2-tz code uses PPCPortInfo data structures to define what
1
vfp_access_check and its helper routine full_vfp_access_check() has
2
devices are present and how they are wired up. Currently we use
2
gradually grown and is now an awkward mix of A-profile only and
3
these to specify device types and addresses, but hard-code the
3
M-profile only pieces. Refactor it into an A-profile only and an
4
interrupt line wiring in each make_* helper function. This works for
4
M-profile only version, taking advantage of the fact that now the
5
the two boards we have at the moment, but the AN524 has some devices
5
only direct call to full_vfp_access_check() is in A-profile-only
6
with different interrupt assignments.
6
code.
7
8
This commit adds the framework to allow PPCPortInfo structures to
9
specify interrupt numbers. We add an array of interrupt numbers to
10
the PPCPortInfo struct, and pass it through to the make_* helpers.
11
The following commit will change the make_* helpers over to using the
12
framework.
13
7
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Message-id: 20210215115138.20465-13-peter.maydell@linaro.org
10
Message-id: 20210618141019.10671-7-peter.maydell@linaro.org
17
---
11
---
18
hw/arm/mps2-tz.c | 36 ++++++++++++++++++++++++------------
12
target/arm/translate-vfp.c | 79 +++++++++++++++++++++++---------------
19
1 file changed, 24 insertions(+), 12 deletions(-)
13
1 file changed, 48 insertions(+), 31 deletions(-)
20
14
21
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
15
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
22
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
23
--- a/hw/arm/mps2-tz.c
17
--- a/target/arm/translate-vfp.c
24
+++ b/hw/arm/mps2-tz.c
18
+++ b/target/arm/translate-vfp.c
25
@@ -XXX,XX +XXX,XX @@ static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
19
@@ -XXX,XX +XXX,XX @@ static void gen_update_fp_context(DisasContext *s)
26
* needs to be plugged into the downstream end of the PPC port.
20
}
21
22
/*
23
- * Check that VFP access is enabled. If it is, do the necessary
24
- * M-profile lazy-FP handling and then return true.
25
- * If not, emit code to generate an appropriate exception and
26
- * return false.
27
+ * Check that VFP access is enabled, A-profile specific version.
28
+ *
29
+ * If VFP is enabled, return true. If not, emit code to generate an
30
+ * appropriate exception and return false.
31
* The ignore_vfp_enabled argument specifies that we should ignore
32
- * whether VFP is enabled via FPEXC[EN]: this should be true for FMXR/FMRX
33
+ * whether VFP is enabled via FPEXC.EN: this should be true for FMXR/FMRX
34
* accesses to FPSID, FPEXC, MVFR0, MVFR1, MVFR2, and false for all other insns.
27
*/
35
*/
28
typedef MemoryRegion *MakeDevFn(MPS2TZMachineState *mms, void *opaque,
36
-static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
29
- const char *name, hwaddr size);
37
+static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled)
30
+ const char *name, hwaddr size,
31
+ const int *irqs);
32
33
typedef struct PPCPortInfo {
34
const char *name;
35
@@ -XXX,XX +XXX,XX @@ typedef struct PPCPortInfo {
36
void *opaque;
37
hwaddr addr;
38
hwaddr size;
39
+ int irqs[3]; /* currently no device needs more IRQ lines than this */
40
} PPCPortInfo;
41
42
typedef struct PPCInfo {
43
@@ -XXX,XX +XXX,XX @@ typedef struct PPCInfo {
44
} PPCInfo;
45
46
static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
47
- void *opaque,
48
- const char *name, hwaddr size)
49
+ void *opaque,
50
+ const char *name, hwaddr size,
51
+ const int *irqs)
52
{
38
{
53
/* Initialize, configure and realize a TYPE_UNIMPLEMENTED_DEVICE,
39
if (s->fp_excp_el) {
54
* and return a pointer to its MemoryRegion.
40
- if (arm_dc_feature(s, ARM_FEATURE_M)) {
55
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
41
- /*
42
- * M-profile mostly catches the "FPU disabled" case early, in
43
- * disas_m_nocp(), but a few insns (eg LCTP, WLSTP, DLSTP)
44
- * which do coprocessor-checks are outside the large ranges of
45
- * the encoding space handled by the patterns in m-nocp.decode,
46
- * and for them we may need to raise NOCP here.
47
- */
48
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
49
- syn_uncategorized(), s->fp_excp_el);
50
- } else {
51
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
52
- syn_fp_access_trap(1, 0xe, false),
53
- s->fp_excp_el);
54
- }
55
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
56
+ syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
57
return false;
58
}
59
60
@@ -XXX,XX +XXX,XX @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
61
unallocated_encoding(s);
62
return false;
63
}
64
+ return true;
65
+}
66
67
- if (arm_dc_feature(s, ARM_FEATURE_M)) {
68
- /* Handle M-profile lazy FP state mechanics */
69
-
70
- /* Trigger lazy-state preservation if necessary */
71
- gen_preserve_fp_state(s);
72
-
73
- /* Update ownership of FP context and create new FP context if needed */
74
- gen_update_fp_context(s);
75
+/*
76
+ * Check that VFP access is enabled, M-profile specific version.
77
+ *
78
+ * If VFP is enabled, do the necessary M-profile lazy-FP handling and then
79
+ * return true. If not, emit code to generate an appropriate exception and
80
+ * return false.
81
+ */
82
+static bool vfp_access_check_m(DisasContext *s)
83
+{
84
+ if (s->fp_excp_el) {
85
+ /*
86
+ * M-profile mostly catches the "FPU disabled" case early, in
87
+ * disas_m_nocp(), but a few insns (eg LCTP, WLSTP, DLSTP)
88
+ * which do coprocessor-checks are outside the large ranges of
89
+ * the encoding space handled by the patterns in m-nocp.decode,
90
+ * and for them we may need to raise NOCP here.
91
+ */
92
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
93
+ syn_uncategorized(), s->fp_excp_el);
94
+ return false;
95
}
96
97
+ /* Handle M-profile lazy FP state mechanics */
98
+
99
+ /* Trigger lazy-state preservation if necessary */
100
+ gen_preserve_fp_state(s);
101
+
102
+ /* Update ownership of FP context and create new FP context if needed */
103
+ gen_update_fp_context(s);
104
+
105
return true;
56
}
106
}
57
107
58
static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
108
@@ -XXX,XX +XXX,XX @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
59
- const char *name, hwaddr size)
109
*/
60
+ const char *name, hwaddr size,
110
bool vfp_access_check(DisasContext *s)
61
+ const int *irqs)
62
{
111
{
63
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
112
- return full_vfp_access_check(s, false);
64
CMSDKAPBUART *uart = opaque;
113
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
65
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
114
+ return vfp_access_check_m(s);
115
+ } else {
116
+ return vfp_access_check_a(s, false);
117
+ }
66
}
118
}
67
119
68
static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
120
static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
69
- const char *name, hwaddr size)
121
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
70
+ const char *name, hwaddr size,
122
return false;
71
+ const int *irqs)
123
}
72
{
124
73
MPS2SCC *scc = opaque;
125
- if (!full_vfp_access_check(s, ignore_vfp_enabled)) {
74
DeviceState *sccdev;
126
+ /*
75
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
127
+ * Call vfp_access_check_a() directly, because we need to tell
76
}
128
+ * it to ignore FPEXC.EN for some register accesses.
77
129
+ */
78
static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
130
+ if (!vfp_access_check_a(s, ignore_vfp_enabled)) {
79
- const char *name, hwaddr size)
131
return true;
80
+ const char *name, hwaddr size,
132
}
81
+ const int *irqs)
133
82
{
83
MPS2FPGAIO *fpgaio = opaque;
84
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
85
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
86
}
87
88
static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
89
- const char *name, hwaddr size)
90
+ const char *name, hwaddr size,
91
+ const int *irqs)
92
{
93
SysBusDevice *s;
94
NICInfo *nd = &nd_table[0];
95
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
96
}
97
98
static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
99
- const char *name, hwaddr size)
100
+ const char *name, hwaddr size,
101
+ const int *irqs)
102
{
103
TZMPC *mpc = opaque;
104
int i = mpc - &mms->ssram_mpc[0];
105
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
106
}
107
108
static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
109
- const char *name, hwaddr size)
110
+ const char *name, hwaddr size,
111
+ const int *irqs)
112
{
113
PL080State *dma = opaque;
114
int i = dma - &mms->dma[0];
115
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_dma(MPS2TZMachineState *mms, void *opaque,
116
}
117
118
static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
119
- const char *name, hwaddr size)
120
+ const char *name, hwaddr size,
121
+ const int *irqs)
122
{
123
/*
124
* The AN505 has five PL022 SPI controllers.
125
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_spi(MPS2TZMachineState *mms, void *opaque,
126
}
127
128
static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
129
- const char *name, hwaddr size)
130
+ const char *name, hwaddr size,
131
+ const int *irqs)
132
{
133
ArmSbconI2CState *i2c = opaque;
134
SysBusDevice *s;
135
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
136
continue;
137
}
138
139
- mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size);
140
+ mr = pinfo->devfn(mms, pinfo->opaque, pinfo->name, pinfo->size,
141
+ pinfo->irqs);
142
portname = g_strdup_printf("port[%d]", port);
143
object_property_set_link(OBJECT(ppc), portname, OBJECT(mr),
144
&error_fatal);
145
--
134
--
146
2.20.1
135
2.20.1
147
136
148
137
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Instead of open-coding the "take NOCP exception if FPU disabled,
2
otherwise call gen_preserve_fp_state()" code in the accessors for
3
FPCXT_NS, add an argument to vfp_access_check_m() which tells it to
4
skip the gen_update_fp_context() call, so we can use it for the
5
FPCXT_NS case.
2
6
3
IDAU is specific to M-profile. KVM only supports A-profile.
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Restrict this interface to TCG, as it is pointless (and
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
confusing) on a KVM-only build.
9
Message-id: 20210618141019.10671-8-peter.maydell@linaro.org
10
---
11
target/arm/translate-a32.h | 2 +-
12
target/arm/translate-m-nocp.c | 10 ++--------
13
target/arm/translate-vfp.c | 13 ++++++++-----
14
3 files changed, 11 insertions(+), 14 deletions(-)
6
15
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20210221222617.2579610-2-f4bug@amsat.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
target/arm/cpu.c | 7 -------
14
target/arm/cpu_tcg.c | 8 ++++++++
15
2 files changed, 8 insertions(+), 7 deletions(-)
16
17
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.c
18
--- a/target/arm/translate-a32.h
20
+++ b/target/arm/cpu.c
19
+++ b/target/arm/translate-a32.h
21
@@ -XXX,XX +XXX,XX @@ static const TypeInfo arm_cpu_type_info = {
20
@@ -XXX,XX +XXX,XX @@ bool disas_neon_shared(DisasContext *s, uint32_t insn);
22
.class_init = arm_cpu_class_init,
21
void load_reg_var(DisasContext *s, TCGv_i32 var, int reg);
23
};
22
void arm_gen_condlabel(DisasContext *s);
24
23
bool vfp_access_check(DisasContext *s);
25
-static const TypeInfo idau_interface_type_info = {
24
-void gen_preserve_fp_state(DisasContext *s);
26
- .name = TYPE_IDAU_INTERFACE,
25
+bool vfp_access_check_m(DisasContext *s, bool skip_context_update);
27
- .parent = TYPE_INTERFACE,
26
void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop);
28
- .class_size = sizeof(IDAUInterfaceClass),
27
void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop);
29
-};
28
void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop);
30
-
29
diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c
31
static void arm_cpu_register_types(void)
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/translate-m-nocp.c
32
+++ b/target/arm/translate-m-nocp.c
33
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
34
* otherwise PreserveFPState(), and then FPCXT_NS writes
35
* behave the same as FPCXT_S writes.
36
*/
37
- if (s->fp_excp_el) {
38
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
39
- syn_uncategorized(), s->fp_excp_el);
40
+ if (!vfp_access_check_m(s, true)) {
41
/*
42
* This was only a conditional exception, so override
43
* gen_exception_insn()'s default to DISAS_NORETURN
44
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
45
s->base.is_jmp = DISAS_NEXT;
46
break;
47
}
48
- gen_preserve_fp_state(s);
49
}
50
/* fall through */
51
case ARM_VFP_FPCXT_S:
52
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
53
* otherwise PreserveFPState(), and then FPCXT_NS
54
* reads the same as FPCXT_S.
55
*/
56
- if (s->fp_excp_el) {
57
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
58
- syn_uncategorized(), s->fp_excp_el);
59
+ if (!vfp_access_check_m(s, true)) {
60
/*
61
* This was only a conditional exception, so override
62
* gen_exception_insn()'s default to DISAS_NORETURN
63
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
64
s->base.is_jmp = DISAS_NEXT;
65
break;
66
}
67
- gen_preserve_fp_state(s);
68
tmp = tcg_temp_new_i32();
69
sfpa = tcg_temp_new_i32();
70
fpscr = tcg_temp_new_i32();
71
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/target/arm/translate-vfp.c
74
+++ b/target/arm/translate-vfp.c
75
@@ -XXX,XX +XXX,XX @@ static inline long vfp_f16_offset(unsigned reg, bool top)
76
* Generate code for M-profile lazy FP state preservation if needed;
77
* this corresponds to the pseudocode PreserveFPState() function.
78
*/
79
-void gen_preserve_fp_state(DisasContext *s)
80
+static void gen_preserve_fp_state(DisasContext *s)
32
{
81
{
33
const size_t cpu_count = ARRAY_SIZE(arm_cpus);
82
if (s->v7m_lspact) {
34
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_register_types(void)
83
/*
35
if (cpu_count) {
84
@@ -XXX,XX +XXX,XX @@ static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled)
36
size_t i;
85
* If VFP is enabled, do the necessary M-profile lazy-FP handling and then
37
86
* return true. If not, emit code to generate an appropriate exception and
38
- type_register_static(&idau_interface_type_info);
87
* return false.
39
for (i = 0; i < cpu_count; ++i) {
88
+ * skip_context_update is true to skip the "update FP context" part of this.
40
arm_cpu_register(&arm_cpus[i]);
89
*/
41
}
90
-static bool vfp_access_check_m(DisasContext *s)
42
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
91
+bool vfp_access_check_m(DisasContext *s, bool skip_context_update)
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/cpu_tcg.c
45
+++ b/target/arm/cpu_tcg.c
46
@@ -XXX,XX +XXX,XX @@
47
#include "hw/core/tcg-cpu-ops.h"
48
#endif /* CONFIG_TCG */
49
#include "internals.h"
50
+#include "target/arm/idau.h"
51
52
/* CPU models. These are not needed for the AArch64 linux-user build. */
53
#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
54
@@ -XXX,XX +XXX,XX @@ static const ARMCPUInfo arm_tcg_cpus[] = {
55
{ .name = "pxa270-c5", .initfn = pxa270c5_initfn },
56
};
57
58
+static const TypeInfo idau_interface_type_info = {
59
+ .name = TYPE_IDAU_INTERFACE,
60
+ .parent = TYPE_INTERFACE,
61
+ .class_size = sizeof(IDAUInterfaceClass),
62
+};
63
+
64
static void arm_tcg_cpu_register_types(void)
65
{
92
{
66
size_t i;
93
if (s->fp_excp_el) {
67
94
/*
68
+ type_register_static(&idau_interface_type_info);
95
@@ -XXX,XX +XXX,XX @@ static bool vfp_access_check_m(DisasContext *s)
69
for (i = 0; i < ARRAY_SIZE(arm_tcg_cpus); ++i) {
96
/* Trigger lazy-state preservation if necessary */
70
arm_cpu_register(&arm_tcg_cpus[i]);
97
gen_preserve_fp_state(s);
98
99
- /* Update ownership of FP context and create new FP context if needed */
100
- gen_update_fp_context(s);
101
+ if (!skip_context_update) {
102
+ /* Update ownership of FP context and create new FP context if needed */
103
+ gen_update_fp_context(s);
104
+ }
105
106
return true;
107
}
108
@@ -XXX,XX +XXX,XX @@ static bool vfp_access_check_m(DisasContext *s)
109
bool vfp_access_check(DisasContext *s)
110
{
111
if (arm_dc_feature(s, ARM_FEATURE_M)) {
112
- return vfp_access_check_m(s);
113
+ return vfp_access_check_m(s, false);
114
} else {
115
return vfp_access_check_a(s, false);
71
}
116
}
72
--
117
--
73
2.20.1
118
2.20.1
74
119
75
120
diff view generated by jsdifflib
1
From: Rebecca Cran <rebecca@nuviainc.com>
1
Implement the forms of the MVE VLDR and VSTR insns which perform
2
non-widening loads of bytes, halfwords or words from memory into
3
vector elements of the same width (encodings T5, T6, T7).
2
4
3
Add support for FEAT_SSBS. SSBS (Speculative Store Bypass Safe) is an
5
(At the moment we know for MVE and M-profile in general that
4
optional feature in ARMv8.0, and mandatory in ARMv8.5.
6
vfp_access_check() can never return false, but we include the
7
conventional return-true-on-failure check for consistency
8
with non-M-profile translation code.)
5
9
6
Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210216224543.16142-2-rebecca@nuviainc.com
12
Message-id: 20210617121628.20116-2-peter.maydell@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
13
---
11
target/arm/cpu.h | 15 ++++++++++++++-
14
target/arm/{translate-mve.c => helper-mve.h} | 19 +-
12
target/arm/internals.h | 6 ++++++
15
target/arm/helper.h | 2 +
13
target/arm/helper.c | 37 +++++++++++++++++++++++++++++++++++++
16
target/arm/internals.h | 11 ++
14
target/arm/translate-a64.c | 12 ++++++++++++
17
target/arm/mve.decode | 22 +++
15
4 files changed, 69 insertions(+), 1 deletion(-)
18
target/arm/mve_helper.c | 172 +++++++++++++++++++
19
target/arm/translate-mve.c | 119 +++++++++++++
20
target/arm/meson.build | 1 +
21
7 files changed, 334 insertions(+), 12 deletions(-)
22
copy target/arm/{translate-mve.c => helper-mve.h} (61%)
23
create mode 100644 target/arm/mve_helper.c
16
24
17
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
25
diff --git a/target/arm/translate-mve.c b/target/arm/helper-mve.h
18
index XXXXXXX..XXXXXXX 100644
26
similarity index 61%
19
--- a/target/arm/cpu.h
27
copy from target/arm/translate-mve.c
20
+++ b/target/arm/cpu.h
28
copy to target/arm/helper-mve.h
21
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
29
index XXXXXXX..XXXXXXX 100644
22
#define SCTLR_TE (1U << 30) /* AArch32 only */
30
--- a/target/arm/translate-mve.c
23
#define SCTLR_EnIB (1U << 30) /* v8.3, AArch64 only */
31
+++ b/target/arm/helper-mve.h
24
#define SCTLR_EnIA (1U << 31) /* v8.3, AArch64 only */
32
@@ -XXX,XX +XXX,XX @@
25
+#define SCTLR_DSSBS_32 (1U << 31) /* v8.5, AArch32 only */
26
#define SCTLR_BT0 (1ULL << 35) /* v8.5-BTI */
27
#define SCTLR_BT1 (1ULL << 36) /* v8.5-BTI */
28
#define SCTLR_ITFSB (1ULL << 37) /* v8.5-MemTag */
29
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
30
#define SCTLR_TCF (3ULL << 40) /* v8.5-MemTag */
31
#define SCTLR_ATA0 (1ULL << 42) /* v8.5-MemTag */
32
#define SCTLR_ATA (1ULL << 43) /* v8.5-MemTag */
33
-#define SCTLR_DSSBS (1ULL << 44) /* v8.5 */
34
+#define SCTLR_DSSBS_64 (1ULL << 44) /* v8.5, AArch64 only */
35
36
#define CPTR_TCPAC (1U << 31)
37
#define CPTR_TTA (1U << 20)
38
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
39
#define CPSR_IL (1U << 20)
40
#define CPSR_DIT (1U << 21)
41
#define CPSR_PAN (1U << 22)
42
+#define CPSR_SSBS (1U << 23)
43
#define CPSR_J (1U << 24)
44
#define CPSR_IT_0_1 (3U << 25)
45
#define CPSR_Q (1U << 27)
46
@@ -XXX,XX +XXX,XX @@ void pmu_init(ARMCPU *cpu);
47
#define PSTATE_A (1U << 8)
48
#define PSTATE_D (1U << 9)
49
#define PSTATE_BTYPE (3U << 10)
50
+#define PSTATE_SSBS (1U << 12)
51
#define PSTATE_IL (1U << 20)
52
#define PSTATE_SS (1U << 21)
53
#define PSTATE_PAN (1U << 22)
54
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_dit(const ARMISARegisters *id)
55
return FIELD_EX32(id->id_pfr0, ID_PFR0, DIT) != 0;
56
}
57
58
+static inline bool isar_feature_aa32_ssbs(const ARMISARegisters *id)
59
+{
60
+ return FIELD_EX32(id->id_pfr2, ID_PFR2, SSBS) != 0;
61
+}
62
+
63
/*
33
/*
64
* 64-bit feature tests via id registers.
34
- * ARM translation: M-profile MVE instructions
35
+ * M-profile MVE specific helper definitions
36
*
37
* Copyright (c) 2021 Linaro, Ltd.
38
*
39
@@ -XXX,XX +XXX,XX @@
40
* You should have received a copy of the GNU Lesser General Public
41
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
65
*/
42
*/
66
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa64_dit(const ARMISARegisters *id)
43
-
67
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, DIT) != 0;
44
-#include "qemu/osdep.h"
68
}
45
-#include "tcg/tcg-op.h"
69
46
-#include "tcg/tcg-op-gvec.h"
70
+static inline bool isar_feature_aa64_ssbs(const ARMISARegisters *id)
47
-#include "exec/exec-all.h"
71
+{
48
-#include "exec/gen-icount.h"
72
+ return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SSBS) != 0;
49
-#include "translate.h"
73
+}
50
-#include "translate-a32.h"
74
+
51
-
75
/*
52
-/* Include the generated decoder */
76
* Feature tests for "does this exist in either 32-bit or 64-bit?"
53
-#include "decode-mve.c.inc"
77
*/
54
+DEF_HELPER_FLAGS_3(mve_vldrb, TCG_CALL_NO_WG, void, env, ptr, i32)
55
+DEF_HELPER_FLAGS_3(mve_vldrh, TCG_CALL_NO_WG, void, env, ptr, i32)
56
+DEF_HELPER_FLAGS_3(mve_vldrw, TCG_CALL_NO_WG, void, env, ptr, i32)
57
+DEF_HELPER_FLAGS_3(mve_vstrb, TCG_CALL_NO_WG, void, env, ptr, i32)
58
+DEF_HELPER_FLAGS_3(mve_vstrh, TCG_CALL_NO_WG, void, env, ptr, i32)
59
+DEF_HELPER_FLAGS_3(mve_vstrw, TCG_CALL_NO_WG, void, env, ptr, i32)
60
diff --git a/target/arm/helper.h b/target/arm/helper.h
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/helper.h
63
+++ b/target/arm/helper.h
64
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_6(gvec_bfmlal_idx, TCG_CALL_NO_RWG,
65
#include "helper-a64.h"
66
#include "helper-sve.h"
67
#endif
68
+
69
+#include "helper-mve.h"
78
diff --git a/target/arm/internals.h b/target/arm/internals.h
70
diff --git a/target/arm/internals.h b/target/arm/internals.h
79
index XXXXXXX..XXXXXXX 100644
71
index XXXXXXX..XXXXXXX 100644
80
--- a/target/arm/internals.h
72
--- a/target/arm/internals.h
81
+++ b/target/arm/internals.h
73
+++ b/target/arm/internals.h
82
@@ -XXX,XX +XXX,XX @@ static inline uint32_t aarch32_cpsr_valid_mask(uint64_t features,
74
@@ -XXX,XX +XXX,XX @@ static inline uint64_t useronly_maybe_clean_ptr(uint32_t desc, uint64_t ptr)
83
if (isar_feature_aa32_dit(id)) {
75
return ptr;
84
valid |= CPSR_DIT;
85
}
86
+ if (isar_feature_aa32_ssbs(id)) {
87
+ valid |= CPSR_SSBS;
88
+ }
89
90
return valid;
91
}
76
}
92
@@ -XXX,XX +XXX,XX @@ static inline uint32_t aarch64_pstate_valid_mask(const ARMISARegisters *id)
77
93
if (isar_feature_aa64_dit(id)) {
78
+/* Values for M-profile PSR.ECI for MVE insns */
94
valid |= PSTATE_DIT;
79
+enum MVEECIState {
95
}
80
+ ECI_NONE = 0, /* No completed beats */
96
+ if (isar_feature_aa64_ssbs(id)) {
81
+ ECI_A0 = 1, /* Completed: A0 */
97
+ valid |= PSTATE_SSBS;
82
+ ECI_A0A1 = 2, /* Completed: A0, A1 */
98
+ }
83
+ /* 3 is reserved */
99
if (isar_feature_aa64_mte(id)) {
84
+ ECI_A0A1A2 = 4, /* Completed: A0, A1, A2 */
100
valid |= PSTATE_TCO;
85
+ ECI_A0A1A2B0 = 5, /* Completed: A0, A1, A2, B0 */
101
}
86
+ /* All other values reserved */
102
diff --git a/target/arm/helper.c b/target/arm/helper.c
103
index XXXXXXX..XXXXXXX 100644
104
--- a/target/arm/helper.c
105
+++ b/target/arm/helper.c
106
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo dit_reginfo = {
107
.readfn = aa64_dit_read, .writefn = aa64_dit_write
108
};
109
110
+static uint64_t aa64_ssbs_read(CPUARMState *env, const ARMCPRegInfo *ri)
111
+{
112
+ return env->pstate & PSTATE_SSBS;
113
+}
114
+
115
+static void aa64_ssbs_write(CPUARMState *env, const ARMCPRegInfo *ri,
116
+ uint64_t value)
117
+{
118
+ env->pstate = (env->pstate & ~PSTATE_SSBS) | (value & PSTATE_SSBS);
119
+}
120
+
121
+static const ARMCPRegInfo ssbs_reginfo = {
122
+ .name = "SSBS", .state = ARM_CP_STATE_AA64,
123
+ .opc0 = 3, .opc1 = 3, .crn = 4, .crm = 2, .opc2 = 6,
124
+ .type = ARM_CP_NO_RAW, .access = PL0_RW,
125
+ .readfn = aa64_ssbs_read, .writefn = aa64_ssbs_write
126
+};
87
+};
127
+
88
+
128
static CPAccessResult aa64_cacheop_poc_access(CPUARMState *env,
89
#endif
129
const ARMCPRegInfo *ri,
90
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
130
bool isread)
91
index XXXXXXX..XXXXXXX 100644
131
@@ -XXX,XX +XXX,XX @@ void register_cp_regs_for_features(ARMCPU *cpu)
92
--- a/target/arm/mve.decode
132
if (cpu_isar_feature(aa64_dit, cpu)) {
93
+++ b/target/arm/mve.decode
133
define_one_arm_cp_reg(cpu, &dit_reginfo);
94
@@ -XXX,XX +XXX,XX @@
134
}
95
#
135
+ if (cpu_isar_feature(aa64_ssbs, cpu)) {
96
# This file is processed by scripts/decodetree.py
136
+ define_one_arm_cp_reg(cpu, &ssbs_reginfo);
97
#
137
+ }
98
+
138
99
+%qd 22:1 13:3
139
if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
100
+
140
define_arm_cp_regs(cpu, vhe_reginfo);
101
+&vldr_vstr rn qd imm p a w size l
141
@@ -XXX,XX +XXX,XX @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
102
+
142
env->uncached_cpsr &= ~(CPSR_IL | CPSR_J);
103
+@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd
143
env->daif |= mask;
104
+
144
105
+# Vector loads and stores
145
+ if (cpu_isar_feature(aa32_ssbs, env_archcpu(env))) {
106
+
146
+ if (env->cp15.sctlr_el[new_el] & SCTLR_DSSBS_32) {
107
+# Non-widening loads/stores (P=0 W=0 is 'related encoding')
147
+ env->uncached_cpsr |= CPSR_SSBS;
108
+VLDR_VSTR 1110110 0 a:1 . 1 . .... ... 111100 ....... @vldr_vstr \
148
+ } else {
109
+ size=0 p=0 w=1
149
+ env->uncached_cpsr &= ~CPSR_SSBS;
110
+VLDR_VSTR 1110110 0 a:1 . 1 . .... ... 111101 ....... @vldr_vstr \
111
+ size=1 p=0 w=1
112
+VLDR_VSTR 1110110 0 a:1 . 1 . .... ... 111110 ....... @vldr_vstr \
113
+ size=2 p=0 w=1
114
+VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111100 ....... @vldr_vstr \
115
+ size=0 p=1
116
+VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111101 ....... @vldr_vstr \
117
+ size=1 p=1
118
+VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111110 ....... @vldr_vstr \
119
+ size=2 p=1
120
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
121
new file mode 100644
122
index XXXXXXX..XXXXXXX
123
--- /dev/null
124
+++ b/target/arm/mve_helper.c
125
@@ -XXX,XX +XXX,XX @@
126
+/*
127
+ * M-profile MVE Operations
128
+ *
129
+ * Copyright (c) 2021 Linaro, Ltd.
130
+ *
131
+ * This library is free software; you can redistribute it and/or
132
+ * modify it under the terms of the GNU Lesser General Public
133
+ * License as published by the Free Software Foundation; either
134
+ * version 2.1 of the License, or (at your option) any later version.
135
+ *
136
+ * This library is distributed in the hope that it will be useful,
137
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
138
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
139
+ * Lesser General Public License for more details.
140
+ *
141
+ * You should have received a copy of the GNU Lesser General Public
142
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
143
+ */
144
+
145
+#include "qemu/osdep.h"
146
+#include "cpu.h"
147
+#include "internals.h"
148
+#include "vec_internal.h"
149
+#include "exec/helper-proto.h"
150
+#include "exec/cpu_ldst.h"
151
+#include "exec/exec-all.h"
152
+
153
+static uint16_t mve_element_mask(CPUARMState *env)
154
+{
155
+ /*
156
+ * Return the mask of which elements in the MVE vector should be
157
+ * updated. This is a combination of multiple things:
158
+ * (1) by default, we update every lane in the vector
159
+ * (2) VPT predication stores its state in the VPR register;
160
+ * (3) low-overhead-branch tail predication will mask out part
161
+ * the vector on the final iteration of the loop
162
+ * (4) if EPSR.ECI is set then we must execute only some beats
163
+ * of the insn
164
+ * We combine all these into a 16-bit result with the same semantics
165
+ * as VPR.P0: 0 to mask the lane, 1 if it is active.
166
+ * 8-bit vector ops will look at all bits of the result;
167
+ * 16-bit ops will look at bits 0, 2, 4, ...;
168
+ * 32-bit ops will look at bits 0, 4, 8 and 12.
169
+ * Compare pseudocode GetCurInstrBeat(), though that only returns
170
+ * the 4-bit slice of the mask corresponding to a single beat.
171
+ */
172
+ uint16_t mask = FIELD_EX32(env->v7m.vpr, V7M_VPR, P0);
173
+
174
+ if (!(env->v7m.vpr & R_V7M_VPR_MASK01_MASK)) {
175
+ mask |= 0xff;
176
+ }
177
+ if (!(env->v7m.vpr & R_V7M_VPR_MASK23_MASK)) {
178
+ mask |= 0xff00;
179
+ }
180
+
181
+ if (env->v7m.ltpsize < 4 &&
182
+ env->regs[14] <= (1 << (4 - env->v7m.ltpsize))) {
183
+ /*
184
+ * Tail predication active, and this is the last loop iteration.
185
+ * The element size is (1 << ltpsize), and we only want to process
186
+ * loopcount elements, so we want to retain the least significant
187
+ * (loopcount * esize) predicate bits and zero out bits above that.
188
+ */
189
+ int masklen = env->regs[14] << env->v7m.ltpsize;
190
+ assert(masklen <= 16);
191
+ mask &= MAKE_64BIT_MASK(0, masklen);
192
+ }
193
+
194
+ if ((env->condexec_bits & 0xf) == 0) {
195
+ /*
196
+ * ECI bits indicate which beats are already executed;
197
+ * we handle this by effectively predicating them out.
198
+ */
199
+ int eci = env->condexec_bits >> 4;
200
+ switch (eci) {
201
+ case ECI_NONE:
202
+ break;
203
+ case ECI_A0:
204
+ mask &= 0xfff0;
205
+ break;
206
+ case ECI_A0A1:
207
+ mask &= 0xff00;
208
+ break;
209
+ case ECI_A0A1A2:
210
+ case ECI_A0A1A2B0:
211
+ mask &= 0xf000;
212
+ break;
213
+ default:
214
+ g_assert_not_reached();
150
+ }
215
+ }
151
+ }
216
+ }
152
+
217
+
153
if (new_mode == ARM_CPU_MODE_HYP) {
218
+ return mask;
154
env->thumb = (env->cp15.sctlr_el[2] & SCTLR_TE) != 0;
219
+}
155
env->elr_el[2] = env->regs[15];
220
+
156
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
221
+static void mve_advance_vpt(CPUARMState *env)
157
new_mode |= PSTATE_TCO;
222
+{
158
}
223
+ /* Advance the VPT and ECI state if necessary */
159
224
+ uint32_t vpr = env->v7m.vpr;
160
+ if (cpu_isar_feature(aa64_ssbs, cpu)) {
225
+ unsigned mask01, mask23;
161
+ if (env->cp15.sctlr_el[new_el] & SCTLR_DSSBS_64) {
226
+
162
+ new_mode |= PSTATE_SSBS;
227
+ if ((env->condexec_bits & 0xf) == 0) {
163
+ } else {
228
+ env->condexec_bits = (env->condexec_bits == (ECI_A0A1A2B0 << 4)) ?
164
+ new_mode &= ~PSTATE_SSBS;
229
+ (ECI_A0 << 4) : (ECI_NONE << 4);
230
+ }
231
+
232
+ if (!(vpr & (R_V7M_VPR_MASK01_MASK | R_V7M_VPR_MASK23_MASK))) {
233
+ /* VPT not enabled, nothing to do */
234
+ return;
235
+ }
236
+
237
+ mask01 = FIELD_EX32(vpr, V7M_VPR, MASK01);
238
+ mask23 = FIELD_EX32(vpr, V7M_VPR, MASK23);
239
+ if (mask01 > 8) {
240
+ /* high bit set, but not 0b1000: invert the relevant half of P0 */
241
+ vpr ^= 0xff;
242
+ }
243
+ if (mask23 > 8) {
244
+ /* high bit set, but not 0b1000: invert the relevant half of P0 */
245
+ vpr ^= 0xff00;
246
+ }
247
+ vpr = FIELD_DP32(vpr, V7M_VPR, MASK01, mask01 << 1);
248
+ vpr = FIELD_DP32(vpr, V7M_VPR, MASK23, mask23 << 1);
249
+ env->v7m.vpr = vpr;
250
+}
251
+
252
+
253
+#define DO_VLDR(OP, MSIZE, LDTYPE, ESIZE, TYPE) \
254
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, uint32_t addr) \
255
+ { \
256
+ TYPE *d = vd; \
257
+ uint16_t mask = mve_element_mask(env); \
258
+ unsigned b, e; \
259
+ /* \
260
+ * R_SXTM allows the dest reg to become UNKNOWN for abandoned \
261
+ * beats so we don't care if we update part of the dest and \
262
+ * then take an exception. \
263
+ */ \
264
+ for (b = 0, e = 0; b < 16; b += ESIZE, e++) { \
265
+ if (mask & (1 << b)) { \
266
+ d[H##ESIZE(e)] = cpu_##LDTYPE##_data_ra(env, addr, GETPC()); \
267
+ } \
268
+ addr += MSIZE; \
269
+ } \
270
+ mve_advance_vpt(env); \
271
+ }
272
+
273
+#define DO_VSTR(OP, MSIZE, STTYPE, ESIZE, TYPE) \
274
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, uint32_t addr) \
275
+ { \
276
+ TYPE *d = vd; \
277
+ uint16_t mask = mve_element_mask(env); \
278
+ unsigned b, e; \
279
+ for (b = 0, e = 0; b < 16; b += ESIZE, e++) { \
280
+ if (mask & (1 << b)) { \
281
+ cpu_##STTYPE##_data_ra(env, addr, d[H##ESIZE(e)], GETPC()); \
282
+ } \
283
+ addr += MSIZE; \
284
+ } \
285
+ mve_advance_vpt(env); \
286
+ }
287
+
288
+DO_VLDR(vldrb, 1, ldub, 1, uint8_t)
289
+DO_VLDR(vldrh, 2, lduw, 2, uint16_t)
290
+DO_VLDR(vldrw, 4, ldl, 4, uint32_t)
291
+
292
+DO_VSTR(vstrb, 1, stb, 1, uint8_t)
293
+DO_VSTR(vstrh, 2, stw, 2, uint16_t)
294
+DO_VSTR(vstrw, 4, stl, 4, uint32_t)
295
+
296
+#undef DO_VLDR
297
+#undef DO_VSTR
298
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
299
index XXXXXXX..XXXXXXX 100644
300
--- a/target/arm/translate-mve.c
301
+++ b/target/arm/translate-mve.c
302
@@ -XXX,XX +XXX,XX @@
303
304
/* Include the generated decoder */
305
#include "decode-mve.c.inc"
306
+
307
+typedef void MVEGenLdStFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
308
+
309
+/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
310
+static inline long mve_qreg_offset(unsigned reg)
311
+{
312
+ return offsetof(CPUARMState, vfp.zregs[reg].d[0]);
313
+}
314
+
315
+static TCGv_ptr mve_qreg_ptr(unsigned reg)
316
+{
317
+ TCGv_ptr ret = tcg_temp_new_ptr();
318
+ tcg_gen_addi_ptr(ret, cpu_env, mve_qreg_offset(reg));
319
+ return ret;
320
+}
321
+
322
+static bool mve_check_qreg_bank(DisasContext *s, int qmask)
323
+{
324
+ /*
325
+ * Check whether Qregs are in range. For v8.1M only Q0..Q7
326
+ * are supported, see VFPSmallRegisterBank().
327
+ */
328
+ return qmask < 8;
329
+}
330
+
331
+static bool mve_eci_check(DisasContext *s)
332
+{
333
+ /*
334
+ * This is a beatwise insn: check that ECI is valid (not a
335
+ * reserved value) and note that we are handling it.
336
+ * Return true if OK, false if we generated an exception.
337
+ */
338
+ s->eci_handled = true;
339
+ switch (s->eci) {
340
+ case ECI_NONE:
341
+ case ECI_A0:
342
+ case ECI_A0A1:
343
+ case ECI_A0A1A2:
344
+ case ECI_A0A1A2B0:
345
+ return true;
346
+ default:
347
+ /* Reserved value: INVSTATE UsageFault */
348
+ gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
349
+ default_exception_el(s));
350
+ return false;
351
+ }
352
+}
353
+
354
+static void mve_update_eci(DisasContext *s)
355
+{
356
+ /*
357
+ * The helper function will always update the CPUState field,
358
+ * so we only need to update the DisasContext field.
359
+ */
360
+ if (s->eci) {
361
+ s->eci = (s->eci == ECI_A0A1A2B0) ? ECI_A0 : ECI_NONE;
362
+ }
363
+}
364
+
365
+static bool do_ldst(DisasContext *s, arg_VLDR_VSTR *a, MVEGenLdStFn *fn)
366
+{
367
+ TCGv_i32 addr;
368
+ uint32_t offset;
369
+ TCGv_ptr qreg;
370
+
371
+ if (!dc_isar_feature(aa32_mve, s) ||
372
+ !mve_check_qreg_bank(s, a->qd) ||
373
+ !fn) {
374
+ return false;
375
+ }
376
+
377
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
378
+ if (a->rn == 15 || (a->rn == 13 && a->w)) {
379
+ return false;
380
+ }
381
+
382
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
383
+ return true;
384
+ }
385
+
386
+ offset = a->imm << a->size;
387
+ if (!a->a) {
388
+ offset = -offset;
389
+ }
390
+ addr = load_reg(s, a->rn);
391
+ if (a->p) {
392
+ tcg_gen_addi_i32(addr, addr, offset);
393
+ }
394
+
395
+ qreg = mve_qreg_ptr(a->qd);
396
+ fn(cpu_env, qreg, addr);
397
+ tcg_temp_free_ptr(qreg);
398
+
399
+ /*
400
+ * Writeback always happens after the last beat of the insn,
401
+ * regardless of predication
402
+ */
403
+ if (a->w) {
404
+ if (!a->p) {
405
+ tcg_gen_addi_i32(addr, addr, offset);
165
+ }
406
+ }
166
+ }
407
+ store_reg(s, a->rn, addr);
167
+
408
+ } else {
168
pstate_write(env, PSTATE_DAIF | new_mode);
409
+ tcg_temp_free_i32(addr);
169
env->aarch64 = 1;
410
+ }
170
aarch64_restore_sp(env, new_el);
411
+ mve_update_eci(s);
171
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
412
+ return true;
172
index XXXXXXX..XXXXXXX 100644
413
+}
173
--- a/target/arm/translate-a64.c
414
+
174
+++ b/target/arm/translate-a64.c
415
+static bool trans_VLDR_VSTR(DisasContext *s, arg_VLDR_VSTR *a)
175
@@ -XXX,XX +XXX,XX @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
416
+{
176
tcg_temp_free_i32(t1);
417
+ static MVEGenLdStFn * const ldstfns[4][2] = {
177
break;
418
+ { gen_helper_mve_vstrb, gen_helper_mve_vldrb },
178
419
+ { gen_helper_mve_vstrh, gen_helper_mve_vldrh },
179
+ case 0x19: /* SSBS */
420
+ { gen_helper_mve_vstrw, gen_helper_mve_vldrw },
180
+ if (!dc_isar_feature(aa64_ssbs, s)) {
421
+ { NULL, NULL }
181
+ goto do_unallocated;
422
+ };
182
+ }
423
+ return do_ldst(s, a, ldstfns[a->size][a->l]);
183
+ if (crm & 1) {
424
+}
184
+ set_pstate_bits(PSTATE_SSBS);
425
diff --git a/target/arm/meson.build b/target/arm/meson.build
185
+ } else {
426
index XXXXXXX..XXXXXXX 100644
186
+ clear_pstate_bits(PSTATE_SSBS);
427
--- a/target/arm/meson.build
187
+ }
428
+++ b/target/arm/meson.build
188
+ /* Don't need to rebuild hflags since SSBS is a nop */
429
@@ -XXX,XX +XXX,XX @@ arm_ss.add(files(
189
+ break;
430
'helper.c',
190
+
431
'iwmmxt_helper.c',
191
case 0x1a: /* DIT */
432
'm_helper.c',
192
if (!dc_isar_feature(aa64_dit, s)) {
433
+ 'mve_helper.c',
193
goto do_unallocated;
434
'neon_helper.c',
435
'op_helper.c',
436
'tlb_helper.c',
194
--
437
--
195
2.20.1
438
2.20.1
196
439
197
440
diff view generated by jsdifflib
New patch
1
Implement the variants of MVE VLDR (encodings T1, T2) which perform
2
"widening" loads where bytes or halfwords are loaded from memory and
3
zero or sign-extended into halfword or word length vector elements,
4
and the narrowing MVE VSTR (encodings T1, T2) where bytes or
5
halfwords are stored from halfword or word elements.
1
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210617121628.20116-3-peter.maydell@linaro.org
10
---
11
target/arm/helper-mve.h | 10 ++++++++++
12
target/arm/mve.decode | 25 +++++++++++++++++++++++--
13
target/arm/mve_helper.c | 11 +++++++++++
14
target/arm/translate-mve.c | 14 ++++++++++++++
15
4 files changed, 58 insertions(+), 2 deletions(-)
16
17
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper-mve.h
20
+++ b/target/arm/helper-mve.h
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vldrw, TCG_CALL_NO_WG, void, env, ptr, i32)
22
DEF_HELPER_FLAGS_3(mve_vstrb, TCG_CALL_NO_WG, void, env, ptr, i32)
23
DEF_HELPER_FLAGS_3(mve_vstrh, TCG_CALL_NO_WG, void, env, ptr, i32)
24
DEF_HELPER_FLAGS_3(mve_vstrw, TCG_CALL_NO_WG, void, env, ptr, i32)
25
+
26
+DEF_HELPER_FLAGS_3(mve_vldrb_sh, TCG_CALL_NO_WG, void, env, ptr, i32)
27
+DEF_HELPER_FLAGS_3(mve_vldrb_sw, TCG_CALL_NO_WG, void, env, ptr, i32)
28
+DEF_HELPER_FLAGS_3(mve_vldrb_uh, TCG_CALL_NO_WG, void, env, ptr, i32)
29
+DEF_HELPER_FLAGS_3(mve_vldrb_uw, TCG_CALL_NO_WG, void, env, ptr, i32)
30
+DEF_HELPER_FLAGS_3(mve_vldrh_sw, TCG_CALL_NO_WG, void, env, ptr, i32)
31
+DEF_HELPER_FLAGS_3(mve_vldrh_uw, TCG_CALL_NO_WG, void, env, ptr, i32)
32
+DEF_HELPER_FLAGS_3(mve_vstrb_h, TCG_CALL_NO_WG, void, env, ptr, i32)
33
+DEF_HELPER_FLAGS_3(mve_vstrb_w, TCG_CALL_NO_WG, void, env, ptr, i32)
34
+DEF_HELPER_FLAGS_3(mve_vstrh_w, TCG_CALL_NO_WG, void, env, ptr, i32)
35
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/mve.decode
38
+++ b/target/arm/mve.decode
39
@@ -XXX,XX +XXX,XX @@
40
41
%qd 22:1 13:3
42
43
-&vldr_vstr rn qd imm p a w size l
44
+&vldr_vstr rn qd imm p a w size l u
45
46
-@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd
47
+@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
48
+# Note that both Rn and Qd are 3 bits only (no D bit)
49
+@vldst_wn ... u:1 ... . . . . l:1 . rn:3 qd:3 . ... .. imm:7 &vldr_vstr
50
51
# Vector loads and stores
52
53
+# Widening loads and narrowing stores:
54
+# for these P=0 W=0 is 'related encoding'; sz=11 is 'related encoding'
55
+# This means we need to expand out to multiple patterns for P, W, SZ.
56
+# For stores the U bit must be 0 but we catch that in the trans_ function.
57
+# The naming scheme here is "VLDSTB_H == in-memory byte load/store to/from
58
+# signed halfword element in register", etc.
59
+VLDSTB_H 111 . 110 0 a:1 0 1 . 0 ... ... 0 111 01 ....... @vldst_wn \
60
+ p=0 w=1 size=1
61
+VLDSTB_H 111 . 110 1 a:1 0 w:1 . 0 ... ... 0 111 01 ....... @vldst_wn \
62
+ p=1 size=1
63
+VLDSTB_W 111 . 110 0 a:1 0 1 . 0 ... ... 0 111 10 ....... @vldst_wn \
64
+ p=0 w=1 size=2
65
+VLDSTB_W 111 . 110 1 a:1 0 w:1 . 0 ... ... 0 111 10 ....... @vldst_wn \
66
+ p=1 size=2
67
+VLDSTH_W 111 . 110 0 a:1 0 1 . 1 ... ... 0 111 10 ....... @vldst_wn \
68
+ p=0 w=1 size=2
69
+VLDSTH_W 111 . 110 1 a:1 0 w:1 . 1 ... ... 0 111 10 ....... @vldst_wn \
70
+ p=1 size=2
71
+
72
# Non-widening loads/stores (P=0 W=0 is 'related encoding')
73
VLDR_VSTR 1110110 0 a:1 . 1 . .... ... 111100 ....... @vldr_vstr \
74
size=0 p=0 w=1
75
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/mve_helper.c
78
+++ b/target/arm/mve_helper.c
79
@@ -XXX,XX +XXX,XX @@ DO_VSTR(vstrb, 1, stb, 1, uint8_t)
80
DO_VSTR(vstrh, 2, stw, 2, uint16_t)
81
DO_VSTR(vstrw, 4, stl, 4, uint32_t)
82
83
+DO_VLDR(vldrb_sh, 1, ldsb, 2, int16_t)
84
+DO_VLDR(vldrb_sw, 1, ldsb, 4, int32_t)
85
+DO_VLDR(vldrb_uh, 1, ldub, 2, uint16_t)
86
+DO_VLDR(vldrb_uw, 1, ldub, 4, uint32_t)
87
+DO_VLDR(vldrh_sw, 2, ldsw, 4, int32_t)
88
+DO_VLDR(vldrh_uw, 2, lduw, 4, uint32_t)
89
+
90
+DO_VSTR(vstrb_h, 1, stb, 2, int16_t)
91
+DO_VSTR(vstrb_w, 1, stb, 4, int32_t)
92
+DO_VSTR(vstrh_w, 2, stw, 4, int32_t)
93
+
94
#undef DO_VLDR
95
#undef DO_VSTR
96
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/target/arm/translate-mve.c
99
+++ b/target/arm/translate-mve.c
100
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDR_VSTR(DisasContext *s, arg_VLDR_VSTR *a)
101
};
102
return do_ldst(s, a, ldstfns[a->size][a->l]);
103
}
104
+
105
+#define DO_VLDST_WIDE_NARROW(OP, SLD, ULD, ST) \
106
+ static bool trans_##OP(DisasContext *s, arg_VLDR_VSTR *a) \
107
+ { \
108
+ static MVEGenLdStFn * const ldstfns[2][2] = { \
109
+ { gen_helper_mve_##ST, gen_helper_mve_##SLD }, \
110
+ { NULL, gen_helper_mve_##ULD }, \
111
+ }; \
112
+ return do_ldst(s, a, ldstfns[a->u][a->l]); \
113
+ }
114
+
115
+DO_VLDST_WIDE_NARROW(VLDSTB_H, vldrb_sh, vldrb_uh, vstrb_h)
116
+DO_VLDST_WIDE_NARROW(VLDSTB_W, vldrb_sw, vldrb_uw, vstrb_w)
117
+DO_VLDST_WIDE_NARROW(VLDSTH_W, vldrh_sw, vldrh_uw, vstrh_w)
118
--
119
2.20.1
120
121
diff view generated by jsdifflib
New patch
1
1
Implement the MVE VCLZ insn (and the necessary machinery
2
for MVE 1-input vector ops).
3
4
Note that for non-load instructions predication is always performed
5
at a byte level granularity regardless of element size (R_ZLSJ),
6
and so the masking logic here differs from that used in the VLDR
7
and VSTR helpers.
8
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20210617121628.20116-4-peter.maydell@linaro.org
12
---
13
target/arm/helper-mve.h | 4 ++
14
target/arm/mve.decode | 8 ++++
15
target/arm/mve_helper.c | 82 ++++++++++++++++++++++++++++++++++++++
16
target/arm/translate-mve.c | 38 ++++++++++++++++++
17
4 files changed, 132 insertions(+)
18
19
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper-mve.h
22
+++ b/target/arm/helper-mve.h
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vldrh_uw, TCG_CALL_NO_WG, void, env, ptr, i32)
24
DEF_HELPER_FLAGS_3(mve_vstrb_h, TCG_CALL_NO_WG, void, env, ptr, i32)
25
DEF_HELPER_FLAGS_3(mve_vstrb_w, TCG_CALL_NO_WG, void, env, ptr, i32)
26
DEF_HELPER_FLAGS_3(mve_vstrh_w, TCG_CALL_NO_WG, void, env, ptr, i32)
27
+
28
+DEF_HELPER_FLAGS_3(mve_vclzb, TCG_CALL_NO_WG, void, env, ptr, ptr)
29
+DEF_HELPER_FLAGS_3(mve_vclzh, TCG_CALL_NO_WG, void, env, ptr, ptr)
30
+DEF_HELPER_FLAGS_3(mve_vclzw, TCG_CALL_NO_WG, void, env, ptr, ptr)
31
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/mve.decode
34
+++ b/target/arm/mve.decode
35
@@ -XXX,XX +XXX,XX @@
36
#
37
38
%qd 22:1 13:3
39
+%qm 5:1 1:3
40
41
&vldr_vstr rn qd imm p a w size l u
42
+&1op qd qm size
43
44
@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
45
# Note that both Rn and Qd are 3 bits only (no D bit)
46
@vldst_wn ... u:1 ... . . . . l:1 . rn:3 qd:3 . ... .. imm:7 &vldr_vstr
47
48
+@1op .... .... .... size:2 .. .... .... .... .... &1op qd=%qd qm=%qm
49
+
50
# Vector loads and stores
51
52
# Widening loads and narrowing stores:
53
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111101 ....... @vldr_vstr \
54
size=1 p=1
55
VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111110 ....... @vldr_vstr \
56
size=2 p=1
57
+
58
+# Vector miscellaneous
59
+
60
+VCLZ 1111 1111 1 . 11 .. 00 ... 0 0100 11 . 0 ... 0 @1op
61
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/target/arm/mve_helper.c
64
+++ b/target/arm/mve_helper.c
65
@@ -XXX,XX +XXX,XX @@ DO_VSTR(vstrh_w, 2, stw, 4, int32_t)
66
67
#undef DO_VLDR
68
#undef DO_VSTR
69
+
70
+/*
71
+ * The mergemask(D, R, M) macro performs the operation "*D = R" but
72
+ * storing only the bytes which correspond to 1 bits in M,
73
+ * leaving other bytes in *D unchanged. We use _Generic
74
+ * to select the correct implementation based on the type of D.
75
+ */
76
+
77
+static void mergemask_ub(uint8_t *d, uint8_t r, uint16_t mask)
78
+{
79
+ if (mask & 1) {
80
+ *d = r;
81
+ }
82
+}
83
+
84
+static void mergemask_sb(int8_t *d, int8_t r, uint16_t mask)
85
+{
86
+ mergemask_ub((uint8_t *)d, r, mask);
87
+}
88
+
89
+static void mergemask_uh(uint16_t *d, uint16_t r, uint16_t mask)
90
+{
91
+ uint16_t bmask = expand_pred_b_data[mask & 3];
92
+ *d = (*d & ~bmask) | (r & bmask);
93
+}
94
+
95
+static void mergemask_sh(int16_t *d, int16_t r, uint16_t mask)
96
+{
97
+ mergemask_uh((uint16_t *)d, r, mask);
98
+}
99
+
100
+static void mergemask_uw(uint32_t *d, uint32_t r, uint16_t mask)
101
+{
102
+ uint32_t bmask = expand_pred_b_data[mask & 0xf];
103
+ *d = (*d & ~bmask) | (r & bmask);
104
+}
105
+
106
+static void mergemask_sw(int32_t *d, int32_t r, uint16_t mask)
107
+{
108
+ mergemask_uw((uint32_t *)d, r, mask);
109
+}
110
+
111
+static void mergemask_uq(uint64_t *d, uint64_t r, uint16_t mask)
112
+{
113
+ uint64_t bmask = expand_pred_b_data[mask & 0xff];
114
+ *d = (*d & ~bmask) | (r & bmask);
115
+}
116
+
117
+static void mergemask_sq(int64_t *d, int64_t r, uint16_t mask)
118
+{
119
+ mergemask_uq((uint64_t *)d, r, mask);
120
+}
121
+
122
+#define mergemask(D, R, M) \
123
+ _Generic(D, \
124
+ uint8_t *: mergemask_ub, \
125
+ int8_t *: mergemask_sb, \
126
+ uint16_t *: mergemask_uh, \
127
+ int16_t *: mergemask_sh, \
128
+ uint32_t *: mergemask_uw, \
129
+ int32_t *: mergemask_sw, \
130
+ uint64_t *: mergemask_uq, \
131
+ int64_t *: mergemask_sq)(D, R, M)
132
+
133
+#define DO_1OP(OP, ESIZE, TYPE, FN) \
134
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm) \
135
+ { \
136
+ TYPE *d = vd, *m = vm; \
137
+ uint16_t mask = mve_element_mask(env); \
138
+ unsigned e; \
139
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
140
+ mergemask(&d[H##ESIZE(e)], FN(m[H##ESIZE(e)]), mask); \
141
+ } \
142
+ mve_advance_vpt(env); \
143
+ }
144
+
145
+#define DO_CLZ_B(N) (clz32(N) - 24)
146
+#define DO_CLZ_H(N) (clz32(N) - 16)
147
+
148
+DO_1OP(vclzb, 1, uint8_t, DO_CLZ_B)
149
+DO_1OP(vclzh, 2, uint16_t, DO_CLZ_H)
150
+DO_1OP(vclzw, 4, uint32_t, clz32)
151
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
152
index XXXXXXX..XXXXXXX 100644
153
--- a/target/arm/translate-mve.c
154
+++ b/target/arm/translate-mve.c
155
@@ -XXX,XX +XXX,XX @@
156
#include "decode-mve.c.inc"
157
158
typedef void MVEGenLdStFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
159
+typedef void MVEGenOneOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
160
161
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
162
static inline long mve_qreg_offset(unsigned reg)
163
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDR_VSTR(DisasContext *s, arg_VLDR_VSTR *a)
164
DO_VLDST_WIDE_NARROW(VLDSTB_H, vldrb_sh, vldrb_uh, vstrb_h)
165
DO_VLDST_WIDE_NARROW(VLDSTB_W, vldrb_sw, vldrb_uw, vstrb_w)
166
DO_VLDST_WIDE_NARROW(VLDSTH_W, vldrh_sw, vldrh_uw, vstrh_w)
167
+
168
+static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
169
+{
170
+ TCGv_ptr qd, qm;
171
+
172
+ if (!dc_isar_feature(aa32_mve, s) ||
173
+ !mve_check_qreg_bank(s, a->qd | a->qm) ||
174
+ !fn) {
175
+ return false;
176
+ }
177
+
178
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
179
+ return true;
180
+ }
181
+
182
+ qd = mve_qreg_ptr(a->qd);
183
+ qm = mve_qreg_ptr(a->qm);
184
+ fn(cpu_env, qd, qm);
185
+ tcg_temp_free_ptr(qd);
186
+ tcg_temp_free_ptr(qm);
187
+ mve_update_eci(s);
188
+ return true;
189
+}
190
+
191
+#define DO_1OP(INSN, FN) \
192
+ static bool trans_##INSN(DisasContext *s, arg_1op *a) \
193
+ { \
194
+ static MVEGenOneOpFn * const fns[] = { \
195
+ gen_helper_mve_##FN##b, \
196
+ gen_helper_mve_##FN##h, \
197
+ gen_helper_mve_##FN##w, \
198
+ NULL, \
199
+ }; \
200
+ return do_1op(s, a, fns[a->size]); \
201
+ }
202
+
203
+DO_1OP(VCLZ, vclz)
204
--
205
2.20.1
206
207
diff view generated by jsdifflib
New patch
1
Implement the MVE VCLS insn.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-5-peter.maydell@linaro.org
6
---
7
target/arm/helper-mve.h | 4 ++++
8
target/arm/mve.decode | 1 +
9
target/arm/mve_helper.c | 7 +++++++
10
target/arm/translate-mve.c | 1 +
11
4 files changed, 13 insertions(+)
12
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
16
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vstrb_h, TCG_CALL_NO_WG, void, env, ptr, i32)
18
DEF_HELPER_FLAGS_3(mve_vstrb_w, TCG_CALL_NO_WG, void, env, ptr, i32)
19
DEF_HELPER_FLAGS_3(mve_vstrh_w, TCG_CALL_NO_WG, void, env, ptr, i32)
20
21
+DEF_HELPER_FLAGS_3(mve_vclsb, TCG_CALL_NO_WG, void, env, ptr, ptr)
22
+DEF_HELPER_FLAGS_3(mve_vclsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
23
+DEF_HELPER_FLAGS_3(mve_vclsw, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
+
25
DEF_HELPER_FLAGS_3(mve_vclzb, TCG_CALL_NO_WG, void, env, ptr, ptr)
26
DEF_HELPER_FLAGS_3(mve_vclzh, TCG_CALL_NO_WG, void, env, ptr, ptr)
27
DEF_HELPER_FLAGS_3(mve_vclzw, TCG_CALL_NO_WG, void, env, ptr, ptr)
28
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/mve.decode
31
+++ b/target/arm/mve.decode
32
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111110 ....... @vldr_vstr \
33
34
# Vector miscellaneous
35
36
+VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
37
VCLZ 1111 1111 1 . 11 .. 00 ... 0 0100 11 . 0 ... 0 @1op
38
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/mve_helper.c
41
+++ b/target/arm/mve_helper.c
42
@@ -XXX,XX +XXX,XX @@ static void mergemask_sq(int64_t *d, int64_t r, uint16_t mask)
43
mve_advance_vpt(env); \
44
}
45
46
+#define DO_CLS_B(N) (clrsb32(N) - 24)
47
+#define DO_CLS_H(N) (clrsb32(N) - 16)
48
+
49
+DO_1OP(vclsb, 1, int8_t, DO_CLS_B)
50
+DO_1OP(vclsh, 2, int16_t, DO_CLS_H)
51
+DO_1OP(vclsw, 4, int32_t, clrsb32)
52
+
53
#define DO_CLZ_B(N) (clz32(N) - 24)
54
#define DO_CLZ_H(N) (clz32(N) - 16)
55
56
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/translate-mve.c
59
+++ b/target/arm/translate-mve.c
60
@@ -XXX,XX +XXX,XX @@ static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
61
}
62
63
DO_1OP(VCLZ, vclz)
64
+DO_1OP(VCLS, vcls)
65
--
66
2.20.1
67
68
diff view generated by jsdifflib
New patch
1
Implement the MVE instructions VREV16, VREV32 and VREV64.
1
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-6-peter.maydell@linaro.org
6
---
7
target/arm/helper-mve.h | 7 +++++++
8
target/arm/mve.decode | 4 ++++
9
target/arm/mve_helper.c | 7 +++++++
10
target/arm/translate-mve.c | 33 +++++++++++++++++++++++++++++++++
11
4 files changed, 51 insertions(+)
12
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
16
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vclsw, TCG_CALL_NO_WG, void, env, ptr, ptr)
18
DEF_HELPER_FLAGS_3(mve_vclzb, TCG_CALL_NO_WG, void, env, ptr, ptr)
19
DEF_HELPER_FLAGS_3(mve_vclzh, TCG_CALL_NO_WG, void, env, ptr, ptr)
20
DEF_HELPER_FLAGS_3(mve_vclzw, TCG_CALL_NO_WG, void, env, ptr, ptr)
21
+
22
+DEF_HELPER_FLAGS_3(mve_vrev16b, TCG_CALL_NO_WG, void, env, ptr, ptr)
23
+DEF_HELPER_FLAGS_3(mve_vrev32b, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
+DEF_HELPER_FLAGS_3(mve_vrev32h, TCG_CALL_NO_WG, void, env, ptr, ptr)
25
+DEF_HELPER_FLAGS_3(mve_vrev64b, TCG_CALL_NO_WG, void, env, ptr, ptr)
26
+DEF_HELPER_FLAGS_3(mve_vrev64h, TCG_CALL_NO_WG, void, env, ptr, ptr)
27
+DEF_HELPER_FLAGS_3(mve_vrev64w, TCG_CALL_NO_WG, void, env, ptr, ptr)
28
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/mve.decode
31
+++ b/target/arm/mve.decode
32
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111110 ....... @vldr_vstr \
33
34
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
35
VCLZ 1111 1111 1 . 11 .. 00 ... 0 0100 11 . 0 ... 0 @1op
36
+
37
+VREV16 1111 1111 1 . 11 .. 00 ... 0 0001 01 . 0 ... 0 @1op
38
+VREV32 1111 1111 1 . 11 .. 00 ... 0 0000 11 . 0 ... 0 @1op
39
+VREV64 1111 1111 1 . 11 .. 00 ... 0 0000 01 . 0 ... 0 @1op
40
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/mve_helper.c
43
+++ b/target/arm/mve_helper.c
44
@@ -XXX,XX +XXX,XX @@ DO_1OP(vclsw, 4, int32_t, clrsb32)
45
DO_1OP(vclzb, 1, uint8_t, DO_CLZ_B)
46
DO_1OP(vclzh, 2, uint16_t, DO_CLZ_H)
47
DO_1OP(vclzw, 4, uint32_t, clz32)
48
+
49
+DO_1OP(vrev16b, 2, uint16_t, bswap16)
50
+DO_1OP(vrev32b, 4, uint32_t, bswap32)
51
+DO_1OP(vrev32h, 4, uint32_t, hswap32)
52
+DO_1OP(vrev64b, 8, uint64_t, bswap64)
53
+DO_1OP(vrev64h, 8, uint64_t, hswap64)
54
+DO_1OP(vrev64w, 8, uint64_t, wswap64)
55
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/translate-mve.c
58
+++ b/target/arm/translate-mve.c
59
@@ -XXX,XX +XXX,XX @@ static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
60
61
DO_1OP(VCLZ, vclz)
62
DO_1OP(VCLS, vcls)
63
+
64
+static bool trans_VREV16(DisasContext *s, arg_1op *a)
65
+{
66
+ static MVEGenOneOpFn * const fns[] = {
67
+ gen_helper_mve_vrev16b,
68
+ NULL,
69
+ NULL,
70
+ NULL,
71
+ };
72
+ return do_1op(s, a, fns[a->size]);
73
+}
74
+
75
+static bool trans_VREV32(DisasContext *s, arg_1op *a)
76
+{
77
+ static MVEGenOneOpFn * const fns[] = {
78
+ gen_helper_mve_vrev32b,
79
+ gen_helper_mve_vrev32h,
80
+ NULL,
81
+ NULL,
82
+ };
83
+ return do_1op(s, a, fns[a->size]);
84
+}
85
+
86
+static bool trans_VREV64(DisasContext *s, arg_1op *a)
87
+{
88
+ static MVEGenOneOpFn * const fns[] = {
89
+ gen_helper_mve_vrev64b,
90
+ gen_helper_mve_vrev64h,
91
+ gen_helper_mve_vrev64w,
92
+ NULL,
93
+ };
94
+ return do_1op(s, a, fns[a->size]);
95
+}
96
--
97
2.20.1
98
99
diff view generated by jsdifflib
1
Update old infocenter.arm.com URLs to the equivalent developer.arm.com
1
Implement the MVE VMVN(register) operation. Note that for
2
ones (the old URLs should redirect, but we might as well avoid the
2
predication this operation is byte-by-byte.
3
redirection notice, and the new URLs are pleasantly shorter).
4
5
This commit covers the links to the MPS2 board TRM, the various
6
Application Notes, the IoTKit and SSE-200 documents.
7
3
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210215115138.20465-25-peter.maydell@linaro.org
6
Message-id: 20210617121628.20116-7-peter.maydell@linaro.org
11
---
7
---
12
include/hw/arm/armsse.h | 4 ++--
8
target/arm/helper-mve.h | 2 ++
13
include/hw/misc/armsse-cpuid.h | 2 +-
9
target/arm/mve.decode | 3 +++
14
include/hw/misc/armsse-mhu.h | 2 +-
10
target/arm/mve_helper.c | 4 ++++
15
include/hw/misc/iotkit-secctl.h | 2 +-
11
target/arm/translate-mve.c | 5 +++++
16
include/hw/misc/iotkit-sysctl.h | 2 +-
12
4 files changed, 14 insertions(+)
17
include/hw/misc/iotkit-sysinfo.h | 2 +-
18
include/hw/misc/mps2-fpgaio.h | 2 +-
19
hw/arm/mps2-tz.c | 11 +++++------
20
hw/misc/armsse-cpuid.c | 2 +-
21
hw/misc/armsse-mhu.c | 2 +-
22
hw/misc/iotkit-sysctl.c | 2 +-
23
hw/misc/iotkit-sysinfo.c | 2 +-
24
hw/misc/mps2-fpgaio.c | 2 +-
25
hw/misc/mps2-scc.c | 2 +-
26
14 files changed, 19 insertions(+), 20 deletions(-)
27
13
28
diff --git a/include/hw/arm/armsse.h b/include/hw/arm/armsse.h
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
29
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
30
--- a/include/hw/arm/armsse.h
16
--- a/target/arm/helper-mve.h
31
+++ b/include/hw/arm/armsse.h
17
+++ b/target/arm/helper-mve.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vrev32h, TCG_CALL_NO_WG, void, env, ptr, ptr)
19
DEF_HELPER_FLAGS_3(mve_vrev64b, TCG_CALL_NO_WG, void, env, ptr, ptr)
20
DEF_HELPER_FLAGS_3(mve_vrev64h, TCG_CALL_NO_WG, void, env, ptr, ptr)
21
DEF_HELPER_FLAGS_3(mve_vrev64w, TCG_CALL_NO_WG, void, env, ptr, ptr)
22
+
23
+DEF_HELPER_FLAGS_3(mve_vmvn, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
25
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/mve.decode
27
+++ b/target/arm/mve.decode
32
@@ -XXX,XX +XXX,XX @@
28
@@ -XXX,XX +XXX,XX @@
33
* hardware, which include the IoT Kit and the SSE-050, SSE-100 and
29
@vldst_wn ... u:1 ... . . . . l:1 . rn:3 qd:3 . ... .. imm:7 &vldr_vstr
34
* SSE-200. Currently we model:
30
35
* - the Arm IoT Kit which is documented in
31
@1op .... .... .... size:2 .. .... .... .... .... &1op qd=%qd qm=%qm
36
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
32
+@1op_nosz .... .... .... .... .... .... .... .... &1op qd=%qd qm=%qm size=0
37
+ * https://developer.arm.com/documentation/ecm0601256/latest
33
38
* - the SSE-200 which is documented in
34
# Vector loads and stores
39
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
35
40
+ * https://developer.arm.com/documentation/101104/latest/
36
@@ -XXX,XX +XXX,XX @@ VCLZ 1111 1111 1 . 11 .. 00 ... 0 0100 11 . 0 ... 0 @1op
41
*
37
VREV16 1111 1111 1 . 11 .. 00 ... 0 0001 01 . 0 ... 0 @1op
42
* The IoTKit contains:
38
VREV32 1111 1111 1 . 11 .. 00 ... 0 0000 11 . 0 ... 0 @1op
43
* a Cortex-M33
39
VREV64 1111 1111 1 . 11 .. 00 ... 0 0000 01 . 0 ... 0 @1op
44
diff --git a/include/hw/misc/armsse-cpuid.h b/include/hw/misc/armsse-cpuid.h
40
+
41
+VMVN 1111 1111 1 . 11 00 00 ... 0 0101 11 . 0 ... 0 @1op_nosz
42
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
45
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
46
--- a/include/hw/misc/armsse-cpuid.h
44
--- a/target/arm/mve_helper.c
47
+++ b/include/hw/misc/armsse-cpuid.h
45
+++ b/target/arm/mve_helper.c
48
@@ -XXX,XX +XXX,XX @@
46
@@ -XXX,XX +XXX,XX @@ DO_1OP(vrev32h, 4, uint32_t, hswap32)
49
/*
47
DO_1OP(vrev64b, 8, uint64_t, bswap64)
50
* This is a model of the "CPU_IDENTITY" register block which is part of the
48
DO_1OP(vrev64h, 8, uint64_t, hswap64)
51
* Arm SSE-200 and documented in
49
DO_1OP(vrev64w, 8, uint64_t, wswap64)
52
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
50
+
53
+ * https://developer.arm.com/documentation/101104/latest/
51
+#define DO_NOT(N) (~(N))
54
*
52
+
55
* QEMU interface:
53
+DO_1OP(vmvn, 8, uint64_t, DO_NOT)
56
* + QOM property "CPUID": the value to use for the CPUID register
54
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
57
diff --git a/include/hw/misc/armsse-mhu.h b/include/hw/misc/armsse-mhu.h
58
index XXXXXXX..XXXXXXX 100644
55
index XXXXXXX..XXXXXXX 100644
59
--- a/include/hw/misc/armsse-mhu.h
56
--- a/target/arm/translate-mve.c
60
+++ b/include/hw/misc/armsse-mhu.h
57
+++ b/target/arm/translate-mve.c
61
@@ -XXX,XX +XXX,XX @@
58
@@ -XXX,XX +XXX,XX @@ static bool trans_VREV64(DisasContext *s, arg_1op *a)
62
/*
59
};
63
* This is a model of the Message Handling Unit (MHU) which is part of the
60
return do_1op(s, a, fns[a->size]);
64
* Arm SSE-200 and documented in
61
}
65
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
62
+
66
+ * https://developer.arm.com/documentation/101104/latest/
63
+static bool trans_VMVN(DisasContext *s, arg_1op *a)
67
*
64
+{
68
* QEMU interface:
65
+ return do_1op(s, a, gen_helper_mve_vmvn);
69
* + sysbus MMIO region 0: the system information register bank
66
+}
70
diff --git a/include/hw/misc/iotkit-secctl.h b/include/hw/misc/iotkit-secctl.h
71
index XXXXXXX..XXXXXXX 100644
72
--- a/include/hw/misc/iotkit-secctl.h
73
+++ b/include/hw/misc/iotkit-secctl.h
74
@@ -XXX,XX +XXX,XX @@
75
76
/* This is a model of the security controller which is part of the
77
* Arm IoT Kit and documented in
78
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
79
+ * https://developer.arm.com/documentation/ecm0601256/latest
80
*
81
* QEMU interface:
82
* + sysbus MMIO region 0 is the "secure privilege control block" registers
83
diff --git a/include/hw/misc/iotkit-sysctl.h b/include/hw/misc/iotkit-sysctl.h
84
index XXXXXXX..XXXXXXX 100644
85
--- a/include/hw/misc/iotkit-sysctl.h
86
+++ b/include/hw/misc/iotkit-sysctl.h
87
@@ -XXX,XX +XXX,XX @@
88
/*
89
* This is a model of the "system control element" which is part of the
90
* Arm IoTKit and documented in
91
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
92
+ * https://developer.arm.com/documentation/ecm0601256/latest
93
* Specifically, it implements the "system information block" and
94
* "system control register" blocks.
95
*
96
diff --git a/include/hw/misc/iotkit-sysinfo.h b/include/hw/misc/iotkit-sysinfo.h
97
index XXXXXXX..XXXXXXX 100644
98
--- a/include/hw/misc/iotkit-sysinfo.h
99
+++ b/include/hw/misc/iotkit-sysinfo.h
100
@@ -XXX,XX +XXX,XX @@
101
/*
102
* This is a model of the "system information block" which is part of the
103
* Arm IoTKit and documented in
104
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
105
+ * https://developer.arm.com/documentation/ecm0601256/latest
106
* QEMU interface:
107
* + QOM property "SYS_VERSION": value to use for SYS_VERSION register
108
* + QOM property "SYS_CONFIG": value to use for SYS_CONFIG register
109
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
110
index XXXXXXX..XXXXXXX 100644
111
--- a/include/hw/misc/mps2-fpgaio.h
112
+++ b/include/hw/misc/mps2-fpgaio.h
113
@@ -XXX,XX +XXX,XX @@
114
/* This is a model of the FPGAIO register block in the AN505
115
* FPGA image for the MPS2 dev board; it is documented in the
116
* application note:
117
- * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
118
+ * https://developer.arm.com/documentation/dai0505/latest/
119
*
120
* QEMU interface:
121
* + sysbus MMIO region 0: the register bank
122
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
123
index XXXXXXX..XXXXXXX 100644
124
--- a/hw/arm/mps2-tz.c
125
+++ b/hw/arm/mps2-tz.c
126
@@ -XXX,XX +XXX,XX @@
127
* https://developer.arm.com/products/system-design/development-boards/fpga-prototyping-boards/mps2
128
*
129
* Board TRM:
130
- * http://infocenter.arm.com/help/topic/com.arm.doc.100112_0200_06_en/versatile_express_cortex_m_prototyping_systems_v2m_mps2_and_v2m_mps2plus_technical_reference_100112_0200_06_en.pdf
131
+ * https://developer.arm.com/documentation/100112/latest/
132
* Application Note AN505:
133
- * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
134
+ * https://developer.arm.com/documentation/dai0505/latest/
135
* Application Note AN521:
136
- * http://infocenter.arm.com/help/topic/com.arm.doc.dai0521c/index.html
137
+ * https://developer.arm.com/documentation/dai0521/latest/
138
* Application Note AN524:
139
* https://developer.arm.com/documentation/dai0524/latest/
140
*
141
* The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
142
* (ARM ECM0601256) for the details of some of the device layout:
143
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
144
+ * https://developer.arm.com/documentation/ecm0601256/latest
145
* Similarly, the AN521 and AN524 use the SSE-200, and the SSE-200 TRM defines
146
* most of the device layout:
147
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
148
- *
149
+ * https://developer.arm.com/documentation/101104/latest/
150
*/
151
152
#include "qemu/osdep.h"
153
diff --git a/hw/misc/armsse-cpuid.c b/hw/misc/armsse-cpuid.c
154
index XXXXXXX..XXXXXXX 100644
155
--- a/hw/misc/armsse-cpuid.c
156
+++ b/hw/misc/armsse-cpuid.c
157
@@ -XXX,XX +XXX,XX @@
158
/*
159
* This is a model of the "CPU_IDENTITY" register block which is part of the
160
* Arm SSE-200 and documented in
161
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
162
+ * https://developer.arm.com/documentation/101104/latest/
163
*
164
* It consists of one read-only CPUID register (set by QOM property), plus the
165
* usual ID registers.
166
diff --git a/hw/misc/armsse-mhu.c b/hw/misc/armsse-mhu.c
167
index XXXXXXX..XXXXXXX 100644
168
--- a/hw/misc/armsse-mhu.c
169
+++ b/hw/misc/armsse-mhu.c
170
@@ -XXX,XX +XXX,XX @@
171
/*
172
* This is a model of the Message Handling Unit (MHU) which is part of the
173
* Arm SSE-200 and documented in
174
- * http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
175
+ * https://developer.arm.com/documentation/101104/latest/
176
*/
177
178
#include "qemu/osdep.h"
179
diff --git a/hw/misc/iotkit-sysctl.c b/hw/misc/iotkit-sysctl.c
180
index XXXXXXX..XXXXXXX 100644
181
--- a/hw/misc/iotkit-sysctl.c
182
+++ b/hw/misc/iotkit-sysctl.c
183
@@ -XXX,XX +XXX,XX @@
184
/*
185
* This is a model of the "system control element" which is part of the
186
* Arm IoTKit and documented in
187
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
188
+ * https://developer.arm.com/documentation/ecm0601256/latest
189
* Specifically, it implements the "system control register" blocks.
190
*/
191
192
diff --git a/hw/misc/iotkit-sysinfo.c b/hw/misc/iotkit-sysinfo.c
193
index XXXXXXX..XXXXXXX 100644
194
--- a/hw/misc/iotkit-sysinfo.c
195
+++ b/hw/misc/iotkit-sysinfo.c
196
@@ -XXX,XX +XXX,XX @@
197
/*
198
* This is a model of the "system information block" which is part of the
199
* Arm IoTKit and documented in
200
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
201
+ * https://developer.arm.com/documentation/ecm0601256/latest
202
* It consists of 2 read-only version/config registers, plus the
203
* usual ID registers.
204
*/
205
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
206
index XXXXXXX..XXXXXXX 100644
207
--- a/hw/misc/mps2-fpgaio.c
208
+++ b/hw/misc/mps2-fpgaio.c
209
@@ -XXX,XX +XXX,XX @@
210
/* This is a model of the "FPGA system control and I/O" block found
211
* in the AN505 FPGA image for the MPS2 devboard.
212
* It is documented in AN505:
213
- * http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
214
+ * https://developer.arm.com/documentation/dai0505/latest/
215
*/
216
217
#include "qemu/osdep.h"
218
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
219
index XXXXXXX..XXXXXXX 100644
220
--- a/hw/misc/mps2-scc.c
221
+++ b/hw/misc/mps2-scc.c
222
@@ -XXX,XX +XXX,XX @@
223
* found in the FPGA images of MPS2 development boards.
224
*
225
* Documentation of it can be found in the MPS2 TRM:
226
- * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.100112_0100_03_en/index.html
227
+ * https://developer.arm.com/documentation/100112/latest/
228
* and also in the Application Notes documenting individual FPGA images.
229
*/
230
231
--
67
--
232
2.20.1
68
2.20.1
233
69
234
70
diff view generated by jsdifflib
1
Add brief documentation of the new mps3-an524 board.
1
Implement the MVE VABS functions (both integer and floating point).
2
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210215115138.20465-24-peter.maydell@linaro.org
5
Message-id: 20210617121628.20116-8-peter.maydell@linaro.org
7
---
6
---
8
docs/system/arm/mps2.rst | 24 ++++++++++++++++++------
7
target/arm/helper-mve.h | 6 ++++++
9
1 file changed, 18 insertions(+), 6 deletions(-)
8
target/arm/mve.decode | 3 +++
9
target/arm/mve_helper.c | 13 +++++++++++++
10
target/arm/translate-mve.c | 15 +++++++++++++++
11
4 files changed, 37 insertions(+)
10
12
11
diff --git a/docs/system/arm/mps2.rst b/docs/system/arm/mps2.rst
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
12
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
13
--- a/docs/system/arm/mps2.rst
15
--- a/target/arm/helper-mve.h
14
+++ b/docs/system/arm/mps2.rst
16
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vrev64h, TCG_CALL_NO_WG, void, env, ptr, ptr)
18
DEF_HELPER_FLAGS_3(mve_vrev64w, TCG_CALL_NO_WG, void, env, ptr, ptr)
19
20
DEF_HELPER_FLAGS_3(mve_vmvn, TCG_CALL_NO_WG, void, env, ptr, ptr)
21
+
22
+DEF_HELPER_FLAGS_3(mve_vabsb, TCG_CALL_NO_WG, void, env, ptr, ptr)
23
+DEF_HELPER_FLAGS_3(mve_vabsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
+DEF_HELPER_FLAGS_3(mve_vabsw, TCG_CALL_NO_WG, void, env, ptr, ptr)
25
+DEF_HELPER_FLAGS_3(mve_vfabsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
26
+DEF_HELPER_FLAGS_3(mve_vfabss, TCG_CALL_NO_WG, void, env, ptr, ptr)
27
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/mve.decode
30
+++ b/target/arm/mve.decode
31
@@ -XXX,XX +XXX,XX @@ VREV32 1111 1111 1 . 11 .. 00 ... 0 0000 11 . 0 ... 0 @1op
32
VREV64 1111 1111 1 . 11 .. 00 ... 0 0000 01 . 0 ... 0 @1op
33
34
VMVN 1111 1111 1 . 11 00 00 ... 0 0101 11 . 0 ... 0 @1op_nosz
35
+
36
+VABS 1111 1111 1 . 11 .. 01 ... 0 0011 01 . 0 ... 0 @1op
37
+VABS_fp 1111 1111 1 . 11 .. 01 ... 0 0111 01 . 0 ... 0 @1op
38
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/mve_helper.c
41
+++ b/target/arm/mve_helper.c
15
@@ -XXX,XX +XXX,XX @@
42
@@ -XXX,XX +XXX,XX @@
16
-Arm MPS2 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``)
43
#include "exec/helper-proto.h"
17
-================================================================================================================
44
#include "exec/cpu_ldst.h"
18
+Arm MPS2 and MPS3 boards (``mps2-an385``, ``mps2-an386``, ``mps2-an500``, ``mps2-an505``, ``mps2-an511``, ``mps2-an521``, ``mps3-an524``)
45
#include "exec/exec-all.h"
19
+=========================================================================================================================================
46
+#include "tcg/tcg.h"
20
47
21
These board models all use Arm M-profile CPUs.
48
static uint16_t mve_element_mask(CPUARMState *env)
22
49
{
23
-The Arm MPS2 and MPS2+ dev boards are FPGA based (the 2+ has a bigger
50
@@ -XXX,XX +XXX,XX @@ DO_1OP(vrev64w, 8, uint64_t, wswap64)
24
-FPGA but is otherwise the same as the 2). Since the CPU itself
51
#define DO_NOT(N) (~(N))
25
-and most of the devices are in the FPGA, the details of the board
52
26
-as seen by the guest depend significantly on the FPGA image.
53
DO_1OP(vmvn, 8, uint64_t, DO_NOT)
27
+The Arm MPS2, MPS2+ and MPS3 dev boards are FPGA based (the 2+ has a
28
+bigger FPGA but is otherwise the same as the 2; the 3 has a bigger
29
+FPGA again, can handle 4GB of RAM and has a USB controller and QSPI flash).
30
+
54
+
31
+Since the CPU itself and most of the devices are in the FPGA, the
55
+#define DO_ABS(N) ((N) < 0 ? -(N) : (N))
32
+details of the board as seen by the guest depend significantly on the
56
+#define DO_FABSH(N) ((N) & dup_const(MO_16, 0x7fff))
33
+FPGA image.
57
+#define DO_FABSS(N) ((N) & dup_const(MO_32, 0x7fffffff))
34
58
+
35
QEMU models the following FPGA images:
59
+DO_1OP(vabsb, 1, int8_t, DO_ABS)
36
60
+DO_1OP(vabsh, 2, int16_t, DO_ABS)
37
@@ -XXX,XX +XXX,XX @@ QEMU models the following FPGA images:
61
+DO_1OP(vabsw, 4, int32_t, DO_ABS)
38
Cortex-M3 'DesignStart' as documented in Arm Application Note AN511
62
+
39
``mps2-an521``
63
+/* We can do these 64 bits at a time */
40
Dual Cortex-M33 as documented in Arm Application Note AN521
64
+DO_1OP(vfabsh, 8, uint64_t, DO_FABSH)
41
+``mps3-an524``
65
+DO_1OP(vfabss, 8, uint64_t, DO_FABSS)
42
+ Dual Cortex-M33 on an MPS3, as documented in Arm Application Note AN524
66
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
43
67
index XXXXXXX..XXXXXXX 100644
44
Differences between QEMU and real hardware:
68
--- a/target/arm/translate-mve.c
45
69
+++ b/target/arm/translate-mve.c
46
- AN385/AN386 remapping of low 16K of memory to either ZBT SSRAM1 or to
70
@@ -XXX,XX +XXX,XX @@ static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
47
block RAM is unimplemented (QEMU always maps this to ZBT SSRAM1, as
71
48
if zbt_boot_ctrl is always zero)
72
DO_1OP(VCLZ, vclz)
49
+- AN524 remapping of low memory to either BRAM or to QSPI flash is
73
DO_1OP(VCLS, vcls)
50
+ unimplemented (QEMU always maps this to BRAM, ignoring the
74
+DO_1OP(VABS, vabs)
51
+ SCC CFG_REG0 memory-remap bit)
75
52
- QEMU provides a LAN9118 ethernet rather than LAN9220; the only guest
76
static bool trans_VREV16(DisasContext *s, arg_1op *a)
53
visible difference is that the LAN9118 doesn't support checksum
77
{
54
offloading
78
@@ -XXX,XX +XXX,XX @@ static bool trans_VMVN(DisasContext *s, arg_1op *a)
55
+- QEMU does not model the QSPI flash in MPS3 boards as real QSPI
79
{
56
+ flash, but only as simple ROM, so attempting to rewrite the flash
80
return do_1op(s, a, gen_helper_mve_vmvn);
57
+ from the guest will fail
81
}
58
+- QEMU does not model the USB controller in MPS3 boards
82
+
83
+static bool trans_VABS_fp(DisasContext *s, arg_1op *a)
84
+{
85
+ static MVEGenOneOpFn * const fns[] = {
86
+ NULL,
87
+ gen_helper_mve_vfabsh,
88
+ gen_helper_mve_vfabss,
89
+ NULL,
90
+ };
91
+ if (!dc_isar_feature(aa32_mve_fp, s)) {
92
+ return false;
93
+ }
94
+ return do_1op(s, a, fns[a->size]);
95
+}
59
--
96
--
60
2.20.1
97
2.20.1
61
98
62
99
diff view generated by jsdifflib
1
We create an OR gate to wire together the overflow IRQs for all the
1
Implement the MVE VNEG insn (both integer and floating point forms).
2
UARTs on the board; this has to have twice the number of inputs as
3
there are UARTs, since each UART feeds it a TX overflow and an RX
4
overflow interrupt line. Replace the hardcoded '10' with a
5
calculation based on the size of the uart[] array in the
6
MPS2TZMachineState. (We rely on OR gate inputs that are never wired
7
up or asserted being treated as always-zero.)
8
2
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20210215115138.20465-15-peter.maydell@linaro.org
5
Message-id: 20210617121628.20116-9-peter.maydell@linaro.org
12
---
6
---
13
hw/arm/mps2-tz.c | 11 ++++++++---
7
target/arm/helper-mve.h | 6 ++++++
14
1 file changed, 8 insertions(+), 3 deletions(-)
8
target/arm/mve.decode | 2 ++
9
target/arm/mve_helper.c | 12 ++++++++++++
10
target/arm/translate-mve.c | 15 +++++++++++++++
11
4 files changed, 35 insertions(+)
15
12
16
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
17
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/arm/mps2-tz.c
15
--- a/target/arm/helper-mve.h
19
+++ b/hw/arm/mps2-tz.c
16
+++ b/target/arm/helper-mve.h
20
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vabsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
21
*/
18
DEF_HELPER_FLAGS_3(mve_vabsw, TCG_CALL_NO_WG, void, env, ptr, ptr)
22
memory_region_add_subregion(system_memory, 0x80000000, machine->ram);
19
DEF_HELPER_FLAGS_3(mve_vfabsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
23
20
DEF_HELPER_FLAGS_3(mve_vfabss, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
- /* The overflow IRQs for all UARTs are ORed together.
21
+
25
+ /*
22
+DEF_HELPER_FLAGS_3(mve_vnegb, TCG_CALL_NO_WG, void, env, ptr, ptr)
26
+ * The overflow IRQs for all UARTs are ORed together.
23
+DEF_HELPER_FLAGS_3(mve_vnegh, TCG_CALL_NO_WG, void, env, ptr, ptr)
27
* Tx, Rx and "combined" IRQs are sent to the NVIC separately.
24
+DEF_HELPER_FLAGS_3(mve_vnegw, TCG_CALL_NO_WG, void, env, ptr, ptr)
28
- * Create the OR gate for this.
25
+DEF_HELPER_FLAGS_3(mve_vfnegh, TCG_CALL_NO_WG, void, env, ptr, ptr)
29
+ * Create the OR gate for this: it has one input for the TX overflow
26
+DEF_HELPER_FLAGS_3(mve_vfnegs, TCG_CALL_NO_WG, void, env, ptr, ptr)
30
+ * and one for the RX overflow for each UART we might have.
27
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
31
+ * (If the board has fewer than the maximum possible number of UARTs
28
index XXXXXXX..XXXXXXX 100644
32
+ * those inputs are never wired up and are treated as always-zero.)
29
--- a/target/arm/mve.decode
33
*/
30
+++ b/target/arm/mve.decode
34
object_initialize_child(OBJECT(mms), "uart-irq-orgate",
31
@@ -XXX,XX +XXX,XX @@ VMVN 1111 1111 1 . 11 00 00 ... 0 0101 11 . 0 ... 0 @1op_nosz
35
&mms->uart_irq_orgate, TYPE_OR_IRQ);
32
36
- object_property_set_int(OBJECT(&mms->uart_irq_orgate), "num-lines", 10,
33
VABS 1111 1111 1 . 11 .. 01 ... 0 0011 01 . 0 ... 0 @1op
37
+ object_property_set_int(OBJECT(&mms->uart_irq_orgate), "num-lines",
34
VABS_fp 1111 1111 1 . 11 .. 01 ... 0 0111 01 . 0 ... 0 @1op
38
+ 2 * ARRAY_SIZE(mms->uart),
35
+VNEG 1111 1111 1 . 11 .. 01 ... 0 0011 11 . 0 ... 0 @1op
39
&error_fatal);
36
+VNEG_fp 1111 1111 1 . 11 .. 01 ... 0 0111 11 . 0 ... 0 @1op
40
qdev_realize(DEVICE(&mms->uart_irq_orgate), NULL, &error_fatal);
37
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
41
qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/mve_helper.c
40
+++ b/target/arm/mve_helper.c
41
@@ -XXX,XX +XXX,XX @@ DO_1OP(vabsw, 4, int32_t, DO_ABS)
42
/* We can do these 64 bits at a time */
43
DO_1OP(vfabsh, 8, uint64_t, DO_FABSH)
44
DO_1OP(vfabss, 8, uint64_t, DO_FABSS)
45
+
46
+#define DO_NEG(N) (-(N))
47
+#define DO_FNEGH(N) ((N) ^ dup_const(MO_16, 0x8000))
48
+#define DO_FNEGS(N) ((N) ^ dup_const(MO_32, 0x80000000))
49
+
50
+DO_1OP(vnegb, 1, int8_t, DO_NEG)
51
+DO_1OP(vnegh, 2, int16_t, DO_NEG)
52
+DO_1OP(vnegw, 4, int32_t, DO_NEG)
53
+
54
+/* We can do these 64 bits at a time */
55
+DO_1OP(vfnegh, 8, uint64_t, DO_FNEGH)
56
+DO_1OP(vfnegs, 8, uint64_t, DO_FNEGS)
57
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/target/arm/translate-mve.c
60
+++ b/target/arm/translate-mve.c
61
@@ -XXX,XX +XXX,XX @@ static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
62
DO_1OP(VCLZ, vclz)
63
DO_1OP(VCLS, vcls)
64
DO_1OP(VABS, vabs)
65
+DO_1OP(VNEG, vneg)
66
67
static bool trans_VREV16(DisasContext *s, arg_1op *a)
68
{
69
@@ -XXX,XX +XXX,XX @@ static bool trans_VABS_fp(DisasContext *s, arg_1op *a)
70
}
71
return do_1op(s, a, fns[a->size]);
72
}
73
+
74
+static bool trans_VNEG_fp(DisasContext *s, arg_1op *a)
75
+{
76
+ static MVEGenOneOpFn * const fns[] = {
77
+ NULL,
78
+ gen_helper_mve_vfnegh,
79
+ gen_helper_mve_vfnegs,
80
+ NULL,
81
+ };
82
+ if (!dc_isar_feature(aa32_mve_fp, s)) {
83
+ return false;
84
+ }
85
+ return do_1op(s, a, fns[a->size]);
86
+}
42
--
87
--
43
2.20.1
88
2.20.1
44
89
45
90
diff view generated by jsdifflib
1
The AN524 has a different SYSCLK frequency from the AN505 and AN521;
1
The Arm MVE VDUP implementation would like to be able to emit code to
2
make the SYSCLK frequency a field in the MPS2TZMachineClass rather
2
duplicate a byte or halfword value into an i32. We have code to do
3
than a compile-time constant so we can support the AN524.
3
this already in tcg-op-gvec.c, so all we need to do is make the
4
functions global.
4
5
6
For consistency with other functions made available to the frontends:
7
* we rename to tcg_gen_dup_*
8
* we expose both the _i32 and _i64 forms
9
* we provide the #define for a _tl form
10
11
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
14
Message-id: 20210617121628.20116-10-peter.maydell@linaro.org
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215115138.20465-2-peter.maydell@linaro.org
9
---
15
---
10
hw/arm/mps2-tz.c | 10 ++++++----
16
include/tcg/tcg-op.h | 8 ++++++++
11
1 file changed, 6 insertions(+), 4 deletions(-)
17
include/tcg/tcg.h | 1 -
18
tcg/tcg-op-gvec.c | 20 ++++++++++----------
19
3 files changed, 18 insertions(+), 11 deletions(-)
12
20
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
21
diff --git a/include/tcg/tcg-op.h b/include/tcg/tcg-op.h
14
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/mps2-tz.c
23
--- a/include/tcg/tcg-op.h
16
+++ b/hw/arm/mps2-tz.c
24
+++ b/include/tcg/tcg-op.h
17
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
25
@@ -XXX,XX +XXX,XX @@ void tcg_gen_umin_i32(TCGv_i32, TCGv_i32 arg1, TCGv_i32 arg2);
18
MachineClass parent;
26
void tcg_gen_umax_i32(TCGv_i32, TCGv_i32 arg1, TCGv_i32 arg2);
19
MPS2TZFPGAType fpga_type;
27
void tcg_gen_abs_i32(TCGv_i32, TCGv_i32);
20
uint32_t scc_id;
28
21
+ uint32_t sysclk_frq; /* Main SYSCLK frequency in Hz */
29
+/* Replicate a value of size @vece from @in to all the lanes in @out */
22
const char *armsse_type;
30
+void tcg_gen_dup_i32(unsigned vece, TCGv_i32 out, TCGv_i32 in);
23
};
31
+
24
32
static inline void tcg_gen_discard_i32(TCGv_i32 arg)
25
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
26
27
OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
28
29
-/* Main SYSCLK frequency in Hz */
30
-#define SYSCLK_FRQ 20000000
31
/* Slow 32Khz S32KCLK frequency in Hz */
32
#define S32KCLK_FRQ (32 * 1000)
33
34
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_unimp_dev(MPS2TZMachineState *mms,
35
static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
36
const char *name, hwaddr size)
37
{
33
{
38
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
34
tcg_gen_op1_i32(INDEX_op_discard, arg);
39
CMSDKAPBUART *uart = opaque;
35
@@ -XXX,XX +XXX,XX @@ void tcg_gen_umin_i64(TCGv_i64, TCGv_i64 arg1, TCGv_i64 arg2);
40
int i = uart - &mms->uart[0];
36
void tcg_gen_umax_i64(TCGv_i64, TCGv_i64 arg1, TCGv_i64 arg2);
41
int rxirqno = i * 2;
37
void tcg_gen_abs_i64(TCGv_i64, TCGv_i64);
42
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
38
43
39
+/* Replicate a value of size @vece from @in to all the lanes in @out */
44
object_initialize_child(OBJECT(mms), name, uart, TYPE_CMSDK_APB_UART);
40
+void tcg_gen_dup_i64(unsigned vece, TCGv_i64 out, TCGv_i64 in);
45
qdev_prop_set_chr(DEVICE(uart), "chardev", serial_hd(i));
41
+
46
- qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", SYSCLK_FRQ);
42
#if TCG_TARGET_REG_BITS == 64
47
+ qdev_prop_set_uint32(DEVICE(uart), "pclk-frq", mmc->sysclk_frq);
43
static inline void tcg_gen_discard_i64(TCGv_i64 arg)
48
sysbus_realize(SYS_BUS_DEVICE(uart), &error_fatal);
44
{
49
s = SYS_BUS_DEVICE(uart);
45
@@ -XXX,XX +XXX,XX @@ void tcg_gen_stl_vec(TCGv_vec r, TCGv_ptr base, TCGArg offset, TCGType t);
50
sysbus_connect_irq(s, 0, get_sse_irq_in(mms, txirqno));
46
#define tcg_gen_atomic_smax_fetch_tl tcg_gen_atomic_smax_fetch_i64
51
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
47
#define tcg_gen_atomic_umax_fetch_tl tcg_gen_atomic_umax_fetch_i64
52
48
#define tcg_gen_dup_tl_vec tcg_gen_dup_i64_vec
53
/* These clocks don't need migration because they are fixed-frequency */
49
+#define tcg_gen_dup_tl tcg_gen_dup_i64
54
mms->sysclk = clock_new(OBJECT(machine), "SYSCLK");
50
#else
55
- clock_set_hz(mms->sysclk, SYSCLK_FRQ);
51
#define tcg_gen_movi_tl tcg_gen_movi_i32
56
+ clock_set_hz(mms->sysclk, mmc->sysclk_frq);
52
#define tcg_gen_mov_tl tcg_gen_mov_i32
57
mms->s32kclk = clock_new(OBJECT(machine), "S32KCLK");
53
@@ -XXX,XX +XXX,XX @@ void tcg_gen_stl_vec(TCGv_vec r, TCGv_ptr base, TCGArg offset, TCGType t);
58
clock_set_hz(mms->s32kclk, S32KCLK_FRQ);
54
#define tcg_gen_atomic_smax_fetch_tl tcg_gen_atomic_smax_fetch_i32
59
55
#define tcg_gen_atomic_umax_fetch_tl tcg_gen_atomic_umax_fetch_i32
60
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
56
#define tcg_gen_dup_tl_vec tcg_gen_dup_i32_vec
61
mmc->fpga_type = FPGA_AN505;
57
+#define tcg_gen_dup_tl tcg_gen_dup_i32
62
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
58
#endif
63
mmc->scc_id = 0x41045050;
59
64
+ mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
60
#if UINTPTR_MAX == UINT32_MAX
65
mmc->armsse_type = TYPE_IOTKIT;
61
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
62
index XXXXXXX..XXXXXXX 100644
63
--- a/include/tcg/tcg.h
64
+++ b/include/tcg/tcg.h
65
@@ -XXX,XX +XXX,XX @@ uint64_t dup_const(unsigned vece, uint64_t c);
66
: (qemu_build_not_reached_always(), 0)) \
67
: dup_const(VECE, C))
68
69
-
70
/*
71
* Memory helpers that will be used by TCG generated code.
72
*/
73
diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c
74
index XXXXXXX..XXXXXXX 100644
75
--- a/tcg/tcg-op-gvec.c
76
+++ b/tcg/tcg-op-gvec.c
77
@@ -XXX,XX +XXX,XX @@ uint64_t (dup_const)(unsigned vece, uint64_t c)
66
}
78
}
67
79
68
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
80
/* Duplicate IN into OUT as per VECE. */
69
mmc->fpga_type = FPGA_AN521;
81
-static void gen_dup_i32(unsigned vece, TCGv_i32 out, TCGv_i32 in)
70
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
82
+void tcg_gen_dup_i32(unsigned vece, TCGv_i32 out, TCGv_i32 in)
71
mmc->scc_id = 0x41045210;
83
{
72
+ mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
84
switch (vece) {
73
mmc->armsse_type = TYPE_SSE200;
85
case MO_8:
86
@@ -XXX,XX +XXX,XX @@ static void gen_dup_i32(unsigned vece, TCGv_i32 out, TCGv_i32 in)
87
}
74
}
88
}
75
89
90
-static void gen_dup_i64(unsigned vece, TCGv_i64 out, TCGv_i64 in)
91
+void tcg_gen_dup_i64(unsigned vece, TCGv_i64 out, TCGv_i64 in)
92
{
93
switch (vece) {
94
case MO_8:
95
@@ -XXX,XX +XXX,XX @@ static void do_dup(unsigned vece, uint32_t dofs, uint32_t oprsz,
96
&& (vece != MO_32 || !check_size_impl(oprsz, 4))) {
97
t_64 = tcg_temp_new_i64();
98
tcg_gen_extu_i32_i64(t_64, in_32);
99
- gen_dup_i64(vece, t_64, t_64);
100
+ tcg_gen_dup_i64(vece, t_64, t_64);
101
} else {
102
t_32 = tcg_temp_new_i32();
103
- gen_dup_i32(vece, t_32, in_32);
104
+ tcg_gen_dup_i32(vece, t_32, in_32);
105
}
106
} else if (in_64) {
107
/* We are given a 64-bit variable input. */
108
t_64 = tcg_temp_new_i64();
109
- gen_dup_i64(vece, t_64, in_64);
110
+ tcg_gen_dup_i64(vece, t_64, in_64);
111
} else {
112
/* We are given a constant input. */
113
/* For 64-bit hosts, use 64-bit constants for "simple" constants
114
@@ -XXX,XX +XXX,XX @@ void tcg_gen_gvec_2s(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
115
} else if (g->fni8 && check_size_impl(oprsz, 8)) {
116
TCGv_i64 t64 = tcg_temp_new_i64();
117
118
- gen_dup_i64(g->vece, t64, c);
119
+ tcg_gen_dup_i64(g->vece, t64, c);
120
expand_2s_i64(dofs, aofs, oprsz, t64, g->scalar_first, g->fni8);
121
tcg_temp_free_i64(t64);
122
} else if (g->fni4 && check_size_impl(oprsz, 4)) {
123
TCGv_i32 t32 = tcg_temp_new_i32();
124
125
tcg_gen_extrl_i64_i32(t32, c);
126
- gen_dup_i32(g->vece, t32, t32);
127
+ tcg_gen_dup_i32(g->vece, t32, t32);
128
expand_2s_i32(dofs, aofs, oprsz, t32, g->scalar_first, g->fni4);
129
tcg_temp_free_i32(t32);
130
} else {
131
@@ -XXX,XX +XXX,XX @@ void tcg_gen_gvec_ands(unsigned vece, uint32_t dofs, uint32_t aofs,
132
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
133
{
134
TCGv_i64 tmp = tcg_temp_new_i64();
135
- gen_dup_i64(vece, tmp, c);
136
+ tcg_gen_dup_i64(vece, tmp, c);
137
tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ands);
138
tcg_temp_free_i64(tmp);
139
}
140
@@ -XXX,XX +XXX,XX @@ void tcg_gen_gvec_xors(unsigned vece, uint32_t dofs, uint32_t aofs,
141
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
142
{
143
TCGv_i64 tmp = tcg_temp_new_i64();
144
- gen_dup_i64(vece, tmp, c);
145
+ tcg_gen_dup_i64(vece, tmp, c);
146
tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_xors);
147
tcg_temp_free_i64(tmp);
148
}
149
@@ -XXX,XX +XXX,XX @@ void tcg_gen_gvec_ors(unsigned vece, uint32_t dofs, uint32_t aofs,
150
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
151
{
152
TCGv_i64 tmp = tcg_temp_new_i64();
153
- gen_dup_i64(vece, tmp, c);
154
+ tcg_gen_dup_i64(vece, tmp, c);
155
tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ors);
156
tcg_temp_free_i64(tmp);
157
}
76
--
158
--
77
2.20.1
159
2.20.1
78
160
79
161
diff view generated by jsdifflib
1
The AN524 has a USB controller (an ISP1763); we don't have a model of
1
Implement the MVE VDUP insn, which duplicates a value from
2
it but we should provide a stub "unimplemented-device" for it. This
2
a general-purpose register into every lane of a vector
3
is slightly complicated because the USB controller shares a PPC port
3
register (subject to predication).
4
with the ethernet controller.
5
6
Implement a make_* function which provides creates a container
7
MemoryRegion with both the ethernet controller and an
8
unimplemented-device stub for the USB controller.
9
4
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20210215115138.20465-22-peter.maydell@linaro.org
7
Message-id: 20210617121628.20116-11-peter.maydell@linaro.org
14
---
8
---
15
hw/arm/mps2-tz.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
9
target/arm/helper-mve.h | 2 ++
16
1 file changed, 47 insertions(+), 1 deletion(-)
10
target/arm/mve.decode | 10 ++++++++++
11
target/arm/mve_helper.c | 16 ++++++++++++++++
12
target/arm/translate-mve.c | 27 +++++++++++++++++++++++++++
13
4 files changed, 55 insertions(+)
17
14
18
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
15
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
19
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/arm/mps2-tz.c
17
--- a/target/arm/helper-mve.h
21
+++ b/hw/arm/mps2-tz.c
18
+++ b/target/arm/helper-mve.h
22
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vstrb_h, TCG_CALL_NO_WG, void, env, ptr, i32)
23
20
DEF_HELPER_FLAGS_3(mve_vstrb_w, TCG_CALL_NO_WG, void, env, ptr, i32)
24
ARMSSE iotkit;
21
DEF_HELPER_FLAGS_3(mve_vstrh_w, TCG_CALL_NO_WG, void, env, ptr, i32)
25
MemoryRegion ram[MPS2TZ_RAM_MAX];
22
26
+ MemoryRegion eth_usb_container;
23
+DEF_HELPER_FLAGS_3(mve_vdup, TCG_CALL_NO_WG, void, env, ptr, i32)
27
+
24
+
28
MPS2SCC scc;
25
DEF_HELPER_FLAGS_3(mve_vclsb, TCG_CALL_NO_WG, void, env, ptr, ptr)
29
MPS2FPGAIO fpgaio;
26
DEF_HELPER_FLAGS_3(mve_vclsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
30
TZPPC ppc[5];
27
DEF_HELPER_FLAGS_3(mve_vclsw, TCG_CALL_NO_WG, void, env, ptr, ptr)
31
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
28
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
32
UnimplementedDeviceState gfx;
29
index XXXXXXX..XXXXXXX 100644
33
UnimplementedDeviceState cldc;
30
--- a/target/arm/mve.decode
34
UnimplementedDeviceState rtc;
31
+++ b/target/arm/mve.decode
35
+ UnimplementedDeviceState usb;
32
@@ -XXX,XX +XXX,XX @@
36
PL080State dma[4];
33
37
TZMSC msc[4];
34
%qd 22:1 13:3
38
CMSDKAPBUART uart[6];
35
%qm 5:1 1:3
39
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
36
+%qn 7:1 17:3
40
return sysbus_mmio_get_region(s, 0);
37
41
}
38
&vldr_vstr rn qd imm p a w size l u
42
39
&1op qd qm size
43
+static MemoryRegion *make_eth_usb(MPS2TZMachineState *mms, void *opaque,
40
@@ -XXX,XX +XXX,XX @@ VABS 1111 1111 1 . 11 .. 01 ... 0 0011 01 . 0 ... 0 @1op
44
+ const char *name, hwaddr size,
41
VABS_fp 1111 1111 1 . 11 .. 01 ... 0 0111 01 . 0 ... 0 @1op
45
+ const int *irqs)
42
VNEG 1111 1111 1 . 11 .. 01 ... 0 0011 11 . 0 ... 0 @1op
43
VNEG_fp 1111 1111 1 . 11 .. 01 ... 0 0111 11 . 0 ... 0 @1op
44
+
45
+&vdup qd rt size
46
+# Qd is in the fields usually named Qn
47
+@vdup .... .... . . .. ... . rt:4 .... . . . . .... qd=%qn &vdup
48
+
49
+# B and E bits encode size, which we decode here to the usual size values
50
+VDUP 1110 1110 1 1 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=0
51
+VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 1 1 0000 @vdup size=1
52
+VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=2
53
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/mve_helper.c
56
+++ b/target/arm/mve_helper.c
57
@@ -XXX,XX +XXX,XX @@ static void mergemask_sq(int64_t *d, int64_t r, uint16_t mask)
58
uint64_t *: mergemask_uq, \
59
int64_t *: mergemask_sq)(D, R, M)
60
61
+void HELPER(mve_vdup)(CPUARMState *env, void *vd, uint32_t val)
46
+{
62
+{
47
+ /*
63
+ /*
48
+ * The AN524 makes the ethernet and USB share a PPC port.
64
+ * The generated code already replicated an 8 or 16 bit constant
49
+ * irqs[] is the ethernet IRQ.
65
+ * into the 32-bit value, so we only need to write the 32-bit
66
+ * value to all elements of the Qreg, allowing for predication.
50
+ */
67
+ */
51
+ SysBusDevice *s;
68
+ uint32_t *d = vd;
52
+ NICInfo *nd = &nd_table[0];
69
+ uint16_t mask = mve_element_mask(env);
53
+
70
+ unsigned e;
54
+ memory_region_init(&mms->eth_usb_container, OBJECT(mms),
71
+ for (e = 0; e < 16 / 4; e++, mask >>= 4) {
55
+ "mps2-tz-eth-usb-container", 0x200000);
72
+ mergemask(&d[H4(e)], val, mask);
56
+
73
+ }
57
+ /*
74
+ mve_advance_vpt(env);
58
+ * In hardware this is a LAN9220; the LAN9118 is software compatible
59
+ * except that it doesn't support the checksum-offload feature.
60
+ */
61
+ qemu_check_nic_model(nd, "lan9118");
62
+ mms->lan9118 = qdev_new(TYPE_LAN9118);
63
+ qdev_set_nic_properties(mms->lan9118, nd);
64
+
65
+ s = SYS_BUS_DEVICE(mms->lan9118);
66
+ sysbus_realize_and_unref(s, &error_fatal);
67
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, irqs[0]));
68
+
69
+ memory_region_add_subregion(&mms->eth_usb_container,
70
+ 0, sysbus_mmio_get_region(s, 0));
71
+
72
+ /* The USB OTG controller is an ISP1763; we don't have a model of it. */
73
+ object_initialize_child(OBJECT(mms), "usb-otg",
74
+ &mms->usb, TYPE_UNIMPLEMENTED_DEVICE);
75
+ qdev_prop_set_string(DEVICE(&mms->usb), "name", "usb-otg");
76
+ qdev_prop_set_uint64(DEVICE(&mms->usb), "size", 0x100000);
77
+ s = SYS_BUS_DEVICE(&mms->usb);
78
+ sysbus_realize(s, &error_fatal);
79
+
80
+ memory_region_add_subregion(&mms->eth_usb_container,
81
+ 0x100000, sysbus_mmio_get_region(s, 0));
82
+
83
+ return &mms->eth_usb_container;
84
+}
75
+}
85
+
76
+
86
static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
77
#define DO_1OP(OP, ESIZE, TYPE, FN) \
87
const char *name, hwaddr size,
78
void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm) \
88
const int *irqs)
79
{ \
89
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
80
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
90
{ "gpio1", make_unimp_dev, &mms->gpio[1], 0x41101000, 0x1000 },
81
index XXXXXXX..XXXXXXX 100644
91
{ "gpio2", make_unimp_dev, &mms->gpio[2], 0x41102000, 0x1000 },
82
--- a/target/arm/translate-mve.c
92
{ "gpio3", make_unimp_dev, &mms->gpio[3], 0x41103000, 0x1000 },
83
+++ b/target/arm/translate-mve.c
93
- { "eth", make_eth_dev, NULL, 0x41400000, 0x100000, { 48 } },
84
@@ -XXX,XX +XXX,XX @@ DO_VLDST_WIDE_NARROW(VLDSTB_H, vldrb_sh, vldrb_uh, vstrb_h)
94
+ { "eth-usb", make_eth_usb, NULL, 0x41400000, 0x200000, { 48 } },
85
DO_VLDST_WIDE_NARROW(VLDSTB_W, vldrb_sw, vldrb_uw, vstrb_w)
95
},
86
DO_VLDST_WIDE_NARROW(VLDSTH_W, vldrh_sw, vldrh_uw, vstrh_w)
96
},
87
97
};
88
+static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
89
+{
90
+ TCGv_ptr qd;
91
+ TCGv_i32 rt;
92
+
93
+ if (!dc_isar_feature(aa32_mve, s) ||
94
+ !mve_check_qreg_bank(s, a->qd)) {
95
+ return false;
96
+ }
97
+ if (a->rt == 13 || a->rt == 15) {
98
+ /* UNPREDICTABLE; we choose to UNDEF */
99
+ return false;
100
+ }
101
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
102
+ return true;
103
+ }
104
+
105
+ qd = mve_qreg_ptr(a->qd);
106
+ rt = load_reg(s, a->rt);
107
+ tcg_gen_dup_i32(a->size, rt, rt);
108
+ gen_helper_mve_vdup(cpu_env, qd, rt);
109
+ tcg_temp_free_ptr(qd);
110
+ tcg_temp_free_i32(rt);
111
+ mve_update_eci(s);
112
+ return true;
113
+}
114
+
115
static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
116
{
117
TCGv_ptr qd, qm;
98
--
118
--
99
2.20.1
119
2.20.1
100
120
101
121
diff view generated by jsdifflib
1
The AN524 version of the SCC interface has different behaviour for
1
Implement the MVE vector logical operations operating
2
some of the CFG registers; implement it.
2
on two registers.
3
4
Each board in this family can have minor differences in the meaning
5
of the CFG registers, so rather than trying to specify all the
6
possible semantics via individual device properties, we make the
7
behaviour conditional on the part-number field of the SCC_ID register
8
which the board code already passes us.
9
10
For the AN524, the differences are:
11
* CFG3 is reserved rather than being board switches
12
* CFG5 is a new register ("ACLK Frequency in Hz")
13
* CFG6 is a new register ("Clock divider for BRAM")
14
15
We implement both of the new registers as reads-as-written.
16
3
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
Message-id: 20210215115138.20465-11-peter.maydell@linaro.org
6
Message-id: 20210617121628.20116-12-peter.maydell@linaro.org
20
---
7
---
21
include/hw/misc/mps2-scc.h | 3 ++
8
target/arm/helper-mve.h | 6 ++++++
22
hw/misc/mps2-scc.c | 71 ++++++++++++++++++++++++++++++++++++--
9
target/arm/mve.decode | 9 +++++++++
23
2 files changed, 72 insertions(+), 2 deletions(-)
10
target/arm/mve_helper.c | 26 ++++++++++++++++++++++++++
11
target/arm/translate-mve.c | 37 +++++++++++++++++++++++++++++++++++++
12
4 files changed, 78 insertions(+)
24
13
25
diff --git a/include/hw/misc/mps2-scc.h b/include/hw/misc/mps2-scc.h
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
26
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
27
--- a/include/hw/misc/mps2-scc.h
16
--- a/target/arm/helper-mve.h
28
+++ b/include/hw/misc/mps2-scc.h
17
+++ b/target/arm/helper-mve.h
29
@@ -XXX,XX +XXX,XX @@ struct MPS2SCC {
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vnegh, TCG_CALL_NO_WG, void, env, ptr, ptr)
30
19
DEF_HELPER_FLAGS_3(mve_vnegw, TCG_CALL_NO_WG, void, env, ptr, ptr)
31
uint32_t cfg0;
20
DEF_HELPER_FLAGS_3(mve_vfnegh, TCG_CALL_NO_WG, void, env, ptr, ptr)
32
uint32_t cfg1;
21
DEF_HELPER_FLAGS_3(mve_vfnegs, TCG_CALL_NO_WG, void, env, ptr, ptr)
33
+ uint32_t cfg2;
22
+
34
uint32_t cfg4;
23
+DEF_HELPER_FLAGS_4(mve_vand, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
35
+ uint32_t cfg5;
24
+DEF_HELPER_FLAGS_4(mve_vbic, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
+ uint32_t cfg6;
25
+DEF_HELPER_FLAGS_4(mve_vorr, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
37
uint32_t cfgdata_rtn;
26
+DEF_HELPER_FLAGS_4(mve_vorn, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
38
uint32_t cfgdata_out;
27
+DEF_HELPER_FLAGS_4(mve_veor, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
39
uint32_t cfgctrl;
28
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
40
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
41
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/misc/mps2-scc.c
30
--- a/target/arm/mve.decode
43
+++ b/hw/misc/mps2-scc.c
31
+++ b/target/arm/mve.decode
44
@@ -XXX,XX +XXX,XX @@
32
@@ -XXX,XX +XXX,XX @@
45
33
46
REG32(CFG0, 0)
34
&vldr_vstr rn qd imm p a w size l u
47
REG32(CFG1, 4)
35
&1op qd qm size
48
+REG32(CFG2, 8)
36
+&2op qd qm qn size
49
REG32(CFG3, 0xc)
37
50
REG32(CFG4, 0x10)
38
@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
51
+REG32(CFG5, 0x14)
39
# Note that both Rn and Qd are 3 bits only (no D bit)
52
+REG32(CFG6, 0x18)
40
@@ -XXX,XX +XXX,XX @@
53
REG32(CFGDATA_RTN, 0xa0)
41
54
REG32(CFGDATA_OUT, 0xa4)
42
@1op .... .... .... size:2 .. .... .... .... .... &1op qd=%qd qm=%qm
55
REG32(CFGCTRL, 0xa8)
43
@1op_nosz .... .... .... .... .... .... .... .... &1op qd=%qd qm=%qm size=0
56
@@ -XXX,XX +XXX,XX @@ REG32(DLL, 0x100)
44
+@2op_nosz .... .... .... .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn size=0
57
REG32(AID, 0xFF8)
45
58
REG32(ID, 0xFFC)
46
# Vector loads and stores
59
47
60
+static int scc_partno(MPS2SCC *s)
48
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111101 ....... @vldr_vstr \
49
VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111110 ....... @vldr_vstr \
50
size=2 p=1
51
52
+# Vector 2-op
53
+VAND 1110 1111 0 . 00 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
54
+VBIC 1110 1111 0 . 01 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
55
+VORR 1110 1111 0 . 10 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
56
+VORN 1110 1111 0 . 11 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
57
+VEOR 1111 1111 0 . 00 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
58
+
59
# Vector miscellaneous
60
61
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
62
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/target/arm/mve_helper.c
65
+++ b/target/arm/mve_helper.c
66
@@ -XXX,XX +XXX,XX @@ DO_1OP(vnegw, 4, int32_t, DO_NEG)
67
/* We can do these 64 bits at a time */
68
DO_1OP(vfnegh, 8, uint64_t, DO_FNEGH)
69
DO_1OP(vfnegs, 8, uint64_t, DO_FNEGS)
70
+
71
+#define DO_2OP(OP, ESIZE, TYPE, FN) \
72
+ void HELPER(glue(mve_, OP))(CPUARMState *env, \
73
+ void *vd, void *vn, void *vm) \
74
+ { \
75
+ TYPE *d = vd, *n = vn, *m = vm; \
76
+ uint16_t mask = mve_element_mask(env); \
77
+ unsigned e; \
78
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
79
+ mergemask(&d[H##ESIZE(e)], \
80
+ FN(n[H##ESIZE(e)], m[H##ESIZE(e)]), mask); \
81
+ } \
82
+ mve_advance_vpt(env); \
83
+ }
84
+
85
+#define DO_AND(N, M) ((N) & (M))
86
+#define DO_BIC(N, M) ((N) & ~(M))
87
+#define DO_ORR(N, M) ((N) | (M))
88
+#define DO_ORN(N, M) ((N) | ~(M))
89
+#define DO_EOR(N, M) ((N) ^ (M))
90
+
91
+DO_2OP(vand, 8, uint64_t, DO_AND)
92
+DO_2OP(vbic, 8, uint64_t, DO_BIC)
93
+DO_2OP(vorr, 8, uint64_t, DO_ORR)
94
+DO_2OP(vorn, 8, uint64_t, DO_ORN)
95
+DO_2OP(veor, 8, uint64_t, DO_EOR)
96
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/target/arm/translate-mve.c
99
+++ b/target/arm/translate-mve.c
100
@@ -XXX,XX +XXX,XX @@
101
102
typedef void MVEGenLdStFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
103
typedef void MVEGenOneOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
104
+typedef void MVEGenTwoOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr);
105
106
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
107
static inline long mve_qreg_offset(unsigned reg)
108
@@ -XXX,XX +XXX,XX @@ static bool trans_VNEG_fp(DisasContext *s, arg_1op *a)
109
}
110
return do_1op(s, a, fns[a->size]);
111
}
112
+
113
+static bool do_2op(DisasContext *s, arg_2op *a, MVEGenTwoOpFn fn)
61
+{
114
+{
62
+ /* Return the partno field of the SCC_ID (0x524, 0x511, etc) */
115
+ TCGv_ptr qd, qn, qm;
63
+ return extract32(s->id, 4, 8);
116
+
117
+ if (!dc_isar_feature(aa32_mve, s) ||
118
+ !mve_check_qreg_bank(s, a->qd | a->qn | a->qm) ||
119
+ !fn) {
120
+ return false;
121
+ }
122
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
123
+ return true;
124
+ }
125
+
126
+ qd = mve_qreg_ptr(a->qd);
127
+ qn = mve_qreg_ptr(a->qn);
128
+ qm = mve_qreg_ptr(a->qm);
129
+ fn(cpu_env, qd, qn, qm);
130
+ tcg_temp_free_ptr(qd);
131
+ tcg_temp_free_ptr(qn);
132
+ tcg_temp_free_ptr(qm);
133
+ mve_update_eci(s);
134
+ return true;
64
+}
135
+}
65
+
136
+
66
/* Handle a write via the SYS_CFG channel to the specified function/device.
137
+#define DO_LOGIC(INSN, HELPER) \
67
* Return false on error (reported to guest via SYS_CFGCTRL ERROR bit).
138
+ static bool trans_##INSN(DisasContext *s, arg_2op *a) \
68
*/
139
+ { \
69
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
140
+ return do_2op(s, a, HELPER); \
70
case A_CFG1:
141
+ }
71
r = s->cfg1;
142
+
72
break;
143
+DO_LOGIC(VAND, gen_helper_mve_vand)
73
+ case A_CFG2:
144
+DO_LOGIC(VBIC, gen_helper_mve_vbic)
74
+ if (scc_partno(s) != 0x524) {
145
+DO_LOGIC(VORR, gen_helper_mve_vorr)
75
+ /* CFG2 reserved on other boards */
146
+DO_LOGIC(VORN, gen_helper_mve_vorn)
76
+ goto bad_offset;
147
+DO_LOGIC(VEOR, gen_helper_mve_veor)
77
+ }
78
+ r = s->cfg2;
79
+ break;
80
case A_CFG3:
81
+ if (scc_partno(s) == 0x524) {
82
+ /* CFG3 reserved on AN524 */
83
+ goto bad_offset;
84
+ }
85
/* These are user-settable DIP switches on the board. We don't
86
* model that, so just return zeroes.
87
*/
88
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
89
case A_CFG4:
90
r = s->cfg4;
91
break;
92
+ case A_CFG5:
93
+ if (scc_partno(s) != 0x524) {
94
+ /* CFG5 reserved on other boards */
95
+ goto bad_offset;
96
+ }
97
+ r = s->cfg5;
98
+ break;
99
+ case A_CFG6:
100
+ if (scc_partno(s) != 0x524) {
101
+ /* CFG6 reserved on other boards */
102
+ goto bad_offset;
103
+ }
104
+ r = s->cfg6;
105
+ break;
106
case A_CFGDATA_RTN:
107
r = s->cfgdata_rtn;
108
break;
109
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_scc_read(void *opaque, hwaddr offset, unsigned size)
110
r = s->id;
111
break;
112
default:
113
+ bad_offset:
114
qemu_log_mask(LOG_GUEST_ERROR,
115
"MPS2 SCC read: bad offset %x\n", (int) offset);
116
r = 0;
117
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
118
led_set_state(s->led[i], extract32(value, i, 1));
119
}
120
break;
121
+ case A_CFG2:
122
+ if (scc_partno(s) != 0x524) {
123
+ /* CFG2 reserved on other boards */
124
+ goto bad_offset;
125
+ }
126
+ /* AN524: QSPI Select signal */
127
+ s->cfg2 = value;
128
+ break;
129
+ case A_CFG5:
130
+ if (scc_partno(s) != 0x524) {
131
+ /* CFG5 reserved on other boards */
132
+ goto bad_offset;
133
+ }
134
+ /* AN524: ACLK frequency in Hz */
135
+ s->cfg5 = value;
136
+ break;
137
+ case A_CFG6:
138
+ if (scc_partno(s) != 0x524) {
139
+ /* CFG6 reserved on other boards */
140
+ goto bad_offset;
141
+ }
142
+ /* AN524: Clock divider for BRAM */
143
+ s->cfg6 = value;
144
+ break;
145
case A_CFGDATA_OUT:
146
s->cfgdata_out = value;
147
break;
148
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_write(void *opaque, hwaddr offset, uint64_t value,
149
s->dll = deposit32(s->dll, 24, 8, extract32(value, 24, 8));
150
break;
151
default:
152
+ bad_offset:
153
qemu_log_mask(LOG_GUEST_ERROR,
154
"MPS2 SCC write: bad offset 0x%x\n", (int) offset);
155
break;
156
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_reset(DeviceState *dev)
157
trace_mps2_scc_reset();
158
s->cfg0 = 0;
159
s->cfg1 = 0;
160
+ s->cfg2 = 0;
161
+ s->cfg5 = 0;
162
+ s->cfg6 = 0;
163
s->cfgdata_rtn = 0;
164
s->cfgdata_out = 0;
165
s->cfgctrl = 0x100000;
166
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_realize(DeviceState *dev, Error **errp)
167
168
static const VMStateDescription mps2_scc_vmstate = {
169
.name = "mps2-scc",
170
- .version_id = 2,
171
- .minimum_version_id = 2,
172
+ .version_id = 3,
173
+ .minimum_version_id = 3,
174
.fields = (VMStateField[]) {
175
VMSTATE_UINT32(cfg0, MPS2SCC),
176
VMSTATE_UINT32(cfg1, MPS2SCC),
177
+ VMSTATE_UINT32(cfg2, MPS2SCC),
178
+ /* cfg3, cfg4 are read-only so need not be migrated */
179
+ VMSTATE_UINT32(cfg5, MPS2SCC),
180
+ VMSTATE_UINT32(cfg6, MPS2SCC),
181
VMSTATE_UINT32(cfgdata_rtn, MPS2SCC),
182
VMSTATE_UINT32(cfgdata_out, MPS2SCC),
183
VMSTATE_UINT32(cfgctrl, MPS2SCC),
184
--
148
--
185
2.20.1
149
2.20.1
186
150
187
151
diff view generated by jsdifflib
1
The AN505 and AN521 don't have any read-only memory, but the AN524
1
Implement the MVE VADD, VSUB and VMUL insns.
2
does; add a flag to ROMInfo to mark a region as ROM.
3
2
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210215115138.20465-19-peter.maydell@linaro.org
5
Message-id: 20210617121628.20116-13-peter.maydell@linaro.org
7
---
6
---
8
hw/arm/mps2-tz.c | 6 ++++++
7
target/arm/helper-mve.h | 12 ++++++++++++
9
1 file changed, 6 insertions(+)
8
target/arm/mve.decode | 5 +++++
9
target/arm/mve_helper.c | 14 ++++++++++++++
10
target/arm/translate-mve.c | 16 ++++++++++++++++
11
4 files changed, 47 insertions(+)
10
12
11
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
12
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/arm/mps2-tz.c
15
--- a/target/arm/helper-mve.h
14
+++ b/hw/arm/mps2-tz.c
16
+++ b/target/arm/helper-mve.h
15
@@ -XXX,XX +XXX,XX @@ typedef struct RAMInfo {
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vbic, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
16
* Flag values:
18
DEF_HELPER_FLAGS_4(mve_vorr, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
17
* IS_ALIAS: this RAM area is an alias to the upstream end of the
19
DEF_HELPER_FLAGS_4(mve_vorn, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
18
* MPC specified by its .mpc value
20
DEF_HELPER_FLAGS_4(mve_veor, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
+ * IS_ROM: this RAM area is read-only
21
+
20
*/
22
+DEF_HELPER_FLAGS_4(mve_vaddb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
#define IS_ALIAS 1
23
+DEF_HELPER_FLAGS_4(mve_vaddh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
+#define IS_ROM 2
24
+DEF_HELPER_FLAGS_4(mve_vaddw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
25
+
24
struct MPS2TZMachineClass {
26
+DEF_HELPER_FLAGS_4(mve_vsubb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
MachineClass parent;
27
+DEF_HELPER_FLAGS_4(mve_vsubh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *mr_for_raminfo(MPS2TZMachineState *mms,
28
+DEF_HELPER_FLAGS_4(mve_vsubw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
if (raminfo->mrindex < 0) {
29
+
28
/* Means this RAMInfo is for QEMU's "system memory" */
30
+DEF_HELPER_FLAGS_4(mve_vmulb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
MachineState *machine = MACHINE(mms);
31
+DEF_HELPER_FLAGS_4(mve_vmulh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
+ assert(!(raminfo->flags & IS_ROM));
32
+DEF_HELPER_FLAGS_4(mve_vmulw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
return machine->ram;
33
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/mve.decode
36
+++ b/target/arm/mve.decode
37
@@ -XXX,XX +XXX,XX @@
38
39
@1op .... .... .... size:2 .. .... .... .... .... &1op qd=%qd qm=%qm
40
@1op_nosz .... .... .... .... .... .... .... .... &1op qd=%qd qm=%qm size=0
41
+@2op .... .... .. size:2 .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn
42
@2op_nosz .... .... .... .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn size=0
43
44
# Vector loads and stores
45
@@ -XXX,XX +XXX,XX @@ VORR 1110 1111 0 . 10 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
46
VORN 1110 1111 0 . 11 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
47
VEOR 1111 1111 0 . 00 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
48
49
+VADD 1110 1111 0 . .. ... 0 ... 0 1000 . 1 . 0 ... 0 @2op
50
+VSUB 1111 1111 0 . .. ... 0 ... 0 1000 . 1 . 0 ... 0 @2op
51
+VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
52
+
53
# Vector miscellaneous
54
55
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
56
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/mve_helper.c
59
+++ b/target/arm/mve_helper.c
60
@@ -XXX,XX +XXX,XX @@ DO_1OP(vfnegs, 8, uint64_t, DO_FNEGS)
61
mve_advance_vpt(env); \
32
}
62
}
33
63
34
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *mr_for_raminfo(MPS2TZMachineState *mms,
64
+/* provide unsigned 2-op helpers for all sizes */
35
65
+#define DO_2OP_U(OP, FN) \
36
memory_region_init_ram(ram, NULL, raminfo->name,
66
+ DO_2OP(OP##b, 1, uint8_t, FN) \
37
raminfo->size, &error_fatal);
67
+ DO_2OP(OP##h, 2, uint16_t, FN) \
38
+ if (raminfo->flags & IS_ROM) {
68
+ DO_2OP(OP##w, 4, uint32_t, FN)
39
+ memory_region_set_readonly(ram, true);
69
+
70
#define DO_AND(N, M) ((N) & (M))
71
#define DO_BIC(N, M) ((N) & ~(M))
72
#define DO_ORR(N, M) ((N) | (M))
73
@@ -XXX,XX +XXX,XX @@ DO_2OP(vbic, 8, uint64_t, DO_BIC)
74
DO_2OP(vorr, 8, uint64_t, DO_ORR)
75
DO_2OP(vorn, 8, uint64_t, DO_ORN)
76
DO_2OP(veor, 8, uint64_t, DO_EOR)
77
+
78
+#define DO_ADD(N, M) ((N) + (M))
79
+#define DO_SUB(N, M) ((N) - (M))
80
+#define DO_MUL(N, M) ((N) * (M))
81
+
82
+DO_2OP_U(vadd, DO_ADD)
83
+DO_2OP_U(vsub, DO_SUB)
84
+DO_2OP_U(vmul, DO_MUL)
85
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/target/arm/translate-mve.c
88
+++ b/target/arm/translate-mve.c
89
@@ -XXX,XX +XXX,XX @@ DO_LOGIC(VBIC, gen_helper_mve_vbic)
90
DO_LOGIC(VORR, gen_helper_mve_vorr)
91
DO_LOGIC(VORN, gen_helper_mve_vorn)
92
DO_LOGIC(VEOR, gen_helper_mve_veor)
93
+
94
+#define DO_2OP(INSN, FN) \
95
+ static bool trans_##INSN(DisasContext *s, arg_2op *a) \
96
+ { \
97
+ static MVEGenTwoOpFn * const fns[] = { \
98
+ gen_helper_mve_##FN##b, \
99
+ gen_helper_mve_##FN##h, \
100
+ gen_helper_mve_##FN##w, \
101
+ NULL, \
102
+ }; \
103
+ return do_2op(s, a, fns[a->size]); \
40
+ }
104
+ }
41
return ram;
105
+
42
}
106
+DO_2OP(VADD, vadd)
43
107
+DO_2OP(VSUB, vsub)
108
+DO_2OP(VMUL, vmul)
44
--
109
--
45
2.20.1
110
2.20.1
46
111
47
112
diff view generated by jsdifflib
1
The AN524 has a PL031 RTC, which we have a model of; provide it
1
Implement the MVE VMULH insn, which performs a vector
2
rather than an unimplemented-device stub.
2
multiply and returns the high half of the result.
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: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210215115138.20465-23-peter.maydell@linaro.org
6
Message-id: 20210617121628.20116-14-peter.maydell@linaro.org
8
---
7
---
9
hw/arm/mps2-tz.c | 22 ++++++++++++++++++++--
8
target/arm/helper-mve.h | 7 +++++++
10
1 file changed, 20 insertions(+), 2 deletions(-)
9
target/arm/mve.decode | 3 +++
10
target/arm/mve_helper.c | 26 ++++++++++++++++++++++++++
11
target/arm/translate-mve.c | 2 ++
12
4 files changed, 38 insertions(+)
11
13
12
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/mps2-tz.c
16
--- a/target/arm/helper-mve.h
15
+++ b/hw/arm/mps2-tz.c
17
+++ b/target/arm/helper-mve.h
16
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vsubw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
17
#include "hw/misc/tz-msc.h"
19
DEF_HELPER_FLAGS_4(mve_vmulb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
18
#include "hw/arm/armsse.h"
20
DEF_HELPER_FLAGS_4(mve_vmulh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
#include "hw/dma/pl080.h"
21
DEF_HELPER_FLAGS_4(mve_vmulw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
+#include "hw/rtc/pl031.h"
22
+
21
#include "hw/ssi/pl022.h"
23
+DEF_HELPER_FLAGS_4(mve_vmulhsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
#include "hw/i2c/arm_sbcon_i2c.h"
24
+DEF_HELPER_FLAGS_4(mve_vmulhsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
#include "hw/net/lan9118.h"
25
+DEF_HELPER_FLAGS_4(mve_vmulhsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
26
+DEF_HELPER_FLAGS_4(mve_vmulhub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
UnimplementedDeviceState gpio[4];
27
+DEF_HELPER_FLAGS_4(mve_vmulhuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
UnimplementedDeviceState gfx;
28
+DEF_HELPER_FLAGS_4(mve_vmulhuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
UnimplementedDeviceState cldc;
29
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
28
- UnimplementedDeviceState rtc;
30
index XXXXXXX..XXXXXXX 100644
29
UnimplementedDeviceState usb;
31
--- a/target/arm/mve.decode
30
+ PL031State rtc;
32
+++ b/target/arm/mve.decode
31
PL080State dma[4];
33
@@ -XXX,XX +XXX,XX @@ VADD 1110 1111 0 . .. ... 0 ... 0 1000 . 1 . 0 ... 0 @2op
32
TZMSC msc[4];
34
VSUB 1111 1111 0 . .. ... 0 ... 0 1000 . 1 . 0 ... 0 @2op
33
CMSDKAPBUART uart[6];
35
VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
34
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
36
35
return sysbus_mmio_get_region(s, 0);
37
+VMULH_S 111 0 1110 0 . .. ...1 ... 0 1110 . 0 . 0 ... 1 @2op
36
}
38
+VMULH_U 111 1 1110 0 . .. ...1 ... 0 1110 . 0 . 0 ... 1 @2op
37
39
+
38
+static MemoryRegion *make_rtc(MPS2TZMachineState *mms, void *opaque,
40
# Vector miscellaneous
39
+ const char *name, hwaddr size,
41
40
+ const int *irqs)
42
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
43
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/mve_helper.c
46
+++ b/target/arm/mve_helper.c
47
@@ -XXX,XX +XXX,XX @@ DO_2OP(veor, 8, uint64_t, DO_EOR)
48
DO_2OP_U(vadd, DO_ADD)
49
DO_2OP_U(vsub, DO_SUB)
50
DO_2OP_U(vmul, DO_MUL)
51
+
52
+/*
53
+ * Because the computation type is at least twice as large as required,
54
+ * these work for both signed and unsigned source types.
55
+ */
56
+static inline uint8_t do_mulh_b(int32_t n, int32_t m)
41
+{
57
+{
42
+ PL031State *pl031 = opaque;
58
+ return (n * m) >> 8;
43
+ SysBusDevice *s;
44
+
45
+ object_initialize_child(OBJECT(mms), name, pl031, TYPE_PL031);
46
+ s = SYS_BUS_DEVICE(pl031);
47
+ sysbus_realize(s, &error_fatal);
48
+ /*
49
+ * The board docs don't give an IRQ number for the PL031, so
50
+ * presumably it is not connected.
51
+ */
52
+ return sysbus_mmio_get_region(s, 0);
53
+}
59
+}
54
+
60
+
55
static void create_non_mpc_ram(MPS2TZMachineState *mms)
61
+static inline uint16_t do_mulh_h(int32_t n, int32_t m)
56
{
62
+{
57
/*
63
+ return (n * m) >> 16;
58
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
64
+}
59
65
+
60
{ /* port 9 reserved */ },
66
+static inline uint32_t do_mulh_w(int64_t n, int64_t m)
61
{ "clcd", make_unimp_dev, &mms->cldc, 0x4130a000, 0x1000 },
67
+{
62
- { "rtc", make_unimp_dev, &mms->rtc, 0x4130b000, 0x1000 },
68
+ return (n * m) >> 32;
63
+ { "rtc", make_rtc, &mms->rtc, 0x4130b000, 0x1000 },
69
+}
64
},
70
+
65
}, {
71
+DO_2OP(vmulhsb, 1, int8_t, do_mulh_b)
66
.name = "ahb_ppcexp0",
72
+DO_2OP(vmulhsh, 2, int16_t, do_mulh_h)
73
+DO_2OP(vmulhsw, 4, int32_t, do_mulh_w)
74
+DO_2OP(vmulhub, 1, uint8_t, do_mulh_b)
75
+DO_2OP(vmulhuh, 2, uint16_t, do_mulh_h)
76
+DO_2OP(vmulhuw, 4, uint32_t, do_mulh_w)
77
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/target/arm/translate-mve.c
80
+++ b/target/arm/translate-mve.c
81
@@ -XXX,XX +XXX,XX @@ DO_LOGIC(VEOR, gen_helper_mve_veor)
82
DO_2OP(VADD, vadd)
83
DO_2OP(VSUB, vsub)
84
DO_2OP(VMUL, vmul)
85
+DO_2OP(VMULH_S, vmulhs)
86
+DO_2OP(VMULH_U, vmulhu)
67
--
87
--
68
2.20.1
88
2.20.1
69
89
70
90
diff view generated by jsdifflib
1
Add support for the mps3-an524 board; this is an SSE-200 based FPGA
1
Implement the MVE VRMULH insn, which performs a rounding multiply
2
image, like the existing mps2-an521. It has a usefully larger amount
2
and then returns the high half.
3
of RAM, and a PL031 RTC, as well as some more minor differences.
4
5
In real hardware this image runs on a newer generation of the FPGA
6
board, the MPS3 rather than the older MPS2. Architecturally the two
7
boards are similar, so we implement the MPS3 boards in the mps2-tz.c
8
file as variations of the existing MPS2 boards.
9
3
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210215115138.20465-21-peter.maydell@linaro.org
6
Message-id: 20210617121628.20116-15-peter.maydell@linaro.org
13
---
7
---
14
hw/arm/mps2-tz.c | 139 +++++++++++++++++++++++++++++++++++++++++++++--
8
target/arm/helper-mve.h | 7 +++++++
15
1 file changed, 135 insertions(+), 4 deletions(-)
9
target/arm/mve.decode | 3 +++
10
target/arm/mve_helper.c | 22 ++++++++++++++++++++++
11
target/arm/translate-mve.c | 2 ++
12
4 files changed, 34 insertions(+)
16
13
17
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/hw/arm/mps2-tz.c
16
--- a/target/arm/helper-mve.h
20
+++ b/hw/arm/mps2-tz.c
17
+++ b/target/arm/helper-mve.h
21
@@ -XXX,XX +XXX,XX @@
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmulhsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
* This source file covers the following FPGA images, for TrustZone cores:
19
DEF_HELPER_FLAGS_4(mve_vmulhub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
* "mps2-an505" -- Cortex-M33 as documented in ARM Application Note AN505
20
DEF_HELPER_FLAGS_4(mve_vmulhuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
* "mps2-an521" -- Dual Cortex-M33 as documented in Application Note AN521
21
DEF_HELPER_FLAGS_4(mve_vmulhuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+ * "mps2-an524" -- Dual Cortex-M33 as documented in Application Note AN524
26
*
27
* Links to the TRM for the board itself and to the various Application
28
* Notes which document the FPGA images can be found here:
29
@@ -XXX,XX +XXX,XX @@
30
* http://infocenter.arm.com/help/topic/com.arm.doc.dai0505b/index.html
31
* Application Note AN521:
32
* http://infocenter.arm.com/help/topic/com.arm.doc.dai0521c/index.html
33
+ * Application Note AN524:
34
+ * https://developer.arm.com/documentation/dai0524/latest/
35
*
36
* The AN505 defers to the Cortex-M33 processor ARMv8M IoT Kit FVP User Guide
37
* (ARM ECM0601256) for the details of some of the device layout:
38
* http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ecm0601256/index.html
39
- * Similarly, the AN521 uses the SSE-200, and the SSE-200 TRM defines
40
+ * Similarly, the AN521 and AN524 use the SSE-200, and the SSE-200 TRM defines
41
* most of the device layout:
42
* http://infocenter.arm.com/help/topic/com.arm.doc.101104_0100_00_en/corelink_sse200_subsystem_for_embedded_technical_reference_manual_101104_0100_00_en.pdf
43
*
44
@@ -XXX,XX +XXX,XX @@
45
#include "hw/qdev-clock.h"
46
#include "qom/object.h"
47
48
-#define MPS2TZ_NUMIRQ_MAX 92
49
+#define MPS2TZ_NUMIRQ_MAX 95
50
#define MPS2TZ_RAM_MAX 4
51
52
typedef enum MPS2TZFPGAType {
53
FPGA_AN505,
54
FPGA_AN521,
55
+ FPGA_AN524,
56
} MPS2TZFPGAType;
57
58
/*
59
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
60
TZPPC ppc[5];
61
TZMPC mpc[3];
62
PL022State spi[5];
63
- ArmSbconI2CState i2c[4];
64
+ ArmSbconI2CState i2c[5];
65
UnimplementedDeviceState i2s_audio;
66
UnimplementedDeviceState gpio[4];
67
UnimplementedDeviceState gfx;
68
+ UnimplementedDeviceState cldc;
69
+ UnimplementedDeviceState rtc;
70
PL080State dma[4];
71
TZMSC msc[4];
72
- CMSDKAPBUART uart[5];
73
+ CMSDKAPBUART uart[6];
74
SplitIRQ sec_resp_splitter;
75
qemu_or_irq uart_irq_orgate;
76
DeviceState *lan9118;
77
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
78
#define TYPE_MPS2TZ_MACHINE "mps2tz"
79
#define TYPE_MPS2TZ_AN505_MACHINE MACHINE_TYPE_NAME("mps2-an505")
80
#define TYPE_MPS2TZ_AN521_MACHINE MACHINE_TYPE_NAME("mps2-an521")
81
+#define TYPE_MPS3TZ_AN524_MACHINE MACHINE_TYPE_NAME("mps3-an524")
82
83
OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
84
85
@@ -XXX,XX +XXX,XX @@ static const uint32_t an505_oscclk[] = {
86
25000000,
87
};
88
89
+static const uint32_t an524_oscclk[] = {
90
+ 24000000,
91
+ 32000000,
92
+ 50000000,
93
+ 50000000,
94
+ 24576000,
95
+ 23750000,
96
+};
97
+
22
+
98
static const RAMInfo an505_raminfo[] = { {
23
+DEF_HELPER_FLAGS_4(mve_vrmulhsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
99
.name = "ssram-0",
24
+DEF_HELPER_FLAGS_4(mve_vrmulhsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
100
.base = 0x00000000,
25
+DEF_HELPER_FLAGS_4(mve_vrmulhsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
101
@@ -XXX,XX +XXX,XX @@ static const RAMInfo an505_raminfo[] = { {
26
+DEF_HELPER_FLAGS_4(mve_vrmulhub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
102
},
27
+DEF_HELPER_FLAGS_4(mve_vrmulhuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
103
};
28
+DEF_HELPER_FLAGS_4(mve_vrmulhuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
104
29
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
105
+static const RAMInfo an524_raminfo[] = { {
30
index XXXXXXX..XXXXXXX 100644
106
+ .name = "bram",
31
--- a/target/arm/mve.decode
107
+ .base = 0x00000000,
32
+++ b/target/arm/mve.decode
108
+ .size = 512 * KiB,
33
@@ -XXX,XX +XXX,XX @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
109
+ .mpc = 0,
34
VMULH_S 111 0 1110 0 . .. ...1 ... 0 1110 . 0 . 0 ... 1 @2op
110
+ .mrindex = 0,
35
VMULH_U 111 1 1110 0 . .. ...1 ... 0 1110 . 0 . 0 ... 1 @2op
111
+ }, {
36
112
+ .name = "sram",
37
+VRMULH_S 111 0 1110 0 . .. ...1 ... 1 1110 . 0 . 0 ... 1 @2op
113
+ .base = 0x20000000,
38
+VRMULH_U 111 1 1110 0 . .. ...1 ... 1 1110 . 0 . 0 ... 1 @2op
114
+ .size = 32 * 4 * KiB,
115
+ .mpc = 1,
116
+ .mrindex = 1,
117
+ }, {
118
+ /* We don't model QSPI flash yet; for now expose it as simple ROM */
119
+ .name = "QSPI",
120
+ .base = 0x28000000,
121
+ .size = 8 * MiB,
122
+ .mpc = 1,
123
+ .mrindex = 2,
124
+ .flags = IS_ROM,
125
+ }, {
126
+ .name = "DDR",
127
+ .base = 0x60000000,
128
+ .size = 2 * GiB,
129
+ .mpc = 2,
130
+ .mrindex = -1,
131
+ }, {
132
+ .name = NULL,
133
+ },
134
+};
135
+
39
+
136
static const RAMInfo *find_raminfo_for_mpc(MPS2TZMachineState *mms, int mpc)
40
# Vector miscellaneous
137
{
41
138
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
42
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
139
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
43
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
140
},
44
index XXXXXXX..XXXXXXX 100644
141
};
45
--- a/target/arm/mve_helper.c
142
46
+++ b/target/arm/mve_helper.c
143
+ const PPCInfo an524_ppcs[] = { {
47
@@ -XXX,XX +XXX,XX @@ static inline uint32_t do_mulh_w(int64_t n, int64_t m)
144
+ .name = "apb_ppcexp0",
48
return (n * m) >> 32;
145
+ .ports = {
146
+ { "bram-mpc", make_mpc, &mms->mpc[0], 0x58007000, 0x1000 },
147
+ { "qspi-mpc", make_mpc, &mms->mpc[1], 0x58008000, 0x1000 },
148
+ { "ddr-mpc", make_mpc, &mms->mpc[2], 0x58009000, 0x1000 },
149
+ },
150
+ }, {
151
+ .name = "apb_ppcexp1",
152
+ .ports = {
153
+ { "i2c0", make_i2c, &mms->i2c[0], 0x41200000, 0x1000 },
154
+ { "i2c1", make_i2c, &mms->i2c[1], 0x41201000, 0x1000 },
155
+ { "spi0", make_spi, &mms->spi[0], 0x41202000, 0x1000, { 52 } },
156
+ { "spi1", make_spi, &mms->spi[1], 0x41203000, 0x1000, { 53 } },
157
+ { "spi2", make_spi, &mms->spi[2], 0x41204000, 0x1000, { 54 } },
158
+ { "i2c2", make_i2c, &mms->i2c[2], 0x41205000, 0x1000 },
159
+ { "i2c3", make_i2c, &mms->i2c[3], 0x41206000, 0x1000 },
160
+ { /* port 7 reserved */ },
161
+ { "i2c4", make_i2c, &mms->i2c[4], 0x41208000, 0x1000 },
162
+ },
163
+ }, {
164
+ .name = "apb_ppcexp2",
165
+ .ports = {
166
+ { "scc", make_scc, &mms->scc, 0x41300000, 0x1000 },
167
+ { "i2s-audio", make_unimp_dev, &mms->i2s_audio,
168
+ 0x41301000, 0x1000 },
169
+ { "fpgaio", make_fpgaio, &mms->fpgaio, 0x41302000, 0x1000 },
170
+ { "uart0", make_uart, &mms->uart[0], 0x41303000, 0x1000, { 32, 33, 42 } },
171
+ { "uart1", make_uart, &mms->uart[1], 0x41304000, 0x1000, { 34, 35, 43 } },
172
+ { "uart2", make_uart, &mms->uart[2], 0x41305000, 0x1000, { 36, 37, 44 } },
173
+ { "uart3", make_uart, &mms->uart[3], 0x41306000, 0x1000, { 38, 39, 45 } },
174
+ { "uart4", make_uart, &mms->uart[4], 0x41307000, 0x1000, { 40, 41, 46 } },
175
+ { "uart5", make_uart, &mms->uart[5], 0x41308000, 0x1000, { 124, 125, 126 } },
176
+
177
+ { /* port 9 reserved */ },
178
+ { "clcd", make_unimp_dev, &mms->cldc, 0x4130a000, 0x1000 },
179
+ { "rtc", make_unimp_dev, &mms->rtc, 0x4130b000, 0x1000 },
180
+ },
181
+ }, {
182
+ .name = "ahb_ppcexp0",
183
+ .ports = {
184
+ { "gpio0", make_unimp_dev, &mms->gpio[0], 0x41100000, 0x1000 },
185
+ { "gpio1", make_unimp_dev, &mms->gpio[1], 0x41101000, 0x1000 },
186
+ { "gpio2", make_unimp_dev, &mms->gpio[2], 0x41102000, 0x1000 },
187
+ { "gpio3", make_unimp_dev, &mms->gpio[3], 0x41103000, 0x1000 },
188
+ { "eth", make_eth_dev, NULL, 0x41400000, 0x100000, { 48 } },
189
+ },
190
+ },
191
+ };
192
+
193
switch (mmc->fpga_type) {
194
case FPGA_AN505:
195
case FPGA_AN521:
196
ppcs = an505_ppcs;
197
num_ppcs = ARRAY_SIZE(an505_ppcs);
198
break;
199
+ case FPGA_AN524:
200
+ ppcs = an524_ppcs;
201
+ num_ppcs = ARRAY_SIZE(an524_ppcs);
202
+ break;
203
default:
204
g_assert_not_reached();
205
}
206
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
207
mps2tz_set_default_ram_info(mmc);
208
}
49
}
209
50
210
+static void mps3tz_an524_class_init(ObjectClass *oc, void *data)
51
+static inline uint8_t do_rmulh_b(int32_t n, int32_t m)
211
+{
52
+{
212
+ MachineClass *mc = MACHINE_CLASS(oc);
53
+ return (n * m + (1U << 7)) >> 8;
213
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_CLASS(oc);
214
+
215
+ mc->desc = "ARM MPS3 with AN524 FPGA image for dual Cortex-M33";
216
+ mc->default_cpus = 2;
217
+ mc->min_cpus = mc->default_cpus;
218
+ mc->max_cpus = mc->default_cpus;
219
+ mmc->fpga_type = FPGA_AN524;
220
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
221
+ mmc->scc_id = 0x41045240;
222
+ mmc->sysclk_frq = 32 * 1000 * 1000; /* 32MHz */
223
+ mmc->oscclk = an524_oscclk;
224
+ mmc->len_oscclk = ARRAY_SIZE(an524_oscclk);
225
+ mmc->fpgaio_num_leds = 10;
226
+ mmc->fpgaio_has_switches = true;
227
+ mmc->numirq = 95;
228
+ mmc->raminfo = an524_raminfo;
229
+ mmc->armsse_type = TYPE_SSE200;
230
+ mps2tz_set_default_ram_info(mmc);
231
+}
54
+}
232
+
55
+
233
static const TypeInfo mps2tz_info = {
56
+static inline uint16_t do_rmulh_h(int32_t n, int32_t m)
234
.name = TYPE_MPS2TZ_MACHINE,
57
+{
235
.parent = TYPE_MACHINE,
58
+ return (n * m + (1U << 15)) >> 16;
236
@@ -XXX,XX +XXX,XX @@ static const TypeInfo mps2tz_an521_info = {
59
+}
237
.class_init = mps2tz_an521_class_init,
238
};
239
240
+static const TypeInfo mps3tz_an524_info = {
241
+ .name = TYPE_MPS3TZ_AN524_MACHINE,
242
+ .parent = TYPE_MPS2TZ_MACHINE,
243
+ .class_init = mps3tz_an524_class_init,
244
+};
245
+
60
+
246
static void mps2tz_machine_init(void)
61
+static inline uint32_t do_rmulh_w(int64_t n, int64_t m)
247
{
62
+{
248
type_register_static(&mps2tz_info);
63
+ return (n * m + (1U << 31)) >> 32;
249
type_register_static(&mps2tz_an505_info);
64
+}
250
type_register_static(&mps2tz_an521_info);
65
+
251
+ type_register_static(&mps3tz_an524_info);
66
DO_2OP(vmulhsb, 1, int8_t, do_mulh_b)
252
}
67
DO_2OP(vmulhsh, 2, int16_t, do_mulh_h)
253
68
DO_2OP(vmulhsw, 4, int32_t, do_mulh_w)
254
type_init(mps2tz_machine_init);
69
DO_2OP(vmulhub, 1, uint8_t, do_mulh_b)
70
DO_2OP(vmulhuh, 2, uint16_t, do_mulh_h)
71
DO_2OP(vmulhuw, 4, uint32_t, do_mulh_w)
72
+
73
+DO_2OP(vrmulhsb, 1, int8_t, do_rmulh_b)
74
+DO_2OP(vrmulhsh, 2, int16_t, do_rmulh_h)
75
+DO_2OP(vrmulhsw, 4, int32_t, do_rmulh_w)
76
+DO_2OP(vrmulhub, 1, uint8_t, do_rmulh_b)
77
+DO_2OP(vrmulhuh, 2, uint16_t, do_rmulh_h)
78
+DO_2OP(vrmulhuw, 4, uint32_t, do_rmulh_w)
79
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/target/arm/translate-mve.c
82
+++ b/target/arm/translate-mve.c
83
@@ -XXX,XX +XXX,XX @@ DO_2OP(VSUB, vsub)
84
DO_2OP(VMUL, vmul)
85
DO_2OP(VMULH_S, vmulhs)
86
DO_2OP(VMULH_U, vmulhu)
87
+DO_2OP(VRMULH_S, vrmulhs)
88
+DO_2OP(VRMULH_U, vrmulhu)
255
--
89
--
256
2.20.1
90
2.20.1
257
91
258
92
diff view generated by jsdifflib
1
Set the FPGAIO num-leds and have-switches properties explicitly
1
Implement the MVE VMAX and VMIN insns.
2
per-board, rather than relying on the defaults. The AN505 and AN521
3
both have the same settings as the default values, but the AN524 will
4
be different.
5
2
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210215115138.20465-8-peter.maydell@linaro.org
5
Message-id: 20210617121628.20116-16-peter.maydell@linaro.org
10
---
6
---
11
hw/arm/mps2-tz.c | 9 +++++++++
7
target/arm/helper-mve.h | 14 ++++++++++++++
12
1 file changed, 9 insertions(+)
8
target/arm/mve.decode | 5 +++++
9
target/arm/mve_helper.c | 14 ++++++++++++++
10
target/arm/translate-mve.c | 4 ++++
11
4 files changed, 37 insertions(+)
13
12
14
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/hw/arm/mps2-tz.c
15
--- a/target/arm/helper-mve.h
17
+++ b/hw/arm/mps2-tz.c
16
+++ b/target/arm/helper-mve.h
18
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vrmulhsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
uint32_t sysclk_frq; /* Main SYSCLK frequency in Hz */
18
DEF_HELPER_FLAGS_4(mve_vrmulhub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
uint32_t len_oscclk;
19
DEF_HELPER_FLAGS_4(mve_vrmulhuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
const uint32_t *oscclk;
20
DEF_HELPER_FLAGS_4(mve_vrmulhuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
+ uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
21
+
23
+ bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
22
+DEF_HELPER_FLAGS_4(mve_vmaxsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
const char *armsse_type;
23
+DEF_HELPER_FLAGS_4(mve_vmaxsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
};
24
+DEF_HELPER_FLAGS_4(mve_vmaxsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
25
+DEF_HELPER_FLAGS_4(mve_vmaxub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_fpgaio(MPS2TZMachineState *mms, void *opaque,
26
+DEF_HELPER_FLAGS_4(mve_vmaxuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
const char *name, hwaddr size)
27
+DEF_HELPER_FLAGS_4(mve_vmaxuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
{
28
+
30
MPS2FPGAIO *fpgaio = opaque;
29
+DEF_HELPER_FLAGS_4(mve_vminsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
30
+DEF_HELPER_FLAGS_4(mve_vminsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
31
+DEF_HELPER_FLAGS_4(mve_vminsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
object_initialize_child(OBJECT(mms), "fpgaio", fpgaio, TYPE_MPS2_FPGAIO);
32
+DEF_HELPER_FLAGS_4(mve_vminub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
+ qdev_prop_set_uint32(DEVICE(fpgaio), "num-leds", mmc->fpgaio_num_leds);
33
+DEF_HELPER_FLAGS_4(mve_vminuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
35
+ qdev_prop_set_bit(DEVICE(fpgaio), "has-switches", mmc->fpgaio_has_switches);
34
+DEF_HELPER_FLAGS_4(mve_vminuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
sysbus_realize(SYS_BUS_DEVICE(fpgaio), &error_fatal);
35
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
37
return sysbus_mmio_get_region(SYS_BUS_DEVICE(fpgaio), 0);
36
index XXXXXXX..XXXXXXX 100644
38
}
37
--- a/target/arm/mve.decode
39
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
38
+++ b/target/arm/mve.decode
40
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
39
@@ -XXX,XX +XXX,XX @@ VMULH_U 111 1 1110 0 . .. ...1 ... 0 1110 . 0 . 0 ... 1 @2op
41
mmc->oscclk = an505_oscclk;
40
VRMULH_S 111 0 1110 0 . .. ...1 ... 1 1110 . 0 . 0 ... 1 @2op
42
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
41
VRMULH_U 111 1 1110 0 . .. ...1 ... 1 1110 . 0 . 0 ... 1 @2op
43
+ mmc->fpgaio_num_leds = 2;
42
44
+ mmc->fpgaio_has_switches = false;
43
+VMAX_S 111 0 1111 0 . .. ... 0 ... 0 0110 . 1 . 0 ... 0 @2op
45
mmc->armsse_type = TYPE_IOTKIT;
44
+VMAX_U 111 1 1111 0 . .. ... 0 ... 0 0110 . 1 . 0 ... 0 @2op
46
}
45
+VMIN_S 111 0 1111 0 . .. ... 0 ... 0 0110 . 1 . 1 ... 0 @2op
47
46
+VMIN_U 111 1 1111 0 . .. ... 0 ... 0 0110 . 1 . 1 ... 0 @2op
48
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
47
+
49
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
48
# Vector miscellaneous
50
mmc->oscclk = an505_oscclk; /* AN521 is the same as AN505 here */
49
51
mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
50
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
52
+ mmc->fpgaio_num_leds = 2;
51
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
53
+ mmc->fpgaio_has_switches = false;
52
index XXXXXXX..XXXXXXX 100644
54
mmc->armsse_type = TYPE_SSE200;
53
--- a/target/arm/mve_helper.c
55
}
54
+++ b/target/arm/mve_helper.c
56
55
@@ -XXX,XX +XXX,XX @@ DO_1OP(vfnegs, 8, uint64_t, DO_FNEGS)
56
DO_2OP(OP##h, 2, uint16_t, FN) \
57
DO_2OP(OP##w, 4, uint32_t, FN)
58
59
+/* provide signed 2-op helpers for all sizes */
60
+#define DO_2OP_S(OP, FN) \
61
+ DO_2OP(OP##b, 1, int8_t, FN) \
62
+ DO_2OP(OP##h, 2, int16_t, FN) \
63
+ DO_2OP(OP##w, 4, int32_t, FN)
64
+
65
#define DO_AND(N, M) ((N) & (M))
66
#define DO_BIC(N, M) ((N) & ~(M))
67
#define DO_ORR(N, M) ((N) | (M))
68
@@ -XXX,XX +XXX,XX @@ DO_2OP(vrmulhsw, 4, int32_t, do_rmulh_w)
69
DO_2OP(vrmulhub, 1, uint8_t, do_rmulh_b)
70
DO_2OP(vrmulhuh, 2, uint16_t, do_rmulh_h)
71
DO_2OP(vrmulhuw, 4, uint32_t, do_rmulh_w)
72
+
73
+#define DO_MAX(N, M) ((N) >= (M) ? (N) : (M))
74
+#define DO_MIN(N, M) ((N) >= (M) ? (M) : (N))
75
+
76
+DO_2OP_S(vmaxs, DO_MAX)
77
+DO_2OP_U(vmaxu, DO_MAX)
78
+DO_2OP_S(vmins, DO_MIN)
79
+DO_2OP_U(vminu, DO_MIN)
80
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/target/arm/translate-mve.c
83
+++ b/target/arm/translate-mve.c
84
@@ -XXX,XX +XXX,XX @@ DO_2OP(VMULH_S, vmulhs)
85
DO_2OP(VMULH_U, vmulhu)
86
DO_2OP(VRMULH_S, vrmulhs)
87
DO_2OP(VRMULH_U, vrmulhu)
88
+DO_2OP(VMAX_S, vmaxs)
89
+DO_2OP(VMAX_U, vmaxu)
90
+DO_2OP(VMIN_S, vmins)
91
+DO_2OP(VMIN_U, vminu)
57
--
92
--
58
2.20.1
93
2.20.1
59
94
60
95
diff view generated by jsdifflib
1
MPS3 boards have an extra SWITCH register in the FPGAIO block which
1
Implement the MVE VABD insn.
2
reports the value of some switches. Implement this, governed by a
3
property the board code can use to specify whether whether it exists.
4
2
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215115138.20465-7-peter.maydell@linaro.org
5
Message-id: 20210617121628.20116-17-peter.maydell@linaro.org
9
---
6
---
10
include/hw/misc/mps2-fpgaio.h | 1 +
7
target/arm/helper-mve.h | 7 +++++++
11
hw/misc/mps2-fpgaio.c | 10 ++++++++++
8
target/arm/mve.decode | 3 +++
12
2 files changed, 11 insertions(+)
9
target/arm/mve_helper.c | 5 +++++
10
target/arm/translate-mve.c | 2 ++
11
4 files changed, 17 insertions(+)
13
12
14
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/misc/mps2-fpgaio.h
15
--- a/target/arm/helper-mve.h
17
+++ b/include/hw/misc/mps2-fpgaio.h
16
+++ b/target/arm/helper-mve.h
18
@@ -XXX,XX +XXX,XX @@ struct MPS2FPGAIO {
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vminsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
MemoryRegion iomem;
18
DEF_HELPER_FLAGS_4(mve_vminub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
LEDState *led[MPS2FPGAIO_MAX_LEDS];
19
DEF_HELPER_FLAGS_4(mve_vminuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
uint32_t num_leds;
20
DEF_HELPER_FLAGS_4(mve_vminuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
+ bool has_switches;
21
+
23
22
+DEF_HELPER_FLAGS_4(mve_vabdsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
uint32_t led0;
23
+DEF_HELPER_FLAGS_4(mve_vabdsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
uint32_t prescale;
24
+DEF_HELPER_FLAGS_4(mve_vabdsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
25
+DEF_HELPER_FLAGS_4(mve_vabdub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
+DEF_HELPER_FLAGS_4(mve_vabduh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_vabduw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
27
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/misc/mps2-fpgaio.c
30
--- a/target/arm/mve.decode
29
+++ b/hw/misc/mps2-fpgaio.c
31
+++ b/target/arm/mve.decode
30
@@ -XXX,XX +XXX,XX @@ REG32(CLK100HZ, 0x14)
32
@@ -XXX,XX +XXX,XX @@ VMAX_U 111 1 1111 0 . .. ... 0 ... 0 0110 . 1 . 0 ... 0 @2op
31
REG32(COUNTER, 0x18)
33
VMIN_S 111 0 1111 0 . .. ... 0 ... 0 0110 . 1 . 1 ... 0 @2op
32
REG32(PRESCALE, 0x1c)
34
VMIN_U 111 1 1111 0 . .. ... 0 ... 0 0110 . 1 . 1 ... 0 @2op
33
REG32(PSCNTR, 0x20)
35
34
+REG32(SWITCH, 0x28)
36
+VABD_S 111 0 1111 0 . .. ... 0 ... 0 0111 . 1 . 0 ... 0 @2op
35
REG32(MISC, 0x4c)
37
+VABD_U 111 1 1111 0 . .. ... 0 ... 0 0111 . 1 . 0 ... 0 @2op
36
38
+
37
static uint32_t counter_from_tickoff(int64_t now, int64_t tick_offset, int frq)
39
# Vector miscellaneous
38
@@ -XXX,XX +XXX,XX @@ static uint64_t mps2_fpgaio_read(void *opaque, hwaddr offset, unsigned size)
40
39
resync_counter(s);
41
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
40
r = s->pscntr;
42
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
41
break;
43
index XXXXXXX..XXXXXXX 100644
42
+ case A_SWITCH:
44
--- a/target/arm/mve_helper.c
43
+ if (!s->has_switches) {
45
+++ b/target/arm/mve_helper.c
44
+ goto bad_offset;
46
@@ -XXX,XX +XXX,XX @@ DO_2OP_S(vmaxs, DO_MAX)
45
+ }
47
DO_2OP_U(vmaxu, DO_MAX)
46
+ /* User-togglable board switches. We don't model that, so report 0. */
48
DO_2OP_S(vmins, DO_MIN)
47
+ r = 0;
49
DO_2OP_U(vminu, DO_MIN)
48
+ break;
50
+
49
default:
51
+#define DO_ABD(N, M) ((N) >= (M) ? (N) - (M) : (M) - (N))
50
+ bad_offset:
52
+
51
qemu_log_mask(LOG_GUEST_ERROR,
53
+DO_2OP_S(vabds, DO_ABD)
52
"MPS2 FPGAIO read: bad offset %x\n", (int) offset);
54
+DO_2OP_U(vabdu, DO_ABD)
53
r = 0;
55
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
54
@@ -XXX,XX +XXX,XX @@ static Property mps2_fpgaio_properties[] = {
56
index XXXXXXX..XXXXXXX 100644
55
DEFINE_PROP_UINT32("prescale-clk", MPS2FPGAIO, prescale_clk, 20000000),
57
--- a/target/arm/translate-mve.c
56
/* Number of LEDs controlled by LED0 register */
58
+++ b/target/arm/translate-mve.c
57
DEFINE_PROP_UINT32("num-leds", MPS2FPGAIO, num_leds, 2),
59
@@ -XXX,XX +XXX,XX @@ DO_2OP(VMAX_S, vmaxs)
58
+ DEFINE_PROP_BOOL("has-switches", MPS2FPGAIO, has_switches, false),
60
DO_2OP(VMAX_U, vmaxu)
59
DEFINE_PROP_END_OF_LIST(),
61
DO_2OP(VMIN_S, vmins)
60
};
62
DO_2OP(VMIN_U, vminu)
61
63
+DO_2OP(VABD_S, vabds)
64
+DO_2OP(VABD_U, vabdu)
62
--
65
--
63
2.20.1
66
2.20.1
64
67
65
68
diff view generated by jsdifflib
1
We only include the template header once, so just inline it into the
1
Implement MVE VHADD and VHSUB insns, which perform an addition
2
source file for the device.
2
or subtraction and then halve the result.
3
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20210617121628.20116-18-peter.maydell@linaro.org
7
Message-id: 20210215103215.4944-9-peter.maydell@linaro.org
8
---
7
---
9
hw/display/omap_lcd_template.h | 154 ---------------------------------
8
target/arm/helper-mve.h | 14 ++++++++++++++
10
hw/display/omap_lcdc.c | 127 ++++++++++++++++++++++++++-
9
target/arm/mve.decode | 5 +++++
11
2 files changed, 125 insertions(+), 156 deletions(-)
10
target/arm/mve_helper.c | 25 +++++++++++++++++++++++++
12
delete mode 100644 hw/display/omap_lcd_template.h
11
target/arm/translate-mve.c | 4 ++++
12
4 files changed, 48 insertions(+)
13
13
14
diff --git a/hw/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
15
deleted file mode 100644
16
index XXXXXXX..XXXXXXX
17
--- a/hw/display/omap_lcd_template.h
18
+++ /dev/null
19
@@ -XXX,XX +XXX,XX @@
20
-/*
21
- * QEMU OMAP LCD Emulator templates
22
- *
23
- * Copyright (c) 2006 Andrzej Zaborowski <balrog@zabor.org>
24
- *
25
- * Redistribution and use in source and binary forms, with or without
26
- * modification, are permitted provided that the following conditions
27
- * are met:
28
- *
29
- * 1. Redistributions of source code must retain the above copyright
30
- * notice, this list of conditions and the following disclaimer.
31
- * 2. Redistributions in binary form must reproduce the above copyright
32
- * notice, this list of conditions and the following disclaimer in
33
- * the documentation and/or other materials provided with the
34
- * distribution.
35
- *
36
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
37
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
38
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
39
- * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
40
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
41
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
42
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
43
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
44
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
46
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47
- */
48
-
49
-/*
50
- * 2-bit colour
51
- */
52
-static void draw_line2_32(void *opaque, uint8_t *d, const uint8_t *s,
53
- int width, int deststep)
54
-{
55
- uint16_t *pal = opaque;
56
- uint8_t v, r, g, b;
57
-
58
- do {
59
- v = ldub_p((void *) s);
60
- r = (pal[v & 3] >> 4) & 0xf0;
61
- g = pal[v & 3] & 0xf0;
62
- b = (pal[v & 3] << 4) & 0xf0;
63
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
64
- d += 4;
65
- v >>= 2;
66
- r = (pal[v & 3] >> 4) & 0xf0;
67
- g = pal[v & 3] & 0xf0;
68
- b = (pal[v & 3] << 4) & 0xf0;
69
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
70
- d += 4;
71
- v >>= 2;
72
- r = (pal[v & 3] >> 4) & 0xf0;
73
- g = pal[v & 3] & 0xf0;
74
- b = (pal[v & 3] << 4) & 0xf0;
75
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
76
- d += 4;
77
- v >>= 2;
78
- r = (pal[v & 3] >> 4) & 0xf0;
79
- g = pal[v & 3] & 0xf0;
80
- b = (pal[v & 3] << 4) & 0xf0;
81
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
82
- d += 4;
83
- s++;
84
- width -= 4;
85
- } while (width > 0);
86
-}
87
-
88
-/*
89
- * 4-bit colour
90
- */
91
-static void draw_line4_32(void *opaque, uint8_t *d, const uint8_t *s,
92
- int width, int deststep)
93
-{
94
- uint16_t *pal = opaque;
95
- uint8_t v, r, g, b;
96
-
97
- do {
98
- v = ldub_p((void *) s);
99
- r = (pal[v & 0xf] >> 4) & 0xf0;
100
- g = pal[v & 0xf] & 0xf0;
101
- b = (pal[v & 0xf] << 4) & 0xf0;
102
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
103
- d += 4;
104
- v >>= 4;
105
- r = (pal[v & 0xf] >> 4) & 0xf0;
106
- g = pal[v & 0xf] & 0xf0;
107
- b = (pal[v & 0xf] << 4) & 0xf0;
108
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
109
- d += 4;
110
- s++;
111
- width -= 2;
112
- } while (width > 0);
113
-}
114
-
115
-/*
116
- * 8-bit colour
117
- */
118
-static void draw_line8_32(void *opaque, uint8_t *d, const uint8_t *s,
119
- int width, int deststep)
120
-{
121
- uint16_t *pal = opaque;
122
- uint8_t v, r, g, b;
123
-
124
- do {
125
- v = ldub_p((void *) s);
126
- r = (pal[v] >> 4) & 0xf0;
127
- g = pal[v] & 0xf0;
128
- b = (pal[v] << 4) & 0xf0;
129
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
130
- s++;
131
- d += 4;
132
- } while (-- width != 0);
133
-}
134
-
135
-/*
136
- * 12-bit colour
137
- */
138
-static void draw_line12_32(void *opaque, uint8_t *d, const uint8_t *s,
139
- int width, int deststep)
140
-{
141
- uint16_t v;
142
- uint8_t r, g, b;
143
-
144
- do {
145
- v = lduw_le_p((void *) s);
146
- r = (v >> 4) & 0xf0;
147
- g = v & 0xf0;
148
- b = (v << 4) & 0xf0;
149
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
150
- s += 2;
151
- d += 4;
152
- } while (-- width != 0);
153
-}
154
-
155
-/*
156
- * 16-bit colour
157
- */
158
-static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
159
- int width, int deststep)
160
-{
161
- uint16_t v;
162
- uint8_t r, g, b;
163
-
164
- do {
165
- v = lduw_le_p((void *) s);
166
- r = (v >> 8) & 0xf8;
167
- g = (v >> 3) & 0xfc;
168
- b = (v << 3) & 0xf8;
169
- ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
170
- s += 2;
171
- d += 4;
172
- } while (-- width != 0);
173
-}
174
diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c
175
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
176
--- a/hw/display/omap_lcdc.c
16
--- a/target/arm/helper-mve.h
177
+++ b/hw/display/omap_lcdc.c
17
+++ b/target/arm/helper-mve.h
178
@@ -XXX,XX +XXX,XX @@ static void omap_lcd_interrupts(struct omap_lcd_panel_s *s)
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vabdsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
179
19
DEF_HELPER_FLAGS_4(mve_vabdub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
180
#define draw_line_func drawfn
20
DEF_HELPER_FLAGS_4(mve_vabduh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
181
21
DEF_HELPER_FLAGS_4(mve_vabduw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
182
-#define DEPTH 32
22
+
183
-#include "omap_lcd_template.h"
23
+DEF_HELPER_FLAGS_4(mve_vhaddsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
184
+/*
24
+DEF_HELPER_FLAGS_4(mve_vhaddsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
185
+ * 2-bit colour
25
+DEF_HELPER_FLAGS_4(mve_vhaddsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
186
+ */
26
+DEF_HELPER_FLAGS_4(mve_vhaddub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
187
+static void draw_line2_32(void *opaque, uint8_t *d, const uint8_t *s,
27
+DEF_HELPER_FLAGS_4(mve_vhadduh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
188
+ int width, int deststep)
28
+DEF_HELPER_FLAGS_4(mve_vhadduw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
+
30
+DEF_HELPER_FLAGS_4(mve_vhsubsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
+DEF_HELPER_FLAGS_4(mve_vhsubsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
+DEF_HELPER_FLAGS_4(mve_vhsubsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
+DEF_HELPER_FLAGS_4(mve_vhsubub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
+DEF_HELPER_FLAGS_4(mve_vhsubuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
35
+DEF_HELPER_FLAGS_4(mve_vhsubuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/mve.decode
39
+++ b/target/arm/mve.decode
40
@@ -XXX,XX +XXX,XX @@ VMIN_U 111 1 1111 0 . .. ... 0 ... 0 0110 . 1 . 1 ... 0 @2op
41
VABD_S 111 0 1111 0 . .. ... 0 ... 0 0111 . 1 . 0 ... 0 @2op
42
VABD_U 111 1 1111 0 . .. ... 0 ... 0 0111 . 1 . 0 ... 0 @2op
43
44
+VHADD_S 111 0 1111 0 . .. ... 0 ... 0 0000 . 1 . 0 ... 0 @2op
45
+VHADD_U 111 1 1111 0 . .. ... 0 ... 0 0000 . 1 . 0 ... 0 @2op
46
+VHSUB_S 111 0 1111 0 . .. ... 0 ... 0 0010 . 1 . 0 ... 0 @2op
47
+VHSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 0 ... 0 @2op
48
+
49
# Vector miscellaneous
50
51
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
52
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/mve_helper.c
55
+++ b/target/arm/mve_helper.c
56
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vminu, DO_MIN)
57
58
DO_2OP_S(vabds, DO_ABD)
59
DO_2OP_U(vabdu, DO_ABD)
60
+
61
+static inline uint32_t do_vhadd_u(uint32_t n, uint32_t m)
189
+{
62
+{
190
+ uint16_t *pal = opaque;
63
+ return ((uint64_t)n + m) >> 1;
191
+ uint8_t v, r, g, b;
192
+
193
+ do {
194
+ v = ldub_p((void *) s);
195
+ r = (pal[v & 3] >> 4) & 0xf0;
196
+ g = pal[v & 3] & 0xf0;
197
+ b = (pal[v & 3] << 4) & 0xf0;
198
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
199
+ d += 4;
200
+ v >>= 2;
201
+ r = (pal[v & 3] >> 4) & 0xf0;
202
+ g = pal[v & 3] & 0xf0;
203
+ b = (pal[v & 3] << 4) & 0xf0;
204
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
205
+ d += 4;
206
+ v >>= 2;
207
+ r = (pal[v & 3] >> 4) & 0xf0;
208
+ g = pal[v & 3] & 0xf0;
209
+ b = (pal[v & 3] << 4) & 0xf0;
210
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
211
+ d += 4;
212
+ v >>= 2;
213
+ r = (pal[v & 3] >> 4) & 0xf0;
214
+ g = pal[v & 3] & 0xf0;
215
+ b = (pal[v & 3] << 4) & 0xf0;
216
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
217
+ d += 4;
218
+ s++;
219
+ width -= 4;
220
+ } while (width > 0);
221
+}
64
+}
222
+
65
+
223
+/*
66
+static inline int32_t do_vhadd_s(int32_t n, int32_t m)
224
+ * 4-bit colour
225
+ */
226
+static void draw_line4_32(void *opaque, uint8_t *d, const uint8_t *s,
227
+ int width, int deststep)
228
+{
67
+{
229
+ uint16_t *pal = opaque;
68
+ return ((int64_t)n + m) >> 1;
230
+ uint8_t v, r, g, b;
231
+
232
+ do {
233
+ v = ldub_p((void *) s);
234
+ r = (pal[v & 0xf] >> 4) & 0xf0;
235
+ g = pal[v & 0xf] & 0xf0;
236
+ b = (pal[v & 0xf] << 4) & 0xf0;
237
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
238
+ d += 4;
239
+ v >>= 4;
240
+ r = (pal[v & 0xf] >> 4) & 0xf0;
241
+ g = pal[v & 0xf] & 0xf0;
242
+ b = (pal[v & 0xf] << 4) & 0xf0;
243
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
244
+ d += 4;
245
+ s++;
246
+ width -= 2;
247
+ } while (width > 0);
248
+}
69
+}
249
+
70
+
250
+/*
71
+static inline uint32_t do_vhsub_u(uint32_t n, uint32_t m)
251
+ * 8-bit colour
252
+ */
253
+static void draw_line8_32(void *opaque, uint8_t *d, const uint8_t *s,
254
+ int width, int deststep)
255
+{
72
+{
256
+ uint16_t *pal = opaque;
73
+ return ((uint64_t)n - m) >> 1;
257
+ uint8_t v, r, g, b;
258
+
259
+ do {
260
+ v = ldub_p((void *) s);
261
+ r = (pal[v] >> 4) & 0xf0;
262
+ g = pal[v] & 0xf0;
263
+ b = (pal[v] << 4) & 0xf0;
264
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
265
+ s++;
266
+ d += 4;
267
+ } while (-- width != 0);
268
+}
74
+}
269
+
75
+
270
+/*
76
+static inline int32_t do_vhsub_s(int32_t n, int32_t m)
271
+ * 12-bit colour
272
+ */
273
+static void draw_line12_32(void *opaque, uint8_t *d, const uint8_t *s,
274
+ int width, int deststep)
275
+{
77
+{
276
+ uint16_t v;
78
+ return ((int64_t)n - m) >> 1;
277
+ uint8_t r, g, b;
278
+
279
+ do {
280
+ v = lduw_le_p((void *) s);
281
+ r = (v >> 4) & 0xf0;
282
+ g = v & 0xf0;
283
+ b = (v << 4) & 0xf0;
284
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
285
+ s += 2;
286
+ d += 4;
287
+ } while (-- width != 0);
288
+}
79
+}
289
+
80
+
290
+/*
81
+DO_2OP_S(vhadds, do_vhadd_s)
291
+ * 16-bit colour
82
+DO_2OP_U(vhaddu, do_vhadd_u)
292
+ */
83
+DO_2OP_S(vhsubs, do_vhsub_s)
293
+static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
84
+DO_2OP_U(vhsubu, do_vhsub_u)
294
+ int width, int deststep)
85
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
295
+{
86
index XXXXXXX..XXXXXXX 100644
296
+ uint16_t v;
87
--- a/target/arm/translate-mve.c
297
+ uint8_t r, g, b;
88
+++ b/target/arm/translate-mve.c
298
+
89
@@ -XXX,XX +XXX,XX @@ DO_2OP(VMIN_S, vmins)
299
+ do {
90
DO_2OP(VMIN_U, vminu)
300
+ v = lduw_le_p((void *) s);
91
DO_2OP(VABD_S, vabds)
301
+ r = (v >> 8) & 0xf8;
92
DO_2OP(VABD_U, vabdu)
302
+ g = (v >> 3) & 0xfc;
93
+DO_2OP(VHADD_S, vhadds)
303
+ b = (v << 3) & 0xf8;
94
+DO_2OP(VHADD_U, vhaddu)
304
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
95
+DO_2OP(VHSUB_S, vhsubs)
305
+ s += 2;
96
+DO_2OP(VHSUB_U, vhsubu)
306
+ d += 4;
307
+ } while (-- width != 0);
308
+}
309
310
static void omap_update_display(void *opaque)
311
{
312
--
97
--
313
2.20.1
98
2.20.1
314
99
315
100
diff view generated by jsdifflib
1
The AN505 and AN521 have the same device layout, but the AN524 is
1
Implement the MVE VMULL insn, which multiplies two single
2
somewhat different. Allow for more than one PPCInfo array, which can
2
width integer elements to produce a double width result.
3
be selected based on the board type.
4
3
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210215115138.20465-16-peter.maydell@linaro.org
6
Message-id: 20210617121628.20116-19-peter.maydell@linaro.org
8
---
7
---
9
hw/arm/mps2-tz.c | 16 ++++++++++++++--
8
target/arm/helper-mve.h | 14 ++++++++++++++
10
1 file changed, 14 insertions(+), 2 deletions(-)
9
target/arm/mve.decode | 5 +++++
10
target/arm/mve_helper.c | 34 ++++++++++++++++++++++++++++++++++
11
target/arm/translate-mve.c | 4 ++++
12
4 files changed, 57 insertions(+)
11
13
12
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
13
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/mps2-tz.c
16
--- a/target/arm/helper-mve.h
15
+++ b/hw/arm/mps2-tz.c
17
+++ b/target/arm/helper-mve.h
16
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vhsubsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
17
MemoryRegion *system_memory = get_system_memory();
19
DEF_HELPER_FLAGS_4(mve_vhsubub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
18
DeviceState *iotkitdev;
20
DEF_HELPER_FLAGS_4(mve_vhsubuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
DeviceState *dev_splitter;
21
DEF_HELPER_FLAGS_4(mve_vhsubuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
+ const PPCInfo *ppcs;
22
+
21
+ int num_ppcs;
23
+DEF_HELPER_FLAGS_4(mve_vmullbsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
int i;
24
+DEF_HELPER_FLAGS_4(mve_vmullbsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
25
+DEF_HELPER_FLAGS_4(mve_vmullbsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
if (strcmp(machine->cpu_type, mc->default_cpu_type) != 0) {
26
+DEF_HELPER_FLAGS_4(mve_vmullbub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
27
+DEF_HELPER_FLAGS_4(mve_vmullbuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
* + wire up the PPC's control lines to the IoTKit object
28
+DEF_HELPER_FLAGS_4(mve_vmullbuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
*/
29
+
28
30
+DEF_HELPER_FLAGS_4(mve_vmulltsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
- const PPCInfo ppcs[] = { {
31
+DEF_HELPER_FLAGS_4(mve_vmulltsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
+ const PPCInfo an505_ppcs[] = { {
32
+DEF_HELPER_FLAGS_4(mve_vmulltsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
.name = "apb_ppcexp0",
33
+DEF_HELPER_FLAGS_4(mve_vmulltub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
.ports = {
34
+DEF_HELPER_FLAGS_4(mve_vmulltuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
{ "ssram-0", make_mpc, &mms->ssram_mpc[0], 0x58007000, 0x1000 },
35
+DEF_HELPER_FLAGS_4(mve_vmulltuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
36
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
35
},
37
index XXXXXXX..XXXXXXX 100644
36
};
38
--- a/target/arm/mve.decode
37
39
+++ b/target/arm/mve.decode
38
- for (i = 0; i < ARRAY_SIZE(ppcs); i++) {
40
@@ -XXX,XX +XXX,XX @@ VHADD_U 111 1 1111 0 . .. ... 0 ... 0 0000 . 1 . 0 ... 0 @2op
39
+ switch (mmc->fpga_type) {
41
VHSUB_S 111 0 1111 0 . .. ... 0 ... 0 0010 . 1 . 0 ... 0 @2op
40
+ case FPGA_AN505:
42
VHSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 0 ... 0 @2op
41
+ case FPGA_AN521:
43
42
+ ppcs = an505_ppcs;
44
+VMULL_BS 111 0 1110 0 . .. ... 1 ... 0 1110 . 0 . 0 ... 0 @2op
43
+ num_ppcs = ARRAY_SIZE(an505_ppcs);
45
+VMULL_BU 111 1 1110 0 . .. ... 1 ... 0 1110 . 0 . 0 ... 0 @2op
44
+ break;
46
+VMULL_TS 111 0 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
45
+ default:
47
+VMULL_TU 111 1 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
46
+ g_assert_not_reached();
48
+
49
# Vector miscellaneous
50
51
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
52
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/mve_helper.c
55
+++ b/target/arm/mve_helper.c
56
@@ -XXX,XX +XXX,XX @@ DO_1OP(vfnegs, 8, uint64_t, DO_FNEGS)
57
DO_2OP(OP##h, 2, int16_t, FN) \
58
DO_2OP(OP##w, 4, int32_t, FN)
59
60
+/*
61
+ * "Long" operations where two half-sized inputs (taken from either the
62
+ * top or the bottom of the input vector) produce a double-width result.
63
+ * Here ESIZE, TYPE are for the input, and LESIZE, LTYPE for the output.
64
+ */
65
+#define DO_2OP_L(OP, TOP, ESIZE, TYPE, LESIZE, LTYPE, FN) \
66
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, void *vm) \
67
+ { \
68
+ LTYPE *d = vd; \
69
+ TYPE *n = vn, *m = vm; \
70
+ uint16_t mask = mve_element_mask(env); \
71
+ unsigned le; \
72
+ for (le = 0; le < 16 / LESIZE; le++, mask >>= LESIZE) { \
73
+ LTYPE r = FN((LTYPE)n[H##ESIZE(le * 2 + TOP)], \
74
+ m[H##ESIZE(le * 2 + TOP)]); \
75
+ mergemask(&d[H##LESIZE(le)], r, mask); \
76
+ } \
77
+ mve_advance_vpt(env); \
47
+ }
78
+ }
48
+
79
+
49
+ for (i = 0; i < num_ppcs; i++) {
80
#define DO_AND(N, M) ((N) & (M))
50
const PPCInfo *ppcinfo = &ppcs[i];
81
#define DO_BIC(N, M) ((N) & ~(M))
51
TZPPC *ppc = &mms->ppc[i];
82
#define DO_ORR(N, M) ((N) | (M))
52
DeviceState *ppcdev;
83
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vadd, DO_ADD)
84
DO_2OP_U(vsub, DO_SUB)
85
DO_2OP_U(vmul, DO_MUL)
86
87
+DO_2OP_L(vmullbsb, 0, 1, int8_t, 2, int16_t, DO_MUL)
88
+DO_2OP_L(vmullbsh, 0, 2, int16_t, 4, int32_t, DO_MUL)
89
+DO_2OP_L(vmullbsw, 0, 4, int32_t, 8, int64_t, DO_MUL)
90
+DO_2OP_L(vmullbub, 0, 1, uint8_t, 2, uint16_t, DO_MUL)
91
+DO_2OP_L(vmullbuh, 0, 2, uint16_t, 4, uint32_t, DO_MUL)
92
+DO_2OP_L(vmullbuw, 0, 4, uint32_t, 8, uint64_t, DO_MUL)
93
+
94
+DO_2OP_L(vmulltsb, 1, 1, int8_t, 2, int16_t, DO_MUL)
95
+DO_2OP_L(vmulltsh, 1, 2, int16_t, 4, int32_t, DO_MUL)
96
+DO_2OP_L(vmulltsw, 1, 4, int32_t, 8, int64_t, DO_MUL)
97
+DO_2OP_L(vmulltub, 1, 1, uint8_t, 2, uint16_t, DO_MUL)
98
+DO_2OP_L(vmulltuh, 1, 2, uint16_t, 4, uint32_t, DO_MUL)
99
+DO_2OP_L(vmulltuw, 1, 4, uint32_t, 8, uint64_t, DO_MUL)
100
+
101
/*
102
* Because the computation type is at least twice as large as required,
103
* these work for both signed and unsigned source types.
104
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
105
index XXXXXXX..XXXXXXX 100644
106
--- a/target/arm/translate-mve.c
107
+++ b/target/arm/translate-mve.c
108
@@ -XXX,XX +XXX,XX @@ DO_2OP(VHADD_S, vhadds)
109
DO_2OP(VHADD_U, vhaddu)
110
DO_2OP(VHSUB_S, vhsubs)
111
DO_2OP(VHSUB_U, vhsubu)
112
+DO_2OP(VMULL_BS, vmullbs)
113
+DO_2OP(VMULL_BU, vmullbu)
114
+DO_2OP(VMULL_TS, vmullts)
115
+DO_2OP(VMULL_TU, vmulltu)
53
--
116
--
54
2.20.1
117
2.20.1
55
118
56
119
diff view generated by jsdifflib
1
The AN505 and AN511 happen to share the same OSCCLK values, but the
1
Implement the MVE VMLALDAV insn, which multiplies pairs of integer
2
AN524 will have a different set (and more of them), so split the
2
elements, accumulating them into a 64-bit result in a pair of
3
settings out to be per-board.
3
general-purpose registers.
4
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215115138.20465-5-peter.maydell@linaro.org
7
Message-id: 20210617121628.20116-20-peter.maydell@linaro.org
9
---
8
---
10
hw/arm/mps2-tz.c | 23 ++++++++++++++++++-----
9
target/arm/helper-mve.h | 8 ++++
11
1 file changed, 18 insertions(+), 5 deletions(-)
10
target/arm/translate.h | 10 ++++
12
11
target/arm/mve.decode | 15 ++++++
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
12
target/arm/mve_helper.c | 34 ++++++++++++++
14
index XXXXXXX..XXXXXXX 100644
13
target/arm/translate-mve.c | 96 ++++++++++++++++++++++++++++++++++++++
15
--- a/hw/arm/mps2-tz.c
14
5 files changed, 163 insertions(+)
16
+++ b/hw/arm/mps2-tz.c
15
17
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
16
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
18
MPS2TZFPGAType fpga_type;
17
index XXXXXXX..XXXXXXX 100644
19
uint32_t scc_id;
18
--- a/target/arm/helper-mve.h
20
uint32_t sysclk_frq; /* Main SYSCLK frequency in Hz */
19
+++ b/target/arm/helper-mve.h
21
+ uint32_t len_oscclk;
20
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmulltsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
+ const uint32_t *oscclk;
21
DEF_HELPER_FLAGS_4(mve_vmulltub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
const char *armsse_type;
22
DEF_HELPER_FLAGS_4(mve_vmulltuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
};
23
DEF_HELPER_FLAGS_4(mve_vmulltuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
24
+
26
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_TYPE(MPS2TZMachineState, MPS2TZMachineClass, MPS2TZ_MACHINE)
25
+DEF_HELPER_FLAGS_4(mve_vmlaldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
27
/* Slow 32Khz S32KCLK frequency in Hz */
26
+DEF_HELPER_FLAGS_4(mve_vmlaldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
28
#define S32KCLK_FRQ (32 * 1000)
27
+DEF_HELPER_FLAGS_4(mve_vmlaldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
29
28
+DEF_HELPER_FLAGS_4(mve_vmlaldavxsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
30
+static const uint32_t an505_oscclk[] = {
29
+
31
+ 40000000,
30
+DEF_HELPER_FLAGS_4(mve_vmlaldavuh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
32
+ 24580000,
31
+DEF_HELPER_FLAGS_4(mve_vmlaldavuw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
33
+ 25000000,
32
diff --git a/target/arm/translate.h b/target/arm/translate.h
34
+};
33
index XXXXXXX..XXXXXXX 100644
35
+
34
--- a/target/arm/translate.h
36
/* Create an alias of an entire original MemoryRegion @orig
35
+++ b/target/arm/translate.h
37
* located at @base in the memory map.
36
@@ -XXX,XX +XXX,XX @@ static inline int negate(DisasContext *s, int x)
38
*/
37
return -x;
39
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
40
MPS2SCC *scc = opaque;
41
DeviceState *sccdev;
42
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
43
+ uint32_t i;
44
45
object_initialize_child(OBJECT(mms), "scc", scc, TYPE_MPS2_SCC);
46
sccdev = DEVICE(scc);
47
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
48
qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008);
49
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
50
- /* This will need to be per-FPGA image eventually */
51
- qdev_prop_set_uint32(sccdev, "len-oscclk", 3);
52
- qdev_prop_set_uint32(sccdev, "oscclk[0]", 40000000);
53
- qdev_prop_set_uint32(sccdev, "oscclk[1]", 24580000);
54
- qdev_prop_set_uint32(sccdev, "oscclk[2]", 25000000);
55
+ qdev_prop_set_uint32(sccdev, "len-oscclk", mmc->len_oscclk);
56
+ for (i = 0; i < mmc->len_oscclk; i++) {
57
+ g_autofree char *propname = g_strdup_printf("oscclk[%u]", i);
58
+ qdev_prop_set_uint32(sccdev, propname, mmc->oscclk[i]);
59
+ }
60
sysbus_realize(SYS_BUS_DEVICE(scc), &error_fatal);
61
return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
62
}
38
}
63
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
39
64
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
40
+static inline int plus_1(DisasContext *s, int x)
65
mmc->scc_id = 0x41045050;
41
+{
66
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
42
+ return x + 1;
67
+ mmc->oscclk = an505_oscclk;
43
+}
68
+ mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
44
+
69
mmc->armsse_type = TYPE_IOTKIT;
45
static inline int plus_2(DisasContext *s, int x)
46
{
47
return x + 2;
48
@@ -XXX,XX +XXX,XX @@ static inline int times_4(DisasContext *s, int x)
49
return x * 4;
70
}
50
}
71
51
72
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
52
+static inline int times_2_plus_1(DisasContext *s, int x)
73
mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m33");
53
+{
74
mmc->scc_id = 0x41045210;
54
+ return x * 2 + 1;
75
mmc->sysclk_frq = 20 * 1000 * 1000; /* 20MHz */
55
+}
76
+ mmc->oscclk = an505_oscclk; /* AN521 is the same as AN505 here */
56
+
77
+ mmc->len_oscclk = ARRAY_SIZE(an505_oscclk);
57
static inline int arm_dc_feature(DisasContext *dc, int feature)
78
mmc->armsse_type = TYPE_SSE200;
58
{
59
return (dc->features & (1ULL << feature)) != 0;
60
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/mve.decode
63
+++ b/target/arm/mve.decode
64
@@ -XXX,XX +XXX,XX @@ VNEG_fp 1111 1111 1 . 11 .. 01 ... 0 0111 11 . 0 ... 0 @1op
65
VDUP 1110 1110 1 1 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=0
66
VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 1 1 0000 @vdup size=1
67
VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=2
68
+
69
+# multiply-add long dual accumulate
70
+# rdahi: bits [3:1] from insn, bit 0 is 1
71
+# rdalo: bits [3:1] from insn, bit 0 is 0
72
+%rdahi 20:3 !function=times_2_plus_1
73
+%rdalo 13:3 !function=times_2
74
+# size bit is 0 for 16 bit, 1 for 32 bit
75
+%size_16 16:1 !function=plus_1
76
+
77
+&vmlaldav rdahi rdalo size qn qm x a
78
+
79
+@vmlaldav .... .... . ... ... . ... . .... .... qm:3 . \
80
+ qn=%qn rdahi=%rdahi rdalo=%rdalo size=%size_16 &vmlaldav
81
+VMLALDAV_S 1110 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 0 @vmlaldav
82
+VMLALDAV_U 1111 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 0 @vmlaldav
83
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/target/arm/mve_helper.c
86
+++ b/target/arm/mve_helper.c
87
@@ -XXX,XX +XXX,XX @@ DO_2OP_S(vhadds, do_vhadd_s)
88
DO_2OP_U(vhaddu, do_vhadd_u)
89
DO_2OP_S(vhsubs, do_vhsub_s)
90
DO_2OP_U(vhsubu, do_vhsub_u)
91
+
92
+
93
+/*
94
+ * Multiply add long dual accumulate ops.
95
+ */
96
+#define DO_LDAV(OP, ESIZE, TYPE, XCHG, EVENACC, ODDACC) \
97
+ uint64_t HELPER(glue(mve_, OP))(CPUARMState *env, void *vn, \
98
+ void *vm, uint64_t a) \
99
+ { \
100
+ uint16_t mask = mve_element_mask(env); \
101
+ unsigned e; \
102
+ TYPE *n = vn, *m = vm; \
103
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
104
+ if (mask & 1) { \
105
+ if (e & 1) { \
106
+ a ODDACC \
107
+ (int64_t)n[H##ESIZE(e - 1 * XCHG)] * m[H##ESIZE(e)]; \
108
+ } else { \
109
+ a EVENACC \
110
+ (int64_t)n[H##ESIZE(e + 1 * XCHG)] * m[H##ESIZE(e)]; \
111
+ } \
112
+ } \
113
+ } \
114
+ mve_advance_vpt(env); \
115
+ return a; \
116
+ }
117
+
118
+DO_LDAV(vmlaldavsh, 2, int16_t, false, +=, +=)
119
+DO_LDAV(vmlaldavxsh, 2, int16_t, true, +=, +=)
120
+DO_LDAV(vmlaldavsw, 4, int32_t, false, +=, +=)
121
+DO_LDAV(vmlaldavxsw, 4, int32_t, true, +=, +=)
122
+
123
+DO_LDAV(vmlaldavuh, 2, uint16_t, false, +=, +=)
124
+DO_LDAV(vmlaldavuw, 4, uint32_t, false, +=, +=)
125
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
126
index XXXXXXX..XXXXXXX 100644
127
--- a/target/arm/translate-mve.c
128
+++ b/target/arm/translate-mve.c
129
@@ -XXX,XX +XXX,XX @@
130
typedef void MVEGenLdStFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
131
typedef void MVEGenOneOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
132
typedef void MVEGenTwoOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr);
133
+typedef void MVEGenDualAccOpFn(TCGv_i64, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i64);
134
135
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
136
static inline long mve_qreg_offset(unsigned reg)
137
@@ -XXX,XX +XXX,XX @@ static void mve_update_eci(DisasContext *s)
138
}
79
}
139
}
80
140
141
+static bool mve_skip_first_beat(DisasContext *s)
142
+{
143
+ /* Return true if PSR.ECI says we must skip the first beat of this insn */
144
+ switch (s->eci) {
145
+ case ECI_NONE:
146
+ return false;
147
+ case ECI_A0:
148
+ case ECI_A0A1:
149
+ case ECI_A0A1A2:
150
+ case ECI_A0A1A2B0:
151
+ return true;
152
+ default:
153
+ g_assert_not_reached();
154
+ }
155
+}
156
+
157
static bool do_ldst(DisasContext *s, arg_VLDR_VSTR *a, MVEGenLdStFn *fn)
158
{
159
TCGv_i32 addr;
160
@@ -XXX,XX +XXX,XX @@ DO_2OP(VMULL_BS, vmullbs)
161
DO_2OP(VMULL_BU, vmullbu)
162
DO_2OP(VMULL_TS, vmullts)
163
DO_2OP(VMULL_TU, vmulltu)
164
+
165
+static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
166
+ MVEGenDualAccOpFn *fn)
167
+{
168
+ TCGv_ptr qn, qm;
169
+ TCGv_i64 rda;
170
+ TCGv_i32 rdalo, rdahi;
171
+
172
+ if (!dc_isar_feature(aa32_mve, s) ||
173
+ !mve_check_qreg_bank(s, a->qn | a->qm) ||
174
+ !fn) {
175
+ return false;
176
+ }
177
+ /*
178
+ * rdahi == 13 is UNPREDICTABLE; rdahi == 15 is a related
179
+ * encoding; rdalo always has bit 0 clear so cannot be 13 or 15.
180
+ */
181
+ if (a->rdahi == 13 || a->rdahi == 15) {
182
+ return false;
183
+ }
184
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
185
+ return true;
186
+ }
187
+
188
+ qn = mve_qreg_ptr(a->qn);
189
+ qm = mve_qreg_ptr(a->qm);
190
+
191
+ /*
192
+ * This insn is subject to beat-wise execution. Partial execution
193
+ * of an A=0 (no-accumulate) insn which does not execute the first
194
+ * beat must start with the current rda value, not 0.
195
+ */
196
+ if (a->a || mve_skip_first_beat(s)) {
197
+ rda = tcg_temp_new_i64();
198
+ rdalo = load_reg(s, a->rdalo);
199
+ rdahi = load_reg(s, a->rdahi);
200
+ tcg_gen_concat_i32_i64(rda, rdalo, rdahi);
201
+ tcg_temp_free_i32(rdalo);
202
+ tcg_temp_free_i32(rdahi);
203
+ } else {
204
+ rda = tcg_const_i64(0);
205
+ }
206
+
207
+ fn(rda, cpu_env, qn, qm, rda);
208
+ tcg_temp_free_ptr(qn);
209
+ tcg_temp_free_ptr(qm);
210
+
211
+ rdalo = tcg_temp_new_i32();
212
+ rdahi = tcg_temp_new_i32();
213
+ tcg_gen_extrl_i64_i32(rdalo, rda);
214
+ tcg_gen_extrh_i64_i32(rdahi, rda);
215
+ store_reg(s, a->rdalo, rdalo);
216
+ store_reg(s, a->rdahi, rdahi);
217
+ tcg_temp_free_i64(rda);
218
+ mve_update_eci(s);
219
+ return true;
220
+}
221
+
222
+static bool trans_VMLALDAV_S(DisasContext *s, arg_vmlaldav *a)
223
+{
224
+ static MVEGenDualAccOpFn * const fns[4][2] = {
225
+ { NULL, NULL },
226
+ { gen_helper_mve_vmlaldavsh, gen_helper_mve_vmlaldavxsh },
227
+ { gen_helper_mve_vmlaldavsw, gen_helper_mve_vmlaldavxsw },
228
+ { NULL, NULL },
229
+ };
230
+ return do_long_dual_acc(s, a, fns[a->size][a->x]);
231
+}
232
+
233
+static bool trans_VMLALDAV_U(DisasContext *s, arg_vmlaldav *a)
234
+{
235
+ static MVEGenDualAccOpFn * const fns[4][2] = {
236
+ { NULL, NULL },
237
+ { gen_helper_mve_vmlaldavuh, NULL },
238
+ { gen_helper_mve_vmlaldavuw, NULL },
239
+ { NULL, NULL },
240
+ };
241
+ return do_long_dual_acc(s, a, fns[a->size][a->x]);
242
+}
81
--
243
--
82
2.20.1
244
2.20.1
83
245
84
246
diff view generated by jsdifflib
1
We were previously using the default OSCCLK settings, which are
1
Implement the MVE insn VMLSLDAV, which multiplies source elements,
2
correct for the older MPS2 boards (mps2-an385, mps2-an386,
2
alternately adding and subtracting them, and accumulates into a
3
mps2-an500, mps2-an511), but wrong for the mps2-an505 and mps2-511
3
64-bit result in a pair of general purpose registers.
4
implemented in mps2-tz.c. Now we're setting the values explicitly we
5
can fix them to be correct.
6
4
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210215115138.20465-4-peter.maydell@linaro.org
7
Message-id: 20210617121628.20116-21-peter.maydell@linaro.org
11
---
8
---
12
hw/arm/mps2-tz.c | 4 ++--
9
target/arm/helper-mve.h | 5 +++++
13
1 file changed, 2 insertions(+), 2 deletions(-)
10
target/arm/mve.decode | 2 ++
11
target/arm/mve_helper.c | 5 +++++
12
target/arm/translate-mve.c | 11 +++++++++++
13
4 files changed, 23 insertions(+)
14
14
15
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
15
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/mps2-tz.c
17
--- a/target/arm/helper-mve.h
18
+++ b/hw/arm/mps2-tz.c
18
+++ b/target/arm/helper-mve.h
19
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmlaldavxsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
20
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
20
21
/* This will need to be per-FPGA image eventually */
21
DEF_HELPER_FLAGS_4(mve_vmlaldavuh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
22
qdev_prop_set_uint32(sccdev, "len-oscclk", 3);
22
DEF_HELPER_FLAGS_4(mve_vmlaldavuw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
23
- qdev_prop_set_uint32(sccdev, "oscclk[0]", 50000000);
23
+
24
- qdev_prop_set_uint32(sccdev, "oscclk[1]", 24576000);
24
+DEF_HELPER_FLAGS_4(mve_vmlsldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
25
+ qdev_prop_set_uint32(sccdev, "oscclk[0]", 40000000);
25
+DEF_HELPER_FLAGS_4(mve_vmlsldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
26
+ qdev_prop_set_uint32(sccdev, "oscclk[1]", 24580000);
26
+DEF_HELPER_FLAGS_4(mve_vmlsldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
27
qdev_prop_set_uint32(sccdev, "oscclk[2]", 25000000);
27
+DEF_HELPER_FLAGS_4(mve_vmlsldavxsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
28
sysbus_realize(SYS_BUS_DEVICE(scc), &error_fatal);
28
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
29
return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/mve.decode
31
+++ b/target/arm/mve.decode
32
@@ -XXX,XX +XXX,XX @@ VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=2
33
qn=%qn rdahi=%rdahi rdalo=%rdalo size=%size_16 &vmlaldav
34
VMLALDAV_S 1110 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 0 @vmlaldav
35
VMLALDAV_U 1111 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 0 @vmlaldav
36
+
37
+VMLSLDAV 1110 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav
38
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/mve_helper.c
41
+++ b/target/arm/mve_helper.c
42
@@ -XXX,XX +XXX,XX @@ DO_LDAV(vmlaldavxsw, 4, int32_t, true, +=, +=)
43
44
DO_LDAV(vmlaldavuh, 2, uint16_t, false, +=, +=)
45
DO_LDAV(vmlaldavuw, 4, uint32_t, false, +=, +=)
46
+
47
+DO_LDAV(vmlsldavsh, 2, int16_t, false, +=, -=)
48
+DO_LDAV(vmlsldavxsh, 2, int16_t, true, +=, -=)
49
+DO_LDAV(vmlsldavsw, 4, int32_t, false, +=, -=)
50
+DO_LDAV(vmlsldavxsw, 4, int32_t, true, +=, -=)
51
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/translate-mve.c
54
+++ b/target/arm/translate-mve.c
55
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLALDAV_U(DisasContext *s, arg_vmlaldav *a)
56
};
57
return do_long_dual_acc(s, a, fns[a->size][a->x]);
58
}
59
+
60
+static bool trans_VMLSLDAV(DisasContext *s, arg_vmlaldav *a)
61
+{
62
+ static MVEGenDualAccOpFn * const fns[4][2] = {
63
+ { NULL, NULL },
64
+ { gen_helper_mve_vmlsldavsh, gen_helper_mve_vmlsldavxsh },
65
+ { gen_helper_mve_vmlsldavsw, gen_helper_mve_vmlsldavxsw },
66
+ { NULL, NULL },
67
+ };
68
+ return do_long_dual_acc(s, a, fns[a->size][a->x]);
69
+}
30
--
70
--
31
2.20.1
71
2.20.1
32
72
33
73
diff view generated by jsdifflib
1
The omap_lcdc template header is already only included once, for
1
Implement the MVE VRMLALDAVH and VRMLSLDAVH insns, which accumulate
2
DEPTH==32, but it still has all the macro-driven parameterization
2
the results of a rounded multiply of pairs of elements into a 72-bit
3
for other depths. Expand out all the macros in the header.
3
accumulator, returning the top 64 bits in a pair of general purpose
4
registers.
4
5
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Message-id: 20210617121628.20116-22-peter.maydell@linaro.org
8
Message-id: 20210215103215.4944-6-peter.maydell@linaro.org
9
---
9
---
10
hw/display/omap_lcd_template.h | 67 ++++++++++++++--------------------
10
target/arm/helper-mve.h | 8 ++++++++
11
1 file changed, 28 insertions(+), 39 deletions(-)
11
target/arm/mve.decode | 7 +++++++
12
target/arm/mve_helper.c | 37 +++++++++++++++++++++++++++++++++++++
13
target/arm/translate-mve.c | 24 ++++++++++++++++++++++++
14
4 files changed, 76 insertions(+)
12
15
13
diff --git a/hw/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h
16
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/display/omap_lcd_template.h
18
--- a/target/arm/helper-mve.h
16
+++ b/hw/display/omap_lcd_template.h
19
+++ b/target/arm/helper-mve.h
20
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmlsldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
21
DEF_HELPER_FLAGS_4(mve_vmlsldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
22
DEF_HELPER_FLAGS_4(mve_vmlsldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
23
DEF_HELPER_FLAGS_4(mve_vmlsldavxsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
24
+
25
+DEF_HELPER_FLAGS_4(mve_vrmlaldavhsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
26
+DEF_HELPER_FLAGS_4(mve_vrmlaldavhxsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
27
+
28
+DEF_HELPER_FLAGS_4(mve_vrmlaldavhuw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
29
+
30
+DEF_HELPER_FLAGS_4(mve_vrmlsldavhsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
31
+DEF_HELPER_FLAGS_4(mve_vrmlsldavhxsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
32
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/mve.decode
35
+++ b/target/arm/mve.decode
36
@@ -XXX,XX +XXX,XX @@ VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=2
37
38
@vmlaldav .... .... . ... ... . ... . .... .... qm:3 . \
39
qn=%qn rdahi=%rdahi rdalo=%rdalo size=%size_16 &vmlaldav
40
+@vmlaldav_nosz .... .... . ... ... . ... . .... .... qm:3 . \
41
+ qn=%qn rdahi=%rdahi rdalo=%rdalo size=0 &vmlaldav
42
VMLALDAV_S 1110 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 0 @vmlaldav
43
VMLALDAV_U 1111 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 0 @vmlaldav
44
45
VMLSLDAV 1110 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav
46
+
47
+VRMLALDAVH_S 1110 1110 1 ... ... 0 ... x:1 1111 . 0 a:1 0 ... 0 @vmlaldav_nosz
48
+VRMLALDAVH_U 1111 1110 1 ... ... 0 ... x:1 1111 . 0 a:1 0 ... 0 @vmlaldav_nosz
49
+
50
+VRMLSLDAVH 1111 1110 1 ... ... 0 ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav_nosz
51
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/mve_helper.c
54
+++ b/target/arm/mve_helper.c
17
@@ -XXX,XX +XXX,XX @@
55
@@ -XXX,XX +XXX,XX @@
18
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19
*/
56
*/
20
57
21
-#if DEPTH == 32
58
#include "qemu/osdep.h"
22
-# define BPP 4
59
+#include "qemu/int128.h"
23
-# define PIXEL_TYPE uint32_t
60
#include "cpu.h"
24
-#else
61
#include "internals.h"
25
-# error unsupport depth
62
#include "vec_internal.h"
26
-#endif
63
@@ -XXX,XX +XXX,XX @@ DO_LDAV(vmlsldavsh, 2, int16_t, false, +=, -=)
27
-
64
DO_LDAV(vmlsldavxsh, 2, int16_t, true, +=, -=)
28
/*
65
DO_LDAV(vmlsldavsw, 4, int32_t, false, +=, -=)
29
* 2-bit colour
66
DO_LDAV(vmlsldavxsw, 4, int32_t, true, +=, -=)
30
*/
67
+
31
-static void glue(draw_line2_, DEPTH)(void *opaque,
68
+/*
32
- uint8_t *d, const uint8_t *s, int width, int deststep)
69
+ * Rounding multiply add long dual accumulate high: we must keep
33
+static void draw_line2_32(void *opaque, uint8_t *d, const uint8_t *s,
70
+ * a 72-bit internal accumulator value and return the top 64 bits.
34
+ int width, int deststep)
71
+ */
35
{
72
+#define DO_LDAVH(OP, ESIZE, TYPE, XCHG, EVENACC, ODDACC, TO128) \
36
uint16_t *pal = opaque;
73
+ uint64_t HELPER(glue(mve_, OP))(CPUARMState *env, void *vn, \
37
uint8_t v, r, g, b;
74
+ void *vm, uint64_t a) \
38
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line2_, DEPTH)(void *opaque,
75
+ { \
39
r = (pal[v & 3] >> 4) & 0xf0;
76
+ uint16_t mask = mve_element_mask(env); \
40
g = pal[v & 3] & 0xf0;
77
+ unsigned e; \
41
b = (pal[v & 3] << 4) & 0xf0;
78
+ TYPE *n = vn, *m = vm; \
42
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
79
+ Int128 acc = int128_lshift(TO128(a), 8); \
43
- d += BPP;
80
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
44
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
81
+ if (mask & 1) { \
45
+ d += 4;
82
+ if (e & 1) { \
46
v >>= 2;
83
+ acc = ODDACC(acc, TO128(n[H##ESIZE(e - 1 * XCHG)] * \
47
r = (pal[v & 3] >> 4) & 0xf0;
84
+ m[H##ESIZE(e)])); \
48
g = pal[v & 3] & 0xf0;
85
+ } else { \
49
b = (pal[v & 3] << 4) & 0xf0;
86
+ acc = EVENACC(acc, TO128(n[H##ESIZE(e + 1 * XCHG)] * \
50
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
87
+ m[H##ESIZE(e)])); \
51
- d += BPP;
88
+ } \
52
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
89
+ acc = int128_add(acc, 1 << 7); \
53
+ d += 4;
90
+ } \
54
v >>= 2;
91
+ } \
55
r = (pal[v & 3] >> 4) & 0xf0;
92
+ mve_advance_vpt(env); \
56
g = pal[v & 3] & 0xf0;
93
+ return int128_getlo(int128_rshift(acc, 8)); \
57
b = (pal[v & 3] << 4) & 0xf0;
94
+ }
58
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
95
+
59
- d += BPP;
96
+DO_LDAVH(vrmlaldavhsw, 4, int32_t, false, int128_add, int128_add, int128_makes64)
60
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
97
+DO_LDAVH(vrmlaldavhxsw, 4, int32_t, true, int128_add, int128_add, int128_makes64)
61
+ d += 4;
98
+
62
v >>= 2;
99
+DO_LDAVH(vrmlaldavhuw, 4, uint32_t, false, int128_add, int128_add, int128_make64)
63
r = (pal[v & 3] >> 4) & 0xf0;
100
+
64
g = pal[v & 3] & 0xf0;
101
+DO_LDAVH(vrmlsldavhsw, 4, int32_t, false, int128_add, int128_sub, int128_makes64)
65
b = (pal[v & 3] << 4) & 0xf0;
102
+DO_LDAVH(vrmlsldavhxsw, 4, int32_t, true, int128_add, int128_sub, int128_makes64)
66
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
103
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
67
- d += BPP;
104
index XXXXXXX..XXXXXXX 100644
68
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
105
--- a/target/arm/translate-mve.c
69
+ d += 4;
106
+++ b/target/arm/translate-mve.c
70
s ++;
107
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLSLDAV(DisasContext *s, arg_vmlaldav *a)
71
width -= 4;
108
};
72
} while (width > 0);
109
return do_long_dual_acc(s, a, fns[a->size][a->x]);
73
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line2_, DEPTH)(void *opaque,
74
/*
75
* 4-bit colour
76
*/
77
-static void glue(draw_line4_, DEPTH)(void *opaque,
78
- uint8_t *d, const uint8_t *s, int width, int deststep)
79
+static void draw_line4_32(void *opaque, uint8_t *d, const uint8_t *s,
80
+ int width, int deststep)
81
{
82
uint16_t *pal = opaque;
83
uint8_t v, r, g, b;
84
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line4_, DEPTH)(void *opaque,
85
r = (pal[v & 0xf] >> 4) & 0xf0;
86
g = pal[v & 0xf] & 0xf0;
87
b = (pal[v & 0xf] << 4) & 0xf0;
88
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
89
- d += BPP;
90
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
91
+ d += 4;
92
v >>= 4;
93
r = (pal[v & 0xf] >> 4) & 0xf0;
94
g = pal[v & 0xf] & 0xf0;
95
b = (pal[v & 0xf] << 4) & 0xf0;
96
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
97
- d += BPP;
98
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
99
+ d += 4;
100
s ++;
101
width -= 2;
102
} while (width > 0);
103
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line4_, DEPTH)(void *opaque,
104
/*
105
* 8-bit colour
106
*/
107
-static void glue(draw_line8_, DEPTH)(void *opaque,
108
- uint8_t *d, const uint8_t *s, int width, int deststep)
109
+static void draw_line8_32(void *opaque, uint8_t *d, const uint8_t *s,
110
+ int width, int deststep)
111
{
112
uint16_t *pal = opaque;
113
uint8_t v, r, g, b;
114
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line8_, DEPTH)(void *opaque,
115
r = (pal[v] >> 4) & 0xf0;
116
g = pal[v] & 0xf0;
117
b = (pal[v] << 4) & 0xf0;
118
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
119
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
120
s ++;
121
- d += BPP;
122
+ d += 4;
123
} while (-- width != 0);
124
}
110
}
125
111
+
126
/*
112
+static bool trans_VRMLALDAVH_S(DisasContext *s, arg_vmlaldav *a)
127
* 12-bit colour
113
+{
128
*/
114
+ static MVEGenDualAccOpFn * const fns[] = {
129
-static void glue(draw_line12_, DEPTH)(void *opaque,
115
+ gen_helper_mve_vrmlaldavhsw, gen_helper_mve_vrmlaldavhxsw,
130
- uint8_t *d, const uint8_t *s, int width, int deststep)
116
+ };
131
+static void draw_line12_32(void *opaque, uint8_t *d, const uint8_t *s,
117
+ return do_long_dual_acc(s, a, fns[a->x]);
132
+ int width, int deststep)
118
+}
133
{
119
+
134
uint16_t v;
120
+static bool trans_VRMLALDAVH_U(DisasContext *s, arg_vmlaldav *a)
135
uint8_t r, g, b;
121
+{
136
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line12_, DEPTH)(void *opaque,
122
+ static MVEGenDualAccOpFn * const fns[] = {
137
r = (v >> 4) & 0xf0;
123
+ gen_helper_mve_vrmlaldavhuw, NULL,
138
g = v & 0xf0;
124
+ };
139
b = (v << 4) & 0xf0;
125
+ return do_long_dual_acc(s, a, fns[a->x]);
140
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
126
+}
141
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
127
+
142
s += 2;
128
+static bool trans_VRMLSLDAVH(DisasContext *s, arg_vmlaldav *a)
143
- d += BPP;
129
+{
144
+ d += 4;
130
+ static MVEGenDualAccOpFn * const fns[] = {
145
} while (-- width != 0);
131
+ gen_helper_mve_vrmlsldavhsw, gen_helper_mve_vrmlsldavhxsw,
146
}
132
+ };
147
133
+ return do_long_dual_acc(s, a, fns[a->x]);
148
/*
134
+}
149
* 16-bit colour
150
*/
151
-static void glue(draw_line16_, DEPTH)(void *opaque,
152
- uint8_t *d, const uint8_t *s, int width, int deststep)
153
+static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
154
+ int width, int deststep)
155
{
156
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
157
memcpy(d, s, width * 2);
158
@@ -XXX,XX +XXX,XX @@ static void glue(draw_line16_, DEPTH)(void *opaque,
159
r = (v >> 8) & 0xf8;
160
g = (v >> 3) & 0xfc;
161
b = (v << 3) & 0xf8;
162
- ((PIXEL_TYPE *) d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
163
+ ((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
164
s += 2;
165
- d += BPP;
166
+ d += 4;
167
} while (-- width != 0);
168
#endif
169
}
170
-
171
-#undef DEPTH
172
-#undef BPP
173
-#undef PIXEL_TYPE
174
--
135
--
175
2.20.1
136
2.20.1
176
137
177
138
diff view generated by jsdifflib
1
The MPS2 board has 2 LEDs, but the MPS3 board has 10 LEDs. The
1
Implement the scalar form of the MVE VADD insn. This takes the
2
FPGAIO device is similar on both sets of boards, but the LED0
2
scalar operand from a general purpose register.
3
register has correspondingly more bits that have an effect. Add a
4
device property for number of LEDs.
5
3
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210215115138.20465-6-peter.maydell@linaro.org
6
Message-id: 20210617121628.20116-23-peter.maydell@linaro.org
10
---
7
---
11
include/hw/misc/mps2-fpgaio.h | 5 ++++-
8
target/arm/helper-mve.h | 4 ++++
12
hw/misc/mps2-fpgaio.c | 31 +++++++++++++++++++++++--------
9
target/arm/mve.decode | 7 ++++++
13
2 files changed, 27 insertions(+), 9 deletions(-)
10
target/arm/mve_helper.c | 22 +++++++++++++++++++
11
target/arm/translate-mve.c | 45 ++++++++++++++++++++++++++++++++++++++
12
4 files changed, 78 insertions(+)
14
13
15
diff --git a/include/hw/misc/mps2-fpgaio.h b/include/hw/misc/mps2-fpgaio.h
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/include/hw/misc/mps2-fpgaio.h
16
--- a/target/arm/helper-mve.h
18
+++ b/include/hw/misc/mps2-fpgaio.h
17
+++ b/target/arm/helper-mve.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmulltub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
DEF_HELPER_FLAGS_4(mve_vmulltuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
DEF_HELPER_FLAGS_4(mve_vmulltuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
22
+DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
23
+DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
+DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
+
26
DEF_HELPER_FLAGS_4(mve_vmlaldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
27
DEF_HELPER_FLAGS_4(mve_vmlaldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
28
DEF_HELPER_FLAGS_4(mve_vmlaldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
29
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/mve.decode
32
+++ b/target/arm/mve.decode
19
@@ -XXX,XX +XXX,XX @@
33
@@ -XXX,XX +XXX,XX @@
20
#define TYPE_MPS2_FPGAIO "mps2-fpgaio"
34
&vldr_vstr rn qd imm p a w size l u
21
OBJECT_DECLARE_SIMPLE_TYPE(MPS2FPGAIO, MPS2_FPGAIO)
35
&1op qd qm size
22
36
&2op qd qm qn size
23
+#define MPS2FPGAIO_MAX_LEDS 32
37
+&2scalar qd qn rm size
38
39
@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
40
# Note that both Rn and Qd are 3 bits only (no D bit)
41
@@ -XXX,XX +XXX,XX @@
42
@2op .... .... .. size:2 .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn
43
@2op_nosz .... .... .... .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn size=0
44
45
+@2scalar .... .... .. size:2 .... .... .... .... rm:4 &2scalar qd=%qd qn=%qn
24
+
46
+
25
struct MPS2FPGAIO {
47
# Vector loads and stores
26
/*< private >*/
48
27
SysBusDevice parent_obj;
49
# Widening loads and narrowing stores:
28
50
@@ -XXX,XX +XXX,XX @@ VRMLALDAVH_S 1110 1110 1 ... ... 0 ... x:1 1111 . 0 a:1 0 ... 0 @vmlaldav_no
29
/*< public >*/
51
VRMLALDAVH_U 1111 1110 1 ... ... 0 ... x:1 1111 . 0 a:1 0 ... 0 @vmlaldav_nosz
30
MemoryRegion iomem;
52
31
- LEDState *led[2];
53
VRMLSLDAVH 1111 1110 1 ... ... 0 ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav_nosz
32
+ LEDState *led[MPS2FPGAIO_MAX_LEDS];
54
+
33
+ uint32_t num_leds;
55
+# Scalar operations
34
56
+
35
uint32_t led0;
57
+VADD_scalar 1110 1110 0 . .. ... 1 ... 0 1111 . 100 .... @2scalar
36
uint32_t prescale;
58
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
37
diff --git a/hw/misc/mps2-fpgaio.c b/hw/misc/mps2-fpgaio.c
38
index XXXXXXX..XXXXXXX 100644
59
index XXXXXXX..XXXXXXX 100644
39
--- a/hw/misc/mps2-fpgaio.c
60
--- a/target/arm/mve_helper.c
40
+++ b/hw/misc/mps2-fpgaio.c
61
+++ b/target/arm/mve_helper.c
41
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_write(void *opaque, hwaddr offset, uint64_t value,
62
@@ -XXX,XX +XXX,XX @@ DO_2OP_S(vhsubs, do_vhsub_s)
42
63
DO_2OP_U(vhsubu, do_vhsub_u)
43
switch (offset) {
64
44
case A_LED0:
65
45
- s->led0 = value & 0x3;
66
+#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
46
- led_set_state(s->led[0], value & 0x01);
67
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
47
- led_set_state(s->led[1], value & 0x02);
68
+ uint32_t rm) \
48
+ if (s->num_leds != 0) {
69
+ { \
49
+ uint32_t i;
70
+ TYPE *d = vd, *n = vn; \
50
+
71
+ TYPE m = rm; \
51
+ s->led0 = value & MAKE_64BIT_MASK(0, s->num_leds);
72
+ uint16_t mask = mve_element_mask(env); \
52
+ for (i = 0; i < s->num_leds; i++) {
73
+ unsigned e; \
53
+ led_set_state(s->led[i], value & (1 << i));
74
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
54
+ }
75
+ mergemask(&d[H##ESIZE(e)], FN(n[H##ESIZE(e)], m), mask); \
55
+ }
76
+ } \
56
break;
77
+ mve_advance_vpt(env); \
57
case A_PRESCALE:
58
resync_counter(s);
59
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_reset(DeviceState *dev)
60
s->pscntr = 0;
61
s->pscntr_sync_ticks = now;
62
63
- for (size_t i = 0; i < ARRAY_SIZE(s->led); i++) {
64
+ for (size_t i = 0; i < s->num_leds; i++) {
65
device_cold_reset(DEVICE(s->led[i]));
66
}
67
}
68
@@ -XXX,XX +XXX,XX @@ static void mps2_fpgaio_init(Object *obj)
69
static void mps2_fpgaio_realize(DeviceState *dev, Error **errp)
70
{
71
MPS2FPGAIO *s = MPS2_FPGAIO(dev);
72
+ uint32_t i;
73
74
- s->led[0] = led_create_simple(OBJECT(dev), GPIO_POLARITY_ACTIVE_HIGH,
75
- LED_COLOR_GREEN, "USERLED0");
76
- s->led[1] = led_create_simple(OBJECT(dev), GPIO_POLARITY_ACTIVE_HIGH,
77
- LED_COLOR_GREEN, "USERLED1");
78
+ if (s->num_leds > MPS2FPGAIO_MAX_LEDS) {
79
+ error_setg(errp, "num-leds cannot be greater than %d",
80
+ MPS2FPGAIO_MAX_LEDS);
81
+ return;
82
+ }
78
+ }
83
+
79
+
84
+ for (i = 0; i < s->num_leds; i++) {
80
+/* provide unsigned 2-op scalar helpers for all sizes */
85
+ g_autofree char *ledname = g_strdup_printf("USERLED%d", i);
81
+#define DO_2OP_SCALAR_U(OP, FN) \
86
+ s->led[i] = led_create_simple(OBJECT(dev), GPIO_POLARITY_ACTIVE_HIGH,
82
+ DO_2OP_SCALAR(OP##b, 1, uint8_t, FN) \
87
+ LED_COLOR_GREEN, ledname);
83
+ DO_2OP_SCALAR(OP##h, 2, uint16_t, FN) \
84
+ DO_2OP_SCALAR(OP##w, 4, uint32_t, FN)
85
+
86
+DO_2OP_SCALAR_U(vadd_scalar, DO_ADD)
87
+
88
/*
89
* Multiply add long dual accumulate ops.
90
*/
91
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
92
index XXXXXXX..XXXXXXX 100644
93
--- a/target/arm/translate-mve.c
94
+++ b/target/arm/translate-mve.c
95
@@ -XXX,XX +XXX,XX @@
96
typedef void MVEGenLdStFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
97
typedef void MVEGenOneOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
98
typedef void MVEGenTwoOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr);
99
+typedef void MVEGenTwoOpScalarFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
100
typedef void MVEGenDualAccOpFn(TCGv_i64, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i64);
101
102
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
103
@@ -XXX,XX +XXX,XX @@ DO_2OP(VMULL_BU, vmullbu)
104
DO_2OP(VMULL_TS, vmullts)
105
DO_2OP(VMULL_TU, vmulltu)
106
107
+static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
108
+ MVEGenTwoOpScalarFn fn)
109
+{
110
+ TCGv_ptr qd, qn;
111
+ TCGv_i32 rm;
112
+
113
+ if (!dc_isar_feature(aa32_mve, s) ||
114
+ !mve_check_qreg_bank(s, a->qd | a->qn) ||
115
+ !fn) {
116
+ return false;
88
+ }
117
+ }
89
}
118
+ if (a->rm == 13 || a->rm == 15) {
90
119
+ /* UNPREDICTABLE */
91
static bool mps2_fpgaio_counters_needed(void *opaque)
120
+ return false;
92
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription mps2_fpgaio_vmstate = {
121
+ }
93
static Property mps2_fpgaio_properties[] = {
122
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
94
/* Frequency of the prescale counter */
123
+ return true;
95
DEFINE_PROP_UINT32("prescale-clk", MPS2FPGAIO, prescale_clk, 20000000),
124
+ }
96
+ /* Number of LEDs controlled by LED0 register */
125
+
97
+ DEFINE_PROP_UINT32("num-leds", MPS2FPGAIO, num_leds, 2),
126
+ qd = mve_qreg_ptr(a->qd);
98
DEFINE_PROP_END_OF_LIST(),
127
+ qn = mve_qreg_ptr(a->qn);
99
};
128
+ rm = load_reg(s, a->rm);
100
129
+ fn(cpu_env, qd, qn, rm);
130
+ tcg_temp_free_i32(rm);
131
+ tcg_temp_free_ptr(qd);
132
+ tcg_temp_free_ptr(qn);
133
+ mve_update_eci(s);
134
+ return true;
135
+}
136
+
137
+#define DO_2OP_SCALAR(INSN, FN) \
138
+ static bool trans_##INSN(DisasContext *s, arg_2scalar *a) \
139
+ { \
140
+ static MVEGenTwoOpScalarFn * const fns[] = { \
141
+ gen_helper_mve_##FN##b, \
142
+ gen_helper_mve_##FN##h, \
143
+ gen_helper_mve_##FN##w, \
144
+ NULL, \
145
+ }; \
146
+ return do_2op_scalar(s, a, fns[a->size]); \
147
+ }
148
+
149
+DO_2OP_SCALAR(VADD_scalar, vadd_scalar)
150
+
151
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
152
MVEGenDualAccOpFn *fn)
153
{
101
--
154
--
102
2.20.1
155
2.20.1
103
156
104
157
diff view generated by jsdifflib
1
Currently the MPS2 SCC device implements a fixed number of OSCCLK
1
Implement the scalar forms of the MVE VSUB and VMUL insns.
2
values (3). The variant of this device in the MPS3 AN524 board has 6
3
OSCCLK values. Switch to using a PROP_ARRAY, which allows board code
4
to specify how large the OSCCLK array should be as well as its
5
values.
6
7
With a variable-length property array, the SCC no longer specifies
8
default values for the OSCCLKs, so we must set them explicitly in the
9
board code. This defaults are actually incorrect for the an521 and
10
an505; we will correct this bug in a following patch.
11
12
This is a migration compatibility break for all the mps boards.
13
2
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20210215115138.20465-3-peter.maydell@linaro.org
5
Message-id: 20210617121628.20116-24-peter.maydell@linaro.org
18
---
6
---
19
include/hw/misc/mps2-scc.h | 7 +++----
7
target/arm/helper-mve.h | 8 ++++++++
20
hw/arm/mps2-tz.c | 5 +++++
8
target/arm/mve.decode | 2 ++
21
hw/arm/mps2.c | 5 +++++
9
target/arm/mve_helper.c | 2 ++
22
hw/misc/mps2-scc.c | 24 +++++++++++++-----------
10
target/arm/translate-mve.c | 2 ++
23
4 files changed, 26 insertions(+), 15 deletions(-)
11
4 files changed, 14 insertions(+)
24
12
25
diff --git a/include/hw/misc/mps2-scc.h b/include/hw/misc/mps2-scc.h
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
26
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
27
--- a/include/hw/misc/mps2-scc.h
15
--- a/target/arm/helper-mve.h
28
+++ b/include/hw/misc/mps2-scc.h
16
+++ b/target/arm/helper-mve.h
29
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
30
#define TYPE_MPS2_SCC "mps2-scc"
18
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
OBJECT_DECLARE_SIMPLE_TYPE(MPS2SCC, MPS2_SCC)
19
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
32
20
33
-#define NUM_OSCCLK 3
21
+DEF_HELPER_FLAGS_4(mve_vsub_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
34
-
22
+DEF_HELPER_FLAGS_4(mve_vsub_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
35
struct MPS2SCC {
23
+DEF_HELPER_FLAGS_4(mve_vsub_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
36
/*< private >*/
24
+
37
SysBusDevice parent_obj;
25
+DEF_HELPER_FLAGS_4(mve_vmul_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
38
@@ -XXX,XX +XXX,XX @@ struct MPS2SCC {
26
+DEF_HELPER_FLAGS_4(mve_vmul_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
39
uint32_t dll;
27
+DEF_HELPER_FLAGS_4(mve_vmul_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
40
uint32_t aid;
28
+
41
uint32_t id;
29
DEF_HELPER_FLAGS_4(mve_vmlaldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
42
- uint32_t oscclk[NUM_OSCCLK];
30
DEF_HELPER_FLAGS_4(mve_vmlaldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
43
- uint32_t oscclk_reset[NUM_OSCCLK];
31
DEF_HELPER_FLAGS_4(mve_vmlaldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
44
+ uint32_t num_oscclk;
32
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
45
+ uint32_t *oscclk;
46
+ uint32_t *oscclk_reset;
47
};
48
49
#endif
50
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
51
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
52
--- a/hw/arm/mps2-tz.c
34
--- a/target/arm/mve.decode
53
+++ b/hw/arm/mps2-tz.c
35
+++ b/target/arm/mve.decode
54
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_scc(MPS2TZMachineState *mms, void *opaque,
36
@@ -XXX,XX +XXX,XX @@ VRMLSLDAVH 1111 1110 1 ... ... 0 ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav_no
55
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
37
# Scalar operations
56
qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008);
38
57
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
39
VADD_scalar 1110 1110 0 . .. ... 1 ... 0 1111 . 100 .... @2scalar
58
+ /* This will need to be per-FPGA image eventually */
40
+VSUB_scalar 1110 1110 0 . .. ... 1 ... 1 1111 . 100 .... @2scalar
59
+ qdev_prop_set_uint32(sccdev, "len-oscclk", 3);
41
+VMUL_scalar 1110 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
60
+ qdev_prop_set_uint32(sccdev, "oscclk[0]", 50000000);
42
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
61
+ qdev_prop_set_uint32(sccdev, "oscclk[1]", 24576000);
62
+ qdev_prop_set_uint32(sccdev, "oscclk[2]", 25000000);
63
sysbus_realize(SYS_BUS_DEVICE(scc), &error_fatal);
64
return sysbus_mmio_get_region(SYS_BUS_DEVICE(sccdev), 0);
65
}
66
diff --git a/hw/arm/mps2.c b/hw/arm/mps2.c
67
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
68
--- a/hw/arm/mps2.c
44
--- a/target/arm/mve_helper.c
69
+++ b/hw/arm/mps2.c
45
+++ b/target/arm/mve_helper.c
70
@@ -XXX,XX +XXX,XX @@ static void mps2_common_init(MachineState *machine)
46
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vhsubu, do_vhsub_u)
71
qdev_prop_set_uint32(sccdev, "scc-cfg4", 0x2);
47
DO_2OP_SCALAR(OP##w, 4, uint32_t, FN)
72
qdev_prop_set_uint32(sccdev, "scc-aid", 0x00200008);
48
73
qdev_prop_set_uint32(sccdev, "scc-id", mmc->scc_id);
49
DO_2OP_SCALAR_U(vadd_scalar, DO_ADD)
74
+ /* All these FPGA images have the same OSCCLK configuration */
50
+DO_2OP_SCALAR_U(vsub_scalar, DO_SUB)
75
+ qdev_prop_set_uint32(sccdev, "len-oscclk", 3);
51
+DO_2OP_SCALAR_U(vmul_scalar, DO_MUL)
76
+ qdev_prop_set_uint32(sccdev, "oscclk[0]", 50000000);
52
77
+ qdev_prop_set_uint32(sccdev, "oscclk[1]", 24576000);
53
/*
78
+ qdev_prop_set_uint32(sccdev, "oscclk[2]", 25000000);
54
* Multiply add long dual accumulate ops.
79
sysbus_realize(SYS_BUS_DEVICE(&mms->scc), &error_fatal);
55
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
80
sysbus_mmio_map(SYS_BUS_DEVICE(sccdev), 0, 0x4002f000);
81
object_initialize_child(OBJECT(mms), "fpgaio",
82
diff --git a/hw/misc/mps2-scc.c b/hw/misc/mps2-scc.c
83
index XXXXXXX..XXXXXXX 100644
56
index XXXXXXX..XXXXXXX 100644
84
--- a/hw/misc/mps2-scc.c
57
--- a/target/arm/translate-mve.c
85
+++ b/hw/misc/mps2-scc.c
58
+++ b/target/arm/translate-mve.c
86
@@ -XXX,XX +XXX,XX @@ static bool scc_cfg_write(MPS2SCC *s, unsigned function,
59
@@ -XXX,XX +XXX,XX @@ static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
87
{
88
trace_mps2_scc_cfg_write(function, device, value);
89
90
- if (function != 1 || device >= NUM_OSCCLK) {
91
+ if (function != 1 || device >= s->num_oscclk) {
92
qemu_log_mask(LOG_GUEST_ERROR,
93
"MPS2 SCC config write: bad function %d device %d\n",
94
function, device);
95
@@ -XXX,XX +XXX,XX @@ static bool scc_cfg_write(MPS2SCC *s, unsigned function,
96
static bool scc_cfg_read(MPS2SCC *s, unsigned function,
97
unsigned device, uint32_t *value)
98
{
99
- if (function != 1 || device >= NUM_OSCCLK) {
100
+ if (function != 1 || device >= s->num_oscclk) {
101
qemu_log_mask(LOG_GUEST_ERROR,
102
"MPS2 SCC config read: bad function %d device %d\n",
103
function, device);
104
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_reset(DeviceState *dev)
105
s->cfgctrl = 0x100000;
106
s->cfgstat = 0;
107
s->dll = 0xffff0001;
108
- for (i = 0; i < NUM_OSCCLK; i++) {
109
+ for (i = 0; i < s->num_oscclk; i++) {
110
s->oscclk[i] = s->oscclk_reset[i];
111
}
60
}
112
for (i = 0; i < ARRAY_SIZE(s->led); i++) {
61
113
@@ -XXX,XX +XXX,XX @@ static void mps2_scc_realize(DeviceState *dev, Error **errp)
62
DO_2OP_SCALAR(VADD_scalar, vadd_scalar)
114
LED_COLOR_GREEN, name);
63
+DO_2OP_SCALAR(VSUB_scalar, vsub_scalar)
115
g_free(name);
64
+DO_2OP_SCALAR(VMUL_scalar, vmul_scalar)
116
}
65
117
+
66
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
118
+ s->oscclk = g_new0(uint32_t, s->num_oscclk);
67
MVEGenDualAccOpFn *fn)
119
}
120
121
static const VMStateDescription mps2_scc_vmstate = {
122
.name = "mps2-scc",
123
- .version_id = 1,
124
- .minimum_version_id = 1,
125
+ .version_id = 2,
126
+ .minimum_version_id = 2,
127
.fields = (VMStateField[]) {
128
VMSTATE_UINT32(cfg0, MPS2SCC),
129
VMSTATE_UINT32(cfg1, MPS2SCC),
130
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription mps2_scc_vmstate = {
131
VMSTATE_UINT32(cfgctrl, MPS2SCC),
132
VMSTATE_UINT32(cfgstat, MPS2SCC),
133
VMSTATE_UINT32(dll, MPS2SCC),
134
- VMSTATE_UINT32_ARRAY(oscclk, MPS2SCC, NUM_OSCCLK),
135
+ VMSTATE_VARRAY_UINT32(oscclk, MPS2SCC, num_oscclk,
136
+ 0, vmstate_info_uint32, uint32_t),
137
VMSTATE_END_OF_LIST()
138
}
139
};
140
@@ -XXX,XX +XXX,XX @@ static Property mps2_scc_properties[] = {
141
DEFINE_PROP_UINT32("scc-cfg4", MPS2SCC, cfg4, 0),
142
DEFINE_PROP_UINT32("scc-aid", MPS2SCC, aid, 0),
143
DEFINE_PROP_UINT32("scc-id", MPS2SCC, id, 0),
144
- /* These are the initial settings for the source clocks on the board.
145
+ /*
146
+ * These are the initial settings for the source clocks on the board.
147
* In hardware they can be configured via a config file read by the
148
* motherboard configuration controller to suit the FPGA image.
149
- * These default values are used by most of the standard FPGA images.
150
*/
151
- DEFINE_PROP_UINT32("oscclk0", MPS2SCC, oscclk_reset[0], 50000000),
152
- DEFINE_PROP_UINT32("oscclk1", MPS2SCC, oscclk_reset[1], 24576000),
153
- DEFINE_PROP_UINT32("oscclk2", MPS2SCC, oscclk_reset[2], 25000000),
154
+ DEFINE_PROP_ARRAY("oscclk", MPS2SCC, num_oscclk, oscclk_reset,
155
+ qdev_prop_uint32, uint32_t),
156
DEFINE_PROP_END_OF_LIST(),
157
};
158
159
--
68
--
160
2.20.1
69
2.20.1
161
70
162
71
diff view generated by jsdifflib
1
For a long time now the UI layer has guaranteed that the console
1
Implement the scalar variants of the MVE VHADD and VHSUB insns.
2
surface is always 32 bits per pixel, RGB. The TCX code already
3
assumes 32bpp, but it still has some checks of is_surface_bgr()
4
in an attempt to support 32bpp BGR. is_surface_bgr() will always
5
return false for the qemu_console_surface(), unless the display
6
device itself has deliberately created an alternate-format
7
surface via a function like qemu_create_displaysurface_from().
8
9
Drop the never-used BGR-handling code, and assert that we have
10
a 32-bit surface rather than just doing nothing if it isn't.
11
2
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20210215102149.20513-1-peter.maydell@linaro.org
5
Message-id: 20210617121628.20116-25-peter.maydell@linaro.org
16
---
6
---
17
hw/display/tcx.c | 31 ++++++++-----------------------
7
target/arm/helper-mve.h | 16 ++++++++++++++++
18
1 file changed, 8 insertions(+), 23 deletions(-)
8
target/arm/mve.decode | 4 ++++
9
target/arm/mve_helper.c | 8 ++++++++
10
target/arm/translate-mve.c | 4 ++++
11
4 files changed, 32 insertions(+)
19
12
20
diff --git a/hw/display/tcx.c b/hw/display/tcx.c
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
21
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/display/tcx.c
15
--- a/target/arm/helper-mve.h
23
+++ b/hw/display/tcx.c
16
+++ b/target/arm/helper-mve.h
24
@@ -XXX,XX +XXX,XX @@ static int tcx_check_dirty(TCXState *s, DirtyBitmapSnapshot *snap,
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmul_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
18
DEF_HELPER_FLAGS_4(mve_vmul_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
26
static void update_palette_entries(TCXState *s, int start, int end)
19
DEF_HELPER_FLAGS_4(mve_vmul_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
27
{
20
28
- DisplaySurface *surface = qemu_console_surface(s->con);
21
+DEF_HELPER_FLAGS_4(mve_vhadds_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
29
int i;
22
+DEF_HELPER_FLAGS_4(mve_vhadds_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
30
23
+DEF_HELPER_FLAGS_4(mve_vhadds_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
for (i = start; i < end; i++) {
24
+
32
- if (is_surface_bgr(surface)) {
25
+DEF_HELPER_FLAGS_4(mve_vhaddu_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
33
- s->palette[i] = rgb_to_pixel32bgr(s->r[i], s->g[i], s->b[i]);
26
+DEF_HELPER_FLAGS_4(mve_vhaddu_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
34
- } else {
27
+DEF_HELPER_FLAGS_4(mve_vhaddu_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
35
- s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
28
+
36
- }
29
+DEF_HELPER_FLAGS_4(mve_vhsubs_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
37
+ s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]);
30
+DEF_HELPER_FLAGS_4(mve_vhsubs_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
38
}
31
+DEF_HELPER_FLAGS_4(mve_vhsubs_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
39
tcx_set_dirty(s, 0, memory_region_size(&s->vram_mem));
32
+
40
}
33
+DEF_HELPER_FLAGS_4(mve_vhsubu_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
41
@@ -XXX,XX +XXX,XX @@ static void tcx_draw_cursor32(TCXState *s1, uint8_t *d,
34
+DEF_HELPER_FLAGS_4(mve_vhsubu_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
42
}
35
+DEF_HELPER_FLAGS_4(mve_vhsubu_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
36
+
37
DEF_HELPER_FLAGS_4(mve_vmlaldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
38
DEF_HELPER_FLAGS_4(mve_vmlaldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
39
DEF_HELPER_FLAGS_4(mve_vmlaldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
40
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/mve.decode
43
+++ b/target/arm/mve.decode
44
@@ -XXX,XX +XXX,XX @@ VRMLSLDAVH 1111 1110 1 ... ... 0 ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav_no
45
VADD_scalar 1110 1110 0 . .. ... 1 ... 0 1111 . 100 .... @2scalar
46
VSUB_scalar 1110 1110 0 . .. ... 1 ... 1 1111 . 100 .... @2scalar
47
VMUL_scalar 1110 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
48
+VHADD_S_scalar 1110 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
49
+VHADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
50
+VHSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
51
+VHSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
52
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/mve_helper.c
55
+++ b/target/arm/mve_helper.c
56
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vhsubu, do_vhsub_u)
57
DO_2OP_SCALAR(OP##b, 1, uint8_t, FN) \
58
DO_2OP_SCALAR(OP##h, 2, uint16_t, FN) \
59
DO_2OP_SCALAR(OP##w, 4, uint32_t, FN)
60
+#define DO_2OP_SCALAR_S(OP, FN) \
61
+ DO_2OP_SCALAR(OP##b, 1, int8_t, FN) \
62
+ DO_2OP_SCALAR(OP##h, 2, int16_t, FN) \
63
+ DO_2OP_SCALAR(OP##w, 4, int32_t, FN)
64
65
DO_2OP_SCALAR_U(vadd_scalar, DO_ADD)
66
DO_2OP_SCALAR_U(vsub_scalar, DO_SUB)
67
DO_2OP_SCALAR_U(vmul_scalar, DO_MUL)
68
+DO_2OP_SCALAR_S(vhadds_scalar, do_vhadd_s)
69
+DO_2OP_SCALAR_U(vhaddu_scalar, do_vhadd_u)
70
+DO_2OP_SCALAR_S(vhsubs_scalar, do_vhsub_s)
71
+DO_2OP_SCALAR_U(vhsubu_scalar, do_vhsub_u)
43
72
44
/*
73
/*
45
- XXX Could be much more optimal:
74
* Multiply add long dual accumulate ops.
46
- * detect if line/page/whole screen is in 24 bit mode
75
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
47
- * if destination is also BGR, use memcpy
76
index XXXXXXX..XXXXXXX 100644
48
- */
77
--- a/target/arm/translate-mve.c
49
+ * XXX Could be much more optimal:
78
+++ b/target/arm/translate-mve.c
50
+ * detect if line/page/whole screen is in 24 bit mode
79
@@ -XXX,XX +XXX,XX @@ static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
51
+ */
80
DO_2OP_SCALAR(VADD_scalar, vadd_scalar)
52
static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
81
DO_2OP_SCALAR(VSUB_scalar, vsub_scalar)
53
const uint8_t *s, int width,
82
DO_2OP_SCALAR(VMUL_scalar, vmul_scalar)
54
const uint32_t *cplane,
83
+DO_2OP_SCALAR(VHADD_S_scalar, vhadds_scalar)
55
const uint32_t *s24)
84
+DO_2OP_SCALAR(VHADD_U_scalar, vhaddu_scalar)
56
{
85
+DO_2OP_SCALAR(VHSUB_S_scalar, vhsubs_scalar)
57
- DisplaySurface *surface = qemu_console_surface(s1->con);
86
+DO_2OP_SCALAR(VHSUB_U_scalar, vhsubu_scalar)
58
- int x, bgr, r, g, b;
87
59
+ int x, r, g, b;
88
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
60
uint8_t val, *p8;
89
MVEGenDualAccOpFn *fn)
61
uint32_t *p = (uint32_t *)d;
62
uint32_t dval;
63
- bgr = is_surface_bgr(surface);
64
for(x = 0; x < width; x++, s++, s24++) {
65
if (be32_to_cpu(*cplane) & 0x03000000) {
66
/* 24-bit direct, BGR order */
67
@@ -XXX,XX +XXX,XX @@ static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
68
b = *p8++;
69
g = *p8++;
70
r = *p8;
71
- if (bgr)
72
- dval = rgb_to_pixel32bgr(r, g, b);
73
- else
74
- dval = rgb_to_pixel32(r, g, b);
75
+ dval = rgb_to_pixel32(r, g, b);
76
} else {
77
/* 8-bit pseudocolor */
78
val = *s;
79
@@ -XXX,XX +XXX,XX @@ static void tcx_update_display(void *opaque)
80
int y, y_start, dd, ds;
81
uint8_t *d, *s;
82
83
- if (surface_bits_per_pixel(surface) != 32) {
84
- return;
85
- }
86
+ assert(surface_bits_per_pixel(surface) == 32);
87
88
page = 0;
89
y_start = -1;
90
@@ -XXX,XX +XXX,XX @@ static void tcx24_update_display(void *opaque)
91
uint8_t *d, *s;
92
uint32_t *cptr, *s24;
93
94
- if (surface_bits_per_pixel(surface) != 32) {
95
- return;
96
- }
97
+ assert(surface_bits_per_pixel(surface) == 32);
98
99
page = 0;
100
y_start = -1;
101
--
90
--
102
2.20.1
91
2.20.1
103
92
104
93
diff view generated by jsdifflib
1
Instead of hardcoding the MachineClass default_ram_size and
1
Implement the MVE VBRSR insn, which reverses a specified
2
default_ram_id fields, set them on class creation by finding the
2
number of bits in each element, setting the rest to zero.
3
entry in the RAMInfo array which is marked as being the QEMU system
4
RAM.
5
3
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215115138.20465-18-peter.maydell@linaro.org
6
Message-id: 20210617121628.20116-26-peter.maydell@linaro.org
9
---
7
---
10
hw/arm/mps2-tz.c | 24 ++++++++++++++++++++++--
8
target/arm/helper-mve.h | 4 ++++
11
1 file changed, 22 insertions(+), 2 deletions(-)
9
target/arm/mve.decode | 1 +
10
target/arm/mve_helper.c | 43 ++++++++++++++++++++++++++++++++++++++
11
target/arm/translate-mve.c | 1 +
12
4 files changed, 49 insertions(+)
12
13
13
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/mps2-tz.c
16
--- a/target/arm/helper-mve.h
16
+++ b/hw/arm/mps2-tz.c
17
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ static void mps2tz_class_init(ObjectClass *oc, void *data)
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vhsubu_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
18
19
DEF_HELPER_FLAGS_4(mve_vhsubu_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
19
mc->init = mps2tz_common_init;
20
DEF_HELPER_FLAGS_4(mve_vhsubu_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
20
iic->check = mps2_tz_idau_check;
21
21
- mc->default_ram_size = 16 * MiB;
22
+DEF_HELPER_FLAGS_4(mve_vbrsrb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
22
- mc->default_ram_id = "mps.ram";
23
+DEF_HELPER_FLAGS_4(mve_vbrsrh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
+DEF_HELPER_FLAGS_4(mve_vbrsrw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
+
26
DEF_HELPER_FLAGS_4(mve_vmlaldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
27
DEF_HELPER_FLAGS_4(mve_vmlaldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
28
DEF_HELPER_FLAGS_4(mve_vmlaldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
29
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/mve.decode
32
+++ b/target/arm/mve.decode
33
@@ -XXX,XX +XXX,XX @@ VHADD_S_scalar 1110 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
34
VHADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
35
VHSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
36
VHSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
37
+VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
38
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/mve_helper.c
41
+++ b/target/arm/mve_helper.c
42
@@ -XXX,XX +XXX,XX @@ DO_2OP_SCALAR_U(vhaddu_scalar, do_vhadd_u)
43
DO_2OP_SCALAR_S(vhsubs_scalar, do_vhsub_s)
44
DO_2OP_SCALAR_U(vhsubu_scalar, do_vhsub_u)
45
46
+static inline uint32_t do_vbrsrb(uint32_t n, uint32_t m)
47
+{
48
+ m &= 0xff;
49
+ if (m == 0) {
50
+ return 0;
51
+ }
52
+ n = revbit8(n);
53
+ if (m < 8) {
54
+ n >>= 8 - m;
55
+ }
56
+ return n;
23
+}
57
+}
24
+
58
+
25
+static void mps2tz_set_default_ram_info(MPS2TZMachineClass *mmc)
59
+static inline uint32_t do_vbrsrh(uint32_t n, uint32_t m)
26
+{
60
+{
27
+ /*
61
+ m &= 0xff;
28
+ * Set mc->default_ram_size and default_ram_id from the
62
+ if (m == 0) {
29
+ * information in mmc->raminfo.
63
+ return 0;
30
+ */
64
+ }
31
+ MachineClass *mc = MACHINE_CLASS(mmc);
65
+ n = revbit16(n);
32
+ const RAMInfo *p;
66
+ if (m < 16) {
67
+ n >>= 16 - m;
68
+ }
69
+ return n;
70
+}
33
+
71
+
34
+ for (p = mmc->raminfo; p->name; p++) {
72
+static inline uint32_t do_vbrsrw(uint32_t n, uint32_t m)
35
+ if (p->mrindex < 0) {
73
+{
36
+ /* Found the entry for "system memory" */
74
+ m &= 0xff;
37
+ mc->default_ram_size = p->size;
75
+ if (m == 0) {
38
+ mc->default_ram_id = p->name;
76
+ return 0;
39
+ return;
40
+ }
41
+ }
77
+ }
42
+ g_assert_not_reached();
78
+ n = revbit32(n);
43
}
79
+ if (m < 32) {
44
80
+ n >>= 32 - m;
45
static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
81
+ }
46
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
82
+ return n;
47
mmc->numirq = 92;
83
+}
48
mmc->raminfo = an505_raminfo;
84
+
49
mmc->armsse_type = TYPE_IOTKIT;
85
+DO_2OP_SCALAR(vbrsrb, 1, uint8_t, do_vbrsrb)
50
+ mps2tz_set_default_ram_info(mmc);
86
+DO_2OP_SCALAR(vbrsrh, 2, uint16_t, do_vbrsrh)
51
}
87
+DO_2OP_SCALAR(vbrsrw, 4, uint32_t, do_vbrsrw)
52
88
+
53
static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
89
/*
54
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
90
* Multiply add long dual accumulate ops.
55
mmc->numirq = 92;
91
*/
56
mmc->raminfo = an505_raminfo; /* AN521 is the same as AN505 here */
92
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
57
mmc->armsse_type = TYPE_SSE200;
93
index XXXXXXX..XXXXXXX 100644
58
+ mps2tz_set_default_ram_info(mmc);
94
--- a/target/arm/translate-mve.c
59
}
95
+++ b/target/arm/translate-mve.c
60
96
@@ -XXX,XX +XXX,XX @@ DO_2OP_SCALAR(VHADD_S_scalar, vhadds_scalar)
61
static const TypeInfo mps2tz_info = {
97
DO_2OP_SCALAR(VHADD_U_scalar, vhaddu_scalar)
98
DO_2OP_SCALAR(VHSUB_S_scalar, vhsubs_scalar)
99
DO_2OP_SCALAR(VHSUB_U_scalar, vhsubu_scalar)
100
+DO_2OP_SCALAR(VBRSR, vbrsr)
101
102
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
103
MVEGenDualAccOpFn *fn)
62
--
104
--
63
2.20.1
105
2.20.1
64
106
65
107
diff view generated by jsdifflib
1
In the mps2-tz board code, we handle devices whose interrupt lines
1
Implement the MVE VPST insn, which sets the predicate mask
2
must be wired to all CPUs by creating IRQ splitter devices for the
2
fields in the VPR to the immediate value encoded in the insn.
3
AN521, because it has 2 CPUs, but wiring the device IRQ directly to
4
the SSE/IoTKit input for the AN505, which has only 1 CPU.
5
6
We can avoid making an explicit check on the board type constant by
7
instead creating and using the IRQ splitters for any board with more
8
than 1 CPU. This avoids having to add extra cases to the
9
conditionals every time we add new boards.
10
3
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Message-id: 20210215115138.20465-9-peter.maydell@linaro.org
6
Message-id: 20210617121628.20116-27-peter.maydell@linaro.org
15
---
7
---
16
hw/arm/mps2-tz.c | 19 +++++++++----------
8
target/arm/mve.decode | 4 +++
17
1 file changed, 9 insertions(+), 10 deletions(-)
9
target/arm/translate-mve.c | 59 ++++++++++++++++++++++++++++++++++++++
10
2 files changed, 63 insertions(+)
18
11
19
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
12
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
20
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
21
--- a/hw/arm/mps2-tz.c
14
--- a/target/arm/mve.decode
22
+++ b/hw/arm/mps2-tz.c
15
+++ b/target/arm/mve.decode
23
@@ -XXX,XX +XXX,XX @@ static void make_ram_alias(MemoryRegion *mr, const char *name,
16
@@ -XXX,XX +XXX,XX @@ VHADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
24
static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
17
VHSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
25
{
18
VHSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
26
/* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
19
VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
27
- MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
20
+
28
+ MachineClass *mc = MACHINE_GET_CLASS(mms);
21
+# Predicate operations
29
22
+%mask_22_13 22:1 13:3
30
assert(irqno < MPS2TZ_NUMIRQ);
23
+VPST 1111 1110 0 . 11 000 1 ... 0 1111 0100 1101 mask=%mask_22_13
31
24
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
32
- switch (mmc->fpga_type) {
25
index XXXXXXX..XXXXXXX 100644
33
- case FPGA_AN505:
26
--- a/target/arm/translate-mve.c
34
- return qdev_get_gpio_in_named(DEVICE(&mms->iotkit), "EXP_IRQ", irqno);
27
+++ b/target/arm/translate-mve.c
35
- case FPGA_AN521:
28
@@ -XXX,XX +XXX,XX @@ static void mve_update_eci(DisasContext *s)
36
+ if (mc->max_cpus > 1) {
37
return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
38
- default:
39
- g_assert_not_reached();
40
+ } else {
41
+ return qdev_get_gpio_in_named(DEVICE(&mms->iotkit), "EXP_IRQ", irqno);
42
}
29
}
43
}
30
}
44
31
45
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
32
+static void mve_update_and_store_eci(DisasContext *s)
46
sysbus_realize(SYS_BUS_DEVICE(&mms->iotkit), &error_fatal);
33
+{
47
34
+ /*
48
/*
35
+ * For insns which don't call a helper function that will call
49
- * The AN521 needs us to create splitters to feed the IRQ inputs
36
+ * mve_advance_vpt(), this version updates s->eci and also stores
50
- * for each CPU in the SSE-200 from each device in the board.
37
+ * it out to the CPUState field.
51
+ * If this board has more than one CPU, then we need to create splitters
38
+ */
52
+ * to feed the IRQ inputs for each CPU in the SSE from each device in the
39
+ if (s->eci) {
53
+ * board. If there is only one CPU, we can just wire the device IRQ
40
+ mve_update_eci(s);
54
+ * directly to the SSE's IRQ input.
41
+ store_cpu_field(tcg_constant_i32(s->eci << 4), condexec_bits);
55
*/
42
+ }
56
- if (mmc->fpga_type == FPGA_AN521) {
43
+}
57
+ if (mc->max_cpus > 1) {
44
+
58
for (i = 0; i < MPS2TZ_NUMIRQ; i++) {
45
static bool mve_skip_first_beat(DisasContext *s)
59
char *name = g_strdup_printf("mps2-irq-splitter%d", i);
46
{
60
SplitIRQ *splitter = &mms->cpu_irq_splitter[i];
47
/* Return true if PSR.ECI says we must skip the first beat of this insn */
48
@@ -XXX,XX +XXX,XX @@ static bool trans_VRMLSLDAVH(DisasContext *s, arg_vmlaldav *a)
49
};
50
return do_long_dual_acc(s, a, fns[a->x]);
51
}
52
+
53
+static bool trans_VPST(DisasContext *s, arg_VPST *a)
54
+{
55
+ TCGv_i32 vpr;
56
+
57
+ /* mask == 0 is a "related encoding" */
58
+ if (!dc_isar_feature(aa32_mve, s) || !a->mask) {
59
+ return false;
60
+ }
61
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
62
+ return true;
63
+ }
64
+ /*
65
+ * Set the VPR mask fields. We take advantage of MASK01 and MASK23
66
+ * being adjacent fields in the register.
67
+ *
68
+ * This insn is not predicated, but it is subject to beat-wise
69
+ * execution, and the mask is updated on the odd-numbered beats.
70
+ * So if PSR.ECI says we should skip beat 1, we mustn't update the
71
+ * 01 mask field.
72
+ */
73
+ vpr = load_cpu_field(v7m.vpr);
74
+ switch (s->eci) {
75
+ case ECI_NONE:
76
+ case ECI_A0:
77
+ /* Update both 01 and 23 fields */
78
+ tcg_gen_deposit_i32(vpr, vpr,
79
+ tcg_constant_i32(a->mask | (a->mask << 4)),
80
+ R_V7M_VPR_MASK01_SHIFT,
81
+ R_V7M_VPR_MASK01_LENGTH + R_V7M_VPR_MASK23_LENGTH);
82
+ break;
83
+ case ECI_A0A1:
84
+ case ECI_A0A1A2:
85
+ case ECI_A0A1A2B0:
86
+ /* Update only the 23 mask field */
87
+ tcg_gen_deposit_i32(vpr, vpr,
88
+ tcg_constant_i32(a->mask),
89
+ R_V7M_VPR_MASK23_SHIFT, R_V7M_VPR_MASK23_LENGTH);
90
+ break;
91
+ default:
92
+ g_assert_not_reached();
93
+ }
94
+ store_cpu_field(vpr, v7m.vpr);
95
+ mve_update_and_store_eci(s);
96
+ return true;
97
+}
61
--
98
--
62
2.20.1
99
2.20.1
63
100
64
101
diff view generated by jsdifflib
1
From: schspa <schspa@gmail.com>
1
Implement the MVE VQADD and VQSUB insns, which perform saturating
2
addition of a scalar to each element. Note that individual bytes of
3
each result element are used or discarded according to the predicate
4
mask, but FPSCR.QC is only set if the predicate mask for the lowest
5
byte of the element is set.
2
6
3
At the moment the following QEMU command line triggers an assertion
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
failure On xlnx-versal SOC:
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
qemu-system-aarch64 \
9
Message-id: 20210617121628.20116-28-peter.maydell@linaro.org
6
-machine xlnx-versal-virt -nographic -smp 2 -m 128 \
10
---
7
-fsdev local,id=shareid,path=${HOME}/work,security_model=none \
11
target/arm/helper-mve.h | 16 ++++++++++
8
-device virtio-9p-device,fsdev=shareid,mount_tag=share \
12
target/arm/mve.decode | 5 +++
9
-fsdev local,id=shareid1,path=${HOME}/Music,security_model=none \
13
target/arm/mve_helper.c | 62 ++++++++++++++++++++++++++++++++++++++
10
-device virtio-9p-device,fsdev=shareid1,mount_tag=share1
14
target/arm/translate-mve.c | 4 +++
15
4 files changed, 87 insertions(+)
11
16
12
qemu-system-aarch64: ../migration/savevm.c:860:
17
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
13
vmstate_register_with_alias_id:
14
Assertion `!se->compat || se->instance_id == 0' failed.
15
16
This problem was fixed on arm virt platform in commit f58b39d2d5b
17
("virtio-mmio: format transport base address in BusClass.get_dev_path")
18
19
It works perfectly on arm virt platform. but there is still there on
20
xlnx-versal SOC.
21
22
The main difference between arm virt and xlnx-versal is they use
23
different way to create virtio-mmio qdev. on arm virt, it calls
24
sysbus_create_simple("virtio-mmio", base, pic[irq]); which will call
25
sysbus_mmio_map internally and assign base address to subsys device
26
mmio correctly. but xlnx-versal's implements won't do this.
27
28
However, xlnx-versal can't switch to sysbus_create_simple() to create
29
virtio-mmio device. It's because xlnx-versal's cpu use
30
VersalVirt.soc.fpd.apu.mr as it's memory. which is subregion of
31
system_memory. sysbus_create_simple will add virtio to system_memory,
32
which can't be accessed by cpu.
33
34
Besides, xlnx-versal can't add sysbus_mmio_map api call too, because
35
this will add memory region to system_memory, and it can't be added
36
to VersalVirt.soc.fpd.apu.mr again.
37
38
We can solve this by assign correct base address offset on dev_path.
39
40
This path was test on aarch64 virt & xlnx-versal platform.
41
42
Signed-off-by: schspa <schspa@gmail.com>
43
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
44
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
45
---
46
hw/virtio/virtio-mmio.c | 13 +++++++------
47
1 file changed, 7 insertions(+), 6 deletions(-)
48
49
diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c
50
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
51
--- a/hw/virtio/virtio-mmio.c
19
--- a/target/arm/helper-mve.h
52
+++ b/hw/virtio/virtio-mmio.c
20
+++ b/target/arm/helper-mve.h
53
@@ -XXX,XX +XXX,XX @@ static char *virtio_mmio_bus_get_dev_path(DeviceState *dev)
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vhsubu_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
54
BusState *virtio_mmio_bus;
22
DEF_HELPER_FLAGS_4(mve_vhsubu_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
55
VirtIOMMIOProxy *virtio_mmio_proxy;
23
DEF_HELPER_FLAGS_4(mve_vhsubu_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
56
char *proxy_path;
24
57
- SysBusDevice *proxy_sbd;
25
+DEF_HELPER_FLAGS_4(mve_vqadds_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
58
char *path;
26
+DEF_HELPER_FLAGS_4(mve_vqadds_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
59
+ MemoryRegionSection section;
27
+DEF_HELPER_FLAGS_4(mve_vqadds_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
60
28
+
61
virtio_mmio_bus = qdev_get_parent_bus(dev);
29
+DEF_HELPER_FLAGS_4(mve_vqaddu_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
62
virtio_mmio_proxy = VIRTIO_MMIO(virtio_mmio_bus->parent);
30
+DEF_HELPER_FLAGS_4(mve_vqaddu_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
63
@@ -XXX,XX +XXX,XX @@ static char *virtio_mmio_bus_get_dev_path(DeviceState *dev)
31
+DEF_HELPER_FLAGS_4(mve_vqaddu_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
32
+
33
+DEF_HELPER_FLAGS_4(mve_vqsubs_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
34
+DEF_HELPER_FLAGS_4(mve_vqsubs_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
35
+DEF_HELPER_FLAGS_4(mve_vqsubs_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
36
+
37
+DEF_HELPER_FLAGS_4(mve_vqsubu_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
38
+DEF_HELPER_FLAGS_4(mve_vqsubu_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
39
+DEF_HELPER_FLAGS_4(mve_vqsubu_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
40
+
41
DEF_HELPER_FLAGS_4(mve_vbrsrb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
42
DEF_HELPER_FLAGS_4(mve_vbrsrh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
43
DEF_HELPER_FLAGS_4(mve_vbrsrw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
44
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
45
index XXXXXXX..XXXXXXX 100644
46
--- a/target/arm/mve.decode
47
+++ b/target/arm/mve.decode
48
@@ -XXX,XX +XXX,XX @@ VHADD_S_scalar 1110 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
49
VHADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
50
VHSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
51
VHSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
52
+
53
+VQADD_S_scalar 1110 1110 0 . .. ... 0 ... 0 1111 . 110 .... @2scalar
54
+VQADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 110 .... @2scalar
55
+VQSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
56
+VQSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
57
VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
58
59
# Predicate operations
60
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/mve_helper.c
63
+++ b/target/arm/mve_helper.c
64
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vhaddu, do_vhadd_u)
65
DO_2OP_S(vhsubs, do_vhsub_s)
66
DO_2OP_U(vhsubu, do_vhsub_u)
67
68
+static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
69
+{
70
+ if (val > max) {
71
+ *s = true;
72
+ return max;
73
+ } else if (val < min) {
74
+ *s = true;
75
+ return min;
76
+ }
77
+ return val;
78
+}
79
+
80
+#define DO_SQADD_B(n, m, s) do_sat_bhw((int64_t)n + m, INT8_MIN, INT8_MAX, s)
81
+#define DO_SQADD_H(n, m, s) do_sat_bhw((int64_t)n + m, INT16_MIN, INT16_MAX, s)
82
+#define DO_SQADD_W(n, m, s) do_sat_bhw((int64_t)n + m, INT32_MIN, INT32_MAX, s)
83
+
84
+#define DO_UQADD_B(n, m, s) do_sat_bhw((int64_t)n + m, 0, UINT8_MAX, s)
85
+#define DO_UQADD_H(n, m, s) do_sat_bhw((int64_t)n + m, 0, UINT16_MAX, s)
86
+#define DO_UQADD_W(n, m, s) do_sat_bhw((int64_t)n + m, 0, UINT32_MAX, s)
87
+
88
+#define DO_SQSUB_B(n, m, s) do_sat_bhw((int64_t)n - m, INT8_MIN, INT8_MAX, s)
89
+#define DO_SQSUB_H(n, m, s) do_sat_bhw((int64_t)n - m, INT16_MIN, INT16_MAX, s)
90
+#define DO_SQSUB_W(n, m, s) do_sat_bhw((int64_t)n - m, INT32_MIN, INT32_MAX, s)
91
+
92
+#define DO_UQSUB_B(n, m, s) do_sat_bhw((int64_t)n - m, 0, UINT8_MAX, s)
93
+#define DO_UQSUB_H(n, m, s) do_sat_bhw((int64_t)n - m, 0, UINT16_MAX, s)
94
+#define DO_UQSUB_W(n, m, s) do_sat_bhw((int64_t)n - m, 0, UINT32_MAX, s)
95
96
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
97
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
98
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vhsubu, do_vhsub_u)
99
mve_advance_vpt(env); \
64
}
100
}
65
101
66
/* Otherwise, we append the base address of the transport. */
102
+#define DO_2OP_SAT_SCALAR(OP, ESIZE, TYPE, FN) \
67
- proxy_sbd = SYS_BUS_DEVICE(virtio_mmio_proxy);
103
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
68
- assert(proxy_sbd->num_mmio == 1);
104
+ uint32_t rm) \
69
- assert(proxy_sbd->mmio[0].memory == &virtio_mmio_proxy->iomem);
105
+ { \
70
+ section = memory_region_find(&virtio_mmio_proxy->iomem, 0, 0x200);
106
+ TYPE *d = vd, *n = vn; \
71
+ assert(section.mr);
107
+ TYPE m = rm; \
72
108
+ uint16_t mask = mve_element_mask(env); \
73
if (proxy_path) {
109
+ unsigned e; \
74
path = g_strdup_printf("%s/virtio-mmio@" TARGET_FMT_plx, proxy_path,
110
+ bool qc = false; \
75
- proxy_sbd->mmio[0].addr);
111
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
76
+ section.offset_within_address_space);
112
+ bool sat = false; \
77
} else {
113
+ mergemask(&d[H##ESIZE(e)], FN(n[H##ESIZE(e)], m, &sat), \
78
path = g_strdup_printf("virtio-mmio@" TARGET_FMT_plx,
114
+ mask); \
79
- proxy_sbd->mmio[0].addr);
115
+ qc |= sat & mask & 1; \
80
+ section.offset_within_address_space);
116
+ } \
81
}
117
+ if (qc) { \
82
+ memory_region_unref(section.mr);
118
+ env->vfp.qc[0] = qc; \
119
+ } \
120
+ mve_advance_vpt(env); \
121
+ }
83
+
122
+
84
g_free(proxy_path);
123
/* provide unsigned 2-op scalar helpers for all sizes */
85
return path;
124
#define DO_2OP_SCALAR_U(OP, FN) \
86
}
125
DO_2OP_SCALAR(OP##b, 1, uint8_t, FN) \
126
@@ -XXX,XX +XXX,XX @@ DO_2OP_SCALAR_U(vhaddu_scalar, do_vhadd_u)
127
DO_2OP_SCALAR_S(vhsubs_scalar, do_vhsub_s)
128
DO_2OP_SCALAR_U(vhsubu_scalar, do_vhsub_u)
129
130
+DO_2OP_SAT_SCALAR(vqaddu_scalarb, 1, uint8_t, DO_UQADD_B)
131
+DO_2OP_SAT_SCALAR(vqaddu_scalarh, 2, uint16_t, DO_UQADD_H)
132
+DO_2OP_SAT_SCALAR(vqaddu_scalarw, 4, uint32_t, DO_UQADD_W)
133
+DO_2OP_SAT_SCALAR(vqadds_scalarb, 1, int8_t, DO_SQADD_B)
134
+DO_2OP_SAT_SCALAR(vqadds_scalarh, 2, int16_t, DO_SQADD_H)
135
+DO_2OP_SAT_SCALAR(vqadds_scalarw, 4, int32_t, DO_SQADD_W)
136
+
137
+DO_2OP_SAT_SCALAR(vqsubu_scalarb, 1, uint8_t, DO_UQSUB_B)
138
+DO_2OP_SAT_SCALAR(vqsubu_scalarh, 2, uint16_t, DO_UQSUB_H)
139
+DO_2OP_SAT_SCALAR(vqsubu_scalarw, 4, uint32_t, DO_UQSUB_W)
140
+DO_2OP_SAT_SCALAR(vqsubs_scalarb, 1, int8_t, DO_SQSUB_B)
141
+DO_2OP_SAT_SCALAR(vqsubs_scalarh, 2, int16_t, DO_SQSUB_H)
142
+DO_2OP_SAT_SCALAR(vqsubs_scalarw, 4, int32_t, DO_SQSUB_W)
143
+
144
static inline uint32_t do_vbrsrb(uint32_t n, uint32_t m)
145
{
146
m &= 0xff;
147
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
148
index XXXXXXX..XXXXXXX 100644
149
--- a/target/arm/translate-mve.c
150
+++ b/target/arm/translate-mve.c
151
@@ -XXX,XX +XXX,XX @@ DO_2OP_SCALAR(VHADD_S_scalar, vhadds_scalar)
152
DO_2OP_SCALAR(VHADD_U_scalar, vhaddu_scalar)
153
DO_2OP_SCALAR(VHSUB_S_scalar, vhsubs_scalar)
154
DO_2OP_SCALAR(VHSUB_U_scalar, vhsubu_scalar)
155
+DO_2OP_SCALAR(VQADD_S_scalar, vqadds_scalar)
156
+DO_2OP_SCALAR(VQADD_U_scalar, vqaddu_scalar)
157
+DO_2OP_SCALAR(VQSUB_S_scalar, vqsubs_scalar)
158
+DO_2OP_SCALAR(VQSUB_U_scalar, vqsubu_scalar)
159
DO_2OP_SCALAR(VBRSR, vbrsr)
160
161
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
87
--
162
--
88
2.20.1
163
2.20.1
89
164
90
165
diff view generated by jsdifflib
1
The macro draw_line_func is used only once; just expand it.
1
Implement the MVE VQDMULH and VQRDMULH scalar insns, which multiply
2
elements by the scalar, double, possibly round, take the high half
3
and saturate.
2
4
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
Message-id: 20210617121628.20116-29-peter.maydell@linaro.org
6
Message-id: 20210215103215.4944-10-peter.maydell@linaro.org
7
---
8
---
8
hw/display/omap_lcdc.c | 4 +---
9
target/arm/helper-mve.h | 8 ++++++++
9
1 file changed, 1 insertion(+), 3 deletions(-)
10
target/arm/mve.decode | 3 +++
11
target/arm/mve_helper.c | 25 +++++++++++++++++++++++++
12
target/arm/translate-mve.c | 2 ++
13
4 files changed, 38 insertions(+)
10
14
11
diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c
15
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
12
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/display/omap_lcdc.c
17
--- a/target/arm/helper-mve.h
14
+++ b/hw/display/omap_lcdc.c
18
+++ b/target/arm/helper-mve.h
15
@@ -XXX,XX +XXX,XX @@ static void omap_lcd_interrupts(struct omap_lcd_panel_s *s)
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqsubu_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
16
qemu_irq_lower(s->irq);
20
DEF_HELPER_FLAGS_4(mve_vqsubu_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
17
}
21
DEF_HELPER_FLAGS_4(mve_vqsubu_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
18
22
19
-#define draw_line_func drawfn
23
+DEF_HELPER_FLAGS_4(mve_vqdmulh_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
20
-
24
+DEF_HELPER_FLAGS_4(mve_vqdmulh_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
21
/*
25
+DEF_HELPER_FLAGS_4(mve_vqdmulh_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
22
* 2-bit colour
26
+
23
*/
27
+DEF_HELPER_FLAGS_4(mve_vqrdmulh_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
@@ -XXX,XX +XXX,XX @@ static void omap_update_display(void *opaque)
28
+DEF_HELPER_FLAGS_4(mve_vqrdmulh_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
29
+DEF_HELPER_FLAGS_4(mve_vqrdmulh_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
30
+
31
DEF_HELPER_FLAGS_4(mve_vbrsrb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
32
DEF_HELPER_FLAGS_4(mve_vbrsrh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
33
DEF_HELPER_FLAGS_4(mve_vbrsrw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
34
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/mve.decode
37
+++ b/target/arm/mve.decode
38
@@ -XXX,XX +XXX,XX @@ VQSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
39
VQSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
40
VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
41
42
+VQDMULH_scalar 1110 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
43
+VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
44
+
45
# Predicate operations
46
%mask_22_13 22:1 13:3
47
VPST 1111 1110 0 . 11 000 1 ... 0 1111 0100 1101 mask=%mask_22_13
48
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
49
index XXXXXXX..XXXXXXX 100644
50
--- a/target/arm/mve_helper.c
51
+++ b/target/arm/mve_helper.c
52
@@ -XXX,XX +XXX,XX @@ static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
53
#define DO_UQSUB_H(n, m, s) do_sat_bhw((int64_t)n - m, 0, UINT16_MAX, s)
54
#define DO_UQSUB_W(n, m, s) do_sat_bhw((int64_t)n - m, 0, UINT32_MAX, s)
55
56
+/*
57
+ * For QDMULH and QRDMULH we simplify "double and shift by esize" into
58
+ * "shift by esize-1", adjusting the QRDMULH rounding constant to match.
59
+ */
60
+#define DO_QDMULH_B(n, m, s) do_sat_bhw(((int64_t)n * m) >> 7, \
61
+ INT8_MIN, INT8_MAX, s)
62
+#define DO_QDMULH_H(n, m, s) do_sat_bhw(((int64_t)n * m) >> 15, \
63
+ INT16_MIN, INT16_MAX, s)
64
+#define DO_QDMULH_W(n, m, s) do_sat_bhw(((int64_t)n * m) >> 31, \
65
+ INT32_MIN, INT32_MAX, s)
66
+
67
+#define DO_QRDMULH_B(n, m, s) do_sat_bhw(((int64_t)n * m + (1 << 6)) >> 7, \
68
+ INT8_MIN, INT8_MAX, s)
69
+#define DO_QRDMULH_H(n, m, s) do_sat_bhw(((int64_t)n * m + (1 << 14)) >> 15, \
70
+ INT16_MIN, INT16_MAX, s)
71
+#define DO_QRDMULH_W(n, m, s) do_sat_bhw(((int64_t)n * m + (1 << 30)) >> 31, \
72
+ INT32_MIN, INT32_MAX, s)
73
+
74
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
75
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
76
uint32_t rm) \
77
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT_SCALAR(vqsubs_scalarb, 1, int8_t, DO_SQSUB_B)
78
DO_2OP_SAT_SCALAR(vqsubs_scalarh, 2, int16_t, DO_SQSUB_H)
79
DO_2OP_SAT_SCALAR(vqsubs_scalarw, 4, int32_t, DO_SQSUB_W)
80
81
+DO_2OP_SAT_SCALAR(vqdmulh_scalarb, 1, int8_t, DO_QDMULH_B)
82
+DO_2OP_SAT_SCALAR(vqdmulh_scalarh, 2, int16_t, DO_QDMULH_H)
83
+DO_2OP_SAT_SCALAR(vqdmulh_scalarw, 4, int32_t, DO_QDMULH_W)
84
+DO_2OP_SAT_SCALAR(vqrdmulh_scalarb, 1, int8_t, DO_QRDMULH_B)
85
+DO_2OP_SAT_SCALAR(vqrdmulh_scalarh, 2, int16_t, DO_QRDMULH_H)
86
+DO_2OP_SAT_SCALAR(vqrdmulh_scalarw, 4, int32_t, DO_QRDMULH_W)
87
+
88
static inline uint32_t do_vbrsrb(uint32_t n, uint32_t m)
25
{
89
{
26
struct omap_lcd_panel_s *omap_lcd = (struct omap_lcd_panel_s *) opaque;
90
m &= 0xff;
27
DisplaySurface *surface;
91
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
28
- draw_line_func draw_line;
92
index XXXXXXX..XXXXXXX 100644
29
+ drawfn draw_line;
93
--- a/target/arm/translate-mve.c
30
int size, height, first, last;
94
+++ b/target/arm/translate-mve.c
31
int width, linesize, step, bpp, frame_offset;
95
@@ -XXX,XX +XXX,XX @@ DO_2OP_SCALAR(VQADD_S_scalar, vqadds_scalar)
32
hwaddr frame_base;
96
DO_2OP_SCALAR(VQADD_U_scalar, vqaddu_scalar)
97
DO_2OP_SCALAR(VQSUB_S_scalar, vqsubs_scalar)
98
DO_2OP_SCALAR(VQSUB_U_scalar, vqsubu_scalar)
99
+DO_2OP_SCALAR(VQDMULH_scalar, vqdmulh_scalar)
100
+DO_2OP_SCALAR(VQRDMULH_scalar, vqrdmulh_scalar)
101
DO_2OP_SCALAR(VBRSR, vbrsr)
102
103
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
33
--
104
--
34
2.20.1
105
2.20.1
35
106
36
107
diff view generated by jsdifflib
1
Fix some minor coding style issues in the template header,
1
Implement the MVE VQDMULL scalar insn. This multiplies the top or
2
so checkpatch doesn't complain when we move the code.
2
bottom half of each element by the scalar, doubles and saturates
3
to a double-width result.
4
5
Note that this encoding overlaps with VQADD and VQSUB; it uses
6
what in VQADD and VQSUB would be the 'size=0b11' encoding.
3
7
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
10
Message-id: 20210617121628.20116-30-peter.maydell@linaro.org
7
Message-id: 20210215103215.4944-8-peter.maydell@linaro.org
8
---
11
---
9
hw/display/omap_lcd_template.h | 6 +++---
12
target/arm/helper-mve.h | 5 +++
10
1 file changed, 3 insertions(+), 3 deletions(-)
13
target/arm/mve.decode | 23 +++++++++++---
11
14
target/arm/mve_helper.c | 65 ++++++++++++++++++++++++++++++++++++++
12
diff --git a/hw/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h
15
target/arm/translate-mve.c | 30 ++++++++++++++++++
13
index XXXXXXX..XXXXXXX 100644
16
4 files changed, 119 insertions(+), 4 deletions(-)
14
--- a/hw/display/omap_lcd_template.h
17
15
+++ b/hw/display/omap_lcd_template.h
18
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
16
@@ -XXX,XX +XXX,XX @@ static void draw_line2_32(void *opaque, uint8_t *d, const uint8_t *s,
19
index XXXXXXX..XXXXXXX 100644
17
b = (pal[v & 3] << 4) & 0xf0;
20
--- a/target/arm/helper-mve.h
18
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
21
+++ b/target/arm/helper-mve.h
19
d += 4;
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vbrsrb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
20
- s ++;
23
DEF_HELPER_FLAGS_4(mve_vbrsrh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
21
+ s++;
24
DEF_HELPER_FLAGS_4(mve_vbrsrw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
22
width -= 4;
25
23
} while (width > 0);
26
+DEF_HELPER_FLAGS_4(mve_vqdmullb_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
}
27
+DEF_HELPER_FLAGS_4(mve_vqdmullb_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
@@ -XXX,XX +XXX,XX @@ static void draw_line4_32(void *opaque, uint8_t *d, const uint8_t *s,
28
+DEF_HELPER_FLAGS_4(mve_vqdmullt_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
26
b = (pal[v & 0xf] << 4) & 0xf0;
29
+DEF_HELPER_FLAGS_4(mve_vqdmullt_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
27
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
30
+
28
d += 4;
31
DEF_HELPER_FLAGS_4(mve_vmlaldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
29
- s ++;
32
DEF_HELPER_FLAGS_4(mve_vmlaldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
30
+ s++;
33
DEF_HELPER_FLAGS_4(mve_vmlaldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
31
width -= 2;
34
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
32
} while (width > 0);
35
index XXXXXXX..XXXXXXX 100644
33
}
36
--- a/target/arm/mve.decode
34
@@ -XXX,XX +XXX,XX @@ static void draw_line8_32(void *opaque, uint8_t *d, const uint8_t *s,
37
+++ b/target/arm/mve.decode
35
g = pal[v] & 0xf0;
38
@@ -XXX,XX +XXX,XX @@
36
b = (pal[v] << 4) & 0xf0;
39
%qm 5:1 1:3
37
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
40
%qn 7:1 17:3
38
- s ++;
41
39
+ s++;
42
+# VQDMULL has size in bit 28: 0 for 16 bit, 1 for 32 bit
40
d += 4;
43
+%size_28 28:1 !function=plus_1
41
} while (-- width != 0);
44
+
42
}
45
&vldr_vstr rn qd imm p a w size l u
46
&1op qd qm size
47
&2op qd qm qn size
48
@@ -XXX,XX +XXX,XX @@
49
@2op_nosz .... .... .... .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn size=0
50
51
@2scalar .... .... .. size:2 .... .... .... .... rm:4 &2scalar qd=%qd qn=%qn
52
+@2scalar_nosz .... .... .... .... .... .... .... rm:4 &2scalar qd=%qd qn=%qn
53
54
# Vector loads and stores
55
56
@@ -XXX,XX +XXX,XX @@ VHADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
57
VHSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
58
VHSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
59
60
-VQADD_S_scalar 1110 1110 0 . .. ... 0 ... 0 1111 . 110 .... @2scalar
61
-VQADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 110 .... @2scalar
62
-VQSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
63
-VQSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
64
+{
65
+ VQADD_S_scalar 1110 1110 0 . .. ... 0 ... 0 1111 . 110 .... @2scalar
66
+ VQADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 110 .... @2scalar
67
+ VQDMULLB_scalar 111 . 1110 0 . 11 ... 0 ... 0 1111 . 110 .... @2scalar_nosz \
68
+ size=%size_28
69
+}
70
+
71
+{
72
+ VQSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
73
+ VQSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
74
+ VQDMULLT_scalar 111 . 1110 0 . 11 ... 0 ... 1 1111 . 110 .... @2scalar_nosz \
75
+ size=%size_28
76
+}
77
+
78
VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
79
80
VQDMULH_scalar 1110 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
81
VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
82
83
+
84
# Predicate operations
85
%mask_22_13 22:1 13:3
86
VPST 1111 1110 0 . 11 000 1 ... 0 1111 0100 1101 mask=%mask_22_13
87
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/target/arm/mve_helper.c
90
+++ b/target/arm/mve_helper.c
91
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT_SCALAR(vqrdmulh_scalarb, 1, int8_t, DO_QRDMULH_B)
92
DO_2OP_SAT_SCALAR(vqrdmulh_scalarh, 2, int16_t, DO_QRDMULH_H)
93
DO_2OP_SAT_SCALAR(vqrdmulh_scalarw, 4, int32_t, DO_QRDMULH_W)
94
95
+/*
96
+ * Long saturating scalar ops. As with DO_2OP_L, TYPE and H are for the
97
+ * input (smaller) type and LESIZE, LTYPE, LH for the output (long) type.
98
+ * SATMASK specifies which bits of the predicate mask matter for determining
99
+ * whether to propagate a saturation indication into FPSCR.QC -- for
100
+ * the 16x16->32 case we must check only the bit corresponding to the T or B
101
+ * half that we used, but for the 32x32->64 case we propagate if the mask
102
+ * bit is set for either half.
103
+ */
104
+#define DO_2OP_SAT_SCALAR_L(OP, TOP, ESIZE, TYPE, LESIZE, LTYPE, FN, SATMASK) \
105
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
106
+ uint32_t rm) \
107
+ { \
108
+ LTYPE *d = vd; \
109
+ TYPE *n = vn; \
110
+ TYPE m = rm; \
111
+ uint16_t mask = mve_element_mask(env); \
112
+ unsigned le; \
113
+ bool qc = false; \
114
+ for (le = 0; le < 16 / LESIZE; le++, mask >>= LESIZE) { \
115
+ bool sat = false; \
116
+ LTYPE r = FN((LTYPE)n[H##ESIZE(le * 2 + TOP)], m, &sat); \
117
+ mergemask(&d[H##LESIZE(le)], r, mask); \
118
+ qc |= sat && (mask & SATMASK); \
119
+ } \
120
+ if (qc) { \
121
+ env->vfp.qc[0] = qc; \
122
+ } \
123
+ mve_advance_vpt(env); \
124
+ }
125
+
126
+static inline int32_t do_qdmullh(int16_t n, int16_t m, bool *sat)
127
+{
128
+ int64_t r = ((int64_t)n * m) * 2;
129
+ return do_sat_bhw(r, INT32_MIN, INT32_MAX, sat);
130
+}
131
+
132
+static inline int64_t do_qdmullw(int32_t n, int32_t m, bool *sat)
133
+{
134
+ /* The multiply can't overflow, but the doubling might */
135
+ int64_t r = (int64_t)n * m;
136
+ if (r > INT64_MAX / 2) {
137
+ *sat = true;
138
+ return INT64_MAX;
139
+ } else if (r < INT64_MIN / 2) {
140
+ *sat = true;
141
+ return INT64_MIN;
142
+ } else {
143
+ return r * 2;
144
+ }
145
+}
146
+
147
+#define SATMASK16B 1
148
+#define SATMASK16T (1 << 2)
149
+#define SATMASK32 ((1 << 4) | 1)
150
+
151
+DO_2OP_SAT_SCALAR_L(vqdmullb_scalarh, 0, 2, int16_t, 4, int32_t, \
152
+ do_qdmullh, SATMASK16B)
153
+DO_2OP_SAT_SCALAR_L(vqdmullb_scalarw, 0, 4, int32_t, 8, int64_t, \
154
+ do_qdmullw, SATMASK32)
155
+DO_2OP_SAT_SCALAR_L(vqdmullt_scalarh, 1, 2, int16_t, 4, int32_t, \
156
+ do_qdmullh, SATMASK16T)
157
+DO_2OP_SAT_SCALAR_L(vqdmullt_scalarw, 1, 4, int32_t, 8, int64_t, \
158
+ do_qdmullw, SATMASK32)
159
+
160
static inline uint32_t do_vbrsrb(uint32_t n, uint32_t m)
161
{
162
m &= 0xff;
163
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
164
index XXXXXXX..XXXXXXX 100644
165
--- a/target/arm/translate-mve.c
166
+++ b/target/arm/translate-mve.c
167
@@ -XXX,XX +XXX,XX @@ DO_2OP_SCALAR(VQDMULH_scalar, vqdmulh_scalar)
168
DO_2OP_SCALAR(VQRDMULH_scalar, vqrdmulh_scalar)
169
DO_2OP_SCALAR(VBRSR, vbrsr)
170
171
+static bool trans_VQDMULLB_scalar(DisasContext *s, arg_2scalar *a)
172
+{
173
+ static MVEGenTwoOpScalarFn * const fns[] = {
174
+ NULL,
175
+ gen_helper_mve_vqdmullb_scalarh,
176
+ gen_helper_mve_vqdmullb_scalarw,
177
+ NULL,
178
+ };
179
+ if (a->qd == a->qn && a->size == MO_32) {
180
+ /* UNPREDICTABLE; we choose to undef */
181
+ return false;
182
+ }
183
+ return do_2op_scalar(s, a, fns[a->size]);
184
+}
185
+
186
+static bool trans_VQDMULLT_scalar(DisasContext *s, arg_2scalar *a)
187
+{
188
+ static MVEGenTwoOpScalarFn * const fns[] = {
189
+ NULL,
190
+ gen_helper_mve_vqdmullt_scalarh,
191
+ gen_helper_mve_vqdmullt_scalarw,
192
+ NULL,
193
+ };
194
+ if (a->qd == a->qn && a->size == MO_32) {
195
+ /* UNPREDICTABLE; we choose to undef */
196
+ return false;
197
+ }
198
+ return do_2op_scalar(s, a, fns[a->size]);
199
+}
200
+
201
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
202
MVEGenDualAccOpFn *fn)
203
{
43
--
204
--
44
2.20.1
205
2.20.1
45
206
46
207
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Implement the vector forms of the MVE VQDMULH and VQRDMULH insns.
2
2
3
Always perform one call instead of two for 16-byte operands.
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Use byte loads/stores directly into the vector register file
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
instead of extractions and deposits to a 64-bit local variable.
5
Message-id: 20210617121628.20116-31-peter.maydell@linaro.org
6
---
7
target/arm/helper-mve.h | 8 ++++++++
8
target/arm/mve.decode | 3 +++
9
target/arm/mve_helper.c | 27 +++++++++++++++++++++++++++
10
target/arm/translate-mve.c | 2 ++
11
4 files changed, 40 insertions(+)
6
12
7
In order to easily receive pointers into the vector register file,
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
8
convert the helper to the gvec out-of-line signature. Move the
9
helper into vec_helper.c, where it can make use of H1 and clear_tail.
10
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
13
Tested-by: Alex Bennée <alex.bennee@linaro.org>
14
Message-id: 20210224230532.276878-1-richard.henderson@linaro.org
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
17
target/arm/helper-a64.h | 2 +-
18
target/arm/helper-a64.c | 32 ---------------------
19
target/arm/translate-a64.c | 58 +++++---------------------------------
20
target/arm/vec_helper.c | 48 +++++++++++++++++++++++++++++++
21
4 files changed, 56 insertions(+), 84 deletions(-)
22
23
diff --git a/target/arm/helper-a64.h b/target/arm/helper-a64.h
24
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/helper-a64.h
15
--- a/target/arm/helper-mve.h
26
+++ b/target/arm/helper-a64.h
16
+++ b/target/arm/helper-mve.h
27
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(vfp_cmps_a64, i64, f32, f32, ptr)
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmulltub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
DEF_HELPER_3(vfp_cmpes_a64, i64, f32, f32, ptr)
18
DEF_HELPER_FLAGS_4(mve_vmulltuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
DEF_HELPER_3(vfp_cmpd_a64, i64, f64, f64, ptr)
19
DEF_HELPER_FLAGS_4(mve_vmulltuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
DEF_HELPER_3(vfp_cmped_a64, i64, f64, f64, ptr)
20
31
-DEF_HELPER_FLAGS_5(simd_tbl, TCG_CALL_NO_RWG_SE, i64, env, i64, i64, i32, i32)
21
+DEF_HELPER_FLAGS_4(mve_vqdmulhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
+DEF_HELPER_FLAGS_4(simd_tblx, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
22
+DEF_HELPER_FLAGS_4(mve_vqdmulhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
DEF_HELPER_FLAGS_3(vfp_mulxs, TCG_CALL_NO_RWG, f32, f32, f32, ptr)
23
+DEF_HELPER_FLAGS_4(mve_vqdmulhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
DEF_HELPER_FLAGS_3(vfp_mulxd, TCG_CALL_NO_RWG, f64, f64, f64, ptr)
24
+
35
DEF_HELPER_FLAGS_3(neon_ceq_f64, TCG_CALL_NO_RWG, i64, i64, i64, ptr)
25
+DEF_HELPER_FLAGS_4(mve_vqrdmulhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
26
+DEF_HELPER_FLAGS_4(mve_vqrdmulhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_vqrdmulhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+
29
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
30
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
32
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
37
index XXXXXXX..XXXXXXX 100644
33
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/helper-a64.c
34
--- a/target/arm/mve.decode
39
+++ b/target/arm/helper-a64.c
35
+++ b/target/arm/mve.decode
40
@@ -XXX,XX +XXX,XX @@ float64 HELPER(vfp_mulxd)(float64 a, float64 b, void *fpstp)
36
@@ -XXX,XX +XXX,XX @@ VMULL_BU 111 1 1110 0 . .. ... 1 ... 0 1110 . 0 . 0 ... 0 @2op
41
return float64_mul(a, b, fpst);
37
VMULL_TS 111 0 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
42
}
38
VMULL_TU 111 1 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
43
39
44
-uint64_t HELPER(simd_tbl)(CPUARMState *env, uint64_t result, uint64_t indices,
40
+VQDMULH 1110 1111 0 . .. ... 0 ... 0 1011 . 1 . 0 ... 0 @2op
45
- uint32_t rn, uint32_t numregs)
41
+VQRDMULH 1111 1111 0 . .. ... 0 ... 0 1011 . 1 . 0 ... 0 @2op
46
-{
42
+
47
- /* Helper function for SIMD TBL and TBX. We have to do the table
43
# Vector miscellaneous
48
- * lookup part for the 64 bits worth of indices we're passed in.
44
49
- * result is the initial results vector (either zeroes for TBL
45
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
50
- * or some guest values for TBX), rn the register number where
46
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
51
- * the table starts, and numregs the number of registers in the table.
52
- * We return the results of the lookups.
53
- */
54
- int shift;
55
-
56
- for (shift = 0; shift < 64; shift += 8) {
57
- int index = extract64(indices, shift, 8);
58
- if (index < 16 * numregs) {
59
- /* Convert index (a byte offset into the virtual table
60
- * which is a series of 128-bit vectors concatenated)
61
- * into the correct register element plus a bit offset
62
- * into that element, bearing in mind that the table
63
- * can wrap around from V31 to V0.
64
- */
65
- int elt = (rn * 2 + (index >> 3)) % 64;
66
- int bitidx = (index & 7) * 8;
67
- uint64_t *q = aa64_vfp_qreg(env, elt >> 1);
68
- uint64_t val = extract64(q[elt & 1], bitidx, 8);
69
-
70
- result = deposit64(result, shift, 8, val);
71
- }
72
- }
73
- return result;
74
-}
75
-
76
/* 64bit/double versions of the neon float compare functions */
77
uint64_t HELPER(neon_ceq_f64)(float64 a, float64 b, void *fpstp)
78
{
79
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
80
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
81
--- a/target/arm/translate-a64.c
48
--- a/target/arm/mve_helper.c
82
+++ b/target/arm/translate-a64.c
49
+++ b/target/arm/mve_helper.c
83
@@ -XXX,XX +XXX,XX @@ static void disas_simd_tb(DisasContext *s, uint32_t insn)
50
@@ -XXX,XX +XXX,XX @@ DO_1OP(vfnegs, 8, uint64_t, DO_FNEGS)
84
int rm = extract32(insn, 16, 5);
51
mve_advance_vpt(env); \
85
int rn = extract32(insn, 5, 5);
86
int rd = extract32(insn, 0, 5);
87
- int is_tblx = extract32(insn, 12, 1);
88
- int len = extract32(insn, 13, 2);
89
- TCGv_i64 tcg_resl, tcg_resh, tcg_idx;
90
- TCGv_i32 tcg_regno, tcg_numregs;
91
+ int is_tbx = extract32(insn, 12, 1);
92
+ int len = (extract32(insn, 13, 2) + 1) * 16;
93
94
if (op2 != 0) {
95
unallocated_encoding(s);
96
@@ -XXX,XX +XXX,XX @@ static void disas_simd_tb(DisasContext *s, uint32_t insn)
97
return;
98
}
52
}
99
53
100
- /* This does a table lookup: for every byte element in the input
54
+#define DO_2OP_SAT(OP, ESIZE, TYPE, FN) \
101
- * we index into a table formed from up to four vector registers,
55
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, void *vm) \
102
- * and then the output is the result of the lookups. Our helper
56
+ { \
103
- * function does the lookup operation for a single 64 bit part of
57
+ TYPE *d = vd, *n = vn, *m = vm; \
104
- * the input.
58
+ uint16_t mask = mve_element_mask(env); \
105
- */
59
+ unsigned e; \
106
- tcg_resl = tcg_temp_new_i64();
60
+ bool qc = false; \
107
- tcg_resh = NULL;
61
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
108
-
62
+ bool sat = false; \
109
- if (is_tblx) {
63
+ TYPE r = FN(n[H##ESIZE(e)], m[H##ESIZE(e)], &sat); \
110
- read_vec_element(s, tcg_resl, rd, 0, MO_64);
64
+ mergemask(&d[H##ESIZE(e)], r, mask); \
111
- } else {
65
+ qc |= sat & mask & 1; \
112
- tcg_gen_movi_i64(tcg_resl, 0);
66
+ } \
113
- }
67
+ if (qc) { \
114
-
68
+ env->vfp.qc[0] = qc; \
115
- if (is_q) {
69
+ } \
116
- tcg_resh = tcg_temp_new_i64();
70
+ mve_advance_vpt(env); \
117
- if (is_tblx) {
118
- read_vec_element(s, tcg_resh, rd, 1, MO_64);
119
- } else {
120
- tcg_gen_movi_i64(tcg_resh, 0);
121
- }
122
- }
123
-
124
- tcg_idx = tcg_temp_new_i64();
125
- tcg_regno = tcg_const_i32(rn);
126
- tcg_numregs = tcg_const_i32(len + 1);
127
- read_vec_element(s, tcg_idx, rm, 0, MO_64);
128
- gen_helper_simd_tbl(tcg_resl, cpu_env, tcg_resl, tcg_idx,
129
- tcg_regno, tcg_numregs);
130
- if (is_q) {
131
- read_vec_element(s, tcg_idx, rm, 1, MO_64);
132
- gen_helper_simd_tbl(tcg_resh, cpu_env, tcg_resh, tcg_idx,
133
- tcg_regno, tcg_numregs);
134
- }
135
- tcg_temp_free_i64(tcg_idx);
136
- tcg_temp_free_i32(tcg_regno);
137
- tcg_temp_free_i32(tcg_numregs);
138
-
139
- write_vec_element(s, tcg_resl, rd, 0, MO_64);
140
- tcg_temp_free_i64(tcg_resl);
141
-
142
- if (is_q) {
143
- write_vec_element(s, tcg_resh, rd, 1, MO_64);
144
- tcg_temp_free_i64(tcg_resh);
145
- }
146
- clear_vec_high(s, is_q, rd);
147
+ tcg_gen_gvec_2_ptr(vec_full_reg_offset(s, rd),
148
+ vec_full_reg_offset(s, rm), cpu_env,
149
+ is_q ? 16 : 8, vec_full_reg_size(s),
150
+ (len << 6) | (is_tbx << 5) | rn,
151
+ gen_helper_simd_tblx);
152
}
153
154
/* ZIP/UZP/TRN
155
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
156
index XXXXXXX..XXXXXXX 100644
157
--- a/target/arm/vec_helper.c
158
+++ b/target/arm/vec_helper.c
159
@@ -XXX,XX +XXX,XX @@ DO_VRINT_RMODE(gvec_vrint_rm_h, helper_rinth, uint16_t)
160
DO_VRINT_RMODE(gvec_vrint_rm_s, helper_rints, uint32_t)
161
162
#undef DO_VRINT_RMODE
163
+
164
+#ifdef TARGET_AARCH64
165
+void HELPER(simd_tblx)(void *vd, void *vm, void *venv, uint32_t desc)
166
+{
167
+ const uint8_t *indices = vm;
168
+ CPUARMState *env = venv;
169
+ size_t oprsz = simd_oprsz(desc);
170
+ uint32_t rn = extract32(desc, SIMD_DATA_SHIFT, 5);
171
+ bool is_tbx = extract32(desc, SIMD_DATA_SHIFT + 5, 1);
172
+ uint32_t table_len = desc >> (SIMD_DATA_SHIFT + 6);
173
+ union {
174
+ uint8_t b[16];
175
+ uint64_t d[2];
176
+ } result;
177
+
178
+ /*
179
+ * We must construct the final result in a temp, lest the output
180
+ * overlaps the input table. For TBL, begin with zero; for TBX,
181
+ * begin with the original register contents. Note that we always
182
+ * copy 16 bytes here to avoid an extra branch; clearing the high
183
+ * bits of the register for oprsz == 8 is handled below.
184
+ */
185
+ if (is_tbx) {
186
+ memcpy(&result, vd, 16);
187
+ } else {
188
+ memset(&result, 0, 16);
189
+ }
71
+ }
190
+
72
+
191
+ for (size_t i = 0; i < oprsz; ++i) {
73
#define DO_AND(N, M) ((N) & (M))
192
+ uint32_t index = indices[H1(i)];
74
#define DO_BIC(N, M) ((N) & ~(M))
75
#define DO_ORR(N, M) ((N) | (M))
76
@@ -XXX,XX +XXX,XX @@ static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
77
#define DO_QRDMULH_W(n, m, s) do_sat_bhw(((int64_t)n * m + (1 << 30)) >> 31, \
78
INT32_MIN, INT32_MAX, s)
79
80
+DO_2OP_SAT(vqdmulhb, 1, int8_t, DO_QDMULH_B)
81
+DO_2OP_SAT(vqdmulhh, 2, int16_t, DO_QDMULH_H)
82
+DO_2OP_SAT(vqdmulhw, 4, int32_t, DO_QDMULH_W)
193
+
83
+
194
+ if (index < table_len) {
84
+DO_2OP_SAT(vqrdmulhb, 1, int8_t, DO_QRDMULH_B)
195
+ /*
85
+DO_2OP_SAT(vqrdmulhh, 2, int16_t, DO_QRDMULH_H)
196
+ * Convert index (a byte offset into the virtual table
86
+DO_2OP_SAT(vqrdmulhw, 4, int32_t, DO_QRDMULH_W)
197
+ * which is a series of 128-bit vectors concatenated)
198
+ * into the correct register element, bearing in mind
199
+ * that the table can wrap around from V31 to V0.
200
+ */
201
+ const uint8_t *table = (const uint8_t *)
202
+ aa64_vfp_qreg(env, (rn + (index >> 4)) % 32);
203
+ result.b[H1(i)] = table[H1(index % 16)];
204
+ }
205
+ }
206
+
87
+
207
+ memcpy(vd, &result, 16);
88
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
208
+ clear_tail(vd, oprsz, simd_maxsz(desc));
89
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
209
+}
90
uint32_t rm) \
210
+#endif
91
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
92
index XXXXXXX..XXXXXXX 100644
93
--- a/target/arm/translate-mve.c
94
+++ b/target/arm/translate-mve.c
95
@@ -XXX,XX +XXX,XX @@ DO_2OP(VMULL_BS, vmullbs)
96
DO_2OP(VMULL_BU, vmullbu)
97
DO_2OP(VMULL_TS, vmullts)
98
DO_2OP(VMULL_TU, vmulltu)
99
+DO_2OP(VQDMULH, vqdmulh)
100
+DO_2OP(VQRDMULH, vqrdmulh)
101
102
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
103
MVEGenTwoOpScalarFn fn)
211
--
104
--
212
2.20.1
105
2.20.1
213
106
214
107
diff view generated by jsdifflib
1
The draw_line16_32() function in the omap_lcdc template header
1
Implement the vector forms of the MVE VQADD and VQSUB insns.
2
includes an ifdef for the case where HOST_WORDS_BIGENDIAN matches
3
TARGET_WORDS_BIGENDIAN. This is trying to optimise for "source
4
bitmap and destination bitmap format match", but it is broken,
5
because in this function the formats don't match: the source is
6
16-bit colour and the destination is 32-bit colour, so a memcpy()
7
will produce corrupted graphics output. Drop the bogus ifdef.
8
2
9
This bug was introduced in commit ea644cf343129, when we dropped
10
support for DEPTH values other than 32 from the template header.
11
The old #if line was
12
#if DEPTH == 16 && defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
13
and this was mistakenly changed to
14
#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
15
rather than deleting the #if as now having an always-false condition.
16
17
Fixes: ea644cf343129
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
5
Message-id: 20210617121628.20116-32-peter.maydell@linaro.org
21
Message-id: 20210215103215.4944-7-peter.maydell@linaro.org
22
---
6
---
23
hw/display/omap_lcd_template.h | 4 ----
7
target/arm/helper-mve.h | 16 ++++++++++++++++
24
1 file changed, 4 deletions(-)
8
target/arm/mve.decode | 5 +++++
9
target/arm/mve_helper.c | 14 ++++++++++++++
10
target/arm/translate-mve.c | 4 ++++
11
4 files changed, 39 insertions(+)
25
12
26
diff --git a/hw/display/omap_lcd_template.h b/hw/display/omap_lcd_template.h
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
27
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/display/omap_lcd_template.h
15
--- a/target/arm/helper-mve.h
29
+++ b/hw/display/omap_lcd_template.h
16
+++ b/target/arm/helper-mve.h
30
@@ -XXX,XX +XXX,XX @@ static void draw_line12_32(void *opaque, uint8_t *d, const uint8_t *s,
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqrdmulhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
18
DEF_HELPER_FLAGS_4(mve_vqrdmulhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
int width, int deststep)
19
DEF_HELPER_FLAGS_4(mve_vqrdmulhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
{
20
34
-#if defined(HOST_WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
21
+DEF_HELPER_FLAGS_4(mve_vqaddsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
35
- memcpy(d, s, width * 2);
22
+DEF_HELPER_FLAGS_4(mve_vqaddsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
-#else
23
+DEF_HELPER_FLAGS_4(mve_vqaddsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
37
uint16_t v;
24
+
38
uint8_t r, g, b;
25
+DEF_HELPER_FLAGS_4(mve_vqaddub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
39
26
+DEF_HELPER_FLAGS_4(mve_vqadduh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
40
@@ -XXX,XX +XXX,XX @@ static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
27
+DEF_HELPER_FLAGS_4(mve_vqadduw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
41
s += 2;
28
+
42
d += 4;
29
+DEF_HELPER_FLAGS_4(mve_vqsubsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
43
} while (-- width != 0);
30
+DEF_HELPER_FLAGS_4(mve_vqsubsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
44
-#endif
31
+DEF_HELPER_FLAGS_4(mve_vqsubsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
45
}
32
+
33
+DEF_HELPER_FLAGS_4(mve_vqsubub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
+DEF_HELPER_FLAGS_4(mve_vqsubuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
35
+DEF_HELPER_FLAGS_4(mve_vqsubuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
+
37
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
38
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
39
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
40
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/mve.decode
43
+++ b/target/arm/mve.decode
44
@@ -XXX,XX +XXX,XX @@ VMULL_TU 111 1 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
45
VQDMULH 1110 1111 0 . .. ... 0 ... 0 1011 . 1 . 0 ... 0 @2op
46
VQRDMULH 1111 1111 0 . .. ... 0 ... 0 1011 . 1 . 0 ... 0 @2op
47
48
+VQADD_S 111 0 1111 0 . .. ... 0 ... 0 0000 . 1 . 1 ... 0 @2op
49
+VQADD_U 111 1 1111 0 . .. ... 0 ... 0 0000 . 1 . 1 ... 0 @2op
50
+VQSUB_S 111 0 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
51
+VQSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
52
+
53
# Vector miscellaneous
54
55
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
56
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/mve_helper.c
59
+++ b/target/arm/mve_helper.c
60
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT(vqrdmulhb, 1, int8_t, DO_QRDMULH_B)
61
DO_2OP_SAT(vqrdmulhh, 2, int16_t, DO_QRDMULH_H)
62
DO_2OP_SAT(vqrdmulhw, 4, int32_t, DO_QRDMULH_W)
63
64
+DO_2OP_SAT(vqaddub, 1, uint8_t, DO_UQADD_B)
65
+DO_2OP_SAT(vqadduh, 2, uint16_t, DO_UQADD_H)
66
+DO_2OP_SAT(vqadduw, 4, uint32_t, DO_UQADD_W)
67
+DO_2OP_SAT(vqaddsb, 1, int8_t, DO_SQADD_B)
68
+DO_2OP_SAT(vqaddsh, 2, int16_t, DO_SQADD_H)
69
+DO_2OP_SAT(vqaddsw, 4, int32_t, DO_SQADD_W)
70
+
71
+DO_2OP_SAT(vqsubub, 1, uint8_t, DO_UQSUB_B)
72
+DO_2OP_SAT(vqsubuh, 2, uint16_t, DO_UQSUB_H)
73
+DO_2OP_SAT(vqsubuw, 4, uint32_t, DO_UQSUB_W)
74
+DO_2OP_SAT(vqsubsb, 1, int8_t, DO_SQSUB_B)
75
+DO_2OP_SAT(vqsubsh, 2, int16_t, DO_SQSUB_H)
76
+DO_2OP_SAT(vqsubsw, 4, int32_t, DO_SQSUB_W)
77
+
78
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
79
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
80
uint32_t rm) \
81
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/target/arm/translate-mve.c
84
+++ b/target/arm/translate-mve.c
85
@@ -XXX,XX +XXX,XX @@ DO_2OP(VMULL_TS, vmullts)
86
DO_2OP(VMULL_TU, vmulltu)
87
DO_2OP(VQDMULH, vqdmulh)
88
DO_2OP(VQRDMULH, vqrdmulh)
89
+DO_2OP(VQADD_S, vqadds)
90
+DO_2OP(VQADD_U, vqaddu)
91
+DO_2OP(VQSUB_S, vqsubs)
92
+DO_2OP(VQSUB_U, vqsubu)
93
94
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
95
MVEGenTwoOpScalarFn fn)
46
--
96
--
47
2.20.1
97
2.20.1
48
98
49
99
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Implement the MVE VQSHL insn (encoding T4, which is the
2
vector-shift-by-vector version).
2
3
3
We hint the 'has_rpu' property is no longer required since commit
4
The DO_SQSHL_OP and DO_UQSHL_OP macros here are derived from
4
6908ec448b4 ("xlnx-zynqmp: Properly support the smp command line
5
the neon_helper.c code for qshl_u{8,16,32} and qshl_s{8,16,32}.
5
option") which was released in QEMU v2.11.0.
6
6
7
Beside, this device is marked 'user_creatable = false', so the
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
only thing that could be setting the property is the board code
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
that creates the device.
9
Message-id: 20210617121628.20116-33-peter.maydell@linaro.org
10
---
11
target/arm/helper-mve.h | 8 ++++++++
12
target/arm/mve.decode | 12 ++++++++++++
13
target/arm/mve_helper.c | 34 ++++++++++++++++++++++++++++++++++
14
target/arm/translate-mve.c | 2 ++
15
4 files changed, 56 insertions(+)
10
16
11
Since the property is not user-facing, we can remove it without
17
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
12
going through the deprecation process.
13
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
16
Message-id: 20210219144350.1979905-1-f4bug@amsat.org
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
---
19
include/hw/arm/xlnx-zynqmp.h | 2 --
20
hw/arm/xlnx-zynqmp.c | 6 ------
21
2 files changed, 8 deletions(-)
22
23
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
24
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/arm/xlnx-zynqmp.h
19
--- a/target/arm/helper-mve.h
26
+++ b/include/hw/arm/xlnx-zynqmp.h
20
+++ b/target/arm/helper-mve.h
27
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqsubub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
bool secure;
22
DEF_HELPER_FLAGS_4(mve_vqsubuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
/* Has the ARM Virtualization extensions? */
23
DEF_HELPER_FLAGS_4(mve_vqsubuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
bool virt;
24
31
- /* Has the RPU subsystem? */
25
+DEF_HELPER_FLAGS_4(mve_vqshlsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
- bool has_rpu;
26
+DEF_HELPER_FLAGS_4(mve_vqshlsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
27
+DEF_HELPER_FLAGS_4(mve_vqshlsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
/* CAN bus. */
28
+
35
CanBusState *canbus[XLNX_ZYNQMP_NUM_CAN];
29
+DEF_HELPER_FLAGS_4(mve_vqshlub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
30
+DEF_HELPER_FLAGS_4(mve_vqshluh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
+DEF_HELPER_FLAGS_4(mve_vqshluw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
+
33
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
34
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
35
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
36
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
37
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
38
--- a/hw/arm/xlnx-zynqmp.c
38
--- a/target/arm/mve.decode
39
+++ b/hw/arm/xlnx-zynqmp.c
39
+++ b/target/arm/mve.decode
40
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
40
@@ -XXX,XX +XXX,XX @@
41
}
41
@2op .... .... .. size:2 .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn
42
@2op_nosz .... .... .... .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn size=0
43
44
+# The _rev suffix indicates that Vn and Vm are reversed. This is
45
+# the case for shifts. In the Arm ARM these insns are documented
46
+# with the Vm and Vn fields in their usual places, but in the
47
+# assembly the operands are listed "backwards", ie in the order
48
+# Qd, Qm, Qn where other insns use Qd, Qn, Qm. For QEMU we choose
49
+# to consider Vm and Vn as being in different fields in the insn.
50
+# This gives us consistency with A64 and Neon.
51
+@2op_rev .... .... .. size:2 .... .... .... .... .... &2op qd=%qd qm=%qn qn=%qm
52
+
53
@2scalar .... .... .. size:2 .... .... .... .... rm:4 &2scalar qd=%qd qn=%qn
54
@2scalar_nosz .... .... .... .... .... .... .... rm:4 &2scalar qd=%qd qn=%qn
55
56
@@ -XXX,XX +XXX,XX @@ VQADD_U 111 1 1111 0 . .. ... 0 ... 0 0000 . 1 . 1 ... 0 @2op
57
VQSUB_S 111 0 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
58
VQSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
59
60
+VQSHL_S 111 0 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
61
+VQSHL_U 111 1 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
62
+
63
# Vector miscellaneous
64
65
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
66
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/mve_helper.c
69
+++ b/target/arm/mve_helper.c
70
@@ -XXX,XX +XXX,XX @@ DO_1OP(vfnegs, 8, uint64_t, DO_FNEGS)
71
mve_advance_vpt(env); \
42
}
72
}
43
73
44
- if (s->has_rpu) {
74
+/* provide unsigned 2-op helpers for all sizes */
45
- info_report("The 'has_rpu' property is no longer required, to use the "
75
+#define DO_2OP_SAT_U(OP, FN) \
46
- "RPUs just use -smp 6.");
76
+ DO_2OP_SAT(OP##b, 1, uint8_t, FN) \
47
- }
77
+ DO_2OP_SAT(OP##h, 2, uint16_t, FN) \
48
-
78
+ DO_2OP_SAT(OP##w, 4, uint32_t, FN)
49
xlnx_zynqmp_create_rpu(ms, s, boot_cpu, &err);
79
+
50
if (err) {
80
+/* provide signed 2-op helpers for all sizes */
51
error_propagate(errp, err);
81
+#define DO_2OP_SAT_S(OP, FN) \
52
@@ -XXX,XX +XXX,XX @@ static Property xlnx_zynqmp_props[] = {
82
+ DO_2OP_SAT(OP##b, 1, int8_t, FN) \
53
DEFINE_PROP_STRING("boot-cpu", XlnxZynqMPState, boot_cpu),
83
+ DO_2OP_SAT(OP##h, 2, int16_t, FN) \
54
DEFINE_PROP_BOOL("secure", XlnxZynqMPState, secure, false),
84
+ DO_2OP_SAT(OP##w, 4, int32_t, FN)
55
DEFINE_PROP_BOOL("virtualization", XlnxZynqMPState, virt, false),
85
+
56
- DEFINE_PROP_BOOL("has_rpu", XlnxZynqMPState, has_rpu, false),
86
#define DO_AND(N, M) ((N) & (M))
57
DEFINE_PROP_LINK("ddr-ram", XlnxZynqMPState, ddr_ram, TYPE_MEMORY_REGION,
87
#define DO_BIC(N, M) ((N) & ~(M))
58
MemoryRegion *),
88
#define DO_ORR(N, M) ((N) | (M))
59
DEFINE_PROP_LINK("canbus0", XlnxZynqMPState, canbus[0], TYPE_CAN_BUS,
89
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT(vqsubsb, 1, int8_t, DO_SQSUB_B)
90
DO_2OP_SAT(vqsubsh, 2, int16_t, DO_SQSUB_H)
91
DO_2OP_SAT(vqsubsw, 4, int32_t, DO_SQSUB_W)
92
93
+/*
94
+ * This wrapper fixes up the impedance mismatch between do_sqrshl_bhs()
95
+ * and friends wanting a uint32_t* sat and our needing a bool*.
96
+ */
97
+#define WRAP_QRSHL_HELPER(FN, N, M, ROUND, satp) \
98
+ ({ \
99
+ uint32_t su32 = 0; \
100
+ typeof(N) r = FN(N, (int8_t)(M), sizeof(N) * 8, ROUND, &su32); \
101
+ if (su32) { \
102
+ *satp = true; \
103
+ } \
104
+ r; \
105
+ })
106
+
107
+#define DO_SQSHL_OP(N, M, satp) \
108
+ WRAP_QRSHL_HELPER(do_sqrshl_bhs, N, M, false, satp)
109
+#define DO_UQSHL_OP(N, M, satp) \
110
+ WRAP_QRSHL_HELPER(do_uqrshl_bhs, N, M, false, satp)
111
+
112
+DO_2OP_SAT_S(vqshls, DO_SQSHL_OP)
113
+DO_2OP_SAT_U(vqshlu, DO_UQSHL_OP)
114
+
115
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
116
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
117
uint32_t rm) \
118
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
119
index XXXXXXX..XXXXXXX 100644
120
--- a/target/arm/translate-mve.c
121
+++ b/target/arm/translate-mve.c
122
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQADD_S, vqadds)
123
DO_2OP(VQADD_U, vqaddu)
124
DO_2OP(VQSUB_S, vqsubs)
125
DO_2OP(VQSUB_U, vqsubu)
126
+DO_2OP(VQSHL_S, vqshls)
127
+DO_2OP(VQSHL_U, vqshlu)
128
129
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
130
MVEGenTwoOpScalarFn fn)
60
--
131
--
61
2.20.1
132
2.20.1
62
133
63
134
diff view generated by jsdifflib
1
The function tc6393xb_draw_graphic32() is called in exactly one place,
1
Implement the MV VQRSHL (vector) insn. Again, the code to perform
2
so just inline the function body at its callsite. This allows us to
2
the actual shifts is borrowed from neon_helper.c.
3
drop the template header entirely.
4
5
The code move includes a single added space after 'for' to fix
6
the coding style.
7
3
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
6
Message-id: 20210617121628.20116-34-peter.maydell@linaro.org
11
Message-id: 20210215103215.4944-5-peter.maydell@linaro.org
12
---
7
---
13
hw/display/tc6393xb_template.h | 45 ----------------------------------
8
target/arm/helper-mve.h | 8 ++++++++
14
hw/display/tc6393xb.c | 23 ++++++++++++++---
9
target/arm/mve.decode | 3 +++
15
2 files changed, 19 insertions(+), 49 deletions(-)
10
target/arm/mve_helper.c | 6 ++++++
16
delete mode 100644 hw/display/tc6393xb_template.h
11
target/arm/translate-mve.c | 2 ++
12
4 files changed, 19 insertions(+)
17
13
18
diff --git a/hw/display/tc6393xb_template.h b/hw/display/tc6393xb_template.h
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
19
deleted file mode 100644
20
index XXXXXXX..XXXXXXX
21
--- a/hw/display/tc6393xb_template.h
22
+++ /dev/null
23
@@ -XXX,XX +XXX,XX @@
24
-/*
25
- * Toshiba TC6393XB I/O Controller.
26
- * Found in Sharp Zaurus SL-6000 (tosa) or some
27
- * Toshiba e-Series PDAs.
28
- *
29
- * FB support code. Based on G364 fb emulator
30
- *
31
- * Copyright (c) 2007 Hervé Poussineau
32
- *
33
- * This program is free software; you can redistribute it and/or
34
- * modify it under the terms of the GNU General Public License as
35
- * published by the Free Software Foundation; either version 2 of
36
- * the License, or (at your option) any later version.
37
- *
38
- * This program is distributed in the hope that it will be useful,
39
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
40
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41
- * GNU General Public License for more details.
42
- *
43
- * You should have received a copy of the GNU General Public License along
44
- * with this program; if not, see <http://www.gnu.org/licenses/>.
45
- */
46
-
47
-static void tc6393xb_draw_graphic32(TC6393xbState *s)
48
-{
49
- DisplaySurface *surface = qemu_console_surface(s->con);
50
- int i;
51
- uint16_t *data_buffer;
52
- uint8_t *data_display;
53
-
54
- data_buffer = s->vram_ptr;
55
- data_display = surface_data(surface);
56
- for(i = 0; i < s->scr_height; i++) {
57
- int j;
58
- for (j = 0; j < s->scr_width; j++, data_display += 4, data_buffer++) {
59
- uint16_t color = *data_buffer;
60
- uint32_t dest_color = rgb_to_pixel32(
61
- ((color & 0xf800) * 0x108) >> 11,
62
- ((color & 0x7e0) * 0x41) >> 9,
63
- ((color & 0x1f) * 0x21) >> 2
64
- );
65
- *(uint32_t *)data_display = dest_color;
66
- }
67
- }
68
-}
69
diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
70
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
71
--- a/hw/display/tc6393xb.c
16
--- a/target/arm/helper-mve.h
72
+++ b/hw/display/tc6393xb.c
17
+++ b/target/arm/helper-mve.h
73
@@ -XXX,XX +XXX,XX @@ static void tc6393xb_nand_writeb(TC6393xbState *s, hwaddr addr, uint32_t value)
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqshlub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
74
(uint32_t) addr, value & 0xff);
19
DEF_HELPER_FLAGS_4(mve_vqshluh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
75
}
20
DEF_HELPER_FLAGS_4(mve_vqshluw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
76
21
77
-#define BITS 32
22
+DEF_HELPER_FLAGS_4(mve_vqrshlsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
78
-#include "tc6393xb_template.h"
23
+DEF_HELPER_FLAGS_4(mve_vqrshlsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
79
-
24
+DEF_HELPER_FLAGS_4(mve_vqrshlsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
80
static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update)
81
{
82
- tc6393xb_draw_graphic32(s);
83
+ DisplaySurface *surface = qemu_console_surface(s->con);
84
+ int i;
85
+ uint16_t *data_buffer;
86
+ uint8_t *data_display;
87
+
25
+
88
+ data_buffer = s->vram_ptr;
26
+DEF_HELPER_FLAGS_4(mve_vqrshlub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
89
+ data_display = surface_data(surface);
27
+DEF_HELPER_FLAGS_4(mve_vqrshluh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
90
+ for (i = 0; i < s->scr_height; i++) {
28
+DEF_HELPER_FLAGS_4(mve_vqrshluw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
91
+ int j;
29
+
92
+ for (j = 0; j < s->scr_width; j++, data_display += 4, data_buffer++) {
30
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
93
+ uint16_t color = *data_buffer;
31
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
94
+ uint32_t dest_color = rgb_to_pixel32(
32
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
95
+ ((color & 0xf800) * 0x108) >> 11,
33
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
96
+ ((color & 0x7e0) * 0x41) >> 9,
34
index XXXXXXX..XXXXXXX 100644
97
+ ((color & 0x1f) * 0x21) >> 2
35
--- a/target/arm/mve.decode
98
+ );
36
+++ b/target/arm/mve.decode
99
+ *(uint32_t *)data_display = dest_color;
37
@@ -XXX,XX +XXX,XX @@ VQSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
100
+ }
38
VQSHL_S 111 0 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
101
+ }
39
VQSHL_U 111 1 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
102
dpy_gfx_update_full(s->con);
40
103
}
41
+VQRSHL_S 111 0 1111 0 . .. ... 0 ... 0 0101 . 1 . 1 ... 0 @2op_rev
104
42
+VQRSHL_U 111 1 1111 0 . .. ... 0 ... 0 0101 . 1 . 1 ... 0 @2op_rev
43
+
44
# Vector miscellaneous
45
46
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
47
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/mve_helper.c
50
+++ b/target/arm/mve_helper.c
51
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT(vqsubsw, 4, int32_t, DO_SQSUB_W)
52
WRAP_QRSHL_HELPER(do_sqrshl_bhs, N, M, false, satp)
53
#define DO_UQSHL_OP(N, M, satp) \
54
WRAP_QRSHL_HELPER(do_uqrshl_bhs, N, M, false, satp)
55
+#define DO_SQRSHL_OP(N, M, satp) \
56
+ WRAP_QRSHL_HELPER(do_sqrshl_bhs, N, M, true, satp)
57
+#define DO_UQRSHL_OP(N, M, satp) \
58
+ WRAP_QRSHL_HELPER(do_uqrshl_bhs, N, M, true, satp)
59
60
DO_2OP_SAT_S(vqshls, DO_SQSHL_OP)
61
DO_2OP_SAT_U(vqshlu, DO_UQSHL_OP)
62
+DO_2OP_SAT_S(vqrshls, DO_SQRSHL_OP)
63
+DO_2OP_SAT_U(vqrshlu, DO_UQRSHL_OP)
64
65
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
66
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
67
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/target/arm/translate-mve.c
70
+++ b/target/arm/translate-mve.c
71
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQSUB_S, vqsubs)
72
DO_2OP(VQSUB_U, vqsubu)
73
DO_2OP(VQSHL_S, vqshls)
74
DO_2OP(VQSHL_U, vqshlu)
75
+DO_2OP(VQRSHL_S, vqrshls)
76
+DO_2OP(VQRSHL_U, vqrshlu)
77
78
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
79
MVEGenTwoOpScalarFn fn)
105
--
80
--
106
2.20.1
81
2.20.1
107
82
108
83
diff view generated by jsdifflib
1
Now the template header is included only for BITS==32, expand
1
Implement the MVE VSHL insn (vector form).
2
out all the macros that depended on the BITS setting.
3
2
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210215103215.4944-4-peter.maydell@linaro.org
5
Message-id: 20210617121628.20116-35-peter.maydell@linaro.org
7
---
6
---
8
hw/display/tc6393xb_template.h | 35 ++++------------------------------
7
target/arm/helper-mve.h | 8 ++++++++
9
1 file changed, 4 insertions(+), 31 deletions(-)
8
target/arm/mve.decode | 3 +++
9
target/arm/mve_helper.c | 6 ++++++
10
target/arm/translate-mve.c | 2 ++
11
4 files changed, 19 insertions(+)
10
12
11
diff --git a/hw/display/tc6393xb_template.h b/hw/display/tc6393xb_template.h
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
12
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
13
--- a/hw/display/tc6393xb_template.h
15
--- a/target/arm/helper-mve.h
14
+++ b/hw/display/tc6393xb_template.h
16
+++ b/target/arm/helper-mve.h
15
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqsubub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
16
* with this program; if not, see <http://www.gnu.org/licenses/>.
18
DEF_HELPER_FLAGS_4(mve_vqsubuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
17
*/
19
DEF_HELPER_FLAGS_4(mve_vqsubuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
18
20
19
-#if BITS == 8
21
+DEF_HELPER_FLAGS_4(mve_vshlsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
-# define SET_PIXEL(addr, color) (*(uint8_t *)addr = color)
22
+DEF_HELPER_FLAGS_4(mve_vshlsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
-#elif BITS == 15 || BITS == 16
23
+DEF_HELPER_FLAGS_4(mve_vshlsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
-# define SET_PIXEL(addr, color) (*(uint16_t *)addr = color)
24
+
23
-#elif BITS == 24
25
+DEF_HELPER_FLAGS_4(mve_vshlub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
-# define SET_PIXEL(addr, color) \
26
+DEF_HELPER_FLAGS_4(mve_vshluh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
- do { \
27
+DEF_HELPER_FLAGS_4(mve_vshluw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
- addr[0] = color; \
28
+
27
- addr[1] = (color) >> 8; \
29
DEF_HELPER_FLAGS_4(mve_vqshlsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
- addr[2] = (color) >> 16; \
30
DEF_HELPER_FLAGS_4(mve_vqshlsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
- } while (0)
31
DEF_HELPER_FLAGS_4(mve_vqshlsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
-#elif BITS == 32
32
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
31
-# define SET_PIXEL(addr, color) (*(uint32_t *)addr = color)
33
index XXXXXXX..XXXXXXX 100644
32
-#else
34
--- a/target/arm/mve.decode
33
-# error unknown bit depth
35
+++ b/target/arm/mve.decode
34
-#endif
36
@@ -XXX,XX +XXX,XX @@ VQADD_U 111 1 1111 0 . .. ... 0 ... 0 0000 . 1 . 1 ... 0 @2op
35
-
37
VQSUB_S 111 0 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
36
-
38
VQSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
37
-static void glue(tc6393xb_draw_graphic, BITS)(TC6393xbState *s)
39
38
+static void tc6393xb_draw_graphic32(TC6393xbState *s)
40
+VSHL_S 111 0 1111 0 . .. ... 0 ... 0 0100 . 1 . 0 ... 0 @2op_rev
41
+VSHL_U 111 1 1111 0 . .. ... 0 ... 0 0100 . 1 . 0 ... 0 @2op_rev
42
+
43
VQSHL_S 111 0 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
44
VQSHL_U 111 1 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
45
46
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/mve_helper.c
49
+++ b/target/arm/mve_helper.c
50
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vhaddu, do_vhadd_u)
51
DO_2OP_S(vhsubs, do_vhsub_s)
52
DO_2OP_U(vhsubu, do_vhsub_u)
53
54
+#define DO_VSHLS(N, M) do_sqrshl_bhs(N, (int8_t)(M), sizeof(N) * 8, false, NULL)
55
+#define DO_VSHLU(N, M) do_uqrshl_bhs(N, (int8_t)(M), sizeof(N) * 8, false, NULL)
56
+
57
+DO_2OP_S(vshls, DO_VSHLS)
58
+DO_2OP_U(vshlu, DO_VSHLU)
59
+
60
static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
39
{
61
{
40
DisplaySurface *surface = qemu_console_surface(s->con);
62
if (val > max) {
41
int i;
63
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
42
@@ -XXX,XX +XXX,XX @@ static void glue(tc6393xb_draw_graphic, BITS)(TC6393xbState *s)
64
index XXXXXXX..XXXXXXX 100644
43
data_buffer = s->vram_ptr;
65
--- a/target/arm/translate-mve.c
44
data_display = surface_data(surface);
66
+++ b/target/arm/translate-mve.c
45
for(i = 0; i < s->scr_height; i++) {
67
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQADD_S, vqadds)
46
-#if (BITS == 16)
68
DO_2OP(VQADD_U, vqaddu)
47
- memcpy(data_display, data_buffer, s->scr_width * 2);
69
DO_2OP(VQSUB_S, vqsubs)
48
- data_buffer += s->scr_width;
70
DO_2OP(VQSUB_U, vqsubu)
49
- data_display += surface_stride(surface);
71
+DO_2OP(VSHL_S, vshls)
50
-#else
72
+DO_2OP(VSHL_U, vshlu)
51
int j;
73
DO_2OP(VQSHL_S, vqshls)
52
- for (j = 0; j < s->scr_width; j++, data_display += BITS / 8, data_buffer++) {
74
DO_2OP(VQSHL_U, vqshlu)
53
+ for (j = 0; j < s->scr_width; j++, data_display += 4, data_buffer++) {
75
DO_2OP(VQRSHL_S, vqrshls)
54
uint16_t color = *data_buffer;
55
- uint32_t dest_color = glue(rgb_to_pixel, BITS)(
56
+ uint32_t dest_color = rgb_to_pixel32(
57
((color & 0xf800) * 0x108) >> 11,
58
((color & 0x7e0) * 0x41) >> 9,
59
((color & 0x1f) * 0x21) >> 2
60
);
61
- SET_PIXEL(data_display, dest_color);
62
+ *(uint32_t *)data_display = dest_color;
63
}
64
-#endif
65
}
66
}
67
-
68
-#undef BITS
69
-#undef SET_PIXEL
70
--
76
--
71
2.20.1
77
2.20.1
72
78
73
79
diff view generated by jsdifflib
1
For a long time now the UI layer has guaranteed that the console
1
Implement the MVE VRSHL insn (vector form).
2
surface is always 32 bits per pixel RGB. Remove the legacy dead
3
code from the tc6393xb display device which was handling the
4
possibility that the console surface was some other format.
5
2
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215103215.4944-3-peter.maydell@linaro.org
5
Message-id: 20210617121628.20116-36-peter.maydell@linaro.org
9
---
6
---
10
include/ui/console.h | 10 ----------
7
target/arm/helper-mve.h | 8 ++++++++
11
hw/display/tc6393xb.c | 33 +--------------------------------
8
target/arm/mve.decode | 3 +++
12
2 files changed, 1 insertion(+), 42 deletions(-)
9
target/arm/mve_helper.c | 4 ++++
10
target/arm/translate-mve.c | 2 ++
11
4 files changed, 17 insertions(+)
13
12
14
diff --git a/include/ui/console.h b/include/ui/console.h
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/include/ui/console.h
15
--- a/target/arm/helper-mve.h
17
+++ b/include/ui/console.h
16
+++ b/target/arm/helper-mve.h
18
@@ -XXX,XX +XXX,XX @@ PixelFormat qemu_default_pixelformat(int bpp);
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vshlub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
DisplaySurface *qemu_create_displaysurface(int width, int height);
18
DEF_HELPER_FLAGS_4(mve_vshluh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
void qemu_free_displaysurface(DisplaySurface *surface);
19
DEF_HELPER_FLAGS_4(mve_vshluw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
20
22
-static inline int is_surface_bgr(DisplaySurface *surface)
21
+DEF_HELPER_FLAGS_4(mve_vrshlsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
-{
22
+DEF_HELPER_FLAGS_4(mve_vrshlsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
- if (PIXMAN_FORMAT_BPP(surface->format) == 32 &&
23
+DEF_HELPER_FLAGS_4(mve_vrshlsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
- PIXMAN_FORMAT_TYPE(surface->format) == PIXMAN_TYPE_ABGR) {
24
+
26
- return 1;
25
+DEF_HELPER_FLAGS_4(mve_vrshlub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
- } else {
26
+DEF_HELPER_FLAGS_4(mve_vrshluh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
- return 0;
27
+DEF_HELPER_FLAGS_4(mve_vrshluw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
- }
28
+
30
-}
29
DEF_HELPER_FLAGS_4(mve_vqshlsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
-
30
DEF_HELPER_FLAGS_4(mve_vqshlsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
static inline int is_buffer_shared(DisplaySurface *surface)
31
DEF_HELPER_FLAGS_4(mve_vqshlsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/mve.decode
35
+++ b/target/arm/mve.decode
36
@@ -XXX,XX +XXX,XX @@ VQSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
37
VSHL_S 111 0 1111 0 . .. ... 0 ... 0 0100 . 1 . 0 ... 0 @2op_rev
38
VSHL_U 111 1 1111 0 . .. ... 0 ... 0 0100 . 1 . 0 ... 0 @2op_rev
39
40
+VRSHL_S 111 0 1111 0 . .. ... 0 ... 0 0101 . 1 . 0 ... 0 @2op_rev
41
+VRSHL_U 111 1 1111 0 . .. ... 0 ... 0 0101 . 1 . 0 ... 0 @2op_rev
42
+
43
VQSHL_S 111 0 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
44
VQSHL_U 111 1 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
45
46
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/mve_helper.c
49
+++ b/target/arm/mve_helper.c
50
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vhsubu, do_vhsub_u)
51
52
#define DO_VSHLS(N, M) do_sqrshl_bhs(N, (int8_t)(M), sizeof(N) * 8, false, NULL)
53
#define DO_VSHLU(N, M) do_uqrshl_bhs(N, (int8_t)(M), sizeof(N) * 8, false, NULL)
54
+#define DO_VRSHLS(N, M) do_sqrshl_bhs(N, (int8_t)(M), sizeof(N) * 8, true, NULL)
55
+#define DO_VRSHLU(N, M) do_uqrshl_bhs(N, (int8_t)(M), sizeof(N) * 8, true, NULL)
56
57
DO_2OP_S(vshls, DO_VSHLS)
58
DO_2OP_U(vshlu, DO_VSHLU)
59
+DO_2OP_S(vrshls, DO_VRSHLS)
60
+DO_2OP_U(vrshlu, DO_VRSHLU)
61
62
static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
33
{
63
{
34
return !(surface->flags & QEMU_ALLOCATED_FLAG);
64
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
35
diff --git a/hw/display/tc6393xb.c b/hw/display/tc6393xb.c
36
index XXXXXXX..XXXXXXX 100644
65
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/display/tc6393xb.c
66
--- a/target/arm/translate-mve.c
38
+++ b/hw/display/tc6393xb.c
67
+++ b/target/arm/translate-mve.c
39
@@ -XXX,XX +XXX,XX @@ static void tc6393xb_nand_writeb(TC6393xbState *s, hwaddr addr, uint32_t value)
68
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQSUB_S, vqsubs)
40
(uint32_t) addr, value & 0xff);
69
DO_2OP(VQSUB_U, vqsubu)
41
}
70
DO_2OP(VSHL_S, vshls)
42
71
DO_2OP(VSHL_U, vshlu)
43
-#define BITS 8
72
+DO_2OP(VRSHL_S, vrshls)
44
-#include "tc6393xb_template.h"
73
+DO_2OP(VRSHL_U, vrshlu)
45
-#define BITS 15
74
DO_2OP(VQSHL_S, vqshls)
46
-#include "tc6393xb_template.h"
75
DO_2OP(VQSHL_U, vqshlu)
47
-#define BITS 16
76
DO_2OP(VQRSHL_S, vqrshls)
48
-#include "tc6393xb_template.h"
49
-#define BITS 24
50
-#include "tc6393xb_template.h"
51
#define BITS 32
52
#include "tc6393xb_template.h"
53
54
static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update)
55
{
56
- DisplaySurface *surface = qemu_console_surface(s->con);
57
-
58
- switch (surface_bits_per_pixel(surface)) {
59
- case 8:
60
- tc6393xb_draw_graphic8(s);
61
- break;
62
- case 15:
63
- tc6393xb_draw_graphic15(s);
64
- break;
65
- case 16:
66
- tc6393xb_draw_graphic16(s);
67
- break;
68
- case 24:
69
- tc6393xb_draw_graphic24(s);
70
- break;
71
- case 32:
72
- tc6393xb_draw_graphic32(s);
73
- break;
74
- default:
75
- printf("tc6393xb: unknown depth %d\n",
76
- surface_bits_per_pixel(surface));
77
- return;
78
- }
79
-
80
+ tc6393xb_draw_graphic32(s);
81
dpy_gfx_update_full(s->con);
82
}
83
84
--
77
--
85
2.20.1
78
2.20.1
86
79
87
80
diff view generated by jsdifflib
1
The AN505 and AN521 have the same layout of RAM; the AN524 does not.
1
Implement the MVE VQDMLADH and VQRDMLADH insns. These multiply
2
Replace the current hard-coding of where the RAM is and which parts
2
elements, and then add pairs of products, double, possibly round,
3
of it are behind which MPCs with a data-driven approach.
3
saturate and return the high half of the result.
4
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210215115138.20465-17-peter.maydell@linaro.org
7
Message-id: 20210617121628.20116-37-peter.maydell@linaro.org
8
---
8
---
9
hw/arm/mps2-tz.c | 175 +++++++++++++++++++++++++++++++++++++----------
9
target/arm/helper-mve.h | 16 +++++++
10
1 file changed, 138 insertions(+), 37 deletions(-)
10
target/arm/mve.decode | 5 +++
11
target/arm/mve_helper.c | 89 ++++++++++++++++++++++++++++++++++++++
12
target/arm/translate-mve.c | 4 ++
13
4 files changed, 114 insertions(+)
11
14
12
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
15
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
13
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/mps2-tz.c
17
--- a/target/arm/helper-mve.h
15
+++ b/hw/arm/mps2-tz.c
18
+++ b/target/arm/helper-mve.h
16
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqrshlub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
17
#include "qom/object.h"
20
DEF_HELPER_FLAGS_4(mve_vqrshluh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
18
21
DEF_HELPER_FLAGS_4(mve_vqrshluw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
#define MPS2TZ_NUMIRQ_MAX 92
22
20
+#define MPS2TZ_RAM_MAX 4
23
+DEF_HELPER_FLAGS_4(mve_vqdmladhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
24
+DEF_HELPER_FLAGS_4(mve_vqdmladhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
typedef enum MPS2TZFPGAType {
25
+DEF_HELPER_FLAGS_4(mve_vqdmladhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
FPGA_AN505,
26
+
24
FPGA_AN521,
27
+DEF_HELPER_FLAGS_4(mve_vqdmladhxb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
} MPS2TZFPGAType;
28
+DEF_HELPER_FLAGS_4(mve_vqdmladhxh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
+DEF_HELPER_FLAGS_4(mve_vqdmladhxw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
+
31
+DEF_HELPER_FLAGS_4(mve_vqrdmladhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
+DEF_HELPER_FLAGS_4(mve_vqrdmladhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
+DEF_HELPER_FLAGS_4(mve_vqrdmladhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
+
35
+DEF_HELPER_FLAGS_4(mve_vqrdmladhxb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
+DEF_HELPER_FLAGS_4(mve_vqrdmladhxh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
37
+DEF_HELPER_FLAGS_4(mve_vqrdmladhxw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
38
+
39
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
40
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
41
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
42
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/mve.decode
45
+++ b/target/arm/mve.decode
46
@@ -XXX,XX +XXX,XX @@ VQSHL_U 111 1 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
47
VQRSHL_S 111 0 1111 0 . .. ... 0 ... 0 0101 . 1 . 1 ... 0 @2op_rev
48
VQRSHL_U 111 1 1111 0 . .. ... 0 ... 0 0101 . 1 . 1 ... 0 @2op_rev
49
50
+VQDMLADH 1110 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 0 @2op
51
+VQDMLADHX 1110 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 0 @2op
52
+VQRDMLADH 1110 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 1 @2op
53
+VQRDMLADHX 1110 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 1 @2op
54
+
55
# Vector miscellaneous
56
57
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
58
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/mve_helper.c
61
+++ b/target/arm/mve_helper.c
62
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT_U(vqshlu, DO_UQSHL_OP)
63
DO_2OP_SAT_S(vqrshls, DO_SQRSHL_OP)
64
DO_2OP_SAT_U(vqrshlu, DO_UQRSHL_OP)
26
65
27
+/*
66
+/*
28
+ * Define the layout of RAM in a board, including which parts are
67
+ * Multiply add dual returning high half
29
+ * behind which MPCs.
68
+ * The 'FN' here takes four inputs A, B, C, D, a 0/1 indicator of
30
+ * mrindex specifies the index into mms->ram[] to use for the backing RAM;
69
+ * whether to add the rounding constant, and the pointer to the
31
+ * -1 means "use the system RAM".
70
+ * saturation flag, and should do "(A * B + C * D) * 2 + rounding constant",
71
+ * saturate to twice the input size and return the high half; or
72
+ * (A * B - C * D) etc for VQDMLSDH.
32
+ */
73
+ */
33
+typedef struct RAMInfo {
74
+#define DO_VQDMLADH_OP(OP, ESIZE, TYPE, XCHG, ROUND, FN) \
34
+ const char *name;
75
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
35
+ uint32_t base;
76
+ void *vm) \
36
+ uint32_t size;
77
+ { \
37
+ int mpc; /* MPC number, -1 for "not behind an MPC" */
78
+ TYPE *d = vd, *n = vn, *m = vm; \
38
+ int mrindex;
79
+ uint16_t mask = mve_element_mask(env); \
39
+ int flags;
80
+ unsigned e; \
40
+} RAMInfo;
81
+ bool qc = false; \
82
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
83
+ bool sat = false; \
84
+ if ((e & 1) == XCHG) { \
85
+ TYPE r = FN(n[H##ESIZE(e)], \
86
+ m[H##ESIZE(e - XCHG)], \
87
+ n[H##ESIZE(e + (1 - 2 * XCHG))], \
88
+ m[H##ESIZE(e + (1 - XCHG))], \
89
+ ROUND, &sat); \
90
+ mergemask(&d[H##ESIZE(e)], r, mask); \
91
+ qc |= sat & mask & 1; \
92
+ } \
93
+ } \
94
+ if (qc) { \
95
+ env->vfp.qc[0] = qc; \
96
+ } \
97
+ mve_advance_vpt(env); \
98
+ }
41
+
99
+
42
+/*
100
+static int8_t do_vqdmladh_b(int8_t a, int8_t b, int8_t c, int8_t d,
43
+ * Flag values:
101
+ int round, bool *sat)
44
+ * IS_ALIAS: this RAM area is an alias to the upstream end of the
45
+ * MPC specified by its .mpc value
46
+ */
47
+#define IS_ALIAS 1
48
+
49
struct MPS2TZMachineClass {
50
MachineClass parent;
51
MPS2TZFPGAType fpga_type;
52
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineClass {
53
uint32_t fpgaio_num_leds; /* Number of LEDs in FPGAIO LED0 register */
54
bool fpgaio_has_switches; /* Does FPGAIO have SWITCH register? */
55
int numirq; /* Number of external interrupts */
56
+ const RAMInfo *raminfo;
57
const char *armsse_type;
58
};
59
60
@@ -XXX,XX +XXX,XX @@ struct MPS2TZMachineState {
61
MachineState parent;
62
63
ARMSSE iotkit;
64
- MemoryRegion ssram[3];
65
- MemoryRegion ssram1_m;
66
+ MemoryRegion ram[MPS2TZ_RAM_MAX];
67
MPS2SCC scc;
68
MPS2FPGAIO fpgaio;
69
TZPPC ppc[5];
70
- TZMPC ssram_mpc[3];
71
+ TZMPC mpc[3];
72
PL022State spi[5];
73
ArmSbconI2CState i2c[4];
74
UnimplementedDeviceState i2s_audio;
75
@@ -XXX,XX +XXX,XX @@ static const uint32_t an505_oscclk[] = {
76
25000000,
77
};
78
79
+static const RAMInfo an505_raminfo[] = { {
80
+ .name = "ssram-0",
81
+ .base = 0x00000000,
82
+ .size = 0x00400000,
83
+ .mpc = 0,
84
+ .mrindex = 0,
85
+ }, {
86
+ .name = "ssram-1",
87
+ .base = 0x28000000,
88
+ .size = 0x00200000,
89
+ .mpc = 1,
90
+ .mrindex = 1,
91
+ }, {
92
+ .name = "ssram-2",
93
+ .base = 0x28200000,
94
+ .size = 0x00200000,
95
+ .mpc = 2,
96
+ .mrindex = 2,
97
+ }, {
98
+ .name = "ssram-0-alias",
99
+ .base = 0x00400000,
100
+ .size = 0x00400000,
101
+ .mpc = 0,
102
+ .mrindex = 3,
103
+ .flags = IS_ALIAS,
104
+ }, {
105
+ /* Use the largest bit of contiguous RAM as our "system memory" */
106
+ .name = "mps.ram",
107
+ .base = 0x80000000,
108
+ .size = 16 * MiB,
109
+ .mpc = -1,
110
+ .mrindex = -1,
111
+ }, {
112
+ .name = NULL,
113
+ },
114
+};
115
+
116
+static const RAMInfo *find_raminfo_for_mpc(MPS2TZMachineState *mms, int mpc)
117
+{
102
+{
118
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
103
+ int64_t r = ((int64_t)a * b + (int64_t)c * d) * 2 + (round << 7);
119
+ const RAMInfo *p;
104
+ return do_sat_bhw(r, INT16_MIN, INT16_MAX, sat) >> 8;
120
+
121
+ for (p = mmc->raminfo; p->name; p++) {
122
+ if (p->mpc == mpc && !(p->flags & IS_ALIAS)) {
123
+ return p;
124
+ }
125
+ }
126
+ /* if raminfo array doesn't have an entry for each MPC this is a bug */
127
+ g_assert_not_reached();
128
+}
105
+}
129
+
106
+
130
+static MemoryRegion *mr_for_raminfo(MPS2TZMachineState *mms,
107
+static int16_t do_vqdmladh_h(int16_t a, int16_t b, int16_t c, int16_t d,
131
+ const RAMInfo *raminfo)
108
+ int round, bool *sat)
132
+{
109
+{
133
+ /* Return an initialized MemoryRegion for the RAMInfo. */
110
+ int64_t r = ((int64_t)a * b + (int64_t)c * d) * 2 + (round << 15);
134
+ MemoryRegion *ram;
111
+ return do_sat_bhw(r, INT32_MIN, INT32_MAX, sat) >> 16;
135
+
136
+ if (raminfo->mrindex < 0) {
137
+ /* Means this RAMInfo is for QEMU's "system memory" */
138
+ MachineState *machine = MACHINE(mms);
139
+ return machine->ram;
140
+ }
141
+
142
+ assert(raminfo->mrindex < MPS2TZ_RAM_MAX);
143
+ ram = &mms->ram[raminfo->mrindex];
144
+
145
+ memory_region_init_ram(ram, NULL, raminfo->name,
146
+ raminfo->size, &error_fatal);
147
+ return ram;
148
+}
112
+}
149
+
113
+
150
/* Create an alias of an entire original MemoryRegion @orig
114
+static int32_t do_vqdmladh_w(int32_t a, int32_t b, int32_t c, int32_t d,
151
* located at @base in the memory map.
115
+ int round, bool *sat)
152
*/
153
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_mpc(MPS2TZMachineState *mms, void *opaque,
154
const int *irqs)
155
{
156
TZMPC *mpc = opaque;
157
- int i = mpc - &mms->ssram_mpc[0];
158
- MemoryRegion *ssram = &mms->ssram[i];
159
+ int i = mpc - &mms->mpc[0];
160
MemoryRegion *upstream;
161
- char *mpcname = g_strdup_printf("%s-mpc", name);
162
- static uint32_t ramsize[] = { 0x00400000, 0x00200000, 0x00200000 };
163
- static uint32_t rambase[] = { 0x00000000, 0x28000000, 0x28200000 };
164
+ const RAMInfo *raminfo = find_raminfo_for_mpc(mms, i);
165
+ MemoryRegion *ram = mr_for_raminfo(mms, raminfo);
166
167
- memory_region_init_ram(ssram, NULL, name, ramsize[i], &error_fatal);
168
-
169
- object_initialize_child(OBJECT(mms), mpcname, mpc, TYPE_TZ_MPC);
170
- object_property_set_link(OBJECT(mpc), "downstream", OBJECT(ssram),
171
+ object_initialize_child(OBJECT(mms), name, mpc, TYPE_TZ_MPC);
172
+ object_property_set_link(OBJECT(mpc), "downstream", OBJECT(ram),
173
&error_fatal);
174
sysbus_realize(SYS_BUS_DEVICE(mpc), &error_fatal);
175
/* Map the upstream end of the MPC into system memory */
176
upstream = sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 1);
177
- memory_region_add_subregion(get_system_memory(), rambase[i], upstream);
178
+ memory_region_add_subregion(get_system_memory(), raminfo->base, upstream);
179
/* and connect its interrupt to the IoTKit */
180
qdev_connect_gpio_out_named(DEVICE(mpc), "irq", 0,
181
qdev_get_gpio_in_named(DEVICE(&mms->iotkit),
182
"mpcexp_status", i));
183
184
- /* The first SSRAM is a special case as it has an alias; accesses to
185
- * the alias region at 0x00400000 must also go to the MPC upstream.
186
- */
187
- if (i == 0) {
188
- make_ram_alias(&mms->ssram1_m, "mps.ssram1_m", upstream, 0x00400000);
189
- }
190
-
191
- g_free(mpcname);
192
/* Return the register interface MR for our caller to map behind the PPC */
193
return sysbus_mmio_get_region(SYS_BUS_DEVICE(mpc), 0);
194
}
195
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_i2c(MPS2TZMachineState *mms, void *opaque,
196
return sysbus_mmio_get_region(s, 0);
197
}
198
199
+static void create_non_mpc_ram(MPS2TZMachineState *mms)
200
+{
116
+{
117
+ int64_t m1 = (int64_t)a * b;
118
+ int64_t m2 = (int64_t)c * d;
119
+ int64_t r;
201
+ /*
120
+ /*
202
+ * Handle the RAMs which are either not behind MPCs or which are
121
+ * Architecturally we should do the entire add, double, round
203
+ * aliases to another MPC.
122
+ * and then check for saturation. We do three saturating adds,
123
+ * but we need to be careful about the order. If the first
124
+ * m1 + m2 saturates then it's impossible for the *2+rc to
125
+ * bring it back into the non-saturated range. However, if
126
+ * m1 + m2 is negative then it's possible that doing the doubling
127
+ * would take the intermediate result below INT64_MAX and the
128
+ * addition of the rounding constant then brings it back in range.
129
+ * So we add half the rounding constant before doubling rather
130
+ * than adding the rounding constant after the doubling.
204
+ */
131
+ */
205
+ const RAMInfo *p;
132
+ if (sadd64_overflow(m1, m2, &r) ||
206
+ MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
133
+ sadd64_overflow(r, (round << 30), &r) ||
207
+
134
+ sadd64_overflow(r, r, &r)) {
208
+ for (p = mmc->raminfo; p->name; p++) {
135
+ *sat = true;
209
+ if (p->flags & IS_ALIAS) {
136
+ return r < 0 ? INT32_MAX : INT32_MIN;
210
+ SysBusDevice *mpc_sbd = SYS_BUS_DEVICE(&mms->mpc[p->mpc]);
211
+ MemoryRegion *upstream = sysbus_mmio_get_region(mpc_sbd, 1);
212
+ make_ram_alias(&mms->ram[p->mrindex], p->name, upstream, p->base);
213
+ } else if (p->mpc == -1) {
214
+ /* RAM not behind an MPC */
215
+ MemoryRegion *mr = mr_for_raminfo(mms, p);
216
+ memory_region_add_subregion(get_system_memory(), p->base, mr);
217
+ }
218
+ }
137
+ }
138
+ return r >> 32;
219
+}
139
+}
220
+
140
+
221
static void mps2tz_common_init(MachineState *machine)
141
+DO_VQDMLADH_OP(vqdmladhb, 1, int8_t, 0, 0, do_vqdmladh_b)
222
{
142
+DO_VQDMLADH_OP(vqdmladhh, 2, int16_t, 0, 0, do_vqdmladh_h)
223
MPS2TZMachineState *mms = MPS2TZ_MACHINE(machine);
143
+DO_VQDMLADH_OP(vqdmladhw, 4, int32_t, 0, 0, do_vqdmladh_w)
224
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
144
+DO_VQDMLADH_OP(vqdmladhxb, 1, int8_t, 1, 0, do_vqdmladh_b)
225
qdev_connect_gpio_out_named(iotkitdev, "sec_resp_cfg", 0,
145
+DO_VQDMLADH_OP(vqdmladhxh, 2, int16_t, 1, 0, do_vqdmladh_h)
226
qdev_get_gpio_in(dev_splitter, 0));
146
+DO_VQDMLADH_OP(vqdmladhxw, 4, int32_t, 1, 0, do_vqdmladh_w)
227
228
- /* The IoTKit sets up much of the memory layout, including
229
+ /*
230
+ * The IoTKit sets up much of the memory layout, including
231
* the aliases between secure and non-secure regions in the
232
- * address space. The FPGA itself contains:
233
- *
234
- * 0x00000000..0x003fffff SSRAM1
235
- * 0x00400000..0x007fffff alias of SSRAM1
236
- * 0x28000000..0x283fffff 4MB SSRAM2 + SSRAM3
237
- * 0x40100000..0x4fffffff AHB Master Expansion 1 interface devices
238
- * 0x80000000..0x80ffffff 16MB PSRAM
239
- */
240
-
241
- /* The FPGA images have an odd combination of different RAMs,
242
+ * address space, and also most of the devices in the system.
243
+ * The FPGA itself contains various RAMs and some additional devices.
244
+ * The FPGA images have an odd combination of different RAMs,
245
* because in hardware they are different implementations and
246
* connected to different buses, giving varying performance/size
247
* tradeoffs. For QEMU they're all just RAM, though. We arbitrarily
248
- * call the 16MB our "system memory", as it's the largest lump.
249
+ * call the largest lump our "system memory".
250
*/
251
- memory_region_add_subregion(system_memory, 0x80000000, machine->ram);
252
253
/*
254
* The overflow IRQs for all UARTs are ORed together.
255
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
256
const PPCInfo an505_ppcs[] = { {
257
.name = "apb_ppcexp0",
258
.ports = {
259
- { "ssram-0", make_mpc, &mms->ssram_mpc[0], 0x58007000, 0x1000 },
260
- { "ssram-1", make_mpc, &mms->ssram_mpc[1], 0x58008000, 0x1000 },
261
- { "ssram-2", make_mpc, &mms->ssram_mpc[2], 0x58009000, 0x1000 },
262
+ { "ssram-0-mpc", make_mpc, &mms->mpc[0], 0x58007000, 0x1000 },
263
+ { "ssram-1-mpc", make_mpc, &mms->mpc[1], 0x58008000, 0x1000 },
264
+ { "ssram-2-mpc", make_mpc, &mms->mpc[2], 0x58009000, 0x1000 },
265
},
266
}, {
267
.name = "apb_ppcexp1",
268
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
269
270
create_unimplemented_device("FPGA NS PC", 0x48007000, 0x1000);
271
272
+ create_non_mpc_ram(mms);
273
+
147
+
274
armv7m_load_kernel(ARM_CPU(first_cpu), machine->kernel_filename, 0x400000);
148
+DO_VQDMLADH_OP(vqrdmladhb, 1, int8_t, 0, 1, do_vqdmladh_b)
275
}
149
+DO_VQDMLADH_OP(vqrdmladhh, 2, int16_t, 0, 1, do_vqdmladh_h)
276
150
+DO_VQDMLADH_OP(vqrdmladhw, 4, int32_t, 0, 1, do_vqdmladh_w)
277
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an505_class_init(ObjectClass *oc, void *data)
151
+DO_VQDMLADH_OP(vqrdmladhxb, 1, int8_t, 1, 1, do_vqdmladh_b)
278
mmc->fpgaio_num_leds = 2;
152
+DO_VQDMLADH_OP(vqrdmladhxh, 2, int16_t, 1, 1, do_vqdmladh_h)
279
mmc->fpgaio_has_switches = false;
153
+DO_VQDMLADH_OP(vqrdmladhxw, 4, int32_t, 1, 1, do_vqdmladh_w)
280
mmc->numirq = 92;
154
+
281
+ mmc->raminfo = an505_raminfo;
155
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
282
mmc->armsse_type = TYPE_IOTKIT;
156
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
283
}
157
uint32_t rm) \
284
158
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
285
@@ -XXX,XX +XXX,XX @@ static void mps2tz_an521_class_init(ObjectClass *oc, void *data)
159
index XXXXXXX..XXXXXXX 100644
286
mmc->fpgaio_num_leds = 2;
160
--- a/target/arm/translate-mve.c
287
mmc->fpgaio_has_switches = false;
161
+++ b/target/arm/translate-mve.c
288
mmc->numirq = 92;
162
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQSHL_S, vqshls)
289
+ mmc->raminfo = an505_raminfo; /* AN521 is the same as AN505 here */
163
DO_2OP(VQSHL_U, vqshlu)
290
mmc->armsse_type = TYPE_SSE200;
164
DO_2OP(VQRSHL_S, vqrshls)
291
}
165
DO_2OP(VQRSHL_U, vqrshlu)
292
166
+DO_2OP(VQDMLADH, vqdmladh)
167
+DO_2OP(VQDMLADHX, vqdmladhx)
168
+DO_2OP(VQRDMLADH, vqrdmladh)
169
+DO_2OP(VQRDMLADHX, vqrdmladhx)
170
171
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
172
MVEGenTwoOpScalarFn fn)
293
--
173
--
294
2.20.1
174
2.20.1
295
175
296
176
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Implement the MVE VQDMLSDH and VQRDMLSDH insns, which are
2
like VQDMLADH and VQRDMLADH except that products are subtracted
3
rather than added.
2
4
3
The STATUS register will be reset to IDLE in
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
cnpcm7xx_smbus_enter_reset(), no need to preset
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
it in instance_init().
7
Message-id: 20210617121628.20116-38-peter.maydell@linaro.org
8
---
9
target/arm/helper-mve.h | 16 ++++++++++++++
10
target/arm/mve.decode | 5 +++++
11
target/arm/mve_helper.c | 44 ++++++++++++++++++++++++++++++++++++++
12
target/arm/translate-mve.c | 4 ++++
13
4 files changed, 69 insertions(+)
6
14
7
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
15
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
8
Reviewed-by: Hao Wu <wuhaotsh@google.com>
9
Message-id: 20210228224813.312532-1-f4bug@amsat.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
hw/i2c/npcm7xx_smbus.c | 1 -
13
1 file changed, 1 deletion(-)
14
15
diff --git a/hw/i2c/npcm7xx_smbus.c b/hw/i2c/npcm7xx_smbus.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/i2c/npcm7xx_smbus.c
17
--- a/target/arm/helper-mve.h
18
+++ b/hw/i2c/npcm7xx_smbus.c
18
+++ b/target/arm/helper-mve.h
19
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_smbus_init(Object *obj)
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqrdmladhxb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
sysbus_init_mmio(sbd, &s->iomem);
20
DEF_HELPER_FLAGS_4(mve_vqrdmladhxh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
21
DEF_HELPER_FLAGS_4(mve_vqrdmladhxw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
s->bus = i2c_init_bus(DEVICE(s), "i2c-bus");
22
23
- s->status = NPCM7XX_SMBUS_STATUS_IDLE;
23
+DEF_HELPER_FLAGS_4(mve_vqdmlsdhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+DEF_HELPER_FLAGS_4(mve_vqdmlsdhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+DEF_HELPER_FLAGS_4(mve_vqdmlsdhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
+
27
+DEF_HELPER_FLAGS_4(mve_vqdmlsdhxb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+DEF_HELPER_FLAGS_4(mve_vqdmlsdhxh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
+DEF_HELPER_FLAGS_4(mve_vqdmlsdhxw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
+
31
+DEF_HELPER_FLAGS_4(mve_vqrdmlsdhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
+DEF_HELPER_FLAGS_4(mve_vqrdmlsdhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
+DEF_HELPER_FLAGS_4(mve_vqrdmlsdhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
+
35
+DEF_HELPER_FLAGS_4(mve_vqrdmlsdhxb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
+DEF_HELPER_FLAGS_4(mve_vqrdmlsdhxh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
37
+DEF_HELPER_FLAGS_4(mve_vqrdmlsdhxw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
38
+
39
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
40
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
41
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
42
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/mve.decode
45
+++ b/target/arm/mve.decode
46
@@ -XXX,XX +XXX,XX @@ VQDMLADHX 1110 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 0 @2op
47
VQRDMLADH 1110 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 1 @2op
48
VQRDMLADHX 1110 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 1 @2op
49
50
+VQDMLSDH 1111 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 0 @2op
51
+VQDMLSDHX 1111 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 0 @2op
52
+VQRDMLSDH 1111 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 1 @2op
53
+VQRDMLSDHX 1111 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 1 @2op
54
+
55
# Vector miscellaneous
56
57
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
58
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/mve_helper.c
61
+++ b/target/arm/mve_helper.c
62
@@ -XXX,XX +XXX,XX @@ static int32_t do_vqdmladh_w(int32_t a, int32_t b, int32_t c, int32_t d,
63
return r >> 32;
24
}
64
}
25
65
26
static const VMStateDescription vmstate_npcm7xx_smbus = {
66
+static int8_t do_vqdmlsdh_b(int8_t a, int8_t b, int8_t c, int8_t d,
67
+ int round, bool *sat)
68
+{
69
+ int64_t r = ((int64_t)a * b - (int64_t)c * d) * 2 + (round << 7);
70
+ return do_sat_bhw(r, INT16_MIN, INT16_MAX, sat) >> 8;
71
+}
72
+
73
+static int16_t do_vqdmlsdh_h(int16_t a, int16_t b, int16_t c, int16_t d,
74
+ int round, bool *sat)
75
+{
76
+ int64_t r = ((int64_t)a * b - (int64_t)c * d) * 2 + (round << 15);
77
+ return do_sat_bhw(r, INT32_MIN, INT32_MAX, sat) >> 16;
78
+}
79
+
80
+static int32_t do_vqdmlsdh_w(int32_t a, int32_t b, int32_t c, int32_t d,
81
+ int round, bool *sat)
82
+{
83
+ int64_t m1 = (int64_t)a * b;
84
+ int64_t m2 = (int64_t)c * d;
85
+ int64_t r;
86
+ /* The same ordering issue as in do_vqdmladh_w applies here too */
87
+ if (ssub64_overflow(m1, m2, &r) ||
88
+ sadd64_overflow(r, (round << 30), &r) ||
89
+ sadd64_overflow(r, r, &r)) {
90
+ *sat = true;
91
+ return r < 0 ? INT32_MAX : INT32_MIN;
92
+ }
93
+ return r >> 32;
94
+}
95
+
96
DO_VQDMLADH_OP(vqdmladhb, 1, int8_t, 0, 0, do_vqdmladh_b)
97
DO_VQDMLADH_OP(vqdmladhh, 2, int16_t, 0, 0, do_vqdmladh_h)
98
DO_VQDMLADH_OP(vqdmladhw, 4, int32_t, 0, 0, do_vqdmladh_w)
99
@@ -XXX,XX +XXX,XX @@ DO_VQDMLADH_OP(vqrdmladhxb, 1, int8_t, 1, 1, do_vqdmladh_b)
100
DO_VQDMLADH_OP(vqrdmladhxh, 2, int16_t, 1, 1, do_vqdmladh_h)
101
DO_VQDMLADH_OP(vqrdmladhxw, 4, int32_t, 1, 1, do_vqdmladh_w)
102
103
+DO_VQDMLADH_OP(vqdmlsdhb, 1, int8_t, 0, 0, do_vqdmlsdh_b)
104
+DO_VQDMLADH_OP(vqdmlsdhh, 2, int16_t, 0, 0, do_vqdmlsdh_h)
105
+DO_VQDMLADH_OP(vqdmlsdhw, 4, int32_t, 0, 0, do_vqdmlsdh_w)
106
+DO_VQDMLADH_OP(vqdmlsdhxb, 1, int8_t, 1, 0, do_vqdmlsdh_b)
107
+DO_VQDMLADH_OP(vqdmlsdhxh, 2, int16_t, 1, 0, do_vqdmlsdh_h)
108
+DO_VQDMLADH_OP(vqdmlsdhxw, 4, int32_t, 1, 0, do_vqdmlsdh_w)
109
+
110
+DO_VQDMLADH_OP(vqrdmlsdhb, 1, int8_t, 0, 1, do_vqdmlsdh_b)
111
+DO_VQDMLADH_OP(vqrdmlsdhh, 2, int16_t, 0, 1, do_vqdmlsdh_h)
112
+DO_VQDMLADH_OP(vqrdmlsdhw, 4, int32_t, 0, 1, do_vqdmlsdh_w)
113
+DO_VQDMLADH_OP(vqrdmlsdhxb, 1, int8_t, 1, 1, do_vqdmlsdh_b)
114
+DO_VQDMLADH_OP(vqrdmlsdhxh, 2, int16_t, 1, 1, do_vqdmlsdh_h)
115
+DO_VQDMLADH_OP(vqrdmlsdhxw, 4, int32_t, 1, 1, do_vqdmlsdh_w)
116
+
117
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
118
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
119
uint32_t rm) \
120
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/target/arm/translate-mve.c
123
+++ b/target/arm/translate-mve.c
124
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQDMLADH, vqdmladh)
125
DO_2OP(VQDMLADHX, vqdmladhx)
126
DO_2OP(VQRDMLADH, vqrdmladh)
127
DO_2OP(VQRDMLADHX, vqrdmladhx)
128
+DO_2OP(VQDMLSDH, vqdmlsdh)
129
+DO_2OP(VQDMLSDHX, vqdmlsdhx)
130
+DO_2OP(VQRDMLSDH, vqrdmlsdh)
131
+DO_2OP(VQRDMLSDHX, vqrdmlsdhx)
132
133
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
134
MVEGenTwoOpScalarFn fn)
27
--
135
--
28
2.20.1
136
2.20.1
29
137
30
138
diff view generated by jsdifflib
1
From: Rebecca Cran <rebecca@nuviainc.com>
1
Implement the vector form of the MVE VQDMULL insn.
2
2
3
Enable FEAT_SSBS for the "max" 32-bit CPU.
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-39-peter.maydell@linaro.org
6
---
7
target/arm/helper-mve.h | 5 +++++
8
target/arm/mve.decode | 5 +++++
9
target/arm/mve_helper.c | 30 ++++++++++++++++++++++++++++++
10
target/arm/translate-mve.c | 30 ++++++++++++++++++++++++++++++
11
4 files changed, 70 insertions(+)
4
12
5
Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210216224543.16142-4-rebecca@nuviainc.com
8
[PMM: fix typo causing compilation failure]
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
target/arm/cpu.c | 4 ++++
12
1 file changed, 4 insertions(+)
13
14
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/cpu.c
15
--- a/target/arm/helper-mve.h
17
+++ b/target/arm/cpu.c
16
+++ b/target/arm/helper-mve.h
18
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqrdmlsdhxb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
t = cpu->isar.id_pfr0;
18
DEF_HELPER_FLAGS_4(mve_vqrdmlsdhxh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
t = FIELD_DP32(t, ID_PFR0, DIT, 1);
19
DEF_HELPER_FLAGS_4(mve_vqrdmlsdhxw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
cpu->isar.id_pfr0 = t;
20
21
+DEF_HELPER_FLAGS_4(mve_vqdmullbh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
+DEF_HELPER_FLAGS_4(mve_vqdmullbw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
+DEF_HELPER_FLAGS_4(mve_vqdmullth, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+DEF_HELPER_FLAGS_4(mve_vqdmulltw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
+
25
+
23
+ t = cpu->isar.id_pfr2;
26
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
+ t = FIELD_DP32(t, ID_PFR2, SSBS, 1);
27
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
+ cpu->isar.id_pfr2 = t;
28
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
26
}
29
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
27
#endif
30
index XXXXXXX..XXXXXXX 100644
28
}
31
--- a/target/arm/mve.decode
32
+++ b/target/arm/mve.decode
33
@@ -XXX,XX +XXX,XX @@
34
@1op_nosz .... .... .... .... .... .... .... .... &1op qd=%qd qm=%qm size=0
35
@2op .... .... .. size:2 .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn
36
@2op_nosz .... .... .... .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn size=0
37
+@2op_sz28 .... .... .... .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn \
38
+ size=%size_28
39
40
# The _rev suffix indicates that Vn and Vm are reversed. This is
41
# the case for shifts. In the Arm ARM these insns are documented
42
@@ -XXX,XX +XXX,XX @@ VQDMLSDHX 1111 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 0 @2op
43
VQRDMLSDH 1111 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 1 @2op
44
VQRDMLSDHX 1111 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 1 @2op
45
46
+VQDMULLB 111 . 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 1 @2op_sz28
47
+VQDMULLT 111 . 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 1 @2op_sz28
48
+
49
# Vector miscellaneous
50
51
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
52
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/mve_helper.c
55
+++ b/target/arm/mve_helper.c
56
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT_SCALAR_L(vqdmullt_scalarh, 1, 2, int16_t, 4, int32_t, \
57
DO_2OP_SAT_SCALAR_L(vqdmullt_scalarw, 1, 4, int32_t, 8, int64_t, \
58
do_qdmullw, SATMASK32)
59
60
+/*
61
+ * Long saturating ops
62
+ */
63
+#define DO_2OP_SAT_L(OP, TOP, ESIZE, TYPE, LESIZE, LTYPE, FN, SATMASK) \
64
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
65
+ void *vm) \
66
+ { \
67
+ LTYPE *d = vd; \
68
+ TYPE *n = vn, *m = vm; \
69
+ uint16_t mask = mve_element_mask(env); \
70
+ unsigned le; \
71
+ bool qc = false; \
72
+ for (le = 0; le < 16 / LESIZE; le++, mask >>= LESIZE) { \
73
+ bool sat = false; \
74
+ LTYPE op1 = n[H##ESIZE(le * 2 + TOP)]; \
75
+ LTYPE op2 = m[H##ESIZE(le * 2 + TOP)]; \
76
+ mergemask(&d[H##LESIZE(le)], FN(op1, op2, &sat), mask); \
77
+ qc |= sat && (mask & SATMASK); \
78
+ } \
79
+ if (qc) { \
80
+ env->vfp.qc[0] = qc; \
81
+ } \
82
+ mve_advance_vpt(env); \
83
+ }
84
+
85
+DO_2OP_SAT_L(vqdmullbh, 0, 2, int16_t, 4, int32_t, do_qdmullh, SATMASK16B)
86
+DO_2OP_SAT_L(vqdmullbw, 0, 4, int32_t, 8, int64_t, do_qdmullw, SATMASK32)
87
+DO_2OP_SAT_L(vqdmullth, 1, 2, int16_t, 4, int32_t, do_qdmullh, SATMASK16T)
88
+DO_2OP_SAT_L(vqdmulltw, 1, 4, int32_t, 8, int64_t, do_qdmullw, SATMASK32)
89
+
90
static inline uint32_t do_vbrsrb(uint32_t n, uint32_t m)
91
{
92
m &= 0xff;
93
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/target/arm/translate-mve.c
96
+++ b/target/arm/translate-mve.c
97
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQDMLSDHX, vqdmlsdhx)
98
DO_2OP(VQRDMLSDH, vqrdmlsdh)
99
DO_2OP(VQRDMLSDHX, vqrdmlsdhx)
100
101
+static bool trans_VQDMULLB(DisasContext *s, arg_2op *a)
102
+{
103
+ static MVEGenTwoOpFn * const fns[] = {
104
+ NULL,
105
+ gen_helper_mve_vqdmullbh,
106
+ gen_helper_mve_vqdmullbw,
107
+ NULL,
108
+ };
109
+ if (a->size == MO_32 && (a->qd == a->qm || a->qd == a->qn)) {
110
+ /* UNPREDICTABLE; we choose to undef */
111
+ return false;
112
+ }
113
+ return do_2op(s, a, fns[a->size]);
114
+}
115
+
116
+static bool trans_VQDMULLT(DisasContext *s, arg_2op *a)
117
+{
118
+ static MVEGenTwoOpFn * const fns[] = {
119
+ NULL,
120
+ gen_helper_mve_vqdmullth,
121
+ gen_helper_mve_vqdmulltw,
122
+ NULL,
123
+ };
124
+ if (a->size == MO_32 && (a->qd == a->qm || a->qd == a->qn)) {
125
+ /* UNPREDICTABLE; we choose to undef */
126
+ return false;
127
+ }
128
+ return do_2op(s, a, fns[a->size]);
129
+}
130
+
131
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
132
MVEGenTwoOpScalarFn fn)
133
{
29
--
134
--
30
2.20.1
135
2.20.1
31
136
32
137
diff view generated by jsdifflib
1
From: Rebecca Cran <rebecca@nuviainc.com>
1
Implement the MVE VRHADD insn, which performs a rounded halving
2
addition.
2
3
3
Set ID_AA64PFR1_EL1.SSBS to 2 and ID_PFR2.SSBS to 1.
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210617121628.20116-40-peter.maydell@linaro.org
7
---
8
target/arm/helper-mve.h | 8 ++++++++
9
target/arm/mve.decode | 3 +++
10
target/arm/mve_helper.c | 6 ++++++
11
target/arm/translate-mve.c | 2 ++
12
4 files changed, 19 insertions(+)
4
13
5
Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210216224543.16142-3-rebecca@nuviainc.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/cpu64.c | 5 +++++
11
1 file changed, 5 insertions(+)
12
13
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/cpu64.c
16
--- a/target/arm/helper-mve.h
16
+++ b/target/arm/cpu64.c
17
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqdmullbw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
18
19
DEF_HELPER_FLAGS_4(mve_vqdmullth, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
t = cpu->isar.id_aa64pfr1;
20
DEF_HELPER_FLAGS_4(mve_vqdmulltw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
t = FIELD_DP64(t, ID_AA64PFR1, BT, 1);
21
21
+ t = FIELD_DP64(t, ID_AA64PFR1, SSBS, 2);
22
+DEF_HELPER_FLAGS_4(mve_vrhaddsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
/*
23
+DEF_HELPER_FLAGS_4(mve_vrhaddsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
* Begin with full support for MTE. This will be downgraded to MTE=0
24
+DEF_HELPER_FLAGS_4(mve_vrhaddsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
* during realize if the board provides no tag memory, much like
25
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
26
u = FIELD_DP32(u, ID_PFR0, DIT, 1);
27
cpu->isar.id_pfr0 = u;
28
29
+ u = cpu->isar.id_pfr2;
30
+ u = FIELD_DP32(u, ID_PFR2, SSBS, 1);
31
+ cpu->isar.id_pfr2 = u;
32
+
25
+
33
u = cpu->isar.id_mmfr3;
26
+DEF_HELPER_FLAGS_4(mve_vrhaddub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */
27
+DEF_HELPER_FLAGS_4(mve_vrhadduh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
35
cpu->isar.id_mmfr3 = u;
28
+DEF_HELPER_FLAGS_4(mve_vrhadduw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
+
30
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
32
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
33
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/mve.decode
36
+++ b/target/arm/mve.decode
37
@@ -XXX,XX +XXX,XX @@ VQRDMLSDHX 1111 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 1 @2op
38
VQDMULLB 111 . 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 1 @2op_sz28
39
VQDMULLT 111 . 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 1 @2op_sz28
40
41
+VRHADD_S 111 0 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
42
+VRHADD_U 111 1 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
43
+
44
# Vector miscellaneous
45
46
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
47
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/mve_helper.c
50
+++ b/target/arm/mve_helper.c
51
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vshlu, DO_VSHLU)
52
DO_2OP_S(vrshls, DO_VRSHLS)
53
DO_2OP_U(vrshlu, DO_VRSHLU)
54
55
+#define DO_RHADD_S(N, M) (((int64_t)(N) + (M) + 1) >> 1)
56
+#define DO_RHADD_U(N, M) (((uint64_t)(N) + (M) + 1) >> 1)
57
+
58
+DO_2OP_S(vrhadds, DO_RHADD_S)
59
+DO_2OP_U(vrhaddu, DO_RHADD_U)
60
+
61
static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
62
{
63
if (val > max) {
64
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/translate-mve.c
67
+++ b/target/arm/translate-mve.c
68
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQDMLSDH, vqdmlsdh)
69
DO_2OP(VQDMLSDHX, vqdmlsdhx)
70
DO_2OP(VQRDMLSDH, vqrdmlsdh)
71
DO_2OP(VQRDMLSDHX, vqrdmlsdhx)
72
+DO_2OP(VRHADD_S, vrhadds)
73
+DO_2OP(VRHADD_U, vrhaddu)
74
75
static bool trans_VQDMULLB(DisasContext *s, arg_2op *a)
76
{
36
--
77
--
37
2.20.1
78
2.20.1
38
79
39
80
diff view generated by jsdifflib
1
From: Doug Evans <dje@google.com>
1
Implement the MVE VADC and VSBC insns. These perform an
2
add-with-carry or subtract-with-carry of the 32-bit elements in each
3
lane of the input vectors, where the carry-out of each add is the
4
carry-in of the next. The initial carry input is either 1 or is from
5
FPSCR.C; the carry out at the end is written back to FPSCR.C.
2
6
3
Reviewed-by: Hao Wu <wuhaotsh@google.com>
4
Reviewed-by: Avi Fishman <avi.fishman@nuvoton.com>
5
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Doug Evans <dje@google.com>
7
Message-id: 20210218212453.831406-4-dje@google.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210617121628.20116-41-peter.maydell@linaro.org
9
---
10
---
10
tests/qtest/npcm7xx_emc-test.c | 862 +++++++++++++++++++++++++++++++++
11
target/arm/helper-mve.h | 5 ++++
11
tests/qtest/meson.build | 3 +-
12
target/arm/mve.decode | 5 ++++
12
2 files changed, 864 insertions(+), 1 deletion(-)
13
target/arm/mve_helper.c | 52 ++++++++++++++++++++++++++++++++++++++
13
create mode 100644 tests/qtest/npcm7xx_emc-test.c
14
target/arm/translate-mve.c | 37 +++++++++++++++++++++++++++
15
4 files changed, 99 insertions(+)
14
16
15
diff --git a/tests/qtest/npcm7xx_emc-test.c b/tests/qtest/npcm7xx_emc-test.c
17
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
16
new file mode 100644
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX
19
--- a/target/arm/helper-mve.h
18
--- /dev/null
20
+++ b/target/arm/helper-mve.h
19
+++ b/tests/qtest/npcm7xx_emc-test.c
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vrhaddub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
@@ -XXX,XX +XXX,XX @@
22
DEF_HELPER_FLAGS_4(mve_vrhadduh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
+/*
23
DEF_HELPER_FLAGS_4(mve_vrhadduw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
+ * QTests for Nuvoton NPCM7xx EMC Modules.
24
23
+ *
25
+DEF_HELPER_FLAGS_4(mve_vadc, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+ * Copyright 2020 Google LLC
26
+DEF_HELPER_FLAGS_4(mve_vadci, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+ *
27
+DEF_HELPER_FLAGS_4(mve_vsbc, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
+ * This program is free software; you can redistribute it and/or modify it
28
+DEF_HELPER_FLAGS_4(mve_vsbci, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+ * under the terms of the GNU General Public License as published by the
28
+ * Free Software Foundation; either version 2 of the License, or
29
+ * (at your option) any later version.
30
+ *
31
+ * This program is distributed in the hope that it will be useful, but WITHOUT
32
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
33
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
34
+ * for more details.
35
+ */
36
+
29
+
37
+#include "qemu/osdep.h"
30
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
38
+#include "qemu-common.h"
31
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
39
+#include "libqos/libqos.h"
32
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
40
+#include "qapi/qmp/qdict.h"
33
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
41
+#include "qapi/qmp/qnum.h"
34
index XXXXXXX..XXXXXXX 100644
42
+#include "qemu/bitops.h"
35
--- a/target/arm/mve.decode
43
+#include "qemu/iov.h"
36
+++ b/target/arm/mve.decode
37
@@ -XXX,XX +XXX,XX @@ VQDMULLT 111 . 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 1 @2op_sz28
38
VRHADD_S 111 0 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
39
VRHADD_U 111 1 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
40
41
+VADC 1110 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
42
+VSBC 1111 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
43
+VADCI 1110 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 0 @2op_nosz
44
+VSBCI 1111 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 0 @2op_nosz
44
+
45
+
45
+/* Name of the emc device. */
46
# Vector miscellaneous
46
+#define TYPE_NPCM7XX_EMC "npcm7xx-emc"
47
48
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
49
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
50
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/mve_helper.c
52
+++ b/target/arm/mve_helper.c
53
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vrshlu, DO_VRSHLU)
54
DO_2OP_S(vrhadds, DO_RHADD_S)
55
DO_2OP_U(vrhaddu, DO_RHADD_U)
56
57
+static void do_vadc(CPUARMState *env, uint32_t *d, uint32_t *n, uint32_t *m,
58
+ uint32_t inv, uint32_t carry_in, bool update_flags)
59
+{
60
+ uint16_t mask = mve_element_mask(env);
61
+ unsigned e;
47
+
62
+
48
+/* Timeout for various operations, in seconds. */
63
+ /* If any additions trigger, we will update flags. */
49
+#define TIMEOUT_SECONDS 10
64
+ if (mask & 0x1111) {
65
+ update_flags = true;
66
+ }
50
+
67
+
51
+/* Address in memory of the descriptor. */
68
+ for (e = 0; e < 16 / 4; e++, mask >>= 4) {
52
+#define DESC_ADDR (1 << 20) /* 1 MiB */
69
+ uint64_t r = carry_in;
70
+ r += n[H4(e)];
71
+ r += m[H4(e)] ^ inv;
72
+ if (mask & 1) {
73
+ carry_in = r >> 32;
74
+ }
75
+ mergemask(&d[H4(e)], r, mask);
76
+ }
53
+
77
+
54
+/* Address in memory of the data packet. */
78
+ if (update_flags) {
55
+#define DATA_ADDR (DESC_ADDR + 4096)
79
+ /* Store C, clear NZV. */
56
+
80
+ env->vfp.xregs[ARM_VFP_FPSCR] &= ~FPCR_NZCV_MASK;
57
+#define CRC_LENGTH 4
81
+ env->vfp.xregs[ARM_VFP_FPSCR] |= carry_in * FPCR_C;
58
+
59
+#define NUM_TX_DESCRIPTORS 3
60
+#define NUM_RX_DESCRIPTORS 2
61
+
62
+/* Size of tx,rx test buffers. */
63
+#define TX_DATA_LEN 64
64
+#define RX_DATA_LEN 64
65
+
66
+#define TX_STEP_COUNT 10000
67
+#define RX_STEP_COUNT 10000
68
+
69
+/* 32-bit register indices. */
70
+typedef enum NPCM7xxPWMRegister {
71
+ /* Control registers. */
72
+ REG_CAMCMR,
73
+ REG_CAMEN,
74
+
75
+ /* There are 16 CAMn[ML] registers. */
76
+ REG_CAMM_BASE,
77
+ REG_CAML_BASE,
78
+
79
+ REG_TXDLSA = 0x22,
80
+ REG_RXDLSA,
81
+ REG_MCMDR,
82
+ REG_MIID,
83
+ REG_MIIDA,
84
+ REG_FFTCR,
85
+ REG_TSDR,
86
+ REG_RSDR,
87
+ REG_DMARFC,
88
+ REG_MIEN,
89
+
90
+ /* Status registers. */
91
+ REG_MISTA,
92
+ REG_MGSTA,
93
+ REG_MPCNT,
94
+ REG_MRPC,
95
+ REG_MRPCC,
96
+ REG_MREPC,
97
+ REG_DMARFS,
98
+ REG_CTXDSA,
99
+ REG_CTXBSA,
100
+ REG_CRXDSA,
101
+ REG_CRXBSA,
102
+
103
+ NPCM7XX_NUM_EMC_REGS,
104
+} NPCM7xxPWMRegister;
105
+
106
+enum { NUM_CAMML_REGS = 16 };
107
+
108
+/* REG_CAMCMR fields */
109
+/* Enable CAM Compare */
110
+#define REG_CAMCMR_ECMP (1 << 4)
111
+/* Accept Unicast Packet */
112
+#define REG_CAMCMR_AUP (1 << 0)
113
+
114
+/* REG_MCMDR fields */
115
+/* Software Reset */
116
+#define REG_MCMDR_SWR (1 << 24)
117
+/* Frame Transmission On */
118
+#define REG_MCMDR_TXON (1 << 8)
119
+/* Accept Long Packet */
120
+#define REG_MCMDR_ALP (1 << 1)
121
+/* Frame Reception On */
122
+#define REG_MCMDR_RXON (1 << 0)
123
+
124
+/* REG_MIEN fields */
125
+/* Enable Transmit Completion Interrupt */
126
+#define REG_MIEN_ENTXCP (1 << 18)
127
+/* Enable Transmit Interrupt */
128
+#define REG_MIEN_ENTXINTR (1 << 16)
129
+/* Enable Receive Good Interrupt */
130
+#define REG_MIEN_ENRXGD (1 << 4)
131
+/* ENable Receive Interrupt */
132
+#define REG_MIEN_ENRXINTR (1 << 0)
133
+
134
+/* REG_MISTA fields */
135
+/* Transmit Bus Error Interrupt */
136
+#define REG_MISTA_TXBERR (1 << 24)
137
+/* Transmit Descriptor Unavailable Interrupt */
138
+#define REG_MISTA_TDU (1 << 23)
139
+/* Transmit Completion Interrupt */
140
+#define REG_MISTA_TXCP (1 << 18)
141
+/* Transmit Interrupt */
142
+#define REG_MISTA_TXINTR (1 << 16)
143
+/* Receive Bus Error Interrupt */
144
+#define REG_MISTA_RXBERR (1 << 11)
145
+/* Receive Descriptor Unavailable Interrupt */
146
+#define REG_MISTA_RDU (1 << 10)
147
+/* DMA Early Notification Interrupt */
148
+#define REG_MISTA_DENI (1 << 9)
149
+/* Maximum Frame Length Interrupt */
150
+#define REG_MISTA_DFOI (1 << 8)
151
+/* Receive Good Interrupt */
152
+#define REG_MISTA_RXGD (1 << 4)
153
+/* Packet Too Long Interrupt */
154
+#define REG_MISTA_PTLE (1 << 3)
155
+/* Receive Interrupt */
156
+#define REG_MISTA_RXINTR (1 << 0)
157
+
158
+typedef struct NPCM7xxEMCTxDesc NPCM7xxEMCTxDesc;
159
+typedef struct NPCM7xxEMCRxDesc NPCM7xxEMCRxDesc;
160
+
161
+struct NPCM7xxEMCTxDesc {
162
+ uint32_t flags;
163
+ uint32_t txbsa;
164
+ uint32_t status_and_length;
165
+ uint32_t ntxdsa;
166
+};
167
+
168
+struct NPCM7xxEMCRxDesc {
169
+ uint32_t status_and_length;
170
+ uint32_t rxbsa;
171
+ uint32_t reserved;
172
+ uint32_t nrxdsa;
173
+};
174
+
175
+/* NPCM7xxEMCTxDesc.flags values */
176
+/* Owner: 0 = cpu, 1 = emc */
177
+#define TX_DESC_FLAG_OWNER_MASK (1 << 31)
178
+/* Transmit interrupt enable */
179
+#define TX_DESC_FLAG_INTEN (1 << 2)
180
+
181
+/* NPCM7xxEMCTxDesc.status_and_length values */
182
+/* Transmission complete */
183
+#define TX_DESC_STATUS_TXCP (1 << 19)
184
+/* Transmit interrupt */
185
+#define TX_DESC_STATUS_TXINTR (1 << 16)
186
+
187
+/* NPCM7xxEMCRxDesc.status_and_length values */
188
+/* Owner: 0b00 = cpu, 0b10 = emc */
189
+#define RX_DESC_STATUS_OWNER_SHIFT 30
190
+#define RX_DESC_STATUS_OWNER_MASK 0xc0000000
191
+/* Frame Reception Complete */
192
+#define RX_DESC_STATUS_RXGD (1 << 20)
193
+/* Packet too long */
194
+#define RX_DESC_STATUS_PTLE (1 << 19)
195
+/* Receive Interrupt */
196
+#define RX_DESC_STATUS_RXINTR (1 << 16)
197
+
198
+#define RX_DESC_PKT_LEN(word) ((uint32_t) (word) & 0xffff)
199
+
200
+typedef struct EMCModule {
201
+ int rx_irq;
202
+ int tx_irq;
203
+ uint64_t base_addr;
204
+} EMCModule;
205
+
206
+typedef struct TestData {
207
+ const EMCModule *module;
208
+} TestData;
209
+
210
+static const EMCModule emc_module_list[] = {
211
+ {
212
+ .rx_irq = 15,
213
+ .tx_irq = 16,
214
+ .base_addr = 0xf0825000
215
+ },
216
+ {
217
+ .rx_irq = 114,
218
+ .tx_irq = 115,
219
+ .base_addr = 0xf0826000
220
+ }
82
+ }
221
+};
83
+ mve_advance_vpt(env);
222
+
223
+/* Returns the index of the EMC module. */
224
+static int emc_module_index(const EMCModule *mod)
225
+{
226
+ ptrdiff_t diff = mod - emc_module_list;
227
+
228
+ g_assert_true(diff >= 0 && diff < ARRAY_SIZE(emc_module_list));
229
+
230
+ return diff;
231
+}
84
+}
232
+
85
+
233
+static void packet_test_clear(void *sockets)
86
+void HELPER(mve_vadc)(CPUARMState *env, void *vd, void *vn, void *vm)
234
+{
87
+{
235
+ int *test_sockets = sockets;
88
+ bool carry_in = env->vfp.xregs[ARM_VFP_FPSCR] & FPCR_C;
236
+
89
+ do_vadc(env, vd, vn, vm, 0, carry_in, false);
237
+ close(test_sockets[0]);
238
+ g_free(test_sockets);
239
+}
90
+}
240
+
91
+
241
+static int *packet_test_init(int module_num, GString *cmd_line)
92
+void HELPER(mve_vsbc)(CPUARMState *env, void *vd, void *vn, void *vm)
242
+{
93
+{
243
+ int *test_sockets = g_new(int, 2);
94
+ bool carry_in = env->vfp.xregs[ARM_VFP_FPSCR] & FPCR_C;
244
+ int ret = socketpair(PF_UNIX, SOCK_STREAM, 0, test_sockets);
95
+ do_vadc(env, vd, vn, vm, -1, carry_in, false);
245
+ g_assert_cmpint(ret, != , -1);
246
+
247
+ /*
248
+ * KISS and use -nic. We specify two nics (both emc{0,1}) because there's
249
+ * currently no way to specify only emc1: The driver implicitly relies on
250
+ * emc[i] == nd_table[i].
251
+ */
252
+ if (module_num == 0) {
253
+ g_string_append_printf(cmd_line,
254
+ " -nic socket,fd=%d,model=" TYPE_NPCM7XX_EMC " "
255
+ " -nic user,model=" TYPE_NPCM7XX_EMC " ",
256
+ test_sockets[1]);
257
+ } else {
258
+ g_string_append_printf(cmd_line,
259
+ " -nic user,model=" TYPE_NPCM7XX_EMC " "
260
+ " -nic socket,fd=%d,model=" TYPE_NPCM7XX_EMC " ",
261
+ test_sockets[1]);
262
+ }
263
+
264
+ g_test_queue_destroy(packet_test_clear, test_sockets);
265
+ return test_sockets;
266
+}
96
+}
267
+
97
+
268
+static uint32_t emc_read(QTestState *qts, const EMCModule *mod,
98
+
269
+ NPCM7xxPWMRegister regno)
99
+void HELPER(mve_vadci)(CPUARMState *env, void *vd, void *vn, void *vm)
270
+{
100
+{
271
+ return qtest_readl(qts, mod->base_addr + regno * sizeof(uint32_t));
101
+ do_vadc(env, vd, vn, vm, 0, 0, true);
272
+}
102
+}
273
+
103
+
274
+static void emc_write(QTestState *qts, const EMCModule *mod,
104
+void HELPER(mve_vsbci)(CPUARMState *env, void *vd, void *vn, void *vm)
275
+ NPCM7xxPWMRegister regno, uint32_t value)
276
+{
105
+{
277
+ qtest_writel(qts, mod->base_addr + regno * sizeof(uint32_t), value);
106
+ do_vadc(env, vd, vn, vm, -1, 1, true);
278
+}
107
+}
279
+
108
+
280
+static void emc_read_tx_desc(QTestState *qts, uint32_t addr,
109
static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
281
+ NPCM7xxEMCTxDesc *desc)
110
{
111
if (val > max) {
112
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
113
index XXXXXXX..XXXXXXX 100644
114
--- a/target/arm/translate-mve.c
115
+++ b/target/arm/translate-mve.c
116
@@ -XXX,XX +XXX,XX @@ static bool trans_VQDMULLT(DisasContext *s, arg_2op *a)
117
return do_2op(s, a, fns[a->size]);
118
}
119
120
+/*
121
+ * VADC and VSBC: these perform an add-with-carry or subtract-with-carry
122
+ * of the 32-bit elements in each lane of the input vectors, where the
123
+ * carry-out of each add is the carry-in of the next. The initial carry
124
+ * input is either fixed (0 for VADCI, 1 for VSBCI) or is from FPSCR.C
125
+ * (for VADC and VSBC); the carry out at the end is written back to FPSCR.C.
126
+ * These insns are subject to beat-wise execution. Partial execution
127
+ * of an I=1 (initial carry input fixed) insn which does not
128
+ * execute the first beat must start with the current FPSCR.NZCV
129
+ * value, not the fixed constant input.
130
+ */
131
+static bool trans_VADC(DisasContext *s, arg_2op *a)
282
+{
132
+{
283
+ qtest_memread(qts, addr, desc, sizeof(*desc));
133
+ return do_2op(s, a, gen_helper_mve_vadc);
284
+ desc->flags = le32_to_cpu(desc->flags);
285
+ desc->txbsa = le32_to_cpu(desc->txbsa);
286
+ desc->status_and_length = le32_to_cpu(desc->status_and_length);
287
+ desc->ntxdsa = le32_to_cpu(desc->ntxdsa);
288
+}
134
+}
289
+
135
+
290
+static void emc_write_tx_desc(QTestState *qts, const NPCM7xxEMCTxDesc *desc,
136
+static bool trans_VADCI(DisasContext *s, arg_2op *a)
291
+ uint32_t addr)
292
+{
137
+{
293
+ NPCM7xxEMCTxDesc le_desc;
138
+ if (mve_skip_first_beat(s)) {
294
+
139
+ return trans_VADC(s, a);
295
+ le_desc.flags = cpu_to_le32(desc->flags);
140
+ }
296
+ le_desc.txbsa = cpu_to_le32(desc->txbsa);
141
+ return do_2op(s, a, gen_helper_mve_vadci);
297
+ le_desc.status_and_length = cpu_to_le32(desc->status_and_length);
298
+ le_desc.ntxdsa = cpu_to_le32(desc->ntxdsa);
299
+ qtest_memwrite(qts, addr, &le_desc, sizeof(le_desc));
300
+}
142
+}
301
+
143
+
302
+static void emc_read_rx_desc(QTestState *qts, uint32_t addr,
144
+static bool trans_VSBC(DisasContext *s, arg_2op *a)
303
+ NPCM7xxEMCRxDesc *desc)
304
+{
145
+{
305
+ qtest_memread(qts, addr, desc, sizeof(*desc));
146
+ return do_2op(s, a, gen_helper_mve_vsbc);
306
+ desc->status_and_length = le32_to_cpu(desc->status_and_length);
307
+ desc->rxbsa = le32_to_cpu(desc->rxbsa);
308
+ desc->reserved = le32_to_cpu(desc->reserved);
309
+ desc->nrxdsa = le32_to_cpu(desc->nrxdsa);
310
+}
147
+}
311
+
148
+
312
+static void emc_write_rx_desc(QTestState *qts, const NPCM7xxEMCRxDesc *desc,
149
+static bool trans_VSBCI(DisasContext *s, arg_2op *a)
313
+ uint32_t addr)
314
+{
150
+{
315
+ NPCM7xxEMCRxDesc le_desc;
151
+ if (mve_skip_first_beat(s)) {
316
+
152
+ return trans_VSBC(s, a);
317
+ le_desc.status_and_length = cpu_to_le32(desc->status_and_length);
153
+ }
318
+ le_desc.rxbsa = cpu_to_le32(desc->rxbsa);
154
+ return do_2op(s, a, gen_helper_mve_vsbci);
319
+ le_desc.reserved = cpu_to_le32(desc->reserved);
320
+ le_desc.nrxdsa = cpu_to_le32(desc->nrxdsa);
321
+ qtest_memwrite(qts, addr, &le_desc, sizeof(le_desc));
322
+}
155
+}
323
+
156
+
324
+/*
157
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
325
+ * Reset the EMC module.
158
MVEGenTwoOpScalarFn fn)
326
+ * The module must be reset before, e.g., TXDLSA,RXDLSA are changed.
159
{
327
+ */
328
+static bool emc_soft_reset(QTestState *qts, const EMCModule *mod)
329
+{
330
+ uint32_t val;
331
+ uint64_t end_time;
332
+
333
+ emc_write(qts, mod, REG_MCMDR, REG_MCMDR_SWR);
334
+
335
+ /*
336
+ * Wait for device to reset as the linux driver does.
337
+ * During reset the AHB reads 0 for all registers. So first wait for
338
+ * something that resets to non-zero, and then wait for SWR becoming 0.
339
+ */
340
+ end_time = g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
341
+
342
+ do {
343
+ qtest_clock_step(qts, 100);
344
+ val = emc_read(qts, mod, REG_FFTCR);
345
+ } while (val == 0 && g_get_monotonic_time() < end_time);
346
+ if (val != 0) {
347
+ do {
348
+ qtest_clock_step(qts, 100);
349
+ val = emc_read(qts, mod, REG_MCMDR);
350
+ if ((val & REG_MCMDR_SWR) == 0) {
351
+ /*
352
+ * N.B. The CAMs have been reset here, so macaddr matching of
353
+ * incoming packets will not work.
354
+ */
355
+ return true;
356
+ }
357
+ } while (g_get_monotonic_time() < end_time);
358
+ }
359
+
360
+ g_message("%s: Timeout expired", __func__);
361
+ return false;
362
+}
363
+
364
+/* Check emc registers are reset to default value. */
365
+static void test_init(gconstpointer test_data)
366
+{
367
+ const TestData *td = test_data;
368
+ const EMCModule *mod = td->module;
369
+ QTestState *qts = qtest_init("-machine quanta-gsj");
370
+ int i;
371
+
372
+#define CHECK_REG(regno, value) \
373
+ do { \
374
+ g_assert_cmphex(emc_read(qts, mod, (regno)), ==, (value)); \
375
+ } while (0)
376
+
377
+ CHECK_REG(REG_CAMCMR, 0);
378
+ CHECK_REG(REG_CAMEN, 0);
379
+ CHECK_REG(REG_TXDLSA, 0xfffffffc);
380
+ CHECK_REG(REG_RXDLSA, 0xfffffffc);
381
+ CHECK_REG(REG_MCMDR, 0);
382
+ CHECK_REG(REG_MIID, 0);
383
+ CHECK_REG(REG_MIIDA, 0x00900000);
384
+ CHECK_REG(REG_FFTCR, 0x0101);
385
+ CHECK_REG(REG_DMARFC, 0x0800);
386
+ CHECK_REG(REG_MIEN, 0);
387
+ CHECK_REG(REG_MISTA, 0);
388
+ CHECK_REG(REG_MGSTA, 0);
389
+ CHECK_REG(REG_MPCNT, 0x7fff);
390
+ CHECK_REG(REG_MRPC, 0);
391
+ CHECK_REG(REG_MRPCC, 0);
392
+ CHECK_REG(REG_MREPC, 0);
393
+ CHECK_REG(REG_DMARFS, 0);
394
+ CHECK_REG(REG_CTXDSA, 0);
395
+ CHECK_REG(REG_CTXBSA, 0);
396
+ CHECK_REG(REG_CRXDSA, 0);
397
+ CHECK_REG(REG_CRXBSA, 0);
398
+
399
+#undef CHECK_REG
400
+
401
+ for (i = 0; i < NUM_CAMML_REGS; ++i) {
402
+ g_assert_cmpuint(emc_read(qts, mod, REG_CAMM_BASE + i * 2), ==,
403
+ 0);
404
+ g_assert_cmpuint(emc_read(qts, mod, REG_CAML_BASE + i * 2), ==,
405
+ 0);
406
+ }
407
+
408
+ qtest_quit(qts);
409
+}
410
+
411
+static bool emc_wait_irq(QTestState *qts, const EMCModule *mod, int step,
412
+ bool is_tx)
413
+{
414
+ uint64_t end_time =
415
+ g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
416
+
417
+ do {
418
+ if (qtest_get_irq(qts, is_tx ? mod->tx_irq : mod->rx_irq)) {
419
+ return true;
420
+ }
421
+ qtest_clock_step(qts, step);
422
+ } while (g_get_monotonic_time() < end_time);
423
+
424
+ g_message("%s: Timeout expired", __func__);
425
+ return false;
426
+}
427
+
428
+static bool emc_wait_mista(QTestState *qts, const EMCModule *mod, int step,
429
+ uint32_t flag)
430
+{
431
+ uint64_t end_time =
432
+ g_get_monotonic_time() + TIMEOUT_SECONDS * G_TIME_SPAN_SECOND;
433
+
434
+ do {
435
+ uint32_t mista = emc_read(qts, mod, REG_MISTA);
436
+ if (mista & flag) {
437
+ return true;
438
+ }
439
+ qtest_clock_step(qts, step);
440
+ } while (g_get_monotonic_time() < end_time);
441
+
442
+ g_message("%s: Timeout expired", __func__);
443
+ return false;
444
+}
445
+
446
+static bool wait_socket_readable(int fd)
447
+{
448
+ fd_set read_fds;
449
+ struct timeval tv;
450
+ int rv;
451
+
452
+ FD_ZERO(&read_fds);
453
+ FD_SET(fd, &read_fds);
454
+ tv.tv_sec = TIMEOUT_SECONDS;
455
+ tv.tv_usec = 0;
456
+ rv = select(fd + 1, &read_fds, NULL, NULL, &tv);
457
+ if (rv == -1) {
458
+ perror("select");
459
+ } else if (rv == 0) {
460
+ g_message("%s: Timeout expired", __func__);
461
+ }
462
+ return rv == 1;
463
+}
464
+
465
+/* Initialize *desc (in host endian format). */
466
+static void init_tx_desc(NPCM7xxEMCTxDesc *desc, size_t count,
467
+ uint32_t desc_addr)
468
+{
469
+ g_assert(count >= 2);
470
+ memset(&desc[0], 0, sizeof(*desc) * count);
471
+ /* Leave the last one alone, owned by the cpu -> stops transmission. */
472
+ for (size_t i = 0; i < count - 1; ++i) {
473
+ desc[i].flags =
474
+ (TX_DESC_FLAG_OWNER_MASK | /* owner = 1: emc */
475
+ TX_DESC_FLAG_INTEN |
476
+ 0 | /* crc append = 0 */
477
+ 0 /* padding enable = 0 */);
478
+ desc[i].status_and_length =
479
+ (0 | /* collision count = 0 */
480
+ 0 | /* SQE = 0 */
481
+ 0 | /* PAU = 0 */
482
+ 0 | /* TXHA = 0 */
483
+ 0 | /* LC = 0 */
484
+ 0 | /* TXABT = 0 */
485
+ 0 | /* NCS = 0 */
486
+ 0 | /* EXDEF = 0 */
487
+ 0 | /* TXCP = 0 */
488
+ 0 | /* DEF = 0 */
489
+ 0 | /* TXINTR = 0 */
490
+ 0 /* length filled in later */);
491
+ desc[i].ntxdsa = desc_addr + (i + 1) * sizeof(*desc);
492
+ }
493
+}
494
+
495
+static void enable_tx(QTestState *qts, const EMCModule *mod,
496
+ const NPCM7xxEMCTxDesc *desc, size_t count,
497
+ uint32_t desc_addr, uint32_t mien_flags)
498
+{
499
+ /* Write the descriptors to guest memory. */
500
+ for (size_t i = 0; i < count; ++i) {
501
+ emc_write_tx_desc(qts, desc + i, desc_addr + i * sizeof(*desc));
502
+ }
503
+
504
+ /* Trigger sending the packet. */
505
+ /* The module must be reset before changing TXDLSA. */
506
+ g_assert(emc_soft_reset(qts, mod));
507
+ emc_write(qts, mod, REG_TXDLSA, desc_addr);
508
+ emc_write(qts, mod, REG_CTXDSA, ~0);
509
+ emc_write(qts, mod, REG_MIEN, REG_MIEN_ENTXCP | mien_flags);
510
+ {
511
+ uint32_t mcmdr = emc_read(qts, mod, REG_MCMDR);
512
+ mcmdr |= REG_MCMDR_TXON;
513
+ emc_write(qts, mod, REG_MCMDR, mcmdr);
514
+ }
515
+
516
+ /* Prod the device to send the packet. */
517
+ emc_write(qts, mod, REG_TSDR, 1);
518
+}
519
+
520
+static void emc_send_verify1(QTestState *qts, const EMCModule *mod, int fd,
521
+ bool with_irq, uint32_t desc_addr,
522
+ uint32_t next_desc_addr,
523
+ const char *test_data, int test_size)
524
+{
525
+ NPCM7xxEMCTxDesc result_desc;
526
+ uint32_t expected_mask, expected_value, recv_len;
527
+ int ret;
528
+ char buffer[TX_DATA_LEN];
529
+
530
+ g_assert(wait_socket_readable(fd));
531
+
532
+ /* Read the descriptor back. */
533
+ emc_read_tx_desc(qts, desc_addr, &result_desc);
534
+ /* Descriptor should be owned by cpu now. */
535
+ g_assert((result_desc.flags & TX_DESC_FLAG_OWNER_MASK) == 0);
536
+ /* Test the status bits, ignoring the length field. */
537
+ expected_mask = 0xffff << 16;
538
+ expected_value = TX_DESC_STATUS_TXCP;
539
+ if (with_irq) {
540
+ expected_value |= TX_DESC_STATUS_TXINTR;
541
+ }
542
+ g_assert_cmphex((result_desc.status_and_length & expected_mask), ==,
543
+ expected_value);
544
+
545
+ /* Check data sent to the backend. */
546
+ recv_len = ~0;
547
+ ret = qemu_recv(fd, &recv_len, sizeof(recv_len), MSG_DONTWAIT);
548
+ g_assert_cmpint(ret, == , sizeof(recv_len));
549
+
550
+ g_assert(wait_socket_readable(fd));
551
+ memset(buffer, 0xff, sizeof(buffer));
552
+ ret = qemu_recv(fd, buffer, test_size, MSG_DONTWAIT);
553
+ g_assert_cmpmem(buffer, ret, test_data, test_size);
554
+}
555
+
556
+static void emc_send_verify(QTestState *qts, const EMCModule *mod, int fd,
557
+ bool with_irq)
558
+{
559
+ NPCM7xxEMCTxDesc desc[NUM_TX_DESCRIPTORS];
560
+ uint32_t desc_addr = DESC_ADDR;
561
+ static const char test1_data[] = "TEST1";
562
+ static const char test2_data[] = "Testing 1 2 3 ...";
563
+ uint32_t data1_addr = DATA_ADDR;
564
+ uint32_t data2_addr = data1_addr + sizeof(test1_data);
565
+ bool got_tdu;
566
+ uint32_t end_desc_addr;
567
+
568
+ /* Prepare test data buffer. */
569
+ qtest_memwrite(qts, data1_addr, test1_data, sizeof(test1_data));
570
+ qtest_memwrite(qts, data2_addr, test2_data, sizeof(test2_data));
571
+
572
+ init_tx_desc(&desc[0], NUM_TX_DESCRIPTORS, desc_addr);
573
+ desc[0].txbsa = data1_addr;
574
+ desc[0].status_and_length |= sizeof(test1_data);
575
+ desc[1].txbsa = data2_addr;
576
+ desc[1].status_and_length |= sizeof(test2_data);
577
+
578
+ enable_tx(qts, mod, &desc[0], NUM_TX_DESCRIPTORS, desc_addr,
579
+ with_irq ? REG_MIEN_ENTXINTR : 0);
580
+
581
+ /*
582
+ * It's problematic to observe the interrupt for each packet.
583
+ * Instead just wait until all the packets go out.
584
+ */
585
+ got_tdu = false;
586
+ while (!got_tdu) {
587
+ if (with_irq) {
588
+ g_assert_true(emc_wait_irq(qts, mod, TX_STEP_COUNT,
589
+ /*is_tx=*/true));
590
+ } else {
591
+ g_assert_true(emc_wait_mista(qts, mod, TX_STEP_COUNT,
592
+ REG_MISTA_TXINTR));
593
+ }
594
+ got_tdu = !!(emc_read(qts, mod, REG_MISTA) & REG_MISTA_TDU);
595
+ /* If we don't have TDU yet, reset the interrupt. */
596
+ if (!got_tdu) {
597
+ emc_write(qts, mod, REG_MISTA,
598
+ emc_read(qts, mod, REG_MISTA) & 0xffff0000);
599
+ }
600
+ }
601
+
602
+ end_desc_addr = desc_addr + 2 * sizeof(desc[0]);
603
+ g_assert_cmphex(emc_read(qts, mod, REG_CTXDSA), ==, end_desc_addr);
604
+ g_assert_cmphex(emc_read(qts, mod, REG_MISTA), ==,
605
+ REG_MISTA_TXCP | REG_MISTA_TXINTR | REG_MISTA_TDU);
606
+
607
+ emc_send_verify1(qts, mod, fd, with_irq,
608
+ desc_addr, end_desc_addr,
609
+ test1_data, sizeof(test1_data));
610
+ emc_send_verify1(qts, mod, fd, with_irq,
611
+ desc_addr + sizeof(desc[0]), end_desc_addr,
612
+ test2_data, sizeof(test2_data));
613
+}
614
+
615
+/* Initialize *desc (in host endian format). */
616
+static void init_rx_desc(NPCM7xxEMCRxDesc *desc, size_t count,
617
+ uint32_t desc_addr, uint32_t data_addr)
618
+{
619
+ g_assert_true(count >= 2);
620
+ memset(desc, 0, sizeof(*desc) * count);
621
+ desc[0].rxbsa = data_addr;
622
+ desc[0].status_and_length =
623
+ (0b10 << RX_DESC_STATUS_OWNER_SHIFT | /* owner = 10: emc */
624
+ 0 | /* RP = 0 */
625
+ 0 | /* ALIE = 0 */
626
+ 0 | /* RXGD = 0 */
627
+ 0 | /* PTLE = 0 */
628
+ 0 | /* CRCE = 0 */
629
+ 0 | /* RXINTR = 0 */
630
+ 0 /* length (filled in later) */);
631
+ /* Leave the last one alone, owned by the cpu -> stops transmission. */
632
+ desc[0].nrxdsa = desc_addr + sizeof(*desc);
633
+}
634
+
635
+static void enable_rx(QTestState *qts, const EMCModule *mod,
636
+ const NPCM7xxEMCRxDesc *desc, size_t count,
637
+ uint32_t desc_addr, uint32_t mien_flags,
638
+ uint32_t mcmdr_flags)
639
+{
640
+ /*
641
+ * Write the descriptor to guest memory.
642
+ * FWIW, IWBN if the docs said the buffer needs to be at least DMARFC
643
+ * bytes.
644
+ */
645
+ for (size_t i = 0; i < count; ++i) {
646
+ emc_write_rx_desc(qts, desc + i, desc_addr + i * sizeof(*desc));
647
+ }
648
+
649
+ /* Trigger receiving the packet. */
650
+ /* The module must be reset before changing RXDLSA. */
651
+ g_assert(emc_soft_reset(qts, mod));
652
+ emc_write(qts, mod, REG_RXDLSA, desc_addr);
653
+ emc_write(qts, mod, REG_MIEN, REG_MIEN_ENRXGD | mien_flags);
654
+
655
+ /*
656
+ * We don't know what the device's macaddr is, so just accept all
657
+ * unicast packets (AUP).
658
+ */
659
+ emc_write(qts, mod, REG_CAMCMR, REG_CAMCMR_AUP);
660
+ emc_write(qts, mod, REG_CAMEN, 1 << 0);
661
+ {
662
+ uint32_t mcmdr = emc_read(qts, mod, REG_MCMDR);
663
+ mcmdr |= REG_MCMDR_RXON | mcmdr_flags;
664
+ emc_write(qts, mod, REG_MCMDR, mcmdr);
665
+ }
666
+
667
+ /* Prod the device to accept a packet. */
668
+ emc_write(qts, mod, REG_RSDR, 1);
669
+}
670
+
671
+static void emc_recv_verify(QTestState *qts, const EMCModule *mod, int fd,
672
+ bool with_irq)
673
+{
674
+ NPCM7xxEMCRxDesc desc[NUM_RX_DESCRIPTORS];
675
+ uint32_t desc_addr = DESC_ADDR;
676
+ uint32_t data_addr = DATA_ADDR;
677
+ int ret;
678
+ uint32_t expected_mask, expected_value;
679
+ NPCM7xxEMCRxDesc result_desc;
680
+
681
+ /* Prepare test data buffer. */
682
+ const char test[RX_DATA_LEN] = "TEST";
683
+ int len = htonl(sizeof(test));
684
+ const struct iovec iov[] = {
685
+ {
686
+ .iov_base = &len,
687
+ .iov_len = sizeof(len),
688
+ },{
689
+ .iov_base = (char *) test,
690
+ .iov_len = sizeof(test),
691
+ },
692
+ };
693
+
694
+ /*
695
+ * Reset the device BEFORE sending a test packet, otherwise the packet
696
+ * may get swallowed by an active device of an earlier test.
697
+ */
698
+ init_rx_desc(&desc[0], NUM_RX_DESCRIPTORS, desc_addr, data_addr);
699
+ enable_rx(qts, mod, &desc[0], NUM_RX_DESCRIPTORS, desc_addr,
700
+ with_irq ? REG_MIEN_ENRXINTR : 0, 0);
701
+
702
+ /* Send test packet to device's socket. */
703
+ ret = iov_send(fd, iov, 2, 0, sizeof(len) + sizeof(test));
704
+ g_assert_cmpint(ret, == , sizeof(test) + sizeof(len));
705
+
706
+ /* Wait for RX interrupt. */
707
+ if (with_irq) {
708
+ g_assert_true(emc_wait_irq(qts, mod, RX_STEP_COUNT, /*is_tx=*/false));
709
+ } else {
710
+ g_assert_true(emc_wait_mista(qts, mod, RX_STEP_COUNT, REG_MISTA_RXGD));
711
+ }
712
+
713
+ g_assert_cmphex(emc_read(qts, mod, REG_CRXDSA), ==,
714
+ desc_addr + sizeof(desc[0]));
715
+
716
+ expected_mask = 0xffff;
717
+ expected_value = (REG_MISTA_DENI |
718
+ REG_MISTA_RXGD |
719
+ REG_MISTA_RXINTR);
720
+ g_assert_cmphex((emc_read(qts, mod, REG_MISTA) & expected_mask),
721
+ ==, expected_value);
722
+
723
+ /* Read the descriptor back. */
724
+ emc_read_rx_desc(qts, desc_addr, &result_desc);
725
+ /* Descriptor should be owned by cpu now. */
726
+ g_assert((result_desc.status_and_length & RX_DESC_STATUS_OWNER_MASK) == 0);
727
+ /* Test the status bits, ignoring the length field. */
728
+ expected_mask = 0xffff << 16;
729
+ expected_value = RX_DESC_STATUS_RXGD;
730
+ if (with_irq) {
731
+ expected_value |= RX_DESC_STATUS_RXINTR;
732
+ }
733
+ g_assert_cmphex((result_desc.status_and_length & expected_mask), ==,
734
+ expected_value);
735
+ g_assert_cmpint(RX_DESC_PKT_LEN(result_desc.status_and_length), ==,
736
+ RX_DATA_LEN + CRC_LENGTH);
737
+
738
+ {
739
+ char buffer[RX_DATA_LEN];
740
+ qtest_memread(qts, data_addr, buffer, sizeof(buffer));
741
+ g_assert_cmpstr(buffer, == , "TEST");
742
+ }
743
+}
744
+
745
+static void emc_test_ptle(QTestState *qts, const EMCModule *mod, int fd)
746
+{
747
+ NPCM7xxEMCRxDesc desc[NUM_RX_DESCRIPTORS];
748
+ uint32_t desc_addr = DESC_ADDR;
749
+ uint32_t data_addr = DATA_ADDR;
750
+ int ret;
751
+ NPCM7xxEMCRxDesc result_desc;
752
+ uint32_t expected_mask, expected_value;
753
+
754
+ /* Prepare test data buffer. */
755
+#define PTLE_DATA_LEN 1600
756
+ char test_data[PTLE_DATA_LEN];
757
+ int len = htonl(sizeof(test_data));
758
+ const struct iovec iov[] = {
759
+ {
760
+ .iov_base = &len,
761
+ .iov_len = sizeof(len),
762
+ },{
763
+ .iov_base = (char *) test_data,
764
+ .iov_len = sizeof(test_data),
765
+ },
766
+ };
767
+ memset(test_data, 42, sizeof(test_data));
768
+
769
+ /*
770
+ * Reset the device BEFORE sending a test packet, otherwise the packet
771
+ * may get swallowed by an active device of an earlier test.
772
+ */
773
+ init_rx_desc(&desc[0], NUM_RX_DESCRIPTORS, desc_addr, data_addr);
774
+ enable_rx(qts, mod, &desc[0], NUM_RX_DESCRIPTORS, desc_addr,
775
+ REG_MIEN_ENRXINTR, REG_MCMDR_ALP);
776
+
777
+ /* Send test packet to device's socket. */
778
+ ret = iov_send(fd, iov, 2, 0, sizeof(len) + sizeof(test_data));
779
+ g_assert_cmpint(ret, == , sizeof(test_data) + sizeof(len));
780
+
781
+ /* Wait for RX interrupt. */
782
+ g_assert_true(emc_wait_irq(qts, mod, RX_STEP_COUNT, /*is_tx=*/false));
783
+
784
+ /* Read the descriptor back. */
785
+ emc_read_rx_desc(qts, desc_addr, &result_desc);
786
+ /* Descriptor should be owned by cpu now. */
787
+ g_assert((result_desc.status_and_length & RX_DESC_STATUS_OWNER_MASK) == 0);
788
+ /* Test the status bits, ignoring the length field. */
789
+ expected_mask = 0xffff << 16;
790
+ expected_value = (RX_DESC_STATUS_RXGD |
791
+ RX_DESC_STATUS_PTLE |
792
+ RX_DESC_STATUS_RXINTR);
793
+ g_assert_cmphex((result_desc.status_and_length & expected_mask), ==,
794
+ expected_value);
795
+ g_assert_cmpint(RX_DESC_PKT_LEN(result_desc.status_and_length), ==,
796
+ PTLE_DATA_LEN + CRC_LENGTH);
797
+
798
+ {
799
+ char buffer[PTLE_DATA_LEN];
800
+ qtest_memread(qts, data_addr, buffer, sizeof(buffer));
801
+ g_assert(memcmp(buffer, test_data, PTLE_DATA_LEN) == 0);
802
+ }
803
+}
804
+
805
+static void test_tx(gconstpointer test_data)
806
+{
807
+ const TestData *td = test_data;
808
+ GString *cmd_line = g_string_new("-machine quanta-gsj");
809
+ int *test_sockets = packet_test_init(emc_module_index(td->module),
810
+ cmd_line);
811
+ QTestState *qts = qtest_init(cmd_line->str);
812
+
813
+ /*
814
+ * TODO: For pedantic correctness test_sockets[0] should be closed after
815
+ * the fork and before the exec, but that will require some harness
816
+ * improvements.
817
+ */
818
+ close(test_sockets[1]);
819
+ /* Defensive programming */
820
+ test_sockets[1] = -1;
821
+
822
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
823
+
824
+ emc_send_verify(qts, td->module, test_sockets[0], /*with_irq=*/false);
825
+ emc_send_verify(qts, td->module, test_sockets[0], /*with_irq=*/true);
826
+
827
+ qtest_quit(qts);
828
+}
829
+
830
+static void test_rx(gconstpointer test_data)
831
+{
832
+ const TestData *td = test_data;
833
+ GString *cmd_line = g_string_new("-machine quanta-gsj");
834
+ int *test_sockets = packet_test_init(emc_module_index(td->module),
835
+ cmd_line);
836
+ QTestState *qts = qtest_init(cmd_line->str);
837
+
838
+ /*
839
+ * TODO: For pedantic correctness test_sockets[0] should be closed after
840
+ * the fork and before the exec, but that will require some harness
841
+ * improvements.
842
+ */
843
+ close(test_sockets[1]);
844
+ /* Defensive programming */
845
+ test_sockets[1] = -1;
846
+
847
+ qtest_irq_intercept_in(qts, "/machine/soc/a9mpcore/gic");
848
+
849
+ emc_recv_verify(qts, td->module, test_sockets[0], /*with_irq=*/false);
850
+ emc_recv_verify(qts, td->module, test_sockets[0], /*with_irq=*/true);
851
+ emc_test_ptle(qts, td->module, test_sockets[0]);
852
+
853
+ qtest_quit(qts);
854
+}
855
+
856
+static void emc_add_test(const char *name, const TestData* td,
857
+ GTestDataFunc fn)
858
+{
859
+ g_autofree char *full_name = g_strdup_printf(
860
+ "npcm7xx_emc/emc[%d]/%s", emc_module_index(td->module), name);
861
+ qtest_add_data_func(full_name, td, fn);
862
+}
863
+#define add_test(name, td) emc_add_test(#name, td, test_##name)
864
+
865
+int main(int argc, char **argv)
866
+{
867
+ TestData test_data_list[ARRAY_SIZE(emc_module_list)];
868
+
869
+ g_test_init(&argc, &argv, NULL);
870
+
871
+ for (int i = 0; i < ARRAY_SIZE(emc_module_list); ++i) {
872
+ TestData *td = &test_data_list[i];
873
+
874
+ td->module = &emc_module_list[i];
875
+
876
+ add_test(init, td);
877
+ add_test(tx, td);
878
+ add_test(rx, td);
879
+ }
880
+
881
+ return g_test_run();
882
+}
883
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
884
index XXXXXXX..XXXXXXX 100644
885
--- a/tests/qtest/meson.build
886
+++ b/tests/qtest/meson.build
887
@@ -XXX,XX +XXX,XX @@ qtests_npcm7xx = \
888
'npcm7xx_rng-test',
889
'npcm7xx_smbus-test',
890
'npcm7xx_timer-test',
891
- 'npcm7xx_watchdog_timer-test']
892
+ 'npcm7xx_watchdog_timer-test'] + \
893
+ (slirp.found() ? ['npcm7xx_emc-test'] : [])
894
qtests_arm = \
895
(config_all_devices.has_key('CONFIG_CMSDK_APB_DUALTIMER') ? ['cmsdk-apb-dualtimer-test'] : []) + \
896
(config_all_devices.has_key('CONFIG_CMSDK_APB_TIMER') ? ['cmsdk-apb-timer-test'] : []) + \
897
--
160
--
898
2.20.1
161
2.20.1
899
162
900
163
diff view generated by jsdifflib
1
From: Doug Evans <dje@google.com>
1
Implement the MVE VCADD insn, which performs a complex add with
2
rotate. Note that the size=0b11 encoding is VSBC.
2
3
3
This is a 10/100 ethernet device that has several features.
4
The architecture grants some leeway for the "destination and Vm
4
Only the ones needed by the Linux driver have been implemented.
5
source overlap" case for the size MO_32 case, but we choose not to
5
See npcm7xx_emc.c for a list of unimplemented features.
6
make use of it, instead always calculating all 16 bytes worth of
7
results before setting the destination register.
6
8
7
Reviewed-by: Hao Wu <wuhaotsh@google.com>
8
Reviewed-by: Avi Fishman <avi.fishman@nuvoton.com>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Doug Evans <dje@google.com>
11
Message-id: 20210218212453.831406-3-dje@google.com
12
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: 20210617121628.20116-42-peter.maydell@linaro.org
13
---
12
---
14
docs/system/arm/nuvoton.rst | 3 ++-
13
target/arm/helper-mve.h | 8 ++++++++
15
include/hw/arm/npcm7xx.h | 2 ++
14
target/arm/mve.decode | 9 +++++++--
16
hw/arm/npcm7xx.c | 50 +++++++++++++++++++++++++++++++++++--
15
target/arm/mve_helper.c | 29 +++++++++++++++++++++++++++++
17
3 files changed, 52 insertions(+), 3 deletions(-)
16
target/arm/translate-mve.c | 7 +++++++
17
4 files changed, 51 insertions(+), 2 deletions(-)
18
18
19
diff --git a/docs/system/arm/nuvoton.rst b/docs/system/arm/nuvoton.rst
19
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
20
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
21
--- a/docs/system/arm/nuvoton.rst
21
--- a/target/arm/helper-mve.h
22
+++ b/docs/system/arm/nuvoton.rst
22
+++ b/target/arm/helper-mve.h
23
@@ -XXX,XX +XXX,XX @@ Supported devices
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vadci, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
* Analog to Digital Converter (ADC)
24
DEF_HELPER_FLAGS_4(mve_vsbc, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
* Pulse Width Modulation (PWM)
25
DEF_HELPER_FLAGS_4(mve_vsbci, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
* SMBus controller (SMBF)
26
27
+ * Ethernet controller (EMC)
27
+DEF_HELPER_FLAGS_4(mve_vcadd90b, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
28
+DEF_HELPER_FLAGS_4(mve_vcadd90h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
Missing devices
29
+DEF_HELPER_FLAGS_4(mve_vcadd90w, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
---------------
30
+
31
@@ -XXX,XX +XXX,XX @@ Missing devices
31
+DEF_HELPER_FLAGS_4(mve_vcadd270b, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
* Shared memory (SHM)
32
+DEF_HELPER_FLAGS_4(mve_vcadd270h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
* eSPI slave interface
33
+DEF_HELPER_FLAGS_4(mve_vcadd270w, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
34
+
35
- * Ethernet controllers (GMAC and EMC)
35
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
36
+ * Ethernet controller (GMAC)
36
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
37
* USB device (USBD)
37
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
38
* Peripheral SPI controller (PSPI)
38
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
39
* SD/MMC host
40
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
41
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
42
--- a/include/hw/arm/npcm7xx.h
40
--- a/target/arm/mve.decode
43
+++ b/include/hw/arm/npcm7xx.h
41
+++ b/target/arm/mve.decode
44
@@ -XXX,XX +XXX,XX @@
42
@@ -XXX,XX +XXX,XX @@ VRHADD_S 111 0 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
45
#include "hw/misc/npcm7xx_gcr.h"
43
VRHADD_U 111 1 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
46
#include "hw/misc/npcm7xx_pwm.h"
44
47
#include "hw/misc/npcm7xx_rng.h"
45
VADC 1110 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
48
+#include "hw/net/npcm7xx_emc.h"
46
-VSBC 1111 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
49
#include "hw/nvram/npcm7xx_otp.h"
47
VADCI 1110 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 0 @2op_nosz
50
#include "hw/timer/npcm7xx_timer.h"
48
-VSBCI 1111 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 0 @2op_nosz
51
#include "hw/ssi/npcm7xx_fiu.h"
49
+
52
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
50
+{
53
EHCISysBusState ehci;
51
+ VSBC 1111 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
54
OHCISysBusState ohci;
52
+ VSBCI 1111 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 0 @2op_nosz
55
NPCM7xxFIUState fiu[2];
53
+ VCADD90 1111 1110 0 . .. ... 0 ... 0 1111 . 0 . 0 ... 0 @2op
56
+ NPCM7xxEMCState emc[2];
54
+ VCADD270 1111 1110 0 . .. ... 0 ... 1 1111 . 0 . 0 ... 0 @2op
57
} NPCM7xxState;
55
+}
58
56
59
#define TYPE_NPCM7XX "npcm7xx"
57
# Vector miscellaneous
60
diff --git a/hw/arm/npcm7xx.c b/hw/arm/npcm7xx.c
58
59
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
61
index XXXXXXX..XXXXXXX 100644
60
index XXXXXXX..XXXXXXX 100644
62
--- a/hw/arm/npcm7xx.c
61
--- a/target/arm/mve_helper.c
63
+++ b/hw/arm/npcm7xx.c
62
+++ b/target/arm/mve_helper.c
64
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
63
@@ -XXX,XX +XXX,XX @@ void HELPER(mve_vsbci)(CPUARMState *env, void *vd, void *vn, void *vm)
65
NPCM7XX_UART1_IRQ,
64
do_vadc(env, vd, vn, vm, -1, 1, true);
66
NPCM7XX_UART2_IRQ,
67
NPCM7XX_UART3_IRQ,
68
+ NPCM7XX_EMC1RX_IRQ = 15,
69
+ NPCM7XX_EMC1TX_IRQ,
70
NPCM7XX_TIMER0_IRQ = 32, /* Timer Module 0 */
71
NPCM7XX_TIMER1_IRQ,
72
NPCM7XX_TIMER2_IRQ,
73
@@ -XXX,XX +XXX,XX @@ enum NPCM7xxInterrupt {
74
NPCM7XX_SMBUS15_IRQ,
75
NPCM7XX_PWM0_IRQ = 93, /* PWM module 0 */
76
NPCM7XX_PWM1_IRQ, /* PWM module 1 */
77
+ NPCM7XX_EMC2RX_IRQ = 114,
78
+ NPCM7XX_EMC2TX_IRQ,
79
NPCM7XX_GPIO0_IRQ = 116,
80
NPCM7XX_GPIO1_IRQ,
81
NPCM7XX_GPIO2_IRQ,
82
@@ -XXX,XX +XXX,XX @@ static const hwaddr npcm7xx_smbus_addr[] = {
83
0xf008f000,
84
};
85
86
+/* Register base address for each EMC Module */
87
+static const hwaddr npcm7xx_emc_addr[] = {
88
+ 0xf0825000,
89
+ 0xf0826000,
90
+};
91
+
92
static const struct {
93
hwaddr regs_addr;
94
uint32_t unconnected_pins;
95
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_init(Object *obj)
96
for (i = 0; i < ARRAY_SIZE(s->pwm); i++) {
97
object_initialize_child(obj, "pwm[*]", &s->pwm[i], TYPE_NPCM7XX_PWM);
98
}
99
+
100
+ for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
101
+ object_initialize_child(obj, "emc[*]", &s->emc[i], TYPE_NPCM7XX_EMC);
102
+ }
103
}
65
}
104
66
105
static void npcm7xx_realize(DeviceState *dev, Error **errp)
67
+#define DO_VCADD(OP, ESIZE, TYPE, FN0, FN1) \
106
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
68
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, void *vm) \
107
sysbus_connect_irq(sbd, i, npcm7xx_irq(s, NPCM7XX_PWM0_IRQ + i));
69
+ { \
108
}
70
+ TYPE *d = vd, *n = vn, *m = vm; \
109
71
+ uint16_t mask = mve_element_mask(env); \
110
+ /*
72
+ unsigned e; \
111
+ * EMC Modules. Cannot fail.
73
+ TYPE r[16 / ESIZE]; \
112
+ * The mapping of the device to its netdev backend works as follows:
74
+ /* Calculate all results first to avoid overwriting inputs */ \
113
+ * emc[i] = nd_table[i]
75
+ for (e = 0; e < 16 / ESIZE; e++) { \
114
+ * This works around the inability to specify the netdev property for the
76
+ if (!(e & 1)) { \
115
+ * emc device: it's not pluggable and thus the -device option can't be
77
+ r[e] = FN0(n[H##ESIZE(e)], m[H##ESIZE(e + 1)]); \
116
+ * used.
78
+ } else { \
117
+ */
79
+ r[e] = FN1(n[H##ESIZE(e)], m[H##ESIZE(e - 1)]); \
118
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(npcm7xx_emc_addr) != ARRAY_SIZE(s->emc));
80
+ } \
119
+ QEMU_BUILD_BUG_ON(ARRAY_SIZE(s->emc) != 2);
81
+ } \
120
+ for (i = 0; i < ARRAY_SIZE(s->emc); i++) {
82
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
121
+ s->emc[i].emc_num = i;
83
+ mergemask(&d[H##ESIZE(e)], r[e], mask); \
122
+ SysBusDevice *sbd = SYS_BUS_DEVICE(&s->emc[i]);
84
+ } \
123
+ if (nd_table[i].used) {
85
+ mve_advance_vpt(env); \
124
+ qemu_check_nic_model(&nd_table[i], TYPE_NPCM7XX_EMC);
125
+ qdev_set_nic_properties(DEVICE(sbd), &nd_table[i]);
126
+ }
127
+ /*
128
+ * The device exists regardless of whether it's connected to a QEMU
129
+ * netdev backend. So always instantiate it even if there is no
130
+ * backend.
131
+ */
132
+ sysbus_realize(sbd, &error_abort);
133
+ sysbus_mmio_map(sbd, 0, npcm7xx_emc_addr[i]);
134
+ int tx_irq = i == 0 ? NPCM7XX_EMC1TX_IRQ : NPCM7XX_EMC2TX_IRQ;
135
+ int rx_irq = i == 0 ? NPCM7XX_EMC1RX_IRQ : NPCM7XX_EMC2RX_IRQ;
136
+ /*
137
+ * N.B. The values for the second argument sysbus_connect_irq are
138
+ * chosen to match the registration order in npcm7xx_emc_realize.
139
+ */
140
+ sysbus_connect_irq(sbd, 0, npcm7xx_irq(s, tx_irq));
141
+ sysbus_connect_irq(sbd, 1, npcm7xx_irq(s, rx_irq));
142
+ }
86
+ }
143
+
87
+
144
/*
88
+#define DO_VCADD_ALL(OP, FN0, FN1) \
145
* Flash Interface Unit (FIU). Can fail if incorrect number of chip selects
89
+ DO_VCADD(OP##b, 1, int8_t, FN0, FN1) \
146
* specified, but this is a programming error.
90
+ DO_VCADD(OP##h, 2, int16_t, FN0, FN1) \
147
@@ -XXX,XX +XXX,XX @@ static void npcm7xx_realize(DeviceState *dev, Error **errp)
91
+ DO_VCADD(OP##w, 4, int32_t, FN0, FN1)
148
create_unimplemented_device("npcm7xx.vcd", 0xf0810000, 64 * KiB);
92
+
149
create_unimplemented_device("npcm7xx.ece", 0xf0820000, 8 * KiB);
93
+DO_VCADD_ALL(vcadd90, DO_SUB, DO_ADD)
150
create_unimplemented_device("npcm7xx.vdma", 0xf0822000, 8 * KiB);
94
+DO_VCADD_ALL(vcadd270, DO_ADD, DO_SUB)
151
- create_unimplemented_device("npcm7xx.emc1", 0xf0825000, 4 * KiB);
95
+
152
- create_unimplemented_device("npcm7xx.emc2", 0xf0826000, 4 * KiB);
96
static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
153
create_unimplemented_device("npcm7xx.usbd[0]", 0xf0830000, 4 * KiB);
97
{
154
create_unimplemented_device("npcm7xx.usbd[1]", 0xf0831000, 4 * KiB);
98
if (val > max) {
155
create_unimplemented_device("npcm7xx.usbd[2]", 0xf0832000, 4 * KiB);
99
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
100
index XXXXXXX..XXXXXXX 100644
101
--- a/target/arm/translate-mve.c
102
+++ b/target/arm/translate-mve.c
103
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQRDMLSDH, vqrdmlsdh)
104
DO_2OP(VQRDMLSDHX, vqrdmlsdhx)
105
DO_2OP(VRHADD_S, vrhadds)
106
DO_2OP(VRHADD_U, vrhaddu)
107
+/*
108
+ * VCADD Qd == Qm at size MO_32 is UNPREDICTABLE; we choose not to diagnose
109
+ * so we can reuse the DO_2OP macro. (Our implementation calculates the
110
+ * "expected" results in this case.)
111
+ */
112
+DO_2OP(VCADD90, vcadd90)
113
+DO_2OP(VCADD270, vcadd270)
114
115
static bool trans_VQDMULLB(DisasContext *s, arg_2op *a)
116
{
156
--
117
--
157
2.20.1
118
2.20.1
158
119
159
120
diff view generated by jsdifflib
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
1
Implement the MVE VHCADD insn, which is similar to VCADD
2
but performs a halving step. This one overlaps with VADC.
2
3
3
Let add 'max' cpu while work goes on adding newer CPU types than
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Cortex-A72. This allows us to check SVE etc support.
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210617121628.20116-43-peter.maydell@linaro.org
7
---
8
target/arm/helper-mve.h | 8 ++++++++
9
target/arm/mve.decode | 8 ++++++--
10
target/arm/mve_helper.c | 2 ++
11
target/arm/translate-mve.c | 4 +++-
12
4 files changed, 19 insertions(+), 3 deletions(-)
5
13
6
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
7
Acked-by: Leif Lindholm <leif@nuviainc.com>
8
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Message-id: 20210216150122.3830863-3-marcin.juszkiewicz@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
hw/arm/sbsa-ref.c | 1 +
13
1 file changed, 1 insertion(+)
14
15
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/sbsa-ref.c
16
--- a/target/arm/helper-mve.h
18
+++ b/hw/arm/sbsa-ref.c
17
+++ b/target/arm/helper-mve.h
19
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vcadd270b, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
static const char * const valid_cpus[] = {
19
DEF_HELPER_FLAGS_4(mve_vcadd270h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
ARM_CPU_TYPE_NAME("cortex-a57"),
20
DEF_HELPER_FLAGS_4(mve_vcadd270w, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
ARM_CPU_TYPE_NAME("cortex-a72"),
21
23
+ ARM_CPU_TYPE_NAME("max"),
22
+DEF_HELPER_FLAGS_4(mve_vhcadd90b, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
};
23
+DEF_HELPER_FLAGS_4(mve_vhcadd90h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
24
+DEF_HELPER_FLAGS_4(mve_vhcadd90w, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
static bool cpu_type_valid(const char *cpu)
25
+
26
+DEF_HELPER_FLAGS_4(mve_vhcadd270b, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_vhcadd270h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+DEF_HELPER_FLAGS_4(mve_vhcadd270w, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
+
30
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
32
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
33
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/mve.decode
36
+++ b/target/arm/mve.decode
37
@@ -XXX,XX +XXX,XX @@ VQDMULLT 111 . 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 1 @2op_sz28
38
VRHADD_S 111 0 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
39
VRHADD_U 111 1 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
40
41
-VADC 1110 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
42
-VADCI 1110 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 0 @2op_nosz
43
+{
44
+ VADC 1110 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
45
+ VADCI 1110 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 0 @2op_nosz
46
+ VHCADD90 1110 1110 0 . .. ... 0 ... 0 1111 . 0 . 0 ... 0 @2op
47
+ VHCADD270 1110 1110 0 . .. ... 0 ... 1 1111 . 0 . 0 ... 0 @2op
48
+}
49
50
{
51
VSBC 1111 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
52
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/mve_helper.c
55
+++ b/target/arm/mve_helper.c
56
@@ -XXX,XX +XXX,XX @@ void HELPER(mve_vsbci)(CPUARMState *env, void *vd, void *vn, void *vm)
57
58
DO_VCADD_ALL(vcadd90, DO_SUB, DO_ADD)
59
DO_VCADD_ALL(vcadd270, DO_ADD, DO_SUB)
60
+DO_VCADD_ALL(vhcadd90, do_vhsub_s, do_vhadd_s)
61
+DO_VCADD_ALL(vhcadd270, do_vhadd_s, do_vhsub_s)
62
63
static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
64
{
65
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/target/arm/translate-mve.c
68
+++ b/target/arm/translate-mve.c
69
@@ -XXX,XX +XXX,XX @@ DO_2OP(VRHADD_U, vrhaddu)
70
/*
71
* VCADD Qd == Qm at size MO_32 is UNPREDICTABLE; we choose not to diagnose
72
* so we can reuse the DO_2OP macro. (Our implementation calculates the
73
- * "expected" results in this case.)
74
+ * "expected" results in this case.) Similarly for VHCADD.
75
*/
76
DO_2OP(VCADD90, vcadd90)
77
DO_2OP(VCADD270, vcadd270)
78
+DO_2OP(VHCADD90, vhcadd90)
79
+DO_2OP(VHCADD270, vhcadd270)
80
81
static bool trans_VQDMULLB(DisasContext *s, arg_2op *a)
82
{
27
--
83
--
28
2.20.1
84
2.20.1
29
85
30
86
diff view generated by jsdifflib
1
On the MPS2 boards, the first 32 interrupt lines are entirely
1
Implement the MVE VADDV insn, which performs an addition
2
internal to the SSE; interrupt lines for devices outside the SSE
2
across vector lanes.
3
start at 32. In the application notes that document each FPGA image,
4
the interrupt wiring is documented from the point of view of the CPU,
5
so '0' is the first of the SSE's interrupts and the devices in the
6
FPGA image itself are '32' and up: so the UART 0 Receive interrupt is
7
32, the SPI #0 interrupt is 51, and so on.
8
9
Within our implementation, because the external interrupts must be
10
connected to the EXP_IRQ[0...n] lines of the SSE object, we made the
11
get_sse_irq_in() function take an irqno whose values start at 0 for
12
the first FPGA device interrupt. In this numbering scheme the UART 0
13
Receive interrupt is 0, the SPI #0 interrupt is 19, and so on.
14
15
The result of these two different numbering schemes has been that
16
half of the devices were wired up to the wrong IRQs: the UART IRQs
17
are wired up correctly, but the DMA and SPI devices were passing
18
start-at-32 values to get_sse_irq_in() and so being mis-connected.
19
20
Fix the bug by making get_sse_irq_in() take values specified with the
21
same scheme that the hardware manuals use, to avoid confusion.
22
3
23
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
24
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
25
Message-id: 20210215115138.20465-12-peter.maydell@linaro.org
6
Message-id: 20210617121628.20116-44-peter.maydell@linaro.org
26
---
7
---
27
hw/arm/mps2-tz.c | 24 +++++++++++++++++-------
8
target/arm/helper-mve.h | 7 +++++++
28
1 file changed, 17 insertions(+), 7 deletions(-)
9
target/arm/mve.decode | 2 ++
10
target/arm/mve_helper.c | 24 +++++++++++++++++++++
11
target/arm/translate-mve.c | 43 ++++++++++++++++++++++++++++++++++++++
12
4 files changed, 76 insertions(+)
29
13
30
diff --git a/hw/arm/mps2-tz.c b/hw/arm/mps2-tz.c
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
31
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
32
--- a/hw/arm/mps2-tz.c
16
--- a/target/arm/helper-mve.h
33
+++ b/hw/arm/mps2-tz.c
17
+++ b/target/arm/helper-mve.h
34
@@ -XXX,XX +XXX,XX @@ static void make_ram_alias(MemoryRegion *mr, const char *name,
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vrmlaldavhuw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
35
19
36
static qemu_irq get_sse_irq_in(MPS2TZMachineState *mms, int irqno)
20
DEF_HELPER_FLAGS_4(mve_vrmlsldavhsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
37
{
21
DEF_HELPER_FLAGS_4(mve_vrmlsldavhxsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
38
- /* Return a qemu_irq which will signal IRQ n to all CPUs in the SSE. */
22
+
39
+ /*
23
+DEF_HELPER_FLAGS_3(mve_vaddvsb, TCG_CALL_NO_WG, i32, env, ptr, i32)
40
+ * Return a qemu_irq which will signal IRQ n to all CPUs in the
24
+DEF_HELPER_FLAGS_3(mve_vaddvub, TCG_CALL_NO_WG, i32, env, ptr, i32)
41
+ * SSE. The irqno should be as the CPU sees it, so the first
25
+DEF_HELPER_FLAGS_3(mve_vaddvsh, TCG_CALL_NO_WG, i32, env, ptr, i32)
42
+ * external-to-the-SSE interrupt is 32.
26
+DEF_HELPER_FLAGS_3(mve_vaddvuh, TCG_CALL_NO_WG, i32, env, ptr, i32)
43
+ */
27
+DEF_HELPER_FLAGS_3(mve_vaddvsw, TCG_CALL_NO_WG, i32, env, ptr, i32)
44
MachineClass *mc = MACHINE_GET_CLASS(mms);
28
+DEF_HELPER_FLAGS_3(mve_vaddvuw, TCG_CALL_NO_WG, i32, env, ptr, i32)
45
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
29
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
46
30
index XXXXXXX..XXXXXXX 100644
47
- assert(irqno < mmc->numirq);
31
--- a/target/arm/mve.decode
48
+ assert(irqno >= 32 && irqno < (mmc->numirq + 32));
32
+++ b/target/arm/mve.decode
33
@@ -XXX,XX +XXX,XX @@ VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
34
VQDMULH_scalar 1110 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
35
VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
36
37
+# Vector add across vector
38
+VADDV 111 u:1 1110 1111 size:2 01 ... 0 1111 0 0 a:1 0 qm:3 0 rda=%rdalo
39
40
# Predicate operations
41
%mask_22_13 22:1 13:3
42
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/mve_helper.c
45
+++ b/target/arm/mve_helper.c
46
@@ -XXX,XX +XXX,XX @@ DO_LDAVH(vrmlaldavhuw, 4, uint32_t, false, int128_add, int128_add, int128_make64
47
48
DO_LDAVH(vrmlsldavhsw, 4, int32_t, false, int128_add, int128_sub, int128_makes64)
49
DO_LDAVH(vrmlsldavhxsw, 4, int32_t, true, int128_add, int128_sub, int128_makes64)
50
+
51
+/* Vector add across vector */
52
+#define DO_VADDV(OP, ESIZE, TYPE) \
53
+ uint32_t HELPER(glue(mve_, OP))(CPUARMState *env, void *vm, \
54
+ uint32_t ra) \
55
+ { \
56
+ uint16_t mask = mve_element_mask(env); \
57
+ unsigned e; \
58
+ TYPE *m = vm; \
59
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
60
+ if (mask & 1) { \
61
+ ra += m[H##ESIZE(e)]; \
62
+ } \
63
+ } \
64
+ mve_advance_vpt(env); \
65
+ return ra; \
66
+ } \
67
+
68
+DO_VADDV(vaddvsb, 1, uint8_t)
69
+DO_VADDV(vaddvsh, 2, uint16_t)
70
+DO_VADDV(vaddvsw, 4, uint32_t)
71
+DO_VADDV(vaddvub, 1, uint8_t)
72
+DO_VADDV(vaddvuh, 2, uint16_t)
73
+DO_VADDV(vaddvuw, 4, uint32_t)
74
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/target/arm/translate-mve.c
77
+++ b/target/arm/translate-mve.c
78
@@ -XXX,XX +XXX,XX @@ typedef void MVEGenOneOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
79
typedef void MVEGenTwoOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr);
80
typedef void MVEGenTwoOpScalarFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
81
typedef void MVEGenDualAccOpFn(TCGv_i64, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i64);
82
+typedef void MVEGenVADDVFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32);
83
84
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
85
static inline long mve_qreg_offset(unsigned reg)
86
@@ -XXX,XX +XXX,XX @@ static bool trans_VPST(DisasContext *s, arg_VPST *a)
87
mve_update_and_store_eci(s);
88
return true;
89
}
90
+
91
+static bool trans_VADDV(DisasContext *s, arg_VADDV *a)
92
+{
93
+ /* VADDV: vector add across vector */
94
+ static MVEGenVADDVFn * const fns[4][2] = {
95
+ { gen_helper_mve_vaddvsb, gen_helper_mve_vaddvub },
96
+ { gen_helper_mve_vaddvsh, gen_helper_mve_vaddvuh },
97
+ { gen_helper_mve_vaddvsw, gen_helper_mve_vaddvuw },
98
+ { NULL, NULL }
99
+ };
100
+ TCGv_ptr qm;
101
+ TCGv_i32 rda;
102
+
103
+ if (!dc_isar_feature(aa32_mve, s) ||
104
+ a->size == 3) {
105
+ return false;
106
+ }
107
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
108
+ return true;
109
+ }
49
+
110
+
50
+ /*
111
+ /*
51
+ * Convert from "CPU irq number" (as listed in the FPGA image
112
+ * This insn is subject to beat-wise execution. Partial execution
52
+ * documentation) to the SSE external-interrupt number.
113
+ * of an A=0 (no-accumulate) insn which does not execute the first
114
+ * beat must start with the current value of Rda, not zero.
53
+ */
115
+ */
54
+ irqno -= 32;
116
+ if (a->a || mve_skip_first_beat(s)) {
55
117
+ /* Accumulate input from Rda */
56
if (mc->max_cpus > 1) {
118
+ rda = load_reg(s, a->rda);
57
return qdev_get_gpio_in(DEVICE(&mms->cpu_irq_splitter[irqno]), 0);
119
+ } else {
58
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_uart(MPS2TZMachineState *mms, void *opaque,
120
+ /* Accumulate starting at zero */
59
MPS2TZMachineClass *mmc = MPS2TZ_MACHINE_GET_CLASS(mms);
121
+ rda = tcg_const_i32(0);
60
CMSDKAPBUART *uart = opaque;
122
+ }
61
int i = uart - &mms->uart[0];
123
+
62
- int rxirqno = i * 2;
124
+ qm = mve_qreg_ptr(a->qm);
63
- int txirqno = i * 2 + 1;
125
+ fns[a->size][a->u](rda, cpu_env, qm, rda);
64
- int combirqno = i + 10;
126
+ store_reg(s, a->rda, rda);
65
+ int rxirqno = i * 2 + 32;
127
+ tcg_temp_free_ptr(qm);
66
+ int txirqno = i * 2 + 33;
128
+
67
+ int combirqno = i + 42;
129
+ mve_update_eci(s);
68
SysBusDevice *s;
130
+ return true;
69
DeviceState *orgate_dev = DEVICE(&mms->uart_irq_orgate);
131
+}
70
71
@@ -XXX,XX +XXX,XX @@ static MemoryRegion *make_eth_dev(MPS2TZMachineState *mms, void *opaque,
72
73
s = SYS_BUS_DEVICE(mms->lan9118);
74
sysbus_realize_and_unref(s, &error_fatal);
75
- sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 16));
76
+ sysbus_connect_irq(s, 0, get_sse_irq_in(mms, 48));
77
return sysbus_mmio_get_region(s, 0);
78
}
79
80
@@ -XXX,XX +XXX,XX @@ static void mps2tz_common_init(MachineState *machine)
81
&error_fatal);
82
qdev_realize(DEVICE(&mms->uart_irq_orgate), NULL, &error_fatal);
83
qdev_connect_gpio_out(DEVICE(&mms->uart_irq_orgate), 0,
84
- get_sse_irq_in(mms, 15));
85
+ get_sse_irq_in(mms, 47));
86
87
/* Most of the devices in the FPGA are behind Peripheral Protection
88
* Controllers. The required order for initializing things is:
89
--
132
--
90
2.20.1
133
2.20.1
91
134
92
135
diff view generated by jsdifflib
1
For a long time now the UI layer has guaranteed that the console
1
In a CPU with MVE, the VMOV (vector lane to general-purpose register)
2
surface is always 32 bits per pixel RGB. Remove the legacy dead
2
and VMOV (general-purpose register to vector lane) insns are not
3
code from the milkymist display device which was handling the
3
predicated, but they are subject to beatwise execution if they
4
possibility that the console surface was some other format.
4
are not in an IT block.
5
6
Since our implementation always executes all 4 beats in one tick,
7
this means only that we need to handle PSR.ECI:
8
* we must do the usual check for bad ECI state
9
* we must advance ECI state if the insn succeeds
10
* if ECI says we should not be executing the beat corresponding
11
to the lane of the vector register being accessed then we
12
should skip performing the move
13
14
Note that if PSR.ECI is non-zero then we cannot be in an IT block.
5
15
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20210215103215.4944-2-peter.maydell@linaro.org
18
Message-id: 20210617121628.20116-45-peter.maydell@linaro.org
9
---
19
---
10
hw/arm/musicpal.c | 64 ++++++++++++++++++-----------------------------
20
target/arm/translate-a32.h | 2 +
11
1 file changed, 24 insertions(+), 40 deletions(-)
21
target/arm/translate-mve.c | 4 +-
22
target/arm/translate-vfp.c | 77 +++++++++++++++++++++++++++++++++++---
23
3 files changed, 75 insertions(+), 8 deletions(-)
12
24
13
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
25
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
14
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
15
--- a/hw/arm/musicpal.c
27
--- a/target/arm/translate-a32.h
16
+++ b/hw/arm/musicpal.c
28
+++ b/target/arm/translate-a32.h
17
@@ -XXX,XX +XXX,XX @@ static uint8_t scale_lcd_color(musicpal_lcd_state *s, uint8_t col)
29
@@ -XXX,XX +XXX,XX @@ long neon_full_reg_offset(unsigned reg);
30
long neon_element_offset(int reg, int element, MemOp memop);
31
void gen_rev16(TCGv_i32 dest, TCGv_i32 var);
32
void clear_eci_state(DisasContext *s);
33
+bool mve_eci_check(DisasContext *s);
34
+void mve_update_and_store_eci(DisasContext *s);
35
36
static inline TCGv_i32 load_cpu_offset(int offset)
37
{
38
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/translate-mve.c
41
+++ b/target/arm/translate-mve.c
42
@@ -XXX,XX +XXX,XX @@ static bool mve_check_qreg_bank(DisasContext *s, int qmask)
43
return qmask < 8;
44
}
45
46
-static bool mve_eci_check(DisasContext *s)
47
+bool mve_eci_check(DisasContext *s)
48
{
49
/*
50
* This is a beatwise insn: check that ECI is valid (not a
51
@@ -XXX,XX +XXX,XX @@ static void mve_update_eci(DisasContext *s)
18
}
52
}
19
}
53
}
20
54
21
-#define SET_LCD_PIXEL(depth, type) \
55
-static void mve_update_and_store_eci(DisasContext *s)
22
-static inline void glue(set_lcd_pixel, depth) \
56
+void mve_update_and_store_eci(DisasContext *s)
23
- (musicpal_lcd_state *s, int x, int y, type col) \
57
{
24
-{ \
58
/*
25
- int dx, dy; \
59
* For insns which don't call a helper function that will call
26
- DisplaySurface *surface = qemu_console_surface(s->con); \
60
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
27
- type *pixel = &((type *) surface_data(surface))[(y * 128 * 3 + x) * 3]; \
61
index XXXXXXX..XXXXXXX 100644
28
-\
62
--- a/target/arm/translate-vfp.c
29
- for (dy = 0; dy < 3; dy++, pixel += 127 * 3) \
63
+++ b/target/arm/translate-vfp.c
30
- for (dx = 0; dx < 3; dx++, pixel++) \
64
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
31
- *pixel = col; \
65
return true;
32
+static inline void set_lcd_pixel32(musicpal_lcd_state *s,
66
}
33
+ int x, int y, uint32_t col)
67
68
+static bool mve_skip_vmov(DisasContext *s, int vn, int index, int size)
34
+{
69
+{
35
+ int dx, dy;
70
+ /*
36
+ DisplaySurface *surface = qemu_console_surface(s->con);
71
+ * In a CPU with MVE, the VMOV (vector lane to general-purpose register)
37
+ uint32_t *pixel =
72
+ * and VMOV (general-purpose register to vector lane) insns are not
38
+ &((uint32_t *) surface_data(surface))[(y * 128 * 3 + x) * 3];
73
+ * predicated, but they are subject to beatwise execution if they are
74
+ * not in an IT block.
75
+ *
76
+ * Since our implementation always executes all 4 beats in one tick,
77
+ * this means only that if PSR.ECI says we should not be executing
78
+ * the beat corresponding to the lane of the vector register being
79
+ * accessed then we should skip performing the move, and that we need
80
+ * to do the usual check for bad ECI state and advance of ECI state.
81
+ *
82
+ * Note that if PSR.ECI is non-zero then we cannot be in an IT block.
83
+ *
84
+ * Return true if this VMOV scalar <-> gpreg should be skipped because
85
+ * the MVE PSR.ECI state says we skip the beat where the store happens.
86
+ */
39
+
87
+
40
+ for (dy = 0; dy < 3; dy++, pixel += 127 * 3) {
88
+ /* Calculate the byte offset into Qn which we're going to access */
41
+ for (dx = 0; dx < 3; dx++, pixel++) {
89
+ int ofs = (index << size) + ((vn & 1) * 8);
42
+ *pixel = col;
90
+
91
+ if (!dc_isar_feature(aa32_mve, s)) {
92
+ return false;
93
+ }
94
+
95
+ switch (s->eci) {
96
+ case ECI_NONE:
97
+ return false;
98
+ case ECI_A0:
99
+ return ofs < 4;
100
+ case ECI_A0A1:
101
+ return ofs < 8;
102
+ case ECI_A0A1A2:
103
+ case ECI_A0A1A2B0:
104
+ return ofs < 12;
105
+ default:
106
+ g_assert_not_reached();
107
+ }
108
+}
109
+
110
static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a)
111
{
112
/* VMOV scalar to general purpose register */
113
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a)
114
return false;
115
}
116
117
+ if (dc_isar_feature(aa32_mve, s)) {
118
+ if (!mve_eci_check(s)) {
119
+ return true;
43
+ }
120
+ }
44
+ }
121
+ }
122
+
123
if (!vfp_access_check(s)) {
124
return true;
125
}
126
127
- tmp = tcg_temp_new_i32();
128
- read_neon_element32(tmp, a->vn, a->index, a->size | (a->u ? 0 : MO_SIGN));
129
- store_reg(s, a->rt, tmp);
130
+ if (!mve_skip_vmov(s, a->vn, a->index, a->size)) {
131
+ tmp = tcg_temp_new_i32();
132
+ read_neon_element32(tmp, a->vn, a->index,
133
+ a->size | (a->u ? 0 : MO_SIGN));
134
+ store_reg(s, a->rt, tmp);
135
+ }
136
137
+ if (dc_isar_feature(aa32_mve, s)) {
138
+ mve_update_and_store_eci(s);
139
+ }
140
return true;
45
}
141
}
46
-SET_LCD_PIXEL(8, uint8_t)
142
47
-SET_LCD_PIXEL(16, uint16_t)
143
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_from_gp(DisasContext *s, arg_VMOV_from_gp *a)
48
-SET_LCD_PIXEL(32, uint32_t)
144
return false;
49
145
}
50
static void lcd_refresh(void *opaque)
146
51
{
147
+ if (dc_isar_feature(aa32_mve, s)) {
52
musicpal_lcd_state *s = opaque;
148
+ if (!mve_eci_check(s)) {
53
- DisplaySurface *surface = qemu_console_surface(s->con);
149
+ return true;
54
int x, y, col;
55
56
- switch (surface_bits_per_pixel(surface)) {
57
- case 0:
58
- return;
59
-#define LCD_REFRESH(depth, func) \
60
- case depth: \
61
- col = func(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff), \
62
- scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff), \
63
- scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff)); \
64
- for (x = 0; x < 128; x++) { \
65
- for (y = 0; y < 64; y++) { \
66
- if (s->video_ram[x + (y/8)*128] & (1 << (y % 8))) { \
67
- glue(set_lcd_pixel, depth)(s, x, y, col); \
68
- } else { \
69
- glue(set_lcd_pixel, depth)(s, x, y, 0); \
70
- } \
71
- } \
72
- } \
73
- break;
74
- LCD_REFRESH(8, rgb_to_pixel8)
75
- LCD_REFRESH(16, rgb_to_pixel16)
76
- LCD_REFRESH(32, (is_surface_bgr(surface) ?
77
- rgb_to_pixel32bgr : rgb_to_pixel32))
78
- default:
79
- hw_error("unsupported colour depth %i\n",
80
- surface_bits_per_pixel(surface));
81
+ col = rgb_to_pixel32(scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 16) & 0xff),
82
+ scale_lcd_color(s, (MP_LCD_TEXTCOLOR >> 8) & 0xff),
83
+ scale_lcd_color(s, MP_LCD_TEXTCOLOR & 0xff));
84
+ for (x = 0; x < 128; x++) {
85
+ for (y = 0; y < 64; y++) {
86
+ if (s->video_ram[x + (y / 8) * 128] & (1 << (y % 8))) {
87
+ set_lcd_pixel32(s, x, y, col);
88
+ } else {
89
+ set_lcd_pixel32(s, x, y, 0);
90
+ }
91
+ }
150
+ }
151
+ }
152
+
153
if (!vfp_access_check(s)) {
154
return true;
92
}
155
}
93
156
94
dpy_gfx_update(s->con, 0, 0, 128*3, 64*3);
157
- tmp = load_reg(s, a->rt);
158
- write_neon_element32(tmp, a->vn, a->index, a->size);
159
- tcg_temp_free_i32(tmp);
160
+ if (!mve_skip_vmov(s, a->vn, a->index, a->size)) {
161
+ tmp = load_reg(s, a->rt);
162
+ write_neon_element32(tmp, a->vn, a->index, a->size);
163
+ tcg_temp_free_i32(tmp);
164
+ }
165
166
+ if (dc_isar_feature(aa32_mve, s)) {
167
+ mve_update_and_store_eci(s);
168
+ }
169
return true;
170
}
171
95
--
172
--
96
2.20.1
173
2.20.1
97
174
98
175
diff view generated by jsdifflib
1
From: Peter Collingbourne <pcc@google.com>
1
From: Peter Collingbourne <pcc@google.com>
2
2
3
Section D6.7 of the ARM ARM states:
3
MTE3 introduces an asymmetric tag checking mode, in which loads are
4
4
checked synchronously and stores are checked asynchronously. Add
5
For the purpose of determining Tag Check Fault handling, unprivileged
5
support for it.
6
load and store instructions are treated as if executed at EL0 when
7
executed at either:
8
- EL1, when the Effective value of PSTATE.UAO is 0.
9
- EL2, when both the Effective value of HCR_EL2.{E2H, TGE} is {1, 1}
10
and the Effective value of PSTATE.UAO is 0.
11
12
ARM has confirmed a defect in the pseudocode function
13
AArch64.TagCheckFault that makes it inconsistent with the above
14
wording. The remedy is to adjust references to PSTATE.EL in that
15
function to instead refer to AArch64.AccessUsesEL(acctype), so
16
that unprivileged instructions use SCTLR_EL1.TCF0 and TFSRE0_EL1.
17
The exception type for synchronous tag check faults remains unchanged.
18
19
This patch implements the described change by partially reverting
20
commits 50244cc76abc and cc97b0019bb5.
21
6
22
Signed-off-by: Peter Collingbourne <pcc@google.com>
7
Signed-off-by: Peter Collingbourne <pcc@google.com>
23
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
24
Message-id: 20210219201820.2672077-1-pcc@google.com
9
Message-id: 20210616195614.11785-1-pcc@google.com
25
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
[PMM: Add line to emulation.rst]
26
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
27
---
12
---
28
target/arm/helper.c | 2 +-
13
docs/system/arm/emulation.rst | 1 +
29
target/arm/mte_helper.c | 13 +++++++++----
14
target/arm/cpu64.c | 2 +-
30
2 files changed, 10 insertions(+), 5 deletions(-)
15
target/arm/mte_helper.c | 82 ++++++++++++++++++++++-------------
16
3 files changed, 53 insertions(+), 32 deletions(-)
31
17
32
diff --git a/target/arm/helper.c b/target/arm/helper.c
18
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
33
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/helper.c
20
--- a/docs/system/arm/emulation.rst
35
+++ b/target/arm/helper.c
21
+++ b/docs/system/arm/emulation.rst
36
@@ -XXX,XX +XXX,XX @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
22
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
37
if (FIELD_EX32(flags, TBFLAG_A64, UNPRIV)
23
- FEAT_LSE (Large System Extensions)
38
&& tbid
24
- FEAT_MTE (Memory Tagging Extension)
39
&& !(env->pstate & PSTATE_TCO)
25
- FEAT_MTE2 (Memory Tagging Extension)
40
- && (sctlr & SCTLR_TCF)
26
+- FEAT_MTE3 (MTE Asymmetric Fault Handling)
41
+ && (sctlr & SCTLR_TCF0)
27
- FEAT_PAN (Privileged access never)
42
&& allocation_tag_access_enabled(env, 0, sctlr)) {
28
- FEAT_PAN2 (AT S1E1R and AT S1E1W instruction variants affected by PSTATE.PAN)
43
flags = FIELD_DP32(flags, TBFLAG_A64, MTE0_ACTIVE, 1);
29
- FEAT_PAuth (Pointer authentication)
44
}
30
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/cpu64.c
33
+++ b/target/arm/cpu64.c
34
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
35
* during realize if the board provides no tag memory, much like
36
* we do for EL2 with the virtualization=on property.
37
*/
38
- t = FIELD_DP64(t, ID_AA64PFR1, MTE, 2);
39
+ t = FIELD_DP64(t, ID_AA64PFR1, MTE, 3);
40
cpu->isar.id_aa64pfr1 = t;
41
42
t = cpu->isar.id_aa64mmfr0;
45
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
43
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
46
index XXXXXXX..XXXXXXX 100644
44
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/mte_helper.c
45
--- a/target/arm/mte_helper.c
48
+++ b/target/arm/mte_helper.c
46
+++ b/target/arm/mte_helper.c
47
@@ -XXX,XX +XXX,XX @@ void HELPER(stzgm_tags)(CPUARMState *env, uint64_t ptr, uint64_t val)
48
}
49
}
50
51
+static void mte_sync_check_fail(CPUARMState *env, uint32_t desc,
52
+ uint64_t dirty_ptr, uintptr_t ra)
53
+{
54
+ int is_write, syn;
55
+
56
+ env->exception.vaddress = dirty_ptr;
57
+
58
+ is_write = FIELD_EX32(desc, MTEDESC, WRITE);
59
+ syn = syn_data_abort_no_iss(arm_current_el(env) != 0, 0, 0, 0, 0, is_write,
60
+ 0x11);
61
+ raise_exception_ra(env, EXCP_DATA_ABORT, syn, exception_target_el(env), ra);
62
+ g_assert_not_reached();
63
+}
64
+
65
+static void mte_async_check_fail(CPUARMState *env, uint64_t dirty_ptr,
66
+ uintptr_t ra, ARMMMUIdx arm_mmu_idx, int el)
67
+{
68
+ int select;
69
+
70
+ if (regime_has_2_ranges(arm_mmu_idx)) {
71
+ select = extract64(dirty_ptr, 55, 1);
72
+ } else {
73
+ select = 0;
74
+ }
75
+ env->cp15.tfsr_el[el] |= 1 << select;
76
+#ifdef CONFIG_USER_ONLY
77
+ /*
78
+ * Stand in for a timer irq, setting _TIF_MTE_ASYNC_FAULT,
79
+ * which then sends a SIGSEGV when the thread is next scheduled.
80
+ * This cpu will return to the main loop at the end of the TB,
81
+ * which is rather sooner than "normal". But the alternative
82
+ * is waiting until the next syscall.
83
+ */
84
+ qemu_cpu_kick(env_cpu(env));
85
+#endif
86
+}
87
+
88
/* Record a tag check failure. */
89
static void mte_check_fail(CPUARMState *env, uint32_t desc,
90
uint64_t dirty_ptr, uintptr_t ra)
91
{
92
int mmu_idx = FIELD_EX32(desc, MTEDESC, MIDX);
93
ARMMMUIdx arm_mmu_idx = core_to_aa64_mmu_idx(mmu_idx);
94
- int el, reg_el, tcf, select, is_write, syn;
95
+ int el, reg_el, tcf;
96
uint64_t sctlr;
97
98
reg_el = regime_el(env, arm_mmu_idx);
49
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
99
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
50
reg_el = regime_el(env, arm_mmu_idx);
100
switch (tcf) {
51
sctlr = env->cp15.sctlr_el[reg_el];
101
case 1:
52
102
/* Tag check fail causes a synchronous exception. */
53
- el = arm_current_el(env);
103
- env->exception.vaddress = dirty_ptr;
54
- if (el == 0) {
104
-
55
+ switch (arm_mmu_idx) {
105
- is_write = FIELD_EX32(desc, MTEDESC, WRITE);
56
+ case ARMMMUIdx_E10_0:
106
- syn = syn_data_abort_no_iss(arm_current_el(env) != 0, 0, 0, 0, 0,
57
+ case ARMMMUIdx_E20_0:
107
- is_write, 0x11);
58
+ el = 0;
108
- raise_exception_ra(env, EXCP_DATA_ABORT, syn,
59
tcf = extract64(sctlr, 38, 2);
109
- exception_target_el(env), ra);
60
- } else {
110
- /* noreturn, but fall through to the assert anyway */
111
+ mte_sync_check_fail(env, desc, dirty_ptr, ra);
61
+ break;
112
+ break;
62
+ default:
113
63
+ el = reg_el;
114
case 0:
64
tcf = extract64(sctlr, 40, 2);
115
/*
116
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
117
118
case 2:
119
/* Tag check fail causes asynchronous flag set. */
120
- if (regime_has_2_ranges(arm_mmu_idx)) {
121
- select = extract64(dirty_ptr, 55, 1);
122
- } else {
123
- select = 0;
124
- }
125
- env->cp15.tfsr_el[el] |= 1 << select;
126
-#ifdef CONFIG_USER_ONLY
127
- /*
128
- * Stand in for a timer irq, setting _TIF_MTE_ASYNC_FAULT,
129
- * which then sends a SIGSEGV when the thread is next scheduled.
130
- * This cpu will return to the main loop at the end of the TB,
131
- * which is rather sooner than "normal". But the alternative
132
- * is waiting until the next syscall.
133
- */
134
- qemu_cpu_kick(env_cpu(env));
135
-#endif
136
+ mte_async_check_fail(env, dirty_ptr, ra, arm_mmu_idx, el);
137
break;
138
139
- default:
140
- /* Case 3: Reserved. */
141
- qemu_log_mask(LOG_GUEST_ERROR,
142
- "Tag check failure with SCTLR_EL%d.TCF%s "
143
- "set to reserved value %d\n",
144
- reg_el, el ? "" : "0", tcf);
145
+ case 3:
146
+ /*
147
+ * Tag check fail causes asynchronous flag set for stores, or
148
+ * a synchronous exception for loads.
149
+ */
150
+ if (FIELD_EX32(desc, MTEDESC, WRITE)) {
151
+ mte_async_check_fail(env, dirty_ptr, ra, arm_mmu_idx, el);
152
+ } else {
153
+ mte_sync_check_fail(env, desc, dirty_ptr, ra);
154
+ }
155
break;
65
}
156
}
66
157
}
67
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
68
env->exception.vaddress = dirty_ptr;
69
70
is_write = FIELD_EX32(desc, MTEDESC, WRITE);
71
- syn = syn_data_abort_no_iss(el != 0, 0, 0, 0, 0, is_write, 0x11);
72
+ syn = syn_data_abort_no_iss(arm_current_el(env) != 0, 0, 0, 0, 0,
73
+ is_write, 0x11);
74
raise_exception(env, EXCP_DATA_ABORT, syn, exception_target_el(env));
75
/* noreturn, but fall through to the assert anyway */
76
77
--
158
--
78
2.20.1
159
2.20.1
79
160
80
161
diff view generated by jsdifflib
1
From: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
1
From: Alexandre Iooss <erdnaxe@crans.org>
2
2
3
Cortex-A53 supports 40bits of address space. sbsa-ref's memory starts
3
This adds the target guide for BBC Micro:bit.
4
above this limit.
5
4
6
Signed-off-by: Marcin Juszkiewicz <marcin.juszkiewicz@linaro.org>
5
Information is taken from https://wiki.qemu.org/Features/MicroBit
6
and from hw/arm/nrf51_soc.c.
7
8
Signed-off-by: Alexandre Iooss <erdnaxe@crans.org>
7
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Acked-by: Leif Lindholm <leif@nuviainc.com>
10
Reviewed-by: Joel Stanley <joel@jms.id.au>
9
Message-id: 20210216150122.3830863-2-marcin.juszkiewicz@linaro.org
11
Message-id: 20210621075625.540471-1-erdnaxe@crans.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
13
---
12
hw/arm/sbsa-ref.c | 1 -
14
docs/system/arm/nrf.rst | 51 ++++++++++++++++++++++++++++++++++++++
13
1 file changed, 1 deletion(-)
15
docs/system/target-arm.rst | 1 +
16
MAINTAINERS | 1 +
17
3 files changed, 53 insertions(+)
18
create mode 100644 docs/system/arm/nrf.rst
14
19
15
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
20
diff --git a/docs/system/arm/nrf.rst b/docs/system/arm/nrf.rst
21
new file mode 100644
22
index XXXXXXX..XXXXXXX
23
--- /dev/null
24
+++ b/docs/system/arm/nrf.rst
25
@@ -XXX,XX +XXX,XX @@
26
+Nordic nRF boards (``microbit``)
27
+================================
28
+
29
+The `Nordic nRF`_ chips are a family of ARM-based System-on-Chip that
30
+are designed to be used for low-power and short-range wireless solutions.
31
+
32
+.. _Nordic nRF: https://www.nordicsemi.com/Products
33
+
34
+The nRF51 series is the first series for short range wireless applications.
35
+It is superseded by the nRF52 series.
36
+The following machines are based on this chip :
37
+
38
+- ``microbit`` BBC micro:bit board with nRF51822 SoC
39
+
40
+There are other series such as nRF52, nRF53 and nRF91 which are currently not
41
+supported by QEMU.
42
+
43
+Supported devices
44
+-----------------
45
+
46
+ * ARM Cortex-M0 (ARMv6-M)
47
+ * Serial ports (UART)
48
+ * Clock controller
49
+ * Timers
50
+ * Random Number Generator (RNG)
51
+ * GPIO controller
52
+ * NVMC
53
+ * SWI
54
+
55
+Missing devices
56
+---------------
57
+
58
+ * Watchdog
59
+ * Real-Time Clock (RTC) controller
60
+ * TWI (i2c)
61
+ * SPI controller
62
+ * Analog to Digital Converter (ADC)
63
+ * Quadrature decoder
64
+ * Radio
65
+
66
+Boot options
67
+------------
68
+
69
+The Micro:bit machine can be started using the ``-device`` option to load a
70
+firmware in `ihex format`_. Example:
71
+
72
+.. _ihex format: https://en.wikipedia.org/wiki/Intel_HEX
73
+
74
+.. code-block:: bash
75
+
76
+ $ qemu-system-arm -M microbit -device loader,file=test.hex
77
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
16
index XXXXXXX..XXXXXXX 100644
78
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/sbsa-ref.c
79
--- a/docs/system/target-arm.rst
18
+++ b/hw/arm/sbsa-ref.c
80
+++ b/docs/system/target-arm.rst
19
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
81
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
20
};
82
arm/digic
21
83
arm/musicpal
22
static const char * const valid_cpus[] = {
84
arm/gumstix
23
- ARM_CPU_TYPE_NAME("cortex-a53"),
85
+ arm/nrf
24
ARM_CPU_TYPE_NAME("cortex-a57"),
86
arm/nseries
25
ARM_CPU_TYPE_NAME("cortex-a72"),
87
arm/nuvoton
26
};
88
arm/orangepi
89
diff --git a/MAINTAINERS b/MAINTAINERS
90
index XXXXXXX..XXXXXXX 100644
91
--- a/MAINTAINERS
92
+++ b/MAINTAINERS
93
@@ -XXX,XX +XXX,XX @@ F: hw/*/microbit*.c
94
F: include/hw/*/nrf51*.h
95
F: include/hw/*/microbit*.h
96
F: tests/qtest/microbit-test.c
97
+F: docs/system/arm/nrf.rst
98
99
AVR Machines
100
-------------
27
--
101
--
28
2.20.1
102
2.20.1
29
103
30
104
diff view generated by jsdifflib