1
First set of arm patches for 6.2. I have a lot more in my
1
The following changes since commit 3db29dcac23da85486704ef9e7a8e7217f7829cd:
2
to-review queue still...
3
2
4
-- PMM
3
Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging (2023-01-12 13:51:36 +0000)
5
6
The following changes since commit d42685765653ec155fdf60910662f8830bdb2cef:
7
8
Open 6.2 development tree (2021-08-25 10:25:12 +0100)
9
4
10
are available in the Git repository at:
5
are available in the Git repository at:
11
6
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210825
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20230113
13
8
14
for you to fetch changes up to 24b1a6aa43615be22c7ee66bd68ec5675f6a6a9a:
9
for you to fetch changes up to 08899b5c68a55a3780d707e2464073c8f2670d31:
15
10
16
docs: Document how to use gdb with unix sockets (2021-08-25 10:48:51 +0100)
11
target/arm: allow writes to SCR_EL3.HXEn bit when FEAT_HCX is enabled (2023-01-13 13:19:36 +0000)
17
12
18
----------------------------------------------------------------
13
----------------------------------------------------------------
19
target-arm queue:
14
target-arm queue:
20
* More MVE emulation work
15
hw/arm/stm32f405: correctly describe the memory layout
21
* Implement M-profile trapping on division by zero
16
hw/arm: Add Olimex H405 board
22
* kvm: use RCU_READ_LOCK_GUARD() in kvm_arch_fixup_msi_route()
17
cubieboard: Support booting from an SD card image with u-boot on it
23
* hw/char/pl011: add support for sending break
18
target/arm: Fix sve_probe_page
24
* fsl-imx6ul: Instantiate SAI1/2/3 and ASRC as unimplemented devices
19
target/arm: allow writes to SCR_EL3.HXEn bit when FEAT_HCX is enabled
25
* hw/dma/pl330: Add memory region to replace default
20
various code cleanups
26
* sbsa-ref: Rename SBSA_GWDT enum value
27
* fsl-imx7: Instantiate SAI1/2/3 as unimplemented devices
28
* docs: Document how to use gdb with unix sockets
29
21
30
----------------------------------------------------------------
22
----------------------------------------------------------------
31
Eduardo Habkost (1):
23
Evgeny Iakovlev (1):
32
sbsa-ref: Rename SBSA_GWDT enum value
24
target/arm: allow writes to SCR_EL3.HXEn bit when FEAT_HCX is enabled
33
25
34
Guenter Roeck (2):
26
Felipe Balbi (2):
35
fsl-imx6ul: Instantiate SAI1/2/3 and ASRC as unimplemented devices
27
hw/arm/stm32f405: correctly describe the memory layout
36
fsl-imx7: Instantiate SAI1/2/3 as unimplemented devices
28
hw/arm: Add Olimex H405
37
29
38
Hamza Mahfooz (1):
30
Philippe Mathieu-Daudé (27):
39
target/arm: kvm: use RCU_READ_LOCK_GUARD() in kvm_arch_fixup_msi_route()
31
hw/arm/pxa2xx: Simplify pxa255_init()
32
hw/arm/pxa2xx: Simplify pxa270_init()
33
hw/arm/collie: Use the IEC binary prefix definitions
34
hw/arm/collie: Simplify flash creation using for() loop
35
hw/arm/gumstix: Improve documentation
36
hw/arm/gumstix: Use the IEC binary prefix definitions
37
hw/arm/mainstone: Use the IEC binary prefix definitions
38
hw/arm/musicpal: Use the IEC binary prefix definitions
39
hw/arm/omap_sx1: Remove unused 'total_ram' definitions
40
hw/arm/omap_sx1: Use the IEC binary prefix definitions
41
hw/arm/z2: Use the IEC binary prefix definitions
42
hw/arm/vexpress: Remove dead code in vexpress_common_init()
43
hw/arm: Remove unreachable code calling pflash_cfi01_register()
44
hw/arm/pxa: Avoid forward-declaring PXA2xxI2CState
45
hw/gpio/omap_gpio: Add local variable to avoid embedded cast
46
hw/arm/omap: Drop useless casts from void * to pointer
47
hw/gpio/omap_gpio: Use CamelCase for TYPE_OMAP1_GPIO type name
48
hw/gpio/omap_gpio: Use CamelCase for TYPE_OMAP2_GPIO type name
49
hw/intc/omap_intc: Use CamelCase for TYPE_OMAP_INTC type name
50
hw/arm/stellaris: Drop useless casts from void * to pointer
51
hw/arm/stellaris: Use CamelCase for STELLARIS_ADC type name
52
hw/arm/bcm2836: Remove definitions generated by OBJECT_DECLARE_TYPE()
53
hw/arm/npcm7xx: Declare QOM macros using OBJECT_DECLARE_SIMPLE_TYPE()
54
hw/misc/sbsa_ec: Rename TYPE_SBSA_EC -> TYPE_SBSA_SECURE_EC
55
hw/misc/sbsa_ec: Declare QOM macros using OBJECT_DECLARE_SIMPLE_TYPE()
56
hw/intc/xilinx_intc: Use 'XpsIntc' typedef instead of 'struct xlx_pic'
57
hw/timer/xilinx_timer: Use XpsTimerState instead of 'struct timerblock'
40
58
41
Jan Luebbe (1):
59
Richard Henderson (1):
42
hw/char/pl011: add support for sending break
60
target/arm: Fix sve_probe_page
43
61
44
Peter Maydell (37):
62
Strahinja Jankovic (7):
45
target/arm: Note that we handle VMOVL as a special case of VSHLL
63
hw/misc: Allwinner-A10 Clock Controller Module Emulation
46
target/arm: Print MVE VPR in CPU dumps
64
hw/misc: Allwinner A10 DRAM Controller Emulation
47
target/arm: Fix MVE VSLI by 0 and VSRI by <dt>
65
{hw/i2c,docs/system/arm}: Allwinner TWI/I2C Emulation
48
target/arm: Fix signed VADDV
66
hw/misc: AXP209 PMU Emulation
49
target/arm: Fix mask handling for MVE narrowing operations
67
hw/arm: Add AXP209 to Cubieboard
50
target/arm: Fix 48-bit saturating shifts
68
hw/arm: Allwinner A10 enable SPL load from MMC
51
target/arm: Fix MVE 48-bit SQRSHRL for small right shifts
69
tests/avocado: Add SD boot test to Cubieboard
52
target/arm: Fix calculation of LTP mask when LR is 0
53
target/arm: Factor out mve_eci_mask()
54
target/arm: Fix VPT advance when ECI is non-zero
55
target/arm: Fix VLDRB/H/W for predicated elements
56
target/arm: Implement MVE VMULL (polynomial)
57
target/arm: Implement MVE incrementing/decrementing dup insns
58
target/arm: Factor out gen_vpst()
59
target/arm: Implement MVE integer vector comparisons
60
target/arm: Implement MVE integer vector-vs-scalar comparisons
61
target/arm: Implement MVE VPSEL
62
target/arm: Implement MVE VMLAS
63
target/arm: Implement MVE shift-by-scalar
64
target/arm: Move 'x' and 'a' bit definitions into vmlaldav formats
65
target/arm: Implement MVE integer min/max across vector
66
target/arm: Implement MVE VABAV
67
target/arm: Implement MVE narrowing moves
68
target/arm: Rename MVEGenDualAccOpFn to MVEGenLongDualAccOpFn
69
target/arm: Implement MVE VMLADAV and VMLSLDAV
70
target/arm: Implement MVE VMLA
71
target/arm: Implement MVE saturating doubling multiply accumulates
72
target/arm: Implement MVE VQABS, VQNEG
73
target/arm: Implement MVE VMAXA, VMINA
74
target/arm: Implement MVE VMOV to/from 2 general-purpose registers
75
target/arm: Implement MVE VPNOT
76
target/arm: Implement MVE VCTP
77
target/arm: Implement MVE scatter-gather insns
78
target/arm: Implement MVE scatter-gather immediate forms
79
target/arm: Implement MVE interleaving loads/stores
80
target/arm: Re-indent sdiv and udiv helpers
81
target/arm: Implement M-profile trapping on division by zero
82
70
83
Sebastian Meyer (1):
71
docs/system/arm/cubieboard.rst | 1 +
84
docs: Document how to use gdb with unix sockets
72
docs/system/arm/orangepi.rst | 1 +
73
docs/system/arm/stm32.rst | 1 +
74
configs/devices/arm-softmmu/default.mak | 1 +
75
include/hw/adc/npcm7xx_adc.h | 7 +-
76
include/hw/arm/allwinner-a10.h | 27 ++
77
include/hw/arm/allwinner-h3.h | 3 +
78
include/hw/arm/npcm7xx.h | 18 +-
79
include/hw/arm/omap.h | 24 +-
80
include/hw/arm/pxa.h | 11 +-
81
include/hw/arm/stm32f405_soc.h | 5 +-
82
include/hw/i2c/allwinner-i2c.h | 55 ++++
83
include/hw/i2c/npcm7xx_smbus.h | 7 +-
84
include/hw/misc/allwinner-a10-ccm.h | 67 +++++
85
include/hw/misc/allwinner-a10-dramc.h | 68 +++++
86
include/hw/misc/npcm7xx_clk.h | 2 +-
87
include/hw/misc/npcm7xx_gcr.h | 6 +-
88
include/hw/misc/npcm7xx_mft.h | 7 +-
89
include/hw/misc/npcm7xx_pwm.h | 3 +-
90
include/hw/misc/npcm7xx_rng.h | 6 +-
91
include/hw/net/npcm7xx_emc.h | 5 +-
92
include/hw/sd/npcm7xx_sdhci.h | 4 +-
93
hw/arm/allwinner-a10.c | 40 +++
94
hw/arm/allwinner-h3.c | 11 +-
95
hw/arm/bcm2836.c | 9 +-
96
hw/arm/collie.c | 25 +-
97
hw/arm/cubieboard.c | 11 +
98
hw/arm/gumstix.c | 45 ++--
99
hw/arm/mainstone.c | 37 ++-
100
hw/arm/musicpal.c | 9 +-
101
hw/arm/olimex-stm32-h405.c | 69 +++++
102
hw/arm/omap1.c | 115 ++++----
103
hw/arm/omap2.c | 40 ++-
104
hw/arm/omap_sx1.c | 53 ++--
105
hw/arm/palm.c | 2 +-
106
hw/arm/pxa2xx.c | 8 +-
107
hw/arm/spitz.c | 6 +-
108
hw/arm/stellaris.c | 73 +++--
109
hw/arm/stm32f405_soc.c | 8 +
110
hw/arm/tosa.c | 2 +-
111
hw/arm/versatilepb.c | 6 +-
112
hw/arm/vexpress.c | 10 +-
113
hw/arm/z2.c | 16 +-
114
hw/char/omap_uart.c | 7 +-
115
hw/display/omap_dss.c | 15 +-
116
hw/display/omap_lcdc.c | 9 +-
117
hw/dma/omap_dma.c | 15 +-
118
hw/gpio/omap_gpio.c | 48 ++--
119
hw/i2c/allwinner-i2c.c | 459 ++++++++++++++++++++++++++++++++
120
hw/intc/omap_intc.c | 38 +--
121
hw/intc/xilinx_intc.c | 28 +-
122
hw/misc/allwinner-a10-ccm.c | 224 ++++++++++++++++
123
hw/misc/allwinner-a10-dramc.c | 179 +++++++++++++
124
hw/misc/axp209.c | 238 +++++++++++++++++
125
hw/misc/omap_gpmc.c | 12 +-
126
hw/misc/omap_l4.c | 7 +-
127
hw/misc/omap_sdrc.c | 7 +-
128
hw/misc/omap_tap.c | 5 +-
129
hw/misc/sbsa_ec.c | 12 +-
130
hw/sd/omap_mmc.c | 9 +-
131
hw/ssi/omap_spi.c | 7 +-
132
hw/timer/omap_gptimer.c | 22 +-
133
hw/timer/omap_synctimer.c | 4 +-
134
hw/timer/xilinx_timer.c | 27 +-
135
target/arm/helper.c | 3 +
136
target/arm/sve_helper.c | 14 +-
137
MAINTAINERS | 8 +
138
hw/arm/Kconfig | 9 +
139
hw/arm/meson.build | 1 +
140
hw/i2c/Kconfig | 4 +
141
hw/i2c/meson.build | 1 +
142
hw/i2c/trace-events | 5 +
143
hw/misc/Kconfig | 10 +
144
hw/misc/meson.build | 3 +
145
hw/misc/trace-events | 5 +
146
tests/avocado/boot_linux_console.py | 47 ++++
147
76 files changed, 1951 insertions(+), 455 deletions(-)
148
create mode 100644 include/hw/i2c/allwinner-i2c.h
149
create mode 100644 include/hw/misc/allwinner-a10-ccm.h
150
create mode 100644 include/hw/misc/allwinner-a10-dramc.h
151
create mode 100644 hw/arm/olimex-stm32-h405.c
152
create mode 100644 hw/i2c/allwinner-i2c.c
153
create mode 100644 hw/misc/allwinner-a10-ccm.c
154
create mode 100644 hw/misc/allwinner-a10-dramc.c
155
create mode 100644 hw/misc/axp209.c
85
156
86
Wen, Jianxian (1):
87
hw/dma/pl330: Add memory region to replace default
88
89
docs/system/gdb.rst | 26 +-
90
include/hw/arm/fsl-imx7.h | 5 +
91
target/arm/cpu.h | 1 +
92
target/arm/helper-mve.h | 283 ++++++++++
93
target/arm/helper.h | 4 +-
94
target/arm/translate-a32.h | 2 +
95
target/arm/vec_internal.h | 11 +
96
target/arm/mve.decode | 226 +++++++-
97
target/arm/t32.decode | 1 +
98
hw/arm/exynos4210.c | 3 +
99
hw/arm/fsl-imx6ul.c | 12 +
100
hw/arm/fsl-imx7.c | 7 +
101
hw/arm/sbsa-ref.c | 6 +-
102
hw/arm/xilinx_zynq.c | 3 +
103
hw/char/pl011.c | 6 +
104
hw/dma/pl330.c | 26 +-
105
target/arm/cpu.c | 3 +
106
target/arm/helper.c | 34 +-
107
target/arm/kvm.c | 17 +-
108
target/arm/m_helper.c | 4 +
109
target/arm/mve_helper.c | 1254 ++++++++++++++++++++++++++++++++++++++++++--
110
target/arm/translate-mve.c | 877 ++++++++++++++++++++++++++++++-
111
target/arm/translate-vfp.c | 2 +-
112
target/arm/translate.c | 37 +-
113
target/arm/vec_helper.c | 14 +-
114
25 files changed, 2746 insertions(+), 118 deletions(-)
115
diff view generated by jsdifflib
1
Implement the MVE interleaving load/store functions VLD2, VLD4, VST2
1
From: Felipe Balbi <balbi@kernel.org>
2
and VST4. VLD2 loads 16 bytes of data from memory and writes to 2
3
consecutive Qregs; VLD4 loads 16 bytes of data from memory and writes
4
to 4 consecutive Qregs. The 'pattern' field in the encoding
5
determines the offset into memory which is accessed and also which
6
elements in the Qregs are written to. (The intention is that a
7
sequence of four consecutive VLD4 with different pattern values
8
performs a complete de-interleaving load of 64 bytes into all
9
elements of the 4 Qregs.) VST2 and VST4 do the same, but for stores.
10
2
3
STM32F405 has 128K of SRAM and another 64K of CCM (Core-coupled
4
Memory) at a different base address. Correctly describe the memory
5
layout to give existing FW images a chance to run unmodified.
6
7
Reviewed-by: Alistair Francis <alistair@alistair23.me>
8
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
9
Signed-off-by: Felipe Balbi <balbi@kernel.org>
10
Message-id: 20221230145733.200496-2-balbi@kernel.org
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
---
12
---
14
target/arm/helper-mve.h | 48 ++++++
13
include/hw/arm/stm32f405_soc.h | 5 ++++-
15
target/arm/mve.decode | 11 ++
14
hw/arm/stm32f405_soc.c | 8 ++++++++
16
target/arm/mve_helper.c | 342 +++++++++++++++++++++++++++++++++++++
15
2 files changed, 12 insertions(+), 1 deletion(-)
17
target/arm/translate-mve.c | 94 ++++++++++
18
4 files changed, 495 insertions(+)
19
16
20
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
17
diff --git a/include/hw/arm/stm32f405_soc.h b/include/hw/arm/stm32f405_soc.h
21
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/helper-mve.h
19
--- a/include/hw/arm/stm32f405_soc.h
23
+++ b/target/arm/helper-mve.h
20
+++ b/include/hw/arm/stm32f405_soc.h
24
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vldrd_sg_wb_ud, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
21
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(STM32F405State, STM32F405_SOC)
25
DEF_HELPER_FLAGS_4(mve_vstrw_sg_wb_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
22
#define FLASH_BASE_ADDRESS 0x08000000
26
DEF_HELPER_FLAGS_4(mve_vstrd_sg_wb_ud, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
23
#define FLASH_SIZE (1024 * 1024)
27
24
#define SRAM_BASE_ADDRESS 0x20000000
28
+DEF_HELPER_FLAGS_3(mve_vld20b, TCG_CALL_NO_WG, void, env, i32, i32)
25
-#define SRAM_SIZE (192 * 1024)
29
+DEF_HELPER_FLAGS_3(mve_vld20h, TCG_CALL_NO_WG, void, env, i32, i32)
26
+#define SRAM_SIZE (128 * 1024)
30
+DEF_HELPER_FLAGS_3(mve_vld20w, TCG_CALL_NO_WG, void, env, i32, i32)
27
+#define CCM_BASE_ADDRESS 0x10000000
28
+#define CCM_SIZE (64 * 1024)
29
30
struct STM32F405State {
31
/*< private >*/
32
@@ -XXX,XX +XXX,XX @@ struct STM32F405State {
33
STM32F2XXADCState adc[STM_NUM_ADCS];
34
STM32F2XXSPIState spi[STM_NUM_SPIS];
35
36
+ MemoryRegion ccm;
37
MemoryRegion sram;
38
MemoryRegion flash;
39
MemoryRegion flash_alias;
40
diff --git a/hw/arm/stm32f405_soc.c b/hw/arm/stm32f405_soc.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/hw/arm/stm32f405_soc.c
43
+++ b/hw/arm/stm32f405_soc.c
44
@@ -XXX,XX +XXX,XX @@ static void stm32f405_soc_realize(DeviceState *dev_soc, Error **errp)
45
}
46
memory_region_add_subregion(system_memory, SRAM_BASE_ADDRESS, &s->sram);
47
48
+ memory_region_init_ram(&s->ccm, NULL, "STM32F405.ccm", CCM_SIZE,
49
+ &err);
50
+ if (err != NULL) {
51
+ error_propagate(errp, err);
52
+ return;
53
+ }
54
+ memory_region_add_subregion(system_memory, CCM_BASE_ADDRESS, &s->ccm);
31
+
55
+
32
+DEF_HELPER_FLAGS_3(mve_vld21b, TCG_CALL_NO_WG, void, env, i32, i32)
56
armv7m = DEVICE(&s->armv7m);
33
+DEF_HELPER_FLAGS_3(mve_vld21h, TCG_CALL_NO_WG, void, env, i32, i32)
57
qdev_prop_set_uint32(armv7m, "num-irq", 96);
34
+DEF_HELPER_FLAGS_3(mve_vld21w, TCG_CALL_NO_WG, void, env, i32, i32)
58
qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
35
+
36
+DEF_HELPER_FLAGS_3(mve_vld40b, TCG_CALL_NO_WG, void, env, i32, i32)
37
+DEF_HELPER_FLAGS_3(mve_vld40h, TCG_CALL_NO_WG, void, env, i32, i32)
38
+DEF_HELPER_FLAGS_3(mve_vld40w, TCG_CALL_NO_WG, void, env, i32, i32)
39
+
40
+DEF_HELPER_FLAGS_3(mve_vld41b, TCG_CALL_NO_WG, void, env, i32, i32)
41
+DEF_HELPER_FLAGS_3(mve_vld41h, TCG_CALL_NO_WG, void, env, i32, i32)
42
+DEF_HELPER_FLAGS_3(mve_vld41w, TCG_CALL_NO_WG, void, env, i32, i32)
43
+
44
+DEF_HELPER_FLAGS_3(mve_vld42b, TCG_CALL_NO_WG, void, env, i32, i32)
45
+DEF_HELPER_FLAGS_3(mve_vld42h, TCG_CALL_NO_WG, void, env, i32, i32)
46
+DEF_HELPER_FLAGS_3(mve_vld42w, TCG_CALL_NO_WG, void, env, i32, i32)
47
+
48
+DEF_HELPER_FLAGS_3(mve_vld43b, TCG_CALL_NO_WG, void, env, i32, i32)
49
+DEF_HELPER_FLAGS_3(mve_vld43h, TCG_CALL_NO_WG, void, env, i32, i32)
50
+DEF_HELPER_FLAGS_3(mve_vld43w, TCG_CALL_NO_WG, void, env, i32, i32)
51
+
52
+DEF_HELPER_FLAGS_3(mve_vst20b, TCG_CALL_NO_WG, void, env, i32, i32)
53
+DEF_HELPER_FLAGS_3(mve_vst20h, TCG_CALL_NO_WG, void, env, i32, i32)
54
+DEF_HELPER_FLAGS_3(mve_vst20w, TCG_CALL_NO_WG, void, env, i32, i32)
55
+
56
+DEF_HELPER_FLAGS_3(mve_vst21b, TCG_CALL_NO_WG, void, env, i32, i32)
57
+DEF_HELPER_FLAGS_3(mve_vst21h, TCG_CALL_NO_WG, void, env, i32, i32)
58
+DEF_HELPER_FLAGS_3(mve_vst21w, TCG_CALL_NO_WG, void, env, i32, i32)
59
+
60
+DEF_HELPER_FLAGS_3(mve_vst40b, TCG_CALL_NO_WG, void, env, i32, i32)
61
+DEF_HELPER_FLAGS_3(mve_vst40h, TCG_CALL_NO_WG, void, env, i32, i32)
62
+DEF_HELPER_FLAGS_3(mve_vst40w, TCG_CALL_NO_WG, void, env, i32, i32)
63
+
64
+DEF_HELPER_FLAGS_3(mve_vst41b, TCG_CALL_NO_WG, void, env, i32, i32)
65
+DEF_HELPER_FLAGS_3(mve_vst41h, TCG_CALL_NO_WG, void, env, i32, i32)
66
+DEF_HELPER_FLAGS_3(mve_vst41w, TCG_CALL_NO_WG, void, env, i32, i32)
67
+
68
+DEF_HELPER_FLAGS_3(mve_vst42b, TCG_CALL_NO_WG, void, env, i32, i32)
69
+DEF_HELPER_FLAGS_3(mve_vst42h, TCG_CALL_NO_WG, void, env, i32, i32)
70
+DEF_HELPER_FLAGS_3(mve_vst42w, TCG_CALL_NO_WG, void, env, i32, i32)
71
+
72
+DEF_HELPER_FLAGS_3(mve_vst43b, TCG_CALL_NO_WG, void, env, i32, i32)
73
+DEF_HELPER_FLAGS_3(mve_vst43h, TCG_CALL_NO_WG, void, env, i32, i32)
74
+DEF_HELPER_FLAGS_3(mve_vst43w, TCG_CALL_NO_WG, void, env, i32, i32)
75
+
76
DEF_HELPER_FLAGS_3(mve_vdup, TCG_CALL_NO_WG, void, env, ptr, i32)
77
78
DEF_HELPER_FLAGS_4(mve_vidupb, TCG_CALL_NO_WG, i32, env, ptr, i32, i32)
79
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
80
index XXXXXXX..XXXXXXX 100644
81
--- a/target/arm/mve.decode
82
+++ b/target/arm/mve.decode
83
@@ -XXX,XX +XXX,XX @@
84
&vabav qn qm rda size
85
&vldst_sg qd qm rn size msize os
86
&vldst_sg_imm qd qm a w imm
87
+&vldst_il qd rn size pat w
88
89
# scatter-gather memory size is in bits 6:4
90
%sg_msize 6:1 4:1
91
@@ -XXX,XX +XXX,XX @@
92
@vldst_sg_imm .... .... a:1 . w:1 . .... .... .... . imm:7 &vldst_sg_imm \
93
qd=%qd qm=%qn
94
95
+# Deinterleaving load/interleaving store
96
+@vldst_il .... .... .. w:1 . rn:4 .... ... size:2 pat:2 ..... &vldst_il \
97
+ qd=%qd
98
+
99
@1op .... .... .... size:2 .. .... .... .... .... &1op qd=%qd qm=%qm
100
@1op_nosz .... .... .... .... .... .... .... .... &1op qd=%qd qm=%qm size=0
101
@2op .... .... .. size:2 .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn
102
@@ -XXX,XX +XXX,XX @@ VLDRD_sg_imm 111 1 1101 ... 1 ... 0 ... 1 1111 .... .... @vldst_sg_imm
103
VSTRW_sg_imm 111 1 1101 ... 0 ... 0 ... 1 1110 .... .... @vldst_sg_imm
104
VSTRD_sg_imm 111 1 1101 ... 0 ... 0 ... 1 1111 .... .... @vldst_sg_imm
105
106
+# deinterleaving loads/interleaving stores
107
+VLD2 1111 1100 1 .. 1 .... ... 1 111 .. .. 00000 @vldst_il
108
+VLD4 1111 1100 1 .. 1 .... ... 1 111 .. .. 00001 @vldst_il
109
+VST2 1111 1100 1 .. 0 .... ... 1 111 .. .. 00000 @vldst_il
110
+VST4 1111 1100 1 .. 0 .... ... 1 111 .. .. 00001 @vldst_il
111
+
112
# Moves between 2 32-bit vector lanes and 2 general purpose registers
113
VMOV_to_2gp 1110 1100 0 . 00 rt2:4 ... 0 1111 000 idx:1 rt:4 qd=%qd
114
VMOV_from_2gp 1110 1100 0 . 01 rt2:4 ... 0 1111 000 idx:1 rt:4 qd=%qd
115
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
116
index XXXXXXX..XXXXXXX 100644
117
--- a/target/arm/mve_helper.c
118
+++ b/target/arm/mve_helper.c
119
@@ -XXX,XX +XXX,XX @@ DO_VLDR64_SG(vldrd_sg_wb_ud, ADDR_ADD, true)
120
DO_VSTR_SG(vstrw_sg_wb_uw, stl, 4, uint32_t, ADDR_ADD, true)
121
DO_VSTR64_SG(vstrd_sg_wb_ud, ADDR_ADD, true)
122
123
+/*
124
+ * Deinterleaving loads/interleaving stores.
125
+ *
126
+ * For these helpers we are passed the index of the first Qreg
127
+ * (VLD2/VST2 will also access Qn+1, VLD4/VST4 access Qn .. Qn+3)
128
+ * and the value of the base address register Rn.
129
+ * The helpers are specialized for pattern and element size, so
130
+ * for instance vld42h is VLD4 with pattern 2, element size MO_16.
131
+ *
132
+ * These insns are beatwise but not predicated, so we must honour ECI,
133
+ * but need not look at mve_element_mask().
134
+ *
135
+ * The pseudocode implements these insns with multiple memory accesses
136
+ * of the element size, but rules R_VVVG and R_FXDM permit us to make
137
+ * one 32-bit memory access per beat.
138
+ */
139
+#define DO_VLD4B(OP, O1, O2, O3, O4) \
140
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
141
+ uint32_t base) \
142
+ { \
143
+ int beat, e; \
144
+ uint16_t mask = mve_eci_mask(env); \
145
+ static const uint8_t off[4] = { O1, O2, O3, O4 }; \
146
+ uint32_t addr, data; \
147
+ for (beat = 0; beat < 4; beat++, mask >>= 4) { \
148
+ if ((mask & 1) == 0) { \
149
+ /* ECI says skip this beat */ \
150
+ continue; \
151
+ } \
152
+ addr = base + off[beat] * 4; \
153
+ data = cpu_ldl_le_data_ra(env, addr, GETPC()); \
154
+ for (e = 0; e < 4; e++, data >>= 8) { \
155
+ uint8_t *qd = (uint8_t *)aa32_vfp_qreg(env, qnidx + e); \
156
+ qd[H1(off[beat])] = data; \
157
+ } \
158
+ } \
159
+ }
160
+
161
+#define DO_VLD4H(OP, O1, O2) \
162
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
163
+ uint32_t base) \
164
+ { \
165
+ int beat; \
166
+ uint16_t mask = mve_eci_mask(env); \
167
+ static const uint8_t off[4] = { O1, O1, O2, O2 }; \
168
+ uint32_t addr, data; \
169
+ int y; /* y counts 0 2 0 2 */ \
170
+ uint16_t *qd; \
171
+ for (beat = 0, y = 0; beat < 4; beat++, mask >>= 4, y ^= 2) { \
172
+ if ((mask & 1) == 0) { \
173
+ /* ECI says skip this beat */ \
174
+ continue; \
175
+ } \
176
+ addr = base + off[beat] * 8 + (beat & 1) * 4; \
177
+ data = cpu_ldl_le_data_ra(env, addr, GETPC()); \
178
+ qd = (uint16_t *)aa32_vfp_qreg(env, qnidx + y); \
179
+ qd[H2(off[beat])] = data; \
180
+ data >>= 16; \
181
+ qd = (uint16_t *)aa32_vfp_qreg(env, qnidx + y + 1); \
182
+ qd[H2(off[beat])] = data; \
183
+ } \
184
+ }
185
+
186
+#define DO_VLD4W(OP, O1, O2, O3, O4) \
187
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
188
+ uint32_t base) \
189
+ { \
190
+ int beat; \
191
+ uint16_t mask = mve_eci_mask(env); \
192
+ static const uint8_t off[4] = { O1, O2, O3, O4 }; \
193
+ uint32_t addr, data; \
194
+ uint32_t *qd; \
195
+ int y; \
196
+ for (beat = 0; beat < 4; beat++, mask >>= 4) { \
197
+ if ((mask & 1) == 0) { \
198
+ /* ECI says skip this beat */ \
199
+ continue; \
200
+ } \
201
+ addr = base + off[beat] * 4; \
202
+ data = cpu_ldl_le_data_ra(env, addr, GETPC()); \
203
+ y = (beat + (O1 & 2)) & 3; \
204
+ qd = (uint32_t *)aa32_vfp_qreg(env, qnidx + y); \
205
+ qd[H4(off[beat] >> 2)] = data; \
206
+ } \
207
+ }
208
+
209
+DO_VLD4B(vld40b, 0, 1, 10, 11)
210
+DO_VLD4B(vld41b, 2, 3, 12, 13)
211
+DO_VLD4B(vld42b, 4, 5, 14, 15)
212
+DO_VLD4B(vld43b, 6, 7, 8, 9)
213
+
214
+DO_VLD4H(vld40h, 0, 5)
215
+DO_VLD4H(vld41h, 1, 6)
216
+DO_VLD4H(vld42h, 2, 7)
217
+DO_VLD4H(vld43h, 3, 4)
218
+
219
+DO_VLD4W(vld40w, 0, 1, 10, 11)
220
+DO_VLD4W(vld41w, 2, 3, 12, 13)
221
+DO_VLD4W(vld42w, 4, 5, 14, 15)
222
+DO_VLD4W(vld43w, 6, 7, 8, 9)
223
+
224
+#define DO_VLD2B(OP, O1, O2, O3, O4) \
225
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
226
+ uint32_t base) \
227
+ { \
228
+ int beat, e; \
229
+ uint16_t mask = mve_eci_mask(env); \
230
+ static const uint8_t off[4] = { O1, O2, O3, O4 }; \
231
+ uint32_t addr, data; \
232
+ uint8_t *qd; \
233
+ for (beat = 0; beat < 4; beat++, mask >>= 4) { \
234
+ if ((mask & 1) == 0) { \
235
+ /* ECI says skip this beat */ \
236
+ continue; \
237
+ } \
238
+ addr = base + off[beat] * 2; \
239
+ data = cpu_ldl_le_data_ra(env, addr, GETPC()); \
240
+ for (e = 0; e < 4; e++, data >>= 8) { \
241
+ qd = (uint8_t *)aa32_vfp_qreg(env, qnidx + (e & 1)); \
242
+ qd[H1(off[beat] + (e >> 1))] = data; \
243
+ } \
244
+ } \
245
+ }
246
+
247
+#define DO_VLD2H(OP, O1, O2, O3, O4) \
248
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
249
+ uint32_t base) \
250
+ { \
251
+ int beat; \
252
+ uint16_t mask = mve_eci_mask(env); \
253
+ static const uint8_t off[4] = { O1, O2, O3, O4 }; \
254
+ uint32_t addr, data; \
255
+ int e; \
256
+ uint16_t *qd; \
257
+ for (beat = 0; beat < 4; beat++, mask >>= 4) { \
258
+ if ((mask & 1) == 0) { \
259
+ /* ECI says skip this beat */ \
260
+ continue; \
261
+ } \
262
+ addr = base + off[beat] * 4; \
263
+ data = cpu_ldl_le_data_ra(env, addr, GETPC()); \
264
+ for (e = 0; e < 2; e++, data >>= 16) { \
265
+ qd = (uint16_t *)aa32_vfp_qreg(env, qnidx + e); \
266
+ qd[H2(off[beat])] = data; \
267
+ } \
268
+ } \
269
+ }
270
+
271
+#define DO_VLD2W(OP, O1, O2, O3, O4) \
272
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
273
+ uint32_t base) \
274
+ { \
275
+ int beat; \
276
+ uint16_t mask = mve_eci_mask(env); \
277
+ static const uint8_t off[4] = { O1, O2, O3, O4 }; \
278
+ uint32_t addr, data; \
279
+ uint32_t *qd; \
280
+ for (beat = 0; beat < 4; beat++, mask >>= 4) { \
281
+ if ((mask & 1) == 0) { \
282
+ /* ECI says skip this beat */ \
283
+ continue; \
284
+ } \
285
+ addr = base + off[beat]; \
286
+ data = cpu_ldl_le_data_ra(env, addr, GETPC()); \
287
+ qd = (uint32_t *)aa32_vfp_qreg(env, qnidx + (beat & 1)); \
288
+ qd[H4(off[beat] >> 3)] = data; \
289
+ } \
290
+ }
291
+
292
+DO_VLD2B(vld20b, 0, 2, 12, 14)
293
+DO_VLD2B(vld21b, 4, 6, 8, 10)
294
+
295
+DO_VLD2H(vld20h, 0, 1, 6, 7)
296
+DO_VLD2H(vld21h, 2, 3, 4, 5)
297
+
298
+DO_VLD2W(vld20w, 0, 4, 24, 28)
299
+DO_VLD2W(vld21w, 8, 12, 16, 20)
300
+
301
+#define DO_VST4B(OP, O1, O2, O3, O4) \
302
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
303
+ uint32_t base) \
304
+ { \
305
+ int beat, e; \
306
+ uint16_t mask = mve_eci_mask(env); \
307
+ static const uint8_t off[4] = { O1, O2, O3, O4 }; \
308
+ uint32_t addr, data; \
309
+ for (beat = 0; beat < 4; beat++, mask >>= 4) { \
310
+ if ((mask & 1) == 0) { \
311
+ /* ECI says skip this beat */ \
312
+ continue; \
313
+ } \
314
+ addr = base + off[beat] * 4; \
315
+ data = 0; \
316
+ for (e = 3; e >= 0; e--) { \
317
+ uint8_t *qd = (uint8_t *)aa32_vfp_qreg(env, qnidx + e); \
318
+ data = (data << 8) | qd[H1(off[beat])]; \
319
+ } \
320
+ cpu_stl_le_data_ra(env, addr, data, GETPC()); \
321
+ } \
322
+ }
323
+
324
+#define DO_VST4H(OP, O1, O2) \
325
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
326
+ uint32_t base) \
327
+ { \
328
+ int beat; \
329
+ uint16_t mask = mve_eci_mask(env); \
330
+ static const uint8_t off[4] = { O1, O1, O2, O2 }; \
331
+ uint32_t addr, data; \
332
+ int y; /* y counts 0 2 0 2 */ \
333
+ uint16_t *qd; \
334
+ for (beat = 0, y = 0; beat < 4; beat++, mask >>= 4, y ^= 2) { \
335
+ if ((mask & 1) == 0) { \
336
+ /* ECI says skip this beat */ \
337
+ continue; \
338
+ } \
339
+ addr = base + off[beat] * 8 + (beat & 1) * 4; \
340
+ qd = (uint16_t *)aa32_vfp_qreg(env, qnidx + y); \
341
+ data = qd[H2(off[beat])]; \
342
+ qd = (uint16_t *)aa32_vfp_qreg(env, qnidx + y + 1); \
343
+ data |= qd[H2(off[beat])] << 16; \
344
+ cpu_stl_le_data_ra(env, addr, data, GETPC()); \
345
+ } \
346
+ }
347
+
348
+#define DO_VST4W(OP, O1, O2, O3, O4) \
349
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
350
+ uint32_t base) \
351
+ { \
352
+ int beat; \
353
+ uint16_t mask = mve_eci_mask(env); \
354
+ static const uint8_t off[4] = { O1, O2, O3, O4 }; \
355
+ uint32_t addr, data; \
356
+ uint32_t *qd; \
357
+ int y; \
358
+ for (beat = 0; beat < 4; beat++, mask >>= 4) { \
359
+ if ((mask & 1) == 0) { \
360
+ /* ECI says skip this beat */ \
361
+ continue; \
362
+ } \
363
+ addr = base + off[beat] * 4; \
364
+ y = (beat + (O1 & 2)) & 3; \
365
+ qd = (uint32_t *)aa32_vfp_qreg(env, qnidx + y); \
366
+ data = qd[H4(off[beat] >> 2)]; \
367
+ cpu_stl_le_data_ra(env, addr, data, GETPC()); \
368
+ } \
369
+ }
370
+
371
+DO_VST4B(vst40b, 0, 1, 10, 11)
372
+DO_VST4B(vst41b, 2, 3, 12, 13)
373
+DO_VST4B(vst42b, 4, 5, 14, 15)
374
+DO_VST4B(vst43b, 6, 7, 8, 9)
375
+
376
+DO_VST4H(vst40h, 0, 5)
377
+DO_VST4H(vst41h, 1, 6)
378
+DO_VST4H(vst42h, 2, 7)
379
+DO_VST4H(vst43h, 3, 4)
380
+
381
+DO_VST4W(vst40w, 0, 1, 10, 11)
382
+DO_VST4W(vst41w, 2, 3, 12, 13)
383
+DO_VST4W(vst42w, 4, 5, 14, 15)
384
+DO_VST4W(vst43w, 6, 7, 8, 9)
385
+
386
+#define DO_VST2B(OP, O1, O2, O3, O4) \
387
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
388
+ uint32_t base) \
389
+ { \
390
+ int beat, e; \
391
+ uint16_t mask = mve_eci_mask(env); \
392
+ static const uint8_t off[4] = { O1, O2, O3, O4 }; \
393
+ uint32_t addr, data; \
394
+ uint8_t *qd; \
395
+ for (beat = 0; beat < 4; beat++, mask >>= 4) { \
396
+ if ((mask & 1) == 0) { \
397
+ /* ECI says skip this beat */ \
398
+ continue; \
399
+ } \
400
+ addr = base + off[beat] * 2; \
401
+ data = 0; \
402
+ for (e = 3; e >= 0; e--) { \
403
+ qd = (uint8_t *)aa32_vfp_qreg(env, qnidx + (e & 1)); \
404
+ data = (data << 8) | qd[H1(off[beat] + (e >> 1))]; \
405
+ } \
406
+ cpu_stl_le_data_ra(env, addr, data, GETPC()); \
407
+ } \
408
+ }
409
+
410
+#define DO_VST2H(OP, O1, O2, O3, O4) \
411
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
412
+ uint32_t base) \
413
+ { \
414
+ int beat; \
415
+ uint16_t mask = mve_eci_mask(env); \
416
+ static const uint8_t off[4] = { O1, O2, O3, O4 }; \
417
+ uint32_t addr, data; \
418
+ int e; \
419
+ uint16_t *qd; \
420
+ for (beat = 0; beat < 4; beat++, mask >>= 4) { \
421
+ if ((mask & 1) == 0) { \
422
+ /* ECI says skip this beat */ \
423
+ continue; \
424
+ } \
425
+ addr = base + off[beat] * 4; \
426
+ data = 0; \
427
+ for (e = 1; e >= 0; e--) { \
428
+ qd = (uint16_t *)aa32_vfp_qreg(env, qnidx + e); \
429
+ data = (data << 16) | qd[H2(off[beat])]; \
430
+ } \
431
+ cpu_stl_le_data_ra(env, addr, data, GETPC()); \
432
+ } \
433
+ }
434
+
435
+#define DO_VST2W(OP, O1, O2, O3, O4) \
436
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
437
+ uint32_t base) \
438
+ { \
439
+ int beat; \
440
+ uint16_t mask = mve_eci_mask(env); \
441
+ static const uint8_t off[4] = { O1, O2, O3, O4 }; \
442
+ uint32_t addr, data; \
443
+ uint32_t *qd; \
444
+ for (beat = 0; beat < 4; beat++, mask >>= 4) { \
445
+ if ((mask & 1) == 0) { \
446
+ /* ECI says skip this beat */ \
447
+ continue; \
448
+ } \
449
+ addr = base + off[beat]; \
450
+ qd = (uint32_t *)aa32_vfp_qreg(env, qnidx + (beat & 1)); \
451
+ data = qd[H4(off[beat] >> 3)]; \
452
+ cpu_stl_le_data_ra(env, addr, data, GETPC()); \
453
+ } \
454
+ }
455
+
456
+DO_VST2B(vst20b, 0, 2, 12, 14)
457
+DO_VST2B(vst21b, 4, 6, 8, 10)
458
+
459
+DO_VST2H(vst20h, 0, 1, 6, 7)
460
+DO_VST2H(vst21h, 2, 3, 4, 5)
461
+
462
+DO_VST2W(vst20w, 0, 4, 24, 28)
463
+DO_VST2W(vst21w, 8, 12, 16, 20)
464
+
465
/*
466
* The mergemask(D, R, M) macro performs the operation "*D = R" but
467
* storing only the bytes which correspond to 1 bits in M,
468
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
469
index XXXXXXX..XXXXXXX 100644
470
--- a/target/arm/translate-mve.c
471
+++ b/target/arm/translate-mve.c
472
@@ -XXX,XX +XXX,XX @@ static inline int vidup_imm(DisasContext *s, int x)
473
474
typedef void MVEGenLdStFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
475
typedef void MVEGenLdStSGFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
476
+typedef void MVEGenLdStIlFn(TCGv_ptr, TCGv_i32, TCGv_i32);
477
typedef void MVEGenOneOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
478
typedef void MVEGenTwoOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr);
479
typedef void MVEGenTwoOpScalarFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
480
@@ -XXX,XX +XXX,XX @@ static bool trans_VSTRD_sg_imm(DisasContext *s, arg_vldst_sg_imm *a)
481
return do_ldst_sg_imm(s, a, fns[a->w], MO_64);
482
}
483
484
+static bool do_vldst_il(DisasContext *s, arg_vldst_il *a, MVEGenLdStIlFn *fn,
485
+ int addrinc)
486
+{
487
+ TCGv_i32 rn;
488
+
489
+ if (!dc_isar_feature(aa32_mve, s) ||
490
+ !mve_check_qreg_bank(s, a->qd) ||
491
+ !fn || (a->rn == 13 && a->w) || a->rn == 15) {
492
+ /* Variously UNPREDICTABLE or UNDEF or related-encoding */
493
+ return false;
494
+ }
495
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
496
+ return true;
497
+ }
498
+
499
+ rn = load_reg(s, a->rn);
500
+ /*
501
+ * We pass the index of Qd, not a pointer, because the helper must
502
+ * access multiple Q registers starting at Qd and working up.
503
+ */
504
+ fn(cpu_env, tcg_constant_i32(a->qd), rn);
505
+
506
+ if (a->w) {
507
+ tcg_gen_addi_i32(rn, rn, addrinc);
508
+ store_reg(s, a->rn, rn);
509
+ } else {
510
+ tcg_temp_free_i32(rn);
511
+ }
512
+ mve_update_and_store_eci(s);
513
+ return true;
514
+}
515
+
516
+/* This macro is just to make the arrays more compact in these functions */
517
+#define F(N) gen_helper_mve_##N
518
+
519
+static bool trans_VLD2(DisasContext *s, arg_vldst_il *a)
520
+{
521
+ static MVEGenLdStIlFn * const fns[4][4] = {
522
+ { F(vld20b), F(vld20h), F(vld20w), NULL, },
523
+ { F(vld21b), F(vld21h), F(vld21w), NULL, },
524
+ { NULL, NULL, NULL, NULL },
525
+ { NULL, NULL, NULL, NULL },
526
+ };
527
+ if (a->qd > 6) {
528
+ return false;
529
+ }
530
+ return do_vldst_il(s, a, fns[a->pat][a->size], 32);
531
+}
532
+
533
+static bool trans_VLD4(DisasContext *s, arg_vldst_il *a)
534
+{
535
+ static MVEGenLdStIlFn * const fns[4][4] = {
536
+ { F(vld40b), F(vld40h), F(vld40w), NULL, },
537
+ { F(vld41b), F(vld41h), F(vld41w), NULL, },
538
+ { F(vld42b), F(vld42h), F(vld42w), NULL, },
539
+ { F(vld43b), F(vld43h), F(vld43w), NULL, },
540
+ };
541
+ if (a->qd > 4) {
542
+ return false;
543
+ }
544
+ return do_vldst_il(s, a, fns[a->pat][a->size], 64);
545
+}
546
+
547
+static bool trans_VST2(DisasContext *s, arg_vldst_il *a)
548
+{
549
+ static MVEGenLdStIlFn * const fns[4][4] = {
550
+ { F(vst20b), F(vst20h), F(vst20w), NULL, },
551
+ { F(vst21b), F(vst21h), F(vst21w), NULL, },
552
+ { NULL, NULL, NULL, NULL },
553
+ { NULL, NULL, NULL, NULL },
554
+ };
555
+ if (a->qd > 6) {
556
+ return false;
557
+ }
558
+ return do_vldst_il(s, a, fns[a->pat][a->size], 32);
559
+}
560
+
561
+static bool trans_VST4(DisasContext *s, arg_vldst_il *a)
562
+{
563
+ static MVEGenLdStIlFn * const fns[4][4] = {
564
+ { F(vst40b), F(vst40h), F(vst40w), NULL, },
565
+ { F(vst41b), F(vst41h), F(vst41w), NULL, },
566
+ { F(vst42b), F(vst42h), F(vst42w), NULL, },
567
+ { F(vst43b), F(vst43h), F(vst43w), NULL, },
568
+ };
569
+ if (a->qd > 4) {
570
+ return false;
571
+ }
572
+ return do_vldst_il(s, a, fns[a->pat][a->size], 64);
573
+}
574
+
575
+#undef F
576
+
577
static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
578
{
579
TCGv_ptr qd;
580
--
59
--
581
2.20.1
60
2.34.1
582
61
583
62
diff view generated by jsdifflib
1
Implement the MVE gather-loads and scatter-stores which
1
From: Felipe Balbi <balbi@kernel.org>
2
form the address by adding a base value from a scalar
3
register to an offset in each element of a vector.
4
2
3
Olimex makes a series of low-cost STM32 boards. This commit introduces
4
the minimum setup to support SMT32-H405. See [1] for details
5
6
[1] https://www.olimex.com/Products/ARM/ST/STM32-H405/
7
8
Signed-off-by: Felipe Balbi <balbi@kernel.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Message-id: 20221230145733.200496-3-balbi@kernel.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
---
13
---
8
target/arm/helper-mve.h | 32 +++++++++
14
docs/system/arm/stm32.rst | 1 +
9
target/arm/mve.decode | 12 ++++
15
configs/devices/arm-softmmu/default.mak | 1 +
10
target/arm/mve_helper.c | 129 +++++++++++++++++++++++++++++++++++++
16
hw/arm/olimex-stm32-h405.c | 69 +++++++++++++++++++++++++
11
target/arm/translate-mve.c | 97 ++++++++++++++++++++++++++++
17
MAINTAINERS | 6 +++
12
4 files changed, 270 insertions(+)
18
hw/arm/Kconfig | 4 ++
19
hw/arm/meson.build | 1 +
20
6 files changed, 82 insertions(+)
21
create mode 100644 hw/arm/olimex-stm32-h405.c
13
22
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
23
diff --git a/docs/system/arm/stm32.rst b/docs/system/arm/stm32.rst
15
index XXXXXXX..XXXXXXX 100644
24
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-mve.h
25
--- a/docs/system/arm/stm32.rst
17
+++ b/target/arm/helper-mve.h
26
+++ b/docs/system/arm/stm32.rst
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vstrb_h, TCG_CALL_NO_WG, void, env, ptr, i32)
27
@@ -XXX,XX +XXX,XX @@ The STM32F4 series is based on ARM Cortex-M4F core. This series is pin-to-pin
19
DEF_HELPER_FLAGS_3(mve_vstrb_w, TCG_CALL_NO_WG, void, env, ptr, i32)
28
compatible with STM32F2 series. The following machines are based on this chip :
20
DEF_HELPER_FLAGS_3(mve_vstrh_w, TCG_CALL_NO_WG, void, env, ptr, i32)
29
21
30
- ``netduinoplus2`` Netduino Plus 2 board with STM32F405RGT6 microcontroller
22
+DEF_HELPER_FLAGS_4(mve_vldrb_sg_sh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
+- ``olimex-stm32-h405`` Olimex STM32 H405 board with STM32F405RGT6 microcontroller
23
+DEF_HELPER_FLAGS_4(mve_vldrb_sg_sw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
32
24
+DEF_HELPER_FLAGS_4(mve_vldrh_sg_sw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
33
There are many other STM32 series that are currently not supported by QEMU.
34
35
diff --git a/configs/devices/arm-softmmu/default.mak b/configs/devices/arm-softmmu/default.mak
36
index XXXXXXX..XXXXXXX 100644
37
--- a/configs/devices/arm-softmmu/default.mak
38
+++ b/configs/devices/arm-softmmu/default.mak
39
@@ -XXX,XX +XXX,XX @@ CONFIG_COLLIE=y
40
CONFIG_ASPEED_SOC=y
41
CONFIG_NETDUINO2=y
42
CONFIG_NETDUINOPLUS2=y
43
+CONFIG_OLIMEX_STM32_H405=y
44
CONFIG_MPS2=y
45
CONFIG_RASPI=y
46
CONFIG_DIGIC=y
47
diff --git a/hw/arm/olimex-stm32-h405.c b/hw/arm/olimex-stm32-h405.c
48
new file mode 100644
49
index XXXXXXX..XXXXXXX
50
--- /dev/null
51
+++ b/hw/arm/olimex-stm32-h405.c
52
@@ -XXX,XX +XXX,XX @@
53
+/*
54
+ * ST STM32VLDISCOVERY machine
55
+ * Olimex STM32-H405 machine
56
+ *
57
+ * Copyright (c) 2022 Felipe Balbi <balbi@kernel.org>
58
+ *
59
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
60
+ * of this software and associated documentation files (the "Software"), to deal
61
+ * in the Software without restriction, including without limitation the rights
62
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
63
+ * copies of the Software, and to permit persons to whom the Software is
64
+ * furnished to do so, subject to the following conditions:
65
+ *
66
+ * The above copyright notice and this permission notice shall be included in
67
+ * all copies or substantial portions of the Software.
68
+ *
69
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
70
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
71
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
72
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
73
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
74
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
75
+ * THE SOFTWARE.
76
+ */
25
+
77
+
26
+DEF_HELPER_FLAGS_4(mve_vldrb_sg_ub, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
78
+#include "qemu/osdep.h"
27
+DEF_HELPER_FLAGS_4(mve_vldrb_sg_uh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
79
+#include "qapi/error.h"
28
+DEF_HELPER_FLAGS_4(mve_vldrb_sg_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
80
+#include "hw/boards.h"
29
+DEF_HELPER_FLAGS_4(mve_vldrh_sg_uh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
81
+#include "hw/qdev-properties.h"
30
+DEF_HELPER_FLAGS_4(mve_vldrh_sg_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
82
+#include "hw/qdev-clock.h"
31
+DEF_HELPER_FLAGS_4(mve_vldrw_sg_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
83
+#include "qemu/error-report.h"
32
+DEF_HELPER_FLAGS_4(mve_vldrd_sg_ud, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
84
+#include "hw/arm/stm32f405_soc.h"
85
+#include "hw/arm/boot.h"
33
+
86
+
34
+DEF_HELPER_FLAGS_4(mve_vstrb_sg_ub, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
87
+/* olimex-stm32-h405 implementation is derived from netduinoplus2 */
35
+DEF_HELPER_FLAGS_4(mve_vstrb_sg_uh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
36
+DEF_HELPER_FLAGS_4(mve_vstrb_sg_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
37
+DEF_HELPER_FLAGS_4(mve_vstrh_sg_uh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
38
+DEF_HELPER_FLAGS_4(mve_vstrh_sg_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
39
+DEF_HELPER_FLAGS_4(mve_vstrw_sg_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
40
+DEF_HELPER_FLAGS_4(mve_vstrd_sg_ud, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
41
+
88
+
42
+DEF_HELPER_FLAGS_4(mve_vldrh_sg_os_sw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
89
+/* Main SYSCLK frequency in Hz (168MHz) */
90
+#define SYSCLK_FRQ 168000000ULL
43
+
91
+
44
+DEF_HELPER_FLAGS_4(mve_vldrh_sg_os_uh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
92
+static void olimex_stm32_h405_init(MachineState *machine)
45
+DEF_HELPER_FLAGS_4(mve_vldrh_sg_os_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
93
+{
46
+DEF_HELPER_FLAGS_4(mve_vldrw_sg_os_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
94
+ DeviceState *dev;
47
+DEF_HELPER_FLAGS_4(mve_vldrd_sg_os_ud, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
95
+ Clock *sysclk;
48
+
96
+
49
+DEF_HELPER_FLAGS_4(mve_vstrh_sg_os_uh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
97
+ /* This clock doesn't need migration because it is fixed-frequency */
50
+DEF_HELPER_FLAGS_4(mve_vstrh_sg_os_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
98
+ sysclk = clock_new(OBJECT(machine), "SYSCLK");
51
+DEF_HELPER_FLAGS_4(mve_vstrw_sg_os_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
99
+ clock_set_hz(sysclk, SYSCLK_FRQ);
52
+DEF_HELPER_FLAGS_4(mve_vstrd_sg_os_ud, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
53
+
100
+
54
DEF_HELPER_FLAGS_3(mve_vdup, TCG_CALL_NO_WG, void, env, ptr, i32)
101
+ dev = qdev_new(TYPE_STM32F405_SOC);
55
102
+ qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4"));
56
DEF_HELPER_FLAGS_4(mve_vidupb, TCG_CALL_NO_WG, i32, env, ptr, i32, i32)
103
+ qdev_connect_clock_in(dev, "sysclk", sysclk);
57
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
104
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
58
index XXXXXXX..XXXXXXX 100644
59
--- a/target/arm/mve.decode
60
+++ b/target/arm/mve.decode
61
@@ -XXX,XX +XXX,XX @@
62
&shl_scalar qda rm size
63
&vmaxv qm rda size
64
&vabav qn qm rda size
65
+&vldst_sg qd qm rn size msize os
66
+
105
+
67
+# scatter-gather memory size is in bits 6:4
106
+ armv7m_load_kernel(ARM_CPU(first_cpu),
68
+%sg_msize 6:1 4:1
107
+ machine->kernel_filename,
69
108
+ 0, FLASH_SIZE);
70
@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
71
# Note that both Rn and Qd are 3 bits only (no D bit)
72
@vldst_wn ... u:1 ... . . . . l:1 . rn:3 qd:3 . ... .. imm:7 &vldr_vstr
73
74
+@vldst_sg .... .... .... rn:4 .... ... size:2 ... ... os:1 &vldst_sg \
75
+ qd=%qd qm=%qm msize=%sg_msize
76
+
77
@1op .... .... .... size:2 .. .... .... .... .... &1op qd=%qd qm=%qm
78
@1op_nosz .... .... .... .... .... .... .... .... &1op qd=%qd qm=%qm size=0
79
@2op .... .... .. size:2 .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn
80
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111101 ....... @vldr_vstr \
81
VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111110 ....... @vldr_vstr \
82
size=2 p=1
83
84
+# gather loads/scatter stores
85
+VLDR_S_sg 111 0 1100 1 . 01 .... ... 0 111 . .... .... @vldst_sg
86
+VLDR_U_sg 111 1 1100 1 . 01 .... ... 0 111 . .... .... @vldst_sg
87
+VSTR_sg 111 0 1100 1 . 00 .... ... 0 111 . .... .... @vldst_sg
88
+
89
# Moves between 2 32-bit vector lanes and 2 general purpose registers
90
VMOV_to_2gp 1110 1100 0 . 00 rt2:4 ... 0 1111 000 idx:1 rt:4 qd=%qd
91
VMOV_from_2gp 1110 1100 0 . 01 rt2:4 ... 0 1111 000 idx:1 rt:4 qd=%qd
92
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
93
index XXXXXXX..XXXXXXX 100644
94
--- a/target/arm/mve_helper.c
95
+++ b/target/arm/mve_helper.c
96
@@ -XXX,XX +XXX,XX @@ DO_VSTR(vstrh_w, 2, stw, 4, int32_t)
97
#undef DO_VLDR
98
#undef DO_VSTR
99
100
+/*
101
+ * Gather loads/scatter stores. Here each element of Qm specifies
102
+ * an offset to use from the base register Rm. In the _os_ versions
103
+ * that offset is scaled by the element size.
104
+ * For loads, predicated lanes are zeroed instead of retaining
105
+ * their previous values.
106
+ */
107
+#define DO_VLDR_SG(OP, LDTYPE, ESIZE, TYPE, OFFTYPE, ADDRFN) \
108
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm, \
109
+ uint32_t base) \
110
+ { \
111
+ TYPE *d = vd; \
112
+ OFFTYPE *m = vm; \
113
+ uint16_t mask = mve_element_mask(env); \
114
+ uint16_t eci_mask = mve_eci_mask(env); \
115
+ unsigned e; \
116
+ uint32_t addr; \
117
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE, eci_mask >>= ESIZE) { \
118
+ if (!(eci_mask & 1)) { \
119
+ continue; \
120
+ } \
121
+ addr = ADDRFN(base, m[H##ESIZE(e)]); \
122
+ d[H##ESIZE(e)] = (mask & 1) ? \
123
+ cpu_##LDTYPE##_data_ra(env, addr, GETPC()) : 0; \
124
+ } \
125
+ mve_advance_vpt(env); \
126
+ }
127
+
128
+/* We know here TYPE is unsigned so always the same as the offset type */
129
+#define DO_VSTR_SG(OP, STTYPE, ESIZE, TYPE, ADDRFN) \
130
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm, \
131
+ uint32_t base) \
132
+ { \
133
+ TYPE *d = vd; \
134
+ TYPE *m = vm; \
135
+ uint16_t mask = mve_element_mask(env); \
136
+ unsigned e; \
137
+ uint32_t addr; \
138
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
139
+ addr = ADDRFN(base, m[H##ESIZE(e)]); \
140
+ if (mask & 1) { \
141
+ cpu_##STTYPE##_data_ra(env, addr, d[H##ESIZE(e)], GETPC()); \
142
+ } \
143
+ } \
144
+ mve_advance_vpt(env); \
145
+ }
146
+
147
+/*
148
+ * 64-bit accesses are slightly different: they are done as two 32-bit
149
+ * accesses, controlled by the predicate mask for the relevant beat,
150
+ * and with a single 32-bit offset in the first of the two Qm elements.
151
+ * Note that for QEMU our IMPDEF AIRCR.ENDIANNESS is always 0 (little).
152
+ */
153
+#define DO_VLDR64_SG(OP, ADDRFN) \
154
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm, \
155
+ uint32_t base) \
156
+ { \
157
+ uint32_t *d = vd; \
158
+ uint32_t *m = vm; \
159
+ uint16_t mask = mve_element_mask(env); \
160
+ uint16_t eci_mask = mve_eci_mask(env); \
161
+ unsigned e; \
162
+ uint32_t addr; \
163
+ for (e = 0; e < 16 / 4; e++, mask >>= 4, eci_mask >>= 4) { \
164
+ if (!(eci_mask & 1)) { \
165
+ continue; \
166
+ } \
167
+ addr = ADDRFN(base, m[H4(e & ~1)]); \
168
+ addr += 4 * (e & 1); \
169
+ d[H4(e)] = (mask & 1) ? cpu_ldl_data_ra(env, addr, GETPC()) : 0; \
170
+ } \
171
+ mve_advance_vpt(env); \
172
+ }
173
+
174
+#define DO_VSTR64_SG(OP, ADDRFN) \
175
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm, \
176
+ uint32_t base) \
177
+ { \
178
+ uint32_t *d = vd; \
179
+ uint32_t *m = vm; \
180
+ uint16_t mask = mve_element_mask(env); \
181
+ unsigned e; \
182
+ uint32_t addr; \
183
+ for (e = 0; e < 16 / 4; e++, mask >>= 4) { \
184
+ addr = ADDRFN(base, m[H4(e & ~1)]); \
185
+ addr += 4 * (e & 1); \
186
+ if (mask & 1) { \
187
+ cpu_stl_data_ra(env, addr, d[H4(e)], GETPC()); \
188
+ } \
189
+ } \
190
+ mve_advance_vpt(env); \
191
+ }
192
+
193
+#define ADDR_ADD(BASE, OFFSET) ((BASE) + (OFFSET))
194
+#define ADDR_ADD_OSH(BASE, OFFSET) ((BASE) + ((OFFSET) << 1))
195
+#define ADDR_ADD_OSW(BASE, OFFSET) ((BASE) + ((OFFSET) << 2))
196
+#define ADDR_ADD_OSD(BASE, OFFSET) ((BASE) + ((OFFSET) << 3))
197
+
198
+DO_VLDR_SG(vldrb_sg_sh, ldsb, 2, int16_t, uint16_t, ADDR_ADD)
199
+DO_VLDR_SG(vldrb_sg_sw, ldsb, 4, int32_t, uint32_t, ADDR_ADD)
200
+DO_VLDR_SG(vldrh_sg_sw, ldsw, 4, int32_t, uint32_t, ADDR_ADD)
201
+
202
+DO_VLDR_SG(vldrb_sg_ub, ldub, 1, uint8_t, uint8_t, ADDR_ADD)
203
+DO_VLDR_SG(vldrb_sg_uh, ldub, 2, uint16_t, uint16_t, ADDR_ADD)
204
+DO_VLDR_SG(vldrb_sg_uw, ldub, 4, uint32_t, uint32_t, ADDR_ADD)
205
+DO_VLDR_SG(vldrh_sg_uh, lduw, 2, uint16_t, uint16_t, ADDR_ADD)
206
+DO_VLDR_SG(vldrh_sg_uw, lduw, 4, uint32_t, uint32_t, ADDR_ADD)
207
+DO_VLDR_SG(vldrw_sg_uw, ldl, 4, uint32_t, uint32_t, ADDR_ADD)
208
+DO_VLDR64_SG(vldrd_sg_ud, ADDR_ADD)
209
+
210
+DO_VLDR_SG(vldrh_sg_os_sw, ldsw, 4, int32_t, uint32_t, ADDR_ADD_OSH)
211
+DO_VLDR_SG(vldrh_sg_os_uh, lduw, 2, uint16_t, uint16_t, ADDR_ADD_OSH)
212
+DO_VLDR_SG(vldrh_sg_os_uw, lduw, 4, uint32_t, uint32_t, ADDR_ADD_OSH)
213
+DO_VLDR_SG(vldrw_sg_os_uw, ldl, 4, uint32_t, uint32_t, ADDR_ADD_OSW)
214
+DO_VLDR64_SG(vldrd_sg_os_ud, ADDR_ADD_OSD)
215
+
216
+DO_VSTR_SG(vstrb_sg_ub, stb, 1, uint8_t, ADDR_ADD)
217
+DO_VSTR_SG(vstrb_sg_uh, stb, 2, uint16_t, ADDR_ADD)
218
+DO_VSTR_SG(vstrb_sg_uw, stb, 4, uint32_t, ADDR_ADD)
219
+DO_VSTR_SG(vstrh_sg_uh, stw, 2, uint16_t, ADDR_ADD)
220
+DO_VSTR_SG(vstrh_sg_uw, stw, 4, uint32_t, ADDR_ADD)
221
+DO_VSTR_SG(vstrw_sg_uw, stl, 4, uint32_t, ADDR_ADD)
222
+DO_VSTR64_SG(vstrd_sg_ud, ADDR_ADD)
223
+
224
+DO_VSTR_SG(vstrh_sg_os_uh, stw, 2, uint16_t, ADDR_ADD_OSH)
225
+DO_VSTR_SG(vstrh_sg_os_uw, stw, 4, uint32_t, ADDR_ADD_OSH)
226
+DO_VSTR_SG(vstrw_sg_os_uw, stl, 4, uint32_t, ADDR_ADD_OSW)
227
+DO_VSTR64_SG(vstrd_sg_os_ud, ADDR_ADD_OSD)
228
+
229
/*
230
* The mergemask(D, R, M) macro performs the operation "*D = R" but
231
* storing only the bytes which correspond to 1 bits in M,
232
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
233
index XXXXXXX..XXXXXXX 100644
234
--- a/target/arm/translate-mve.c
235
+++ b/target/arm/translate-mve.c
236
@@ -XXX,XX +XXX,XX @@ static inline int vidup_imm(DisasContext *s, int x)
237
#include "decode-mve.c.inc"
238
239
typedef void MVEGenLdStFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
240
+typedef void MVEGenLdStSGFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
241
typedef void MVEGenOneOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
242
typedef void MVEGenTwoOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr);
243
typedef void MVEGenTwoOpScalarFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
244
@@ -XXX,XX +XXX,XX @@ DO_VLDST_WIDE_NARROW(VLDSTB_H, vldrb_sh, vldrb_uh, vstrb_h, MO_8)
245
DO_VLDST_WIDE_NARROW(VLDSTB_W, vldrb_sw, vldrb_uw, vstrb_w, MO_8)
246
DO_VLDST_WIDE_NARROW(VLDSTH_W, vldrh_sw, vldrh_uw, vstrh_w, MO_16)
247
248
+static bool do_ldst_sg(DisasContext *s, arg_vldst_sg *a, MVEGenLdStSGFn fn)
249
+{
250
+ TCGv_i32 addr;
251
+ TCGv_ptr qd, qm;
252
+
253
+ if (!dc_isar_feature(aa32_mve, s) ||
254
+ !mve_check_qreg_bank(s, a->qd | a->qm) ||
255
+ !fn || a->rn == 15) {
256
+ /* Rn case is UNPREDICTABLE */
257
+ return false;
258
+ }
259
+
260
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
261
+ return true;
262
+ }
263
+
264
+ addr = load_reg(s, a->rn);
265
+
266
+ qd = mve_qreg_ptr(a->qd);
267
+ qm = mve_qreg_ptr(a->qm);
268
+ fn(cpu_env, qd, qm, addr);
269
+ tcg_temp_free_ptr(qd);
270
+ tcg_temp_free_ptr(qm);
271
+ tcg_temp_free_i32(addr);
272
+ mve_update_eci(s);
273
+ return true;
274
+}
109
+}
275
+
110
+
276
+/*
111
+static void olimex_stm32_h405_machine_init(MachineClass *mc)
277
+ * The naming scheme here is "vldrb_sg_sh == in-memory byte loads
112
+{
278
+ * signextended to halfword elements in register". _os_ indicates that
113
+ mc->desc = "Olimex STM32-H405 (Cortex-M4)";
279
+ * the offsets in Qm should be scaled by the element size.
114
+ mc->init = olimex_stm32_h405_init;
280
+ */
115
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m4");
281
+/* This macro is just to make the arrays more compact in these functions */
282
+#define F(N) gen_helper_mve_##N
283
+
116
+
284
+/* VLDRB/VSTRB (ie msize 1) with OS=1 is UNPREDICTABLE; we UNDEF */
117
+ /* SRAM pre-allocated as part of the SoC instantiation */
285
+static bool trans_VLDR_S_sg(DisasContext *s, arg_vldst_sg *a)
118
+ mc->default_ram_size = 0;
286
+{
287
+ static MVEGenLdStSGFn * const fns[2][4][4] = { {
288
+ { NULL, F(vldrb_sg_sh), F(vldrb_sg_sw), NULL },
289
+ { NULL, NULL, F(vldrh_sg_sw), NULL },
290
+ { NULL, NULL, NULL, NULL },
291
+ { NULL, NULL, NULL, NULL }
292
+ }, {
293
+ { NULL, NULL, NULL, NULL },
294
+ { NULL, NULL, F(vldrh_sg_os_sw), NULL },
295
+ { NULL, NULL, NULL, NULL },
296
+ { NULL, NULL, NULL, NULL }
297
+ }
298
+ };
299
+ if (a->qd == a->qm) {
300
+ return false; /* UNPREDICTABLE */
301
+ }
302
+ return do_ldst_sg(s, a, fns[a->os][a->msize][a->size]);
303
+}
119
+}
304
+
120
+
305
+static bool trans_VLDR_U_sg(DisasContext *s, arg_vldst_sg *a)
121
+DEFINE_MACHINE("olimex-stm32-h405", olimex_stm32_h405_machine_init)
306
+{
122
diff --git a/MAINTAINERS b/MAINTAINERS
307
+ static MVEGenLdStSGFn * const fns[2][4][4] = { {
123
index XXXXXXX..XXXXXXX 100644
308
+ { F(vldrb_sg_ub), F(vldrb_sg_uh), F(vldrb_sg_uw), NULL },
124
--- a/MAINTAINERS
309
+ { NULL, F(vldrh_sg_uh), F(vldrh_sg_uw), NULL },
125
+++ b/MAINTAINERS
310
+ { NULL, NULL, F(vldrw_sg_uw), NULL },
126
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
311
+ { NULL, NULL, NULL, F(vldrd_sg_ud) }
127
S: Maintained
312
+ }, {
128
F: hw/arm/netduinoplus2.c
313
+ { NULL, NULL, NULL, NULL },
129
314
+ { NULL, F(vldrh_sg_os_uh), F(vldrh_sg_os_uw), NULL },
130
+Olimex STM32 H405
315
+ { NULL, NULL, F(vldrw_sg_os_uw), NULL },
131
+M: Felipe Balbi <balbi@kernel.org>
316
+ { NULL, NULL, NULL, F(vldrd_sg_os_ud) }
132
+L: qemu-arm@nongnu.org
317
+ }
133
+S: Maintained
318
+ };
134
+F: hw/arm/olimex-stm32-h405.c
319
+ if (a->qd == a->qm) {
320
+ return false; /* UNPREDICTABLE */
321
+ }
322
+ return do_ldst_sg(s, a, fns[a->os][a->msize][a->size]);
323
+}
324
+
135
+
325
+static bool trans_VSTR_sg(DisasContext *s, arg_vldst_sg *a)
136
SmartFusion2
326
+{
137
M: Subbaraya Sundeep <sundeep.lkml@gmail.com>
327
+ static MVEGenLdStSGFn * const fns[2][4][4] = { {
138
M: Peter Maydell <peter.maydell@linaro.org>
328
+ { F(vstrb_sg_ub), F(vstrb_sg_uh), F(vstrb_sg_uw), NULL },
139
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
329
+ { NULL, F(vstrh_sg_uh), F(vstrh_sg_uw), NULL },
140
index XXXXXXX..XXXXXXX 100644
330
+ { NULL, NULL, F(vstrw_sg_uw), NULL },
141
--- a/hw/arm/Kconfig
331
+ { NULL, NULL, NULL, F(vstrd_sg_ud) }
142
+++ b/hw/arm/Kconfig
332
+ }, {
143
@@ -XXX,XX +XXX,XX @@ config NETDUINOPLUS2
333
+ { NULL, NULL, NULL, NULL },
144
bool
334
+ { NULL, F(vstrh_sg_os_uh), F(vstrh_sg_os_uw), NULL },
145
select STM32F405_SOC
335
+ { NULL, NULL, F(vstrw_sg_os_uw), NULL },
146
336
+ { NULL, NULL, NULL, F(vstrd_sg_os_ud) }
147
+config OLIMEX_STM32_H405
337
+ }
148
+ bool
338
+ };
149
+ select STM32F405_SOC
339
+ return do_ldst_sg(s, a, fns[a->os][a->msize][a->size]);
340
+}
341
+
150
+
342
+#undef F
151
config NSERIES
343
+
152
bool
344
static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
153
select OMAP
345
{
154
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
346
TCGv_ptr qd;
155
index XXXXXXX..XXXXXXX 100644
156
--- a/hw/arm/meson.build
157
+++ b/hw/arm/meson.build
158
@@ -XXX,XX +XXX,XX @@ arm_ss.add(when: 'CONFIG_MICROBIT', if_true: files('microbit.c'))
159
arm_ss.add(when: 'CONFIG_MUSICPAL', if_true: files('musicpal.c'))
160
arm_ss.add(when: 'CONFIG_NETDUINO2', if_true: files('netduino2.c'))
161
arm_ss.add(when: 'CONFIG_NETDUINOPLUS2', if_true: files('netduinoplus2.c'))
162
+arm_ss.add(when: 'CONFIG_OLIMEX_STM32_H405', if_true: files('olimex-stm32-h405.c'))
163
arm_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx.c', 'npcm7xx_boards.c'))
164
arm_ss.add(when: 'CONFIG_NSERIES', if_true: files('nseries.c'))
165
arm_ss.add(when: 'CONFIG_SX1', if_true: files('omap_sx1.c'))
347
--
166
--
348
2.20.1
167
2.34.1
349
168
350
169
diff view generated by jsdifflib
1
Implement the MVE VMOV forms that move data between 2 general-purpose
1
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
2
registers and 2 32-bit lanes in a vector register.
3
2
3
During SPL boot several Clock Controller Module (CCM) registers are
4
read, most important are PLL and Tuning, as well as divisor registers.
5
6
This patch adds these registers and initializes reset values from user's
7
guide.
8
9
Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
10
11
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
12
Message-id: 20221226220303.14420-2-strahinja.p.jankovic@gmail.com
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
---
14
---
7
target/arm/translate-a32.h | 1 +
15
include/hw/arm/allwinner-a10.h | 2 +
8
target/arm/mve.decode | 4 ++
16
include/hw/misc/allwinner-a10-ccm.h | 67 +++++++++
9
target/arm/translate-mve.c | 85 ++++++++++++++++++++++++++++++++++++++
17
hw/arm/allwinner-a10.c | 7 +
10
target/arm/translate-vfp.c | 2 +-
18
hw/misc/allwinner-a10-ccm.c | 224 ++++++++++++++++++++++++++++
11
4 files changed, 91 insertions(+), 1 deletion(-)
19
hw/arm/Kconfig | 1 +
20
hw/misc/Kconfig | 3 +
21
hw/misc/meson.build | 1 +
22
7 files changed, 305 insertions(+)
23
create mode 100644 include/hw/misc/allwinner-a10-ccm.h
24
create mode 100644 hw/misc/allwinner-a10-ccm.c
12
25
13
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
26
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
14
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-a32.h
28
--- a/include/hw/arm/allwinner-a10.h
16
+++ b/target/arm/translate-a32.h
29
+++ b/include/hw/arm/allwinner-a10.h
17
@@ -XXX,XX +XXX,XX @@ void gen_rev16(TCGv_i32 dest, TCGv_i32 var);
30
@@ -XXX,XX +XXX,XX @@
18
void clear_eci_state(DisasContext *s);
31
#include "hw/usb/hcd-ohci.h"
19
bool mve_eci_check(DisasContext *s);
32
#include "hw/usb/hcd-ehci.h"
20
void mve_update_and_store_eci(DisasContext *s);
33
#include "hw/rtc/allwinner-rtc.h"
21
+bool mve_skip_vmov(DisasContext *s, int vn, int index, int size);
34
+#include "hw/misc/allwinner-a10-ccm.h"
22
35
23
static inline TCGv_i32 load_cpu_offset(int offset)
36
#include "target/arm/cpu.h"
24
{
37
#include "qom/object.h"
25
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
38
@@ -XXX,XX +XXX,XX @@ struct AwA10State {
39
/*< public >*/
40
41
ARMCPU cpu;
42
+ AwA10ClockCtlState ccm;
43
AwA10PITState timer;
44
AwA10PICState intc;
45
AwEmacState emac;
46
diff --git a/include/hw/misc/allwinner-a10-ccm.h b/include/hw/misc/allwinner-a10-ccm.h
47
new file mode 100644
48
index XXXXXXX..XXXXXXX
49
--- /dev/null
50
+++ b/include/hw/misc/allwinner-a10-ccm.h
51
@@ -XXX,XX +XXX,XX @@
52
+/*
53
+ * Allwinner A10 Clock Control Module emulation
54
+ *
55
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
56
+ *
57
+ * This file is derived from Allwinner H3 CCU,
58
+ * by Niek Linnenbank.
59
+ *
60
+ * This program is free software: you can redistribute it and/or modify
61
+ * it under the terms of the GNU General Public License as published by
62
+ * the Free Software Foundation, either version 2 of the License, or
63
+ * (at your option) any later version.
64
+ *
65
+ * This program is distributed in the hope that it will be useful,
66
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
67
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
68
+ * GNU General Public License for more details.
69
+ *
70
+ * You should have received a copy of the GNU General Public License
71
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
72
+ */
73
+
74
+#ifndef HW_MISC_ALLWINNER_A10_CCM_H
75
+#define HW_MISC_ALLWINNER_A10_CCM_H
76
+
77
+#include "qom/object.h"
78
+#include "hw/sysbus.h"
79
+
80
+/**
81
+ * @name Constants
82
+ * @{
83
+ */
84
+
85
+/** Size of register I/O address space used by CCM device */
86
+#define AW_A10_CCM_IOSIZE (0x400)
87
+
88
+/** Total number of known registers */
89
+#define AW_A10_CCM_REGS_NUM (AW_A10_CCM_IOSIZE / sizeof(uint32_t))
90
+
91
+/** @} */
92
+
93
+/**
94
+ * @name Object model
95
+ * @{
96
+ */
97
+
98
+#define TYPE_AW_A10_CCM "allwinner-a10-ccm"
99
+OBJECT_DECLARE_SIMPLE_TYPE(AwA10ClockCtlState, AW_A10_CCM)
100
+
101
+/** @} */
102
+
103
+/**
104
+ * Allwinner A10 CCM object instance state.
105
+ */
106
+struct AwA10ClockCtlState {
107
+ /*< private >*/
108
+ SysBusDevice parent_obj;
109
+ /*< public >*/
110
+
111
+ /** Maps I/O registers in physical memory */
112
+ MemoryRegion iomem;
113
+
114
+ /** Array of hardware registers */
115
+ uint32_t regs[AW_A10_CCM_REGS_NUM];
116
+};
117
+
118
+#endif /* HW_MISC_ALLWINNER_H3_CCU_H */
119
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
26
index XXXXXXX..XXXXXXX 100644
120
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/mve.decode
121
--- a/hw/arm/allwinner-a10.c
28
+++ b/target/arm/mve.decode
122
+++ b/hw/arm/allwinner-a10.c
29
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111101 ....... @vldr_vstr \
123
@@ -XXX,XX +XXX,XX @@
30
VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111110 ....... @vldr_vstr \
124
#include "hw/usb/hcd-ohci.h"
31
size=2 p=1
125
32
126
#define AW_A10_MMC0_BASE 0x01c0f000
33
+# Moves between 2 32-bit vector lanes and 2 general purpose registers
127
+#define AW_A10_CCM_BASE 0x01c20000
34
+VMOV_to_2gp 1110 1100 0 . 00 rt2:4 ... 0 1111 000 idx:1 rt:4 qd=%qd
128
#define AW_A10_PIC_REG_BASE 0x01c20400
35
+VMOV_from_2gp 1110 1100 0 . 01 rt2:4 ... 0 1111 000 idx:1 rt:4 qd=%qd
129
#define AW_A10_PIT_REG_BASE 0x01c20c00
36
+
130
#define AW_A10_UART0_REG_BASE 0x01c28000
37
# Vector 2-op
131
@@ -XXX,XX +XXX,XX @@ static void aw_a10_init(Object *obj)
38
VAND 1110 1111 0 . 00 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
132
39
VBIC 1110 1111 0 . 01 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
133
object_initialize_child(obj, "timer", &s->timer, TYPE_AW_A10_PIT);
40
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
134
135
+ object_initialize_child(obj, "ccm", &s->ccm, TYPE_AW_A10_CCM);
136
+
137
object_initialize_child(obj, "emac", &s->emac, TYPE_AW_EMAC);
138
139
object_initialize_child(obj, "sata", &s->sata, TYPE_ALLWINNER_AHCI);
140
@@ -XXX,XX +XXX,XX @@ static void aw_a10_realize(DeviceState *dev, Error **errp)
141
memory_region_add_subregion(get_system_memory(), 0x00000000, &s->sram_a);
142
create_unimplemented_device("a10-sram-ctrl", 0x01c00000, 4 * KiB);
143
144
+ /* Clock Control Module */
145
+ sysbus_realize(SYS_BUS_DEVICE(&s->ccm), &error_fatal);
146
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, AW_A10_CCM_BASE);
147
+
148
/* FIXME use qdev NIC properties instead of nd_table[] */
149
if (nd_table[0].used) {
150
qemu_check_nic_model(&nd_table[0], TYPE_AW_EMAC);
151
diff --git a/hw/misc/allwinner-a10-ccm.c b/hw/misc/allwinner-a10-ccm.c
152
new file mode 100644
153
index XXXXXXX..XXXXXXX
154
--- /dev/null
155
+++ b/hw/misc/allwinner-a10-ccm.c
156
@@ -XXX,XX +XXX,XX @@
157
+/*
158
+ * Allwinner A10 Clock Control Module emulation
159
+ *
160
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
161
+ *
162
+ * This file is derived from Allwinner H3 CCU,
163
+ * by Niek Linnenbank.
164
+ *
165
+ * This program is free software: you can redistribute it and/or modify
166
+ * it under the terms of the GNU General Public License as published by
167
+ * the Free Software Foundation, either version 2 of the License, or
168
+ * (at your option) any later version.
169
+ *
170
+ * This program is distributed in the hope that it will be useful,
171
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
172
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
173
+ * GNU General Public License for more details.
174
+ *
175
+ * You should have received a copy of the GNU General Public License
176
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
177
+ */
178
+
179
+#include "qemu/osdep.h"
180
+#include "qemu/units.h"
181
+#include "hw/sysbus.h"
182
+#include "migration/vmstate.h"
183
+#include "qemu/log.h"
184
+#include "qemu/module.h"
185
+#include "hw/misc/allwinner-a10-ccm.h"
186
+
187
+/* CCM register offsets */
188
+enum {
189
+ REG_PLL1_CFG = 0x0000, /* PLL1 Control */
190
+ REG_PLL1_TUN = 0x0004, /* PLL1 Tuning */
191
+ REG_PLL2_CFG = 0x0008, /* PLL2 Control */
192
+ REG_PLL2_TUN = 0x000C, /* PLL2 Tuning */
193
+ REG_PLL3_CFG = 0x0010, /* PLL3 Control */
194
+ REG_PLL4_CFG = 0x0018, /* PLL4 Control */
195
+ REG_PLL5_CFG = 0x0020, /* PLL5 Control */
196
+ REG_PLL5_TUN = 0x0024, /* PLL5 Tuning */
197
+ REG_PLL6_CFG = 0x0028, /* PLL6 Control */
198
+ REG_PLL6_TUN = 0x002C, /* PLL6 Tuning */
199
+ REG_PLL7_CFG = 0x0030, /* PLL7 Control */
200
+ REG_PLL1_TUN2 = 0x0038, /* PLL1 Tuning2 */
201
+ REG_PLL5_TUN2 = 0x003C, /* PLL5 Tuning2 */
202
+ REG_PLL8_CFG = 0x0040, /* PLL8 Control */
203
+ REG_OSC24M_CFG = 0x0050, /* OSC24M Control */
204
+ REG_CPU_AHB_APB0_CFG = 0x0054, /* CPU, AHB and APB0 Divide Ratio */
205
+};
206
+
207
+#define REG_INDEX(offset) (offset / sizeof(uint32_t))
208
+
209
+/* CCM register reset values */
210
+enum {
211
+ REG_PLL1_CFG_RST = 0x21005000,
212
+ REG_PLL1_TUN_RST = 0x0A101000,
213
+ REG_PLL2_CFG_RST = 0x08100010,
214
+ REG_PLL2_TUN_RST = 0x00000000,
215
+ REG_PLL3_CFG_RST = 0x0010D063,
216
+ REG_PLL4_CFG_RST = 0x21009911,
217
+ REG_PLL5_CFG_RST = 0x11049280,
218
+ REG_PLL5_TUN_RST = 0x14888000,
219
+ REG_PLL6_CFG_RST = 0x21009911,
220
+ REG_PLL6_TUN_RST = 0x00000000,
221
+ REG_PLL7_CFG_RST = 0x0010D063,
222
+ REG_PLL1_TUN2_RST = 0x00000000,
223
+ REG_PLL5_TUN2_RST = 0x00000000,
224
+ REG_PLL8_CFG_RST = 0x21009911,
225
+ REG_OSC24M_CFG_RST = 0x00138013,
226
+ REG_CPU_AHB_APB0_CFG_RST = 0x00010010,
227
+};
228
+
229
+static uint64_t allwinner_a10_ccm_read(void *opaque, hwaddr offset,
230
+ unsigned size)
231
+{
232
+ const AwA10ClockCtlState *s = AW_A10_CCM(opaque);
233
+ const uint32_t idx = REG_INDEX(offset);
234
+
235
+ switch (offset) {
236
+ case REG_PLL1_CFG:
237
+ case REG_PLL1_TUN:
238
+ case REG_PLL2_CFG:
239
+ case REG_PLL2_TUN:
240
+ case REG_PLL3_CFG:
241
+ case REG_PLL4_CFG:
242
+ case REG_PLL5_CFG:
243
+ case REG_PLL5_TUN:
244
+ case REG_PLL6_CFG:
245
+ case REG_PLL6_TUN:
246
+ case REG_PLL7_CFG:
247
+ case REG_PLL1_TUN2:
248
+ case REG_PLL5_TUN2:
249
+ case REG_PLL8_CFG:
250
+ case REG_OSC24M_CFG:
251
+ case REG_CPU_AHB_APB0_CFG:
252
+ break;
253
+ case 0x158 ... AW_A10_CCM_IOSIZE:
254
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
255
+ __func__, (uint32_t)offset);
256
+ return 0;
257
+ default:
258
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented read offset 0x%04x\n",
259
+ __func__, (uint32_t)offset);
260
+ return 0;
261
+ }
262
+
263
+ return s->regs[idx];
264
+}
265
+
266
+static void allwinner_a10_ccm_write(void *opaque, hwaddr offset,
267
+ uint64_t val, unsigned size)
268
+{
269
+ AwA10ClockCtlState *s = AW_A10_CCM(opaque);
270
+ const uint32_t idx = REG_INDEX(offset);
271
+
272
+ switch (offset) {
273
+ case REG_PLL1_CFG:
274
+ case REG_PLL1_TUN:
275
+ case REG_PLL2_CFG:
276
+ case REG_PLL2_TUN:
277
+ case REG_PLL3_CFG:
278
+ case REG_PLL4_CFG:
279
+ case REG_PLL5_CFG:
280
+ case REG_PLL5_TUN:
281
+ case REG_PLL6_CFG:
282
+ case REG_PLL6_TUN:
283
+ case REG_PLL7_CFG:
284
+ case REG_PLL1_TUN2:
285
+ case REG_PLL5_TUN2:
286
+ case REG_PLL8_CFG:
287
+ case REG_OSC24M_CFG:
288
+ case REG_CPU_AHB_APB0_CFG:
289
+ break;
290
+ case 0x158 ... AW_A10_CCM_IOSIZE:
291
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
292
+ __func__, (uint32_t)offset);
293
+ break;
294
+ default:
295
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented write offset 0x%04x\n",
296
+ __func__, (uint32_t)offset);
297
+ break;
298
+ }
299
+
300
+ s->regs[idx] = (uint32_t) val;
301
+}
302
+
303
+static const MemoryRegionOps allwinner_a10_ccm_ops = {
304
+ .read = allwinner_a10_ccm_read,
305
+ .write = allwinner_a10_ccm_write,
306
+ .endianness = DEVICE_NATIVE_ENDIAN,
307
+ .valid = {
308
+ .min_access_size = 4,
309
+ .max_access_size = 4,
310
+ },
311
+ .impl.min_access_size = 4,
312
+};
313
+
314
+static void allwinner_a10_ccm_reset_enter(Object *obj, ResetType type)
315
+{
316
+ AwA10ClockCtlState *s = AW_A10_CCM(obj);
317
+
318
+ /* Set default values for registers */
319
+ s->regs[REG_INDEX(REG_PLL1_CFG)] = REG_PLL1_CFG_RST;
320
+ s->regs[REG_INDEX(REG_PLL1_TUN)] = REG_PLL1_TUN_RST;
321
+ s->regs[REG_INDEX(REG_PLL2_CFG)] = REG_PLL2_CFG_RST;
322
+ s->regs[REG_INDEX(REG_PLL2_TUN)] = REG_PLL2_TUN_RST;
323
+ s->regs[REG_INDEX(REG_PLL3_CFG)] = REG_PLL3_CFG_RST;
324
+ s->regs[REG_INDEX(REG_PLL4_CFG)] = REG_PLL4_CFG_RST;
325
+ s->regs[REG_INDEX(REG_PLL5_CFG)] = REG_PLL5_CFG_RST;
326
+ s->regs[REG_INDEX(REG_PLL5_TUN)] = REG_PLL5_TUN_RST;
327
+ s->regs[REG_INDEX(REG_PLL6_CFG)] = REG_PLL6_CFG_RST;
328
+ s->regs[REG_INDEX(REG_PLL6_TUN)] = REG_PLL6_TUN_RST;
329
+ s->regs[REG_INDEX(REG_PLL7_CFG)] = REG_PLL7_CFG_RST;
330
+ s->regs[REG_INDEX(REG_PLL1_TUN2)] = REG_PLL1_TUN2_RST;
331
+ s->regs[REG_INDEX(REG_PLL5_TUN2)] = REG_PLL5_TUN2_RST;
332
+ s->regs[REG_INDEX(REG_PLL8_CFG)] = REG_PLL8_CFG_RST;
333
+ s->regs[REG_INDEX(REG_OSC24M_CFG)] = REG_OSC24M_CFG_RST;
334
+ s->regs[REG_INDEX(REG_CPU_AHB_APB0_CFG)] = REG_CPU_AHB_APB0_CFG_RST;
335
+}
336
+
337
+static void allwinner_a10_ccm_init(Object *obj)
338
+{
339
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
340
+ AwA10ClockCtlState *s = AW_A10_CCM(obj);
341
+
342
+ /* Memory mapping */
343
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_a10_ccm_ops, s,
344
+ TYPE_AW_A10_CCM, AW_A10_CCM_IOSIZE);
345
+ sysbus_init_mmio(sbd, &s->iomem);
346
+}
347
+
348
+static const VMStateDescription allwinner_a10_ccm_vmstate = {
349
+ .name = "allwinner-a10-ccm",
350
+ .version_id = 1,
351
+ .minimum_version_id = 1,
352
+ .fields = (VMStateField[]) {
353
+ VMSTATE_UINT32_ARRAY(regs, AwA10ClockCtlState, AW_A10_CCM_REGS_NUM),
354
+ VMSTATE_END_OF_LIST()
355
+ }
356
+};
357
+
358
+static void allwinner_a10_ccm_class_init(ObjectClass *klass, void *data)
359
+{
360
+ DeviceClass *dc = DEVICE_CLASS(klass);
361
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
362
+
363
+ rc->phases.enter = allwinner_a10_ccm_reset_enter;
364
+ dc->vmsd = &allwinner_a10_ccm_vmstate;
365
+}
366
+
367
+static const TypeInfo allwinner_a10_ccm_info = {
368
+ .name = TYPE_AW_A10_CCM,
369
+ .parent = TYPE_SYS_BUS_DEVICE,
370
+ .instance_init = allwinner_a10_ccm_init,
371
+ .instance_size = sizeof(AwA10ClockCtlState),
372
+ .class_init = allwinner_a10_ccm_class_init,
373
+};
374
+
375
+static void allwinner_a10_ccm_register(void)
376
+{
377
+ type_register_static(&allwinner_a10_ccm_info);
378
+}
379
+
380
+type_init(allwinner_a10_ccm_register)
381
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
41
index XXXXXXX..XXXXXXX 100644
382
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/translate-mve.c
383
--- a/hw/arm/Kconfig
43
+++ b/target/arm/translate-mve.c
384
+++ b/hw/arm/Kconfig
44
@@ -XXX,XX +XXX,XX @@ static bool do_vabav(DisasContext *s, arg_vabav *a, MVEGenVABAVFn *fn)
385
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10
45
386
select AHCI
46
DO_VABAV(VABAV_S, vabavs)
387
select ALLWINNER_A10_PIT
47
DO_VABAV(VABAV_U, vabavu)
388
select ALLWINNER_A10_PIC
48
+
389
+ select ALLWINNER_A10_CCM
49
+static bool trans_VMOV_to_2gp(DisasContext *s, arg_VMOV_to_2gp *a)
390
select ALLWINNER_EMAC
50
+{
391
select SERIAL
51
+ /*
392
select UNIMP
52
+ * VMOV two 32-bit vector lanes to two general-purpose registers.
393
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
53
+ * This insn is not predicated but it is subject to beat-wise
54
+ * execution if it is not in an IT block. For us this means
55
+ * only that if PSR.ECI says we should not be executing the beat
56
+ * corresponding to the lane of the vector register being accessed
57
+ * then we should skip perfoming the move, and that we need to do
58
+ * the usual check for bad ECI state and advance of ECI state.
59
+ * (If PSR.ECI is non-zero then we cannot be in an IT block.)
60
+ */
61
+ TCGv_i32 tmp;
62
+ int vd;
63
+
64
+ if (!dc_isar_feature(aa32_mve, s) || !mve_check_qreg_bank(s, a->qd) ||
65
+ a->rt == 13 || a->rt == 15 || a->rt2 == 13 || a->rt2 == 15 ||
66
+ a->rt == a->rt2) {
67
+ /* Rt/Rt2 cases are UNPREDICTABLE */
68
+ return false;
69
+ }
70
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
71
+ return true;
72
+ }
73
+
74
+ /* Convert Qreg index to Dreg for read_neon_element32() etc */
75
+ vd = a->qd * 2;
76
+
77
+ if (!mve_skip_vmov(s, vd, a->idx, MO_32)) {
78
+ tmp = tcg_temp_new_i32();
79
+ read_neon_element32(tmp, vd, a->idx, MO_32);
80
+ store_reg(s, a->rt, tmp);
81
+ }
82
+ if (!mve_skip_vmov(s, vd + 1, a->idx, MO_32)) {
83
+ tmp = tcg_temp_new_i32();
84
+ read_neon_element32(tmp, vd + 1, a->idx, MO_32);
85
+ store_reg(s, a->rt2, tmp);
86
+ }
87
+
88
+ mve_update_and_store_eci(s);
89
+ return true;
90
+}
91
+
92
+static bool trans_VMOV_from_2gp(DisasContext *s, arg_VMOV_to_2gp *a)
93
+{
94
+ /*
95
+ * VMOV two general-purpose registers to two 32-bit vector lanes.
96
+ * This insn is not predicated but it is subject to beat-wise
97
+ * execution if it is not in an IT block. For us this means
98
+ * only that if PSR.ECI says we should not be executing the beat
99
+ * corresponding to the lane of the vector register being accessed
100
+ * then we should skip perfoming the move, and that we need to do
101
+ * the usual check for bad ECI state and advance of ECI state.
102
+ * (If PSR.ECI is non-zero then we cannot be in an IT block.)
103
+ */
104
+ TCGv_i32 tmp;
105
+ int vd;
106
+
107
+ if (!dc_isar_feature(aa32_mve, s) || !mve_check_qreg_bank(s, a->qd) ||
108
+ a->rt == 13 || a->rt == 15 || a->rt2 == 13 || a->rt2 == 15) {
109
+ /* Rt/Rt2 cases are UNPREDICTABLE */
110
+ return false;
111
+ }
112
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
113
+ return true;
114
+ }
115
+
116
+ /* Convert Qreg idx to Dreg for read_neon_element32() etc */
117
+ vd = a->qd * 2;
118
+
119
+ if (!mve_skip_vmov(s, vd, a->idx, MO_32)) {
120
+ tmp = load_reg(s, a->rt);
121
+ write_neon_element32(tmp, vd, a->idx, MO_32);
122
+ tcg_temp_free_i32(tmp);
123
+ }
124
+ if (!mve_skip_vmov(s, vd + 1, a->idx, MO_32)) {
125
+ tmp = load_reg(s, a->rt2);
126
+ write_neon_element32(tmp, vd + 1, a->idx, MO_32);
127
+ tcg_temp_free_i32(tmp);
128
+ }
129
+
130
+ mve_update_and_store_eci(s);
131
+ return true;
132
+}
133
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
134
index XXXXXXX..XXXXXXX 100644
394
index XXXXXXX..XXXXXXX 100644
135
--- a/target/arm/translate-vfp.c
395
--- a/hw/misc/Kconfig
136
+++ b/target/arm/translate-vfp.c
396
+++ b/hw/misc/Kconfig
137
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
397
@@ -XXX,XX +XXX,XX @@ config VIRT_CTRL
138
return true;
398
config LASI
139
}
399
bool
140
400
141
-static bool mve_skip_vmov(DisasContext *s, int vn, int index, int size)
401
+config ALLWINNER_A10_CCM
142
+bool mve_skip_vmov(DisasContext *s, int vn, int index, int size)
402
+ bool
143
{
403
+
144
/*
404
source macio/Kconfig
145
* In a CPU with MVE, the VMOV (vector lane to general-purpose register)
405
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
406
index XXXXXXX..XXXXXXX 100644
407
--- a/hw/misc/meson.build
408
+++ b/hw/misc/meson.build
409
@@ -XXX,XX +XXX,XX @@ subdir('macio')
410
411
softmmu_ss.add(when: 'CONFIG_IVSHMEM_DEVICE', if_true: files('ivshmem.c'))
412
413
+softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10_CCM', if_true: files('allwinner-a10-ccm.c'))
414
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-ccu.c'))
415
specific_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-cpucfg.c'))
416
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-dramc.c'))
146
--
417
--
147
2.20.1
418
2.34.1
148
149
diff view generated by jsdifflib
1
Implement the MVE incrementing/decrementing dup insns VIDUP, VDDUP,
1
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
2
VIWDUP and VDWDUP. These fill the elements of a vector with
2
3
successively incrementing values, starting at the offset specified in
3
During SPL boot several DRAM Controller registers are used. Most
4
a general purpose register. The final value of the offset is written
4
important registers are those related to DRAM initialization and
5
back to this register. The wrapping variants take a second general
5
calibration, where SPL initiates process and waits until certain bit is
6
purpose register which specifies the point where the count should
6
set/cleared.
7
wrap back to 0.
7
8
8
This patch adds these registers, initializes reset values from user's
9
guide and updates state of registers as SPL expects it.
10
11
Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
12
13
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
14
Message-id: 20221226220303.14420-3-strahinja.p.jankovic@gmail.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
---
16
---
12
target/arm/helper-mve.h | 12 ++++
17
include/hw/arm/allwinner-a10.h | 2 +
13
target/arm/mve.decode | 25 ++++++++
18
include/hw/misc/allwinner-a10-dramc.h | 68 ++++++++++
14
target/arm/mve_helper.c | 63 +++++++++++++++++++
19
hw/arm/allwinner-a10.c | 7 +
15
target/arm/translate-mve.c | 120 +++++++++++++++++++++++++++++++++++++
20
hw/misc/allwinner-a10-dramc.c | 179 ++++++++++++++++++++++++++
16
4 files changed, 220 insertions(+)
21
hw/arm/Kconfig | 1 +
17
22
hw/misc/Kconfig | 3 +
18
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
23
hw/misc/meson.build | 1 +
19
index XXXXXXX..XXXXXXX 100644
24
7 files changed, 261 insertions(+)
20
--- a/target/arm/helper-mve.h
25
create mode 100644 include/hw/misc/allwinner-a10-dramc.h
21
+++ b/target/arm/helper-mve.h
26
create mode 100644 hw/misc/allwinner-a10-dramc.c
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vstrh_w, TCG_CALL_NO_WG, void, env, ptr, i32)
27
23
28
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
24
DEF_HELPER_FLAGS_3(mve_vdup, TCG_CALL_NO_WG, void, env, ptr, i32)
29
index XXXXXXX..XXXXXXX 100644
25
30
--- a/include/hw/arm/allwinner-a10.h
26
+DEF_HELPER_FLAGS_4(mve_vidupb, TCG_CALL_NO_WG, i32, env, ptr, i32, i32)
31
+++ b/include/hw/arm/allwinner-a10.h
27
+DEF_HELPER_FLAGS_4(mve_viduph, TCG_CALL_NO_WG, i32, env, ptr, i32, i32)
28
+DEF_HELPER_FLAGS_4(mve_vidupw, TCG_CALL_NO_WG, i32, env, ptr, i32, i32)
29
+
30
+DEF_HELPER_FLAGS_5(mve_viwdupb, TCG_CALL_NO_WG, i32, env, ptr, i32, i32, i32)
31
+DEF_HELPER_FLAGS_5(mve_viwduph, TCG_CALL_NO_WG, i32, env, ptr, i32, i32, i32)
32
+DEF_HELPER_FLAGS_5(mve_viwdupw, TCG_CALL_NO_WG, i32, env, ptr, i32, i32, i32)
33
+
34
+DEF_HELPER_FLAGS_5(mve_vdwdupb, TCG_CALL_NO_WG, i32, env, ptr, i32, i32, i32)
35
+DEF_HELPER_FLAGS_5(mve_vdwduph, TCG_CALL_NO_WG, i32, env, ptr, i32, i32, i32)
36
+DEF_HELPER_FLAGS_5(mve_vdwdupw, TCG_CALL_NO_WG, i32, env, ptr, i32, i32, i32)
37
+
38
DEF_HELPER_FLAGS_3(mve_vclsb, TCG_CALL_NO_WG, void, env, ptr, ptr)
39
DEF_HELPER_FLAGS_3(mve_vclsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
40
DEF_HELPER_FLAGS_3(mve_vclsw, TCG_CALL_NO_WG, void, env, ptr, ptr)
41
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
42
index XXXXXXX..XXXXXXX 100644
43
--- a/target/arm/mve.decode
44
+++ b/target/arm/mve.decode
45
@@ -XXX,XX +XXX,XX @@
32
@@ -XXX,XX +XXX,XX @@
46
&2scalar qd qn rm size
33
#include "hw/usb/hcd-ehci.h"
47
&1imm qd imm cmode op
34
#include "hw/rtc/allwinner-rtc.h"
48
&2shift qd qm shift size
35
#include "hw/misc/allwinner-a10-ccm.h"
49
+&vidup qd rn size imm
36
+#include "hw/misc/allwinner-a10-dramc.h"
50
+&viwdup qd rn rm size imm
37
51
38
#include "target/arm/cpu.h"
52
@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
39
#include "qom/object.h"
53
# Note that both Rn and Qd are 3 bits only (no D bit)
40
@@ -XXX,XX +XXX,XX @@ struct AwA10State {
54
@@ -XXX,XX +XXX,XX @@ VDUP 1110 1110 1 1 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=0
41
55
VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 1 1 0000 @vdup size=1
42
ARMCPU cpu;
56
VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=2
43
AwA10ClockCtlState ccm;
57
44
+ AwA10DramControllerState dramc;
58
+# Incrementing and decrementing dup
45
AwA10PITState timer;
59
+
46
AwA10PICState intc;
60
+# VIDUP, VDDUP format immediate: 1 << (immh:imml)
47
AwEmacState emac;
61
+%imm_vidup 7:1 0:1 !function=vidup_imm
48
diff --git a/include/hw/misc/allwinner-a10-dramc.h b/include/hw/misc/allwinner-a10-dramc.h
62
+
49
new file mode 100644
63
+# VIDUP, VDDUP registers: Rm bits [3:1] from insn, bit 0 is 1;
50
index XXXXXXX..XXXXXXX
64
+# Rn bits [3:1] from insn, bit 0 is 0
51
--- /dev/null
65
+%vidup_rm 1:3 !function=times_2_plus_1
52
+++ b/include/hw/misc/allwinner-a10-dramc.h
66
+%vidup_rn 17:3 !function=times_2
53
@@ -XXX,XX +XXX,XX @@
67
+
54
+/*
68
+@vidup .... .... . . size:2 .... .... .... .... .... \
55
+ * Allwinner A10 DRAM Controller emulation
69
+ qd=%qd imm=%imm_vidup rn=%vidup_rn &vidup
56
+ *
70
+@viwdup .... .... . . size:2 .... .... .... .... .... \
57
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
71
+ qd=%qd imm=%imm_vidup rm=%vidup_rm rn=%vidup_rn &viwdup
58
+ *
72
+{
59
+ * This file is derived from Allwinner H3 DRAMC,
73
+ VIDUP 1110 1110 0 . .. ... 1 ... 0 1111 . 110 111 . @vidup
60
+ * by Niek Linnenbank.
74
+ VIWDUP 1110 1110 0 . .. ... 1 ... 0 1111 . 110 ... . @viwdup
61
+ *
75
+}
62
+ * This program is free software: you can redistribute it and/or modify
76
+{
63
+ * it under the terms of the GNU General Public License as published by
77
+ VDDUP 1110 1110 0 . .. ... 1 ... 1 1111 . 110 111 . @vidup
64
+ * the Free Software Foundation, either version 2 of the License, or
78
+ VDWDUP 1110 1110 0 . .. ... 1 ... 1 1111 . 110 ... . @viwdup
65
+ * (at your option) any later version.
79
+}
66
+ *
80
+
67
+ * This program is distributed in the hope that it will be useful,
81
# multiply-add long dual accumulate
68
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
82
# rdahi: bits [3:1] from insn, bit 0 is 1
69
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
83
# rdalo: bits [3:1] from insn, bit 0 is 0
70
+ * GNU General Public License for more details.
84
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
71
+ *
85
index XXXXXXX..XXXXXXX 100644
72
+ * You should have received a copy of the GNU General Public License
86
--- a/target/arm/mve_helper.c
73
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
87
+++ b/target/arm/mve_helper.c
74
+ */
88
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(mve_sqrshr)(CPUARMState *env, uint32_t n, uint32_t shift)
75
+
89
{
76
+#ifndef HW_MISC_ALLWINNER_A10_DRAMC_H
90
return do_sqrshl_bhs(n, -(int8_t)shift, 32, true, &env->QF);
77
+#define HW_MISC_ALLWINNER_A10_DRAMC_H
91
}
78
+
92
+
79
+#include "qom/object.h"
93
+#define DO_VIDUP(OP, ESIZE, TYPE, FN) \
80
+#include "hw/sysbus.h"
94
+ uint32_t HELPER(mve_##OP)(CPUARMState *env, void *vd, \
81
+#include "hw/register.h"
95
+ uint32_t offset, uint32_t imm) \
82
+
96
+ { \
83
+/**
97
+ TYPE *d = vd; \
84
+ * @name Constants
98
+ uint16_t mask = mve_element_mask(env); \
85
+ * @{
99
+ unsigned e; \
86
+ */
100
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
87
+
101
+ mergemask(&d[H##ESIZE(e)], offset, mask); \
88
+/** Size of register I/O address space used by DRAMC device */
102
+ offset = FN(offset, imm); \
89
+#define AW_A10_DRAMC_IOSIZE (0x1000)
103
+ } \
90
+
104
+ mve_advance_vpt(env); \
91
+/** Total number of known registers */
105
+ return offset; \
92
+#define AW_A10_DRAMC_REGS_NUM (AW_A10_DRAMC_IOSIZE / sizeof(uint32_t))
93
+
94
+/** @} */
95
+
96
+/**
97
+ * @name Object model
98
+ * @{
99
+ */
100
+
101
+#define TYPE_AW_A10_DRAMC "allwinner-a10-dramc"
102
+OBJECT_DECLARE_SIMPLE_TYPE(AwA10DramControllerState, AW_A10_DRAMC)
103
+
104
+/** @} */
105
+
106
+/**
107
+ * Allwinner A10 DRAMC object instance state.
108
+ */
109
+struct AwA10DramControllerState {
110
+ /*< private >*/
111
+ SysBusDevice parent_obj;
112
+ /*< public >*/
113
+
114
+ /** Maps I/O registers in physical memory */
115
+ MemoryRegion iomem;
116
+
117
+ /** Array of hardware registers */
118
+ uint32_t regs[AW_A10_DRAMC_REGS_NUM];
119
+};
120
+
121
+#endif /* HW_MISC_ALLWINNER_A10_DRAMC_H */
122
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
123
index XXXXXXX..XXXXXXX 100644
124
--- a/hw/arm/allwinner-a10.c
125
+++ b/hw/arm/allwinner-a10.c
126
@@ -XXX,XX +XXX,XX @@
127
#include "hw/boards.h"
128
#include "hw/usb/hcd-ohci.h"
129
130
+#define AW_A10_DRAMC_BASE 0x01c01000
131
#define AW_A10_MMC0_BASE 0x01c0f000
132
#define AW_A10_CCM_BASE 0x01c20000
133
#define AW_A10_PIC_REG_BASE 0x01c20400
134
@@ -XXX,XX +XXX,XX @@ static void aw_a10_init(Object *obj)
135
136
object_initialize_child(obj, "ccm", &s->ccm, TYPE_AW_A10_CCM);
137
138
+ object_initialize_child(obj, "dramc", &s->dramc, TYPE_AW_A10_DRAMC);
139
+
140
object_initialize_child(obj, "emac", &s->emac, TYPE_AW_EMAC);
141
142
object_initialize_child(obj, "sata", &s->sata, TYPE_ALLWINNER_AHCI);
143
@@ -XXX,XX +XXX,XX @@ static void aw_a10_realize(DeviceState *dev, Error **errp)
144
sysbus_realize(SYS_BUS_DEVICE(&s->ccm), &error_fatal);
145
sysbus_mmio_map(SYS_BUS_DEVICE(&s->ccm), 0, AW_A10_CCM_BASE);
146
147
+ /* DRAM Control Module */
148
+ sysbus_realize(SYS_BUS_DEVICE(&s->dramc), &error_fatal);
149
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->dramc), 0, AW_A10_DRAMC_BASE);
150
+
151
/* FIXME use qdev NIC properties instead of nd_table[] */
152
if (nd_table[0].used) {
153
qemu_check_nic_model(&nd_table[0], TYPE_AW_EMAC);
154
diff --git a/hw/misc/allwinner-a10-dramc.c b/hw/misc/allwinner-a10-dramc.c
155
new file mode 100644
156
index XXXXXXX..XXXXXXX
157
--- /dev/null
158
+++ b/hw/misc/allwinner-a10-dramc.c
159
@@ -XXX,XX +XXX,XX @@
160
+/*
161
+ * Allwinner A10 DRAM Controller emulation
162
+ *
163
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
164
+ *
165
+ * This file is derived from Allwinner H3 DRAMC,
166
+ * by Niek Linnenbank.
167
+ *
168
+ * This program is free software: you can redistribute it and/or modify
169
+ * it under the terms of the GNU General Public License as published by
170
+ * the Free Software Foundation, either version 2 of the License, or
171
+ * (at your option) any later version.
172
+ *
173
+ * This program is distributed in the hope that it will be useful,
174
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
175
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
176
+ * GNU General Public License for more details.
177
+ *
178
+ * You should have received a copy of the GNU General Public License
179
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
180
+ */
181
+
182
+#include "qemu/osdep.h"
183
+#include "qemu/units.h"
184
+#include "hw/sysbus.h"
185
+#include "migration/vmstate.h"
186
+#include "qemu/log.h"
187
+#include "qemu/module.h"
188
+#include "hw/misc/allwinner-a10-dramc.h"
189
+
190
+/* DRAMC register offsets */
191
+enum {
192
+ REG_SDR_CCR = 0x0000,
193
+ REG_SDR_ZQCR0 = 0x00a8,
194
+ REG_SDR_ZQSR = 0x00b0
195
+};
196
+
197
+#define REG_INDEX(offset) (offset / sizeof(uint32_t))
198
+
199
+/* DRAMC register flags */
200
+enum {
201
+ REG_SDR_CCR_DATA_TRAINING = (1 << 30),
202
+ REG_SDR_CCR_DRAM_INIT = (1 << 31),
203
+};
204
+enum {
205
+ REG_SDR_ZQSR_ZCAL = (1 << 31),
206
+};
207
+
208
+/* DRAMC register reset values */
209
+enum {
210
+ REG_SDR_CCR_RESET = 0x80020000,
211
+ REG_SDR_ZQCR0_RESET = 0x07b00000,
212
+ REG_SDR_ZQSR_RESET = 0x80000000
213
+};
214
+
215
+static uint64_t allwinner_a10_dramc_read(void *opaque, hwaddr offset,
216
+ unsigned size)
217
+{
218
+ const AwA10DramControllerState *s = AW_A10_DRAMC(opaque);
219
+ const uint32_t idx = REG_INDEX(offset);
220
+
221
+ switch (offset) {
222
+ case REG_SDR_CCR:
223
+ case REG_SDR_ZQCR0:
224
+ case REG_SDR_ZQSR:
225
+ break;
226
+ case 0x2e4 ... AW_A10_DRAMC_IOSIZE:
227
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
228
+ __func__, (uint32_t)offset);
229
+ return 0;
230
+ default:
231
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented read offset 0x%04x\n",
232
+ __func__, (uint32_t)offset);
233
+ return 0;
106
+ }
234
+ }
107
+
235
+
108
+#define DO_VIWDUP(OP, ESIZE, TYPE, FN) \
236
+ return s->regs[idx];
109
+ uint32_t HELPER(mve_##OP)(CPUARMState *env, void *vd, \
237
+}
110
+ uint32_t offset, uint32_t wrap, \
238
+
111
+ uint32_t imm) \
239
+static void allwinner_a10_dramc_write(void *opaque, hwaddr offset,
112
+ { \
240
+ uint64_t val, unsigned size)
113
+ TYPE *d = vd; \
241
+{
114
+ uint16_t mask = mve_element_mask(env); \
242
+ AwA10DramControllerState *s = AW_A10_DRAMC(opaque);
115
+ unsigned e; \
243
+ const uint32_t idx = REG_INDEX(offset);
116
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
244
+
117
+ mergemask(&d[H##ESIZE(e)], offset, mask); \
245
+ switch (offset) {
118
+ offset = FN(offset, wrap, imm); \
246
+ case REG_SDR_CCR:
119
+ } \
247
+ if (val & REG_SDR_CCR_DRAM_INIT) {
120
+ mve_advance_vpt(env); \
248
+ /* Clear DRAM_INIT to indicate process is done. */
121
+ return offset; \
249
+ val &= ~REG_SDR_CCR_DRAM_INIT;
250
+ }
251
+ if (val & REG_SDR_CCR_DATA_TRAINING) {
252
+ /* Clear DATA_TRAINING to indicate process is done. */
253
+ val &= ~REG_SDR_CCR_DATA_TRAINING;
254
+ }
255
+ break;
256
+ case REG_SDR_ZQCR0:
257
+ /* Set ZCAL in ZQSR to indicate calibration is done. */
258
+ s->regs[REG_INDEX(REG_SDR_ZQSR)] |= REG_SDR_ZQSR_ZCAL;
259
+ break;
260
+ case 0x2e4 ... AW_A10_DRAMC_IOSIZE:
261
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
262
+ __func__, (uint32_t)offset);
263
+ break;
264
+ default:
265
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented write offset 0x%04x\n",
266
+ __func__, (uint32_t)offset);
267
+ break;
122
+ }
268
+ }
123
+
269
+
124
+#define DO_VIDUP_ALL(OP, FN) \
270
+ s->regs[idx] = (uint32_t) val;
125
+ DO_VIDUP(OP##b, 1, int8_t, FN) \
271
+}
126
+ DO_VIDUP(OP##h, 2, int16_t, FN) \
272
+
127
+ DO_VIDUP(OP##w, 4, int32_t, FN)
273
+static const MemoryRegionOps allwinner_a10_dramc_ops = {
128
+
274
+ .read = allwinner_a10_dramc_read,
129
+#define DO_VIWDUP_ALL(OP, FN) \
275
+ .write = allwinner_a10_dramc_write,
130
+ DO_VIWDUP(OP##b, 1, int8_t, FN) \
276
+ .endianness = DEVICE_NATIVE_ENDIAN,
131
+ DO_VIWDUP(OP##h, 2, int16_t, FN) \
277
+ .valid = {
132
+ DO_VIWDUP(OP##w, 4, int32_t, FN)
278
+ .min_access_size = 4,
133
+
279
+ .max_access_size = 4,
134
+static uint32_t do_add_wrap(uint32_t offset, uint32_t wrap, uint32_t imm)
280
+ },
135
+{
281
+ .impl.min_access_size = 4,
136
+ offset += imm;
282
+};
137
+ if (offset == wrap) {
283
+
138
+ offset = 0;
284
+static void allwinner_a10_dramc_reset_enter(Object *obj, ResetType type)
285
+{
286
+ AwA10DramControllerState *s = AW_A10_DRAMC(obj);
287
+
288
+ /* Set default values for registers */
289
+ s->regs[REG_INDEX(REG_SDR_CCR)] = REG_SDR_CCR_RESET;
290
+ s->regs[REG_INDEX(REG_SDR_ZQCR0)] = REG_SDR_ZQCR0_RESET;
291
+ s->regs[REG_INDEX(REG_SDR_ZQSR)] = REG_SDR_ZQSR_RESET;
292
+}
293
+
294
+static void allwinner_a10_dramc_init(Object *obj)
295
+{
296
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
297
+ AwA10DramControllerState *s = AW_A10_DRAMC(obj);
298
+
299
+ /* Memory mapping */
300
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_a10_dramc_ops, s,
301
+ TYPE_AW_A10_DRAMC, AW_A10_DRAMC_IOSIZE);
302
+ sysbus_init_mmio(sbd, &s->iomem);
303
+}
304
+
305
+static const VMStateDescription allwinner_a10_dramc_vmstate = {
306
+ .name = "allwinner-a10-dramc",
307
+ .version_id = 1,
308
+ .minimum_version_id = 1,
309
+ .fields = (VMStateField[]) {
310
+ VMSTATE_UINT32_ARRAY(regs, AwA10DramControllerState,
311
+ AW_A10_DRAMC_REGS_NUM),
312
+ VMSTATE_END_OF_LIST()
139
+ }
313
+ }
140
+ return offset;
314
+};
141
+}
315
+
142
+
316
+static void allwinner_a10_dramc_class_init(ObjectClass *klass, void *data)
143
+static uint32_t do_sub_wrap(uint32_t offset, uint32_t wrap, uint32_t imm)
317
+{
144
+{
318
+ DeviceClass *dc = DEVICE_CLASS(klass);
145
+ if (offset == 0) {
319
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
146
+ offset = wrap;
320
+
147
+ }
321
+ rc->phases.enter = allwinner_a10_dramc_reset_enter;
148
+ offset -= imm;
322
+ dc->vmsd = &allwinner_a10_dramc_vmstate;
149
+ return offset;
323
+}
150
+}
324
+
151
+
325
+static const TypeInfo allwinner_a10_dramc_info = {
152
+DO_VIDUP_ALL(vidup, DO_ADD)
326
+ .name = TYPE_AW_A10_DRAMC,
153
+DO_VIWDUP_ALL(viwdup, do_add_wrap)
327
+ .parent = TYPE_SYS_BUS_DEVICE,
154
+DO_VIWDUP_ALL(vdwdup, do_sub_wrap)
328
+ .instance_init = allwinner_a10_dramc_init,
155
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
329
+ .instance_size = sizeof(AwA10DramControllerState),
156
index XXXXXXX..XXXXXXX 100644
330
+ .class_init = allwinner_a10_dramc_class_init,
157
--- a/target/arm/translate-mve.c
331
+};
158
+++ b/target/arm/translate-mve.c
332
+
159
@@ -XXX,XX +XXX,XX @@
333
+static void allwinner_a10_dramc_register(void)
160
#include "translate.h"
334
+{
161
#include "translate-a32.h"
335
+ type_register_static(&allwinner_a10_dramc_info);
162
336
+}
163
+static inline int vidup_imm(DisasContext *s, int x)
337
+
164
+{
338
+type_init(allwinner_a10_dramc_register)
165
+ return 1 << x;
339
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
166
+}
340
index XXXXXXX..XXXXXXX 100644
167
+
341
--- a/hw/arm/Kconfig
168
/* Include the generated decoder */
342
+++ b/hw/arm/Kconfig
169
#include "decode-mve.c.inc"
343
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10
170
344
select ALLWINNER_A10_PIT
171
@@ -XXX,XX +XXX,XX @@ typedef void MVEGenTwoOpShiftFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
345
select ALLWINNER_A10_PIC
172
typedef void MVEGenDualAccOpFn(TCGv_i64, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i64);
346
select ALLWINNER_A10_CCM
173
typedef void MVEGenVADDVFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32);
347
+ select ALLWINNER_A10_DRAMC
174
typedef void MVEGenOneOpImmFn(TCGv_ptr, TCGv_ptr, TCGv_i64);
348
select ALLWINNER_EMAC
175
+typedef void MVEGenVIDUPFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32, TCGv_i32);
349
select SERIAL
176
+typedef void MVEGenVIWDUPFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32, TCGv_i32, TCGv_i32);
350
select UNIMP
177
351
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
178
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
352
index XXXXXXX..XXXXXXX 100644
179
static inline long mve_qreg_offset(unsigned reg)
353
--- a/hw/misc/Kconfig
180
@@ -XXX,XX +XXX,XX @@ static bool trans_VSHLC(DisasContext *s, arg_VSHLC *a)
354
+++ b/hw/misc/Kconfig
181
mve_update_eci(s);
355
@@ -XXX,XX +XXX,XX @@ config LASI
182
return true;
356
config ALLWINNER_A10_CCM
183
}
357
bool
184
+
358
185
+static bool do_vidup(DisasContext *s, arg_vidup *a, MVEGenVIDUPFn *fn)
359
+config ALLWINNER_A10_DRAMC
186
+{
360
+ bool
187
+ TCGv_ptr qd;
361
+
188
+ TCGv_i32 rn;
362
source macio/Kconfig
189
+
363
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
190
+ /*
364
index XXXXXXX..XXXXXXX 100644
191
+ * Vector increment/decrement with wrap and duplicate (VIDUP, VDDUP).
365
--- a/hw/misc/meson.build
192
+ * This fills the vector with elements of successively increasing
366
+++ b/hw/misc/meson.build
193
+ * or decreasing values, starting from Rn.
367
@@ -XXX,XX +XXX,XX @@ subdir('macio')
194
+ */
368
softmmu_ss.add(when: 'CONFIG_IVSHMEM_DEVICE', if_true: files('ivshmem.c'))
195
+ if (!dc_isar_feature(aa32_mve, s) || !mve_check_qreg_bank(s, a->qd)) {
369
196
+ return false;
370
softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10_CCM', if_true: files('allwinner-a10-ccm.c'))
197
+ }
371
+softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10_DRAMC', if_true: files('allwinner-a10-dramc.c'))
198
+ if (a->size == MO_64) {
372
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-ccu.c'))
199
+ /* size 0b11 is another encoding */
373
specific_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-cpucfg.c'))
200
+ return false;
374
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-dramc.c'))
201
+ }
202
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
203
+ return true;
204
+ }
205
+
206
+ qd = mve_qreg_ptr(a->qd);
207
+ rn = load_reg(s, a->rn);
208
+ fn(rn, cpu_env, qd, rn, tcg_constant_i32(a->imm));
209
+ store_reg(s, a->rn, rn);
210
+ tcg_temp_free_ptr(qd);
211
+ mve_update_eci(s);
212
+ return true;
213
+}
214
+
215
+static bool do_viwdup(DisasContext *s, arg_viwdup *a, MVEGenVIWDUPFn *fn)
216
+{
217
+ TCGv_ptr qd;
218
+ TCGv_i32 rn, rm;
219
+
220
+ /*
221
+ * Vector increment/decrement with wrap and duplicate (VIWDUp, VDWDUP)
222
+ * This fills the vector with elements of successively increasing
223
+ * or decreasing values, starting from Rn. Rm specifies a point where
224
+ * the count wraps back around to 0. The updated offset is written back
225
+ * to Rn.
226
+ */
227
+ if (!dc_isar_feature(aa32_mve, s) || !mve_check_qreg_bank(s, a->qd)) {
228
+ return false;
229
+ }
230
+ if (!fn || a->rm == 13 || a->rm == 15) {
231
+ /*
232
+ * size 0b11 is another encoding; Rm == 13 is UNPREDICTABLE;
233
+ * Rm == 13 is VIWDUP, VDWDUP.
234
+ */
235
+ return false;
236
+ }
237
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
238
+ return true;
239
+ }
240
+
241
+ qd = mve_qreg_ptr(a->qd);
242
+ rn = load_reg(s, a->rn);
243
+ rm = load_reg(s, a->rm);
244
+ fn(rn, cpu_env, qd, rn, rm, tcg_constant_i32(a->imm));
245
+ store_reg(s, a->rn, rn);
246
+ tcg_temp_free_ptr(qd);
247
+ tcg_temp_free_i32(rm);
248
+ mve_update_eci(s);
249
+ return true;
250
+}
251
+
252
+static bool trans_VIDUP(DisasContext *s, arg_vidup *a)
253
+{
254
+ static MVEGenVIDUPFn * const fns[] = {
255
+ gen_helper_mve_vidupb,
256
+ gen_helper_mve_viduph,
257
+ gen_helper_mve_vidupw,
258
+ NULL,
259
+ };
260
+ return do_vidup(s, a, fns[a->size]);
261
+}
262
+
263
+static bool trans_VDDUP(DisasContext *s, arg_vidup *a)
264
+{
265
+ static MVEGenVIDUPFn * const fns[] = {
266
+ gen_helper_mve_vidupb,
267
+ gen_helper_mve_viduph,
268
+ gen_helper_mve_vidupw,
269
+ NULL,
270
+ };
271
+ /* VDDUP is just like VIDUP but with a negative immediate */
272
+ a->imm = -a->imm;
273
+ return do_vidup(s, a, fns[a->size]);
274
+}
275
+
276
+static bool trans_VIWDUP(DisasContext *s, arg_viwdup *a)
277
+{
278
+ static MVEGenVIWDUPFn * const fns[] = {
279
+ gen_helper_mve_viwdupb,
280
+ gen_helper_mve_viwduph,
281
+ gen_helper_mve_viwdupw,
282
+ NULL,
283
+ };
284
+ return do_viwdup(s, a, fns[a->size]);
285
+}
286
+
287
+static bool trans_VDWDUP(DisasContext *s, arg_viwdup *a)
288
+{
289
+ static MVEGenVIWDUPFn * const fns[] = {
290
+ gen_helper_mve_vdwdupb,
291
+ gen_helper_mve_vdwduph,
292
+ gen_helper_mve_vdwdupw,
293
+ NULL,
294
+ };
295
+ return do_viwdup(s, a, fns[a->size]);
296
+}
297
--
375
--
298
2.20.1
376
2.34.1
299
300
diff view generated by jsdifflib
1
Unlike A-profile, for M-profile the UDIV and SDIV insns can be
1
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
2
configured to raise an exception on division by zero, using the CCR
3
DIV_0_TRP bit.
4
2
5
Implement support for setting this bit by making the helper functions
3
This patch implements Allwinner TWI/I2C controller emulation. Only
6
raise the appropriate exception.
4
master-mode functionality is implemented.
7
5
6
The SPL boot for Cubieboard expects AXP209 PMIC on TWI0/I2C0 bus, so this is
7
first part enabling the TWI/I2C bus operation.
8
9
Since both Allwinner A10 and H3 use the same module, it is added for
10
both boards.
11
12
Docs are also updated for Cubieboard and Orangepi-PC board to indicate
13
I2C availability.
14
15
Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
16
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
17
Message-id: 20221226220303.14420-4-strahinja.p.jankovic@gmail.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210730151636.17254-3-peter.maydell@linaro.org
11
---
19
---
12
target/arm/cpu.h | 1 +
20
docs/system/arm/cubieboard.rst | 1 +
13
target/arm/helper.h | 4 ++--
21
docs/system/arm/orangepi.rst | 1 +
14
target/arm/helper.c | 19 +++++++++++++++++--
22
include/hw/arm/allwinner-a10.h | 2 +
15
target/arm/m_helper.c | 4 ++++
23
include/hw/arm/allwinner-h3.h | 3 +
16
target/arm/translate.c | 4 ++--
24
include/hw/i2c/allwinner-i2c.h | 55 ++++
17
5 files changed, 26 insertions(+), 6 deletions(-)
25
hw/arm/allwinner-a10.c | 8 +
26
hw/arm/allwinner-h3.c | 11 +-
27
hw/i2c/allwinner-i2c.c | 459 +++++++++++++++++++++++++++++++++
28
hw/arm/Kconfig | 2 +
29
hw/i2c/Kconfig | 4 +
30
hw/i2c/meson.build | 1 +
31
hw/i2c/trace-events | 5 +
32
12 files changed, 551 insertions(+), 1 deletion(-)
33
create mode 100644 include/hw/i2c/allwinner-i2c.h
34
create mode 100644 hw/i2c/allwinner-i2c.c
18
35
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
36
diff --git a/docs/system/arm/cubieboard.rst b/docs/system/arm/cubieboard.rst
20
index XXXXXXX..XXXXXXX 100644
37
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.h
38
--- a/docs/system/arm/cubieboard.rst
22
+++ b/target/arm/cpu.h
39
+++ b/docs/system/arm/cubieboard.rst
40
@@ -XXX,XX +XXX,XX @@ Emulated devices:
41
- SDHCI
42
- USB controller
43
- SATA controller
44
+- TWI (I2C) controller
45
diff --git a/docs/system/arm/orangepi.rst b/docs/system/arm/orangepi.rst
46
index XXXXXXX..XXXXXXX 100644
47
--- a/docs/system/arm/orangepi.rst
48
+++ b/docs/system/arm/orangepi.rst
49
@@ -XXX,XX +XXX,XX @@ The Orange Pi PC machine supports the following devices:
50
* Clock Control Unit
51
* System Control module
52
* Security Identifier device
53
+ * TWI (I2C)
54
55
Limitations
56
"""""""""""
57
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
58
index XXXXXXX..XXXXXXX 100644
59
--- a/include/hw/arm/allwinner-a10.h
60
+++ b/include/hw/arm/allwinner-a10.h
23
@@ -XXX,XX +XXX,XX @@
61
@@ -XXX,XX +XXX,XX @@
24
#define EXCP_LAZYFP 20 /* v7M fault during lazy FP stacking */
62
#include "hw/rtc/allwinner-rtc.h"
25
#define EXCP_LSERR 21 /* v8M LSERR SecureFault */
63
#include "hw/misc/allwinner-a10-ccm.h"
26
#define EXCP_UNALIGNED 22 /* v7M UNALIGNED UsageFault */
64
#include "hw/misc/allwinner-a10-dramc.h"
27
+#define EXCP_DIVBYZERO 23 /* v7M DIVBYZERO UsageFault */
65
+#include "hw/i2c/allwinner-i2c.h"
28
/* NB: add new EXCP_ defines to the array in arm_log_exception() too */
66
29
67
#include "target/arm/cpu.h"
30
#define ARMV7M_EXCP_RESET 1
68
#include "qom/object.h"
31
diff --git a/target/arm/helper.h b/target/arm/helper.h
69
@@ -XXX,XX +XXX,XX @@ struct AwA10State {
32
index XXXXXXX..XXXXXXX 100644
70
AwEmacState emac;
33
--- a/target/arm/helper.h
71
AllwinnerAHCIState sata;
34
+++ b/target/arm/helper.h
72
AwSdHostState mmc0;
35
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(add_saturate, i32, env, i32, i32)
73
+ AWI2CState i2c0;
36
DEF_HELPER_3(sub_saturate, i32, env, i32, i32)
74
AwRtcState rtc;
37
DEF_HELPER_3(add_usaturate, i32, env, i32, i32)
75
MemoryRegion sram_a;
38
DEF_HELPER_3(sub_usaturate, i32, env, i32, i32)
76
EHCISysBusState ehci[AW_A10_NUM_USB];
39
-DEF_HELPER_FLAGS_2(sdiv, TCG_CALL_NO_RWG_SE, s32, s32, s32)
77
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
40
-DEF_HELPER_FLAGS_2(udiv, TCG_CALL_NO_RWG_SE, i32, i32, i32)
78
index XXXXXXX..XXXXXXX 100644
41
+DEF_HELPER_FLAGS_3(sdiv, TCG_CALL_NO_RWG, s32, env, s32, s32)
79
--- a/include/hw/arm/allwinner-h3.h
42
+DEF_HELPER_FLAGS_3(udiv, TCG_CALL_NO_RWG, i32, env, i32, i32)
80
+++ b/include/hw/arm/allwinner-h3.h
43
DEF_HELPER_FLAGS_1(rbit, TCG_CALL_NO_RWG_SE, i32, i32)
81
@@ -XXX,XX +XXX,XX @@
44
82
#include "hw/sd/allwinner-sdhost.h"
45
#define PAS_OP(pfx) \
83
#include "hw/net/allwinner-sun8i-emac.h"
46
diff --git a/target/arm/helper.c b/target/arm/helper.c
84
#include "hw/rtc/allwinner-rtc.h"
47
index XXXXXXX..XXXXXXX 100644
85
+#include "hw/i2c/allwinner-i2c.h"
48
--- a/target/arm/helper.c
86
#include "target/arm/cpu.h"
49
+++ b/target/arm/helper.c
87
#include "sysemu/block-backend.h"
50
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(sxtb16)(uint32_t x)
88
51
return res;
89
@@ -XXX,XX +XXX,XX @@ enum {
90
AW_H3_DEV_UART2,
91
AW_H3_DEV_UART3,
92
AW_H3_DEV_EMAC,
93
+ AW_H3_DEV_TWI0,
94
AW_H3_DEV_DRAMCOM,
95
AW_H3_DEV_DRAMCTL,
96
AW_H3_DEV_DRAMPHY,
97
@@ -XXX,XX +XXX,XX @@ struct AwH3State {
98
AwH3SysCtrlState sysctrl;
99
AwSidState sid;
100
AwSdHostState mmc0;
101
+ AWI2CState i2c0;
102
AwSun8iEmacState emac;
103
AwRtcState rtc;
104
GICState gic;
105
diff --git a/include/hw/i2c/allwinner-i2c.h b/include/hw/i2c/allwinner-i2c.h
106
new file mode 100644
107
index XXXXXXX..XXXXXXX
108
--- /dev/null
109
+++ b/include/hw/i2c/allwinner-i2c.h
110
@@ -XXX,XX +XXX,XX @@
111
+/*
112
+ * Allwinner I2C Bus Serial Interface registers definition
113
+ *
114
+ * Copyright (C) 2022 Strahinja Jankovic. <strahinja.p.jankovic@gmail.com>
115
+ *
116
+ * This file is derived from IMX I2C controller,
117
+ * by Jean-Christophe DUBOIS .
118
+ *
119
+ * This program is free software; you can redistribute it and/or modify it
120
+ * under the terms of the GNU General Public License as published by the
121
+ * Free Software Foundation; either version 2 of the License, or
122
+ * (at your option) any later version.
123
+ *
124
+ * This program is distributed in the hope that it will be useful, but WITHOUT
125
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
126
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
127
+ * for more details.
128
+ *
129
+ * You should have received a copy of the GNU General Public License along
130
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
131
+ *
132
+ */
133
+
134
+#ifndef ALLWINNER_I2C_H
135
+#define ALLWINNER_I2C_H
136
+
137
+#include "hw/sysbus.h"
138
+#include "qom/object.h"
139
+
140
+#define TYPE_AW_I2C "allwinner.i2c"
141
+OBJECT_DECLARE_SIMPLE_TYPE(AWI2CState, AW_I2C)
142
+
143
+#define AW_I2C_MEM_SIZE 0x24
144
+
145
+struct AWI2CState {
146
+ /*< private >*/
147
+ SysBusDevice parent_obj;
148
+
149
+ /*< public >*/
150
+ MemoryRegion iomem;
151
+ I2CBus *bus;
152
+ qemu_irq irq;
153
+
154
+ uint8_t addr;
155
+ uint8_t xaddr;
156
+ uint8_t data;
157
+ uint8_t cntr;
158
+ uint8_t stat;
159
+ uint8_t ccr;
160
+ uint8_t srst;
161
+ uint8_t efr;
162
+ uint8_t lcr;
163
+};
164
+
165
+#endif /* ALLWINNER_I2C_H */
166
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
167
index XXXXXXX..XXXXXXX 100644
168
--- a/hw/arm/allwinner-a10.c
169
+++ b/hw/arm/allwinner-a10.c
170
@@ -XXX,XX +XXX,XX @@
171
#define AW_A10_OHCI_BASE 0x01c14400
172
#define AW_A10_SATA_BASE 0x01c18000
173
#define AW_A10_RTC_BASE 0x01c20d00
174
+#define AW_A10_I2C0_BASE 0x01c2ac00
175
176
static void aw_a10_init(Object *obj)
177
{
178
@@ -XXX,XX +XXX,XX @@ static void aw_a10_init(Object *obj)
179
180
object_initialize_child(obj, "sata", &s->sata, TYPE_ALLWINNER_AHCI);
181
182
+ object_initialize_child(obj, "i2c0", &s->i2c0, TYPE_AW_I2C);
183
+
184
if (machine_usb(current_machine)) {
185
int i;
186
187
@@ -XXX,XX +XXX,XX @@ static void aw_a10_realize(DeviceState *dev, Error **errp)
188
/* RTC */
189
sysbus_realize(SYS_BUS_DEVICE(&s->rtc), &error_fatal);
190
sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->rtc), 0, AW_A10_RTC_BASE, 10);
191
+
192
+ /* I2C */
193
+ sysbus_realize(SYS_BUS_DEVICE(&s->i2c0), &error_fatal);
194
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c0), 0, AW_A10_I2C0_BASE);
195
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c0), 0, qdev_get_gpio_in(dev, 7));
52
}
196
}
53
197
54
+static void handle_possible_div0_trap(CPUARMState *env, uintptr_t ra)
198
static void aw_a10_class_init(ObjectClass *oc, void *data)
199
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
200
index XXXXXXX..XXXXXXX 100644
201
--- a/hw/arm/allwinner-h3.c
202
+++ b/hw/arm/allwinner-h3.c
203
@@ -XXX,XX +XXX,XX @@ const hwaddr allwinner_h3_memmap[] = {
204
[AW_H3_DEV_UART1] = 0x01c28400,
205
[AW_H3_DEV_UART2] = 0x01c28800,
206
[AW_H3_DEV_UART3] = 0x01c28c00,
207
+ [AW_H3_DEV_TWI0] = 0x01c2ac00,
208
[AW_H3_DEV_EMAC] = 0x01c30000,
209
[AW_H3_DEV_DRAMCOM] = 0x01c62000,
210
[AW_H3_DEV_DRAMCTL] = 0x01c63000,
211
@@ -XXX,XX +XXX,XX @@ struct AwH3Unimplemented {
212
{ "uart1", 0x01c28400, 1 * KiB },
213
{ "uart2", 0x01c28800, 1 * KiB },
214
{ "uart3", 0x01c28c00, 1 * KiB },
215
- { "twi0", 0x01c2ac00, 1 * KiB },
216
{ "twi1", 0x01c2b000, 1 * KiB },
217
{ "twi2", 0x01c2b400, 1 * KiB },
218
{ "scr", 0x01c2c400, 1 * KiB },
219
@@ -XXX,XX +XXX,XX @@ enum {
220
AW_H3_GIC_SPI_UART1 = 1,
221
AW_H3_GIC_SPI_UART2 = 2,
222
AW_H3_GIC_SPI_UART3 = 3,
223
+ AW_H3_GIC_SPI_TWI0 = 6,
224
AW_H3_GIC_SPI_TIMER0 = 18,
225
AW_H3_GIC_SPI_TIMER1 = 19,
226
AW_H3_GIC_SPI_MMC0 = 60,
227
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_init(Object *obj)
228
"ram-size");
229
230
object_initialize_child(obj, "rtc", &s->rtc, TYPE_AW_RTC_SUN6I);
231
+
232
+ object_initialize_child(obj, "twi0", &s->i2c0, TYPE_AW_I2C);
233
}
234
235
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
236
@@ -XXX,XX +XXX,XX @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
237
sysbus_realize(SYS_BUS_DEVICE(&s->rtc), &error_fatal);
238
sysbus_mmio_map(SYS_BUS_DEVICE(&s->rtc), 0, s->memmap[AW_H3_DEV_RTC]);
239
240
+ /* I2C */
241
+ sysbus_realize(SYS_BUS_DEVICE(&s->i2c0), &error_fatal);
242
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c0), 0, s->memmap[AW_H3_DEV_TWI0]);
243
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c0), 0,
244
+ qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_TWI0));
245
+
246
/* Unimplemented devices */
247
for (i = 0; i < ARRAY_SIZE(unimplemented); i++) {
248
create_unimplemented_device(unimplemented[i].device_name,
249
diff --git a/hw/i2c/allwinner-i2c.c b/hw/i2c/allwinner-i2c.c
250
new file mode 100644
251
index XXXXXXX..XXXXXXX
252
--- /dev/null
253
+++ b/hw/i2c/allwinner-i2c.c
254
@@ -XXX,XX +XXX,XX @@
255
+/*
256
+ * Allwinner I2C Bus Serial Interface Emulation
257
+ *
258
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
259
+ *
260
+ * This file is derived from IMX I2C controller,
261
+ * by Jean-Christophe DUBOIS .
262
+ *
263
+ * This program is free software; you can redistribute it and/or modify it
264
+ * under the terms of the GNU General Public License as published by the
265
+ * Free Software Foundation; either version 2 of the License, or
266
+ * (at your option) any later version.
267
+ *
268
+ * This program is distributed in the hope that it will be useful, but WITHOUT
269
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
270
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
271
+ * for more details.
272
+ *
273
+ * You should have received a copy of the GNU General Public License along
274
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
275
+ *
276
+ * SPDX-License-Identifier: MIT
277
+ */
278
+
279
+#include "qemu/osdep.h"
280
+#include "hw/i2c/allwinner-i2c.h"
281
+#include "hw/irq.h"
282
+#include "migration/vmstate.h"
283
+#include "hw/i2c/i2c.h"
284
+#include "qemu/log.h"
285
+#include "trace.h"
286
+#include "qemu/module.h"
287
+
288
+/* Allwinner I2C memory map */
289
+#define TWI_ADDR_REG 0x00 /* slave address register */
290
+#define TWI_XADDR_REG 0x04 /* extended slave address register */
291
+#define TWI_DATA_REG 0x08 /* data register */
292
+#define TWI_CNTR_REG 0x0c /* control register */
293
+#define TWI_STAT_REG 0x10 /* status register */
294
+#define TWI_CCR_REG 0x14 /* clock control register */
295
+#define TWI_SRST_REG 0x18 /* software reset register */
296
+#define TWI_EFR_REG 0x1c /* enhance feature register */
297
+#define TWI_LCR_REG 0x20 /* line control register */
298
+
299
+/* Used only in slave mode, do not set */
300
+#define TWI_ADDR_RESET 0
301
+#define TWI_XADDR_RESET 0
302
+
303
+/* Data register */
304
+#define TWI_DATA_MASK 0xFF
305
+#define TWI_DATA_RESET 0
306
+
307
+/* Control register */
308
+#define TWI_CNTR_INT_EN (1 << 7)
309
+#define TWI_CNTR_BUS_EN (1 << 6)
310
+#define TWI_CNTR_M_STA (1 << 5)
311
+#define TWI_CNTR_M_STP (1 << 4)
312
+#define TWI_CNTR_INT_FLAG (1 << 3)
313
+#define TWI_CNTR_A_ACK (1 << 2)
314
+#define TWI_CNTR_MASK 0xFC
315
+#define TWI_CNTR_RESET 0
316
+
317
+/* Status register */
318
+#define TWI_STAT_MASK 0xF8
319
+#define TWI_STAT_RESET 0xF8
320
+
321
+/* Clock register */
322
+#define TWI_CCR_CLK_M_MASK 0x78
323
+#define TWI_CCR_CLK_N_MASK 0x07
324
+#define TWI_CCR_MASK 0x7F
325
+#define TWI_CCR_RESET 0
326
+
327
+/* Soft reset */
328
+#define TWI_SRST_MASK 0x01
329
+#define TWI_SRST_RESET 0
330
+
331
+/* Enhance feature */
332
+#define TWI_EFR_MASK 0x03
333
+#define TWI_EFR_RESET 0
334
+
335
+/* Line control */
336
+#define TWI_LCR_SCL_STATE (1 << 5)
337
+#define TWI_LCR_SDA_STATE (1 << 4)
338
+#define TWI_LCR_SCL_CTL (1 << 3)
339
+#define TWI_LCR_SCL_CTL_EN (1 << 2)
340
+#define TWI_LCR_SDA_CTL (1 << 1)
341
+#define TWI_LCR_SDA_CTL_EN (1 << 0)
342
+#define TWI_LCR_MASK 0x3F
343
+#define TWI_LCR_RESET 0x3A
344
+
345
+/* Status value in STAT register is shifted by 3 bits */
346
+#define TWI_STAT_SHIFT 3
347
+#define STAT_FROM_STA(x) ((x) << TWI_STAT_SHIFT)
348
+#define STAT_TO_STA(x) ((x) >> TWI_STAT_SHIFT)
349
+
350
+enum {
351
+ STAT_BUS_ERROR = 0,
352
+ /* Master mode */
353
+ STAT_M_STA_TX,
354
+ STAT_M_RSTA_TX,
355
+ STAT_M_ADDR_WR_ACK,
356
+ STAT_M_ADDR_WR_NACK,
357
+ STAT_M_DATA_TX_ACK,
358
+ STAT_M_DATA_TX_NACK,
359
+ STAT_M_ARB_LOST,
360
+ STAT_M_ADDR_RD_ACK,
361
+ STAT_M_ADDR_RD_NACK,
362
+ STAT_M_DATA_RX_ACK,
363
+ STAT_M_DATA_RX_NACK,
364
+ /* Slave mode */
365
+ STAT_S_ADDR_WR_ACK,
366
+ STAT_S_ARB_LOST_AW_ACK,
367
+ STAT_S_GCA_ACK,
368
+ STAT_S_ARB_LOST_GCA_ACK,
369
+ STAT_S_DATA_RX_SA_ACK,
370
+ STAT_S_DATA_RX_SA_NACK,
371
+ STAT_S_DATA_RX_GCA_ACK,
372
+ STAT_S_DATA_RX_GCA_NACK,
373
+ STAT_S_STP_RSTA,
374
+ STAT_S_ADDR_RD_ACK,
375
+ STAT_S_ARB_LOST_AR_ACK,
376
+ STAT_S_DATA_TX_ACK,
377
+ STAT_S_DATA_TX_NACK,
378
+ STAT_S_LB_TX_ACK,
379
+ /* Master mode, 10-bit */
380
+ STAT_M_2ND_ADDR_WR_ACK,
381
+ STAT_M_2ND_ADDR_WR_NACK,
382
+ /* Idle */
383
+ STAT_IDLE = 0x1f
384
+} TWI_STAT_STA;
385
+
386
+static const char *allwinner_i2c_get_regname(unsigned offset)
387
+{
388
+ switch (offset) {
389
+ case TWI_ADDR_REG:
390
+ return "ADDR";
391
+ case TWI_XADDR_REG:
392
+ return "XADDR";
393
+ case TWI_DATA_REG:
394
+ return "DATA";
395
+ case TWI_CNTR_REG:
396
+ return "CNTR";
397
+ case TWI_STAT_REG:
398
+ return "STAT";
399
+ case TWI_CCR_REG:
400
+ return "CCR";
401
+ case TWI_SRST_REG:
402
+ return "SRST";
403
+ case TWI_EFR_REG:
404
+ return "EFR";
405
+ case TWI_LCR_REG:
406
+ return "LCR";
407
+ default:
408
+ return "[?]";
409
+ }
410
+}
411
+
412
+static inline bool allwinner_i2c_is_reset(AWI2CState *s)
413
+{
414
+ return s->srst & TWI_SRST_MASK;
415
+}
416
+
417
+static inline bool allwinner_i2c_bus_is_enabled(AWI2CState *s)
418
+{
419
+ return s->cntr & TWI_CNTR_BUS_EN;
420
+}
421
+
422
+static inline bool allwinner_i2c_interrupt_is_enabled(AWI2CState *s)
423
+{
424
+ return s->cntr & TWI_CNTR_INT_EN;
425
+}
426
+
427
+static void allwinner_i2c_reset_hold(Object *obj)
428
+{
429
+ AWI2CState *s = AW_I2C(obj);
430
+
431
+ if (STAT_TO_STA(s->stat) != STAT_IDLE) {
432
+ i2c_end_transfer(s->bus);
433
+ }
434
+
435
+ s->addr = TWI_ADDR_RESET;
436
+ s->xaddr = TWI_XADDR_RESET;
437
+ s->data = TWI_DATA_RESET;
438
+ s->cntr = TWI_CNTR_RESET;
439
+ s->stat = TWI_STAT_RESET;
440
+ s->ccr = TWI_CCR_RESET;
441
+ s->srst = TWI_SRST_RESET;
442
+ s->efr = TWI_EFR_RESET;
443
+ s->lcr = TWI_LCR_RESET;
444
+}
445
+
446
+static inline void allwinner_i2c_raise_interrupt(AWI2CState *s)
55
+{
447
+{
56
+ /*
448
+ /*
57
+ * Take a division-by-zero exception if necessary; otherwise return
449
+ * Raise an interrupt if the device is not reset and it is configured
58
+ * to get the usual non-trapping division behaviour (result of 0)
450
+ * to generate some interrupts.
59
+ */
451
+ */
60
+ if (arm_feature(env, ARM_FEATURE_M)
452
+ if (!allwinner_i2c_is_reset(s) && allwinner_i2c_bus_is_enabled(s)) {
61
+ && (env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_DIV_0_TRP_MASK)) {
453
+ if (STAT_TO_STA(s->stat) != STAT_IDLE) {
62
+ raise_exception_ra(env, EXCP_DIVBYZERO, 0, 1, ra);
454
+ s->cntr |= TWI_CNTR_INT_FLAG;
455
+ if (allwinner_i2c_interrupt_is_enabled(s)) {
456
+ qemu_irq_raise(s->irq);
457
+ }
458
+ }
63
+ }
459
+ }
64
+}
460
+}
65
+
461
+
66
uint32_t HELPER(uxtb16)(uint32_t x)
462
+static uint64_t allwinner_i2c_read(void *opaque, hwaddr offset,
67
{
463
+ unsigned size)
68
uint32_t res;
464
+{
69
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(uxtb16)(uint32_t x)
465
+ uint16_t value;
70
return res;
466
+ AWI2CState *s = AW_I2C(opaque);
71
}
467
+
72
468
+ switch (offset) {
73
-int32_t HELPER(sdiv)(int32_t num, int32_t den)
469
+ case TWI_ADDR_REG:
74
+int32_t HELPER(sdiv)(CPUARMState *env, int32_t num, int32_t den)
470
+ value = s->addr;
75
{
471
+ break;
76
if (den == 0) {
472
+ case TWI_XADDR_REG:
77
+ handle_possible_div0_trap(env, GETPC());
473
+ value = s->xaddr;
78
return 0;
474
+ break;
79
}
475
+ case TWI_DATA_REG:
80
if (num == INT_MIN && den == -1) {
476
+ if ((STAT_TO_STA(s->stat) == STAT_M_ADDR_RD_ACK) ||
81
@@ -XXX,XX +XXX,XX @@ int32_t HELPER(sdiv)(int32_t num, int32_t den)
477
+ (STAT_TO_STA(s->stat) == STAT_M_DATA_RX_ACK) ||
82
return num / den;
478
+ (STAT_TO_STA(s->stat) == STAT_M_DATA_RX_NACK)) {
83
}
479
+ /* Get the next byte */
84
480
+ s->data = i2c_recv(s->bus);
85
-uint32_t HELPER(udiv)(uint32_t num, uint32_t den)
481
+
86
+uint32_t HELPER(udiv)(CPUARMState *env, uint32_t num, uint32_t den)
482
+ if (s->cntr & TWI_CNTR_A_ACK) {
87
{
483
+ s->stat = STAT_FROM_STA(STAT_M_DATA_RX_ACK);
88
if (den == 0) {
484
+ } else {
89
+ handle_possible_div0_trap(env, GETPC());
485
+ s->stat = STAT_FROM_STA(STAT_M_DATA_RX_NACK);
90
return 0;
486
+ }
91
}
487
+ allwinner_i2c_raise_interrupt(s);
92
return num / den;
488
+ }
93
@@ -XXX,XX +XXX,XX @@ void arm_log_exception(int idx)
489
+ value = s->data;
94
[EXCP_LAZYFP] = "v7M exception during lazy FP stacking",
490
+ break;
95
[EXCP_LSERR] = "v8M LSERR UsageFault",
491
+ case TWI_CNTR_REG:
96
[EXCP_UNALIGNED] = "v7M UNALIGNED UsageFault",
492
+ value = s->cntr;
97
+ [EXCP_DIVBYZERO] = "v7M DIVBYZERO UsageFault",
493
+ break;
98
};
494
+ case TWI_STAT_REG:
99
495
+ value = s->stat;
100
if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
496
+ /*
101
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
497
+ * If polling when reading then change state to indicate data
102
index XXXXXXX..XXXXXXX 100644
498
+ * is available
103
--- a/target/arm/m_helper.c
499
+ */
104
+++ b/target/arm/m_helper.c
500
+ if (STAT_TO_STA(s->stat) == STAT_M_ADDR_RD_ACK) {
105
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
501
+ if (s->cntr & TWI_CNTR_A_ACK) {
106
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
502
+ s->stat = STAT_FROM_STA(STAT_M_DATA_RX_ACK);
107
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_UNALIGNED_MASK;
503
+ } else {
108
break;
504
+ s->stat = STAT_FROM_STA(STAT_M_DATA_RX_NACK);
109
+ case EXCP_DIVBYZERO:
505
+ }
110
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
506
+ allwinner_i2c_raise_interrupt(s);
111
+ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_DIVBYZERO_MASK;
507
+ }
112
+ break;
508
+ break;
113
case EXCP_SWI:
509
+ case TWI_CCR_REG:
114
/* The PC already points to the next instruction. */
510
+ value = s->ccr;
115
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC, env->v7m.secure);
511
+ break;
116
diff --git a/target/arm/translate.c b/target/arm/translate.c
512
+ case TWI_SRST_REG:
117
index XXXXXXX..XXXXXXX 100644
513
+ value = s->srst;
118
--- a/target/arm/translate.c
514
+ break;
119
+++ b/target/arm/translate.c
515
+ case TWI_EFR_REG:
120
@@ -XXX,XX +XXX,XX @@ static bool op_div(DisasContext *s, arg_rrr *a, bool u)
516
+ value = s->efr;
121
t1 = load_reg(s, a->rn);
517
+ break;
122
t2 = load_reg(s, a->rm);
518
+ case TWI_LCR_REG:
123
if (u) {
519
+ value = s->lcr;
124
- gen_helper_udiv(t1, t1, t2);
520
+ break;
125
+ gen_helper_udiv(t1, cpu_env, t1, t2);
521
+ default:
126
} else {
522
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
127
- gen_helper_sdiv(t1, t1, t2);
523
+ HWADDR_PRIx "\n", TYPE_AW_I2C, __func__, offset);
128
+ gen_helper_sdiv(t1, cpu_env, t1, t2);
524
+ value = 0;
129
}
525
+ break;
130
tcg_temp_free_i32(t2);
526
+ }
131
store_reg(s, a->rd, t1);
527
+
528
+ trace_allwinner_i2c_read(allwinner_i2c_get_regname(offset), offset, value);
529
+
530
+ return (uint64_t)value;
531
+}
532
+
533
+static void allwinner_i2c_write(void *opaque, hwaddr offset,
534
+ uint64_t value, unsigned size)
535
+{
536
+ AWI2CState *s = AW_I2C(opaque);
537
+
538
+ value &= 0xff;
539
+
540
+ trace_allwinner_i2c_write(allwinner_i2c_get_regname(offset), offset, value);
541
+
542
+ switch (offset) {
543
+ case TWI_ADDR_REG:
544
+ s->addr = (uint8_t)value;
545
+ break;
546
+ case TWI_XADDR_REG:
547
+ s->xaddr = (uint8_t)value;
548
+ break;
549
+ case TWI_DATA_REG:
550
+ /* If the device is in reset or not enabled, nothing to do */
551
+ if (allwinner_i2c_is_reset(s) || (!allwinner_i2c_bus_is_enabled(s))) {
552
+ break;
553
+ }
554
+
555
+ s->data = value & TWI_DATA_MASK;
556
+
557
+ switch (STAT_TO_STA(s->stat)) {
558
+ case STAT_M_STA_TX:
559
+ case STAT_M_RSTA_TX:
560
+ /* Send address */
561
+ if (i2c_start_transfer(s->bus, extract32(s->data, 1, 7),
562
+ extract32(s->data, 0, 1))) {
563
+ /* If non zero is returned, the address is not valid */
564
+ s->stat = STAT_FROM_STA(STAT_M_ADDR_WR_NACK);
565
+ } else {
566
+ /* Determine if read of write */
567
+ if (extract32(s->data, 0, 1)) {
568
+ s->stat = STAT_FROM_STA(STAT_M_ADDR_RD_ACK);
569
+ } else {
570
+ s->stat = STAT_FROM_STA(STAT_M_ADDR_WR_ACK);
571
+ }
572
+ allwinner_i2c_raise_interrupt(s);
573
+ }
574
+ break;
575
+ case STAT_M_ADDR_WR_ACK:
576
+ case STAT_M_DATA_TX_ACK:
577
+ if (i2c_send(s->bus, s->data)) {
578
+ /* If the target return non zero then end the transfer */
579
+ s->stat = STAT_FROM_STA(STAT_M_DATA_TX_NACK);
580
+ i2c_end_transfer(s->bus);
581
+ } else {
582
+ s->stat = STAT_FROM_STA(STAT_M_DATA_TX_ACK);
583
+ allwinner_i2c_raise_interrupt(s);
584
+ }
585
+ break;
586
+ default:
587
+ break;
588
+ }
589
+ break;
590
+ case TWI_CNTR_REG:
591
+ if (!allwinner_i2c_is_reset(s)) {
592
+ /* Do something only if not in software reset */
593
+ s->cntr = value & TWI_CNTR_MASK;
594
+
595
+ /* Check if start condition should be sent */
596
+ if (s->cntr & TWI_CNTR_M_STA) {
597
+ /* Update status */
598
+ if (STAT_TO_STA(s->stat) == STAT_IDLE) {
599
+ /* Send start condition */
600
+ s->stat = STAT_FROM_STA(STAT_M_STA_TX);
601
+ } else {
602
+ /* Send repeated start condition */
603
+ s->stat = STAT_FROM_STA(STAT_M_RSTA_TX);
604
+ }
605
+ /* Clear start condition */
606
+ s->cntr &= ~TWI_CNTR_M_STA;
607
+ }
608
+ if (s->cntr & TWI_CNTR_M_STP) {
609
+ /* Update status */
610
+ i2c_end_transfer(s->bus);
611
+ s->stat = STAT_FROM_STA(STAT_IDLE);
612
+ s->cntr &= ~TWI_CNTR_M_STP;
613
+ }
614
+ if ((s->cntr & TWI_CNTR_INT_FLAG) == 0) {
615
+ /* Interrupt flag cleared */
616
+ qemu_irq_lower(s->irq);
617
+ }
618
+ if ((s->cntr & TWI_CNTR_A_ACK) == 0) {
619
+ if (STAT_TO_STA(s->stat) == STAT_M_DATA_RX_ACK) {
620
+ s->stat = STAT_FROM_STA(STAT_M_DATA_RX_NACK);
621
+ }
622
+ } else {
623
+ if (STAT_TO_STA(s->stat) == STAT_M_DATA_RX_NACK) {
624
+ s->stat = STAT_FROM_STA(STAT_M_DATA_RX_ACK);
625
+ }
626
+ }
627
+ allwinner_i2c_raise_interrupt(s);
628
+
629
+ }
630
+ break;
631
+ case TWI_CCR_REG:
632
+ s->ccr = value & TWI_CCR_MASK;
633
+ break;
634
+ case TWI_SRST_REG:
635
+ if (((value & TWI_SRST_MASK) == 0) && (s->srst & TWI_SRST_MASK)) {
636
+ /* Perform reset */
637
+ allwinner_i2c_reset_hold(OBJECT(s));
638
+ }
639
+ s->srst = value & TWI_SRST_MASK;
640
+ break;
641
+ case TWI_EFR_REG:
642
+ s->efr = value & TWI_EFR_MASK;
643
+ break;
644
+ case TWI_LCR_REG:
645
+ s->lcr = value & TWI_LCR_MASK;
646
+ break;
647
+ default:
648
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
649
+ HWADDR_PRIx "\n", TYPE_AW_I2C, __func__, offset);
650
+ break;
651
+ }
652
+}
653
+
654
+static const MemoryRegionOps allwinner_i2c_ops = {
655
+ .read = allwinner_i2c_read,
656
+ .write = allwinner_i2c_write,
657
+ .valid.min_access_size = 1,
658
+ .valid.max_access_size = 4,
659
+ .endianness = DEVICE_NATIVE_ENDIAN,
660
+};
661
+
662
+static const VMStateDescription allwinner_i2c_vmstate = {
663
+ .name = TYPE_AW_I2C,
664
+ .version_id = 1,
665
+ .minimum_version_id = 1,
666
+ .fields = (VMStateField[]) {
667
+ VMSTATE_UINT8(addr, AWI2CState),
668
+ VMSTATE_UINT8(xaddr, AWI2CState),
669
+ VMSTATE_UINT8(data, AWI2CState),
670
+ VMSTATE_UINT8(cntr, AWI2CState),
671
+ VMSTATE_UINT8(ccr, AWI2CState),
672
+ VMSTATE_UINT8(srst, AWI2CState),
673
+ VMSTATE_UINT8(efr, AWI2CState),
674
+ VMSTATE_UINT8(lcr, AWI2CState),
675
+ VMSTATE_END_OF_LIST()
676
+ }
677
+};
678
+
679
+static void allwinner_i2c_realize(DeviceState *dev, Error **errp)
680
+{
681
+ AWI2CState *s = AW_I2C(dev);
682
+
683
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_i2c_ops, s,
684
+ TYPE_AW_I2C, AW_I2C_MEM_SIZE);
685
+ sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
686
+ sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq);
687
+ s->bus = i2c_init_bus(dev, "i2c");
688
+}
689
+
690
+static void allwinner_i2c_class_init(ObjectClass *klass, void *data)
691
+{
692
+ DeviceClass *dc = DEVICE_CLASS(klass);
693
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
694
+
695
+ rc->phases.hold = allwinner_i2c_reset_hold;
696
+ dc->vmsd = &allwinner_i2c_vmstate;
697
+ dc->realize = allwinner_i2c_realize;
698
+ dc->desc = "Allwinner I2C Controller";
699
+}
700
+
701
+static const TypeInfo allwinner_i2c_type_info = {
702
+ .name = TYPE_AW_I2C,
703
+ .parent = TYPE_SYS_BUS_DEVICE,
704
+ .instance_size = sizeof(AWI2CState),
705
+ .class_init = allwinner_i2c_class_init,
706
+};
707
+
708
+static void allwinner_i2c_register_types(void)
709
+{
710
+ type_register_static(&allwinner_i2c_type_info);
711
+}
712
+
713
+type_init(allwinner_i2c_register_types)
714
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
715
index XXXXXXX..XXXXXXX 100644
716
--- a/hw/arm/Kconfig
717
+++ b/hw/arm/Kconfig
718
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10
719
select ALLWINNER_A10_CCM
720
select ALLWINNER_A10_DRAMC
721
select ALLWINNER_EMAC
722
+ select ALLWINNER_I2C
723
select SERIAL
724
select UNIMP
725
726
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_H3
727
bool
728
select ALLWINNER_A10_PIT
729
select ALLWINNER_SUN8I_EMAC
730
+ select ALLWINNER_I2C
731
select SERIAL
732
select ARM_TIMER
733
select ARM_GIC
734
diff --git a/hw/i2c/Kconfig b/hw/i2c/Kconfig
735
index XXXXXXX..XXXXXXX 100644
736
--- a/hw/i2c/Kconfig
737
+++ b/hw/i2c/Kconfig
738
@@ -XXX,XX +XXX,XX @@ config MPC_I2C
739
bool
740
select I2C
741
742
+config ALLWINNER_I2C
743
+ bool
744
+ select I2C
745
+
746
config PCA954X
747
bool
748
select I2C
749
diff --git a/hw/i2c/meson.build b/hw/i2c/meson.build
750
index XXXXXXX..XXXXXXX 100644
751
--- a/hw/i2c/meson.build
752
+++ b/hw/i2c/meson.build
753
@@ -XXX,XX +XXX,XX @@ i2c_ss.add(when: 'CONFIG_BITBANG_I2C', if_true: files('bitbang_i2c.c'))
754
i2c_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_i2c.c'))
755
i2c_ss.add(when: 'CONFIG_IMX_I2C', if_true: files('imx_i2c.c'))
756
i2c_ss.add(when: 'CONFIG_MPC_I2C', if_true: files('mpc_i2c.c'))
757
+i2c_ss.add(when: 'CONFIG_ALLWINNER_I2C', if_true: files('allwinner-i2c.c'))
758
i2c_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('microbit_i2c.c'))
759
i2c_ss.add(when: 'CONFIG_NPCM7XX', if_true: files('npcm7xx_smbus.c'))
760
i2c_ss.add(when: 'CONFIG_SMBUS_EEPROM', if_true: files('smbus_eeprom.c'))
761
diff --git a/hw/i2c/trace-events b/hw/i2c/trace-events
762
index XXXXXXX..XXXXXXX 100644
763
--- a/hw/i2c/trace-events
764
+++ b/hw/i2c/trace-events
765
@@ -XXX,XX +XXX,XX @@ i2c_send_async(uint8_t address, uint8_t data) "send_async(addr:0x%02x) data:0x%0
766
i2c_recv(uint8_t address, uint8_t data) "recv(addr:0x%02x) data:0x%02x"
767
i2c_ack(void) ""
768
769
+# allwinner_i2c.c
770
+
771
+allwinner_i2c_read(const char* reg_name, uint64_t offset, uint64_t value) "read %s [0x%" PRIx64 "]: -> 0x%" PRIx64
772
+allwinner_i2c_write(const char* reg_name, uint64_t offset, uint64_t value) "write %s [0x%" PRIx64 "]: <- 0x%" PRIx64
773
+
774
# aspeed_i2c.c
775
776
aspeed_i2c_bus_cmd(uint32_t cmd, const char *cmd_flags, uint32_t count, uint32_t intr_status) "handling cmd=0x%x %s count=%d intr=0x%x"
132
--
777
--
133
2.20.1
778
2.34.1
134
135
diff view generated by jsdifflib
1
From: Jan Luebbe <jlu@pengutronix.de>
1
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
2
2
3
Break events are currently only handled by chardev/char-serial.c, so we
3
This patch adds minimal support for AXP-209 PMU.
4
just ignore errors, which results in no behaviour change for other
4
Most important is chip ID since U-Boot SPL expects version 0x1. Besides
5
chardevs.
5
the chip ID register, reset values for two more registers used by A10
6
U-Boot SPL are covered.
6
7
7
Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
8
Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
8
Message-id: 20210806144700.3751979-1-jlu@pengutronix.de
9
Message-id: 20221226220303.14420-5-strahinja.p.jankovic@gmail.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
---
12
hw/char/pl011.c | 6 ++++++
13
hw/misc/axp209.c | 238 +++++++++++++++++++++++++++++++++++++++++++
13
1 file changed, 6 insertions(+)
14
MAINTAINERS | 2 +
15
hw/misc/Kconfig | 4 +
16
hw/misc/meson.build | 1 +
17
hw/misc/trace-events | 5 +
18
5 files changed, 250 insertions(+)
19
create mode 100644 hw/misc/axp209.c
14
20
15
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
21
diff --git a/hw/misc/axp209.c b/hw/misc/axp209.c
22
new file mode 100644
23
index XXXXXXX..XXXXXXX
24
--- /dev/null
25
+++ b/hw/misc/axp209.c
26
@@ -XXX,XX +XXX,XX @@
27
+/*
28
+ * AXP-209 PMU Emulation
29
+ *
30
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
31
+ *
32
+ * Permission is hereby granted, free of charge, to any person obtaining a
33
+ * copy of this software and associated documentation files (the "Software"),
34
+ * to deal in the Software without restriction, including without limitation
35
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
36
+ * and/or sell copies of the Software, and to permit persons to whom the
37
+ * Software is furnished to do so, subject to the following conditions:
38
+ *
39
+ * The above copyright notice and this permission notice shall be included in
40
+ * all copies or substantial portions of the Software.
41
+ *
42
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
43
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
44
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
45
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
46
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
47
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
48
+ * DEALINGS IN THE SOFTWARE.
49
+ *
50
+ * SPDX-License-Identifier: MIT
51
+ */
52
+
53
+#include "qemu/osdep.h"
54
+#include "qemu/log.h"
55
+#include "trace.h"
56
+#include "hw/i2c/i2c.h"
57
+#include "migration/vmstate.h"
58
+
59
+#define TYPE_AXP209_PMU "axp209_pmu"
60
+
61
+#define AXP209(obj) \
62
+ OBJECT_CHECK(AXP209I2CState, (obj), TYPE_AXP209_PMU)
63
+
64
+/* registers */
65
+enum {
66
+ REG_POWER_STATUS = 0x0u,
67
+ REG_OPERATING_MODE,
68
+ REG_OTG_VBUS_STATUS,
69
+ REG_CHIP_VERSION,
70
+ REG_DATA_CACHE_0,
71
+ REG_DATA_CACHE_1,
72
+ REG_DATA_CACHE_2,
73
+ REG_DATA_CACHE_3,
74
+ REG_DATA_CACHE_4,
75
+ REG_DATA_CACHE_5,
76
+ REG_DATA_CACHE_6,
77
+ REG_DATA_CACHE_7,
78
+ REG_DATA_CACHE_8,
79
+ REG_DATA_CACHE_9,
80
+ REG_DATA_CACHE_A,
81
+ REG_DATA_CACHE_B,
82
+ REG_POWER_OUTPUT_CTRL = 0x12u,
83
+ REG_DC_DC2_OUT_V_CTRL = 0x23u,
84
+ REG_DC_DC2_DVS_CTRL = 0x25u,
85
+ REG_DC_DC3_OUT_V_CTRL = 0x27u,
86
+ REG_LDO2_4_OUT_V_CTRL,
87
+ REG_LDO3_OUT_V_CTRL,
88
+ REG_VBUS_CH_MGMT = 0x30u,
89
+ REG_SHUTDOWN_V_CTRL,
90
+ REG_SHUTDOWN_CTRL,
91
+ REG_CHARGE_CTRL_1,
92
+ REG_CHARGE_CTRL_2,
93
+ REG_SPARE_CHARGE_CTRL,
94
+ REG_PEK_KEY_CTRL,
95
+ REG_DC_DC_FREQ_SET,
96
+ REG_CHR_TEMP_TH_SET,
97
+ REG_CHR_HIGH_TEMP_TH_CTRL,
98
+ REG_IPSOUT_WARN_L1,
99
+ REG_IPSOUT_WARN_L2,
100
+ REG_DISCHR_TEMP_TH_SET,
101
+ REG_DISCHR_HIGH_TEMP_TH_CTRL,
102
+ REG_IRQ_BANK_1_CTRL = 0x40u,
103
+ REG_IRQ_BANK_2_CTRL,
104
+ REG_IRQ_BANK_3_CTRL,
105
+ REG_IRQ_BANK_4_CTRL,
106
+ REG_IRQ_BANK_5_CTRL,
107
+ REG_IRQ_BANK_1_STAT = 0x48u,
108
+ REG_IRQ_BANK_2_STAT,
109
+ REG_IRQ_BANK_3_STAT,
110
+ REG_IRQ_BANK_4_STAT,
111
+ REG_IRQ_BANK_5_STAT,
112
+ REG_ADC_ACIN_V_H = 0x56u,
113
+ REG_ADC_ACIN_V_L,
114
+ REG_ADC_ACIN_CURR_H,
115
+ REG_ADC_ACIN_CURR_L,
116
+ REG_ADC_VBUS_V_H,
117
+ REG_ADC_VBUS_V_L,
118
+ REG_ADC_VBUS_CURR_H,
119
+ REG_ADC_VBUS_CURR_L,
120
+ REG_ADC_INT_TEMP_H,
121
+ REG_ADC_INT_TEMP_L,
122
+ REG_ADC_TEMP_SENS_V_H = 0x62u,
123
+ REG_ADC_TEMP_SENS_V_L,
124
+ REG_ADC_BAT_V_H = 0x78u,
125
+ REG_ADC_BAT_V_L,
126
+ REG_ADC_BAT_DISCHR_CURR_H,
127
+ REG_ADC_BAT_DISCHR_CURR_L,
128
+ REG_ADC_BAT_CHR_CURR_H,
129
+ REG_ADC_BAT_CHR_CURR_L,
130
+ REG_ADC_IPSOUT_V_H,
131
+ REG_ADC_IPSOUT_V_L,
132
+ REG_DC_DC_MOD_SEL = 0x80u,
133
+ REG_ADC_EN_1,
134
+ REG_ADC_EN_2,
135
+ REG_ADC_SR_CTRL,
136
+ REG_ADC_IN_RANGE,
137
+ REG_GPIO1_ADC_IRQ_RISING_TH,
138
+ REG_GPIO1_ADC_IRQ_FALLING_TH,
139
+ REG_TIMER_CTRL = 0x8au,
140
+ REG_VBUS_CTRL_MON_SRP,
141
+ REG_OVER_TEMP_SHUTDOWN = 0x8fu,
142
+ REG_GPIO0_FEAT_SET,
143
+ REG_GPIO_OUT_HIGH_SET,
144
+ REG_GPIO1_FEAT_SET,
145
+ REG_GPIO2_FEAT_SET,
146
+ REG_GPIO_SIG_STATE_SET_MON,
147
+ REG_GPIO3_SET,
148
+ REG_COULOMB_CNTR_CTRL = 0xb8u,
149
+ REG_POWER_MEAS_RES,
150
+ NR_REGS
151
+};
152
+
153
+#define AXP209_CHIP_VERSION_ID (0x01)
154
+#define AXP209_DC_DC2_OUT_V_CTRL_RESET (0x16)
155
+#define AXP209_IRQ_BANK_1_CTRL_RESET (0xd8)
156
+
157
+/* A simple I2C slave which returns values of ID or CNT register. */
158
+typedef struct AXP209I2CState {
159
+ /*< private >*/
160
+ I2CSlave i2c;
161
+ /*< public >*/
162
+ uint8_t regs[NR_REGS]; /* peripheral registers */
163
+ uint8_t ptr; /* current register index */
164
+ uint8_t count; /* counter used for tx/rx */
165
+} AXP209I2CState;
166
+
167
+/* Reset all counters and load ID register */
168
+static void axp209_reset_enter(Object *obj, ResetType type)
169
+{
170
+ AXP209I2CState *s = AXP209(obj);
171
+
172
+ memset(s->regs, 0, NR_REGS);
173
+ s->ptr = 0;
174
+ s->count = 0;
175
+ s->regs[REG_CHIP_VERSION] = AXP209_CHIP_VERSION_ID;
176
+ s->regs[REG_DC_DC2_OUT_V_CTRL] = AXP209_DC_DC2_OUT_V_CTRL_RESET;
177
+ s->regs[REG_IRQ_BANK_1_CTRL] = AXP209_IRQ_BANK_1_CTRL_RESET;
178
+}
179
+
180
+/* Handle events from master. */
181
+static int axp209_event(I2CSlave *i2c, enum i2c_event event)
182
+{
183
+ AXP209I2CState *s = AXP209(i2c);
184
+
185
+ s->count = 0;
186
+
187
+ return 0;
188
+}
189
+
190
+/* Called when master requests read */
191
+static uint8_t axp209_rx(I2CSlave *i2c)
192
+{
193
+ AXP209I2CState *s = AXP209(i2c);
194
+ uint8_t ret = 0xff;
195
+
196
+ if (s->ptr < NR_REGS) {
197
+ ret = s->regs[s->ptr++];
198
+ }
199
+
200
+ trace_axp209_rx(s->ptr - 1, ret);
201
+
202
+ return ret;
203
+}
204
+
205
+/*
206
+ * Called when master sends write.
207
+ * Update ptr with byte 0, then perform write with second byte.
208
+ */
209
+static int axp209_tx(I2CSlave *i2c, uint8_t data)
210
+{
211
+ AXP209I2CState *s = AXP209(i2c);
212
+
213
+ if (s->count == 0) {
214
+ /* Store register address */
215
+ s->ptr = data;
216
+ s->count++;
217
+ trace_axp209_select(data);
218
+ } else {
219
+ trace_axp209_tx(s->ptr, data);
220
+ if (s->ptr == REG_DC_DC2_OUT_V_CTRL) {
221
+ s->regs[s->ptr++] = data;
222
+ }
223
+ }
224
+
225
+ return 0;
226
+}
227
+
228
+static const VMStateDescription vmstate_axp209 = {
229
+ .name = TYPE_AXP209_PMU,
230
+ .version_id = 1,
231
+ .fields = (VMStateField[]) {
232
+ VMSTATE_UINT8_ARRAY(regs, AXP209I2CState, NR_REGS),
233
+ VMSTATE_UINT8(count, AXP209I2CState),
234
+ VMSTATE_UINT8(ptr, AXP209I2CState),
235
+ VMSTATE_END_OF_LIST()
236
+ }
237
+};
238
+
239
+static void axp209_class_init(ObjectClass *oc, void *data)
240
+{
241
+ DeviceClass *dc = DEVICE_CLASS(oc);
242
+ I2CSlaveClass *isc = I2C_SLAVE_CLASS(oc);
243
+ ResettableClass *rc = RESETTABLE_CLASS(oc);
244
+
245
+ rc->phases.enter = axp209_reset_enter;
246
+ dc->vmsd = &vmstate_axp209;
247
+ isc->event = axp209_event;
248
+ isc->recv = axp209_rx;
249
+ isc->send = axp209_tx;
250
+}
251
+
252
+static const TypeInfo axp209_info = {
253
+ .name = TYPE_AXP209_PMU,
254
+ .parent = TYPE_I2C_SLAVE,
255
+ .instance_size = sizeof(AXP209I2CState),
256
+ .class_init = axp209_class_init
257
+};
258
+
259
+static void axp209_register_devices(void)
260
+{
261
+ type_register_static(&axp209_info);
262
+}
263
+
264
+type_init(axp209_register_devices);
265
diff --git a/MAINTAINERS b/MAINTAINERS
16
index XXXXXXX..XXXXXXX 100644
266
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/char/pl011.c
267
--- a/MAINTAINERS
18
+++ b/hw/char/pl011.c
268
+++ b/MAINTAINERS
19
@@ -XXX,XX +XXX,XX @@
269
@@ -XXX,XX +XXX,XX @@ ARM Machines
20
#include "hw/qdev-properties-system.h"
270
Allwinner-a10
21
#include "migration/vmstate.h"
271
M: Beniamino Galvani <b.galvani@gmail.com>
22
#include "chardev/char-fe.h"
272
M: Peter Maydell <peter.maydell@linaro.org>
23
+#include "chardev/char-serial.h"
273
+R: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
24
#include "qemu/log.h"
274
L: qemu-arm@nongnu.org
25
#include "qemu/module.h"
275
S: Odd Fixes
26
#include "trace.h"
276
F: hw/*/allwinner*
27
@@ -XXX,XX +XXX,XX @@ static void pl011_write(void *opaque, hwaddr offset,
277
F: include/hw/*/allwinner*
28
s->read_count = 0;
278
F: hw/arm/cubieboard.c
29
s->read_pos = 0;
279
F: docs/system/arm/cubieboard.rst
30
}
280
+F: hw/misc/axp209.c
31
+ if ((s->lcr ^ value) & 0x1) {
281
32
+ int break_enable = value & 0x1;
282
Allwinner-h3
33
+ qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
283
M: Niek Linnenbank <nieklinnenbank@gmail.com>
34
+ &break_enable);
284
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
35
+ }
285
index XXXXXXX..XXXXXXX 100644
36
s->lcr = value;
286
--- a/hw/misc/Kconfig
37
pl011_set_read_trigger(s);
287
+++ b/hw/misc/Kconfig
38
break;
288
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10_CCM
289
config ALLWINNER_A10_DRAMC
290
bool
291
292
+config AXP209_PMU
293
+ bool
294
+ depends on I2C
295
+
296
source macio/Kconfig
297
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
298
index XXXXXXX..XXXXXXX 100644
299
--- a/hw/misc/meson.build
300
+++ b/hw/misc/meson.build
301
@@ -XXX,XX +XXX,XX @@ specific_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-cpucfg.c'
302
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-dramc.c'))
303
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-sysctrl.c'))
304
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-sid.c'))
305
+softmmu_ss.add(when: 'CONFIG_AXP209_PMU', if_true: files('axp209.c'))
306
softmmu_ss.add(when: 'CONFIG_REALVIEW', if_true: files('arm_sysctl.c'))
307
softmmu_ss.add(when: 'CONFIG_NSERIES', if_true: files('cbus.c'))
308
softmmu_ss.add(when: 'CONFIG_ECCMEMCTL', if_true: files('eccmemctl.c'))
309
diff --git a/hw/misc/trace-events b/hw/misc/trace-events
310
index XXXXXXX..XXXXXXX 100644
311
--- a/hw/misc/trace-events
312
+++ b/hw/misc/trace-events
313
@@ -XXX,XX +XXX,XX @@ allwinner_sid_write(uint64_t offset, uint64_t data, unsigned size) "offset 0x%"
314
avr_power_read(uint8_t value) "power_reduc read value:%u"
315
avr_power_write(uint8_t value) "power_reduc write value:%u"
316
317
+# axp209.c
318
+axp209_rx(uint8_t reg, uint8_t data) "Read reg 0x%" PRIx8 " : 0x%" PRIx8
319
+axp209_select(uint8_t reg) "Accessing reg 0x%" PRIx8
320
+axp209_tx(uint8_t reg, uint8_t data) "Write reg 0x%" PRIx8 " : 0x%" PRIx8
321
+
322
# eccmemctl.c
323
ecc_mem_writel_mer(uint32_t val) "Write memory enable 0x%08x"
324
ecc_mem_writel_mdr(uint32_t val) "Write memory delay 0x%08x"
39
--
325
--
40
2.20.1
326
2.34.1
41
42
diff view generated by jsdifflib
1
All the users of the vmlaldav formats have an 'x bit in bit 12 and an
1
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
2
'a' bit in bit 5; move these to the format rather than specifying them
3
in each insn pattern.
4
2
3
SPL Boot for Cubieboard expects AXP209 connected to I2C0 bus.
4
5
Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
6
7
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Message-id: 20221226220303.14420-6-strahinja.p.jankovic@gmail.com
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
---
10
---
8
target/arm/mve.decode | 16 ++++++++--------
11
hw/arm/cubieboard.c | 6 ++++++
9
1 file changed, 8 insertions(+), 8 deletions(-)
12
hw/arm/Kconfig | 1 +
13
2 files changed, 7 insertions(+)
10
14
11
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
15
diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
12
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/mve.decode
17
--- a/hw/arm/cubieboard.c
14
+++ b/target/arm/mve.decode
18
+++ b/hw/arm/cubieboard.c
15
@@ -XXX,XX +XXX,XX @@ VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=2
19
@@ -XXX,XX +XXX,XX @@
16
20
#include "hw/boards.h"
17
&vmlaldav rdahi rdalo size qn qm x a
21
#include "hw/qdev-properties.h"
18
22
#include "hw/arm/allwinner-a10.h"
19
-@vmlaldav .... .... . ... ... . ... . .... .... qm:3 . \
23
+#include "hw/i2c/i2c.h"
20
+@vmlaldav .... .... . ... ... . ... x:1 .... .. a:1 . qm:3 . \
24
21
qn=%qn rdahi=%rdahi rdalo=%rdalo size=%size_16 &vmlaldav
25
static struct arm_boot_info cubieboard_binfo = {
22
-@vmlaldav_nosz .... .... . ... ... . ... . .... .... qm:3 . \
26
.loader_start = AW_A10_SDRAM_BASE,
23
+@vmlaldav_nosz .... .... . ... ... . ... x:1 .... .. a:1 . qm:3 . \
27
@@ -XXX,XX +XXX,XX @@ static void cubieboard_init(MachineState *machine)
24
qn=%qn rdahi=%rdahi rdalo=%rdalo size=0 &vmlaldav
28
BlockBackend *blk;
25
-VMLALDAV_S 1110 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 0 @vmlaldav
29
BusState *bus;
26
-VMLALDAV_U 1111 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 0 @vmlaldav
30
DeviceState *carddev;
27
+VMLALDAV_S 1110 1110 1 ... ... . ... . 1110 . 0 . 0 ... 0 @vmlaldav
31
+ I2CBus *i2c;
28
+VMLALDAV_U 1111 1110 1 ... ... . ... . 1110 . 0 . 0 ... 0 @vmlaldav
32
29
33
/* BIOS is not supported by this board */
30
-VMLSLDAV 1110 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav
34
if (machine->firmware) {
31
+VMLSLDAV 1110 1110 1 ... ... . ... . 1110 . 0 . 0 ... 1 @vmlaldav
35
@@ -XXX,XX +XXX,XX @@ static void cubieboard_init(MachineState *machine)
32
36
exit(1);
33
-VRMLALDAVH_S 1110 1110 1 ... ... 0 ... x:1 1111 . 0 a:1 0 ... 0 @vmlaldav_nosz
37
}
34
-VRMLALDAVH_U 1111 1110 1 ... ... 0 ... x:1 1111 . 0 a:1 0 ... 0 @vmlaldav_nosz
38
35
+VRMLALDAVH_S 1110 1110 1 ... ... 0 ... . 1111 . 0 . 0 ... 0 @vmlaldav_nosz
39
+ /* Connect AXP 209 */
36
+VRMLALDAVH_U 1111 1110 1 ... ... 0 ... . 1111 . 0 . 0 ... 0 @vmlaldav_nosz
40
+ i2c = I2C_BUS(qdev_get_child_bus(DEVICE(&a10->i2c0), "i2c"));
37
41
+ i2c_slave_create_simple(i2c, "axp209_pmu", 0x34);
38
-VRMLSLDAVH 1111 1110 1 ... ... 0 ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav_nosz
42
+
39
+VRMLSLDAVH 1111 1110 1 ... ... 0 ... . 1110 . 0 . 0 ... 1 @vmlaldav_nosz
43
/* Retrieve SD bus */
40
44
di = drive_get(IF_SD, 0, 0);
41
# Scalar operations
45
blk = di ? blk_by_legacy_dinfo(di) : NULL;
46
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/arm/Kconfig
49
+++ b/hw/arm/Kconfig
50
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10
51
select ALLWINNER_A10_DRAMC
52
select ALLWINNER_EMAC
53
select ALLWINNER_I2C
54
+ select AXP209_PMU
55
select SERIAL
56
select UNIMP
42
57
43
--
58
--
44
2.20.1
59
2.34.1
45
60
46
61
diff view generated by jsdifflib
1
Implement the MVE saturating doubling multiply accumulate insns
1
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
2
VQDMLAH, VQRDMLAH, VQDMLASH and VQRDMLASH. These perform a multiply,
3
double, add the accumulator shifted by the element size, possibly
4
round, saturate to twice the element size, then take the high half of
5
the result. The *MLAH insns do vector * scalar + vector, and the
6
*MLASH insns do vector * vector + scalar.
7
2
3
This patch enables copying of SPL from MMC if `-kernel` parameter is not
4
passed when starting QEMU. SPL is copied to SRAM_A.
5
6
The approach is reused from Allwinner H3 implementation.
7
8
Tested with Armbian and custom Yocto image.
9
10
Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
11
12
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
13
Message-id: 20221226220303.14420-7-strahinja.p.jankovic@gmail.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
---
15
---
11
target/arm/helper-mve.h | 16 +++++++
16
include/hw/arm/allwinner-a10.h | 21 +++++++++++++++++++++
12
target/arm/mve.decode | 5 ++
17
hw/arm/allwinner-a10.c | 18 ++++++++++++++++++
13
target/arm/mve_helper.c | 95 ++++++++++++++++++++++++++++++++++++++
18
hw/arm/cubieboard.c | 5 +++++
14
target/arm/translate-mve.c | 4 ++
19
3 files changed, 44 insertions(+)
15
4 files changed, 120 insertions(+)
16
20
17
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
21
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
18
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper-mve.h
23
--- a/include/hw/arm/allwinner-a10.h
20
+++ b/target/arm/helper-mve.h
24
+++ b/include/hw/arm/allwinner-a10.h
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmlasb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
@@ -XXX,XX +XXX,XX @@
22
DEF_HELPER_FLAGS_4(mve_vmlash, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
26
#include "hw/misc/allwinner-a10-ccm.h"
23
DEF_HELPER_FLAGS_4(mve_vmlasw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
27
#include "hw/misc/allwinner-a10-dramc.h"
24
28
#include "hw/i2c/allwinner-i2c.h"
25
+DEF_HELPER_FLAGS_4(mve_vqdmlahb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
29
+#include "sysemu/block-backend.h"
26
+DEF_HELPER_FLAGS_4(mve_vqdmlahh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
30
27
+DEF_HELPER_FLAGS_4(mve_vqdmlahw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
#include "target/arm/cpu.h"
32
#include "qom/object.h"
33
@@ -XXX,XX +XXX,XX @@ struct AwA10State {
34
OHCISysBusState ohci[AW_A10_NUM_USB];
35
};
36
37
+/**
38
+ * Emulate Boot ROM firmware setup functionality.
39
+ *
40
+ * A real Allwinner A10 SoC contains a Boot ROM
41
+ * which is the first code that runs right after
42
+ * the SoC is powered on. The Boot ROM is responsible
43
+ * for loading user code (e.g. a bootloader) from any
44
+ * of the supported external devices and writing the
45
+ * downloaded code to internal SRAM. After loading the SoC
46
+ * begins executing the code written to SRAM.
47
+ *
48
+ * This function emulates the Boot ROM by copying 32 KiB
49
+ * of data at offset 8 KiB from the given block device and writes it to
50
+ * the start of the first internal SRAM memory.
51
+ *
52
+ * @s: Allwinner A10 state object pointer
53
+ * @blk: Block backend device object pointer
54
+ */
55
+void allwinner_a10_bootrom_setup(AwA10State *s, BlockBackend *blk);
28
+
56
+
29
+DEF_HELPER_FLAGS_4(mve_vqrdmlahb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
57
#endif
30
+DEF_HELPER_FLAGS_4(mve_vqrdmlahh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
58
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
31
+DEF_HELPER_FLAGS_4(mve_vqrdmlahw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
59
index XXXXXXX..XXXXXXX 100644
60
--- a/hw/arm/allwinner-a10.c
61
+++ b/hw/arm/allwinner-a10.c
62
@@ -XXX,XX +XXX,XX @@
63
#include "sysemu/sysemu.h"
64
#include "hw/boards.h"
65
#include "hw/usb/hcd-ohci.h"
66
+#include "hw/loader.h"
67
68
+#define AW_A10_SRAM_A_BASE 0x00000000
69
#define AW_A10_DRAMC_BASE 0x01c01000
70
#define AW_A10_MMC0_BASE 0x01c0f000
71
#define AW_A10_CCM_BASE 0x01c20000
72
@@ -XXX,XX +XXX,XX @@
73
#define AW_A10_RTC_BASE 0x01c20d00
74
#define AW_A10_I2C0_BASE 0x01c2ac00
75
76
+void allwinner_a10_bootrom_setup(AwA10State *s, BlockBackend *blk)
77
+{
78
+ const int64_t rom_size = 32 * KiB;
79
+ g_autofree uint8_t *buffer = g_new0(uint8_t, rom_size);
32
+
80
+
33
+DEF_HELPER_FLAGS_4(mve_vqdmlashb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
81
+ if (blk_pread(blk, 8 * KiB, rom_size, buffer, 0) < 0) {
34
+DEF_HELPER_FLAGS_4(mve_vqdmlashh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
82
+ error_setg(&error_fatal, "%s: failed to read BlockBackend data",
35
+DEF_HELPER_FLAGS_4(mve_vqdmlashw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
83
+ __func__);
36
+
84
+ return;
37
+DEF_HELPER_FLAGS_4(mve_vqrdmlashb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
38
+DEF_HELPER_FLAGS_4(mve_vqrdmlashh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
39
+DEF_HELPER_FLAGS_4(mve_vqrdmlashw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
40
+
41
DEF_HELPER_FLAGS_4(mve_vmlaldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
42
DEF_HELPER_FLAGS_4(mve_vmlaldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
43
DEF_HELPER_FLAGS_4(mve_vmlaldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
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 @@ VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
49
VMLA 111- 1110 0 . .. ... 1 ... 0 1110 . 100 .... @2scalar
50
VMLAS 111- 1110 0 . .. ... 1 ... 1 1110 . 100 .... @2scalar
51
52
+VQRDMLAH 1110 1110 0 . .. ... 0 ... 0 1110 . 100 .... @2scalar
53
+VQRDMLASH 1110 1110 0 . .. ... 0 ... 1 1110 . 100 .... @2scalar
54
+VQDMLAH 1110 1110 0 . .. ... 0 ... 0 1110 . 110 .... @2scalar
55
+VQDMLASH 1110 1110 0 . .. ... 0 ... 1 1110 . 110 .... @2scalar
56
+
57
# Vector add across vector
58
{
59
VADDV 111 u:1 1110 1111 size:2 01 ... 0 1111 0 0 a:1 0 qm:3 0 rda=%rdalo
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_VQDMLADH_OP(vqrdmlsdhxw, 4, int32_t, 1, 1, do_vqdmlsdh_w)
65
mve_advance_vpt(env); \
66
}
67
68
+#define DO_2OP_SAT_ACC_SCALAR(OP, ESIZE, TYPE, FN) \
69
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
70
+ uint32_t rm) \
71
+ { \
72
+ TYPE *d = vd, *n = vn; \
73
+ TYPE m = rm; \
74
+ uint16_t mask = mve_element_mask(env); \
75
+ unsigned e; \
76
+ bool qc = false; \
77
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
78
+ bool sat = false; \
79
+ mergemask(&d[H##ESIZE(e)], \
80
+ FN(d[H##ESIZE(e)], n[H##ESIZE(e)], m, &sat), \
81
+ mask); \
82
+ qc |= sat & mask & 1; \
83
+ } \
84
+ if (qc) { \
85
+ env->vfp.qc[0] = qc; \
86
+ } \
87
+ mve_advance_vpt(env); \
88
+ }
85
+ }
89
+
86
+
90
/* provide unsigned 2-op scalar helpers for all sizes */
87
+ rom_add_blob("allwinner-a10.bootrom", buffer, rom_size,
91
#define DO_2OP_SCALAR_U(OP, FN) \
88
+ rom_size, AW_A10_SRAM_A_BASE,
92
DO_2OP_SCALAR(OP##b, 1, uint8_t, FN) \
89
+ NULL, NULL, NULL, NULL, false);
93
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT_SCALAR(vqrdmulh_scalarb, 1, int8_t, DO_QRDMULH_B)
94
DO_2OP_SAT_SCALAR(vqrdmulh_scalarh, 2, int16_t, DO_QRDMULH_H)
95
DO_2OP_SAT_SCALAR(vqrdmulh_scalarw, 4, int32_t, DO_QRDMULH_W)
96
97
+static int8_t do_vqdmlah_b(int8_t a, int8_t b, int8_t c, int round, bool *sat)
98
+{
99
+ int64_t r = (int64_t)a * b * 2 + ((int64_t)c << 8) + (round << 7);
100
+ return do_sat_bhw(r, INT16_MIN, INT16_MAX, sat) >> 8;
101
+}
90
+}
102
+
91
+
103
+static int16_t do_vqdmlah_h(int16_t a, int16_t b, int16_t c,
92
static void aw_a10_init(Object *obj)
104
+ int round, bool *sat)
93
{
105
+{
94
AwA10State *s = AW_A10(obj);
106
+ int64_t r = (int64_t)a * b * 2 + ((int64_t)c << 16) + (round << 15);
95
diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
107
+ return do_sat_bhw(r, INT32_MIN, INT32_MAX, sat) >> 16;
96
index XXXXXXX..XXXXXXX 100644
108
+}
97
--- a/hw/arm/cubieboard.c
109
+
98
+++ b/hw/arm/cubieboard.c
110
+static int32_t do_vqdmlah_w(int32_t a, int32_t b, int32_t c,
99
@@ -XXX,XX +XXX,XX @@ static void cubieboard_init(MachineState *machine)
111
+ int round, bool *sat)
100
memory_region_add_subregion(get_system_memory(), AW_A10_SDRAM_BASE,
112
+{
101
machine->ram);
113
+ /*
102
114
+ * Architecturally we should do the entire add, double, round
103
+ /* Load target kernel or start using BootROM */
115
+ * and then check for saturation. We do three saturating adds,
104
+ if (!machine->kernel_filename && blk && blk_is_available(blk)) {
116
+ * but we need to be careful about the order. If the first
105
+ /* Use Boot ROM to copy data from SD card to SRAM */
117
+ * m1 + m2 saturates then it's impossible for the *2+rc to
106
+ allwinner_a10_bootrom_setup(a10, blk);
118
+ * bring it back into the non-saturated range. However, if
119
+ * m1 + m2 is negative then it's possible that doing the doubling
120
+ * would take the intermediate result below INT64_MAX and the
121
+ * addition of the rounding constant then brings it back in range.
122
+ * So we add half the rounding constant and half the "c << esize"
123
+ * before doubling rather than adding the rounding constant after
124
+ * the doubling.
125
+ */
126
+ int64_t m1 = (int64_t)a * b;
127
+ int64_t m2 = (int64_t)c << 31;
128
+ int64_t r;
129
+ if (sadd64_overflow(m1, m2, &r) ||
130
+ sadd64_overflow(r, (round << 30), &r) ||
131
+ sadd64_overflow(r, r, &r)) {
132
+ *sat = true;
133
+ return r < 0 ? INT32_MAX : INT32_MIN;
134
+ }
107
+ }
135
+ return r >> 32;
108
/* TODO create and connect IDE devices for ide_drive_get() */
136
+}
109
137
+
110
cubieboard_binfo.ram_size = machine->ram_size;
138
+/*
139
+ * The *MLAH insns are vector * scalar + vector;
140
+ * the *MLASH insns are vector * vector + scalar
141
+ */
142
+#define DO_VQDMLAH_B(D, N, M, S) do_vqdmlah_b(N, M, D, 0, S)
143
+#define DO_VQDMLAH_H(D, N, M, S) do_vqdmlah_h(N, M, D, 0, S)
144
+#define DO_VQDMLAH_W(D, N, M, S) do_vqdmlah_w(N, M, D, 0, S)
145
+#define DO_VQRDMLAH_B(D, N, M, S) do_vqdmlah_b(N, M, D, 1, S)
146
+#define DO_VQRDMLAH_H(D, N, M, S) do_vqdmlah_h(N, M, D, 1, S)
147
+#define DO_VQRDMLAH_W(D, N, M, S) do_vqdmlah_w(N, M, D, 1, S)
148
+
149
+#define DO_VQDMLASH_B(D, N, M, S) do_vqdmlah_b(N, D, M, 0, S)
150
+#define DO_VQDMLASH_H(D, N, M, S) do_vqdmlah_h(N, D, M, 0, S)
151
+#define DO_VQDMLASH_W(D, N, M, S) do_vqdmlah_w(N, D, M, 0, S)
152
+#define DO_VQRDMLASH_B(D, N, M, S) do_vqdmlah_b(N, D, M, 1, S)
153
+#define DO_VQRDMLASH_H(D, N, M, S) do_vqdmlah_h(N, D, M, 1, S)
154
+#define DO_VQRDMLASH_W(D, N, M, S) do_vqdmlah_w(N, D, M, 1, S)
155
+
156
+DO_2OP_SAT_ACC_SCALAR(vqdmlahb, 1, int8_t, DO_VQDMLAH_B)
157
+DO_2OP_SAT_ACC_SCALAR(vqdmlahh, 2, int16_t, DO_VQDMLAH_H)
158
+DO_2OP_SAT_ACC_SCALAR(vqdmlahw, 4, int32_t, DO_VQDMLAH_W)
159
+DO_2OP_SAT_ACC_SCALAR(vqrdmlahb, 1, int8_t, DO_VQRDMLAH_B)
160
+DO_2OP_SAT_ACC_SCALAR(vqrdmlahh, 2, int16_t, DO_VQRDMLAH_H)
161
+DO_2OP_SAT_ACC_SCALAR(vqrdmlahw, 4, int32_t, DO_VQRDMLAH_W)
162
+
163
+DO_2OP_SAT_ACC_SCALAR(vqdmlashb, 1, int8_t, DO_VQDMLASH_B)
164
+DO_2OP_SAT_ACC_SCALAR(vqdmlashh, 2, int16_t, DO_VQDMLASH_H)
165
+DO_2OP_SAT_ACC_SCALAR(vqdmlashw, 4, int32_t, DO_VQDMLASH_W)
166
+DO_2OP_SAT_ACC_SCALAR(vqrdmlashb, 1, int8_t, DO_VQRDMLASH_B)
167
+DO_2OP_SAT_ACC_SCALAR(vqrdmlashh, 2, int16_t, DO_VQRDMLASH_H)
168
+DO_2OP_SAT_ACC_SCALAR(vqrdmlashw, 4, int32_t, DO_VQRDMLASH_W)
169
+
170
/* Vector by scalar plus vector */
171
#define DO_VMLA(D, N, M) ((N) * (M) + (D))
172
173
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
174
index XXXXXXX..XXXXXXX 100644
175
--- a/target/arm/translate-mve.c
176
+++ b/target/arm/translate-mve.c
177
@@ -XXX,XX +XXX,XX @@ DO_2OP_SCALAR(VQRDMULH_scalar, vqrdmulh_scalar)
178
DO_2OP_SCALAR(VBRSR, vbrsr)
179
DO_2OP_SCALAR(VMLA, vmla)
180
DO_2OP_SCALAR(VMLAS, vmlas)
181
+DO_2OP_SCALAR(VQDMLAH, vqdmlah)
182
+DO_2OP_SCALAR(VQRDMLAH, vqrdmlah)
183
+DO_2OP_SCALAR(VQDMLASH, vqdmlash)
184
+DO_2OP_SCALAR(VQRDMLASH, vqrdmlash)
185
186
static bool trans_VQDMULLB_scalar(DisasContext *s, arg_2scalar *a)
187
{
188
--
111
--
189
2.20.1
112
2.34.1
190
191
diff view generated by jsdifflib
1
Implement the MVE 1-operand saturating operations VQABS and VQNEG.
1
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
2
2
3
Cubieboard now can boot directly from SD card, without the need to pass
4
`-kernel` parameter. Update Avocado tests to cover this functionality.
5
6
Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
7
Reviewed-by: Niek Linnenbank <nieklinnenbank@gmail.com>
8
Tested-by: Niek Linnenbank <nieklinnenbank@gmail.com>
9
Message-id: 20221226220303.14420-8-strahinja.p.jankovic@gmail.com
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
---
11
---
6
target/arm/helper-mve.h | 8 ++++++++
12
tests/avocado/boot_linux_console.py | 47 +++++++++++++++++++++++++++++
7
target/arm/mve.decode | 3 +++
13
1 file changed, 47 insertions(+)
8
target/arm/mve_helper.c | 37 +++++++++++++++++++++++++++++++++++++
9
target/arm/translate-mve.c | 2 ++
10
4 files changed, 50 insertions(+)
11
14
12
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
15
diff --git a/tests/avocado/boot_linux_console.py b/tests/avocado/boot_linux_console.py
13
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/helper-mve.h
17
--- a/tests/avocado/boot_linux_console.py
15
+++ b/target/arm/helper-mve.h
18
+++ b/tests/avocado/boot_linux_console.py
16
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vnegw, TCG_CALL_NO_WG, void, env, ptr, ptr)
19
@@ -XXX,XX +XXX,XX @@ def test_arm_cubieboard_sata(self):
17
DEF_HELPER_FLAGS_3(mve_vfnegh, TCG_CALL_NO_WG, void, env, ptr, ptr)
20
'sda')
18
DEF_HELPER_FLAGS_3(mve_vfnegs, TCG_CALL_NO_WG, void, env, ptr, ptr)
21
# cubieboard's reboot is not functioning; omit reboot test.
19
22
20
+DEF_HELPER_FLAGS_3(mve_vqabsb, TCG_CALL_NO_WG, void, env, ptr, ptr)
23
+ @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
21
+DEF_HELPER_FLAGS_3(mve_vqabsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
+ def test_arm_cubieboard_openwrt_22_03_2(self):
22
+DEF_HELPER_FLAGS_3(mve_vqabsw, TCG_CALL_NO_WG, void, env, ptr, ptr)
25
+ """
26
+ :avocado: tags=arch:arm
27
+ :avocado: tags=machine:cubieboard
28
+ :avocado: tags=device:sd
29
+ """
23
+
30
+
24
+DEF_HELPER_FLAGS_3(mve_vqnegb, TCG_CALL_NO_WG, void, env, ptr, ptr)
31
+ # This test download a 7.5 MiB compressed image and expand it
25
+DEF_HELPER_FLAGS_3(mve_vqnegh, TCG_CALL_NO_WG, void, env, ptr, ptr)
32
+ # to 126 MiB.
26
+DEF_HELPER_FLAGS_3(mve_vqnegw, TCG_CALL_NO_WG, void, env, ptr, ptr)
33
+ image_url = ('https://downloads.openwrt.org/releases/22.03.2/targets/'
34
+ 'sunxi/cortexa8/openwrt-22.03.2-sunxi-cortexa8-'
35
+ 'cubietech_a10-cubieboard-ext4-sdcard.img.gz')
36
+ image_hash = ('94b5ecbfbc0b3b56276e5146b899eafa'
37
+ '2ac5dc2d08733d6705af9f144f39f554')
38
+ image_path_gz = self.fetch_asset(image_url, asset_hash=image_hash,
39
+ algorithm='sha256')
40
+ image_path = archive.extract(image_path_gz, self.workdir)
41
+ image_pow2ceil_expand(image_path)
27
+
42
+
28
DEF_HELPER_FLAGS_3(mve_vmovnbb, TCG_CALL_NO_WG, void, env, ptr, ptr)
43
+ self.vm.set_console()
29
DEF_HELPER_FLAGS_3(mve_vmovnbh, TCG_CALL_NO_WG, void, env, ptr, ptr)
44
+ self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw',
30
DEF_HELPER_FLAGS_3(mve_vmovntb, TCG_CALL_NO_WG, void, env, ptr, ptr)
45
+ '-nic', 'user',
31
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
46
+ '-no-reboot')
32
index XXXXXXX..XXXXXXX 100644
47
+ self.vm.launch()
33
--- a/target/arm/mve.decode
34
+++ b/target/arm/mve.decode
35
@@ -XXX,XX +XXX,XX @@ VABS_fp 1111 1111 1 . 11 .. 01 ... 0 0111 01 . 0 ... 0 @1op
36
VNEG 1111 1111 1 . 11 .. 01 ... 0 0011 11 . 0 ... 0 @1op
37
VNEG_fp 1111 1111 1 . 11 .. 01 ... 0 0111 11 . 0 ... 0 @1op
38
39
+VQABS 1111 1111 1 . 11 .. 00 ... 0 0111 01 . 0 ... 0 @1op
40
+VQNEG 1111 1111 1 . 11 .. 00 ... 0 0111 11 . 0 ... 0 @1op
41
+
48
+
42
&vdup qd rt size
49
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
43
# Qd is in the fields usually named Qn
50
+ 'usbcore.nousb '
44
@vdup .... .... . . .. ... . rt:4 .... . . . . .... qd=%qn &vdup
51
+ 'noreboot')
45
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/mve_helper.c
48
+++ b/target/arm/mve_helper.c
49
@@ -XXX,XX +XXX,XX @@ void HELPER(mve_vpsel)(CPUARMState *env, void *vd, void *vn, void *vm)
50
}
51
mve_advance_vpt(env);
52
}
53
+
52
+
54
+#define DO_1OP_SAT(OP, ESIZE, TYPE, FN) \
53
+ self.wait_for_console_pattern('U-Boot SPL')
55
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm) \
56
+ { \
57
+ TYPE *d = vd, *m = vm; \
58
+ uint16_t mask = mve_element_mask(env); \
59
+ unsigned e; \
60
+ bool qc = false; \
61
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
62
+ bool sat = false; \
63
+ mergemask(&d[H##ESIZE(e)], FN(m[H##ESIZE(e)], &sat), mask); \
64
+ qc |= sat & mask & 1; \
65
+ } \
66
+ if (qc) { \
67
+ env->vfp.qc[0] = qc; \
68
+ } \
69
+ mve_advance_vpt(env); \
70
+ }
71
+
54
+
72
+#define DO_VQABS_B(N, SATP) \
55
+ interrupt_interactive_console_until_pattern(
73
+ do_sat_bhs(DO_ABS((int64_t)N), INT8_MIN, INT8_MAX, SATP)
56
+ self, 'Hit any key to stop autoboot:', '=>')
74
+#define DO_VQABS_H(N, SATP) \
57
+ exec_command_and_wait_for_pattern(self, "setenv extraargs '" +
75
+ do_sat_bhs(DO_ABS((int64_t)N), INT16_MIN, INT16_MAX, SATP)
58
+ kernel_command_line + "'", '=>')
76
+#define DO_VQABS_W(N, SATP) \
59
+ exec_command_and_wait_for_pattern(self, 'boot', 'Starting kernel ...');
77
+ do_sat_bhs(DO_ABS((int64_t)N), INT32_MIN, INT32_MAX, SATP)
78
+
60
+
79
+#define DO_VQNEG_B(N, SATP) do_sat_bhs(-(int64_t)N, INT8_MIN, INT8_MAX, SATP)
61
+ self.wait_for_console_pattern(
80
+#define DO_VQNEG_H(N, SATP) do_sat_bhs(-(int64_t)N, INT16_MIN, INT16_MAX, SATP)
62
+ 'Please press Enter to activate this console.')
81
+#define DO_VQNEG_W(N, SATP) do_sat_bhs(-(int64_t)N, INT32_MIN, INT32_MAX, SATP)
82
+
63
+
83
+DO_1OP_SAT(vqabsb, 1, int8_t, DO_VQABS_B)
64
+ exec_command_and_wait_for_pattern(self, ' ', 'root@')
84
+DO_1OP_SAT(vqabsh, 2, int16_t, DO_VQABS_H)
85
+DO_1OP_SAT(vqabsw, 4, int32_t, DO_VQABS_W)
86
+
65
+
87
+DO_1OP_SAT(vqnegb, 1, int8_t, DO_VQNEG_B)
66
+ exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
88
+DO_1OP_SAT(vqnegh, 2, int16_t, DO_VQNEG_H)
67
+ 'Allwinner sun4i/sun5i')
89
+DO_1OP_SAT(vqnegw, 4, int32_t, DO_VQNEG_W)
68
+ # cubieboard's reboot is not functioning; omit reboot test.
90
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
69
+
91
index XXXXXXX..XXXXXXX 100644
70
@skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout')
92
--- a/target/arm/translate-mve.c
71
def test_arm_quanta_gsj(self):
93
+++ b/target/arm/translate-mve.c
72
"""
94
@@ -XXX,XX +XXX,XX @@ DO_1OP(VCLZ, vclz)
95
DO_1OP(VCLS, vcls)
96
DO_1OP(VABS, vabs)
97
DO_1OP(VNEG, vneg)
98
+DO_1OP(VQABS, vqabs)
99
+DO_1OP(VQNEG, vqneg)
100
101
/* Narrowing moves: only size 0 and 1 are valid */
102
#define DO_VMOVN(INSN, FN) \
103
--
73
--
104
2.20.1
74
2.34.1
105
106
diff view generated by jsdifflib
1
We were not paying attention to the ECI state when advancing the VPT
1
From: Richard Henderson <richard.henderson@linaro.org>
2
state. Architecturally, VPT state advance happens for every beat
3
(see the pseudocode VPTAdvance()), so on every beat the 4 bits of
4
VPR.P0 corresponding to the current beat are inverted if required,
5
and at the end of beats 1 and 3 the VPR MASK fields are updated.
6
This means that if the ECI state says we should not be executing all
7
4 beats then we need to skip some of the updating of the VPR that we
8
currently do in mve_advance_vpt().
9
2
3
Don't dereference CPUTLBEntryFull until we verify that
4
the page is valid. Move the other user-only info field
5
updates after the valid check to match.
6
7
Cc: qemu-stable@nongnu.org
8
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1412
9
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Message-id: 20230104190056.305143-1-richard.henderson@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
---
13
---
13
target/arm/mve_helper.c | 24 +++++++++++++++++-------
14
target/arm/sve_helper.c | 14 +++++++++-----
14
1 file changed, 17 insertions(+), 7 deletions(-)
15
1 file changed, 9 insertions(+), 5 deletions(-)
15
16
16
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
17
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
17
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/mve_helper.c
19
--- a/target/arm/sve_helper.c
19
+++ b/target/arm/mve_helper.c
20
+++ b/target/arm/sve_helper.c
20
@@ -XXX,XX +XXX,XX @@ static void mve_advance_vpt(CPUARMState *env)
21
@@ -XXX,XX +XXX,XX @@ bool sve_probe_page(SVEHostPage *info, bool nofault, CPUARMState *env,
21
/* Advance the VPT and ECI state if necessary */
22
#ifdef CONFIG_USER_ONLY
22
uint32_t vpr = env->v7m.vpr;
23
flags = probe_access_flags(env, addr, access_type, mmu_idx, nofault,
23
unsigned mask01, mask23;
24
&info->host, retaddr);
24
+ uint16_t inv_mask;
25
- memset(&info->attrs, 0, sizeof(info->attrs));
25
+ uint16_t eci_mask = mve_eci_mask(env);
26
- /* Require both ANON and MTE; see allocation_tag_mem(). */
26
27
- info->tagged = (flags & PAGE_ANON) && (flags & PAGE_MTE);
27
if ((env->condexec_bits & 0xf) == 0) {
28
#else
28
env->condexec_bits = (env->condexec_bits == (ECI_A0A1A2B0 << 4)) ?
29
CPUTLBEntryFull *full;
29
@@ -XXX,XX +XXX,XX @@ static void mve_advance_vpt(CPUARMState *env)
30
flags = probe_access_full(env, addr, access_type, mmu_idx, nofault,
30
return;
31
&info->host, &full, retaddr);
32
- info->attrs = full->attrs;
33
- info->tagged = full->pte_attrs == 0xf0;
34
#endif
35
info->flags = flags;
36
37
@@ -XXX,XX +XXX,XX @@ bool sve_probe_page(SVEHostPage *info, bool nofault, CPUARMState *env,
38
return false;
31
}
39
}
32
40
33
+ /* Invert P0 bits if needed, but only for beats we actually executed */
41
+#ifdef CONFIG_USER_ONLY
34
mask01 = FIELD_EX32(vpr, V7M_VPR, MASK01);
42
+ memset(&info->attrs, 0, sizeof(info->attrs));
35
mask23 = FIELD_EX32(vpr, V7M_VPR, MASK23);
43
+ /* Require both ANON and MTE; see allocation_tag_mem(). */
36
- if (mask01 > 8) {
44
+ info->tagged = (flags & PAGE_ANON) && (flags & PAGE_MTE);
37
- /* high bit set, but not 0b1000: invert the relevant half of P0 */
45
+#else
38
- vpr ^= 0xff;
46
+ info->attrs = full->attrs;
39
+ /* Start by assuming we invert all bits corresponding to executed beats */
47
+ info->tagged = full->pte_attrs == 0xf0;
40
+ inv_mask = eci_mask;
48
+#endif
41
+ if (mask01 <= 8) {
49
+
42
+ /* MASK01 says don't invert low half of P0 */
50
/* Ensure that info->host[] is relative to addr, not addr + mem_off. */
43
+ inv_mask &= ~0xff;
51
info->host -= mem_off;
44
}
52
return true;
45
- if (mask23 > 8) {
46
- /* high bit set, but not 0b1000: invert the relevant half of P0 */
47
- vpr ^= 0xff00;
48
+ if (mask23 <= 8) {
49
+ /* MASK23 says don't invert high half of P0 */
50
+ inv_mask &= ~0xff00;
51
}
52
- vpr = FIELD_DP32(vpr, V7M_VPR, MASK01, mask01 << 1);
53
+ vpr ^= inv_mask;
54
+ /* Only update MASK01 if beat 1 executed */
55
+ if (eci_mask & 0xf0) {
56
+ vpr = FIELD_DP32(vpr, V7M_VPR, MASK01, mask01 << 1);
57
+ }
58
+ /* Beat 3 always executes, so update MASK23 */
59
vpr = FIELD_DP32(vpr, V7M_VPR, MASK23, mask23 << 1);
60
env->v7m.vpr = vpr;
61
}
62
--
53
--
63
2.20.1
54
2.34.1
64
55
65
56
diff view generated by jsdifflib
1
The MVEGenDualAccOpFn is a bit misnamed, since it is used for
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
the "long dual accumulate" operations that use a 64-bit
3
accumulator. Rename it to MVEGenLongDualAccOpFn so we can
4
use the former name for the 32-bit accumulator insns.
5
2
3
Since pxa255_init() must map the device in the system memory,
4
there is no point in passing get_system_memory() by argument.
5
6
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230109115316.2235-2-philmd@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
---
10
---
9
target/arm/translate-mve.c | 16 ++++++++--------
11
include/hw/arm/pxa.h | 2 +-
10
1 file changed, 8 insertions(+), 8 deletions(-)
12
hw/arm/gumstix.c | 3 +--
13
hw/arm/pxa2xx.c | 4 +++-
14
hw/arm/tosa.c | 2 +-
15
4 files changed, 6 insertions(+), 5 deletions(-)
11
16
12
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
17
diff --git a/include/hw/arm/pxa.h b/include/hw/arm/pxa.h
13
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/translate-mve.c
19
--- a/include/hw/arm/pxa.h
15
+++ b/target/arm/translate-mve.c
20
+++ b/include/hw/arm/pxa.h
16
@@ -XXX,XX +XXX,XX @@ typedef void MVEGenOneOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
21
@@ -XXX,XX +XXX,XX @@ struct PXA2xxI2SState {
17
typedef void MVEGenTwoOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr);
22
18
typedef void MVEGenTwoOpScalarFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
23
PXA2xxState *pxa270_init(MemoryRegion *address_space, unsigned int sdram_size,
19
typedef void MVEGenTwoOpShiftFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
24
const char *revision);
20
-typedef void MVEGenDualAccOpFn(TCGv_i64, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i64);
25
-PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size);
21
+typedef void MVEGenLongDualAccOpFn(TCGv_i64, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i64);
26
+PXA2xxState *pxa255_init(unsigned int sdram_size);
22
typedef void MVEGenVADDVFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32);
27
23
typedef void MVEGenOneOpImmFn(TCGv_ptr, TCGv_ptr, TCGv_i64);
28
#endif /* PXA_H */
24
typedef void MVEGenVIDUPFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32, TCGv_i32);
29
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
25
@@ -XXX,XX +XXX,XX @@ static bool trans_VQDMULLT_scalar(DisasContext *s, arg_2scalar *a)
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/gumstix.c
32
+++ b/hw/arm/gumstix.c
33
@@ -XXX,XX +XXX,XX @@ static void connex_init(MachineState *machine)
34
{
35
PXA2xxState *cpu;
36
DriveInfo *dinfo;
37
- MemoryRegion *address_space_mem = get_system_memory();
38
39
uint32_t connex_rom = 0x01000000;
40
uint32_t connex_ram = 0x04000000;
41
42
- cpu = pxa255_init(address_space_mem, connex_ram);
43
+ cpu = pxa255_init(connex_ram);
44
45
dinfo = drive_get(IF_PFLASH, 0, 0);
46
if (!dinfo && !qtest_enabled()) {
47
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/arm/pxa2xx.c
50
+++ b/hw/arm/pxa2xx.c
51
@@ -XXX,XX +XXX,XX @@
52
#include "qemu/error-report.h"
53
#include "qemu/module.h"
54
#include "qapi/error.h"
55
+#include "exec/address-spaces.h"
56
#include "cpu.h"
57
#include "hw/sysbus.h"
58
#include "migration/vmstate.h"
59
@@ -XXX,XX +XXX,XX @@ PXA2xxState *pxa270_init(MemoryRegion *address_space,
26
}
60
}
27
61
28
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
62
/* Initialise a PXA255 integrated chip (ARM based core). */
29
- MVEGenDualAccOpFn *fn)
63
-PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
30
+ MVEGenLongDualAccOpFn *fn)
64
+PXA2xxState *pxa255_init(unsigned int sdram_size)
31
{
65
{
32
TCGv_ptr qn, qm;
66
+ MemoryRegion *address_space = get_system_memory();
33
TCGv_i64 rda;
67
PXA2xxState *s;
34
@@ -XXX,XX +XXX,XX @@ static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
68
int i;
35
69
DriveInfo *dinfo;
36
static bool trans_VMLALDAV_S(DisasContext *s, arg_vmlaldav *a)
70
diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c
37
{
71
index XXXXXXX..XXXXXXX 100644
38
- static MVEGenDualAccOpFn * const fns[4][2] = {
72
--- a/hw/arm/tosa.c
39
+ static MVEGenLongDualAccOpFn * const fns[4][2] = {
73
+++ b/hw/arm/tosa.c
40
{ NULL, NULL },
74
@@ -XXX,XX +XXX,XX @@ static void tosa_init(MachineState *machine)
41
{ gen_helper_mve_vmlaldavsh, gen_helper_mve_vmlaldavxsh },
75
TC6393xbState *tmio;
42
{ gen_helper_mve_vmlaldavsw, gen_helper_mve_vmlaldavxsw },
76
DeviceState *scp0, *scp1;
43
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLALDAV_S(DisasContext *s, arg_vmlaldav *a)
77
44
78
- mpu = pxa255_init(address_space_mem, tosa_binfo.ram_size);
45
static bool trans_VMLALDAV_U(DisasContext *s, arg_vmlaldav *a)
79
+ mpu = pxa255_init(tosa_binfo.ram_size);
46
{
80
47
- static MVEGenDualAccOpFn * const fns[4][2] = {
81
memory_region_init_rom(rom, NULL, "tosa.rom", TOSA_ROM, &error_fatal);
48
+ static MVEGenLongDualAccOpFn * const fns[4][2] = {
82
memory_region_add_subregion(address_space_mem, 0, rom);
49
{ NULL, NULL },
50
{ gen_helper_mve_vmlaldavuh, NULL },
51
{ gen_helper_mve_vmlaldavuw, NULL },
52
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLALDAV_U(DisasContext *s, arg_vmlaldav *a)
53
54
static bool trans_VMLSLDAV(DisasContext *s, arg_vmlaldav *a)
55
{
56
- static MVEGenDualAccOpFn * const fns[4][2] = {
57
+ static MVEGenLongDualAccOpFn * const fns[4][2] = {
58
{ NULL, NULL },
59
{ gen_helper_mve_vmlsldavsh, gen_helper_mve_vmlsldavxsh },
60
{ gen_helper_mve_vmlsldavsw, gen_helper_mve_vmlsldavxsw },
61
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLSLDAV(DisasContext *s, arg_vmlaldav *a)
62
63
static bool trans_VRMLALDAVH_S(DisasContext *s, arg_vmlaldav *a)
64
{
65
- static MVEGenDualAccOpFn * const fns[] = {
66
+ static MVEGenLongDualAccOpFn * const fns[] = {
67
gen_helper_mve_vrmlaldavhsw, gen_helper_mve_vrmlaldavhxsw,
68
};
69
return do_long_dual_acc(s, a, fns[a->x]);
70
@@ -XXX,XX +XXX,XX @@ static bool trans_VRMLALDAVH_S(DisasContext *s, arg_vmlaldav *a)
71
72
static bool trans_VRMLALDAVH_U(DisasContext *s, arg_vmlaldav *a)
73
{
74
- static MVEGenDualAccOpFn * const fns[] = {
75
+ static MVEGenLongDualAccOpFn * const fns[] = {
76
gen_helper_mve_vrmlaldavhuw, NULL,
77
};
78
return do_long_dual_acc(s, a, fns[a->x]);
79
@@ -XXX,XX +XXX,XX @@ static bool trans_VRMLALDAVH_U(DisasContext *s, arg_vmlaldav *a)
80
81
static bool trans_VRMLSLDAVH(DisasContext *s, arg_vmlaldav *a)
82
{
83
- static MVEGenDualAccOpFn * const fns[] = {
84
+ static MVEGenLongDualAccOpFn * const fns[] = {
85
gen_helper_mve_vrmlsldavhsw, gen_helper_mve_vrmlsldavhxsw,
86
};
87
return do_long_dual_acc(s, a, fns[a->x]);
88
--
83
--
89
2.20.1
84
2.34.1
90
85
91
86
diff view generated by jsdifflib
1
Implement the MVE VMAXA and VMINA insns, which take the absolute
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
value of the signed elements in the input vector and then accumulate
3
the unsigned max or min into the destination vector.
4
2
3
Since pxa270_init() must map the device in the system memory,
4
there is no point in passing get_system_memory() by argument.
5
6
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230109115316.2235-3-philmd@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
---
10
---
8
target/arm/helper-mve.h | 8 ++++++++
11
include/hw/arm/pxa.h | 3 +--
9
target/arm/mve.decode | 4 ++++
12
hw/arm/gumstix.c | 3 +--
10
target/arm/mve_helper.c | 26 ++++++++++++++++++++++++++
13
hw/arm/mainstone.c | 10 ++++------
11
target/arm/translate-mve.c | 2 ++
14
hw/arm/pxa2xx.c | 4 ++--
12
4 files changed, 40 insertions(+)
15
hw/arm/spitz.c | 6 ++----
16
hw/arm/z2.c | 3 +--
17
6 files changed, 11 insertions(+), 18 deletions(-)
13
18
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
19
diff --git a/include/hw/arm/pxa.h b/include/hw/arm/pxa.h
15
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-mve.h
21
--- a/include/hw/arm/pxa.h
17
+++ b/target/arm/helper-mve.h
22
+++ b/include/hw/arm/pxa.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vqnegb, TCG_CALL_NO_WG, void, env, ptr, ptr)
23
@@ -XXX,XX +XXX,XX @@ struct PXA2xxI2SState {
19
DEF_HELPER_FLAGS_3(mve_vqnegh, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
20
DEF_HELPER_FLAGS_3(mve_vqnegw, TCG_CALL_NO_WG, void, env, ptr, ptr)
25
# define PA_FMT            "0x%08lx"
21
26
22
+DEF_HELPER_FLAGS_3(mve_vmaxab, TCG_CALL_NO_WG, void, env, ptr, ptr)
27
-PXA2xxState *pxa270_init(MemoryRegion *address_space, unsigned int sdram_size,
23
+DEF_HELPER_FLAGS_3(mve_vmaxah, TCG_CALL_NO_WG, void, env, ptr, ptr)
28
- const char *revision);
24
+DEF_HELPER_FLAGS_3(mve_vmaxaw, TCG_CALL_NO_WG, void, env, ptr, ptr)
29
+PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision);
25
+
30
PXA2xxState *pxa255_init(unsigned int sdram_size);
26
+DEF_HELPER_FLAGS_3(mve_vminab, TCG_CALL_NO_WG, void, env, ptr, ptr)
31
27
+DEF_HELPER_FLAGS_3(mve_vminah, TCG_CALL_NO_WG, void, env, ptr, ptr)
32
#endif /* PXA_H */
28
+DEF_HELPER_FLAGS_3(mve_vminaw, TCG_CALL_NO_WG, void, env, ptr, ptr)
33
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
29
+
30
DEF_HELPER_FLAGS_3(mve_vmovnbb, TCG_CALL_NO_WG, void, env, ptr, ptr)
31
DEF_HELPER_FLAGS_3(mve_vmovnbh, TCG_CALL_NO_WG, void, env, ptr, ptr)
32
DEF_HELPER_FLAGS_3(mve_vmovntb, TCG_CALL_NO_WG, void, env, ptr, ptr)
33
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
34
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/mve.decode
35
--- a/hw/arm/gumstix.c
36
+++ b/target/arm/mve.decode
36
+++ b/hw/arm/gumstix.c
37
@@ -XXX,XX +XXX,XX @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
37
@@ -XXX,XX +XXX,XX @@ static void verdex_init(MachineState *machine)
38
VQMOVUNB 111 0 1110 0 . 11 .. 01 ... 0 1110 1 0 . 0 ... 1 @1op
38
{
39
VQMOVN_BS 111 0 1110 0 . 11 .. 11 ... 0 1110 0 0 . 0 ... 1 @1op
39
PXA2xxState *cpu;
40
40
DriveInfo *dinfo;
41
+ VMAXA 111 0 1110 0 . 11 .. 11 ... 0 1110 1 0 . 0 ... 1 @1op
41
- MemoryRegion *address_space_mem = get_system_memory();
42
+
42
43
VMULH_S 111 0 1110 0 . .. ...1 ... 0 1110 . 0 . 0 ... 1 @2op
43
uint32_t verdex_rom = 0x02000000;
44
uint32_t verdex_ram = 0x10000000;
45
46
- cpu = pxa270_init(address_space_mem, verdex_ram, machine->cpu_type);
47
+ cpu = pxa270_init(verdex_ram, machine->cpu_type);
48
49
dinfo = drive_get(IF_PFLASH, 0, 0);
50
if (!dinfo && !qtest_enabled()) {
51
diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/hw/arm/mainstone.c
54
+++ b/hw/arm/mainstone.c
55
@@ -XXX,XX +XXX,XX @@ static struct arm_boot_info mainstone_binfo = {
56
.ram_size = 0x04000000,
57
};
58
59
-static void mainstone_common_init(MemoryRegion *address_space_mem,
60
- MachineState *machine,
61
+static void mainstone_common_init(MachineState *machine,
62
enum mainstone_model_e model, int arm_id)
63
{
64
uint32_t sector_len = 256 * 1024;
65
@@ -XXX,XX +XXX,XX @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
66
MemoryRegion *rom = g_new(MemoryRegion, 1);
67
68
/* Setup CPU & memory */
69
- mpu = pxa270_init(address_space_mem, mainstone_binfo.ram_size,
70
- machine->cpu_type);
71
+ mpu = pxa270_init(mainstone_binfo.ram_size, machine->cpu_type);
72
memory_region_init_rom(rom, NULL, "mainstone.rom", MAINSTONE_ROM,
73
&error_fatal);
74
- memory_region_add_subregion(address_space_mem, 0, rom);
75
+ memory_region_add_subregion(get_system_memory(), 0x00000000, rom);
76
77
/* There are two 32MiB flash devices on the board */
78
for (i = 0; i < 2; i ++) {
79
@@ -XXX,XX +XXX,XX @@ static void mainstone_common_init(MemoryRegion *address_space_mem,
80
81
static void mainstone_init(MachineState *machine)
82
{
83
- mainstone_common_init(get_system_memory(), machine, mainstone, 0x196);
84
+ mainstone_common_init(machine, mainstone, 0x196);
44
}
85
}
45
86
46
@@ -XXX,XX +XXX,XX @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
87
static void mainstone2_machine_init(MachineClass *mc)
47
VQMOVUNT 111 0 1110 0 . 11 .. 01 ... 1 1110 1 0 . 0 ... 1 @1op
88
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
48
VQMOVN_TS 111 0 1110 0 . 11 .. 11 ... 1 1110 0 0 . 0 ... 1 @1op
89
index XXXXXXX..XXXXXXX 100644
49
90
--- a/hw/arm/pxa2xx.c
50
+ VMINA 111 0 1110 0 . 11 .. 11 ... 1 1110 1 0 . 0 ... 1 @1op
91
+++ b/hw/arm/pxa2xx.c
51
+
92
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_reset(void *opaque, int line, int level)
52
VRMULH_S 111 0 1110 0 . .. ...1 ... 1 1110 . 0 . 0 ... 1 @2op
53
}
93
}
54
94
55
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
95
/* Initialise a PXA270 integrated chip (ARM based core). */
96
-PXA2xxState *pxa270_init(MemoryRegion *address_space,
97
- unsigned int sdram_size, const char *cpu_type)
98
+PXA2xxState *pxa270_init(unsigned int sdram_size, const char *cpu_type)
99
{
100
+ MemoryRegion *address_space = get_system_memory();
101
PXA2xxState *s;
102
int i;
103
DriveInfo *dinfo;
104
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
56
index XXXXXXX..XXXXXXX 100644
105
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/mve_helper.c
106
--- a/hw/arm/spitz.c
58
+++ b/target/arm/mve_helper.c
107
+++ b/hw/arm/spitz.c
59
@@ -XXX,XX +XXX,XX @@ DO_1OP_SAT(vqabsw, 4, int32_t, DO_VQABS_W)
108
@@ -XXX,XX +XXX,XX @@ static void spitz_common_init(MachineState *machine)
60
DO_1OP_SAT(vqnegb, 1, int8_t, DO_VQNEG_B)
109
SpitzMachineState *sms = SPITZ_MACHINE(machine);
61
DO_1OP_SAT(vqnegh, 2, int16_t, DO_VQNEG_H)
110
enum spitz_model_e model = smc->model;
62
DO_1OP_SAT(vqnegw, 4, int32_t, DO_VQNEG_W)
111
PXA2xxState *mpu;
63
+
112
- MemoryRegion *address_space_mem = get_system_memory();
64
+/*
113
MemoryRegion *rom = g_new(MemoryRegion, 1);
65
+ * VMAXA, VMINA: vd is unsigned; vm is signed, and we take its
114
66
+ * absolute value; we then do an unsigned comparison.
115
/* Setup CPU & memory */
67
+ */
116
- mpu = pxa270_init(address_space_mem, spitz_binfo.ram_size,
68
+#define DO_VMAXMINA(OP, ESIZE, STYPE, UTYPE, FN) \
117
- machine->cpu_type);
69
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm) \
118
+ mpu = pxa270_init(spitz_binfo.ram_size, machine->cpu_type);
70
+ { \
119
sms->mpu = mpu;
71
+ UTYPE *d = vd; \
120
72
+ STYPE *m = vm; \
121
sl_flash_register(mpu, (model == spitz) ? FLASH_128M : FLASH_1024M);
73
+ uint16_t mask = mve_element_mask(env); \
122
74
+ unsigned e; \
123
memory_region_init_rom(rom, NULL, "spitz.rom", SPITZ_ROM, &error_fatal);
75
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
124
- memory_region_add_subregion(address_space_mem, 0, rom);
76
+ UTYPE r = DO_ABS(m[H##ESIZE(e)]); \
125
+ memory_region_add_subregion(get_system_memory(), 0, rom);
77
+ r = FN(d[H##ESIZE(e)], r); \
126
78
+ mergemask(&d[H##ESIZE(e)], r, mask); \
127
/* Setup peripherals */
79
+ } \
128
spitz_keyboard_register(mpu);
80
+ mve_advance_vpt(env); \
129
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
81
+ }
82
+
83
+DO_VMAXMINA(vmaxab, 1, int8_t, uint8_t, DO_MAX)
84
+DO_VMAXMINA(vmaxah, 2, int16_t, uint16_t, DO_MAX)
85
+DO_VMAXMINA(vmaxaw, 4, int32_t, uint32_t, DO_MAX)
86
+DO_VMAXMINA(vminab, 1, int8_t, uint8_t, DO_MIN)
87
+DO_VMAXMINA(vminah, 2, int16_t, uint16_t, DO_MIN)
88
+DO_VMAXMINA(vminaw, 4, int32_t, uint32_t, DO_MIN)
89
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
90
index XXXXXXX..XXXXXXX 100644
130
index XXXXXXX..XXXXXXX 100644
91
--- a/target/arm/translate-mve.c
131
--- a/hw/arm/z2.c
92
+++ b/target/arm/translate-mve.c
132
+++ b/hw/arm/z2.c
93
@@ -XXX,XX +XXX,XX @@ DO_1OP(VABS, vabs)
133
@@ -XXX,XX +XXX,XX @@ static const TypeInfo aer915_info = {
94
DO_1OP(VNEG, vneg)
134
95
DO_1OP(VQABS, vqabs)
135
static void z2_init(MachineState *machine)
96
DO_1OP(VQNEG, vqneg)
136
{
97
+DO_1OP(VMAXA, vmaxa)
137
- MemoryRegion *address_space_mem = get_system_memory();
98
+DO_1OP(VMINA, vmina)
138
uint32_t sector_len = 0x10000;
99
139
PXA2xxState *mpu;
100
/* Narrowing moves: only size 0 and 1 are valid */
140
DriveInfo *dinfo;
101
#define DO_VMOVN(INSN, FN) \
141
@@ -XXX,XX +XXX,XX @@ static void z2_init(MachineState *machine)
142
DeviceState *wm;
143
144
/* Setup CPU & memory */
145
- mpu = pxa270_init(address_space_mem, z2_binfo.ram_size, machine->cpu_type);
146
+ mpu = pxa270_init(z2_binfo.ram_size, machine->cpu_type);
147
148
dinfo = drive_get(IF_PFLASH, 0, 0);
149
if (!pflash_cfi01_register(Z2_FLASH_BASE, "z2.flash0", Z2_FLASH_SIZE,
102
--
150
--
103
2.20.1
151
2.34.1
104
152
105
153
diff view generated by jsdifflib
1
In some situations we need a mask telling us which parts of the
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
vector correspond to beats that are not being executed because of
3
ECI, separately from the combined "which bytes are predicated away"
4
mask. Factor this mask calculation out of mve_element_mask() into
5
its own function.
6
2
3
IEC binary prefixes ease code review: the unit is explicit.
4
5
Add definitions for RAM / Flash / Flash blocksize.
6
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230109115316.2235-4-philmd@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
---
11
---
10
target/arm/mve_helper.c | 58 ++++++++++++++++++++++++-----------------
12
hw/arm/collie.c | 16 ++++++++++------
11
1 file changed, 34 insertions(+), 24 deletions(-)
13
1 file changed, 10 insertions(+), 6 deletions(-)
12
14
13
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
15
diff --git a/hw/arm/collie.c b/hw/arm/collie.c
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/mve_helper.c
17
--- a/hw/arm/collie.c
16
+++ b/target/arm/mve_helper.c
18
+++ b/hw/arm/collie.c
17
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
18
#include "exec/exec-all.h"
20
#include "cpu.h"
19
#include "tcg/tcg.h"
21
#include "qom/object.h"
20
22
21
+static uint16_t mve_eci_mask(CPUARMState *env)
23
+#define RAM_SIZE (512 * MiB)
22
+{
24
+#define FLASH_SIZE (32 * MiB)
23
+ /*
25
+#define FLASH_SECTOR_SIZE (64 * KiB)
24
+ * Return the mask of which elements in the MVE vector correspond
25
+ * to beats being executed. The mask has 1 bits for executed lanes
26
+ * and 0 bits where ECI says this beat was already executed.
27
+ */
28
+ int eci;
29
+
26
+
30
+ if ((env->condexec_bits & 0xf) != 0) {
27
struct CollieMachineState {
31
+ return 0xffff;
28
MachineState parent;
32
+ }
29
33
+
30
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(CollieMachineState, COLLIE_MACHINE)
34
+ eci = env->condexec_bits >> 4;
31
35
+ switch (eci) {
32
static struct arm_boot_info collie_binfo = {
36
+ case ECI_NONE:
33
.loader_start = SA_SDCS0,
37
+ return 0xffff;
34
- .ram_size = 0x20000000,
38
+ case ECI_A0:
35
+ .ram_size = RAM_SIZE,
39
+ return 0xfff0;
36
};
40
+ case ECI_A0A1:
37
41
+ return 0xff00;
38
static void collie_init(MachineState *machine)
42
+ case ECI_A0A1A2:
39
@@ -XXX,XX +XXX,XX @@ static void collie_init(MachineState *machine)
43
+ case ECI_A0A1A2B0:
40
memory_region_add_subregion(get_system_memory(), SA_SDCS0, machine->ram);
44
+ return 0xf000;
41
45
+ default:
42
dinfo = drive_get(IF_PFLASH, 0, 0);
46
+ g_assert_not_reached();
43
- pflash_cfi01_register(SA_CS0, "collie.fl1", 0x02000000,
47
+ }
44
+ pflash_cfi01_register(SA_CS0, "collie.fl1", FLASH_SIZE,
48
+}
45
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
49
+
46
- 64 * KiB, 4, 0x00, 0x00, 0x00, 0x00, 0);
50
static uint16_t mve_element_mask(CPUARMState *env)
47
+ FLASH_SECTOR_SIZE, 4, 0x00, 0x00, 0x00, 0x00, 0);
51
{
48
52
/*
49
dinfo = drive_get(IF_PFLASH, 0, 1);
53
@@ -XXX,XX +XXX,XX @@ static uint16_t mve_element_mask(CPUARMState *env)
50
- pflash_cfi01_register(SA_CS1, "collie.fl2", 0x02000000,
54
mask &= ltpmask;
51
+ pflash_cfi01_register(SA_CS1, "collie.fl2", FLASH_SIZE,
55
}
52
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
56
53
- 64 * KiB, 4, 0x00, 0x00, 0x00, 0x00, 0);
57
- if ((env->condexec_bits & 0xf) == 0) {
54
+ FLASH_SECTOR_SIZE, 4, 0x00, 0x00, 0x00, 0x00, 0);
58
- /*
55
59
- * ECI bits indicate which beats are already executed;
56
sysbus_create_simple("scoop", 0x40800000, NULL);
60
- * we handle this by effectively predicating them out.
57
61
- */
58
@@ -XXX,XX +XXX,XX @@ static void collie_machine_class_init(ObjectClass *oc, void *data)
62
- int eci = env->condexec_bits >> 4;
59
mc->init = collie_init;
63
- switch (eci) {
60
mc->ignore_memory_transaction_failures = true;
64
- case ECI_NONE:
61
mc->default_cpu_type = ARM_CPU_TYPE_NAME("sa1110");
65
- break;
62
- mc->default_ram_size = 0x20000000;
66
- case ECI_A0:
63
+ mc->default_ram_size = RAM_SIZE;
67
- mask &= 0xfff0;
64
mc->default_ram_id = "strongarm.sdram";
68
- break;
69
- case ECI_A0A1:
70
- mask &= 0xff00;
71
- break;
72
- case ECI_A0A1A2:
73
- case ECI_A0A1A2B0:
74
- mask &= 0xf000;
75
- break;
76
- default:
77
- g_assert_not_reached();
78
- }
79
- }
80
-
81
+ /*
82
+ * ECI bits indicate which beats are already executed;
83
+ * we handle this by effectively predicating them out.
84
+ */
85
+ mask &= mve_eci_mask(env);
86
return mask;
87
}
65
}
88
66
89
--
67
--
90
2.20.1
68
2.34.1
91
69
92
70
diff view generated by jsdifflib
1
From: Sebastian Meyer <meyer@absint.com>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
With gdb 9.0 and better it is possible to connect to a gdbstub
3
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
over unix sockets, which is better than a TCP socket connection
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
in some situations. The QEMU command line to set this up is
5
Message-id: 20230109115316.2235-5-philmd@linaro.org
6
non-obvious; document it.
7
8
Signed-off-by: Sebastian Meyer <meyer@absint.com>
9
Message-id: 162867284829.27377.4784930719350564918-0@git.sr.ht
10
[PMM: Tweaked commit message; adjusted wording in a couple of
11
places; fixed rST formatting issue; moved section up out of
12
the 'advanced debugging options' subsection]
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
7
---
17
docs/system/gdb.rst | 26 +++++++++++++++++++++++++-
8
hw/arm/collie.c | 17 +++++++----------
18
1 file changed, 25 insertions(+), 1 deletion(-)
9
1 file changed, 7 insertions(+), 10 deletions(-)
19
10
20
diff --git a/docs/system/gdb.rst b/docs/system/gdb.rst
11
diff --git a/hw/arm/collie.c b/hw/arm/collie.c
21
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
22
--- a/docs/system/gdb.rst
13
--- a/hw/arm/collie.c
23
+++ b/docs/system/gdb.rst
14
+++ b/hw/arm/collie.c
24
@@ -XXX,XX +XXX,XX @@ The ``-s`` option will make QEMU listen for an incoming connection
15
@@ -XXX,XX +XXX,XX @@ static struct arm_boot_info collie_binfo = {
25
from gdb on TCP port 1234, and ``-S`` will make QEMU not start the
16
26
guest until you tell it to from gdb. (If you want to specify which
17
static void collie_init(MachineState *machine)
27
TCP port to use or to use something other than TCP for the gdbstub
18
{
28
-connection, use the ``-gdb dev`` option instead of ``-s``.)
19
- DriveInfo *dinfo;
29
+connection, use the ``-gdb dev`` option instead of ``-s``. See
20
MachineClass *mc = MACHINE_GET_CLASS(machine);
30
+`Using unix sockets`_ for an example.)
21
CollieMachineState *cms = COLLIE_MACHINE(machine);
31
22
32
.. parsed-literal::
23
@@ -XXX,XX +XXX,XX @@ static void collie_init(MachineState *machine)
33
24
34
@@ -XXX,XX +XXX,XX @@ not just those in the cluster you are currently working on::
25
memory_region_add_subregion(get_system_memory(), SA_SDCS0, machine->ram);
35
26
36
(gdb) set schedule-multiple on
27
- dinfo = drive_get(IF_PFLASH, 0, 0);
37
28
- pflash_cfi01_register(SA_CS0, "collie.fl1", FLASH_SIZE,
38
+Using unix sockets
29
- dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
39
+==================
30
- FLASH_SECTOR_SIZE, 4, 0x00, 0x00, 0x00, 0x00, 0);
40
+
31
-
41
+An alternate method for connecting gdb to the QEMU gdbstub is to use
32
- dinfo = drive_get(IF_PFLASH, 0, 1);
42
+a unix socket (if supported by your operating system). This is useful when
33
- pflash_cfi01_register(SA_CS1, "collie.fl2", FLASH_SIZE,
43
+running several tests in parallel, or if you do not have a known free TCP
34
- dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
44
+port (e.g. when running automated tests).
35
- FLASH_SECTOR_SIZE, 4, 0x00, 0x00, 0x00, 0x00, 0);
45
+
36
+ for (unsigned i = 0; i < 2; i++) {
46
+First create a chardev with the appropriate options, then
37
+ DriveInfo *dinfo = drive_get(IF_PFLASH, 0, i);
47
+instruct the gdbserver to use that device:
38
+ pflash_cfi01_register(i ? SA_CS1 : SA_CS0,
48
+
39
+ i ? "collie.fl2" : "collie.fl1", FLASH_SIZE,
49
+.. parsed-literal::
40
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
50
+
41
+ FLASH_SECTOR_SIZE, 4, 0x00, 0x00, 0x00, 0x00, 0);
51
+ |qemu_system| -chardev socket,path=/tmp/gdb-socket,server=on,wait=off,id=gdb0 -gdb chardev:gdb0 -S ...
42
+ }
52
+
43
53
+Start gdb as before, but this time connect using the path to
44
sysbus_create_simple("scoop", 0x40800000, NULL);
54
+the socket::
55
+
56
+ (gdb) target remote /tmp/gdb-socket
57
+
58
+Note that to use a unix socket for the connection you will need
59
+gdb version 9.0 or newer.
60
+
61
Advanced debugging options
62
==========================
63
45
64
--
46
--
65
2.20.1
47
2.34.1
66
48
67
49
diff view generated by jsdifflib
1
Implement the MVE integer vector comparison instructions that compare
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
each element against a scalar from a general purpose register. These
3
are "VCMP (vector)" encodings T4, T5 and T6 and "VPT (vector)"
4
encodings T4, T5 and T6.
5
2
6
We have to move the decodetree pattern for VPST, because it
3
Add a comment describing the Connex uses a Numonyx RC28F128J3F75
7
overlaps with VCMP T4 with size = 0b11.
4
flash, and the Verdex uses a Micron RC28F256P30TFA.
8
5
6
Correct the Verdex machine description (we model the 'Pro' board).
7
8
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20230109115316.2235-6-philmd@linaro.org
11
Message-Id: <20200223231044.8003-3-philmd@redhat.com>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
---
13
---
12
target/arm/helper-mve.h | 32 +++++++++++++++++++++++++++
14
hw/arm/gumstix.c | 6 ++++--
13
target/arm/mve.decode | 18 +++++++++++++---
15
1 file changed, 4 insertions(+), 2 deletions(-)
14
target/arm/mve_helper.c | 44 +++++++++++++++++++++++++++++++-------
15
target/arm/translate-mve.c | 43 +++++++++++++++++++++++++++++++++++++
16
4 files changed, 126 insertions(+), 11 deletions(-)
17
16
18
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
17
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
19
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper-mve.h
19
--- a/hw/arm/gumstix.c
21
+++ b/target/arm/helper-mve.h
20
+++ b/hw/arm/gumstix.c
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vcmpgtw, TCG_CALL_NO_WG, void, env, ptr, ptr)
21
@@ -XXX,XX +XXX,XX @@
23
DEF_HELPER_FLAGS_3(mve_vcmpleb, TCG_CALL_NO_WG, void, env, ptr, ptr)
22
* Contributions after 2012-01-13 are licensed under the terms of the
24
DEF_HELPER_FLAGS_3(mve_vcmpleh, TCG_CALL_NO_WG, void, env, ptr, ptr)
23
* GNU GPL, version 2 or (at your option) any later version.
25
DEF_HELPER_FLAGS_3(mve_vcmplew, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
*/
25
-
26
+
26
+
27
+DEF_HELPER_FLAGS_3(mve_vcmpeq_scalarb, TCG_CALL_NO_WG, void, env, ptr, i32)
27
/*
28
+DEF_HELPER_FLAGS_3(mve_vcmpeq_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
28
* Example usage:
29
+DEF_HELPER_FLAGS_3(mve_vcmpeq_scalarw, TCG_CALL_NO_WG, void, env, ptr, i32)
29
*
30
+
30
@@ -XXX,XX +XXX,XX @@ static void connex_init(MachineState *machine)
31
+DEF_HELPER_FLAGS_3(mve_vcmpne_scalarb, TCG_CALL_NO_WG, void, env, ptr, i32)
31
exit(1);
32
+DEF_HELPER_FLAGS_3(mve_vcmpne_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
33
+DEF_HELPER_FLAGS_3(mve_vcmpne_scalarw, TCG_CALL_NO_WG, void, env, ptr, i32)
34
+
35
+DEF_HELPER_FLAGS_3(mve_vcmpcs_scalarb, TCG_CALL_NO_WG, void, env, ptr, i32)
36
+DEF_HELPER_FLAGS_3(mve_vcmpcs_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
37
+DEF_HELPER_FLAGS_3(mve_vcmpcs_scalarw, TCG_CALL_NO_WG, void, env, ptr, i32)
38
+
39
+DEF_HELPER_FLAGS_3(mve_vcmphi_scalarb, TCG_CALL_NO_WG, void, env, ptr, i32)
40
+DEF_HELPER_FLAGS_3(mve_vcmphi_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
41
+DEF_HELPER_FLAGS_3(mve_vcmphi_scalarw, TCG_CALL_NO_WG, void, env, ptr, i32)
42
+
43
+DEF_HELPER_FLAGS_3(mve_vcmpge_scalarb, TCG_CALL_NO_WG, void, env, ptr, i32)
44
+DEF_HELPER_FLAGS_3(mve_vcmpge_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
45
+DEF_HELPER_FLAGS_3(mve_vcmpge_scalarw, TCG_CALL_NO_WG, void, env, ptr, i32)
46
+
47
+DEF_HELPER_FLAGS_3(mve_vcmplt_scalarb, TCG_CALL_NO_WG, void, env, ptr, i32)
48
+DEF_HELPER_FLAGS_3(mve_vcmplt_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
49
+DEF_HELPER_FLAGS_3(mve_vcmplt_scalarw, TCG_CALL_NO_WG, void, env, ptr, i32)
50
+
51
+DEF_HELPER_FLAGS_3(mve_vcmpgt_scalarb, TCG_CALL_NO_WG, void, env, ptr, i32)
52
+DEF_HELPER_FLAGS_3(mve_vcmpgt_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
53
+DEF_HELPER_FLAGS_3(mve_vcmpgt_scalarw, TCG_CALL_NO_WG, void, env, ptr, i32)
54
+
55
+DEF_HELPER_FLAGS_3(mve_vcmple_scalarb, TCG_CALL_NO_WG, void, env, ptr, i32)
56
+DEF_HELPER_FLAGS_3(mve_vcmple_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
57
+DEF_HELPER_FLAGS_3(mve_vcmple_scalarw, TCG_CALL_NO_WG, void, env, ptr, i32)
58
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
59
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/mve.decode
61
+++ b/target/arm/mve.decode
62
@@ -XXX,XX +XXX,XX @@
63
&vidup qd rn size imm
64
&viwdup qd rn rm size imm
65
&vcmp qm qn size mask
66
+&vcmp_scalar qn rm size mask
67
68
@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
69
# Note that both Rn and Qd are 3 bits only (no D bit)
70
@@ -XXX,XX +XXX,XX @@
71
# Vector comparison; 4-bit Qm but 3-bit Qn
72
%mask_22_13 22:1 13:3
73
@vcmp .... .... .. size:2 qn:3 . .... .... .... .... &vcmp qm=%qm mask=%mask_22_13
74
+@vcmp_scalar .... .... .. size:2 qn:3 . .... .... .... rm:4 &vcmp_scalar \
75
+ mask=%mask_22_13
76
77
# Vector loads and stores
78
79
@@ -XXX,XX +XXX,XX @@ VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
80
rdahi=%rdahi rdalo=%rdalo
81
}
82
83
-# Predicate operations
84
-VPST 1111 1110 0 . 11 000 1 ... 0 1111 0100 1101 mask=%mask_22_13
85
-
86
# Logical immediate operations (1 reg and modified-immediate)
87
88
# The cmode/op bits here decode VORR/VBIC/VMOV/VMVN, but
89
@@ -XXX,XX +XXX,XX @@ VCMPGE 1111 1110 0 . .. ... 1 ... 1 1111 0 0 . 0 ... 0 @vcmp
90
VCMPLT 1111 1110 0 . .. ... 1 ... 1 1111 1 0 . 0 ... 0 @vcmp
91
VCMPGT 1111 1110 0 . .. ... 1 ... 1 1111 0 0 . 0 ... 1 @vcmp
92
VCMPLE 1111 1110 0 . .. ... 1 ... 1 1111 1 0 . 0 ... 1 @vcmp
93
+
94
+{
95
+ VPST 1111 1110 0 . 11 000 1 ... 0 1111 0100 1101 mask=%mask_22_13
96
+ VCMPEQ_scalar 1111 1110 0 . .. ... 1 ... 0 1111 0 1 0 0 .... @vcmp_scalar
97
+}
98
+VCMPNE_scalar 1111 1110 0 . .. ... 1 ... 0 1111 1 1 0 0 .... @vcmp_scalar
99
+VCMPCS_scalar 1111 1110 0 . .. ... 1 ... 0 1111 0 1 1 0 .... @vcmp_scalar
100
+VCMPHI_scalar 1111 1110 0 . .. ... 1 ... 0 1111 1 1 1 0 .... @vcmp_scalar
101
+VCMPGE_scalar 1111 1110 0 . .. ... 1 ... 1 1111 0 1 0 0 .... @vcmp_scalar
102
+VCMPLT_scalar 1111 1110 0 . .. ... 1 ... 1 1111 1 1 0 0 .... @vcmp_scalar
103
+VCMPGT_scalar 1111 1110 0 . .. ... 1 ... 1 1111 0 1 1 0 .... @vcmp_scalar
104
+VCMPLE_scalar 1111 1110 0 . .. ... 1 ... 1 1111 1 1 1 0 .... @vcmp_scalar
105
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/target/arm/mve_helper.c
108
+++ b/target/arm/mve_helper.c
109
@@ -XXX,XX +XXX,XX @@ DO_VIWDUP_ALL(vdwdup, do_sub_wrap)
110
mve_advance_vpt(env); \
111
}
32
}
112
33
113
-#define DO_VCMP_S(OP, FN) \
34
+ /* Numonyx RC28F128J3F75 */
114
- DO_VCMP(OP##b, 1, int8_t, FN) \
35
if (!pflash_cfi01_register(0x00000000, "connext.rom", connex_rom,
115
- DO_VCMP(OP##h, 2, int16_t, FN) \
36
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
116
- DO_VCMP(OP##w, 4, int32_t, FN)
37
sector_len, 2, 0, 0, 0, 0, 0)) {
117
+#define DO_VCMP_SCALAR(OP, ESIZE, TYPE, FN) \
38
@@ -XXX,XX +XXX,XX @@ static void verdex_init(MachineState *machine)
118
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vn, \
39
exit(1);
119
+ uint32_t rm) \
120
+ { \
121
+ TYPE *n = vn; \
122
+ uint16_t mask = mve_element_mask(env); \
123
+ uint16_t eci_mask = mve_eci_mask(env); \
124
+ uint16_t beatpred = 0; \
125
+ uint16_t emask = MAKE_64BIT_MASK(0, ESIZE); \
126
+ unsigned e; \
127
+ for (e = 0; e < 16 / ESIZE; e++) { \
128
+ bool r = FN(n[H##ESIZE(e)], (TYPE)rm); \
129
+ /* Comparison sets 0/1 bits for each byte in the element */ \
130
+ beatpred |= r * emask; \
131
+ emask <<= ESIZE; \
132
+ } \
133
+ beatpred &= mask; \
134
+ env->v7m.vpr = (env->v7m.vpr & ~(uint32_t)eci_mask) | \
135
+ (beatpred & eci_mask); \
136
+ mve_advance_vpt(env); \
137
+ }
138
139
-#define DO_VCMP_U(OP, FN) \
140
- DO_VCMP(OP##b, 1, uint8_t, FN) \
141
- DO_VCMP(OP##h, 2, uint16_t, FN) \
142
- DO_VCMP(OP##w, 4, uint32_t, FN)
143
+#define DO_VCMP_S(OP, FN) \
144
+ DO_VCMP(OP##b, 1, int8_t, FN) \
145
+ DO_VCMP(OP##h, 2, int16_t, FN) \
146
+ DO_VCMP(OP##w, 4, int32_t, FN) \
147
+ DO_VCMP_SCALAR(OP##_scalarb, 1, int8_t, FN) \
148
+ DO_VCMP_SCALAR(OP##_scalarh, 2, int16_t, FN) \
149
+ DO_VCMP_SCALAR(OP##_scalarw, 4, int32_t, FN)
150
+
151
+#define DO_VCMP_U(OP, FN) \
152
+ DO_VCMP(OP##b, 1, uint8_t, FN) \
153
+ DO_VCMP(OP##h, 2, uint16_t, FN) \
154
+ DO_VCMP(OP##w, 4, uint32_t, FN) \
155
+ DO_VCMP_SCALAR(OP##_scalarb, 1, uint8_t, FN) \
156
+ DO_VCMP_SCALAR(OP##_scalarh, 2, uint16_t, FN) \
157
+ DO_VCMP_SCALAR(OP##_scalarw, 4, uint32_t, FN)
158
159
#define DO_EQ(N, M) ((N) == (M))
160
#define DO_NE(N, M) ((N) != (M))
161
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
162
index XXXXXXX..XXXXXXX 100644
163
--- a/target/arm/translate-mve.c
164
+++ b/target/arm/translate-mve.c
165
@@ -XXX,XX +XXX,XX @@ typedef void MVEGenOneOpImmFn(TCGv_ptr, TCGv_ptr, TCGv_i64);
166
typedef void MVEGenVIDUPFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32, TCGv_i32);
167
typedef void MVEGenVIWDUPFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32, TCGv_i32, TCGv_i32);
168
typedef void MVEGenCmpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
169
+typedef void MVEGenScalarCmpFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
170
171
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
172
static inline long mve_qreg_offset(unsigned reg)
173
@@ -XXX,XX +XXX,XX @@ static bool do_vcmp(DisasContext *s, arg_vcmp *a, MVEGenCmpFn *fn)
174
return true;
175
}
176
177
+static bool do_vcmp_scalar(DisasContext *s, arg_vcmp_scalar *a,
178
+ MVEGenScalarCmpFn *fn)
179
+{
180
+ TCGv_ptr qn;
181
+ TCGv_i32 rm;
182
+
183
+ if (!dc_isar_feature(aa32_mve, s) || !fn || a->rm == 13) {
184
+ return false;
185
+ }
186
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
187
+ return true;
188
+ }
189
+
190
+ qn = mve_qreg_ptr(a->qn);
191
+ if (a->rm == 15) {
192
+ /* Encoding Rm=0b1111 means "constant zero" */
193
+ rm = tcg_constant_i32(0);
194
+ } else {
195
+ rm = load_reg(s, a->rm);
196
+ }
197
+ fn(cpu_env, qn, rm);
198
+ tcg_temp_free_ptr(qn);
199
+ tcg_temp_free_i32(rm);
200
+ if (a->mask) {
201
+ /* VPT */
202
+ gen_vpst(s, a->mask);
203
+ }
204
+ mve_update_eci(s);
205
+ return true;
206
+}
207
+
208
#define DO_VCMP(INSN, FN) \
209
static bool trans_##INSN(DisasContext *s, arg_vcmp *a) \
210
{ \
211
@@ -XXX,XX +XXX,XX @@ static bool do_vcmp(DisasContext *s, arg_vcmp *a, MVEGenCmpFn *fn)
212
NULL, \
213
}; \
214
return do_vcmp(s, a, fns[a->size]); \
215
+ } \
216
+ static bool trans_##INSN##_scalar(DisasContext *s, \
217
+ arg_vcmp_scalar *a) \
218
+ { \
219
+ static MVEGenScalarCmpFn * const fns[] = { \
220
+ gen_helper_mve_##FN##_scalarb, \
221
+ gen_helper_mve_##FN##_scalarh, \
222
+ gen_helper_mve_##FN##_scalarw, \
223
+ NULL, \
224
+ }; \
225
+ return do_vcmp_scalar(s, a, fns[a->size]); \
226
}
40
}
227
41
228
DO_VCMP(VCMPEQ, vcmpeq)
42
+ /* Micron RC28F256P30TFA */
43
if (!pflash_cfi01_register(0x00000000, "verdex.rom", verdex_rom,
44
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
45
sector_len, 2, 0, 0, 0, 0, 0)) {
46
@@ -XXX,XX +XXX,XX @@ static void verdex_class_init(ObjectClass *oc, void *data)
47
{
48
MachineClass *mc = MACHINE_CLASS(oc);
49
50
- mc->desc = "Gumstix Verdex (PXA270)";
51
+ mc->desc = "Gumstix Verdex Pro XL6P COMs (PXA270)";
52
mc->init = verdex_init;
53
mc->ignore_memory_transaction_failures = true;
54
mc->default_cpu_type = ARM_CPU_TYPE_NAME("pxa270-c0");
229
--
55
--
230
2.20.1
56
2.34.1
231
57
232
58
diff view generated by jsdifflib
1
Implement the MVE VLDR/VSTR insns which do scatter-gather using base
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
addresses from Qm plus or minus an immediate offset (possibly with
3
writeback). Note that writeback is not predicated but it does have
4
to honour ECI state, so we have to add an eci_mask check to the
5
VSTR_SG macros (the VLDR_SG macros already needed this to be able
6
to distinguish "skip beat" from "set predicated element to 0").
7
2
3
IEC binary prefixes ease code review: the unit is explicit.
4
5
Add definitions for RAM / Flash / Flash blocksize.
6
7
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230109115316.2235-7-philmd@linaro.org
10
Message-Id: <20200223231044.8003-3-philmd@redhat.com>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
---
12
---
11
target/arm/helper-mve.h | 5 +++
13
hw/arm/gumstix.c | 27 ++++++++++++++-------------
12
target/arm/mve.decode | 10 +++++
14
1 file changed, 14 insertions(+), 13 deletions(-)
13
target/arm/mve_helper.c | 91 ++++++++++++++++++++++++--------------
14
target/arm/translate-mve.c | 72 ++++++++++++++++++++++++++++++
15
4 files changed, 146 insertions(+), 32 deletions(-)
16
15
17
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
16
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper-mve.h
18
--- a/hw/arm/gumstix.c
20
+++ b/target/arm/helper-mve.h
19
+++ b/hw/arm/gumstix.c
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vstrh_sg_os_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
20
@@ -XXX,XX +XXX,XX @@
22
DEF_HELPER_FLAGS_4(mve_vstrw_sg_os_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
21
*/
23
DEF_HELPER_FLAGS_4(mve_vstrd_sg_os_ud, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
22
24
23
#include "qemu/osdep.h"
25
+DEF_HELPER_FLAGS_4(mve_vldrw_sg_wb_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
+#include "qemu/units.h"
26
+DEF_HELPER_FLAGS_4(mve_vldrd_sg_wb_ud, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
#include "qemu/error-report.h"
27
+DEF_HELPER_FLAGS_4(mve_vstrw_sg_wb_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
26
#include "hw/arm/pxa.h"
28
+DEF_HELPER_FLAGS_4(mve_vstrd_sg_wb_ud, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
27
#include "net/net.h"
28
@@ -XXX,XX +XXX,XX @@
29
#include "sysemu/qtest.h"
30
#include "cpu.h"
31
32
-static const int sector_len = 128 * 1024;
33
+#define CONNEX_FLASH_SIZE (16 * MiB)
34
+#define CONNEX_RAM_SIZE (64 * MiB)
29
+
35
+
30
DEF_HELPER_FLAGS_3(mve_vdup, TCG_CALL_NO_WG, void, env, ptr, i32)
36
+#define VERDEX_FLASH_SIZE (32 * MiB)
31
37
+#define VERDEX_RAM_SIZE (256 * MiB)
32
DEF_HELPER_FLAGS_4(mve_vidupb, TCG_CALL_NO_WG, i32, env, ptr, i32, 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 @@
38
&vmaxv qm rda size
39
&vabav qn qm rda size
40
&vldst_sg qd qm rn size msize os
41
+&vldst_sg_imm qd qm a w imm
42
43
# scatter-gather memory size is in bits 6:4
44
%sg_msize 6:1 4:1
45
@@ -XXX,XX +XXX,XX @@
46
@vldst_sg .... .... .... rn:4 .... ... size:2 ... ... os:1 &vldst_sg \
47
qd=%qd qm=%qm msize=%sg_msize
48
49
+# Qm is in the fields usually labeled Qn
50
+@vldst_sg_imm .... .... a:1 . w:1 . .... .... .... . imm:7 &vldst_sg_imm \
51
+ qd=%qd qm=%qn
52
+
38
+
53
@1op .... .... .... size:2 .. .... .... .... .... &1op qd=%qd qm=%qm
39
+#define FLASH_SECTOR_SIZE (128 * KiB)
54
@1op_nosz .... .... .... .... .... .... .... .... &1op qd=%qd qm=%qm size=0
40
55
@2op .... .... .. size:2 .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn
41
static void connex_init(MachineState *machine)
56
@@ -XXX,XX +XXX,XX @@ VLDR_S_sg 111 0 1100 1 . 01 .... ... 0 111 . .... .... @vldst_sg
42
{
57
VLDR_U_sg 111 1 1100 1 . 01 .... ... 0 111 . .... .... @vldst_sg
43
PXA2xxState *cpu;
58
VSTR_sg 111 0 1100 1 . 00 .... ... 0 111 . .... .... @vldst_sg
44
DriveInfo *dinfo;
59
45
60
+VLDRW_sg_imm 111 1 1101 ... 1 ... 0 ... 1 1110 .... .... @vldst_sg_imm
46
- uint32_t connex_rom = 0x01000000;
61
+VLDRD_sg_imm 111 1 1101 ... 1 ... 0 ... 1 1111 .... .... @vldst_sg_imm
47
- uint32_t connex_ram = 0x04000000;
62
+VSTRW_sg_imm 111 1 1101 ... 0 ... 0 ... 1 1110 .... .... @vldst_sg_imm
48
-
63
+VSTRD_sg_imm 111 1 1101 ... 0 ... 0 ... 1 1111 .... .... @vldst_sg_imm
49
- cpu = pxa255_init(connex_ram);
64
+
50
+ cpu = pxa255_init(CONNEX_RAM_SIZE);
65
# Moves between 2 32-bit vector lanes and 2 general purpose registers
51
66
VMOV_to_2gp 1110 1100 0 . 00 rt2:4 ... 0 1111 000 idx:1 rt:4 qd=%qd
52
dinfo = drive_get(IF_PFLASH, 0, 0);
67
VMOV_from_2gp 1110 1100 0 . 01 rt2:4 ... 0 1111 000 idx:1 rt:4 qd=%qd
53
if (!dinfo && !qtest_enabled()) {
68
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
54
@@ -XXX,XX +XXX,XX @@ static void connex_init(MachineState *machine)
69
index XXXXXXX..XXXXXXX 100644
70
--- a/target/arm/mve_helper.c
71
+++ b/target/arm/mve_helper.c
72
@@ -XXX,XX +XXX,XX @@ DO_VSTR(vstrh_w, 2, stw, 4, int32_t)
73
* For loads, predicated lanes are zeroed instead of retaining
74
* their previous values.
75
*/
76
-#define DO_VLDR_SG(OP, LDTYPE, ESIZE, TYPE, OFFTYPE, ADDRFN) \
77
+#define DO_VLDR_SG(OP, LDTYPE, ESIZE, TYPE, OFFTYPE, ADDRFN, WB) \
78
void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm, \
79
uint32_t base) \
80
{ \
81
@@ -XXX,XX +XXX,XX @@ DO_VSTR(vstrh_w, 2, stw, 4, int32_t)
82
addr = ADDRFN(base, m[H##ESIZE(e)]); \
83
d[H##ESIZE(e)] = (mask & 1) ? \
84
cpu_##LDTYPE##_data_ra(env, addr, GETPC()) : 0; \
85
+ if (WB) { \
86
+ m[H##ESIZE(e)] = addr; \
87
+ } \
88
} \
89
mve_advance_vpt(env); \
90
}
55
}
91
56
92
/* We know here TYPE is unsigned so always the same as the offset type */
57
/* Numonyx RC28F128J3F75 */
93
-#define DO_VSTR_SG(OP, STTYPE, ESIZE, TYPE, ADDRFN) \
58
- if (!pflash_cfi01_register(0x00000000, "connext.rom", connex_rom,
94
+#define DO_VSTR_SG(OP, STTYPE, ESIZE, TYPE, ADDRFN, WB) \
59
+ if (!pflash_cfi01_register(0x00000000, "connext.rom", CONNEX_FLASH_SIZE,
95
void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm, \
60
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
96
uint32_t base) \
61
- sector_len, 2, 0, 0, 0, 0, 0)) {
97
{ \
62
+ FLASH_SECTOR_SIZE, 2, 0, 0, 0, 0, 0)) {
98
TYPE *d = vd; \
63
error_report("Error registering flash memory");
99
TYPE *m = vm; \
64
exit(1);
100
uint16_t mask = mve_element_mask(env); \
101
+ uint16_t eci_mask = mve_eci_mask(env); \
102
unsigned e; \
103
uint32_t addr; \
104
- for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
105
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE, eci_mask >>= ESIZE) { \
106
+ if (!(eci_mask & 1)) { \
107
+ continue; \
108
+ } \
109
addr = ADDRFN(base, m[H##ESIZE(e)]); \
110
if (mask & 1) { \
111
cpu_##STTYPE##_data_ra(env, addr, d[H##ESIZE(e)], GETPC()); \
112
} \
113
+ if (WB) { \
114
+ m[H##ESIZE(e)] = addr; \
115
+ } \
116
} \
117
mve_advance_vpt(env); \
118
}
65
}
119
@@ -XXX,XX +XXX,XX @@ DO_VSTR(vstrh_w, 2, stw, 4, int32_t)
66
@@ -XXX,XX +XXX,XX @@ static void verdex_init(MachineState *machine)
120
* accesses, controlled by the predicate mask for the relevant beat,
67
PXA2xxState *cpu;
121
* and with a single 32-bit offset in the first of the two Qm elements.
68
DriveInfo *dinfo;
122
* Note that for QEMU our IMPDEF AIRCR.ENDIANNESS is always 0 (little).
69
123
+ * Address writeback happens on the odd beats and updates the address
70
- uint32_t verdex_rom = 0x02000000;
124
+ * stored in the even-beat element.
71
- uint32_t verdex_ram = 0x10000000;
125
*/
72
-
126
-#define DO_VLDR64_SG(OP, ADDRFN) \
73
- cpu = pxa270_init(verdex_ram, machine->cpu_type);
127
+#define DO_VLDR64_SG(OP, ADDRFN, WB) \
74
+ cpu = pxa270_init(VERDEX_RAM_SIZE, machine->cpu_type);
128
void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm, \
75
129
uint32_t base) \
76
dinfo = drive_get(IF_PFLASH, 0, 0);
130
{ \
77
if (!dinfo && !qtest_enabled()) {
131
@@ -XXX,XX +XXX,XX @@ DO_VSTR(vstrh_w, 2, stw, 4, int32_t)
78
@@ -XXX,XX +XXX,XX @@ static void verdex_init(MachineState *machine)
132
addr = ADDRFN(base, m[H4(e & ~1)]); \
133
addr += 4 * (e & 1); \
134
d[H4(e)] = (mask & 1) ? cpu_ldl_data_ra(env, addr, GETPC()) : 0; \
135
+ if (WB && (e & 1)) { \
136
+ m[H4(e & ~1)] = addr - 4; \
137
+ } \
138
} \
139
mve_advance_vpt(env); \
140
}
79
}
141
80
142
-#define DO_VSTR64_SG(OP, ADDRFN) \
81
/* Micron RC28F256P30TFA */
143
+#define DO_VSTR64_SG(OP, ADDRFN, WB) \
82
- if (!pflash_cfi01_register(0x00000000, "verdex.rom", verdex_rom,
144
void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm, \
83
+ if (!pflash_cfi01_register(0x00000000, "verdex.rom", VERDEX_FLASH_SIZE,
145
uint32_t base) \
84
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
146
{ \
85
- sector_len, 2, 0, 0, 0, 0, 0)) {
147
uint32_t *d = vd; \
86
+ FLASH_SECTOR_SIZE, 2, 0, 0, 0, 0, 0)) {
148
uint32_t *m = vm; \
87
error_report("Error registering flash memory");
149
uint16_t mask = mve_element_mask(env); \
88
exit(1);
150
+ uint16_t eci_mask = mve_eci_mask(env); \
151
unsigned e; \
152
uint32_t addr; \
153
- for (e = 0; e < 16 / 4; e++, mask >>= 4) { \
154
+ for (e = 0; e < 16 / 4; e++, mask >>= 4, eci_mask >>= 4) { \
155
+ if (!(eci_mask & 1)) { \
156
+ continue; \
157
+ } \
158
addr = ADDRFN(base, m[H4(e & ~1)]); \
159
addr += 4 * (e & 1); \
160
if (mask & 1) { \
161
cpu_stl_data_ra(env, addr, d[H4(e)], GETPC()); \
162
} \
163
+ if (WB && (e & 1)) { \
164
+ m[H4(e & ~1)] = addr - 4; \
165
+ } \
166
} \
167
mve_advance_vpt(env); \
168
}
89
}
169
@@ -XXX,XX +XXX,XX @@ DO_VSTR(vstrh_w, 2, stw, 4, int32_t)
170
#define ADDR_ADD_OSW(BASE, OFFSET) ((BASE) + ((OFFSET) << 2))
171
#define ADDR_ADD_OSD(BASE, OFFSET) ((BASE) + ((OFFSET) << 3))
172
173
-DO_VLDR_SG(vldrb_sg_sh, ldsb, 2, int16_t, uint16_t, ADDR_ADD)
174
-DO_VLDR_SG(vldrb_sg_sw, ldsb, 4, int32_t, uint32_t, ADDR_ADD)
175
-DO_VLDR_SG(vldrh_sg_sw, ldsw, 4, int32_t, uint32_t, ADDR_ADD)
176
+DO_VLDR_SG(vldrb_sg_sh, ldsb, 2, int16_t, uint16_t, ADDR_ADD, false)
177
+DO_VLDR_SG(vldrb_sg_sw, ldsb, 4, int32_t, uint32_t, ADDR_ADD, false)
178
+DO_VLDR_SG(vldrh_sg_sw, ldsw, 4, int32_t, uint32_t, ADDR_ADD, false)
179
180
-DO_VLDR_SG(vldrb_sg_ub, ldub, 1, uint8_t, uint8_t, ADDR_ADD)
181
-DO_VLDR_SG(vldrb_sg_uh, ldub, 2, uint16_t, uint16_t, ADDR_ADD)
182
-DO_VLDR_SG(vldrb_sg_uw, ldub, 4, uint32_t, uint32_t, ADDR_ADD)
183
-DO_VLDR_SG(vldrh_sg_uh, lduw, 2, uint16_t, uint16_t, ADDR_ADD)
184
-DO_VLDR_SG(vldrh_sg_uw, lduw, 4, uint32_t, uint32_t, ADDR_ADD)
185
-DO_VLDR_SG(vldrw_sg_uw, ldl, 4, uint32_t, uint32_t, ADDR_ADD)
186
-DO_VLDR64_SG(vldrd_sg_ud, ADDR_ADD)
187
+DO_VLDR_SG(vldrb_sg_ub, ldub, 1, uint8_t, uint8_t, ADDR_ADD, false)
188
+DO_VLDR_SG(vldrb_sg_uh, ldub, 2, uint16_t, uint16_t, ADDR_ADD, false)
189
+DO_VLDR_SG(vldrb_sg_uw, ldub, 4, uint32_t, uint32_t, ADDR_ADD, false)
190
+DO_VLDR_SG(vldrh_sg_uh, lduw, 2, uint16_t, uint16_t, ADDR_ADD, false)
191
+DO_VLDR_SG(vldrh_sg_uw, lduw, 4, uint32_t, uint32_t, ADDR_ADD, false)
192
+DO_VLDR_SG(vldrw_sg_uw, ldl, 4, uint32_t, uint32_t, ADDR_ADD, false)
193
+DO_VLDR64_SG(vldrd_sg_ud, ADDR_ADD, false)
194
195
-DO_VLDR_SG(vldrh_sg_os_sw, ldsw, 4, int32_t, uint32_t, ADDR_ADD_OSH)
196
-DO_VLDR_SG(vldrh_sg_os_uh, lduw, 2, uint16_t, uint16_t, ADDR_ADD_OSH)
197
-DO_VLDR_SG(vldrh_sg_os_uw, lduw, 4, uint32_t, uint32_t, ADDR_ADD_OSH)
198
-DO_VLDR_SG(vldrw_sg_os_uw, ldl, 4, uint32_t, uint32_t, ADDR_ADD_OSW)
199
-DO_VLDR64_SG(vldrd_sg_os_ud, ADDR_ADD_OSD)
200
+DO_VLDR_SG(vldrh_sg_os_sw, ldsw, 4, int32_t, uint32_t, ADDR_ADD_OSH, false)
201
+DO_VLDR_SG(vldrh_sg_os_uh, lduw, 2, uint16_t, uint16_t, ADDR_ADD_OSH, false)
202
+DO_VLDR_SG(vldrh_sg_os_uw, lduw, 4, uint32_t, uint32_t, ADDR_ADD_OSH, false)
203
+DO_VLDR_SG(vldrw_sg_os_uw, ldl, 4, uint32_t, uint32_t, ADDR_ADD_OSW, false)
204
+DO_VLDR64_SG(vldrd_sg_os_ud, ADDR_ADD_OSD, false)
205
206
-DO_VSTR_SG(vstrb_sg_ub, stb, 1, uint8_t, ADDR_ADD)
207
-DO_VSTR_SG(vstrb_sg_uh, stb, 2, uint16_t, ADDR_ADD)
208
-DO_VSTR_SG(vstrb_sg_uw, stb, 4, uint32_t, ADDR_ADD)
209
-DO_VSTR_SG(vstrh_sg_uh, stw, 2, uint16_t, ADDR_ADD)
210
-DO_VSTR_SG(vstrh_sg_uw, stw, 4, uint32_t, ADDR_ADD)
211
-DO_VSTR_SG(vstrw_sg_uw, stl, 4, uint32_t, ADDR_ADD)
212
-DO_VSTR64_SG(vstrd_sg_ud, ADDR_ADD)
213
+DO_VSTR_SG(vstrb_sg_ub, stb, 1, uint8_t, ADDR_ADD, false)
214
+DO_VSTR_SG(vstrb_sg_uh, stb, 2, uint16_t, ADDR_ADD, false)
215
+DO_VSTR_SG(vstrb_sg_uw, stb, 4, uint32_t, ADDR_ADD, false)
216
+DO_VSTR_SG(vstrh_sg_uh, stw, 2, uint16_t, ADDR_ADD, false)
217
+DO_VSTR_SG(vstrh_sg_uw, stw, 4, uint32_t, ADDR_ADD, false)
218
+DO_VSTR_SG(vstrw_sg_uw, stl, 4, uint32_t, ADDR_ADD, false)
219
+DO_VSTR64_SG(vstrd_sg_ud, ADDR_ADD, false)
220
221
-DO_VSTR_SG(vstrh_sg_os_uh, stw, 2, uint16_t, ADDR_ADD_OSH)
222
-DO_VSTR_SG(vstrh_sg_os_uw, stw, 4, uint32_t, ADDR_ADD_OSH)
223
-DO_VSTR_SG(vstrw_sg_os_uw, stl, 4, uint32_t, ADDR_ADD_OSW)
224
-DO_VSTR64_SG(vstrd_sg_os_ud, ADDR_ADD_OSD)
225
+DO_VSTR_SG(vstrh_sg_os_uh, stw, 2, uint16_t, ADDR_ADD_OSH, false)
226
+DO_VSTR_SG(vstrh_sg_os_uw, stw, 4, uint32_t, ADDR_ADD_OSH, false)
227
+DO_VSTR_SG(vstrw_sg_os_uw, stl, 4, uint32_t, ADDR_ADD_OSW, false)
228
+DO_VSTR64_SG(vstrd_sg_os_ud, ADDR_ADD_OSD, false)
229
+
230
+DO_VLDR_SG(vldrw_sg_wb_uw, ldl, 4, uint32_t, uint32_t, ADDR_ADD, true)
231
+DO_VLDR64_SG(vldrd_sg_wb_ud, ADDR_ADD, true)
232
+DO_VSTR_SG(vstrw_sg_wb_uw, stl, 4, uint32_t, ADDR_ADD, true)
233
+DO_VSTR64_SG(vstrd_sg_wb_ud, ADDR_ADD, true)
234
235
/*
236
* The mergemask(D, R, M) macro performs the operation "*D = R" but
237
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
238
index XXXXXXX..XXXXXXX 100644
239
--- a/target/arm/translate-mve.c
240
+++ b/target/arm/translate-mve.c
241
@@ -XXX,XX +XXX,XX @@ static bool trans_VSTR_sg(DisasContext *s, arg_vldst_sg *a)
242
243
#undef F
244
245
+static bool do_ldst_sg_imm(DisasContext *s, arg_vldst_sg_imm *a,
246
+ MVEGenLdStSGFn *fn, unsigned msize)
247
+{
248
+ uint32_t offset;
249
+ TCGv_ptr qd, qm;
250
+
251
+ if (!dc_isar_feature(aa32_mve, s) ||
252
+ !mve_check_qreg_bank(s, a->qd | a->qm) ||
253
+ !fn) {
254
+ return false;
255
+ }
256
+
257
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
258
+ return true;
259
+ }
260
+
261
+ offset = a->imm << msize;
262
+ if (!a->a) {
263
+ offset = -offset;
264
+ }
265
+
266
+ qd = mve_qreg_ptr(a->qd);
267
+ qm = mve_qreg_ptr(a->qm);
268
+ fn(cpu_env, qd, qm, tcg_constant_i32(offset));
269
+ tcg_temp_free_ptr(qd);
270
+ tcg_temp_free_ptr(qm);
271
+ mve_update_eci(s);
272
+ return true;
273
+}
274
+
275
+static bool trans_VLDRW_sg_imm(DisasContext *s, arg_vldst_sg_imm *a)
276
+{
277
+ static MVEGenLdStSGFn * const fns[] = {
278
+ gen_helper_mve_vldrw_sg_uw,
279
+ gen_helper_mve_vldrw_sg_wb_uw,
280
+ };
281
+ if (a->qd == a->qm) {
282
+ return false; /* UNPREDICTABLE */
283
+ }
284
+ return do_ldst_sg_imm(s, a, fns[a->w], MO_32);
285
+}
286
+
287
+static bool trans_VLDRD_sg_imm(DisasContext *s, arg_vldst_sg_imm *a)
288
+{
289
+ static MVEGenLdStSGFn * const fns[] = {
290
+ gen_helper_mve_vldrd_sg_ud,
291
+ gen_helper_mve_vldrd_sg_wb_ud,
292
+ };
293
+ if (a->qd == a->qm) {
294
+ return false; /* UNPREDICTABLE */
295
+ }
296
+ return do_ldst_sg_imm(s, a, fns[a->w], MO_64);
297
+}
298
+
299
+static bool trans_VSTRW_sg_imm(DisasContext *s, arg_vldst_sg_imm *a)
300
+{
301
+ static MVEGenLdStSGFn * const fns[] = {
302
+ gen_helper_mve_vstrw_sg_uw,
303
+ gen_helper_mve_vstrw_sg_wb_uw,
304
+ };
305
+ return do_ldst_sg_imm(s, a, fns[a->w], MO_32);
306
+}
307
+
308
+static bool trans_VSTRD_sg_imm(DisasContext *s, arg_vldst_sg_imm *a)
309
+{
310
+ static MVEGenLdStSGFn * const fns[] = {
311
+ gen_helper_mve_vstrd_sg_ud,
312
+ gen_helper_mve_vstrd_sg_wb_ud,
313
+ };
314
+ return do_ldst_sg_imm(s, a, fns[a->w], MO_64);
315
+}
316
+
317
static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
318
{
319
TCGv_ptr qd;
320
--
90
--
321
2.20.1
91
2.34.1
322
92
323
93
diff view generated by jsdifflib
1
Implement the MVE VMLA insn, which multiplies a vector by a scalar
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
and accumulates into another vector.
3
2
3
IEC binary prefixes ease code review: the unit is explicit.
4
5
Add the FLASH_SECTOR_SIZE definition.
6
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230109115316.2235-8-philmd@linaro.org
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
---
11
---
7
target/arm/helper-mve.h | 4 ++++
12
hw/arm/mainstone.c | 18 ++++++++++--------
8
target/arm/mve.decode | 1 +
13
1 file changed, 10 insertions(+), 8 deletions(-)
9
target/arm/mve_helper.c | 5 +++++
10
target/arm/translate-mve.c | 1 +
11
4 files changed, 11 insertions(+)
12
14
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
15
diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
14
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
17
--- a/hw/arm/mainstone.c
16
+++ b/target/arm/helper-mve.h
18
+++ b/hw/arm/mainstone.c
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqdmullb_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i3
19
@@ -XXX,XX +XXX,XX @@
18
DEF_HELPER_FLAGS_4(mve_vqdmullt_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
20
* GNU GPL, version 2 or (at your option) any later version.
19
DEF_HELPER_FLAGS_4(mve_vqdmullt_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
21
*/
20
22
#include "qemu/osdep.h"
21
+DEF_HELPER_FLAGS_4(mve_vmlab, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
23
+#include "qemu/units.h"
22
+DEF_HELPER_FLAGS_4(mve_vmlah, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
#include "qemu/error-report.h"
23
+DEF_HELPER_FLAGS_4(mve_vmlaw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
#include "qapi/error.h"
26
#include "hw/arm/pxa.h"
27
@@ -XXX,XX +XXX,XX @@ static const struct keymap map[0xE0] = {
28
29
enum mainstone_model_e { mainstone };
30
31
-#define MAINSTONE_RAM    0x04000000
32
-#define MAINSTONE_ROM    0x00800000
33
-#define MAINSTONE_FLASH    0x02000000
34
+#define MAINSTONE_RAM_SIZE (64 * MiB)
35
+#define MAINSTONE_ROM_SIZE (8 * MiB)
36
+#define MAINSTONE_FLASH_SIZE (32 * MiB)
37
38
static struct arm_boot_info mainstone_binfo = {
39
.loader_start = PXA2XX_SDRAM_BASE,
40
- .ram_size = 0x04000000,
41
+ .ram_size = MAINSTONE_RAM_SIZE,
42
};
43
44
+#define FLASH_SECTOR_SIZE (256 * KiB)
24
+
45
+
25
DEF_HELPER_FLAGS_4(mve_vmlasb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
46
static void mainstone_common_init(MachineState *machine,
26
DEF_HELPER_FLAGS_4(mve_vmlash, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
47
enum mainstone_model_e model, int arm_id)
27
DEF_HELPER_FLAGS_4(mve_vmlasw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
48
{
28
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
49
- uint32_t sector_len = 256 * 1024;
29
index XXXXXXX..XXXXXXX 100644
50
hwaddr mainstone_flash_base[] = { MST_FLASH_0, MST_FLASH_1 };
30
--- a/target/arm/mve.decode
51
PXA2xxState *mpu;
31
+++ b/target/arm/mve.decode
52
DeviceState *mst_irq;
32
@@ -XXX,XX +XXX,XX @@ VQDMULH_scalar 1110 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
53
@@ -XXX,XX +XXX,XX @@ static void mainstone_common_init(MachineState *machine,
33
VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
54
34
55
/* Setup CPU & memory */
35
# The U bit (28) is don't-care because it does not affect the result
56
mpu = pxa270_init(mainstone_binfo.ram_size, machine->cpu_type);
36
+VMLA 111- 1110 0 . .. ... 1 ... 0 1110 . 100 .... @2scalar
57
- memory_region_init_rom(rom, NULL, "mainstone.rom", MAINSTONE_ROM,
37
VMLAS 111- 1110 0 . .. ... 1 ... 1 1110 . 100 .... @2scalar
58
+ memory_region_init_rom(rom, NULL, "mainstone.rom", MAINSTONE_ROM_SIZE,
38
59
&error_fatal);
39
# Vector add across vector
60
memory_region_add_subregion(get_system_memory(), 0x00000000, rom);
40
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
61
41
index XXXXXXX..XXXXXXX 100644
62
@@ -XXX,XX +XXX,XX @@ static void mainstone_common_init(MachineState *machine,
42
--- a/target/arm/mve_helper.c
63
dinfo = drive_get(IF_PFLASH, 0, i);
43
+++ b/target/arm/mve_helper.c
64
if (!pflash_cfi01_register(mainstone_flash_base[i],
44
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT_SCALAR(vqrdmulh_scalarb, 1, int8_t, DO_QRDMULH_B)
65
i ? "mainstone.flash1" : "mainstone.flash0",
45
DO_2OP_SAT_SCALAR(vqrdmulh_scalarh, 2, int16_t, DO_QRDMULH_H)
66
- MAINSTONE_FLASH,
46
DO_2OP_SAT_SCALAR(vqrdmulh_scalarw, 4, int32_t, DO_QRDMULH_W)
67
+ MAINSTONE_FLASH_SIZE,
47
68
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
48
+/* Vector by scalar plus vector */
69
- sector_len, 4, 0, 0, 0, 0, 0)) {
49
+#define DO_VMLA(D, N, M) ((N) * (M) + (D))
70
+ FLASH_SECTOR_SIZE, 4, 0, 0, 0, 0, 0)) {
50
+
71
error_report("Error registering flash memory");
51
+DO_2OP_ACC_SCALAR_U(vmla, DO_VMLA)
72
exit(1);
52
+
73
}
53
/* Vector by vector plus scalar */
54
#define DO_VMLAS(D, N, M) ((N) * (D) + (M))
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 @@ DO_2OP_SCALAR(VQSUB_U_scalar, vqsubu_scalar)
61
DO_2OP_SCALAR(VQDMULH_scalar, vqdmulh_scalar)
62
DO_2OP_SCALAR(VQRDMULH_scalar, vqrdmulh_scalar)
63
DO_2OP_SCALAR(VBRSR, vbrsr)
64
+DO_2OP_SCALAR(VMLA, vmla)
65
DO_2OP_SCALAR(VMLAS, vmlas)
66
67
static bool trans_VQDMULLB_scalar(DisasContext *s, arg_2scalar *a)
68
--
74
--
69
2.20.1
75
2.34.1
70
76
71
77
diff view generated by jsdifflib
1
From: Guenter Roeck <linux@roeck-us.net>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
Instantiate SAI1/2/3 as unimplemented devices to avoid Linux kernel crashes
3
IEC binary prefixes ease code review: the unit is explicit.
4
such as the following.
5
4
6
Unhandled fault: external abort on non-linefetch (0x808) at 0xd19b0000
5
Add the FLASH_SECTOR_SIZE definition.
7
pgd = (ptrval)
8
[d19b0000] *pgd=82711811, *pte=308a0653, *ppte=308a0453
9
Internal error: : 808 [#1] SMP ARM
10
Modules linked in:
11
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.14.0-rc5 #1
12
...
13
[<c095e974>] (regmap_mmio_write32le) from [<c095eb48>] (regmap_mmio_write+0x3c/0x54)
14
[<c095eb48>] (regmap_mmio_write) from [<c09580f4>] (_regmap_write+0x4c/0x1f0)
15
[<c09580f4>] (_regmap_write) from [<c0959b28>] (regmap_write+0x3c/0x60)
16
[<c0959b28>] (regmap_write) from [<c0d41130>] (fsl_sai_runtime_resume+0x9c/0x1ec)
17
[<c0d41130>] (fsl_sai_runtime_resume) from [<c0942464>] (__rpm_callback+0x3c/0x108)
18
[<c0942464>] (__rpm_callback) from [<c0942590>] (rpm_callback+0x60/0x64)
19
[<c0942590>] (rpm_callback) from [<c0942b60>] (rpm_resume+0x5cc/0x808)
20
[<c0942b60>] (rpm_resume) from [<c0942dfc>] (__pm_runtime_resume+0x60/0xa0)
21
[<c0942dfc>] (__pm_runtime_resume) from [<c0d4231c>] (fsl_sai_probe+0x2b8/0x65c)
22
[<c0d4231c>] (fsl_sai_probe) from [<c0935b08>] (platform_probe+0x58/0xb8)
23
[<c0935b08>] (platform_probe) from [<c0933264>] (really_probe.part.0+0x9c/0x334)
24
[<c0933264>] (really_probe.part.0) from [<c093359c>] (__driver_probe_device+0xa0/0x138)
25
[<c093359c>] (__driver_probe_device) from [<c0933664>] (driver_probe_device+0x30/0xc8)
26
[<c0933664>] (driver_probe_device) from [<c0933c88>] (__driver_attach+0x90/0x130)
27
[<c0933c88>] (__driver_attach) from [<c0931060>] (bus_for_each_dev+0x78/0xb8)
28
[<c0931060>] (bus_for_each_dev) from [<c093254c>] (bus_add_driver+0xf0/0x1d8)
29
[<c093254c>] (bus_add_driver) from [<c0934a30>] (driver_register+0x88/0x118)
30
[<c0934a30>] (driver_register) from [<c01022c0>] (do_one_initcall+0x7c/0x3a4)
31
[<c01022c0>] (do_one_initcall) from [<c1601204>] (kernel_init_freeable+0x198/0x22c)
32
[<c1601204>] (kernel_init_freeable) from [<c0f5ff2c>] (kernel_init+0x10/0x128)
33
[<c0f5ff2c>] (kernel_init) from [<c010013c>] (ret_from_fork+0x14/0x38)
34
6
35
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
36
Message-id: 20210810175607.538090-1-linux@roeck-us.net
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
37
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Message-id: 20230109115316.2235-9-philmd@linaro.org
38
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
39
---
11
---
40
include/hw/arm/fsl-imx7.h | 5 +++++
12
hw/arm/musicpal.c | 9 ++++++---
41
hw/arm/fsl-imx7.c | 7 +++++++
13
1 file changed, 6 insertions(+), 3 deletions(-)
42
2 files changed, 12 insertions(+)
43
14
44
diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h
15
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
45
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
46
--- a/include/hw/arm/fsl-imx7.h
17
--- a/hw/arm/musicpal.c
47
+++ b/include/hw/arm/fsl-imx7.h
18
+++ b/hw/arm/musicpal.c
48
@@ -XXX,XX +XXX,XX @@ enum FslIMX7MemoryMap {
19
@@ -XXX,XX +XXX,XX @@
49
FSL_IMX7_UART6_ADDR = 0x30A80000,
20
*/
50
FSL_IMX7_UART7_ADDR = 0x30A90000,
21
51
22
#include "qemu/osdep.h"
52
+ FSL_IMX7_SAI1_ADDR = 0x308A0000,
23
+#include "qemu/units.h"
53
+ FSL_IMX7_SAI2_ADDR = 0x308B0000,
24
#include "qapi/error.h"
54
+ FSL_IMX7_SAI3_ADDR = 0x308C0000,
25
#include "cpu.h"
55
+ FSL_IMX7_SAIn_SIZE = 0x10000,
26
#include "hw/sysbus.h"
27
@@ -XXX,XX +XXX,XX @@ static const TypeInfo musicpal_key_info = {
28
.class_init = musicpal_key_class_init,
29
};
30
31
+#define FLASH_SECTOR_SIZE (64 * KiB)
56
+
32
+
57
FSL_IMX7_ENET1_ADDR = 0x30BE0000,
33
static struct arm_boot_info musicpal_binfo = {
58
FSL_IMX7_ENET2_ADDR = 0x30BF0000,
34
.loader_start = 0x0,
59
35
.board_id = 0x20e,
60
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
36
@@ -XXX,XX +XXX,XX @@ static void musicpal_init(MachineState *machine)
61
index XXXXXXX..XXXXXXX 100644
37
BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
62
--- a/hw/arm/fsl-imx7.c
38
63
+++ b/hw/arm/fsl-imx7.c
39
flash_size = blk_getlength(blk);
64
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
40
- if (flash_size != 8*1024*1024 && flash_size != 16*1024*1024 &&
65
create_unimplemented_device("can1", FSL_IMX7_CAN1_ADDR, FSL_IMX7_CANn_SIZE);
41
- flash_size != 32*1024*1024) {
66
create_unimplemented_device("can2", FSL_IMX7_CAN2_ADDR, FSL_IMX7_CANn_SIZE);
42
+ if (flash_size != 8 * MiB && flash_size != 16 * MiB &&
67
43
+ flash_size != 32 * MiB) {
68
+ /*
44
error_report("Invalid flash image size");
69
+ * SAI (Audio SSI (Synchronous Serial Interface))
45
exit(1);
70
+ */
46
}
71
+ create_unimplemented_device("sai1", FSL_IMX7_SAI1_ADDR, FSL_IMX7_SAIn_SIZE);
47
@@ -XXX,XX +XXX,XX @@ static void musicpal_init(MachineState *machine)
72
+ create_unimplemented_device("sai2", FSL_IMX7_SAI2_ADDR, FSL_IMX7_SAIn_SIZE);
48
*/
73
+ create_unimplemented_device("sai2", FSL_IMX7_SAI3_ADDR, FSL_IMX7_SAIn_SIZE);
49
pflash_cfi02_register(0x100000000ULL - MP_FLASH_SIZE_MAX,
74
+
50
"musicpal.flash", flash_size,
75
/*
51
- blk, 0x10000,
76
* OCOTP
52
+ blk, FLASH_SECTOR_SIZE,
77
*/
53
MP_FLASH_SIZE_MAX / flash_size,
54
2, 0x00BF, 0x236D, 0x0000, 0x0000,
55
0x5555, 0x2AAA, 0);
78
--
56
--
79
2.20.1
57
2.34.1
80
58
81
59
diff view generated by jsdifflib
1
From: Guenter Roeck <linux@roeck-us.net>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
Instantiate SAI1/2/3 and ASRC as unimplemented devices to avoid random
3
The total_ram_v1/total_ram_v2 definitions were never used.
4
Linux kernel crashes, such as
5
4
6
Unhandled fault: external abort on non-linefetch (0x808) at 0xd1580010
5
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
pgd = (ptrval)
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
[d1580010] *pgd=8231b811, *pte=02034653, *ppte=02034453
7
Message-id: 20230109115316.2235-10-philmd@linaro.org
9
Internal error: : 808 [#1] SMP ARM
10
...
11
[<c095e974>] (regmap_mmio_write32le) from [<c095eb48>] (regmap_mmio_write+0x3c/0x54)
12
[<c095eb48>] (regmap_mmio_write) from [<c09580f4>] (_regmap_write+0x4c/0x1f0)
13
[<c09580f4>] (_regmap_write) from [<c095837c>] (_regmap_update_bits+0xe4/0xec)
14
[<c095837c>] (_regmap_update_bits) from [<c09599b4>] (regmap_update_bits_base+0x50/0x74)
15
[<c09599b4>] (regmap_update_bits_base) from [<c0d3e9e4>] (fsl_asrc_runtime_resume+0x1e4/0x21c)
16
[<c0d3e9e4>] (fsl_asrc_runtime_resume) from [<c0942464>] (__rpm_callback+0x3c/0x108)
17
[<c0942464>] (__rpm_callback) from [<c0942590>] (rpm_callback+0x60/0x64)
18
[<c0942590>] (rpm_callback) from [<c0942b60>] (rpm_resume+0x5cc/0x808)
19
[<c0942b60>] (rpm_resume) from [<c0942dfc>] (__pm_runtime_resume+0x60/0xa0)
20
[<c0942dfc>] (__pm_runtime_resume) from [<c0d3ecc4>] (fsl_asrc_probe+0x2a8/0x708)
21
[<c0d3ecc4>] (fsl_asrc_probe) from [<c0935b08>] (platform_probe+0x58/0xb8)
22
[<c0935b08>] (platform_probe) from [<c0933264>] (really_probe.part.0+0x9c/0x334)
23
[<c0933264>] (really_probe.part.0) from [<c093359c>] (__driver_probe_device+0xa0/0x138)
24
[<c093359c>] (__driver_probe_device) from [<c0933664>] (driver_probe_device+0x30/0xc8)
25
[<c0933664>] (driver_probe_device) from [<c0933c88>] (__driver_attach+0x90/0x130)
26
[<c0933c88>] (__driver_attach) from [<c0931060>] (bus_for_each_dev+0x78/0xb8)
27
[<c0931060>] (bus_for_each_dev) from [<c093254c>] (bus_add_driver+0xf0/0x1d8)
28
[<c093254c>] (bus_add_driver) from [<c0934a30>] (driver_register+0x88/0x118)
29
[<c0934a30>] (driver_register) from [<c01022c0>] (do_one_initcall+0x7c/0x3a4)
30
[<c01022c0>] (do_one_initcall) from [<c1601204>] (kernel_init_freeable+0x198/0x22c)
31
[<c1601204>] (kernel_init_freeable) from [<c0f5ff2c>] (kernel_init+0x10/0x128)
32
[<c0f5ff2c>] (kernel_init) from [<c010013c>] (ret_from_fork+0x14/0x38)
33
34
or
35
36
Unhandled fault: external abort on non-linefetch (0x808) at 0xd19b0000
37
pgd = (ptrval)
38
[d19b0000] *pgd=82711811, *pte=308a0653, *ppte=308a0453
39
Internal error: : 808 [#1] SMP ARM
40
...
41
[<c095e974>] (regmap_mmio_write32le) from [<c095eb48>] (regmap_mmio_write+0x3c/0x54)
42
[<c095eb48>] (regmap_mmio_write) from [<c09580f4>] (_regmap_write+0x4c/0x1f0)
43
[<c09580f4>] (_regmap_write) from [<c0959b28>] (regmap_write+0x3c/0x60)
44
[<c0959b28>] (regmap_write) from [<c0d41130>] (fsl_sai_runtime_resume+0x9c/0x1ec)
45
[<c0d41130>] (fsl_sai_runtime_resume) from [<c0942464>] (__rpm_callback+0x3c/0x108)
46
[<c0942464>] (__rpm_callback) from [<c0942590>] (rpm_callback+0x60/0x64)
47
[<c0942590>] (rpm_callback) from [<c0942b60>] (rpm_resume+0x5cc/0x808)
48
[<c0942b60>] (rpm_resume) from [<c0942dfc>] (__pm_runtime_resume+0x60/0xa0)
49
[<c0942dfc>] (__pm_runtime_resume) from [<c0d4231c>] (fsl_sai_probe+0x2b8/0x65c)
50
[<c0d4231c>] (fsl_sai_probe) from [<c0935b08>] (platform_probe+0x58/0xb8)
51
[<c0935b08>] (platform_probe) from [<c0933264>] (really_probe.part.0+0x9c/0x334)
52
[<c0933264>] (really_probe.part.0) from [<c093359c>] (__driver_probe_device+0xa0/0x138)
53
[<c093359c>] (__driver_probe_device) from [<c0933664>] (driver_probe_device+0x30/0xc8)
54
[<c0933664>] (driver_probe_device) from [<c0933c88>] (__driver_attach+0x90/0x130)
55
[<c0933c88>] (__driver_attach) from [<c0931060>] (bus_for_each_dev+0x78/0xb8)
56
[<c0931060>] (bus_for_each_dev) from [<c093254c>] (bus_add_driver+0xf0/0x1d8)
57
[<c093254c>] (bus_add_driver) from [<c0934a30>] (driver_register+0x88/0x118)
58
[<c0934a30>] (driver_register) from [<c01022c0>] (do_one_initcall+0x7c/0x3a4)
59
[<c01022c0>] (do_one_initcall) from [<c1601204>] (kernel_init_freeable+0x198/0x22c)
60
[<c1601204>] (kernel_init_freeable) from [<c0f5ff2c>] (kernel_init+0x10/0x128)
61
[<c0f5ff2c>] (kernel_init) from [<c010013c>] (ret_from_fork+0x14/0x38)
62
63
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
64
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
65
Message-id: 20210810160318.87376-1-linux@roeck-us.net
66
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
67
---
9
---
68
hw/arm/fsl-imx6ul.c | 12 ++++++++++++
10
hw/arm/omap_sx1.c | 2 --
69
1 file changed, 12 insertions(+)
11
1 file changed, 2 deletions(-)
70
12
71
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
13
diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
72
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
73
--- a/hw/arm/fsl-imx6ul.c
15
--- a/hw/arm/omap_sx1.c
74
+++ b/hw/arm/fsl-imx6ul.c
16
+++ b/hw/arm/omap_sx1.c
75
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
17
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps static_ops = {
76
*/
18
#define flash0_size    (16 * 1024 * 1024)
77
create_unimplemented_device("sdma", FSL_IMX6UL_SDMA_ADDR, 0x4000);
19
#define flash1_size    ( 8 * 1024 * 1024)
78
20
#define flash2_size    (32 * 1024 * 1024)
79
+ /*
21
-#define total_ram_v1    (sdram_size + flash0_size + flash1_size + OMAP15XX_SRAM_SIZE)
80
+ * SAI (Audio SSI (Synchronous Serial Interface))
22
-#define total_ram_v2    (sdram_size + flash2_size + OMAP15XX_SRAM_SIZE)
81
+ */
23
82
+ create_unimplemented_device("sai1", FSL_IMX6UL_SAI1_ADDR, 0x4000);
24
static struct arm_boot_info sx1_binfo = {
83
+ create_unimplemented_device("sai2", FSL_IMX6UL_SAI2_ADDR, 0x4000);
25
.loader_start = OMAP_EMIFF_BASE,
84
+ create_unimplemented_device("sai3", FSL_IMX6UL_SAI3_ADDR, 0x4000);
85
+
86
/*
87
* PWM
88
*/
89
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
90
create_unimplemented_device("pwm3", FSL_IMX6UL_PWM3_ADDR, 0x4000);
91
create_unimplemented_device("pwm4", FSL_IMX6UL_PWM4_ADDR, 0x4000);
92
93
+ /*
94
+ * Audio ASRC (asynchronous sample rate converter)
95
+ */
96
+ create_unimplemented_device("asrc", FSL_IMX6UL_ASRC_ADDR, 0x4000);
97
+
98
/*
99
* CAN
100
*/
101
--
26
--
102
2.20.1
27
2.34.1
103
28
104
29
diff view generated by jsdifflib
1
From: Hamza Mahfooz <someguy@effective-light.com>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
As per commit 5626f8c6d468 ("rcu: Add automatically released rcu_read_lock
3
IEC binary prefixes ease code review: the unit is explicit.
4
variants"), RCU_READ_LOCK_GUARD() should be used instead of
5
rcu_read_{un}lock().
6
4
7
Signed-off-by: Hamza Mahfooz <someguy@effective-light.com>
5
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210727235201.11491-1-someguy@effective-light.com
7
Message-id: 20230109115316.2235-11-philmd@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
9
---
12
target/arm/kvm.c | 17 ++++++++---------
10
hw/arm/omap_sx1.c | 33 +++++++++++++++++----------------
13
1 file changed, 8 insertions(+), 9 deletions(-)
11
1 file changed, 17 insertions(+), 16 deletions(-)
14
12
15
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
13
diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
16
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/kvm.c
15
--- a/hw/arm/omap_sx1.c
18
+++ b/target/arm/kvm.c
16
+++ b/hw/arm/omap_sx1.c
19
@@ -XXX,XX +XXX,XX @@ int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
17
@@ -XXX,XX +XXX,XX @@
20
hwaddr xlat, len, doorbell_gpa;
18
* with this program; if not, see <http://www.gnu.org/licenses/>.
21
MemoryRegionSection mrs;
19
*/
22
MemoryRegion *mr;
20
#include "qemu/osdep.h"
23
- int ret = 1;
21
+#include "qemu/units.h"
24
22
#include "qapi/error.h"
25
if (as == &address_space_memory) {
23
#include "ui/console.h"
26
return 0;
24
#include "hw/arm/omap.h"
27
@@ -XXX,XX +XXX,XX @@ int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
25
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps static_ops = {
28
26
.endianness = DEVICE_NATIVE_ENDIAN,
29
/* MSI doorbell address is translated by an IOMMU */
27
};
30
28
31
- rcu_read_lock();
29
-#define sdram_size    0x02000000
32
+ RCU_READ_LOCK_GUARD();
30
-#define sector_size    (128 * 1024)
33
+
31
-#define flash0_size    (16 * 1024 * 1024)
34
mr = address_space_translate(as, address, &xlat, &len, true,
32
-#define flash1_size    ( 8 * 1024 * 1024)
35
MEMTXATTRS_UNSPECIFIED);
33
-#define flash2_size    (32 * 1024 * 1024)
36
+
34
+#define SDRAM_SIZE (32 * MiB)
37
if (!mr) {
35
+#define SECTOR_SIZE (128 * KiB)
38
- goto unlock;
36
+#define FLASH0_SIZE (16 * MiB)
39
+ return 1;
37
+#define FLASH1_SIZE (8 * MiB)
38
+#define FLASH2_SIZE (32 * MiB)
39
40
static struct arm_boot_info sx1_binfo = {
41
.loader_start = OMAP_EMIFF_BASE,
42
- .ram_size = sdram_size,
43
+ .ram_size = SDRAM_SIZE,
44
.board_id = 0x265,
45
};
46
47
@@ -XXX,XX +XXX,XX @@ static void sx1_init(MachineState *machine, const int version)
48
static uint32_t cs3val = 0x00001139;
49
DriveInfo *dinfo;
50
int fl_idx;
51
- uint32_t flash_size = flash0_size;
52
+ uint32_t flash_size = FLASH0_SIZE;
53
54
if (machine->ram_size != mc->default_ram_size) {
55
char *sz = size_to_str(mc->default_ram_size);
56
@@ -XXX,XX +XXX,XX @@ static void sx1_init(MachineState *machine, const int version)
40
}
57
}
41
+
58
42
mrs = memory_region_find(mr, xlat, 1);
59
if (version == 2) {
43
+
60
- flash_size = flash2_size;
44
if (!mrs.mr) {
61
+ flash_size = FLASH2_SIZE;
45
- goto unlock;
46
+ return 1;
47
}
62
}
48
63
49
doorbell_gpa = mrs.offset_within_address_space;
64
memory_region_add_subregion(address_space, OMAP_EMIFF_BASE, machine->ram);
50
@@ -XXX,XX +XXX,XX @@ int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
65
@@ -XXX,XX +XXX,XX @@ static void sx1_init(MachineState *machine, const int version)
51
66
if (!pflash_cfi01_register(OMAP_CS0_BASE,
52
trace_kvm_arm_fixup_msi_route(address, doorbell_gpa);
67
"omap_sx1.flash0-1", flash_size,
53
68
blk_by_legacy_dinfo(dinfo),
54
- ret = 0;
69
- sector_size, 4, 0, 0, 0, 0, 0)) {
55
-
70
+ SECTOR_SIZE, 4, 0, 0, 0, 0, 0)) {
56
-unlock:
71
fprintf(stderr, "qemu: Error registering flash memory %d.\n",
57
- rcu_read_unlock();
72
fl_idx);
58
- return ret;
73
}
59
+ return 0;
74
@@ -XXX,XX +XXX,XX @@ static void sx1_init(MachineState *machine, const int version)
75
(dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
76
MemoryRegion *flash_1 = g_new(MemoryRegion, 1);
77
memory_region_init_rom(flash_1, NULL, "omap_sx1.flash1-0",
78
- flash1_size, &error_fatal);
79
+ FLASH1_SIZE, &error_fatal);
80
memory_region_add_subregion(address_space, OMAP_CS1_BASE, flash_1);
81
82
memory_region_init_io(&cs[1], NULL, &static_ops, &cs1val,
83
- "sx1.cs1", OMAP_CS1_SIZE - flash1_size);
84
+ "sx1.cs1", OMAP_CS1_SIZE - FLASH1_SIZE);
85
memory_region_add_subregion(address_space,
86
- OMAP_CS1_BASE + flash1_size, &cs[1]);
87
+ OMAP_CS1_BASE + FLASH1_SIZE, &cs[1]);
88
89
if (!pflash_cfi01_register(OMAP_CS1_BASE,
90
- "omap_sx1.flash1-1", flash1_size,
91
+ "omap_sx1.flash1-1", FLASH1_SIZE,
92
blk_by_legacy_dinfo(dinfo),
93
- sector_size, 4, 0, 0, 0, 0, 0)) {
94
+ SECTOR_SIZE, 4, 0, 0, 0, 0, 0)) {
95
fprintf(stderr, "qemu: Error registering flash memory %d.\n",
96
fl_idx);
97
}
98
@@ -XXX,XX +XXX,XX @@ static void sx1_machine_v2_class_init(ObjectClass *oc, void *data)
99
mc->init = sx1_init_v2;
100
mc->ignore_memory_transaction_failures = true;
101
mc->default_cpu_type = ARM_CPU_TYPE_NAME("ti925t");
102
- mc->default_ram_size = sdram_size;
103
+ mc->default_ram_size = SDRAM_SIZE;
104
mc->default_ram_id = "omap1.dram";
60
}
105
}
61
106
62
int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
107
@@ -XXX,XX +XXX,XX @@ static void sx1_machine_v1_class_init(ObjectClass *oc, void *data)
108
mc->init = sx1_init_v1;
109
mc->ignore_memory_transaction_failures = true;
110
mc->default_cpu_type = ARM_CPU_TYPE_NAME("ti925t");
111
- mc->default_ram_size = sdram_size;
112
+ mc->default_ram_size = SDRAM_SIZE;
113
mc->default_ram_id = "omap1.dram";
114
}
115
63
--
116
--
64
2.20.1
117
2.34.1
65
118
66
119
diff view generated by jsdifflib
1
Implement the MVE VABAV insn, which computes absolute differences
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
between elements of two vectors and accumulates the result into
3
a general purpose register.
4
2
3
IEC binary prefixes ease code review: the unit is explicit.
4
5
Add the FLASH_SECTOR_SIZE definition.
6
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230109115316.2235-12-philmd@linaro.org
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
---
11
---
8
target/arm/helper-mve.h | 7 +++++++
12
hw/arm/z2.c | 6 ++++--
9
target/arm/mve.decode | 6 ++++++
13
1 file changed, 4 insertions(+), 2 deletions(-)
10
target/arm/mve_helper.c | 26 +++++++++++++++++++++++
11
target/arm/translate-mve.c | 43 ++++++++++++++++++++++++++++++++++++++
12
4 files changed, 82 insertions(+)
13
14
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
15
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-mve.h
17
--- a/hw/arm/z2.c
17
+++ b/target/arm/helper-mve.h
18
+++ b/hw/arm/z2.c
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vminavw, TCG_CALL_NO_WG, i32, env, ptr, i32)
19
@@ -XXX,XX +XXX,XX @@
19
DEF_HELPER_FLAGS_3(mve_vaddlv_s, TCG_CALL_NO_WG, i64, env, ptr, i64)
20
*/
20
DEF_HELPER_FLAGS_3(mve_vaddlv_u, TCG_CALL_NO_WG, i64, env, ptr, i64)
21
21
22
#include "qemu/osdep.h"
22
+DEF_HELPER_FLAGS_4(mve_vabavsb, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
23
+#include "qemu/units.h"
23
+DEF_HELPER_FLAGS_4(mve_vabavsh, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
24
#include "hw/arm/pxa.h"
24
+DEF_HELPER_FLAGS_4(mve_vabavsw, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
25
#include "hw/arm/boot.h"
25
+DEF_HELPER_FLAGS_4(mve_vabavub, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
26
#include "hw/i2c/i2c.h"
26
+DEF_HELPER_FLAGS_4(mve_vabavuh, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
27
@@ -XXX,XX +XXX,XX @@ static const TypeInfo aer915_info = {
27
+DEF_HELPER_FLAGS_4(mve_vabavuw, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
28
.class_init = aer915_class_init,
29
};
30
31
+#define FLASH_SECTOR_SIZE (64 * KiB)
28
+
32
+
29
DEF_HELPER_FLAGS_3(mve_vmovi, TCG_CALL_NO_WG, void, env, ptr, i64)
33
static void z2_init(MachineState *machine)
30
DEF_HELPER_FLAGS_3(mve_vandi, TCG_CALL_NO_WG, void, env, ptr, i64)
34
{
31
DEF_HELPER_FLAGS_3(mve_vorri, TCG_CALL_NO_WG, void, env, ptr, i64)
35
- uint32_t sector_len = 0x10000;
32
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
36
PXA2xxState *mpu;
33
index XXXXXXX..XXXXXXX 100644
37
DriveInfo *dinfo;
34
--- a/target/arm/mve.decode
38
void *z2_lcd;
35
+++ b/target/arm/mve.decode
39
@@ -XXX,XX +XXX,XX @@ static void z2_init(MachineState *machine)
36
@@ -XXX,XX +XXX,XX @@
40
dinfo = drive_get(IF_PFLASH, 0, 0);
37
&vcmp_scalar qn rm size mask
41
if (!pflash_cfi01_register(Z2_FLASH_BASE, "z2.flash0", Z2_FLASH_SIZE,
38
&shl_scalar qda rm size
42
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
39
&vmaxv qm rda size
43
- sector_len, 4, 0, 0, 0, 0, 0)) {
40
+&vabav qn qm rda size
44
+ FLASH_SECTOR_SIZE, 4, 0, 0, 0, 0, 0)) {
41
45
error_report("Error registering flash memory");
42
@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
46
exit(1);
43
# Note that both Rn and Qd are 3 bits only (no D bit)
47
}
44
@@ -XXX,XX +XXX,XX @@ VMLAS 111- 1110 0 . .. ... 1 ... 1 1110 . 100 .... @2scalar
45
rdahi=%rdahi rdalo=%rdalo
46
}
47
48
+@vabav .... .... .. size:2 .... rda:4 .... .... .... &vabav qn=%qn qm=%qm
49
+
50
+VABAV_S 111 0 1110 10 .. ... 0 .... 1111 . 0 . 0 ... 1 @vabav
51
+VABAV_U 111 1 1110 10 .. ... 0 .... 1111 . 0 . 0 ... 1 @vabav
52
+
53
# Logical immediate operations (1 reg and modified-immediate)
54
55
# The cmode/op bits here decode VORR/VBIC/VMOV/VMVN, but
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_VMAXMINV(vminavb, 1, int8_t, uint8_t, do_mina)
61
DO_VMAXMINV(vminavh, 2, int16_t, uint16_t, do_mina)
62
DO_VMAXMINV(vminavw, 4, int32_t, uint32_t, do_mina)
63
64
+#define DO_VABAV(OP, ESIZE, TYPE) \
65
+ uint32_t HELPER(glue(mve_, OP))(CPUARMState *env, void *vn, \
66
+ void *vm, uint32_t ra) \
67
+ { \
68
+ uint16_t mask = mve_element_mask(env); \
69
+ unsigned e; \
70
+ TYPE *m = vm, *n = vn; \
71
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
72
+ if (mask & 1) { \
73
+ int64_t n0 = n[H##ESIZE(e)]; \
74
+ int64_t m0 = m[H##ESIZE(e)]; \
75
+ uint32_t r = n0 >= m0 ? (n0 - m0) : (m0 - n0); \
76
+ ra += r; \
77
+ } \
78
+ } \
79
+ mve_advance_vpt(env); \
80
+ return ra; \
81
+ }
82
+
83
+DO_VABAV(vabavsb, 1, int8_t)
84
+DO_VABAV(vabavsh, 2, int16_t)
85
+DO_VABAV(vabavsw, 4, int32_t)
86
+DO_VABAV(vabavub, 1, uint8_t)
87
+DO_VABAV(vabavuh, 2, uint16_t)
88
+DO_VABAV(vabavuw, 4, uint32_t)
89
+
90
#define DO_VADDLV(OP, TYPE, LTYPE) \
91
uint64_t HELPER(glue(mve_, OP))(CPUARMState *env, void *vm, \
92
uint64_t ra) \
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 @@ typedef void MVEGenVIDUPFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32, TCGv_i32);
98
typedef void MVEGenVIWDUPFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32, TCGv_i32, TCGv_i32);
99
typedef void MVEGenCmpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
100
typedef void MVEGenScalarCmpFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
101
+typedef void MVEGenVABAVFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
102
103
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
104
static inline long mve_qreg_offset(unsigned reg)
105
@@ -XXX,XX +XXX,XX @@ DO_VMAXV(VMAXAV, vmaxav)
106
DO_VMAXV(VMINV_S, vminvs)
107
DO_VMAXV(VMINV_U, vminvu)
108
DO_VMAXV(VMINAV, vminav)
109
+
110
+static bool do_vabav(DisasContext *s, arg_vabav *a, MVEGenVABAVFn *fn)
111
+{
112
+ /* Absolute difference accumulated across vector */
113
+ TCGv_ptr qn, qm;
114
+ TCGv_i32 rda;
115
+
116
+ if (!dc_isar_feature(aa32_mve, s) ||
117
+ !mve_check_qreg_bank(s, a->qm | a->qn) ||
118
+ !fn || a->rda == 13 || a->rda == 15) {
119
+ /* Rda cases are UNPREDICTABLE */
120
+ return false;
121
+ }
122
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
123
+ return true;
124
+ }
125
+
126
+ qm = mve_qreg_ptr(a->qm);
127
+ qn = mve_qreg_ptr(a->qn);
128
+ rda = load_reg(s, a->rda);
129
+ fn(rda, cpu_env, qn, qm, rda);
130
+ store_reg(s, a->rda, rda);
131
+ tcg_temp_free_ptr(qm);
132
+ tcg_temp_free_ptr(qn);
133
+ mve_update_eci(s);
134
+ return true;
135
+}
136
+
137
+#define DO_VABAV(INSN, FN) \
138
+ static bool trans_##INSN(DisasContext *s, arg_vabav *a) \
139
+ { \
140
+ static MVEGenVABAVFn * 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_vabav(s, a, fns[a->size]); \
147
+ }
148
+
149
+DO_VABAV(VABAV_S, vabavs)
150
+DO_VABAV(VABAV_U, vabavu)
151
--
48
--
152
2.20.1
49
2.34.1
153
50
154
51
diff view generated by jsdifflib
1
Implement the MVE VMLAS insn, which multiplies a vector by a vector
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
and adds a scalar.
3
2
3
Upon introduction in commit b8433303fb ("Set proper device-width
4
for vexpress flash"), ve_pflash_cfi01_register() was calling
5
qdev_init_nofail() which can not fail. This call was later
6
converted with a script to use &error_fatal, still unable to
7
fail. Remove the unreachable code.
8
9
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20230109115316.2235-13-philmd@linaro.org
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
---
13
---
7
target/arm/helper-mve.h | 4 ++++
14
hw/arm/vexpress.c | 10 +---------
8
target/arm/mve.decode | 3 +++
15
1 file changed, 1 insertion(+), 9 deletions(-)
9
target/arm/mve_helper.c | 26 ++++++++++++++++++++++++++
10
target/arm/translate-mve.c | 1 +
11
4 files changed, 34 insertions(+)
12
16
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
17
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
19
--- a/hw/arm/vexpress.c
16
+++ b/target/arm/helper-mve.h
20
+++ b/hw/arm/vexpress.c
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqdmullb_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i3
21
@@ -XXX,XX +XXX,XX @@ static void vexpress_common_init(MachineState *machine)
18
DEF_HELPER_FLAGS_4(mve_vqdmullt_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
22
dinfo = drive_get(IF_PFLASH, 0, 0);
19
DEF_HELPER_FLAGS_4(mve_vqdmullt_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
23
pflash0 = ve_pflash_cfi01_register(map[VE_NORFLASH0], "vexpress.flash0",
20
24
dinfo);
21
+DEF_HELPER_FLAGS_4(mve_vmlasb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
- if (!pflash0) {
22
+DEF_HELPER_FLAGS_4(mve_vmlash, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
26
- error_report("vexpress: error registering flash 0");
23
+DEF_HELPER_FLAGS_4(mve_vmlasw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
27
- exit(1);
24
+
28
- }
25
DEF_HELPER_FLAGS_4(mve_vmlaldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
29
26
DEF_HELPER_FLAGS_4(mve_vmlaldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
30
if (map[VE_NORFLASHALIAS] != -1) {
27
DEF_HELPER_FLAGS_4(mve_vmlaldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
31
/* Map flash 0 as an alias into low memory */
28
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
32
@@ -XXX,XX +XXX,XX @@ static void vexpress_common_init(MachineState *machine)
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/mve.decode
31
+++ b/target/arm/mve.decode
32
@@ -XXX,XX +XXX,XX @@ VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
33
VQDMULH_scalar 1110 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
34
VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
35
36
+# The U bit (28) is don't-care because it does not affect the result
37
+VMLAS 111- 1110 0 . .. ... 1 ... 1 1110 . 100 .... @2scalar
38
+
39
# Vector add across vector
40
{
41
VADDV 111 u:1 1110 1111 size:2 01 ... 0 1111 0 0 a:1 0 qm:3 0 rda=%rdalo
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_VQDMLADH_OP(vqrdmlsdhxw, 4, int32_t, 1, 1, do_vqdmlsdh_w)
47
mve_advance_vpt(env); \
48
}
33
}
49
34
50
+/* "accumulating" version where FN takes d as well as n and m */
35
dinfo = drive_get(IF_PFLASH, 0, 1);
51
+#define DO_2OP_ACC_SCALAR(OP, ESIZE, TYPE, FN) \
36
- if (!ve_pflash_cfi01_register(map[VE_NORFLASH1], "vexpress.flash1",
52
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
37
- dinfo)) {
53
+ uint32_t rm) \
38
- error_report("vexpress: error registering flash 1");
54
+ { \
39
- exit(1);
55
+ TYPE *d = vd, *n = vn; \
40
- }
56
+ TYPE m = rm; \
41
+ ve_pflash_cfi01_register(map[VE_NORFLASH1], "vexpress.flash1", dinfo);
57
+ uint16_t mask = mve_element_mask(env); \
42
58
+ unsigned e; \
43
sram_size = 0x2000000;
59
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
44
memory_region_init_ram(sram, NULL, "vexpress.sram", sram_size,
60
+ mergemask(&d[H##ESIZE(e)], \
61
+ FN(d[H##ESIZE(e)], n[H##ESIZE(e)], m), mask); \
62
+ } \
63
+ mve_advance_vpt(env); \
64
+ }
65
+
66
/* provide unsigned 2-op scalar helpers for all sizes */
67
#define DO_2OP_SCALAR_U(OP, FN) \
68
DO_2OP_SCALAR(OP##b, 1, uint8_t, FN) \
69
@@ -XXX,XX +XXX,XX @@ DO_VQDMLADH_OP(vqrdmlsdhxw, 4, int32_t, 1, 1, do_vqdmlsdh_w)
70
DO_2OP_SCALAR(OP##h, 2, int16_t, FN) \
71
DO_2OP_SCALAR(OP##w, 4, int32_t, FN)
72
73
+#define DO_2OP_ACC_SCALAR_U(OP, FN) \
74
+ DO_2OP_ACC_SCALAR(OP##b, 1, uint8_t, FN) \
75
+ DO_2OP_ACC_SCALAR(OP##h, 2, uint16_t, FN) \
76
+ DO_2OP_ACC_SCALAR(OP##w, 4, uint32_t, FN)
77
+
78
DO_2OP_SCALAR_U(vadd_scalar, DO_ADD)
79
DO_2OP_SCALAR_U(vsub_scalar, DO_SUB)
80
DO_2OP_SCALAR_U(vmul_scalar, DO_MUL)
81
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT_SCALAR(vqrdmulh_scalarb, 1, int8_t, DO_QRDMULH_B)
82
DO_2OP_SAT_SCALAR(vqrdmulh_scalarh, 2, int16_t, DO_QRDMULH_H)
83
DO_2OP_SAT_SCALAR(vqrdmulh_scalarw, 4, int32_t, DO_QRDMULH_W)
84
85
+/* Vector by vector plus scalar */
86
+#define DO_VMLAS(D, N, M) ((N) * (D) + (M))
87
+
88
+DO_2OP_ACC_SCALAR_U(vmlas, DO_VMLAS)
89
+
90
/*
91
* Long saturating scalar ops. As with DO_2OP_L, TYPE and H are for the
92
* input (smaller) type and LESIZE, LTYPE, LH for the output (long) type.
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_SCALAR(VQSUB_U_scalar, vqsubu_scalar)
98
DO_2OP_SCALAR(VQDMULH_scalar, vqdmulh_scalar)
99
DO_2OP_SCALAR(VQRDMULH_scalar, vqrdmulh_scalar)
100
DO_2OP_SCALAR(VBRSR, vbrsr)
101
+DO_2OP_SCALAR(VMLAS, vmlas)
102
103
static bool trans_VQDMULLB_scalar(DisasContext *s, arg_2scalar *a)
104
{
105
--
45
--
106
2.20.1
46
2.34.1
107
47
108
48
diff view generated by jsdifflib
1
In do_sqrshl48_d() and do_uqrshl48_d() we got some of the edge
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
cases wrong and failed to saturate correctly:
3
2
4
(1) In do_sqrshl48_d() we used the same code that do_shrshl_bhs()
3
Since its QOM'ification in commit 368a354f02 ("pflash_cfi0x:
5
does to obtain the saturated most-negative and most-positive 48-bit
4
QOMified") the pflash_cfi01_register() function does not fail.
6
signed values for the large-shift-left case. This gives (1 << 47)
7
for saturate-to-most-negative, but we weren't sign-extending this
8
value to the 64-bit output as the pseudocode requires.
9
5
10
(2) For left shifts by less than 48, we copied the "8/16 bit" code
6
This call was later converted with a script to use &error_fatal,
11
from do_sqrshl_bhs() and do_uqrshl_bhs(). This doesn't do the right
7
still unable to fail. Remove the unreachable code.
12
thing because it assumes the C type we're working with is at least
13
twice the number of bits we're saturating to (so that a shift left by
14
bits-1 can't shift anything off the top of the value). This isn't
15
true for bits == 48, so we would incorrectly return 0 rather than the
16
most-positive value for situations like "shift (1 << 44) right by
17
20". Instead check for saturation by doing the shift and signextend
18
and then testing whether shifting back left again gives the original
19
value.
20
8
9
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20230109115316.2235-14-philmd@linaro.org
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
---
13
---
24
target/arm/mve_helper.c | 12 +++++-------
14
hw/arm/gumstix.c | 18 ++++++------------
25
1 file changed, 5 insertions(+), 7 deletions(-)
15
hw/arm/mainstone.c | 13 +++++--------
16
hw/arm/omap_sx1.c | 22 ++++++++--------------
17
hw/arm/versatilepb.c | 6 ++----
18
hw/arm/z2.c | 9 +++------
19
5 files changed, 24 insertions(+), 44 deletions(-)
26
20
27
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
21
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
28
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/mve_helper.c
23
--- a/hw/arm/gumstix.c
30
+++ b/target/arm/mve_helper.c
24
+++ b/hw/arm/gumstix.c
31
@@ -XXX,XX +XXX,XX @@ static inline int64_t do_sqrshl48_d(int64_t src, int64_t shift,
25
@@ -XXX,XX +XXX,XX @@ static void connex_init(MachineState *machine)
32
}
33
return src >> -shift;
34
} else if (shift < 48) {
35
- int64_t val = src << shift;
36
- int64_t extval = sextract64(val, 0, 48);
37
- if (!sat || val == extval) {
38
+ int64_t extval = sextract64(src << shift, 0, 48);
39
+ if (!sat || src == (extval >> shift)) {
40
return extval;
41
}
42
} else if (!sat || src == 0) {
43
@@ -XXX,XX +XXX,XX @@ static inline int64_t do_sqrshl48_d(int64_t src, int64_t shift,
44
}
26
}
45
27
46
*sat = 1;
28
/* Numonyx RC28F128J3F75 */
47
- return (1ULL << 47) - (src >= 0);
29
- if (!pflash_cfi01_register(0x00000000, "connext.rom", CONNEX_FLASH_SIZE,
48
+ return src >= 0 ? MAKE_64BIT_MASK(0, 47) : MAKE_64BIT_MASK(47, 17);
30
- dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
49
}
31
- FLASH_SECTOR_SIZE, 2, 0, 0, 0, 0, 0)) {
50
32
- error_report("Error registering flash memory");
51
/* Operate on 64-bit values, but saturate at 48 bits */
33
- exit(1);
52
@@ -XXX,XX +XXX,XX @@ static inline uint64_t do_uqrshl48_d(uint64_t src, int64_t shift,
34
- }
53
return extval;
35
+ pflash_cfi01_register(0x00000000, "connext.rom", CONNEX_FLASH_SIZE,
54
}
36
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
55
} else if (shift < 48) {
37
+ FLASH_SECTOR_SIZE, 2, 0, 0, 0, 0, 0);
56
- uint64_t val = src << shift;
38
57
- uint64_t extval = extract64(val, 0, 48);
39
/* Interrupt line of NIC is connected to GPIO line 36 */
58
- if (!sat || val == extval) {
40
smc91c111_init(&nd_table[0], 0x04000300,
59
+ uint64_t extval = extract64(src << shift, 0, 48);
41
@@ -XXX,XX +XXX,XX @@ static void verdex_init(MachineState *machine)
60
+ if (!sat || src == (extval >> shift)) {
42
}
61
return extval;
43
62
}
44
/* Micron RC28F256P30TFA */
63
} else if (!sat || src == 0) {
45
- if (!pflash_cfi01_register(0x00000000, "verdex.rom", VERDEX_FLASH_SIZE,
46
- dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
47
- FLASH_SECTOR_SIZE, 2, 0, 0, 0, 0, 0)) {
48
- error_report("Error registering flash memory");
49
- exit(1);
50
- }
51
+ pflash_cfi01_register(0x00000000, "verdex.rom", VERDEX_FLASH_SIZE,
52
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
53
+ FLASH_SECTOR_SIZE, 2, 0, 0, 0, 0, 0);
54
55
/* Interrupt line of NIC is connected to GPIO line 99 */
56
smc91c111_init(&nd_table[0], 0x04000300,
57
diff --git a/hw/arm/mainstone.c b/hw/arm/mainstone.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/hw/arm/mainstone.c
60
+++ b/hw/arm/mainstone.c
61
@@ -XXX,XX +XXX,XX @@ static void mainstone_common_init(MachineState *machine,
62
/* There are two 32MiB flash devices on the board */
63
for (i = 0; i < 2; i ++) {
64
dinfo = drive_get(IF_PFLASH, 0, i);
65
- if (!pflash_cfi01_register(mainstone_flash_base[i],
66
- i ? "mainstone.flash1" : "mainstone.flash0",
67
- MAINSTONE_FLASH_SIZE,
68
- dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
69
- FLASH_SECTOR_SIZE, 4, 0, 0, 0, 0, 0)) {
70
- error_report("Error registering flash memory");
71
- exit(1);
72
- }
73
+ pflash_cfi01_register(mainstone_flash_base[i],
74
+ i ? "mainstone.flash1" : "mainstone.flash0",
75
+ MAINSTONE_FLASH_SIZE,
76
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
77
+ FLASH_SECTOR_SIZE, 4, 0, 0, 0, 0, 0);
78
}
79
80
mst_irq = sysbus_create_simple("mainstone-fpga", MST_FPGA_PHYS,
81
diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/hw/arm/omap_sx1.c
84
+++ b/hw/arm/omap_sx1.c
85
@@ -XXX,XX +XXX,XX @@ static void sx1_init(MachineState *machine, const int version)
86
87
fl_idx = 0;
88
if ((dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
89
- if (!pflash_cfi01_register(OMAP_CS0_BASE,
90
- "omap_sx1.flash0-1", flash_size,
91
- blk_by_legacy_dinfo(dinfo),
92
- SECTOR_SIZE, 4, 0, 0, 0, 0, 0)) {
93
- fprintf(stderr, "qemu: Error registering flash memory %d.\n",
94
- fl_idx);
95
- }
96
+ pflash_cfi01_register(OMAP_CS0_BASE,
97
+ "omap_sx1.flash0-1", flash_size,
98
+ blk_by_legacy_dinfo(dinfo),
99
+ SECTOR_SIZE, 4, 0, 0, 0, 0, 0);
100
fl_idx++;
101
}
102
103
@@ -XXX,XX +XXX,XX @@ static void sx1_init(MachineState *machine, const int version)
104
memory_region_add_subregion(address_space,
105
OMAP_CS1_BASE + FLASH1_SIZE, &cs[1]);
106
107
- if (!pflash_cfi01_register(OMAP_CS1_BASE,
108
- "omap_sx1.flash1-1", FLASH1_SIZE,
109
- blk_by_legacy_dinfo(dinfo),
110
- SECTOR_SIZE, 4, 0, 0, 0, 0, 0)) {
111
- fprintf(stderr, "qemu: Error registering flash memory %d.\n",
112
- fl_idx);
113
- }
114
+ pflash_cfi01_register(OMAP_CS1_BASE,
115
+ "omap_sx1.flash1-1", FLASH1_SIZE,
116
+ blk_by_legacy_dinfo(dinfo),
117
+ SECTOR_SIZE, 4, 0, 0, 0, 0, 0);
118
fl_idx++;
119
} else {
120
memory_region_init_io(&cs[1], NULL, &static_ops, &cs1val,
121
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
122
index XXXXXXX..XXXXXXX 100644
123
--- a/hw/arm/versatilepb.c
124
+++ b/hw/arm/versatilepb.c
125
@@ -XXX,XX +XXX,XX @@ static void versatile_init(MachineState *machine, int board_id)
126
/* 0x34000000 NOR Flash */
127
128
dinfo = drive_get(IF_PFLASH, 0, 0);
129
- if (!pflash_cfi01_register(VERSATILE_FLASH_ADDR, "versatile.flash",
130
+ pflash_cfi01_register(VERSATILE_FLASH_ADDR, "versatile.flash",
131
VERSATILE_FLASH_SIZE,
132
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
133
VERSATILE_FLASH_SECT_SIZE,
134
- 4, 0x0089, 0x0018, 0x0000, 0x0, 0)) {
135
- fprintf(stderr, "qemu: Error registering flash memory.\n");
136
- }
137
+ 4, 0x0089, 0x0018, 0x0000, 0x0, 0);
138
139
versatile_binfo.ram_size = machine->ram_size;
140
versatile_binfo.board_id = board_id;
141
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
142
index XXXXXXX..XXXXXXX 100644
143
--- a/hw/arm/z2.c
144
+++ b/hw/arm/z2.c
145
@@ -XXX,XX +XXX,XX @@ static void z2_init(MachineState *machine)
146
mpu = pxa270_init(z2_binfo.ram_size, machine->cpu_type);
147
148
dinfo = drive_get(IF_PFLASH, 0, 0);
149
- if (!pflash_cfi01_register(Z2_FLASH_BASE, "z2.flash0", Z2_FLASH_SIZE,
150
- dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
151
- FLASH_SECTOR_SIZE, 4, 0, 0, 0, 0, 0)) {
152
- error_report("Error registering flash memory");
153
- exit(1);
154
- }
155
+ pflash_cfi01_register(Z2_FLASH_BASE, "z2.flash0", Z2_FLASH_SIZE,
156
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
157
+ FLASH_SECTOR_SIZE, 4, 0, 0, 0, 0, 0);
158
159
/* setup keypad */
160
pxa27x_register_keypad(mpu->kp, map, 0x100);
64
--
161
--
65
2.20.1
162
2.34.1
66
163
67
164
diff view generated by jsdifflib
1
A cut-and-paste error meant we handled signed VADDV like
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
unsigned VADDV; fix the type used.
3
2
3
To avoid forward-declaring PXA2xxI2CState, declare
4
PXA2XX_I2C before its use in pxa2xx_i2c_init() prototype.
5
6
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230109140306.23161-2-philmd@linaro.org
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
---
10
---
7
target/arm/mve_helper.c | 6 +++---
11
include/hw/arm/pxa.h | 6 +++---
8
1 file changed, 3 insertions(+), 3 deletions(-)
12
1 file changed, 3 insertions(+), 3 deletions(-)
9
13
10
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
14
diff --git a/include/hw/arm/pxa.h b/include/hw/arm/pxa.h
11
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
12
--- a/target/arm/mve_helper.c
16
--- a/include/hw/arm/pxa.h
13
+++ b/target/arm/mve_helper.c
17
+++ b/include/hw/arm/pxa.h
14
@@ -XXX,XX +XXX,XX @@ DO_LDAVH(vrmlsldavhxsw, int32_t, int64_t, true, true)
18
@@ -XXX,XX +XXX,XX @@ void pxa27x_register_keypad(PXA2xxKeyPadState *kp,
15
return ra; \
19
const struct keymap *map, int size);
16
} \
20
17
21
/* pxa2xx.c */
18
-DO_VADDV(vaddvsb, 1, uint8_t)
22
-typedef struct PXA2xxI2CState PXA2xxI2CState;
19
-DO_VADDV(vaddvsh, 2, uint16_t)
23
+#define TYPE_PXA2XX_I2C "pxa2xx_i2c"
20
-DO_VADDV(vaddvsw, 4, uint32_t)
24
+OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxI2CState, PXA2XX_I2C)
21
+DO_VADDV(vaddvsb, 1, int8_t)
25
+
22
+DO_VADDV(vaddvsh, 2, int16_t)
26
PXA2xxI2CState *pxa2xx_i2c_init(hwaddr base,
23
+DO_VADDV(vaddvsw, 4, int32_t)
27
qemu_irq irq, uint32_t page_size);
24
DO_VADDV(vaddvub, 1, uint8_t)
28
I2CBus *pxa2xx_i2c_bus(PXA2xxI2CState *s);
25
DO_VADDV(vaddvuh, 2, uint16_t)
29
26
DO_VADDV(vaddvuw, 4, uint32_t)
30
-#define TYPE_PXA2XX_I2C "pxa2xx_i2c"
31
typedef struct PXA2xxI2SState PXA2xxI2SState;
32
-OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxI2CState, PXA2XX_I2C)
33
34
#define TYPE_PXA2XX_FIR "pxa2xx-fir"
35
OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxFIrState, PXA2XX_FIR)
27
--
36
--
28
2.20.1
37
2.34.1
29
38
30
39
diff view generated by jsdifflib
1
In mve_element_mask(), we calculate a mask for tail predication which
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
should have a number of 1 bits based on the value of LR. However,
3
our MAKE_64BIT_MASK() macro has undefined behaviour when passed a
4
zero length. Special case this to give the all-zeroes mask we
5
require.
6
2
3
Add a local 'struct omap_gpif_s *' variable to improve readability.
4
(This also eases next commit conversion).
5
6
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20230109140306.23161-3-philmd@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
---
10
---
10
target/arm/mve_helper.c | 3 ++-
11
hw/gpio/omap_gpio.c | 3 ++-
11
1 file changed, 2 insertions(+), 1 deletion(-)
12
1 file changed, 2 insertions(+), 1 deletion(-)
12
13
13
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
14
diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/mve_helper.c
16
--- a/hw/gpio/omap_gpio.c
16
+++ b/target/arm/mve_helper.c
17
+++ b/hw/gpio/omap_gpio.c
17
@@ -XXX,XX +XXX,XX @@ static uint16_t mve_element_mask(CPUARMState *env)
18
@@ -XXX,XX +XXX,XX @@ struct omap_gpif_s {
18
*/
19
/* General-Purpose I/O of OMAP1 */
19
int masklen = env->regs[14] << env->v7m.ltpsize;
20
static void omap_gpio_set(void *opaque, int line, int level)
20
assert(masklen <= 16);
21
{
21
- mask &= MAKE_64BIT_MASK(0, masklen);
22
- struct omap_gpio_s *s = &((struct omap_gpif_s *) opaque)->omap1;
22
+ uint16_t ltpmask = masklen ? MAKE_64BIT_MASK(0, masklen) : 0;
23
+ struct omap_gpif_s *p = opaque;
23
+ mask &= ltpmask;
24
+ struct omap_gpio_s *s = &p->omap1;
24
}
25
uint16_t prev = s->inputs;
25
26
26
if ((env->condexec_bits & 0xf) == 0) {
27
if (level)
27
--
28
--
28
2.20.1
29
2.34.1
29
30
30
31
diff view generated by jsdifflib
1
Include the MVE VPR register value in the CPU dumps produced by
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
arm_cpu_dump_state() if we are printing FPU information. This
3
makes it easier to interpret debug logs when predication is
4
active.
5
2
3
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20230109140306.23161-4-philmd@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
---
7
---
9
target/arm/cpu.c | 3 +++
8
hw/arm/omap1.c | 115 ++++++++++++++++++--------------------
10
1 file changed, 3 insertions(+)
9
hw/arm/omap2.c | 40 ++++++-------
10
hw/arm/omap_sx1.c | 2 +-
11
hw/arm/palm.c | 2 +-
12
hw/char/omap_uart.c | 7 +--
13
hw/display/omap_dss.c | 15 +++--
14
hw/display/omap_lcdc.c | 9 ++-
15
hw/dma/omap_dma.c | 15 +++--
16
hw/gpio/omap_gpio.c | 15 +++--
17
hw/intc/omap_intc.c | 12 ++--
18
hw/misc/omap_gpmc.c | 12 ++--
19
hw/misc/omap_l4.c | 7 +--
20
hw/misc/omap_sdrc.c | 7 +--
21
hw/misc/omap_tap.c | 5 +-
22
hw/sd/omap_mmc.c | 9 ++-
23
hw/ssi/omap_spi.c | 7 +--
24
hw/timer/omap_gptimer.c | 22 ++++----
25
hw/timer/omap_synctimer.c | 4 +-
26
18 files changed, 142 insertions(+), 163 deletions(-)
11
27
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
28
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
13
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/cpu.c
30
--- a/hw/arm/omap1.c
15
+++ b/target/arm/cpu.c
31
+++ b/hw/arm/omap1.c
16
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_dump_state(CPUState *cs, FILE *f, int flags)
32
@@ -XXX,XX +XXX,XX @@ static void omap_timer_fire(void *opaque)
17
i, v);
33
18
}
34
static void omap_timer_tick(void *opaque)
19
qemu_fprintf(f, "FPSCR: %08x\n", vfp_get_fpscr(env));
35
{
20
+ if (cpu_isar_feature(aa32_mve, cpu)) {
36
- struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
21
+ qemu_fprintf(f, "VPR: %08x\n", env->v7m.vpr);
37
+ struct omap_mpu_timer_s *timer = opaque;
22
+ }
38
39
omap_timer_sync(timer);
40
omap_timer_fire(timer);
41
@@ -XXX,XX +XXX,XX @@ static void omap_timer_tick(void *opaque)
42
43
static void omap_timer_clk_update(void *opaque, int line, int on)
44
{
45
- struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
46
+ struct omap_mpu_timer_s *timer = opaque;
47
48
omap_timer_sync(timer);
49
timer->rate = on ? omap_clk_getrate(timer->clk) : 0;
50
@@ -XXX,XX +XXX,XX @@ static void omap_timer_clk_setup(struct omap_mpu_timer_s *timer)
51
static uint64_t omap_mpu_timer_read(void *opaque, hwaddr addr,
52
unsigned size)
53
{
54
- struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
55
+ struct omap_mpu_timer_s *s = opaque;
56
57
if (size != 4) {
58
return omap_badwidth_read32(opaque, addr);
59
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_mpu_timer_read(void *opaque, hwaddr addr,
60
static void omap_mpu_timer_write(void *opaque, hwaddr addr,
61
uint64_t value, unsigned size)
62
{
63
- struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
64
+ struct omap_mpu_timer_s *s = opaque;
65
66
if (size != 4) {
67
omap_badwidth_write32(opaque, addr, value);
68
@@ -XXX,XX +XXX,XX @@ struct omap_watchdog_timer_s {
69
static uint64_t omap_wd_timer_read(void *opaque, hwaddr addr,
70
unsigned size)
71
{
72
- struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
73
+ struct omap_watchdog_timer_s *s = opaque;
74
75
if (size != 2) {
76
return omap_badwidth_read16(opaque, addr);
77
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_wd_timer_read(void *opaque, hwaddr addr,
78
static void omap_wd_timer_write(void *opaque, hwaddr addr,
79
uint64_t value, unsigned size)
80
{
81
- struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
82
+ struct omap_watchdog_timer_s *s = opaque;
83
84
if (size != 2) {
85
omap_badwidth_write16(opaque, addr, value);
86
@@ -XXX,XX +XXX,XX @@ struct omap_32khz_timer_s {
87
static uint64_t omap_os_timer_read(void *opaque, hwaddr addr,
88
unsigned size)
89
{
90
- struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;
91
+ struct omap_32khz_timer_s *s = opaque;
92
int offset = addr & OMAP_MPUI_REG_MASK;
93
94
if (size != 4) {
95
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_os_timer_read(void *opaque, hwaddr addr,
96
static void omap_os_timer_write(void *opaque, hwaddr addr,
97
uint64_t value, unsigned size)
98
{
99
- struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;
100
+ struct omap_32khz_timer_s *s = opaque;
101
int offset = addr & OMAP_MPUI_REG_MASK;
102
103
if (size != 4) {
104
@@ -XXX,XX +XXX,XX @@ static struct omap_32khz_timer_s *omap_os_timer_init(MemoryRegion *memory,
105
static uint64_t omap_ulpd_pm_read(void *opaque, hwaddr addr,
106
unsigned size)
107
{
108
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
109
+ struct omap_mpu_state_s *s = opaque;
110
uint16_t ret;
111
112
if (size != 2) {
113
@@ -XXX,XX +XXX,XX @@ static inline void omap_ulpd_req_update(struct omap_mpu_state_s *s,
114
static void omap_ulpd_pm_write(void *opaque, hwaddr addr,
115
uint64_t value, unsigned size)
116
{
117
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
118
+ struct omap_mpu_state_s *s = opaque;
119
int64_t now, ticks;
120
int div, mult;
121
static const int bypass_div[4] = { 1, 2, 4, 4 };
122
@@ -XXX,XX +XXX,XX @@ static void omap_ulpd_pm_init(MemoryRegion *system_memory,
123
static uint64_t omap_pin_cfg_read(void *opaque, hwaddr addr,
124
unsigned size)
125
{
126
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
127
+ struct omap_mpu_state_s *s = opaque;
128
129
if (size != 4) {
130
return omap_badwidth_read32(opaque, addr);
131
@@ -XXX,XX +XXX,XX @@ static inline void omap_pin_modconf1_update(struct omap_mpu_state_s *s,
132
static void omap_pin_cfg_write(void *opaque, hwaddr addr,
133
uint64_t value, unsigned size)
134
{
135
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
136
+ struct omap_mpu_state_s *s = opaque;
137
uint32_t diff;
138
139
if (size != 4) {
140
@@ -XXX,XX +XXX,XX @@ static void omap_pin_cfg_init(MemoryRegion *system_memory,
141
static uint64_t omap_id_read(void *opaque, hwaddr addr,
142
unsigned size)
143
{
144
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
145
+ struct omap_mpu_state_s *s = opaque;
146
147
if (size != 4) {
148
return omap_badwidth_read32(opaque, addr);
149
@@ -XXX,XX +XXX,XX @@ static void omap_id_init(MemoryRegion *memory, struct omap_mpu_state_s *mpu)
150
static uint64_t omap_mpui_read(void *opaque, hwaddr addr,
151
unsigned size)
152
{
153
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
154
+ struct omap_mpu_state_s *s = opaque;
155
156
if (size != 4) {
157
return omap_badwidth_read32(opaque, addr);
158
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_mpui_read(void *opaque, hwaddr addr,
159
static void omap_mpui_write(void *opaque, hwaddr addr,
160
uint64_t value, unsigned size)
161
{
162
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
163
+ struct omap_mpu_state_s *s = opaque;
164
165
if (size != 4) {
166
omap_badwidth_write32(opaque, addr, value);
167
@@ -XXX,XX +XXX,XX @@ struct omap_tipb_bridge_s {
168
static uint64_t omap_tipb_bridge_read(void *opaque, hwaddr addr,
169
unsigned size)
170
{
171
- struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque;
172
+ struct omap_tipb_bridge_s *s = opaque;
173
174
if (size < 2) {
175
return omap_badwidth_read16(opaque, addr);
176
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_tipb_bridge_read(void *opaque, hwaddr addr,
177
static void omap_tipb_bridge_write(void *opaque, hwaddr addr,
178
uint64_t value, unsigned size)
179
{
180
- struct omap_tipb_bridge_s *s = (struct omap_tipb_bridge_s *) opaque;
181
+ struct omap_tipb_bridge_s *s = opaque;
182
183
if (size < 2) {
184
omap_badwidth_write16(opaque, addr, value);
185
@@ -XXX,XX +XXX,XX @@ static struct omap_tipb_bridge_s *omap_tipb_bridge_init(
186
static uint64_t omap_tcmi_read(void *opaque, hwaddr addr,
187
unsigned size)
188
{
189
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
190
+ struct omap_mpu_state_s *s = opaque;
191
uint32_t ret;
192
193
if (size != 4) {
194
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_tcmi_read(void *opaque, hwaddr addr,
195
static void omap_tcmi_write(void *opaque, hwaddr addr,
196
uint64_t value, unsigned size)
197
{
198
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
199
+ struct omap_mpu_state_s *s = opaque;
200
201
if (size != 4) {
202
omap_badwidth_write32(opaque, addr, value);
203
@@ -XXX,XX +XXX,XX @@ struct dpll_ctl_s {
204
static uint64_t omap_dpll_read(void *opaque, hwaddr addr,
205
unsigned size)
206
{
207
- struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque;
208
+ struct dpll_ctl_s *s = opaque;
209
210
if (size != 2) {
211
return omap_badwidth_read16(opaque, addr);
212
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_dpll_read(void *opaque, hwaddr addr,
213
static void omap_dpll_write(void *opaque, hwaddr addr,
214
uint64_t value, unsigned size)
215
{
216
- struct dpll_ctl_s *s = (struct dpll_ctl_s *) opaque;
217
+ struct dpll_ctl_s *s = opaque;
218
uint16_t diff;
219
static const int bypass_div[4] = { 1, 2, 4, 4 };
220
int div, mult;
221
@@ -XXX,XX +XXX,XX @@ static struct dpll_ctl_s *omap_dpll_init(MemoryRegion *memory,
222
static uint64_t omap_clkm_read(void *opaque, hwaddr addr,
223
unsigned size)
224
{
225
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
226
+ struct omap_mpu_state_s *s = opaque;
227
228
if (size != 2) {
229
return omap_badwidth_read16(opaque, addr);
230
@@ -XXX,XX +XXX,XX @@ static inline void omap_clkm_ckout1_update(struct omap_mpu_state_s *s,
231
static void omap_clkm_write(void *opaque, hwaddr addr,
232
uint64_t value, unsigned size)
233
{
234
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
235
+ struct omap_mpu_state_s *s = opaque;
236
uint16_t diff;
237
omap_clk clk;
238
static const char *clkschemename[8] = {
239
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps omap_clkm_ops = {
240
static uint64_t omap_clkdsp_read(void *opaque, hwaddr addr,
241
unsigned size)
242
{
243
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
244
+ struct omap_mpu_state_s *s = opaque;
245
CPUState *cpu = CPU(s->cpu);
246
247
if (size != 2) {
248
@@ -XXX,XX +XXX,XX @@ static inline void omap_clkdsp_idlect2_update(struct omap_mpu_state_s *s,
249
static void omap_clkdsp_write(void *opaque, hwaddr addr,
250
uint64_t value, unsigned size)
251
{
252
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
253
+ struct omap_mpu_state_s *s = opaque;
254
uint16_t diff;
255
256
if (size != 2) {
257
@@ -XXX,XX +XXX,XX @@ struct omap_mpuio_s {
258
259
static void omap_mpuio_set(void *opaque, int line, int level)
260
{
261
- struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
262
+ struct omap_mpuio_s *s = opaque;
263
uint16_t prev = s->inputs;
264
265
if (level)
266
@@ -XXX,XX +XXX,XX @@ static void omap_mpuio_kbd_update(struct omap_mpuio_s *s)
267
static uint64_t omap_mpuio_read(void *opaque, hwaddr addr,
268
unsigned size)
269
{
270
- struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
271
+ struct omap_mpuio_s *s = opaque;
272
int offset = addr & OMAP_MPUI_REG_MASK;
273
uint16_t ret;
274
275
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_mpuio_read(void *opaque, hwaddr addr,
276
static void omap_mpuio_write(void *opaque, hwaddr addr,
277
uint64_t value, unsigned size)
278
{
279
- struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
280
+ struct omap_mpuio_s *s = opaque;
281
int offset = addr & OMAP_MPUI_REG_MASK;
282
uint16_t diff;
283
int ln;
284
@@ -XXX,XX +XXX,XX @@ static void omap_mpuio_reset(struct omap_mpuio_s *s)
285
286
static void omap_mpuio_onoff(void *opaque, int line, int on)
287
{
288
- struct omap_mpuio_s *s = (struct omap_mpuio_s *) opaque;
289
+ struct omap_mpuio_s *s = opaque;
290
291
s->clk = on;
292
if (on)
293
@@ -XXX,XX +XXX,XX @@ static void omap_uwire_transfer_start(struct omap_uwire_s *s)
23
}
294
}
24
}
295
}
25
296
297
-static uint64_t omap_uwire_read(void *opaque, hwaddr addr,
298
- unsigned size)
299
+static uint64_t omap_uwire_read(void *opaque, hwaddr addr, unsigned size)
300
{
301
- struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
302
+ struct omap_uwire_s *s = opaque;
303
int offset = addr & OMAP_MPUI_REG_MASK;
304
305
if (size != 2) {
306
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_uwire_read(void *opaque, hwaddr addr,
307
static void omap_uwire_write(void *opaque, hwaddr addr,
308
uint64_t value, unsigned size)
309
{
310
- struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
311
+ struct omap_uwire_s *s = opaque;
312
int offset = addr & OMAP_MPUI_REG_MASK;
313
314
if (size != 2) {
315
@@ -XXX,XX +XXX,XX @@ static void omap_pwl_update(struct omap_pwl_s *s)
316
}
317
}
318
319
-static uint64_t omap_pwl_read(void *opaque, hwaddr addr,
320
- unsigned size)
321
+static uint64_t omap_pwl_read(void *opaque, hwaddr addr, unsigned size)
322
{
323
- struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
324
+ struct omap_pwl_s *s = opaque;
325
int offset = addr & OMAP_MPUI_REG_MASK;
326
327
if (size != 1) {
328
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_pwl_read(void *opaque, hwaddr addr,
329
static void omap_pwl_write(void *opaque, hwaddr addr,
330
uint64_t value, unsigned size)
331
{
332
- struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
333
+ struct omap_pwl_s *s = opaque;
334
int offset = addr & OMAP_MPUI_REG_MASK;
335
336
if (size != 1) {
337
@@ -XXX,XX +XXX,XX @@ static void omap_pwl_reset(struct omap_pwl_s *s)
338
339
static void omap_pwl_clk_update(void *opaque, int line, int on)
340
{
341
- struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
342
+ struct omap_pwl_s *s = opaque;
343
344
s->clk = on;
345
omap_pwl_update(s);
346
@@ -XXX,XX +XXX,XX @@ struct omap_pwt_s {
347
omap_clk clk;
348
};
349
350
-static uint64_t omap_pwt_read(void *opaque, hwaddr addr,
351
- unsigned size)
352
+static uint64_t omap_pwt_read(void *opaque, hwaddr addr, unsigned size)
353
{
354
- struct omap_pwt_s *s = (struct omap_pwt_s *) opaque;
355
+ struct omap_pwt_s *s = opaque;
356
int offset = addr & OMAP_MPUI_REG_MASK;
357
358
if (size != 1) {
359
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_pwt_read(void *opaque, hwaddr addr,
360
static void omap_pwt_write(void *opaque, hwaddr addr,
361
uint64_t value, unsigned size)
362
{
363
- struct omap_pwt_s *s = (struct omap_pwt_s *) opaque;
364
+ struct omap_pwt_s *s = opaque;
365
int offset = addr & OMAP_MPUI_REG_MASK;
366
367
if (size != 1) {
368
@@ -XXX,XX +XXX,XX @@ static void omap_rtc_alarm_update(struct omap_rtc_s *s)
369
printf("%s: conversion failed\n", __func__);
370
}
371
372
-static uint64_t omap_rtc_read(void *opaque, hwaddr addr,
373
- unsigned size)
374
+static uint64_t omap_rtc_read(void *opaque, hwaddr addr, unsigned size)
375
{
376
- struct omap_rtc_s *s = (struct omap_rtc_s *) opaque;
377
+ struct omap_rtc_s *s = opaque;
378
int offset = addr & OMAP_MPUI_REG_MASK;
379
uint8_t i;
380
381
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_rtc_read(void *opaque, hwaddr addr,
382
static void omap_rtc_write(void *opaque, hwaddr addr,
383
uint64_t value, unsigned size)
384
{
385
- struct omap_rtc_s *s = (struct omap_rtc_s *) opaque;
386
+ struct omap_rtc_s *s = opaque;
387
int offset = addr & OMAP_MPUI_REG_MASK;
388
struct tm new_tm;
389
time_t ti[2];
390
@@ -XXX,XX +XXX,XX @@ static void omap_mcbsp_rx_newdata(struct omap_mcbsp_s *s)
391
392
static void omap_mcbsp_source_tick(void *opaque)
393
{
394
- struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
395
+ struct omap_mcbsp_s *s = opaque;
396
static const int bps[8] = { 0, 1, 1, 2, 2, 2, -255, -255 };
397
398
if (!s->rx_rate)
399
@@ -XXX,XX +XXX,XX @@ static void omap_mcbsp_tx_newdata(struct omap_mcbsp_s *s)
400
401
static void omap_mcbsp_sink_tick(void *opaque)
402
{
403
- struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
404
+ struct omap_mcbsp_s *s = opaque;
405
static const int bps[8] = { 0, 1, 1, 2, 2, 2, -255, -255 };
406
407
if (!s->tx_rate)
408
@@ -XXX,XX +XXX,XX @@ static void omap_mcbsp_req_update(struct omap_mcbsp_s *s)
409
static uint64_t omap_mcbsp_read(void *opaque, hwaddr addr,
410
unsigned size)
411
{
412
- struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
413
+ struct omap_mcbsp_s *s = opaque;
414
int offset = addr & OMAP_MPUI_REG_MASK;
415
uint16_t ret;
416
417
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_mcbsp_read(void *opaque, hwaddr addr,
418
static void omap_mcbsp_writeh(void *opaque, hwaddr addr,
419
uint32_t value)
420
{
421
- struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
422
+ struct omap_mcbsp_s *s = opaque;
423
int offset = addr & OMAP_MPUI_REG_MASK;
424
425
switch (offset) {
426
@@ -XXX,XX +XXX,XX @@ static void omap_mcbsp_writeh(void *opaque, hwaddr addr,
427
static void omap_mcbsp_writew(void *opaque, hwaddr addr,
428
uint32_t value)
429
{
430
- struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
431
+ struct omap_mcbsp_s *s = opaque;
432
int offset = addr & OMAP_MPUI_REG_MASK;
433
434
if (offset == 0x04) {                /* DXR */
435
@@ -XXX,XX +XXX,XX @@ static struct omap_mcbsp_s *omap_mcbsp_init(MemoryRegion *system_memory,
436
437
static void omap_mcbsp_i2s_swallow(void *opaque, int line, int level)
438
{
439
- struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
440
+ struct omap_mcbsp_s *s = opaque;
441
442
if (s->rx_rate) {
443
s->rx_req = s->codec->in.len;
444
@@ -XXX,XX +XXX,XX @@ static void omap_mcbsp_i2s_swallow(void *opaque, int line, int level)
445
446
static void omap_mcbsp_i2s_start(void *opaque, int line, int level)
447
{
448
- struct omap_mcbsp_s *s = (struct omap_mcbsp_s *) opaque;
449
+ struct omap_mcbsp_s *s = opaque;
450
451
if (s->tx_rate) {
452
s->tx_req = s->codec->out.size;
453
@@ -XXX,XX +XXX,XX @@ static void omap_lpg_reset(struct omap_lpg_s *s)
454
omap_lpg_update(s);
455
}
456
457
-static uint64_t omap_lpg_read(void *opaque, hwaddr addr,
458
- unsigned size)
459
+static uint64_t omap_lpg_read(void *opaque, hwaddr addr, unsigned size)
460
{
461
- struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
462
+ struct omap_lpg_s *s = opaque;
463
int offset = addr & OMAP_MPUI_REG_MASK;
464
465
if (size != 1) {
466
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_lpg_read(void *opaque, hwaddr addr,
467
static void omap_lpg_write(void *opaque, hwaddr addr,
468
uint64_t value, unsigned size)
469
{
470
- struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
471
+ struct omap_lpg_s *s = opaque;
472
int offset = addr & OMAP_MPUI_REG_MASK;
473
474
if (size != 1) {
475
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps omap_lpg_ops = {
476
477
static void omap_lpg_clk_update(void *opaque, int line, int on)
478
{
479
- struct omap_lpg_s *s = (struct omap_lpg_s *) opaque;
480
+ struct omap_lpg_s *s = opaque;
481
482
s->clk = on;
483
omap_lpg_update(s);
484
@@ -XXX,XX +XXX,XX @@ static void omap_setup_mpui_io(MemoryRegion *system_memory,
485
/* General chip reset */
486
static void omap1_mpu_reset(void *opaque)
487
{
488
- struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
489
+ struct omap_mpu_state_s *mpu = opaque;
490
491
omap_dma_reset(mpu->dma);
492
omap_mpu_timer_reset(mpu->timer[0]);
493
@@ -XXX,XX +XXX,XX @@ static void omap_setup_dsp_mapping(MemoryRegion *system_memory,
494
495
void omap_mpu_wakeup(void *opaque, int irq, int req)
496
{
497
- struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
498
+ struct omap_mpu_state_s *mpu = opaque;
499
CPUState *cpu = CPU(mpu->cpu);
500
501
if (cpu->halted) {
502
diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c
503
index XXXXXXX..XXXXXXX 100644
504
--- a/hw/arm/omap2.c
505
+++ b/hw/arm/omap2.c
506
@@ -XXX,XX +XXX,XX @@ static inline void omap_eac_out_empty(struct omap_eac_s *s)
507
508
static void omap_eac_in_cb(void *opaque, int avail_b)
509
{
510
- struct omap_eac_s *s = (struct omap_eac_s *) opaque;
511
+ struct omap_eac_s *s = opaque;
512
513
s->codec.rxavail = avail_b >> 2;
514
omap_eac_in_refill(s);
515
@@ -XXX,XX +XXX,XX @@ static void omap_eac_in_cb(void *opaque, int avail_b)
516
517
static void omap_eac_out_cb(void *opaque, int free_b)
518
{
519
- struct omap_eac_s *s = (struct omap_eac_s *) opaque;
520
+ struct omap_eac_s *s = opaque;
521
522
s->codec.txavail = free_b >> 2;
523
if (s->codec.txlen)
524
@@ -XXX,XX +XXX,XX @@ static void omap_eac_reset(struct omap_eac_s *s)
525
omap_eac_interrupt_update(s);
526
}
527
528
-static uint64_t omap_eac_read(void *opaque, hwaddr addr,
529
- unsigned size)
530
+static uint64_t omap_eac_read(void *opaque, hwaddr addr, unsigned size)
531
{
532
- struct omap_eac_s *s = (struct omap_eac_s *) opaque;
533
+ struct omap_eac_s *s = opaque;
534
uint32_t ret;
535
536
if (size != 2) {
537
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_eac_read(void *opaque, hwaddr addr,
538
static void omap_eac_write(void *opaque, hwaddr addr,
539
uint64_t value, unsigned size)
540
{
541
- struct omap_eac_s *s = (struct omap_eac_s *) opaque;
542
+ struct omap_eac_s *s = opaque;
543
544
if (size != 2) {
545
omap_badwidth_write16(opaque, addr, value);
546
@@ -XXX,XX +XXX,XX @@ static void omap_sti_reset(struct omap_sti_s *s)
547
static uint64_t omap_sti_read(void *opaque, hwaddr addr,
548
unsigned size)
549
{
550
- struct omap_sti_s *s = (struct omap_sti_s *) opaque;
551
+ struct omap_sti_s *s = opaque;
552
553
if (size != 4) {
554
return omap_badwidth_read32(opaque, addr);
555
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_sti_read(void *opaque, hwaddr addr,
556
static void omap_sti_write(void *opaque, hwaddr addr,
557
uint64_t value, unsigned size)
558
{
559
- struct omap_sti_s *s = (struct omap_sti_s *) opaque;
560
+ struct omap_sti_s *s = opaque;
561
562
if (size != 4) {
563
omap_badwidth_write32(opaque, addr, value);
564
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps omap_sti_ops = {
565
.endianness = DEVICE_NATIVE_ENDIAN,
566
};
567
568
-static uint64_t omap_sti_fifo_read(void *opaque, hwaddr addr,
569
- unsigned size)
570
+static uint64_t omap_sti_fifo_read(void *opaque, hwaddr addr, unsigned size)
571
{
572
OMAP_BAD_REG(addr);
573
return 0;
574
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_sti_fifo_read(void *opaque, hwaddr addr,
575
static void omap_sti_fifo_write(void *opaque, hwaddr addr,
576
uint64_t value, unsigned size)
577
{
578
- struct omap_sti_s *s = (struct omap_sti_s *) opaque;
579
+ struct omap_sti_s *s = opaque;
580
int ch = addr >> 6;
581
uint8_t byte = value;
582
583
@@ -XXX,XX +XXX,XX @@ static void omap_prcm_int_update(struct omap_prcm_s *s, int dom)
584
static uint64_t omap_prcm_read(void *opaque, hwaddr addr,
585
unsigned size)
586
{
587
- struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
588
+ struct omap_prcm_s *s = opaque;
589
uint32_t ret;
590
591
if (size != 4) {
592
@@ -XXX,XX +XXX,XX @@ static void omap_prcm_dpll_update(struct omap_prcm_s *s)
593
static void omap_prcm_write(void *opaque, hwaddr addr,
594
uint64_t value, unsigned size)
595
{
596
- struct omap_prcm_s *s = (struct omap_prcm_s *) opaque;
597
+ struct omap_prcm_s *s = opaque;
598
599
if (size != 4) {
600
omap_badwidth_write32(opaque, addr, value);
601
@@ -XXX,XX +XXX,XX @@ struct omap_sysctl_s {
602
static uint32_t omap_sysctl_read8(void *opaque, hwaddr addr)
603
{
604
605
- struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
606
+ struct omap_sysctl_s *s = opaque;
607
int pad_offset, byte_offset;
608
int value;
609
610
@@ -XXX,XX +XXX,XX @@ static uint32_t omap_sysctl_read8(void *opaque, hwaddr addr)
611
612
static uint32_t omap_sysctl_read(void *opaque, hwaddr addr)
613
{
614
- struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
615
+ struct omap_sysctl_s *s = opaque;
616
617
switch (addr) {
618
case 0x000:    /* CONTROL_REVISION */
619
@@ -XXX,XX +XXX,XX @@ static uint32_t omap_sysctl_read(void *opaque, hwaddr addr)
620
return 0;
621
}
622
623
-static void omap_sysctl_write8(void *opaque, hwaddr addr,
624
- uint32_t value)
625
+static void omap_sysctl_write8(void *opaque, hwaddr addr, uint32_t value)
626
{
627
- struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
628
+ struct omap_sysctl_s *s = opaque;
629
int pad_offset, byte_offset;
630
int prev_value;
631
632
@@ -XXX,XX +XXX,XX @@ static void omap_sysctl_write8(void *opaque, hwaddr addr,
633
}
634
}
635
636
-static void omap_sysctl_write(void *opaque, hwaddr addr,
637
- uint32_t value)
638
+static void omap_sysctl_write(void *opaque, hwaddr addr, uint32_t value)
639
{
640
- struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
641
+ struct omap_sysctl_s *s = opaque;
642
643
switch (addr) {
644
case 0x000:    /* CONTROL_REVISION */
645
@@ -XXX,XX +XXX,XX @@ static struct omap_sysctl_s *omap_sysctl_init(struct omap_target_agent_s *ta,
646
/* General chip reset */
647
static void omap2_mpu_reset(void *opaque)
648
{
649
- struct omap_mpu_state_s *mpu = (struct omap_mpu_state_s *) opaque;
650
+ struct omap_mpu_state_s *mpu = opaque;
651
652
omap_dma_reset(mpu->dma);
653
omap_prcm_reset(mpu->prcm);
654
diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
655
index XXXXXXX..XXXXXXX 100644
656
--- a/hw/arm/omap_sx1.c
657
+++ b/hw/arm/omap_sx1.c
658
@@ -XXX,XX +XXX,XX @@
659
static uint64_t static_read(void *opaque, hwaddr offset,
660
unsigned size)
661
{
662
- uint32_t *val = (uint32_t *) opaque;
663
+ uint32_t *val = opaque;
664
uint32_t mask = (4 / size) - 1;
665
666
return *val >> ((offset & mask) << 3);
667
diff --git a/hw/arm/palm.c b/hw/arm/palm.c
668
index XXXXXXX..XXXXXXX 100644
669
--- a/hw/arm/palm.c
670
+++ b/hw/arm/palm.c
671
@@ -XXX,XX +XXX,XX @@ static struct {
672
673
static void palmte_button_event(void *opaque, int keycode)
674
{
675
- struct omap_mpu_state_s *cpu = (struct omap_mpu_state_s *) opaque;
676
+ struct omap_mpu_state_s *cpu = opaque;
677
678
if (palmte_keymap[keycode & 0x7f].row != -1)
679
omap_mpuio_key(cpu->mpuio,
680
diff --git a/hw/char/omap_uart.c b/hw/char/omap_uart.c
681
index XXXXXXX..XXXXXXX 100644
682
--- a/hw/char/omap_uart.c
683
+++ b/hw/char/omap_uart.c
684
@@ -XXX,XX +XXX,XX @@ struct omap_uart_s *omap_uart_init(hwaddr base,
685
return s;
686
}
687
688
-static uint64_t omap_uart_read(void *opaque, hwaddr addr,
689
- unsigned size)
690
+static uint64_t omap_uart_read(void *opaque, hwaddr addr, unsigned size)
691
{
692
- struct omap_uart_s *s = (struct omap_uart_s *) opaque;
693
+ struct omap_uart_s *s = opaque;
694
695
if (size == 4) {
696
return omap_badwidth_read8(opaque, addr);
697
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_uart_read(void *opaque, hwaddr addr,
698
static void omap_uart_write(void *opaque, hwaddr addr,
699
uint64_t value, unsigned size)
700
{
701
- struct omap_uart_s *s = (struct omap_uart_s *) opaque;
702
+ struct omap_uart_s *s = opaque;
703
704
if (size == 4) {
705
omap_badwidth_write8(opaque, addr, value);
706
diff --git a/hw/display/omap_dss.c b/hw/display/omap_dss.c
707
index XXXXXXX..XXXXXXX 100644
708
--- a/hw/display/omap_dss.c
709
+++ b/hw/display/omap_dss.c
710
@@ -XXX,XX +XXX,XX @@ void omap_dss_reset(struct omap_dss_s *s)
711
static uint64_t omap_diss_read(void *opaque, hwaddr addr,
712
unsigned size)
713
{
714
- struct omap_dss_s *s = (struct omap_dss_s *) opaque;
715
+ struct omap_dss_s *s = opaque;
716
717
if (size != 4) {
718
return omap_badwidth_read32(opaque, addr);
719
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_diss_read(void *opaque, hwaddr addr,
720
static void omap_diss_write(void *opaque, hwaddr addr,
721
uint64_t value, unsigned size)
722
{
723
- struct omap_dss_s *s = (struct omap_dss_s *) opaque;
724
+ struct omap_dss_s *s = opaque;
725
726
if (size != 4) {
727
omap_badwidth_write32(opaque, addr, value);
728
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps omap_diss_ops = {
729
static uint64_t omap_disc_read(void *opaque, hwaddr addr,
730
unsigned size)
731
{
732
- struct omap_dss_s *s = (struct omap_dss_s *) opaque;
733
+ struct omap_dss_s *s = opaque;
734
735
if (size != 4) {
736
return omap_badwidth_read32(opaque, addr);
737
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_disc_read(void *opaque, hwaddr addr,
738
static void omap_disc_write(void *opaque, hwaddr addr,
739
uint64_t value, unsigned size)
740
{
741
- struct omap_dss_s *s = (struct omap_dss_s *) opaque;
742
+ struct omap_dss_s *s = opaque;
743
744
if (size != 4) {
745
omap_badwidth_write32(opaque, addr, value);
746
@@ -XXX,XX +XXX,XX @@ static void omap_rfbi_transfer_start(struct omap_dss_s *s)
747
omap_dispc_interrupt_update(s);
748
}
749
750
-static uint64_t omap_rfbi_read(void *opaque, hwaddr addr,
751
- unsigned size)
752
+static uint64_t omap_rfbi_read(void *opaque, hwaddr addr, unsigned size)
753
{
754
- struct omap_dss_s *s = (struct omap_dss_s *) opaque;
755
+ struct omap_dss_s *s = opaque;
756
757
if (size != 4) {
758
return omap_badwidth_read32(opaque, addr);
759
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_rfbi_read(void *opaque, hwaddr addr,
760
static void omap_rfbi_write(void *opaque, hwaddr addr,
761
uint64_t value, unsigned size)
762
{
763
- struct omap_dss_s *s = (struct omap_dss_s *) opaque;
764
+ struct omap_dss_s *s = opaque;
765
766
if (size != 4) {
767
omap_badwidth_write32(opaque, addr, value);
768
diff --git a/hw/display/omap_lcdc.c b/hw/display/omap_lcdc.c
769
index XXXXXXX..XXXXXXX 100644
770
--- a/hw/display/omap_lcdc.c
771
+++ b/hw/display/omap_lcdc.c
772
@@ -XXX,XX +XXX,XX @@ static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
773
774
static void omap_update_display(void *opaque)
775
{
776
- struct omap_lcd_panel_s *omap_lcd = (struct omap_lcd_panel_s *) opaque;
777
+ struct omap_lcd_panel_s *omap_lcd = opaque;
778
DisplaySurface *surface;
779
drawfn draw_line;
780
int size, height, first, last;
781
@@ -XXX,XX +XXX,XX @@ static void omap_lcd_update(struct omap_lcd_panel_s *s) {
782
}
783
}
784
785
-static uint64_t omap_lcdc_read(void *opaque, hwaddr addr,
786
- unsigned size)
787
+static uint64_t omap_lcdc_read(void *opaque, hwaddr addr, unsigned size)
788
{
789
- struct omap_lcd_panel_s *s = (struct omap_lcd_panel_s *) opaque;
790
+ struct omap_lcd_panel_s *s = opaque;
791
792
switch (addr) {
793
case 0x00:    /* LCD_CONTROL */
794
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_lcdc_read(void *opaque, hwaddr addr,
795
static void omap_lcdc_write(void *opaque, hwaddr addr,
796
uint64_t value, unsigned size)
797
{
798
- struct omap_lcd_panel_s *s = (struct omap_lcd_panel_s *) opaque;
799
+ struct omap_lcd_panel_s *s = opaque;
800
801
switch (addr) {
802
case 0x00:    /* LCD_CONTROL */
803
diff --git a/hw/dma/omap_dma.c b/hw/dma/omap_dma.c
804
index XXXXXXX..XXXXXXX 100644
805
--- a/hw/dma/omap_dma.c
806
+++ b/hw/dma/omap_dma.c
807
@@ -XXX,XX +XXX,XX @@ static int omap_dma_sys_read(struct omap_dma_s *s, int offset,
808
return 0;
809
}
810
811
-static uint64_t omap_dma_read(void *opaque, hwaddr addr,
812
- unsigned size)
813
+static uint64_t omap_dma_read(void *opaque, hwaddr addr, unsigned size)
814
{
815
- struct omap_dma_s *s = (struct omap_dma_s *) opaque;
816
+ struct omap_dma_s *s = opaque;
817
int reg, ch;
818
uint16_t ret;
819
820
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_dma_read(void *opaque, hwaddr addr,
821
static void omap_dma_write(void *opaque, hwaddr addr,
822
uint64_t value, unsigned size)
823
{
824
- struct omap_dma_s *s = (struct omap_dma_s *) opaque;
825
+ struct omap_dma_s *s = opaque;
826
int reg, ch;
827
828
if (size != 2) {
829
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps omap_dma_ops = {
830
831
static void omap_dma_request(void *opaque, int drq, int req)
832
{
833
- struct omap_dma_s *s = (struct omap_dma_s *) opaque;
834
+ struct omap_dma_s *s = opaque;
835
/* The request pins are level triggered in QEMU. */
836
if (req) {
837
if (~s->dma->drqbmp & (1ULL << drq)) {
838
@@ -XXX,XX +XXX,XX @@ static void omap_dma_request(void *opaque, int drq, int req)
839
/* XXX: this won't be needed once soc_dma knows about clocks. */
840
static void omap_dma_clk_update(void *opaque, int line, int on)
841
{
842
- struct omap_dma_s *s = (struct omap_dma_s *) opaque;
843
+ struct omap_dma_s *s = opaque;
844
int i;
845
846
s->dma->freq = omap_clk_getrate(s->clk);
847
@@ -XXX,XX +XXX,XX @@ static void omap_dma_interrupts_4_update(struct omap_dma_s *s)
848
static uint64_t omap_dma4_read(void *opaque, hwaddr addr,
849
unsigned size)
850
{
851
- struct omap_dma_s *s = (struct omap_dma_s *) opaque;
852
+ struct omap_dma_s *s = opaque;
853
int irqn = 0, chnum;
854
struct omap_dma_channel_s *ch;
855
856
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_dma4_read(void *opaque, hwaddr addr,
857
static void omap_dma4_write(void *opaque, hwaddr addr,
858
uint64_t value, unsigned size)
859
{
860
- struct omap_dma_s *s = (struct omap_dma_s *) opaque;
861
+ struct omap_dma_s *s = opaque;
862
int chnum, irqn = 0;
863
struct omap_dma_channel_s *ch;
864
865
diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c
866
index XXXXXXX..XXXXXXX 100644
867
--- a/hw/gpio/omap_gpio.c
868
+++ b/hw/gpio/omap_gpio.c
869
@@ -XXX,XX +XXX,XX @@ static void omap_gpio_set(void *opaque, int line, int level)
870
static uint64_t omap_gpio_read(void *opaque, hwaddr addr,
871
unsigned size)
872
{
873
- struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
874
+ struct omap_gpio_s *s = opaque;
875
int offset = addr & OMAP_MPUI_REG_MASK;
876
877
if (size != 2) {
878
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_gpio_read(void *opaque, hwaddr addr,
879
static void omap_gpio_write(void *opaque, hwaddr addr,
880
uint64_t value, unsigned size)
881
{
882
- struct omap_gpio_s *s = (struct omap_gpio_s *) opaque;
883
+ struct omap_gpio_s *s = opaque;
884
int offset = addr & OMAP_MPUI_REG_MASK;
885
uint16_t diff;
886
int ln;
887
@@ -XXX,XX +XXX,XX @@ static void omap2_gpio_module_reset(struct omap2_gpio_s *s)
888
889
static uint32_t omap2_gpio_module_read(void *opaque, hwaddr addr)
890
{
891
- struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
892
+ struct omap2_gpio_s *s = opaque;
893
894
switch (addr) {
895
case 0x00:    /* GPIO_REVISION */
896
@@ -XXX,XX +XXX,XX @@ static uint32_t omap2_gpio_module_read(void *opaque, hwaddr addr)
897
static void omap2_gpio_module_write(void *opaque, hwaddr addr,
898
uint32_t value)
899
{
900
- struct omap2_gpio_s *s = (struct omap2_gpio_s *) opaque;
901
+ struct omap2_gpio_s *s = opaque;
902
uint32_t diff;
903
int ln;
904
905
@@ -XXX,XX +XXX,XX @@ static void omap2_gpif_reset(DeviceState *dev)
906
s->gpo = 0;
907
}
908
909
-static uint64_t omap2_gpif_top_read(void *opaque, hwaddr addr,
910
- unsigned size)
911
+static uint64_t omap2_gpif_top_read(void *opaque, hwaddr addr, unsigned size)
912
{
913
- struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
914
+ struct omap2_gpif_s *s = opaque;
915
916
switch (addr) {
917
case 0x00:    /* IPGENERICOCPSPL_REVISION */
918
@@ -XXX,XX +XXX,XX @@ static uint64_t omap2_gpif_top_read(void *opaque, hwaddr addr,
919
static void omap2_gpif_top_write(void *opaque, hwaddr addr,
920
uint64_t value, unsigned size)
921
{
922
- struct omap2_gpif_s *s = (struct omap2_gpif_s *) opaque;
923
+ struct omap2_gpif_s *s = opaque;
924
925
switch (addr) {
926
case 0x00:    /* IPGENERICOCPSPL_REVISION */
927
diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c
928
index XXXXXXX..XXXXXXX 100644
929
--- a/hw/intc/omap_intc.c
930
+++ b/hw/intc/omap_intc.c
931
@@ -XXX,XX +XXX,XX @@ static inline void omap_inth_update(struct omap_intr_handler_s *s, int is_fiq)
932
933
static void omap_set_intr(void *opaque, int irq, int req)
934
{
935
- struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
936
+ struct omap_intr_handler_s *ih = opaque;
937
uint32_t rise;
938
939
struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
940
@@ -XXX,XX +XXX,XX @@ static void omap_set_intr(void *opaque, int irq, int req)
941
/* Simplified version with no edge detection */
942
static void omap_set_intr_noedge(void *opaque, int irq, int req)
943
{
944
- struct omap_intr_handler_s *ih = (struct omap_intr_handler_s *) opaque;
945
+ struct omap_intr_handler_s *ih = opaque;
946
uint32_t rise;
947
948
struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
949
@@ -XXX,XX +XXX,XX @@ static void omap_set_intr_noedge(void *opaque, int irq, int req)
950
static uint64_t omap_inth_read(void *opaque, hwaddr addr,
951
unsigned size)
952
{
953
- struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
954
+ struct omap_intr_handler_s *s = opaque;
955
int i, offset = addr;
956
int bank_no = offset >> 8;
957
int line_no;
958
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_inth_read(void *opaque, hwaddr addr,
959
static void omap_inth_write(void *opaque, hwaddr addr,
960
uint64_t value, unsigned size)
961
{
962
- struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
963
+ struct omap_intr_handler_s *s = opaque;
964
int i, offset = addr;
965
int bank_no = offset >> 8;
966
struct omap_intr_handler_bank_s *bank = &s->bank[bank_no];
967
@@ -XXX,XX +XXX,XX @@ static const TypeInfo omap_intc_info = {
968
static uint64_t omap2_inth_read(void *opaque, hwaddr addr,
969
unsigned size)
970
{
971
- struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
972
+ struct omap_intr_handler_s *s = opaque;
973
int offset = addr;
974
int bank_no, line_no;
975
struct omap_intr_handler_bank_s *bank = NULL;
976
@@ -XXX,XX +XXX,XX @@ static uint64_t omap2_inth_read(void *opaque, hwaddr addr,
977
static void omap2_inth_write(void *opaque, hwaddr addr,
978
uint64_t value, unsigned size)
979
{
980
- struct omap_intr_handler_s *s = (struct omap_intr_handler_s *) opaque;
981
+ struct omap_intr_handler_s *s = opaque;
982
int offset = addr;
983
int bank_no, line_no;
984
struct omap_intr_handler_bank_s *bank = NULL;
985
diff --git a/hw/misc/omap_gpmc.c b/hw/misc/omap_gpmc.c
986
index XXXXXXX..XXXXXXX 100644
987
--- a/hw/misc/omap_gpmc.c
988
+++ b/hw/misc/omap_gpmc.c
989
@@ -XXX,XX +XXX,XX @@ static void omap_gpmc_dma_update(struct omap_gpmc_s *s, int value)
990
static uint64_t omap_nand_read(void *opaque, hwaddr addr,
991
unsigned size)
992
{
993
- struct omap_gpmc_cs_file_s *f = (struct omap_gpmc_cs_file_s *)opaque;
994
+ struct omap_gpmc_cs_file_s *f = opaque;
995
uint64_t v;
996
nand_setpins(f->dev, 0, 0, 0, 1, 0);
997
switch (omap_gpmc_devsize(f)) {
998
@@ -XXX,XX +XXX,XX @@ static void omap_nand_setio(DeviceState *dev, uint64_t value,
999
static void omap_nand_write(void *opaque, hwaddr addr,
1000
uint64_t value, unsigned size)
1001
{
1002
- struct omap_gpmc_cs_file_s *f = (struct omap_gpmc_cs_file_s *)opaque;
1003
+ struct omap_gpmc_cs_file_s *f = opaque;
1004
nand_setpins(f->dev, 0, 0, 0, 1, 0);
1005
omap_nand_setio(f->dev, value, omap_gpmc_devsize(f), size);
1006
}
1007
@@ -XXX,XX +XXX,XX @@ static void fill_prefetch_fifo(struct omap_gpmc_s *s)
1008
static uint64_t omap_gpmc_prefetch_read(void *opaque, hwaddr addr,
1009
unsigned size)
1010
{
1011
- struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque;
1012
+ struct omap_gpmc_s *s = opaque;
1013
uint32_t data;
1014
if (s->prefetch.config1 & 1) {
1015
/* The TRM doesn't define the behaviour if you read from the
1016
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_gpmc_prefetch_read(void *opaque, hwaddr addr,
1017
static void omap_gpmc_prefetch_write(void *opaque, hwaddr addr,
1018
uint64_t value, unsigned size)
1019
{
1020
- struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque;
1021
+ struct omap_gpmc_s *s = opaque;
1022
int cs = prefetch_cs(s->prefetch.config1);
1023
if ((s->prefetch.config1 & 1) == 0) {
1024
/* The TRM doesn't define the behaviour of writing to the
1025
@@ -XXX,XX +XXX,XX @@ static int gpmc_wordaccess_only(hwaddr addr)
1026
static uint64_t omap_gpmc_read(void *opaque, hwaddr addr,
1027
unsigned size)
1028
{
1029
- struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque;
1030
+ struct omap_gpmc_s *s = opaque;
1031
int cs;
1032
struct omap_gpmc_cs_file_s *f;
1033
1034
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_gpmc_read(void *opaque, hwaddr addr,
1035
static void omap_gpmc_write(void *opaque, hwaddr addr,
1036
uint64_t value, unsigned size)
1037
{
1038
- struct omap_gpmc_s *s = (struct omap_gpmc_s *) opaque;
1039
+ struct omap_gpmc_s *s = opaque;
1040
int cs;
1041
struct omap_gpmc_cs_file_s *f;
1042
1043
diff --git a/hw/misc/omap_l4.c b/hw/misc/omap_l4.c
1044
index XXXXXXX..XXXXXXX 100644
1045
--- a/hw/misc/omap_l4.c
1046
+++ b/hw/misc/omap_l4.c
1047
@@ -XXX,XX +XXX,XX @@ hwaddr omap_l4_region_size(struct omap_target_agent_s *ta,
1048
return ta->start[region].size;
1049
}
1050
1051
-static uint64_t omap_l4ta_read(void *opaque, hwaddr addr,
1052
- unsigned size)
1053
+static uint64_t omap_l4ta_read(void *opaque, hwaddr addr, unsigned size)
1054
{
1055
- struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
1056
+ struct omap_target_agent_s *s = opaque;
1057
1058
if (size != 2) {
1059
return omap_badwidth_read16(opaque, addr);
1060
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_l4ta_read(void *opaque, hwaddr addr,
1061
static void omap_l4ta_write(void *opaque, hwaddr addr,
1062
uint64_t value, unsigned size)
1063
{
1064
- struct omap_target_agent_s *s = (struct omap_target_agent_s *) opaque;
1065
+ struct omap_target_agent_s *s = opaque;
1066
1067
if (size != 4) {
1068
omap_badwidth_write32(opaque, addr, value);
1069
diff --git a/hw/misc/omap_sdrc.c b/hw/misc/omap_sdrc.c
1070
index XXXXXXX..XXXXXXX 100644
1071
--- a/hw/misc/omap_sdrc.c
1072
+++ b/hw/misc/omap_sdrc.c
1073
@@ -XXX,XX +XXX,XX @@ void omap_sdrc_reset(struct omap_sdrc_s *s)
1074
s->config = 0x10;
1075
}
1076
1077
-static uint64_t omap_sdrc_read(void *opaque, hwaddr addr,
1078
- unsigned size)
1079
+static uint64_t omap_sdrc_read(void *opaque, hwaddr addr, unsigned size)
1080
{
1081
- struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque;
1082
+ struct omap_sdrc_s *s = opaque;
1083
1084
if (size != 4) {
1085
return omap_badwidth_read32(opaque, addr);
1086
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_sdrc_read(void *opaque, hwaddr addr,
1087
static void omap_sdrc_write(void *opaque, hwaddr addr,
1088
uint64_t value, unsigned size)
1089
{
1090
- struct omap_sdrc_s *s = (struct omap_sdrc_s *) opaque;
1091
+ struct omap_sdrc_s *s = opaque;
1092
1093
if (size != 4) {
1094
omap_badwidth_write32(opaque, addr, value);
1095
diff --git a/hw/misc/omap_tap.c b/hw/misc/omap_tap.c
1096
index XXXXXXX..XXXXXXX 100644
1097
--- a/hw/misc/omap_tap.c
1098
+++ b/hw/misc/omap_tap.c
1099
@@ -XXX,XX +XXX,XX @@
1100
#include "hw/arm/omap.h"
1101
1102
/* TEST-Chip-level TAP */
1103
-static uint64_t omap_tap_read(void *opaque, hwaddr addr,
1104
- unsigned size)
1105
+static uint64_t omap_tap_read(void *opaque, hwaddr addr, unsigned size)
1106
{
1107
- struct omap_mpu_state_s *s = (struct omap_mpu_state_s *) opaque;
1108
+ struct omap_mpu_state_s *s = opaque;
1109
1110
if (size != 4) {
1111
return omap_badwidth_read32(opaque, addr);
1112
diff --git a/hw/sd/omap_mmc.c b/hw/sd/omap_mmc.c
1113
index XXXXXXX..XXXXXXX 100644
1114
--- a/hw/sd/omap_mmc.c
1115
+++ b/hw/sd/omap_mmc.c
1116
@@ -XXX,XX +XXX,XX @@ void omap_mmc_reset(struct omap_mmc_s *host)
1117
device_cold_reset(DEVICE(host->card));
1118
}
1119
1120
-static uint64_t omap_mmc_read(void *opaque, hwaddr offset,
1121
- unsigned size)
1122
+static uint64_t omap_mmc_read(void *opaque, hwaddr offset, unsigned size)
1123
{
1124
uint16_t i;
1125
- struct omap_mmc_s *s = (struct omap_mmc_s *) opaque;
1126
+ struct omap_mmc_s *s = opaque;
1127
1128
if (size != 2) {
1129
return omap_badwidth_read16(opaque, offset);
1130
@@ -XXX,XX +XXX,XX @@ static void omap_mmc_write(void *opaque, hwaddr offset,
1131
uint64_t value, unsigned size)
1132
{
1133
int i;
1134
- struct omap_mmc_s *s = (struct omap_mmc_s *) opaque;
1135
+ struct omap_mmc_s *s = opaque;
1136
1137
if (size != 2) {
1138
omap_badwidth_write16(opaque, offset, value);
1139
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps omap_mmc_ops = {
1140
1141
static void omap_mmc_cover_cb(void *opaque, int line, int level)
1142
{
1143
- struct omap_mmc_s *host = (struct omap_mmc_s *) opaque;
1144
+ struct omap_mmc_s *host = opaque;
1145
1146
if (!host->cdet_state && level) {
1147
host->status |= 0x0002;
1148
diff --git a/hw/ssi/omap_spi.c b/hw/ssi/omap_spi.c
1149
index XXXXXXX..XXXXXXX 100644
1150
--- a/hw/ssi/omap_spi.c
1151
+++ b/hw/ssi/omap_spi.c
1152
@@ -XXX,XX +XXX,XX @@ void omap_mcspi_reset(struct omap_mcspi_s *s)
1153
omap_mcspi_interrupt_update(s);
1154
}
1155
1156
-static uint64_t omap_mcspi_read(void *opaque, hwaddr addr,
1157
- unsigned size)
1158
+static uint64_t omap_mcspi_read(void *opaque, hwaddr addr, unsigned size)
1159
{
1160
- struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;
1161
+ struct omap_mcspi_s *s = opaque;
1162
int ch = 0;
1163
uint32_t ret;
1164
1165
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_mcspi_read(void *opaque, hwaddr addr,
1166
static void omap_mcspi_write(void *opaque, hwaddr addr,
1167
uint64_t value, unsigned size)
1168
{
1169
- struct omap_mcspi_s *s = (struct omap_mcspi_s *) opaque;
1170
+ struct omap_mcspi_s *s = opaque;
1171
int ch = 0;
1172
1173
if (size != 4) {
1174
diff --git a/hw/timer/omap_gptimer.c b/hw/timer/omap_gptimer.c
1175
index XXXXXXX..XXXXXXX 100644
1176
--- a/hw/timer/omap_gptimer.c
1177
+++ b/hw/timer/omap_gptimer.c
1178
@@ -XXX,XX +XXX,XX @@ static inline void omap_gp_timer_trigger(struct omap_gp_timer_s *timer)
1179
1180
static void omap_gp_timer_tick(void *opaque)
1181
{
1182
- struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
1183
+ struct omap_gp_timer_s *timer = opaque;
1184
1185
if (!timer->ar) {
1186
timer->st = 0;
1187
@@ -XXX,XX +XXX,XX @@ static void omap_gp_timer_tick(void *opaque)
1188
1189
static void omap_gp_timer_match(void *opaque)
1190
{
1191
- struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
1192
+ struct omap_gp_timer_s *timer = opaque;
1193
1194
if (timer->trigger == gpt_trigger_both)
1195
omap_gp_timer_trigger(timer);
1196
@@ -XXX,XX +XXX,XX @@ static void omap_gp_timer_match(void *opaque)
1197
1198
static void omap_gp_timer_input(void *opaque, int line, int on)
1199
{
1200
- struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
1201
+ struct omap_gp_timer_s *s = opaque;
1202
int trigger;
1203
1204
switch (s->capture) {
1205
@@ -XXX,XX +XXX,XX @@ static void omap_gp_timer_input(void *opaque, int line, int on)
1206
1207
static void omap_gp_timer_clk_update(void *opaque, int line, int on)
1208
{
1209
- struct omap_gp_timer_s *timer = (struct omap_gp_timer_s *) opaque;
1210
+ struct omap_gp_timer_s *timer = opaque;
1211
1212
omap_gp_timer_sync(timer);
1213
timer->rate = on ? omap_clk_getrate(timer->clk) : 0;
1214
@@ -XXX,XX +XXX,XX @@ void omap_gp_timer_reset(struct omap_gp_timer_s *s)
1215
1216
static uint32_t omap_gp_timer_readw(void *opaque, hwaddr addr)
1217
{
1218
- struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
1219
+ struct omap_gp_timer_s *s = opaque;
1220
1221
switch (addr) {
1222
case 0x00:    /* TIDR */
1223
@@ -XXX,XX +XXX,XX @@ static uint32_t omap_gp_timer_readw(void *opaque, hwaddr addr)
1224
1225
static uint32_t omap_gp_timer_readh(void *opaque, hwaddr addr)
1226
{
1227
- struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
1228
+ struct omap_gp_timer_s *s = opaque;
1229
uint32_t ret;
1230
1231
if (addr & 2)
1232
@@ -XXX,XX +XXX,XX @@ static uint32_t omap_gp_timer_readh(void *opaque, hwaddr addr)
1233
}
1234
}
1235
1236
-static void omap_gp_timer_write(void *opaque, hwaddr addr,
1237
- uint32_t value)
1238
+static void omap_gp_timer_write(void *opaque, hwaddr addr, uint32_t value)
1239
{
1240
- struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
1241
+ struct omap_gp_timer_s *s = opaque;
1242
1243
switch (addr) {
1244
case 0x00:    /* TIDR */
1245
@@ -XXX,XX +XXX,XX @@ static void omap_gp_timer_write(void *opaque, hwaddr addr,
1246
}
1247
}
1248
1249
-static void omap_gp_timer_writeh(void *opaque, hwaddr addr,
1250
- uint32_t value)
1251
+static void omap_gp_timer_writeh(void *opaque, hwaddr addr, uint32_t value)
1252
{
1253
- struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
1254
+ struct omap_gp_timer_s *s = opaque;
1255
1256
if (addr & 2)
1257
omap_gp_timer_write(opaque, addr, (value << 16) | s->writeh);
1258
diff --git a/hw/timer/omap_synctimer.c b/hw/timer/omap_synctimer.c
1259
index XXXXXXX..XXXXXXX 100644
1260
--- a/hw/timer/omap_synctimer.c
1261
+++ b/hw/timer/omap_synctimer.c
1262
@@ -XXX,XX +XXX,XX @@ void omap_synctimer_reset(struct omap_synctimer_s *s)
1263
1264
static uint32_t omap_synctimer_readw(void *opaque, hwaddr addr)
1265
{
1266
- struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
1267
+ struct omap_synctimer_s *s = opaque;
1268
1269
switch (addr) {
1270
case 0x00:    /* 32KSYNCNT_REV */
1271
@@ -XXX,XX +XXX,XX @@ static uint32_t omap_synctimer_readw(void *opaque, hwaddr addr)
1272
1273
static uint32_t omap_synctimer_readh(void *opaque, hwaddr addr)
1274
{
1275
- struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
1276
+ struct omap_synctimer_s *s = opaque;
1277
uint32_t ret;
1278
1279
if (addr & 2)
26
--
1280
--
27
2.20.1
1281
2.34.1
28
1282
29
1283
diff view generated by jsdifflib
1
Implement the MVE VCTP insn, which sets the VPR.P0 predicate bits so
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
as to predicate any element at index Rn or greater is predicated. As
3
with VPNOT, this insn itself is predicable and subject to beatwise
4
execution.
5
2
6
The calculation of the mask is the same as is used to determine
3
Following docs/devel/style.rst guidelines, rename omap_gpif_s ->
7
ltpmask in mve_element_mask(), but we precalculate masklen in
4
Omap1GpioState. This also remove a use of 'struct' in the
8
generated code to avoid having to have 4 helpers specialized by size.
5
DECLARE_INSTANCE_CHECKER() macro call.
9
6
10
We put the decode line in with the low-overhead-loop insns in
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
t32.decode because it's logically part of that collection of insn
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
patterns, even though it is an MVE only insn.
9
Message-id: 20230109140306.23161-5-philmd@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/arm/omap.h | 6 +++---
13
hw/gpio/omap_gpio.c | 16 ++++++++--------
14
2 files changed, 11 insertions(+), 11 deletions(-)
13
15
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
---
17
target/arm/helper-mve.h | 2 ++
18
target/arm/translate-a32.h | 1 +
19
target/arm/t32.decode | 1 +
20
target/arm/mve_helper.c | 20 ++++++++++++++++++++
21
target/arm/translate-mve.c | 2 +-
22
target/arm/translate.c | 33 +++++++++++++++++++++++++++++++++
23
6 files changed, 58 insertions(+), 1 deletion(-)
24
25
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
26
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/helper-mve.h
18
--- a/include/hw/arm/omap.h
28
+++ b/target/arm/helper-mve.h
19
+++ b/include/hw/arm/omap.h
29
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_veor, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
@@ -XXX,XX +XXX,XX @@ void omap_i2c_set_fclk(OMAPI2CState *i2c, omap_clk clk);
30
DEF_HELPER_FLAGS_4(mve_vpsel, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
31
DEF_HELPER_FLAGS_1(mve_vpnot, TCG_CALL_NO_WG, void, env)
22
/* omap_gpio.c */
32
23
#define TYPE_OMAP1_GPIO "omap-gpio"
33
+DEF_HELPER_FLAGS_2(mve_vctp, TCG_CALL_NO_WG, void, env, i32)
24
-DECLARE_INSTANCE_CHECKER(struct omap_gpif_s, OMAP1_GPIO,
34
+
25
+typedef struct Omap1GpioState Omap1GpioState;
35
DEF_HELPER_FLAGS_4(mve_vaddb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
+DECLARE_INSTANCE_CHECKER(Omap1GpioState, OMAP1_GPIO,
36
DEF_HELPER_FLAGS_4(mve_vaddh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
TYPE_OMAP1_GPIO)
37
DEF_HELPER_FLAGS_4(mve_vaddw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
38
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
29
#define TYPE_OMAP2_GPIO "omap2-gpio"
30
DECLARE_INSTANCE_CHECKER(struct omap2_gpif_s, OMAP2_GPIO,
31
TYPE_OMAP2_GPIO)
32
33
-typedef struct omap_gpif_s omap_gpif;
34
typedef struct omap2_gpif_s omap2_gpif;
35
36
/* TODO: clock framework (see above) */
37
-void omap_gpio_set_clk(omap_gpif *gpio, omap_clk clk);
38
+void omap_gpio_set_clk(Omap1GpioState *gpio, omap_clk clk);
39
40
void omap2_gpio_set_iclk(omap2_gpif *gpio, omap_clk clk);
41
void omap2_gpio_set_fclk(omap2_gpif *gpio, uint8_t i, omap_clk clk);
42
diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c
39
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/translate-a32.h
44
--- a/hw/gpio/omap_gpio.c
41
+++ b/target/arm/translate-a32.h
45
+++ b/hw/gpio/omap_gpio.c
42
@@ -XXX,XX +XXX,XX @@ long neon_element_offset(int reg, int element, MemOp memop);
46
@@ -XXX,XX +XXX,XX @@ struct omap_gpio_s {
43
void gen_rev16(TCGv_i32 dest, TCGv_i32 var);
47
uint16_t pins;
44
void clear_eci_state(DisasContext *s);
48
};
45
bool mve_eci_check(DisasContext *s);
49
46
+void mve_update_eci(DisasContext *s);
50
-struct omap_gpif_s {
47
void mve_update_and_store_eci(DisasContext *s);
51
+struct Omap1GpioState {
48
bool mve_skip_vmov(DisasContext *s, int vn, int index, int size);
52
SysBusDevice parent_obj;
49
53
50
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
54
MemoryRegion iomem;
51
index XXXXXXX..XXXXXXX 100644
55
@@ -XXX,XX +XXX,XX @@ struct omap_gpif_s {
52
--- a/target/arm/t32.decode
56
/* General-Purpose I/O of OMAP1 */
53
+++ b/target/arm/t32.decode
57
static void omap_gpio_set(void *opaque, int line, int level)
54
@@ -XXX,XX +XXX,XX @@ BL 1111 0. .......... 11.1 ............ @branch24
58
{
55
# This is DLSTP
59
- struct omap_gpif_s *p = opaque;
56
DLS 1111 0 0000 0 size:2 rn:4 1110 0000 0000 0001
60
+ Omap1GpioState *p = opaque;
57
}
61
struct omap_gpio_s *s = &p->omap1;
58
+ VCTP 1111 0 0000 0 size:2 rn:4 1110 1000 0000 0001
62
uint16_t prev = s->inputs;
59
]
63
64
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps omap2_gpio_module_ops = {
65
66
static void omap_gpif_reset(DeviceState *dev)
67
{
68
- struct omap_gpif_s *s = OMAP1_GPIO(dev);
69
+ Omap1GpioState *s = OMAP1_GPIO(dev);
70
71
omap_gpio_reset(&s->omap1);
60
}
72
}
61
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
73
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps omap2_gpif_top_ops = {
62
index XXXXXXX..XXXXXXX 100644
74
static void omap_gpio_init(Object *obj)
63
--- a/target/arm/mve_helper.c
75
{
64
+++ b/target/arm/mve_helper.c
76
DeviceState *dev = DEVICE(obj);
65
@@ -XXX,XX +XXX,XX @@ void HELPER(mve_vpnot)(CPUARMState *env)
77
- struct omap_gpif_s *s = OMAP1_GPIO(obj);
66
mve_advance_vpt(env);
78
+ Omap1GpioState *s = OMAP1_GPIO(obj);
67
}
79
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
68
80
69
+/*
81
qdev_init_gpio_in(dev, omap_gpio_set, 16);
70
+ * VCTP: P0 unexecuted bits unchanged, predicated bits zeroed,
82
@@ -XXX,XX +XXX,XX @@ static void omap_gpio_init(Object *obj)
71
+ * otherwise set according to value of Rn. The calculation of
83
72
+ * newmask here works in the same way as the calculation of the
84
static void omap_gpio_realize(DeviceState *dev, Error **errp)
73
+ * ltpmask in mve_element_mask(), but we have pre-calculated
85
{
74
+ * the masklen in the generated code.
86
- struct omap_gpif_s *s = OMAP1_GPIO(dev);
75
+ */
87
+ Omap1GpioState *s = OMAP1_GPIO(dev);
76
+void HELPER(mve_vctp)(CPUARMState *env, uint32_t masklen)
88
77
+{
89
if (!s->clk) {
78
+ uint16_t mask = mve_element_mask(env);
90
error_setg(errp, "omap-gpio: clk not connected");
79
+ uint16_t eci_mask = mve_eci_mask(env);
91
@@ -XXX,XX +XXX,XX @@ static void omap2_gpio_realize(DeviceState *dev, Error **errp)
80
+ uint16_t newmask;
81
+
82
+ assert(masklen <= 16);
83
+ newmask = masklen ? MAKE_64BIT_MASK(0, masklen) : 0;
84
+ newmask &= mask;
85
+ env->v7m.vpr = (env->v7m.vpr & ~(uint32_t)eci_mask) | (newmask & eci_mask);
86
+ mve_advance_vpt(env);
87
+}
88
+
89
#define DO_1OP_SAT(OP, ESIZE, TYPE, FN) \
90
void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm) \
91
{ \
92
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
93
index XXXXXXX..XXXXXXX 100644
94
--- a/target/arm/translate-mve.c
95
+++ b/target/arm/translate-mve.c
96
@@ -XXX,XX +XXX,XX @@ bool mve_eci_check(DisasContext *s)
97
}
92
}
98
}
93
}
99
94
100
-static void mve_update_eci(DisasContext *s)
95
-void omap_gpio_set_clk(omap_gpif *gpio, omap_clk clk)
101
+void mve_update_eci(DisasContext *s)
96
+void omap_gpio_set_clk(Omap1GpioState *gpio, omap_clk clk)
102
{
97
{
103
/*
98
gpio->clk = clk;
104
* The helper function will always update the CPUState field,
105
diff --git a/target/arm/translate.c b/target/arm/translate.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/target/arm/translate.c
108
+++ b/target/arm/translate.c
109
@@ -XXX,XX +XXX,XX @@ static bool trans_LCTP(DisasContext *s, arg_LCTP *a)
110
return true;
111
}
99
}
112
100
113
+static bool trans_VCTP(DisasContext *s, arg_VCTP *a)
101
static Property omap_gpio_properties[] = {
114
+{
102
- DEFINE_PROP_INT32("mpu_model", struct omap_gpif_s, mpu_model, 0),
115
+ /*
103
+ DEFINE_PROP_INT32("mpu_model", Omap1GpioState, mpu_model, 0),
116
+ * M-profile Create Vector Tail Predicate. This insn is itself
104
DEFINE_PROP_END_OF_LIST(),
117
+ * predicated and is subject to beatwise execution.
105
};
118
+ */
106
119
+ TCGv_i32 rn_shifted, masklen;
107
@@ -XXX,XX +XXX,XX @@ static void omap_gpio_class_init(ObjectClass *klass, void *data)
120
+
108
static const TypeInfo omap_gpio_info = {
121
+ if (!dc_isar_feature(aa32_mve, s) || a->rn == 13 || a->rn == 15) {
109
.name = TYPE_OMAP1_GPIO,
122
+ return false;
110
.parent = TYPE_SYS_BUS_DEVICE,
123
+ }
111
- .instance_size = sizeof(struct omap_gpif_s),
124
+
112
+ .instance_size = sizeof(Omap1GpioState),
125
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
113
.instance_init = omap_gpio_init,
126
+ return true;
114
.class_init = omap_gpio_class_init,
127
+ }
115
};
128
+
129
+ /*
130
+ * We pre-calculate the mask length here to avoid having
131
+ * to have multiple helpers specialized for size.
132
+ * We pass the helper "rn <= (1 << (4 - size)) ? (rn << size) : 16".
133
+ */
134
+ rn_shifted = tcg_temp_new_i32();
135
+ masklen = load_reg(s, a->rn);
136
+ tcg_gen_shli_i32(rn_shifted, masklen, a->size);
137
+ tcg_gen_movcond_i32(TCG_COND_LEU, masklen,
138
+ masklen, tcg_constant_i32(1 << (4 - a->size)),
139
+ rn_shifted, tcg_constant_i32(16));
140
+ gen_helper_mve_vctp(cpu_env, masklen);
141
+ tcg_temp_free_i32(masklen);
142
+ tcg_temp_free_i32(rn_shifted);
143
+ mve_update_eci(s);
144
+ return true;
145
+}
146
147
static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
148
{
149
--
116
--
150
2.20.1
117
2.34.1
151
118
152
119
diff view generated by jsdifflib
1
From: "Wen, Jianxian" <Jianxian.Wen@verisilicon.com>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
Add property memory region which can connect with IOMMU region to support SMMU translate.
3
Following docs/devel/style.rst guidelines, rename omap2_gpif_s ->
4
Omap2GpioState. This also remove a use of 'struct' in the
5
DECLARE_INSTANCE_CHECKER() macro call.
4
6
5
Signed-off-by: Jianxian Wen <jianxian.wen@verisilicon.com>
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 4C23C17B8E87E74E906A25A3254A03F4FA1FEC31@SHASXM03.verisilicon.com
9
Message-id: 20230109140306.23161-6-philmd@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
11
---
10
hw/arm/exynos4210.c | 3 +++
12
include/hw/arm/omap.h | 9 ++++-----
11
hw/arm/xilinx_zynq.c | 3 +++
13
hw/gpio/omap_gpio.c | 20 ++++++++++----------
12
hw/dma/pl330.c | 26 ++++++++++++++++++++++----
14
2 files changed, 14 insertions(+), 15 deletions(-)
13
3 files changed, 28 insertions(+), 4 deletions(-)
14
15
15
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
16
diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/exynos4210.c
18
--- a/include/hw/arm/omap.h
18
+++ b/hw/arm/exynos4210.c
19
+++ b/include/hw/arm/omap.h
19
@@ -XXX,XX +XXX,XX @@ static DeviceState *pl330_create(uint32_t base, qemu_or_irq *orgate,
20
@@ -XXX,XX +XXX,XX @@ DECLARE_INSTANCE_CHECKER(Omap1GpioState, OMAP1_GPIO,
21
TYPE_OMAP1_GPIO)
22
23
#define TYPE_OMAP2_GPIO "omap2-gpio"
24
-DECLARE_INSTANCE_CHECKER(struct omap2_gpif_s, OMAP2_GPIO,
25
+typedef struct Omap2GpioState Omap2GpioState;
26
+DECLARE_INSTANCE_CHECKER(Omap2GpioState, OMAP2_GPIO,
27
TYPE_OMAP2_GPIO)
28
29
-typedef struct omap2_gpif_s omap2_gpif;
30
-
31
/* TODO: clock framework (see above) */
32
void omap_gpio_set_clk(Omap1GpioState *gpio, omap_clk clk);
33
34
-void omap2_gpio_set_iclk(omap2_gpif *gpio, omap_clk clk);
35
-void omap2_gpio_set_fclk(omap2_gpif *gpio, uint8_t i, omap_clk clk);
36
+void omap2_gpio_set_iclk(Omap2GpioState *gpio, omap_clk clk);
37
+void omap2_gpio_set_fclk(Omap2GpioState *gpio, uint8_t i, omap_clk clk);
38
39
/* OMAP2 l4 Interconnect */
40
struct omap_l4_s;
41
diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c
42
index XXXXXXX..XXXXXXX 100644
43
--- a/hw/gpio/omap_gpio.c
44
+++ b/hw/gpio/omap_gpio.c
45
@@ -XXX,XX +XXX,XX @@ struct omap2_gpio_s {
46
uint8_t delay;
47
};
48
49
-struct omap2_gpif_s {
50
+struct Omap2GpioState {
51
SysBusDevice parent_obj;
52
53
MemoryRegion iomem;
54
@@ -XXX,XX +XXX,XX @@ static inline void omap2_gpio_module_int(struct omap2_gpio_s *s, int line)
55
56
static void omap2_gpio_set(void *opaque, int line, int level)
57
{
58
- struct omap2_gpif_s *p = opaque;
59
+ Omap2GpioState *p = opaque;
60
struct omap2_gpio_s *s = &p->modules[line >> 5];
61
62
line &= 31;
63
@@ -XXX,XX +XXX,XX @@ static void omap_gpif_reset(DeviceState *dev)
64
65
static void omap2_gpif_reset(DeviceState *dev)
66
{
67
- struct omap2_gpif_s *s = OMAP2_GPIO(dev);
68
+ Omap2GpioState *s = OMAP2_GPIO(dev);
20
int i;
69
int i;
21
70
22
dev = qdev_new("pl330");
71
for (i = 0; i < s->modulecount; i++) {
23
+ object_property_set_link(OBJECT(dev), "memory",
72
@@ -XXX,XX +XXX,XX @@ static void omap2_gpif_reset(DeviceState *dev)
24
+ OBJECT(get_system_memory()),
73
25
+ &error_fatal);
74
static uint64_t omap2_gpif_top_read(void *opaque, hwaddr addr, unsigned size)
26
qdev_prop_set_uint8(dev, "num_events", nevents);
75
{
27
qdev_prop_set_uint8(dev, "num_chnls", 8);
76
- struct omap2_gpif_s *s = opaque;
28
qdev_prop_set_uint8(dev, "num_periph_req", nreq);
77
+ Omap2GpioState *s = opaque;
29
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
78
30
index XXXXXXX..XXXXXXX 100644
79
switch (addr) {
31
--- a/hw/arm/xilinx_zynq.c
80
case 0x00:    /* IPGENERICOCPSPL_REVISION */
32
+++ b/hw/arm/xilinx_zynq.c
81
@@ -XXX,XX +XXX,XX @@ static uint64_t omap2_gpif_top_read(void *opaque, hwaddr addr, unsigned size)
33
@@ -XXX,XX +XXX,XX @@ static void zynq_init(MachineState *machine)
82
static void omap2_gpif_top_write(void *opaque, hwaddr addr,
34
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[39-IRQ_OFFSET]);
83
uint64_t value, unsigned size)
35
84
{
36
dev = qdev_new("pl330");
85
- struct omap2_gpif_s *s = opaque;
37
+ object_property_set_link(OBJECT(dev), "memory",
86
+ Omap2GpioState *s = opaque;
38
+ OBJECT(address_space_mem),
87
39
+ &error_fatal);
88
switch (addr) {
40
qdev_prop_set_uint8(dev, "num_chnls", 8);
89
case 0x00:    /* IPGENERICOCPSPL_REVISION */
41
qdev_prop_set_uint8(dev, "num_periph_req", 4);
90
@@ -XXX,XX +XXX,XX @@ static void omap_gpio_realize(DeviceState *dev, Error **errp)
42
qdev_prop_set_uint8(dev, "num_events", 16);
91
43
diff --git a/hw/dma/pl330.c b/hw/dma/pl330.c
92
static void omap2_gpio_realize(DeviceState *dev, Error **errp)
44
index XXXXXXX..XXXXXXX 100644
93
{
45
--- a/hw/dma/pl330.c
94
- struct omap2_gpif_s *s = OMAP2_GPIO(dev);
46
+++ b/hw/dma/pl330.c
95
+ Omap2GpioState *s = OMAP2_GPIO(dev);
47
@@ -XXX,XX +XXX,XX @@ struct PL330State {
96
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
48
uint8_t num_faulting;
97
int i;
49
uint8_t periph_busy[PL330_PERIPH_NUM];
98
50
99
@@ -XXX,XX +XXX,XX @@ static const TypeInfo omap_gpio_info = {
51
+ /* Memory region that DMA operation access */
100
.class_init = omap_gpio_class_init,
52
+ MemoryRegion *mem_mr;
53
+ AddressSpace *mem_as;
54
};
101
};
55
102
56
#define TYPE_PL330 "pl330"
103
-void omap2_gpio_set_iclk(omap2_gpif *gpio, omap_clk clk)
57
@@ -XXX,XX +XXX,XX @@ static inline const PL330InsnDesc *pl330_fetch_insn(PL330Chan *ch)
104
+void omap2_gpio_set_iclk(Omap2GpioState *gpio, omap_clk clk)
58
uint8_t opcode;
105
{
59
int i;
106
gpio->iclk = clk;
60
61
- dma_memory_read(&address_space_memory, ch->pc, &opcode, 1);
62
+ dma_memory_read(ch->parent->mem_as, ch->pc, &opcode, 1);
63
for (i = 0; insn_desc[i].size; i++) {
64
if ((opcode & insn_desc[i].opmask) == insn_desc[i].opcode) {
65
return &insn_desc[i];
66
@@ -XXX,XX +XXX,XX @@ static inline void pl330_exec_insn(PL330Chan *ch, const PL330InsnDesc *insn)
67
uint8_t buf[PL330_INSN_MAXSIZE];
68
69
assert(insn->size <= PL330_INSN_MAXSIZE);
70
- dma_memory_read(&address_space_memory, ch->pc, buf, insn->size);
71
+ dma_memory_read(ch->parent->mem_as, ch->pc, buf, insn->size);
72
insn->exec(ch, buf[0], &buf[1], insn->size - 1);
73
}
107
}
74
108
75
@@ -XXX,XX +XXX,XX @@ static int pl330_exec_cycle(PL330Chan *channel)
109
-void omap2_gpio_set_fclk(omap2_gpif *gpio, uint8_t i, omap_clk clk)
76
if (q != NULL && q->len <= pl330_fifo_num_free(&s->fifo)) {
110
+void omap2_gpio_set_fclk(Omap2GpioState *gpio, uint8_t i, omap_clk clk)
77
int len = q->len - (q->addr & (q->len - 1));
111
{
78
112
assert(i <= 5);
79
- dma_memory_read(&address_space_memory, q->addr, buf, len);
113
gpio->fclk[i] = clk;
80
+ dma_memory_read(s->mem_as, q->addr, buf, len);
114
}
81
trace_pl330_exec_cycle(q->addr, len);
115
82
if (trace_event_get_state_backends(TRACE_PL330_HEXDUMP)) {
116
static Property omap2_gpio_properties[] = {
83
pl330_hexdump(buf, len);
117
- DEFINE_PROP_INT32("mpu_model", struct omap2_gpif_s, mpu_model, 0),
84
@@ -XXX,XX +XXX,XX @@ static int pl330_exec_cycle(PL330Chan *channel)
118
+ DEFINE_PROP_INT32("mpu_model", Omap2GpioState, mpu_model, 0),
85
fifo_res = pl330_fifo_get(&s->fifo, buf, len, q->tag);
86
}
87
if (fifo_res == PL330_FIFO_OK || q->z) {
88
- dma_memory_write(&address_space_memory, q->addr, buf, len);
89
+ dma_memory_write(s->mem_as, q->addr, buf, len);
90
trace_pl330_exec_cycle(q->addr, len);
91
if (trace_event_get_state_backends(TRACE_PL330_HEXDUMP)) {
92
pl330_hexdump(buf, len);
93
@@ -XXX,XX +XXX,XX @@ static void pl330_realize(DeviceState *dev, Error **errp)
94
"dma", PL330_IOMEM_SIZE);
95
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
96
97
+ if (!s->mem_mr) {
98
+ error_setg(errp, "'memory' link is not set");
99
+ return;
100
+ } else if (s->mem_mr == get_system_memory()) {
101
+ /* Avoid creating new AS for system memory. */
102
+ s->mem_as = &address_space_memory;
103
+ } else {
104
+ s->mem_as = g_new0(AddressSpace, 1);
105
+ address_space_init(s->mem_as, s->mem_mr,
106
+ memory_region_name(s->mem_mr));
107
+ }
108
+
109
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pl330_exec_cycle_timer, s);
110
111
s->cfg[0] = (s->mgr_ns_at_rst ? 0x4 : 0) |
112
@@ -XXX,XX +XXX,XX @@ static Property pl330_properties[] = {
113
DEFINE_PROP_UINT8("rd_q_dep", PL330State, rd_q_dep, 16),
114
DEFINE_PROP_UINT16("data_buffer_dep", PL330State, data_buffer_dep, 256),
115
116
+ DEFINE_PROP_LINK("memory", PL330State, mem_mr,
117
+ TYPE_MEMORY_REGION, MemoryRegion *),
118
+
119
DEFINE_PROP_END_OF_LIST(),
119
DEFINE_PROP_END_OF_LIST(),
120
};
120
};
121
121
122
@@ -XXX,XX +XXX,XX @@ static void omap2_gpio_class_init(ObjectClass *klass, void *data)
123
static const TypeInfo omap2_gpio_info = {
124
.name = TYPE_OMAP2_GPIO,
125
.parent = TYPE_SYS_BUS_DEVICE,
126
- .instance_size = sizeof(struct omap2_gpif_s),
127
+ .instance_size = sizeof(Omap2GpioState),
128
.class_init = omap2_gpio_class_init,
129
};
130
122
--
131
--
123
2.20.1
132
2.34.1
124
133
125
134
diff view generated by jsdifflib
1
Although the architecture doesn't define it as an alias, VMOVL
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
(vector move long) is encoded as a VSHLL with a zero shift.
2
3
Add a comment in the decode file noting that we handle VMOVL
3
Following docs/devel/style.rst guidelines, rename
4
as part of VSHLL.
4
omap_intr_handler_s -> OMAPIntcState. This also remove a
5
5
use of 'struct' in the DECLARE_INSTANCE_CHECKER() macro call.
6
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230109140306.23161-7-philmd@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
---
11
---
9
target/arm/mve.decode | 2 ++
12
include/hw/arm/omap.h | 9 ++++-----
10
1 file changed, 2 insertions(+)
13
hw/intc/omap_intc.c | 38 +++++++++++++++++++-------------------
11
14
2 files changed, 23 insertions(+), 24 deletions(-)
12
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
15
16
diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h
13
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/mve.decode
18
--- a/include/hw/arm/omap.h
15
+++ b/target/arm/mve.decode
19
+++ b/include/hw/arm/omap.h
16
@@ -XXX,XX +XXX,XX @@ VRSHRI_U 111 1 1111 1 . ... ... ... 0 0010 0 1 . 1 ... 0 @2_shr_h
20
@@ -XXX,XX +XXX,XX @@ void omap_clk_reparent(omap_clk clk, omap_clk parent);
17
VRSHRI_U 111 1 1111 1 . ... ... ... 0 0010 0 1 . 1 ... 0 @2_shr_w
21
18
22
/* omap_intc.c */
19
# VSHLL T1 encoding; the T2 VSHLL encoding is elsewhere in this file
23
#define TYPE_OMAP_INTC "common-omap-intc"
20
+# Note that VMOVL is encoded as "VSHLL with a zero shift count"; we
24
-typedef struct omap_intr_handler_s omap_intr_handler;
21
+# implement it that way rather than special-casing it in the decode.
25
-DECLARE_INSTANCE_CHECKER(omap_intr_handler, OMAP_INTC,
22
VSHLL_BS 111 0 1110 1 . 1 .. ... ... 0 1111 0 1 . 0 ... 0 @2_shll_b
26
- TYPE_OMAP_INTC)
23
VSHLL_BS 111 0 1110 1 . 1 .. ... ... 0 1111 0 1 . 0 ... 0 @2_shll_h
27
+typedef struct OMAPIntcState OMAPIntcState;
28
+DECLARE_INSTANCE_CHECKER(OMAPIntcState, OMAP_INTC, TYPE_OMAP_INTC)
29
30
31
/*
32
@@ -XXX,XX +XXX,XX @@ DECLARE_INSTANCE_CHECKER(omap_intr_handler, OMAP_INTC,
33
* (ie the struct omap_mpu_state_s*) to do the clockname to pointer
34
* translation.)
35
*/
36
-void omap_intc_set_iclk(omap_intr_handler *intc, omap_clk clk);
37
-void omap_intc_set_fclk(omap_intr_handler *intc, omap_clk clk);
38
+void omap_intc_set_iclk(OMAPIntcState *intc, omap_clk clk);
39
+void omap_intc_set_fclk(OMAPIntcState *intc, omap_clk clk);
40
41
/* omap_i2c.c */
42
#define TYPE_OMAP_I2C "omap_i2c"
43
diff --git a/hw/intc/omap_intc.c b/hw/intc/omap_intc.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/intc/omap_intc.c
46
+++ b/hw/intc/omap_intc.c
47
@@ -XXX,XX +XXX,XX @@ struct omap_intr_handler_bank_s {
48
unsigned char priority[32];
49
};
50
51
-struct omap_intr_handler_s {
52
+struct OMAPIntcState {
53
SysBusDevice parent_obj;
54
55
qemu_irq *pins;
56
@@ -XXX,XX +XXX,XX @@ struct omap_intr_handler_s {
57
struct omap_intr_handler_bank_s bank[3];
58
};
59
60
-static void omap_inth_sir_update(struct omap_intr_handler_s *s, int is_fiq)
61
+static void omap_inth_sir_update(OMAPIntcState *s, int is_fiq)
62
{
63
int i, j, sir_intr, p_intr, p;
64
uint32_t level;
65
@@ -XXX,XX +XXX,XX @@ static void omap_inth_sir_update(struct omap_intr_handler_s *s, int is_fiq)
66
s->sir_intr[is_fiq] = sir_intr;
67
}
68
69
-static inline void omap_inth_update(struct omap_intr_handler_s *s, int is_fiq)
70
+static inline void omap_inth_update(OMAPIntcState *s, int is_fiq)
71
{
72
int i;
73
uint32_t has_intr = 0;
74
@@ -XXX,XX +XXX,XX @@ static inline void omap_inth_update(struct omap_intr_handler_s *s, int is_fiq)
75
76
static void omap_set_intr(void *opaque, int irq, int req)
77
{
78
- struct omap_intr_handler_s *ih = opaque;
79
+ OMAPIntcState *ih = opaque;
80
uint32_t rise;
81
82
struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
83
@@ -XXX,XX +XXX,XX @@ static void omap_set_intr(void *opaque, int irq, int req)
84
/* Simplified version with no edge detection */
85
static void omap_set_intr_noedge(void *opaque, int irq, int req)
86
{
87
- struct omap_intr_handler_s *ih = opaque;
88
+ OMAPIntcState *ih = opaque;
89
uint32_t rise;
90
91
struct omap_intr_handler_bank_s *bank = &ih->bank[irq >> 5];
92
@@ -XXX,XX +XXX,XX @@ static void omap_set_intr_noedge(void *opaque, int irq, int req)
93
static uint64_t omap_inth_read(void *opaque, hwaddr addr,
94
unsigned size)
95
{
96
- struct omap_intr_handler_s *s = opaque;
97
+ OMAPIntcState *s = opaque;
98
int i, offset = addr;
99
int bank_no = offset >> 8;
100
int line_no;
101
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_inth_read(void *opaque, hwaddr addr,
102
static void omap_inth_write(void *opaque, hwaddr addr,
103
uint64_t value, unsigned size)
104
{
105
- struct omap_intr_handler_s *s = opaque;
106
+ OMAPIntcState *s = opaque;
107
int i, offset = addr;
108
int bank_no = offset >> 8;
109
struct omap_intr_handler_bank_s *bank = &s->bank[bank_no];
110
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps omap_inth_mem_ops = {
111
112
static void omap_inth_reset(DeviceState *dev)
113
{
114
- struct omap_intr_handler_s *s = OMAP_INTC(dev);
115
+ OMAPIntcState *s = OMAP_INTC(dev);
116
int i;
117
118
for (i = 0; i < s->nbanks; ++i){
119
@@ -XXX,XX +XXX,XX @@ static void omap_inth_reset(DeviceState *dev)
120
static void omap_intc_init(Object *obj)
121
{
122
DeviceState *dev = DEVICE(obj);
123
- struct omap_intr_handler_s *s = OMAP_INTC(obj);
124
+ OMAPIntcState *s = OMAP_INTC(obj);
125
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
126
127
s->nbanks = 1;
128
@@ -XXX,XX +XXX,XX @@ static void omap_intc_init(Object *obj)
129
130
static void omap_intc_realize(DeviceState *dev, Error **errp)
131
{
132
- struct omap_intr_handler_s *s = OMAP_INTC(dev);
133
+ OMAPIntcState *s = OMAP_INTC(dev);
134
135
if (!s->iclk) {
136
error_setg(errp, "omap-intc: clk not connected");
137
}
138
}
139
140
-void omap_intc_set_iclk(omap_intr_handler *intc, omap_clk clk)
141
+void omap_intc_set_iclk(OMAPIntcState *intc, omap_clk clk)
142
{
143
intc->iclk = clk;
144
}
145
146
-void omap_intc_set_fclk(omap_intr_handler *intc, omap_clk clk)
147
+void omap_intc_set_fclk(OMAPIntcState *intc, omap_clk clk)
148
{
149
intc->fclk = clk;
150
}
151
152
static Property omap_intc_properties[] = {
153
- DEFINE_PROP_UINT32("size", struct omap_intr_handler_s, size, 0x100),
154
+ DEFINE_PROP_UINT32("size", OMAPIntcState, size, 0x100),
155
DEFINE_PROP_END_OF_LIST(),
156
};
157
158
@@ -XXX,XX +XXX,XX @@ static const TypeInfo omap_intc_info = {
159
static uint64_t omap2_inth_read(void *opaque, hwaddr addr,
160
unsigned size)
161
{
162
- struct omap_intr_handler_s *s = opaque;
163
+ OMAPIntcState *s = opaque;
164
int offset = addr;
165
int bank_no, line_no;
166
struct omap_intr_handler_bank_s *bank = NULL;
167
@@ -XXX,XX +XXX,XX @@ static uint64_t omap2_inth_read(void *opaque, hwaddr addr,
168
static void omap2_inth_write(void *opaque, hwaddr addr,
169
uint64_t value, unsigned size)
170
{
171
- struct omap_intr_handler_s *s = opaque;
172
+ OMAPIntcState *s = opaque;
173
int offset = addr;
174
int bank_no, line_no;
175
struct omap_intr_handler_bank_s *bank = NULL;
176
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps omap2_inth_mem_ops = {
177
static void omap2_intc_init(Object *obj)
178
{
179
DeviceState *dev = DEVICE(obj);
180
- struct omap_intr_handler_s *s = OMAP_INTC(obj);
181
+ OMAPIntcState *s = OMAP_INTC(obj);
182
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
183
184
s->level_only = 1;
185
@@ -XXX,XX +XXX,XX @@ static void omap2_intc_init(Object *obj)
186
187
static void omap2_intc_realize(DeviceState *dev, Error **errp)
188
{
189
- struct omap_intr_handler_s *s = OMAP_INTC(dev);
190
+ OMAPIntcState *s = OMAP_INTC(dev);
191
192
if (!s->iclk) {
193
error_setg(errp, "omap2-intc: iclk not connected");
194
@@ -XXX,XX +XXX,XX @@ static void omap2_intc_realize(DeviceState *dev, Error **errp)
195
}
196
197
static Property omap2_intc_properties[] = {
198
- DEFINE_PROP_UINT8("revision", struct omap_intr_handler_s,
199
+ DEFINE_PROP_UINT8("revision", OMAPIntcState,
200
revision, 0x21),
201
DEFINE_PROP_END_OF_LIST(),
202
};
203
@@ -XXX,XX +XXX,XX @@ static const TypeInfo omap2_intc_info = {
204
static const TypeInfo omap_intc_type_info = {
205
.name = TYPE_OMAP_INTC,
206
.parent = TYPE_SYS_BUS_DEVICE,
207
- .instance_size = sizeof(omap_intr_handler),
208
+ .instance_size = sizeof(OMAPIntcState),
209
.abstract = true,
210
};
24
211
25
--
212
--
26
2.20.1
213
2.34.1
27
214
28
215
diff view generated by jsdifflib
Deleted patch
1
In the MVE shift-and-insert insns, we special case VSLI by 0
2
and VSRI by <dt>. VSRI by <dt> means "don't update the destination",
3
which is what we've implemented. However VSLI by 0 is "set
4
destination to the input", so we don't want to use the same
5
special-casing that we do for VSRI by <dt>.
6
1
7
Since the generic logic gives the right answer for a shift
8
by 0, just use that.
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
---
13
target/arm/mve_helper.c | 9 +++++----
14
1 file changed, 5 insertions(+), 4 deletions(-)
15
16
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/mve_helper.c
19
+++ b/target/arm/mve_helper.c
20
@@ -XXX,XX +XXX,XX @@ DO_2SHIFT_S(vrshli_s, DO_VRSHLS)
21
uint16_t mask; \
22
uint64_t shiftmask; \
23
unsigned e; \
24
- if (shift == 0 || shift == ESIZE * 8) { \
25
+ if (shift == ESIZE * 8) { \
26
/* \
27
- * Only VSLI can shift by 0; only VSRI can shift by <dt>. \
28
- * The generic logic would give the right answer for 0 but \
29
- * fails for <dt>. \
30
+ * Only VSRI can shift by <dt>; it should mean "don't \
31
+ * update the destination". The generic logic can't handle \
32
+ * this because it would try to shift by an out-of-range \
33
+ * amount, so special case it here. \
34
*/ \
35
goto done; \
36
} \
37
--
38
2.20.1
39
40
diff view generated by jsdifflib
Deleted patch
1
In the MVE helpers for the narrowing operations (DO_VSHRN and
2
DO_VSHRN_SAT) we were using the wrong bits of the predicate mask for
3
the 'top' versions of the insn. This is because the loop works over
4
the double-sized input elements and shifts the predicate mask by that
5
many bits each time, but when we write out the half-sized output we
6
must look at the mask bits for whichever half of the element we are
7
writing to.
8
1
9
Correct this by shifting the whole mask right by ESIZE bits for the
10
'top' insns. This allows us also to simplify the saturation bit
11
checking (where we had noticed that we needed to look at a different
12
mask bit for the 'top' insn.)
13
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
---
17
target/arm/mve_helper.c | 4 +++-
18
1 file changed, 3 insertions(+), 1 deletion(-)
19
20
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/mve_helper.c
23
+++ b/target/arm/mve_helper.c
24
@@ -XXX,XX +XXX,XX @@ DO_VSHLL_ALL(vshllt, true)
25
TYPE *d = vd; \
26
uint16_t mask = mve_element_mask(env); \
27
unsigned le; \
28
+ mask >>= ESIZE * TOP; \
29
for (le = 0; le < 16 / LESIZE; le++, mask >>= LESIZE) { \
30
TYPE r = FN(m[H##LESIZE(le)], shift); \
31
mergemask(&d[H##ESIZE(le * 2 + TOP)], r, mask); \
32
@@ -XXX,XX +XXX,XX @@ static inline int32_t do_sat_bhs(int64_t val, int64_t min, int64_t max,
33
uint16_t mask = mve_element_mask(env); \
34
bool qc = false; \
35
unsigned le; \
36
+ mask >>= ESIZE * TOP; \
37
for (le = 0; le < 16 / LESIZE; le++, mask >>= LESIZE) { \
38
bool sat = false; \
39
TYPE r = FN(m[H##LESIZE(le)], shift, &sat); \
40
mergemask(&d[H##ESIZE(le * 2 + TOP)], r, mask); \
41
- qc |= sat && (mask & 1 << (TOP * ESIZE)); \
42
+ qc |= sat & mask & 1; \
43
} \
44
if (qc) { \
45
env->vfp.qc[0] = qc; \
46
--
47
2.20.1
48
49
diff view generated by jsdifflib
Deleted patch
1
We got an edge case wrong in the 48-bit SQRSHRL implementation: if
2
the shift is to the right, although it always makes the result
3
smaller than the input value it might not be within the 48-bit range
4
the result is supposed to be if the input had some bits in [63..48]
5
set and the shift didn't bring all of those within the [47..0] range.
6
1
7
Handle this similarly to the way we already do for this case in
8
do_uqrshl48_d(): extend the calculated result from 48 bits,
9
and return that if not saturating or if it doesn't change the
10
result; otherwise fall through to return a saturated value.
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
---
15
target/arm/mve_helper.c | 11 +++++++++--
16
1 file changed, 9 insertions(+), 2 deletions(-)
17
18
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/mve_helper.c
21
+++ b/target/arm/mve_helper.c
22
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(mve_uqrshll)(CPUARMState *env, uint64_t n, uint32_t shift)
23
static inline int64_t do_sqrshl48_d(int64_t src, int64_t shift,
24
bool round, uint32_t *sat)
25
{
26
+ int64_t val, extval;
27
+
28
if (shift <= -48) {
29
/* Rounding the sign bit always produces 0. */
30
if (round) {
31
@@ -XXX,XX +XXX,XX @@ static inline int64_t do_sqrshl48_d(int64_t src, int64_t shift,
32
} else if (shift < 0) {
33
if (round) {
34
src >>= -shift - 1;
35
- return (src >> 1) + (src & 1);
36
+ val = (src >> 1) + (src & 1);
37
+ } else {
38
+ val = src >> -shift;
39
+ }
40
+ extval = sextract64(val, 0, 48);
41
+ if (!sat || val == extval) {
42
+ return extval;
43
}
44
- return src >> -shift;
45
} else if (shift < 48) {
46
int64_t extval = sextract64(src << shift, 0, 48);
47
if (!sat || src == (extval >> shift)) {
48
--
49
2.20.1
50
51
diff view generated by jsdifflib
Deleted patch
1
For vector loads, predicated elements are zeroed, instead of
2
retaining their previous values (as happens for most data
3
processing operations). This means we need to distinguish
4
"beat not executed due to ECI" (don't touch destination
5
element) from "beat executed but predicated out" (zero
6
destination element).
7
1
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
---
11
target/arm/mve_helper.c | 8 +++++---
12
1 file changed, 5 insertions(+), 3 deletions(-)
13
14
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/mve_helper.c
17
+++ b/target/arm/mve_helper.c
18
@@ -XXX,XX +XXX,XX @@ static void mve_advance_vpt(CPUARMState *env)
19
env->v7m.vpr = vpr;
20
}
21
22
-
23
+/* For loads, predicated lanes are zeroed instead of keeping their old values */
24
#define DO_VLDR(OP, MSIZE, LDTYPE, ESIZE, TYPE) \
25
void HELPER(mve_##OP)(CPUARMState *env, void *vd, uint32_t addr) \
26
{ \
27
TYPE *d = vd; \
28
uint16_t mask = mve_element_mask(env); \
29
+ uint16_t eci_mask = mve_eci_mask(env); \
30
unsigned b, e; \
31
/* \
32
* R_SXTM allows the dest reg to become UNKNOWN for abandoned \
33
@@ -XXX,XX +XXX,XX @@ static void mve_advance_vpt(CPUARMState *env)
34
* then take an exception. \
35
*/ \
36
for (b = 0, e = 0; b < 16; b += ESIZE, e++) { \
37
- if (mask & (1 << b)) { \
38
- d[H##ESIZE(e)] = cpu_##LDTYPE##_data_ra(env, addr, GETPC()); \
39
+ if (eci_mask & (1 << b)) { \
40
+ d[H##ESIZE(e)] = (mask & (1 << b)) ? \
41
+ cpu_##LDTYPE##_data_ra(env, addr, GETPC()) : 0; \
42
} \
43
addr += MSIZE; \
44
} \
45
--
46
2.20.1
47
48
diff view generated by jsdifflib
1
From: Eduardo Habkost <ehabkost@redhat.com>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
The SBSA_GWDT enum value conflicts with the SBSA_GWDT() QOM type
3
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
checking helper, preventing us from using a OBJECT_DEFINE* or
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
DEFINE_INSTANCE_CHECKER macro for the SBSA_GWDT() wrapper.
5
Message-id: 20230109140306.23161-8-philmd@linaro.org
6
7
If I understand the SBSA 6.0 specification correctly, the signal
8
being connected to IRQ 16 is the WS0 output signal from the
9
Generic Watchdog. Rename the enum value to SBSA_GWDT_WS0 to be
10
more explicit and avoid the name conflict.
11
12
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
13
Message-id: 20210806023119.431680-1-ehabkost@redhat.com
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
7
---
17
hw/arm/sbsa-ref.c | 6 +++---
8
hw/arm/stellaris.c | 6 +++---
18
1 file changed, 3 insertions(+), 3 deletions(-)
9
1 file changed, 3 insertions(+), 3 deletions(-)
19
10
20
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
11
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
21
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
22
--- a/hw/arm/sbsa-ref.c
13
--- a/hw/arm/stellaris.c
23
+++ b/hw/arm/sbsa-ref.c
14
+++ b/hw/arm/stellaris.c
24
@@ -XXX,XX +XXX,XX @@ enum {
15
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_update(stellaris_adc_state *s)
25
SBSA_GIC_DIST,
16
26
SBSA_GIC_REDIST,
17
static void stellaris_adc_trigger(void *opaque, int irq, int level)
27
SBSA_SECURE_EC,
18
{
28
- SBSA_GWDT,
19
- stellaris_adc_state *s = (stellaris_adc_state *)opaque;
29
+ SBSA_GWDT_WS0,
20
+ stellaris_adc_state *s = opaque;
30
SBSA_GWDT_REFRESH,
21
int n;
31
SBSA_GWDT_CONTROL,
22
32
SBSA_SMMU,
23
for (n = 0; n < 4; n++) {
33
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
24
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_reset(stellaris_adc_state *s)
34
[SBSA_AHCI] = 10,
25
static uint64_t stellaris_adc_read(void *opaque, hwaddr offset,
35
[SBSA_EHCI] = 11,
26
unsigned size)
36
[SBSA_SMMU] = 12, /* ... to 15 */
27
{
37
- [SBSA_GWDT] = 16,
28
- stellaris_adc_state *s = (stellaris_adc_state *)opaque;
38
+ [SBSA_GWDT_WS0] = 16,
29
+ stellaris_adc_state *s = opaque;
39
};
30
40
31
/* TODO: Implement this. */
41
static const char * const valid_cpus[] = {
32
if (offset >= 0x40 && offset < 0xc0) {
42
@@ -XXX,XX +XXX,XX @@ static void create_wdt(const SBSAMachineState *sms)
33
@@ -XXX,XX +XXX,XX @@ static uint64_t stellaris_adc_read(void *opaque, hwaddr offset,
43
hwaddr cbase = sbsa_ref_memmap[SBSA_GWDT_CONTROL].base;
34
static void stellaris_adc_write(void *opaque, hwaddr offset,
44
DeviceState *dev = qdev_new(TYPE_WDT_SBSA);
35
uint64_t value, unsigned size)
45
SysBusDevice *s = SYS_BUS_DEVICE(dev);
36
{
46
- int irq = sbsa_ref_irqmap[SBSA_GWDT];
37
- stellaris_adc_state *s = (stellaris_adc_state *)opaque;
47
+ int irq = sbsa_ref_irqmap[SBSA_GWDT_WS0];
38
+ stellaris_adc_state *s = opaque;
48
39
49
sysbus_realize_and_unref(s, &error_fatal);
40
/* TODO: Implement this. */
50
sysbus_mmio_map(s, 0, rbase);
41
if (offset >= 0x40 && offset < 0xc0) {
51
--
42
--
52
2.20.1
43
2.34.1
53
44
54
45
diff view generated by jsdifflib
1
Implement the MVE narrowing move insns VMOVN, VQMOVN and VQMOVUN.
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
These take a double-width input, narrow it (possibly saturating) and
3
store the result to either the top or bottom half of the output
4
element.
5
2
3
Following docs/devel/style.rst guidelines, rename
4
stellaris_adc_state -> StellarisADCState. This also remove a
5
use of 'struct' in the DECLARE_INSTANCE_CHECKER() macro call.
6
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230109140306.23161-9-philmd@linaro.org
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
---
11
---
9
target/arm/helper-mve.h | 20 ++++++++++
12
hw/arm/stellaris.c | 73 +++++++++++++++++++++++-----------------------
10
target/arm/mve.decode | 12 ++++++
13
1 file changed, 36 insertions(+), 37 deletions(-)
11
target/arm/mve_helper.c | 78 ++++++++++++++++++++++++++++++++++++++
12
target/arm/translate-mve.c | 22 +++++++++++
13
4 files changed, 132 insertions(+)
14
14
15
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
15
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper-mve.h
17
--- a/hw/arm/stellaris.c
18
+++ b/target/arm/helper-mve.h
18
+++ b/hw/arm/stellaris.c
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vnegw, TCG_CALL_NO_WG, void, env, ptr, ptr)
19
@@ -XXX,XX +XXX,XX @@ static void stellaris_i2c_init(Object *obj)
20
DEF_HELPER_FLAGS_3(mve_vfnegh, TCG_CALL_NO_WG, void, env, ptr, ptr)
20
#define STELLARIS_ADC_FIFO_FULL 0x1000
21
DEF_HELPER_FLAGS_3(mve_vfnegs, TCG_CALL_NO_WG, void, env, ptr, ptr)
21
22
22
#define TYPE_STELLARIS_ADC "stellaris-adc"
23
+DEF_HELPER_FLAGS_3(mve_vmovnbb, TCG_CALL_NO_WG, void, env, ptr, ptr)
23
-typedef struct StellarisADCState stellaris_adc_state;
24
+DEF_HELPER_FLAGS_3(mve_vmovnbh, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
-DECLARE_INSTANCE_CHECKER(stellaris_adc_state, STELLARIS_ADC,
25
+DEF_HELPER_FLAGS_3(mve_vmovntb, TCG_CALL_NO_WG, void, env, ptr, ptr)
25
- TYPE_STELLARIS_ADC)
26
+DEF_HELPER_FLAGS_3(mve_vmovnth, TCG_CALL_NO_WG, void, env, ptr, ptr)
26
+typedef struct StellarisADCState StellarisADCState;
27
+
27
+DECLARE_INSTANCE_CHECKER(StellarisADCState, STELLARIS_ADC, TYPE_STELLARIS_ADC)
28
+DEF_HELPER_FLAGS_3(mve_vqmovunbb, TCG_CALL_NO_WG, void, env, ptr, ptr)
28
29
+DEF_HELPER_FLAGS_3(mve_vqmovunbh, TCG_CALL_NO_WG, void, env, ptr, ptr)
29
struct StellarisADCState {
30
+DEF_HELPER_FLAGS_3(mve_vqmovuntb, TCG_CALL_NO_WG, void, env, ptr, ptr)
30
SysBusDevice parent_obj;
31
+DEF_HELPER_FLAGS_3(mve_vqmovunth, TCG_CALL_NO_WG, void, env, ptr, ptr)
31
@@ -XXX,XX +XXX,XX @@ struct StellarisADCState {
32
+
32
qemu_irq irq[4];
33
+DEF_HELPER_FLAGS_3(mve_vqmovnbsb, TCG_CALL_NO_WG, void, env, ptr, ptr)
33
};
34
+DEF_HELPER_FLAGS_3(mve_vqmovnbsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
34
35
+DEF_HELPER_FLAGS_3(mve_vqmovntsb, TCG_CALL_NO_WG, void, env, ptr, ptr)
35
-static uint32_t stellaris_adc_fifo_read(stellaris_adc_state *s, int n)
36
+DEF_HELPER_FLAGS_3(mve_vqmovntsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
36
+static uint32_t stellaris_adc_fifo_read(StellarisADCState *s, int n)
37
+
37
{
38
+DEF_HELPER_FLAGS_3(mve_vqmovnbub, TCG_CALL_NO_WG, void, env, ptr, ptr)
38
int tail;
39
+DEF_HELPER_FLAGS_3(mve_vqmovnbuh, TCG_CALL_NO_WG, void, env, ptr, ptr)
39
40
+DEF_HELPER_FLAGS_3(mve_vqmovntub, TCG_CALL_NO_WG, void, env, ptr, ptr)
40
@@ -XXX,XX +XXX,XX @@ static uint32_t stellaris_adc_fifo_read(stellaris_adc_state *s, int n)
41
+DEF_HELPER_FLAGS_3(mve_vqmovntuh, TCG_CALL_NO_WG, void, env, ptr, ptr)
41
return s->fifo[n].data[tail];
42
+
43
DEF_HELPER_FLAGS_4(mve_vand, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
44
DEF_HELPER_FLAGS_4(mve_vbic, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
45
DEF_HELPER_FLAGS_4(mve_vorr, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
46
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/mve.decode
49
+++ b/target/arm/mve.decode
50
@@ -XXX,XX +XXX,XX @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
51
VSHLL_BS 111 0 1110 0 . 11 .. 01 ... 0 1110 0 0 . 0 ... 1 @2_shll_esize_b
52
VSHLL_BS 111 0 1110 0 . 11 .. 01 ... 0 1110 0 0 . 0 ... 1 @2_shll_esize_h
53
54
+ VQMOVUNB 111 0 1110 0 . 11 .. 01 ... 0 1110 1 0 . 0 ... 1 @1op
55
+ VQMOVN_BS 111 0 1110 0 . 11 .. 11 ... 0 1110 0 0 . 0 ... 1 @1op
56
+
57
VMULH_S 111 0 1110 0 . .. ...1 ... 0 1110 . 0 . 0 ... 1 @2op
58
}
42
}
59
43
60
@@ -XXX,XX +XXX,XX @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
44
-static void stellaris_adc_fifo_write(stellaris_adc_state *s, int n,
61
VSHLL_BU 111 1 1110 0 . 11 .. 01 ... 0 1110 0 0 . 0 ... 1 @2_shll_esize_b
45
+static void stellaris_adc_fifo_write(StellarisADCState *s, int n,
62
VSHLL_BU 111 1 1110 0 . 11 .. 01 ... 0 1110 0 0 . 0 ... 1 @2_shll_esize_h
46
uint32_t value)
63
47
{
64
+ VMOVNB 111 1 1110 0 . 11 .. 01 ... 0 1110 1 0 . 0 ... 1 @1op
48
int head;
65
+ VQMOVN_BU 111 1 1110 0 . 11 .. 11 ... 0 1110 0 0 . 0 ... 1 @1op
49
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_fifo_write(stellaris_adc_state *s, int n,
66
+
50
s->fifo[n].state |= STELLARIS_ADC_FIFO_FULL;
67
VMULH_U 111 1 1110 0 . .. ...1 ... 0 1110 . 0 . 0 ... 1 @2op
68
}
51
}
69
52
70
@@ -XXX,XX +XXX,XX @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
53
-static void stellaris_adc_update(stellaris_adc_state *s)
71
VSHLL_TS 111 0 1110 0 . 11 .. 01 ... 1 1110 0 0 . 0 ... 1 @2_shll_esize_b
54
+static void stellaris_adc_update(StellarisADCState *s)
72
VSHLL_TS 111 0 1110 0 . 11 .. 01 ... 1 1110 0 0 . 0 ... 1 @2_shll_esize_h
55
{
73
56
int level;
74
+ VQMOVUNT 111 0 1110 0 . 11 .. 01 ... 1 1110 1 0 . 0 ... 1 @1op
57
int n;
75
+ VQMOVN_TS 111 0 1110 0 . 11 .. 11 ... 1 1110 0 0 . 0 ... 1 @1op
58
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_update(stellaris_adc_state *s)
76
+
59
77
VRMULH_S 111 0 1110 0 . .. ...1 ... 1 1110 . 0 . 0 ... 1 @2op
60
static void stellaris_adc_trigger(void *opaque, int irq, int level)
61
{
62
- stellaris_adc_state *s = opaque;
63
+ StellarisADCState *s = opaque;
64
int n;
65
66
for (n = 0; n < 4; n++) {
67
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_trigger(void *opaque, int irq, int level)
68
}
78
}
69
}
79
70
80
@@ -XXX,XX +XXX,XX @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
71
-static void stellaris_adc_reset(stellaris_adc_state *s)
81
VSHLL_TU 111 1 1110 0 . 11 .. 01 ... 1 1110 0 0 . 0 ... 1 @2_shll_esize_b
72
+static void stellaris_adc_reset(StellarisADCState *s)
82
VSHLL_TU 111 1 1110 0 . 11 .. 01 ... 1 1110 0 0 . 0 ... 1 @2_shll_esize_h
83
84
+ VMOVNT 111 1 1110 0 . 11 .. 01 ... 1 1110 1 0 . 0 ... 1 @1op
85
+ VQMOVN_TU 111 1 1110 0 . 11 .. 11 ... 1 1110 0 0 . 0 ... 1 @1op
86
+
87
VRMULH_U 111 1 1110 0 . .. ...1 ... 1 1110 . 0 . 0 ... 1 @2op
88
}
89
90
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
91
index XXXXXXX..XXXXXXX 100644
92
--- a/target/arm/mve_helper.c
93
+++ b/target/arm/mve_helper.c
94
@@ -XXX,XX +XXX,XX @@ DO_VSHRN_SAT_UH(vqrshrnb_uh, vqrshrnt_uh, DO_RSHRN_UH)
95
DO_VSHRN_SAT_SB(vqrshrunbb, vqrshruntb, DO_RSHRUN_B)
96
DO_VSHRN_SAT_SH(vqrshrunbh, vqrshrunth, DO_RSHRUN_H)
97
98
+#define DO_VMOVN(OP, TOP, ESIZE, TYPE, LESIZE, LTYPE) \
99
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm) \
100
+ { \
101
+ LTYPE *m = vm; \
102
+ TYPE *d = vd; \
103
+ uint16_t mask = mve_element_mask(env); \
104
+ unsigned le; \
105
+ mask >>= ESIZE * TOP; \
106
+ for (le = 0; le < 16 / LESIZE; le++, mask >>= LESIZE) { \
107
+ mergemask(&d[H##ESIZE(le * 2 + TOP)], \
108
+ m[H##LESIZE(le)], mask); \
109
+ } \
110
+ mve_advance_vpt(env); \
111
+ }
112
+
113
+DO_VMOVN(vmovnbb, false, 1, uint8_t, 2, uint16_t)
114
+DO_VMOVN(vmovnbh, false, 2, uint16_t, 4, uint32_t)
115
+DO_VMOVN(vmovntb, true, 1, uint8_t, 2, uint16_t)
116
+DO_VMOVN(vmovnth, true, 2, uint16_t, 4, uint32_t)
117
+
118
+#define DO_VMOVN_SAT(OP, TOP, ESIZE, TYPE, LESIZE, LTYPE, FN) \
119
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm) \
120
+ { \
121
+ LTYPE *m = vm; \
122
+ TYPE *d = vd; \
123
+ uint16_t mask = mve_element_mask(env); \
124
+ bool qc = false; \
125
+ unsigned le; \
126
+ mask >>= ESIZE * TOP; \
127
+ for (le = 0; le < 16 / LESIZE; le++, mask >>= LESIZE) { \
128
+ bool sat = false; \
129
+ TYPE r = FN(m[H##LESIZE(le)], &sat); \
130
+ mergemask(&d[H##ESIZE(le * 2 + TOP)], r, mask); \
131
+ qc |= sat & mask & 1; \
132
+ } \
133
+ if (qc) { \
134
+ env->vfp.qc[0] = qc; \
135
+ } \
136
+ mve_advance_vpt(env); \
137
+ }
138
+
139
+#define DO_VMOVN_SAT_UB(BOP, TOP, FN) \
140
+ DO_VMOVN_SAT(BOP, false, 1, uint8_t, 2, uint16_t, FN) \
141
+ DO_VMOVN_SAT(TOP, true, 1, uint8_t, 2, uint16_t, FN)
142
+
143
+#define DO_VMOVN_SAT_UH(BOP, TOP, FN) \
144
+ DO_VMOVN_SAT(BOP, false, 2, uint16_t, 4, uint32_t, FN) \
145
+ DO_VMOVN_SAT(TOP, true, 2, uint16_t, 4, uint32_t, FN)
146
+
147
+#define DO_VMOVN_SAT_SB(BOP, TOP, FN) \
148
+ DO_VMOVN_SAT(BOP, false, 1, int8_t, 2, int16_t, FN) \
149
+ DO_VMOVN_SAT(TOP, true, 1, int8_t, 2, int16_t, FN)
150
+
151
+#define DO_VMOVN_SAT_SH(BOP, TOP, FN) \
152
+ DO_VMOVN_SAT(BOP, false, 2, int16_t, 4, int32_t, FN) \
153
+ DO_VMOVN_SAT(TOP, true, 2, int16_t, 4, int32_t, FN)
154
+
155
+#define DO_VQMOVN_SB(N, SATP) \
156
+ do_sat_bhs((int64_t)(N), INT8_MIN, INT8_MAX, SATP)
157
+#define DO_VQMOVN_UB(N, SATP) \
158
+ do_sat_bhs((uint64_t)(N), 0, UINT8_MAX, SATP)
159
+#define DO_VQMOVUN_B(N, SATP) \
160
+ do_sat_bhs((int64_t)(N), 0, UINT8_MAX, SATP)
161
+
162
+#define DO_VQMOVN_SH(N, SATP) \
163
+ do_sat_bhs((int64_t)(N), INT16_MIN, INT16_MAX, SATP)
164
+#define DO_VQMOVN_UH(N, SATP) \
165
+ do_sat_bhs((uint64_t)(N), 0, UINT16_MAX, SATP)
166
+#define DO_VQMOVUN_H(N, SATP) \
167
+ do_sat_bhs((int64_t)(N), 0, UINT16_MAX, SATP)
168
+
169
+DO_VMOVN_SAT_SB(vqmovnbsb, vqmovntsb, DO_VQMOVN_SB)
170
+DO_VMOVN_SAT_SH(vqmovnbsh, vqmovntsh, DO_VQMOVN_SH)
171
+DO_VMOVN_SAT_UB(vqmovnbub, vqmovntub, DO_VQMOVN_UB)
172
+DO_VMOVN_SAT_UH(vqmovnbuh, vqmovntuh, DO_VQMOVN_UH)
173
+DO_VMOVN_SAT_SB(vqmovunbb, vqmovuntb, DO_VQMOVUN_B)
174
+DO_VMOVN_SAT_SH(vqmovunbh, vqmovunth, DO_VQMOVUN_H)
175
+
176
uint32_t HELPER(mve_vshlc)(CPUARMState *env, void *vd, uint32_t rdm,
177
uint32_t shift)
178
{
73
{
179
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
74
int n;
180
index XXXXXXX..XXXXXXX 100644
75
181
--- a/target/arm/translate-mve.c
76
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_reset(stellaris_adc_state *s)
182
+++ b/target/arm/translate-mve.c
77
static uint64_t stellaris_adc_read(void *opaque, hwaddr offset,
183
@@ -XXX,XX +XXX,XX @@ DO_1OP(VCLS, vcls)
78
unsigned size)
184
DO_1OP(VABS, vabs)
185
DO_1OP(VNEG, vneg)
186
187
+/* Narrowing moves: only size 0 and 1 are valid */
188
+#define DO_VMOVN(INSN, FN) \
189
+ static bool trans_##INSN(DisasContext *s, arg_1op *a) \
190
+ { \
191
+ static MVEGenOneOpFn * const fns[] = { \
192
+ gen_helper_mve_##FN##b, \
193
+ gen_helper_mve_##FN##h, \
194
+ NULL, \
195
+ NULL, \
196
+ }; \
197
+ return do_1op(s, a, fns[a->size]); \
198
+ }
199
+
200
+DO_VMOVN(VMOVNB, vmovnb)
201
+DO_VMOVN(VMOVNT, vmovnt)
202
+DO_VMOVN(VQMOVUNB, vqmovunb)
203
+DO_VMOVN(VQMOVUNT, vqmovunt)
204
+DO_VMOVN(VQMOVN_BS, vqmovnbs)
205
+DO_VMOVN(VQMOVN_TS, vqmovnts)
206
+DO_VMOVN(VQMOVN_BU, vqmovnbu)
207
+DO_VMOVN(VQMOVN_TU, vqmovntu)
208
+
209
static bool trans_VREV16(DisasContext *s, arg_1op *a)
210
{
79
{
211
static MVEGenOneOpFn * const fns[] = {
80
- stellaris_adc_state *s = opaque;
81
+ StellarisADCState *s = opaque;
82
83
/* TODO: Implement this. */
84
if (offset >= 0x40 && offset < 0xc0) {
85
@@ -XXX,XX +XXX,XX @@ static uint64_t stellaris_adc_read(void *opaque, hwaddr offset,
86
static void stellaris_adc_write(void *opaque, hwaddr offset,
87
uint64_t value, unsigned size)
88
{
89
- stellaris_adc_state *s = opaque;
90
+ StellarisADCState *s = opaque;
91
92
/* TODO: Implement this. */
93
if (offset >= 0x40 && offset < 0xc0) {
94
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_stellaris_adc = {
95
.version_id = 1,
96
.minimum_version_id = 1,
97
.fields = (VMStateField[]) {
98
- VMSTATE_UINT32(actss, stellaris_adc_state),
99
- VMSTATE_UINT32(ris, stellaris_adc_state),
100
- VMSTATE_UINT32(im, stellaris_adc_state),
101
- VMSTATE_UINT32(emux, stellaris_adc_state),
102
- VMSTATE_UINT32(ostat, stellaris_adc_state),
103
- VMSTATE_UINT32(ustat, stellaris_adc_state),
104
- VMSTATE_UINT32(sspri, stellaris_adc_state),
105
- VMSTATE_UINT32(sac, stellaris_adc_state),
106
- VMSTATE_UINT32(fifo[0].state, stellaris_adc_state),
107
- VMSTATE_UINT32_ARRAY(fifo[0].data, stellaris_adc_state, 16),
108
- VMSTATE_UINT32(ssmux[0], stellaris_adc_state),
109
- VMSTATE_UINT32(ssctl[0], stellaris_adc_state),
110
- VMSTATE_UINT32(fifo[1].state, stellaris_adc_state),
111
- VMSTATE_UINT32_ARRAY(fifo[1].data, stellaris_adc_state, 16),
112
- VMSTATE_UINT32(ssmux[1], stellaris_adc_state),
113
- VMSTATE_UINT32(ssctl[1], stellaris_adc_state),
114
- VMSTATE_UINT32(fifo[2].state, stellaris_adc_state),
115
- VMSTATE_UINT32_ARRAY(fifo[2].data, stellaris_adc_state, 16),
116
- VMSTATE_UINT32(ssmux[2], stellaris_adc_state),
117
- VMSTATE_UINT32(ssctl[2], stellaris_adc_state),
118
- VMSTATE_UINT32(fifo[3].state, stellaris_adc_state),
119
- VMSTATE_UINT32_ARRAY(fifo[3].data, stellaris_adc_state, 16),
120
- VMSTATE_UINT32(ssmux[3], stellaris_adc_state),
121
- VMSTATE_UINT32(ssctl[3], stellaris_adc_state),
122
- VMSTATE_UINT32(noise, stellaris_adc_state),
123
+ VMSTATE_UINT32(actss, StellarisADCState),
124
+ VMSTATE_UINT32(ris, StellarisADCState),
125
+ VMSTATE_UINT32(im, StellarisADCState),
126
+ VMSTATE_UINT32(emux, StellarisADCState),
127
+ VMSTATE_UINT32(ostat, StellarisADCState),
128
+ VMSTATE_UINT32(ustat, StellarisADCState),
129
+ VMSTATE_UINT32(sspri, StellarisADCState),
130
+ VMSTATE_UINT32(sac, StellarisADCState),
131
+ VMSTATE_UINT32(fifo[0].state, StellarisADCState),
132
+ VMSTATE_UINT32_ARRAY(fifo[0].data, StellarisADCState, 16),
133
+ VMSTATE_UINT32(ssmux[0], StellarisADCState),
134
+ VMSTATE_UINT32(ssctl[0], StellarisADCState),
135
+ VMSTATE_UINT32(fifo[1].state, StellarisADCState),
136
+ VMSTATE_UINT32_ARRAY(fifo[1].data, StellarisADCState, 16),
137
+ VMSTATE_UINT32(ssmux[1], StellarisADCState),
138
+ VMSTATE_UINT32(ssctl[1], StellarisADCState),
139
+ VMSTATE_UINT32(fifo[2].state, StellarisADCState),
140
+ VMSTATE_UINT32_ARRAY(fifo[2].data, StellarisADCState, 16),
141
+ VMSTATE_UINT32(ssmux[2], StellarisADCState),
142
+ VMSTATE_UINT32(ssctl[2], StellarisADCState),
143
+ VMSTATE_UINT32(fifo[3].state, StellarisADCState),
144
+ VMSTATE_UINT32_ARRAY(fifo[3].data, StellarisADCState, 16),
145
+ VMSTATE_UINT32(ssmux[3], StellarisADCState),
146
+ VMSTATE_UINT32(ssctl[3], StellarisADCState),
147
+ VMSTATE_UINT32(noise, StellarisADCState),
148
VMSTATE_END_OF_LIST()
149
}
150
};
151
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_stellaris_adc = {
152
static void stellaris_adc_init(Object *obj)
153
{
154
DeviceState *dev = DEVICE(obj);
155
- stellaris_adc_state *s = STELLARIS_ADC(obj);
156
+ StellarisADCState *s = STELLARIS_ADC(obj);
157
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
158
int n;
159
160
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_class_init(ObjectClass *klass, void *data)
161
static const TypeInfo stellaris_adc_info = {
162
.name = TYPE_STELLARIS_ADC,
163
.parent = TYPE_SYS_BUS_DEVICE,
164
- .instance_size = sizeof(stellaris_adc_state),
165
+ .instance_size = sizeof(StellarisADCState),
166
.instance_init = stellaris_adc_init,
167
.class_init = stellaris_adc_class_init,
168
};
212
--
169
--
213
2.20.1
170
2.34.1
214
171
215
172
diff view generated by jsdifflib
1
Implement the MVE integer min/max across vector insns
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
VMAXV, VMINV, VMAXAV and VMINAV, which find the maximum
3
from the vector elements and a general purpose register,
4
and store the maximum back into the general purpose
5
register.
6
2
7
These insns overlap with VRMLALDAVH (they use what would
3
The typedef and definitions are generated by the OBJECT_DECLARE_TYPE
8
be RdaHi=0b110).
4
macro in "hw/arm/bcm2836.h":
9
5
6
20 #define TYPE_BCM283X "bcm283x"
7
21 OBJECT_DECLARE_TYPE(BCM283XState, BCM283XClass, BCM283X)
8
9
The script ran in commit a489d1951c ("Use OBJECT_DECLARE_TYPE when
10
possible") missed them because they are declared in a different
11
file unit. Remove them.
12
13
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20230109140306.23161-10-philmd@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
---
17
---
13
target/arm/helper-mve.h | 20 ++++++++++++
18
hw/arm/bcm2836.c | 9 ++-------
14
target/arm/mve.decode | 18 +++++++++--
19
1 file changed, 2 insertions(+), 7 deletions(-)
15
target/arm/mve_helper.c | 66 ++++++++++++++++++++++++++++++++++++++
16
target/arm/translate-mve.c | 48 +++++++++++++++++++++++++++
17
4 files changed, 150 insertions(+), 2 deletions(-)
18
20
19
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
21
diff --git a/hw/arm/bcm2836.c b/hw/arm/bcm2836.c
20
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper-mve.h
23
--- a/hw/arm/bcm2836.c
22
+++ b/target/arm/helper-mve.h
24
+++ b/hw/arm/bcm2836.c
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vaddvuh, TCG_CALL_NO_WG, i32, env, ptr, i32)
24
DEF_HELPER_FLAGS_3(mve_vaddvsw, TCG_CALL_NO_WG, i32, env, ptr, i32)
25
DEF_HELPER_FLAGS_3(mve_vaddvuw, TCG_CALL_NO_WG, i32, env, ptr, i32)
26
27
+DEF_HELPER_FLAGS_3(mve_vmaxvsb, TCG_CALL_NO_WG, i32, env, ptr, i32)
28
+DEF_HELPER_FLAGS_3(mve_vmaxvsh, TCG_CALL_NO_WG, i32, env, ptr, i32)
29
+DEF_HELPER_FLAGS_3(mve_vmaxvsw, TCG_CALL_NO_WG, i32, env, ptr, i32)
30
+DEF_HELPER_FLAGS_3(mve_vmaxvub, TCG_CALL_NO_WG, i32, env, ptr, i32)
31
+DEF_HELPER_FLAGS_3(mve_vmaxvuh, TCG_CALL_NO_WG, i32, env, ptr, i32)
32
+DEF_HELPER_FLAGS_3(mve_vmaxvuw, TCG_CALL_NO_WG, i32, env, ptr, i32)
33
+DEF_HELPER_FLAGS_3(mve_vmaxavb, TCG_CALL_NO_WG, i32, env, ptr, i32)
34
+DEF_HELPER_FLAGS_3(mve_vmaxavh, TCG_CALL_NO_WG, i32, env, ptr, i32)
35
+DEF_HELPER_FLAGS_3(mve_vmaxavw, TCG_CALL_NO_WG, i32, env, ptr, i32)
36
+
37
+DEF_HELPER_FLAGS_3(mve_vminvsb, TCG_CALL_NO_WG, i32, env, ptr, i32)
38
+DEF_HELPER_FLAGS_3(mve_vminvsh, TCG_CALL_NO_WG, i32, env, ptr, i32)
39
+DEF_HELPER_FLAGS_3(mve_vminvsw, TCG_CALL_NO_WG, i32, env, ptr, i32)
40
+DEF_HELPER_FLAGS_3(mve_vminvub, TCG_CALL_NO_WG, i32, env, ptr, i32)
41
+DEF_HELPER_FLAGS_3(mve_vminvuh, TCG_CALL_NO_WG, i32, env, ptr, i32)
42
+DEF_HELPER_FLAGS_3(mve_vminvuw, TCG_CALL_NO_WG, i32, env, ptr, i32)
43
+DEF_HELPER_FLAGS_3(mve_vminavb, TCG_CALL_NO_WG, i32, env, ptr, i32)
44
+DEF_HELPER_FLAGS_3(mve_vminavh, TCG_CALL_NO_WG, i32, env, ptr, i32)
45
+DEF_HELPER_FLAGS_3(mve_vminavw, TCG_CALL_NO_WG, i32, env, ptr, i32)
46
+
47
DEF_HELPER_FLAGS_3(mve_vaddlv_s, TCG_CALL_NO_WG, i64, env, ptr, i64)
48
DEF_HELPER_FLAGS_3(mve_vaddlv_u, TCG_CALL_NO_WG, i64, env, ptr, i64)
49
50
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/mve.decode
53
+++ b/target/arm/mve.decode
54
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@
55
&vcmp qm qn size mask
26
#include "hw/arm/raspi_platform.h"
56
&vcmp_scalar qn rm size mask
27
#include "hw/sysbus.h"
57
&shl_scalar qda rm size
28
58
+&vmaxv qm rda size
29
-typedef struct BCM283XClass {
59
30
+struct BCM283XClass {
60
@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
31
/*< private >*/
61
# Note that both Rn and Qd are 3 bits only (no D bit)
32
DeviceClass parent_class;
62
@@ -XXX,XX +XXX,XX @@
33
/*< public >*/
63
@vcmp_scalar .... .... .. size:2 qn:3 . .... .... .... rm:4 &vcmp_scalar \
34
@@ -XXX,XX +XXX,XX @@ typedef struct BCM283XClass {
64
mask=%mask_22_13
35
hwaddr peri_base; /* Peripheral base address seen by the CPU */
65
36
hwaddr ctrl_base; /* Interrupt controller and mailboxes etc. */
66
+@vmaxv .... .... .... size:2 .. rda:4 .... .... .... &vmaxv qm=%qm
37
int clusterid;
67
+
38
-} BCM283XClass;
68
# Vector loads and stores
39
-
69
40
-#define BCM283X_CLASS(klass) \
70
# Widening loads and narrowing stores:
41
- OBJECT_CLASS_CHECK(BCM283XClass, (klass), TYPE_BCM283X)
71
@@ -XXX,XX +XXX,XX @@ VMLALDAV_U 1111 1110 1 ... ... . ... . 1110 . 0 . 0 ... 0 @vmlaldav
42
-#define BCM283X_GET_CLASS(obj) \
72
43
- OBJECT_GET_CLASS(BCM283XClass, (obj), TYPE_BCM283X)
73
VMLSLDAV 1110 1110 1 ... ... . ... . 1110 . 0 . 0 ... 1 @vmlaldav
44
+};
74
45
75
-VRMLALDAVH_S 1110 1110 1 ... ... 0 ... . 1111 . 0 . 0 ... 0 @vmlaldav_nosz
46
static Property bcm2836_enabled_cores_property =
76
-VRMLALDAVH_U 1111 1110 1 ... ... 0 ... . 1111 . 0 . 0 ... 0 @vmlaldav_nosz
47
DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus, 0);
77
+{
78
+ VMAXV_S 1110 1110 1110 .. 10 .... 1111 0 0 . 0 ... 0 @vmaxv
79
+ VMINV_S 1110 1110 1110 .. 10 .... 1111 1 0 . 0 ... 0 @vmaxv
80
+ VMAXAV 1110 1110 1110 .. 00 .... 1111 0 0 . 0 ... 0 @vmaxv
81
+ VMINAV 1110 1110 1110 .. 00 .... 1111 1 0 . 0 ... 0 @vmaxv
82
+ VRMLALDAVH_S 1110 1110 1 ... ... 0 ... . 1111 . 0 . 0 ... 0 @vmlaldav_nosz
83
+}
84
+
85
+{
86
+ VMAXV_U 1111 1110 1110 .. 10 .... 1111 0 0 . 0 ... 0 @vmaxv
87
+ VMINV_U 1111 1110 1110 .. 10 .... 1111 1 0 . 0 ... 0 @vmaxv
88
+ VRMLALDAVH_U 1111 1110 1 ... ... 0 ... . 1111 . 0 . 0 ... 0 @vmlaldav_nosz
89
+}
90
91
VRMLSLDAVH 1111 1110 1 ... ... 0 ... . 1110 . 0 . 0 ... 1 @vmlaldav_nosz
92
93
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/target/arm/mve_helper.c
96
+++ b/target/arm/mve_helper.c
97
@@ -XXX,XX +XXX,XX @@ DO_VADDV(vaddvub, 1, uint8_t)
98
DO_VADDV(vaddvuh, 2, uint16_t)
99
DO_VADDV(vaddvuw, 4, uint32_t)
100
101
+/*
102
+ * Vector max/min across vector. Unlike VADDV, we must
103
+ * read ra as the element size, not its full width.
104
+ * We work with int64_t internally for simplicity.
105
+ */
106
+#define DO_VMAXMINV(OP, ESIZE, TYPE, RATYPE, FN) \
107
+ uint32_t HELPER(glue(mve_, OP))(CPUARMState *env, void *vm, \
108
+ uint32_t ra_in) \
109
+ { \
110
+ uint16_t mask = mve_element_mask(env); \
111
+ unsigned e; \
112
+ TYPE *m = vm; \
113
+ int64_t ra = (RATYPE)ra_in; \
114
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
115
+ if (mask & 1) { \
116
+ ra = FN(ra, m[H##ESIZE(e)]); \
117
+ } \
118
+ } \
119
+ mve_advance_vpt(env); \
120
+ return ra; \
121
+ } \
122
+
123
+#define DO_VMAXMINV_U(INSN, FN) \
124
+ DO_VMAXMINV(INSN##b, 1, uint8_t, uint8_t, FN) \
125
+ DO_VMAXMINV(INSN##h, 2, uint16_t, uint16_t, FN) \
126
+ DO_VMAXMINV(INSN##w, 4, uint32_t, uint32_t, FN)
127
+#define DO_VMAXMINV_S(INSN, FN) \
128
+ DO_VMAXMINV(INSN##b, 1, int8_t, int8_t, FN) \
129
+ DO_VMAXMINV(INSN##h, 2, int16_t, int16_t, FN) \
130
+ DO_VMAXMINV(INSN##w, 4, int32_t, int32_t, FN)
131
+
132
+/*
133
+ * Helpers for max and min of absolute values across vector:
134
+ * note that we only take the absolute value of 'm', not 'n'
135
+ */
136
+static int64_t do_maxa(int64_t n, int64_t m)
137
+{
138
+ if (m < 0) {
139
+ m = -m;
140
+ }
141
+ return MAX(n, m);
142
+}
143
+
144
+static int64_t do_mina(int64_t n, int64_t m)
145
+{
146
+ if (m < 0) {
147
+ m = -m;
148
+ }
149
+ return MIN(n, m);
150
+}
151
+
152
+DO_VMAXMINV_S(vmaxvs, DO_MAX)
153
+DO_VMAXMINV_U(vmaxvu, DO_MAX)
154
+DO_VMAXMINV_S(vminvs, DO_MIN)
155
+DO_VMAXMINV_U(vminvu, DO_MIN)
156
+/*
157
+ * VMAXAV, VMINAV treat the general purpose input as unsigned
158
+ * and the vector elements as signed.
159
+ */
160
+DO_VMAXMINV(vmaxavb, 1, int8_t, uint8_t, do_maxa)
161
+DO_VMAXMINV(vmaxavh, 2, int16_t, uint16_t, do_maxa)
162
+DO_VMAXMINV(vmaxavw, 4, int32_t, uint32_t, do_maxa)
163
+DO_VMAXMINV(vminavb, 1, int8_t, uint8_t, do_mina)
164
+DO_VMAXMINV(vminavh, 2, int16_t, uint16_t, do_mina)
165
+DO_VMAXMINV(vminavw, 4, int32_t, uint32_t, do_mina)
166
+
167
#define DO_VADDLV(OP, TYPE, LTYPE) \
168
uint64_t HELPER(glue(mve_, OP))(CPUARMState *env, void *vm, \
169
uint64_t ra) \
170
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
171
index XXXXXXX..XXXXXXX 100644
172
--- a/target/arm/translate-mve.c
173
+++ b/target/arm/translate-mve.c
174
@@ -XXX,XX +XXX,XX @@ DO_VCMP(VCMPGE, vcmpge)
175
DO_VCMP(VCMPLT, vcmplt)
176
DO_VCMP(VCMPGT, vcmpgt)
177
DO_VCMP(VCMPLE, vcmple)
178
+
179
+static bool do_vmaxv(DisasContext *s, arg_vmaxv *a, MVEGenVADDVFn fn)
180
+{
181
+ /*
182
+ * MIN/MAX operations across a vector: compute the min or
183
+ * max of the initial value in a general purpose register
184
+ * and all the elements in the vector, and store it back
185
+ * into the general purpose register.
186
+ */
187
+ TCGv_ptr qm;
188
+ TCGv_i32 rda;
189
+
190
+ if (!dc_isar_feature(aa32_mve, s) || !mve_check_qreg_bank(s, a->qm) ||
191
+ !fn || a->rda == 13 || a->rda == 15) {
192
+ /* Rda cases are UNPREDICTABLE */
193
+ return false;
194
+ }
195
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
196
+ return true;
197
+ }
198
+
199
+ qm = mve_qreg_ptr(a->qm);
200
+ rda = load_reg(s, a->rda);
201
+ fn(rda, cpu_env, qm, rda);
202
+ store_reg(s, a->rda, rda);
203
+ tcg_temp_free_ptr(qm);
204
+ mve_update_eci(s);
205
+ return true;
206
+}
207
+
208
+#define DO_VMAXV(INSN, FN) \
209
+ static bool trans_##INSN(DisasContext *s, arg_vmaxv *a) \
210
+ { \
211
+ static MVEGenVADDVFn * const fns[] = { \
212
+ gen_helper_mve_##FN##b, \
213
+ gen_helper_mve_##FN##h, \
214
+ gen_helper_mve_##FN##w, \
215
+ NULL, \
216
+ }; \
217
+ return do_vmaxv(s, a, fns[a->size]); \
218
+ }
219
+
220
+DO_VMAXV(VMAXV_S, vmaxvs)
221
+DO_VMAXV(VMAXV_U, vmaxvu)
222
+DO_VMAXV(VMAXAV, vmaxav)
223
+DO_VMAXV(VMINV_S, vminvs)
224
+DO_VMAXV(VMINV_U, vminvu)
225
+DO_VMAXV(VMINAV, vminav)
226
--
48
--
227
2.20.1
49
2.34.1
228
50
229
51
diff view generated by jsdifflib
1
Implement the MVE instructions which perform shifts by a scalar.
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
These are VSHL T2, VRSHL T2, VQSHL T1 and VQRSHL T2. They take the
2
3
shift amount in a general purpose register and shift every element in
3
NPCM7XX models have been commited after the conversion from
4
the vector by that amount.
4
commit 8063396bf3 ("Use OBJECT_DECLARE_SIMPLE_TYPE when possible").
5
5
Manually convert them.
6
Mostly we can reuse the helper functions for shift-by-immediate; we
6
7
do need two new helpers for VQRSHL.
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230109140306.23161-11-philmd@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
---
11
---
12
target/arm/helper-mve.h | 8 +++++++
12
include/hw/adc/npcm7xx_adc.h | 7 +++----
13
target/arm/mve.decode | 23 ++++++++++++++++---
13
include/hw/arm/npcm7xx.h | 18 ++++++------------
14
target/arm/mve_helper.c | 2 ++
14
include/hw/i2c/npcm7xx_smbus.h | 7 +++----
15
target/arm/translate-mve.c | 46 ++++++++++++++++++++++++++++++++++++++
15
include/hw/misc/npcm7xx_clk.h | 2 +-
16
4 files changed, 76 insertions(+), 3 deletions(-)
16
include/hw/misc/npcm7xx_gcr.h | 6 +++---
17
17
include/hw/misc/npcm7xx_mft.h | 7 +++----
18
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
18
include/hw/misc/npcm7xx_pwm.h | 3 +--
19
index XXXXXXX..XXXXXXX 100644
19
include/hw/misc/npcm7xx_rng.h | 6 +++---
20
--- a/target/arm/helper-mve.h
20
include/hw/net/npcm7xx_emc.h | 5 +----
21
+++ b/target/arm/helper-mve.h
21
include/hw/sd/npcm7xx_sdhci.h | 4 ++--
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vrshli_ub, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
22
10 files changed, 26 insertions(+), 39 deletions(-)
23
DEF_HELPER_FLAGS_4(mve_vrshli_uh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
23
24
DEF_HELPER_FLAGS_4(mve_vrshli_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
diff --git a/include/hw/adc/npcm7xx_adc.h b/include/hw/adc/npcm7xx_adc.h
25
25
index XXXXXXX..XXXXXXX 100644
26
+DEF_HELPER_FLAGS_4(mve_vqrshli_sb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
26
--- a/include/hw/adc/npcm7xx_adc.h
27
+DEF_HELPER_FLAGS_4(mve_vqrshli_sh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
27
+++ b/include/hw/adc/npcm7xx_adc.h
28
+DEF_HELPER_FLAGS_4(mve_vqrshli_sw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
28
@@ -XXX,XX +XXX,XX @@
29
+
29
* @iref: The internal reference voltage, initialized at launch time.
30
+DEF_HELPER_FLAGS_4(mve_vqrshli_ub, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
30
* @rv: The calibrated output values of 0.5V and 1.5V for the ADC.
31
+DEF_HELPER_FLAGS_4(mve_vqrshli_uh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
*/
32
+DEF_HELPER_FLAGS_4(mve_vqrshli_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
32
-typedef struct {
33
+
33
+struct NPCM7xxADCState {
34
DEF_HELPER_FLAGS_4(mve_vshllbsb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
34
SysBusDevice parent;
35
DEF_HELPER_FLAGS_4(mve_vshllbsh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
35
36
DEF_HELPER_FLAGS_4(mve_vshllbub, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
36
MemoryRegion iomem;
37
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
37
@@ -XXX,XX +XXX,XX @@ typedef struct {
38
index XXXXXXX..XXXXXXX 100644
38
uint32_t iref;
39
--- a/target/arm/mve.decode
39
40
+++ b/target/arm/mve.decode
40
uint16_t calibration_r_values[NPCM7XX_ADC_NUM_CALIB];
41
@@ -XXX,XX +XXX,XX @@
41
-} NPCM7xxADCState;
42
&viwdup qd rn rm size imm
42
+};
43
&vcmp qm qn size mask
43
44
&vcmp_scalar qn rm size mask
44
#define TYPE_NPCM7XX_ADC "npcm7xx-adc"
45
+&shl_scalar qda rm size
45
-#define NPCM7XX_ADC(obj) \
46
46
- OBJECT_CHECK(NPCM7xxADCState, (obj), TYPE_NPCM7XX_ADC)
47
@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
47
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxADCState, NPCM7XX_ADC)
48
# Note that both Rn and Qd are 3 bits only (no D bit)
48
49
@@ -XXX,XX +XXX,XX @@
49
#endif /* NPCM7XX_ADC_H */
50
@2_shr_w .... .... .. 1 ..... .... .... .... .... &2shift qd=%qd qm=%qm \
50
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
51
size=2 shift=%rshift_i5
51
index XXXXXXX..XXXXXXX 100644
52
52
--- a/include/hw/arm/npcm7xx.h
53
+@shl_scalar .... .... .... size:2 .. .... .... .... rm:4 &shl_scalar qda=%qd
53
+++ b/include/hw/arm/npcm7xx.h
54
+
54
@@ -XXX,XX +XXX,XX @@
55
# Vector comparison; 4-bit Qm but 3-bit Qn
55
56
%mask_22_13 22:1 13:3
56
#define NPCM7XX_NR_PWM_MODULES 2
57
@vcmp .... .... .. size:2 qn:3 . .... .... .... .... &vcmp qm=%qm mask=%mask_22_13
57
58
@@ -XXX,XX +XXX,XX @@ VRMLSLDAVH 1111 1110 1 ... ... 0 ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav_no
58
-typedef struct NPCM7xxMachine {
59
59
+struct NPCM7xxMachine {
60
VADD_scalar 1110 1110 0 . .. ... 1 ... 0 1111 . 100 .... @2scalar
60
MachineState parent;
61
VSUB_scalar 1110 1110 0 . .. ... 1 ... 1 1111 . 100 .... @2scalar
61
/*
62
-VMUL_scalar 1110 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
62
* PWM fan splitter. each splitter connects to one PWM output and
63
+
63
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxMachine {
64
+{
64
*/
65
+ VSHL_S_scalar 1110 1110 0 . 11 .. 01 ... 1 1110 0110 .... @shl_scalar
65
SplitIRQ fan_splitter[NPCM7XX_NR_PWM_MODULES *
66
+ VRSHL_S_scalar 1110 1110 0 . 11 .. 11 ... 1 1110 0110 .... @shl_scalar
66
NPCM7XX_PWM_PER_MODULE];
67
+ VQSHL_S_scalar 1110 1110 0 . 11 .. 01 ... 1 1110 1110 .... @shl_scalar
67
-} NPCM7xxMachine;
68
+ VQRSHL_S_scalar 1110 1110 0 . 11 .. 11 ... 1 1110 1110 .... @shl_scalar
68
+};
69
+ VMUL_scalar 1110 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
69
70
+}
70
#define TYPE_NPCM7XX_MACHINE MACHINE_TYPE_NAME("npcm7xx")
71
+
71
-#define NPCM7XX_MACHINE(obj) \
72
+{
72
- OBJECT_CHECK(NPCM7xxMachine, (obj), TYPE_NPCM7XX_MACHINE)
73
+ VSHL_U_scalar 1111 1110 0 . 11 .. 01 ... 1 1110 0110 .... @shl_scalar
73
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxMachine, NPCM7XX_MACHINE)
74
+ VRSHL_U_scalar 1111 1110 0 . 11 .. 11 ... 1 1110 0110 .... @shl_scalar
74
75
+ VQSHL_U_scalar 1111 1110 0 . 11 .. 01 ... 1 1110 1110 .... @shl_scalar
75
typedef struct NPCM7xxMachineClass {
76
+ VQRSHL_U_scalar 1111 1110 0 . 11 .. 11 ... 1 1110 1110 .... @shl_scalar
76
MachineClass parent;
77
+ VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
77
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxMachineClass {
78
+}
78
#define NPCM7XX_MACHINE_GET_CLASS(obj) \
79
+
79
OBJECT_GET_CLASS(NPCM7xxMachineClass, (obj), TYPE_NPCM7XX_MACHINE)
80
VHADD_S_scalar 1110 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
80
81
VHADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
81
-typedef struct NPCM7xxState {
82
VHSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
82
+struct NPCM7xxState {
83
@@ -XXX,XX +XXX,XX @@ VHSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
83
DeviceState parent;
84
size=%size_28
84
85
}
85
ARMCPU cpu[NPCM7XX_MAX_NUM_CPUS];
86
86
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
87
-VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
87
NPCM7xxFIUState fiu[2];
88
NPCM7xxEMCState emc[2];
89
NPCM7xxSDHCIState mmc;
90
-} NPCM7xxState;
91
+};
92
93
#define TYPE_NPCM7XX "npcm7xx"
94
-#define NPCM7XX(obj) OBJECT_CHECK(NPCM7xxState, (obj), TYPE_NPCM7XX)
95
+OBJECT_DECLARE_TYPE(NPCM7xxState, NPCM7xxClass, NPCM7XX)
96
97
#define TYPE_NPCM730 "npcm730"
98
#define TYPE_NPCM750 "npcm750"
99
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxClass {
100
uint32_t num_cpus;
101
} NPCM7xxClass;
102
103
-#define NPCM7XX_CLASS(klass) \
104
- OBJECT_CLASS_CHECK(NPCM7xxClass, (klass), TYPE_NPCM7XX)
105
-#define NPCM7XX_GET_CLASS(obj) \
106
- OBJECT_GET_CLASS(NPCM7xxClass, (obj), TYPE_NPCM7XX)
88
-
107
-
89
VQDMULH_scalar 1110 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
108
/**
90
VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
109
* npcm7xx_load_kernel - Loads memory with everything needed to boot
91
110
* @machine - The machine containing the SoC to be booted.
92
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
111
diff --git a/include/hw/i2c/npcm7xx_smbus.h b/include/hw/i2c/npcm7xx_smbus.h
93
index XXXXXXX..XXXXXXX 100644
112
index XXXXXXX..XXXXXXX 100644
94
--- a/target/arm/mve_helper.c
113
--- a/include/hw/i2c/npcm7xx_smbus.h
95
+++ b/target/arm/mve_helper.c
114
+++ b/include/hw/i2c/npcm7xx_smbus.h
96
@@ -XXX,XX +XXX,XX @@ DO_2SHIFT_SAT_S(vqshli_s, DO_SQSHL_OP)
115
@@ -XXX,XX +XXX,XX @@ typedef enum NPCM7xxSMBusStatus {
97
DO_2SHIFT_SAT_S(vqshlui_s, DO_SUQSHL_OP)
116
* @rx_cur: The current position of rx_fifo.
98
DO_2SHIFT_U(vrshli_u, DO_VRSHLU)
117
* @status: The current status of the SMBus.
99
DO_2SHIFT_S(vrshli_s, DO_VRSHLS)
118
*/
100
+DO_2SHIFT_SAT_U(vqrshli_u, DO_UQRSHL_OP)
119
-typedef struct NPCM7xxSMBusState {
101
+DO_2SHIFT_SAT_S(vqrshli_s, DO_SQRSHL_OP)
120
+struct NPCM7xxSMBusState {
102
121
SysBusDevice parent;
103
/* Shift-and-insert; we always work with 64 bits at a time */
122
104
#define DO_2SHIFT_INSERT(OP, ESIZE, SHIFTFN, MASKFN) \
123
MemoryRegion iomem;
105
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
124
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxSMBusState {
106
index XXXXXXX..XXXXXXX 100644
125
uint8_t rx_cur;
107
--- a/target/arm/translate-mve.c
126
108
+++ b/target/arm/translate-mve.c
127
NPCM7xxSMBusStatus status;
109
@@ -XXX,XX +XXX,XX @@ DO_2SHIFT(VRSHRI_U, vrshli_u, true)
128
-} NPCM7xxSMBusState;
110
DO_2SHIFT(VSRI, vsri, false)
129
+};
111
DO_2SHIFT(VSLI, vsli, false)
130
112
131
#define TYPE_NPCM7XX_SMBUS "npcm7xx-smbus"
113
+static bool do_2shift_scalar(DisasContext *s, arg_shl_scalar *a,
132
-#define NPCM7XX_SMBUS(obj) OBJECT_CHECK(NPCM7xxSMBusState, (obj), \
114
+ MVEGenTwoOpShiftFn *fn)
133
- TYPE_NPCM7XX_SMBUS)
115
+{
134
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxSMBusState, NPCM7XX_SMBUS)
116
+ TCGv_ptr qda;
135
117
+ TCGv_i32 rm;
136
#endif /* NPCM7XX_SMBUS_H */
118
+
137
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
119
+ if (!dc_isar_feature(aa32_mve, s) ||
138
index XXXXXXX..XXXXXXX 100644
120
+ !mve_check_qreg_bank(s, a->qda) ||
139
--- a/include/hw/misc/npcm7xx_clk.h
121
+ a->rm == 13 || a->rm == 15 || !fn) {
140
+++ b/include/hw/misc/npcm7xx_clk.h
122
+ /* Rm cases are UNPREDICTABLE */
141
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxCLKState {
123
+ return false;
142
};
124
+ }
143
125
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
144
#define TYPE_NPCM7XX_CLK "npcm7xx-clk"
126
+ return true;
145
-#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_NPCM7XX_CLK)
127
+ }
146
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxCLKState, NPCM7XX_CLK)
128
+
147
129
+ qda = mve_qreg_ptr(a->qda);
148
#endif /* NPCM7XX_CLK_H */
130
+ rm = load_reg(s, a->rm);
149
diff --git a/include/hw/misc/npcm7xx_gcr.h b/include/hw/misc/npcm7xx_gcr.h
131
+ fn(cpu_env, qda, qda, rm);
150
index XXXXXXX..XXXXXXX 100644
132
+ tcg_temp_free_ptr(qda);
151
--- a/include/hw/misc/npcm7xx_gcr.h
133
+ tcg_temp_free_i32(rm);
152
+++ b/include/hw/misc/npcm7xx_gcr.h
134
+ mve_update_eci(s);
153
@@ -XXX,XX +XXX,XX @@
135
+ return true;
154
*/
136
+}
155
#define NPCM7XX_GCR_NR_REGS (0x148 / sizeof(uint32_t))
137
+
156
138
+#define DO_2SHIFT_SCALAR(INSN, FN) \
157
-typedef struct NPCM7xxGCRState {
139
+ static bool trans_##INSN(DisasContext *s, arg_shl_scalar *a) \
158
+struct NPCM7xxGCRState {
140
+ { \
159
SysBusDevice parent;
141
+ static MVEGenTwoOpShiftFn * const fns[] = { \
160
142
+ gen_helper_mve_##FN##b, \
161
MemoryRegion iomem;
143
+ gen_helper_mve_##FN##h, \
162
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxGCRState {
144
+ gen_helper_mve_##FN##w, \
163
uint32_t reset_pwron;
145
+ NULL, \
164
uint32_t reset_mdlr;
146
+ }; \
165
uint32_t reset_intcr3;
147
+ return do_2shift_scalar(s, a, fns[a->size]); \
166
-} NPCM7xxGCRState;
148
+ }
167
+};
149
+
168
150
+DO_2SHIFT_SCALAR(VSHL_S_scalar, vshli_s)
169
#define TYPE_NPCM7XX_GCR "npcm7xx-gcr"
151
+DO_2SHIFT_SCALAR(VSHL_U_scalar, vshli_u)
170
-#define NPCM7XX_GCR(obj) OBJECT_CHECK(NPCM7xxGCRState, (obj), TYPE_NPCM7XX_GCR)
152
+DO_2SHIFT_SCALAR(VRSHL_S_scalar, vrshli_s)
171
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxGCRState, NPCM7XX_GCR)
153
+DO_2SHIFT_SCALAR(VRSHL_U_scalar, vrshli_u)
172
154
+DO_2SHIFT_SCALAR(VQSHL_S_scalar, vqshli_s)
173
#endif /* NPCM7XX_GCR_H */
155
+DO_2SHIFT_SCALAR(VQSHL_U_scalar, vqshli_u)
174
diff --git a/include/hw/misc/npcm7xx_mft.h b/include/hw/misc/npcm7xx_mft.h
156
+DO_2SHIFT_SCALAR(VQRSHL_S_scalar, vqrshli_s)
175
index XXXXXXX..XXXXXXX 100644
157
+DO_2SHIFT_SCALAR(VQRSHL_U_scalar, vqrshli_u)
176
--- a/include/hw/misc/npcm7xx_mft.h
158
+
177
+++ b/include/hw/misc/npcm7xx_mft.h
159
#define DO_VSHLL(INSN, FN) \
178
@@ -XXX,XX +XXX,XX @@
160
static bool trans_##INSN(DisasContext *s, arg_2shift *a) \
179
* @max_rpm: The maximum rpm for fans. Order: A0, B0, A1, B1.
161
{ \
180
* @duty: The duty cycles for fans, relative to NPCM7XX_PWM_MAX_DUTY.
181
*/
182
-typedef struct NPCM7xxMFTState {
183
+struct NPCM7xxMFTState {
184
SysBusDevice parent;
185
186
MemoryRegion iomem;
187
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxMFTState {
188
189
uint32_t max_rpm[NPCM7XX_MFT_FANIN_COUNT];
190
uint32_t duty[NPCM7XX_MFT_FANIN_COUNT];
191
-} NPCM7xxMFTState;
192
+};
193
194
#define TYPE_NPCM7XX_MFT "npcm7xx-mft"
195
-#define NPCM7XX_MFT(obj) \
196
- OBJECT_CHECK(NPCM7xxMFTState, (obj), TYPE_NPCM7XX_MFT)
197
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxMFTState, NPCM7XX_MFT)
198
199
#endif /* NPCM7XX_MFT_H */
200
diff --git a/include/hw/misc/npcm7xx_pwm.h b/include/hw/misc/npcm7xx_pwm.h
201
index XXXXXXX..XXXXXXX 100644
202
--- a/include/hw/misc/npcm7xx_pwm.h
203
+++ b/include/hw/misc/npcm7xx_pwm.h
204
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxPWMState {
205
};
206
207
#define TYPE_NPCM7XX_PWM "npcm7xx-pwm"
208
-#define NPCM7XX_PWM(obj) \
209
- OBJECT_CHECK(NPCM7xxPWMState, (obj), TYPE_NPCM7XX_PWM)
210
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxPWMState, NPCM7XX_PWM)
211
212
#endif /* NPCM7XX_PWM_H */
213
diff --git a/include/hw/misc/npcm7xx_rng.h b/include/hw/misc/npcm7xx_rng.h
214
index XXXXXXX..XXXXXXX 100644
215
--- a/include/hw/misc/npcm7xx_rng.h
216
+++ b/include/hw/misc/npcm7xx_rng.h
217
@@ -XXX,XX +XXX,XX @@
218
219
#include "hw/sysbus.h"
220
221
-typedef struct NPCM7xxRNGState {
222
+struct NPCM7xxRNGState {
223
SysBusDevice parent;
224
225
MemoryRegion iomem;
226
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxRNGState {
227
uint8_t rngcs;
228
uint8_t rngd;
229
uint8_t rngmode;
230
-} NPCM7xxRNGState;
231
+};
232
233
#define TYPE_NPCM7XX_RNG "npcm7xx-rng"
234
-#define NPCM7XX_RNG(obj) OBJECT_CHECK(NPCM7xxRNGState, (obj), TYPE_NPCM7XX_RNG)
235
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxRNGState, NPCM7XX_RNG)
236
237
#endif /* NPCM7XX_RNG_H */
238
diff --git a/include/hw/net/npcm7xx_emc.h b/include/hw/net/npcm7xx_emc.h
239
index XXXXXXX..XXXXXXX 100644
240
--- a/include/hw/net/npcm7xx_emc.h
241
+++ b/include/hw/net/npcm7xx_emc.h
242
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxEMCState {
243
bool rx_active;
244
};
245
246
-typedef struct NPCM7xxEMCState NPCM7xxEMCState;
247
-
248
#define TYPE_NPCM7XX_EMC "npcm7xx-emc"
249
-#define NPCM7XX_EMC(obj) \
250
- OBJECT_CHECK(NPCM7xxEMCState, (obj), TYPE_NPCM7XX_EMC)
251
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxEMCState, NPCM7XX_EMC)
252
253
#endif /* NPCM7XX_EMC_H */
254
diff --git a/include/hw/sd/npcm7xx_sdhci.h b/include/hw/sd/npcm7xx_sdhci.h
255
index XXXXXXX..XXXXXXX 100644
256
--- a/include/hw/sd/npcm7xx_sdhci.h
257
+++ b/include/hw/sd/npcm7xx_sdhci.h
258
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxRegs {
259
uint32_t boottoctrl;
260
} NPCM7xxRegisters;
261
262
-typedef struct NPCM7xxSDHCIState {
263
+struct NPCM7xxSDHCIState {
264
SysBusDevice parent;
265
266
MemoryRegion container;
267
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxSDHCIState {
268
NPCM7xxRegisters regs;
269
270
SDHCIState sdhci;
271
-} NPCM7xxSDHCIState;
272
+};
273
274
#endif /* NPCM7XX_SDHCI_H */
162
--
275
--
163
2.20.1
276
2.34.1
164
277
165
278
diff view generated by jsdifflib
1
Implement the MVE VMULL (polynomial) insn. Unlike Neon, this comes
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
in two flavours: 8x8->16 and a 16x16->32. Also unlike Neon, the
3
inputs are in either the low or the high half of each double-width
4
element.
5
2
6
The assembler for this insn indicates the size with "P8" or "P16",
3
The structure is named SECUREECState. Rename the type accordingly.
7
encoded into bit 28 as size = 0 or 1. We choose to follow the
8
same encoding as VQDMULL and decode this into a->size as MO_16
9
or MO_32 indicating the size of the result elements. This then
10
carries through to the helper function names where it then
11
matches up with the existing pmull_h() which does an 8x8->16
12
operation and a new pmull_w() which does the 16x16->32.
13
4
5
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20230109140306.23161-12-philmd@linaro.org
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>
16
---
9
---
17
target/arm/helper-mve.h | 5 +++++
10
hw/misc/sbsa_ec.c | 13 +++++++------
18
target/arm/vec_internal.h | 11 +++++++++++
11
1 file changed, 7 insertions(+), 6 deletions(-)
19
target/arm/mve.decode | 14 ++++++++++----
20
target/arm/mve_helper.c | 16 ++++++++++++++++
21
target/arm/translate-mve.c | 28 ++++++++++++++++++++++++++++
22
target/arm/vec_helper.c | 14 +++++++++++++-
23
6 files changed, 83 insertions(+), 5 deletions(-)
24
12
25
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
13
diff --git a/hw/misc/sbsa_ec.c b/hw/misc/sbsa_ec.c
26
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/helper-mve.h
15
--- a/hw/misc/sbsa_ec.c
28
+++ b/target/arm/helper-mve.h
16
+++ b/hw/misc/sbsa_ec.c
29
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmulltub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
17
@@ -XXX,XX +XXX,XX @@
30
DEF_HELPER_FLAGS_4(mve_vmulltuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
18
#include "hw/sysbus.h"
31
DEF_HELPER_FLAGS_4(mve_vmulltuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
#include "sysemu/runstate.h"
32
20
33
+DEF_HELPER_FLAGS_4(mve_vmullpbh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
-typedef struct {
34
+DEF_HELPER_FLAGS_4(mve_vmullpth, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
+typedef struct SECUREECState {
35
+DEF_HELPER_FLAGS_4(mve_vmullpbw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
SysBusDevice parent_obj;
36
+DEF_HELPER_FLAGS_4(mve_vmullptw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
MemoryRegion iomem;
37
+
25
} SECUREECState;
38
DEF_HELPER_FLAGS_4(mve_vqdmulhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
39
DEF_HELPER_FLAGS_4(mve_vqdmulhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
-#define TYPE_SBSA_EC "sbsa-ec"
40
DEF_HELPER_FLAGS_4(mve_vqdmulhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
-#define SECURE_EC(obj) OBJECT_CHECK(SECUREECState, (obj), TYPE_SBSA_EC)
41
diff --git a/target/arm/vec_internal.h b/target/arm/vec_internal.h
29
+#define TYPE_SBSA_SECURE_EC "sbsa-ec"
42
index XXXXXXX..XXXXXXX 100644
30
+#define SBSA_SECURE_EC(obj) \
43
--- a/target/arm/vec_internal.h
31
+ OBJECT_CHECK(SECUREECState, (obj), TYPE_SBSA_SECURE_EC)
44
+++ b/target/arm/vec_internal.h
32
45
@@ -XXX,XX +XXX,XX @@ int16_t do_sqrdmlah_h(int16_t, int16_t, int16_t, bool, bool, uint32_t *);
33
enum sbsa_ec_powerstates {
46
int32_t do_sqrdmlah_s(int32_t, int32_t, int32_t, bool, bool, uint32_t *);
34
SBSA_EC_CMD_POWEROFF = 0x01,
47
int64_t do_sqrdmlah_d(int64_t, int64_t, int64_t, bool, bool);
35
@@ -XXX,XX +XXX,XX @@ static uint64_t sbsa_ec_read(void *opaque, hwaddr offset, unsigned size)
48
49
+/*
50
+ * 8 x 8 -> 16 vector polynomial multiply where the inputs are
51
+ * in the low 8 bits of each 16-bit element
52
+*/
53
+uint64_t pmull_h(uint64_t op1, uint64_t op2);
54
+/*
55
+ * 16 x 16 -> 32 vector polynomial multiply where the inputs are
56
+ * in the low 16 bits of each 32-bit element
57
+ */
58
+uint64_t pmull_w(uint64_t op1, uint64_t op2);
59
+
60
#endif /* TARGET_ARM_VEC_INTERNALS_H */
61
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
62
index XXXXXXX..XXXXXXX 100644
63
--- a/target/arm/mve.decode
64
+++ b/target/arm/mve.decode
65
@@ -XXX,XX +XXX,XX @@ VHADD_U 111 1 1111 0 . .. ... 0 ... 0 0000 . 1 . 0 ... 0 @2op
66
VHSUB_S 111 0 1111 0 . .. ... 0 ... 0 0010 . 1 . 0 ... 0 @2op
67
VHSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 0 ... 0 @2op
68
69
-VMULL_BS 111 0 1110 0 . .. ... 1 ... 0 1110 . 0 . 0 ... 0 @2op
70
-VMULL_BU 111 1 1110 0 . .. ... 1 ... 0 1110 . 0 . 0 ... 0 @2op
71
-VMULL_TS 111 0 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
72
-VMULL_TU 111 1 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
73
+{
74
+ VMULLP_B 111 . 1110 0 . 11 ... 1 ... 0 1110 . 0 . 0 ... 0 @2op_sz28
75
+ VMULL_BS 111 0 1110 0 . .. ... 1 ... 0 1110 . 0 . 0 ... 0 @2op
76
+ VMULL_BU 111 1 1110 0 . .. ... 1 ... 0 1110 . 0 . 0 ... 0 @2op
77
+}
78
+{
79
+ VMULLP_T 111 . 1110 0 . 11 ... 1 ... 1 1110 . 0 . 0 ... 0 @2op_sz28
80
+ VMULL_TS 111 0 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
81
+ VMULL_TU 111 1 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
82
+}
83
84
VQDMULH 1110 1111 0 . .. ... 0 ... 0 1011 . 1 . 0 ... 0 @2op
85
VQRDMULH 1111 1111 0 . .. ... 0 ... 0 1011 . 1 . 0 ... 0 @2op
86
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/target/arm/mve_helper.c
89
+++ b/target/arm/mve_helper.c
90
@@ -XXX,XX +XXX,XX @@ DO_2OP_L(vmulltub, 1, 1, uint8_t, 2, uint16_t, DO_MUL)
91
DO_2OP_L(vmulltuh, 1, 2, uint16_t, 4, uint32_t, DO_MUL)
92
DO_2OP_L(vmulltuw, 1, 4, uint32_t, 8, uint64_t, DO_MUL)
93
94
+/*
95
+ * Polynomial multiply. We can always do this generating 64 bits
96
+ * of the result at a time, so we don't need to use DO_2OP_L.
97
+ */
98
+#define VMULLPH_MASK 0x00ff00ff00ff00ffULL
99
+#define VMULLPW_MASK 0x0000ffff0000ffffULL
100
+#define DO_VMULLPBH(N, M) pmull_h((N) & VMULLPH_MASK, (M) & VMULLPH_MASK)
101
+#define DO_VMULLPTH(N, M) DO_VMULLPBH((N) >> 8, (M) >> 8)
102
+#define DO_VMULLPBW(N, M) pmull_w((N) & VMULLPW_MASK, (M) & VMULLPW_MASK)
103
+#define DO_VMULLPTW(N, M) DO_VMULLPBW((N) >> 16, (M) >> 16)
104
+
105
+DO_2OP(vmullpbh, 8, uint64_t, DO_VMULLPBH)
106
+DO_2OP(vmullpth, 8, uint64_t, DO_VMULLPTH)
107
+DO_2OP(vmullpbw, 8, uint64_t, DO_VMULLPBW)
108
+DO_2OP(vmullptw, 8, uint64_t, DO_VMULLPTW)
109
+
110
/*
111
* Because the computation type is at least twice as large as required,
112
* these work for both signed and unsigned source types.
113
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
114
index XXXXXXX..XXXXXXX 100644
115
--- a/target/arm/translate-mve.c
116
+++ b/target/arm/translate-mve.c
117
@@ -XXX,XX +XXX,XX @@ static bool trans_VQDMULLT(DisasContext *s, arg_2op *a)
118
return do_2op(s, a, fns[a->size]);
119
}
36
}
120
37
121
+static bool trans_VMULLP_B(DisasContext *s, arg_2op *a)
38
static void sbsa_ec_write(void *opaque, hwaddr offset,
122
+{
39
- uint64_t value, unsigned size)
123
+ /*
40
+ uint64_t value, unsigned size)
124
+ * Note that a->size indicates the output size, ie VMULL.P8
41
{
125
+ * is the 8x8->16 operation and a->size is MO_16; VMULL.P16
42
if (offset == 0) { /* PSCI machine power command register */
126
+ * is the 16x16->32 operation and a->size is MO_32.
43
switch (value) {
127
+ */
44
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps sbsa_ec_ops = {
128
+ static MVEGenTwoOpFn * const fns[] = {
45
129
+ NULL,
46
static void sbsa_ec_init(Object *obj)
130
+ gen_helper_mve_vmullpbh,
47
{
131
+ gen_helper_mve_vmullpbw,
48
- SECUREECState *s = SECURE_EC(obj);
132
+ NULL,
49
+ SECUREECState *s = SBSA_SECURE_EC(obj);
133
+ };
50
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
134
+ return do_2op(s, a, fns[a->size]);
51
135
+}
52
memory_region_init_io(&s->iomem, obj, &sbsa_ec_ops, s, "sbsa-ec",
136
+
53
@@ -XXX,XX +XXX,XX @@ static void sbsa_ec_class_init(ObjectClass *klass, void *data)
137
+static bool trans_VMULLP_T(DisasContext *s, arg_2op *a)
138
+{
139
+ /* a->size is as for trans_VMULLP_B */
140
+ static MVEGenTwoOpFn * const fns[] = {
141
+ NULL,
142
+ gen_helper_mve_vmullpth,
143
+ gen_helper_mve_vmullptw,
144
+ NULL,
145
+ };
146
+ return do_2op(s, a, fns[a->size]);
147
+}
148
+
149
/*
150
* VADC and VSBC: these perform an add-with-carry or subtract-with-carry
151
* of the 32-bit elements in each lane of the input vectors, where the
152
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
153
index XXXXXXX..XXXXXXX 100644
154
--- a/target/arm/vec_helper.c
155
+++ b/target/arm/vec_helper.c
156
@@ -XXX,XX +XXX,XX @@ static uint64_t expand_byte_to_half(uint64_t x)
157
| ((x & 0xff000000) << 24);
158
}
54
}
159
55
160
-static uint64_t pmull_h(uint64_t op1, uint64_t op2)
56
static const TypeInfo sbsa_ec_info = {
161
+uint64_t pmull_w(uint64_t op1, uint64_t op2)
57
- .name = TYPE_SBSA_EC,
162
{
58
+ .name = TYPE_SBSA_SECURE_EC,
163
uint64_t result = 0;
59
.parent = TYPE_SYS_BUS_DEVICE,
164
int i;
60
.instance_size = sizeof(SECUREECState),
165
+ for (i = 0; i < 16; ++i) {
61
.instance_init = sbsa_ec_init,
166
+ uint64_t mask = (op1 & 0x0000000100000001ull) * 0xffffffff;
167
+ result ^= op2 & mask;
168
+ op1 >>= 1;
169
+ op2 <<= 1;
170
+ }
171
+ return result;
172
+}
173
174
+uint64_t pmull_h(uint64_t op1, uint64_t op2)
175
+{
176
+ uint64_t result = 0;
177
+ int i;
178
for (i = 0; i < 8; ++i) {
179
uint64_t mask = (op1 & 0x0001000100010001ull) * 0xffff;
180
result ^= op2 & mask;
181
--
62
--
182
2.20.1
63
2.34.1
183
64
184
65
diff view generated by jsdifflib
Deleted patch
1
Factor out the "generate code to update VPR.MASK01/MASK23" part of
2
trans_VPST(); we are going to want to reuse it for the VPT insns.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
---
7
target/arm/translate-mve.c | 31 +++++++++++++++++--------------
8
1 file changed, 17 insertions(+), 14 deletions(-)
9
10
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/arm/translate-mve.c
13
+++ b/target/arm/translate-mve.c
14
@@ -XXX,XX +XXX,XX @@ static bool trans_VRMLSLDAVH(DisasContext *s, arg_vmlaldav *a)
15
return do_long_dual_acc(s, a, fns[a->x]);
16
}
17
18
-static bool trans_VPST(DisasContext *s, arg_VPST *a)
19
+static void gen_vpst(DisasContext *s, uint32_t mask)
20
{
21
- TCGv_i32 vpr;
22
-
23
- /* mask == 0 is a "related encoding" */
24
- if (!dc_isar_feature(aa32_mve, s) || !a->mask) {
25
- return false;
26
- }
27
- if (!mve_eci_check(s) || !vfp_access_check(s)) {
28
- return true;
29
- }
30
/*
31
* Set the VPR mask fields. We take advantage of MASK01 and MASK23
32
* being adjacent fields in the register.
33
*
34
- * This insn is not predicated, but it is subject to beat-wise
35
+ * Updating the masks is not predicated, but it is subject to beat-wise
36
* execution, and the mask is updated on the odd-numbered beats.
37
* So if PSR.ECI says we should skip beat 1, we mustn't update the
38
* 01 mask field.
39
*/
40
- vpr = load_cpu_field(v7m.vpr);
41
+ TCGv_i32 vpr = load_cpu_field(v7m.vpr);
42
switch (s->eci) {
43
case ECI_NONE:
44
case ECI_A0:
45
/* Update both 01 and 23 fields */
46
tcg_gen_deposit_i32(vpr, vpr,
47
- tcg_constant_i32(a->mask | (a->mask << 4)),
48
+ tcg_constant_i32(mask | (mask << 4)),
49
R_V7M_VPR_MASK01_SHIFT,
50
R_V7M_VPR_MASK01_LENGTH + R_V7M_VPR_MASK23_LENGTH);
51
break;
52
@@ -XXX,XX +XXX,XX @@ static bool trans_VPST(DisasContext *s, arg_VPST *a)
53
case ECI_A0A1A2B0:
54
/* Update only the 23 mask field */
55
tcg_gen_deposit_i32(vpr, vpr,
56
- tcg_constant_i32(a->mask),
57
+ tcg_constant_i32(mask),
58
R_V7M_VPR_MASK23_SHIFT, R_V7M_VPR_MASK23_LENGTH);
59
break;
60
default:
61
g_assert_not_reached();
62
}
63
store_cpu_field(vpr, v7m.vpr);
64
+}
65
+
66
+static bool trans_VPST(DisasContext *s, arg_VPST *a)
67
+{
68
+ /* mask == 0 is a "related encoding" */
69
+ if (!dc_isar_feature(aa32_mve, s) || !a->mask) {
70
+ return false;
71
+ }
72
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
73
+ return true;
74
+ }
75
+ gen_vpst(s, a->mask);
76
mve_update_and_store_eci(s);
77
return true;
78
}
79
--
80
2.20.1
81
82
diff view generated by jsdifflib
1
Implement the MVE integer vector comparison instructions. These are
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
"VCMP (vector)" encodings T1, T2 and T3, and "VPT (vector)" encodings
3
T1, T2 and T3.
4
2
5
These insns compare corresponding elements in each vector, and update
3
This model was merged few days before the QOM cleanup from
6
the VPR.P0 predicate bits with the results of the comparison. VPT
4
commit 8063396bf3 ("Use OBJECT_DECLARE_SIMPLE_TYPE when possible")
7
also sets the VPR.MASK01 and VPR.MASK23 fields -- it is effectively
5
was pulled and merged. Manually adapt.
8
"VCMP then VPST".
9
6
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230109140306.23161-13-philmd@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
---
11
---
13
target/arm/helper-mve.h | 32 ++++++++++++++++++++++
12
hw/misc/sbsa_ec.c | 3 +--
14
target/arm/mve.decode | 18 +++++++++++-
13
1 file changed, 1 insertion(+), 2 deletions(-)
15
target/arm/mve_helper.c | 56 ++++++++++++++++++++++++++++++++++++++
16
target/arm/translate-mve.c | 47 ++++++++++++++++++++++++++++++++
17
4 files changed, 152 insertions(+), 1 deletion(-)
18
14
19
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
15
diff --git a/hw/misc/sbsa_ec.c b/hw/misc/sbsa_ec.c
20
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper-mve.h
17
--- a/hw/misc/sbsa_ec.c
22
+++ b/target/arm/helper-mve.h
18
+++ b/hw/misc/sbsa_ec.c
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_uqshl, TCG_CALL_NO_RWG, i32, env, i32, i32)
19
@@ -XXX,XX +XXX,XX @@ typedef struct SECUREECState {
24
DEF_HELPER_FLAGS_3(mve_sqshl, TCG_CALL_NO_RWG, i32, env, i32, i32)
20
} SECUREECState;
25
DEF_HELPER_FLAGS_3(mve_uqrshl, TCG_CALL_NO_RWG, i32, env, i32, i32)
21
26
DEF_HELPER_FLAGS_3(mve_sqrshr, TCG_CALL_NO_RWG, i32, env, i32, i32)
22
#define TYPE_SBSA_SECURE_EC "sbsa-ec"
27
+
23
-#define SBSA_SECURE_EC(obj) \
28
+DEF_HELPER_FLAGS_3(mve_vcmpeqb, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
- OBJECT_CHECK(SECUREECState, (obj), TYPE_SBSA_SECURE_EC)
29
+DEF_HELPER_FLAGS_3(mve_vcmpeqh, TCG_CALL_NO_WG, void, env, ptr, ptr)
25
+OBJECT_DECLARE_SIMPLE_TYPE(SECUREECState, SBSA_SECURE_EC)
30
+DEF_HELPER_FLAGS_3(mve_vcmpeqw, TCG_CALL_NO_WG, void, env, ptr, ptr)
26
31
+
27
enum sbsa_ec_powerstates {
32
+DEF_HELPER_FLAGS_3(mve_vcmpneb, TCG_CALL_NO_WG, void, env, ptr, ptr)
28
SBSA_EC_CMD_POWEROFF = 0x01,
33
+DEF_HELPER_FLAGS_3(mve_vcmpneh, TCG_CALL_NO_WG, void, env, ptr, ptr)
34
+DEF_HELPER_FLAGS_3(mve_vcmpnew, TCG_CALL_NO_WG, void, env, ptr, ptr)
35
+
36
+DEF_HELPER_FLAGS_3(mve_vcmpcsb, TCG_CALL_NO_WG, void, env, ptr, ptr)
37
+DEF_HELPER_FLAGS_3(mve_vcmpcsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
38
+DEF_HELPER_FLAGS_3(mve_vcmpcsw, TCG_CALL_NO_WG, void, env, ptr, ptr)
39
+
40
+DEF_HELPER_FLAGS_3(mve_vcmphib, TCG_CALL_NO_WG, void, env, ptr, ptr)
41
+DEF_HELPER_FLAGS_3(mve_vcmphih, TCG_CALL_NO_WG, void, env, ptr, ptr)
42
+DEF_HELPER_FLAGS_3(mve_vcmphiw, TCG_CALL_NO_WG, void, env, ptr, ptr)
43
+
44
+DEF_HELPER_FLAGS_3(mve_vcmpgeb, TCG_CALL_NO_WG, void, env, ptr, ptr)
45
+DEF_HELPER_FLAGS_3(mve_vcmpgeh, TCG_CALL_NO_WG, void, env, ptr, ptr)
46
+DEF_HELPER_FLAGS_3(mve_vcmpgew, TCG_CALL_NO_WG, void, env, ptr, ptr)
47
+
48
+DEF_HELPER_FLAGS_3(mve_vcmpltb, TCG_CALL_NO_WG, void, env, ptr, ptr)
49
+DEF_HELPER_FLAGS_3(mve_vcmplth, TCG_CALL_NO_WG, void, env, ptr, ptr)
50
+DEF_HELPER_FLAGS_3(mve_vcmpltw, TCG_CALL_NO_WG, void, env, ptr, ptr)
51
+
52
+DEF_HELPER_FLAGS_3(mve_vcmpgtb, TCG_CALL_NO_WG, void, env, ptr, ptr)
53
+DEF_HELPER_FLAGS_3(mve_vcmpgth, TCG_CALL_NO_WG, void, env, ptr, ptr)
54
+DEF_HELPER_FLAGS_3(mve_vcmpgtw, TCG_CALL_NO_WG, void, env, ptr, ptr)
55
+
56
+DEF_HELPER_FLAGS_3(mve_vcmpleb, TCG_CALL_NO_WG, void, env, ptr, ptr)
57
+DEF_HELPER_FLAGS_3(mve_vcmpleh, TCG_CALL_NO_WG, void, env, ptr, ptr)
58
+DEF_HELPER_FLAGS_3(mve_vcmplew, TCG_CALL_NO_WG, void, env, ptr, ptr)
59
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
60
index XXXXXXX..XXXXXXX 100644
61
--- a/target/arm/mve.decode
62
+++ b/target/arm/mve.decode
63
@@ -XXX,XX +XXX,XX @@
64
&2shift qd qm shift size
65
&vidup qd rn size imm
66
&viwdup qd rn rm size imm
67
+&vcmp qm qn size mask
68
69
@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
70
# Note that both Rn and Qd are 3 bits only (no D bit)
71
@@ -XXX,XX +XXX,XX @@
72
@2_shr_w .... .... .. 1 ..... .... .... .... .... &2shift qd=%qd qm=%qm \
73
size=2 shift=%rshift_i5
74
75
+# Vector comparison; 4-bit Qm but 3-bit Qn
76
+%mask_22_13 22:1 13:3
77
+@vcmp .... .... .. size:2 qn:3 . .... .... .... .... &vcmp qm=%qm mask=%mask_22_13
78
+
79
# Vector loads and stores
80
81
# Widening loads and narrowing stores:
82
@@ -XXX,XX +XXX,XX @@ VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
83
}
84
85
# Predicate operations
86
-%mask_22_13 22:1 13:3
87
VPST 1111 1110 0 . 11 000 1 ... 0 1111 0100 1101 mask=%mask_22_13
88
89
# Logical immediate operations (1 reg and modified-immediate)
90
@@ -XXX,XX +XXX,XX @@ VQRSHRUNT 111 1 1110 1 . ... ... ... 1 1111 1 1 . 0 ... 0 @2_shr_b
91
VQRSHRUNT 111 1 1110 1 . ... ... ... 1 1111 1 1 . 0 ... 0 @2_shr_h
92
93
VSHLC 111 0 1110 1 . 1 imm:5 ... 0 1111 1100 rdm:4 qd=%qd
94
+
95
+# Comparisons. We expand out the conditions which are split across
96
+# encodings T1, T2, T3 and the fc bits. These include VPT, which is
97
+# effectively "VCMP then VPST". A plain "VCMP" has a mask field of zero.
98
+VCMPEQ 1111 1110 0 . .. ... 1 ... 0 1111 0 0 . 0 ... 0 @vcmp
99
+VCMPNE 1111 1110 0 . .. ... 1 ... 0 1111 1 0 . 0 ... 0 @vcmp
100
+VCMPCS 1111 1110 0 . .. ... 1 ... 0 1111 0 0 . 0 ... 1 @vcmp
101
+VCMPHI 1111 1110 0 . .. ... 1 ... 0 1111 1 0 . 0 ... 1 @vcmp
102
+VCMPGE 1111 1110 0 . .. ... 1 ... 1 1111 0 0 . 0 ... 0 @vcmp
103
+VCMPLT 1111 1110 0 . .. ... 1 ... 1 1111 1 0 . 0 ... 0 @vcmp
104
+VCMPGT 1111 1110 0 . .. ... 1 ... 1 1111 0 0 . 0 ... 1 @vcmp
105
+VCMPLE 1111 1110 0 . .. ... 1 ... 1 1111 1 0 . 0 ... 1 @vcmp
106
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
107
index XXXXXXX..XXXXXXX 100644
108
--- a/target/arm/mve_helper.c
109
+++ b/target/arm/mve_helper.c
110
@@ -XXX,XX +XXX,XX @@ static uint32_t do_sub_wrap(uint32_t offset, uint32_t wrap, uint32_t imm)
111
DO_VIDUP_ALL(vidup, DO_ADD)
112
DO_VIWDUP_ALL(viwdup, do_add_wrap)
113
DO_VIWDUP_ALL(vdwdup, do_sub_wrap)
114
+
115
+/*
116
+ * Vector comparison.
117
+ * P0 bits for non-executed beats (where eci_mask is 0) are unchanged.
118
+ * P0 bits for predicated lanes in executed beats (where mask is 0) are 0.
119
+ * P0 bits otherwise are updated with the results of the comparisons.
120
+ * We must also keep unchanged the MASK fields at the top of v7m.vpr.
121
+ */
122
+#define DO_VCMP(OP, ESIZE, TYPE, FN) \
123
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vn, void *vm) \
124
+ { \
125
+ TYPE *n = vn, *m = vm; \
126
+ uint16_t mask = mve_element_mask(env); \
127
+ uint16_t eci_mask = mve_eci_mask(env); \
128
+ uint16_t beatpred = 0; \
129
+ uint16_t emask = MAKE_64BIT_MASK(0, ESIZE); \
130
+ unsigned e; \
131
+ for (e = 0; e < 16 / ESIZE; e++) { \
132
+ bool r = FN(n[H##ESIZE(e)], m[H##ESIZE(e)]); \
133
+ /* Comparison sets 0/1 bits for each byte in the element */ \
134
+ beatpred |= r * emask; \
135
+ emask <<= ESIZE; \
136
+ } \
137
+ beatpred &= mask; \
138
+ env->v7m.vpr = (env->v7m.vpr & ~(uint32_t)eci_mask) | \
139
+ (beatpred & eci_mask); \
140
+ mve_advance_vpt(env); \
141
+ }
142
+
143
+#define DO_VCMP_S(OP, FN) \
144
+ DO_VCMP(OP##b, 1, int8_t, FN) \
145
+ DO_VCMP(OP##h, 2, int16_t, FN) \
146
+ DO_VCMP(OP##w, 4, int32_t, FN)
147
+
148
+#define DO_VCMP_U(OP, FN) \
149
+ DO_VCMP(OP##b, 1, uint8_t, FN) \
150
+ DO_VCMP(OP##h, 2, uint16_t, FN) \
151
+ DO_VCMP(OP##w, 4, uint32_t, FN)
152
+
153
+#define DO_EQ(N, M) ((N) == (M))
154
+#define DO_NE(N, M) ((N) != (M))
155
+#define DO_EQ(N, M) ((N) == (M))
156
+#define DO_EQ(N, M) ((N) == (M))
157
+#define DO_GE(N, M) ((N) >= (M))
158
+#define DO_LT(N, M) ((N) < (M))
159
+#define DO_GT(N, M) ((N) > (M))
160
+#define DO_LE(N, M) ((N) <= (M))
161
+
162
+DO_VCMP_U(vcmpeq, DO_EQ)
163
+DO_VCMP_U(vcmpne, DO_NE)
164
+DO_VCMP_U(vcmpcs, DO_GE)
165
+DO_VCMP_U(vcmphi, DO_GT)
166
+DO_VCMP_S(vcmpge, DO_GE)
167
+DO_VCMP_S(vcmplt, DO_LT)
168
+DO_VCMP_S(vcmpgt, DO_GT)
169
+DO_VCMP_S(vcmple, DO_LE)
170
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
171
index XXXXXXX..XXXXXXX 100644
172
--- a/target/arm/translate-mve.c
173
+++ b/target/arm/translate-mve.c
174
@@ -XXX,XX +XXX,XX @@ typedef void MVEGenVADDVFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32);
175
typedef void MVEGenOneOpImmFn(TCGv_ptr, TCGv_ptr, TCGv_i64);
176
typedef void MVEGenVIDUPFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32, TCGv_i32);
177
typedef void MVEGenVIWDUPFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32, TCGv_i32, TCGv_i32);
178
+typedef void MVEGenCmpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
179
180
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
181
static inline long mve_qreg_offset(unsigned reg)
182
@@ -XXX,XX +XXX,XX @@ static bool trans_VDWDUP(DisasContext *s, arg_viwdup *a)
183
};
184
return do_viwdup(s, a, fns[a->size]);
185
}
186
+
187
+static bool do_vcmp(DisasContext *s, arg_vcmp *a, MVEGenCmpFn *fn)
188
+{
189
+ TCGv_ptr qn, qm;
190
+
191
+ if (!dc_isar_feature(aa32_mve, s) || !mve_check_qreg_bank(s, a->qm) ||
192
+ !fn) {
193
+ return false;
194
+ }
195
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
196
+ return true;
197
+ }
198
+
199
+ qn = mve_qreg_ptr(a->qn);
200
+ qm = mve_qreg_ptr(a->qm);
201
+ fn(cpu_env, qn, qm);
202
+ tcg_temp_free_ptr(qn);
203
+ tcg_temp_free_ptr(qm);
204
+ if (a->mask) {
205
+ /* VPT */
206
+ gen_vpst(s, a->mask);
207
+ }
208
+ mve_update_eci(s);
209
+ return true;
210
+}
211
+
212
+#define DO_VCMP(INSN, FN) \
213
+ static bool trans_##INSN(DisasContext *s, arg_vcmp *a) \
214
+ { \
215
+ static MVEGenCmpFn * const fns[] = { \
216
+ gen_helper_mve_##FN##b, \
217
+ gen_helper_mve_##FN##h, \
218
+ gen_helper_mve_##FN##w, \
219
+ NULL, \
220
+ }; \
221
+ return do_vcmp(s, a, fns[a->size]); \
222
+ }
223
+
224
+DO_VCMP(VCMPEQ, vcmpeq)
225
+DO_VCMP(VCMPNE, vcmpne)
226
+DO_VCMP(VCMPCS, vcmpcs)
227
+DO_VCMP(VCMPHI, vcmphi)
228
+DO_VCMP(VCMPGE, vcmpge)
229
+DO_VCMP(VCMPLT, vcmplt)
230
+DO_VCMP(VCMPGT, vcmpgt)
231
+DO_VCMP(VCMPLE, vcmple)
232
--
29
--
233
2.20.1
30
2.34.1
234
31
235
32
diff view generated by jsdifflib
Deleted patch
1
Implement the MVE VPSEL insn, which sets each byte of the destination
2
vector Qd to the byte from either Qn or Qm depending on the value of
3
the corresponding bit in VPR.P0.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
target/arm/helper-mve.h | 2 ++
9
target/arm/mve.decode | 7 +++++--
10
target/arm/mve_helper.c | 19 +++++++++++++++++++
11
target/arm/translate-mve.c | 2 ++
12
4 files changed, 28 insertions(+), 2 deletions(-)
13
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-mve.h
17
+++ b/target/arm/helper-mve.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vorr, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
DEF_HELPER_FLAGS_4(mve_vorn, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
DEF_HELPER_FLAGS_4(mve_veor, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
22
+DEF_HELPER_FLAGS_4(mve_vpsel, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
+
24
DEF_HELPER_FLAGS_4(mve_vaddb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
DEF_HELPER_FLAGS_4(mve_vaddh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
DEF_HELPER_FLAGS_4(mve_vaddw, TCG_CALL_NO_WG, void, env, ptr, 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 @@ VSHLC 111 0 1110 1 . 1 imm:5 ... 0 1111 1100 rdm:4 qd=%qd
32
# effectively "VCMP then VPST". A plain "VCMP" has a mask field of zero.
33
VCMPEQ 1111 1110 0 . .. ... 1 ... 0 1111 0 0 . 0 ... 0 @vcmp
34
VCMPNE 1111 1110 0 . .. ... 1 ... 0 1111 1 0 . 0 ... 0 @vcmp
35
-VCMPCS 1111 1110 0 . .. ... 1 ... 0 1111 0 0 . 0 ... 1 @vcmp
36
-VCMPHI 1111 1110 0 . .. ... 1 ... 0 1111 1 0 . 0 ... 1 @vcmp
37
+{
38
+ VPSEL 1111 1110 0 . 11 ... 1 ... 0 1111 . 0 . 0 ... 1 @2op_nosz
39
+ VCMPCS 1111 1110 0 . .. ... 1 ... 0 1111 0 0 . 0 ... 1 @vcmp
40
+ VCMPHI 1111 1110 0 . .. ... 1 ... 0 1111 1 0 . 0 ... 1 @vcmp
41
+}
42
VCMPGE 1111 1110 0 . .. ... 1 ... 1 1111 0 0 . 0 ... 0 @vcmp
43
VCMPLT 1111 1110 0 . .. ... 1 ... 1 1111 1 0 . 0 ... 0 @vcmp
44
VCMPGT 1111 1110 0 . .. ... 1 ... 1 1111 0 0 . 0 ... 1 @vcmp
45
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/mve_helper.c
48
+++ b/target/arm/mve_helper.c
49
@@ -XXX,XX +XXX,XX @@ DO_VCMP_S(vcmpge, DO_GE)
50
DO_VCMP_S(vcmplt, DO_LT)
51
DO_VCMP_S(vcmpgt, DO_GT)
52
DO_VCMP_S(vcmple, DO_LE)
53
+
54
+void HELPER(mve_vpsel)(CPUARMState *env, void *vd, void *vn, void *vm)
55
+{
56
+ /*
57
+ * Qd[n] = VPR.P0[n] ? Qn[n] : Qm[n]
58
+ * but note that whether bytes are written to Qd is still subject
59
+ * to (all forms of) predication in the usual way.
60
+ */
61
+ uint64_t *d = vd, *n = vn, *m = vm;
62
+ uint16_t mask = mve_element_mask(env);
63
+ uint16_t p0 = FIELD_EX32(env->v7m.vpr, V7M_VPR, P0);
64
+ unsigned e;
65
+ for (e = 0; e < 16 / 8; e++, mask >>= 8, p0 >>= 8) {
66
+ uint64_t r = m[H8(e)];
67
+ mergemask(&r, n[H8(e)], p0);
68
+ mergemask(&d[H8(e)], r, mask);
69
+ }
70
+ mve_advance_vpt(env);
71
+}
72
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/target/arm/translate-mve.c
75
+++ b/target/arm/translate-mve.c
76
@@ -XXX,XX +XXX,XX @@ DO_LOGIC(VORR, gen_helper_mve_vorr)
77
DO_LOGIC(VORN, gen_helper_mve_vorn)
78
DO_LOGIC(VEOR, gen_helper_mve_veor)
79
80
+DO_LOGIC(VPSEL, gen_helper_mve_vpsel)
81
+
82
#define DO_2OP(INSN, FN) \
83
static bool trans_##INSN(DisasContext *s, arg_2op *a) \
84
{ \
85
--
86
2.20.1
87
88
diff view generated by jsdifflib
1
Implement the MVE VMLADAV and VMLSLDAV insns. Like the VMLALDAV and
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
VMLSLDAV insns already implemented, these accumulate multiplied
3
vector elements; but they accumulate a 32-bit result rather than a
4
64-bit one.
5
2
6
Note that these encodings overlap with what would be RdaHi=0b111 for
3
This remove a use of 'struct' in the DECLARE_INSTANCE_CHECKER()
7
VMLALDAV, VMLSLDAV, VRMLALDAVH and VRMLSLDAVH.
4
macro call, to avoid after a QOM refactor:
8
5
6
hw/intc/xilinx_intc.c:45:1: error: declaration of anonymous struct must be a definition
7
DECLARE_INSTANCE_CHECKER(struct xlx_pic, XILINX_INTC,
8
^
9
10
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Edgar E. Iglesias <edgar@zeroasic.com>
13
Message-id: 20230109140306.23161-14-philmd@linaro.org
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
---
15
---
12
target/arm/helper-mve.h | 17 ++++++++++
16
hw/intc/xilinx_intc.c | 28 +++++++++++++---------------
13
target/arm/mve.decode | 33 +++++++++++++++++---
17
1 file changed, 13 insertions(+), 15 deletions(-)
14
target/arm/mve_helper.c | 41 ++++++++++++++++++++++++
15
target/arm/translate-mve.c | 64 ++++++++++++++++++++++++++++++++++++++
16
4 files changed, 150 insertions(+), 5 deletions(-)
17
18
18
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
19
diff --git a/hw/intc/xilinx_intc.c b/hw/intc/xilinx_intc.c
19
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper-mve.h
21
--- a/hw/intc/xilinx_intc.c
21
+++ b/target/arm/helper-mve.h
22
+++ b/hw/intc/xilinx_intc.c
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vrmlaldavhuw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
23
@@ -XXX,XX +XXX,XX @@
23
DEF_HELPER_FLAGS_4(mve_vrmlsldavhsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
24
#define R_MAX 8
24
DEF_HELPER_FLAGS_4(mve_vrmlsldavhxsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
25
25
26
#define TYPE_XILINX_INTC "xlnx.xps-intc"
26
+DEF_HELPER_FLAGS_4(mve_vmladavsb, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
27
-DECLARE_INSTANCE_CHECKER(struct xlx_pic, XILINX_INTC,
27
+DEF_HELPER_FLAGS_4(mve_vmladavsh, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
28
- TYPE_XILINX_INTC)
28
+DEF_HELPER_FLAGS_4(mve_vmladavsw, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
29
+typedef struct XpsIntc XpsIntc;
29
+DEF_HELPER_FLAGS_4(mve_vmladavub, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
30
+DECLARE_INSTANCE_CHECKER(XpsIntc, XILINX_INTC, TYPE_XILINX_INTC)
30
+DEF_HELPER_FLAGS_4(mve_vmladavuh, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
31
31
+DEF_HELPER_FLAGS_4(mve_vmladavuw, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
32
-struct xlx_pic
32
+DEF_HELPER_FLAGS_4(mve_vmlsdavb, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
33
+struct XpsIntc
33
+DEF_HELPER_FLAGS_4(mve_vmlsdavh, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
34
+DEF_HELPER_FLAGS_4(mve_vmlsdavw, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
35
+
36
+DEF_HELPER_FLAGS_4(mve_vmladavsxb, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
37
+DEF_HELPER_FLAGS_4(mve_vmladavsxh, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
38
+DEF_HELPER_FLAGS_4(mve_vmladavsxw, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
39
+DEF_HELPER_FLAGS_4(mve_vmlsdavxb, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
40
+DEF_HELPER_FLAGS_4(mve_vmlsdavxh, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
41
+DEF_HELPER_FLAGS_4(mve_vmlsdavxw, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
42
+
43
DEF_HELPER_FLAGS_3(mve_vaddvsb, TCG_CALL_NO_WG, i32, env, ptr, i32)
44
DEF_HELPER_FLAGS_3(mve_vaddvub, TCG_CALL_NO_WG, i32, env, ptr, i32)
45
DEF_HELPER_FLAGS_3(mve_vaddvsh, TCG_CALL_NO_WG, i32, env, ptr, i32)
46
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/mve.decode
49
+++ b/target/arm/mve.decode
50
@@ -XXX,XX +XXX,XX @@ VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=2
51
%size_16 16:1 !function=plus_1
52
53
&vmlaldav rdahi rdalo size qn qm x a
54
+&vmladav rda size qn qm x a
55
56
@vmlaldav .... .... . ... ... . ... x:1 .... .. a:1 . qm:3 . \
57
qn=%qn rdahi=%rdahi rdalo=%rdalo size=%size_16 &vmlaldav
58
@vmlaldav_nosz .... .... . ... ... . ... x:1 .... .. a:1 . qm:3 . \
59
qn=%qn rdahi=%rdahi rdalo=%rdalo size=0 &vmlaldav
60
-VMLALDAV_S 1110 1110 1 ... ... . ... . 1110 . 0 . 0 ... 0 @vmlaldav
61
-VMLALDAV_U 1111 1110 1 ... ... . ... . 1110 . 0 . 0 ... 0 @vmlaldav
62
+@vmladav .... .... .... ... . ... x:1 .... . . a:1 . qm:3 . \
63
+ qn=%qn rda=%rdalo size=%size_16 &vmladav
64
+@vmladav_nosz .... .... .... ... . ... x:1 .... . . a:1 . qm:3 . \
65
+ qn=%qn rda=%rdalo size=0 &vmladav
66
67
-VMLSLDAV 1110 1110 1 ... ... . ... . 1110 . 0 . 0 ... 1 @vmlaldav
68
+{
69
+ VMLADAV_S 1110 1110 1111 ... . ... . 1110 . 0 . 0 ... 0 @vmladav
70
+ VMLALDAV_S 1110 1110 1 ... ... . ... . 1110 . 0 . 0 ... 0 @vmlaldav
71
+}
72
+{
73
+ VMLADAV_U 1111 1110 1111 ... . ... . 1110 . 0 . 0 ... 0 @vmladav
74
+ VMLALDAV_U 1111 1110 1 ... ... . ... . 1110 . 0 . 0 ... 0 @vmlaldav
75
+}
76
+
77
+{
78
+ VMLSDAV 1110 1110 1111 ... . ... . 1110 . 0 . 0 ... 1 @vmladav
79
+ VMLSLDAV 1110 1110 1 ... ... . ... . 1110 . 0 . 0 ... 1 @vmlaldav
80
+}
81
+
82
+{
83
+ VMLSDAV 1111 1110 1111 ... 0 ... . 1110 . 0 . 0 ... 1 @vmladav_nosz
84
+ VRMLSLDAVH 1111 1110 1 ... ... 0 ... . 1110 . 0 . 0 ... 1 @vmlaldav_nosz
85
+}
86
+
87
+VMLADAV_S 1110 1110 1111 ... 0 ... . 1111 . 0 . 0 ... 1 @vmladav_nosz
88
+VMLADAV_U 1111 1110 1111 ... 0 ... . 1111 . 0 . 0 ... 1 @vmladav_nosz
89
90
{
34
{
91
VMAXV_S 1110 1110 1110 .. 10 .... 1111 0 0 . 0 ... 0 @vmaxv
35
SysBusDevice parent_obj;
92
VMINV_S 1110 1110 1110 .. 10 .... 1111 1 0 . 0 ... 0 @vmaxv
36
93
VMAXAV 1110 1110 1110 .. 00 .... 1111 0 0 . 0 ... 0 @vmaxv
37
@@ -XXX,XX +XXX,XX @@ struct xlx_pic
94
VMINAV 1110 1110 1110 .. 00 .... 1111 1 0 . 0 ... 0 @vmaxv
38
uint32_t irq_pin_state;
95
+ VMLADAV_S 1110 1110 1111 ... 0 ... . 1111 . 0 . 0 ... 0 @vmladav_nosz
39
};
96
VRMLALDAVH_S 1110 1110 1 ... ... 0 ... . 1111 . 0 . 0 ... 0 @vmlaldav_nosz
40
41
-static void update_irq(struct xlx_pic *p)
42
+static void update_irq(XpsIntc *p)
43
{
44
uint32_t i;
45
46
@@ -XXX,XX +XXX,XX @@ static void update_irq(struct xlx_pic *p)
47
qemu_set_irq(p->parent_irq, (p->regs[R_MER] & 1) && p->regs[R_IPR]);
97
}
48
}
98
49
50
-static uint64_t
51
-pic_read(void *opaque, hwaddr addr, unsigned int size)
52
+static uint64_t pic_read(void *opaque, hwaddr addr, unsigned int size)
99
{
53
{
100
VMAXV_U 1111 1110 1110 .. 10 .... 1111 0 0 . 0 ... 0 @vmaxv
54
- struct xlx_pic *p = opaque;
101
VMINV_U 1111 1110 1110 .. 10 .... 1111 1 0 . 0 ... 0 @vmaxv
55
+ XpsIntc *p = opaque;
102
+ VMLADAV_U 1111 1110 1111 ... 0 ... . 1111 . 0 . 0 ... 0 @vmladav_nosz
56
uint32_t r = 0;
103
VRMLALDAVH_U 1111 1110 1 ... ... 0 ... . 1111 . 0 . 0 ... 0 @vmlaldav_nosz
57
58
addr >>= 2;
59
@@ -XXX,XX +XXX,XX @@ pic_read(void *opaque, hwaddr addr, unsigned int size)
60
return r;
104
}
61
}
105
62
106
-VRMLSLDAVH 1111 1110 1 ... ... 0 ... . 1110 . 0 . 0 ... 1 @vmlaldav_nosz
63
-static void
107
-
64
-pic_write(void *opaque, hwaddr addr,
108
# Scalar operations
65
- uint64_t val64, unsigned int size)
109
66
+static void pic_write(void *opaque, hwaddr addr,
110
VADD_scalar 1110 1110 0 . .. ... 1 ... 0 1111 . 100 .... @2scalar
67
+ uint64_t val64, unsigned int size)
111
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
68
{
112
index XXXXXXX..XXXXXXX 100644
69
- struct xlx_pic *p = opaque;
113
--- a/target/arm/mve_helper.c
70
+ XpsIntc *p = opaque;
114
+++ b/target/arm/mve_helper.c
71
uint32_t value = val64;
115
@@ -XXX,XX +XXX,XX @@ DO_LDAV(vmlsldavxsh, 2, int16_t, true, +=, -=)
72
116
DO_LDAV(vmlsldavsw, 4, int32_t, false, +=, -=)
73
addr >>= 2;
117
DO_LDAV(vmlsldavxsw, 4, int32_t, true, +=, -=)
74
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps pic_ops = {
118
75
119
+/*
76
static void irq_handler(void *opaque, int irq, int level)
120
+ * Multiply add dual accumulate ops
77
{
121
+ */
78
- struct xlx_pic *p = opaque;
122
+#define DO_DAV(OP, ESIZE, TYPE, XCHG, EVENACC, ODDACC) \
79
+ XpsIntc *p = opaque;
123
+ uint32_t HELPER(glue(mve_, OP))(CPUARMState *env, void *vn, \
80
124
+ void *vm, uint32_t a) \
81
/* edge triggered interrupt */
125
+ { \
82
if (p->c_kind_of_intr & (1 << irq) && p->regs[R_MER] & 2) {
126
+ uint16_t mask = mve_element_mask(env); \
83
@@ -XXX,XX +XXX,XX @@ static void irq_handler(void *opaque, int irq, int level)
127
+ unsigned e; \
84
128
+ TYPE *n = vn, *m = vm; \
85
static void xilinx_intc_init(Object *obj)
129
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
86
{
130
+ if (mask & 1) { \
87
- struct xlx_pic *p = XILINX_INTC(obj);
131
+ if (e & 1) { \
88
+ XpsIntc *p = XILINX_INTC(obj);
132
+ a ODDACC \
89
133
+ n[H##ESIZE(e - 1 * XCHG)] * m[H##ESIZE(e)]; \
90
qdev_init_gpio_in(DEVICE(obj), irq_handler, 32);
134
+ } else { \
91
sysbus_init_irq(SYS_BUS_DEVICE(obj), &p->parent_irq);
135
+ a EVENACC \
92
@@ -XXX,XX +XXX,XX @@ static void xilinx_intc_init(Object *obj)
136
+ n[H##ESIZE(e + 1 * XCHG)] * m[H##ESIZE(e)]; \
137
+ } \
138
+ } \
139
+ } \
140
+ mve_advance_vpt(env); \
141
+ return a; \
142
+ }
143
+
144
+#define DO_DAV_S(INSN, XCHG, EVENACC, ODDACC) \
145
+ DO_DAV(INSN##b, 1, int8_t, XCHG, EVENACC, ODDACC) \
146
+ DO_DAV(INSN##h, 2, int16_t, XCHG, EVENACC, ODDACC) \
147
+ DO_DAV(INSN##w, 4, int32_t, XCHG, EVENACC, ODDACC)
148
+
149
+#define DO_DAV_U(INSN, XCHG, EVENACC, ODDACC) \
150
+ DO_DAV(INSN##b, 1, uint8_t, XCHG, EVENACC, ODDACC) \
151
+ DO_DAV(INSN##h, 2, uint16_t, XCHG, EVENACC, ODDACC) \
152
+ DO_DAV(INSN##w, 4, uint32_t, XCHG, EVENACC, ODDACC)
153
+
154
+DO_DAV_S(vmladavs, false, +=, +=)
155
+DO_DAV_U(vmladavu, false, +=, +=)
156
+DO_DAV_S(vmlsdav, false, +=, -=)
157
+DO_DAV_S(vmladavsx, true, +=, +=)
158
+DO_DAV_S(vmlsdavx, true, +=, -=)
159
+
160
/*
161
* Rounding multiply add long dual accumulate high. In the pseudocode
162
* this is implemented with a 72-bit internal accumulator value of which
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 @@ typedef void MVEGenVIWDUPFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32, TCGv_i32, TC
168
typedef void MVEGenCmpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
169
typedef void MVEGenScalarCmpFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
170
typedef void MVEGenVABAVFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
171
+typedef void MVEGenDualAccOpFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
172
173
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
174
static inline long mve_qreg_offset(unsigned reg)
175
@@ -XXX,XX +XXX,XX @@ static bool trans_VRMLSLDAVH(DisasContext *s, arg_vmlaldav *a)
176
return do_long_dual_acc(s, a, fns[a->x]);
177
}
93
}
178
94
179
+static bool do_dual_acc(DisasContext *s, arg_vmladav *a, MVEGenDualAccOpFn *fn)
95
static Property xilinx_intc_properties[] = {
180
+{
96
- DEFINE_PROP_UINT32("kind-of-intr", struct xlx_pic, c_kind_of_intr, 0),
181
+ TCGv_ptr qn, qm;
97
+ DEFINE_PROP_UINT32("kind-of-intr", XpsIntc, c_kind_of_intr, 0),
182
+ TCGv_i32 rda;
98
DEFINE_PROP_END_OF_LIST(),
183
+
99
};
184
+ if (!dc_isar_feature(aa32_mve, s) ||
100
185
+ !mve_check_qreg_bank(s, a->qn) ||
101
@@ -XXX,XX +XXX,XX @@ static void xilinx_intc_class_init(ObjectClass *klass, void *data)
186
+ !fn) {
102
static const TypeInfo xilinx_intc_info = {
187
+ return false;
103
.name = TYPE_XILINX_INTC,
188
+ }
104
.parent = TYPE_SYS_BUS_DEVICE,
189
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
105
- .instance_size = sizeof(struct xlx_pic),
190
+ return true;
106
+ .instance_size = sizeof(XpsIntc),
191
+ }
107
.instance_init = xilinx_intc_init,
192
+
108
.class_init = xilinx_intc_class_init,
193
+ qn = mve_qreg_ptr(a->qn);
109
};
194
+ qm = mve_qreg_ptr(a->qm);
195
+
196
+ /*
197
+ * This insn is subject to beat-wise execution. Partial execution
198
+ * of an A=0 (no-accumulate) insn which does not execute the first
199
+ * beat must start with the current rda value, not 0.
200
+ */
201
+ if (a->a || mve_skip_first_beat(s)) {
202
+ rda = load_reg(s, a->rda);
203
+ } else {
204
+ rda = tcg_const_i32(0);
205
+ }
206
+
207
+ fn(rda, cpu_env, qn, qm, rda);
208
+ store_reg(s, a->rda, rda);
209
+ tcg_temp_free_ptr(qn);
210
+ tcg_temp_free_ptr(qm);
211
+
212
+ mve_update_eci(s);
213
+ return true;
214
+}
215
+
216
+#define DO_DUAL_ACC(INSN, FN) \
217
+ static bool trans_##INSN(DisasContext *s, arg_vmladav *a) \
218
+ { \
219
+ static MVEGenDualAccOpFn * const fns[4][2] = { \
220
+ { gen_helper_mve_##FN##b, gen_helper_mve_##FN##xb }, \
221
+ { gen_helper_mve_##FN##h, gen_helper_mve_##FN##xh }, \
222
+ { gen_helper_mve_##FN##w, gen_helper_mve_##FN##xw }, \
223
+ { NULL, NULL }, \
224
+ }; \
225
+ return do_dual_acc(s, a, fns[a->size][a->x]); \
226
+ }
227
+
228
+DO_DUAL_ACC(VMLADAV_S, vmladavs)
229
+DO_DUAL_ACC(VMLSDAV, vmlsdav)
230
+
231
+static bool trans_VMLADAV_U(DisasContext *s, arg_vmladav *a)
232
+{
233
+ static MVEGenDualAccOpFn * const fns[4][2] = {
234
+ { gen_helper_mve_vmladavub, NULL },
235
+ { gen_helper_mve_vmladavuh, NULL },
236
+ { gen_helper_mve_vmladavuw, NULL },
237
+ { NULL, NULL },
238
+ };
239
+ return do_dual_acc(s, a, fns[a->size][a->x]);
240
+}
241
+
242
static void gen_vpst(DisasContext *s, uint32_t mask)
243
{
244
/*
245
--
110
--
246
2.20.1
111
2.34.1
247
112
248
113
diff view generated by jsdifflib
1
Implement the MVE VPNOT insn, which inverts the bits in VPR.P0
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
(subject to both predication and to beatwise execution).
3
2
3
This remove a use of 'struct' in the DECLARE_INSTANCE_CHECKER()
4
macro call, to avoid after a QOM refactor:
5
6
hw/timer/xilinx_timer.c:65:1: error: declaration of anonymous struct must be a definition
7
DECLARE_INSTANCE_CHECKER(struct timerblock, XILINX_TIMER,
8
^
9
10
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Reviewed-by: Edgar E. Iglesias <edgar@zeroasic.com>
13
Message-id: 20230109140306.23161-15-philmd@linaro.org
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
---
15
---
7
target/arm/helper-mve.h | 1 +
16
hw/timer/xilinx_timer.c | 27 +++++++++++++--------------
8
target/arm/mve.decode | 1 +
17
1 file changed, 13 insertions(+), 14 deletions(-)
9
target/arm/mve_helper.c | 17 +++++++++++++++++
10
target/arm/translate-mve.c | 19 +++++++++++++++++++
11
4 files changed, 38 insertions(+)
12
18
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
19
diff --git a/hw/timer/xilinx_timer.c b/hw/timer/xilinx_timer.c
14
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
21
--- a/hw/timer/xilinx_timer.c
16
+++ b/target/arm/helper-mve.h
22
+++ b/hw/timer/xilinx_timer.c
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vorn, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
@@ -XXX,XX +XXX,XX @@ struct xlx_timer
18
DEF_HELPER_FLAGS_4(mve_veor, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
};
19
25
20
DEF_HELPER_FLAGS_4(mve_vpsel, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
#define TYPE_XILINX_TIMER "xlnx.xps-timer"
21
+DEF_HELPER_FLAGS_1(mve_vpnot, TCG_CALL_NO_WG, void, env)
27
-DECLARE_INSTANCE_CHECKER(struct timerblock, XILINX_TIMER,
22
28
- TYPE_XILINX_TIMER)
23
DEF_HELPER_FLAGS_4(mve_vaddb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
+typedef struct XpsTimerState XpsTimerState;
24
DEF_HELPER_FLAGS_4(mve_vaddh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
+DECLARE_INSTANCE_CHECKER(XpsTimerState, XILINX_TIMER, TYPE_XILINX_TIMER)
25
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
31
26
index XXXXXXX..XXXXXXX 100644
32
-struct timerblock
27
--- a/target/arm/mve.decode
33
+struct XpsTimerState
28
+++ b/target/arm/mve.decode
29
@@ -XXX,XX +XXX,XX @@ VCMPGT 1111 1110 0 . .. ... 1 ... 1 1111 0 0 . 0 ... 1 @vcmp
30
VCMPLE 1111 1110 0 . .. ... 1 ... 1 1111 1 0 . 0 ... 1 @vcmp
31
32
{
34
{
33
+ VPNOT 1111 1110 0 0 11 000 1 000 0 1111 0100 1101
35
SysBusDevice parent_obj;
34
VPST 1111 1110 0 . 11 000 1 ... 0 1111 0100 1101 mask=%mask_22_13
36
35
VCMPEQ_scalar 1111 1110 0 . .. ... 1 ... 0 1111 0 1 0 0 .... @vcmp_scalar
37
@@ -XXX,XX +XXX,XX @@ struct timerblock
38
struct xlx_timer *timers;
39
};
40
41
-static inline unsigned int num_timers(struct timerblock *t)
42
+static inline unsigned int num_timers(XpsTimerState *t)
43
{
44
return 2 - t->one_timer_only;
36
}
45
}
37
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
46
@@ -XXX,XX +XXX,XX @@ static inline unsigned int timer_from_addr(hwaddr addr)
38
index XXXXXXX..XXXXXXX 100644
47
return addr >> 2;
39
--- a/target/arm/mve_helper.c
40
+++ b/target/arm/mve_helper.c
41
@@ -XXX,XX +XXX,XX @@ void HELPER(mve_vpsel)(CPUARMState *env, void *vd, void *vn, void *vm)
42
mve_advance_vpt(env);
43
}
48
}
44
49
45
+void HELPER(mve_vpnot)(CPUARMState *env)
50
-static void timer_update_irq(struct timerblock *t)
46
+{
51
+static void timer_update_irq(XpsTimerState *t)
47
+ /*
52
{
48
+ * P0 bits for unexecuted beats (where eci_mask is 0) are unchanged.
53
unsigned int i, irq = 0;
49
+ * P0 bits for predicated lanes in executed bits (where mask is 0) are 0.
54
uint32_t csr;
50
+ * P0 bits otherwise are inverted.
55
@@ -XXX,XX +XXX,XX @@ static void timer_update_irq(struct timerblock *t)
51
+ * (This is the same logic as VCMP.)
56
static uint64_t
52
+ * This insn is itself subject to predication and to beat-wise execution,
57
timer_read(void *opaque, hwaddr addr, unsigned int size)
53
+ * and after it executes VPT state advances in the usual way.
58
{
54
+ */
59
- struct timerblock *t = opaque;
55
+ uint16_t mask = mve_element_mask(env);
60
+ XpsTimerState *t = opaque;
56
+ uint16_t eci_mask = mve_eci_mask(env);
61
struct xlx_timer *xt;
57
+ uint16_t beatpred = ~env->v7m.vpr & mask;
62
uint32_t r = 0;
58
+ env->v7m.vpr = (env->v7m.vpr & ~(uint32_t)eci_mask) | (beatpred & eci_mask);
63
unsigned int timer;
59
+ mve_advance_vpt(env);
64
@@ -XXX,XX +XXX,XX @@ static void
60
+}
65
timer_write(void *opaque, hwaddr addr,
61
+
66
uint64_t val64, unsigned int size)
62
#define DO_1OP_SAT(OP, ESIZE, TYPE, FN) \
67
{
63
void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm) \
68
- struct timerblock *t = opaque;
64
{ \
69
+ XpsTimerState *t = opaque;
65
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
70
struct xlx_timer *xt;
66
index XXXXXXX..XXXXXXX 100644
71
unsigned int timer;
67
--- a/target/arm/translate-mve.c
72
uint32_t value = val64;
68
+++ b/target/arm/translate-mve.c
73
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps timer_ops = {
69
@@ -XXX,XX +XXX,XX @@ static bool trans_VPST(DisasContext *s, arg_VPST *a)
74
static void timer_hit(void *opaque)
70
return true;
75
{
76
struct xlx_timer *xt = opaque;
77
- struct timerblock *t = xt->parent;
78
+ XpsTimerState *t = xt->parent;
79
D(fprintf(stderr, "%s %d\n", __func__, xt->nr));
80
xt->regs[R_TCSR] |= TCSR_TINT;
81
82
@@ -XXX,XX +XXX,XX @@ static void timer_hit(void *opaque)
83
84
static void xilinx_timer_realize(DeviceState *dev, Error **errp)
85
{
86
- struct timerblock *t = XILINX_TIMER(dev);
87
+ XpsTimerState *t = XILINX_TIMER(dev);
88
unsigned int i;
89
90
/* Init all the ptimers. */
91
@@ -XXX,XX +XXX,XX @@ static void xilinx_timer_realize(DeviceState *dev, Error **errp)
92
93
static void xilinx_timer_init(Object *obj)
94
{
95
- struct timerblock *t = XILINX_TIMER(obj);
96
+ XpsTimerState *t = XILINX_TIMER(obj);
97
98
/* All timers share a single irq line. */
99
sysbus_init_irq(SYS_BUS_DEVICE(obj), &t->irq);
71
}
100
}
72
101
73
+static bool trans_VPNOT(DisasContext *s, arg_VPNOT *a)
102
static Property xilinx_timer_properties[] = {
74
+{
103
- DEFINE_PROP_UINT32("clock-frequency", struct timerblock, freq_hz,
75
+ /*
104
- 62 * 1000000),
76
+ * Invert the predicate in VPR.P0. We have call out to
105
- DEFINE_PROP_UINT8("one-timer-only", struct timerblock, one_timer_only, 0),
77
+ * a helper because this insn itself is beatwise and can
106
+ DEFINE_PROP_UINT32("clock-frequency", XpsTimerState, freq_hz, 62 * 1000000),
78
+ * be predicated.
107
+ DEFINE_PROP_UINT8("one-timer-only", XpsTimerState, one_timer_only, 0),
79
+ */
108
DEFINE_PROP_END_OF_LIST(),
80
+ if (!dc_isar_feature(aa32_mve, s)) {
109
};
81
+ return false;
110
82
+ }
111
@@ -XXX,XX +XXX,XX @@ static void xilinx_timer_class_init(ObjectClass *klass, void *data)
83
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
112
static const TypeInfo xilinx_timer_info = {
84
+ return true;
113
.name = TYPE_XILINX_TIMER,
85
+ }
114
.parent = TYPE_SYS_BUS_DEVICE,
86
+
115
- .instance_size = sizeof(struct timerblock),
87
+ gen_helper_mve_vpnot(cpu_env);
116
+ .instance_size = sizeof(XpsTimerState),
88
+ mve_update_eci(s);
117
.instance_init = xilinx_timer_init,
89
+ return true;
118
.class_init = xilinx_timer_class_init,
90
+}
119
};
91
+
92
static bool trans_VADDV(DisasContext *s, arg_VADDV *a)
93
{
94
/* VADDV: vector add across vector */
95
--
120
--
96
2.20.1
121
2.34.1
97
122
98
123
diff view generated by jsdifflib
1
We're about to make a code change to the sdiv and udiv helper
1
From: Evgeny Iakovlev <eiakovlev@linux.microsoft.com>
2
functions, so first fix their indentation and coding style.
3
2
3
ARM trusted firmware, when built with FEAT_HCX support, sets SCR_EL3.HXEn bit
4
to allow EL2 to modify HCRX_EL2 register without trapping it in EL3. Qemu
5
uses a valid mask to clear unsupported SCR_EL3 bits when emulating SCR_EL3
6
write, and that mask doesn't include SCR_EL3.HXEn bit even if FEAT_HCX is
7
enabled and exposed to the guest. As a result EL3 writes of that bit are
8
ignored.
9
10
Cc: qemu-stable@nongnu.org
11
Signed-off-by: Evgeny Iakovlev <eiakovlev@linux.microsoft.com>
12
Message-id: 20230105221251.17896-4-eiakovlev@linux.microsoft.com
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210730151636.17254-2-peter.maydell@linaro.org
7
---
15
---
8
target/arm/helper.c | 15 +++++++++------
16
target/arm/helper.c | 3 +++
9
1 file changed, 9 insertions(+), 6 deletions(-)
17
1 file changed, 3 insertions(+)
10
18
11
diff --git a/target/arm/helper.c b/target/arm/helper.c
19
diff --git a/target/arm/helper.c b/target/arm/helper.c
12
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/helper.c
21
--- a/target/arm/helper.c
14
+++ b/target/arm/helper.c
22
+++ b/target/arm/helper.c
15
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(uxtb16)(uint32_t x)
23
@@ -XXX,XX +XXX,XX @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
16
24
if (cpu_isar_feature(aa64_sme, cpu)) {
17
int32_t HELPER(sdiv)(int32_t num, int32_t den)
25
valid_mask |= SCR_ENTP2;
18
{
26
}
19
- if (den == 0)
27
+ if (cpu_isar_feature(aa64_hcx, cpu)) {
20
- return 0;
28
+ valid_mask |= SCR_HXEN;
21
- if (num == INT_MIN && den == -1)
29
+ }
22
- return INT_MIN;
30
} else {
23
+ if (den == 0) {
31
valid_mask &= ~(SCR_RW | SCR_ST);
24
+ return 0;
32
if (cpu_isar_feature(aa32_ras, cpu)) {
25
+ }
26
+ if (num == INT_MIN && den == -1) {
27
+ return INT_MIN;
28
+ }
29
return num / den;
30
}
31
32
uint32_t HELPER(udiv)(uint32_t num, uint32_t den)
33
{
34
- if (den == 0)
35
- return 0;
36
+ if (den == 0) {
37
+ return 0;
38
+ }
39
return num / den;
40
}
41
42
--
33
--
43
2.20.1
34
2.34.1
44
45
diff view generated by jsdifflib