1
The following changes since commit 53f306f316549d20c76886903181413d20842423:
1
The following changes since commit 3db29dcac23da85486704ef9e7a8e7217f7829cd:
2
2
3
Merge remote-tracking branch 'remotes/ehabkost-gl/tags/x86-next-pull-request' into staging (2021-06-21 11:26:04 +0100)
3
Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging (2023-01-12 13:51:36 +0000)
4
4
5
are available in the Git repository at:
5
are available in the Git repository at:
6
6
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210621
7
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20230113
8
8
9
for you to fetch changes up to a83f1d9263d281f938a3984cda7104d55affd43a:
9
for you to fetch changes up to 08899b5c68a55a3780d707e2464073c8f2670d31:
10
10
11
docs/system: arm: Add nRF boards description (2021-06-21 17:24:33 +0100)
11
target/arm: allow writes to SCR_EL3.HXEn bit when FEAT_HCX is enabled (2023-01-13 13:19:36 +0000)
12
12
13
----------------------------------------------------------------
13
----------------------------------------------------------------
14
target-arm queue:
14
target-arm queue:
15
* Don't require 'virt' board to be compiled in for ACPI GHES code
15
hw/arm/stm32f405: correctly describe the memory layout
16
* docs: Document which architecture extensions we emulate
16
hw/arm: Add Olimex H405 board
17
* Fix bugs in M-profile FPCXT_NS accesses
17
cubieboard: Support booting from an SD card image with u-boot on it
18
* First slice of MVE patches
18
target/arm: Fix sve_probe_page
19
* Implement MTE3
19
target/arm: allow writes to SCR_EL3.HXEn bit when FEAT_HCX is enabled
20
* docs/system: arm: Add nRF boards description
20
various code cleanups
21
21
22
----------------------------------------------------------------
22
----------------------------------------------------------------
23
Alexandre Iooss (1):
23
Evgeny Iakovlev (1):
24
docs/system: arm: Add nRF boards description
24
target/arm: allow writes to SCR_EL3.HXEn bit when FEAT_HCX is enabled
25
25
26
Peter Collingbourne (1):
26
Felipe Balbi (2):
27
target/arm: Implement MTE3
27
hw/arm/stm32f405: correctly describe the memory layout
28
hw/arm: Add Olimex H405
28
29
29
Peter Maydell (55):
30
Philippe Mathieu-Daudé (27):
30
hw/acpi: Provide stub version of acpi_ghes_record_errors()
31
hw/arm/pxa2xx: Simplify pxa255_init()
31
hw/acpi: Provide function acpi_ghes_present()
32
hw/arm/pxa2xx: Simplify pxa270_init()
32
target/arm: Use acpi_ghes_present() to see if we report ACPI memory errors
33
hw/arm/collie: Use the IEC binary prefix definitions
33
docs/system/arm: Document which architecture extensions we emulate
34
hw/arm/collie: Simplify flash creation using for() loop
34
target/arm/translate-vfp.c: Whitespace fixes
35
hw/arm/gumstix: Improve documentation
35
target/arm: Handle FPU being disabled in FPCXT_NS accesses
36
hw/arm/gumstix: Use the IEC binary prefix definitions
36
target/arm: Don't NOCP fault for FPCXT_NS accesses
37
hw/arm/mainstone: Use the IEC binary prefix definitions
37
target/arm: Handle writeback in VLDR/VSTR sysreg with no memory access
38
hw/arm/musicpal: Use the IEC binary prefix definitions
38
target/arm: Factor FP context update code out into helper function
39
hw/arm/omap_sx1: Remove unused 'total_ram' definitions
39
target/arm: Split vfp_access_check() into A and M versions
40
hw/arm/omap_sx1: Use the IEC binary prefix definitions
40
target/arm: Handle FPU check for FPCXT_NS insns via vfp_access_check_m()
41
hw/arm/z2: Use the IEC binary prefix definitions
41
target/arm: Implement MVE VLDR/VSTR (non-widening forms)
42
hw/arm/vexpress: Remove dead code in vexpress_common_init()
42
target/arm: Implement widening/narrowing MVE VLDR/VSTR insns
43
hw/arm: Remove unreachable code calling pflash_cfi01_register()
43
target/arm: Implement MVE VCLZ
44
hw/arm/pxa: Avoid forward-declaring PXA2xxI2CState
44
target/arm: Implement MVE VCLS
45
hw/gpio/omap_gpio: Add local variable to avoid embedded cast
45
target/arm: Implement MVE VREV16, VREV32, VREV64
46
hw/arm/omap: Drop useless casts from void * to pointer
46
target/arm: Implement MVE VMVN (register)
47
hw/gpio/omap_gpio: Use CamelCase for TYPE_OMAP1_GPIO type name
47
target/arm: Implement MVE VABS
48
hw/gpio/omap_gpio: Use CamelCase for TYPE_OMAP2_GPIO type name
48
target/arm: Implement MVE VNEG
49
hw/intc/omap_intc: Use CamelCase for TYPE_OMAP_INTC type name
49
tcg: Make gen_dup_i32/i64() public as tcg_gen_dup_i32/i64
50
hw/arm/stellaris: Drop useless casts from void * to pointer
50
target/arm: Implement MVE VDUP
51
hw/arm/stellaris: Use CamelCase for STELLARIS_ADC type name
51
target/arm: Implement MVE VAND, VBIC, VORR, VORN, VEOR
52
hw/arm/bcm2836: Remove definitions generated by OBJECT_DECLARE_TYPE()
52
target/arm: Implement MVE VADD, VSUB, VMUL
53
hw/arm/npcm7xx: Declare QOM macros using OBJECT_DECLARE_SIMPLE_TYPE()
53
target/arm: Implement MVE VMULH
54
hw/misc/sbsa_ec: Rename TYPE_SBSA_EC -> TYPE_SBSA_SECURE_EC
54
target/arm: Implement MVE VRMULH
55
hw/misc/sbsa_ec: Declare QOM macros using OBJECT_DECLARE_SIMPLE_TYPE()
55
target/arm: Implement MVE VMAX, VMIN
56
hw/intc/xilinx_intc: Use 'XpsIntc' typedef instead of 'struct xlx_pic'
56
target/arm: Implement MVE VABD
57
hw/timer/xilinx_timer: Use XpsTimerState instead of 'struct timerblock'
57
target/arm: Implement MVE VHADD, VHSUB
58
target/arm: Implement MVE VMULL
59
target/arm: Implement MVE VMLALDAV
60
target/arm: Implement MVE VMLSLDAV
61
target/arm: Implement MVE VRMLALDAVH, VRMLSLDAVH
62
target/arm: Implement MVE VADD (scalar)
63
target/arm: Implement MVE VSUB, VMUL (scalar)
64
target/arm: Implement MVE VHADD, VHSUB (scalar)
65
target/arm: Implement MVE VBRSR
66
target/arm: Implement MVE VPST
67
target/arm: Implement MVE VQADD and VQSUB
68
target/arm: Implement MVE VQDMULH and VQRDMULH (scalar)
69
target/arm: Implement MVE VQDMULL scalar
70
target/arm: Implement MVE VQDMULH, VQRDMULH (vector)
71
target/arm: Implement MVE VQADD, VQSUB (vector)
72
target/arm: Implement MVE VQSHL (vector)
73
target/arm: Implement MVE VQRSHL
74
target/arm: Implement MVE VSHL insn
75
target/arm: Implement MVE VRSHL
76
target/arm: Implement MVE VQDMLADH and VQRDMLADH
77
target/arm: Implement MVE VQDMLSDH and VQRDMLSDH
78
target/arm: Implement MVE VQDMULL (vector)
79
target/arm: Implement MVE VRHADD
80
target/arm: Implement MVE VADC, VSBC
81
target/arm: Implement MVE VCADD
82
target/arm: Implement MVE VHCADD
83
target/arm: Implement MVE VADDV
84
target/arm: Make VMOV scalar <-> gpreg beatwise for MVE
85
58
86
docs/system/arm/emulation.rst | 103 ++++
59
Richard Henderson (1):
87
docs/system/arm/nrf.rst | 51 ++
60
target/arm: Fix sve_probe_page
88
docs/system/target-arm.rst | 7 +
89
include/hw/acpi/ghes.h | 9 +
90
include/tcg/tcg-op.h | 8 +
91
include/tcg/tcg.h | 1 -
92
target/arm/helper-mve.h | 357 +++++++++++++
93
target/arm/helper.h | 2 +
94
target/arm/internals.h | 11 +
95
target/arm/translate-a32.h | 3 +
96
target/arm/translate.h | 10 +
97
target/arm/m-nocp.decode | 24 +
98
target/arm/mve.decode | 240 +++++++++
99
target/arm/vfp.decode | 14 -
100
hw/acpi/ghes-stub.c | 22 +
101
hw/acpi/ghes.c | 17 +
102
target/arm/cpu64.c | 2 +-
103
target/arm/kvm64.c | 6 +-
104
target/arm/mte_helper.c | 82 +--
105
target/arm/mve_helper.c | 1160 +++++++++++++++++++++++++++++++++++++++++
106
target/arm/translate-m-nocp.c | 550 +++++++++++++++++++
107
target/arm/translate-mve.c | 759 +++++++++++++++++++++++++++
108
target/arm/translate-vfp.c | 741 +++++++-------------------
109
tcg/tcg-op-gvec.c | 20 +-
110
MAINTAINERS | 1 +
111
hw/acpi/meson.build | 6 +-
112
target/arm/meson.build | 1 +
113
27 files changed, 3578 insertions(+), 629 deletions(-)
114
create mode 100644 docs/system/arm/emulation.rst
115
create mode 100644 docs/system/arm/nrf.rst
116
create mode 100644 target/arm/helper-mve.h
117
create mode 100644 hw/acpi/ghes-stub.c
118
create mode 100644 target/arm/mve_helper.c
119
61
62
Strahinja Jankovic (7):
63
hw/misc: Allwinner-A10 Clock Controller Module Emulation
64
hw/misc: Allwinner A10 DRAM Controller Emulation
65
{hw/i2c,docs/system/arm}: Allwinner TWI/I2C Emulation
66
hw/misc: AXP209 PMU Emulation
67
hw/arm: Add AXP209 to Cubieboard
68
hw/arm: Allwinner A10 enable SPL load from MMC
69
tests/avocado: Add SD boot test to Cubieboard
70
71
docs/system/arm/cubieboard.rst | 1 +
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
156
diff view generated by jsdifflib
1
Implement the MVE VADDV insn, which performs an addition
1
From: Felipe Balbi <balbi@kernel.org>
2
across vector lanes.
3
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
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210617121628.20116-44-peter.maydell@linaro.org
7
---
12
---
8
target/arm/helper-mve.h | 7 +++++++
13
include/hw/arm/stm32f405_soc.h | 5 ++++-
9
target/arm/mve.decode | 2 ++
14
hw/arm/stm32f405_soc.c | 8 ++++++++
10
target/arm/mve_helper.c | 24 +++++++++++++++++++++
15
2 files changed, 12 insertions(+), 1 deletion(-)
11
target/arm/translate-mve.c | 43 ++++++++++++++++++++++++++++++++++++++
12
4 files changed, 76 insertions(+)
13
16
14
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
15
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-mve.h
19
--- a/include/hw/arm/stm32f405_soc.h
17
+++ b/target/arm/helper-mve.h
20
+++ b/include/hw/arm/stm32f405_soc.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vrmlaldavhuw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
21
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(STM32F405State, STM32F405_SOC)
19
22
#define FLASH_BASE_ADDRESS 0x08000000
20
DEF_HELPER_FLAGS_4(mve_vrmlsldavhsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
23
#define FLASH_SIZE (1024 * 1024)
21
DEF_HELPER_FLAGS_4(mve_vrmlsldavhxsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
24
#define SRAM_BASE_ADDRESS 0x20000000
25
-#define SRAM_SIZE (192 * 1024)
26
+#define SRAM_SIZE (128 * 1024)
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);
22
+
55
+
23
+DEF_HELPER_FLAGS_3(mve_vaddvsb, TCG_CALL_NO_WG, i32, env, ptr, i32)
56
armv7m = DEVICE(&s->armv7m);
24
+DEF_HELPER_FLAGS_3(mve_vaddvub, TCG_CALL_NO_WG, i32, env, ptr, i32)
57
qdev_prop_set_uint32(armv7m, "num-irq", 96);
25
+DEF_HELPER_FLAGS_3(mve_vaddvsh, TCG_CALL_NO_WG, i32, env, ptr, i32)
58
qdev_prop_set_string(armv7m, "cpu-type", s->cpu_type);
26
+DEF_HELPER_FLAGS_3(mve_vaddvuh, TCG_CALL_NO_WG, i32, env, ptr, i32)
27
+DEF_HELPER_FLAGS_3(mve_vaddvsw, TCG_CALL_NO_WG, i32, env, ptr, i32)
28
+DEF_HELPER_FLAGS_3(mve_vaddvuw, TCG_CALL_NO_WG, i32, env, ptr, i32)
29
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/mve.decode
32
+++ b/target/arm/mve.decode
33
@@ -XXX,XX +XXX,XX @@ VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
34
VQDMULH_scalar 1110 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
35
VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
36
37
+# Vector add across vector
38
+VADDV 111 u:1 1110 1111 size:2 01 ... 0 1111 0 0 a:1 0 qm:3 0 rda=%rdalo
39
40
# Predicate operations
41
%mask_22_13 22:1 13:3
42
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/mve_helper.c
45
+++ b/target/arm/mve_helper.c
46
@@ -XXX,XX +XXX,XX @@ DO_LDAVH(vrmlaldavhuw, 4, uint32_t, false, int128_add, int128_add, int128_make64
47
48
DO_LDAVH(vrmlsldavhsw, 4, int32_t, false, int128_add, int128_sub, int128_makes64)
49
DO_LDAVH(vrmlsldavhxsw, 4, int32_t, true, int128_add, int128_sub, int128_makes64)
50
+
51
+/* Vector add across vector */
52
+#define DO_VADDV(OP, ESIZE, TYPE) \
53
+ uint32_t HELPER(glue(mve_, OP))(CPUARMState *env, void *vm, \
54
+ uint32_t ra) \
55
+ { \
56
+ uint16_t mask = mve_element_mask(env); \
57
+ unsigned e; \
58
+ TYPE *m = vm; \
59
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
60
+ if (mask & 1) { \
61
+ ra += m[H##ESIZE(e)]; \
62
+ } \
63
+ } \
64
+ mve_advance_vpt(env); \
65
+ return ra; \
66
+ } \
67
+
68
+DO_VADDV(vaddvsb, 1, uint8_t)
69
+DO_VADDV(vaddvsh, 2, uint16_t)
70
+DO_VADDV(vaddvsw, 4, uint32_t)
71
+DO_VADDV(vaddvub, 1, uint8_t)
72
+DO_VADDV(vaddvuh, 2, uint16_t)
73
+DO_VADDV(vaddvuw, 4, uint32_t)
74
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
75
index XXXXXXX..XXXXXXX 100644
76
--- a/target/arm/translate-mve.c
77
+++ b/target/arm/translate-mve.c
78
@@ -XXX,XX +XXX,XX @@ typedef void MVEGenOneOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
79
typedef void MVEGenTwoOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr);
80
typedef void MVEGenTwoOpScalarFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
81
typedef void MVEGenDualAccOpFn(TCGv_i64, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i64);
82
+typedef void MVEGenVADDVFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32);
83
84
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
85
static inline long mve_qreg_offset(unsigned reg)
86
@@ -XXX,XX +XXX,XX @@ static bool trans_VPST(DisasContext *s, arg_VPST *a)
87
mve_update_and_store_eci(s);
88
return true;
89
}
90
+
91
+static bool trans_VADDV(DisasContext *s, arg_VADDV *a)
92
+{
93
+ /* VADDV: vector add across vector */
94
+ static MVEGenVADDVFn * const fns[4][2] = {
95
+ { gen_helper_mve_vaddvsb, gen_helper_mve_vaddvub },
96
+ { gen_helper_mve_vaddvsh, gen_helper_mve_vaddvuh },
97
+ { gen_helper_mve_vaddvsw, gen_helper_mve_vaddvuw },
98
+ { NULL, NULL }
99
+ };
100
+ TCGv_ptr qm;
101
+ TCGv_i32 rda;
102
+
103
+ if (!dc_isar_feature(aa32_mve, s) ||
104
+ a->size == 3) {
105
+ return false;
106
+ }
107
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
108
+ return true;
109
+ }
110
+
111
+ /*
112
+ * This insn is subject to beat-wise execution. Partial execution
113
+ * of an A=0 (no-accumulate) insn which does not execute the first
114
+ * beat must start with the current value of Rda, not zero.
115
+ */
116
+ if (a->a || mve_skip_first_beat(s)) {
117
+ /* Accumulate input from Rda */
118
+ rda = load_reg(s, a->rda);
119
+ } else {
120
+ /* Accumulate starting at zero */
121
+ rda = tcg_const_i32(0);
122
+ }
123
+
124
+ qm = mve_qreg_ptr(a->qm);
125
+ fns[a->size][a->u](rda, cpu_env, qm, rda);
126
+ store_reg(s, a->rda, rda);
127
+ tcg_temp_free_ptr(qm);
128
+
129
+ mve_update_eci(s);
130
+ return true;
131
+}
132
--
59
--
133
2.20.1
60
2.34.1
134
61
135
62
diff view generated by jsdifflib
1
From: Alexandre Iooss <erdnaxe@crans.org>
1
From: Felipe Balbi <balbi@kernel.org>
2
2
3
This adds the target guide for BBC Micro:bit.
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
4
5
5
Information is taken from https://wiki.qemu.org/Features/MicroBit
6
[1] https://www.olimex.com/Products/ARM/ST/STM32-H405/
6
and from hw/arm/nrf51_soc.c.
7
7
8
Signed-off-by: Alexandre Iooss <erdnaxe@crans.org>
8
Signed-off-by: Felipe Balbi <balbi@kernel.org>
9
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
10
Reviewed-by: Joel Stanley <joel@jms.id.au>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Message-id: 20210621075625.540471-1-erdnaxe@crans.org
11
Message-id: 20221230145733.200496-3-balbi@kernel.org
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
13
---
14
docs/system/arm/nrf.rst | 51 ++++++++++++++++++++++++++++++++++++++
14
docs/system/arm/stm32.rst | 1 +
15
docs/system/target-arm.rst | 1 +
15
configs/devices/arm-softmmu/default.mak | 1 +
16
MAINTAINERS | 1 +
16
hw/arm/olimex-stm32-h405.c | 69 +++++++++++++++++++++++++
17
3 files changed, 53 insertions(+)
17
MAINTAINERS | 6 +++
18
create mode 100644 docs/system/arm/nrf.rst
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
19
22
20
diff --git a/docs/system/arm/nrf.rst b/docs/system/arm/nrf.rst
23
diff --git a/docs/system/arm/stm32.rst b/docs/system/arm/stm32.rst
24
index XXXXXXX..XXXXXXX 100644
25
--- a/docs/system/arm/stm32.rst
26
+++ b/docs/system/arm/stm32.rst
27
@@ -XXX,XX +XXX,XX @@ The STM32F4 series is based on ARM Cortex-M4F core. This series is pin-to-pin
28
compatible with STM32F2 series. The following machines are based on this chip :
29
30
- ``netduinoplus2`` Netduino Plus 2 board with STM32F405RGT6 microcontroller
31
+- ``olimex-stm32-h405`` Olimex STM32 H405 board with STM32F405RGT6 microcontroller
32
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
21
new file mode 100644
48
new file mode 100644
22
index XXXXXXX..XXXXXXX
49
index XXXXXXX..XXXXXXX
23
--- /dev/null
50
--- /dev/null
24
+++ b/docs/system/arm/nrf.rst
51
+++ b/hw/arm/olimex-stm32-h405.c
25
@@ -XXX,XX +XXX,XX @@
52
@@ -XXX,XX +XXX,XX @@
26
+Nordic nRF boards (``microbit``)
53
+/*
27
+================================
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
+ */
28
+
77
+
29
+The `Nordic nRF`_ chips are a family of ARM-based System-on-Chip that
78
+#include "qemu/osdep.h"
30
+are designed to be used for low-power and short-range wireless solutions.
79
+#include "qapi/error.h"
80
+#include "hw/boards.h"
81
+#include "hw/qdev-properties.h"
82
+#include "hw/qdev-clock.h"
83
+#include "qemu/error-report.h"
84
+#include "hw/arm/stm32f405_soc.h"
85
+#include "hw/arm/boot.h"
31
+
86
+
32
+.. _Nordic nRF: https://www.nordicsemi.com/Products
87
+/* olimex-stm32-h405 implementation is derived from netduinoplus2 */
33
+
88
+
34
+The nRF51 series is the first series for short range wireless applications.
89
+/* Main SYSCLK frequency in Hz (168MHz) */
35
+It is superseded by the nRF52 series.
90
+#define SYSCLK_FRQ 168000000ULL
36
+The following machines are based on this chip :
37
+
91
+
38
+- ``microbit`` BBC micro:bit board with nRF51822 SoC
92
+static void olimex_stm32_h405_init(MachineState *machine)
93
+{
94
+ DeviceState *dev;
95
+ Clock *sysclk;
39
+
96
+
40
+There are other series such as nRF52, nRF53 and nRF91 which are currently not
97
+ /* This clock doesn't need migration because it is fixed-frequency */
41
+supported by QEMU.
98
+ sysclk = clock_new(OBJECT(machine), "SYSCLK");
99
+ clock_set_hz(sysclk, SYSCLK_FRQ);
42
+
100
+
43
+Supported devices
101
+ dev = qdev_new(TYPE_STM32F405_SOC);
44
+-----------------
102
+ qdev_prop_set_string(dev, "cpu-type", ARM_CPU_TYPE_NAME("cortex-m4"));
103
+ qdev_connect_clock_in(dev, "sysclk", sysclk);
104
+ sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
45
+
105
+
46
+ * ARM Cortex-M0 (ARMv6-M)
106
+ armv7m_load_kernel(ARM_CPU(first_cpu),
47
+ * Serial ports (UART)
107
+ machine->kernel_filename,
48
+ * Clock controller
108
+ 0, FLASH_SIZE);
49
+ * Timers
109
+}
50
+ * Random Number Generator (RNG)
51
+ * GPIO controller
52
+ * NVMC
53
+ * SWI
54
+
110
+
55
+Missing devices
111
+static void olimex_stm32_h405_machine_init(MachineClass *mc)
56
+---------------
112
+{
113
+ mc->desc = "Olimex STM32-H405 (Cortex-M4)";
114
+ mc->init = olimex_stm32_h405_init;
115
+ mc->default_cpu_type = ARM_CPU_TYPE_NAME("cortex-m4");
57
+
116
+
58
+ * Watchdog
117
+ /* SRAM pre-allocated as part of the SoC instantiation */
59
+ * Real-Time Clock (RTC) controller
118
+ mc->default_ram_size = 0;
60
+ * TWI (i2c)
119
+}
61
+ * SPI controller
62
+ * Analog to Digital Converter (ADC)
63
+ * Quadrature decoder
64
+ * Radio
65
+
120
+
66
+Boot options
121
+DEFINE_MACHINE("olimex-stm32-h405", olimex_stm32_h405_machine_init)
67
+------------
68
+
69
+The Micro:bit machine can be started using the ``-device`` option to load a
70
+firmware in `ihex format`_. Example:
71
+
72
+.. _ihex format: https://en.wikipedia.org/wiki/Intel_HEX
73
+
74
+.. code-block:: bash
75
+
76
+ $ qemu-system-arm -M microbit -device loader,file=test.hex
77
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
78
index XXXXXXX..XXXXXXX 100644
79
--- a/docs/system/target-arm.rst
80
+++ b/docs/system/target-arm.rst
81
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
82
arm/digic
83
arm/musicpal
84
arm/gumstix
85
+ arm/nrf
86
arm/nseries
87
arm/nuvoton
88
arm/orangepi
89
diff --git a/MAINTAINERS b/MAINTAINERS
122
diff --git a/MAINTAINERS b/MAINTAINERS
90
index XXXXXXX..XXXXXXX 100644
123
index XXXXXXX..XXXXXXX 100644
91
--- a/MAINTAINERS
124
--- a/MAINTAINERS
92
+++ b/MAINTAINERS
125
+++ b/MAINTAINERS
93
@@ -XXX,XX +XXX,XX @@ F: hw/*/microbit*.c
126
@@ -XXX,XX +XXX,XX @@ L: qemu-arm@nongnu.org
94
F: include/hw/*/nrf51*.h
127
S: Maintained
95
F: include/hw/*/microbit*.h
128
F: hw/arm/netduinoplus2.c
96
F: tests/qtest/microbit-test.c
129
97
+F: docs/system/arm/nrf.rst
130
+Olimex STM32 H405
98
131
+M: Felipe Balbi <balbi@kernel.org>
99
AVR Machines
132
+L: qemu-arm@nongnu.org
100
-------------
133
+S: Maintained
134
+F: hw/arm/olimex-stm32-h405.c
135
+
136
SmartFusion2
137
M: Subbaraya Sundeep <sundeep.lkml@gmail.com>
138
M: Peter Maydell <peter.maydell@linaro.org>
139
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
140
index XXXXXXX..XXXXXXX 100644
141
--- a/hw/arm/Kconfig
142
+++ b/hw/arm/Kconfig
143
@@ -XXX,XX +XXX,XX @@ config NETDUINOPLUS2
144
bool
145
select STM32F405_SOC
146
147
+config OLIMEX_STM32_H405
148
+ bool
149
+ select STM32F405_SOC
150
+
151
config NSERIES
152
bool
153
select OMAP
154
diff --git a/hw/arm/meson.build b/hw/arm/meson.build
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'))
101
--
166
--
102
2.20.1
167
2.34.1
103
168
104
169
diff view generated by jsdifflib
1
The M-profile architecture requires that accesses to FPCXT_NS when
1
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
2
there is no active FP state must not take a NOCP fault even if the
3
FPU is disabled. We were not implementing this correctly, because
4
in our decode we catch the NOCP faults early in m-nocp.decode.
5
2
6
Fix this bug by moving all the handling of M-profile FP system
3
During SPL boot several Clock Controller Module (CCM) registers are
7
register accesses from vfp.decode into m-nocp.decode and putting
4
read, most important are PLL and Tuning, as well as divisor registers.
8
it above the NOCP blocks. This provides the correct behaviour:
9
* for accesses other than FPCXT_NS the trans functions call
10
vfp_access_check(), which will check for FPU disabled and
11
raise a NOCP exception if necessary
12
* for FPCXT_NS we have the special case code that doesn't
13
call vfp_access_check()
14
* when these trans functions want to raise an UNDEF they return
15
false, so the decoder will fall through into the NOCP blocks.
16
This means that NOCP correctly takes precedence over UNDEF
17
for these insns. (This is a difference from the other insns
18
handled by m-nocp.decode, where UNDEF takes precedence and
19
which we implement by having those trans functions call
20
unallocated_encoding() in the appropriate places.)
21
5
22
[Note for backport to stable: this commit has a semantic dependency
6
This patch adds these registers and initializes reset values from user's
23
on commit 9a486856e9173af, which was not marked as cc-stable because
7
guide.
24
we didn't know we'd need it for a for-stable bugfix.]
25
8
26
Cc: qemu-stable@nongnu.org
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
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
29
Message-id: 20210618141019.10671-4-peter.maydell@linaro.org
30
---
14
---
31
target/arm/translate-a32.h | 1 +
15
include/hw/arm/allwinner-a10.h | 2 +
32
target/arm/m-nocp.decode | 24 ++
16
include/hw/misc/allwinner-a10-ccm.h | 67 +++++++++
33
target/arm/vfp.decode | 14 -
17
hw/arm/allwinner-a10.c | 7 +
34
target/arm/translate-m-nocp.c | 514 +++++++++++++++++++++++++++++++++
18
hw/misc/allwinner-a10-ccm.c | 224 ++++++++++++++++++++++++++++
35
target/arm/translate-vfp.c | 517 +---------------------------------
19
hw/arm/Kconfig | 1 +
36
5 files changed, 542 insertions(+), 528 deletions(-)
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
37
25
38
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
39
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/translate-a32.h
28
--- a/include/hw/arm/allwinner-a10.h
41
+++ b/target/arm/translate-a32.h
29
+++ b/include/hw/arm/allwinner-a10.h
42
@@ -XXX,XX +XXX,XX @@ bool disas_neon_shared(DisasContext *s, uint32_t insn);
30
@@ -XXX,XX +XXX,XX @@
43
void load_reg_var(DisasContext *s, TCGv_i32 var, int reg);
31
#include "hw/usb/hcd-ohci.h"
44
void arm_gen_condlabel(DisasContext *s);
32
#include "hw/usb/hcd-ehci.h"
45
bool vfp_access_check(DisasContext *s);
33
#include "hw/rtc/allwinner-rtc.h"
46
+void gen_preserve_fp_state(DisasContext *s);
34
+#include "hw/misc/allwinner-a10-ccm.h"
47
void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop);
35
48
void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop);
36
#include "target/arm/cpu.h"
49
void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop);
37
#include "qom/object.h"
50
diff --git a/target/arm/m-nocp.decode b/target/arm/m-nocp.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
51
index XXXXXXX..XXXXXXX 100644
120
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/m-nocp.decode
121
--- a/hw/arm/allwinner-a10.c
53
+++ b/target/arm/m-nocp.decode
122
+++ b/hw/arm/allwinner-a10.c
54
@@ -XXX,XX +XXX,XX @@
123
@@ -XXX,XX +XXX,XX @@
55
124
#include "hw/usb/hcd-ohci.h"
56
&nocp cp
125
57
126
#define AW_A10_MMC0_BASE 0x01c0f000
58
+# M-profile VLDR/VSTR to sysreg
127
+#define AW_A10_CCM_BASE 0x01c20000
59
+%vldr_sysreg 22:1 13:3
128
#define AW_A10_PIC_REG_BASE 0x01c20400
60
+%imm7_0x4 0:7 !function=times_4
129
#define AW_A10_PIT_REG_BASE 0x01c20c00
61
+
130
#define AW_A10_UART0_REG_BASE 0x01c28000
62
+&vldr_sysreg rn reg imm a w p
131
@@ -XXX,XX +XXX,XX @@ static void aw_a10_init(Object *obj)
63
+@vldr_sysreg .... ... . a:1 . . . rn:4 ... . ... .. ....... \
132
64
+ reg=%vldr_sysreg imm=%imm7_0x4 &vldr_sysreg
133
object_initialize_child(obj, "timer", &s->timer, TYPE_AW_A10_PIT);
65
+
134
66
{
135
+ object_initialize_child(obj, "ccm", &s->ccm, TYPE_AW_A10_CCM);
67
# Special cases which do not take an early NOCP: VLLDM and VLSTM
136
+
68
VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 op:1 000 0000
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
69
@@ -XXX,XX +XXX,XX @@
156
@@ -XXX,XX +XXX,XX @@
70
VSCCLRM 1110 1100 1.01 1111 .... 1011 imm:7 0 vd=%vd_dp size=3
71
VSCCLRM 1110 1100 1.01 1111 .... 1010 imm:8 vd=%vd_sp size=2
72
73
+ # FP system register accesses: these are a special case because accesses
74
+ # to FPCXT_NS succeed even if the FPU is disabled. We therefore need
75
+ # to handle them before the big NOCP blocks. Note that within these
76
+ # insns NOCP still has higher priority than UNDEFs; this is implemented
77
+ # by their returning 'false' for UNDEF so as to fall through into the
78
+ # NOCP check (in contrast to VLLDM etc, which call unallocated_encoding()
79
+ # for the UNDEFs there that must take precedence over NOCP.)
80
+
81
+ VMSR_VMRS ---- 1110 111 l:1 reg:4 rt:4 1010 0001 0000
82
+
83
+ # P=0 W=0 is SEE "Related encodings", so split into two patterns
84
+ VLDR_sysreg ---- 110 1 . . w:1 1 .... ... 0 111 11 ....... @vldr_sysreg p=1
85
+ VLDR_sysreg ---- 110 0 . . 1 1 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
86
+ VSTR_sysreg ---- 110 1 . . w:1 0 .... ... 0 111 11 ....... @vldr_sysreg p=1
87
+ VSTR_sysreg ---- 110 0 . . 1 0 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
88
+
89
NOCP 111- 1110 ---- ---- ---- cp:4 ---- ---- &nocp
90
NOCP 111- 110- ---- ---- ---- cp:4 ---- ---- &nocp
91
# From v8.1M onwards this range will also NOCP:
92
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
93
index XXXXXXX..XXXXXXX 100644
94
--- a/target/arm/vfp.decode
95
+++ b/target/arm/vfp.decode
96
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR_hp ---- 1101 u:1 .0 l:1 rn:4 .... 1001 imm:8 vd=%vd_sp
97
VLDR_VSTR_sp ---- 1101 u:1 .0 l:1 rn:4 .... 1010 imm:8 vd=%vd_sp
98
VLDR_VSTR_dp ---- 1101 u:1 .0 l:1 rn:4 .... 1011 imm:8 vd=%vd_dp
99
100
-# M-profile VLDR/VSTR to sysreg
101
-%vldr_sysreg 22:1 13:3
102
-%imm7_0x4 0:7 !function=times_4
103
-
104
-&vldr_sysreg rn reg imm a w p
105
-@vldr_sysreg .... ... . a:1 . . . rn:4 ... . ... .. ....... \
106
- reg=%vldr_sysreg imm=%imm7_0x4 &vldr_sysreg
107
-
108
-# P=0 W=0 is SEE "Related encodings", so split into two patterns
109
-VLDR_sysreg ---- 110 1 . . w:1 1 .... ... 0 111 11 ....... @vldr_sysreg p=1
110
-VLDR_sysreg ---- 110 0 . . 1 1 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
111
-VSTR_sysreg ---- 110 1 . . w:1 0 .... ... 0 111 11 ....... @vldr_sysreg p=1
112
-VSTR_sysreg ---- 110 0 . . 1 0 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
113
-
114
# We split the load/store multiple up into two patterns to avoid
115
# overlap with other insns in the "Advanced SIMD load/store and 64-bit move"
116
# grouping:
117
diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c
118
index XXXXXXX..XXXXXXX 100644
119
--- a/target/arm/translate-m-nocp.c
120
+++ b/target/arm/translate-m-nocp.c
121
@@ -XXX,XX +XXX,XX @@
122
123
#include "qemu/osdep.h"
124
#include "tcg/tcg-op.h"
125
+#include "tcg/tcg-op-gvec.h"
126
#include "translate.h"
127
#include "translate-a32.h"
128
129
@@ -XXX,XX +XXX,XX @@ static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
130
return true;
131
}
132
133
+/*
157
+/*
134
+ * M-profile provides two different sets of instructions that can
158
+ * Allwinner A10 Clock Control Module emulation
135
+ * access floating point system registers: VMSR/VMRS (which move
159
+ *
136
+ * to/from a general purpose register) and VLDR/VSTR sysreg (which
160
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
137
+ * move directly to/from memory). In some cases there are also side
161
+ *
138
+ * effects which must happen after any write to memory (which could
162
+ * This file is derived from Allwinner H3 CCU,
139
+ * cause an exception). So we implement the common logic for the
163
+ * by Niek Linnenbank.
140
+ * sysreg access in gen_M_fp_sysreg_write() and gen_M_fp_sysreg_read(),
164
+ *
141
+ * which take pointers to callback functions which will perform the
165
+ * This program is free software: you can redistribute it and/or modify
142
+ * actual "read/write general purpose register" and "read/write
166
+ * it under the terms of the GNU General Public License as published by
143
+ * memory" operations.
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/>.
144
+ */
177
+ */
145
+
178
+
146
+/*
179
+#include "qemu/osdep.h"
147
+ * Emit code to store the sysreg to its final destination; frees the
180
+#include "qemu/units.h"
148
+ * TCG temp 'value' it is passed.
181
+#include "hw/sysbus.h"
149
+ */
182
+#include "migration/vmstate.h"
150
+typedef void fp_sysreg_storefn(DisasContext *s, void *opaque, TCGv_i32 value);
183
+#include "qemu/log.h"
151
+/*
184
+#include "qemu/module.h"
152
+ * Emit code to load the value to be copied to the sysreg; returns
185
+#include "hw/misc/allwinner-a10-ccm.h"
153
+ * a new TCG temporary
186
+
154
+ */
187
+/* CCM register offsets */
155
+typedef TCGv_i32 fp_sysreg_loadfn(DisasContext *s, void *opaque);
188
+enum {
156
+
189
+ REG_PLL1_CFG = 0x0000, /* PLL1 Control */
157
+/* Common decode/access checks for fp sysreg read/write */
190
+ REG_PLL1_TUN = 0x0004, /* PLL1 Tuning */
158
+typedef enum FPSysRegCheckResult {
191
+ REG_PLL2_CFG = 0x0008, /* PLL2 Control */
159
+ FPSysRegCheckFailed, /* caller should return false */
192
+ REG_PLL2_TUN = 0x000C, /* PLL2 Tuning */
160
+ FPSysRegCheckDone, /* caller should return true */
193
+ REG_PLL3_CFG = 0x0010, /* PLL3 Control */
161
+ FPSysRegCheckContinue, /* caller should continue generating code */
194
+ REG_PLL4_CFG = 0x0018, /* PLL4 Control */
162
+} FPSysRegCheckResult;
195
+ REG_PLL5_CFG = 0x0020, /* PLL5 Control */
163
+
196
+ REG_PLL5_TUN = 0x0024, /* PLL5 Tuning */
164
+static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
197
+ REG_PLL6_CFG = 0x0028, /* PLL6 Control */
165
+{
198
+ REG_PLL6_TUN = 0x002C, /* PLL6 Tuning */
166
+ if (!dc_isar_feature(aa32_fpsp_v2, s) && !dc_isar_feature(aa32_mve, s)) {
199
+ REG_PLL7_CFG = 0x0030, /* PLL7 Control */
167
+ return FPSysRegCheckFailed;
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;
168
+ }
261
+ }
169
+
262
+
170
+ switch (regno) {
263
+ return s->regs[idx];
171
+ case ARM_VFP_FPSCR:
264
+}
172
+ case QEMU_VFP_FPSCR_NZCV:
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:
173
+ break;
289
+ break;
174
+ case ARM_VFP_FPSCR_NZCVQC:
290
+ case 0x158 ... AW_A10_CCM_IOSIZE:
175
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
291
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
176
+ return FPSysRegCheckFailed;
292
+ __func__, (uint32_t)offset);
177
+ }
178
+ break;
179
+ case ARM_VFP_FPCXT_S:
180
+ case ARM_VFP_FPCXT_NS:
181
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
182
+ return FPSysRegCheckFailed;
183
+ }
184
+ if (!s->v8m_secure) {
185
+ return FPSysRegCheckFailed;
186
+ }
187
+ break;
188
+ case ARM_VFP_VPR:
189
+ case ARM_VFP_P0:
190
+ if (!dc_isar_feature(aa32_mve, s)) {
191
+ return FPSysRegCheckFailed;
192
+ }
193
+ break;
293
+ break;
194
+ default:
294
+ default:
195
+ return FPSysRegCheckFailed;
295
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented write offset 0x%04x\n",
196
+ }
296
+ __func__, (uint32_t)offset);
197
+
198
+ /*
199
+ * FPCXT_NS is a special case: it has specific handling for
200
+ * "current FP state is inactive", and must do the PreserveFPState()
201
+ * but not the usual full set of actions done by ExecuteFPCheck().
202
+ * So we don't call vfp_access_check() and the callers must handle this.
203
+ */
204
+ if (regno != ARM_VFP_FPCXT_NS && !vfp_access_check(s)) {
205
+ return FPSysRegCheckDone;
206
+ }
207
+ return FPSysRegCheckContinue;
208
+}
209
+
210
+static void gen_branch_fpInactive(DisasContext *s, TCGCond cond,
211
+ TCGLabel *label)
212
+{
213
+ /*
214
+ * FPCXT_NS is a special case: it has specific handling for
215
+ * "current FP state is inactive", and must do the PreserveFPState()
216
+ * but not the usual full set of actions done by ExecuteFPCheck().
217
+ * We don't have a TB flag that matches the fpInactive check, so we
218
+ * do it at runtime as we don't expect FPCXT_NS accesses to be frequent.
219
+ *
220
+ * Emit code that checks fpInactive and does a conditional
221
+ * branch to label based on it:
222
+ * if cond is TCG_COND_NE then branch if fpInactive != 0 (ie if inactive)
223
+ * if cond is TCG_COND_EQ then branch if fpInactive == 0 (ie if active)
224
+ */
225
+ assert(cond == TCG_COND_EQ || cond == TCG_COND_NE);
226
+
227
+ /* fpInactive = FPCCR_NS.ASPEN == 1 && CONTROL.FPCA == 0 */
228
+ TCGv_i32 aspen, fpca;
229
+ aspen = load_cpu_field(v7m.fpccr[M_REG_NS]);
230
+ fpca = load_cpu_field(v7m.control[M_REG_S]);
231
+ tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
232
+ tcg_gen_xori_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
233
+ tcg_gen_andi_i32(fpca, fpca, R_V7M_CONTROL_FPCA_MASK);
234
+ tcg_gen_or_i32(fpca, fpca, aspen);
235
+ tcg_gen_brcondi_i32(tcg_invert_cond(cond), fpca, 0, label);
236
+ tcg_temp_free_i32(aspen);
237
+ tcg_temp_free_i32(fpca);
238
+}
239
+
240
+static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
241
+ fp_sysreg_loadfn *loadfn,
242
+ void *opaque)
243
+{
244
+ /* Do a write to an M-profile floating point system register */
245
+ TCGv_i32 tmp;
246
+ TCGLabel *lab_end = NULL;
247
+
248
+ switch (fp_sysreg_checks(s, regno)) {
249
+ case FPSysRegCheckFailed:
250
+ return false;
251
+ case FPSysRegCheckDone:
252
+ return true;
253
+ case FPSysRegCheckContinue:
254
+ break;
297
+ break;
255
+ }
298
+ }
256
+
299
+
257
+ switch (regno) {
300
+ s->regs[idx] = (uint32_t) val;
258
+ case ARM_VFP_FPSCR:
301
+}
259
+ tmp = loadfn(s, opaque);
302
+
260
+ gen_helper_vfp_set_fpscr(cpu_env, tmp);
303
+static const MemoryRegionOps allwinner_a10_ccm_ops = {
261
+ tcg_temp_free_i32(tmp);
304
+ .read = allwinner_a10_ccm_read,
262
+ gen_lookup_tb(s);
305
+ .write = allwinner_a10_ccm_write,
263
+ break;
306
+ .endianness = DEVICE_NATIVE_ENDIAN,
264
+ case ARM_VFP_FPSCR_NZCVQC:
307
+ .valid = {
265
+ {
308
+ .min_access_size = 4,
266
+ TCGv_i32 fpscr;
309
+ .max_access_size = 4,
267
+ tmp = loadfn(s, opaque);
310
+ },
268
+ if (dc_isar_feature(aa32_mve, s)) {
311
+ .impl.min_access_size = 4,
269
+ /* QC is only present for MVE; otherwise RES0 */
312
+};
270
+ TCGv_i32 qc = tcg_temp_new_i32();
313
+
271
+ tcg_gen_andi_i32(qc, tmp, FPCR_QC);
314
+static void allwinner_a10_ccm_reset_enter(Object *obj, ResetType type)
272
+ /*
315
+{
273
+ * The 4 vfp.qc[] fields need only be "zero" vs "non-zero";
316
+ AwA10ClockCtlState *s = AW_A10_CCM(obj);
274
+ * here writing the same value into all elements is simplest.
317
+
275
+ */
318
+ /* Set default values for registers */
276
+ tcg_gen_gvec_dup_i32(MO_32, offsetof(CPUARMState, vfp.qc),
319
+ s->regs[REG_INDEX(REG_PLL1_CFG)] = REG_PLL1_CFG_RST;
277
+ 16, 16, qc);
320
+ s->regs[REG_INDEX(REG_PLL1_TUN)] = REG_PLL1_TUN_RST;
278
+ }
321
+ s->regs[REG_INDEX(REG_PLL2_CFG)] = REG_PLL2_CFG_RST;
279
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
322
+ s->regs[REG_INDEX(REG_PLL2_TUN)] = REG_PLL2_TUN_RST;
280
+ fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
323
+ s->regs[REG_INDEX(REG_PLL3_CFG)] = REG_PLL3_CFG_RST;
281
+ tcg_gen_andi_i32(fpscr, fpscr, ~FPCR_NZCV_MASK);
324
+ s->regs[REG_INDEX(REG_PLL4_CFG)] = REG_PLL4_CFG_RST;
282
+ tcg_gen_or_i32(fpscr, fpscr, tmp);
325
+ s->regs[REG_INDEX(REG_PLL5_CFG)] = REG_PLL5_CFG_RST;
283
+ store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
326
+ s->regs[REG_INDEX(REG_PLL5_TUN)] = REG_PLL5_TUN_RST;
284
+ tcg_temp_free_i32(tmp);
327
+ s->regs[REG_INDEX(REG_PLL6_CFG)] = REG_PLL6_CFG_RST;
285
+ break;
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()
286
+ }
355
+ }
287
+ case ARM_VFP_FPCXT_NS:
356
+};
288
+ lab_end = gen_new_label();
357
+
289
+ /* fpInactive case: write is a NOP, so branch to end */
358
+static void allwinner_a10_ccm_class_init(ObjectClass *klass, void *data)
290
+ gen_branch_fpInactive(s, TCG_COND_NE, lab_end);
359
+{
291
+ /*
360
+ DeviceClass *dc = DEVICE_CLASS(klass);
292
+ * !fpInactive: if FPU disabled, take NOCP exception;
361
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
293
+ * otherwise PreserveFPState(), and then FPCXT_NS writes
362
+
294
+ * behave the same as FPCXT_S writes.
363
+ rc->phases.enter = allwinner_a10_ccm_reset_enter;
295
+ */
364
+ dc->vmsd = &allwinner_a10_ccm_vmstate;
296
+ if (s->fp_excp_el) {
365
+}
297
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
366
+
298
+ syn_uncategorized(), s->fp_excp_el);
367
+static const TypeInfo allwinner_a10_ccm_info = {
299
+ /*
368
+ .name = TYPE_AW_A10_CCM,
300
+ * This was only a conditional exception, so override
369
+ .parent = TYPE_SYS_BUS_DEVICE,
301
+ * gen_exception_insn()'s default to DISAS_NORETURN
370
+ .instance_init = allwinner_a10_ccm_init,
302
+ */
371
+ .instance_size = sizeof(AwA10ClockCtlState),
303
+ s->base.is_jmp = DISAS_NEXT;
372
+ .class_init = allwinner_a10_ccm_class_init,
304
+ break;
373
+};
305
+ }
374
+
306
+ gen_preserve_fp_state(s);
375
+static void allwinner_a10_ccm_register(void)
307
+ /* fall through */
376
+{
308
+ case ARM_VFP_FPCXT_S:
377
+ type_register_static(&allwinner_a10_ccm_info);
309
+ {
378
+}
310
+ TCGv_i32 sfpa, control;
379
+
311
+ /*
380
+type_init(allwinner_a10_ccm_register)
312
+ * Set FPSCR and CONTROL.SFPA from value; the new FPSCR takes
381
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
313
+ * bits [27:0] from value and zeroes bits [31:28].
314
+ */
315
+ tmp = loadfn(s, opaque);
316
+ sfpa = tcg_temp_new_i32();
317
+ tcg_gen_shri_i32(sfpa, tmp, 31);
318
+ control = load_cpu_field(v7m.control[M_REG_S]);
319
+ tcg_gen_deposit_i32(control, control, sfpa,
320
+ R_V7M_CONTROL_SFPA_SHIFT, 1);
321
+ store_cpu_field(control, v7m.control[M_REG_S]);
322
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
323
+ gen_helper_vfp_set_fpscr(cpu_env, tmp);
324
+ tcg_temp_free_i32(tmp);
325
+ tcg_temp_free_i32(sfpa);
326
+ break;
327
+ }
328
+ case ARM_VFP_VPR:
329
+ /* Behaves as NOP if not privileged */
330
+ if (IS_USER(s)) {
331
+ break;
332
+ }
333
+ tmp = loadfn(s, opaque);
334
+ store_cpu_field(tmp, v7m.vpr);
335
+ break;
336
+ case ARM_VFP_P0:
337
+ {
338
+ TCGv_i32 vpr;
339
+ tmp = loadfn(s, opaque);
340
+ vpr = load_cpu_field(v7m.vpr);
341
+ tcg_gen_deposit_i32(vpr, vpr, tmp,
342
+ R_V7M_VPR_P0_SHIFT, R_V7M_VPR_P0_LENGTH);
343
+ store_cpu_field(vpr, v7m.vpr);
344
+ tcg_temp_free_i32(tmp);
345
+ break;
346
+ }
347
+ default:
348
+ g_assert_not_reached();
349
+ }
350
+ if (lab_end) {
351
+ gen_set_label(lab_end);
352
+ }
353
+ return true;
354
+}
355
+
356
+static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
357
+ fp_sysreg_storefn *storefn,
358
+ void *opaque)
359
+{
360
+ /* Do a read from an M-profile floating point system register */
361
+ TCGv_i32 tmp;
362
+ TCGLabel *lab_end = NULL;
363
+ bool lookup_tb = false;
364
+
365
+ switch (fp_sysreg_checks(s, regno)) {
366
+ case FPSysRegCheckFailed:
367
+ return false;
368
+ case FPSysRegCheckDone:
369
+ return true;
370
+ case FPSysRegCheckContinue:
371
+ break;
372
+ }
373
+
374
+ if (regno == ARM_VFP_FPSCR_NZCVQC && !dc_isar_feature(aa32_mve, s)) {
375
+ /* QC is RES0 without MVE, so NZCVQC simplifies to NZCV */
376
+ regno = QEMU_VFP_FPSCR_NZCV;
377
+ }
378
+
379
+ switch (regno) {
380
+ case ARM_VFP_FPSCR:
381
+ tmp = tcg_temp_new_i32();
382
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
383
+ storefn(s, opaque, tmp);
384
+ break;
385
+ case ARM_VFP_FPSCR_NZCVQC:
386
+ tmp = tcg_temp_new_i32();
387
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
388
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCVQC_MASK);
389
+ storefn(s, opaque, tmp);
390
+ break;
391
+ case QEMU_VFP_FPSCR_NZCV:
392
+ /*
393
+ * Read just NZCV; this is a special case to avoid the
394
+ * helper call for the "VMRS to CPSR.NZCV" insn.
395
+ */
396
+ tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
397
+ tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
398
+ storefn(s, opaque, tmp);
399
+ break;
400
+ case ARM_VFP_FPCXT_S:
401
+ {
402
+ TCGv_i32 control, sfpa, fpscr;
403
+ /* Bits [27:0] from FPSCR, bit [31] from CONTROL.SFPA */
404
+ tmp = tcg_temp_new_i32();
405
+ sfpa = tcg_temp_new_i32();
406
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
407
+ tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
408
+ control = load_cpu_field(v7m.control[M_REG_S]);
409
+ tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
410
+ tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
411
+ tcg_gen_or_i32(tmp, tmp, sfpa);
412
+ tcg_temp_free_i32(sfpa);
413
+ /*
414
+ * Store result before updating FPSCR etc, in case
415
+ * it is a memory write which causes an exception.
416
+ */
417
+ storefn(s, opaque, tmp);
418
+ /*
419
+ * Now we must reset FPSCR from FPDSCR_NS, and clear
420
+ * CONTROL.SFPA; so we'll end the TB here.
421
+ */
422
+ tcg_gen_andi_i32(control, control, ~R_V7M_CONTROL_SFPA_MASK);
423
+ store_cpu_field(control, v7m.control[M_REG_S]);
424
+ fpscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
425
+ gen_helper_vfp_set_fpscr(cpu_env, fpscr);
426
+ tcg_temp_free_i32(fpscr);
427
+ lookup_tb = true;
428
+ break;
429
+ }
430
+ case ARM_VFP_FPCXT_NS:
431
+ {
432
+ TCGv_i32 control, sfpa, fpscr, fpdscr, zero;
433
+ TCGLabel *lab_active = gen_new_label();
434
+
435
+ lookup_tb = true;
436
+
437
+ gen_branch_fpInactive(s, TCG_COND_EQ, lab_active);
438
+ /* fpInactive case: reads as FPDSCR_NS */
439
+ TCGv_i32 tmp = load_cpu_field(v7m.fpdscr[M_REG_NS]);
440
+ storefn(s, opaque, tmp);
441
+ lab_end = gen_new_label();
442
+ tcg_gen_br(lab_end);
443
+
444
+ gen_set_label(lab_active);
445
+ /*
446
+ * !fpInactive: if FPU disabled, take NOCP exception;
447
+ * otherwise PreserveFPState(), and then FPCXT_NS
448
+ * reads the same as FPCXT_S.
449
+ */
450
+ if (s->fp_excp_el) {
451
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
452
+ syn_uncategorized(), s->fp_excp_el);
453
+ /*
454
+ * This was only a conditional exception, so override
455
+ * gen_exception_insn()'s default to DISAS_NORETURN
456
+ */
457
+ s->base.is_jmp = DISAS_NEXT;
458
+ break;
459
+ }
460
+ gen_preserve_fp_state(s);
461
+ tmp = tcg_temp_new_i32();
462
+ sfpa = tcg_temp_new_i32();
463
+ fpscr = tcg_temp_new_i32();
464
+ gen_helper_vfp_get_fpscr(fpscr, cpu_env);
465
+ tcg_gen_andi_i32(tmp, fpscr, ~FPCR_NZCV_MASK);
466
+ control = load_cpu_field(v7m.control[M_REG_S]);
467
+ tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
468
+ tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
469
+ tcg_gen_or_i32(tmp, tmp, sfpa);
470
+ tcg_temp_free_i32(control);
471
+ /* Store result before updating FPSCR, in case it faults */
472
+ storefn(s, opaque, tmp);
473
+ /* If SFPA is zero then set FPSCR from FPDSCR_NS */
474
+ fpdscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
475
+ zero = tcg_const_i32(0);
476
+ tcg_gen_movcond_i32(TCG_COND_EQ, fpscr, sfpa, zero, fpdscr, fpscr);
477
+ gen_helper_vfp_set_fpscr(cpu_env, fpscr);
478
+ tcg_temp_free_i32(zero);
479
+ tcg_temp_free_i32(sfpa);
480
+ tcg_temp_free_i32(fpdscr);
481
+ tcg_temp_free_i32(fpscr);
482
+ break;
483
+ }
484
+ case ARM_VFP_VPR:
485
+ /* Behaves as NOP if not privileged */
486
+ if (IS_USER(s)) {
487
+ break;
488
+ }
489
+ tmp = load_cpu_field(v7m.vpr);
490
+ storefn(s, opaque, tmp);
491
+ break;
492
+ case ARM_VFP_P0:
493
+ tmp = load_cpu_field(v7m.vpr);
494
+ tcg_gen_extract_i32(tmp, tmp, R_V7M_VPR_P0_SHIFT, R_V7M_VPR_P0_LENGTH);
495
+ storefn(s, opaque, tmp);
496
+ break;
497
+ default:
498
+ g_assert_not_reached();
499
+ }
500
+
501
+ if (lab_end) {
502
+ gen_set_label(lab_end);
503
+ }
504
+ if (lookup_tb) {
505
+ gen_lookup_tb(s);
506
+ }
507
+ return true;
508
+}
509
+
510
+static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value)
511
+{
512
+ arg_VMSR_VMRS *a = opaque;
513
+
514
+ if (a->rt == 15) {
515
+ /* Set the 4 flag bits in the CPSR */
516
+ gen_set_nzcv(value);
517
+ tcg_temp_free_i32(value);
518
+ } else {
519
+ store_reg(s, a->rt, value);
520
+ }
521
+}
522
+
523
+static TCGv_i32 gpr_to_fp_sysreg(DisasContext *s, void *opaque)
524
+{
525
+ arg_VMSR_VMRS *a = opaque;
526
+
527
+ return load_reg(s, a->rt);
528
+}
529
+
530
+static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
531
+{
532
+ /*
533
+ * Accesses to R15 are UNPREDICTABLE; we choose to undef.
534
+ * FPSCR -> r15 is a special case which writes to the PSR flags;
535
+ * set a->reg to a special value to tell gen_M_fp_sysreg_read()
536
+ * we only care about the top 4 bits of FPSCR there.
537
+ */
538
+ if (a->rt == 15) {
539
+ if (a->l && a->reg == ARM_VFP_FPSCR) {
540
+ a->reg = QEMU_VFP_FPSCR_NZCV;
541
+ } else {
542
+ return false;
543
+ }
544
+ }
545
+
546
+ if (a->l) {
547
+ /* VMRS, move FP system register to gp register */
548
+ return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_gpr, a);
549
+ } else {
550
+ /* VMSR, move gp register to FP system register */
551
+ return gen_M_fp_sysreg_write(s, a->reg, gpr_to_fp_sysreg, a);
552
+ }
553
+}
554
+
555
+static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
556
+{
557
+ arg_vldr_sysreg *a = opaque;
558
+ uint32_t offset = a->imm;
559
+ TCGv_i32 addr;
560
+
561
+ if (!a->a) {
562
+ offset = -offset;
563
+ }
564
+
565
+ addr = load_reg(s, a->rn);
566
+ if (a->p) {
567
+ tcg_gen_addi_i32(addr, addr, offset);
568
+ }
569
+
570
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
571
+ gen_helper_v8m_stackcheck(cpu_env, addr);
572
+ }
573
+
574
+ gen_aa32_st_i32(s, value, addr, get_mem_index(s),
575
+ MO_UL | MO_ALIGN | s->be_data);
576
+ tcg_temp_free_i32(value);
577
+
578
+ if (a->w) {
579
+ /* writeback */
580
+ if (!a->p) {
581
+ tcg_gen_addi_i32(addr, addr, offset);
582
+ }
583
+ store_reg(s, a->rn, addr);
584
+ } else {
585
+ tcg_temp_free_i32(addr);
586
+ }
587
+}
588
+
589
+static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
590
+{
591
+ arg_vldr_sysreg *a = opaque;
592
+ uint32_t offset = a->imm;
593
+ TCGv_i32 addr;
594
+ TCGv_i32 value = tcg_temp_new_i32();
595
+
596
+ if (!a->a) {
597
+ offset = -offset;
598
+ }
599
+
600
+ addr = load_reg(s, a->rn);
601
+ if (a->p) {
602
+ tcg_gen_addi_i32(addr, addr, offset);
603
+ }
604
+
605
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
606
+ gen_helper_v8m_stackcheck(cpu_env, addr);
607
+ }
608
+
609
+ gen_aa32_ld_i32(s, value, addr, get_mem_index(s),
610
+ MO_UL | MO_ALIGN | s->be_data);
611
+
612
+ if (a->w) {
613
+ /* writeback */
614
+ if (!a->p) {
615
+ tcg_gen_addi_i32(addr, addr, offset);
616
+ }
617
+ store_reg(s, a->rn, addr);
618
+ } else {
619
+ tcg_temp_free_i32(addr);
620
+ }
621
+ return value;
622
+}
623
+
624
+static bool trans_VLDR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
625
+{
626
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
627
+ return false;
628
+ }
629
+ if (a->rn == 15) {
630
+ return false;
631
+ }
632
+ return gen_M_fp_sysreg_write(s, a->reg, memory_to_fp_sysreg, a);
633
+}
634
+
635
+static bool trans_VSTR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
636
+{
637
+ if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
638
+ return false;
639
+ }
640
+ if (a->rn == 15) {
641
+ return false;
642
+ }
643
+ return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_memory, a);
644
+}
645
+
646
static bool trans_NOCP(DisasContext *s, arg_nocp *a)
647
{
648
/*
649
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
650
index XXXXXXX..XXXXXXX 100644
382
index XXXXXXX..XXXXXXX 100644
651
--- a/target/arm/translate-vfp.c
383
--- a/hw/arm/Kconfig
652
+++ b/target/arm/translate-vfp.c
384
+++ b/hw/arm/Kconfig
653
@@ -XXX,XX +XXX,XX @@ static inline long vfp_f16_offset(unsigned reg, bool top)
385
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10
654
* Generate code for M-profile lazy FP state preservation if needed;
386
select AHCI
655
* this corresponds to the pseudocode PreserveFPState() function.
387
select ALLWINNER_A10_PIT
656
*/
388
select ALLWINNER_A10_PIC
657
-static void gen_preserve_fp_state(DisasContext *s)
389
+ select ALLWINNER_A10_CCM
658
+void gen_preserve_fp_state(DisasContext *s)
390
select ALLWINNER_EMAC
659
{
391
select SERIAL
660
if (s->v7m_lspact) {
392
select UNIMP
661
/*
393
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
662
@@ -XXX,XX +XXX,XX @@ static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
394
index XXXXXXX..XXXXXXX 100644
663
return true;
395
--- a/hw/misc/Kconfig
664
}
396
+++ b/hw/misc/Kconfig
665
397
@@ -XXX,XX +XXX,XX @@ config VIRT_CTRL
666
-/*
398
config LASI
667
- * M-profile provides two different sets of instructions that can
399
bool
668
- * access floating point system registers: VMSR/VMRS (which move
400
669
- * to/from a general purpose register) and VLDR/VSTR sysreg (which
401
+config ALLWINNER_A10_CCM
670
- * move directly to/from memory). In some cases there are also side
402
+ bool
671
- * effects which must happen after any write to memory (which could
403
+
672
- * cause an exception). So we implement the common logic for the
404
source macio/Kconfig
673
- * sysreg access in gen_M_fp_sysreg_write() and gen_M_fp_sysreg_read(),
405
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
674
- * which take pointers to callback functions which will perform the
406
index XXXXXXX..XXXXXXX 100644
675
- * actual "read/write general purpose register" and "read/write
407
--- a/hw/misc/meson.build
676
- * memory" operations.
408
+++ b/hw/misc/meson.build
677
- */
409
@@ -XXX,XX +XXX,XX @@ subdir('macio')
678
-
410
679
-/*
411
softmmu_ss.add(when: 'CONFIG_IVSHMEM_DEVICE', if_true: files('ivshmem.c'))
680
- * Emit code to store the sysreg to its final destination; frees the
412
681
- * TCG temp 'value' it is passed.
413
+softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10_CCM', if_true: files('allwinner-a10-ccm.c'))
682
- */
414
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-ccu.c'))
683
-typedef void fp_sysreg_storefn(DisasContext *s, void *opaque, TCGv_i32 value);
415
specific_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-cpucfg.c'))
684
-/*
416
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-dramc.c'))
685
- * Emit code to load the value to be copied to the sysreg; returns
686
- * a new TCG temporary
687
- */
688
-typedef TCGv_i32 fp_sysreg_loadfn(DisasContext *s, void *opaque);
689
-
690
-/* Common decode/access checks for fp sysreg read/write */
691
-typedef enum FPSysRegCheckResult {
692
- FPSysRegCheckFailed, /* caller should return false */
693
- FPSysRegCheckDone, /* caller should return true */
694
- FPSysRegCheckContinue, /* caller should continue generating code */
695
-} FPSysRegCheckResult;
696
-
697
-static FPSysRegCheckResult fp_sysreg_checks(DisasContext *s, int regno)
698
-{
699
- if (!dc_isar_feature(aa32_fpsp_v2, s) && !dc_isar_feature(aa32_mve, s)) {
700
- return FPSysRegCheckFailed;
701
- }
702
-
703
- switch (regno) {
704
- case ARM_VFP_FPSCR:
705
- case QEMU_VFP_FPSCR_NZCV:
706
- break;
707
- case ARM_VFP_FPSCR_NZCVQC:
708
- if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
709
- return FPSysRegCheckFailed;
710
- }
711
- break;
712
- case ARM_VFP_FPCXT_S:
713
- case ARM_VFP_FPCXT_NS:
714
- if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
715
- return FPSysRegCheckFailed;
716
- }
717
- if (!s->v8m_secure) {
718
- return FPSysRegCheckFailed;
719
- }
720
- break;
721
- case ARM_VFP_VPR:
722
- case ARM_VFP_P0:
723
- if (!dc_isar_feature(aa32_mve, s)) {
724
- return FPSysRegCheckFailed;
725
- }
726
- break;
727
- default:
728
- return FPSysRegCheckFailed;
729
- }
730
-
731
- /*
732
- * FPCXT_NS is a special case: it has specific handling for
733
- * "current FP state is inactive", and must do the PreserveFPState()
734
- * but not the usual full set of actions done by ExecuteFPCheck().
735
- * So we don't call vfp_access_check() and the callers must handle this.
736
- */
737
- if (regno != ARM_VFP_FPCXT_NS && !vfp_access_check(s)) {
738
- return FPSysRegCheckDone;
739
- }
740
- return FPSysRegCheckContinue;
741
-}
742
-
743
-static void gen_branch_fpInactive(DisasContext *s, TCGCond cond,
744
- TCGLabel *label)
745
-{
746
- /*
747
- * FPCXT_NS is a special case: it has specific handling for
748
- * "current FP state is inactive", and must do the PreserveFPState()
749
- * but not the usual full set of actions done by ExecuteFPCheck().
750
- * We don't have a TB flag that matches the fpInactive check, so we
751
- * do it at runtime as we don't expect FPCXT_NS accesses to be frequent.
752
- *
753
- * Emit code that checks fpInactive and does a conditional
754
- * branch to label based on it:
755
- * if cond is TCG_COND_NE then branch if fpInactive != 0 (ie if inactive)
756
- * if cond is TCG_COND_EQ then branch if fpInactive == 0 (ie if active)
757
- */
758
- assert(cond == TCG_COND_EQ || cond == TCG_COND_NE);
759
-
760
- /* fpInactive = FPCCR_NS.ASPEN == 1 && CONTROL.FPCA == 0 */
761
- TCGv_i32 aspen, fpca;
762
- aspen = load_cpu_field(v7m.fpccr[M_REG_NS]);
763
- fpca = load_cpu_field(v7m.control[M_REG_S]);
764
- tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
765
- tcg_gen_xori_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK);
766
- tcg_gen_andi_i32(fpca, fpca, R_V7M_CONTROL_FPCA_MASK);
767
- tcg_gen_or_i32(fpca, fpca, aspen);
768
- tcg_gen_brcondi_i32(tcg_invert_cond(cond), fpca, 0, label);
769
- tcg_temp_free_i32(aspen);
770
- tcg_temp_free_i32(fpca);
771
-}
772
-
773
-static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
774
- fp_sysreg_loadfn *loadfn,
775
- void *opaque)
776
-{
777
- /* Do a write to an M-profile floating point system register */
778
- TCGv_i32 tmp;
779
- TCGLabel *lab_end = NULL;
780
-
781
- switch (fp_sysreg_checks(s, regno)) {
782
- case FPSysRegCheckFailed:
783
- return false;
784
- case FPSysRegCheckDone:
785
- return true;
786
- case FPSysRegCheckContinue:
787
- break;
788
- }
789
-
790
- switch (regno) {
791
- case ARM_VFP_FPSCR:
792
- tmp = loadfn(s, opaque);
793
- gen_helper_vfp_set_fpscr(cpu_env, tmp);
794
- tcg_temp_free_i32(tmp);
795
- gen_lookup_tb(s);
796
- break;
797
- case ARM_VFP_FPSCR_NZCVQC:
798
- {
799
- TCGv_i32 fpscr;
800
- tmp = loadfn(s, opaque);
801
- if (dc_isar_feature(aa32_mve, s)) {
802
- /* QC is only present for MVE; otherwise RES0 */
803
- TCGv_i32 qc = tcg_temp_new_i32();
804
- tcg_gen_andi_i32(qc, tmp, FPCR_QC);
805
- /*
806
- * The 4 vfp.qc[] fields need only be "zero" vs "non-zero";
807
- * here writing the same value into all elements is simplest.
808
- */
809
- tcg_gen_gvec_dup_i32(MO_32, offsetof(CPUARMState, vfp.qc),
810
- 16, 16, qc);
811
- }
812
- tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
813
- fpscr = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
814
- tcg_gen_andi_i32(fpscr, fpscr, ~FPCR_NZCV_MASK);
815
- tcg_gen_or_i32(fpscr, fpscr, tmp);
816
- store_cpu_field(fpscr, vfp.xregs[ARM_VFP_FPSCR]);
817
- tcg_temp_free_i32(tmp);
818
- break;
819
- }
820
- case ARM_VFP_FPCXT_NS:
821
- lab_end = gen_new_label();
822
- /* fpInactive case: write is a NOP, so branch to end */
823
- gen_branch_fpInactive(s, TCG_COND_NE, lab_end);
824
- /*
825
- * !fpInactive: if FPU disabled, take NOCP exception;
826
- * otherwise PreserveFPState(), and then FPCXT_NS writes
827
- * behave the same as FPCXT_S writes.
828
- */
829
- if (s->fp_excp_el) {
830
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
831
- syn_uncategorized(), s->fp_excp_el);
832
- /*
833
- * This was only a conditional exception, so override
834
- * gen_exception_insn()'s default to DISAS_NORETURN
835
- */
836
- s->base.is_jmp = DISAS_NEXT;
837
- break;
838
- }
839
- gen_preserve_fp_state(s);
840
- /* fall through */
841
- case ARM_VFP_FPCXT_S:
842
- {
843
- TCGv_i32 sfpa, control;
844
- /*
845
- * Set FPSCR and CONTROL.SFPA from value; the new FPSCR takes
846
- * bits [27:0] from value and zeroes bits [31:28].
847
- */
848
- tmp = loadfn(s, opaque);
849
- sfpa = tcg_temp_new_i32();
850
- tcg_gen_shri_i32(sfpa, tmp, 31);
851
- control = load_cpu_field(v7m.control[M_REG_S]);
852
- tcg_gen_deposit_i32(control, control, sfpa,
853
- R_V7M_CONTROL_SFPA_SHIFT, 1);
854
- store_cpu_field(control, v7m.control[M_REG_S]);
855
- tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
856
- gen_helper_vfp_set_fpscr(cpu_env, tmp);
857
- tcg_temp_free_i32(tmp);
858
- tcg_temp_free_i32(sfpa);
859
- break;
860
- }
861
- case ARM_VFP_VPR:
862
- /* Behaves as NOP if not privileged */
863
- if (IS_USER(s)) {
864
- break;
865
- }
866
- tmp = loadfn(s, opaque);
867
- store_cpu_field(tmp, v7m.vpr);
868
- break;
869
- case ARM_VFP_P0:
870
- {
871
- TCGv_i32 vpr;
872
- tmp = loadfn(s, opaque);
873
- vpr = load_cpu_field(v7m.vpr);
874
- tcg_gen_deposit_i32(vpr, vpr, tmp,
875
- R_V7M_VPR_P0_SHIFT, R_V7M_VPR_P0_LENGTH);
876
- store_cpu_field(vpr, v7m.vpr);
877
- tcg_temp_free_i32(tmp);
878
- break;
879
- }
880
- default:
881
- g_assert_not_reached();
882
- }
883
- if (lab_end) {
884
- gen_set_label(lab_end);
885
- }
886
- return true;
887
-}
888
-
889
-static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
890
- fp_sysreg_storefn *storefn,
891
- void *opaque)
892
-{
893
- /* Do a read from an M-profile floating point system register */
894
- TCGv_i32 tmp;
895
- TCGLabel *lab_end = NULL;
896
- bool lookup_tb = false;
897
-
898
- switch (fp_sysreg_checks(s, regno)) {
899
- case FPSysRegCheckFailed:
900
- return false;
901
- case FPSysRegCheckDone:
902
- return true;
903
- case FPSysRegCheckContinue:
904
- break;
905
- }
906
-
907
- if (regno == ARM_VFP_FPSCR_NZCVQC && !dc_isar_feature(aa32_mve, s)) {
908
- /* QC is RES0 without MVE, so NZCVQC simplifies to NZCV */
909
- regno = QEMU_VFP_FPSCR_NZCV;
910
- }
911
-
912
- switch (regno) {
913
- case ARM_VFP_FPSCR:
914
- tmp = tcg_temp_new_i32();
915
- gen_helper_vfp_get_fpscr(tmp, cpu_env);
916
- storefn(s, opaque, tmp);
917
- break;
918
- case ARM_VFP_FPSCR_NZCVQC:
919
- tmp = tcg_temp_new_i32();
920
- gen_helper_vfp_get_fpscr(tmp, cpu_env);
921
- tcg_gen_andi_i32(tmp, tmp, FPCR_NZCVQC_MASK);
922
- storefn(s, opaque, tmp);
923
- break;
924
- case QEMU_VFP_FPSCR_NZCV:
925
- /*
926
- * Read just NZCV; this is a special case to avoid the
927
- * helper call for the "VMRS to CPSR.NZCV" insn.
928
- */
929
- tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
930
- tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
931
- storefn(s, opaque, tmp);
932
- break;
933
- case ARM_VFP_FPCXT_S:
934
- {
935
- TCGv_i32 control, sfpa, fpscr;
936
- /* Bits [27:0] from FPSCR, bit [31] from CONTROL.SFPA */
937
- tmp = tcg_temp_new_i32();
938
- sfpa = tcg_temp_new_i32();
939
- gen_helper_vfp_get_fpscr(tmp, cpu_env);
940
- tcg_gen_andi_i32(tmp, tmp, ~FPCR_NZCV_MASK);
941
- control = load_cpu_field(v7m.control[M_REG_S]);
942
- tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
943
- tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
944
- tcg_gen_or_i32(tmp, tmp, sfpa);
945
- tcg_temp_free_i32(sfpa);
946
- /*
947
- * Store result before updating FPSCR etc, in case
948
- * it is a memory write which causes an exception.
949
- */
950
- storefn(s, opaque, tmp);
951
- /*
952
- * Now we must reset FPSCR from FPDSCR_NS, and clear
953
- * CONTROL.SFPA; so we'll end the TB here.
954
- */
955
- tcg_gen_andi_i32(control, control, ~R_V7M_CONTROL_SFPA_MASK);
956
- store_cpu_field(control, v7m.control[M_REG_S]);
957
- fpscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
958
- gen_helper_vfp_set_fpscr(cpu_env, fpscr);
959
- tcg_temp_free_i32(fpscr);
960
- lookup_tb = true;
961
- break;
962
- }
963
- case ARM_VFP_FPCXT_NS:
964
- {
965
- TCGv_i32 control, sfpa, fpscr, fpdscr, zero;
966
- TCGLabel *lab_active = gen_new_label();
967
-
968
- lookup_tb = true;
969
-
970
- gen_branch_fpInactive(s, TCG_COND_EQ, lab_active);
971
- /* fpInactive case: reads as FPDSCR_NS */
972
- TCGv_i32 tmp = load_cpu_field(v7m.fpdscr[M_REG_NS]);
973
- storefn(s, opaque, tmp);
974
- lab_end = gen_new_label();
975
- tcg_gen_br(lab_end);
976
-
977
- gen_set_label(lab_active);
978
- /*
979
- * !fpInactive: if FPU disabled, take NOCP exception;
980
- * otherwise PreserveFPState(), and then FPCXT_NS
981
- * reads the same as FPCXT_S.
982
- */
983
- if (s->fp_excp_el) {
984
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
985
- syn_uncategorized(), s->fp_excp_el);
986
- /*
987
- * This was only a conditional exception, so override
988
- * gen_exception_insn()'s default to DISAS_NORETURN
989
- */
990
- s->base.is_jmp = DISAS_NEXT;
991
- break;
992
- }
993
- gen_preserve_fp_state(s);
994
- tmp = tcg_temp_new_i32();
995
- sfpa = tcg_temp_new_i32();
996
- fpscr = tcg_temp_new_i32();
997
- gen_helper_vfp_get_fpscr(fpscr, cpu_env);
998
- tcg_gen_andi_i32(tmp, fpscr, ~FPCR_NZCV_MASK);
999
- control = load_cpu_field(v7m.control[M_REG_S]);
1000
- tcg_gen_andi_i32(sfpa, control, R_V7M_CONTROL_SFPA_MASK);
1001
- tcg_gen_shli_i32(sfpa, sfpa, 31 - R_V7M_CONTROL_SFPA_SHIFT);
1002
- tcg_gen_or_i32(tmp, tmp, sfpa);
1003
- tcg_temp_free_i32(control);
1004
- /* Store result before updating FPSCR, in case it faults */
1005
- storefn(s, opaque, tmp);
1006
- /* If SFPA is zero then set FPSCR from FPDSCR_NS */
1007
- fpdscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
1008
- zero = tcg_const_i32(0);
1009
- tcg_gen_movcond_i32(TCG_COND_EQ, fpscr, sfpa, zero, fpdscr, fpscr);
1010
- gen_helper_vfp_set_fpscr(cpu_env, fpscr);
1011
- tcg_temp_free_i32(zero);
1012
- tcg_temp_free_i32(sfpa);
1013
- tcg_temp_free_i32(fpdscr);
1014
- tcg_temp_free_i32(fpscr);
1015
- break;
1016
- }
1017
- case ARM_VFP_VPR:
1018
- /* Behaves as NOP if not privileged */
1019
- if (IS_USER(s)) {
1020
- break;
1021
- }
1022
- tmp = load_cpu_field(v7m.vpr);
1023
- storefn(s, opaque, tmp);
1024
- break;
1025
- case ARM_VFP_P0:
1026
- tmp = load_cpu_field(v7m.vpr);
1027
- tcg_gen_extract_i32(tmp, tmp, R_V7M_VPR_P0_SHIFT, R_V7M_VPR_P0_LENGTH);
1028
- storefn(s, opaque, tmp);
1029
- break;
1030
- default:
1031
- g_assert_not_reached();
1032
- }
1033
-
1034
- if (lab_end) {
1035
- gen_set_label(lab_end);
1036
- }
1037
- if (lookup_tb) {
1038
- gen_lookup_tb(s);
1039
- }
1040
- return true;
1041
-}
1042
-
1043
-static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value)
1044
-{
1045
- arg_VMSR_VMRS *a = opaque;
1046
-
1047
- if (a->rt == 15) {
1048
- /* Set the 4 flag bits in the CPSR */
1049
- gen_set_nzcv(value);
1050
- tcg_temp_free_i32(value);
1051
- } else {
1052
- store_reg(s, a->rt, value);
1053
- }
1054
-}
1055
-
1056
-static TCGv_i32 gpr_to_fp_sysreg(DisasContext *s, void *opaque)
1057
-{
1058
- arg_VMSR_VMRS *a = opaque;
1059
-
1060
- return load_reg(s, a->rt);
1061
-}
1062
-
1063
-static bool gen_M_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
1064
-{
1065
- /*
1066
- * Accesses to R15 are UNPREDICTABLE; we choose to undef.
1067
- * FPSCR -> r15 is a special case which writes to the PSR flags;
1068
- * set a->reg to a special value to tell gen_M_fp_sysreg_read()
1069
- * we only care about the top 4 bits of FPSCR there.
1070
- */
1071
- if (a->rt == 15) {
1072
- if (a->l && a->reg == ARM_VFP_FPSCR) {
1073
- a->reg = QEMU_VFP_FPSCR_NZCV;
1074
- } else {
1075
- return false;
1076
- }
1077
- }
1078
-
1079
- if (a->l) {
1080
- /* VMRS, move FP system register to gp register */
1081
- return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_gpr, a);
1082
- } else {
1083
- /* VMSR, move gp register to FP system register */
1084
- return gen_M_fp_sysreg_write(s, a->reg, gpr_to_fp_sysreg, a);
1085
- }
1086
-}
1087
-
1088
static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
1089
{
1090
TCGv_i32 tmp;
1091
bool ignore_vfp_enabled = false;
1092
1093
if (arm_dc_feature(s, ARM_FEATURE_M)) {
1094
- return gen_M_VMSR_VMRS(s, a);
1095
+ /* M profile version was already handled in m-nocp.decode */
1096
+ return false;
1097
}
1098
1099
if (!dc_isar_feature(aa32_fpsp_v2, s)) {
1100
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
1101
return true;
1102
}
1103
1104
-static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
1105
-{
1106
- arg_vldr_sysreg *a = opaque;
1107
- uint32_t offset = a->imm;
1108
- TCGv_i32 addr;
1109
-
1110
- if (!a->a) {
1111
- offset = -offset;
1112
- }
1113
-
1114
- addr = load_reg(s, a->rn);
1115
- if (a->p) {
1116
- tcg_gen_addi_i32(addr, addr, offset);
1117
- }
1118
-
1119
- if (s->v8m_stackcheck && a->rn == 13 && a->w) {
1120
- gen_helper_v8m_stackcheck(cpu_env, addr);
1121
- }
1122
-
1123
- gen_aa32_st_i32(s, value, addr, get_mem_index(s),
1124
- MO_UL | MO_ALIGN | s->be_data);
1125
- tcg_temp_free_i32(value);
1126
-
1127
- if (a->w) {
1128
- /* writeback */
1129
- if (!a->p) {
1130
- tcg_gen_addi_i32(addr, addr, offset);
1131
- }
1132
- store_reg(s, a->rn, addr);
1133
- } else {
1134
- tcg_temp_free_i32(addr);
1135
- }
1136
-}
1137
-
1138
-static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
1139
-{
1140
- arg_vldr_sysreg *a = opaque;
1141
- uint32_t offset = a->imm;
1142
- TCGv_i32 addr;
1143
- TCGv_i32 value = tcg_temp_new_i32();
1144
-
1145
- if (!a->a) {
1146
- offset = -offset;
1147
- }
1148
-
1149
- addr = load_reg(s, a->rn);
1150
- if (a->p) {
1151
- tcg_gen_addi_i32(addr, addr, offset);
1152
- }
1153
-
1154
- if (s->v8m_stackcheck && a->rn == 13 && a->w) {
1155
- gen_helper_v8m_stackcheck(cpu_env, addr);
1156
- }
1157
-
1158
- gen_aa32_ld_i32(s, value, addr, get_mem_index(s),
1159
- MO_UL | MO_ALIGN | s->be_data);
1160
-
1161
- if (a->w) {
1162
- /* writeback */
1163
- if (!a->p) {
1164
- tcg_gen_addi_i32(addr, addr, offset);
1165
- }
1166
- store_reg(s, a->rn, addr);
1167
- } else {
1168
- tcg_temp_free_i32(addr);
1169
- }
1170
- return value;
1171
-}
1172
-
1173
-static bool trans_VLDR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
1174
-{
1175
- if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
1176
- return false;
1177
- }
1178
- if (a->rn == 15) {
1179
- return false;
1180
- }
1181
- return gen_M_fp_sysreg_write(s, a->reg, memory_to_fp_sysreg, a);
1182
-}
1183
-
1184
-static bool trans_VSTR_sysreg(DisasContext *s, arg_vldr_sysreg *a)
1185
-{
1186
- if (!arm_dc_feature(s, ARM_FEATURE_V8_1M)) {
1187
- return false;
1188
- }
1189
- if (a->rn == 15) {
1190
- return false;
1191
- }
1192
- return gen_M_fp_sysreg_read(s, a->reg, fp_sysreg_to_memory, a);
1193
-}
1194
1195
static bool trans_VMOV_half(DisasContext *s, arg_VMOV_single *a)
1196
{
1197
--
417
--
1198
2.20.1
418
2.34.1
1199
1200
diff view generated by jsdifflib
1
Generic code in target/arm wants to call acpi_ghes_record_errors();
1
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
2
provide a stub version so that we don't fail to link when
2
3
CONFIG_ACPI_APEI is not set. This requires us to add a new
3
During SPL boot several DRAM Controller registers are used. Most
4
ghes-stub.c file to contain it and the meson.build mechanics
4
important registers are those related to DRAM initialization and
5
to use it when appropriate.
5
calibration, where SPL initiates process and waits until certain bit is
6
6
set/cleared.
7
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
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Dongjiu Geng <gengdongjiu1@gmail.com>
10
Message-id: 20210603171259.27962-2-peter.maydell@linaro.org
11
---
16
---
12
hw/acpi/ghes-stub.c | 17 +++++++++++++++++
17
include/hw/arm/allwinner-a10.h | 2 +
13
hw/acpi/meson.build | 6 +++---
18
include/hw/misc/allwinner-a10-dramc.h | 68 ++++++++++
14
2 files changed, 20 insertions(+), 3 deletions(-)
19
hw/arm/allwinner-a10.c | 7 +
15
create mode 100644 hw/acpi/ghes-stub.c
20
hw/misc/allwinner-a10-dramc.c | 179 ++++++++++++++++++++++++++
16
21
hw/arm/Kconfig | 1 +
17
diff --git a/hw/acpi/ghes-stub.c b/hw/acpi/ghes-stub.c
22
hw/misc/Kconfig | 3 +
23
hw/misc/meson.build | 1 +
24
7 files changed, 261 insertions(+)
25
create mode 100644 include/hw/misc/allwinner-a10-dramc.h
26
create mode 100644 hw/misc/allwinner-a10-dramc.c
27
28
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/include/hw/arm/allwinner-a10.h
31
+++ b/include/hw/arm/allwinner-a10.h
32
@@ -XXX,XX +XXX,XX @@
33
#include "hw/usb/hcd-ehci.h"
34
#include "hw/rtc/allwinner-rtc.h"
35
#include "hw/misc/allwinner-a10-ccm.h"
36
+#include "hw/misc/allwinner-a10-dramc.h"
37
38
#include "target/arm/cpu.h"
39
#include "qom/object.h"
40
@@ -XXX,XX +XXX,XX @@ struct AwA10State {
41
42
ARMCPU cpu;
43
AwA10ClockCtlState ccm;
44
+ AwA10DramControllerState dramc;
45
AwA10PITState timer;
46
AwA10PICState intc;
47
AwEmacState emac;
48
diff --git a/include/hw/misc/allwinner-a10-dramc.h b/include/hw/misc/allwinner-a10-dramc.h
18
new file mode 100644
49
new file mode 100644
19
index XXXXXXX..XXXXXXX
50
index XXXXXXX..XXXXXXX
20
--- /dev/null
51
--- /dev/null
21
+++ b/hw/acpi/ghes-stub.c
52
+++ b/include/hw/misc/allwinner-a10-dramc.h
22
@@ -XXX,XX +XXX,XX @@
53
@@ -XXX,XX +XXX,XX @@
23
+/*
54
+/*
24
+ * Support for generating APEI tables and recording CPER for Guests:
55
+ * Allwinner A10 DRAM Controller emulation
25
+ * stub functions.
56
+ *
26
+ *
57
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
27
+ * Copyright (c) 2021 Linaro, Ltd
58
+ *
28
+ *
59
+ * This file is derived from Allwinner H3 DRAMC,
29
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
60
+ * by Niek Linnenbank.
30
+ * See the COPYING file in the top-level directory.
61
+ *
62
+ * This program is free software: you can redistribute it and/or modify
63
+ * it under the terms of the GNU General Public License as published by
64
+ * the Free Software Foundation, either version 2 of the License, or
65
+ * (at your option) any later version.
66
+ *
67
+ * This program is distributed in the hope that it will be useful,
68
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
69
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
70
+ * GNU General Public License for more details.
71
+ *
72
+ * You should have received a copy of the GNU General Public License
73
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
74
+ */
75
+
76
+#ifndef HW_MISC_ALLWINNER_A10_DRAMC_H
77
+#define HW_MISC_ALLWINNER_A10_DRAMC_H
78
+
79
+#include "qom/object.h"
80
+#include "hw/sysbus.h"
81
+#include "hw/register.h"
82
+
83
+/**
84
+ * @name Constants
85
+ * @{
86
+ */
87
+
88
+/** Size of register I/O address space used by DRAMC device */
89
+#define AW_A10_DRAMC_IOSIZE (0x1000)
90
+
91
+/** Total number of known registers */
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/>.
31
+ */
180
+ */
32
+
181
+
33
+#include "qemu/osdep.h"
182
+#include "qemu/osdep.h"
34
+#include "hw/acpi/ghes.h"
183
+#include "qemu/units.h"
35
+
184
+#include "hw/sysbus.h"
36
+int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address)
185
+#include "migration/vmstate.h"
37
+{
186
+#include "qemu/log.h"
38
+ return -1;
187
+#include "qemu/module.h"
39
+}
188
+#include "hw/misc/allwinner-a10-dramc.h"
40
diff --git a/hw/acpi/meson.build b/hw/acpi/meson.build
189
+
41
index XXXXXXX..XXXXXXX 100644
190
+/* DRAMC register offsets */
42
--- a/hw/acpi/meson.build
191
+enum {
43
+++ b/hw/acpi/meson.build
192
+ REG_SDR_CCR = 0x0000,
44
@@ -XXX,XX +XXX,XX @@ acpi_ss.add(when: 'CONFIG_ACPI_PCI', if_true: files('pci.c'))
193
+ REG_SDR_ZQCR0 = 0x00a8,
45
acpi_ss.add(when: 'CONFIG_ACPI_VMGENID', if_true: files('vmgenid.c'))
194
+ REG_SDR_ZQSR = 0x00b0
46
acpi_ss.add(when: 'CONFIG_ACPI_HW_REDUCED', if_true: files('generic_event_device.c'))
195
+};
47
acpi_ss.add(when: 'CONFIG_ACPI_HMAT', if_true: files('hmat.c'))
196
+
48
-acpi_ss.add(when: 'CONFIG_ACPI_APEI', if_true: files('ghes.c'))
197
+#define REG_INDEX(offset) (offset / sizeof(uint32_t))
49
+acpi_ss.add(when: 'CONFIG_ACPI_APEI', if_true: files('ghes.c'), if_false: files('ghes-stub.c'))
198
+
50
acpi_ss.add(when: 'CONFIG_ACPI_X86', if_true: files('core.c', 'piix4.c', 'pcihp.c'), if_false: files('acpi-stub.c'))
199
+/* DRAMC register flags */
51
acpi_ss.add(when: 'CONFIG_ACPI_X86_ICH', if_true: files('ich9.c', 'tco.c'))
200
+enum {
52
acpi_ss.add(when: 'CONFIG_IPMI', if_true: files('ipmi.c'), if_false: files('ipmi-stub.c'))
201
+ REG_SDR_CCR_DATA_TRAINING = (1 << 30),
53
acpi_ss.add(when: 'CONFIG_PC', if_false: files('acpi-x86-stub.c'))
202
+ REG_SDR_CCR_DRAM_INIT = (1 << 31),
54
acpi_ss.add(when: 'CONFIG_TPM', if_true: files('tpm.c'))
203
+};
55
-softmmu_ss.add(when: 'CONFIG_ACPI', if_false: files('acpi-stub.c', 'aml-build-stub.c'))
204
+enum {
56
+softmmu_ss.add(when: 'CONFIG_ACPI', if_false: files('acpi-stub.c', 'aml-build-stub.c', 'ghes-stub.c'))
205
+ REG_SDR_ZQSR_ZCAL = (1 << 31),
57
softmmu_ss.add_all(when: 'CONFIG_ACPI', if_true: acpi_ss)
206
+};
58
softmmu_ss.add(when: 'CONFIG_ALL', if_true: files('acpi-stub.c', 'aml-build-stub.c',
207
+
59
- 'acpi-x86-stub.c', 'ipmi-stub.c'))
208
+/* DRAMC register reset values */
60
+ 'acpi-x86-stub.c', 'ipmi-stub.c', 'ghes-stub.c'))
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;
234
+ }
235
+
236
+ return s->regs[idx];
237
+}
238
+
239
+static void allwinner_a10_dramc_write(void *opaque, hwaddr offset,
240
+ uint64_t val, unsigned size)
241
+{
242
+ AwA10DramControllerState *s = AW_A10_DRAMC(opaque);
243
+ const uint32_t idx = REG_INDEX(offset);
244
+
245
+ switch (offset) {
246
+ case REG_SDR_CCR:
247
+ if (val & REG_SDR_CCR_DRAM_INIT) {
248
+ /* Clear DRAM_INIT to indicate process is done. */
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;
268
+ }
269
+
270
+ s->regs[idx] = (uint32_t) val;
271
+}
272
+
273
+static const MemoryRegionOps allwinner_a10_dramc_ops = {
274
+ .read = allwinner_a10_dramc_read,
275
+ .write = allwinner_a10_dramc_write,
276
+ .endianness = DEVICE_NATIVE_ENDIAN,
277
+ .valid = {
278
+ .min_access_size = 4,
279
+ .max_access_size = 4,
280
+ },
281
+ .impl.min_access_size = 4,
282
+};
283
+
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()
313
+ }
314
+};
315
+
316
+static void allwinner_a10_dramc_class_init(ObjectClass *klass, void *data)
317
+{
318
+ DeviceClass *dc = DEVICE_CLASS(klass);
319
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
320
+
321
+ rc->phases.enter = allwinner_a10_dramc_reset_enter;
322
+ dc->vmsd = &allwinner_a10_dramc_vmstate;
323
+}
324
+
325
+static const TypeInfo allwinner_a10_dramc_info = {
326
+ .name = TYPE_AW_A10_DRAMC,
327
+ .parent = TYPE_SYS_BUS_DEVICE,
328
+ .instance_init = allwinner_a10_dramc_init,
329
+ .instance_size = sizeof(AwA10DramControllerState),
330
+ .class_init = allwinner_a10_dramc_class_init,
331
+};
332
+
333
+static void allwinner_a10_dramc_register(void)
334
+{
335
+ type_register_static(&allwinner_a10_dramc_info);
336
+}
337
+
338
+type_init(allwinner_a10_dramc_register)
339
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
340
index XXXXXXX..XXXXXXX 100644
341
--- a/hw/arm/Kconfig
342
+++ b/hw/arm/Kconfig
343
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10
344
select ALLWINNER_A10_PIT
345
select ALLWINNER_A10_PIC
346
select ALLWINNER_A10_CCM
347
+ select ALLWINNER_A10_DRAMC
348
select ALLWINNER_EMAC
349
select SERIAL
350
select UNIMP
351
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
352
index XXXXXXX..XXXXXXX 100644
353
--- a/hw/misc/Kconfig
354
+++ b/hw/misc/Kconfig
355
@@ -XXX,XX +XXX,XX @@ config LASI
356
config ALLWINNER_A10_CCM
357
bool
358
359
+config ALLWINNER_A10_DRAMC
360
+ bool
361
+
362
source macio/Kconfig
363
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
364
index XXXXXXX..XXXXXXX 100644
365
--- a/hw/misc/meson.build
366
+++ b/hw/misc/meson.build
367
@@ -XXX,XX +XXX,XX @@ subdir('macio')
368
softmmu_ss.add(when: 'CONFIG_IVSHMEM_DEVICE', if_true: files('ivshmem.c'))
369
370
softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10_CCM', if_true: files('allwinner-a10-ccm.c'))
371
+softmmu_ss.add(when: 'CONFIG_ALLWINNER_A10_DRAMC', if_true: files('allwinner-a10-dramc.c'))
372
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-ccu.c'))
373
specific_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-cpucfg.c'))
374
softmmu_ss.add(when: 'CONFIG_ALLWINNER_H3', if_true: files('allwinner-h3-dramc.c'))
61
--
375
--
62
2.20.1
376
2.34.1
63
64
diff view generated by jsdifflib
1
Implement the MVE VCLZ insn (and the necessary machinery
1
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
2
for MVE 1-input vector ops).
3
2
4
Note that for non-load instructions predication is always performed
3
This patch implements Allwinner TWI/I2C controller emulation. Only
5
at a byte level granularity regardless of element size (R_ZLSJ),
4
master-mode functionality is implemented.
6
and so the masking logic here differs from that used in the VLDR
7
and VSTR helpers.
8
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
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20210617121628.20116-4-peter.maydell@linaro.org
12
---
19
---
13
target/arm/helper-mve.h | 4 ++
20
docs/system/arm/cubieboard.rst | 1 +
14
target/arm/mve.decode | 8 ++++
21
docs/system/arm/orangepi.rst | 1 +
15
target/arm/mve_helper.c | 82 ++++++++++++++++++++++++++++++++++++++
22
include/hw/arm/allwinner-a10.h | 2 +
16
target/arm/translate-mve.c | 38 ++++++++++++++++++
23
include/hw/arm/allwinner-h3.h | 3 +
17
4 files changed, 132 insertions(+)
24
include/hw/i2c/allwinner-i2c.h | 55 ++++
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/helper-mve.h b/target/arm/helper-mve.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/helper-mve.h
38
--- a/docs/system/arm/cubieboard.rst
22
+++ b/target/arm/helper-mve.h
39
+++ b/docs/system/arm/cubieboard.rst
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vldrh_uw, TCG_CALL_NO_WG, void, env, ptr, i32)
40
@@ -XXX,XX +XXX,XX @@ Emulated devices:
24
DEF_HELPER_FLAGS_3(mve_vstrb_h, TCG_CALL_NO_WG, void, env, ptr, i32)
41
- SDHCI
25
DEF_HELPER_FLAGS_3(mve_vstrb_w, TCG_CALL_NO_WG, void, env, ptr, i32)
42
- USB controller
26
DEF_HELPER_FLAGS_3(mve_vstrh_w, TCG_CALL_NO_WG, void, env, ptr, i32)
43
- SATA controller
27
+
44
+- TWI (I2C) controller
28
+DEF_HELPER_FLAGS_3(mve_vclzb, TCG_CALL_NO_WG, void, env, ptr, ptr)
45
diff --git a/docs/system/arm/orangepi.rst b/docs/system/arm/orangepi.rst
29
+DEF_HELPER_FLAGS_3(mve_vclzh, TCG_CALL_NO_WG, void, env, ptr, ptr)
46
index XXXXXXX..XXXXXXX 100644
30
+DEF_HELPER_FLAGS_3(mve_vclzw, TCG_CALL_NO_WG, void, env, ptr, ptr)
47
--- a/docs/system/arm/orangepi.rst
31
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
48
+++ b/docs/system/arm/orangepi.rst
32
index XXXXXXX..XXXXXXX 100644
49
@@ -XXX,XX +XXX,XX @@ The Orange Pi PC machine supports the following devices:
33
--- a/target/arm/mve.decode
50
* Clock Control Unit
34
+++ b/target/arm/mve.decode
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
35
@@ -XXX,XX +XXX,XX @@
61
@@ -XXX,XX +XXX,XX @@
36
#
62
#include "hw/rtc/allwinner-rtc.h"
37
63
#include "hw/misc/allwinner-a10-ccm.h"
38
%qd 22:1 13:3
64
#include "hw/misc/allwinner-a10-dramc.h"
39
+%qm 5:1 1:3
65
+#include "hw/i2c/allwinner-i2c.h"
40
66
41
&vldr_vstr rn qd imm p a w size l u
67
#include "target/arm/cpu.h"
42
+&1op qd qm size
68
#include "qom/object.h"
43
69
@@ -XXX,XX +XXX,XX @@ struct AwA10State {
44
@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
70
AwEmacState emac;
45
# Note that both Rn and Qd are 3 bits only (no D bit)
71
AllwinnerAHCIState sata;
46
@vldst_wn ... u:1 ... . . . . l:1 . rn:3 qd:3 . ... .. imm:7 &vldr_vstr
72
AwSdHostState mmc0;
47
73
+ AWI2CState i2c0;
48
+@1op .... .... .... size:2 .. .... .... .... .... &1op qd=%qd qm=%qm
74
AwRtcState rtc;
49
+
75
MemoryRegion sram_a;
50
# Vector loads and stores
76
EHCISysBusState ehci[AW_A10_NUM_USB];
51
77
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
52
# Widening loads and narrowing stores:
78
index XXXXXXX..XXXXXXX 100644
53
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111101 ....... @vldr_vstr \
79
--- a/include/hw/arm/allwinner-h3.h
54
size=1 p=1
80
+++ b/include/hw/arm/allwinner-h3.h
55
VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111110 ....... @vldr_vstr \
81
@@ -XXX,XX +XXX,XX @@
56
size=2 p=1
82
#include "hw/sd/allwinner-sdhost.h"
57
+
83
#include "hw/net/allwinner-sun8i-emac.h"
58
+# Vector miscellaneous
84
#include "hw/rtc/allwinner-rtc.h"
59
+
85
+#include "hw/i2c/allwinner-i2c.h"
60
+VCLZ 1111 1111 1 . 11 .. 00 ... 0 0100 11 . 0 ... 0 @1op
86
#include "target/arm/cpu.h"
61
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
87
#include "sysemu/block-backend.h"
62
index XXXXXXX..XXXXXXX 100644
88
63
--- a/target/arm/mve_helper.c
89
@@ -XXX,XX +XXX,XX @@ enum {
64
+++ b/target/arm/mve_helper.c
90
AW_H3_DEV_UART2,
65
@@ -XXX,XX +XXX,XX @@ DO_VSTR(vstrh_w, 2, stw, 4, int32_t)
91
AW_H3_DEV_UART3,
66
92
AW_H3_DEV_EMAC,
67
#undef DO_VLDR
93
+ AW_H3_DEV_TWI0,
68
#undef DO_VSTR
94
AW_H3_DEV_DRAMCOM,
69
+
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 @@
70
+/*
111
+/*
71
+ * The mergemask(D, R, M) macro performs the operation "*D = R" but
112
+ * Allwinner I2C Bus Serial Interface registers definition
72
+ * storing only the bytes which correspond to 1 bits in M,
113
+ *
73
+ * leaving other bytes in *D unchanged. We use _Generic
114
+ * Copyright (C) 2022 Strahinja Jankovic. <strahinja.p.jankovic@gmail.com>
74
+ * to select the correct implementation based on the type of D.
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
+ *
75
+ */
132
+ */
76
+
133
+
77
+static void mergemask_ub(uint8_t *d, uint8_t r, uint16_t mask)
134
+#ifndef ALLWINNER_I2C_H
78
+{
135
+#define ALLWINNER_I2C_H
79
+ if (mask & 1) {
136
+
80
+ *d = r;
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));
196
}
197
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 "[?]";
81
+ }
409
+ }
82
+}
410
+}
83
+
411
+
84
+static void mergemask_sb(int8_t *d, int8_t r, uint16_t mask)
412
+static inline bool allwinner_i2c_is_reset(AWI2CState *s)
85
+{
413
+{
86
+ mergemask_ub((uint8_t *)d, r, mask);
414
+ return s->srst & TWI_SRST_MASK;
87
+}
415
+}
88
+
416
+
89
+static void mergemask_uh(uint16_t *d, uint16_t r, uint16_t mask)
417
+static inline bool allwinner_i2c_bus_is_enabled(AWI2CState *s)
90
+{
418
+{
91
+ uint16_t bmask = expand_pred_b_data[mask & 3];
419
+ return s->cntr & TWI_CNTR_BUS_EN;
92
+ *d = (*d & ~bmask) | (r & bmask);
420
+}
93
+}
421
+
94
+
422
+static inline bool allwinner_i2c_interrupt_is_enabled(AWI2CState *s)
95
+static void mergemask_sh(int16_t *d, int16_t r, uint16_t mask)
423
+{
96
+{
424
+ return s->cntr & TWI_CNTR_INT_EN;
97
+ mergemask_uh((uint16_t *)d, r, mask);
425
+}
98
+}
426
+
99
+
427
+static void allwinner_i2c_reset_hold(Object *obj)
100
+static void mergemask_uw(uint32_t *d, uint32_t r, uint16_t mask)
428
+{
101
+{
429
+ AWI2CState *s = AW_I2C(obj);
102
+ uint32_t bmask = expand_pred_b_data[mask & 0xf];
430
+
103
+ *d = (*d & ~bmask) | (r & bmask);
431
+ if (STAT_TO_STA(s->stat) != STAT_IDLE) {
104
+}
432
+ i2c_end_transfer(s->bus);
105
+
106
+static void mergemask_sw(int32_t *d, int32_t r, uint16_t mask)
107
+{
108
+ mergemask_uw((uint32_t *)d, r, mask);
109
+}
110
+
111
+static void mergemask_uq(uint64_t *d, uint64_t r, uint16_t mask)
112
+{
113
+ uint64_t bmask = expand_pred_b_data[mask & 0xff];
114
+ *d = (*d & ~bmask) | (r & bmask);
115
+}
116
+
117
+static void mergemask_sq(int64_t *d, int64_t r, uint16_t mask)
118
+{
119
+ mergemask_uq((uint64_t *)d, r, mask);
120
+}
121
+
122
+#define mergemask(D, R, M) \
123
+ _Generic(D, \
124
+ uint8_t *: mergemask_ub, \
125
+ int8_t *: mergemask_sb, \
126
+ uint16_t *: mergemask_uh, \
127
+ int16_t *: mergemask_sh, \
128
+ uint32_t *: mergemask_uw, \
129
+ int32_t *: mergemask_sw, \
130
+ uint64_t *: mergemask_uq, \
131
+ int64_t *: mergemask_sq)(D, R, M)
132
+
133
+#define DO_1OP(OP, ESIZE, TYPE, FN) \
134
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm) \
135
+ { \
136
+ TYPE *d = vd, *m = vm; \
137
+ uint16_t mask = mve_element_mask(env); \
138
+ unsigned e; \
139
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
140
+ mergemask(&d[H##ESIZE(e)], FN(m[H##ESIZE(e)]), mask); \
141
+ } \
142
+ mve_advance_vpt(env); \
143
+ }
433
+ }
144
+
434
+
145
+#define DO_CLZ_B(N) (clz32(N) - 24)
435
+ s->addr = TWI_ADDR_RESET;
146
+#define DO_CLZ_H(N) (clz32(N) - 16)
436
+ s->xaddr = TWI_XADDR_RESET;
147
+
437
+ s->data = TWI_DATA_RESET;
148
+DO_1OP(vclzb, 1, uint8_t, DO_CLZ_B)
438
+ s->cntr = TWI_CNTR_RESET;
149
+DO_1OP(vclzh, 2, uint16_t, DO_CLZ_H)
439
+ s->stat = TWI_STAT_RESET;
150
+DO_1OP(vclzw, 4, uint32_t, clz32)
440
+ s->ccr = TWI_CCR_RESET;
151
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
441
+ s->srst = TWI_SRST_RESET;
152
index XXXXXXX..XXXXXXX 100644
442
+ s->efr = TWI_EFR_RESET;
153
--- a/target/arm/translate-mve.c
443
+ s->lcr = TWI_LCR_RESET;
154
+++ b/target/arm/translate-mve.c
444
+}
155
@@ -XXX,XX +XXX,XX @@
445
+
156
#include "decode-mve.c.inc"
446
+static inline void allwinner_i2c_raise_interrupt(AWI2CState *s)
157
447
+{
158
typedef void MVEGenLdStFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
448
+ /*
159
+typedef void MVEGenOneOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
449
+ * Raise an interrupt if the device is not reset and it is configured
160
450
+ * to generate some interrupts.
161
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
451
+ */
162
static inline long mve_qreg_offset(unsigned reg)
452
+ if (!allwinner_i2c_is_reset(s) && allwinner_i2c_bus_is_enabled(s)) {
163
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDR_VSTR(DisasContext *s, arg_VLDR_VSTR *a)
453
+ if (STAT_TO_STA(s->stat) != STAT_IDLE) {
164
DO_VLDST_WIDE_NARROW(VLDSTB_H, vldrb_sh, vldrb_uh, vstrb_h)
454
+ s->cntr |= TWI_CNTR_INT_FLAG;
165
DO_VLDST_WIDE_NARROW(VLDSTB_W, vldrb_sw, vldrb_uw, vstrb_w)
455
+ if (allwinner_i2c_interrupt_is_enabled(s)) {
166
DO_VLDST_WIDE_NARROW(VLDSTH_W, vldrh_sw, vldrh_uw, vstrh_w)
456
+ qemu_irq_raise(s->irq);
167
+
457
+ }
168
+static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
458
+ }
169
+{
170
+ TCGv_ptr qd, qm;
171
+
172
+ if (!dc_isar_feature(aa32_mve, s) ||
173
+ !mve_check_qreg_bank(s, a->qd | a->qm) ||
174
+ !fn) {
175
+ return false;
176
+ }
459
+ }
177
+
460
+}
178
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
461
+
179
+ return true;
462
+static uint64_t allwinner_i2c_read(void *opaque, hwaddr offset,
463
+ unsigned size)
464
+{
465
+ uint16_t value;
466
+ AWI2CState *s = AW_I2C(opaque);
467
+
468
+ switch (offset) {
469
+ case TWI_ADDR_REG:
470
+ value = s->addr;
471
+ break;
472
+ case TWI_XADDR_REG:
473
+ value = s->xaddr;
474
+ break;
475
+ case TWI_DATA_REG:
476
+ if ((STAT_TO_STA(s->stat) == STAT_M_ADDR_RD_ACK) ||
477
+ (STAT_TO_STA(s->stat) == STAT_M_DATA_RX_ACK) ||
478
+ (STAT_TO_STA(s->stat) == STAT_M_DATA_RX_NACK)) {
479
+ /* Get the next byte */
480
+ s->data = i2c_recv(s->bus);
481
+
482
+ if (s->cntr & TWI_CNTR_A_ACK) {
483
+ s->stat = STAT_FROM_STA(STAT_M_DATA_RX_ACK);
484
+ } else {
485
+ s->stat = STAT_FROM_STA(STAT_M_DATA_RX_NACK);
486
+ }
487
+ allwinner_i2c_raise_interrupt(s);
488
+ }
489
+ value = s->data;
490
+ break;
491
+ case TWI_CNTR_REG:
492
+ value = s->cntr;
493
+ break;
494
+ case TWI_STAT_REG:
495
+ value = s->stat;
496
+ /*
497
+ * If polling when reading then change state to indicate data
498
+ * is available
499
+ */
500
+ if (STAT_TO_STA(s->stat) == STAT_M_ADDR_RD_ACK) {
501
+ if (s->cntr & TWI_CNTR_A_ACK) {
502
+ s->stat = STAT_FROM_STA(STAT_M_DATA_RX_ACK);
503
+ } else {
504
+ s->stat = STAT_FROM_STA(STAT_M_DATA_RX_NACK);
505
+ }
506
+ allwinner_i2c_raise_interrupt(s);
507
+ }
508
+ break;
509
+ case TWI_CCR_REG:
510
+ value = s->ccr;
511
+ break;
512
+ case TWI_SRST_REG:
513
+ value = s->srst;
514
+ break;
515
+ case TWI_EFR_REG:
516
+ value = s->efr;
517
+ break;
518
+ case TWI_LCR_REG:
519
+ value = s->lcr;
520
+ break;
521
+ default:
522
+ qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad address at offset 0x%"
523
+ HWADDR_PRIx "\n", TYPE_AW_I2C, __func__, offset);
524
+ value = 0;
525
+ break;
180
+ }
526
+ }
181
+
527
+
182
+ qd = mve_qreg_ptr(a->qd);
528
+ trace_allwinner_i2c_read(allwinner_i2c_get_regname(offset), offset, value);
183
+ qm = mve_qreg_ptr(a->qm);
529
+
184
+ fn(cpu_env, qd, qm);
530
+ return (uint64_t)value;
185
+ tcg_temp_free_ptr(qd);
531
+}
186
+ tcg_temp_free_ptr(qm);
532
+
187
+ mve_update_eci(s);
533
+static void allwinner_i2c_write(void *opaque, hwaddr offset,
188
+ return true;
534
+ uint64_t value, unsigned size)
189
+}
535
+{
190
+
536
+ AWI2CState *s = AW_I2C(opaque);
191
+#define DO_1OP(INSN, FN) \
537
+
192
+ static bool trans_##INSN(DisasContext *s, arg_1op *a) \
538
+ value &= 0xff;
193
+ { \
539
+
194
+ static MVEGenOneOpFn * const fns[] = { \
540
+ trace_allwinner_i2c_write(allwinner_i2c_get_regname(offset), offset, value);
195
+ gen_helper_mve_##FN##b, \
541
+
196
+ gen_helper_mve_##FN##h, \
542
+ switch (offset) {
197
+ gen_helper_mve_##FN##w, \
543
+ case TWI_ADDR_REG:
198
+ NULL, \
544
+ s->addr = (uint8_t)value;
199
+ }; \
545
+ break;
200
+ return do_1op(s, a, fns[a->size]); \
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;
201
+ }
651
+ }
202
+
652
+}
203
+DO_1OP(VCLZ, vclz)
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"
204
--
777
--
205
2.20.1
778
2.34.1
206
207
diff view generated by jsdifflib
1
Implement the forms of the MVE VLDR and VSTR insns which perform
1
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
2
non-widening loads of bytes, halfwords or words from memory into
3
vector elements of the same width (encodings T5, T6, T7).
4
2
5
(At the moment we know for MVE and M-profile in general that
3
This patch adds minimal support for AXP-209 PMU.
6
vfp_access_check() can never return false, but we include the
4
Most important is chip ID since U-Boot SPL expects version 0x1. Besides
7
conventional return-true-on-failure check for consistency
5
the chip ID register, reset values for two more registers used by A10
8
with non-M-profile translation code.)
6
U-Boot SPL are covered.
9
7
8
Signed-off-by: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
9
Message-id: 20221226220303.14420-5-strahinja.p.jankovic@gmail.com
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
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
Message-id: 20210617121628.20116-2-peter.maydell@linaro.org
13
---
12
---
14
target/arm/{translate-mve.c => helper-mve.h} | 19 +-
13
hw/misc/axp209.c | 238 +++++++++++++++++++++++++++++++++++++++++++
15
target/arm/helper.h | 2 +
14
MAINTAINERS | 2 +
16
target/arm/internals.h | 11 ++
15
hw/misc/Kconfig | 4 +
17
target/arm/mve.decode | 22 +++
16
hw/misc/meson.build | 1 +
18
target/arm/mve_helper.c | 172 +++++++++++++++++++
17
hw/misc/trace-events | 5 +
19
target/arm/translate-mve.c | 119 +++++++++++++
18
5 files changed, 250 insertions(+)
20
target/arm/meson.build | 1 +
19
create mode 100644 hw/misc/axp209.c
21
7 files changed, 334 insertions(+), 12 deletions(-)
22
copy target/arm/{translate-mve.c => helper-mve.h} (61%)
23
create mode 100644 target/arm/mve_helper.c
24
20
25
diff --git a/target/arm/translate-mve.c b/target/arm/helper-mve.h
21
diff --git a/hw/misc/axp209.c b/hw/misc/axp209.c
26
similarity index 61%
27
copy from target/arm/translate-mve.c
28
copy to target/arm/helper-mve.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/translate-mve.c
31
+++ b/target/arm/helper-mve.h
32
@@ -XXX,XX +XXX,XX @@
33
/*
34
- * ARM translation: M-profile MVE instructions
35
+ * M-profile MVE specific helper definitions
36
*
37
* Copyright (c) 2021 Linaro, Ltd.
38
*
39
@@ -XXX,XX +XXX,XX @@
40
* You should have received a copy of the GNU Lesser General Public
41
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
42
*/
43
-
44
-#include "qemu/osdep.h"
45
-#include "tcg/tcg-op.h"
46
-#include "tcg/tcg-op-gvec.h"
47
-#include "exec/exec-all.h"
48
-#include "exec/gen-icount.h"
49
-#include "translate.h"
50
-#include "translate-a32.h"
51
-
52
-/* Include the generated decoder */
53
-#include "decode-mve.c.inc"
54
+DEF_HELPER_FLAGS_3(mve_vldrb, TCG_CALL_NO_WG, void, env, ptr, i32)
55
+DEF_HELPER_FLAGS_3(mve_vldrh, TCG_CALL_NO_WG, void, env, ptr, i32)
56
+DEF_HELPER_FLAGS_3(mve_vldrw, TCG_CALL_NO_WG, void, env, ptr, i32)
57
+DEF_HELPER_FLAGS_3(mve_vstrb, TCG_CALL_NO_WG, void, env, ptr, i32)
58
+DEF_HELPER_FLAGS_3(mve_vstrh, TCG_CALL_NO_WG, void, env, ptr, i32)
59
+DEF_HELPER_FLAGS_3(mve_vstrw, TCG_CALL_NO_WG, void, env, ptr, i32)
60
diff --git a/target/arm/helper.h b/target/arm/helper.h
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/helper.h
63
+++ b/target/arm/helper.h
64
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_6(gvec_bfmlal_idx, TCG_CALL_NO_RWG,
65
#include "helper-a64.h"
66
#include "helper-sve.h"
67
#endif
68
+
69
+#include "helper-mve.h"
70
diff --git a/target/arm/internals.h b/target/arm/internals.h
71
index XXXXXXX..XXXXXXX 100644
72
--- a/target/arm/internals.h
73
+++ b/target/arm/internals.h
74
@@ -XXX,XX +XXX,XX @@ static inline uint64_t useronly_maybe_clean_ptr(uint32_t desc, uint64_t ptr)
75
return ptr;
76
}
77
78
+/* Values for M-profile PSR.ECI for MVE insns */
79
+enum MVEECIState {
80
+ ECI_NONE = 0, /* No completed beats */
81
+ ECI_A0 = 1, /* Completed: A0 */
82
+ ECI_A0A1 = 2, /* Completed: A0, A1 */
83
+ /* 3 is reserved */
84
+ ECI_A0A1A2 = 4, /* Completed: A0, A1, A2 */
85
+ ECI_A0A1A2B0 = 5, /* Completed: A0, A1, A2, B0 */
86
+ /* All other values reserved */
87
+};
88
+
89
#endif
90
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
91
index XXXXXXX..XXXXXXX 100644
92
--- a/target/arm/mve.decode
93
+++ b/target/arm/mve.decode
94
@@ -XXX,XX +XXX,XX @@
95
#
96
# This file is processed by scripts/decodetree.py
97
#
98
+
99
+%qd 22:1 13:3
100
+
101
+&vldr_vstr rn qd imm p a w size l
102
+
103
+@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd
104
+
105
+# Vector loads and stores
106
+
107
+# Non-widening loads/stores (P=0 W=0 is 'related encoding')
108
+VLDR_VSTR 1110110 0 a:1 . 1 . .... ... 111100 ....... @vldr_vstr \
109
+ size=0 p=0 w=1
110
+VLDR_VSTR 1110110 0 a:1 . 1 . .... ... 111101 ....... @vldr_vstr \
111
+ size=1 p=0 w=1
112
+VLDR_VSTR 1110110 0 a:1 . 1 . .... ... 111110 ....... @vldr_vstr \
113
+ size=2 p=0 w=1
114
+VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111100 ....... @vldr_vstr \
115
+ size=0 p=1
116
+VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111101 ....... @vldr_vstr \
117
+ size=1 p=1
118
+VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111110 ....... @vldr_vstr \
119
+ size=2 p=1
120
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
121
new file mode 100644
22
new file mode 100644
122
index XXXXXXX..XXXXXXX
23
index XXXXXXX..XXXXXXX
123
--- /dev/null
24
--- /dev/null
124
+++ b/target/arm/mve_helper.c
25
+++ b/hw/misc/axp209.c
125
@@ -XXX,XX +XXX,XX @@
26
@@ -XXX,XX +XXX,XX @@
126
+/*
27
+/*
127
+ * M-profile MVE Operations
28
+ * AXP-209 PMU Emulation
128
+ *
29
+ *
129
+ * Copyright (c) 2021 Linaro, Ltd.
30
+ * Copyright (C) 2022 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
130
+ *
31
+ *
131
+ * This library is free software; you can redistribute it and/or
32
+ * Permission is hereby granted, free of charge, to any person obtaining a
132
+ * modify it under the terms of the GNU Lesser General Public
33
+ * copy of this software and associated documentation files (the "Software"),
133
+ * License as published by the Free Software Foundation; either
34
+ * to deal in the Software without restriction, including without limitation
134
+ * version 2.1 of the License, or (at your option) any later version.
35
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
135
+ *
36
+ * and/or sell copies of the Software, and to permit persons to whom the
136
+ * This library is distributed in the hope that it will be useful,
37
+ * Software is furnished to do so, subject to the following conditions:
137
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
38
+ *
138
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
39
+ * The above copyright notice and this permission notice shall be included in
139
+ * Lesser General Public License for more details.
40
+ * all copies or substantial portions of the Software.
140
+ *
41
+ *
141
+ * You should have received a copy of the GNU Lesser General Public
42
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
142
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
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
143
+ */
51
+ */
144
+
52
+
145
+#include "qemu/osdep.h"
53
+#include "qemu/osdep.h"
146
+#include "cpu.h"
54
+#include "qemu/log.h"
147
+#include "internals.h"
55
+#include "trace.h"
148
+#include "vec_internal.h"
56
+#include "hw/i2c/i2c.h"
149
+#include "exec/helper-proto.h"
57
+#include "migration/vmstate.h"
150
+#include "exec/cpu_ldst.h"
58
+
151
+#include "exec/exec-all.h"
59
+#define TYPE_AXP209_PMU "axp209_pmu"
152
+
60
+
153
+static uint16_t mve_element_mask(CPUARMState *env)
61
+#define AXP209(obj) \
154
+{
62
+ OBJECT_CHECK(AXP209I2CState, (obj), TYPE_AXP209_PMU)
155
+ /*
63
+
156
+ * Return the mask of which elements in the MVE vector should be
64
+/* registers */
157
+ * updated. This is a combination of multiple things:
65
+enum {
158
+ * (1) by default, we update every lane in the vector
66
+ REG_POWER_STATUS = 0x0u,
159
+ * (2) VPT predication stores its state in the VPR register;
67
+ REG_OPERATING_MODE,
160
+ * (3) low-overhead-branch tail predication will mask out part
68
+ REG_OTG_VBUS_STATUS,
161
+ * the vector on the final iteration of the loop
69
+ REG_CHIP_VERSION,
162
+ * (4) if EPSR.ECI is set then we must execute only some beats
70
+ REG_DATA_CACHE_0,
163
+ * of the insn
71
+ REG_DATA_CACHE_1,
164
+ * We combine all these into a 16-bit result with the same semantics
72
+ REG_DATA_CACHE_2,
165
+ * as VPR.P0: 0 to mask the lane, 1 if it is active.
73
+ REG_DATA_CACHE_3,
166
+ * 8-bit vector ops will look at all bits of the result;
74
+ REG_DATA_CACHE_4,
167
+ * 16-bit ops will look at bits 0, 2, 4, ...;
75
+ REG_DATA_CACHE_5,
168
+ * 32-bit ops will look at bits 0, 4, 8 and 12.
76
+ REG_DATA_CACHE_6,
169
+ * Compare pseudocode GetCurInstrBeat(), though that only returns
77
+ REG_DATA_CACHE_7,
170
+ * the 4-bit slice of the mask corresponding to a single beat.
78
+ REG_DATA_CACHE_8,
171
+ */
79
+ REG_DATA_CACHE_9,
172
+ uint16_t mask = FIELD_EX32(env->v7m.vpr, V7M_VPR, P0);
80
+ REG_DATA_CACHE_A,
173
+
81
+ REG_DATA_CACHE_B,
174
+ if (!(env->v7m.vpr & R_V7M_VPR_MASK01_MASK)) {
82
+ REG_POWER_OUTPUT_CTRL = 0x12u,
175
+ mask |= 0xff;
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++];
176
+ }
198
+ }
177
+ if (!(env->v7m.vpr & R_V7M_VPR_MASK23_MASK)) {
199
+
178
+ mask |= 0xff00;
200
+ trace_axp209_rx(s->ptr - 1, ret);
179
+ }
201
+
180
+
202
+ return ret;
181
+ if (env->v7m.ltpsize < 4 &&
203
+}
182
+ env->regs[14] <= (1 << (4 - env->v7m.ltpsize))) {
204
+
183
+ /*
205
+/*
184
+ * Tail predication active, and this is the last loop iteration.
206
+ * Called when master sends write.
185
+ * The element size is (1 << ltpsize), and we only want to process
207
+ * Update ptr with byte 0, then perform write with second byte.
186
+ * loopcount elements, so we want to retain the least significant
208
+ */
187
+ * (loopcount * esize) predicate bits and zero out bits above that.
209
+static int axp209_tx(I2CSlave *i2c, uint8_t data)
188
+ */
210
+{
189
+ int masklen = env->regs[14] << env->v7m.ltpsize;
211
+ AXP209I2CState *s = AXP209(i2c);
190
+ assert(masklen <= 16);
212
+
191
+ mask &= MAKE_64BIT_MASK(0, masklen);
213
+ if (s->count == 0) {
192
+ }
214
+ /* Store register address */
193
+
215
+ s->ptr = data;
194
+ if ((env->condexec_bits & 0xf) == 0) {
216
+ s->count++;
195
+ /*
217
+ trace_axp209_select(data);
196
+ * ECI bits indicate which beats are already executed;
218
+ } else {
197
+ * we handle this by effectively predicating them out.
219
+ trace_axp209_tx(s->ptr, data);
198
+ */
220
+ if (s->ptr == REG_DC_DC2_OUT_V_CTRL) {
199
+ int eci = env->condexec_bits >> 4;
221
+ s->regs[s->ptr++] = data;
200
+ switch (eci) {
201
+ case ECI_NONE:
202
+ break;
203
+ case ECI_A0:
204
+ mask &= 0xfff0;
205
+ break;
206
+ case ECI_A0A1:
207
+ mask &= 0xff00;
208
+ break;
209
+ case ECI_A0A1A2:
210
+ case ECI_A0A1A2B0:
211
+ mask &= 0xf000;
212
+ break;
213
+ default:
214
+ g_assert_not_reached();
215
+ }
222
+ }
216
+ }
223
+ }
217
+
224
+
218
+ return mask;
225
+ return 0;
219
+}
226
+}
220
+
227
+
221
+static void mve_advance_vpt(CPUARMState *env)
228
+static const VMStateDescription vmstate_axp209 = {
222
+{
229
+ .name = TYPE_AXP209_PMU,
223
+ /* Advance the VPT and ECI state if necessary */
230
+ .version_id = 1,
224
+ uint32_t vpr = env->v7m.vpr;
231
+ .fields = (VMStateField[]) {
225
+ unsigned mask01, mask23;
232
+ VMSTATE_UINT8_ARRAY(regs, AXP209I2CState, NR_REGS),
226
+
233
+ VMSTATE_UINT8(count, AXP209I2CState),
227
+ if ((env->condexec_bits & 0xf) == 0) {
234
+ VMSTATE_UINT8(ptr, AXP209I2CState),
228
+ env->condexec_bits = (env->condexec_bits == (ECI_A0A1A2B0 << 4)) ?
235
+ VMSTATE_END_OF_LIST()
229
+ (ECI_A0 << 4) : (ECI_NONE << 4);
230
+ }
236
+ }
231
+
237
+};
232
+ if (!(vpr & (R_V7M_VPR_MASK01_MASK | R_V7M_VPR_MASK23_MASK))) {
238
+
233
+ /* VPT not enabled, nothing to do */
239
+static void axp209_class_init(ObjectClass *oc, void *data)
234
+ return;
240
+{
235
+ }
241
+ DeviceClass *dc = DEVICE_CLASS(oc);
236
+
242
+ I2CSlaveClass *isc = I2C_SLAVE_CLASS(oc);
237
+ mask01 = FIELD_EX32(vpr, V7M_VPR, MASK01);
243
+ ResettableClass *rc = RESETTABLE_CLASS(oc);
238
+ mask23 = FIELD_EX32(vpr, V7M_VPR, MASK23);
244
+
239
+ if (mask01 > 8) {
245
+ rc->phases.enter = axp209_reset_enter;
240
+ /* high bit set, but not 0b1000: invert the relevant half of P0 */
246
+ dc->vmsd = &vmstate_axp209;
241
+ vpr ^= 0xff;
247
+ isc->event = axp209_event;
242
+ }
248
+ isc->recv = axp209_rx;
243
+ if (mask23 > 8) {
249
+ isc->send = axp209_tx;
244
+ /* high bit set, but not 0b1000: invert the relevant half of P0 */
250
+}
245
+ vpr ^= 0xff00;
251
+
246
+ }
252
+static const TypeInfo axp209_info = {
247
+ vpr = FIELD_DP32(vpr, V7M_VPR, MASK01, mask01 << 1);
253
+ .name = TYPE_AXP209_PMU,
248
+ vpr = FIELD_DP32(vpr, V7M_VPR, MASK23, mask23 << 1);
254
+ .parent = TYPE_I2C_SLAVE,
249
+ env->v7m.vpr = vpr;
255
+ .instance_size = sizeof(AXP209I2CState),
250
+}
256
+ .class_init = axp209_class_init
251
+
257
+};
252
+
258
+
253
+#define DO_VLDR(OP, MSIZE, LDTYPE, ESIZE, TYPE) \
259
+static void axp209_register_devices(void)
254
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, uint32_t addr) \
260
+{
255
+ { \
261
+ type_register_static(&axp209_info);
256
+ TYPE *d = vd; \
262
+}
257
+ uint16_t mask = mve_element_mask(env); \
263
+
258
+ unsigned b, e; \
264
+type_init(axp209_register_devices);
259
+ /* \
265
diff --git a/MAINTAINERS b/MAINTAINERS
260
+ * R_SXTM allows the dest reg to become UNKNOWN for abandoned \
261
+ * beats so we don't care if we update part of the dest and \
262
+ * then take an exception. \
263
+ */ \
264
+ for (b = 0, e = 0; b < 16; b += ESIZE, e++) { \
265
+ if (mask & (1 << b)) { \
266
+ d[H##ESIZE(e)] = cpu_##LDTYPE##_data_ra(env, addr, GETPC()); \
267
+ } \
268
+ addr += MSIZE; \
269
+ } \
270
+ mve_advance_vpt(env); \
271
+ }
272
+
273
+#define DO_VSTR(OP, MSIZE, STTYPE, ESIZE, TYPE) \
274
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, uint32_t addr) \
275
+ { \
276
+ TYPE *d = vd; \
277
+ uint16_t mask = mve_element_mask(env); \
278
+ unsigned b, e; \
279
+ for (b = 0, e = 0; b < 16; b += ESIZE, e++) { \
280
+ if (mask & (1 << b)) { \
281
+ cpu_##STTYPE##_data_ra(env, addr, d[H##ESIZE(e)], GETPC()); \
282
+ } \
283
+ addr += MSIZE; \
284
+ } \
285
+ mve_advance_vpt(env); \
286
+ }
287
+
288
+DO_VLDR(vldrb, 1, ldub, 1, uint8_t)
289
+DO_VLDR(vldrh, 2, lduw, 2, uint16_t)
290
+DO_VLDR(vldrw, 4, ldl, 4, uint32_t)
291
+
292
+DO_VSTR(vstrb, 1, stb, 1, uint8_t)
293
+DO_VSTR(vstrh, 2, stw, 2, uint16_t)
294
+DO_VSTR(vstrw, 4, stl, 4, uint32_t)
295
+
296
+#undef DO_VLDR
297
+#undef DO_VSTR
298
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
299
index XXXXXXX..XXXXXXX 100644
266
index XXXXXXX..XXXXXXX 100644
300
--- a/target/arm/translate-mve.c
267
--- a/MAINTAINERS
301
+++ b/target/arm/translate-mve.c
268
+++ b/MAINTAINERS
302
@@ -XXX,XX +XXX,XX @@
269
@@ -XXX,XX +XXX,XX @@ ARM Machines
303
270
Allwinner-a10
304
/* Include the generated decoder */
271
M: Beniamino Galvani <b.galvani@gmail.com>
305
#include "decode-mve.c.inc"
272
M: Peter Maydell <peter.maydell@linaro.org>
306
+
273
+R: Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
307
+typedef void MVEGenLdStFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
274
L: qemu-arm@nongnu.org
308
+
275
S: Odd Fixes
309
+/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
276
F: hw/*/allwinner*
310
+static inline long mve_qreg_offset(unsigned reg)
277
F: include/hw/*/allwinner*
311
+{
278
F: hw/arm/cubieboard.c
312
+ return offsetof(CPUARMState, vfp.zregs[reg].d[0]);
279
F: docs/system/arm/cubieboard.rst
313
+}
280
+F: hw/misc/axp209.c
314
+
281
315
+static TCGv_ptr mve_qreg_ptr(unsigned reg)
282
Allwinner-h3
316
+{
283
M: Niek Linnenbank <nieklinnenbank@gmail.com>
317
+ TCGv_ptr ret = tcg_temp_new_ptr();
284
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
318
+ tcg_gen_addi_ptr(ret, cpu_env, mve_qreg_offset(reg));
319
+ return ret;
320
+}
321
+
322
+static bool mve_check_qreg_bank(DisasContext *s, int qmask)
323
+{
324
+ /*
325
+ * Check whether Qregs are in range. For v8.1M only Q0..Q7
326
+ * are supported, see VFPSmallRegisterBank().
327
+ */
328
+ return qmask < 8;
329
+}
330
+
331
+static bool mve_eci_check(DisasContext *s)
332
+{
333
+ /*
334
+ * This is a beatwise insn: check that ECI is valid (not a
335
+ * reserved value) and note that we are handling it.
336
+ * Return true if OK, false if we generated an exception.
337
+ */
338
+ s->eci_handled = true;
339
+ switch (s->eci) {
340
+ case ECI_NONE:
341
+ case ECI_A0:
342
+ case ECI_A0A1:
343
+ case ECI_A0A1A2:
344
+ case ECI_A0A1A2B0:
345
+ return true;
346
+ default:
347
+ /* Reserved value: INVSTATE UsageFault */
348
+ gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
349
+ default_exception_el(s));
350
+ return false;
351
+ }
352
+}
353
+
354
+static void mve_update_eci(DisasContext *s)
355
+{
356
+ /*
357
+ * The helper function will always update the CPUState field,
358
+ * so we only need to update the DisasContext field.
359
+ */
360
+ if (s->eci) {
361
+ s->eci = (s->eci == ECI_A0A1A2B0) ? ECI_A0 : ECI_NONE;
362
+ }
363
+}
364
+
365
+static bool do_ldst(DisasContext *s, arg_VLDR_VSTR *a, MVEGenLdStFn *fn)
366
+{
367
+ TCGv_i32 addr;
368
+ uint32_t offset;
369
+ TCGv_ptr qreg;
370
+
371
+ if (!dc_isar_feature(aa32_mve, s) ||
372
+ !mve_check_qreg_bank(s, a->qd) ||
373
+ !fn) {
374
+ return false;
375
+ }
376
+
377
+ /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
378
+ if (a->rn == 15 || (a->rn == 13 && a->w)) {
379
+ return false;
380
+ }
381
+
382
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
383
+ return true;
384
+ }
385
+
386
+ offset = a->imm << a->size;
387
+ if (!a->a) {
388
+ offset = -offset;
389
+ }
390
+ addr = load_reg(s, a->rn);
391
+ if (a->p) {
392
+ tcg_gen_addi_i32(addr, addr, offset);
393
+ }
394
+
395
+ qreg = mve_qreg_ptr(a->qd);
396
+ fn(cpu_env, qreg, addr);
397
+ tcg_temp_free_ptr(qreg);
398
+
399
+ /*
400
+ * Writeback always happens after the last beat of the insn,
401
+ * regardless of predication
402
+ */
403
+ if (a->w) {
404
+ if (!a->p) {
405
+ tcg_gen_addi_i32(addr, addr, offset);
406
+ }
407
+ store_reg(s, a->rn, addr);
408
+ } else {
409
+ tcg_temp_free_i32(addr);
410
+ }
411
+ mve_update_eci(s);
412
+ return true;
413
+}
414
+
415
+static bool trans_VLDR_VSTR(DisasContext *s, arg_VLDR_VSTR *a)
416
+{
417
+ static MVEGenLdStFn * const ldstfns[4][2] = {
418
+ { gen_helper_mve_vstrb, gen_helper_mve_vldrb },
419
+ { gen_helper_mve_vstrh, gen_helper_mve_vldrh },
420
+ { gen_helper_mve_vstrw, gen_helper_mve_vldrw },
421
+ { NULL, NULL }
422
+ };
423
+ return do_ldst(s, a, ldstfns[a->size][a->l]);
424
+}
425
diff --git a/target/arm/meson.build b/target/arm/meson.build
426
index XXXXXXX..XXXXXXX 100644
285
index XXXXXXX..XXXXXXX 100644
427
--- a/target/arm/meson.build
286
--- a/hw/misc/Kconfig
428
+++ b/target/arm/meson.build
287
+++ b/hw/misc/Kconfig
429
@@ -XXX,XX +XXX,XX @@ arm_ss.add(files(
288
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10_CCM
430
'helper.c',
289
config ALLWINNER_A10_DRAMC
431
'iwmmxt_helper.c',
290
bool
432
'm_helper.c',
291
433
+ 'mve_helper.c',
292
+config AXP209_PMU
434
'neon_helper.c',
293
+ bool
435
'op_helper.c',
294
+ depends on I2C
436
'tlb_helper.c',
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"
437
--
325
--
438
2.20.1
326
2.34.1
439
440
diff view generated by jsdifflib
1
Implement the MVE VHCADD insn, which is similar to VCADD
1
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
2
but performs a halving step. This one overlaps with VADC.
3
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
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
Message-id: 20210617121628.20116-43-peter.maydell@linaro.org
7
---
10
---
8
target/arm/helper-mve.h | 8 ++++++++
11
hw/arm/cubieboard.c | 6 ++++++
9
target/arm/mve.decode | 8 ++++++--
12
hw/arm/Kconfig | 1 +
10
target/arm/mve_helper.c | 2 ++
13
2 files changed, 7 insertions(+)
11
target/arm/translate-mve.c | 4 +++-
12
4 files changed, 19 insertions(+), 3 deletions(-)
13
14
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
15
diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-mve.h
17
--- a/hw/arm/cubieboard.c
17
+++ b/target/arm/helper-mve.h
18
+++ b/hw/arm/cubieboard.c
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vcadd270b, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
@@ -XXX,XX +XXX,XX @@
19
DEF_HELPER_FLAGS_4(mve_vcadd270h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
#include "hw/boards.h"
20
DEF_HELPER_FLAGS_4(mve_vcadd270w, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
#include "hw/qdev-properties.h"
21
22
#include "hw/arm/allwinner-a10.h"
22
+DEF_HELPER_FLAGS_4(mve_vhcadd90b, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
+#include "hw/i2c/i2c.h"
23
+DEF_HELPER_FLAGS_4(mve_vhcadd90h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
24
+DEF_HELPER_FLAGS_4(mve_vhcadd90w, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
static struct arm_boot_info cubieboard_binfo = {
26
.loader_start = AW_A10_SDRAM_BASE,
27
@@ -XXX,XX +XXX,XX @@ static void cubieboard_init(MachineState *machine)
28
BlockBackend *blk;
29
BusState *bus;
30
DeviceState *carddev;
31
+ I2CBus *i2c;
32
33
/* BIOS is not supported by this board */
34
if (machine->firmware) {
35
@@ -XXX,XX +XXX,XX @@ static void cubieboard_init(MachineState *machine)
36
exit(1);
37
}
38
39
+ /* Connect AXP 209 */
40
+ i2c = I2C_BUS(qdev_get_child_bus(DEVICE(&a10->i2c0), "i2c"));
41
+ i2c_slave_create_simple(i2c, "axp209_pmu", 0x34);
25
+
42
+
26
+DEF_HELPER_FLAGS_4(mve_vhcadd270b, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
43
/* Retrieve SD bus */
27
+DEF_HELPER_FLAGS_4(mve_vhcadd270h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
44
di = drive_get(IF_SD, 0, 0);
28
+DEF_HELPER_FLAGS_4(mve_vhcadd270w, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
45
blk = di ? blk_by_legacy_dinfo(di) : NULL;
29
+
46
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
30
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
32
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
33
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
34
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/mve.decode
48
--- a/hw/arm/Kconfig
36
+++ b/target/arm/mve.decode
49
+++ b/hw/arm/Kconfig
37
@@ -XXX,XX +XXX,XX @@ VQDMULLT 111 . 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 1 @2op_sz28
50
@@ -XXX,XX +XXX,XX @@ config ALLWINNER_A10
38
VRHADD_S 111 0 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
51
select ALLWINNER_A10_DRAMC
39
VRHADD_U 111 1 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
52
select ALLWINNER_EMAC
40
53
select ALLWINNER_I2C
41
-VADC 1110 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
54
+ select AXP209_PMU
42
-VADCI 1110 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 0 @2op_nosz
55
select SERIAL
43
+{
56
select UNIMP
44
+ VADC 1110 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
57
45
+ VADCI 1110 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 0 @2op_nosz
46
+ VHCADD90 1110 1110 0 . .. ... 0 ... 0 1111 . 0 . 0 ... 0 @2op
47
+ VHCADD270 1110 1110 0 . .. ... 0 ... 1 1111 . 0 . 0 ... 0 @2op
48
+}
49
50
{
51
VSBC 1111 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
52
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/mve_helper.c
55
+++ b/target/arm/mve_helper.c
56
@@ -XXX,XX +XXX,XX @@ void HELPER(mve_vsbci)(CPUARMState *env, void *vd, void *vn, void *vm)
57
58
DO_VCADD_ALL(vcadd90, DO_SUB, DO_ADD)
59
DO_VCADD_ALL(vcadd270, DO_ADD, DO_SUB)
60
+DO_VCADD_ALL(vhcadd90, do_vhsub_s, do_vhadd_s)
61
+DO_VCADD_ALL(vhcadd270, do_vhadd_s, do_vhsub_s)
62
63
static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
64
{
65
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/target/arm/translate-mve.c
68
+++ b/target/arm/translate-mve.c
69
@@ -XXX,XX +XXX,XX @@ DO_2OP(VRHADD_U, vrhaddu)
70
/*
71
* VCADD Qd == Qm at size MO_32 is UNPREDICTABLE; we choose not to diagnose
72
* so we can reuse the DO_2OP macro. (Our implementation calculates the
73
- * "expected" results in this case.)
74
+ * "expected" results in this case.) Similarly for VHCADD.
75
*/
76
DO_2OP(VCADD90, vcadd90)
77
DO_2OP(VCADD270, vcadd270)
78
+DO_2OP(VHCADD90, vhcadd90)
79
+DO_2OP(VHCADD270, vhcadd270)
80
81
static bool trans_VQDMULLB(DisasContext *s, arg_2op *a)
82
{
83
--
58
--
84
2.20.1
59
2.34.1
85
60
86
61
diff view generated by jsdifflib
1
Implement the vector form of the MVE VQDMULL insn.
1
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
2
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
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-39-peter.maydell@linaro.org
6
---
15
---
7
target/arm/helper-mve.h | 5 +++++
16
include/hw/arm/allwinner-a10.h | 21 +++++++++++++++++++++
8
target/arm/mve.decode | 5 +++++
17
hw/arm/allwinner-a10.c | 18 ++++++++++++++++++
9
target/arm/mve_helper.c | 30 ++++++++++++++++++++++++++++++
18
hw/arm/cubieboard.c | 5 +++++
10
target/arm/translate-mve.c | 30 ++++++++++++++++++++++++++++++
19
3 files changed, 44 insertions(+)
11
4 files changed, 70 insertions(+)
12
20
13
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
14
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
23
--- a/include/hw/arm/allwinner-a10.h
16
+++ b/target/arm/helper-mve.h
24
+++ b/include/hw/arm/allwinner-a10.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqrdmlsdhxb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
@@ -XXX,XX +XXX,XX @@
18
DEF_HELPER_FLAGS_4(mve_vqrdmlsdhxh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
#include "hw/misc/allwinner-a10-ccm.h"
19
DEF_HELPER_FLAGS_4(mve_vqrdmlsdhxw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
#include "hw/misc/allwinner-a10-dramc.h"
20
28
#include "hw/i2c/allwinner-i2c.h"
21
+DEF_HELPER_FLAGS_4(mve_vqdmullbh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
+#include "sysemu/block-backend.h"
22
+DEF_HELPER_FLAGS_4(mve_vqdmullbw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
23
+DEF_HELPER_FLAGS_4(mve_vqdmullth, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
#include "target/arm/cpu.h"
24
+DEF_HELPER_FLAGS_4(mve_vqdmulltw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
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);
25
+
56
+
26
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
57
#endif
27
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
58
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
28
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
29
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
30
index XXXXXXX..XXXXXXX 100644
59
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/mve.decode
60
--- a/hw/arm/allwinner-a10.c
32
+++ b/target/arm/mve.decode
61
+++ b/hw/arm/allwinner-a10.c
33
@@ -XXX,XX +XXX,XX @@
62
@@ -XXX,XX +XXX,XX @@
34
@1op_nosz .... .... .... .... .... .... .... .... &1op qd=%qd qm=%qm size=0
63
#include "sysemu/sysemu.h"
35
@2op .... .... .. size:2 .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn
64
#include "hw/boards.h"
36
@2op_nosz .... .... .... .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn size=0
65
#include "hw/usb/hcd-ohci.h"
37
+@2op_sz28 .... .... .... .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn \
66
+#include "hw/loader.h"
38
+ size=%size_28
67
39
68
+#define AW_A10_SRAM_A_BASE 0x00000000
40
# The _rev suffix indicates that Vn and Vm are reversed. This is
69
#define AW_A10_DRAMC_BASE 0x01c01000
41
# the case for shifts. In the Arm ARM these insns are documented
70
#define AW_A10_MMC0_BASE 0x01c0f000
42
@@ -XXX,XX +XXX,XX @@ VQDMLSDHX 1111 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 0 @2op
71
#define AW_A10_CCM_BASE 0x01c20000
43
VQRDMLSDH 1111 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 1 @2op
72
@@ -XXX,XX +XXX,XX @@
44
VQRDMLSDHX 1111 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 1 @2op
73
#define AW_A10_RTC_BASE 0x01c20d00
45
74
#define AW_A10_I2C0_BASE 0x01c2ac00
46
+VQDMULLB 111 . 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 1 @2op_sz28
75
47
+VQDMULLT 111 . 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 1 @2op_sz28
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);
48
+
80
+
49
# Vector miscellaneous
81
+ if (blk_pread(blk, 8 * KiB, rom_size, buffer, 0) < 0) {
50
82
+ error_setg(&error_fatal, "%s: failed to read BlockBackend data",
51
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
83
+ __func__);
52
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
84
+ return;
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/mve_helper.c
55
+++ b/target/arm/mve_helper.c
56
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT_SCALAR_L(vqdmullt_scalarh, 1, 2, int16_t, 4, int32_t, \
57
DO_2OP_SAT_SCALAR_L(vqdmullt_scalarw, 1, 4, int32_t, 8, int64_t, \
58
do_qdmullw, SATMASK32)
59
60
+/*
61
+ * Long saturating ops
62
+ */
63
+#define DO_2OP_SAT_L(OP, TOP, ESIZE, TYPE, LESIZE, LTYPE, FN, SATMASK) \
64
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
65
+ void *vm) \
66
+ { \
67
+ LTYPE *d = vd; \
68
+ TYPE *n = vn, *m = vm; \
69
+ uint16_t mask = mve_element_mask(env); \
70
+ unsigned le; \
71
+ bool qc = false; \
72
+ for (le = 0; le < 16 / LESIZE; le++, mask >>= LESIZE) { \
73
+ bool sat = false; \
74
+ LTYPE op1 = n[H##ESIZE(le * 2 + TOP)]; \
75
+ LTYPE op2 = m[H##ESIZE(le * 2 + TOP)]; \
76
+ mergemask(&d[H##LESIZE(le)], FN(op1, op2, &sat), mask); \
77
+ qc |= sat && (mask & SATMASK); \
78
+ } \
79
+ if (qc) { \
80
+ env->vfp.qc[0] = qc; \
81
+ } \
82
+ mve_advance_vpt(env); \
83
+ }
85
+ }
84
+
86
+
85
+DO_2OP_SAT_L(vqdmullbh, 0, 2, int16_t, 4, int32_t, do_qdmullh, SATMASK16B)
87
+ rom_add_blob("allwinner-a10.bootrom", buffer, rom_size,
86
+DO_2OP_SAT_L(vqdmullbw, 0, 4, int32_t, 8, int64_t, do_qdmullw, SATMASK32)
88
+ rom_size, AW_A10_SRAM_A_BASE,
87
+DO_2OP_SAT_L(vqdmullth, 1, 2, int16_t, 4, int32_t, do_qdmullh, SATMASK16T)
89
+ NULL, NULL, NULL, NULL, false);
88
+DO_2OP_SAT_L(vqdmulltw, 1, 4, int32_t, 8, int64_t, do_qdmullw, SATMASK32)
89
+
90
static inline uint32_t do_vbrsrb(uint32_t n, uint32_t m)
91
{
92
m &= 0xff;
93
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/target/arm/translate-mve.c
96
+++ b/target/arm/translate-mve.c
97
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQDMLSDHX, vqdmlsdhx)
98
DO_2OP(VQRDMLSDH, vqrdmlsdh)
99
DO_2OP(VQRDMLSDHX, vqrdmlsdhx)
100
101
+static bool trans_VQDMULLB(DisasContext *s, arg_2op *a)
102
+{
103
+ static MVEGenTwoOpFn * const fns[] = {
104
+ NULL,
105
+ gen_helper_mve_vqdmullbh,
106
+ gen_helper_mve_vqdmullbw,
107
+ NULL,
108
+ };
109
+ if (a->size == MO_32 && (a->qd == a->qm || a->qd == a->qn)) {
110
+ /* UNPREDICTABLE; we choose to undef */
111
+ return false;
112
+ }
113
+ return do_2op(s, a, fns[a->size]);
114
+}
90
+}
115
+
91
+
116
+static bool trans_VQDMULLT(DisasContext *s, arg_2op *a)
92
static void aw_a10_init(Object *obj)
117
+{
93
{
118
+ static MVEGenTwoOpFn * const fns[] = {
94
AwA10State *s = AW_A10(obj);
119
+ NULL,
95
diff --git a/hw/arm/cubieboard.c b/hw/arm/cubieboard.c
120
+ gen_helper_mve_vqdmullth,
96
index XXXXXXX..XXXXXXX 100644
121
+ gen_helper_mve_vqdmulltw,
97
--- a/hw/arm/cubieboard.c
122
+ NULL,
98
+++ b/hw/arm/cubieboard.c
123
+ };
99
@@ -XXX,XX +XXX,XX @@ static void cubieboard_init(MachineState *machine)
124
+ if (a->size == MO_32 && (a->qd == a->qm || a->qd == a->qn)) {
100
memory_region_add_subregion(get_system_memory(), AW_A10_SDRAM_BASE,
125
+ /* UNPREDICTABLE; we choose to undef */
101
machine->ram);
126
+ return false;
102
103
+ /* Load target kernel or start using BootROM */
104
+ if (!machine->kernel_filename && blk && blk_is_available(blk)) {
105
+ /* Use Boot ROM to copy data from SD card to SRAM */
106
+ allwinner_a10_bootrom_setup(a10, blk);
127
+ }
107
+ }
128
+ return do_2op(s, a, fns[a->size]);
108
/* TODO create and connect IDE devices for ide_drive_get() */
129
+}
109
130
+
110
cubieboard_binfo.ram_size = machine->ram_size;
131
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
132
MVEGenTwoOpScalarFn fn)
133
{
134
--
111
--
135
2.20.1
112
2.34.1
136
137
diff view generated by jsdifflib
1
Implement the MVE VRHADD insn, which performs a rounded halving
1
From: Strahinja Jankovic <strahinjapjankovic@gmail.com>
2
addition.
3
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
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
Message-id: 20210617121628.20116-40-peter.maydell@linaro.org
7
---
11
---
8
target/arm/helper-mve.h | 8 ++++++++
12
tests/avocado/boot_linux_console.py | 47 +++++++++++++++++++++++++++++
9
target/arm/mve.decode | 3 +++
13
1 file changed, 47 insertions(+)
10
target/arm/mve_helper.c | 6 ++++++
11
target/arm/translate-mve.c | 2 ++
12
4 files changed, 19 insertions(+)
13
14
14
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
15
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-mve.h
17
--- a/tests/avocado/boot_linux_console.py
17
+++ b/target/arm/helper-mve.h
18
+++ b/tests/avocado/boot_linux_console.py
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqdmullbw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
@@ -XXX,XX +XXX,XX @@ def test_arm_cubieboard_sata(self):
19
DEF_HELPER_FLAGS_4(mve_vqdmullth, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
'sda')
20
DEF_HELPER_FLAGS_4(mve_vqdmulltw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
# cubieboard's reboot is not functioning; omit reboot test.
21
22
22
+DEF_HELPER_FLAGS_4(mve_vrhaddsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
+ @skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
23
+DEF_HELPER_FLAGS_4(mve_vrhaddsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+ def test_arm_cubieboard_openwrt_22_03_2(self):
24
+DEF_HELPER_FLAGS_4(mve_vrhaddsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+ """
26
+ :avocado: tags=arch:arm
27
+ :avocado: tags=machine:cubieboard
28
+ :avocado: tags=device:sd
29
+ """
25
+
30
+
26
+DEF_HELPER_FLAGS_4(mve_vrhaddub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
+ # This test download a 7.5 MiB compressed image and expand it
27
+DEF_HELPER_FLAGS_4(mve_vrhadduh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
+ # to 126 MiB.
28
+DEF_HELPER_FLAGS_4(mve_vrhadduw, TCG_CALL_NO_WG, void, env, ptr, 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)
29
+
42
+
30
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
43
+ self.vm.set_console()
31
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
44
+ self.vm.add_args('-drive', 'file=' + image_path + ',if=sd,format=raw',
32
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
45
+ '-nic', 'user',
33
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
46
+ '-no-reboot')
34
index XXXXXXX..XXXXXXX 100644
47
+ self.vm.launch()
35
--- a/target/arm/mve.decode
36
+++ b/target/arm/mve.decode
37
@@ -XXX,XX +XXX,XX @@ VQRDMLSDHX 1111 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 1 @2op
38
VQDMULLB 111 . 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 1 @2op_sz28
39
VQDMULLT 111 . 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 1 @2op_sz28
40
41
+VRHADD_S 111 0 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
42
+VRHADD_U 111 1 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
43
+
48
+
44
# Vector miscellaneous
49
+ kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
45
50
+ 'usbcore.nousb '
46
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
51
+ 'noreboot')
47
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/mve_helper.c
50
+++ b/target/arm/mve_helper.c
51
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vshlu, DO_VSHLU)
52
DO_2OP_S(vrshls, DO_VRSHLS)
53
DO_2OP_U(vrshlu, DO_VRSHLU)
54
55
+#define DO_RHADD_S(N, M) (((int64_t)(N) + (M) + 1) >> 1)
56
+#define DO_RHADD_U(N, M) (((uint64_t)(N) + (M) + 1) >> 1)
57
+
52
+
58
+DO_2OP_S(vrhadds, DO_RHADD_S)
53
+ self.wait_for_console_pattern('U-Boot SPL')
59
+DO_2OP_U(vrhaddu, DO_RHADD_U)
60
+
54
+
61
static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
55
+ interrupt_interactive_console_until_pattern(
62
{
56
+ self, 'Hit any key to stop autoboot:', '=>')
63
if (val > max) {
57
+ exec_command_and_wait_for_pattern(self, "setenv extraargs '" +
64
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
58
+ kernel_command_line + "'", '=>')
65
index XXXXXXX..XXXXXXX 100644
59
+ exec_command_and_wait_for_pattern(self, 'boot', 'Starting kernel ...');
66
--- a/target/arm/translate-mve.c
60
+
67
+++ b/target/arm/translate-mve.c
61
+ self.wait_for_console_pattern(
68
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQDMLSDH, vqdmlsdh)
62
+ 'Please press Enter to activate this console.')
69
DO_2OP(VQDMLSDHX, vqdmlsdhx)
63
+
70
DO_2OP(VQRDMLSDH, vqrdmlsdh)
64
+ exec_command_and_wait_for_pattern(self, ' ', 'root@')
71
DO_2OP(VQRDMLSDHX, vqrdmlsdhx)
65
+
72
+DO_2OP(VRHADD_S, vrhadds)
66
+ exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
73
+DO_2OP(VRHADD_U, vrhaddu)
67
+ 'Allwinner sun4i/sun5i')
74
68
+ # cubieboard's reboot is not functioning; omit reboot test.
75
static bool trans_VQDMULLB(DisasContext *s, arg_2op *a)
69
+
76
{
70
@skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout')
71
def test_arm_quanta_gsj(self):
72
"""
77
--
73
--
78
2.20.1
74
2.34.1
79
80
diff view generated by jsdifflib
1
In the code for handling VFP system register accesses there is some
1
From: Richard Henderson <richard.henderson@linaro.org>
2
stray whitespace after a unary '-' operator, and also some incorrect
2
3
indent in a couple of function prototypes. We're about to move this
3
Don't dereference CPUTLBEntryFull until we verify that
4
code to another file, so fix the code style issues first so
4
the page is valid. Move the other user-only info field
5
checkpatch doesn't complain about the code-movement patch.
5
updates after the valid check to match.
6
6
7
Cc: qemu-stable@nongnu.org
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
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210618141019.10671-2-peter.maydell@linaro.org
11
---
13
---
12
target/arm/translate-vfp.c | 11 +++++------
14
target/arm/sve_helper.c | 14 +++++++++-----
13
1 file changed, 5 insertions(+), 6 deletions(-)
15
1 file changed, 9 insertions(+), 5 deletions(-)
14
16
15
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
17
diff --git a/target/arm/sve_helper.c b/target/arm/sve_helper.c
16
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-vfp.c
19
--- a/target/arm/sve_helper.c
18
+++ b/target/arm/translate-vfp.c
20
+++ b/target/arm/sve_helper.c
19
@@ -XXX,XX +XXX,XX @@ static void gen_branch_fpInactive(DisasContext *s, TCGCond cond,
21
@@ -XXX,XX +XXX,XX @@ bool sve_probe_page(SVEHostPage *info, bool nofault, CPUARMState *env,
20
}
22
#ifdef CONFIG_USER_ONLY
21
23
flags = probe_access_flags(env, addr, access_type, mmu_idx, nofault,
22
static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
24
&info->host, retaddr);
23
-
25
- memset(&info->attrs, 0, sizeof(info->attrs));
24
fp_sysreg_loadfn *loadfn,
26
- /* Require both ANON and MTE; see allocation_tag_mem(). */
25
- void *opaque)
27
- info->tagged = (flags & PAGE_ANON) && (flags & PAGE_MTE);
26
+ void *opaque)
28
#else
27
{
29
CPUTLBEntryFull *full;
28
/* Do a write to an M-profile floating point system register */
30
flags = probe_access_full(env, addr, access_type, mmu_idx, nofault,
29
TCGv_i32 tmp;
31
&info->host, &full, retaddr);
30
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
32
- info->attrs = full->attrs;
31
}
33
- info->tagged = full->pte_attrs == 0xf0;
32
34
#endif
33
static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
35
info->flags = flags;
34
- fp_sysreg_storefn *storefn,
36
35
- void *opaque)
37
@@ -XXX,XX +XXX,XX @@ bool sve_probe_page(SVEHostPage *info, bool nofault, CPUARMState *env,
36
+ fp_sysreg_storefn *storefn,
38
return false;
37
+ void *opaque)
38
{
39
/* Do a read from an M-profile floating point system register */
40
TCGv_i32 tmp;
41
@@ -XXX,XX +XXX,XX @@ static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
42
TCGv_i32 addr;
43
44
if (!a->a) {
45
- offset = - offset;
46
+ offset = -offset;
47
}
39
}
48
40
49
addr = load_reg(s, a->rn);
41
+#ifdef CONFIG_USER_ONLY
50
@@ -XXX,XX +XXX,XX @@ static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
42
+ memset(&info->attrs, 0, sizeof(info->attrs));
51
TCGv_i32 value = tcg_temp_new_i32();
43
+ /* Require both ANON and MTE; see allocation_tag_mem(). */
52
44
+ info->tagged = (flags & PAGE_ANON) && (flags & PAGE_MTE);
53
if (!a->a) {
45
+#else
54
- offset = - offset;
46
+ info->attrs = full->attrs;
55
+ offset = -offset;
47
+ info->tagged = full->pte_attrs == 0xf0;
56
}
48
+#endif
57
49
+
58
addr = load_reg(s, a->rn);
50
/* Ensure that info->host[] is relative to addr, not addr + mem_off. */
51
info->host -= mem_off;
52
return true;
59
--
53
--
60
2.20.1
54
2.34.1
61
55
62
56
diff view generated by jsdifflib
1
Implement the MVE VCADD insn, which performs a complex add with
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
rotate. Note that the size=0b11 encoding is VSBC.
3
2
4
The architecture grants some leeway for the "destination and Vm
3
Since pxa255_init() must map the device in the system memory,
5
source overlap" case for the size MO_32 case, but we choose not to
4
there is no point in passing get_system_memory() by argument.
6
make use of it, instead always calculating all 16 bytes worth of
7
results before setting the destination register.
8
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
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20210617121628.20116-42-peter.maydell@linaro.org
12
---
10
---
13
target/arm/helper-mve.h | 8 ++++++++
11
include/hw/arm/pxa.h | 2 +-
14
target/arm/mve.decode | 9 +++++++--
12
hw/arm/gumstix.c | 3 +--
15
target/arm/mve_helper.c | 29 +++++++++++++++++++++++++++++
13
hw/arm/pxa2xx.c | 4 +++-
16
target/arm/translate-mve.c | 7 +++++++
14
hw/arm/tosa.c | 2 +-
17
4 files changed, 51 insertions(+), 2 deletions(-)
15
4 files changed, 6 insertions(+), 5 deletions(-)
18
16
19
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
17
diff --git a/include/hw/arm/pxa.h b/include/hw/arm/pxa.h
20
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper-mve.h
19
--- a/include/hw/arm/pxa.h
22
+++ b/target/arm/helper-mve.h
20
+++ b/include/hw/arm/pxa.h
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vadci, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
@@ -XXX,XX +XXX,XX @@ struct PXA2xxI2SState {
24
DEF_HELPER_FLAGS_4(mve_vsbc, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
25
DEF_HELPER_FLAGS_4(mve_vsbci, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
PXA2xxState *pxa270_init(MemoryRegion *address_space, unsigned int sdram_size,
26
24
const char *revision);
27
+DEF_HELPER_FLAGS_4(mve_vcadd90b, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
-PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size);
28
+DEF_HELPER_FLAGS_4(mve_vcadd90h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
+PXA2xxState *pxa255_init(unsigned int sdram_size);
29
+DEF_HELPER_FLAGS_4(mve_vcadd90w, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
30
+
28
#endif /* PXA_H */
31
+DEF_HELPER_FLAGS_4(mve_vcadd270b, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
32
+DEF_HELPER_FLAGS_4(mve_vcadd270h, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
+DEF_HELPER_FLAGS_4(mve_vcadd270w, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
+
35
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
36
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
37
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
38
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
39
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/mve.decode
31
--- a/hw/arm/gumstix.c
41
+++ b/target/arm/mve.decode
32
+++ b/hw/arm/gumstix.c
42
@@ -XXX,XX +XXX,XX @@ VRHADD_S 111 0 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
33
@@ -XXX,XX +XXX,XX @@ static void connex_init(MachineState *machine)
43
VRHADD_U 111 1 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
34
{
44
35
PXA2xxState *cpu;
45
VADC 1110 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
36
DriveInfo *dinfo;
46
-VSBC 1111 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
37
- MemoryRegion *address_space_mem = get_system_memory();
47
VADCI 1110 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 0 @2op_nosz
38
48
-VSBCI 1111 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 0 @2op_nosz
39
uint32_t connex_rom = 0x01000000;
49
+
40
uint32_t connex_ram = 0x04000000;
50
+{
41
51
+ VSBC 1111 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
42
- cpu = pxa255_init(address_space_mem, connex_ram);
52
+ VSBCI 1111 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 0 @2op_nosz
43
+ cpu = pxa255_init(connex_ram);
53
+ VCADD90 1111 1110 0 . .. ... 0 ... 0 1111 . 0 . 0 ... 0 @2op
44
54
+ VCADD270 1111 1110 0 . .. ... 0 ... 1 1111 . 0 . 0 ... 0 @2op
45
dinfo = drive_get(IF_PFLASH, 0, 0);
55
+}
46
if (!dinfo && !qtest_enabled()) {
56
47
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
57
# Vector miscellaneous
58
59
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
60
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
61
--- a/target/arm/mve_helper.c
49
--- a/hw/arm/pxa2xx.c
62
+++ b/target/arm/mve_helper.c
50
+++ b/hw/arm/pxa2xx.c
63
@@ -XXX,XX +XXX,XX @@ void HELPER(mve_vsbci)(CPUARMState *env, void *vd, void *vn, void *vm)
51
@@ -XXX,XX +XXX,XX @@
64
do_vadc(env, vd, vn, vm, -1, 1, true);
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,
65
}
60
}
66
61
67
+#define DO_VCADD(OP, ESIZE, TYPE, FN0, FN1) \
62
/* Initialise a PXA255 integrated chip (ARM based core). */
68
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, void *vm) \
63
-PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
69
+ { \
64
+PXA2xxState *pxa255_init(unsigned int sdram_size)
70
+ TYPE *d = vd, *n = vn, *m = vm; \
71
+ uint16_t mask = mve_element_mask(env); \
72
+ unsigned e; \
73
+ TYPE r[16 / ESIZE]; \
74
+ /* Calculate all results first to avoid overwriting inputs */ \
75
+ for (e = 0; e < 16 / ESIZE; e++) { \
76
+ if (!(e & 1)) { \
77
+ r[e] = FN0(n[H##ESIZE(e)], m[H##ESIZE(e + 1)]); \
78
+ } else { \
79
+ r[e] = FN1(n[H##ESIZE(e)], m[H##ESIZE(e - 1)]); \
80
+ } \
81
+ } \
82
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
83
+ mergemask(&d[H##ESIZE(e)], r[e], mask); \
84
+ } \
85
+ mve_advance_vpt(env); \
86
+ }
87
+
88
+#define DO_VCADD_ALL(OP, FN0, FN1) \
89
+ DO_VCADD(OP##b, 1, int8_t, FN0, FN1) \
90
+ DO_VCADD(OP##h, 2, int16_t, FN0, FN1) \
91
+ DO_VCADD(OP##w, 4, int32_t, FN0, FN1)
92
+
93
+DO_VCADD_ALL(vcadd90, DO_SUB, DO_ADD)
94
+DO_VCADD_ALL(vcadd270, DO_ADD, DO_SUB)
95
+
96
static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
97
{
65
{
98
if (val > max) {
66
+ MemoryRegion *address_space = get_system_memory();
99
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
67
PXA2xxState *s;
68
int i;
69
DriveInfo *dinfo;
70
diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c
100
index XXXXXXX..XXXXXXX 100644
71
index XXXXXXX..XXXXXXX 100644
101
--- a/target/arm/translate-mve.c
72
--- a/hw/arm/tosa.c
102
+++ b/target/arm/translate-mve.c
73
+++ b/hw/arm/tosa.c
103
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQRDMLSDH, vqrdmlsdh)
74
@@ -XXX,XX +XXX,XX @@ static void tosa_init(MachineState *machine)
104
DO_2OP(VQRDMLSDHX, vqrdmlsdhx)
75
TC6393xbState *tmio;
105
DO_2OP(VRHADD_S, vrhadds)
76
DeviceState *scp0, *scp1;
106
DO_2OP(VRHADD_U, vrhaddu)
77
107
+/*
78
- mpu = pxa255_init(address_space_mem, tosa_binfo.ram_size);
108
+ * VCADD Qd == Qm at size MO_32 is UNPREDICTABLE; we choose not to diagnose
79
+ mpu = pxa255_init(tosa_binfo.ram_size);
109
+ * so we can reuse the DO_2OP macro. (Our implementation calculates the
80
110
+ * "expected" results in this case.)
81
memory_region_init_rom(rom, NULL, "tosa.rom", TOSA_ROM, &error_fatal);
111
+ */
82
memory_region_add_subregion(address_space_mem, 0, rom);
112
+DO_2OP(VCADD90, vcadd90)
113
+DO_2OP(VCADD270, vcadd270)
114
115
static bool trans_VQDMULLB(DisasContext *s, arg_2op *a)
116
{
117
--
83
--
118
2.20.1
84
2.34.1
119
85
120
86
diff view generated by jsdifflib
1
Implement the MVE VADC and VSBC insns. These perform an
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
add-with-carry or subtract-with-carry of the 32-bit elements in each
3
lane of the input vectors, where the carry-out of each add is the
4
carry-in of the next. The initial carry input is either 1 or is from
5
FPSCR.C; the carry out at the end is written back to FPSCR.C.
6
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
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
Message-id: 20210617121628.20116-41-peter.maydell@linaro.org
10
---
10
---
11
target/arm/helper-mve.h | 5 ++++
11
include/hw/arm/pxa.h | 3 +--
12
target/arm/mve.decode | 5 ++++
12
hw/arm/gumstix.c | 3 +--
13
target/arm/mve_helper.c | 52 ++++++++++++++++++++++++++++++++++++++
13
hw/arm/mainstone.c | 10 ++++------
14
target/arm/translate-mve.c | 37 +++++++++++++++++++++++++++
14
hw/arm/pxa2xx.c | 4 ++--
15
4 files changed, 99 insertions(+)
15
hw/arm/spitz.c | 6 ++----
16
hw/arm/z2.c | 3 +--
17
6 files changed, 11 insertions(+), 18 deletions(-)
16
18
17
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
18
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper-mve.h
21
--- a/include/hw/arm/pxa.h
20
+++ b/target/arm/helper-mve.h
22
+++ b/include/hw/arm/pxa.h
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vrhaddub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
@@ -XXX,XX +XXX,XX @@ struct PXA2xxI2SState {
22
DEF_HELPER_FLAGS_4(mve_vrhadduh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
23
DEF_HELPER_FLAGS_4(mve_vrhadduw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
# define PA_FMT            "0x%08lx"
24
26
25
+DEF_HELPER_FLAGS_4(mve_vadc, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
-PXA2xxState *pxa270_init(MemoryRegion *address_space, unsigned int sdram_size,
26
+DEF_HELPER_FLAGS_4(mve_vadci, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
- const char *revision);
27
+DEF_HELPER_FLAGS_4(mve_vsbc, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
+PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision);
28
+DEF_HELPER_FLAGS_4(mve_vsbci, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
PXA2xxState *pxa255_init(unsigned int sdram_size);
29
+
31
30
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
32
#endif /* PXA_H */
31
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
33
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
32
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
33
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
34
index XXXXXXX..XXXXXXX 100644
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 @@ VQDMULLT 111 . 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 1 @2op_sz28
37
@@ -XXX,XX +XXX,XX @@ static void verdex_init(MachineState *machine)
38
VRHADD_S 111 0 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
38
{
39
VRHADD_U 111 1 1111 0 . .. ... 0 ... 0 0001 . 1 . 0 ... 0 @2op
39
PXA2xxState *cpu;
40
40
DriveInfo *dinfo;
41
+VADC 1110 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
41
- MemoryRegion *address_space_mem = get_system_memory();
42
+VSBC 1111 1110 0 . 11 ... 0 ... 0 1111 . 0 . 0 ... 0 @2op_nosz
42
43
+VADCI 1110 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 0 @2op_nosz
43
uint32_t verdex_rom = 0x02000000;
44
+VSBCI 1111 1110 0 . 11 ... 0 ... 1 1111 . 0 . 0 ... 0 @2op_nosz
44
uint32_t verdex_ram = 0x10000000;
45
+
45
46
# Vector miscellaneous
46
- cpu = pxa270_init(address_space_mem, verdex_ram, machine->cpu_type);
47
47
+ cpu = pxa270_init(verdex_ram, machine->cpu_type);
48
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
48
49
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
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
50
index XXXXXXX..XXXXXXX 100644
52
index XXXXXXX..XXXXXXX 100644
51
--- a/target/arm/mve_helper.c
53
--- a/hw/arm/mainstone.c
52
+++ b/target/arm/mve_helper.c
54
+++ b/hw/arm/mainstone.c
53
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vrshlu, DO_VRSHLU)
55
@@ -XXX,XX +XXX,XX @@ static struct arm_boot_info mainstone_binfo = {
54
DO_2OP_S(vrhadds, DO_RHADD_S)
56
.ram_size = 0x04000000,
55
DO_2OP_U(vrhaddu, DO_RHADD_U)
57
};
56
58
57
+static void do_vadc(CPUARMState *env, uint32_t *d, uint32_t *n, uint32_t *m,
59
-static void mainstone_common_init(MemoryRegion *address_space_mem,
58
+ uint32_t inv, uint32_t carry_in, bool update_flags)
60
- MachineState *machine,
59
+{
61
+static void mainstone_common_init(MachineState *machine,
60
+ uint16_t mask = mve_element_mask(env);
62
enum mainstone_model_e model, int arm_id)
61
+ unsigned e;
62
+
63
+ /* If any additions trigger, we will update flags. */
64
+ if (mask & 0x1111) {
65
+ update_flags = true;
66
+ }
67
+
68
+ for (e = 0; e < 16 / 4; e++, mask >>= 4) {
69
+ uint64_t r = carry_in;
70
+ r += n[H4(e)];
71
+ r += m[H4(e)] ^ inv;
72
+ if (mask & 1) {
73
+ carry_in = r >> 32;
74
+ }
75
+ mergemask(&d[H4(e)], r, mask);
76
+ }
77
+
78
+ if (update_flags) {
79
+ /* Store C, clear NZV. */
80
+ env->vfp.xregs[ARM_VFP_FPSCR] &= ~FPCR_NZCV_MASK;
81
+ env->vfp.xregs[ARM_VFP_FPSCR] |= carry_in * FPCR_C;
82
+ }
83
+ mve_advance_vpt(env);
84
+}
85
+
86
+void HELPER(mve_vadc)(CPUARMState *env, void *vd, void *vn, void *vm)
87
+{
88
+ bool carry_in = env->vfp.xregs[ARM_VFP_FPSCR] & FPCR_C;
89
+ do_vadc(env, vd, vn, vm, 0, carry_in, false);
90
+}
91
+
92
+void HELPER(mve_vsbc)(CPUARMState *env, void *vd, void *vn, void *vm)
93
+{
94
+ bool carry_in = env->vfp.xregs[ARM_VFP_FPSCR] & FPCR_C;
95
+ do_vadc(env, vd, vn, vm, -1, carry_in, false);
96
+}
97
+
98
+
99
+void HELPER(mve_vadci)(CPUARMState *env, void *vd, void *vn, void *vm)
100
+{
101
+ do_vadc(env, vd, vn, vm, 0, 0, true);
102
+}
103
+
104
+void HELPER(mve_vsbci)(CPUARMState *env, void *vd, void *vn, void *vm)
105
+{
106
+ do_vadc(env, vd, vn, vm, -1, 1, true);
107
+}
108
+
109
static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
110
{
63
{
111
if (val > max) {
64
uint32_t sector_len = 256 * 1024;
112
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
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);
85
}
86
87
static void mainstone2_machine_init(MachineClass *mc)
88
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
113
index XXXXXXX..XXXXXXX 100644
89
index XXXXXXX..XXXXXXX 100644
114
--- a/target/arm/translate-mve.c
90
--- a/hw/arm/pxa2xx.c
115
+++ b/target/arm/translate-mve.c
91
+++ b/hw/arm/pxa2xx.c
116
@@ -XXX,XX +XXX,XX @@ static bool trans_VQDMULLT(DisasContext *s, arg_2op *a)
92
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_reset(void *opaque, int line, int level)
117
return do_2op(s, a, fns[a->size]);
118
}
93
}
119
94
120
+/*
95
/* Initialise a PXA270 integrated chip (ARM based core). */
121
+ * VADC and VSBC: these perform an add-with-carry or subtract-with-carry
96
-PXA2xxState *pxa270_init(MemoryRegion *address_space,
122
+ * of the 32-bit elements in each lane of the input vectors, where the
97
- unsigned int sdram_size, const char *cpu_type)
123
+ * carry-out of each add is the carry-in of the next. The initial carry
98
+PXA2xxState *pxa270_init(unsigned int sdram_size, const char *cpu_type)
124
+ * input is either fixed (0 for VADCI, 1 for VSBCI) or is from FPSCR.C
125
+ * (for VADC and VSBC); the carry out at the end is written back to FPSCR.C.
126
+ * These insns are subject to beat-wise execution. Partial execution
127
+ * of an I=1 (initial carry input fixed) insn which does not
128
+ * execute the first beat must start with the current FPSCR.NZCV
129
+ * value, not the fixed constant input.
130
+ */
131
+static bool trans_VADC(DisasContext *s, arg_2op *a)
132
+{
133
+ return do_2op(s, a, gen_helper_mve_vadc);
134
+}
135
+
136
+static bool trans_VADCI(DisasContext *s, arg_2op *a)
137
+{
138
+ if (mve_skip_first_beat(s)) {
139
+ return trans_VADC(s, a);
140
+ }
141
+ return do_2op(s, a, gen_helper_mve_vadci);
142
+}
143
+
144
+static bool trans_VSBC(DisasContext *s, arg_2op *a)
145
+{
146
+ return do_2op(s, a, gen_helper_mve_vsbc);
147
+}
148
+
149
+static bool trans_VSBCI(DisasContext *s, arg_2op *a)
150
+{
151
+ if (mve_skip_first_beat(s)) {
152
+ return trans_VSBC(s, a);
153
+ }
154
+ return do_2op(s, a, gen_helper_mve_vsbci);
155
+}
156
+
157
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
158
MVEGenTwoOpScalarFn fn)
159
{
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
105
index XXXXXXX..XXXXXXX 100644
106
--- a/hw/arm/spitz.c
107
+++ b/hw/arm/spitz.c
108
@@ -XXX,XX +XXX,XX @@ static void spitz_common_init(MachineState *machine)
109
SpitzMachineState *sms = SPITZ_MACHINE(machine);
110
enum spitz_model_e model = smc->model;
111
PXA2xxState *mpu;
112
- MemoryRegion *address_space_mem = get_system_memory();
113
MemoryRegion *rom = g_new(MemoryRegion, 1);
114
115
/* Setup CPU & memory */
116
- mpu = pxa270_init(address_space_mem, spitz_binfo.ram_size,
117
- machine->cpu_type);
118
+ mpu = pxa270_init(spitz_binfo.ram_size, machine->cpu_type);
119
sms->mpu = mpu;
120
121
sl_flash_register(mpu, (model == spitz) ? FLASH_128M : FLASH_1024M);
122
123
memory_region_init_rom(rom, NULL, "spitz.rom", SPITZ_ROM, &error_fatal);
124
- memory_region_add_subregion(address_space_mem, 0, rom);
125
+ memory_region_add_subregion(get_system_memory(), 0, rom);
126
127
/* Setup peripherals */
128
spitz_keyboard_register(mpu);
129
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
130
index XXXXXXX..XXXXXXX 100644
131
--- a/hw/arm/z2.c
132
+++ b/hw/arm/z2.c
133
@@ -XXX,XX +XXX,XX @@ static const TypeInfo aer915_info = {
134
135
static void z2_init(MachineState *machine)
136
{
137
- MemoryRegion *address_space_mem = get_system_memory();
138
uint32_t sector_len = 0x10000;
139
PXA2xxState *mpu;
140
DriveInfo *dinfo;
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,
160
--
150
--
161
2.20.1
151
2.34.1
162
152
163
153
diff view generated by jsdifflib
1
Implement the MVE VQDMLSDH and VQRDMLSDH insns, which are
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
like VQDMLADH and VQRDMLADH except that products are subtracted
3
rather than added.
4
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
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
Message-id: 20210617121628.20116-38-peter.maydell@linaro.org
8
---
11
---
9
target/arm/helper-mve.h | 16 ++++++++++++++
12
hw/arm/collie.c | 16 ++++++++++------
10
target/arm/mve.decode | 5 +++++
13
1 file changed, 10 insertions(+), 6 deletions(-)
11
target/arm/mve_helper.c | 44 ++++++++++++++++++++++++++++++++++++++
12
target/arm/translate-mve.c | 4 ++++
13
4 files changed, 69 insertions(+)
14
14
15
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
15
diff --git a/hw/arm/collie.c b/hw/arm/collie.c
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper-mve.h
17
--- a/hw/arm/collie.c
18
+++ b/target/arm/helper-mve.h
18
+++ b/hw/arm/collie.c
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqrdmladhxb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
@@ -XXX,XX +XXX,XX @@
20
DEF_HELPER_FLAGS_4(mve_vqrdmladhxh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
#include "cpu.h"
21
DEF_HELPER_FLAGS_4(mve_vqrdmladhxw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
#include "qom/object.h"
22
22
23
+DEF_HELPER_FLAGS_4(mve_vqdmlsdhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
+#define RAM_SIZE (512 * MiB)
24
+DEF_HELPER_FLAGS_4(mve_vqdmlsdhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+#define FLASH_SIZE (32 * MiB)
25
+DEF_HELPER_FLAGS_4(mve_vqdmlsdhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+#define FLASH_SECTOR_SIZE (64 * KiB)
26
+
26
+
27
+DEF_HELPER_FLAGS_4(mve_vqdmlsdhxb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
struct CollieMachineState {
28
+DEF_HELPER_FLAGS_4(mve_vqdmlsdhxh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
MachineState parent;
29
+DEF_HELPER_FLAGS_4(mve_vqdmlsdhxw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
30
+
30
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(CollieMachineState, COLLIE_MACHINE)
31
+DEF_HELPER_FLAGS_4(mve_vqrdmlsdhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
32
+DEF_HELPER_FLAGS_4(mve_vqrdmlsdhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
static struct arm_boot_info collie_binfo = {
33
+DEF_HELPER_FLAGS_4(mve_vqrdmlsdhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
.loader_start = SA_SDCS0,
34
+
34
- .ram_size = 0x20000000,
35
+DEF_HELPER_FLAGS_4(mve_vqrdmlsdhxb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
35
+ .ram_size = RAM_SIZE,
36
+DEF_HELPER_FLAGS_4(mve_vqrdmlsdhxh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
};
37
+DEF_HELPER_FLAGS_4(mve_vqrdmlsdhxw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
37
38
+
38
static void collie_init(MachineState *machine)
39
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
39
@@ -XXX,XX +XXX,XX @@ static void collie_init(MachineState *machine)
40
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
40
memory_region_add_subregion(get_system_memory(), SA_SDCS0, machine->ram);
41
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
41
42
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
42
dinfo = drive_get(IF_PFLASH, 0, 0);
43
index XXXXXXX..XXXXXXX 100644
43
- pflash_cfi01_register(SA_CS0, "collie.fl1", 0x02000000,
44
--- a/target/arm/mve.decode
44
+ pflash_cfi01_register(SA_CS0, "collie.fl1", FLASH_SIZE,
45
+++ b/target/arm/mve.decode
45
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
46
@@ -XXX,XX +XXX,XX @@ VQDMLADHX 1110 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 0 @2op
46
- 64 * KiB, 4, 0x00, 0x00, 0x00, 0x00, 0);
47
VQRDMLADH 1110 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 1 @2op
47
+ FLASH_SECTOR_SIZE, 4, 0x00, 0x00, 0x00, 0x00, 0);
48
VQRDMLADHX 1110 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 1 @2op
48
49
49
dinfo = drive_get(IF_PFLASH, 0, 1);
50
+VQDMLSDH 1111 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 0 @2op
50
- pflash_cfi01_register(SA_CS1, "collie.fl2", 0x02000000,
51
+VQDMLSDHX 1111 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 0 @2op
51
+ pflash_cfi01_register(SA_CS1, "collie.fl2", FLASH_SIZE,
52
+VQRDMLSDH 1111 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 1 @2op
52
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
53
+VQRDMLSDHX 1111 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 1 @2op
53
- 64 * KiB, 4, 0x00, 0x00, 0x00, 0x00, 0);
54
+
54
+ FLASH_SECTOR_SIZE, 4, 0x00, 0x00, 0x00, 0x00, 0);
55
# Vector miscellaneous
55
56
56
sysbus_create_simple("scoop", 0x40800000, NULL);
57
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
57
58
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
58
@@ -XXX,XX +XXX,XX @@ static void collie_machine_class_init(ObjectClass *oc, void *data)
59
index XXXXXXX..XXXXXXX 100644
59
mc->init = collie_init;
60
--- a/target/arm/mve_helper.c
60
mc->ignore_memory_transaction_failures = true;
61
+++ b/target/arm/mve_helper.c
61
mc->default_cpu_type = ARM_CPU_TYPE_NAME("sa1110");
62
@@ -XXX,XX +XXX,XX @@ static int32_t do_vqdmladh_w(int32_t a, int32_t b, int32_t c, int32_t d,
62
- mc->default_ram_size = 0x20000000;
63
return r >> 32;
63
+ mc->default_ram_size = RAM_SIZE;
64
mc->default_ram_id = "strongarm.sdram";
64
}
65
}
65
66
66
+static int8_t do_vqdmlsdh_b(int8_t a, int8_t b, int8_t c, int8_t d,
67
+ int round, bool *sat)
68
+{
69
+ int64_t r = ((int64_t)a * b - (int64_t)c * d) * 2 + (round << 7);
70
+ return do_sat_bhw(r, INT16_MIN, INT16_MAX, sat) >> 8;
71
+}
72
+
73
+static int16_t do_vqdmlsdh_h(int16_t a, int16_t b, int16_t c, int16_t d,
74
+ int round, bool *sat)
75
+{
76
+ int64_t r = ((int64_t)a * b - (int64_t)c * d) * 2 + (round << 15);
77
+ return do_sat_bhw(r, INT32_MIN, INT32_MAX, sat) >> 16;
78
+}
79
+
80
+static int32_t do_vqdmlsdh_w(int32_t a, int32_t b, int32_t c, int32_t d,
81
+ int round, bool *sat)
82
+{
83
+ int64_t m1 = (int64_t)a * b;
84
+ int64_t m2 = (int64_t)c * d;
85
+ int64_t r;
86
+ /* The same ordering issue as in do_vqdmladh_w applies here too */
87
+ if (ssub64_overflow(m1, m2, &r) ||
88
+ sadd64_overflow(r, (round << 30), &r) ||
89
+ sadd64_overflow(r, r, &r)) {
90
+ *sat = true;
91
+ return r < 0 ? INT32_MAX : INT32_MIN;
92
+ }
93
+ return r >> 32;
94
+}
95
+
96
DO_VQDMLADH_OP(vqdmladhb, 1, int8_t, 0, 0, do_vqdmladh_b)
97
DO_VQDMLADH_OP(vqdmladhh, 2, int16_t, 0, 0, do_vqdmladh_h)
98
DO_VQDMLADH_OP(vqdmladhw, 4, int32_t, 0, 0, do_vqdmladh_w)
99
@@ -XXX,XX +XXX,XX @@ DO_VQDMLADH_OP(vqrdmladhxb, 1, int8_t, 1, 1, do_vqdmladh_b)
100
DO_VQDMLADH_OP(vqrdmladhxh, 2, int16_t, 1, 1, do_vqdmladh_h)
101
DO_VQDMLADH_OP(vqrdmladhxw, 4, int32_t, 1, 1, do_vqdmladh_w)
102
103
+DO_VQDMLADH_OP(vqdmlsdhb, 1, int8_t, 0, 0, do_vqdmlsdh_b)
104
+DO_VQDMLADH_OP(vqdmlsdhh, 2, int16_t, 0, 0, do_vqdmlsdh_h)
105
+DO_VQDMLADH_OP(vqdmlsdhw, 4, int32_t, 0, 0, do_vqdmlsdh_w)
106
+DO_VQDMLADH_OP(vqdmlsdhxb, 1, int8_t, 1, 0, do_vqdmlsdh_b)
107
+DO_VQDMLADH_OP(vqdmlsdhxh, 2, int16_t, 1, 0, do_vqdmlsdh_h)
108
+DO_VQDMLADH_OP(vqdmlsdhxw, 4, int32_t, 1, 0, do_vqdmlsdh_w)
109
+
110
+DO_VQDMLADH_OP(vqrdmlsdhb, 1, int8_t, 0, 1, do_vqdmlsdh_b)
111
+DO_VQDMLADH_OP(vqrdmlsdhh, 2, int16_t, 0, 1, do_vqdmlsdh_h)
112
+DO_VQDMLADH_OP(vqrdmlsdhw, 4, int32_t, 0, 1, do_vqdmlsdh_w)
113
+DO_VQDMLADH_OP(vqrdmlsdhxb, 1, int8_t, 1, 1, do_vqdmlsdh_b)
114
+DO_VQDMLADH_OP(vqrdmlsdhxh, 2, int16_t, 1, 1, do_vqdmlsdh_h)
115
+DO_VQDMLADH_OP(vqrdmlsdhxw, 4, int32_t, 1, 1, do_vqdmlsdh_w)
116
+
117
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
118
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
119
uint32_t rm) \
120
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
121
index XXXXXXX..XXXXXXX 100644
122
--- a/target/arm/translate-mve.c
123
+++ b/target/arm/translate-mve.c
124
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQDMLADH, vqdmladh)
125
DO_2OP(VQDMLADHX, vqdmladhx)
126
DO_2OP(VQRDMLADH, vqrdmladh)
127
DO_2OP(VQRDMLADHX, vqrdmladhx)
128
+DO_2OP(VQDMLSDH, vqdmlsdh)
129
+DO_2OP(VQDMLSDHX, vqdmlsdhx)
130
+DO_2OP(VQRDMLSDH, vqrdmlsdh)
131
+DO_2OP(VQRDMLSDHX, vqrdmlsdhx)
132
133
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
134
MVEGenTwoOpScalarFn fn)
135
--
67
--
136
2.20.1
68
2.34.1
137
69
138
70
diff view generated by jsdifflib
1
These days the Arm architecture has a wide range of fine-grained
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
optional extra architectural features. We implement quite a lot
3
of these but by no means all of them. Document what we do implement,
4
so that users can find out without having to dig through back-issues
5
of our Changelog on the wiki.
6
2
3
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20230109115316.2235-5-philmd@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
9
Message-id: 20210617140328.28622-1-peter.maydell@linaro.org
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
---
7
---
12
docs/system/arm/emulation.rst | 102 ++++++++++++++++++++++++++++++++++
8
hw/arm/collie.c | 17 +++++++----------
13
docs/system/target-arm.rst | 6 ++
9
1 file changed, 7 insertions(+), 10 deletions(-)
14
2 files changed, 108 insertions(+)
15
create mode 100644 docs/system/arm/emulation.rst
16
10
17
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
11
diff --git a/hw/arm/collie.c b/hw/arm/collie.c
18
new file mode 100644
19
index XXXXXXX..XXXXXXX
20
--- /dev/null
21
+++ b/docs/system/arm/emulation.rst
22
@@ -XXX,XX +XXX,XX @@
23
+A-profile CPU architecture support
24
+==================================
25
+
26
+QEMU's TCG emulation includes support for the Armv5, Armv6, Armv7 and
27
+Armv8 versions of the A-profile architecture. It also has support for
28
+the following architecture extensions:
29
+
30
+- FEAT_AA32BF16 (AArch32 BFloat16 instructions)
31
+- FEAT_AA32HPD (AArch32 hierarchical permission disables)
32
+- FEAT_AA32I8MM (AArch32 Int8 matrix multiplication instructions)
33
+- FEAT_AES (AESD and AESE instructions)
34
+- FEAT_BF16 (AArch64 BFloat16 instructions)
35
+- FEAT_BTI (Branch Target Identification)
36
+- FEAT_DIT (Data Independent Timing instructions)
37
+- FEAT_DPB (DC CVAP instruction)
38
+- FEAT_DotProd (Advanced SIMD dot product instructions)
39
+- FEAT_FCMA (Floating-point complex number instructions)
40
+- FEAT_FHM (Floating-point half-precision multiplication instructions)
41
+- FEAT_FP16 (Half-precision floating-point data processing)
42
+- FEAT_FRINTTS (Floating-point to integer instructions)
43
+- FEAT_FlagM (Flag manipulation instructions v2)
44
+- FEAT_FlagM2 (Enhancements to flag manipulation instructions)
45
+- FEAT_HPDS (Hierarchical permission disables)
46
+- FEAT_I8MM (AArch64 Int8 matrix multiplication instructions)
47
+- FEAT_JSCVT (JavaScript conversion instructions)
48
+- FEAT_LOR (Limited ordering regions)
49
+- FEAT_LRCPC (Load-acquire RCpc instructions)
50
+- FEAT_LRCPC2 (Load-acquire RCpc instructions v2)
51
+- FEAT_LSE (Large System Extensions)
52
+- FEAT_MTE (Memory Tagging Extension)
53
+- FEAT_MTE2 (Memory Tagging Extension)
54
+- FEAT_PAN (Privileged access never)
55
+- FEAT_PAN2 (AT S1E1R and AT S1E1W instruction variants affected by PSTATE.PAN)
56
+- FEAT_PAuth (Pointer authentication)
57
+- FEAT_PMULL (PMULL, PMULL2 instructions)
58
+- FEAT_PMUv3p1 (PMU Extensions v3.1)
59
+- FEAT_PMUv3p4 (PMU Extensions v3.4)
60
+- FEAT_RDM (Advanced SIMD rounding double multiply accumulate instructions)
61
+- FEAT_RNG (Random number generator)
62
+- FEAT_SB (Speculation Barrier)
63
+- FEAT_SEL2 (Secure EL2)
64
+- FEAT_SHA1 (SHA1 instructions)
65
+- FEAT_SHA256 (SHA256 instructions)
66
+- FEAT_SHA3 (Advanced SIMD SHA3 instructions)
67
+- FEAT_SHA512 (Advanced SIMD SHA512 instructions)
68
+- FEAT_SM3 (Advanced SIMD SM3 instructions)
69
+- FEAT_SM4 (Advanced SIMD SM4 instructions)
70
+- FEAT_SPECRES (Speculation restriction instructions)
71
+- FEAT_SSBS (Speculative Store Bypass Safe)
72
+- FEAT_TLBIOS (TLB invalidate instructions in Outer Shareable domain)
73
+- FEAT_TLBIRANGE (TLB invalidate range instructions)
74
+- FEAT_TTCNP (Translation table Common not private translations)
75
+- FEAT_TTST (Small translation tables)
76
+- FEAT_UAO (Unprivileged Access Override control)
77
+- FEAT_VHE (Virtualization Host Extensions)
78
+- FEAT_VMID16 (16-bit VMID)
79
+- FEAT_XNX (Translation table stage 2 Unprivileged Execute-never)
80
+- SVE (The Scalable Vector Extension)
81
+- SVE2 (The Scalable Vector Extension v2)
82
+
83
+For information on the specifics of these extensions, please refer
84
+to the `Armv8-A Arm Architecture Reference Manual
85
+<https://developer.arm.com/documentation/ddi0487/latest>`_.
86
+
87
+When a specific named CPU is being emulated, only those features which
88
+are present in hardware for that CPU are emulated. (If a feature is
89
+not in the list above then it is not supported, even if the real
90
+hardware should have it.) The ``max`` CPU enables all features.
91
+
92
+R-profile CPU architecture support
93
+==================================
94
+
95
+QEMU's TCG emulation support for R-profile CPUs is currently limited.
96
+We emulate only the Cortex-R5 and Cortex-R5F CPUs.
97
+
98
+M-profile CPU architecture support
99
+==================================
100
+
101
+QEMU's TCG emulation includes support for Armv6-M, Armv7-M, Armv8-M, and
102
+Armv8.1-M versions of the M-profile architucture. It also has support
103
+for the following architecture extensions:
104
+
105
+- FP (Floating-point Extension)
106
+- FPCXT (FPCXT access instructions)
107
+- HP (Half-precision floating-point instructions)
108
+- LOB (Low Overhead loops and Branch future)
109
+- M (Main Extension)
110
+- MPU (Memory Protection Unit Extension)
111
+- PXN (Privileged Execute Never)
112
+- RAS (Reliability, Serviceability and Availability): "minimum RAS Extension" only
113
+- S (Security Extension)
114
+- ST (System Timer Extension)
115
+
116
+For information on the specifics of these extensions, please refer
117
+to the `Armv8-M Arm Architecture Reference Manual
118
+<https://developer.arm.com/documentation/ddi0553/latest>`_.
119
+
120
+When a specific named CPU is being emulated, only those features which
121
+are present in hardware for that CPU are emulated. (If a feature is
122
+not in the list above then it is not supported, even if the real
123
+hardware should have it.) There is no equivalent of the ``max`` CPU for
124
+M-profile.
125
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
126
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
127
--- a/docs/system/target-arm.rst
13
--- a/hw/arm/collie.c
128
+++ b/docs/system/target-arm.rst
14
+++ b/hw/arm/collie.c
129
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
15
@@ -XXX,XX +XXX,XX @@ static struct arm_boot_info collie_binfo = {
130
arm/virt
16
131
arm/xlnx-versal-virt
17
static void collie_init(MachineState *machine)
132
18
{
133
+Emulated CPU architecture support
19
- DriveInfo *dinfo;
134
+=================================
20
MachineClass *mc = MACHINE_GET_CLASS(machine);
135
+
21
CollieMachineState *cms = COLLIE_MACHINE(machine);
136
+.. toctree::
22
137
+ arm/emulation
23
@@ -XXX,XX +XXX,XX @@ static void collie_init(MachineState *machine)
138
+
24
139
Arm CPU features
25
memory_region_add_subregion(get_system_memory(), SA_SDCS0, machine->ram);
140
================
26
27
- dinfo = drive_get(IF_PFLASH, 0, 0);
28
- pflash_cfi01_register(SA_CS0, "collie.fl1", FLASH_SIZE,
29
- dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
30
- FLASH_SECTOR_SIZE, 4, 0x00, 0x00, 0x00, 0x00, 0);
31
-
32
- dinfo = drive_get(IF_PFLASH, 0, 1);
33
- pflash_cfi01_register(SA_CS1, "collie.fl2", FLASH_SIZE,
34
- dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
35
- FLASH_SECTOR_SIZE, 4, 0x00, 0x00, 0x00, 0x00, 0);
36
+ for (unsigned i = 0; i < 2; i++) {
37
+ DriveInfo *dinfo = drive_get(IF_PFLASH, 0, i);
38
+ pflash_cfi01_register(i ? SA_CS1 : SA_CS0,
39
+ i ? "collie.fl2" : "collie.fl1", FLASH_SIZE,
40
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
41
+ FLASH_SECTOR_SIZE, 4, 0x00, 0x00, 0x00, 0x00, 0);
42
+ }
43
44
sysbus_create_simple("scoop", 0x40800000, NULL);
141
45
142
--
46
--
143
2.20.1
47
2.34.1
144
48
145
49
diff view generated by jsdifflib
1
Implement the MVE VCLS insn.
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
2
3
Add a comment describing the Connex uses a Numonyx RC28F128J3F75
4
flash, and the Verdex uses a Micron RC28F256P30TFA.
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>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-5-peter.maydell@linaro.org
6
---
13
---
7
target/arm/helper-mve.h | 4 ++++
14
hw/arm/gumstix.c | 6 ++++--
8
target/arm/mve.decode | 1 +
15
1 file changed, 4 insertions(+), 2 deletions(-)
9
target/arm/mve_helper.c | 7 +++++++
10
target/arm/translate-mve.c | 1 +
11
4 files changed, 13 insertions(+)
12
16
13
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
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
19
--- a/hw/arm/gumstix.c
16
+++ b/target/arm/helper-mve.h
20
+++ b/hw/arm/gumstix.c
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vstrb_h, TCG_CALL_NO_WG, void, env, ptr, i32)
21
@@ -XXX,XX +XXX,XX @@
18
DEF_HELPER_FLAGS_3(mve_vstrb_w, TCG_CALL_NO_WG, void, env, ptr, i32)
22
* Contributions after 2012-01-13 are licensed under the terms of the
19
DEF_HELPER_FLAGS_3(mve_vstrh_w, TCG_CALL_NO_WG, void, env, ptr, i32)
23
* GNU GPL, version 2 or (at your option) any later version.
20
24
*/
21
+DEF_HELPER_FLAGS_3(mve_vclsb, TCG_CALL_NO_WG, void, env, ptr, ptr)
25
-
22
+DEF_HELPER_FLAGS_3(mve_vclsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
23
+DEF_HELPER_FLAGS_3(mve_vclsw, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
+
26
+
25
DEF_HELPER_FLAGS_3(mve_vclzb, TCG_CALL_NO_WG, void, env, ptr, ptr)
27
/*
26
DEF_HELPER_FLAGS_3(mve_vclzh, TCG_CALL_NO_WG, void, env, ptr, ptr)
28
* Example usage:
27
DEF_HELPER_FLAGS_3(mve_vclzw, TCG_CALL_NO_WG, void, env, ptr, ptr)
29
*
28
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
30
@@ -XXX,XX +XXX,XX @@ static void connex_init(MachineState *machine)
29
index XXXXXXX..XXXXXXX 100644
31
exit(1);
30
--- a/target/arm/mve.decode
31
+++ b/target/arm/mve.decode
32
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111110 ....... @vldr_vstr \
33
34
# Vector miscellaneous
35
36
+VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
37
VCLZ 1111 1111 1 . 11 .. 00 ... 0 0100 11 . 0 ... 0 @1op
38
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/mve_helper.c
41
+++ b/target/arm/mve_helper.c
42
@@ -XXX,XX +XXX,XX @@ static void mergemask_sq(int64_t *d, int64_t r, uint16_t mask)
43
mve_advance_vpt(env); \
44
}
32
}
45
33
46
+#define DO_CLS_B(N) (clrsb32(N) - 24)
34
+ /* Numonyx RC28F128J3F75 */
47
+#define DO_CLS_H(N) (clrsb32(N) - 16)
35
if (!pflash_cfi01_register(0x00000000, "connext.rom", connex_rom,
48
+
36
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
49
+DO_1OP(vclsb, 1, int8_t, DO_CLS_B)
37
sector_len, 2, 0, 0, 0, 0, 0)) {
50
+DO_1OP(vclsh, 2, int16_t, DO_CLS_H)
38
@@ -XXX,XX +XXX,XX @@ static void verdex_init(MachineState *machine)
51
+DO_1OP(vclsw, 4, int32_t, clrsb32)
39
exit(1);
52
+
53
#define DO_CLZ_B(N) (clz32(N) - 24)
54
#define DO_CLZ_H(N) (clz32(N) - 16)
55
56
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/translate-mve.c
59
+++ b/target/arm/translate-mve.c
60
@@ -XXX,XX +XXX,XX @@ static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
61
}
40
}
62
41
63
DO_1OP(VCLZ, vclz)
42
+ /* Micron RC28F256P30TFA */
64
+DO_1OP(VCLS, vcls)
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");
65
--
55
--
66
2.20.1
56
2.34.1
67
57
68
58
diff view generated by jsdifflib
1
Implement the MVE VQSHL insn (encoding T4, which is the
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
2
vector-shift-by-vector version).
3
2
4
The DO_SQSHL_OP and DO_UQSHL_OP macros here are derived from
3
IEC binary prefixes ease code review: the unit is explicit.
5
the neon_helper.c code for qshl_u{8,16,32} and qshl_s{8,16,32}.
6
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>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210617121628.20116-33-peter.maydell@linaro.org
10
---
12
---
11
target/arm/helper-mve.h | 8 ++++++++
13
hw/arm/gumstix.c | 27 ++++++++++++++-------------
12
target/arm/mve.decode | 12 ++++++++++++
14
1 file changed, 14 insertions(+), 13 deletions(-)
13
target/arm/mve_helper.c | 34 ++++++++++++++++++++++++++++++++++
14
target/arm/translate-mve.c | 2 ++
15
4 files changed, 56 insertions(+)
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_vqsubub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
@@ -XXX,XX +XXX,XX @@
22
DEF_HELPER_FLAGS_4(mve_vqsubuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
*/
23
DEF_HELPER_FLAGS_4(mve_vqsubuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
24
23
#include "qemu/osdep.h"
25
+DEF_HELPER_FLAGS_4(mve_vqshlsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+#include "qemu/units.h"
26
+DEF_HELPER_FLAGS_4(mve_vqshlsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
#include "qemu/error-report.h"
27
+DEF_HELPER_FLAGS_4(mve_vqshlsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
#include "hw/arm/pxa.h"
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)
28
+
35
+
29
+DEF_HELPER_FLAGS_4(mve_vqshlub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
+#define VERDEX_FLASH_SIZE (32 * MiB)
30
+DEF_HELPER_FLAGS_4(mve_vqshluh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
37
+#define VERDEX_RAM_SIZE (256 * MiB)
31
+DEF_HELPER_FLAGS_4(mve_vqshluw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
+
38
+
33
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
39
+#define FLASH_SECTOR_SIZE (128 * KiB)
34
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
40
35
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
41
static void connex_init(MachineState *machine)
36
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
42
{
37
index XXXXXXX..XXXXXXX 100644
43
PXA2xxState *cpu;
38
--- a/target/arm/mve.decode
44
DriveInfo *dinfo;
39
+++ b/target/arm/mve.decode
45
40
@@ -XXX,XX +XXX,XX @@
46
- uint32_t connex_rom = 0x01000000;
41
@2op .... .... .. size:2 .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn
47
- uint32_t connex_ram = 0x04000000;
42
@2op_nosz .... .... .... .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn size=0
48
-
43
49
- cpu = pxa255_init(connex_ram);
44
+# The _rev suffix indicates that Vn and Vm are reversed. This is
50
+ cpu = pxa255_init(CONNEX_RAM_SIZE);
45
+# the case for shifts. In the Arm ARM these insns are documented
51
46
+# with the Vm and Vn fields in their usual places, but in the
52
dinfo = drive_get(IF_PFLASH, 0, 0);
47
+# assembly the operands are listed "backwards", ie in the order
53
if (!dinfo && !qtest_enabled()) {
48
+# Qd, Qm, Qn where other insns use Qd, Qn, Qm. For QEMU we choose
54
@@ -XXX,XX +XXX,XX @@ static void connex_init(MachineState *machine)
49
+# to consider Vm and Vn as being in different fields in the insn.
50
+# This gives us consistency with A64 and Neon.
51
+@2op_rev .... .... .. size:2 .... .... .... .... .... &2op qd=%qd qm=%qn qn=%qm
52
+
53
@2scalar .... .... .. size:2 .... .... .... .... rm:4 &2scalar qd=%qd qn=%qn
54
@2scalar_nosz .... .... .... .... .... .... .... rm:4 &2scalar qd=%qd qn=%qn
55
56
@@ -XXX,XX +XXX,XX @@ VQADD_U 111 1 1111 0 . .. ... 0 ... 0 0000 . 1 . 1 ... 0 @2op
57
VQSUB_S 111 0 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
58
VQSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
59
60
+VQSHL_S 111 0 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
61
+VQSHL_U 111 1 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
62
+
63
# Vector miscellaneous
64
65
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
66
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/mve_helper.c
69
+++ b/target/arm/mve_helper.c
70
@@ -XXX,XX +XXX,XX @@ DO_1OP(vfnegs, 8, uint64_t, DO_FNEGS)
71
mve_advance_vpt(env); \
72
}
55
}
73
56
74
+/* provide unsigned 2-op helpers for all sizes */
57
/* Numonyx RC28F128J3F75 */
75
+#define DO_2OP_SAT_U(OP, FN) \
58
- if (!pflash_cfi01_register(0x00000000, "connext.rom", connex_rom,
76
+ DO_2OP_SAT(OP##b, 1, uint8_t, FN) \
59
+ if (!pflash_cfi01_register(0x00000000, "connext.rom", CONNEX_FLASH_SIZE,
77
+ DO_2OP_SAT(OP##h, 2, uint16_t, FN) \
60
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
78
+ DO_2OP_SAT(OP##w, 4, uint32_t, FN)
61
- sector_len, 2, 0, 0, 0, 0, 0)) {
79
+
62
+ FLASH_SECTOR_SIZE, 2, 0, 0, 0, 0, 0)) {
80
+/* provide signed 2-op helpers for all sizes */
63
error_report("Error registering flash memory");
81
+#define DO_2OP_SAT_S(OP, FN) \
64
exit(1);
82
+ DO_2OP_SAT(OP##b, 1, int8_t, FN) \
65
}
83
+ DO_2OP_SAT(OP##h, 2, int16_t, FN) \
66
@@ -XXX,XX +XXX,XX @@ static void verdex_init(MachineState *machine)
84
+ DO_2OP_SAT(OP##w, 4, int32_t, FN)
67
PXA2xxState *cpu;
85
+
68
DriveInfo *dinfo;
86
#define DO_AND(N, M) ((N) & (M))
69
87
#define DO_BIC(N, M) ((N) & ~(M))
70
- uint32_t verdex_rom = 0x02000000;
88
#define DO_ORR(N, M) ((N) | (M))
71
- uint32_t verdex_ram = 0x10000000;
89
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT(vqsubsb, 1, int8_t, DO_SQSUB_B)
72
-
90
DO_2OP_SAT(vqsubsh, 2, int16_t, DO_SQSUB_H)
73
- cpu = pxa270_init(verdex_ram, machine->cpu_type);
91
DO_2OP_SAT(vqsubsw, 4, int32_t, DO_SQSUB_W)
74
+ cpu = pxa270_init(VERDEX_RAM_SIZE, machine->cpu_type);
92
75
93
+/*
76
dinfo = drive_get(IF_PFLASH, 0, 0);
94
+ * This wrapper fixes up the impedance mismatch between do_sqrshl_bhs()
77
if (!dinfo && !qtest_enabled()) {
95
+ * and friends wanting a uint32_t* sat and our needing a bool*.
78
@@ -XXX,XX +XXX,XX @@ static void verdex_init(MachineState *machine)
96
+ */
79
}
97
+#define WRAP_QRSHL_HELPER(FN, N, M, ROUND, satp) \
80
98
+ ({ \
81
/* Micron RC28F256P30TFA */
99
+ uint32_t su32 = 0; \
82
- if (!pflash_cfi01_register(0x00000000, "verdex.rom", verdex_rom,
100
+ typeof(N) r = FN(N, (int8_t)(M), sizeof(N) * 8, ROUND, &su32); \
83
+ if (!pflash_cfi01_register(0x00000000, "verdex.rom", VERDEX_FLASH_SIZE,
101
+ if (su32) { \
84
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
102
+ *satp = true; \
85
- sector_len, 2, 0, 0, 0, 0, 0)) {
103
+ } \
86
+ FLASH_SECTOR_SIZE, 2, 0, 0, 0, 0, 0)) {
104
+ r; \
87
error_report("Error registering flash memory");
105
+ })
88
exit(1);
106
+
89
}
107
+#define DO_SQSHL_OP(N, M, satp) \
108
+ WRAP_QRSHL_HELPER(do_sqrshl_bhs, N, M, false, satp)
109
+#define DO_UQSHL_OP(N, M, satp) \
110
+ WRAP_QRSHL_HELPER(do_uqrshl_bhs, N, M, false, satp)
111
+
112
+DO_2OP_SAT_S(vqshls, DO_SQSHL_OP)
113
+DO_2OP_SAT_U(vqshlu, DO_UQSHL_OP)
114
+
115
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
116
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
117
uint32_t rm) \
118
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
119
index XXXXXXX..XXXXXXX 100644
120
--- a/target/arm/translate-mve.c
121
+++ b/target/arm/translate-mve.c
122
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQADD_S, vqadds)
123
DO_2OP(VQADD_U, vqaddu)
124
DO_2OP(VQSUB_S, vqsubs)
125
DO_2OP(VQSUB_U, vqsubu)
126
+DO_2OP(VQSHL_S, vqshls)
127
+DO_2OP(VQSHL_U, vqshlu)
128
129
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
130
MVEGenTwoOpScalarFn fn)
131
--
90
--
132
2.20.1
91
2.34.1
133
92
134
93
diff view generated by jsdifflib
1
Implement the MVE VQDMLADH and VQRDMLADH insns. These multiply
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
elements, and then add pairs of products, double, possibly round,
3
saturate and return the high half of the result.
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-8-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
Message-id: 20210617121628.20116-37-peter.maydell@linaro.org
8
---
11
---
9
target/arm/helper-mve.h | 16 +++++++
12
hw/arm/mainstone.c | 18 ++++++++++--------
10
target/arm/mve.decode | 5 +++
13
1 file changed, 10 insertions(+), 8 deletions(-)
11
target/arm/mve_helper.c | 89 ++++++++++++++++++++++++++++++++++++++
12
target/arm/translate-mve.c | 4 ++
13
4 files changed, 114 insertions(+)
14
14
15
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
16
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper-mve.h
17
--- a/hw/arm/mainstone.c
18
+++ b/target/arm/helper-mve.h
18
+++ b/hw/arm/mainstone.c
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqrshlub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
@@ -XXX,XX +XXX,XX @@
20
DEF_HELPER_FLAGS_4(mve_vqrshluh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
* GNU GPL, version 2 or (at your option) any later version.
21
DEF_HELPER_FLAGS_4(mve_vqrshluw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
*/
22
22
#include "qemu/osdep.h"
23
+DEF_HELPER_FLAGS_4(mve_vqdmladhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
+#include "qemu/units.h"
24
+DEF_HELPER_FLAGS_4(mve_vqdmladhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
#include "qemu/error-report.h"
25
+DEF_HELPER_FLAGS_4(mve_vqdmladhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
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)
26
+
45
+
27
+DEF_HELPER_FLAGS_4(mve_vqdmladhxb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
46
static void mainstone_common_init(MachineState *machine,
28
+DEF_HELPER_FLAGS_4(mve_vqdmladhxh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
47
enum mainstone_model_e model, int arm_id)
29
+DEF_HELPER_FLAGS_4(mve_vqdmladhxw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
48
{
30
+
49
- uint32_t sector_len = 256 * 1024;
31
+DEF_HELPER_FLAGS_4(mve_vqrdmladhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
50
hwaddr mainstone_flash_base[] = { MST_FLASH_0, MST_FLASH_1 };
32
+DEF_HELPER_FLAGS_4(mve_vqrdmladhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
51
PXA2xxState *mpu;
33
+DEF_HELPER_FLAGS_4(mve_vqrdmladhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
52
DeviceState *mst_irq;
34
+
53
@@ -XXX,XX +XXX,XX @@ static void mainstone_common_init(MachineState *machine,
35
+DEF_HELPER_FLAGS_4(mve_vqrdmladhxb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
54
36
+DEF_HELPER_FLAGS_4(mve_vqrdmladhxh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
55
/* Setup CPU & memory */
37
+DEF_HELPER_FLAGS_4(mve_vqrdmladhxw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
56
mpu = pxa270_init(mainstone_binfo.ram_size, machine->cpu_type);
38
+
57
- memory_region_init_rom(rom, NULL, "mainstone.rom", MAINSTONE_ROM,
39
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
58
+ memory_region_init_rom(rom, NULL, "mainstone.rom", MAINSTONE_ROM_SIZE,
40
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
59
&error_fatal);
41
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
60
memory_region_add_subregion(get_system_memory(), 0x00000000, rom);
42
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
61
43
index XXXXXXX..XXXXXXX 100644
62
@@ -XXX,XX +XXX,XX @@ static void mainstone_common_init(MachineState *machine,
44
--- a/target/arm/mve.decode
63
dinfo = drive_get(IF_PFLASH, 0, i);
45
+++ b/target/arm/mve.decode
64
if (!pflash_cfi01_register(mainstone_flash_base[i],
46
@@ -XXX,XX +XXX,XX @@ VQSHL_U 111 1 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
65
i ? "mainstone.flash1" : "mainstone.flash0",
47
VQRSHL_S 111 0 1111 0 . .. ... 0 ... 0 0101 . 1 . 1 ... 0 @2op_rev
66
- MAINSTONE_FLASH,
48
VQRSHL_U 111 1 1111 0 . .. ... 0 ... 0 0101 . 1 . 1 ... 0 @2op_rev
67
+ MAINSTONE_FLASH_SIZE,
49
68
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
50
+VQDMLADH 1110 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 0 @2op
69
- sector_len, 4, 0, 0, 0, 0, 0)) {
51
+VQDMLADHX 1110 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 0 @2op
70
+ FLASH_SECTOR_SIZE, 4, 0, 0, 0, 0, 0)) {
52
+VQRDMLADH 1110 1110 0 . .. ... 0 ... 0 1110 . 0 . 0 ... 1 @2op
71
error_report("Error registering flash memory");
53
+VQRDMLADHX 1110 1110 0 . .. ... 0 ... 1 1110 . 0 . 0 ... 1 @2op
72
exit(1);
54
+
73
}
55
# Vector miscellaneous
56
57
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
58
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/mve_helper.c
61
+++ b/target/arm/mve_helper.c
62
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT_U(vqshlu, DO_UQSHL_OP)
63
DO_2OP_SAT_S(vqrshls, DO_SQRSHL_OP)
64
DO_2OP_SAT_U(vqrshlu, DO_UQRSHL_OP)
65
66
+/*
67
+ * Multiply add dual returning high half
68
+ * The 'FN' here takes four inputs A, B, C, D, a 0/1 indicator of
69
+ * whether to add the rounding constant, and the pointer to the
70
+ * saturation flag, and should do "(A * B + C * D) * 2 + rounding constant",
71
+ * saturate to twice the input size and return the high half; or
72
+ * (A * B - C * D) etc for VQDMLSDH.
73
+ */
74
+#define DO_VQDMLADH_OP(OP, ESIZE, TYPE, XCHG, ROUND, FN) \
75
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
76
+ void *vm) \
77
+ { \
78
+ TYPE *d = vd, *n = vn, *m = vm; \
79
+ uint16_t mask = mve_element_mask(env); \
80
+ unsigned e; \
81
+ bool qc = false; \
82
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
83
+ bool sat = false; \
84
+ if ((e & 1) == XCHG) { \
85
+ TYPE r = FN(n[H##ESIZE(e)], \
86
+ m[H##ESIZE(e - XCHG)], \
87
+ n[H##ESIZE(e + (1 - 2 * XCHG))], \
88
+ m[H##ESIZE(e + (1 - XCHG))], \
89
+ ROUND, &sat); \
90
+ mergemask(&d[H##ESIZE(e)], r, mask); \
91
+ qc |= sat & mask & 1; \
92
+ } \
93
+ } \
94
+ if (qc) { \
95
+ env->vfp.qc[0] = qc; \
96
+ } \
97
+ mve_advance_vpt(env); \
98
+ }
99
+
100
+static int8_t do_vqdmladh_b(int8_t a, int8_t b, int8_t c, int8_t d,
101
+ int round, bool *sat)
102
+{
103
+ int64_t r = ((int64_t)a * b + (int64_t)c * d) * 2 + (round << 7);
104
+ return do_sat_bhw(r, INT16_MIN, INT16_MAX, sat) >> 8;
105
+}
106
+
107
+static int16_t do_vqdmladh_h(int16_t a, int16_t b, int16_t c, int16_t d,
108
+ int round, bool *sat)
109
+{
110
+ int64_t r = ((int64_t)a * b + (int64_t)c * d) * 2 + (round << 15);
111
+ return do_sat_bhw(r, INT32_MIN, INT32_MAX, sat) >> 16;
112
+}
113
+
114
+static int32_t do_vqdmladh_w(int32_t a, int32_t b, int32_t c, int32_t d,
115
+ int round, bool *sat)
116
+{
117
+ int64_t m1 = (int64_t)a * b;
118
+ int64_t m2 = (int64_t)c * d;
119
+ int64_t r;
120
+ /*
121
+ * Architecturally we should do the entire add, double, round
122
+ * and then check for saturation. We do three saturating adds,
123
+ * but we need to be careful about the order. If the first
124
+ * m1 + m2 saturates then it's impossible for the *2+rc to
125
+ * bring it back into the non-saturated range. However, if
126
+ * m1 + m2 is negative then it's possible that doing the doubling
127
+ * would take the intermediate result below INT64_MAX and the
128
+ * addition of the rounding constant then brings it back in range.
129
+ * So we add half the rounding constant before doubling rather
130
+ * than adding the rounding constant after the doubling.
131
+ */
132
+ if (sadd64_overflow(m1, m2, &r) ||
133
+ sadd64_overflow(r, (round << 30), &r) ||
134
+ sadd64_overflow(r, r, &r)) {
135
+ *sat = true;
136
+ return r < 0 ? INT32_MAX : INT32_MIN;
137
+ }
138
+ return r >> 32;
139
+}
140
+
141
+DO_VQDMLADH_OP(vqdmladhb, 1, int8_t, 0, 0, do_vqdmladh_b)
142
+DO_VQDMLADH_OP(vqdmladhh, 2, int16_t, 0, 0, do_vqdmladh_h)
143
+DO_VQDMLADH_OP(vqdmladhw, 4, int32_t, 0, 0, do_vqdmladh_w)
144
+DO_VQDMLADH_OP(vqdmladhxb, 1, int8_t, 1, 0, do_vqdmladh_b)
145
+DO_VQDMLADH_OP(vqdmladhxh, 2, int16_t, 1, 0, do_vqdmladh_h)
146
+DO_VQDMLADH_OP(vqdmladhxw, 4, int32_t, 1, 0, do_vqdmladh_w)
147
+
148
+DO_VQDMLADH_OP(vqrdmladhb, 1, int8_t, 0, 1, do_vqdmladh_b)
149
+DO_VQDMLADH_OP(vqrdmladhh, 2, int16_t, 0, 1, do_vqdmladh_h)
150
+DO_VQDMLADH_OP(vqrdmladhw, 4, int32_t, 0, 1, do_vqdmladh_w)
151
+DO_VQDMLADH_OP(vqrdmladhxb, 1, int8_t, 1, 1, do_vqdmladh_b)
152
+DO_VQDMLADH_OP(vqrdmladhxh, 2, int16_t, 1, 1, do_vqdmladh_h)
153
+DO_VQDMLADH_OP(vqrdmladhxw, 4, int32_t, 1, 1, do_vqdmladh_w)
154
+
155
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
156
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
157
uint32_t rm) \
158
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
159
index XXXXXXX..XXXXXXX 100644
160
--- a/target/arm/translate-mve.c
161
+++ b/target/arm/translate-mve.c
162
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQSHL_S, vqshls)
163
DO_2OP(VQSHL_U, vqshlu)
164
DO_2OP(VQRSHL_S, vqrshls)
165
DO_2OP(VQRSHL_U, vqrshlu)
166
+DO_2OP(VQDMLADH, vqdmladh)
167
+DO_2OP(VQDMLADHX, vqdmladhx)
168
+DO_2OP(VQRDMLADH, vqrdmladh)
169
+DO_2OP(VQRDMLADHX, vqrdmladhx)
170
171
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
172
MVEGenTwoOpScalarFn fn)
173
--
74
--
174
2.20.1
75
2.34.1
175
76
176
77
diff view generated by jsdifflib
1
Implement the MVE VRMLALDAVH and VRMLSLDAVH insns, which accumulate
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
the results of a rounded multiply of pairs of elements into a 72-bit
3
accumulator, returning the top 64 bits in a pair of general purpose
4
registers.
5
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-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
Message-id: 20210617121628.20116-22-peter.maydell@linaro.org
9
---
11
---
10
target/arm/helper-mve.h | 8 ++++++++
12
hw/arm/musicpal.c | 9 ++++++---
11
target/arm/mve.decode | 7 +++++++
13
1 file changed, 6 insertions(+), 3 deletions(-)
12
target/arm/mve_helper.c | 37 +++++++++++++++++++++++++++++++++++++
13
target/arm/translate-mve.c | 24 ++++++++++++++++++++++++
14
4 files changed, 76 insertions(+)
15
14
16
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
15
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper-mve.h
17
--- a/hw/arm/musicpal.c
19
+++ b/target/arm/helper-mve.h
18
+++ b/hw/arm/musicpal.c
20
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmlsldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
21
DEF_HELPER_FLAGS_4(mve_vmlsldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
22
DEF_HELPER_FLAGS_4(mve_vmlsldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
23
DEF_HELPER_FLAGS_4(mve_vmlsldavxsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
24
+
25
+DEF_HELPER_FLAGS_4(mve_vrmlaldavhsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
26
+DEF_HELPER_FLAGS_4(mve_vrmlaldavhxsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
27
+
28
+DEF_HELPER_FLAGS_4(mve_vrmlaldavhuw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
29
+
30
+DEF_HELPER_FLAGS_4(mve_vrmlsldavhsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
31
+DEF_HELPER_FLAGS_4(mve_vrmlsldavhxsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
32
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/mve.decode
35
+++ b/target/arm/mve.decode
36
@@ -XXX,XX +XXX,XX @@ VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=2
37
38
@vmlaldav .... .... . ... ... . ... . .... .... qm:3 . \
39
qn=%qn rdahi=%rdahi rdalo=%rdalo size=%size_16 &vmlaldav
40
+@vmlaldav_nosz .... .... . ... ... . ... . .... .... qm:3 . \
41
+ qn=%qn rdahi=%rdahi rdalo=%rdalo size=0 &vmlaldav
42
VMLALDAV_S 1110 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 0 @vmlaldav
43
VMLALDAV_U 1111 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 0 @vmlaldav
44
45
VMLSLDAV 1110 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav
46
+
47
+VRMLALDAVH_S 1110 1110 1 ... ... 0 ... x:1 1111 . 0 a:1 0 ... 0 @vmlaldav_nosz
48
+VRMLALDAVH_U 1111 1110 1 ... ... 0 ... x:1 1111 . 0 a:1 0 ... 0 @vmlaldav_nosz
49
+
50
+VRMLSLDAVH 1111 1110 1 ... ... 0 ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav_nosz
51
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/mve_helper.c
54
+++ b/target/arm/mve_helper.c
55
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
56
*/
20
*/
57
21
58
#include "qemu/osdep.h"
22
#include "qemu/osdep.h"
59
+#include "qemu/int128.h"
23
+#include "qemu/units.h"
24
#include "qapi/error.h"
60
#include "cpu.h"
25
#include "cpu.h"
61
#include "internals.h"
26
#include "hw/sysbus.h"
62
#include "vec_internal.h"
27
@@ -XXX,XX +XXX,XX @@ static const TypeInfo musicpal_key_info = {
63
@@ -XXX,XX +XXX,XX @@ DO_LDAV(vmlsldavsh, 2, int16_t, false, +=, -=)
28
.class_init = musicpal_key_class_init,
64
DO_LDAV(vmlsldavxsh, 2, int16_t, true, +=, -=)
29
};
65
DO_LDAV(vmlsldavsw, 4, int32_t, false, +=, -=)
30
66
DO_LDAV(vmlsldavxsw, 4, int32_t, true, +=, -=)
31
+#define FLASH_SECTOR_SIZE (64 * KiB)
67
+
32
+
68
+/*
33
static struct arm_boot_info musicpal_binfo = {
69
+ * Rounding multiply add long dual accumulate high: we must keep
34
.loader_start = 0x0,
70
+ * a 72-bit internal accumulator value and return the top 64 bits.
35
.board_id = 0x20e,
71
+ */
36
@@ -XXX,XX +XXX,XX @@ static void musicpal_init(MachineState *machine)
72
+#define DO_LDAVH(OP, ESIZE, TYPE, XCHG, EVENACC, ODDACC, TO128) \
37
BlockBackend *blk = blk_by_legacy_dinfo(dinfo);
73
+ uint64_t HELPER(glue(mve_, OP))(CPUARMState *env, void *vn, \
38
74
+ void *vm, uint64_t a) \
39
flash_size = blk_getlength(blk);
75
+ { \
40
- if (flash_size != 8*1024*1024 && flash_size != 16*1024*1024 &&
76
+ uint16_t mask = mve_element_mask(env); \
41
- flash_size != 32*1024*1024) {
77
+ unsigned e; \
42
+ if (flash_size != 8 * MiB && flash_size != 16 * MiB &&
78
+ TYPE *n = vn, *m = vm; \
43
+ flash_size != 32 * MiB) {
79
+ Int128 acc = int128_lshift(TO128(a), 8); \
44
error_report("Invalid flash image size");
80
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
45
exit(1);
81
+ if (mask & 1) { \
46
}
82
+ if (e & 1) { \
47
@@ -XXX,XX +XXX,XX @@ static void musicpal_init(MachineState *machine)
83
+ acc = ODDACC(acc, TO128(n[H##ESIZE(e - 1 * XCHG)] * \
48
*/
84
+ m[H##ESIZE(e)])); \
49
pflash_cfi02_register(0x100000000ULL - MP_FLASH_SIZE_MAX,
85
+ } else { \
50
"musicpal.flash", flash_size,
86
+ acc = EVENACC(acc, TO128(n[H##ESIZE(e + 1 * XCHG)] * \
51
- blk, 0x10000,
87
+ m[H##ESIZE(e)])); \
52
+ blk, FLASH_SECTOR_SIZE,
88
+ } \
53
MP_FLASH_SIZE_MAX / flash_size,
89
+ acc = int128_add(acc, 1 << 7); \
54
2, 0x00BF, 0x236D, 0x0000, 0x0000,
90
+ } \
55
0x5555, 0x2AAA, 0);
91
+ } \
92
+ mve_advance_vpt(env); \
93
+ return int128_getlo(int128_rshift(acc, 8)); \
94
+ }
95
+
96
+DO_LDAVH(vrmlaldavhsw, 4, int32_t, false, int128_add, int128_add, int128_makes64)
97
+DO_LDAVH(vrmlaldavhxsw, 4, int32_t, true, int128_add, int128_add, int128_makes64)
98
+
99
+DO_LDAVH(vrmlaldavhuw, 4, uint32_t, false, int128_add, int128_add, int128_make64)
100
+
101
+DO_LDAVH(vrmlsldavhsw, 4, int32_t, false, int128_add, int128_sub, int128_makes64)
102
+DO_LDAVH(vrmlsldavhxsw, 4, int32_t, true, int128_add, int128_sub, int128_makes64)
103
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
104
index XXXXXXX..XXXXXXX 100644
105
--- a/target/arm/translate-mve.c
106
+++ b/target/arm/translate-mve.c
107
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLSLDAV(DisasContext *s, arg_vmlaldav *a)
108
};
109
return do_long_dual_acc(s, a, fns[a->size][a->x]);
110
}
111
+
112
+static bool trans_VRMLALDAVH_S(DisasContext *s, arg_vmlaldav *a)
113
+{
114
+ static MVEGenDualAccOpFn * const fns[] = {
115
+ gen_helper_mve_vrmlaldavhsw, gen_helper_mve_vrmlaldavhxsw,
116
+ };
117
+ return do_long_dual_acc(s, a, fns[a->x]);
118
+}
119
+
120
+static bool trans_VRMLALDAVH_U(DisasContext *s, arg_vmlaldav *a)
121
+{
122
+ static MVEGenDualAccOpFn * const fns[] = {
123
+ gen_helper_mve_vrmlaldavhuw, NULL,
124
+ };
125
+ return do_long_dual_acc(s, a, fns[a->x]);
126
+}
127
+
128
+static bool trans_VRMLSLDAVH(DisasContext *s, arg_vmlaldav *a)
129
+{
130
+ static MVEGenDualAccOpFn * const fns[] = {
131
+ gen_helper_mve_vrmlsldavhsw, gen_helper_mve_vrmlsldavhxsw,
132
+ };
133
+ return do_long_dual_acc(s, a, fns[a->x]);
134
+}
135
--
56
--
136
2.20.1
57
2.34.1
137
58
138
59
diff view generated by jsdifflib
1
Implement the MVE VRSHL insn (vector form).
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
The total_ram_v1/total_ram_v2 definitions were never used.
4
5
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20230109115316.2235-10-philmd@linaro.org
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-36-peter.maydell@linaro.org
6
---
9
---
7
target/arm/helper-mve.h | 8 ++++++++
10
hw/arm/omap_sx1.c | 2 --
8
target/arm/mve.decode | 3 +++
11
1 file changed, 2 deletions(-)
9
target/arm/mve_helper.c | 4 ++++
10
target/arm/translate-mve.c | 2 ++
11
4 files changed, 17 insertions(+)
12
12
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
13
diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
15
--- a/hw/arm/omap_sx1.c
16
+++ b/target/arm/helper-mve.h
16
+++ b/hw/arm/omap_sx1.c
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vshlub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
17
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps static_ops = {
18
DEF_HELPER_FLAGS_4(mve_vshluh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
18
#define flash0_size    (16 * 1024 * 1024)
19
DEF_HELPER_FLAGS_4(mve_vshluw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
#define flash1_size    ( 8 * 1024 * 1024)
20
20
#define flash2_size    (32 * 1024 * 1024)
21
+DEF_HELPER_FLAGS_4(mve_vrshlsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
-#define total_ram_v1    (sdram_size + flash0_size + flash1_size + OMAP15XX_SRAM_SIZE)
22
+DEF_HELPER_FLAGS_4(mve_vrshlsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
-#define total_ram_v2    (sdram_size + flash2_size + OMAP15XX_SRAM_SIZE)
23
+DEF_HELPER_FLAGS_4(mve_vrshlsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
24
+
24
static struct arm_boot_info sx1_binfo = {
25
+DEF_HELPER_FLAGS_4(mve_vrshlub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
.loader_start = OMAP_EMIFF_BASE,
26
+DEF_HELPER_FLAGS_4(mve_vrshluh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_vrshluw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+
29
DEF_HELPER_FLAGS_4(mve_vqshlsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
DEF_HELPER_FLAGS_4(mve_vqshlsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
DEF_HELPER_FLAGS_4(mve_vqshlsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/mve.decode
35
+++ b/target/arm/mve.decode
36
@@ -XXX,XX +XXX,XX @@ VQSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
37
VSHL_S 111 0 1111 0 . .. ... 0 ... 0 0100 . 1 . 0 ... 0 @2op_rev
38
VSHL_U 111 1 1111 0 . .. ... 0 ... 0 0100 . 1 . 0 ... 0 @2op_rev
39
40
+VRSHL_S 111 0 1111 0 . .. ... 0 ... 0 0101 . 1 . 0 ... 0 @2op_rev
41
+VRSHL_U 111 1 1111 0 . .. ... 0 ... 0 0101 . 1 . 0 ... 0 @2op_rev
42
+
43
VQSHL_S 111 0 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
44
VQSHL_U 111 1 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
45
46
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/mve_helper.c
49
+++ b/target/arm/mve_helper.c
50
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vhsubu, do_vhsub_u)
51
52
#define DO_VSHLS(N, M) do_sqrshl_bhs(N, (int8_t)(M), sizeof(N) * 8, false, NULL)
53
#define DO_VSHLU(N, M) do_uqrshl_bhs(N, (int8_t)(M), sizeof(N) * 8, false, NULL)
54
+#define DO_VRSHLS(N, M) do_sqrshl_bhs(N, (int8_t)(M), sizeof(N) * 8, true, NULL)
55
+#define DO_VRSHLU(N, M) do_uqrshl_bhs(N, (int8_t)(M), sizeof(N) * 8, true, NULL)
56
57
DO_2OP_S(vshls, DO_VSHLS)
58
DO_2OP_U(vshlu, DO_VSHLU)
59
+DO_2OP_S(vrshls, DO_VRSHLS)
60
+DO_2OP_U(vrshlu, DO_VRSHLU)
61
62
static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
63
{
64
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
65
index XXXXXXX..XXXXXXX 100644
66
--- a/target/arm/translate-mve.c
67
+++ b/target/arm/translate-mve.c
68
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQSUB_S, vqsubs)
69
DO_2OP(VQSUB_U, vqsubu)
70
DO_2OP(VSHL_S, vshls)
71
DO_2OP(VSHL_U, vshlu)
72
+DO_2OP(VRSHL_S, vrshls)
73
+DO_2OP(VRSHL_U, vrshlu)
74
DO_2OP(VQSHL_S, vqshls)
75
DO_2OP(VQSHL_U, vqshlu)
76
DO_2OP(VQRSHL_S, vqrshls)
77
--
26
--
78
2.20.1
27
2.34.1
79
28
80
29
diff view generated by jsdifflib
1
The Arm MVE VDUP implementation would like to be able to emit code to
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
duplicate a byte or halfword value into an i32. We have code to do
3
this already in tcg-op-gvec.c, so all we need to do is make the
4
functions global.
5
2
6
For consistency with other functions made available to the frontends:
3
IEC binary prefixes ease code review: the unit is explicit.
7
* we rename to tcg_gen_dup_*
8
* we expose both the _i32 and _i64 forms
9
* we provide the #define for a _tl form
10
4
11
Suggested-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20230109115316.2235-11-philmd@linaro.org
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20210617121628.20116-10-peter.maydell@linaro.org
15
---
9
---
16
include/tcg/tcg-op.h | 8 ++++++++
10
hw/arm/omap_sx1.c | 33 +++++++++++++++++----------------
17
include/tcg/tcg.h | 1 -
11
1 file changed, 17 insertions(+), 16 deletions(-)
18
tcg/tcg-op-gvec.c | 20 ++++++++++----------
19
3 files changed, 18 insertions(+), 11 deletions(-)
20
12
21
diff --git a/include/tcg/tcg-op.h b/include/tcg/tcg-op.h
13
diff --git a/hw/arm/omap_sx1.c b/hw/arm/omap_sx1.c
22
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
23
--- a/include/tcg/tcg-op.h
15
--- a/hw/arm/omap_sx1.c
24
+++ b/include/tcg/tcg-op.h
16
+++ b/hw/arm/omap_sx1.c
25
@@ -XXX,XX +XXX,XX @@ void tcg_gen_umin_i32(TCGv_i32, TCGv_i32 arg1, TCGv_i32 arg2);
17
@@ -XXX,XX +XXX,XX @@
26
void tcg_gen_umax_i32(TCGv_i32, TCGv_i32 arg1, TCGv_i32 arg2);
18
* with this program; if not, see <http://www.gnu.org/licenses/>.
27
void tcg_gen_abs_i32(TCGv_i32, TCGv_i32);
28
29
+/* Replicate a value of size @vece from @in to all the lanes in @out */
30
+void tcg_gen_dup_i32(unsigned vece, TCGv_i32 out, TCGv_i32 in);
31
+
32
static inline void tcg_gen_discard_i32(TCGv_i32 arg)
33
{
34
tcg_gen_op1_i32(INDEX_op_discard, arg);
35
@@ -XXX,XX +XXX,XX @@ void tcg_gen_umin_i64(TCGv_i64, TCGv_i64 arg1, TCGv_i64 arg2);
36
void tcg_gen_umax_i64(TCGv_i64, TCGv_i64 arg1, TCGv_i64 arg2);
37
void tcg_gen_abs_i64(TCGv_i64, TCGv_i64);
38
39
+/* Replicate a value of size @vece from @in to all the lanes in @out */
40
+void tcg_gen_dup_i64(unsigned vece, TCGv_i64 out, TCGv_i64 in);
41
+
42
#if TCG_TARGET_REG_BITS == 64
43
static inline void tcg_gen_discard_i64(TCGv_i64 arg)
44
{
45
@@ -XXX,XX +XXX,XX @@ void tcg_gen_stl_vec(TCGv_vec r, TCGv_ptr base, TCGArg offset, TCGType t);
46
#define tcg_gen_atomic_smax_fetch_tl tcg_gen_atomic_smax_fetch_i64
47
#define tcg_gen_atomic_umax_fetch_tl tcg_gen_atomic_umax_fetch_i64
48
#define tcg_gen_dup_tl_vec tcg_gen_dup_i64_vec
49
+#define tcg_gen_dup_tl tcg_gen_dup_i64
50
#else
51
#define tcg_gen_movi_tl tcg_gen_movi_i32
52
#define tcg_gen_mov_tl tcg_gen_mov_i32
53
@@ -XXX,XX +XXX,XX @@ void tcg_gen_stl_vec(TCGv_vec r, TCGv_ptr base, TCGArg offset, TCGType t);
54
#define tcg_gen_atomic_smax_fetch_tl tcg_gen_atomic_smax_fetch_i32
55
#define tcg_gen_atomic_umax_fetch_tl tcg_gen_atomic_umax_fetch_i32
56
#define tcg_gen_dup_tl_vec tcg_gen_dup_i32_vec
57
+#define tcg_gen_dup_tl tcg_gen_dup_i32
58
#endif
59
60
#if UINTPTR_MAX == UINT32_MAX
61
diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
62
index XXXXXXX..XXXXXXX 100644
63
--- a/include/tcg/tcg.h
64
+++ b/include/tcg/tcg.h
65
@@ -XXX,XX +XXX,XX @@ uint64_t dup_const(unsigned vece, uint64_t c);
66
: (qemu_build_not_reached_always(), 0)) \
67
: dup_const(VECE, C))
68
69
-
70
/*
71
* Memory helpers that will be used by TCG generated code.
72
*/
19
*/
73
diff --git a/tcg/tcg-op-gvec.c b/tcg/tcg-op-gvec.c
20
#include "qemu/osdep.h"
74
index XXXXXXX..XXXXXXX 100644
21
+#include "qemu/units.h"
75
--- a/tcg/tcg-op-gvec.c
22
#include "qapi/error.h"
76
+++ b/tcg/tcg-op-gvec.c
23
#include "ui/console.h"
77
@@ -XXX,XX +XXX,XX @@ uint64_t (dup_const)(unsigned vece, uint64_t c)
24
#include "hw/arm/omap.h"
25
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps static_ops = {
26
.endianness = DEVICE_NATIVE_ENDIAN,
27
};
28
29
-#define sdram_size    0x02000000
30
-#define sector_size    (128 * 1024)
31
-#define flash0_size    (16 * 1024 * 1024)
32
-#define flash1_size    ( 8 * 1024 * 1024)
33
-#define flash2_size    (32 * 1024 * 1024)
34
+#define SDRAM_SIZE (32 * MiB)
35
+#define SECTOR_SIZE (128 * KiB)
36
+#define FLASH0_SIZE (16 * MiB)
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)
57
}
58
59
if (version == 2) {
60
- flash_size = flash2_size;
61
+ flash_size = FLASH2_SIZE;
62
}
63
64
memory_region_add_subregion(address_space, OMAP_EMIFF_BASE, machine->ram);
65
@@ -XXX,XX +XXX,XX @@ static void sx1_init(MachineState *machine, const int version)
66
if (!pflash_cfi01_register(OMAP_CS0_BASE,
67
"omap_sx1.flash0-1", flash_size,
68
blk_by_legacy_dinfo(dinfo),
69
- sector_size, 4, 0, 0, 0, 0, 0)) {
70
+ SECTOR_SIZE, 4, 0, 0, 0, 0, 0)) {
71
fprintf(stderr, "qemu: Error registering flash memory %d.\n",
72
fl_idx);
73
}
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";
78
}
105
}
79
106
80
/* Duplicate IN into OUT as per VECE. */
107
@@ -XXX,XX +XXX,XX @@ static void sx1_machine_v1_class_init(ObjectClass *oc, void *data)
81
-static void gen_dup_i32(unsigned vece, TCGv_i32 out, TCGv_i32 in)
108
mc->init = sx1_init_v1;
82
+void tcg_gen_dup_i32(unsigned vece, TCGv_i32 out, TCGv_i32 in)
109
mc->ignore_memory_transaction_failures = true;
83
{
110
mc->default_cpu_type = ARM_CPU_TYPE_NAME("ti925t");
84
switch (vece) {
111
- mc->default_ram_size = sdram_size;
85
case MO_8:
112
+ mc->default_ram_size = SDRAM_SIZE;
86
@@ -XXX,XX +XXX,XX @@ static void gen_dup_i32(unsigned vece, TCGv_i32 out, TCGv_i32 in)
113
mc->default_ram_id = "omap1.dram";
87
}
88
}
114
}
89
115
90
-static void gen_dup_i64(unsigned vece, TCGv_i64 out, TCGv_i64 in)
91
+void tcg_gen_dup_i64(unsigned vece, TCGv_i64 out, TCGv_i64 in)
92
{
93
switch (vece) {
94
case MO_8:
95
@@ -XXX,XX +XXX,XX @@ static void do_dup(unsigned vece, uint32_t dofs, uint32_t oprsz,
96
&& (vece != MO_32 || !check_size_impl(oprsz, 4))) {
97
t_64 = tcg_temp_new_i64();
98
tcg_gen_extu_i32_i64(t_64, in_32);
99
- gen_dup_i64(vece, t_64, t_64);
100
+ tcg_gen_dup_i64(vece, t_64, t_64);
101
} else {
102
t_32 = tcg_temp_new_i32();
103
- gen_dup_i32(vece, t_32, in_32);
104
+ tcg_gen_dup_i32(vece, t_32, in_32);
105
}
106
} else if (in_64) {
107
/* We are given a 64-bit variable input. */
108
t_64 = tcg_temp_new_i64();
109
- gen_dup_i64(vece, t_64, in_64);
110
+ tcg_gen_dup_i64(vece, t_64, in_64);
111
} else {
112
/* We are given a constant input. */
113
/* For 64-bit hosts, use 64-bit constants for "simple" constants
114
@@ -XXX,XX +XXX,XX @@ void tcg_gen_gvec_2s(uint32_t dofs, uint32_t aofs, uint32_t oprsz,
115
} else if (g->fni8 && check_size_impl(oprsz, 8)) {
116
TCGv_i64 t64 = tcg_temp_new_i64();
117
118
- gen_dup_i64(g->vece, t64, c);
119
+ tcg_gen_dup_i64(g->vece, t64, c);
120
expand_2s_i64(dofs, aofs, oprsz, t64, g->scalar_first, g->fni8);
121
tcg_temp_free_i64(t64);
122
} else if (g->fni4 && check_size_impl(oprsz, 4)) {
123
TCGv_i32 t32 = tcg_temp_new_i32();
124
125
tcg_gen_extrl_i64_i32(t32, c);
126
- gen_dup_i32(g->vece, t32, t32);
127
+ tcg_gen_dup_i32(g->vece, t32, t32);
128
expand_2s_i32(dofs, aofs, oprsz, t32, g->scalar_first, g->fni4);
129
tcg_temp_free_i32(t32);
130
} else {
131
@@ -XXX,XX +XXX,XX @@ void tcg_gen_gvec_ands(unsigned vece, uint32_t dofs, uint32_t aofs,
132
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
133
{
134
TCGv_i64 tmp = tcg_temp_new_i64();
135
- gen_dup_i64(vece, tmp, c);
136
+ tcg_gen_dup_i64(vece, tmp, c);
137
tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ands);
138
tcg_temp_free_i64(tmp);
139
}
140
@@ -XXX,XX +XXX,XX @@ void tcg_gen_gvec_xors(unsigned vece, uint32_t dofs, uint32_t aofs,
141
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
142
{
143
TCGv_i64 tmp = tcg_temp_new_i64();
144
- gen_dup_i64(vece, tmp, c);
145
+ tcg_gen_dup_i64(vece, tmp, c);
146
tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_xors);
147
tcg_temp_free_i64(tmp);
148
}
149
@@ -XXX,XX +XXX,XX @@ void tcg_gen_gvec_ors(unsigned vece, uint32_t dofs, uint32_t aofs,
150
TCGv_i64 c, uint32_t oprsz, uint32_t maxsz)
151
{
152
TCGv_i64 tmp = tcg_temp_new_i64();
153
- gen_dup_i64(vece, tmp, c);
154
+ tcg_gen_dup_i64(vece, tmp, c);
155
tcg_gen_gvec_2s(dofs, aofs, oprsz, maxsz, tmp, &gop_ors);
156
tcg_temp_free_i64(tmp);
157
}
158
--
116
--
159
2.20.1
117
2.34.1
160
118
161
119
diff view generated by jsdifflib
1
Instead of open-coding the "take NOCP exception if FPU disabled,
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
otherwise call gen_preserve_fp_state()" code in the accessors for
3
FPCXT_NS, add an argument to vfp_access_check_m() which tells it to
4
skip the gen_update_fp_context() call, so we can use it for the
5
FPCXT_NS case.
6
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
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
Message-id: 20210618141019.10671-8-peter.maydell@linaro.org
10
---
11
---
11
target/arm/translate-a32.h | 2 +-
12
hw/arm/z2.c | 6 ++++--
12
target/arm/translate-m-nocp.c | 10 ++--------
13
1 file changed, 4 insertions(+), 2 deletions(-)
13
target/arm/translate-vfp.c | 13 ++++++++-----
14
3 files changed, 11 insertions(+), 14 deletions(-)
15
14
16
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
15
diff --git a/hw/arm/z2.c b/hw/arm/z2.c
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate-a32.h
17
--- a/hw/arm/z2.c
19
+++ b/target/arm/translate-a32.h
18
+++ b/hw/arm/z2.c
20
@@ -XXX,XX +XXX,XX @@ bool disas_neon_shared(DisasContext *s, uint32_t insn);
19
@@ -XXX,XX +XXX,XX @@
21
void load_reg_var(DisasContext *s, TCGv_i32 var, int reg);
22
void arm_gen_condlabel(DisasContext *s);
23
bool vfp_access_check(DisasContext *s);
24
-void gen_preserve_fp_state(DisasContext *s);
25
+bool vfp_access_check_m(DisasContext *s, bool skip_context_update);
26
void read_neon_element32(TCGv_i32 dest, int reg, int ele, MemOp memop);
27
void read_neon_element64(TCGv_i64 dest, int reg, int ele, MemOp memop);
28
void write_neon_element32(TCGv_i32 src, int reg, int ele, MemOp memop);
29
diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/translate-m-nocp.c
32
+++ b/target/arm/translate-m-nocp.c
33
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
34
* otherwise PreserveFPState(), and then FPCXT_NS writes
35
* behave the same as FPCXT_S writes.
36
*/
37
- if (s->fp_excp_el) {
38
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
39
- syn_uncategorized(), s->fp_excp_el);
40
+ if (!vfp_access_check_m(s, true)) {
41
/*
42
* This was only a conditional exception, so override
43
* gen_exception_insn()'s default to DISAS_NORETURN
44
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
45
s->base.is_jmp = DISAS_NEXT;
46
break;
47
}
48
- gen_preserve_fp_state(s);
49
}
50
/* fall through */
51
case ARM_VFP_FPCXT_S:
52
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
53
* otherwise PreserveFPState(), and then FPCXT_NS
54
* reads the same as FPCXT_S.
55
*/
56
- if (s->fp_excp_el) {
57
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
58
- syn_uncategorized(), s->fp_excp_el);
59
+ if (!vfp_access_check_m(s, true)) {
60
/*
61
* This was only a conditional exception, so override
62
* gen_exception_insn()'s default to DISAS_NORETURN
63
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
64
s->base.is_jmp = DISAS_NEXT;
65
break;
66
}
67
- gen_preserve_fp_state(s);
68
tmp = tcg_temp_new_i32();
69
sfpa = tcg_temp_new_i32();
70
fpscr = tcg_temp_new_i32();
71
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/target/arm/translate-vfp.c
74
+++ b/target/arm/translate-vfp.c
75
@@ -XXX,XX +XXX,XX @@ static inline long vfp_f16_offset(unsigned reg, bool top)
76
* Generate code for M-profile lazy FP state preservation if needed;
77
* this corresponds to the pseudocode PreserveFPState() function.
78
*/
20
*/
79
-void gen_preserve_fp_state(DisasContext *s)
21
80
+static void gen_preserve_fp_state(DisasContext *s)
22
#include "qemu/osdep.h"
23
+#include "qemu/units.h"
24
#include "hw/arm/pxa.h"
25
#include "hw/arm/boot.h"
26
#include "hw/i2c/i2c.h"
27
@@ -XXX,XX +XXX,XX @@ static const TypeInfo aer915_info = {
28
.class_init = aer915_class_init,
29
};
30
31
+#define FLASH_SECTOR_SIZE (64 * KiB)
32
+
33
static void z2_init(MachineState *machine)
81
{
34
{
82
if (s->v7m_lspact) {
35
- uint32_t sector_len = 0x10000;
83
/*
36
PXA2xxState *mpu;
84
@@ -XXX,XX +XXX,XX @@ static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled)
37
DriveInfo *dinfo;
85
* If VFP is enabled, do the necessary M-profile lazy-FP handling and then
38
void *z2_lcd;
86
* return true. If not, emit code to generate an appropriate exception and
39
@@ -XXX,XX +XXX,XX @@ static void z2_init(MachineState *machine)
87
* return false.
40
dinfo = drive_get(IF_PFLASH, 0, 0);
88
+ * skip_context_update is true to skip the "update FP context" part of this.
41
if (!pflash_cfi01_register(Z2_FLASH_BASE, "z2.flash0", Z2_FLASH_SIZE,
89
*/
42
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
90
-static bool vfp_access_check_m(DisasContext *s)
43
- sector_len, 4, 0, 0, 0, 0, 0)) {
91
+bool vfp_access_check_m(DisasContext *s, bool skip_context_update)
44
+ FLASH_SECTOR_SIZE, 4, 0, 0, 0, 0, 0)) {
92
{
45
error_report("Error registering flash memory");
93
if (s->fp_excp_el) {
46
exit(1);
94
/*
95
@@ -XXX,XX +XXX,XX @@ static bool vfp_access_check_m(DisasContext *s)
96
/* Trigger lazy-state preservation if necessary */
97
gen_preserve_fp_state(s);
98
99
- /* Update ownership of FP context and create new FP context if needed */
100
- gen_update_fp_context(s);
101
+ if (!skip_context_update) {
102
+ /* Update ownership of FP context and create new FP context if needed */
103
+ gen_update_fp_context(s);
104
+ }
105
106
return true;
107
}
108
@@ -XXX,XX +XXX,XX @@ static bool vfp_access_check_m(DisasContext *s)
109
bool vfp_access_check(DisasContext *s)
110
{
111
if (arm_dc_feature(s, ARM_FEATURE_M)) {
112
- return vfp_access_check_m(s);
113
+ return vfp_access_check_m(s, false);
114
} else {
115
return vfp_access_check_a(s, false);
116
}
47
}
117
--
48
--
118
2.20.1
49
2.34.1
119
50
120
51
diff view generated by jsdifflib
1
Implement the vector forms of the MVE VQDMULH and VQRDMULH insns.
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
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
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-31-peter.maydell@linaro.org
6
---
13
---
7
target/arm/helper-mve.h | 8 ++++++++
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 | 27 +++++++++++++++++++++++++++
10
target/arm/translate-mve.c | 2 ++
11
4 files changed, 40 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_vmulltub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
@@ -XXX,XX +XXX,XX @@ static void vexpress_common_init(MachineState *machine)
18
DEF_HELPER_FLAGS_4(mve_vmulltuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
dinfo = drive_get(IF_PFLASH, 0, 0);
19
DEF_HELPER_FLAGS_4(mve_vmulltuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
pflash0 = ve_pflash_cfi01_register(map[VE_NORFLASH0], "vexpress.flash0",
20
24
dinfo);
21
+DEF_HELPER_FLAGS_4(mve_vqdmulhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
- if (!pflash0) {
22
+DEF_HELPER_FLAGS_4(mve_vqdmulhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
- error_report("vexpress: error registering flash 0");
23
+DEF_HELPER_FLAGS_4(mve_vqdmulhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
- exit(1);
24
+
28
- }
25
+DEF_HELPER_FLAGS_4(mve_vqrdmulhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
26
+DEF_HELPER_FLAGS_4(mve_vqrdmulhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
if (map[VE_NORFLASHALIAS] != -1) {
27
+DEF_HELPER_FLAGS_4(mve_vqrdmulhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
/* Map flash 0 as an alias into low memory */
28
+
32
@@ -XXX,XX +XXX,XX @@ static void vexpress_common_init(MachineState *machine)
29
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
30
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
32
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/mve.decode
35
+++ b/target/arm/mve.decode
36
@@ -XXX,XX +XXX,XX @@ VMULL_BU 111 1 1110 0 . .. ... 1 ... 0 1110 . 0 . 0 ... 0 @2op
37
VMULL_TS 111 0 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
38
VMULL_TU 111 1 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
39
40
+VQDMULH 1110 1111 0 . .. ... 0 ... 0 1011 . 1 . 0 ... 0 @2op
41
+VQRDMULH 1111 1111 0 . .. ... 0 ... 0 1011 . 1 . 0 ... 0 @2op
42
+
43
# Vector miscellaneous
44
45
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
46
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/mve_helper.c
49
+++ b/target/arm/mve_helper.c
50
@@ -XXX,XX +XXX,XX @@ DO_1OP(vfnegs, 8, uint64_t, DO_FNEGS)
51
mve_advance_vpt(env); \
52
}
33
}
53
34
54
+#define DO_2OP_SAT(OP, ESIZE, TYPE, FN) \
35
dinfo = drive_get(IF_PFLASH, 0, 1);
55
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, void *vm) \
36
- if (!ve_pflash_cfi01_register(map[VE_NORFLASH1], "vexpress.flash1",
56
+ { \
37
- dinfo)) {
57
+ TYPE *d = vd, *n = vn, *m = vm; \
38
- error_report("vexpress: error registering flash 1");
58
+ uint16_t mask = mve_element_mask(env); \
39
- exit(1);
59
+ unsigned e; \
40
- }
60
+ bool qc = false; \
41
+ ve_pflash_cfi01_register(map[VE_NORFLASH1], "vexpress.flash1", dinfo);
61
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
42
62
+ bool sat = false; \
43
sram_size = 0x2000000;
63
+ TYPE r = FN(n[H##ESIZE(e)], m[H##ESIZE(e)], &sat); \
44
memory_region_init_ram(sram, NULL, "vexpress.sram", sram_size,
64
+ mergemask(&d[H##ESIZE(e)], r, mask); \
65
+ qc |= sat & mask & 1; \
66
+ } \
67
+ if (qc) { \
68
+ env->vfp.qc[0] = qc; \
69
+ } \
70
+ mve_advance_vpt(env); \
71
+ }
72
+
73
#define DO_AND(N, M) ((N) & (M))
74
#define DO_BIC(N, M) ((N) & ~(M))
75
#define DO_ORR(N, M) ((N) | (M))
76
@@ -XXX,XX +XXX,XX @@ static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
77
#define DO_QRDMULH_W(n, m, s) do_sat_bhw(((int64_t)n * m + (1 << 30)) >> 31, \
78
INT32_MIN, INT32_MAX, s)
79
80
+DO_2OP_SAT(vqdmulhb, 1, int8_t, DO_QDMULH_B)
81
+DO_2OP_SAT(vqdmulhh, 2, int16_t, DO_QDMULH_H)
82
+DO_2OP_SAT(vqdmulhw, 4, int32_t, DO_QDMULH_W)
83
+
84
+DO_2OP_SAT(vqrdmulhb, 1, int8_t, DO_QRDMULH_B)
85
+DO_2OP_SAT(vqrdmulhh, 2, int16_t, DO_QRDMULH_H)
86
+DO_2OP_SAT(vqrdmulhw, 4, int32_t, DO_QRDMULH_W)
87
+
88
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
89
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
90
uint32_t rm) \
91
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
92
index XXXXXXX..XXXXXXX 100644
93
--- a/target/arm/translate-mve.c
94
+++ b/target/arm/translate-mve.c
95
@@ -XXX,XX +XXX,XX @@ DO_2OP(VMULL_BS, vmullbs)
96
DO_2OP(VMULL_BU, vmullbu)
97
DO_2OP(VMULL_TS, vmullts)
98
DO_2OP(VMULL_TU, vmulltu)
99
+DO_2OP(VQDMULH, vqdmulh)
100
+DO_2OP(VQRDMULH, vqrdmulh)
101
102
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
103
MVEGenTwoOpScalarFn fn)
104
--
45
--
105
2.20.1
46
2.34.1
106
47
107
48
diff view generated by jsdifflib
1
Implement the MVE VQADD and VQSUB insns, which perform saturating
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
addition of a scalar to each element. Note that individual bytes of
3
each result element are used or discarded according to the predicate
4
mask, but FPSCR.QC is only set if the predicate mask for the lowest
5
byte of the element is set.
6
2
3
Since its QOM'ification in commit 368a354f02 ("pflash_cfi0x:
4
QOMified") the pflash_cfi01_register() function does not fail.
5
6
This call was later converted with a script to use &error_fatal,
7
still unable to 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-14-philmd@linaro.org
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210617121628.20116-28-peter.maydell@linaro.org
10
---
13
---
11
target/arm/helper-mve.h | 16 ++++++++++
14
hw/arm/gumstix.c | 18 ++++++------------
12
target/arm/mve.decode | 5 +++
15
hw/arm/mainstone.c | 13 +++++--------
13
target/arm/mve_helper.c | 62 ++++++++++++++++++++++++++++++++++++++
16
hw/arm/omap_sx1.c | 22 ++++++++--------------
14
target/arm/translate-mve.c | 4 +++
17
hw/arm/versatilepb.c | 6 ++----
15
4 files changed, 87 insertions(+)
18
hw/arm/z2.c | 9 +++------
19
5 files changed, 24 insertions(+), 44 deletions(-)
16
20
17
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
21
diff --git a/hw/arm/gumstix.c b/hw/arm/gumstix.c
18
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper-mve.h
23
--- a/hw/arm/gumstix.c
20
+++ b/target/arm/helper-mve.h
24
+++ b/hw/arm/gumstix.c
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vhsubu_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
@@ -XXX,XX +XXX,XX @@ static void connex_init(MachineState *machine)
22
DEF_HELPER_FLAGS_4(mve_vhsubu_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
26
}
23
DEF_HELPER_FLAGS_4(mve_vhsubu_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
27
24
28
/* Numonyx RC28F128J3F75 */
25
+DEF_HELPER_FLAGS_4(mve_vqadds_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
29
- if (!pflash_cfi01_register(0x00000000, "connext.rom", CONNEX_FLASH_SIZE,
26
+DEF_HELPER_FLAGS_4(mve_vqadds_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
30
- dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
27
+DEF_HELPER_FLAGS_4(mve_vqadds_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
- FLASH_SECTOR_SIZE, 2, 0, 0, 0, 0, 0)) {
28
+
32
- error_report("Error registering flash memory");
29
+DEF_HELPER_FLAGS_4(mve_vqaddu_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
33
- exit(1);
30
+DEF_HELPER_FLAGS_4(mve_vqaddu_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
34
- }
31
+DEF_HELPER_FLAGS_4(mve_vqaddu_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
35
+ pflash_cfi01_register(0x00000000, "connext.rom", CONNEX_FLASH_SIZE,
32
+
36
+ dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
33
+DEF_HELPER_FLAGS_4(mve_vqsubs_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
37
+ FLASH_SECTOR_SIZE, 2, 0, 0, 0, 0, 0);
34
+DEF_HELPER_FLAGS_4(mve_vqsubs_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
38
35
+DEF_HELPER_FLAGS_4(mve_vqsubs_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
39
/* Interrupt line of NIC is connected to GPIO line 36 */
36
+
40
smc91c111_init(&nd_table[0], 0x04000300,
37
+DEF_HELPER_FLAGS_4(mve_vqsubu_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
41
@@ -XXX,XX +XXX,XX @@ static void verdex_init(MachineState *machine)
38
+DEF_HELPER_FLAGS_4(mve_vqsubu_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
42
}
39
+DEF_HELPER_FLAGS_4(mve_vqsubu_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
43
40
+
44
/* Micron RC28F256P30TFA */
41
DEF_HELPER_FLAGS_4(mve_vbrsrb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
45
- if (!pflash_cfi01_register(0x00000000, "verdex.rom", VERDEX_FLASH_SIZE,
42
DEF_HELPER_FLAGS_4(mve_vbrsrh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
46
- dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
43
DEF_HELPER_FLAGS_4(mve_vbrsrw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
47
- FLASH_SECTOR_SIZE, 2, 0, 0, 0, 0, 0)) {
44
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
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
45
index XXXXXXX..XXXXXXX 100644
58
index XXXXXXX..XXXXXXX 100644
46
--- a/target/arm/mve.decode
59
--- a/hw/arm/mainstone.c
47
+++ b/target/arm/mve.decode
60
+++ b/hw/arm/mainstone.c
48
@@ -XXX,XX +XXX,XX @@ VHADD_S_scalar 1110 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
61
@@ -XXX,XX +XXX,XX @@ static void mainstone_common_init(MachineState *machine,
49
VHADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
62
/* There are two 32MiB flash devices on the board */
50
VHSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
63
for (i = 0; i < 2; i ++) {
51
VHSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
64
dinfo = drive_get(IF_PFLASH, 0, i);
52
+
65
- if (!pflash_cfi01_register(mainstone_flash_base[i],
53
+VQADD_S_scalar 1110 1110 0 . .. ... 0 ... 0 1111 . 110 .... @2scalar
66
- i ? "mainstone.flash1" : "mainstone.flash0",
54
+VQADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 110 .... @2scalar
67
- MAINSTONE_FLASH_SIZE,
55
+VQSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
68
- dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
56
+VQSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
69
- FLASH_SECTOR_SIZE, 4, 0, 0, 0, 0, 0)) {
57
VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
70
- error_report("Error registering flash memory");
58
71
- exit(1);
59
# Predicate operations
72
- }
60
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
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
61
index XXXXXXX..XXXXXXX 100644
82
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/mve_helper.c
83
--- a/hw/arm/omap_sx1.c
63
+++ b/target/arm/mve_helper.c
84
+++ b/hw/arm/omap_sx1.c
64
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vhaddu, do_vhadd_u)
85
@@ -XXX,XX +XXX,XX @@ static void sx1_init(MachineState *machine, const int version)
65
DO_2OP_S(vhsubs, do_vhsub_s)
86
66
DO_2OP_U(vhsubu, do_vhsub_u)
87
fl_idx = 0;
67
88
if ((dinfo = drive_get(IF_PFLASH, 0, fl_idx)) != NULL) {
68
+static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
89
- if (!pflash_cfi01_register(OMAP_CS0_BASE,
69
+{
90
- "omap_sx1.flash0-1", flash_size,
70
+ if (val > max) {
91
- blk_by_legacy_dinfo(dinfo),
71
+ *s = true;
92
- SECTOR_SIZE, 4, 0, 0, 0, 0, 0)) {
72
+ return max;
93
- fprintf(stderr, "qemu: Error registering flash memory %d.\n",
73
+ } else if (val < min) {
94
- fl_idx);
74
+ *s = true;
95
- }
75
+ return min;
96
+ pflash_cfi01_register(OMAP_CS0_BASE,
76
+ }
97
+ "omap_sx1.flash0-1", flash_size,
77
+ return val;
98
+ blk_by_legacy_dinfo(dinfo),
78
+}
99
+ SECTOR_SIZE, 4, 0, 0, 0, 0, 0);
79
+
100
fl_idx++;
80
+#define DO_SQADD_B(n, m, s) do_sat_bhw((int64_t)n + m, INT8_MIN, INT8_MAX, s)
81
+#define DO_SQADD_H(n, m, s) do_sat_bhw((int64_t)n + m, INT16_MIN, INT16_MAX, s)
82
+#define DO_SQADD_W(n, m, s) do_sat_bhw((int64_t)n + m, INT32_MIN, INT32_MAX, s)
83
+
84
+#define DO_UQADD_B(n, m, s) do_sat_bhw((int64_t)n + m, 0, UINT8_MAX, s)
85
+#define DO_UQADD_H(n, m, s) do_sat_bhw((int64_t)n + m, 0, UINT16_MAX, s)
86
+#define DO_UQADD_W(n, m, s) do_sat_bhw((int64_t)n + m, 0, UINT32_MAX, s)
87
+
88
+#define DO_SQSUB_B(n, m, s) do_sat_bhw((int64_t)n - m, INT8_MIN, INT8_MAX, s)
89
+#define DO_SQSUB_H(n, m, s) do_sat_bhw((int64_t)n - m, INT16_MIN, INT16_MAX, s)
90
+#define DO_SQSUB_W(n, m, s) do_sat_bhw((int64_t)n - m, INT32_MIN, INT32_MAX, s)
91
+
92
+#define DO_UQSUB_B(n, m, s) do_sat_bhw((int64_t)n - m, 0, UINT8_MAX, s)
93
+#define DO_UQSUB_H(n, m, s) do_sat_bhw((int64_t)n - m, 0, UINT16_MAX, s)
94
+#define DO_UQSUB_W(n, m, s) do_sat_bhw((int64_t)n - m, 0, UINT32_MAX, s)
95
96
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
97
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
98
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vhsubu, do_vhsub_u)
99
mve_advance_vpt(env); \
100
}
101
}
101
102
102
+#define DO_2OP_SAT_SCALAR(OP, ESIZE, TYPE, FN) \
103
@@ -XXX,XX +XXX,XX @@ static void sx1_init(MachineState *machine, const int version)
103
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
104
memory_region_add_subregion(address_space,
104
+ uint32_t rm) \
105
OMAP_CS1_BASE + FLASH1_SIZE, &cs[1]);
105
+ { \
106
106
+ TYPE *d = vd, *n = vn; \
107
- if (!pflash_cfi01_register(OMAP_CS1_BASE,
107
+ TYPE m = rm; \
108
- "omap_sx1.flash1-1", FLASH1_SIZE,
108
+ uint16_t mask = mve_element_mask(env); \
109
- blk_by_legacy_dinfo(dinfo),
109
+ unsigned e; \
110
- SECTOR_SIZE, 4, 0, 0, 0, 0, 0)) {
110
+ bool qc = false; \
111
- fprintf(stderr, "qemu: Error registering flash memory %d.\n",
111
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
112
- fl_idx);
112
+ bool sat = false; \
113
- }
113
+ mergemask(&d[H##ESIZE(e)], FN(n[H##ESIZE(e)], m, &sat), \
114
+ pflash_cfi01_register(OMAP_CS1_BASE,
114
+ mask); \
115
+ "omap_sx1.flash1-1", FLASH1_SIZE,
115
+ qc |= sat & mask & 1; \
116
+ blk_by_legacy_dinfo(dinfo),
116
+ } \
117
+ SECTOR_SIZE, 4, 0, 0, 0, 0, 0);
117
+ if (qc) { \
118
fl_idx++;
118
+ env->vfp.qc[0] = qc; \
119
} else {
119
+ } \
120
memory_region_init_io(&cs[1], NULL, &static_ops, &cs1val,
120
+ mve_advance_vpt(env); \
121
diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
121
+ }
122
+
123
/* provide unsigned 2-op scalar helpers for all sizes */
124
#define DO_2OP_SCALAR_U(OP, FN) \
125
DO_2OP_SCALAR(OP##b, 1, uint8_t, FN) \
126
@@ -XXX,XX +XXX,XX @@ DO_2OP_SCALAR_U(vhaddu_scalar, do_vhadd_u)
127
DO_2OP_SCALAR_S(vhsubs_scalar, do_vhsub_s)
128
DO_2OP_SCALAR_U(vhsubu_scalar, do_vhsub_u)
129
130
+DO_2OP_SAT_SCALAR(vqaddu_scalarb, 1, uint8_t, DO_UQADD_B)
131
+DO_2OP_SAT_SCALAR(vqaddu_scalarh, 2, uint16_t, DO_UQADD_H)
132
+DO_2OP_SAT_SCALAR(vqaddu_scalarw, 4, uint32_t, DO_UQADD_W)
133
+DO_2OP_SAT_SCALAR(vqadds_scalarb, 1, int8_t, DO_SQADD_B)
134
+DO_2OP_SAT_SCALAR(vqadds_scalarh, 2, int16_t, DO_SQADD_H)
135
+DO_2OP_SAT_SCALAR(vqadds_scalarw, 4, int32_t, DO_SQADD_W)
136
+
137
+DO_2OP_SAT_SCALAR(vqsubu_scalarb, 1, uint8_t, DO_UQSUB_B)
138
+DO_2OP_SAT_SCALAR(vqsubu_scalarh, 2, uint16_t, DO_UQSUB_H)
139
+DO_2OP_SAT_SCALAR(vqsubu_scalarw, 4, uint32_t, DO_UQSUB_W)
140
+DO_2OP_SAT_SCALAR(vqsubs_scalarb, 1, int8_t, DO_SQSUB_B)
141
+DO_2OP_SAT_SCALAR(vqsubs_scalarh, 2, int16_t, DO_SQSUB_H)
142
+DO_2OP_SAT_SCALAR(vqsubs_scalarw, 4, int32_t, DO_SQSUB_W)
143
+
144
static inline uint32_t do_vbrsrb(uint32_t n, uint32_t m)
145
{
146
m &= 0xff;
147
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
148
index XXXXXXX..XXXXXXX 100644
122
index XXXXXXX..XXXXXXX 100644
149
--- a/target/arm/translate-mve.c
123
--- a/hw/arm/versatilepb.c
150
+++ b/target/arm/translate-mve.c
124
+++ b/hw/arm/versatilepb.c
151
@@ -XXX,XX +XXX,XX @@ DO_2OP_SCALAR(VHADD_S_scalar, vhadds_scalar)
125
@@ -XXX,XX +XXX,XX @@ static void versatile_init(MachineState *machine, int board_id)
152
DO_2OP_SCALAR(VHADD_U_scalar, vhaddu_scalar)
126
/* 0x34000000 NOR Flash */
153
DO_2OP_SCALAR(VHSUB_S_scalar, vhsubs_scalar)
127
154
DO_2OP_SCALAR(VHSUB_U_scalar, vhsubu_scalar)
128
dinfo = drive_get(IF_PFLASH, 0, 0);
155
+DO_2OP_SCALAR(VQADD_S_scalar, vqadds_scalar)
129
- if (!pflash_cfi01_register(VERSATILE_FLASH_ADDR, "versatile.flash",
156
+DO_2OP_SCALAR(VQADD_U_scalar, vqaddu_scalar)
130
+ pflash_cfi01_register(VERSATILE_FLASH_ADDR, "versatile.flash",
157
+DO_2OP_SCALAR(VQSUB_S_scalar, vqsubs_scalar)
131
VERSATILE_FLASH_SIZE,
158
+DO_2OP_SCALAR(VQSUB_U_scalar, vqsubu_scalar)
132
dinfo ? blk_by_legacy_dinfo(dinfo) : NULL,
159
DO_2OP_SCALAR(VBRSR, vbrsr)
133
VERSATILE_FLASH_SECT_SIZE,
160
134
- 4, 0x0089, 0x0018, 0x0000, 0x0, 0)) {
161
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
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);
162
--
161
--
163
2.20.1
162
2.34.1
164
163
165
164
diff view generated by jsdifflib
1
Implement the MVE VSHL insn (vector form).
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
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
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-35-peter.maydell@linaro.org
6
---
10
---
7
target/arm/helper-mve.h | 8 ++++++++
11
include/hw/arm/pxa.h | 6 +++---
8
target/arm/mve.decode | 3 +++
12
1 file changed, 3 insertions(+), 3 deletions(-)
9
target/arm/mve_helper.c | 6 ++++++
10
target/arm/translate-mve.c | 2 ++
11
4 files changed, 19 insertions(+)
12
13
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
diff --git a/include/hw/arm/pxa.h b/include/hw/arm/pxa.h
14
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
16
--- a/include/hw/arm/pxa.h
16
+++ b/target/arm/helper-mve.h
17
+++ b/include/hw/arm/pxa.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqsubub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
18
@@ -XXX,XX +XXX,XX @@ void pxa27x_register_keypad(PXA2xxKeyPadState *kp,
18
DEF_HELPER_FLAGS_4(mve_vqsubuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
const struct keymap *map, int size);
19
DEF_HELPER_FLAGS_4(mve_vqsubuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
20
21
/* pxa2xx.c */
21
+DEF_HELPER_FLAGS_4(mve_vshlsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
-typedef struct PXA2xxI2CState PXA2xxI2CState;
22
+DEF_HELPER_FLAGS_4(mve_vshlsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
+#define TYPE_PXA2XX_I2C "pxa2xx_i2c"
23
+DEF_HELPER_FLAGS_4(mve_vshlsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxI2CState, PXA2XX_I2C)
24
+
25
+
25
+DEF_HELPER_FLAGS_4(mve_vshlub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
PXA2xxI2CState *pxa2xx_i2c_init(hwaddr base,
26
+DEF_HELPER_FLAGS_4(mve_vshluh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
qemu_irq irq, uint32_t page_size);
27
+DEF_HELPER_FLAGS_4(mve_vshluw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
I2CBus *pxa2xx_i2c_bus(PXA2xxI2CState *s);
28
+
29
29
DEF_HELPER_FLAGS_4(mve_vqshlsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
-#define TYPE_PXA2XX_I2C "pxa2xx_i2c"
30
DEF_HELPER_FLAGS_4(mve_vqshlsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
typedef struct PXA2xxI2SState PXA2xxI2SState;
31
DEF_HELPER_FLAGS_4(mve_vqshlsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
-OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxI2CState, PXA2XX_I2C)
32
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
33
33
index XXXXXXX..XXXXXXX 100644
34
#define TYPE_PXA2XX_FIR "pxa2xx-fir"
34
--- a/target/arm/mve.decode
35
OBJECT_DECLARE_SIMPLE_TYPE(PXA2xxFIrState, PXA2XX_FIR)
35
+++ b/target/arm/mve.decode
36
@@ -XXX,XX +XXX,XX @@ VQADD_U 111 1 1111 0 . .. ... 0 ... 0 0000 . 1 . 1 ... 0 @2op
37
VQSUB_S 111 0 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
38
VQSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
39
40
+VSHL_S 111 0 1111 0 . .. ... 0 ... 0 0100 . 1 . 0 ... 0 @2op_rev
41
+VSHL_U 111 1 1111 0 . .. ... 0 ... 0 0100 . 1 . 0 ... 0 @2op_rev
42
+
43
VQSHL_S 111 0 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
44
VQSHL_U 111 1 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
45
46
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/mve_helper.c
49
+++ b/target/arm/mve_helper.c
50
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vhaddu, do_vhadd_u)
51
DO_2OP_S(vhsubs, do_vhsub_s)
52
DO_2OP_U(vhsubu, do_vhsub_u)
53
54
+#define DO_VSHLS(N, M) do_sqrshl_bhs(N, (int8_t)(M), sizeof(N) * 8, false, NULL)
55
+#define DO_VSHLU(N, M) do_uqrshl_bhs(N, (int8_t)(M), sizeof(N) * 8, false, NULL)
56
+
57
+DO_2OP_S(vshls, DO_VSHLS)
58
+DO_2OP_U(vshlu, DO_VSHLU)
59
+
60
static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
61
{
62
if (val > max) {
63
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
64
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/translate-mve.c
66
+++ b/target/arm/translate-mve.c
67
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQADD_S, vqadds)
68
DO_2OP(VQADD_U, vqaddu)
69
DO_2OP(VQSUB_S, vqsubs)
70
DO_2OP(VQSUB_U, vqsubu)
71
+DO_2OP(VSHL_S, vshls)
72
+DO_2OP(VSHL_U, vshlu)
73
DO_2OP(VQSHL_S, vqshls)
74
DO_2OP(VQSHL_U, vqshlu)
75
DO_2OP(VQRSHL_S, vqrshls)
76
--
36
--
77
2.20.1
37
2.34.1
78
38
79
39
diff view generated by jsdifflib
1
Implement the MV VQRSHL (vector) insn. Again, the code to perform
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
the actual shifts is borrowed from neon_helper.c.
3
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
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
Message-id: 20210617121628.20116-34-peter.maydell@linaro.org
7
---
10
---
8
target/arm/helper-mve.h | 8 ++++++++
11
hw/gpio/omap_gpio.c | 3 ++-
9
target/arm/mve.decode | 3 +++
12
1 file changed, 2 insertions(+), 1 deletion(-)
10
target/arm/mve_helper.c | 6 ++++++
11
target/arm/translate-mve.c | 2 ++
12
4 files changed, 19 insertions(+)
13
13
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
diff --git a/hw/gpio/omap_gpio.c b/hw/gpio/omap_gpio.c
15
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-mve.h
16
--- a/hw/gpio/omap_gpio.c
17
+++ b/target/arm/helper-mve.h
17
+++ b/hw/gpio/omap_gpio.c
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqshlub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
18
@@ -XXX,XX +XXX,XX @@ struct omap_gpif_s {
19
DEF_HELPER_FLAGS_4(mve_vqshluh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
/* General-Purpose I/O of OMAP1 */
20
DEF_HELPER_FLAGS_4(mve_vqshluw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
static void omap_gpio_set(void *opaque, int line, int level)
21
21
{
22
+DEF_HELPER_FLAGS_4(mve_vqrshlsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
- struct omap_gpio_s *s = &((struct omap_gpif_s *) opaque)->omap1;
23
+DEF_HELPER_FLAGS_4(mve_vqrshlsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
+ struct omap_gpif_s *p = opaque;
24
+DEF_HELPER_FLAGS_4(mve_vqrshlsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+ struct omap_gpio_s *s = &p->omap1;
25
+
25
uint16_t prev = s->inputs;
26
+DEF_HELPER_FLAGS_4(mve_vqrshlub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
27
+DEF_HELPER_FLAGS_4(mve_vqrshluh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
if (level)
28
+DEF_HELPER_FLAGS_4(mve_vqrshluw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
+
30
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
32
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
33
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/mve.decode
36
+++ b/target/arm/mve.decode
37
@@ -XXX,XX +XXX,XX @@ VQSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
38
VQSHL_S 111 0 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
39
VQSHL_U 111 1 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
40
41
+VQRSHL_S 111 0 1111 0 . .. ... 0 ... 0 0101 . 1 . 1 ... 0 @2op_rev
42
+VQRSHL_U 111 1 1111 0 . .. ... 0 ... 0 0101 . 1 . 1 ... 0 @2op_rev
43
+
44
# Vector miscellaneous
45
46
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
47
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/mve_helper.c
50
+++ b/target/arm/mve_helper.c
51
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT(vqsubsw, 4, int32_t, DO_SQSUB_W)
52
WRAP_QRSHL_HELPER(do_sqrshl_bhs, N, M, false, satp)
53
#define DO_UQSHL_OP(N, M, satp) \
54
WRAP_QRSHL_HELPER(do_uqrshl_bhs, N, M, false, satp)
55
+#define DO_SQRSHL_OP(N, M, satp) \
56
+ WRAP_QRSHL_HELPER(do_sqrshl_bhs, N, M, true, satp)
57
+#define DO_UQRSHL_OP(N, M, satp) \
58
+ WRAP_QRSHL_HELPER(do_uqrshl_bhs, N, M, true, satp)
59
60
DO_2OP_SAT_S(vqshls, DO_SQSHL_OP)
61
DO_2OP_SAT_U(vqshlu, DO_UQSHL_OP)
62
+DO_2OP_SAT_S(vqrshls, DO_SQRSHL_OP)
63
+DO_2OP_SAT_U(vqrshlu, DO_UQRSHL_OP)
64
65
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
66
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
67
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/target/arm/translate-mve.c
70
+++ b/target/arm/translate-mve.c
71
@@ -XXX,XX +XXX,XX @@ DO_2OP(VQSUB_S, vqsubs)
72
DO_2OP(VQSUB_U, vqsubu)
73
DO_2OP(VQSHL_S, vqshls)
74
DO_2OP(VQSHL_U, vqshlu)
75
+DO_2OP(VQRSHL_S, vqrshls)
76
+DO_2OP(VQRSHL_U, vqrshlu)
77
78
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
79
MVEGenTwoOpScalarFn fn)
80
--
28
--
81
2.20.1
29
2.34.1
82
30
83
31
diff view generated by jsdifflib
1
A few subcases of VLDR/VSTR sysreg succeed but do not perform a
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
memory access:
3
* VSTR of VPR when unprivileged
4
* VLDR to VPR when unprivileged
5
* VLDR to FPCXT_NS when fpInactive
6
2
7
In these cases, even though we don't do the memory access we should
3
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
still update the base register and perform the stack limit check if
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
the insn's addressing mode specifies writeback. Our implementation
5
Message-id: 20230109140306.23161-4-philmd@linaro.org
10
failed to do this, because we handle these side-effects inside the
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
memory_to_fp_sysreg() and fp_sysreg_to_memory() callback functions,
7
---
12
which are only called if there's something to load or store.
8
hw/arm/omap1.c | 115 ++++++++++++++++++--------------------
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(-)
13
27
14
Fix this by adding an extra argument to the callbacks which is set to
28
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
15
true to actually perform the access and false to only do side effects
29
index XXXXXXX..XXXXXXX 100644
16
like writeback, and calling the callback with do_access = false
30
--- a/hw/arm/omap1.c
17
for the three cases listed above.
31
+++ b/hw/arm/omap1.c
18
32
@@ -XXX,XX +XXX,XX @@ static void omap_timer_fire(void *opaque)
19
This produces slightly suboptimal code for the case of a write
33
20
to FPCXT_NS when the FPU is inactive and the insn didn't have
34
static void omap_timer_tick(void *opaque)
21
side effects (ie no writeback, or via VMSR), in which case we'll
35
{
22
generate a conditional branch over an unconditional branch.
36
- struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
23
But this doesn't seem to be important enough to merit requiring
37
+ struct omap_mpu_timer_s *timer = opaque;
24
the callback to report back whether it generated any code or not.
38
25
39
omap_timer_sync(timer);
26
Cc: qemu-stable@nongnu.org
40
omap_timer_fire(timer);
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
41
@@ -XXX,XX +XXX,XX @@ static void omap_timer_tick(void *opaque)
28
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
42
29
Message-id: 20210618141019.10671-5-peter.maydell@linaro.org
43
static void omap_timer_clk_update(void *opaque, int line, int on)
30
---
44
{
31
target/arm/translate-m-nocp.c | 102 ++++++++++++++++++++++++----------
45
- struct omap_mpu_timer_s *timer = (struct omap_mpu_timer_s *) opaque;
32
1 file changed, 72 insertions(+), 30 deletions(-)
46
+ struct omap_mpu_timer_s *timer = opaque;
33
47
34
diff --git a/target/arm/translate-m-nocp.c b/target/arm/translate-m-nocp.c
48
omap_timer_sync(timer);
35
index XXXXXXX..XXXXXXX 100644
49
timer->rate = on ? omap_clk_getrate(timer->clk) : 0;
36
--- a/target/arm/translate-m-nocp.c
50
@@ -XXX,XX +XXX,XX @@ static void omap_timer_clk_setup(struct omap_mpu_timer_s *timer)
37
+++ b/target/arm/translate-m-nocp.c
51
static uint64_t omap_mpu_timer_read(void *opaque, hwaddr addr,
38
@@ -XXX,XX +XXX,XX @@ static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
52
unsigned size)
39
53
{
40
/*
54
- struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
41
* Emit code to store the sysreg to its final destination; frees the
55
+ struct omap_mpu_timer_s *s = opaque;
42
- * TCG temp 'value' it is passed.
56
43
+ * TCG temp 'value' it is passed. do_access is true to do the store,
57
if (size != 4) {
44
+ * and false to skip it and only perform side-effects like base
58
return omap_badwidth_read32(opaque, addr);
45
+ * register writeback.
59
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_mpu_timer_read(void *opaque, hwaddr addr,
46
*/
60
static void omap_mpu_timer_write(void *opaque, hwaddr addr,
47
-typedef void fp_sysreg_storefn(DisasContext *s, void *opaque, TCGv_i32 value);
61
uint64_t value, unsigned size)
48
+typedef void fp_sysreg_storefn(DisasContext *s, void *opaque, TCGv_i32 value,
62
{
49
+ bool do_access);
63
- struct omap_mpu_timer_s *s = (struct omap_mpu_timer_s *) opaque;
50
/*
64
+ struct omap_mpu_timer_s *s = opaque;
51
* Emit code to load the value to be copied to the sysreg; returns
65
52
- * a new TCG temporary
66
if (size != 4) {
53
+ * a new TCG temporary. do_access is true to do the store,
67
omap_badwidth_write32(opaque, addr, value);
54
+ * and false to skip it and only perform side-effects like base
68
@@ -XXX,XX +XXX,XX @@ struct omap_watchdog_timer_s {
55
+ * register writeback.
69
static uint64_t omap_wd_timer_read(void *opaque, hwaddr addr,
56
*/
70
unsigned size)
57
-typedef TCGv_i32 fp_sysreg_loadfn(DisasContext *s, void *opaque);
71
{
58
+typedef TCGv_i32 fp_sysreg_loadfn(DisasContext *s, void *opaque,
72
- struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
59
+ bool do_access);
73
+ struct omap_watchdog_timer_s *s = opaque;
60
74
61
/* Common decode/access checks for fp sysreg read/write */
75
if (size != 2) {
62
typedef enum FPSysRegCheckResult {
76
return omap_badwidth_read16(opaque, addr);
63
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
77
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_wd_timer_read(void *opaque, hwaddr addr,
64
78
static void omap_wd_timer_write(void *opaque, hwaddr addr,
65
switch (regno) {
79
uint64_t value, unsigned size)
66
case ARM_VFP_FPSCR:
80
{
67
- tmp = loadfn(s, opaque);
81
- struct omap_watchdog_timer_s *s = (struct omap_watchdog_timer_s *) opaque;
68
+ tmp = loadfn(s, opaque, true);
82
+ struct omap_watchdog_timer_s *s = opaque;
69
gen_helper_vfp_set_fpscr(cpu_env, tmp);
83
70
tcg_temp_free_i32(tmp);
84
if (size != 2) {
71
gen_lookup_tb(s);
85
omap_badwidth_write16(opaque, addr, value);
72
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
86
@@ -XXX,XX +XXX,XX @@ struct omap_32khz_timer_s {
73
case ARM_VFP_FPSCR_NZCVQC:
87
static uint64_t omap_os_timer_read(void *opaque, hwaddr addr,
74
{
88
unsigned size)
75
TCGv_i32 fpscr;
89
{
76
- tmp = loadfn(s, opaque);
90
- struct omap_32khz_timer_s *s = (struct omap_32khz_timer_s *) opaque;
77
+ tmp = loadfn(s, opaque, true);
91
+ struct omap_32khz_timer_s *s = opaque;
78
if (dc_isar_feature(aa32_mve, s)) {
92
int offset = addr & OMAP_MPUI_REG_MASK;
79
/* QC is only present for MVE; otherwise RES0 */
93
80
TCGv_i32 qc = tcg_temp_new_i32();
94
if (size != 4) {
81
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
95
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_os_timer_read(void *opaque, hwaddr addr,
82
break;
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)
83
}
294
}
84
case ARM_VFP_FPCXT_NS:
295
}
85
+ {
296
86
+ TCGLabel *lab_active = gen_new_label();
297
-static uint64_t omap_uwire_read(void *opaque, hwaddr addr,
87
+
298
- unsigned size)
88
lab_end = gen_new_label();
299
+static uint64_t omap_uwire_read(void *opaque, hwaddr addr, unsigned size)
89
- /* fpInactive case: write is a NOP, so branch to end */
300
{
90
- gen_branch_fpInactive(s, TCG_COND_NE, lab_end);
301
- struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
91
+ gen_branch_fpInactive(s, TCG_COND_EQ, lab_active);
302
+ struct omap_uwire_s *s = opaque;
92
+ /*
303
int offset = addr & OMAP_MPUI_REG_MASK;
93
+ * fpInactive case: write is a NOP, so only do side effects
304
94
+ * like register writeback before we branch to end
305
if (size != 2) {
95
+ */
306
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_uwire_read(void *opaque, hwaddr addr,
96
+ loadfn(s, opaque, false);
307
static void omap_uwire_write(void *opaque, hwaddr addr,
97
+ tcg_gen_br(lab_end);
308
uint64_t value, unsigned size)
98
+
309
{
99
+ gen_set_label(lab_active);
310
- struct omap_uwire_s *s = (struct omap_uwire_s *) opaque;
100
/*
311
+ struct omap_uwire_s *s = opaque;
101
* !fpInactive: if FPU disabled, take NOCP exception;
312
int offset = addr & OMAP_MPUI_REG_MASK;
102
* otherwise PreserveFPState(), and then FPCXT_NS writes
313
103
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
314
if (size != 2) {
104
break;
315
@@ -XXX,XX +XXX,XX @@ static void omap_pwl_update(struct omap_pwl_s *s)
105
}
106
gen_preserve_fp_state(s);
107
- /* fall through */
108
+ }
109
+ /* fall through */
110
case ARM_VFP_FPCXT_S:
111
{
112
TCGv_i32 sfpa, control;
113
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
114
* Set FPSCR and CONTROL.SFPA from value; the new FPSCR takes
115
* bits [27:0] from value and zeroes bits [31:28].
116
*/
117
- tmp = loadfn(s, opaque);
118
+ tmp = loadfn(s, opaque, true);
119
sfpa = tcg_temp_new_i32();
120
tcg_gen_shri_i32(sfpa, tmp, 31);
121
control = load_cpu_field(v7m.control[M_REG_S]);
122
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
123
case ARM_VFP_VPR:
124
/* Behaves as NOP if not privileged */
125
if (IS_USER(s)) {
126
+ loadfn(s, opaque, false);
127
break;
128
}
129
- tmp = loadfn(s, opaque);
130
+ tmp = loadfn(s, opaque, true);
131
store_cpu_field(tmp, v7m.vpr);
132
break;
133
case ARM_VFP_P0:
134
{
135
TCGv_i32 vpr;
136
- tmp = loadfn(s, opaque);
137
+ tmp = loadfn(s, opaque, true);
138
vpr = load_cpu_field(v7m.vpr);
139
tcg_gen_deposit_i32(vpr, vpr, tmp,
140
R_V7M_VPR_P0_SHIFT, R_V7M_VPR_P0_LENGTH);
141
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
142
case ARM_VFP_FPSCR:
143
tmp = tcg_temp_new_i32();
144
gen_helper_vfp_get_fpscr(tmp, cpu_env);
145
- storefn(s, opaque, tmp);
146
+ storefn(s, opaque, tmp, true);
147
break;
148
case ARM_VFP_FPSCR_NZCVQC:
149
tmp = tcg_temp_new_i32();
150
gen_helper_vfp_get_fpscr(tmp, cpu_env);
151
tcg_gen_andi_i32(tmp, tmp, FPCR_NZCVQC_MASK);
152
- storefn(s, opaque, tmp);
153
+ storefn(s, opaque, tmp, true);
154
break;
155
case QEMU_VFP_FPSCR_NZCV:
156
/*
157
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
158
*/
159
tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
160
tcg_gen_andi_i32(tmp, tmp, FPCR_NZCV_MASK);
161
- storefn(s, opaque, tmp);
162
+ storefn(s, opaque, tmp, true);
163
break;
164
case ARM_VFP_FPCXT_S:
165
{
166
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
167
* Store result before updating FPSCR etc, in case
168
* it is a memory write which causes an exception.
169
*/
170
- storefn(s, opaque, tmp);
171
+ storefn(s, opaque, tmp, true);
172
/*
173
* Now we must reset FPSCR from FPDSCR_NS, and clear
174
* CONTROL.SFPA; so we'll end the TB here.
175
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
176
gen_branch_fpInactive(s, TCG_COND_EQ, lab_active);
177
/* fpInactive case: reads as FPDSCR_NS */
178
TCGv_i32 tmp = load_cpu_field(v7m.fpdscr[M_REG_NS]);
179
- storefn(s, opaque, tmp);
180
+ storefn(s, opaque, tmp, true);
181
lab_end = gen_new_label();
182
tcg_gen_br(lab_end);
183
184
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
185
tcg_gen_or_i32(tmp, tmp, sfpa);
186
tcg_temp_free_i32(control);
187
/* Store result before updating FPSCR, in case it faults */
188
- storefn(s, opaque, tmp);
189
+ storefn(s, opaque, tmp, true);
190
/* If SFPA is zero then set FPSCR from FPDSCR_NS */
191
fpdscr = load_cpu_field(v7m.fpdscr[M_REG_NS]);
192
zero = tcg_const_i32(0);
193
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
194
case ARM_VFP_VPR:
195
/* Behaves as NOP if not privileged */
196
if (IS_USER(s)) {
197
+ storefn(s, opaque, NULL, false);
198
break;
199
}
200
tmp = load_cpu_field(v7m.vpr);
201
- storefn(s, opaque, tmp);
202
+ storefn(s, opaque, tmp, true);
203
break;
204
case ARM_VFP_P0:
205
tmp = load_cpu_field(v7m.vpr);
206
tcg_gen_extract_i32(tmp, tmp, R_V7M_VPR_P0_SHIFT, R_V7M_VPR_P0_LENGTH);
207
- storefn(s, opaque, tmp);
208
+ storefn(s, opaque, tmp, true);
209
break;
210
default:
211
g_assert_not_reached();
212
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
213
return true;
214
}
215
216
-static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value)
217
+static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value,
218
+ bool do_access)
219
{
220
arg_VMSR_VMRS *a = opaque;
221
222
+ if (!do_access) {
223
+ return;
224
+ }
225
+
226
if (a->rt == 15) {
227
/* Set the 4 flag bits in the CPSR */
228
gen_set_nzcv(value);
229
@@ -XXX,XX +XXX,XX @@ static void fp_sysreg_to_gpr(DisasContext *s, void *opaque, TCGv_i32 value)
230
}
316
}
231
}
317
}
232
318
233
-static TCGv_i32 gpr_to_fp_sysreg(DisasContext *s, void *opaque)
319
-static uint64_t omap_pwl_read(void *opaque, hwaddr addr,
234
+static TCGv_i32 gpr_to_fp_sysreg(DisasContext *s, void *opaque, bool do_access)
320
- unsigned size)
235
{
321
+static uint64_t omap_pwl_read(void *opaque, hwaddr addr, unsigned size)
236
arg_VMSR_VMRS *a = opaque;
322
{
237
323
- struct omap_pwl_s *s = (struct omap_pwl_s *) opaque;
238
+ if (!do_access) {
324
+ struct omap_pwl_s *s = opaque;
239
+ return NULL;
325
int offset = addr & OMAP_MPUI_REG_MASK;
240
+ }
326
241
return load_reg(s, a->rt);
327
if (size != 1) {
242
}
328
@@ -XXX,XX +XXX,XX @@ static uint64_t omap_pwl_read(void *opaque, hwaddr addr,
243
329
static void omap_pwl_write(void *opaque, hwaddr addr,
244
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
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,
245
}
633
}
246
}
634
}
247
635
248
-static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
636
-static void omap_sysctl_write(void *opaque, hwaddr addr,
249
+static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value,
637
- uint32_t value)
250
+ bool do_access)
638
+static void omap_sysctl_write(void *opaque, hwaddr addr, uint32_t value)
251
{
639
{
252
arg_vldr_sysreg *a = opaque;
640
- struct omap_sysctl_s *s = (struct omap_sysctl_s *) opaque;
253
uint32_t offset = a->imm;
641
+ struct omap_sysctl_s *s = opaque;
254
@@ -XXX,XX +XXX,XX @@ static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
642
255
offset = -offset;
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) {
256
}
782
}
257
783
}
258
+ if (!do_access && !a->w) {
784
259
+ return;
785
-static uint64_t omap_lcdc_read(void *opaque, hwaddr addr,
260
+ }
786
- unsigned size)
261
+
787
+static uint64_t omap_lcdc_read(void *opaque, hwaddr addr, unsigned size)
262
addr = load_reg(s, a->rn);
788
{
263
if (a->p) {
789
- struct omap_lcd_panel_s *s = (struct omap_lcd_panel_s *) opaque;
264
tcg_gen_addi_i32(addr, addr, offset);
790
+ struct omap_lcd_panel_s *s = opaque;
265
@@ -XXX,XX +XXX,XX @@ static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
791
266
gen_helper_v8m_stackcheck(cpu_env, addr);
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)
267
}
1233
}
268
1234
}
269
- gen_aa32_st_i32(s, value, addr, get_mem_index(s),
1235
270
- MO_UL | MO_ALIGN | s->be_data);
1236
-static void omap_gp_timer_write(void *opaque, hwaddr addr,
271
- tcg_temp_free_i32(value);
1237
- uint32_t value)
272
+ if (do_access) {
1238
+static void omap_gp_timer_write(void *opaque, hwaddr addr, uint32_t value)
273
+ gen_aa32_st_i32(s, value, addr, get_mem_index(s),
1239
{
274
+ MO_UL | MO_ALIGN | s->be_data);
1240
- struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
275
+ tcg_temp_free_i32(value);
1241
+ struct omap_gp_timer_s *s = opaque;
276
+ }
1242
277
1243
switch (addr) {
278
if (a->w) {
1244
case 0x00:    /* TIDR */
279
/* writeback */
1245
@@ -XXX,XX +XXX,XX @@ static void omap_gp_timer_write(void *opaque, hwaddr addr,
280
@@ -XXX,XX +XXX,XX @@ static void fp_sysreg_to_memory(DisasContext *s, void *opaque, TCGv_i32 value)
281
}
1246
}
282
}
1247
}
283
1248
284
-static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
1249
-static void omap_gp_timer_writeh(void *opaque, hwaddr addr,
285
+static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque,
1250
- uint32_t value)
286
+ bool do_access)
1251
+static void omap_gp_timer_writeh(void *opaque, hwaddr addr, uint32_t value)
287
{
1252
{
288
arg_vldr_sysreg *a = opaque;
1253
- struct omap_gp_timer_s *s = (struct omap_gp_timer_s *) opaque;
289
uint32_t offset = a->imm;
1254
+ struct omap_gp_timer_s *s = opaque;
290
TCGv_i32 addr;
1255
291
- TCGv_i32 value = tcg_temp_new_i32();
1256
if (addr & 2)
292
+ TCGv_i32 value = NULL;
1257
omap_gp_timer_write(opaque, addr, (value << 16) | s->writeh);
293
1258
diff --git a/hw/timer/omap_synctimer.c b/hw/timer/omap_synctimer.c
294
if (!a->a) {
1259
index XXXXXXX..XXXXXXX 100644
295
offset = -offset;
1260
--- a/hw/timer/omap_synctimer.c
296
}
1261
+++ b/hw/timer/omap_synctimer.c
297
1262
@@ -XXX,XX +XXX,XX @@ void omap_synctimer_reset(struct omap_synctimer_s *s)
298
+ if (!do_access && !a->w) {
1263
299
+ return NULL;
1264
static uint32_t omap_synctimer_readw(void *opaque, hwaddr addr)
300
+ }
1265
{
301
+
1266
- struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
302
addr = load_reg(s, a->rn);
1267
+ struct omap_synctimer_s *s = opaque;
303
if (a->p) {
1268
304
tcg_gen_addi_i32(addr, addr, offset);
1269
switch (addr) {
305
@@ -XXX,XX +XXX,XX @@ static TCGv_i32 memory_to_fp_sysreg(DisasContext *s, void *opaque)
1270
case 0x00:    /* 32KSYNCNT_REV */
306
gen_helper_v8m_stackcheck(cpu_env, addr);
1271
@@ -XXX,XX +XXX,XX @@ static uint32_t omap_synctimer_readw(void *opaque, hwaddr addr)
307
}
1272
308
1273
static uint32_t omap_synctimer_readh(void *opaque, hwaddr addr)
309
- gen_aa32_ld_i32(s, value, addr, get_mem_index(s),
1274
{
310
- MO_UL | MO_ALIGN | s->be_data);
1275
- struct omap_synctimer_s *s = (struct omap_synctimer_s *) opaque;
311
+ if (do_access) {
1276
+ struct omap_synctimer_s *s = opaque;
312
+ value = tcg_temp_new_i32();
1277
uint32_t ret;
313
+ gen_aa32_ld_i32(s, value, addr, get_mem_index(s),
1278
314
+ MO_UL | MO_ALIGN | s->be_data);
1279
if (addr & 2)
315
+ }
316
317
if (a->w) {
318
/* writeback */
319
--
1280
--
320
2.20.1
1281
2.34.1
321
1282
322
1283
diff view generated by jsdifflib
1
Implement the MVE VPST insn, which sets the predicate mask
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
fields in the VPR to the immediate value encoded in the insn.
3
2
3
Following docs/devel/style.rst guidelines, rename omap_gpif_s ->
4
Omap1GpioState. This also remove a use of 'struct' in the
5
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-5-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
Message-id: 20210617121628.20116-27-peter.maydell@linaro.org
7
---
11
---
8
target/arm/mve.decode | 4 +++
12
include/hw/arm/omap.h | 6 +++---
9
target/arm/translate-mve.c | 59 ++++++++++++++++++++++++++++++++++++++
13
hw/gpio/omap_gpio.c | 16 ++++++++--------
10
2 files changed, 63 insertions(+)
14
2 files changed, 11 insertions(+), 11 deletions(-)
11
15
12
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
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 @@ VHADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
20
@@ -XXX,XX +XXX,XX @@ void omap_i2c_set_fclk(OMAPI2CState *i2c, omap_clk clk);
17
VHSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
21
18
VHSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
22
/* omap_gpio.c */
19
VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
23
#define TYPE_OMAP1_GPIO "omap-gpio"
20
+
24
-DECLARE_INSTANCE_CHECKER(struct omap_gpif_s, OMAP1_GPIO,
21
+# Predicate operations
25
+typedef struct Omap1GpioState Omap1GpioState;
22
+%mask_22_13 22:1 13:3
26
+DECLARE_INSTANCE_CHECKER(Omap1GpioState, OMAP1_GPIO,
23
+VPST 1111 1110 0 . 11 000 1 ... 0 1111 0100 1101 mask=%mask_22_13
27
TYPE_OMAP1_GPIO)
24
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
28
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
25
index XXXXXXX..XXXXXXX 100644
43
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/translate-mve.c
44
--- a/hw/gpio/omap_gpio.c
27
+++ b/target/arm/translate-mve.c
45
+++ b/hw/gpio/omap_gpio.c
28
@@ -XXX,XX +XXX,XX @@ static void mve_update_eci(DisasContext *s)
46
@@ -XXX,XX +XXX,XX @@ struct omap_gpio_s {
47
uint16_t pins;
48
};
49
50
-struct omap_gpif_s {
51
+struct Omap1GpioState {
52
SysBusDevice parent_obj;
53
54
MemoryRegion iomem;
55
@@ -XXX,XX +XXX,XX @@ struct omap_gpif_s {
56
/* General-Purpose I/O of OMAP1 */
57
static void omap_gpio_set(void *opaque, int line, int level)
58
{
59
- struct omap_gpif_s *p = opaque;
60
+ Omap1GpioState *p = opaque;
61
struct omap_gpio_s *s = &p->omap1;
62
uint16_t prev = s->inputs;
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);
72
}
73
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps omap2_gpif_top_ops = {
74
static void omap_gpio_init(Object *obj)
75
{
76
DeviceState *dev = DEVICE(obj);
77
- struct omap_gpif_s *s = OMAP1_GPIO(obj);
78
+ Omap1GpioState *s = OMAP1_GPIO(obj);
79
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
80
81
qdev_init_gpio_in(dev, omap_gpio_set, 16);
82
@@ -XXX,XX +XXX,XX @@ static void omap_gpio_init(Object *obj)
83
84
static void omap_gpio_realize(DeviceState *dev, Error **errp)
85
{
86
- struct omap_gpif_s *s = OMAP1_GPIO(dev);
87
+ Omap1GpioState *s = OMAP1_GPIO(dev);
88
89
if (!s->clk) {
90
error_setg(errp, "omap-gpio: clk not connected");
91
@@ -XXX,XX +XXX,XX @@ static void omap2_gpio_realize(DeviceState *dev, Error **errp)
29
}
92
}
30
}
93
}
31
94
32
+static void mve_update_and_store_eci(DisasContext *s)
95
-void omap_gpio_set_clk(omap_gpif *gpio, omap_clk clk)
33
+{
96
+void omap_gpio_set_clk(Omap1GpioState *gpio, omap_clk clk)
34
+ /*
35
+ * For insns which don't call a helper function that will call
36
+ * mve_advance_vpt(), this version updates s->eci and also stores
37
+ * it out to the CPUState field.
38
+ */
39
+ if (s->eci) {
40
+ mve_update_eci(s);
41
+ store_cpu_field(tcg_constant_i32(s->eci << 4), condexec_bits);
42
+ }
43
+}
44
+
45
static bool mve_skip_first_beat(DisasContext *s)
46
{
97
{
47
/* Return true if PSR.ECI says we must skip the first beat of this insn */
98
gpio->clk = clk;
48
@@ -XXX,XX +XXX,XX @@ static bool trans_VRMLSLDAVH(DisasContext *s, arg_vmlaldav *a)
49
};
50
return do_long_dual_acc(s, a, fns[a->x]);
51
}
99
}
52
+
100
53
+static bool trans_VPST(DisasContext *s, arg_VPST *a)
101
static Property omap_gpio_properties[] = {
54
+{
102
- DEFINE_PROP_INT32("mpu_model", struct omap_gpif_s, mpu_model, 0),
55
+ TCGv_i32 vpr;
103
+ DEFINE_PROP_INT32("mpu_model", Omap1GpioState, mpu_model, 0),
56
+
104
DEFINE_PROP_END_OF_LIST(),
57
+ /* mask == 0 is a "related encoding" */
105
};
58
+ if (!dc_isar_feature(aa32_mve, s) || !a->mask) {
106
59
+ return false;
107
@@ -XXX,XX +XXX,XX @@ static void omap_gpio_class_init(ObjectClass *klass, void *data)
60
+ }
108
static const TypeInfo omap_gpio_info = {
61
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
109
.name = TYPE_OMAP1_GPIO,
62
+ return true;
110
.parent = TYPE_SYS_BUS_DEVICE,
63
+ }
111
- .instance_size = sizeof(struct omap_gpif_s),
64
+ /*
112
+ .instance_size = sizeof(Omap1GpioState),
65
+ * Set the VPR mask fields. We take advantage of MASK01 and MASK23
113
.instance_init = omap_gpio_init,
66
+ * being adjacent fields in the register.
114
.class_init = omap_gpio_class_init,
67
+ *
115
};
68
+ * This insn is not predicated, but it is subject to beat-wise
69
+ * execution, and the mask is updated on the odd-numbered beats.
70
+ * So if PSR.ECI says we should skip beat 1, we mustn't update the
71
+ * 01 mask field.
72
+ */
73
+ vpr = load_cpu_field(v7m.vpr);
74
+ switch (s->eci) {
75
+ case ECI_NONE:
76
+ case ECI_A0:
77
+ /* Update both 01 and 23 fields */
78
+ tcg_gen_deposit_i32(vpr, vpr,
79
+ tcg_constant_i32(a->mask | (a->mask << 4)),
80
+ R_V7M_VPR_MASK01_SHIFT,
81
+ R_V7M_VPR_MASK01_LENGTH + R_V7M_VPR_MASK23_LENGTH);
82
+ break;
83
+ case ECI_A0A1:
84
+ case ECI_A0A1A2:
85
+ case ECI_A0A1A2B0:
86
+ /* Update only the 23 mask field */
87
+ tcg_gen_deposit_i32(vpr, vpr,
88
+ tcg_constant_i32(a->mask),
89
+ R_V7M_VPR_MASK23_SHIFT, R_V7M_VPR_MASK23_LENGTH);
90
+ break;
91
+ default:
92
+ g_assert_not_reached();
93
+ }
94
+ store_cpu_field(vpr, v7m.vpr);
95
+ mve_update_and_store_eci(s);
96
+ return true;
97
+}
98
--
116
--
99
2.20.1
117
2.34.1
100
118
101
119
diff view generated by jsdifflib
1
In a CPU with MVE, the VMOV (vector lane to general-purpose register)
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
and VMOV (general-purpose register to vector lane) insns are not
3
predicated, but they are subject to beatwise execution if they
4
are not in an IT block.
5
2
6
Since our implementation always executes all 4 beats in one tick,
3
Following docs/devel/style.rst guidelines, rename omap2_gpif_s ->
7
this means only that we need to handle PSR.ECI:
4
Omap2GpioState. This also remove a use of 'struct' in the
8
* we must do the usual check for bad ECI state
5
DECLARE_INSTANCE_CHECKER() macro call.
9
* we must advance ECI state if the insn succeeds
10
* if ECI says we should not be executing the beat corresponding
11
to the lane of the vector register being accessed then we
12
should skip performing the move
13
6
14
Note that if PSR.ECI is non-zero then we cannot be in an IT block.
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20230109140306.23161-6-philmd@linaro.org
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
include/hw/arm/omap.h | 9 ++++-----
13
hw/gpio/omap_gpio.c | 20 ++++++++++----------
14
2 files changed, 14 insertions(+), 15 deletions(-)
15
15
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
diff --git a/include/hw/arm/omap.h b/include/hw/arm/omap.h
17
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
18
Message-id: 20210617121628.20116-45-peter.maydell@linaro.org
19
---
20
target/arm/translate-a32.h | 2 +
21
target/arm/translate-mve.c | 4 +-
22
target/arm/translate-vfp.c | 77 +++++++++++++++++++++++++++++++++++---
23
3 files changed, 75 insertions(+), 8 deletions(-)
24
25
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
26
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/translate-a32.h
18
--- a/include/hw/arm/omap.h
28
+++ b/target/arm/translate-a32.h
19
+++ b/include/hw/arm/omap.h
29
@@ -XXX,XX +XXX,XX @@ long neon_full_reg_offset(unsigned reg);
20
@@ -XXX,XX +XXX,XX @@ DECLARE_INSTANCE_CHECKER(Omap1GpioState, OMAP1_GPIO,
30
long neon_element_offset(int reg, int element, MemOp memop);
21
TYPE_OMAP1_GPIO)
31
void gen_rev16(TCGv_i32 dest, TCGv_i32 var);
22
32
void clear_eci_state(DisasContext *s);
23
#define TYPE_OMAP2_GPIO "omap2-gpio"
33
+bool mve_eci_check(DisasContext *s);
24
-DECLARE_INSTANCE_CHECKER(struct omap2_gpif_s, OMAP2_GPIO,
34
+void mve_update_and_store_eci(DisasContext *s);
25
+typedef struct Omap2GpioState Omap2GpioState;
35
26
+DECLARE_INSTANCE_CHECKER(Omap2GpioState, OMAP2_GPIO,
36
static inline TCGv_i32 load_cpu_offset(int offset)
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)
37
{
57
{
38
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
58
- struct omap2_gpif_s *p = opaque;
39
index XXXXXXX..XXXXXXX 100644
59
+ Omap2GpioState *p = opaque;
40
--- a/target/arm/translate-mve.c
60
struct omap2_gpio_s *s = &p->modules[line >> 5];
41
+++ b/target/arm/translate-mve.c
61
42
@@ -XXX,XX +XXX,XX @@ static bool mve_check_qreg_bank(DisasContext *s, int qmask)
62
line &= 31;
43
return qmask < 8;
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);
69
int i;
70
71
for (i = 0; i < s->modulecount; i++) {
72
@@ -XXX,XX +XXX,XX @@ static void omap2_gpif_reset(DeviceState *dev)
73
74
static uint64_t omap2_gpif_top_read(void *opaque, hwaddr addr, unsigned size)
75
{
76
- struct omap2_gpif_s *s = opaque;
77
+ Omap2GpioState *s = opaque;
78
79
switch (addr) {
80
case 0x00:    /* IPGENERICOCPSPL_REVISION */
81
@@ -XXX,XX +XXX,XX @@ static uint64_t omap2_gpif_top_read(void *opaque, hwaddr addr, unsigned size)
82
static void omap2_gpif_top_write(void *opaque, hwaddr addr,
83
uint64_t value, unsigned size)
84
{
85
- struct omap2_gpif_s *s = opaque;
86
+ Omap2GpioState *s = opaque;
87
88
switch (addr) {
89
case 0x00:    /* IPGENERICOCPSPL_REVISION */
90
@@ -XXX,XX +XXX,XX @@ static void omap_gpio_realize(DeviceState *dev, Error **errp)
91
92
static void omap2_gpio_realize(DeviceState *dev, Error **errp)
93
{
94
- struct omap2_gpif_s *s = OMAP2_GPIO(dev);
95
+ Omap2GpioState *s = OMAP2_GPIO(dev);
96
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
97
int i;
98
99
@@ -XXX,XX +XXX,XX @@ static const TypeInfo omap_gpio_info = {
100
.class_init = omap_gpio_class_init,
101
};
102
103
-void omap2_gpio_set_iclk(omap2_gpif *gpio, omap_clk clk)
104
+void omap2_gpio_set_iclk(Omap2GpioState *gpio, omap_clk clk)
105
{
106
gpio->iclk = clk;
44
}
107
}
45
108
46
-static bool mve_eci_check(DisasContext *s)
109
-void omap2_gpio_set_fclk(omap2_gpif *gpio, uint8_t i, omap_clk clk)
47
+bool mve_eci_check(DisasContext *s)
110
+void omap2_gpio_set_fclk(Omap2GpioState *gpio, uint8_t i, omap_clk clk)
48
{
111
{
49
/*
112
assert(i <= 5);
50
* This is a beatwise insn: check that ECI is valid (not a
113
gpio->fclk[i] = clk;
51
@@ -XXX,XX +XXX,XX @@ static void mve_update_eci(DisasContext *s)
52
}
53
}
114
}
54
115
55
-static void mve_update_and_store_eci(DisasContext *s)
116
static Property omap2_gpio_properties[] = {
56
+void mve_update_and_store_eci(DisasContext *s)
117
- DEFINE_PROP_INT32("mpu_model", struct omap2_gpif_s, mpu_model, 0),
57
{
118
+ DEFINE_PROP_INT32("mpu_model", Omap2GpioState, mpu_model, 0),
58
/*
119
DEFINE_PROP_END_OF_LIST(),
59
* For insns which don't call a helper function that will call
120
};
60
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
121
61
index XXXXXXX..XXXXXXX 100644
122
@@ -XXX,XX +XXX,XX @@ static void omap2_gpio_class_init(ObjectClass *klass, void *data)
62
--- a/target/arm/translate-vfp.c
123
static const TypeInfo omap2_gpio_info = {
63
+++ b/target/arm/translate-vfp.c
124
.name = TYPE_OMAP2_GPIO,
64
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
125
.parent = TYPE_SYS_BUS_DEVICE,
65
return true;
126
- .instance_size = sizeof(struct omap2_gpif_s),
66
}
127
+ .instance_size = sizeof(Omap2GpioState),
67
128
.class_init = omap2_gpio_class_init,
68
+static bool mve_skip_vmov(DisasContext *s, int vn, int index, int size)
129
};
69
+{
70
+ /*
71
+ * In a CPU with MVE, the VMOV (vector lane to general-purpose register)
72
+ * and VMOV (general-purpose register to vector lane) insns are not
73
+ * predicated, but they are subject to beatwise execution if they are
74
+ * not in an IT block.
75
+ *
76
+ * Since our implementation always executes all 4 beats in one tick,
77
+ * this means only that if PSR.ECI says we should not be executing
78
+ * the beat corresponding to the lane of the vector register being
79
+ * accessed then we should skip performing the move, and that we need
80
+ * to do the usual check for bad ECI state and advance of ECI state.
81
+ *
82
+ * Note that if PSR.ECI is non-zero then we cannot be in an IT block.
83
+ *
84
+ * Return true if this VMOV scalar <-> gpreg should be skipped because
85
+ * the MVE PSR.ECI state says we skip the beat where the store happens.
86
+ */
87
+
88
+ /* Calculate the byte offset into Qn which we're going to access */
89
+ int ofs = (index << size) + ((vn & 1) * 8);
90
+
91
+ if (!dc_isar_feature(aa32_mve, s)) {
92
+ return false;
93
+ }
94
+
95
+ switch (s->eci) {
96
+ case ECI_NONE:
97
+ return false;
98
+ case ECI_A0:
99
+ return ofs < 4;
100
+ case ECI_A0A1:
101
+ return ofs < 8;
102
+ case ECI_A0A1A2:
103
+ case ECI_A0A1A2B0:
104
+ return ofs < 12;
105
+ default:
106
+ g_assert_not_reached();
107
+ }
108
+}
109
+
110
static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a)
111
{
112
/* VMOV scalar to general purpose register */
113
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a)
114
return false;
115
}
116
117
+ if (dc_isar_feature(aa32_mve, s)) {
118
+ if (!mve_eci_check(s)) {
119
+ return true;
120
+ }
121
+ }
122
+
123
if (!vfp_access_check(s)) {
124
return true;
125
}
126
127
- tmp = tcg_temp_new_i32();
128
- read_neon_element32(tmp, a->vn, a->index, a->size | (a->u ? 0 : MO_SIGN));
129
- store_reg(s, a->rt, tmp);
130
+ if (!mve_skip_vmov(s, a->vn, a->index, a->size)) {
131
+ tmp = tcg_temp_new_i32();
132
+ read_neon_element32(tmp, a->vn, a->index,
133
+ a->size | (a->u ? 0 : MO_SIGN));
134
+ store_reg(s, a->rt, tmp);
135
+ }
136
137
+ if (dc_isar_feature(aa32_mve, s)) {
138
+ mve_update_and_store_eci(s);
139
+ }
140
return true;
141
}
142
143
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_from_gp(DisasContext *s, arg_VMOV_from_gp *a)
144
return false;
145
}
146
147
+ if (dc_isar_feature(aa32_mve, s)) {
148
+ if (!mve_eci_check(s)) {
149
+ return true;
150
+ }
151
+ }
152
+
153
if (!vfp_access_check(s)) {
154
return true;
155
}
156
157
- tmp = load_reg(s, a->rt);
158
- write_neon_element32(tmp, a->vn, a->index, a->size);
159
- tcg_temp_free_i32(tmp);
160
+ if (!mve_skip_vmov(s, a->vn, a->index, a->size)) {
161
+ tmp = load_reg(s, a->rt);
162
+ write_neon_element32(tmp, a->vn, a->index, a->size);
163
+ tcg_temp_free_i32(tmp);
164
+ }
165
166
+ if (dc_isar_feature(aa32_mve, s)) {
167
+ mve_update_and_store_eci(s);
168
+ }
169
return true;
170
}
171
130
172
--
131
--
173
2.20.1
132
2.34.1
174
133
175
134
diff view generated by jsdifflib
1
Factor the code in full_vfp_access_check() which updates the
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
ownership of the FP context and creates a new FP context
2
3
out into its own function.
3
Following docs/devel/style.rst guidelines, rename
4
4
omap_intr_handler_s -> OMAPIntcState. 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-7-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
Message-id: 20210618141019.10671-6-peter.maydell@linaro.org
8
---
11
---
9
target/arm/translate-vfp.c | 104 +++++++++++++++++++++----------------
12
include/hw/arm/omap.h | 9 ++++-----
10
1 file changed, 58 insertions(+), 46 deletions(-)
13
hw/intc/omap_intc.c | 38 +++++++++++++++++++-------------------
11
14
2 files changed, 23 insertions(+), 24 deletions(-)
12
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
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/translate-vfp.c
18
--- a/include/hw/arm/omap.h
15
+++ b/target/arm/translate-vfp.c
19
+++ b/include/hw/arm/omap.h
16
@@ -XXX,XX +XXX,XX @@ void gen_preserve_fp_state(DisasContext *s)
20
@@ -XXX,XX +XXX,XX @@ void omap_clk_reparent(omap_clk clk, omap_clk parent);
21
22
/* omap_intc.c */
23
#define TYPE_OMAP_INTC "common-omap-intc"
24
-typedef struct omap_intr_handler_s omap_intr_handler;
25
-DECLARE_INSTANCE_CHECKER(omap_intr_handler, OMAP_INTC,
26
- TYPE_OMAP_INTC)
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");
17
}
137
}
18
}
138
}
19
139
20
+/*
140
-void omap_intc_set_iclk(omap_intr_handler *intc, omap_clk clk)
21
+ * Generate code for M-profile FP context handling: update the
141
+void omap_intc_set_iclk(OMAPIntcState *intc, omap_clk clk)
22
+ * ownership of the FP context, and create a new context if
142
{
23
+ * necessary. This corresponds to the parts of the pseudocode
143
intc->iclk = clk;
24
+ * ExecuteFPCheck() after the inital PreserveFPState() call.
144
}
25
+ */
145
26
+static void gen_update_fp_context(DisasContext *s)
146
-void omap_intc_set_fclk(omap_intr_handler *intc, omap_clk clk)
27
+{
147
+void omap_intc_set_fclk(OMAPIntcState *intc, omap_clk clk)
28
+ /* Update ownership of FP context: set FPCCR.S to match current state */
148
{
29
+ if (s->v8m_fpccr_s_wrong) {
149
intc->fclk = clk;
30
+ TCGv_i32 tmp;
150
}
31
+
151
32
+ tmp = load_cpu_field(v7m.fpccr[M_REG_S]);
152
static Property omap_intc_properties[] = {
33
+ if (s->v8m_secure) {
153
- DEFINE_PROP_UINT32("size", struct omap_intr_handler_s, size, 0x100),
34
+ tcg_gen_ori_i32(tmp, tmp, R_V7M_FPCCR_S_MASK);
154
+ DEFINE_PROP_UINT32("size", OMAPIntcState, size, 0x100),
35
+ } else {
155
DEFINE_PROP_END_OF_LIST(),
36
+ tcg_gen_andi_i32(tmp, tmp, ~R_V7M_FPCCR_S_MASK);
156
};
37
+ }
157
38
+ store_cpu_field(tmp, v7m.fpccr[M_REG_S]);
158
@@ -XXX,XX +XXX,XX @@ static const TypeInfo omap_intc_info = {
39
+ /* Don't need to do this for any further FP insns in this TB */
159
static uint64_t omap2_inth_read(void *opaque, hwaddr addr,
40
+ s->v8m_fpccr_s_wrong = false;
160
unsigned size)
41
+ }
161
{
42
+
162
- struct omap_intr_handler_s *s = opaque;
43
+ if (s->v7m_new_fp_ctxt_needed) {
163
+ OMAPIntcState *s = opaque;
44
+ /*
164
int offset = addr;
45
+ * Create new FP context by updating CONTROL.FPCA, CONTROL.SFPA,
165
int bank_no, line_no;
46
+ * the FPSCR, and VPR.
166
struct omap_intr_handler_bank_s *bank = NULL;
47
+ */
167
@@ -XXX,XX +XXX,XX @@ static uint64_t omap2_inth_read(void *opaque, hwaddr addr,
48
+ TCGv_i32 control, fpscr;
168
static void omap2_inth_write(void *opaque, hwaddr addr,
49
+ uint32_t bits = R_V7M_CONTROL_FPCA_MASK;
169
uint64_t value, unsigned size)
50
+
170
{
51
+ fpscr = load_cpu_field(v7m.fpdscr[s->v8m_secure]);
171
- struct omap_intr_handler_s *s = opaque;
52
+ gen_helper_vfp_set_fpscr(cpu_env, fpscr);
172
+ OMAPIntcState *s = opaque;
53
+ tcg_temp_free_i32(fpscr);
173
int offset = addr;
54
+ if (dc_isar_feature(aa32_mve, s)) {
174
int bank_no, line_no;
55
+ TCGv_i32 z32 = tcg_const_i32(0);
175
struct omap_intr_handler_bank_s *bank = NULL;
56
+ store_cpu_field(z32, v7m.vpr);
176
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps omap2_inth_mem_ops = {
57
+ }
177
static void omap2_intc_init(Object *obj)
58
+
178
{
59
+ /*
179
DeviceState *dev = DEVICE(obj);
60
+ * We don't need to arrange to end the TB, because the only
180
- struct omap_intr_handler_s *s = OMAP_INTC(obj);
61
+ * parts of FPSCR which we cache in the TB flags are the VECLEN
181
+ OMAPIntcState *s = OMAP_INTC(obj);
62
+ * and VECSTRIDE, and those don't exist for M-profile.
182
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
63
+ */
183
64
+
184
s->level_only = 1;
65
+ if (s->v8m_secure) {
185
@@ -XXX,XX +XXX,XX @@ static void omap2_intc_init(Object *obj)
66
+ bits |= R_V7M_CONTROL_SFPA_MASK;
186
67
+ }
187
static void omap2_intc_realize(DeviceState *dev, Error **errp)
68
+ control = load_cpu_field(v7m.control[M_REG_S]);
188
{
69
+ tcg_gen_ori_i32(control, control, bits);
189
- struct omap_intr_handler_s *s = OMAP_INTC(dev);
70
+ store_cpu_field(control, v7m.control[M_REG_S]);
190
+ OMAPIntcState *s = OMAP_INTC(dev);
71
+ /* Don't need to do this for any further FP insns in this TB */
191
72
+ s->v7m_new_fp_ctxt_needed = false;
192
if (!s->iclk) {
73
+ }
193
error_setg(errp, "omap2-intc: iclk not connected");
74
+}
194
@@ -XXX,XX +XXX,XX @@ static void omap2_intc_realize(DeviceState *dev, Error **errp)
75
+
195
}
76
/*
196
77
* Check that VFP access is enabled. If it is, do the necessary
197
static Property omap2_intc_properties[] = {
78
* M-profile lazy-FP handling and then return true.
198
- DEFINE_PROP_UINT8("revision", struct omap_intr_handler_s,
79
@@ -XXX,XX +XXX,XX @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
199
+ DEFINE_PROP_UINT8("revision", OMAPIntcState,
80
/* Trigger lazy-state preservation if necessary */
200
revision, 0x21),
81
gen_preserve_fp_state(s);
201
DEFINE_PROP_END_OF_LIST(),
82
202
};
83
- /* Update ownership of FP context: set FPCCR.S to match current state */
203
@@ -XXX,XX +XXX,XX @@ static const TypeInfo omap2_intc_info = {
84
- if (s->v8m_fpccr_s_wrong) {
204
static const TypeInfo omap_intc_type_info = {
85
- TCGv_i32 tmp;
205
.name = TYPE_OMAP_INTC,
86
-
206
.parent = TYPE_SYS_BUS_DEVICE,
87
- tmp = load_cpu_field(v7m.fpccr[M_REG_S]);
207
- .instance_size = sizeof(omap_intr_handler),
88
- if (s->v8m_secure) {
208
+ .instance_size = sizeof(OMAPIntcState),
89
- tcg_gen_ori_i32(tmp, tmp, R_V7M_FPCCR_S_MASK);
209
.abstract = true,
90
- } else {
210
};
91
- tcg_gen_andi_i32(tmp, tmp, ~R_V7M_FPCCR_S_MASK);
211
92
- }
93
- store_cpu_field(tmp, v7m.fpccr[M_REG_S]);
94
- /* Don't need to do this for any further FP insns in this TB */
95
- s->v8m_fpccr_s_wrong = false;
96
- }
97
-
98
- if (s->v7m_new_fp_ctxt_needed) {
99
- /*
100
- * Create new FP context by updating CONTROL.FPCA, CONTROL.SFPA,
101
- * the FPSCR, and VPR.
102
- */
103
- TCGv_i32 control, fpscr;
104
- uint32_t bits = R_V7M_CONTROL_FPCA_MASK;
105
-
106
- fpscr = load_cpu_field(v7m.fpdscr[s->v8m_secure]);
107
- gen_helper_vfp_set_fpscr(cpu_env, fpscr);
108
- tcg_temp_free_i32(fpscr);
109
- if (dc_isar_feature(aa32_mve, s)) {
110
- TCGv_i32 z32 = tcg_const_i32(0);
111
- store_cpu_field(z32, v7m.vpr);
112
- }
113
-
114
- /*
115
- * We don't need to arrange to end the TB, because the only
116
- * parts of FPSCR which we cache in the TB flags are the VECLEN
117
- * and VECSTRIDE, and those don't exist for M-profile.
118
- */
119
-
120
- if (s->v8m_secure) {
121
- bits |= R_V7M_CONTROL_SFPA_MASK;
122
- }
123
- control = load_cpu_field(v7m.control[M_REG_S]);
124
- tcg_gen_ori_i32(control, control, bits);
125
- store_cpu_field(control, v7m.control[M_REG_S]);
126
- /* Don't need to do this for any further FP insns in this TB */
127
- s->v7m_new_fp_ctxt_needed = false;
128
- }
129
+ /* Update ownership of FP context and create new FP context if needed */
130
+ gen_update_fp_context(s);
131
}
132
133
return true;
134
--
212
--
135
2.20.1
213
2.34.1
136
214
137
215
diff view generated by jsdifflib
1
Implement the vector forms of the MVE VQADD and VQSUB insns.
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
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-8-philmd@linaro.org
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-32-peter.maydell@linaro.org
6
---
7
---
7
target/arm/helper-mve.h | 16 ++++++++++++++++
8
hw/arm/stellaris.c | 6 +++---
8
target/arm/mve.decode | 5 +++++
9
1 file changed, 3 insertions(+), 3 deletions(-)
9
target/arm/mve_helper.c | 14 ++++++++++++++
10
target/arm/translate-mve.c | 4 ++++
11
4 files changed, 39 insertions(+)
12
10
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
11
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
14
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
13
--- a/hw/arm/stellaris.c
16
+++ b/target/arm/helper-mve.h
14
+++ b/hw/arm/stellaris.c
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqrdmulhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
15
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_update(stellaris_adc_state *s)
18
DEF_HELPER_FLAGS_4(mve_vqrdmulhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
16
19
DEF_HELPER_FLAGS_4(mve_vqrdmulhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
17
static void stellaris_adc_trigger(void *opaque, int irq, int level)
20
18
{
21
+DEF_HELPER_FLAGS_4(mve_vqaddsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
- stellaris_adc_state *s = (stellaris_adc_state *)opaque;
22
+DEF_HELPER_FLAGS_4(mve_vqaddsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
+ stellaris_adc_state *s = opaque;
23
+DEF_HELPER_FLAGS_4(mve_vqaddsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
int n;
24
+
22
25
+DEF_HELPER_FLAGS_4(mve_vqaddub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
for (n = 0; n < 4; n++) {
26
+DEF_HELPER_FLAGS_4(mve_vqadduh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_reset(stellaris_adc_state *s)
27
+DEF_HELPER_FLAGS_4(mve_vqadduw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
static uint64_t stellaris_adc_read(void *opaque, hwaddr offset,
28
+
26
unsigned size)
29
+DEF_HELPER_FLAGS_4(mve_vqsubsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
{
30
+DEF_HELPER_FLAGS_4(mve_vqsubsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
- stellaris_adc_state *s = (stellaris_adc_state *)opaque;
31
+DEF_HELPER_FLAGS_4(mve_vqsubsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
+ stellaris_adc_state *s = opaque;
32
+
30
33
+DEF_HELPER_FLAGS_4(mve_vqsubub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
/* TODO: Implement this. */
34
+DEF_HELPER_FLAGS_4(mve_vqsubuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
if (offset >= 0x40 && offset < 0xc0) {
35
+DEF_HELPER_FLAGS_4(mve_vqsubuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
@@ -XXX,XX +XXX,XX @@ static uint64_t stellaris_adc_read(void *opaque, hwaddr offset,
36
+
34
static void stellaris_adc_write(void *opaque, hwaddr offset,
37
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
35
uint64_t value, unsigned size)
38
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
36
{
39
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
37
- stellaris_adc_state *s = (stellaris_adc_state *)opaque;
40
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
38
+ stellaris_adc_state *s = opaque;
41
index XXXXXXX..XXXXXXX 100644
39
42
--- a/target/arm/mve.decode
40
/* TODO: Implement this. */
43
+++ b/target/arm/mve.decode
41
if (offset >= 0x40 && offset < 0xc0) {
44
@@ -XXX,XX +XXX,XX @@ VMULL_TU 111 1 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
45
VQDMULH 1110 1111 0 . .. ... 0 ... 0 1011 . 1 . 0 ... 0 @2op
46
VQRDMULH 1111 1111 0 . .. ... 0 ... 0 1011 . 1 . 0 ... 0 @2op
47
48
+VQADD_S 111 0 1111 0 . .. ... 0 ... 0 0000 . 1 . 1 ... 0 @2op
49
+VQADD_U 111 1 1111 0 . .. ... 0 ... 0 0000 . 1 . 1 ... 0 @2op
50
+VQSUB_S 111 0 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
51
+VQSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
52
+
53
# Vector miscellaneous
54
55
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
56
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/mve_helper.c
59
+++ b/target/arm/mve_helper.c
60
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT(vqrdmulhb, 1, int8_t, DO_QRDMULH_B)
61
DO_2OP_SAT(vqrdmulhh, 2, int16_t, DO_QRDMULH_H)
62
DO_2OP_SAT(vqrdmulhw, 4, int32_t, DO_QRDMULH_W)
63
64
+DO_2OP_SAT(vqaddub, 1, uint8_t, DO_UQADD_B)
65
+DO_2OP_SAT(vqadduh, 2, uint16_t, DO_UQADD_H)
66
+DO_2OP_SAT(vqadduw, 4, uint32_t, DO_UQADD_W)
67
+DO_2OP_SAT(vqaddsb, 1, int8_t, DO_SQADD_B)
68
+DO_2OP_SAT(vqaddsh, 2, int16_t, DO_SQADD_H)
69
+DO_2OP_SAT(vqaddsw, 4, int32_t, DO_SQADD_W)
70
+
71
+DO_2OP_SAT(vqsubub, 1, uint8_t, DO_UQSUB_B)
72
+DO_2OP_SAT(vqsubuh, 2, uint16_t, DO_UQSUB_H)
73
+DO_2OP_SAT(vqsubuw, 4, uint32_t, DO_UQSUB_W)
74
+DO_2OP_SAT(vqsubsb, 1, int8_t, DO_SQSUB_B)
75
+DO_2OP_SAT(vqsubsh, 2, int16_t, DO_SQSUB_H)
76
+DO_2OP_SAT(vqsubsw, 4, int32_t, DO_SQSUB_W)
77
+
78
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
79
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
80
uint32_t rm) \
81
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
82
index XXXXXXX..XXXXXXX 100644
83
--- a/target/arm/translate-mve.c
84
+++ b/target/arm/translate-mve.c
85
@@ -XXX,XX +XXX,XX @@ DO_2OP(VMULL_TS, vmullts)
86
DO_2OP(VMULL_TU, vmulltu)
87
DO_2OP(VQDMULH, vqdmulh)
88
DO_2OP(VQRDMULH, vqrdmulh)
89
+DO_2OP(VQADD_S, vqadds)
90
+DO_2OP(VQADD_U, vqaddu)
91
+DO_2OP(VQSUB_S, vqsubs)
92
+DO_2OP(VQSUB_U, vqsubu)
93
94
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
95
MVEGenTwoOpScalarFn fn)
96
--
42
--
97
2.20.1
43
2.34.1
98
44
99
45
diff view generated by jsdifflib
1
Implement the MVE VMLALDAV insn, which multiplies pairs of integer
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
elements, accumulating them into a 64-bit result in a pair of
3
general-purpose registers.
4
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
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
Message-id: 20210617121628.20116-20-peter.maydell@linaro.org
8
---
11
---
9
target/arm/helper-mve.h | 8 ++++
12
hw/arm/stellaris.c | 73 +++++++++++++++++++++++-----------------------
10
target/arm/translate.h | 10 ++++
13
1 file changed, 36 insertions(+), 37 deletions(-)
11
target/arm/mve.decode | 15 ++++++
12
target/arm/mve_helper.c | 34 ++++++++++++++
13
target/arm/translate-mve.c | 96 ++++++++++++++++++++++++++++++++++++++
14
5 files changed, 163 insertions(+)
15
14
16
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
17
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/helper-mve.h
17
--- a/hw/arm/stellaris.c
19
+++ b/target/arm/helper-mve.h
18
+++ b/hw/arm/stellaris.c
20
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmulltsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
@@ -XXX,XX +XXX,XX @@ static void stellaris_i2c_init(Object *obj)
21
DEF_HELPER_FLAGS_4(mve_vmulltub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
#define STELLARIS_ADC_FIFO_FULL 0x1000
22
DEF_HELPER_FLAGS_4(mve_vmulltuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
23
DEF_HELPER_FLAGS_4(mve_vmulltuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
#define TYPE_STELLARIS_ADC "stellaris-adc"
24
+
23
-typedef struct StellarisADCState stellaris_adc_state;
25
+DEF_HELPER_FLAGS_4(mve_vmlaldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
24
-DECLARE_INSTANCE_CHECKER(stellaris_adc_state, STELLARIS_ADC,
26
+DEF_HELPER_FLAGS_4(mve_vmlaldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
25
- TYPE_STELLARIS_ADC)
27
+DEF_HELPER_FLAGS_4(mve_vmlaldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
26
+typedef struct StellarisADCState StellarisADCState;
28
+DEF_HELPER_FLAGS_4(mve_vmlaldavxsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
27
+DECLARE_INSTANCE_CHECKER(StellarisADCState, STELLARIS_ADC, TYPE_STELLARIS_ADC)
29
+
28
30
+DEF_HELPER_FLAGS_4(mve_vmlaldavuh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
29
struct StellarisADCState {
31
+DEF_HELPER_FLAGS_4(mve_vmlaldavuw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
30
SysBusDevice parent_obj;
32
diff --git a/target/arm/translate.h b/target/arm/translate.h
31
@@ -XXX,XX +XXX,XX @@ struct StellarisADCState {
33
index XXXXXXX..XXXXXXX 100644
32
qemu_irq irq[4];
34
--- a/target/arm/translate.h
33
};
35
+++ b/target/arm/translate.h
34
36
@@ -XXX,XX +XXX,XX @@ static inline int negate(DisasContext *s, int x)
35
-static uint32_t stellaris_adc_fifo_read(stellaris_adc_state *s, int n)
37
return -x;
36
+static uint32_t stellaris_adc_fifo_read(StellarisADCState *s, int n)
37
{
38
int tail;
39
40
@@ -XXX,XX +XXX,XX @@ static uint32_t stellaris_adc_fifo_read(stellaris_adc_state *s, int n)
41
return s->fifo[n].data[tail];
38
}
42
}
39
43
40
+static inline int plus_1(DisasContext *s, int x)
44
-static void stellaris_adc_fifo_write(stellaris_adc_state *s, int n,
41
+{
45
+static void stellaris_adc_fifo_write(StellarisADCState *s, int n,
42
+ return x + 1;
46
uint32_t value)
43
+}
44
+
45
static inline int plus_2(DisasContext *s, int x)
46
{
47
{
47
return x + 2;
48
int head;
48
@@ -XXX,XX +XXX,XX @@ static inline int times_4(DisasContext *s, int x)
49
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_fifo_write(stellaris_adc_state *s, int n,
49
return x * 4;
50
s->fifo[n].state |= STELLARIS_ADC_FIFO_FULL;
50
}
51
}
51
52
52
+static inline int times_2_plus_1(DisasContext *s, int x)
53
-static void stellaris_adc_update(stellaris_adc_state *s)
53
+{
54
+static void stellaris_adc_update(StellarisADCState *s)
54
+ return x * 2 + 1;
55
+}
56
+
57
static inline int arm_dc_feature(DisasContext *dc, int feature)
58
{
55
{
59
return (dc->features & (1ULL << feature)) != 0;
56
int level;
60
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
57
int n;
61
index XXXXXXX..XXXXXXX 100644
58
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_update(stellaris_adc_state *s)
62
--- a/target/arm/mve.decode
59
63
+++ b/target/arm/mve.decode
60
static void stellaris_adc_trigger(void *opaque, int irq, int level)
64
@@ -XXX,XX +XXX,XX @@ VNEG_fp 1111 1111 1 . 11 .. 01 ... 0 0111 11 . 0 ... 0 @1op
61
{
65
VDUP 1110 1110 1 1 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=0
62
- stellaris_adc_state *s = opaque;
66
VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 1 1 0000 @vdup size=1
63
+ StellarisADCState *s = opaque;
67
VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=2
64
int n;
68
+
65
69
+# multiply-add long dual accumulate
66
for (n = 0; n < 4; n++) {
70
+# rdahi: bits [3:1] from insn, bit 0 is 1
67
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_trigger(void *opaque, int irq, int level)
71
+# rdalo: bits [3:1] from insn, bit 0 is 0
72
+%rdahi 20:3 !function=times_2_plus_1
73
+%rdalo 13:3 !function=times_2
74
+# size bit is 0 for 16 bit, 1 for 32 bit
75
+%size_16 16:1 !function=plus_1
76
+
77
+&vmlaldav rdahi rdalo size qn qm x a
78
+
79
+@vmlaldav .... .... . ... ... . ... . .... .... qm:3 . \
80
+ qn=%qn rdahi=%rdahi rdalo=%rdalo size=%size_16 &vmlaldav
81
+VMLALDAV_S 1110 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 0 @vmlaldav
82
+VMLALDAV_U 1111 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 0 @vmlaldav
83
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/target/arm/mve_helper.c
86
+++ b/target/arm/mve_helper.c
87
@@ -XXX,XX +XXX,XX @@ DO_2OP_S(vhadds, do_vhadd_s)
88
DO_2OP_U(vhaddu, do_vhadd_u)
89
DO_2OP_S(vhsubs, do_vhsub_s)
90
DO_2OP_U(vhsubu, do_vhsub_u)
91
+
92
+
93
+/*
94
+ * Multiply add long dual accumulate ops.
95
+ */
96
+#define DO_LDAV(OP, ESIZE, TYPE, XCHG, EVENACC, ODDACC) \
97
+ uint64_t HELPER(glue(mve_, OP))(CPUARMState *env, void *vn, \
98
+ void *vm, uint64_t a) \
99
+ { \
100
+ uint16_t mask = mve_element_mask(env); \
101
+ unsigned e; \
102
+ TYPE *n = vn, *m = vm; \
103
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
104
+ if (mask & 1) { \
105
+ if (e & 1) { \
106
+ a ODDACC \
107
+ (int64_t)n[H##ESIZE(e - 1 * XCHG)] * m[H##ESIZE(e)]; \
108
+ } else { \
109
+ a EVENACC \
110
+ (int64_t)n[H##ESIZE(e + 1 * XCHG)] * m[H##ESIZE(e)]; \
111
+ } \
112
+ } \
113
+ } \
114
+ mve_advance_vpt(env); \
115
+ return a; \
116
+ }
117
+
118
+DO_LDAV(vmlaldavsh, 2, int16_t, false, +=, +=)
119
+DO_LDAV(vmlaldavxsh, 2, int16_t, true, +=, +=)
120
+DO_LDAV(vmlaldavsw, 4, int32_t, false, +=, +=)
121
+DO_LDAV(vmlaldavxsw, 4, int32_t, true, +=, +=)
122
+
123
+DO_LDAV(vmlaldavuh, 2, uint16_t, false, +=, +=)
124
+DO_LDAV(vmlaldavuw, 4, uint32_t, false, +=, +=)
125
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
126
index XXXXXXX..XXXXXXX 100644
127
--- a/target/arm/translate-mve.c
128
+++ b/target/arm/translate-mve.c
129
@@ -XXX,XX +XXX,XX @@
130
typedef void MVEGenLdStFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
131
typedef void MVEGenOneOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
132
typedef void MVEGenTwoOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr);
133
+typedef void MVEGenDualAccOpFn(TCGv_i64, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i64);
134
135
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
136
static inline long mve_qreg_offset(unsigned reg)
137
@@ -XXX,XX +XXX,XX @@ static void mve_update_eci(DisasContext *s)
138
}
68
}
139
}
69
}
140
70
141
+static bool mve_skip_first_beat(DisasContext *s)
71
-static void stellaris_adc_reset(stellaris_adc_state *s)
142
+{
72
+static void stellaris_adc_reset(StellarisADCState *s)
143
+ /* Return true if PSR.ECI says we must skip the first beat of this insn */
144
+ switch (s->eci) {
145
+ case ECI_NONE:
146
+ return false;
147
+ case ECI_A0:
148
+ case ECI_A0A1:
149
+ case ECI_A0A1A2:
150
+ case ECI_A0A1A2B0:
151
+ return true;
152
+ default:
153
+ g_assert_not_reached();
154
+ }
155
+}
156
+
157
static bool do_ldst(DisasContext *s, arg_VLDR_VSTR *a, MVEGenLdStFn *fn)
158
{
73
{
159
TCGv_i32 addr;
74
int n;
160
@@ -XXX,XX +XXX,XX @@ DO_2OP(VMULL_BS, vmullbs)
75
161
DO_2OP(VMULL_BU, vmullbu)
76
@@ -XXX,XX +XXX,XX @@ static void stellaris_adc_reset(stellaris_adc_state *s)
162
DO_2OP(VMULL_TS, vmullts)
77
static uint64_t stellaris_adc_read(void *opaque, hwaddr offset,
163
DO_2OP(VMULL_TU, vmulltu)
78
unsigned size)
164
+
79
{
165
+static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
80
- stellaris_adc_state *s = opaque;
166
+ MVEGenDualAccOpFn *fn)
81
+ StellarisADCState *s = opaque;
167
+{
82
168
+ TCGv_ptr qn, qm;
83
/* TODO: Implement this. */
169
+ TCGv_i64 rda;
84
if (offset >= 0x40 && offset < 0xc0) {
170
+ TCGv_i32 rdalo, rdahi;
85
@@ -XXX,XX +XXX,XX @@ static uint64_t stellaris_adc_read(void *opaque, hwaddr offset,
171
+
86
static void stellaris_adc_write(void *opaque, hwaddr offset,
172
+ if (!dc_isar_feature(aa32_mve, s) ||
87
uint64_t value, unsigned size)
173
+ !mve_check_qreg_bank(s, a->qn | a->qm) ||
88
{
174
+ !fn) {
89
- stellaris_adc_state *s = opaque;
175
+ return false;
90
+ StellarisADCState *s = opaque;
176
+ }
91
177
+ /*
92
/* TODO: Implement this. */
178
+ * rdahi == 13 is UNPREDICTABLE; rdahi == 15 is a related
93
if (offset >= 0x40 && offset < 0xc0) {
179
+ * encoding; rdalo always has bit 0 clear so cannot be 13 or 15.
94
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_stellaris_adc = {
180
+ */
95
.version_id = 1,
181
+ if (a->rdahi == 13 || a->rdahi == 15) {
96
.minimum_version_id = 1,
182
+ return false;
97
.fields = (VMStateField[]) {
183
+ }
98
- VMSTATE_UINT32(actss, stellaris_adc_state),
184
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
99
- VMSTATE_UINT32(ris, stellaris_adc_state),
185
+ return true;
100
- VMSTATE_UINT32(im, stellaris_adc_state),
186
+ }
101
- VMSTATE_UINT32(emux, stellaris_adc_state),
187
+
102
- VMSTATE_UINT32(ostat, stellaris_adc_state),
188
+ qn = mve_qreg_ptr(a->qn);
103
- VMSTATE_UINT32(ustat, stellaris_adc_state),
189
+ qm = mve_qreg_ptr(a->qm);
104
- VMSTATE_UINT32(sspri, stellaris_adc_state),
190
+
105
- VMSTATE_UINT32(sac, stellaris_adc_state),
191
+ /*
106
- VMSTATE_UINT32(fifo[0].state, stellaris_adc_state),
192
+ * This insn is subject to beat-wise execution. Partial execution
107
- VMSTATE_UINT32_ARRAY(fifo[0].data, stellaris_adc_state, 16),
193
+ * of an A=0 (no-accumulate) insn which does not execute the first
108
- VMSTATE_UINT32(ssmux[0], stellaris_adc_state),
194
+ * beat must start with the current rda value, not 0.
109
- VMSTATE_UINT32(ssctl[0], stellaris_adc_state),
195
+ */
110
- VMSTATE_UINT32(fifo[1].state, stellaris_adc_state),
196
+ if (a->a || mve_skip_first_beat(s)) {
111
- VMSTATE_UINT32_ARRAY(fifo[1].data, stellaris_adc_state, 16),
197
+ rda = tcg_temp_new_i64();
112
- VMSTATE_UINT32(ssmux[1], stellaris_adc_state),
198
+ rdalo = load_reg(s, a->rdalo);
113
- VMSTATE_UINT32(ssctl[1], stellaris_adc_state),
199
+ rdahi = load_reg(s, a->rdahi);
114
- VMSTATE_UINT32(fifo[2].state, stellaris_adc_state),
200
+ tcg_gen_concat_i32_i64(rda, rdalo, rdahi);
115
- VMSTATE_UINT32_ARRAY(fifo[2].data, stellaris_adc_state, 16),
201
+ tcg_temp_free_i32(rdalo);
116
- VMSTATE_UINT32(ssmux[2], stellaris_adc_state),
202
+ tcg_temp_free_i32(rdahi);
117
- VMSTATE_UINT32(ssctl[2], stellaris_adc_state),
203
+ } else {
118
- VMSTATE_UINT32(fifo[3].state, stellaris_adc_state),
204
+ rda = tcg_const_i64(0);
119
- VMSTATE_UINT32_ARRAY(fifo[3].data, stellaris_adc_state, 16),
205
+ }
120
- VMSTATE_UINT32(ssmux[3], stellaris_adc_state),
206
+
121
- VMSTATE_UINT32(ssctl[3], stellaris_adc_state),
207
+ fn(rda, cpu_env, qn, qm, rda);
122
- VMSTATE_UINT32(noise, stellaris_adc_state),
208
+ tcg_temp_free_ptr(qn);
123
+ VMSTATE_UINT32(actss, StellarisADCState),
209
+ tcg_temp_free_ptr(qm);
124
+ VMSTATE_UINT32(ris, StellarisADCState),
210
+
125
+ VMSTATE_UINT32(im, StellarisADCState),
211
+ rdalo = tcg_temp_new_i32();
126
+ VMSTATE_UINT32(emux, StellarisADCState),
212
+ rdahi = tcg_temp_new_i32();
127
+ VMSTATE_UINT32(ostat, StellarisADCState),
213
+ tcg_gen_extrl_i64_i32(rdalo, rda);
128
+ VMSTATE_UINT32(ustat, StellarisADCState),
214
+ tcg_gen_extrh_i64_i32(rdahi, rda);
129
+ VMSTATE_UINT32(sspri, StellarisADCState),
215
+ store_reg(s, a->rdalo, rdalo);
130
+ VMSTATE_UINT32(sac, StellarisADCState),
216
+ store_reg(s, a->rdahi, rdahi);
131
+ VMSTATE_UINT32(fifo[0].state, StellarisADCState),
217
+ tcg_temp_free_i64(rda);
132
+ VMSTATE_UINT32_ARRAY(fifo[0].data, StellarisADCState, 16),
218
+ mve_update_eci(s);
133
+ VMSTATE_UINT32(ssmux[0], StellarisADCState),
219
+ return true;
134
+ VMSTATE_UINT32(ssctl[0], StellarisADCState),
220
+}
135
+ VMSTATE_UINT32(fifo[1].state, StellarisADCState),
221
+
136
+ VMSTATE_UINT32_ARRAY(fifo[1].data, StellarisADCState, 16),
222
+static bool trans_VMLALDAV_S(DisasContext *s, arg_vmlaldav *a)
137
+ VMSTATE_UINT32(ssmux[1], StellarisADCState),
223
+{
138
+ VMSTATE_UINT32(ssctl[1], StellarisADCState),
224
+ static MVEGenDualAccOpFn * const fns[4][2] = {
139
+ VMSTATE_UINT32(fifo[2].state, StellarisADCState),
225
+ { NULL, NULL },
140
+ VMSTATE_UINT32_ARRAY(fifo[2].data, StellarisADCState, 16),
226
+ { gen_helper_mve_vmlaldavsh, gen_helper_mve_vmlaldavxsh },
141
+ VMSTATE_UINT32(ssmux[2], StellarisADCState),
227
+ { gen_helper_mve_vmlaldavsw, gen_helper_mve_vmlaldavxsw },
142
+ VMSTATE_UINT32(ssctl[2], StellarisADCState),
228
+ { NULL, NULL },
143
+ VMSTATE_UINT32(fifo[3].state, StellarisADCState),
229
+ };
144
+ VMSTATE_UINT32_ARRAY(fifo[3].data, StellarisADCState, 16),
230
+ return do_long_dual_acc(s, a, fns[a->size][a->x]);
145
+ VMSTATE_UINT32(ssmux[3], StellarisADCState),
231
+}
146
+ VMSTATE_UINT32(ssctl[3], StellarisADCState),
232
+
147
+ VMSTATE_UINT32(noise, StellarisADCState),
233
+static bool trans_VMLALDAV_U(DisasContext *s, arg_vmlaldav *a)
148
VMSTATE_END_OF_LIST()
234
+{
149
}
235
+ static MVEGenDualAccOpFn * const fns[4][2] = {
150
};
236
+ { NULL, NULL },
151
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_stellaris_adc = {
237
+ { gen_helper_mve_vmlaldavuh, NULL },
152
static void stellaris_adc_init(Object *obj)
238
+ { gen_helper_mve_vmlaldavuw, NULL },
153
{
239
+ { NULL, NULL },
154
DeviceState *dev = DEVICE(obj);
240
+ };
155
- stellaris_adc_state *s = STELLARIS_ADC(obj);
241
+ return do_long_dual_acc(s, a, fns[a->size][a->x]);
156
+ StellarisADCState *s = STELLARIS_ADC(obj);
242
+}
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
};
243
--
169
--
244
2.20.1
170
2.34.1
245
171
246
172
diff view generated by jsdifflib
1
Implement the MVE VQDMULL scalar insn. This multiplies the top or
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
bottom half of each element by the scalar, doubles and saturates
3
to a double-width result.
4
2
5
Note that this encoding overlaps with VQADD and VQSUB; it uses
3
The typedef and definitions are generated by the OBJECT_DECLARE_TYPE
6
what in VQADD and VQSUB would be the 'size=0b11' encoding.
4
macro in "hw/arm/bcm2836.h":
7
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
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210617121628.20116-30-peter.maydell@linaro.org
11
---
17
---
12
target/arm/helper-mve.h | 5 +++
18
hw/arm/bcm2836.c | 9 ++-------
13
target/arm/mve.decode | 23 +++++++++++---
19
1 file changed, 2 insertions(+), 7 deletions(-)
14
target/arm/mve_helper.c | 65 ++++++++++++++++++++++++++++++++++++++
15
target/arm/translate-mve.c | 30 ++++++++++++++++++
16
4 files changed, 119 insertions(+), 4 deletions(-)
17
20
18
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
19
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper-mve.h
23
--- a/hw/arm/bcm2836.c
21
+++ b/target/arm/helper-mve.h
24
+++ b/hw/arm/bcm2836.c
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vbrsrb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
23
DEF_HELPER_FLAGS_4(mve_vbrsrh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
DEF_HELPER_FLAGS_4(mve_vbrsrw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
26
+DEF_HELPER_FLAGS_4(mve_vqdmullb_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
27
+DEF_HELPER_FLAGS_4(mve_vqdmullb_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
28
+DEF_HELPER_FLAGS_4(mve_vqdmullt_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
29
+DEF_HELPER_FLAGS_4(mve_vqdmullt_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
30
+
31
DEF_HELPER_FLAGS_4(mve_vmlaldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
32
DEF_HELPER_FLAGS_4(mve_vmlaldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
33
DEF_HELPER_FLAGS_4(mve_vmlaldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
34
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/mve.decode
37
+++ b/target/arm/mve.decode
38
@@ -XXX,XX +XXX,XX @@
25
@@ -XXX,XX +XXX,XX @@
39
%qm 5:1 1:3
26
#include "hw/arm/raspi_platform.h"
40
%qn 7:1 17:3
27
#include "hw/sysbus.h"
41
28
42
+# VQDMULL has size in bit 28: 0 for 16 bit, 1 for 32 bit
29
-typedef struct BCM283XClass {
43
+%size_28 28:1 !function=plus_1
30
+struct BCM283XClass {
44
+
31
/*< private >*/
45
&vldr_vstr rn qd imm p a w size l u
32
DeviceClass parent_class;
46
&1op qd qm size
33
/*< public >*/
47
&2op qd qm qn size
34
@@ -XXX,XX +XXX,XX @@ typedef struct BCM283XClass {
48
@@ -XXX,XX +XXX,XX @@
35
hwaddr peri_base; /* Peripheral base address seen by the CPU */
49
@2op_nosz .... .... .... .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn size=0
36
hwaddr ctrl_base; /* Interrupt controller and mailboxes etc. */
50
37
int clusterid;
51
@2scalar .... .... .. size:2 .... .... .... .... rm:4 &2scalar qd=%qd qn=%qn
38
-} BCM283XClass;
52
+@2scalar_nosz .... .... .... .... .... .... .... rm:4 &2scalar qd=%qd qn=%qn
39
-
53
40
-#define BCM283X_CLASS(klass) \
54
# Vector loads and stores
41
- OBJECT_CLASS_CHECK(BCM283XClass, (klass), TYPE_BCM283X)
55
42
-#define BCM283X_GET_CLASS(obj) \
56
@@ -XXX,XX +XXX,XX @@ VHADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
43
- OBJECT_GET_CLASS(BCM283XClass, (obj), TYPE_BCM283X)
57
VHSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
44
+};
58
VHSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
45
59
46
static Property bcm2836_enabled_cores_property =
60
-VQADD_S_scalar 1110 1110 0 . .. ... 0 ... 0 1111 . 110 .... @2scalar
47
DEFINE_PROP_UINT32("enabled-cpus", BCM283XState, enabled_cpus, 0);
61
-VQADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 110 .... @2scalar
62
-VQSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
63
-VQSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
64
+{
65
+ VQADD_S_scalar 1110 1110 0 . .. ... 0 ... 0 1111 . 110 .... @2scalar
66
+ VQADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 110 .... @2scalar
67
+ VQDMULLB_scalar 111 . 1110 0 . 11 ... 0 ... 0 1111 . 110 .... @2scalar_nosz \
68
+ size=%size_28
69
+}
70
+
71
+{
72
+ VQSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
73
+ VQSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
74
+ VQDMULLT_scalar 111 . 1110 0 . 11 ... 0 ... 1 1111 . 110 .... @2scalar_nosz \
75
+ size=%size_28
76
+}
77
+
78
VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
79
80
VQDMULH_scalar 1110 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
81
VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
82
83
+
84
# Predicate operations
85
%mask_22_13 22:1 13:3
86
VPST 1111 1110 0 . 11 000 1 ... 0 1111 0100 1101 mask=%mask_22_13
87
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
88
index XXXXXXX..XXXXXXX 100644
89
--- a/target/arm/mve_helper.c
90
+++ b/target/arm/mve_helper.c
91
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT_SCALAR(vqrdmulh_scalarb, 1, int8_t, DO_QRDMULH_B)
92
DO_2OP_SAT_SCALAR(vqrdmulh_scalarh, 2, int16_t, DO_QRDMULH_H)
93
DO_2OP_SAT_SCALAR(vqrdmulh_scalarw, 4, int32_t, DO_QRDMULH_W)
94
95
+/*
96
+ * Long saturating scalar ops. As with DO_2OP_L, TYPE and H are for the
97
+ * input (smaller) type and LESIZE, LTYPE, LH for the output (long) type.
98
+ * SATMASK specifies which bits of the predicate mask matter for determining
99
+ * whether to propagate a saturation indication into FPSCR.QC -- for
100
+ * the 16x16->32 case we must check only the bit corresponding to the T or B
101
+ * half that we used, but for the 32x32->64 case we propagate if the mask
102
+ * bit is set for either half.
103
+ */
104
+#define DO_2OP_SAT_SCALAR_L(OP, TOP, ESIZE, TYPE, LESIZE, LTYPE, FN, SATMASK) \
105
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
106
+ uint32_t rm) \
107
+ { \
108
+ LTYPE *d = vd; \
109
+ TYPE *n = vn; \
110
+ TYPE m = rm; \
111
+ uint16_t mask = mve_element_mask(env); \
112
+ unsigned le; \
113
+ bool qc = false; \
114
+ for (le = 0; le < 16 / LESIZE; le++, mask >>= LESIZE) { \
115
+ bool sat = false; \
116
+ LTYPE r = FN((LTYPE)n[H##ESIZE(le * 2 + TOP)], m, &sat); \
117
+ mergemask(&d[H##LESIZE(le)], r, mask); \
118
+ qc |= sat && (mask & SATMASK); \
119
+ } \
120
+ if (qc) { \
121
+ env->vfp.qc[0] = qc; \
122
+ } \
123
+ mve_advance_vpt(env); \
124
+ }
125
+
126
+static inline int32_t do_qdmullh(int16_t n, int16_t m, bool *sat)
127
+{
128
+ int64_t r = ((int64_t)n * m) * 2;
129
+ return do_sat_bhw(r, INT32_MIN, INT32_MAX, sat);
130
+}
131
+
132
+static inline int64_t do_qdmullw(int32_t n, int32_t m, bool *sat)
133
+{
134
+ /* The multiply can't overflow, but the doubling might */
135
+ int64_t r = (int64_t)n * m;
136
+ if (r > INT64_MAX / 2) {
137
+ *sat = true;
138
+ return INT64_MAX;
139
+ } else if (r < INT64_MIN / 2) {
140
+ *sat = true;
141
+ return INT64_MIN;
142
+ } else {
143
+ return r * 2;
144
+ }
145
+}
146
+
147
+#define SATMASK16B 1
148
+#define SATMASK16T (1 << 2)
149
+#define SATMASK32 ((1 << 4) | 1)
150
+
151
+DO_2OP_SAT_SCALAR_L(vqdmullb_scalarh, 0, 2, int16_t, 4, int32_t, \
152
+ do_qdmullh, SATMASK16B)
153
+DO_2OP_SAT_SCALAR_L(vqdmullb_scalarw, 0, 4, int32_t, 8, int64_t, \
154
+ do_qdmullw, SATMASK32)
155
+DO_2OP_SAT_SCALAR_L(vqdmullt_scalarh, 1, 2, int16_t, 4, int32_t, \
156
+ do_qdmullh, SATMASK16T)
157
+DO_2OP_SAT_SCALAR_L(vqdmullt_scalarw, 1, 4, int32_t, 8, int64_t, \
158
+ do_qdmullw, SATMASK32)
159
+
160
static inline uint32_t do_vbrsrb(uint32_t n, uint32_t m)
161
{
162
m &= 0xff;
163
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
164
index XXXXXXX..XXXXXXX 100644
165
--- a/target/arm/translate-mve.c
166
+++ b/target/arm/translate-mve.c
167
@@ -XXX,XX +XXX,XX @@ DO_2OP_SCALAR(VQDMULH_scalar, vqdmulh_scalar)
168
DO_2OP_SCALAR(VQRDMULH_scalar, vqrdmulh_scalar)
169
DO_2OP_SCALAR(VBRSR, vbrsr)
170
171
+static bool trans_VQDMULLB_scalar(DisasContext *s, arg_2scalar *a)
172
+{
173
+ static MVEGenTwoOpScalarFn * const fns[] = {
174
+ NULL,
175
+ gen_helper_mve_vqdmullb_scalarh,
176
+ gen_helper_mve_vqdmullb_scalarw,
177
+ NULL,
178
+ };
179
+ if (a->qd == a->qn && a->size == MO_32) {
180
+ /* UNPREDICTABLE; we choose to undef */
181
+ return false;
182
+ }
183
+ return do_2op_scalar(s, a, fns[a->size]);
184
+}
185
+
186
+static bool trans_VQDMULLT_scalar(DisasContext *s, arg_2scalar *a)
187
+{
188
+ static MVEGenTwoOpScalarFn * const fns[] = {
189
+ NULL,
190
+ gen_helper_mve_vqdmullt_scalarh,
191
+ gen_helper_mve_vqdmullt_scalarw,
192
+ NULL,
193
+ };
194
+ if (a->qd == a->qn && a->size == MO_32) {
195
+ /* UNPREDICTABLE; we choose to undef */
196
+ return false;
197
+ }
198
+ return do_2op_scalar(s, a, fns[a->size]);
199
+}
200
+
201
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
202
MVEGenDualAccOpFn *fn)
203
{
204
--
48
--
205
2.20.1
49
2.34.1
206
50
207
51
diff view generated by jsdifflib
1
Implement the MVE VQDMULH and VQRDMULH scalar insns, which multiply
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
elements by the scalar, double, possibly round, take the high half
2
3
and saturate.
3
NPCM7XX models have been commited after the conversion from
4
4
commit 8063396bf3 ("Use OBJECT_DECLARE_SIMPLE_TYPE when possible").
5
Manually convert them.
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-11-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
Message-id: 20210617121628.20116-29-peter.maydell@linaro.org
8
---
11
---
9
target/arm/helper-mve.h | 8 ++++++++
12
include/hw/adc/npcm7xx_adc.h | 7 +++----
10
target/arm/mve.decode | 3 +++
13
include/hw/arm/npcm7xx.h | 18 ++++++------------
11
target/arm/mve_helper.c | 25 +++++++++++++++++++++++++
14
include/hw/i2c/npcm7xx_smbus.h | 7 +++----
12
target/arm/translate-mve.c | 2 ++
15
include/hw/misc/npcm7xx_clk.h | 2 +-
13
4 files changed, 38 insertions(+)
16
include/hw/misc/npcm7xx_gcr.h | 6 +++---
14
17
include/hw/misc/npcm7xx_mft.h | 7 +++----
15
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
18
include/hw/misc/npcm7xx_pwm.h | 3 +--
16
index XXXXXXX..XXXXXXX 100644
19
include/hw/misc/npcm7xx_rng.h | 6 +++---
17
--- a/target/arm/helper-mve.h
20
include/hw/net/npcm7xx_emc.h | 5 +----
18
+++ b/target/arm/helper-mve.h
21
include/hw/sd/npcm7xx_sdhci.h | 4 ++--
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqsubu_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
22
10 files changed, 26 insertions(+), 39 deletions(-)
20
DEF_HELPER_FLAGS_4(mve_vqsubu_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
23
21
DEF_HELPER_FLAGS_4(mve_vqsubu_scalarw, 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
22
25
index XXXXXXX..XXXXXXX 100644
23
+DEF_HELPER_FLAGS_4(mve_vqdmulh_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
26
--- a/include/hw/adc/npcm7xx_adc.h
24
+DEF_HELPER_FLAGS_4(mve_vqdmulh_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
27
+++ b/include/hw/adc/npcm7xx_adc.h
25
+DEF_HELPER_FLAGS_4(mve_vqdmulh_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
28
@@ -XXX,XX +XXX,XX @@
26
+
29
* @iref: The internal reference voltage, initialized at launch time.
27
+DEF_HELPER_FLAGS_4(mve_vqrdmulh_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
30
* @rv: The calibrated output values of 0.5V and 1.5V for the ADC.
28
+DEF_HELPER_FLAGS_4(mve_vqrdmulh_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
*/
29
+DEF_HELPER_FLAGS_4(mve_vqrdmulh_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
32
-typedef struct {
30
+
33
+struct NPCM7xxADCState {
31
DEF_HELPER_FLAGS_4(mve_vbrsrb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
34
SysBusDevice parent;
32
DEF_HELPER_FLAGS_4(mve_vbrsrh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
35
33
DEF_HELPER_FLAGS_4(mve_vbrsrw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
36
MemoryRegion iomem;
34
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
37
@@ -XXX,XX +XXX,XX @@ typedef struct {
35
index XXXXXXX..XXXXXXX 100644
38
uint32_t iref;
36
--- a/target/arm/mve.decode
39
37
+++ b/target/arm/mve.decode
40
uint16_t calibration_r_values[NPCM7XX_ADC_NUM_CALIB];
38
@@ -XXX,XX +XXX,XX @@ VQSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
41
-} NPCM7xxADCState;
39
VQSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 110 .... @2scalar
42
+};
40
VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
43
41
44
#define TYPE_NPCM7XX_ADC "npcm7xx-adc"
42
+VQDMULH_scalar 1110 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
45
-#define NPCM7XX_ADC(obj) \
43
+VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
46
- OBJECT_CHECK(NPCM7xxADCState, (obj), TYPE_NPCM7XX_ADC)
44
+
47
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxADCState, NPCM7XX_ADC)
45
# Predicate operations
48
46
%mask_22_13 22:1 13:3
49
#endif /* NPCM7XX_ADC_H */
47
VPST 1111 1110 0 . 11 000 1 ... 0 1111 0100 1101 mask=%mask_22_13
50
diff --git a/include/hw/arm/npcm7xx.h b/include/hw/arm/npcm7xx.h
48
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
51
index XXXXXXX..XXXXXXX 100644
49
index XXXXXXX..XXXXXXX 100644
52
--- a/include/hw/arm/npcm7xx.h
50
--- a/target/arm/mve_helper.c
53
+++ b/include/hw/arm/npcm7xx.h
51
+++ b/target/arm/mve_helper.c
54
@@ -XXX,XX +XXX,XX @@
52
@@ -XXX,XX +XXX,XX @@ static inline int32_t do_sat_bhw(int64_t val, int64_t min, int64_t max, bool *s)
55
53
#define DO_UQSUB_H(n, m, s) do_sat_bhw((int64_t)n - m, 0, UINT16_MAX, s)
56
#define NPCM7XX_NR_PWM_MODULES 2
54
#define DO_UQSUB_W(n, m, s) do_sat_bhw((int64_t)n - m, 0, UINT32_MAX, s)
57
55
58
-typedef struct NPCM7xxMachine {
56
+/*
59
+struct NPCM7xxMachine {
57
+ * For QDMULH and QRDMULH we simplify "double and shift by esize" into
60
MachineState parent;
58
+ * "shift by esize-1", adjusting the QRDMULH rounding constant to match.
61
/*
59
+ */
62
* PWM fan splitter. each splitter connects to one PWM output and
60
+#define DO_QDMULH_B(n, m, s) do_sat_bhw(((int64_t)n * m) >> 7, \
63
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxMachine {
61
+ INT8_MIN, INT8_MAX, s)
64
*/
62
+#define DO_QDMULH_H(n, m, s) do_sat_bhw(((int64_t)n * m) >> 15, \
65
SplitIRQ fan_splitter[NPCM7XX_NR_PWM_MODULES *
63
+ INT16_MIN, INT16_MAX, s)
66
NPCM7XX_PWM_PER_MODULE];
64
+#define DO_QDMULH_W(n, m, s) do_sat_bhw(((int64_t)n * m) >> 31, \
67
-} NPCM7xxMachine;
65
+ INT32_MIN, INT32_MAX, s)
68
+};
66
+
69
67
+#define DO_QRDMULH_B(n, m, s) do_sat_bhw(((int64_t)n * m + (1 << 6)) >> 7, \
70
#define TYPE_NPCM7XX_MACHINE MACHINE_TYPE_NAME("npcm7xx")
68
+ INT8_MIN, INT8_MAX, s)
71
-#define NPCM7XX_MACHINE(obj) \
69
+#define DO_QRDMULH_H(n, m, s) do_sat_bhw(((int64_t)n * m + (1 << 14)) >> 15, \
72
- OBJECT_CHECK(NPCM7xxMachine, (obj), TYPE_NPCM7XX_MACHINE)
70
+ INT16_MIN, INT16_MAX, s)
73
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxMachine, NPCM7XX_MACHINE)
71
+#define DO_QRDMULH_W(n, m, s) do_sat_bhw(((int64_t)n * m + (1 << 30)) >> 31, \
74
72
+ INT32_MIN, INT32_MAX, s)
75
typedef struct NPCM7xxMachineClass {
73
+
76
MachineClass parent;
74
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
77
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxMachineClass {
75
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
78
#define NPCM7XX_MACHINE_GET_CLASS(obj) \
76
uint32_t rm) \
79
OBJECT_GET_CLASS(NPCM7xxMachineClass, (obj), TYPE_NPCM7XX_MACHINE)
77
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT_SCALAR(vqsubs_scalarb, 1, int8_t, DO_SQSUB_B)
80
78
DO_2OP_SAT_SCALAR(vqsubs_scalarh, 2, int16_t, DO_SQSUB_H)
81
-typedef struct NPCM7xxState {
79
DO_2OP_SAT_SCALAR(vqsubs_scalarw, 4, int32_t, DO_SQSUB_W)
82
+struct NPCM7xxState {
80
83
DeviceState parent;
81
+DO_2OP_SAT_SCALAR(vqdmulh_scalarb, 1, int8_t, DO_QDMULH_B)
84
82
+DO_2OP_SAT_SCALAR(vqdmulh_scalarh, 2, int16_t, DO_QDMULH_H)
85
ARMCPU cpu[NPCM7XX_MAX_NUM_CPUS];
83
+DO_2OP_SAT_SCALAR(vqdmulh_scalarw, 4, int32_t, DO_QDMULH_W)
86
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxState {
84
+DO_2OP_SAT_SCALAR(vqrdmulh_scalarb, 1, int8_t, DO_QRDMULH_B)
87
NPCM7xxFIUState fiu[2];
85
+DO_2OP_SAT_SCALAR(vqrdmulh_scalarh, 2, int16_t, DO_QRDMULH_H)
88
NPCM7xxEMCState emc[2];
86
+DO_2OP_SAT_SCALAR(vqrdmulh_scalarw, 4, int32_t, DO_QRDMULH_W)
89
NPCM7xxSDHCIState mmc;
87
+
90
-} NPCM7xxState;
88
static inline uint32_t do_vbrsrb(uint32_t n, uint32_t m)
91
+};
89
{
92
90
m &= 0xff;
93
#define TYPE_NPCM7XX "npcm7xx"
91
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
94
-#define NPCM7XX(obj) OBJECT_CHECK(NPCM7xxState, (obj), TYPE_NPCM7XX)
92
index XXXXXXX..XXXXXXX 100644
95
+OBJECT_DECLARE_TYPE(NPCM7xxState, NPCM7xxClass, NPCM7XX)
93
--- a/target/arm/translate-mve.c
96
94
+++ b/target/arm/translate-mve.c
97
#define TYPE_NPCM730 "npcm730"
95
@@ -XXX,XX +XXX,XX @@ DO_2OP_SCALAR(VQADD_S_scalar, vqadds_scalar)
98
#define TYPE_NPCM750 "npcm750"
96
DO_2OP_SCALAR(VQADD_U_scalar, vqaddu_scalar)
99
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxClass {
97
DO_2OP_SCALAR(VQSUB_S_scalar, vqsubs_scalar)
100
uint32_t num_cpus;
98
DO_2OP_SCALAR(VQSUB_U_scalar, vqsubu_scalar)
101
} NPCM7xxClass;
99
+DO_2OP_SCALAR(VQDMULH_scalar, vqdmulh_scalar)
102
100
+DO_2OP_SCALAR(VQRDMULH_scalar, vqrdmulh_scalar)
103
-#define NPCM7XX_CLASS(klass) \
101
DO_2OP_SCALAR(VBRSR, vbrsr)
104
- OBJECT_CLASS_CHECK(NPCM7xxClass, (klass), TYPE_NPCM7XX)
102
105
-#define NPCM7XX_GET_CLASS(obj) \
103
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
106
- OBJECT_GET_CLASS(NPCM7xxClass, (obj), TYPE_NPCM7XX)
107
-
108
/**
109
* npcm7xx_load_kernel - Loads memory with everything needed to boot
110
* @machine - The machine containing the SoC to be booted.
111
diff --git a/include/hw/i2c/npcm7xx_smbus.h b/include/hw/i2c/npcm7xx_smbus.h
112
index XXXXXXX..XXXXXXX 100644
113
--- a/include/hw/i2c/npcm7xx_smbus.h
114
+++ b/include/hw/i2c/npcm7xx_smbus.h
115
@@ -XXX,XX +XXX,XX @@ typedef enum NPCM7xxSMBusStatus {
116
* @rx_cur: The current position of rx_fifo.
117
* @status: The current status of the SMBus.
118
*/
119
-typedef struct NPCM7xxSMBusState {
120
+struct NPCM7xxSMBusState {
121
SysBusDevice parent;
122
123
MemoryRegion iomem;
124
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxSMBusState {
125
uint8_t rx_cur;
126
127
NPCM7xxSMBusStatus status;
128
-} NPCM7xxSMBusState;
129
+};
130
131
#define TYPE_NPCM7XX_SMBUS "npcm7xx-smbus"
132
-#define NPCM7XX_SMBUS(obj) OBJECT_CHECK(NPCM7xxSMBusState, (obj), \
133
- TYPE_NPCM7XX_SMBUS)
134
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxSMBusState, NPCM7XX_SMBUS)
135
136
#endif /* NPCM7XX_SMBUS_H */
137
diff --git a/include/hw/misc/npcm7xx_clk.h b/include/hw/misc/npcm7xx_clk.h
138
index XXXXXXX..XXXXXXX 100644
139
--- a/include/hw/misc/npcm7xx_clk.h
140
+++ b/include/hw/misc/npcm7xx_clk.h
141
@@ -XXX,XX +XXX,XX @@ struct NPCM7xxCLKState {
142
};
143
144
#define TYPE_NPCM7XX_CLK "npcm7xx-clk"
145
-#define NPCM7XX_CLK(obj) OBJECT_CHECK(NPCM7xxCLKState, (obj), TYPE_NPCM7XX_CLK)
146
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxCLKState, NPCM7XX_CLK)
147
148
#endif /* NPCM7XX_CLK_H */
149
diff --git a/include/hw/misc/npcm7xx_gcr.h b/include/hw/misc/npcm7xx_gcr.h
150
index XXXXXXX..XXXXXXX 100644
151
--- a/include/hw/misc/npcm7xx_gcr.h
152
+++ b/include/hw/misc/npcm7xx_gcr.h
153
@@ -XXX,XX +XXX,XX @@
154
*/
155
#define NPCM7XX_GCR_NR_REGS (0x148 / sizeof(uint32_t))
156
157
-typedef struct NPCM7xxGCRState {
158
+struct NPCM7xxGCRState {
159
SysBusDevice parent;
160
161
MemoryRegion iomem;
162
@@ -XXX,XX +XXX,XX @@ typedef struct NPCM7xxGCRState {
163
uint32_t reset_pwron;
164
uint32_t reset_mdlr;
165
uint32_t reset_intcr3;
166
-} NPCM7xxGCRState;
167
+};
168
169
#define TYPE_NPCM7XX_GCR "npcm7xx-gcr"
170
-#define NPCM7XX_GCR(obj) OBJECT_CHECK(NPCM7xxGCRState, (obj), TYPE_NPCM7XX_GCR)
171
+OBJECT_DECLARE_SIMPLE_TYPE(NPCM7xxGCRState, NPCM7XX_GCR)
172
173
#endif /* NPCM7XX_GCR_H */
174
diff --git a/include/hw/misc/npcm7xx_mft.h b/include/hw/misc/npcm7xx_mft.h
175
index XXXXXXX..XXXXXXX 100644
176
--- a/include/hw/misc/npcm7xx_mft.h
177
+++ b/include/hw/misc/npcm7xx_mft.h
178
@@ -XXX,XX +XXX,XX @@
179
* @max_rpm: The maximum rpm for fans. Order: A0, B0, A1, B1.
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 */
104
--
275
--
105
2.20.1
276
2.34.1
106
277
107
278
diff view generated by jsdifflib
1
Implement the MVE VRMULH insn, which performs a rounding multiply
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
and then returns the high half.
3
2
3
The structure is named SECUREECState. Rename the type accordingly.
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
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210617121628.20116-15-peter.maydell@linaro.org
7
---
9
---
8
target/arm/helper-mve.h | 7 +++++++
10
hw/misc/sbsa_ec.c | 13 +++++++------
9
target/arm/mve.decode | 3 +++
11
1 file changed, 7 insertions(+), 6 deletions(-)
10
target/arm/mve_helper.c | 22 ++++++++++++++++++++++
11
target/arm/translate-mve.c | 2 ++
12
4 files changed, 34 insertions(+)
13
12
14
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
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-mve.h
15
--- a/hw/misc/sbsa_ec.c
17
+++ b/target/arm/helper-mve.h
16
+++ b/hw/misc/sbsa_ec.c
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmulhsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
17
@@ -XXX,XX +XXX,XX @@
19
DEF_HELPER_FLAGS_4(mve_vmulhub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
18
#include "hw/sysbus.h"
20
DEF_HELPER_FLAGS_4(mve_vmulhuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
#include "sysemu/runstate.h"
21
DEF_HELPER_FLAGS_4(mve_vmulhuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
22
+
21
-typedef struct {
23
+DEF_HELPER_FLAGS_4(mve_vrmulhsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
+typedef struct SECUREECState {
24
+DEF_HELPER_FLAGS_4(mve_vrmulhsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
SysBusDevice parent_obj;
25
+DEF_HELPER_FLAGS_4(mve_vrmulhsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
MemoryRegion iomem;
26
+DEF_HELPER_FLAGS_4(mve_vrmulhub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
} SECUREECState;
27
+DEF_HELPER_FLAGS_4(mve_vrmulhuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
28
+DEF_HELPER_FLAGS_4(mve_vrmulhuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
-#define TYPE_SBSA_EC "sbsa-ec"
29
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
28
-#define SECURE_EC(obj) OBJECT_CHECK(SECUREECState, (obj), TYPE_SBSA_EC)
30
index XXXXXXX..XXXXXXX 100644
29
+#define TYPE_SBSA_SECURE_EC "sbsa-ec"
31
--- a/target/arm/mve.decode
30
+#define SBSA_SECURE_EC(obj) \
32
+++ b/target/arm/mve.decode
31
+ OBJECT_CHECK(SECUREECState, (obj), TYPE_SBSA_SECURE_EC)
33
@@ -XXX,XX +XXX,XX @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
32
34
VMULH_S 111 0 1110 0 . .. ...1 ... 0 1110 . 0 . 0 ... 1 @2op
33
enum sbsa_ec_powerstates {
35
VMULH_U 111 1 1110 0 . .. ...1 ... 0 1110 . 0 . 0 ... 1 @2op
34
SBSA_EC_CMD_POWEROFF = 0x01,
36
35
@@ -XXX,XX +XXX,XX @@ static uint64_t sbsa_ec_read(void *opaque, hwaddr offset, unsigned size)
37
+VRMULH_S 111 0 1110 0 . .. ...1 ... 1 1110 . 0 . 0 ... 1 @2op
38
+VRMULH_U 111 1 1110 0 . .. ...1 ... 1 1110 . 0 . 0 ... 1 @2op
39
+
40
# Vector miscellaneous
41
42
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
43
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/mve_helper.c
46
+++ b/target/arm/mve_helper.c
47
@@ -XXX,XX +XXX,XX @@ static inline uint32_t do_mulh_w(int64_t n, int64_t m)
48
return (n * m) >> 32;
49
}
36
}
50
37
51
+static inline uint8_t do_rmulh_b(int32_t n, int32_t m)
38
static void sbsa_ec_write(void *opaque, hwaddr offset,
52
+{
39
- uint64_t value, unsigned size)
53
+ return (n * m + (1U << 7)) >> 8;
40
+ uint64_t value, unsigned size)
54
+}
41
{
55
+
42
if (offset == 0) { /* PSCI machine power command register */
56
+static inline uint16_t do_rmulh_h(int32_t n, int32_t m)
43
switch (value) {
57
+{
44
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps sbsa_ec_ops = {
58
+ return (n * m + (1U << 15)) >> 16;
45
59
+}
46
static void sbsa_ec_init(Object *obj)
60
+
47
{
61
+static inline uint32_t do_rmulh_w(int64_t n, int64_t m)
48
- SECUREECState *s = SECURE_EC(obj);
62
+{
49
+ SECUREECState *s = SBSA_SECURE_EC(obj);
63
+ return (n * m + (1U << 31)) >> 32;
50
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
64
+}
51
65
+
52
memory_region_init_io(&s->iomem, obj, &sbsa_ec_ops, s, "sbsa-ec",
66
DO_2OP(vmulhsb, 1, int8_t, do_mulh_b)
53
@@ -XXX,XX +XXX,XX @@ static void sbsa_ec_class_init(ObjectClass *klass, void *data)
67
DO_2OP(vmulhsh, 2, int16_t, do_mulh_h)
54
}
68
DO_2OP(vmulhsw, 4, int32_t, do_mulh_w)
55
69
DO_2OP(vmulhub, 1, uint8_t, do_mulh_b)
56
static const TypeInfo sbsa_ec_info = {
70
DO_2OP(vmulhuh, 2, uint16_t, do_mulh_h)
57
- .name = TYPE_SBSA_EC,
71
DO_2OP(vmulhuw, 4, uint32_t, do_mulh_w)
58
+ .name = TYPE_SBSA_SECURE_EC,
72
+
59
.parent = TYPE_SYS_BUS_DEVICE,
73
+DO_2OP(vrmulhsb, 1, int8_t, do_rmulh_b)
60
.instance_size = sizeof(SECUREECState),
74
+DO_2OP(vrmulhsh, 2, int16_t, do_rmulh_h)
61
.instance_init = sbsa_ec_init,
75
+DO_2OP(vrmulhsw, 4, int32_t, do_rmulh_w)
76
+DO_2OP(vrmulhub, 1, uint8_t, do_rmulh_b)
77
+DO_2OP(vrmulhuh, 2, uint16_t, do_rmulh_h)
78
+DO_2OP(vrmulhuw, 4, uint32_t, do_rmulh_w)
79
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/target/arm/translate-mve.c
82
+++ b/target/arm/translate-mve.c
83
@@ -XXX,XX +XXX,XX @@ DO_2OP(VSUB, vsub)
84
DO_2OP(VMUL, vmul)
85
DO_2OP(VMULH_S, vmulhs)
86
DO_2OP(VMULH_U, vmulhu)
87
+DO_2OP(VRMULH_S, vrmulhs)
88
+DO_2OP(VRMULH_U, vrmulhu)
89
--
62
--
90
2.20.1
63
2.34.1
91
64
92
65
diff view generated by jsdifflib
1
From: Peter Collingbourne <pcc@google.com>
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
2
3
MTE3 introduces an asymmetric tag checking mode, in which loads are
3
This model was merged few days before the QOM cleanup from
4
checked synchronously and stores are checked asynchronously. Add
4
commit 8063396bf3 ("Use OBJECT_DECLARE_SIMPLE_TYPE when possible")
5
support for it.
5
was pulled and merged. Manually adapt.
6
6
7
Signed-off-by: Peter Collingbourne <pcc@google.com>
7
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210616195614.11785-1-pcc@google.com
9
Message-id: 20230109140306.23161-13-philmd@linaro.org
10
[PMM: Add line to emulation.rst]
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
11
---
13
docs/system/arm/emulation.rst | 1 +
12
hw/misc/sbsa_ec.c | 3 +--
14
target/arm/cpu64.c | 2 +-
13
1 file changed, 1 insertion(+), 2 deletions(-)
15
target/arm/mte_helper.c | 82 ++++++++++++++++++++++-------------
16
3 files changed, 53 insertions(+), 32 deletions(-)
17
14
18
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
15
diff --git a/hw/misc/sbsa_ec.c b/hw/misc/sbsa_ec.c
19
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
20
--- a/docs/system/arm/emulation.rst
17
--- a/hw/misc/sbsa_ec.c
21
+++ b/docs/system/arm/emulation.rst
18
+++ b/hw/misc/sbsa_ec.c
22
@@ -XXX,XX +XXX,XX @@ the following architecture extensions:
19
@@ -XXX,XX +XXX,XX @@ typedef struct SECUREECState {
23
- FEAT_LSE (Large System Extensions)
20
} SECUREECState;
24
- FEAT_MTE (Memory Tagging Extension)
21
25
- FEAT_MTE2 (Memory Tagging Extension)
22
#define TYPE_SBSA_SECURE_EC "sbsa-ec"
26
+- FEAT_MTE3 (MTE Asymmetric Fault Handling)
23
-#define SBSA_SECURE_EC(obj) \
27
- FEAT_PAN (Privileged access never)
24
- OBJECT_CHECK(SECUREECState, (obj), TYPE_SBSA_SECURE_EC)
28
- FEAT_PAN2 (AT S1E1R and AT S1E1W instruction variants affected by PSTATE.PAN)
25
+OBJECT_DECLARE_SIMPLE_TYPE(SECUREECState, SBSA_SECURE_EC)
29
- FEAT_PAuth (Pointer authentication)
26
30
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
27
enum sbsa_ec_powerstates {
31
index XXXXXXX..XXXXXXX 100644
28
SBSA_EC_CMD_POWEROFF = 0x01,
32
--- a/target/arm/cpu64.c
33
+++ b/target/arm/cpu64.c
34
@@ -XXX,XX +XXX,XX @@ static void aarch64_max_initfn(Object *obj)
35
* during realize if the board provides no tag memory, much like
36
* we do for EL2 with the virtualization=on property.
37
*/
38
- t = FIELD_DP64(t, ID_AA64PFR1, MTE, 2);
39
+ t = FIELD_DP64(t, ID_AA64PFR1, MTE, 3);
40
cpu->isar.id_aa64pfr1 = t;
41
42
t = cpu->isar.id_aa64mmfr0;
43
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/mte_helper.c
46
+++ b/target/arm/mte_helper.c
47
@@ -XXX,XX +XXX,XX @@ void HELPER(stzgm_tags)(CPUARMState *env, uint64_t ptr, uint64_t val)
48
}
49
}
50
51
+static void mte_sync_check_fail(CPUARMState *env, uint32_t desc,
52
+ uint64_t dirty_ptr, uintptr_t ra)
53
+{
54
+ int is_write, syn;
55
+
56
+ env->exception.vaddress = dirty_ptr;
57
+
58
+ is_write = FIELD_EX32(desc, MTEDESC, WRITE);
59
+ syn = syn_data_abort_no_iss(arm_current_el(env) != 0, 0, 0, 0, 0, is_write,
60
+ 0x11);
61
+ raise_exception_ra(env, EXCP_DATA_ABORT, syn, exception_target_el(env), ra);
62
+ g_assert_not_reached();
63
+}
64
+
65
+static void mte_async_check_fail(CPUARMState *env, uint64_t dirty_ptr,
66
+ uintptr_t ra, ARMMMUIdx arm_mmu_idx, int el)
67
+{
68
+ int select;
69
+
70
+ if (regime_has_2_ranges(arm_mmu_idx)) {
71
+ select = extract64(dirty_ptr, 55, 1);
72
+ } else {
73
+ select = 0;
74
+ }
75
+ env->cp15.tfsr_el[el] |= 1 << select;
76
+#ifdef CONFIG_USER_ONLY
77
+ /*
78
+ * Stand in for a timer irq, setting _TIF_MTE_ASYNC_FAULT,
79
+ * which then sends a SIGSEGV when the thread is next scheduled.
80
+ * This cpu will return to the main loop at the end of the TB,
81
+ * which is rather sooner than "normal". But the alternative
82
+ * is waiting until the next syscall.
83
+ */
84
+ qemu_cpu_kick(env_cpu(env));
85
+#endif
86
+}
87
+
88
/* Record a tag check failure. */
89
static void mte_check_fail(CPUARMState *env, uint32_t desc,
90
uint64_t dirty_ptr, uintptr_t ra)
91
{
92
int mmu_idx = FIELD_EX32(desc, MTEDESC, MIDX);
93
ARMMMUIdx arm_mmu_idx = core_to_aa64_mmu_idx(mmu_idx);
94
- int el, reg_el, tcf, select, is_write, syn;
95
+ int el, reg_el, tcf;
96
uint64_t sctlr;
97
98
reg_el = regime_el(env, arm_mmu_idx);
99
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
100
switch (tcf) {
101
case 1:
102
/* Tag check fail causes a synchronous exception. */
103
- env->exception.vaddress = dirty_ptr;
104
-
105
- is_write = FIELD_EX32(desc, MTEDESC, WRITE);
106
- syn = syn_data_abort_no_iss(arm_current_el(env) != 0, 0, 0, 0, 0,
107
- is_write, 0x11);
108
- raise_exception_ra(env, EXCP_DATA_ABORT, syn,
109
- exception_target_el(env), ra);
110
- /* noreturn, but fall through to the assert anyway */
111
+ mte_sync_check_fail(env, desc, dirty_ptr, ra);
112
+ break;
113
114
case 0:
115
/*
116
@@ -XXX,XX +XXX,XX @@ static void mte_check_fail(CPUARMState *env, uint32_t desc,
117
118
case 2:
119
/* Tag check fail causes asynchronous flag set. */
120
- if (regime_has_2_ranges(arm_mmu_idx)) {
121
- select = extract64(dirty_ptr, 55, 1);
122
- } else {
123
- select = 0;
124
- }
125
- env->cp15.tfsr_el[el] |= 1 << select;
126
-#ifdef CONFIG_USER_ONLY
127
- /*
128
- * Stand in for a timer irq, setting _TIF_MTE_ASYNC_FAULT,
129
- * which then sends a SIGSEGV when the thread is next scheduled.
130
- * This cpu will return to the main loop at the end of the TB,
131
- * which is rather sooner than "normal". But the alternative
132
- * is waiting until the next syscall.
133
- */
134
- qemu_cpu_kick(env_cpu(env));
135
-#endif
136
+ mte_async_check_fail(env, dirty_ptr, ra, arm_mmu_idx, el);
137
break;
138
139
- default:
140
- /* Case 3: Reserved. */
141
- qemu_log_mask(LOG_GUEST_ERROR,
142
- "Tag check failure with SCTLR_EL%d.TCF%s "
143
- "set to reserved value %d\n",
144
- reg_el, el ? "" : "0", tcf);
145
+ case 3:
146
+ /*
147
+ * Tag check fail causes asynchronous flag set for stores, or
148
+ * a synchronous exception for loads.
149
+ */
150
+ if (FIELD_EX32(desc, MTEDESC, WRITE)) {
151
+ mte_async_check_fail(env, dirty_ptr, ra, arm_mmu_idx, el);
152
+ } else {
153
+ mte_sync_check_fail(env, desc, dirty_ptr, ra);
154
+ }
155
break;
156
}
157
}
158
--
29
--
159
2.20.1
30
2.34.1
160
31
161
32
diff view generated by jsdifflib
1
vfp_access_check and its helper routine full_vfp_access_check() has
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
gradually grown and is now an awkward mix of A-profile only and
3
M-profile only pieces. Refactor it into an A-profile only and an
4
M-profile only version, taking advantage of the fact that now the
5
only direct call to full_vfp_access_check() is in A-profile-only
6
code.
7
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/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
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
Message-id: 20210618141019.10671-7-peter.maydell@linaro.org
11
---
15
---
12
target/arm/translate-vfp.c | 79 +++++++++++++++++++++++---------------
16
hw/intc/xilinx_intc.c | 28 +++++++++++++---------------
13
1 file changed, 48 insertions(+), 31 deletions(-)
17
1 file changed, 13 insertions(+), 15 deletions(-)
14
18
15
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
19
diff --git a/hw/intc/xilinx_intc.c b/hw/intc/xilinx_intc.c
16
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-vfp.c
21
--- a/hw/intc/xilinx_intc.c
18
+++ b/target/arm/translate-vfp.c
22
+++ b/hw/intc/xilinx_intc.c
19
@@ -XXX,XX +XXX,XX @@ static void gen_update_fp_context(DisasContext *s)
23
@@ -XXX,XX +XXX,XX @@
24
#define R_MAX 8
25
26
#define TYPE_XILINX_INTC "xlnx.xps-intc"
27
-DECLARE_INSTANCE_CHECKER(struct xlx_pic, XILINX_INTC,
28
- TYPE_XILINX_INTC)
29
+typedef struct XpsIntc XpsIntc;
30
+DECLARE_INSTANCE_CHECKER(XpsIntc, XILINX_INTC, TYPE_XILINX_INTC)
31
32
-struct xlx_pic
33
+struct XpsIntc
34
{
35
SysBusDevice parent_obj;
36
37
@@ -XXX,XX +XXX,XX @@ struct xlx_pic
38
uint32_t irq_pin_state;
39
};
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]);
20
}
48
}
21
49
22
/*
50
-static uint64_t
23
- * Check that VFP access is enabled. If it is, do the necessary
51
-pic_read(void *opaque, hwaddr addr, unsigned int size)
24
- * M-profile lazy-FP handling and then return true.
52
+static uint64_t pic_read(void *opaque, hwaddr addr, unsigned int size)
25
- * If not, emit code to generate an appropriate exception and
26
- * return false.
27
+ * Check that VFP access is enabled, A-profile specific version.
28
+ *
29
+ * If VFP is enabled, return true. If not, emit code to generate an
30
+ * appropriate exception and return false.
31
* The ignore_vfp_enabled argument specifies that we should ignore
32
- * whether VFP is enabled via FPEXC[EN]: this should be true for FMXR/FMRX
33
+ * whether VFP is enabled via FPEXC.EN: this should be true for FMXR/FMRX
34
* accesses to FPSID, FPEXC, MVFR0, MVFR1, MVFR2, and false for all other insns.
35
*/
36
-static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
37
+static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled)
38
{
53
{
39
if (s->fp_excp_el) {
54
- struct xlx_pic *p = opaque;
40
- if (arm_dc_feature(s, ARM_FEATURE_M)) {
55
+ XpsIntc *p = opaque;
41
- /*
56
uint32_t r = 0;
42
- * M-profile mostly catches the "FPU disabled" case early, in
57
43
- * disas_m_nocp(), but a few insns (eg LCTP, WLSTP, DLSTP)
58
addr >>= 2;
44
- * which do coprocessor-checks are outside the large ranges of
59
@@ -XXX,XX +XXX,XX @@ pic_read(void *opaque, hwaddr addr, unsigned int size)
45
- * the encoding space handled by the patterns in m-nocp.decode,
60
return r;
46
- * and for them we may need to raise NOCP here.
47
- */
48
- gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
49
- syn_uncategorized(), s->fp_excp_el);
50
- } else {
51
- gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
52
- syn_fp_access_trap(1, 0xe, false),
53
- s->fp_excp_el);
54
- }
55
+ gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
56
+ syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
57
return false;
58
}
59
60
@@ -XXX,XX +XXX,XX @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
61
unallocated_encoding(s);
62
return false;
63
}
64
+ return true;
65
+}
66
67
- if (arm_dc_feature(s, ARM_FEATURE_M)) {
68
- /* Handle M-profile lazy FP state mechanics */
69
-
70
- /* Trigger lazy-state preservation if necessary */
71
- gen_preserve_fp_state(s);
72
-
73
- /* Update ownership of FP context and create new FP context if needed */
74
- gen_update_fp_context(s);
75
+/*
76
+ * Check that VFP access is enabled, M-profile specific version.
77
+ *
78
+ * If VFP is enabled, do the necessary M-profile lazy-FP handling and then
79
+ * return true. If not, emit code to generate an appropriate exception and
80
+ * return false.
81
+ */
82
+static bool vfp_access_check_m(DisasContext *s)
83
+{
84
+ if (s->fp_excp_el) {
85
+ /*
86
+ * M-profile mostly catches the "FPU disabled" case early, in
87
+ * disas_m_nocp(), but a few insns (eg LCTP, WLSTP, DLSTP)
88
+ * which do coprocessor-checks are outside the large ranges of
89
+ * the encoding space handled by the patterns in m-nocp.decode,
90
+ * and for them we may need to raise NOCP here.
91
+ */
92
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
93
+ syn_uncategorized(), s->fp_excp_el);
94
+ return false;
95
}
96
97
+ /* Handle M-profile lazy FP state mechanics */
98
+
99
+ /* Trigger lazy-state preservation if necessary */
100
+ gen_preserve_fp_state(s);
101
+
102
+ /* Update ownership of FP context and create new FP context if needed */
103
+ gen_update_fp_context(s);
104
+
105
return true;
106
}
61
}
107
62
108
@@ -XXX,XX +XXX,XX @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
63
-static void
109
*/
64
-pic_write(void *opaque, hwaddr addr,
110
bool vfp_access_check(DisasContext *s)
65
- uint64_t val64, unsigned int size)
66
+static void pic_write(void *opaque, hwaddr addr,
67
+ uint64_t val64, unsigned int size)
111
{
68
{
112
- return full_vfp_access_check(s, false);
69
- struct xlx_pic *p = opaque;
113
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
70
+ XpsIntc *p = opaque;
114
+ return vfp_access_check_m(s);
71
uint32_t value = val64;
115
+ } else {
72
116
+ return vfp_access_check_a(s, false);
73
addr >>= 2;
117
+ }
74
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps pic_ops = {
75
76
static void irq_handler(void *opaque, int irq, int level)
77
{
78
- struct xlx_pic *p = opaque;
79
+ XpsIntc *p = opaque;
80
81
/* edge triggered interrupt */
82
if (p->c_kind_of_intr & (1 << irq) && p->regs[R_MER] & 2) {
83
@@ -XXX,XX +XXX,XX @@ static void irq_handler(void *opaque, int irq, int level)
84
85
static void xilinx_intc_init(Object *obj)
86
{
87
- struct xlx_pic *p = XILINX_INTC(obj);
88
+ XpsIntc *p = XILINX_INTC(obj);
89
90
qdev_init_gpio_in(DEVICE(obj), irq_handler, 32);
91
sysbus_init_irq(SYS_BUS_DEVICE(obj), &p->parent_irq);
92
@@ -XXX,XX +XXX,XX @@ static void xilinx_intc_init(Object *obj)
118
}
93
}
119
94
120
static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
95
static Property xilinx_intc_properties[] = {
121
@@ -XXX,XX +XXX,XX @@ static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
96
- DEFINE_PROP_UINT32("kind-of-intr", struct xlx_pic, c_kind_of_intr, 0),
122
return false;
97
+ DEFINE_PROP_UINT32("kind-of-intr", XpsIntc, c_kind_of_intr, 0),
123
}
98
DEFINE_PROP_END_OF_LIST(),
124
99
};
125
- if (!full_vfp_access_check(s, ignore_vfp_enabled)) {
100
126
+ /*
101
@@ -XXX,XX +XXX,XX @@ static void xilinx_intc_class_init(ObjectClass *klass, void *data)
127
+ * Call vfp_access_check_a() directly, because we need to tell
102
static const TypeInfo xilinx_intc_info = {
128
+ * it to ignore FPEXC.EN for some register accesses.
103
.name = TYPE_XILINX_INTC,
129
+ */
104
.parent = TYPE_SYS_BUS_DEVICE,
130
+ if (!vfp_access_check_a(s, ignore_vfp_enabled)) {
105
- .instance_size = sizeof(struct xlx_pic),
131
return true;
106
+ .instance_size = sizeof(XpsIntc),
132
}
107
.instance_init = xilinx_intc_init,
133
108
.class_init = xilinx_intc_class_init,
109
};
134
--
110
--
135
2.20.1
111
2.34.1
136
112
137
113
diff view generated by jsdifflib
1
Allow code elsewhere in the system to check whether the ACPI GHES
1
From: Philippe Mathieu-Daudé <philmd@linaro.org>
2
table is present, so it can determine whether it is OK to try to
3
record an error by calling acpi_ghes_record_errors().
4
2
5
(We don't need to migrate the new 'present' field in AcpiGhesState,
3
This remove a use of 'struct' in the DECLARE_INSTANCE_CHECKER()
6
because it is set once at system initialization and doesn't change.)
4
macro call, to avoid after a QOM refactor:
7
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
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
Reviewed-by: Dongjiu Geng <gengdongjiu1@gmail.com>
11
Message-id: 20210603171259.27962-3-peter.maydell@linaro.org
12
---
15
---
13
include/hw/acpi/ghes.h | 9 +++++++++
16
hw/timer/xilinx_timer.c | 27 +++++++++++++--------------
14
hw/acpi/ghes-stub.c | 5 +++++
17
1 file changed, 13 insertions(+), 14 deletions(-)
15
hw/acpi/ghes.c | 17 +++++++++++++++++
16
3 files changed, 31 insertions(+)
17
18
18
diff --git a/include/hw/acpi/ghes.h b/include/hw/acpi/ghes.h
19
diff --git a/hw/timer/xilinx_timer.c b/hw/timer/xilinx_timer.c
19
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
20
--- a/include/hw/acpi/ghes.h
21
--- a/hw/timer/xilinx_timer.c
21
+++ b/include/hw/acpi/ghes.h
22
+++ b/hw/timer/xilinx_timer.c
22
@@ -XXX,XX +XXX,XX @@ enum {
23
@@ -XXX,XX +XXX,XX @@ struct xlx_timer
23
24
};
24
typedef struct AcpiGhesState {
25
25
uint64_t ghes_addr_le;
26
#define TYPE_XILINX_TIMER "xlnx.xps-timer"
26
+ bool present; /* True if GHES is present at all on this board */
27
-DECLARE_INSTANCE_CHECKER(struct timerblock, XILINX_TIMER,
27
} AcpiGhesState;
28
- TYPE_XILINX_TIMER)
28
29
+typedef struct XpsTimerState XpsTimerState;
29
void build_ghes_error_table(GArray *hardware_errors, BIOSLinker *linker);
30
+DECLARE_INSTANCE_CHECKER(XpsTimerState, XILINX_TIMER, TYPE_XILINX_TIMER)
30
@@ -XXX,XX +XXX,XX @@ void acpi_build_hest(GArray *table_data, BIOSLinker *linker,
31
31
void acpi_ghes_add_fw_cfg(AcpiGhesState *vms, FWCfgState *s,
32
-struct timerblock
32
GArray *hardware_errors);
33
+struct XpsTimerState
33
int acpi_ghes_record_errors(uint8_t notify, uint64_t error_physical_addr);
34
+
35
+/**
36
+ * acpi_ghes_present: Report whether ACPI GHES table is present
37
+ *
38
+ * Returns: true if the system has an ACPI GHES table and it is
39
+ * safe to call acpi_ghes_record_errors() to record a memory error.
40
+ */
41
+bool acpi_ghes_present(void);
42
#endif
43
diff --git a/hw/acpi/ghes-stub.c b/hw/acpi/ghes-stub.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/acpi/ghes-stub.c
46
+++ b/hw/acpi/ghes-stub.c
47
@@ -XXX,XX +XXX,XX @@ int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address)
48
{
34
{
49
return -1;
35
SysBusDevice parent_obj;
36
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;
50
}
45
}
51
+
46
@@ -XXX,XX +XXX,XX @@ static inline unsigned int timer_from_addr(hwaddr addr)
52
+bool acpi_ghes_present(void)
47
return addr >> 2;
53
+{
54
+ return false;
55
+}
56
diff --git a/hw/acpi/ghes.c b/hw/acpi/ghes.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/hw/acpi/ghes.c
59
+++ b/hw/acpi/ghes.c
60
@@ -XXX,XX +XXX,XX @@ void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s,
61
/* Create a read-write fw_cfg file for Address */
62
fw_cfg_add_file_callback(s, ACPI_GHES_DATA_ADDR_FW_CFG_FILE, NULL, NULL,
63
NULL, &(ags->ghes_addr_le), sizeof(ags->ghes_addr_le), false);
64
+
65
+ ags->present = true;
66
}
48
}
67
49
68
int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address)
50
-static void timer_update_irq(struct timerblock *t)
69
@@ -XXX,XX +XXX,XX @@ int acpi_ghes_record_errors(uint8_t source_id, uint64_t physical_address)
51
+static void timer_update_irq(XpsTimerState *t)
70
52
{
71
return ret;
53
unsigned int i, irq = 0;
54
uint32_t csr;
55
@@ -XXX,XX +XXX,XX @@ static void timer_update_irq(struct timerblock *t)
56
static uint64_t
57
timer_read(void *opaque, hwaddr addr, unsigned int size)
58
{
59
- struct timerblock *t = opaque;
60
+ XpsTimerState *t = opaque;
61
struct xlx_timer *xt;
62
uint32_t r = 0;
63
unsigned int timer;
64
@@ -XXX,XX +XXX,XX @@ static void
65
timer_write(void *opaque, hwaddr addr,
66
uint64_t val64, unsigned int size)
67
{
68
- struct timerblock *t = opaque;
69
+ XpsTimerState *t = opaque;
70
struct xlx_timer *xt;
71
unsigned int timer;
72
uint32_t value = val64;
73
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps timer_ops = {
74
static void timer_hit(void *opaque)
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);
72
}
100
}
73
+
101
74
+bool acpi_ghes_present(void)
102
static Property xilinx_timer_properties[] = {
75
+{
103
- DEFINE_PROP_UINT32("clock-frequency", struct timerblock, freq_hz,
76
+ AcpiGedState *acpi_ged_state;
104
- 62 * 1000000),
77
+ AcpiGhesState *ags;
105
- DEFINE_PROP_UINT8("one-timer-only", struct timerblock, one_timer_only, 0),
78
+
106
+ DEFINE_PROP_UINT32("clock-frequency", XpsTimerState, freq_hz, 62 * 1000000),
79
+ acpi_ged_state = ACPI_GED(object_resolve_path_type("", TYPE_ACPI_GED,
107
+ DEFINE_PROP_UINT8("one-timer-only", XpsTimerState, one_timer_only, 0),
80
+ NULL));
108
DEFINE_PROP_END_OF_LIST(),
81
+
109
};
82
+ if (!acpi_ged_state) {
110
83
+ return false;
111
@@ -XXX,XX +XXX,XX @@ static void xilinx_timer_class_init(ObjectClass *klass, void *data)
84
+ }
112
static const TypeInfo xilinx_timer_info = {
85
+ ags = &acpi_ged_state->ghes_state;
113
.name = TYPE_XILINX_TIMER,
86
+ return ags->present;
114
.parent = TYPE_SYS_BUS_DEVICE,
87
+}
115
- .instance_size = sizeof(struct timerblock),
116
+ .instance_size = sizeof(XpsTimerState),
117
.instance_init = xilinx_timer_init,
118
.class_init = xilinx_timer_class_init,
119
};
88
--
120
--
89
2.20.1
121
2.34.1
90
122
91
123
diff view generated by jsdifflib
Deleted patch
1
The virt_is_acpi_enabled() function is specific to the virt board, as
2
is the check for its 'ras' property. Use the new acpi_ghes_present()
3
function to check whether we should report memory errors via
4
acpi_ghes_record_errors().
5
1
6
This avoids a link error if QEMU was built without support for the
7
virt board, and provides a mechanism that can be used by any future
8
board models that want to add ACPI memory error reporting support
9
(they only need to call acpi_ghes_add_fw_cfg()).
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
Reviewed-by: Dongjiu Geng <gengdongjiu1@gmail.com>
14
Message-id: 20210603171259.27962-4-peter.maydell@linaro.org
15
---
16
target/arm/kvm64.c | 6 +-----
17
1 file changed, 1 insertion(+), 5 deletions(-)
18
19
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/kvm64.c
22
+++ b/target/arm/kvm64.c
23
@@ -XXX,XX +XXX,XX @@ void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr)
24
{
25
ram_addr_t ram_addr;
26
hwaddr paddr;
27
- Object *obj = qdev_get_machine();
28
- VirtMachineState *vms = VIRT_MACHINE(obj);
29
- bool acpi_enabled = virt_is_acpi_enabled(vms);
30
31
assert(code == BUS_MCEERR_AR || code == BUS_MCEERR_AO);
32
33
- if (acpi_enabled && addr &&
34
- object_property_get_bool(obj, "ras", NULL)) {
35
+ if (acpi_ghes_present() && addr) {
36
ram_addr = qemu_ram_addr_from_host(addr);
37
if (ram_addr != RAM_ADDR_INVALID &&
38
kvm_physical_memory_addr_from_host(c->kvm_state, addr, &paddr)) {
39
--
40
2.20.1
41
42
diff view generated by jsdifflib
1
If the guest makes an FPCXT_NS access when the FPU is disabled,
1
From: Evgeny Iakovlev <eiakovlev@linux.microsoft.com>
2
one of two things happens:
3
* if there is no active FP context, then the insn behaves the
4
same way as if the FPU was enabled: writes ignored, reads
5
same value as FPDSCR_NS
6
* if there is an active FP context, then we take a NOCP
7
exception
8
2
9
Add code to the sysreg read/write functions which emits
3
ARM trusted firmware, when built with FEAT_HCX support, sets SCR_EL3.HXEn bit
10
code to take the NOCP exception in the latter case.
4
to allow EL2 to modify HCRX_EL2 register without trapping it in EL3. Qemu
11
5
uses a valid mask to clear unsupported SCR_EL3 bits when emulating SCR_EL3
12
At the moment this will never be used, because the NOCP checks in
6
write, and that mask doesn't include SCR_EL3.HXEn bit even if FEAT_HCX is
13
m-nocp.decode happen first, and so the trans functions are never
7
enabled and exposed to the guest. As a result EL3 writes of that bit are
14
called when the FPU is disabled. The code will be needed when we
8
ignored.
15
move the sysreg access insns to before the NOCP patterns in the
16
following commit.
17
9
18
Cc: qemu-stable@nongnu.org
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>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20210618141019.10671-3-peter.maydell@linaro.org
22
---
15
---
23
target/arm/translate-vfp.c | 32 ++++++++++++++++++++++++++++++--
16
target/arm/helper.c | 3 +++
24
1 file changed, 30 insertions(+), 2 deletions(-)
17
1 file changed, 3 insertions(+)
25
18
26
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
19
diff --git a/target/arm/helper.c b/target/arm/helper.c
27
index XXXXXXX..XXXXXXX 100644
20
index XXXXXXX..XXXXXXX 100644
28
--- a/target/arm/translate-vfp.c
21
--- a/target/arm/helper.c
29
+++ b/target/arm/translate-vfp.c
22
+++ b/target/arm/helper.c
30
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
23
@@ -XXX,XX +XXX,XX @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
31
lab_end = gen_new_label();
24
if (cpu_isar_feature(aa64_sme, cpu)) {
32
/* fpInactive case: write is a NOP, so branch to end */
25
valid_mask |= SCR_ENTP2;
33
gen_branch_fpInactive(s, TCG_COND_NE, lab_end);
26
}
34
- /* !fpInactive: PreserveFPState(), and reads same as FPCXT_S */
27
+ if (cpu_isar_feature(aa64_hcx, cpu)) {
35
+ /*
28
+ valid_mask |= SCR_HXEN;
36
+ * !fpInactive: if FPU disabled, take NOCP exception;
37
+ * otherwise PreserveFPState(), and then FPCXT_NS writes
38
+ * behave the same as FPCXT_S writes.
39
+ */
40
+ if (s->fp_excp_el) {
41
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
42
+ syn_uncategorized(), s->fp_excp_el);
43
+ /*
44
+ * This was only a conditional exception, so override
45
+ * gen_exception_insn()'s default to DISAS_NORETURN
46
+ */
47
+ s->base.is_jmp = DISAS_NEXT;
48
+ break;
49
+ }
29
+ }
50
gen_preserve_fp_state(s);
30
} else {
51
/* fall through */
31
valid_mask &= ~(SCR_RW | SCR_ST);
52
case ARM_VFP_FPCXT_S:
32
if (cpu_isar_feature(aa32_ras, cpu)) {
53
@@ -XXX,XX +XXX,XX @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
54
tcg_gen_br(lab_end);
55
56
gen_set_label(lab_active);
57
- /* !fpInactive: Reads the same as FPCXT_S, but side effects differ */
58
+ /*
59
+ * !fpInactive: if FPU disabled, take NOCP exception;
60
+ * otherwise PreserveFPState(), and then FPCXT_NS
61
+ * reads the same as FPCXT_S.
62
+ */
63
+ if (s->fp_excp_el) {
64
+ gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
65
+ syn_uncategorized(), s->fp_excp_el);
66
+ /*
67
+ * This was only a conditional exception, so override
68
+ * gen_exception_insn()'s default to DISAS_NORETURN
69
+ */
70
+ s->base.is_jmp = DISAS_NEXT;
71
+ break;
72
+ }
73
gen_preserve_fp_state(s);
74
tmp = tcg_temp_new_i32();
75
sfpa = tcg_temp_new_i32();
76
--
33
--
77
2.20.1
34
2.34.1
78
79
diff view generated by jsdifflib
Deleted patch
1
Implement the variants of MVE VLDR (encodings T1, T2) which perform
2
"widening" loads where bytes or halfwords are loaded from memory and
3
zero or sign-extended into halfword or word length vector elements,
4
and the narrowing MVE VSTR (encodings T1, T2) where bytes or
5
halfwords are stored from halfword or word elements.
6
1
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20210617121628.20116-3-peter.maydell@linaro.org
10
---
11
target/arm/helper-mve.h | 10 ++++++++++
12
target/arm/mve.decode | 25 +++++++++++++++++++++++--
13
target/arm/mve_helper.c | 11 +++++++++++
14
target/arm/translate-mve.c | 14 ++++++++++++++
15
4 files changed, 58 insertions(+), 2 deletions(-)
16
17
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper-mve.h
20
+++ b/target/arm/helper-mve.h
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vldrw, TCG_CALL_NO_WG, void, env, ptr, i32)
22
DEF_HELPER_FLAGS_3(mve_vstrb, TCG_CALL_NO_WG, void, env, ptr, i32)
23
DEF_HELPER_FLAGS_3(mve_vstrh, TCG_CALL_NO_WG, void, env, ptr, i32)
24
DEF_HELPER_FLAGS_3(mve_vstrw, TCG_CALL_NO_WG, void, env, ptr, i32)
25
+
26
+DEF_HELPER_FLAGS_3(mve_vldrb_sh, TCG_CALL_NO_WG, void, env, ptr, i32)
27
+DEF_HELPER_FLAGS_3(mve_vldrb_sw, TCG_CALL_NO_WG, void, env, ptr, i32)
28
+DEF_HELPER_FLAGS_3(mve_vldrb_uh, TCG_CALL_NO_WG, void, env, ptr, i32)
29
+DEF_HELPER_FLAGS_3(mve_vldrb_uw, TCG_CALL_NO_WG, void, env, ptr, i32)
30
+DEF_HELPER_FLAGS_3(mve_vldrh_sw, TCG_CALL_NO_WG, void, env, ptr, i32)
31
+DEF_HELPER_FLAGS_3(mve_vldrh_uw, TCG_CALL_NO_WG, void, env, ptr, i32)
32
+DEF_HELPER_FLAGS_3(mve_vstrb_h, TCG_CALL_NO_WG, void, env, ptr, i32)
33
+DEF_HELPER_FLAGS_3(mve_vstrb_w, TCG_CALL_NO_WG, void, env, ptr, i32)
34
+DEF_HELPER_FLAGS_3(mve_vstrh_w, TCG_CALL_NO_WG, void, env, ptr, i32)
35
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/mve.decode
38
+++ b/target/arm/mve.decode
39
@@ -XXX,XX +XXX,XX @@
40
41
%qd 22:1 13:3
42
43
-&vldr_vstr rn qd imm p a w size l
44
+&vldr_vstr rn qd imm p a w size l u
45
46
-@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd
47
+@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
48
+# Note that both Rn and Qd are 3 bits only (no D bit)
49
+@vldst_wn ... u:1 ... . . . . l:1 . rn:3 qd:3 . ... .. imm:7 &vldr_vstr
50
51
# Vector loads and stores
52
53
+# Widening loads and narrowing stores:
54
+# for these P=0 W=0 is 'related encoding'; sz=11 is 'related encoding'
55
+# This means we need to expand out to multiple patterns for P, W, SZ.
56
+# For stores the U bit must be 0 but we catch that in the trans_ function.
57
+# The naming scheme here is "VLDSTB_H == in-memory byte load/store to/from
58
+# signed halfword element in register", etc.
59
+VLDSTB_H 111 . 110 0 a:1 0 1 . 0 ... ... 0 111 01 ....... @vldst_wn \
60
+ p=0 w=1 size=1
61
+VLDSTB_H 111 . 110 1 a:1 0 w:1 . 0 ... ... 0 111 01 ....... @vldst_wn \
62
+ p=1 size=1
63
+VLDSTB_W 111 . 110 0 a:1 0 1 . 0 ... ... 0 111 10 ....... @vldst_wn \
64
+ p=0 w=1 size=2
65
+VLDSTB_W 111 . 110 1 a:1 0 w:1 . 0 ... ... 0 111 10 ....... @vldst_wn \
66
+ p=1 size=2
67
+VLDSTH_W 111 . 110 0 a:1 0 1 . 1 ... ... 0 111 10 ....... @vldst_wn \
68
+ p=0 w=1 size=2
69
+VLDSTH_W 111 . 110 1 a:1 0 w:1 . 1 ... ... 0 111 10 ....... @vldst_wn \
70
+ p=1 size=2
71
+
72
# Non-widening loads/stores (P=0 W=0 is 'related encoding')
73
VLDR_VSTR 1110110 0 a:1 . 1 . .... ... 111100 ....... @vldr_vstr \
74
size=0 p=0 w=1
75
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/mve_helper.c
78
+++ b/target/arm/mve_helper.c
79
@@ -XXX,XX +XXX,XX @@ DO_VSTR(vstrb, 1, stb, 1, uint8_t)
80
DO_VSTR(vstrh, 2, stw, 2, uint16_t)
81
DO_VSTR(vstrw, 4, stl, 4, uint32_t)
82
83
+DO_VLDR(vldrb_sh, 1, ldsb, 2, int16_t)
84
+DO_VLDR(vldrb_sw, 1, ldsb, 4, int32_t)
85
+DO_VLDR(vldrb_uh, 1, ldub, 2, uint16_t)
86
+DO_VLDR(vldrb_uw, 1, ldub, 4, uint32_t)
87
+DO_VLDR(vldrh_sw, 2, ldsw, 4, int32_t)
88
+DO_VLDR(vldrh_uw, 2, lduw, 4, uint32_t)
89
+
90
+DO_VSTR(vstrb_h, 1, stb, 2, int16_t)
91
+DO_VSTR(vstrb_w, 1, stb, 4, int32_t)
92
+DO_VSTR(vstrh_w, 2, stw, 4, int32_t)
93
+
94
#undef DO_VLDR
95
#undef DO_VSTR
96
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/target/arm/translate-mve.c
99
+++ b/target/arm/translate-mve.c
100
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDR_VSTR(DisasContext *s, arg_VLDR_VSTR *a)
101
};
102
return do_ldst(s, a, ldstfns[a->size][a->l]);
103
}
104
+
105
+#define DO_VLDST_WIDE_NARROW(OP, SLD, ULD, ST) \
106
+ static bool trans_##OP(DisasContext *s, arg_VLDR_VSTR *a) \
107
+ { \
108
+ static MVEGenLdStFn * const ldstfns[2][2] = { \
109
+ { gen_helper_mve_##ST, gen_helper_mve_##SLD }, \
110
+ { NULL, gen_helper_mve_##ULD }, \
111
+ }; \
112
+ return do_ldst(s, a, ldstfns[a->u][a->l]); \
113
+ }
114
+
115
+DO_VLDST_WIDE_NARROW(VLDSTB_H, vldrb_sh, vldrb_uh, vstrb_h)
116
+DO_VLDST_WIDE_NARROW(VLDSTB_W, vldrb_sw, vldrb_uw, vstrb_w)
117
+DO_VLDST_WIDE_NARROW(VLDSTH_W, vldrh_sw, vldrh_uw, vstrh_w)
118
--
119
2.20.1
120
121
diff view generated by jsdifflib
Deleted patch
1
Implement the MVE instructions VREV16, VREV32 and VREV64.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-6-peter.maydell@linaro.org
6
---
7
target/arm/helper-mve.h | 7 +++++++
8
target/arm/mve.decode | 4 ++++
9
target/arm/mve_helper.c | 7 +++++++
10
target/arm/translate-mve.c | 33 +++++++++++++++++++++++++++++++++
11
4 files changed, 51 insertions(+)
12
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
16
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vclsw, TCG_CALL_NO_WG, void, env, ptr, ptr)
18
DEF_HELPER_FLAGS_3(mve_vclzb, TCG_CALL_NO_WG, void, env, ptr, ptr)
19
DEF_HELPER_FLAGS_3(mve_vclzh, TCG_CALL_NO_WG, void, env, ptr, ptr)
20
DEF_HELPER_FLAGS_3(mve_vclzw, TCG_CALL_NO_WG, void, env, ptr, ptr)
21
+
22
+DEF_HELPER_FLAGS_3(mve_vrev16b, TCG_CALL_NO_WG, void, env, ptr, ptr)
23
+DEF_HELPER_FLAGS_3(mve_vrev32b, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
+DEF_HELPER_FLAGS_3(mve_vrev32h, TCG_CALL_NO_WG, void, env, ptr, ptr)
25
+DEF_HELPER_FLAGS_3(mve_vrev64b, TCG_CALL_NO_WG, void, env, ptr, ptr)
26
+DEF_HELPER_FLAGS_3(mve_vrev64h, TCG_CALL_NO_WG, void, env, ptr, ptr)
27
+DEF_HELPER_FLAGS_3(mve_vrev64w, TCG_CALL_NO_WG, void, env, ptr, ptr)
28
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/mve.decode
31
+++ b/target/arm/mve.decode
32
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111110 ....... @vldr_vstr \
33
34
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
35
VCLZ 1111 1111 1 . 11 .. 00 ... 0 0100 11 . 0 ... 0 @1op
36
+
37
+VREV16 1111 1111 1 . 11 .. 00 ... 0 0001 01 . 0 ... 0 @1op
38
+VREV32 1111 1111 1 . 11 .. 00 ... 0 0000 11 . 0 ... 0 @1op
39
+VREV64 1111 1111 1 . 11 .. 00 ... 0 0000 01 . 0 ... 0 @1op
40
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/mve_helper.c
43
+++ b/target/arm/mve_helper.c
44
@@ -XXX,XX +XXX,XX @@ DO_1OP(vclsw, 4, int32_t, clrsb32)
45
DO_1OP(vclzb, 1, uint8_t, DO_CLZ_B)
46
DO_1OP(vclzh, 2, uint16_t, DO_CLZ_H)
47
DO_1OP(vclzw, 4, uint32_t, clz32)
48
+
49
+DO_1OP(vrev16b, 2, uint16_t, bswap16)
50
+DO_1OP(vrev32b, 4, uint32_t, bswap32)
51
+DO_1OP(vrev32h, 4, uint32_t, hswap32)
52
+DO_1OP(vrev64b, 8, uint64_t, bswap64)
53
+DO_1OP(vrev64h, 8, uint64_t, hswap64)
54
+DO_1OP(vrev64w, 8, uint64_t, wswap64)
55
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/translate-mve.c
58
+++ b/target/arm/translate-mve.c
59
@@ -XXX,XX +XXX,XX @@ static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
60
61
DO_1OP(VCLZ, vclz)
62
DO_1OP(VCLS, vcls)
63
+
64
+static bool trans_VREV16(DisasContext *s, arg_1op *a)
65
+{
66
+ static MVEGenOneOpFn * const fns[] = {
67
+ gen_helper_mve_vrev16b,
68
+ NULL,
69
+ NULL,
70
+ NULL,
71
+ };
72
+ return do_1op(s, a, fns[a->size]);
73
+}
74
+
75
+static bool trans_VREV32(DisasContext *s, arg_1op *a)
76
+{
77
+ static MVEGenOneOpFn * const fns[] = {
78
+ gen_helper_mve_vrev32b,
79
+ gen_helper_mve_vrev32h,
80
+ NULL,
81
+ NULL,
82
+ };
83
+ return do_1op(s, a, fns[a->size]);
84
+}
85
+
86
+static bool trans_VREV64(DisasContext *s, arg_1op *a)
87
+{
88
+ static MVEGenOneOpFn * const fns[] = {
89
+ gen_helper_mve_vrev64b,
90
+ gen_helper_mve_vrev64h,
91
+ gen_helper_mve_vrev64w,
92
+ NULL,
93
+ };
94
+ return do_1op(s, a, fns[a->size]);
95
+}
96
--
97
2.20.1
98
99
diff view generated by jsdifflib
Deleted patch
1
Implement the MVE VMVN(register) operation. Note that for
2
predication this operation is byte-by-byte.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210617121628.20116-7-peter.maydell@linaro.org
7
---
8
target/arm/helper-mve.h | 2 ++
9
target/arm/mve.decode | 3 +++
10
target/arm/mve_helper.c | 4 ++++
11
target/arm/translate-mve.c | 5 +++++
12
4 files changed, 14 insertions(+)
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_3(mve_vrev32h, TCG_CALL_NO_WG, void, env, ptr, ptr)
19
DEF_HELPER_FLAGS_3(mve_vrev64b, TCG_CALL_NO_WG, void, env, ptr, ptr)
20
DEF_HELPER_FLAGS_3(mve_vrev64h, TCG_CALL_NO_WG, void, env, ptr, ptr)
21
DEF_HELPER_FLAGS_3(mve_vrev64w, TCG_CALL_NO_WG, void, env, ptr, ptr)
22
+
23
+DEF_HELPER_FLAGS_3(mve_vmvn, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
25
index XXXXXXX..XXXXXXX 100644
26
--- a/target/arm/mve.decode
27
+++ b/target/arm/mve.decode
28
@@ -XXX,XX +XXX,XX @@
29
@vldst_wn ... u:1 ... . . . . l:1 . rn:3 qd:3 . ... .. imm:7 &vldr_vstr
30
31
@1op .... .... .... size:2 .. .... .... .... .... &1op qd=%qd qm=%qm
32
+@1op_nosz .... .... .... .... .... .... .... .... &1op qd=%qd qm=%qm size=0
33
34
# Vector loads and stores
35
36
@@ -XXX,XX +XXX,XX @@ VCLZ 1111 1111 1 . 11 .. 00 ... 0 0100 11 . 0 ... 0 @1op
37
VREV16 1111 1111 1 . 11 .. 00 ... 0 0001 01 . 0 ... 0 @1op
38
VREV32 1111 1111 1 . 11 .. 00 ... 0 0000 11 . 0 ... 0 @1op
39
VREV64 1111 1111 1 . 11 .. 00 ... 0 0000 01 . 0 ... 0 @1op
40
+
41
+VMVN 1111 1111 1 . 11 00 00 ... 0 0101 11 . 0 ... 0 @1op_nosz
42
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
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_1OP(vrev32h, 4, uint32_t, hswap32)
47
DO_1OP(vrev64b, 8, uint64_t, bswap64)
48
DO_1OP(vrev64h, 8, uint64_t, hswap64)
49
DO_1OP(vrev64w, 8, uint64_t, wswap64)
50
+
51
+#define DO_NOT(N) (~(N))
52
+
53
+DO_1OP(vmvn, 8, uint64_t, DO_NOT)
54
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
55
index XXXXXXX..XXXXXXX 100644
56
--- a/target/arm/translate-mve.c
57
+++ b/target/arm/translate-mve.c
58
@@ -XXX,XX +XXX,XX @@ static bool trans_VREV64(DisasContext *s, arg_1op *a)
59
};
60
return do_1op(s, a, fns[a->size]);
61
}
62
+
63
+static bool trans_VMVN(DisasContext *s, arg_1op *a)
64
+{
65
+ return do_1op(s, a, gen_helper_mve_vmvn);
66
+}
67
--
68
2.20.1
69
70
diff view generated by jsdifflib
Deleted patch
1
Implement the MVE VABS functions (both integer and floating point).
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-8-peter.maydell@linaro.org
6
---
7
target/arm/helper-mve.h | 6 ++++++
8
target/arm/mve.decode | 3 +++
9
target/arm/mve_helper.c | 13 +++++++++++++
10
target/arm/translate-mve.c | 15 +++++++++++++++
11
4 files changed, 37 insertions(+)
12
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
16
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vrev64h, TCG_CALL_NO_WG, void, env, ptr, ptr)
18
DEF_HELPER_FLAGS_3(mve_vrev64w, TCG_CALL_NO_WG, void, env, ptr, ptr)
19
20
DEF_HELPER_FLAGS_3(mve_vmvn, TCG_CALL_NO_WG, void, env, ptr, ptr)
21
+
22
+DEF_HELPER_FLAGS_3(mve_vabsb, TCG_CALL_NO_WG, void, env, ptr, ptr)
23
+DEF_HELPER_FLAGS_3(mve_vabsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
+DEF_HELPER_FLAGS_3(mve_vabsw, TCG_CALL_NO_WG, void, env, ptr, ptr)
25
+DEF_HELPER_FLAGS_3(mve_vfabsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
26
+DEF_HELPER_FLAGS_3(mve_vfabss, TCG_CALL_NO_WG, void, env, ptr, ptr)
27
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/mve.decode
30
+++ b/target/arm/mve.decode
31
@@ -XXX,XX +XXX,XX @@ VREV32 1111 1111 1 . 11 .. 00 ... 0 0000 11 . 0 ... 0 @1op
32
VREV64 1111 1111 1 . 11 .. 00 ... 0 0000 01 . 0 ... 0 @1op
33
34
VMVN 1111 1111 1 . 11 00 00 ... 0 0101 11 . 0 ... 0 @1op_nosz
35
+
36
+VABS 1111 1111 1 . 11 .. 01 ... 0 0011 01 . 0 ... 0 @1op
37
+VABS_fp 1111 1111 1 . 11 .. 01 ... 0 0111 01 . 0 ... 0 @1op
38
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/mve_helper.c
41
+++ b/target/arm/mve_helper.c
42
@@ -XXX,XX +XXX,XX @@
43
#include "exec/helper-proto.h"
44
#include "exec/cpu_ldst.h"
45
#include "exec/exec-all.h"
46
+#include "tcg/tcg.h"
47
48
static uint16_t mve_element_mask(CPUARMState *env)
49
{
50
@@ -XXX,XX +XXX,XX @@ DO_1OP(vrev64w, 8, uint64_t, wswap64)
51
#define DO_NOT(N) (~(N))
52
53
DO_1OP(vmvn, 8, uint64_t, DO_NOT)
54
+
55
+#define DO_ABS(N) ((N) < 0 ? -(N) : (N))
56
+#define DO_FABSH(N) ((N) & dup_const(MO_16, 0x7fff))
57
+#define DO_FABSS(N) ((N) & dup_const(MO_32, 0x7fffffff))
58
+
59
+DO_1OP(vabsb, 1, int8_t, DO_ABS)
60
+DO_1OP(vabsh, 2, int16_t, DO_ABS)
61
+DO_1OP(vabsw, 4, int32_t, DO_ABS)
62
+
63
+/* We can do these 64 bits at a time */
64
+DO_1OP(vfabsh, 8, uint64_t, DO_FABSH)
65
+DO_1OP(vfabss, 8, uint64_t, DO_FABSS)
66
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/target/arm/translate-mve.c
69
+++ b/target/arm/translate-mve.c
70
@@ -XXX,XX +XXX,XX @@ static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
71
72
DO_1OP(VCLZ, vclz)
73
DO_1OP(VCLS, vcls)
74
+DO_1OP(VABS, vabs)
75
76
static bool trans_VREV16(DisasContext *s, arg_1op *a)
77
{
78
@@ -XXX,XX +XXX,XX @@ static bool trans_VMVN(DisasContext *s, arg_1op *a)
79
{
80
return do_1op(s, a, gen_helper_mve_vmvn);
81
}
82
+
83
+static bool trans_VABS_fp(DisasContext *s, arg_1op *a)
84
+{
85
+ static MVEGenOneOpFn * const fns[] = {
86
+ NULL,
87
+ gen_helper_mve_vfabsh,
88
+ gen_helper_mve_vfabss,
89
+ NULL,
90
+ };
91
+ if (!dc_isar_feature(aa32_mve_fp, s)) {
92
+ return false;
93
+ }
94
+ return do_1op(s, a, fns[a->size]);
95
+}
96
--
97
2.20.1
98
99
diff view generated by jsdifflib
Deleted patch
1
Implement the MVE VNEG insn (both integer and floating point forms).
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-9-peter.maydell@linaro.org
6
---
7
target/arm/helper-mve.h | 6 ++++++
8
target/arm/mve.decode | 2 ++
9
target/arm/mve_helper.c | 12 ++++++++++++
10
target/arm/translate-mve.c | 15 +++++++++++++++
11
4 files changed, 35 insertions(+)
12
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
16
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vabsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
18
DEF_HELPER_FLAGS_3(mve_vabsw, TCG_CALL_NO_WG, void, env, ptr, ptr)
19
DEF_HELPER_FLAGS_3(mve_vfabsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
20
DEF_HELPER_FLAGS_3(mve_vfabss, TCG_CALL_NO_WG, void, env, ptr, ptr)
21
+
22
+DEF_HELPER_FLAGS_3(mve_vnegb, TCG_CALL_NO_WG, void, env, ptr, ptr)
23
+DEF_HELPER_FLAGS_3(mve_vnegh, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
+DEF_HELPER_FLAGS_3(mve_vnegw, TCG_CALL_NO_WG, void, env, ptr, ptr)
25
+DEF_HELPER_FLAGS_3(mve_vfnegh, TCG_CALL_NO_WG, void, env, ptr, ptr)
26
+DEF_HELPER_FLAGS_3(mve_vfnegs, TCG_CALL_NO_WG, void, env, ptr, ptr)
27
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/mve.decode
30
+++ b/target/arm/mve.decode
31
@@ -XXX,XX +XXX,XX @@ VMVN 1111 1111 1 . 11 00 00 ... 0 0101 11 . 0 ... 0 @1op_nosz
32
33
VABS 1111 1111 1 . 11 .. 01 ... 0 0011 01 . 0 ... 0 @1op
34
VABS_fp 1111 1111 1 . 11 .. 01 ... 0 0111 01 . 0 ... 0 @1op
35
+VNEG 1111 1111 1 . 11 .. 01 ... 0 0011 11 . 0 ... 0 @1op
36
+VNEG_fp 1111 1111 1 . 11 .. 01 ... 0 0111 11 . 0 ... 0 @1op
37
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
38
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/mve_helper.c
40
+++ b/target/arm/mve_helper.c
41
@@ -XXX,XX +XXX,XX @@ DO_1OP(vabsw, 4, int32_t, DO_ABS)
42
/* We can do these 64 bits at a time */
43
DO_1OP(vfabsh, 8, uint64_t, DO_FABSH)
44
DO_1OP(vfabss, 8, uint64_t, DO_FABSS)
45
+
46
+#define DO_NEG(N) (-(N))
47
+#define DO_FNEGH(N) ((N) ^ dup_const(MO_16, 0x8000))
48
+#define DO_FNEGS(N) ((N) ^ dup_const(MO_32, 0x80000000))
49
+
50
+DO_1OP(vnegb, 1, int8_t, DO_NEG)
51
+DO_1OP(vnegh, 2, int16_t, DO_NEG)
52
+DO_1OP(vnegw, 4, int32_t, DO_NEG)
53
+
54
+/* We can do these 64 bits at a time */
55
+DO_1OP(vfnegh, 8, uint64_t, DO_FNEGH)
56
+DO_1OP(vfnegs, 8, uint64_t, DO_FNEGS)
57
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/target/arm/translate-mve.c
60
+++ b/target/arm/translate-mve.c
61
@@ -XXX,XX +XXX,XX @@ static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
62
DO_1OP(VCLZ, vclz)
63
DO_1OP(VCLS, vcls)
64
DO_1OP(VABS, vabs)
65
+DO_1OP(VNEG, vneg)
66
67
static bool trans_VREV16(DisasContext *s, arg_1op *a)
68
{
69
@@ -XXX,XX +XXX,XX @@ static bool trans_VABS_fp(DisasContext *s, arg_1op *a)
70
}
71
return do_1op(s, a, fns[a->size]);
72
}
73
+
74
+static bool trans_VNEG_fp(DisasContext *s, arg_1op *a)
75
+{
76
+ static MVEGenOneOpFn * const fns[] = {
77
+ NULL,
78
+ gen_helper_mve_vfnegh,
79
+ gen_helper_mve_vfnegs,
80
+ NULL,
81
+ };
82
+ if (!dc_isar_feature(aa32_mve_fp, s)) {
83
+ return false;
84
+ }
85
+ return do_1op(s, a, fns[a->size]);
86
+}
87
--
88
2.20.1
89
90
diff view generated by jsdifflib
Deleted patch
1
Implement the MVE VDUP insn, which duplicates a value from
2
a general-purpose register into every lane of a vector
3
register (subject to predication).
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210617121628.20116-11-peter.maydell@linaro.org
8
---
9
target/arm/helper-mve.h | 2 ++
10
target/arm/mve.decode | 10 ++++++++++
11
target/arm/mve_helper.c | 16 ++++++++++++++++
12
target/arm/translate-mve.c | 27 +++++++++++++++++++++++++++
13
4 files changed, 55 insertions(+)
14
15
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper-mve.h
18
+++ b/target/arm/helper-mve.h
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vstrb_h, TCG_CALL_NO_WG, void, env, ptr, i32)
20
DEF_HELPER_FLAGS_3(mve_vstrb_w, TCG_CALL_NO_WG, void, env, ptr, i32)
21
DEF_HELPER_FLAGS_3(mve_vstrh_w, TCG_CALL_NO_WG, void, env, ptr, i32)
22
23
+DEF_HELPER_FLAGS_3(mve_vdup, TCG_CALL_NO_WG, void, env, ptr, i32)
24
+
25
DEF_HELPER_FLAGS_3(mve_vclsb, TCG_CALL_NO_WG, void, env, ptr, ptr)
26
DEF_HELPER_FLAGS_3(mve_vclsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
27
DEF_HELPER_FLAGS_3(mve_vclsw, TCG_CALL_NO_WG, void, env, ptr, ptr)
28
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/mve.decode
31
+++ b/target/arm/mve.decode
32
@@ -XXX,XX +XXX,XX @@
33
34
%qd 22:1 13:3
35
%qm 5:1 1:3
36
+%qn 7:1 17:3
37
38
&vldr_vstr rn qd imm p a w size l u
39
&1op qd qm size
40
@@ -XXX,XX +XXX,XX @@ VABS 1111 1111 1 . 11 .. 01 ... 0 0011 01 . 0 ... 0 @1op
41
VABS_fp 1111 1111 1 . 11 .. 01 ... 0 0111 01 . 0 ... 0 @1op
42
VNEG 1111 1111 1 . 11 .. 01 ... 0 0011 11 . 0 ... 0 @1op
43
VNEG_fp 1111 1111 1 . 11 .. 01 ... 0 0111 11 . 0 ... 0 @1op
44
+
45
+&vdup qd rt size
46
+# Qd is in the fields usually named Qn
47
+@vdup .... .... . . .. ... . rt:4 .... . . . . .... qd=%qn &vdup
48
+
49
+# B and E bits encode size, which we decode here to the usual size values
50
+VDUP 1110 1110 1 1 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=0
51
+VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 1 1 0000 @vdup size=1
52
+VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=2
53
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
54
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/mve_helper.c
56
+++ b/target/arm/mve_helper.c
57
@@ -XXX,XX +XXX,XX @@ static void mergemask_sq(int64_t *d, int64_t r, uint16_t mask)
58
uint64_t *: mergemask_uq, \
59
int64_t *: mergemask_sq)(D, R, M)
60
61
+void HELPER(mve_vdup)(CPUARMState *env, void *vd, uint32_t val)
62
+{
63
+ /*
64
+ * The generated code already replicated an 8 or 16 bit constant
65
+ * into the 32-bit value, so we only need to write the 32-bit
66
+ * value to all elements of the Qreg, allowing for predication.
67
+ */
68
+ uint32_t *d = vd;
69
+ uint16_t mask = mve_element_mask(env);
70
+ unsigned e;
71
+ for (e = 0; e < 16 / 4; e++, mask >>= 4) {
72
+ mergemask(&d[H4(e)], val, mask);
73
+ }
74
+ mve_advance_vpt(env);
75
+}
76
+
77
#define DO_1OP(OP, ESIZE, TYPE, FN) \
78
void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm) \
79
{ \
80
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/target/arm/translate-mve.c
83
+++ b/target/arm/translate-mve.c
84
@@ -XXX,XX +XXX,XX @@ DO_VLDST_WIDE_NARROW(VLDSTB_H, vldrb_sh, vldrb_uh, vstrb_h)
85
DO_VLDST_WIDE_NARROW(VLDSTB_W, vldrb_sw, vldrb_uw, vstrb_w)
86
DO_VLDST_WIDE_NARROW(VLDSTH_W, vldrh_sw, vldrh_uw, vstrh_w)
87
88
+static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
89
+{
90
+ TCGv_ptr qd;
91
+ TCGv_i32 rt;
92
+
93
+ if (!dc_isar_feature(aa32_mve, s) ||
94
+ !mve_check_qreg_bank(s, a->qd)) {
95
+ return false;
96
+ }
97
+ if (a->rt == 13 || a->rt == 15) {
98
+ /* UNPREDICTABLE; we choose to UNDEF */
99
+ return false;
100
+ }
101
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
102
+ return true;
103
+ }
104
+
105
+ qd = mve_qreg_ptr(a->qd);
106
+ rt = load_reg(s, a->rt);
107
+ tcg_gen_dup_i32(a->size, rt, rt);
108
+ gen_helper_mve_vdup(cpu_env, qd, rt);
109
+ tcg_temp_free_ptr(qd);
110
+ tcg_temp_free_i32(rt);
111
+ mve_update_eci(s);
112
+ return true;
113
+}
114
+
115
static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
116
{
117
TCGv_ptr qd, qm;
118
--
119
2.20.1
120
121
diff view generated by jsdifflib
Deleted patch
1
Implement the MVE vector logical operations operating
2
on two registers.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210617121628.20116-12-peter.maydell@linaro.org
7
---
8
target/arm/helper-mve.h | 6 ++++++
9
target/arm/mve.decode | 9 +++++++++
10
target/arm/mve_helper.c | 26 ++++++++++++++++++++++++++
11
target/arm/translate-mve.c | 37 +++++++++++++++++++++++++++++++++++++
12
4 files changed, 78 insertions(+)
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_3(mve_vnegh, TCG_CALL_NO_WG, void, env, ptr, ptr)
19
DEF_HELPER_FLAGS_3(mve_vnegw, TCG_CALL_NO_WG, void, env, ptr, ptr)
20
DEF_HELPER_FLAGS_3(mve_vfnegh, TCG_CALL_NO_WG, void, env, ptr, ptr)
21
DEF_HELPER_FLAGS_3(mve_vfnegs, TCG_CALL_NO_WG, void, env, ptr, ptr)
22
+
23
+DEF_HELPER_FLAGS_4(mve_vand, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+DEF_HELPER_FLAGS_4(mve_vbic, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+DEF_HELPER_FLAGS_4(mve_vorr, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
+DEF_HELPER_FLAGS_4(mve_vorn, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_veor, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/mve.decode
31
+++ b/target/arm/mve.decode
32
@@ -XXX,XX +XXX,XX @@
33
34
&vldr_vstr rn qd imm p a w size l u
35
&1op qd qm size
36
+&2op qd qm qn size
37
38
@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
39
# Note that both Rn and Qd are 3 bits only (no D bit)
40
@@ -XXX,XX +XXX,XX @@
41
42
@1op .... .... .... size:2 .. .... .... .... .... &1op qd=%qd qm=%qm
43
@1op_nosz .... .... .... .... .... .... .... .... &1op qd=%qd qm=%qm size=0
44
+@2op_nosz .... .... .... .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn size=0
45
46
# Vector loads and stores
47
48
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111101 ....... @vldr_vstr \
49
VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111110 ....... @vldr_vstr \
50
size=2 p=1
51
52
+# Vector 2-op
53
+VAND 1110 1111 0 . 00 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
54
+VBIC 1110 1111 0 . 01 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
55
+VORR 1110 1111 0 . 10 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
56
+VORN 1110 1111 0 . 11 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
57
+VEOR 1111 1111 0 . 00 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
58
+
59
# Vector miscellaneous
60
61
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
62
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/target/arm/mve_helper.c
65
+++ b/target/arm/mve_helper.c
66
@@ -XXX,XX +XXX,XX @@ DO_1OP(vnegw, 4, int32_t, DO_NEG)
67
/* We can do these 64 bits at a time */
68
DO_1OP(vfnegh, 8, uint64_t, DO_FNEGH)
69
DO_1OP(vfnegs, 8, uint64_t, DO_FNEGS)
70
+
71
+#define DO_2OP(OP, ESIZE, TYPE, FN) \
72
+ void HELPER(glue(mve_, OP))(CPUARMState *env, \
73
+ void *vd, void *vn, void *vm) \
74
+ { \
75
+ TYPE *d = vd, *n = vn, *m = vm; \
76
+ uint16_t mask = mve_element_mask(env); \
77
+ unsigned e; \
78
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
79
+ mergemask(&d[H##ESIZE(e)], \
80
+ FN(n[H##ESIZE(e)], m[H##ESIZE(e)]), mask); \
81
+ } \
82
+ mve_advance_vpt(env); \
83
+ }
84
+
85
+#define DO_AND(N, M) ((N) & (M))
86
+#define DO_BIC(N, M) ((N) & ~(M))
87
+#define DO_ORR(N, M) ((N) | (M))
88
+#define DO_ORN(N, M) ((N) | ~(M))
89
+#define DO_EOR(N, M) ((N) ^ (M))
90
+
91
+DO_2OP(vand, 8, uint64_t, DO_AND)
92
+DO_2OP(vbic, 8, uint64_t, DO_BIC)
93
+DO_2OP(vorr, 8, uint64_t, DO_ORR)
94
+DO_2OP(vorn, 8, uint64_t, DO_ORN)
95
+DO_2OP(veor, 8, uint64_t, DO_EOR)
96
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
97
index XXXXXXX..XXXXXXX 100644
98
--- a/target/arm/translate-mve.c
99
+++ b/target/arm/translate-mve.c
100
@@ -XXX,XX +XXX,XX @@
101
102
typedef void MVEGenLdStFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
103
typedef void MVEGenOneOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
104
+typedef void MVEGenTwoOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr);
105
106
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
107
static inline long mve_qreg_offset(unsigned reg)
108
@@ -XXX,XX +XXX,XX @@ static bool trans_VNEG_fp(DisasContext *s, arg_1op *a)
109
}
110
return do_1op(s, a, fns[a->size]);
111
}
112
+
113
+static bool do_2op(DisasContext *s, arg_2op *a, MVEGenTwoOpFn fn)
114
+{
115
+ TCGv_ptr qd, qn, qm;
116
+
117
+ if (!dc_isar_feature(aa32_mve, s) ||
118
+ !mve_check_qreg_bank(s, a->qd | a->qn | a->qm) ||
119
+ !fn) {
120
+ return false;
121
+ }
122
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
123
+ return true;
124
+ }
125
+
126
+ qd = mve_qreg_ptr(a->qd);
127
+ qn = mve_qreg_ptr(a->qn);
128
+ qm = mve_qreg_ptr(a->qm);
129
+ fn(cpu_env, qd, qn, qm);
130
+ tcg_temp_free_ptr(qd);
131
+ tcg_temp_free_ptr(qn);
132
+ tcg_temp_free_ptr(qm);
133
+ mve_update_eci(s);
134
+ return true;
135
+}
136
+
137
+#define DO_LOGIC(INSN, HELPER) \
138
+ static bool trans_##INSN(DisasContext *s, arg_2op *a) \
139
+ { \
140
+ return do_2op(s, a, HELPER); \
141
+ }
142
+
143
+DO_LOGIC(VAND, gen_helper_mve_vand)
144
+DO_LOGIC(VBIC, gen_helper_mve_vbic)
145
+DO_LOGIC(VORR, gen_helper_mve_vorr)
146
+DO_LOGIC(VORN, gen_helper_mve_vorn)
147
+DO_LOGIC(VEOR, gen_helper_mve_veor)
148
--
149
2.20.1
150
151
diff view generated by jsdifflib
Deleted patch
1
Implement the MVE VADD, VSUB and VMUL insns.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-13-peter.maydell@linaro.org
6
---
7
target/arm/helper-mve.h | 12 ++++++++++++
8
target/arm/mve.decode | 5 +++++
9
target/arm/mve_helper.c | 14 ++++++++++++++
10
target/arm/translate-mve.c | 16 ++++++++++++++++
11
4 files changed, 47 insertions(+)
12
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
16
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vbic, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
18
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_vaddb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
+DEF_HELPER_FLAGS_4(mve_vaddh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+DEF_HELPER_FLAGS_4(mve_vaddw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+
26
+DEF_HELPER_FLAGS_4(mve_vsubb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_vsubh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+DEF_HELPER_FLAGS_4(mve_vsubw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
+
30
+DEF_HELPER_FLAGS_4(mve_vmulb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
+DEF_HELPER_FLAGS_4(mve_vmulh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
+DEF_HELPER_FLAGS_4(mve_vmulw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/mve.decode
36
+++ b/target/arm/mve.decode
37
@@ -XXX,XX +XXX,XX @@
38
39
@1op .... .... .... size:2 .. .... .... .... .... &1op qd=%qd qm=%qm
40
@1op_nosz .... .... .... .... .... .... .... .... &1op qd=%qd qm=%qm size=0
41
+@2op .... .... .. size:2 .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn
42
@2op_nosz .... .... .... .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn size=0
43
44
# Vector loads and stores
45
@@ -XXX,XX +XXX,XX @@ VORR 1110 1111 0 . 10 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
46
VORN 1110 1111 0 . 11 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
47
VEOR 1111 1111 0 . 00 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
48
49
+VADD 1110 1111 0 . .. ... 0 ... 0 1000 . 1 . 0 ... 0 @2op
50
+VSUB 1111 1111 0 . .. ... 0 ... 0 1000 . 1 . 0 ... 0 @2op
51
+VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
52
+
53
# Vector miscellaneous
54
55
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
56
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/mve_helper.c
59
+++ b/target/arm/mve_helper.c
60
@@ -XXX,XX +XXX,XX @@ DO_1OP(vfnegs, 8, uint64_t, DO_FNEGS)
61
mve_advance_vpt(env); \
62
}
63
64
+/* provide unsigned 2-op helpers for all sizes */
65
+#define DO_2OP_U(OP, FN) \
66
+ DO_2OP(OP##b, 1, uint8_t, FN) \
67
+ DO_2OP(OP##h, 2, uint16_t, FN) \
68
+ DO_2OP(OP##w, 4, uint32_t, FN)
69
+
70
#define DO_AND(N, M) ((N) & (M))
71
#define DO_BIC(N, M) ((N) & ~(M))
72
#define DO_ORR(N, M) ((N) | (M))
73
@@ -XXX,XX +XXX,XX @@ DO_2OP(vbic, 8, uint64_t, DO_BIC)
74
DO_2OP(vorr, 8, uint64_t, DO_ORR)
75
DO_2OP(vorn, 8, uint64_t, DO_ORN)
76
DO_2OP(veor, 8, uint64_t, DO_EOR)
77
+
78
+#define DO_ADD(N, M) ((N) + (M))
79
+#define DO_SUB(N, M) ((N) - (M))
80
+#define DO_MUL(N, M) ((N) * (M))
81
+
82
+DO_2OP_U(vadd, DO_ADD)
83
+DO_2OP_U(vsub, DO_SUB)
84
+DO_2OP_U(vmul, DO_MUL)
85
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/target/arm/translate-mve.c
88
+++ b/target/arm/translate-mve.c
89
@@ -XXX,XX +XXX,XX @@ DO_LOGIC(VBIC, gen_helper_mve_vbic)
90
DO_LOGIC(VORR, gen_helper_mve_vorr)
91
DO_LOGIC(VORN, gen_helper_mve_vorn)
92
DO_LOGIC(VEOR, gen_helper_mve_veor)
93
+
94
+#define DO_2OP(INSN, FN) \
95
+ static bool trans_##INSN(DisasContext *s, arg_2op *a) \
96
+ { \
97
+ static MVEGenTwoOpFn * const fns[] = { \
98
+ gen_helper_mve_##FN##b, \
99
+ gen_helper_mve_##FN##h, \
100
+ gen_helper_mve_##FN##w, \
101
+ NULL, \
102
+ }; \
103
+ return do_2op(s, a, fns[a->size]); \
104
+ }
105
+
106
+DO_2OP(VADD, vadd)
107
+DO_2OP(VSUB, vsub)
108
+DO_2OP(VMUL, vmul)
109
--
110
2.20.1
111
112
diff view generated by jsdifflib
Deleted patch
1
Implement the MVE VMULH insn, which performs a vector
2
multiply and returns the high half of the result.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210617121628.20116-14-peter.maydell@linaro.org
7
---
8
target/arm/helper-mve.h | 7 +++++++
9
target/arm/mve.decode | 3 +++
10
target/arm/mve_helper.c | 26 ++++++++++++++++++++++++++
11
target/arm/translate-mve.c | 2 ++
12
4 files changed, 38 insertions(+)
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_vsubw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
DEF_HELPER_FLAGS_4(mve_vmulb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
DEF_HELPER_FLAGS_4(mve_vmulh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
DEF_HELPER_FLAGS_4(mve_vmulw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
+
23
+DEF_HELPER_FLAGS_4(mve_vmulhsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+DEF_HELPER_FLAGS_4(mve_vmulhsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+DEF_HELPER_FLAGS_4(mve_vmulhsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
+DEF_HELPER_FLAGS_4(mve_vmulhub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_vmulhuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+DEF_HELPER_FLAGS_4(mve_vmulhuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/mve.decode
32
+++ b/target/arm/mve.decode
33
@@ -XXX,XX +XXX,XX @@ VADD 1110 1111 0 . .. ... 0 ... 0 1000 . 1 . 0 ... 0 @2op
34
VSUB 1111 1111 0 . .. ... 0 ... 0 1000 . 1 . 0 ... 0 @2op
35
VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
36
37
+VMULH_S 111 0 1110 0 . .. ...1 ... 0 1110 . 0 . 0 ... 1 @2op
38
+VMULH_U 111 1 1110 0 . .. ...1 ... 0 1110 . 0 . 0 ... 1 @2op
39
+
40
# Vector miscellaneous
41
42
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
43
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/mve_helper.c
46
+++ b/target/arm/mve_helper.c
47
@@ -XXX,XX +XXX,XX @@ DO_2OP(veor, 8, uint64_t, DO_EOR)
48
DO_2OP_U(vadd, DO_ADD)
49
DO_2OP_U(vsub, DO_SUB)
50
DO_2OP_U(vmul, DO_MUL)
51
+
52
+/*
53
+ * Because the computation type is at least twice as large as required,
54
+ * these work for both signed and unsigned source types.
55
+ */
56
+static inline uint8_t do_mulh_b(int32_t n, int32_t m)
57
+{
58
+ return (n * m) >> 8;
59
+}
60
+
61
+static inline uint16_t do_mulh_h(int32_t n, int32_t m)
62
+{
63
+ return (n * m) >> 16;
64
+}
65
+
66
+static inline uint32_t do_mulh_w(int64_t n, int64_t m)
67
+{
68
+ return (n * m) >> 32;
69
+}
70
+
71
+DO_2OP(vmulhsb, 1, int8_t, do_mulh_b)
72
+DO_2OP(vmulhsh, 2, int16_t, do_mulh_h)
73
+DO_2OP(vmulhsw, 4, int32_t, do_mulh_w)
74
+DO_2OP(vmulhub, 1, uint8_t, do_mulh_b)
75
+DO_2OP(vmulhuh, 2, uint16_t, do_mulh_h)
76
+DO_2OP(vmulhuw, 4, uint32_t, do_mulh_w)
77
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/target/arm/translate-mve.c
80
+++ b/target/arm/translate-mve.c
81
@@ -XXX,XX +XXX,XX @@ DO_LOGIC(VEOR, gen_helper_mve_veor)
82
DO_2OP(VADD, vadd)
83
DO_2OP(VSUB, vsub)
84
DO_2OP(VMUL, vmul)
85
+DO_2OP(VMULH_S, vmulhs)
86
+DO_2OP(VMULH_U, vmulhu)
87
--
88
2.20.1
89
90
diff view generated by jsdifflib
Deleted patch
1
Implement the MVE VMAX and VMIN insns.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-16-peter.maydell@linaro.org
6
---
7
target/arm/helper-mve.h | 14 ++++++++++++++
8
target/arm/mve.decode | 5 +++++
9
target/arm/mve_helper.c | 14 ++++++++++++++
10
target/arm/translate-mve.c | 4 ++++
11
4 files changed, 37 insertions(+)
12
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
16
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vrmulhsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
18
DEF_HELPER_FLAGS_4(mve_vrmulhub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
DEF_HELPER_FLAGS_4(mve_vrmulhuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
DEF_HELPER_FLAGS_4(mve_vrmulhuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
+
22
+DEF_HELPER_FLAGS_4(mve_vmaxsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
+DEF_HELPER_FLAGS_4(mve_vmaxsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+DEF_HELPER_FLAGS_4(mve_vmaxsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+DEF_HELPER_FLAGS_4(mve_vmaxub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
+DEF_HELPER_FLAGS_4(mve_vmaxuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_vmaxuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+
29
+DEF_HELPER_FLAGS_4(mve_vminsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
+DEF_HELPER_FLAGS_4(mve_vminsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
+DEF_HELPER_FLAGS_4(mve_vminsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
+DEF_HELPER_FLAGS_4(mve_vminub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
+DEF_HELPER_FLAGS_4(mve_vminuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
+DEF_HELPER_FLAGS_4(mve_vminuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
35
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
36
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/mve.decode
38
+++ b/target/arm/mve.decode
39
@@ -XXX,XX +XXX,XX @@ VMULH_U 111 1 1110 0 . .. ...1 ... 0 1110 . 0 . 0 ... 1 @2op
40
VRMULH_S 111 0 1110 0 . .. ...1 ... 1 1110 . 0 . 0 ... 1 @2op
41
VRMULH_U 111 1 1110 0 . .. ...1 ... 1 1110 . 0 . 0 ... 1 @2op
42
43
+VMAX_S 111 0 1111 0 . .. ... 0 ... 0 0110 . 1 . 0 ... 0 @2op
44
+VMAX_U 111 1 1111 0 . .. ... 0 ... 0 0110 . 1 . 0 ... 0 @2op
45
+VMIN_S 111 0 1111 0 . .. ... 0 ... 0 0110 . 1 . 1 ... 0 @2op
46
+VMIN_U 111 1 1111 0 . .. ... 0 ... 0 0110 . 1 . 1 ... 0 @2op
47
+
48
# Vector miscellaneous
49
50
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
51
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/mve_helper.c
54
+++ b/target/arm/mve_helper.c
55
@@ -XXX,XX +XXX,XX @@ DO_1OP(vfnegs, 8, uint64_t, DO_FNEGS)
56
DO_2OP(OP##h, 2, uint16_t, FN) \
57
DO_2OP(OP##w, 4, uint32_t, FN)
58
59
+/* provide signed 2-op helpers for all sizes */
60
+#define DO_2OP_S(OP, FN) \
61
+ DO_2OP(OP##b, 1, int8_t, FN) \
62
+ DO_2OP(OP##h, 2, int16_t, FN) \
63
+ DO_2OP(OP##w, 4, int32_t, FN)
64
+
65
#define DO_AND(N, M) ((N) & (M))
66
#define DO_BIC(N, M) ((N) & ~(M))
67
#define DO_ORR(N, M) ((N) | (M))
68
@@ -XXX,XX +XXX,XX @@ DO_2OP(vrmulhsw, 4, int32_t, do_rmulh_w)
69
DO_2OP(vrmulhub, 1, uint8_t, do_rmulh_b)
70
DO_2OP(vrmulhuh, 2, uint16_t, do_rmulh_h)
71
DO_2OP(vrmulhuw, 4, uint32_t, do_rmulh_w)
72
+
73
+#define DO_MAX(N, M) ((N) >= (M) ? (N) : (M))
74
+#define DO_MIN(N, M) ((N) >= (M) ? (M) : (N))
75
+
76
+DO_2OP_S(vmaxs, DO_MAX)
77
+DO_2OP_U(vmaxu, DO_MAX)
78
+DO_2OP_S(vmins, DO_MIN)
79
+DO_2OP_U(vminu, DO_MIN)
80
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/target/arm/translate-mve.c
83
+++ b/target/arm/translate-mve.c
84
@@ -XXX,XX +XXX,XX @@ DO_2OP(VMULH_S, vmulhs)
85
DO_2OP(VMULH_U, vmulhu)
86
DO_2OP(VRMULH_S, vrmulhs)
87
DO_2OP(VRMULH_U, vrmulhu)
88
+DO_2OP(VMAX_S, vmaxs)
89
+DO_2OP(VMAX_U, vmaxu)
90
+DO_2OP(VMIN_S, vmins)
91
+DO_2OP(VMIN_U, vminu)
92
--
93
2.20.1
94
95
diff view generated by jsdifflib
Deleted patch
1
Implement the MVE VABD insn.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-17-peter.maydell@linaro.org
6
---
7
target/arm/helper-mve.h | 7 +++++++
8
target/arm/mve.decode | 3 +++
9
target/arm/mve_helper.c | 5 +++++
10
target/arm/translate-mve.c | 2 ++
11
4 files changed, 17 insertions(+)
12
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
16
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vminsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
18
DEF_HELPER_FLAGS_4(mve_vminub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
DEF_HELPER_FLAGS_4(mve_vminuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
DEF_HELPER_FLAGS_4(mve_vminuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
+
22
+DEF_HELPER_FLAGS_4(mve_vabdsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
+DEF_HELPER_FLAGS_4(mve_vabdsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+DEF_HELPER_FLAGS_4(mve_vabdsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+DEF_HELPER_FLAGS_4(mve_vabdub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
+DEF_HELPER_FLAGS_4(mve_vabduh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_vabduw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/mve.decode
31
+++ b/target/arm/mve.decode
32
@@ -XXX,XX +XXX,XX @@ VMAX_U 111 1 1111 0 . .. ... 0 ... 0 0110 . 1 . 0 ... 0 @2op
33
VMIN_S 111 0 1111 0 . .. ... 0 ... 0 0110 . 1 . 1 ... 0 @2op
34
VMIN_U 111 1 1111 0 . .. ... 0 ... 0 0110 . 1 . 1 ... 0 @2op
35
36
+VABD_S 111 0 1111 0 . .. ... 0 ... 0 0111 . 1 . 0 ... 0 @2op
37
+VABD_U 111 1 1111 0 . .. ... 0 ... 0 0111 . 1 . 0 ... 0 @2op
38
+
39
# Vector miscellaneous
40
41
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
42
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/mve_helper.c
45
+++ b/target/arm/mve_helper.c
46
@@ -XXX,XX +XXX,XX @@ DO_2OP_S(vmaxs, DO_MAX)
47
DO_2OP_U(vmaxu, DO_MAX)
48
DO_2OP_S(vmins, DO_MIN)
49
DO_2OP_U(vminu, DO_MIN)
50
+
51
+#define DO_ABD(N, M) ((N) >= (M) ? (N) - (M) : (M) - (N))
52
+
53
+DO_2OP_S(vabds, DO_ABD)
54
+DO_2OP_U(vabdu, DO_ABD)
55
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/translate-mve.c
58
+++ b/target/arm/translate-mve.c
59
@@ -XXX,XX +XXX,XX @@ DO_2OP(VMAX_S, vmaxs)
60
DO_2OP(VMAX_U, vmaxu)
61
DO_2OP(VMIN_S, vmins)
62
DO_2OP(VMIN_U, vminu)
63
+DO_2OP(VABD_S, vabds)
64
+DO_2OP(VABD_U, vabdu)
65
--
66
2.20.1
67
68
diff view generated by jsdifflib
Deleted patch
1
Implement MVE VHADD and VHSUB insns, which perform an addition
2
or subtraction and then halve the result.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210617121628.20116-18-peter.maydell@linaro.org
7
---
8
target/arm/helper-mve.h | 14 ++++++++++++++
9
target/arm/mve.decode | 5 +++++
10
target/arm/mve_helper.c | 25 +++++++++++++++++++++++++
11
target/arm/translate-mve.c | 4 ++++
12
4 files changed, 48 insertions(+)
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_vabdsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
DEF_HELPER_FLAGS_4(mve_vabdub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
DEF_HELPER_FLAGS_4(mve_vabduh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
DEF_HELPER_FLAGS_4(mve_vabduw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
+
23
+DEF_HELPER_FLAGS_4(mve_vhaddsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+DEF_HELPER_FLAGS_4(mve_vhaddsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+DEF_HELPER_FLAGS_4(mve_vhaddsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
+DEF_HELPER_FLAGS_4(mve_vhaddub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_vhadduh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+DEF_HELPER_FLAGS_4(mve_vhadduw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
+
30
+DEF_HELPER_FLAGS_4(mve_vhsubsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
+DEF_HELPER_FLAGS_4(mve_vhsubsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
+DEF_HELPER_FLAGS_4(mve_vhsubsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
+DEF_HELPER_FLAGS_4(mve_vhsubub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
+DEF_HELPER_FLAGS_4(mve_vhsubuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
35
+DEF_HELPER_FLAGS_4(mve_vhsubuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/mve.decode
39
+++ b/target/arm/mve.decode
40
@@ -XXX,XX +XXX,XX @@ VMIN_U 111 1 1111 0 . .. ... 0 ... 0 0110 . 1 . 1 ... 0 @2op
41
VABD_S 111 0 1111 0 . .. ... 0 ... 0 0111 . 1 . 0 ... 0 @2op
42
VABD_U 111 1 1111 0 . .. ... 0 ... 0 0111 . 1 . 0 ... 0 @2op
43
44
+VHADD_S 111 0 1111 0 . .. ... 0 ... 0 0000 . 1 . 0 ... 0 @2op
45
+VHADD_U 111 1 1111 0 . .. ... 0 ... 0 0000 . 1 . 0 ... 0 @2op
46
+VHSUB_S 111 0 1111 0 . .. ... 0 ... 0 0010 . 1 . 0 ... 0 @2op
47
+VHSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 0 ... 0 @2op
48
+
49
# Vector miscellaneous
50
51
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
52
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/mve_helper.c
55
+++ b/target/arm/mve_helper.c
56
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vminu, DO_MIN)
57
58
DO_2OP_S(vabds, DO_ABD)
59
DO_2OP_U(vabdu, DO_ABD)
60
+
61
+static inline uint32_t do_vhadd_u(uint32_t n, uint32_t m)
62
+{
63
+ return ((uint64_t)n + m) >> 1;
64
+}
65
+
66
+static inline int32_t do_vhadd_s(int32_t n, int32_t m)
67
+{
68
+ return ((int64_t)n + m) >> 1;
69
+}
70
+
71
+static inline uint32_t do_vhsub_u(uint32_t n, uint32_t m)
72
+{
73
+ return ((uint64_t)n - m) >> 1;
74
+}
75
+
76
+static inline int32_t do_vhsub_s(int32_t n, int32_t m)
77
+{
78
+ return ((int64_t)n - m) >> 1;
79
+}
80
+
81
+DO_2OP_S(vhadds, do_vhadd_s)
82
+DO_2OP_U(vhaddu, do_vhadd_u)
83
+DO_2OP_S(vhsubs, do_vhsub_s)
84
+DO_2OP_U(vhsubu, do_vhsub_u)
85
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
86
index XXXXXXX..XXXXXXX 100644
87
--- a/target/arm/translate-mve.c
88
+++ b/target/arm/translate-mve.c
89
@@ -XXX,XX +XXX,XX @@ DO_2OP(VMIN_S, vmins)
90
DO_2OP(VMIN_U, vminu)
91
DO_2OP(VABD_S, vabds)
92
DO_2OP(VABD_U, vabdu)
93
+DO_2OP(VHADD_S, vhadds)
94
+DO_2OP(VHADD_U, vhaddu)
95
+DO_2OP(VHSUB_S, vhsubs)
96
+DO_2OP(VHSUB_U, vhsubu)
97
--
98
2.20.1
99
100
diff view generated by jsdifflib
Deleted patch
1
Implement the MVE VMULL insn, which multiplies two single
2
width integer elements to produce a double width result.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210617121628.20116-19-peter.maydell@linaro.org
7
---
8
target/arm/helper-mve.h | 14 ++++++++++++++
9
target/arm/mve.decode | 5 +++++
10
target/arm/mve_helper.c | 34 ++++++++++++++++++++++++++++++++++
11
target/arm/translate-mve.c | 4 ++++
12
4 files changed, 57 insertions(+)
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_vhsubsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
DEF_HELPER_FLAGS_4(mve_vhsubub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
DEF_HELPER_FLAGS_4(mve_vhsubuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
DEF_HELPER_FLAGS_4(mve_vhsubuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
+
23
+DEF_HELPER_FLAGS_4(mve_vmullbsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
24
+DEF_HELPER_FLAGS_4(mve_vmullbsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+DEF_HELPER_FLAGS_4(mve_vmullbsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
+DEF_HELPER_FLAGS_4(mve_vmullbub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(mve_vmullbuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+DEF_HELPER_FLAGS_4(mve_vmullbuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
+
30
+DEF_HELPER_FLAGS_4(mve_vmulltsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
+DEF_HELPER_FLAGS_4(mve_vmulltsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
+DEF_HELPER_FLAGS_4(mve_vmulltsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
33
+DEF_HELPER_FLAGS_4(mve_vmulltub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
+DEF_HELPER_FLAGS_4(mve_vmulltuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
35
+DEF_HELPER_FLAGS_4(mve_vmulltuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/mve.decode
39
+++ b/target/arm/mve.decode
40
@@ -XXX,XX +XXX,XX @@ VHADD_U 111 1 1111 0 . .. ... 0 ... 0 0000 . 1 . 0 ... 0 @2op
41
VHSUB_S 111 0 1111 0 . .. ... 0 ... 0 0010 . 1 . 0 ... 0 @2op
42
VHSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 0 ... 0 @2op
43
44
+VMULL_BS 111 0 1110 0 . .. ... 1 ... 0 1110 . 0 . 0 ... 0 @2op
45
+VMULL_BU 111 1 1110 0 . .. ... 1 ... 0 1110 . 0 . 0 ... 0 @2op
46
+VMULL_TS 111 0 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
47
+VMULL_TU 111 1 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
48
+
49
# Vector miscellaneous
50
51
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
52
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/mve_helper.c
55
+++ b/target/arm/mve_helper.c
56
@@ -XXX,XX +XXX,XX @@ DO_1OP(vfnegs, 8, uint64_t, DO_FNEGS)
57
DO_2OP(OP##h, 2, int16_t, FN) \
58
DO_2OP(OP##w, 4, int32_t, FN)
59
60
+/*
61
+ * "Long" operations where two half-sized inputs (taken from either the
62
+ * top or the bottom of the input vector) produce a double-width result.
63
+ * Here ESIZE, TYPE are for the input, and LESIZE, LTYPE for the output.
64
+ */
65
+#define DO_2OP_L(OP, TOP, ESIZE, TYPE, LESIZE, LTYPE, FN) \
66
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, void *vm) \
67
+ { \
68
+ LTYPE *d = vd; \
69
+ TYPE *n = vn, *m = vm; \
70
+ uint16_t mask = mve_element_mask(env); \
71
+ unsigned le; \
72
+ for (le = 0; le < 16 / LESIZE; le++, mask >>= LESIZE) { \
73
+ LTYPE r = FN((LTYPE)n[H##ESIZE(le * 2 + TOP)], \
74
+ m[H##ESIZE(le * 2 + TOP)]); \
75
+ mergemask(&d[H##LESIZE(le)], r, mask); \
76
+ } \
77
+ mve_advance_vpt(env); \
78
+ }
79
+
80
#define DO_AND(N, M) ((N) & (M))
81
#define DO_BIC(N, M) ((N) & ~(M))
82
#define DO_ORR(N, M) ((N) | (M))
83
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vadd, DO_ADD)
84
DO_2OP_U(vsub, DO_SUB)
85
DO_2OP_U(vmul, DO_MUL)
86
87
+DO_2OP_L(vmullbsb, 0, 1, int8_t, 2, int16_t, DO_MUL)
88
+DO_2OP_L(vmullbsh, 0, 2, int16_t, 4, int32_t, DO_MUL)
89
+DO_2OP_L(vmullbsw, 0, 4, int32_t, 8, int64_t, DO_MUL)
90
+DO_2OP_L(vmullbub, 0, 1, uint8_t, 2, uint16_t, DO_MUL)
91
+DO_2OP_L(vmullbuh, 0, 2, uint16_t, 4, uint32_t, DO_MUL)
92
+DO_2OP_L(vmullbuw, 0, 4, uint32_t, 8, uint64_t, DO_MUL)
93
+
94
+DO_2OP_L(vmulltsb, 1, 1, int8_t, 2, int16_t, DO_MUL)
95
+DO_2OP_L(vmulltsh, 1, 2, int16_t, 4, int32_t, DO_MUL)
96
+DO_2OP_L(vmulltsw, 1, 4, int32_t, 8, int64_t, DO_MUL)
97
+DO_2OP_L(vmulltub, 1, 1, uint8_t, 2, uint16_t, DO_MUL)
98
+DO_2OP_L(vmulltuh, 1, 2, uint16_t, 4, uint32_t, DO_MUL)
99
+DO_2OP_L(vmulltuw, 1, 4, uint32_t, 8, uint64_t, DO_MUL)
100
+
101
/*
102
* Because the computation type is at least twice as large as required,
103
* these work for both signed and unsigned source types.
104
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
105
index XXXXXXX..XXXXXXX 100644
106
--- a/target/arm/translate-mve.c
107
+++ b/target/arm/translate-mve.c
108
@@ -XXX,XX +XXX,XX @@ DO_2OP(VHADD_S, vhadds)
109
DO_2OP(VHADD_U, vhaddu)
110
DO_2OP(VHSUB_S, vhsubs)
111
DO_2OP(VHSUB_U, vhsubu)
112
+DO_2OP(VMULL_BS, vmullbs)
113
+DO_2OP(VMULL_BU, vmullbu)
114
+DO_2OP(VMULL_TS, vmullts)
115
+DO_2OP(VMULL_TU, vmulltu)
116
--
117
2.20.1
118
119
diff view generated by jsdifflib
Deleted patch
1
Implement the MVE insn VMLSLDAV, which multiplies source elements,
2
alternately adding and subtracting them, and accumulates into a
3
64-bit result in a pair of general purpose registers.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20210617121628.20116-21-peter.maydell@linaro.org
8
---
9
target/arm/helper-mve.h | 5 +++++
10
target/arm/mve.decode | 2 ++
11
target/arm/mve_helper.c | 5 +++++
12
target/arm/translate-mve.c | 11 +++++++++++
13
4 files changed, 23 insertions(+)
14
15
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
16
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/helper-mve.h
18
+++ b/target/arm/helper-mve.h
19
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmlaldavxsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
20
21
DEF_HELPER_FLAGS_4(mve_vmlaldavuh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
22
DEF_HELPER_FLAGS_4(mve_vmlaldavuw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
23
+
24
+DEF_HELPER_FLAGS_4(mve_vmlsldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
25
+DEF_HELPER_FLAGS_4(mve_vmlsldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
26
+DEF_HELPER_FLAGS_4(mve_vmlsldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
27
+DEF_HELPER_FLAGS_4(mve_vmlsldavxsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
28
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/mve.decode
31
+++ b/target/arm/mve.decode
32
@@ -XXX,XX +XXX,XX @@ VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=2
33
qn=%qn rdahi=%rdahi rdalo=%rdalo size=%size_16 &vmlaldav
34
VMLALDAV_S 1110 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 0 @vmlaldav
35
VMLALDAV_U 1111 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 0 @vmlaldav
36
+
37
+VMLSLDAV 1110 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav
38
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/mve_helper.c
41
+++ b/target/arm/mve_helper.c
42
@@ -XXX,XX +XXX,XX @@ DO_LDAV(vmlaldavxsw, 4, int32_t, true, +=, +=)
43
44
DO_LDAV(vmlaldavuh, 2, uint16_t, false, +=, +=)
45
DO_LDAV(vmlaldavuw, 4, uint32_t, false, +=, +=)
46
+
47
+DO_LDAV(vmlsldavsh, 2, int16_t, false, +=, -=)
48
+DO_LDAV(vmlsldavxsh, 2, int16_t, true, +=, -=)
49
+DO_LDAV(vmlsldavsw, 4, int32_t, false, +=, -=)
50
+DO_LDAV(vmlsldavxsw, 4, int32_t, true, +=, -=)
51
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
52
index XXXXXXX..XXXXXXX 100644
53
--- a/target/arm/translate-mve.c
54
+++ b/target/arm/translate-mve.c
55
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLALDAV_U(DisasContext *s, arg_vmlaldav *a)
56
};
57
return do_long_dual_acc(s, a, fns[a->size][a->x]);
58
}
59
+
60
+static bool trans_VMLSLDAV(DisasContext *s, arg_vmlaldav *a)
61
+{
62
+ static MVEGenDualAccOpFn * const fns[4][2] = {
63
+ { NULL, NULL },
64
+ { gen_helper_mve_vmlsldavsh, gen_helper_mve_vmlsldavxsh },
65
+ { gen_helper_mve_vmlsldavsw, gen_helper_mve_vmlsldavxsw },
66
+ { NULL, NULL },
67
+ };
68
+ return do_long_dual_acc(s, a, fns[a->size][a->x]);
69
+}
70
--
71
2.20.1
72
73
diff view generated by jsdifflib
Deleted patch
1
Implement the scalar form of the MVE VADD insn. This takes the
2
scalar operand from a general purpose register.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210617121628.20116-23-peter.maydell@linaro.org
7
---
8
target/arm/helper-mve.h | 4 ++++
9
target/arm/mve.decode | 7 ++++++
10
target/arm/mve_helper.c | 22 +++++++++++++++++++
11
target/arm/translate-mve.c | 45 ++++++++++++++++++++++++++++++++++++++
12
4 files changed, 78 insertions(+)
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_vmulltub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
DEF_HELPER_FLAGS_4(mve_vmulltuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
DEF_HELPER_FLAGS_4(mve_vmulltuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
22
+DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
23
+DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
+DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
+
26
DEF_HELPER_FLAGS_4(mve_vmlaldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
27
DEF_HELPER_FLAGS_4(mve_vmlaldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
28
DEF_HELPER_FLAGS_4(mve_vmlaldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
29
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/mve.decode
32
+++ b/target/arm/mve.decode
33
@@ -XXX,XX +XXX,XX @@
34
&vldr_vstr rn qd imm p a w size l u
35
&1op qd qm size
36
&2op qd qm qn size
37
+&2scalar qd qn rm size
38
39
@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
40
# Note that both Rn and Qd are 3 bits only (no D bit)
41
@@ -XXX,XX +XXX,XX @@
42
@2op .... .... .. size:2 .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn
43
@2op_nosz .... .... .... .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn size=0
44
45
+@2scalar .... .... .. size:2 .... .... .... .... rm:4 &2scalar qd=%qd qn=%qn
46
+
47
# Vector loads and stores
48
49
# Widening loads and narrowing stores:
50
@@ -XXX,XX +XXX,XX @@ VRMLALDAVH_S 1110 1110 1 ... ... 0 ... x:1 1111 . 0 a:1 0 ... 0 @vmlaldav_no
51
VRMLALDAVH_U 1111 1110 1 ... ... 0 ... x:1 1111 . 0 a:1 0 ... 0 @vmlaldav_nosz
52
53
VRMLSLDAVH 1111 1110 1 ... ... 0 ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav_nosz
54
+
55
+# Scalar operations
56
+
57
+VADD_scalar 1110 1110 0 . .. ... 1 ... 0 1111 . 100 .... @2scalar
58
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/mve_helper.c
61
+++ b/target/arm/mve_helper.c
62
@@ -XXX,XX +XXX,XX @@ DO_2OP_S(vhsubs, do_vhsub_s)
63
DO_2OP_U(vhsubu, do_vhsub_u)
64
65
66
+#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
67
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
68
+ uint32_t rm) \
69
+ { \
70
+ TYPE *d = vd, *n = vn; \
71
+ TYPE m = rm; \
72
+ uint16_t mask = mve_element_mask(env); \
73
+ unsigned e; \
74
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
75
+ mergemask(&d[H##ESIZE(e)], FN(n[H##ESIZE(e)], m), mask); \
76
+ } \
77
+ mve_advance_vpt(env); \
78
+ }
79
+
80
+/* provide unsigned 2-op scalar helpers for all sizes */
81
+#define DO_2OP_SCALAR_U(OP, FN) \
82
+ DO_2OP_SCALAR(OP##b, 1, uint8_t, FN) \
83
+ DO_2OP_SCALAR(OP##h, 2, uint16_t, FN) \
84
+ DO_2OP_SCALAR(OP##w, 4, uint32_t, FN)
85
+
86
+DO_2OP_SCALAR_U(vadd_scalar, DO_ADD)
87
+
88
/*
89
* Multiply add long dual accumulate ops.
90
*/
91
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
92
index XXXXXXX..XXXXXXX 100644
93
--- a/target/arm/translate-mve.c
94
+++ b/target/arm/translate-mve.c
95
@@ -XXX,XX +XXX,XX @@
96
typedef void MVEGenLdStFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
97
typedef void MVEGenOneOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
98
typedef void MVEGenTwoOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr);
99
+typedef void MVEGenTwoOpScalarFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
100
typedef void MVEGenDualAccOpFn(TCGv_i64, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i64);
101
102
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
103
@@ -XXX,XX +XXX,XX @@ DO_2OP(VMULL_BU, vmullbu)
104
DO_2OP(VMULL_TS, vmullts)
105
DO_2OP(VMULL_TU, vmulltu)
106
107
+static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
108
+ MVEGenTwoOpScalarFn fn)
109
+{
110
+ TCGv_ptr qd, qn;
111
+ TCGv_i32 rm;
112
+
113
+ if (!dc_isar_feature(aa32_mve, s) ||
114
+ !mve_check_qreg_bank(s, a->qd | a->qn) ||
115
+ !fn) {
116
+ return false;
117
+ }
118
+ if (a->rm == 13 || a->rm == 15) {
119
+ /* UNPREDICTABLE */
120
+ return false;
121
+ }
122
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
123
+ return true;
124
+ }
125
+
126
+ qd = mve_qreg_ptr(a->qd);
127
+ qn = mve_qreg_ptr(a->qn);
128
+ rm = load_reg(s, a->rm);
129
+ fn(cpu_env, qd, qn, rm);
130
+ tcg_temp_free_i32(rm);
131
+ tcg_temp_free_ptr(qd);
132
+ tcg_temp_free_ptr(qn);
133
+ mve_update_eci(s);
134
+ return true;
135
+}
136
+
137
+#define DO_2OP_SCALAR(INSN, FN) \
138
+ static bool trans_##INSN(DisasContext *s, arg_2scalar *a) \
139
+ { \
140
+ static MVEGenTwoOpScalarFn * const fns[] = { \
141
+ gen_helper_mve_##FN##b, \
142
+ gen_helper_mve_##FN##h, \
143
+ gen_helper_mve_##FN##w, \
144
+ NULL, \
145
+ }; \
146
+ return do_2op_scalar(s, a, fns[a->size]); \
147
+ }
148
+
149
+DO_2OP_SCALAR(VADD_scalar, vadd_scalar)
150
+
151
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
152
MVEGenDualAccOpFn *fn)
153
{
154
--
155
2.20.1
156
157
diff view generated by jsdifflib
Deleted patch
1
Implement the scalar forms of the MVE VSUB and VMUL insns.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-24-peter.maydell@linaro.org
6
---
7
target/arm/helper-mve.h | 8 ++++++++
8
target/arm/mve.decode | 2 ++
9
target/arm/mve_helper.c | 2 ++
10
target/arm/translate-mve.c | 2 ++
11
4 files changed, 14 insertions(+)
12
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
16
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
18
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
19
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
20
21
+DEF_HELPER_FLAGS_4(mve_vsub_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
22
+DEF_HELPER_FLAGS_4(mve_vsub_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
23
+DEF_HELPER_FLAGS_4(mve_vsub_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
+
25
+DEF_HELPER_FLAGS_4(mve_vmul_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
26
+DEF_HELPER_FLAGS_4(mve_vmul_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
27
+DEF_HELPER_FLAGS_4(mve_vmul_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
28
+
29
DEF_HELPER_FLAGS_4(mve_vmlaldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
30
DEF_HELPER_FLAGS_4(mve_vmlaldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
31
DEF_HELPER_FLAGS_4(mve_vmlaldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
32
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
33
index XXXXXXX..XXXXXXX 100644
34
--- a/target/arm/mve.decode
35
+++ b/target/arm/mve.decode
36
@@ -XXX,XX +XXX,XX @@ VRMLSLDAVH 1111 1110 1 ... ... 0 ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav_no
37
# Scalar operations
38
39
VADD_scalar 1110 1110 0 . .. ... 1 ... 0 1111 . 100 .... @2scalar
40
+VSUB_scalar 1110 1110 0 . .. ... 1 ... 1 1111 . 100 .... @2scalar
41
+VMUL_scalar 1110 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
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_2OP_U(vhsubu, do_vhsub_u)
47
DO_2OP_SCALAR(OP##w, 4, uint32_t, FN)
48
49
DO_2OP_SCALAR_U(vadd_scalar, DO_ADD)
50
+DO_2OP_SCALAR_U(vsub_scalar, DO_SUB)
51
+DO_2OP_SCALAR_U(vmul_scalar, DO_MUL)
52
53
/*
54
* Multiply add long dual accumulate ops.
55
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
56
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/translate-mve.c
58
+++ b/target/arm/translate-mve.c
59
@@ -XXX,XX +XXX,XX @@ static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
60
}
61
62
DO_2OP_SCALAR(VADD_scalar, vadd_scalar)
63
+DO_2OP_SCALAR(VSUB_scalar, vsub_scalar)
64
+DO_2OP_SCALAR(VMUL_scalar, vmul_scalar)
65
66
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
67
MVEGenDualAccOpFn *fn)
68
--
69
2.20.1
70
71
diff view generated by jsdifflib
Deleted patch
1
Implement the scalar variants of the MVE VHADD and VHSUB insns.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20210617121628.20116-25-peter.maydell@linaro.org
6
---
7
target/arm/helper-mve.h | 16 ++++++++++++++++
8
target/arm/mve.decode | 4 ++++
9
target/arm/mve_helper.c | 8 ++++++++
10
target/arm/translate-mve.c | 4 ++++
11
4 files changed, 32 insertions(+)
12
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/helper-mve.h
16
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmul_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
18
DEF_HELPER_FLAGS_4(mve_vmul_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
19
DEF_HELPER_FLAGS_4(mve_vmul_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
20
21
+DEF_HELPER_FLAGS_4(mve_vhadds_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
22
+DEF_HELPER_FLAGS_4(mve_vhadds_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
23
+DEF_HELPER_FLAGS_4(mve_vhadds_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
+
25
+DEF_HELPER_FLAGS_4(mve_vhaddu_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
26
+DEF_HELPER_FLAGS_4(mve_vhaddu_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
27
+DEF_HELPER_FLAGS_4(mve_vhaddu_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
28
+
29
+DEF_HELPER_FLAGS_4(mve_vhsubs_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
30
+DEF_HELPER_FLAGS_4(mve_vhsubs_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
+DEF_HELPER_FLAGS_4(mve_vhsubs_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
32
+
33
+DEF_HELPER_FLAGS_4(mve_vhsubu_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
34
+DEF_HELPER_FLAGS_4(mve_vhsubu_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
35
+DEF_HELPER_FLAGS_4(mve_vhsubu_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
36
+
37
DEF_HELPER_FLAGS_4(mve_vmlaldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
38
DEF_HELPER_FLAGS_4(mve_vmlaldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
39
DEF_HELPER_FLAGS_4(mve_vmlaldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
40
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/mve.decode
43
+++ b/target/arm/mve.decode
44
@@ -XXX,XX +XXX,XX @@ VRMLSLDAVH 1111 1110 1 ... ... 0 ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav_no
45
VADD_scalar 1110 1110 0 . .. ... 1 ... 0 1111 . 100 .... @2scalar
46
VSUB_scalar 1110 1110 0 . .. ... 1 ... 1 1111 . 100 .... @2scalar
47
VMUL_scalar 1110 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
48
+VHADD_S_scalar 1110 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
49
+VHADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
50
+VHSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
51
+VHSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
52
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/mve_helper.c
55
+++ b/target/arm/mve_helper.c
56
@@ -XXX,XX +XXX,XX @@ DO_2OP_U(vhsubu, do_vhsub_u)
57
DO_2OP_SCALAR(OP##b, 1, uint8_t, FN) \
58
DO_2OP_SCALAR(OP##h, 2, uint16_t, FN) \
59
DO_2OP_SCALAR(OP##w, 4, uint32_t, FN)
60
+#define DO_2OP_SCALAR_S(OP, FN) \
61
+ DO_2OP_SCALAR(OP##b, 1, int8_t, FN) \
62
+ DO_2OP_SCALAR(OP##h, 2, int16_t, FN) \
63
+ DO_2OP_SCALAR(OP##w, 4, int32_t, FN)
64
65
DO_2OP_SCALAR_U(vadd_scalar, DO_ADD)
66
DO_2OP_SCALAR_U(vsub_scalar, DO_SUB)
67
DO_2OP_SCALAR_U(vmul_scalar, DO_MUL)
68
+DO_2OP_SCALAR_S(vhadds_scalar, do_vhadd_s)
69
+DO_2OP_SCALAR_U(vhaddu_scalar, do_vhadd_u)
70
+DO_2OP_SCALAR_S(vhsubs_scalar, do_vhsub_s)
71
+DO_2OP_SCALAR_U(vhsubu_scalar, do_vhsub_u)
72
73
/*
74
* Multiply add long dual accumulate ops.
75
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/translate-mve.c
78
+++ b/target/arm/translate-mve.c
79
@@ -XXX,XX +XXX,XX @@ static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
80
DO_2OP_SCALAR(VADD_scalar, vadd_scalar)
81
DO_2OP_SCALAR(VSUB_scalar, vsub_scalar)
82
DO_2OP_SCALAR(VMUL_scalar, vmul_scalar)
83
+DO_2OP_SCALAR(VHADD_S_scalar, vhadds_scalar)
84
+DO_2OP_SCALAR(VHADD_U_scalar, vhaddu_scalar)
85
+DO_2OP_SCALAR(VHSUB_S_scalar, vhsubs_scalar)
86
+DO_2OP_SCALAR(VHSUB_U_scalar, vhsubu_scalar)
87
88
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
89
MVEGenDualAccOpFn *fn)
90
--
91
2.20.1
92
93
diff view generated by jsdifflib
Deleted patch
1
Implement the MVE VBRSR insn, which reverses a specified
2
number of bits in each element, setting the rest to zero.
3
1
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210617121628.20116-26-peter.maydell@linaro.org
7
---
8
target/arm/helper-mve.h | 4 ++++
9
target/arm/mve.decode | 1 +
10
target/arm/mve_helper.c | 43 ++++++++++++++++++++++++++++++++++++++
11
target/arm/translate-mve.c | 1 +
12
4 files changed, 49 insertions(+)
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_vhsubu_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
19
DEF_HELPER_FLAGS_4(mve_vhsubu_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
20
DEF_HELPER_FLAGS_4(mve_vhsubu_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
21
22
+DEF_HELPER_FLAGS_4(mve_vbrsrb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
23
+DEF_HELPER_FLAGS_4(mve_vbrsrh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
+DEF_HELPER_FLAGS_4(mve_vbrsrw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
+
26
DEF_HELPER_FLAGS_4(mve_vmlaldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
27
DEF_HELPER_FLAGS_4(mve_vmlaldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
28
DEF_HELPER_FLAGS_4(mve_vmlaldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
29
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/mve.decode
32
+++ b/target/arm/mve.decode
33
@@ -XXX,XX +XXX,XX @@ VHADD_S_scalar 1110 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
34
VHADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
35
VHSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
36
VHSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
37
+VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
38
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
39
index XXXXXXX..XXXXXXX 100644
40
--- a/target/arm/mve_helper.c
41
+++ b/target/arm/mve_helper.c
42
@@ -XXX,XX +XXX,XX @@ DO_2OP_SCALAR_U(vhaddu_scalar, do_vhadd_u)
43
DO_2OP_SCALAR_S(vhsubs_scalar, do_vhsub_s)
44
DO_2OP_SCALAR_U(vhsubu_scalar, do_vhsub_u)
45
46
+static inline uint32_t do_vbrsrb(uint32_t n, uint32_t m)
47
+{
48
+ m &= 0xff;
49
+ if (m == 0) {
50
+ return 0;
51
+ }
52
+ n = revbit8(n);
53
+ if (m < 8) {
54
+ n >>= 8 - m;
55
+ }
56
+ return n;
57
+}
58
+
59
+static inline uint32_t do_vbrsrh(uint32_t n, uint32_t m)
60
+{
61
+ m &= 0xff;
62
+ if (m == 0) {
63
+ return 0;
64
+ }
65
+ n = revbit16(n);
66
+ if (m < 16) {
67
+ n >>= 16 - m;
68
+ }
69
+ return n;
70
+}
71
+
72
+static inline uint32_t do_vbrsrw(uint32_t n, uint32_t m)
73
+{
74
+ m &= 0xff;
75
+ if (m == 0) {
76
+ return 0;
77
+ }
78
+ n = revbit32(n);
79
+ if (m < 32) {
80
+ n >>= 32 - m;
81
+ }
82
+ return n;
83
+}
84
+
85
+DO_2OP_SCALAR(vbrsrb, 1, uint8_t, do_vbrsrb)
86
+DO_2OP_SCALAR(vbrsrh, 2, uint16_t, do_vbrsrh)
87
+DO_2OP_SCALAR(vbrsrw, 4, uint32_t, do_vbrsrw)
88
+
89
/*
90
* Multiply add long dual accumulate ops.
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 @@ DO_2OP_SCALAR(VHADD_S_scalar, vhadds_scalar)
97
DO_2OP_SCALAR(VHADD_U_scalar, vhaddu_scalar)
98
DO_2OP_SCALAR(VHSUB_S_scalar, vhsubs_scalar)
99
DO_2OP_SCALAR(VHSUB_U_scalar, vhsubu_scalar)
100
+DO_2OP_SCALAR(VBRSR, vbrsr)
101
102
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
103
MVEGenDualAccOpFn *fn)
104
--
105
2.20.1
106
107
diff view generated by jsdifflib