1
Arm queue; the bulk of this is the VFP decodetree conversion...
1
First arm pullreq for 7.1. The bulk of this is the qemu_split_irq
2
removal.
3
4
I have enough stuff in my to-review queue that I expect to do another
5
pullreq early next week, but 31 patches is enough to not hang on to.
2
6
3
thanks
7
thanks
4
-- PMM
8
-- PMM
5
9
6
The following changes since commit 4747524f9f243ca5ff1f146d37e423c00e923ee1:
10
The following changes since commit 9c125d17e9402c232c46610802e5931b3639d77b:
7
11
8
Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2019-06-12' into staging (2019-06-13 11:58:00 +0100)
12
Merge tag 'pull-tcg-20220420' of https://gitlab.com/rth7680/qemu into staging (2022-04-20 16:43:11 -0700)
9
13
10
are available in the Git repository at:
14
are available in the Git repository at:
11
15
12
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20190613
16
https://git.linaro.org/people/pmaydell/qemu-arm.git tags/pull-target-arm-20220421
13
17
14
for you to fetch changes up to 07e4c7f769120c9a5bd6a26c2dc1421f2f838d80:
18
for you to fetch changes up to 5b415dd61bdbf61fb4be0e9f1a7172b8bce682c6:
15
19
16
target/arm: Fix short-vector increment behaviour (2019-06-13 12:57:37 +0100)
20
hw/arm: Use bit fields for NPCM7XX PWRON STRAPs (2022-04-21 11:37:05 +0100)
17
21
18
----------------------------------------------------------------
22
----------------------------------------------------------------
19
target-arm queue:
23
target-arm queue:
20
* convert aarch32 VFP decoder to decodetree
24
* hw/arm/virt: Check for attempt to use TrustZone with KVM or HVF
21
(includes tightening up decode in a few places)
25
* versal: Add the Cortex-R5s in the Real-Time Processing Unit (RPU) subsystem
22
* fix minor bugs in VFP short-vector handling
26
* versal: model enough of the Clock/Reset Low-power domain (CRL) to allow control of the Cortex-R5s
23
* hw/core/bus.c: Only the main system bus can have no parent
27
* xlnx-zynqmp: Connect 4 TTC timers
24
* smmuv3: Fix decoding of ID register range
28
* exynos4210: Refactor GIC/combiner code to stop using qemu_split_irq
25
* Implement NSACR gating of floating point
29
* realview: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
26
* Use tcg_gen_gvec_bitsel
30
* stellaris: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
27
* Vectorize USHL and SSHL
31
* hw/core/irq: remove unused 'qemu_irq_split' function
32
* npcm7xx: use symbolic constants for PWRON STRAP bit fields
33
* virt: document impact of gic-version on max CPUs
28
34
29
----------------------------------------------------------------
35
----------------------------------------------------------------
30
Peter Maydell (44):
36
Edgar E. Iglesias (6):
31
target/arm: Implement NSACR gating of floating point
37
timer: cadence_ttc: Break out header file to allow embedding
32
hw/arm/smmuv3: Fix decoding of ID register range
38
hw/arm/xlnx-zynqmp: Connect 4 TTC timers
33
hw/core/bus.c: Only the main system bus can have no parent
39
hw/arm: versal: Create an APU CPU Cluster
34
target/arm: Add stubs for AArch32 VFP decodetree
40
hw/arm: versal: Add the Cortex-R5Fs
35
target/arm: Factor out VFP access checking code
41
hw/misc: Add a model of the Xilinx Versal CRL
36
target/arm: Fix Cortex-R5F MVFR values
42
hw/arm: versal: Connect the CRL
37
target/arm: Explicitly enable VFP short-vectors for aarch32 -cpu max
38
target/arm: Convert the VSEL instructions to decodetree
39
target/arm: Convert VMINNM, VMAXNM to decodetree
40
target/arm: Convert VRINTA/VRINTN/VRINTP/VRINTM to decodetree
41
target/arm: Convert VCVTA/VCVTN/VCVTP/VCVTM to decodetree
42
target/arm: Move the VFP trans_* functions to translate-vfp.inc.c
43
target/arm: Add helpers for VFP register loads and stores
44
target/arm: Convert "double-precision" register moves to decodetree
45
target/arm: Convert "single-precision" register moves to decodetree
46
target/arm: Convert VFP two-register transfer insns to decodetree
47
target/arm: Convert VFP VLDR and VSTR to decodetree
48
target/arm: Convert the VFP load/store multiple insns to decodetree
49
target/arm: Remove VLDR/VSTR/VLDM/VSTM use of cpu_F0s and cpu_F0d
50
target/arm: Convert VFP VMLA to decodetree
51
target/arm: Convert VFP VMLS to decodetree
52
target/arm: Convert VFP VNMLS to decodetree
53
target/arm: Convert VFP VNMLA to decodetree
54
target/arm: Convert VMUL to decodetree
55
target/arm: Convert VNMUL to decodetree
56
target/arm: Convert VADD to decodetree
57
target/arm: Convert VSUB to decodetree
58
target/arm: Convert VDIV to decodetree
59
target/arm: Convert VFP fused multiply-add insns to decodetree
60
target/arm: Convert VMOV (imm) to decodetree
61
target/arm: Convert VABS to decodetree
62
target/arm: Convert VNEG to decodetree
63
target/arm: Convert VSQRT to decodetree
64
target/arm: Convert VMOV (register) to decodetree
65
target/arm: Convert VFP comparison insns to decodetree
66
target/arm: Convert the VCVT-from-f16 insns to decodetree
67
target/arm: Convert the VCVT-to-f16 insns to decodetree
68
target/arm: Convert VFP round insns to decodetree
69
target/arm: Convert double-single precision conversion insns to decodetree
70
target/arm: Convert integer-to-float insns to decodetree
71
target/arm: Convert VJCVT to decodetree
72
target/arm: Convert VCVT fp/fixed-point conversion insns to decodetree
73
target/arm: Convert float-to-integer VCVT insns to decodetree
74
target/arm: Fix short-vector increment behaviour
75
43
76
Richard Henderson (4):
44
Hao Wu (2):
77
target/arm: Vectorize USHL and SSHL
45
hw/misc: Add PWRON STRAP bit fields in GCR module
78
target/arm: Use tcg_gen_gvec_bitsel
46
hw/arm: Use bit fields for NPCM7XX PWRON STRAPs
79
target/arm: Fix output of PAuth Auth
80
decodetree: Fix comparison of Field
81
47
82
target/arm/Makefile.objs | 13 +
48
Heinrich Schuchardt (1):
83
tests/tcg/aarch64/Makefile.target | 2 +-
49
hw/arm/virt: impact of gic-version on max CPUs
84
target/arm/cpu.h | 11 +
85
target/arm/helper.h | 11 +-
86
target/arm/translate-a64.h | 2 +
87
target/arm/translate.h | 9 +-
88
hw/arm/smmuv3.c | 2 +-
89
hw/core/bus.c | 21 +-
90
target/arm/cpu.c | 6 +
91
target/arm/helper.c | 75 +-
92
target/arm/neon_helper.c | 33 -
93
target/arm/pauth_helper.c | 4 +-
94
target/arm/translate-a64.c | 33 +-
95
target/arm/translate-vfp.inc.c | 2672 +++++++++++++++++++++++++++++++++++++
96
target/arm/translate.c | 1881 +++++---------------------
97
target/arm/vec_helper.c | 88 ++
98
tests/tcg/aarch64/pauth-2.c | 61 +
99
scripts/decodetree.py | 2 +-
100
target/arm/vfp-uncond.decode | 63 +
101
target/arm/vfp.decode | 242 ++++
102
20 files changed, 3593 insertions(+), 1638 deletions(-)
103
create mode 100644 target/arm/translate-vfp.inc.c
104
create mode 100644 tests/tcg/aarch64/pauth-2.c
105
create mode 100644 target/arm/vfp-uncond.decode
106
create mode 100644 target/arm/vfp.decode
107
50
51
Peter Maydell (19):
52
hw/arm/virt: Check for attempt to use TrustZone with KVM or HVF
53
hw/arm/exynos4210: Use TYPE_OR_IRQ instead of custom OR-gate device
54
hw/intc/exynos4210_gic: Remove unused TYPE_EXYNOS4210_IRQ_GATE
55
hw/arm/exynos4210: Put a9mpcore device into state struct
56
hw/arm/exynos4210: Drop int_gic_irq[] from Exynos4210Irq struct
57
hw/arm/exynos4210: Coalesce board_irqs and irq_table
58
hw/arm/exynos4210: Fix code style nit in combiner_grp_to_gic_id[]
59
hw/arm/exynos4210: Move exynos4210_init_board_irqs() into exynos4210.c
60
hw/arm/exynos4210: Put external GIC into state struct
61
hw/arm/exynos4210: Drop ext_gic_irq[] from Exynos4210Irq struct
62
hw/arm/exynos4210: Move exynos4210_combiner_get_gpioin() into exynos4210.c
63
hw/arm/exynos4210: Delete unused macro definitions
64
hw/arm/exynos4210: Use TYPE_SPLIT_IRQ in exynos4210_init_board_irqs()
65
hw/arm/exynos4210: Fill in irq_table[] for internal-combiner-only IRQ lines
66
hw/arm/exynos4210: Connect MCT_G0 and MCT_G1 to both combiners
67
hw/arm/exynos4210: Don't connect multiple lines to external GIC inputs
68
hw/arm/exynos4210: Fold combiner splits into exynos4210_init_board_irqs()
69
hw/arm/exynos4210: Put combiners into state struct
70
hw/arm/exynos4210: Drop Exynos4210Irq struct
71
72
Zongyuan Li (3):
73
hw/arm/realview: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
74
hw/arm/stellaris: replace 'qemu_split_irq' with 'TYPE_SPLIT_IRQ'
75
hw/core/irq: remove unused 'qemu_irq_split' function
76
77
docs/system/arm/virt.rst | 4 +-
78
include/hw/arm/exynos4210.h | 50 ++--
79
include/hw/arm/xlnx-versal.h | 16 ++
80
include/hw/arm/xlnx-zynqmp.h | 4 +
81
include/hw/intc/exynos4210_combiner.h | 57 +++++
82
include/hw/intc/exynos4210_gic.h | 43 ++++
83
include/hw/irq.h | 5 -
84
include/hw/misc/npcm7xx_gcr.h | 30 +++
85
include/hw/misc/xlnx-versal-crl.h | 235 +++++++++++++++++++
86
include/hw/timer/cadence_ttc.h | 54 +++++
87
hw/arm/exynos4210.c | 430 ++++++++++++++++++++++++++++++----
88
hw/arm/npcm7xx_boards.c | 24 +-
89
hw/arm/realview.c | 33 ++-
90
hw/arm/stellaris.c | 15 +-
91
hw/arm/virt.c | 7 +
92
hw/arm/xlnx-versal-virt.c | 6 +-
93
hw/arm/xlnx-versal.c | 99 +++++++-
94
hw/arm/xlnx-zynqmp.c | 22 ++
95
hw/core/irq.c | 15 --
96
hw/intc/exynos4210_combiner.c | 108 +--------
97
hw/intc/exynos4210_gic.c | 344 +--------------------------
98
hw/misc/xlnx-versal-crl.c | 421 +++++++++++++++++++++++++++++++++
99
hw/timer/cadence_ttc.c | 32 +--
100
MAINTAINERS | 2 +-
101
hw/misc/meson.build | 1 +
102
25 files changed, 1457 insertions(+), 600 deletions(-)
103
create mode 100644 include/hw/intc/exynos4210_combiner.h
104
create mode 100644 include/hw/intc/exynos4210_gic.h
105
create mode 100644 include/hw/misc/xlnx-versal-crl.h
106
create mode 100644 include/hw/timer/cadence_ttc.h
107
create mode 100644 hw/misc/xlnx-versal-crl.c
diff view generated by jsdifflib
1
Convert the VCVT (between floating-point and fixed-point) instructions
1
It's not possible to provide the guest with the Security extensions
2
to decodetree.
2
(TrustZone) when using KVM or HVF, because the hardware
3
virtualization extensions don't permit running EL3 guest code.
4
However, we weren't checking for this combination, with the result
5
that QEMU would assert if you tried it:
3
6
7
$ qemu-system-aarch64 -enable-kvm -machine virt,secure=on -cpu host -display none
8
Unexpected error in object_property_find_err() at ../../qom/object.c:1304:
9
qemu-system-aarch64: Property 'host-arm-cpu.secure-memory' not found
10
Aborted
11
12
Check for this combination of options and report an error, in the
13
same way we already do for attempts to give a KVM or HVF guest the
14
Virtualization or MTE extensions. Now we will report:
15
16
qemu-system-aarch64: mach-virt: KVM does not support providing Security extensions (TrustZone) to the guest CPU
17
18
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/961
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
19
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
20
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
21
Message-id: 20220404155301.566542-1-peter.maydell@linaro.org
6
---
22
---
7
target/arm/translate-vfp.inc.c | 124 +++++++++++++++++++++++++++++++++
23
hw/arm/virt.c | 7 +++++++
8
target/arm/translate.c | 57 +--------------
24
1 file changed, 7 insertions(+)
9
target/arm/vfp.decode | 10 +++
10
3 files changed, 136 insertions(+), 55 deletions(-)
11
25
12
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
26
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
13
index XXXXXXX..XXXXXXX 100644
27
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/translate-vfp.inc.c
28
--- a/hw/arm/virt.c
15
+++ b/target/arm/translate-vfp.inc.c
29
+++ b/hw/arm/virt.c
16
@@ -XXX,XX +XXX,XX @@ static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a)
30
@@ -XXX,XX +XXX,XX @@ static void machvirt_init(MachineState *machine)
17
tcg_temp_free_i32(vd);
31
exit(1);
18
return true;
32
}
19
}
33
20
+
34
+ if (vms->secure && (kvm_enabled() || hvf_enabled())) {
21
+static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
35
+ error_report("mach-virt: %s does not support providing "
22
+{
36
+ "Security extensions (TrustZone) to the guest CPU",
23
+ TCGv_i32 vd, shift;
37
+ kvm_enabled() ? "KVM" : "HVF");
24
+ TCGv_ptr fpst;
38
+ exit(1);
25
+ int frac_bits;
26
+
27
+ if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
28
+ return false;
29
+ }
39
+ }
30
+
40
+
31
+ if (!vfp_access_check(s)) {
41
if (vms->virt && (kvm_enabled() || hvf_enabled())) {
32
+ return true;
42
error_report("mach-virt: %s does not support providing "
33
+ }
43
"Virtualization extensions to the guest CPU",
34
+
35
+ frac_bits = (a->opc & 1) ? (32 - a->imm) : (16 - a->imm);
36
+
37
+ vd = tcg_temp_new_i32();
38
+ neon_load_reg32(vd, a->vd);
39
+
40
+ fpst = get_fpstatus_ptr(false);
41
+ shift = tcg_const_i32(frac_bits);
42
+
43
+ /* Switch on op:U:sx bits */
44
+ switch (a->opc) {
45
+ case 0:
46
+ gen_helper_vfp_shtos(vd, vd, shift, fpst);
47
+ break;
48
+ case 1:
49
+ gen_helper_vfp_sltos(vd, vd, shift, fpst);
50
+ break;
51
+ case 2:
52
+ gen_helper_vfp_uhtos(vd, vd, shift, fpst);
53
+ break;
54
+ case 3:
55
+ gen_helper_vfp_ultos(vd, vd, shift, fpst);
56
+ break;
57
+ case 4:
58
+ gen_helper_vfp_toshs_round_to_zero(vd, vd, shift, fpst);
59
+ break;
60
+ case 5:
61
+ gen_helper_vfp_tosls_round_to_zero(vd, vd, shift, fpst);
62
+ break;
63
+ case 6:
64
+ gen_helper_vfp_touhs_round_to_zero(vd, vd, shift, fpst);
65
+ break;
66
+ case 7:
67
+ gen_helper_vfp_touls_round_to_zero(vd, vd, shift, fpst);
68
+ break;
69
+ default:
70
+ g_assert_not_reached();
71
+ }
72
+
73
+ neon_store_reg32(vd, a->vd);
74
+ tcg_temp_free_i32(vd);
75
+ tcg_temp_free_i32(shift);
76
+ tcg_temp_free_ptr(fpst);
77
+ return true;
78
+}
79
+
80
+static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
81
+{
82
+ TCGv_i64 vd;
83
+ TCGv_i32 shift;
84
+ TCGv_ptr fpst;
85
+ int frac_bits;
86
+
87
+ if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
88
+ return false;
89
+ }
90
+
91
+ /* UNDEF accesses to D16-D31 if they don't exist. */
92
+ if (!dc_isar_feature(aa32_fp_d32, s) && (a->vd & 0x10)) {
93
+ return false;
94
+ }
95
+
96
+ if (!vfp_access_check(s)) {
97
+ return true;
98
+ }
99
+
100
+ frac_bits = (a->opc & 1) ? (32 - a->imm) : (16 - a->imm);
101
+
102
+ vd = tcg_temp_new_i64();
103
+ neon_load_reg64(vd, a->vd);
104
+
105
+ fpst = get_fpstatus_ptr(false);
106
+ shift = tcg_const_i32(frac_bits);
107
+
108
+ /* Switch on op:U:sx bits */
109
+ switch (a->opc) {
110
+ case 0:
111
+ gen_helper_vfp_shtod(vd, vd, shift, fpst);
112
+ break;
113
+ case 1:
114
+ gen_helper_vfp_sltod(vd, vd, shift, fpst);
115
+ break;
116
+ case 2:
117
+ gen_helper_vfp_uhtod(vd, vd, shift, fpst);
118
+ break;
119
+ case 3:
120
+ gen_helper_vfp_ultod(vd, vd, shift, fpst);
121
+ break;
122
+ case 4:
123
+ gen_helper_vfp_toshd_round_to_zero(vd, vd, shift, fpst);
124
+ break;
125
+ case 5:
126
+ gen_helper_vfp_tosld_round_to_zero(vd, vd, shift, fpst);
127
+ break;
128
+ case 6:
129
+ gen_helper_vfp_touhd_round_to_zero(vd, vd, shift, fpst);
130
+ break;
131
+ case 7:
132
+ gen_helper_vfp_tould_round_to_zero(vd, vd, shift, fpst);
133
+ break;
134
+ default:
135
+ g_assert_not_reached();
136
+ }
137
+
138
+ neon_store_reg64(vd, a->vd);
139
+ tcg_temp_free_i64(vd);
140
+ tcg_temp_free_i32(shift);
141
+ tcg_temp_free_ptr(fpst);
142
+ return true;
143
+}
144
diff --git a/target/arm/translate.c b/target/arm/translate.c
145
index XXXXXXX..XXXXXXX 100644
146
--- a/target/arm/translate.c
147
+++ b/target/arm/translate.c
148
@@ -XXX,XX +XXX,XX @@ static inline void gen_vfp_##name(int dp, int shift, int neon) \
149
tcg_temp_free_i32(tmp_shift); \
150
tcg_temp_free_ptr(statusptr); \
151
}
152
-VFP_GEN_FIX(tosh, _round_to_zero)
153
VFP_GEN_FIX(tosl, _round_to_zero)
154
-VFP_GEN_FIX(touh, _round_to_zero)
155
VFP_GEN_FIX(toul, _round_to_zero)
156
-VFP_GEN_FIX(shto, )
157
VFP_GEN_FIX(slto, )
158
-VFP_GEN_FIX(uhto, )
159
VFP_GEN_FIX(ulto, )
160
#undef VFP_GEN_FIX
161
162
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
163
return 1;
164
case 15:
165
switch (rn) {
166
- case 0 ... 19:
167
+ case 0 ... 23:
168
+ case 28 ... 31:
169
/* Already handled by decodetree */
170
return 1;
171
default:
172
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
173
rd_is_dp = false;
174
break;
175
176
- case 0x14: /* vcvt fp <-> fixed */
177
- case 0x15:
178
- case 0x16:
179
- case 0x17:
180
- case 0x1c:
181
- case 0x1d:
182
- case 0x1e:
183
- case 0x1f:
184
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
185
- return 1;
186
- }
187
- /* Immediate frac_bits has same format as SREG_M. */
188
- rm_is_dp = false;
189
- break;
190
-
191
default:
192
return 1;
193
}
194
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
195
/* Load the initial operands. */
196
if (op == 15) {
197
switch (rn) {
198
- case 0x14: /* vcvt fp <-> fixed */
199
- case 0x15:
200
- case 0x16:
201
- case 0x17:
202
- case 0x1c:
203
- case 0x1d:
204
- case 0x1e:
205
- case 0x1f:
206
- /* Source and destination the same. */
207
- gen_mov_F0_vreg(dp, rd);
208
- break;
209
default:
210
/* One source operand. */
211
gen_mov_F0_vreg(rm_is_dp, rm);
212
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
213
switch (op) {
214
case 15: /* extension space */
215
switch (rn) {
216
- case 20: /* fshto */
217
- gen_vfp_shto(dp, 16 - rm, 0);
218
- break;
219
- case 21: /* fslto */
220
- gen_vfp_slto(dp, 32 - rm, 0);
221
- break;
222
- case 22: /* fuhto */
223
- gen_vfp_uhto(dp, 16 - rm, 0);
224
- break;
225
- case 23: /* fulto */
226
- gen_vfp_ulto(dp, 32 - rm, 0);
227
- break;
228
case 24: /* ftoui */
229
gen_vfp_toui(dp, 0);
230
break;
231
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
232
case 27: /* ftosiz */
233
gen_vfp_tosiz(dp, 0);
234
break;
235
- case 28: /* ftosh */
236
- gen_vfp_tosh(dp, 16 - rm, 0);
237
- break;
238
- case 29: /* ftosl */
239
- gen_vfp_tosl(dp, 32 - rm, 0);
240
- break;
241
- case 30: /* ftouh */
242
- gen_vfp_touh(dp, 16 - rm, 0);
243
- break;
244
- case 31: /* ftoul */
245
- gen_vfp_toul(dp, 32 - rm, 0);
246
- break;
247
default: /* undefined */
248
g_assert_not_reached();
249
}
250
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
251
index XXXXXXX..XXXXXXX 100644
252
--- a/target/arm/vfp.decode
253
+++ b/target/arm/vfp.decode
254
@@ -XXX,XX +XXX,XX @@ VCVT_int_dp ---- 1110 1.11 1000 .... 1011 s:1 1.0 .... \
255
# VJCVT is always dp to sp
256
VJCVT ---- 1110 1.11 1001 .... 1011 11.0 .... \
257
vd=%vd_sp vm=%vm_dp
258
+
259
+# VCVT between floating-point and fixed-point. The immediate value
260
+# is in the same format as a Vm single-precision register number.
261
+# We assemble bits 18 (op), 16 (u) and 7 (sx) into a single opc field
262
+# for the convenience of the trans_VCVT_fix functions.
263
+%vcvt_fix_op 18:1 16:1 7:1
264
+VCVT_fix_sp ---- 1110 1.11 1.1. .... 1010 .1.0 .... \
265
+ vd=%vd_sp imm=%vm_sp opc=%vcvt_fix_op
266
+VCVT_fix_dp ---- 1110 1.11 1.1. .... 1011 .1.0 .... \
267
+ vd=%vd_dp imm=%vm_sp opc=%vcvt_fix_op
268
--
44
--
269
2.20.1
45
2.25.1
270
271
diff view generated by jsdifflib
1
Convert the VRINTA/VRINTN/VRINTP/VRINTM instructions to decodetree.
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
Again, trans_VRINT() is temporarily left in translate.c.
3
2
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
3
Break out header file to allow embedding of the the TTC.
4
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
8
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
9
Message-id: 20220331222017.2914409-2-edgar.iglesias@gmail.com
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
---
11
---
6
target/arm/translate.c | 60 +++++++++++++++++++++++-------------
12
include/hw/timer/cadence_ttc.h | 54 ++++++++++++++++++++++++++++++++++
7
target/arm/vfp-uncond.decode | 5 +++
13
hw/timer/cadence_ttc.c | 32 ++------------------
8
2 files changed, 43 insertions(+), 22 deletions(-)
14
2 files changed, 56 insertions(+), 30 deletions(-)
15
create mode 100644 include/hw/timer/cadence_ttc.h
9
16
10
diff --git a/target/arm/translate.c b/target/arm/translate.c
17
diff --git a/include/hw/timer/cadence_ttc.h b/include/hw/timer/cadence_ttc.h
11
index XXXXXXX..XXXXXXX 100644
18
new file mode 100644
12
--- a/target/arm/translate.c
19
index XXXXXXX..XXXXXXX
13
+++ b/target/arm/translate.c
20
--- /dev/null
14
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINMAXNM(DisasContext *s, arg_VMINMAXNM *a)
21
+++ b/include/hw/timer/cadence_ttc.h
15
return true;
22
@@ -XXX,XX +XXX,XX @@
16
}
17
18
-static int handle_vrint(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
19
- int rounding)
20
+/*
23
+/*
21
+ * Table for converting the most common AArch32 encoding of
24
+ * Xilinx Zynq cadence TTC model
22
+ * rounding mode to arm_fprounding order (which matches the
25
+ *
23
+ * common AArch64 order); see ARM ARM pseudocode FPDecodeRM().
26
+ * Copyright (c) 2011 Xilinx Inc.
27
+ * Copyright (c) 2012 Peter A.G. Crosthwaite (peter.crosthwaite@petalogix.com)
28
+ * Copyright (c) 2012 PetaLogix Pty Ltd.
29
+ * Written By Haibing Ma
30
+ * M. Habib
31
+ *
32
+ * This program is free software; you can redistribute it and/or
33
+ * modify it under the terms of the GNU General Public License
34
+ * as published by the Free Software Foundation; either version
35
+ * 2 of the License, or (at your option) any later version.
36
+ *
37
+ * You should have received a copy of the GNU General Public License along
38
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
24
+ */
39
+ */
25
+static const uint8_t fp_decode_rm[] = {
40
+#ifndef HW_TIMER_CADENCE_TTC_H
26
+ FPROUNDING_TIEAWAY,
41
+#define HW_TIMER_CADENCE_TTC_H
27
+ FPROUNDING_TIEEVEN,
42
+
28
+ FPROUNDING_POSINF,
43
+#include "hw/sysbus.h"
29
+ FPROUNDING_NEGINF,
44
+#include "qemu/timer.h"
45
+
46
+typedef struct {
47
+ QEMUTimer *timer;
48
+ int freq;
49
+
50
+ uint32_t reg_clock;
51
+ uint32_t reg_count;
52
+ uint32_t reg_value;
53
+ uint16_t reg_interval;
54
+ uint16_t reg_match[3];
55
+ uint32_t reg_intr;
56
+ uint32_t reg_intr_en;
57
+ uint32_t reg_event_ctrl;
58
+ uint32_t reg_event;
59
+
60
+ uint64_t cpu_time;
61
+ unsigned int cpu_time_valid;
62
+
63
+ qemu_irq irq;
64
+} CadenceTimerState;
65
+
66
+#define TYPE_CADENCE_TTC "cadence_ttc"
67
+OBJECT_DECLARE_SIMPLE_TYPE(CadenceTTCState, CADENCE_TTC)
68
+
69
+struct CadenceTTCState {
70
+ SysBusDevice parent_obj;
71
+
72
+ MemoryRegion iomem;
73
+ CadenceTimerState timer[3];
30
+};
74
+};
31
+
75
+
32
+static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
76
+#endif
33
{
77
diff --git a/hw/timer/cadence_ttc.c b/hw/timer/cadence_ttc.c
34
- TCGv_ptr fpst = get_fpstatus_ptr(0);
78
index XXXXXXX..XXXXXXX 100644
35
+ uint32_t rd, rm;
79
--- a/hw/timer/cadence_ttc.c
36
+ bool dp = a->dp;
80
+++ b/hw/timer/cadence_ttc.c
37
+ TCGv_ptr fpst;
81
@@ -XXX,XX +XXX,XX @@
38
TCGv_i32 tcg_rmode;
82
#include "qemu/timer.h"
39
+ int rounding = fp_decode_rm[a->rm];
83
#include "qom/object.h"
84
85
+#include "hw/timer/cadence_ttc.h"
40
+
86
+
41
+ if (!dc_isar_feature(aa32_vrint, s)) {
87
#ifdef CADENCE_TTC_ERR_DEBUG
42
+ return false;
88
#define DB_PRINT(...) do { \
43
+ }
89
fprintf(stderr, ": %s: ", __func__); \
44
+
90
@@ -XXX,XX +XXX,XX @@
45
+ /* UNDEF accesses to D16-D31 if they don't exist */
91
#define CLOCK_CTRL_PS_EN 0x00000001
46
+ if (dp && !dc_isar_feature(aa32_fp_d32, s) &&
92
#define CLOCK_CTRL_PS_V 0x0000001e
47
+ ((a->vm | a->vd) & 0x10)) {
93
48
+ return false;
94
-typedef struct {
49
+ }
95
- QEMUTimer *timer;
50
+ rd = a->vd;
96
- int freq;
51
+ rm = a->vm;
97
-
52
+
98
- uint32_t reg_clock;
53
+ if (!vfp_access_check(s)) {
99
- uint32_t reg_count;
54
+ return true;
100
- uint32_t reg_value;
55
+ }
101
- uint16_t reg_interval;
56
+
102
- uint16_t reg_match[3];
57
+ fpst = get_fpstatus_ptr(0);
103
- uint32_t reg_intr;
58
104
- uint32_t reg_intr_en;
59
tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
105
- uint32_t reg_event_ctrl;
60
gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
106
- uint32_t reg_event;
61
@@ -XXX,XX +XXX,XX @@ static int handle_vrint(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
107
-
62
tcg_temp_free_i32(tcg_rmode);
108
- uint64_t cpu_time;
63
109
- unsigned int cpu_time_valid;
64
tcg_temp_free_ptr(fpst);
110
-
65
- return 0;
111
- qemu_irq irq;
66
+ return true;
112
-} CadenceTimerState;
67
}
113
-
68
114
-#define TYPE_CADENCE_TTC "cadence_ttc"
69
static int handle_vcvt(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
115
-OBJECT_DECLARE_SIMPLE_TYPE(CadenceTTCState, CADENCE_TTC)
70
@@ -XXX,XX +XXX,XX @@ static int handle_vcvt(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
116
-
71
return 0;
117
-struct CadenceTTCState {
72
}
118
- SysBusDevice parent_obj;
73
119
-
74
-/* Table for converting the most common AArch32 encoding of
120
- MemoryRegion iomem;
75
- * rounding mode to arm_fprounding order (which matches the
121
- CadenceTimerState timer[3];
76
- * common AArch64 order); see ARM ARM pseudocode FPDecodeRM().
77
- */
78
-static const uint8_t fp_decode_rm[] = {
79
- FPROUNDING_TIEAWAY,
80
- FPROUNDING_TIEEVEN,
81
- FPROUNDING_POSINF,
82
- FPROUNDING_NEGINF,
83
-};
122
-};
84
-
123
-
85
static int disas_vfp_misc_insn(DisasContext *s, uint32_t insn)
124
static void cadence_timer_update(CadenceTimerState *s)
86
{
125
{
87
uint32_t rd, rm, dp = extract32(insn, 8, 1);
126
qemu_set_irq(s->irq, !!(s->reg_intr & s->reg_intr_en));
88
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_misc_insn(DisasContext *s, uint32_t insn)
89
rm = VFP_SREG_M(insn);
90
}
91
92
- if ((insn & 0x0fbc0ed0) == 0x0eb80a40 &&
93
- dc_isar_feature(aa32_vrint, s)) {
94
- /* VRINTA, VRINTN, VRINTP, VRINTM */
95
- int rounding = fp_decode_rm[extract32(insn, 16, 2)];
96
- return handle_vrint(insn, rd, rm, dp, rounding);
97
- } else if ((insn & 0x0fbc0e50) == 0x0ebc0a40 &&
98
- dc_isar_feature(aa32_vcvt_dr, s)) {
99
+ if ((insn & 0x0fbc0e50) == 0x0ebc0a40 &&
100
+ dc_isar_feature(aa32_vcvt_dr, s)) {
101
/* VCVTA, VCVTN, VCVTP, VCVTM */
102
int rounding = fp_decode_rm[extract32(insn, 16, 2)];
103
return handle_vcvt(insn, rd, rm, dp, rounding);
104
diff --git a/target/arm/vfp-uncond.decode b/target/arm/vfp-uncond.decode
105
index XXXXXXX..XXXXXXX 100644
106
--- a/target/arm/vfp-uncond.decode
107
+++ b/target/arm/vfp-uncond.decode
108
@@ -XXX,XX +XXX,XX @@ VMINMAXNM 1111 1110 1.00 .... .... 1010 . op:1 .0 .... \
109
vm=%vm_sp vn=%vn_sp vd=%vd_sp dp=0
110
VMINMAXNM 1111 1110 1.00 .... .... 1011 . op:1 .0 .... \
111
vm=%vm_dp vn=%vn_dp vd=%vd_dp dp=1
112
+
113
+VRINT 1111 1110 1.11 10 rm:2 .... 1010 01.0 .... \
114
+ vm=%vm_sp vd=%vd_sp dp=0
115
+VRINT 1111 1110 1.11 10 rm:2 .... 1011 01.0 .... \
116
+ vm=%vm_dp vd=%vd_dp dp=1
117
--
127
--
118
2.20.1
128
2.25.1
119
120
diff view generated by jsdifflib
1
Convert the VFP VABS instruction to decodetree.
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
2
3
Unlike the 3-op versions, we don't pass fpst to the VFPGen2OpSPFn or
3
Connect the 4 TTC timers on the ZynqMP.
4
VFPGen2OpDPFn because none of the operations which use this format
5
and support short vectors will need it.
6
4
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
6
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
7
Reviewed-by: Luc Michel <luc@lmichel.fr>
8
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
9
Message-id: 20220331222017.2914409-3-edgar.iglesias@gmail.com
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
---
11
---
10
target/arm/translate-vfp.inc.c | 167 +++++++++++++++++++++++++++++++++
12
include/hw/arm/xlnx-zynqmp.h | 4 ++++
11
target/arm/translate.c | 12 ++-
13
hw/arm/xlnx-zynqmp.c | 22 ++++++++++++++++++++++
12
target/arm/vfp.decode | 5 +
14
2 files changed, 26 insertions(+)
13
3 files changed, 180 insertions(+), 4 deletions(-)
14
15
15
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
16
diff --git a/include/hw/arm/xlnx-zynqmp.h b/include/hw/arm/xlnx-zynqmp.h
16
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
17
--- a/target/arm/translate-vfp.inc.c
18
--- a/include/hw/arm/xlnx-zynqmp.h
18
+++ b/target/arm/translate-vfp.inc.c
19
+++ b/include/hw/arm/xlnx-zynqmp.h
19
@@ -XXX,XX +XXX,XX @@ typedef void VFPGen3OpSPFn(TCGv_i32 vd,
20
@@ -XXX,XX +XXX,XX @@
20
typedef void VFPGen3OpDPFn(TCGv_i64 vd,
21
#include "hw/or-irq.h"
21
TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst);
22
#include "hw/misc/xlnx-zynqmp-apu-ctrl.h"
22
23
#include "hw/misc/xlnx-zynqmp-crf.h"
23
+/*
24
+#include "hw/timer/cadence_ttc.h"
24
+ * Types for callbacks for do_vfp_2op_sp() and do_vfp_2op_dp().
25
25
+ * The callback should emit code to write a value to vd (which
26
#define TYPE_XLNX_ZYNQMP "xlnx-zynqmp"
26
+ * should be written to only).
27
OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
27
+ */
28
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(XlnxZynqMPState, XLNX_ZYNQMP)
28
+typedef void VFPGen2OpSPFn(TCGv_i32 vd, TCGv_i32 vm);
29
#define XLNX_ZYNQMP_MAX_RAM_SIZE (XLNX_ZYNQMP_MAX_LOW_RAM_SIZE + \
29
+typedef void VFPGen2OpDPFn(TCGv_i64 vd, TCGv_i64 vm);
30
XLNX_ZYNQMP_MAX_HIGH_RAM_SIZE)
31
32
+#define XLNX_ZYNQMP_NUM_TTC 4
30
+
33
+
31
/*
34
/*
32
* Perform a 3-operand VFP data processing instruction. fn is the
35
* Unimplemented mmio regions needed to boot some images.
33
* callback to do the actual operation; this function deals with the
36
*/
34
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn,
37
@@ -XXX,XX +XXX,XX @@ struct XlnxZynqMPState {
35
return true;
38
qemu_or_irq qspi_irq_orgate;
39
XlnxZynqMPAPUCtrl apu_ctrl;
40
XlnxZynqMPCRF crf;
41
+ CadenceTTCState ttc[XLNX_ZYNQMP_NUM_TTC];
42
43
char *boot_cpu;
44
ARMCPU *boot_cpu_ptr;
45
diff --git a/hw/arm/xlnx-zynqmp.c b/hw/arm/xlnx-zynqmp.c
46
index XXXXXXX..XXXXXXX 100644
47
--- a/hw/arm/xlnx-zynqmp.c
48
+++ b/hw/arm/xlnx-zynqmp.c
49
@@ -XXX,XX +XXX,XX @@
50
#define APU_ADDR 0xfd5c0000
51
#define APU_IRQ 153
52
53
+#define TTC0_ADDR 0xFF110000
54
+#define TTC0_IRQ 36
55
+
56
#define IPI_ADDR 0xFF300000
57
#define IPI_IRQ 64
58
59
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_create_crf(XlnxZynqMPState *s, qemu_irq *gic)
60
sysbus_connect_irq(sbd, 0, gic[CRF_IRQ]);
36
}
61
}
37
62
38
+static bool do_vfp_2op_sp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm)
63
+static void xlnx_zynqmp_create_ttc(XlnxZynqMPState *s, qemu_irq *gic)
39
+{
64
+{
40
+ uint32_t delta_m = 0;
65
+ SysBusDevice *sbd;
41
+ uint32_t delta_d = 0;
66
+ int i, irq;
42
+ uint32_t bank_mask = 0;
43
+ int veclen = s->vec_len;
44
+ TCGv_i32 f0, fd;
45
+
67
+
46
+ if (!dc_isar_feature(aa32_fpshvec, s) &&
68
+ for (i = 0; i < XLNX_ZYNQMP_NUM_TTC; i++) {
47
+ (veclen != 0 || s->vec_stride != 0)) {
69
+ object_initialize_child(OBJECT(s), "ttc[*]", &s->ttc[i],
48
+ return false;
70
+ TYPE_CADENCE_TTC);
49
+ }
71
+ sbd = SYS_BUS_DEVICE(&s->ttc[i]);
50
+
72
+
51
+ if (!vfp_access_check(s)) {
73
+ sysbus_realize(sbd, &error_fatal);
52
+ return true;
74
+ sysbus_mmio_map(sbd, 0, TTC0_ADDR + i * 0x10000);
53
+ }
75
+ for (irq = 0; irq < 3; irq++) {
54
+
76
+ sysbus_connect_irq(sbd, irq, gic[TTC0_IRQ + i * 3 + irq]);
55
+ if (veclen > 0) {
56
+ bank_mask = 0x18;
57
+
58
+ /* Figure out what type of vector operation this is. */
59
+ if ((vd & bank_mask) == 0) {
60
+ /* scalar */
61
+ veclen = 0;
62
+ } else {
63
+ delta_d = s->vec_stride + 1;
64
+
65
+ if ((vm & bank_mask) == 0) {
66
+ /* mixed scalar/vector */
67
+ delta_m = 0;
68
+ } else {
69
+ /* vector */
70
+ delta_m = delta_d;
71
+ }
72
+ }
77
+ }
73
+ }
78
+ }
74
+
75
+ f0 = tcg_temp_new_i32();
76
+ fd = tcg_temp_new_i32();
77
+
78
+ neon_load_reg32(f0, vm);
79
+
80
+ for (;;) {
81
+ fn(fd, f0);
82
+ neon_store_reg32(fd, vd);
83
+
84
+ if (veclen == 0) {
85
+ break;
86
+ }
87
+
88
+ if (delta_m == 0) {
89
+ /* single source one-many */
90
+ while (veclen--) {
91
+ vd = ((vd + delta_d) & (bank_mask - 1)) | (vd & bank_mask);
92
+ neon_store_reg32(fd, vd);
93
+ }
94
+ break;
95
+ }
96
+
97
+ /* Set up the operands for the next iteration */
98
+ veclen--;
99
+ vd = ((vd + delta_d) & (bank_mask - 1)) | (vd & bank_mask);
100
+ vm = ((vm + delta_m) & (bank_mask - 1)) | (vm & bank_mask);
101
+ neon_load_reg32(f0, vm);
102
+ }
103
+
104
+ tcg_temp_free_i32(f0);
105
+ tcg_temp_free_i32(fd);
106
+
107
+ return true;
108
+}
79
+}
109
+
80
+
110
+static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm)
81
static void xlnx_zynqmp_create_unimp_mmio(XlnxZynqMPState *s)
111
+{
112
+ uint32_t delta_m = 0;
113
+ uint32_t delta_d = 0;
114
+ uint32_t bank_mask = 0;
115
+ int veclen = s->vec_len;
116
+ TCGv_i64 f0, fd;
117
+
118
+ /* UNDEF accesses to D16-D31 if they don't exist */
119
+ if (!dc_isar_feature(aa32_fp_d32, s) && ((vd | vm) & 0x10)) {
120
+ return false;
121
+ }
122
+
123
+ if (!dc_isar_feature(aa32_fpshvec, s) &&
124
+ (veclen != 0 || s->vec_stride != 0)) {
125
+ return false;
126
+ }
127
+
128
+ if (!vfp_access_check(s)) {
129
+ return true;
130
+ }
131
+
132
+ if (veclen > 0) {
133
+ bank_mask = 0xc;
134
+
135
+ /* Figure out what type of vector operation this is. */
136
+ if ((vd & bank_mask) == 0) {
137
+ /* scalar */
138
+ veclen = 0;
139
+ } else {
140
+ delta_d = (s->vec_stride >> 1) + 1;
141
+
142
+ if ((vm & bank_mask) == 0) {
143
+ /* mixed scalar/vector */
144
+ delta_m = 0;
145
+ } else {
146
+ /* vector */
147
+ delta_m = delta_d;
148
+ }
149
+ }
150
+ }
151
+
152
+ f0 = tcg_temp_new_i64();
153
+ fd = tcg_temp_new_i64();
154
+
155
+ neon_load_reg64(f0, vm);
156
+
157
+ for (;;) {
158
+ fn(fd, f0);
159
+ neon_store_reg64(fd, vd);
160
+
161
+ if (veclen == 0) {
162
+ break;
163
+ }
164
+
165
+ if (delta_m == 0) {
166
+ /* single source one-many */
167
+ while (veclen--) {
168
+ vd = ((vd + delta_d) & (bank_mask - 1)) | (vd & bank_mask);
169
+ neon_store_reg64(fd, vd);
170
+ }
171
+ break;
172
+ }
173
+
174
+ /* Set up the operands for the next iteration */
175
+ veclen--;
176
+ vd = ((vd + delta_d) & (bank_mask - 1)) | (vd & bank_mask);
177
+ vm = ((vm + delta_m) & (bank_mask - 1)) | (vm & bank_mask);
178
+ neon_load_reg64(f0, vm);
179
+ }
180
+
181
+ tcg_temp_free_i64(f0);
182
+ tcg_temp_free_i64(fd);
183
+
184
+ return true;
185
+}
186
+
187
static void gen_VMLA_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
188
{
82
{
189
/* Note that order of inputs to the add matters for NaNs */
83
static const struct UnimpInfo {
190
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
84
@@ -XXX,XX +XXX,XX @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
191
tcg_temp_free_i64(fd);
85
xlnx_zynqmp_create_efuse(s, gic_spi);
192
return true;
86
xlnx_zynqmp_create_apu_ctrl(s, gic_spi);
193
}
87
xlnx_zynqmp_create_crf(s, gic_spi);
194
+
88
+ xlnx_zynqmp_create_ttc(s, gic_spi);
195
+static bool trans_VABS_sp(DisasContext *s, arg_VABS_sp *a)
89
xlnx_zynqmp_create_unimp_mmio(s);
196
+{
90
197
+ return do_vfp_2op_sp(s, gen_helper_vfp_abss, a->vd, a->vm);
91
for (i = 0; i < XLNX_ZYNQMP_NUM_GDMA_CH; i++) {
198
+}
199
+
200
+static bool trans_VABS_dp(DisasContext *s, arg_VABS_dp *a)
201
+{
202
+ return do_vfp_2op_dp(s, gen_helper_vfp_absd, a->vd, a->vm);
203
+}
204
diff --git a/target/arm/translate.c b/target/arm/translate.c
205
index XXXXXXX..XXXXXXX 100644
206
--- a/target/arm/translate.c
207
+++ b/target/arm/translate.c
208
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
209
case 0 ... 14:
210
/* Already handled by decodetree */
211
return 1;
212
+ case 15:
213
+ switch (rn) {
214
+ case 1:
215
+ /* Already handled by decodetree */
216
+ return 1;
217
+ default:
218
+ break;
219
+ }
220
default:
221
break;
222
}
223
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
224
/* rn is opcode, encoded as per VFP_SREG_N. */
225
switch (rn) {
226
case 0x00: /* vmov */
227
- case 0x01: /* vabs */
228
case 0x02: /* vneg */
229
case 0x03: /* vsqrt */
230
break;
231
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
232
case 0: /* cpy */
233
/* no-op */
234
break;
235
- case 1: /* abs */
236
- gen_vfp_abs(dp);
237
- break;
238
case 2: /* neg */
239
gen_vfp_neg(dp);
240
break;
241
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
242
index XXXXXXX..XXXXXXX 100644
243
--- a/target/arm/vfp.decode
244
+++ b/target/arm/vfp.decode
245
@@ -XXX,XX +XXX,XX @@ VMOV_imm_sp ---- 1110 1.11 imm4h:4 .... 1010 0000 imm4l:4 \
246
vd=%vd_sp
247
VMOV_imm_dp ---- 1110 1.11 imm4h:4 .... 1011 0000 imm4l:4 \
248
vd=%vd_dp
249
+
250
+VABS_sp ---- 1110 1.11 0000 .... 1010 11.0 .... \
251
+ vd=%vd_sp vm=%vm_sp
252
+VABS_dp ---- 1110 1.11 0000 .... 1011 11.0 .... \
253
+ vd=%vd_dp vm=%vm_dp
254
--
92
--
255
2.20.1
93
2.25.1
256
257
diff view generated by jsdifflib
1
The NSACR register allows secure code to configure the FPU
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
to be inaccessible to non-secure code. If the NSACR.CP10
3
bit is set then:
4
* NS accesses to the FPU trap as UNDEF (ie to NS EL1 or EL2)
5
* CPACR.{CP10,CP11} behave as if RAZ/WI
6
* HCPTR.{TCP11,TCP10} behave as if RAO/WI
7
2
8
Note that we do not implement the NSACR.NSASEDIS bit which
3
Create an APU CPU Cluster. This is in preparation to add the RPU.
9
gates only access to Advanced SIMD, in the same way that
10
we don't implement the equivalent CPACR.ASEDIS and HCPTR.TASE.
11
4
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
6
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
7
Message-id: 20220406174303.2022038-2-edgar.iglesias@xilinx.com
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Message-id: 20190510110357.18825-1-peter.maydell@linaro.org
15
---
9
---
16
target/arm/helper.c | 75 +++++++++++++++++++++++++++++++++++++++++++--
10
include/hw/arm/xlnx-versal.h | 2 ++
17
1 file changed, 73 insertions(+), 2 deletions(-)
11
hw/arm/xlnx-versal.c | 9 ++++++++-
12
2 files changed, 10 insertions(+), 1 deletion(-)
18
13
19
diff --git a/target/arm/helper.c b/target/arm/helper.c
14
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
20
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/helper.c
16
--- a/include/hw/arm/xlnx-versal.h
22
+++ b/target/arm/helper.c
17
+++ b/include/hw/arm/xlnx-versal.h
23
@@ -XXX,XX +XXX,XX @@ static void cpacr_write(CPUARMState *env, const ARMCPRegInfo *ri,
18
@@ -XXX,XX +XXX,XX @@
24
}
19
25
value &= mask;
20
#include "hw/sysbus.h"
21
#include "hw/arm/boot.h"
22
+#include "hw/cpu/cluster.h"
23
#include "hw/or-irq.h"
24
#include "hw/sd/sdhci.h"
25
#include "hw/intc/arm_gicv3.h"
26
@@ -XXX,XX +XXX,XX @@ struct Versal {
27
struct {
28
struct {
29
MemoryRegion mr;
30
+ CPUClusterState cluster;
31
ARMCPU cpu[XLNX_VERSAL_NR_ACPUS];
32
GICv3State gic;
33
} apu;
34
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/hw/arm/xlnx-versal.c
37
+++ b/hw/arm/xlnx-versal.c
38
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_cpus(Versal *s)
39
{
40
int i;
41
42
+ object_initialize_child(OBJECT(s), "apu-cluster", &s->fpd.apu.cluster,
43
+ TYPE_CPU_CLUSTER);
44
+ qdev_prop_set_uint32(DEVICE(&s->fpd.apu.cluster), "cluster-id", 0);
45
+
46
for (i = 0; i < ARRAY_SIZE(s->fpd.apu.cpu); i++) {
47
Object *obj;
48
49
- object_initialize_child(OBJECT(s), "apu-cpu[*]", &s->fpd.apu.cpu[i],
50
+ object_initialize_child(OBJECT(&s->fpd.apu.cluster),
51
+ "apu-cpu[*]", &s->fpd.apu.cpu[i],
52
XLNX_VERSAL_ACPU_TYPE);
53
obj = OBJECT(&s->fpd.apu.cpu[i]);
54
if (i) {
55
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_cpus(Versal *s)
56
&error_abort);
57
qdev_realize(DEVICE(obj), NULL, &error_fatal);
26
}
58
}
27
+
59
+
28
+ /*
60
+ qdev_realize(DEVICE(&s->fpd.apu.cluster), NULL, &error_fatal);
29
+ * For A-profile AArch32 EL3 (but not M-profile secure mode), if NSACR.CP10
30
+ * is 0 then CPACR.{CP11,CP10} ignore writes and read as 0b00.
31
+ */
32
+ if (arm_feature(env, ARM_FEATURE_EL3) && !arm_el_is_aa64(env, 3) &&
33
+ !arm_is_secure(env) && !extract32(env->cp15.nsacr, 10, 1)) {
34
+ value &= ~(0xf << 20);
35
+ value |= env->cp15.cpacr_el1 & (0xf << 20);
36
+ }
37
+
38
env->cp15.cpacr_el1 = value;
39
}
61
}
40
62
41
+static uint64_t cpacr_read(CPUARMState *env, const ARMCPRegInfo *ri)
63
static void versal_create_apu_gic(Versal *s, qemu_irq *pic)
42
+{
43
+ /*
44
+ * For A-profile AArch32 EL3 (but not M-profile secure mode), if NSACR.CP10
45
+ * is 0 then CPACR.{CP11,CP10} ignore writes and read as 0b00.
46
+ */
47
+ uint64_t value = env->cp15.cpacr_el1;
48
+
49
+ if (arm_feature(env, ARM_FEATURE_EL3) && !arm_el_is_aa64(env, 3) &&
50
+ !arm_is_secure(env) && !extract32(env->cp15.nsacr, 10, 1)) {
51
+ value &= ~(0xf << 20);
52
+ }
53
+ return value;
54
+}
55
+
56
+
57
static void cpacr_reset(CPUARMState *env, const ARMCPRegInfo *ri)
58
{
59
/* Call cpacr_write() so that we reset with the correct RAO bits set
60
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo v6_cp_reginfo[] = {
61
{ .name = "CPACR", .state = ARM_CP_STATE_BOTH, .opc0 = 3,
62
.crn = 1, .crm = 0, .opc1 = 0, .opc2 = 2, .accessfn = cpacr_access,
63
.access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.cpacr_el1),
64
- .resetfn = cpacr_reset, .writefn = cpacr_write },
65
+ .resetfn = cpacr_reset, .writefn = cpacr_write, .readfn = cpacr_read },
66
REGINFO_SENTINEL
67
};
68
69
@@ -XXX,XX +XXX,XX @@ uint64_t arm_hcr_el2_eff(CPUARMState *env)
70
return ret;
71
}
72
73
+static void cptr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
74
+ uint64_t value)
75
+{
76
+ /*
77
+ * For A-profile AArch32 EL3, if NSACR.CP10
78
+ * is 0 then HCPTR.{TCP11,TCP10} ignore writes and read as 1.
79
+ */
80
+ if (arm_feature(env, ARM_FEATURE_EL3) && !arm_el_is_aa64(env, 3) &&
81
+ !arm_is_secure(env) && !extract32(env->cp15.nsacr, 10, 1)) {
82
+ value &= ~(0x3 << 10);
83
+ value |= env->cp15.cptr_el[2] & (0x3 << 10);
84
+ }
85
+ env->cp15.cptr_el[2] = value;
86
+}
87
+
88
+static uint64_t cptr_el2_read(CPUARMState *env, const ARMCPRegInfo *ri)
89
+{
90
+ /*
91
+ * For A-profile AArch32 EL3, if NSACR.CP10
92
+ * is 0 then HCPTR.{TCP11,TCP10} ignore writes and read as 1.
93
+ */
94
+ uint64_t value = env->cp15.cptr_el[2];
95
+
96
+ if (arm_feature(env, ARM_FEATURE_EL3) && !arm_el_is_aa64(env, 3) &&
97
+ !arm_is_secure(env) && !extract32(env->cp15.nsacr, 10, 1)) {
98
+ value |= 0x3 << 10;
99
+ }
100
+ return value;
101
+}
102
+
103
static const ARMCPRegInfo el2_cp_reginfo[] = {
104
{ .name = "HCR_EL2", .state = ARM_CP_STATE_AA64,
105
.type = ARM_CP_IO,
106
@@ -XXX,XX +XXX,XX @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
107
{ .name = "CPTR_EL2", .state = ARM_CP_STATE_BOTH,
108
.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 2,
109
.access = PL2_RW, .accessfn = cptr_access, .resetvalue = 0,
110
- .fieldoffset = offsetof(CPUARMState, cp15.cptr_el[2]) },
111
+ .fieldoffset = offsetof(CPUARMState, cp15.cptr_el[2]),
112
+ .readfn = cptr_el2_read, .writefn = cptr_el2_write },
113
{ .name = "MAIR_EL2", .state = ARM_CP_STATE_BOTH,
114
.opc0 = 3, .opc1 = 4, .crn = 10, .crm = 2, .opc2 = 0,
115
.access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.mair_el[2]),
116
@@ -XXX,XX +XXX,XX @@ int fp_exception_el(CPUARMState *env, int cur_el)
117
break;
118
}
119
120
+ /*
121
+ * The NSACR allows A-profile AArch32 EL3 and M-profile secure mode
122
+ * to control non-secure access to the FPU. It doesn't have any
123
+ * effect if EL3 is AArch64 or if EL3 doesn't exist at all.
124
+ */
125
+ if ((arm_feature(env, ARM_FEATURE_EL3) && !arm_el_is_aa64(env, 3) &&
126
+ cur_el <= 2 && !arm_is_secure_below_el3(env))) {
127
+ if (!extract32(env->cp15.nsacr, 10, 1)) {
128
+ /* FP insns act as UNDEF */
129
+ return cur_el == 2 ? 2 : 1;
130
+ }
131
+ }
132
+
133
/* For the CPTR registers we don't need to guard with an ARM_FEATURE
134
* check because zero bits in the registers mean "don't trap".
135
*/
136
--
64
--
137
2.20.1
65
2.25.1
138
139
diff view generated by jsdifflib
1
Convert the VFP comparison instructions to decodetree.
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
2
3
Note that comparison instructions should not honour the VFP
3
Add the Cortex-R5Fs of the Versal RPU (Real-time Processing Unit)
4
short-vector length and stride information: they are scalar-only
4
subsystem.
5
operations. This applies to all the 2-operand instructions except
6
for VMOV, VABS, VNEG and VSQRT. (In the old decoder this is
7
implemented via the "if (op == 15 && rn > 3) { veclen = 0; }" check.)
8
5
6
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
8
Message-id: 20220406174303.2022038-3-edgar.iglesias@xilinx.com
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
---
10
---
12
target/arm/translate-vfp.inc.c | 75 ++++++++++++++++++++++++++++++++++
11
include/hw/arm/xlnx-versal.h | 10 ++++++++++
13
target/arm/translate.c | 51 +----------------------
12
hw/arm/xlnx-versal-virt.c | 6 +++---
14
target/arm/vfp.decode | 5 +++
13
hw/arm/xlnx-versal.c | 36 ++++++++++++++++++++++++++++++++++++
15
3 files changed, 81 insertions(+), 50 deletions(-)
14
3 files changed, 49 insertions(+), 3 deletions(-)
16
15
17
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
16
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
18
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/translate-vfp.inc.c
18
--- a/include/hw/arm/xlnx-versal.h
20
+++ b/target/arm/translate-vfp.inc.c
19
+++ b/include/hw/arm/xlnx-versal.h
21
@@ -XXX,XX +XXX,XX @@ static bool trans_VSQRT_dp(DisasContext *s, arg_VSQRT_dp *a)
20
@@ -XXX,XX +XXX,XX @@
22
{
21
OBJECT_DECLARE_SIMPLE_TYPE(Versal, XLNX_VERSAL)
23
return do_vfp_2op_dp(s, gen_VSQRT_dp, a->vd, a->vm);
22
23
#define XLNX_VERSAL_NR_ACPUS 2
24
+#define XLNX_VERSAL_NR_RCPUS 2
25
#define XLNX_VERSAL_NR_UARTS 2
26
#define XLNX_VERSAL_NR_GEMS 2
27
#define XLNX_VERSAL_NR_ADMAS 8
28
@@ -XXX,XX +XXX,XX @@ struct Versal {
29
VersalUsb2 usb;
30
} iou;
31
32
+ /* Real-time Processing Unit. */
33
+ struct {
34
+ MemoryRegion mr;
35
+ MemoryRegion mr_ps_alias;
36
+
37
+ CPUClusterState cluster;
38
+ ARMCPU cpu[XLNX_VERSAL_NR_RCPUS];
39
+ } rpu;
40
+
41
struct {
42
qemu_or_irq irq_orgate;
43
XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM];
44
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/arm/xlnx-versal-virt.c
47
+++ b/hw/arm/xlnx-versal-virt.c
48
@@ -XXX,XX +XXX,XX @@ static void versal_virt_machine_class_init(ObjectClass *oc, void *data)
49
50
mc->desc = "Xilinx Versal Virtual development board";
51
mc->init = versal_virt_init;
52
- mc->min_cpus = XLNX_VERSAL_NR_ACPUS;
53
- mc->max_cpus = XLNX_VERSAL_NR_ACPUS;
54
- mc->default_cpus = XLNX_VERSAL_NR_ACPUS;
55
+ mc->min_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
56
+ mc->max_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
57
+ mc->default_cpus = XLNX_VERSAL_NR_ACPUS + XLNX_VERSAL_NR_RCPUS;
58
mc->no_cdrom = true;
59
mc->default_ram_id = "ddr";
24
}
60
}
61
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
62
index XXXXXXX..XXXXXXX 100644
63
--- a/hw/arm/xlnx-versal.c
64
+++ b/hw/arm/xlnx-versal.c
65
@@ -XXX,XX +XXX,XX @@
66
#include "hw/sysbus.h"
67
68
#define XLNX_VERSAL_ACPU_TYPE ARM_CPU_TYPE_NAME("cortex-a72")
69
+#define XLNX_VERSAL_RCPU_TYPE ARM_CPU_TYPE_NAME("cortex-r5f")
70
#define GEM_REVISION 0x40070106
71
72
#define VERSAL_NUM_PMC_APB_IRQS 3
73
@@ -XXX,XX +XXX,XX @@ static void versal_create_apu_gic(Versal *s, qemu_irq *pic)
74
}
75
}
76
77
+static void versal_create_rpu_cpus(Versal *s)
78
+{
79
+ int i;
25
+
80
+
26
+static bool trans_VCMP_sp(DisasContext *s, arg_VCMP_sp *a)
81
+ object_initialize_child(OBJECT(s), "rpu-cluster", &s->lpd.rpu.cluster,
27
+{
82
+ TYPE_CPU_CLUSTER);
28
+ TCGv_i32 vd, vm;
83
+ qdev_prop_set_uint32(DEVICE(&s->lpd.rpu.cluster), "cluster-id", 1);
29
+
84
+
30
+ /* Vm/M bits must be zero for the Z variant */
85
+ for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) {
31
+ if (a->z && a->vm != 0) {
86
+ Object *obj;
32
+ return false;
87
+
88
+ object_initialize_child(OBJECT(&s->lpd.rpu.cluster),
89
+ "rpu-cpu[*]", &s->lpd.rpu.cpu[i],
90
+ XLNX_VERSAL_RCPU_TYPE);
91
+ obj = OBJECT(&s->lpd.rpu.cpu[i]);
92
+ object_property_set_bool(obj, "start-powered-off", true,
93
+ &error_abort);
94
+
95
+ object_property_set_int(obj, "mp-affinity", 0x100 | i, &error_abort);
96
+ object_property_set_int(obj, "core-count", ARRAY_SIZE(s->lpd.rpu.cpu),
97
+ &error_abort);
98
+ object_property_set_link(obj, "memory", OBJECT(&s->lpd.rpu.mr),
99
+ &error_abort);
100
+ qdev_realize(DEVICE(obj), NULL, &error_fatal);
33
+ }
101
+ }
34
+
102
+
35
+ if (!vfp_access_check(s)) {
103
+ qdev_realize(DEVICE(&s->lpd.rpu.cluster), NULL, &error_fatal);
36
+ return true;
37
+ }
38
+
39
+ vd = tcg_temp_new_i32();
40
+ vm = tcg_temp_new_i32();
41
+
42
+ neon_load_reg32(vd, a->vd);
43
+ if (a->z) {
44
+ tcg_gen_movi_i32(vm, 0);
45
+ } else {
46
+ neon_load_reg32(vm, a->vm);
47
+ }
48
+
49
+ if (a->e) {
50
+ gen_helper_vfp_cmpes(vd, vm, cpu_env);
51
+ } else {
52
+ gen_helper_vfp_cmps(vd, vm, cpu_env);
53
+ }
54
+
55
+ tcg_temp_free_i32(vd);
56
+ tcg_temp_free_i32(vm);
57
+
58
+ return true;
59
+}
104
+}
60
+
105
+
61
+static bool trans_VCMP_dp(DisasContext *s, arg_VCMP_dp *a)
106
static void versal_create_uarts(Versal *s, qemu_irq *pic)
62
+{
107
{
63
+ TCGv_i64 vd, vm;
108
int i;
64
+
109
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
65
+ /* Vm/M bits must be zero for the Z variant */
110
66
+ if (a->z && a->vm != 0) {
111
versal_create_apu_cpus(s);
67
+ return false;
112
versal_create_apu_gic(s, pic);
68
+ }
113
+ versal_create_rpu_cpus(s);
69
+
114
versal_create_uarts(s, pic);
70
+ /* UNDEF accesses to D16-D31 if they don't exist. */
115
versal_create_usbs(s, pic);
71
+ if (!dc_isar_feature(aa32_fp_d32, s) && ((a->vd | a->vm) & 0x10)) {
116
versal_create_gems(s, pic);
72
+ return false;
117
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
73
+ }
118
74
+
119
memory_region_add_subregion_overlap(&s->mr_ps, MM_OCM, &s->lpd.mr_ocm, 0);
75
+ if (!vfp_access_check(s)) {
120
memory_region_add_subregion_overlap(&s->fpd.apu.mr, 0, &s->mr_ps, 0);
76
+ return true;
121
+ memory_region_add_subregion_overlap(&s->lpd.rpu.mr, 0,
77
+ }
122
+ &s->lpd.rpu.mr_ps_alias, 0);
78
+
79
+ vd = tcg_temp_new_i64();
80
+ vm = tcg_temp_new_i64();
81
+
82
+ neon_load_reg64(vd, a->vd);
83
+ if (a->z) {
84
+ tcg_gen_movi_i64(vm, 0);
85
+ } else {
86
+ neon_load_reg64(vm, a->vm);
87
+ }
88
+
89
+ if (a->e) {
90
+ gen_helper_vfp_cmped(vd, vm, cpu_env);
91
+ } else {
92
+ gen_helper_vfp_cmpd(vd, vm, cpu_env);
93
+ }
94
+
95
+ tcg_temp_free_i64(vd);
96
+ tcg_temp_free_i64(vm);
97
+
98
+ return true;
99
+}
100
diff --git a/target/arm/translate.c b/target/arm/translate.c
101
index XXXXXXX..XXXXXXX 100644
102
--- a/target/arm/translate.c
103
+++ b/target/arm/translate.c
104
@@ -XXX,XX +XXX,XX @@ static inline void gen_vfp_neg(int dp)
105
gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
106
}
123
}
107
124
108
-static inline void gen_vfp_cmp(int dp)
125
static void versal_init(Object *obj)
109
-{
126
@@ -XXX,XX +XXX,XX @@ static void versal_init(Object *obj)
110
- if (dp)
127
Versal *s = XLNX_VERSAL(obj);
111
- gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
128
112
- else
129
memory_region_init(&s->fpd.apu.mr, obj, "mr-apu", UINT64_MAX);
113
- gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
130
+ memory_region_init(&s->lpd.rpu.mr, obj, "mr-rpu", UINT64_MAX);
114
-}
131
memory_region_init(&s->mr_ps, obj, "mr-ps-switch", UINT64_MAX);
115
-
132
+ memory_region_init_alias(&s->lpd.rpu.mr_ps_alias, OBJECT(s),
116
-static inline void gen_vfp_cmpe(int dp)
133
+ "mr-rpu-ps-alias", &s->mr_ps, 0, UINT64_MAX);
117
-{
134
}
118
- if (dp)
135
119
- gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
136
static Property versal_properties[] = {
120
- else
121
- gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
122
-}
123
-
124
-static inline void gen_vfp_F1_ld0(int dp)
125
-{
126
- if (dp)
127
- tcg_gen_movi_i64(cpu_F1d, 0);
128
- else
129
- tcg_gen_movi_i32(cpu_F1s, 0);
130
-}
131
-
132
#define VFP_GEN_ITOF(name) \
133
static inline void gen_vfp_##name(int dp, int neon) \
134
{ \
135
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
136
case 15:
137
switch (rn) {
138
case 0 ... 3:
139
+ case 8 ... 11:
140
/* Already handled by decodetree */
141
return 1;
142
default:
143
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
144
rd_is_dp = false;
145
break;
146
147
- case 0x08: case 0x0a: /* vcmp, vcmpz */
148
- case 0x09: case 0x0b: /* vcmpe, vcmpez */
149
- no_output = true;
150
- break;
151
-
152
case 0x0c: /* vrintr */
153
case 0x0d: /* vrintz */
154
case 0x0e: /* vrintx */
155
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
156
/* Load the initial operands. */
157
if (op == 15) {
158
switch (rn) {
159
- case 0x08: case 0x09: /* Compare */
160
- gen_mov_F0_vreg(dp, rd);
161
- gen_mov_F1_vreg(dp, rm);
162
- break;
163
- case 0x0a: case 0x0b: /* Compare with zero */
164
- gen_mov_F0_vreg(dp, rd);
165
- gen_vfp_F1_ld0(dp);
166
- break;
167
case 0x14: /* vcvt fp <-> fixed */
168
case 0x15:
169
case 0x16:
170
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
171
gen_vfp_msr(tmp);
172
break;
173
}
174
- case 8: /* cmp */
175
- gen_vfp_cmp(dp);
176
- break;
177
- case 9: /* cmpe */
178
- gen_vfp_cmpe(dp);
179
- break;
180
- case 10: /* cmpz */
181
- gen_vfp_cmp(dp);
182
- break;
183
- case 11: /* cmpez */
184
- gen_vfp_F1_ld0(dp);
185
- gen_vfp_cmpe(dp);
186
- break;
187
case 12: /* vrintr */
188
{
189
TCGv_ptr fpst = get_fpstatus_ptr(0);
190
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
191
index XXXXXXX..XXXXXXX 100644
192
--- a/target/arm/vfp.decode
193
+++ b/target/arm/vfp.decode
194
@@ -XXX,XX +XXX,XX @@ VSQRT_sp ---- 1110 1.11 0001 .... 1010 11.0 .... \
195
vd=%vd_sp vm=%vm_sp
196
VSQRT_dp ---- 1110 1.11 0001 .... 1011 11.0 .... \
197
vd=%vd_dp vm=%vm_dp
198
+
199
+VCMP_sp ---- 1110 1.11 010 z:1 .... 1010 e:1 1.0 .... \
200
+ vd=%vd_sp vm=%vm_sp
201
+VCMP_dp ---- 1110 1.11 010 z:1 .... 1011 e:1 1.0 .... \
202
+ vd=%vd_dp vm=%vm_dp
203
--
137
--
204
2.20.1
138
2.25.1
205
206
diff view generated by jsdifflib
1
Add the infrastructure for building and invoking a decodetree decoder
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
for the AArch32 VFP encodings. At the moment the new decoder covers
3
nothing, so we always fall back to the existing hand-written decode.
4
2
5
We need to have one decoder for the unconditional insns and one for
3
Add a model of the Xilinx Versal CRL.
6
the conditional insns, as otherwise the patterns for conditional
7
insns would incorrectly match against the unconditional ones too.
8
4
9
Since translate.c is over 14,000 lines long and we're going to be
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
10
touching pretty much every line of the VFP code as part of the
6
Reviewed-by: Frederic Konrad <fkonrad@amd.com>
11
decodetree conversion, we create a new translate-vfp.inc.c to hold
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
12
the code which deals with VFP in the new scheme. It should be
8
Message-id: 20220406174303.2022038-4-edgar.iglesias@xilinx.com
13
possible to convert this into a standalone translation unit
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
eventually, but the conversion process will be much simpler if we
10
---
15
simply #include it midway through translate.c to start with.
11
include/hw/misc/xlnx-versal-crl.h | 235 +++++++++++++++++
12
hw/misc/xlnx-versal-crl.c | 421 ++++++++++++++++++++++++++++++
13
hw/misc/meson.build | 1 +
14
3 files changed, 657 insertions(+)
15
create mode 100644 include/hw/misc/xlnx-versal-crl.h
16
create mode 100644 hw/misc/xlnx-versal-crl.c
16
17
17
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
18
diff --git a/include/hw/misc/xlnx-versal-crl.h b/include/hw/misc/xlnx-versal-crl.h
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
---
20
target/arm/Makefile.objs | 13 +++++++++++++
21
target/arm/translate-vfp.inc.c | 31 +++++++++++++++++++++++++++++++
22
target/arm/translate.c | 19 +++++++++++++++++++
23
target/arm/vfp-uncond.decode | 28 ++++++++++++++++++++++++++++
24
target/arm/vfp.decode | 28 ++++++++++++++++++++++++++++
25
5 files changed, 119 insertions(+)
26
create mode 100644 target/arm/translate-vfp.inc.c
27
create mode 100644 target/arm/vfp-uncond.decode
28
create mode 100644 target/arm/vfp.decode
29
30
diff --git a/target/arm/Makefile.objs b/target/arm/Makefile.objs
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/Makefile.objs
33
+++ b/target/arm/Makefile.objs
34
@@ -XXX,XX +XXX,XX @@ target/arm/decode-sve.inc.c: $(SRC_PATH)/target/arm/sve.decode $(DECODETREE)
35
     $(PYTHON) $(DECODETREE) --decode disas_sve -o $@ $<,\
36
     "GEN", $(TARGET_DIR)$@)
37
38
+target/arm/decode-vfp.inc.c: $(SRC_PATH)/target/arm/vfp.decode $(DECODETREE)
39
+    $(call quiet-command,\
40
+     $(PYTHON) $(DECODETREE) --static-decode disas_vfp -o $@ $<,\
41
+     "GEN", $(TARGET_DIR)$@)
42
+
43
+target/arm/decode-vfp-uncond.inc.c: $(SRC_PATH)/target/arm/vfp-uncond.decode $(DECODETREE)
44
+    $(call quiet-command,\
45
+     $(PYTHON) $(DECODETREE) --static-decode disas_vfp_uncond -o $@ $<,\
46
+     "GEN", $(TARGET_DIR)$@)
47
+
48
target/arm/translate-sve.o: target/arm/decode-sve.inc.c
49
+target/arm/translate.o: target/arm/decode-vfp.inc.c
50
+target/arm/translate.o: target/arm/decode-vfp-uncond.inc.c
51
+
52
obj-$(TARGET_AARCH64) += translate-sve.o sve_helper.o
53
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
54
new file mode 100644
19
new file mode 100644
55
index XXXXXXX..XXXXXXX
20
index XXXXXXX..XXXXXXX
56
--- /dev/null
21
--- /dev/null
57
+++ b/target/arm/translate-vfp.inc.c
22
+++ b/include/hw/misc/xlnx-versal-crl.h
58
@@ -XXX,XX +XXX,XX @@
23
@@ -XXX,XX +XXX,XX @@
59
+/*
24
+/*
60
+ * ARM translation: AArch32 VFP instructions
25
+ * QEMU model of the Clock-Reset-LPD (CRL).
61
+ *
26
+ *
62
+ * Copyright (c) 2003 Fabrice Bellard
27
+ * Copyright (c) 2022 Xilinx Inc.
63
+ * Copyright (c) 2005-2007 CodeSourcery
28
+ * SPDX-License-Identifier: GPL-2.0-or-later
64
+ * Copyright (c) 2007 OpenedHand, Ltd.
65
+ * Copyright (c) 2019 Linaro, Ltd.
66
+ *
29
+ *
67
+ * This library is free software; you can redistribute it and/or
30
+ * Written by Edgar E. Iglesias <edgar.iglesias@xilinx.com>
68
+ * modify it under the terms of the GNU Lesser General Public
69
+ * License as published by the Free Software Foundation; either
70
+ * version 2 of the License, or (at your option) any later version.
71
+ *
72
+ * This library 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 GNU
75
+ * Lesser General Public License for more details.
76
+ *
77
+ * You should have received a copy of the GNU Lesser General Public
78
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
79
+ */
31
+ */
80
+
32
+#ifndef HW_MISC_XLNX_VERSAL_CRL_H
81
+/*
33
+#define HW_MISC_XLNX_VERSAL_CRL_H
82
+ * This file is intended to be included from translate.c; it uses
34
+
83
+ * some macros and definitions provided by that file.
35
+#include "hw/sysbus.h"
84
+ * It might be possible to convert it to a standalone .c file eventually.
36
+#include "hw/register.h"
85
+ */
37
+#include "target/arm/cpu.h"
86
+
38
+
87
+/* Include the generated VFP decoder */
39
+#define TYPE_XLNX_VERSAL_CRL "xlnx,versal-crl"
88
+#include "decode-vfp.inc.c"
40
+OBJECT_DECLARE_SIMPLE_TYPE(XlnxVersalCRL, XLNX_VERSAL_CRL)
89
+#include "decode-vfp-uncond.inc.c"
41
+
90
diff --git a/target/arm/translate.c b/target/arm/translate.c
42
+REG32(ERR_CTRL, 0x0)
91
index XXXXXXX..XXXXXXX 100644
43
+ FIELD(ERR_CTRL, SLVERR_ENABLE, 0, 1)
92
--- a/target/arm/translate.c
44
+REG32(IR_STATUS, 0x4)
93
+++ b/target/arm/translate.c
45
+ FIELD(IR_STATUS, ADDR_DECODE_ERR, 0, 1)
94
@@ -XXX,XX +XXX,XX @@ static inline void gen_mov_vreg_F0(int dp, int reg)
46
+REG32(IR_MASK, 0x8)
95
47
+ FIELD(IR_MASK, ADDR_DECODE_ERR, 0, 1)
96
#define ARM_CP_RW_BIT (1 << 20)
48
+REG32(IR_ENABLE, 0xc)
97
49
+ FIELD(IR_ENABLE, ADDR_DECODE_ERR, 0, 1)
98
+/* Include the VFP decoder */
50
+REG32(IR_DISABLE, 0x10)
99
+#include "translate-vfp.inc.c"
51
+ FIELD(IR_DISABLE, ADDR_DECODE_ERR, 0, 1)
100
+
52
+REG32(WPROT, 0x1c)
101
static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
53
+ FIELD(WPROT, ACTIVE, 0, 1)
102
{
54
+REG32(PLL_CLK_OTHER_DMN, 0x20)
103
tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
55
+ FIELD(PLL_CLK_OTHER_DMN, APLL_BYPASS, 0, 1)
104
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
56
+REG32(RPLL_CTRL, 0x40)
105
return 1;
57
+ FIELD(RPLL_CTRL, POST_SRC, 24, 3)
106
}
58
+ FIELD(RPLL_CTRL, PRE_SRC, 20, 3)
107
59
+ FIELD(RPLL_CTRL, CLKOUTDIV, 16, 2)
108
+ /*
60
+ FIELD(RPLL_CTRL, FBDIV, 8, 8)
109
+ * If the decodetree decoder handles this insn it will always
61
+ FIELD(RPLL_CTRL, BYPASS, 3, 1)
110
+ * emit code to either execute the insn or generate an appropriate
62
+ FIELD(RPLL_CTRL, RESET, 0, 1)
111
+ * exception; so we don't need to ever return non-zero to tell
63
+REG32(RPLL_CFG, 0x44)
112
+ * the calling code to emit an UNDEF exception.
64
+ FIELD(RPLL_CFG, LOCK_DLY, 25, 7)
113
+ */
65
+ FIELD(RPLL_CFG, LOCK_CNT, 13, 10)
114
+ if (extract32(insn, 28, 4) == 0xf) {
66
+ FIELD(RPLL_CFG, LFHF, 10, 2)
115
+ if (disas_vfp_uncond(s, insn)) {
67
+ FIELD(RPLL_CFG, CP, 5, 4)
116
+ return 0;
68
+ FIELD(RPLL_CFG, RES, 0, 4)
117
+ }
69
+REG32(RPLL_FRAC_CFG, 0x48)
118
+ } else {
70
+ FIELD(RPLL_FRAC_CFG, ENABLED, 31, 1)
119
+ if (disas_vfp(s, insn)) {
71
+ FIELD(RPLL_FRAC_CFG, SEED, 22, 3)
120
+ return 0;
72
+ FIELD(RPLL_FRAC_CFG, ALGRTHM, 19, 1)
121
+ }
73
+ FIELD(RPLL_FRAC_CFG, ORDER, 18, 1)
122
+ }
74
+ FIELD(RPLL_FRAC_CFG, DATA, 0, 16)
123
+
75
+REG32(PLL_STATUS, 0x50)
124
/* FIXME: this access check should not take precedence over UNDEF
76
+ FIELD(PLL_STATUS, RPLL_STABLE, 2, 1)
125
* for invalid encodings; we will generate incorrect syndrome information
77
+ FIELD(PLL_STATUS, RPLL_LOCK, 0, 1)
126
* for attempts to execute invalid vfp/neon encodings with FP disabled.
78
+REG32(RPLL_TO_XPD_CTRL, 0x100)
127
diff --git a/target/arm/vfp-uncond.decode b/target/arm/vfp-uncond.decode
79
+ FIELD(RPLL_TO_XPD_CTRL, CLKACT, 25, 1)
80
+ FIELD(RPLL_TO_XPD_CTRL, DIVISOR0, 8, 10)
81
+REG32(LPD_TOP_SWITCH_CTRL, 0x104)
82
+ FIELD(LPD_TOP_SWITCH_CTRL, CLKACT_ADMA, 26, 1)
83
+ FIELD(LPD_TOP_SWITCH_CTRL, CLKACT, 25, 1)
84
+ FIELD(LPD_TOP_SWITCH_CTRL, DIVISOR0, 8, 10)
85
+ FIELD(LPD_TOP_SWITCH_CTRL, SRCSEL, 0, 3)
86
+REG32(LPD_LSBUS_CTRL, 0x108)
87
+ FIELD(LPD_LSBUS_CTRL, CLKACT, 25, 1)
88
+ FIELD(LPD_LSBUS_CTRL, DIVISOR0, 8, 10)
89
+ FIELD(LPD_LSBUS_CTRL, SRCSEL, 0, 3)
90
+REG32(CPU_R5_CTRL, 0x10c)
91
+ FIELD(CPU_R5_CTRL, CLKACT_OCM2, 28, 1)
92
+ FIELD(CPU_R5_CTRL, CLKACT_OCM, 27, 1)
93
+ FIELD(CPU_R5_CTRL, CLKACT_CORE, 26, 1)
94
+ FIELD(CPU_R5_CTRL, CLKACT, 25, 1)
95
+ FIELD(CPU_R5_CTRL, DIVISOR0, 8, 10)
96
+ FIELD(CPU_R5_CTRL, SRCSEL, 0, 3)
97
+REG32(IOU_SWITCH_CTRL, 0x114)
98
+ FIELD(IOU_SWITCH_CTRL, CLKACT, 25, 1)
99
+ FIELD(IOU_SWITCH_CTRL, DIVISOR0, 8, 10)
100
+ FIELD(IOU_SWITCH_CTRL, SRCSEL, 0, 3)
101
+REG32(GEM0_REF_CTRL, 0x118)
102
+ FIELD(GEM0_REF_CTRL, CLKACT_RX, 27, 1)
103
+ FIELD(GEM0_REF_CTRL, CLKACT_TX, 26, 1)
104
+ FIELD(GEM0_REF_CTRL, CLKACT, 25, 1)
105
+ FIELD(GEM0_REF_CTRL, DIVISOR0, 8, 10)
106
+ FIELD(GEM0_REF_CTRL, SRCSEL, 0, 3)
107
+REG32(GEM1_REF_CTRL, 0x11c)
108
+ FIELD(GEM1_REF_CTRL, CLKACT_RX, 27, 1)
109
+ FIELD(GEM1_REF_CTRL, CLKACT_TX, 26, 1)
110
+ FIELD(GEM1_REF_CTRL, CLKACT, 25, 1)
111
+ FIELD(GEM1_REF_CTRL, DIVISOR0, 8, 10)
112
+ FIELD(GEM1_REF_CTRL, SRCSEL, 0, 3)
113
+REG32(GEM_TSU_REF_CTRL, 0x120)
114
+ FIELD(GEM_TSU_REF_CTRL, CLKACT, 25, 1)
115
+ FIELD(GEM_TSU_REF_CTRL, DIVISOR0, 8, 10)
116
+ FIELD(GEM_TSU_REF_CTRL, SRCSEL, 0, 3)
117
+REG32(USB0_BUS_REF_CTRL, 0x124)
118
+ FIELD(USB0_BUS_REF_CTRL, CLKACT, 25, 1)
119
+ FIELD(USB0_BUS_REF_CTRL, DIVISOR0, 8, 10)
120
+ FIELD(USB0_BUS_REF_CTRL, SRCSEL, 0, 3)
121
+REG32(UART0_REF_CTRL, 0x128)
122
+ FIELD(UART0_REF_CTRL, CLKACT, 25, 1)
123
+ FIELD(UART0_REF_CTRL, DIVISOR0, 8, 10)
124
+ FIELD(UART0_REF_CTRL, SRCSEL, 0, 3)
125
+REG32(UART1_REF_CTRL, 0x12c)
126
+ FIELD(UART1_REF_CTRL, CLKACT, 25, 1)
127
+ FIELD(UART1_REF_CTRL, DIVISOR0, 8, 10)
128
+ FIELD(UART1_REF_CTRL, SRCSEL, 0, 3)
129
+REG32(SPI0_REF_CTRL, 0x130)
130
+ FIELD(SPI0_REF_CTRL, CLKACT, 25, 1)
131
+ FIELD(SPI0_REF_CTRL, DIVISOR0, 8, 10)
132
+ FIELD(SPI0_REF_CTRL, SRCSEL, 0, 3)
133
+REG32(SPI1_REF_CTRL, 0x134)
134
+ FIELD(SPI1_REF_CTRL, CLKACT, 25, 1)
135
+ FIELD(SPI1_REF_CTRL, DIVISOR0, 8, 10)
136
+ FIELD(SPI1_REF_CTRL, SRCSEL, 0, 3)
137
+REG32(CAN0_REF_CTRL, 0x138)
138
+ FIELD(CAN0_REF_CTRL, CLKACT, 25, 1)
139
+ FIELD(CAN0_REF_CTRL, DIVISOR0, 8, 10)
140
+ FIELD(CAN0_REF_CTRL, SRCSEL, 0, 3)
141
+REG32(CAN1_REF_CTRL, 0x13c)
142
+ FIELD(CAN1_REF_CTRL, CLKACT, 25, 1)
143
+ FIELD(CAN1_REF_CTRL, DIVISOR0, 8, 10)
144
+ FIELD(CAN1_REF_CTRL, SRCSEL, 0, 3)
145
+REG32(I2C0_REF_CTRL, 0x140)
146
+ FIELD(I2C0_REF_CTRL, CLKACT, 25, 1)
147
+ FIELD(I2C0_REF_CTRL, DIVISOR0, 8, 10)
148
+ FIELD(I2C0_REF_CTRL, SRCSEL, 0, 3)
149
+REG32(I2C1_REF_CTRL, 0x144)
150
+ FIELD(I2C1_REF_CTRL, CLKACT, 25, 1)
151
+ FIELD(I2C1_REF_CTRL, DIVISOR0, 8, 10)
152
+ FIELD(I2C1_REF_CTRL, SRCSEL, 0, 3)
153
+REG32(DBG_LPD_CTRL, 0x148)
154
+ FIELD(DBG_LPD_CTRL, CLKACT, 25, 1)
155
+ FIELD(DBG_LPD_CTRL, DIVISOR0, 8, 10)
156
+ FIELD(DBG_LPD_CTRL, SRCSEL, 0, 3)
157
+REG32(TIMESTAMP_REF_CTRL, 0x14c)
158
+ FIELD(TIMESTAMP_REF_CTRL, CLKACT, 25, 1)
159
+ FIELD(TIMESTAMP_REF_CTRL, DIVISOR0, 8, 10)
160
+ FIELD(TIMESTAMP_REF_CTRL, SRCSEL, 0, 3)
161
+REG32(CRL_SAFETY_CHK, 0x150)
162
+REG32(PSM_REF_CTRL, 0x154)
163
+ FIELD(PSM_REF_CTRL, DIVISOR0, 8, 10)
164
+ FIELD(PSM_REF_CTRL, SRCSEL, 0, 3)
165
+REG32(DBG_TSTMP_CTRL, 0x158)
166
+ FIELD(DBG_TSTMP_CTRL, CLKACT, 25, 1)
167
+ FIELD(DBG_TSTMP_CTRL, DIVISOR0, 8, 10)
168
+ FIELD(DBG_TSTMP_CTRL, SRCSEL, 0, 3)
169
+REG32(CPM_TOPSW_REF_CTRL, 0x15c)
170
+ FIELD(CPM_TOPSW_REF_CTRL, CLKACT, 25, 1)
171
+ FIELD(CPM_TOPSW_REF_CTRL, DIVISOR0, 8, 10)
172
+ FIELD(CPM_TOPSW_REF_CTRL, SRCSEL, 0, 3)
173
+REG32(USB3_DUAL_REF_CTRL, 0x160)
174
+ FIELD(USB3_DUAL_REF_CTRL, CLKACT, 25, 1)
175
+ FIELD(USB3_DUAL_REF_CTRL, DIVISOR0, 8, 10)
176
+ FIELD(USB3_DUAL_REF_CTRL, SRCSEL, 0, 3)
177
+REG32(RST_CPU_R5, 0x300)
178
+ FIELD(RST_CPU_R5, RESET_PGE, 4, 1)
179
+ FIELD(RST_CPU_R5, RESET_AMBA, 2, 1)
180
+ FIELD(RST_CPU_R5, RESET_CPU1, 1, 1)
181
+ FIELD(RST_CPU_R5, RESET_CPU0, 0, 1)
182
+REG32(RST_ADMA, 0x304)
183
+ FIELD(RST_ADMA, RESET, 0, 1)
184
+REG32(RST_GEM0, 0x308)
185
+ FIELD(RST_GEM0, RESET, 0, 1)
186
+REG32(RST_GEM1, 0x30c)
187
+ FIELD(RST_GEM1, RESET, 0, 1)
188
+REG32(RST_SPARE, 0x310)
189
+ FIELD(RST_SPARE, RESET, 0, 1)
190
+REG32(RST_USB0, 0x314)
191
+ FIELD(RST_USB0, RESET, 0, 1)
192
+REG32(RST_UART0, 0x318)
193
+ FIELD(RST_UART0, RESET, 0, 1)
194
+REG32(RST_UART1, 0x31c)
195
+ FIELD(RST_UART1, RESET, 0, 1)
196
+REG32(RST_SPI0, 0x320)
197
+ FIELD(RST_SPI0, RESET, 0, 1)
198
+REG32(RST_SPI1, 0x324)
199
+ FIELD(RST_SPI1, RESET, 0, 1)
200
+REG32(RST_CAN0, 0x328)
201
+ FIELD(RST_CAN0, RESET, 0, 1)
202
+REG32(RST_CAN1, 0x32c)
203
+ FIELD(RST_CAN1, RESET, 0, 1)
204
+REG32(RST_I2C0, 0x330)
205
+ FIELD(RST_I2C0, RESET, 0, 1)
206
+REG32(RST_I2C1, 0x334)
207
+ FIELD(RST_I2C1, RESET, 0, 1)
208
+REG32(RST_DBG_LPD, 0x338)
209
+ FIELD(RST_DBG_LPD, RPU_DBG1_RESET, 5, 1)
210
+ FIELD(RST_DBG_LPD, RPU_DBG0_RESET, 4, 1)
211
+ FIELD(RST_DBG_LPD, RESET_HSDP, 1, 1)
212
+ FIELD(RST_DBG_LPD, RESET, 0, 1)
213
+REG32(RST_GPIO, 0x33c)
214
+ FIELD(RST_GPIO, RESET, 0, 1)
215
+REG32(RST_TTC, 0x344)
216
+ FIELD(RST_TTC, TTC3_RESET, 3, 1)
217
+ FIELD(RST_TTC, TTC2_RESET, 2, 1)
218
+ FIELD(RST_TTC, TTC1_RESET, 1, 1)
219
+ FIELD(RST_TTC, TTC0_RESET, 0, 1)
220
+REG32(RST_TIMESTAMP, 0x348)
221
+ FIELD(RST_TIMESTAMP, RESET, 0, 1)
222
+REG32(RST_SWDT, 0x34c)
223
+ FIELD(RST_SWDT, RESET, 0, 1)
224
+REG32(RST_OCM, 0x350)
225
+ FIELD(RST_OCM, RESET, 0, 1)
226
+REG32(RST_IPI, 0x354)
227
+ FIELD(RST_IPI, RESET, 0, 1)
228
+REG32(RST_SYSMON, 0x358)
229
+ FIELD(RST_SYSMON, SEQ_RST, 1, 1)
230
+ FIELD(RST_SYSMON, CFG_RST, 0, 1)
231
+REG32(RST_FPD, 0x360)
232
+ FIELD(RST_FPD, SRST, 1, 1)
233
+ FIELD(RST_FPD, POR, 0, 1)
234
+REG32(PSM_RST_MODE, 0x370)
235
+ FIELD(PSM_RST_MODE, WAKEUP, 2, 1)
236
+ FIELD(PSM_RST_MODE, RST_MODE, 0, 2)
237
+
238
+#define CRL_R_MAX (R_PSM_RST_MODE + 1)
239
+
240
+#define RPU_MAX_CPU 2
241
+
242
+struct XlnxVersalCRL {
243
+ SysBusDevice parent_obj;
244
+ qemu_irq irq;
245
+
246
+ struct {
247
+ ARMCPU *cpu_r5[RPU_MAX_CPU];
248
+ DeviceState *adma[8];
249
+ DeviceState *uart[2];
250
+ DeviceState *gem[2];
251
+ DeviceState *usb;
252
+ } cfg;
253
+
254
+ RegisterInfoArray *reg_array;
255
+ uint32_t regs[CRL_R_MAX];
256
+ RegisterInfo regs_info[CRL_R_MAX];
257
+};
258
+#endif
259
diff --git a/hw/misc/xlnx-versal-crl.c b/hw/misc/xlnx-versal-crl.c
128
new file mode 100644
260
new file mode 100644
129
index XXXXXXX..XXXXXXX
261
index XXXXXXX..XXXXXXX
130
--- /dev/null
262
--- /dev/null
131
+++ b/target/arm/vfp-uncond.decode
263
+++ b/hw/misc/xlnx-versal-crl.c
132
@@ -XXX,XX +XXX,XX @@
264
@@ -XXX,XX +XXX,XX @@
133
+# AArch32 VFP instruction descriptions (unconditional insns)
265
+/*
134
+#
266
+ * QEMU model of the Clock-Reset-LPD (CRL).
135
+# Copyright (c) 2019 Linaro, Ltd
267
+ *
136
+#
268
+ * Copyright (c) 2022 Advanced Micro Devices, Inc.
137
+# This library is free software; you can redistribute it and/or
269
+ * SPDX-License-Identifier: GPL-2.0-or-later
138
+# modify it under the terms of the GNU Lesser General Public
270
+ *
139
+# License as published by the Free Software Foundation; either
271
+ * Written by Edgar E. Iglesias <edgar.iglesias@amd.com>
140
+# version 2 of the License, or (at your option) any later version.
272
+ */
141
+#
273
+
142
+# This library is distributed in the hope that it will be useful,
274
+#include "qemu/osdep.h"
143
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
275
+#include "qapi/error.h"
144
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
276
+#include "qemu/log.h"
145
+# Lesser General Public License for more details.
277
+#include "qemu/bitops.h"
146
+#
278
+#include "migration/vmstate.h"
147
+# You should have received a copy of the GNU Lesser General Public
279
+#include "hw/qdev-properties.h"
148
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
280
+#include "hw/sysbus.h"
149
+
281
+#include "hw/irq.h"
150
+#
282
+#include "hw/register.h"
151
+# This file is processed by scripts/decodetree.py
283
+#include "hw/resettable.h"
152
+#
284
+
153
+# Encodings for the unconditional VFP instructions are here:
285
+#include "target/arm/arm-powerctl.h"
154
+# generally anything matching A32
286
+#include "hw/misc/xlnx-versal-crl.h"
155
+# 1111 1110 .... .... .... 101. ...0 ....
287
+
156
+# and T32
288
+#ifndef XLNX_VERSAL_CRL_ERR_DEBUG
157
+# 1111 110. .... .... .... 101. .... ....
289
+#define XLNX_VERSAL_CRL_ERR_DEBUG 0
158
+# 1111 1110 .... .... .... 101. .... ....
290
+#endif
159
+# (but those patterns might also cover some Neon instructions,
291
+
160
+# which do not live in this file.)
292
+static void crl_update_irq(XlnxVersalCRL *s)
161
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
293
+{
162
new file mode 100644
294
+ bool pending = s->regs[R_IR_STATUS] & ~s->regs[R_IR_MASK];
163
index XXXXXXX..XXXXXXX
295
+ qemu_set_irq(s->irq, pending);
164
--- /dev/null
296
+}
165
+++ b/target/arm/vfp.decode
297
+
166
@@ -XXX,XX +XXX,XX @@
298
+static void crl_status_postw(RegisterInfo *reg, uint64_t val64)
167
+# AArch32 VFP instruction descriptions (conditional insns)
299
+{
168
+#
300
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
169
+# Copyright (c) 2019 Linaro, Ltd
301
+ crl_update_irq(s);
170
+#
302
+}
171
+# This library is free software; you can redistribute it and/or
303
+
172
+# modify it under the terms of the GNU Lesser General Public
304
+static uint64_t crl_enable_prew(RegisterInfo *reg, uint64_t val64)
173
+# License as published by the Free Software Foundation; either
305
+{
174
+# version 2 of the License, or (at your option) any later version.
306
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
175
+#
307
+ uint32_t val = val64;
176
+# This library is distributed in the hope that it will be useful,
308
+
177
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
309
+ s->regs[R_IR_MASK] &= ~val;
178
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
310
+ crl_update_irq(s);
179
+# Lesser General Public License for more details.
311
+ return 0;
180
+#
312
+}
181
+# You should have received a copy of the GNU Lesser General Public
313
+
182
+# License along with this library; if not, see <http://www.gnu.org/licenses/>.
314
+static uint64_t crl_disable_prew(RegisterInfo *reg, uint64_t val64)
183
+
315
+{
184
+#
316
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
185
+# This file is processed by scripts/decodetree.py
317
+ uint32_t val = val64;
186
+#
318
+
187
+# Encodings for the conditional VFP instructions are here:
319
+ s->regs[R_IR_MASK] |= val;
188
+# generally anything matching A32
320
+ crl_update_irq(s);
189
+# cccc 11.. .... .... .... 101. .... ....
321
+ return 0;
190
+# and T32
322
+}
191
+# 1110 110. .... .... .... 101. .... ....
323
+
192
+# 1110 1110 .... .... .... 101. .... ....
324
+static void crl_reset_dev(XlnxVersalCRL *s, DeviceState *dev,
193
+# (but those patterns might also cover some Neon instructions,
325
+ bool rst_old, bool rst_new)
194
+# which do not live in this file.)
326
+{
327
+ device_cold_reset(dev);
328
+}
329
+
330
+static void crl_reset_cpu(XlnxVersalCRL *s, ARMCPU *armcpu,
331
+ bool rst_old, bool rst_new)
332
+{
333
+ if (rst_new) {
334
+ arm_set_cpu_off(armcpu->mp_affinity);
335
+ } else {
336
+ arm_set_cpu_on_and_reset(armcpu->mp_affinity);
337
+ }
338
+}
339
+
340
+#define REGFIELD_RESET(type, s, reg, f, new_val, dev) { \
341
+ bool old_f = ARRAY_FIELD_EX32((s)->regs, reg, f); \
342
+ bool new_f = FIELD_EX32(new_val, reg, f); \
343
+ \
344
+ /* Detect edges. */ \
345
+ if (dev && old_f != new_f) { \
346
+ crl_reset_ ## type(s, dev, old_f, new_f); \
347
+ } \
348
+}
349
+
350
+static uint64_t crl_rst_r5_prew(RegisterInfo *reg, uint64_t val64)
351
+{
352
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
353
+
354
+ REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU0, val64, s->cfg.cpu_r5[0]);
355
+ REGFIELD_RESET(cpu, s, RST_CPU_R5, RESET_CPU1, val64, s->cfg.cpu_r5[1]);
356
+ return val64;
357
+}
358
+
359
+static uint64_t crl_rst_adma_prew(RegisterInfo *reg, uint64_t val64)
360
+{
361
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
362
+ int i;
363
+
364
+ /* A single register fans out to all ADMA reset inputs. */
365
+ for (i = 0; i < ARRAY_SIZE(s->cfg.adma); i++) {
366
+ REGFIELD_RESET(dev, s, RST_ADMA, RESET, val64, s->cfg.adma[i]);
367
+ }
368
+ return val64;
369
+}
370
+
371
+static uint64_t crl_rst_uart0_prew(RegisterInfo *reg, uint64_t val64)
372
+{
373
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
374
+
375
+ REGFIELD_RESET(dev, s, RST_UART0, RESET, val64, s->cfg.uart[0]);
376
+ return val64;
377
+}
378
+
379
+static uint64_t crl_rst_uart1_prew(RegisterInfo *reg, uint64_t val64)
380
+{
381
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
382
+
383
+ REGFIELD_RESET(dev, s, RST_UART1, RESET, val64, s->cfg.uart[1]);
384
+ return val64;
385
+}
386
+
387
+static uint64_t crl_rst_gem0_prew(RegisterInfo *reg, uint64_t val64)
388
+{
389
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
390
+
391
+ REGFIELD_RESET(dev, s, RST_GEM0, RESET, val64, s->cfg.gem[0]);
392
+ return val64;
393
+}
394
+
395
+static uint64_t crl_rst_gem1_prew(RegisterInfo *reg, uint64_t val64)
396
+{
397
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
398
+
399
+ REGFIELD_RESET(dev, s, RST_GEM1, RESET, val64, s->cfg.gem[1]);
400
+ return val64;
401
+}
402
+
403
+static uint64_t crl_rst_usb_prew(RegisterInfo *reg, uint64_t val64)
404
+{
405
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(reg->opaque);
406
+
407
+ REGFIELD_RESET(dev, s, RST_USB0, RESET, val64, s->cfg.usb);
408
+ return val64;
409
+}
410
+
411
+static const RegisterAccessInfo crl_regs_info[] = {
412
+ { .name = "ERR_CTRL", .addr = A_ERR_CTRL,
413
+ },{ .name = "IR_STATUS", .addr = A_IR_STATUS,
414
+ .w1c = 0x1,
415
+ .post_write = crl_status_postw,
416
+ },{ .name = "IR_MASK", .addr = A_IR_MASK,
417
+ .reset = 0x1,
418
+ .ro = 0x1,
419
+ },{ .name = "IR_ENABLE", .addr = A_IR_ENABLE,
420
+ .pre_write = crl_enable_prew,
421
+ },{ .name = "IR_DISABLE", .addr = A_IR_DISABLE,
422
+ .pre_write = crl_disable_prew,
423
+ },{ .name = "WPROT", .addr = A_WPROT,
424
+ },{ .name = "PLL_CLK_OTHER_DMN", .addr = A_PLL_CLK_OTHER_DMN,
425
+ .reset = 0x1,
426
+ .rsvd = 0xe,
427
+ },{ .name = "RPLL_CTRL", .addr = A_RPLL_CTRL,
428
+ .reset = 0x24809,
429
+ .rsvd = 0xf88c00f6,
430
+ },{ .name = "RPLL_CFG", .addr = A_RPLL_CFG,
431
+ .reset = 0x2000000,
432
+ .rsvd = 0x1801210,
433
+ },{ .name = "RPLL_FRAC_CFG", .addr = A_RPLL_FRAC_CFG,
434
+ .rsvd = 0x7e330000,
435
+ },{ .name = "PLL_STATUS", .addr = A_PLL_STATUS,
436
+ .reset = R_PLL_STATUS_RPLL_STABLE_MASK |
437
+ R_PLL_STATUS_RPLL_LOCK_MASK,
438
+ .rsvd = 0xfa,
439
+ .ro = 0x5,
440
+ },{ .name = "RPLL_TO_XPD_CTRL", .addr = A_RPLL_TO_XPD_CTRL,
441
+ .reset = 0x2000100,
442
+ .rsvd = 0xfdfc00ff,
443
+ },{ .name = "LPD_TOP_SWITCH_CTRL", .addr = A_LPD_TOP_SWITCH_CTRL,
444
+ .reset = 0x6000300,
445
+ .rsvd = 0xf9fc00f8,
446
+ },{ .name = "LPD_LSBUS_CTRL", .addr = A_LPD_LSBUS_CTRL,
447
+ .reset = 0x2000800,
448
+ .rsvd = 0xfdfc00f8,
449
+ },{ .name = "CPU_R5_CTRL", .addr = A_CPU_R5_CTRL,
450
+ .reset = 0xe000300,
451
+ .rsvd = 0xe1fc00f8,
452
+ },{ .name = "IOU_SWITCH_CTRL", .addr = A_IOU_SWITCH_CTRL,
453
+ .reset = 0x2000500,
454
+ .rsvd = 0xfdfc00f8,
455
+ },{ .name = "GEM0_REF_CTRL", .addr = A_GEM0_REF_CTRL,
456
+ .reset = 0xe000a00,
457
+ .rsvd = 0xf1fc00f8,
458
+ },{ .name = "GEM1_REF_CTRL", .addr = A_GEM1_REF_CTRL,
459
+ .reset = 0xe000a00,
460
+ .rsvd = 0xf1fc00f8,
461
+ },{ .name = "GEM_TSU_REF_CTRL", .addr = A_GEM_TSU_REF_CTRL,
462
+ .reset = 0x300,
463
+ .rsvd = 0xfdfc00f8,
464
+ },{ .name = "USB0_BUS_REF_CTRL", .addr = A_USB0_BUS_REF_CTRL,
465
+ .reset = 0x2001900,
466
+ .rsvd = 0xfdfc00f8,
467
+ },{ .name = "UART0_REF_CTRL", .addr = A_UART0_REF_CTRL,
468
+ .reset = 0xc00,
469
+ .rsvd = 0xfdfc00f8,
470
+ },{ .name = "UART1_REF_CTRL", .addr = A_UART1_REF_CTRL,
471
+ .reset = 0xc00,
472
+ .rsvd = 0xfdfc00f8,
473
+ },{ .name = "SPI0_REF_CTRL", .addr = A_SPI0_REF_CTRL,
474
+ .reset = 0x600,
475
+ .rsvd = 0xfdfc00f8,
476
+ },{ .name = "SPI1_REF_CTRL", .addr = A_SPI1_REF_CTRL,
477
+ .reset = 0x600,
478
+ .rsvd = 0xfdfc00f8,
479
+ },{ .name = "CAN0_REF_CTRL", .addr = A_CAN0_REF_CTRL,
480
+ .reset = 0xc00,
481
+ .rsvd = 0xfdfc00f8,
482
+ },{ .name = "CAN1_REF_CTRL", .addr = A_CAN1_REF_CTRL,
483
+ .reset = 0xc00,
484
+ .rsvd = 0xfdfc00f8,
485
+ },{ .name = "I2C0_REF_CTRL", .addr = A_I2C0_REF_CTRL,
486
+ .reset = 0xc00,
487
+ .rsvd = 0xfdfc00f8,
488
+ },{ .name = "I2C1_REF_CTRL", .addr = A_I2C1_REF_CTRL,
489
+ .reset = 0xc00,
490
+ .rsvd = 0xfdfc00f8,
491
+ },{ .name = "DBG_LPD_CTRL", .addr = A_DBG_LPD_CTRL,
492
+ .reset = 0x300,
493
+ .rsvd = 0xfdfc00f8,
494
+ },{ .name = "TIMESTAMP_REF_CTRL", .addr = A_TIMESTAMP_REF_CTRL,
495
+ .reset = 0x2000c00,
496
+ .rsvd = 0xfdfc00f8,
497
+ },{ .name = "CRL_SAFETY_CHK", .addr = A_CRL_SAFETY_CHK,
498
+ },{ .name = "PSM_REF_CTRL", .addr = A_PSM_REF_CTRL,
499
+ .reset = 0xf04,
500
+ .rsvd = 0xfffc00f8,
501
+ },{ .name = "DBG_TSTMP_CTRL", .addr = A_DBG_TSTMP_CTRL,
502
+ .reset = 0x300,
503
+ .rsvd = 0xfdfc00f8,
504
+ },{ .name = "CPM_TOPSW_REF_CTRL", .addr = A_CPM_TOPSW_REF_CTRL,
505
+ .reset = 0x300,
506
+ .rsvd = 0xfdfc00f8,
507
+ },{ .name = "USB3_DUAL_REF_CTRL", .addr = A_USB3_DUAL_REF_CTRL,
508
+ .reset = 0x3c00,
509
+ .rsvd = 0xfdfc00f8,
510
+ },{ .name = "RST_CPU_R5", .addr = A_RST_CPU_R5,
511
+ .reset = 0x17,
512
+ .rsvd = 0x8,
513
+ .pre_write = crl_rst_r5_prew,
514
+ },{ .name = "RST_ADMA", .addr = A_RST_ADMA,
515
+ .reset = 0x1,
516
+ .pre_write = crl_rst_adma_prew,
517
+ },{ .name = "RST_GEM0", .addr = A_RST_GEM0,
518
+ .reset = 0x1,
519
+ .pre_write = crl_rst_gem0_prew,
520
+ },{ .name = "RST_GEM1", .addr = A_RST_GEM1,
521
+ .reset = 0x1,
522
+ .pre_write = crl_rst_gem1_prew,
523
+ },{ .name = "RST_SPARE", .addr = A_RST_SPARE,
524
+ .reset = 0x1,
525
+ },{ .name = "RST_USB0", .addr = A_RST_USB0,
526
+ .reset = 0x1,
527
+ .pre_write = crl_rst_usb_prew,
528
+ },{ .name = "RST_UART0", .addr = A_RST_UART0,
529
+ .reset = 0x1,
530
+ .pre_write = crl_rst_uart0_prew,
531
+ },{ .name = "RST_UART1", .addr = A_RST_UART1,
532
+ .reset = 0x1,
533
+ .pre_write = crl_rst_uart1_prew,
534
+ },{ .name = "RST_SPI0", .addr = A_RST_SPI0,
535
+ .reset = 0x1,
536
+ },{ .name = "RST_SPI1", .addr = A_RST_SPI1,
537
+ .reset = 0x1,
538
+ },{ .name = "RST_CAN0", .addr = A_RST_CAN0,
539
+ .reset = 0x1,
540
+ },{ .name = "RST_CAN1", .addr = A_RST_CAN1,
541
+ .reset = 0x1,
542
+ },{ .name = "RST_I2C0", .addr = A_RST_I2C0,
543
+ .reset = 0x1,
544
+ },{ .name = "RST_I2C1", .addr = A_RST_I2C1,
545
+ .reset = 0x1,
546
+ },{ .name = "RST_DBG_LPD", .addr = A_RST_DBG_LPD,
547
+ .reset = 0x33,
548
+ .rsvd = 0xcc,
549
+ },{ .name = "RST_GPIO", .addr = A_RST_GPIO,
550
+ .reset = 0x1,
551
+ },{ .name = "RST_TTC", .addr = A_RST_TTC,
552
+ .reset = 0xf,
553
+ },{ .name = "RST_TIMESTAMP", .addr = A_RST_TIMESTAMP,
554
+ .reset = 0x1,
555
+ },{ .name = "RST_SWDT", .addr = A_RST_SWDT,
556
+ .reset = 0x1,
557
+ },{ .name = "RST_OCM", .addr = A_RST_OCM,
558
+ },{ .name = "RST_IPI", .addr = A_RST_IPI,
559
+ },{ .name = "RST_FPD", .addr = A_RST_FPD,
560
+ .reset = 0x3,
561
+ },{ .name = "PSM_RST_MODE", .addr = A_PSM_RST_MODE,
562
+ .reset = 0x1,
563
+ .rsvd = 0xf8,
564
+ }
565
+};
566
+
567
+static void crl_reset_enter(Object *obj, ResetType type)
568
+{
569
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
570
+ unsigned int i;
571
+
572
+ for (i = 0; i < ARRAY_SIZE(s->regs_info); ++i) {
573
+ register_reset(&s->regs_info[i]);
574
+ }
575
+}
576
+
577
+static void crl_reset_hold(Object *obj)
578
+{
579
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
580
+
581
+ crl_update_irq(s);
582
+}
583
+
584
+static const MemoryRegionOps crl_ops = {
585
+ .read = register_read_memory,
586
+ .write = register_write_memory,
587
+ .endianness = DEVICE_LITTLE_ENDIAN,
588
+ .valid = {
589
+ .min_access_size = 4,
590
+ .max_access_size = 4,
591
+ },
592
+};
593
+
594
+static void crl_init(Object *obj)
595
+{
596
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
597
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
598
+ int i;
599
+
600
+ s->reg_array =
601
+ register_init_block32(DEVICE(obj), crl_regs_info,
602
+ ARRAY_SIZE(crl_regs_info),
603
+ s->regs_info, s->regs,
604
+ &crl_ops,
605
+ XLNX_VERSAL_CRL_ERR_DEBUG,
606
+ CRL_R_MAX * 4);
607
+ sysbus_init_mmio(sbd, &s->reg_array->mem);
608
+ sysbus_init_irq(sbd, &s->irq);
609
+
610
+ for (i = 0; i < ARRAY_SIZE(s->cfg.cpu_r5); ++i) {
611
+ object_property_add_link(obj, "cpu_r5[*]", TYPE_ARM_CPU,
612
+ (Object **)&s->cfg.cpu_r5[i],
613
+ qdev_prop_allow_set_link_before_realize,
614
+ OBJ_PROP_LINK_STRONG);
615
+ }
616
+
617
+ for (i = 0; i < ARRAY_SIZE(s->cfg.adma); ++i) {
618
+ object_property_add_link(obj, "adma[*]", TYPE_DEVICE,
619
+ (Object **)&s->cfg.adma[i],
620
+ qdev_prop_allow_set_link_before_realize,
621
+ OBJ_PROP_LINK_STRONG);
622
+ }
623
+
624
+ for (i = 0; i < ARRAY_SIZE(s->cfg.uart); ++i) {
625
+ object_property_add_link(obj, "uart[*]", TYPE_DEVICE,
626
+ (Object **)&s->cfg.uart[i],
627
+ qdev_prop_allow_set_link_before_realize,
628
+ OBJ_PROP_LINK_STRONG);
629
+ }
630
+
631
+ for (i = 0; i < ARRAY_SIZE(s->cfg.gem); ++i) {
632
+ object_property_add_link(obj, "gem[*]", TYPE_DEVICE,
633
+ (Object **)&s->cfg.gem[i],
634
+ qdev_prop_allow_set_link_before_realize,
635
+ OBJ_PROP_LINK_STRONG);
636
+ }
637
+
638
+ object_property_add_link(obj, "usb", TYPE_DEVICE,
639
+ (Object **)&s->cfg.gem[i],
640
+ qdev_prop_allow_set_link_before_realize,
641
+ OBJ_PROP_LINK_STRONG);
642
+}
643
+
644
+static void crl_finalize(Object *obj)
645
+{
646
+ XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
647
+ register_finalize_block(s->reg_array);
648
+}
649
+
650
+static const VMStateDescription vmstate_crl = {
651
+ .name = TYPE_XLNX_VERSAL_CRL,
652
+ .version_id = 1,
653
+ .minimum_version_id = 1,
654
+ .fields = (VMStateField[]) {
655
+ VMSTATE_UINT32_ARRAY(regs, XlnxVersalCRL, CRL_R_MAX),
656
+ VMSTATE_END_OF_LIST(),
657
+ }
658
+};
659
+
660
+static void crl_class_init(ObjectClass *klass, void *data)
661
+{
662
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
663
+ DeviceClass *dc = DEVICE_CLASS(klass);
664
+
665
+ dc->vmsd = &vmstate_crl;
666
+
667
+ rc->phases.enter = crl_reset_enter;
668
+ rc->phases.hold = crl_reset_hold;
669
+}
670
+
671
+static const TypeInfo crl_info = {
672
+ .name = TYPE_XLNX_VERSAL_CRL,
673
+ .parent = TYPE_SYS_BUS_DEVICE,
674
+ .instance_size = sizeof(XlnxVersalCRL),
675
+ .class_init = crl_class_init,
676
+ .instance_init = crl_init,
677
+ .instance_finalize = crl_finalize,
678
+};
679
+
680
+static void crl_register_types(void)
681
+{
682
+ type_register_static(&crl_info);
683
+}
684
+
685
+type_init(crl_register_types)
686
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
687
index XXXXXXX..XXXXXXX 100644
688
--- a/hw/misc/meson.build
689
+++ b/hw/misc/meson.build
690
@@ -XXX,XX +XXX,XX @@ softmmu_ss.add(when: 'CONFIG_SLAVIO', if_true: files('slavio_misc.c'))
691
softmmu_ss.add(when: 'CONFIG_ZYNQ', if_true: files('zynq_slcr.c'))
692
specific_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp-crf.c'))
693
specific_ss.add(when: 'CONFIG_XLNX_ZYNQMP_ARM', if_true: files('xlnx-zynqmp-apu-ctrl.c'))
694
+specific_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files('xlnx-versal-crl.c'))
695
softmmu_ss.add(when: 'CONFIG_XLNX_VERSAL', if_true: files(
696
'xlnx-versal-xramc.c',
697
'xlnx-versal-pmc-iou-slcr.c',
195
--
698
--
196
2.20.1
699
2.25.1
197
198
diff view generated by jsdifflib
1
Convert the VFP VMOV (immediate) instruction to decodetree.
1
From: "Edgar E. Iglesias" <edgar.iglesias@amd.com>
2
2
3
Connect the CRL (Clock Reset LPD) to the Versal SoC.
4
5
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com>
6
Reviewed-by: Frederic Konrad <fkonrad@amd.com>
7
Reviewed-by: Francisco Iglesias <francisco.iglesias@amd.com>
8
Message-id: 20220406174303.2022038-5-edgar.iglesias@xilinx.com
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
---
10
---
6
target/arm/translate-vfp.inc.c | 129 +++++++++++++++++++++++++++++++++
11
include/hw/arm/xlnx-versal.h | 4 +++
7
target/arm/translate.c | 27 +------
12
hw/arm/xlnx-versal.c | 54 ++++++++++++++++++++++++++++++++++--
8
target/arm/vfp.decode | 5 ++
13
2 files changed, 56 insertions(+), 2 deletions(-)
9
3 files changed, 136 insertions(+), 25 deletions(-)
10
14
11
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
15
diff --git a/include/hw/arm/xlnx-versal.h b/include/hw/arm/xlnx-versal.h
12
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-vfp.inc.c
17
--- a/include/hw/arm/xlnx-versal.h
14
+++ b/target/arm/translate-vfp.inc.c
18
+++ b/include/hw/arm/xlnx-versal.h
15
@@ -XXX,XX +XXX,XX @@ static bool trans_VFM_dp(DisasContext *s, arg_VFM_sp *a)
19
@@ -XXX,XX +XXX,XX @@
16
20
#include "hw/nvram/xlnx-versal-efuse.h"
17
return true;
21
#include "hw/ssi/xlnx-versal-ospi.h"
22
#include "hw/dma/xlnx_csu_dma.h"
23
+#include "hw/misc/xlnx-versal-crl.h"
24
#include "hw/misc/xlnx-versal-pmc-iou-slcr.h"
25
26
#define TYPE_XLNX_VERSAL "xlnx-versal"
27
@@ -XXX,XX +XXX,XX @@ struct Versal {
28
qemu_or_irq irq_orgate;
29
XlnxXramCtrl ctrl[XLNX_VERSAL_NR_XRAM];
30
} xram;
31
+
32
+ XlnxVersalCRL crl;
33
} lpd;
34
35
/* The Platform Management Controller subsystem. */
36
@@ -XXX,XX +XXX,XX @@ struct Versal {
37
#define VERSAL_TIMER_NS_EL1_IRQ 14
38
#define VERSAL_TIMER_NS_EL2_IRQ 10
39
40
+#define VERSAL_CRL_IRQ 10
41
#define VERSAL_UART0_IRQ_0 18
42
#define VERSAL_UART1_IRQ_0 19
43
#define VERSAL_USB0_IRQ_0 22
44
diff --git a/hw/arm/xlnx-versal.c b/hw/arm/xlnx-versal.c
45
index XXXXXXX..XXXXXXX 100644
46
--- a/hw/arm/xlnx-versal.c
47
+++ b/hw/arm/xlnx-versal.c
48
@@ -XXX,XX +XXX,XX @@ static void versal_create_ospi(Versal *s, qemu_irq *pic)
49
qdev_connect_gpio_out(orgate, 0, pic[VERSAL_OSPI_IRQ]);
18
}
50
}
51
52
+static void versal_create_crl(Versal *s, qemu_irq *pic)
53
+{
54
+ SysBusDevice *sbd;
55
+ int i;
19
+
56
+
20
+static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a)
57
+ object_initialize_child(OBJECT(s), "crl", &s->lpd.crl,
21
+{
58
+ TYPE_XLNX_VERSAL_CRL);
22
+ uint32_t delta_d = 0;
59
+ sbd = SYS_BUS_DEVICE(&s->lpd.crl);
23
+ uint32_t bank_mask = 0;
24
+ int veclen = s->vec_len;
25
+ TCGv_i32 fd;
26
+ uint32_t n, i, vd;
27
+
60
+
28
+ vd = a->vd;
61
+ for (i = 0; i < ARRAY_SIZE(s->lpd.rpu.cpu); i++) {
62
+ g_autofree gchar *name = g_strdup_printf("cpu_r5[%d]", i);
29
+
63
+
30
+ if (!dc_isar_feature(aa32_fpshvec, s) &&
64
+ object_property_set_link(OBJECT(&s->lpd.crl),
31
+ (veclen != 0 || s->vec_stride != 0)) {
65
+ name, OBJECT(&s->lpd.rpu.cpu[i]),
32
+ return false;
66
+ &error_abort);
33
+ }
67
+ }
34
+
68
+
35
+ if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
69
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.gem); i++) {
36
+ return false;
70
+ g_autofree gchar *name = g_strdup_printf("gem[%d]", i);
71
+
72
+ object_property_set_link(OBJECT(&s->lpd.crl),
73
+ name, OBJECT(&s->lpd.iou.gem[i]),
74
+ &error_abort);
37
+ }
75
+ }
38
+
76
+
39
+ if (!vfp_access_check(s)) {
77
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.adma); i++) {
40
+ return true;
78
+ g_autofree gchar *name = g_strdup_printf("adma[%d]", i);
79
+
80
+ object_property_set_link(OBJECT(&s->lpd.crl),
81
+ name, OBJECT(&s->lpd.iou.adma[i]),
82
+ &error_abort);
41
+ }
83
+ }
42
+
84
+
43
+ if (veclen > 0) {
85
+ for (i = 0; i < ARRAY_SIZE(s->lpd.iou.uart); i++) {
44
+ bank_mask = 0x18;
86
+ g_autofree gchar *name = g_strdup_printf("uart[%d]", i);
45
+ /* Figure out what type of vector operation this is. */
87
+
46
+ if ((vd & bank_mask) == 0) {
88
+ object_property_set_link(OBJECT(&s->lpd.crl),
47
+ /* scalar */
89
+ name, OBJECT(&s->lpd.iou.uart[i]),
48
+ veclen = 0;
90
+ &error_abort);
49
+ } else {
50
+ delta_d = s->vec_stride + 1;
51
+ }
52
+ }
91
+ }
53
+
92
+
54
+ n = (a->imm4h << 28) & 0x80000000;
93
+ object_property_set_link(OBJECT(&s->lpd.crl),
55
+ i = ((a->imm4h << 4) & 0x70) | a->imm4l;
94
+ "usb", OBJECT(&s->lpd.iou.usb),
56
+ if (i & 0x40) {
95
+ &error_abort);
57
+ i |= 0x780;
58
+ } else {
59
+ i |= 0x800;
60
+ }
61
+ n |= i << 19;
62
+
96
+
63
+ fd = tcg_temp_new_i32();
97
+ sysbus_realize(sbd, &error_fatal);
64
+ tcg_gen_movi_i32(fd, n);
98
+ memory_region_add_subregion(&s->mr_ps, MM_CRL,
65
+
99
+ sysbus_mmio_get_region(sbd, 0));
66
+ for (;;) {
100
+ sysbus_connect_irq(sbd, 0, pic[VERSAL_CRL_IRQ]);
67
+ neon_store_reg32(fd, vd);
68
+
69
+ if (veclen == 0) {
70
+ break;
71
+ }
72
+
73
+ /* Set up the operands for the next iteration */
74
+ veclen--;
75
+ vd = ((vd + delta_d) & (bank_mask - 1)) | (vd & bank_mask);
76
+ }
77
+
78
+ tcg_temp_free_i32(fd);
79
+ return true;
80
+}
101
+}
81
+
102
+
82
+static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
103
/* This takes the board allocated linear DDR memory and creates aliases
83
+{
104
* for each split DDR range/aperture on the Versal address map.
84
+ uint32_t delta_d = 0;
85
+ uint32_t bank_mask = 0;
86
+ int veclen = s->vec_len;
87
+ TCGv_i64 fd;
88
+ uint32_t n, i, vd;
89
+
90
+ vd = a->vd;
91
+
92
+ /* UNDEF accesses to D16-D31 if they don't exist. */
93
+ if (!dc_isar_feature(aa32_fp_d32, s) && (vd & 0x10)) {
94
+ return false;
95
+ }
96
+
97
+ if (!dc_isar_feature(aa32_fpshvec, s) &&
98
+ (veclen != 0 || s->vec_stride != 0)) {
99
+ return false;
100
+ }
101
+
102
+ if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
103
+ return false;
104
+ }
105
+
106
+ if (!vfp_access_check(s)) {
107
+ return true;
108
+ }
109
+
110
+ if (veclen > 0) {
111
+ bank_mask = 0xc;
112
+ /* Figure out what type of vector operation this is. */
113
+ if ((vd & bank_mask) == 0) {
114
+ /* scalar */
115
+ veclen = 0;
116
+ } else {
117
+ delta_d = (s->vec_stride >> 1) + 1;
118
+ }
119
+ }
120
+
121
+ n = (a->imm4h << 28) & 0x80000000;
122
+ i = ((a->imm4h << 4) & 0x70) | a->imm4l;
123
+ if (i & 0x40) {
124
+ i |= 0x3f80;
125
+ } else {
126
+ i |= 0x4000;
127
+ }
128
+ n |= i << 16;
129
+
130
+ fd = tcg_temp_new_i64();
131
+ tcg_gen_movi_i64(fd, ((uint64_t)n) << 32);
132
+
133
+ for (;;) {
134
+ neon_store_reg64(fd, vd);
135
+
136
+ if (veclen == 0) {
137
+ break;
138
+ }
139
+
140
+ /* Set up the operands for the next iteration */
141
+ veclen--;
142
+ vd = ((vd + delta_d) & (bank_mask - 1)) | (vd & bank_mask);
143
+ }
144
+
145
+ tcg_temp_free_i64(fd);
146
+ return true;
147
+}
148
diff --git a/target/arm/translate.c b/target/arm/translate.c
149
index XXXXXXX..XXXXXXX 100644
150
--- a/target/arm/translate.c
151
+++ b/target/arm/translate.c
152
@@ -XXX,XX +XXX,XX @@ static void gen_neon_dup_high16(TCGv_i32 var)
153
*/
105
*/
154
static int disas_vfp_insn(DisasContext *s, uint32_t insn)
106
@@ -XXX,XX +XXX,XX @@ static void versal_unimp(Versal *s)
155
{
107
156
- uint32_t rd, rn, rm, op, i, n, delta_d, delta_m, bank_mask;
108
versal_unimp_area(s, "psm", &s->mr_ps,
157
+ uint32_t rd, rn, rm, op, delta_d, delta_m, bank_mask;
109
MM_PSM_START, MM_PSM_END - MM_PSM_START);
158
int dp, veclen;
110
- versal_unimp_area(s, "crl", &s->mr_ps,
159
TCGv_i32 tmp;
111
- MM_CRL, MM_CRL_SIZE);
160
TCGv_i32 tmp2;
112
versal_unimp_area(s, "crf", &s->mr_ps,
161
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
113
MM_FPD_CRF, MM_FPD_CRF_SIZE);
162
rn = VFP_SREG_N(insn);
114
versal_unimp_area(s, "apu", &s->mr_ps,
163
115
@@ -XXX,XX +XXX,XX @@ static void versal_realize(DeviceState *dev, Error **errp)
164
switch (op) {
116
versal_create_efuse(s, pic);
165
- case 0 ... 13:
117
versal_create_pmc_iou_slcr(s, pic);
166
+ case 0 ... 14:
118
versal_create_ospi(s, pic);
167
/* Already handled by decodetree */
119
+ versal_create_crl(s, pic);
168
return 1;
120
versal_map_ddr(s);
169
default:
121
versal_unimp(s);
170
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
122
171
for (;;) {
172
/* Perform the calculation. */
173
switch (op) {
174
- case 14: /* fconst */
175
- if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
176
- return 1;
177
- }
178
-
179
- n = (insn << 12) & 0x80000000;
180
- i = ((insn >> 12) & 0x70) | (insn & 0xf);
181
- if (dp) {
182
- if (i & 0x40)
183
- i |= 0x3f80;
184
- else
185
- i |= 0x4000;
186
- n |= i << 16;
187
- tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
188
- } else {
189
- if (i & 0x40)
190
- i |= 0x780;
191
- else
192
- i |= 0x800;
193
- n |= i << 19;
194
- tcg_gen_movi_i32(cpu_F0s, n);
195
- }
196
- break;
197
case 15: /* extension space */
198
switch (rn) {
199
case 0: /* cpy */
200
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
201
index XXXXXXX..XXXXXXX 100644
202
--- a/target/arm/vfp.decode
203
+++ b/target/arm/vfp.decode
204
@@ -XXX,XX +XXX,XX @@ VFM_sp ---- 1110 1.10 .... .... 1010 . o2:1 . 0 .... \
205
vm=%vm_sp vn=%vn_sp vd=%vd_sp o1=2
206
VFM_dp ---- 1110 1.10 .... .... 1011 . o2:1 . 0 .... \
207
vm=%vm_dp vn=%vn_dp vd=%vd_dp o1=2
208
+
209
+VMOV_imm_sp ---- 1110 1.11 imm4h:4 .... 1010 0000 imm4l:4 \
210
+ vd=%vd_sp
211
+VMOV_imm_dp ---- 1110 1.11 imm4h:4 .... 1011 0000 imm4l:4 \
212
+ vd=%vd_dp
213
--
123
--
214
2.20.1
124
2.25.1
215
216
diff view generated by jsdifflib
1
Convert the VMINNM and VMAXNM instructions to decodetree.
1
The Exynos4210 SoC device currently uses a custom device
2
As with VSEL, we leave the trans_VMINMAXNM() function
2
"exynos4210.irq_gate" to model the OR gate that feeds each CPU's IRQ
3
in translate.c for the moment.
3
line. We have a standard TYPE_OR_IRQ device for this now, so use
4
that instead.
5
6
(This is a migration compatibility break, but that is OK for this
7
machine type.)
4
8
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-2-peter.maydell@linaro.org
7
---
12
---
8
target/arm/translate.c | 41 ++++++++++++++++++++++++------------
13
include/hw/arm/exynos4210.h | 1 +
9
target/arm/vfp-uncond.decode | 5 +++++
14
hw/arm/exynos4210.c | 31 ++++++++++++++++---------------
10
2 files changed, 33 insertions(+), 13 deletions(-)
15
2 files changed, 17 insertions(+), 15 deletions(-)
11
16
12
diff --git a/target/arm/translate.c b/target/arm/translate.c
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
13
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/translate.c
19
--- a/include/hw/arm/exynos4210.h
15
+++ b/target/arm/translate.c
20
+++ b/include/hw/arm/exynos4210.h
16
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
21
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
17
return true;
22
MemoryRegion bootreg_mem;
23
I2CBus *i2c_if[EXYNOS4210_I2C_NUMBER];
24
qemu_or_irq pl330_irq_orgate[EXYNOS4210_NUM_DMA];
25
+ qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
26
};
27
28
#define TYPE_EXYNOS4210_SOC "exynos4210"
29
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/exynos4210.c
32
+++ b/hw/arm/exynos4210.c
33
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
34
{
35
Exynos4210State *s = EXYNOS4210_SOC(socdev);
36
MemoryRegion *system_mem = get_system_memory();
37
- qemu_irq gate_irq[EXYNOS4210_NCPUS][EXYNOS4210_IRQ_GATE_NINPUTS];
38
SysBusDevice *busdev;
39
DeviceState *dev, *uart[4], *pl330[3];
40
int i, n;
41
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
42
43
/* IRQ Gate */
44
for (i = 0; i < EXYNOS4210_NCPUS; i++) {
45
- dev = qdev_new("exynos4210.irq_gate");
46
- qdev_prop_set_uint32(dev, "n_in", EXYNOS4210_IRQ_GATE_NINPUTS);
47
- sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
48
- /* Get IRQ Gate input in gate_irq */
49
- for (n = 0; n < EXYNOS4210_IRQ_GATE_NINPUTS; n++) {
50
- gate_irq[i][n] = qdev_get_gpio_in(dev, n);
51
- }
52
- busdev = SYS_BUS_DEVICE(dev);
53
-
54
- /* Connect IRQ Gate output to CPU's IRQ line */
55
- sysbus_connect_irq(busdev, 0,
56
- qdev_get_gpio_in(DEVICE(s->cpu[i]), ARM_CPU_IRQ));
57
+ DeviceState *orgate = DEVICE(&s->cpu_irq_orgate[i]);
58
+ object_property_set_int(OBJECT(orgate), "num-lines",
59
+ EXYNOS4210_IRQ_GATE_NINPUTS,
60
+ &error_abort);
61
+ qdev_realize(orgate, NULL, &error_abort);
62
+ qdev_connect_gpio_out(orgate, 0,
63
+ qdev_get_gpio_in(DEVICE(s->cpu[i]), ARM_CPU_IRQ));
64
}
65
66
/* Private memory region and Internal GIC */
67
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
68
sysbus_realize_and_unref(busdev, &error_fatal);
69
sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
70
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
71
- sysbus_connect_irq(busdev, n, gate_irq[n][0]);
72
+ sysbus_connect_irq(busdev, n,
73
+ qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 0));
74
}
75
for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
76
s->irqs.int_gic_irq[n] = qdev_get_gpio_in(dev, n);
77
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
78
/* Map Distributer interface */
79
sysbus_mmio_map(busdev, 1, EXYNOS4210_EXT_GIC_DIST_BASE_ADDR);
80
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
81
- sysbus_connect_irq(busdev, n, gate_irq[n][1]);
82
+ sysbus_connect_irq(busdev, n,
83
+ qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 1));
84
}
85
for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
86
s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(dev, n);
87
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
88
object_initialize_child(obj, name, orgate, TYPE_OR_IRQ);
89
g_free(name);
90
}
91
+
92
+ for (i = 0; i < ARRAY_SIZE(s->cpu_irq_orgate); i++) {
93
+ g_autofree char *name = g_strdup_printf("cpu-irq-orgate%d", i);
94
+ object_initialize_child(obj, name, &s->cpu_irq_orgate[i], TYPE_OR_IRQ);
95
+ }
18
}
96
}
19
97
20
-static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
98
static void exynos4210_class_init(ObjectClass *klass, void *data)
21
- uint32_t rm, uint32_t dp)
22
+static bool trans_VMINMAXNM(DisasContext *s, arg_VMINMAXNM *a)
23
{
24
- uint32_t vmin = extract32(insn, 6, 1);
25
- TCGv_ptr fpst = get_fpstatus_ptr(0);
26
+ uint32_t rd, rn, rm;
27
+ bool dp = a->dp;
28
+ bool vmin = a->op;
29
+ TCGv_ptr fpst;
30
+
31
+ if (!dc_isar_feature(aa32_vminmaxnm, s)) {
32
+ return false;
33
+ }
34
+
35
+ /* UNDEF accesses to D16-D31 if they don't exist */
36
+ if (dp && !dc_isar_feature(aa32_fp_d32, s) &&
37
+ ((a->vm | a->vn | a->vd) & 0x10)) {
38
+ return false;
39
+ }
40
+ rd = a->vd;
41
+ rn = a->vn;
42
+ rm = a->vm;
43
+
44
+ if (!vfp_access_check(s)) {
45
+ return true;
46
+ }
47
+
48
+ fpst = get_fpstatus_ptr(0);
49
50
if (dp) {
51
TCGv_i64 frn, frm, dest;
52
@@ -XXX,XX +XXX,XX @@ static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
53
}
54
55
tcg_temp_free_ptr(fpst);
56
- return 0;
57
+ return true;
58
}
59
60
static int handle_vrint(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
61
@@ -XXX,XX +XXX,XX @@ static const uint8_t fp_decode_rm[] = {
62
63
static int disas_vfp_misc_insn(DisasContext *s, uint32_t insn)
64
{
65
- uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
66
+ uint32_t rd, rm, dp = extract32(insn, 8, 1);
67
68
if (dp) {
69
VFP_DREG_D(rd, insn);
70
- VFP_DREG_N(rn, insn);
71
VFP_DREG_M(rm, insn);
72
} else {
73
rd = VFP_SREG_D(insn);
74
- rn = VFP_SREG_N(insn);
75
rm = VFP_SREG_M(insn);
76
}
77
78
- if ((insn & 0x0fb00e10) == 0x0e800a00 &&
79
- dc_isar_feature(aa32_vminmaxnm, s)) {
80
- return handle_vminmaxnm(insn, rd, rn, rm, dp);
81
- } else if ((insn & 0x0fbc0ed0) == 0x0eb80a40 &&
82
- dc_isar_feature(aa32_vrint, s)) {
83
+ if ((insn & 0x0fbc0ed0) == 0x0eb80a40 &&
84
+ dc_isar_feature(aa32_vrint, s)) {
85
/* VRINTA, VRINTN, VRINTP, VRINTM */
86
int rounding = fp_decode_rm[extract32(insn, 16, 2)];
87
return handle_vrint(insn, rd, rm, dp, rounding);
88
diff --git a/target/arm/vfp-uncond.decode b/target/arm/vfp-uncond.decode
89
index XXXXXXX..XXXXXXX 100644
90
--- a/target/arm/vfp-uncond.decode
91
+++ b/target/arm/vfp-uncond.decode
92
@@ -XXX,XX +XXX,XX @@ VSEL 1111 1110 0. cc:2 .... .... 1010 .0.0 .... \
93
vm=%vm_sp vn=%vn_sp vd=%vd_sp dp=0
94
VSEL 1111 1110 0. cc:2 .... .... 1011 .0.0 .... \
95
vm=%vm_dp vn=%vn_dp vd=%vd_dp dp=1
96
+
97
+VMINMAXNM 1111 1110 1.00 .... .... 1010 . op:1 .0 .... \
98
+ vm=%vm_sp vn=%vn_sp vd=%vd_sp dp=0
99
+VMINMAXNM 1111 1110 1.00 .... .... 1011 . op:1 .0 .... \
100
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp dp=1
101
--
99
--
102
2.20.1
100
2.25.1
103
104
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
Now we have removed the only use of TYPE_EXYNOS4210_IRQ_GATE we can
2
delete the device entirely.
2
3
3
This replaces 3 target-specific implementations for BIT, BIF, and BSL.
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Francisco Iglesias <frasse.iglesias@gmail.com>
6
Message-id: 20220404154658.565020-3-peter.maydell@linaro.org
7
---
8
hw/intc/exynos4210_gic.c | 107 ---------------------------------------
9
1 file changed, 107 deletions(-)
4
10
5
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
11
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
6
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
7
Message-id: 20190518191934.21887-3-richard.henderson@linaro.org
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
---
10
target/arm/translate-a64.h | 2 +
11
target/arm/translate.h | 3 --
12
target/arm/translate-a64.c | 15 ++++++--
13
target/arm/translate.c | 78 +++-----------------------------------
14
4 files changed, 20 insertions(+), 78 deletions(-)
15
16
diff --git a/target/arm/translate-a64.h b/target/arm/translate-a64.h
17
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate-a64.h
13
--- a/hw/intc/exynos4210_gic.c
19
+++ b/target/arm/translate-a64.h
14
+++ b/hw/intc/exynos4210_gic.c
20
@@ -XXX,XX +XXX,XX @@ typedef void GVecGen2iFn(unsigned, uint32_t, uint32_t, int64_t,
15
@@ -XXX,XX +XXX,XX @@ static void exynos4210_gic_register_types(void)
21
uint32_t, uint32_t);
22
typedef void GVecGen3Fn(unsigned, uint32_t, uint32_t,
23
uint32_t, uint32_t, uint32_t);
24
+typedef void GVecGen4Fn(unsigned, uint32_t, uint32_t, uint32_t,
25
+ uint32_t, uint32_t, uint32_t);
26
27
#endif /* TARGET_ARM_TRANSLATE_A64_H */
28
diff --git a/target/arm/translate.h b/target/arm/translate.h
29
index XXXXXXX..XXXXXXX 100644
30
--- a/target/arm/translate.h
31
+++ b/target/arm/translate.h
32
@@ -XXX,XX +XXX,XX @@ static inline void gen_ss_advance(DisasContext *s)
33
}
16
}
34
17
35
/* Vector operations shared between ARM and AArch64. */
18
type_init(exynos4210_gic_register_types)
36
-extern const GVecGen3 bsl_op;
19
-
37
-extern const GVecGen3 bit_op;
20
-/* IRQ OR Gate struct.
38
-extern const GVecGen3 bif_op;
21
- *
39
extern const GVecGen3 mla_op[4];
22
- * This device models an OR gate. There are n_in input qdev gpio lines and one
40
extern const GVecGen3 mls_op[4];
23
- * output sysbus IRQ line. The output IRQ level is formed as OR between all
41
extern const GVecGen3 cmtst_op[4];
24
- * gpio inputs.
42
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
43
index XXXXXXX..XXXXXXX 100644
44
--- a/target/arm/translate-a64.c
45
+++ b/target/arm/translate-a64.c
46
@@ -XXX,XX +XXX,XX @@ static void gen_gvec_fn3(DisasContext *s, bool is_q, int rd, int rn, int rm,
47
vec_full_reg_offset(s, rm), is_q ? 16 : 8, vec_full_reg_size(s));
48
}
49
50
+/* Expand a 4-operand AdvSIMD vector operation using an expander function. */
51
+static void gen_gvec_fn4(DisasContext *s, bool is_q, int rd, int rn, int rm,
52
+ int rx, GVecGen4Fn *gvec_fn, int vece)
53
+{
54
+ gvec_fn(vece, vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
55
+ vec_full_reg_offset(s, rm), vec_full_reg_offset(s, rx),
56
+ is_q ? 16 : 8, vec_full_reg_size(s));
57
+}
58
+
59
/* Expand a 2-operand + immediate AdvSIMD vector operation using
60
* an op descriptor.
61
*/
62
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_logic(DisasContext *s, uint32_t insn)
63
return;
64
65
case 5: /* BSL bitwise select */
66
- gen_gvec_op3(s, is_q, rd, rn, rm, &bsl_op);
67
+ gen_gvec_fn4(s, is_q, rd, rd, rn, rm, tcg_gen_gvec_bitsel, 0);
68
return;
69
case 6: /* BIT, bitwise insert if true */
70
- gen_gvec_op3(s, is_q, rd, rn, rm, &bit_op);
71
+ gen_gvec_fn4(s, is_q, rd, rm, rn, rd, tcg_gen_gvec_bitsel, 0);
72
return;
73
case 7: /* BIF, bitwise insert if false */
74
- gen_gvec_op3(s, is_q, rd, rn, rm, &bif_op);
75
+ gen_gvec_fn4(s, is_q, rd, rm, rd, rn, tcg_gen_gvec_bitsel, 0);
76
return;
77
78
default:
79
diff --git a/target/arm/translate.c b/target/arm/translate.c
80
index XXXXXXX..XXXXXXX 100644
81
--- a/target/arm/translate.c
82
+++ b/target/arm/translate.c
83
@@ -XXX,XX +XXX,XX @@ static int do_v81_helper(DisasContext *s, gen_helper_gvec_3_ptr *fn,
84
return 1;
85
}
86
87
-/*
88
- * Expanders for VBitOps_VBIF, VBIT, VBSL.
89
- */
25
- */
90
-static void gen_bsl_i64(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
26
-
27
-#define TYPE_EXYNOS4210_IRQ_GATE "exynos4210.irq_gate"
28
-OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210IRQGateState, EXYNOS4210_IRQ_GATE)
29
-
30
-struct Exynos4210IRQGateState {
31
- SysBusDevice parent_obj;
32
-
33
- uint32_t n_in; /* inputs amount */
34
- uint32_t *level; /* input levels */
35
- qemu_irq out; /* output IRQ */
36
-};
37
-
38
-static Property exynos4210_irq_gate_properties[] = {
39
- DEFINE_PROP_UINT32("n_in", Exynos4210IRQGateState, n_in, 1),
40
- DEFINE_PROP_END_OF_LIST(),
41
-};
42
-
43
-static const VMStateDescription vmstate_exynos4210_irq_gate = {
44
- .name = "exynos4210.irq_gate",
45
- .version_id = 2,
46
- .minimum_version_id = 2,
47
- .fields = (VMStateField[]) {
48
- VMSTATE_VBUFFER_UINT32(level, Exynos4210IRQGateState, 1, NULL, n_in),
49
- VMSTATE_END_OF_LIST()
50
- }
51
-};
52
-
53
-/* Process a change in IRQ input. */
54
-static void exynos4210_irq_gate_handler(void *opaque, int irq, int level)
91
-{
55
-{
92
- tcg_gen_xor_i64(rn, rn, rm);
56
- Exynos4210IRQGateState *s = (Exynos4210IRQGateState *)opaque;
93
- tcg_gen_and_i64(rn, rn, rd);
57
- uint32_t i;
94
- tcg_gen_xor_i64(rd, rm, rn);
58
-
59
- assert(irq < s->n_in);
60
-
61
- s->level[irq] = level;
62
-
63
- for (i = 0; i < s->n_in; i++) {
64
- if (s->level[i] >= 1) {
65
- qemu_irq_raise(s->out);
66
- return;
67
- }
68
- }
69
-
70
- qemu_irq_lower(s->out);
95
-}
71
-}
96
-
72
-
97
-static void gen_bit_i64(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
73
-static void exynos4210_irq_gate_reset(DeviceState *d)
98
-{
74
-{
99
- tcg_gen_xor_i64(rn, rn, rd);
75
- Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(d);
100
- tcg_gen_and_i64(rn, rn, rm);
76
-
101
- tcg_gen_xor_i64(rd, rd, rn);
77
- memset(s->level, 0, s->n_in * sizeof(*s->level));
102
-}
78
-}
103
-
79
-
104
-static void gen_bif_i64(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
80
-/*
81
- * IRQ Gate initialization.
82
- */
83
-static void exynos4210_irq_gate_init(Object *obj)
105
-{
84
-{
106
- tcg_gen_xor_i64(rn, rn, rd);
85
- Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(obj);
107
- tcg_gen_andc_i64(rn, rn, rm);
86
- SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
108
- tcg_gen_xor_i64(rd, rd, rn);
87
-
88
- sysbus_init_irq(sbd, &s->out);
109
-}
89
-}
110
-
90
-
111
-static void gen_bsl_vec(unsigned vece, TCGv_vec rd, TCGv_vec rn, TCGv_vec rm)
91
-static void exynos4210_irq_gate_realize(DeviceState *dev, Error **errp)
112
-{
92
-{
113
- tcg_gen_xor_vec(vece, rn, rn, rm);
93
- Exynos4210IRQGateState *s = EXYNOS4210_IRQ_GATE(dev);
114
- tcg_gen_and_vec(vece, rn, rn, rd);
94
-
115
- tcg_gen_xor_vec(vece, rd, rm, rn);
95
- /* Allocate general purpose input signals and connect a handler to each of
96
- * them */
97
- qdev_init_gpio_in(dev, exynos4210_irq_gate_handler, s->n_in);
98
-
99
- s->level = g_malloc0(s->n_in * sizeof(*s->level));
116
-}
100
-}
117
-
101
-
118
-static void gen_bit_vec(unsigned vece, TCGv_vec rd, TCGv_vec rn, TCGv_vec rm)
102
-static void exynos4210_irq_gate_class_init(ObjectClass *klass, void *data)
119
-{
103
-{
120
- tcg_gen_xor_vec(vece, rn, rn, rd);
104
- DeviceClass *dc = DEVICE_CLASS(klass);
121
- tcg_gen_and_vec(vece, rn, rn, rm);
105
-
122
- tcg_gen_xor_vec(vece, rd, rd, rn);
106
- dc->reset = exynos4210_irq_gate_reset;
107
- dc->vmsd = &vmstate_exynos4210_irq_gate;
108
- device_class_set_props(dc, exynos4210_irq_gate_properties);
109
- dc->realize = exynos4210_irq_gate_realize;
123
-}
110
-}
124
-
111
-
125
-static void gen_bif_vec(unsigned vece, TCGv_vec rd, TCGv_vec rn, TCGv_vec rm)
112
-static const TypeInfo exynos4210_irq_gate_info = {
113
- .name = TYPE_EXYNOS4210_IRQ_GATE,
114
- .parent = TYPE_SYS_BUS_DEVICE,
115
- .instance_size = sizeof(Exynos4210IRQGateState),
116
- .instance_init = exynos4210_irq_gate_init,
117
- .class_init = exynos4210_irq_gate_class_init,
118
-};
119
-
120
-static void exynos4210_irq_gate_register_types(void)
126
-{
121
-{
127
- tcg_gen_xor_vec(vece, rn, rn, rd);
122
- type_register_static(&exynos4210_irq_gate_info);
128
- tcg_gen_andc_vec(vece, rn, rn, rm);
129
- tcg_gen_xor_vec(vece, rd, rd, rn);
130
-}
123
-}
131
-
124
-
132
-const GVecGen3 bsl_op = {
125
-type_init(exynos4210_irq_gate_register_types)
133
- .fni8 = gen_bsl_i64,
134
- .fniv = gen_bsl_vec,
135
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
136
- .load_dest = true
137
-};
138
-
139
-const GVecGen3 bit_op = {
140
- .fni8 = gen_bit_i64,
141
- .fniv = gen_bit_vec,
142
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
143
- .load_dest = true
144
-};
145
-
146
-const GVecGen3 bif_op = {
147
- .fni8 = gen_bif_i64,
148
- .fniv = gen_bif_vec,
149
- .prefer_i64 = TCG_TARGET_REG_BITS == 64,
150
- .load_dest = true
151
-};
152
-
153
static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
154
{
155
tcg_gen_vec_sar8i_i64(a, a, shift);
156
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
157
vec_size, vec_size);
158
break;
159
case 5: /* VBSL */
160
- tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
161
- vec_size, vec_size, &bsl_op);
162
+ tcg_gen_gvec_bitsel(MO_8, rd_ofs, rd_ofs, rn_ofs, rm_ofs,
163
+ vec_size, vec_size);
164
break;
165
case 6: /* VBIT */
166
- tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
167
- vec_size, vec_size, &bit_op);
168
+ tcg_gen_gvec_bitsel(MO_8, rd_ofs, rm_ofs, rn_ofs, rd_ofs,
169
+ vec_size, vec_size);
170
break;
171
case 7: /* VBIF */
172
- tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs,
173
- vec_size, vec_size, &bif_op);
174
+ tcg_gen_gvec_bitsel(MO_8, rd_ofs, rm_ofs, rd_ofs, rn_ofs,
175
+ vec_size, vec_size);
176
break;
177
}
178
return 0;
179
--
126
--
180
2.20.1
127
2.25.1
181
182
diff view generated by jsdifflib
1
Convert the VFP VMLA instruction to decodetree.
1
The exynos4210 SoC mostly creates its child devices as if it were
2
2
board code. This includes the a9mpcore object. Switch that to a
3
This is the first of the VFP 3-operand data processing instructions,
3
new-style "embedded in the state struct" creation, because in the
4
so we include in this patch the code which loops over the elements
4
next commit we're going to want to refer to the object again further
5
for an old-style VFP vector operation. The existing code to do this
5
down in the exynos4210_realize() function.
6
looping uses the deprecated cpu_F0s/F0d/F1s/F1d TCG globals; since
7
we are going to be converting instructions one at a time anyway
8
we can take the opportunity to make the new loop use TCG temporaries,
9
which means we can do that conversion one operation at a time
10
rather than needing to do it all in one go.
11
12
We include an UNDEF check which was missing in the old code:
13
short-vector operations (with stride or length non-zero) were
14
deprecated in v7A and must UNDEF in v8A, so if the MVFR0 FPShVec
15
field does not indicate that support for short vectors is present
16
we UNDEF the operations that would use them. (This is a change
17
of behaviour for Cortex-A7, Cortex-A15 and the v8 CPUs, which
18
previously were all incorrectly allowing short-vector operations.)
19
20
Note that the conversion fixes a bug in the old code for the
21
case of VFP short-vector "mixed scalar/vector operations". These
22
happen where the destination register is in a vector bank but
23
but the second operand is in a scalar bank. For example
24
vmla.f64 d10, d1, d16 with length 2 stride 2
25
is equivalent to the pair of scalar operations
26
vmla.f64 d10, d1, d16
27
vmla.f64 d8, d3, d16
28
where the destination and first input register cycle through
29
their vector but the second input is scalar (d16). In the
30
old decoder the gen_vfp_F1_mul() operation uses cpu_F1{s,d}
31
as a temporary output for the multiply, which trashes the
32
second input operand. For the fully-scalar case (where we
33
never do a second iteration) and the fully-vector case
34
(where the loop loads the new second input operand) this
35
doesn't matter, but for the mixed scalar/vector case we
36
will end up using the wrong value for later loop iterations.
37
In the new code we use TCG temporaries and so avoid the bug.
38
This bug is present for all the multiply-accumulate insns
39
that operate on short vectors: VMLA, VMLS, VNMLA, VNMLS.
40
41
Note 2: the expression used to calculate the next register
42
number in the vector bank is not in fact correct; we leave
43
this behaviour unchanged from the old decoder and will
44
fix this bug later in the series.
45
6
46
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
47
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
9
Message-id: 20220404154658.565020-4-peter.maydell@linaro.org
48
---
10
---
49
target/arm/cpu.h | 5 +
11
include/hw/arm/exynos4210.h | 2 ++
50
target/arm/translate-vfp.inc.c | 205 +++++++++++++++++++++++++++++++++
12
hw/arm/exynos4210.c | 11 ++++++-----
51
target/arm/translate.c | 14 ++-
13
2 files changed, 8 insertions(+), 5 deletions(-)
52
target/arm/vfp.decode | 6 +
53
4 files changed, 224 insertions(+), 6 deletions(-)
54
14
55
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
15
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
56
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
57
--- a/target/arm/cpu.h
17
--- a/include/hw/arm/exynos4210.h
58
+++ b/target/arm/cpu.h
18
+++ b/include/hw/arm/exynos4210.h
59
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_fp_d32(const ARMISARegisters *id)
19
@@ -XXX,XX +XXX,XX @@
60
return FIELD_EX64(id->mvfr0, MVFR0, SIMDREG) >= 2;
20
21
#include "hw/or-irq.h"
22
#include "hw/sysbus.h"
23
+#include "hw/cpu/a9mpcore.h"
24
#include "target/arm/cpu-qom.h"
25
#include "qom/object.h"
26
27
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
28
I2CBus *i2c_if[EXYNOS4210_I2C_NUMBER];
29
qemu_or_irq pl330_irq_orgate[EXYNOS4210_NUM_DMA];
30
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
31
+ A9MPPrivState a9mpcore;
32
};
33
34
#define TYPE_EXYNOS4210_SOC "exynos4210"
35
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
36
index XXXXXXX..XXXXXXX 100644
37
--- a/hw/arm/exynos4210.c
38
+++ b/hw/arm/exynos4210.c
39
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
40
}
41
42
/* Private memory region and Internal GIC */
43
- dev = qdev_new(TYPE_A9MPCORE_PRIV);
44
- qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
45
- busdev = SYS_BUS_DEVICE(dev);
46
- sysbus_realize_and_unref(busdev, &error_fatal);
47
+ qdev_prop_set_uint32(DEVICE(&s->a9mpcore), "num-cpu", EXYNOS4210_NCPUS);
48
+ busdev = SYS_BUS_DEVICE(&s->a9mpcore);
49
+ sysbus_realize(busdev, &error_fatal);
50
sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR);
51
for (n = 0; n < EXYNOS4210_NCPUS; n++) {
52
sysbus_connect_irq(busdev, n,
53
qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 0));
54
}
55
for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
56
- s->irqs.int_gic_irq[n] = qdev_get_gpio_in(dev, n);
57
+ s->irqs.int_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
58
}
59
60
/* Cache controller */
61
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
62
g_autofree char *name = g_strdup_printf("cpu-irq-orgate%d", i);
63
object_initialize_child(obj, name, &s->cpu_irq_orgate[i], TYPE_OR_IRQ);
64
}
65
+
66
+ object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
61
}
67
}
62
68
63
+static inline bool isar_feature_aa32_fpshvec(const ARMISARegisters *id)
69
static void exynos4210_class_init(ObjectClass *klass, void *data)
64
+{
65
+ return FIELD_EX64(id->mvfr0, MVFR0, FPSHVEC) > 0;
66
+}
67
+
68
/*
69
* We always set the FP and SIMD FP16 fields to indicate identical
70
* levels of support (assuming SIMD is implemented at all), so
71
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
72
index XXXXXXX..XXXXXXX 100644
73
--- a/target/arm/translate-vfp.inc.c
74
+++ b/target/arm/translate-vfp.inc.c
75
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDM_VSTM_dp(DisasContext *s, arg_VLDM_VSTM_dp *a)
76
77
return true;
78
}
79
+
80
+/*
81
+ * Types for callbacks for do_vfp_3op_sp() and do_vfp_3op_dp().
82
+ * The callback should emit code to write a value to vd. If
83
+ * do_vfp_3op_{sp,dp}() was passed reads_vd then the TCGv vd
84
+ * will contain the old value of the relevant VFP register;
85
+ * otherwise it must be written to only.
86
+ */
87
+typedef void VFPGen3OpSPFn(TCGv_i32 vd,
88
+ TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst);
89
+typedef void VFPGen3OpDPFn(TCGv_i64 vd,
90
+ TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst);
91
+
92
+/*
93
+ * Perform a 3-operand VFP data processing instruction. fn is the
94
+ * callback to do the actual operation; this function deals with the
95
+ * code to handle looping around for VFP vector processing.
96
+ */
97
+static bool do_vfp_3op_sp(DisasContext *s, VFPGen3OpSPFn *fn,
98
+ int vd, int vn, int vm, bool reads_vd)
99
+{
100
+ uint32_t delta_m = 0;
101
+ uint32_t delta_d = 0;
102
+ uint32_t bank_mask = 0;
103
+ int veclen = s->vec_len;
104
+ TCGv_i32 f0, f1, fd;
105
+ TCGv_ptr fpst;
106
+
107
+ if (!dc_isar_feature(aa32_fpshvec, s) &&
108
+ (veclen != 0 || s->vec_stride != 0)) {
109
+ return false;
110
+ }
111
+
112
+ if (!vfp_access_check(s)) {
113
+ return true;
114
+ }
115
+
116
+ if (veclen > 0) {
117
+ bank_mask = 0x18;
118
+
119
+ /* Figure out what type of vector operation this is. */
120
+ if ((vd & bank_mask) == 0) {
121
+ /* scalar */
122
+ veclen = 0;
123
+ } else {
124
+ delta_d = s->vec_stride + 1;
125
+
126
+ if ((vm & bank_mask) == 0) {
127
+ /* mixed scalar/vector */
128
+ delta_m = 0;
129
+ } else {
130
+ /* vector */
131
+ delta_m = delta_d;
132
+ }
133
+ }
134
+ }
135
+
136
+ f0 = tcg_temp_new_i32();
137
+ f1 = tcg_temp_new_i32();
138
+ fd = tcg_temp_new_i32();
139
+ fpst = get_fpstatus_ptr(0);
140
+
141
+ neon_load_reg32(f0, vn);
142
+ neon_load_reg32(f1, vm);
143
+
144
+ for (;;) {
145
+ if (reads_vd) {
146
+ neon_load_reg32(fd, vd);
147
+ }
148
+ fn(fd, f0, f1, fpst);
149
+ neon_store_reg32(fd, vd);
150
+
151
+ if (veclen == 0) {
152
+ break;
153
+ }
154
+
155
+ /* Set up the operands for the next iteration */
156
+ veclen--;
157
+ vd = ((vd + delta_d) & (bank_mask - 1)) | (vd & bank_mask);
158
+ vn = ((vn + delta_d) & (bank_mask - 1)) | (vn & bank_mask);
159
+ neon_load_reg32(f0, vn);
160
+ if (delta_m) {
161
+ vm = ((vm + delta_m) & (bank_mask - 1)) | (vm & bank_mask);
162
+ neon_load_reg32(f1, vm);
163
+ }
164
+ }
165
+
166
+ tcg_temp_free_i32(f0);
167
+ tcg_temp_free_i32(f1);
168
+ tcg_temp_free_i32(fd);
169
+ tcg_temp_free_ptr(fpst);
170
+
171
+ return true;
172
+}
173
+
174
+static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn,
175
+ int vd, int vn, int vm, bool reads_vd)
176
+{
177
+ uint32_t delta_m = 0;
178
+ uint32_t delta_d = 0;
179
+ uint32_t bank_mask = 0;
180
+ int veclen = s->vec_len;
181
+ TCGv_i64 f0, f1, fd;
182
+ TCGv_ptr fpst;
183
+
184
+ /* UNDEF accesses to D16-D31 if they don't exist */
185
+ if (!dc_isar_feature(aa32_fp_d32, s) && ((vd | vn | vm) & 0x10)) {
186
+ return false;
187
+ }
188
+
189
+ if (!dc_isar_feature(aa32_fpshvec, s) &&
190
+ (veclen != 0 || s->vec_stride != 0)) {
191
+ return false;
192
+ }
193
+
194
+ if (!vfp_access_check(s)) {
195
+ return true;
196
+ }
197
+
198
+ if (veclen > 0) {
199
+ bank_mask = 0xc;
200
+
201
+ /* Figure out what type of vector operation this is. */
202
+ if ((vd & bank_mask) == 0) {
203
+ /* scalar */
204
+ veclen = 0;
205
+ } else {
206
+ delta_d = (s->vec_stride >> 1) + 1;
207
+
208
+ if ((vm & bank_mask) == 0) {
209
+ /* mixed scalar/vector */
210
+ delta_m = 0;
211
+ } else {
212
+ /* vector */
213
+ delta_m = delta_d;
214
+ }
215
+ }
216
+ }
217
+
218
+ f0 = tcg_temp_new_i64();
219
+ f1 = tcg_temp_new_i64();
220
+ fd = tcg_temp_new_i64();
221
+ fpst = get_fpstatus_ptr(0);
222
+
223
+ neon_load_reg64(f0, vn);
224
+ neon_load_reg64(f1, vm);
225
+
226
+ for (;;) {
227
+ if (reads_vd) {
228
+ neon_load_reg64(fd, vd);
229
+ }
230
+ fn(fd, f0, f1, fpst);
231
+ neon_store_reg64(fd, vd);
232
+
233
+ if (veclen == 0) {
234
+ break;
235
+ }
236
+ /* Set up the operands for the next iteration */
237
+ veclen--;
238
+ vd = ((vd + delta_d) & (bank_mask - 1)) | (vd & bank_mask);
239
+ vn = ((vn + delta_d) & (bank_mask - 1)) | (vn & bank_mask);
240
+ neon_load_reg64(f0, vn);
241
+ if (delta_m) {
242
+ vm = ((vm + delta_m) & (bank_mask - 1)) | (vm & bank_mask);
243
+ neon_load_reg64(f1, vm);
244
+ }
245
+ }
246
+
247
+ tcg_temp_free_i64(f0);
248
+ tcg_temp_free_i64(f1);
249
+ tcg_temp_free_i64(fd);
250
+ tcg_temp_free_ptr(fpst);
251
+
252
+ return true;
253
+}
254
+
255
+static void gen_VMLA_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
256
+{
257
+ /* Note that order of inputs to the add matters for NaNs */
258
+ TCGv_i32 tmp = tcg_temp_new_i32();
259
+
260
+ gen_helper_vfp_muls(tmp, vn, vm, fpst);
261
+ gen_helper_vfp_adds(vd, vd, tmp, fpst);
262
+ tcg_temp_free_i32(tmp);
263
+}
264
+
265
+static bool trans_VMLA_sp(DisasContext *s, arg_VMLA_sp *a)
266
+{
267
+ return do_vfp_3op_sp(s, gen_VMLA_sp, a->vd, a->vn, a->vm, true);
268
+}
269
+
270
+static void gen_VMLA_dp(TCGv_i64 vd, TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst)
271
+{
272
+ /* Note that order of inputs to the add matters for NaNs */
273
+ TCGv_i64 tmp = tcg_temp_new_i64();
274
+
275
+ gen_helper_vfp_muld(tmp, vn, vm, fpst);
276
+ gen_helper_vfp_addd(vd, vd, tmp, fpst);
277
+ tcg_temp_free_i64(tmp);
278
+}
279
+
280
+static bool trans_VMLA_dp(DisasContext *s, arg_VMLA_sp *a)
281
+{
282
+ return do_vfp_3op_dp(s, gen_VMLA_dp, a->vd, a->vn, a->vm, true);
283
+}
284
diff --git a/target/arm/translate.c b/target/arm/translate.c
285
index XXXXXXX..XXXXXXX 100644
286
--- a/target/arm/translate.c
287
+++ b/target/arm/translate.c
288
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
289
op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
290
rn = VFP_SREG_N(insn);
291
292
+ switch (op) {
293
+ case 0:
294
+ /* Already handled by decodetree */
295
+ return 1;
296
+ default:
297
+ break;
298
+ }
299
+
300
if (op == 15) {
301
/* rn is opcode, encoded as per VFP_SREG_N. */
302
switch (rn) {
303
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
304
for (;;) {
305
/* Perform the calculation. */
306
switch (op) {
307
- case 0: /* VMLA: fd + (fn * fm) */
308
- /* Note that order of inputs to the add matters for NaNs */
309
- gen_vfp_F1_mul(dp);
310
- gen_mov_F0_vreg(dp, rd);
311
- gen_vfp_add(dp);
312
- break;
313
case 1: /* VMLS: fd + -(fn * fm) */
314
gen_vfp_mul(dp);
315
gen_vfp_F1_neg(dp);
316
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
317
index XXXXXXX..XXXXXXX 100644
318
--- a/target/arm/vfp.decode
319
+++ b/target/arm/vfp.decode
320
@@ -XXX,XX +XXX,XX @@ VLDM_VSTM_sp ---- 1101 0.1 l:1 rn:4 .... 1010 imm:8 \
321
vd=%vd_sp p=1 u=0 w=1
322
VLDM_VSTM_dp ---- 1101 0.1 l:1 rn:4 .... 1011 imm:8 \
323
vd=%vd_dp p=1 u=0 w=1
324
+
325
+# 3-register VFP data-processing; bits [23,21:20,6] identify the operation.
326
+VMLA_sp ---- 1110 0.00 .... .... 1010 .0.0 .... \
327
+ vm=%vm_sp vn=%vn_sp vd=%vd_sp
328
+VMLA_dp ---- 1110 0.00 .... .... 1011 .0.0 .... \
329
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
330
--
70
--
331
2.20.1
71
2.25.1
332
333
diff view generated by jsdifflib
1
Convert the VJCVT instruction to decodetree.
1
The only time we use the int_gic_irq[] array in the Exynos4210Irq
2
struct is in the exynos4210_realize() function: we initialize it with
3
the GPIO inputs of the a9mpcore device, and then a bit later on we
4
connect those to the outputs of the internal combiner. Now that the
5
a9mpcore object is easily accessible as s->a9mpcore we can make the
6
connection directly from one device to the other without going via
7
this array.
2
8
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-5-peter.maydell@linaro.org
5
---
12
---
6
target/arm/translate-vfp.inc.c | 28 ++++++++++++++++++++++++++++
13
include/hw/arm/exynos4210.h | 1 -
7
target/arm/translate.c | 12 +-----------
14
hw/arm/exynos4210.c | 6 ++----
8
target/arm/vfp.decode | 4 ++++
15
2 files changed, 2 insertions(+), 5 deletions(-)
9
3 files changed, 33 insertions(+), 11 deletions(-)
10
16
11
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
12
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-vfp.inc.c
19
--- a/include/hw/arm/exynos4210.h
14
+++ b/target/arm/translate-vfp.inc.c
20
+++ b/include/hw/arm/exynos4210.h
15
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_int_dp(DisasContext *s, arg_VCVT_int_dp *a)
21
@@ -XXX,XX +XXX,XX @@
16
tcg_temp_free_ptr(fpst);
22
typedef struct Exynos4210Irq {
17
return true;
23
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
18
}
24
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
19
+
25
- qemu_irq int_gic_irq[EXYNOS4210_INT_GIC_NIRQ];
20
+static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a)
26
qemu_irq ext_gic_irq[EXYNOS4210_EXT_GIC_NIRQ];
21
+{
27
qemu_irq board_irqs[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
22
+ TCGv_i32 vd;
28
} Exynos4210Irq;
23
+ TCGv_i64 vm;
29
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
24
+
25
+ if (!dc_isar_feature(aa32_jscvt, s)) {
26
+ return false;
27
+ }
28
+
29
+ /* UNDEF accesses to D16-D31 if they don't exist. */
30
+ if (!dc_isar_feature(aa32_fp_d32, s) && (a->vm & 0x10)) {
31
+ return false;
32
+ }
33
+
34
+ if (!vfp_access_check(s)) {
35
+ return true;
36
+ }
37
+
38
+ vm = tcg_temp_new_i64();
39
+ vd = tcg_temp_new_i32();
40
+ neon_load_reg64(vm, a->vm);
41
+ gen_helper_vjcvt(vd, vm, cpu_env);
42
+ neon_store_reg32(vd, a->vd);
43
+ tcg_temp_free_i64(vm);
44
+ tcg_temp_free_i32(vd);
45
+ return true;
46
+}
47
diff --git a/target/arm/translate.c b/target/arm/translate.c
48
index XXXXXXX..XXXXXXX 100644
30
index XXXXXXX..XXXXXXX 100644
49
--- a/target/arm/translate.c
31
--- a/hw/arm/exynos4210.c
50
+++ b/target/arm/translate.c
32
+++ b/hw/arm/exynos4210.c
51
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
33
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
52
return 1;
34
sysbus_connect_irq(busdev, n,
53
case 15:
35
qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 0));
54
switch (rn) {
36
}
55
- case 0 ... 17:
37
- for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) {
56
+ case 0 ... 19:
38
- s->irqs.int_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->a9mpcore), n);
57
/* Already handled by decodetree */
39
- }
58
return 1;
40
59
default:
41
/* Cache controller */
60
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
42
sysbus_create_simple("l2x0", EXYNOS4210_L2X0_BASE_ADDR, NULL);
61
rm_is_dp = false;
43
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
62
break;
44
busdev = SYS_BUS_DEVICE(dev);
63
45
sysbus_realize_and_unref(busdev, &error_fatal);
64
- case 0x13: /* vjcvt */
46
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
65
- if (!dp || !dc_isar_feature(aa32_jscvt, s)) {
47
- sysbus_connect_irq(busdev, n, s->irqs.int_gic_irq[n]);
66
- return 1;
48
+ sysbus_connect_irq(busdev, n,
67
- }
49
+ qdev_get_gpio_in(DEVICE(&s->a9mpcore), n));
68
- rd_is_dp = false;
50
}
69
- break;
51
exynos4210_combiner_get_gpioin(&s->irqs, dev, 0);
70
-
52
sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
71
default:
72
return 1;
73
}
74
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
75
switch (op) {
76
case 15: /* extension space */
77
switch (rn) {
78
- case 19: /* vjcvt */
79
- gen_helper_vjcvt(cpu_F0s, cpu_F0d, cpu_env);
80
- break;
81
case 20: /* fshto */
82
gen_vfp_shto(dp, 16 - rm, 0);
83
break;
84
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
85
index XXXXXXX..XXXXXXX 100644
86
--- a/target/arm/vfp.decode
87
+++ b/target/arm/vfp.decode
88
@@ -XXX,XX +XXX,XX @@ VCVT_int_sp ---- 1110 1.11 1000 .... 1010 s:1 1.0 .... \
89
vd=%vd_sp vm=%vm_sp
90
VCVT_int_dp ---- 1110 1.11 1000 .... 1011 s:1 1.0 .... \
91
vd=%vd_dp vm=%vm_sp
92
+
93
+# VJCVT is always dp to sp
94
+VJCVT ---- 1110 1.11 1001 .... 1011 11.0 .... \
95
+ vd=%vd_sp vm=%vm_dp
96
--
53
--
97
2.20.1
54
2.25.1
98
99
diff view generated by jsdifflib
1
Convert the float-to-integer VCVT instructions to decodetree.
1
The exynos4210 code currently has two very similar arrays of IRQs:
2
Since these are the last unconverted instructions, we can
2
3
delete the old decoder structure entirely now.
3
* board_irqs is a field of the Exynos4210Irq struct which is filled
4
in by exynos4210_init_board_irqs() with the appropriate qemu_irqs
5
for each IRQ the board/SoC can assert
6
* irq_table is a set of qemu_irqs pointed to from the
7
Exynos4210State struct. It's allocated in exynos4210_init_irq,
8
and the only behaviour these irqs have is that they pass on the
9
level to the equivalent board_irqs[] irq
10
11
The extra indirection through irq_table is unnecessary, so coalesce
12
these into a single irq_table[] array as a direct field in
13
Exynos4210State which exynos4210_init_board_irqs() fills in.
4
14
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
Message-id: 20220404154658.565020-6-peter.maydell@linaro.org
7
---
18
---
8
target/arm/translate-vfp.inc.c | 72 ++++++++++
19
include/hw/arm/exynos4210.h | 8 ++------
9
target/arm/translate.c | 241 +--------------------------------
20
hw/arm/exynos4210.c | 6 +-----
10
target/arm/vfp.decode | 6 +
21
hw/intc/exynos4210_gic.c | 32 ++++++++------------------------
11
3 files changed, 80 insertions(+), 239 deletions(-)
22
3 files changed, 11 insertions(+), 35 deletions(-)
12
23
13
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
24
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
14
index XXXXXXX..XXXXXXX 100644
25
index XXXXXXX..XXXXXXX 100644
15
--- a/target/arm/translate-vfp.inc.c
26
--- a/include/hw/arm/exynos4210.h
16
+++ b/target/arm/translate-vfp.inc.c
27
+++ b/include/hw/arm/exynos4210.h
17
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
28
@@ -XXX,XX +XXX,XX @@ typedef struct Exynos4210Irq {
18
tcg_temp_free_ptr(fpst);
29
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
19
return true;
30
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
20
}
31
qemu_irq ext_gic_irq[EXYNOS4210_EXT_GIC_NIRQ];
21
+
32
- qemu_irq board_irqs[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
22
+static bool trans_VCVT_sp_int(DisasContext *s, arg_VCVT_sp_int *a)
33
} Exynos4210Irq;
23
+{
34
24
+ TCGv_i32 vm;
35
struct Exynos4210State {
25
+ TCGv_ptr fpst;
36
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
26
+
37
/*< public >*/
27
+ if (!vfp_access_check(s)) {
38
ARMCPU *cpu[EXYNOS4210_NCPUS];
28
+ return true;
39
Exynos4210Irq irqs;
29
+ }
40
- qemu_irq *irq_table;
30
+
41
+ qemu_irq irq_table[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
31
+ fpst = get_fpstatus_ptr(false);
42
32
+ vm = tcg_temp_new_i32();
43
MemoryRegion chipid_mem;
33
+ neon_load_reg32(vm, a->vm);
44
MemoryRegion iram_mem;
34
+
45
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210State, EXYNOS4210_SOC)
35
+ if (a->s) {
46
void exynos4210_write_secondary(ARMCPU *cpu,
36
+ if (a->rz) {
47
const struct arm_boot_info *info);
37
+ gen_helper_vfp_tosizs(vm, vm, fpst);
48
38
+ } else {
49
-/* Initialize exynos4210 IRQ subsystem stub */
39
+ gen_helper_vfp_tosis(vm, vm, fpst);
50
-qemu_irq *exynos4210_init_irq(Exynos4210Irq *env);
40
+ }
51
-
41
+ } else {
52
/* Initialize board IRQs.
42
+ if (a->rz) {
53
* These IRQs contain splitted Int/External Combiner and External Gic IRQs */
43
+ gen_helper_vfp_touizs(vm, vm, fpst);
54
-void exynos4210_init_board_irqs(Exynos4210Irq *s);
44
+ } else {
55
+void exynos4210_init_board_irqs(Exynos4210State *s);
45
+ gen_helper_vfp_touis(vm, vm, fpst);
56
46
+ }
57
/* Get IRQ number from exynos4210 IRQ subsystem stub.
47
+ }
58
* To identify IRQ source use internal combiner group and bit number
48
+ neon_store_reg32(vm, a->vd);
59
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
49
+ tcg_temp_free_i32(vm);
50
+ tcg_temp_free_ptr(fpst);
51
+ return true;
52
+}
53
+
54
+static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a)
55
+{
56
+ TCGv_i32 vd;
57
+ TCGv_i64 vm;
58
+ TCGv_ptr fpst;
59
+
60
+ /* UNDEF accesses to D16-D31 if they don't exist. */
61
+ if (!dc_isar_feature(aa32_fp_d32, s) && (a->vm & 0x10)) {
62
+ return false;
63
+ }
64
+
65
+ if (!vfp_access_check(s)) {
66
+ return true;
67
+ }
68
+
69
+ fpst = get_fpstatus_ptr(false);
70
+ vm = tcg_temp_new_i64();
71
+ vd = tcg_temp_new_i32();
72
+ neon_load_reg64(vm, a->vm);
73
+
74
+ if (a->s) {
75
+ if (a->rz) {
76
+ gen_helper_vfp_tosizd(vd, vm, fpst);
77
+ } else {
78
+ gen_helper_vfp_tosid(vd, vm, fpst);
79
+ }
80
+ } else {
81
+ if (a->rz) {
82
+ gen_helper_vfp_touizd(vd, vm, fpst);
83
+ } else {
84
+ gen_helper_vfp_touid(vd, vm, fpst);
85
+ }
86
+ }
87
+ neon_store_reg32(vd, a->vd);
88
+ tcg_temp_free_i32(vd);
89
+ tcg_temp_free_i64(vm);
90
+ tcg_temp_free_ptr(fpst);
91
+ return true;
92
+}
93
diff --git a/target/arm/translate.c b/target/arm/translate.c
94
index XXXXXXX..XXXXXXX 100644
60
index XXXXXXX..XXXXXXX 100644
95
--- a/target/arm/translate.c
61
--- a/hw/arm/exynos4210.c
96
+++ b/target/arm/translate.c
62
+++ b/hw/arm/exynos4210.c
97
@@ -XXX,XX +XXX,XX @@ static inline void gen_vfp_##name(int dp, int neon) \
63
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
98
tcg_temp_free_ptr(statusptr); \
64
qdev_realize(DEVICE(cpuobj), NULL, &error_fatal);
99
}
65
}
100
66
101
-VFP_GEN_FTOI(toui)
67
- /*** IRQs ***/
102
VFP_GEN_FTOI(touiz)
103
-VFP_GEN_FTOI(tosi)
104
VFP_GEN_FTOI(tosiz)
105
#undef VFP_GEN_FTOI
106
107
@@ -XXX,XX +XXX,XX @@ static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
108
}
109
110
#define tcg_gen_ld_f32 tcg_gen_ld_i32
111
-#define tcg_gen_ld_f64 tcg_gen_ld_i64
112
#define tcg_gen_st_f32 tcg_gen_st_i32
113
-#define tcg_gen_st_f64 tcg_gen_st_i64
114
-
68
-
115
-static inline void gen_mov_F0_vreg(int dp, int reg)
69
- s->irq_table = exynos4210_init_irq(&s->irqs);
70
-
71
/* IRQ Gate */
72
for (i = 0; i < EXYNOS4210_NCPUS; i++) {
73
DeviceState *orgate = DEVICE(&s->cpu_irq_orgate[i]);
74
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
75
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
76
77
/* Initialize board IRQs. */
78
- exynos4210_init_board_irqs(&s->irqs);
79
+ exynos4210_init_board_irqs(s);
80
81
/*** Memory ***/
82
83
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
84
index XXXXXXX..XXXXXXX 100644
85
--- a/hw/intc/exynos4210_gic.c
86
+++ b/hw/intc/exynos4210_gic.c
87
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64-EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
88
#define EXYNOS4210_GIC_CPU_REGION_SIZE 0x100
89
#define EXYNOS4210_GIC_DIST_REGION_SIZE 0x1000
90
91
-static void exynos4210_irq_handler(void *opaque, int irq, int level)
116
-{
92
-{
117
- if (dp)
93
- Exynos4210Irq *s = (Exynos4210Irq *)opaque;
118
- tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
94
-
119
- else
95
- /* Bypass */
120
- tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
96
- qemu_set_irq(s->board_irqs[irq], level);
121
-}
97
-}
122
-
98
-
123
-static inline void gen_mov_F1_vreg(int dp, int reg)
99
-/*
100
- * Initialize exynos4210 IRQ subsystem stub.
101
- */
102
-qemu_irq *exynos4210_init_irq(Exynos4210Irq *s)
124
-{
103
-{
125
- if (dp)
104
- return qemu_allocate_irqs(exynos4210_irq_handler, s,
126
- tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
105
- EXYNOS4210_MAX_INT_COMBINER_IN_IRQ);
127
- else
128
- tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
129
-}
106
-}
130
-
107
-
131
-static inline void gen_mov_vreg_F0(int dp, int reg)
108
/*
132
-{
109
* Initialize board IRQs.
133
- if (dp)
110
* These IRQs contain splitted Int/External Combiner and External Gic IRQs.
134
- tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
135
- else
136
- tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
137
-}
138
139
#define ARM_CP_RW_BIT (1 << 20)
140
141
@@ -XXX,XX +XXX,XX @@ static void gen_neon_dup_high16(TCGv_i32 var)
142
*/
111
*/
143
static int disas_vfp_insn(DisasContext *s, uint32_t insn)
112
-void exynos4210_init_board_irqs(Exynos4210Irq *s)
113
+void exynos4210_init_board_irqs(Exynos4210State *s)
144
{
114
{
145
- uint32_t rd, rn, rm, op, delta_d, delta_m, bank_mask;
115
uint32_t grp, bit, irq_id, n;
146
- int dp, veclen;
116
+ Exynos4210Irq *is = &s->irqs;
147
-
117
148
if (!arm_dc_feature(s, ARM_FEATURE_VFP)) {
118
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
149
return 1;
119
irq_id = 0;
150
}
120
@@ -XXX,XX +XXX,XX @@ void exynos4210_init_board_irqs(Exynos4210Irq *s)
151
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
121
irq_id = EXT_GIC_ID_MCT_G1;
152
return 0;
122
}
123
if (irq_id) {
124
- s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
125
- s->ext_gic_irq[irq_id-32]);
126
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
127
+ is->ext_gic_irq[irq_id - 32]);
128
} else {
129
- s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
130
- s->ext_combiner_irq[n]);
131
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
132
+ is->ext_combiner_irq[n]);
153
}
133
}
154
}
134
}
155
-
135
for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
156
- if (extract32(insn, 28, 4) == 0xf) {
136
@@ -XXX,XX +XXX,XX @@ void exynos4210_init_board_irqs(Exynos4210Irq *s)
157
- /*
137
EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
158
- * Encodings with T=1 (Thumb) or unconditional (ARM): these
138
159
- * were all handled by the decodetree decoder, so any insn
139
if (irq_id) {
160
- * patterns which get here must be UNDEF.
140
- s->board_irqs[n] = qemu_irq_split(s->int_combiner_irq[n],
161
- */
141
- s->ext_gic_irq[irq_id-32]);
162
- return 1;
142
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
163
- }
143
+ is->ext_gic_irq[irq_id - 32]);
164
-
144
}
165
- /*
145
}
166
- * FIXME: this access check should not take precedence over UNDEF
167
- * for invalid encodings; we will generate incorrect syndrome information
168
- * for attempts to execute invalid vfp/neon encodings with FP disabled.
169
- */
170
- if (!vfp_access_check(s)) {
171
- return 0;
172
- }
173
-
174
- dp = ((insn & 0xf00) == 0xb00);
175
- switch ((insn >> 24) & 0xf) {
176
- case 0xe:
177
- if (insn & (1 << 4)) {
178
- /* already handled by decodetree */
179
- return 1;
180
- } else {
181
- /* data processing */
182
- bool rd_is_dp = dp;
183
- bool rm_is_dp = dp;
184
- bool no_output = false;
185
-
186
- /* The opcode is in bits 23, 21, 20 and 6. */
187
- op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
188
- rn = VFP_SREG_N(insn);
189
-
190
- switch (op) {
191
- case 0 ... 14:
192
- /* Already handled by decodetree */
193
- return 1;
194
- case 15:
195
- switch (rn) {
196
- case 0 ... 23:
197
- case 28 ... 31:
198
- /* Already handled by decodetree */
199
- return 1;
200
- default:
201
- break;
202
- }
203
- default:
204
- break;
205
- }
206
-
207
- if (op == 15) {
208
- /* rn is opcode, encoded as per VFP_SREG_N. */
209
- switch (rn) {
210
- case 0x18: /* vcvtr.u32.fxx */
211
- case 0x19: /* vcvtz.u32.fxx */
212
- case 0x1a: /* vcvtr.s32.fxx */
213
- case 0x1b: /* vcvtz.s32.fxx */
214
- rd_is_dp = false;
215
- break;
216
-
217
- default:
218
- return 1;
219
- }
220
- } else if (dp) {
221
- /* rn is register number */
222
- VFP_DREG_N(rn, insn);
223
- }
224
-
225
- if (rd_is_dp) {
226
- VFP_DREG_D(rd, insn);
227
- } else {
228
- rd = VFP_SREG_D(insn);
229
- }
230
- if (rm_is_dp) {
231
- VFP_DREG_M(rm, insn);
232
- } else {
233
- rm = VFP_SREG_M(insn);
234
- }
235
-
236
- veclen = s->vec_len;
237
- if (op == 15 && rn > 3) {
238
- veclen = 0;
239
- }
240
-
241
- /* Shut up compiler warnings. */
242
- delta_m = 0;
243
- delta_d = 0;
244
- bank_mask = 0;
245
-
246
- if (veclen > 0) {
247
- if (dp)
248
- bank_mask = 0xc;
249
- else
250
- bank_mask = 0x18;
251
-
252
- /* Figure out what type of vector operation this is. */
253
- if ((rd & bank_mask) == 0) {
254
- /* scalar */
255
- veclen = 0;
256
- } else {
257
- if (dp)
258
- delta_d = (s->vec_stride >> 1) + 1;
259
- else
260
- delta_d = s->vec_stride + 1;
261
-
262
- if ((rm & bank_mask) == 0) {
263
- /* mixed scalar/vector */
264
- delta_m = 0;
265
- } else {
266
- /* vector */
267
- delta_m = delta_d;
268
- }
269
- }
270
- }
271
-
272
- /* Load the initial operands. */
273
- if (op == 15) {
274
- switch (rn) {
275
- default:
276
- /* One source operand. */
277
- gen_mov_F0_vreg(rm_is_dp, rm);
278
- break;
279
- }
280
- } else {
281
- /* Two source operands. */
282
- gen_mov_F0_vreg(dp, rn);
283
- gen_mov_F1_vreg(dp, rm);
284
- }
285
-
286
- for (;;) {
287
- /* Perform the calculation. */
288
- switch (op) {
289
- case 15: /* extension space */
290
- switch (rn) {
291
- case 24: /* ftoui */
292
- gen_vfp_toui(dp, 0);
293
- break;
294
- case 25: /* ftouiz */
295
- gen_vfp_touiz(dp, 0);
296
- break;
297
- case 26: /* ftosi */
298
- gen_vfp_tosi(dp, 0);
299
- break;
300
- case 27: /* ftosiz */
301
- gen_vfp_tosiz(dp, 0);
302
- break;
303
- default: /* undefined */
304
- g_assert_not_reached();
305
- }
306
- break;
307
- default: /* undefined */
308
- return 1;
309
- }
310
-
311
- /* Write back the result, if any. */
312
- if (!no_output) {
313
- gen_mov_vreg_F0(rd_is_dp, rd);
314
- }
315
-
316
- /* break out of the loop if we have finished */
317
- if (veclen == 0) {
318
- break;
319
- }
320
-
321
- if (op == 15 && delta_m == 0) {
322
- /* single source one-many */
323
- while (veclen--) {
324
- rd = ((rd + delta_d) & (bank_mask - 1))
325
- | (rd & bank_mask);
326
- gen_mov_vreg_F0(dp, rd);
327
- }
328
- break;
329
- }
330
- /* Setup the next operands. */
331
- veclen--;
332
- rd = ((rd + delta_d) & (bank_mask - 1))
333
- | (rd & bank_mask);
334
-
335
- if (op == 15) {
336
- /* One source operand. */
337
- rm = ((rm + delta_m) & (bank_mask - 1))
338
- | (rm & bank_mask);
339
- gen_mov_F0_vreg(dp, rm);
340
- } else {
341
- /* Two source operands. */
342
- rn = ((rn + delta_d) & (bank_mask - 1))
343
- | (rn & bank_mask);
344
- gen_mov_F0_vreg(dp, rn);
345
- if (delta_m) {
346
- rm = ((rm + delta_m) & (bank_mask - 1))
347
- | (rm & bank_mask);
348
- gen_mov_F1_vreg(dp, rm);
349
- }
350
- }
351
- }
352
- }
353
- break;
354
- case 0xc:
355
- case 0xd:
356
- /* Already handled by decodetree */
357
- return 1;
358
- default:
359
- /* Should never happen. */
360
- return 1;
361
- }
362
- return 0;
363
+ /* If the decodetree decoder didn't handle this insn, it must be UNDEF */
364
+ return 1;
365
}
146
}
366
367
static inline bool use_goto_tb(DisasContext *s, target_ulong dest)
368
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
369
index XXXXXXX..XXXXXXX 100644
370
--- a/target/arm/vfp.decode
371
+++ b/target/arm/vfp.decode
372
@@ -XXX,XX +XXX,XX @@ VCVT_fix_sp ---- 1110 1.11 1.1. .... 1010 .1.0 .... \
373
vd=%vd_sp imm=%vm_sp opc=%vcvt_fix_op
374
VCVT_fix_dp ---- 1110 1.11 1.1. .... 1011 .1.0 .... \
375
vd=%vd_dp imm=%vm_sp opc=%vcvt_fix_op
376
+
377
+# VCVT float to integer (VCVT and VCVTR): Vd always single; Vd depends on size
378
+VCVT_sp_int ---- 1110 1.11 110 s:1 .... 1010 rz:1 1.0 .... \
379
+ vd=%vd_sp vm=%vm_sp
380
+VCVT_dp_int ---- 1110 1.11 110 s:1 .... 1011 rz:1 1.0 .... \
381
+ vd=%vd_sp vm=%vm_dp
382
--
147
--
383
2.20.1
148
2.25.1
384
385
diff view generated by jsdifflib
1
Convert the VCVT integer-to-float instructions to decodetree.
1
Fix a missing set of spaces around '-' in the definition of
2
combiner_grp_to_gic_id[]. We're about to move this code, so
3
fix the style issue first to keep checkpatch happy with the
4
code-motion patch.
2
5
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20220404154658.565020-7-peter.maydell@linaro.org
5
---
9
---
6
target/arm/translate-vfp.inc.c | 58 ++++++++++++++++++++++++++++++++++
10
hw/intc/exynos4210_gic.c | 2 +-
7
target/arm/translate.c | 12 +------
11
1 file changed, 1 insertion(+), 1 deletion(-)
8
target/arm/vfp.decode | 6 ++++
9
3 files changed, 65 insertions(+), 11 deletions(-)
10
12
11
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
13
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
12
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-vfp.inc.c
15
--- a/hw/intc/exynos4210_gic.c
14
+++ b/target/arm/translate-vfp.inc.c
16
+++ b/hw/intc/exynos4210_gic.c
15
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_dp(DisasContext *s, arg_VCVT_dp *a)
17
@@ -XXX,XX +XXX,XX @@ enum ExtInt {
16
tcg_temp_free_i64(vm);
18
*/
17
return true;
19
18
}
20
static const uint32_t
19
+
21
-combiner_grp_to_gic_id[64-EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
20
+static bool trans_VCVT_int_sp(DisasContext *s, arg_VCVT_int_sp *a)
22
+combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
21
+{
23
/* int combiner groups 16-19 */
22
+ TCGv_i32 vm;
24
{ }, { }, { }, { },
23
+ TCGv_ptr fpst;
25
/* int combiner group 20 */
24
+
25
+ if (!vfp_access_check(s)) {
26
+ return true;
27
+ }
28
+
29
+ vm = tcg_temp_new_i32();
30
+ neon_load_reg32(vm, a->vm);
31
+ fpst = get_fpstatus_ptr(false);
32
+ if (a->s) {
33
+ /* i32 -> f32 */
34
+ gen_helper_vfp_sitos(vm, vm, fpst);
35
+ } else {
36
+ /* u32 -> f32 */
37
+ gen_helper_vfp_uitos(vm, vm, fpst);
38
+ }
39
+ neon_store_reg32(vm, a->vd);
40
+ tcg_temp_free_i32(vm);
41
+ tcg_temp_free_ptr(fpst);
42
+ return true;
43
+}
44
+
45
+static bool trans_VCVT_int_dp(DisasContext *s, arg_VCVT_int_dp *a)
46
+{
47
+ TCGv_i32 vm;
48
+ TCGv_i64 vd;
49
+ TCGv_ptr fpst;
50
+
51
+ /* UNDEF accesses to D16-D31 if they don't exist. */
52
+ if (!dc_isar_feature(aa32_fp_d32, s) && (a->vd & 0x10)) {
53
+ return false;
54
+ }
55
+
56
+ if (!vfp_access_check(s)) {
57
+ return true;
58
+ }
59
+
60
+ vm = tcg_temp_new_i32();
61
+ vd = tcg_temp_new_i64();
62
+ neon_load_reg32(vm, a->vm);
63
+ fpst = get_fpstatus_ptr(false);
64
+ if (a->s) {
65
+ /* i32 -> f64 */
66
+ gen_helper_vfp_sitod(vd, vm, fpst);
67
+ } else {
68
+ /* u32 -> f64 */
69
+ gen_helper_vfp_uitod(vd, vm, fpst);
70
+ }
71
+ neon_store_reg64(vd, a->vd);
72
+ tcg_temp_free_i32(vm);
73
+ tcg_temp_free_i64(vd);
74
+ tcg_temp_free_ptr(fpst);
75
+ return true;
76
+}
77
diff --git a/target/arm/translate.c b/target/arm/translate.c
78
index XXXXXXX..XXXXXXX 100644
79
--- a/target/arm/translate.c
80
+++ b/target/arm/translate.c
81
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
82
return 1;
83
case 15:
84
switch (rn) {
85
- case 0 ... 15:
86
+ case 0 ... 17:
87
/* Already handled by decodetree */
88
return 1;
89
default:
90
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
91
if (op == 15) {
92
/* rn is opcode, encoded as per VFP_SREG_N. */
93
switch (rn) {
94
- case 0x10: /* vcvt.fxx.u32 */
95
- case 0x11: /* vcvt.fxx.s32 */
96
- rm_is_dp = false;
97
- break;
98
case 0x18: /* vcvtr.u32.fxx */
99
case 0x19: /* vcvtz.u32.fxx */
100
case 0x1a: /* vcvtr.s32.fxx */
101
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
102
switch (op) {
103
case 15: /* extension space */
104
switch (rn) {
105
- case 16: /* fuito */
106
- gen_vfp_uito(dp, 0);
107
- break;
108
- case 17: /* fsito */
109
- gen_vfp_sito(dp, 0);
110
- break;
111
case 19: /* vjcvt */
112
gen_helper_vjcvt(cpu_F0s, cpu_F0d, cpu_env);
113
break;
114
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
115
index XXXXXXX..XXXXXXX 100644
116
--- a/target/arm/vfp.decode
117
+++ b/target/arm/vfp.decode
118
@@ -XXX,XX +XXX,XX @@ VCVT_sp ---- 1110 1.11 0111 .... 1010 11.0 .... \
119
vd=%vd_dp vm=%vm_sp
120
VCVT_dp ---- 1110 1.11 0111 .... 1011 11.0 .... \
121
vd=%vd_sp vm=%vm_dp
122
+
123
+# VCVT from integer to floating point: Vm always single; Vd depends on size
124
+VCVT_int_sp ---- 1110 1.11 1000 .... 1010 s:1 1.0 .... \
125
+ vd=%vd_sp vm=%vm_sp
126
+VCVT_int_dp ---- 1110 1.11 1000 .... 1011 s:1 1.0 .... \
127
+ vd=%vd_dp vm=%vm_sp
128
--
26
--
129
2.20.1
27
2.25.1
130
131
diff view generated by jsdifflib
1
Convert the "single-precision" register moves to decodetree:
1
The function exynos4210_init_board_irqs() currently lives in
2
* VMSR
2
exynos4210_gic.c, but it isn't really part of the exynos4210.gic
3
* VMRS
3
device -- it is a function that implements (some of) the wiring up of
4
* VMOV between general purpose register and single precision
4
interrupts between the SoC's GIC and combiner components. This means
5
5
it fits better in exynos4210.c, which is the SoC-level code. Move it
6
Note that the VMSR/VMRS conversions make our handling of
6
there. Similarly, exynos4210_git_irq() is used almost only in the
7
the "should this UNDEF?" checks consistent between the two
7
SoC-level code, so move it too.
8
instructions:
9
* VMSR to MVFR0, MVFR1, MVFR2 now UNDEF from EL0
10
(previously was a nop)
11
* VMSR to FPSID now UNDEFs from EL0 or if VFPv3 or better
12
(previously was a nop)
13
* VMSR to FPINST and FPINST2 now UNDEF if VFPv3 or better
14
(previously would write to the register, which had no
15
guest-visible effect because we always UNDEF reads)
16
17
We also tighten up the decode: we were previously underdecoding
18
some SBZ or SBO bits.
19
20
The conversion of VMOV_single includes the expansion out of the
21
gen_mov_F0_vreg()/gen_vfp_mrs() and gen_mov_vreg_F0()/gen_vfp_msr()
22
sequences into the simpler direct load/store of the TCG temp via
23
neon_{load,store}_reg32(): we know in the new function that we're
24
always single-precision, we don't need to use the old-and-deprecated
25
cpu_F0* TCG globals, and we don't happen to have the declaration of
26
gen_vfp_msr() and gen_vfp_mrs() at the point in the file where the
27
new function is.
28
8
29
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
30
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-8-peter.maydell@linaro.org
31
---
12
---
32
target/arm/translate-vfp.inc.c | 161 +++++++++++++++++++++++++++++++++
13
include/hw/arm/exynos4210.h | 4 -
33
target/arm/translate.c | 148 +-----------------------------
14
hw/arm/exynos4210.c | 202 +++++++++++++++++++++++++++++++++++
34
target/arm/vfp.decode | 4 +
15
hw/intc/exynos4210_gic.c | 204 ------------------------------------
35
3 files changed, 168 insertions(+), 145 deletions(-)
16
3 files changed, 202 insertions(+), 208 deletions(-)
36
17
37
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
18
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
38
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/translate-vfp.inc.c
20
--- a/include/hw/arm/exynos4210.h
40
+++ b/target/arm/translate-vfp.inc.c
21
+++ b/include/hw/arm/exynos4210.h
41
@@ -XXX,XX +XXX,XX @@ static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
22
@@ -XXX,XX +XXX,XX @@ OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210State, EXYNOS4210_SOC)
42
23
void exynos4210_write_secondary(ARMCPU *cpu,
43
return true;
24
const struct arm_boot_info *info);
44
}
25
45
+
26
-/* Initialize board IRQs.
46
+static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
27
- * These IRQs contain splitted Int/External Combiner and External Gic IRQs */
28
-void exynos4210_init_board_irqs(Exynos4210State *s);
29
-
30
/* Get IRQ number from exynos4210 IRQ subsystem stub.
31
* To identify IRQ source use internal combiner group and bit number
32
* grp - group number
33
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
34
index XXXXXXX..XXXXXXX 100644
35
--- a/hw/arm/exynos4210.c
36
+++ b/hw/arm/exynos4210.c
37
@@ -XXX,XX +XXX,XX @@
38
#define EXYNOS4210_PL330_BASE1_ADDR 0x12690000
39
#define EXYNOS4210_PL330_BASE2_ADDR 0x12850000
40
41
+enum ExtGicId {
42
+ EXT_GIC_ID_MDMA_LCD0 = 66,
43
+ EXT_GIC_ID_PDMA0,
44
+ EXT_GIC_ID_PDMA1,
45
+ EXT_GIC_ID_TIMER0,
46
+ EXT_GIC_ID_TIMER1,
47
+ EXT_GIC_ID_TIMER2,
48
+ EXT_GIC_ID_TIMER3,
49
+ EXT_GIC_ID_TIMER4,
50
+ EXT_GIC_ID_MCT_L0,
51
+ EXT_GIC_ID_WDT,
52
+ EXT_GIC_ID_RTC_ALARM,
53
+ EXT_GIC_ID_RTC_TIC,
54
+ EXT_GIC_ID_GPIO_XB,
55
+ EXT_GIC_ID_GPIO_XA,
56
+ EXT_GIC_ID_MCT_L1,
57
+ EXT_GIC_ID_IEM_APC,
58
+ EXT_GIC_ID_IEM_IEC,
59
+ EXT_GIC_ID_NFC,
60
+ EXT_GIC_ID_UART0,
61
+ EXT_GIC_ID_UART1,
62
+ EXT_GIC_ID_UART2,
63
+ EXT_GIC_ID_UART3,
64
+ EXT_GIC_ID_UART4,
65
+ EXT_GIC_ID_MCT_G0,
66
+ EXT_GIC_ID_I2C0,
67
+ EXT_GIC_ID_I2C1,
68
+ EXT_GIC_ID_I2C2,
69
+ EXT_GIC_ID_I2C3,
70
+ EXT_GIC_ID_I2C4,
71
+ EXT_GIC_ID_I2C5,
72
+ EXT_GIC_ID_I2C6,
73
+ EXT_GIC_ID_I2C7,
74
+ EXT_GIC_ID_SPI0,
75
+ EXT_GIC_ID_SPI1,
76
+ EXT_GIC_ID_SPI2,
77
+ EXT_GIC_ID_MCT_G1,
78
+ EXT_GIC_ID_USB_HOST,
79
+ EXT_GIC_ID_USB_DEVICE,
80
+ EXT_GIC_ID_MODEMIF,
81
+ EXT_GIC_ID_HSMMC0,
82
+ EXT_GIC_ID_HSMMC1,
83
+ EXT_GIC_ID_HSMMC2,
84
+ EXT_GIC_ID_HSMMC3,
85
+ EXT_GIC_ID_SDMMC,
86
+ EXT_GIC_ID_MIPI_CSI_4LANE,
87
+ EXT_GIC_ID_MIPI_DSI_4LANE,
88
+ EXT_GIC_ID_MIPI_CSI_2LANE,
89
+ EXT_GIC_ID_MIPI_DSI_2LANE,
90
+ EXT_GIC_ID_ONENAND_AUDI,
91
+ EXT_GIC_ID_ROTATOR,
92
+ EXT_GIC_ID_FIMC0,
93
+ EXT_GIC_ID_FIMC1,
94
+ EXT_GIC_ID_FIMC2,
95
+ EXT_GIC_ID_FIMC3,
96
+ EXT_GIC_ID_JPEG,
97
+ EXT_GIC_ID_2D,
98
+ EXT_GIC_ID_PCIe,
99
+ EXT_GIC_ID_MIXER,
100
+ EXT_GIC_ID_HDMI,
101
+ EXT_GIC_ID_HDMI_I2C,
102
+ EXT_GIC_ID_MFC,
103
+ EXT_GIC_ID_TVENC,
104
+};
105
+
106
+enum ExtInt {
107
+ EXT_GIC_ID_EXTINT0 = 48,
108
+ EXT_GIC_ID_EXTINT1,
109
+ EXT_GIC_ID_EXTINT2,
110
+ EXT_GIC_ID_EXTINT3,
111
+ EXT_GIC_ID_EXTINT4,
112
+ EXT_GIC_ID_EXTINT5,
113
+ EXT_GIC_ID_EXTINT6,
114
+ EXT_GIC_ID_EXTINT7,
115
+ EXT_GIC_ID_EXTINT8,
116
+ EXT_GIC_ID_EXTINT9,
117
+ EXT_GIC_ID_EXTINT10,
118
+ EXT_GIC_ID_EXTINT11,
119
+ EXT_GIC_ID_EXTINT12,
120
+ EXT_GIC_ID_EXTINT13,
121
+ EXT_GIC_ID_EXTINT14,
122
+ EXT_GIC_ID_EXTINT15
123
+};
124
+
125
+/*
126
+ * External GIC sources which are not from External Interrupt Combiner or
127
+ * External Interrupts are starting from EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ,
128
+ * which is INTG16 in Internal Interrupt Combiner.
129
+ */
130
+
131
+static const uint32_t
132
+combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
133
+ /* int combiner groups 16-19 */
134
+ { }, { }, { }, { },
135
+ /* int combiner group 20 */
136
+ { 0, EXT_GIC_ID_MDMA_LCD0 },
137
+ /* int combiner group 21 */
138
+ { EXT_GIC_ID_PDMA0, EXT_GIC_ID_PDMA1 },
139
+ /* int combiner group 22 */
140
+ { EXT_GIC_ID_TIMER0, EXT_GIC_ID_TIMER1, EXT_GIC_ID_TIMER2,
141
+ EXT_GIC_ID_TIMER3, EXT_GIC_ID_TIMER4 },
142
+ /* int combiner group 23 */
143
+ { EXT_GIC_ID_RTC_ALARM, EXT_GIC_ID_RTC_TIC },
144
+ /* int combiner group 24 */
145
+ { EXT_GIC_ID_GPIO_XB, EXT_GIC_ID_GPIO_XA },
146
+ /* int combiner group 25 */
147
+ { EXT_GIC_ID_IEM_APC, EXT_GIC_ID_IEM_IEC },
148
+ /* int combiner group 26 */
149
+ { EXT_GIC_ID_UART0, EXT_GIC_ID_UART1, EXT_GIC_ID_UART2, EXT_GIC_ID_UART3,
150
+ EXT_GIC_ID_UART4 },
151
+ /* int combiner group 27 */
152
+ { EXT_GIC_ID_I2C0, EXT_GIC_ID_I2C1, EXT_GIC_ID_I2C2, EXT_GIC_ID_I2C3,
153
+ EXT_GIC_ID_I2C4, EXT_GIC_ID_I2C5, EXT_GIC_ID_I2C6,
154
+ EXT_GIC_ID_I2C7 },
155
+ /* int combiner group 28 */
156
+ { EXT_GIC_ID_SPI0, EXT_GIC_ID_SPI1, EXT_GIC_ID_SPI2 , EXT_GIC_ID_USB_HOST},
157
+ /* int combiner group 29 */
158
+ { EXT_GIC_ID_HSMMC0, EXT_GIC_ID_HSMMC1, EXT_GIC_ID_HSMMC2,
159
+ EXT_GIC_ID_HSMMC3, EXT_GIC_ID_SDMMC },
160
+ /* int combiner group 30 */
161
+ { EXT_GIC_ID_MIPI_CSI_4LANE, EXT_GIC_ID_MIPI_CSI_2LANE },
162
+ /* int combiner group 31 */
163
+ { EXT_GIC_ID_MIPI_DSI_4LANE, EXT_GIC_ID_MIPI_DSI_2LANE },
164
+ /* int combiner group 32 */
165
+ { EXT_GIC_ID_FIMC0, EXT_GIC_ID_FIMC1 },
166
+ /* int combiner group 33 */
167
+ { EXT_GIC_ID_FIMC2, EXT_GIC_ID_FIMC3 },
168
+ /* int combiner group 34 */
169
+ { EXT_GIC_ID_ONENAND_AUDI, EXT_GIC_ID_NFC },
170
+ /* int combiner group 35 */
171
+ { 0, 0, 0, EXT_GIC_ID_MCT_L1, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
172
+ /* int combiner group 36 */
173
+ { EXT_GIC_ID_MIXER },
174
+ /* int combiner group 37 */
175
+ { EXT_GIC_ID_EXTINT4, EXT_GIC_ID_EXTINT5, EXT_GIC_ID_EXTINT6,
176
+ EXT_GIC_ID_EXTINT7 },
177
+ /* groups 38-50 */
178
+ { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { },
179
+ /* int combiner group 51 */
180
+ { EXT_GIC_ID_MCT_L0, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
181
+ /* group 52 */
182
+ { },
183
+ /* int combiner group 53 */
184
+ { EXT_GIC_ID_WDT, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
185
+ /* groups 54-63 */
186
+ { }, { }, { }, { }, { }, { }, { }, { }, { }, { }
187
+};
188
+
189
+/*
190
+ * Initialize board IRQs.
191
+ * These IRQs contain splitted Int/External Combiner and External Gic IRQs.
192
+ */
193
+static void exynos4210_init_board_irqs(Exynos4210State *s)
47
+{
194
+{
48
+ TCGv_i32 tmp;
195
+ uint32_t grp, bit, irq_id, n;
49
+ bool ignore_vfp_enabled = false;
196
+ Exynos4210Irq *is = &s->irqs;
50
+
197
+
51
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
198
+ for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
52
+ /*
199
+ irq_id = 0;
53
+ * The only M-profile VFP vmrs/vmsr sysreg is FPSCR.
200
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4) ||
54
+ * Writes to R15 are UNPREDICTABLE; we choose to undef.
201
+ n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4)) {
55
+ */
202
+ /* MCT_G0 is passed to External GIC */
56
+ if (a->rt == 15 || a->reg != ARM_VFP_FPSCR) {
203
+ irq_id = EXT_GIC_ID_MCT_G0;
57
+ return false;
204
+ }
205
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) ||
206
+ n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) {
207
+ /* MCT_G1 is passed to External and GIC */
208
+ irq_id = EXT_GIC_ID_MCT_G1;
209
+ }
210
+ if (irq_id) {
211
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
212
+ is->ext_gic_irq[irq_id - 32]);
213
+ } else {
214
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
215
+ is->ext_combiner_irq[n]);
58
+ }
216
+ }
59
+ }
217
+ }
60
+
218
+ for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
61
+ switch (a->reg) {
219
+ /* these IDs are passed to Internal Combiner and External GIC */
62
+ case ARM_VFP_FPSID:
220
+ grp = EXYNOS4210_COMBINER_GET_GRP_NUM(n);
63
+ /*
221
+ bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
64
+ * VFPv2 allows access to FPSID from userspace; VFPv3 restricts
222
+ irq_id = combiner_grp_to_gic_id[grp -
65
+ * all ID registers to privileged access only.
223
+ EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
66
+ */
224
+
67
+ if (IS_USER(s) && arm_dc_feature(s, ARM_FEATURE_VFP3)) {
225
+ if (irq_id) {
68
+ return false;
226
+ s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
69
+ }
227
+ is->ext_gic_irq[irq_id - 32]);
70
+ ignore_vfp_enabled = true;
71
+ break;
72
+ case ARM_VFP_MVFR0:
73
+ case ARM_VFP_MVFR1:
74
+ if (IS_USER(s) || !arm_dc_feature(s, ARM_FEATURE_MVFR)) {
75
+ return false;
76
+ }
77
+ ignore_vfp_enabled = true;
78
+ break;
79
+ case ARM_VFP_MVFR2:
80
+ if (IS_USER(s) || !arm_dc_feature(s, ARM_FEATURE_V8)) {
81
+ return false;
82
+ }
83
+ ignore_vfp_enabled = true;
84
+ break;
85
+ case ARM_VFP_FPSCR:
86
+ break;
87
+ case ARM_VFP_FPEXC:
88
+ if (IS_USER(s)) {
89
+ return false;
90
+ }
91
+ ignore_vfp_enabled = true;
92
+ break;
93
+ case ARM_VFP_FPINST:
94
+ case ARM_VFP_FPINST2:
95
+ /* Not present in VFPv3 */
96
+ if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_VFP3)) {
97
+ return false;
98
+ }
99
+ break;
100
+ default:
101
+ return false;
102
+ }
103
+
104
+ if (!full_vfp_access_check(s, ignore_vfp_enabled)) {
105
+ return true;
106
+ }
107
+
108
+ if (a->l) {
109
+ /* VMRS, move VFP special register to gp register */
110
+ switch (a->reg) {
111
+ case ARM_VFP_FPSID:
112
+ case ARM_VFP_FPEXC:
113
+ case ARM_VFP_FPINST:
114
+ case ARM_VFP_FPINST2:
115
+ case ARM_VFP_MVFR0:
116
+ case ARM_VFP_MVFR1:
117
+ case ARM_VFP_MVFR2:
118
+ tmp = load_cpu_field(vfp.xregs[a->reg]);
119
+ break;
120
+ case ARM_VFP_FPSCR:
121
+ if (a->rt == 15) {
122
+ tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
123
+ tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
124
+ } else {
125
+ tmp = tcg_temp_new_i32();
126
+ gen_helper_vfp_get_fpscr(tmp, cpu_env);
127
+ }
128
+ break;
129
+ default:
130
+ g_assert_not_reached();
131
+ }
132
+
133
+ if (a->rt == 15) {
134
+ /* Set the 4 flag bits in the CPSR. */
135
+ gen_set_nzcv(tmp);
136
+ tcg_temp_free_i32(tmp);
137
+ } else {
138
+ store_reg(s, a->rt, tmp);
139
+ }
140
+ } else {
141
+ /* VMSR, move gp register to VFP special register */
142
+ switch (a->reg) {
143
+ case ARM_VFP_FPSID:
144
+ case ARM_VFP_MVFR0:
145
+ case ARM_VFP_MVFR1:
146
+ case ARM_VFP_MVFR2:
147
+ /* Writes are ignored. */
148
+ break;
149
+ case ARM_VFP_FPSCR:
150
+ tmp = load_reg(s, a->rt);
151
+ gen_helper_vfp_set_fpscr(cpu_env, tmp);
152
+ tcg_temp_free_i32(tmp);
153
+ gen_lookup_tb(s);
154
+ break;
155
+ case ARM_VFP_FPEXC:
156
+ /*
157
+ * TODO: VFP subarchitecture support.
158
+ * For now, keep the EN bit only
159
+ */
160
+ tmp = load_reg(s, a->rt);
161
+ tcg_gen_andi_i32(tmp, tmp, 1 << 30);
162
+ store_cpu_field(tmp, vfp.xregs[a->reg]);
163
+ gen_lookup_tb(s);
164
+ break;
165
+ case ARM_VFP_FPINST:
166
+ case ARM_VFP_FPINST2:
167
+ tmp = load_reg(s, a->rt);
168
+ store_cpu_field(tmp, vfp.xregs[a->reg]);
169
+ break;
170
+ default:
171
+ g_assert_not_reached();
172
+ }
228
+ }
173
+ }
229
+ }
174
+
175
+ return true;
176
+}
230
+}
177
+
231
+
178
+static bool trans_VMOV_single(DisasContext *s, arg_VMOV_single *a)
232
+/*
233
+ * Get IRQ number from exynos4210 IRQ subsystem stub.
234
+ * To identify IRQ source use internal combiner group and bit number
235
+ * grp - group number
236
+ * bit - bit number inside group
237
+ */
238
+uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
179
+{
239
+{
180
+ TCGv_i32 tmp;
240
+ return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
181
+
182
+ if (!vfp_access_check(s)) {
183
+ return true;
184
+ }
185
+
186
+ if (a->l) {
187
+ /* VFP to general purpose register */
188
+ tmp = tcg_temp_new_i32();
189
+ neon_load_reg32(tmp, a->vn);
190
+ if (a->rt == 15) {
191
+ /* Set the 4 flag bits in the CPSR. */
192
+ gen_set_nzcv(tmp);
193
+ tcg_temp_free_i32(tmp);
194
+ } else {
195
+ store_reg(s, a->rt, tmp);
196
+ }
197
+ } else {
198
+ /* general purpose register to VFP */
199
+ tmp = load_reg(s, a->rt);
200
+ neon_store_reg32(tmp, a->vn);
201
+ tcg_temp_free_i32(tmp);
202
+ }
203
+
204
+ return true;
205
+}
241
+}
206
diff --git a/target/arm/translate.c b/target/arm/translate.c
242
+
243
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
244
0x09, 0x00, 0x00, 0x00 };
245
246
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
207
index XXXXXXX..XXXXXXX 100644
247
index XXXXXXX..XXXXXXX 100644
208
--- a/target/arm/translate.c
248
--- a/hw/intc/exynos4210_gic.c
209
+++ b/target/arm/translate.c
249
+++ b/hw/intc/exynos4210_gic.c
210
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
250
@@ -XXX,XX +XXX,XX @@
211
TCGv_i32 addr;
251
#include "hw/arm/exynos4210.h"
212
TCGv_i32 tmp;
252
#include "qom/object.h"
213
TCGv_i32 tmp2;
253
214
- bool ignore_vfp_enabled = false;
254
-enum ExtGicId {
215
255
- EXT_GIC_ID_MDMA_LCD0 = 66,
216
if (!arm_dc_feature(s, ARM_FEATURE_VFP)) {
256
- EXT_GIC_ID_PDMA0,
217
return 1;
257
- EXT_GIC_ID_PDMA1,
218
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
258
- EXT_GIC_ID_TIMER0,
219
* for invalid encodings; we will generate incorrect syndrome information
259
- EXT_GIC_ID_TIMER1,
220
* for attempts to execute invalid vfp/neon encodings with FP disabled.
260
- EXT_GIC_ID_TIMER2,
221
*/
261
- EXT_GIC_ID_TIMER3,
222
- if ((insn & 0x0fe00fff) == 0x0ee00a10) {
262
- EXT_GIC_ID_TIMER4,
223
- rn = (insn >> 16) & 0xf;
263
- EXT_GIC_ID_MCT_L0,
224
- if (rn == ARM_VFP_FPSID || rn == ARM_VFP_FPEXC || rn == ARM_VFP_MVFR2
264
- EXT_GIC_ID_WDT,
225
- || rn == ARM_VFP_MVFR1 || rn == ARM_VFP_MVFR0) {
265
- EXT_GIC_ID_RTC_ALARM,
226
- ignore_vfp_enabled = true;
266
- EXT_GIC_ID_RTC_TIC,
267
- EXT_GIC_ID_GPIO_XB,
268
- EXT_GIC_ID_GPIO_XA,
269
- EXT_GIC_ID_MCT_L1,
270
- EXT_GIC_ID_IEM_APC,
271
- EXT_GIC_ID_IEM_IEC,
272
- EXT_GIC_ID_NFC,
273
- EXT_GIC_ID_UART0,
274
- EXT_GIC_ID_UART1,
275
- EXT_GIC_ID_UART2,
276
- EXT_GIC_ID_UART3,
277
- EXT_GIC_ID_UART4,
278
- EXT_GIC_ID_MCT_G0,
279
- EXT_GIC_ID_I2C0,
280
- EXT_GIC_ID_I2C1,
281
- EXT_GIC_ID_I2C2,
282
- EXT_GIC_ID_I2C3,
283
- EXT_GIC_ID_I2C4,
284
- EXT_GIC_ID_I2C5,
285
- EXT_GIC_ID_I2C6,
286
- EXT_GIC_ID_I2C7,
287
- EXT_GIC_ID_SPI0,
288
- EXT_GIC_ID_SPI1,
289
- EXT_GIC_ID_SPI2,
290
- EXT_GIC_ID_MCT_G1,
291
- EXT_GIC_ID_USB_HOST,
292
- EXT_GIC_ID_USB_DEVICE,
293
- EXT_GIC_ID_MODEMIF,
294
- EXT_GIC_ID_HSMMC0,
295
- EXT_GIC_ID_HSMMC1,
296
- EXT_GIC_ID_HSMMC2,
297
- EXT_GIC_ID_HSMMC3,
298
- EXT_GIC_ID_SDMMC,
299
- EXT_GIC_ID_MIPI_CSI_4LANE,
300
- EXT_GIC_ID_MIPI_DSI_4LANE,
301
- EXT_GIC_ID_MIPI_CSI_2LANE,
302
- EXT_GIC_ID_MIPI_DSI_2LANE,
303
- EXT_GIC_ID_ONENAND_AUDI,
304
- EXT_GIC_ID_ROTATOR,
305
- EXT_GIC_ID_FIMC0,
306
- EXT_GIC_ID_FIMC1,
307
- EXT_GIC_ID_FIMC2,
308
- EXT_GIC_ID_FIMC3,
309
- EXT_GIC_ID_JPEG,
310
- EXT_GIC_ID_2D,
311
- EXT_GIC_ID_PCIe,
312
- EXT_GIC_ID_MIXER,
313
- EXT_GIC_ID_HDMI,
314
- EXT_GIC_ID_HDMI_I2C,
315
- EXT_GIC_ID_MFC,
316
- EXT_GIC_ID_TVENC,
317
-};
318
-
319
-enum ExtInt {
320
- EXT_GIC_ID_EXTINT0 = 48,
321
- EXT_GIC_ID_EXTINT1,
322
- EXT_GIC_ID_EXTINT2,
323
- EXT_GIC_ID_EXTINT3,
324
- EXT_GIC_ID_EXTINT4,
325
- EXT_GIC_ID_EXTINT5,
326
- EXT_GIC_ID_EXTINT6,
327
- EXT_GIC_ID_EXTINT7,
328
- EXT_GIC_ID_EXTINT8,
329
- EXT_GIC_ID_EXTINT9,
330
- EXT_GIC_ID_EXTINT10,
331
- EXT_GIC_ID_EXTINT11,
332
- EXT_GIC_ID_EXTINT12,
333
- EXT_GIC_ID_EXTINT13,
334
- EXT_GIC_ID_EXTINT14,
335
- EXT_GIC_ID_EXTINT15
336
-};
337
-
338
-/*
339
- * External GIC sources which are not from External Interrupt Combiner or
340
- * External Interrupts are starting from EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ,
341
- * which is INTG16 in Internal Interrupt Combiner.
342
- */
343
-
344
-static const uint32_t
345
-combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
346
- /* int combiner groups 16-19 */
347
- { }, { }, { }, { },
348
- /* int combiner group 20 */
349
- { 0, EXT_GIC_ID_MDMA_LCD0 },
350
- /* int combiner group 21 */
351
- { EXT_GIC_ID_PDMA0, EXT_GIC_ID_PDMA1 },
352
- /* int combiner group 22 */
353
- { EXT_GIC_ID_TIMER0, EXT_GIC_ID_TIMER1, EXT_GIC_ID_TIMER2,
354
- EXT_GIC_ID_TIMER3, EXT_GIC_ID_TIMER4 },
355
- /* int combiner group 23 */
356
- { EXT_GIC_ID_RTC_ALARM, EXT_GIC_ID_RTC_TIC },
357
- /* int combiner group 24 */
358
- { EXT_GIC_ID_GPIO_XB, EXT_GIC_ID_GPIO_XA },
359
- /* int combiner group 25 */
360
- { EXT_GIC_ID_IEM_APC, EXT_GIC_ID_IEM_IEC },
361
- /* int combiner group 26 */
362
- { EXT_GIC_ID_UART0, EXT_GIC_ID_UART1, EXT_GIC_ID_UART2, EXT_GIC_ID_UART3,
363
- EXT_GIC_ID_UART4 },
364
- /* int combiner group 27 */
365
- { EXT_GIC_ID_I2C0, EXT_GIC_ID_I2C1, EXT_GIC_ID_I2C2, EXT_GIC_ID_I2C3,
366
- EXT_GIC_ID_I2C4, EXT_GIC_ID_I2C5, EXT_GIC_ID_I2C6,
367
- EXT_GIC_ID_I2C7 },
368
- /* int combiner group 28 */
369
- { EXT_GIC_ID_SPI0, EXT_GIC_ID_SPI1, EXT_GIC_ID_SPI2 , EXT_GIC_ID_USB_HOST},
370
- /* int combiner group 29 */
371
- { EXT_GIC_ID_HSMMC0, EXT_GIC_ID_HSMMC1, EXT_GIC_ID_HSMMC2,
372
- EXT_GIC_ID_HSMMC3, EXT_GIC_ID_SDMMC },
373
- /* int combiner group 30 */
374
- { EXT_GIC_ID_MIPI_CSI_4LANE, EXT_GIC_ID_MIPI_CSI_2LANE },
375
- /* int combiner group 31 */
376
- { EXT_GIC_ID_MIPI_DSI_4LANE, EXT_GIC_ID_MIPI_DSI_2LANE },
377
- /* int combiner group 32 */
378
- { EXT_GIC_ID_FIMC0, EXT_GIC_ID_FIMC1 },
379
- /* int combiner group 33 */
380
- { EXT_GIC_ID_FIMC2, EXT_GIC_ID_FIMC3 },
381
- /* int combiner group 34 */
382
- { EXT_GIC_ID_ONENAND_AUDI, EXT_GIC_ID_NFC },
383
- /* int combiner group 35 */
384
- { 0, 0, 0, EXT_GIC_ID_MCT_L1, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
385
- /* int combiner group 36 */
386
- { EXT_GIC_ID_MIXER },
387
- /* int combiner group 37 */
388
- { EXT_GIC_ID_EXTINT4, EXT_GIC_ID_EXTINT5, EXT_GIC_ID_EXTINT6,
389
- EXT_GIC_ID_EXTINT7 },
390
- /* groups 38-50 */
391
- { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { },
392
- /* int combiner group 51 */
393
- { EXT_GIC_ID_MCT_L0, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
394
- /* group 52 */
395
- { },
396
- /* int combiner group 53 */
397
- { EXT_GIC_ID_WDT, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
398
- /* groups 54-63 */
399
- { }, { }, { }, { }, { }, { }, { }, { }, { }, { }
400
-};
401
-
402
#define EXYNOS4210_GIC_NIRQ 160
403
404
#define EXYNOS4210_EXT_GIC_CPU_REGION_SIZE 0x10000
405
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
406
#define EXYNOS4210_GIC_CPU_REGION_SIZE 0x100
407
#define EXYNOS4210_GIC_DIST_REGION_SIZE 0x1000
408
409
-/*
410
- * Initialize board IRQs.
411
- * These IRQs contain splitted Int/External Combiner and External Gic IRQs.
412
- */
413
-void exynos4210_init_board_irqs(Exynos4210State *s)
414
-{
415
- uint32_t grp, bit, irq_id, n;
416
- Exynos4210Irq *is = &s->irqs;
417
-
418
- for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
419
- irq_id = 0;
420
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4) ||
421
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4)) {
422
- /* MCT_G0 is passed to External GIC */
423
- irq_id = EXT_GIC_ID_MCT_G0;
424
- }
425
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) ||
426
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) {
427
- /* MCT_G1 is passed to External and GIC */
428
- irq_id = EXT_GIC_ID_MCT_G1;
429
- }
430
- if (irq_id) {
431
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
432
- is->ext_gic_irq[irq_id - 32]);
433
- } else {
434
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
435
- is->ext_combiner_irq[n]);
227
- }
436
- }
228
- }
437
- }
229
- if (!full_vfp_access_check(s, ignore_vfp_enabled)) {
438
- for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
230
+ if (!vfp_access_check(s)) {
439
- /* these IDs are passed to Internal Combiner and External GIC */
231
return 0;
440
- grp = EXYNOS4210_COMBINER_GET_GRP_NUM(n);
232
}
441
- bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
233
442
- irq_id = combiner_grp_to_gic_id[grp -
234
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
443
- EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
235
switch ((insn >> 24) & 0xf) {
444
-
236
case 0xe:
445
- if (irq_id) {
237
if (insn & (1 << 4)) {
446
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
238
- /* single register transfer */
447
- is->ext_gic_irq[irq_id - 32]);
239
- rd = (insn >> 12) & 0xf;
448
- }
240
- if (dp) {
449
- }
241
- /* already handled by decodetree */
450
-}
242
- return 1;
451
-
243
- } else { /* !dp */
452
-/*
244
- bool is_sysreg;
453
- * Get IRQ number from exynos4210 IRQ subsystem stub.
245
-
454
- * To identify IRQ source use internal combiner group and bit number
246
- if ((insn & 0x6f) != 0x00)
455
- * grp - group number
247
- return 1;
456
- * bit - bit number inside group
248
- rn = VFP_SREG_N(insn);
457
- */
249
-
458
-uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
250
- is_sysreg = extract32(insn, 21, 1);
459
-{
251
-
460
- return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
252
- if (arm_dc_feature(s, ARM_FEATURE_M)) {
461
-}
253
- /*
462
-
254
- * The only M-profile VFP vmrs/vmsr sysreg is FPSCR.
463
-/********* GIC part *********/
255
- * Writes to R15 are UNPREDICTABLE; we choose to undef.
464
-
256
- */
465
#define TYPE_EXYNOS4210_GIC "exynos4210.gic"
257
- if (is_sysreg && (rd == 15 || (rn >> 1) != ARM_VFP_FPSCR)) {
466
OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210GicState, EXYNOS4210_GIC)
258
- return 1;
467
259
- }
260
- }
261
-
262
- if (insn & ARM_CP_RW_BIT) {
263
- /* vfp->arm */
264
- if (is_sysreg) {
265
- /* system register */
266
- rn >>= 1;
267
-
268
- switch (rn) {
269
- case ARM_VFP_FPSID:
270
- /* VFP2 allows access to FSID from userspace.
271
- VFP3 restricts all id registers to privileged
272
- accesses. */
273
- if (IS_USER(s)
274
- && arm_dc_feature(s, ARM_FEATURE_VFP3)) {
275
- return 1;
276
- }
277
- tmp = load_cpu_field(vfp.xregs[rn]);
278
- break;
279
- case ARM_VFP_FPEXC:
280
- if (IS_USER(s))
281
- return 1;
282
- tmp = load_cpu_field(vfp.xregs[rn]);
283
- break;
284
- case ARM_VFP_FPINST:
285
- case ARM_VFP_FPINST2:
286
- /* Not present in VFP3. */
287
- if (IS_USER(s)
288
- || arm_dc_feature(s, ARM_FEATURE_VFP3)) {
289
- return 1;
290
- }
291
- tmp = load_cpu_field(vfp.xregs[rn]);
292
- break;
293
- case ARM_VFP_FPSCR:
294
- if (rd == 15) {
295
- tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
296
- tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
297
- } else {
298
- tmp = tcg_temp_new_i32();
299
- gen_helper_vfp_get_fpscr(tmp, cpu_env);
300
- }
301
- break;
302
- case ARM_VFP_MVFR2:
303
- if (!arm_dc_feature(s, ARM_FEATURE_V8)) {
304
- return 1;
305
- }
306
- /* fall through */
307
- case ARM_VFP_MVFR0:
308
- case ARM_VFP_MVFR1:
309
- if (IS_USER(s)
310
- || !arm_dc_feature(s, ARM_FEATURE_MVFR)) {
311
- return 1;
312
- }
313
- tmp = load_cpu_field(vfp.xregs[rn]);
314
- break;
315
- default:
316
- return 1;
317
- }
318
- } else {
319
- gen_mov_F0_vreg(0, rn);
320
- tmp = gen_vfp_mrs();
321
- }
322
- if (rd == 15) {
323
- /* Set the 4 flag bits in the CPSR. */
324
- gen_set_nzcv(tmp);
325
- tcg_temp_free_i32(tmp);
326
- } else {
327
- store_reg(s, rd, tmp);
328
- }
329
- } else {
330
- /* arm->vfp */
331
- if (is_sysreg) {
332
- rn >>= 1;
333
- /* system register */
334
- switch (rn) {
335
- case ARM_VFP_FPSID:
336
- case ARM_VFP_MVFR0:
337
- case ARM_VFP_MVFR1:
338
- /* Writes are ignored. */
339
- break;
340
- case ARM_VFP_FPSCR:
341
- tmp = load_reg(s, rd);
342
- gen_helper_vfp_set_fpscr(cpu_env, tmp);
343
- tcg_temp_free_i32(tmp);
344
- gen_lookup_tb(s);
345
- break;
346
- case ARM_VFP_FPEXC:
347
- if (IS_USER(s))
348
- return 1;
349
- /* TODO: VFP subarchitecture support.
350
- * For now, keep the EN bit only */
351
- tmp = load_reg(s, rd);
352
- tcg_gen_andi_i32(tmp, tmp, 1 << 30);
353
- store_cpu_field(tmp, vfp.xregs[rn]);
354
- gen_lookup_tb(s);
355
- break;
356
- case ARM_VFP_FPINST:
357
- case ARM_VFP_FPINST2:
358
- if (IS_USER(s)) {
359
- return 1;
360
- }
361
- tmp = load_reg(s, rd);
362
- store_cpu_field(tmp, vfp.xregs[rn]);
363
- break;
364
- default:
365
- return 1;
366
- }
367
- } else {
368
- tmp = load_reg(s, rd);
369
- gen_vfp_msr(tmp);
370
- gen_mov_vreg_F0(0, rn);
371
- }
372
- }
373
- }
374
+ /* already handled by decodetree */
375
+ return 1;
376
} else {
377
/* data processing */
378
bool rd_is_dp = dp;
379
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
380
index XXXXXXX..XXXXXXX 100644
381
--- a/target/arm/vfp.decode
382
+++ b/target/arm/vfp.decode
383
@@ -XXX,XX +XXX,XX @@ VMOV_from_gp ---- 1110 0 0 index:1 0 .... rt:4 1011 .00 1 0000 \
384
385
VDUP ---- 1110 1 b:1 q:1 0 .... rt:4 1011 . 0 e:1 1 0000 \
386
vn=%vn_dp
387
+
388
+VMSR_VMRS ---- 1110 111 l:1 reg:4 rt:4 1010 0001 0000
389
+VMOV_single ---- 1110 000 l:1 .... rt:4 1010 . 001 0000 \
390
+ vn=%vn_sp
391
--
468
--
392
2.20.1
469
2.25.1
393
394
diff view generated by jsdifflib
1
Move the trans_*() functions we've just created from translate.c
1
Switch the creation of the external GIC to the new-style "embedded in
2
to translate-vfp.inc.c. This is pure code motion with no textual
2
state struct" approach, so we can easily refer to the object
3
changes (this can be checked with 'git show --color-moved').
3
elsewhere during realize.
4
4
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220404154658.565020-9-peter.maydell@linaro.org
7
---
8
---
8
target/arm/translate-vfp.inc.c | 337 +++++++++++++++++++++++++++++++++
9
include/hw/arm/exynos4210.h | 2 ++
9
target/arm/translate.c | 337 ---------------------------------
10
include/hw/intc/exynos4210_gic.h | 43 ++++++++++++++++++++++++++++++++
10
2 files changed, 337 insertions(+), 337 deletions(-)
11
hw/arm/exynos4210.c | 10 ++++----
12
hw/intc/exynos4210_gic.c | 17 ++-----------
13
MAINTAINERS | 2 +-
14
5 files changed, 53 insertions(+), 21 deletions(-)
15
create mode 100644 include/hw/intc/exynos4210_gic.h
11
16
12
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
13
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/translate-vfp.inc.c
19
--- a/include/hw/arm/exynos4210.h
15
+++ b/target/arm/translate-vfp.inc.c
20
+++ b/include/hw/arm/exynos4210.h
16
@@ -XXX,XX +XXX,XX @@ static bool vfp_access_check(DisasContext *s)
21
@@ -XXX,XX +XXX,XX @@
17
{
22
#include "hw/or-irq.h"
18
return full_vfp_access_check(s, false);
23
#include "hw/sysbus.h"
19
}
24
#include "hw/cpu/a9mpcore.h"
25
+#include "hw/intc/exynos4210_gic.h"
26
#include "target/arm/cpu-qom.h"
27
#include "qom/object.h"
28
29
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
30
qemu_or_irq pl330_irq_orgate[EXYNOS4210_NUM_DMA];
31
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
32
A9MPPrivState a9mpcore;
33
+ Exynos4210GicState ext_gic;
34
};
35
36
#define TYPE_EXYNOS4210_SOC "exynos4210"
37
diff --git a/include/hw/intc/exynos4210_gic.h b/include/hw/intc/exynos4210_gic.h
38
new file mode 100644
39
index XXXXXXX..XXXXXXX
40
--- /dev/null
41
+++ b/include/hw/intc/exynos4210_gic.h
42
@@ -XXX,XX +XXX,XX @@
43
+/*
44
+ * Samsung exynos4210 GIC implementation. Based on hw/arm_gic.c
45
+ *
46
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
47
+ * All rights reserved.
48
+ *
49
+ * Evgeny Voevodin <e.voevodin@samsung.com>
50
+ *
51
+ * This program is free software; you can redistribute it and/or modify it
52
+ * under the terms of the GNU General Public License as published by the
53
+ * Free Software Foundation; either version 2 of the License, or (at your
54
+ * option) any later version.
55
+ *
56
+ * This program is distributed in the hope that it will be useful,
57
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
58
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
59
+ * See the GNU General Public License for more details.
60
+ *
61
+ * You should have received a copy of the GNU General Public License along
62
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
63
+ */
64
+#ifndef HW_INTC_EXYNOS4210_GIC_H
65
+#define HW_INTC_EXYNOS4210_GIC_H
20
+
66
+
21
+static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
67
+#include "hw/sysbus.h"
22
+{
23
+ uint32_t rd, rn, rm;
24
+ bool dp = a->dp;
25
+
68
+
26
+ if (!dc_isar_feature(aa32_vsel, s)) {
69
+#define TYPE_EXYNOS4210_GIC "exynos4210.gic"
27
+ return false;
70
+OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210GicState, EXYNOS4210_GIC)
28
+ }
29
+
71
+
30
+ /* UNDEF accesses to D16-D31 if they don't exist */
72
+#define EXYNOS4210_GIC_NCPUS 2
31
+ if (dp && !dc_isar_feature(aa32_fp_d32, s) &&
32
+ ((a->vm | a->vn | a->vd) & 0x10)) {
33
+ return false;
34
+ }
35
+ rd = a->vd;
36
+ rn = a->vn;
37
+ rm = a->vm;
38
+
73
+
39
+ if (!vfp_access_check(s)) {
74
+struct Exynos4210GicState {
40
+ return true;
75
+ SysBusDevice parent_obj;
41
+ }
42
+
76
+
43
+ if (dp) {
77
+ MemoryRegion cpu_container;
44
+ TCGv_i64 frn, frm, dest;
78
+ MemoryRegion dist_container;
45
+ TCGv_i64 tmp, zero, zf, nf, vf;
79
+ MemoryRegion cpu_alias[EXYNOS4210_GIC_NCPUS];
46
+
80
+ MemoryRegion dist_alias[EXYNOS4210_GIC_NCPUS];
47
+ zero = tcg_const_i64(0);
81
+ uint32_t num_cpu;
48
+
82
+ DeviceState *gic;
49
+ frn = tcg_temp_new_i64();
50
+ frm = tcg_temp_new_i64();
51
+ dest = tcg_temp_new_i64();
52
+
53
+ zf = tcg_temp_new_i64();
54
+ nf = tcg_temp_new_i64();
55
+ vf = tcg_temp_new_i64();
56
+
57
+ tcg_gen_extu_i32_i64(zf, cpu_ZF);
58
+ tcg_gen_ext_i32_i64(nf, cpu_NF);
59
+ tcg_gen_ext_i32_i64(vf, cpu_VF);
60
+
61
+ tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
62
+ tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
63
+ switch (a->cc) {
64
+ case 0: /* eq: Z */
65
+ tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
66
+ frn, frm);
67
+ break;
68
+ case 1: /* vs: V */
69
+ tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero,
70
+ frn, frm);
71
+ break;
72
+ case 2: /* ge: N == V -> N ^ V == 0 */
73
+ tmp = tcg_temp_new_i64();
74
+ tcg_gen_xor_i64(tmp, vf, nf);
75
+ tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
76
+ frn, frm);
77
+ tcg_temp_free_i64(tmp);
78
+ break;
79
+ case 3: /* gt: !Z && N == V */
80
+ tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero,
81
+ frn, frm);
82
+ tmp = tcg_temp_new_i64();
83
+ tcg_gen_xor_i64(tmp, vf, nf);
84
+ tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
85
+ dest, frm);
86
+ tcg_temp_free_i64(tmp);
87
+ break;
88
+ }
89
+ tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
90
+ tcg_temp_free_i64(frn);
91
+ tcg_temp_free_i64(frm);
92
+ tcg_temp_free_i64(dest);
93
+
94
+ tcg_temp_free_i64(zf);
95
+ tcg_temp_free_i64(nf);
96
+ tcg_temp_free_i64(vf);
97
+
98
+ tcg_temp_free_i64(zero);
99
+ } else {
100
+ TCGv_i32 frn, frm, dest;
101
+ TCGv_i32 tmp, zero;
102
+
103
+ zero = tcg_const_i32(0);
104
+
105
+ frn = tcg_temp_new_i32();
106
+ frm = tcg_temp_new_i32();
107
+ dest = tcg_temp_new_i32();
108
+ tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
109
+ tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
110
+ switch (a->cc) {
111
+ case 0: /* eq: Z */
112
+ tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
113
+ frn, frm);
114
+ break;
115
+ case 1: /* vs: V */
116
+ tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero,
117
+ frn, frm);
118
+ break;
119
+ case 2: /* ge: N == V -> N ^ V == 0 */
120
+ tmp = tcg_temp_new_i32();
121
+ tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
122
+ tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
123
+ frn, frm);
124
+ tcg_temp_free_i32(tmp);
125
+ break;
126
+ case 3: /* gt: !Z && N == V */
127
+ tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero,
128
+ frn, frm);
129
+ tmp = tcg_temp_new_i32();
130
+ tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
131
+ tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
132
+ dest, frm);
133
+ tcg_temp_free_i32(tmp);
134
+ break;
135
+ }
136
+ tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
137
+ tcg_temp_free_i32(frn);
138
+ tcg_temp_free_i32(frm);
139
+ tcg_temp_free_i32(dest);
140
+
141
+ tcg_temp_free_i32(zero);
142
+ }
143
+
144
+ return true;
145
+}
146
+
147
+static bool trans_VMINMAXNM(DisasContext *s, arg_VMINMAXNM *a)
148
+{
149
+ uint32_t rd, rn, rm;
150
+ bool dp = a->dp;
151
+ bool vmin = a->op;
152
+ TCGv_ptr fpst;
153
+
154
+ if (!dc_isar_feature(aa32_vminmaxnm, s)) {
155
+ return false;
156
+ }
157
+
158
+ /* UNDEF accesses to D16-D31 if they don't exist */
159
+ if (dp && !dc_isar_feature(aa32_fp_d32, s) &&
160
+ ((a->vm | a->vn | a->vd) & 0x10)) {
161
+ return false;
162
+ }
163
+ rd = a->vd;
164
+ rn = a->vn;
165
+ rm = a->vm;
166
+
167
+ if (!vfp_access_check(s)) {
168
+ return true;
169
+ }
170
+
171
+ fpst = get_fpstatus_ptr(0);
172
+
173
+ if (dp) {
174
+ TCGv_i64 frn, frm, dest;
175
+
176
+ frn = tcg_temp_new_i64();
177
+ frm = tcg_temp_new_i64();
178
+ dest = tcg_temp_new_i64();
179
+
180
+ tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
181
+ tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
182
+ if (vmin) {
183
+ gen_helper_vfp_minnumd(dest, frn, frm, fpst);
184
+ } else {
185
+ gen_helper_vfp_maxnumd(dest, frn, frm, fpst);
186
+ }
187
+ tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
188
+ tcg_temp_free_i64(frn);
189
+ tcg_temp_free_i64(frm);
190
+ tcg_temp_free_i64(dest);
191
+ } else {
192
+ TCGv_i32 frn, frm, dest;
193
+
194
+ frn = tcg_temp_new_i32();
195
+ frm = tcg_temp_new_i32();
196
+ dest = tcg_temp_new_i32();
197
+
198
+ tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
199
+ tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
200
+ if (vmin) {
201
+ gen_helper_vfp_minnums(dest, frn, frm, fpst);
202
+ } else {
203
+ gen_helper_vfp_maxnums(dest, frn, frm, fpst);
204
+ }
205
+ tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
206
+ tcg_temp_free_i32(frn);
207
+ tcg_temp_free_i32(frm);
208
+ tcg_temp_free_i32(dest);
209
+ }
210
+
211
+ tcg_temp_free_ptr(fpst);
212
+ return true;
213
+}
214
+
215
+/*
216
+ * Table for converting the most common AArch32 encoding of
217
+ * rounding mode to arm_fprounding order (which matches the
218
+ * common AArch64 order); see ARM ARM pseudocode FPDecodeRM().
219
+ */
220
+static const uint8_t fp_decode_rm[] = {
221
+ FPROUNDING_TIEAWAY,
222
+ FPROUNDING_TIEEVEN,
223
+ FPROUNDING_POSINF,
224
+ FPROUNDING_NEGINF,
225
+};
83
+};
226
+
84
+
227
+static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
85
+#endif
228
+{
86
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
229
+ uint32_t rd, rm;
230
+ bool dp = a->dp;
231
+ TCGv_ptr fpst;
232
+ TCGv_i32 tcg_rmode;
233
+ int rounding = fp_decode_rm[a->rm];
234
+
235
+ if (!dc_isar_feature(aa32_vrint, s)) {
236
+ return false;
237
+ }
238
+
239
+ /* UNDEF accesses to D16-D31 if they don't exist */
240
+ if (dp && !dc_isar_feature(aa32_fp_d32, s) &&
241
+ ((a->vm | a->vd) & 0x10)) {
242
+ return false;
243
+ }
244
+ rd = a->vd;
245
+ rm = a->vm;
246
+
247
+ if (!vfp_access_check(s)) {
248
+ return true;
249
+ }
250
+
251
+ fpst = get_fpstatus_ptr(0);
252
+
253
+ tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
254
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
255
+
256
+ if (dp) {
257
+ TCGv_i64 tcg_op;
258
+ TCGv_i64 tcg_res;
259
+ tcg_op = tcg_temp_new_i64();
260
+ tcg_res = tcg_temp_new_i64();
261
+ tcg_gen_ld_f64(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
262
+ gen_helper_rintd(tcg_res, tcg_op, fpst);
263
+ tcg_gen_st_f64(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
264
+ tcg_temp_free_i64(tcg_op);
265
+ tcg_temp_free_i64(tcg_res);
266
+ } else {
267
+ TCGv_i32 tcg_op;
268
+ TCGv_i32 tcg_res;
269
+ tcg_op = tcg_temp_new_i32();
270
+ tcg_res = tcg_temp_new_i32();
271
+ tcg_gen_ld_f32(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
272
+ gen_helper_rints(tcg_res, tcg_op, fpst);
273
+ tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
274
+ tcg_temp_free_i32(tcg_op);
275
+ tcg_temp_free_i32(tcg_res);
276
+ }
277
+
278
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
279
+ tcg_temp_free_i32(tcg_rmode);
280
+
281
+ tcg_temp_free_ptr(fpst);
282
+ return true;
283
+}
284
+
285
+static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
286
+{
287
+ uint32_t rd, rm;
288
+ bool dp = a->dp;
289
+ TCGv_ptr fpst;
290
+ TCGv_i32 tcg_rmode, tcg_shift;
291
+ int rounding = fp_decode_rm[a->rm];
292
+ bool is_signed = a->op;
293
+
294
+ if (!dc_isar_feature(aa32_vcvt_dr, s)) {
295
+ return false;
296
+ }
297
+
298
+ /* UNDEF accesses to D16-D31 if they don't exist */
299
+ if (dp && !dc_isar_feature(aa32_fp_d32, s) && (a->vm & 0x10)) {
300
+ return false;
301
+ }
302
+ rd = a->vd;
303
+ rm = a->vm;
304
+
305
+ if (!vfp_access_check(s)) {
306
+ return true;
307
+ }
308
+
309
+ fpst = get_fpstatus_ptr(0);
310
+
311
+ tcg_shift = tcg_const_i32(0);
312
+
313
+ tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
314
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
315
+
316
+ if (dp) {
317
+ TCGv_i64 tcg_double, tcg_res;
318
+ TCGv_i32 tcg_tmp;
319
+ tcg_double = tcg_temp_new_i64();
320
+ tcg_res = tcg_temp_new_i64();
321
+ tcg_tmp = tcg_temp_new_i32();
322
+ tcg_gen_ld_f64(tcg_double, cpu_env, vfp_reg_offset(1, rm));
323
+ if (is_signed) {
324
+ gen_helper_vfp_tosld(tcg_res, tcg_double, tcg_shift, fpst);
325
+ } else {
326
+ gen_helper_vfp_tould(tcg_res, tcg_double, tcg_shift, fpst);
327
+ }
328
+ tcg_gen_extrl_i64_i32(tcg_tmp, tcg_res);
329
+ tcg_gen_st_f32(tcg_tmp, cpu_env, vfp_reg_offset(0, rd));
330
+ tcg_temp_free_i32(tcg_tmp);
331
+ tcg_temp_free_i64(tcg_res);
332
+ tcg_temp_free_i64(tcg_double);
333
+ } else {
334
+ TCGv_i32 tcg_single, tcg_res;
335
+ tcg_single = tcg_temp_new_i32();
336
+ tcg_res = tcg_temp_new_i32();
337
+ tcg_gen_ld_f32(tcg_single, cpu_env, vfp_reg_offset(0, rm));
338
+ if (is_signed) {
339
+ gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
340
+ } else {
341
+ gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
342
+ }
343
+ tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(0, rd));
344
+ tcg_temp_free_i32(tcg_res);
345
+ tcg_temp_free_i32(tcg_single);
346
+ }
347
+
348
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
349
+ tcg_temp_free_i32(tcg_rmode);
350
+
351
+ tcg_temp_free_i32(tcg_shift);
352
+
353
+ tcg_temp_free_ptr(fpst);
354
+
355
+ return true;
356
+}
357
diff --git a/target/arm/translate.c b/target/arm/translate.c
358
index XXXXXXX..XXXXXXX 100644
87
index XXXXXXX..XXXXXXX 100644
359
--- a/target/arm/translate.c
88
--- a/hw/arm/exynos4210.c
360
+++ b/target/arm/translate.c
89
+++ b/hw/arm/exynos4210.c
361
@@ -XXX,XX +XXX,XX @@ static void gen_neon_dup_high16(TCGv_i32 var)
90
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
362
tcg_temp_free_i32(tmp);
91
sysbus_create_simple("l2x0", EXYNOS4210_L2X0_BASE_ADDR, NULL);
92
93
/* External GIC */
94
- dev = qdev_new("exynos4210.gic");
95
- qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS);
96
- busdev = SYS_BUS_DEVICE(dev);
97
- sysbus_realize_and_unref(busdev, &error_fatal);
98
+ qdev_prop_set_uint32(DEVICE(&s->ext_gic), "num-cpu", EXYNOS4210_NCPUS);
99
+ busdev = SYS_BUS_DEVICE(&s->ext_gic);
100
+ sysbus_realize(busdev, &error_fatal);
101
/* Map CPU interface */
102
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_GIC_CPU_BASE_ADDR);
103
/* Map Distributer interface */
104
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
105
qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 1));
106
}
107
for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
108
- s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(dev, n);
109
+ s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->ext_gic), n);
110
}
111
112
/* Internal Interrupt Combiner */
113
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
114
}
115
116
object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
117
+ object_initialize_child(obj, "ext-gic", &s->ext_gic, TYPE_EXYNOS4210_GIC);
363
}
118
}
364
119
365
-static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
120
static void exynos4210_class_init(ObjectClass *klass, void *data)
366
-{
121
diff --git a/hw/intc/exynos4210_gic.c b/hw/intc/exynos4210_gic.c
367
- uint32_t rd, rn, rm;
122
index XXXXXXX..XXXXXXX 100644
368
- bool dp = a->dp;
123
--- a/hw/intc/exynos4210_gic.c
124
+++ b/hw/intc/exynos4210_gic.c
125
@@ -XXX,XX +XXX,XX @@
126
#include "qemu/module.h"
127
#include "hw/irq.h"
128
#include "hw/qdev-properties.h"
129
+#include "hw/intc/exynos4210_gic.h"
130
#include "hw/arm/exynos4210.h"
131
#include "qom/object.h"
132
133
@@ -XXX,XX +XXX,XX @@
134
#define EXYNOS4210_GIC_CPU_REGION_SIZE 0x100
135
#define EXYNOS4210_GIC_DIST_REGION_SIZE 0x1000
136
137
-#define TYPE_EXYNOS4210_GIC "exynos4210.gic"
138
-OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210GicState, EXYNOS4210_GIC)
369
-
139
-
370
- if (!dc_isar_feature(aa32_vsel, s)) {
140
-struct Exynos4210GicState {
371
- return false;
141
- SysBusDevice parent_obj;
372
- }
373
-
142
-
374
- /* UNDEF accesses to D16-D31 if they don't exist */
143
- MemoryRegion cpu_container;
375
- if (dp && !dc_isar_feature(aa32_fp_d32, s) &&
144
- MemoryRegion dist_container;
376
- ((a->vm | a->vn | a->vd) & 0x10)) {
145
- MemoryRegion cpu_alias[EXYNOS4210_NCPUS];
377
- return false;
146
- MemoryRegion dist_alias[EXYNOS4210_NCPUS];
378
- }
147
- uint32_t num_cpu;
379
- rd = a->vd;
148
- DeviceState *gic;
380
- rn = a->vn;
381
- rm = a->vm;
382
-
383
- if (!vfp_access_check(s)) {
384
- return true;
385
- }
386
-
387
- if (dp) {
388
- TCGv_i64 frn, frm, dest;
389
- TCGv_i64 tmp, zero, zf, nf, vf;
390
-
391
- zero = tcg_const_i64(0);
392
-
393
- frn = tcg_temp_new_i64();
394
- frm = tcg_temp_new_i64();
395
- dest = tcg_temp_new_i64();
396
-
397
- zf = tcg_temp_new_i64();
398
- nf = tcg_temp_new_i64();
399
- vf = tcg_temp_new_i64();
400
-
401
- tcg_gen_extu_i32_i64(zf, cpu_ZF);
402
- tcg_gen_ext_i32_i64(nf, cpu_NF);
403
- tcg_gen_ext_i32_i64(vf, cpu_VF);
404
-
405
- tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
406
- tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
407
- switch (a->cc) {
408
- case 0: /* eq: Z */
409
- tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
410
- frn, frm);
411
- break;
412
- case 1: /* vs: V */
413
- tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero,
414
- frn, frm);
415
- break;
416
- case 2: /* ge: N == V -> N ^ V == 0 */
417
- tmp = tcg_temp_new_i64();
418
- tcg_gen_xor_i64(tmp, vf, nf);
419
- tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
420
- frn, frm);
421
- tcg_temp_free_i64(tmp);
422
- break;
423
- case 3: /* gt: !Z && N == V */
424
- tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero,
425
- frn, frm);
426
- tmp = tcg_temp_new_i64();
427
- tcg_gen_xor_i64(tmp, vf, nf);
428
- tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
429
- dest, frm);
430
- tcg_temp_free_i64(tmp);
431
- break;
432
- }
433
- tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
434
- tcg_temp_free_i64(frn);
435
- tcg_temp_free_i64(frm);
436
- tcg_temp_free_i64(dest);
437
-
438
- tcg_temp_free_i64(zf);
439
- tcg_temp_free_i64(nf);
440
- tcg_temp_free_i64(vf);
441
-
442
- tcg_temp_free_i64(zero);
443
- } else {
444
- TCGv_i32 frn, frm, dest;
445
- TCGv_i32 tmp, zero;
446
-
447
- zero = tcg_const_i32(0);
448
-
449
- frn = tcg_temp_new_i32();
450
- frm = tcg_temp_new_i32();
451
- dest = tcg_temp_new_i32();
452
- tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
453
- tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
454
- switch (a->cc) {
455
- case 0: /* eq: Z */
456
- tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
457
- frn, frm);
458
- break;
459
- case 1: /* vs: V */
460
- tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero,
461
- frn, frm);
462
- break;
463
- case 2: /* ge: N == V -> N ^ V == 0 */
464
- tmp = tcg_temp_new_i32();
465
- tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
466
- tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
467
- frn, frm);
468
- tcg_temp_free_i32(tmp);
469
- break;
470
- case 3: /* gt: !Z && N == V */
471
- tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero,
472
- frn, frm);
473
- tmp = tcg_temp_new_i32();
474
- tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
475
- tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
476
- dest, frm);
477
- tcg_temp_free_i32(tmp);
478
- break;
479
- }
480
- tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
481
- tcg_temp_free_i32(frn);
482
- tcg_temp_free_i32(frm);
483
- tcg_temp_free_i32(dest);
484
-
485
- tcg_temp_free_i32(zero);
486
- }
487
-
488
- return true;
489
-}
490
-
491
-static bool trans_VMINMAXNM(DisasContext *s, arg_VMINMAXNM *a)
492
-{
493
- uint32_t rd, rn, rm;
494
- bool dp = a->dp;
495
- bool vmin = a->op;
496
- TCGv_ptr fpst;
497
-
498
- if (!dc_isar_feature(aa32_vminmaxnm, s)) {
499
- return false;
500
- }
501
-
502
- /* UNDEF accesses to D16-D31 if they don't exist */
503
- if (dp && !dc_isar_feature(aa32_fp_d32, s) &&
504
- ((a->vm | a->vn | a->vd) & 0x10)) {
505
- return false;
506
- }
507
- rd = a->vd;
508
- rn = a->vn;
509
- rm = a->vm;
510
-
511
- if (!vfp_access_check(s)) {
512
- return true;
513
- }
514
-
515
- fpst = get_fpstatus_ptr(0);
516
-
517
- if (dp) {
518
- TCGv_i64 frn, frm, dest;
519
-
520
- frn = tcg_temp_new_i64();
521
- frm = tcg_temp_new_i64();
522
- dest = tcg_temp_new_i64();
523
-
524
- tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
525
- tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
526
- if (vmin) {
527
- gen_helper_vfp_minnumd(dest, frn, frm, fpst);
528
- } else {
529
- gen_helper_vfp_maxnumd(dest, frn, frm, fpst);
530
- }
531
- tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
532
- tcg_temp_free_i64(frn);
533
- tcg_temp_free_i64(frm);
534
- tcg_temp_free_i64(dest);
535
- } else {
536
- TCGv_i32 frn, frm, dest;
537
-
538
- frn = tcg_temp_new_i32();
539
- frm = tcg_temp_new_i32();
540
- dest = tcg_temp_new_i32();
541
-
542
- tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
543
- tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
544
- if (vmin) {
545
- gen_helper_vfp_minnums(dest, frn, frm, fpst);
546
- } else {
547
- gen_helper_vfp_maxnums(dest, frn, frm, fpst);
548
- }
549
- tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
550
- tcg_temp_free_i32(frn);
551
- tcg_temp_free_i32(frm);
552
- tcg_temp_free_i32(dest);
553
- }
554
-
555
- tcg_temp_free_ptr(fpst);
556
- return true;
557
-}
558
-
559
-/*
560
- * Table for converting the most common AArch32 encoding of
561
- * rounding mode to arm_fprounding order (which matches the
562
- * common AArch64 order); see ARM ARM pseudocode FPDecodeRM().
563
- */
564
-static const uint8_t fp_decode_rm[] = {
565
- FPROUNDING_TIEAWAY,
566
- FPROUNDING_TIEEVEN,
567
- FPROUNDING_POSINF,
568
- FPROUNDING_NEGINF,
569
-};
149
-};
570
-
150
-
571
-static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
151
static void exynos4210_gic_set_irq(void *opaque, int irq, int level)
572
-{
152
{
573
- uint32_t rd, rm;
153
Exynos4210GicState *s = (Exynos4210GicState *)opaque;
574
- bool dp = a->dp;
154
@@ -XXX,XX +XXX,XX @@ static void exynos4210_gic_realize(DeviceState *dev, Error **errp)
575
- TCGv_ptr fpst;
155
* enough room for the cpu numbers. gcc 9.2.1 on 32-bit x86
576
- TCGv_i32 tcg_rmode;
156
* doesn't figure this out, otherwise and gives spurious warnings.
577
- int rounding = fp_decode_rm[a->rm];
157
*/
578
-
158
- assert(n <= EXYNOS4210_NCPUS);
579
- if (!dc_isar_feature(aa32_vrint, s)) {
159
+ assert(n <= EXYNOS4210_GIC_NCPUS);
580
- return false;
160
for (i = 0; i < n; i++) {
581
- }
161
/* Map CPU interface per SMP Core */
582
-
162
sprintf(cpu_alias_name, "%s%x", cpu_prefix, i);
583
- /* UNDEF accesses to D16-D31 if they don't exist */
163
diff --git a/MAINTAINERS b/MAINTAINERS
584
- if (dp && !dc_isar_feature(aa32_fp_d32, s) &&
164
index XXXXXXX..XXXXXXX 100644
585
- ((a->vm | a->vd) & 0x10)) {
165
--- a/MAINTAINERS
586
- return false;
166
+++ b/MAINTAINERS
587
- }
167
@@ -XXX,XX +XXX,XX @@ M: Peter Maydell <peter.maydell@linaro.org>
588
- rd = a->vd;
168
L: qemu-arm@nongnu.org
589
- rm = a->vm;
169
S: Odd Fixes
590
-
170
F: hw/*/exynos*
591
- if (!vfp_access_check(s)) {
171
-F: include/hw/arm/exynos4210.h
592
- return true;
172
+F: include/hw/*/exynos*
593
- }
173
594
-
174
Calxeda Highbank
595
- fpst = get_fpstatus_ptr(0);
175
M: Rob Herring <robh@kernel.org>
596
-
597
- tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
598
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
599
-
600
- if (dp) {
601
- TCGv_i64 tcg_op;
602
- TCGv_i64 tcg_res;
603
- tcg_op = tcg_temp_new_i64();
604
- tcg_res = tcg_temp_new_i64();
605
- tcg_gen_ld_f64(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
606
- gen_helper_rintd(tcg_res, tcg_op, fpst);
607
- tcg_gen_st_f64(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
608
- tcg_temp_free_i64(tcg_op);
609
- tcg_temp_free_i64(tcg_res);
610
- } else {
611
- TCGv_i32 tcg_op;
612
- TCGv_i32 tcg_res;
613
- tcg_op = tcg_temp_new_i32();
614
- tcg_res = tcg_temp_new_i32();
615
- tcg_gen_ld_f32(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
616
- gen_helper_rints(tcg_res, tcg_op, fpst);
617
- tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
618
- tcg_temp_free_i32(tcg_op);
619
- tcg_temp_free_i32(tcg_res);
620
- }
621
-
622
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
623
- tcg_temp_free_i32(tcg_rmode);
624
-
625
- tcg_temp_free_ptr(fpst);
626
- return true;
627
-}
628
-
629
-static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
630
-{
631
- uint32_t rd, rm;
632
- bool dp = a->dp;
633
- TCGv_ptr fpst;
634
- TCGv_i32 tcg_rmode, tcg_shift;
635
- int rounding = fp_decode_rm[a->rm];
636
- bool is_signed = a->op;
637
-
638
- if (!dc_isar_feature(aa32_vcvt_dr, s)) {
639
- return false;
640
- }
641
-
642
- /* UNDEF accesses to D16-D31 if they don't exist */
643
- if (dp && !dc_isar_feature(aa32_fp_d32, s) && (a->vm & 0x10)) {
644
- return false;
645
- }
646
- rd = a->vd;
647
- rm = a->vm;
648
-
649
- if (!vfp_access_check(s)) {
650
- return true;
651
- }
652
-
653
- fpst = get_fpstatus_ptr(0);
654
-
655
- tcg_shift = tcg_const_i32(0);
656
-
657
- tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
658
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
659
-
660
- if (dp) {
661
- TCGv_i64 tcg_double, tcg_res;
662
- TCGv_i32 tcg_tmp;
663
- tcg_double = tcg_temp_new_i64();
664
- tcg_res = tcg_temp_new_i64();
665
- tcg_tmp = tcg_temp_new_i32();
666
- tcg_gen_ld_f64(tcg_double, cpu_env, vfp_reg_offset(1, rm));
667
- if (is_signed) {
668
- gen_helper_vfp_tosld(tcg_res, tcg_double, tcg_shift, fpst);
669
- } else {
670
- gen_helper_vfp_tould(tcg_res, tcg_double, tcg_shift, fpst);
671
- }
672
- tcg_gen_extrl_i64_i32(tcg_tmp, tcg_res);
673
- tcg_gen_st_f32(tcg_tmp, cpu_env, vfp_reg_offset(0, rd));
674
- tcg_temp_free_i32(tcg_tmp);
675
- tcg_temp_free_i64(tcg_res);
676
- tcg_temp_free_i64(tcg_double);
677
- } else {
678
- TCGv_i32 tcg_single, tcg_res;
679
- tcg_single = tcg_temp_new_i32();
680
- tcg_res = tcg_temp_new_i32();
681
- tcg_gen_ld_f32(tcg_single, cpu_env, vfp_reg_offset(0, rm));
682
- if (is_signed) {
683
- gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
684
- } else {
685
- gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
686
- }
687
- tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(0, rd));
688
- tcg_temp_free_i32(tcg_res);
689
- tcg_temp_free_i32(tcg_single);
690
- }
691
-
692
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
693
- tcg_temp_free_i32(tcg_rmode);
694
-
695
- tcg_temp_free_i32(tcg_shift);
696
-
697
- tcg_temp_free_ptr(fpst);
698
-
699
- return true;
700
-}
701
-
702
/*
703
* Disassemble a VFP instruction. Returns nonzero if an error occurred
704
* (ie. an undefined instruction).
705
--
176
--
706
2.20.1
177
2.25.1
707
708
diff view generated by jsdifflib
1
Convert the VCVTA/VCVTN/VCVTP/VCVTM instructions to decodetree.
1
The only time we use the ext_gic_irq[] array in the Exynos4210Irq
2
trans_VCVT() is temporarily left in translate.c.
2
struct is during realize of the SoC -- we initialize it with the
3
input IRQs of the external GIC device, and then connect those to
4
outputs of other devices further on in realize (including in the
5
exynos4210_init_board_irqs() function). Now that the ext_gic object
6
is easily accessible as s->ext_gic we can make the connections
7
directly from one device to the other without going via this array.
3
8
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-10-peter.maydell@linaro.org
6
---
12
---
7
target/arm/translate.c | 72 +++++++++++++++++-------------------
13
include/hw/arm/exynos4210.h | 1 -
8
target/arm/vfp-uncond.decode | 6 +++
14
hw/arm/exynos4210.c | 12 ++++++------
9
2 files changed, 39 insertions(+), 39 deletions(-)
15
2 files changed, 6 insertions(+), 7 deletions(-)
10
16
11
diff --git a/target/arm/translate.c b/target/arm/translate.c
17
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
12
index XXXXXXX..XXXXXXX 100644
18
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate.c
19
--- a/include/hw/arm/exynos4210.h
14
+++ b/target/arm/translate.c
20
+++ b/include/hw/arm/exynos4210.h
15
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
21
@@ -XXX,XX +XXX,XX @@
16
return true;
22
typedef struct Exynos4210Irq {
17
}
23
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
18
24
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
19
-static int handle_vcvt(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
25
- qemu_irq ext_gic_irq[EXYNOS4210_EXT_GIC_NIRQ];
20
- int rounding)
26
} Exynos4210Irq;
21
+static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
27
28
struct Exynos4210State {
29
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/arm/exynos4210.c
32
+++ b/hw/arm/exynos4210.c
33
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
22
{
34
{
23
- bool is_signed = extract32(insn, 7, 1);
35
uint32_t grp, bit, irq_id, n;
24
- TCGv_ptr fpst = get_fpstatus_ptr(0);
36
Exynos4210Irq *is = &s->irqs;
25
+ uint32_t rd, rm;
37
+ DeviceState *extgicdev = DEVICE(&s->ext_gic);
26
+ bool dp = a->dp;
38
27
+ TCGv_ptr fpst;
39
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
28
TCGv_i32 tcg_rmode, tcg_shift;
40
irq_id = 0;
29
+ int rounding = fp_decode_rm[a->rm];
41
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
30
+ bool is_signed = a->op;
42
}
31
+
43
if (irq_id) {
32
+ if (!dc_isar_feature(aa32_vcvt_dr, s)) {
44
s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
33
+ return false;
45
- is->ext_gic_irq[irq_id - 32]);
34
+ }
46
+ qdev_get_gpio_in(extgicdev,
35
+
47
+ irq_id - 32));
36
+ /* UNDEF accesses to D16-D31 if they don't exist */
48
} else {
37
+ if (dp && !dc_isar_feature(aa32_fp_d32, s) && (a->vm & 0x10)) {
49
s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
38
+ return false;
50
is->ext_combiner_irq[n]);
39
+ }
51
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
40
+ rd = a->vd;
52
41
+ rm = a->vm;
53
if (irq_id) {
42
+
54
s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
43
+ if (!vfp_access_check(s)) {
55
- is->ext_gic_irq[irq_id - 32]);
44
+ return true;
56
+ qdev_get_gpio_in(extgicdev,
45
+ }
57
+ irq_id - 32));
46
+
47
+ fpst = get_fpstatus_ptr(0);
48
49
tcg_shift = tcg_const_i32(0);
50
51
@@ -XXX,XX +XXX,XX @@ static int handle_vcvt(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
52
if (dp) {
53
TCGv_i64 tcg_double, tcg_res;
54
TCGv_i32 tcg_tmp;
55
- /* Rd is encoded as a single precision register even when the source
56
- * is double precision.
57
- */
58
- rd = ((rd << 1) & 0x1e) | ((rd >> 4) & 0x1);
59
tcg_double = tcg_temp_new_i64();
60
tcg_res = tcg_temp_new_i64();
61
tcg_tmp = tcg_temp_new_i32();
62
@@ -XXX,XX +XXX,XX @@ static int handle_vcvt(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
63
64
tcg_temp_free_ptr(fpst);
65
66
- return 0;
67
-}
68
-
69
-static int disas_vfp_misc_insn(DisasContext *s, uint32_t insn)
70
-{
71
- uint32_t rd, rm, dp = extract32(insn, 8, 1);
72
-
73
- if (dp) {
74
- VFP_DREG_D(rd, insn);
75
- VFP_DREG_M(rm, insn);
76
- } else {
77
- rd = VFP_SREG_D(insn);
78
- rm = VFP_SREG_M(insn);
79
- }
80
-
81
- if ((insn & 0x0fbc0e50) == 0x0ebc0a40 &&
82
- dc_isar_feature(aa32_vcvt_dr, s)) {
83
- /* VCVTA, VCVTN, VCVTP, VCVTM */
84
- int rounding = fp_decode_rm[extract32(insn, 16, 2)];
85
- return handle_vcvt(insn, rd, rm, dp, rounding);
86
- }
87
- return 1;
88
+ return true;
89
}
90
91
/*
92
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
93
}
58
}
94
}
59
}
95
60
}
96
+ if (extract32(insn, 28, 4) == 0xf) {
61
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
97
+ /*
62
sysbus_connect_irq(busdev, n,
98
+ * Encodings with T=1 (Thumb) or unconditional (ARM): these
63
qdev_get_gpio_in(DEVICE(&s->cpu_irq_orgate[n]), 1));
99
+ * were all handled by the decodetree decoder, so any insn
100
+ * patterns which get here must be UNDEF.
101
+ */
102
+ return 1;
103
+ }
104
+
105
/*
106
* FIXME: this access check should not take precedence over UNDEF
107
* for invalid encodings; we will generate incorrect syndrome information
108
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
109
return 0;
110
}
64
}
111
65
- for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) {
112
- if (extract32(insn, 28, 4) == 0xf) {
66
- s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(DEVICE(&s->ext_gic), n);
113
- /*
114
- * Encodings with T=1 (Thumb) or unconditional (ARM):
115
- * only used for the "miscellaneous VFP features" added in v8A
116
- * and v7M (and gated on the MVFR2.FPMisc field).
117
- */
118
- return disas_vfp_misc_insn(s, insn);
119
- }
67
- }
120
-
68
121
dp = ((insn & 0xf00) == 0xb00);
69
/* Internal Interrupt Combiner */
122
switch ((insn >> 24) & 0xf) {
70
dev = qdev_new("exynos4210.combiner");
123
case 0xe:
71
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
124
diff --git a/target/arm/vfp-uncond.decode b/target/arm/vfp-uncond.decode
72
busdev = SYS_BUS_DEVICE(dev);
125
index XXXXXXX..XXXXXXX 100644
73
sysbus_realize_and_unref(busdev, &error_fatal);
126
--- a/target/arm/vfp-uncond.decode
74
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
127
+++ b/target/arm/vfp-uncond.decode
75
- sysbus_connect_irq(busdev, n, s->irqs.ext_gic_irq[n]);
128
@@ -XXX,XX +XXX,XX @@ VRINT 1111 1110 1.11 10 rm:2 .... 1010 01.0 .... \
76
+ sysbus_connect_irq(busdev, n, qdev_get_gpio_in(DEVICE(&s->ext_gic), n));
129
vm=%vm_sp vd=%vd_sp dp=0
77
}
130
VRINT 1111 1110 1.11 10 rm:2 .... 1011 01.0 .... \
78
exynos4210_combiner_get_gpioin(&s->irqs, dev, 1);
131
vm=%vm_dp vd=%vd_dp dp=1
79
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
132
+
133
+# VCVT float to int with specified rounding mode; Vd is always single-precision
134
+VCVT 1111 1110 1.11 11 rm:2 .... 1010 op:1 1.0 .... \
135
+ vm=%vm_sp vd=%vd_sp dp=0
136
+VCVT 1111 1110 1.11 11 rm:2 .... 1011 op:1 1.0 .... \
137
+ vm=%vm_dp vd=%vd_sp dp=1
138
--
80
--
139
2.20.1
81
2.25.1
140
141
diff view generated by jsdifflib
1
Convert the VFP VNMLA instruction to decodetree.
1
The function exynos4210_combiner_get_gpioin() currently lives in
2
exynos4210_combiner.c, but it isn't really part of the combiner
3
device itself -- it is a function that implements the wiring up of
4
some interrupt sources to multiple combiner inputs. Move it to live
5
with the other SoC-level code in exynos4210.c, along with a few
6
macros previously defined in exynos4210.h which are now used only
7
in exynos4210.c.
2
8
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
11
Message-id: 20220404154658.565020-11-peter.maydell@linaro.org
5
---
12
---
6
target/arm/translate-vfp.inc.c | 34 ++++++++++++++++++++++++++++++++++
13
include/hw/arm/exynos4210.h | 11 -----
7
target/arm/translate.c | 19 +------------------
14
hw/arm/exynos4210.c | 82 +++++++++++++++++++++++++++++++++++
8
target/arm/vfp.decode | 5 +++++
15
hw/intc/exynos4210_combiner.c | 77 --------------------------------
9
3 files changed, 40 insertions(+), 18 deletions(-)
16
3 files changed, 82 insertions(+), 88 deletions(-)
10
17
11
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
18
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
12
index XXXXXXX..XXXXXXX 100644
19
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-vfp.inc.c
20
--- a/include/hw/arm/exynos4210.h
14
+++ b/target/arm/translate-vfp.inc.c
21
+++ b/include/hw/arm/exynos4210.h
15
@@ -XXX,XX +XXX,XX @@ static bool trans_VNMLS_dp(DisasContext *s, arg_VNMLS_sp *a)
22
@@ -XXX,XX +XXX,XX @@
16
{
23
#define EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ \
17
return do_vfp_3op_dp(s, gen_VNMLS_dp, a->vd, a->vn, a->vm, true);
24
(EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ * 8)
25
26
-#define EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit) ((grp)*8 + (bit))
27
-#define EXYNOS4210_COMBINER_GET_GRP_NUM(irq) ((irq) / 8)
28
-#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
29
- ((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
30
-
31
/* IRQs number for external and internal GIC */
32
#define EXYNOS4210_EXT_GIC_NIRQ (160-32)
33
#define EXYNOS4210_INT_GIC_NIRQ 64
34
@@ -XXX,XX +XXX,XX @@ void exynos4210_write_secondary(ARMCPU *cpu,
35
* bit - bit number inside group */
36
uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit);
37
38
-/*
39
- * Get Combiner input GPIO into irqs structure
40
- */
41
-void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs, DeviceState *dev,
42
- int ext);
43
-
44
/*
45
* exynos4210 UART
46
*/
47
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
48
index XXXXXXX..XXXXXXX 100644
49
--- a/hw/arm/exynos4210.c
50
+++ b/hw/arm/exynos4210.c
51
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
52
{ }, { }, { }, { }, { }, { }, { }, { }, { }, { }
53
};
54
55
+#define EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit) ((grp) * 8 + (bit))
56
+#define EXYNOS4210_COMBINER_GET_GRP_NUM(irq) ((irq) / 8)
57
+#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
58
+ ((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
59
+
60
/*
61
* Initialize board IRQs.
62
* These IRQs contain splitted Int/External Combiner and External Gic IRQs.
63
@@ -XXX,XX +XXX,XX @@ uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
64
return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
18
}
65
}
19
+
66
20
+static void gen_VNMLA_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
67
+/*
68
+ * Get Combiner input GPIO into irqs structure
69
+ */
70
+static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
71
+ DeviceState *dev, int ext)
21
+{
72
+{
22
+ /* VNMLA: -fd + -(fn * fm) */
73
+ int n;
23
+ TCGv_i32 tmp = tcg_temp_new_i32();
74
+ int bit;
24
+
75
+ int max;
25
+ gen_helper_vfp_muls(tmp, vn, vm, fpst);
76
+ qemu_irq *irq;
26
+ gen_helper_vfp_negs(tmp, tmp);
77
+
27
+ gen_helper_vfp_negs(vd, vd);
78
+ max = ext ? EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ :
28
+ gen_helper_vfp_adds(vd, vd, tmp, fpst);
79
+ EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
29
+ tcg_temp_free_i32(tmp);
80
+ irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
81
+
82
+ /*
83
+ * Some IRQs of Int/External Combiner are going to two Combiners groups,
84
+ * so let split them.
85
+ */
86
+ for (n = 0; n < max; n++) {
87
+
88
+ bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
89
+
90
+ switch (n) {
91
+ /* MDNIE_LCD1 INTG1 */
92
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 0) ...
93
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 3):
94
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
95
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(0, bit + 4)]);
96
+ continue;
97
+
98
+ /* TMU INTG3 */
99
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(3, 4):
100
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
101
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(2, bit)]);
102
+ continue;
103
+
104
+ /* LCD1 INTG12 */
105
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 0) ...
106
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 3):
107
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
108
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(11, bit + 4)]);
109
+ continue;
110
+
111
+ /* Multi-Core Timer INTG12 */
112
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4) ...
113
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 8):
114
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
115
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
116
+ continue;
117
+
118
+ /* Multi-Core Timer INTG35 */
119
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 4) ...
120
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 8):
121
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
122
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
123
+ continue;
124
+
125
+ /* Multi-Core Timer INTG51 */
126
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 4) ...
127
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 8):
128
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
129
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
130
+ continue;
131
+
132
+ /* Multi-Core Timer INTG53 */
133
+ case EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 4) ...
134
+ EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 8):
135
+ irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
136
+ irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
137
+ continue;
138
+ }
139
+
140
+ irq[n] = qdev_get_gpio_in(dev, n);
141
+ }
30
+}
142
+}
31
+
143
+
32
+static bool trans_VNMLA_sp(DisasContext *s, arg_VNMLA_sp *a)
144
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
33
+{
145
0x09, 0x00, 0x00, 0x00 };
34
+ return do_vfp_3op_sp(s, gen_VNMLA_sp, a->vd, a->vn, a->vm, true);
146
35
+}
147
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
36
+
37
+static void gen_VNMLA_dp(TCGv_i64 vd, TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst)
38
+{
39
+ /* VNMLA: -fd + (fn * fm) */
40
+ TCGv_i64 tmp = tcg_temp_new_i64();
41
+
42
+ gen_helper_vfp_muld(tmp, vn, vm, fpst);
43
+ gen_helper_vfp_negd(tmp, tmp);
44
+ gen_helper_vfp_negd(vd, vd);
45
+ gen_helper_vfp_addd(vd, vd, tmp, fpst);
46
+ tcg_temp_free_i64(tmp);
47
+}
48
+
49
+static bool trans_VNMLA_dp(DisasContext *s, arg_VNMLA_sp *a)
50
+{
51
+ return do_vfp_3op_dp(s, gen_VNMLA_dp, a->vd, a->vn, a->vm, true);
52
+}
53
diff --git a/target/arm/translate.c b/target/arm/translate.c
54
index XXXXXXX..XXXXXXX 100644
148
index XXXXXXX..XXXXXXX 100644
55
--- a/target/arm/translate.c
149
--- a/hw/intc/exynos4210_combiner.c
56
+++ b/target/arm/translate.c
150
+++ b/hw/intc/exynos4210_combiner.c
57
@@ -XXX,XX +XXX,XX @@ VFP_OP2(div)
151
@@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_exynos4210_combiner = {
58
152
}
59
#undef VFP_OP2
153
};
60
154
61
-static inline void gen_vfp_F1_neg(int dp)
155
-/*
156
- * Get Combiner input GPIO into irqs structure
157
- */
158
-void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs, DeviceState *dev,
159
- int ext)
62
-{
160
-{
63
- /* Like gen_vfp_neg() but put result in F1 */
161
- int n;
64
- if (dp) {
162
- int bit;
65
- gen_helper_vfp_negd(cpu_F1d, cpu_F0d);
163
- int max;
66
- } else {
164
- qemu_irq *irq;
67
- gen_helper_vfp_negs(cpu_F1s, cpu_F0s);
165
-
166
- max = ext ? EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ :
167
- EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
168
- irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
169
-
170
- /*
171
- * Some IRQs of Int/External Combiner are going to two Combiners groups,
172
- * so let split them.
173
- */
174
- for (n = 0; n < max; n++) {
175
-
176
- bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
177
-
178
- switch (n) {
179
- /* MDNIE_LCD1 INTG1 */
180
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 0) ...
181
- EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 3):
182
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
183
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(0, bit + 4)]);
184
- continue;
185
-
186
- /* TMU INTG3 */
187
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(3, 4):
188
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
189
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(2, bit)]);
190
- continue;
191
-
192
- /* LCD1 INTG12 */
193
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 0) ...
194
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 3):
195
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
196
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(11, bit + 4)]);
197
- continue;
198
-
199
- /* Multi-Core Timer INTG12 */
200
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4) ...
201
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 8):
202
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
203
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
204
- continue;
205
-
206
- /* Multi-Core Timer INTG35 */
207
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 4) ...
208
- EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 8):
209
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
210
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
211
- continue;
212
-
213
- /* Multi-Core Timer INTG51 */
214
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 4) ...
215
- EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 8):
216
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
217
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
218
- continue;
219
-
220
- /* Multi-Core Timer INTG53 */
221
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 4) ...
222
- EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 8):
223
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
224
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
225
- continue;
226
- }
227
-
228
- irq[n] = qdev_get_gpio_in(dev, n);
68
- }
229
- }
69
-}
230
-}
70
-
231
-
71
static inline void gen_vfp_abs(int dp)
232
static uint64_t
233
exynos4210_combiner_read(void *opaque, hwaddr offset, unsigned size)
72
{
234
{
73
if (dp)
74
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
75
rn = VFP_SREG_N(insn);
76
77
switch (op) {
78
- case 0 ... 2:
79
+ case 0 ... 3:
80
/* Already handled by decodetree */
81
return 1;
82
default:
83
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
84
for (;;) {
85
/* Perform the calculation. */
86
switch (op) {
87
- case 3: /* VNMLA: -fd + -(fn * fm) */
88
- gen_vfp_mul(dp);
89
- gen_vfp_F1_neg(dp);
90
- gen_mov_F0_vreg(dp, rd);
91
- gen_vfp_neg(dp);
92
- gen_vfp_add(dp);
93
- break;
94
case 4: /* mul: fn * fm */
95
gen_vfp_mul(dp);
96
break;
97
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
98
index XXXXXXX..XXXXXXX 100644
99
--- a/target/arm/vfp.decode
100
+++ b/target/arm/vfp.decode
101
@@ -XXX,XX +XXX,XX @@ VNMLS_sp ---- 1110 0.01 .... .... 1010 .0.0 .... \
102
vm=%vm_sp vn=%vn_sp vd=%vd_sp
103
VNMLS_dp ---- 1110 0.01 .... .... 1011 .0.0 .... \
104
vm=%vm_dp vn=%vn_dp vd=%vd_dp
105
+
106
+VNMLA_sp ---- 1110 0.01 .... .... 1010 .1.0 .... \
107
+ vm=%vm_sp vn=%vn_sp vd=%vd_sp
108
+VNMLA_dp ---- 1110 0.01 .... .... 1011 .1.0 .... \
109
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
110
--
235
--
111
2.20.1
236
2.25.1
112
113
diff view generated by jsdifflib
1
Convert the VCVT double/single precision conversion insns to decodetree.
1
Delete a couple of #defines which are never used.
2
2
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Message-id: 20220404154658.565020-12-peter.maydell@linaro.org
5
---
6
---
6
target/arm/translate-vfp.inc.c | 48 ++++++++++++++++++++++++++++++++++
7
include/hw/arm/exynos4210.h | 4 ----
7
target/arm/translate.c | 13 +--------
8
1 file changed, 4 deletions(-)
8
target/arm/vfp.decode | 6 +++++
9
3 files changed, 55 insertions(+), 12 deletions(-)
10
9
11
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
10
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
12
index XXXXXXX..XXXXXXX 100644
11
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-vfp.inc.c
12
--- a/include/hw/arm/exynos4210.h
14
+++ b/target/arm/translate-vfp.inc.c
13
+++ b/include/hw/arm/exynos4210.h
15
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINTX_dp(DisasContext *s, arg_VRINTX_dp *a)
14
@@ -XXX,XX +XXX,XX @@
16
tcg_temp_free_i64(tmp);
15
#define EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ \
17
return true;
16
(EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ * 8)
18
}
17
19
+
18
-/* IRQs number for external and internal GIC */
20
+static bool trans_VCVT_sp(DisasContext *s, arg_VCVT_sp *a)
19
-#define EXYNOS4210_EXT_GIC_NIRQ (160-32)
21
+{
20
-#define EXYNOS4210_INT_GIC_NIRQ 64
22
+ TCGv_i64 vd;
23
+ TCGv_i32 vm;
24
+
25
+ /* UNDEF accesses to D16-D31 if they don't exist. */
26
+ if (!dc_isar_feature(aa32_fp_d32, s) && (a->vd & 0x10)) {
27
+ return false;
28
+ }
29
+
30
+ if (!vfp_access_check(s)) {
31
+ return true;
32
+ }
33
+
34
+ vm = tcg_temp_new_i32();
35
+ vd = tcg_temp_new_i64();
36
+ neon_load_reg32(vm, a->vm);
37
+ gen_helper_vfp_fcvtds(vd, vm, cpu_env);
38
+ neon_store_reg64(vd, a->vd);
39
+ tcg_temp_free_i32(vm);
40
+ tcg_temp_free_i64(vd);
41
+ return true;
42
+}
43
+
44
+static bool trans_VCVT_dp(DisasContext *s, arg_VCVT_dp *a)
45
+{
46
+ TCGv_i64 vm;
47
+ TCGv_i32 vd;
48
+
49
+ /* UNDEF accesses to D16-D31 if they don't exist. */
50
+ if (!dc_isar_feature(aa32_fp_d32, s) && (a->vm & 0x10)) {
51
+ return false;
52
+ }
53
+
54
+ if (!vfp_access_check(s)) {
55
+ return true;
56
+ }
57
+
58
+ vd = tcg_temp_new_i32();
59
+ vm = tcg_temp_new_i64();
60
+ neon_load_reg64(vm, a->vm);
61
+ gen_helper_vfp_fcvtsd(vd, vm, cpu_env);
62
+ neon_store_reg32(vd, a->vd);
63
+ tcg_temp_free_i32(vd);
64
+ tcg_temp_free_i64(vm);
65
+ return true;
66
+}
67
diff --git a/target/arm/translate.c b/target/arm/translate.c
68
index XXXXXXX..XXXXXXX 100644
69
--- a/target/arm/translate.c
70
+++ b/target/arm/translate.c
71
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
72
return 1;
73
case 15:
74
switch (rn) {
75
- case 0 ... 14:
76
+ case 0 ... 15:
77
/* Already handled by decodetree */
78
return 1;
79
default:
80
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
81
if (op == 15) {
82
/* rn is opcode, encoded as per VFP_SREG_N. */
83
switch (rn) {
84
- case 0x0f: /* vcvt double<->single */
85
- rd_is_dp = !dp;
86
- break;
87
-
21
-
88
case 0x10: /* vcvt.fxx.u32 */
22
#define EXYNOS4210_I2C_NUMBER 9
89
case 0x11: /* vcvt.fxx.s32 */
23
90
rm_is_dp = false;
24
#define EXYNOS4210_NUM_DMA 3
91
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
92
switch (op) {
93
case 15: /* extension space */
94
switch (rn) {
95
- case 15: /* single<->double conversion */
96
- if (dp) {
97
- gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
98
- } else {
99
- gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
100
- }
101
- break;
102
case 16: /* fuito */
103
gen_vfp_uito(dp, 0);
104
break;
105
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
106
index XXXXXXX..XXXXXXX 100644
107
--- a/target/arm/vfp.decode
108
+++ b/target/arm/vfp.decode
109
@@ -XXX,XX +XXX,XX @@ VRINTX_sp ---- 1110 1.11 0111 .... 1010 01.0 .... \
110
vd=%vd_sp vm=%vm_sp
111
VRINTX_dp ---- 1110 1.11 0111 .... 1011 01.0 .... \
112
vd=%vd_dp vm=%vm_dp
113
+
114
+# VCVT between single and double: Vm precision depends on size; Vd is its reverse
115
+VCVT_sp ---- 1110 1.11 0111 .... 1010 11.0 .... \
116
+ vd=%vd_dp vm=%vm_sp
117
+VCVT_dp ---- 1110 1.11 0111 .... 1011 11.0 .... \
118
+ vd=%vd_sp vm=%vm_dp
119
--
25
--
120
2.20.1
26
2.25.1
121
122
diff view generated by jsdifflib
1
For VFP short vectors, the VFP registers are divided into a
1
In exynos4210_init_board_irqs(), use the TYPE_SPLIT_IRQ device
2
series of banks: for single-precision these are s0-s7, s8-s15,
2
instead of qemu_irq_split().
3
s16-s23 and s24-s31; for double-precision they are d0-d3,
4
d4-d7, ... d28-d31. Some banks are "scalar" meaning that
5
use of a register within them triggers a pure-scalar or
6
mixed vector-scalar operation rather than a full vector
7
operation. The scalar banks are s0-s7, d0-d3 and d16-d19.
8
When using a bank as part of a vector operation, we
9
iterate through it, increasing the register number by
10
the specified stride each time, and wrapping around to
11
the beginning of the bank.
12
13
Unfortunately our calculation of the "increment" part of this
14
was incorrect:
15
vd = ((vd + delta_d) & (bank_mask - 1)) | (vd & bank_mask)
16
will only do the intended thing if bank_mask has exactly
17
one set high bit. For instance for doubles (bank_mask = 0xc),
18
if we start with vd = 6 and delta_d = 2 then vd is updated
19
to 12 rather than the intended 4.
20
21
This only causes problems in the unlikely case that the
22
starting register is not the first in its bank: if the
23
register number doesn't have to wrap around then the
24
expression happens to give the right answer.
25
26
Fix this bug by abstracting out the "check whether register
27
is in a scalar bank" and "advance register within bank"
28
operations to utility functions which use the right
29
bit masking operations.
30
3
31
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
32
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Message-id: 20220404154658.565020-13-peter.maydell@linaro.org
33
---
7
---
34
target/arm/translate-vfp.inc.c | 100 ++++++++++++++++++++-------------
8
include/hw/arm/exynos4210.h | 9 ++++++++
35
1 file changed, 60 insertions(+), 40 deletions(-)
9
hw/arm/exynos4210.c | 41 +++++++++++++++++++++++++++++--------
10
2 files changed, 42 insertions(+), 8 deletions(-)
36
11
37
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
12
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
38
index XXXXXXX..XXXXXXX 100644
13
index XXXXXXX..XXXXXXX 100644
39
--- a/target/arm/translate-vfp.inc.c
14
--- a/include/hw/arm/exynos4210.h
40
+++ b/target/arm/translate-vfp.inc.c
15
+++ b/include/hw/arm/exynos4210.h
41
@@ -XXX,XX +XXX,XX @@ typedef void VFPGen3OpDPFn(TCGv_i64 vd,
16
@@ -XXX,XX +XXX,XX @@
42
typedef void VFPGen2OpSPFn(TCGv_i32 vd, TCGv_i32 vm);
17
#include "hw/sysbus.h"
43
typedef void VFPGen2OpDPFn(TCGv_i64 vd, TCGv_i64 vm);
18
#include "hw/cpu/a9mpcore.h"
19
#include "hw/intc/exynos4210_gic.h"
20
+#include "hw/core/split-irq.h"
21
#include "target/arm/cpu-qom.h"
22
#include "qom/object.h"
23
24
@@ -XXX,XX +XXX,XX @@
25
26
#define EXYNOS4210_NUM_DMA 3
44
27
45
+/*
28
+/*
46
+ * Return true if the specified S reg is in a scalar bank
29
+ * We need one splitter for every external combiner input, plus
47
+ * (ie if it is s0..s7)
30
+ * one for every non-zero entry in combiner_grp_to_gic_id[].
31
+ * We'll assert in exynos4210_init_board_irqs() if this is wrong.
48
+ */
32
+ */
49
+static inline bool vfp_sreg_is_scalar(int reg)
33
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 60)
50
+{
51
+ return (reg & 0x18) == 0;
52
+}
53
+
34
+
54
+/*
35
typedef struct Exynos4210Irq {
55
+ * Return true if the specified D reg is in a scalar bank
36
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
56
+ * (ie if it is d0..d3 or d16..d19)
37
qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
57
+ */
38
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
58
+static inline bool vfp_dreg_is_scalar(int reg)
39
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
59
+{
40
A9MPPrivState a9mpcore;
60
+ return (reg & 0xc) == 0;
41
Exynos4210GicState ext_gic;
61
+}
42
+ SplitIRQ splitter[EXYNOS4210_NUM_SPLITTERS];
43
};
44
45
#define TYPE_EXYNOS4210_SOC "exynos4210"
46
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
47
index XXXXXXX..XXXXXXX 100644
48
--- a/hw/arm/exynos4210.c
49
+++ b/hw/arm/exynos4210.c
50
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
51
uint32_t grp, bit, irq_id, n;
52
Exynos4210Irq *is = &s->irqs;
53
DeviceState *extgicdev = DEVICE(&s->ext_gic);
54
+ int splitcount = 0;
55
+ DeviceState *splitter;
56
57
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
58
irq_id = 0;
59
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
60
/* MCT_G1 is passed to External and GIC */
61
irq_id = EXT_GIC_ID_MCT_G1;
62
}
62
+
63
+
63
+/*
64
+ assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
64
+ * Advance the S reg number forwards by delta within its bank
65
+ splitter = DEVICE(&s->splitter[splitcount]);
65
+ * (ie increment the low 3 bits but leave the rest the same)
66
+ qdev_prop_set_uint16(splitter, "num-lines", 2);
66
+ */
67
+ qdev_realize(splitter, NULL, &error_abort);
67
+static inline int vfp_advance_sreg(int reg, int delta)
68
+ splitcount++;
68
+{
69
+ s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
69
+ return ((reg + delta) & 0x7) | (reg & ~0x7);
70
+ qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
70
+}
71
if (irq_id) {
71
+
72
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
72
+/*
73
- qdev_get_gpio_in(extgicdev,
73
+ * Advance the D reg number forwards by delta within its bank
74
- irq_id - 32));
74
+ * (ie increment the low 2 bits but leave the rest the same)
75
+ qdev_connect_gpio_out(splitter, 1,
75
+ */
76
+ qdev_get_gpio_in(extgicdev, irq_id - 32));
76
+static inline int vfp_advance_dreg(int reg, int delta)
77
+{
78
+ return ((reg + delta) & 0x3) | (reg & ~0x3);
79
+}
80
+
81
/*
82
* Perform a 3-operand VFP data processing instruction. fn is the
83
* callback to do the actual operation; this function deals with the
84
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_sp(DisasContext *s, VFPGen3OpSPFn *fn,
85
{
86
uint32_t delta_m = 0;
87
uint32_t delta_d = 0;
88
- uint32_t bank_mask = 0;
89
int veclen = s->vec_len;
90
TCGv_i32 f0, f1, fd;
91
TCGv_ptr fpst;
92
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_sp(DisasContext *s, VFPGen3OpSPFn *fn,
93
}
94
95
if (veclen > 0) {
96
- bank_mask = 0x18;
97
-
98
/* Figure out what type of vector operation this is. */
99
- if ((vd & bank_mask) == 0) {
100
+ if (vfp_sreg_is_scalar(vd)) {
101
/* scalar */
102
veclen = 0;
103
} else {
77
} else {
104
delta_d = s->vec_stride + 1;
78
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
105
79
- is->ext_combiner_irq[n]);
106
- if ((vm & bank_mask) == 0) {
80
+ qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
107
+ if (vfp_sreg_is_scalar(vm)) {
108
/* mixed scalar/vector */
109
delta_m = 0;
110
} else {
111
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_sp(DisasContext *s, VFPGen3OpSPFn *fn,
112
113
/* Set up the operands for the next iteration */
114
veclen--;
115
- vd = ((vd + delta_d) & (bank_mask - 1)) | (vd & bank_mask);
116
- vn = ((vn + delta_d) & (bank_mask - 1)) | (vn & bank_mask);
117
+ vd = vfp_advance_sreg(vd, delta_d);
118
+ vn = vfp_advance_sreg(vn, delta_d);
119
neon_load_reg32(f0, vn);
120
if (delta_m) {
121
- vm = ((vm + delta_m) & (bank_mask - 1)) | (vm & bank_mask);
122
+ vm = vfp_advance_sreg(vm, delta_m);
123
neon_load_reg32(f1, vm);
124
}
81
}
125
}
82
}
126
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn,
83
for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
127
{
84
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
128
uint32_t delta_m = 0;
85
EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
129
uint32_t delta_d = 0;
86
130
- uint32_t bank_mask = 0;
87
if (irq_id) {
131
int veclen = s->vec_len;
88
- s->irq_table[n] = qemu_irq_split(is->int_combiner_irq[n],
132
TCGv_i64 f0, f1, fd;
89
- qdev_get_gpio_in(extgicdev,
133
TCGv_ptr fpst;
90
- irq_id - 32));
134
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn,
91
+ assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
135
}
92
+ splitter = DEVICE(&s->splitter[splitcount]);
136
93
+ qdev_prop_set_uint16(splitter, "num-lines", 2);
137
if (veclen > 0) {
94
+ qdev_realize(splitter, NULL, &error_abort);
138
- bank_mask = 0xc;
95
+ splitcount++;
139
-
96
+ s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
140
/* Figure out what type of vector operation this is. */
97
+ qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
141
- if ((vd & bank_mask) == 0) {
98
+ qdev_connect_gpio_out(splitter, 1,
142
+ if (vfp_dreg_is_scalar(vd)) {
99
+ qdev_get_gpio_in(extgicdev, irq_id - 32));
143
/* scalar */
144
veclen = 0;
145
} else {
146
delta_d = (s->vec_stride >> 1) + 1;
147
148
- if ((vm & bank_mask) == 0) {
149
+ if (vfp_dreg_is_scalar(vm)) {
150
/* mixed scalar/vector */
151
delta_m = 0;
152
} else {
153
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn,
154
}
155
/* Set up the operands for the next iteration */
156
veclen--;
157
- vd = ((vd + delta_d) & (bank_mask - 1)) | (vd & bank_mask);
158
- vn = ((vn + delta_d) & (bank_mask - 1)) | (vn & bank_mask);
159
+ vd = vfp_advance_dreg(vd, delta_d);
160
+ vn = vfp_advance_dreg(vn, delta_d);
161
neon_load_reg64(f0, vn);
162
if (delta_m) {
163
- vm = ((vm + delta_m) & (bank_mask - 1)) | (vm & bank_mask);
164
+ vm = vfp_advance_dreg(vm, delta_m);
165
neon_load_reg64(f1, vm);
166
}
100
}
167
}
101
}
168
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_sp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm)
102
+ /*
169
{
103
+ * We check this here to avoid a more obscure assert later when
170
uint32_t delta_m = 0;
104
+ * qdev_assert_realized_properly() checks that we realized every
171
uint32_t delta_d = 0;
105
+ * child object we initialized.
172
- uint32_t bank_mask = 0;
106
+ */
173
int veclen = s->vec_len;
107
+ assert(splitcount == EXYNOS4210_NUM_SPLITTERS);
174
TCGv_i32 f0, fd;
108
}
175
109
176
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_sp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm)
110
/*
111
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
112
object_initialize_child(obj, name, &s->cpu_irq_orgate[i], TYPE_OR_IRQ);
177
}
113
}
178
114
179
if (veclen > 0) {
115
+ for (i = 0; i < ARRAY_SIZE(s->splitter); i++) {
180
- bank_mask = 0x18;
116
+ g_autofree char *name = g_strdup_printf("irq-splitter%d", i);
181
-
117
+ object_initialize_child(obj, name, &s->splitter[i], TYPE_SPLIT_IRQ);
182
/* Figure out what type of vector operation this is. */
118
+ }
183
- if ((vd & bank_mask) == 0) {
119
+
184
+ if (vfp_sreg_is_scalar(vd)) {
120
object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
185
/* scalar */
121
object_initialize_child(obj, "ext-gic", &s->ext_gic, TYPE_EXYNOS4210_GIC);
186
veclen = 0;
122
}
187
} else {
188
delta_d = s->vec_stride + 1;
189
190
- if ((vm & bank_mask) == 0) {
191
+ if (vfp_sreg_is_scalar(vm)) {
192
/* mixed scalar/vector */
193
delta_m = 0;
194
} else {
195
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_sp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm)
196
if (delta_m == 0) {
197
/* single source one-many */
198
while (veclen--) {
199
- vd = ((vd + delta_d) & (bank_mask - 1)) | (vd & bank_mask);
200
+ vd = vfp_advance_sreg(vd, delta_d);
201
neon_store_reg32(fd, vd);
202
}
203
break;
204
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_sp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm)
205
206
/* Set up the operands for the next iteration */
207
veclen--;
208
- vd = ((vd + delta_d) & (bank_mask - 1)) | (vd & bank_mask);
209
- vm = ((vm + delta_m) & (bank_mask - 1)) | (vm & bank_mask);
210
+ vd = vfp_advance_sreg(vd, delta_d);
211
+ vm = vfp_advance_sreg(vm, delta_m);
212
neon_load_reg32(f0, vm);
213
}
214
215
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm)
216
{
217
uint32_t delta_m = 0;
218
uint32_t delta_d = 0;
219
- uint32_t bank_mask = 0;
220
int veclen = s->vec_len;
221
TCGv_i64 f0, fd;
222
223
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm)
224
}
225
226
if (veclen > 0) {
227
- bank_mask = 0xc;
228
-
229
/* Figure out what type of vector operation this is. */
230
- if ((vd & bank_mask) == 0) {
231
+ if (vfp_dreg_is_scalar(vd)) {
232
/* scalar */
233
veclen = 0;
234
} else {
235
delta_d = (s->vec_stride >> 1) + 1;
236
237
- if ((vm & bank_mask) == 0) {
238
+ if (vfp_dreg_is_scalar(vm)) {
239
/* mixed scalar/vector */
240
delta_m = 0;
241
} else {
242
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm)
243
if (delta_m == 0) {
244
/* single source one-many */
245
while (veclen--) {
246
- vd = ((vd + delta_d) & (bank_mask - 1)) | (vd & bank_mask);
247
+ vd = vfp_advance_dreg(vd, delta_d);
248
neon_store_reg64(fd, vd);
249
}
250
break;
251
@@ -XXX,XX +XXX,XX @@ static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm)
252
253
/* Set up the operands for the next iteration */
254
veclen--;
255
- vd = ((vd + delta_d) & (bank_mask - 1)) | (vd & bank_mask);
256
- vm = ((vm + delta_m) & (bank_mask - 1)) | (vm & bank_mask);
257
+ vd = vfp_advance_dreg(vd, delta_d);
258
+ vd = vfp_advance_dreg(vm, delta_m);
259
neon_load_reg64(f0, vm);
260
}
261
262
@@ -XXX,XX +XXX,XX @@ static bool trans_VFM_dp(DisasContext *s, arg_VFM_sp *a)
263
static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a)
264
{
265
uint32_t delta_d = 0;
266
- uint32_t bank_mask = 0;
267
int veclen = s->vec_len;
268
TCGv_i32 fd;
269
uint32_t n, i, vd;
270
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a)
271
}
272
273
if (veclen > 0) {
274
- bank_mask = 0x18;
275
/* Figure out what type of vector operation this is. */
276
- if ((vd & bank_mask) == 0) {
277
+ if (vfp_sreg_is_scalar(vd)) {
278
/* scalar */
279
veclen = 0;
280
} else {
281
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a)
282
283
/* Set up the operands for the next iteration */
284
veclen--;
285
- vd = ((vd + delta_d) & (bank_mask - 1)) | (vd & bank_mask);
286
+ vd = vfp_advance_sreg(vd, delta_d);
287
}
288
289
tcg_temp_free_i32(fd);
290
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a)
291
static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
292
{
293
uint32_t delta_d = 0;
294
- uint32_t bank_mask = 0;
295
int veclen = s->vec_len;
296
TCGv_i64 fd;
297
uint32_t n, i, vd;
298
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
299
}
300
301
if (veclen > 0) {
302
- bank_mask = 0xc;
303
/* Figure out what type of vector operation this is. */
304
- if ((vd & bank_mask) == 0) {
305
+ if (vfp_dreg_is_scalar(vd)) {
306
/* scalar */
307
veclen = 0;
308
} else {
309
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
310
311
/* Set up the operands for the next iteration */
312
veclen--;
313
- vd = ((vd + delta_d) & (bank_mask - 1)) | (vd & bank_mask);
314
+ vfp_advance_dreg(vd, delta_d);
315
}
316
317
tcg_temp_free_i64(fd);
318
--
123
--
319
2.20.1
124
2.25.1
320
321
diff view generated by jsdifflib
1
The Cortex-R5F initfn was not correctly setting up the MVFR
1
In exynos4210_init_board_irqs(), the loop that handles IRQ lines that
2
ID register values. Fill these in, since some subsequent patches
2
are in a range that applies to the internal combiner only creates a
3
will use ID register checks rather than CPU feature bit checks.
3
splitter for those interrupts which go to both the internal combiner
4
and to the external GIC, but it does nothing at all for the
5
interrupts which don't go to the external GIC, leaving the
6
irq_table[] array element empty for those. (This will result in
7
those interrupts simply being lost, not in a QEMU crash.)
8
9
I don't have a reliable datasheet for this SoC, but since we do wire
10
up one interrupt line in this category (the HDMI I2C device on
11
interrupt 16,1), this seems like it must be a bug in the existing
12
QEMU code. Fill in the irq_table[] entries where we're not splitting
13
the IRQ to both the internal combiner and the external GIC with the
14
IRQ line of the internal combiner. (That is, these IRQ lines go to
15
just one device, not multiple.)
16
17
This bug didn't have any visible guest effects because the only
18
implemented device that was affected was the HDMI I2C controller,
19
and we never connect any I2C devices to that bus.
4
20
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
21
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
22
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
23
Message-id: 20220404154658.565020-14-peter.maydell@linaro.org
7
---
24
---
8
target/arm/cpu.c | 2 ++
25
hw/arm/exynos4210.c | 2 ++
9
1 file changed, 2 insertions(+)
26
1 file changed, 2 insertions(+)
10
27
11
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
28
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
12
index XXXXXXX..XXXXXXX 100644
29
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/cpu.c
30
--- a/hw/arm/exynos4210.c
14
+++ b/target/arm/cpu.c
31
+++ b/hw/arm/exynos4210.c
15
@@ -XXX,XX +XXX,XX @@ static void cortex_r5f_initfn(Object *obj)
32
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
16
33
qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
17
cortex_r5_initfn(obj);
34
qdev_connect_gpio_out(splitter, 1,
18
set_feature(&cpu->env, ARM_FEATURE_VFP3);
35
qdev_get_gpio_in(extgicdev, irq_id - 32));
19
+ cpu->isar.mvfr0 = 0x10110221;
36
+ } else {
20
+ cpu->isar.mvfr1 = 0x00000011;
37
+ s->irq_table[n] = is->int_combiner_irq[n];
21
}
38
}
22
39
}
23
static const ARMCPRegInfo cortexa8_cp_reginfo[] = {
40
/*
24
--
41
--
25
2.20.1
42
2.25.1
26
27
diff view generated by jsdifflib
1
Factor out the VFP access checking code so that we can use it in the
1
Currently for the interrupts MCT_G0 and MCT_G1 which are
2
leaf functions of the decodetree decoder.
2
the only ones in the input range of the external combiner
3
and which are also wired to the external GIC, we connect
4
them only to the internal combiner and the external GIC.
5
This seems likely to be a bug, as all other interrupts
6
which are in the input range of both combiners are
7
connected to both combiners. (The fact that the code in
8
exynos4210_combiner_get_gpioin() is also trying to wire
9
up these inputs on both combiners also suggests this.)
3
10
4
We call the function full_vfp_access_check() so we can keep
11
Wire these interrupts up to both combiners, like the rest.
5
the more natural vfp_access_check() for a version which doesn't
6
have the 'ignore_vfp_enabled' flag -- that way almost all VFP
7
insns will be able to use vfp_access_check(s) and only the
8
special-register access function will have to use
9
full_vfp_access_check(s, ignore_vfp_enabled).
10
12
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20220404154658.565020-15-peter.maydell@linaro.org
13
---
16
---
14
target/arm/translate-vfp.inc.c | 100 ++++++++++++++++++++++++++++++++
17
hw/arm/exynos4210.c | 7 +++----
15
target/arm/translate.c | 101 +++++----------------------------
18
1 file changed, 3 insertions(+), 4 deletions(-)
16
2 files changed, 113 insertions(+), 88 deletions(-)
17
19
18
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
20
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
19
index XXXXXXX..XXXXXXX 100644
21
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/translate-vfp.inc.c
22
--- a/hw/arm/exynos4210.c
21
+++ b/target/arm/translate-vfp.inc.c
23
+++ b/hw/arm/exynos4210.c
22
@@ -XXX,XX +XXX,XX @@
24
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
23
/* Include the generated VFP decoder */
25
24
#include "decode-vfp.inc.c"
26
assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
25
#include "decode-vfp-uncond.inc.c"
27
splitter = DEVICE(&s->splitter[splitcount]);
26
+
28
- qdev_prop_set_uint16(splitter, "num-lines", 2);
27
+/*
29
+ qdev_prop_set_uint16(splitter, "num-lines", irq_id ? 3 : 2);
28
+ * Check that VFP access is enabled. If it is, do the necessary
30
qdev_realize(splitter, NULL, &error_abort);
29
+ * M-profile lazy-FP handling and then return true.
31
splitcount++;
30
+ * If not, emit code to generate an appropriate exception and
32
s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
31
+ * return false.
33
qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
32
+ * The ignore_vfp_enabled argument specifies that we should ignore
34
+ qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
33
+ * whether VFP is enabled via FPEXC[EN]: this should be true for FMXR/FMRX
35
if (irq_id) {
34
+ * accesses to FPSID, FPEXC, MVFR0, MVFR1, MVFR2, and false for all other insns.
36
- qdev_connect_gpio_out(splitter, 1,
35
+ */
37
+ qdev_connect_gpio_out(splitter, 2,
36
+static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
38
qdev_get_gpio_in(extgicdev, irq_id - 32));
37
+{
39
- } else {
38
+ if (s->fp_excp_el) {
40
- qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
39
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
40
+ gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
41
+ s->fp_excp_el);
42
+ } else {
43
+ gen_exception_insn(s, 4, EXCP_UDEF,
44
+ syn_fp_access_trap(1, 0xe, false),
45
+ s->fp_excp_el);
46
+ }
47
+ return false;
48
+ }
49
+
50
+ if (!s->vfp_enabled && !ignore_vfp_enabled) {
51
+ assert(!arm_dc_feature(s, ARM_FEATURE_M));
52
+ gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
53
+ default_exception_el(s));
54
+ return false;
55
+ }
56
+
57
+ if (arm_dc_feature(s, ARM_FEATURE_M)) {
58
+ /* Handle M-profile lazy FP state mechanics */
59
+
60
+ /* Trigger lazy-state preservation if necessary */
61
+ if (s->v7m_lspact) {
62
+ /*
63
+ * Lazy state saving affects external memory and also the NVIC,
64
+ * so we must mark it as an IO operation for icount.
65
+ */
66
+ if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
67
+ gen_io_start();
68
+ }
69
+ gen_helper_v7m_preserve_fp_state(cpu_env);
70
+ if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
71
+ gen_io_end();
72
+ }
73
+ /*
74
+ * If the preserve_fp_state helper doesn't throw an exception
75
+ * then it will clear LSPACT; we don't need to repeat this for
76
+ * any further FP insns in this TB.
77
+ */
78
+ s->v7m_lspact = false;
79
+ }
80
+
81
+ /* Update ownership of FP context: set FPCCR.S to match current state */
82
+ if (s->v8m_fpccr_s_wrong) {
83
+ TCGv_i32 tmp;
84
+
85
+ tmp = load_cpu_field(v7m.fpccr[M_REG_S]);
86
+ if (s->v8m_secure) {
87
+ tcg_gen_ori_i32(tmp, tmp, R_V7M_FPCCR_S_MASK);
88
+ } else {
89
+ tcg_gen_andi_i32(tmp, tmp, ~R_V7M_FPCCR_S_MASK);
90
+ }
91
+ store_cpu_field(tmp, v7m.fpccr[M_REG_S]);
92
+ /* Don't need to do this for any further FP insns in this TB */
93
+ s->v8m_fpccr_s_wrong = false;
94
+ }
95
+
96
+ if (s->v7m_new_fp_ctxt_needed) {
97
+ /*
98
+ * Create new FP context by updating CONTROL.FPCA, CONTROL.SFPA
99
+ * and the FPSCR.
100
+ */
101
+ TCGv_i32 control, fpscr;
102
+ uint32_t bits = R_V7M_CONTROL_FPCA_MASK;
103
+
104
+ fpscr = load_cpu_field(v7m.fpdscr[s->v8m_secure]);
105
+ gen_helper_vfp_set_fpscr(cpu_env, fpscr);
106
+ tcg_temp_free_i32(fpscr);
107
+ /*
108
+ * We don't need to arrange to end the TB, because the only
109
+ * parts of FPSCR which we cache in the TB flags are the VECLEN
110
+ * and VECSTRIDE, and those don't exist for M-profile.
111
+ */
112
+
113
+ if (s->v8m_secure) {
114
+ bits |= R_V7M_CONTROL_SFPA_MASK;
115
+ }
116
+ control = load_cpu_field(v7m.control[M_REG_S]);
117
+ tcg_gen_ori_i32(control, control, bits);
118
+ store_cpu_field(control, v7m.control[M_REG_S]);
119
+ /* Don't need to do this for any further FP insns in this TB */
120
+ s->v7m_new_fp_ctxt_needed = false;
121
+ }
122
+ }
123
+
124
+ return true;
125
+}
126
diff --git a/target/arm/translate.c b/target/arm/translate.c
127
index XXXXXXX..XXXXXXX 100644
128
--- a/target/arm/translate.c
129
+++ b/target/arm/translate.c
130
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_misc_insn(DisasContext *s, uint32_t insn)
131
return 1;
132
}
133
134
-/* Disassemble a VFP instruction. Returns nonzero if an error occurred
135
- (ie. an undefined instruction). */
136
+/*
137
+ * Disassemble a VFP instruction. Returns nonzero if an error occurred
138
+ * (ie. an undefined instruction).
139
+ */
140
static int disas_vfp_insn(DisasContext *s, uint32_t insn)
141
{
142
uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
143
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
144
TCGv_i32 addr;
145
TCGv_i32 tmp;
146
TCGv_i32 tmp2;
147
+ bool ignore_vfp_enabled = false;
148
149
if (!arm_dc_feature(s, ARM_FEATURE_VFP)) {
150
return 1;
151
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
152
}
41
}
153
}
42
}
154
43
for (; n < EXYNOS4210_MAX_INT_COMBINER_IN_IRQ; n++) {
155
- /* FIXME: this access check should not take precedence over UNDEF
156
+ /*
157
+ * FIXME: this access check should not take precedence over UNDEF
158
* for invalid encodings; we will generate incorrect syndrome information
159
* for attempts to execute invalid vfp/neon encodings with FP disabled.
160
*/
161
- if (s->fp_excp_el) {
162
- if (arm_dc_feature(s, ARM_FEATURE_M)) {
163
- gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(),
164
- s->fp_excp_el);
165
- } else {
166
- gen_exception_insn(s, 4, EXCP_UDEF,
167
- syn_fp_access_trap(1, 0xe, false),
168
- s->fp_excp_el);
169
- }
170
- return 0;
171
- }
172
-
173
- if (!s->vfp_enabled) {
174
- /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
175
- if ((insn & 0x0fe00fff) != 0x0ee00a10)
176
- return 1;
177
+ if ((insn & 0x0fe00fff) == 0x0ee00a10) {
178
rn = (insn >> 16) & 0xf;
179
- if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC && rn != ARM_VFP_MVFR2
180
- && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0) {
181
- return 1;
182
+ if (rn == ARM_VFP_FPSID || rn == ARM_VFP_FPEXC || rn == ARM_VFP_MVFR2
183
+ || rn == ARM_VFP_MVFR1 || rn == ARM_VFP_MVFR0) {
184
+ ignore_vfp_enabled = true;
185
}
186
}
187
-
188
- if (arm_dc_feature(s, ARM_FEATURE_M)) {
189
- /* Handle M-profile lazy FP state mechanics */
190
-
191
- /* Trigger lazy-state preservation if necessary */
192
- if (s->v7m_lspact) {
193
- /*
194
- * Lazy state saving affects external memory and also the NVIC,
195
- * so we must mark it as an IO operation for icount.
196
- */
197
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
198
- gen_io_start();
199
- }
200
- gen_helper_v7m_preserve_fp_state(cpu_env);
201
- if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
202
- gen_io_end();
203
- }
204
- /*
205
- * If the preserve_fp_state helper doesn't throw an exception
206
- * then it will clear LSPACT; we don't need to repeat this for
207
- * any further FP insns in this TB.
208
- */
209
- s->v7m_lspact = false;
210
- }
211
-
212
- /* Update ownership of FP context: set FPCCR.S to match current state */
213
- if (s->v8m_fpccr_s_wrong) {
214
- TCGv_i32 tmp;
215
-
216
- tmp = load_cpu_field(v7m.fpccr[M_REG_S]);
217
- if (s->v8m_secure) {
218
- tcg_gen_ori_i32(tmp, tmp, R_V7M_FPCCR_S_MASK);
219
- } else {
220
- tcg_gen_andi_i32(tmp, tmp, ~R_V7M_FPCCR_S_MASK);
221
- }
222
- store_cpu_field(tmp, v7m.fpccr[M_REG_S]);
223
- /* Don't need to do this for any further FP insns in this TB */
224
- s->v8m_fpccr_s_wrong = false;
225
- }
226
-
227
- if (s->v7m_new_fp_ctxt_needed) {
228
- /*
229
- * Create new FP context by updating CONTROL.FPCA, CONTROL.SFPA
230
- * and the FPSCR.
231
- */
232
- TCGv_i32 control, fpscr;
233
- uint32_t bits = R_V7M_CONTROL_FPCA_MASK;
234
-
235
- fpscr = load_cpu_field(v7m.fpdscr[s->v8m_secure]);
236
- gen_helper_vfp_set_fpscr(cpu_env, fpscr);
237
- tcg_temp_free_i32(fpscr);
238
- /*
239
- * We don't need to arrange to end the TB, because the only
240
- * parts of FPSCR which we cache in the TB flags are the VECLEN
241
- * and VECSTRIDE, and those don't exist for M-profile.
242
- */
243
-
244
- if (s->v8m_secure) {
245
- bits |= R_V7M_CONTROL_SFPA_MASK;
246
- }
247
- control = load_cpu_field(v7m.control[M_REG_S]);
248
- tcg_gen_ori_i32(control, control, bits);
249
- store_cpu_field(control, v7m.control[M_REG_S]);
250
- /* Don't need to do this for any further FP insns in this TB */
251
- s->v7m_new_fp_ctxt_needed = false;
252
- }
253
+ if (!full_vfp_access_check(s, ignore_vfp_enabled)) {
254
+ return 0;
255
}
256
257
if (extract32(insn, 28, 4) == 0xf) {
258
--
44
--
259
2.20.1
45
2.25.1
260
261
diff view generated by jsdifflib
1
Convert the VFP round-to-integer instructions VRINTR, VRINTZ and
1
The combiner_grp_to_gic_id[] array includes the EXT_GIC_ID_MCT_G0
2
VRINTX to decodetree.
2
and EXT_GIC_ID_MCT_G1 multiple times. This means that we will
3
connect multiple IRQs up to the same external GIC input, which
4
is not permitted. We do the same thing in the code in
5
exynos4210_init_board_irqs() because the conditionals selecting
6
an irq_id in the first loop match multiple interrupt IDs.
3
7
4
These instructions were only introduced as part of the "VFP misc"
8
Overall we do this for interrupt IDs
5
additions in v8A, so we check this. The old decoder's implementation
9
(1, 4), (12, 4), (35, 4), (51, 4), (53, 4) for EXT_GIC_ID_MCT_G0
6
was incorrectly providing them even for v7A CPUs.
10
and
11
(1, 5), (12, 5), (35, 5), (51, 5), (53, 5) for EXT_GIC_ID_MCT_G1
12
13
These correspond to the cases for the multi-core timer that we are
14
wiring up to multiple inputs on the combiner in
15
exynos4210_combiner_get_gpioin(). That code already deals with all
16
these interrupt IDs being the same input source, so we don't need to
17
connect the external GIC interrupt for any of them except the first
18
(1, 4) and (1, 5). Remove the array entries and conditionals which
19
were incorrectly causing us to wire up extra lines.
20
21
This bug didn't cause any visible effects, because we only connect
22
up a device to the "primary" ID values (1, 4) and (1, 5), so the
23
extra lines would never be set to a level.
7
24
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
25
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
26
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
27
Message-id: 20220404154658.565020-16-peter.maydell@linaro.org
10
---
28
---
11
target/arm/translate-vfp.inc.c | 163 +++++++++++++++++++++++++++++++++
29
include/hw/arm/exynos4210.h | 2 +-
12
target/arm/translate.c | 45 +--------
30
hw/arm/exynos4210.c | 12 +++++-------
13
target/arm/vfp.decode | 15 +++
31
2 files changed, 6 insertions(+), 8 deletions(-)
14
3 files changed, 179 insertions(+), 44 deletions(-)
15
32
16
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
33
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
17
index XXXXXXX..XXXXXXX 100644
34
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate-vfp.inc.c
35
--- a/include/hw/arm/exynos4210.h
19
+++ b/target/arm/translate-vfp.inc.c
36
+++ b/include/hw/arm/exynos4210.h
20
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a)
37
@@ -XXX,XX +XXX,XX @@
21
tcg_temp_free_i32(tmp);
38
* one for every non-zero entry in combiner_grp_to_gic_id[].
22
return true;
39
* We'll assert in exynos4210_init_board_irqs() if this is wrong.
23
}
40
*/
24
+
41
-#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 60)
25
+static bool trans_VRINTR_sp(DisasContext *s, arg_VRINTR_sp *a)
42
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 54)
26
+{
43
27
+ TCGv_ptr fpst;
44
typedef struct Exynos4210Irq {
28
+ TCGv_i32 tmp;
45
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
29
+
46
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
30
+ if (!dc_isar_feature(aa32_vrint, s)) {
31
+ return false;
32
+ }
33
+
34
+ if (!vfp_access_check(s)) {
35
+ return true;
36
+ }
37
+
38
+ tmp = tcg_temp_new_i32();
39
+ neon_load_reg32(tmp, a->vm);
40
+ fpst = get_fpstatus_ptr(false);
41
+ gen_helper_rints(tmp, tmp, fpst);
42
+ neon_store_reg32(tmp, a->vd);
43
+ tcg_temp_free_ptr(fpst);
44
+ tcg_temp_free_i32(tmp);
45
+ return true;
46
+}
47
+
48
+static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_sp *a)
49
+{
50
+ TCGv_ptr fpst;
51
+ TCGv_i64 tmp;
52
+
53
+ if (!dc_isar_feature(aa32_vrint, s)) {
54
+ return false;
55
+ }
56
+
57
+ /* UNDEF accesses to D16-D31 if they don't exist. */
58
+ if (!dc_isar_feature(aa32_fp_d32, s) && ((a->vd | a->vm) & 0x10)) {
59
+ return false;
60
+ }
61
+
62
+ if (!vfp_access_check(s)) {
63
+ return true;
64
+ }
65
+
66
+ tmp = tcg_temp_new_i64();
67
+ neon_load_reg64(tmp, a->vm);
68
+ fpst = get_fpstatus_ptr(false);
69
+ gen_helper_rintd(tmp, tmp, fpst);
70
+ neon_store_reg64(tmp, a->vd);
71
+ tcg_temp_free_ptr(fpst);
72
+ tcg_temp_free_i64(tmp);
73
+ return true;
74
+}
75
+
76
+static bool trans_VRINTZ_sp(DisasContext *s, arg_VRINTZ_sp *a)
77
+{
78
+ TCGv_ptr fpst;
79
+ TCGv_i32 tmp;
80
+ TCGv_i32 tcg_rmode;
81
+
82
+ if (!dc_isar_feature(aa32_vrint, s)) {
83
+ return false;
84
+ }
85
+
86
+ if (!vfp_access_check(s)) {
87
+ return true;
88
+ }
89
+
90
+ tmp = tcg_temp_new_i32();
91
+ neon_load_reg32(tmp, a->vm);
92
+ fpst = get_fpstatus_ptr(false);
93
+ tcg_rmode = tcg_const_i32(float_round_to_zero);
94
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
95
+ gen_helper_rints(tmp, tmp, fpst);
96
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
97
+ neon_store_reg32(tmp, a->vd);
98
+ tcg_temp_free_ptr(fpst);
99
+ tcg_temp_free_i32(tcg_rmode);
100
+ tcg_temp_free_i32(tmp);
101
+ return true;
102
+}
103
+
104
+static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_sp *a)
105
+{
106
+ TCGv_ptr fpst;
107
+ TCGv_i64 tmp;
108
+ TCGv_i32 tcg_rmode;
109
+
110
+ if (!dc_isar_feature(aa32_vrint, s)) {
111
+ return false;
112
+ }
113
+
114
+ /* UNDEF accesses to D16-D31 if they don't exist. */
115
+ if (!dc_isar_feature(aa32_fp_d32, s) && ((a->vd | a->vm) & 0x10)) {
116
+ return false;
117
+ }
118
+
119
+ if (!vfp_access_check(s)) {
120
+ return true;
121
+ }
122
+
123
+ tmp = tcg_temp_new_i64();
124
+ neon_load_reg64(tmp, a->vm);
125
+ fpst = get_fpstatus_ptr(false);
126
+ tcg_rmode = tcg_const_i32(float_round_to_zero);
127
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
128
+ gen_helper_rintd(tmp, tmp, fpst);
129
+ gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
130
+ neon_store_reg64(tmp, a->vd);
131
+ tcg_temp_free_ptr(fpst);
132
+ tcg_temp_free_i64(tmp);
133
+ tcg_temp_free_i32(tcg_rmode);
134
+ return true;
135
+}
136
+
137
+static bool trans_VRINTX_sp(DisasContext *s, arg_VRINTX_sp *a)
138
+{
139
+ TCGv_ptr fpst;
140
+ TCGv_i32 tmp;
141
+
142
+ if (!dc_isar_feature(aa32_vrint, s)) {
143
+ return false;
144
+ }
145
+
146
+ if (!vfp_access_check(s)) {
147
+ return true;
148
+ }
149
+
150
+ tmp = tcg_temp_new_i32();
151
+ neon_load_reg32(tmp, a->vm);
152
+ fpst = get_fpstatus_ptr(false);
153
+ gen_helper_rints_exact(tmp, tmp, fpst);
154
+ neon_store_reg32(tmp, a->vd);
155
+ tcg_temp_free_ptr(fpst);
156
+ tcg_temp_free_i32(tmp);
157
+ return true;
158
+}
159
+
160
+static bool trans_VRINTX_dp(DisasContext *s, arg_VRINTX_dp *a)
161
+{
162
+ TCGv_ptr fpst;
163
+ TCGv_i64 tmp;
164
+
165
+ if (!dc_isar_feature(aa32_vrint, s)) {
166
+ return false;
167
+ }
168
+
169
+ /* UNDEF accesses to D16-D31 if they don't exist. */
170
+ if (!dc_isar_feature(aa32_fp_d32, s) && ((a->vd | a->vm) & 0x10)) {
171
+ return false;
172
+ }
173
+
174
+ if (!vfp_access_check(s)) {
175
+ return true;
176
+ }
177
+
178
+ tmp = tcg_temp_new_i64();
179
+ neon_load_reg64(tmp, a->vm);
180
+ fpst = get_fpstatus_ptr(false);
181
+ gen_helper_rintd_exact(tmp, tmp, fpst);
182
+ neon_store_reg64(tmp, a->vd);
183
+ tcg_temp_free_ptr(fpst);
184
+ tcg_temp_free_i64(tmp);
185
+ return true;
186
+}
187
diff --git a/target/arm/translate.c b/target/arm/translate.c
188
index XXXXXXX..XXXXXXX 100644
47
index XXXXXXX..XXXXXXX 100644
189
--- a/target/arm/translate.c
48
--- a/hw/arm/exynos4210.c
190
+++ b/target/arm/translate.c
49
+++ b/hw/arm/exynos4210.c
191
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
50
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
192
return 1;
51
/* int combiner group 34 */
193
case 15:
52
{ EXT_GIC_ID_ONENAND_AUDI, EXT_GIC_ID_NFC },
194
switch (rn) {
53
/* int combiner group 35 */
195
- case 0 ... 11:
54
- { 0, 0, 0, EXT_GIC_ID_MCT_L1, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
196
+ case 0 ... 14:
55
+ { 0, 0, 0, EXT_GIC_ID_MCT_L1 },
197
/* Already handled by decodetree */
56
/* int combiner group 36 */
198
return 1;
57
{ EXT_GIC_ID_MIXER },
199
default:
58
/* int combiner group 37 */
200
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
59
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
201
if (op == 15) {
60
/* groups 38-50 */
202
/* rn is opcode, encoded as per VFP_SREG_N. */
61
{ }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { }, { },
203
switch (rn) {
62
/* int combiner group 51 */
204
- case 0x0c: /* vrintr */
63
- { EXT_GIC_ID_MCT_L0, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
205
- case 0x0d: /* vrintz */
64
+ { EXT_GIC_ID_MCT_L0 },
206
- case 0x0e: /* vrintx */
65
/* group 52 */
207
- break;
66
{ },
208
-
67
/* int combiner group 53 */
209
case 0x0f: /* vcvt double<->single */
68
- { EXT_GIC_ID_WDT, 0, 0, 0, EXT_GIC_ID_MCT_G0, EXT_GIC_ID_MCT_G1 },
210
rd_is_dp = !dp;
69
+ { EXT_GIC_ID_WDT },
211
break;
70
/* groups 54-63 */
212
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
71
{ }, { }, { }, { }, { }, { }, { }, { }, { }, { }
213
switch (op) {
72
};
214
case 15: /* extension space */
73
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
215
switch (rn) {
74
216
- case 12: /* vrintr */
75
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
217
- {
76
irq_id = 0;
218
- TCGv_ptr fpst = get_fpstatus_ptr(0);
77
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4) ||
219
- if (dp) {
78
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4)) {
220
- gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
79
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 4)) {
221
- } else {
80
/* MCT_G0 is passed to External GIC */
222
- gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
81
irq_id = EXT_GIC_ID_MCT_G0;
223
- }
82
}
224
- tcg_temp_free_ptr(fpst);
83
- if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5) ||
225
- break;
84
- n == EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 5)) {
226
- }
85
+ if (n == EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 5)) {
227
- case 13: /* vrintz */
86
/* MCT_G1 is passed to External and GIC */
228
- {
87
irq_id = EXT_GIC_ID_MCT_G1;
229
- TCGv_ptr fpst = get_fpstatus_ptr(0);
88
}
230
- TCGv_i32 tcg_rmode;
231
- tcg_rmode = tcg_const_i32(float_round_to_zero);
232
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
233
- if (dp) {
234
- gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
235
- } else {
236
- gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
237
- }
238
- gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
239
- tcg_temp_free_i32(tcg_rmode);
240
- tcg_temp_free_ptr(fpst);
241
- break;
242
- }
243
- case 14: /* vrintx */
244
- {
245
- TCGv_ptr fpst = get_fpstatus_ptr(0);
246
- if (dp) {
247
- gen_helper_rintd_exact(cpu_F0d, cpu_F0d, fpst);
248
- } else {
249
- gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpst);
250
- }
251
- tcg_temp_free_ptr(fpst);
252
- break;
253
- }
254
case 15: /* single<->double conversion */
255
if (dp) {
256
gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
257
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
258
index XXXXXXX..XXXXXXX 100644
259
--- a/target/arm/vfp.decode
260
+++ b/target/arm/vfp.decode
261
@@ -XXX,XX +XXX,XX @@ VCVT_f16_f32 ---- 1110 1.11 0011 .... 1010 t:1 1.0 .... \
262
vd=%vd_sp vm=%vm_sp
263
VCVT_f16_f64 ---- 1110 1.11 0011 .... 1011 t:1 1.0 .... \
264
vd=%vd_sp vm=%vm_dp
265
+
266
+VRINTR_sp ---- 1110 1.11 0110 .... 1010 01.0 .... \
267
+ vd=%vd_sp vm=%vm_sp
268
+VRINTR_dp ---- 1110 1.11 0110 .... 1011 01.0 .... \
269
+ vd=%vd_dp vm=%vm_dp
270
+
271
+VRINTZ_sp ---- 1110 1.11 0110 .... 1010 11.0 .... \
272
+ vd=%vd_sp vm=%vm_sp
273
+VRINTZ_dp ---- 1110 1.11 0110 .... 1011 11.0 .... \
274
+ vd=%vd_dp vm=%vm_dp
275
+
276
+VRINTX_sp ---- 1110 1.11 0111 .... 1010 01.0 .... \
277
+ vd=%vd_sp vm=%vm_sp
278
+VRINTX_dp ---- 1110 1.11 0111 .... 1011 01.0 .... \
279
+ vd=%vd_dp vm=%vm_dp
280
--
89
--
281
2.20.1
90
2.25.1
282
283
diff view generated by jsdifflib
1
Convert the VFP VNMLS instruction to decodetree.
1
At this point, the function exynos4210_init_board_irqs() splits input
2
IRQ lines to connect them to the input combiner, output combiner and
3
external GIC. The function exynos4210_combiner_get_gpioin() splits
4
some of the combiner input lines further to connect them to multiple
5
different inputs on the combiner.
6
7
Because (unlike qemu_irq_split()) the TYPE_SPLIT_IRQ device has a
8
configurable number of outputs, we can do all this in one place, by
9
making exynos4210_init_board_irqs() add extra outputs to the splitter
10
device when it must be connected to more than one input on each
11
combiner.
12
13
We do this with a new data structure, the combinermap, which is an
14
array each of whose elements is a list of the interrupt IDs on the
15
combiner which must be tied together. As we loop through each
16
interrupt ID, if we find that it is the first one in one of these
17
lists, we configure the splitter device with eonugh extra outputs and
18
wire them up to the other interrupt IDs in the list.
19
20
Conveniently, for all the cases where this is necessary, the
21
lowest-numbered interrupt ID in each group is in the range of the
22
external combiner, so we only need to code for this in the first of
23
the two loops in exynos4210_init_board_irqs().
24
25
The old code in exynos4210_combiner_get_gpioin() which is being
26
deleted here had several problems which don't exist in the new code
27
in its handling of the multi-core timer interrupts:
28
(1) the case labels specified bits 4 ... 8, but bit '8' doesn't
29
exist; these should have been 4 ... 7
30
(2) it used the input irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]
31
multiple times as the input of several different splitters,
32
which isn't allowed
33
(3) in an apparent cut-and-paste error, the cases for all the
34
multi-core timer inputs used "bit + 4" even though the
35
bit range for the case was (intended to be) 4 ... 7, which
36
meant it was looking at non-existent bits 8 ... 11.
37
None of these exist in the new code.
2
38
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
39
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
40
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
41
Message-id: 20220404154658.565020-17-peter.maydell@linaro.org
5
---
42
---
6
target/arm/translate-vfp.inc.c | 42 ++++++++++++++++++++++++++++++++++
43
include/hw/arm/exynos4210.h | 6 +-
7
target/arm/translate.c | 24 +------------------
44
hw/arm/exynos4210.c | 178 +++++++++++++++++++++++-------------
8
target/arm/vfp.decode | 5 ++++
45
2 files changed, 119 insertions(+), 65 deletions(-)
9
3 files changed, 48 insertions(+), 23 deletions(-)
46
10
47
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
11
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
12
index XXXXXXX..XXXXXXX 100644
48
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-vfp.inc.c
49
--- a/include/hw/arm/exynos4210.h
14
+++ b/target/arm/translate-vfp.inc.c
50
+++ b/include/hw/arm/exynos4210.h
15
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLS_dp(DisasContext *s, arg_VMLS_sp *a)
51
@@ -XXX,XX +XXX,XX @@
16
{
52
17
return do_vfp_3op_dp(s, gen_VMLS_dp, a->vd, a->vn, a->vm, true);
53
/*
18
}
54
* We need one splitter for every external combiner input, plus
19
+
55
- * one for every non-zero entry in combiner_grp_to_gic_id[].
20
+static void gen_VNMLS_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
56
+ * one for every non-zero entry in combiner_grp_to_gic_id[],
57
+ * minus one for every external combiner ID in second or later
58
+ * places in a combinermap[] line.
59
* We'll assert in exynos4210_init_board_irqs() if this is wrong.
60
*/
61
-#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 54)
62
+#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 38)
63
64
typedef struct Exynos4210Irq {
65
qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
66
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
67
index XXXXXXX..XXXXXXX 100644
68
--- a/hw/arm/exynos4210.c
69
+++ b/hw/arm/exynos4210.c
70
@@ -XXX,XX +XXX,XX @@ combiner_grp_to_gic_id[64 - EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][8] = {
71
#define EXYNOS4210_COMBINER_GET_BIT_NUM(irq) \
72
((irq) - 8 * EXYNOS4210_COMBINER_GET_GRP_NUM(irq))
73
74
+/*
75
+ * Some interrupt lines go to multiple combiner inputs.
76
+ * This data structure defines those: each array element is
77
+ * a list of combiner inputs which are connected together;
78
+ * the one with the smallest interrupt ID value must be first.
79
+ * As with combiner_grp_to_gic_id[], we rely on (0, 0) not being
80
+ * wired to anything so we can use 0 as a terminator.
81
+ */
82
+#define IRQNO(G, B) EXYNOS4210_COMBINER_GET_IRQ_NUM(G, B)
83
+#define IRQNONE 0
84
+
85
+#define COMBINERMAP_SIZE 16
86
+
87
+static const int combinermap[COMBINERMAP_SIZE][6] = {
88
+ /* MDNIE_LCD1 */
89
+ { IRQNO(0, 4), IRQNO(1, 0), IRQNONE },
90
+ { IRQNO(0, 5), IRQNO(1, 1), IRQNONE },
91
+ { IRQNO(0, 6), IRQNO(1, 2), IRQNONE },
92
+ { IRQNO(0, 7), IRQNO(1, 3), IRQNONE },
93
+ /* TMU */
94
+ { IRQNO(2, 4), IRQNO(3, 4), IRQNONE },
95
+ { IRQNO(2, 5), IRQNO(3, 5), IRQNONE },
96
+ { IRQNO(2, 6), IRQNO(3, 6), IRQNONE },
97
+ { IRQNO(2, 7), IRQNO(3, 7), IRQNONE },
98
+ /* LCD1 */
99
+ { IRQNO(11, 4), IRQNO(12, 0), IRQNONE },
100
+ { IRQNO(11, 5), IRQNO(12, 1), IRQNONE },
101
+ { IRQNO(11, 6), IRQNO(12, 2), IRQNONE },
102
+ { IRQNO(11, 7), IRQNO(12, 3), IRQNONE },
103
+ /* Multi-core timer */
104
+ { IRQNO(1, 4), IRQNO(12, 4), IRQNO(35, 4), IRQNO(51, 4), IRQNO(53, 4), IRQNONE },
105
+ { IRQNO(1, 5), IRQNO(12, 5), IRQNO(35, 5), IRQNO(51, 5), IRQNO(53, 5), IRQNONE },
106
+ { IRQNO(1, 6), IRQNO(12, 6), IRQNO(35, 6), IRQNO(51, 6), IRQNO(53, 6), IRQNONE },
107
+ { IRQNO(1, 7), IRQNO(12, 7), IRQNO(35, 7), IRQNO(51, 7), IRQNO(53, 7), IRQNONE },
108
+};
109
+
110
+#undef IRQNO
111
+
112
+static const int *combinermap_entry(int irq)
21
+{
113
+{
22
+ /*
114
+ /*
23
+ * VNMLS: -fd + (fn * fm)
115
+ * If the interrupt number passed in is the first entry in some
24
+ * Note that it isn't valid to replace (-A + B) with (B - A) or similar
116
+ * line of the combinermap, return a pointer to that line;
25
+ * plausible looking simplifications because this will give wrong results
117
+ * otherwise return NULL.
26
+ * for NaNs.
27
+ */
118
+ */
28
+ TCGv_i32 tmp = tcg_temp_new_i32();
119
+ int i;
29
+
120
+ for (i = 0; i < COMBINERMAP_SIZE; i++) {
30
+ gen_helper_vfp_muls(tmp, vn, vm, fpst);
121
+ if (combinermap[i][0] == irq) {
31
+ gen_helper_vfp_negs(vd, vd);
122
+ return combinermap[i];
32
+ gen_helper_vfp_adds(vd, vd, tmp, fpst);
123
+ }
33
+ tcg_temp_free_i32(tmp);
124
+ }
125
+ return NULL;
34
+}
126
+}
35
+
127
+
36
+static bool trans_VNMLS_sp(DisasContext *s, arg_VNMLS_sp *a)
128
+static int mapline_size(const int *mapline)
37
+{
129
+{
38
+ return do_vfp_3op_sp(s, gen_VNMLS_sp, a->vd, a->vn, a->vm, true);
130
+ /* Return number of entries in this mapline in total */
131
+ int i = 0;
132
+
133
+ if (!mapline) {
134
+ /* Not in the map? IRQ goes to exactly one combiner input */
135
+ return 1;
136
+ }
137
+ while (*mapline != IRQNONE) {
138
+ mapline++;
139
+ i++;
140
+ }
141
+ return i;
39
+}
142
+}
40
+
143
+
41
+static void gen_VNMLS_dp(TCGv_i64 vd, TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst)
144
/*
42
+{
145
* Initialize board IRQs.
43
+ /*
146
* These IRQs contain splitted Int/External Combiner and External Gic IRQs.
44
+ * VNMLS: -fd + (fn * fm)
147
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
45
+ * Note that it isn't valid to replace (-A + B) with (B - A) or similar
148
DeviceState *extgicdev = DEVICE(&s->ext_gic);
46
+ * plausible looking simplifications because this will give wrong results
149
int splitcount = 0;
47
+ * for NaNs.
150
DeviceState *splitter;
48
+ */
151
+ const int *mapline;
49
+ TCGv_i64 tmp = tcg_temp_new_i64();
152
+ int numlines, splitin, in;
50
+
153
51
+ gen_helper_vfp_muld(tmp, vn, vm, fpst);
154
for (n = 0; n < EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ; n++) {
52
+ gen_helper_vfp_negd(vd, vd);
155
irq_id = 0;
53
+ gen_helper_vfp_addd(vd, vd, tmp, fpst);
156
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
54
+ tcg_temp_free_i64(tmp);
157
irq_id = EXT_GIC_ID_MCT_G1;
55
+}
158
}
56
+
159
57
+static bool trans_VNMLS_dp(DisasContext *s, arg_VNMLS_sp *a)
160
+ if (s->irq_table[n]) {
58
+{
161
+ /*
59
+ return do_vfp_3op_dp(s, gen_VNMLS_dp, a->vd, a->vn, a->vm, true);
162
+ * This must be some non-first entry in a combinermap line,
60
+}
163
+ * and we've already filled it in.
61
diff --git a/target/arm/translate.c b/target/arm/translate.c
164
+ */
62
index XXXXXXX..XXXXXXX 100644
165
+ continue;
63
--- a/target/arm/translate.c
166
+ }
64
+++ b/target/arm/translate.c
167
+ mapline = combinermap_entry(n);
65
@@ -XXX,XX +XXX,XX @@ VFP_OP2(div)
168
+ /*
66
169
+ * We need to connect the IRQ to multiple inputs on both combiners
67
#undef VFP_OP2
170
+ * and possibly also to the external GIC.
68
171
+ */
69
-static inline void gen_vfp_F1_mul(int dp)
172
+ numlines = 2 * mapline_size(mapline);
70
-{
173
+ if (irq_id) {
71
- /* Like gen_vfp_mul() but put result in F1 */
174
+ numlines++;
72
- TCGv_ptr fpst = get_fpstatus_ptr(0);
175
+ }
73
- if (dp) {
176
assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
74
- gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, fpst);
177
splitter = DEVICE(&s->splitter[splitcount]);
75
- } else {
178
- qdev_prop_set_uint16(splitter, "num-lines", irq_id ? 3 : 2);
76
- gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, fpst);
179
+ qdev_prop_set_uint16(splitter, "num-lines", numlines);
77
- }
180
qdev_realize(splitter, NULL, &error_abort);
78
- tcg_temp_free_ptr(fpst);
181
splitcount++;
79
-}
182
- s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
80
-
183
- qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
81
static inline void gen_vfp_F1_neg(int dp)
184
- qdev_connect_gpio_out(splitter, 1, is->ext_combiner_irq[n]);
185
+
186
+ in = n;
187
+ splitin = 0;
188
+ for (;;) {
189
+ s->irq_table[in] = qdev_get_gpio_in(splitter, 0);
190
+ qdev_connect_gpio_out(splitter, splitin, is->int_combiner_irq[in]);
191
+ qdev_connect_gpio_out(splitter, splitin + 1, is->ext_combiner_irq[in]);
192
+ splitin += 2;
193
+ if (!mapline) {
194
+ break;
195
+ }
196
+ mapline++;
197
+ in = *mapline;
198
+ if (in == IRQNONE) {
199
+ break;
200
+ }
201
+ }
202
if (irq_id) {
203
- qdev_connect_gpio_out(splitter, 2,
204
+ qdev_connect_gpio_out(splitter, splitin,
205
qdev_get_gpio_in(extgicdev, irq_id - 32));
206
}
207
}
208
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
209
irq_id = combiner_grp_to_gic_id[grp -
210
EXYNOS4210_MAX_EXT_COMBINER_OUT_IRQ][bit];
211
212
+ if (s->irq_table[n]) {
213
+ /*
214
+ * This must be some non-first entry in a combinermap line,
215
+ * and we've already filled it in.
216
+ */
217
+ continue;
218
+ }
219
+
220
if (irq_id) {
221
assert(splitcount < EXYNOS4210_NUM_SPLITTERS);
222
splitter = DEVICE(&s->splitter[splitcount]);
223
@@ -XXX,XX +XXX,XX @@ static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
224
DeviceState *dev, int ext)
82
{
225
{
83
/* Like gen_vfp_neg() but put result in F1 */
226
int n;
84
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
227
- int bit;
85
rn = VFP_SREG_N(insn);
228
int max;
86
229
qemu_irq *irq;
87
switch (op) {
230
88
- case 0 ... 1:
231
@@ -XXX,XX +XXX,XX @@ static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
89
+ case 0 ... 2:
232
EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
90
/* Already handled by decodetree */
233
irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
91
return 1;
234
92
default:
235
- /*
93
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
236
- * Some IRQs of Int/External Combiner are going to two Combiners groups,
94
for (;;) {
237
- * so let split them.
95
/* Perform the calculation. */
238
- */
96
switch (op) {
239
for (n = 0; n < max; n++) {
97
- case 2: /* VNMLS: -fd + (fn * fm) */
240
-
98
- /* Note that it isn't valid to replace (-A + B) with (B - A)
241
- bit = EXYNOS4210_COMBINER_GET_BIT_NUM(n);
99
- * or similar plausible looking simplifications
242
-
100
- * because this will give wrong results for NaNs.
243
- switch (n) {
101
- */
244
- /* MDNIE_LCD1 INTG1 */
102
- gen_vfp_F1_mul(dp);
245
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 0) ...
103
- gen_mov_F0_vreg(dp, rd);
246
- EXYNOS4210_COMBINER_GET_IRQ_NUM(1, 3):
104
- gen_vfp_neg(dp);
247
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
105
- gen_vfp_add(dp);
248
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(0, bit + 4)]);
106
- break;
249
- continue;
107
case 3: /* VNMLA: -fd + -(fn * fm) */
250
-
108
gen_vfp_mul(dp);
251
- /* TMU INTG3 */
109
gen_vfp_F1_neg(dp);
252
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(3, 4):
110
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
253
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
111
index XXXXXXX..XXXXXXX 100644
254
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(2, bit)]);
112
--- a/target/arm/vfp.decode
255
- continue;
113
+++ b/target/arm/vfp.decode
256
-
114
@@ -XXX,XX +XXX,XX @@ VMLS_sp ---- 1110 0.00 .... .... 1010 .1.0 .... \
257
- /* LCD1 INTG12 */
115
vm=%vm_sp vn=%vn_sp vd=%vd_sp
258
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 0) ...
116
VMLS_dp ---- 1110 0.00 .... .... 1011 .1.0 .... \
259
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 3):
117
vm=%vm_dp vn=%vn_dp vd=%vd_dp
260
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
118
+
261
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(11, bit + 4)]);
119
+VNMLS_sp ---- 1110 0.01 .... .... 1010 .0.0 .... \
262
- continue;
120
+ vm=%vm_sp vn=%vn_sp vd=%vd_sp
263
-
121
+VNMLS_dp ---- 1110 0.01 .... .... 1011 .0.0 .... \
264
- /* Multi-Core Timer INTG12 */
122
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
265
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 4) ...
266
- EXYNOS4210_COMBINER_GET_IRQ_NUM(12, 8):
267
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
268
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
269
- continue;
270
-
271
- /* Multi-Core Timer INTG35 */
272
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 4) ...
273
- EXYNOS4210_COMBINER_GET_IRQ_NUM(35, 8):
274
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
275
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
276
- continue;
277
-
278
- /* Multi-Core Timer INTG51 */
279
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 4) ...
280
- EXYNOS4210_COMBINER_GET_IRQ_NUM(51, 8):
281
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
282
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
283
- continue;
284
-
285
- /* Multi-Core Timer INTG53 */
286
- case EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 4) ...
287
- EXYNOS4210_COMBINER_GET_IRQ_NUM(53, 8):
288
- irq[n] = qemu_irq_split(qdev_get_gpio_in(dev, n),
289
- irq[EXYNOS4210_COMBINER_GET_IRQ_NUM(1, bit + 4)]);
290
- continue;
291
- }
292
-
293
irq[n] = qdev_get_gpio_in(dev, n);
294
}
295
}
123
--
296
--
124
2.20.1
297
2.25.1
125
126
diff view generated by jsdifflib
1
Convert the VSEL instructions to decodetree.
1
Switch the creation of the combiner devices to the new-style
2
We leave trans_VSEL() in translate.c for now as this allows
2
"embedded in state struct" approach, so we can easily refer
3
the patch to show just the changes from the old handle_vsel().
3
to the object elsewhere during realize.
4
5
In the old code the check for "do D16-D31 exist" was hidden in
6
the VFP_DREG macro, and assumed that VFPv3 always implied that
7
D16-D31 exist. In the new code we do the correct ID register test.
8
This gives identical behaviour for most of our CPUs, and fixes
9
previously incorrect handling for Cortex-R5F, Cortex-M4 and
10
Cortex-M33, which all implement VFPv3 or better with only 16
11
double-precision registers.
12
4
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
7
Message-id: 20220404154658.565020-18-peter.maydell@linaro.org
15
---
8
---
16
target/arm/cpu.h | 6 ++++++
9
include/hw/arm/exynos4210.h | 3 ++
17
target/arm/translate-vfp.inc.c | 9 +++++++++
10
include/hw/intc/exynos4210_combiner.h | 57 +++++++++++++++++++++++++++
18
target/arm/translate.c | 35 ++++++++++++++++++++++++----------
11
hw/arm/exynos4210.c | 20 +++++-----
19
target/arm/vfp-uncond.decode | 19 ++++++++++++++++++
12
hw/intc/exynos4210_combiner.c | 31 +--------------
20
4 files changed, 59 insertions(+), 10 deletions(-)
13
4 files changed, 72 insertions(+), 39 deletions(-)
14
create mode 100644 include/hw/intc/exynos4210_combiner.h
21
15
22
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
16
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
23
index XXXXXXX..XXXXXXX 100644
17
index XXXXXXX..XXXXXXX 100644
24
--- a/target/arm/cpu.h
18
--- a/include/hw/arm/exynos4210.h
25
+++ b/target/arm/cpu.h
19
+++ b/include/hw/arm/exynos4210.h
26
@@ -XXX,XX +XXX,XX @@ static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
20
@@ -XXX,XX +XXX,XX @@
27
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1;
21
#include "hw/sysbus.h"
28
}
22
#include "hw/cpu/a9mpcore.h"
29
23
#include "hw/intc/exynos4210_gic.h"
30
+static inline bool isar_feature_aa32_fp_d32(const ARMISARegisters *id)
24
+#include "hw/intc/exynos4210_combiner.h"
31
+{
25
#include "hw/core/split-irq.h"
32
+ /* Return true if D16-D31 are implemented */
26
#include "target/arm/cpu-qom.h"
33
+ return FIELD_EX64(id->mvfr0, MVFR0, SIMDREG) >= 2;
27
#include "qom/object.h"
34
+}
28
@@ -XXX,XX +XXX,XX @@ struct Exynos4210State {
29
qemu_or_irq cpu_irq_orgate[EXYNOS4210_NCPUS];
30
A9MPPrivState a9mpcore;
31
Exynos4210GicState ext_gic;
32
+ Exynos4210CombinerState int_combiner;
33
+ Exynos4210CombinerState ext_combiner;
34
SplitIRQ splitter[EXYNOS4210_NUM_SPLITTERS];
35
};
36
37
diff --git a/include/hw/intc/exynos4210_combiner.h b/include/hw/intc/exynos4210_combiner.h
38
new file mode 100644
39
index XXXXXXX..XXXXXXX
40
--- /dev/null
41
+++ b/include/hw/intc/exynos4210_combiner.h
42
@@ -XXX,XX +XXX,XX @@
43
+/*
44
+ * Samsung exynos4210 Interrupt Combiner
45
+ *
46
+ * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd.
47
+ * All rights reserved.
48
+ *
49
+ * Evgeny Voevodin <e.voevodin@samsung.com>
50
+ *
51
+ * This program is free software; you can redistribute it and/or modify it
52
+ * under the terms of the GNU General Public License as published by the
53
+ * Free Software Foundation; either version 2 of the License, or (at your
54
+ * option) any later version.
55
+ *
56
+ * This program is distributed in the hope that it will be useful,
57
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
58
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
59
+ * See the GNU General Public License for more details.
60
+ *
61
+ * You should have received a copy of the GNU General Public License along
62
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
63
+ */
35
+
64
+
36
/*
65
+#ifndef HW_INTC_EXYNOS4210_COMBINER
37
* We always set the FP and SIMD FP16 fields to indicate identical
66
+#define HW_INTC_EXYNOS4210_COMBINER
38
* levels of support (assuming SIMD is implemented at all), so
67
+
39
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
68
+#include "hw/sysbus.h"
40
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/translate-vfp.inc.c
42
+++ b/target/arm/translate-vfp.inc.c
43
@@ -XXX,XX +XXX,XX @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
44
45
return true;
46
}
47
+
69
+
48
+/*
70
+/*
49
+ * The most usual kind of VFP access check, for everything except
71
+ * State for each output signal of internal combiner
50
+ * FMXR/FMRX to the always-available special registers.
51
+ */
72
+ */
52
+static bool vfp_access_check(DisasContext *s)
73
+typedef struct CombinerGroupState {
53
+{
74
+ uint8_t src_mask; /* 1 - source enabled, 0 - disabled */
54
+ return full_vfp_access_check(s, false);
75
+ uint8_t src_pending; /* Pending source interrupts before masking */
55
+}
76
+} CombinerGroupState;
56
diff --git a/target/arm/translate.c b/target/arm/translate.c
77
+
78
+#define TYPE_EXYNOS4210_COMBINER "exynos4210.combiner"
79
+OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210CombinerState, EXYNOS4210_COMBINER)
80
+
81
+/* Number of groups and total number of interrupts for the internal combiner */
82
+#define IIC_NGRP 64
83
+#define IIC_NIRQ (IIC_NGRP * 8)
84
+#define IIC_REGSET_SIZE 0x41
85
+
86
+struct Exynos4210CombinerState {
87
+ SysBusDevice parent_obj;
88
+
89
+ MemoryRegion iomem;
90
+
91
+ struct CombinerGroupState group[IIC_NGRP];
92
+ uint32_t reg_set[IIC_REGSET_SIZE];
93
+ uint32_t icipsr[2];
94
+ uint32_t external; /* 1 means that this combiner is external */
95
+
96
+ qemu_irq output_irq[IIC_NGRP];
97
+};
98
+
99
+#endif
100
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
57
index XXXXXXX..XXXXXXX 100644
101
index XXXXXXX..XXXXXXX 100644
58
--- a/target/arm/translate.c
102
--- a/hw/arm/exynos4210.c
59
+++ b/target/arm/translate.c
103
+++ b/hw/arm/exynos4210.c
60
@@ -XXX,XX +XXX,XX @@ static void gen_neon_dup_high16(TCGv_i32 var)
104
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
61
tcg_temp_free_i32(tmp);
105
}
106
107
/* Internal Interrupt Combiner */
108
- dev = qdev_new("exynos4210.combiner");
109
- busdev = SYS_BUS_DEVICE(dev);
110
- sysbus_realize_and_unref(busdev, &error_fatal);
111
+ busdev = SYS_BUS_DEVICE(&s->int_combiner);
112
+ sysbus_realize(busdev, &error_fatal);
113
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
114
sysbus_connect_irq(busdev, n,
115
qdev_get_gpio_in(DEVICE(&s->a9mpcore), n));
116
}
117
- exynos4210_combiner_get_gpioin(&s->irqs, dev, 0);
118
+ exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->int_combiner), 0);
119
sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
120
121
/* External Interrupt Combiner */
122
- dev = qdev_new("exynos4210.combiner");
123
- qdev_prop_set_uint32(dev, "external", 1);
124
- busdev = SYS_BUS_DEVICE(dev);
125
- sysbus_realize_and_unref(busdev, &error_fatal);
126
+ qdev_prop_set_uint32(DEVICE(&s->ext_combiner), "external", 1);
127
+ busdev = SYS_BUS_DEVICE(&s->ext_combiner);
128
+ sysbus_realize(busdev, &error_fatal);
129
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
130
sysbus_connect_irq(busdev, n, qdev_get_gpio_in(DEVICE(&s->ext_gic), n));
131
}
132
- exynos4210_combiner_get_gpioin(&s->irqs, dev, 1);
133
+ exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->ext_combiner), 1);
134
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
135
136
/* Initialize board IRQs. */
137
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init(Object *obj)
138
139
object_initialize_child(obj, "a9mpcore", &s->a9mpcore, TYPE_A9MPCORE_PRIV);
140
object_initialize_child(obj, "ext-gic", &s->ext_gic, TYPE_EXYNOS4210_GIC);
141
+ object_initialize_child(obj, "int-combiner", &s->int_combiner,
142
+ TYPE_EXYNOS4210_COMBINER);
143
+ object_initialize_child(obj, "ext-combiner", &s->ext_combiner,
144
+ TYPE_EXYNOS4210_COMBINER);
62
}
145
}
63
146
64
-static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
147
static void exynos4210_class_init(ObjectClass *klass, void *data)
65
- uint32_t dp)
148
diff --git a/hw/intc/exynos4210_combiner.c b/hw/intc/exynos4210_combiner.c
66
+static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
67
{
68
- uint32_t cc = extract32(insn, 20, 2);
69
+ uint32_t rd, rn, rm;
70
+ bool dp = a->dp;
71
+
72
+ if (!dc_isar_feature(aa32_vsel, s)) {
73
+ return false;
74
+ }
75
+
76
+ /* UNDEF accesses to D16-D31 if they don't exist */
77
+ if (dp && !dc_isar_feature(aa32_fp_d32, s) &&
78
+ ((a->vm | a->vn | a->vd) & 0x10)) {
79
+ return false;
80
+ }
81
+ rd = a->vd;
82
+ rn = a->vn;
83
+ rm = a->vm;
84
+
85
+ if (!vfp_access_check(s)) {
86
+ return true;
87
+ }
88
89
if (dp) {
90
TCGv_i64 frn, frm, dest;
91
@@ -XXX,XX +XXX,XX @@ static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
92
93
tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
94
tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
95
- switch (cc) {
96
+ switch (a->cc) {
97
case 0: /* eq: Z */
98
tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
99
frn, frm);
100
@@ -XXX,XX +XXX,XX @@ static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
101
dest = tcg_temp_new_i32();
102
tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
103
tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
104
- switch (cc) {
105
+ switch (a->cc) {
106
case 0: /* eq: Z */
107
tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
108
frn, frm);
109
@@ -XXX,XX +XXX,XX @@ static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
110
tcg_temp_free_i32(zero);
111
}
112
113
- return 0;
114
+ return true;
115
}
116
117
static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
118
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_misc_insn(DisasContext *s, uint32_t insn)
119
rm = VFP_SREG_M(insn);
120
}
121
122
- if ((insn & 0x0f800e50) == 0x0e000a00 && dc_isar_feature(aa32_vsel, s)) {
123
- return handle_vsel(insn, rd, rn, rm, dp);
124
- } else if ((insn & 0x0fb00e10) == 0x0e800a00 &&
125
- dc_isar_feature(aa32_vminmaxnm, s)) {
126
+ if ((insn & 0x0fb00e10) == 0x0e800a00 &&
127
+ dc_isar_feature(aa32_vminmaxnm, s)) {
128
return handle_vminmaxnm(insn, rd, rn, rm, dp);
129
} else if ((insn & 0x0fbc0ed0) == 0x0eb80a40 &&
130
dc_isar_feature(aa32_vrint, s)) {
131
diff --git a/target/arm/vfp-uncond.decode b/target/arm/vfp-uncond.decode
132
index XXXXXXX..XXXXXXX 100644
149
index XXXXXXX..XXXXXXX 100644
133
--- a/target/arm/vfp-uncond.decode
150
--- a/hw/intc/exynos4210_combiner.c
134
+++ b/target/arm/vfp-uncond.decode
151
+++ b/hw/intc/exynos4210_combiner.c
135
@@ -XXX,XX +XXX,XX @@
152
@@ -XXX,XX +XXX,XX @@
136
# 1111 1110 .... .... .... 101. .... ....
153
#include "hw/sysbus.h"
137
# (but those patterns might also cover some Neon instructions,
154
#include "migration/vmstate.h"
138
# which do not live in this file.)
155
#include "qemu/module.h"
139
+
156
-
140
+# VFP registers have an odd encoding with a four-bit field
157
+#include "hw/intc/exynos4210_combiner.h"
141
+# and a one-bit field which are assembled in different orders
158
#include "hw/arm/exynos4210.h"
142
+# depending on whether the register is double or single precision.
159
#include "hw/hw.h"
143
+# Each individual instruction function must do the checks for
160
#include "hw/irq.h"
144
+# "double register selected but CPU does not have double support"
161
@@ -XXX,XX +XXX,XX @@
145
+# and "double register number has bit 4 set but CPU does not
162
#define DPRINTF(fmt, ...) do {} while (0)
146
+# support D16-D31" (which should UNDEF).
163
#endif
147
+%vm_dp 5:1 0:4
164
148
+%vm_sp 0:4 5:1
165
-#define IIC_NGRP 64 /* Internal Interrupt Combiner
149
+%vn_dp 7:1 16:4
166
- Groups number */
150
+%vn_sp 16:4 7:1
167
-#define IIC_NIRQ (IIC_NGRP * 8)/* Internal Interrupt Combiner
151
+%vd_dp 22:1 12:4
168
- Interrupts number */
152
+%vd_sp 12:4 22:1
169
#define IIC_REGION_SIZE 0x108 /* Size of memory mapped region */
153
+
170
-#define IIC_REGSET_SIZE 0x41
154
+VSEL 1111 1110 0. cc:2 .... .... 1010 .0.0 .... \
171
-
155
+ vm=%vm_sp vn=%vn_sp vd=%vd_sp dp=0
172
-/*
156
+VSEL 1111 1110 0. cc:2 .... .... 1011 .0.0 .... \
173
- * State for each output signal of internal combiner
157
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp dp=1
174
- */
175
-typedef struct CombinerGroupState {
176
- uint8_t src_mask; /* 1 - source enabled, 0 - disabled */
177
- uint8_t src_pending; /* Pending source interrupts before masking */
178
-} CombinerGroupState;
179
-
180
-#define TYPE_EXYNOS4210_COMBINER "exynos4210.combiner"
181
-OBJECT_DECLARE_SIMPLE_TYPE(Exynos4210CombinerState, EXYNOS4210_COMBINER)
182
-
183
-struct Exynos4210CombinerState {
184
- SysBusDevice parent_obj;
185
-
186
- MemoryRegion iomem;
187
-
188
- struct CombinerGroupState group[IIC_NGRP];
189
- uint32_t reg_set[IIC_REGSET_SIZE];
190
- uint32_t icipsr[2];
191
- uint32_t external; /* 1 means that this combiner is external */
192
-
193
- qemu_irq output_irq[IIC_NGRP];
194
-};
195
196
static const VMStateDescription vmstate_exynos4210_combiner_group_state = {
197
.name = "exynos4210.combiner.groupstate",
158
--
198
--
159
2.20.1
199
2.25.1
160
161
diff view generated by jsdifflib
1
Expand out the sequences in the new decoder VLDR/VSTR/VLDM/VSTM trans
1
The only time we use the int_combiner_irq[] and ext_combiner_irq[]
2
functions which perform the memory accesses by going via the TCG
2
arrays in the Exynos4210Irq struct is during realize of the SoC -- we
3
globals cpu_F0s and cpu_F0d, to use local TCG temps instead.
3
initialize them with the input IRQs of the combiner devices, and then
4
connect those to outputs of other devices in
5
exynos4210_init_board_irqs(). Now that the combiner objects are
6
easily accessible as s->int_combiner and s->ext_combiner we can make
7
the connections directly from one device to the other without going
8
via these arrays.
9
10
Since these are the only two remaining elements of Exynos4210Irq,
11
we can remove that struct entirely.
4
12
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
14
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
15
Message-id: 20220404154658.565020-19-peter.maydell@linaro.org
7
---
16
---
8
target/arm/translate-vfp.inc.c | 46 +++++++++++++++++++++-------------
17
include/hw/arm/exynos4210.h | 6 ------
9
target/arm/translate.c | 18 -------------
18
hw/arm/exynos4210.c | 34 ++++++++--------------------------
10
2 files changed, 28 insertions(+), 36 deletions(-)
19
2 files changed, 8 insertions(+), 32 deletions(-)
11
20
12
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
21
diff --git a/include/hw/arm/exynos4210.h b/include/hw/arm/exynos4210.h
13
index XXXXXXX..XXXXXXX 100644
22
index XXXXXXX..XXXXXXX 100644
14
--- a/target/arm/translate-vfp.inc.c
23
--- a/include/hw/arm/exynos4210.h
15
+++ b/target/arm/translate-vfp.inc.c
24
+++ b/include/hw/arm/exynos4210.h
16
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_64_dp(DisasContext *s, arg_VMOV_64_sp *a)
25
@@ -XXX,XX +XXX,XX @@
17
static bool trans_VLDR_VSTR_sp(DisasContext *s, arg_VLDR_VSTR_sp *a)
26
*/
27
#define EXYNOS4210_NUM_SPLITTERS (EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ + 38)
28
29
-typedef struct Exynos4210Irq {
30
- qemu_irq int_combiner_irq[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
31
- qemu_irq ext_combiner_irq[EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ];
32
-} Exynos4210Irq;
33
-
34
struct Exynos4210State {
35
/*< private >*/
36
SysBusDevice parent_obj;
37
/*< public >*/
38
ARMCPU *cpu[EXYNOS4210_NCPUS];
39
- Exynos4210Irq irqs;
40
qemu_irq irq_table[EXYNOS4210_MAX_INT_COMBINER_IN_IRQ];
41
42
MemoryRegion chipid_mem;
43
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/hw/arm/exynos4210.c
46
+++ b/hw/arm/exynos4210.c
47
@@ -XXX,XX +XXX,XX @@ static int mapline_size(const int *mapline)
48
static void exynos4210_init_board_irqs(Exynos4210State *s)
18
{
49
{
19
uint32_t offset;
50
uint32_t grp, bit, irq_id, n;
20
- TCGv_i32 addr;
51
- Exynos4210Irq *is = &s->irqs;
21
+ TCGv_i32 addr, tmp;
52
DeviceState *extgicdev = DEVICE(&s->ext_gic);
22
53
+ DeviceState *intcdev = DEVICE(&s->int_combiner);
23
if (!vfp_access_check(s)) {
54
+ DeviceState *extcdev = DEVICE(&s->ext_combiner);
24
return true;
55
int splitcount = 0;
25
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDR_VSTR_sp(DisasContext *s, arg_VLDR_VSTR_sp *a)
56
DeviceState *splitter;
26
addr = load_reg(s, a->rn);
57
const int *mapline;
58
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
59
splitin = 0;
60
for (;;) {
61
s->irq_table[in] = qdev_get_gpio_in(splitter, 0);
62
- qdev_connect_gpio_out(splitter, splitin, is->int_combiner_irq[in]);
63
- qdev_connect_gpio_out(splitter, splitin + 1, is->ext_combiner_irq[in]);
64
+ qdev_connect_gpio_out(splitter, splitin,
65
+ qdev_get_gpio_in(intcdev, in));
66
+ qdev_connect_gpio_out(splitter, splitin + 1,
67
+ qdev_get_gpio_in(extcdev, in));
68
splitin += 2;
69
if (!mapline) {
70
break;
71
@@ -XXX,XX +XXX,XX @@ static void exynos4210_init_board_irqs(Exynos4210State *s)
72
qdev_realize(splitter, NULL, &error_abort);
73
splitcount++;
74
s->irq_table[n] = qdev_get_gpio_in(splitter, 0);
75
- qdev_connect_gpio_out(splitter, 0, is->int_combiner_irq[n]);
76
+ qdev_connect_gpio_out(splitter, 0, qdev_get_gpio_in(intcdev, n));
77
qdev_connect_gpio_out(splitter, 1,
78
qdev_get_gpio_in(extgicdev, irq_id - 32));
79
} else {
80
- s->irq_table[n] = is->int_combiner_irq[n];
81
+ s->irq_table[n] = qdev_get_gpio_in(intcdev, n);
82
}
27
}
83
}
28
tcg_gen_addi_i32(addr, addr, offset);
84
/*
29
+ tmp = tcg_temp_new_i32();
85
@@ -XXX,XX +XXX,XX @@ uint32_t exynos4210_get_irq(uint32_t grp, uint32_t bit)
30
if (a->l) {
86
return EXYNOS4210_COMBINER_GET_IRQ_NUM(grp, bit);
31
- gen_vfp_ld(s, false, addr);
87
}
32
- gen_mov_vreg_F0(false, a->vd);
88
33
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
89
-/*
34
+ neon_store_reg32(tmp, a->vd);
90
- * Get Combiner input GPIO into irqs structure
35
} else {
91
- */
36
- gen_mov_F0_vreg(false, a->vd);
92
-static void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs,
37
- gen_vfp_st(s, false, addr);
93
- DeviceState *dev, int ext)
38
+ neon_load_reg32(tmp, a->vd);
39
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
40
}
41
+ tcg_temp_free_i32(tmp);
42
tcg_temp_free_i32(addr);
43
44
return true;
45
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDR_VSTR_dp(DisasContext *s, arg_VLDR_VSTR_sp *a)
46
{
47
uint32_t offset;
48
TCGv_i32 addr;
49
+ TCGv_i64 tmp;
50
51
/* UNDEF accesses to D16-D31 if they don't exist */
52
if (!dc_isar_feature(aa32_fp_d32, s) && (a->vd & 0x10)) {
53
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDR_VSTR_dp(DisasContext *s, arg_VLDR_VSTR_sp *a)
54
addr = load_reg(s, a->rn);
55
}
56
tcg_gen_addi_i32(addr, addr, offset);
57
+ tmp = tcg_temp_new_i64();
58
if (a->l) {
59
- gen_vfp_ld(s, true, addr);
60
- gen_mov_vreg_F0(true, a->vd);
61
+ gen_aa32_ld64(s, tmp, addr, get_mem_index(s));
62
+ neon_store_reg64(tmp, a->vd);
63
} else {
64
- gen_mov_F0_vreg(true, a->vd);
65
- gen_vfp_st(s, true, addr);
66
+ neon_load_reg64(tmp, a->vd);
67
+ gen_aa32_st64(s, tmp, addr, get_mem_index(s));
68
}
69
+ tcg_temp_free_i64(tmp);
70
tcg_temp_free_i32(addr);
71
72
return true;
73
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDR_VSTR_dp(DisasContext *s, arg_VLDR_VSTR_sp *a)
74
static bool trans_VLDM_VSTM_sp(DisasContext *s, arg_VLDM_VSTM_sp *a)
75
{
76
uint32_t offset;
77
- TCGv_i32 addr;
78
+ TCGv_i32 addr, tmp;
79
int i, n;
80
81
n = a->imm;
82
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDM_VSTM_sp(DisasContext *s, arg_VLDM_VSTM_sp *a)
83
}
84
85
offset = 4;
86
+ tmp = tcg_temp_new_i32();
87
for (i = 0; i < n; i++) {
88
if (a->l) {
89
/* load */
90
- gen_vfp_ld(s, false, addr);
91
- gen_mov_vreg_F0(false, a->vd + i);
92
+ gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
93
+ neon_store_reg32(tmp, a->vd + i);
94
} else {
95
/* store */
96
- gen_mov_F0_vreg(false, a->vd + i);
97
- gen_vfp_st(s, false, addr);
98
+ neon_load_reg32(tmp, a->vd + i);
99
+ gen_aa32_st32(s, tmp, addr, get_mem_index(s));
100
}
101
tcg_gen_addi_i32(addr, addr, offset);
102
}
103
+ tcg_temp_free_i32(tmp);
104
if (a->w) {
105
/* writeback */
106
if (a->p) {
107
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDM_VSTM_dp(DisasContext *s, arg_VLDM_VSTM_dp *a)
108
{
109
uint32_t offset;
110
TCGv_i32 addr;
111
+ TCGv_i64 tmp;
112
int i, n;
113
114
n = a->imm >> 1;
115
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDM_VSTM_dp(DisasContext *s, arg_VLDM_VSTM_dp *a)
116
}
117
118
offset = 8;
119
+ tmp = tcg_temp_new_i64();
120
for (i = 0; i < n; i++) {
121
if (a->l) {
122
/* load */
123
- gen_vfp_ld(s, true, addr);
124
- gen_mov_vreg_F0(true, a->vd + i);
125
+ gen_aa32_ld64(s, tmp, addr, get_mem_index(s));
126
+ neon_store_reg64(tmp, a->vd + i);
127
} else {
128
/* store */
129
- gen_mov_F0_vreg(true, a->vd + i);
130
- gen_vfp_st(s, true, addr);
131
+ neon_load_reg64(tmp, a->vd + i);
132
+ gen_aa32_st64(s, tmp, addr, get_mem_index(s));
133
}
134
tcg_gen_addi_i32(addr, addr, offset);
135
}
136
+ tcg_temp_free_i64(tmp);
137
if (a->w) {
138
/* writeback */
139
if (a->p) {
140
diff --git a/target/arm/translate.c b/target/arm/translate.c
141
index XXXXXXX..XXXXXXX 100644
142
--- a/target/arm/translate.c
143
+++ b/target/arm/translate.c
144
@@ -XXX,XX +XXX,XX @@ VFP_GEN_FIX(uhto, )
145
VFP_GEN_FIX(ulto, )
146
#undef VFP_GEN_FIX
147
148
-static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
149
-{
94
-{
150
- if (dp) {
95
- int n;
151
- gen_aa32_ld64(s, cpu_F0d, addr, get_mem_index(s));
96
- int max;
152
- } else {
97
- qemu_irq *irq;
153
- gen_aa32_ld32u(s, cpu_F0s, addr, get_mem_index(s));
98
-
99
- max = ext ? EXYNOS4210_MAX_EXT_COMBINER_IN_IRQ :
100
- EXYNOS4210_MAX_INT_COMBINER_IN_IRQ;
101
- irq = ext ? irqs->ext_combiner_irq : irqs->int_combiner_irq;
102
-
103
- for (n = 0; n < max; n++) {
104
- irq[n] = qdev_get_gpio_in(dev, n);
154
- }
105
- }
155
-}
106
-}
156
-
107
-
157
-static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
108
static uint8_t chipid_and_omr[] = { 0x11, 0x02, 0x21, 0x43,
158
-{
109
0x09, 0x00, 0x00, 0x00 };
159
- if (dp) {
110
160
- gen_aa32_st64(s, cpu_F0d, addr, get_mem_index(s));
111
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
161
- } else {
112
sysbus_connect_irq(busdev, n,
162
- gen_aa32_st32(s, cpu_F0s, addr, get_mem_index(s));
113
qdev_get_gpio_in(DEVICE(&s->a9mpcore), n));
163
- }
114
}
164
-}
115
- exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->int_combiner), 0);
165
-
116
sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR);
166
static inline long vfp_reg_offset(bool dp, unsigned reg)
117
167
{
118
/* External Interrupt Combiner */
168
if (dp) {
119
@@ -XXX,XX +XXX,XX @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
120
for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) {
121
sysbus_connect_irq(busdev, n, qdev_get_gpio_in(DEVICE(&s->ext_gic), n));
122
}
123
- exynos4210_combiner_get_gpioin(&s->irqs, DEVICE(&s->ext_combiner), 1);
124
sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR);
125
126
/* Initialize board IRQs. */
169
--
127
--
170
2.20.1
128
2.25.1
171
172
diff view generated by jsdifflib
1
Convert the "double-precision" register moves to decodetree:
1
From: Zongyuan Li <zongyuan.li@smartx.com>
2
this covers VMOV scalar-to-gpreg, VMOV gpreg-to-scalar and VDUP.
3
2
4
Note that the conversion process has tightened up a few of the
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
5
UNDEF encoding checks: we now correctly forbid:
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
* VMOV-to-gpr with U:opc1:opc2 == 10x00 or x0x10
5
Message-id: 20220324181557.203805-2-zongyuan.li@smartx.com
7
* VMOV-from-gpr with opc1:opc2 == 0x10
8
* VDUP with B:E == 11
9
* VDUP with Q == 1 and Vn<0> == 1
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
7
---
13
The accesses of elements < 32 bits could be improved by doing
8
hw/arm/realview.c | 33 ++++++++++++++++++++++++---------
14
direct ld/st of the right size rather than 32-bit read-and-shift
9
1 file changed, 24 insertions(+), 9 deletions(-)
15
or read-modify-write, but we leave this for later cleanup,
16
since this series is generally trying to stick to fixing
17
the decode.
18
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
19
---
20
target/arm/translate-vfp.inc.c | 147 +++++++++++++++++++++++++++++++++
21
target/arm/translate.c | 83 +------------------
22
target/arm/vfp.decode | 36 ++++++++
23
3 files changed, 185 insertions(+), 81 deletions(-)
24
10
25
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
11
diff --git a/hw/arm/realview.c b/hw/arm/realview.c
26
index XXXXXXX..XXXXXXX 100644
12
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/translate-vfp.inc.c
13
--- a/hw/arm/realview.c
28
+++ b/target/arm/translate-vfp.inc.c
14
+++ b/hw/arm/realview.c
29
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
15
@@ -XXX,XX +XXX,XX @@
30
16
#include "hw/sysbus.h"
31
return true;
17
#include "hw/arm/boot.h"
32
}
18
#include "hw/arm/primecell.h"
19
+#include "hw/core/split-irq.h"
20
#include "hw/net/lan9118.h"
21
#include "hw/net/smc91c111.h"
22
#include "hw/pci/pci.h"
23
+#include "hw/qdev-core.h"
24
#include "net/net.h"
25
#include "sysemu/sysemu.h"
26
#include "hw/boards.h"
27
@@ -XXX,XX +XXX,XX @@ static const int realview_board_id[] = {
28
0x76d
29
};
30
31
+static void split_irq_from_named(DeviceState *src, const char* outname,
32
+ qemu_irq out1, qemu_irq out2) {
33
+ DeviceState *splitter = qdev_new(TYPE_SPLIT_IRQ);
33
+
34
+
34
+static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a)
35
+ qdev_prop_set_uint32(splitter, "num-lines", 2);
35
+{
36
+ /* VMOV scalar to general purpose register */
37
+ TCGv_i32 tmp;
38
+ int pass;
39
+ uint32_t offset;
40
+
36
+
41
+ /* UNDEF accesses to D16-D31 if they don't exist */
37
+ qdev_realize_and_unref(splitter, NULL, &error_fatal);
42
+ if (!dc_isar_feature(aa32_fp_d32, s) && (a->vn & 0x10)) {
43
+ return false;
44
+ }
45
+
38
+
46
+ offset = a->index << a->size;
39
+ qdev_connect_gpio_out(splitter, 0, out1);
47
+ pass = extract32(offset, 2, 1);
40
+ qdev_connect_gpio_out(splitter, 1, out2);
48
+ offset = extract32(offset, 0, 2) * 8;
41
+ qdev_connect_gpio_out_named(src, outname, 0,
49
+
42
+ qdev_get_gpio_in(splitter, 0));
50
+ if (a->size != 2 && !arm_dc_feature(s, ARM_FEATURE_NEON)) {
51
+ return false;
52
+ }
53
+
54
+ if (!vfp_access_check(s)) {
55
+ return true;
56
+ }
57
+
58
+ tmp = neon_load_reg(a->vn, pass);
59
+ switch (a->size) {
60
+ case 0:
61
+ if (offset) {
62
+ tcg_gen_shri_i32(tmp, tmp, offset);
63
+ }
64
+ if (a->u) {
65
+ gen_uxtb(tmp);
66
+ } else {
67
+ gen_sxtb(tmp);
68
+ }
69
+ break;
70
+ case 1:
71
+ if (a->u) {
72
+ if (offset) {
73
+ tcg_gen_shri_i32(tmp, tmp, 16);
74
+ } else {
75
+ gen_uxth(tmp);
76
+ }
77
+ } else {
78
+ if (offset) {
79
+ tcg_gen_sari_i32(tmp, tmp, 16);
80
+ } else {
81
+ gen_sxth(tmp);
82
+ }
83
+ }
84
+ break;
85
+ case 2:
86
+ break;
87
+ }
88
+ store_reg(s, a->rt, tmp);
89
+
90
+ return true;
91
+}
43
+}
92
+
44
+
93
+static bool trans_VMOV_from_gp(DisasContext *s, arg_VMOV_from_gp *a)
45
static void realview_init(MachineState *machine,
94
+{
46
enum realview_board_type board_type)
95
+ /* VMOV general purpose register to scalar */
47
{
96
+ TCGv_i32 tmp, tmp2;
48
@@ -XXX,XX +XXX,XX @@ static void realview_init(MachineState *machine,
97
+ int pass;
49
DeviceState *dev, *sysctl, *gpio2, *pl041;
98
+ uint32_t offset;
50
SysBusDevice *busdev;
51
qemu_irq pic[64];
52
- qemu_irq mmc_irq[2];
53
PCIBus *pci_bus = NULL;
54
NICInfo *nd;
55
DriveInfo *dinfo;
56
@@ -XXX,XX +XXX,XX @@ static void realview_init(MachineState *machine,
57
* and the PL061 has them the other way about. Also the card
58
* detect line is inverted.
59
*/
60
- mmc_irq[0] = qemu_irq_split(
61
- qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT),
62
- qdev_get_gpio_in(gpio2, 1));
63
- mmc_irq[1] = qemu_irq_split(
64
- qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN),
65
- qemu_irq_invert(qdev_get_gpio_in(gpio2, 0)));
66
- qdev_connect_gpio_out_named(dev, "card-read-only", 0, mmc_irq[0]);
67
- qdev_connect_gpio_out_named(dev, "card-inserted", 0, mmc_irq[1]);
68
+ split_irq_from_named(dev, "card-read-only",
69
+ qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT),
70
+ qdev_get_gpio_in(gpio2, 1));
99
+
71
+
100
+ /* UNDEF accesses to D16-D31 if they don't exist */
72
+ split_irq_from_named(dev, "card-inserted",
101
+ if (!dc_isar_feature(aa32_fp_d32, s) && (a->vn & 0x10)) {
73
+ qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN),
102
+ return false;
74
+ qemu_irq_invert(qdev_get_gpio_in(gpio2, 0)));
103
+ }
104
+
75
+
105
+ offset = a->index << a->size;
76
dinfo = drive_get(IF_SD, 0, 0);
106
+ pass = extract32(offset, 2, 1);
77
if (dinfo) {
107
+ offset = extract32(offset, 0, 2) * 8;
78
DeviceState *card;
108
+
109
+ if (a->size != 2 && !arm_dc_feature(s, ARM_FEATURE_NEON)) {
110
+ return false;
111
+ }
112
+
113
+ if (!vfp_access_check(s)) {
114
+ return true;
115
+ }
116
+
117
+ tmp = load_reg(s, a->rt);
118
+ switch (a->size) {
119
+ case 0:
120
+ tmp2 = neon_load_reg(a->vn, pass);
121
+ tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8);
122
+ tcg_temp_free_i32(tmp2);
123
+ break;
124
+ case 1:
125
+ tmp2 = neon_load_reg(a->vn, pass);
126
+ tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16);
127
+ tcg_temp_free_i32(tmp2);
128
+ break;
129
+ case 2:
130
+ break;
131
+ }
132
+ neon_store_reg(a->vn, pass, tmp);
133
+
134
+ return true;
135
+}
136
+
137
+static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
138
+{
139
+ /* VDUP (general purpose register) */
140
+ TCGv_i32 tmp;
141
+ int size, vec_size;
142
+
143
+ if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
144
+ return false;
145
+ }
146
+
147
+ /* UNDEF accesses to D16-D31 if they don't exist */
148
+ if (!dc_isar_feature(aa32_fp_d32, s) && (a->vn & 0x10)) {
149
+ return false;
150
+ }
151
+
152
+ if (a->b && a->e) {
153
+ return false;
154
+ }
155
+
156
+ if (a->q && (a->vn & 1)) {
157
+ return false;
158
+ }
159
+
160
+ vec_size = a->q ? 16 : 8;
161
+ if (a->b) {
162
+ size = 0;
163
+ } else if (a->e) {
164
+ size = 1;
165
+ } else {
166
+ size = 2;
167
+ }
168
+
169
+ if (!vfp_access_check(s)) {
170
+ return true;
171
+ }
172
+
173
+ tmp = load_reg(s, a->rt);
174
+ tcg_gen_gvec_dup_i32(size, neon_reg_offset(a->vn, 0),
175
+ vec_size, vec_size, tmp);
176
+ tcg_temp_free_i32(tmp);
177
+
178
+ return true;
179
+}
180
diff --git a/target/arm/translate.c b/target/arm/translate.c
181
index XXXXXXX..XXXXXXX 100644
182
--- a/target/arm/translate.c
183
+++ b/target/arm/translate.c
184
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
185
/* single register transfer */
186
rd = (insn >> 12) & 0xf;
187
if (dp) {
188
- int size;
189
- int pass;
190
-
191
- VFP_DREG_N(rn, insn);
192
- if (insn & 0xf)
193
- return 1;
194
- if (insn & 0x00c00060
195
- && !arm_dc_feature(s, ARM_FEATURE_NEON)) {
196
- return 1;
197
- }
198
-
199
- pass = (insn >> 21) & 1;
200
- if (insn & (1 << 22)) {
201
- size = 0;
202
- offset = ((insn >> 5) & 3) * 8;
203
- } else if (insn & (1 << 5)) {
204
- size = 1;
205
- offset = (insn & (1 << 6)) ? 16 : 0;
206
- } else {
207
- size = 2;
208
- offset = 0;
209
- }
210
- if (insn & ARM_CP_RW_BIT) {
211
- /* vfp->arm */
212
- tmp = neon_load_reg(rn, pass);
213
- switch (size) {
214
- case 0:
215
- if (offset)
216
- tcg_gen_shri_i32(tmp, tmp, offset);
217
- if (insn & (1 << 23))
218
- gen_uxtb(tmp);
219
- else
220
- gen_sxtb(tmp);
221
- break;
222
- case 1:
223
- if (insn & (1 << 23)) {
224
- if (offset) {
225
- tcg_gen_shri_i32(tmp, tmp, 16);
226
- } else {
227
- gen_uxth(tmp);
228
- }
229
- } else {
230
- if (offset) {
231
- tcg_gen_sari_i32(tmp, tmp, 16);
232
- } else {
233
- gen_sxth(tmp);
234
- }
235
- }
236
- break;
237
- case 2:
238
- break;
239
- }
240
- store_reg(s, rd, tmp);
241
- } else {
242
- /* arm->vfp */
243
- tmp = load_reg(s, rd);
244
- if (insn & (1 << 23)) {
245
- /* VDUP */
246
- int vec_size = pass ? 16 : 8;
247
- tcg_gen_gvec_dup_i32(size, neon_reg_offset(rn, 0),
248
- vec_size, vec_size, tmp);
249
- tcg_temp_free_i32(tmp);
250
- } else {
251
- /* VMOV */
252
- switch (size) {
253
- case 0:
254
- tmp2 = neon_load_reg(rn, pass);
255
- tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8);
256
- tcg_temp_free_i32(tmp2);
257
- break;
258
- case 1:
259
- tmp2 = neon_load_reg(rn, pass);
260
- tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16);
261
- tcg_temp_free_i32(tmp2);
262
- break;
263
- case 2:
264
- break;
265
- }
266
- neon_store_reg(rn, pass, tmp);
267
- }
268
- }
269
+ /* already handled by decodetree */
270
+ return 1;
271
} else { /* !dp */
272
bool is_sysreg;
273
274
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
275
index XXXXXXX..XXXXXXX 100644
276
--- a/target/arm/vfp.decode
277
+++ b/target/arm/vfp.decode
278
@@ -XXX,XX +XXX,XX @@
279
# 1110 1110 .... .... .... 101. .... ....
280
# (but those patterns might also cover some Neon instructions,
281
# which do not live in this file.)
282
+
283
+# VFP registers have an odd encoding with a four-bit field
284
+# and a one-bit field which are assembled in different orders
285
+# depending on whether the register is double or single precision.
286
+# Each individual instruction function must do the checks for
287
+# "double register selected but CPU does not have double support"
288
+# and "double register number has bit 4 set but CPU does not
289
+# support D16-D31" (which should UNDEF).
290
+%vm_dp 5:1 0:4
291
+%vm_sp 0:4 5:1
292
+%vn_dp 7:1 16:4
293
+%vn_sp 16:4 7:1
294
+%vd_dp 22:1 12:4
295
+%vd_sp 12:4 22:1
296
+
297
+%vmov_idx_b 21:1 5:2
298
+%vmov_idx_h 21:1 6:1
299
+
300
+# VMOV scalar to general-purpose register; note that this does
301
+# include some Neon cases.
302
+VMOV_to_gp ---- 1110 u:1 1. 1 .... rt:4 1011 ... 1 0000 \
303
+ vn=%vn_dp size=0 index=%vmov_idx_b
304
+VMOV_to_gp ---- 1110 u:1 0. 1 .... rt:4 1011 ..1 1 0000 \
305
+ vn=%vn_dp size=1 index=%vmov_idx_h
306
+VMOV_to_gp ---- 1110 0 0 index:1 1 .... rt:4 1011 .00 1 0000 \
307
+ vn=%vn_dp size=2 u=0
308
+
309
+VMOV_from_gp ---- 1110 0 1. 0 .... rt:4 1011 ... 1 0000 \
310
+ vn=%vn_dp size=0 index=%vmov_idx_b
311
+VMOV_from_gp ---- 1110 0 0. 0 .... rt:4 1011 ..1 1 0000 \
312
+ vn=%vn_dp size=1 index=%vmov_idx_h
313
+VMOV_from_gp ---- 1110 0 0 index:1 0 .... rt:4 1011 .00 1 0000 \
314
+ vn=%vn_dp size=2
315
+
316
+VDUP ---- 1110 1 b:1 q:1 0 .... rt:4 1011 . 0 e:1 1 0000 \
317
+ vn=%vn_dp
318
--
79
--
319
2.20.1
80
2.25.1
320
321
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Zongyuan Li <zongyuan.li@smartx.com>
2
2
3
Typo comparing the sign of the field, twice, instead of also comparing
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
4
the mask of the field (which itself encodes both position and length).
5
6
Reported-by: Peter Maydell <peter.maydell@linaro.org>
7
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
8
Message-id: 20190604154225.26992-1-richard.henderson@linaro.org
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
5
Message-id: 20220324181557.203805-3-zongyuan.li@smartx.com
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
---
7
---
13
scripts/decodetree.py | 2 +-
8
hw/arm/stellaris.c | 15 +++++++++++++--
14
1 file changed, 1 insertion(+), 1 deletion(-)
9
1 file changed, 13 insertions(+), 2 deletions(-)
15
10
16
diff --git a/scripts/decodetree.py b/scripts/decodetree.py
11
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
17
index XXXXXXX..XXXXXXX 100755
12
index XXXXXXX..XXXXXXX 100644
18
--- a/scripts/decodetree.py
13
--- a/hw/arm/stellaris.c
19
+++ b/scripts/decodetree.py
14
+++ b/hw/arm/stellaris.c
20
@@ -XXX,XX +XXX,XX @@ class Field:
15
@@ -XXX,XX +XXX,XX @@
21
return '{0}(insn, {1}, {2})'.format(extr, self.pos, self.len)
16
22
17
#include "qemu/osdep.h"
23
def __eq__(self, other):
18
#include "qapi/error.h"
24
- return self.sign == other.sign and self.sign == other.sign
19
+#include "hw/core/split-irq.h"
25
+ return self.sign == other.sign and self.mask == other.mask
20
#include "hw/sysbus.h"
26
21
#include "hw/sd/sd.h"
27
def __ne__(self, other):
22
#include "hw/ssi/ssi.h"
28
return not self.__eq__(other)
23
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
24
DeviceState *ssddev;
25
DriveInfo *dinfo;
26
DeviceState *carddev;
27
+ DeviceState *gpio_d_splitter;
28
BlockBackend *blk;
29
30
/*
31
@@ -XXX,XX +XXX,XX @@ static void stellaris_init(MachineState *ms, stellaris_board_info *board)
32
&error_fatal);
33
34
ssddev = ssi_create_peripheral(bus, "ssd0323");
35
- gpio_out[GPIO_D][0] = qemu_irq_split(
36
- qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0),
37
+
38
+ gpio_d_splitter = qdev_new(TYPE_SPLIT_IRQ);
39
+ qdev_prop_set_uint32(gpio_d_splitter, "num-lines", 2);
40
+ qdev_realize_and_unref(gpio_d_splitter, NULL, &error_fatal);
41
+ qdev_connect_gpio_out(
42
+ gpio_d_splitter, 0,
43
+ qdev_get_gpio_in_named(sddev, SSI_GPIO_CS, 0));
44
+ qdev_connect_gpio_out(
45
+ gpio_d_splitter, 1,
46
qdev_get_gpio_in_named(ssddev, SSI_GPIO_CS, 0));
47
+ gpio_out[GPIO_D][0] = qdev_get_gpio_in(gpio_d_splitter, 0);
48
+
49
gpio_out[GPIO_C][7] = qdev_get_gpio_in(ssddev, 0);
50
51
/* Make sure the select pin is high. */
29
--
52
--
30
2.20.1
53
2.25.1
31
32
diff view generated by jsdifflib
1
Convert the VCVTT and VCVTB instructions which convert from
1
From: Zongyuan Li <zongyuan.li@smartx.com>
2
f32 and f64 to f16 to decodetree.
3
2
4
Since we're no longer constrained to the old decoder's style
3
Signed-off-by: Zongyuan Li <zongyuan.li@smartx.com>
5
using cpu_F0s and cpu_F0d we can perform a direct 16 bit
4
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
6
store of the right half of the input single-precision register
5
Message-id: 20220324181557.203805-5-zongyuan.li@smartx.com
7
rather than doing a load/modify/store sequence on the full
6
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/811
8
32 bits.
7
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
8
---
9
include/hw/irq.h | 5 -----
10
hw/core/irq.c | 15 ---------------
11
2 files changed, 20 deletions(-)
9
12
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
diff --git a/include/hw/irq.h b/include/hw/irq.h
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
---
13
target/arm/translate-vfp.inc.c | 62 ++++++++++++++++++++++++++
14
target/arm/translate.c | 79 +---------------------------------
15
target/arm/vfp.decode | 6 +++
16
3 files changed, 69 insertions(+), 78 deletions(-)
17
18
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
19
index XXXXXXX..XXXXXXX 100644
14
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/translate-vfp.inc.c
15
--- a/include/hw/irq.h
21
+++ b/target/arm/translate-vfp.inc.c
16
+++ b/include/hw/irq.h
22
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT_f64_f16(DisasContext *s, arg_VCVT_f64_f16 *a)
17
@@ -XXX,XX +XXX,XX @@ void qemu_free_irq(qemu_irq irq);
23
tcg_temp_free_i64(vd);
18
/* Returns a new IRQ with opposite polarity. */
24
return true;
19
qemu_irq qemu_irq_invert(qemu_irq irq);
20
21
-/* Returns a new IRQ which feeds into both the passed IRQs.
22
- * It's probably better to use the TYPE_SPLIT_IRQ device instead.
23
- */
24
-qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2);
25
-
26
/* For internal use in qtest. Similar to qemu_irq_split, but operating
27
on an existing vector of qemu_irq. */
28
void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n);
29
diff --git a/hw/core/irq.c b/hw/core/irq.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/hw/core/irq.c
32
+++ b/hw/core/irq.c
33
@@ -XXX,XX +XXX,XX @@ qemu_irq qemu_irq_invert(qemu_irq irq)
34
return qemu_allocate_irq(qemu_notirq, irq, 0);
25
}
35
}
26
+
36
27
+static bool trans_VCVT_f16_f32(DisasContext *s, arg_VCVT_f16_f32 *a)
37
-static void qemu_splitirq(void *opaque, int line, int level)
28
+{
29
+ TCGv_ptr fpst;
30
+ TCGv_i32 ahp_mode;
31
+ TCGv_i32 tmp;
32
+
33
+ if (!dc_isar_feature(aa32_fp16_spconv, s)) {
34
+ return false;
35
+ }
36
+
37
+ if (!vfp_access_check(s)) {
38
+ return true;
39
+ }
40
+
41
+ fpst = get_fpstatus_ptr(false);
42
+ ahp_mode = get_ahp_flag();
43
+ tmp = tcg_temp_new_i32();
44
+
45
+ neon_load_reg32(tmp, a->vm);
46
+ gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp_mode);
47
+ tcg_gen_st16_i32(tmp, cpu_env, vfp_f16_offset(a->vd, a->t));
48
+ tcg_temp_free_i32(ahp_mode);
49
+ tcg_temp_free_ptr(fpst);
50
+ tcg_temp_free_i32(tmp);
51
+ return true;
52
+}
53
+
54
+static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a)
55
+{
56
+ TCGv_ptr fpst;
57
+ TCGv_i32 ahp_mode;
58
+ TCGv_i32 tmp;
59
+ TCGv_i64 vm;
60
+
61
+ if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
62
+ return false;
63
+ }
64
+
65
+ /* UNDEF accesses to D16-D31 if they don't exist. */
66
+ if (!dc_isar_feature(aa32_fp_d32, s) && (a->vm & 0x10)) {
67
+ return false;
68
+ }
69
+
70
+ if (!vfp_access_check(s)) {
71
+ return true;
72
+ }
73
+
74
+ fpst = get_fpstatus_ptr(false);
75
+ ahp_mode = get_ahp_flag();
76
+ tmp = tcg_temp_new_i32();
77
+ vm = tcg_temp_new_i64();
78
+
79
+ neon_load_reg64(vm, a->vm);
80
+ gen_helper_vfp_fcvt_f64_to_f16(tmp, vm, fpst, ahp_mode);
81
+ tcg_temp_free_i64(vm);
82
+ tcg_gen_st16_i32(tmp, cpu_env, vfp_f16_offset(a->vd, a->t));
83
+ tcg_temp_free_i32(ahp_mode);
84
+ tcg_temp_free_ptr(fpst);
85
+ tcg_temp_free_i32(tmp);
86
+ return true;
87
+}
88
diff --git a/target/arm/translate.c b/target/arm/translate.c
89
index XXXXXXX..XXXXXXX 100644
90
--- a/target/arm/translate.c
91
+++ b/target/arm/translate.c
92
@@ -XXX,XX +XXX,XX @@ static int disas_dsp_insn(DisasContext *s, uint32_t insn)
93
#define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
94
#define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
95
96
-/* Move between integer and VFP cores. */
97
-static TCGv_i32 gen_vfp_mrs(void)
98
-{
38
-{
99
- TCGv_i32 tmp = tcg_temp_new_i32();
39
- struct IRQState **irq = opaque;
100
- tcg_gen_mov_i32(tmp, cpu_F0s);
40
- irq[0]->handler(irq[0]->opaque, irq[0]->n, level);
101
- return tmp;
41
- irq[1]->handler(irq[1]->opaque, irq[1]->n, level);
102
-}
42
-}
103
-
43
-
104
-static void gen_vfp_msr(TCGv_i32 tmp)
44
-qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2)
105
-{
45
-{
106
- tcg_gen_mov_i32(cpu_F0s, tmp);
46
- qemu_irq *s = g_new0(qemu_irq, 2);
107
- tcg_temp_free_i32(tmp);
47
- s[0] = irq1;
48
- s[1] = irq2;
49
- return qemu_allocate_irq(qemu_splitirq, s, 0);
108
-}
50
-}
109
-
51
-
110
static void gen_neon_dup_low16(TCGv_i32 var)
52
void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n)
111
{
53
{
112
TCGv_i32 tmp = tcg_temp_new_i32();
54
int i;
113
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
114
{
115
uint32_t rd, rn, rm, op, delta_d, delta_m, bank_mask;
116
int dp, veclen;
117
- TCGv_i32 tmp;
118
- TCGv_i32 tmp2;
119
120
if (!arm_dc_feature(s, ARM_FEATURE_VFP)) {
121
return 1;
122
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
123
return 1;
124
case 15:
125
switch (rn) {
126
- case 0 ... 5:
127
- case 8 ... 11:
128
+ case 0 ... 11:
129
/* Already handled by decodetree */
130
return 1;
131
default:
132
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
133
if (op == 15) {
134
/* rn is opcode, encoded as per VFP_SREG_N. */
135
switch (rn) {
136
- case 0x06: /* vcvtb.f16.f32, vcvtb.f16.f64 */
137
- case 0x07: /* vcvtt.f16.f32, vcvtt.f16.f64 */
138
- if (dp) {
139
- if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
140
- return 1;
141
- }
142
- } else {
143
- if (!dc_isar_feature(aa32_fp16_spconv, s)) {
144
- return 1;
145
- }
146
- }
147
- rd_is_dp = false;
148
- break;
149
-
150
case 0x0c: /* vrintr */
151
case 0x0d: /* vrintz */
152
case 0x0e: /* vrintx */
153
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
154
switch (op) {
155
case 15: /* extension space */
156
switch (rn) {
157
- case 6: /* vcvtb.f16.f32, vcvtb.f16.f64 */
158
- {
159
- TCGv_ptr fpst = get_fpstatus_ptr(false);
160
- TCGv_i32 ahp = get_ahp_flag();
161
- tmp = tcg_temp_new_i32();
162
-
163
- if (dp) {
164
- gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
165
- fpst, ahp);
166
- } else {
167
- gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
168
- fpst, ahp);
169
- }
170
- tcg_temp_free_i32(ahp);
171
- tcg_temp_free_ptr(fpst);
172
- gen_mov_F0_vreg(0, rd);
173
- tmp2 = gen_vfp_mrs();
174
- tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
175
- tcg_gen_or_i32(tmp, tmp, tmp2);
176
- tcg_temp_free_i32(tmp2);
177
- gen_vfp_msr(tmp);
178
- break;
179
- }
180
- case 7: /* vcvtt.f16.f32, vcvtt.f16.f64 */
181
- {
182
- TCGv_ptr fpst = get_fpstatus_ptr(false);
183
- TCGv_i32 ahp = get_ahp_flag();
184
- tmp = tcg_temp_new_i32();
185
- if (dp) {
186
- gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
187
- fpst, ahp);
188
- } else {
189
- gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
190
- fpst, ahp);
191
- }
192
- tcg_temp_free_i32(ahp);
193
- tcg_temp_free_ptr(fpst);
194
- tcg_gen_shli_i32(tmp, tmp, 16);
195
- gen_mov_F0_vreg(0, rd);
196
- tmp2 = gen_vfp_mrs();
197
- tcg_gen_ext16u_i32(tmp2, tmp2);
198
- tcg_gen_or_i32(tmp, tmp, tmp2);
199
- tcg_temp_free_i32(tmp2);
200
- gen_vfp_msr(tmp);
201
- break;
202
- }
203
case 12: /* vrintr */
204
{
205
TCGv_ptr fpst = get_fpstatus_ptr(0);
206
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
207
index XXXXXXX..XXXXXXX 100644
208
--- a/target/arm/vfp.decode
209
+++ b/target/arm/vfp.decode
210
@@ -XXX,XX +XXX,XX @@ VCVT_f32_f16 ---- 1110 1.11 0010 .... 1010 t:1 1.0 .... \
211
vd=%vd_sp vm=%vm_sp
212
VCVT_f64_f16 ---- 1110 1.11 0010 .... 1011 t:1 1.0 .... \
213
vd=%vd_dp vm=%vm_sp
214
+
215
+# VCVTB and VCVTT to f16: Vd format is always vd_sp; Vm format depends on size bit
216
+VCVT_f16_f32 ---- 1110 1.11 0011 .... 1010 t:1 1.0 .... \
217
+ vd=%vd_sp vm=%vm_sp
218
+VCVT_f16_f64 ---- 1110 1.11 0011 .... 1011 t:1 1.0 .... \
219
+ vd=%vd_sp vm=%vm_dp
220
--
55
--
221
2.20.1
56
2.25.1
222
223
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
2
2
3
The ARM pseudocode installs the error_code into the original
3
Describe that the gic-version influences the maximum number of CPUs.
4
pointer, not the encrypted pointer. The difference applies
5
within the 7 bits of pac data; the result should be the sign
6
extension of bit 55.
7
4
8
Add a testcase to that effect.
5
Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
9
6
Message-id: 20220413231456.35811-1-heinrich.schuchardt@canonical.com
10
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
7
[PMM: minor punctuation tweaks]
11
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
8
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
12
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
13
---
10
---
14
tests/tcg/aarch64/Makefile.target | 2 +-
11
docs/system/arm/virt.rst | 4 ++--
15
target/arm/pauth_helper.c | 4 +-
12
1 file changed, 2 insertions(+), 2 deletions(-)
16
tests/tcg/aarch64/pauth-2.c | 61 +++++++++++++++++++++++++++++++
17
3 files changed, 64 insertions(+), 3 deletions(-)
18
create mode 100644 tests/tcg/aarch64/pauth-2.c
19
13
20
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
14
diff --git a/docs/system/arm/virt.rst b/docs/system/arm/virt.rst
21
index XXXXXXX..XXXXXXX 100644
15
index XXXXXXX..XXXXXXX 100644
22
--- a/tests/tcg/aarch64/Makefile.target
16
--- a/docs/system/arm/virt.rst
23
+++ b/tests/tcg/aarch64/Makefile.target
17
+++ b/docs/system/arm/virt.rst
24
@@ -XXX,XX +XXX,XX @@ run-fcvt: fcvt
18
@@ -XXX,XX +XXX,XX @@ gic-version
25
    $(call run-test,$<,$(QEMU) $<, "$< on $(TARGET_NAME)")
19
Valid values are:
26
    $(call diff-out,$<,$(AARCH64_SRC)/fcvt.ref)
20
27
21
``2``
28
-AARCH64_TESTS += pauth-1
22
- GICv2
29
+AARCH64_TESTS += pauth-1 pauth-2
23
+ GICv2. Note that this limits the number of CPUs to 8.
30
run-pauth-%: QEMU += -cpu max
24
``3``
31
25
- GICv3
32
TESTS:=$(AARCH64_TESTS)
26
+ GICv3. This allows up to 512 CPUs.
33
diff --git a/target/arm/pauth_helper.c b/target/arm/pauth_helper.c
27
``host``
34
index XXXXXXX..XXXXXXX 100644
28
Use the same GIC version the host provides, when using KVM
35
--- a/target/arm/pauth_helper.c
29
``max``
36
+++ b/target/arm/pauth_helper.c
37
@@ -XXX,XX +XXX,XX @@ static uint64_t pauth_auth(CPUARMState *env, uint64_t ptr, uint64_t modifier,
38
if (unlikely(extract64(test, bot_bit, top_bit - bot_bit))) {
39
int error_code = (keynumber << 1) | (keynumber ^ 1);
40
if (param.tbi) {
41
- return deposit64(ptr, 53, 2, error_code);
42
+ return deposit64(orig_ptr, 53, 2, error_code);
43
} else {
44
- return deposit64(ptr, 61, 2, error_code);
45
+ return deposit64(orig_ptr, 61, 2, error_code);
46
}
47
}
48
return orig_ptr;
49
diff --git a/tests/tcg/aarch64/pauth-2.c b/tests/tcg/aarch64/pauth-2.c
50
new file mode 100644
51
index XXXXXXX..XXXXXXX
52
--- /dev/null
53
+++ b/tests/tcg/aarch64/pauth-2.c
54
@@ -XXX,XX +XXX,XX @@
55
+#include <stdint.h>
56
+#include <assert.h>
57
+
58
+asm(".arch armv8.4-a");
59
+
60
+void do_test(uint64_t value)
61
+{
62
+ uint64_t salt1, salt2;
63
+ uint64_t encode, decode;
64
+
65
+ /*
66
+ * With TBI enabled and a 48-bit VA, there are 7 bits of auth,
67
+ * and so a 1/128 chance of encode = pac(value,key,salt) producing
68
+ * an auth for which leaves value unchanged.
69
+ * Iterate until we find a salt for which encode != value.
70
+ */
71
+ for (salt1 = 1; ; salt1++) {
72
+ asm volatile("pacda %0, %2" : "=r"(encode) : "0"(value), "r"(salt1));
73
+ if (encode != value) {
74
+ break;
75
+ }
76
+ }
77
+
78
+ /* A valid salt must produce a valid authorization. */
79
+ asm volatile("autda %0, %2" : "=r"(decode) : "0"(encode), "r"(salt1));
80
+ assert(decode == value);
81
+
82
+ /*
83
+ * An invalid salt usually fails authorization, but again there
84
+ * is a chance of choosing another salt that works.
85
+ * Iterate until we find another salt which does fail.
86
+ */
87
+ for (salt2 = salt1 + 1; ; salt2++) {
88
+ asm volatile("autda %0, %2" : "=r"(decode) : "0"(encode), "r"(salt2));
89
+ if (decode != value) {
90
+ break;
91
+ }
92
+ }
93
+
94
+ /* The VA bits, bit 55, and the TBI bits, should be unchanged. */
95
+ assert(((decode ^ value) & 0xff80ffffffffffffull) == 0);
96
+
97
+ /*
98
+ * Bits [54:53] are an error indicator based on the key used;
99
+ * the DA key above is keynumber 0, so error == 0b01. Otherwise
100
+ * bit 55 of the original is sign-extended into the rest of the auth.
101
+ */
102
+ if ((value >> 55) & 1) {
103
+ assert(((decode >> 48) & 0xff) == 0b10111111);
104
+ } else {
105
+ assert(((decode >> 48) & 0xff) == 0b00100000);
106
+ }
107
+}
108
+
109
+int main()
110
+{
111
+ do_test(0);
112
+ do_test(-1);
113
+ do_test(0xda004acedeadbeefull);
114
+ return 0;
115
+}
116
--
30
--
117
2.20.1
31
2.25.1
118
119
diff view generated by jsdifflib
1
Convert the VCVTT, VCVTB instructions that deal with conversion
1
From: Hao Wu <wuhaotsh@google.com>
2
from half-precision floats to f32 or 64 to decodetree.
3
2
4
Since we're no longer constrained to the old decoder's style
3
Similar to the Aspeed code in include/misc/aspeed_scu.h, we define
5
using cpu_F0s and cpu_F0d we can perform a direct 16 bit
4
the PWRON STRAP fields in their corresponding module for NPCM7XX.
6
load of the right half of the input single-precision register
7
rather than loading the full 32 bits and then doing a
8
separate shift or sign-extension.
9
5
6
Signed-off-by: Hao Wu <wuhaotsh@google.com>
7
Reviewed-by: Patrick Venture <venture@google.com>
8
Message-id: 20220411165842.3912945-2-wuhaotsh@google.com
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
11
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
12
---
11
---
13
target/arm/translate-vfp.inc.c | 82 ++++++++++++++++++++++++++++++++++
12
include/hw/misc/npcm7xx_gcr.h | 30 ++++++++++++++++++++++++++++++
14
target/arm/translate.c | 56 +----------------------
13
1 file changed, 30 insertions(+)
15
target/arm/vfp.decode | 6 +++
16
3 files changed, 89 insertions(+), 55 deletions(-)
17
14
18
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
15
diff --git a/include/hw/misc/npcm7xx_gcr.h b/include/hw/misc/npcm7xx_gcr.h
19
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
20
--- a/target/arm/translate-vfp.inc.c
17
--- a/include/hw/misc/npcm7xx_gcr.h
21
+++ b/target/arm/translate-vfp.inc.c
18
+++ b/include/hw/misc/npcm7xx_gcr.h
22
@@ -XXX,XX +XXX,XX @@
19
@@ -XXX,XX +XXX,XX @@
23
#include "decode-vfp.inc.c"
20
#include "exec/memory.h"
24
#include "decode-vfp-uncond.inc.c"
21
#include "hw/sysbus.h"
25
22
26
+/*
23
+/*
27
+ * Return the offset of a 16-bit half of the specified VFP single-precision
24
+ * NPCM7XX PWRON STRAP bit fields
28
+ * register. If top is true, returns the top 16 bits; otherwise the bottom
25
+ * 12: SPI0 powered by VSBV3 at 1.8V
29
+ * 16 bits.
26
+ * 11: System flash attached to BMC
27
+ * 10: BSP alternative pins.
28
+ * 9:8: Flash UART command route enabled.
29
+ * 7: Security enabled.
30
+ * 6: HI-Z state control.
31
+ * 5: ECC disabled.
32
+ * 4: Reserved
33
+ * 3: JTAG2 enabled.
34
+ * 2:0: CPU and DRAM clock frequency.
30
+ */
35
+ */
31
+static inline long vfp_f16_offset(unsigned reg, bool top)
36
+#define NPCM7XX_PWRON_STRAP_SPI0F18 BIT(12)
32
+{
37
+#define NPCM7XX_PWRON_STRAP_SFAB BIT(11)
33
+ long offs = vfp_reg_offset(false, reg);
38
+#define NPCM7XX_PWRON_STRAP_BSPA BIT(10)
34
+#ifdef HOST_WORDS_BIGENDIAN
39
+#define NPCM7XX_PWRON_STRAP_FUP(x) ((x) << 8)
35
+ if (!top) {
40
+#define FUP_NORM_UART2 3
36
+ offs += 2;
41
+#define FUP_PROG_UART3 2
37
+ }
42
+#define FUP_PROG_UART2 1
38
+#else
43
+#define FUP_NORM_UART3 0
39
+ if (top) {
44
+#define NPCM7XX_PWRON_STRAP_SECEN BIT(7)
40
+ offs += 2;
45
+#define NPCM7XX_PWRON_STRAP_HIZ BIT(6)
41
+ }
46
+#define NPCM7XX_PWRON_STRAP_ECC BIT(5)
42
+#endif
47
+#define NPCM7XX_PWRON_STRAP_RESERVE1 BIT(4)
43
+ return offs;
48
+#define NPCM7XX_PWRON_STRAP_J2EN BIT(3)
44
+}
49
+#define NPCM7XX_PWRON_STRAP_CKFRQ(x) (x)
50
+#define CKFRQ_SKIPINIT 0x000
51
+#define CKFRQ_DEFAULT 0x111
45
+
52
+
46
/*
53
/*
47
* Check that VFP access is enabled. If it is, do the necessary
54
* Number of registers in our device state structure. Don't change this without
48
* M-profile lazy-FP handling and then return true.
55
* incrementing the version_id in the vmstate.
49
@@ -XXX,XX +XXX,XX @@ static bool trans_VCMP_dp(DisasContext *s, arg_VCMP_dp *a)
50
51
return true;
52
}
53
+
54
+static bool trans_VCVT_f32_f16(DisasContext *s, arg_VCVT_f32_f16 *a)
55
+{
56
+ TCGv_ptr fpst;
57
+ TCGv_i32 ahp_mode;
58
+ TCGv_i32 tmp;
59
+
60
+ if (!dc_isar_feature(aa32_fp16_spconv, s)) {
61
+ return false;
62
+ }
63
+
64
+ if (!vfp_access_check(s)) {
65
+ return true;
66
+ }
67
+
68
+ fpst = get_fpstatus_ptr(false);
69
+ ahp_mode = get_ahp_flag();
70
+ tmp = tcg_temp_new_i32();
71
+ /* The T bit tells us if we want the low or high 16 bits of Vm */
72
+ tcg_gen_ld16u_i32(tmp, cpu_env, vfp_f16_offset(a->vm, a->t));
73
+ gen_helper_vfp_fcvt_f16_to_f32(tmp, tmp, fpst, ahp_mode);
74
+ neon_store_reg32(tmp, a->vd);
75
+ tcg_temp_free_i32(ahp_mode);
76
+ tcg_temp_free_ptr(fpst);
77
+ tcg_temp_free_i32(tmp);
78
+ return true;
79
+}
80
+
81
+static bool trans_VCVT_f64_f16(DisasContext *s, arg_VCVT_f64_f16 *a)
82
+{
83
+ TCGv_ptr fpst;
84
+ TCGv_i32 ahp_mode;
85
+ TCGv_i32 tmp;
86
+ TCGv_i64 vd;
87
+
88
+ if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
89
+ return false;
90
+ }
91
+
92
+ /* UNDEF accesses to D16-D31 if they don't exist. */
93
+ if (!dc_isar_feature(aa32_fp_d32, s) && (a->vd & 0x10)) {
94
+ return false;
95
+ }
96
+
97
+ if (!vfp_access_check(s)) {
98
+ return true;
99
+ }
100
+
101
+ fpst = get_fpstatus_ptr(false);
102
+ ahp_mode = get_ahp_flag();
103
+ tmp = tcg_temp_new_i32();
104
+ /* The T bit tells us if we want the low or high 16 bits of Vm */
105
+ tcg_gen_ld16u_i32(tmp, cpu_env, vfp_f16_offset(a->vm, a->t));
106
+ vd = tcg_temp_new_i64();
107
+ gen_helper_vfp_fcvt_f16_to_f64(vd, tmp, fpst, ahp_mode);
108
+ neon_store_reg64(vd, a->vd);
109
+ tcg_temp_free_i32(ahp_mode);
110
+ tcg_temp_free_ptr(fpst);
111
+ tcg_temp_free_i32(tmp);
112
+ tcg_temp_free_i64(vd);
113
+ return true;
114
+}
115
diff --git a/target/arm/translate.c b/target/arm/translate.c
116
index XXXXXXX..XXXXXXX 100644
117
--- a/target/arm/translate.c
118
+++ b/target/arm/translate.c
119
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
120
return 1;
121
case 15:
122
switch (rn) {
123
- case 0 ... 3:
124
+ case 0 ... 5:
125
case 8 ... 11:
126
/* Already handled by decodetree */
127
return 1;
128
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
129
if (op == 15) {
130
/* rn is opcode, encoded as per VFP_SREG_N. */
131
switch (rn) {
132
- case 0x04: /* vcvtb.f64.f16, vcvtb.f32.f16 */
133
- case 0x05: /* vcvtt.f64.f16, vcvtt.f32.f16 */
134
- /*
135
- * VCVTB, VCVTT: only present with the halfprec extension
136
- * UNPREDICTABLE if bit 8 is set prior to ARMv8
137
- * (we choose to UNDEF)
138
- */
139
- if (dp) {
140
- if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
141
- return 1;
142
- }
143
- } else {
144
- if (!dc_isar_feature(aa32_fp16_spconv, s)) {
145
- return 1;
146
- }
147
- }
148
- rm_is_dp = false;
149
- break;
150
case 0x06: /* vcvtb.f16.f32, vcvtb.f16.f64 */
151
case 0x07: /* vcvtt.f16.f32, vcvtt.f16.f64 */
152
if (dp) {
153
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
154
switch (op) {
155
case 15: /* extension space */
156
switch (rn) {
157
- case 4: /* vcvtb.f32.f16, vcvtb.f64.f16 */
158
- {
159
- TCGv_ptr fpst = get_fpstatus_ptr(false);
160
- TCGv_i32 ahp_mode = get_ahp_flag();
161
- tmp = gen_vfp_mrs();
162
- tcg_gen_ext16u_i32(tmp, tmp);
163
- if (dp) {
164
- gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
165
- fpst, ahp_mode);
166
- } else {
167
- gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
168
- fpst, ahp_mode);
169
- }
170
- tcg_temp_free_i32(ahp_mode);
171
- tcg_temp_free_ptr(fpst);
172
- tcg_temp_free_i32(tmp);
173
- break;
174
- }
175
- case 5: /* vcvtt.f32.f16, vcvtt.f64.f16 */
176
- {
177
- TCGv_ptr fpst = get_fpstatus_ptr(false);
178
- TCGv_i32 ahp = get_ahp_flag();
179
- tmp = gen_vfp_mrs();
180
- tcg_gen_shri_i32(tmp, tmp, 16);
181
- if (dp) {
182
- gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
183
- fpst, ahp);
184
- } else {
185
- gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
186
- fpst, ahp);
187
- }
188
- tcg_temp_free_i32(tmp);
189
- tcg_temp_free_i32(ahp);
190
- tcg_temp_free_ptr(fpst);
191
- break;
192
- }
193
case 6: /* vcvtb.f16.f32, vcvtb.f16.f64 */
194
{
195
TCGv_ptr fpst = get_fpstatus_ptr(false);
196
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
197
index XXXXXXX..XXXXXXX 100644
198
--- a/target/arm/vfp.decode
199
+++ b/target/arm/vfp.decode
200
@@ -XXX,XX +XXX,XX @@ VCMP_sp ---- 1110 1.11 010 z:1 .... 1010 e:1 1.0 .... \
201
vd=%vd_sp vm=%vm_sp
202
VCMP_dp ---- 1110 1.11 010 z:1 .... 1011 e:1 1.0 .... \
203
vd=%vd_dp vm=%vm_dp
204
+
205
+# VCVTT and VCVTB from f16: Vd format depends on size bit; Vm is always vm_sp
206
+VCVT_f32_f16 ---- 1110 1.11 0010 .... 1010 t:1 1.0 .... \
207
+ vd=%vd_sp vm=%vm_sp
208
+VCVT_f64_f16 ---- 1110 1.11 0010 .... 1011 t:1 1.0 .... \
209
+ vd=%vd_dp vm=%vm_sp
210
--
56
--
211
2.20.1
57
2.25.1
212
213
diff view generated by jsdifflib
1
From: Richard Henderson <richard.henderson@linaro.org>
1
From: Hao Wu <wuhaotsh@google.com>
2
2
3
These instructions shift left or right depending on the sign
3
This patch uses the defined fields to describe PWRON STRAPs for
4
of the input, and 7 bits are significant to the shift. This
4
better readability.
5
requires several masks and selects in addition to the actual
6
shifts to form the complete answer.
7
5
8
That said, the operation is still a small improvement even for
6
Signed-off-by: Hao Wu <wuhaotsh@google.com>
9
two 64-bit elements -- 13 vector operations instead of 2 * 7
7
Reviewed-by: Patrick Venture <venture@google.com>
10
integer operations.
8
Message-id: 20220411165842.3912945-3-wuhaotsh@google.com
11
12
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
13
Message-id: 20190603232209.20704-1-richard.henderson@linaro.org
14
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
10
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
---
11
---
17
target/arm/helper.h | 11 +-
12
hw/arm/npcm7xx_boards.c | 24 +++++++++++++++++++-----
18
target/arm/translate.h | 6 +
13
1 file changed, 19 insertions(+), 5 deletions(-)
19
target/arm/neon_helper.c | 33 ----
20
target/arm/translate-a64.c | 18 +--
21
target/arm/translate.c | 300 +++++++++++++++++++++++++++++++++++--
22
target/arm/vec_helper.c | 88 +++++++++++
23
6 files changed, 390 insertions(+), 66 deletions(-)
24
14
25
diff --git a/target/arm/helper.h b/target/arm/helper.h
15
diff --git a/hw/arm/npcm7xx_boards.c b/hw/arm/npcm7xx_boards.c
26
index XXXXXXX..XXXXXXX 100644
16
index XXXXXXX..XXXXXXX 100644
27
--- a/target/arm/helper.h
17
--- a/hw/arm/npcm7xx_boards.c
28
+++ b/target/arm/helper.h
18
+++ b/hw/arm/npcm7xx_boards.c
29
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_2(neon_abd_s16, i32, i32, i32)
19
@@ -XXX,XX +XXX,XX @@
30
DEF_HELPER_2(neon_abd_u32, i32, i32, i32)
20
#include "sysemu/sysemu.h"
31
DEF_HELPER_2(neon_abd_s32, i32, i32, i32)
21
#include "sysemu/block-backend.h"
32
22
33
-DEF_HELPER_2(neon_shl_u8, i32, i32, i32)
23
-#define NPCM750_EVB_POWER_ON_STRAPS 0x00001ff7
34
-DEF_HELPER_2(neon_shl_s8, i32, i32, i32)
24
-#define QUANTA_GSJ_POWER_ON_STRAPS 0x00001fff
35
DEF_HELPER_2(neon_shl_u16, i32, i32, i32)
25
-#define QUANTA_GBS_POWER_ON_STRAPS 0x000017ff
36
DEF_HELPER_2(neon_shl_s16, i32, i32, i32)
26
-#define KUDO_BMC_POWER_ON_STRAPS 0x00001fff
37
-DEF_HELPER_2(neon_shl_u32, i32, i32, i32)
27
-#define MORI_BMC_POWER_ON_STRAPS 0x00001fff
38
-DEF_HELPER_2(neon_shl_s32, i32, i32, i32)
28
+#define NPCM7XX_POWER_ON_STRAPS_DEFAULT ( \
39
-DEF_HELPER_2(neon_shl_u64, i64, i64, i64)
29
+ NPCM7XX_PWRON_STRAP_SPI0F18 | \
40
-DEF_HELPER_2(neon_shl_s64, i64, i64, i64)
30
+ NPCM7XX_PWRON_STRAP_SFAB | \
41
DEF_HELPER_2(neon_rshl_u8, i32, i32, i32)
31
+ NPCM7XX_PWRON_STRAP_BSPA | \
42
DEF_HELPER_2(neon_rshl_s8, i32, i32, i32)
32
+ NPCM7XX_PWRON_STRAP_FUP(FUP_NORM_UART2) | \
43
DEF_HELPER_2(neon_rshl_u16, i32, i32, i32)
33
+ NPCM7XX_PWRON_STRAP_SECEN | \
44
@@ -XXX,XX +XXX,XX @@ DEF_HELPER_FLAGS_2(frint64_s, TCG_CALL_NO_RWG, f32, f32, ptr)
34
+ NPCM7XX_PWRON_STRAP_HIZ | \
45
DEF_HELPER_FLAGS_2(frint32_d, TCG_CALL_NO_RWG, f64, f64, ptr)
35
+ NPCM7XX_PWRON_STRAP_ECC | \
46
DEF_HELPER_FLAGS_2(frint64_d, TCG_CALL_NO_RWG, f64, f64, ptr)
36
+ NPCM7XX_PWRON_STRAP_RESERVE1 | \
47
37
+ NPCM7XX_PWRON_STRAP_J2EN | \
48
+DEF_HELPER_FLAGS_4(gvec_sshl_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
38
+ NPCM7XX_PWRON_STRAP_CKFRQ(CKFRQ_DEFAULT))
49
+DEF_HELPER_FLAGS_4(gvec_sshl_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
50
+DEF_HELPER_FLAGS_4(gvec_ushl_b, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
51
+DEF_HELPER_FLAGS_4(gvec_ushl_h, TCG_CALL_NO_RWG, void, ptr, ptr, ptr, i32)
52
+
39
+
53
#ifdef TARGET_AARCH64
40
+#define NPCM750_EVB_POWER_ON_STRAPS ( \
54
#include "helper-a64.h"
41
+ NPCM7XX_POWER_ON_STRAPS_DEFAULT & ~NPCM7XX_PWRON_STRAP_J2EN)
55
#include "helper-sve.h"
42
+#define QUANTA_GSJ_POWER_ON_STRAPS NPCM7XX_POWER_ON_STRAPS_DEFAULT
56
diff --git a/target/arm/translate.h b/target/arm/translate.h
43
+#define QUANTA_GBS_POWER_ON_STRAPS ( \
57
index XXXXXXX..XXXXXXX 100644
44
+ NPCM7XX_POWER_ON_STRAPS_DEFAULT & ~NPCM7XX_PWRON_STRAP_SFAB)
58
--- a/target/arm/translate.h
45
+#define KUDO_BMC_POWER_ON_STRAPS NPCM7XX_POWER_ON_STRAPS_DEFAULT
59
+++ b/target/arm/translate.h
46
+#define MORI_BMC_POWER_ON_STRAPS NPCM7XX_POWER_ON_STRAPS_DEFAULT
60
@@ -XXX,XX +XXX,XX @@ extern const GVecGen3 bif_op;
47
61
extern const GVecGen3 mla_op[4];
48
static const char npcm7xx_default_bootrom[] = "npcm7xx_bootrom.bin";
62
extern const GVecGen3 mls_op[4];
49
63
extern const GVecGen3 cmtst_op[4];
64
+extern const GVecGen3 sshl_op[4];
65
+extern const GVecGen3 ushl_op[4];
66
extern const GVecGen2i ssra_op[4];
67
extern const GVecGen2i usra_op[4];
68
extern const GVecGen2i sri_op[4];
69
@@ -XXX,XX +XXX,XX @@ extern const GVecGen4 sqadd_op[4];
70
extern const GVecGen4 uqsub_op[4];
71
extern const GVecGen4 sqsub_op[4];
72
void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
73
+void gen_ushl_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
74
+void gen_sshl_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
75
+void gen_ushl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
76
+void gen_sshl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
77
78
/*
79
* Forward to the isar_feature_* tests given a DisasContext pointer.
80
diff --git a/target/arm/neon_helper.c b/target/arm/neon_helper.c
81
index XXXXXXX..XXXXXXX 100644
82
--- a/target/arm/neon_helper.c
83
+++ b/target/arm/neon_helper.c
84
@@ -XXX,XX +XXX,XX @@ NEON_VOP(abd_u32, neon_u32, 1)
85
} else { \
86
dest = src1 << tmp; \
87
}} while (0)
88
-NEON_VOP(shl_u8, neon_u8, 4)
89
NEON_VOP(shl_u16, neon_u16, 2)
90
-NEON_VOP(shl_u32, neon_u32, 1)
91
#undef NEON_FN
92
93
-uint64_t HELPER(neon_shl_u64)(uint64_t val, uint64_t shiftop)
94
-{
95
- int8_t shift = (int8_t)shiftop;
96
- if (shift >= 64 || shift <= -64) {
97
- val = 0;
98
- } else if (shift < 0) {
99
- val >>= -shift;
100
- } else {
101
- val <<= shift;
102
- }
103
- return val;
104
-}
105
-
106
#define NEON_FN(dest, src1, src2) do { \
107
int8_t tmp; \
108
tmp = (int8_t)src2; \
109
@@ -XXX,XX +XXX,XX @@ uint64_t HELPER(neon_shl_u64)(uint64_t val, uint64_t shiftop)
110
} else { \
111
dest = src1 << tmp; \
112
}} while (0)
113
-NEON_VOP(shl_s8, neon_s8, 4)
114
NEON_VOP(shl_s16, neon_s16, 2)
115
-NEON_VOP(shl_s32, neon_s32, 1)
116
#undef NEON_FN
117
118
-uint64_t HELPER(neon_shl_s64)(uint64_t valop, uint64_t shiftop)
119
-{
120
- int8_t shift = (int8_t)shiftop;
121
- int64_t val = valop;
122
- if (shift >= 64) {
123
- val = 0;
124
- } else if (shift <= -64) {
125
- val >>= 63;
126
- } else if (shift < 0) {
127
- val >>= -shift;
128
- } else {
129
- val <<= shift;
130
- }
131
- return val;
132
-}
133
-
134
#define NEON_FN(dest, src1, src2) do { \
135
int8_t tmp; \
136
tmp = (int8_t)src2; \
137
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
138
index XXXXXXX..XXXXXXX 100644
139
--- a/target/arm/translate-a64.c
140
+++ b/target/arm/translate-a64.c
141
@@ -XXX,XX +XXX,XX @@ static void handle_3same_64(DisasContext *s, int opcode, bool u,
142
break;
143
case 0x8: /* SSHL, USHL */
144
if (u) {
145
- gen_helper_neon_shl_u64(tcg_rd, tcg_rn, tcg_rm);
146
+ gen_ushl_i64(tcg_rd, tcg_rn, tcg_rm);
147
} else {
148
- gen_helper_neon_shl_s64(tcg_rd, tcg_rn, tcg_rm);
149
+ gen_sshl_i64(tcg_rd, tcg_rn, tcg_rm);
150
}
151
break;
152
case 0x9: /* SQSHL, UQSHL */
153
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
154
is_q ? 16 : 8, vec_full_reg_size(s),
155
(u ? uqsub_op : sqsub_op) + size);
156
return;
157
+ case 0x08: /* SSHL, USHL */
158
+ gen_gvec_op3(s, is_q, rd, rn, rm,
159
+ u ? &ushl_op[size] : &sshl_op[size]);
160
+ return;
161
case 0x0c: /* SMAX, UMAX */
162
if (u) {
163
gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_umax, size);
164
@@ -XXX,XX +XXX,XX @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
165
genfn = fns[size][u];
166
break;
167
}
168
- case 0x8: /* SSHL, USHL */
169
- {
170
- static NeonGenTwoOpFn * const fns[3][2] = {
171
- { gen_helper_neon_shl_s8, gen_helper_neon_shl_u8 },
172
- { gen_helper_neon_shl_s16, gen_helper_neon_shl_u16 },
173
- { gen_helper_neon_shl_s32, gen_helper_neon_shl_u32 },
174
- };
175
- genfn = fns[size][u];
176
- break;
177
- }
178
case 0x9: /* SQSHL, UQSHL */
179
{
180
static NeonGenTwoOpEnvFn * const fns[3][2] = {
181
diff --git a/target/arm/translate.c b/target/arm/translate.c
182
index XXXXXXX..XXXXXXX 100644
183
--- a/target/arm/translate.c
184
+++ b/target/arm/translate.c
185
@@ -XXX,XX +XXX,XX @@ static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
186
if (u) {
187
switch (size) {
188
case 1: gen_helper_neon_shl_u16(var, var, shift); break;
189
- case 2: gen_helper_neon_shl_u32(var, var, shift); break;
190
+ case 2: gen_ushl_i32(var, var, shift); break;
191
default: abort();
192
}
193
} else {
194
switch (size) {
195
case 1: gen_helper_neon_shl_s16(var, var, shift); break;
196
- case 2: gen_helper_neon_shl_s32(var, var, shift); break;
197
+ case 2: gen_sshl_i32(var, var, shift); break;
198
default: abort();
199
}
200
}
201
@@ -XXX,XX +XXX,XX @@ const GVecGen3 cmtst_op[4] = {
202
.vece = MO_64 },
203
};
204
205
+void gen_ushl_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
206
+{
207
+ TCGv_i32 lval = tcg_temp_new_i32();
208
+ TCGv_i32 rval = tcg_temp_new_i32();
209
+ TCGv_i32 lsh = tcg_temp_new_i32();
210
+ TCGv_i32 rsh = tcg_temp_new_i32();
211
+ TCGv_i32 zero = tcg_const_i32(0);
212
+ TCGv_i32 max = tcg_const_i32(32);
213
+
214
+ /*
215
+ * Rely on the TCG guarantee that out of range shifts produce
216
+ * unspecified results, not undefined behaviour (i.e. no trap).
217
+ * Discard out-of-range results after the fact.
218
+ */
219
+ tcg_gen_ext8s_i32(lsh, b);
220
+ tcg_gen_neg_i32(rsh, lsh);
221
+ tcg_gen_shl_i32(lval, a, lsh);
222
+ tcg_gen_shr_i32(rval, a, rsh);
223
+ tcg_gen_movcond_i32(TCG_COND_LTU, d, lsh, max, lval, zero);
224
+ tcg_gen_movcond_i32(TCG_COND_LTU, d, rsh, max, rval, d);
225
+
226
+ tcg_temp_free_i32(lval);
227
+ tcg_temp_free_i32(rval);
228
+ tcg_temp_free_i32(lsh);
229
+ tcg_temp_free_i32(rsh);
230
+ tcg_temp_free_i32(zero);
231
+ tcg_temp_free_i32(max);
232
+}
233
+
234
+void gen_ushl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
235
+{
236
+ TCGv_i64 lval = tcg_temp_new_i64();
237
+ TCGv_i64 rval = tcg_temp_new_i64();
238
+ TCGv_i64 lsh = tcg_temp_new_i64();
239
+ TCGv_i64 rsh = tcg_temp_new_i64();
240
+ TCGv_i64 zero = tcg_const_i64(0);
241
+ TCGv_i64 max = tcg_const_i64(64);
242
+
243
+ /*
244
+ * Rely on the TCG guarantee that out of range shifts produce
245
+ * unspecified results, not undefined behaviour (i.e. no trap).
246
+ * Discard out-of-range results after the fact.
247
+ */
248
+ tcg_gen_ext8s_i64(lsh, b);
249
+ tcg_gen_neg_i64(rsh, lsh);
250
+ tcg_gen_shl_i64(lval, a, lsh);
251
+ tcg_gen_shr_i64(rval, a, rsh);
252
+ tcg_gen_movcond_i64(TCG_COND_LTU, d, lsh, max, lval, zero);
253
+ tcg_gen_movcond_i64(TCG_COND_LTU, d, rsh, max, rval, d);
254
+
255
+ tcg_temp_free_i64(lval);
256
+ tcg_temp_free_i64(rval);
257
+ tcg_temp_free_i64(lsh);
258
+ tcg_temp_free_i64(rsh);
259
+ tcg_temp_free_i64(zero);
260
+ tcg_temp_free_i64(max);
261
+}
262
+
263
+static void gen_ushl_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
264
+{
265
+ TCGv_vec lval = tcg_temp_new_vec_matching(d);
266
+ TCGv_vec rval = tcg_temp_new_vec_matching(d);
267
+ TCGv_vec lsh = tcg_temp_new_vec_matching(d);
268
+ TCGv_vec rsh = tcg_temp_new_vec_matching(d);
269
+ TCGv_vec msk, max;
270
+
271
+ /*
272
+ * Rely on the TCG guarantee that out of range shifts produce
273
+ * unspecified results, not undefined behaviour (i.e. no trap).
274
+ * Discard out-of-range results after the fact.
275
+ */
276
+ tcg_gen_neg_vec(vece, rsh, b);
277
+ if (vece == MO_8) {
278
+ tcg_gen_mov_vec(lsh, b);
279
+ } else {
280
+ msk = tcg_temp_new_vec_matching(d);
281
+ tcg_gen_dupi_vec(vece, msk, 0xff);
282
+ tcg_gen_and_vec(vece, lsh, b, msk);
283
+ tcg_gen_and_vec(vece, rsh, rsh, msk);
284
+ tcg_temp_free_vec(msk);
285
+ }
286
+
287
+ /*
288
+ * Perform possibly out of range shifts, trusting that the operation
289
+ * does not trap. Discard unused results after the fact.
290
+ */
291
+ tcg_gen_shlv_vec(vece, lval, a, lsh);
292
+ tcg_gen_shrv_vec(vece, rval, a, rsh);
293
+
294
+ max = tcg_temp_new_vec_matching(d);
295
+ tcg_gen_dupi_vec(vece, max, 8 << vece);
296
+
297
+ /*
298
+ * The choice of LT (signed) and GEU (unsigned) are biased toward
299
+ * the instructions of the x86_64 host. For MO_8, the whole byte
300
+ * is significant so we must use an unsigned compare; otherwise we
301
+ * have already masked to a byte and so a signed compare works.
302
+ * Other tcg hosts have a full set of comparisons and do not care.
303
+ */
304
+ if (vece == MO_8) {
305
+ tcg_gen_cmp_vec(TCG_COND_GEU, vece, lsh, lsh, max);
306
+ tcg_gen_cmp_vec(TCG_COND_GEU, vece, rsh, rsh, max);
307
+ tcg_gen_andc_vec(vece, lval, lval, lsh);
308
+ tcg_gen_andc_vec(vece, rval, rval, rsh);
309
+ } else {
310
+ tcg_gen_cmp_vec(TCG_COND_LT, vece, lsh, lsh, max);
311
+ tcg_gen_cmp_vec(TCG_COND_LT, vece, rsh, rsh, max);
312
+ tcg_gen_and_vec(vece, lval, lval, lsh);
313
+ tcg_gen_and_vec(vece, rval, rval, rsh);
314
+ }
315
+ tcg_gen_or_vec(vece, d, lval, rval);
316
+
317
+ tcg_temp_free_vec(max);
318
+ tcg_temp_free_vec(lval);
319
+ tcg_temp_free_vec(rval);
320
+ tcg_temp_free_vec(lsh);
321
+ tcg_temp_free_vec(rsh);
322
+}
323
+
324
+static const TCGOpcode ushl_list[] = {
325
+ INDEX_op_neg_vec, INDEX_op_shlv_vec,
326
+ INDEX_op_shrv_vec, INDEX_op_cmp_vec, 0
327
+};
328
+
329
+const GVecGen3 ushl_op[4] = {
330
+ { .fniv = gen_ushl_vec,
331
+ .fno = gen_helper_gvec_ushl_b,
332
+ .opt_opc = ushl_list,
333
+ .vece = MO_8 },
334
+ { .fniv = gen_ushl_vec,
335
+ .fno = gen_helper_gvec_ushl_h,
336
+ .opt_opc = ushl_list,
337
+ .vece = MO_16 },
338
+ { .fni4 = gen_ushl_i32,
339
+ .fniv = gen_ushl_vec,
340
+ .opt_opc = ushl_list,
341
+ .vece = MO_32 },
342
+ { .fni8 = gen_ushl_i64,
343
+ .fniv = gen_ushl_vec,
344
+ .opt_opc = ushl_list,
345
+ .vece = MO_64 },
346
+};
347
+
348
+void gen_sshl_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
349
+{
350
+ TCGv_i32 lval = tcg_temp_new_i32();
351
+ TCGv_i32 rval = tcg_temp_new_i32();
352
+ TCGv_i32 lsh = tcg_temp_new_i32();
353
+ TCGv_i32 rsh = tcg_temp_new_i32();
354
+ TCGv_i32 zero = tcg_const_i32(0);
355
+ TCGv_i32 max = tcg_const_i32(31);
356
+
357
+ /*
358
+ * Rely on the TCG guarantee that out of range shifts produce
359
+ * unspecified results, not undefined behaviour (i.e. no trap).
360
+ * Discard out-of-range results after the fact.
361
+ */
362
+ tcg_gen_ext8s_i32(lsh, b);
363
+ tcg_gen_neg_i32(rsh, lsh);
364
+ tcg_gen_shl_i32(lval, a, lsh);
365
+ tcg_gen_umin_i32(rsh, rsh, max);
366
+ tcg_gen_sar_i32(rval, a, rsh);
367
+ tcg_gen_movcond_i32(TCG_COND_LEU, lval, lsh, max, lval, zero);
368
+ tcg_gen_movcond_i32(TCG_COND_LT, d, lsh, zero, rval, lval);
369
+
370
+ tcg_temp_free_i32(lval);
371
+ tcg_temp_free_i32(rval);
372
+ tcg_temp_free_i32(lsh);
373
+ tcg_temp_free_i32(rsh);
374
+ tcg_temp_free_i32(zero);
375
+ tcg_temp_free_i32(max);
376
+}
377
+
378
+void gen_sshl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
379
+{
380
+ TCGv_i64 lval = tcg_temp_new_i64();
381
+ TCGv_i64 rval = tcg_temp_new_i64();
382
+ TCGv_i64 lsh = tcg_temp_new_i64();
383
+ TCGv_i64 rsh = tcg_temp_new_i64();
384
+ TCGv_i64 zero = tcg_const_i64(0);
385
+ TCGv_i64 max = tcg_const_i64(63);
386
+
387
+ /*
388
+ * Rely on the TCG guarantee that out of range shifts produce
389
+ * unspecified results, not undefined behaviour (i.e. no trap).
390
+ * Discard out-of-range results after the fact.
391
+ */
392
+ tcg_gen_ext8s_i64(lsh, b);
393
+ tcg_gen_neg_i64(rsh, lsh);
394
+ tcg_gen_shl_i64(lval, a, lsh);
395
+ tcg_gen_umin_i64(rsh, rsh, max);
396
+ tcg_gen_sar_i64(rval, a, rsh);
397
+ tcg_gen_movcond_i64(TCG_COND_LEU, lval, lsh, max, lval, zero);
398
+ tcg_gen_movcond_i64(TCG_COND_LT, d, lsh, zero, rval, lval);
399
+
400
+ tcg_temp_free_i64(lval);
401
+ tcg_temp_free_i64(rval);
402
+ tcg_temp_free_i64(lsh);
403
+ tcg_temp_free_i64(rsh);
404
+ tcg_temp_free_i64(zero);
405
+ tcg_temp_free_i64(max);
406
+}
407
+
408
+static void gen_sshl_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
409
+{
410
+ TCGv_vec lval = tcg_temp_new_vec_matching(d);
411
+ TCGv_vec rval = tcg_temp_new_vec_matching(d);
412
+ TCGv_vec lsh = tcg_temp_new_vec_matching(d);
413
+ TCGv_vec rsh = tcg_temp_new_vec_matching(d);
414
+ TCGv_vec tmp = tcg_temp_new_vec_matching(d);
415
+
416
+ /*
417
+ * Rely on the TCG guarantee that out of range shifts produce
418
+ * unspecified results, not undefined behaviour (i.e. no trap).
419
+ * Discard out-of-range results after the fact.
420
+ */
421
+ tcg_gen_neg_vec(vece, rsh, b);
422
+ if (vece == MO_8) {
423
+ tcg_gen_mov_vec(lsh, b);
424
+ } else {
425
+ tcg_gen_dupi_vec(vece, tmp, 0xff);
426
+ tcg_gen_and_vec(vece, lsh, b, tmp);
427
+ tcg_gen_and_vec(vece, rsh, rsh, tmp);
428
+ }
429
+
430
+ /* Bound rsh so out of bound right shift gets -1. */
431
+ tcg_gen_dupi_vec(vece, tmp, (8 << vece) - 1);
432
+ tcg_gen_umin_vec(vece, rsh, rsh, tmp);
433
+ tcg_gen_cmp_vec(TCG_COND_GT, vece, tmp, lsh, tmp);
434
+
435
+ tcg_gen_shlv_vec(vece, lval, a, lsh);
436
+ tcg_gen_sarv_vec(vece, rval, a, rsh);
437
+
438
+ /* Select in-bound left shift. */
439
+ tcg_gen_andc_vec(vece, lval, lval, tmp);
440
+
441
+ /* Select between left and right shift. */
442
+ if (vece == MO_8) {
443
+ tcg_gen_dupi_vec(vece, tmp, 0);
444
+ tcg_gen_cmpsel_vec(TCG_COND_LT, vece, d, lsh, tmp, rval, lval);
445
+ } else {
446
+ tcg_gen_dupi_vec(vece, tmp, 0x80);
447
+ tcg_gen_cmpsel_vec(TCG_COND_LT, vece, d, lsh, tmp, lval, rval);
448
+ }
449
+
450
+ tcg_temp_free_vec(lval);
451
+ tcg_temp_free_vec(rval);
452
+ tcg_temp_free_vec(lsh);
453
+ tcg_temp_free_vec(rsh);
454
+ tcg_temp_free_vec(tmp);
455
+}
456
+
457
+static const TCGOpcode sshl_list[] = {
458
+ INDEX_op_neg_vec, INDEX_op_umin_vec, INDEX_op_shlv_vec,
459
+ INDEX_op_sarv_vec, INDEX_op_cmp_vec, INDEX_op_cmpsel_vec, 0
460
+};
461
+
462
+const GVecGen3 sshl_op[4] = {
463
+ { .fniv = gen_sshl_vec,
464
+ .fno = gen_helper_gvec_sshl_b,
465
+ .opt_opc = sshl_list,
466
+ .vece = MO_8 },
467
+ { .fniv = gen_sshl_vec,
468
+ .fno = gen_helper_gvec_sshl_h,
469
+ .opt_opc = sshl_list,
470
+ .vece = MO_16 },
471
+ { .fni4 = gen_sshl_i32,
472
+ .fniv = gen_sshl_vec,
473
+ .opt_opc = sshl_list,
474
+ .vece = MO_32 },
475
+ { .fni8 = gen_sshl_i64,
476
+ .fniv = gen_sshl_vec,
477
+ .opt_opc = sshl_list,
478
+ .vece = MO_64 },
479
+};
480
+
481
static void gen_uqadd_vec(unsigned vece, TCGv_vec t, TCGv_vec sat,
482
TCGv_vec a, TCGv_vec b)
483
{
484
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
485
vec_size, vec_size);
486
}
487
return 0;
488
+
489
+ case NEON_3R_VSHL:
490
+ tcg_gen_gvec_3(rd_ofs, rn_ofs, rm_ofs, vec_size, vec_size,
491
+ u ? &ushl_op[size] : &sshl_op[size]);
492
+ return 0;
493
}
494
495
if (size == 3) {
496
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
497
neon_load_reg64(cpu_V0, rn + pass);
498
neon_load_reg64(cpu_V1, rm + pass);
499
switch (op) {
500
- case NEON_3R_VSHL:
501
- if (u) {
502
- gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
503
- } else {
504
- gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
505
- }
506
- break;
507
case NEON_3R_VQSHL:
508
if (u) {
509
gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
510
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
511
}
512
pairwise = 0;
513
switch (op) {
514
- case NEON_3R_VSHL:
515
case NEON_3R_VQSHL:
516
case NEON_3R_VRSHL:
517
case NEON_3R_VQRSHL:
518
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
519
case NEON_3R_VHSUB:
520
GEN_NEON_INTEGER_OP(hsub);
521
break;
522
- case NEON_3R_VSHL:
523
- GEN_NEON_INTEGER_OP(shl);
524
- break;
525
case NEON_3R_VQSHL:
526
GEN_NEON_INTEGER_OP_ENV(qshl);
527
break;
528
@@ -XXX,XX +XXX,XX @@ static int disas_neon_data_insn(DisasContext *s, uint32_t insn)
529
}
530
} else {
531
if (input_unsigned) {
532
- gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
533
+ gen_ushl_i64(cpu_V0, in, tmp64);
534
} else {
535
- gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
536
+ gen_sshl_i64(cpu_V0, in, tmp64);
537
}
538
}
539
tmp = tcg_temp_new_i32();
540
diff --git a/target/arm/vec_helper.c b/target/arm/vec_helper.c
541
index XXXXXXX..XXXXXXX 100644
542
--- a/target/arm/vec_helper.c
543
+++ b/target/arm/vec_helper.c
544
@@ -XXX,XX +XXX,XX @@ void HELPER(gvec_fmlal_idx_a64)(void *vd, void *vn, void *vm,
545
do_fmlal_idx(vd, vn, vm, &env->vfp.fp_status, desc,
546
get_flush_inputs_to_zero(&env->vfp.fp_status_f16));
547
}
548
+
549
+void HELPER(gvec_sshl_b)(void *vd, void *vn, void *vm, uint32_t desc)
550
+{
551
+ intptr_t i, opr_sz = simd_oprsz(desc);
552
+ int8_t *d = vd, *n = vn, *m = vm;
553
+
554
+ for (i = 0; i < opr_sz; ++i) {
555
+ int8_t mm = m[i];
556
+ int8_t nn = n[i];
557
+ int8_t res = 0;
558
+ if (mm >= 0) {
559
+ if (mm < 8) {
560
+ res = nn << mm;
561
+ }
562
+ } else {
563
+ res = nn >> (mm > -8 ? -mm : 7);
564
+ }
565
+ d[i] = res;
566
+ }
567
+ clear_tail(d, opr_sz, simd_maxsz(desc));
568
+}
569
+
570
+void HELPER(gvec_sshl_h)(void *vd, void *vn, void *vm, uint32_t desc)
571
+{
572
+ intptr_t i, opr_sz = simd_oprsz(desc);
573
+ int16_t *d = vd, *n = vn, *m = vm;
574
+
575
+ for (i = 0; i < opr_sz / 2; ++i) {
576
+ int8_t mm = m[i]; /* only 8 bits of shift are significant */
577
+ int16_t nn = n[i];
578
+ int16_t res = 0;
579
+ if (mm >= 0) {
580
+ if (mm < 16) {
581
+ res = nn << mm;
582
+ }
583
+ } else {
584
+ res = nn >> (mm > -16 ? -mm : 15);
585
+ }
586
+ d[i] = res;
587
+ }
588
+ clear_tail(d, opr_sz, simd_maxsz(desc));
589
+}
590
+
591
+void HELPER(gvec_ushl_b)(void *vd, void *vn, void *vm, uint32_t desc)
592
+{
593
+ intptr_t i, opr_sz = simd_oprsz(desc);
594
+ uint8_t *d = vd, *n = vn, *m = vm;
595
+
596
+ for (i = 0; i < opr_sz; ++i) {
597
+ int8_t mm = m[i];
598
+ uint8_t nn = n[i];
599
+ uint8_t res = 0;
600
+ if (mm >= 0) {
601
+ if (mm < 8) {
602
+ res = nn << mm;
603
+ }
604
+ } else {
605
+ if (mm > -8) {
606
+ res = nn >> -mm;
607
+ }
608
+ }
609
+ d[i] = res;
610
+ }
611
+ clear_tail(d, opr_sz, simd_maxsz(desc));
612
+}
613
+
614
+void HELPER(gvec_ushl_h)(void *vd, void *vn, void *vm, uint32_t desc)
615
+{
616
+ intptr_t i, opr_sz = simd_oprsz(desc);
617
+ uint16_t *d = vd, *n = vn, *m = vm;
618
+
619
+ for (i = 0; i < opr_sz / 2; ++i) {
620
+ int8_t mm = m[i]; /* only 8 bits of shift are significant */
621
+ uint16_t nn = n[i];
622
+ uint16_t res = 0;
623
+ if (mm >= 0) {
624
+ if (mm < 16) {
625
+ res = nn << mm;
626
+ }
627
+ } else {
628
+ if (mm > -16) {
629
+ res = nn >> -mm;
630
+ }
631
+ }
632
+ d[i] = res;
633
+ }
634
+ clear_tail(d, opr_sz, simd_maxsz(desc));
635
+}
636
--
50
--
637
2.20.1
51
2.25.1
638
639
diff view generated by jsdifflib
Deleted patch
1
The SMMUv3 ID registers cover an area 0x30 bytes in size
2
(12 registers, 4 bytes each). We were incorrectly decoding
3
only the first 0x20 bytes.
4
1
5
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
6
Reviewed-by: Eric Auger <eric.auger@redhat.com>
7
Message-id: 20190524124829.2589-1-peter.maydell@linaro.org
8
---
9
hw/arm/smmuv3.c | 2 +-
10
1 file changed, 1 insertion(+), 1 deletion(-)
11
12
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
13
index XXXXXXX..XXXXXXX 100644
14
--- a/hw/arm/smmuv3.c
15
+++ b/hw/arm/smmuv3.c
16
@@ -XXX,XX +XXX,XX @@ static MemTxResult smmu_readl(SMMUv3State *s, hwaddr offset,
17
uint64_t *data, MemTxAttrs attrs)
18
{
19
switch (offset) {
20
- case A_IDREGS ... A_IDREGS + 0x1f:
21
+ case A_IDREGS ... A_IDREGS + 0x2f:
22
*data = smmuv3_idreg(offset - A_IDREGS);
23
return MEMTX_OK;
24
case A_IDR0 ... A_IDR5:
25
--
26
2.20.1
27
28
diff view generated by jsdifflib
Deleted patch
1
In commit 80376c3fc2c38fdd453 in 2010 we added a workaround for
2
some qbus buses not being connected to qdev devices -- if the
3
bus has no parent object then we register a reset function which
4
resets the bus on system reset (and unregister it when the
5
bus is unparented).
6
1
7
Nearly a decade later, we have now no buses in the tree which
8
are created with non-NULL parents, so we can remove the
9
workaround and instead just assert that if the bus has a NULL
10
parent then it is the main system bus.
11
12
(The absence of other parentless buses was confirmed by
13
code inspection of all the callsites of qbus_create() and
14
qbus_create_inplace() and cross-checked by 'make check'.)
15
16
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
17
Reviewed-by: Markus Armbruster <armbru@redhat.com>
18
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
19
Reviewed-by: Damien Hedde <damien.hedde@greensocs.com>
20
Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
21
Message-id: 20190523150543.22676-1-peter.maydell@linaro.org
22
---
23
hw/core/bus.c | 21 +++++++++------------
24
1 file changed, 9 insertions(+), 12 deletions(-)
25
26
diff --git a/hw/core/bus.c b/hw/core/bus.c
27
index XXXXXXX..XXXXXXX 100644
28
--- a/hw/core/bus.c
29
+++ b/hw/core/bus.c
30
@@ -XXX,XX +XXX,XX @@ static void qbus_realize(BusState *bus, DeviceState *parent, const char *name)
31
bus->parent->num_child_bus++;
32
object_property_add_child(OBJECT(bus->parent), bus->name, OBJECT(bus), NULL);
33
object_unref(OBJECT(bus));
34
- } else if (bus != sysbus_get_default()) {
35
- /* TODO: once all bus devices are qdevified,
36
- only reset handler for main_system_bus should be registered here. */
37
- qemu_register_reset(qbus_reset_all_fn, bus);
38
+ } else {
39
+ /* The only bus without a parent is the main system bus */
40
+ assert(bus == sysbus_get_default());
41
}
42
}
43
44
@@ -XXX,XX +XXX,XX @@ static void bus_unparent(Object *obj)
45
BusState *bus = BUS(obj);
46
BusChild *kid;
47
48
+ /* Only the main system bus has no parent, and that bus is never freed */
49
+ assert(bus->parent);
50
+
51
while ((kid = QTAILQ_FIRST(&bus->children)) != NULL) {
52
DeviceState *dev = kid->child;
53
object_unparent(OBJECT(dev));
54
}
55
- if (bus->parent) {
56
- QLIST_REMOVE(bus, sibling);
57
- bus->parent->num_child_bus--;
58
- bus->parent = NULL;
59
- } else {
60
- assert(bus != sysbus_get_default()); /* main_system_bus is never freed */
61
- qemu_unregister_reset(qbus_reset_all_fn, bus);
62
- }
63
+ QLIST_REMOVE(bus, sibling);
64
+ bus->parent->num_child_bus--;
65
+ bus->parent = NULL;
66
}
67
68
void qbus_create_inplace(void *bus, size_t size, const char *typename,
69
--
70
2.20.1
71
72
diff view generated by jsdifflib
Deleted patch
1
At the moment our -cpu max for AArch32 supports VFP short-vectors
2
because we always implement them, even for CPUs which should
3
not have them. The following commits are going to switch to
4
using the correct ID-register-check to enable or disable short
5
vector support, so we need to turn it on explicitly for -cpu max,
6
because Cortex-A15 doesn't implement it.
7
1
8
We don't enable this for the AArch64 -cpu max, because the v8A
9
architecture never supports short-vectors.
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
---
14
target/arm/cpu.c | 4 ++++
15
1 file changed, 4 insertions(+)
16
17
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
18
index XXXXXXX..XXXXXXX 100644
19
--- a/target/arm/cpu.c
20
+++ b/target/arm/cpu.c
21
@@ -XXX,XX +XXX,XX @@ static void arm_max_initfn(Object *obj)
22
kvm_arm_set_cpu_features_from_host(cpu);
23
} else {
24
cortex_a15_initfn(obj);
25
+
26
+ /* old-style VFP short-vector support */
27
+ cpu->isar.mvfr0 = FIELD_DP32(cpu->isar.mvfr0, MVFR0, FPSHVEC, 1);
28
+
29
#ifdef CONFIG_USER_ONLY
30
/* We don't set these in system emulation mode for the moment,
31
* since we don't correctly set (all of) the ID registers to
32
--
33
2.20.1
34
35
diff view generated by jsdifflib
Deleted patch
1
The current VFP code has two different idioms for
2
loading and storing from the VFP register file:
3
1 using the gen_mov_F0_vreg() and similar functions,
4
which load and store to a fixed set of TCG globals
5
cpu_F0s, CPU_F0d, etc
6
2 by direct calls to tcg_gen_ld_f64() and friends
7
1
8
We want to phase out idiom 1 (because the use of the
9
fixed globals is a relic of a much older version of TCG),
10
but idiom 2 is quite longwinded:
11
tcg_gen_ld_f64(tmp, cpu_env, vfp_reg_offset(true, reg))
12
requires us to specify the 64-bitness twice, once in
13
the function name and once by passing 'true' to
14
vfp_reg_offset(). There's no guard against accidentally
15
passing the wrong flag.
16
17
Instead, let's move to a convention of accessing 64-bit
18
registers via the existing neon_load_reg64() and
19
neon_store_reg64(), and provide new neon_load_reg32()
20
and neon_store_reg32() for the 32-bit equivalents.
21
22
Implement the new functions and use them in the code in
23
translate-vfp.inc.c. We will convert the rest of the VFP
24
code as we do the decodetree conversion in subsequent
25
commits.
26
27
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
28
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
29
---
30
target/arm/translate-vfp.inc.c | 40 +++++++++++++++++-----------------
31
target/arm/translate.c | 10 +++++++++
32
2 files changed, 30 insertions(+), 20 deletions(-)
33
34
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
35
index XXXXXXX..XXXXXXX 100644
36
--- a/target/arm/translate-vfp.inc.c
37
+++ b/target/arm/translate-vfp.inc.c
38
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
39
tcg_gen_ext_i32_i64(nf, cpu_NF);
40
tcg_gen_ext_i32_i64(vf, cpu_VF);
41
42
- tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
43
- tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
44
+ neon_load_reg64(frn, rn);
45
+ neon_load_reg64(frm, rm);
46
switch (a->cc) {
47
case 0: /* eq: Z */
48
tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
49
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
50
tcg_temp_free_i64(tmp);
51
break;
52
}
53
- tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
54
+ neon_store_reg64(dest, rd);
55
tcg_temp_free_i64(frn);
56
tcg_temp_free_i64(frm);
57
tcg_temp_free_i64(dest);
58
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
59
frn = tcg_temp_new_i32();
60
frm = tcg_temp_new_i32();
61
dest = tcg_temp_new_i32();
62
- tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
63
- tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
64
+ neon_load_reg32(frn, rn);
65
+ neon_load_reg32(frm, rm);
66
switch (a->cc) {
67
case 0: /* eq: Z */
68
tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
69
@@ -XXX,XX +XXX,XX @@ static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
70
tcg_temp_free_i32(tmp);
71
break;
72
}
73
- tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
74
+ neon_store_reg32(dest, rd);
75
tcg_temp_free_i32(frn);
76
tcg_temp_free_i32(frm);
77
tcg_temp_free_i32(dest);
78
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINMAXNM(DisasContext *s, arg_VMINMAXNM *a)
79
frm = tcg_temp_new_i64();
80
dest = tcg_temp_new_i64();
81
82
- tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
83
- tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
84
+ neon_load_reg64(frn, rn);
85
+ neon_load_reg64(frm, rm);
86
if (vmin) {
87
gen_helper_vfp_minnumd(dest, frn, frm, fpst);
88
} else {
89
gen_helper_vfp_maxnumd(dest, frn, frm, fpst);
90
}
91
- tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
92
+ neon_store_reg64(dest, rd);
93
tcg_temp_free_i64(frn);
94
tcg_temp_free_i64(frm);
95
tcg_temp_free_i64(dest);
96
@@ -XXX,XX +XXX,XX @@ static bool trans_VMINMAXNM(DisasContext *s, arg_VMINMAXNM *a)
97
frm = tcg_temp_new_i32();
98
dest = tcg_temp_new_i32();
99
100
- tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
101
- tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
102
+ neon_load_reg32(frn, rn);
103
+ neon_load_reg32(frm, rm);
104
if (vmin) {
105
gen_helper_vfp_minnums(dest, frn, frm, fpst);
106
} else {
107
gen_helper_vfp_maxnums(dest, frn, frm, fpst);
108
}
109
- tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
110
+ neon_store_reg32(dest, rd);
111
tcg_temp_free_i32(frn);
112
tcg_temp_free_i32(frm);
113
tcg_temp_free_i32(dest);
114
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
115
TCGv_i64 tcg_res;
116
tcg_op = tcg_temp_new_i64();
117
tcg_res = tcg_temp_new_i64();
118
- tcg_gen_ld_f64(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
119
+ neon_load_reg64(tcg_op, rm);
120
gen_helper_rintd(tcg_res, tcg_op, fpst);
121
- tcg_gen_st_f64(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
122
+ neon_store_reg64(tcg_res, rd);
123
tcg_temp_free_i64(tcg_op);
124
tcg_temp_free_i64(tcg_res);
125
} else {
126
@@ -XXX,XX +XXX,XX @@ static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
127
TCGv_i32 tcg_res;
128
tcg_op = tcg_temp_new_i32();
129
tcg_res = tcg_temp_new_i32();
130
- tcg_gen_ld_f32(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
131
+ neon_load_reg32(tcg_op, rm);
132
gen_helper_rints(tcg_res, tcg_op, fpst);
133
- tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
134
+ neon_store_reg32(tcg_res, rd);
135
tcg_temp_free_i32(tcg_op);
136
tcg_temp_free_i32(tcg_res);
137
}
138
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
139
tcg_double = tcg_temp_new_i64();
140
tcg_res = tcg_temp_new_i64();
141
tcg_tmp = tcg_temp_new_i32();
142
- tcg_gen_ld_f64(tcg_double, cpu_env, vfp_reg_offset(1, rm));
143
+ neon_load_reg64(tcg_double, rm);
144
if (is_signed) {
145
gen_helper_vfp_tosld(tcg_res, tcg_double, tcg_shift, fpst);
146
} else {
147
gen_helper_vfp_tould(tcg_res, tcg_double, tcg_shift, fpst);
148
}
149
tcg_gen_extrl_i64_i32(tcg_tmp, tcg_res);
150
- tcg_gen_st_f32(tcg_tmp, cpu_env, vfp_reg_offset(0, rd));
151
+ neon_store_reg32(tcg_tmp, rd);
152
tcg_temp_free_i32(tcg_tmp);
153
tcg_temp_free_i64(tcg_res);
154
tcg_temp_free_i64(tcg_double);
155
@@ -XXX,XX +XXX,XX @@ static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
156
TCGv_i32 tcg_single, tcg_res;
157
tcg_single = tcg_temp_new_i32();
158
tcg_res = tcg_temp_new_i32();
159
- tcg_gen_ld_f32(tcg_single, cpu_env, vfp_reg_offset(0, rm));
160
+ neon_load_reg32(tcg_single, rm);
161
if (is_signed) {
162
gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
163
} else {
164
gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
165
}
166
- tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(0, rd));
167
+ neon_store_reg32(tcg_res, rd);
168
tcg_temp_free_i32(tcg_res);
169
tcg_temp_free_i32(tcg_single);
170
}
171
diff --git a/target/arm/translate.c b/target/arm/translate.c
172
index XXXXXXX..XXXXXXX 100644
173
--- a/target/arm/translate.c
174
+++ b/target/arm/translate.c
175
@@ -XXX,XX +XXX,XX @@ static inline void neon_store_reg64(TCGv_i64 var, int reg)
176
tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
177
}
178
179
+static inline void neon_load_reg32(TCGv_i32 var, int reg)
180
+{
181
+ tcg_gen_ld_i32(var, cpu_env, vfp_reg_offset(false, reg));
182
+}
183
+
184
+static inline void neon_store_reg32(TCGv_i32 var, int reg)
185
+{
186
+ tcg_gen_st_i32(var, cpu_env, vfp_reg_offset(false, reg));
187
+}
188
+
189
static TCGv_ptr vfp_reg_ptr(bool dp, int reg)
190
{
191
TCGv_ptr ret = tcg_temp_new_ptr();
192
--
193
2.20.1
194
195
diff view generated by jsdifflib
Deleted patch
1
Convert the VFP two-register transfer instructions to decodetree
2
(in the v8 Arm ARM these are the "Advanced SIMD and floating-point
3
64-bit move" encoding group).
4
1
5
Again, we expand out the sequences involving gen_vfp_msr() and
6
gen_msr_vfp().
7
8
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
9
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
10
---
11
target/arm/translate-vfp.inc.c | 70 ++++++++++++++++++++++++++++++++++
12
target/arm/translate.c | 46 +---------------------
13
target/arm/vfp.decode | 5 +++
14
3 files changed, 77 insertions(+), 44 deletions(-)
15
16
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
17
index XXXXXXX..XXXXXXX 100644
18
--- a/target/arm/translate-vfp.inc.c
19
+++ b/target/arm/translate-vfp.inc.c
20
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_single(DisasContext *s, arg_VMOV_single *a)
21
22
return true;
23
}
24
+
25
+static bool trans_VMOV_64_sp(DisasContext *s, arg_VMOV_64_sp *a)
26
+{
27
+ TCGv_i32 tmp;
28
+
29
+ /*
30
+ * VMOV between two general-purpose registers and two single precision
31
+ * floating point registers
32
+ */
33
+ if (!vfp_access_check(s)) {
34
+ return true;
35
+ }
36
+
37
+ if (a->op) {
38
+ /* fpreg to gpreg */
39
+ tmp = tcg_temp_new_i32();
40
+ neon_load_reg32(tmp, a->vm);
41
+ store_reg(s, a->rt, tmp);
42
+ tmp = tcg_temp_new_i32();
43
+ neon_load_reg32(tmp, a->vm + 1);
44
+ store_reg(s, a->rt2, tmp);
45
+ } else {
46
+ /* gpreg to fpreg */
47
+ tmp = load_reg(s, a->rt);
48
+ neon_store_reg32(tmp, a->vm);
49
+ tmp = load_reg(s, a->rt2);
50
+ neon_store_reg32(tmp, a->vm + 1);
51
+ }
52
+
53
+ return true;
54
+}
55
+
56
+static bool trans_VMOV_64_dp(DisasContext *s, arg_VMOV_64_sp *a)
57
+{
58
+ TCGv_i32 tmp;
59
+
60
+ /*
61
+ * VMOV between two general-purpose registers and one double precision
62
+ * floating point register
63
+ */
64
+
65
+ /* UNDEF accesses to D16-D31 if they don't exist */
66
+ if (!dc_isar_feature(aa32_fp_d32, s) && (a->vm & 0x10)) {
67
+ return false;
68
+ }
69
+
70
+ if (!vfp_access_check(s)) {
71
+ return true;
72
+ }
73
+
74
+ if (a->op) {
75
+ /* fpreg to gpreg */
76
+ tmp = tcg_temp_new_i32();
77
+ neon_load_reg32(tmp, a->vm * 2);
78
+ store_reg(s, a->rt, tmp);
79
+ tmp = tcg_temp_new_i32();
80
+ neon_load_reg32(tmp, a->vm * 2 + 1);
81
+ store_reg(s, a->rt2, tmp);
82
+ } else {
83
+ /* gpreg to fpreg */
84
+ tmp = load_reg(s, a->rt);
85
+ neon_store_reg32(tmp, a->vm * 2);
86
+ tcg_temp_free_i32(tmp);
87
+ tmp = load_reg(s, a->rt2);
88
+ neon_store_reg32(tmp, a->vm * 2 + 1);
89
+ tcg_temp_free_i32(tmp);
90
+ }
91
+
92
+ return true;
93
+}
94
diff --git a/target/arm/translate.c b/target/arm/translate.c
95
index XXXXXXX..XXXXXXX 100644
96
--- a/target/arm/translate.c
97
+++ b/target/arm/translate.c
98
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
99
case 0xc:
100
case 0xd:
101
if ((insn & 0x03e00000) == 0x00400000) {
102
- /* two-register transfer */
103
- rn = (insn >> 16) & 0xf;
104
- rd = (insn >> 12) & 0xf;
105
- if (dp) {
106
- VFP_DREG_M(rm, insn);
107
- } else {
108
- rm = VFP_SREG_M(insn);
109
- }
110
-
111
- if (insn & ARM_CP_RW_BIT) {
112
- /* vfp->arm */
113
- if (dp) {
114
- gen_mov_F0_vreg(0, rm * 2);
115
- tmp = gen_vfp_mrs();
116
- store_reg(s, rd, tmp);
117
- gen_mov_F0_vreg(0, rm * 2 + 1);
118
- tmp = gen_vfp_mrs();
119
- store_reg(s, rn, tmp);
120
- } else {
121
- gen_mov_F0_vreg(0, rm);
122
- tmp = gen_vfp_mrs();
123
- store_reg(s, rd, tmp);
124
- gen_mov_F0_vreg(0, rm + 1);
125
- tmp = gen_vfp_mrs();
126
- store_reg(s, rn, tmp);
127
- }
128
- } else {
129
- /* arm->vfp */
130
- if (dp) {
131
- tmp = load_reg(s, rd);
132
- gen_vfp_msr(tmp);
133
- gen_mov_vreg_F0(0, rm * 2);
134
- tmp = load_reg(s, rn);
135
- gen_vfp_msr(tmp);
136
- gen_mov_vreg_F0(0, rm * 2 + 1);
137
- } else {
138
- tmp = load_reg(s, rd);
139
- gen_vfp_msr(tmp);
140
- gen_mov_vreg_F0(0, rm);
141
- tmp = load_reg(s, rn);
142
- gen_vfp_msr(tmp);
143
- gen_mov_vreg_F0(0, rm + 1);
144
- }
145
- }
146
+ /* Already handled by decodetree */
147
+ return 1;
148
} else {
149
/* Load/store */
150
rn = (insn >> 16) & 0xf;
151
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
152
index XXXXXXX..XXXXXXX 100644
153
--- a/target/arm/vfp.decode
154
+++ b/target/arm/vfp.decode
155
@@ -XXX,XX +XXX,XX @@ VDUP ---- 1110 1 b:1 q:1 0 .... rt:4 1011 . 0 e:1 1 0000 \
156
VMSR_VMRS ---- 1110 111 l:1 reg:4 rt:4 1010 0001 0000
157
VMOV_single ---- 1110 000 l:1 .... rt:4 1010 . 001 0000 \
158
vn=%vn_sp
159
+
160
+VMOV_64_sp ---- 1100 010 op:1 rt2:4 rt:4 1010 00.1 .... \
161
+ vm=%vm_sp
162
+VMOV_64_dp ---- 1100 010 op:1 rt2:4 rt:4 1011 00.1 .... \
163
+ vm=%vm_dp
164
--
165
2.20.1
166
167
diff view generated by jsdifflib
Deleted patch
1
Convert the VFP single load/store insns VLDR and VSTR to decodetree.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
---
6
target/arm/translate-vfp.inc.c | 73 ++++++++++++++++++++++++++++++++++
7
target/arm/translate.c | 22 +---------
8
target/arm/vfp.decode | 7 ++++
9
3 files changed, 82 insertions(+), 20 deletions(-)
10
11
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-vfp.inc.c
14
+++ b/target/arm/translate-vfp.inc.c
15
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_64_dp(DisasContext *s, arg_VMOV_64_sp *a)
16
17
return true;
18
}
19
+
20
+static bool trans_VLDR_VSTR_sp(DisasContext *s, arg_VLDR_VSTR_sp *a)
21
+{
22
+ uint32_t offset;
23
+ TCGv_i32 addr;
24
+
25
+ if (!vfp_access_check(s)) {
26
+ return true;
27
+ }
28
+
29
+ offset = a->imm << 2;
30
+ if (!a->u) {
31
+ offset = -offset;
32
+ }
33
+
34
+ if (s->thumb && a->rn == 15) {
35
+ /* This is actually UNPREDICTABLE */
36
+ addr = tcg_temp_new_i32();
37
+ tcg_gen_movi_i32(addr, s->pc & ~2);
38
+ } else {
39
+ addr = load_reg(s, a->rn);
40
+ }
41
+ tcg_gen_addi_i32(addr, addr, offset);
42
+ if (a->l) {
43
+ gen_vfp_ld(s, false, addr);
44
+ gen_mov_vreg_F0(false, a->vd);
45
+ } else {
46
+ gen_mov_F0_vreg(false, a->vd);
47
+ gen_vfp_st(s, false, addr);
48
+ }
49
+ tcg_temp_free_i32(addr);
50
+
51
+ return true;
52
+}
53
+
54
+static bool trans_VLDR_VSTR_dp(DisasContext *s, arg_VLDR_VSTR_sp *a)
55
+{
56
+ uint32_t offset;
57
+ TCGv_i32 addr;
58
+
59
+ /* UNDEF accesses to D16-D31 if they don't exist */
60
+ if (!dc_isar_feature(aa32_fp_d32, s) && (a->vd & 0x10)) {
61
+ return false;
62
+ }
63
+
64
+ if (!vfp_access_check(s)) {
65
+ return true;
66
+ }
67
+
68
+ offset = a->imm << 2;
69
+ if (!a->u) {
70
+ offset = -offset;
71
+ }
72
+
73
+ if (s->thumb && a->rn == 15) {
74
+ /* This is actually UNPREDICTABLE */
75
+ addr = tcg_temp_new_i32();
76
+ tcg_gen_movi_i32(addr, s->pc & ~2);
77
+ } else {
78
+ addr = load_reg(s, a->rn);
79
+ }
80
+ tcg_gen_addi_i32(addr, addr, offset);
81
+ if (a->l) {
82
+ gen_vfp_ld(s, true, addr);
83
+ gen_mov_vreg_F0(true, a->vd);
84
+ } else {
85
+ gen_mov_F0_vreg(true, a->vd);
86
+ gen_vfp_st(s, true, addr);
87
+ }
88
+ tcg_temp_free_i32(addr);
89
+
90
+ return true;
91
+}
92
diff --git a/target/arm/translate.c b/target/arm/translate.c
93
index XXXXXXX..XXXXXXX 100644
94
--- a/target/arm/translate.c
95
+++ b/target/arm/translate.c
96
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
97
else
98
rd = VFP_SREG_D(insn);
99
if ((insn & 0x01200000) == 0x01000000) {
100
- /* Single load/store */
101
- offset = (insn & 0xff) << 2;
102
- if ((insn & (1 << 23)) == 0)
103
- offset = -offset;
104
- if (s->thumb && rn == 15) {
105
- /* This is actually UNPREDICTABLE */
106
- addr = tcg_temp_new_i32();
107
- tcg_gen_movi_i32(addr, s->pc & ~2);
108
- } else {
109
- addr = load_reg(s, rn);
110
- }
111
- tcg_gen_addi_i32(addr, addr, offset);
112
- if (insn & (1 << 20)) {
113
- gen_vfp_ld(s, dp, addr);
114
- gen_mov_vreg_F0(dp, rd);
115
- } else {
116
- gen_mov_F0_vreg(dp, rd);
117
- gen_vfp_st(s, dp, addr);
118
- }
119
- tcg_temp_free_i32(addr);
120
+ /* Already handled by decodetree */
121
+ return 1;
122
} else {
123
/* load/store multiple */
124
int w = insn & (1 << 21);
125
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
126
index XXXXXXX..XXXXXXX 100644
127
--- a/target/arm/vfp.decode
128
+++ b/target/arm/vfp.decode
129
@@ -XXX,XX +XXX,XX @@ VMOV_64_sp ---- 1100 010 op:1 rt2:4 rt:4 1010 00.1 .... \
130
vm=%vm_sp
131
VMOV_64_dp ---- 1100 010 op:1 rt2:4 rt:4 1011 00.1 .... \
132
vm=%vm_dp
133
+
134
+# Note that the half-precision variants of VLDR and VSTR are
135
+# not part of this decodetree at all because they have bits [9:8] == 0b01
136
+VLDR_VSTR_sp ---- 1101 u:1 .0 l:1 rn:4 .... 1010 imm:8 \
137
+ vd=%vd_sp
138
+VLDR_VSTR_dp ---- 1101 u:1 .0 l:1 rn:4 .... 1011 imm:8 \
139
+ vd=%vd_dp
140
--
141
2.20.1
142
143
diff view generated by jsdifflib
Deleted patch
1
Convert the VFP load/store multiple insns to decodetree.
2
This includes tightening up the UNDEF checking for pre-VFPv3
3
CPUs which only have D0-D15 : they now UNDEF for any access
4
to D16-D31, not merely when the smallest register in the
5
transfer list is in D16-D31.
6
1
7
This conversion does not try to share code between the single
8
precision and the double precision versions; this looks a bit
9
duplicative of code, but it leaves the door open for a future
10
refactoring which gets rid of the use of the "F0" registers
11
by inlining the various functions like gen_vfp_ld() and
12
gen_mov_F0_reg() which are hiding "if (dp) { ... } else { ... }"
13
conditionalisation.
14
15
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
16
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
17
---
18
target/arm/translate-vfp.inc.c | 162 +++++++++++++++++++++++++++++++++
19
target/arm/translate.c | 97 +-------------------
20
target/arm/vfp.decode | 18 ++++
21
3 files changed, 183 insertions(+), 94 deletions(-)
22
23
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
24
index XXXXXXX..XXXXXXX 100644
25
--- a/target/arm/translate-vfp.inc.c
26
+++ b/target/arm/translate-vfp.inc.c
27
@@ -XXX,XX +XXX,XX @@ static bool trans_VLDR_VSTR_dp(DisasContext *s, arg_VLDR_VSTR_sp *a)
28
29
return true;
30
}
31
+
32
+static bool trans_VLDM_VSTM_sp(DisasContext *s, arg_VLDM_VSTM_sp *a)
33
+{
34
+ uint32_t offset;
35
+ TCGv_i32 addr;
36
+ int i, n;
37
+
38
+ n = a->imm;
39
+
40
+ if (n == 0 || (a->vd + n) > 32) {
41
+ /*
42
+ * UNPREDICTABLE cases for bad immediates: we choose to
43
+ * UNDEF to avoid generating huge numbers of TCG ops
44
+ */
45
+ return false;
46
+ }
47
+ if (a->rn == 15 && a->w) {
48
+ /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
49
+ return false;
50
+ }
51
+
52
+ if (!vfp_access_check(s)) {
53
+ return true;
54
+ }
55
+
56
+ if (s->thumb && a->rn == 15) {
57
+ /* This is actually UNPREDICTABLE */
58
+ addr = tcg_temp_new_i32();
59
+ tcg_gen_movi_i32(addr, s->pc & ~2);
60
+ } else {
61
+ addr = load_reg(s, a->rn);
62
+ }
63
+ if (a->p) {
64
+ /* pre-decrement */
65
+ tcg_gen_addi_i32(addr, addr, -(a->imm << 2));
66
+ }
67
+
68
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
69
+ /*
70
+ * Here 'addr' is the lowest address we will store to,
71
+ * and is either the old SP (if post-increment) or
72
+ * the new SP (if pre-decrement). For post-increment
73
+ * where the old value is below the limit and the new
74
+ * value is above, it is UNKNOWN whether the limit check
75
+ * triggers; we choose to trigger.
76
+ */
77
+ gen_helper_v8m_stackcheck(cpu_env, addr);
78
+ }
79
+
80
+ offset = 4;
81
+ for (i = 0; i < n; i++) {
82
+ if (a->l) {
83
+ /* load */
84
+ gen_vfp_ld(s, false, addr);
85
+ gen_mov_vreg_F0(false, a->vd + i);
86
+ } else {
87
+ /* store */
88
+ gen_mov_F0_vreg(false, a->vd + i);
89
+ gen_vfp_st(s, false, addr);
90
+ }
91
+ tcg_gen_addi_i32(addr, addr, offset);
92
+ }
93
+ if (a->w) {
94
+ /* writeback */
95
+ if (a->p) {
96
+ offset = -offset * n;
97
+ tcg_gen_addi_i32(addr, addr, offset);
98
+ }
99
+ store_reg(s, a->rn, addr);
100
+ } else {
101
+ tcg_temp_free_i32(addr);
102
+ }
103
+
104
+ return true;
105
+}
106
+
107
+static bool trans_VLDM_VSTM_dp(DisasContext *s, arg_VLDM_VSTM_dp *a)
108
+{
109
+ uint32_t offset;
110
+ TCGv_i32 addr;
111
+ int i, n;
112
+
113
+ n = a->imm >> 1;
114
+
115
+ if (n == 0 || (a->vd + n) > 32 || n > 16) {
116
+ /*
117
+ * UNPREDICTABLE cases for bad immediates: we choose to
118
+ * UNDEF to avoid generating huge numbers of TCG ops
119
+ */
120
+ return false;
121
+ }
122
+ if (a->rn == 15 && a->w) {
123
+ /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
124
+ return false;
125
+ }
126
+
127
+ /* UNDEF accesses to D16-D31 if they don't exist */
128
+ if (!dc_isar_feature(aa32_fp_d32, s) && (a->vd + n) > 16) {
129
+ return false;
130
+ }
131
+
132
+ if (!vfp_access_check(s)) {
133
+ return true;
134
+ }
135
+
136
+ if (s->thumb && a->rn == 15) {
137
+ /* This is actually UNPREDICTABLE */
138
+ addr = tcg_temp_new_i32();
139
+ tcg_gen_movi_i32(addr, s->pc & ~2);
140
+ } else {
141
+ addr = load_reg(s, a->rn);
142
+ }
143
+ if (a->p) {
144
+ /* pre-decrement */
145
+ tcg_gen_addi_i32(addr, addr, -(a->imm << 2));
146
+ }
147
+
148
+ if (s->v8m_stackcheck && a->rn == 13 && a->w) {
149
+ /*
150
+ * Here 'addr' is the lowest address we will store to,
151
+ * and is either the old SP (if post-increment) or
152
+ * the new SP (if pre-decrement). For post-increment
153
+ * where the old value is below the limit and the new
154
+ * value is above, it is UNKNOWN whether the limit check
155
+ * triggers; we choose to trigger.
156
+ */
157
+ gen_helper_v8m_stackcheck(cpu_env, addr);
158
+ }
159
+
160
+ offset = 8;
161
+ for (i = 0; i < n; i++) {
162
+ if (a->l) {
163
+ /* load */
164
+ gen_vfp_ld(s, true, addr);
165
+ gen_mov_vreg_F0(true, a->vd + i);
166
+ } else {
167
+ /* store */
168
+ gen_mov_F0_vreg(true, a->vd + i);
169
+ gen_vfp_st(s, true, addr);
170
+ }
171
+ tcg_gen_addi_i32(addr, addr, offset);
172
+ }
173
+ if (a->w) {
174
+ /* writeback */
175
+ if (a->p) {
176
+ offset = -offset * n;
177
+ } else if (a->imm & 1) {
178
+ offset = 4;
179
+ } else {
180
+ offset = 0;
181
+ }
182
+
183
+ if (offset != 0) {
184
+ tcg_gen_addi_i32(addr, addr, offset);
185
+ }
186
+ store_reg(s, a->rn, addr);
187
+ } else {
188
+ tcg_temp_free_i32(addr);
189
+ }
190
+
191
+ return true;
192
+}
193
diff --git a/target/arm/translate.c b/target/arm/translate.c
194
index XXXXXXX..XXXXXXX 100644
195
--- a/target/arm/translate.c
196
+++ b/target/arm/translate.c
197
@@ -XXX,XX +XXX,XX @@ static void gen_neon_dup_high16(TCGv_i32 var)
198
*/
199
static int disas_vfp_insn(DisasContext *s, uint32_t insn)
200
{
201
- uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
202
+ uint32_t rd, rn, rm, op, i, n, delta_d, delta_m, bank_mask;
203
int dp, veclen;
204
- TCGv_i32 addr;
205
TCGv_i32 tmp;
206
TCGv_i32 tmp2;
207
208
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
209
break;
210
case 0xc:
211
case 0xd:
212
- if ((insn & 0x03e00000) == 0x00400000) {
213
- /* Already handled by decodetree */
214
- return 1;
215
- } else {
216
- /* Load/store */
217
- rn = (insn >> 16) & 0xf;
218
- if (dp)
219
- VFP_DREG_D(rd, insn);
220
- else
221
- rd = VFP_SREG_D(insn);
222
- if ((insn & 0x01200000) == 0x01000000) {
223
- /* Already handled by decodetree */
224
- return 1;
225
- } else {
226
- /* load/store multiple */
227
- int w = insn & (1 << 21);
228
- if (dp)
229
- n = (insn >> 1) & 0x7f;
230
- else
231
- n = insn & 0xff;
232
-
233
- if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) {
234
- /* P == U , W == 1 => UNDEF */
235
- return 1;
236
- }
237
- if (n == 0 || (rd + n) > 32 || (dp && n > 16)) {
238
- /* UNPREDICTABLE cases for bad immediates: we choose to
239
- * UNDEF to avoid generating huge numbers of TCG ops
240
- */
241
- return 1;
242
- }
243
- if (rn == 15 && w) {
244
- /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
245
- return 1;
246
- }
247
-
248
- if (s->thumb && rn == 15) {
249
- /* This is actually UNPREDICTABLE */
250
- addr = tcg_temp_new_i32();
251
- tcg_gen_movi_i32(addr, s->pc & ~2);
252
- } else {
253
- addr = load_reg(s, rn);
254
- }
255
- if (insn & (1 << 24)) /* pre-decrement */
256
- tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
257
-
258
- if (s->v8m_stackcheck && rn == 13 && w) {
259
- /*
260
- * Here 'addr' is the lowest address we will store to,
261
- * and is either the old SP (if post-increment) or
262
- * the new SP (if pre-decrement). For post-increment
263
- * where the old value is below the limit and the new
264
- * value is above, it is UNKNOWN whether the limit check
265
- * triggers; we choose to trigger.
266
- */
267
- gen_helper_v8m_stackcheck(cpu_env, addr);
268
- }
269
-
270
- if (dp)
271
- offset = 8;
272
- else
273
- offset = 4;
274
- for (i = 0; i < n; i++) {
275
- if (insn & ARM_CP_RW_BIT) {
276
- /* load */
277
- gen_vfp_ld(s, dp, addr);
278
- gen_mov_vreg_F0(dp, rd + i);
279
- } else {
280
- /* store */
281
- gen_mov_F0_vreg(dp, rd + i);
282
- gen_vfp_st(s, dp, addr);
283
- }
284
- tcg_gen_addi_i32(addr, addr, offset);
285
- }
286
- if (w) {
287
- /* writeback */
288
- if (insn & (1 << 24))
289
- offset = -offset * n;
290
- else if (dp && (insn & 1))
291
- offset = 4;
292
- else
293
- offset = 0;
294
-
295
- if (offset != 0)
296
- tcg_gen_addi_i32(addr, addr, offset);
297
- store_reg(s, rn, addr);
298
- } else {
299
- tcg_temp_free_i32(addr);
300
- }
301
- }
302
- }
303
- break;
304
+ /* Already handled by decodetree */
305
+ return 1;
306
default:
307
/* Should never happen. */
308
return 1;
309
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
310
index XXXXXXX..XXXXXXX 100644
311
--- a/target/arm/vfp.decode
312
+++ b/target/arm/vfp.decode
313
@@ -XXX,XX +XXX,XX @@ VLDR_VSTR_sp ---- 1101 u:1 .0 l:1 rn:4 .... 1010 imm:8 \
314
vd=%vd_sp
315
VLDR_VSTR_dp ---- 1101 u:1 .0 l:1 rn:4 .... 1011 imm:8 \
316
vd=%vd_dp
317
+
318
+# We split the load/store multiple up into two patterns to avoid
319
+# overlap with other insns in the "Advanced SIMD load/store and 64-bit move"
320
+# grouping:
321
+# P=0 U=0 W=0 is 64-bit VMOV
322
+# P=1 W=0 is VLDR/VSTR
323
+# P=U W=1 is UNDEF
324
+# leaving P=0 U=1 W=x and P=1 U=0 W=1 for load/store multiple.
325
+# These include FSTM/FLDM.
326
+VLDM_VSTM_sp ---- 1100 1 . w:1 l:1 rn:4 .... 1010 imm:8 \
327
+ vd=%vd_sp p=0 u=1
328
+VLDM_VSTM_dp ---- 1100 1 . w:1 l:1 rn:4 .... 1011 imm:8 \
329
+ vd=%vd_dp p=0 u=1
330
+
331
+VLDM_VSTM_sp ---- 1101 0.1 l:1 rn:4 .... 1010 imm:8 \
332
+ vd=%vd_sp p=1 u=0 w=1
333
+VLDM_VSTM_dp ---- 1101 0.1 l:1 rn:4 .... 1011 imm:8 \
334
+ vd=%vd_dp p=1 u=0 w=1
335
--
336
2.20.1
337
338
diff view generated by jsdifflib
Deleted patch
1
Convert the VFP VMLS instruction to decodetree.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
---
6
target/arm/translate-vfp.inc.c | 38 ++++++++++++++++++++++++++++++++++
7
target/arm/translate.c | 8 +------
8
target/arm/vfp.decode | 5 +++++
9
3 files changed, 44 insertions(+), 7 deletions(-)
10
11
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-vfp.inc.c
14
+++ b/target/arm/translate-vfp.inc.c
15
@@ -XXX,XX +XXX,XX @@ static bool trans_VMLA_dp(DisasContext *s, arg_VMLA_sp *a)
16
{
17
return do_vfp_3op_dp(s, gen_VMLA_dp, a->vd, a->vn, a->vm, true);
18
}
19
+
20
+static void gen_VMLS_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
21
+{
22
+ /*
23
+ * VMLS: vd = vd + -(vn * vm)
24
+ * Note that order of inputs to the add matters for NaNs.
25
+ */
26
+ TCGv_i32 tmp = tcg_temp_new_i32();
27
+
28
+ gen_helper_vfp_muls(tmp, vn, vm, fpst);
29
+ gen_helper_vfp_negs(tmp, tmp);
30
+ gen_helper_vfp_adds(vd, vd, tmp, fpst);
31
+ tcg_temp_free_i32(tmp);
32
+}
33
+
34
+static bool trans_VMLS_sp(DisasContext *s, arg_VMLS_sp *a)
35
+{
36
+ return do_vfp_3op_sp(s, gen_VMLS_sp, a->vd, a->vn, a->vm, true);
37
+}
38
+
39
+static void gen_VMLS_dp(TCGv_i64 vd, TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst)
40
+{
41
+ /*
42
+ * VMLS: vd = vd + -(vn * vm)
43
+ * Note that order of inputs to the add matters for NaNs.
44
+ */
45
+ TCGv_i64 tmp = tcg_temp_new_i64();
46
+
47
+ gen_helper_vfp_muld(tmp, vn, vm, fpst);
48
+ gen_helper_vfp_negd(tmp, tmp);
49
+ gen_helper_vfp_addd(vd, vd, tmp, fpst);
50
+ tcg_temp_free_i64(tmp);
51
+}
52
+
53
+static bool trans_VMLS_dp(DisasContext *s, arg_VMLS_sp *a)
54
+{
55
+ return do_vfp_3op_dp(s, gen_VMLS_dp, a->vd, a->vn, a->vm, true);
56
+}
57
diff --git a/target/arm/translate.c b/target/arm/translate.c
58
index XXXXXXX..XXXXXXX 100644
59
--- a/target/arm/translate.c
60
+++ b/target/arm/translate.c
61
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
62
rn = VFP_SREG_N(insn);
63
64
switch (op) {
65
- case 0:
66
+ case 0 ... 1:
67
/* Already handled by decodetree */
68
return 1;
69
default:
70
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
71
for (;;) {
72
/* Perform the calculation. */
73
switch (op) {
74
- case 1: /* VMLS: fd + -(fn * fm) */
75
- gen_vfp_mul(dp);
76
- gen_vfp_F1_neg(dp);
77
- gen_mov_F0_vreg(dp, rd);
78
- gen_vfp_add(dp);
79
- break;
80
case 2: /* VNMLS: -fd + (fn * fm) */
81
/* Note that it isn't valid to replace (-A + B) with (B - A)
82
* or similar plausible looking simplifications
83
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
84
index XXXXXXX..XXXXXXX 100644
85
--- a/target/arm/vfp.decode
86
+++ b/target/arm/vfp.decode
87
@@ -XXX,XX +XXX,XX @@ VMLA_sp ---- 1110 0.00 .... .... 1010 .0.0 .... \
88
vm=%vm_sp vn=%vn_sp vd=%vd_sp
89
VMLA_dp ---- 1110 0.00 .... .... 1011 .0.0 .... \
90
vm=%vm_dp vn=%vn_dp vd=%vd_dp
91
+
92
+VMLS_sp ---- 1110 0.00 .... .... 1010 .1.0 .... \
93
+ vm=%vm_sp vn=%vn_sp vd=%vd_sp
94
+VMLS_dp ---- 1110 0.00 .... .... 1011 .1.0 .... \
95
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
96
--
97
2.20.1
98
99
diff view generated by jsdifflib
Deleted patch
1
Convert the VMUL instruction to decodetree.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
---
6
target/arm/translate-vfp.inc.c | 10 ++++++++++
7
target/arm/translate.c | 5 +----
8
target/arm/vfp.decode | 5 +++++
9
3 files changed, 16 insertions(+), 4 deletions(-)
10
11
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-vfp.inc.c
14
+++ b/target/arm/translate-vfp.inc.c
15
@@ -XXX,XX +XXX,XX @@ static bool trans_VNMLA_dp(DisasContext *s, arg_VNMLA_sp *a)
16
{
17
return do_vfp_3op_dp(s, gen_VNMLA_dp, a->vd, a->vn, a->vm, true);
18
}
19
+
20
+static bool trans_VMUL_sp(DisasContext *s, arg_VMUL_sp *a)
21
+{
22
+ return do_vfp_3op_sp(s, gen_helper_vfp_muls, a->vd, a->vn, a->vm, false);
23
+}
24
+
25
+static bool trans_VMUL_dp(DisasContext *s, arg_VMUL_sp *a)
26
+{
27
+ return do_vfp_3op_dp(s, gen_helper_vfp_muld, a->vd, a->vn, a->vm, false);
28
+}
29
diff --git a/target/arm/translate.c b/target/arm/translate.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/translate.c
32
+++ b/target/arm/translate.c
33
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
34
rn = VFP_SREG_N(insn);
35
36
switch (op) {
37
- case 0 ... 3:
38
+ case 0 ... 4:
39
/* Already handled by decodetree */
40
return 1;
41
default:
42
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
43
for (;;) {
44
/* Perform the calculation. */
45
switch (op) {
46
- case 4: /* mul: fn * fm */
47
- gen_vfp_mul(dp);
48
- break;
49
case 5: /* nmul: -(fn * fm) */
50
gen_vfp_mul(dp);
51
gen_vfp_neg(dp);
52
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
53
index XXXXXXX..XXXXXXX 100644
54
--- a/target/arm/vfp.decode
55
+++ b/target/arm/vfp.decode
56
@@ -XXX,XX +XXX,XX @@ VNMLA_sp ---- 1110 0.01 .... .... 1010 .1.0 .... \
57
vm=%vm_sp vn=%vn_sp vd=%vd_sp
58
VNMLA_dp ---- 1110 0.01 .... .... 1011 .1.0 .... \
59
vm=%vm_dp vn=%vn_dp vd=%vd_dp
60
+
61
+VMUL_sp ---- 1110 0.10 .... .... 1010 .0.0 .... \
62
+ vm=%vm_sp vn=%vn_sp vd=%vd_sp
63
+VMUL_dp ---- 1110 0.10 .... .... 1011 .0.0 .... \
64
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
65
--
66
2.20.1
67
68
diff view generated by jsdifflib
Deleted patch
1
Convert the VNMUL instruction to decodetree.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
---
6
target/arm/translate-vfp.inc.c | 24 ++++++++++++++++++++++++
7
target/arm/translate.c | 7 +------
8
target/arm/vfp.decode | 5 +++++
9
3 files changed, 30 insertions(+), 6 deletions(-)
10
11
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-vfp.inc.c
14
+++ b/target/arm/translate-vfp.inc.c
15
@@ -XXX,XX +XXX,XX @@ static bool trans_VMUL_dp(DisasContext *s, arg_VMUL_sp *a)
16
{
17
return do_vfp_3op_dp(s, gen_helper_vfp_muld, a->vd, a->vn, a->vm, false);
18
}
19
+
20
+static void gen_VNMUL_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
21
+{
22
+ /* VNMUL: -(fn * fm) */
23
+ gen_helper_vfp_muls(vd, vn, vm, fpst);
24
+ gen_helper_vfp_negs(vd, vd);
25
+}
26
+
27
+static bool trans_VNMUL_sp(DisasContext *s, arg_VNMUL_sp *a)
28
+{
29
+ return do_vfp_3op_sp(s, gen_VNMUL_sp, a->vd, a->vn, a->vm, false);
30
+}
31
+
32
+static void gen_VNMUL_dp(TCGv_i64 vd, TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst)
33
+{
34
+ /* VNMUL: -(fn * fm) */
35
+ gen_helper_vfp_muld(vd, vn, vm, fpst);
36
+ gen_helper_vfp_negd(vd, vd);
37
+}
38
+
39
+static bool trans_VNMUL_dp(DisasContext *s, arg_VNMUL_sp *a)
40
+{
41
+ return do_vfp_3op_dp(s, gen_VNMUL_dp, a->vd, a->vn, a->vm, false);
42
+}
43
diff --git a/target/arm/translate.c b/target/arm/translate.c
44
index XXXXXXX..XXXXXXX 100644
45
--- a/target/arm/translate.c
46
+++ b/target/arm/translate.c
47
@@ -XXX,XX +XXX,XX @@ static inline void gen_vfp_##name(int dp) \
48
49
VFP_OP2(add)
50
VFP_OP2(sub)
51
-VFP_OP2(mul)
52
VFP_OP2(div)
53
54
#undef VFP_OP2
55
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
56
rn = VFP_SREG_N(insn);
57
58
switch (op) {
59
- case 0 ... 4:
60
+ case 0 ... 5:
61
/* Already handled by decodetree */
62
return 1;
63
default:
64
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
65
for (;;) {
66
/* Perform the calculation. */
67
switch (op) {
68
- case 5: /* nmul: -(fn * fm) */
69
- gen_vfp_mul(dp);
70
- gen_vfp_neg(dp);
71
- break;
72
case 6: /* add: fn + fm */
73
gen_vfp_add(dp);
74
break;
75
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/vfp.decode
78
+++ b/target/arm/vfp.decode
79
@@ -XXX,XX +XXX,XX @@ VMUL_sp ---- 1110 0.10 .... .... 1010 .0.0 .... \
80
vm=%vm_sp vn=%vn_sp vd=%vd_sp
81
VMUL_dp ---- 1110 0.10 .... .... 1011 .0.0 .... \
82
vm=%vm_dp vn=%vn_dp vd=%vd_dp
83
+
84
+VNMUL_sp ---- 1110 0.10 .... .... 1010 .1.0 .... \
85
+ vm=%vm_sp vn=%vn_sp vd=%vd_sp
86
+VNMUL_dp ---- 1110 0.10 .... .... 1011 .1.0 .... \
87
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
88
--
89
2.20.1
90
91
diff view generated by jsdifflib
Deleted patch
1
Convert the VADD instruction to decodetree.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
---
6
target/arm/translate-vfp.inc.c | 10 ++++++++++
7
target/arm/translate.c | 6 +-----
8
target/arm/vfp.decode | 5 +++++
9
3 files changed, 16 insertions(+), 5 deletions(-)
10
11
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-vfp.inc.c
14
+++ b/target/arm/translate-vfp.inc.c
15
@@ -XXX,XX +XXX,XX @@ static bool trans_VNMUL_dp(DisasContext *s, arg_VNMUL_sp *a)
16
{
17
return do_vfp_3op_dp(s, gen_VNMUL_dp, a->vd, a->vn, a->vm, false);
18
}
19
+
20
+static bool trans_VADD_sp(DisasContext *s, arg_VADD_sp *a)
21
+{
22
+ return do_vfp_3op_sp(s, gen_helper_vfp_adds, a->vd, a->vn, a->vm, false);
23
+}
24
+
25
+static bool trans_VADD_dp(DisasContext *s, arg_VADD_sp *a)
26
+{
27
+ return do_vfp_3op_dp(s, gen_helper_vfp_addd, a->vd, a->vn, a->vm, false);
28
+}
29
diff --git a/target/arm/translate.c b/target/arm/translate.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/translate.c
32
+++ b/target/arm/translate.c
33
@@ -XXX,XX +XXX,XX @@ static inline void gen_vfp_##name(int dp) \
34
tcg_temp_free_ptr(fpst); \
35
}
36
37
-VFP_OP2(add)
38
VFP_OP2(sub)
39
VFP_OP2(div)
40
41
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
42
rn = VFP_SREG_N(insn);
43
44
switch (op) {
45
- case 0 ... 5:
46
+ case 0 ... 6:
47
/* Already handled by decodetree */
48
return 1;
49
default:
50
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
51
for (;;) {
52
/* Perform the calculation. */
53
switch (op) {
54
- case 6: /* add: fn + fm */
55
- gen_vfp_add(dp);
56
- break;
57
case 7: /* sub: fn - fm */
58
gen_vfp_sub(dp);
59
break;
60
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/vfp.decode
63
+++ b/target/arm/vfp.decode
64
@@ -XXX,XX +XXX,XX @@ VNMUL_sp ---- 1110 0.10 .... .... 1010 .1.0 .... \
65
vm=%vm_sp vn=%vn_sp vd=%vd_sp
66
VNMUL_dp ---- 1110 0.10 .... .... 1011 .1.0 .... \
67
vm=%vm_dp vn=%vn_dp vd=%vd_dp
68
+
69
+VADD_sp ---- 1110 0.11 .... .... 1010 .0.0 .... \
70
+ vm=%vm_sp vn=%vn_sp vd=%vd_sp
71
+VADD_dp ---- 1110 0.11 .... .... 1011 .0.0 .... \
72
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
73
--
74
2.20.1
75
76
diff view generated by jsdifflib
Deleted patch
1
Convert the VSUB instruction to decodetree.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
---
6
target/arm/translate-vfp.inc.c | 10 ++++++++++
7
target/arm/translate.c | 6 +-----
8
target/arm/vfp.decode | 5 +++++
9
3 files changed, 16 insertions(+), 5 deletions(-)
10
11
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-vfp.inc.c
14
+++ b/target/arm/translate-vfp.inc.c
15
@@ -XXX,XX +XXX,XX @@ static bool trans_VADD_dp(DisasContext *s, arg_VADD_sp *a)
16
{
17
return do_vfp_3op_dp(s, gen_helper_vfp_addd, a->vd, a->vn, a->vm, false);
18
}
19
+
20
+static bool trans_VSUB_sp(DisasContext *s, arg_VSUB_sp *a)
21
+{
22
+ return do_vfp_3op_sp(s, gen_helper_vfp_subs, a->vd, a->vn, a->vm, false);
23
+}
24
+
25
+static bool trans_VSUB_dp(DisasContext *s, arg_VSUB_sp *a)
26
+{
27
+ return do_vfp_3op_dp(s, gen_helper_vfp_subd, a->vd, a->vn, a->vm, false);
28
+}
29
diff --git a/target/arm/translate.c b/target/arm/translate.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/translate.c
32
+++ b/target/arm/translate.c
33
@@ -XXX,XX +XXX,XX @@ static inline void gen_vfp_##name(int dp) \
34
tcg_temp_free_ptr(fpst); \
35
}
36
37
-VFP_OP2(sub)
38
VFP_OP2(div)
39
40
#undef VFP_OP2
41
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
42
rn = VFP_SREG_N(insn);
43
44
switch (op) {
45
- case 0 ... 6:
46
+ case 0 ... 7:
47
/* Already handled by decodetree */
48
return 1;
49
default:
50
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
51
for (;;) {
52
/* Perform the calculation. */
53
switch (op) {
54
- case 7: /* sub: fn - fm */
55
- gen_vfp_sub(dp);
56
- break;
57
case 8: /* div: fn / fm */
58
gen_vfp_div(dp);
59
break;
60
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/vfp.decode
63
+++ b/target/arm/vfp.decode
64
@@ -XXX,XX +XXX,XX @@ VADD_sp ---- 1110 0.11 .... .... 1010 .0.0 .... \
65
vm=%vm_sp vn=%vn_sp vd=%vd_sp
66
VADD_dp ---- 1110 0.11 .... .... 1011 .0.0 .... \
67
vm=%vm_dp vn=%vn_dp vd=%vd_dp
68
+
69
+VSUB_sp ---- 1110 0.11 .... .... 1010 .1.0 .... \
70
+ vm=%vm_sp vn=%vn_sp vd=%vd_sp
71
+VSUB_dp ---- 1110 0.11 .... .... 1011 .1.0 .... \
72
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
73
--
74
2.20.1
75
76
diff view generated by jsdifflib
Deleted patch
1
Convert the VDIV instruction to decodetree.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
---
6
target/arm/translate-vfp.inc.c | 10 ++++++++++
7
target/arm/translate.c | 21 +--------------------
8
target/arm/vfp.decode | 5 +++++
9
3 files changed, 16 insertions(+), 20 deletions(-)
10
11
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-vfp.inc.c
14
+++ b/target/arm/translate-vfp.inc.c
15
@@ -XXX,XX +XXX,XX @@ static bool trans_VSUB_dp(DisasContext *s, arg_VSUB_sp *a)
16
{
17
return do_vfp_3op_dp(s, gen_helper_vfp_subd, a->vd, a->vn, a->vm, false);
18
}
19
+
20
+static bool trans_VDIV_sp(DisasContext *s, arg_VDIV_sp *a)
21
+{
22
+ return do_vfp_3op_sp(s, gen_helper_vfp_divs, a->vd, a->vn, a->vm, false);
23
+}
24
+
25
+static bool trans_VDIV_dp(DisasContext *s, arg_VDIV_sp *a)
26
+{
27
+ return do_vfp_3op_dp(s, gen_helper_vfp_divd, a->vd, a->vn, a->vm, false);
28
+}
29
diff --git a/target/arm/translate.c b/target/arm/translate.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/translate.c
32
+++ b/target/arm/translate.c
33
@@ -XXX,XX +XXX,XX @@ static TCGv_ptr get_fpstatus_ptr(int neon)
34
return statusptr;
35
}
36
37
-#define VFP_OP2(name) \
38
-static inline void gen_vfp_##name(int dp) \
39
-{ \
40
- TCGv_ptr fpst = get_fpstatus_ptr(0); \
41
- if (dp) { \
42
- gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst); \
43
- } else { \
44
- gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst); \
45
- } \
46
- tcg_temp_free_ptr(fpst); \
47
-}
48
-
49
-VFP_OP2(div)
50
-
51
-#undef VFP_OP2
52
-
53
static inline void gen_vfp_abs(int dp)
54
{
55
if (dp)
56
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
57
rn = VFP_SREG_N(insn);
58
59
switch (op) {
60
- case 0 ... 7:
61
+ case 0 ... 8:
62
/* Already handled by decodetree */
63
return 1;
64
default:
65
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
66
for (;;) {
67
/* Perform the calculation. */
68
switch (op) {
69
- case 8: /* div: fn / fm */
70
- gen_vfp_div(dp);
71
- break;
72
case 10: /* VFNMA : fd = muladd(-fd, fn, fm) */
73
case 11: /* VFNMS : fd = muladd(-fd, -fn, fm) */
74
case 12: /* VFMA : fd = muladd( fd, fn, fm) */
75
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
76
index XXXXXXX..XXXXXXX 100644
77
--- a/target/arm/vfp.decode
78
+++ b/target/arm/vfp.decode
79
@@ -XXX,XX +XXX,XX @@ VSUB_sp ---- 1110 0.11 .... .... 1010 .1.0 .... \
80
vm=%vm_sp vn=%vn_sp vd=%vd_sp
81
VSUB_dp ---- 1110 0.11 .... .... 1011 .1.0 .... \
82
vm=%vm_dp vn=%vn_dp vd=%vd_dp
83
+
84
+VDIV_sp ---- 1110 1.00 .... .... 1010 .0.0 .... \
85
+ vm=%vm_sp vn=%vn_sp vd=%vd_sp
86
+VDIV_dp ---- 1110 1.00 .... .... 1011 .0.0 .... \
87
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp
88
--
89
2.20.1
90
91
diff view generated by jsdifflib
Deleted patch
1
Convert the VFP fused multiply-add instructions (VFNMA, VFNMS,
2
VFMA, VFMS) to decodetree.
3
1
4
Note that in the old decode structure we were implementing
5
these to honour the VFP vector stride/length. These instructions
6
were introduced in VFPv4, and in the v7A architecture they
7
are UNPREDICTABLE if the vector stride or length are non-zero.
8
In v8A they must UNDEF if stride or length are non-zero, like
9
all VFP instructions; we choose to UNDEF always.
10
11
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
12
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
13
---
14
target/arm/translate-vfp.inc.c | 121 +++++++++++++++++++++++++++++++++
15
target/arm/translate.c | 53 +--------------
16
target/arm/vfp.decode | 9 +++
17
3 files changed, 131 insertions(+), 52 deletions(-)
18
19
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
20
index XXXXXXX..XXXXXXX 100644
21
--- a/target/arm/translate-vfp.inc.c
22
+++ b/target/arm/translate-vfp.inc.c
23
@@ -XXX,XX +XXX,XX @@ static bool trans_VDIV_dp(DisasContext *s, arg_VDIV_sp *a)
24
{
25
return do_vfp_3op_dp(s, gen_helper_vfp_divd, a->vd, a->vn, a->vm, false);
26
}
27
+
28
+static bool trans_VFM_sp(DisasContext *s, arg_VFM_sp *a)
29
+{
30
+ /*
31
+ * VFNMA : fd = muladd(-fd, fn, fm)
32
+ * VFNMS : fd = muladd(-fd, -fn, fm)
33
+ * VFMA : fd = muladd( fd, fn, fm)
34
+ * VFMS : fd = muladd( fd, -fn, fm)
35
+ *
36
+ * These are fused multiply-add, and must be done as one floating
37
+ * point operation with no rounding between the multiplication and
38
+ * addition steps. NB that doing the negations here as separate
39
+ * steps is correct : an input NaN should come out with its sign
40
+ * bit flipped if it is a negated-input.
41
+ */
42
+ TCGv_ptr fpst;
43
+ TCGv_i32 vn, vm, vd;
44
+
45
+ /*
46
+ * Present in VFPv4 only.
47
+ * In v7A, UNPREDICTABLE with non-zero vector length/stride; from
48
+ * v8A, must UNDEF. We choose to UNDEF for both v7A and v8A.
49
+ */
50
+ if (!arm_dc_feature(s, ARM_FEATURE_VFP4) ||
51
+ (s->vec_len != 0 || s->vec_stride != 0)) {
52
+ return false;
53
+ }
54
+
55
+ if (!vfp_access_check(s)) {
56
+ return true;
57
+ }
58
+
59
+ vn = tcg_temp_new_i32();
60
+ vm = tcg_temp_new_i32();
61
+ vd = tcg_temp_new_i32();
62
+
63
+ neon_load_reg32(vn, a->vn);
64
+ neon_load_reg32(vm, a->vm);
65
+ if (a->o2) {
66
+ /* VFNMS, VFMS */
67
+ gen_helper_vfp_negs(vn, vn);
68
+ }
69
+ neon_load_reg32(vd, a->vd);
70
+ if (a->o1 & 1) {
71
+ /* VFNMA, VFNMS */
72
+ gen_helper_vfp_negs(vd, vd);
73
+ }
74
+ fpst = get_fpstatus_ptr(0);
75
+ gen_helper_vfp_muladds(vd, vn, vm, vd, fpst);
76
+ neon_store_reg32(vd, a->vd);
77
+
78
+ tcg_temp_free_ptr(fpst);
79
+ tcg_temp_free_i32(vn);
80
+ tcg_temp_free_i32(vm);
81
+ tcg_temp_free_i32(vd);
82
+
83
+ return true;
84
+}
85
+
86
+static bool trans_VFM_dp(DisasContext *s, arg_VFM_sp *a)
87
+{
88
+ /*
89
+ * VFNMA : fd = muladd(-fd, fn, fm)
90
+ * VFNMS : fd = muladd(-fd, -fn, fm)
91
+ * VFMA : fd = muladd( fd, fn, fm)
92
+ * VFMS : fd = muladd( fd, -fn, fm)
93
+ *
94
+ * These are fused multiply-add, and must be done as one floating
95
+ * point operation with no rounding between the multiplication and
96
+ * addition steps. NB that doing the negations here as separate
97
+ * steps is correct : an input NaN should come out with its sign
98
+ * bit flipped if it is a negated-input.
99
+ */
100
+ TCGv_ptr fpst;
101
+ TCGv_i64 vn, vm, vd;
102
+
103
+ /*
104
+ * Present in VFPv4 only.
105
+ * In v7A, UNPREDICTABLE with non-zero vector length/stride; from
106
+ * v8A, must UNDEF. We choose to UNDEF for both v7A and v8A.
107
+ */
108
+ if (!arm_dc_feature(s, ARM_FEATURE_VFP4) ||
109
+ (s->vec_len != 0 || s->vec_stride != 0)) {
110
+ return false;
111
+ }
112
+
113
+ /* UNDEF accesses to D16-D31 if they don't exist. */
114
+ if (!dc_isar_feature(aa32_fp_d32, s) && ((a->vd | a->vn | a->vm) & 0x10)) {
115
+ return false;
116
+ }
117
+
118
+ if (!vfp_access_check(s)) {
119
+ return true;
120
+ }
121
+
122
+ vn = tcg_temp_new_i64();
123
+ vm = tcg_temp_new_i64();
124
+ vd = tcg_temp_new_i64();
125
+
126
+ neon_load_reg64(vn, a->vn);
127
+ neon_load_reg64(vm, a->vm);
128
+ if (a->o2) {
129
+ /* VFNMS, VFMS */
130
+ gen_helper_vfp_negd(vn, vn);
131
+ }
132
+ neon_load_reg64(vd, a->vd);
133
+ if (a->o1 & 1) {
134
+ /* VFNMA, VFNMS */
135
+ gen_helper_vfp_negd(vd, vd);
136
+ }
137
+ fpst = get_fpstatus_ptr(0);
138
+ gen_helper_vfp_muladdd(vd, vn, vm, vd, fpst);
139
+ neon_store_reg64(vd, a->vd);
140
+
141
+ tcg_temp_free_ptr(fpst);
142
+ tcg_temp_free_i64(vn);
143
+ tcg_temp_free_i64(vm);
144
+ tcg_temp_free_i64(vd);
145
+
146
+ return true;
147
+}
148
diff --git a/target/arm/translate.c b/target/arm/translate.c
149
index XXXXXXX..XXXXXXX 100644
150
--- a/target/arm/translate.c
151
+++ b/target/arm/translate.c
152
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
153
rn = VFP_SREG_N(insn);
154
155
switch (op) {
156
- case 0 ... 8:
157
+ case 0 ... 13:
158
/* Already handled by decodetree */
159
return 1;
160
default:
161
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
162
for (;;) {
163
/* Perform the calculation. */
164
switch (op) {
165
- case 10: /* VFNMA : fd = muladd(-fd, fn, fm) */
166
- case 11: /* VFNMS : fd = muladd(-fd, -fn, fm) */
167
- case 12: /* VFMA : fd = muladd( fd, fn, fm) */
168
- case 13: /* VFMS : fd = muladd( fd, -fn, fm) */
169
- /* These are fused multiply-add, and must be done as one
170
- * floating point operation with no rounding between the
171
- * multiplication and addition steps.
172
- * NB that doing the negations here as separate steps is
173
- * correct : an input NaN should come out with its sign bit
174
- * flipped if it is a negated-input.
175
- */
176
- if (!arm_dc_feature(s, ARM_FEATURE_VFP4)) {
177
- return 1;
178
- }
179
- if (dp) {
180
- TCGv_ptr fpst;
181
- TCGv_i64 frd;
182
- if (op & 1) {
183
- /* VFNMS, VFMS */
184
- gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
185
- }
186
- frd = tcg_temp_new_i64();
187
- tcg_gen_ld_f64(frd, cpu_env, vfp_reg_offset(dp, rd));
188
- if (op & 2) {
189
- /* VFNMA, VFNMS */
190
- gen_helper_vfp_negd(frd, frd);
191
- }
192
- fpst = get_fpstatus_ptr(0);
193
- gen_helper_vfp_muladdd(cpu_F0d, cpu_F0d,
194
- cpu_F1d, frd, fpst);
195
- tcg_temp_free_ptr(fpst);
196
- tcg_temp_free_i64(frd);
197
- } else {
198
- TCGv_ptr fpst;
199
- TCGv_i32 frd;
200
- if (op & 1) {
201
- /* VFNMS, VFMS */
202
- gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
203
- }
204
- frd = tcg_temp_new_i32();
205
- tcg_gen_ld_f32(frd, cpu_env, vfp_reg_offset(dp, rd));
206
- if (op & 2) {
207
- gen_helper_vfp_negs(frd, frd);
208
- }
209
- fpst = get_fpstatus_ptr(0);
210
- gen_helper_vfp_muladds(cpu_F0s, cpu_F0s,
211
- cpu_F1s, frd, fpst);
212
- tcg_temp_free_ptr(fpst);
213
- tcg_temp_free_i32(frd);
214
- }
215
- break;
216
case 14: /* fconst */
217
if (!arm_dc_feature(s, ARM_FEATURE_VFP3)) {
218
return 1;
219
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
220
index XXXXXXX..XXXXXXX 100644
221
--- a/target/arm/vfp.decode
222
+++ b/target/arm/vfp.decode
223
@@ -XXX,XX +XXX,XX @@ VDIV_sp ---- 1110 1.00 .... .... 1010 .0.0 .... \
224
vm=%vm_sp vn=%vn_sp vd=%vd_sp
225
VDIV_dp ---- 1110 1.00 .... .... 1011 .0.0 .... \
226
vm=%vm_dp vn=%vn_dp vd=%vd_dp
227
+
228
+VFM_sp ---- 1110 1.01 .... .... 1010 . o2:1 . 0 .... \
229
+ vm=%vm_sp vn=%vn_sp vd=%vd_sp o1=1
230
+VFM_dp ---- 1110 1.01 .... .... 1011 . o2:1 . 0 .... \
231
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp o1=1
232
+VFM_sp ---- 1110 1.10 .... .... 1010 . o2:1 . 0 .... \
233
+ vm=%vm_sp vn=%vn_sp vd=%vd_sp o1=2
234
+VFM_dp ---- 1110 1.10 .... .... 1011 . o2:1 . 0 .... \
235
+ vm=%vm_dp vn=%vn_dp vd=%vd_dp o1=2
236
--
237
2.20.1
238
239
diff view generated by jsdifflib
Deleted patch
1
Convert the VNEG instruction to decodetree.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
---
6
target/arm/translate-vfp.inc.c | 10 ++++++++++
7
target/arm/translate.c | 6 +-----
8
target/arm/vfp.decode | 5 +++++
9
3 files changed, 16 insertions(+), 5 deletions(-)
10
11
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-vfp.inc.c
14
+++ b/target/arm/translate-vfp.inc.c
15
@@ -XXX,XX +XXX,XX @@ static bool trans_VABS_dp(DisasContext *s, arg_VABS_dp *a)
16
{
17
return do_vfp_2op_dp(s, gen_helper_vfp_absd, a->vd, a->vm);
18
}
19
+
20
+static bool trans_VNEG_sp(DisasContext *s, arg_VNEG_sp *a)
21
+{
22
+ return do_vfp_2op_sp(s, gen_helper_vfp_negs, a->vd, a->vm);
23
+}
24
+
25
+static bool trans_VNEG_dp(DisasContext *s, arg_VNEG_dp *a)
26
+{
27
+ return do_vfp_2op_dp(s, gen_helper_vfp_negd, a->vd, a->vm);
28
+}
29
diff --git a/target/arm/translate.c b/target/arm/translate.c
30
index XXXXXXX..XXXXXXX 100644
31
--- a/target/arm/translate.c
32
+++ b/target/arm/translate.c
33
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
34
return 1;
35
case 15:
36
switch (rn) {
37
- case 1:
38
+ case 1 ... 2:
39
/* Already handled by decodetree */
40
return 1;
41
default:
42
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
43
/* rn is opcode, encoded as per VFP_SREG_N. */
44
switch (rn) {
45
case 0x00: /* vmov */
46
- case 0x02: /* vneg */
47
case 0x03: /* vsqrt */
48
break;
49
50
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
51
case 0: /* cpy */
52
/* no-op */
53
break;
54
- case 2: /* neg */
55
- gen_vfp_neg(dp);
56
- break;
57
case 3: /* sqrt */
58
gen_vfp_sqrt(dp);
59
break;
60
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
61
index XXXXXXX..XXXXXXX 100644
62
--- a/target/arm/vfp.decode
63
+++ b/target/arm/vfp.decode
64
@@ -XXX,XX +XXX,XX @@ VABS_sp ---- 1110 1.11 0000 .... 1010 11.0 .... \
65
vd=%vd_sp vm=%vm_sp
66
VABS_dp ---- 1110 1.11 0000 .... 1011 11.0 .... \
67
vd=%vd_dp vm=%vm_dp
68
+
69
+VNEG_sp ---- 1110 1.11 0001 .... 1010 01.0 .... \
70
+ vd=%vd_sp vm=%vm_sp
71
+VNEG_dp ---- 1110 1.11 0001 .... 1011 01.0 .... \
72
+ vd=%vd_dp vm=%vm_dp
73
--
74
2.20.1
75
76
diff view generated by jsdifflib
Deleted patch
1
Convert the VSQRT instruction to decodetree.
2
1
3
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
4
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
5
---
6
target/arm/translate-vfp.inc.c | 20 ++++++++++++++++++++
7
target/arm/translate.c | 14 +-------------
8
target/arm/vfp.decode | 5 +++++
9
3 files changed, 26 insertions(+), 13 deletions(-)
10
11
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
12
index XXXXXXX..XXXXXXX 100644
13
--- a/target/arm/translate-vfp.inc.c
14
+++ b/target/arm/translate-vfp.inc.c
15
@@ -XXX,XX +XXX,XX @@ static bool trans_VNEG_dp(DisasContext *s, arg_VNEG_dp *a)
16
{
17
return do_vfp_2op_dp(s, gen_helper_vfp_negd, a->vd, a->vm);
18
}
19
+
20
+static void gen_VSQRT_sp(TCGv_i32 vd, TCGv_i32 vm)
21
+{
22
+ gen_helper_vfp_sqrts(vd, vm, cpu_env);
23
+}
24
+
25
+static bool trans_VSQRT_sp(DisasContext *s, arg_VSQRT_sp *a)
26
+{
27
+ return do_vfp_2op_sp(s, gen_VSQRT_sp, a->vd, a->vm);
28
+}
29
+
30
+static void gen_VSQRT_dp(TCGv_i64 vd, TCGv_i64 vm)
31
+{
32
+ gen_helper_vfp_sqrtd(vd, vm, cpu_env);
33
+}
34
+
35
+static bool trans_VSQRT_dp(DisasContext *s, arg_VSQRT_dp *a)
36
+{
37
+ return do_vfp_2op_dp(s, gen_VSQRT_dp, a->vd, a->vm);
38
+}
39
diff --git a/target/arm/translate.c b/target/arm/translate.c
40
index XXXXXXX..XXXXXXX 100644
41
--- a/target/arm/translate.c
42
+++ b/target/arm/translate.c
43
@@ -XXX,XX +XXX,XX @@ static inline void gen_vfp_neg(int dp)
44
gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
45
}
46
47
-static inline void gen_vfp_sqrt(int dp)
48
-{
49
- if (dp)
50
- gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
51
- else
52
- gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
53
-}
54
-
55
static inline void gen_vfp_cmp(int dp)
56
{
57
if (dp)
58
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
59
return 1;
60
case 15:
61
switch (rn) {
62
- case 1 ... 2:
63
+ case 1 ... 3:
64
/* Already handled by decodetree */
65
return 1;
66
default:
67
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
68
/* rn is opcode, encoded as per VFP_SREG_N. */
69
switch (rn) {
70
case 0x00: /* vmov */
71
- case 0x03: /* vsqrt */
72
break;
73
74
case 0x04: /* vcvtb.f64.f16, vcvtb.f32.f16 */
75
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
76
case 0: /* cpy */
77
/* no-op */
78
break;
79
- case 3: /* sqrt */
80
- gen_vfp_sqrt(dp);
81
- break;
82
case 4: /* vcvtb.f32.f16, vcvtb.f64.f16 */
83
{
84
TCGv_ptr fpst = get_fpstatus_ptr(false);
85
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
86
index XXXXXXX..XXXXXXX 100644
87
--- a/target/arm/vfp.decode
88
+++ b/target/arm/vfp.decode
89
@@ -XXX,XX +XXX,XX @@ VNEG_sp ---- 1110 1.11 0001 .... 1010 01.0 .... \
90
vd=%vd_sp vm=%vm_sp
91
VNEG_dp ---- 1110 1.11 0001 .... 1011 01.0 .... \
92
vd=%vd_dp vm=%vm_dp
93
+
94
+VSQRT_sp ---- 1110 1.11 0001 .... 1010 11.0 .... \
95
+ vd=%vd_sp vm=%vm_sp
96
+VSQRT_dp ---- 1110 1.11 0001 .... 1011 11.0 .... \
97
+ vd=%vd_dp vm=%vm_dp
98
--
99
2.20.1
100
101
diff view generated by jsdifflib
Deleted patch
1
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
2
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
3
---
4
target/arm/translate-vfp.inc.c | 10 ++++++++++
5
target/arm/translate.c | 8 +-------
6
target/arm/vfp.decode | 5 +++++
7
3 files changed, 16 insertions(+), 7 deletions(-)
8
1
9
diff --git a/target/arm/translate-vfp.inc.c b/target/arm/translate-vfp.inc.c
10
index XXXXXXX..XXXXXXX 100644
11
--- a/target/arm/translate-vfp.inc.c
12
+++ b/target/arm/translate-vfp.inc.c
13
@@ -XXX,XX +XXX,XX @@ static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
14
return true;
15
}
16
17
+static bool trans_VMOV_reg_sp(DisasContext *s, arg_VMOV_reg_sp *a)
18
+{
19
+ return do_vfp_2op_sp(s, tcg_gen_mov_i32, a->vd, a->vm);
20
+}
21
+
22
+static bool trans_VMOV_reg_dp(DisasContext *s, arg_VMOV_reg_dp *a)
23
+{
24
+ return do_vfp_2op_dp(s, tcg_gen_mov_i64, a->vd, a->vm);
25
+}
26
+
27
static bool trans_VABS_sp(DisasContext *s, arg_VABS_sp *a)
28
{
29
return do_vfp_2op_sp(s, gen_helper_vfp_abss, a->vd, a->vm);
30
diff --git a/target/arm/translate.c b/target/arm/translate.c
31
index XXXXXXX..XXXXXXX 100644
32
--- a/target/arm/translate.c
33
+++ b/target/arm/translate.c
34
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
35
return 1;
36
case 15:
37
switch (rn) {
38
- case 1 ... 3:
39
+ case 0 ... 3:
40
/* Already handled by decodetree */
41
return 1;
42
default:
43
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
44
if (op == 15) {
45
/* rn is opcode, encoded as per VFP_SREG_N. */
46
switch (rn) {
47
- case 0x00: /* vmov */
48
- break;
49
-
50
case 0x04: /* vcvtb.f64.f16, vcvtb.f32.f16 */
51
case 0x05: /* vcvtt.f64.f16, vcvtt.f32.f16 */
52
/*
53
@@ -XXX,XX +XXX,XX @@ static int disas_vfp_insn(DisasContext *s, uint32_t insn)
54
switch (op) {
55
case 15: /* extension space */
56
switch (rn) {
57
- case 0: /* cpy */
58
- /* no-op */
59
- break;
60
case 4: /* vcvtb.f32.f16, vcvtb.f64.f16 */
61
{
62
TCGv_ptr fpst = get_fpstatus_ptr(false);
63
diff --git a/target/arm/vfp.decode b/target/arm/vfp.decode
64
index XXXXXXX..XXXXXXX 100644
65
--- a/target/arm/vfp.decode
66
+++ b/target/arm/vfp.decode
67
@@ -XXX,XX +XXX,XX @@ VMOV_imm_sp ---- 1110 1.11 imm4h:4 .... 1010 0000 imm4l:4 \
68
VMOV_imm_dp ---- 1110 1.11 imm4h:4 .... 1011 0000 imm4l:4 \
69
vd=%vd_dp
70
71
+VMOV_reg_sp ---- 1110 1.11 0000 .... 1010 01.0 .... \
72
+ vd=%vd_sp vm=%vm_sp
73
+VMOV_reg_dp ---- 1110 1.11 0000 .... 1011 01.0 .... \
74
+ vd=%vd_dp vm=%vm_dp
75
+
76
VABS_sp ---- 1110 1.11 0000 .... 1010 11.0 .... \
77
vd=%vd_sp vm=%vm_sp
78
VABS_dp ---- 1110 1.11 0000 .... 1011 11.0 .... \
79
--
80
2.20.1
81
82
diff view generated by jsdifflib