1
Arm queue; some of the simpler stuff, things other have reviewed (thanks!), etc.
1
First set of arm patches for 6.2. I have a lot more in my
2
to-review queue still...
2
3
3
-- PMM
4
-- PMM
4
5
5
The following changes since commit 5d2f557b47dfbf8f23277a5bdd8473d4607c681a:
6
The following changes since commit d42685765653ec155fdf60910662f8830bdb2cef:
6
7
7
Merge remote-tracking branch 'remotes/kraxel/tags/vga-20200605-pull-request' into staging (2020-06-05 13:53:05 +0100)
8
Open 6.2 development tree (2021-08-25 10:25:12 +0100)
8
9
9
are available in the Git repository at:
10
are available in the Git repository at:
10
11
11
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20200605
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20210825
12
13
13
for you to fetch changes up to 2c35a39eda0b16c2ed85c94cec204bf5efb97812:
14
for you to fetch changes up to 24b1a6aa43615be22c7ee66bd68ec5675f6a6a9a:
14
15
15
target/arm: Convert Neon one-register-and-immediate insns to decodetree (2020-06-05 17:23:10 +0100)
16
docs: Document how to use gdb with unix sockets (2021-08-25 10:48:51 +0100)
16
17
17
----------------------------------------------------------------
18
----------------------------------------------------------------
18
target-arm queue:
19
target-arm queue:
19
hw/ssi/imx_spi: Handle tx burst lengths other than 8 correctly
20
* More MVE emulation work
20
hw/input/pxa2xx_keypad: Replace hw_error() by qemu_log_mask()
21
* Implement M-profile trapping on division by zero
21
hw/arm/pxa2xx: Replace printf() call by qemu_log_mask()
22
* kvm: use RCU_READ_LOCK_GUARD() in kvm_arch_fixup_msi_route()
22
target/arm: Convert crypto insns to gvec
23
* hw/char/pl011: add support for sending break
23
hw/adc/stm32f2xx_adc: Correct memory region size and access size
24
* fsl-imx6ul: Instantiate SAI1/2/3 and ASRC as unimplemented devices
24
tests/acceptance: Add a boot test for the xlnx-versal-virt machine
25
* hw/dma/pl330: Add memory region to replace default
25
docs/system: Document Aspeed boards
26
* sbsa-ref: Rename SBSA_GWDT enum value
26
raspi: Add model of the USB controller
27
* fsl-imx7: Instantiate SAI1/2/3 as unimplemented devices
27
target/arm: Convert 2-reg-and-shift and 1-reg-imm Neon insns to decodetree
28
* docs: Document how to use gdb with unix sockets
28
29
29
----------------------------------------------------------------
30
----------------------------------------------------------------
30
Cédric Le Goater (1):
31
Eduardo Habkost (1):
31
docs/system: Document Aspeed boards
32
sbsa-ref: Rename SBSA_GWDT enum value
32
33
33
Eden Mikitas (2):
34
Guenter Roeck (2):
34
hw/ssi/imx_spi: changed while statement to prevent underflow
35
fsl-imx6ul: Instantiate SAI1/2/3 and ASRC as unimplemented devices
35
hw/ssi/imx_spi: Removed unnecessary cast of rx data received from slave
36
fsl-imx7: Instantiate SAI1/2/3 as unimplemented devices
36
37
37
Paul Zimmerman (7):
38
Hamza Mahfooz (1):
38
raspi: add BCM2835 SOC MPHI emulation
39
target/arm: kvm: use RCU_READ_LOCK_GUARD() in kvm_arch_fixup_msi_route()
39
dwc-hsotg (dwc2) USB host controller register definitions
40
dwc-hsotg (dwc2) USB host controller state definitions
41
dwc-hsotg (dwc2) USB host controller emulation
42
usb: add short-packet handling to usb-storage driver
43
wire in the dwc-hsotg (dwc2) USB host controller emulation
44
raspi2 acceptance test: add test for dwc-hsotg (dwc2) USB host
45
40
46
Peter Maydell (9):
41
Jan Luebbe (1):
47
target/arm: Convert Neon VSHL and VSLI 2-reg-shift insn to decodetree
42
hw/char/pl011: add support for sending break
48
target/arm: Convert Neon VSHR 2-reg-shift insns to decodetree
49
target/arm: Convert Neon VSRA, VSRI, VRSHR, VRSRA 2-reg-shift insns to decodetree
50
target/arm: Convert VQSHLU, VQSHL 2-reg-shift insns to decodetree
51
target/arm: Convert Neon narrowing shifts with op==8 to decodetree
52
target/arm: Convert Neon narrowing shifts with op==9 to decodetree
53
target/arm: Convert Neon VSHLL, VMOVL to decodetree
54
target/arm: Convert VCVT fixed-point ops to decodetree
55
target/arm: Convert Neon one-register-and-immediate insns to decodetree
56
43
57
Philippe Mathieu-Daudé (3):
44
Peter Maydell (37):
58
hw/input/pxa2xx_keypad: Replace hw_error() by qemu_log_mask()
45
target/arm: Note that we handle VMOVL as a special case of VSHLL
59
hw/arm/pxa2xx: Replace printf() call by qemu_log_mask()
46
target/arm: Print MVE VPR in CPU dumps
60
hw/adc/stm32f2xx_adc: Correct memory region size and access size
47
target/arm: Fix MVE VSLI by 0 and VSRI by <dt>
48
target/arm: Fix signed VADDV
49
target/arm: Fix mask handling for MVE narrowing operations
50
target/arm: Fix 48-bit saturating shifts
51
target/arm: Fix MVE 48-bit SQRSHRL for small right shifts
52
target/arm: Fix calculation of LTP mask when LR is 0
53
target/arm: Factor out mve_eci_mask()
54
target/arm: Fix VPT advance when ECI is non-zero
55
target/arm: Fix VLDRB/H/W for predicated elements
56
target/arm: Implement MVE VMULL (polynomial)
57
target/arm: Implement MVE incrementing/decrementing dup insns
58
target/arm: Factor out gen_vpst()
59
target/arm: Implement MVE integer vector comparisons
60
target/arm: Implement MVE integer vector-vs-scalar comparisons
61
target/arm: Implement MVE VPSEL
62
target/arm: Implement MVE VMLAS
63
target/arm: Implement MVE shift-by-scalar
64
target/arm: Move 'x' and 'a' bit definitions into vmlaldav formats
65
target/arm: Implement MVE integer min/max across vector
66
target/arm: Implement MVE VABAV
67
target/arm: Implement MVE narrowing moves
68
target/arm: Rename MVEGenDualAccOpFn to MVEGenLongDualAccOpFn
69
target/arm: Implement MVE VMLADAV and VMLSLDAV
70
target/arm: Implement MVE VMLA
71
target/arm: Implement MVE saturating doubling multiply accumulates
72
target/arm: Implement MVE VQABS, VQNEG
73
target/arm: Implement MVE VMAXA, VMINA
74
target/arm: Implement MVE VMOV to/from 2 general-purpose registers
75
target/arm: Implement MVE VPNOT
76
target/arm: Implement MVE VCTP
77
target/arm: Implement MVE scatter-gather insns
78
target/arm: Implement MVE scatter-gather immediate forms
79
target/arm: Implement MVE interleaving loads/stores
80
target/arm: Re-indent sdiv and udiv helpers
81
target/arm: Implement M-profile trapping on division by zero
61
82
62
Richard Henderson (6):
83
Sebastian Meyer (1):
63
target/arm: Convert aes and sm4 to gvec helpers
84
docs: Document how to use gdb with unix sockets
64
target/arm: Convert rax1 to gvec helpers
65
target/arm: Convert sha512 and sm3 to gvec helpers
66
target/arm: Convert sha1 and sha256 to gvec helpers
67
target/arm: Split helper_crypto_sha1_3reg
68
target/arm: Split helper_crypto_sm3tt
69
85
70
Thomas Huth (1):
86
Wen, Jianxian (1):
71
tests/acceptance: Add a boot test for the xlnx-versal-virt machine
87
hw/dma/pl330: Add memory region to replace default
72
88
73
docs/system/arm/aspeed.rst | 85 ++
89
docs/system/gdb.rst | 26 +-
74
docs/system/target-arm.rst | 1 +
90
include/hw/arm/fsl-imx7.h | 5 +
75
hw/usb/hcd-dwc2.h | 190 +++++
91
target/arm/cpu.h | 1 +
76
include/hw/arm/bcm2835_peripherals.h | 5 +-
92
target/arm/helper-mve.h | 283 ++++++++++
77
include/hw/misc/bcm2835_mphi.h | 44 +
93
target/arm/helper.h | 4 +-
78
include/hw/usb/dwc2-regs.h | 899 ++++++++++++++++++++
94
target/arm/translate-a32.h | 2 +
79
target/arm/helper.h | 45 +-
95
target/arm/vec_internal.h | 11 +
80
target/arm/translate-a64.h | 3 +
96
target/arm/mve.decode | 226 +++++++-
81
target/arm/vec_internal.h | 33 +
97
target/arm/t32.decode | 1 +
82
target/arm/neon-dp.decode | 214 ++++-
98
hw/arm/exynos4210.c | 3 +
83
hw/adc/stm32f2xx_adc.c | 4 +-
99
hw/arm/fsl-imx6ul.c | 12 +
84
hw/arm/bcm2835_peripherals.c | 38 +-
100
hw/arm/fsl-imx7.c | 7 +
85
hw/arm/pxa2xx.c | 66 +-
101
hw/arm/sbsa-ref.c | 6 +-
86
hw/input/pxa2xx_keypad.c | 10 +-
102
hw/arm/xilinx_zynq.c | 3 +
87
hw/misc/bcm2835_mphi.c | 191 +++++
103
hw/char/pl011.c | 6 +
88
hw/ssi/imx_spi.c | 4 +-
104
hw/dma/pl330.c | 26 +-
89
hw/usb/dev-storage.c | 15 +-
105
target/arm/cpu.c | 3 +
90
hw/usb/hcd-dwc2.c | 1417 ++++++++++++++++++++++++++++++++
106
target/arm/helper.c | 34 +-
91
target/arm/crypto_helper.c | 267 ++++--
107
target/arm/kvm.c | 17 +-
92
target/arm/translate-a64.c | 198 ++---
108
target/arm/m_helper.c | 4 +
93
target/arm/translate-neon.inc.c | 796 ++++++++++++++----
109
target/arm/mve_helper.c | 1254 ++++++++++++++++++++++++++++++++++++++++++--
94
target/arm/translate.c | 539 +-----------
110
target/arm/translate-mve.c | 877 ++++++++++++++++++++++++++++++-
95
target/arm/vec_helper.c | 12 +-
111
target/arm/translate-vfp.c | 2 +-
96
hw/misc/Makefile.objs | 1 +
112
target/arm/translate.c | 37 +-
97
hw/usb/Kconfig | 5 +
113
target/arm/vec_helper.c | 14 +-
98
hw/usb/Makefile.objs | 1 +
114
25 files changed, 2746 insertions(+), 118 deletions(-)
99
hw/usb/trace-events | 50 ++
100
tests/acceptance/boot_linux_console.py | 35 +-
101
28 files changed, 4258 insertions(+), 910 deletions(-)
102
create mode 100644 docs/system/arm/aspeed.rst
103
create mode 100644 hw/usb/hcd-dwc2.h
104
create mode 100644 include/hw/misc/bcm2835_mphi.h
105
create mode 100644 include/hw/usb/dwc2-regs.h
106
create mode 100644 target/arm/vec_internal.h
107
create mode 100644 hw/misc/bcm2835_mphi.c
108
create mode 100644 hw/usb/hcd-dwc2.c
109
115
diff view generated by jsdifflib
1
Convert the VSRA, VSRI, VRSHR, VRSRA 2-reg-shift insns to decodetree.
1
Although the architecture doesn't define it as an alias, VMOVL
2
(These are the last instructions in the group that are vectorized;
2
(vector move long) is encoded as a VSHLL with a zero shift.
3
the rest all require looping over each element.)
3
Add a comment in the decode file noting that we handle VMOVL
4
as part of VSHLL.
4
5
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200522145520.6778-4-peter.maydell@linaro.org
8
---
8
---
9
target/arm/neon-dp.decode | 35 ++++++++++++++++++++++
9
target/arm/mve.decode | 2 ++
10
target/arm/translate-neon.inc.c | 7 +++++
10
1 file changed, 2 insertions(+)
11
target/arm/translate.c | 52 +++------------------------------
12
3 files changed, 46 insertions(+), 48 deletions(-)
13
11
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
12
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
15
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/neon-dp.decode
14
--- a/target/arm/mve.decode
17
+++ b/target/arm/neon-dp.decode
15
+++ b/target/arm/mve.decode
18
@@ -XXX,XX +XXX,XX @@ VSHR_U_2sh 1111 001 1 1 . ...... .... 0000 . . . 1 .... @2reg_shr_s
16
@@ -XXX,XX +XXX,XX @@ VRSHRI_U 111 1 1111 1 . ... ... ... 0 0010 0 1 . 1 ... 0 @2_shr_h
19
VSHR_U_2sh 1111 001 1 1 . ...... .... 0000 . . . 1 .... @2reg_shr_h
17
VRSHRI_U 111 1 1111 1 . ... ... ... 0 0010 0 1 . 1 ... 0 @2_shr_w
20
VSHR_U_2sh 1111 001 1 1 . ...... .... 0000 . . . 1 .... @2reg_shr_b
18
21
19
# VSHLL T1 encoding; the T2 VSHLL encoding is elsewhere in this file
22
+VSRA_S_2sh 1111 001 0 1 . ...... .... 0001 . . . 1 .... @2reg_shr_d
20
+# Note that VMOVL is encoded as "VSHLL with a zero shift count"; we
23
+VSRA_S_2sh 1111 001 0 1 . ...... .... 0001 . . . 1 .... @2reg_shr_s
21
+# implement it that way rather than special-casing it in the decode.
24
+VSRA_S_2sh 1111 001 0 1 . ...... .... 0001 . . . 1 .... @2reg_shr_h
22
VSHLL_BS 111 0 1110 1 . 1 .. ... ... 0 1111 0 1 . 0 ... 0 @2_shll_b
25
+VSRA_S_2sh 1111 001 0 1 . ...... .... 0001 . . . 1 .... @2reg_shr_b
23
VSHLL_BS 111 0 1110 1 . 1 .. ... ... 0 1111 0 1 . 0 ... 0 @2_shll_h
26
+
24
27
+VSRA_U_2sh 1111 001 1 1 . ...... .... 0001 . . . 1 .... @2reg_shr_d
28
+VSRA_U_2sh 1111 001 1 1 . ...... .... 0001 . . . 1 .... @2reg_shr_s
29
+VSRA_U_2sh 1111 001 1 1 . ...... .... 0001 . . . 1 .... @2reg_shr_h
30
+VSRA_U_2sh 1111 001 1 1 . ...... .... 0001 . . . 1 .... @2reg_shr_b
31
+
32
+VRSHR_S_2sh 1111 001 0 1 . ...... .... 0010 . . . 1 .... @2reg_shr_d
33
+VRSHR_S_2sh 1111 001 0 1 . ...... .... 0010 . . . 1 .... @2reg_shr_s
34
+VRSHR_S_2sh 1111 001 0 1 . ...... .... 0010 . . . 1 .... @2reg_shr_h
35
+VRSHR_S_2sh 1111 001 0 1 . ...... .... 0010 . . . 1 .... @2reg_shr_b
36
+
37
+VRSHR_U_2sh 1111 001 1 1 . ...... .... 0010 . . . 1 .... @2reg_shr_d
38
+VRSHR_U_2sh 1111 001 1 1 . ...... .... 0010 . . . 1 .... @2reg_shr_s
39
+VRSHR_U_2sh 1111 001 1 1 . ...... .... 0010 . . . 1 .... @2reg_shr_h
40
+VRSHR_U_2sh 1111 001 1 1 . ...... .... 0010 . . . 1 .... @2reg_shr_b
41
+
42
+VRSRA_S_2sh 1111 001 0 1 . ...... .... 0011 . . . 1 .... @2reg_shr_d
43
+VRSRA_S_2sh 1111 001 0 1 . ...... .... 0011 . . . 1 .... @2reg_shr_s
44
+VRSRA_S_2sh 1111 001 0 1 . ...... .... 0011 . . . 1 .... @2reg_shr_h
45
+VRSRA_S_2sh 1111 001 0 1 . ...... .... 0011 . . . 1 .... @2reg_shr_b
46
+
47
+VRSRA_U_2sh 1111 001 1 1 . ...... .... 0011 . . . 1 .... @2reg_shr_d
48
+VRSRA_U_2sh 1111 001 1 1 . ...... .... 0011 . . . 1 .... @2reg_shr_s
49
+VRSRA_U_2sh 1111 001 1 1 . ...... .... 0011 . . . 1 .... @2reg_shr_h
50
+VRSRA_U_2sh 1111 001 1 1 . ...... .... 0011 . . . 1 .... @2reg_shr_b
51
+
52
+VSRI_2sh 1111 001 1 1 . ...... .... 0100 . . . 1 .... @2reg_shr_d
53
+VSRI_2sh 1111 001 1 1 . ...... .... 0100 . . . 1 .... @2reg_shr_s
54
+VSRI_2sh 1111 001 1 1 . ...... .... 0100 . . . 1 .... @2reg_shr_h
55
+VSRI_2sh 1111 001 1 1 . ...... .... 0100 . . . 1 .... @2reg_shr_b
56
+
57
VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_d
58
VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_s
59
VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_h
60
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/translate-neon.inc.c
63
+++ b/target/arm/translate-neon.inc.c
64
@@ -XXX,XX +XXX,XX @@ static bool do_vector_2sh(DisasContext *s, arg_2reg_shift *a, GVecGen2iFn *fn)
65
66
DO_2SH(VSHL, tcg_gen_gvec_shli)
67
DO_2SH(VSLI, gen_gvec_sli)
68
+DO_2SH(VSRI, gen_gvec_sri)
69
+DO_2SH(VSRA_S, gen_gvec_ssra)
70
+DO_2SH(VSRA_U, gen_gvec_usra)
71
+DO_2SH(VRSHR_S, gen_gvec_srshr)
72
+DO_2SH(VRSHR_U, gen_gvec_urshr)
73
+DO_2SH(VRSRA_S, gen_gvec_srsra)
74
+DO_2SH(VRSRA_U, gen_gvec_ursra)
75
76
static bool trans_VSHR_S_2sh(DisasContext *s, arg_2reg_shift *a)
77
{
78
diff --git a/target/arm/translate.c b/target/arm/translate.c
79
index XXXXXXX..XXXXXXX 100644
80
--- a/target/arm/translate.c
81
+++ b/target/arm/translate.c
82
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
83
84
switch (op) {
85
case 0: /* VSHR */
86
+ case 1: /* VSRA */
87
+ case 2: /* VRSHR */
88
+ case 3: /* VRSRA */
89
+ case 4: /* VSRI */
90
case 5: /* VSHL, VSLI */
91
return 1; /* handled by decodetree */
92
default:
93
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
94
shift = shift - (1 << (size + 3));
95
}
96
97
- switch (op) {
98
- case 1: /* VSRA */
99
- /* Right shift comes here negative. */
100
- shift = -shift;
101
- if (u) {
102
- gen_gvec_usra(size, rd_ofs, rm_ofs, shift,
103
- vec_size, vec_size);
104
- } else {
105
- gen_gvec_ssra(size, rd_ofs, rm_ofs, shift,
106
- vec_size, vec_size);
107
- }
108
- return 0;
109
-
110
- case 2: /* VRSHR */
111
- /* Right shift comes here negative. */
112
- shift = -shift;
113
- if (u) {
114
- gen_gvec_urshr(size, rd_ofs, rm_ofs, shift,
115
- vec_size, vec_size);
116
- } else {
117
- gen_gvec_srshr(size, rd_ofs, rm_ofs, shift,
118
- vec_size, vec_size);
119
- }
120
- return 0;
121
-
122
- case 3: /* VRSRA */
123
- /* Right shift comes here negative. */
124
- shift = -shift;
125
- if (u) {
126
- gen_gvec_ursra(size, rd_ofs, rm_ofs, shift,
127
- vec_size, vec_size);
128
- } else {
129
- gen_gvec_srsra(size, rd_ofs, rm_ofs, shift,
130
- vec_size, vec_size);
131
- }
132
- return 0;
133
-
134
- case 4: /* VSRI */
135
- if (!u) {
136
- return 1;
137
- }
138
- /* Right shift comes here negative. */
139
- shift = -shift;
140
- gen_gvec_sri(size, rd_ofs, rm_ofs, shift,
141
- vec_size, vec_size);
142
- return 0;
143
- }
144
-
145
if (size == 3) {
146
count = q + 1;
147
} else {
148
--
25
--
149
2.20.1
26
2.20.1
150
27
151
28
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
Include the MVE VPR register value in the CPU dumps produced by
2
arm_cpu_dump_state() if we are printing FPU information. This
3
makes it easier to interpret debug logs when predication is
4
active.
2
5
3
hw_error() calls exit(). This a bit overkill when we can log
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
the accesses as unimplemented or guest error.
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
---
9
target/arm/cpu.c | 3 +++
10
1 file changed, 3 insertions(+)
5
11
6
When fuzzing the devices, we don't want the whole process to
12
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
7
exit. Replace some hw_error() calls by qemu_log_mask()
8
(missed in commit 5a0001ec7e).
9
10
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
11
Message-id: 20200525114123.21317-2-f4bug@amsat.org
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
hw/input/pxa2xx_keypad.c | 10 +++++++---
16
1 file changed, 7 insertions(+), 3 deletions(-)
17
18
diff --git a/hw/input/pxa2xx_keypad.c b/hw/input/pxa2xx_keypad.c
19
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/input/pxa2xx_keypad.c
14
--- a/target/arm/cpu.c
21
+++ b/hw/input/pxa2xx_keypad.c
15
+++ b/target/arm/cpu.c
22
@@ -XXX,XX +XXX,XX @@
16
@@ -XXX,XX +XXX,XX @@ static void arm_cpu_dump_state(CPUState *cs, FILE *f, int flags)
23
*/
17
i, v);
24
18
}
25
#include "qemu/osdep.h"
19
qemu_fprintf(f, "FPSCR: %08x\n", vfp_get_fpscr(env));
26
-#include "hw/hw.h"
20
+ if (cpu_isar_feature(aa32_mve, cpu)) {
27
+#include "qemu/log.h"
21
+ qemu_fprintf(f, "VPR: %08x\n", env->v7m.vpr);
28
#include "hw/irq.h"
22
+ }
29
#include "migration/vmstate.h"
30
#include "hw/arm/pxa.h"
31
@@ -XXX,XX +XXX,XX @@ static uint64_t pxa2xx_keypad_read(void *opaque, hwaddr offset,
32
return s->kpkdi;
33
break;
34
default:
35
- hw_error("%s: Bad offset " REG_FMT "\n", __func__, offset);
36
+ qemu_log_mask(LOG_GUEST_ERROR,
37
+ "%s: Bad read offset 0x%"HWADDR_PRIx"\n",
38
+ __func__, offset);
39
}
40
41
return 0;
42
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_keypad_write(void *opaque, hwaddr offset,
43
break;
44
45
default:
46
- hw_error("%s: Bad offset " REG_FMT "\n", __func__, offset);
47
+ qemu_log_mask(LOG_GUEST_ERROR,
48
+ "%s: Bad write offset 0x%"HWADDR_PRIx"\n",
49
+ __func__, offset);
50
}
23
}
51
}
24
}
52
25
53
--
26
--
54
2.20.1
27
2.20.1
55
28
56
29
diff view generated by jsdifflib
New patch
1
In the MVE shift-and-insert insns, we special case VSLI by 0
2
and VSRI by <dt>. VSRI by <dt> means "don't update the destination",
3
which is what we've implemented. However VSLI by 0 is "set
4
destination to the input", so we don't want to use the same
5
special-casing that we do for VSRI by <dt>.
1
6
7
Since the generic logic gives the right answer for a shift
8
by 0, just use that.
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
---
13
target/arm/mve_helper.c | 9 +++++----
14
1 file changed, 5 insertions(+), 4 deletions(-)
15
16
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/mve_helper.c
19
+++ b/target/arm/mve_helper.c
20
@@ -XXX,XX +XXX,XX @@ DO_2SHIFT_S(vrshli_s, DO_VRSHLS)
21
uint16_t mask; \
22
uint64_t shiftmask; \
23
unsigned e; \
24
- if (shift == 0 || shift == ESIZE * 8) { \
25
+ if (shift == ESIZE * 8) { \
26
/* \
27
- * Only VSLI can shift by 0; only VSRI can shift by <dt>. \
28
- * The generic logic would give the right answer for 0 but \
29
- * fails for <dt>. \
30
+ * Only VSRI can shift by <dt>; it should mean "don't \
31
+ * update the destination". The generic logic can't handle \
32
+ * this because it would try to shift by an out-of-range \
33
+ * amount, so special case it here. \
34
*/ \
35
goto done; \
36
} \
37
--
38
2.20.1
39
40
diff view generated by jsdifflib
New patch
1
A cut-and-paste error meant we handled signed VADDV like
2
unsigned VADDV; fix the type used.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
---
7
target/arm/mve_helper.c | 6 +++---
8
1 file changed, 3 insertions(+), 3 deletions(-)
9
10
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/arm/mve_helper.c
13
+++ b/target/arm/mve_helper.c
14
@@ -XXX,XX +XXX,XX @@ DO_LDAVH(vrmlsldavhxsw, int32_t, int64_t, true, true)
15
return ra; \
16
} \
17
18
-DO_VADDV(vaddvsb, 1, uint8_t)
19
-DO_VADDV(vaddvsh, 2, uint16_t)
20
-DO_VADDV(vaddvsw, 4, uint32_t)
21
+DO_VADDV(vaddvsb, 1, int8_t)
22
+DO_VADDV(vaddvsh, 2, int16_t)
23
+DO_VADDV(vaddvsw, 4, int32_t)
24
DO_VADDV(vaddvub, 1, uint8_t)
25
DO_VADDV(vaddvuh, 2, uint16_t)
26
DO_VADDV(vaddvuw, 4, uint32_t)
27
--
28
2.20.1
29
30
diff view generated by jsdifflib
New patch
1
In the MVE helpers for the narrowing operations (DO_VSHRN and
2
DO_VSHRN_SAT) we were using the wrong bits of the predicate mask for
3
the 'top' versions of the insn. This is because the loop works over
4
the double-sized input elements and shifts the predicate mask by that
5
many bits each time, but when we write out the half-sized output we
6
must look at the mask bits for whichever half of the element we are
7
writing to.
1
8
9
Correct this by shifting the whole mask right by ESIZE bits for the
10
'top' insns. This allows us also to simplify the saturation bit
11
checking (where we had noticed that we needed to look at a different
12
mask bit for the 'top' insn.)
13
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
---
17
target/arm/mve_helper.c | 4 +++-
18
1 file changed, 3 insertions(+), 1 deletion(-)
19
20
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
21
index XXXXXXX..XXXXXXX 100644
22
--- a/target/arm/mve_helper.c
23
+++ b/target/arm/mve_helper.c
24
@@ -XXX,XX +XXX,XX @@ DO_VSHLL_ALL(vshllt, true)
25
TYPE *d = vd; \
26
uint16_t mask = mve_element_mask(env); \
27
unsigned le; \
28
+ mask >>= ESIZE * TOP; \
29
for (le = 0; le < 16 / LESIZE; le++, mask >>= LESIZE) { \
30
TYPE r = FN(m[H##LESIZE(le)], shift); \
31
mergemask(&d[H##ESIZE(le * 2 + TOP)], r, mask); \
32
@@ -XXX,XX +XXX,XX @@ static inline int32_t do_sat_bhs(int64_t val, int64_t min, int64_t max,
33
uint16_t mask = mve_element_mask(env); \
34
bool qc = false; \
35
unsigned le; \
36
+ mask >>= ESIZE * TOP; \
37
for (le = 0; le < 16 / LESIZE; le++, mask >>= LESIZE) { \
38
bool sat = false; \
39
TYPE r = FN(m[H##LESIZE(le)], shift, &sat); \
40
mergemask(&d[H##ESIZE(le * 2 + TOP)], r, mask); \
41
- qc |= sat && (mask & 1 << (TOP * ESIZE)); \
42
+ qc |= sat & mask & 1; \
43
} \
44
if (qc) { \
45
env->vfp.qc[0] = qc; \
46
--
47
2.20.1
48
49
diff view generated by jsdifflib
New patch
1
In do_sqrshl48_d() and do_uqrshl48_d() we got some of the edge
2
cases wrong and failed to saturate correctly:
1
3
4
(1) In do_sqrshl48_d() we used the same code that do_shrshl_bhs()
5
does to obtain the saturated most-negative and most-positive 48-bit
6
signed values for the large-shift-left case. This gives (1 << 47)
7
for saturate-to-most-negative, but we weren't sign-extending this
8
value to the 64-bit output as the pseudocode requires.
9
10
(2) For left shifts by less than 48, we copied the "8/16 bit" code
11
from do_sqrshl_bhs() and do_uqrshl_bhs(). This doesn't do the right
12
thing because it assumes the C type we're working with is at least
13
twice the number of bits we're saturating to (so that a shift left by
14
bits-1 can't shift anything off the top of the value). This isn't
15
true for bits == 48, so we would incorrectly return 0 rather than the
16
most-positive value for situations like "shift (1 << 44) right by
17
20". Instead check for saturation by doing the shift and signextend
18
and then testing whether shifting back left again gives the original
19
value.
20
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
---
24
target/arm/mve_helper.c | 12 +++++-------
25
1 file changed, 5 insertions(+), 7 deletions(-)
26
27
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/mve_helper.c
30
+++ b/target/arm/mve_helper.c
31
@@ -XXX,XX +XXX,XX @@ static inline int64_t do_sqrshl48_d(int64_t src, int64_t shift,
32
}
33
return src >> -shift;
34
} else if (shift < 48) {
35
- int64_t val = src << shift;
36
- int64_t extval = sextract64(val, 0, 48);
37
- if (!sat || val == extval) {
38
+ int64_t extval = sextract64(src << shift, 0, 48);
39
+ if (!sat || src == (extval >> shift)) {
40
return extval;
41
}
42
} else if (!sat || src == 0) {
43
@@ -XXX,XX +XXX,XX @@ static inline int64_t do_sqrshl48_d(int64_t src, int64_t shift,
44
}
45
46
*sat = 1;
47
- return (1ULL << 47) - (src >= 0);
48
+ return src >= 0 ? MAKE_64BIT_MASK(0, 47) : MAKE_64BIT_MASK(47, 17);
49
}
50
51
/* Operate on 64-bit values, but saturate at 48 bits */
52
@@ -XXX,XX +XXX,XX @@ static inline uint64_t do_uqrshl48_d(uint64_t src, int64_t shift,
53
return extval;
54
}
55
} else if (shift < 48) {
56
- uint64_t val = src << shift;
57
- uint64_t extval = extract64(val, 0, 48);
58
- if (!sat || val == extval) {
59
+ uint64_t extval = extract64(src << shift, 0, 48);
60
+ if (!sat || src == (extval >> shift)) {
61
return extval;
62
}
63
} else if (!sat || src == 0) {
64
--
65
2.20.1
66
67
diff view generated by jsdifflib
New patch
1
We got an edge case wrong in the 48-bit SQRSHRL implementation: if
2
the shift is to the right, although it always makes the result
3
smaller than the input value it might not be within the 48-bit range
4
the result is supposed to be if the input had some bits in [63..48]
5
set and the shift didn't bring all of those within the [47..0] range.
1
6
7
Handle this similarly to the way we already do for this case in
8
do_uqrshl48_d(): extend the calculated result from 48 bits,
9
and return that if not saturating or if it doesn't change the
10
result; otherwise fall through to return a saturated value.
11
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
---
15
target/arm/mve_helper.c | 11 +++++++++--
16
1 file changed, 9 insertions(+), 2 deletions(-)
17
18
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
19
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/mve_helper.c
21
+++ b/target/arm/mve_helper.c
22
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(mve_uqrshll)(CPUARMState *env, uint64_t n, uint32_t shift)
23
static inline int64_t do_sqrshl48_d(int64_t src, int64_t shift,
24
bool round, uint32_t *sat)
25
{
26
+ int64_t val, extval;
27
+
28
if (shift <= -48) {
29
/* Rounding the sign bit always produces 0. */
30
if (round) {
31
@@ -XXX,XX +XXX,XX @@ static inline int64_t do_sqrshl48_d(int64_t src, int64_t shift,
32
} else if (shift < 0) {
33
if (round) {
34
src >>= -shift - 1;
35
- return (src >> 1) + (src & 1);
36
+ val = (src >> 1) + (src & 1);
37
+ } else {
38
+ val = src >> -shift;
39
+ }
40
+ extval = sextract64(val, 0, 48);
41
+ if (!sat || val == extval) {
42
+ return extval;
43
}
44
- return src >> -shift;
45
} else if (shift < 48) {
46
int64_t extval = sextract64(src << shift, 0, 48);
47
if (!sat || src == (extval >> shift)) {
48
--
49
2.20.1
50
51
diff view generated by jsdifflib
New patch
1
In mve_element_mask(), we calculate a mask for tail predication which
2
should have a number of 1 bits based on the value of LR. However,
3
our MAKE_64BIT_MASK() macro has undefined behaviour when passed a
4
zero length. Special case this to give the all-zeroes mask we
5
require.
1
6
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
---
10
target/arm/mve_helper.c | 3 ++-
11
1 file changed, 2 insertions(+), 1 deletion(-)
12
13
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/mve_helper.c
16
+++ b/target/arm/mve_helper.c
17
@@ -XXX,XX +XXX,XX @@ static uint16_t mve_element_mask(CPUARMState *env)
18
*/
19
int masklen = env->regs[14] << env->v7m.ltpsize;
20
assert(masklen <= 16);
21
- mask &= MAKE_64BIT_MASK(0, masklen);
22
+ uint16_t ltpmask = masklen ? MAKE_64BIT_MASK(0, masklen) : 0;
23
+ mask &= ltpmask;
24
}
25
26
if ((env->condexec_bits & 0xf) == 0) {
27
--
28
2.20.1
29
30
diff view generated by jsdifflib
1
From: Paul Zimmerman <pauldzim@gmail.com>
1
In some situations we need a mask telling us which parts of the
2
vector correspond to beats that are not being executed because of
3
ECI, separately from the combined "which bytes are predicated away"
4
mask. Factor this mask calculation out of mve_element_mask() into
5
its own function.
2
6
3
Add the dwc-hsotg (dwc2) USB host controller emulation code.
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Based on hw/usb/hcd-ehci.c and hw/usb/hcd-ohci.c.
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
---
10
target/arm/mve_helper.c | 58 ++++++++++++++++++++++++-----------------
11
1 file changed, 34 insertions(+), 24 deletions(-)
5
12
6
Note that to use this with the dwc-otg driver in the Raspbian
13
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
7
kernel, you must pass the option "dwc_otg.fiq_fsm_enable=0" on
14
index XXXXXXX..XXXXXXX 100644
8
the kernel command line.
15
--- a/target/arm/mve_helper.c
9
16
+++ b/target/arm/mve_helper.c
10
Emulation of slave mode and of descriptor-DMA mode has not been
11
implemented yet. These modes are seldom used.
12
13
I have used some on-line sources of information while developing
14
this emulation, including:
15
16
http://www.capital-micro.com/PDF/CME-M7_Family_User_Guide_EN.pdf
17
which has a pretty complete description of the controller starting
18
on page 370.
19
20
https://sourceforge.net/p/wive-ng/wive-ng-mt/ci/master/tree/docs/DataSheets/RT3050_5x_V2.0_081408_0902.pdf
21
which has a description of the controller registers starting on
22
page 130.
23
24
Thanks to Felippe Mathieu-Daude for providing a cleaner method
25
of implementing the memory regions for the controller registers.
26
27
Signed-off-by: Paul Zimmerman <pauldzim@gmail.com>
28
Message-id: 20200520235349.21215-5-pauldzim@gmail.com
29
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
30
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
31
---
32
hw/usb/hcd-dwc2.c | 1417 ++++++++++++++++++++++++++++++++++++++++++
33
hw/usb/Kconfig | 5 +
34
hw/usb/Makefile.objs | 1 +
35
hw/usb/trace-events | 50 ++
36
4 files changed, 1473 insertions(+)
37
create mode 100644 hw/usb/hcd-dwc2.c
38
39
diff --git a/hw/usb/hcd-dwc2.c b/hw/usb/hcd-dwc2.c
40
new file mode 100644
41
index XXXXXXX..XXXXXXX
42
--- /dev/null
43
+++ b/hw/usb/hcd-dwc2.c
44
@@ -XXX,XX +XXX,XX @@
17
@@ -XXX,XX +XXX,XX @@
45
+/*
18
#include "exec/exec-all.h"
46
+ * dwc-hsotg (dwc2) USB host controller emulation
19
#include "tcg/tcg.h"
47
+ *
20
48
+ * Based on hw/usb/hcd-ehci.c and hw/usb/hcd-ohci.c
21
+static uint16_t mve_eci_mask(CPUARMState *env)
49
+ *
22
+{
50
+ * Note that to use this emulation with the dwc-otg driver in the
23
+ /*
51
+ * Raspbian kernel, you must pass the option "dwc_otg.fiq_fsm_enable=0"
24
+ * Return the mask of which elements in the MVE vector correspond
52
+ * on the kernel command line.
25
+ * to beats being executed. The mask has 1 bits for executed lanes
53
+ *
26
+ * and 0 bits where ECI says this beat was already executed.
54
+ * Some useful documentation used to develop this emulation can be
27
+ */
55
+ * found online (as of April 2020) at:
28
+ int eci;
56
+ *
57
+ * http://www.capital-micro.com/PDF/CME-M7_Family_User_Guide_EN.pdf
58
+ * which has a pretty complete description of the controller starting
59
+ * on page 370.
60
+ *
61
+ * https://sourceforge.net/p/wive-ng/wive-ng-mt/ci/master/tree/docs/DataSheets/RT3050_5x_V2.0_081408_0902.pdf
62
+ * which has a description of the controller registers starting on
63
+ * page 130.
64
+ *
65
+ * Copyright (c) 2020 Paul Zimmerman <pauldzim@gmail.com>
66
+ *
67
+ * This program is free software; you can redistribute it and/or modify
68
+ * it under the terms of the GNU General Public License as published by
69
+ * the Free Software Foundation; either version 2 of the License, or
70
+ * (at your option) any later version.
71
+ *
72
+ * This program is distributed in the hope that it will be useful,
73
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
74
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
75
+ * GNU General Public License for more details.
76
+ */
77
+
29
+
78
+#include "qemu/osdep.h"
30
+ if ((env->condexec_bits & 0xf) != 0) {
79
+#include "qemu/units.h"
31
+ return 0xffff;
80
+#include "qapi/error.h"
81
+#include "hw/usb/dwc2-regs.h"
82
+#include "hw/usb/hcd-dwc2.h"
83
+#include "migration/vmstate.h"
84
+#include "trace.h"
85
+#include "qemu/log.h"
86
+#include "qemu/error-report.h"
87
+#include "qemu/main-loop.h"
88
+#include "hw/qdev-properties.h"
89
+
90
+#define USB_HZ_FS 12000000
91
+#define USB_HZ_HS 96000000
92
+#define USB_FRMINTVL 12000
93
+
94
+/* nifty macros from Arnon's EHCI version */
95
+#define get_field(data, field) \
96
+ (((data) & field##_MASK) >> field##_SHIFT)
97
+
98
+#define set_field(data, newval, field) do { \
99
+ uint32_t val = *(data); \
100
+ val &= ~field##_MASK; \
101
+ val |= ((newval) << field##_SHIFT) & field##_MASK; \
102
+ *(data) = val; \
103
+} while (0)
104
+
105
+#define get_bit(data, bitmask) \
106
+ (!!((data) & (bitmask)))
107
+
108
+/* update irq line */
109
+static inline void dwc2_update_irq(DWC2State *s)
110
+{
111
+ static int oldlevel;
112
+ int level = 0;
113
+
114
+ if ((s->gintsts & s->gintmsk) && (s->gahbcfg & GAHBCFG_GLBL_INTR_EN)) {
115
+ level = 1;
116
+ }
117
+ if (level != oldlevel) {
118
+ oldlevel = level;
119
+ trace_usb_dwc2_update_irq(level);
120
+ qemu_set_irq(s->irq, level);
121
+ }
122
+}
123
+
124
+/* flag interrupt condition */
125
+static inline void dwc2_raise_global_irq(DWC2State *s, uint32_t intr)
126
+{
127
+ if (!(s->gintsts & intr)) {
128
+ s->gintsts |= intr;
129
+ trace_usb_dwc2_raise_global_irq(intr);
130
+ dwc2_update_irq(s);
131
+ }
132
+}
133
+
134
+static inline void dwc2_lower_global_irq(DWC2State *s, uint32_t intr)
135
+{
136
+ if (s->gintsts & intr) {
137
+ s->gintsts &= ~intr;
138
+ trace_usb_dwc2_lower_global_irq(intr);
139
+ dwc2_update_irq(s);
140
+ }
141
+}
142
+
143
+static inline void dwc2_raise_host_irq(DWC2State *s, uint32_t host_intr)
144
+{
145
+ if (!(s->haint & host_intr)) {
146
+ s->haint |= host_intr;
147
+ s->haint &= 0xffff;
148
+ trace_usb_dwc2_raise_host_irq(host_intr);
149
+ if (s->haint & s->haintmsk) {
150
+ dwc2_raise_global_irq(s, GINTSTS_HCHINT);
151
+ }
152
+ }
153
+}
154
+
155
+static inline void dwc2_lower_host_irq(DWC2State *s, uint32_t host_intr)
156
+{
157
+ if (s->haint & host_intr) {
158
+ s->haint &= ~host_intr;
159
+ trace_usb_dwc2_lower_host_irq(host_intr);
160
+ if (!(s->haint & s->haintmsk)) {
161
+ dwc2_lower_global_irq(s, GINTSTS_HCHINT);
162
+ }
163
+ }
164
+}
165
+
166
+static inline void dwc2_update_hc_irq(DWC2State *s, int index)
167
+{
168
+ uint32_t host_intr = 1 << (index >> 3);
169
+
170
+ if (s->hreg1[index + 2] & s->hreg1[index + 3]) {
171
+ dwc2_raise_host_irq(s, host_intr);
172
+ } else {
173
+ dwc2_lower_host_irq(s, host_intr);
174
+ }
175
+}
176
+
177
+/* set a timer for EOF */
178
+static void dwc2_eof_timer(DWC2State *s)
179
+{
180
+ timer_mod(s->eof_timer, s->sof_time + s->usb_frame_time);
181
+}
182
+
183
+/* Set a timer for EOF and generate SOF event */
184
+static void dwc2_sof(DWC2State *s)
185
+{
186
+ s->sof_time += s->usb_frame_time;
187
+ trace_usb_dwc2_sof(s->sof_time);
188
+ dwc2_eof_timer(s);
189
+ dwc2_raise_global_irq(s, GINTSTS_SOF);
190
+}
191
+
192
+/* Do frame processing on frame boundary */
193
+static void dwc2_frame_boundary(void *opaque)
194
+{
195
+ DWC2State *s = opaque;
196
+ int64_t now;
197
+ uint16_t frcnt;
198
+
199
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
200
+
201
+ /* Frame boundary, so do EOF stuff here */
202
+
203
+ /* Increment frame number */
204
+ frcnt = (uint16_t)((now - s->sof_time) / s->fi);
205
+ s->frame_number = (s->frame_number + frcnt) & 0xffff;
206
+ s->hfnum = s->frame_number & HFNUM_MAX_FRNUM;
207
+
208
+ /* Do SOF stuff here */
209
+ dwc2_sof(s);
210
+}
211
+
212
+/* Start sending SOF tokens on the USB bus */
213
+static void dwc2_bus_start(DWC2State *s)
214
+{
215
+ trace_usb_dwc2_bus_start();
216
+ s->sof_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
217
+ dwc2_eof_timer(s);
218
+}
219
+
220
+/* Stop sending SOF tokens on the USB bus */
221
+static void dwc2_bus_stop(DWC2State *s)
222
+{
223
+ trace_usb_dwc2_bus_stop();
224
+ timer_del(s->eof_timer);
225
+}
226
+
227
+static USBDevice *dwc2_find_device(DWC2State *s, uint8_t addr)
228
+{
229
+ USBDevice *dev;
230
+
231
+ trace_usb_dwc2_find_device(addr);
232
+
233
+ if (!(s->hprt0 & HPRT0_ENA)) {
234
+ trace_usb_dwc2_port_disabled(0);
235
+ } else {
236
+ dev = usb_find_device(&s->uport, addr);
237
+ if (dev != NULL) {
238
+ trace_usb_dwc2_device_found(0);
239
+ return dev;
240
+ }
241
+ }
32
+ }
242
+
33
+
243
+ trace_usb_dwc2_device_not_found();
34
+ eci = env->condexec_bits >> 4;
244
+ return NULL;
35
+ switch (eci) {
245
+}
36
+ case ECI_NONE:
246
+
37
+ return 0xffff;
247
+static const char *pstatus[] = {
38
+ case ECI_A0:
248
+ "USB_RET_SUCCESS", "USB_RET_NODEV", "USB_RET_NAK", "USB_RET_STALL",
39
+ return 0xfff0;
249
+ "USB_RET_BABBLE", "USB_RET_IOERROR", "USB_RET_ASYNC",
40
+ case ECI_A0A1:
250
+ "USB_RET_ADD_TO_QUEUE", "USB_RET_REMOVE_FROM_QUEUE"
41
+ return 0xff00;
251
+};
42
+ case ECI_A0A1A2:
252
+
43
+ case ECI_A0A1A2B0:
253
+static uint32_t pintr[] = {
44
+ return 0xf000;
254
+ HCINTMSK_XFERCOMPL, HCINTMSK_XACTERR, HCINTMSK_NAK, HCINTMSK_STALL,
255
+ HCINTMSK_BBLERR, HCINTMSK_XACTERR, HCINTMSK_XACTERR, HCINTMSK_XACTERR,
256
+ HCINTMSK_XACTERR
257
+};
258
+
259
+static const char *types[] = {
260
+ "Ctrl", "Isoc", "Bulk", "Intr"
261
+};
262
+
263
+static const char *dirs[] = {
264
+ "Out", "In"
265
+};
266
+
267
+static void dwc2_handle_packet(DWC2State *s, uint32_t devadr, USBDevice *dev,
268
+ USBEndpoint *ep, uint32_t index, bool send)
269
+{
270
+ DWC2Packet *p;
271
+ uint32_t hcchar = s->hreg1[index];
272
+ uint32_t hctsiz = s->hreg1[index + 4];
273
+ uint32_t hcdma = s->hreg1[index + 5];
274
+ uint32_t chan, epnum, epdir, eptype, mps, pid, pcnt, len, tlen, intr = 0;
275
+ uint32_t tpcnt, stsidx, actual = 0;
276
+ bool do_intr = false, done = false;
277
+
278
+ epnum = get_field(hcchar, HCCHAR_EPNUM);
279
+ epdir = get_bit(hcchar, HCCHAR_EPDIR);
280
+ eptype = get_field(hcchar, HCCHAR_EPTYPE);
281
+ mps = get_field(hcchar, HCCHAR_MPS);
282
+ pid = get_field(hctsiz, TSIZ_SC_MC_PID);
283
+ pcnt = get_field(hctsiz, TSIZ_PKTCNT);
284
+ len = get_field(hctsiz, TSIZ_XFERSIZE);
285
+ assert(len <= DWC2_MAX_XFER_SIZE);
286
+ chan = index >> 3;
287
+ p = &s->packet[chan];
288
+
289
+ trace_usb_dwc2_handle_packet(chan, dev, &p->packet, epnum, types[eptype],
290
+ dirs[epdir], mps, len, pcnt);
291
+
292
+ if (eptype == USB_ENDPOINT_XFER_CONTROL && pid == TSIZ_SC_MC_PID_SETUP) {
293
+ pid = USB_TOKEN_SETUP;
294
+ } else {
295
+ pid = epdir ? USB_TOKEN_IN : USB_TOKEN_OUT;
296
+ }
297
+
298
+ if (send) {
299
+ tlen = len;
300
+ if (p->small) {
301
+ if (tlen > mps) {
302
+ tlen = mps;
303
+ }
304
+ }
305
+
306
+ if (pid != USB_TOKEN_IN) {
307
+ trace_usb_dwc2_memory_read(hcdma, tlen);
308
+ if (dma_memory_read(&s->dma_as, hcdma,
309
+ s->usb_buf[chan], tlen) != MEMTX_OK) {
310
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: dma_memory_read failed\n",
311
+ __func__);
312
+ }
313
+ }
314
+
315
+ usb_packet_init(&p->packet);
316
+ usb_packet_setup(&p->packet, pid, ep, 0, hcdma,
317
+ pid != USB_TOKEN_IN, true);
318
+ usb_packet_addbuf(&p->packet, s->usb_buf[chan], tlen);
319
+ p->async = DWC2_ASYNC_NONE;
320
+ usb_handle_packet(dev, &p->packet);
321
+ } else {
322
+ tlen = p->len;
323
+ }
324
+
325
+ stsidx = -p->packet.status;
326
+ assert(stsidx < sizeof(pstatus) / sizeof(*pstatus));
327
+ actual = p->packet.actual_length;
328
+ trace_usb_dwc2_packet_status(pstatus[stsidx], actual);
329
+
330
+babble:
331
+ if (p->packet.status != USB_RET_SUCCESS &&
332
+ p->packet.status != USB_RET_NAK &&
333
+ p->packet.status != USB_RET_STALL &&
334
+ p->packet.status != USB_RET_ASYNC) {
335
+ trace_usb_dwc2_packet_error(pstatus[stsidx]);
336
+ }
337
+
338
+ if (p->packet.status == USB_RET_ASYNC) {
339
+ trace_usb_dwc2_async_packet(&p->packet, chan, dev, epnum,
340
+ dirs[epdir], tlen);
341
+ usb_device_flush_ep_queue(dev, ep);
342
+ assert(p->async != DWC2_ASYNC_INFLIGHT);
343
+ p->devadr = devadr;
344
+ p->epnum = epnum;
345
+ p->epdir = epdir;
346
+ p->mps = mps;
347
+ p->pid = pid;
348
+ p->index = index;
349
+ p->pcnt = pcnt;
350
+ p->len = tlen;
351
+ p->async = DWC2_ASYNC_INFLIGHT;
352
+ p->needs_service = false;
353
+ return;
354
+ }
355
+
356
+ if (p->packet.status == USB_RET_SUCCESS) {
357
+ if (actual > tlen) {
358
+ p->packet.status = USB_RET_BABBLE;
359
+ goto babble;
360
+ }
361
+
362
+ if (pid == USB_TOKEN_IN) {
363
+ trace_usb_dwc2_memory_write(hcdma, actual);
364
+ if (dma_memory_write(&s->dma_as, hcdma, s->usb_buf[chan],
365
+ actual) != MEMTX_OK) {
366
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: dma_memory_write failed\n",
367
+ __func__);
368
+ }
369
+ }
370
+
371
+ tpcnt = actual / mps;
372
+ if (actual % mps) {
373
+ tpcnt++;
374
+ if (pid == USB_TOKEN_IN) {
375
+ done = true;
376
+ }
377
+ }
378
+
379
+ pcnt -= tpcnt < pcnt ? tpcnt : pcnt;
380
+ set_field(&hctsiz, pcnt, TSIZ_PKTCNT);
381
+ len -= actual < len ? actual : len;
382
+ set_field(&hctsiz, len, TSIZ_XFERSIZE);
383
+ s->hreg1[index + 4] = hctsiz;
384
+ hcdma += actual;
385
+ s->hreg1[index + 5] = hcdma;
386
+
387
+ if (!pcnt || len == 0 || actual == 0) {
388
+ done = true;
389
+ }
390
+ } else {
391
+ intr |= pintr[stsidx];
392
+ if (p->packet.status == USB_RET_NAK &&
393
+ (eptype == USB_ENDPOINT_XFER_CONTROL ||
394
+ eptype == USB_ENDPOINT_XFER_BULK)) {
395
+ /*
396
+ * for ctrl/bulk, automatically retry on NAK,
397
+ * but send the interrupt anyway
398
+ */
399
+ intr &= ~HCINTMSK_RESERVED14_31;
400
+ s->hreg1[index + 2] |= intr;
401
+ do_intr = true;
402
+ } else {
403
+ intr |= HCINTMSK_CHHLTD;
404
+ done = true;
405
+ }
406
+ }
407
+
408
+ usb_packet_cleanup(&p->packet);
409
+
410
+ if (done) {
411
+ hcchar &= ~HCCHAR_CHENA;
412
+ s->hreg1[index] = hcchar;
413
+ if (!(intr & HCINTMSK_CHHLTD)) {
414
+ intr |= HCINTMSK_CHHLTD | HCINTMSK_XFERCOMPL;
415
+ }
416
+ intr &= ~HCINTMSK_RESERVED14_31;
417
+ s->hreg1[index + 2] |= intr;
418
+ p->needs_service = false;
419
+ trace_usb_dwc2_packet_done(pstatus[stsidx], actual, len, pcnt);
420
+ dwc2_update_hc_irq(s, index);
421
+ return;
422
+ }
423
+
424
+ p->devadr = devadr;
425
+ p->epnum = epnum;
426
+ p->epdir = epdir;
427
+ p->mps = mps;
428
+ p->pid = pid;
429
+ p->index = index;
430
+ p->pcnt = pcnt;
431
+ p->len = len;
432
+ p->needs_service = true;
433
+ trace_usb_dwc2_packet_next(pstatus[stsidx], len, pcnt);
434
+ if (do_intr) {
435
+ dwc2_update_hc_irq(s, index);
436
+ }
437
+}
438
+
439
+/* Attach or detach a device on root hub */
440
+
441
+static const char *speeds[] = {
442
+ "low", "full", "high"
443
+};
444
+
445
+static void dwc2_attach(USBPort *port)
446
+{
447
+ DWC2State *s = port->opaque;
448
+ int hispd = 0;
449
+
450
+ trace_usb_dwc2_attach(port);
451
+ assert(port->index == 0);
452
+
453
+ if (!port->dev || !port->dev->attached) {
454
+ return;
455
+ }
456
+
457
+ assert(port->dev->speed <= USB_SPEED_HIGH);
458
+ trace_usb_dwc2_attach_speed(speeds[port->dev->speed]);
459
+ s->hprt0 &= ~HPRT0_SPD_MASK;
460
+
461
+ switch (port->dev->speed) {
462
+ case USB_SPEED_LOW:
463
+ s->hprt0 |= HPRT0_SPD_LOW_SPEED << HPRT0_SPD_SHIFT;
464
+ break;
465
+ case USB_SPEED_FULL:
466
+ s->hprt0 |= HPRT0_SPD_FULL_SPEED << HPRT0_SPD_SHIFT;
467
+ break;
468
+ case USB_SPEED_HIGH:
469
+ s->hprt0 |= HPRT0_SPD_HIGH_SPEED << HPRT0_SPD_SHIFT;
470
+ hispd = 1;
471
+ break;
472
+ }
473
+
474
+ if (hispd) {
475
+ s->usb_frame_time = NANOSECONDS_PER_SECOND / 8000; /* 125000 */
476
+ if (NANOSECONDS_PER_SECOND >= USB_HZ_HS) {
477
+ s->usb_bit_time = NANOSECONDS_PER_SECOND / USB_HZ_HS; /* 10.4 */
478
+ } else {
479
+ s->usb_bit_time = 1;
480
+ }
481
+ } else {
482
+ s->usb_frame_time = NANOSECONDS_PER_SECOND / 1000; /* 1000000 */
483
+ if (NANOSECONDS_PER_SECOND >= USB_HZ_FS) {
484
+ s->usb_bit_time = NANOSECONDS_PER_SECOND / USB_HZ_FS; /* 83.3 */
485
+ } else {
486
+ s->usb_bit_time = 1;
487
+ }
488
+ }
489
+
490
+ s->fi = USB_FRMINTVL - 1;
491
+ s->hprt0 |= HPRT0_CONNDET | HPRT0_CONNSTS;
492
+
493
+ dwc2_bus_start(s);
494
+ dwc2_raise_global_irq(s, GINTSTS_PRTINT);
495
+}
496
+
497
+static void dwc2_detach(USBPort *port)
498
+{
499
+ DWC2State *s = port->opaque;
500
+
501
+ trace_usb_dwc2_detach(port);
502
+ assert(port->index == 0);
503
+
504
+ dwc2_bus_stop(s);
505
+
506
+ s->hprt0 &= ~(HPRT0_SPD_MASK | HPRT0_SUSP | HPRT0_ENA | HPRT0_CONNSTS);
507
+ s->hprt0 |= HPRT0_CONNDET | HPRT0_ENACHG;
508
+
509
+ dwc2_raise_global_irq(s, GINTSTS_PRTINT);
510
+}
511
+
512
+static void dwc2_child_detach(USBPort *port, USBDevice *child)
513
+{
514
+ trace_usb_dwc2_child_detach(port, child);
515
+ assert(port->index == 0);
516
+}
517
+
518
+static void dwc2_wakeup(USBPort *port)
519
+{
520
+ DWC2State *s = port->opaque;
521
+
522
+ trace_usb_dwc2_wakeup(port);
523
+ assert(port->index == 0);
524
+
525
+ if (s->hprt0 & HPRT0_SUSP) {
526
+ s->hprt0 |= HPRT0_RES;
527
+ dwc2_raise_global_irq(s, GINTSTS_PRTINT);
528
+ }
529
+
530
+ qemu_bh_schedule(s->async_bh);
531
+}
532
+
533
+static void dwc2_async_packet_complete(USBPort *port, USBPacket *packet)
534
+{
535
+ DWC2State *s = port->opaque;
536
+ DWC2Packet *p;
537
+ USBDevice *dev;
538
+ USBEndpoint *ep;
539
+
540
+ assert(port->index == 0);
541
+ p = container_of(packet, DWC2Packet, packet);
542
+ dev = dwc2_find_device(s, p->devadr);
543
+ ep = usb_ep_get(dev, p->pid, p->epnum);
544
+ trace_usb_dwc2_async_packet_complete(port, packet, p->index >> 3, dev,
545
+ p->epnum, dirs[p->epdir], p->len);
546
+ assert(p->async == DWC2_ASYNC_INFLIGHT);
547
+
548
+ if (packet->status == USB_RET_REMOVE_FROM_QUEUE) {
549
+ usb_cancel_packet(packet);
550
+ usb_packet_cleanup(packet);
551
+ return;
552
+ }
553
+
554
+ dwc2_handle_packet(s, p->devadr, dev, ep, p->index, false);
555
+
556
+ p->async = DWC2_ASYNC_FINISHED;
557
+ qemu_bh_schedule(s->async_bh);
558
+}
559
+
560
+static USBPortOps dwc2_port_ops = {
561
+ .attach = dwc2_attach,
562
+ .detach = dwc2_detach,
563
+ .child_detach = dwc2_child_detach,
564
+ .wakeup = dwc2_wakeup,
565
+ .complete = dwc2_async_packet_complete,
566
+};
567
+
568
+static uint32_t dwc2_get_frame_remaining(DWC2State *s)
569
+{
570
+ uint32_t fr = 0;
571
+ int64_t tks;
572
+
573
+ tks = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - s->sof_time;
574
+ if (tks < 0) {
575
+ tks = 0;
576
+ }
577
+
578
+ /* avoid muldiv if possible */
579
+ if (tks >= s->usb_frame_time) {
580
+ goto out;
581
+ }
582
+ if (tks < s->usb_bit_time) {
583
+ fr = s->fi;
584
+ goto out;
585
+ }
586
+
587
+ /* tks = number of ns since SOF, divided by 83 (fs) or 10 (hs) */
588
+ tks = tks / s->usb_bit_time;
589
+ if (tks >= (int64_t)s->fi) {
590
+ goto out;
591
+ }
592
+
593
+ /* remaining = frame interval minus tks */
594
+ fr = (uint32_t)((int64_t)s->fi - tks);
595
+
596
+out:
597
+ return fr;
598
+}
599
+
600
+static void dwc2_work_bh(void *opaque)
601
+{
602
+ DWC2State *s = opaque;
603
+ DWC2Packet *p;
604
+ USBDevice *dev;
605
+ USBEndpoint *ep;
606
+ int64_t t_now, expire_time;
607
+ int chan;
608
+ bool found = false;
609
+
610
+ trace_usb_dwc2_work_bh();
611
+ if (s->working) {
612
+ return;
613
+ }
614
+ s->working = true;
615
+
616
+ t_now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
617
+ chan = s->next_chan;
618
+
619
+ do {
620
+ p = &s->packet[chan];
621
+ if (p->needs_service) {
622
+ dev = dwc2_find_device(s, p->devadr);
623
+ ep = usb_ep_get(dev, p->pid, p->epnum);
624
+ trace_usb_dwc2_work_bh_service(s->next_chan, chan, dev, p->epnum);
625
+ dwc2_handle_packet(s, p->devadr, dev, ep, p->index, true);
626
+ found = true;
627
+ }
628
+ if (++chan == DWC2_NB_CHAN) {
629
+ chan = 0;
630
+ }
631
+ if (found) {
632
+ s->next_chan = chan;
633
+ trace_usb_dwc2_work_bh_next(chan);
634
+ }
635
+ } while (chan != s->next_chan);
636
+
637
+ if (found) {
638
+ expire_time = t_now + NANOSECONDS_PER_SECOND / 4000;
639
+ timer_mod(s->frame_timer, expire_time);
640
+ }
641
+ s->working = false;
642
+}
643
+
644
+static void dwc2_enable_chan(DWC2State *s, uint32_t index)
645
+{
646
+ USBDevice *dev;
647
+ USBEndpoint *ep;
648
+ uint32_t hcchar;
649
+ uint32_t hctsiz;
650
+ uint32_t devadr, epnum, epdir, eptype, pid, len;
651
+ DWC2Packet *p;
652
+
653
+ assert((index >> 3) < DWC2_NB_CHAN);
654
+ p = &s->packet[index >> 3];
655
+ hcchar = s->hreg1[index];
656
+ hctsiz = s->hreg1[index + 4];
657
+ devadr = get_field(hcchar, HCCHAR_DEVADDR);
658
+ epnum = get_field(hcchar, HCCHAR_EPNUM);
659
+ epdir = get_bit(hcchar, HCCHAR_EPDIR);
660
+ eptype = get_field(hcchar, HCCHAR_EPTYPE);
661
+ pid = get_field(hctsiz, TSIZ_SC_MC_PID);
662
+ len = get_field(hctsiz, TSIZ_XFERSIZE);
663
+
664
+ dev = dwc2_find_device(s, devadr);
665
+
666
+ trace_usb_dwc2_enable_chan(index >> 3, dev, &p->packet, epnum);
667
+ if (dev == NULL) {
668
+ return;
669
+ }
670
+
671
+ if (eptype == USB_ENDPOINT_XFER_CONTROL && pid == TSIZ_SC_MC_PID_SETUP) {
672
+ pid = USB_TOKEN_SETUP;
673
+ } else {
674
+ pid = epdir ? USB_TOKEN_IN : USB_TOKEN_OUT;
675
+ }
676
+
677
+ ep = usb_ep_get(dev, pid, epnum);
678
+
679
+ /*
680
+ * Hack: Networking doesn't like us delivering large transfers, it kind
681
+ * of works but the latency is horrible. So if the transfer is <= the mtu
682
+ * size, we take that as a hint that this might be a network transfer,
683
+ * and do the transfer packet-by-packet.
684
+ */
685
+ if (len > 1536) {
686
+ p->small = false;
687
+ } else {
688
+ p->small = true;
689
+ }
690
+
691
+ dwc2_handle_packet(s, devadr, dev, ep, index, true);
692
+ qemu_bh_schedule(s->async_bh);
693
+}
694
+
695
+static const char *glbregnm[] = {
696
+ "GOTGCTL ", "GOTGINT ", "GAHBCFG ", "GUSBCFG ", "GRSTCTL ",
697
+ "GINTSTS ", "GINTMSK ", "GRXSTSR ", "GRXSTSP ", "GRXFSIZ ",
698
+ "GNPTXFSIZ", "GNPTXSTS ", "GI2CCTL ", "GPVNDCTL ", "GGPIO ",
699
+ "GUID ", "GSNPSID ", "GHWCFG1 ", "GHWCFG2 ", "GHWCFG3 ",
700
+ "GHWCFG4 ", "GLPMCFG ", "GPWRDN ", "GDFIFOCFG", "GADPCTL ",
701
+ "GREFCLK ", "GINTMSK2 ", "GINTSTS2 "
702
+};
703
+
704
+static uint64_t dwc2_glbreg_read(void *ptr, hwaddr addr, int index,
705
+ unsigned size)
706
+{
707
+ DWC2State *s = ptr;
708
+ uint32_t val;
709
+
710
+ assert(addr <= GINTSTS2);
711
+ val = s->glbreg[index];
712
+
713
+ switch (addr) {
714
+ case GRSTCTL:
715
+ /* clear any self-clearing bits that were set */
716
+ val &= ~(GRSTCTL_TXFFLSH | GRSTCTL_RXFFLSH | GRSTCTL_IN_TKNQ_FLSH |
717
+ GRSTCTL_FRMCNTRRST | GRSTCTL_HSFTRST | GRSTCTL_CSFTRST);
718
+ s->glbreg[index] = val;
719
+ break;
720
+ default:
721
+ break;
722
+ }
723
+
724
+ trace_usb_dwc2_glbreg_read(addr, glbregnm[index], val);
725
+ return val;
726
+}
727
+
728
+static void dwc2_glbreg_write(void *ptr, hwaddr addr, int index, uint64_t val,
729
+ unsigned size)
730
+{
731
+ DWC2State *s = ptr;
732
+ uint64_t orig = val;
733
+ uint32_t *mmio;
734
+ uint32_t old;
735
+ int iflg = 0;
736
+
737
+ assert(addr <= GINTSTS2);
738
+ mmio = &s->glbreg[index];
739
+ old = *mmio;
740
+
741
+ switch (addr) {
742
+ case GOTGCTL:
743
+ /* don't allow setting of read-only bits */
744
+ val &= ~(GOTGCTL_MULT_VALID_BC_MASK | GOTGCTL_BSESVLD |
745
+ GOTGCTL_ASESVLD | GOTGCTL_DBNC_SHORT | GOTGCTL_CONID_B |
746
+ GOTGCTL_HSTNEGSCS | GOTGCTL_SESREQSCS);
747
+ /* don't allow clearing of read-only bits */
748
+ val |= old & (GOTGCTL_MULT_VALID_BC_MASK | GOTGCTL_BSESVLD |
749
+ GOTGCTL_ASESVLD | GOTGCTL_DBNC_SHORT | GOTGCTL_CONID_B |
750
+ GOTGCTL_HSTNEGSCS | GOTGCTL_SESREQSCS);
751
+ break;
752
+ case GAHBCFG:
753
+ if ((val & GAHBCFG_GLBL_INTR_EN) && !(old & GAHBCFG_GLBL_INTR_EN)) {
754
+ iflg = 1;
755
+ }
756
+ break;
757
+ case GRSTCTL:
758
+ val |= GRSTCTL_AHBIDLE;
759
+ val &= ~GRSTCTL_DMAREQ;
760
+ if (!(old & GRSTCTL_TXFFLSH) && (val & GRSTCTL_TXFFLSH)) {
761
+ /* TODO - TX fifo flush */
762
+ qemu_log_mask(LOG_UNIMP, "Tx FIFO flush not implemented\n");
763
+ }
764
+ if (!(old & GRSTCTL_RXFFLSH) && (val & GRSTCTL_RXFFLSH)) {
765
+ /* TODO - RX fifo flush */
766
+ qemu_log_mask(LOG_UNIMP, "Rx FIFO flush not implemented\n");
767
+ }
768
+ if (!(old & GRSTCTL_IN_TKNQ_FLSH) && (val & GRSTCTL_IN_TKNQ_FLSH)) {
769
+ /* TODO - device IN token queue flush */
770
+ qemu_log_mask(LOG_UNIMP, "Token queue flush not implemented\n");
771
+ }
772
+ if (!(old & GRSTCTL_FRMCNTRRST) && (val & GRSTCTL_FRMCNTRRST)) {
773
+ /* TODO - host frame counter reset */
774
+ qemu_log_mask(LOG_UNIMP, "Frame counter reset not implemented\n");
775
+ }
776
+ if (!(old & GRSTCTL_HSFTRST) && (val & GRSTCTL_HSFTRST)) {
777
+ /* TODO - host soft reset */
778
+ qemu_log_mask(LOG_UNIMP, "Host soft reset not implemented\n");
779
+ }
780
+ if (!(old & GRSTCTL_CSFTRST) && (val & GRSTCTL_CSFTRST)) {
781
+ /* TODO - core soft reset */
782
+ qemu_log_mask(LOG_UNIMP, "Core soft reset not implemented\n");
783
+ }
784
+ /* don't allow clearing of self-clearing bits */
785
+ val |= old & (GRSTCTL_TXFFLSH | GRSTCTL_RXFFLSH |
786
+ GRSTCTL_IN_TKNQ_FLSH | GRSTCTL_FRMCNTRRST |
787
+ GRSTCTL_HSFTRST | GRSTCTL_CSFTRST);
788
+ break;
789
+ case GINTSTS:
790
+ /* clear the write-1-to-clear bits */
791
+ val |= ~old;
792
+ val = ~val;
793
+ /* don't allow clearing of read-only bits */
794
+ val |= old & (GINTSTS_PTXFEMP | GINTSTS_HCHINT | GINTSTS_PRTINT |
795
+ GINTSTS_OEPINT | GINTSTS_IEPINT | GINTSTS_GOUTNAKEFF |
796
+ GINTSTS_GINNAKEFF | GINTSTS_NPTXFEMP | GINTSTS_RXFLVL |
797
+ GINTSTS_OTGINT | GINTSTS_CURMODE_HOST);
798
+ iflg = 1;
799
+ break;
800
+ case GINTMSK:
801
+ iflg = 1;
802
+ break;
803
+ default:
804
+ break;
805
+ }
806
+
807
+ trace_usb_dwc2_glbreg_write(addr, glbregnm[index], orig, old, val);
808
+ *mmio = val;
809
+
810
+ if (iflg) {
811
+ dwc2_update_irq(s);
812
+ }
813
+}
814
+
815
+static uint64_t dwc2_fszreg_read(void *ptr, hwaddr addr, int index,
816
+ unsigned size)
817
+{
818
+ DWC2State *s = ptr;
819
+ uint32_t val;
820
+
821
+ assert(addr == HPTXFSIZ);
822
+ val = s->fszreg[index];
823
+
824
+ trace_usb_dwc2_fszreg_read(addr, val);
825
+ return val;
826
+}
827
+
828
+static void dwc2_fszreg_write(void *ptr, hwaddr addr, int index, uint64_t val,
829
+ unsigned size)
830
+{
831
+ DWC2State *s = ptr;
832
+ uint64_t orig = val;
833
+ uint32_t *mmio;
834
+ uint32_t old;
835
+
836
+ assert(addr == HPTXFSIZ);
837
+ mmio = &s->fszreg[index];
838
+ old = *mmio;
839
+
840
+ trace_usb_dwc2_fszreg_write(addr, orig, old, val);
841
+ *mmio = val;
842
+}
843
+
844
+static const char *hreg0nm[] = {
845
+ "HCFG ", "HFIR ", "HFNUM ", "<rsvd> ", "HPTXSTS ",
846
+ "HAINT ", "HAINTMSK ", "HFLBADDR ", "<rsvd> ", "<rsvd> ",
847
+ "<rsvd> ", "<rsvd> ", "<rsvd> ", "<rsvd> ", "<rsvd> ",
848
+ "<rsvd> ", "HPRT0 "
849
+};
850
+
851
+static uint64_t dwc2_hreg0_read(void *ptr, hwaddr addr, int index,
852
+ unsigned size)
853
+{
854
+ DWC2State *s = ptr;
855
+ uint32_t val;
856
+
857
+ assert(addr >= HCFG && addr <= HPRT0);
858
+ val = s->hreg0[index];
859
+
860
+ switch (addr) {
861
+ case HFNUM:
862
+ val = (dwc2_get_frame_remaining(s) << HFNUM_FRREM_SHIFT) |
863
+ (s->hfnum << HFNUM_FRNUM_SHIFT);
864
+ break;
865
+ default:
866
+ break;
867
+ }
868
+
869
+ trace_usb_dwc2_hreg0_read(addr, hreg0nm[index], val);
870
+ return val;
871
+}
872
+
873
+static void dwc2_hreg0_write(void *ptr, hwaddr addr, int index, uint64_t val,
874
+ unsigned size)
875
+{
876
+ DWC2State *s = ptr;
877
+ USBDevice *dev = s->uport.dev;
878
+ uint64_t orig = val;
879
+ uint32_t *mmio;
880
+ uint32_t tval, told, old;
881
+ int prst = 0;
882
+ int iflg = 0;
883
+
884
+ assert(addr >= HCFG && addr <= HPRT0);
885
+ mmio = &s->hreg0[index];
886
+ old = *mmio;
887
+
888
+ switch (addr) {
889
+ case HFIR:
890
+ break;
891
+ case HFNUM:
892
+ case HPTXSTS:
893
+ case HAINT:
894
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: write to read-only register\n",
895
+ __func__);
896
+ return;
897
+ case HAINTMSK:
898
+ val &= 0xffff;
899
+ break;
900
+ case HPRT0:
901
+ /* don't allow clearing of read-only bits */
902
+ val |= old & (HPRT0_SPD_MASK | HPRT0_LNSTS_MASK | HPRT0_OVRCURRACT |
903
+ HPRT0_CONNSTS);
904
+ /* don't allow clearing of self-clearing bits */
905
+ val |= old & (HPRT0_SUSP | HPRT0_RES);
906
+ /* don't allow setting of self-setting bits */
907
+ if (!(old & HPRT0_ENA) && (val & HPRT0_ENA)) {
908
+ val &= ~HPRT0_ENA;
909
+ }
910
+ /* clear the write-1-to-clear bits */
911
+ tval = val & (HPRT0_OVRCURRCHG | HPRT0_ENACHG | HPRT0_ENA |
912
+ HPRT0_CONNDET);
913
+ told = old & (HPRT0_OVRCURRCHG | HPRT0_ENACHG | HPRT0_ENA |
914
+ HPRT0_CONNDET);
915
+ tval |= ~told;
916
+ tval = ~tval;
917
+ tval &= (HPRT0_OVRCURRCHG | HPRT0_ENACHG | HPRT0_ENA |
918
+ HPRT0_CONNDET);
919
+ val &= ~(HPRT0_OVRCURRCHG | HPRT0_ENACHG | HPRT0_ENA |
920
+ HPRT0_CONNDET);
921
+ val |= tval;
922
+ if (!(val & HPRT0_RST) && (old & HPRT0_RST)) {
923
+ if (dev && dev->attached) {
924
+ val |= HPRT0_ENA | HPRT0_ENACHG;
925
+ prst = 1;
926
+ }
927
+ }
928
+ if (val & (HPRT0_OVRCURRCHG | HPRT0_ENACHG | HPRT0_CONNDET)) {
929
+ iflg = 1;
930
+ } else {
931
+ iflg = -1;
932
+ }
933
+ break;
934
+ default:
935
+ break;
936
+ }
937
+
938
+ if (prst) {
939
+ trace_usb_dwc2_hreg0_write(addr, hreg0nm[index], orig, old,
940
+ val & ~HPRT0_CONNDET);
941
+ trace_usb_dwc2_hreg0_action("call usb_port_reset");
942
+ usb_port_reset(&s->uport);
943
+ val &= ~HPRT0_CONNDET;
944
+ } else {
945
+ trace_usb_dwc2_hreg0_write(addr, hreg0nm[index], orig, old, val);
946
+ }
947
+
948
+ *mmio = val;
949
+
950
+ if (iflg > 0) {
951
+ trace_usb_dwc2_hreg0_action("enable PRTINT");
952
+ dwc2_raise_global_irq(s, GINTSTS_PRTINT);
953
+ } else if (iflg < 0) {
954
+ trace_usb_dwc2_hreg0_action("disable PRTINT");
955
+ dwc2_lower_global_irq(s, GINTSTS_PRTINT);
956
+ }
957
+}
958
+
959
+static const char *hreg1nm[] = {
960
+ "HCCHAR ", "HCSPLT ", "HCINT ", "HCINTMSK", "HCTSIZ ", "HCDMA ",
961
+ "<rsvd> ", "HCDMAB "
962
+};
963
+
964
+static uint64_t dwc2_hreg1_read(void *ptr, hwaddr addr, int index,
965
+ unsigned size)
966
+{
967
+ DWC2State *s = ptr;
968
+ uint32_t val;
969
+
970
+ assert(addr >= HCCHAR(0) && addr <= HCDMAB(DWC2_NB_CHAN - 1));
971
+ val = s->hreg1[index];
972
+
973
+ trace_usb_dwc2_hreg1_read(addr, hreg1nm[index & 7], addr >> 5, val);
974
+ return val;
975
+}
976
+
977
+static void dwc2_hreg1_write(void *ptr, hwaddr addr, int index, uint64_t val,
978
+ unsigned size)
979
+{
980
+ DWC2State *s = ptr;
981
+ uint64_t orig = val;
982
+ uint32_t *mmio;
983
+ uint32_t old;
984
+ int iflg = 0;
985
+ int enflg = 0;
986
+ int disflg = 0;
987
+
988
+ assert(addr >= HCCHAR(0) && addr <= HCDMAB(DWC2_NB_CHAN - 1));
989
+ mmio = &s->hreg1[index];
990
+ old = *mmio;
991
+
992
+ switch (HSOTG_REG(0x500) + (addr & 0x1c)) {
993
+ case HCCHAR(0):
994
+ if ((val & HCCHAR_CHDIS) && !(old & HCCHAR_CHDIS)) {
995
+ val &= ~(HCCHAR_CHENA | HCCHAR_CHDIS);
996
+ disflg = 1;
997
+ } else {
998
+ val |= old & HCCHAR_CHDIS;
999
+ if ((val & HCCHAR_CHENA) && !(old & HCCHAR_CHENA)) {
1000
+ val &= ~HCCHAR_CHDIS;
1001
+ enflg = 1;
1002
+ } else {
1003
+ val |= old & HCCHAR_CHENA;
1004
+ }
1005
+ }
1006
+ break;
1007
+ case HCINT(0):
1008
+ /* clear the write-1-to-clear bits */
1009
+ val |= ~old;
1010
+ val = ~val;
1011
+ val &= ~HCINTMSK_RESERVED14_31;
1012
+ iflg = 1;
1013
+ break;
1014
+ case HCINTMSK(0):
1015
+ val &= ~HCINTMSK_RESERVED14_31;
1016
+ iflg = 1;
1017
+ break;
1018
+ case HCDMAB(0):
1019
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: write to read-only register\n",
1020
+ __func__);
1021
+ return;
1022
+ default:
1023
+ break;
1024
+ }
1025
+
1026
+ trace_usb_dwc2_hreg1_write(addr, hreg1nm[index & 7], index >> 3, orig,
1027
+ old, val);
1028
+ *mmio = val;
1029
+
1030
+ if (disflg) {
1031
+ /* set ChHltd in HCINT */
1032
+ s->hreg1[(index & ~7) + 2] |= HCINTMSK_CHHLTD;
1033
+ iflg = 1;
1034
+ }
1035
+
1036
+ if (enflg) {
1037
+ dwc2_enable_chan(s, index & ~7);
1038
+ }
1039
+
1040
+ if (iflg) {
1041
+ dwc2_update_hc_irq(s, index & ~7);
1042
+ }
1043
+}
1044
+
1045
+static const char *pcgregnm[] = {
1046
+ "PCGCTL ", "PCGCCTL1 "
1047
+};
1048
+
1049
+static uint64_t dwc2_pcgreg_read(void *ptr, hwaddr addr, int index,
1050
+ unsigned size)
1051
+{
1052
+ DWC2State *s = ptr;
1053
+ uint32_t val;
1054
+
1055
+ assert(addr >= PCGCTL && addr <= PCGCCTL1);
1056
+ val = s->pcgreg[index];
1057
+
1058
+ trace_usb_dwc2_pcgreg_read(addr, pcgregnm[index], val);
1059
+ return val;
1060
+}
1061
+
1062
+static void dwc2_pcgreg_write(void *ptr, hwaddr addr, int index,
1063
+ uint64_t val, unsigned size)
1064
+{
1065
+ DWC2State *s = ptr;
1066
+ uint64_t orig = val;
1067
+ uint32_t *mmio;
1068
+ uint32_t old;
1069
+
1070
+ assert(addr >= PCGCTL && addr <= PCGCCTL1);
1071
+ mmio = &s->pcgreg[index];
1072
+ old = *mmio;
1073
+
1074
+ trace_usb_dwc2_pcgreg_write(addr, pcgregnm[index], orig, old, val);
1075
+ *mmio = val;
1076
+}
1077
+
1078
+static uint64_t dwc2_hsotg_read(void *ptr, hwaddr addr, unsigned size)
1079
+{
1080
+ uint64_t val;
1081
+
1082
+ switch (addr) {
1083
+ case HSOTG_REG(0x000) ... HSOTG_REG(0x0fc):
1084
+ val = dwc2_glbreg_read(ptr, addr, (addr - HSOTG_REG(0x000)) >> 2, size);
1085
+ break;
1086
+ case HSOTG_REG(0x100):
1087
+ val = dwc2_fszreg_read(ptr, addr, (addr - HSOTG_REG(0x100)) >> 2, size);
1088
+ break;
1089
+ case HSOTG_REG(0x104) ... HSOTG_REG(0x3fc):
1090
+ /* Gadget-mode registers, just return 0 for now */
1091
+ val = 0;
1092
+ break;
1093
+ case HSOTG_REG(0x400) ... HSOTG_REG(0x4fc):
1094
+ val = dwc2_hreg0_read(ptr, addr, (addr - HSOTG_REG(0x400)) >> 2, size);
1095
+ break;
1096
+ case HSOTG_REG(0x500) ... HSOTG_REG(0x7fc):
1097
+ val = dwc2_hreg1_read(ptr, addr, (addr - HSOTG_REG(0x500)) >> 2, size);
1098
+ break;
1099
+ case HSOTG_REG(0x800) ... HSOTG_REG(0xdfc):
1100
+ /* Gadget-mode registers, just return 0 for now */
1101
+ val = 0;
1102
+ break;
1103
+ case HSOTG_REG(0xe00) ... HSOTG_REG(0xffc):
1104
+ val = dwc2_pcgreg_read(ptr, addr, (addr - HSOTG_REG(0xe00)) >> 2, size);
1105
+ break;
1106
+ default:
1107
+ g_assert_not_reached();
1108
+ }
1109
+
1110
+ return val;
1111
+}
1112
+
1113
+static void dwc2_hsotg_write(void *ptr, hwaddr addr, uint64_t val,
1114
+ unsigned size)
1115
+{
1116
+ switch (addr) {
1117
+ case HSOTG_REG(0x000) ... HSOTG_REG(0x0fc):
1118
+ dwc2_glbreg_write(ptr, addr, (addr - HSOTG_REG(0x000)) >> 2, val, size);
1119
+ break;
1120
+ case HSOTG_REG(0x100):
1121
+ dwc2_fszreg_write(ptr, addr, (addr - HSOTG_REG(0x100)) >> 2, val, size);
1122
+ break;
1123
+ case HSOTG_REG(0x104) ... HSOTG_REG(0x3fc):
1124
+ /* Gadget-mode registers, do nothing for now */
1125
+ break;
1126
+ case HSOTG_REG(0x400) ... HSOTG_REG(0x4fc):
1127
+ dwc2_hreg0_write(ptr, addr, (addr - HSOTG_REG(0x400)) >> 2, val, size);
1128
+ break;
1129
+ case HSOTG_REG(0x500) ... HSOTG_REG(0x7fc):
1130
+ dwc2_hreg1_write(ptr, addr, (addr - HSOTG_REG(0x500)) >> 2, val, size);
1131
+ break;
1132
+ case HSOTG_REG(0x800) ... HSOTG_REG(0xdfc):
1133
+ /* Gadget-mode registers, do nothing for now */
1134
+ break;
1135
+ case HSOTG_REG(0xe00) ... HSOTG_REG(0xffc):
1136
+ dwc2_pcgreg_write(ptr, addr, (addr - HSOTG_REG(0xe00)) >> 2, val, size);
1137
+ break;
1138
+ default:
45
+ default:
1139
+ g_assert_not_reached();
46
+ g_assert_not_reached();
1140
+ }
47
+ }
1141
+}
48
+}
1142
+
49
+
1143
+static const MemoryRegionOps dwc2_mmio_hsotg_ops = {
50
static uint16_t mve_element_mask(CPUARMState *env)
1144
+ .read = dwc2_hsotg_read,
51
{
1145
+ .write = dwc2_hsotg_write,
52
/*
1146
+ .impl.min_access_size = 4,
53
@@ -XXX,XX +XXX,XX @@ static uint16_t mve_element_mask(CPUARMState *env)
1147
+ .impl.max_access_size = 4,
54
mask &= ltpmask;
1148
+ .endianness = DEVICE_LITTLE_ENDIAN,
55
}
1149
+};
56
1150
+
57
- if ((env->condexec_bits & 0xf) == 0) {
1151
+static uint64_t dwc2_hreg2_read(void *ptr, hwaddr addr, unsigned size)
58
- /*
1152
+{
59
- * ECI bits indicate which beats are already executed;
1153
+ /* TODO - implement FIFOs to support slave mode */
60
- * we handle this by effectively predicating them out.
1154
+ trace_usb_dwc2_hreg2_read(addr, addr >> 12, 0);
61
- */
1155
+ qemu_log_mask(LOG_UNIMP, "FIFO read not implemented\n");
62
- int eci = env->condexec_bits >> 4;
1156
+ return 0;
63
- switch (eci) {
1157
+}
64
- case ECI_NONE:
1158
+
65
- break;
1159
+static void dwc2_hreg2_write(void *ptr, hwaddr addr, uint64_t val,
66
- case ECI_A0:
1160
+ unsigned size)
67
- mask &= 0xfff0;
1161
+{
68
- break;
1162
+ uint64_t orig = val;
69
- case ECI_A0A1:
1163
+
70
- mask &= 0xff00;
1164
+ /* TODO - implement FIFOs to support slave mode */
71
- break;
1165
+ trace_usb_dwc2_hreg2_write(addr, addr >> 12, orig, 0, val);
72
- case ECI_A0A1A2:
1166
+ qemu_log_mask(LOG_UNIMP, "FIFO write not implemented\n");
73
- case ECI_A0A1A2B0:
1167
+}
74
- mask &= 0xf000;
1168
+
75
- break;
1169
+static const MemoryRegionOps dwc2_mmio_hreg2_ops = {
76
- default:
1170
+ .read = dwc2_hreg2_read,
77
- g_assert_not_reached();
1171
+ .write = dwc2_hreg2_write,
78
- }
1172
+ .impl.min_access_size = 4,
79
- }
1173
+ .impl.max_access_size = 4,
80
-
1174
+ .endianness = DEVICE_LITTLE_ENDIAN,
81
+ /*
1175
+};
82
+ * ECI bits indicate which beats are already executed;
1176
+
83
+ * we handle this by effectively predicating them out.
1177
+static void dwc2_wakeup_endpoint(USBBus *bus, USBEndpoint *ep,
84
+ */
1178
+ unsigned int stream)
85
+ mask &= mve_eci_mask(env);
1179
+{
86
return mask;
1180
+ DWC2State *s = container_of(bus, DWC2State, bus);
87
}
1181
+
88
1182
+ trace_usb_dwc2_wakeup_endpoint(ep, stream);
1183
+
1184
+ /* TODO - do something here? */
1185
+ qemu_bh_schedule(s->async_bh);
1186
+}
1187
+
1188
+static USBBusOps dwc2_bus_ops = {
1189
+ .wakeup_endpoint = dwc2_wakeup_endpoint,
1190
+};
1191
+
1192
+static void dwc2_work_timer(void *opaque)
1193
+{
1194
+ DWC2State *s = opaque;
1195
+
1196
+ trace_usb_dwc2_work_timer();
1197
+ qemu_bh_schedule(s->async_bh);
1198
+}
1199
+
1200
+static void dwc2_reset_enter(Object *obj, ResetType type)
1201
+{
1202
+ DWC2Class *c = DWC2_GET_CLASS(obj);
1203
+ DWC2State *s = DWC2_USB(obj);
1204
+ int i;
1205
+
1206
+ trace_usb_dwc2_reset_enter();
1207
+
1208
+ if (c->parent_phases.enter) {
1209
+ c->parent_phases.enter(obj, type);
1210
+ }
1211
+
1212
+ timer_del(s->frame_timer);
1213
+ qemu_bh_cancel(s->async_bh);
1214
+
1215
+ if (s->uport.dev && s->uport.dev->attached) {
1216
+ usb_detach(&s->uport);
1217
+ }
1218
+
1219
+ dwc2_bus_stop(s);
1220
+
1221
+ s->gotgctl = GOTGCTL_BSESVLD | GOTGCTL_ASESVLD | GOTGCTL_CONID_B;
1222
+ s->gotgint = 0;
1223
+ s->gahbcfg = 0;
1224
+ s->gusbcfg = 5 << GUSBCFG_USBTRDTIM_SHIFT;
1225
+ s->grstctl = GRSTCTL_AHBIDLE;
1226
+ s->gintsts = GINTSTS_CONIDSTSCHNG | GINTSTS_PTXFEMP | GINTSTS_NPTXFEMP |
1227
+ GINTSTS_CURMODE_HOST;
1228
+ s->gintmsk = 0;
1229
+ s->grxstsr = 0;
1230
+ s->grxstsp = 0;
1231
+ s->grxfsiz = 1024;
1232
+ s->gnptxfsiz = 1024 << FIFOSIZE_DEPTH_SHIFT;
1233
+ s->gnptxsts = (4 << FIFOSIZE_DEPTH_SHIFT) | 1024;
1234
+ s->gi2cctl = GI2CCTL_I2CDATSE0 | GI2CCTL_ACK;
1235
+ s->gpvndctl = 0;
1236
+ s->ggpio = 0;
1237
+ s->guid = 0;
1238
+ s->gsnpsid = 0x4f54294a;
1239
+ s->ghwcfg1 = 0;
1240
+ s->ghwcfg2 = (8 << GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT) |
1241
+ (4 << GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT) |
1242
+ (4 << GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT) |
1243
+ GHWCFG2_DYNAMIC_FIFO |
1244
+ GHWCFG2_PERIO_EP_SUPPORTED |
1245
+ ((DWC2_NB_CHAN - 1) << GHWCFG2_NUM_HOST_CHAN_SHIFT) |
1246
+ (GHWCFG2_INT_DMA_ARCH << GHWCFG2_ARCHITECTURE_SHIFT) |
1247
+ (GHWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST << GHWCFG2_OP_MODE_SHIFT);
1248
+ s->ghwcfg3 = (4096 << GHWCFG3_DFIFO_DEPTH_SHIFT) |
1249
+ (4 << GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT) |
1250
+ (4 << GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT);
1251
+ s->ghwcfg4 = 0;
1252
+ s->glpmcfg = 0;
1253
+ s->gpwrdn = GPWRDN_PWRDNRSTN;
1254
+ s->gdfifocfg = 0;
1255
+ s->gadpctl = 0;
1256
+ s->grefclk = 0;
1257
+ s->gintmsk2 = 0;
1258
+ s->gintsts2 = 0;
1259
+
1260
+ s->hptxfsiz = 500 << FIFOSIZE_DEPTH_SHIFT;
1261
+
1262
+ s->hcfg = 2 << HCFG_RESVALID_SHIFT;
1263
+ s->hfir = 60000;
1264
+ s->hfnum = 0x3fff;
1265
+ s->hptxsts = (16 << TXSTS_QSPCAVAIL_SHIFT) | 32768;
1266
+ s->haint = 0;
1267
+ s->haintmsk = 0;
1268
+ s->hprt0 = 0;
1269
+
1270
+ memset(s->hreg1, 0, sizeof(s->hreg1));
1271
+ memset(s->pcgreg, 0, sizeof(s->pcgreg));
1272
+
1273
+ s->sof_time = 0;
1274
+ s->frame_number = 0;
1275
+ s->fi = USB_FRMINTVL - 1;
1276
+ s->next_chan = 0;
1277
+ s->working = false;
1278
+
1279
+ for (i = 0; i < DWC2_NB_CHAN; i++) {
1280
+ s->packet[i].needs_service = false;
1281
+ }
1282
+}
1283
+
1284
+static void dwc2_reset_hold(Object *obj)
1285
+{
1286
+ DWC2Class *c = DWC2_GET_CLASS(obj);
1287
+ DWC2State *s = DWC2_USB(obj);
1288
+
1289
+ trace_usb_dwc2_reset_hold();
1290
+
1291
+ if (c->parent_phases.hold) {
1292
+ c->parent_phases.hold(obj);
1293
+ }
1294
+
1295
+ dwc2_update_irq(s);
1296
+}
1297
+
1298
+static void dwc2_reset_exit(Object *obj)
1299
+{
1300
+ DWC2Class *c = DWC2_GET_CLASS(obj);
1301
+ DWC2State *s = DWC2_USB(obj);
1302
+
1303
+ trace_usb_dwc2_reset_exit();
1304
+
1305
+ if (c->parent_phases.exit) {
1306
+ c->parent_phases.exit(obj);
1307
+ }
1308
+
1309
+ s->hprt0 = HPRT0_PWR;
1310
+ if (s->uport.dev && s->uport.dev->attached) {
1311
+ usb_attach(&s->uport);
1312
+ usb_device_reset(s->uport.dev);
1313
+ }
1314
+}
1315
+
1316
+static void dwc2_realize(DeviceState *dev, Error **errp)
1317
+{
1318
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
1319
+ DWC2State *s = DWC2_USB(dev);
1320
+ Object *obj;
1321
+ Error *err = NULL;
1322
+
1323
+ obj = object_property_get_link(OBJECT(dev), "dma-mr", &err);
1324
+ if (err) {
1325
+ error_setg(errp, "dwc2: required dma-mr link not found: %s",
1326
+ error_get_pretty(err));
1327
+ return;
1328
+ }
1329
+ assert(obj != NULL);
1330
+
1331
+ s->dma_mr = MEMORY_REGION(obj);
1332
+ address_space_init(&s->dma_as, s->dma_mr, "dwc2");
1333
+
1334
+ usb_bus_new(&s->bus, sizeof(s->bus), &dwc2_bus_ops, dev);
1335
+ usb_register_port(&s->bus, &s->uport, s, 0, &dwc2_port_ops,
1336
+ USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL |
1337
+ (s->usb_version == 2 ? USB_SPEED_MASK_HIGH : 0));
1338
+ s->uport.dev = 0;
1339
+
1340
+ s->usb_frame_time = NANOSECONDS_PER_SECOND / 1000; /* 1000000 */
1341
+ if (NANOSECONDS_PER_SECOND >= USB_HZ_FS) {
1342
+ s->usb_bit_time = NANOSECONDS_PER_SECOND / USB_HZ_FS; /* 83.3 */
1343
+ } else {
1344
+ s->usb_bit_time = 1;
1345
+ }
1346
+
1347
+ s->fi = USB_FRMINTVL - 1;
1348
+ s->eof_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, dwc2_frame_boundary, s);
1349
+ s->frame_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, dwc2_work_timer, s);
1350
+ s->async_bh = qemu_bh_new(dwc2_work_bh, s);
1351
+
1352
+ sysbus_init_irq(sbd, &s->irq);
1353
+}
1354
+
1355
+static void dwc2_init(Object *obj)
1356
+{
1357
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
1358
+ DWC2State *s = DWC2_USB(obj);
1359
+
1360
+ memory_region_init(&s->container, obj, "dwc2", DWC2_MMIO_SIZE);
1361
+ sysbus_init_mmio(sbd, &s->container);
1362
+
1363
+ memory_region_init_io(&s->hsotg, obj, &dwc2_mmio_hsotg_ops, s,
1364
+ "dwc2-io", 4 * KiB);
1365
+ memory_region_add_subregion(&s->container, 0x0000, &s->hsotg);
1366
+
1367
+ memory_region_init_io(&s->fifos, obj, &dwc2_mmio_hreg2_ops, s,
1368
+ "dwc2-fifo", 64 * KiB);
1369
+ memory_region_add_subregion(&s->container, 0x1000, &s->fifos);
1370
+}
1371
+
1372
+static const VMStateDescription vmstate_dwc2_state_packet = {
1373
+ .name = "dwc2/packet",
1374
+ .version_id = 1,
1375
+ .minimum_version_id = 1,
1376
+ .fields = (VMStateField[]) {
1377
+ VMSTATE_UINT32(devadr, DWC2Packet),
1378
+ VMSTATE_UINT32(epnum, DWC2Packet),
1379
+ VMSTATE_UINT32(epdir, DWC2Packet),
1380
+ VMSTATE_UINT32(mps, DWC2Packet),
1381
+ VMSTATE_UINT32(pid, DWC2Packet),
1382
+ VMSTATE_UINT32(index, DWC2Packet),
1383
+ VMSTATE_UINT32(pcnt, DWC2Packet),
1384
+ VMSTATE_UINT32(len, DWC2Packet),
1385
+ VMSTATE_INT32(async, DWC2Packet),
1386
+ VMSTATE_BOOL(small, DWC2Packet),
1387
+ VMSTATE_BOOL(needs_service, DWC2Packet),
1388
+ VMSTATE_END_OF_LIST()
1389
+ },
1390
+};
1391
+
1392
+const VMStateDescription vmstate_dwc2_state = {
1393
+ .name = "dwc2",
1394
+ .version_id = 1,
1395
+ .minimum_version_id = 1,
1396
+ .fields = (VMStateField[]) {
1397
+ VMSTATE_UINT32_ARRAY(glbreg, DWC2State,
1398
+ DWC2_GLBREG_SIZE / sizeof(uint32_t)),
1399
+ VMSTATE_UINT32_ARRAY(fszreg, DWC2State,
1400
+ DWC2_FSZREG_SIZE / sizeof(uint32_t)),
1401
+ VMSTATE_UINT32_ARRAY(hreg0, DWC2State,
1402
+ DWC2_HREG0_SIZE / sizeof(uint32_t)),
1403
+ VMSTATE_UINT32_ARRAY(hreg1, DWC2State,
1404
+ DWC2_HREG1_SIZE / sizeof(uint32_t)),
1405
+ VMSTATE_UINT32_ARRAY(pcgreg, DWC2State,
1406
+ DWC2_PCGREG_SIZE / sizeof(uint32_t)),
1407
+
1408
+ VMSTATE_TIMER_PTR(eof_timer, DWC2State),
1409
+ VMSTATE_TIMER_PTR(frame_timer, DWC2State),
1410
+ VMSTATE_INT64(sof_time, DWC2State),
1411
+ VMSTATE_INT64(usb_frame_time, DWC2State),
1412
+ VMSTATE_INT64(usb_bit_time, DWC2State),
1413
+ VMSTATE_UINT32(usb_version, DWC2State),
1414
+ VMSTATE_UINT16(frame_number, DWC2State),
1415
+ VMSTATE_UINT16(fi, DWC2State),
1416
+ VMSTATE_UINT16(next_chan, DWC2State),
1417
+ VMSTATE_BOOL(working, DWC2State),
1418
+
1419
+ VMSTATE_STRUCT_ARRAY(packet, DWC2State, DWC2_NB_CHAN, 1,
1420
+ vmstate_dwc2_state_packet, DWC2Packet),
1421
+ VMSTATE_UINT8_2DARRAY(usb_buf, DWC2State, DWC2_NB_CHAN,
1422
+ DWC2_MAX_XFER_SIZE),
1423
+
1424
+ VMSTATE_END_OF_LIST()
1425
+ }
1426
+};
1427
+
1428
+static Property dwc2_usb_properties[] = {
1429
+ DEFINE_PROP_UINT32("usb_version", DWC2State, usb_version, 2),
1430
+ DEFINE_PROP_END_OF_LIST(),
1431
+};
1432
+
1433
+static void dwc2_class_init(ObjectClass *klass, void *data)
1434
+{
1435
+ DeviceClass *dc = DEVICE_CLASS(klass);
1436
+ DWC2Class *c = DWC2_CLASS(klass);
1437
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
1438
+
1439
+ dc->realize = dwc2_realize;
1440
+ dc->vmsd = &vmstate_dwc2_state;
1441
+ set_bit(DEVICE_CATEGORY_USB, dc->categories);
1442
+ device_class_set_props(dc, dwc2_usb_properties);
1443
+ resettable_class_set_parent_phases(rc, dwc2_reset_enter, dwc2_reset_hold,
1444
+ dwc2_reset_exit, &c->parent_phases);
1445
+}
1446
+
1447
+static const TypeInfo dwc2_usb_type_info = {
1448
+ .name = TYPE_DWC2_USB,
1449
+ .parent = TYPE_SYS_BUS_DEVICE,
1450
+ .instance_size = sizeof(DWC2State),
1451
+ .instance_init = dwc2_init,
1452
+ .class_size = sizeof(DWC2Class),
1453
+ .class_init = dwc2_class_init,
1454
+};
1455
+
1456
+static void dwc2_usb_register_types(void)
1457
+{
1458
+ type_register_static(&dwc2_usb_type_info);
1459
+}
1460
+
1461
+type_init(dwc2_usb_register_types)
1462
diff --git a/hw/usb/Kconfig b/hw/usb/Kconfig
1463
index XXXXXXX..XXXXXXX 100644
1464
--- a/hw/usb/Kconfig
1465
+++ b/hw/usb/Kconfig
1466
@@ -XXX,XX +XXX,XX @@ config USB_MUSB
1467
bool
1468
select USB
1469
1470
+config USB_DWC2
1471
+ bool
1472
+ default y
1473
+ select USB
1474
+
1475
config TUSB6010
1476
bool
1477
select USB_MUSB
1478
diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs
1479
index XXXXXXX..XXXXXXX 100644
1480
--- a/hw/usb/Makefile.objs
1481
+++ b/hw/usb/Makefile.objs
1482
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_USB_EHCI_SYSBUS) += hcd-ehci-sysbus.o
1483
common-obj-$(CONFIG_USB_XHCI) += hcd-xhci.o
1484
common-obj-$(CONFIG_USB_XHCI_NEC) += hcd-xhci-nec.o
1485
common-obj-$(CONFIG_USB_MUSB) += hcd-musb.o
1486
+common-obj-$(CONFIG_USB_DWC2) += hcd-dwc2.o
1487
1488
common-obj-$(CONFIG_TUSB6010) += tusb6010.o
1489
common-obj-$(CONFIG_IMX) += chipidea.o
1490
diff --git a/hw/usb/trace-events b/hw/usb/trace-events
1491
index XXXXXXX..XXXXXXX 100644
1492
--- a/hw/usb/trace-events
1493
+++ b/hw/usb/trace-events
1494
@@ -XXX,XX +XXX,XX @@ usb_xhci_xfer_error(void *xfer, uint32_t ret) "%p: ret %d"
1495
usb_xhci_unimplemented(const char *item, int nr) "%s (0x%x)"
1496
usb_xhci_enforced_limit(const char *item) "%s"
1497
1498
+# hcd-dwc2.c
1499
+usb_dwc2_update_irq(uint32_t level) "level=%d"
1500
+usb_dwc2_raise_global_irq(uint32_t intr) "0x%08x"
1501
+usb_dwc2_lower_global_irq(uint32_t intr) "0x%08x"
1502
+usb_dwc2_raise_host_irq(uint32_t intr) "0x%04x"
1503
+usb_dwc2_lower_host_irq(uint32_t intr) "0x%04x"
1504
+usb_dwc2_sof(int64_t next) "next SOF %" PRId64
1505
+usb_dwc2_bus_start(void) "start SOFs"
1506
+usb_dwc2_bus_stop(void) "stop SOFs"
1507
+usb_dwc2_find_device(uint8_t addr) "%d"
1508
+usb_dwc2_port_disabled(uint32_t pnum) "port %d disabled"
1509
+usb_dwc2_device_found(uint32_t pnum) "device found on port %d"
1510
+usb_dwc2_device_not_found(void) "device not found"
1511
+usb_dwc2_handle_packet(uint32_t chan, void *dev, void *pkt, uint32_t ep, const char *type, const char *dir, uint32_t mps, uint32_t len, uint32_t pcnt) "ch %d dev %p pkt %p ep %d type %s dir %s mps %d len %d pcnt %d"
1512
+usb_dwc2_memory_read(uint32_t addr, uint32_t len) "addr %d len %d"
1513
+usb_dwc2_packet_status(const char *status, uint32_t len) "status %s len %d"
1514
+usb_dwc2_packet_error(const char *status) "ERROR %s"
1515
+usb_dwc2_async_packet(void *pkt, uint32_t chan, void *dev, uint32_t ep, const char *dir, uint32_t len) "pkt %p ch %d dev %p ep %d %s len %d"
1516
+usb_dwc2_memory_write(uint32_t addr, uint32_t len) "addr %d len %d"
1517
+usb_dwc2_packet_done(const char *status, uint32_t actual, uint32_t len, uint32_t pcnt) "status %s actual %d len %d pcnt %d"
1518
+usb_dwc2_packet_next(const char *status, uint32_t len, uint32_t pcnt) "status %s len %d pcnt %d"
1519
+usb_dwc2_attach(void *port) "port %p"
1520
+usb_dwc2_attach_speed(const char *speed) "%s-speed device attached"
1521
+usb_dwc2_detach(void *port) "port %p"
1522
+usb_dwc2_child_detach(void *port, void *child) "port %p child %p"
1523
+usb_dwc2_wakeup(void *port) "port %p"
1524
+usb_dwc2_async_packet_complete(void *port, void *pkt, uint32_t chan, void *dev, uint32_t ep, const char *dir, uint32_t len) "port %p packet %p ch %d dev %p ep %d %s len %d"
1525
+usb_dwc2_work_bh(void) ""
1526
+usb_dwc2_work_bh_service(uint32_t first, uint32_t current, void *dev, uint32_t ep) "first %d servicing %d dev %p ep %d"
1527
+usb_dwc2_work_bh_next(uint32_t chan) "next %d"
1528
+usb_dwc2_enable_chan(uint32_t chan, void *dev, void *pkt, uint32_t ep) "ch %d dev %p pkt %p ep %d"
1529
+usb_dwc2_glbreg_read(uint64_t addr, const char *reg, uint32_t val) " 0x%04" PRIx64 " %s val 0x%08x"
1530
+usb_dwc2_glbreg_write(uint64_t addr, const char *reg, uint64_t val, uint32_t old, uint64_t result) "0x%04" PRIx64 " %s val 0x%08" PRIx64 " old 0x%08x result 0x%08" PRIx64
1531
+usb_dwc2_fszreg_read(uint64_t addr, uint32_t val) " 0x%04" PRIx64 " HPTXFSIZ val 0x%08x"
1532
+usb_dwc2_fszreg_write(uint64_t addr, uint64_t val, uint32_t old, uint64_t result) "0x%04" PRIx64 " HPTXFSIZ val 0x%08" PRIx64 " old 0x%08x result 0x%08" PRIx64
1533
+usb_dwc2_hreg0_read(uint64_t addr, const char *reg, uint32_t val) " 0x%04" PRIx64 " %s val 0x%08x"
1534
+usb_dwc2_hreg0_write(uint64_t addr, const char *reg, uint64_t val, uint32_t old, uint64_t result) " 0x%04" PRIx64 " %s val 0x%08" PRIx64 " old 0x%08x result 0x%08" PRIx64
1535
+usb_dwc2_hreg1_read(uint64_t addr, const char *reg, uint64_t chan, uint32_t val) " 0x%04" PRIx64 " %s%" PRId64 " val 0x%08x"
1536
+usb_dwc2_hreg1_write(uint64_t addr, const char *reg, uint64_t chan, uint64_t val, uint32_t old, uint64_t result) " 0x%04" PRIx64 " %s%" PRId64 " val 0x%08" PRIx64 " old 0x%08x result 0x%08" PRIx64
1537
+usb_dwc2_pcgreg_read(uint64_t addr, const char *reg, uint32_t val) " 0x%04" PRIx64 " %s val 0x%08x"
1538
+usb_dwc2_pcgreg_write(uint64_t addr, const char *reg, uint64_t val, uint32_t old, uint64_t result) "0x%04" PRIx64 " %s val 0x%08" PRIx64 " old 0x%08x result 0x%08" PRIx64
1539
+usb_dwc2_hreg2_read(uint64_t addr, uint64_t fifo, uint32_t val) " 0x%04" PRIx64 " FIFO%" PRId64 " val 0x%08x"
1540
+usb_dwc2_hreg2_write(uint64_t addr, uint64_t fifo, uint64_t val, uint32_t old, uint64_t result) " 0x%04" PRIx64 " FIFO%" PRId64 " val 0x%08" PRIx64 " old 0x%08x result 0x%08" PRIx64
1541
+usb_dwc2_hreg0_action(const char *s) "%s"
1542
+usb_dwc2_wakeup_endpoint(void *ep, uint32_t stream) "endp %p stream %d"
1543
+usb_dwc2_work_timer(void) ""
1544
+usb_dwc2_reset_enter(void) "=== RESET enter ==="
1545
+usb_dwc2_reset_hold(void) "=== RESET hold ==="
1546
+usb_dwc2_reset_exit(void) "=== RESET exit ==="
1547
+
1548
# desc.c
1549
usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"
1550
usb_desc_device_qualifier(int addr, int len, int ret) "dev %d query device qualifier, len %d, ret %d"
1551
--
89
--
1552
2.20.1
90
2.20.1
1553
91
1554
92
diff view generated by jsdifflib
New patch
1
We were not paying attention to the ECI state when advancing the VPT
2
state. Architecturally, VPT state advance happens for every beat
3
(see the pseudocode VPTAdvance()), so on every beat the 4 bits of
4
VPR.P0 corresponding to the current beat are inverted if required,
5
and at the end of beats 1 and 3 the VPR MASK fields are updated.
6
This means that if the ECI state says we should not be executing all
7
4 beats then we need to skip some of the updating of the VPR that we
8
currently do in mve_advance_vpt().
1
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
---
13
target/arm/mve_helper.c | 24 +++++++++++++++++-------
14
1 file changed, 17 insertions(+), 7 deletions(-)
15
16
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/mve_helper.c
19
+++ b/target/arm/mve_helper.c
20
@@ -XXX,XX +XXX,XX @@ static void mve_advance_vpt(CPUARMState *env)
21
/* Advance the VPT and ECI state if necessary */
22
uint32_t vpr = env->v7m.vpr;
23
unsigned mask01, mask23;
24
+ uint16_t inv_mask;
25
+ uint16_t eci_mask = mve_eci_mask(env);
26
27
if ((env->condexec_bits & 0xf) == 0) {
28
env->condexec_bits = (env->condexec_bits == (ECI_A0A1A2B0 << 4)) ?
29
@@ -XXX,XX +XXX,XX @@ static void mve_advance_vpt(CPUARMState *env)
30
return;
31
}
32
33
+ /* Invert P0 bits if needed, but only for beats we actually executed */
34
mask01 = FIELD_EX32(vpr, V7M_VPR, MASK01);
35
mask23 = FIELD_EX32(vpr, V7M_VPR, MASK23);
36
- if (mask01 > 8) {
37
- /* high bit set, but not 0b1000: invert the relevant half of P0 */
38
- vpr ^= 0xff;
39
+ /* Start by assuming we invert all bits corresponding to executed beats */
40
+ inv_mask = eci_mask;
41
+ if (mask01 <= 8) {
42
+ /* MASK01 says don't invert low half of P0 */
43
+ inv_mask &= ~0xff;
44
}
45
- if (mask23 > 8) {
46
- /* high bit set, but not 0b1000: invert the relevant half of P0 */
47
- vpr ^= 0xff00;
48
+ if (mask23 <= 8) {
49
+ /* MASK23 says don't invert high half of P0 */
50
+ inv_mask &= ~0xff00;
51
}
52
- vpr = FIELD_DP32(vpr, V7M_VPR, MASK01, mask01 << 1);
53
+ vpr ^= inv_mask;
54
+ /* Only update MASK01 if beat 1 executed */
55
+ if (eci_mask & 0xf0) {
56
+ vpr = FIELD_DP32(vpr, V7M_VPR, MASK01, mask01 << 1);
57
+ }
58
+ /* Beat 3 always executes, so update MASK23 */
59
vpr = FIELD_DP32(vpr, V7M_VPR, MASK23, mask23 << 1);
60
env->v7m.vpr = vpr;
61
}
62
--
63
2.20.1
64
65
diff view generated by jsdifflib
New patch
1
For vector loads, predicated elements are zeroed, instead of
2
retaining their previous values (as happens for most data
3
processing operations). This means we need to distinguish
4
"beat not executed due to ECI" (don't touch destination
5
element) from "beat executed but predicated out" (zero
6
destination element).
1
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
---
11
target/arm/mve_helper.c | 8 +++++---
12
1 file changed, 5 insertions(+), 3 deletions(-)
13
14
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/mve_helper.c
17
+++ b/target/arm/mve_helper.c
18
@@ -XXX,XX +XXX,XX @@ static void mve_advance_vpt(CPUARMState *env)
19
env->v7m.vpr = vpr;
20
}
21
22
-
23
+/* For loads, predicated lanes are zeroed instead of keeping their old values */
24
#define DO_VLDR(OP, MSIZE, LDTYPE, ESIZE, TYPE) \
25
void HELPER(mve_##OP)(CPUARMState *env, void *vd, uint32_t addr) \
26
{ \
27
TYPE *d = vd; \
28
uint16_t mask = mve_element_mask(env); \
29
+ uint16_t eci_mask = mve_eci_mask(env); \
30
unsigned b, e; \
31
/* \
32
* R_SXTM allows the dest reg to become UNKNOWN for abandoned \
33
@@ -XXX,XX +XXX,XX @@ static void mve_advance_vpt(CPUARMState *env)
34
* then take an exception. \
35
*/ \
36
for (b = 0, e = 0; b < 16; b += ESIZE, e++) { \
37
- if (mask & (1 << b)) { \
38
- d[H##ESIZE(e)] = cpu_##LDTYPE##_data_ra(env, addr, GETPC()); \
39
+ if (eci_mask & (1 << b)) { \
40
+ d[H##ESIZE(e)] = (mask & (1 << b)) ? \
41
+ cpu_##LDTYPE##_data_ra(env, addr, GETPC()) : 0; \
42
} \
43
addr += MSIZE; \
44
} \
45
--
46
2.20.1
47
48
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Implement the MVE VMULL (polynomial) insn. Unlike Neon, this comes
2
in two flavours: 8x8->16 and a 16x16->32. Also unlike Neon, the
3
inputs are in either the low or the high half of each double-width
4
element.
2
5
3
With this conversion, we will be able to use the same helpers
6
The assembler for this insn indicates the size with "P8" or "P16",
4
with sve. In particular, pass 3 vector parameters for the
7
encoded into bit 28 as size = 0 or 1. We choose to follow the
5
3-operand operations; for advsimd the destination register
8
same encoding as VQDMULL and decode this into a->size as MO_16
6
is also an input.
9
or MO_32 indicating the size of the result elements. This then
10
carries through to the helper function names where it then
11
matches up with the existing pmull_h() which does an 8x8->16
12
operation and a new pmull_w() which does the 16x16->32.
7
13
8
This also fixes a bug in which we failed to clear the high bits
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
of the SVE register after an AdvSIMD operation.
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
---
17
target/arm/helper-mve.h | 5 +++++
18
target/arm/vec_internal.h | 11 +++++++++++
19
target/arm/mve.decode | 14 ++++++++++----
20
target/arm/mve_helper.c | 16 ++++++++++++++++
21
target/arm/translate-mve.c | 28 ++++++++++++++++++++++++++++
22
target/arm/vec_helper.c | 14 +++++++++++++-
23
6 files changed, 83 insertions(+), 5 deletions(-)
10
24
11
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
25
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
12
Message-id: 20200514212831.31248-2-richard.henderson@linaro.org
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
---
16
target/arm/helper.h | 6 ++--
17
target/arm/vec_internal.h | 33 +++++++++++++++++
18
target/arm/crypto_helper.c | 72 +++++++++++++++++++++++++++-----------
19
target/arm/translate-a64.c | 55 ++++++++++++++++++-----------
20
target/arm/translate.c | 27 +++++++-------
21
target/arm/vec_helper.c | 12 +------
22
6 files changed, 138 insertions(+), 67 deletions(-)
23
create mode 100644 target/arm/vec_internal.h
24
25
diff --git a/target/arm/helper.h b/target/arm/helper.h
26
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/helper.h
27
--- a/target/arm/helper-mve.h
28
+++ b/target/arm/helper.h
28
+++ b/target/arm/helper-mve.h
29
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(neon_qzip8, TCG_CALL_NO_RWG, void, ptr, ptr)
29
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmulltub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
DEF_HELPER_FLAGS_2(neon_qzip16, TCG_CALL_NO_RWG, void, ptr, ptr)
30
DEF_HELPER_FLAGS_4(mve_vmulltuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
31
DEF_HELPER_FLAGS_2(neon_qzip32, TCG_CALL_NO_RWG, void, ptr, ptr)
31
DEF_HELPER_FLAGS_4(mve_vmulltuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
32
32
33
-DEF_HELPER_FLAGS_3(crypto_aese, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
33
+DEF_HELPER_FLAGS_4(mve_vmullpbh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
34
+DEF_HELPER_FLAGS_4(crypto_aese, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
34
+DEF_HELPER_FLAGS_4(mve_vmullpth, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
35
DEF_HELPER_FLAGS_3(crypto_aesmc, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
35
+DEF_HELPER_FLAGS_4(mve_vmullpbw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
36
36
+DEF_HELPER_FLAGS_4(mve_vmullptw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
37
DEF_HELPER_FLAGS_4(crypto_sha1_3reg, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
37
+
38
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_5(crypto_sm3tt, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32, i32)
38
DEF_HELPER_FLAGS_4(mve_vqdmulhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
39
DEF_HELPER_FLAGS_3(crypto_sm3partw1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
39
DEF_HELPER_FLAGS_4(mve_vqdmulhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
40
DEF_HELPER_FLAGS_3(crypto_sm3partw2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
40
DEF_HELPER_FLAGS_4(mve_vqdmulhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
41
42
-DEF_HELPER_FLAGS_2(crypto_sm4e, TCG_CALL_NO_RWG, void, ptr, ptr)
43
-DEF_HELPER_FLAGS_3(crypto_sm4ekey, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
44
+DEF_HELPER_FLAGS_4(crypto_sm4e, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
45
+DEF_HELPER_FLAGS_4(crypto_sm4ekey, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
46
47
DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
48
DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
49
diff --git a/target/arm/vec_internal.h b/target/arm/vec_internal.h
41
diff --git a/target/arm/vec_internal.h b/target/arm/vec_internal.h
50
new file mode 100644
42
index XXXXXXX..XXXXXXX 100644
51
index XXXXXXX..XXXXXXX
43
--- a/target/arm/vec_internal.h
52
--- /dev/null
53
+++ b/target/arm/vec_internal.h
44
+++ b/target/arm/vec_internal.h
54
@@ -XXX,XX +XXX,XX @@
45
@@ -XXX,XX +XXX,XX @@ int16_t do_sqrdmlah_h(int16_t, int16_t, int16_t, bool, bool, uint32_t *);
46
int32_t do_sqrdmlah_s(int32_t, int32_t, int32_t, bool, bool, uint32_t *);
47
int64_t do_sqrdmlah_d(int64_t, int64_t, int64_t, bool, bool);
48
55
+/*
49
+/*
56
+ * ARM AdvSIMD / SVE Vector Helpers
50
+ * 8 x 8 -> 16 vector polynomial multiply where the inputs are
57
+ *
51
+ * in the low 8 bits of each 16-bit element
58
+ * Copyright (c) 2020 Linaro
52
+*/
59
+ *
53
+uint64_t pmull_h(uint64_t op1, uint64_t op2);
60
+ * This library is free software; you can redistribute it and/or
54
+/*
61
+ * modify it under the terms of the GNU Lesser General Public
55
+ * 16 x 16 -> 32 vector polynomial multiply where the inputs are
62
+ * License as published by the Free Software Foundation; either
56
+ * in the low 16 bits of each 32-bit element
63
+ * version 2 of the License, or (at your option) any later version.
64
+ *
65
+ * This library 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 GNU
68
+ * Lesser General Public License for more details.
69
+ *
70
+ * You should have received a copy of the GNU Lesser General Public
71
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
72
+ */
57
+ */
58
+uint64_t pmull_w(uint64_t op1, uint64_t op2);
73
+
59
+
74
+#ifndef TARGET_ARM_VEC_INTERNALS_H
60
#endif /* TARGET_ARM_VEC_INTERNALS_H */
75
+#define TARGET_ARM_VEC_INTERNALS_H
61
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
62
index XXXXXXX..XXXXXXX 100644
63
--- a/target/arm/mve.decode
64
+++ b/target/arm/mve.decode
65
@@ -XXX,XX +XXX,XX @@ VHADD_U 111 1 1111 0 . .. ... 0 ... 0 0000 . 1 . 0 ... 0 @2op
66
VHSUB_S 111 0 1111 0 . .. ... 0 ... 0 0010 . 1 . 0 ... 0 @2op
67
VHSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 0 ... 0 @2op
68
69
-VMULL_BS 111 0 1110 0 . .. ... 1 ... 0 1110 . 0 . 0 ... 0 @2op
70
-VMULL_BU 111 1 1110 0 . .. ... 1 ... 0 1110 . 0 . 0 ... 0 @2op
71
-VMULL_TS 111 0 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
72
-VMULL_TU 111 1 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
73
+{
74
+ VMULLP_B 111 . 1110 0 . 11 ... 1 ... 0 1110 . 0 . 0 ... 0 @2op_sz28
75
+ VMULL_BS 111 0 1110 0 . .. ... 1 ... 0 1110 . 0 . 0 ... 0 @2op
76
+ VMULL_BU 111 1 1110 0 . .. ... 1 ... 0 1110 . 0 . 0 ... 0 @2op
77
+}
78
+{
79
+ VMULLP_T 111 . 1110 0 . 11 ... 1 ... 1 1110 . 0 . 0 ... 0 @2op_sz28
80
+ VMULL_TS 111 0 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
81
+ VMULL_TU 111 1 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
82
+}
83
84
VQDMULH 1110 1111 0 . .. ... 0 ... 0 1011 . 1 . 0 ... 0 @2op
85
VQRDMULH 1111 1111 0 . .. ... 0 ... 0 1011 . 1 . 0 ... 0 @2op
86
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
87
index XXXXXXX..XXXXXXX 100644
88
--- a/target/arm/mve_helper.c
89
+++ b/target/arm/mve_helper.c
90
@@ -XXX,XX +XXX,XX @@ DO_2OP_L(vmulltub, 1, 1, uint8_t, 2, uint16_t, DO_MUL)
91
DO_2OP_L(vmulltuh, 1, 2, uint16_t, 4, uint32_t, DO_MUL)
92
DO_2OP_L(vmulltuw, 1, 4, uint32_t, 8, uint64_t, DO_MUL)
93
94
+/*
95
+ * Polynomial multiply. We can always do this generating 64 bits
96
+ * of the result at a time, so we don't need to use DO_2OP_L.
97
+ */
98
+#define VMULLPH_MASK 0x00ff00ff00ff00ffULL
99
+#define VMULLPW_MASK 0x0000ffff0000ffffULL
100
+#define DO_VMULLPBH(N, M) pmull_h((N) & VMULLPH_MASK, (M) & VMULLPH_MASK)
101
+#define DO_VMULLPTH(N, M) DO_VMULLPBH((N) >> 8, (M) >> 8)
102
+#define DO_VMULLPBW(N, M) pmull_w((N) & VMULLPW_MASK, (M) & VMULLPW_MASK)
103
+#define DO_VMULLPTW(N, M) DO_VMULLPBW((N) >> 16, (M) >> 16)
76
+
104
+
77
+static inline void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
105
+DO_2OP(vmullpbh, 8, uint64_t, DO_VMULLPBH)
106
+DO_2OP(vmullpth, 8, uint64_t, DO_VMULLPTH)
107
+DO_2OP(vmullpbw, 8, uint64_t, DO_VMULLPBW)
108
+DO_2OP(vmullptw, 8, uint64_t, DO_VMULLPTW)
109
+
110
/*
111
* Because the computation type is at least twice as large as required,
112
* these work for both signed and unsigned source types.
113
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
114
index XXXXXXX..XXXXXXX 100644
115
--- a/target/arm/translate-mve.c
116
+++ b/target/arm/translate-mve.c
117
@@ -XXX,XX +XXX,XX @@ static bool trans_VQDMULLT(DisasContext *s, arg_2op *a)
118
return do_2op(s, a, fns[a->size]);
119
}
120
121
+static bool trans_VMULLP_B(DisasContext *s, arg_2op *a)
78
+{
122
+{
79
+ uint64_t *d = vd + opr_sz;
123
+ /*
80
+ uintptr_t i;
124
+ * Note that a->size indicates the output size, ie VMULL.P8
81
+
125
+ * is the 8x8->16 operation and a->size is MO_16; VMULL.P16
82
+ for (i = opr_sz; i < max_sz; i += 8) {
126
+ * is the 16x16->32 operation and a->size is MO_32.
83
+ *d++ = 0;
127
+ */
84
+ }
128
+ static MVEGenTwoOpFn * const fns[] = {
129
+ NULL,
130
+ gen_helper_mve_vmullpbh,
131
+ gen_helper_mve_vmullpbw,
132
+ NULL,
133
+ };
134
+ return do_2op(s, a, fns[a->size]);
85
+}
135
+}
86
+
136
+
87
+#endif /* TARGET_ARM_VEC_INTERNALS_H */
137
+static bool trans_VMULLP_T(DisasContext *s, arg_2op *a)
88
diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/target/arm/crypto_helper.c
91
+++ b/target/arm/crypto_helper.c
92
@@ -XXX,XX +XXX,XX @@
93
94
#include "cpu.h"
95
#include "exec/helper-proto.h"
96
+#include "tcg/tcg-gvec-desc.h"
97
#include "crypto/aes.h"
98
+#include "vec_internal.h"
99
100
union CRYPTO_STATE {
101
uint8_t bytes[16];
102
@@ -XXX,XX +XXX,XX @@ union CRYPTO_STATE {
103
#define CR_ST_WORD(state, i) (state.words[i])
104
#endif
105
106
-void HELPER(crypto_aese)(void *vd, void *vm, uint32_t decrypt)
107
+static void do_crypto_aese(uint64_t *rd, uint64_t *rn,
108
+ uint64_t *rm, bool decrypt)
109
{
110
static uint8_t const * const sbox[2] = { AES_sbox, AES_isbox };
111
static uint8_t const * const shift[2] = { AES_shifts, AES_ishifts };
112
- uint64_t *rd = vd;
113
- uint64_t *rm = vm;
114
union CRYPTO_STATE rk = { .l = { rm[0], rm[1] } };
115
- union CRYPTO_STATE st = { .l = { rd[0], rd[1] } };
116
+ union CRYPTO_STATE st = { .l = { rn[0], rn[1] } };
117
int i;
118
119
- assert(decrypt < 2);
120
-
121
/* xor state vector with round key */
122
rk.l[0] ^= st.l[0];
123
rk.l[1] ^= st.l[1];
124
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_aese)(void *vd, void *vm, uint32_t decrypt)
125
rd[1] = st.l[1];
126
}
127
128
-void HELPER(crypto_aesmc)(void *vd, void *vm, uint32_t decrypt)
129
+void HELPER(crypto_aese)(void *vd, void *vn, void *vm, uint32_t desc)
130
+{
138
+{
131
+ intptr_t i, opr_sz = simd_oprsz(desc);
139
+ /* a->size is as for trans_VMULLP_B */
132
+ bool decrypt = simd_data(desc);
140
+ static MVEGenTwoOpFn * const fns[] = {
133
+
141
+ NULL,
134
+ for (i = 0; i < opr_sz; i += 16) {
142
+ gen_helper_mve_vmullpth,
135
+ do_crypto_aese(vd + i, vn + i, vm + i, decrypt);
143
+ gen_helper_mve_vmullptw,
136
+ }
144
+ NULL,
137
+ clear_tail(vd, opr_sz, simd_maxsz(desc));
145
+ };
138
+}
146
+ return do_2op(s, a, fns[a->size]);
139
+
140
+static void do_crypto_aesmc(uint64_t *rd, uint64_t *rm, bool decrypt)
141
{
142
static uint32_t const mc[][256] = { {
143
/* MixColumns lookup table */
144
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_aesmc)(void *vd, void *vm, uint32_t decrypt)
145
0xbe805d9f, 0xb58d5491, 0xa89a4f83, 0xa397468d,
146
} };
147
148
- uint64_t *rd = vd;
149
- uint64_t *rm = vm;
150
union CRYPTO_STATE st = { .l = { rm[0], rm[1] } };
151
int i;
152
153
- assert(decrypt < 2);
154
-
155
for (i = 0; i < 16; i += 4) {
156
CR_ST_WORD(st, i >> 2) =
157
mc[decrypt][CR_ST_BYTE(st, i)] ^
158
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_aesmc)(void *vd, void *vm, uint32_t decrypt)
159
rd[1] = st.l[1];
160
}
161
162
+void HELPER(crypto_aesmc)(void *vd, void *vm, uint32_t desc)
163
+{
164
+ intptr_t i, opr_sz = simd_oprsz(desc);
165
+ bool decrypt = simd_data(desc);
166
+
167
+ for (i = 0; i < opr_sz; i += 16) {
168
+ do_crypto_aesmc(vd + i, vm + i, decrypt);
169
+ }
170
+ clear_tail(vd, opr_sz, simd_maxsz(desc));
171
+}
147
+}
172
+
148
+
173
/*
149
/*
174
* SHA-1 logical functions
150
* VADC and VSBC: these perform an add-with-carry or subtract-with-carry
175
*/
151
* of the 32-bit elements in each lane of the input vectors, where the
176
@@ -XXX,XX +XXX,XX @@ static uint8_t const sm4_sbox[] = {
177
0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48,
178
};
179
180
-void HELPER(crypto_sm4e)(void *vd, void *vn)
181
+static void do_crypto_sm4e(uint64_t *rd, uint64_t *rn, uint64_t *rm)
182
{
183
- uint64_t *rd = vd;
184
- uint64_t *rn = vn;
185
- union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
186
- union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
187
+ union CRYPTO_STATE d = { .l = { rn[0], rn[1] } };
188
+ union CRYPTO_STATE n = { .l = { rm[0], rm[1] } };
189
uint32_t t, i;
190
191
for (i = 0; i < 4; i++) {
192
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sm4e)(void *vd, void *vn)
193
rd[1] = d.l[1];
194
}
195
196
-void HELPER(crypto_sm4ekey)(void *vd, void *vn, void* vm)
197
+void HELPER(crypto_sm4e)(void *vd, void *vn, void *vm, uint32_t desc)
198
+{
199
+ intptr_t i, opr_sz = simd_oprsz(desc);
200
+
201
+ for (i = 0; i < opr_sz; i += 16) {
202
+ do_crypto_sm4e(vd + i, vn + i, vm + i);
203
+ }
204
+ clear_tail(vd, opr_sz, simd_maxsz(desc));
205
+}
206
+
207
+static void do_crypto_sm4ekey(uint64_t *rd, uint64_t *rn, uint64_t *rm)
208
{
209
- uint64_t *rd = vd;
210
- uint64_t *rn = vn;
211
- uint64_t *rm = vm;
212
union CRYPTO_STATE d;
213
union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
214
union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
215
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sm4ekey)(void *vd, void *vn, void* vm)
216
rd[0] = d.l[0];
217
rd[1] = d.l[1];
218
}
219
+
220
+void HELPER(crypto_sm4ekey)(void *vd, void *vn, void* vm, uint32_t desc)
221
+{
222
+ intptr_t i, opr_sz = simd_oprsz(desc);
223
+
224
+ for (i = 0; i < opr_sz; i += 16) {
225
+ do_crypto_sm4ekey(vd + i, vn + i, vm + i);
226
+ }
227
+ clear_tail(vd, opr_sz, simd_maxsz(desc));
228
+}
229
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
230
index XXXXXXX..XXXXXXX 100644
231
--- a/target/arm/translate-a64.c
232
+++ b/target/arm/translate-a64.c
233
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_fn4(DisasContext *s, bool is_q, int rd, int rn, int rm,
234
is_q ? 16 : 8, vec_full_reg_size(s));
235
}
236
237
+/* Expand a 2-operand operation using an out-of-line helper. */
238
+static void gen_gvec_op2_ool(DisasContext *s, bool is_q, int rd,
239
+ int rn, int data, gen_helper_gvec_2 *fn)
240
+{
241
+ tcg_gen_gvec_2_ool(vec_full_reg_offset(s, rd),
242
+ vec_full_reg_offset(s, rn),
243
+ is_q ? 16 : 8, vec_full_reg_size(s), data, fn);
244
+}
245
+
246
/* Expand a 3-operand operation using an out-of-line helper. */
247
static void gen_gvec_op3_ool(DisasContext *s, bool is_q, int rd,
248
int rn, int rm, int data, gen_helper_gvec_3 *fn)
249
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_aes(DisasContext *s, uint32_t insn)
250
int rn = extract32(insn, 5, 5);
251
int rd = extract32(insn, 0, 5);
252
int decrypt;
253
- TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
254
- TCGv_i32 tcg_decrypt;
255
- CryptoThreeOpIntFn *genfn;
256
+ gen_helper_gvec_2 *genfn2 = NULL;
257
+ gen_helper_gvec_3 *genfn3 = NULL;
258
259
if (!dc_isar_feature(aa64_aes, s) || size != 0) {
260
unallocated_encoding(s);
261
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_aes(DisasContext *s, uint32_t insn)
262
switch (opcode) {
263
case 0x4: /* AESE */
264
decrypt = 0;
265
- genfn = gen_helper_crypto_aese;
266
+ genfn3 = gen_helper_crypto_aese;
267
break;
268
case 0x6: /* AESMC */
269
decrypt = 0;
270
- genfn = gen_helper_crypto_aesmc;
271
+ genfn2 = gen_helper_crypto_aesmc;
272
break;
273
case 0x5: /* AESD */
274
decrypt = 1;
275
- genfn = gen_helper_crypto_aese;
276
+ genfn3 = gen_helper_crypto_aese;
277
break;
278
case 0x7: /* AESIMC */
279
decrypt = 1;
280
- genfn = gen_helper_crypto_aesmc;
281
+ genfn2 = gen_helper_crypto_aesmc;
282
break;
283
default:
284
unallocated_encoding(s);
285
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_aes(DisasContext *s, uint32_t insn)
286
if (!fp_access_check(s)) {
287
return;
288
}
289
-
290
- tcg_rd_ptr = vec_full_reg_ptr(s, rd);
291
- tcg_rn_ptr = vec_full_reg_ptr(s, rn);
292
- tcg_decrypt = tcg_const_i32(decrypt);
293
-
294
- genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_decrypt);
295
-
296
- tcg_temp_free_ptr(tcg_rd_ptr);
297
- tcg_temp_free_ptr(tcg_rn_ptr);
298
- tcg_temp_free_i32(tcg_decrypt);
299
+ if (genfn2) {
300
+ gen_gvec_op2_ool(s, true, rd, rn, decrypt, genfn2);
301
+ } else {
302
+ gen_gvec_op3_ool(s, true, rd, rd, rn, decrypt, genfn3);
303
+ }
304
}
305
306
/* Crypto three-reg SHA
307
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
308
int rn = extract32(insn, 5, 5);
309
int rd = extract32(insn, 0, 5);
310
bool feature;
311
- CryptoThreeOpFn *genfn;
312
+ CryptoThreeOpFn *genfn = NULL;
313
+ gen_helper_gvec_3 *oolfn = NULL;
314
315
if (o == 0) {
316
switch (opcode) {
317
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
318
break;
319
case 2: /* SM4EKEY */
320
feature = dc_isar_feature(aa64_sm4, s);
321
- genfn = gen_helper_crypto_sm4ekey;
322
+ oolfn = gen_helper_crypto_sm4ekey;
323
break;
324
default:
325
unallocated_encoding(s);
326
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
327
return;
328
}
329
330
+ if (oolfn) {
331
+ gen_gvec_op3_ool(s, true, rd, rn, rm, 0, oolfn);
332
+ return;
333
+ }
334
+
335
if (genfn) {
336
TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
337
338
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn)
339
TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
340
bool feature;
341
CryptoTwoOpFn *genfn;
342
+ gen_helper_gvec_3 *oolfn = NULL;
343
344
switch (opcode) {
345
case 0: /* SHA512SU0 */
346
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn)
347
break;
348
case 1: /* SM4E */
349
feature = dc_isar_feature(aa64_sm4, s);
350
- genfn = gen_helper_crypto_sm4e;
351
+ oolfn = gen_helper_crypto_sm4e;
352
break;
353
default:
354
unallocated_encoding(s);
355
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn)
356
return;
357
}
358
359
+ if (oolfn) {
360
+ gen_gvec_op3_ool(s, true, rd, rd, rn, 0, oolfn);
361
+ return;
362
+ }
363
+
364
tcg_rd_ptr = vec_full_reg_ptr(s, rd);
365
tcg_rn_ptr = vec_full_reg_ptr(s, rn);
366
367
diff --git a/target/arm/translate.c b/target/arm/translate.c
368
index XXXXXXX..XXXXXXX 100644
369
--- a/target/arm/translate.c
370
+++ b/target/arm/translate.c
371
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
372
if (!dc_isar_feature(aa32_aes, s) || ((rm | rd) & 1)) {
373
return 1;
374
}
375
- ptr1 = vfp_reg_ptr(true, rd);
376
- ptr2 = vfp_reg_ptr(true, rm);
377
-
378
- /* Bit 6 is the lowest opcode bit; it distinguishes between
379
- * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
380
- */
381
- tmp3 = tcg_const_i32(extract32(insn, 6, 1));
382
-
383
+ /*
384
+ * Bit 6 is the lowest opcode bit; it distinguishes
385
+ * between encryption (AESE/AESMC) and decryption
386
+ * (AESD/AESIMC).
387
+ */
388
if (op == NEON_2RM_AESE) {
389
- gen_helper_crypto_aese(ptr1, ptr2, tmp3);
390
+ tcg_gen_gvec_3_ool(vfp_reg_offset(true, rd),
391
+ vfp_reg_offset(true, rd),
392
+ vfp_reg_offset(true, rm),
393
+ 16, 16, extract32(insn, 6, 1),
394
+ gen_helper_crypto_aese);
395
} else {
396
- gen_helper_crypto_aesmc(ptr1, ptr2, tmp3);
397
+ tcg_gen_gvec_2_ool(vfp_reg_offset(true, rd),
398
+ vfp_reg_offset(true, rm),
399
+ 16, 16, extract32(insn, 6, 1),
400
+ gen_helper_crypto_aesmc);
401
}
402
- tcg_temp_free_ptr(ptr1);
403
- tcg_temp_free_ptr(ptr2);
404
- tcg_temp_free_i32(tmp3);
405
break;
406
case NEON_2RM_SHA1H:
407
if (!dc_isar_feature(aa32_sha1, s) || ((rm | rd) & 1)) {
408
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
152
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
409
index XXXXXXX..XXXXXXX 100644
153
index XXXXXXX..XXXXXXX 100644
410
--- a/target/arm/vec_helper.c
154
--- a/target/arm/vec_helper.c
411
+++ b/target/arm/vec_helper.c
155
+++ b/target/arm/vec_helper.c
412
@@ -XXX,XX +XXX,XX @@
156
@@ -XXX,XX +XXX,XX @@ static uint64_t expand_byte_to_half(uint64_t x)
413
#include "exec/helper-proto.h"
157
| ((x & 0xff000000) << 24);
414
#include "tcg/tcg-gvec-desc.h"
158
}
415
#include "fpu/softfloat.h"
159
416
-
160
-static uint64_t pmull_h(uint64_t op1, uint64_t op2)
417
+#include "vec_internal.h"
161
+uint64_t pmull_w(uint64_t op1, uint64_t op2)
418
162
{
419
/* Note that vector data is stored in host-endian 64-bit chunks,
163
uint64_t result = 0;
420
so addressing units smaller than that needs a host-endian fixup. */
164
int i;
421
@@ -XXX,XX +XXX,XX @@
165
+ for (i = 0; i < 16; ++i) {
422
#define H4(x) (x)
166
+ uint64_t mask = (op1 & 0x0000000100000001ull) * 0xffffffff;
423
#endif
167
+ result ^= op2 & mask;
424
168
+ op1 >>= 1;
425
-static void clear_tail(void *vd, uintptr_t opr_sz, uintptr_t max_sz)
169
+ op2 <<= 1;
426
-{
170
+ }
427
- uint64_t *d = vd + opr_sz;
171
+ return result;
428
- uintptr_t i;
172
+}
429
-
173
430
- for (i = opr_sz; i < max_sz; i += 8) {
174
+uint64_t pmull_h(uint64_t op1, uint64_t op2)
431
- *d++ = 0;
175
+{
432
- }
176
+ uint64_t result = 0;
433
-}
177
+ int i;
434
-
178
for (i = 0; i < 8; ++i) {
435
/* Signed saturating rounding doubling multiply-accumulate high half, 16-bit */
179
uint64_t mask = (op1 & 0x0001000100010001ull) * 0xffff;
436
static int16_t inl_qrdmlah_s16(int16_t src1, int16_t src2,
180
result ^= op2 & mask;
437
int16_t src3, uint32_t *sat)
438
--
181
--
439
2.20.1
182
2.20.1
440
183
441
184
diff view generated by jsdifflib
1
Convert the VCVT fixed-point conversion operations in the
1
Implement the MVE incrementing/decrementing dup insns VIDUP, VDDUP,
2
Neon 2-regs-and-shift group to decodetree.
2
VIWDUP and VDWDUP. These fill the elements of a vector with
3
successively incrementing values, starting at the offset specified in
4
a general purpose register. The final value of the offset is written
5
back to this register. The wrapping variants take a second general
6
purpose register which specifies the point where the count should
7
wrap back to 0.
3
8
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200522145520.6778-9-peter.maydell@linaro.org
7
---
11
---
8
target/arm/neon-dp.decode | 11 +++++
12
target/arm/helper-mve.h | 12 ++++
9
target/arm/translate-neon.inc.c | 49 +++++++++++++++++++++
13
target/arm/mve.decode | 25 ++++++++
10
target/arm/translate.c | 75 +--------------------------------
14
target/arm/mve_helper.c | 63 +++++++++++++++++++
11
3 files changed, 62 insertions(+), 73 deletions(-)
15
target/arm/translate-mve.c | 120 +++++++++++++++++++++++++++++++++++++
16
4 files changed, 220 insertions(+)
12
17
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
18
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
20
--- a/target/arm/helper-mve.h
16
+++ b/target/arm/neon-dp.decode
21
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vstrh_w, TCG_CALL_NO_WG, void, env, ptr, i32)
18
@2reg_shll_b .... ... . . . 001 shift:3 .... .... 0 . . . .... \
23
19
&2reg_shift vm=%vm_dp vd=%vd_dp size=0 q=0
24
DEF_HELPER_FLAGS_3(mve_vdup, TCG_CALL_NO_WG, void, env, ptr, i32)
20
25
21
+# We use size=0 for fp32 and size=1 for fp16 to match the 3-same encodings.
26
+DEF_HELPER_FLAGS_4(mve_vidupb, TCG_CALL_NO_WG, i32, env, ptr, i32, i32)
22
+@2reg_vcvt .... ... . . . 1 ..... .... .... . q:1 . . .... \
27
+DEF_HELPER_FLAGS_4(mve_viduph, TCG_CALL_NO_WG, i32, env, ptr, i32, i32)
23
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=0 shift=%neon_rshift_i5
28
+DEF_HELPER_FLAGS_4(mve_vidupw, TCG_CALL_NO_WG, i32, env, ptr, i32, i32)
24
+
29
+
25
VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_d
30
+DEF_HELPER_FLAGS_5(mve_viwdupb, TCG_CALL_NO_WG, i32, env, ptr, i32, i32, i32)
26
VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_s
31
+DEF_HELPER_FLAGS_5(mve_viwduph, TCG_CALL_NO_WG, i32, env, ptr, i32, i32, i32)
27
VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_h
32
+DEF_HELPER_FLAGS_5(mve_viwdupw, TCG_CALL_NO_WG, i32, env, ptr, i32, i32, i32)
28
@@ -XXX,XX +XXX,XX @@ VSHLL_S_2sh 1111 001 0 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_b
33
+
29
VSHLL_U_2sh 1111 001 1 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_s
34
+DEF_HELPER_FLAGS_5(mve_vdwdupb, TCG_CALL_NO_WG, i32, env, ptr, i32, i32, i32)
30
VSHLL_U_2sh 1111 001 1 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_h
35
+DEF_HELPER_FLAGS_5(mve_vdwduph, TCG_CALL_NO_WG, i32, env, ptr, i32, i32, i32)
31
VSHLL_U_2sh 1111 001 1 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_b
36
+DEF_HELPER_FLAGS_5(mve_vdwdupw, TCG_CALL_NO_WG, i32, env, ptr, i32, i32, i32)
32
+
37
+
33
+# VCVT fixed<->float conversions
38
DEF_HELPER_FLAGS_3(mve_vclsb, TCG_CALL_NO_WG, void, env, ptr, ptr)
34
+# TODO: FP16 fixed<->float conversions are opc==0b1100 and 0b1101
39
DEF_HELPER_FLAGS_3(mve_vclsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
35
+VCVT_SF_2sh 1111 001 0 1 . ...... .... 1110 0 . . 1 .... @2reg_vcvt
40
DEF_HELPER_FLAGS_3(mve_vclsw, TCG_CALL_NO_WG, void, env, ptr, ptr)
36
+VCVT_UF_2sh 1111 001 1 1 . ...... .... 1110 0 . . 1 .... @2reg_vcvt
41
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
37
+VCVT_FS_2sh 1111 001 0 1 . ...... .... 1111 0 . . 1 .... @2reg_vcvt
38
+VCVT_FU_2sh 1111 001 1 1 . ...... .... 1111 0 . . 1 .... @2reg_vcvt
39
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
40
index XXXXXXX..XXXXXXX 100644
42
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/translate-neon.inc.c
43
--- a/target/arm/mve.decode
42
+++ b/target/arm/translate-neon.inc.c
44
+++ b/target/arm/mve.decode
43
@@ -XXX,XX +XXX,XX @@ static bool trans_VSHLL_U_2sh(DisasContext *s, arg_2reg_shift *a)
45
@@ -XXX,XX +XXX,XX @@
44
};
46
&2scalar qd qn rm size
45
return do_vshll_2sh(s, a, widenfn[a->size], true);
47
&1imm qd imm cmode op
48
&2shift qd qm shift size
49
+&vidup qd rn size imm
50
+&viwdup qd rn rm size imm
51
52
@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
53
# Note that both Rn and Qd are 3 bits only (no D bit)
54
@@ -XXX,XX +XXX,XX @@ VDUP 1110 1110 1 1 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=0
55
VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 1 1 0000 @vdup size=1
56
VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=2
57
58
+# Incrementing and decrementing dup
59
+
60
+# VIDUP, VDDUP format immediate: 1 << (immh:imml)
61
+%imm_vidup 7:1 0:1 !function=vidup_imm
62
+
63
+# VIDUP, VDDUP registers: Rm bits [3:1] from insn, bit 0 is 1;
64
+# Rn bits [3:1] from insn, bit 0 is 0
65
+%vidup_rm 1:3 !function=times_2_plus_1
66
+%vidup_rn 17:3 !function=times_2
67
+
68
+@vidup .... .... . . size:2 .... .... .... .... .... \
69
+ qd=%qd imm=%imm_vidup rn=%vidup_rn &vidup
70
+@viwdup .... .... . . size:2 .... .... .... .... .... \
71
+ qd=%qd imm=%imm_vidup rm=%vidup_rm rn=%vidup_rn &viwdup
72
+{
73
+ VIDUP 1110 1110 0 . .. ... 1 ... 0 1111 . 110 111 . @vidup
74
+ VIWDUP 1110 1110 0 . .. ... 1 ... 0 1111 . 110 ... . @viwdup
75
+}
76
+{
77
+ VDDUP 1110 1110 0 . .. ... 1 ... 1 1111 . 110 111 . @vidup
78
+ VDWDUP 1110 1110 0 . .. ... 1 ... 1 1111 . 110 ... . @viwdup
79
+}
80
+
81
# multiply-add long dual accumulate
82
# rdahi: bits [3:1] from insn, bit 0 is 1
83
# rdalo: bits [3:1] from insn, bit 0 is 0
84
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
85
index XXXXXXX..XXXXXXX 100644
86
--- a/target/arm/mve_helper.c
87
+++ b/target/arm/mve_helper.c
88
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(mve_sqrshr)(CPUARMState *env, uint32_t n, uint32_t shift)
89
{
90
return do_sqrshl_bhs(n, -(int8_t)shift, 32, true, &env->QF);
46
}
91
}
47
+
92
+
48
+static bool do_fp_2sh(DisasContext *s, arg_2reg_shift *a,
93
+#define DO_VIDUP(OP, ESIZE, TYPE, FN) \
49
+ NeonGenTwoSingleOPFn *fn)
94
+ uint32_t HELPER(mve_##OP)(CPUARMState *env, void *vd, \
50
+{
95
+ uint32_t offset, uint32_t imm) \
51
+ /* FP operations in 2-reg-and-shift group */
96
+ { \
52
+ TCGv_i32 tmp, shiftv;
97
+ TYPE *d = vd; \
53
+ TCGv_ptr fpstatus;
98
+ uint16_t mask = mve_element_mask(env); \
54
+ int pass;
99
+ unsigned e; \
55
+
100
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
56
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
101
+ mergemask(&d[H##ESIZE(e)], offset, mask); \
102
+ offset = FN(offset, imm); \
103
+ } \
104
+ mve_advance_vpt(env); \
105
+ return offset; \
106
+ }
107
+
108
+#define DO_VIWDUP(OP, ESIZE, TYPE, FN) \
109
+ uint32_t HELPER(mve_##OP)(CPUARMState *env, void *vd, \
110
+ uint32_t offset, uint32_t wrap, \
111
+ uint32_t imm) \
112
+ { \
113
+ TYPE *d = vd; \
114
+ uint16_t mask = mve_element_mask(env); \
115
+ unsigned e; \
116
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
117
+ mergemask(&d[H##ESIZE(e)], offset, mask); \
118
+ offset = FN(offset, wrap, imm); \
119
+ } \
120
+ mve_advance_vpt(env); \
121
+ return offset; \
122
+ }
123
+
124
+#define DO_VIDUP_ALL(OP, FN) \
125
+ DO_VIDUP(OP##b, 1, int8_t, FN) \
126
+ DO_VIDUP(OP##h, 2, int16_t, FN) \
127
+ DO_VIDUP(OP##w, 4, int32_t, FN)
128
+
129
+#define DO_VIWDUP_ALL(OP, FN) \
130
+ DO_VIWDUP(OP##b, 1, int8_t, FN) \
131
+ DO_VIWDUP(OP##h, 2, int16_t, FN) \
132
+ DO_VIWDUP(OP##w, 4, int32_t, FN)
133
+
134
+static uint32_t do_add_wrap(uint32_t offset, uint32_t wrap, uint32_t imm)
135
+{
136
+ offset += imm;
137
+ if (offset == wrap) {
138
+ offset = 0;
139
+ }
140
+ return offset;
141
+}
142
+
143
+static uint32_t do_sub_wrap(uint32_t offset, uint32_t wrap, uint32_t imm)
144
+{
145
+ if (offset == 0) {
146
+ offset = wrap;
147
+ }
148
+ offset -= imm;
149
+ return offset;
150
+}
151
+
152
+DO_VIDUP_ALL(vidup, DO_ADD)
153
+DO_VIWDUP_ALL(viwdup, do_add_wrap)
154
+DO_VIWDUP_ALL(vdwdup, do_sub_wrap)
155
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
156
index XXXXXXX..XXXXXXX 100644
157
--- a/target/arm/translate-mve.c
158
+++ b/target/arm/translate-mve.c
159
@@ -XXX,XX +XXX,XX @@
160
#include "translate.h"
161
#include "translate-a32.h"
162
163
+static inline int vidup_imm(DisasContext *s, int x)
164
+{
165
+ return 1 << x;
166
+}
167
+
168
/* Include the generated decoder */
169
#include "decode-mve.c.inc"
170
171
@@ -XXX,XX +XXX,XX @@ typedef void MVEGenTwoOpShiftFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
172
typedef void MVEGenDualAccOpFn(TCGv_i64, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i64);
173
typedef void MVEGenVADDVFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32);
174
typedef void MVEGenOneOpImmFn(TCGv_ptr, TCGv_ptr, TCGv_i64);
175
+typedef void MVEGenVIDUPFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32, TCGv_i32);
176
+typedef void MVEGenVIWDUPFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32, TCGv_i32, TCGv_i32);
177
178
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
179
static inline long mve_qreg_offset(unsigned reg)
180
@@ -XXX,XX +XXX,XX @@ static bool trans_VSHLC(DisasContext *s, arg_VSHLC *a)
181
mve_update_eci(s);
182
return true;
183
}
184
+
185
+static bool do_vidup(DisasContext *s, arg_vidup *a, MVEGenVIDUPFn *fn)
186
+{
187
+ TCGv_ptr qd;
188
+ TCGv_i32 rn;
189
+
190
+ /*
191
+ * Vector increment/decrement with wrap and duplicate (VIDUP, VDDUP).
192
+ * This fills the vector with elements of successively increasing
193
+ * or decreasing values, starting from Rn.
194
+ */
195
+ if (!dc_isar_feature(aa32_mve, s) || !mve_check_qreg_bank(s, a->qd)) {
57
+ return false;
196
+ return false;
58
+ }
197
+ }
59
+
198
+ if (a->size == MO_64) {
60
+ /* UNDEF accesses to D16-D31 if they don't exist. */
199
+ /* size 0b11 is another encoding */
61
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
62
+ ((a->vd | a->vm) & 0x10)) {
63
+ return false;
200
+ return false;
64
+ }
201
+ }
65
+
202
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
66
+ if ((a->vm | a->vd) & a->q) {
203
+ return true;
204
+ }
205
+
206
+ qd = mve_qreg_ptr(a->qd);
207
+ rn = load_reg(s, a->rn);
208
+ fn(rn, cpu_env, qd, rn, tcg_constant_i32(a->imm));
209
+ store_reg(s, a->rn, rn);
210
+ tcg_temp_free_ptr(qd);
211
+ mve_update_eci(s);
212
+ return true;
213
+}
214
+
215
+static bool do_viwdup(DisasContext *s, arg_viwdup *a, MVEGenVIWDUPFn *fn)
216
+{
217
+ TCGv_ptr qd;
218
+ TCGv_i32 rn, rm;
219
+
220
+ /*
221
+ * Vector increment/decrement with wrap and duplicate (VIWDUp, VDWDUP)
222
+ * This fills the vector with elements of successively increasing
223
+ * or decreasing values, starting from Rn. Rm specifies a point where
224
+ * the count wraps back around to 0. The updated offset is written back
225
+ * to Rn.
226
+ */
227
+ if (!dc_isar_feature(aa32_mve, s) || !mve_check_qreg_bank(s, a->qd)) {
67
+ return false;
228
+ return false;
68
+ }
229
+ }
69
+
230
+ if (!fn || a->rm == 13 || a->rm == 15) {
70
+ if (!vfp_access_check(s)) {
231
+ /*
232
+ * size 0b11 is another encoding; Rm == 13 is UNPREDICTABLE;
233
+ * Rm == 13 is VIWDUP, VDWDUP.
234
+ */
235
+ return false;
236
+ }
237
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
71
+ return true;
238
+ return true;
72
+ }
239
+ }
73
+
240
+
74
+ fpstatus = get_fpstatus_ptr(1);
241
+ qd = mve_qreg_ptr(a->qd);
75
+ shiftv = tcg_const_i32(a->shift);
242
+ rn = load_reg(s, a->rn);
76
+ for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
243
+ rm = load_reg(s, a->rm);
77
+ tmp = neon_load_reg(a->vm, pass);
244
+ fn(rn, cpu_env, qd, rn, rm, tcg_constant_i32(a->imm));
78
+ fn(tmp, tmp, shiftv, fpstatus);
245
+ store_reg(s, a->rn, rn);
79
+ neon_store_reg(a->vd, pass, tmp);
246
+ tcg_temp_free_ptr(qd);
80
+ }
247
+ tcg_temp_free_i32(rm);
81
+ tcg_temp_free_ptr(fpstatus);
248
+ mve_update_eci(s);
82
+ tcg_temp_free_i32(shiftv);
83
+ return true;
249
+ return true;
84
+}
250
+}
85
+
251
+
86
+#define DO_FP_2SH(INSN, FUNC) \
252
+static bool trans_VIDUP(DisasContext *s, arg_vidup *a)
87
+ static bool trans_##INSN##_2sh(DisasContext *s, arg_2reg_shift *a) \
253
+{
88
+ { \
254
+ static MVEGenVIDUPFn * const fns[] = {
89
+ return do_fp_2sh(s, a, FUNC); \
255
+ gen_helper_mve_vidupb,
90
+ }
256
+ gen_helper_mve_viduph,
91
+
257
+ gen_helper_mve_vidupw,
92
+DO_FP_2SH(VCVT_SF, gen_helper_vfp_sltos)
258
+ NULL,
93
+DO_FP_2SH(VCVT_UF, gen_helper_vfp_ultos)
259
+ };
94
+DO_FP_2SH(VCVT_FS, gen_helper_vfp_tosls_round_to_zero)
260
+ return do_vidup(s, a, fns[a->size]);
95
+DO_FP_2SH(VCVT_FU, gen_helper_vfp_touls_round_to_zero)
261
+}
96
diff --git a/target/arm/translate.c b/target/arm/translate.c
262
+
97
index XXXXXXX..XXXXXXX 100644
263
+static bool trans_VDDUP(DisasContext *s, arg_vidup *a)
98
--- a/target/arm/translate.c
264
+{
99
+++ b/target/arm/translate.c
265
+ static MVEGenVIDUPFn * const fns[] = {
100
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
266
+ gen_helper_mve_vidupb,
101
int q;
267
+ gen_helper_mve_viduph,
102
int rd, rn, rm, rd_ofs, rn_ofs, rm_ofs;
268
+ gen_helper_mve_vidupw,
103
int size;
269
+ NULL,
104
- int shift;
270
+ };
105
int pass;
271
+ /* VDDUP is just like VIDUP but with a negative immediate */
106
int u;
272
+ a->imm = -a->imm;
107
int vec_size;
273
+ return do_vidup(s, a, fns[a->size]);
108
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
274
+}
109
return 1;
275
+
110
} else if (insn & (1 << 4)) {
276
+static bool trans_VIWDUP(DisasContext *s, arg_viwdup *a)
111
if ((insn & 0x00380080) != 0) {
277
+{
112
- /* Two registers and shift. */
278
+ static MVEGenVIWDUPFn * const fns[] = {
113
- op = (insn >> 8) & 0xf;
279
+ gen_helper_mve_viwdupb,
114
-
280
+ gen_helper_mve_viwduph,
115
- switch (op) {
281
+ gen_helper_mve_viwdupw,
116
- case 0: /* VSHR */
282
+ NULL,
117
- case 1: /* VSRA */
283
+ };
118
- case 2: /* VRSHR */
284
+ return do_viwdup(s, a, fns[a->size]);
119
- case 3: /* VRSRA */
285
+}
120
- case 4: /* VSRI */
286
+
121
- case 5: /* VSHL, VSLI */
287
+static bool trans_VDWDUP(DisasContext *s, arg_viwdup *a)
122
- case 6: /* VQSHLU */
288
+{
123
- case 7: /* VQSHL */
289
+ static MVEGenVIWDUPFn * const fns[] = {
124
- case 8: /* VSHRN, VRSHRN, VQSHRUN, VQRSHRUN */
290
+ gen_helper_mve_vdwdupb,
125
- case 9: /* VQSHRN, VQRSHRN */
291
+ gen_helper_mve_vdwduph,
126
- case 10: /* VSHLL, including VMOVL */
292
+ gen_helper_mve_vdwdupw,
127
- return 1; /* handled by decodetree */
293
+ NULL,
128
- default:
294
+ };
129
- break;
295
+ return do_viwdup(s, a, fns[a->size]);
130
- }
296
+}
131
-
132
- if (insn & (1 << 7)) {
133
- /* 64-bit shift. */
134
- if (op > 7) {
135
- return 1;
136
- }
137
- size = 3;
138
- } else {
139
- size = 2;
140
- while ((insn & (1 << (size + 19))) == 0)
141
- size--;
142
- }
143
- shift = (insn >> 16) & ((1 << (3 + size)) - 1);
144
- if (op >= 14) {
145
- /* VCVT fixed-point. */
146
- TCGv_ptr fpst;
147
- TCGv_i32 shiftv;
148
- VFPGenFixPointFn *fn;
149
-
150
- if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
151
- return 1;
152
- }
153
-
154
- if (!(op & 1)) {
155
- if (u) {
156
- fn = gen_helper_vfp_ultos;
157
- } else {
158
- fn = gen_helper_vfp_sltos;
159
- }
160
- } else {
161
- if (u) {
162
- fn = gen_helper_vfp_touls_round_to_zero;
163
- } else {
164
- fn = gen_helper_vfp_tosls_round_to_zero;
165
- }
166
- }
167
-
168
- /* We have already masked out the must-be-1 top bit of imm6,
169
- * hence this 32-shift where the ARM ARM has 64-imm6.
170
- */
171
- shift = 32 - shift;
172
- fpst = get_fpstatus_ptr(1);
173
- shiftv = tcg_const_i32(shift);
174
- for (pass = 0; pass < (q ? 4 : 2); pass++) {
175
- TCGv_i32 tmpf = neon_load_reg(rm, pass);
176
- fn(tmpf, tmpf, shiftv, fpst);
177
- neon_store_reg(rd, pass, tmpf);
178
- }
179
- tcg_temp_free_ptr(fpst);
180
- tcg_temp_free_i32(shiftv);
181
- } else {
182
- return 1;
183
- }
184
+ /* Two registers and shift: handled by decodetree */
185
+ return 1;
186
} else { /* (insn & 0x00380080) == 0 */
187
int invert, reg_ofs, vec_size;
188
189
--
297
--
190
2.20.1
298
2.20.1
191
299
192
300
diff view generated by jsdifflib
New patch
1
Factor out the "generate code to update VPR.MASK01/MASK23" part of
2
trans_VPST(); we are going to want to reuse it for the VPT insns.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
---
7
target/arm/translate-mve.c | 31 +++++++++++++++++--------------
8
1 file changed, 17 insertions(+), 14 deletions(-)
9
10
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
11
index XXXXXXX..XXXXXXX 100644
12
--- a/target/arm/translate-mve.c
13
+++ b/target/arm/translate-mve.c
14
@@ -XXX,XX +XXX,XX @@ static bool trans_VRMLSLDAVH(DisasContext *s, arg_vmlaldav *a)
15
return do_long_dual_acc(s, a, fns[a->x]);
16
}
17
18
-static bool trans_VPST(DisasContext *s, arg_VPST *a)
19
+static void gen_vpst(DisasContext *s, uint32_t mask)
20
{
21
- TCGv_i32 vpr;
22
-
23
- /* mask == 0 is a "related encoding" */
24
- if (!dc_isar_feature(aa32_mve, s) || !a->mask) {
25
- return false;
26
- }
27
- if (!mve_eci_check(s) || !vfp_access_check(s)) {
28
- return true;
29
- }
30
/*
31
* Set the VPR mask fields. We take advantage of MASK01 and MASK23
32
* being adjacent fields in the register.
33
*
34
- * This insn is not predicated, but it is subject to beat-wise
35
+ * Updating the masks is not predicated, but it is subject to beat-wise
36
* execution, and the mask is updated on the odd-numbered beats.
37
* So if PSR.ECI says we should skip beat 1, we mustn't update the
38
* 01 mask field.
39
*/
40
- vpr = load_cpu_field(v7m.vpr);
41
+ TCGv_i32 vpr = load_cpu_field(v7m.vpr);
42
switch (s->eci) {
43
case ECI_NONE:
44
case ECI_A0:
45
/* Update both 01 and 23 fields */
46
tcg_gen_deposit_i32(vpr, vpr,
47
- tcg_constant_i32(a->mask | (a->mask << 4)),
48
+ tcg_constant_i32(mask | (mask << 4)),
49
R_V7M_VPR_MASK01_SHIFT,
50
R_V7M_VPR_MASK01_LENGTH + R_V7M_VPR_MASK23_LENGTH);
51
break;
52
@@ -XXX,XX +XXX,XX @@ static bool trans_VPST(DisasContext *s, arg_VPST *a)
53
case ECI_A0A1A2B0:
54
/* Update only the 23 mask field */
55
tcg_gen_deposit_i32(vpr, vpr,
56
- tcg_constant_i32(a->mask),
57
+ tcg_constant_i32(mask),
58
R_V7M_VPR_MASK23_SHIFT, R_V7M_VPR_MASK23_LENGTH);
59
break;
60
default:
61
g_assert_not_reached();
62
}
63
store_cpu_field(vpr, v7m.vpr);
64
+}
65
+
66
+static bool trans_VPST(DisasContext *s, arg_VPST *a)
67
+{
68
+ /* mask == 0 is a "related encoding" */
69
+ if (!dc_isar_feature(aa32_mve, s) || !a->mask) {
70
+ return false;
71
+ }
72
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
73
+ return true;
74
+ }
75
+ gen_vpst(s, a->mask);
76
mve_update_and_store_eci(s);
77
return true;
78
}
79
--
80
2.20.1
81
82
diff view generated by jsdifflib
New patch
1
1
Implement the MVE integer vector comparison instructions. These are
2
"VCMP (vector)" encodings T1, T2 and T3, and "VPT (vector)" encodings
3
T1, T2 and T3.
4
5
These insns compare corresponding elements in each vector, and update
6
the VPR.P0 predicate bits with the results of the comparison. VPT
7
also sets the VPR.MASK01 and VPR.MASK23 fields -- it is effectively
8
"VCMP then VPST".
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
---
13
target/arm/helper-mve.h | 32 ++++++++++++++++++++++
14
target/arm/mve.decode | 18 +++++++++++-
15
target/arm/mve_helper.c | 56 ++++++++++++++++++++++++++++++++++++++
16
target/arm/translate-mve.c | 47 ++++++++++++++++++++++++++++++++
17
4 files changed, 152 insertions(+), 1 deletion(-)
18
19
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper-mve.h
22
+++ b/target/arm/helper-mve.h
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_uqshl, TCG_CALL_NO_RWG, i32, env, i32, i32)
24
DEF_HELPER_FLAGS_3(mve_sqshl, TCG_CALL_NO_RWG, i32, env, i32, i32)
25
DEF_HELPER_FLAGS_3(mve_uqrshl, TCG_CALL_NO_RWG, i32, env, i32, i32)
26
DEF_HELPER_FLAGS_3(mve_sqrshr, TCG_CALL_NO_RWG, i32, env, i32, i32)
27
+
28
+DEF_HELPER_FLAGS_3(mve_vcmpeqb, TCG_CALL_NO_WG, void, env, ptr, ptr)
29
+DEF_HELPER_FLAGS_3(mve_vcmpeqh, TCG_CALL_NO_WG, void, env, ptr, ptr)
30
+DEF_HELPER_FLAGS_3(mve_vcmpeqw, TCG_CALL_NO_WG, void, env, ptr, ptr)
31
+
32
+DEF_HELPER_FLAGS_3(mve_vcmpneb, TCG_CALL_NO_WG, void, env, ptr, ptr)
33
+DEF_HELPER_FLAGS_3(mve_vcmpneh, TCG_CALL_NO_WG, void, env, ptr, ptr)
34
+DEF_HELPER_FLAGS_3(mve_vcmpnew, TCG_CALL_NO_WG, void, env, ptr, ptr)
35
+
36
+DEF_HELPER_FLAGS_3(mve_vcmpcsb, TCG_CALL_NO_WG, void, env, ptr, ptr)
37
+DEF_HELPER_FLAGS_3(mve_vcmpcsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
38
+DEF_HELPER_FLAGS_3(mve_vcmpcsw, TCG_CALL_NO_WG, void, env, ptr, ptr)
39
+
40
+DEF_HELPER_FLAGS_3(mve_vcmphib, TCG_CALL_NO_WG, void, env, ptr, ptr)
41
+DEF_HELPER_FLAGS_3(mve_vcmphih, TCG_CALL_NO_WG, void, env, ptr, ptr)
42
+DEF_HELPER_FLAGS_3(mve_vcmphiw, TCG_CALL_NO_WG, void, env, ptr, ptr)
43
+
44
+DEF_HELPER_FLAGS_3(mve_vcmpgeb, TCG_CALL_NO_WG, void, env, ptr, ptr)
45
+DEF_HELPER_FLAGS_3(mve_vcmpgeh, TCG_CALL_NO_WG, void, env, ptr, ptr)
46
+DEF_HELPER_FLAGS_3(mve_vcmpgew, TCG_CALL_NO_WG, void, env, ptr, ptr)
47
+
48
+DEF_HELPER_FLAGS_3(mve_vcmpltb, TCG_CALL_NO_WG, void, env, ptr, ptr)
49
+DEF_HELPER_FLAGS_3(mve_vcmplth, TCG_CALL_NO_WG, void, env, ptr, ptr)
50
+DEF_HELPER_FLAGS_3(mve_vcmpltw, TCG_CALL_NO_WG, void, env, ptr, ptr)
51
+
52
+DEF_HELPER_FLAGS_3(mve_vcmpgtb, TCG_CALL_NO_WG, void, env, ptr, ptr)
53
+DEF_HELPER_FLAGS_3(mve_vcmpgth, TCG_CALL_NO_WG, void, env, ptr, ptr)
54
+DEF_HELPER_FLAGS_3(mve_vcmpgtw, TCG_CALL_NO_WG, void, env, ptr, ptr)
55
+
56
+DEF_HELPER_FLAGS_3(mve_vcmpleb, TCG_CALL_NO_WG, void, env, ptr, ptr)
57
+DEF_HELPER_FLAGS_3(mve_vcmpleh, TCG_CALL_NO_WG, void, env, ptr, ptr)
58
+DEF_HELPER_FLAGS_3(mve_vcmplew, TCG_CALL_NO_WG, void, env, ptr, ptr)
59
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
60
index XXXXXXX..XXXXXXX 100644
61
--- a/target/arm/mve.decode
62
+++ b/target/arm/mve.decode
63
@@ -XXX,XX +XXX,XX @@
64
&2shift qd qm shift size
65
&vidup qd rn size imm
66
&viwdup qd rn rm size imm
67
+&vcmp qm qn size mask
68
69
@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
70
# Note that both Rn and Qd are 3 bits only (no D bit)
71
@@ -XXX,XX +XXX,XX @@
72
@2_shr_w .... .... .. 1 ..... .... .... .... .... &2shift qd=%qd qm=%qm \
73
size=2 shift=%rshift_i5
74
75
+# Vector comparison; 4-bit Qm but 3-bit Qn
76
+%mask_22_13 22:1 13:3
77
+@vcmp .... .... .. size:2 qn:3 . .... .... .... .... &vcmp qm=%qm mask=%mask_22_13
78
+
79
# Vector loads and stores
80
81
# Widening loads and narrowing stores:
82
@@ -XXX,XX +XXX,XX @@ VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
83
}
84
85
# Predicate operations
86
-%mask_22_13 22:1 13:3
87
VPST 1111 1110 0 . 11 000 1 ... 0 1111 0100 1101 mask=%mask_22_13
88
89
# Logical immediate operations (1 reg and modified-immediate)
90
@@ -XXX,XX +XXX,XX @@ VQRSHRUNT 111 1 1110 1 . ... ... ... 1 1111 1 1 . 0 ... 0 @2_shr_b
91
VQRSHRUNT 111 1 1110 1 . ... ... ... 1 1111 1 1 . 0 ... 0 @2_shr_h
92
93
VSHLC 111 0 1110 1 . 1 imm:5 ... 0 1111 1100 rdm:4 qd=%qd
94
+
95
+# Comparisons. We expand out the conditions which are split across
96
+# encodings T1, T2, T3 and the fc bits. These include VPT, which is
97
+# effectively "VCMP then VPST". A plain "VCMP" has a mask field of zero.
98
+VCMPEQ 1111 1110 0 . .. ... 1 ... 0 1111 0 0 . 0 ... 0 @vcmp
99
+VCMPNE 1111 1110 0 . .. ... 1 ... 0 1111 1 0 . 0 ... 0 @vcmp
100
+VCMPCS 1111 1110 0 . .. ... 1 ... 0 1111 0 0 . 0 ... 1 @vcmp
101
+VCMPHI 1111 1110 0 . .. ... 1 ... 0 1111 1 0 . 0 ... 1 @vcmp
102
+VCMPGE 1111 1110 0 . .. ... 1 ... 1 1111 0 0 . 0 ... 0 @vcmp
103
+VCMPLT 1111 1110 0 . .. ... 1 ... 1 1111 1 0 . 0 ... 0 @vcmp
104
+VCMPGT 1111 1110 0 . .. ... 1 ... 1 1111 0 0 . 0 ... 1 @vcmp
105
+VCMPLE 1111 1110 0 . .. ... 1 ... 1 1111 1 0 . 0 ... 1 @vcmp
106
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
107
index XXXXXXX..XXXXXXX 100644
108
--- a/target/arm/mve_helper.c
109
+++ b/target/arm/mve_helper.c
110
@@ -XXX,XX +XXX,XX @@ static uint32_t do_sub_wrap(uint32_t offset, uint32_t wrap, uint32_t imm)
111
DO_VIDUP_ALL(vidup, DO_ADD)
112
DO_VIWDUP_ALL(viwdup, do_add_wrap)
113
DO_VIWDUP_ALL(vdwdup, do_sub_wrap)
114
+
115
+/*
116
+ * Vector comparison.
117
+ * P0 bits for non-executed beats (where eci_mask is 0) are unchanged.
118
+ * P0 bits for predicated lanes in executed beats (where mask is 0) are 0.
119
+ * P0 bits otherwise are updated with the results of the comparisons.
120
+ * We must also keep unchanged the MASK fields at the top of v7m.vpr.
121
+ */
122
+#define DO_VCMP(OP, ESIZE, TYPE, FN) \
123
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vn, void *vm) \
124
+ { \
125
+ TYPE *n = vn, *m = vm; \
126
+ uint16_t mask = mve_element_mask(env); \
127
+ uint16_t eci_mask = mve_eci_mask(env); \
128
+ uint16_t beatpred = 0; \
129
+ uint16_t emask = MAKE_64BIT_MASK(0, ESIZE); \
130
+ unsigned e; \
131
+ for (e = 0; e < 16 / ESIZE; e++) { \
132
+ bool r = FN(n[H##ESIZE(e)], m[H##ESIZE(e)]); \
133
+ /* Comparison sets 0/1 bits for each byte in the element */ \
134
+ beatpred |= r * emask; \
135
+ emask <<= ESIZE; \
136
+ } \
137
+ beatpred &= mask; \
138
+ env->v7m.vpr = (env->v7m.vpr & ~(uint32_t)eci_mask) | \
139
+ (beatpred & eci_mask); \
140
+ mve_advance_vpt(env); \
141
+ }
142
+
143
+#define DO_VCMP_S(OP, FN) \
144
+ DO_VCMP(OP##b, 1, int8_t, FN) \
145
+ DO_VCMP(OP##h, 2, int16_t, FN) \
146
+ DO_VCMP(OP##w, 4, int32_t, FN)
147
+
148
+#define DO_VCMP_U(OP, FN) \
149
+ DO_VCMP(OP##b, 1, uint8_t, FN) \
150
+ DO_VCMP(OP##h, 2, uint16_t, FN) \
151
+ DO_VCMP(OP##w, 4, uint32_t, FN)
152
+
153
+#define DO_EQ(N, M) ((N) == (M))
154
+#define DO_NE(N, M) ((N) != (M))
155
+#define DO_EQ(N, M) ((N) == (M))
156
+#define DO_EQ(N, M) ((N) == (M))
157
+#define DO_GE(N, M) ((N) >= (M))
158
+#define DO_LT(N, M) ((N) < (M))
159
+#define DO_GT(N, M) ((N) > (M))
160
+#define DO_LE(N, M) ((N) <= (M))
161
+
162
+DO_VCMP_U(vcmpeq, DO_EQ)
163
+DO_VCMP_U(vcmpne, DO_NE)
164
+DO_VCMP_U(vcmpcs, DO_GE)
165
+DO_VCMP_U(vcmphi, DO_GT)
166
+DO_VCMP_S(vcmpge, DO_GE)
167
+DO_VCMP_S(vcmplt, DO_LT)
168
+DO_VCMP_S(vcmpgt, DO_GT)
169
+DO_VCMP_S(vcmple, DO_LE)
170
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
171
index XXXXXXX..XXXXXXX 100644
172
--- a/target/arm/translate-mve.c
173
+++ b/target/arm/translate-mve.c
174
@@ -XXX,XX +XXX,XX @@ typedef void MVEGenVADDVFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32);
175
typedef void MVEGenOneOpImmFn(TCGv_ptr, TCGv_ptr, TCGv_i64);
176
typedef void MVEGenVIDUPFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32, TCGv_i32);
177
typedef void MVEGenVIWDUPFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32, TCGv_i32, TCGv_i32);
178
+typedef void MVEGenCmpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
179
180
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
181
static inline long mve_qreg_offset(unsigned reg)
182
@@ -XXX,XX +XXX,XX @@ static bool trans_VDWDUP(DisasContext *s, arg_viwdup *a)
183
};
184
return do_viwdup(s, a, fns[a->size]);
185
}
186
+
187
+static bool do_vcmp(DisasContext *s, arg_vcmp *a, MVEGenCmpFn *fn)
188
+{
189
+ TCGv_ptr qn, qm;
190
+
191
+ if (!dc_isar_feature(aa32_mve, s) || !mve_check_qreg_bank(s, a->qm) ||
192
+ !fn) {
193
+ return false;
194
+ }
195
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
196
+ return true;
197
+ }
198
+
199
+ qn = mve_qreg_ptr(a->qn);
200
+ qm = mve_qreg_ptr(a->qm);
201
+ fn(cpu_env, qn, qm);
202
+ tcg_temp_free_ptr(qn);
203
+ tcg_temp_free_ptr(qm);
204
+ if (a->mask) {
205
+ /* VPT */
206
+ gen_vpst(s, a->mask);
207
+ }
208
+ mve_update_eci(s);
209
+ return true;
210
+}
211
+
212
+#define DO_VCMP(INSN, FN) \
213
+ static bool trans_##INSN(DisasContext *s, arg_vcmp *a) \
214
+ { \
215
+ static MVEGenCmpFn * const fns[] = { \
216
+ gen_helper_mve_##FN##b, \
217
+ gen_helper_mve_##FN##h, \
218
+ gen_helper_mve_##FN##w, \
219
+ NULL, \
220
+ }; \
221
+ return do_vcmp(s, a, fns[a->size]); \
222
+ }
223
+
224
+DO_VCMP(VCMPEQ, vcmpeq)
225
+DO_VCMP(VCMPNE, vcmpne)
226
+DO_VCMP(VCMPCS, vcmpcs)
227
+DO_VCMP(VCMPHI, vcmphi)
228
+DO_VCMP(VCMPGE, vcmpge)
229
+DO_VCMP(VCMPLT, vcmplt)
230
+DO_VCMP(VCMPGT, vcmpgt)
231
+DO_VCMP(VCMPLE, vcmple)
232
--
233
2.20.1
234
235
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Implement the MVE integer vector comparison instructions that compare
2
2
each element against a scalar from a general purpose register. These
3
Do not yet convert the helpers to loop over opr_sz, but the
3
are "VCMP (vector)" encodings T4, T5 and T6 and "VPT (vector)"
4
descriptor allows the vector tail to be cleared. Which fixes
4
encodings T4, T5 and T6.
5
an existing bug vs SVE.
5
6
6
We have to move the decodetree pattern for VPST, because it
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
overlaps with VCMP T4 with size = 0b11.
8
Message-id: 20200514212831.31248-5-richard.henderson@linaro.org
8
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
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
---
11
---
12
target/arm/helper.h | 12 ++--
12
target/arm/helper-mve.h | 32 +++++++++++++++++++++++++++
13
target/arm/neon-dp.decode | 12 ++--
13
target/arm/mve.decode | 18 +++++++++++++---
14
target/arm/crypto_helper.c | 24 +++++--
14
target/arm/mve_helper.c | 44 +++++++++++++++++++++++++++++++-------
15
target/arm/translate-a64.c | 34 ++++-----
15
target/arm/translate-mve.c | 43 +++++++++++++++++++++++++++++++++++++
16
target/arm/translate-neon.inc.c | 124 +++++---------------------------
16
4 files changed, 126 insertions(+), 11 deletions(-)
17
target/arm/translate.c | 24 ++-----
17
18
6 files changed, 67 insertions(+), 163 deletions(-)
18
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
19
19
index XXXXXXX..XXXXXXX 100644
20
diff --git a/target/arm/helper.h b/target/arm/helper.h
20
--- a/target/arm/helper-mve.h
21
index XXXXXXX..XXXXXXX 100644
21
+++ b/target/arm/helper-mve.h
22
--- a/target/arm/helper.h
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vcmpgtw, TCG_CALL_NO_WG, void, env, ptr, ptr)
23
+++ b/target/arm/helper.h
23
DEF_HELPER_FLAGS_3(mve_vcmpleb, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(crypto_aese, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
DEF_HELPER_FLAGS_3(mve_vcmpleh, TCG_CALL_NO_WG, void, env, ptr, ptr)
25
DEF_HELPER_FLAGS_3(crypto_aesmc, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
25
DEF_HELPER_FLAGS_3(mve_vcmplew, TCG_CALL_NO_WG, void, env, ptr, ptr)
26
26
+
27
DEF_HELPER_FLAGS_4(crypto_sha1_3reg, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
27
+DEF_HELPER_FLAGS_3(mve_vcmpeq_scalarb, TCG_CALL_NO_WG, void, env, ptr, i32)
28
-DEF_HELPER_FLAGS_2(crypto_sha1h, TCG_CALL_NO_RWG, void, ptr, ptr)
28
+DEF_HELPER_FLAGS_3(mve_vcmpeq_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
29
-DEF_HELPER_FLAGS_2(crypto_sha1su1, TCG_CALL_NO_RWG, void, ptr, ptr)
29
+DEF_HELPER_FLAGS_3(mve_vcmpeq_scalarw, TCG_CALL_NO_WG, void, env, ptr, i32)
30
+DEF_HELPER_FLAGS_3(crypto_sha1h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
30
+
31
+DEF_HELPER_FLAGS_3(crypto_sha1su1, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
31
+DEF_HELPER_FLAGS_3(mve_vcmpne_scalarb, TCG_CALL_NO_WG, void, env, ptr, i32)
32
32
+DEF_HELPER_FLAGS_3(mve_vcmpne_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
33
-DEF_HELPER_FLAGS_3(crypto_sha256h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
33
+DEF_HELPER_FLAGS_3(mve_vcmpne_scalarw, TCG_CALL_NO_WG, void, env, ptr, i32)
34
-DEF_HELPER_FLAGS_3(crypto_sha256h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
34
+
35
-DEF_HELPER_FLAGS_2(crypto_sha256su0, TCG_CALL_NO_RWG, void, ptr, ptr)
35
+DEF_HELPER_FLAGS_3(mve_vcmpcs_scalarb, TCG_CALL_NO_WG, void, env, ptr, i32)
36
-DEF_HELPER_FLAGS_3(crypto_sha256su1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
36
+DEF_HELPER_FLAGS_3(mve_vcmpcs_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
37
+DEF_HELPER_FLAGS_4(crypto_sha256h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
37
+DEF_HELPER_FLAGS_3(mve_vcmpcs_scalarw, TCG_CALL_NO_WG, void, env, ptr, i32)
38
+DEF_HELPER_FLAGS_4(crypto_sha256h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
38
+
39
+DEF_HELPER_FLAGS_3(crypto_sha256su0, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
39
+DEF_HELPER_FLAGS_3(mve_vcmphi_scalarb, TCG_CALL_NO_WG, void, env, ptr, i32)
40
+DEF_HELPER_FLAGS_4(crypto_sha256su1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
40
+DEF_HELPER_FLAGS_3(mve_vcmphi_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
41
41
+DEF_HELPER_FLAGS_3(mve_vcmphi_scalarw, TCG_CALL_NO_WG, void, env, ptr, i32)
42
DEF_HELPER_FLAGS_4(crypto_sha512h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
42
+
43
DEF_HELPER_FLAGS_4(crypto_sha512h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
43
+DEF_HELPER_FLAGS_3(mve_vcmpge_scalarb, TCG_CALL_NO_WG, void, env, ptr, i32)
44
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
44
+DEF_HELPER_FLAGS_3(mve_vcmpge_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
45
index XXXXXXX..XXXXXXX 100644
45
+DEF_HELPER_FLAGS_3(mve_vcmpge_scalarw, TCG_CALL_NO_WG, void, env, ptr, i32)
46
--- a/target/arm/neon-dp.decode
46
+
47
+++ b/target/arm/neon-dp.decode
47
+DEF_HELPER_FLAGS_3(mve_vcmplt_scalarb, TCG_CALL_NO_WG, void, env, ptr, i32)
48
@@ -XXX,XX +XXX,XX @@ VPADD_3s 1111 001 0 0 . .. .... .... 1011 . . . 1 .... @3same_q0
48
+DEF_HELPER_FLAGS_3(mve_vcmplt_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
49
49
+DEF_HELPER_FLAGS_3(mve_vcmplt_scalarw, TCG_CALL_NO_WG, void, env, ptr, i32)
50
VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same
50
+
51
51
+DEF_HELPER_FLAGS_3(mve_vcmpgt_scalarb, TCG_CALL_NO_WG, void, env, ptr, i32)
52
+@3same_crypto .... .... .... .... .... .... .... .... \
52
+DEF_HELPER_FLAGS_3(mve_vcmpgt_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
53
+ &3same vm=%vm_dp vn=%vn_dp vd=%vd_dp size=0 q=1
53
+DEF_HELPER_FLAGS_3(mve_vcmpgt_scalarw, TCG_CALL_NO_WG, void, env, ptr, i32)
54
+
54
+
55
SHA1_3s 1111 001 0 0 . optype:2 .... .... 1100 . 1 . 0 .... \
55
+DEF_HELPER_FLAGS_3(mve_vcmple_scalarb, TCG_CALL_NO_WG, void, env, ptr, i32)
56
vm=%vm_dp vn=%vn_dp vd=%vd_dp
56
+DEF_HELPER_FLAGS_3(mve_vcmple_scalarh, TCG_CALL_NO_WG, void, env, ptr, i32)
57
-SHA256H_3s 1111 001 1 0 . 00 .... .... 1100 . 1 . 0 .... \
57
+DEF_HELPER_FLAGS_3(mve_vcmple_scalarw, TCG_CALL_NO_WG, void, env, ptr, i32)
58
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
58
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
59
-SHA256H2_3s 1111 001 1 0 . 01 .... .... 1100 . 1 . 0 .... \
59
index XXXXXXX..XXXXXXX 100644
60
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
60
--- a/target/arm/mve.decode
61
-SHA256SU1_3s 1111 001 1 0 . 10 .... .... 1100 . 1 . 0 .... \
61
+++ b/target/arm/mve.decode
62
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
62
@@ -XXX,XX +XXX,XX @@
63
+SHA256H_3s 1111 001 1 0 . 00 .... .... 1100 . 1 . 0 .... @3same_crypto
63
&vidup qd rn size imm
64
+SHA256H2_3s 1111 001 1 0 . 01 .... .... 1100 . 1 . 0 .... @3same_crypto
64
&viwdup qd rn rm size imm
65
+SHA256SU1_3s 1111 001 1 0 . 10 .... .... 1100 . 1 . 0 .... @3same_crypto
65
&vcmp qm qn size mask
66
66
+&vcmp_scalar qn rm size mask
67
VFMA_fp_3s 1111 001 0 0 . 0 . .... .... 1100 ... 1 .... @3same_fp
67
68
VFMS_fp_3s 1111 001 0 0 . 1 . .... .... 1100 ... 1 .... @3same_fp
68
@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
69
diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c
69
# Note that both Rn and Qd are 3 bits only (no D bit)
70
index XXXXXXX..XXXXXXX 100644
70
@@ -XXX,XX +XXX,XX @@
71
--- a/target/arm/crypto_helper.c
71
# Vector comparison; 4-bit Qm but 3-bit Qn
72
+++ b/target/arm/crypto_helper.c
72
%mask_22_13 22:1 13:3
73
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha1_3reg)(void *vd, void *vn, void *vm, uint32_t op)
73
@vcmp .... .... .. size:2 qn:3 . .... .... .... .... &vcmp qm=%qm mask=%mask_22_13
74
rd[1] = d.l[1];
74
+@vcmp_scalar .... .... .. size:2 qn:3 . .... .... .... rm:4 &vcmp_scalar \
75
+ mask=%mask_22_13
76
77
# Vector loads and stores
78
79
@@ -XXX,XX +XXX,XX @@ VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
80
rdahi=%rdahi rdalo=%rdalo
75
}
81
}
76
82
77
-void HELPER(crypto_sha1h)(void *vd, void *vm)
83
-# Predicate operations
78
+void HELPER(crypto_sha1h)(void *vd, void *vm, uint32_t desc)
84
-VPST 1111 1110 0 . 11 000 1 ... 0 1111 0100 1101 mask=%mask_22_13
79
{
85
-
80
uint64_t *rd = vd;
86
# Logical immediate operations (1 reg and modified-immediate)
81
uint64_t *rm = vm;
87
82
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha1h)(void *vd, void *vm)
88
# The cmode/op bits here decode VORR/VBIC/VMOV/VMVN, but
83
89
@@ -XXX,XX +XXX,XX @@ VCMPGE 1111 1110 0 . .. ... 1 ... 1 1111 0 0 . 0 ... 0 @vcmp
84
rd[0] = m.l[0];
90
VCMPLT 1111 1110 0 . .. ... 1 ... 1 1111 1 0 . 0 ... 0 @vcmp
85
rd[1] = m.l[1];
91
VCMPGT 1111 1110 0 . .. ... 1 ... 1 1111 0 0 . 0 ... 1 @vcmp
86
+
92
VCMPLE 1111 1110 0 . .. ... 1 ... 1 1111 1 0 . 0 ... 1 @vcmp
87
+ clear_tail_16(vd, desc);
93
+
88
}
94
+{
89
95
+ VPST 1111 1110 0 . 11 000 1 ... 0 1111 0100 1101 mask=%mask_22_13
90
-void HELPER(crypto_sha1su1)(void *vd, void *vm)
96
+ VCMPEQ_scalar 1111 1110 0 . .. ... 1 ... 0 1111 0 1 0 0 .... @vcmp_scalar
91
+void HELPER(crypto_sha1su1)(void *vd, void *vm, uint32_t desc)
97
+}
92
{
98
+VCMPNE_scalar 1111 1110 0 . .. ... 1 ... 0 1111 1 1 0 0 .... @vcmp_scalar
93
uint64_t *rd = vd;
99
+VCMPCS_scalar 1111 1110 0 . .. ... 1 ... 0 1111 0 1 1 0 .... @vcmp_scalar
94
uint64_t *rm = vm;
100
+VCMPHI_scalar 1111 1110 0 . .. ... 1 ... 0 1111 1 1 1 0 .... @vcmp_scalar
95
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha1su1)(void *vd, void *vm)
101
+VCMPGE_scalar 1111 1110 0 . .. ... 1 ... 1 1111 0 1 0 0 .... @vcmp_scalar
96
102
+VCMPLT_scalar 1111 1110 0 . .. ... 1 ... 1 1111 1 1 0 0 .... @vcmp_scalar
97
rd[0] = d.l[0];
103
+VCMPGT_scalar 1111 1110 0 . .. ... 1 ... 1 1111 0 1 1 0 .... @vcmp_scalar
98
rd[1] = d.l[1];
104
+VCMPLE_scalar 1111 1110 0 . .. ... 1 ... 1 1111 1 1 1 0 .... @vcmp_scalar
99
+
105
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
100
+ clear_tail_16(vd, desc);
106
index XXXXXXX..XXXXXXX 100644
101
}
107
--- a/target/arm/mve_helper.c
102
108
+++ b/target/arm/mve_helper.c
103
/*
109
@@ -XXX,XX +XXX,XX @@ DO_VIWDUP_ALL(vdwdup, do_sub_wrap)
104
@@ -XXX,XX +XXX,XX @@ static uint32_t s1(uint32_t x)
110
mve_advance_vpt(env); \
105
return ror32(x, 17) ^ ror32(x, 19) ^ (x >> 10);
106
}
107
108
-void HELPER(crypto_sha256h)(void *vd, void *vn, void *vm)
109
+void HELPER(crypto_sha256h)(void *vd, void *vn, void *vm, uint32_t desc)
110
{
111
uint64_t *rd = vd;
112
uint64_t *rn = vn;
113
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha256h)(void *vd, void *vn, void *vm)
114
115
rd[0] = d.l[0];
116
rd[1] = d.l[1];
117
+
118
+ clear_tail_16(vd, desc);
119
}
120
121
-void HELPER(crypto_sha256h2)(void *vd, void *vn, void *vm)
122
+void HELPER(crypto_sha256h2)(void *vd, void *vn, void *vm, uint32_t desc)
123
{
124
uint64_t *rd = vd;
125
uint64_t *rn = vn;
126
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha256h2)(void *vd, void *vn, void *vm)
127
128
rd[0] = d.l[0];
129
rd[1] = d.l[1];
130
+
131
+ clear_tail_16(vd, desc);
132
}
133
134
-void HELPER(crypto_sha256su0)(void *vd, void *vm)
135
+void HELPER(crypto_sha256su0)(void *vd, void *vm, uint32_t desc)
136
{
137
uint64_t *rd = vd;
138
uint64_t *rm = vm;
139
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha256su0)(void *vd, void *vm)
140
141
rd[0] = d.l[0];
142
rd[1] = d.l[1];
143
+
144
+ clear_tail_16(vd, desc);
145
}
146
147
-void HELPER(crypto_sha256su1)(void *vd, void *vn, void *vm)
148
+void HELPER(crypto_sha256su1)(void *vd, void *vn, void *vm, uint32_t desc)
149
{
150
uint64_t *rd = vd;
151
uint64_t *rn = vn;
152
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha256su1)(void *vd, void *vn, void *vm)
153
154
rd[0] = d.l[0];
155
rd[1] = d.l[1];
156
+
157
+ clear_tail_16(vd, desc);
158
}
159
160
/*
161
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
162
index XXXXXXX..XXXXXXX 100644
163
--- a/target/arm/translate-a64.c
164
+++ b/target/arm/translate-a64.c
165
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
166
int rm = extract32(insn, 16, 5);
167
int rn = extract32(insn, 5, 5);
168
int rd = extract32(insn, 0, 5);
169
- CryptoThreeOpFn *genfn;
170
- TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
171
+ gen_helper_gvec_3 *genfn;
172
bool feature;
173
174
if (size != 0) {
175
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
176
return;
177
}
111
}
178
112
179
- tcg_rd_ptr = vec_full_reg_ptr(s, rd);
113
-#define DO_VCMP_S(OP, FN) \
180
- tcg_rn_ptr = vec_full_reg_ptr(s, rn);
114
- DO_VCMP(OP##b, 1, int8_t, FN) \
181
- tcg_rm_ptr = vec_full_reg_ptr(s, rm);
115
- DO_VCMP(OP##h, 2, int16_t, FN) \
182
-
116
- DO_VCMP(OP##w, 4, int32_t, FN)
183
if (genfn) {
117
+#define DO_VCMP_SCALAR(OP, ESIZE, TYPE, FN) \
184
- genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr);
118
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vn, \
185
+ gen_gvec_op3_ool(s, true, rd, rn, rm, 0, genfn);
119
+ uint32_t rm) \
186
} else {
120
+ { \
187
TCGv_i32 tcg_opcode = tcg_const_i32(opcode);
121
+ TYPE *n = vn; \
188
+ TCGv_ptr tcg_rd_ptr = vec_full_reg_ptr(s, rd);
122
+ uint16_t mask = mve_element_mask(env); \
189
+ TCGv_ptr tcg_rn_ptr = vec_full_reg_ptr(s, rn);
123
+ uint16_t eci_mask = mve_eci_mask(env); \
190
+ TCGv_ptr tcg_rm_ptr = vec_full_reg_ptr(s, rm);
124
+ uint16_t beatpred = 0; \
191
125
+ uint16_t emask = MAKE_64BIT_MASK(0, ESIZE); \
192
gen_helper_crypto_sha1_3reg(tcg_rd_ptr, tcg_rn_ptr,
126
+ unsigned e; \
193
tcg_rm_ptr, tcg_opcode);
127
+ for (e = 0; e < 16 / ESIZE; e++) { \
194
- tcg_temp_free_i32(tcg_opcode);
128
+ bool r = FN(n[H##ESIZE(e)], (TYPE)rm); \
195
- }
129
+ /* Comparison sets 0/1 bits for each byte in the element */ \
196
130
+ beatpred |= r * emask; \
197
- tcg_temp_free_ptr(tcg_rd_ptr);
131
+ emask <<= ESIZE; \
198
- tcg_temp_free_ptr(tcg_rn_ptr);
132
+ } \
199
- tcg_temp_free_ptr(tcg_rm_ptr);
133
+ beatpred &= mask; \
200
+ tcg_temp_free_i32(tcg_opcode);
134
+ env->v7m.vpr = (env->v7m.vpr & ~(uint32_t)eci_mask) | \
201
+ tcg_temp_free_ptr(tcg_rd_ptr);
135
+ (beatpred & eci_mask); \
202
+ tcg_temp_free_ptr(tcg_rn_ptr);
136
+ mve_advance_vpt(env); \
203
+ tcg_temp_free_ptr(tcg_rm_ptr);
137
+ }
204
+ }
138
205
}
139
-#define DO_VCMP_U(OP, FN) \
206
140
- DO_VCMP(OP##b, 1, uint8_t, FN) \
207
/* Crypto two-reg SHA
141
- DO_VCMP(OP##h, 2, uint16_t, FN) \
208
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
142
- DO_VCMP(OP##w, 4, uint32_t, FN)
209
int opcode = extract32(insn, 12, 5);
143
+#define DO_VCMP_S(OP, FN) \
210
int rn = extract32(insn, 5, 5);
144
+ DO_VCMP(OP##b, 1, int8_t, FN) \
211
int rd = extract32(insn, 0, 5);
145
+ DO_VCMP(OP##h, 2, int16_t, FN) \
212
- CryptoTwoOpFn *genfn;
146
+ DO_VCMP(OP##w, 4, int32_t, FN) \
213
+ gen_helper_gvec_2 *genfn;
147
+ DO_VCMP_SCALAR(OP##_scalarb, 1, int8_t, FN) \
214
bool feature;
148
+ DO_VCMP_SCALAR(OP##_scalarh, 2, int16_t, FN) \
215
- TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
149
+ DO_VCMP_SCALAR(OP##_scalarw, 4, int32_t, FN)
216
150
+
217
if (size != 0) {
151
+#define DO_VCMP_U(OP, FN) \
218
unallocated_encoding(s);
152
+ DO_VCMP(OP##b, 1, uint8_t, FN) \
219
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
153
+ DO_VCMP(OP##h, 2, uint16_t, FN) \
220
if (!fp_access_check(s)) {
154
+ DO_VCMP(OP##w, 4, uint32_t, FN) \
221
return;
155
+ DO_VCMP_SCALAR(OP##_scalarb, 1, uint8_t, FN) \
222
}
156
+ DO_VCMP_SCALAR(OP##_scalarh, 2, uint16_t, FN) \
223
-
157
+ DO_VCMP_SCALAR(OP##_scalarw, 4, uint32_t, FN)
224
- tcg_rd_ptr = vec_full_reg_ptr(s, rd);
158
225
- tcg_rn_ptr = vec_full_reg_ptr(s, rn);
159
#define DO_EQ(N, M) ((N) == (M))
226
-
160
#define DO_NE(N, M) ((N) != (M))
227
- genfn(tcg_rd_ptr, tcg_rn_ptr);
161
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
228
-
162
index XXXXXXX..XXXXXXX 100644
229
- tcg_temp_free_ptr(tcg_rd_ptr);
163
--- a/target/arm/translate-mve.c
230
- tcg_temp_free_ptr(tcg_rn_ptr);
164
+++ b/target/arm/translate-mve.c
231
+ gen_gvec_op2_ool(s, true, rd, rn, 0, genfn);
165
@@ -XXX,XX +XXX,XX @@ typedef void MVEGenOneOpImmFn(TCGv_ptr, TCGv_ptr, TCGv_i64);
232
}
166
typedef void MVEGenVIDUPFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32, TCGv_i32);
233
167
typedef void MVEGenVIWDUPFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32, TCGv_i32, TCGv_i32);
234
static void gen_rax1_i64(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m)
168
typedef void MVEGenCmpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
235
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
169
+typedef void MVEGenScalarCmpFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
236
index XXXXXXX..XXXXXXX 100644
170
237
--- a/target/arm/translate-neon.inc.c
171
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
238
+++ b/target/arm/translate-neon.inc.c
172
static inline long mve_qreg_offset(unsigned reg)
239
@@ -XXX,XX +XXX,XX @@ DO_3SAME_CMP(VCGE_S, TCG_COND_GE)
173
@@ -XXX,XX +XXX,XX @@ static bool do_vcmp(DisasContext *s, arg_vcmp *a, MVEGenCmpFn *fn)
240
DO_3SAME_CMP(VCGE_U, TCG_COND_GEU)
241
DO_3SAME_CMP(VCEQ, TCG_COND_EQ)
242
243
-static void gen_VMUL_p_3s(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
244
- uint32_t rm_ofs, uint32_t oprsz, uint32_t maxsz)
245
-{
246
- tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz,
247
- 0, gen_helper_gvec_pmul_b);
248
-}
249
+#define WRAP_OOL_FN(WRAPNAME, FUNC) \
250
+ static void WRAPNAME(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs, \
251
+ uint32_t rm_ofs, uint32_t oprsz, uint32_t maxsz) \
252
+ { \
253
+ tcg_gen_gvec_3_ool(rd_ofs, rn_ofs, rm_ofs, oprsz, maxsz, 0, FUNC); \
254
+ }
255
+
256
+WRAP_OOL_FN(gen_VMUL_p_3s, gen_helper_gvec_pmul_b)
257
258
static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a)
259
{
260
@@ -XXX,XX +XXX,XX @@ static bool trans_SHA1_3s(DisasContext *s, arg_SHA1_3s *a)
261
return true;
174
return true;
262
}
175
}
263
176
264
-static bool trans_SHA256H_3s(DisasContext *s, arg_SHA256H_3s *a)
177
+static bool do_vcmp_scalar(DisasContext *s, arg_vcmp_scalar *a,
265
-{
178
+ MVEGenScalarCmpFn *fn)
266
- TCGv_ptr ptr1, ptr2, ptr3;
179
+{
267
-
180
+ TCGv_ptr qn;
268
- if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
181
+ TCGv_i32 rm;
269
- !dc_isar_feature(aa32_sha2, s)) {
182
+
270
- return false;
183
+ if (!dc_isar_feature(aa32_mve, s) || !fn || a->rm == 13) {
271
+#define DO_SHA2(NAME, FUNC) \
184
+ return false;
272
+ WRAP_OOL_FN(gen_##NAME##_3s, FUNC) \
185
+ }
273
+ static bool trans_##NAME##_3s(DisasContext *s, arg_3same *a) \
186
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
274
+ { \
187
+ return true;
275
+ if (!dc_isar_feature(aa32_sha2, s)) { \
188
+ }
276
+ return false; \
189
+
277
+ } \
190
+ qn = mve_qreg_ptr(a->qn);
278
+ return do_3same(s, a, gen_##NAME##_3s); \
191
+ if (a->rm == 15) {
192
+ /* Encoding Rm=0b1111 means "constant zero" */
193
+ rm = tcg_constant_i32(0);
194
+ } else {
195
+ rm = load_reg(s, a->rm);
196
+ }
197
+ fn(cpu_env, qn, rm);
198
+ tcg_temp_free_ptr(qn);
199
+ tcg_temp_free_i32(rm);
200
+ if (a->mask) {
201
+ /* VPT */
202
+ gen_vpst(s, a->mask);
203
+ }
204
+ mve_update_eci(s);
205
+ return true;
206
+}
207
+
208
#define DO_VCMP(INSN, FN) \
209
static bool trans_##INSN(DisasContext *s, arg_vcmp *a) \
210
{ \
211
@@ -XXX,XX +XXX,XX @@ static bool do_vcmp(DisasContext *s, arg_vcmp *a, MVEGenCmpFn *fn)
212
NULL, \
213
}; \
214
return do_vcmp(s, a, fns[a->size]); \
215
+ } \
216
+ static bool trans_##INSN##_scalar(DisasContext *s, \
217
+ arg_vcmp_scalar *a) \
218
+ { \
219
+ static MVEGenScalarCmpFn * const fns[] = { \
220
+ gen_helper_mve_##FN##_scalarb, \
221
+ gen_helper_mve_##FN##_scalarh, \
222
+ gen_helper_mve_##FN##_scalarw, \
223
+ NULL, \
224
+ }; \
225
+ return do_vcmp_scalar(s, a, fns[a->size]); \
279
}
226
}
280
227
281
- /* UNDEF accesses to D16-D31 if they don't exist. */
228
DO_VCMP(VCMPEQ, vcmpeq)
282
- if (!dc_isar_feature(aa32_simd_r32, s) &&
283
- ((a->vd | a->vn | a->vm) & 0x10)) {
284
- return false;
285
- }
286
-
287
- if ((a->vn | a->vm | a->vd) & 1) {
288
- return false;
289
- }
290
-
291
- if (!vfp_access_check(s)) {
292
- return true;
293
- }
294
-
295
- ptr1 = vfp_reg_ptr(true, a->vd);
296
- ptr2 = vfp_reg_ptr(true, a->vn);
297
- ptr3 = vfp_reg_ptr(true, a->vm);
298
- gen_helper_crypto_sha256h(ptr1, ptr2, ptr3);
299
- tcg_temp_free_ptr(ptr1);
300
- tcg_temp_free_ptr(ptr2);
301
- tcg_temp_free_ptr(ptr3);
302
-
303
- return true;
304
-}
305
-
306
-static bool trans_SHA256H2_3s(DisasContext *s, arg_SHA256H2_3s *a)
307
-{
308
- TCGv_ptr ptr1, ptr2, ptr3;
309
-
310
- if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
311
- !dc_isar_feature(aa32_sha2, s)) {
312
- return false;
313
- }
314
-
315
- /* UNDEF accesses to D16-D31 if they don't exist. */
316
- if (!dc_isar_feature(aa32_simd_r32, s) &&
317
- ((a->vd | a->vn | a->vm) & 0x10)) {
318
- return false;
319
- }
320
-
321
- if ((a->vn | a->vm | a->vd) & 1) {
322
- return false;
323
- }
324
-
325
- if (!vfp_access_check(s)) {
326
- return true;
327
- }
328
-
329
- ptr1 = vfp_reg_ptr(true, a->vd);
330
- ptr2 = vfp_reg_ptr(true, a->vn);
331
- ptr3 = vfp_reg_ptr(true, a->vm);
332
- gen_helper_crypto_sha256h2(ptr1, ptr2, ptr3);
333
- tcg_temp_free_ptr(ptr1);
334
- tcg_temp_free_ptr(ptr2);
335
- tcg_temp_free_ptr(ptr3);
336
-
337
- return true;
338
-}
339
-
340
-static bool trans_SHA256SU1_3s(DisasContext *s, arg_SHA256SU1_3s *a)
341
-{
342
- TCGv_ptr ptr1, ptr2, ptr3;
343
-
344
- if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
345
- !dc_isar_feature(aa32_sha2, s)) {
346
- return false;
347
- }
348
-
349
- /* UNDEF accesses to D16-D31 if they don't exist. */
350
- if (!dc_isar_feature(aa32_simd_r32, s) &&
351
- ((a->vd | a->vn | a->vm) & 0x10)) {
352
- return false;
353
- }
354
-
355
- if ((a->vn | a->vm | a->vd) & 1) {
356
- return false;
357
- }
358
-
359
- if (!vfp_access_check(s)) {
360
- return true;
361
- }
362
-
363
- ptr1 = vfp_reg_ptr(true, a->vd);
364
- ptr2 = vfp_reg_ptr(true, a->vn);
365
- ptr3 = vfp_reg_ptr(true, a->vm);
366
- gen_helper_crypto_sha256su1(ptr1, ptr2, ptr3);
367
- tcg_temp_free_ptr(ptr1);
368
- tcg_temp_free_ptr(ptr2);
369
- tcg_temp_free_ptr(ptr3);
370
-
371
- return true;
372
-}
373
+DO_SHA2(SHA256H, gen_helper_crypto_sha256h)
374
+DO_SHA2(SHA256H2, gen_helper_crypto_sha256h2)
375
+DO_SHA2(SHA256SU1, gen_helper_crypto_sha256su1)
376
377
#define DO_3SAME_64(INSN, FUNC) \
378
static void gen_##INSN##_3s(unsigned vece, uint32_t rd_ofs, \
379
diff --git a/target/arm/translate.c b/target/arm/translate.c
380
index XXXXXXX..XXXXXXX 100644
381
--- a/target/arm/translate.c
382
+++ b/target/arm/translate.c
383
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
384
int vec_size;
385
uint32_t imm;
386
TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
387
- TCGv_ptr ptr1, ptr2;
388
+ TCGv_ptr ptr1;
389
TCGv_i64 tmp64;
390
391
if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
392
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
393
if (!dc_isar_feature(aa32_sha1, s) || ((rm | rd) & 1)) {
394
return 1;
395
}
396
- ptr1 = vfp_reg_ptr(true, rd);
397
- ptr2 = vfp_reg_ptr(true, rm);
398
-
399
- gen_helper_crypto_sha1h(ptr1, ptr2);
400
-
401
- tcg_temp_free_ptr(ptr1);
402
- tcg_temp_free_ptr(ptr2);
403
+ tcg_gen_gvec_2_ool(rd_ofs, rm_ofs, 16, 16, 0,
404
+ gen_helper_crypto_sha1h);
405
break;
406
case NEON_2RM_SHA1SU1:
407
if ((rm | rd) & 1) {
408
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
409
} else if (!dc_isar_feature(aa32_sha1, s)) {
410
return 1;
411
}
412
- ptr1 = vfp_reg_ptr(true, rd);
413
- ptr2 = vfp_reg_ptr(true, rm);
414
- if (q) {
415
- gen_helper_crypto_sha256su0(ptr1, ptr2);
416
- } else {
417
- gen_helper_crypto_sha1su1(ptr1, ptr2);
418
- }
419
- tcg_temp_free_ptr(ptr1);
420
- tcg_temp_free_ptr(ptr2);
421
+ tcg_gen_gvec_2_ool(rd_ofs, rm_ofs, 16, 16, 0,
422
+ q ? gen_helper_crypto_sha256su0
423
+ : gen_helper_crypto_sha1su1);
424
break;
425
-
426
case NEON_2RM_VMVN:
427
tcg_gen_gvec_not(0, rd_ofs, rm_ofs, vec_size, vec_size);
428
break;
429
--
229
--
430
2.20.1
230
2.20.1
431
231
432
232
diff view generated by jsdifflib
New patch
1
Implement the MVE VPSEL insn, which sets each byte of the destination
2
vector Qd to the byte from either Qn or Qm depending on the value of
3
the corresponding bit in VPR.P0.
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
target/arm/helper-mve.h | 2 ++
9
target/arm/mve.decode | 7 +++++--
10
target/arm/mve_helper.c | 19 +++++++++++++++++++
11
target/arm/translate-mve.c | 2 ++
12
4 files changed, 28 insertions(+), 2 deletions(-)
13
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
15
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/helper-mve.h
17
+++ b/target/arm/helper-mve.h
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vorr, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
19
DEF_HELPER_FLAGS_4(mve_vorn, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
20
DEF_HELPER_FLAGS_4(mve_veor, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
21
22
+DEF_HELPER_FLAGS_4(mve_vpsel, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
+
24
DEF_HELPER_FLAGS_4(mve_vaddb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
DEF_HELPER_FLAGS_4(mve_vaddh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
26
DEF_HELPER_FLAGS_4(mve_vaddw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
27
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
28
index XXXXXXX..XXXXXXX 100644
29
--- a/target/arm/mve.decode
30
+++ b/target/arm/mve.decode
31
@@ -XXX,XX +XXX,XX @@ VSHLC 111 0 1110 1 . 1 imm:5 ... 0 1111 1100 rdm:4 qd=%qd
32
# effectively "VCMP then VPST". A plain "VCMP" has a mask field of zero.
33
VCMPEQ 1111 1110 0 . .. ... 1 ... 0 1111 0 0 . 0 ... 0 @vcmp
34
VCMPNE 1111 1110 0 . .. ... 1 ... 0 1111 1 0 . 0 ... 0 @vcmp
35
-VCMPCS 1111 1110 0 . .. ... 1 ... 0 1111 0 0 . 0 ... 1 @vcmp
36
-VCMPHI 1111 1110 0 . .. ... 1 ... 0 1111 1 0 . 0 ... 1 @vcmp
37
+{
38
+ VPSEL 1111 1110 0 . 11 ... 1 ... 0 1111 . 0 . 0 ... 1 @2op_nosz
39
+ VCMPCS 1111 1110 0 . .. ... 1 ... 0 1111 0 0 . 0 ... 1 @vcmp
40
+ VCMPHI 1111 1110 0 . .. ... 1 ... 0 1111 1 0 . 0 ... 1 @vcmp
41
+}
42
VCMPGE 1111 1110 0 . .. ... 1 ... 1 1111 0 0 . 0 ... 0 @vcmp
43
VCMPLT 1111 1110 0 . .. ... 1 ... 1 1111 1 0 . 0 ... 0 @vcmp
44
VCMPGT 1111 1110 0 . .. ... 1 ... 1 1111 0 0 . 0 ... 1 @vcmp
45
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/mve_helper.c
48
+++ b/target/arm/mve_helper.c
49
@@ -XXX,XX +XXX,XX @@ DO_VCMP_S(vcmpge, DO_GE)
50
DO_VCMP_S(vcmplt, DO_LT)
51
DO_VCMP_S(vcmpgt, DO_GT)
52
DO_VCMP_S(vcmple, DO_LE)
53
+
54
+void HELPER(mve_vpsel)(CPUARMState *env, void *vd, void *vn, void *vm)
55
+{
56
+ /*
57
+ * Qd[n] = VPR.P0[n] ? Qn[n] : Qm[n]
58
+ * but note that whether bytes are written to Qd is still subject
59
+ * to (all forms of) predication in the usual way.
60
+ */
61
+ uint64_t *d = vd, *n = vn, *m = vm;
62
+ uint16_t mask = mve_element_mask(env);
63
+ uint16_t p0 = FIELD_EX32(env->v7m.vpr, V7M_VPR, P0);
64
+ unsigned e;
65
+ for (e = 0; e < 16 / 8; e++, mask >>= 8, p0 >>= 8) {
66
+ uint64_t r = m[H8(e)];
67
+ mergemask(&r, n[H8(e)], p0);
68
+ mergemask(&d[H8(e)], r, mask);
69
+ }
70
+ mve_advance_vpt(env);
71
+}
72
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
73
index XXXXXXX..XXXXXXX 100644
74
--- a/target/arm/translate-mve.c
75
+++ b/target/arm/translate-mve.c
76
@@ -XXX,XX +XXX,XX @@ DO_LOGIC(VORR, gen_helper_mve_vorr)
77
DO_LOGIC(VORN, gen_helper_mve_vorn)
78
DO_LOGIC(VEOR, gen_helper_mve_veor)
79
80
+DO_LOGIC(VPSEL, gen_helper_mve_vpsel)
81
+
82
#define DO_2OP(INSN, FN) \
83
static bool trans_##INSN(DisasContext *s, arg_2op *a) \
84
{ \
85
--
86
2.20.1
87
88
diff view generated by jsdifflib
New patch
1
Implement the MVE VMLAS insn, which multiplies a vector by a vector
2
and adds a scalar.
1
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
---
7
target/arm/helper-mve.h | 4 ++++
8
target/arm/mve.decode | 3 +++
9
target/arm/mve_helper.c | 26 ++++++++++++++++++++++++++
10
target/arm/translate-mve.c | 1 +
11
4 files changed, 34 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_vqdmullb_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i3
18
DEF_HELPER_FLAGS_4(mve_vqdmullt_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
19
DEF_HELPER_FLAGS_4(mve_vqdmullt_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
20
21
+DEF_HELPER_FLAGS_4(mve_vmlasb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
22
+DEF_HELPER_FLAGS_4(mve_vmlash, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
23
+DEF_HELPER_FLAGS_4(mve_vmlasw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
+
25
DEF_HELPER_FLAGS_4(mve_vmlaldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
26
DEF_HELPER_FLAGS_4(mve_vmlaldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
27
DEF_HELPER_FLAGS_4(mve_vmlaldavxsh, 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 @@ VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
33
VQDMULH_scalar 1110 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
34
VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
35
36
+# The U bit (28) is don't-care because it does not affect the result
37
+VMLAS 111- 1110 0 . .. ... 1 ... 1 1110 . 100 .... @2scalar
38
+
39
# Vector add across vector
40
{
41
VADDV 111 u:1 1110 1111 size:2 01 ... 0 1111 0 0 a:1 0 qm:3 0 rda=%rdalo
42
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/mve_helper.c
45
+++ b/target/arm/mve_helper.c
46
@@ -XXX,XX +XXX,XX @@ DO_VQDMLADH_OP(vqrdmlsdhxw, 4, int32_t, 1, 1, do_vqdmlsdh_w)
47
mve_advance_vpt(env); \
48
}
49
50
+/* "accumulating" version where FN takes d as well as n and m */
51
+#define DO_2OP_ACC_SCALAR(OP, ESIZE, TYPE, FN) \
52
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
53
+ uint32_t rm) \
54
+ { \
55
+ TYPE *d = vd, *n = vn; \
56
+ TYPE m = rm; \
57
+ uint16_t mask = mve_element_mask(env); \
58
+ unsigned e; \
59
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
60
+ mergemask(&d[H##ESIZE(e)], \
61
+ FN(d[H##ESIZE(e)], n[H##ESIZE(e)], m), mask); \
62
+ } \
63
+ mve_advance_vpt(env); \
64
+ }
65
+
66
/* provide unsigned 2-op scalar helpers for all sizes */
67
#define DO_2OP_SCALAR_U(OP, FN) \
68
DO_2OP_SCALAR(OP##b, 1, uint8_t, FN) \
69
@@ -XXX,XX +XXX,XX @@ DO_VQDMLADH_OP(vqrdmlsdhxw, 4, int32_t, 1, 1, do_vqdmlsdh_w)
70
DO_2OP_SCALAR(OP##h, 2, int16_t, FN) \
71
DO_2OP_SCALAR(OP##w, 4, int32_t, FN)
72
73
+#define DO_2OP_ACC_SCALAR_U(OP, FN) \
74
+ DO_2OP_ACC_SCALAR(OP##b, 1, uint8_t, FN) \
75
+ DO_2OP_ACC_SCALAR(OP##h, 2, uint16_t, FN) \
76
+ DO_2OP_ACC_SCALAR(OP##w, 4, uint32_t, FN)
77
+
78
DO_2OP_SCALAR_U(vadd_scalar, DO_ADD)
79
DO_2OP_SCALAR_U(vsub_scalar, DO_SUB)
80
DO_2OP_SCALAR_U(vmul_scalar, DO_MUL)
81
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT_SCALAR(vqrdmulh_scalarb, 1, int8_t, DO_QRDMULH_B)
82
DO_2OP_SAT_SCALAR(vqrdmulh_scalarh, 2, int16_t, DO_QRDMULH_H)
83
DO_2OP_SAT_SCALAR(vqrdmulh_scalarw, 4, int32_t, DO_QRDMULH_W)
84
85
+/* Vector by vector plus scalar */
86
+#define DO_VMLAS(D, N, M) ((N) * (D) + (M))
87
+
88
+DO_2OP_ACC_SCALAR_U(vmlas, DO_VMLAS)
89
+
90
/*
91
* Long saturating scalar ops. As with DO_2OP_L, TYPE and H are for the
92
* input (smaller) type and LESIZE, LTYPE, LH for the output (long) type.
93
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/target/arm/translate-mve.c
96
+++ b/target/arm/translate-mve.c
97
@@ -XXX,XX +XXX,XX @@ DO_2OP_SCALAR(VQSUB_U_scalar, vqsubu_scalar)
98
DO_2OP_SCALAR(VQDMULH_scalar, vqdmulh_scalar)
99
DO_2OP_SCALAR(VQRDMULH_scalar, vqrdmulh_scalar)
100
DO_2OP_SCALAR(VBRSR, vbrsr)
101
+DO_2OP_SCALAR(VMLAS, vmlas)
102
103
static bool trans_VQDMULLB_scalar(DisasContext *s, arg_2scalar *a)
104
{
105
--
106
2.20.1
107
108
diff view generated by jsdifflib
1
Convert the VSHR 2-reg-shift insns to decodetree.
1
Implement the MVE instructions which perform shifts by a scalar.
2
These are VSHL T2, VRSHL T2, VQSHL T1 and VQRSHL T2. They take the
3
shift amount in a general purpose register and shift every element in
4
the vector by that amount.
2
5
3
Note that unlike the legacy decoder, we present the right shift
6
Mostly we can reuse the helper functions for shift-by-immediate; we
4
amount to the trans_ function as a positive integer.
7
do need two new helpers for VQRSHL.
5
8
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200522145520.6778-3-peter.maydell@linaro.org
9
---
11
---
10
target/arm/neon-dp.decode | 25 ++++++++++++++++++++
12
target/arm/helper-mve.h | 8 +++++++
11
target/arm/translate-neon.inc.c | 41 +++++++++++++++++++++++++++++++++
13
target/arm/mve.decode | 23 ++++++++++++++++---
12
target/arm/translate.c | 21 +----------------
14
target/arm/mve_helper.c | 2 ++
13
3 files changed, 67 insertions(+), 20 deletions(-)
15
target/arm/translate-mve.c | 46 ++++++++++++++++++++++++++++++++++++++
16
4 files changed, 76 insertions(+), 3 deletions(-)
14
17
15
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
18
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
16
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/neon-dp.decode
20
--- a/target/arm/helper-mve.h
18
+++ b/target/arm/neon-dp.decode
21
+++ b/target/arm/helper-mve.h
19
@@ -XXX,XX +XXX,XX @@ VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vrshli_ub, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
20
######################################################################
23
DEF_HELPER_FLAGS_4(mve_vrshli_uh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
21
&2reg_shift vm vd q shift size
24
DEF_HELPER_FLAGS_4(mve_vrshli_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
22
25
23
+# Right shifts are encoded as N - shift, where N is the element size in bits.
26
+DEF_HELPER_FLAGS_4(mve_vqrshli_sb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
+%neon_rshift_i6 16:6 !function=rsub_64
27
+DEF_HELPER_FLAGS_4(mve_vqrshli_sh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
+%neon_rshift_i5 16:5 !function=rsub_32
28
+DEF_HELPER_FLAGS_4(mve_vqrshli_sw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
26
+%neon_rshift_i4 16:4 !function=rsub_16
27
+%neon_rshift_i3 16:3 !function=rsub_8
28
+
29
+
29
+@2reg_shr_d .... ... . . . ...... .... .... 1 q:1 . . .... \
30
+DEF_HELPER_FLAGS_4(mve_vqrshli_ub, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
30
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=3 shift=%neon_rshift_i6
31
+DEF_HELPER_FLAGS_4(mve_vqrshli_uh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
+@2reg_shr_s .... ... . . . 1 ..... .... .... 0 q:1 . . .... \
32
+DEF_HELPER_FLAGS_4(mve_vqrshli_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
32
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=2 shift=%neon_rshift_i5
33
+@2reg_shr_h .... ... . . . 01 .... .... .... 0 q:1 . . .... \
34
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=1 shift=%neon_rshift_i4
35
+@2reg_shr_b .... ... . . . 001 ... .... .... 0 q:1 . . .... \
36
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=0 shift=%neon_rshift_i3
37
+
33
+
38
@2reg_shl_d .... ... . . . shift:6 .... .... 1 q:1 . . .... \
34
DEF_HELPER_FLAGS_4(mve_vshllbsb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
39
&2reg_shift vm=%vm_dp vd=%vd_dp size=3
35
DEF_HELPER_FLAGS_4(mve_vshllbsh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
40
@2reg_shl_s .... ... . . . 1 shift:5 .... .... 0 q:1 . . .... \
36
DEF_HELPER_FLAGS_4(mve_vshllbub, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
41
@@ -XXX,XX +XXX,XX @@ VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
37
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
42
@2reg_shl_b .... ... . . . 001 shift:3 .... .... 0 q:1 . . .... \
38
index XXXXXXX..XXXXXXX 100644
43
&2reg_shift vm=%vm_dp vd=%vd_dp size=0
39
--- a/target/arm/mve.decode
44
40
+++ b/target/arm/mve.decode
45
+VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_d
41
@@ -XXX,XX +XXX,XX @@
46
+VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_s
42
&viwdup qd rn rm size imm
47
+VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_h
43
&vcmp qm qn size mask
48
+VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_b
44
&vcmp_scalar qn rm size mask
45
+&shl_scalar qda rm size
46
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
@@ -XXX,XX +XXX,XX @@
50
@2_shr_w .... .... .. 1 ..... .... .... .... .... &2shift qd=%qd qm=%qm \
51
size=2 shift=%rshift_i5
52
53
+@shl_scalar .... .... .... size:2 .. .... .... .... rm:4 &shl_scalar qda=%qd
49
+
54
+
50
+VSHR_U_2sh 1111 001 1 1 . ...... .... 0000 . . . 1 .... @2reg_shr_d
55
# Vector comparison; 4-bit Qm but 3-bit Qn
51
+VSHR_U_2sh 1111 001 1 1 . ...... .... 0000 . . . 1 .... @2reg_shr_s
56
%mask_22_13 22:1 13:3
52
+VSHR_U_2sh 1111 001 1 1 . ...... .... 0000 . . . 1 .... @2reg_shr_h
57
@vcmp .... .... .. size:2 qn:3 . .... .... .... .... &vcmp qm=%qm mask=%mask_22_13
53
+VSHR_U_2sh 1111 001 1 1 . ...... .... 0000 . . . 1 .... @2reg_shr_b
58
@@ -XXX,XX +XXX,XX @@ VRMLSLDAVH 1111 1110 1 ... ... 0 ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav_no
59
60
VADD_scalar 1110 1110 0 . .. ... 1 ... 0 1111 . 100 .... @2scalar
61
VSUB_scalar 1110 1110 0 . .. ... 1 ... 1 1111 . 100 .... @2scalar
62
-VMUL_scalar 1110 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
54
+
63
+
55
VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_d
56
VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_s
57
VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_h
58
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
59
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/translate-neon.inc.c
61
+++ b/target/arm/translate-neon.inc.c
62
@@ -XXX,XX +XXX,XX @@ static inline int plus1(DisasContext *s, int x)
63
return x + 1;
64
}
65
66
+static inline int rsub_64(DisasContext *s, int x)
67
+{
64
+{
68
+ return 64 - x;
65
+ VSHL_S_scalar 1110 1110 0 . 11 .. 01 ... 1 1110 0110 .... @shl_scalar
66
+ VRSHL_S_scalar 1110 1110 0 . 11 .. 11 ... 1 1110 0110 .... @shl_scalar
67
+ VQSHL_S_scalar 1110 1110 0 . 11 .. 01 ... 1 1110 1110 .... @shl_scalar
68
+ VQRSHL_S_scalar 1110 1110 0 . 11 .. 11 ... 1 1110 1110 .... @shl_scalar
69
+ VMUL_scalar 1110 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
69
+}
70
+}
70
+
71
+
71
+static inline int rsub_32(DisasContext *s, int x)
72
+{
72
+{
73
+ return 32 - x;
73
+ VSHL_U_scalar 1111 1110 0 . 11 .. 01 ... 1 1110 0110 .... @shl_scalar
74
+}
74
+ VRSHL_U_scalar 1111 1110 0 . 11 .. 11 ... 1 1110 0110 .... @shl_scalar
75
+static inline int rsub_16(DisasContext *s, int x)
75
+ VQSHL_U_scalar 1111 1110 0 . 11 .. 01 ... 1 1110 1110 .... @shl_scalar
76
+{
76
+ VQRSHL_U_scalar 1111 1110 0 . 11 .. 11 ... 1 1110 1110 .... @shl_scalar
77
+ return 16 - x;
77
+ VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
78
+}
79
+static inline int rsub_8(DisasContext *s, int x)
80
+{
81
+ return 8 - x;
82
+}
78
+}
83
+
79
+
84
/* Include the generated Neon decoder */
80
VHADD_S_scalar 1110 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
85
#include "decode-neon-dp.inc.c"
81
VHADD_U_scalar 1111 1110 0 . .. ... 0 ... 0 1111 . 100 .... @2scalar
86
#include "decode-neon-ls.inc.c"
82
VHSUB_S_scalar 1110 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
87
@@ -XXX,XX +XXX,XX @@ static bool do_vector_2sh(DisasContext *s, arg_2reg_shift *a, GVecGen2iFn *fn)
83
@@ -XXX,XX +XXX,XX @@ VHSUB_U_scalar 1111 1110 0 . .. ... 0 ... 1 1111 . 100 .... @2scalar
88
84
size=%size_28
89
DO_2SH(VSHL, tcg_gen_gvec_shli)
85
}
90
DO_2SH(VSLI, gen_gvec_sli)
86
87
-VBRSR 1111 1110 0 . .. ... 1 ... 1 1110 . 110 .... @2scalar
88
-
89
VQDMULH_scalar 1110 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
90
VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
91
92
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
93
index XXXXXXX..XXXXXXX 100644
94
--- a/target/arm/mve_helper.c
95
+++ b/target/arm/mve_helper.c
96
@@ -XXX,XX +XXX,XX @@ DO_2SHIFT_SAT_S(vqshli_s, DO_SQSHL_OP)
97
DO_2SHIFT_SAT_S(vqshlui_s, DO_SUQSHL_OP)
98
DO_2SHIFT_U(vrshli_u, DO_VRSHLU)
99
DO_2SHIFT_S(vrshli_s, DO_VRSHLS)
100
+DO_2SHIFT_SAT_U(vqrshli_u, DO_UQRSHL_OP)
101
+DO_2SHIFT_SAT_S(vqrshli_s, DO_SQRSHL_OP)
102
103
/* Shift-and-insert; we always work with 64 bits at a time */
104
#define DO_2SHIFT_INSERT(OP, ESIZE, SHIFTFN, MASKFN) \
105
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
106
index XXXXXXX..XXXXXXX 100644
107
--- a/target/arm/translate-mve.c
108
+++ b/target/arm/translate-mve.c
109
@@ -XXX,XX +XXX,XX @@ DO_2SHIFT(VRSHRI_U, vrshli_u, true)
110
DO_2SHIFT(VSRI, vsri, false)
111
DO_2SHIFT(VSLI, vsli, false)
112
113
+static bool do_2shift_scalar(DisasContext *s, arg_shl_scalar *a,
114
+ MVEGenTwoOpShiftFn *fn)
115
+{
116
+ TCGv_ptr qda;
117
+ TCGv_i32 rm;
91
+
118
+
92
+static bool trans_VSHR_S_2sh(DisasContext *s, arg_2reg_shift *a)
119
+ if (!dc_isar_feature(aa32_mve, s) ||
93
+{
120
+ !mve_check_qreg_bank(s, a->qda) ||
94
+ /* Signed shift out of range results in all-sign-bits */
121
+ a->rm == 13 || a->rm == 15 || !fn) {
95
+ a->shift = MIN(a->shift, (8 << a->size) - 1);
122
+ /* Rm cases are UNPREDICTABLE */
96
+ return do_vector_2sh(s, a, tcg_gen_gvec_sari);
123
+ return false;
124
+ }
125
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
126
+ return true;
127
+ }
128
+
129
+ qda = mve_qreg_ptr(a->qda);
130
+ rm = load_reg(s, a->rm);
131
+ fn(cpu_env, qda, qda, rm);
132
+ tcg_temp_free_ptr(qda);
133
+ tcg_temp_free_i32(rm);
134
+ mve_update_eci(s);
135
+ return true;
97
+}
136
+}
98
+
137
+
99
+static void gen_zero_rd_2sh(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
138
+#define DO_2SHIFT_SCALAR(INSN, FN) \
100
+ int64_t shift, uint32_t oprsz, uint32_t maxsz)
139
+ static bool trans_##INSN(DisasContext *s, arg_shl_scalar *a) \
101
+{
140
+ { \
102
+ tcg_gen_gvec_dup_imm(vece, rd_ofs, oprsz, maxsz, 0);
141
+ static MVEGenTwoOpShiftFn * const fns[] = { \
103
+}
142
+ gen_helper_mve_##FN##b, \
143
+ gen_helper_mve_##FN##h, \
144
+ gen_helper_mve_##FN##w, \
145
+ NULL, \
146
+ }; \
147
+ return do_2shift_scalar(s, a, fns[a->size]); \
148
+ }
104
+
149
+
105
+static bool trans_VSHR_U_2sh(DisasContext *s, arg_2reg_shift *a)
150
+DO_2SHIFT_SCALAR(VSHL_S_scalar, vshli_s)
106
+{
151
+DO_2SHIFT_SCALAR(VSHL_U_scalar, vshli_u)
107
+ /* Shift out of range is architecturally valid and results in zero. */
152
+DO_2SHIFT_SCALAR(VRSHL_S_scalar, vrshli_s)
108
+ if (a->shift >= (8 << a->size)) {
153
+DO_2SHIFT_SCALAR(VRSHL_U_scalar, vrshli_u)
109
+ return do_vector_2sh(s, a, gen_zero_rd_2sh);
154
+DO_2SHIFT_SCALAR(VQSHL_S_scalar, vqshli_s)
110
+ } else {
155
+DO_2SHIFT_SCALAR(VQSHL_U_scalar, vqshli_u)
111
+ return do_vector_2sh(s, a, tcg_gen_gvec_shri);
156
+DO_2SHIFT_SCALAR(VQRSHL_S_scalar, vqrshli_s)
112
+ }
157
+DO_2SHIFT_SCALAR(VQRSHL_U_scalar, vqrshli_u)
113
+}
158
+
114
diff --git a/target/arm/translate.c b/target/arm/translate.c
159
#define DO_VSHLL(INSN, FN) \
115
index XXXXXXX..XXXXXXX 100644
160
static bool trans_##INSN(DisasContext *s, arg_2shift *a) \
116
--- a/target/arm/translate.c
161
{ \
117
+++ b/target/arm/translate.c
118
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
119
op = (insn >> 8) & 0xf;
120
121
switch (op) {
122
+ case 0: /* VSHR */
123
case 5: /* VSHL, VSLI */
124
return 1; /* handled by decodetree */
125
default:
126
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
127
}
128
129
switch (op) {
130
- case 0: /* VSHR */
131
- /* Right shift comes here negative. */
132
- shift = -shift;
133
- /* Shifts larger than the element size are architecturally
134
- * valid. Unsigned results in all zeros; signed results
135
- * in all sign bits.
136
- */
137
- if (!u) {
138
- tcg_gen_gvec_sari(size, rd_ofs, rm_ofs,
139
- MIN(shift, (8 << size) - 1),
140
- vec_size, vec_size);
141
- } else if (shift >= 8 << size) {
142
- tcg_gen_gvec_dup_imm(MO_8, rd_ofs, vec_size,
143
- vec_size, 0);
144
- } else {
145
- tcg_gen_gvec_shri(size, rd_ofs, rm_ofs, shift,
146
- vec_size, vec_size);
147
- }
148
- return 0;
149
-
150
case 1: /* VSRA */
151
/* Right shift comes here negative. */
152
shift = -shift;
153
--
162
--
154
2.20.1
163
2.20.1
155
164
156
165
diff view generated by jsdifflib
New patch
1
All the users of the vmlaldav formats have an 'x bit in bit 12 and an
2
'a' bit in bit 5; move these to the format rather than specifying them
3
in each insn pattern.
1
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
---
8
target/arm/mve.decode | 16 ++++++++--------
9
1 file changed, 8 insertions(+), 8 deletions(-)
10
11
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/mve.decode
14
+++ b/target/arm/mve.decode
15
@@ -XXX,XX +XXX,XX @@ VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=2
16
17
&vmlaldav rdahi rdalo size qn qm x a
18
19
-@vmlaldav .... .... . ... ... . ... . .... .... qm:3 . \
20
+@vmlaldav .... .... . ... ... . ... x:1 .... .. a:1 . qm:3 . \
21
qn=%qn rdahi=%rdahi rdalo=%rdalo size=%size_16 &vmlaldav
22
-@vmlaldav_nosz .... .... . ... ... . ... . .... .... qm:3 . \
23
+@vmlaldav_nosz .... .... . ... ... . ... x:1 .... .. a:1 . qm:3 . \
24
qn=%qn rdahi=%rdahi rdalo=%rdalo size=0 &vmlaldav
25
-VMLALDAV_S 1110 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 0 @vmlaldav
26
-VMLALDAV_U 1111 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 0 @vmlaldav
27
+VMLALDAV_S 1110 1110 1 ... ... . ... . 1110 . 0 . 0 ... 0 @vmlaldav
28
+VMLALDAV_U 1111 1110 1 ... ... . ... . 1110 . 0 . 0 ... 0 @vmlaldav
29
30
-VMLSLDAV 1110 1110 1 ... ... . ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav
31
+VMLSLDAV 1110 1110 1 ... ... . ... . 1110 . 0 . 0 ... 1 @vmlaldav
32
33
-VRMLALDAVH_S 1110 1110 1 ... ... 0 ... x:1 1111 . 0 a:1 0 ... 0 @vmlaldav_nosz
34
-VRMLALDAVH_U 1111 1110 1 ... ... 0 ... x:1 1111 . 0 a:1 0 ... 0 @vmlaldav_nosz
35
+VRMLALDAVH_S 1110 1110 1 ... ... 0 ... . 1111 . 0 . 0 ... 0 @vmlaldav_nosz
36
+VRMLALDAVH_U 1111 1110 1 ... ... 0 ... . 1111 . 0 . 0 ... 0 @vmlaldav_nosz
37
38
-VRMLSLDAVH 1111 1110 1 ... ... 0 ... x:1 1110 . 0 a:1 0 ... 1 @vmlaldav_nosz
39
+VRMLSLDAVH 1111 1110 1 ... ... 0 ... . 1110 . 0 . 0 ... 1 @vmlaldav_nosz
40
41
# Scalar operations
42
43
--
44
2.20.1
45
46
diff view generated by jsdifflib
New patch
1
1
Implement the MVE integer min/max across vector insns
2
VMAXV, VMINV, VMAXAV and VMINAV, which find the maximum
3
from the vector elements and a general purpose register,
4
and store the maximum back into the general purpose
5
register.
6
7
These insns overlap with VRMLALDAVH (they use what would
8
be RdaHi=0b110).
9
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
---
13
target/arm/helper-mve.h | 20 ++++++++++++
14
target/arm/mve.decode | 18 +++++++++--
15
target/arm/mve_helper.c | 66 ++++++++++++++++++++++++++++++++++++++
16
target/arm/translate-mve.c | 48 +++++++++++++++++++++++++++
17
4 files changed, 150 insertions(+), 2 deletions(-)
18
19
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper-mve.h
22
+++ b/target/arm/helper-mve.h
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vaddvuh, TCG_CALL_NO_WG, i32, env, ptr, i32)
24
DEF_HELPER_FLAGS_3(mve_vaddvsw, TCG_CALL_NO_WG, i32, env, ptr, i32)
25
DEF_HELPER_FLAGS_3(mve_vaddvuw, TCG_CALL_NO_WG, i32, env, ptr, i32)
26
27
+DEF_HELPER_FLAGS_3(mve_vmaxvsb, TCG_CALL_NO_WG, i32, env, ptr, i32)
28
+DEF_HELPER_FLAGS_3(mve_vmaxvsh, TCG_CALL_NO_WG, i32, env, ptr, i32)
29
+DEF_HELPER_FLAGS_3(mve_vmaxvsw, TCG_CALL_NO_WG, i32, env, ptr, i32)
30
+DEF_HELPER_FLAGS_3(mve_vmaxvub, TCG_CALL_NO_WG, i32, env, ptr, i32)
31
+DEF_HELPER_FLAGS_3(mve_vmaxvuh, TCG_CALL_NO_WG, i32, env, ptr, i32)
32
+DEF_HELPER_FLAGS_3(mve_vmaxvuw, TCG_CALL_NO_WG, i32, env, ptr, i32)
33
+DEF_HELPER_FLAGS_3(mve_vmaxavb, TCG_CALL_NO_WG, i32, env, ptr, i32)
34
+DEF_HELPER_FLAGS_3(mve_vmaxavh, TCG_CALL_NO_WG, i32, env, ptr, i32)
35
+DEF_HELPER_FLAGS_3(mve_vmaxavw, TCG_CALL_NO_WG, i32, env, ptr, i32)
36
+
37
+DEF_HELPER_FLAGS_3(mve_vminvsb, TCG_CALL_NO_WG, i32, env, ptr, i32)
38
+DEF_HELPER_FLAGS_3(mve_vminvsh, TCG_CALL_NO_WG, i32, env, ptr, i32)
39
+DEF_HELPER_FLAGS_3(mve_vminvsw, TCG_CALL_NO_WG, i32, env, ptr, i32)
40
+DEF_HELPER_FLAGS_3(mve_vminvub, TCG_CALL_NO_WG, i32, env, ptr, i32)
41
+DEF_HELPER_FLAGS_3(mve_vminvuh, TCG_CALL_NO_WG, i32, env, ptr, i32)
42
+DEF_HELPER_FLAGS_3(mve_vminvuw, TCG_CALL_NO_WG, i32, env, ptr, i32)
43
+DEF_HELPER_FLAGS_3(mve_vminavb, TCG_CALL_NO_WG, i32, env, ptr, i32)
44
+DEF_HELPER_FLAGS_3(mve_vminavh, TCG_CALL_NO_WG, i32, env, ptr, i32)
45
+DEF_HELPER_FLAGS_3(mve_vminavw, TCG_CALL_NO_WG, i32, env, ptr, i32)
46
+
47
DEF_HELPER_FLAGS_3(mve_vaddlv_s, TCG_CALL_NO_WG, i64, env, ptr, i64)
48
DEF_HELPER_FLAGS_3(mve_vaddlv_u, TCG_CALL_NO_WG, i64, env, ptr, i64)
49
50
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/mve.decode
53
+++ b/target/arm/mve.decode
54
@@ -XXX,XX +XXX,XX @@
55
&vcmp qm qn size mask
56
&vcmp_scalar qn rm size mask
57
&shl_scalar qda rm size
58
+&vmaxv qm rda size
59
60
@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
61
# Note that both Rn and Qd are 3 bits only (no D bit)
62
@@ -XXX,XX +XXX,XX @@
63
@vcmp_scalar .... .... .. size:2 qn:3 . .... .... .... rm:4 &vcmp_scalar \
64
mask=%mask_22_13
65
66
+@vmaxv .... .... .... size:2 .. rda:4 .... .... .... &vmaxv qm=%qm
67
+
68
# Vector loads and stores
69
70
# Widening loads and narrowing stores:
71
@@ -XXX,XX +XXX,XX @@ VMLALDAV_U 1111 1110 1 ... ... . ... . 1110 . 0 . 0 ... 0 @vmlaldav
72
73
VMLSLDAV 1110 1110 1 ... ... . ... . 1110 . 0 . 0 ... 1 @vmlaldav
74
75
-VRMLALDAVH_S 1110 1110 1 ... ... 0 ... . 1111 . 0 . 0 ... 0 @vmlaldav_nosz
76
-VRMLALDAVH_U 1111 1110 1 ... ... 0 ... . 1111 . 0 . 0 ... 0 @vmlaldav_nosz
77
+{
78
+ VMAXV_S 1110 1110 1110 .. 10 .... 1111 0 0 . 0 ... 0 @vmaxv
79
+ VMINV_S 1110 1110 1110 .. 10 .... 1111 1 0 . 0 ... 0 @vmaxv
80
+ VMAXAV 1110 1110 1110 .. 00 .... 1111 0 0 . 0 ... 0 @vmaxv
81
+ VMINAV 1110 1110 1110 .. 00 .... 1111 1 0 . 0 ... 0 @vmaxv
82
+ VRMLALDAVH_S 1110 1110 1 ... ... 0 ... . 1111 . 0 . 0 ... 0 @vmlaldav_nosz
83
+}
84
+
85
+{
86
+ VMAXV_U 1111 1110 1110 .. 10 .... 1111 0 0 . 0 ... 0 @vmaxv
87
+ VMINV_U 1111 1110 1110 .. 10 .... 1111 1 0 . 0 ... 0 @vmaxv
88
+ VRMLALDAVH_U 1111 1110 1 ... ... 0 ... . 1111 . 0 . 0 ... 0 @vmlaldav_nosz
89
+}
90
91
VRMLSLDAVH 1111 1110 1 ... ... 0 ... . 1110 . 0 . 0 ... 1 @vmlaldav_nosz
92
93
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/target/arm/mve_helper.c
96
+++ b/target/arm/mve_helper.c
97
@@ -XXX,XX +XXX,XX @@ DO_VADDV(vaddvub, 1, uint8_t)
98
DO_VADDV(vaddvuh, 2, uint16_t)
99
DO_VADDV(vaddvuw, 4, uint32_t)
100
101
+/*
102
+ * Vector max/min across vector. Unlike VADDV, we must
103
+ * read ra as the element size, not its full width.
104
+ * We work with int64_t internally for simplicity.
105
+ */
106
+#define DO_VMAXMINV(OP, ESIZE, TYPE, RATYPE, FN) \
107
+ uint32_t HELPER(glue(mve_, OP))(CPUARMState *env, void *vm, \
108
+ uint32_t ra_in) \
109
+ { \
110
+ uint16_t mask = mve_element_mask(env); \
111
+ unsigned e; \
112
+ TYPE *m = vm; \
113
+ int64_t ra = (RATYPE)ra_in; \
114
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
115
+ if (mask & 1) { \
116
+ ra = FN(ra, m[H##ESIZE(e)]); \
117
+ } \
118
+ } \
119
+ mve_advance_vpt(env); \
120
+ return ra; \
121
+ } \
122
+
123
+#define DO_VMAXMINV_U(INSN, FN) \
124
+ DO_VMAXMINV(INSN##b, 1, uint8_t, uint8_t, FN) \
125
+ DO_VMAXMINV(INSN##h, 2, uint16_t, uint16_t, FN) \
126
+ DO_VMAXMINV(INSN##w, 4, uint32_t, uint32_t, FN)
127
+#define DO_VMAXMINV_S(INSN, FN) \
128
+ DO_VMAXMINV(INSN##b, 1, int8_t, int8_t, FN) \
129
+ DO_VMAXMINV(INSN##h, 2, int16_t, int16_t, FN) \
130
+ DO_VMAXMINV(INSN##w, 4, int32_t, int32_t, FN)
131
+
132
+/*
133
+ * Helpers for max and min of absolute values across vector:
134
+ * note that we only take the absolute value of 'm', not 'n'
135
+ */
136
+static int64_t do_maxa(int64_t n, int64_t m)
137
+{
138
+ if (m < 0) {
139
+ m = -m;
140
+ }
141
+ return MAX(n, m);
142
+}
143
+
144
+static int64_t do_mina(int64_t n, int64_t m)
145
+{
146
+ if (m < 0) {
147
+ m = -m;
148
+ }
149
+ return MIN(n, m);
150
+}
151
+
152
+DO_VMAXMINV_S(vmaxvs, DO_MAX)
153
+DO_VMAXMINV_U(vmaxvu, DO_MAX)
154
+DO_VMAXMINV_S(vminvs, DO_MIN)
155
+DO_VMAXMINV_U(vminvu, DO_MIN)
156
+/*
157
+ * VMAXAV, VMINAV treat the general purpose input as unsigned
158
+ * and the vector elements as signed.
159
+ */
160
+DO_VMAXMINV(vmaxavb, 1, int8_t, uint8_t, do_maxa)
161
+DO_VMAXMINV(vmaxavh, 2, int16_t, uint16_t, do_maxa)
162
+DO_VMAXMINV(vmaxavw, 4, int32_t, uint32_t, do_maxa)
163
+DO_VMAXMINV(vminavb, 1, int8_t, uint8_t, do_mina)
164
+DO_VMAXMINV(vminavh, 2, int16_t, uint16_t, do_mina)
165
+DO_VMAXMINV(vminavw, 4, int32_t, uint32_t, do_mina)
166
+
167
#define DO_VADDLV(OP, TYPE, LTYPE) \
168
uint64_t HELPER(glue(mve_, OP))(CPUARMState *env, void *vm, \
169
uint64_t ra) \
170
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
171
index XXXXXXX..XXXXXXX 100644
172
--- a/target/arm/translate-mve.c
173
+++ b/target/arm/translate-mve.c
174
@@ -XXX,XX +XXX,XX @@ DO_VCMP(VCMPGE, vcmpge)
175
DO_VCMP(VCMPLT, vcmplt)
176
DO_VCMP(VCMPGT, vcmpgt)
177
DO_VCMP(VCMPLE, vcmple)
178
+
179
+static bool do_vmaxv(DisasContext *s, arg_vmaxv *a, MVEGenVADDVFn fn)
180
+{
181
+ /*
182
+ * MIN/MAX operations across a vector: compute the min or
183
+ * max of the initial value in a general purpose register
184
+ * and all the elements in the vector, and store it back
185
+ * into the general purpose register.
186
+ */
187
+ TCGv_ptr qm;
188
+ TCGv_i32 rda;
189
+
190
+ if (!dc_isar_feature(aa32_mve, s) || !mve_check_qreg_bank(s, a->qm) ||
191
+ !fn || a->rda == 13 || a->rda == 15) {
192
+ /* Rda cases are UNPREDICTABLE */
193
+ return false;
194
+ }
195
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
196
+ return true;
197
+ }
198
+
199
+ qm = mve_qreg_ptr(a->qm);
200
+ rda = load_reg(s, a->rda);
201
+ fn(rda, cpu_env, qm, rda);
202
+ store_reg(s, a->rda, rda);
203
+ tcg_temp_free_ptr(qm);
204
+ mve_update_eci(s);
205
+ return true;
206
+}
207
+
208
+#define DO_VMAXV(INSN, FN) \
209
+ static bool trans_##INSN(DisasContext *s, arg_vmaxv *a) \
210
+ { \
211
+ static MVEGenVADDVFn * const fns[] = { \
212
+ gen_helper_mve_##FN##b, \
213
+ gen_helper_mve_##FN##h, \
214
+ gen_helper_mve_##FN##w, \
215
+ NULL, \
216
+ }; \
217
+ return do_vmaxv(s, a, fns[a->size]); \
218
+ }
219
+
220
+DO_VMAXV(VMAXV_S, vmaxvs)
221
+DO_VMAXV(VMAXV_U, vmaxvu)
222
+DO_VMAXV(VMAXAV, vmaxav)
223
+DO_VMAXV(VMINV_S, vminvs)
224
+DO_VMAXV(VMINV_U, vminvu)
225
+DO_VMAXV(VMINAV, vminav)
226
--
227
2.20.1
228
229
diff view generated by jsdifflib
1
From: Eden Mikitas <e.mikitas@gmail.com>
1
Implement the MVE VABAV insn, which computes absolute differences
2
between elements of two vectors and accumulates the result into
3
a general purpose register.
2
4
3
When inserting the value retrieved (rx) from the spi slave, rx is pushed to
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
rx_fifo after being cast to uint8_t. rx_fifo is a fifo32, and the rx
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
register the driver uses is also 32 bit. This zeroes the 24 most
7
---
6
significant bits of rx. This proved problematic with devices that expect to
8
target/arm/helper-mve.h | 7 +++++++
7
use the whole 32 bits of the rx register.
9
target/arm/mve.decode | 6 ++++++
10
target/arm/mve_helper.c | 26 +++++++++++++++++++++++
11
target/arm/translate-mve.c | 43 ++++++++++++++++++++++++++++++++++++++
12
4 files changed, 82 insertions(+)
8
13
9
Signed-off-by: Eden Mikitas <e.mikitas@gmail.com>
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
13
hw/ssi/imx_spi.c | 2 +-
14
1 file changed, 1 insertion(+), 1 deletion(-)
15
16
diff --git a/hw/ssi/imx_spi.c b/hw/ssi/imx_spi.c
17
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/ssi/imx_spi.c
16
--- a/target/arm/helper-mve.h
19
+++ b/hw/ssi/imx_spi.c
17
+++ b/target/arm/helper-mve.h
20
@@ -XXX,XX +XXX,XX @@ static void imx_spi_flush_txfifo(IMXSPIState *s)
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vminavw, TCG_CALL_NO_WG, i32, env, ptr, i32)
21
if (fifo32_is_full(&s->rx_fifo)) {
19
DEF_HELPER_FLAGS_3(mve_vaddlv_s, TCG_CALL_NO_WG, i64, env, ptr, i64)
22
s->regs[ECSPI_STATREG] |= ECSPI_STATREG_RO;
20
DEF_HELPER_FLAGS_3(mve_vaddlv_u, TCG_CALL_NO_WG, i64, env, ptr, i64)
23
} else {
21
24
- fifo32_push(&s->rx_fifo, (uint8_t)rx);
22
+DEF_HELPER_FLAGS_4(mve_vabavsb, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
25
+ fifo32_push(&s->rx_fifo, rx);
23
+DEF_HELPER_FLAGS_4(mve_vabavsh, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
26
}
24
+DEF_HELPER_FLAGS_4(mve_vabavsw, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
27
25
+DEF_HELPER_FLAGS_4(mve_vabavub, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
28
if (s->burst_length <= 0) {
26
+DEF_HELPER_FLAGS_4(mve_vabavuh, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
27
+DEF_HELPER_FLAGS_4(mve_vabavuw, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
28
+
29
DEF_HELPER_FLAGS_3(mve_vmovi, TCG_CALL_NO_WG, void, env, ptr, i64)
30
DEF_HELPER_FLAGS_3(mve_vandi, TCG_CALL_NO_WG, void, env, ptr, i64)
31
DEF_HELPER_FLAGS_3(mve_vorri, TCG_CALL_NO_WG, void, env, 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 @@
37
&vcmp_scalar qn rm size mask
38
&shl_scalar qda rm size
39
&vmaxv qm rda size
40
+&vabav qn qm rda size
41
42
@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
43
# Note that both Rn and Qd are 3 bits only (no D bit)
44
@@ -XXX,XX +XXX,XX @@ VMLAS 111- 1110 0 . .. ... 1 ... 1 1110 . 100 .... @2scalar
45
rdahi=%rdahi rdalo=%rdalo
46
}
47
48
+@vabav .... .... .. size:2 .... rda:4 .... .... .... &vabav qn=%qn qm=%qm
49
+
50
+VABAV_S 111 0 1110 10 .. ... 0 .... 1111 . 0 . 0 ... 1 @vabav
51
+VABAV_U 111 1 1110 10 .. ... 0 .... 1111 . 0 . 0 ... 1 @vabav
52
+
53
# Logical immediate operations (1 reg and modified-immediate)
54
55
# The cmode/op bits here decode VORR/VBIC/VMOV/VMVN, but
56
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/mve_helper.c
59
+++ b/target/arm/mve_helper.c
60
@@ -XXX,XX +XXX,XX @@ DO_VMAXMINV(vminavb, 1, int8_t, uint8_t, do_mina)
61
DO_VMAXMINV(vminavh, 2, int16_t, uint16_t, do_mina)
62
DO_VMAXMINV(vminavw, 4, int32_t, uint32_t, do_mina)
63
64
+#define DO_VABAV(OP, ESIZE, TYPE) \
65
+ uint32_t HELPER(glue(mve_, OP))(CPUARMState *env, void *vn, \
66
+ void *vm, uint32_t ra) \
67
+ { \
68
+ uint16_t mask = mve_element_mask(env); \
69
+ unsigned e; \
70
+ TYPE *m = vm, *n = vn; \
71
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
72
+ if (mask & 1) { \
73
+ int64_t n0 = n[H##ESIZE(e)]; \
74
+ int64_t m0 = m[H##ESIZE(e)]; \
75
+ uint32_t r = n0 >= m0 ? (n0 - m0) : (m0 - n0); \
76
+ ra += r; \
77
+ } \
78
+ } \
79
+ mve_advance_vpt(env); \
80
+ return ra; \
81
+ }
82
+
83
+DO_VABAV(vabavsb, 1, int8_t)
84
+DO_VABAV(vabavsh, 2, int16_t)
85
+DO_VABAV(vabavsw, 4, int32_t)
86
+DO_VABAV(vabavub, 1, uint8_t)
87
+DO_VABAV(vabavuh, 2, uint16_t)
88
+DO_VABAV(vabavuw, 4, uint32_t)
89
+
90
#define DO_VADDLV(OP, TYPE, LTYPE) \
91
uint64_t HELPER(glue(mve_, OP))(CPUARMState *env, void *vm, \
92
uint64_t ra) \
93
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
94
index XXXXXXX..XXXXXXX 100644
95
--- a/target/arm/translate-mve.c
96
+++ b/target/arm/translate-mve.c
97
@@ -XXX,XX +XXX,XX @@ typedef void MVEGenVIDUPFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32, TCGv_i32);
98
typedef void MVEGenVIWDUPFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32, TCGv_i32, TCGv_i32);
99
typedef void MVEGenCmpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
100
typedef void MVEGenScalarCmpFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
101
+typedef void MVEGenVABAVFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
102
103
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
104
static inline long mve_qreg_offset(unsigned reg)
105
@@ -XXX,XX +XXX,XX @@ DO_VMAXV(VMAXAV, vmaxav)
106
DO_VMAXV(VMINV_S, vminvs)
107
DO_VMAXV(VMINV_U, vminvu)
108
DO_VMAXV(VMINAV, vminav)
109
+
110
+static bool do_vabav(DisasContext *s, arg_vabav *a, MVEGenVABAVFn *fn)
111
+{
112
+ /* Absolute difference accumulated across vector */
113
+ TCGv_ptr qn, qm;
114
+ TCGv_i32 rda;
115
+
116
+ if (!dc_isar_feature(aa32_mve, s) ||
117
+ !mve_check_qreg_bank(s, a->qm | a->qn) ||
118
+ !fn || a->rda == 13 || a->rda == 15) {
119
+ /* Rda cases are UNPREDICTABLE */
120
+ return false;
121
+ }
122
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
123
+ return true;
124
+ }
125
+
126
+ qm = mve_qreg_ptr(a->qm);
127
+ qn = mve_qreg_ptr(a->qn);
128
+ rda = load_reg(s, a->rda);
129
+ fn(rda, cpu_env, qn, qm, rda);
130
+ store_reg(s, a->rda, rda);
131
+ tcg_temp_free_ptr(qm);
132
+ tcg_temp_free_ptr(qn);
133
+ mve_update_eci(s);
134
+ return true;
135
+}
136
+
137
+#define DO_VABAV(INSN, FN) \
138
+ static bool trans_##INSN(DisasContext *s, arg_vabav *a) \
139
+ { \
140
+ static MVEGenVABAVFn * const fns[] = { \
141
+ gen_helper_mve_##FN##b, \
142
+ gen_helper_mve_##FN##h, \
143
+ gen_helper_mve_##FN##w, \
144
+ NULL, \
145
+ }; \
146
+ return do_vabav(s, a, fns[a->size]); \
147
+ }
148
+
149
+DO_VABAV(VABAV_S, vabavs)
150
+DO_VABAV(VABAV_U, vabavu)
29
--
151
--
30
2.20.1
152
2.20.1
31
153
32
154
diff view generated by jsdifflib
New patch
1
1
Implement the MVE narrowing move insns VMOVN, VQMOVN and VQMOVUN.
2
These take a double-width input, narrow it (possibly saturating) and
3
store the result to either the top or bottom half of the output
4
element.
5
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
---
9
target/arm/helper-mve.h | 20 ++++++++++
10
target/arm/mve.decode | 12 ++++++
11
target/arm/mve_helper.c | 78 ++++++++++++++++++++++++++++++++++++++
12
target/arm/translate-mve.c | 22 +++++++++++
13
4 files changed, 132 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_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_3(mve_vmovnbb, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
+DEF_HELPER_FLAGS_3(mve_vmovnbh, TCG_CALL_NO_WG, void, env, ptr, ptr)
25
+DEF_HELPER_FLAGS_3(mve_vmovntb, TCG_CALL_NO_WG, void, env, ptr, ptr)
26
+DEF_HELPER_FLAGS_3(mve_vmovnth, TCG_CALL_NO_WG, void, env, ptr, ptr)
27
+
28
+DEF_HELPER_FLAGS_3(mve_vqmovunbb, TCG_CALL_NO_WG, void, env, ptr, ptr)
29
+DEF_HELPER_FLAGS_3(mve_vqmovunbh, TCG_CALL_NO_WG, void, env, ptr, ptr)
30
+DEF_HELPER_FLAGS_3(mve_vqmovuntb, TCG_CALL_NO_WG, void, env, ptr, ptr)
31
+DEF_HELPER_FLAGS_3(mve_vqmovunth, TCG_CALL_NO_WG, void, env, ptr, ptr)
32
+
33
+DEF_HELPER_FLAGS_3(mve_vqmovnbsb, TCG_CALL_NO_WG, void, env, ptr, ptr)
34
+DEF_HELPER_FLAGS_3(mve_vqmovnbsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
35
+DEF_HELPER_FLAGS_3(mve_vqmovntsb, TCG_CALL_NO_WG, void, env, ptr, ptr)
36
+DEF_HELPER_FLAGS_3(mve_vqmovntsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
37
+
38
+DEF_HELPER_FLAGS_3(mve_vqmovnbub, TCG_CALL_NO_WG, void, env, ptr, ptr)
39
+DEF_HELPER_FLAGS_3(mve_vqmovnbuh, TCG_CALL_NO_WG, void, env, ptr, ptr)
40
+DEF_HELPER_FLAGS_3(mve_vqmovntub, TCG_CALL_NO_WG, void, env, ptr, ptr)
41
+DEF_HELPER_FLAGS_3(mve_vqmovntuh, TCG_CALL_NO_WG, void, env, ptr, ptr)
42
+
43
DEF_HELPER_FLAGS_4(mve_vand, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
44
DEF_HELPER_FLAGS_4(mve_vbic, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
45
DEF_HELPER_FLAGS_4(mve_vorr, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
46
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
47
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/mve.decode
49
+++ b/target/arm/mve.decode
50
@@ -XXX,XX +XXX,XX @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
51
VSHLL_BS 111 0 1110 0 . 11 .. 01 ... 0 1110 0 0 . 0 ... 1 @2_shll_esize_b
52
VSHLL_BS 111 0 1110 0 . 11 .. 01 ... 0 1110 0 0 . 0 ... 1 @2_shll_esize_h
53
54
+ VQMOVUNB 111 0 1110 0 . 11 .. 01 ... 0 1110 1 0 . 0 ... 1 @1op
55
+ VQMOVN_BS 111 0 1110 0 . 11 .. 11 ... 0 1110 0 0 . 0 ... 1 @1op
56
+
57
VMULH_S 111 0 1110 0 . .. ...1 ... 0 1110 . 0 . 0 ... 1 @2op
58
}
59
60
@@ -XXX,XX +XXX,XX @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
61
VSHLL_BU 111 1 1110 0 . 11 .. 01 ... 0 1110 0 0 . 0 ... 1 @2_shll_esize_b
62
VSHLL_BU 111 1 1110 0 . 11 .. 01 ... 0 1110 0 0 . 0 ... 1 @2_shll_esize_h
63
64
+ VMOVNB 111 1 1110 0 . 11 .. 01 ... 0 1110 1 0 . 0 ... 1 @1op
65
+ VQMOVN_BU 111 1 1110 0 . 11 .. 11 ... 0 1110 0 0 . 0 ... 1 @1op
66
+
67
VMULH_U 111 1 1110 0 . .. ...1 ... 0 1110 . 0 . 0 ... 1 @2op
68
}
69
70
@@ -XXX,XX +XXX,XX @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
71
VSHLL_TS 111 0 1110 0 . 11 .. 01 ... 1 1110 0 0 . 0 ... 1 @2_shll_esize_b
72
VSHLL_TS 111 0 1110 0 . 11 .. 01 ... 1 1110 0 0 . 0 ... 1 @2_shll_esize_h
73
74
+ VQMOVUNT 111 0 1110 0 . 11 .. 01 ... 1 1110 1 0 . 0 ... 1 @1op
75
+ VQMOVN_TS 111 0 1110 0 . 11 .. 11 ... 1 1110 0 0 . 0 ... 1 @1op
76
+
77
VRMULH_S 111 0 1110 0 . .. ...1 ... 1 1110 . 0 . 0 ... 1 @2op
78
}
79
80
@@ -XXX,XX +XXX,XX @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
81
VSHLL_TU 111 1 1110 0 . 11 .. 01 ... 1 1110 0 0 . 0 ... 1 @2_shll_esize_b
82
VSHLL_TU 111 1 1110 0 . 11 .. 01 ... 1 1110 0 0 . 0 ... 1 @2_shll_esize_h
83
84
+ VMOVNT 111 1 1110 0 . 11 .. 01 ... 1 1110 1 0 . 0 ... 1 @1op
85
+ VQMOVN_TU 111 1 1110 0 . 11 .. 11 ... 1 1110 0 0 . 0 ... 1 @1op
86
+
87
VRMULH_U 111 1 1110 0 . .. ...1 ... 1 1110 . 0 . 0 ... 1 @2op
88
}
89
90
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
91
index XXXXXXX..XXXXXXX 100644
92
--- a/target/arm/mve_helper.c
93
+++ b/target/arm/mve_helper.c
94
@@ -XXX,XX +XXX,XX @@ DO_VSHRN_SAT_UH(vqrshrnb_uh, vqrshrnt_uh, DO_RSHRN_UH)
95
DO_VSHRN_SAT_SB(vqrshrunbb, vqrshruntb, DO_RSHRUN_B)
96
DO_VSHRN_SAT_SH(vqrshrunbh, vqrshrunth, DO_RSHRUN_H)
97
98
+#define DO_VMOVN(OP, TOP, ESIZE, TYPE, LESIZE, LTYPE) \
99
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm) \
100
+ { \
101
+ LTYPE *m = vm; \
102
+ TYPE *d = vd; \
103
+ uint16_t mask = mve_element_mask(env); \
104
+ unsigned le; \
105
+ mask >>= ESIZE * TOP; \
106
+ for (le = 0; le < 16 / LESIZE; le++, mask >>= LESIZE) { \
107
+ mergemask(&d[H##ESIZE(le * 2 + TOP)], \
108
+ m[H##LESIZE(le)], mask); \
109
+ } \
110
+ mve_advance_vpt(env); \
111
+ }
112
+
113
+DO_VMOVN(vmovnbb, false, 1, uint8_t, 2, uint16_t)
114
+DO_VMOVN(vmovnbh, false, 2, uint16_t, 4, uint32_t)
115
+DO_VMOVN(vmovntb, true, 1, uint8_t, 2, uint16_t)
116
+DO_VMOVN(vmovnth, true, 2, uint16_t, 4, uint32_t)
117
+
118
+#define DO_VMOVN_SAT(OP, TOP, ESIZE, TYPE, LESIZE, LTYPE, FN) \
119
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm) \
120
+ { \
121
+ LTYPE *m = vm; \
122
+ TYPE *d = vd; \
123
+ uint16_t mask = mve_element_mask(env); \
124
+ bool qc = false; \
125
+ unsigned le; \
126
+ mask >>= ESIZE * TOP; \
127
+ for (le = 0; le < 16 / LESIZE; le++, mask >>= LESIZE) { \
128
+ bool sat = false; \
129
+ TYPE r = FN(m[H##LESIZE(le)], &sat); \
130
+ mergemask(&d[H##ESIZE(le * 2 + TOP)], r, mask); \
131
+ qc |= sat & mask & 1; \
132
+ } \
133
+ if (qc) { \
134
+ env->vfp.qc[0] = qc; \
135
+ } \
136
+ mve_advance_vpt(env); \
137
+ }
138
+
139
+#define DO_VMOVN_SAT_UB(BOP, TOP, FN) \
140
+ DO_VMOVN_SAT(BOP, false, 1, uint8_t, 2, uint16_t, FN) \
141
+ DO_VMOVN_SAT(TOP, true, 1, uint8_t, 2, uint16_t, FN)
142
+
143
+#define DO_VMOVN_SAT_UH(BOP, TOP, FN) \
144
+ DO_VMOVN_SAT(BOP, false, 2, uint16_t, 4, uint32_t, FN) \
145
+ DO_VMOVN_SAT(TOP, true, 2, uint16_t, 4, uint32_t, FN)
146
+
147
+#define DO_VMOVN_SAT_SB(BOP, TOP, FN) \
148
+ DO_VMOVN_SAT(BOP, false, 1, int8_t, 2, int16_t, FN) \
149
+ DO_VMOVN_SAT(TOP, true, 1, int8_t, 2, int16_t, FN)
150
+
151
+#define DO_VMOVN_SAT_SH(BOP, TOP, FN) \
152
+ DO_VMOVN_SAT(BOP, false, 2, int16_t, 4, int32_t, FN) \
153
+ DO_VMOVN_SAT(TOP, true, 2, int16_t, 4, int32_t, FN)
154
+
155
+#define DO_VQMOVN_SB(N, SATP) \
156
+ do_sat_bhs((int64_t)(N), INT8_MIN, INT8_MAX, SATP)
157
+#define DO_VQMOVN_UB(N, SATP) \
158
+ do_sat_bhs((uint64_t)(N), 0, UINT8_MAX, SATP)
159
+#define DO_VQMOVUN_B(N, SATP) \
160
+ do_sat_bhs((int64_t)(N), 0, UINT8_MAX, SATP)
161
+
162
+#define DO_VQMOVN_SH(N, SATP) \
163
+ do_sat_bhs((int64_t)(N), INT16_MIN, INT16_MAX, SATP)
164
+#define DO_VQMOVN_UH(N, SATP) \
165
+ do_sat_bhs((uint64_t)(N), 0, UINT16_MAX, SATP)
166
+#define DO_VQMOVUN_H(N, SATP) \
167
+ do_sat_bhs((int64_t)(N), 0, UINT16_MAX, SATP)
168
+
169
+DO_VMOVN_SAT_SB(vqmovnbsb, vqmovntsb, DO_VQMOVN_SB)
170
+DO_VMOVN_SAT_SH(vqmovnbsh, vqmovntsh, DO_VQMOVN_SH)
171
+DO_VMOVN_SAT_UB(vqmovnbub, vqmovntub, DO_VQMOVN_UB)
172
+DO_VMOVN_SAT_UH(vqmovnbuh, vqmovntuh, DO_VQMOVN_UH)
173
+DO_VMOVN_SAT_SB(vqmovunbb, vqmovuntb, DO_VQMOVUN_B)
174
+DO_VMOVN_SAT_SH(vqmovunbh, vqmovunth, DO_VQMOVUN_H)
175
+
176
uint32_t HELPER(mve_vshlc)(CPUARMState *env, void *vd, uint32_t rdm,
177
uint32_t shift)
178
{
179
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
180
index XXXXXXX..XXXXXXX 100644
181
--- a/target/arm/translate-mve.c
182
+++ b/target/arm/translate-mve.c
183
@@ -XXX,XX +XXX,XX @@ DO_1OP(VCLS, vcls)
184
DO_1OP(VABS, vabs)
185
DO_1OP(VNEG, vneg)
186
187
+/* Narrowing moves: only size 0 and 1 are valid */
188
+#define DO_VMOVN(INSN, FN) \
189
+ static bool trans_##INSN(DisasContext *s, arg_1op *a) \
190
+ { \
191
+ static MVEGenOneOpFn * const fns[] = { \
192
+ gen_helper_mve_##FN##b, \
193
+ gen_helper_mve_##FN##h, \
194
+ NULL, \
195
+ NULL, \
196
+ }; \
197
+ return do_1op(s, a, fns[a->size]); \
198
+ }
199
+
200
+DO_VMOVN(VMOVNB, vmovnb)
201
+DO_VMOVN(VMOVNT, vmovnt)
202
+DO_VMOVN(VQMOVUNB, vqmovunb)
203
+DO_VMOVN(VQMOVUNT, vqmovunt)
204
+DO_VMOVN(VQMOVN_BS, vqmovnbs)
205
+DO_VMOVN(VQMOVN_TS, vqmovnts)
206
+DO_VMOVN(VQMOVN_BU, vqmovnbu)
207
+DO_VMOVN(VQMOVN_TU, vqmovntu)
208
+
209
static bool trans_VREV16(DisasContext *s, arg_1op *a)
210
{
211
static MVEGenOneOpFn * const fns[] = {
212
--
213
2.20.1
214
215
diff view generated by jsdifflib
1
Convert the remaining Neon narrowing shifts to decodetree:
1
The MVEGenDualAccOpFn is a bit misnamed, since it is used for
2
* VQSHRN
2
the "long dual accumulate" operations that use a 64-bit
3
* VQRSHRN
3
accumulator. Rename it to MVEGenLongDualAccOpFn so we can
4
use the former name for the 32-bit accumulator insns.
4
5
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200522145520.6778-7-peter.maydell@linaro.org
8
---
8
---
9
target/arm/neon-dp.decode | 20 ++++++
9
target/arm/translate-mve.c | 16 ++++++++--------
10
target/arm/translate-neon.inc.c | 15 +++++
10
1 file changed, 8 insertions(+), 8 deletions(-)
11
target/arm/translate.c | 110 +-------------------------------
12
3 files changed, 37 insertions(+), 108 deletions(-)
13
11
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
12
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
15
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
16
--- a/target/arm/neon-dp.decode
14
--- a/target/arm/translate-mve.c
17
+++ b/target/arm/neon-dp.decode
15
+++ b/target/arm/translate-mve.c
18
@@ -XXX,XX +XXX,XX @@ VQSHRUN_16_2sh 1111 001 1 1 . ...... .... 1000 . 0 . 1 .... @2reg_shrn_h
16
@@ -XXX,XX +XXX,XX @@ typedef void MVEGenOneOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
19
VQRSHRUN_64_2sh 1111 001 1 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_d
17
typedef void MVEGenTwoOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr);
20
VQRSHRUN_32_2sh 1111 001 1 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_s
18
typedef void MVEGenTwoOpScalarFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
21
VQRSHRUN_16_2sh 1111 001 1 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_h
19
typedef void MVEGenTwoOpShiftFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
22
+
20
-typedef void MVEGenDualAccOpFn(TCGv_i64, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i64);
23
+# VQSHRN with signed input
21
+typedef void MVEGenLongDualAccOpFn(TCGv_i64, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i64);
24
+VQSHRN_S64_2sh 1111 001 0 1 . ...... .... 1001 . 0 . 1 .... @2reg_shrn_d
22
typedef void MVEGenVADDVFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32);
25
+VQSHRN_S32_2sh 1111 001 0 1 . ...... .... 1001 . 0 . 1 .... @2reg_shrn_s
23
typedef void MVEGenOneOpImmFn(TCGv_ptr, TCGv_ptr, TCGv_i64);
26
+VQSHRN_S16_2sh 1111 001 0 1 . ...... .... 1001 . 0 . 1 .... @2reg_shrn_h
24
typedef void MVEGenVIDUPFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32, TCGv_i32);
27
+
25
@@ -XXX,XX +XXX,XX @@ static bool trans_VQDMULLT_scalar(DisasContext *s, arg_2scalar *a)
28
+# VQRSHRN with signed input
29
+VQRSHRN_S64_2sh 1111 001 0 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_d
30
+VQRSHRN_S32_2sh 1111 001 0 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_s
31
+VQRSHRN_S16_2sh 1111 001 0 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_h
32
+
33
+# VQSHRN with unsigned input
34
+VQSHRN_U64_2sh 1111 001 1 1 . ...... .... 1001 . 0 . 1 .... @2reg_shrn_d
35
+VQSHRN_U32_2sh 1111 001 1 1 . ...... .... 1001 . 0 . 1 .... @2reg_shrn_s
36
+VQSHRN_U16_2sh 1111 001 1 1 . ...... .... 1001 . 0 . 1 .... @2reg_shrn_h
37
+
38
+# VQRSHRN with unsigned input
39
+VQRSHRN_U64_2sh 1111 001 1 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_d
40
+VQRSHRN_U32_2sh 1111 001 1 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_s
41
+VQRSHRN_U16_2sh 1111 001 1 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_h
42
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/translate-neon.inc.c
45
+++ b/target/arm/translate-neon.inc.c
46
@@ -XXX,XX +XXX,XX @@ DO_2SN_32(VQSHRUN_16, gen_helper_neon_shl_s16, gen_helper_neon_unarrow_sat8)
47
DO_2SN_64(VQRSHRUN_64, gen_helper_neon_rshl_s64, gen_helper_neon_unarrow_sat32)
48
DO_2SN_32(VQRSHRUN_32, gen_helper_neon_rshl_s32, gen_helper_neon_unarrow_sat16)
49
DO_2SN_32(VQRSHRUN_16, gen_helper_neon_rshl_s16, gen_helper_neon_unarrow_sat8)
50
+DO_2SN_64(VQSHRN_S64, gen_sshl_i64, gen_helper_neon_narrow_sat_s32)
51
+DO_2SN_32(VQSHRN_S32, gen_sshl_i32, gen_helper_neon_narrow_sat_s16)
52
+DO_2SN_32(VQSHRN_S16, gen_helper_neon_shl_s16, gen_helper_neon_narrow_sat_s8)
53
+
54
+DO_2SN_64(VQRSHRN_S64, gen_helper_neon_rshl_s64, gen_helper_neon_narrow_sat_s32)
55
+DO_2SN_32(VQRSHRN_S32, gen_helper_neon_rshl_s32, gen_helper_neon_narrow_sat_s16)
56
+DO_2SN_32(VQRSHRN_S16, gen_helper_neon_rshl_s16, gen_helper_neon_narrow_sat_s8)
57
+
58
+DO_2SN_64(VQSHRN_U64, gen_ushl_i64, gen_helper_neon_narrow_sat_u32)
59
+DO_2SN_32(VQSHRN_U32, gen_ushl_i32, gen_helper_neon_narrow_sat_u16)
60
+DO_2SN_32(VQSHRN_U16, gen_helper_neon_shl_u16, gen_helper_neon_narrow_sat_u8)
61
+
62
+DO_2SN_64(VQRSHRN_U64, gen_helper_neon_rshl_u64, gen_helper_neon_narrow_sat_u32)
63
+DO_2SN_32(VQRSHRN_U32, gen_helper_neon_rshl_u32, gen_helper_neon_narrow_sat_u16)
64
+DO_2SN_32(VQRSHRN_U16, gen_helper_neon_rshl_u16, gen_helper_neon_narrow_sat_u8)
65
diff --git a/target/arm/translate.c b/target/arm/translate.c
66
index XXXXXXX..XXXXXXX 100644
67
--- a/target/arm/translate.c
68
+++ b/target/arm/translate.c
69
@@ -XXX,XX +XXX,XX @@ static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
70
}
71
}
26
}
72
27
73
-static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
28
static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
74
- int q, int u)
29
- MVEGenDualAccOpFn *fn)
75
-{
30
+ MVEGenLongDualAccOpFn *fn)
76
- if (q) {
77
- if (u) {
78
- switch (size) {
79
- case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
80
- case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
81
- default: abort();
82
- }
83
- } else {
84
- switch (size) {
85
- case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
86
- case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
87
- default: abort();
88
- }
89
- }
90
- } else {
91
- if (u) {
92
- switch (size) {
93
- case 1: gen_helper_neon_shl_u16(var, var, shift); break;
94
- case 2: gen_ushl_i32(var, var, shift); break;
95
- default: abort();
96
- }
97
- } else {
98
- switch (size) {
99
- case 1: gen_helper_neon_shl_s16(var, var, shift); break;
100
- case 2: gen_sshl_i32(var, var, shift); break;
101
- default: abort();
102
- }
103
- }
104
- }
105
-}
106
-
107
static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
108
{
31
{
109
if (u) {
32
TCGv_ptr qn, qm;
110
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
33
TCGv_i64 rda;
111
case 6: /* VQSHLU */
34
@@ -XXX,XX +XXX,XX @@ static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
112
case 7: /* VQSHL */
35
113
case 8: /* VSHRN, VRSHRN, VQSHRUN, VQRSHRUN */
36
static bool trans_VMLALDAV_S(DisasContext *s, arg_vmlaldav *a)
114
+ case 9: /* VQSHRN, VQRSHRN */
37
{
115
return 1; /* handled by decodetree */
38
- static MVEGenDualAccOpFn * const fns[4][2] = {
116
default:
39
+ static MVEGenLongDualAccOpFn * const fns[4][2] = {
117
break;
40
{ NULL, NULL },
118
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
41
{ gen_helper_mve_vmlaldavsh, gen_helper_mve_vmlaldavxsh },
119
size--;
42
{ gen_helper_mve_vmlaldavsw, gen_helper_mve_vmlaldavxsw },
120
}
43
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLALDAV_S(DisasContext *s, arg_vmlaldav *a)
121
shift = (insn >> 16) & ((1 << (3 + size)) - 1);
44
122
- if (op < 10) {
45
static bool trans_VMLALDAV_U(DisasContext *s, arg_vmlaldav *a)
123
- /* Shift by immediate and narrow:
46
{
124
- VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
47
- static MVEGenDualAccOpFn * const fns[4][2] = {
125
- int input_unsigned = (op == 8) ? !u : u;
48
+ static MVEGenLongDualAccOpFn * const fns[4][2] = {
126
- if (rm & 1) {
49
{ NULL, NULL },
127
- return 1;
50
{ gen_helper_mve_vmlaldavuh, NULL },
128
- }
51
{ gen_helper_mve_vmlaldavuw, NULL },
129
- shift = shift - (1 << (size + 3));
52
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLALDAV_U(DisasContext *s, arg_vmlaldav *a)
130
- size++;
53
131
- if (size == 3) {
54
static bool trans_VMLSLDAV(DisasContext *s, arg_vmlaldav *a)
132
- tmp64 = tcg_const_i64(shift);
55
{
133
- neon_load_reg64(cpu_V0, rm);
56
- static MVEGenDualAccOpFn * const fns[4][2] = {
134
- neon_load_reg64(cpu_V1, rm + 1);
57
+ static MVEGenLongDualAccOpFn * const fns[4][2] = {
135
- for (pass = 0; pass < 2; pass++) {
58
{ NULL, NULL },
136
- TCGv_i64 in;
59
{ gen_helper_mve_vmlsldavsh, gen_helper_mve_vmlsldavxsh },
137
- if (pass == 0) {
60
{ gen_helper_mve_vmlsldavsw, gen_helper_mve_vmlsldavxsw },
138
- in = cpu_V0;
61
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLSLDAV(DisasContext *s, arg_vmlaldav *a)
139
- } else {
62
140
- in = cpu_V1;
63
static bool trans_VRMLALDAVH_S(DisasContext *s, arg_vmlaldav *a)
141
- }
64
{
142
- if (q) {
65
- static MVEGenDualAccOpFn * const fns[] = {
143
- if (input_unsigned) {
66
+ static MVEGenLongDualAccOpFn * const fns[] = {
144
- gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
67
gen_helper_mve_vrmlaldavhsw, gen_helper_mve_vrmlaldavhxsw,
145
- } else {
68
};
146
- gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
69
return do_long_dual_acc(s, a, fns[a->x]);
147
- }
70
@@ -XXX,XX +XXX,XX @@ static bool trans_VRMLALDAVH_S(DisasContext *s, arg_vmlaldav *a)
148
- } else {
71
149
- if (input_unsigned) {
72
static bool trans_VRMLALDAVH_U(DisasContext *s, arg_vmlaldav *a)
150
- gen_ushl_i64(cpu_V0, in, tmp64);
73
{
151
- } else {
74
- static MVEGenDualAccOpFn * const fns[] = {
152
- gen_sshl_i64(cpu_V0, in, tmp64);
75
+ static MVEGenLongDualAccOpFn * const fns[] = {
153
- }
76
gen_helper_mve_vrmlaldavhuw, NULL,
154
- }
77
};
155
- tmp = tcg_temp_new_i32();
78
return do_long_dual_acc(s, a, fns[a->x]);
156
- gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
79
@@ -XXX,XX +XXX,XX @@ static bool trans_VRMLALDAVH_U(DisasContext *s, arg_vmlaldav *a)
157
- neon_store_reg(rd, pass, tmp);
80
158
- } /* for pass */
81
static bool trans_VRMLSLDAVH(DisasContext *s, arg_vmlaldav *a)
159
- tcg_temp_free_i64(tmp64);
82
{
160
- } else {
83
- static MVEGenDualAccOpFn * const fns[] = {
161
- if (size == 1) {
84
+ static MVEGenLongDualAccOpFn * const fns[] = {
162
- imm = (uint16_t)shift;
85
gen_helper_mve_vrmlsldavhsw, gen_helper_mve_vrmlsldavhxsw,
163
- imm |= imm << 16;
86
};
164
- } else {
87
return do_long_dual_acc(s, a, fns[a->x]);
165
- /* size == 2 */
166
- imm = (uint32_t)shift;
167
- }
168
- tmp2 = tcg_const_i32(imm);
169
- tmp4 = neon_load_reg(rm + 1, 0);
170
- tmp5 = neon_load_reg(rm + 1, 1);
171
- for (pass = 0; pass < 2; pass++) {
172
- if (pass == 0) {
173
- tmp = neon_load_reg(rm, 0);
174
- } else {
175
- tmp = tmp4;
176
- }
177
- gen_neon_shift_narrow(size, tmp, tmp2, q,
178
- input_unsigned);
179
- if (pass == 0) {
180
- tmp3 = neon_load_reg(rm, 1);
181
- } else {
182
- tmp3 = tmp5;
183
- }
184
- gen_neon_shift_narrow(size, tmp3, tmp2, q,
185
- input_unsigned);
186
- tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
187
- tcg_temp_free_i32(tmp);
188
- tcg_temp_free_i32(tmp3);
189
- tmp = tcg_temp_new_i32();
190
- gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
191
- neon_store_reg(rd, pass, tmp);
192
- } /* for pass */
193
- tcg_temp_free_i32(tmp2);
194
- }
195
- } else if (op == 10) {
196
+ if (op == 10) {
197
/* VSHLL, VMOVL */
198
if (q || (rd & 1)) {
199
return 1;
200
--
88
--
201
2.20.1
89
2.20.1
202
90
203
91
diff view generated by jsdifflib
1
Convert the VSHLL and VMOVL insns from the 2-reg-shift group
1
Implement the MVE VMLADAV and VMLSLDAV insns. Like the VMLALDAV and
2
to decodetree. Since the loop always has two passes, we unroll
2
VMLSLDAV insns already implemented, these accumulate multiplied
3
it to avoid the awkward reassignment of one TCGv to another.
3
vector elements; but they accumulate a 32-bit result rather than a
4
64-bit one.
5
6
Note that these encodings overlap with what would be RdaHi=0b111 for
7
VMLALDAV, VMLSLDAV, VRMLALDAVH and VRMLSLDAVH.
4
8
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20200522145520.6778-8-peter.maydell@linaro.org
8
---
11
---
9
target/arm/neon-dp.decode | 16 +++++++
12
target/arm/helper-mve.h | 17 ++++++++++
10
target/arm/translate-neon.inc.c | 81 +++++++++++++++++++++++++++++++++
13
target/arm/mve.decode | 33 +++++++++++++++++---
11
target/arm/translate.c | 46 +------------------
14
target/arm/mve_helper.c | 41 ++++++++++++++++++++++++
12
3 files changed, 99 insertions(+), 44 deletions(-)
15
target/arm/translate-mve.c | 64 ++++++++++++++++++++++++++++++++++++++
13
16
4 files changed, 150 insertions(+), 5 deletions(-)
14
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
17
15
index XXXXXXX..XXXXXXX 100644
18
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
16
--- a/target/arm/neon-dp.decode
19
index XXXXXXX..XXXXXXX 100644
17
+++ b/target/arm/neon-dp.decode
20
--- a/target/arm/helper-mve.h
18
@@ -XXX,XX +XXX,XX @@ VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
21
+++ b/target/arm/helper-mve.h
19
&2reg_shift vm=%vm_dp vd=%vd_dp size=1 q=0 \
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vrmlaldavhuw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
20
shift=%neon_rshift_i3
23
DEF_HELPER_FLAGS_4(mve_vrmlsldavhsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
21
24
DEF_HELPER_FLAGS_4(mve_vrmlsldavhxsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
22
+# Long left shifts: again Q is part of opcode decode
25
23
+@2reg_shll_s .... ... . . . 1 shift:5 .... .... 0 . . . .... \
26
+DEF_HELPER_FLAGS_4(mve_vmladavsb, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
24
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=2 q=0
27
+DEF_HELPER_FLAGS_4(mve_vmladavsh, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
25
+@2reg_shll_h .... ... . . . 01 shift:4 .... .... 0 . . . .... \
28
+DEF_HELPER_FLAGS_4(mve_vmladavsw, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
26
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=1 q=0
29
+DEF_HELPER_FLAGS_4(mve_vmladavub, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
27
+@2reg_shll_b .... ... . . . 001 shift:3 .... .... 0 . . . .... \
30
+DEF_HELPER_FLAGS_4(mve_vmladavuh, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
28
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=0 q=0
31
+DEF_HELPER_FLAGS_4(mve_vmladavuw, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
29
+
32
+DEF_HELPER_FLAGS_4(mve_vmlsdavb, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
30
VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_d
33
+DEF_HELPER_FLAGS_4(mve_vmlsdavh, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
31
VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_s
34
+DEF_HELPER_FLAGS_4(mve_vmlsdavw, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
32
VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_h
35
+
33
@@ -XXX,XX +XXX,XX @@ VQSHRN_U16_2sh 1111 001 1 1 . ...... .... 1001 . 0 . 1 .... @2reg_shrn_h
36
+DEF_HELPER_FLAGS_4(mve_vmladavsxb, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
34
VQRSHRN_U64_2sh 1111 001 1 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_d
37
+DEF_HELPER_FLAGS_4(mve_vmladavsxh, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
35
VQRSHRN_U32_2sh 1111 001 1 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_s
38
+DEF_HELPER_FLAGS_4(mve_vmladavsxw, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
36
VQRSHRN_U16_2sh 1111 001 1 1 . ...... .... 1001 . 1 . 1 .... @2reg_shrn_h
39
+DEF_HELPER_FLAGS_4(mve_vmlsdavxb, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
37
+
40
+DEF_HELPER_FLAGS_4(mve_vmlsdavxh, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
38
+VSHLL_S_2sh 1111 001 0 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_s
41
+DEF_HELPER_FLAGS_4(mve_vmlsdavxw, TCG_CALL_NO_WG, i32, env, ptr, ptr, i32)
39
+VSHLL_S_2sh 1111 001 0 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_h
42
+
40
+VSHLL_S_2sh 1111 001 0 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_b
43
DEF_HELPER_FLAGS_3(mve_vaddvsb, TCG_CALL_NO_WG, i32, env, ptr, i32)
41
+
44
DEF_HELPER_FLAGS_3(mve_vaddvub, TCG_CALL_NO_WG, i32, env, ptr, i32)
42
+VSHLL_U_2sh 1111 001 1 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_s
45
DEF_HELPER_FLAGS_3(mve_vaddvsh, TCG_CALL_NO_WG, i32, env, ptr, i32)
43
+VSHLL_U_2sh 1111 001 1 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_h
46
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
44
+VSHLL_U_2sh 1111 001 1 1 . ...... .... 1010 . 0 . 1 .... @2reg_shll_b
47
index XXXXXXX..XXXXXXX 100644
45
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
48
--- a/target/arm/mve.decode
46
index XXXXXXX..XXXXXXX 100644
49
+++ b/target/arm/mve.decode
47
--- a/target/arm/translate-neon.inc.c
50
@@ -XXX,XX +XXX,XX @@ VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=2
48
+++ b/target/arm/translate-neon.inc.c
51
%size_16 16:1 !function=plus_1
49
@@ -XXX,XX +XXX,XX @@ DO_2SN_32(VQSHRN_U16, gen_helper_neon_shl_u16, gen_helper_neon_narrow_sat_u8)
52
50
DO_2SN_64(VQRSHRN_U64, gen_helper_neon_rshl_u64, gen_helper_neon_narrow_sat_u32)
53
&vmlaldav rdahi rdalo size qn qm x a
51
DO_2SN_32(VQRSHRN_U32, gen_helper_neon_rshl_u32, gen_helper_neon_narrow_sat_u16)
54
+&vmladav rda size qn qm x a
52
DO_2SN_32(VQRSHRN_U16, gen_helper_neon_rshl_u16, gen_helper_neon_narrow_sat_u8)
55
53
+
56
@vmlaldav .... .... . ... ... . ... x:1 .... .. a:1 . qm:3 . \
54
+static bool do_vshll_2sh(DisasContext *s, arg_2reg_shift *a,
57
qn=%qn rdahi=%rdahi rdalo=%rdalo size=%size_16 &vmlaldav
55
+ NeonGenWidenFn *widenfn, bool u)
58
@vmlaldav_nosz .... .... . ... ... . ... x:1 .... .. a:1 . qm:3 . \
56
+{
59
qn=%qn rdahi=%rdahi rdalo=%rdalo size=0 &vmlaldav
57
+ TCGv_i64 tmp;
60
-VMLALDAV_S 1110 1110 1 ... ... . ... . 1110 . 0 . 0 ... 0 @vmlaldav
58
+ TCGv_i32 rm0, rm1;
61
-VMLALDAV_U 1111 1110 1 ... ... . ... . 1110 . 0 . 0 ... 0 @vmlaldav
59
+ uint64_t widen_mask = 0;
62
+@vmladav .... .... .... ... . ... x:1 .... . . a:1 . qm:3 . \
60
+
63
+ qn=%qn rda=%rdalo size=%size_16 &vmladav
61
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
64
+@vmladav_nosz .... .... .... ... . ... x:1 .... . . a:1 . qm:3 . \
65
+ qn=%qn rda=%rdalo size=0 &vmladav
66
67
-VMLSLDAV 1110 1110 1 ... ... . ... . 1110 . 0 . 0 ... 1 @vmlaldav
68
+{
69
+ VMLADAV_S 1110 1110 1111 ... . ... . 1110 . 0 . 0 ... 0 @vmladav
70
+ VMLALDAV_S 1110 1110 1 ... ... . ... . 1110 . 0 . 0 ... 0 @vmlaldav
71
+}
72
+{
73
+ VMLADAV_U 1111 1110 1111 ... . ... . 1110 . 0 . 0 ... 0 @vmladav
74
+ VMLALDAV_U 1111 1110 1 ... ... . ... . 1110 . 0 . 0 ... 0 @vmlaldav
75
+}
76
+
77
+{
78
+ VMLSDAV 1110 1110 1111 ... . ... . 1110 . 0 . 0 ... 1 @vmladav
79
+ VMLSLDAV 1110 1110 1 ... ... . ... . 1110 . 0 . 0 ... 1 @vmlaldav
80
+}
81
+
82
+{
83
+ VMLSDAV 1111 1110 1111 ... 0 ... . 1110 . 0 . 0 ... 1 @vmladav_nosz
84
+ VRMLSLDAVH 1111 1110 1 ... ... 0 ... . 1110 . 0 . 0 ... 1 @vmlaldav_nosz
85
+}
86
+
87
+VMLADAV_S 1110 1110 1111 ... 0 ... . 1111 . 0 . 0 ... 1 @vmladav_nosz
88
+VMLADAV_U 1111 1110 1111 ... 0 ... . 1111 . 0 . 0 ... 1 @vmladav_nosz
89
90
{
91
VMAXV_S 1110 1110 1110 .. 10 .... 1111 0 0 . 0 ... 0 @vmaxv
92
VMINV_S 1110 1110 1110 .. 10 .... 1111 1 0 . 0 ... 0 @vmaxv
93
VMAXAV 1110 1110 1110 .. 00 .... 1111 0 0 . 0 ... 0 @vmaxv
94
VMINAV 1110 1110 1110 .. 00 .... 1111 1 0 . 0 ... 0 @vmaxv
95
+ VMLADAV_S 1110 1110 1111 ... 0 ... . 1111 . 0 . 0 ... 0 @vmladav_nosz
96
VRMLALDAVH_S 1110 1110 1 ... ... 0 ... . 1111 . 0 . 0 ... 0 @vmlaldav_nosz
97
}
98
99
{
100
VMAXV_U 1111 1110 1110 .. 10 .... 1111 0 0 . 0 ... 0 @vmaxv
101
VMINV_U 1111 1110 1110 .. 10 .... 1111 1 0 . 0 ... 0 @vmaxv
102
+ VMLADAV_U 1111 1110 1111 ... 0 ... . 1111 . 0 . 0 ... 0 @vmladav_nosz
103
VRMLALDAVH_U 1111 1110 1 ... ... 0 ... . 1111 . 0 . 0 ... 0 @vmlaldav_nosz
104
}
105
106
-VRMLSLDAVH 1111 1110 1 ... ... 0 ... . 1110 . 0 . 0 ... 1 @vmlaldav_nosz
107
-
108
# Scalar operations
109
110
VADD_scalar 1110 1110 0 . .. ... 1 ... 0 1111 . 100 .... @2scalar
111
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
112
index XXXXXXX..XXXXXXX 100644
113
--- a/target/arm/mve_helper.c
114
+++ b/target/arm/mve_helper.c
115
@@ -XXX,XX +XXX,XX @@ DO_LDAV(vmlsldavxsh, 2, int16_t, true, +=, -=)
116
DO_LDAV(vmlsldavsw, 4, int32_t, false, +=, -=)
117
DO_LDAV(vmlsldavxsw, 4, int32_t, true, +=, -=)
118
119
+/*
120
+ * Multiply add dual accumulate ops
121
+ */
122
+#define DO_DAV(OP, ESIZE, TYPE, XCHG, EVENACC, ODDACC) \
123
+ uint32_t HELPER(glue(mve_, OP))(CPUARMState *env, void *vn, \
124
+ void *vm, uint32_t a) \
125
+ { \
126
+ uint16_t mask = mve_element_mask(env); \
127
+ unsigned e; \
128
+ TYPE *n = vn, *m = vm; \
129
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
130
+ if (mask & 1) { \
131
+ if (e & 1) { \
132
+ a ODDACC \
133
+ n[H##ESIZE(e - 1 * XCHG)] * m[H##ESIZE(e)]; \
134
+ } else { \
135
+ a EVENACC \
136
+ n[H##ESIZE(e + 1 * XCHG)] * m[H##ESIZE(e)]; \
137
+ } \
138
+ } \
139
+ } \
140
+ mve_advance_vpt(env); \
141
+ return a; \
142
+ }
143
+
144
+#define DO_DAV_S(INSN, XCHG, EVENACC, ODDACC) \
145
+ DO_DAV(INSN##b, 1, int8_t, XCHG, EVENACC, ODDACC) \
146
+ DO_DAV(INSN##h, 2, int16_t, XCHG, EVENACC, ODDACC) \
147
+ DO_DAV(INSN##w, 4, int32_t, XCHG, EVENACC, ODDACC)
148
+
149
+#define DO_DAV_U(INSN, XCHG, EVENACC, ODDACC) \
150
+ DO_DAV(INSN##b, 1, uint8_t, XCHG, EVENACC, ODDACC) \
151
+ DO_DAV(INSN##h, 2, uint16_t, XCHG, EVENACC, ODDACC) \
152
+ DO_DAV(INSN##w, 4, uint32_t, XCHG, EVENACC, ODDACC)
153
+
154
+DO_DAV_S(vmladavs, false, +=, +=)
155
+DO_DAV_U(vmladavu, false, +=, +=)
156
+DO_DAV_S(vmlsdav, false, +=, -=)
157
+DO_DAV_S(vmladavsx, true, +=, +=)
158
+DO_DAV_S(vmlsdavx, true, +=, -=)
159
+
160
/*
161
* Rounding multiply add long dual accumulate high. In the pseudocode
162
* this is implemented with a 72-bit internal accumulator value of which
163
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
164
index XXXXXXX..XXXXXXX 100644
165
--- a/target/arm/translate-mve.c
166
+++ b/target/arm/translate-mve.c
167
@@ -XXX,XX +XXX,XX @@ typedef void MVEGenVIWDUPFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32, TCGv_i32, TC
168
typedef void MVEGenCmpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
169
typedef void MVEGenScalarCmpFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
170
typedef void MVEGenVABAVFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
171
+typedef void MVEGenDualAccOpFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
172
173
/* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
174
static inline long mve_qreg_offset(unsigned reg)
175
@@ -XXX,XX +XXX,XX @@ static bool trans_VRMLSLDAVH(DisasContext *s, arg_vmlaldav *a)
176
return do_long_dual_acc(s, a, fns[a->x]);
177
}
178
179
+static bool do_dual_acc(DisasContext *s, arg_vmladav *a, MVEGenDualAccOpFn *fn)
180
+{
181
+ TCGv_ptr qn, qm;
182
+ TCGv_i32 rda;
183
+
184
+ if (!dc_isar_feature(aa32_mve, s) ||
185
+ !mve_check_qreg_bank(s, a->qn) ||
186
+ !fn) {
62
+ return false;
187
+ return false;
63
+ }
188
+ }
64
+
189
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
65
+ /* UNDEF accesses to D16-D31 if they don't exist. */
66
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
67
+ ((a->vd | a->vm) & 0x10)) {
68
+ return false;
69
+ }
70
+
71
+ if (a->vd & 1) {
72
+ return false;
73
+ }
74
+
75
+ if (!vfp_access_check(s)) {
76
+ return true;
190
+ return true;
77
+ }
191
+ }
78
+
192
+
193
+ qn = mve_qreg_ptr(a->qn);
194
+ qm = mve_qreg_ptr(a->qm);
195
+
79
+ /*
196
+ /*
80
+ * This is a widen-and-shift operation. The shift is always less
197
+ * This insn is subject to beat-wise execution. Partial execution
81
+ * than the width of the source type, so after widening the input
198
+ * of an A=0 (no-accumulate) insn which does not execute the first
82
+ * vector we can simply shift the whole 64-bit widened register,
199
+ * beat must start with the current rda value, not 0.
83
+ * and then clear the potential overflow bits resulting from left
84
+ * bits of the narrow input appearing as right bits of the left
85
+ * neighbour narrow input. Calculate a mask of bits to clear.
86
+ */
200
+ */
87
+ if ((a->shift != 0) && (a->size < 2 || u)) {
201
+ if (a->a || mve_skip_first_beat(s)) {
88
+ int esize = 8 << a->size;
202
+ rda = load_reg(s, a->rda);
89
+ widen_mask = MAKE_64BIT_MASK(0, esize);
203
+ } else {
90
+ widen_mask >>= esize - a->shift;
204
+ rda = tcg_const_i32(0);
91
+ widen_mask = dup_const(a->size + 1, widen_mask);
205
+ }
92
+ }
206
+
93
+
207
+ fn(rda, cpu_env, qn, qm, rda);
94
+ rm0 = neon_load_reg(a->vm, 0);
208
+ store_reg(s, a->rda, rda);
95
+ rm1 = neon_load_reg(a->vm, 1);
209
+ tcg_temp_free_ptr(qn);
96
+ tmp = tcg_temp_new_i64();
210
+ tcg_temp_free_ptr(qm);
97
+
211
+
98
+ widenfn(tmp, rm0);
212
+ mve_update_eci(s);
99
+ if (a->shift != 0) {
100
+ tcg_gen_shli_i64(tmp, tmp, a->shift);
101
+ tcg_gen_andi_i64(tmp, tmp, ~widen_mask);
102
+ }
103
+ neon_store_reg64(tmp, a->vd);
104
+
105
+ widenfn(tmp, rm1);
106
+ if (a->shift != 0) {
107
+ tcg_gen_shli_i64(tmp, tmp, a->shift);
108
+ tcg_gen_andi_i64(tmp, tmp, ~widen_mask);
109
+ }
110
+ neon_store_reg64(tmp, a->vd + 1);
111
+ tcg_temp_free_i64(tmp);
112
+ return true;
213
+ return true;
113
+}
214
+}
114
+
215
+
115
+static bool trans_VSHLL_S_2sh(DisasContext *s, arg_2reg_shift *a)
216
+#define DO_DUAL_ACC(INSN, FN) \
116
+{
217
+ static bool trans_##INSN(DisasContext *s, arg_vmladav *a) \
117
+ NeonGenWidenFn *widenfn[] = {
218
+ { \
118
+ gen_helper_neon_widen_s8,
219
+ static MVEGenDualAccOpFn * const fns[4][2] = { \
119
+ gen_helper_neon_widen_s16,
220
+ { gen_helper_mve_##FN##b, gen_helper_mve_##FN##xb }, \
120
+ tcg_gen_ext_i32_i64,
221
+ { gen_helper_mve_##FN##h, gen_helper_mve_##FN##xh }, \
222
+ { gen_helper_mve_##FN##w, gen_helper_mve_##FN##xw }, \
223
+ { NULL, NULL }, \
224
+ }; \
225
+ return do_dual_acc(s, a, fns[a->size][a->x]); \
226
+ }
227
+
228
+DO_DUAL_ACC(VMLADAV_S, vmladavs)
229
+DO_DUAL_ACC(VMLSDAV, vmlsdav)
230
+
231
+static bool trans_VMLADAV_U(DisasContext *s, arg_vmladav *a)
232
+{
233
+ static MVEGenDualAccOpFn * const fns[4][2] = {
234
+ { gen_helper_mve_vmladavub, NULL },
235
+ { gen_helper_mve_vmladavuh, NULL },
236
+ { gen_helper_mve_vmladavuw, NULL },
237
+ { NULL, NULL },
121
+ };
238
+ };
122
+ return do_vshll_2sh(s, a, widenfn[a->size], false);
239
+ return do_dual_acc(s, a, fns[a->size][a->x]);
123
+}
240
+}
124
+
241
+
125
+static bool trans_VSHLL_U_2sh(DisasContext *s, arg_2reg_shift *a)
242
static void gen_vpst(DisasContext *s, uint32_t mask)
126
+{
243
{
127
+ NeonGenWidenFn *widenfn[] = {
244
/*
128
+ gen_helper_neon_widen_u8,
129
+ gen_helper_neon_widen_u16,
130
+ tcg_gen_extu_i32_i64,
131
+ };
132
+ return do_vshll_2sh(s, a, widenfn[a->size], true);
133
+}
134
diff --git a/target/arm/translate.c b/target/arm/translate.c
135
index XXXXXXX..XXXXXXX 100644
136
--- a/target/arm/translate.c
137
+++ b/target/arm/translate.c
138
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
139
case 7: /* VQSHL */
140
case 8: /* VSHRN, VRSHRN, VQSHRUN, VQRSHRUN */
141
case 9: /* VQSHRN, VQRSHRN */
142
+ case 10: /* VSHLL, including VMOVL */
143
return 1; /* handled by decodetree */
144
default:
145
break;
146
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
147
size--;
148
}
149
shift = (insn >> 16) & ((1 << (3 + size)) - 1);
150
- if (op == 10) {
151
- /* VSHLL, VMOVL */
152
- if (q || (rd & 1)) {
153
- return 1;
154
- }
155
- tmp = neon_load_reg(rm, 0);
156
- tmp2 = neon_load_reg(rm, 1);
157
- for (pass = 0; pass < 2; pass++) {
158
- if (pass == 1)
159
- tmp = tmp2;
160
-
161
- gen_neon_widen(cpu_V0, tmp, size, u);
162
-
163
- if (shift != 0) {
164
- /* The shift is less than the width of the source
165
- type, so we can just shift the whole register. */
166
- tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
167
- /* Widen the result of shift: we need to clear
168
- * the potential overflow bits resulting from
169
- * left bits of the narrow input appearing as
170
- * right bits of left the neighbour narrow
171
- * input. */
172
- if (size < 2 || !u) {
173
- uint64_t imm64;
174
- if (size == 0) {
175
- imm = (0xffu >> (8 - shift));
176
- imm |= imm << 16;
177
- } else if (size == 1) {
178
- imm = 0xffff >> (16 - shift);
179
- } else {
180
- /* size == 2 */
181
- imm = 0xffffffff >> (32 - shift);
182
- }
183
- if (size < 2) {
184
- imm64 = imm | (((uint64_t)imm) << 32);
185
- } else {
186
- imm64 = imm;
187
- }
188
- tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
189
- }
190
- }
191
- neon_store_reg64(cpu_V0, rd + pass);
192
- }
193
- } else if (op >= 14) {
194
+ if (op >= 14) {
195
/* VCVT fixed-point. */
196
TCGv_ptr fpst;
197
TCGv_i32 shiftv;
198
--
245
--
199
2.20.1
246
2.20.1
200
247
201
248
diff view generated by jsdifflib
1
From: Paul Zimmerman <pauldzim@gmail.com>
1
Implement the MVE VMLA insn, which multiplies a vector by a scalar
2
and accumulates into another vector.
2
3
3
Add a check for functional dwc-hsotg (dwc2) USB host emulation to
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
the Raspi 2 acceptance test
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
---
7
target/arm/helper-mve.h | 4 ++++
8
target/arm/mve.decode | 1 +
9
target/arm/mve_helper.c | 5 +++++
10
target/arm/translate-mve.c | 1 +
11
4 files changed, 11 insertions(+)
5
12
6
Signed-off-by: Paul Zimmerman <pauldzim@gmail.com>
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
7
Reviewed-by: Philippe Mathieu-Daude <f4bug@amsat.org>
8
Message-id: 20200520235349.21215-8-pauldzim@gmail.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
tests/acceptance/boot_linux_console.py | 9 +++++++--
12
1 file changed, 7 insertions(+), 2 deletions(-)
13
14
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
15
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
16
--- a/tests/acceptance/boot_linux_console.py
15
--- a/target/arm/helper-mve.h
17
+++ b/tests/acceptance/boot_linux_console.py
16
+++ b/target/arm/helper-mve.h
18
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(LinuxKernelTest):
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vqdmullb_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i3
19
18
DEF_HELPER_FLAGS_4(mve_vqdmullt_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
20
self.vm.set_console()
19
DEF_HELPER_FLAGS_4(mve_vqdmullt_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
21
kernel_command_line = (self.KERNEL_COMMON_COMMAND_LINE +
20
22
- serial_kernel_cmdline[uart_id])
21
+DEF_HELPER_FLAGS_4(mve_vmlab, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
23
+ serial_kernel_cmdline[uart_id] +
22
+DEF_HELPER_FLAGS_4(mve_vmlah, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
+ ' root=/dev/mmcblk0p2 rootwait ' +
23
+DEF_HELPER_FLAGS_4(mve_vmlaw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
+ 'dwc_otg.fiq_fsm_enable=0')
24
+
26
self.vm.add_args('-kernel', kernel_path,
25
DEF_HELPER_FLAGS_4(mve_vmlasb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
27
'-dtb', dtb_path,
26
DEF_HELPER_FLAGS_4(mve_vmlash, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
28
- '-append', kernel_command_line)
27
DEF_HELPER_FLAGS_4(mve_vmlasw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
29
+ '-append', kernel_command_line,
28
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
30
+ '-device', 'usb-kbd')
29
index XXXXXXX..XXXXXXX 100644
31
self.vm.launch()
30
--- a/target/arm/mve.decode
32
console_pattern = 'Kernel command line: %s' % kernel_command_line
31
+++ b/target/arm/mve.decode
33
self.wait_for_console_pattern(console_pattern)
32
@@ -XXX,XX +XXX,XX @@ VQDMULH_scalar 1110 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
34
+ console_pattern = 'Product: QEMU USB Keyboard'
33
VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
35
+ self.wait_for_console_pattern(console_pattern)
34
36
35
# The U bit (28) is don't-care because it does not affect the result
37
def test_arm_raspi2_uart0(self):
36
+VMLA 111- 1110 0 . .. ... 1 ... 0 1110 . 100 .... @2scalar
38
"""
37
VMLAS 111- 1110 0 . .. ... 1 ... 1 1110 . 100 .... @2scalar
38
39
# Vector add across vector
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_2OP_SAT_SCALAR(vqrdmulh_scalarb, 1, int8_t, DO_QRDMULH_B)
45
DO_2OP_SAT_SCALAR(vqrdmulh_scalarh, 2, int16_t, DO_QRDMULH_H)
46
DO_2OP_SAT_SCALAR(vqrdmulh_scalarw, 4, int32_t, DO_QRDMULH_W)
47
48
+/* Vector by scalar plus vector */
49
+#define DO_VMLA(D, N, M) ((N) * (M) + (D))
50
+
51
+DO_2OP_ACC_SCALAR_U(vmla, DO_VMLA)
52
+
53
/* Vector by vector plus scalar */
54
#define DO_VMLAS(D, N, M) ((N) * (D) + (M))
55
56
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
57
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/translate-mve.c
59
+++ b/target/arm/translate-mve.c
60
@@ -XXX,XX +XXX,XX @@ DO_2OP_SCALAR(VQSUB_U_scalar, vqsubu_scalar)
61
DO_2OP_SCALAR(VQDMULH_scalar, vqdmulh_scalar)
62
DO_2OP_SCALAR(VQRDMULH_scalar, vqrdmulh_scalar)
63
DO_2OP_SCALAR(VBRSR, vbrsr)
64
+DO_2OP_SCALAR(VMLA, vmla)
65
DO_2OP_SCALAR(VMLAS, vmlas)
66
67
static bool trans_VQDMULLB_scalar(DisasContext *s, arg_2scalar *a)
39
--
68
--
40
2.20.1
69
2.20.1
41
70
42
71
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Implement the MVE saturating doubling multiply accumulate insns
2
VQDMLAH, VQRDMLAH, VQDMLASH and VQRDMLASH. These perform a multiply,
3
double, add the accumulator shifted by the element size, possibly
4
round, saturate to twice the element size, then take the high half of
5
the result. The *MLAH insns do vector * scalar + vector, and the
6
*MLASH insns do vector * vector + scalar.
2
7
3
With this conversion, we will be able to use the same helpers
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
with sve. This also fixes a bug in which we failed to clear
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
the high bits of the SVE register after an AdvSIMD operation.
10
---
11
target/arm/helper-mve.h | 16 +++++++
12
target/arm/mve.decode | 5 ++
13
target/arm/mve_helper.c | 95 ++++++++++++++++++++++++++++++++++++++
14
target/arm/translate-mve.c | 4 ++
15
4 files changed, 120 insertions(+)
6
16
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
17
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
8
Message-id: 20200514212831.31248-3-richard.henderson@linaro.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/helper.h | 2 ++
13
target/arm/translate-a64.h | 3 ++
14
target/arm/crypto_helper.c | 11 +++++++
15
target/arm/translate-a64.c | 59 ++++++++++++++++++++------------------
16
4 files changed, 47 insertions(+), 28 deletions(-)
17
18
diff --git a/target/arm/helper.h b/target/arm/helper.h
19
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/helper.h
19
--- a/target/arm/helper-mve.h
21
+++ b/target/arm/helper.h
20
+++ b/target/arm/helper-mve.h
22
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(crypto_sm3partw2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vmlasb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
23
DEF_HELPER_FLAGS_4(crypto_sm4e, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
22
DEF_HELPER_FLAGS_4(mve_vmlash, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
DEF_HELPER_FLAGS_4(crypto_sm4ekey, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
23
DEF_HELPER_FLAGS_4(mve_vmlasw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
24
26
+DEF_HELPER_FLAGS_4(crypto_rax1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
25
+DEF_HELPER_FLAGS_4(mve_vqdmlahb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
26
+DEF_HELPER_FLAGS_4(mve_vqdmlahh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
27
+DEF_HELPER_FLAGS_4(mve_vqdmlahw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
27
+
28
+
28
DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
29
+DEF_HELPER_FLAGS_4(mve_vqrdmlahb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
29
DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
30
+DEF_HELPER_FLAGS_4(mve_vqrdmlahh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
30
31
+DEF_HELPER_FLAGS_4(mve_vqrdmlahw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
32
+
33
+DEF_HELPER_FLAGS_4(mve_vqdmlashb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
34
+DEF_HELPER_FLAGS_4(mve_vqdmlashh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
35
+DEF_HELPER_FLAGS_4(mve_vqdmlashw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
36
+
37
+DEF_HELPER_FLAGS_4(mve_vqrdmlashb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
38
+DEF_HELPER_FLAGS_4(mve_vqrdmlashh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
39
+DEF_HELPER_FLAGS_4(mve_vqrdmlashw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
40
+
41
DEF_HELPER_FLAGS_4(mve_vmlaldavsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
42
DEF_HELPER_FLAGS_4(mve_vmlaldavsw, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
43
DEF_HELPER_FLAGS_4(mve_vmlaldavxsh, TCG_CALL_NO_WG, i64, env, ptr, ptr, i64)
44
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
32
index XXXXXXX..XXXXXXX 100644
45
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/translate-a64.h
46
--- a/target/arm/mve.decode
34
+++ b/target/arm/translate-a64.h
47
+++ b/target/arm/mve.decode
35
@@ -XXX,XX +XXX,XX @@ static inline int vec_full_reg_size(DisasContext *s)
48
@@ -XXX,XX +XXX,XX @@ VQRDMULH_scalar 1111 1110 0 . .. ... 1 ... 0 1110 . 110 .... @2scalar
36
49
VMLA 111- 1110 0 . .. ... 1 ... 0 1110 . 100 .... @2scalar
37
bool disas_sve(DisasContext *, uint32_t);
50
VMLAS 111- 1110 0 . .. ... 1 ... 1 1110 . 100 .... @2scalar
38
51
39
+void gen_gvec_rax1(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
52
+VQRDMLAH 1110 1110 0 . .. ... 0 ... 0 1110 . 100 .... @2scalar
40
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
53
+VQRDMLASH 1110 1110 0 . .. ... 0 ... 1 1110 . 100 .... @2scalar
54
+VQDMLAH 1110 1110 0 . .. ... 0 ... 0 1110 . 110 .... @2scalar
55
+VQDMLASH 1110 1110 0 . .. ... 0 ... 1 1110 . 110 .... @2scalar
41
+
56
+
42
#endif /* TARGET_ARM_TRANSLATE_A64_H */
57
# Vector add across vector
43
diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c
58
{
59
VADDV 111 u:1 1110 1111 size:2 01 ... 0 1111 0 0 a:1 0 qm:3 0 rda=%rdalo
60
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
44
index XXXXXXX..XXXXXXX 100644
61
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/crypto_helper.c
62
--- a/target/arm/mve_helper.c
46
+++ b/target/arm/crypto_helper.c
63
+++ b/target/arm/mve_helper.c
47
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sm4ekey)(void *vd, void *vn, void* vm, uint32_t desc)
64
@@ -XXX,XX +XXX,XX @@ DO_VQDMLADH_OP(vqrdmlsdhxw, 4, int32_t, 1, 1, do_vqdmlsdh_w)
65
mve_advance_vpt(env); \
48
}
66
}
49
clear_tail(vd, opr_sz, simd_maxsz(desc));
67
50
}
68
+#define DO_2OP_SAT_ACC_SCALAR(OP, ESIZE, TYPE, FN) \
69
+ void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
70
+ uint32_t rm) \
71
+ { \
72
+ TYPE *d = vd, *n = vn; \
73
+ TYPE m = rm; \
74
+ uint16_t mask = mve_element_mask(env); \
75
+ unsigned e; \
76
+ bool qc = false; \
77
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
78
+ bool sat = false; \
79
+ mergemask(&d[H##ESIZE(e)], \
80
+ FN(d[H##ESIZE(e)], n[H##ESIZE(e)], m, &sat), \
81
+ mask); \
82
+ qc |= sat & mask & 1; \
83
+ } \
84
+ if (qc) { \
85
+ env->vfp.qc[0] = qc; \
86
+ } \
87
+ mve_advance_vpt(env); \
88
+ }
51
+
89
+
52
+void HELPER(crypto_rax1)(void *vd, void *vn, void *vm, uint32_t desc)
90
/* provide unsigned 2-op scalar helpers for all sizes */
91
#define DO_2OP_SCALAR_U(OP, FN) \
92
DO_2OP_SCALAR(OP##b, 1, uint8_t, FN) \
93
@@ -XXX,XX +XXX,XX @@ DO_2OP_SAT_SCALAR(vqrdmulh_scalarb, 1, int8_t, DO_QRDMULH_B)
94
DO_2OP_SAT_SCALAR(vqrdmulh_scalarh, 2, int16_t, DO_QRDMULH_H)
95
DO_2OP_SAT_SCALAR(vqrdmulh_scalarw, 4, int32_t, DO_QRDMULH_W)
96
97
+static int8_t do_vqdmlah_b(int8_t a, int8_t b, int8_t c, int round, bool *sat)
53
+{
98
+{
54
+ intptr_t i, opr_sz = simd_oprsz(desc);
99
+ int64_t r = (int64_t)a * b * 2 + ((int64_t)c << 8) + (round << 7);
55
+ uint64_t *d = vd, *n = vn, *m = vm;
100
+ return do_sat_bhw(r, INT16_MIN, INT16_MAX, sat) >> 8;
56
+
57
+ for (i = 0; i < opr_sz / 8; ++i) {
58
+ d[i] = n[i] ^ rol64(m[i], 1);
59
+ }
60
+ clear_tail(vd, opr_sz, simd_maxsz(desc));
61
+}
62
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
63
index XXXXXXX..XXXXXXX 100644
64
--- a/target/arm/translate-a64.c
65
+++ b/target/arm/translate-a64.c
66
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
67
tcg_temp_free_ptr(tcg_rn_ptr);
68
}
69
70
+static void gen_rax1_i64(TCGv_i64 d, TCGv_i64 n, TCGv_i64 m)
71
+{
72
+ tcg_gen_rotli_i64(d, m, 1);
73
+ tcg_gen_xor_i64(d, d, n);
74
+}
101
+}
75
+
102
+
76
+static void gen_rax1_vec(unsigned vece, TCGv_vec d, TCGv_vec n, TCGv_vec m)
103
+static int16_t do_vqdmlah_h(int16_t a, int16_t b, int16_t c,
104
+ int round, bool *sat)
77
+{
105
+{
78
+ tcg_gen_rotli_vec(vece, d, m, 1);
106
+ int64_t r = (int64_t)a * b * 2 + ((int64_t)c << 16) + (round << 15);
79
+ tcg_gen_xor_vec(vece, d, d, n);
107
+ return do_sat_bhw(r, INT32_MIN, INT32_MAX, sat) >> 16;
80
+}
108
+}
81
+
109
+
82
+void gen_gvec_rax1(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
110
+static int32_t do_vqdmlah_w(int32_t a, int32_t b, int32_t c,
83
+ uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz)
111
+ int round, bool *sat)
84
+{
112
+{
85
+ static const TCGOpcode vecop_list[] = { INDEX_op_rotli_vec, 0 };
113
+ /*
86
+ static const GVecGen3 op = {
114
+ * Architecturally we should do the entire add, double, round
87
+ .fni8 = gen_rax1_i64,
115
+ * and then check for saturation. We do three saturating adds,
88
+ .fniv = gen_rax1_vec,
116
+ * but we need to be careful about the order. If the first
89
+ .opt_opc = vecop_list,
117
+ * m1 + m2 saturates then it's impossible for the *2+rc to
90
+ .fno = gen_helper_crypto_rax1,
118
+ * bring it back into the non-saturated range. However, if
91
+ .vece = MO_64,
119
+ * m1 + m2 is negative then it's possible that doing the doubling
92
+ };
120
+ * would take the intermediate result below INT64_MAX and the
93
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, opr_sz, max_sz, &op);
121
+ * addition of the rounding constant then brings it back in range.
122
+ * So we add half the rounding constant and half the "c << esize"
123
+ * before doubling rather than adding the rounding constant after
124
+ * the doubling.
125
+ */
126
+ int64_t m1 = (int64_t)a * b;
127
+ int64_t m2 = (int64_t)c << 31;
128
+ int64_t r;
129
+ if (sadd64_overflow(m1, m2, &r) ||
130
+ sadd64_overflow(r, (round << 30), &r) ||
131
+ sadd64_overflow(r, r, &r)) {
132
+ *sat = true;
133
+ return r < 0 ? INT32_MAX : INT32_MIN;
134
+ }
135
+ return r >> 32;
94
+}
136
+}
95
+
137
+
96
/* Crypto three-reg SHA512
138
+/*
97
* 31 21 20 16 15 14 13 12 11 10 9 5 4 0
139
+ * The *MLAH insns are vector * scalar + vector;
98
* +-----------------------+------+---+---+-----+--------+------+------+
140
+ * the *MLASH insns are vector * vector + scalar
99
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
141
+ */
100
bool feature;
142
+#define DO_VQDMLAH_B(D, N, M, S) do_vqdmlah_b(N, M, D, 0, S)
101
CryptoThreeOpFn *genfn = NULL;
143
+#define DO_VQDMLAH_H(D, N, M, S) do_vqdmlah_h(N, M, D, 0, S)
102
gen_helper_gvec_3 *oolfn = NULL;
144
+#define DO_VQDMLAH_W(D, N, M, S) do_vqdmlah_w(N, M, D, 0, S)
103
+ GVecGen3Fn *gvecfn = NULL;
145
+#define DO_VQRDMLAH_B(D, N, M, S) do_vqdmlah_b(N, M, D, 1, S)
104
146
+#define DO_VQRDMLAH_H(D, N, M, S) do_vqdmlah_h(N, M, D, 1, S)
105
if (o == 0) {
147
+#define DO_VQRDMLAH_W(D, N, M, S) do_vqdmlah_w(N, M, D, 1, S)
106
switch (opcode) {
148
+
107
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
149
+#define DO_VQDMLASH_B(D, N, M, S) do_vqdmlah_b(N, D, M, 0, S)
108
break;
150
+#define DO_VQDMLASH_H(D, N, M, S) do_vqdmlah_h(N, D, M, 0, S)
109
case 3: /* RAX1 */
151
+#define DO_VQDMLASH_W(D, N, M, S) do_vqdmlah_w(N, D, M, 0, S)
110
feature = dc_isar_feature(aa64_sha3, s);
152
+#define DO_VQRDMLASH_B(D, N, M, S) do_vqdmlah_b(N, D, M, 1, S)
111
- genfn = NULL;
153
+#define DO_VQRDMLASH_H(D, N, M, S) do_vqdmlah_h(N, D, M, 1, S)
112
+ gvecfn = gen_gvec_rax1;
154
+#define DO_VQRDMLASH_W(D, N, M, S) do_vqdmlah_w(N, D, M, 1, S)
113
break;
155
+
114
default:
156
+DO_2OP_SAT_ACC_SCALAR(vqdmlahb, 1, int8_t, DO_VQDMLAH_B)
115
g_assert_not_reached();
157
+DO_2OP_SAT_ACC_SCALAR(vqdmlahh, 2, int16_t, DO_VQDMLAH_H)
116
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
158
+DO_2OP_SAT_ACC_SCALAR(vqdmlahw, 4, int32_t, DO_VQDMLAH_W)
117
159
+DO_2OP_SAT_ACC_SCALAR(vqrdmlahb, 1, int8_t, DO_VQRDMLAH_B)
118
if (oolfn) {
160
+DO_2OP_SAT_ACC_SCALAR(vqrdmlahh, 2, int16_t, DO_VQRDMLAH_H)
119
gen_gvec_op3_ool(s, true, rd, rn, rm, 0, oolfn);
161
+DO_2OP_SAT_ACC_SCALAR(vqrdmlahw, 4, int32_t, DO_VQRDMLAH_W)
120
- return;
162
+
121
- }
163
+DO_2OP_SAT_ACC_SCALAR(vqdmlashb, 1, int8_t, DO_VQDMLASH_B)
122
-
164
+DO_2OP_SAT_ACC_SCALAR(vqdmlashh, 2, int16_t, DO_VQDMLASH_H)
123
- if (genfn) {
165
+DO_2OP_SAT_ACC_SCALAR(vqdmlashw, 4, int32_t, DO_VQDMLASH_W)
124
+ } else if (gvecfn) {
166
+DO_2OP_SAT_ACC_SCALAR(vqrdmlashb, 1, int8_t, DO_VQRDMLASH_B)
125
+ gen_gvec_fn3(s, true, rd, rn, rm, gvecfn, MO_64);
167
+DO_2OP_SAT_ACC_SCALAR(vqrdmlashh, 2, int16_t, DO_VQRDMLASH_H)
126
+ } else {
168
+DO_2OP_SAT_ACC_SCALAR(vqrdmlashw, 4, int32_t, DO_VQRDMLASH_W)
127
TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
169
+
128
170
/* Vector by scalar plus vector */
129
tcg_rd_ptr = vec_full_reg_ptr(s, rd);
171
#define DO_VMLA(D, N, M) ((N) * (M) + (D))
130
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
172
131
tcg_temp_free_ptr(tcg_rd_ptr);
173
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
132
tcg_temp_free_ptr(tcg_rn_ptr);
174
index XXXXXXX..XXXXXXX 100644
133
tcg_temp_free_ptr(tcg_rm_ptr);
175
--- a/target/arm/translate-mve.c
134
- } else {
176
+++ b/target/arm/translate-mve.c
135
- TCGv_i64 tcg_op1, tcg_op2, tcg_res[2];
177
@@ -XXX,XX +XXX,XX @@ DO_2OP_SCALAR(VQRDMULH_scalar, vqrdmulh_scalar)
136
- int pass;
178
DO_2OP_SCALAR(VBRSR, vbrsr)
137
-
179
DO_2OP_SCALAR(VMLA, vmla)
138
- tcg_op1 = tcg_temp_new_i64();
180
DO_2OP_SCALAR(VMLAS, vmlas)
139
- tcg_op2 = tcg_temp_new_i64();
181
+DO_2OP_SCALAR(VQDMLAH, vqdmlah)
140
- tcg_res[0] = tcg_temp_new_i64();
182
+DO_2OP_SCALAR(VQRDMLAH, vqrdmlah)
141
- tcg_res[1] = tcg_temp_new_i64();
183
+DO_2OP_SCALAR(VQDMLASH, vqdmlash)
142
-
184
+DO_2OP_SCALAR(VQRDMLASH, vqrdmlash)
143
- for (pass = 0; pass < 2; pass++) {
185
144
- read_vec_element(s, tcg_op1, rn, pass, MO_64);
186
static bool trans_VQDMULLB_scalar(DisasContext *s, arg_2scalar *a)
145
- read_vec_element(s, tcg_op2, rm, pass, MO_64);
187
{
146
-
147
- tcg_gen_rotli_i64(tcg_res[pass], tcg_op2, 1);
148
- tcg_gen_xor_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
149
- }
150
- write_vec_element(s, tcg_res[0], rd, 0, MO_64);
151
- write_vec_element(s, tcg_res[1], rd, 1, MO_64);
152
-
153
- tcg_temp_free_i64(tcg_op1);
154
- tcg_temp_free_i64(tcg_op2);
155
- tcg_temp_free_i64(tcg_res[0]);
156
- tcg_temp_free_i64(tcg_res[1]);
157
}
158
}
159
160
--
188
--
161
2.20.1
189
2.20.1
162
190
163
191
diff view generated by jsdifflib
1
From: Paul Zimmerman <pauldzim@gmail.com>
1
Implement the MVE 1-operand saturating operations VQABS and VQNEG.
2
2
3
The dwc-hsotg (dwc2) USB host depends on a short packet to
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
indicate the end of an IN transfer. The usb-storage driver
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
currently doesn't provide this, so fix it.
5
---
6
target/arm/helper-mve.h | 8 ++++++++
7
target/arm/mve.decode | 3 +++
8
target/arm/mve_helper.c | 37 +++++++++++++++++++++++++++++++++++++
9
target/arm/translate-mve.c | 2 ++
10
4 files changed, 50 insertions(+)
6
11
7
I have tested this change rather extensively using a PC
12
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
8
emulation with xhci, ehci, and uhci controllers, and have
9
not observed any regressions.
10
11
Signed-off-by: Paul Zimmerman <pauldzim@gmail.com>
12
Message-id: 20200520235349.21215-6-pauldzim@gmail.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
15
hw/usb/dev-storage.c | 15 ++++++++++++++-
16
1 file changed, 14 insertions(+), 1 deletion(-)
17
18
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
19
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
20
--- a/hw/usb/dev-storage.c
14
--- a/target/arm/helper-mve.h
21
+++ b/hw/usb/dev-storage.c
15
+++ b/target/arm/helper-mve.h
22
@@ -XXX,XX +XXX,XX @@ static void usb_msd_copy_data(MSDState *s, USBPacket *p)
16
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vnegw, TCG_CALL_NO_WG, void, env, ptr, ptr)
23
usb_packet_copy(p, scsi_req_get_buf(s->req) + s->scsi_off, len);
17
DEF_HELPER_FLAGS_3(mve_vfnegh, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
s->scsi_len -= len;
18
DEF_HELPER_FLAGS_3(mve_vfnegs, TCG_CALL_NO_WG, void, env, ptr, ptr)
25
s->scsi_off += len;
19
26
+ if (len > s->data_len) {
20
+DEF_HELPER_FLAGS_3(mve_vqabsb, TCG_CALL_NO_WG, void, env, ptr, ptr)
27
+ len = s->data_len;
21
+DEF_HELPER_FLAGS_3(mve_vqabsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
22
+DEF_HELPER_FLAGS_3(mve_vqabsw, TCG_CALL_NO_WG, void, env, ptr, ptr)
23
+
24
+DEF_HELPER_FLAGS_3(mve_vqnegb, TCG_CALL_NO_WG, void, env, ptr, ptr)
25
+DEF_HELPER_FLAGS_3(mve_vqnegh, TCG_CALL_NO_WG, void, env, ptr, ptr)
26
+DEF_HELPER_FLAGS_3(mve_vqnegw, TCG_CALL_NO_WG, void, env, ptr, ptr)
27
+
28
DEF_HELPER_FLAGS_3(mve_vmovnbb, TCG_CALL_NO_WG, void, env, ptr, ptr)
29
DEF_HELPER_FLAGS_3(mve_vmovnbh, TCG_CALL_NO_WG, void, env, ptr, ptr)
30
DEF_HELPER_FLAGS_3(mve_vmovntb, TCG_CALL_NO_WG, void, env, ptr, ptr)
31
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
32
index XXXXXXX..XXXXXXX 100644
33
--- a/target/arm/mve.decode
34
+++ b/target/arm/mve.decode
35
@@ -XXX,XX +XXX,XX @@ VABS_fp 1111 1111 1 . 11 .. 01 ... 0 0111 01 . 0 ... 0 @1op
36
VNEG 1111 1111 1 . 11 .. 01 ... 0 0011 11 . 0 ... 0 @1op
37
VNEG_fp 1111 1111 1 . 11 .. 01 ... 0 0111 11 . 0 ... 0 @1op
38
39
+VQABS 1111 1111 1 . 11 .. 00 ... 0 0111 01 . 0 ... 0 @1op
40
+VQNEG 1111 1111 1 . 11 .. 00 ... 0 0111 11 . 0 ... 0 @1op
41
+
42
&vdup qd rt size
43
# Qd is in the fields usually named Qn
44
@vdup .... .... . . .. ... . rt:4 .... . . . . .... qd=%qn &vdup
45
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/mve_helper.c
48
+++ b/target/arm/mve_helper.c
49
@@ -XXX,XX +XXX,XX @@ void HELPER(mve_vpsel)(CPUARMState *env, void *vd, void *vn, void *vm)
50
}
51
mve_advance_vpt(env);
52
}
53
+
54
+#define DO_1OP_SAT(OP, ESIZE, TYPE, FN) \
55
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm) \
56
+ { \
57
+ TYPE *d = vd, *m = vm; \
58
+ uint16_t mask = mve_element_mask(env); \
59
+ unsigned e; \
60
+ bool qc = false; \
61
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
62
+ bool sat = false; \
63
+ mergemask(&d[H##ESIZE(e)], FN(m[H##ESIZE(e)], &sat), mask); \
64
+ qc |= sat & mask & 1; \
65
+ } \
66
+ if (qc) { \
67
+ env->vfp.qc[0] = qc; \
68
+ } \
69
+ mve_advance_vpt(env); \
28
+ }
70
+ }
29
s->data_len -= len;
71
+
30
if (s->scsi_len == 0 || s->data_len == 0) {
72
+#define DO_VQABS_B(N, SATP) \
31
scsi_req_continue(s->req);
73
+ do_sat_bhs(DO_ABS((int64_t)N), INT8_MIN, INT8_MAX, SATP)
32
@@ -XXX,XX +XXX,XX @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t r
74
+#define DO_VQABS_H(N, SATP) \
33
if (s->data_len) {
75
+ do_sat_bhs(DO_ABS((int64_t)N), INT16_MIN, INT16_MAX, SATP)
34
int len = (p->iov.size - p->actual_length);
76
+#define DO_VQABS_W(N, SATP) \
35
usb_packet_skip(p, len);
77
+ do_sat_bhs(DO_ABS((int64_t)N), INT32_MIN, INT32_MAX, SATP)
36
+ if (len > s->data_len) {
78
+
37
+ len = s->data_len;
79
+#define DO_VQNEG_B(N, SATP) do_sat_bhs(-(int64_t)N, INT8_MIN, INT8_MAX, SATP)
38
+ }
80
+#define DO_VQNEG_H(N, SATP) do_sat_bhs(-(int64_t)N, INT16_MIN, INT16_MAX, SATP)
39
s->data_len -= len;
81
+#define DO_VQNEG_W(N, SATP) do_sat_bhs(-(int64_t)N, INT32_MIN, INT32_MAX, SATP)
40
}
82
+
41
if (s->data_len == 0) {
83
+DO_1OP_SAT(vqabsb, 1, int8_t, DO_VQABS_B)
42
@@ -XXX,XX +XXX,XX @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p)
84
+DO_1OP_SAT(vqabsh, 2, int16_t, DO_VQABS_H)
43
int len = p->iov.size - p->actual_length;
85
+DO_1OP_SAT(vqabsw, 4, int32_t, DO_VQABS_W)
44
if (len) {
86
+
45
usb_packet_skip(p, len);
87
+DO_1OP_SAT(vqnegb, 1, int8_t, DO_VQNEG_B)
46
+ if (len > s->data_len) {
88
+DO_1OP_SAT(vqnegh, 2, int16_t, DO_VQNEG_H)
47
+ len = s->data_len;
89
+DO_1OP_SAT(vqnegw, 4, int32_t, DO_VQNEG_W)
48
+ }
90
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
49
s->data_len -= len;
91
index XXXXXXX..XXXXXXX 100644
50
if (s->data_len == 0) {
92
--- a/target/arm/translate-mve.c
51
s->mode = USB_MSDM_CSW;
93
+++ b/target/arm/translate-mve.c
52
@@ -XXX,XX +XXX,XX @@ static void usb_msd_handle_data(USBDevice *dev, USBPacket *p)
94
@@ -XXX,XX +XXX,XX @@ DO_1OP(VCLZ, vclz)
53
int len = p->iov.size - p->actual_length;
95
DO_1OP(VCLS, vcls)
54
if (len) {
96
DO_1OP(VABS, vabs)
55
usb_packet_skip(p, len);
97
DO_1OP(VNEG, vneg)
56
+ if (len > s->data_len) {
98
+DO_1OP(VQABS, vqabs)
57
+ len = s->data_len;
99
+DO_1OP(VQNEG, vqneg)
58
+ }
100
59
s->data_len -= len;
101
/* Narrowing moves: only size 0 and 1 are valid */
60
if (s->data_len == 0) {
102
#define DO_VMOVN(INSN, FN) \
61
s->mode = USB_MSDM_CSW;
62
}
63
}
64
}
65
- if (p->actual_length < p->iov.size) {
66
+ if (p->actual_length < p->iov.size && (p->short_not_ok ||
67
+ s->scsi_len >= p->ep->max_packet_size)) {
68
DPRINTF("Deferring packet %p [wait data-in]\n", p);
69
s->packet = p;
70
p->status = USB_RET_ASYNC;
71
--
103
--
72
2.20.1
104
2.20.1
73
105
74
106
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Implement the MVE VMAXA and VMINA insns, which take the absolute
2
value of the signed elements in the input vector and then accumulate
3
the unsigned max or min into the destination vector.
2
4
3
Rather than passing an opcode to a helper, fully decode the
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
operation at translate time. Use clear_tail_16 to zap the
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
balance of the SVE register with the AdvSIMD write.
7
---
8
target/arm/helper-mve.h | 8 ++++++++
9
target/arm/mve.decode | 4 ++++
10
target/arm/mve_helper.c | 26 ++++++++++++++++++++++++++
11
target/arm/translate-mve.c | 2 ++
12
4 files changed, 40 insertions(+)
6
13
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
8
Message-id: 20200514212831.31248-7-richard.henderson@linaro.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
12
target/arm/helper.h | 5 ++++-
13
target/arm/crypto_helper.c | 24 ++++++++++++++++++------
14
target/arm/translate-a64.c | 21 +++++----------------
15
3 files changed, 27 insertions(+), 23 deletions(-)
16
17
diff --git a/target/arm/helper.h b/target/arm/helper.h
18
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.h
16
--- a/target/arm/helper-mve.h
20
+++ b/target/arm/helper.h
17
+++ b/target/arm/helper-mve.h
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(crypto_sha512su0, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vqnegb, TCG_CALL_NO_WG, void, env, ptr, ptr)
22
DEF_HELPER_FLAGS_4(crypto_sha512su1, TCG_CALL_NO_RWG,
19
DEF_HELPER_FLAGS_3(mve_vqnegh, TCG_CALL_NO_WG, void, env, ptr, ptr)
23
void, ptr, ptr, ptr, i32)
20
DEF_HELPER_FLAGS_3(mve_vqnegw, TCG_CALL_NO_WG, void, env, ptr, ptr)
24
21
25
-DEF_HELPER_FLAGS_5(crypto_sm3tt, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32, i32)
22
+DEF_HELPER_FLAGS_3(mve_vmaxab, TCG_CALL_NO_WG, void, env, ptr, ptr)
26
+DEF_HELPER_FLAGS_4(crypto_sm3tt1a, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
23
+DEF_HELPER_FLAGS_3(mve_vmaxah, TCG_CALL_NO_WG, void, env, ptr, ptr)
27
+DEF_HELPER_FLAGS_4(crypto_sm3tt1b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
24
+DEF_HELPER_FLAGS_3(mve_vmaxaw, TCG_CALL_NO_WG, void, env, ptr, ptr)
28
+DEF_HELPER_FLAGS_4(crypto_sm3tt2a, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
25
+
29
+DEF_HELPER_FLAGS_4(crypto_sm3tt2b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
26
+DEF_HELPER_FLAGS_3(mve_vminab, TCG_CALL_NO_WG, void, env, ptr, ptr)
30
DEF_HELPER_FLAGS_4(crypto_sm3partw1, TCG_CALL_NO_RWG,
27
+DEF_HELPER_FLAGS_3(mve_vminah, TCG_CALL_NO_WG, void, env, ptr, ptr)
31
void, ptr, ptr, ptr, i32)
28
+DEF_HELPER_FLAGS_3(mve_vminaw, TCG_CALL_NO_WG, void, env, ptr, ptr)
32
DEF_HELPER_FLAGS_4(crypto_sm3partw2, TCG_CALL_NO_RWG,
29
+
33
diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c
30
DEF_HELPER_FLAGS_3(mve_vmovnbb, TCG_CALL_NO_WG, void, env, ptr, ptr)
31
DEF_HELPER_FLAGS_3(mve_vmovnbh, TCG_CALL_NO_WG, void, env, ptr, ptr)
32
DEF_HELPER_FLAGS_3(mve_vmovntb, TCG_CALL_NO_WG, void, env, ptr, ptr)
33
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
34
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
35
--- a/target/arm/crypto_helper.c
35
--- a/target/arm/mve.decode
36
+++ b/target/arm/crypto_helper.c
36
+++ b/target/arm/mve.decode
37
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sm3partw2)(void *vd, void *vn, void *vm, uint32_t desc)
37
@@ -XXX,XX +XXX,XX @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
38
clear_tail_16(vd, desc);
38
VQMOVUNB 111 0 1110 0 . 11 .. 01 ... 0 1110 1 0 . 0 ... 1 @1op
39
VQMOVN_BS 111 0 1110 0 . 11 .. 11 ... 0 1110 0 0 . 0 ... 1 @1op
40
41
+ VMAXA 111 0 1110 0 . 11 .. 11 ... 0 1110 1 0 . 0 ... 1 @1op
42
+
43
VMULH_S 111 0 1110 0 . .. ...1 ... 0 1110 . 0 . 0 ... 1 @2op
39
}
44
}
40
45
41
-void HELPER(crypto_sm3tt)(void *vd, void *vn, void *vm, uint32_t imm2,
46
@@ -XXX,XX +XXX,XX @@ VMUL 1110 1111 0 . .. ... 0 ... 0 1001 . 1 . 1 ... 0 @2op
42
- uint32_t opcode)
47
VQMOVUNT 111 0 1110 0 . 11 .. 01 ... 1 1110 1 0 . 0 ... 1 @1op
43
+static inline void QEMU_ALWAYS_INLINE
48
VQMOVN_TS 111 0 1110 0 . 11 .. 11 ... 1 1110 0 0 . 0 ... 1 @1op
44
+crypto_sm3tt(uint64_t *rd, uint64_t *rn, uint64_t *rm,
49
45
+ uint32_t desc, uint32_t opcode)
50
+ VMINA 111 0 1110 0 . 11 .. 11 ... 1 1110 1 0 . 0 ... 1 @1op
46
{
47
- uint64_t *rd = vd;
48
- uint64_t *rn = vn;
49
- uint64_t *rm = vm;
50
union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
51
union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
52
union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
53
+ uint32_t imm2 = simd_data(desc);
54
uint32_t t;
55
56
assert(imm2 < 4);
57
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sm3tt)(void *vd, void *vn, void *vm, uint32_t imm2,
58
/* SM3TT2B */
59
t = cho(CR_ST_WORD(d, 3), CR_ST_WORD(d, 2), CR_ST_WORD(d, 1));
60
} else {
61
- g_assert_not_reached();
62
+ qemu_build_not_reached();
63
}
64
65
t += CR_ST_WORD(d, 0) + CR_ST_WORD(m, imm2);
66
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sm3tt)(void *vd, void *vn, void *vm, uint32_t imm2,
67
68
rd[0] = d.l[0];
69
rd[1] = d.l[1];
70
+
51
+
71
+ clear_tail_16(rd, desc);
52
VRMULH_S 111 0 1110 0 . .. ...1 ... 1 1110 . 0 . 0 ... 1 @2op
72
}
53
}
73
54
74
+#define DO_SM3TT(NAME, OPCODE) \
55
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
75
+ void HELPER(NAME)(void *vd, void *vn, void *vm, uint32_t desc) \
56
index XXXXXXX..XXXXXXX 100644
76
+ { crypto_sm3tt(vd, vn, vm, desc, OPCODE); }
57
--- a/target/arm/mve_helper.c
58
+++ b/target/arm/mve_helper.c
59
@@ -XXX,XX +XXX,XX @@ DO_1OP_SAT(vqabsw, 4, int32_t, DO_VQABS_W)
60
DO_1OP_SAT(vqnegb, 1, int8_t, DO_VQNEG_B)
61
DO_1OP_SAT(vqnegh, 2, int16_t, DO_VQNEG_H)
62
DO_1OP_SAT(vqnegw, 4, int32_t, DO_VQNEG_W)
77
+
63
+
78
+DO_SM3TT(crypto_sm3tt1a, 0)
64
+/*
79
+DO_SM3TT(crypto_sm3tt1b, 1)
65
+ * VMAXA, VMINA: vd is unsigned; vm is signed, and we take its
80
+DO_SM3TT(crypto_sm3tt2a, 2)
66
+ * absolute value; we then do an unsigned comparison.
81
+DO_SM3TT(crypto_sm3tt2b, 3)
67
+ */
68
+#define DO_VMAXMINA(OP, ESIZE, STYPE, UTYPE, FN) \
69
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm) \
70
+ { \
71
+ UTYPE *d = vd; \
72
+ STYPE *m = vm; \
73
+ uint16_t mask = mve_element_mask(env); \
74
+ unsigned e; \
75
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
76
+ UTYPE r = DO_ABS(m[H##ESIZE(e)]); \
77
+ r = FN(d[H##ESIZE(e)], r); \
78
+ mergemask(&d[H##ESIZE(e)], r, mask); \
79
+ } \
80
+ mve_advance_vpt(env); \
81
+ }
82
+
82
+
83
+#undef DO_SM3TT
83
+DO_VMAXMINA(vmaxab, 1, int8_t, uint8_t, DO_MAX)
84
+
84
+DO_VMAXMINA(vmaxah, 2, int16_t, uint16_t, DO_MAX)
85
static uint8_t const sm4_sbox[] = {
85
+DO_VMAXMINA(vmaxaw, 4, int32_t, uint32_t, DO_MAX)
86
0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7,
86
+DO_VMAXMINA(vminab, 1, int8_t, uint8_t, DO_MIN)
87
0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
87
+DO_VMAXMINA(vminah, 2, int16_t, uint16_t, DO_MIN)
88
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
88
+DO_VMAXMINA(vminaw, 4, int32_t, uint32_t, DO_MIN)
89
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
89
index XXXXXXX..XXXXXXX 100644
90
index XXXXXXX..XXXXXXX 100644
90
--- a/target/arm/translate-a64.c
91
--- a/target/arm/translate-mve.c
91
+++ b/target/arm/translate-a64.c
92
+++ b/target/arm/translate-mve.c
92
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_xar(DisasContext *s, uint32_t insn)
93
@@ -XXX,XX +XXX,XX @@ DO_1OP(VABS, vabs)
93
*/
94
DO_1OP(VNEG, vneg)
94
static void disas_crypto_three_reg_imm2(DisasContext *s, uint32_t insn)
95
DO_1OP(VQABS, vqabs)
95
{
96
DO_1OP(VQNEG, vqneg)
96
+ static gen_helper_gvec_3 * const fns[4] = {
97
+DO_1OP(VMAXA, vmaxa)
97
+ gen_helper_crypto_sm3tt1a, gen_helper_crypto_sm3tt1b,
98
+DO_1OP(VMINA, vmina)
98
+ gen_helper_crypto_sm3tt2a, gen_helper_crypto_sm3tt2b,
99
99
+ };
100
/* Narrowing moves: only size 0 and 1 are valid */
100
int opcode = extract32(insn, 10, 2);
101
#define DO_VMOVN(INSN, FN) \
101
int imm2 = extract32(insn, 12, 2);
102
int rm = extract32(insn, 16, 5);
103
int rn = extract32(insn, 5, 5);
104
int rd = extract32(insn, 0, 5);
105
- TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
106
- TCGv_i32 tcg_imm2, tcg_opcode;
107
108
if (!dc_isar_feature(aa64_sm3, s)) {
109
unallocated_encoding(s);
110
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_imm2(DisasContext *s, uint32_t insn)
111
return;
112
}
113
114
- tcg_rd_ptr = vec_full_reg_ptr(s, rd);
115
- tcg_rn_ptr = vec_full_reg_ptr(s, rn);
116
- tcg_rm_ptr = vec_full_reg_ptr(s, rm);
117
- tcg_imm2 = tcg_const_i32(imm2);
118
- tcg_opcode = tcg_const_i32(opcode);
119
-
120
- gen_helper_crypto_sm3tt(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr, tcg_imm2,
121
- tcg_opcode);
122
-
123
- tcg_temp_free_ptr(tcg_rd_ptr);
124
- tcg_temp_free_ptr(tcg_rn_ptr);
125
- tcg_temp_free_ptr(tcg_rm_ptr);
126
- tcg_temp_free_i32(tcg_imm2);
127
- tcg_temp_free_i32(tcg_opcode);
128
+ gen_gvec_op3_ool(s, true, rd, rn, rm, imm2, fns[opcode]);
129
}
130
131
/* C3.6 Data processing - SIMD, inc Crypto
132
--
102
--
133
2.20.1
103
2.20.1
134
104
135
105
diff view generated by jsdifflib
1
Convert the VQSHLU and QVSHL 2-reg-shift insns to decodetree.
1
Implement the MVE VMOV forms that move data between 2 general-purpose
2
These are the last of the simple shift-by-immediate insns.
2
registers and 2 32-bit lanes in a vector register.
3
3
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200522145520.6778-5-peter.maydell@linaro.org
7
---
6
---
8
target/arm/neon-dp.decode | 15 +++++
7
target/arm/translate-a32.h | 1 +
9
target/arm/translate-neon.inc.c | 108 +++++++++++++++++++++++++++++++
8
target/arm/mve.decode | 4 ++
10
target/arm/translate.c | 110 +-------------------------------
9
target/arm/translate-mve.c | 85 ++++++++++++++++++++++++++++++++++++++
11
3 files changed, 126 insertions(+), 107 deletions(-)
10
target/arm/translate-vfp.c | 2 +-
11
4 files changed, 91 insertions(+), 1 deletion(-)
12
12
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
13
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
14
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
15
--- a/target/arm/translate-a32.h
16
+++ b/target/arm/neon-dp.decode
16
+++ b/target/arm/translate-a32.h
17
@@ -XXX,XX +XXX,XX @@ VSLI_2sh 1111 001 1 1 . ...... .... 0101 . . . 1 .... @2reg_shl_d
17
@@ -XXX,XX +XXX,XX @@ void gen_rev16(TCGv_i32 dest, TCGv_i32 var);
18
VSLI_2sh 1111 001 1 1 . ...... .... 0101 . . . 1 .... @2reg_shl_s
18
void clear_eci_state(DisasContext *s);
19
VSLI_2sh 1111 001 1 1 . ...... .... 0101 . . . 1 .... @2reg_shl_h
19
bool mve_eci_check(DisasContext *s);
20
VSLI_2sh 1111 001 1 1 . ...... .... 0101 . . . 1 .... @2reg_shl_b
20
void mve_update_and_store_eci(DisasContext *s);
21
+bool mve_skip_vmov(DisasContext *s, int vn, int index, int size);
22
23
static inline TCGv_i32 load_cpu_offset(int offset)
24
{
25
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
26
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/mve.decode
28
+++ b/target/arm/mve.decode
29
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111101 ....... @vldr_vstr \
30
VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111110 ....... @vldr_vstr \
31
size=2 p=1
32
33
+# Moves between 2 32-bit vector lanes and 2 general purpose registers
34
+VMOV_to_2gp 1110 1100 0 . 00 rt2:4 ... 0 1111 000 idx:1 rt:4 qd=%qd
35
+VMOV_from_2gp 1110 1100 0 . 01 rt2:4 ... 0 1111 000 idx:1 rt:4 qd=%qd
21
+
36
+
22
+VQSHLU_64_2sh 1111 001 1 1 . ...... .... 0110 . . . 1 .... @2reg_shl_d
37
# Vector 2-op
23
+VQSHLU_2sh 1111 001 1 1 . ...... .... 0110 . . . 1 .... @2reg_shl_s
38
VAND 1110 1111 0 . 00 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
24
+VQSHLU_2sh 1111 001 1 1 . ...... .... 0110 . . . 1 .... @2reg_shl_h
39
VBIC 1110 1111 0 . 01 ... 0 ... 0 0001 . 1 . 1 ... 0 @2op_nosz
25
+VQSHLU_2sh 1111 001 1 1 . ...... .... 0110 . . . 1 .... @2reg_shl_b
40
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
41
index XXXXXXX..XXXXXXX 100644
42
--- a/target/arm/translate-mve.c
43
+++ b/target/arm/translate-mve.c
44
@@ -XXX,XX +XXX,XX @@ static bool do_vabav(DisasContext *s, arg_vabav *a, MVEGenVABAVFn *fn)
45
46
DO_VABAV(VABAV_S, vabavs)
47
DO_VABAV(VABAV_U, vabavu)
26
+
48
+
27
+VQSHL_S_64_2sh 1111 001 0 1 . ...... .... 0111 . . . 1 .... @2reg_shl_d
49
+static bool trans_VMOV_to_2gp(DisasContext *s, arg_VMOV_to_2gp *a)
28
+VQSHL_S_2sh 1111 001 0 1 . ...... .... 0111 . . . 1 .... @2reg_shl_s
29
+VQSHL_S_2sh 1111 001 0 1 . ...... .... 0111 . . . 1 .... @2reg_shl_h
30
+VQSHL_S_2sh 1111 001 0 1 . ...... .... 0111 . . . 1 .... @2reg_shl_b
31
+
32
+VQSHL_U_64_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_d
33
+VQSHL_U_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_s
34
+VQSHL_U_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_h
35
+VQSHL_U_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_b
36
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
37
index XXXXXXX..XXXXXXX 100644
38
--- a/target/arm/translate-neon.inc.c
39
+++ b/target/arm/translate-neon.inc.c
40
@@ -XXX,XX +XXX,XX @@ static bool trans_VSHR_U_2sh(DisasContext *s, arg_2reg_shift *a)
41
return do_vector_2sh(s, a, tcg_gen_gvec_shri);
42
}
43
}
44
+
45
+static bool do_2shift_env_64(DisasContext *s, arg_2reg_shift *a,
46
+ NeonGenTwo64OpEnvFn *fn)
47
+{
50
+{
48
+ /*
51
+ /*
49
+ * 2-reg-and-shift operations, size == 3 case, where the
52
+ * VMOV two 32-bit vector lanes to two general-purpose registers.
50
+ * function needs to be passed cpu_env.
53
+ * This insn is not predicated but it is subject to beat-wise
54
+ * execution if it is not in an IT block. For us this means
55
+ * only that if PSR.ECI says we should not be executing the beat
56
+ * corresponding to the lane of the vector register being accessed
57
+ * then we should skip perfoming the move, and that we need to do
58
+ * the usual check for bad ECI state and advance of ECI state.
59
+ * (If PSR.ECI is non-zero then we cannot be in an IT block.)
51
+ */
60
+ */
52
+ TCGv_i64 constimm;
61
+ TCGv_i32 tmp;
53
+ int pass;
62
+ int vd;
54
+
63
+
55
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
64
+ if (!dc_isar_feature(aa32_mve, s) || !mve_check_qreg_bank(s, a->qd) ||
65
+ a->rt == 13 || a->rt == 15 || a->rt2 == 13 || a->rt2 == 15 ||
66
+ a->rt == a->rt2) {
67
+ /* Rt/Rt2 cases are UNPREDICTABLE */
56
+ return false;
68
+ return false;
57
+ }
69
+ }
58
+
70
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
59
+ /* UNDEF accesses to D16-D31 if they don't exist. */
60
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
61
+ ((a->vd | a->vm) & 0x10)) {
62
+ return false;
63
+ }
64
+
65
+ if ((a->vm | a->vd) & a->q) {
66
+ return false;
67
+ }
68
+
69
+ if (!vfp_access_check(s)) {
70
+ return true;
71
+ return true;
71
+ }
72
+ }
72
+
73
+
73
+ /*
74
+ /* Convert Qreg index to Dreg for read_neon_element32() etc */
74
+ * To avoid excessive duplication of ops we implement shift
75
+ vd = a->qd * 2;
75
+ * by immediate using the variable shift operations.
76
+ */
77
+ constimm = tcg_const_i64(dup_const(a->size, a->shift));
78
+
76
+
79
+ for (pass = 0; pass < a->q + 1; pass++) {
77
+ if (!mve_skip_vmov(s, vd, a->idx, MO_32)) {
80
+ TCGv_i64 tmp = tcg_temp_new_i64();
78
+ tmp = tcg_temp_new_i32();
79
+ read_neon_element32(tmp, vd, a->idx, MO_32);
80
+ store_reg(s, a->rt, tmp);
81
+ }
82
+ if (!mve_skip_vmov(s, vd + 1, a->idx, MO_32)) {
83
+ tmp = tcg_temp_new_i32();
84
+ read_neon_element32(tmp, vd + 1, a->idx, MO_32);
85
+ store_reg(s, a->rt2, tmp);
86
+ }
81
+
87
+
82
+ neon_load_reg64(tmp, a->vm + pass);
88
+ mve_update_and_store_eci(s);
83
+ fn(tmp, cpu_env, tmp, constimm);
84
+ neon_store_reg64(tmp, a->vd + pass);
85
+ }
86
+ tcg_temp_free_i64(constimm);
87
+ return true;
89
+ return true;
88
+}
90
+}
89
+
91
+
90
+static bool do_2shift_env_32(DisasContext *s, arg_2reg_shift *a,
92
+static bool trans_VMOV_from_2gp(DisasContext *s, arg_VMOV_to_2gp *a)
91
+ NeonGenTwoOpEnvFn *fn)
92
+{
93
+{
93
+ /*
94
+ /*
94
+ * 2-reg-and-shift operations, size < 3 case, where the
95
+ * VMOV two general-purpose registers to two 32-bit vector lanes.
95
+ * helper needs to be passed cpu_env.
96
+ * This insn is not predicated but it is subject to beat-wise
97
+ * execution if it is not in an IT block. For us this means
98
+ * only that if PSR.ECI says we should not be executing the beat
99
+ * corresponding to the lane of the vector register being accessed
100
+ * then we should skip perfoming the move, and that we need to do
101
+ * the usual check for bad ECI state and advance of ECI state.
102
+ * (If PSR.ECI is non-zero then we cannot be in an IT block.)
96
+ */
103
+ */
97
+ TCGv_i32 constimm;
104
+ TCGv_i32 tmp;
98
+ int pass;
105
+ int vd;
99
+
106
+
100
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
107
+ if (!dc_isar_feature(aa32_mve, s) || !mve_check_qreg_bank(s, a->qd) ||
108
+ a->rt == 13 || a->rt == 15 || a->rt2 == 13 || a->rt2 == 15) {
109
+ /* Rt/Rt2 cases are UNPREDICTABLE */
101
+ return false;
110
+ return false;
102
+ }
111
+ }
103
+
112
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
104
+ /* UNDEF accesses to D16-D31 if they don't exist. */
105
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
106
+ ((a->vd | a->vm) & 0x10)) {
107
+ return false;
108
+ }
109
+
110
+ if ((a->vm | a->vd) & a->q) {
111
+ return false;
112
+ }
113
+
114
+ if (!vfp_access_check(s)) {
115
+ return true;
113
+ return true;
116
+ }
114
+ }
117
+
115
+
118
+ /*
116
+ /* Convert Qreg idx to Dreg for read_neon_element32() etc */
119
+ * To avoid excessive duplication of ops we implement shift
117
+ vd = a->qd * 2;
120
+ * by immediate using the variable shift operations.
121
+ */
122
+ constimm = tcg_const_i32(dup_const(a->size, a->shift));
123
+
118
+
124
+ for (pass = 0; pass < (a->q ? 4 : 2); pass++) {
119
+ if (!mve_skip_vmov(s, vd, a->idx, MO_32)) {
125
+ TCGv_i32 tmp = neon_load_reg(a->vm, pass);
120
+ tmp = load_reg(s, a->rt);
126
+ fn(tmp, cpu_env, tmp, constimm);
121
+ write_neon_element32(tmp, vd, a->idx, MO_32);
127
+ neon_store_reg(a->vd, pass, tmp);
122
+ tcg_temp_free_i32(tmp);
128
+ }
123
+ }
129
+ tcg_temp_free_i32(constimm);
124
+ if (!mve_skip_vmov(s, vd + 1, a->idx, MO_32)) {
125
+ tmp = load_reg(s, a->rt2);
126
+ write_neon_element32(tmp, vd + 1, a->idx, MO_32);
127
+ tcg_temp_free_i32(tmp);
128
+ }
129
+
130
+ mve_update_and_store_eci(s);
130
+ return true;
131
+ return true;
131
+}
132
+}
132
+
133
diff --git a/target/arm/translate-vfp.c b/target/arm/translate-vfp.c
133
+#define DO_2SHIFT_ENV(INSN, FUNC) \
134
+ static bool trans_##INSN##_64_2sh(DisasContext *s, arg_2reg_shift *a) \
135
+ { \
136
+ return do_2shift_env_64(s, a, gen_helper_neon_##FUNC##64); \
137
+ } \
138
+ static bool trans_##INSN##_2sh(DisasContext *s, arg_2reg_shift *a) \
139
+ { \
140
+ static NeonGenTwoOpEnvFn * const fns[] = { \
141
+ gen_helper_neon_##FUNC##8, \
142
+ gen_helper_neon_##FUNC##16, \
143
+ gen_helper_neon_##FUNC##32, \
144
+ }; \
145
+ assert(a->size < ARRAY_SIZE(fns)); \
146
+ return do_2shift_env_32(s, a, fns[a->size]); \
147
+ }
148
+
149
+DO_2SHIFT_ENV(VQSHLU, qshlu_s)
150
+DO_2SHIFT_ENV(VQSHL_U, qshl_u)
151
+DO_2SHIFT_ENV(VQSHL_S, qshl_s)
152
diff --git a/target/arm/translate.c b/target/arm/translate.c
153
index XXXXXXX..XXXXXXX 100644
134
index XXXXXXX..XXXXXXX 100644
154
--- a/target/arm/translate.c
135
--- a/target/arm/translate-vfp.c
155
+++ b/target/arm/translate.c
136
+++ b/target/arm/translate-vfp.c
156
@@ -XXX,XX +XXX,XX @@ static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
137
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
157
}
138
return true;
158
}
139
}
159
140
160
-#define GEN_NEON_INTEGER_OP_ENV(name) do { \
141
-static bool mve_skip_vmov(DisasContext *s, int vn, int index, int size)
161
- switch ((size << 1) | u) { \
142
+bool mve_skip_vmov(DisasContext *s, int vn, int index, int size)
162
- case 0: \
163
- gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
164
- break; \
165
- case 1: \
166
- gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
167
- break; \
168
- case 2: \
169
- gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
170
- break; \
171
- case 3: \
172
- gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
173
- break; \
174
- case 4: \
175
- gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
176
- break; \
177
- case 5: \
178
- gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
179
- break; \
180
- default: return 1; \
181
- }} while (0)
182
-
183
static TCGv_i32 neon_load_scratch(int scratch)
184
{
143
{
185
TCGv_i32 tmp = tcg_temp_new_i32();
144
/*
186
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
145
* In a CPU with MVE, the VMOV (vector lane to general-purpose register)
187
int size;
188
int shift;
189
int pass;
190
- int count;
191
int u;
192
int vec_size;
193
uint32_t imm;
194
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
195
case 3: /* VRSRA */
196
case 4: /* VSRI */
197
case 5: /* VSHL, VSLI */
198
+ case 6: /* VQSHLU */
199
+ case 7: /* VQSHL */
200
return 1; /* handled by decodetree */
201
default:
202
break;
203
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
204
size--;
205
}
206
shift = (insn >> 16) & ((1 << (3 + size)) - 1);
207
- if (op < 8) {
208
- /* Shift by immediate:
209
- VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
210
- if (q && ((rd | rm) & 1)) {
211
- return 1;
212
- }
213
- if (!u && (op == 4 || op == 6)) {
214
- return 1;
215
- }
216
- /* Right shifts are encoded as N - shift, where N is the
217
- element size in bits. */
218
- if (op <= 4) {
219
- shift = shift - (1 << (size + 3));
220
- }
221
-
222
- if (size == 3) {
223
- count = q + 1;
224
- } else {
225
- count = q ? 4: 2;
226
- }
227
-
228
- /* To avoid excessive duplication of ops we implement shift
229
- * by immediate using the variable shift operations.
230
- */
231
- imm = dup_const(size, shift);
232
-
233
- for (pass = 0; pass < count; pass++) {
234
- if (size == 3) {
235
- neon_load_reg64(cpu_V0, rm + pass);
236
- tcg_gen_movi_i64(cpu_V1, imm);
237
- switch (op) {
238
- case 6: /* VQSHLU */
239
- gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
240
- cpu_V0, cpu_V1);
241
- break;
242
- case 7: /* VQSHL */
243
- if (u) {
244
- gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
245
- cpu_V0, cpu_V1);
246
- } else {
247
- gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
248
- cpu_V0, cpu_V1);
249
- }
250
- break;
251
- default:
252
- g_assert_not_reached();
253
- }
254
- neon_store_reg64(cpu_V0, rd + pass);
255
- } else { /* size < 3 */
256
- /* Operands in T0 and T1. */
257
- tmp = neon_load_reg(rm, pass);
258
- tmp2 = tcg_temp_new_i32();
259
- tcg_gen_movi_i32(tmp2, imm);
260
- switch (op) {
261
- case 6: /* VQSHLU */
262
- switch (size) {
263
- case 0:
264
- gen_helper_neon_qshlu_s8(tmp, cpu_env,
265
- tmp, tmp2);
266
- break;
267
- case 1:
268
- gen_helper_neon_qshlu_s16(tmp, cpu_env,
269
- tmp, tmp2);
270
- break;
271
- case 2:
272
- gen_helper_neon_qshlu_s32(tmp, cpu_env,
273
- tmp, tmp2);
274
- break;
275
- default:
276
- abort();
277
- }
278
- break;
279
- case 7: /* VQSHL */
280
- GEN_NEON_INTEGER_OP_ENV(qshl);
281
- break;
282
- default:
283
- g_assert_not_reached();
284
- }
285
- tcg_temp_free_i32(tmp2);
286
- neon_store_reg(rd, pass, tmp);
287
- }
288
- } /* for pass */
289
- } else if (op < 10) {
290
+ if (op < 10) {
291
/* Shift by immediate and narrow:
292
VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
293
int input_unsigned = (op == 8) ? !u : u;
294
--
146
--
295
2.20.1
147
2.20.1
296
148
297
149
diff view generated by jsdifflib
1
Convert the insns in the one-register-and-immediate group to decodetree.
1
Implement the MVE VPNOT insn, which inverts the bits in VPR.P0
2
2
(subject to both predication and to beatwise execution).
3
In the new decode, our asimd_imm_const() function returns a 64-bit value
4
rather than a 32-bit one, which means we don't need to treat cmode=14 op=1
5
as a special case in the decoder (it is the only encoding where the two
6
halves of the 64-bit value are different).
7
3
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20200522145520.6778-10-peter.maydell@linaro.org
11
---
6
---
12
target/arm/neon-dp.decode | 22 ++++++
7
target/arm/helper-mve.h | 1 +
13
target/arm/translate-neon.inc.c | 118 ++++++++++++++++++++++++++++++++
8
target/arm/mve.decode | 1 +
14
target/arm/translate.c | 101 +--------------------------
9
target/arm/mve_helper.c | 17 +++++++++++++++++
15
3 files changed, 142 insertions(+), 99 deletions(-)
10
target/arm/translate-mve.c | 19 +++++++++++++++++++
11
4 files changed, 38 insertions(+)
16
12
17
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
13
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
18
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/neon-dp.decode
15
--- a/target/arm/helper-mve.h
20
+++ b/target/arm/neon-dp.decode
16
+++ b/target/arm/helper-mve.h
21
@@ -XXX,XX +XXX,XX @@ VCVT_SF_2sh 1111 001 0 1 . ...... .... 1110 0 . . 1 .... @2reg_vcvt
17
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vorn, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
VCVT_UF_2sh 1111 001 1 1 . ...... .... 1110 0 . . 1 .... @2reg_vcvt
18
DEF_HELPER_FLAGS_4(mve_veor, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
VCVT_FS_2sh 1111 001 0 1 . ...... .... 1111 0 . . 1 .... @2reg_vcvt
19
24
VCVT_FU_2sh 1111 001 1 1 . ...... .... 1111 0 . . 1 .... @2reg_vcvt
20
DEF_HELPER_FLAGS_4(mve_vpsel, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
25
+
21
+DEF_HELPER_FLAGS_1(mve_vpnot, TCG_CALL_NO_WG, void, env)
26
+######################################################################
22
27
+# 1-reg-and-modified-immediate grouping:
23
DEF_HELPER_FLAGS_4(mve_vaddb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
+# 1111 001 i 1 D 000 imm:3 Vd:4 cmode:4 0 Q op 1 Vm:4
24
DEF_HELPER_FLAGS_4(mve_vaddh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
+######################################################################
25
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
30
+
31
+&1reg_imm vd q imm cmode op
32
+
33
+%asimd_imm_value 24:1 16:3 0:4
34
+
35
+@1reg_imm .... ... . . . ... ... .... .... . q:1 . . .... \
36
+ &1reg_imm imm=%asimd_imm_value vd=%vd_dp
37
+
38
+# The cmode/op bits here decode VORR/VBIC/VMOV/VMNV, but
39
+# not in a way we can conveniently represent in decodetree without
40
+# a lot of repetition:
41
+# VORR: op=0, (cmode & 1) && cmode < 12
42
+# VBIC: op=1, (cmode & 1) && cmode < 12
43
+# VMOV: everything else
44
+# So we have a single decode line and check the cmode/op in the
45
+# trans function.
46
+Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 . op:1 1 .... @1reg_imm
47
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
48
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/translate-neon.inc.c
27
--- a/target/arm/mve.decode
50
+++ b/target/arm/translate-neon.inc.c
28
+++ b/target/arm/mve.decode
51
@@ -XXX,XX +XXX,XX @@ DO_FP_2SH(VCVT_SF, gen_helper_vfp_sltos)
29
@@ -XXX,XX +XXX,XX @@ VCMPGT 1111 1110 0 . .. ... 1 ... 1 1111 0 0 . 0 ... 1 @vcmp
52
DO_FP_2SH(VCVT_UF, gen_helper_vfp_ultos)
30
VCMPLE 1111 1110 0 . .. ... 1 ... 1 1111 1 0 . 0 ... 1 @vcmp
53
DO_FP_2SH(VCVT_FS, gen_helper_vfp_tosls_round_to_zero)
31
54
DO_FP_2SH(VCVT_FU, gen_helper_vfp_touls_round_to_zero)
32
{
55
+
33
+ VPNOT 1111 1110 0 0 11 000 1 000 0 1111 0100 1101
56
+static uint64_t asimd_imm_const(uint32_t imm, int cmode, int op)
34
VPST 1111 1110 0 . 11 000 1 ... 0 1111 0100 1101 mask=%mask_22_13
35
VCMPEQ_scalar 1111 1110 0 . .. ... 1 ... 0 1111 0 1 0 0 .... @vcmp_scalar
36
}
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 @@ void HELPER(mve_vpsel)(CPUARMState *env, void *vd, void *vn, void *vm)
42
mve_advance_vpt(env);
43
}
44
45
+void HELPER(mve_vpnot)(CPUARMState *env)
57
+{
46
+{
58
+ /*
47
+ /*
59
+ * Expand the encoded constant.
48
+ * P0 bits for unexecuted beats (where eci_mask is 0) are unchanged.
60
+ * Note that cmode = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
49
+ * P0 bits for predicated lanes in executed bits (where mask is 0) are 0.
61
+ * We choose to not special-case this and will behave as if a
50
+ * P0 bits otherwise are inverted.
62
+ * valid constant encoding of 0 had been given.
51
+ * (This is the same logic as VCMP.)
63
+ * cmode = 15 op = 1 must UNDEF; we assume decode has handled that.
52
+ * This insn is itself subject to predication and to beat-wise execution,
53
+ * and after it executes VPT state advances in the usual way.
64
+ */
54
+ */
65
+ switch (cmode) {
55
+ uint16_t mask = mve_element_mask(env);
66
+ case 0: case 1:
56
+ uint16_t eci_mask = mve_eci_mask(env);
67
+ /* no-op */
57
+ uint16_t beatpred = ~env->v7m.vpr & mask;
68
+ break;
58
+ env->v7m.vpr = (env->v7m.vpr & ~(uint32_t)eci_mask) | (beatpred & eci_mask);
69
+ case 2: case 3:
59
+ mve_advance_vpt(env);
70
+ imm <<= 8;
71
+ break;
72
+ case 4: case 5:
73
+ imm <<= 16;
74
+ break;
75
+ case 6: case 7:
76
+ imm <<= 24;
77
+ break;
78
+ case 8: case 9:
79
+ imm |= imm << 16;
80
+ break;
81
+ case 10: case 11:
82
+ imm = (imm << 8) | (imm << 24);
83
+ break;
84
+ case 12:
85
+ imm = (imm << 8) | 0xff;
86
+ break;
87
+ case 13:
88
+ imm = (imm << 16) | 0xffff;
89
+ break;
90
+ case 14:
91
+ if (op) {
92
+ /*
93
+ * This is the only case where the top and bottom 32 bits
94
+ * of the encoded constant differ.
95
+ */
96
+ uint64_t imm64 = 0;
97
+ int n;
98
+
99
+ for (n = 0; n < 8; n++) {
100
+ if (imm & (1 << n)) {
101
+ imm64 |= (0xffULL << (n * 8));
102
+ }
103
+ }
104
+ return imm64;
105
+ }
106
+ imm |= (imm << 8) | (imm << 16) | (imm << 24);
107
+ break;
108
+ case 15:
109
+ imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
110
+ | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
111
+ break;
112
+ }
113
+ if (op) {
114
+ imm = ~imm;
115
+ }
116
+ return dup_const(MO_32, imm);
117
+}
60
+}
118
+
61
+
119
+static bool do_1reg_imm(DisasContext *s, arg_1reg_imm *a,
62
#define DO_1OP_SAT(OP, ESIZE, TYPE, FN) \
120
+ GVecGen2iFn *fn)
63
void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm) \
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 @@ static bool trans_VPST(DisasContext *s, arg_VPST *a)
70
return true;
71
}
72
73
+static bool trans_VPNOT(DisasContext *s, arg_VPNOT *a)
121
+{
74
+{
122
+ uint64_t imm;
75
+ /*
123
+ int reg_ofs, vec_size;
76
+ * Invert the predicate in VPR.P0. We have call out to
124
+
77
+ * a helper because this insn itself is beatwise and can
125
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
78
+ * be predicated.
79
+ */
80
+ if (!dc_isar_feature(aa32_mve, s)) {
126
+ return false;
81
+ return false;
127
+ }
82
+ }
128
+
83
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
129
+ /* UNDEF accesses to D16-D31 if they don't exist. */
130
+ if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
131
+ return false;
132
+ }
133
+
134
+ if (a->vd & a->q) {
135
+ return false;
136
+ }
137
+
138
+ if (!vfp_access_check(s)) {
139
+ return true;
84
+ return true;
140
+ }
85
+ }
141
+
86
+
142
+ reg_ofs = neon_reg_offset(a->vd, 0);
87
+ gen_helper_mve_vpnot(cpu_env);
143
+ vec_size = a->q ? 16 : 8;
88
+ mve_update_eci(s);
144
+ imm = asimd_imm_const(a->imm, a->cmode, a->op);
145
+
146
+ fn(MO_64, reg_ofs, reg_ofs, imm, vec_size, vec_size);
147
+ return true;
89
+ return true;
148
+}
90
+}
149
+
91
+
150
+static void gen_VMOV_1r(unsigned vece, uint32_t dofs, uint32_t aofs,
92
static bool trans_VADDV(DisasContext *s, arg_VADDV *a)
151
+ int64_t c, uint32_t oprsz, uint32_t maxsz)
93
{
152
+{
94
/* VADDV: vector add across vector */
153
+ tcg_gen_gvec_dup_imm(MO_64, dofs, oprsz, maxsz, c);
154
+}
155
+
156
+static bool trans_Vimm_1r(DisasContext *s, arg_1reg_imm *a)
157
+{
158
+ /* Handle decode of cmode/op here between VORR/VBIC/VMOV */
159
+ GVecGen2iFn *fn;
160
+
161
+ if ((a->cmode & 1) && a->cmode < 12) {
162
+ /* for op=1, the imm will be inverted, so BIC becomes AND. */
163
+ fn = a->op ? tcg_gen_gvec_andi : tcg_gen_gvec_ori;
164
+ } else {
165
+ /* There is one unallocated cmode/op combination in this space */
166
+ if (a->cmode == 15 && a->op == 1) {
167
+ return false;
168
+ }
169
+ fn = gen_VMOV_1r;
170
+ }
171
+ return do_1reg_imm(s, a, fn);
172
+}
173
diff --git a/target/arm/translate.c b/target/arm/translate.c
174
index XXXXXXX..XXXXXXX 100644
175
--- a/target/arm/translate.c
176
+++ b/target/arm/translate.c
177
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
178
/* Three register same length: handled by decodetree */
179
return 1;
180
} else if (insn & (1 << 4)) {
181
- if ((insn & 0x00380080) != 0) {
182
- /* Two registers and shift: handled by decodetree */
183
- return 1;
184
- } else { /* (insn & 0x00380080) == 0 */
185
- int invert, reg_ofs, vec_size;
186
-
187
- if (q && (rd & 1)) {
188
- return 1;
189
- }
190
-
191
- op = (insn >> 8) & 0xf;
192
- /* One register and immediate. */
193
- imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
194
- invert = (insn & (1 << 5)) != 0;
195
- /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
196
- * We choose to not special-case this and will behave as if a
197
- * valid constant encoding of 0 had been given.
198
- */
199
- switch (op) {
200
- case 0: case 1:
201
- /* no-op */
202
- break;
203
- case 2: case 3:
204
- imm <<= 8;
205
- break;
206
- case 4: case 5:
207
- imm <<= 16;
208
- break;
209
- case 6: case 7:
210
- imm <<= 24;
211
- break;
212
- case 8: case 9:
213
- imm |= imm << 16;
214
- break;
215
- case 10: case 11:
216
- imm = (imm << 8) | (imm << 24);
217
- break;
218
- case 12:
219
- imm = (imm << 8) | 0xff;
220
- break;
221
- case 13:
222
- imm = (imm << 16) | 0xffff;
223
- break;
224
- case 14:
225
- imm |= (imm << 8) | (imm << 16) | (imm << 24);
226
- if (invert) {
227
- imm = ~imm;
228
- }
229
- break;
230
- case 15:
231
- if (invert) {
232
- return 1;
233
- }
234
- imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
235
- | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
236
- break;
237
- }
238
- if (invert) {
239
- imm = ~imm;
240
- }
241
-
242
- reg_ofs = neon_reg_offset(rd, 0);
243
- vec_size = q ? 16 : 8;
244
-
245
- if (op & 1 && op < 12) {
246
- if (invert) {
247
- /* The immediate value has already been inverted,
248
- * so BIC becomes AND.
249
- */
250
- tcg_gen_gvec_andi(MO_32, reg_ofs, reg_ofs, imm,
251
- vec_size, vec_size);
252
- } else {
253
- tcg_gen_gvec_ori(MO_32, reg_ofs, reg_ofs, imm,
254
- vec_size, vec_size);
255
- }
256
- } else {
257
- /* VMOV, VMVN. */
258
- if (op == 14 && invert) {
259
- TCGv_i64 t64 = tcg_temp_new_i64();
260
-
261
- for (pass = 0; pass <= q; ++pass) {
262
- uint64_t val = 0;
263
- int n;
264
-
265
- for (n = 0; n < 8; n++) {
266
- if (imm & (1 << (n + pass * 8))) {
267
- val |= 0xffull << (n * 8);
268
- }
269
- }
270
- tcg_gen_movi_i64(t64, val);
271
- neon_store_reg64(t64, rd + pass);
272
- }
273
- tcg_temp_free_i64(t64);
274
- } else {
275
- tcg_gen_gvec_dup_imm(MO_32, reg_ofs, vec_size,
276
- vec_size, imm);
277
- }
278
- }
279
- }
280
+ /* Two registers and shift or reg and imm: handled by decodetree */
281
+ return 1;
282
} else { /* (insn & 0x00800010 == 0x00800000) */
283
if (size != 3) {
284
op = (insn >> 8) & 0xf;
285
--
95
--
286
2.20.1
96
2.20.1
287
97
288
98
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Implement the MVE VCTP insn, which sets the VPR.P0 predicate bits so
2
as to predicate any element at index Rn or greater is predicated. As
3
with VPNOT, this insn itself is predicable and subject to beatwise
4
execution.
2
5
3
Do not yet convert the helpers to loop over opr_sz, but the
6
The calculation of the mask is the same as is used to determine
4
descriptor allows the vector tail to be cleared. Which fixes
7
ltpmask in mve_element_mask(), but we precalculate masklen in
5
an existing bug vs SVE.
8
generated code to avoid having to have 4 helpers specialized by size.
6
9
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
10
We put the decode line in with the low-overhead-loop insns in
8
Message-id: 20200514212831.31248-4-richard.henderson@linaro.org
11
t32.decode because it's logically part of that collection of insn
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
patterns, even though it is an MVE only insn.
13
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
---
16
---
12
target/arm/helper.h | 15 +++++++-----
17
target/arm/helper-mve.h | 2 ++
13
target/arm/crypto_helper.c | 37 +++++++++++++++++++++++-----
18
target/arm/translate-a32.h | 1 +
14
target/arm/translate-a64.c | 50 ++++++++++++--------------------------
19
target/arm/t32.decode | 1 +
15
3 files changed, 55 insertions(+), 47 deletions(-)
20
target/arm/mve_helper.c | 20 ++++++++++++++++++++
21
target/arm/translate-mve.c | 2 +-
22
target/arm/translate.c | 33 +++++++++++++++++++++++++++++++++
23
6 files changed, 58 insertions(+), 1 deletion(-)
16
24
17
diff --git a/target/arm/helper.h b/target/arm/helper.h
25
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
18
index XXXXXXX..XXXXXXX 100644
26
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/helper.h
27
--- a/target/arm/helper-mve.h
20
+++ b/target/arm/helper.h
28
+++ b/target/arm/helper-mve.h
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(crypto_sha256h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
29
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_veor, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
22
DEF_HELPER_FLAGS_2(crypto_sha256su0, TCG_CALL_NO_RWG, void, ptr, ptr)
30
DEF_HELPER_FLAGS_4(mve_vpsel, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
23
DEF_HELPER_FLAGS_3(crypto_sha256su1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
31
DEF_HELPER_FLAGS_1(mve_vpnot, TCG_CALL_NO_WG, void, env)
24
32
25
-DEF_HELPER_FLAGS_3(crypto_sha512h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
33
+DEF_HELPER_FLAGS_2(mve_vctp, TCG_CALL_NO_WG, void, env, i32)
26
-DEF_HELPER_FLAGS_3(crypto_sha512h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
34
+
27
-DEF_HELPER_FLAGS_2(crypto_sha512su0, TCG_CALL_NO_RWG, void, ptr, ptr)
35
DEF_HELPER_FLAGS_4(mve_vaddb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
28
-DEF_HELPER_FLAGS_3(crypto_sha512su1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
36
DEF_HELPER_FLAGS_4(mve_vaddh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
29
+DEF_HELPER_FLAGS_4(crypto_sha512h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
37
DEF_HELPER_FLAGS_4(mve_vaddw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
30
+DEF_HELPER_FLAGS_4(crypto_sha512h2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
38
diff --git a/target/arm/translate-a32.h b/target/arm/translate-a32.h
31
+DEF_HELPER_FLAGS_3(crypto_sha512su0, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
32
+DEF_HELPER_FLAGS_4(crypto_sha512su1, TCG_CALL_NO_RWG,
33
+ void, ptr, ptr, ptr, i32)
34
35
DEF_HELPER_FLAGS_5(crypto_sm3tt, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32, i32)
36
-DEF_HELPER_FLAGS_3(crypto_sm3partw1, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
37
-DEF_HELPER_FLAGS_3(crypto_sm3partw2, TCG_CALL_NO_RWG, void, ptr, ptr, ptr)
38
+DEF_HELPER_FLAGS_4(crypto_sm3partw1, TCG_CALL_NO_RWG,
39
+ void, ptr, ptr, ptr, i32)
40
+DEF_HELPER_FLAGS_4(crypto_sm3partw2, TCG_CALL_NO_RWG,
41
+ void, ptr, ptr, ptr, i32)
42
43
DEF_HELPER_FLAGS_4(crypto_sm4e, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
44
DEF_HELPER_FLAGS_4(crypto_sm4ekey, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
45
diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c
46
index XXXXXXX..XXXXXXX 100644
39
index XXXXXXX..XXXXXXX 100644
47
--- a/target/arm/crypto_helper.c
40
--- a/target/arm/translate-a32.h
48
+++ b/target/arm/crypto_helper.c
41
+++ b/target/arm/translate-a32.h
49
@@ -XXX,XX +XXX,XX @@ union CRYPTO_STATE {
42
@@ -XXX,XX +XXX,XX @@ long neon_element_offset(int reg, int element, MemOp memop);
50
#define CR_ST_WORD(state, i) (state.words[i])
43
void gen_rev16(TCGv_i32 dest, TCGv_i32 var);
51
#endif
44
void clear_eci_state(DisasContext *s);
45
bool mve_eci_check(DisasContext *s);
46
+void mve_update_eci(DisasContext *s);
47
void mve_update_and_store_eci(DisasContext *s);
48
bool mve_skip_vmov(DisasContext *s, int vn, int index, int size);
49
50
diff --git a/target/arm/t32.decode b/target/arm/t32.decode
51
index XXXXXXX..XXXXXXX 100644
52
--- a/target/arm/t32.decode
53
+++ b/target/arm/t32.decode
54
@@ -XXX,XX +XXX,XX @@ BL 1111 0. .......... 11.1 ............ @branch24
55
# This is DLSTP
56
DLS 1111 0 0000 0 size:2 rn:4 1110 0000 0000 0001
57
}
58
+ VCTP 1111 0 0000 0 size:2 rn:4 1110 1000 0000 0001
59
]
60
}
61
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/target/arm/mve_helper.c
64
+++ b/target/arm/mve_helper.c
65
@@ -XXX,XX +XXX,XX @@ void HELPER(mve_vpnot)(CPUARMState *env)
66
mve_advance_vpt(env);
67
}
52
68
53
+/*
69
+/*
54
+ * The caller has not been converted to full gvec, and so only
70
+ * VCTP: P0 unexecuted bits unchanged, predicated bits zeroed,
55
+ * modifies the low 16 bytes of the vector register.
71
+ * otherwise set according to value of Rn. The calculation of
72
+ * newmask here works in the same way as the calculation of the
73
+ * ltpmask in mve_element_mask(), but we have pre-calculated
74
+ * the masklen in the generated code.
56
+ */
75
+ */
57
+static void clear_tail_16(void *vd, uint32_t desc)
76
+void HELPER(mve_vctp)(CPUARMState *env, uint32_t masklen)
58
+{
77
+{
59
+ int opr_sz = simd_oprsz(desc);
78
+ uint16_t mask = mve_element_mask(env);
60
+ int max_sz = simd_maxsz(desc);
79
+ uint16_t eci_mask = mve_eci_mask(env);
80
+ uint16_t newmask;
61
+
81
+
62
+ assert(opr_sz == 16);
82
+ assert(masklen <= 16);
63
+ clear_tail(vd, opr_sz, max_sz);
83
+ newmask = masklen ? MAKE_64BIT_MASK(0, masklen) : 0;
84
+ newmask &= mask;
85
+ env->v7m.vpr = (env->v7m.vpr & ~(uint32_t)eci_mask) | (newmask & eci_mask);
86
+ mve_advance_vpt(env);
64
+}
87
+}
65
+
88
+
66
static void do_crypto_aese(uint64_t *rd, uint64_t *rn,
89
#define DO_1OP_SAT(OP, ESIZE, TYPE, FN) \
67
uint64_t *rm, bool decrypt)
90
void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm) \
68
{
91
{ \
69
@@ -XXX,XX +XXX,XX @@ static uint64_t s1_512(uint64_t x)
92
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
70
return ror64(x, 19) ^ ror64(x, 61) ^ (x >> 6);
71
}
72
73
-void HELPER(crypto_sha512h)(void *vd, void *vn, void *vm)
74
+void HELPER(crypto_sha512h)(void *vd, void *vn, void *vm, uint32_t desc)
75
{
76
uint64_t *rd = vd;
77
uint64_t *rn = vn;
78
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha512h)(void *vd, void *vn, void *vm)
79
80
rd[0] = d0;
81
rd[1] = d1;
82
+
83
+ clear_tail_16(vd, desc);
84
}
85
86
-void HELPER(crypto_sha512h2)(void *vd, void *vn, void *vm)
87
+void HELPER(crypto_sha512h2)(void *vd, void *vn, void *vm, uint32_t desc)
88
{
89
uint64_t *rd = vd;
90
uint64_t *rn = vn;
91
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha512h2)(void *vd, void *vn, void *vm)
92
93
rd[0] = d0;
94
rd[1] = d1;
95
+
96
+ clear_tail_16(vd, desc);
97
}
98
99
-void HELPER(crypto_sha512su0)(void *vd, void *vn)
100
+void HELPER(crypto_sha512su0)(void *vd, void *vn, uint32_t desc)
101
{
102
uint64_t *rd = vd;
103
uint64_t *rn = vn;
104
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha512su0)(void *vd, void *vn)
105
106
rd[0] = d0;
107
rd[1] = d1;
108
+
109
+ clear_tail_16(vd, desc);
110
}
111
112
-void HELPER(crypto_sha512su1)(void *vd, void *vn, void *vm)
113
+void HELPER(crypto_sha512su1)(void *vd, void *vn, void *vm, uint32_t desc)
114
{
115
uint64_t *rd = vd;
116
uint64_t *rn = vn;
117
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sha512su1)(void *vd, void *vn, void *vm)
118
119
rd[0] += s1_512(rn[0]) + rm[0];
120
rd[1] += s1_512(rn[1]) + rm[1];
121
+
122
+ clear_tail_16(vd, desc);
123
}
124
125
-void HELPER(crypto_sm3partw1)(void *vd, void *vn, void *vm)
126
+void HELPER(crypto_sm3partw1)(void *vd, void *vn, void *vm, uint32_t desc)
127
{
128
uint64_t *rd = vd;
129
uint64_t *rn = vn;
130
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sm3partw1)(void *vd, void *vn, void *vm)
131
132
rd[0] = d.l[0];
133
rd[1] = d.l[1];
134
+
135
+ clear_tail_16(vd, desc);
136
}
137
138
-void HELPER(crypto_sm3partw2)(void *vd, void *vn, void *vm)
139
+void HELPER(crypto_sm3partw2)(void *vd, void *vn, void *vm, uint32_t desc)
140
{
141
uint64_t *rd = vd;
142
uint64_t *rn = vn;
143
@@ -XXX,XX +XXX,XX @@ void HELPER(crypto_sm3partw2)(void *vd, void *vn, void *vm)
144
145
rd[0] = d.l[0];
146
rd[1] = d.l[1];
147
+
148
+ clear_tail_16(vd, desc);
149
}
150
151
void HELPER(crypto_sm3tt)(void *vd, void *vn, void *vm, uint32_t imm2,
152
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
153
index XXXXXXX..XXXXXXX 100644
93
index XXXXXXX..XXXXXXX 100644
154
--- a/target/arm/translate-a64.c
94
--- a/target/arm/translate-mve.c
155
+++ b/target/arm/translate-a64.c
95
+++ b/target/arm/translate-mve.c
156
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
96
@@ -XXX,XX +XXX,XX @@ bool mve_eci_check(DisasContext *s)
157
int rn = extract32(insn, 5, 5);
158
int rd = extract32(insn, 0, 5);
159
bool feature;
160
- CryptoThreeOpFn *genfn = NULL;
161
gen_helper_gvec_3 *oolfn = NULL;
162
GVecGen3Fn *gvecfn = NULL;
163
164
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
165
switch (opcode) {
166
case 0: /* SHA512H */
167
feature = dc_isar_feature(aa64_sha512, s);
168
- genfn = gen_helper_crypto_sha512h;
169
+ oolfn = gen_helper_crypto_sha512h;
170
break;
171
case 1: /* SHA512H2 */
172
feature = dc_isar_feature(aa64_sha512, s);
173
- genfn = gen_helper_crypto_sha512h2;
174
+ oolfn = gen_helper_crypto_sha512h2;
175
break;
176
case 2: /* SHA512SU1 */
177
feature = dc_isar_feature(aa64_sha512, s);
178
- genfn = gen_helper_crypto_sha512su1;
179
+ oolfn = gen_helper_crypto_sha512su1;
180
break;
181
case 3: /* RAX1 */
182
feature = dc_isar_feature(aa64_sha3, s);
183
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
184
switch (opcode) {
185
case 0: /* SM3PARTW1 */
186
feature = dc_isar_feature(aa64_sm3, s);
187
- genfn = gen_helper_crypto_sm3partw1;
188
+ oolfn = gen_helper_crypto_sm3partw1;
189
break;
190
case 1: /* SM3PARTW2 */
191
feature = dc_isar_feature(aa64_sm3, s);
192
- genfn = gen_helper_crypto_sm3partw2;
193
+ oolfn = gen_helper_crypto_sm3partw2;
194
break;
195
case 2: /* SM4EKEY */
196
feature = dc_isar_feature(aa64_sm4, s);
197
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
198
199
if (oolfn) {
200
gen_gvec_op3_ool(s, true, rd, rn, rm, 0, oolfn);
201
- } else if (gvecfn) {
202
- gen_gvec_fn3(s, true, rd, rn, rm, gvecfn, MO_64);
203
} else {
204
- TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
205
-
206
- tcg_rd_ptr = vec_full_reg_ptr(s, rd);
207
- tcg_rn_ptr = vec_full_reg_ptr(s, rn);
208
- tcg_rm_ptr = vec_full_reg_ptr(s, rm);
209
-
210
- genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr);
211
-
212
- tcg_temp_free_ptr(tcg_rd_ptr);
213
- tcg_temp_free_ptr(tcg_rn_ptr);
214
- tcg_temp_free_ptr(tcg_rm_ptr);
215
+ gen_gvec_fn3(s, true, rd, rn, rm, gvecfn, MO_64);
216
}
97
}
217
}
98
}
218
99
219
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn)
100
-static void mve_update_eci(DisasContext *s)
220
int opcode = extract32(insn, 10, 2);
101
+void mve_update_eci(DisasContext *s)
221
int rn = extract32(insn, 5, 5);
102
{
222
int rd = extract32(insn, 0, 5);
103
/*
223
- TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
104
* The helper function will always update the CPUState field,
224
bool feature;
105
diff --git a/target/arm/translate.c b/target/arm/translate.c
225
- CryptoTwoOpFn *genfn;
106
index XXXXXXX..XXXXXXX 100644
226
- gen_helper_gvec_3 *oolfn = NULL;
107
--- a/target/arm/translate.c
227
108
+++ b/target/arm/translate.c
228
switch (opcode) {
109
@@ -XXX,XX +XXX,XX @@ static bool trans_LCTP(DisasContext *s, arg_LCTP *a)
229
case 0: /* SHA512SU0 */
110
return true;
230
feature = dc_isar_feature(aa64_sha512, s);
231
- genfn = gen_helper_crypto_sha512su0;
232
break;
233
case 1: /* SM4E */
234
feature = dc_isar_feature(aa64_sm4, s);
235
- oolfn = gen_helper_crypto_sm4e;
236
break;
237
default:
238
unallocated_encoding(s);
239
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn)
240
return;
241
}
242
243
- if (oolfn) {
244
- gen_gvec_op3_ool(s, true, rd, rd, rn, 0, oolfn);
245
- return;
246
+ switch (opcode) {
247
+ case 0: /* SHA512SU0 */
248
+ gen_gvec_op2_ool(s, true, rd, rn, 0, gen_helper_crypto_sha512su0);
249
+ break;
250
+ case 1: /* SM4E */
251
+ gen_gvec_op3_ool(s, true, rd, rd, rn, 0, gen_helper_crypto_sm4e);
252
+ break;
253
+ default:
254
+ g_assert_not_reached();
255
}
256
-
257
- tcg_rd_ptr = vec_full_reg_ptr(s, rd);
258
- tcg_rn_ptr = vec_full_reg_ptr(s, rn);
259
-
260
- genfn(tcg_rd_ptr, tcg_rn_ptr);
261
-
262
- tcg_temp_free_ptr(tcg_rd_ptr);
263
- tcg_temp_free_ptr(tcg_rn_ptr);
264
}
111
}
265
112
266
/* Crypto four-register
113
+static bool trans_VCTP(DisasContext *s, arg_VCTP *a)
114
+{
115
+ /*
116
+ * M-profile Create Vector Tail Predicate. This insn is itself
117
+ * predicated and is subject to beatwise execution.
118
+ */
119
+ TCGv_i32 rn_shifted, masklen;
120
+
121
+ if (!dc_isar_feature(aa32_mve, s) || a->rn == 13 || a->rn == 15) {
122
+ return false;
123
+ }
124
+
125
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
126
+ return true;
127
+ }
128
+
129
+ /*
130
+ * We pre-calculate the mask length here to avoid having
131
+ * to have multiple helpers specialized for size.
132
+ * We pass the helper "rn <= (1 << (4 - size)) ? (rn << size) : 16".
133
+ */
134
+ rn_shifted = tcg_temp_new_i32();
135
+ masklen = load_reg(s, a->rn);
136
+ tcg_gen_shli_i32(rn_shifted, masklen, a->size);
137
+ tcg_gen_movcond_i32(TCG_COND_LEU, masklen,
138
+ masklen, tcg_constant_i32(1 << (4 - a->size)),
139
+ rn_shifted, tcg_constant_i32(16));
140
+ gen_helper_mve_vctp(cpu_env, masklen);
141
+ tcg_temp_free_i32(masklen);
142
+ tcg_temp_free_i32(rn_shifted);
143
+ mve_update_eci(s);
144
+ return true;
145
+}
146
147
static bool op_tbranch(DisasContext *s, arg_tbranch *a, bool half)
148
{
267
--
149
--
268
2.20.1
150
2.20.1
269
151
270
152
diff view generated by jsdifflib
1
Convert the Neon narrowing shifts where op==8 to decodetree:
1
Implement the MVE gather-loads and scatter-stores which
2
* VSHRN
2
form the address by adding a base value from a scalar
3
* VRSHRN
3
register to an offset in each element of a vector.
4
* VQSHRUN
5
* VQRSHRUN
6
4
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20200522145520.6778-6-peter.maydell@linaro.org
10
---
7
---
11
target/arm/neon-dp.decode | 27 ++++++
8
target/arm/helper-mve.h | 32 +++++++++
12
target/arm/translate-neon.inc.c | 167 ++++++++++++++++++++++++++++++++
9
target/arm/mve.decode | 12 ++++
13
target/arm/translate.c | 1 +
10
target/arm/mve_helper.c | 129 +++++++++++++++++++++++++++++++++++++
14
3 files changed, 195 insertions(+)
11
target/arm/translate-mve.c | 97 ++++++++++++++++++++++++++++
12
4 files changed, 270 insertions(+)
15
13
16
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
14
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
17
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/neon-dp.decode
16
--- a/target/arm/helper-mve.h
19
+++ b/target/arm/neon-dp.decode
17
+++ b/target/arm/helper-mve.h
20
@@ -XXX,XX +XXX,XX @@ VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
18
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_3(mve_vstrb_h, TCG_CALL_NO_WG, void, env, ptr, i32)
21
@2reg_shl_b .... ... . . . 001 shift:3 .... .... 0 q:1 . . .... \
19
DEF_HELPER_FLAGS_3(mve_vstrb_w, TCG_CALL_NO_WG, void, env, ptr, i32)
22
&2reg_shift vm=%vm_dp vd=%vd_dp size=0
20
DEF_HELPER_FLAGS_3(mve_vstrh_w, TCG_CALL_NO_WG, void, env, ptr, i32)
23
21
24
+# Narrowing right shifts: here the Q bit is part of the opcode decode
22
+DEF_HELPER_FLAGS_4(mve_vldrb_sg_sh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
+@2reg_shrn_d .... ... . . . 1 ..... .... .... 0 . . . .... \
23
+DEF_HELPER_FLAGS_4(mve_vldrb_sg_sw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
26
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=3 q=0 \
24
+DEF_HELPER_FLAGS_4(mve_vldrh_sg_sw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
27
+ shift=%neon_rshift_i5
25
+
28
+@2reg_shrn_s .... ... . . . 01 .... .... .... 0 . . . .... \
26
+DEF_HELPER_FLAGS_4(mve_vldrb_sg_ub, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
29
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=2 q=0 \
27
+DEF_HELPER_FLAGS_4(mve_vldrb_sg_uh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
30
+ shift=%neon_rshift_i4
28
+DEF_HELPER_FLAGS_4(mve_vldrb_sg_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
31
+@2reg_shrn_h .... ... . . . 001 ... .... .... 0 . . . .... \
29
+DEF_HELPER_FLAGS_4(mve_vldrh_sg_uh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
32
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=1 q=0 \
30
+DEF_HELPER_FLAGS_4(mve_vldrh_sg_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
33
+ shift=%neon_rshift_i3
31
+DEF_HELPER_FLAGS_4(mve_vldrw_sg_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
34
+
32
+DEF_HELPER_FLAGS_4(mve_vldrd_sg_ud, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
35
VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_d
33
+
36
VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_s
34
+DEF_HELPER_FLAGS_4(mve_vstrb_sg_ub, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
37
VSHR_S_2sh 1111 001 0 1 . ...... .... 0000 . . . 1 .... @2reg_shr_h
35
+DEF_HELPER_FLAGS_4(mve_vstrb_sg_uh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
38
@@ -XXX,XX +XXX,XX @@ VQSHL_U_64_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_d
36
+DEF_HELPER_FLAGS_4(mve_vstrb_sg_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
39
VQSHL_U_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_s
37
+DEF_HELPER_FLAGS_4(mve_vstrh_sg_uh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
40
VQSHL_U_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_h
38
+DEF_HELPER_FLAGS_4(mve_vstrh_sg_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
41
VQSHL_U_2sh 1111 001 1 1 . ...... .... 0111 . . . 1 .... @2reg_shl_b
39
+DEF_HELPER_FLAGS_4(mve_vstrw_sg_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
42
+
40
+DEF_HELPER_FLAGS_4(mve_vstrd_sg_ud, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
43
+VSHRN_64_2sh 1111 001 0 1 . ...... .... 1000 . 0 . 1 .... @2reg_shrn_d
41
+
44
+VSHRN_32_2sh 1111 001 0 1 . ...... .... 1000 . 0 . 1 .... @2reg_shrn_s
42
+DEF_HELPER_FLAGS_4(mve_vldrh_sg_os_sw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
45
+VSHRN_16_2sh 1111 001 0 1 . ...... .... 1000 . 0 . 1 .... @2reg_shrn_h
43
+
46
+
44
+DEF_HELPER_FLAGS_4(mve_vldrh_sg_os_uh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
47
+VRSHRN_64_2sh 1111 001 0 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_d
45
+DEF_HELPER_FLAGS_4(mve_vldrh_sg_os_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
48
+VRSHRN_32_2sh 1111 001 0 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_s
46
+DEF_HELPER_FLAGS_4(mve_vldrw_sg_os_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
49
+VRSHRN_16_2sh 1111 001 0 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_h
47
+DEF_HELPER_FLAGS_4(mve_vldrd_sg_os_ud, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
50
+
48
+
51
+VQSHRUN_64_2sh 1111 001 1 1 . ...... .... 1000 . 0 . 1 .... @2reg_shrn_d
49
+DEF_HELPER_FLAGS_4(mve_vstrh_sg_os_uh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
52
+VQSHRUN_32_2sh 1111 001 1 1 . ...... .... 1000 . 0 . 1 .... @2reg_shrn_s
50
+DEF_HELPER_FLAGS_4(mve_vstrh_sg_os_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
53
+VQSHRUN_16_2sh 1111 001 1 1 . ...... .... 1000 . 0 . 1 .... @2reg_shrn_h
51
+DEF_HELPER_FLAGS_4(mve_vstrw_sg_os_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
54
+
52
+DEF_HELPER_FLAGS_4(mve_vstrd_sg_os_ud, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
55
+VQRSHRUN_64_2sh 1111 001 1 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_d
53
+
56
+VQRSHRUN_32_2sh 1111 001 1 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_s
54
DEF_HELPER_FLAGS_3(mve_vdup, TCG_CALL_NO_WG, void, env, ptr, i32)
57
+VQRSHRUN_16_2sh 1111 001 1 1 . ...... .... 1000 . 1 . 1 .... @2reg_shrn_h
55
58
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
56
DEF_HELPER_FLAGS_4(mve_vidupb, TCG_CALL_NO_WG, i32, env, ptr, i32, i32)
57
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
59
index XXXXXXX..XXXXXXX 100644
58
index XXXXXXX..XXXXXXX 100644
60
--- a/target/arm/translate-neon.inc.c
59
--- a/target/arm/mve.decode
61
+++ b/target/arm/translate-neon.inc.c
60
+++ b/target/arm/mve.decode
62
@@ -XXX,XX +XXX,XX @@ static bool do_2shift_env_32(DisasContext *s, arg_2reg_shift *a,
61
@@ -XXX,XX +XXX,XX @@
63
DO_2SHIFT_ENV(VQSHLU, qshlu_s)
62
&shl_scalar qda rm size
64
DO_2SHIFT_ENV(VQSHL_U, qshl_u)
63
&vmaxv qm rda size
65
DO_2SHIFT_ENV(VQSHL_S, qshl_s)
64
&vabav qn qm rda size
66
+
65
+&vldst_sg qd qm rn size msize os
67
+static bool do_2shift_narrow_64(DisasContext *s, arg_2reg_shift *a,
66
+
68
+ NeonGenTwo64OpFn *shiftfn,
67
+# scatter-gather memory size is in bits 6:4
69
+ NeonGenNarrowEnvFn *narrowfn)
68
+%sg_msize 6:1 4:1
69
70
@vldr_vstr ....... . . . . l:1 rn:4 ... ...... imm:7 &vldr_vstr qd=%qd u=0
71
# Note that both Rn and Qd are 3 bits only (no D bit)
72
@vldst_wn ... u:1 ... . . . . l:1 . rn:3 qd:3 . ... .. imm:7 &vldr_vstr
73
74
+@vldst_sg .... .... .... rn:4 .... ... size:2 ... ... os:1 &vldst_sg \
75
+ qd=%qd qm=%qm msize=%sg_msize
76
+
77
@1op .... .... .... size:2 .. .... .... .... .... &1op qd=%qd qm=%qm
78
@1op_nosz .... .... .... .... .... .... .... .... &1op qd=%qd qm=%qm size=0
79
@2op .... .... .. size:2 .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn
80
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111101 ....... @vldr_vstr \
81
VLDR_VSTR 1110110 1 a:1 . w:1 . .... ... 111110 ....... @vldr_vstr \
82
size=2 p=1
83
84
+# gather loads/scatter stores
85
+VLDR_S_sg 111 0 1100 1 . 01 .... ... 0 111 . .... .... @vldst_sg
86
+VLDR_U_sg 111 1 1100 1 . 01 .... ... 0 111 . .... .... @vldst_sg
87
+VSTR_sg 111 0 1100 1 . 00 .... ... 0 111 . .... .... @vldst_sg
88
+
89
# Moves between 2 32-bit vector lanes and 2 general purpose registers
90
VMOV_to_2gp 1110 1100 0 . 00 rt2:4 ... 0 1111 000 idx:1 rt:4 qd=%qd
91
VMOV_from_2gp 1110 1100 0 . 01 rt2:4 ... 0 1111 000 idx:1 rt:4 qd=%qd
92
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
93
index XXXXXXX..XXXXXXX 100644
94
--- a/target/arm/mve_helper.c
95
+++ b/target/arm/mve_helper.c
96
@@ -XXX,XX +XXX,XX @@ DO_VSTR(vstrh_w, 2, stw, 4, int32_t)
97
#undef DO_VLDR
98
#undef DO_VSTR
99
100
+/*
101
+ * Gather loads/scatter stores. Here each element of Qm specifies
102
+ * an offset to use from the base register Rm. In the _os_ versions
103
+ * that offset is scaled by the element size.
104
+ * For loads, predicated lanes are zeroed instead of retaining
105
+ * their previous values.
106
+ */
107
+#define DO_VLDR_SG(OP, LDTYPE, ESIZE, TYPE, OFFTYPE, ADDRFN) \
108
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm, \
109
+ uint32_t base) \
110
+ { \
111
+ TYPE *d = vd; \
112
+ OFFTYPE *m = vm; \
113
+ uint16_t mask = mve_element_mask(env); \
114
+ uint16_t eci_mask = mve_eci_mask(env); \
115
+ unsigned e; \
116
+ uint32_t addr; \
117
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE, eci_mask >>= ESIZE) { \
118
+ if (!(eci_mask & 1)) { \
119
+ continue; \
120
+ } \
121
+ addr = ADDRFN(base, m[H##ESIZE(e)]); \
122
+ d[H##ESIZE(e)] = (mask & 1) ? \
123
+ cpu_##LDTYPE##_data_ra(env, addr, GETPC()) : 0; \
124
+ } \
125
+ mve_advance_vpt(env); \
126
+ }
127
+
128
+/* We know here TYPE is unsigned so always the same as the offset type */
129
+#define DO_VSTR_SG(OP, STTYPE, ESIZE, TYPE, ADDRFN) \
130
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm, \
131
+ uint32_t base) \
132
+ { \
133
+ TYPE *d = vd; \
134
+ TYPE *m = vm; \
135
+ uint16_t mask = mve_element_mask(env); \
136
+ unsigned e; \
137
+ uint32_t addr; \
138
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
139
+ addr = ADDRFN(base, m[H##ESIZE(e)]); \
140
+ if (mask & 1) { \
141
+ cpu_##STTYPE##_data_ra(env, addr, d[H##ESIZE(e)], GETPC()); \
142
+ } \
143
+ } \
144
+ mve_advance_vpt(env); \
145
+ }
146
+
147
+/*
148
+ * 64-bit accesses are slightly different: they are done as two 32-bit
149
+ * accesses, controlled by the predicate mask for the relevant beat,
150
+ * and with a single 32-bit offset in the first of the two Qm elements.
151
+ * Note that for QEMU our IMPDEF AIRCR.ENDIANNESS is always 0 (little).
152
+ */
153
+#define DO_VLDR64_SG(OP, ADDRFN) \
154
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm, \
155
+ uint32_t base) \
156
+ { \
157
+ uint32_t *d = vd; \
158
+ uint32_t *m = vm; \
159
+ uint16_t mask = mve_element_mask(env); \
160
+ uint16_t eci_mask = mve_eci_mask(env); \
161
+ unsigned e; \
162
+ uint32_t addr; \
163
+ for (e = 0; e < 16 / 4; e++, mask >>= 4, eci_mask >>= 4) { \
164
+ if (!(eci_mask & 1)) { \
165
+ continue; \
166
+ } \
167
+ addr = ADDRFN(base, m[H4(e & ~1)]); \
168
+ addr += 4 * (e & 1); \
169
+ d[H4(e)] = (mask & 1) ? cpu_ldl_data_ra(env, addr, GETPC()) : 0; \
170
+ } \
171
+ mve_advance_vpt(env); \
172
+ }
173
+
174
+#define DO_VSTR64_SG(OP, ADDRFN) \
175
+ void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm, \
176
+ uint32_t base) \
177
+ { \
178
+ uint32_t *d = vd; \
179
+ uint32_t *m = vm; \
180
+ uint16_t mask = mve_element_mask(env); \
181
+ unsigned e; \
182
+ uint32_t addr; \
183
+ for (e = 0; e < 16 / 4; e++, mask >>= 4) { \
184
+ addr = ADDRFN(base, m[H4(e & ~1)]); \
185
+ addr += 4 * (e & 1); \
186
+ if (mask & 1) { \
187
+ cpu_stl_data_ra(env, addr, d[H4(e)], GETPC()); \
188
+ } \
189
+ } \
190
+ mve_advance_vpt(env); \
191
+ }
192
+
193
+#define ADDR_ADD(BASE, OFFSET) ((BASE) + (OFFSET))
194
+#define ADDR_ADD_OSH(BASE, OFFSET) ((BASE) + ((OFFSET) << 1))
195
+#define ADDR_ADD_OSW(BASE, OFFSET) ((BASE) + ((OFFSET) << 2))
196
+#define ADDR_ADD_OSD(BASE, OFFSET) ((BASE) + ((OFFSET) << 3))
197
+
198
+DO_VLDR_SG(vldrb_sg_sh, ldsb, 2, int16_t, uint16_t, ADDR_ADD)
199
+DO_VLDR_SG(vldrb_sg_sw, ldsb, 4, int32_t, uint32_t, ADDR_ADD)
200
+DO_VLDR_SG(vldrh_sg_sw, ldsw, 4, int32_t, uint32_t, ADDR_ADD)
201
+
202
+DO_VLDR_SG(vldrb_sg_ub, ldub, 1, uint8_t, uint8_t, ADDR_ADD)
203
+DO_VLDR_SG(vldrb_sg_uh, ldub, 2, uint16_t, uint16_t, ADDR_ADD)
204
+DO_VLDR_SG(vldrb_sg_uw, ldub, 4, uint32_t, uint32_t, ADDR_ADD)
205
+DO_VLDR_SG(vldrh_sg_uh, lduw, 2, uint16_t, uint16_t, ADDR_ADD)
206
+DO_VLDR_SG(vldrh_sg_uw, lduw, 4, uint32_t, uint32_t, ADDR_ADD)
207
+DO_VLDR_SG(vldrw_sg_uw, ldl, 4, uint32_t, uint32_t, ADDR_ADD)
208
+DO_VLDR64_SG(vldrd_sg_ud, ADDR_ADD)
209
+
210
+DO_VLDR_SG(vldrh_sg_os_sw, ldsw, 4, int32_t, uint32_t, ADDR_ADD_OSH)
211
+DO_VLDR_SG(vldrh_sg_os_uh, lduw, 2, uint16_t, uint16_t, ADDR_ADD_OSH)
212
+DO_VLDR_SG(vldrh_sg_os_uw, lduw, 4, uint32_t, uint32_t, ADDR_ADD_OSH)
213
+DO_VLDR_SG(vldrw_sg_os_uw, ldl, 4, uint32_t, uint32_t, ADDR_ADD_OSW)
214
+DO_VLDR64_SG(vldrd_sg_os_ud, ADDR_ADD_OSD)
215
+
216
+DO_VSTR_SG(vstrb_sg_ub, stb, 1, uint8_t, ADDR_ADD)
217
+DO_VSTR_SG(vstrb_sg_uh, stb, 2, uint16_t, ADDR_ADD)
218
+DO_VSTR_SG(vstrb_sg_uw, stb, 4, uint32_t, ADDR_ADD)
219
+DO_VSTR_SG(vstrh_sg_uh, stw, 2, uint16_t, ADDR_ADD)
220
+DO_VSTR_SG(vstrh_sg_uw, stw, 4, uint32_t, ADDR_ADD)
221
+DO_VSTR_SG(vstrw_sg_uw, stl, 4, uint32_t, ADDR_ADD)
222
+DO_VSTR64_SG(vstrd_sg_ud, ADDR_ADD)
223
+
224
+DO_VSTR_SG(vstrh_sg_os_uh, stw, 2, uint16_t, ADDR_ADD_OSH)
225
+DO_VSTR_SG(vstrh_sg_os_uw, stw, 4, uint32_t, ADDR_ADD_OSH)
226
+DO_VSTR_SG(vstrw_sg_os_uw, stl, 4, uint32_t, ADDR_ADD_OSW)
227
+DO_VSTR64_SG(vstrd_sg_os_ud, ADDR_ADD_OSD)
228
+
229
/*
230
* The mergemask(D, R, M) macro performs the operation "*D = R" but
231
* storing only the bytes which correspond to 1 bits in M,
232
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
233
index XXXXXXX..XXXXXXX 100644
234
--- a/target/arm/translate-mve.c
235
+++ b/target/arm/translate-mve.c
236
@@ -XXX,XX +XXX,XX @@ static inline int vidup_imm(DisasContext *s, int x)
237
#include "decode-mve.c.inc"
238
239
typedef void MVEGenLdStFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
240
+typedef void MVEGenLdStSGFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
241
typedef void MVEGenOneOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
242
typedef void MVEGenTwoOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr);
243
typedef void MVEGenTwoOpScalarFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
244
@@ -XXX,XX +XXX,XX @@ DO_VLDST_WIDE_NARROW(VLDSTB_H, vldrb_sh, vldrb_uh, vstrb_h, MO_8)
245
DO_VLDST_WIDE_NARROW(VLDSTB_W, vldrb_sw, vldrb_uw, vstrb_w, MO_8)
246
DO_VLDST_WIDE_NARROW(VLDSTH_W, vldrh_sw, vldrh_uw, vstrh_w, MO_16)
247
248
+static bool do_ldst_sg(DisasContext *s, arg_vldst_sg *a, MVEGenLdStSGFn fn)
70
+{
249
+{
71
+ /* 2-reg-and-shift narrowing-shift operations, size == 3 case */
250
+ TCGv_i32 addr;
72
+ TCGv_i64 constimm, rm1, rm2;
251
+ TCGv_ptr qd, qm;
73
+ TCGv_i32 rd;
252
+
74
+
253
+ if (!dc_isar_feature(aa32_mve, s) ||
75
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
254
+ !mve_check_qreg_bank(s, a->qd | a->qm) ||
255
+ !fn || a->rn == 15) {
256
+ /* Rn case is UNPREDICTABLE */
76
+ return false;
257
+ return false;
77
+ }
258
+ }
78
+
259
+
79
+ /* UNDEF accesses to D16-D31 if they don't exist. */
260
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
80
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
81
+ ((a->vd | a->vm) & 0x10)) {
82
+ return false;
83
+ }
84
+
85
+ if (a->vm & 1) {
86
+ return false;
87
+ }
88
+
89
+ if (!vfp_access_check(s)) {
90
+ return true;
261
+ return true;
91
+ }
262
+ }
92
+
263
+
93
+ /*
264
+ addr = load_reg(s, a->rn);
94
+ * This is always a right shift, and the shiftfn is always a
265
+
95
+ * left-shift helper, which thus needs the negated shift count.
266
+ qd = mve_qreg_ptr(a->qd);
96
+ */
267
+ qm = mve_qreg_ptr(a->qm);
97
+ constimm = tcg_const_i64(-a->shift);
268
+ fn(cpu_env, qd, qm, addr);
98
+ rm1 = tcg_temp_new_i64();
269
+ tcg_temp_free_ptr(qd);
99
+ rm2 = tcg_temp_new_i64();
270
+ tcg_temp_free_ptr(qm);
100
+
271
+ tcg_temp_free_i32(addr);
101
+ /* Load both inputs first to avoid potential overwrite if rm == rd */
272
+ mve_update_eci(s);
102
+ neon_load_reg64(rm1, a->vm);
103
+ neon_load_reg64(rm2, a->vm + 1);
104
+
105
+ shiftfn(rm1, rm1, constimm);
106
+ rd = tcg_temp_new_i32();
107
+ narrowfn(rd, cpu_env, rm1);
108
+ neon_store_reg(a->vd, 0, rd);
109
+
110
+ shiftfn(rm2, rm2, constimm);
111
+ rd = tcg_temp_new_i32();
112
+ narrowfn(rd, cpu_env, rm2);
113
+ neon_store_reg(a->vd, 1, rd);
114
+
115
+ tcg_temp_free_i64(rm1);
116
+ tcg_temp_free_i64(rm2);
117
+ tcg_temp_free_i64(constimm);
118
+
119
+ return true;
273
+ return true;
120
+}
274
+}
121
+
275
+
122
+static bool do_2shift_narrow_32(DisasContext *s, arg_2reg_shift *a,
276
+/*
123
+ NeonGenTwoOpFn *shiftfn,
277
+ * The naming scheme here is "vldrb_sg_sh == in-memory byte loads
124
+ NeonGenNarrowEnvFn *narrowfn)
278
+ * signextended to halfword elements in register". _os_ indicates that
279
+ * the offsets in Qm should be scaled by the element size.
280
+ */
281
+/* This macro is just to make the arrays more compact in these functions */
282
+#define F(N) gen_helper_mve_##N
283
+
284
+/* VLDRB/VSTRB (ie msize 1) with OS=1 is UNPREDICTABLE; we UNDEF */
285
+static bool trans_VLDR_S_sg(DisasContext *s, arg_vldst_sg *a)
125
+{
286
+{
126
+ /* 2-reg-and-shift narrowing-shift operations, size < 3 case */
287
+ static MVEGenLdStSGFn * const fns[2][4][4] = { {
127
+ TCGv_i32 constimm, rm1, rm2, rm3, rm4;
288
+ { NULL, F(vldrb_sg_sh), F(vldrb_sg_sw), NULL },
128
+ TCGv_i64 rtmp;
289
+ { NULL, NULL, F(vldrh_sg_sw), NULL },
129
+ uint32_t imm;
290
+ { NULL, NULL, NULL, NULL },
130
+
291
+ { NULL, NULL, NULL, NULL }
131
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
292
+ }, {
132
+ return false;
293
+ { NULL, NULL, NULL, NULL },
133
+ }
294
+ { NULL, NULL, F(vldrh_sg_os_sw), NULL },
134
+
295
+ { NULL, NULL, NULL, NULL },
135
+ /* UNDEF accesses to D16-D31 if they don't exist. */
296
+ { NULL, NULL, NULL, NULL }
136
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
297
+ }
137
+ ((a->vd | a->vm) & 0x10)) {
298
+ };
138
+ return false;
299
+ if (a->qd == a->qm) {
139
+ }
300
+ return false; /* UNPREDICTABLE */
140
+
301
+ }
141
+ if (a->vm & 1) {
302
+ return do_ldst_sg(s, a, fns[a->os][a->msize][a->size]);
142
+ return false;
143
+ }
144
+
145
+ if (!vfp_access_check(s)) {
146
+ return true;
147
+ }
148
+
149
+ /*
150
+ * This is always a right shift, and the shiftfn is always a
151
+ * left-shift helper, which thus needs the negated shift count
152
+ * duplicated into each lane of the immediate value.
153
+ */
154
+ if (a->size == 1) {
155
+ imm = (uint16_t)(-a->shift);
156
+ imm |= imm << 16;
157
+ } else {
158
+ /* size == 2 */
159
+ imm = -a->shift;
160
+ }
161
+ constimm = tcg_const_i32(imm);
162
+
163
+ /* Load all inputs first to avoid potential overwrite */
164
+ rm1 = neon_load_reg(a->vm, 0);
165
+ rm2 = neon_load_reg(a->vm, 1);
166
+ rm3 = neon_load_reg(a->vm + 1, 0);
167
+ rm4 = neon_load_reg(a->vm + 1, 1);
168
+ rtmp = tcg_temp_new_i64();
169
+
170
+ shiftfn(rm1, rm1, constimm);
171
+ shiftfn(rm2, rm2, constimm);
172
+
173
+ tcg_gen_concat_i32_i64(rtmp, rm1, rm2);
174
+ tcg_temp_free_i32(rm2);
175
+
176
+ narrowfn(rm1, cpu_env, rtmp);
177
+ neon_store_reg(a->vd, 0, rm1);
178
+
179
+ shiftfn(rm3, rm3, constimm);
180
+ shiftfn(rm4, rm4, constimm);
181
+ tcg_temp_free_i32(constimm);
182
+
183
+ tcg_gen_concat_i32_i64(rtmp, rm3, rm4);
184
+ tcg_temp_free_i32(rm4);
185
+
186
+ narrowfn(rm3, cpu_env, rtmp);
187
+ tcg_temp_free_i64(rtmp);
188
+ neon_store_reg(a->vd, 1, rm3);
189
+ return true;
190
+}
303
+}
191
+
304
+
192
+#define DO_2SN_64(INSN, FUNC, NARROWFUNC) \
305
+static bool trans_VLDR_U_sg(DisasContext *s, arg_vldst_sg *a)
193
+ static bool trans_##INSN##_2sh(DisasContext *s, arg_2reg_shift *a) \
194
+ { \
195
+ return do_2shift_narrow_64(s, a, FUNC, NARROWFUNC); \
196
+ }
197
+#define DO_2SN_32(INSN, FUNC, NARROWFUNC) \
198
+ static bool trans_##INSN##_2sh(DisasContext *s, arg_2reg_shift *a) \
199
+ { \
200
+ return do_2shift_narrow_32(s, a, FUNC, NARROWFUNC); \
201
+ }
202
+
203
+static void gen_neon_narrow_u32(TCGv_i32 dest, TCGv_ptr env, TCGv_i64 src)
204
+{
306
+{
205
+ tcg_gen_extrl_i64_i32(dest, src);
307
+ static MVEGenLdStSGFn * const fns[2][4][4] = { {
308
+ { F(vldrb_sg_ub), F(vldrb_sg_uh), F(vldrb_sg_uw), NULL },
309
+ { NULL, F(vldrh_sg_uh), F(vldrh_sg_uw), NULL },
310
+ { NULL, NULL, F(vldrw_sg_uw), NULL },
311
+ { NULL, NULL, NULL, F(vldrd_sg_ud) }
312
+ }, {
313
+ { NULL, NULL, NULL, NULL },
314
+ { NULL, F(vldrh_sg_os_uh), F(vldrh_sg_os_uw), NULL },
315
+ { NULL, NULL, F(vldrw_sg_os_uw), NULL },
316
+ { NULL, NULL, NULL, F(vldrd_sg_os_ud) }
317
+ }
318
+ };
319
+ if (a->qd == a->qm) {
320
+ return false; /* UNPREDICTABLE */
321
+ }
322
+ return do_ldst_sg(s, a, fns[a->os][a->msize][a->size]);
206
+}
323
+}
207
+
324
+
208
+static void gen_neon_narrow_u16(TCGv_i32 dest, TCGv_ptr env, TCGv_i64 src)
325
+static bool trans_VSTR_sg(DisasContext *s, arg_vldst_sg *a)
209
+{
326
+{
210
+ gen_helper_neon_narrow_u16(dest, src);
327
+ static MVEGenLdStSGFn * const fns[2][4][4] = { {
328
+ { F(vstrb_sg_ub), F(vstrb_sg_uh), F(vstrb_sg_uw), NULL },
329
+ { NULL, F(vstrh_sg_uh), F(vstrh_sg_uw), NULL },
330
+ { NULL, NULL, F(vstrw_sg_uw), NULL },
331
+ { NULL, NULL, NULL, F(vstrd_sg_ud) }
332
+ }, {
333
+ { NULL, NULL, NULL, NULL },
334
+ { NULL, F(vstrh_sg_os_uh), F(vstrh_sg_os_uw), NULL },
335
+ { NULL, NULL, F(vstrw_sg_os_uw), NULL },
336
+ { NULL, NULL, NULL, F(vstrd_sg_os_ud) }
337
+ }
338
+ };
339
+ return do_ldst_sg(s, a, fns[a->os][a->msize][a->size]);
211
+}
340
+}
212
+
341
+
213
+static void gen_neon_narrow_u8(TCGv_i32 dest, TCGv_ptr env, TCGv_i64 src)
342
+#undef F
214
+{
343
+
215
+ gen_helper_neon_narrow_u8(dest, src);
344
static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
216
+}
345
{
217
+
346
TCGv_ptr qd;
218
+DO_2SN_64(VSHRN_64, gen_ushl_i64, gen_neon_narrow_u32)
219
+DO_2SN_32(VSHRN_32, gen_ushl_i32, gen_neon_narrow_u16)
220
+DO_2SN_32(VSHRN_16, gen_helper_neon_shl_u16, gen_neon_narrow_u8)
221
+
222
+DO_2SN_64(VRSHRN_64, gen_helper_neon_rshl_u64, gen_neon_narrow_u32)
223
+DO_2SN_32(VRSHRN_32, gen_helper_neon_rshl_u32, gen_neon_narrow_u16)
224
+DO_2SN_32(VRSHRN_16, gen_helper_neon_rshl_u16, gen_neon_narrow_u8)
225
+
226
+DO_2SN_64(VQSHRUN_64, gen_sshl_i64, gen_helper_neon_unarrow_sat32)
227
+DO_2SN_32(VQSHRUN_32, gen_sshl_i32, gen_helper_neon_unarrow_sat16)
228
+DO_2SN_32(VQSHRUN_16, gen_helper_neon_shl_s16, gen_helper_neon_unarrow_sat8)
229
+
230
+DO_2SN_64(VQRSHRUN_64, gen_helper_neon_rshl_s64, gen_helper_neon_unarrow_sat32)
231
+DO_2SN_32(VQRSHRUN_32, gen_helper_neon_rshl_s32, gen_helper_neon_unarrow_sat16)
232
+DO_2SN_32(VQRSHRUN_16, gen_helper_neon_rshl_s16, gen_helper_neon_unarrow_sat8)
233
diff --git a/target/arm/translate.c b/target/arm/translate.c
234
index XXXXXXX..XXXXXXX 100644
235
--- a/target/arm/translate.c
236
+++ b/target/arm/translate.c
237
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
238
case 5: /* VSHL, VSLI */
239
case 6: /* VQSHLU */
240
case 7: /* VQSHL */
241
+ case 8: /* VSHRN, VRSHRN, VQSHRUN, VQRSHRUN */
242
return 1; /* handled by decodetree */
243
default:
244
break;
245
--
347
--
246
2.20.1
348
2.20.1
247
349
248
350
diff view generated by jsdifflib
1
Convert the VSHL and VSLI insns from the Neon 2-registers-and-a-shift
1
Implement the MVE VLDR/VSTR insns which do scatter-gather using base
2
group to decodetree.
2
addresses from Qm plus or minus an immediate offset (possibly with
3
writeback). Note that writeback is not predicated but it does have
4
to honour ECI state, so we have to add an eci_mask check to the
5
VSTR_SG macros (the VLDR_SG macros already needed this to be able
6
to distinguish "skip beat" from "set predicated element to 0").
3
7
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20200522145520.6778-2-peter.maydell@linaro.org
7
---
10
---
8
target/arm/neon-dp.decode | 25 ++++++++++++++++++++++
11
target/arm/helper-mve.h | 5 +++
9
target/arm/translate-neon.inc.c | 38 +++++++++++++++++++++++++++++++++
12
target/arm/mve.decode | 10 +++++
10
target/arm/translate.c | 18 +++++++---------
13
target/arm/mve_helper.c | 91 ++++++++++++++++++++++++--------------
11
3 files changed, 71 insertions(+), 10 deletions(-)
14
target/arm/translate-mve.c | 72 ++++++++++++++++++++++++++++++
15
4 files changed, 146 insertions(+), 32 deletions(-)
12
16
13
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
17
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
14
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/neon-dp.decode
19
--- a/target/arm/helper-mve.h
16
+++ b/target/arm/neon-dp.decode
20
+++ b/target/arm/helper-mve.h
17
@@ -XXX,XX +XXX,XX @@ VRECPS_fp_3s 1111 001 0 0 . 0 . .... .... 1111 ... 1 .... @3same_fp
21
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vstrh_sg_os_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
18
VRSQRTS_fp_3s 1111 001 0 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
22
DEF_HELPER_FLAGS_4(mve_vstrw_sg_os_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
19
VMAXNM_fp_3s 1111 001 1 0 . 0 . .... .... 1111 ... 1 .... @3same_fp
23
DEF_HELPER_FLAGS_4(mve_vstrd_sg_os_ud, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
20
VMINNM_fp_3s 1111 001 1 0 . 1 . .... .... 1111 ... 1 .... @3same_fp
24
21
+
25
+DEF_HELPER_FLAGS_4(mve_vldrw_sg_wb_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
22
+######################################################################
26
+DEF_HELPER_FLAGS_4(mve_vldrd_sg_wb_ud, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
23
+# 2-reg-and-shift grouping:
27
+DEF_HELPER_FLAGS_4(mve_vstrw_sg_wb_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
24
+# 1111 001 U 1 D immH:3 immL:3 Vd:4 opc:4 L Q M 1 Vm:4
28
+DEF_HELPER_FLAGS_4(mve_vstrd_sg_wb_ud, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
+######################################################################
29
+
26
+&2reg_shift vm vd q shift size
30
DEF_HELPER_FLAGS_3(mve_vdup, TCG_CALL_NO_WG, void, env, ptr, i32)
27
+
31
28
+@2reg_shl_d .... ... . . . shift:6 .... .... 1 q:1 . . .... \
32
DEF_HELPER_FLAGS_4(mve_vidupb, TCG_CALL_NO_WG, i32, env, ptr, i32, i32)
29
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=3
33
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
30
+@2reg_shl_s .... ... . . . 1 shift:5 .... .... 0 q:1 . . .... \
31
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=2
32
+@2reg_shl_h .... ... . . . 01 shift:4 .... .... 0 q:1 . . .... \
33
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=1
34
+@2reg_shl_b .... ... . . . 001 shift:3 .... .... 0 q:1 . . .... \
35
+ &2reg_shift vm=%vm_dp vd=%vd_dp size=0
36
+
37
+VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_d
38
+VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_s
39
+VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_h
40
+VSHL_2sh 1111 001 0 1 . ...... .... 0101 . . . 1 .... @2reg_shl_b
41
+
42
+VSLI_2sh 1111 001 1 1 . ...... .... 0101 . . . 1 .... @2reg_shl_d
43
+VSLI_2sh 1111 001 1 1 . ...... .... 0101 . . . 1 .... @2reg_shl_s
44
+VSLI_2sh 1111 001 1 1 . ...... .... 0101 . . . 1 .... @2reg_shl_h
45
+VSLI_2sh 1111 001 1 1 . ...... .... 0101 . . . 1 .... @2reg_shl_b
46
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
47
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
48
--- a/target/arm/translate-neon.inc.c
35
--- a/target/arm/mve.decode
49
+++ b/target/arm/translate-neon.inc.c
36
+++ b/target/arm/mve.decode
50
@@ -XXX,XX +XXX,XX @@ static bool do_3same_fp_pair(DisasContext *s, arg_3same *a, VFPGen3OpSPFn *fn)
37
@@ -XXX,XX +XXX,XX @@
51
DO_3S_FP_PAIR(VPADD, gen_helper_vfp_adds)
38
&vmaxv qm rda size
52
DO_3S_FP_PAIR(VPMAX, gen_helper_vfp_maxs)
39
&vabav qn qm rda size
53
DO_3S_FP_PAIR(VPMIN, gen_helper_vfp_mins)
40
&vldst_sg qd qm rn size msize os
54
+
41
+&vldst_sg_imm qd qm a w imm
55
+static bool do_vector_2sh(DisasContext *s, arg_2reg_shift *a, GVecGen2iFn *fn)
42
56
+{
43
# scatter-gather memory size is in bits 6:4
57
+ /* Handle a 2-reg-shift insn which can be vectorized. */
44
%sg_msize 6:1 4:1
58
+ int vec_size = a->q ? 16 : 8;
45
@@ -XXX,XX +XXX,XX @@
59
+ int rd_ofs = neon_reg_offset(a->vd, 0);
46
@vldst_sg .... .... .... rn:4 .... ... size:2 ... ... os:1 &vldst_sg \
60
+ int rm_ofs = neon_reg_offset(a->vm, 0);
47
qd=%qd qm=%qm msize=%sg_msize
61
+
48
62
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
49
+# Qm is in the fields usually labeled Qn
50
+@vldst_sg_imm .... .... a:1 . w:1 . .... .... .... . imm:7 &vldst_sg_imm \
51
+ qd=%qd qm=%qn
52
+
53
@1op .... .... .... size:2 .. .... .... .... .... &1op qd=%qd qm=%qm
54
@1op_nosz .... .... .... .... .... .... .... .... &1op qd=%qd qm=%qm size=0
55
@2op .... .... .. size:2 .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn
56
@@ -XXX,XX +XXX,XX @@ VLDR_S_sg 111 0 1100 1 . 01 .... ... 0 111 . .... .... @vldst_sg
57
VLDR_U_sg 111 1 1100 1 . 01 .... ... 0 111 . .... .... @vldst_sg
58
VSTR_sg 111 0 1100 1 . 00 .... ... 0 111 . .... .... @vldst_sg
59
60
+VLDRW_sg_imm 111 1 1101 ... 1 ... 0 ... 1 1110 .... .... @vldst_sg_imm
61
+VLDRD_sg_imm 111 1 1101 ... 1 ... 0 ... 1 1111 .... .... @vldst_sg_imm
62
+VSTRW_sg_imm 111 1 1101 ... 0 ... 0 ... 1 1110 .... .... @vldst_sg_imm
63
+VSTRD_sg_imm 111 1 1101 ... 0 ... 0 ... 1 1111 .... .... @vldst_sg_imm
64
+
65
# Moves between 2 32-bit vector lanes and 2 general purpose registers
66
VMOV_to_2gp 1110 1100 0 . 00 rt2:4 ... 0 1111 000 idx:1 rt:4 qd=%qd
67
VMOV_from_2gp 1110 1100 0 . 01 rt2:4 ... 0 1111 000 idx:1 rt:4 qd=%qd
68
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
69
index XXXXXXX..XXXXXXX 100644
70
--- a/target/arm/mve_helper.c
71
+++ b/target/arm/mve_helper.c
72
@@ -XXX,XX +XXX,XX @@ DO_VSTR(vstrh_w, 2, stw, 4, int32_t)
73
* For loads, predicated lanes are zeroed instead of retaining
74
* their previous values.
75
*/
76
-#define DO_VLDR_SG(OP, LDTYPE, ESIZE, TYPE, OFFTYPE, ADDRFN) \
77
+#define DO_VLDR_SG(OP, LDTYPE, ESIZE, TYPE, OFFTYPE, ADDRFN, WB) \
78
void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm, \
79
uint32_t base) \
80
{ \
81
@@ -XXX,XX +XXX,XX @@ DO_VSTR(vstrh_w, 2, stw, 4, int32_t)
82
addr = ADDRFN(base, m[H##ESIZE(e)]); \
83
d[H##ESIZE(e)] = (mask & 1) ? \
84
cpu_##LDTYPE##_data_ra(env, addr, GETPC()) : 0; \
85
+ if (WB) { \
86
+ m[H##ESIZE(e)] = addr; \
87
+ } \
88
} \
89
mve_advance_vpt(env); \
90
}
91
92
/* We know here TYPE is unsigned so always the same as the offset type */
93
-#define DO_VSTR_SG(OP, STTYPE, ESIZE, TYPE, ADDRFN) \
94
+#define DO_VSTR_SG(OP, STTYPE, ESIZE, TYPE, ADDRFN, WB) \
95
void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm, \
96
uint32_t base) \
97
{ \
98
TYPE *d = vd; \
99
TYPE *m = vm; \
100
uint16_t mask = mve_element_mask(env); \
101
+ uint16_t eci_mask = mve_eci_mask(env); \
102
unsigned e; \
103
uint32_t addr; \
104
- for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE) { \
105
+ for (e = 0; e < 16 / ESIZE; e++, mask >>= ESIZE, eci_mask >>= ESIZE) { \
106
+ if (!(eci_mask & 1)) { \
107
+ continue; \
108
+ } \
109
addr = ADDRFN(base, m[H##ESIZE(e)]); \
110
if (mask & 1) { \
111
cpu_##STTYPE##_data_ra(env, addr, d[H##ESIZE(e)], GETPC()); \
112
} \
113
+ if (WB) { \
114
+ m[H##ESIZE(e)] = addr; \
115
+ } \
116
} \
117
mve_advance_vpt(env); \
118
}
119
@@ -XXX,XX +XXX,XX @@ DO_VSTR(vstrh_w, 2, stw, 4, int32_t)
120
* accesses, controlled by the predicate mask for the relevant beat,
121
* and with a single 32-bit offset in the first of the two Qm elements.
122
* Note that for QEMU our IMPDEF AIRCR.ENDIANNESS is always 0 (little).
123
+ * Address writeback happens on the odd beats and updates the address
124
+ * stored in the even-beat element.
125
*/
126
-#define DO_VLDR64_SG(OP, ADDRFN) \
127
+#define DO_VLDR64_SG(OP, ADDRFN, WB) \
128
void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm, \
129
uint32_t base) \
130
{ \
131
@@ -XXX,XX +XXX,XX @@ DO_VSTR(vstrh_w, 2, stw, 4, int32_t)
132
addr = ADDRFN(base, m[H4(e & ~1)]); \
133
addr += 4 * (e & 1); \
134
d[H4(e)] = (mask & 1) ? cpu_ldl_data_ra(env, addr, GETPC()) : 0; \
135
+ if (WB && (e & 1)) { \
136
+ m[H4(e & ~1)] = addr - 4; \
137
+ } \
138
} \
139
mve_advance_vpt(env); \
140
}
141
142
-#define DO_VSTR64_SG(OP, ADDRFN) \
143
+#define DO_VSTR64_SG(OP, ADDRFN, WB) \
144
void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm, \
145
uint32_t base) \
146
{ \
147
uint32_t *d = vd; \
148
uint32_t *m = vm; \
149
uint16_t mask = mve_element_mask(env); \
150
+ uint16_t eci_mask = mve_eci_mask(env); \
151
unsigned e; \
152
uint32_t addr; \
153
- for (e = 0; e < 16 / 4; e++, mask >>= 4) { \
154
+ for (e = 0; e < 16 / 4; e++, mask >>= 4, eci_mask >>= 4) { \
155
+ if (!(eci_mask & 1)) { \
156
+ continue; \
157
+ } \
158
addr = ADDRFN(base, m[H4(e & ~1)]); \
159
addr += 4 * (e & 1); \
160
if (mask & 1) { \
161
cpu_stl_data_ra(env, addr, d[H4(e)], GETPC()); \
162
} \
163
+ if (WB && (e & 1)) { \
164
+ m[H4(e & ~1)] = addr - 4; \
165
+ } \
166
} \
167
mve_advance_vpt(env); \
168
}
169
@@ -XXX,XX +XXX,XX @@ DO_VSTR(vstrh_w, 2, stw, 4, int32_t)
170
#define ADDR_ADD_OSW(BASE, OFFSET) ((BASE) + ((OFFSET) << 2))
171
#define ADDR_ADD_OSD(BASE, OFFSET) ((BASE) + ((OFFSET) << 3))
172
173
-DO_VLDR_SG(vldrb_sg_sh, ldsb, 2, int16_t, uint16_t, ADDR_ADD)
174
-DO_VLDR_SG(vldrb_sg_sw, ldsb, 4, int32_t, uint32_t, ADDR_ADD)
175
-DO_VLDR_SG(vldrh_sg_sw, ldsw, 4, int32_t, uint32_t, ADDR_ADD)
176
+DO_VLDR_SG(vldrb_sg_sh, ldsb, 2, int16_t, uint16_t, ADDR_ADD, false)
177
+DO_VLDR_SG(vldrb_sg_sw, ldsb, 4, int32_t, uint32_t, ADDR_ADD, false)
178
+DO_VLDR_SG(vldrh_sg_sw, ldsw, 4, int32_t, uint32_t, ADDR_ADD, false)
179
180
-DO_VLDR_SG(vldrb_sg_ub, ldub, 1, uint8_t, uint8_t, ADDR_ADD)
181
-DO_VLDR_SG(vldrb_sg_uh, ldub, 2, uint16_t, uint16_t, ADDR_ADD)
182
-DO_VLDR_SG(vldrb_sg_uw, ldub, 4, uint32_t, uint32_t, ADDR_ADD)
183
-DO_VLDR_SG(vldrh_sg_uh, lduw, 2, uint16_t, uint16_t, ADDR_ADD)
184
-DO_VLDR_SG(vldrh_sg_uw, lduw, 4, uint32_t, uint32_t, ADDR_ADD)
185
-DO_VLDR_SG(vldrw_sg_uw, ldl, 4, uint32_t, uint32_t, ADDR_ADD)
186
-DO_VLDR64_SG(vldrd_sg_ud, ADDR_ADD)
187
+DO_VLDR_SG(vldrb_sg_ub, ldub, 1, uint8_t, uint8_t, ADDR_ADD, false)
188
+DO_VLDR_SG(vldrb_sg_uh, ldub, 2, uint16_t, uint16_t, ADDR_ADD, false)
189
+DO_VLDR_SG(vldrb_sg_uw, ldub, 4, uint32_t, uint32_t, ADDR_ADD, false)
190
+DO_VLDR_SG(vldrh_sg_uh, lduw, 2, uint16_t, uint16_t, ADDR_ADD, false)
191
+DO_VLDR_SG(vldrh_sg_uw, lduw, 4, uint32_t, uint32_t, ADDR_ADD, false)
192
+DO_VLDR_SG(vldrw_sg_uw, ldl, 4, uint32_t, uint32_t, ADDR_ADD, false)
193
+DO_VLDR64_SG(vldrd_sg_ud, ADDR_ADD, false)
194
195
-DO_VLDR_SG(vldrh_sg_os_sw, ldsw, 4, int32_t, uint32_t, ADDR_ADD_OSH)
196
-DO_VLDR_SG(vldrh_sg_os_uh, lduw, 2, uint16_t, uint16_t, ADDR_ADD_OSH)
197
-DO_VLDR_SG(vldrh_sg_os_uw, lduw, 4, uint32_t, uint32_t, ADDR_ADD_OSH)
198
-DO_VLDR_SG(vldrw_sg_os_uw, ldl, 4, uint32_t, uint32_t, ADDR_ADD_OSW)
199
-DO_VLDR64_SG(vldrd_sg_os_ud, ADDR_ADD_OSD)
200
+DO_VLDR_SG(vldrh_sg_os_sw, ldsw, 4, int32_t, uint32_t, ADDR_ADD_OSH, false)
201
+DO_VLDR_SG(vldrh_sg_os_uh, lduw, 2, uint16_t, uint16_t, ADDR_ADD_OSH, false)
202
+DO_VLDR_SG(vldrh_sg_os_uw, lduw, 4, uint32_t, uint32_t, ADDR_ADD_OSH, false)
203
+DO_VLDR_SG(vldrw_sg_os_uw, ldl, 4, uint32_t, uint32_t, ADDR_ADD_OSW, false)
204
+DO_VLDR64_SG(vldrd_sg_os_ud, ADDR_ADD_OSD, false)
205
206
-DO_VSTR_SG(vstrb_sg_ub, stb, 1, uint8_t, ADDR_ADD)
207
-DO_VSTR_SG(vstrb_sg_uh, stb, 2, uint16_t, ADDR_ADD)
208
-DO_VSTR_SG(vstrb_sg_uw, stb, 4, uint32_t, ADDR_ADD)
209
-DO_VSTR_SG(vstrh_sg_uh, stw, 2, uint16_t, ADDR_ADD)
210
-DO_VSTR_SG(vstrh_sg_uw, stw, 4, uint32_t, ADDR_ADD)
211
-DO_VSTR_SG(vstrw_sg_uw, stl, 4, uint32_t, ADDR_ADD)
212
-DO_VSTR64_SG(vstrd_sg_ud, ADDR_ADD)
213
+DO_VSTR_SG(vstrb_sg_ub, stb, 1, uint8_t, ADDR_ADD, false)
214
+DO_VSTR_SG(vstrb_sg_uh, stb, 2, uint16_t, ADDR_ADD, false)
215
+DO_VSTR_SG(vstrb_sg_uw, stb, 4, uint32_t, ADDR_ADD, false)
216
+DO_VSTR_SG(vstrh_sg_uh, stw, 2, uint16_t, ADDR_ADD, false)
217
+DO_VSTR_SG(vstrh_sg_uw, stw, 4, uint32_t, ADDR_ADD, false)
218
+DO_VSTR_SG(vstrw_sg_uw, stl, 4, uint32_t, ADDR_ADD, false)
219
+DO_VSTR64_SG(vstrd_sg_ud, ADDR_ADD, false)
220
221
-DO_VSTR_SG(vstrh_sg_os_uh, stw, 2, uint16_t, ADDR_ADD_OSH)
222
-DO_VSTR_SG(vstrh_sg_os_uw, stw, 4, uint32_t, ADDR_ADD_OSH)
223
-DO_VSTR_SG(vstrw_sg_os_uw, stl, 4, uint32_t, ADDR_ADD_OSW)
224
-DO_VSTR64_SG(vstrd_sg_os_ud, ADDR_ADD_OSD)
225
+DO_VSTR_SG(vstrh_sg_os_uh, stw, 2, uint16_t, ADDR_ADD_OSH, false)
226
+DO_VSTR_SG(vstrh_sg_os_uw, stw, 4, uint32_t, ADDR_ADD_OSH, false)
227
+DO_VSTR_SG(vstrw_sg_os_uw, stl, 4, uint32_t, ADDR_ADD_OSW, false)
228
+DO_VSTR64_SG(vstrd_sg_os_ud, ADDR_ADD_OSD, false)
229
+
230
+DO_VLDR_SG(vldrw_sg_wb_uw, ldl, 4, uint32_t, uint32_t, ADDR_ADD, true)
231
+DO_VLDR64_SG(vldrd_sg_wb_ud, ADDR_ADD, true)
232
+DO_VSTR_SG(vstrw_sg_wb_uw, stl, 4, uint32_t, ADDR_ADD, true)
233
+DO_VSTR64_SG(vstrd_sg_wb_ud, ADDR_ADD, true)
234
235
/*
236
* The mergemask(D, R, M) macro performs the operation "*D = R" but
237
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
238
index XXXXXXX..XXXXXXX 100644
239
--- a/target/arm/translate-mve.c
240
+++ b/target/arm/translate-mve.c
241
@@ -XXX,XX +XXX,XX @@ static bool trans_VSTR_sg(DisasContext *s, arg_vldst_sg *a)
242
243
#undef F
244
245
+static bool do_ldst_sg_imm(DisasContext *s, arg_vldst_sg_imm *a,
246
+ MVEGenLdStSGFn *fn, unsigned msize)
247
+{
248
+ uint32_t offset;
249
+ TCGv_ptr qd, qm;
250
+
251
+ if (!dc_isar_feature(aa32_mve, s) ||
252
+ !mve_check_qreg_bank(s, a->qd | a->qm) ||
253
+ !fn) {
63
+ return false;
254
+ return false;
64
+ }
255
+ }
65
+
256
+
66
+ /* UNDEF accesses to D16-D31 if they don't exist. */
257
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
67
+ if (!dc_isar_feature(aa32_simd_r32, s) &&
68
+ ((a->vd | a->vm) & 0x10)) {
69
+ return false;
70
+ }
71
+
72
+ if ((a->vm | a->vd) & a->q) {
73
+ return false;
74
+ }
75
+
76
+ if (!vfp_access_check(s)) {
77
+ return true;
258
+ return true;
78
+ }
259
+ }
79
+
260
+
80
+ fn(a->size, rd_ofs, rm_ofs, a->shift, vec_size, vec_size);
261
+ offset = a->imm << msize;
262
+ if (!a->a) {
263
+ offset = -offset;
264
+ }
265
+
266
+ qd = mve_qreg_ptr(a->qd);
267
+ qm = mve_qreg_ptr(a->qm);
268
+ fn(cpu_env, qd, qm, tcg_constant_i32(offset));
269
+ tcg_temp_free_ptr(qd);
270
+ tcg_temp_free_ptr(qm);
271
+ mve_update_eci(s);
81
+ return true;
272
+ return true;
82
+}
273
+}
83
+
274
+
84
+#define DO_2SH(INSN, FUNC) \
275
+static bool trans_VLDRW_sg_imm(DisasContext *s, arg_vldst_sg_imm *a)
85
+ static bool trans_##INSN##_2sh(DisasContext *s, arg_2reg_shift *a) \
276
+{
86
+ { \
277
+ static MVEGenLdStSGFn * const fns[] = {
87
+ return do_vector_2sh(s, a, FUNC); \
278
+ gen_helper_mve_vldrw_sg_uw,
88
+ } \
279
+ gen_helper_mve_vldrw_sg_wb_uw,
89
+
280
+ };
90
+DO_2SH(VSHL, tcg_gen_gvec_shli)
281
+ if (a->qd == a->qm) {
91
+DO_2SH(VSLI, gen_gvec_sli)
282
+ return false; /* UNPREDICTABLE */
92
diff --git a/target/arm/translate.c b/target/arm/translate.c
283
+ }
93
index XXXXXXX..XXXXXXX 100644
284
+ return do_ldst_sg_imm(s, a, fns[a->w], MO_32);
94
--- a/target/arm/translate.c
285
+}
95
+++ b/target/arm/translate.c
286
+
96
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
287
+static bool trans_VLDRD_sg_imm(DisasContext *s, arg_vldst_sg_imm *a)
97
if ((insn & 0x00380080) != 0) {
288
+{
98
/* Two registers and shift. */
289
+ static MVEGenLdStSGFn * const fns[] = {
99
op = (insn >> 8) & 0xf;
290
+ gen_helper_mve_vldrd_sg_ud,
100
+
291
+ gen_helper_mve_vldrd_sg_wb_ud,
101
+ switch (op) {
292
+ };
102
+ case 5: /* VSHL, VSLI */
293
+ if (a->qd == a->qm) {
103
+ return 1; /* handled by decodetree */
294
+ return false; /* UNPREDICTABLE */
104
+ default:
295
+ }
105
+ break;
296
+ return do_ldst_sg_imm(s, a, fns[a->w], MO_64);
106
+ }
297
+}
107
+
298
+
108
if (insn & (1 << 7)) {
299
+static bool trans_VSTRW_sg_imm(DisasContext *s, arg_vldst_sg_imm *a)
109
/* 64-bit shift. */
300
+{
110
if (op > 7) {
301
+ static MVEGenLdStSGFn * const fns[] = {
111
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
302
+ gen_helper_mve_vstrw_sg_uw,
112
gen_gvec_sri(size, rd_ofs, rm_ofs, shift,
303
+ gen_helper_mve_vstrw_sg_wb_uw,
113
vec_size, vec_size);
304
+ };
114
return 0;
305
+ return do_ldst_sg_imm(s, a, fns[a->w], MO_32);
115
-
306
+}
116
- case 5: /* VSHL, VSLI */
307
+
117
- if (u) { /* VSLI */
308
+static bool trans_VSTRD_sg_imm(DisasContext *s, arg_vldst_sg_imm *a)
118
- gen_gvec_sli(size, rd_ofs, rm_ofs, shift,
309
+{
119
- vec_size, vec_size);
310
+ static MVEGenLdStSGFn * const fns[] = {
120
- } else { /* VSHL */
311
+ gen_helper_mve_vstrd_sg_ud,
121
- tcg_gen_gvec_shli(size, rd_ofs, rm_ofs, shift,
312
+ gen_helper_mve_vstrd_sg_wb_ud,
122
- vec_size, vec_size);
313
+ };
123
- }
314
+ return do_ldst_sg_imm(s, a, fns[a->w], MO_64);
124
- return 0;
315
+}
125
}
316
+
126
317
static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
127
if (size == 3) {
318
{
319
TCGv_ptr qd;
128
--
320
--
129
2.20.1
321
2.20.1
130
322
131
323
diff view generated by jsdifflib
1
From: Paul Zimmerman <pauldzim@gmail.com>
1
Implement the MVE interleaving load/store functions VLD2, VLD4, VST2
2
and VST4. VLD2 loads 16 bytes of data from memory and writes to 2
3
consecutive Qregs; VLD4 loads 16 bytes of data from memory and writes
4
to 4 consecutive Qregs. The 'pattern' field in the encoding
5
determines the offset into memory which is accessed and also which
6
elements in the Qregs are written to. (The intention is that a
7
sequence of four consecutive VLD4 with different pattern values
8
performs a complete de-interleaving load of 64 bytes into all
9
elements of the 4 Qregs.) VST2 and VST4 do the same, but for stores.
2
10
3
Add BCM2835 SOC MPHI (Message-based Parallel Host Interface)
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
emulation. It is very basic, only providing the FIQ interrupt
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
needed to allow the dwc-otg USB host controller driver in the
13
---
6
Raspbian kernel to function.
14
target/arm/helper-mve.h | 48 ++++++
15
target/arm/mve.decode | 11 ++
16
target/arm/mve_helper.c | 342 +++++++++++++++++++++++++++++++++++++
17
target/arm/translate-mve.c | 94 ++++++++++
18
4 files changed, 495 insertions(+)
7
19
8
Signed-off-by: Paul Zimmerman <pauldzim@gmail.com>
20
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h
9
Acked-by: Philippe Mathieu-Daude <f4bug@amsat.org>
10
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
11
Message-id: 20200520235349.21215-2-pauldzim@gmail.com
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
14
include/hw/arm/bcm2835_peripherals.h | 2 +
15
include/hw/misc/bcm2835_mphi.h | 44 ++++++
16
hw/arm/bcm2835_peripherals.c | 17 +++
17
hw/misc/bcm2835_mphi.c | 191 +++++++++++++++++++++++++++
18
hw/misc/Makefile.objs | 1 +
19
5 files changed, 255 insertions(+)
20
create mode 100644 include/hw/misc/bcm2835_mphi.h
21
create mode 100644 hw/misc/bcm2835_mphi.c
22
23
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
24
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
25
--- a/include/hw/arm/bcm2835_peripherals.h
22
--- a/target/arm/helper-mve.h
26
+++ b/include/hw/arm/bcm2835_peripherals.h
23
+++ b/target/arm/helper-mve.h
24
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_4(mve_vldrd_sg_wb_ud, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
25
DEF_HELPER_FLAGS_4(mve_vstrw_sg_wb_uw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
26
DEF_HELPER_FLAGS_4(mve_vstrd_sg_wb_ud, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
27
28
+DEF_HELPER_FLAGS_3(mve_vld20b, TCG_CALL_NO_WG, void, env, i32, i32)
29
+DEF_HELPER_FLAGS_3(mve_vld20h, TCG_CALL_NO_WG, void, env, i32, i32)
30
+DEF_HELPER_FLAGS_3(mve_vld20w, TCG_CALL_NO_WG, void, env, i32, i32)
31
+
32
+DEF_HELPER_FLAGS_3(mve_vld21b, TCG_CALL_NO_WG, void, env, i32, i32)
33
+DEF_HELPER_FLAGS_3(mve_vld21h, TCG_CALL_NO_WG, void, env, i32, i32)
34
+DEF_HELPER_FLAGS_3(mve_vld21w, TCG_CALL_NO_WG, void, env, i32, i32)
35
+
36
+DEF_HELPER_FLAGS_3(mve_vld40b, TCG_CALL_NO_WG, void, env, i32, i32)
37
+DEF_HELPER_FLAGS_3(mve_vld40h, TCG_CALL_NO_WG, void, env, i32, i32)
38
+DEF_HELPER_FLAGS_3(mve_vld40w, TCG_CALL_NO_WG, void, env, i32, i32)
39
+
40
+DEF_HELPER_FLAGS_3(mve_vld41b, TCG_CALL_NO_WG, void, env, i32, i32)
41
+DEF_HELPER_FLAGS_3(mve_vld41h, TCG_CALL_NO_WG, void, env, i32, i32)
42
+DEF_HELPER_FLAGS_3(mve_vld41w, TCG_CALL_NO_WG, void, env, i32, i32)
43
+
44
+DEF_HELPER_FLAGS_3(mve_vld42b, TCG_CALL_NO_WG, void, env, i32, i32)
45
+DEF_HELPER_FLAGS_3(mve_vld42h, TCG_CALL_NO_WG, void, env, i32, i32)
46
+DEF_HELPER_FLAGS_3(mve_vld42w, TCG_CALL_NO_WG, void, env, i32, i32)
47
+
48
+DEF_HELPER_FLAGS_3(mve_vld43b, TCG_CALL_NO_WG, void, env, i32, i32)
49
+DEF_HELPER_FLAGS_3(mve_vld43h, TCG_CALL_NO_WG, void, env, i32, i32)
50
+DEF_HELPER_FLAGS_3(mve_vld43w, TCG_CALL_NO_WG, void, env, i32, i32)
51
+
52
+DEF_HELPER_FLAGS_3(mve_vst20b, TCG_CALL_NO_WG, void, env, i32, i32)
53
+DEF_HELPER_FLAGS_3(mve_vst20h, TCG_CALL_NO_WG, void, env, i32, i32)
54
+DEF_HELPER_FLAGS_3(mve_vst20w, TCG_CALL_NO_WG, void, env, i32, i32)
55
+
56
+DEF_HELPER_FLAGS_3(mve_vst21b, TCG_CALL_NO_WG, void, env, i32, i32)
57
+DEF_HELPER_FLAGS_3(mve_vst21h, TCG_CALL_NO_WG, void, env, i32, i32)
58
+DEF_HELPER_FLAGS_3(mve_vst21w, TCG_CALL_NO_WG, void, env, i32, i32)
59
+
60
+DEF_HELPER_FLAGS_3(mve_vst40b, TCG_CALL_NO_WG, void, env, i32, i32)
61
+DEF_HELPER_FLAGS_3(mve_vst40h, TCG_CALL_NO_WG, void, env, i32, i32)
62
+DEF_HELPER_FLAGS_3(mve_vst40w, TCG_CALL_NO_WG, void, env, i32, i32)
63
+
64
+DEF_HELPER_FLAGS_3(mve_vst41b, TCG_CALL_NO_WG, void, env, i32, i32)
65
+DEF_HELPER_FLAGS_3(mve_vst41h, TCG_CALL_NO_WG, void, env, i32, i32)
66
+DEF_HELPER_FLAGS_3(mve_vst41w, TCG_CALL_NO_WG, void, env, i32, i32)
67
+
68
+DEF_HELPER_FLAGS_3(mve_vst42b, TCG_CALL_NO_WG, void, env, i32, i32)
69
+DEF_HELPER_FLAGS_3(mve_vst42h, TCG_CALL_NO_WG, void, env, i32, i32)
70
+DEF_HELPER_FLAGS_3(mve_vst42w, TCG_CALL_NO_WG, void, env, i32, i32)
71
+
72
+DEF_HELPER_FLAGS_3(mve_vst43b, TCG_CALL_NO_WG, void, env, i32, i32)
73
+DEF_HELPER_FLAGS_3(mve_vst43h, TCG_CALL_NO_WG, void, env, i32, i32)
74
+DEF_HELPER_FLAGS_3(mve_vst43w, TCG_CALL_NO_WG, void, env, i32, i32)
75
+
76
DEF_HELPER_FLAGS_3(mve_vdup, TCG_CALL_NO_WG, void, env, ptr, i32)
77
78
DEF_HELPER_FLAGS_4(mve_vidupb, TCG_CALL_NO_WG, i32, env, ptr, i32, i32)
79
diff --git a/target/arm/mve.decode b/target/arm/mve.decode
80
index XXXXXXX..XXXXXXX 100644
81
--- a/target/arm/mve.decode
82
+++ b/target/arm/mve.decode
27
@@ -XXX,XX +XXX,XX @@
83
@@ -XXX,XX +XXX,XX @@
28
#include "hw/misc/bcm2835_property.h"
84
&vabav qn qm rda size
29
#include "hw/misc/bcm2835_rng.h"
85
&vldst_sg qd qm rn size msize os
30
#include "hw/misc/bcm2835_mbox.h"
86
&vldst_sg_imm qd qm a w imm
31
+#include "hw/misc/bcm2835_mphi.h"
87
+&vldst_il qd rn size pat w
32
#include "hw/misc/bcm2835_thermal.h"
88
33
#include "hw/sd/sdhci.h"
89
# scatter-gather memory size is in bits 6:4
34
#include "hw/sd/bcm2835_sdhost.h"
90
%sg_msize 6:1 4:1
35
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2835PeripheralState {
36
qemu_irq irq, fiq;
37
38
BCM2835SystemTimerState systmr;
39
+ BCM2835MphiState mphi;
40
UnimplementedDeviceState armtmr;
41
UnimplementedDeviceState cprman;
42
UnimplementedDeviceState a2w;
43
diff --git a/include/hw/misc/bcm2835_mphi.h b/include/hw/misc/bcm2835_mphi.h
44
new file mode 100644
45
index XXXXXXX..XXXXXXX
46
--- /dev/null
47
+++ b/include/hw/misc/bcm2835_mphi.h
48
@@ -XXX,XX +XXX,XX @@
91
@@ -XXX,XX +XXX,XX @@
92
@vldst_sg_imm .... .... a:1 . w:1 . .... .... .... . imm:7 &vldst_sg_imm \
93
qd=%qd qm=%qn
94
95
+# Deinterleaving load/interleaving store
96
+@vldst_il .... .... .. w:1 . rn:4 .... ... size:2 pat:2 ..... &vldst_il \
97
+ qd=%qd
98
+
99
@1op .... .... .... size:2 .. .... .... .... .... &1op qd=%qd qm=%qm
100
@1op_nosz .... .... .... .... .... .... .... .... &1op qd=%qd qm=%qm size=0
101
@2op .... .... .. size:2 .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn
102
@@ -XXX,XX +XXX,XX @@ VLDRD_sg_imm 111 1 1101 ... 1 ... 0 ... 1 1111 .... .... @vldst_sg_imm
103
VSTRW_sg_imm 111 1 1101 ... 0 ... 0 ... 1 1110 .... .... @vldst_sg_imm
104
VSTRD_sg_imm 111 1 1101 ... 0 ... 0 ... 1 1111 .... .... @vldst_sg_imm
105
106
+# deinterleaving loads/interleaving stores
107
+VLD2 1111 1100 1 .. 1 .... ... 1 111 .. .. 00000 @vldst_il
108
+VLD4 1111 1100 1 .. 1 .... ... 1 111 .. .. 00001 @vldst_il
109
+VST2 1111 1100 1 .. 0 .... ... 1 111 .. .. 00000 @vldst_il
110
+VST4 1111 1100 1 .. 0 .... ... 1 111 .. .. 00001 @vldst_il
111
+
112
# Moves between 2 32-bit vector lanes and 2 general purpose registers
113
VMOV_to_2gp 1110 1100 0 . 00 rt2:4 ... 0 1111 000 idx:1 rt:4 qd=%qd
114
VMOV_from_2gp 1110 1100 0 . 01 rt2:4 ... 0 1111 000 idx:1 rt:4 qd=%qd
115
diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c
116
index XXXXXXX..XXXXXXX 100644
117
--- a/target/arm/mve_helper.c
118
+++ b/target/arm/mve_helper.c
119
@@ -XXX,XX +XXX,XX @@ DO_VLDR64_SG(vldrd_sg_wb_ud, ADDR_ADD, true)
120
DO_VSTR_SG(vstrw_sg_wb_uw, stl, 4, uint32_t, ADDR_ADD, true)
121
DO_VSTR64_SG(vstrd_sg_wb_ud, ADDR_ADD, true)
122
49
+/*
123
+/*
50
+ * BCM2835 SOC MPHI state definitions
124
+ * Deinterleaving loads/interleaving stores.
51
+ *
125
+ *
52
+ * Copyright (c) 2020 Paul Zimmerman <pauldzim@gmail.com>
126
+ * For these helpers we are passed the index of the first Qreg
127
+ * (VLD2/VST2 will also access Qn+1, VLD4/VST4 access Qn .. Qn+3)
128
+ * and the value of the base address register Rn.
129
+ * The helpers are specialized for pattern and element size, so
130
+ * for instance vld42h is VLD4 with pattern 2, element size MO_16.
53
+ *
131
+ *
54
+ * This program is free software; you can redistribute it and/or modify
132
+ * These insns are beatwise but not predicated, so we must honour ECI,
55
+ * it under the terms of the GNU General Public License as published by
133
+ * but need not look at mve_element_mask().
56
+ * the Free Software Foundation; either version 2 of the License, or
57
+ * (at your option) any later version.
58
+ *
134
+ *
59
+ * This program is distributed in the hope that it will be useful,
135
+ * The pseudocode implements these insns with multiple memory accesses
60
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
136
+ * of the element size, but rules R_VVVG and R_FXDM permit us to make
61
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
137
+ * one 32-bit memory access per beat.
62
+ * GNU General Public License for more details.
63
+ */
138
+ */
64
+
139
+#define DO_VLD4B(OP, O1, O2, O3, O4) \
65
+#ifndef HW_MISC_BCM2835_MPHI_H
140
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
66
+#define HW_MISC_BCM2835_MPHI_H
141
+ uint32_t base) \
67
+
142
+ { \
68
+#include "hw/irq.h"
143
+ int beat, e; \
69
+#include "hw/sysbus.h"
144
+ uint16_t mask = mve_eci_mask(env); \
70
+
145
+ static const uint8_t off[4] = { O1, O2, O3, O4 }; \
71
+#define MPHI_MMIO_SIZE 0x1000
146
+ uint32_t addr, data; \
72
+
147
+ for (beat = 0; beat < 4; beat++, mask >>= 4) { \
73
+typedef struct BCM2835MphiState BCM2835MphiState;
148
+ if ((mask & 1) == 0) { \
74
+
149
+ /* ECI says skip this beat */ \
75
+struct BCM2835MphiState {
150
+ continue; \
76
+ SysBusDevice parent_obj;
151
+ } \
77
+ qemu_irq irq;
152
+ addr = base + off[beat] * 4; \
78
+ MemoryRegion iomem;
153
+ data = cpu_ldl_le_data_ra(env, addr, GETPC()); \
79
+
154
+ for (e = 0; e < 4; e++, data >>= 8) { \
80
+ uint32_t outdda;
155
+ uint8_t *qd = (uint8_t *)aa32_vfp_qreg(env, qnidx + e); \
81
+ uint32_t outddb;
156
+ qd[H1(off[beat])] = data; \
82
+ uint32_t ctrl;
157
+ } \
83
+ uint32_t intstat;
158
+ } \
84
+ uint32_t swirq;
159
+ }
85
+};
160
+
86
+
161
+#define DO_VLD4H(OP, O1, O2) \
87
+#define TYPE_BCM2835_MPHI "bcm2835-mphi"
162
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
88
+
163
+ uint32_t base) \
89
+#define BCM2835_MPHI(obj) \
164
+ { \
90
+ OBJECT_CHECK(BCM2835MphiState, (obj), TYPE_BCM2835_MPHI)
165
+ int beat; \
91
+
166
+ uint16_t mask = mve_eci_mask(env); \
92
+#endif
167
+ static const uint8_t off[4] = { O1, O1, O2, O2 }; \
93
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
168
+ uint32_t addr, data; \
169
+ int y; /* y counts 0 2 0 2 */ \
170
+ uint16_t *qd; \
171
+ for (beat = 0, y = 0; beat < 4; beat++, mask >>= 4, y ^= 2) { \
172
+ if ((mask & 1) == 0) { \
173
+ /* ECI says skip this beat */ \
174
+ continue; \
175
+ } \
176
+ addr = base + off[beat] * 8 + (beat & 1) * 4; \
177
+ data = cpu_ldl_le_data_ra(env, addr, GETPC()); \
178
+ qd = (uint16_t *)aa32_vfp_qreg(env, qnidx + y); \
179
+ qd[H2(off[beat])] = data; \
180
+ data >>= 16; \
181
+ qd = (uint16_t *)aa32_vfp_qreg(env, qnidx + y + 1); \
182
+ qd[H2(off[beat])] = data; \
183
+ } \
184
+ }
185
+
186
+#define DO_VLD4W(OP, O1, O2, O3, O4) \
187
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
188
+ uint32_t base) \
189
+ { \
190
+ int beat; \
191
+ uint16_t mask = mve_eci_mask(env); \
192
+ static const uint8_t off[4] = { O1, O2, O3, O4 }; \
193
+ uint32_t addr, data; \
194
+ uint32_t *qd; \
195
+ int y; \
196
+ for (beat = 0; beat < 4; beat++, mask >>= 4) { \
197
+ if ((mask & 1) == 0) { \
198
+ /* ECI says skip this beat */ \
199
+ continue; \
200
+ } \
201
+ addr = base + off[beat] * 4; \
202
+ data = cpu_ldl_le_data_ra(env, addr, GETPC()); \
203
+ y = (beat + (O1 & 2)) & 3; \
204
+ qd = (uint32_t *)aa32_vfp_qreg(env, qnidx + y); \
205
+ qd[H4(off[beat] >> 2)] = data; \
206
+ } \
207
+ }
208
+
209
+DO_VLD4B(vld40b, 0, 1, 10, 11)
210
+DO_VLD4B(vld41b, 2, 3, 12, 13)
211
+DO_VLD4B(vld42b, 4, 5, 14, 15)
212
+DO_VLD4B(vld43b, 6, 7, 8, 9)
213
+
214
+DO_VLD4H(vld40h, 0, 5)
215
+DO_VLD4H(vld41h, 1, 6)
216
+DO_VLD4H(vld42h, 2, 7)
217
+DO_VLD4H(vld43h, 3, 4)
218
+
219
+DO_VLD4W(vld40w, 0, 1, 10, 11)
220
+DO_VLD4W(vld41w, 2, 3, 12, 13)
221
+DO_VLD4W(vld42w, 4, 5, 14, 15)
222
+DO_VLD4W(vld43w, 6, 7, 8, 9)
223
+
224
+#define DO_VLD2B(OP, O1, O2, O3, O4) \
225
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
226
+ uint32_t base) \
227
+ { \
228
+ int beat, e; \
229
+ uint16_t mask = mve_eci_mask(env); \
230
+ static const uint8_t off[4] = { O1, O2, O3, O4 }; \
231
+ uint32_t addr, data; \
232
+ uint8_t *qd; \
233
+ for (beat = 0; beat < 4; beat++, mask >>= 4) { \
234
+ if ((mask & 1) == 0) { \
235
+ /* ECI says skip this beat */ \
236
+ continue; \
237
+ } \
238
+ addr = base + off[beat] * 2; \
239
+ data = cpu_ldl_le_data_ra(env, addr, GETPC()); \
240
+ for (e = 0; e < 4; e++, data >>= 8) { \
241
+ qd = (uint8_t *)aa32_vfp_qreg(env, qnidx + (e & 1)); \
242
+ qd[H1(off[beat] + (e >> 1))] = data; \
243
+ } \
244
+ } \
245
+ }
246
+
247
+#define DO_VLD2H(OP, O1, O2, O3, O4) \
248
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
249
+ uint32_t base) \
250
+ { \
251
+ int beat; \
252
+ uint16_t mask = mve_eci_mask(env); \
253
+ static const uint8_t off[4] = { O1, O2, O3, O4 }; \
254
+ uint32_t addr, data; \
255
+ int e; \
256
+ uint16_t *qd; \
257
+ for (beat = 0; beat < 4; beat++, mask >>= 4) { \
258
+ if ((mask & 1) == 0) { \
259
+ /* ECI says skip this beat */ \
260
+ continue; \
261
+ } \
262
+ addr = base + off[beat] * 4; \
263
+ data = cpu_ldl_le_data_ra(env, addr, GETPC()); \
264
+ for (e = 0; e < 2; e++, data >>= 16) { \
265
+ qd = (uint16_t *)aa32_vfp_qreg(env, qnidx + e); \
266
+ qd[H2(off[beat])] = data; \
267
+ } \
268
+ } \
269
+ }
270
+
271
+#define DO_VLD2W(OP, O1, O2, O3, O4) \
272
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
273
+ uint32_t base) \
274
+ { \
275
+ int beat; \
276
+ uint16_t mask = mve_eci_mask(env); \
277
+ static const uint8_t off[4] = { O1, O2, O3, O4 }; \
278
+ uint32_t addr, data; \
279
+ uint32_t *qd; \
280
+ for (beat = 0; beat < 4; beat++, mask >>= 4) { \
281
+ if ((mask & 1) == 0) { \
282
+ /* ECI says skip this beat */ \
283
+ continue; \
284
+ } \
285
+ addr = base + off[beat]; \
286
+ data = cpu_ldl_le_data_ra(env, addr, GETPC()); \
287
+ qd = (uint32_t *)aa32_vfp_qreg(env, qnidx + (beat & 1)); \
288
+ qd[H4(off[beat] >> 3)] = data; \
289
+ } \
290
+ }
291
+
292
+DO_VLD2B(vld20b, 0, 2, 12, 14)
293
+DO_VLD2B(vld21b, 4, 6, 8, 10)
294
+
295
+DO_VLD2H(vld20h, 0, 1, 6, 7)
296
+DO_VLD2H(vld21h, 2, 3, 4, 5)
297
+
298
+DO_VLD2W(vld20w, 0, 4, 24, 28)
299
+DO_VLD2W(vld21w, 8, 12, 16, 20)
300
+
301
+#define DO_VST4B(OP, O1, O2, O3, O4) \
302
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
303
+ uint32_t base) \
304
+ { \
305
+ int beat, e; \
306
+ uint16_t mask = mve_eci_mask(env); \
307
+ static const uint8_t off[4] = { O1, O2, O3, O4 }; \
308
+ uint32_t addr, data; \
309
+ for (beat = 0; beat < 4; beat++, mask >>= 4) { \
310
+ if ((mask & 1) == 0) { \
311
+ /* ECI says skip this beat */ \
312
+ continue; \
313
+ } \
314
+ addr = base + off[beat] * 4; \
315
+ data = 0; \
316
+ for (e = 3; e >= 0; e--) { \
317
+ uint8_t *qd = (uint8_t *)aa32_vfp_qreg(env, qnidx + e); \
318
+ data = (data << 8) | qd[H1(off[beat])]; \
319
+ } \
320
+ cpu_stl_le_data_ra(env, addr, data, GETPC()); \
321
+ } \
322
+ }
323
+
324
+#define DO_VST4H(OP, O1, O2) \
325
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
326
+ uint32_t base) \
327
+ { \
328
+ int beat; \
329
+ uint16_t mask = mve_eci_mask(env); \
330
+ static const uint8_t off[4] = { O1, O1, O2, O2 }; \
331
+ uint32_t addr, data; \
332
+ int y; /* y counts 0 2 0 2 */ \
333
+ uint16_t *qd; \
334
+ for (beat = 0, y = 0; beat < 4; beat++, mask >>= 4, y ^= 2) { \
335
+ if ((mask & 1) == 0) { \
336
+ /* ECI says skip this beat */ \
337
+ continue; \
338
+ } \
339
+ addr = base + off[beat] * 8 + (beat & 1) * 4; \
340
+ qd = (uint16_t *)aa32_vfp_qreg(env, qnidx + y); \
341
+ data = qd[H2(off[beat])]; \
342
+ qd = (uint16_t *)aa32_vfp_qreg(env, qnidx + y + 1); \
343
+ data |= qd[H2(off[beat])] << 16; \
344
+ cpu_stl_le_data_ra(env, addr, data, GETPC()); \
345
+ } \
346
+ }
347
+
348
+#define DO_VST4W(OP, O1, O2, O3, O4) \
349
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
350
+ uint32_t base) \
351
+ { \
352
+ int beat; \
353
+ uint16_t mask = mve_eci_mask(env); \
354
+ static const uint8_t off[4] = { O1, O2, O3, O4 }; \
355
+ uint32_t addr, data; \
356
+ uint32_t *qd; \
357
+ int y; \
358
+ for (beat = 0; beat < 4; beat++, mask >>= 4) { \
359
+ if ((mask & 1) == 0) { \
360
+ /* ECI says skip this beat */ \
361
+ continue; \
362
+ } \
363
+ addr = base + off[beat] * 4; \
364
+ y = (beat + (O1 & 2)) & 3; \
365
+ qd = (uint32_t *)aa32_vfp_qreg(env, qnidx + y); \
366
+ data = qd[H4(off[beat] >> 2)]; \
367
+ cpu_stl_le_data_ra(env, addr, data, GETPC()); \
368
+ } \
369
+ }
370
+
371
+DO_VST4B(vst40b, 0, 1, 10, 11)
372
+DO_VST4B(vst41b, 2, 3, 12, 13)
373
+DO_VST4B(vst42b, 4, 5, 14, 15)
374
+DO_VST4B(vst43b, 6, 7, 8, 9)
375
+
376
+DO_VST4H(vst40h, 0, 5)
377
+DO_VST4H(vst41h, 1, 6)
378
+DO_VST4H(vst42h, 2, 7)
379
+DO_VST4H(vst43h, 3, 4)
380
+
381
+DO_VST4W(vst40w, 0, 1, 10, 11)
382
+DO_VST4W(vst41w, 2, 3, 12, 13)
383
+DO_VST4W(vst42w, 4, 5, 14, 15)
384
+DO_VST4W(vst43w, 6, 7, 8, 9)
385
+
386
+#define DO_VST2B(OP, O1, O2, O3, O4) \
387
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
388
+ uint32_t base) \
389
+ { \
390
+ int beat, e; \
391
+ uint16_t mask = mve_eci_mask(env); \
392
+ static const uint8_t off[4] = { O1, O2, O3, O4 }; \
393
+ uint32_t addr, data; \
394
+ uint8_t *qd; \
395
+ for (beat = 0; beat < 4; beat++, mask >>= 4) { \
396
+ if ((mask & 1) == 0) { \
397
+ /* ECI says skip this beat */ \
398
+ continue; \
399
+ } \
400
+ addr = base + off[beat] * 2; \
401
+ data = 0; \
402
+ for (e = 3; e >= 0; e--) { \
403
+ qd = (uint8_t *)aa32_vfp_qreg(env, qnidx + (e & 1)); \
404
+ data = (data << 8) | qd[H1(off[beat] + (e >> 1))]; \
405
+ } \
406
+ cpu_stl_le_data_ra(env, addr, data, GETPC()); \
407
+ } \
408
+ }
409
+
410
+#define DO_VST2H(OP, O1, O2, O3, O4) \
411
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
412
+ uint32_t base) \
413
+ { \
414
+ int beat; \
415
+ uint16_t mask = mve_eci_mask(env); \
416
+ static const uint8_t off[4] = { O1, O2, O3, O4 }; \
417
+ uint32_t addr, data; \
418
+ int e; \
419
+ uint16_t *qd; \
420
+ for (beat = 0; beat < 4; beat++, mask >>= 4) { \
421
+ if ((mask & 1) == 0) { \
422
+ /* ECI says skip this beat */ \
423
+ continue; \
424
+ } \
425
+ addr = base + off[beat] * 4; \
426
+ data = 0; \
427
+ for (e = 1; e >= 0; e--) { \
428
+ qd = (uint16_t *)aa32_vfp_qreg(env, qnidx + e); \
429
+ data = (data << 16) | qd[H2(off[beat])]; \
430
+ } \
431
+ cpu_stl_le_data_ra(env, addr, data, GETPC()); \
432
+ } \
433
+ }
434
+
435
+#define DO_VST2W(OP, O1, O2, O3, O4) \
436
+ void HELPER(mve_##OP)(CPUARMState *env, uint32_t qnidx, \
437
+ uint32_t base) \
438
+ { \
439
+ int beat; \
440
+ uint16_t mask = mve_eci_mask(env); \
441
+ static const uint8_t off[4] = { O1, O2, O3, O4 }; \
442
+ uint32_t addr, data; \
443
+ uint32_t *qd; \
444
+ for (beat = 0; beat < 4; beat++, mask >>= 4) { \
445
+ if ((mask & 1) == 0) { \
446
+ /* ECI says skip this beat */ \
447
+ continue; \
448
+ } \
449
+ addr = base + off[beat]; \
450
+ qd = (uint32_t *)aa32_vfp_qreg(env, qnidx + (beat & 1)); \
451
+ data = qd[H4(off[beat] >> 3)]; \
452
+ cpu_stl_le_data_ra(env, addr, data, GETPC()); \
453
+ } \
454
+ }
455
+
456
+DO_VST2B(vst20b, 0, 2, 12, 14)
457
+DO_VST2B(vst21b, 4, 6, 8, 10)
458
+
459
+DO_VST2H(vst20h, 0, 1, 6, 7)
460
+DO_VST2H(vst21h, 2, 3, 4, 5)
461
+
462
+DO_VST2W(vst20w, 0, 4, 24, 28)
463
+DO_VST2W(vst21w, 8, 12, 16, 20)
464
+
465
/*
466
* The mergemask(D, R, M) macro performs the operation "*D = R" but
467
* storing only the bytes which correspond to 1 bits in M,
468
diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c
94
index XXXXXXX..XXXXXXX 100644
469
index XXXXXXX..XXXXXXX 100644
95
--- a/hw/arm/bcm2835_peripherals.c
470
--- a/target/arm/translate-mve.c
96
+++ b/hw/arm/bcm2835_peripherals.c
471
+++ b/target/arm/translate-mve.c
97
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
472
@@ -XXX,XX +XXX,XX @@ static inline int vidup_imm(DisasContext *s, int x)
98
OBJECT(&s->sdhci.sdbus));
473
99
object_property_add_const_link(OBJECT(&s->gpio), "sdbus-sdhost",
474
typedef void MVEGenLdStFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
100
OBJECT(&s->sdhost.sdbus));
475
typedef void MVEGenLdStSGFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
101
+
476
+typedef void MVEGenLdStIlFn(TCGv_ptr, TCGv_i32, TCGv_i32);
102
+ /* Mphi */
477
typedef void MVEGenOneOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
103
+ sysbus_init_child_obj(obj, "mphi", &s->mphi, sizeof(s->mphi),
478
typedef void MVEGenTwoOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr);
104
+ TYPE_BCM2835_MPHI);
479
typedef void MVEGenTwoOpScalarFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
480
@@ -XXX,XX +XXX,XX @@ static bool trans_VSTRD_sg_imm(DisasContext *s, arg_vldst_sg_imm *a)
481
return do_ldst_sg_imm(s, a, fns[a->w], MO_64);
105
}
482
}
106
483
107
static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
484
+static bool do_vldst_il(DisasContext *s, arg_vldst_il *a, MVEGenLdStIlFn *fn,
108
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
485
+ int addrinc)
109
110
object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->gpio), "sd-bus");
111
112
+ /* Mphi */
113
+ object_property_set_bool(OBJECT(&s->mphi), true, "realized", &err);
114
+ if (err) {
115
+ error_propagate(errp, err);
116
+ return;
117
+ }
118
+
119
+ memory_region_add_subregion(&s->peri_mr, MPHI_OFFSET,
120
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mphi), 0));
121
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->mphi), 0,
122
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
123
+ INTERRUPT_HOSTPORT));
124
+
125
create_unimp(s, &s->armtmr, "bcm2835-sp804", ARMCTRL_TIMER0_1_OFFSET, 0x40);
126
create_unimp(s, &s->cprman, "bcm2835-cprman", CPRMAN_OFFSET, 0x1000);
127
create_unimp(s, &s->a2w, "bcm2835-a2w", A2W_OFFSET, 0x1000);
128
diff --git a/hw/misc/bcm2835_mphi.c b/hw/misc/bcm2835_mphi.c
129
new file mode 100644
130
index XXXXXXX..XXXXXXX
131
--- /dev/null
132
+++ b/hw/misc/bcm2835_mphi.c
133
@@ -XXX,XX +XXX,XX @@
134
+/*
135
+ * BCM2835 SOC MPHI emulation
136
+ *
137
+ * Very basic emulation, only providing the FIQ interrupt needed to
138
+ * allow the dwc-otg USB host controller driver in the Raspbian kernel
139
+ * to function.
140
+ *
141
+ * Copyright (c) 2020 Paul Zimmerman <pauldzim@gmail.com>
142
+ *
143
+ * This program is free software; you can redistribute it and/or modify
144
+ * it under the terms of the GNU General Public License as published by
145
+ * the Free Software Foundation; either version 2 of the License, or
146
+ * (at your option) any later version.
147
+ *
148
+ * This program is distributed in the hope that it will be useful,
149
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
150
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
151
+ * GNU General Public License for more details.
152
+ */
153
+
154
+#include "qemu/osdep.h"
155
+#include "qapi/error.h"
156
+#include "hw/misc/bcm2835_mphi.h"
157
+#include "migration/vmstate.h"
158
+#include "qemu/error-report.h"
159
+#include "qemu/log.h"
160
+#include "qemu/main-loop.h"
161
+
162
+static inline void mphi_raise_irq(BCM2835MphiState *s)
163
+{
486
+{
164
+ qemu_set_irq(s->irq, 1);
487
+ TCGv_i32 rn;
488
+
489
+ if (!dc_isar_feature(aa32_mve, s) ||
490
+ !mve_check_qreg_bank(s, a->qd) ||
491
+ !fn || (a->rn == 13 && a->w) || a->rn == 15) {
492
+ /* Variously UNPREDICTABLE or UNDEF or related-encoding */
493
+ return false;
494
+ }
495
+ if (!mve_eci_check(s) || !vfp_access_check(s)) {
496
+ return true;
497
+ }
498
+
499
+ rn = load_reg(s, a->rn);
500
+ /*
501
+ * We pass the index of Qd, not a pointer, because the helper must
502
+ * access multiple Q registers starting at Qd and working up.
503
+ */
504
+ fn(cpu_env, tcg_constant_i32(a->qd), rn);
505
+
506
+ if (a->w) {
507
+ tcg_gen_addi_i32(rn, rn, addrinc);
508
+ store_reg(s, a->rn, rn);
509
+ } else {
510
+ tcg_temp_free_i32(rn);
511
+ }
512
+ mve_update_and_store_eci(s);
513
+ return true;
165
+}
514
+}
166
+
515
+
167
+static inline void mphi_lower_irq(BCM2835MphiState *s)
516
+/* This macro is just to make the arrays more compact in these functions */
517
+#define F(N) gen_helper_mve_##N
518
+
519
+static bool trans_VLD2(DisasContext *s, arg_vldst_il *a)
168
+{
520
+{
169
+ qemu_set_irq(s->irq, 0);
521
+ static MVEGenLdStIlFn * const fns[4][4] = {
522
+ { F(vld20b), F(vld20h), F(vld20w), NULL, },
523
+ { F(vld21b), F(vld21h), F(vld21w), NULL, },
524
+ { NULL, NULL, NULL, NULL },
525
+ { NULL, NULL, NULL, NULL },
526
+ };
527
+ if (a->qd > 6) {
528
+ return false;
529
+ }
530
+ return do_vldst_il(s, a, fns[a->pat][a->size], 32);
170
+}
531
+}
171
+
532
+
172
+static uint64_t mphi_reg_read(void *ptr, hwaddr addr, unsigned size)
533
+static bool trans_VLD4(DisasContext *s, arg_vldst_il *a)
173
+{
534
+{
174
+ BCM2835MphiState *s = ptr;
535
+ static MVEGenLdStIlFn * const fns[4][4] = {
175
+ uint32_t val = 0;
536
+ { F(vld40b), F(vld40h), F(vld40w), NULL, },
176
+
537
+ { F(vld41b), F(vld41h), F(vld41w), NULL, },
177
+ switch (addr) {
538
+ { F(vld42b), F(vld42h), F(vld42w), NULL, },
178
+ case 0x28: /* outdda */
539
+ { F(vld43b), F(vld43h), F(vld43w), NULL, },
179
+ val = s->outdda;
540
+ };
180
+ break;
541
+ if (a->qd > 4) {
181
+ case 0x2c: /* outddb */
542
+ return false;
182
+ val = s->outddb;
543
+ }
183
+ break;
544
+ return do_vldst_il(s, a, fns[a->pat][a->size], 64);
184
+ case 0x4c: /* ctrl */
185
+ val = s->ctrl;
186
+ val |= 1 << 17;
187
+ break;
188
+ case 0x50: /* intstat */
189
+ val = s->intstat;
190
+ break;
191
+ case 0x1f0: /* swirq_set */
192
+ val = s->swirq;
193
+ break;
194
+ case 0x1f4: /* swirq_clr */
195
+ val = s->swirq;
196
+ break;
197
+ default:
198
+ qemu_log_mask(LOG_UNIMP, "read from unknown register");
199
+ break;
200
+ }
201
+
202
+ return val;
203
+}
545
+}
204
+
546
+
205
+static void mphi_reg_write(void *ptr, hwaddr addr, uint64_t val, unsigned size)
547
+static bool trans_VST2(DisasContext *s, arg_vldst_il *a)
206
+{
548
+{
207
+ BCM2835MphiState *s = ptr;
549
+ static MVEGenLdStIlFn * const fns[4][4] = {
208
+ int do_irq = 0;
550
+ { F(vst20b), F(vst20h), F(vst20w), NULL, },
209
+
551
+ { F(vst21b), F(vst21h), F(vst21w), NULL, },
210
+ switch (addr) {
552
+ { NULL, NULL, NULL, NULL },
211
+ case 0x28: /* outdda */
553
+ { NULL, NULL, NULL, NULL },
212
+ s->outdda = val;
554
+ };
213
+ break;
555
+ if (a->qd > 6) {
214
+ case 0x2c: /* outddb */
556
+ return false;
215
+ s->outddb = val;
557
+ }
216
+ if (val & (1 << 29)) {
558
+ return do_vldst_il(s, a, fns[a->pat][a->size], 32);
217
+ do_irq = 1;
218
+ }
219
+ break;
220
+ case 0x4c: /* ctrl */
221
+ s->ctrl = val;
222
+ if (val & (1 << 16)) {
223
+ do_irq = -1;
224
+ }
225
+ break;
226
+ case 0x50: /* intstat */
227
+ s->intstat = val;
228
+ if (val & ((1 << 16) | (1 << 29))) {
229
+ do_irq = -1;
230
+ }
231
+ break;
232
+ case 0x1f0: /* swirq_set */
233
+ s->swirq |= val;
234
+ do_irq = 1;
235
+ break;
236
+ case 0x1f4: /* swirq_clr */
237
+ s->swirq &= ~val;
238
+ do_irq = -1;
239
+ break;
240
+ default:
241
+ qemu_log_mask(LOG_UNIMP, "write to unknown register");
242
+ return;
243
+ }
244
+
245
+ if (do_irq > 0) {
246
+ mphi_raise_irq(s);
247
+ } else if (do_irq < 0) {
248
+ mphi_lower_irq(s);
249
+ }
250
+}
559
+}
251
+
560
+
252
+static const MemoryRegionOps mphi_mmio_ops = {
561
+static bool trans_VST4(DisasContext *s, arg_vldst_il *a)
253
+ .read = mphi_reg_read,
254
+ .write = mphi_reg_write,
255
+ .impl.min_access_size = 4,
256
+ .impl.max_access_size = 4,
257
+ .endianness = DEVICE_LITTLE_ENDIAN,
258
+};
259
+
260
+static void mphi_reset(DeviceState *dev)
261
+{
562
+{
262
+ BCM2835MphiState *s = BCM2835_MPHI(dev);
563
+ static MVEGenLdStIlFn * const fns[4][4] = {
263
+
564
+ { F(vst40b), F(vst40h), F(vst40w), NULL, },
264
+ s->outdda = 0;
565
+ { F(vst41b), F(vst41h), F(vst41w), NULL, },
265
+ s->outddb = 0;
566
+ { F(vst42b), F(vst42h), F(vst42w), NULL, },
266
+ s->ctrl = 0;
567
+ { F(vst43b), F(vst43h), F(vst43w), NULL, },
267
+ s->intstat = 0;
568
+ };
268
+ s->swirq = 0;
569
+ if (a->qd > 4) {
570
+ return false;
571
+ }
572
+ return do_vldst_il(s, a, fns[a->pat][a->size], 64);
269
+}
573
+}
270
+
574
+
271
+static void mphi_realize(DeviceState *dev, Error **errp)
575
+#undef F
272
+{
576
+
273
+ SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
577
static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
274
+ BCM2835MphiState *s = BCM2835_MPHI(dev);
578
{
275
+
579
TCGv_ptr qd;
276
+ sysbus_init_irq(sbd, &s->irq);
277
+}
278
+
279
+static void mphi_init(Object *obj)
280
+{
281
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
282
+ BCM2835MphiState *s = BCM2835_MPHI(obj);
283
+
284
+ memory_region_init_io(&s->iomem, obj, &mphi_mmio_ops, s, "mphi", MPHI_MMIO_SIZE);
285
+ sysbus_init_mmio(sbd, &s->iomem);
286
+}
287
+
288
+const VMStateDescription vmstate_mphi_state = {
289
+ .name = "mphi",
290
+ .version_id = 1,
291
+ .minimum_version_id = 1,
292
+ .fields = (VMStateField[]) {
293
+ VMSTATE_UINT32(outdda, BCM2835MphiState),
294
+ VMSTATE_UINT32(outddb, BCM2835MphiState),
295
+ VMSTATE_UINT32(ctrl, BCM2835MphiState),
296
+ VMSTATE_UINT32(intstat, BCM2835MphiState),
297
+ VMSTATE_UINT32(swirq, BCM2835MphiState),
298
+ VMSTATE_END_OF_LIST()
299
+ }
300
+};
301
+
302
+static void mphi_class_init(ObjectClass *klass, void *data)
303
+{
304
+ DeviceClass *dc = DEVICE_CLASS(klass);
305
+
306
+ dc->realize = mphi_realize;
307
+ dc->reset = mphi_reset;
308
+ dc->vmsd = &vmstate_mphi_state;
309
+}
310
+
311
+static const TypeInfo bcm2835_mphi_type_info = {
312
+ .name = TYPE_BCM2835_MPHI,
313
+ .parent = TYPE_SYS_BUS_DEVICE,
314
+ .instance_size = sizeof(BCM2835MphiState),
315
+ .instance_init = mphi_init,
316
+ .class_init = mphi_class_init,
317
+};
318
+
319
+static void bcm2835_mphi_register_types(void)
320
+{
321
+ type_register_static(&bcm2835_mphi_type_info);
322
+}
323
+
324
+type_init(bcm2835_mphi_register_types)
325
diff --git a/hw/misc/Makefile.objs b/hw/misc/Makefile.objs
326
index XXXXXXX..XXXXXXX 100644
327
--- a/hw/misc/Makefile.objs
328
+++ b/hw/misc/Makefile.objs
329
@@ -XXX,XX +XXX,XX @@ common-obj-$(CONFIG_OMAP) += omap_l4.o
330
common-obj-$(CONFIG_OMAP) += omap_sdrc.o
331
common-obj-$(CONFIG_OMAP) += omap_tap.o
332
common-obj-$(CONFIG_RASPI) += bcm2835_mbox.o
333
+common-obj-$(CONFIG_RASPI) += bcm2835_mphi.o
334
common-obj-$(CONFIG_RASPI) += bcm2835_property.o
335
common-obj-$(CONFIG_RASPI) += bcm2835_rng.o
336
common-obj-$(CONFIG_RASPI) += bcm2835_thermal.o
337
--
580
--
338
2.20.1
581
2.20.1
339
582
340
583
diff view generated by jsdifflib
1
From: Paul Zimmerman <pauldzim@gmail.com>
1
We're about to make a code change to the sdiv and udiv helper
2
functions, so first fix their indentation and coding style.
2
3
3
Wire the dwc-hsotg (dwc2) emulation into Qemu
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20210730151636.17254-2-peter.maydell@linaro.org
7
---
8
target/arm/helper.c | 15 +++++++++------
9
1 file changed, 9 insertions(+), 6 deletions(-)
4
10
5
Signed-off-by: Paul Zimmerman <pauldzim@gmail.com>
11
diff --git a/target/arm/helper.c b/target/arm/helper.c
6
Reviewed-by: Philippe Mathieu-Daude <f4bug@amsat.org>
7
Message-id: 20200520235349.21215-7-pauldzim@gmail.com
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
include/hw/arm/bcm2835_peripherals.h | 3 ++-
11
hw/arm/bcm2835_peripherals.c | 21 ++++++++++++++++++++-
12
2 files changed, 22 insertions(+), 2 deletions(-)
13
14
diff --git a/include/hw/arm/bcm2835_peripherals.h b/include/hw/arm/bcm2835_peripherals.h
15
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
16
--- a/include/hw/arm/bcm2835_peripherals.h
13
--- a/target/arm/helper.c
17
+++ b/include/hw/arm/bcm2835_peripherals.h
14
+++ b/target/arm/helper.c
18
@@ -XXX,XX +XXX,XX @@
15
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(uxtb16)(uint32_t x)
19
#include "hw/sd/bcm2835_sdhost.h"
16
20
#include "hw/gpio/bcm2835_gpio.h"
17
int32_t HELPER(sdiv)(int32_t num, int32_t den)
21
#include "hw/timer/bcm2835_systmr.h"
18
{
22
+#include "hw/usb/hcd-dwc2.h"
19
- if (den == 0)
23
#include "hw/misc/unimp.h"
20
- return 0;
24
21
- if (num == INT_MIN && den == -1)
25
#define TYPE_BCM2835_PERIPHERALS "bcm2835-peripherals"
22
- return INT_MIN;
26
@@ -XXX,XX +XXX,XX @@ typedef struct BCM2835PeripheralState {
23
+ if (den == 0) {
27
UnimplementedDeviceState ave0;
24
+ return 0;
28
UnimplementedDeviceState bscsl;
25
+ }
29
UnimplementedDeviceState smi;
26
+ if (num == INT_MIN && den == -1) {
30
- UnimplementedDeviceState dwc2;
27
+ return INT_MIN;
31
+ DWC2State dwc2;
28
+ }
32
UnimplementedDeviceState sdramc;
29
return num / den;
33
} BCM2835PeripheralState;
34
35
diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/arm/bcm2835_peripherals.c
38
+++ b/hw/arm/bcm2835_peripherals.c
39
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_init(Object *obj)
40
/* Mphi */
41
sysbus_init_child_obj(obj, "mphi", &s->mphi, sizeof(s->mphi),
42
TYPE_BCM2835_MPHI);
43
+
44
+ /* DWC2 */
45
+ sysbus_init_child_obj(obj, "dwc2", &s->dwc2, sizeof(s->dwc2),
46
+ TYPE_DWC2_USB);
47
+
48
+ object_property_add_const_link(OBJECT(&s->dwc2), "dma-mr",
49
+ OBJECT(&s->gpu_bus_mr));
50
}
30
}
51
31
52
static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
32
uint32_t HELPER(udiv)(uint32_t num, uint32_t den)
53
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
33
{
54
qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
34
- if (den == 0)
55
INTERRUPT_HOSTPORT));
35
- return 0;
56
36
+ if (den == 0) {
57
+ /* DWC2 */
37
+ return 0;
58
+ object_property_set_bool(OBJECT(&s->dwc2), true, "realized", &err);
59
+ if (err) {
60
+ error_propagate(errp, err);
61
+ return;
62
+ }
38
+ }
63
+
39
return num / den;
64
+ memory_region_add_subregion(&s->peri_mr, USB_OTG_OFFSET,
65
+ sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dwc2), 0));
66
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->dwc2), 0,
67
+ qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
68
+ INTERRUPT_USB));
69
+
70
create_unimp(s, &s->armtmr, "bcm2835-sp804", ARMCTRL_TIMER0_1_OFFSET, 0x40);
71
create_unimp(s, &s->cprman, "bcm2835-cprman", CPRMAN_OFFSET, 0x1000);
72
create_unimp(s, &s->a2w, "bcm2835-a2w", A2W_OFFSET, 0x1000);
73
@@ -XXX,XX +XXX,XX @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
74
create_unimp(s, &s->otp, "bcm2835-otp", OTP_OFFSET, 0x80);
75
create_unimp(s, &s->dbus, "bcm2835-dbus", DBUS_OFFSET, 0x8000);
76
create_unimp(s, &s->ave0, "bcm2835-ave0", AVE0_OFFSET, 0x8000);
77
- create_unimp(s, &s->dwc2, "dwc-usb2", USB_OTG_OFFSET, 0x1000);
78
create_unimp(s, &s->sdramc, "bcm2835-sdramc", SDRAMC_OFFSET, 0x100);
79
}
40
}
80
41
81
--
42
--
82
2.20.1
43
2.20.1
83
44
84
45
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Unlike A-profile, for M-profile the UDIV and SDIV insns can be
2
configured to raise an exception on division by zero, using the CCR
3
DIV_0_TRP bit.
2
4
3
Rather than passing an opcode to a helper, fully decode the
5
Implement support for setting this bit by making the helper functions
4
operation at translate time. Use clear_tail_16 to zap the
6
raise the appropriate exception.
5
balance of the SVE register with the AdvSIMD write.
6
7
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20200514212831.31248-6-richard.henderson@linaro.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Message-id: 20210730151636.17254-3-peter.maydell@linaro.org
11
---
11
---
12
target/arm/helper.h | 5 +-
12
target/arm/cpu.h | 1 +
13
target/arm/neon-dp.decode | 6 +-
13
target/arm/helper.h | 4 ++--
14
target/arm/crypto_helper.c | 99 +++++++++++++++++++++------------
14
target/arm/helper.c | 19 +++++++++++++++++--
15
target/arm/translate-a64.c | 29 ++++------
15
target/arm/m_helper.c | 4 ++++
16
target/arm/translate-neon.inc.c | 46 ++++-----------
16
target/arm/translate.c | 4 ++--
17
5 files changed, 93 insertions(+), 92 deletions(-)
17
5 files changed, 26 insertions(+), 6 deletions(-)
18
18
19
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/cpu.h
22
+++ b/target/arm/cpu.h
23
@@ -XXX,XX +XXX,XX @@
24
#define EXCP_LAZYFP 20 /* v7M fault during lazy FP stacking */
25
#define EXCP_LSERR 21 /* v8M LSERR SecureFault */
26
#define EXCP_UNALIGNED 22 /* v7M UNALIGNED UsageFault */
27
+#define EXCP_DIVBYZERO 23 /* v7M DIVBYZERO UsageFault */
28
/* NB: add new EXCP_ defines to the array in arm_log_exception() too */
29
30
#define ARMV7M_EXCP_RESET 1
19
diff --git a/target/arm/helper.h b/target/arm/helper.h
31
diff --git a/target/arm/helper.h b/target/arm/helper.h
20
index XXXXXXX..XXXXXXX 100644
32
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper.h
33
--- a/target/arm/helper.h
22
+++ b/target/arm/helper.h
34
+++ b/target/arm/helper.h
23
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(neon_qzip32, TCG_CALL_NO_RWG, void, ptr, ptr)
35
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_3(add_saturate, i32, env, i32, i32)
24
DEF_HELPER_FLAGS_4(crypto_aese, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
36
DEF_HELPER_3(sub_saturate, i32, env, i32, i32)
25
DEF_HELPER_FLAGS_3(crypto_aesmc, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
37
DEF_HELPER_3(add_usaturate, i32, env, i32, i32)
26
38
DEF_HELPER_3(sub_usaturate, i32, env, i32, i32)
27
-DEF_HELPER_FLAGS_4(crypto_sha1_3reg, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
39
-DEF_HELPER_FLAGS_2(sdiv, TCG_CALL_NO_RWG_SE, s32, s32, s32)
28
+DEF_HELPER_FLAGS_4(crypto_sha1su0, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
40
-DEF_HELPER_FLAGS_2(udiv, TCG_CALL_NO_RWG_SE, i32, i32, i32)
29
+DEF_HELPER_FLAGS_4(crypto_sha1c, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
41
+DEF_HELPER_FLAGS_3(sdiv, TCG_CALL_NO_RWG, s32, env, s32, s32)
30
+DEF_HELPER_FLAGS_4(crypto_sha1p, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
42
+DEF_HELPER_FLAGS_3(udiv, TCG_CALL_NO_RWG, i32, env, i32, i32)
31
+DEF_HELPER_FLAGS_4(crypto_sha1m, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
43
DEF_HELPER_FLAGS_1(rbit, TCG_CALL_NO_RWG_SE, i32, i32)
32
DEF_HELPER_FLAGS_3(crypto_sha1h, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
44
33
DEF_HELPER_FLAGS_3(crypto_sha1su1, TCG_CALL_NO_RWG, void, ptr, ptr, i32)
45
#define PAS_OP(pfx) \
34
46
diff --git a/target/arm/helper.c b/target/arm/helper.c
35
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
36
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
37
--- a/target/arm/neon-dp.decode
48
--- a/target/arm/helper.c
38
+++ b/target/arm/neon-dp.decode
49
+++ b/target/arm/helper.c
39
@@ -XXX,XX +XXX,XX @@ VQRDMLAH_3s 1111 001 1 0 . .. .... .... 1011 ... 1 .... @3same
50
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(sxtb16)(uint32_t x)
40
@3same_crypto .... .... .... .... .... .... .... .... \
51
return res;
41
&3same vm=%vm_dp vn=%vn_dp vd=%vd_dp size=0 q=1
42
43
-SHA1_3s 1111 001 0 0 . optype:2 .... .... 1100 . 1 . 0 .... \
44
- vm=%vm_dp vn=%vn_dp vd=%vd_dp
45
+SHA1C_3s 1111 001 0 0 . 00 .... .... 1100 . 1 . 0 .... @3same_crypto
46
+SHA1P_3s 1111 001 0 0 . 01 .... .... 1100 . 1 . 0 .... @3same_crypto
47
+SHA1M_3s 1111 001 0 0 . 10 .... .... 1100 . 1 . 0 .... @3same_crypto
48
+SHA1SU0_3s 1111 001 0 0 . 11 .... .... 1100 . 1 . 0 .... @3same_crypto
49
SHA256H_3s 1111 001 1 0 . 00 .... .... 1100 . 1 . 0 .... @3same_crypto
50
SHA256H2_3s 1111 001 1 0 . 01 .... .... 1100 . 1 . 0 .... @3same_crypto
51
SHA256SU1_3s 1111 001 1 0 . 10 .... .... 1100 . 1 . 0 .... @3same_crypto
52
diff --git a/target/arm/crypto_helper.c b/target/arm/crypto_helper.c
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/crypto_helper.c
55
+++ b/target/arm/crypto_helper.c
56
@@ -XXX,XX +XXX,XX @@ union CRYPTO_STATE {
57
};
58
59
#ifdef HOST_WORDS_BIGENDIAN
60
-#define CR_ST_BYTE(state, i) (state.bytes[(15 - (i)) ^ 8])
61
-#define CR_ST_WORD(state, i) (state.words[(3 - (i)) ^ 2])
62
+#define CR_ST_BYTE(state, i) ((state).bytes[(15 - (i)) ^ 8])
63
+#define CR_ST_WORD(state, i) ((state).words[(3 - (i)) ^ 2])
64
#else
65
-#define CR_ST_BYTE(state, i) (state.bytes[i])
66
-#define CR_ST_WORD(state, i) (state.words[i])
67
+#define CR_ST_BYTE(state, i) ((state).bytes[i])
68
+#define CR_ST_WORD(state, i) ((state).words[i])
69
#endif
70
71
/*
72
@@ -XXX,XX +XXX,XX @@ static uint32_t maj(uint32_t x, uint32_t y, uint32_t z)
73
return (x & y) | ((x | y) & z);
74
}
52
}
75
53
76
-void HELPER(crypto_sha1_3reg)(void *vd, void *vn, void *vm, uint32_t op)
54
+static void handle_possible_div0_trap(CPUARMState *env, uintptr_t ra)
77
+void HELPER(crypto_sha1su0)(void *vd, void *vn, void *vm, uint32_t desc)
78
+{
55
+{
79
+ uint64_t *d = vd, *n = vn, *m = vm;
56
+ /*
80
+ uint64_t d0, d1;
57
+ * Take a division-by-zero exception if necessary; otherwise return
81
+
58
+ * to get the usual non-trapping division behaviour (result of 0)
82
+ d0 = d[1] ^ d[0] ^ m[0];
59
+ */
83
+ d1 = n[0] ^ d[1] ^ m[1];
60
+ if (arm_feature(env, ARM_FEATURE_M)
84
+ d[0] = d0;
61
+ && (env->v7m.ccr[env->v7m.secure] & R_V7M_CCR_DIV_0_TRP_MASK)) {
85
+ d[1] = d1;
62
+ raise_exception_ra(env, EXCP_DIVBYZERO, 0, 1, ra);
86
+
63
+ }
87
+ clear_tail_16(vd, desc);
88
+}
64
+}
89
+
65
+
90
+static inline void crypto_sha1_3reg(uint64_t *rd, uint64_t *rn,
66
uint32_t HELPER(uxtb16)(uint32_t x)
91
+ uint64_t *rm, uint32_t desc,
92
+ uint32_t (*fn)(union CRYPTO_STATE *d))
93
{
67
{
94
- uint64_t *rd = vd;
68
uint32_t res;
95
- uint64_t *rn = vn;
69
@@ -XXX,XX +XXX,XX @@ uint32_t HELPER(uxtb16)(uint32_t x)
96
- uint64_t *rm = vm;
70
return res;
97
union CRYPTO_STATE d = { .l = { rd[0], rd[1] } };
71
}
98
union CRYPTO_STATE n = { .l = { rn[0], rn[1] } };
72
99
union CRYPTO_STATE m = { .l = { rm[0], rm[1] } };
73
-int32_t HELPER(sdiv)(int32_t num, int32_t den)
100
+ int i;
74
+int32_t HELPER(sdiv)(CPUARMState *env, int32_t num, int32_t den)
101
75
{
102
- if (op == 3) { /* sha1su0 */
76
if (den == 0) {
103
- d.l[0] ^= d.l[1] ^ m.l[0];
77
+ handle_possible_div0_trap(env, GETPC());
104
- d.l[1] ^= n.l[0] ^ m.l[1];
78
return 0;
105
- } else {
106
- int i;
107
+ for (i = 0; i < 4; i++) {
108
+ uint32_t t = fn(&d);
109
110
- for (i = 0; i < 4; i++) {
111
- uint32_t t;
112
+ t += rol32(CR_ST_WORD(d, 0), 5) + CR_ST_WORD(n, 0)
113
+ + CR_ST_WORD(m, i);
114
115
- switch (op) {
116
- case 0: /* sha1c */
117
- t = cho(CR_ST_WORD(d, 1), CR_ST_WORD(d, 2), CR_ST_WORD(d, 3));
118
- break;
119
- case 1: /* sha1p */
120
- t = par(CR_ST_WORD(d, 1), CR_ST_WORD(d, 2), CR_ST_WORD(d, 3));
121
- break;
122
- case 2: /* sha1m */
123
- t = maj(CR_ST_WORD(d, 1), CR_ST_WORD(d, 2), CR_ST_WORD(d, 3));
124
- break;
125
- default:
126
- g_assert_not_reached();
127
- }
128
- t += rol32(CR_ST_WORD(d, 0), 5) + CR_ST_WORD(n, 0)
129
- + CR_ST_WORD(m, i);
130
-
131
- CR_ST_WORD(n, 0) = CR_ST_WORD(d, 3);
132
- CR_ST_WORD(d, 3) = CR_ST_WORD(d, 2);
133
- CR_ST_WORD(d, 2) = ror32(CR_ST_WORD(d, 1), 2);
134
- CR_ST_WORD(d, 1) = CR_ST_WORD(d, 0);
135
- CR_ST_WORD(d, 0) = t;
136
- }
137
+ CR_ST_WORD(n, 0) = CR_ST_WORD(d, 3);
138
+ CR_ST_WORD(d, 3) = CR_ST_WORD(d, 2);
139
+ CR_ST_WORD(d, 2) = ror32(CR_ST_WORD(d, 1), 2);
140
+ CR_ST_WORD(d, 1) = CR_ST_WORD(d, 0);
141
+ CR_ST_WORD(d, 0) = t;
142
}
79
}
143
rd[0] = d.l[0];
80
if (num == INT_MIN && den == -1) {
144
rd[1] = d.l[1];
81
@@ -XXX,XX +XXX,XX @@ int32_t HELPER(sdiv)(int32_t num, int32_t den)
145
+
82
return num / den;
146
+ clear_tail_16(rd, desc);
147
+}
148
+
149
+static uint32_t do_sha1c(union CRYPTO_STATE *d)
150
+{
151
+ return cho(CR_ST_WORD(*d, 1), CR_ST_WORD(*d, 2), CR_ST_WORD(*d, 3));
152
+}
153
+
154
+void HELPER(crypto_sha1c)(void *vd, void *vn, void *vm, uint32_t desc)
155
+{
156
+ crypto_sha1_3reg(vd, vn, vm, desc, do_sha1c);
157
+}
158
+
159
+static uint32_t do_sha1p(union CRYPTO_STATE *d)
160
+{
161
+ return par(CR_ST_WORD(*d, 1), CR_ST_WORD(*d, 2), CR_ST_WORD(*d, 3));
162
+}
163
+
164
+void HELPER(crypto_sha1p)(void *vd, void *vn, void *vm, uint32_t desc)
165
+{
166
+ crypto_sha1_3reg(vd, vn, vm, desc, do_sha1p);
167
+}
168
+
169
+static uint32_t do_sha1m(union CRYPTO_STATE *d)
170
+{
171
+ return maj(CR_ST_WORD(*d, 1), CR_ST_WORD(*d, 2), CR_ST_WORD(*d, 3));
172
+}
173
+
174
+void HELPER(crypto_sha1m)(void *vd, void *vn, void *vm, uint32_t desc)
175
+{
176
+ crypto_sha1_3reg(vd, vn, vm, desc, do_sha1m);
177
}
83
}
178
84
179
void HELPER(crypto_sha1h)(void *vd, void *vm, uint32_t desc)
85
-uint32_t HELPER(udiv)(uint32_t num, uint32_t den)
180
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
86
+uint32_t HELPER(udiv)(CPUARMState *env, uint32_t num, uint32_t den)
87
{
88
if (den == 0) {
89
+ handle_possible_div0_trap(env, GETPC());
90
return 0;
91
}
92
return num / den;
93
@@ -XXX,XX +XXX,XX @@ void arm_log_exception(int idx)
94
[EXCP_LAZYFP] = "v7M exception during lazy FP stacking",
95
[EXCP_LSERR] = "v8M LSERR UsageFault",
96
[EXCP_UNALIGNED] = "v7M UNALIGNED UsageFault",
97
+ [EXCP_DIVBYZERO] = "v7M DIVBYZERO UsageFault",
98
};
99
100
if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
101
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
181
index XXXXXXX..XXXXXXX 100644
102
index XXXXXXX..XXXXXXX 100644
182
--- a/target/arm/translate-a64.c
103
--- a/target/arm/m_helper.c
183
+++ b/target/arm/translate-a64.c
104
+++ b/target/arm/m_helper.c
184
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
105
@@ -XXX,XX +XXX,XX @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
185
106
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
186
switch (opcode) {
107
env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_UNALIGNED_MASK;
187
case 0: /* SHA1C */
108
break;
188
+ genfn = gen_helper_crypto_sha1c;
109
+ case EXCP_DIVBYZERO:
189
+ feature = dc_isar_feature(aa64_sha1, s);
110
+ armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_USAGE, env->v7m.secure);
111
+ env->v7m.cfsr[env->v7m.secure] |= R_V7M_CFSR_DIVBYZERO_MASK;
190
+ break;
112
+ break;
191
case 1: /* SHA1P */
113
case EXCP_SWI:
192
+ genfn = gen_helper_crypto_sha1p;
114
/* The PC already points to the next instruction. */
193
+ feature = dc_isar_feature(aa64_sha1, s);
115
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_SVC, env->v7m.secure);
194
+ break;
116
diff --git a/target/arm/translate.c b/target/arm/translate.c
195
case 2: /* SHA1M */
117
index XXXXXXX..XXXXXXX 100644
196
+ genfn = gen_helper_crypto_sha1m;
118
--- a/target/arm/translate.c
197
+ feature = dc_isar_feature(aa64_sha1, s);
119
+++ b/target/arm/translate.c
198
+ break;
120
@@ -XXX,XX +XXX,XX @@ static bool op_div(DisasContext *s, arg_rrr *a, bool u)
199
case 3: /* SHA1SU0 */
121
t1 = load_reg(s, a->rn);
200
- genfn = NULL;
122
t2 = load_reg(s, a->rm);
201
+ genfn = gen_helper_crypto_sha1su0;
123
if (u) {
202
feature = dc_isar_feature(aa64_sha1, s);
124
- gen_helper_udiv(t1, t1, t2);
203
break;
125
+ gen_helper_udiv(t1, cpu_env, t1, t2);
204
case 4: /* SHA256H */
126
} else {
205
@@ -XXX,XX +XXX,XX @@ static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
127
- gen_helper_sdiv(t1, t1, t2);
206
if (!fp_access_check(s)) {
128
+ gen_helper_sdiv(t1, cpu_env, t1, t2);
207
return;
208
}
129
}
209
-
130
tcg_temp_free_i32(t2);
210
- if (genfn) {
131
store_reg(s, a->rd, t1);
211
- gen_gvec_op3_ool(s, true, rd, rn, rm, 0, genfn);
212
- } else {
213
- TCGv_i32 tcg_opcode = tcg_const_i32(opcode);
214
- TCGv_ptr tcg_rd_ptr = vec_full_reg_ptr(s, rd);
215
- TCGv_ptr tcg_rn_ptr = vec_full_reg_ptr(s, rn);
216
- TCGv_ptr tcg_rm_ptr = vec_full_reg_ptr(s, rm);
217
-
218
- gen_helper_crypto_sha1_3reg(tcg_rd_ptr, tcg_rn_ptr,
219
- tcg_rm_ptr, tcg_opcode);
220
-
221
- tcg_temp_free_i32(tcg_opcode);
222
- tcg_temp_free_ptr(tcg_rd_ptr);
223
- tcg_temp_free_ptr(tcg_rn_ptr);
224
- tcg_temp_free_ptr(tcg_rm_ptr);
225
- }
226
+ gen_gvec_op3_ool(s, true, rd, rn, rm, 0, genfn);
227
}
228
229
/* Crypto two-reg SHA
230
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
231
index XXXXXXX..XXXXXXX 100644
232
--- a/target/arm/translate-neon.inc.c
233
+++ b/target/arm/translate-neon.inc.c
234
@@ -XXX,XX +XXX,XX @@ static bool trans_VMUL_p_3s(DisasContext *s, arg_3same *a)
235
DO_VQRDMLAH(VQRDMLAH, gen_gvec_sqrdmlah_qc)
236
DO_VQRDMLAH(VQRDMLSH, gen_gvec_sqrdmlsh_qc)
237
238
-static bool trans_SHA1_3s(DisasContext *s, arg_SHA1_3s *a)
239
-{
240
- TCGv_ptr ptr1, ptr2, ptr3;
241
- TCGv_i32 tmp;
242
-
243
- if (!arm_dc_feature(s, ARM_FEATURE_NEON) ||
244
- !dc_isar_feature(aa32_sha1, s)) {
245
- return false;
246
+#define DO_SHA1(NAME, FUNC) \
247
+ WRAP_OOL_FN(gen_##NAME##_3s, FUNC) \
248
+ static bool trans_##NAME##_3s(DisasContext *s, arg_3same *a) \
249
+ { \
250
+ if (!dc_isar_feature(aa32_sha1, s)) { \
251
+ return false; \
252
+ } \
253
+ return do_3same(s, a, gen_##NAME##_3s); \
254
}
255
256
- /* UNDEF accesses to D16-D31 if they don't exist. */
257
- if (!dc_isar_feature(aa32_simd_r32, s) &&
258
- ((a->vd | a->vn | a->vm) & 0x10)) {
259
- return false;
260
- }
261
-
262
- if ((a->vn | a->vm | a->vd) & 1) {
263
- return false;
264
- }
265
-
266
- if (!vfp_access_check(s)) {
267
- return true;
268
- }
269
-
270
- ptr1 = vfp_reg_ptr(true, a->vd);
271
- ptr2 = vfp_reg_ptr(true, a->vn);
272
- ptr3 = vfp_reg_ptr(true, a->vm);
273
- tmp = tcg_const_i32(a->optype);
274
- gen_helper_crypto_sha1_3reg(ptr1, ptr2, ptr3, tmp);
275
- tcg_temp_free_i32(tmp);
276
- tcg_temp_free_ptr(ptr1);
277
- tcg_temp_free_ptr(ptr2);
278
- tcg_temp_free_ptr(ptr3);
279
-
280
- return true;
281
-}
282
+DO_SHA1(SHA1C, gen_helper_crypto_sha1c)
283
+DO_SHA1(SHA1P, gen_helper_crypto_sha1p)
284
+DO_SHA1(SHA1M, gen_helper_crypto_sha1m)
285
+DO_SHA1(SHA1SU0, gen_helper_crypto_sha1su0)
286
287
#define DO_SHA2(NAME, FUNC) \
288
WRAP_OOL_FN(gen_##NAME##_3s, FUNC) \
289
--
132
--
290
2.20.1
133
2.20.1
291
134
292
135
diff view generated by jsdifflib
1
From: Cédric Le Goater <clg@kaod.org>
1
From: Hamza Mahfooz <someguy@effective-light.com>
2
2
3
Signed-off-by: Cédric Le Goater <clg@kaod.org>
3
As per commit 5626f8c6d468 ("rcu: Add automatically released rcu_read_lock
4
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
4
variants"), RCU_READ_LOCK_GUARD() should be used instead of
5
Message-id: 20200602135050.593692-1-clg@kaod.org
5
rcu_read_{un}lock().
6
7
Signed-off-by: Hamza Mahfooz <someguy@effective-light.com>
8
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
9
Message-id: 20210727235201.11491-1-someguy@effective-light.com
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
---
11
---
8
docs/system/arm/aspeed.rst | 85 ++++++++++++++++++++++++++++++++++++++
12
target/arm/kvm.c | 17 ++++++++---------
9
docs/system/target-arm.rst | 1 +
13
1 file changed, 8 insertions(+), 9 deletions(-)
10
2 files changed, 86 insertions(+)
11
create mode 100644 docs/system/arm/aspeed.rst
12
14
13
diff --git a/docs/system/arm/aspeed.rst b/docs/system/arm/aspeed.rst
15
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
14
new file mode 100644
16
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX
17
--- a/target/arm/kvm.c
16
--- /dev/null
18
+++ b/target/arm/kvm.c
17
+++ b/docs/system/arm/aspeed.rst
19
@@ -XXX,XX +XXX,XX @@ int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
18
@@ -XXX,XX +XXX,XX @@
20
hwaddr xlat, len, doorbell_gpa;
19
+Aspeed family boards (``*-bmc``, ``ast2500-evb``, ``ast2600-evb``)
21
MemoryRegionSection mrs;
20
+==================================================================
22
MemoryRegion *mr;
23
- int ret = 1;
24
25
if (as == &address_space_memory) {
26
return 0;
27
@@ -XXX,XX +XXX,XX @@ int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
28
29
/* MSI doorbell address is translated by an IOMMU */
30
31
- rcu_read_lock();
32
+ RCU_READ_LOCK_GUARD();
21
+
33
+
22
+The QEMU Aspeed machines model BMCs of various OpenPOWER systems and
34
mr = address_space_translate(as, address, &xlat, &len, true,
23
+Aspeed evaluation boards. They are based on different releases of the
35
MEMTXATTRS_UNSPECIFIED);
24
+Aspeed SoC : the AST2400 integrating an ARM926EJ-S CPU (400MHz), the
25
+AST2500 with an ARM1176JZS CPU (800MHz) and more recently the AST2600
26
+with dual cores ARM Cortex A7 CPUs (1.2GHz).
27
+
36
+
28
+The SoC comes with RAM, Gigabit ethernet, USB, SD/MMC, USB, SPI, I2C,
37
if (!mr) {
29
+etc.
38
- goto unlock;
39
+ return 1;
40
}
30
+
41
+
31
+AST2400 SoC based machines :
42
mrs = memory_region_find(mr, xlat, 1);
32
+
43
+
33
+- ``palmetto-bmc`` OpenPOWER Palmetto POWER8 BMC
44
if (!mrs.mr) {
34
+
45
- goto unlock;
35
+AST2500 SoC based machines :
46
+ return 1;
36
+
47
}
37
+- ``ast2500-evb`` Aspeed AST2500 Evaluation board
48
38
+- ``romulus-bmc`` OpenPOWER Romulus POWER9 BMC
49
doorbell_gpa = mrs.offset_within_address_space;
39
+- ``witherspoon-bmc`` OpenPOWER Witherspoon POWER9 BMC
50
@@ -XXX,XX +XXX,XX @@ int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
40
+- ``sonorapass-bmc`` OCP SonoraPass BMC
51
41
+- ``swift-bmc`` OpenPOWER Swift BMC POWER9
52
trace_kvm_arm_fixup_msi_route(address, doorbell_gpa);
42
+
53
43
+AST2600 SoC based machines :
54
- ret = 0;
44
+
55
-
45
+- ``ast2600-evb`` Aspeed AST2600 Evaluation board (Cortex A7)
56
-unlock:
46
+- ``tacoma-bmc`` OpenPOWER Witherspoon POWER9 AST2600 BMC
57
- rcu_read_unlock();
47
+
58
- return ret;
48
+Supported devices
59
+ return 0;
49
+-----------------
60
}
50
+
61
51
+ * SMP (for the AST2600 Cortex-A7)
62
int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
52
+ * Interrupt Controller (VIC)
53
+ * Timer Controller
54
+ * RTC Controller
55
+ * I2C Controller
56
+ * System Control Unit (SCU)
57
+ * SRAM mapping
58
+ * X-DMA Controller (basic interface)
59
+ * Static Memory Controller (SMC or FMC) - Only SPI Flash support
60
+ * SPI Memory Controller
61
+ * USB 2.0 Controller
62
+ * SD/MMC storage controllers
63
+ * SDRAM controller (dummy interface for basic settings and training)
64
+ * Watchdog Controller
65
+ * GPIO Controller (Master only)
66
+ * UART
67
+ * Ethernet controllers
68
+
69
+
70
+Missing devices
71
+---------------
72
+
73
+ * Coprocessor support
74
+ * ADC (out of tree implementation)
75
+ * PWM and Fan Controller
76
+ * LPC Bus Controller
77
+ * Slave GPIO Controller
78
+ * Super I/O Controller
79
+ * Hash/Crypto Engine
80
+ * PCI-Express 1 Controller
81
+ * Graphic Display Controller
82
+ * PECI Controller
83
+ * MCTP Controller
84
+ * Mailbox Controller
85
+ * Virtual UART
86
+ * eSPI Controller
87
+ * I3C Controller
88
+
89
+Boot options
90
+------------
91
+
92
+The Aspeed machines can be started using the -kernel option to load a
93
+Linux kernel or from a firmare image which can be downloaded from the
94
+OpenPOWER jenkins :
95
+
96
+ https://openpower.xyz/
97
+
98
+The image should be attached as an MTD drive. Run :
99
+
100
+.. code-block:: bash
101
+
102
+ $ qemu-system-arm -M romulus-bmc -nic user \
103
+    -drive file=flash-romulus,format=raw,if=mtd -nographic
104
diff --git a/docs/system/target-arm.rst b/docs/system/target-arm.rst
105
index XXXXXXX..XXXXXXX 100644
106
--- a/docs/system/target-arm.rst
107
+++ b/docs/system/target-arm.rst
108
@@ -XXX,XX +XXX,XX @@ undocumented; you can get a complete list by running
109
arm/realview
110
arm/versatile
111
arm/vexpress
112
+ arm/aspeed
113
arm/musicpal
114
arm/nseries
115
arm/orangepi
116
--
63
--
117
2.20.1
64
2.20.1
118
65
119
66
diff view generated by jsdifflib
1
From: Paul Zimmerman <pauldzim@gmail.com>
1
From: Jan Luebbe <jlu@pengutronix.de>
2
2
3
Add the dwc-hsotg (dwc2) USB host controller state definitions.
3
Break events are currently only handled by chardev/char-serial.c, so we
4
Mostly based on hw/usb/hcd-ehci.h.
4
just ignore errors, which results in no behaviour change for other
5
chardevs.
5
6
6
Signed-off-by: Paul Zimmerman <pauldzim@gmail.com>
7
Signed-off-by: Jan Luebbe <jlu@pengutronix.de>
7
Message-id: 20200520235349.21215-4-pauldzim@gmail.com
8
Message-id: 20210806144700.3751979-1-jlu@pengutronix.de
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
---
11
---
11
hw/usb/hcd-dwc2.h | 190 ++++++++++++++++++++++++++++++++++++++++++++++
12
hw/char/pl011.c | 6 ++++++
12
1 file changed, 190 insertions(+)
13
1 file changed, 6 insertions(+)
13
create mode 100644 hw/usb/hcd-dwc2.h
14
14
15
diff --git a/hw/usb/hcd-dwc2.h b/hw/usb/hcd-dwc2.h
15
diff --git a/hw/char/pl011.c b/hw/char/pl011.c
16
new file mode 100644
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX
17
--- a/hw/char/pl011.c
18
--- /dev/null
18
+++ b/hw/char/pl011.c
19
+++ b/hw/usb/hcd-dwc2.h
20
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
21
+/*
20
#include "hw/qdev-properties-system.h"
22
+ * dwc-hsotg (dwc2) USB host controller state definitions
21
#include "migration/vmstate.h"
23
+ *
22
#include "chardev/char-fe.h"
24
+ * Based on hw/usb/hcd-ehci.h
23
+#include "chardev/char-serial.h"
25
+ *
24
#include "qemu/log.h"
26
+ * Copyright (c) 2020 Paul Zimmerman <pauldzim@gmail.com>
25
#include "qemu/module.h"
27
+ *
26
#include "trace.h"
28
+ * This program is free software; you can redistribute it and/or modify
27
@@ -XXX,XX +XXX,XX @@ static void pl011_write(void *opaque, hwaddr offset,
29
+ * it under the terms of the GNU General Public License as published by
28
s->read_count = 0;
30
+ * the Free Software Foundation; either version 2 of the License, or
29
s->read_pos = 0;
31
+ * (at your option) any later version.
30
}
32
+ *
31
+ if ((s->lcr ^ value) & 0x1) {
33
+ * This program is distributed in the hope that it will be useful,
32
+ int break_enable = value & 0x1;
34
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
33
+ qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
35
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34
+ &break_enable);
36
+ * GNU General Public License for more details.
35
+ }
37
+ */
36
s->lcr = value;
38
+
37
pl011_set_read_trigger(s);
39
+#ifndef HW_USB_DWC2_H
38
break;
40
+#define HW_USB_DWC2_H
41
+
42
+#include "qemu/timer.h"
43
+#include "hw/irq.h"
44
+#include "hw/sysbus.h"
45
+#include "hw/usb.h"
46
+#include "sysemu/dma.h"
47
+
48
+#define DWC2_MMIO_SIZE 0x11000
49
+
50
+#define DWC2_NB_CHAN 8 /* Number of host channels */
51
+#define DWC2_MAX_XFER_SIZE 65536 /* Max transfer size expected in HCTSIZ */
52
+
53
+typedef struct DWC2Packet DWC2Packet;
54
+typedef struct DWC2State DWC2State;
55
+typedef struct DWC2Class DWC2Class;
56
+
57
+enum async_state {
58
+ DWC2_ASYNC_NONE = 0,
59
+ DWC2_ASYNC_INITIALIZED,
60
+ DWC2_ASYNC_INFLIGHT,
61
+ DWC2_ASYNC_FINISHED,
62
+};
63
+
64
+struct DWC2Packet {
65
+ USBPacket packet;
66
+ uint32_t devadr;
67
+ uint32_t epnum;
68
+ uint32_t epdir;
69
+ uint32_t mps;
70
+ uint32_t pid;
71
+ uint32_t index;
72
+ uint32_t pcnt;
73
+ uint32_t len;
74
+ int32_t async;
75
+ bool small;
76
+ bool needs_service;
77
+};
78
+
79
+struct DWC2State {
80
+ /*< private >*/
81
+ SysBusDevice parent_obj;
82
+
83
+ /*< public >*/
84
+ USBBus bus;
85
+ qemu_irq irq;
86
+ MemoryRegion *dma_mr;
87
+ AddressSpace dma_as;
88
+ MemoryRegion container;
89
+ MemoryRegion hsotg;
90
+ MemoryRegion fifos;
91
+
92
+ union {
93
+#define DWC2_GLBREG_SIZE 0x70
94
+ uint32_t glbreg[DWC2_GLBREG_SIZE / sizeof(uint32_t)];
95
+ struct {
96
+ uint32_t gotgctl; /* 00 */
97
+ uint32_t gotgint; /* 04 */
98
+ uint32_t gahbcfg; /* 08 */
99
+ uint32_t gusbcfg; /* 0c */
100
+ uint32_t grstctl; /* 10 */
101
+ uint32_t gintsts; /* 14 */
102
+ uint32_t gintmsk; /* 18 */
103
+ uint32_t grxstsr; /* 1c */
104
+ uint32_t grxstsp; /* 20 */
105
+ uint32_t grxfsiz; /* 24 */
106
+ uint32_t gnptxfsiz; /* 28 */
107
+ uint32_t gnptxsts; /* 2c */
108
+ uint32_t gi2cctl; /* 30 */
109
+ uint32_t gpvndctl; /* 34 */
110
+ uint32_t ggpio; /* 38 */
111
+ uint32_t guid; /* 3c */
112
+ uint32_t gsnpsid; /* 40 */
113
+ uint32_t ghwcfg1; /* 44 */
114
+ uint32_t ghwcfg2; /* 48 */
115
+ uint32_t ghwcfg3; /* 4c */
116
+ uint32_t ghwcfg4; /* 50 */
117
+ uint32_t glpmcfg; /* 54 */
118
+ uint32_t gpwrdn; /* 58 */
119
+ uint32_t gdfifocfg; /* 5c */
120
+ uint32_t gadpctl; /* 60 */
121
+ uint32_t grefclk; /* 64 */
122
+ uint32_t gintmsk2; /* 68 */
123
+ uint32_t gintsts2; /* 6c */
124
+ };
125
+ };
126
+
127
+ union {
128
+#define DWC2_FSZREG_SIZE 0x04
129
+ uint32_t fszreg[DWC2_FSZREG_SIZE / sizeof(uint32_t)];
130
+ struct {
131
+ uint32_t hptxfsiz; /* 100 */
132
+ };
133
+ };
134
+
135
+ union {
136
+#define DWC2_HREG0_SIZE 0x44
137
+ uint32_t hreg0[DWC2_HREG0_SIZE / sizeof(uint32_t)];
138
+ struct {
139
+ uint32_t hcfg; /* 400 */
140
+ uint32_t hfir; /* 404 */
141
+ uint32_t hfnum; /* 408 */
142
+ uint32_t rsvd0; /* 40c */
143
+ uint32_t hptxsts; /* 410 */
144
+ uint32_t haint; /* 414 */
145
+ uint32_t haintmsk; /* 418 */
146
+ uint32_t hflbaddr; /* 41c */
147
+ uint32_t rsvd1[8]; /* 420-43c */
148
+ uint32_t hprt0; /* 440 */
149
+ };
150
+ };
151
+
152
+#define DWC2_HREG1_SIZE (0x20 * DWC2_NB_CHAN)
153
+ uint32_t hreg1[DWC2_HREG1_SIZE / sizeof(uint32_t)];
154
+
155
+#define hcchar(_ch) hreg1[((_ch) << 3) + 0] /* 500, 520, ... */
156
+#define hcsplt(_ch) hreg1[((_ch) << 3) + 1] /* 504, 524, ... */
157
+#define hcint(_ch) hreg1[((_ch) << 3) + 2] /* 508, 528, ... */
158
+#define hcintmsk(_ch) hreg1[((_ch) << 3) + 3] /* 50c, 52c, ... */
159
+#define hctsiz(_ch) hreg1[((_ch) << 3) + 4] /* 510, 530, ... */
160
+#define hcdma(_ch) hreg1[((_ch) << 3) + 5] /* 514, 534, ... */
161
+#define hcdmab(_ch) hreg1[((_ch) << 3) + 7] /* 51c, 53c, ... */
162
+
163
+ union {
164
+#define DWC2_PCGREG_SIZE 0x08
165
+ uint32_t pcgreg[DWC2_PCGREG_SIZE / sizeof(uint32_t)];
166
+ struct {
167
+ uint32_t pcgctl; /* e00 */
168
+ uint32_t pcgcctl1; /* e04 */
169
+ };
170
+ };
171
+
172
+ /* TODO - implement FIFO registers for slave mode */
173
+#define DWC2_HFIFO_SIZE (0x1000 * DWC2_NB_CHAN)
174
+
175
+ /*
176
+ * Internal state
177
+ */
178
+ QEMUTimer *eof_timer;
179
+ QEMUTimer *frame_timer;
180
+ QEMUBH *async_bh;
181
+ int64_t sof_time;
182
+ int64_t usb_frame_time;
183
+ int64_t usb_bit_time;
184
+ uint32_t usb_version;
185
+ uint16_t frame_number;
186
+ uint16_t fi;
187
+ uint16_t next_chan;
188
+ bool working;
189
+ USBPort uport;
190
+ DWC2Packet packet[DWC2_NB_CHAN]; /* one packet per chan */
191
+ uint8_t usb_buf[DWC2_NB_CHAN][DWC2_MAX_XFER_SIZE]; /* one buffer per chan */
192
+};
193
+
194
+struct DWC2Class {
195
+ /*< private >*/
196
+ SysBusDeviceClass parent_class;
197
+ ResettablePhases parent_phases;
198
+
199
+ /*< public >*/
200
+};
201
+
202
+#define TYPE_DWC2_USB "dwc2-usb"
203
+#define DWC2_USB(obj) \
204
+ OBJECT_CHECK(DWC2State, (obj), TYPE_DWC2_USB)
205
+#define DWC2_CLASS(klass) \
206
+ OBJECT_CLASS_CHECK(DWC2Class, (klass), TYPE_DWC2_USB)
207
+#define DWC2_GET_CLASS(obj) \
208
+ OBJECT_GET_CLASS(DWC2Class, (obj), TYPE_DWC2_USB)
209
+
210
+#endif
211
--
39
--
212
2.20.1
40
2.20.1
213
41
214
42
diff view generated by jsdifflib
1
From: Thomas Huth <thuth@redhat.com>
1
From: Guenter Roeck <linux@roeck-us.net>
2
2
3
As described by Edgar here:
3
Instantiate SAI1/2/3 and ASRC as unimplemented devices to avoid random
4
Linux kernel crashes, such as
4
5
5
https://www.mail-archive.com/qemu-devel@nongnu.org/msg605124.html
6
Unhandled fault: external abort on non-linefetch (0x808) at 0xd1580010
7
pgd = (ptrval)
8
[d1580010] *pgd=8231b811, *pte=02034653, *ppte=02034453
9
Internal error: : 808 [#1] SMP ARM
10
...
11
[<c095e974>] (regmap_mmio_write32le) from [<c095eb48>] (regmap_mmio_write+0x3c/0x54)
12
[<c095eb48>] (regmap_mmio_write) from [<c09580f4>] (_regmap_write+0x4c/0x1f0)
13
[<c09580f4>] (_regmap_write) from [<c095837c>] (_regmap_update_bits+0xe4/0xec)
14
[<c095837c>] (_regmap_update_bits) from [<c09599b4>] (regmap_update_bits_base+0x50/0x74)
15
[<c09599b4>] (regmap_update_bits_base) from [<c0d3e9e4>] (fsl_asrc_runtime_resume+0x1e4/0x21c)
16
[<c0d3e9e4>] (fsl_asrc_runtime_resume) from [<c0942464>] (__rpm_callback+0x3c/0x108)
17
[<c0942464>] (__rpm_callback) from [<c0942590>] (rpm_callback+0x60/0x64)
18
[<c0942590>] (rpm_callback) from [<c0942b60>] (rpm_resume+0x5cc/0x808)
19
[<c0942b60>] (rpm_resume) from [<c0942dfc>] (__pm_runtime_resume+0x60/0xa0)
20
[<c0942dfc>] (__pm_runtime_resume) from [<c0d3ecc4>] (fsl_asrc_probe+0x2a8/0x708)
21
[<c0d3ecc4>] (fsl_asrc_probe) from [<c0935b08>] (platform_probe+0x58/0xb8)
22
[<c0935b08>] (platform_probe) from [<c0933264>] (really_probe.part.0+0x9c/0x334)
23
[<c0933264>] (really_probe.part.0) from [<c093359c>] (__driver_probe_device+0xa0/0x138)
24
[<c093359c>] (__driver_probe_device) from [<c0933664>] (driver_probe_device+0x30/0xc8)
25
[<c0933664>] (driver_probe_device) from [<c0933c88>] (__driver_attach+0x90/0x130)
26
[<c0933c88>] (__driver_attach) from [<c0931060>] (bus_for_each_dev+0x78/0xb8)
27
[<c0931060>] (bus_for_each_dev) from [<c093254c>] (bus_add_driver+0xf0/0x1d8)
28
[<c093254c>] (bus_add_driver) from [<c0934a30>] (driver_register+0x88/0x118)
29
[<c0934a30>] (driver_register) from [<c01022c0>] (do_one_initcall+0x7c/0x3a4)
30
[<c01022c0>] (do_one_initcall) from [<c1601204>] (kernel_init_freeable+0x198/0x22c)
31
[<c1601204>] (kernel_init_freeable) from [<c0f5ff2c>] (kernel_init+0x10/0x128)
32
[<c0f5ff2c>] (kernel_init) from [<c010013c>] (ret_from_fork+0x14/0x38)
6
33
7
we can use the Ubuntu kernel for testing the xlnx-versal-virt machine.
34
or
8
So let's add a boot test for this now.
9
35
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
36
Unhandled fault: external abort on non-linefetch (0x808) at 0xd19b0000
11
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
37
pgd = (ptrval)
12
Signed-off-by: Thomas Huth <thuth@redhat.com>
38
[d19b0000] *pgd=82711811, *pte=308a0653, *ppte=308a0453
13
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
39
Internal error: : 808 [#1] SMP ARM
14
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com>
40
...
15
Message-id: 20200525141237.15243-1-thuth@redhat.com
41
[<c095e974>] (regmap_mmio_write32le) from [<c095eb48>] (regmap_mmio_write+0x3c/0x54)
42
[<c095eb48>] (regmap_mmio_write) from [<c09580f4>] (_regmap_write+0x4c/0x1f0)
43
[<c09580f4>] (_regmap_write) from [<c0959b28>] (regmap_write+0x3c/0x60)
44
[<c0959b28>] (regmap_write) from [<c0d41130>] (fsl_sai_runtime_resume+0x9c/0x1ec)
45
[<c0d41130>] (fsl_sai_runtime_resume) from [<c0942464>] (__rpm_callback+0x3c/0x108)
46
[<c0942464>] (__rpm_callback) from [<c0942590>] (rpm_callback+0x60/0x64)
47
[<c0942590>] (rpm_callback) from [<c0942b60>] (rpm_resume+0x5cc/0x808)
48
[<c0942b60>] (rpm_resume) from [<c0942dfc>] (__pm_runtime_resume+0x60/0xa0)
49
[<c0942dfc>] (__pm_runtime_resume) from [<c0d4231c>] (fsl_sai_probe+0x2b8/0x65c)
50
[<c0d4231c>] (fsl_sai_probe) from [<c0935b08>] (platform_probe+0x58/0xb8)
51
[<c0935b08>] (platform_probe) from [<c0933264>] (really_probe.part.0+0x9c/0x334)
52
[<c0933264>] (really_probe.part.0) from [<c093359c>] (__driver_probe_device+0xa0/0x138)
53
[<c093359c>] (__driver_probe_device) from [<c0933664>] (driver_probe_device+0x30/0xc8)
54
[<c0933664>] (driver_probe_device) from [<c0933c88>] (__driver_attach+0x90/0x130)
55
[<c0933c88>] (__driver_attach) from [<c0931060>] (bus_for_each_dev+0x78/0xb8)
56
[<c0931060>] (bus_for_each_dev) from [<c093254c>] (bus_add_driver+0xf0/0x1d8)
57
[<c093254c>] (bus_add_driver) from [<c0934a30>] (driver_register+0x88/0x118)
58
[<c0934a30>] (driver_register) from [<c01022c0>] (do_one_initcall+0x7c/0x3a4)
59
[<c01022c0>] (do_one_initcall) from [<c1601204>] (kernel_init_freeable+0x198/0x22c)
60
[<c1601204>] (kernel_init_freeable) from [<c0f5ff2c>] (kernel_init+0x10/0x128)
61
[<c0f5ff2c>] (kernel_init) from [<c010013c>] (ret_from_fork+0x14/0x38)
62
63
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
64
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
65
Message-id: 20210810160318.87376-1-linux@roeck-us.net
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
66
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
---
67
---
18
tests/acceptance/boot_linux_console.py | 26 ++++++++++++++++++++++++++
68
hw/arm/fsl-imx6ul.c | 12 ++++++++++++
19
1 file changed, 26 insertions(+)
69
1 file changed, 12 insertions(+)
20
70
21
diff --git a/tests/acceptance/boot_linux_console.py b/tests/acceptance/boot_linux_console.py
71
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
22
index XXXXXXX..XXXXXXX 100644
72
index XXXXXXX..XXXXXXX 100644
23
--- a/tests/acceptance/boot_linux_console.py
73
--- a/hw/arm/fsl-imx6ul.c
24
+++ b/tests/acceptance/boot_linux_console.py
74
+++ b/hw/arm/fsl-imx6ul.c
25
@@ -XXX,XX +XXX,XX @@ class BootLinuxConsole(LinuxKernelTest):
75
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
26
console_pattern = 'Kernel command line: %s' % kernel_command_line
76
*/
27
self.wait_for_console_pattern(console_pattern)
77
create_unimplemented_device("sdma", FSL_IMX6UL_SDMA_ADDR, 0x4000);
28
78
29
+ def test_aarch64_xlnx_versal_virt(self):
79
+ /*
30
+ """
80
+ * SAI (Audio SSI (Synchronous Serial Interface))
31
+ :avocado: tags=arch:aarch64
81
+ */
32
+ :avocado: tags=machine:xlnx-versal-virt
82
+ create_unimplemented_device("sai1", FSL_IMX6UL_SAI1_ADDR, 0x4000);
33
+ :avocado: tags=device:pl011
83
+ create_unimplemented_device("sai2", FSL_IMX6UL_SAI2_ADDR, 0x4000);
34
+ :avocado: tags=device:arm_gicv3
84
+ create_unimplemented_device("sai3", FSL_IMX6UL_SAI3_ADDR, 0x4000);
35
+ """
36
+ kernel_url = ('http://ports.ubuntu.com/ubuntu-ports/dists/'
37
+ 'bionic-updates/main/installer-arm64/current/images/'
38
+ 'netboot/ubuntu-installer/arm64/linux')
39
+ kernel_hash = '5bfc54cf7ed8157d93f6e5b0241e727b6dc22c50'
40
+ kernel_path = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
41
+
85
+
42
+ initrd_url = ('http://ports.ubuntu.com/ubuntu-ports/dists/'
86
/*
43
+ 'bionic-updates/main/installer-arm64/current/images/'
87
* PWM
44
+ 'netboot/ubuntu-installer/arm64/initrd.gz')
88
*/
45
+ initrd_hash = 'd385d3e88d53e2004c5d43cbe668b458a094f772'
89
@@ -XXX,XX +XXX,XX @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
46
+ initrd_path = self.fetch_asset(initrd_url, asset_hash=initrd_hash)
90
create_unimplemented_device("pwm3", FSL_IMX6UL_PWM3_ADDR, 0x4000);
91
create_unimplemented_device("pwm4", FSL_IMX6UL_PWM4_ADDR, 0x4000);
92
93
+ /*
94
+ * Audio ASRC (asynchronous sample rate converter)
95
+ */
96
+ create_unimplemented_device("asrc", FSL_IMX6UL_ASRC_ADDR, 0x4000);
47
+
97
+
48
+ self.vm.set_console()
98
/*
49
+ self.vm.add_args('-m', '2G',
99
* CAN
50
+ '-kernel', kernel_path,
100
*/
51
+ '-initrd', initrd_path)
52
+ self.vm.launch()
53
+ self.wait_for_console_pattern('Checked W+X mappings: passed')
54
+
55
def test_arm_virt(self):
56
"""
57
:avocado: tags=arch:arm
58
--
101
--
59
2.20.1
102
2.20.1
60
103
61
104
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: "Wen, Jianxian" <Jianxian.Wen@verisilicon.com>
2
2
3
The ADC region size is 256B, split as:
3
Add property memory region which can connect with IOMMU region to support SMMU translate.
4
- [0x00 - 0x4f] defined
5
- [0x50 - 0xff] reserved
6
4
7
All registers are 32-bit (thus when the datasheet mentions the
5
Signed-off-by: Jianxian Wen <jianxian.wen@verisilicon.com>
8
last defined register is 0x4c, it means its address range is
6
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
9
0x4c .. 0x4f.
7
Message-id: 4C23C17B8E87E74E906A25A3254A03F4FA1FEC31@SHASXM03.verisilicon.com
10
11
This model implementation is also 32-bit. Set MemoryRegionOps
12
'impl' fields.
13
14
See:
15
'RM0033 Reference manual Rev 8', Table 10.13.18 "ADC register map".
16
17
Reported-by: Seth Kintigh <skintigh@gmail.com>
18
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
19
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
20
Message-id: 20200603055915.17678-1-f4bug@amsat.org
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
22
---
9
---
23
hw/adc/stm32f2xx_adc.c | 4 +++-
10
hw/arm/exynos4210.c | 3 +++
24
1 file changed, 3 insertions(+), 1 deletion(-)
11
hw/arm/xilinx_zynq.c | 3 +++
12
hw/dma/pl330.c | 26 ++++++++++++++++++++++----
13
3 files changed, 28 insertions(+), 4 deletions(-)
25
14
26
diff --git a/hw/adc/stm32f2xx_adc.c b/hw/adc/stm32f2xx_adc.c
15
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
27
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/adc/stm32f2xx_adc.c
17
--- a/hw/arm/exynos4210.c
29
+++ b/hw/adc/stm32f2xx_adc.c
18
+++ b/hw/arm/exynos4210.c
30
@@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps stm32f2xx_adc_ops = {
19
@@ -XXX,XX +XXX,XX @@ static DeviceState *pl330_create(uint32_t base, qemu_or_irq *orgate,
31
.read = stm32f2xx_adc_read,
20
int i;
32
.write = stm32f2xx_adc_write,
21
33
.endianness = DEVICE_NATIVE_ENDIAN,
22
dev = qdev_new("pl330");
34
+ .impl.min_access_size = 4,
23
+ object_property_set_link(OBJECT(dev), "memory",
35
+ .impl.max_access_size = 4,
24
+ OBJECT(get_system_memory()),
25
+ &error_fatal);
26
qdev_prop_set_uint8(dev, "num_events", nevents);
27
qdev_prop_set_uint8(dev, "num_chnls", 8);
28
qdev_prop_set_uint8(dev, "num_periph_req", nreq);
29
diff --git a/hw/arm/xilinx_zynq.c b/hw/arm/xilinx_zynq.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/xilinx_zynq.c
32
+++ b/hw/arm/xilinx_zynq.c
33
@@ -XXX,XX +XXX,XX @@ static void zynq_init(MachineState *machine)
34
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[39-IRQ_OFFSET]);
35
36
dev = qdev_new("pl330");
37
+ object_property_set_link(OBJECT(dev), "memory",
38
+ OBJECT(address_space_mem),
39
+ &error_fatal);
40
qdev_prop_set_uint8(dev, "num_chnls", 8);
41
qdev_prop_set_uint8(dev, "num_periph_req", 4);
42
qdev_prop_set_uint8(dev, "num_events", 16);
43
diff --git a/hw/dma/pl330.c b/hw/dma/pl330.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/dma/pl330.c
46
+++ b/hw/dma/pl330.c
47
@@ -XXX,XX +XXX,XX @@ struct PL330State {
48
uint8_t num_faulting;
49
uint8_t periph_busy[PL330_PERIPH_NUM];
50
51
+ /* Memory region that DMA operation access */
52
+ MemoryRegion *mem_mr;
53
+ AddressSpace *mem_as;
36
};
54
};
37
55
38
static const VMStateDescription vmstate_stm32f2xx_adc = {
56
#define TYPE_PL330 "pl330"
39
@@ -XXX,XX +XXX,XX @@ static void stm32f2xx_adc_init(Object *obj)
57
@@ -XXX,XX +XXX,XX @@ static inline const PL330InsnDesc *pl330_fetch_insn(PL330Chan *ch)
40
sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
58
uint8_t opcode;
41
59
int i;
42
memory_region_init_io(&s->mmio, obj, &stm32f2xx_adc_ops, s,
60
43
- TYPE_STM32F2XX_ADC, 0xFF);
61
- dma_memory_read(&address_space_memory, ch->pc, &opcode, 1);
44
+ TYPE_STM32F2XX_ADC, 0x100);
62
+ dma_memory_read(ch->parent->mem_as, ch->pc, &opcode, 1);
45
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
63
for (i = 0; insn_desc[i].size; i++) {
64
if ((opcode & insn_desc[i].opmask) == insn_desc[i].opcode) {
65
return &insn_desc[i];
66
@@ -XXX,XX +XXX,XX @@ static inline void pl330_exec_insn(PL330Chan *ch, const PL330InsnDesc *insn)
67
uint8_t buf[PL330_INSN_MAXSIZE];
68
69
assert(insn->size <= PL330_INSN_MAXSIZE);
70
- dma_memory_read(&address_space_memory, ch->pc, buf, insn->size);
71
+ dma_memory_read(ch->parent->mem_as, ch->pc, buf, insn->size);
72
insn->exec(ch, buf[0], &buf[1], insn->size - 1);
46
}
73
}
74
75
@@ -XXX,XX +XXX,XX @@ static int pl330_exec_cycle(PL330Chan *channel)
76
if (q != NULL && q->len <= pl330_fifo_num_free(&s->fifo)) {
77
int len = q->len - (q->addr & (q->len - 1));
78
79
- dma_memory_read(&address_space_memory, q->addr, buf, len);
80
+ dma_memory_read(s->mem_as, q->addr, buf, len);
81
trace_pl330_exec_cycle(q->addr, len);
82
if (trace_event_get_state_backends(TRACE_PL330_HEXDUMP)) {
83
pl330_hexdump(buf, len);
84
@@ -XXX,XX +XXX,XX @@ static int pl330_exec_cycle(PL330Chan *channel)
85
fifo_res = pl330_fifo_get(&s->fifo, buf, len, q->tag);
86
}
87
if (fifo_res == PL330_FIFO_OK || q->z) {
88
- dma_memory_write(&address_space_memory, q->addr, buf, len);
89
+ dma_memory_write(s->mem_as, q->addr, buf, len);
90
trace_pl330_exec_cycle(q->addr, len);
91
if (trace_event_get_state_backends(TRACE_PL330_HEXDUMP)) {
92
pl330_hexdump(buf, len);
93
@@ -XXX,XX +XXX,XX @@ static void pl330_realize(DeviceState *dev, Error **errp)
94
"dma", PL330_IOMEM_SIZE);
95
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
96
97
+ if (!s->mem_mr) {
98
+ error_setg(errp, "'memory' link is not set");
99
+ return;
100
+ } else if (s->mem_mr == get_system_memory()) {
101
+ /* Avoid creating new AS for system memory. */
102
+ s->mem_as = &address_space_memory;
103
+ } else {
104
+ s->mem_as = g_new0(AddressSpace, 1);
105
+ address_space_init(s->mem_as, s->mem_mr,
106
+ memory_region_name(s->mem_mr));
107
+ }
108
+
109
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pl330_exec_cycle_timer, s);
110
111
s->cfg[0] = (s->mgr_ns_at_rst ? 0x4 : 0) |
112
@@ -XXX,XX +XXX,XX @@ static Property pl330_properties[] = {
113
DEFINE_PROP_UINT8("rd_q_dep", PL330State, rd_q_dep, 16),
114
DEFINE_PROP_UINT16("data_buffer_dep", PL330State, data_buffer_dep, 256),
115
116
+ DEFINE_PROP_LINK("memory", PL330State, mem_mr,
117
+ TYPE_MEMORY_REGION, MemoryRegion *),
118
+
119
DEFINE_PROP_END_OF_LIST(),
120
};
47
121
48
--
122
--
49
2.20.1
123
2.20.1
50
124
51
125
diff view generated by jsdifflib
1
From: Philippe Mathieu-Daudé <f4bug@amsat.org>
1
From: Eduardo Habkost <ehabkost@redhat.com>
2
2
3
Replace printf() calls by qemu_log_mask(), which is disabled
3
The SBSA_GWDT enum value conflicts with the SBSA_GWDT() QOM type
4
by default. This avoid flooding the terminal when fuzzing the
4
checking helper, preventing us from using a OBJECT_DEFINE* or
5
device.
5
DEFINE_INSTANCE_CHECKER macro for the SBSA_GWDT() wrapper.
6
6
7
Signed-off-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
7
If I understand the SBSA 6.0 specification correctly, the signal
8
Message-id: 20200525114123.21317-3-f4bug@amsat.org
8
being connected to IRQ 16 is the WS0 output signal from the
9
Generic Watchdog. Rename the enum value to SBSA_GWDT_WS0 to be
10
more explicit and avoid the name conflict.
11
12
Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
13
Message-id: 20210806023119.431680-1-ehabkost@redhat.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
---
16
---
12
hw/arm/pxa2xx.c | 66 ++++++++++++++++++++++++++++++++++++-------------
17
hw/arm/sbsa-ref.c | 6 +++---
13
1 file changed, 49 insertions(+), 17 deletions(-)
18
1 file changed, 3 insertions(+), 3 deletions(-)
14
19
15
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
20
diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c
16
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
17
--- a/hw/arm/pxa2xx.c
22
--- a/hw/arm/sbsa-ref.c
18
+++ b/hw/arm/pxa2xx.c
23
+++ b/hw/arm/sbsa-ref.c
19
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@ enum {
20
#include "sysemu/blockdev.h"
25
SBSA_GIC_DIST,
21
#include "sysemu/qtest.h"
26
SBSA_GIC_REDIST,
22
#include "qemu/cutils.h"
27
SBSA_SECURE_EC,
23
+#include "qemu/log.h"
28
- SBSA_GWDT,
24
29
+ SBSA_GWDT_WS0,
25
static struct {
30
SBSA_GWDT_REFRESH,
26
hwaddr io_base;
31
SBSA_GWDT_CONTROL,
27
@@ -XXX,XX +XXX,XX @@ static uint64_t pxa2xx_pm_read(void *opaque, hwaddr addr,
32
SBSA_SMMU,
28
return s->pm_regs[addr >> 2];
33
@@ -XXX,XX +XXX,XX @@ static const int sbsa_ref_irqmap[] = {
29
default:
34
[SBSA_AHCI] = 10,
30
fail:
35
[SBSA_EHCI] = 11,
31
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
36
[SBSA_SMMU] = 12, /* ... to 15 */
32
+ qemu_log_mask(LOG_GUEST_ERROR,
37
- [SBSA_GWDT] = 16,
33
+ "%s: Bad read offset 0x%"HWADDR_PRIx"\n",
38
+ [SBSA_GWDT_WS0] = 16,
34
+ __func__, addr);
39
};
35
break;
40
36
}
41
static const char * const valid_cpus[] = {
37
return 0;
42
@@ -XXX,XX +XXX,XX @@ static void create_wdt(const SBSAMachineState *sms)
38
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_pm_write(void *opaque, hwaddr addr,
43
hwaddr cbase = sbsa_ref_memmap[SBSA_GWDT_CONTROL].base;
39
s->pm_regs[addr >> 2] = value;
44
DeviceState *dev = qdev_new(TYPE_WDT_SBSA);
40
break;
45
SysBusDevice *s = SYS_BUS_DEVICE(dev);
41
}
46
- int irq = sbsa_ref_irqmap[SBSA_GWDT];
42
-
47
+ int irq = sbsa_ref_irqmap[SBSA_GWDT_WS0];
43
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
48
44
+ qemu_log_mask(LOG_GUEST_ERROR,
49
sysbus_realize_and_unref(s, &error_fatal);
45
+ "%s: Bad write offset 0x%"HWADDR_PRIx"\n",
50
sysbus_mmio_map(s, 0, rbase);
46
+ __func__, addr);
47
break;
48
}
49
}
50
@@ -XXX,XX +XXX,XX @@ static uint64_t pxa2xx_cm_read(void *opaque, hwaddr addr,
51
return s->cm_regs[CCCR >> 2] | (3 << 28);
52
53
default:
54
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
55
+ qemu_log_mask(LOG_GUEST_ERROR,
56
+ "%s: Bad read offset 0x%"HWADDR_PRIx"\n",
57
+ __func__, addr);
58
break;
59
}
60
return 0;
61
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_cm_write(void *opaque, hwaddr addr,
62
break;
63
64
default:
65
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
66
+ qemu_log_mask(LOG_GUEST_ERROR,
67
+ "%s: Bad write offset 0x%"HWADDR_PRIx"\n",
68
+ __func__, addr);
69
break;
70
}
71
}
72
@@ -XXX,XX +XXX,XX @@ static uint64_t pxa2xx_mm_read(void *opaque, hwaddr addr,
73
return s->mm_regs[addr >> 2];
74
/* fall through */
75
default:
76
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
77
+ qemu_log_mask(LOG_GUEST_ERROR,
78
+ "%s: Bad read offset 0x%"HWADDR_PRIx"\n",
79
+ __func__, addr);
80
break;
81
}
82
return 0;
83
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_mm_write(void *opaque, hwaddr addr,
84
}
85
86
default:
87
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
88
+ qemu_log_mask(LOG_GUEST_ERROR,
89
+ "%s: Bad write offset 0x%"HWADDR_PRIx"\n",
90
+ __func__, addr);
91
break;
92
}
93
}
94
@@ -XXX,XX +XXX,XX @@ static uint64_t pxa2xx_ssp_read(void *opaque, hwaddr addr,
95
case SSACD:
96
return s->ssacd;
97
default:
98
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
99
+ qemu_log_mask(LOG_GUEST_ERROR,
100
+ "%s: Bad read offset 0x%"HWADDR_PRIx"\n",
101
+ __func__, addr);
102
break;
103
}
104
return 0;
105
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_ssp_write(void *opaque, hwaddr addr,
106
break;
107
108
default:
109
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
110
+ qemu_log_mask(LOG_GUEST_ERROR,
111
+ "%s: Bad write offset 0x%"HWADDR_PRIx"\n",
112
+ __func__, addr);
113
break;
114
}
115
}
116
@@ -XXX,XX +XXX,XX @@ static uint64_t pxa2xx_rtc_read(void *opaque, hwaddr addr,
117
else
118
return s->last_swcr;
119
default:
120
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
121
+ qemu_log_mask(LOG_GUEST_ERROR,
122
+ "%s: Bad read offset 0x%"HWADDR_PRIx"\n",
123
+ __func__, addr);
124
break;
125
}
126
return 0;
127
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_rtc_write(void *opaque, hwaddr addr,
128
break;
129
130
default:
131
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
132
+ qemu_log_mask(LOG_GUEST_ERROR,
133
+ "%s: Bad write offset 0x%"HWADDR_PRIx"\n",
134
+ __func__, addr);
135
}
136
}
137
138
@@ -XXX,XX +XXX,XX @@ static uint64_t pxa2xx_i2c_read(void *opaque, hwaddr addr,
139
s->ibmr = 0;
140
return s->ibmr;
141
default:
142
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
143
+ qemu_log_mask(LOG_GUEST_ERROR,
144
+ "%s: Bad read offset 0x%"HWADDR_PRIx"\n",
145
+ __func__, addr);
146
break;
147
}
148
return 0;
149
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_i2c_write(void *opaque, hwaddr addr,
150
break;
151
152
default:
153
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
154
+ qemu_log_mask(LOG_GUEST_ERROR,
155
+ "%s: Bad write offset 0x%"HWADDR_PRIx"\n",
156
+ __func__, addr);
157
}
158
}
159
160
@@ -XXX,XX +XXX,XX @@ static uint64_t pxa2xx_i2s_read(void *opaque, hwaddr addr,
161
}
162
return 0;
163
default:
164
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
165
+ qemu_log_mask(LOG_GUEST_ERROR,
166
+ "%s: Bad read offset 0x%"HWADDR_PRIx"\n",
167
+ __func__, addr);
168
break;
169
}
170
return 0;
171
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_i2s_write(void *opaque, hwaddr addr,
172
}
173
break;
174
default:
175
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
176
+ qemu_log_mask(LOG_GUEST_ERROR,
177
+ "%s: Bad write offset 0x%"HWADDR_PRIx"\n",
178
+ __func__, addr);
179
}
180
}
181
182
@@ -XXX,XX +XXX,XX @@ static uint64_t pxa2xx_fir_read(void *opaque, hwaddr addr,
183
case ICFOR:
184
return s->rx_len;
185
default:
186
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
187
+ qemu_log_mask(LOG_GUEST_ERROR,
188
+ "%s: Bad read offset 0x%"HWADDR_PRIx"\n",
189
+ __func__, addr);
190
break;
191
}
192
return 0;
193
@@ -XXX,XX +XXX,XX @@ static void pxa2xx_fir_write(void *opaque, hwaddr addr,
194
case ICFOR:
195
break;
196
default:
197
- printf("%s: Bad register " REG_FMT "\n", __func__, addr);
198
+ qemu_log_mask(LOG_GUEST_ERROR,
199
+ "%s: Bad write offset 0x%"HWADDR_PRIx"\n",
200
+ __func__, addr);
201
}
202
}
203
204
--
51
--
205
2.20.1
52
2.20.1
206
53
207
54
diff view generated by jsdifflib
1
From: Paul Zimmerman <pauldzim@gmail.com>
1
From: Guenter Roeck <linux@roeck-us.net>
2
2
3
Import the dwc-hsotg (dwc2) register definitions file from the
3
Instantiate SAI1/2/3 as unimplemented devices to avoid Linux kernel crashes
4
Linux kernel. This is a copy of drivers/usb/dwc2/hw.h from the
4
such as the following.
5
mainline Linux kernel, the only changes being to the header, and
6
two instances of 'u32' changed to 'uint32_t' to allow it to
7
compile. Checkpatch throws a boatload of errors due to the tab
8
indentation, but I would rather import it as-is than reformat it.
9
5
10
Signed-off-by: Paul Zimmerman <pauldzim@gmail.com>
6
Unhandled fault: external abort on non-linefetch (0x808) at 0xd19b0000
11
Message-id: 20200520235349.21215-3-pauldzim@gmail.com
7
pgd = (ptrval)
8
[d19b0000] *pgd=82711811, *pte=308a0653, *ppte=308a0453
9
Internal error: : 808 [#1] SMP ARM
10
Modules linked in:
11
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.14.0-rc5 #1
12
...
13
[<c095e974>] (regmap_mmio_write32le) from [<c095eb48>] (regmap_mmio_write+0x3c/0x54)
14
[<c095eb48>] (regmap_mmio_write) from [<c09580f4>] (_regmap_write+0x4c/0x1f0)
15
[<c09580f4>] (_regmap_write) from [<c0959b28>] (regmap_write+0x3c/0x60)
16
[<c0959b28>] (regmap_write) from [<c0d41130>] (fsl_sai_runtime_resume+0x9c/0x1ec)
17
[<c0d41130>] (fsl_sai_runtime_resume) from [<c0942464>] (__rpm_callback+0x3c/0x108)
18
[<c0942464>] (__rpm_callback) from [<c0942590>] (rpm_callback+0x60/0x64)
19
[<c0942590>] (rpm_callback) from [<c0942b60>] (rpm_resume+0x5cc/0x808)
20
[<c0942b60>] (rpm_resume) from [<c0942dfc>] (__pm_runtime_resume+0x60/0xa0)
21
[<c0942dfc>] (__pm_runtime_resume) from [<c0d4231c>] (fsl_sai_probe+0x2b8/0x65c)
22
[<c0d4231c>] (fsl_sai_probe) from [<c0935b08>] (platform_probe+0x58/0xb8)
23
[<c0935b08>] (platform_probe) from [<c0933264>] (really_probe.part.0+0x9c/0x334)
24
[<c0933264>] (really_probe.part.0) from [<c093359c>] (__driver_probe_device+0xa0/0x138)
25
[<c093359c>] (__driver_probe_device) from [<c0933664>] (driver_probe_device+0x30/0xc8)
26
[<c0933664>] (driver_probe_device) from [<c0933c88>] (__driver_attach+0x90/0x130)
27
[<c0933c88>] (__driver_attach) from [<c0931060>] (bus_for_each_dev+0x78/0xb8)
28
[<c0931060>] (bus_for_each_dev) from [<c093254c>] (bus_add_driver+0xf0/0x1d8)
29
[<c093254c>] (bus_add_driver) from [<c0934a30>] (driver_register+0x88/0x118)
30
[<c0934a30>] (driver_register) from [<c01022c0>] (do_one_initcall+0x7c/0x3a4)
31
[<c01022c0>] (do_one_initcall) from [<c1601204>] (kernel_init_freeable+0x198/0x22c)
32
[<c1601204>] (kernel_init_freeable) from [<c0f5ff2c>] (kernel_init+0x10/0x128)
33
[<c0f5ff2c>] (kernel_init) from [<c010013c>] (ret_from_fork+0x14/0x38)
34
35
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
36
Message-id: 20210810175607.538090-1-linux@roeck-us.net
12
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
37
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
38
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
---
39
---
15
include/hw/usb/dwc2-regs.h | 899 +++++++++++++++++++++++++++++++++++++
40
include/hw/arm/fsl-imx7.h | 5 +++++
16
1 file changed, 899 insertions(+)
41
hw/arm/fsl-imx7.c | 7 +++++++
17
create mode 100644 include/hw/usb/dwc2-regs.h
42
2 files changed, 12 insertions(+)
18
43
19
diff --git a/include/hw/usb/dwc2-regs.h b/include/hw/usb/dwc2-regs.h
44
diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h
20
new file mode 100644
45
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX
46
--- a/include/hw/arm/fsl-imx7.h
22
--- /dev/null
47
+++ b/include/hw/arm/fsl-imx7.h
23
+++ b/include/hw/usb/dwc2-regs.h
48
@@ -XXX,XX +XXX,XX @@ enum FslIMX7MemoryMap {
24
@@ -XXX,XX +XXX,XX @@
49
FSL_IMX7_UART6_ADDR = 0x30A80000,
25
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
50
FSL_IMX7_UART7_ADDR = 0x30A90000,
26
+/*
51
27
+ * Imported from the Linux kernel file drivers/usb/dwc2/hw.h, commit
52
+ FSL_IMX7_SAI1_ADDR = 0x308A0000,
28
+ * a89bae709b3492b478480a2c9734e7e9393b279c ("usb: dwc2: Move
53
+ FSL_IMX7_SAI2_ADDR = 0x308B0000,
29
+ * UTMI_PHY_DATA defines closer")
54
+ FSL_IMX7_SAI3_ADDR = 0x308C0000,
30
+ *
55
+ FSL_IMX7_SAIn_SIZE = 0x10000,
31
+ * hw.h - DesignWare HS OTG Controller hardware definitions
32
+ *
33
+ * Copyright 2004-2013 Synopsys, Inc.
34
+ *
35
+ * Redistribution and use in source and binary forms, with or without
36
+ * modification, are permitted provided that the following conditions
37
+ * are met:
38
+ * 1. Redistributions of source code must retain the above copyright
39
+ * notice, this list of conditions, and the following disclaimer,
40
+ * without modification.
41
+ * 2. Redistributions in binary form must reproduce the above copyright
42
+ * notice, this list of conditions and the following disclaimer in the
43
+ * documentation and/or other materials provided with the distribution.
44
+ * 3. The names of the above-listed copyright holders may not be used
45
+ * to endorse or promote products derived from this software without
46
+ * specific prior written permission.
47
+ *
48
+ * ALTERNATIVELY, this software may be distributed under the terms of the
49
+ * GNU General Public License ("GPL") as published by the Free Software
50
+ * Foundation; either version 2 of the License, or (at your option) any
51
+ * later version.
52
+ *
53
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
54
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
55
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
57
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
58
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
59
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
60
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
61
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
62
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
63
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64
+ */
65
+
56
+
66
+#ifndef __DWC2_HW_H__
57
FSL_IMX7_ENET1_ADDR = 0x30BE0000,
67
+#define __DWC2_HW_H__
58
FSL_IMX7_ENET2_ADDR = 0x30BF0000,
59
60
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
61
index XXXXXXX..XXXXXXX 100644
62
--- a/hw/arm/fsl-imx7.c
63
+++ b/hw/arm/fsl-imx7.c
64
@@ -XXX,XX +XXX,XX @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
65
create_unimplemented_device("can1", FSL_IMX7_CAN1_ADDR, FSL_IMX7_CANn_SIZE);
66
create_unimplemented_device("can2", FSL_IMX7_CAN2_ADDR, FSL_IMX7_CANn_SIZE);
67
68
+ /*
69
+ * SAI (Audio SSI (Synchronous Serial Interface))
70
+ */
71
+ create_unimplemented_device("sai1", FSL_IMX7_SAI1_ADDR, FSL_IMX7_SAIn_SIZE);
72
+ create_unimplemented_device("sai2", FSL_IMX7_SAI2_ADDR, FSL_IMX7_SAIn_SIZE);
73
+ create_unimplemented_device("sai2", FSL_IMX7_SAI3_ADDR, FSL_IMX7_SAIn_SIZE);
68
+
74
+
69
+#define HSOTG_REG(x)    (x)
75
/*
70
+
76
* OCOTP
71
+#define GOTGCTL                HSOTG_REG(0x000)
77
*/
72
+#define GOTGCTL_CHIRPEN            BIT(27)
73
+#define GOTGCTL_MULT_VALID_BC_MASK    (0x1f << 22)
74
+#define GOTGCTL_MULT_VALID_BC_SHIFT    22
75
+#define GOTGCTL_OTGVER            BIT(20)
76
+#define GOTGCTL_BSESVLD            BIT(19)
77
+#define GOTGCTL_ASESVLD            BIT(18)
78
+#define GOTGCTL_DBNC_SHORT        BIT(17)
79
+#define GOTGCTL_CONID_B            BIT(16)
80
+#define GOTGCTL_DBNCE_FLTR_BYPASS    BIT(15)
81
+#define GOTGCTL_DEVHNPEN        BIT(11)
82
+#define GOTGCTL_HSTSETHNPEN        BIT(10)
83
+#define GOTGCTL_HNPREQ            BIT(9)
84
+#define GOTGCTL_HSTNEGSCS        BIT(8)
85
+#define GOTGCTL_SESREQ            BIT(1)
86
+#define GOTGCTL_SESREQSCS        BIT(0)
87
+
88
+#define GOTGINT                HSOTG_REG(0x004)
89
+#define GOTGINT_DBNCE_DONE        BIT(19)
90
+#define GOTGINT_A_DEV_TOUT_CHG        BIT(18)
91
+#define GOTGINT_HST_NEG_DET        BIT(17)
92
+#define GOTGINT_HST_NEG_SUC_STS_CHNG    BIT(9)
93
+#define GOTGINT_SES_REQ_SUC_STS_CHNG    BIT(8)
94
+#define GOTGINT_SES_END_DET        BIT(2)
95
+
96
+#define GAHBCFG                HSOTG_REG(0x008)
97
+#define GAHBCFG_AHB_SINGLE        BIT(23)
98
+#define GAHBCFG_NOTI_ALL_DMA_WRIT    BIT(22)
99
+#define GAHBCFG_REM_MEM_SUPP        BIT(21)
100
+#define GAHBCFG_P_TXF_EMP_LVL        BIT(8)
101
+#define GAHBCFG_NP_TXF_EMP_LVL        BIT(7)
102
+#define GAHBCFG_DMA_EN            BIT(5)
103
+#define GAHBCFG_HBSTLEN_MASK        (0xf << 1)
104
+#define GAHBCFG_HBSTLEN_SHIFT        1
105
+#define GAHBCFG_HBSTLEN_SINGLE        0
106
+#define GAHBCFG_HBSTLEN_INCR        1
107
+#define GAHBCFG_HBSTLEN_INCR4        3
108
+#define GAHBCFG_HBSTLEN_INCR8        5
109
+#define GAHBCFG_HBSTLEN_INCR16        7
110
+#define GAHBCFG_GLBL_INTR_EN        BIT(0)
111
+#define GAHBCFG_CTRL_MASK        (GAHBCFG_P_TXF_EMP_LVL | \
112
+                     GAHBCFG_NP_TXF_EMP_LVL | \
113
+                     GAHBCFG_DMA_EN | \
114
+                     GAHBCFG_GLBL_INTR_EN)
115
+
116
+#define GUSBCFG                HSOTG_REG(0x00C)
117
+#define GUSBCFG_FORCEDEVMODE        BIT(30)
118
+#define GUSBCFG_FORCEHOSTMODE        BIT(29)
119
+#define GUSBCFG_TXENDDELAY        BIT(28)
120
+#define GUSBCFG_ICTRAFFICPULLREMOVE    BIT(27)
121
+#define GUSBCFG_ICUSBCAP        BIT(26)
122
+#define GUSBCFG_ULPI_INT_PROT_DIS    BIT(25)
123
+#define GUSBCFG_INDICATORPASSTHROUGH    BIT(24)
124
+#define GUSBCFG_INDICATORCOMPLEMENT    BIT(23)
125
+#define GUSBCFG_TERMSELDLPULSE        BIT(22)
126
+#define GUSBCFG_ULPI_INT_VBUS_IND    BIT(21)
127
+#define GUSBCFG_ULPI_EXT_VBUS_DRV    BIT(20)
128
+#define GUSBCFG_ULPI_CLK_SUSP_M        BIT(19)
129
+#define GUSBCFG_ULPI_AUTO_RES        BIT(18)
130
+#define GUSBCFG_ULPI_FS_LS        BIT(17)
131
+#define GUSBCFG_OTG_UTMI_FS_SEL        BIT(16)
132
+#define GUSBCFG_PHY_LP_CLK_SEL        BIT(15)
133
+#define GUSBCFG_USBTRDTIM_MASK        (0xf << 10)
134
+#define GUSBCFG_USBTRDTIM_SHIFT        10
135
+#define GUSBCFG_HNPCAP            BIT(9)
136
+#define GUSBCFG_SRPCAP            BIT(8)
137
+#define GUSBCFG_DDRSEL            BIT(7)
138
+#define GUSBCFG_PHYSEL            BIT(6)
139
+#define GUSBCFG_FSINTF            BIT(5)
140
+#define GUSBCFG_ULPI_UTMI_SEL        BIT(4)
141
+#define GUSBCFG_PHYIF16            BIT(3)
142
+#define GUSBCFG_PHYIF8            (0 << 3)
143
+#define GUSBCFG_TOUTCAL_MASK        (0x7 << 0)
144
+#define GUSBCFG_TOUTCAL_SHIFT        0
145
+#define GUSBCFG_TOUTCAL_LIMIT        0x7
146
+#define GUSBCFG_TOUTCAL(_x)        ((_x) << 0)
147
+
148
+#define GRSTCTL                HSOTG_REG(0x010)
149
+#define GRSTCTL_AHBIDLE            BIT(31)
150
+#define GRSTCTL_DMAREQ            BIT(30)
151
+#define GRSTCTL_TXFNUM_MASK        (0x1f << 6)
152
+#define GRSTCTL_TXFNUM_SHIFT        6
153
+#define GRSTCTL_TXFNUM_LIMIT        0x1f
154
+#define GRSTCTL_TXFNUM(_x)        ((_x) << 6)
155
+#define GRSTCTL_TXFFLSH            BIT(5)
156
+#define GRSTCTL_RXFFLSH            BIT(4)
157
+#define GRSTCTL_IN_TKNQ_FLSH        BIT(3)
158
+#define GRSTCTL_FRMCNTRRST        BIT(2)
159
+#define GRSTCTL_HSFTRST            BIT(1)
160
+#define GRSTCTL_CSFTRST            BIT(0)
161
+
162
+#define GINTSTS                HSOTG_REG(0x014)
163
+#define GINTMSK                HSOTG_REG(0x018)
164
+#define GINTSTS_WKUPINT            BIT(31)
165
+#define GINTSTS_SESSREQINT        BIT(30)
166
+#define GINTSTS_DISCONNINT        BIT(29)
167
+#define GINTSTS_CONIDSTSCHNG        BIT(28)
168
+#define GINTSTS_LPMTRANRCVD        BIT(27)
169
+#define GINTSTS_PTXFEMP            BIT(26)
170
+#define GINTSTS_HCHINT            BIT(25)
171
+#define GINTSTS_PRTINT            BIT(24)
172
+#define GINTSTS_RESETDET        BIT(23)
173
+#define GINTSTS_FET_SUSP        BIT(22)
174
+#define GINTSTS_INCOMPL_IP        BIT(21)
175
+#define GINTSTS_INCOMPL_SOOUT        BIT(21)
176
+#define GINTSTS_INCOMPL_SOIN        BIT(20)
177
+#define GINTSTS_OEPINT            BIT(19)
178
+#define GINTSTS_IEPINT            BIT(18)
179
+#define GINTSTS_EPMIS            BIT(17)
180
+#define GINTSTS_RESTOREDONE        BIT(16)
181
+#define GINTSTS_EOPF            BIT(15)
182
+#define GINTSTS_ISOUTDROP        BIT(14)
183
+#define GINTSTS_ENUMDONE        BIT(13)
184
+#define GINTSTS_USBRST            BIT(12)
185
+#define GINTSTS_USBSUSP            BIT(11)
186
+#define GINTSTS_ERLYSUSP        BIT(10)
187
+#define GINTSTS_I2CINT            BIT(9)
188
+#define GINTSTS_ULPI_CK_INT        BIT(8)
189
+#define GINTSTS_GOUTNAKEFF        BIT(7)
190
+#define GINTSTS_GINNAKEFF        BIT(6)
191
+#define GINTSTS_NPTXFEMP        BIT(5)
192
+#define GINTSTS_RXFLVL            BIT(4)
193
+#define GINTSTS_SOF            BIT(3)
194
+#define GINTSTS_OTGINT            BIT(2)
195
+#define GINTSTS_MODEMIS            BIT(1)
196
+#define GINTSTS_CURMODE_HOST        BIT(0)
197
+
198
+#define GRXSTSR                HSOTG_REG(0x01C)
199
+#define GRXSTSP                HSOTG_REG(0x020)
200
+#define GRXSTS_FN_MASK            (0x7f << 25)
201
+#define GRXSTS_FN_SHIFT            25
202
+#define GRXSTS_PKTSTS_MASK        (0xf << 17)
203
+#define GRXSTS_PKTSTS_SHIFT        17
204
+#define GRXSTS_PKTSTS_GLOBALOUTNAK    1
205
+#define GRXSTS_PKTSTS_OUTRX        2
206
+#define GRXSTS_PKTSTS_HCHIN        2
207
+#define GRXSTS_PKTSTS_OUTDONE        3
208
+#define GRXSTS_PKTSTS_HCHIN_XFER_COMP    3
209
+#define GRXSTS_PKTSTS_SETUPDONE        4
210
+#define GRXSTS_PKTSTS_DATATOGGLEERR    5
211
+#define GRXSTS_PKTSTS_SETUPRX        6
212
+#define GRXSTS_PKTSTS_HCHHALTED        7
213
+#define GRXSTS_HCHNUM_MASK        (0xf << 0)
214
+#define GRXSTS_HCHNUM_SHIFT        0
215
+#define GRXSTS_DPID_MASK        (0x3 << 15)
216
+#define GRXSTS_DPID_SHIFT        15
217
+#define GRXSTS_BYTECNT_MASK        (0x7ff << 4)
218
+#define GRXSTS_BYTECNT_SHIFT        4
219
+#define GRXSTS_EPNUM_MASK        (0xf << 0)
220
+#define GRXSTS_EPNUM_SHIFT        0
221
+
222
+#define GRXFSIZ                HSOTG_REG(0x024)
223
+#define GRXFSIZ_DEPTH_MASK        (0xffff << 0)
224
+#define GRXFSIZ_DEPTH_SHIFT        0
225
+
226
+#define GNPTXFSIZ            HSOTG_REG(0x028)
227
+/* Use FIFOSIZE_* constants to access this register */
228
+
229
+#define GNPTXSTS            HSOTG_REG(0x02C)
230
+#define GNPTXSTS_NP_TXQ_TOP_MASK        (0x7f << 24)
231
+#define GNPTXSTS_NP_TXQ_TOP_SHIFT        24
232
+#define GNPTXSTS_NP_TXQ_SPC_AVAIL_MASK        (0xff << 16)
233
+#define GNPTXSTS_NP_TXQ_SPC_AVAIL_SHIFT        16
234
+#define GNPTXSTS_NP_TXQ_SPC_AVAIL_GET(_v)    (((_v) >> 16) & 0xff)
235
+#define GNPTXSTS_NP_TXF_SPC_AVAIL_MASK        (0xffff << 0)
236
+#define GNPTXSTS_NP_TXF_SPC_AVAIL_SHIFT        0
237
+#define GNPTXSTS_NP_TXF_SPC_AVAIL_GET(_v)    (((_v) >> 0) & 0xffff)
238
+
239
+#define GI2CCTL                HSOTG_REG(0x0030)
240
+#define GI2CCTL_BSYDNE            BIT(31)
241
+#define GI2CCTL_RW            BIT(30)
242
+#define GI2CCTL_I2CDATSE0        BIT(28)
243
+#define GI2CCTL_I2CDEVADDR_MASK        (0x3 << 26)
244
+#define GI2CCTL_I2CDEVADDR_SHIFT    26
245
+#define GI2CCTL_I2CSUSPCTL        BIT(25)
246
+#define GI2CCTL_ACK            BIT(24)
247
+#define GI2CCTL_I2CEN            BIT(23)
248
+#define GI2CCTL_ADDR_MASK        (0x7f << 16)
249
+#define GI2CCTL_ADDR_SHIFT        16
250
+#define GI2CCTL_REGADDR_MASK        (0xff << 8)
251
+#define GI2CCTL_REGADDR_SHIFT        8
252
+#define GI2CCTL_RWDATA_MASK        (0xff << 0)
253
+#define GI2CCTL_RWDATA_SHIFT        0
254
+
255
+#define GPVNDCTL            HSOTG_REG(0x0034)
256
+#define GGPIO                HSOTG_REG(0x0038)
257
+#define GGPIO_STM32_OTG_GCCFG_PWRDWN    BIT(16)
258
+
259
+#define GUID                HSOTG_REG(0x003c)
260
+#define GSNPSID                HSOTG_REG(0x0040)
261
+#define GHWCFG1                HSOTG_REG(0x0044)
262
+#define GSNPSID_ID_MASK            GENMASK(31, 16)
263
+
264
+#define GHWCFG2                HSOTG_REG(0x0048)
265
+#define GHWCFG2_OTG_ENABLE_IC_USB        BIT(31)
266
+#define GHWCFG2_DEV_TOKEN_Q_DEPTH_MASK        (0x1f << 26)
267
+#define GHWCFG2_DEV_TOKEN_Q_DEPTH_SHIFT        26
268
+#define GHWCFG2_HOST_PERIO_TX_Q_DEPTH_MASK    (0x3 << 24)
269
+#define GHWCFG2_HOST_PERIO_TX_Q_DEPTH_SHIFT    24
270
+#define GHWCFG2_NONPERIO_TX_Q_DEPTH_MASK    (0x3 << 22)
271
+#define GHWCFG2_NONPERIO_TX_Q_DEPTH_SHIFT    22
272
+#define GHWCFG2_MULTI_PROC_INT            BIT(20)
273
+#define GHWCFG2_DYNAMIC_FIFO            BIT(19)
274
+#define GHWCFG2_PERIO_EP_SUPPORTED        BIT(18)
275
+#define GHWCFG2_NUM_HOST_CHAN_MASK        (0xf << 14)
276
+#define GHWCFG2_NUM_HOST_CHAN_SHIFT        14
277
+#define GHWCFG2_NUM_DEV_EP_MASK            (0xf << 10)
278
+#define GHWCFG2_NUM_DEV_EP_SHIFT        10
279
+#define GHWCFG2_FS_PHY_TYPE_MASK        (0x3 << 8)
280
+#define GHWCFG2_FS_PHY_TYPE_SHIFT        8
281
+#define GHWCFG2_FS_PHY_TYPE_NOT_SUPPORTED    0
282
+#define GHWCFG2_FS_PHY_TYPE_DEDICATED        1
283
+#define GHWCFG2_FS_PHY_TYPE_SHARED_UTMI        2
284
+#define GHWCFG2_FS_PHY_TYPE_SHARED_ULPI        3
285
+#define GHWCFG2_HS_PHY_TYPE_MASK        (0x3 << 6)
286
+#define GHWCFG2_HS_PHY_TYPE_SHIFT        6
287
+#define GHWCFG2_HS_PHY_TYPE_NOT_SUPPORTED    0
288
+#define GHWCFG2_HS_PHY_TYPE_UTMI        1
289
+#define GHWCFG2_HS_PHY_TYPE_ULPI        2
290
+#define GHWCFG2_HS_PHY_TYPE_UTMI_ULPI        3
291
+#define GHWCFG2_POINT2POINT            BIT(5)
292
+#define GHWCFG2_ARCHITECTURE_MASK        (0x3 << 3)
293
+#define GHWCFG2_ARCHITECTURE_SHIFT        3
294
+#define GHWCFG2_SLAVE_ONLY_ARCH            0
295
+#define GHWCFG2_EXT_DMA_ARCH            1
296
+#define GHWCFG2_INT_DMA_ARCH            2
297
+#define GHWCFG2_OP_MODE_MASK            (0x7 << 0)
298
+#define GHWCFG2_OP_MODE_SHIFT            0
299
+#define GHWCFG2_OP_MODE_HNP_SRP_CAPABLE        0
300
+#define GHWCFG2_OP_MODE_SRP_ONLY_CAPABLE    1
301
+#define GHWCFG2_OP_MODE_NO_HNP_SRP_CAPABLE    2
302
+#define GHWCFG2_OP_MODE_SRP_CAPABLE_DEVICE    3
303
+#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_DEVICE    4
304
+#define GHWCFG2_OP_MODE_SRP_CAPABLE_HOST    5
305
+#define GHWCFG2_OP_MODE_NO_SRP_CAPABLE_HOST    6
306
+#define GHWCFG2_OP_MODE_UNDEFINED        7
307
+
308
+#define GHWCFG3                HSOTG_REG(0x004c)
309
+#define GHWCFG3_DFIFO_DEPTH_MASK        (0xffff << 16)
310
+#define GHWCFG3_DFIFO_DEPTH_SHIFT        16
311
+#define GHWCFG3_OTG_LPM_EN            BIT(15)
312
+#define GHWCFG3_BC_SUPPORT            BIT(14)
313
+#define GHWCFG3_OTG_ENABLE_HSIC            BIT(13)
314
+#define GHWCFG3_ADP_SUPP            BIT(12)
315
+#define GHWCFG3_SYNCH_RESET_TYPE        BIT(11)
316
+#define GHWCFG3_OPTIONAL_FEATURES        BIT(10)
317
+#define GHWCFG3_VENDOR_CTRL_IF            BIT(9)
318
+#define GHWCFG3_I2C                BIT(8)
319
+#define GHWCFG3_OTG_FUNC            BIT(7)
320
+#define GHWCFG3_PACKET_SIZE_CNTR_WIDTH_MASK    (0x7 << 4)
321
+#define GHWCFG3_PACKET_SIZE_CNTR_WIDTH_SHIFT    4
322
+#define GHWCFG3_XFER_SIZE_CNTR_WIDTH_MASK    (0xf << 0)
323
+#define GHWCFG3_XFER_SIZE_CNTR_WIDTH_SHIFT    0
324
+
325
+#define GHWCFG4                HSOTG_REG(0x0050)
326
+#define GHWCFG4_DESC_DMA_DYN            BIT(31)
327
+#define GHWCFG4_DESC_DMA            BIT(30)
328
+#define GHWCFG4_NUM_IN_EPS_MASK            (0xf << 26)
329
+#define GHWCFG4_NUM_IN_EPS_SHIFT        26
330
+#define GHWCFG4_DED_FIFO_EN            BIT(25)
331
+#define GHWCFG4_DED_FIFO_SHIFT        25
332
+#define GHWCFG4_SESSION_END_FILT_EN        BIT(24)
333
+#define GHWCFG4_B_VALID_FILT_EN            BIT(23)
334
+#define GHWCFG4_A_VALID_FILT_EN            BIT(22)
335
+#define GHWCFG4_VBUS_VALID_FILT_EN        BIT(21)
336
+#define GHWCFG4_IDDIG_FILT_EN            BIT(20)
337
+#define GHWCFG4_NUM_DEV_MODE_CTRL_EP_MASK    (0xf << 16)
338
+#define GHWCFG4_NUM_DEV_MODE_CTRL_EP_SHIFT    16
339
+#define GHWCFG4_UTMI_PHY_DATA_WIDTH_MASK    (0x3 << 14)
340
+#define GHWCFG4_UTMI_PHY_DATA_WIDTH_SHIFT    14
341
+#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8        0
342
+#define GHWCFG4_UTMI_PHY_DATA_WIDTH_16        1
343
+#define GHWCFG4_UTMI_PHY_DATA_WIDTH_8_OR_16    2
344
+#define GHWCFG4_ACG_SUPPORTED            BIT(12)
345
+#define GHWCFG4_IPG_ISOC_SUPPORTED        BIT(11)
346
+#define GHWCFG4_SERVICE_INTERVAL_SUPPORTED BIT(10)
347
+#define GHWCFG4_XHIBER                BIT(7)
348
+#define GHWCFG4_HIBER                BIT(6)
349
+#define GHWCFG4_MIN_AHB_FREQ            BIT(5)
350
+#define GHWCFG4_POWER_OPTIMIZ            BIT(4)
351
+#define GHWCFG4_NUM_DEV_PERIO_IN_EP_MASK    (0xf << 0)
352
+#define GHWCFG4_NUM_DEV_PERIO_IN_EP_SHIFT    0
353
+
354
+#define GLPMCFG                HSOTG_REG(0x0054)
355
+#define GLPMCFG_INVSELHSIC        BIT(31)
356
+#define GLPMCFG_HSICCON            BIT(30)
357
+#define GLPMCFG_RSTRSLPSTS        BIT(29)
358
+#define GLPMCFG_ENBESL            BIT(28)
359
+#define GLPMCFG_LPM_RETRYCNT_STS_MASK    (0x7 << 25)
360
+#define GLPMCFG_LPM_RETRYCNT_STS_SHIFT    25
361
+#define GLPMCFG_SNDLPM            BIT(24)
362
+#define GLPMCFG_RETRY_CNT_MASK        (0x7 << 21)
363
+#define GLPMCFG_RETRY_CNT_SHIFT        21
364
+#define GLPMCFG_LPM_REJECT_CTRL_CONTROL    BIT(21)
365
+#define GLPMCFG_LPM_ACCEPT_CTRL_ISOC    BIT(22)
366
+#define GLPMCFG_LPM_CHNL_INDX_MASK    (0xf << 17)
367
+#define GLPMCFG_LPM_CHNL_INDX_SHIFT    17
368
+#define GLPMCFG_L1RESUMEOK        BIT(16)
369
+#define GLPMCFG_SLPSTS            BIT(15)
370
+#define GLPMCFG_COREL1RES_MASK        (0x3 << 13)
371
+#define GLPMCFG_COREL1RES_SHIFT        13
372
+#define GLPMCFG_HIRD_THRES_MASK        (0x1f << 8)
373
+#define GLPMCFG_HIRD_THRES_SHIFT    8
374
+#define GLPMCFG_HIRD_THRES_EN        (0x10 << 8)
375
+#define GLPMCFG_ENBLSLPM        BIT(7)
376
+#define GLPMCFG_BREMOTEWAKE        BIT(6)
377
+#define GLPMCFG_HIRD_MASK        (0xf << 2)
378
+#define GLPMCFG_HIRD_SHIFT        2
379
+#define GLPMCFG_APPL1RES        BIT(1)
380
+#define GLPMCFG_LPMCAP            BIT(0)
381
+
382
+#define GPWRDN                HSOTG_REG(0x0058)
383
+#define GPWRDN_MULT_VAL_ID_BC_MASK    (0x1f << 24)
384
+#define GPWRDN_MULT_VAL_ID_BC_SHIFT    24
385
+#define GPWRDN_ADP_INT            BIT(23)
386
+#define GPWRDN_BSESSVLD            BIT(22)
387
+#define GPWRDN_IDSTS            BIT(21)
388
+#define GPWRDN_LINESTATE_MASK        (0x3 << 19)
389
+#define GPWRDN_LINESTATE_SHIFT        19
390
+#define GPWRDN_STS_CHGINT_MSK        BIT(18)
391
+#define GPWRDN_STS_CHGINT        BIT(17)
392
+#define GPWRDN_SRP_DET_MSK        BIT(16)
393
+#define GPWRDN_SRP_DET            BIT(15)
394
+#define GPWRDN_CONNECT_DET_MSK        BIT(14)
395
+#define GPWRDN_CONNECT_DET        BIT(13)
396
+#define GPWRDN_DISCONN_DET_MSK        BIT(12)
397
+#define GPWRDN_DISCONN_DET        BIT(11)
398
+#define GPWRDN_RST_DET_MSK        BIT(10)
399
+#define GPWRDN_RST_DET            BIT(9)
400
+#define GPWRDN_LNSTSCHG_MSK        BIT(8)
401
+#define GPWRDN_LNSTSCHG            BIT(7)
402
+#define GPWRDN_DIS_VBUS            BIT(6)
403
+#define GPWRDN_PWRDNSWTCH        BIT(5)
404
+#define GPWRDN_PWRDNRSTN        BIT(4)
405
+#define GPWRDN_PWRDNCLMP        BIT(3)
406
+#define GPWRDN_RESTORE            BIT(2)
407
+#define GPWRDN_PMUACTV            BIT(1)
408
+#define GPWRDN_PMUINTSEL        BIT(0)
409
+
410
+#define GDFIFOCFG            HSOTG_REG(0x005c)
411
+#define GDFIFOCFG_EPINFOBASE_MASK    (0xffff << 16)
412
+#define GDFIFOCFG_EPINFOBASE_SHIFT    16
413
+#define GDFIFOCFG_GDFIFOCFG_MASK    (0xffff << 0)
414
+#define GDFIFOCFG_GDFIFOCFG_SHIFT    0
415
+
416
+#define ADPCTL                HSOTG_REG(0x0060)
417
+#define ADPCTL_AR_MASK            (0x3 << 27)
418
+#define ADPCTL_AR_SHIFT            27
419
+#define ADPCTL_ADP_TMOUT_INT_MSK    BIT(26)
420
+#define ADPCTL_ADP_SNS_INT_MSK        BIT(25)
421
+#define ADPCTL_ADP_PRB_INT_MSK        BIT(24)
422
+#define ADPCTL_ADP_TMOUT_INT        BIT(23)
423
+#define ADPCTL_ADP_SNS_INT        BIT(22)
424
+#define ADPCTL_ADP_PRB_INT        BIT(21)
425
+#define ADPCTL_ADPENA            BIT(20)
426
+#define ADPCTL_ADPRES            BIT(19)
427
+#define ADPCTL_ENASNS            BIT(18)
428
+#define ADPCTL_ENAPRB            BIT(17)
429
+#define ADPCTL_RTIM_MASK        (0x7ff << 6)
430
+#define ADPCTL_RTIM_SHIFT        6
431
+#define ADPCTL_PRB_PER_MASK        (0x3 << 4)
432
+#define ADPCTL_PRB_PER_SHIFT        4
433
+#define ADPCTL_PRB_DELTA_MASK        (0x3 << 2)
434
+#define ADPCTL_PRB_DELTA_SHIFT        2
435
+#define ADPCTL_PRB_DSCHRG_MASK        (0x3 << 0)
436
+#define ADPCTL_PRB_DSCHRG_SHIFT        0
437
+
438
+#define GREFCLK                 HSOTG_REG(0x0064)
439
+#define GREFCLK_REFCLKPER_MASK         (0x1ffff << 15)
440
+#define GREFCLK_REFCLKPER_SHIFT         15
441
+#define GREFCLK_REF_CLK_MODE         BIT(14)
442
+#define GREFCLK_SOF_CNT_WKUP_ALERT_MASK     (0x3ff)
443
+#define GREFCLK_SOF_CNT_WKUP_ALERT_SHIFT 0
444
+
445
+#define GINTMSK2            HSOTG_REG(0x0068)
446
+#define GINTMSK2_WKUP_ALERT_INT_MSK    BIT(0)
447
+
448
+#define GINTSTS2            HSOTG_REG(0x006c)
449
+#define GINTSTS2_WKUP_ALERT_INT        BIT(0)
450
+
451
+#define HPTXFSIZ            HSOTG_REG(0x100)
452
+/* Use FIFOSIZE_* constants to access this register */
453
+
454
+#define DPTXFSIZN(_a)            HSOTG_REG(0x104 + (((_a) - 1) * 4))
455
+/* Use FIFOSIZE_* constants to access this register */
456
+
457
+/* These apply to the GNPTXFSIZ, HPTXFSIZ and DPTXFSIZN registers */
458
+#define FIFOSIZE_DEPTH_MASK        (0xffff << 16)
459
+#define FIFOSIZE_DEPTH_SHIFT        16
460
+#define FIFOSIZE_STARTADDR_MASK        (0xffff << 0)
461
+#define FIFOSIZE_STARTADDR_SHIFT    0
462
+#define FIFOSIZE_DEPTH_GET(_x)        (((_x) >> 16) & 0xffff)
463
+
464
+/* Device mode registers */
465
+
466
+#define DCFG                HSOTG_REG(0x800)
467
+#define DCFG_DESCDMA_EN            BIT(23)
468
+#define DCFG_EPMISCNT_MASK        (0x1f << 18)
469
+#define DCFG_EPMISCNT_SHIFT        18
470
+#define DCFG_EPMISCNT_LIMIT        0x1f
471
+#define DCFG_EPMISCNT(_x)        ((_x) << 18)
472
+#define DCFG_IPG_ISOC_SUPPORDED        BIT(17)
473
+#define DCFG_PERFRINT_MASK        (0x3 << 11)
474
+#define DCFG_PERFRINT_SHIFT        11
475
+#define DCFG_PERFRINT_LIMIT        0x3
476
+#define DCFG_PERFRINT(_x)        ((_x) << 11)
477
+#define DCFG_DEVADDR_MASK        (0x7f << 4)
478
+#define DCFG_DEVADDR_SHIFT        4
479
+#define DCFG_DEVADDR_LIMIT        0x7f
480
+#define DCFG_DEVADDR(_x)        ((_x) << 4)
481
+#define DCFG_NZ_STS_OUT_HSHK        BIT(2)
482
+#define DCFG_DEVSPD_MASK        (0x3 << 0)
483
+#define DCFG_DEVSPD_SHIFT        0
484
+#define DCFG_DEVSPD_HS            0
485
+#define DCFG_DEVSPD_FS            1
486
+#define DCFG_DEVSPD_LS            2
487
+#define DCFG_DEVSPD_FS48        3
488
+
489
+#define DCTL                HSOTG_REG(0x804)
490
+#define DCTL_SERVICE_INTERVAL_SUPPORTED BIT(19)
491
+#define DCTL_PWRONPRGDONE        BIT(11)
492
+#define DCTL_CGOUTNAK            BIT(10)
493
+#define DCTL_SGOUTNAK            BIT(9)
494
+#define DCTL_CGNPINNAK            BIT(8)
495
+#define DCTL_SGNPINNAK            BIT(7)
496
+#define DCTL_TSTCTL_MASK        (0x7 << 4)
497
+#define DCTL_TSTCTL_SHIFT        4
498
+#define DCTL_GOUTNAKSTS            BIT(3)
499
+#define DCTL_GNPINNAKSTS        BIT(2)
500
+#define DCTL_SFTDISCON            BIT(1)
501
+#define DCTL_RMTWKUPSIG            BIT(0)
502
+
503
+#define DSTS                HSOTG_REG(0x808)
504
+#define DSTS_SOFFN_MASK            (0x3fff << 8)
505
+#define DSTS_SOFFN_SHIFT        8
506
+#define DSTS_SOFFN_LIMIT        0x3fff
507
+#define DSTS_SOFFN(_x)            ((_x) << 8)
508
+#define DSTS_ERRATICERR            BIT(3)
509
+#define DSTS_ENUMSPD_MASK        (0x3 << 1)
510
+#define DSTS_ENUMSPD_SHIFT        1
511
+#define DSTS_ENUMSPD_HS            0
512
+#define DSTS_ENUMSPD_FS            1
513
+#define DSTS_ENUMSPD_LS            2
514
+#define DSTS_ENUMSPD_FS48        3
515
+#define DSTS_SUSPSTS            BIT(0)
516
+
517
+#define DIEPMSK                HSOTG_REG(0x810)
518
+#define DIEPMSK_NAKMSK            BIT(13)
519
+#define DIEPMSK_BNAININTRMSK        BIT(9)
520
+#define DIEPMSK_TXFIFOUNDRNMSK        BIT(8)
521
+#define DIEPMSK_TXFIFOEMPTY        BIT(7)
522
+#define DIEPMSK_INEPNAKEFFMSK        BIT(6)
523
+#define DIEPMSK_INTKNEPMISMSK        BIT(5)
524
+#define DIEPMSK_INTKNTXFEMPMSK        BIT(4)
525
+#define DIEPMSK_TIMEOUTMSK        BIT(3)
526
+#define DIEPMSK_AHBERRMSK        BIT(2)
527
+#define DIEPMSK_EPDISBLDMSK        BIT(1)
528
+#define DIEPMSK_XFERCOMPLMSK        BIT(0)
529
+
530
+#define DOEPMSK                HSOTG_REG(0x814)
531
+#define DOEPMSK_BNAMSK            BIT(9)
532
+#define DOEPMSK_BACK2BACKSETUP        BIT(6)
533
+#define DOEPMSK_STSPHSERCVDMSK        BIT(5)
534
+#define DOEPMSK_OUTTKNEPDISMSK        BIT(4)
535
+#define DOEPMSK_SETUPMSK        BIT(3)
536
+#define DOEPMSK_AHBERRMSK        BIT(2)
537
+#define DOEPMSK_EPDISBLDMSK        BIT(1)
538
+#define DOEPMSK_XFERCOMPLMSK        BIT(0)
539
+
540
+#define DAINT                HSOTG_REG(0x818)
541
+#define DAINTMSK            HSOTG_REG(0x81C)
542
+#define DAINT_OUTEP_SHIFT        16
543
+#define DAINT_OUTEP(_x)            (1 << ((_x) + 16))
544
+#define DAINT_INEP(_x)            (1 << (_x))
545
+
546
+#define DTKNQR1                HSOTG_REG(0x820)
547
+#define DTKNQR2                HSOTG_REG(0x824)
548
+#define DTKNQR3                HSOTG_REG(0x830)
549
+#define DTKNQR4                HSOTG_REG(0x834)
550
+#define DIEPEMPMSK            HSOTG_REG(0x834)
551
+
552
+#define DVBUSDIS            HSOTG_REG(0x828)
553
+#define DVBUSPULSE            HSOTG_REG(0x82C)
554
+
555
+#define DIEPCTL0            HSOTG_REG(0x900)
556
+#define DIEPCTL(_a)            HSOTG_REG(0x900 + ((_a) * 0x20))
557
+
558
+#define DOEPCTL0            HSOTG_REG(0xB00)
559
+#define DOEPCTL(_a)            HSOTG_REG(0xB00 + ((_a) * 0x20))
560
+
561
+/* EP0 specialness:
562
+ * bits[29..28] - reserved (no SetD0PID, SetD1PID)
563
+ * bits[25..22] - should always be zero, this isn't a periodic endpoint
564
+ * bits[10..0] - MPS setting different for EP0
565
+ */
566
+#define D0EPCTL_MPS_MASK        (0x3 << 0)
567
+#define D0EPCTL_MPS_SHIFT        0
568
+#define D0EPCTL_MPS_64            0
569
+#define D0EPCTL_MPS_32            1
570
+#define D0EPCTL_MPS_16            2
571
+#define D0EPCTL_MPS_8            3
572
+
573
+#define DXEPCTL_EPENA            BIT(31)
574
+#define DXEPCTL_EPDIS            BIT(30)
575
+#define DXEPCTL_SETD1PID        BIT(29)
576
+#define DXEPCTL_SETODDFR        BIT(29)
577
+#define DXEPCTL_SETD0PID        BIT(28)
578
+#define DXEPCTL_SETEVENFR        BIT(28)
579
+#define DXEPCTL_SNAK            BIT(27)
580
+#define DXEPCTL_CNAK            BIT(26)
581
+#define DXEPCTL_TXFNUM_MASK        (0xf << 22)
582
+#define DXEPCTL_TXFNUM_SHIFT        22
583
+#define DXEPCTL_TXFNUM_LIMIT        0xf
584
+#define DXEPCTL_TXFNUM(_x)        ((_x) << 22)
585
+#define DXEPCTL_STALL            BIT(21)
586
+#define DXEPCTL_SNP            BIT(20)
587
+#define DXEPCTL_EPTYPE_MASK        (0x3 << 18)
588
+#define DXEPCTL_EPTYPE_CONTROL        (0x0 << 18)
589
+#define DXEPCTL_EPTYPE_ISO        (0x1 << 18)
590
+#define DXEPCTL_EPTYPE_BULK        (0x2 << 18)
591
+#define DXEPCTL_EPTYPE_INTERRUPT    (0x3 << 18)
592
+
593
+#define DXEPCTL_NAKSTS            BIT(17)
594
+#define DXEPCTL_DPID            BIT(16)
595
+#define DXEPCTL_EOFRNUM            BIT(16)
596
+#define DXEPCTL_USBACTEP        BIT(15)
597
+#define DXEPCTL_NEXTEP_MASK        (0xf << 11)
598
+#define DXEPCTL_NEXTEP_SHIFT        11
599
+#define DXEPCTL_NEXTEP_LIMIT        0xf
600
+#define DXEPCTL_NEXTEP(_x)        ((_x) << 11)
601
+#define DXEPCTL_MPS_MASK        (0x7ff << 0)
602
+#define DXEPCTL_MPS_SHIFT        0
603
+#define DXEPCTL_MPS_LIMIT        0x7ff
604
+#define DXEPCTL_MPS(_x)            ((_x) << 0)
605
+
606
+#define DIEPINT(_a)            HSOTG_REG(0x908 + ((_a) * 0x20))
607
+#define DOEPINT(_a)            HSOTG_REG(0xB08 + ((_a) * 0x20))
608
+#define DXEPINT_SETUP_RCVD        BIT(15)
609
+#define DXEPINT_NYETINTRPT        BIT(14)
610
+#define DXEPINT_NAKINTRPT        BIT(13)
611
+#define DXEPINT_BBLEERRINTRPT        BIT(12)
612
+#define DXEPINT_PKTDRPSTS        BIT(11)
613
+#define DXEPINT_BNAINTR            BIT(9)
614
+#define DXEPINT_TXFIFOUNDRN        BIT(8)
615
+#define DXEPINT_OUTPKTERR        BIT(8)
616
+#define DXEPINT_TXFEMP            BIT(7)
617
+#define DXEPINT_INEPNAKEFF        BIT(6)
618
+#define DXEPINT_BACK2BACKSETUP        BIT(6)
619
+#define DXEPINT_INTKNEPMIS        BIT(5)
620
+#define DXEPINT_STSPHSERCVD        BIT(5)
621
+#define DXEPINT_INTKNTXFEMP        BIT(4)
622
+#define DXEPINT_OUTTKNEPDIS        BIT(4)
623
+#define DXEPINT_TIMEOUT            BIT(3)
624
+#define DXEPINT_SETUP            BIT(3)
625
+#define DXEPINT_AHBERR            BIT(2)
626
+#define DXEPINT_EPDISBLD        BIT(1)
627
+#define DXEPINT_XFERCOMPL        BIT(0)
628
+
629
+#define DIEPTSIZ0            HSOTG_REG(0x910)
630
+#define DIEPTSIZ0_PKTCNT_MASK        (0x3 << 19)
631
+#define DIEPTSIZ0_PKTCNT_SHIFT        19
632
+#define DIEPTSIZ0_PKTCNT_LIMIT        0x3
633
+#define DIEPTSIZ0_PKTCNT(_x)        ((_x) << 19)
634
+#define DIEPTSIZ0_XFERSIZE_MASK        (0x7f << 0)
635
+#define DIEPTSIZ0_XFERSIZE_SHIFT    0
636
+#define DIEPTSIZ0_XFERSIZE_LIMIT    0x7f
637
+#define DIEPTSIZ0_XFERSIZE(_x)        ((_x) << 0)
638
+
639
+#define DOEPTSIZ0            HSOTG_REG(0xB10)
640
+#define DOEPTSIZ0_SUPCNT_MASK        (0x3 << 29)
641
+#define DOEPTSIZ0_SUPCNT_SHIFT        29
642
+#define DOEPTSIZ0_SUPCNT_LIMIT        0x3
643
+#define DOEPTSIZ0_SUPCNT(_x)        ((_x) << 29)
644
+#define DOEPTSIZ0_PKTCNT        BIT(19)
645
+#define DOEPTSIZ0_XFERSIZE_MASK        (0x7f << 0)
646
+#define DOEPTSIZ0_XFERSIZE_SHIFT    0
647
+
648
+#define DIEPTSIZ(_a)            HSOTG_REG(0x910 + ((_a) * 0x20))
649
+#define DOEPTSIZ(_a)            HSOTG_REG(0xB10 + ((_a) * 0x20))
650
+#define DXEPTSIZ_MC_MASK        (0x3 << 29)
651
+#define DXEPTSIZ_MC_SHIFT        29
652
+#define DXEPTSIZ_MC_LIMIT        0x3
653
+#define DXEPTSIZ_MC(_x)            ((_x) << 29)
654
+#define DXEPTSIZ_PKTCNT_MASK        (0x3ff << 19)
655
+#define DXEPTSIZ_PKTCNT_SHIFT        19
656
+#define DXEPTSIZ_PKTCNT_LIMIT        0x3ff
657
+#define DXEPTSIZ_PKTCNT_GET(_v)        (((_v) >> 19) & 0x3ff)
658
+#define DXEPTSIZ_PKTCNT(_x)        ((_x) << 19)
659
+#define DXEPTSIZ_XFERSIZE_MASK        (0x7ffff << 0)
660
+#define DXEPTSIZ_XFERSIZE_SHIFT        0
661
+#define DXEPTSIZ_XFERSIZE_LIMIT        0x7ffff
662
+#define DXEPTSIZ_XFERSIZE_GET(_v)    (((_v) >> 0) & 0x7ffff)
663
+#define DXEPTSIZ_XFERSIZE(_x)        ((_x) << 0)
664
+
665
+#define DIEPDMA(_a)            HSOTG_REG(0x914 + ((_a) * 0x20))
666
+#define DOEPDMA(_a)            HSOTG_REG(0xB14 + ((_a) * 0x20))
667
+
668
+#define DTXFSTS(_a)            HSOTG_REG(0x918 + ((_a) * 0x20))
669
+
670
+#define PCGCTL                HSOTG_REG(0x0e00)
671
+#define PCGCTL_IF_DEV_MODE        BIT(31)
672
+#define PCGCTL_P2HD_PRT_SPD_MASK    (0x3 << 29)
673
+#define PCGCTL_P2HD_PRT_SPD_SHIFT    29
674
+#define PCGCTL_P2HD_DEV_ENUM_SPD_MASK    (0x3 << 27)
675
+#define PCGCTL_P2HD_DEV_ENUM_SPD_SHIFT    27
676
+#define PCGCTL_MAC_DEV_ADDR_MASK    (0x7f << 20)
677
+#define PCGCTL_MAC_DEV_ADDR_SHIFT    20
678
+#define PCGCTL_MAX_TERMSEL        BIT(19)
679
+#define PCGCTL_MAX_XCVRSELECT_MASK    (0x3 << 17)
680
+#define PCGCTL_MAX_XCVRSELECT_SHIFT    17
681
+#define PCGCTL_PORT_POWER        BIT(16)
682
+#define PCGCTL_PRT_CLK_SEL_MASK        (0x3 << 14)
683
+#define PCGCTL_PRT_CLK_SEL_SHIFT    14
684
+#define PCGCTL_ESS_REG_RESTORED        BIT(13)
685
+#define PCGCTL_EXTND_HIBER_SWITCH    BIT(12)
686
+#define PCGCTL_EXTND_HIBER_PWRCLMP    BIT(11)
687
+#define PCGCTL_ENBL_EXTND_HIBER        BIT(10)
688
+#define PCGCTL_RESTOREMODE        BIT(9)
689
+#define PCGCTL_RESETAFTSUSP        BIT(8)
690
+#define PCGCTL_DEEP_SLEEP        BIT(7)
691
+#define PCGCTL_PHY_IN_SLEEP        BIT(6)
692
+#define PCGCTL_ENBL_SLEEP_GATING    BIT(5)
693
+#define PCGCTL_RSTPDWNMODULE        BIT(3)
694
+#define PCGCTL_PWRCLMP            BIT(2)
695
+#define PCGCTL_GATEHCLK            BIT(1)
696
+#define PCGCTL_STOPPCLK            BIT(0)
697
+
698
+#define PCGCCTL1 HSOTG_REG(0xe04)
699
+#define PCGCCTL1_TIMER (0x3 << 1)
700
+#define PCGCCTL1_GATEEN BIT(0)
701
+
702
+#define EPFIFO(_a)            HSOTG_REG(0x1000 + ((_a) * 0x1000))
703
+
704
+/* Host Mode Registers */
705
+
706
+#define HCFG                HSOTG_REG(0x0400)
707
+#define HCFG_MODECHTIMEN        BIT(31)
708
+#define HCFG_PERSCHEDENA        BIT(26)
709
+#define HCFG_FRLISTEN_MASK        (0x3 << 24)
710
+#define HCFG_FRLISTEN_SHIFT        24
711
+#define HCFG_FRLISTEN_8                (0 << 24)
712
+#define FRLISTEN_8_SIZE                8
713
+#define HCFG_FRLISTEN_16            BIT(24)
714
+#define FRLISTEN_16_SIZE            16
715
+#define HCFG_FRLISTEN_32            (2 << 24)
716
+#define FRLISTEN_32_SIZE            32
717
+#define HCFG_FRLISTEN_64            (3 << 24)
718
+#define FRLISTEN_64_SIZE            64
719
+#define HCFG_DESCDMA            BIT(23)
720
+#define HCFG_RESVALID_MASK        (0xff << 8)
721
+#define HCFG_RESVALID_SHIFT        8
722
+#define HCFG_ENA32KHZ            BIT(7)
723
+#define HCFG_FSLSSUPP            BIT(2)
724
+#define HCFG_FSLSPCLKSEL_MASK        (0x3 << 0)
725
+#define HCFG_FSLSPCLKSEL_SHIFT        0
726
+#define HCFG_FSLSPCLKSEL_30_60_MHZ    0
727
+#define HCFG_FSLSPCLKSEL_48_MHZ        1
728
+#define HCFG_FSLSPCLKSEL_6_MHZ        2
729
+
730
+#define HFIR                HSOTG_REG(0x0404)
731
+#define HFIR_FRINT_MASK            (0xffff << 0)
732
+#define HFIR_FRINT_SHIFT        0
733
+#define HFIR_RLDCTRL            BIT(16)
734
+
735
+#define HFNUM                HSOTG_REG(0x0408)
736
+#define HFNUM_FRREM_MASK        (0xffff << 16)
737
+#define HFNUM_FRREM_SHIFT        16
738
+#define HFNUM_FRNUM_MASK        (0xffff << 0)
739
+#define HFNUM_FRNUM_SHIFT        0
740
+#define HFNUM_MAX_FRNUM            0x3fff
741
+
742
+#define HPTXSTS                HSOTG_REG(0x0410)
743
+#define TXSTS_QTOP_ODD            BIT(31)
744
+#define TXSTS_QTOP_CHNEP_MASK        (0xf << 27)
745
+#define TXSTS_QTOP_CHNEP_SHIFT        27
746
+#define TXSTS_QTOP_TOKEN_MASK        (0x3 << 25)
747
+#define TXSTS_QTOP_TOKEN_SHIFT        25
748
+#define TXSTS_QTOP_TERMINATE        BIT(24)
749
+#define TXSTS_QSPCAVAIL_MASK        (0xff << 16)
750
+#define TXSTS_QSPCAVAIL_SHIFT        16
751
+#define TXSTS_FSPCAVAIL_MASK        (0xffff << 0)
752
+#define TXSTS_FSPCAVAIL_SHIFT        0
753
+
754
+#define HAINT                HSOTG_REG(0x0414)
755
+#define HAINTMSK            HSOTG_REG(0x0418)
756
+#define HFLBADDR            HSOTG_REG(0x041c)
757
+
758
+#define HPRT0                HSOTG_REG(0x0440)
759
+#define HPRT0_SPD_MASK            (0x3 << 17)
760
+#define HPRT0_SPD_SHIFT            17
761
+#define HPRT0_SPD_HIGH_SPEED        0
762
+#define HPRT0_SPD_FULL_SPEED        1
763
+#define HPRT0_SPD_LOW_SPEED        2
764
+#define HPRT0_TSTCTL_MASK        (0xf << 13)
765
+#define HPRT0_TSTCTL_SHIFT        13
766
+#define HPRT0_PWR            BIT(12)
767
+#define HPRT0_LNSTS_MASK        (0x3 << 10)
768
+#define HPRT0_LNSTS_SHIFT        10
769
+#define HPRT0_RST            BIT(8)
770
+#define HPRT0_SUSP            BIT(7)
771
+#define HPRT0_RES            BIT(6)
772
+#define HPRT0_OVRCURRCHG        BIT(5)
773
+#define HPRT0_OVRCURRACT        BIT(4)
774
+#define HPRT0_ENACHG            BIT(3)
775
+#define HPRT0_ENA            BIT(2)
776
+#define HPRT0_CONNDET            BIT(1)
777
+#define HPRT0_CONNSTS            BIT(0)
778
+
779
+#define HCCHAR(_ch)            HSOTG_REG(0x0500 + 0x20 * (_ch))
780
+#define HCCHAR_CHENA            BIT(31)
781
+#define HCCHAR_CHDIS            BIT(30)
782
+#define HCCHAR_ODDFRM            BIT(29)
783
+#define HCCHAR_DEVADDR_MASK        (0x7f << 22)
784
+#define HCCHAR_DEVADDR_SHIFT        22
785
+#define HCCHAR_MULTICNT_MASK        (0x3 << 20)
786
+#define HCCHAR_MULTICNT_SHIFT        20
787
+#define HCCHAR_EPTYPE_MASK        (0x3 << 18)
788
+#define HCCHAR_EPTYPE_SHIFT        18
789
+#define HCCHAR_LSPDDEV            BIT(17)
790
+#define HCCHAR_EPDIR            BIT(15)
791
+#define HCCHAR_EPNUM_MASK        (0xf << 11)
792
+#define HCCHAR_EPNUM_SHIFT        11
793
+#define HCCHAR_MPS_MASK            (0x7ff << 0)
794
+#define HCCHAR_MPS_SHIFT        0
795
+
796
+#define HCSPLT(_ch)            HSOTG_REG(0x0504 + 0x20 * (_ch))
797
+#define HCSPLT_SPLTENA            BIT(31)
798
+#define HCSPLT_COMPSPLT            BIT(16)
799
+#define HCSPLT_XACTPOS_MASK        (0x3 << 14)
800
+#define HCSPLT_XACTPOS_SHIFT        14
801
+#define HCSPLT_XACTPOS_MID        0
802
+#define HCSPLT_XACTPOS_END        1
803
+#define HCSPLT_XACTPOS_BEGIN        2
804
+#define HCSPLT_XACTPOS_ALL        3
805
+#define HCSPLT_HUBADDR_MASK        (0x7f << 7)
806
+#define HCSPLT_HUBADDR_SHIFT        7
807
+#define HCSPLT_PRTADDR_MASK        (0x7f << 0)
808
+#define HCSPLT_PRTADDR_SHIFT        0
809
+
810
+#define HCINT(_ch)            HSOTG_REG(0x0508 + 0x20 * (_ch))
811
+#define HCINTMSK(_ch)            HSOTG_REG(0x050c + 0x20 * (_ch))
812
+#define HCINTMSK_RESERVED14_31        (0x3ffff << 14)
813
+#define HCINTMSK_FRM_LIST_ROLL        BIT(13)
814
+#define HCINTMSK_XCS_XACT        BIT(12)
815
+#define HCINTMSK_BNA            BIT(11)
816
+#define HCINTMSK_DATATGLERR        BIT(10)
817
+#define HCINTMSK_FRMOVRUN        BIT(9)
818
+#define HCINTMSK_BBLERR            BIT(8)
819
+#define HCINTMSK_XACTERR        BIT(7)
820
+#define HCINTMSK_NYET            BIT(6)
821
+#define HCINTMSK_ACK            BIT(5)
822
+#define HCINTMSK_NAK            BIT(4)
823
+#define HCINTMSK_STALL            BIT(3)
824
+#define HCINTMSK_AHBERR            BIT(2)
825
+#define HCINTMSK_CHHLTD            BIT(1)
826
+#define HCINTMSK_XFERCOMPL        BIT(0)
827
+
828
+#define HCTSIZ(_ch)            HSOTG_REG(0x0510 + 0x20 * (_ch))
829
+#define TSIZ_DOPNG            BIT(31)
830
+#define TSIZ_SC_MC_PID_MASK        (0x3 << 29)
831
+#define TSIZ_SC_MC_PID_SHIFT        29
832
+#define TSIZ_SC_MC_PID_DATA0        0
833
+#define TSIZ_SC_MC_PID_DATA2        1
834
+#define TSIZ_SC_MC_PID_DATA1        2
835
+#define TSIZ_SC_MC_PID_MDATA        3
836
+#define TSIZ_SC_MC_PID_SETUP        3
837
+#define TSIZ_PKTCNT_MASK        (0x3ff << 19)
838
+#define TSIZ_PKTCNT_SHIFT        19
839
+#define TSIZ_NTD_MASK            (0xff << 8)
840
+#define TSIZ_NTD_SHIFT            8
841
+#define TSIZ_SCHINFO_MASK        (0xff << 0)
842
+#define TSIZ_SCHINFO_SHIFT        0
843
+#define TSIZ_XFERSIZE_MASK        (0x7ffff << 0)
844
+#define TSIZ_XFERSIZE_SHIFT        0
845
+
846
+#define HCDMA(_ch)            HSOTG_REG(0x0514 + 0x20 * (_ch))
847
+
848
+#define HCDMAB(_ch)            HSOTG_REG(0x051c + 0x20 * (_ch))
849
+
850
+#define HCFIFO(_ch)            HSOTG_REG(0x1000 + 0x1000 * (_ch))
851
+
852
+/**
853
+ * struct dwc2_dma_desc - DMA descriptor structure,
854
+ * used for both host and gadget modes
855
+ *
856
+ * @status: DMA descriptor status quadlet
857
+ * @buf: DMA descriptor data buffer pointer
858
+ *
859
+ * DMA Descriptor structure contains two quadlets:
860
+ * Status quadlet and Data buffer pointer.
861
+ */
862
+struct dwc2_dma_desc {
863
+    uint32_t status;
864
+    uint32_t buf;
865
+} __packed;
866
+
867
+/* Host Mode DMA descriptor status quadlet */
868
+
869
+#define HOST_DMA_A            BIT(31)
870
+#define HOST_DMA_STS_MASK        (0x3 << 28)
871
+#define HOST_DMA_STS_SHIFT        28
872
+#define HOST_DMA_STS_PKTERR        BIT(28)
873
+#define HOST_DMA_EOL            BIT(26)
874
+#define HOST_DMA_IOC            BIT(25)
875
+#define HOST_DMA_SUP            BIT(24)
876
+#define HOST_DMA_ALT_QTD        BIT(23)
877
+#define HOST_DMA_QTD_OFFSET_MASK    (0x3f << 17)
878
+#define HOST_DMA_QTD_OFFSET_SHIFT    17
879
+#define HOST_DMA_ISOC_NBYTES_MASK    (0xfff << 0)
880
+#define HOST_DMA_ISOC_NBYTES_SHIFT    0
881
+#define HOST_DMA_NBYTES_MASK        (0x1ffff << 0)
882
+#define HOST_DMA_NBYTES_SHIFT        0
883
+#define HOST_DMA_NBYTES_LIMIT        131071
884
+
885
+/* Device Mode DMA descriptor status quadlet */
886
+
887
+#define DEV_DMA_BUFF_STS_MASK        (0x3 << 30)
888
+#define DEV_DMA_BUFF_STS_SHIFT        30
889
+#define DEV_DMA_BUFF_STS_HREADY        0
890
+#define DEV_DMA_BUFF_STS_DMABUSY    1
891
+#define DEV_DMA_BUFF_STS_DMADONE    2
892
+#define DEV_DMA_BUFF_STS_HBUSY        3
893
+#define DEV_DMA_STS_MASK        (0x3 << 28)
894
+#define DEV_DMA_STS_SHIFT        28
895
+#define DEV_DMA_STS_SUCC        0
896
+#define DEV_DMA_STS_BUFF_FLUSH        1
897
+#define DEV_DMA_STS_BUFF_ERR        3
898
+#define DEV_DMA_L            BIT(27)
899
+#define DEV_DMA_SHORT            BIT(26)
900
+#define DEV_DMA_IOC            BIT(25)
901
+#define DEV_DMA_SR            BIT(24)
902
+#define DEV_DMA_MTRF            BIT(23)
903
+#define DEV_DMA_ISOC_PID_MASK        (0x3 << 23)
904
+#define DEV_DMA_ISOC_PID_SHIFT        23
905
+#define DEV_DMA_ISOC_PID_DATA0        0
906
+#define DEV_DMA_ISOC_PID_DATA2        1
907
+#define DEV_DMA_ISOC_PID_DATA1        2
908
+#define DEV_DMA_ISOC_PID_MDATA        3
909
+#define DEV_DMA_ISOC_FRNUM_MASK        (0x7ff << 12)
910
+#define DEV_DMA_ISOC_FRNUM_SHIFT    12
911
+#define DEV_DMA_ISOC_TX_NBYTES_MASK    (0xfff << 0)
912
+#define DEV_DMA_ISOC_TX_NBYTES_LIMIT    0xfff
913
+#define DEV_DMA_ISOC_RX_NBYTES_MASK    (0x7ff << 0)
914
+#define DEV_DMA_ISOC_RX_NBYTES_LIMIT    0x7ff
915
+#define DEV_DMA_ISOC_NBYTES_SHIFT    0
916
+#define DEV_DMA_NBYTES_MASK        (0xffff << 0)
917
+#define DEV_DMA_NBYTES_SHIFT        0
918
+#define DEV_DMA_NBYTES_LIMIT        0xffff
919
+
920
+#define MAX_DMA_DESC_NUM_GENERIC    64
921
+#define MAX_DMA_DESC_NUM_HS_ISOC    256
922
+
923
+#endif /* __DWC2_HW_H__ */
924
--
78
--
925
2.20.1
79
2.20.1
926
80
927
81
diff view generated by jsdifflib
1
From: Eden Mikitas <e.mikitas@gmail.com>
1
From: Sebastian Meyer <meyer@absint.com>
2
2
3
The while statement in question only checked if tx_burst is not 0.
3
With gdb 9.0 and better it is possible to connect to a gdbstub
4
tx_burst is a signed int, which is assigned the value put by the
4
over unix sockets, which is better than a TCP socket connection
5
guest driver in ECSPI_CONREG. The burst length can be anywhere
5
in some situations. The QEMU command line to set this up is
6
between 1 and 4096, and since tx_burst is always decremented by 8
6
non-obvious; document it.
7
it could possibly underflow, causing an infinite loop.
8
7
9
Signed-off-by: Eden Mikitas <e.mikitas@gmail.com>
8
Signed-off-by: Sebastian Meyer <meyer@absint.com>
10
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
9
Message-id: 162867284829.27377.4784930719350564918-0@git.sr.ht
10
[PMM: Tweaked commit message; adjusted wording in a couple of
11
places; fixed rST formatting issue; moved section up out of
12
the 'advanced debugging options' subsection]
13
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
16
---
13
hw/ssi/imx_spi.c | 2 +-
17
docs/system/gdb.rst | 26 +++++++++++++++++++++++++-
14
1 file changed, 1 insertion(+), 1 deletion(-)
18
1 file changed, 25 insertions(+), 1 deletion(-)
15
19
16
diff --git a/hw/ssi/imx_spi.c b/hw/ssi/imx_spi.c
20
diff --git a/docs/system/gdb.rst b/docs/system/gdb.rst
17
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
18
--- a/hw/ssi/imx_spi.c
22
--- a/docs/system/gdb.rst
19
+++ b/hw/ssi/imx_spi.c
23
+++ b/docs/system/gdb.rst
20
@@ -XXX,XX +XXX,XX @@ static void imx_spi_flush_txfifo(IMXSPIState *s)
24
@@ -XXX,XX +XXX,XX @@ The ``-s`` option will make QEMU listen for an incoming connection
21
25
from gdb on TCP port 1234, and ``-S`` will make QEMU not start the
22
rx = 0;
26
guest until you tell it to from gdb. (If you want to specify which
23
27
TCP port to use or to use something other than TCP for the gdbstub
24
- while (tx_burst) {
28
-connection, use the ``-gdb dev`` option instead of ``-s``.)
25
+ while (tx_burst > 0) {
29
+connection, use the ``-gdb dev`` option instead of ``-s``. See
26
uint8_t byte = tx & 0xff;
30
+`Using unix sockets`_ for an example.)
27
31
28
DPRINTF("writing 0x%02x\n", (uint32_t)byte);
32
.. parsed-literal::
33
34
@@ -XXX,XX +XXX,XX @@ not just those in the cluster you are currently working on::
35
36
(gdb) set schedule-multiple on
37
38
+Using unix sockets
39
+==================
40
+
41
+An alternate method for connecting gdb to the QEMU gdbstub is to use
42
+a unix socket (if supported by your operating system). This is useful when
43
+running several tests in parallel, or if you do not have a known free TCP
44
+port (e.g. when running automated tests).
45
+
46
+First create a chardev with the appropriate options, then
47
+instruct the gdbserver to use that device:
48
+
49
+.. parsed-literal::
50
+
51
+ |qemu_system| -chardev socket,path=/tmp/gdb-socket,server=on,wait=off,id=gdb0 -gdb chardev:gdb0 -S ...
52
+
53
+Start gdb as before, but this time connect using the path to
54
+the socket::
55
+
56
+ (gdb) target remote /tmp/gdb-socket
57
+
58
+Note that to use a unix socket for the connection you will need
59
+gdb version 9.0 or newer.
60
+
61
Advanced debugging options
62
==========================
63
29
--
64
--
30
2.20.1
65
2.20.1
31
66
32
67
diff view generated by jsdifflib